/ Changes On Branch begin-concurrent-pnu-wal2
Login

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

Changes In Branch begin-concurrent-pnu-wal2 Excluding Merge-Ins

This is equivalent to a diff from a93ca38b43 to 5a22010c35

2023-02-02
20:27
Instead of free()ing them, retain allocated page buffers on an internal per-connection reuse-list when a page-cache is reset. (check-in: 754f331614 user: dan tags: bedrock)
14:27
Merge latest enhancments into this branch from branch wal2. (Leaf check-in: 5a22010c35 user: dan tags: begin-concurrent-pnu-wal2)
14:21
Merge trunk enhancements into this branch. (check-in: c9b0180203 user: dan tags: wal2)
2023-01-12
15:44
Fix a startup race condition that could occur if a wal file grows from 0 bytes while a BEGIN CONCURRENT transaction is running. Cherrypick of [c1feca4d]. (check-in: 2c14f3832e user: dan tags: begin-concurrent-pnu-wal2)
2019-03-08
15:30
Merge all the latest enhancements from trunk. (check-in: 667cce3dce user: drh tags: begin-concurrent-pnu)
2018-12-18
18:01
Merge the wal2 feature into this branch. (check-in: a2c618c0a4 user: dan tags: begin-concurrent-pnu-wal2)
17:47
Merge latest begin-concurrent changes into this branch. (check-in: a93ca38b43 user: dan tags: begin-concurrent-pnu)
17:20
Merge latest trunk changes into this branch. (check-in: 123cbb3312 user: dan tags: begin-concurrent)
2018-12-06
03:13
Merge fixes from trunk. (check-in: f2083ee410 user: drh tags: begin-concurrent-pnu)

Added LICENSE.md.







1
2
3
4
5
6
+
+
+
+
+
+
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.

Changes to Makefile.in.

31
32
33
34
35
36
37
38

39
40
41
42
43
44
45
31
32
33
34
35
36
37

38
39
40
41
42
43
44
45







-
+







CC = @CC@
CFLAGS = @CPPFLAGS@ @CFLAGS@
TCC = ${CC} ${CFLAGS} -I. -I${TOP}/src -I${TOP}/ext/rtree -I${TOP}/ext/icu
TCC += -I${TOP}/ext/fts3 -I${TOP}/ext/async -I${TOP}/ext/session
TCC += -I${TOP}/ext/userauth

# Define this for the autoconf-based build, so that the code knows it can
# include the generated config.h
# include the generated sqlite_cfg.h
#
TCC += -D_HAVE_SQLITE_CONFIG_H -DBUILD_sqlite

# Define -DNDEBUG to compile without debugging (i.e., for production usage)
# Omitting the define will cause extra debugging code to be inserted and
# includes extra comments when "EXPLAIN stmt" is used.
#
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
201
202







+














-
+



-
+






+
-
+







LTLINK = $(LIBTOOL) --mode=link $(TCC) $(LTCOMPILE_EXTRAS) @LDFLAGS@ $(LTLINK_EXTRAS)
LTINSTALL = $(LIBTOOL) --mode=install $(INSTALL)

# You should not have to change anything below this line
###############################################################################

USE_AMALGAMATION = @USE_AMALGAMATION@
AMALGAMATION_LINE_MACROS = @AMALGAMATION_LINE_MACROS@

# Object files for the SQLite library (non-amalgamation).
#
LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
         backup.lo bitvec.lo btmutex.lo btree.lo build.lo \
         callback.lo complete.lo ctime.lo \
         date.lo dbpage.lo dbstat.lo delete.lo \
         expr.lo fault.lo fkey.lo \
         fts3.lo fts3_aux.lo fts3_expr.lo fts3_hash.lo fts3_icu.lo \
         fts3_porter.lo fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo \
         fts3_tokenize_vtab.lo \
         fts3_unicode.lo fts3_unicode2.lo fts3_write.lo \
	 fts5.lo \
         func.lo global.lo hash.lo \
         icu.lo insert.lo json1.lo legacy.lo loadext.lo \
         icu.lo insert.lo json.lo legacy.lo loadext.lo \
         main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \
         memdb.lo memjournal.lo \
         mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \
         notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \
         notify.lo opcodes.lo os.lo os_kv.lo os_unix.lo os_win.lo \
         pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
         random.lo resolve.lo rowset.lo rtree.lo \
         sqlite3session.lo select.lo sqlite3rbu.lo status.lo stmt.lo \
         table.lo threads.lo tokenize.lo treeview.lo trigger.lo \
         update.lo userauth.lo upsert.lo util.lo vacuum.lo \
         vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \
         vdbetrace.lo vdbevtab.lo \
         vdbetrace.lo wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \
         wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \
         window.lo utf.lo vtab.lo

# Object files for the amalgamation.
#
LIBOBJS1 = sqlite3.lo

# Determine the real value of LIBOBJ based on the 'configure' script
228
229
230
231
232
233
234

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







+







  $(TOP)/src/fkey.c \
  $(TOP)/src/func.c \
  $(TOP)/src/global.c \
  $(TOP)/src/hash.c \
  $(TOP)/src/hash.h \
  $(TOP)/src/hwtime.h \
  $(TOP)/src/insert.c \
  $(TOP)/src/json.c \
  $(TOP)/src/legacy.c \
  $(TOP)/src/loadext.c \
  $(TOP)/src/main.c \
  $(TOP)/src/malloc.c \
  $(TOP)/src/mem0.c \
  $(TOP)/src/mem1.c \
  $(TOP)/src/mem2.c \
250
251
252
253
254
255
256

257
258
259
260
261
262
263
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267







+







  $(TOP)/src/mutex_unix.c \
  $(TOP)/src/mutex_w32.c \
  $(TOP)/src/notify.c \
  $(TOP)/src/os.c \
  $(TOP)/src/os.h \
  $(TOP)/src/os_common.h \
  $(TOP)/src/os_setup.h \
  $(TOP)/src/os_kv.c \
  $(TOP)/src/os_unix.c \
  $(TOP)/src/os_win.c \
  $(TOP)/src/os_win.h \
  $(TOP)/src/pager.c \
  $(TOP)/src/pager.h \
  $(TOP)/src/parse.y \
  $(TOP)/src/pcache.c \
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
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







+















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







  $(TOP)/src/vdbe.h \
  $(TOP)/src/vdbeapi.c \
  $(TOP)/src/vdbeaux.c \
  $(TOP)/src/vdbeblob.c \
  $(TOP)/src/vdbemem.c \
  $(TOP)/src/vdbesort.c \
  $(TOP)/src/vdbetrace.c \
  $(TOP)/src/vdbevtab.c \
  $(TOP)/src/vdbeInt.h \
  $(TOP)/src/vtab.c \
  $(TOP)/src/vxworks.h \
  $(TOP)/src/wal.c \
  $(TOP)/src/wal.h \
  $(TOP)/src/walker.c \
  $(TOP)/src/where.c \
  $(TOP)/src/wherecode.c \
  $(TOP)/src/whereexpr.c \
  $(TOP)/src/whereInt.h \
  $(TOP)/src/window.c

# Source code for extensions
#
SRC += \
  $(TOP)/ext/fts1/fts1.c \
  $(TOP)/ext/fts1/fts1.h \
  $(TOP)/ext/fts1/fts1_hash.c \
  $(TOP)/ext/fts1/fts1_hash.h \
  $(TOP)/ext/fts1/fts1_porter.c \
  $(TOP)/ext/fts1/fts1_tokenizer.h \
  $(TOP)/ext/fts1/fts1_tokenizer1.c
SRC += \
  $(TOP)/ext/fts2/fts2.c \
  $(TOP)/ext/fts2/fts2.h \
  $(TOP)/ext/fts2/fts2_hash.c \
  $(TOP)/ext/fts2/fts2_hash.h \
  $(TOP)/ext/fts2/fts2_icu.c \
  $(TOP)/ext/fts2/fts2_porter.c \
  $(TOP)/ext/fts2/fts2_tokenizer.h \
  $(TOP)/ext/fts2/fts2_tokenizer.c \
  $(TOP)/ext/fts2/fts2_tokenizer1.c
SRC += \
  $(TOP)/ext/fts3/fts3.c \
  $(TOP)/ext/fts3/fts3.h \
  $(TOP)/ext/fts3/fts3Int.h \
  $(TOP)/ext/fts3/fts3_aux.c \
  $(TOP)/ext/fts3/fts3_expr.c \
  $(TOP)/ext/fts3/fts3_hash.c \
  $(TOP)/ext/fts3/fts3_hash.h \
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
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







-










-
+







SRC += \
  $(TOP)/ext/userauth/userauth.c \
  $(TOP)/ext/userauth/sqlite3userauth.h
SRC += \
  $(TOP)/ext/rbu/sqlite3rbu.h \
  $(TOP)/ext/rbu/sqlite3rbu.c
SRC += \
  $(TOP)/ext/misc/json1.c \
  $(TOP)/ext/misc/stmt.c

# Generated source code files
#
SRC += \
  keywordhash.h \
  opcodes.c \
  opcodes.h \
  parse.c \
  parse.h \
  config.h \
  sqlite_cfg.h \
  shell.c \
  sqlite3.h

# Source code to the test files.
#
TESTSRC = \
  $(TOP)/src/test1.c \
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
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







+







+
+
+
+








+
+
+

+


+












+
+








-
+
+







  $(TOP)/src/test_schema.c \
  $(TOP)/src/test_server.c \
  $(TOP)/src/test_superlock.c \
  $(TOP)/src/test_syscall.c \
  $(TOP)/src/test_tclsh.c \
  $(TOP)/src/test_tclvar.c \
  $(TOP)/src/test_thread.c \
  $(TOP)/src/test_vdbecov.c \
  $(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/session/sqlite3changebatch.c \
  $(TOP)/ext/recover/sqlite3recover.c \
  $(TOP)/ext/recover/dbdata.c \
  $(TOP)/ext/recover/test_recover.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 \
  $(TOP)/ext/misc/bgckpt.c \
  $(TOP)/ext/misc/appendvfs.c \
  $(TOP)/ext/misc/basexx.c \
  $(TOP)/ext/misc/carray.c \
  $(TOP)/ext/misc/cksumvfs.c \
  $(TOP)/ext/misc/closure.c \
  $(TOP)/ext/misc/csv.c \
  $(TOP)/ext/misc/decimal.c \
  $(TOP)/ext/misc/eval.c \
  $(TOP)/ext/misc/explain.c \
  $(TOP)/ext/misc/fileio.c \
  $(TOP)/ext/misc/fuzzer.c \
  $(TOP)/ext/fts5/fts5_tcl.c \
  $(TOP)/ext/fts5/fts5_test_mi.c \
  $(TOP)/ext/fts5/fts5_test_tok.c \
  $(TOP)/ext/misc/ieee754.c \
  $(TOP)/ext/misc/mmapwarm.c \
  $(TOP)/ext/misc/nextchar.c \
  $(TOP)/ext/misc/normalize.c \
  $(TOP)/ext/misc/percentile.c \
  $(TOP)/ext/misc/prefixes.c \
  $(TOP)/ext/misc/qpvtab.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/zipfile.c \
  $(TOP)/ext/userauth/userauth.c
  $(TOP)/ext/userauth/userauth.c \
  $(TOP)/ext/rtree/test_rtreedoc.c

# Source code to the library files needed by the test fixture
#
TESTSRC2 = \
  $(TOP)/src/attach.c \
  $(TOP)/src/backup.c \
  $(TOP)/src/bitvec.c \
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
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







+











+







+













-
+
+







  $(TOP)/src/func.c \
  $(TOP)/src/global.c \
  $(TOP)/src/insert.c \
  $(TOP)/src/wal.c \
  $(TOP)/src/main.c \
  $(TOP)/src/mem5.c \
  $(TOP)/src/os.c \
  $(TOP)/src/os_kv.c \
  $(TOP)/src/os_unix.c \
  $(TOP)/src/os_win.c \
  $(TOP)/src/pager.c \
  $(TOP)/src/pragma.c \
  $(TOP)/src/prepare.c \
  $(TOP)/src/printf.c \
  $(TOP)/src/random.c \
  $(TOP)/src/pcache.c \
  $(TOP)/src/pcache1.c \
  $(TOP)/src/select.c \
  $(TOP)/src/tokenize.c \
  $(TOP)/src/treeview.c \
  $(TOP)/src/utf.c \
  $(TOP)/src/util.c \
  $(TOP)/src/vdbeapi.c \
  $(TOP)/src/vdbeaux.c \
  $(TOP)/src/vdbe.c \
  $(TOP)/src/vdbemem.c \
  $(TOP)/src/vdbetrace.c \
  $(TOP)/src/vdbevtab.c \
  $(TOP)/src/where.c \
  $(TOP)/src/wherecode.c \
  $(TOP)/src/whereexpr.c \
  $(TOP)/src/window.c \
  parse.c \
  $(TOP)/ext/fts3/fts3.c \
  $(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 \
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
541
542
543
544
545
546
547

548
549
550
551
552








553
554
555
556
557
558
559







-
+




-
-
-
-
-
-
-
-







   $(TOP)/src/sqlite3ext.h \
   $(TOP)/src/sqliteInt.h  \
   $(TOP)/src/sqliteLimit.h \
   $(TOP)/src/vdbe.h \
   $(TOP)/src/vdbeInt.h \
   $(TOP)/src/vxworks.h \
   $(TOP)/src/whereInt.h \
   config.h
   sqlite_cfg.h

# Header files used by extensions
#
EXTHDR += \
  $(TOP)/ext/fts1/fts1.h \
  $(TOP)/ext/fts1/fts1_hash.h \
  $(TOP)/ext/fts1/fts1_tokenizer.h
EXTHDR += \
  $(TOP)/ext/fts2/fts2.h \
  $(TOP)/ext/fts2/fts2_hash.h \
  $(TOP)/ext/fts2/fts2_tokenizer.h
EXTHDR += \
  $(TOP)/ext/fts3/fts3.h \
  $(TOP)/ext/fts3/fts3Int.h \
  $(TOP)/ext/fts3/fts3_hash.h \
  $(TOP)/ext/fts3/fts3_tokenizer.h
EXTHDR += \
  $(TOP)/ext/rtree/rtree.h \
  $(TOP)/ext/rtree/geopoly.c
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
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







-
+
+







-
+







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


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

+







FUZZDATA = \
  $(TOP)/test/fuzzdata1.db \
  $(TOP)/test/fuzzdata2.db \
  $(TOP)/test/fuzzdata3.db \
  $(TOP)/test/fuzzdata4.db \
  $(TOP)/test/fuzzdata5.db \
  $(TOP)/test/fuzzdata6.db \
  $(TOP)/test/fuzzdata7.db
  $(TOP)/test/fuzzdata7.db \
  $(TOP)/test/fuzzdata8.db

# Standard options to testfixture
#
TESTOPTS = --verbose=file --output=test-out.txt

# Extra compiler options for various shell tools
#
SHELL_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4
SHELL_OPT = -DSQLITE_ENABLE_FTS4
#SHELL_OPT += -DSQLITE_ENABLE_FTS5
SHELL_OPT += -DSQLITE_ENABLE_RTREE
SHELL_OPT += -DSQLITE_ENABLE_EXPLAIN_COMMENTS
SHELL_OPT += -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
SHELL_OPT += -DSQLITE_ENABLE_STMTVTAB
SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB
SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC
SHELL_OPT += -DSQLITE_ENABLE_DESERIALIZE
SHELL_OPT += -DSQLITE_ENABLE_BYTECODE_VTAB
SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC
SHELL_OPT += -DSQLITE_INTROSPECTION_PRAGMAS
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ
FUZZERSHELL_OPT = 
FUZZCHECK_OPT += -I$(TOP)/test
FUZZCHECK_OPT += -I$(TOP)/ext/recover
FUZZCHECK_OPT += -DSQLITE_OMIT_LOAD_EXTENSION
FUZZCHECK_OPT += -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ
FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000
FUZZCHECK_OPT += -DSQLITE_PRINTF_PRECISION_LIMIT=1000
FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS4
FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS3_PARENTHESIS
FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS5
FUZZCHECK_OPT += -DSQLITE_ENABLE_RTREE
FUZZCHECK_OPT += -DSQLITE_ENABLE_GEOPOLY
FUZZCHECK_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
FUZZCHECK_OPT += -DSQLITE_ENABLE_BYTECODE_VTAB
FUZZCHECK_SRC = $(TOP)/test/fuzzcheck.c $(TOP)/test/ossfuzz.c
FUZZCHECK_SRC += $(TOP)/test/fuzzcheck.c
FUZZCHECK_SRC += $(TOP)/test/ossfuzz.c
FUZZCHECK_SRC += $(TOP)/test/fuzzinvariants.c
FUZZCHECK_SRC += $(TOP)/ext/recover/dbdata.c
FUZZCHECK_SRC += $(TOP)/ext/recover/sqlite3recover.c
FUZZCHECK_SRC += $(TOP)/test/vt02.c
DBFUZZ_OPT =
ST_OPT = -DSQLITE_OS_KV_OPTIONAL

# This is the default Makefile target.  The objects listed here
# are what get build when you type just "make" with no arguments.
#
all:	sqlite3.h libsqlite3.la sqlite3$(TEXE) $(HAVE_TCL:1=libtclsqlite3.la)

Makefile: $(TOP)/Makefile.in
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
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







-
+















-


+


-
+

+
+
+
+
+
+
+
-
+

-
-
+
+
+
+
+
+
+
+
+







sourcetest:	srcck1$(BEXE) sqlite3.c
	./srcck1 sqlite3.c

fuzzershell$(TEXE):	$(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h
	$(LTLINK) -o $@ $(FUZZERSHELL_OPT) \
	  $(TOP)/tool/fuzzershell.c sqlite3.c $(TLIBS)

fuzzcheck$(TEXE):	$(FUZZCHECK_SRC) sqlite3.c sqlite3.h
fuzzcheck$(TEXE):	$(FUZZCHECK_SRC) sqlite3.c sqlite3.h $(FUZZCHECK_DEP)
	$(LTLINK) -o $@ $(FUZZCHECK_OPT) $(FUZZCHECK_SRC) sqlite3.c $(TLIBS)

ossshell$(TEXE):	$(TOP)/test/ossfuzz.c $(TOP)/test/ossshell.c sqlite3.c sqlite3.h
	$(LTLINK) -o $@ $(FUZZCHECK_OPT) $(TOP)/test/ossshell.c \
             $(TOP)/test/ossfuzz.c sqlite3.c $(TLIBS)

sessionfuzz$(TEXE):	$(TOP)/test/sessionfuzz.c sqlite3.c sqlite3.h
	$(LTLINK) -o $@ $(TOP)/test/sessionfuzz.c $(TLIBS)

dbfuzz$(TEXE):	$(TOP)/test/dbfuzz.c sqlite3.c sqlite3.h
	$(LTLINK) -o $@ $(DBFUZZ_OPT) $(TOP)/test/dbfuzz.c sqlite3.c $(TLIBS)

DBFUZZ2_OPTS = \
  -DSQLITE_THREADSAFE=0 \
  -DSQLITE_OMIT_LOAD_EXTENSION \
  -DSQLITE_ENABLE_DESERIALIZE \
  -DSQLITE_DEBUG \
  -DSQLITE_ENABLE_DBSTAT_VTAB \
  -DSQLITE_ENABLE_BYTECODE_VTAB \
  -DSQLITE_ENABLE_RTREE \
  -DSQLITE_ENABLE_FTS4 \
  -DSQLITE_EANBLE_FTS5
  -DSQLITE_ENABLE_FTS5

dbfuzz2$(TEXE):	$(TOP)/test/dbfuzz2.c sqlite3.c sqlite3.h
	$(CC) $(OPT_FEATURE_FLAGS) $(OPTS) -I. -g -O0 \
		-DSTANDALONE -o dbfuzz2 \
		$(DBFUZZ2_OPTS) $(TOP)/test/dbfuzz2.c sqlite3.c $(TLIBS)
	mkdir -p dbfuzz2-dir
	cp $(TOP)/test/dbfuzz2-seed* dbfuzz2-dir

dbfuzz2:	$(TOP)/test/dbfuzz2.c sqlite3.c sqlite3.h
dbfuzz2-asan:	$(TOP)/test/dbfuzz2.c sqlite3.c sqlite3.h
	clang-6.0 $(OPT_FEATURE_FLAGS) $(OPTS) -I. -g -O0 \
		-fsanitize=fuzzer,undefined,address -o dbfuzz2 \
		$(DBFUZZ2_OPTS) $(TOP)/test/dbfuzz2.c sqlite3.c
		-fsanitize=fuzzer,undefined,address -o dbfuzz2-asan \
		$(DBFUZZ2_OPTS) $(TOP)/test/dbfuzz2.c sqlite3.c $(TLIBS)
	mkdir -p dbfuzz2-dir
	cp $(TOP)/test/dbfuzz2-seed* dbfuzz2-dir

dbfuzz2-msan:	$(TOP)/test/dbfuzz2.c sqlite3.c sqlite3.h
	clang-6.0 $(OPT_FEATURE_FLAGS) $(OPTS) -I. -g -O0 \
		-fsanitize=fuzzer,undefined,memory -o dbfuzz2-msan \
		$(DBFUZZ2_OPTS) $(TOP)/test/dbfuzz2.c sqlite3.c $(TLIBS)
	mkdir -p dbfuzz2-dir
	cp $(TOP)/test/dbfuzz2-seed* dbfuzz2-dir

mptester$(TEXE):	sqlite3.lo $(TOP)/mptest/mptest.c
	$(LTLINK) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.lo \
		$(TLIBS) -rpath "$(libdir)"

722
723
724
725
726
727
728
729

730
731
732









733
734
735
736
737
738
739
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







-
+



+
+
+
+
+
+
+
+
+







	rm tsrc/sqlite.h.in tsrc/parse.y
	$(TCLSH_CMD) $(TOP)/tool/vdbe-compress.tcl $(OPTS) <tsrc/vdbe.c >vdbe.new
	mv vdbe.new tsrc/vdbe.c
	cp fts5.c fts5.h tsrc
	touch .target_source

sqlite3.c:	.target_source $(TOP)/tool/mksqlite3c.tcl
	$(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl
	$(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl $(AMALGAMATION_LINE_MACROS)
	cp tsrc/sqlite3ext.h .
	cp $(TOP)/ext/session/sqlite3session.h .

sqlite3r.h: sqlite3.h
	$(TCLSH_CMD) $(TOP)/tool/mksqlite3h.tcl $(TOP) --enable-recover >sqlite3r.h

sqlite3r.c: sqlite3.c sqlite3r.h
	cp $(TOP)/ext/recover/sqlite3recover.c tsrc/
	cp $(TOP)/ext/recover/sqlite3recover.h tsrc/
	cp $(TOP)/ext/recover/dbdata.c tsrc/
	$(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl --enable-recover $(AMALGAMATION_LINE_MACROS)

sqlite3ext.h:	.target_source
	cp tsrc/sqlite3ext.h .

tclsqlite3.c:	sqlite3.c
	echo '#ifndef USE_SYSTEM_SQLITE' >tclsqlite3.c
	cat sqlite3.c >>tclsqlite3.c
	echo '#endif /* USE_SYSTEM_SQLITE */' >>tclsqlite3.c
837
838
839
840
841
842
843



844
845
846
847
848
849
850
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887







+
+
+








hash.lo:	$(TOP)/src/hash.c $(HDR)
	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/hash.c

insert.lo:	$(TOP)/src/insert.c $(HDR)
	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/insert.c

json.lo:	$(TOP)/src/json.c $(HDR)
	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/json.c

legacy.lo:	$(TOP)/src/legacy.c $(HDR)
	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/legacy.c

loadext.lo:	$(TOP)/src/loadext.c $(HDR)
	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/loadext.c

main.lo:	$(TOP)/src/main.c $(HDR)
897
898
899
900
901
902
903



904
905
906
907
908
909
910
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950







+
+
+








pcache1.lo:	$(TOP)/src/pcache1.c $(HDR) $(TOP)/src/pcache.h
	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/pcache1.c

os.lo:	$(TOP)/src/os.c $(HDR)
	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/os.c

os_kv.lo:	$(TOP)/src/os_kv.c $(HDR)
	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/os_kv.c

os_unix.lo:	$(TOP)/src/os_unix.c $(HDR)
	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/os_unix.c

os_win.lo:	$(TOP)/src/os_win.c $(HDR)
	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/os_win.c

pragma.lo:	$(TOP)/src/pragma.c $(HDR)
978
979
980
981
982
983
984



985
986
987
988
989
990
991
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034







+
+
+








vdbesort.lo:	$(TOP)/src/vdbesort.c $(HDR)
	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vdbesort.c

vdbetrace.lo:	$(TOP)/src/vdbetrace.c $(HDR)
	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vdbetrace.c

vdbevtab.lo:	$(TOP)/src/vdbevtab.c $(HDR)
	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vdbevtab.c

vtab.lo:	$(TOP)/src/vtab.c $(HDR)
	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vtab.c

wal.lo:	$(TOP)/src/wal.c $(HDR)
	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/wal.c

walker.lo:	$(TOP)/src/walker.c $(HDR)
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
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







-
+

-
-
+
-
-



+
+
+
+
+
+









+
-
+
+
+
+

-
+
+
+
+

+



+
+
+
+













-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







opcodes.h:	parse.h $(TOP)/src/vdbe.c $(TOP)/tool/mkopcodeh.tcl
	cat parse.h $(TOP)/src/vdbe.c | $(TCLSH_CMD) $(TOP)/tool/mkopcodeh.tcl >opcodes.h

# Rules to build parse.c and parse.h - the outputs of lemon.
#
parse.h:	parse.c

parse.c:	$(TOP)/src/parse.y lemon$(BEXE) $(TOP)/tool/addopcodes.tcl
parse.c:	$(TOP)/src/parse.y lemon$(BEXE)
	cp $(TOP)/src/parse.y .
	rm -f parse.h
	./lemon$(BEXE) $(OPT_FEATURE_FLAGS) $(OPTS) parse.y
	./lemon$(BEXE) $(OPT_FEATURE_FLAGS) $(OPTS) -S parse.y
	mv parse.h parse.h.temp
	$(TCLSH_CMD) $(TOP)/tool/addopcodes.tcl parse.h.temp >parse.h

sqlite3.h:	$(TOP)/src/sqlite.h.in $(TOP)/manifest mksourceid$(BEXE) $(TOP)/VERSION
	$(TCLSH_CMD) $(TOP)/tool/mksqlite3h.tcl $(TOP) >sqlite3.h

sqlite3rc.h:	$(TOP)/src/sqlite3.rc $(TOP)/VERSION
	echo '#ifndef SQLITE_RESOURCE_VERSION' >$@
	echo -n '#define SQLITE_RESOURCE_VERSION ' >>$@
	cat $(TOP)/VERSION | $(TCLSH_CMD) $(TOP)/tool/replace.tcl exact . , >>$@
	echo '#endif' >>sqlite3rc.h

keywordhash.h:	$(TOP)/tool/mkkeywordhash.c
	$(BCC) -o mkkeywordhash$(BEXE) $(OPT_FEATURE_FLAGS) $(OPTS) $(TOP)/tool/mkkeywordhash.c
	./mkkeywordhash$(BEXE) >keywordhash.h

# Source files that go into making shell.c
SHELL_SRC = \
	$(TOP)/src/shell.c.in \
        $(TOP)/ext/misc/appendvfs.c \
	$(TOP)/ext/misc/completion.c \
	$(TOP)/ext/misc/shathree.c \
        $(TOP)/ext/misc/decimal.c \
        $(TOP)/ext/misc/basexx.c \
        $(TOP)/ext/misc/base64.c \
        $(TOP)/ext/misc/base85.c \
	$(TOP)/ext/misc/fileio.c \
	$(TOP)/ext/misc/completion.c \
        $(TOP)/ext/misc/ieee754.c \
        $(TOP)/ext/misc/regexp.c \
        $(TOP)/ext/misc/series.c \
	$(TOP)/ext/misc/shathree.c \
	$(TOP)/ext/misc/sqlar.c \
        $(TOP)/ext/misc/uint.c \
	$(TOP)/ext/expert/sqlite3expert.c \
	$(TOP)/ext/expert/sqlite3expert.h \
	$(TOP)/ext/misc/zipfile.c \
	$(TOP)/ext/misc/memtrace.c \
	$(TOP)/ext/recover/dbdata.c \
	$(TOP)/ext/recover/sqlite3recover.c \
	$(TOP)/ext/recover/sqlite3recover.h \
        $(TOP)/src/test_windirent.c

shell.c:	$(SHELL_SRC) $(TOP)/tool/mkshellc.tcl
	$(TCLSH_CMD) $(TOP)/tool/mkshellc.tcl >shell.c




# Rules to build the extension objects.
#
icu.lo:	$(TOP)/ext/icu/icu.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/icu/icu.c

fts2.lo:	$(TOP)/ext/fts2/fts2.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2.c

fts2_hash.lo:	$(TOP)/ext/fts2/fts2_hash.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_hash.c

fts2_icu.lo:	$(TOP)/ext/fts2/fts2_icu.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_icu.c

fts2_porter.lo:	$(TOP)/ext/fts2/fts2_porter.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_porter.c

fts2_tokenizer.lo:	$(TOP)/ext/fts2/fts2_tokenizer.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_tokenizer.c

fts2_tokenizer1.lo:	$(TOP)/ext/fts2/fts2_tokenizer1.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_tokenizer1.c

fts3.lo:	$(TOP)/ext/fts3/fts3.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3.c

fts3_aux.lo:	$(TOP)/ext/fts3/fts3_aux.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_aux.c

fts3_expr.lo:	$(TOP)/ext/fts3/fts3_expr.c $(HDR) $(EXTHDR)
1122
1123
1124
1125
1126
1127
1128
1129

1130
1131
1132

1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1162
1163
1164
1165
1166
1167
1168

1169
1170
1171

1172
1173
1174



1175
1176
1177
1178
1179
1180
1181







-
+


-
+


-
-
-








fts3_write.lo:	$(TOP)/ext/fts3/fts3_write.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_write.c

rtree.lo:	$(TOP)/ext/rtree/rtree.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/rtree/rtree.c

sqlite3session.lo:	$(TOP)/ext/userauth/userauth.c $(HDR) $(EXTHDR)
userauth.lo:	$(TOP)/ext/userauth/userauth.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/userauth/userauth.c

userauth.lo:	$(TOP)/ext/session/sqlite3session.c $(HDR) $(EXTHDR)
sqlite3session.lo:	$(TOP)/ext/session/sqlite3session.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/session/sqlite3session.c

json1.lo:	$(TOP)/ext/misc/json1.c
	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/misc/json1.c

stmt.lo:	$(TOP)/ext/misc/stmt.c
	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/misc/stmt.c

# FTS5 things
#
FTS5_SRC = \
   $(TOP)/ext/fts5/fts5.h \
1153
1154
1155
1156
1157
1158
1159
1160

1161
1162
1163

1164
1165
1166
1167
1168
1169
1170
1190
1191
1192
1193
1194
1195
1196

1197
1198
1199

1200
1201
1202
1203
1204
1205
1206
1207







-
+


-
+







   fts5parse.c fts5parse.h \
   $(TOP)/ext/fts5/fts5_storage.c \
   $(TOP)/ext/fts5/fts5_tokenize.c \
   $(TOP)/ext/fts5/fts5_unicode2.c \
   $(TOP)/ext/fts5/fts5_varint.c \
   $(TOP)/ext/fts5/fts5_vocab.c  \

fts5parse.c:	$(TOP)/ext/fts5/fts5parse.y lemon
fts5parse.c:	$(TOP)/ext/fts5/fts5parse.y lemon$(BEXE)
	cp $(TOP)/ext/fts5/fts5parse.y .
	rm -f fts5parse.h
	./lemon$(BEXE) $(OPTS) fts5parse.y
	./lemon$(BEXE) $(OPTS) -S fts5parse.y

fts5parse.h: fts5parse.c

fts5.c: $(FTS5_SRC)
	$(TCLSH_CMD) $(TOP)/ext/fts5/tool/mkfts5c.tcl
	cp $(TOP)/ext/fts5/fts5.h .

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







-
+
+















+
+
+
-
+















-
-
-
-

-
+






+
+
+
+
+
+









-
+














+
+
+







TESTFIXTURE_FLAGS += -DTCLSH_INIT_PROC=sqlite3TestInit
TESTFIXTURE_FLAGS += -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE
TESTFIXTURE_FLAGS += -DBUILD_sqlite
TESTFIXTURE_FLAGS += -DSQLITE_SERIES_CONSTRAINT_VERIFY=1
TESTFIXTURE_FLAGS += -DSQLITE_DEFAULT_PAGE_SIZE=1024
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_STMTVTAB
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_DBPAGE_VTAB
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_DESERIALIZE
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_BYTECODE_VTAB
TESTFIXTURE_FLAGS += -DSQLITE_CKSUMVFS_STATIC

TESTFIXTURE_SRC0 = $(TESTSRC2) libsqlite3.la
TESTFIXTURE_SRC1 = sqlite3.c
TESTFIXTURE_SRC = $(TESTSRC) $(TOP)/src/tclsqlite.c
TESTFIXTURE_SRC += $(TESTFIXTURE_SRC$(USE_AMALGAMATION))

testfixture$(TEXE):	$(TESTFIXTURE_SRC)
	$(LTLINK) -DSQLITE_NO_SYNC=1 $(TEMP_STORE) $(TESTFIXTURE_FLAGS) \
		-o $@ $(TESTFIXTURE_SRC) $(LIBTCL) $(TLIBS)

coretestprogs:	$(TESTPROGS)

testprogs:	coretestprogs srcck1$(BEXE) fuzzcheck$(TEXE) sessionfuzz$(TEXE)

# A very detailed test running most or all test cases
fulltest:	alltest fuzztest

# Run most or all tcl test cases
fulltest:	$(TESTPROGS) fuzztest
alltest:	$(TESTPROGS)
	./testfixture$(TEXE) $(TOP)/test/all.test $(TESTOPTS)

# Really really long testing
soaktest:	$(TESTPROGS)
	./testfixture$(TEXE) $(TOP)/test/all.test -soak=1 $(TESTOPTS)

# Do extra testing but not everything.
fulltestonly:	$(TESTPROGS) fuzztest
	./testfixture$(TEXE) $(TOP)/test/full.test

# Fuzz testing
fuzztest:	fuzzcheck$(TEXE) $(FUZZDATA) sessionfuzz$(TEXE) $(TOP)/test/sessionfuzz-data1.db
	./fuzzcheck$(TEXE) $(FUZZDATA)
	./sessionfuzz$(TEXE) run $(TOP)/test/sessionfuzz-data1.db

fastfuzztest:	fuzzcheck$(TEXE) $(FUZZDATA) sessionfuzz$(TEXE) $(TOP)/test/sessionfuzz-data1.db
	./fuzzcheck$(TEXE) --limit-mem 100M $(FUZZDATA)
	./sessionfuzz$(TEXE) run $(TOP)/test/sessionfuzz-data1.db

valgrindfuzz:	fuzzcheck$(TEXT) $(FUZZDATA) sessionfuzz$(TEXE) $(TOP)/test/sessionfuzz-data1.db
	valgrind ./fuzzcheck$(TEXE) --cell-size-check --limit-mem 10M --timeout 600 $(FUZZDATA)
	valgrind ./fuzzcheck$(TEXE) --cell-size-check --limit-mem 10M $(FUZZDATA)
	valgrind ./sessionfuzz$(TEXE) run $(TOP)/test/sessionfuzz-data1.db

# The veryquick.test TCL tests.
#
tcltest:	./testfixture$(TEXE)
	./testfixture$(TEXE) $(TOP)/test/veryquick.test $(TESTOPTS)

# Runs all the same tests cases as the "tcltest" target but uses
# the testrunner.tcl script to run them in multiple cores
# concurrently.
testrunner:	testfixture$(TEXE)
	./testfixture$(TEXE) $(TOP)/test/testrunner.tcl

# Minimal testing that runs in less than 3 minutes
#
quicktest:	./testfixture$(TEXE)
	./testfixture$(TEXE) $(TOP)/test/extraquick.test $(TESTOPTS)

# This is the common case.  Run many tests that do not take too long,
# including fuzzcheck, sqlite3_analyzer, and sqldiff tests.
#
test:	fastfuzztest sourcetest $(TESTPROGS) tcltest
test:	fuzztest sourcetest $(TESTPROGS) tcltest

# Run a test using valgrind.  This can take a really long time
# because valgrind is so much slower than a native machine.
#
valgrindtest:	$(TESTPROGS) valgrindfuzz
	OMIT_MISUSE=1 valgrind -v ./testfixture$(TEXE) $(TOP)/test/permutations.test valgrind $(TESTOPTS)

# A very fast test that checks basic sanity.  The name comes from
# the 60s-era electronics testing:  "Turn it on and see if smoke
# comes out."
#
smoketest:	$(TESTPROGS) fuzzcheck$(TEXE)
	./testfixture$(TEXE) $(TOP)/test/main.test $(TESTOPTS)

shelltest: $(TESTPROGS)
	./testfixture$(TEXT) $(TOP)/test/permutations.test shell

sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in
	$(TCLSH_CMD) $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in >sqlite3_analyzer.c

sqlite3_analyzer$(TEXE): sqlite3_analyzer.c
	$(LTLINK) sqlite3_analyzer.c -o $@ $(LIBTCL) $(TLIBS)

sqltclsh.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/sqltclsh.tcl $(TOP)/ext/misc/appendvfs.c $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqltclsh.c.in
1308
1309
1310
1311
1312
1313
1314
1315

1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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
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
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456

1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477







-
+



















-
+


+
+
+
















-
-
+
+
+






-
+


-
+



















+
+
+



















-
+












+







showwal$(TEXE):	$(TOP)/tool/showwal.c sqlite3.lo
	$(LTLINK) -o $@ $(TOP)/tool/showwal.c sqlite3.lo $(TLIBS)

showshm$(TEXE):	$(TOP)/tool/showshm.c
	$(LTLINK) -o $@ $(TOP)/tool/showshm.c

index_usage$(TEXE): $(TOP)/tool/index_usage.c sqlite3.lo
	$(LTLINK) -o $@ $(TOP)/tool/index_usage.c sqlite3.lo $(TLIBS)
	$(LTLINK) $(SHELL_OPT) -o $@ $(TOP)/tool/index_usage.c sqlite3.lo $(TLIBS)

changeset$(TEXE):	$(TOP)/ext/session/changeset.c sqlite3.lo
	$(LTLINK) -o $@ $(TOP)/ext/session/changeset.c sqlite3.lo $(TLIBS)

changesetfuzz$(TEXE):	$(TOP)/ext/session/changesetfuzz.c sqlite3.lo
	$(LTLINK) -o $@ $(TOP)/ext/session/changesetfuzz.c sqlite3.lo $(TLIBS)

rollback-test$(TEXE):	$(TOP)/tool/rollback-test.c sqlite3.lo
	$(LTLINK) -o $@ $(TOP)/tool/rollback-test.c sqlite3.lo $(TLIBS)

atrc$(TEXX): $(TOP)/test/atrc.c sqlite3.lo
	$(LTLINK) -o $@ $(TOP)/test/atrc.c sqlite3.lo $(TLIBS)

LogEst$(TEXE):	$(TOP)/tool/logest.c sqlite3.h
	$(LTLINK) -I. -o $@ $(TOP)/tool/logest.c

wordcount$(TEXE):	$(TOP)/test/wordcount.c sqlite3.lo
	$(LTLINK) -o $@ $(TOP)/test/wordcount.c sqlite3.lo $(TLIBS)

speedtest1$(TEXE):	$(TOP)/test/speedtest1.c sqlite3.c
speedtest1$(TEXE):	$(TOP)/test/speedtest1.c sqlite3.c Makefile
	$(LTLINK) $(ST_OPT) -o $@ $(TOP)/test/speedtest1.c sqlite3.c $(TLIBS)

startup$(TEXE):	$(TOP)/test/startup.c sqlite3.c
	$(CC) -Os -g -DSQLITE_THREADSAFE=0 -o $@ $(TOP)/test/startup.c sqlite3.c $(TLIBS)

KV_OPT += -DSQLITE_DIRECT_OVERFLOW_READ

kvtest$(TEXE):	$(TOP)/test/kvtest.c sqlite3.c
	$(LTLINK) $(KV_OPT) -o $@ $(TOP)/test/kvtest.c sqlite3.c $(TLIBS)

rbu$(EXE): $(TOP)/ext/rbu/rbu.c $(TOP)/ext/rbu/sqlite3rbu.c sqlite3.lo
	$(LTLINK) -I. -o $@ $(TOP)/ext/rbu/rbu.c sqlite3.lo $(TLIBS)

loadfts$(EXE): $(TOP)/tool/loadfts.c libsqlite3.la
	$(LTLINK) $(TOP)/tool/loadfts.c libsqlite3.la -o $@ $(TLIBS)

# This target will fail if the SQLite amalgamation contains any exported
# symbols that do not begin with "sqlite3_". It is run as part of the
# releasetest.tcl script.
#
VALIDIDS=' sqlite3(changeset|changegroup|session)?_'
checksymbols: sqlite3.lo
	nm -g --defined-only sqlite3.lo | egrep -v $(VALIDIDS); test $$? -ne 0
checksymbols: sqlite3.o
	nm -g --defined-only sqlite3.o
	nm -g --defined-only sqlite3.o | egrep -v $(VALIDIDS); test $$? -ne 0
	echo '0 errors out of 1 tests'

# Build the amalgamation-autoconf package.  The amalamgation-tarball target builds
# a tarball named for the version number.  Ex:  sqlite-autoconf-3110000.tar.gz.
# The snapshot-tarball target builds a tarball named by the SHA1 hash
#
amalgamation-tarball: sqlite3.c
amalgamation-tarball: sqlite3.c sqlite3rc.h
	TOP=$(TOP) sh $(TOP)/tool/mkautoconfamal.sh --normal

snapshot-tarball: sqlite3.c
snapshot-tarball: sqlite3.c sqlite3rc.h
	TOP=$(TOP) sh $(TOP)/tool/mkautoconfamal.sh --snapshot

# The next two rules are used to support the "threadtest" target. Building
# threadtest runs a few thread-safety tests that are implemented in C. This
# target is invoked by the releasetest.tcl script.
#
THREADTEST3_SRC = $(TOP)/test/threadtest3.c    \
                  $(TOP)/test/tt3_checkpoint.c \
                  $(TOP)/test/tt3_index.c      \
                  $(TOP)/test/tt3_vacuum.c      \
                  $(TOP)/test/tt3_stress.c      \
                  $(TOP)/test/tt3_lookaside1.c

threadtest3$(TEXE): sqlite3.lo $(THREADTEST3_SRC)
	$(LTLINK) $(TOP)/test/threadtest3.c $(TOP)/src/test_multiplex.c sqlite3.lo -o $@ $(TLIBS)

threadtest: threadtest3$(TEXE)
	./threadtest3$(TEXE)

threadtest5: sqlite3.c $(TOP)/test/threadtest5.c
	$(LTLINK) $(TOP)/test/threadtest5.c sqlite3.c -o $@ $(TLIBS)

releasetest:
	$(TCLSH_CMD) $(TOP)/test/releasetest.tcl

# Standard install and cleanup targets
#
lib_install:	libsqlite3.la
	$(INSTALL) -d $(DESTDIR)$(libdir)
	$(LTINSTALL) libsqlite3.la $(DESTDIR)$(libdir)

install:	sqlite3$(TEXE) lib_install sqlite3.h sqlite3.pc ${HAVE_TCL:1=tcl_install}
	$(INSTALL) -d $(DESTDIR)$(bindir)
	$(LTINSTALL) sqlite3$(TEXE) $(DESTDIR)$(bindir)
	$(INSTALL) -d $(DESTDIR)$(includedir)
	$(INSTALL) -m 0644 sqlite3.h $(DESTDIR)$(includedir)
	$(INSTALL) -m 0644 $(TOP)/src/sqlite3ext.h $(DESTDIR)$(includedir)
	$(INSTALL) -d $(DESTDIR)$(pkgconfigdir)
	$(INSTALL) -m 0644 sqlite3.pc $(DESTDIR)$(pkgconfigdir)

pkgIndex.tcl:
	echo 'package ifneeded sqlite3 $(RELEASE) [list load $(TCLLIBDIR)/libtclsqlite3$(SHLIB_SUFFIX) sqlite3]' > $@
	echo 'package ifneeded sqlite3 $(RELEASE) [list load [file join $$dir libtclsqlite3[info sharedlibextension]] sqlite3]' > $@
tcl_install:	lib_install libtclsqlite3.la pkgIndex.tcl
	$(INSTALL) -d $(DESTDIR)$(TCLLIBDIR)
	$(LTINSTALL) libtclsqlite3.la $(DESTDIR)$(TCLLIBDIR)
	rm -f $(DESTDIR)$(TCLLIBDIR)/libtclsqlite3.la $(DESTDIR)$(TCLLIBDIR)/libtclsqlite3.a
	$(INSTALL) -m 0644 pkgIndex.tcl $(DESTDIR)$(TCLLIBDIR)

clean:
	rm -f *.lo *.la *.o sqlite3$(TEXE) libsqlite3.la
	rm -f sqlite3.h opcodes.*
	rm -rf .libs .deps
	rm -f lemon$(BEXE) lempar.c parse.* sqlite*.tar.gz
	rm -f mkkeywordhash$(BEXE) keywordhash.h
	rm -f mksourceid$(BEXE)
	rm -f *.da *.bb *.bbg gmon.out
	rm -rf tsrc .target_source
	rm -f tclsqlite3$(TEXE)
	rm -f testfixture$(TEXE) test.db
	rm -f LogEst$(TEXE) fts3view$(TEXE) rollback-test$(TEXE) showdb$(TEXE)
	rm -f showjournal$(TEXE) showstat4$(TEXE) showwal$(TEXE) speedtest1$(TEXE)
	rm -f wordcount$(TEXE) changeset$(TEXE)
1431
1432
1433
1434
1435
1436
1437

1438
1439
1440


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






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







+


-
+
+


















+
+
+
+
+
+
	rm -f rbu rbu.exe
	rm -f srcck1 srcck1.exe
	rm -f fuzzershell fuzzershell.exe
	rm -f fuzzcheck fuzzcheck.exe
	rm -f sqldiff sqldiff.exe
	rm -f dbhash dbhash.exe
	rm -f fts5.* fts5parse.*
	rm -f threadtest5

distclean:	clean
	rm -f config.h config.log config.status libtool Makefile sqlite3.pc
	rm -f sqlite_cfg.h config.log config.status libtool Makefile sqlite3.pc \
		$(TESTPROGS)

#
# Windows section
#
dll: sqlite3.dll

REAL_LIBOBJ = $(LIBOBJ:%.lo=.libs/%.o)

$(REAL_LIBOBJ): $(LIBOBJ)

sqlite3.def: $(REAL_LIBOBJ)
	echo 'EXPORTS' >sqlite3.def
	nm $(REAL_LIBOBJ) | grep ' T ' | grep ' _sqlite3_' \
		| sed 's/^.* _//' >>sqlite3.def

sqlite3.dll: $(REAL_LIBOBJ) sqlite3.def
	$(TCC) -shared -o $@ sqlite3.def \
		-Wl,"--strip-all" $(REAL_LIBOBJ)

#
# Fiddle app
#
fiddle: sqlite3.c shell.c
	make -C ext/wasm fiddle emcc_opt=-Os

Changes to Makefile.linux-gcc.

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







-
+


















-
-
+
+














-
-
+
+
-
-
-
+











-
+




















-
-
-
+
-
-




-
+
-
-







#    that contains this "Makefile.in" and the "configure.in" script.
#
TOP = ../sqlite

#### C Compiler and options for use in building executables that
#    will run on the platform that is doing the build.
#
BCC = gcc -g -O2
BCC = gcc -g -O0
#BCC = /opt/ancic/bin/c89 -0

#### If the target operating system supports the "usleep()" system
#    call, then define the HAVE_USLEEP macro for all C modules.
#
#USLEEP = 
USLEEP = -DHAVE_USLEEP=1

#### If you want the SQLite library to be safe for use within a 
#    multi-threaded program, then define the following macro
#    appropriately:
#
#THREADSAFE = -DTHREADSAFE=1
THREADSAFE = -DTHREADSAFE=0

#### Specify any extra linker options needed to make the library
#    thread safe
#
#THREADLIB = -lpthread
THREADLIB = 
THREADLIB = -lpthread -lm -ldl
#THREADLIB = 

#### Specify any extra libraries needed to access required functions.
#
#TLIBS = -lrt    # fdatasync on Solaris 8
TLIBS = 

#### Leave SQLITE_DEBUG undefined for maximum speed.  Use SQLITE_DEBUG=1
#    to check for memory leaks.  Use SQLITE_DEBUG=2 to print a log of all
#    malloc()s and free()s in order to track down memory leaks.
#    
#    SQLite uses some expensive assert() statements in the inner loop.
#    You can make the library go almost twice as fast if you compile
#    with -DNDEBUG=1
#
#OPTS = -DSQLITE_DEBUG=2
#OPTS = -DSQLITE_DEBUG=1
OPTS += -DSQLITE_DEBUG=1
OPTS += -DSQLITE_ENABLE_WHERETRACE
#OPTS = 
OPTS = -DNDEBUG=1
OPTS += -DHAVE_FDATASYNC=1
OPTS += -DSQLITE_ENABLE_SELECTTRACE

#### The suffix to add to executable files.  ".exe" for windows.
#    Nothing for unix.
#
#EXE = .exe
EXE =

#### C Compile and options for use in building executables that 
#    will run on the target platform.  This is usually the same
#    as BCC, unless you are cross-compiling.
#
TCC = gcc -O6
TCC = gcc -O0
#TCC = gcc -g -O0 -Wall
#TCC = gcc -g -O0 -Wall -fprofile-arcs -ftest-coverage
#TCC = /opt/mingw/bin/i386-mingw32-gcc -O6
#TCC = /opt/ansic/bin/c89 -O +z -Wl,-a,archive

#### Tools used to build a static library.
#
AR = ar cr
#AR = /opt/mingw/bin/i386-mingw32-ar cr
RANLIB = ranlib
#RANLIB = /opt/mingw/bin/i386-mingw32-ranlib

MKSHLIB = gcc -shared
SO = so
SHPREFIX = lib
# SO = dll
# SHPREFIX =

#### Extra compiler options needed for programs that use the TCL library.
#
#TCL_FLAGS =
#TCL_FLAGS = -DSTATIC_BUILD=1
TCL_FLAGS = -I/home/drh/tcltk/8.5linux
TCL_FLAGS = -I/home/drh/tcl/include/tcl8.6
#TCL_FLAGS = -I/home/drh/tcltk/8.5win -DSTATIC_BUILD=1
#TCL_FLAGS = -I/home/drh/tcltk/8.3hpux

#### Linker options needed to link against the TCL library.
#
#LIBTCL = -ltcl -lm -ldl
LIBTCL = /home/drh/tcltk/8.5linux/libtcl8.5g.a -lm -ldl
LIBTCL = /home/drh/tcl/lib/libtcl8.6.a -lm -lpthread -ldl -lz
#LIBTCL = /home/drh/tcltk/8.5win/libtcl85s.a -lmsvcrt
#LIBTCL = /home/drh/tcltk/8.3hpux/libtcl8.3.a -ldld -lm -lc

#### Additional objects for SQLite library when TCL support is enabled.
#TCLOBJ =
TCLOBJ = tclsqlite.o

#### Compiler options needed for programs that use the readline() library.
#

Changes to Makefile.msc.

69
70
71
72
73
74
75
76

77
78
79
80
81
82
83
69
70
71
72
73
74
75

76
77
78
79
80
81
82
83







-
+







# If necessary, create a list of harmless compiler warnings to disable when
# compiling the various tools.  For the SQLite source code itself, warnings,
# if any, will be disabled from within it.
#
!IFNDEF NO_WARN
!IF $(USE_FULLWARN)!=0
NO_WARN = -wd4054 -wd4055 -wd4100 -wd4127 -wd4130 -wd4152 -wd4189 -wd4206
NO_WARN = $(NO_WARN) -wd4210 -wd4232 -wd4305 -wd4306 -wd4702 -wd4706
NO_WARN = $(NO_WARN) -wd4210 -wd4232 -wd4244 -wd4305 -wd4306 -wd4702 -wd4706
!ENDIF
!ENDIF

# Set this non-0 to use the library paths and other options necessary for
# Windows Phone 8.1.
#
!IFNDEF USE_WP81_OPTS
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
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







+
+
+
+
+
+
+
+
+
+













+
+
+
+
+
+







# 5 == SQLITE_DEBUG_OS_TRACE: Enables output from the OSTRACE() macros.
# 6 == SQLITE_ENABLE_IOTRACE: Enables output from the IOTRACE() macros.
#
!IFNDEF DEBUG
DEBUG = 0
!ENDIF

# <<mark>>
# By default, use --linemacros=1 argument to the mksqlite3c.tcl tool, which
# is used to build the amalgamation. This can be turned off to ease debug
# of the amalgamation away from the source tree.
#
!IFNDEF NO_LINEMACROS
NO_LINEMACROS = 0
!ENDIF
# <</mark>>

# Enable use of available compiler optimizations?  Normally, this should be
# non-zero.  Setting this to zero, thus disabling all compiler optimizations,
# can be useful for testing.
#
!IFNDEF OPTIMIZATIONS
OPTIMIZATIONS = 2
!ENDIF

# Set this to non-0 to enable support for the session extension.
#
!IFNDEF SESSION
SESSION = 0
!ENDIF

# Set this to non-0 to enable support for the rbu extension.
#
!IFNDEF RBU
RBU = 0
!ENDIF

# Set the source code file to be used by executables and libraries when
# they need the amalgamation.
#
!IFNDEF SQLITE3C
!IF $(SPLIT_AMALGAMATION)!=0
SQLITE3C = sqlite3-all.c
315
316
317
318
319
320
321







322
323
324
325
326
327
328
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351







+
+
+
+
+
+
+







!IFNDEF SQLITETCLH
SQLITETCLH = sqlite_tcl.h
!ENDIF

!IFNDEF SQLITETCLDECLSH
SQLITETCLDECLSH = sqlite_tclDecls.h
!ENDIF

# This is the name to use for the dynamic link library (DLL) containing the
# Tcl bindings for SQLite.
#
!IFNDEF SQLITE3TCLDLL
SQLITE3TCLDLL = tclsqlite3.dll
!ENDIF

# These are the additional targets that the targets that integrate with the
# Tcl library should depend on when compiling, etc.
#
!IFNDEF SQLITE_TCL_DEP
!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
SQLITE_TCL_DEP = $(SQLITETCLDECLSH) $(SQLITETCLH)
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
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







-



-
+
-











+
+
+
+
+
+
+
+
+
+







# the Windows platform.
#
!IFNDEF OPT_FEATURE_FLAGS
!IF $(MINIMAL_AMALGAMATION)==0
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_GEOPOLY=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_JSON1=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBSTAT_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_INTROSPECTION_PRAGMAS=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DESERIALIZE=1
!ENDIF
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
!ENDIF

# Should the session extension be enabled?  If so, add compilation options
# to enable it.
#
!IF $(SESSION)!=0
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_SESSION=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_PREUPDATE_HOOK=1
!ENDIF

# Always enable math functions on Windows
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_MATH_FUNCTIONS

# Should the rbu extension be enabled?  If so, add compilation options
# to enable it.
#
!IF $(RBU)!=0
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RBU=1
!ENDIF

# These are the "extended" SQLite compilation options used when compiling for
# the Windows 10 platform.
#
!IFNDEF EXT_FEATURE_FLAGS
!IF $(FOR_WIN10)!=0
EXT_FEATURE_FLAGS = $(EXT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS4=1
491
492
493
494
495
496
497
498

499
500

501
502
503
504
505
506
507
522
523
524
525
526
527
528

529
530

531
532
533
534
535
536
537
538







-
+

-
+








UCRTLIBPATH = $(UCRTLIBPATH:\\=\)

# C compiler and options for use in building executables that
# will run on the platform that is doing the build.
#
!IF $(USE_FULLWARN)!=0
BCC = $(NCC) -nologo -W4 $(CCOPTS) $(BCCOPTS)
BCC = $(NCC) -nologo -W4 -Fd$*.pdb $(CCOPTS) $(BCCOPTS)
!ELSE
BCC = $(NCC) -nologo -W3 $(CCOPTS) $(BCCOPTS)
BCC = $(NCC) -nologo -W3 -Fd$*.pdb $(CCOPTS) $(BCCOPTS)
!ENDIF

# Check if assembly code listings should be generated for the source
# code files to be compiled.
#
!IF $(USE_LISTINGS)!=0
BCC = $(BCC) -FAcs
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
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







-
-
+
+

-
+



-
-
+
+

-
+







# also be noted here that building any target with these "stdcall" options
# will most likely fail if the Tcl library is also required.  This is due
# to how the Tcl library functions are declared and exported (i.e. without
# an explicit calling convention, which results in "cdecl").
#
!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
!IF "$(PLATFORM)"=="x86"
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
CORE_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
SHELL_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
# <<mark>>
TEST_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall -DINCLUDE_SQLITE_TCL_H=1 -DSQLITE_TCLAPI=__cdecl
TEST_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall -DINCLUDE_SQLITE_TCL_H=1 -DSQLITE_TCLAPI=__cdecl
# <</mark>>
!ELSE
!IFNDEF PLATFORM
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
CORE_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
SHELL_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
# <<mark>>
TEST_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall -DINCLUDE_SQLITE_TCL_H=1 -DSQLITE_TCLAPI=__cdecl
TEST_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall -DINCLUDE_SQLITE_TCL_H=1 -DSQLITE_TCLAPI=__cdecl
# <</mark>>
!ELSE
CORE_CCONV_OPTS =
SHELL_CCONV_OPTS =
# <<mark>>
TEST_CCONV_OPTS =
# <</mark>>
752
753
754
755
756
757
758
759
760


761
762

763
764
765
766
767
768
769
783
784
785
786
787
788
789


790
791
792

793
794
795
796
797
798
799
800







-
-
+
+

-
+







MKSQLITE3C_TOOL = $(TOP)\tool\mksqlite3c-noext.tcl
!ELSE
MKSQLITE3C_TOOL = $(TOP)\tool\mksqlite3c.tcl
!ENDIF
!ENDIF

!IFNDEF MKSQLITE3C_ARGS
!IF $(DEBUG)>1
MKSQLITE3C_ARGS = --linemacros
!IF $(DEBUG)>1 && $(NO_LINEMACROS)==0
MKSQLITE3C_ARGS = --linemacros=1
!ELSE
MKSQLITE3C_ARGS =
MKSQLITE3C_ARGS = --linemacros=0
!ENDIF
!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
MKSQLITE3C_ARGS = $(MKSQLITE3C_ARGS) --useapicall
!ENDIF
!ENDIF

# The mksqlite3h.tcl script accepts some options on the command line.
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
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907

908
909
910
911

912
913
914
915
916
917
918
919







+
+
+
+
+
+
+
+













-
+



-
+







# <<mark>>
# The locations of the Tcl header and library files.  Also, the library that
# non-stubs enabled programs using Tcl must link against.  These variables
# (TCLINCDIR, TCLLIBDIR, and LIBTCL) may be overridden via the environment
# prior to running nmake in order to match the actual installed location and
# version on this machine.
#
!IFNDEF TCLVERSION
TCLVERSION = 86
!ENDIF

!IFNDEF TCLSUFFIX
TCLSUFFIX =
!ENDIF

!IFNDEF TCLDIR
TCLDIR = $(TOP)\compat\tcl
!ENDIF

!IFNDEF TCLINCDIR
TCLINCDIR = $(TCLDIR)\include
!ENDIF

!IFNDEF TCLLIBDIR
TCLLIBDIR = $(TCLDIR)\lib
!ENDIF

!IFNDEF LIBTCL
LIBTCL = tcl86.lib
LIBTCL = tcl$(TCLVERSION)$(TCLSUFFIX).lib
!ENDIF

!IFNDEF LIBTCLSTUB
LIBTCLSTUB = tclstub86.lib
LIBTCLSTUB = tclstub$(TCLVERSION)$(TCLSUFFIX).lib
!ENDIF

!IFNDEF LIBTCLPATH
LIBTCLPATH = $(TCLDIR)\bin
!ENDIF

# The locations of the zlib header and library files.  These variables
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
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







-
+

















+
+
+
+
+







RCC = $(RCC) -I$(ICUINCDIR)
!ENDIF
# <</mark>>

# Command line prefixes for compiling code, compiling resources,
# linking, etc.
#
LTCOMPILE = $(TCC) -Fo$@
LTCOMPILE = $(TCC) -Fo$@ -Fd$*.pdb
LTRCOMPILE = $(RCC) -r
LTLIB = lib.exe
LTLINK = $(TCC) -Fe$@

# If requested, link to the RPCRT4 library.
#
!IF $(USE_RPCRT4_LIB)!=0
LTLIBS = $(LTLIBS) rpcrt4.lib
!ENDIF

# If a platform was set, force the linker to target that.
# Note that the vcvars*.bat family of batch files typically
# set this for you.  Otherwise, the linker will attempt
# to deduce the binary type based on the object files.
!IFDEF PLATFORM
LTLINKOPTS = /NOLOGO /MACHINE:$(PLATFORM)
LTLIBOPTS = /NOLOGO /MACHINE:$(PLATFORM)
!ELSEIF "$(VISUALSTUDIOVERSION)"=="12.0" || \
        "$(VISUALSTUDIOVERSION)"=="14.0" || \
        "$(VISUALSTUDIOVERSION)"=="15.0"
LTLINKOPTS = /NOLOGO /MACHINE:x86
LTLIBOPTS = /NOLOGO /MACHINE:x86
!ELSE
LTLINKOPTS = /NOLOGO
LTLIBOPTS = /NOLOGO
!ENDIF

# When compiling for use in the WinRT environment, the following
# linker option must be used to mark the executable as runnable
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
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







-
+



-
+






-
+
+







         date.lo dbpage.lo dbstat.lo delete.lo \
         expr.lo fault.lo fkey.lo \
         fts3.lo fts3_aux.lo fts3_expr.lo fts3_hash.lo fts3_icu.lo \
         fts3_porter.lo fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo \
         fts3_tokenize_vtab.lo fts3_unicode.lo fts3_unicode2.lo fts3_write.lo \
         fts5.lo \
         func.lo global.lo hash.lo \
         icu.lo insert.lo json1.lo legacy.lo loadext.lo \
         icu.lo insert.lo json.lo legacy.lo loadext.lo \
         main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \
         memdb.lo memjournal.lo \
         mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \
         notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \
         notify.lo opcodes.lo os.lo os_kv.lo os_unix.lo os_win.lo \
         pager.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
         random.lo resolve.lo rowset.lo rtree.lo \
         sqlite3session.lo select.lo sqlite3rbu.lo status.lo stmt.lo \
         table.lo threads.lo tokenize.lo treeview.lo trigger.lo \
         update.lo upsert.lo util.lo vacuum.lo \
         vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \
         vdbetrace.lo wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \
         vdbetrace.lo vdbevtab.lo wal.lo walker.lo where.lo wherecode.lo \
         whereexpr.lo \
         window.lo utf.lo vtab.lo
# <</mark>>

# Object files for the amalgamation.
#
LIBOBJS1 = sqlite3.lo

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
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342







+

















+







  $(TOP)\src\expr.c \
  $(TOP)\src\fault.c \
  $(TOP)\src\fkey.c \
  $(TOP)\src\func.c \
  $(TOP)\src\global.c \
  $(TOP)\src\hash.c \
  $(TOP)\src\insert.c \
  $(TOP)\src\json.c \
  $(TOP)\src\legacy.c \
  $(TOP)\src\loadext.c \
  $(TOP)\src\main.c \
  $(TOP)\src\malloc.c \
  $(TOP)\src\mem0.c \
  $(TOP)\src\mem1.c \
  $(TOP)\src\mem2.c \
  $(TOP)\src\mem3.c \
  $(TOP)\src\mem5.c \
  $(TOP)\src\memdb.c \
  $(TOP)\src\memjournal.c \
  $(TOP)\src\mutex.c \
  $(TOP)\src\mutex_noop.c \
  $(TOP)\src\mutex_unix.c \
  $(TOP)\src\mutex_w32.c \
  $(TOP)\src\notify.c \
  $(TOP)\src\os.c \
  $(TOP)\src\os_kv.c \
  $(TOP)\src\os_unix.c \
  $(TOP)\src\os_win.c

# Core source code files, part 2.
#
SRC01 = \
  $(TOP)\src\pager.c \
1317
1318
1319
1320
1321
1322
1323

1324
1325
1326
1327
1328
1329
1330
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378







+







  $(TOP)\src\vdbe.c \
  $(TOP)\src\vdbeapi.c \
  $(TOP)\src\vdbeaux.c \
  $(TOP)\src\vdbeblob.c \
  $(TOP)\src\vdbemem.c \
  $(TOP)\src\vdbesort.c \
  $(TOP)\src\vdbetrace.c \
  $(TOP)\src\vdbevtab.c \
  $(TOP)\src\vtab.c \
  $(TOP)\src\wal.c \
  $(TOP)\src\walker.c \
  $(TOP)\src\where.c \
  $(TOP)\src\wherecode.c \
  $(TOP)\src\whereexpr.c \
  $(TOP)\src\window.c
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
1408
1409
1410
1411
1412
1413
1414














1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434

1435
1436










1437
1438
1439
1440
1441
1442
1443







-
-
-
-
-
-
-
-
-
-
-
-
-
-




















-


-
-
-
-
-
-
-
-
-
-







  $(TOP)\src\sqliteLimit.h \
  $(TOP)\src\vdbe.h \
  $(TOP)\src\vdbeInt.h \
  $(TOP)\src\vxworks.h \
  $(TOP)\src\wal.h \
  $(TOP)\src\whereInt.h

# Extension source code files, part 1.
#
SRC06 = \
  $(TOP)\ext\fts1\fts1.c \
  $(TOP)\ext\fts1\fts1_hash.c \
  $(TOP)\ext\fts1\fts1_porter.c \
  $(TOP)\ext\fts1\fts1_tokenizer1.c \
  $(TOP)\ext\fts2\fts2.c \
  $(TOP)\ext\fts2\fts2_hash.c \
  $(TOP)\ext\fts2\fts2_icu.c \
  $(TOP)\ext\fts2\fts2_porter.c \
  $(TOP)\ext\fts2\fts2_tokenizer.c \
  $(TOP)\ext\fts2\fts2_tokenizer1.c

# Extension source code files, part 2.
#
SRC07 = \
  $(TOP)\ext\fts3\fts3.c \
  $(TOP)\ext\fts3\fts3_aux.c \
  $(TOP)\ext\fts3\fts3_expr.c \
  $(TOP)\ext\fts3\fts3_hash.c \
  $(TOP)\ext\fts3\fts3_icu.c \
  $(TOP)\ext\fts3\fts3_porter.c \
  $(TOP)\ext\fts3\fts3_snippet.c \
  $(TOP)\ext\fts3\fts3_tokenizer.c \
  $(TOP)\ext\fts3\fts3_tokenizer1.c \
  $(TOP)\ext\fts3\fts3_tokenize_vtab.c \
  $(TOP)\ext\fts3\fts3_unicode.c \
  $(TOP)\ext\fts3\fts3_unicode2.c \
  $(TOP)\ext\fts3\fts3_write.c \
  $(TOP)\ext\icu\icu.c \
  $(TOP)\ext\rtree\rtree.c \
  $(TOP)\ext\session\sqlite3session.c \
  $(TOP)\ext\rbu\sqlite3rbu.c \
  $(TOP)\ext\misc\json1.c \
  $(TOP)\ext\misc\stmt.c

# Extension header files, part 1.
#
SRC08 = \
  $(TOP)\ext\fts1\fts1.h \
  $(TOP)\ext\fts1\fts1_hash.h \
  $(TOP)\ext\fts1\fts1_tokenizer.h \
  $(TOP)\ext\fts2\fts2.h \
  $(TOP)\ext\fts2\fts2_hash.h \
  $(TOP)\ext\fts2\fts2_tokenizer.h

# Extension header files, part 2.
#
SRC09 = \
  $(TOP)\ext\fts3\fts3.h \
  $(TOP)\ext\fts3\fts3Int.h \
  $(TOP)\ext\fts3\fts3_hash.h \
  $(TOP)\ext\fts3\fts3_tokenizer.h \
1447
1448
1449
1450
1451
1452
1453
1454

1455
1456
1457
1458
1459
1460
1461
1470
1471
1472
1473
1474
1475
1476

1477
1478
1479
1480
1481
1482
1483
1484







-
+







  $(SQLITETCLDECLSH)
!ELSE
SRC12 =
!ENDIF

# All source code files.
#
SRC = $(SRC00) $(SRC01) $(SRC03) $(SRC04) $(SRC05) $(SRC06) $(SRC07) $(SRC08) $(SRC09) $(SRC10) $(SRC11)
SRC = $(SRC00) $(SRC01) $(SRC03) $(SRC04) $(SRC05) $(SRC07) $(SRC09) $(SRC10) $(SRC11) $(SRC12)

# Source code to the test files.
#
TESTSRC = \
  $(TOP)\src\test1.c \
  $(TOP)\src\test2.c \
  $(TOP)\src\test3.c \
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
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
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
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
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585

1586
1587
1588
1589
1590
1591
1592







+







-
+







+
+
+

+


+












+
+






-
+
+
+
+
+
+













-







  $(TOP)\src\test_schema.c \
  $(TOP)\src\test_server.c \
  $(TOP)\src\test_superlock.c \
  $(TOP)\src\test_syscall.c \
  $(TOP)\src\test_tclsh.c \
  $(TOP)\src\test_tclvar.c \
  $(TOP)\src\test_thread.c \
  $(TOP)\src\test_vdbecov.c \
  $(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 \
  $(TOP)\ext\misc\appendvfs.c \
  $(TOP)\ext\misc\basexx.c \
  $(TOP)\ext\misc\bgckpt.c \
  $(TOP)\ext\misc\carray.c \
  $(TOP)\ext\misc\cksumvfs.c \
  $(TOP)\ext\misc\closure.c \
  $(TOP)\ext\misc\csv.c \
  $(TOP)\ext\misc\decimal.c \
  $(TOP)\ext\misc\eval.c \
  $(TOP)\ext\misc\explain.c \
  $(TOP)\ext\misc\fileio.c \
  $(TOP)\ext\misc\fuzzer.c \
  $(TOP)\ext\fts5\fts5_tcl.c \
  $(TOP)\ext\fts5\fts5_test_mi.c \
  $(TOP)\ext\fts5\fts5_test_tok.c \
  $(TOP)\ext\misc\ieee754.c \
  $(TOP)\ext\misc\mmapwarm.c \
  $(TOP)\ext\misc\nextchar.c \
  $(TOP)\ext\misc\normalize.c \
  $(TOP)\ext\misc\percentile.c \
  $(TOP)\ext\misc\prefixes.c \
  $(TOP)\ext\misc\qpvtab.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 \
  $(TOP)\ext\rtree\test_rtreedoc.c \
  $(TOP)\ext\recover\sqlite3recover.c \
  $(TOP)\ext\recover\test_recover.c \
  $(TOP)\ext\recover\dbdata.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

# Source code to the library files needed by the test fixture
# (non-amalgamation)
#
TESTSRC2 = \
  $(SRC00) \
  $(SRC01) \
  $(SRC06) \
  $(SRC07) \
  $(SRC10) \
  $(TOP)\ext\async\sqlite3async.c

# Header files used by all library source files.
#
HDR = \
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1614
1615
1616
1617
1618
1619
1620








1621
1622
1623
1624
1625
1626
1627







-
-
-
-
-
-
-
-







   $(TOP)\src\vdbeInt.h \
   $(TOP)\src\vxworks.h \
   $(TOP)\src\whereInt.h

# Header files used by extensions
#
EXTHDR = $(EXTHDR) \
  $(TOP)\ext\fts1\fts1.h \
  $(TOP)\ext\fts1\fts1_hash.h \
  $(TOP)\ext\fts1\fts1_tokenizer.h
EXTHDR = $(EXTHDR) \
  $(TOP)\ext\fts2\fts2.h \
  $(TOP)\ext\fts2\fts2_hash.h \
  $(TOP)\ext\fts2\fts2_tokenizer.h
EXTHDR = $(EXTHDR) \
  $(TOP)\ext\fts3\fts3.h \
  $(TOP)\ext\fts3\fts3Int.h \
  $(TOP)\ext\fts3\fts3_hash.h \
  $(TOP)\ext\fts3\fts3_tokenizer.h
EXTHDR = $(EXTHDR) \
  $(TOP)\ext\rtree\rtree.h \
  $(TOP)\ext\rtree\geopoly.c
1621
1622
1623
1624
1625
1626
1627
1628


1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647





















1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660

1661
1662
1663
1664
1665
1666
1667
1648
1649
1650
1651
1652
1653
1654

1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665

1666
1667
1668
1669
1670




1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703

1704
1705
1706
1707
1708
1709
1710
1711







-
+
+









-





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












-
+







FUZZDATA = \
  $(TOP)\test\fuzzdata1.db \
  $(TOP)\test\fuzzdata2.db \
  $(TOP)\test\fuzzdata3.db \
  $(TOP)\test\fuzzdata4.db \
  $(TOP)\test\fuzzdata5.db \
  $(TOP)\test\fuzzdata6.db \
  $(TOP)\test\fuzzdata7.db
  $(TOP)\test\fuzzdata7.db \
  $(TOP)\test\fuzzdata8.db
# <</mark>>

# Additional compiler options for the shell.  These are only effective
# when the shell is not being dynamically linked.
#
!IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_FTS4=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DESERIALIZE=1
!ENDIF

# <<mark>>
# Extra compiler options for various test tools.
#
MPTESTER_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5
FUZZERSHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1
FUZZCHECK_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ -DSQLITE_MAX_MEMORY=50000000 -DSQLITE_PRINTF_PRECISION_LIMIT=1000
FUZZCHECK_SRC = $(TOP)\test\fuzzcheck.c $(TOP)\test\ossfuzz.c
MPTESTER_COMPILE_OPTS = -DSQLITE_ENABLE_FTS5
FUZZERSHELL_COMPILE_OPTS =
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -I$(TOP)\test -I$(TOP)\ext\recover
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_MEMSYS5
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_OSS_FUZZ
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_MAX_MEMORY=50000000
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_PRINTF_PRECISION_LIMIT=1000
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_OMIT_LOAD_EXTENSION
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_FTS4
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_FTS5
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_RTREE
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_GEOPOLY
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_DBSTAT_VTAB
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_BYTECODE_VTAB
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\test\fuzzcheck.c
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\test\ossfuzz.c
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\test\fuzzinvariants.c
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\test\vt02.c
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\recover\dbdata.c
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\recover\sqlite3recover.c

OSSSHELL_SRC = $(TOP)\test\ossshell.c $(TOP)\test\ossfuzz.c
DBFUZZ_COMPILE_OPTS = -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION
KV_COMPILE_OPTS = -DSQLITE_THREADSAFE=0 -DSQLITE_DIRECT_OVERFLOW_READ
ST_COMPILE_OPTS = -DSQLITE_THREADSAFE=0

# Standard options to testfixture.
#
TESTOPTS = --verbose=file --output=test-out.txt

# Extra targets for the "all" target that require Tcl.
#
!IF $(NO_TCL)==0
ALL_TCL_TARGETS = libtclsqlite3.lib
ALL_TCL_TARGETS = $(SQLITE3TCLDLL)
!ELSE
ALL_TCL_TARGETS =
!ENDIF
# <</mark>>

# This is the default Makefile target.  The objects listed here
# are what get build when you type just "make" with no arguments.
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
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
1755
1756
1757
1758
1759
1760

1761
1762
1763
1764
1765
1766
1767
1768







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









-
+







shell:	$(SQLITE3EXE)

# <<mark>>
libsqlite3.lib:	$(LIBOBJ)
	$(LTLIB) $(LTLIBOPTS) /OUT:$@ $(LIBOBJ) $(TLIBS)

libtclsqlite3.lib:	tclsqlite.lo libsqlite3.lib
	$(LTLIB) $(LTLIBOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite.lo libsqlite3.lib $(LIBTCLSTUB) $(TLIBS)
	$(LTLIB) $(LTLIBOPTS) $(TCLLIBPATHS) $(LTLIBPATHS) /OUT:$@ tclsqlite.lo libsqlite3.lib $(LIBTCLSTUB) $(TLIBS)

tclsqlite3.def:	tclsqlite.lo
	echo EXPORTS > tclsqlite3.def
	dumpbin /all tclsqlite.lo \
		| $(TCLSH_CMD) $(TOP)\tool\replace.tcl include "^\s+/EXPORT:_?((?:Sqlite3|Tclsqlite3)_[^@]*)(?:@\d+)?$$" \1 \
		| sort >> tclsqlite3.def

pkgIndex.tcl:	$(TOP)\VERSION
	for /F %%V in ('type "$(TOP)\VERSION"') do ( \
		echo package ifneeded sqlite3 @version@ [list load [file join $$dir $(SQLITE3TCLDLL)] sqlite3] \
			| $(TCLSH_CMD) $(TOP)\tool\replace.tcl exact @version@ %%V > pkgIndex.tcl \
	)

$(SQLITE3TCLDLL):	libtclsqlite3.lib $(LIBRESOBJS) tclsqlite3.def pkgIndex.tcl
	$(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /DEF:tclsqlite3.def /OUT:$@ libtclsqlite3.lib $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
# <</mark>>

$(SQLITE3DLL):	$(LIBOBJ) $(LIBRESOBJS) $(CORE_LINK_DEP)
	$(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL $(CORE_LINK_OPTS) /OUT:$@ $(LIBOBJ) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)

# <<block2>>
sqlite3.def:	libsqlite3.lib
	echo EXPORTS > sqlite3.def
	dumpbin /all libsqlite3.lib \
		| $(TCLSH_CMD) $(TOP)\tool\replace.tcl include "^\s+1 _?(sqlite3(?:session|changeset|changegroup|rebaser)?_[^@]*)(?:@\d+)?$$" \1 \
		| $(TCLSH_CMD) $(TOP)\tool\replace.tcl include "^\s+1 _?(sqlite3(?:session|changeset|changegroup|rebaser|rbu)?_[^@]*)(?:@\d+)?$$" \1 \
		| sort >> sqlite3.def
# <</block2>>

$(SQLITE3EXE):	shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H)
	$(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) shell.c $(SHELL_CORE_SRC) \
		/link $(SQLITE3EXEPDB) $(LDFLAGS) $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)

1726
1727
1728
1729
1730
1731
1732
1733

1734
1735
1736

1737
1738
1739
1740
1741
1742
1743
1785
1786
1787
1788
1789
1790
1791

1792
1793
1794

1795
1796
1797
1798
1799
1800
1801
1802







-
+


-
+







fuzzershell.exe:	$(TOP)\tool\fuzzershell.c $(SQLITE3C) $(SQLITE3H)
	$(LTLINK) $(NO_WARN) $(FUZZERSHELL_COMPILE_OPTS) $(TOP)\tool\fuzzershell.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)

dbfuzz.exe:	$(TOP)\test\dbfuzz.c $(SQLITE3C) $(SQLITE3H)
	$(LTLINK) $(NO_WARN) $(DBFUZZ_COMPILE_OPTS) $(TOP)\test\dbfuzz.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)

fuzzcheck.exe:	$(FUZZCHECK_SRC) $(SQLITE3C) $(SQLITE3H)
	$(LTLINK) $(NO_WARN) $(FUZZCHECK_COMPILE_OPTS) $(FUZZCHECK_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
	$(LTLINK) $(NO_WARN) $(FUZZCHECK_OPTS) $(FUZZCHECK_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)

ossshell.exe:	$(OSSSHELL_SRC) $(SQLITE3C) $(SQLITE3H)
	$(LTLINK) $(NO_WARN) $(FUZZCHECK_COMPILE_OPTS) $(OSSSHELL_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
	$(LTLINK) $(NO_WARN) $(FUZZCHECK_OPTS) $(OSSSHELL_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)

sessionfuzz.exe:	zlib $(TOP)\test\sessionfuzz.c $(SQLITE3C) $(SQLITE3H)
	$(LTLINK) $(NO_WARN) -I$(ZLIBINCDIR) $(TOP)\test\sessionfuzz.c /link $(LDFLAGS) $(LTLINKOPTS) /LIBPATH:$(ZLIBLIBDIR) $(ZLIBLIB)

mptester.exe:	$(TOP)\mptest\mptest.c $(SQLITE3C) $(SQLITE3H)
	$(LTLINK) $(NO_WARN) $(MPTESTER_COMPILE_OPTS) $(TOP)\mptest\mptest.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)

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







-

-





+

+





-
+

-














-
+
+







	-rmdir /Q/S tsrc 2>NUL
	-mkdir tsrc
	for %i in ($(SRC00)) do copy /Y %i tsrc
	for %i in ($(SRC01)) do copy /Y %i tsrc
	for %i in ($(SRC03)) do copy /Y %i tsrc
	for %i in ($(SRC04)) do copy /Y %i tsrc
	for %i in ($(SRC05)) do copy /Y %i tsrc
	for %i in ($(SRC06)) do copy /Y %i tsrc
	for %i in ($(SRC07)) do copy /Y %i tsrc
	for %i in ($(SRC08)) do copy /Y %i tsrc
	for %i in ($(SRC09)) do copy /Y %i tsrc
	for %i in ($(SRC10)) do copy /Y %i tsrc
	for %i in ($(SRC11)) do copy /Y %i tsrc
	for %i in ($(SRC12)) do copy /Y %i tsrc
	copy /Y fts5.c tsrc
	copy /B tsrc\fts5.c +,,
	copy /Y fts5.h tsrc
	copy /B tsrc\fts5.h +,,
	del /Q tsrc\sqlite.h.in tsrc\parse.y 2>NUL
	$(TCLSH_CMD) $(TOP)\tool\vdbe-compress.tcl $(OPTS) < tsrc\vdbe.c > vdbe.new
	move vdbe.new tsrc\vdbe.c
	echo > .target_source

sqlite3.c:	.target_source sqlite3ext.h $(MKSQLITE3C_TOOL)
sqlite3.c:	.target_source sqlite3ext.h sqlite3session.h $(MKSQLITE3C_TOOL)
	$(TCLSH_CMD) $(MKSQLITE3C_TOOL) $(MKSQLITE3C_ARGS)
	copy $(TOP)\ext\session\sqlite3session.h .

sqlite3-all.c:	sqlite3.c $(TOP)\tool\split-sqlite3c.tcl
	$(TCLSH_CMD) $(TOP)\tool\split-sqlite3c.tcl
# <</mark>>

# Rule to build the amalgamation
#
sqlite3.lo:	$(SQLITE3C)
	$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(SQLITE3C)

# <<mark>>
# Rules to build the LEMON compiler generator
#
lempar.c:	$(TOP)\tool\lempar.c
	copy $(TOP)\tool\lempar.c .
	copy /Y $(TOP)\tool\lempar.c .
	copy /B lempar.c +,,

lemon.exe:	$(TOP)\tool\lemon.c lempar.c
	$(BCC) $(NO_WARN) -Daccess=_access \
		-Fe$@ $(TOP)\tool\lemon.c /link $(LDFLAGS) $(NLTLINKOPTS) $(NLTLIBPATHS)

# <<mark>>
# Rules to build the source-id generator tool
1825
1826
1827
1828
1829
1830
1831
1832

1833
1834
1835
1836
1837
1838
1839
1884
1885
1886
1887
1888
1889
1890

1891
1892
1893
1894
1895
1896
1897
1898







-
+







	$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c opcodes.c
# <</mark>>

# Rule to build the Win32 resources object file.
#
!IF $(USE_RC)!=0
# <<block1>>
$(LIBRESOBJS):	$(TOP)\src\sqlite3.rc $(SQLITE3H)
$(LIBRESOBJS):	$(TOP)\src\sqlite3.rc $(SQLITE3H) $(TOP)\VERSION
	echo #ifndef SQLITE_RESOURCE_VERSION > sqlite3rc.h
	for /F %%V in ('type "$(TOP)\VERSION"') do ( \
		echo #define SQLITE_RESOURCE_VERSION %%V \
			| $(TCLSH_CMD) $(TOP)\tool\replace.tcl exact . ^, >> sqlite3rc.h \
	)
	echo #endif >> sqlite3rc.h
	$(LTRCOMPILE) -fo $(LIBRESOBJS) $(TOP)\src\sqlite3.rc
1908
1909
1910
1911
1912
1913
1914



1915
1916
1917
1918
1919
1920
1921
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983







+
+
+








hash.lo:	$(TOP)\src\hash.c $(HDR)
	$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\hash.c

insert.lo:	$(TOP)\src\insert.c $(HDR)
	$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\insert.c

json.lo:	$(TOP)\src\json.c $(HDR)
	$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\json.c

legacy.lo:	$(TOP)\src\legacy.c $(HDR)
	$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\legacy.c

loadext.lo:	$(TOP)\src\loadext.c $(HDR)
	$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\loadext.c

main.lo:	$(TOP)\src\main.c $(HDR)
1968
1969
1970
1971
1972
1973
1974



1975
1976
1977
1978
1979
1980
1981
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046







+
+
+








pcache1.lo:	$(TOP)\src\pcache1.c $(HDR) $(TOP)\src\pcache.h
	$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\pcache1.c

os.lo:	$(TOP)\src\os.c $(HDR)
	$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\os.c

os_kv.lo:	$(TOP)\src\os_kv.c $(HDR)
	$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\os_kv.c

os_unix.lo:	$(TOP)\src\os_unix.c $(HDR)
	$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\os_unix.c

os_win.lo:	$(TOP)\src\os_win.c $(HDR)
	$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\os_win.c

pragma.lo:	$(TOP)\src\pragma.c $(HDR)
2049
2050
2051
2052
2053
2054
2055



2056
2057
2058
2059
2060
2061
2062
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130







+
+
+








vdbesort.lo:	$(TOP)\src\vdbesort.c $(HDR)
	$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vdbesort.c

vdbetrace.lo:	$(TOP)\src\vdbetrace.c $(HDR)
	$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vdbetrace.c

vdbevtab.lo:	$(TOP)\src\vdbevtab.c $(HDR)
	$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vdbevtab.c

vtab.lo:	$(TOP)\src\vtab.c $(HDR)
	$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vtab.c

wal.lo:	$(TOP)\src\wal.c $(HDR)
	$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\wal.c

walker.lo:	$(TOP)\src\walker.c $(HDR)
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
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2159
2160
2161
2162
2163
2164
2165

2166
2167


2168
2169
2170


2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200

2201
2202
2203
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
2234
2235


















2236
2237
2238
2239
2240
2241
2242







-
+

-
-
+
+
+
-
-











+

+
+
+
+












+
-
+
+
+

+
+
+
+
-
+


+
+
+
+




















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







opcodes.h:	parse.h $(TOP)\src\vdbe.c $(TOP)\tool\mkopcodeh.tcl
	type parse.h $(TOP)\src\vdbe.c | $(TCLSH_CMD) $(TOP)\tool\mkopcodeh.tcl > opcodes.h

# Rules to build parse.c and parse.h - the outputs of lemon.
#
parse.h:	parse.c

parse.c:	$(TOP)\src\parse.y lemon.exe $(TOP)\tool\addopcodes.tcl
parse.c:	$(TOP)\src\parse.y lemon.exe
	del /Q parse.y parse.h parse.h.temp 2>NUL
	copy $(TOP)\src\parse.y .
	.\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) parse.y
	copy /Y $(TOP)\src\parse.y .
	copy /B parse.y +,,
	.\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) -S parse.y
	move parse.h parse.h.temp
	$(TCLSH_CMD) $(TOP)\tool\addopcodes.tcl parse.h.temp > parse.h

$(SQLITE3H):	$(TOP)\src\sqlite.h.in $(TOP)\manifest mksourceid.exe $(TOP)\VERSION
	$(TCLSH_CMD) $(TOP)\tool\mksqlite3h.tcl $(TOP:\=/) > $(SQLITE3H) $(MKSQLITE3H_ARGS)

sqlite3ext.h:	.target_source
!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
	type tsrc\sqlite3ext.h | $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "\(\*\)" "(SQLITE_CALLBACK *)" \
		| $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "\(\*" "(SQLITE_APICALL *" > sqlite3ext.h
	copy /Y sqlite3ext.h tsrc\sqlite3ext.h
!ELSE
	copy /Y tsrc\sqlite3ext.h sqlite3ext.h
	copy /B sqlite3ext.h +,,
!ENDIF

sqlite3session.h:	$(TOP)\ext\session\sqlite3session.h
	copy /Y $(TOP)\ext\session\sqlite3session.h .
	copy /B sqlite3session.h +,,

mkkeywordhash.exe:	$(TOP)\tool\mkkeywordhash.c
	$(BCC) $(NO_WARN) -Fe$@ $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) \
		$(TOP)\tool\mkkeywordhash.c /link $(LDFLAGS) $(NLTLINKOPTS) $(NLTLIBPATHS)

keywordhash.h:	$(TOP)\tool\mkkeywordhash.c mkkeywordhash.exe
	.\mkkeywordhash.exe > keywordhash.h

# Source files that go into making shell.c
SHELL_SRC = \
	$(TOP)\src\shell.c.in \
	$(TOP)\ext\misc\appendvfs.c \
	$(TOP)\ext\misc\completion.c \
	$(TOP)\ext\misc\shathree.c \
        $(TOP)\ext\misc\base64.c \
        $(TOP)\ext\misc\base85.c \
	$(TOP)\ext\misc\decimal.c \
	$(TOP)\ext\misc\fileio.c \
	$(TOP)\ext\misc\ieee754.c \
	$(TOP)\ext\misc\regexp.c \
	$(TOP)\ext\misc\series.c \
	$(TOP)\ext\misc\shathree.c \
	$(TOP)\ext\misc\completion.c \
	$(TOP)\ext\misc\uint.c \
	$(TOP)\ext\expert\sqlite3expert.c \
	$(TOP)\ext\expert\sqlite3expert.h \
	$(TOP)\ext\misc\memtrace.c \
	$(TOP)/ext/recover/dbdata.c \
	$(TOP)/ext/recover/sqlite3recover.c \
	$(TOP)/ext/recover/sqlite3recover.h \
	$(TOP)\src\test_windirent.c

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

shell.c:	$(SHELL_SRC) $(TOP)\tool\mkshellc.tcl
	$(TCLSH_CMD) $(TOP)\tool\mkshellc.tcl > shell.c

zlib:
	pushd $(ZLIBDIR) && $(MAKE) /f win32\Makefile.msc clean $(ZLIBLIB) && popd

# Rules to build the extension objects.
#
icu.lo:	$(TOP)\ext\icu\icu.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\icu\icu.c

fts2.lo:	$(TOP)\ext\fts2\fts2.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2.c

fts2_hash.lo:	$(TOP)\ext\fts2\fts2_hash.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2_hash.c

fts2_icu.lo:	$(TOP)\ext\fts2\fts2_icu.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2_icu.c

fts2_porter.lo:	$(TOP)\ext\fts2\fts2_porter.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2_porter.c

fts2_tokenizer.lo:	$(TOP)\ext\fts2\fts2_tokenizer.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2_tokenizer.c

fts2_tokenizer1.lo:	$(TOP)\ext\fts2\fts2_tokenizer1.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2_tokenizer1.c

fts3.lo:	$(TOP)\ext\fts3\fts3.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3.c

fts3_aux.lo:	$(TOP)\ext\fts3\fts3_aux.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_aux.c

fts3_expr.lo:	$(TOP)\ext\fts3\fts3_expr.c $(HDR) $(EXTHDR)
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2268
2269
2270
2271
2272
2273
2274



2275
2276
2277
2278
2279
2280
2281







-
-
-








fts3_unicode2.lo:	$(TOP)\ext\fts3\fts3_unicode2.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_unicode2.c

fts3_write.lo:	$(TOP)\ext\fts3\fts3_write.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_write.c

json1.lo:	$(TOP)\ext\misc\json1.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\misc\json1.c

stmt.lo:	$(TOP)\ext\misc\stmt.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\misc\stmt.c

rtree.lo:	$(TOP)\ext\rtree\rtree.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\rtree\rtree.c

sqlite3session.lo:	$(TOP)\ext\session\sqlite3session.c $(HDR) $(EXTHDR)
2253
2254
2255
2256
2257
2258
2259
2260


2261
2262

2263
2264
2265
2266
2267
2268


2269
2270
2271
2272


2273
2274
2275
2276
2277
2278
2279
2315
2316
2317
2318
2319
2320
2321

2322
2323
2324

2325
2326
2327
2328
2329
2330

2331
2332
2333
2334
2335

2336
2337
2338
2339
2340
2341
2342
2343
2344







-
+
+

-
+





-
+
+



-
+
+







   $(TOP)\ext\lsm1\lsm_tree.c \
   $(TOP)\ext\lsm1\lsm_unix.c \
   $(TOP)\ext\lsm1\lsm_varint.c \
   $(TOP)\ext\lsm1\lsm_vtab.c \
   $(TOP)\ext\lsm1\lsm_win32.c

fts5parse.c:	$(TOP)\ext\fts5\fts5parse.y lemon.exe
	copy $(TOP)\ext\fts5\fts5parse.y .
	copy /Y $(TOP)\ext\fts5\fts5parse.y .
	copy /B fts5parse.y +,,
	del /Q fts5parse.h 2>NUL
	.\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) fts5parse.y
	.\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) -S fts5parse.y

fts5parse.h:	fts5parse.c

fts5.c:	$(FTS5_SRC)
	$(TCLSH_CMD) $(TOP)\ext\fts5\tool\mkfts5c.tcl
	copy $(TOP)\ext\fts5\fts5.h .
	copy /Y $(TOP)\ext\fts5\fts5.h .
	copy /B fts5.h +,,

lsm1.c:	$(LSM1_SRC)
	$(TCLSH_CMD) $(TOP)\ext\lsm1\tool\mklsm1c.tcl
	copy $(TOP)\ext\lsm1\lsm.h .
	copy /Y $(TOP)\ext\lsm1\lsm.h .
	copy /B lsm.h +,,

fts5.lo:	fts5.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c fts5.c

fts5_ext.lo:	fts5.c $(HDR) $(EXTHDR)
	$(LTCOMPILE) $(NO_WARN) -c fts5.c

2293
2294
2295
2296
2297
2298
2299
2300
2301


2302
2303
2304
2305
2306
2307
2308
2358
2359
2360
2361
2362
2363
2364


2365
2366
2367
2368
2369
2370
2371
2372
2373







-
-
+
+







TESTFIXTURE_FLAGS = -DTCLSH_INIT_PROC=sqlite3TestInit -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERVER=1 -DSQLITE_PRIVATE=""
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_CORE $(NO_WARN)
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERIES_CONSTRAINT_VERIFY=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_DEFAULT_PAGE_SIZE=1024
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_JSON1=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_DESERIALIZE=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_CKSUMVFS_STATIC=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) $(TEST_CCONV_OPTS)

TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2)
TESTFIXTURE_SRC1 = $(TESTEXT) $(SQLITE3C)
!IF $(USE_AMALGAMATION)==0
TESTFIXTURE_SRC = $(TESTSRC) $(TOP)\src\tclsqlite.c $(TESTFIXTURE_SRC0)
!ELSE
2339
2340
2341
2342
2343
2344
2345


2346

2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377





2378
2379






2380
2381
2382
2383
2384



2385
2386
2387
2388
2389
2390
2391
2404
2405
2406
2407
2408
2409
2410
2411
2412

2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431



2432
2433
2434
2435
2436
2437
2438
2439
2440

2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468







+
+
-
+


















-
-
-









-
+
+
+
+
+


+
+
+
+
+
+





+
+
+







	@set PATH=$(LIBTCLPATH);$(PATH)
	.\testfixture.exe $(TOP)\test\loadext.test $(TESTOPTS)

coretestprogs:	$(TESTPROGS)

testprogs:	coretestprogs srcck1.exe fuzzcheck.exe sessionfuzz.exe

fulltest:	alltest fuzztest

fulltest:	$(TESTPROGS) fuzztest
alltest:	$(TESTPROGS)
	@set PATH=$(LIBTCLPATH);$(PATH)
	.\testfixture.exe $(TOP)\test\all.test $(TESTOPTS)

soaktest:	$(TESTPROGS)
	@set PATH=$(LIBTCLPATH);$(PATH)
	.\testfixture.exe $(TOP)\test\all.test -soak=1 $(TESTOPTS)

fulltestonly:	$(TESTPROGS) fuzztest
	@set PATH=$(LIBTCLPATH);$(PATH)
	.\testfixture.exe $(TOP)\test\full.test

queryplantest:	testfixture.exe shell
	@set PATH=$(LIBTCLPATH);$(PATH)
	.\testfixture.exe $(TOP)\test\permutations.test queryplanner $(TESTOPTS)

fuzztest:	fuzzcheck.exe
	.\fuzzcheck.exe $(FUZZDATA)

fastfuzztest:	fuzzcheck.exe
	.\fuzzcheck.exe --limit-mem 100M $(FUZZDATA)

# Minimal testing that runs in less than 3 minutes (on a fast machine)
#
quicktest:	testfixture.exe sourcetest
	@set PATH=$(LIBTCLPATH);$(PATH)
	.\testfixture.exe $(TOP)\test\extraquick.test $(TESTOPTS)

# This is the common case.  Run many tests that do not take too long,
# including fuzzcheck, sqlite3_analyzer, and sqldiff tests.
#
test:	$(TESTPROGS) sourcetest fastfuzztest
test:	$(TESTPROGS) sourcetest fuzztest tcltest

# The veryquick.test TCL tests.
#
tcltest: testfixture.exe
	@set PATH=$(LIBTCLPATH);$(PATH)
	.\testfixture.exe $(TOP)\test\veryquick.test $(TESTOPTS)

# Runs all the same tests cases as the "tcltest" target but uses
# the testrunner.tcl script to run them in multiple cores
# concurrently.
testrunner:	testfixture.exe
	.\testfixture.exe $(TOP)\test\testrunner.tcl

smoketest:	$(TESTPROGS)
	@set PATH=$(LIBTCLPATH);$(PATH)
	.\testfixture.exe $(TOP)\test\main.test $(TESTOPTS)

shelltest: $(TESTPROGS)
	.\testfixture.exe $(TOP)\test\permutations.test shell

sqlite3_analyzer.c:	$(SQLITE3C) $(SQLITE3H) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqlite3_analyzer.c.in $(SQLITE_TCL_DEP)
	$(TCLSH_CMD) $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqlite3_analyzer.c.in > $@

sqlite3_analyzer.exe:	sqlite3_analyzer.c $(LIBRESOBJS)
	$(LTLINK) $(NO_WARN) -DBUILD_sqlite -I$(TCLINCDIR) sqlite3_analyzer.c \
		/link $(LDFLAGS) $(LTLINKOPTS) $(TCLLIBPATHS) $(LTLIBPATHS) $(LIBRESOBJS) $(TCLLIBS) $(LTLIBS) $(TLIBS)

2489
2490
2491
2492
2493
2494
2495











2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507

2508
2509
2510
2511
2512
2513
2514
2515
2516
2517

2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531

2532
2533
2534
2535
2536
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620

2621
2622
2623
2624
2625
2626







+
+
+
+
+
+
+
+
+
+
+












+










+













-
+





	$(LTLINK) $(NO_WARN) $(KV_COMPILE_OPTS) \
		$(TOP)\test\kvtest.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)

rbu.exe:	$(TOP)\ext\rbu\rbu.c $(TOP)\ext\rbu\sqlite3rbu.c $(SQLITE3C) $(SQLITE3H)
	$(LTLINK) $(NO_WARN) -DSQLITE_ENABLE_RBU \
		$(TOP)\ext\rbu\rbu.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)

THREADTEST3_SRC = \
  $(TOP)\test\threadtest3.c \
  $(TOP)\test\tt3_checkpoint.c \
  $(TOP)\test\tt3_index.c \
  $(TOP)\test\tt3_vacuum.c \
  $(TOP)\test\tt3_stress.c \
  $(TOP)\test\tt3_lookaside1.c

threadtest3.exe: $(THREADTEST3_SRC) $(TOP)\src\test_multiplex.c $(SQLITE3C) $(SQLITE3H)
	$(LTLINK) $(NO_WARN) $(TOP)\test\threadtest3.c $(TOP)\src\test_multiplex.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)

LSMDIR=$(TOP)\ext\lsm1
!INCLUDE $(LSMDIR)\Makefile.msc

moreclean:	clean
	del /Q $(SQLITE3C) $(SQLITE3H) 2>NUL
# <</mark>>

clean:
	del /Q *.exp *.lo *.ilk *.lib *.obj *.ncb *.pdb *.sdf *.suo 2>NUL
	del /Q *.bsc *.def *.cod *.da *.bb *.bbg *.vc gmon.out 2>NUL
	del /Q $(SQLITE3EXE) $(SQLITE3DLL) Replace.exe 2>NUL
# <<mark>>
	del /Q $(SQLITE3TCLDLL) pkgIndex.tcl 2>NUL
	del /Q opcodes.c opcodes.h 2>NUL
	del /Q lemon.* lempar.c parse.* 2>NUL
	del /Q mksourceid.* mkkeywordhash.* keywordhash.h 2>NUL
	del /Q notasharedlib.* 2>NUL
	-rmdir /Q/S .deps 2>NUL
	-rmdir /Q/S .libs 2>NUL
	-rmdir /Q/S tsrc 2>NUL
	del /Q .target_source 2>NUL
	del /Q tclsqlite3.exe $(SQLITETCLH) $(SQLITETCLDECLSH) 2>NUL
	del /Q lsm.dll lsmtest.exe 2>NUL
	del /Q atrc.exe changesetfuzz.exe dbtotxt.exe index_usage.exe 2>NUL
	del /Q testloadext.dll 2>NUL
	del /Q testfixture.exe test.db 2>NUL
	del /Q LogEst.exe fts3view.exe rollback-test.exe showdb.exe dbdump.exe 2>NUL
	del /Q changeset.exe 2>NUL
	del /Q showjournal.exe showstat4.exe showwal.exe speedtest1.exe 2>NUL
	del /Q mptester.exe wordcount.exe rbu.exe srcck1.exe 2>NUL
	del /Q sqlite3.c sqlite3-*.c sqlite3.h 2>NUL
	del /Q sqlite3rc.h 2>NUL
	del /Q shell.c sqlite3ext.h sqlite3session.h 2>NUL
	del /Q sqlite3_analyzer.exe sqlite3_analyzer.c 2>NUL
	del /Q sqlite-*-output.vsix 2>NUL
	del /Q fuzzershell.exe fuzzcheck.exe sqldiff.exe dbhash.exe 2>NUL
	del /Q sqltclsh.* 2>NUL
	del /Q dbfuzz.exe sessionfuzz.exe 2>NUL
	del /Q dbfuzz.exe sessionfuzz.exe threadtest3.exe 2>NUL
	del /Q kvtest.exe ossshell.exe scrub.exe 2>NUL
	del /Q showshm.exe sqlite3_checker.* sqlite3_expert.exe 2>NUL
	del /Q fts5.* fts5parse.* 2>NUL
	del /Q lsm.h lsm1.c 2>NUL
# <</mark>>

Changes to README.md.

1
2
3
4


5
6
7

8
9
10
11


















12
13
14
15
16
17
18
19
20
21

22
23
24
25
26
27
28
29
30
31
32

33
34
35
36
37
38

39
40
41
42

43
44
45
46

47
48
49
50



51
52

53
54
55
56
57
58
59

60
61
62
63
64
65
66
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


-
-
+
+



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



-
-
-



-
+










-
+





-
+



-
+



-
+

-
-
-
+
+
+

-
+






-
+







<h1 align="center">SQLite Source Repository</h1>

This repository contains the complete source code for the 
[SQLite database engine](https://sqlite.org/).  Some test scripts 
This repository contains the complete source code for the
[SQLite database engine](https://sqlite.org/).  Some test scripts
are also included.  However, many other test scripts
and most of the documentation are managed separately.

## Version Control
SQLite [does not use Git](https://sqlite.org/whynotgit.html).
If you are reading this on GitHub, then you are looking at an
unofficial mirror. See <https://sqlite.org/src> for the official
repository.

SQLite sources are managed using the
[Fossil](https://www.fossil-scm.org/), a distributed version control system
that was specifically designed and written to support SQLite development.
The [Fossil repository](https://sqlite.org/src/timeline) contains the urtext.

If you are reading this on GitHub or some other Git repository or service,
then you are looking at a mirror.  The names of check-ins and
other artifacts in a Git mirror are different from the official
names for those objects.  The official names for check-ins are
found in a footer on the check-in comment for authorized mirrors.
The official check-in name can also be seen in the `manifest.uuid` file
in the root of the tree.  Always use the official name, not  the
Git-name, when communicating about an SQLite check-in.

If you pulled your SQLite source code from a secondary source and want to
verify its integrity, there are hints on how to do that in the
[Verifying Code Authenticity](#vauth) section below.

## Obtaining The Code

SQLite sources are managed using the
[Fossil](https://www.fossil-scm.org/), a distributed version control system
that was specifically designed to support SQLite development.
If you do not want to use Fossil, you can download tarballs or ZIP
archives or [SQLite archives](https://sqlite.org/cli.html#sqlar) as follows:

  *  Lastest trunk check-in as
  *  Latest trunk check-in as
     [Tarball](https://www.sqlite.org/src/tarball/sqlite.tar.gz),
     [ZIP-archive](https://www.sqlite.org/src/zip/sqlite.zip), or
     [SQLite-archive](https://www.sqlite.org/src/sqlar/sqlite.sqlar).

  *  Latest release as
     [Tarball](https://www.sqlite.org/src/tarball/sqlite.tar.gz?r=release),
     [ZIP-archive](https://www.sqlite.org/src/zip/sqlite.zip?r=release), or
     [SQLite-archive](https://www.sqlite.org/src/sqlar/sqlite.sqlar?r=release).

  *  For other check-ins, substitute an appropriate branch name or
     tag or hash prefix for "release" in the URLs of the previous
     tag or hash prefix in place of "release" in the URLs of the previous
     bullet.  Or browse the [timeline](https://www.sqlite.org/src/timeline)
     to locate the check-in desired, click on its information page link,
     then click on the "Tarball" or "ZIP Archive" links on the information
     page.

If you do want to use Fossil to check out the source tree, 
If you do want to use Fossil to check out the source tree,
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 
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:
update to the latest 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.

## Compiling
## Compiling for Unix-like systems

First create a directory in which to place
the build products.  It is recommended, but not required, that the
build directory be separate from the source directory.  Cd into the
build directory and then from the build directory run the configure
script found at the root of the source tree.  Then run "make".

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







-
+






-
+



-
-
-
-
-
+
+
+
+
+








The configure script uses autoconf 2.61 and libtool.  If the configure
script does not work out for you, there is a generic makefile named
"Makefile.linux-gcc" in the top directory of the source tree that you
can copy and edit to suit your needs.  Comments on the generic makefile
show what changes are needed.

## Using MSVC
## Using MSVC for Windows systems

On Windows, all applicable build products can be compiled with MSVC.
First open the command prompt window associated with the desired compiler
version (e.g. "Developer Command Prompt for VS2013").  Next, use NMAKE
with the provided "Makefile.msc" to build one of the supported targets.

For example:
For example, from the parent directory of the source subtree named "sqlite":

        mkdir bld
        cd bld
        nmake /f Makefile.msc TOP=..\sqlite
        nmake /f Makefile.msc sqlite3.c TOP=..\sqlite
        nmake /f Makefile.msc sqlite3.dll TOP=..\sqlite
        nmake /f Makefile.msc sqlite3.exe TOP=..\sqlite
        nmake /f Makefile.msc test TOP=..\sqlite
        nmake /f ..\sqlite\Makefile.msc TOP=..\sqlite
        nmake /f ..\sqlite\Makefile.msc sqlite3.c TOP=..\sqlite
        nmake /f ..\sqlite\Makefile.msc sqlite3.dll TOP=..\sqlite
        nmake /f ..\sqlite\Makefile.msc sqlite3.exe TOP=..\sqlite
        nmake /f ..\sqlite\Makefile.msc test TOP=..\sqlite

There are several build options that can be set via the NMAKE command
line.  For example, to build for WinRT, simply add "FOR_WINRT=1" argument
to the "sqlite3.dll" command line above.  When debugging into the SQLite
code, adding the "DEBUG=1" argument to one of the above command lines is
recommended.

120
121
122
123
124
125
126
127

128
129
130
131
132
133
134
132
133
134
135
136
137
138

139
140
141
142
143
144
145
146







-
+







[command-line shell](https://sqlite.org/cli.html) and
the "tclsqlite.c" file which implements the
[Tcl bindings](https://sqlite.org/tclsqlite.html) for SQLite.
(Historical note:  SQLite began as a Tcl
extension and only later escaped to the wild as an independent library.)

Test scripts and programs are found in the **test/** subdirectory.
Addtional test code is found in other source repositories.
Additional test code is found in other source repositories.
See [How SQLite Is Tested](http://www.sqlite.org/testing.html) for
additional information.

The **ext/** subdirectory contains code for extensions.  The
Full-text search engine is in **ext/fts3**.  The R-Tree engine is in
**ext/rtree**.  The **ext/misc** subdirectory contains a number of
smaller, single-file extensions, such as a REGEXP operator.
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
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







-
+




-

-
+
-
-



-
+







and is used to generate the SQLITE\_SOURCE\_ID macro.  The VERSION file
contains the current SQLite version number.  The sqlite3.h header is really
just a copy of src/sqlite.h.in with the source-id and version number inserted
at just the right spots. Note that comment text in the sqlite3.h file is
used to generate much of the SQLite API documentation.  The Tcl scripts
used to generate that documentation are in a separate source repository.

The SQL language parser is **parse.c** which is generate from a grammar in
The SQL language parser is **parse.c** which is generated from a grammar in
the src/parse.y file.  The conversion of "parse.y" into "parse.c" is done
by the [lemon](./doc/lemon.html) LALR(1) parser generator.  The source code
for lemon is at tool/lemon.c.  Lemon uses the tool/lempar.c file as a
template for generating its parser.

Lemon also generates the **parse.h** header file, at the same time it
generates parse.c. But the parse.h header file is
generates parse.c.
modified further (to add additional symbols) using the ./addopcodes.tcl
Tcl script.

The **opcodes.h** header file contains macros that define the numbers
corresponding to opcodes in the "VDBE" virtual machine.  The opcodes.h
file is generated by the scanning the src/vdbe.c source file.  The
file is generated by scanning the src/vdbe.c source file.  The
Tcl script at ./mkopcodeh.tcl does this scan and generates opcodes.h.
A second Tcl script, ./mkopcodec.tcl, then scans opcodes.h to generate
the **opcodes.c** source file, which contains a reverse mapping from
opcode-number to opcode-name that is used for EXPLAIN output.

The **keywordhash.h** header file contains the definition of a hash table
that maps SQL language keywords (ex: "CREATE", "SELECT", "INDEX", etc.) into
224
225
226
227
228
229
230
231

232
233
234
235
236
237
238
233
234
235
236
237
238
239

240
241
242
243
244
245
246
247







-
+







(helping to understand how SQLite works include the
[file format](http://www.sqlite.org/fileformat2.html) description,
the [virtual machine](http://www.sqlite.org/opcode.html) that runs
prepared statements, the description of
[how transactions work](http://www.sqlite.org/atomiccommit.html), and
the [overview of the query planner](http://www.sqlite.org/optoverview.html).

Years of effort have gone into optimizating SQLite, both
Years of effort have gone into optimizing SQLite, both
for small size and high performance.  And optimizations tend to result in
complex code.  So there is a lot of complexity in the current SQLite
implementation.  It will not be the easiest library in the world to hack.

Key files:

  *  **sqlite.h.in** - This file defines the public interface to the SQLite
281
282
283
284
285
286
287
288

289
290
291
292

293
294
295
296

















297
298
299
300

301
302
303
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







-
+



-
+




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



-
+



     is not part of the core SQLite library.  But as most of the tests in this
     repository are written in Tcl, the Tcl language bindings are important.

  *  **test*.c** - Files in the src/ folder that begin with "test" go into
     building the "testfixture.exe" program.  The testfixture.exe program is
     an enhanced Tcl shell.  The testfixture.exe program runs scripts in the
     test/ folder to validate the core SQLite code.  The testfixture program
     (and some other test programs too) is build and run when you type
     (and some other test programs too) is built and run when you type
     "make test".

  *  **ext/misc/json1.c** - This file implements the various JSON functions
     that are build into SQLite.
     that are built into SQLite.

There are many other source files.  Each has a succinct header comment that
describes its purpose and role within the larger system.

<a name="vauth"></a>
## Verifying Code Authenticity

The `manifest` file at the root directory of the source tree
contains either a SHA3-256 hash (for newer files) or a SHA1 hash (for
older files) for every source file in the repository.
The name of the version of the entire source tree is just the
SHA3-256 hash of the `manifest` file itself, possibly with the
last line of that file omitted if the last line begins with
"`# Remove this line`".
The `manifest.uuid` file should contain the SHA3-256 hash of the
`manifest` file. If all of the above hash comparisons are correct, then
you can be confident that your source tree is authentic and unadulterated.

The format of the `manifest` file should be mostly self-explanatory, but
if you want details, they are available
[here](https://fossil-scm.org/fossil/doc/trunk/www/fileformat.wiki#manifest).

## Contacts

The main SQLite webpage is [http://www.sqlite.org/](http://www.sqlite.org/)
The main SQLite website is [http://www.sqlite.org/](http://www.sqlite.org/)
with geographically distributed backups at
[http://www2.sqlite.org/](http://www2.sqlite.org) and
[http://www3.sqlite.org/](http://www3.sqlite.org).

Changes to VERSION.

1


1
-
+
3.27.0
3.41.0

Changes to autoconf/Makefile.am.

9
10
11
12
13
14
15
16

17
18
19
20
9
10
11
12
13
14
15

16
17
18
19
20







-
+




EXTRA_sqlite3_SOURCES = sqlite3.c
sqlite3_LDADD = @EXTRA_SHELL_OBJ@ @READLINE_LIBS@
sqlite3_DEPENDENCIES = @EXTRA_SHELL_OBJ@
sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_ENABLE_STMTVTAB -DSQLITE_ENABLE_DBSTAT_VTAB $(SHELL_CFLAGS)

include_HEADERS = sqlite3.h sqlite3ext.h

EXTRA_DIST = sqlite3.1 tea Makefile.msc sqlite3.rc README.txt Replace.cs Makefile.fallback
EXTRA_DIST = sqlite3.1 tea Makefile.msc sqlite3.rc sqlite3rc.h README.txt Replace.cs Makefile.fallback
pkgconfigdir = ${libdir}/pkgconfig
pkgconfig_DATA = sqlite3.pc

man_MANS = sqlite3.1

Changes to autoconf/Makefile.msc.

69
70
71
72
73
74
75
76

77
78
79
80
81
82
83
69
70
71
72
73
74
75

76
77
78
79
80
81
82
83







-
+







# If necessary, create a list of harmless compiler warnings to disable when
# compiling the various tools.  For the SQLite source code itself, warnings,
# if any, will be disabled from within it.
#
!IFNDEF NO_WARN
!IF $(USE_FULLWARN)!=0
NO_WARN = -wd4054 -wd4055 -wd4100 -wd4127 -wd4130 -wd4152 -wd4189 -wd4206
NO_WARN = $(NO_WARN) -wd4210 -wd4232 -wd4305 -wd4306 -wd4702 -wd4706
NO_WARN = $(NO_WARN) -wd4210 -wd4232 -wd4244 -wd4305 -wd4306 -wd4702 -wd4706
!ENDIF
!ENDIF

# Set this non-0 to use the library paths and other options necessary for
# Windows Phone 8.1.
#
!IFNDEF USE_WP81_OPTS
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
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







+














+
+
+
+
+
+







# 4 == SQLITE_WIN32_MALLOC_VALIDATE: Validate the Win32 native heap per call.
# 5 == SQLITE_DEBUG_OS_TRACE: Enables output from the OSTRACE() macros.
# 6 == SQLITE_ENABLE_IOTRACE: Enables output from the IOTRACE() macros.
#
!IFNDEF DEBUG
DEBUG = 0
!ENDIF


# Enable use of available compiler optimizations?  Normally, this should be
# non-zero.  Setting this to zero, thus disabling all compiler optimizations,
# can be useful for testing.
#
!IFNDEF OPTIMIZATIONS
OPTIMIZATIONS = 2
!ENDIF

# Set this to non-0 to enable support for the session extension.
#
!IFNDEF SESSION
SESSION = 0
!ENDIF

# Set this to non-0 to enable support for the rbu extension.
#
!IFNDEF RBU
RBU = 0
!ENDIF

# Set the source code file to be used by executables and libraries when
# they need the amalgamation.
#
!IFNDEF SQLITE3C
!IF $(SPLIT_AMALGAMATION)!=0
SQLITE3C = sqlite3-all.c
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
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







-



-
+
-











+
+
+
+
+
+
+
+
+
+







# the Windows platform.
#
!IFNDEF OPT_FEATURE_FLAGS
!IF $(MINIMAL_AMALGAMATION)==0
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_GEOPOLY=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_JSON1=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBSTAT_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_INTROSPECTION_PRAGMAS=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DESERIALIZE=1
!ENDIF
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
!ENDIF

# Should the session extension be enabled?  If so, add compilation options
# to enable it.
#
!IF $(SESSION)!=0
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_SESSION=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_PREUPDATE_HOOK=1
!ENDIF

# Always enable math functions on Windows
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_MATH_FUNCTIONS

# Should the rbu extension be enabled?  If so, add compilation options
# to enable it.
#
!IF $(RBU)!=0
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RBU=1
!ENDIF

# These are the "extended" SQLite compilation options used when compiling for
# the Windows 10 platform.
#
!IFNDEF EXT_FEATURE_FLAGS
!IF $(FOR_WIN10)!=0
EXT_FEATURE_FLAGS = $(EXT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS4=1
429
430
431
432
433
434
435
436

437
438

439
440
441
442
443
444
445
444
445
446
447
448
449
450

451
452

453
454
455
456
457
458
459
460







-
+

-
+








UCRTLIBPATH = $(UCRTLIBPATH:\\=\)

# C compiler and options for use in building executables that
# will run on the platform that is doing the build.
#
!IF $(USE_FULLWARN)!=0
BCC = $(NCC) -nologo -W4 $(CCOPTS) $(BCCOPTS)
BCC = $(NCC) -nologo -W4 -Fd$*.pdb $(CCOPTS) $(BCCOPTS)
!ELSE
BCC = $(NCC) -nologo -W3 $(CCOPTS) $(BCCOPTS)
BCC = $(NCC) -nologo -W3 -Fd$*.pdb $(CCOPTS) $(BCCOPTS)
!ENDIF

# Check if assembly code listings should be generated for the source
# code files to be compiled.
#
!IF $(USE_LISTINGS)!=0
BCC = $(BCC) -FAcs
482
483
484
485
486
487
488
489
490


491
492
493
494


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


504
505
506
507


508
509
510
511
512
513
514
515
516







-
-
+
+


-
-
+
+







# also be noted here that building any target with these "stdcall" options
# will most likely fail if the Tcl library is also required.  This is due
# to how the Tcl library functions are declared and exported (i.e. without
# an explicit calling convention, which results in "cdecl").
#
!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
!IF "$(PLATFORM)"=="x86"
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
CORE_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
SHELL_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
!ELSE
!IFNDEF PLATFORM
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
CORE_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
SHELL_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
!ELSE
CORE_CCONV_OPTS =
SHELL_CCONV_OPTS =
!ENDIF
!ENDIF
!ELSE
CORE_CCONV_OPTS =
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
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







-
+

















+
+
+
+
+







BCC = $(BCC) -Zi
!ENDIF


# Command line prefixes for compiling code, compiling resources,
# linking, etc.
#
LTCOMPILE = $(TCC) -Fo$@
LTCOMPILE = $(TCC) -Fo$@ -Fd$*.pdb
LTRCOMPILE = $(RCC) -r
LTLIB = lib.exe
LTLINK = $(TCC) -Fe$@

# If requested, link to the RPCRT4 library.
#
!IF $(USE_RPCRT4_LIB)!=0
LTLIBS = $(LTLIBS) rpcrt4.lib
!ENDIF

# If a platform was set, force the linker to target that.
# Note that the vcvars*.bat family of batch files typically
# set this for you.  Otherwise, the linker will attempt
# to deduce the binary type based on the object files.
!IFDEF PLATFORM
LTLINKOPTS = /NOLOGO /MACHINE:$(PLATFORM)
LTLIBOPTS = /NOLOGO /MACHINE:$(PLATFORM)
!ELSEIF "$(VISUALSTUDIOVERSION)"=="12.0" || \
        "$(VISUALSTUDIOVERSION)"=="14.0" || \
        "$(VISUALSTUDIOVERSION)"=="15.0"
LTLINKOPTS = /NOLOGO /MACHINE:x86
LTLIBOPTS = /NOLOGO /MACHINE:x86
!ELSE
LTLINKOPTS = /NOLOGO
LTLIBOPTS = /NOLOGO
!ENDIF

# When compiling for use in the WinRT environment, the following
# linker option must be used to mark the executable as runnable
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
954
955
956
957
958
959
960

961
962
963
964
965
966
967







-







# Additional compiler options for the shell.  These are only effective
# when the shell is not being dynamically linked.
#
!IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_FTS4=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DESERIALIZE=1
!ENDIF


# This is the default Makefile target.  The objects listed here
# are what get build when you type just "make" with no arguments.
#
core:	dll shell
969
970
971
972
973
974
975
976

977
978
979
980
981
982
983
988
989
990
991
992
993
994

995
996
997
998
999
1000
1001
1002







-
+








Replace.exe:
	$(CSC) /target:exe $(TOP)\Replace.cs

sqlite3.def:	Replace.exe $(LIBOBJ)
	echo EXPORTS > sqlite3.def
	dumpbin /all $(LIBOBJ) \
		| .\Replace.exe "^\s+/EXPORT:_?(sqlite3(?:session|changeset|changegroup|rebaser)?_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \
		| .\Replace.exe "^\s+/EXPORT:_?(sqlite3(?:session|changeset|changegroup|rebaser|rbu)?_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \
		| sort >> sqlite3.def

$(SQLITE3EXE):	shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H)
	$(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) shell.c $(SHELL_CORE_SRC) \
		/link $(SQLITE3EXEPDB) $(LDFLAGS) $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)


Changes to autoconf/README.txt.

101
102
103
104
105
106
107
108

109
110
111
112
113
101
102
103
104
105
106
107

108
109
110
111
112
113







-
+






Additionally, preprocessor defines may be specified by using the OPTS macro
on the NMAKE command line.  However, not all possible preprocessor defines
may be specified in this manner as some require the amalgamation to be built
with them enabled (see http://www.sqlite.org/compile.html). For example, the
following will work:

  "OPTS=-DSQLITE_ENABLE_STAT4=1 -DSQLITE_ENABLE_JSON1=1"
  "OPTS=-DSQLITE_ENABLE_STAT4=1 -DSQLITE_OMIT_JSON=1"

However, the following will not compile unless the amalgamation was built
with it enabled:

  "OPTS=-DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1"

Changes to autoconf/configure.ac.

83
84
85
86
87
88
89
90



91
92
93
94
95
96
97
83
84
85
86
87
88
89

90
91
92
93
94
95
96
97
98
99







-
+
+
+








#-----------------------------------------------------------------------
#   --enable-threadsafe
#
AC_ARG_ENABLE(threadsafe, [AS_HELP_STRING(
  [--enable-threadsafe], [build a thread-safe library [default=yes]])], 
  [], [enable_threadsafe=yes])
if test x"$enable_threadsafe" != "xno"; then
if test x"$enable_threadsafe" == "xno"; then
  BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_THREADSAFE=0"
else
  BUILD_CFLAGS="$BUILD_CFLAGS -D_REENTRANT=1 -DSQLITE_THREADSAFE=1"
  AC_SEARCH_LIBS(pthread_create, pthread)
  AC_SEARCH_LIBS(pthread_mutexattr_init, pthread)
fi
#-----------------------------------------------------------------------

#-----------------------------------------------------------------------
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
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







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






+


+
+
+









+


+
+
+









+

+


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









+

-
+
+
+
+









+


+
+
+









+



+
+
+







else
  BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_OMIT_LOAD_EXTENSION=1"
fi
AC_MSG_CHECKING([for whether to support dynamic extensions])
AC_MSG_RESULT($enable_dynamic_extensions)
#-----------------------------------------------------------------------

#-----------------------------------------------------------------------
#   --enable-math
#
AC_ARG_ENABLE(math, [AS_HELP_STRING(
  [--enable-math], [SQL math functions [default=yes]])],
  [], [enable_math=yes])
AC_MSG_CHECKING([SQL math functions])
if test x"$enable_math" = "xyes"; then
  BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_MATH_FUNCTIONS"
  AC_MSG_RESULT([enabled])
  AC_SEARCH_LIBS(ceil, m)
else
  AC_MSG_RESULT([disabled])
fi
#-----------------------------------------------------------------------

#-----------------------------------------------------------------------
#   --enable-fts4
#
AC_ARG_ENABLE(fts4, [AS_HELP_STRING(
  [--enable-fts4], [include fts4 support [default=yes]])], 
  [], [enable_fts4=yes])
AC_MSG_CHECKING([FTS4 extension])
if test x"$enable_fts4" = "xyes"; then
  BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_FTS4"
  AC_MSG_RESULT([enabled])
else
  AC_MSG_RESULT([disabled])
fi
#-----------------------------------------------------------------------

#-----------------------------------------------------------------------
#   --enable-fts3
#
AC_ARG_ENABLE(fts3, [AS_HELP_STRING(
  [--enable-fts3], [include fts3 support [default=no]])], 
  [], [])
AC_MSG_CHECKING([FTS3 extension])
if test x"$enable_fts3" = "xyes" -a x"$enable_fts4" = "xno"; then
  BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_FTS3"
  AC_MSG_RESULT([enabled])
else
  AC_MSG_RESULT([disabled])
fi
#-----------------------------------------------------------------------

#-----------------------------------------------------------------------
#   --enable-fts5
#
AC_ARG_ENABLE(fts5, [AS_HELP_STRING(
  [--enable-fts5], [include fts5 support [default=yes]])], 
  [], [enable_fts5=yes])
AC_MSG_CHECKING([FTS5 extension])
if test x"$enable_fts5" = "xyes"; then
  AC_MSG_RESULT([enabled])
  AC_SEARCH_LIBS(log, m)
  BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_FTS5"
fi
#-----------------------------------------------------------------------

else
#-----------------------------------------------------------------------
#   --enable-json1
  AC_MSG_RESULT([disabled])
#
AC_ARG_ENABLE(json1, [AS_HELP_STRING(
  [--enable-json1], [include json1 support [default=yes]])], 
  [],[enable_json1=yes])
if test x"$enable_json1" = "xyes"; then
  BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_JSON1"
fi
#-----------------------------------------------------------------------

#-----------------------------------------------------------------------
#   --enable-rtree
#
AC_ARG_ENABLE(rtree, [AS_HELP_STRING(
  [--enable-rtree], [include rtree support [default=yes]])], 
  [], [enable_rtree=yes])
AC_MSG_CHECKING([RTREE extension])
if test x"$enable_rtree" = "xyes"; then
  BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_RTREE"
  BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_GEOPOLY"
  AC_MSG_RESULT([enabled])
else
  AC_MSG_RESULT([disabled])
fi
#-----------------------------------------------------------------------

#-----------------------------------------------------------------------
#   --enable-session
#
AC_ARG_ENABLE(session, [AS_HELP_STRING(
  [--enable-session], [enable the session extension [default=no]])], 
  [], [])
AC_MSG_CHECKING([Session extension])
if test x"$enable_session" = "xyes"; then
  BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK"
  AC_MSG_RESULT([enabled])
else
  AC_MSG_RESULT([disabled])
fi
#-----------------------------------------------------------------------

#-----------------------------------------------------------------------
#   --enable-debug
#
AC_ARG_ENABLE(debug, [AS_HELP_STRING(
  [--enable-debug], [build with debugging features enabled [default=no]])], 
  [], [])
AC_MSG_CHECKING([Build type])
if test x"$enable_debug" = "xyes"; then
  BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_DEBUG -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE"
  CFLAGS="-g -O0"
  AC_MSG_RESULT([debug])
else
  AC_MSG_RESULT([release])
fi
#-----------------------------------------------------------------------

#-----------------------------------------------------------------------
#   --enable-static-shell
#
AC_ARG_ENABLE(static-shell, [AS_HELP_STRING(

Changes to autoconf/tea/Makefile.in.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1
2
3
4
5
6
7
8
9
10
11
12
13


14
15
16
17
18
19
20













-
-







# Makefile.in --
#
#	This file is a Makefile for Sample TEA Extension.  If it has the name
#	"Makefile.in" then it is a template for a Makefile;  to generate the
#	actual Makefile, run "./configure", which is a configuration script
#	generated by the "autoconf" program (constructs like "@foo@" will get
#	replaced in the actual Makefile.
#
# Copyright (c) 1999 Scriptics Corporation.
# Copyright (c) 2002-2005 ActiveState Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: Makefile.in,v 1.59 2005/07/26 19:17:02 mdejong Exp $

#========================================================================
# Add additional lines to handle any additional AC_SUBST cases that
# have been added in a customized configure script.
#========================================================================

#SAMPLE_NEW_VAR	= @SAMPLE_NEW_VAR@
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
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







+
+













+

+


-








-
+

+
-
-
+
+

+

+




+


-



-
-














-
-













-
-
+
+


-


-
+

+

-
+
-



-
+





-
+






+

+





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







-
+

















-








#========================================================================
# "PKG_LIB_FILE" refers to the library (dynamic or static as per
# configuration options) composed of the named objects.
#========================================================================

PKG_LIB_FILE	= @PKG_LIB_FILE@
PKG_LIB_FILE8	= @PKG_LIB_FILE8@
PKG_LIB_FILE9	= @PKG_LIB_FILE9@
PKG_STUB_LIB_FILE = @PKG_STUB_LIB_FILE@

lib_BINARIES	= $(PKG_LIB_FILE)
BINARIES	= $(lib_BINARIES)

SHELL		= @SHELL@

srcdir		= @srcdir@
prefix		= @prefix@
exec_prefix	= @exec_prefix@

bindir		= @bindir@
libdir		= @libdir@
includedir	= @includedir@
datarootdir	= @datarootdir@
runstatedir	= @runstatedir@
datadir		= @datadir@
mandir		= @mandir@
includedir	= @includedir@

DESTDIR		=

PKG_DIR		= $(PACKAGE_NAME)$(PACKAGE_VERSION)
pkgdatadir	= $(datadir)/$(PKG_DIR)
pkglibdir	= $(libdir)/$(PKG_DIR)
pkgincludedir	= $(includedir)/$(PKG_DIR)

top_builddir	= .
top_builddir	= @abs_top_builddir@

INSTALL_OPTIONS	=
INSTALL		= @INSTALL@
INSTALL_PROGRAM	= @INSTALL_PROGRAM@
INSTALL		= @INSTALL@ $(INSTALL_OPTIONS)
INSTALL_DATA_DIR = @INSTALL_DATA_DIR@
INSTALL_DATA	= @INSTALL_DATA@
INSTALL_PROGRAM	= @INSTALL_PROGRAM@
INSTALL_SCRIPT	= @INSTALL_SCRIPT@
INSTALL_LIBRARY	= @INSTALL_LIBRARY@

PACKAGE_NAME	= @PACKAGE_NAME@
PACKAGE_VERSION	= @PACKAGE_VERSION@
CC		= @CC@
CCLD		= @CCLD@
CFLAGS_DEFAULT	= @CFLAGS_DEFAULT@
CFLAGS_WARNING	= @CFLAGS_WARNING@
CLEANFILES	= @CLEANFILES@
EXEEXT		= @EXEEXT@
LDFLAGS_DEFAULT	= @LDFLAGS_DEFAULT@
MAKE_LIB	= @MAKE_LIB@
MAKE_SHARED_LIB	= @MAKE_SHARED_LIB@
MAKE_STATIC_LIB	= @MAKE_STATIC_LIB@
MAKE_STUB_LIB	= @MAKE_STUB_LIB@
OBJEXT		= @OBJEXT@
RANLIB		= @RANLIB@
RANLIB_STUB	= @RANLIB_STUB@
SHLIB_CFLAGS	= @SHLIB_CFLAGS@
SHLIB_LD	= @SHLIB_LD@
SHLIB_LD_LIBS	= @SHLIB_LD_LIBS@
STLIB_LD	= @STLIB_LD@
#TCL_DEFS	= @TCL_DEFS@
TCL_BIN_DIR	= @TCL_BIN_DIR@
TCL_SRC_DIR	= @TCL_SRC_DIR@
#TK_BIN_DIR	= @TK_BIN_DIR@
#TK_SRC_DIR	= @TK_SRC_DIR@

# This is no longer necessary even for packages that use private Tcl headers
#TCL_TOP_DIR_NATIVE	= @TCL_TOP_DIR_NATIVE@
# Not used, but retained for reference of what libs Tcl required
#TCL_LIBS	= @TCL_LIBS@

#========================================================================
# TCLLIBPATH seeds the auto_path in Tcl's init.tcl so we can test our
# package without installing.  The other environment variables allow us
# to test against an uninstalled Tcl.  Add special env vars that you
# require for testing here (like TCLX_LIBRARY).
#========================================================================

EXTRA_PATH	= $(top_builddir):$(TCL_BIN_DIR)
#EXTRA_PATH	= $(top_builddir):$(TCL_BIN_DIR):$(TK_BIN_DIR)
TCLLIBPATH	= $(top_builddir)
TCLSH_ENV	= TCL_LIBRARY=`@CYGPATH@ $(TCL_SRC_DIR)/library` \
		  @LD_LIBRARY_PATH_VAR@="$(EXTRA_PATH):$(@LD_LIBRARY_PATH_VAR@)" \
TCLSH_ENV	= TCL_LIBRARY=`@CYGPATH@ $(TCL_SRC_DIR)/library`
PKG_ENV		= @LD_LIBRARY_PATH_VAR@="$(EXTRA_PATH):$(@LD_LIBRARY_PATH_VAR@)" \
		  PATH="$(EXTRA_PATH):$(PATH)" \
		  TCLLIBPATH="$(TCLLIBPATH)"
#		  TK_LIBRARY=`@CYGPATH@ $(TK_SRC_DIR)/library`

TCLSH_PROG	= @TCLSH_PROG@
TCLSH	= $(TCLSH_ENV) $(TCLSH_PROG)
TCLSH		= $(TCLSH_ENV) $(PKG_ENV) $(TCLSH_PROG)

#WISH_ENV	= TK_LIBRARY=`@CYGPATH@ $(TK_SRC_DIR)/library`
#WISH_PROG	= @WISH_PROG@
#WISH	= $(TCLSH_ENV) $(WISH_PROG)
#WISH		= $(TCLSH_ENV) $(WISH_ENV) $(PKG_ENV) $(WISH_PROG)


SHARED_BUILD	= @SHARED_BUILD@

INCLUDES	= @PKG_INCLUDES@ @TCL_INCLUDES@ -I$(srcdir)/..
INCLUDES	= @PKG_INCLUDES@ @TCL_INCLUDES@ -I. -I$(srcdir)/..
#INCLUDES	= @PKG_INCLUDES@ @TCL_INCLUDES@ @TK_INCLUDES@ @TK_XINCLUDES@

PKG_CFLAGS	= @PKG_CFLAGS@

# TCL_DEFS is not strictly need here, but if you remove it, then you
# must make sure that configure.in checks for the necessary components
# must make sure that configure.ac checks for the necessary components
# that your library may use.  TCL_DEFS can actually be a problem if
# you do not compile with a similar machine setup as the Tcl core was
# compiled with.
#DEFS		= $(TCL_DEFS) @DEFS@ $(PKG_CFLAGS)
DEFS		= @DEFS@ $(PKG_CFLAGS)

# Move pkgIndex.tcl to 'BINARIES' var if it is generated in the Makefile
CONFIG_CLEAN_FILES = Makefile pkgIndex.tcl
CLEANFILES	= @CLEANFILES@

CPPFLAGS	= @CPPFLAGS@
LIBS		= @PKG_LIBS@ @LIBS@
AR		= @AR@
CFLAGS		= @CFLAGS@
LDFLAGS		= @LDFLAGS@
LDFLAGS_DEFAULT			= @LDFLAGS_DEFAULT@
COMPILE		= $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
COMPILE		= $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) \
			  $(CFLAGS_DEFAULT) $(CFLAGS_WARNING) $(SHLIB_CFLAGS) $(CFLAGS)

GDB		= gdb
VALGRIND	= valgrind
VALGRINDARGS	= --tool=memcheck --num-callers=8 --leak-resolution=high \
		  --leak-check=yes --show-reachable=yes -v

.SUFFIXES: .c .$(OBJEXT)

#========================================================================
# Start of user-definable TARGETS section
#========================================================================

#========================================================================
# TEA TARGETS.  Please note that the "libraries:" target refers to platform
# independent files, and the "binaries:" target inclues executable programs and
# independent files, and the "binaries:" target includes executable programs and
# platform-dependent libraries.  Modify these targets so that they install
# the various pieces of your package.  The make and install rules
# for the BINARIES that you specified above have already been done.
#========================================================================

all: binaries libraries doc

#========================================================================
# The binaries target builds executable programs, Windows .dll's, unix
# shared/static libraries, and any other platform-dependent files.
# The list of targets to build for "binaries:" is specified at the top
# of the Makefile, in the "BINARIES" variable.
#========================================================================

binaries: $(BINARIES)

libraries:


#========================================================================
# Your doc target should differentiate from doc builds (by the developer)
# and doc installs (see install-doc), which just install the docs on the
# end user machine when building from source.
#========================================================================

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







-
+



-
+








-
+



-
+
-









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








#========================================================================
# This rule installs platform-independent files, such as header files.
# The list=...; for p in $$list handles the empty list case x-platform.
#========================================================================

install-libraries: libraries
	@mkdir -p $(DESTDIR)$(includedir)
	@$(INSTALL_DATA_DIR) "$(DESTDIR)$(includedir)"
	@echo "Installing header files in $(DESTDIR)$(includedir)"
	@list='$(PKG_HEADERS)'; for i in $$list; do \
	    echo "Installing $(srcdir)/$$i" ; \
	    $(INSTALL_DATA) $(srcdir)/$$i $(DESTDIR)$(includedir) ; \
	    $(INSTALL_DATA) $(srcdir)/$$i "$(DESTDIR)$(includedir)" ; \
	done;

#========================================================================
# Install documentation.  Unix manpages should go in the $(mandir)
# directory.
#========================================================================

install-doc: doc
	@mkdir -p $(DESTDIR)$(mandir)/mann
	@$(INSTALL_DATA_DIR) "$(DESTDIR)$(mandir)/mann"
	@echo "Installing documentation in $(DESTDIR)$(mandir)"
	@list='$(srcdir)/doc/*.n'; for i in $$list; do \
	    echo "Installing $$i"; \
	    rm -f $(DESTDIR)$(mandir)/mann/`basename $$i`; \
	    $(INSTALL_DATA) $$i "$(DESTDIR)$(mandir)/mann" ; \
	    $(INSTALL_DATA) $$i $(DESTDIR)$(mandir)/mann ; \
	done

test: binaries libraries
	@echo "SQLite TEA distribution does not include tests"

shell: binaries libraries
	@$(TCLSH) $(SCRIPT)

gdb:
	$(TCLSH_ENV) $(PKG_ENV) $(GDB) $(TCLSH_PROG) $(SCRIPT)

gdb-test: binaries libraries
	$(TCLSH_ENV) gdb $(TCLSH_PROG) $(SCRIPT)
	$(TCLSH_ENV) $(PKG_ENV) $(GDB) \
	    --args $(TCLSH_PROG) `@CYGPATH@ $(srcdir)/tests/all.tcl` \
	    $(TESTFLAGS) -singleproc 1 \
	    -load "package ifneeded $(PACKAGE_NAME) $(PACKAGE_VERSION) \
		[list load `@CYGPATH@ $(PKG_LIB_FILE)` [string totitle $(PACKAGE_NAME)]]"

valgrind: binaries libraries
	$(TCLSH_ENV) $(PKG_ENV) $(VALGRIND) $(VALGRINDARGS) $(TCLSH_PROG) \
	    `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS)

valgrindshell: binaries libraries
	$(TCLSH_ENV) $(PKG_ENV) $(VALGRIND) $(VALGRINDARGS) $(TCLSH_PROG) $(SCRIPT)

depend:

#========================================================================
# $(PKG_LIB_FILE) should be listed as part of the BINARIES variable
# mentioned above.  That will ensure that this target is built when you
# run "make binaries".
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
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







-
+



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







-
+



+
+
+



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

+
+
-
+
-
-
+
+
-
-

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

-
+


-
-
+
+











-
+


-
+







-
+













-
+


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





-
+








-
+




-
+












-
+



-
+



-
-






-
+



-
+


-
+



+




# 	$(COMPILE) -c `@CYGPATH@ $(srcdir)/generic/sample.c` -o $@
#
# Setting the VPATH variable to a list of paths will cause the makefile
# to look into these paths when resolving .c to .obj dependencies.
# As necessary, add $(srcdir):$(srcdir)/compat:....
#========================================================================

VPATH = $(srcdir):$(srcdir)/generic:$(srcdir)/unix:$(srcdir)/win
VPATH = $(srcdir):$(srcdir)/generic:$(srcdir)/unix:$(srcdir)/win:$(srcdir)/macosx

.c.@OBJEXT@:
	$(COMPILE) -c `@CYGPATH@ $<` -o $@

tclsample.@OBJEXT@:	sampleUuid.h

$(srcdir)/manifest.uuid:
	printf "git-" >$(srcdir)/manifest.uuid
	(cd $(srcdir); git rev-parse HEAD >>$(srcdir)/manifest.uuid || \
	    (printf "svn-r" >$(srcdir)/manifest.uuid ; \
	    svn info --show-item last-changed-revision >>$(srcdir)/manifest.uuid) || \
	    printf "unknown" >$(srcdir)/manifest.uuid)

sampleUuid.h:	$(srcdir)/manifest.uuid
	echo "#define SAMPLE_VERSION_UUID \\" >$@
	cat $(srcdir)/manifest.uuid >>$@
	echo "" >>$@

#========================================================================
# Distribution creation
# You may need to tweak this target to make it work correctly.
#========================================================================

#COMPRESS	= tar cvf $(PKG_DIR).tar $(PKG_DIR); compress $(PKG_DIR).tar
COMPRESS	= gtar zcvf $(PKG_DIR).tar.gz $(PKG_DIR)
COMPRESS	= tar zcvf $(PKG_DIR).tar.gz $(PKG_DIR)
DIST_ROOT	= /tmp/dist
DIST_DIR	= $(DIST_ROOT)/$(PKG_DIR)

DIST_INSTALL_DATA	= CPPROG='cp -p' $(INSTALL) -m 644
DIST_INSTALL_SCRIPT	= CPPROG='cp -p' $(INSTALL) -m 755

dist-clean:
	rm -rf $(DIST_DIR) $(DIST_ROOT)/$(PKG_DIR).tar.*

dist: dist-clean
	mkdir -p $(DIST_DIR)
	cp -p $(srcdir)/README* $(srcdir)/license* \
		$(srcdir)/aclocal.m4 $(srcdir)/configure $(srcdir)/*.in \
		$(DIST_DIR)/
dist: dist-clean $(srcdir)/manifest.uuid
	$(INSTALL_DATA_DIR) $(DIST_DIR)

	# TEA files
	$(DIST_INSTALL_DATA) $(srcdir)/Makefile.in \
	    $(srcdir)/aclocal.m4 $(srcdir)/configure.ac \
	    $(DIST_DIR)/
	chmod 664 $(DIST_DIR)/Makefile.in $(DIST_DIR)/aclocal.m4
	chmod 775 $(DIST_DIR)/configure $(DIST_DIR)/configure.in
	$(DIST_INSTALL_SCRIPT) $(srcdir)/configure $(DIST_DIR)/

	$(INSTALL_DATA_DIR) $(DIST_DIR)/tclconfig
	$(DIST_INSTALL_DATA) $(srcdir)/tclconfig/README.txt \
	for i in $(srcdir)/*.[ch]; do \
	    $(srcdir)/manifest.uuid \
	    if [ -f $$i ]; then \
		cp -p $$i $(DIST_DIR)/ ; \
	    $(srcdir)/tclconfig/tcl.m4 $(srcdir)/tclconfig/install-sh \
	    $(DIST_DIR)/tclconfig/
	    fi; \
	done;

	# Extension files
	mkdir $(DIST_DIR)/tclconfig
	cp $(srcdir)/tclconfig/install-sh $(srcdir)/tclconfig/tcl.m4 \
		$(DIST_DIR)/tclconfig/
	$(DIST_INSTALL_DATA) \
	    $(srcdir)/ChangeLog \
	    $(srcdir)/README.sha \
	    $(srcdir)/license.terms \
	    $(srcdir)/README \
	    $(srcdir)/pkgIndex.tcl.in \
	    $(DIST_DIR)/
	chmod 664 $(DIST_DIR)/tclconfig/tcl.m4
	chmod +x $(DIST_DIR)/tclconfig/install-sh

	list='demos doc generic library mac tests unix win'; \
	list='demos doc generic library macosx tests unix win'; \
	for p in $$list; do \
	    if test -d $(srcdir)/$$p ; then \
		mkdir $(DIST_DIR)/$$p; \
		cp -p $(srcdir)/$$p/*.* $(DIST_DIR)/$$p/; \
		$(INSTALL_DATA_DIR) $(DIST_DIR)/$$p; \
		$(DIST_INSTALL_DATA) $(srcdir)/$$p/* $(DIST_DIR)/$$p/; \
	    fi; \
	done

	(cd $(DIST_ROOT); $(COMPRESS);)

#========================================================================
# End of user-definable section
#========================================================================

#========================================================================
# Don't modify the file to clean here.  Instead, set the "CLEANFILES"
# variable in configure.in
# variable in configure.ac
#========================================================================

clean:  
clean:
	-test -z "$(BINARIES)" || rm -f $(BINARIES)
	-rm -f *.$(OBJEXT) core *.core
	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)

distclean: clean
	-rm -f *.tab.c
	-rm -f $(CONFIG_CLEAN_FILES)
	-rm -f config.h config.cache config.log config.status
	-rm -f config.cache config.log config.status

#========================================================================
# Install binary object libraries.  On Windows this includes both .dll and
# .lib files.  Because the .lib files are not explicitly listed anywhere,
# we need to deduce their existence from the .dll file of the same name.
# Library files go into the lib directory.
# In addition, this will generate the pkgIndex.tcl
# file in the install location (assuming it can find a usable tclsh shell)
#
# You should not have to modify this target.
#========================================================================

install-lib-binaries: binaries
	@mkdir -p $(DESTDIR)$(pkglibdir)
	@$(INSTALL_DATA_DIR) "$(DESTDIR)$(pkglibdir)"
	@list='$(lib_BINARIES)'; for p in $$list; do \
	  if test -f $$p; then \
	    echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(pkglibdir)/$$p"; \
	    echo " $(INSTALL_LIBRARY) $$p $(DESTDIR)$(pkglibdir)/$$p"; \
	    $(INSTALL_PROGRAM) $$p $(DESTDIR)$(pkglibdir)/$$p; \
	    stub=`echo $$p|sed -e "s/.*\(stub\).*/\1/"`; \
	    if test "x$$stub" = "xstub"; then \
		echo " $(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p"; \
		$(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p; \
	    else \
		echo " $(RANLIB) $(DESTDIR)$(pkglibdir)/$$p"; \
	    $(INSTALL_LIBRARY) $$p "$(DESTDIR)$(pkglibdir)/$$p"; \
		$(RANLIB) $(DESTDIR)$(pkglibdir)/$$p; \
	    fi; \
	    ext=`echo $$p|sed -e "s/.*\.//"`; \
	    if test "x$$ext" = "xdll"; then \
		lib=`basename $$p|sed -e 's/.[^.]*$$//'`.lib; \
		if test -f $$lib; then \
		    echo " $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib"; \
	            $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib; \
	            $(INSTALL_DATA) $$lib "$(DESTDIR)$(pkglibdir)/$$lib"; \
		fi; \
	    fi; \
	  fi; \
	done
	@list='$(PKG_TCL_SOURCES)'; for p in $$list; do \
	  if test -f $(srcdir)/$$p; then \
	    destp=`basename $$p`; \
	    echo " Install $$destp $(DESTDIR)$(pkglibdir)/$$destp"; \
	    $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(pkglibdir)/$$destp; \
	    $(INSTALL_DATA) $(srcdir)/$$p "$(DESTDIR)$(pkglibdir)/$$destp"; \
	  fi; \
	done
	@if test "x$(SHARED_BUILD)" = "x1"; then \
	    echo " Install pkgIndex.tcl $(DESTDIR)$(pkglibdir)"; \
	    $(INSTALL_DATA) pkgIndex.tcl $(DESTDIR)$(pkglibdir); \
	    $(INSTALL_DATA) pkgIndex.tcl "$(DESTDIR)$(pkglibdir)"; \
	fi

#========================================================================
# Install binary executables (e.g. .exe files and dependent .dll files)
# This is for files that must go in the bin directory (located next to
# wish and tclsh), like dependent .dll files on Windows.
#
# You should not have to modify this target, except to define bin_BINARIES
# above if necessary.
#========================================================================

install-bin-binaries: binaries
	@mkdir -p $(DESTDIR)$(bindir)
	@$(INSTALL_DATA_DIR) "$(DESTDIR)$(bindir)"
	@list='$(bin_BINARIES)'; for p in $$list; do \
	  if test -f $$p; then \
	    echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p"; \
	    $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p; \
	    $(INSTALL_PROGRAM) $$p "$(DESTDIR)$(bindir)/$$p"; \
	  fi; \
	done

.SUFFIXES: .c .$(OBJEXT)

Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
	cd $(top_builddir) \
	  && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status

uninstall-binaries:
	list='$(lib_BINARIES)'; for p in $$list; do \
	  rm -f $(DESTDIR)$(pkglibdir)/$$p; \
	  rm -f "$(DESTDIR)$(pkglibdir)/$$p"; \
	done
	list='$(PKG_TCL_SOURCES)'; for p in $$list; do \
	  p=`basename $$p`; \
	  rm -f $(DESTDIR)$(pkglibdir)/$$p; \
	  rm -f "$(DESTDIR)$(pkglibdir)/$$p"; \
	done
	list='$(bin_BINARIES)'; for p in $$list; do \
	  rm -f $(DESTDIR)$(bindir)/$$p; \
	  rm -f "$(DESTDIR)$(bindir)/$$p"; \
	done

.PHONY: all binaries clean depend distclean doc install libraries test
.PHONY: gdb gdb-test valgrind valgrindshell

# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

Changes to autoconf/tea/configure.ac.

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




-
+
-
-

-
+










+
+


-
+







-
+







#!/bin/bash -norc
dnl	This file is an input file used by the GNU "autoconf" program to
dnl	generate the file "configure", which is run during Tcl installation
dnl	to configure the system for the local environment.
#

# RCS: @(#) $Id: configure.in,v 1.43 2005/07/26 19:17:05 mdejong Exp $

#-----------------------------------------------------------------------
# Sample configure.in for Tcl Extensions.  The only places you should
# Sample configure.ac for Tcl Extensions.  The only places you should
# need to modify this file are marked by the string __CHANGE__
#-----------------------------------------------------------------------

#-----------------------------------------------------------------------
# __CHANGE__
# Set your package name and version numbers here.
#
# This initializes the environment with PACKAGE_NAME and PACKAGE_VERSION
# set as provided.  These will also be added as -D defs in your Makefile
# so you can encode the package version directly into the source files.
# This will also define a special symbol for Windows (BUILD_<PACKAGE_NAME>
# so that we create the export library with the dll.
#-----------------------------------------------------------------------

AC_INIT([sqlite], [3.7.4])
AC_INIT([sqlite],[3.40.0])

#--------------------------------------------------------------------
# Call TEA_INIT as the first TEA_ macro to set up initial vars.
# This will define a ${TEA_PLATFORM} variable == "unix" or "windows"
# as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE.
#--------------------------------------------------------------------

TEA_INIT([3.9])
TEA_INIT()

AC_CONFIG_AUX_DIR(tclconfig)

#--------------------------------------------------------------------
# Load the tclConfig.sh file
#--------------------------------------------------------------------

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







-
-
+
+
















-
+


+
+


+
+
+
+
+
+




















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







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

TEA_PREFIX

#-----------------------------------------------------------------------
# Standard compiler checks.
# This sets up CC by using the CC env var, or looks for gcc otherwise.
# This also calls AC_PROG_CC, AC_PROG_INSTALL and a few others to create
# the basic setup necessary to compile executables.
# This also calls AC_PROG_CC and a few others to create the basic setup
# necessary to compile executables.
#-----------------------------------------------------------------------

TEA_SETUP_COMPILER

#-----------------------------------------------------------------------
# __CHANGE__
# Specify the C source files to compile in TEA_ADD_SOURCES,
# public headers that need to be installed in TEA_ADD_HEADERS,
# stub library C source files to compile in TEA_ADD_STUB_SOURCES,
# and runtime Tcl library files in TEA_ADD_TCL_SOURCES.
# This defines PKG(_STUB)_SOURCES, PKG(_STUB)_OBJECTS, PKG_HEADERS
# and PKG_TCL_SOURCES.
#-----------------------------------------------------------------------

TEA_ADD_SOURCES([tclsqlite3.c])
TEA_ADD_HEADERS([])
TEA_ADD_INCLUDES([-I\"`\${CYGPATH} \${srcdir}/generic`\"])
TEA_ADD_INCLUDES([])
TEA_ADD_LIBS([])
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_FTS3=1])
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_FTS4=1])
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_FTS5=1])
TEA_ADD_CFLAGS([-DSQLITE_3_SUFFIX_ONLY=1])
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_RTREE=1])
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_GEOPOLY=1])
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_MATH_FUNCTIONS=1])
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_DESERIALIZE=1])
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_DBPAGE_VTAB=1])
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_BYTECODE_VTAB=1])
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_DBSTAT_VTAB=1])
TEA_ADD_STUB_SOURCES([])
TEA_ADD_TCL_SOURCES([])

#--------------------------------------------------------------------
# The --with-system-sqlite causes the TCL bindings to SQLite to use
# the system shared library for SQLite rather than statically linking
# against its own private copy.  This is dangerous and leads to
# undersirable dependences and is not recommended.
# Patchs from rmax.
#--------------------------------------------------------------------
AC_ARG_WITH([system-sqlite],
 [AC_HELP_STRING([--with-system-sqlite],
   [use a system-supplied libsqlite3 instead of the bundled one])],
 [], [with_system_sqlite=no])
if test x$with_system_sqlite != xno; then
 AC_CHECK_HEADER([sqlite3.h],
   [AC_CHECK_LIB([sqlite3],[sqlite3_initialize],
     [AC_DEFINE(USE_SYSTEM_SQLITE)
      LIBS="$LIBS -lsqlite3"])])
fi

#--------------------------------------------------------------------
# __CHANGE__
#
# You can add more files to clean if your extension creates any extra
# files by extending CLEANFILES.
# Add pkgIndex.tcl if it is generated in the Makefile instead of ./configure
# and change Makefile.in to move it from CONFIG_CLEAN_FILES to BINARIES var.
#
# A few miscellaneous platform-specific items:
# TEA_ADD_* any platform specific compiler/build info here.
#--------------------------------------------------------------------

#CLEANFILES="$CLEANFILES pkgIndex.tcl"
if test "${TEA_PLATFORM}" = "windows" ; then
    # Ensure no empty if clauses
    :
    #TEA_ADD_SOURCES([win/winFile.c])
    #TEA_ADD_INCLUDES([-I\"$(${CYGPATH} ${srcdir}/win)\"])
else
    # Ensure no empty else clauses
    :
    #TEA_ADD_SOURCES([unix/unixFile.c])
    #TEA_ADD_LIBS([-lsuperfly])
fi

#--------------------------------------------------------------------
# __CHANGE__
# Choose which headers you need.  Extension authors should try very
# hard to only rely on the Tcl public header files.  Internal headers
# contain private data structures and are subject to change without
# notice.
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
179
180
181
182
183
184
185






















186
187
188
189
190
191
192







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







TEA_CONFIG_CFLAGS

#--------------------------------------------------------------------
# Set the default compiler switches based on the --enable-symbols option.
#--------------------------------------------------------------------

TEA_ENABLE_SYMBOLS

#--------------------------------------------------------------------
# Everyone should be linking against the Tcl stub library.  If you
# can't for some reason, remove this definition.  If you aren't using
# stubs, you also need to modify the SHLIB_LD_LIBS setting below to
# link against the non-stubbed Tcl library.  Add Tk too if necessary.
#--------------------------------------------------------------------

AC_DEFINE(USE_TCL_STUBS, 1, [Use Tcl stubs])
#AC_DEFINE(USE_TK_STUBS, 1, [Use Tk stubs])


#--------------------------------------------------------------------
# Redefine fdatasync as fsync on systems that lack fdatasync
#--------------------------------------------------------------------
#
#AC_CHECK_FUNC(fdatasync, , AC_DEFINE(fdatasync, fsync))
# Check for library functions that SQLite can optionally use.
AC_CHECK_FUNCS([fdatasync usleep fullfsync localtime_r gmtime_r])

AC_FUNC_STRERROR_R


#--------------------------------------------------------------------
# This macro generates a line to use when building a library.  It
# depends on values set by the TEA_ENABLE_SHARED, TEA_ENABLE_SYMBOLS,
# and TEA_LOAD_TCLCONFIG macros above.
#--------------------------------------------------------------------

189
190
191
192
193
194
195


196
197
198








199
200
201









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







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


-
+
+
+
+
+
+
+
+
+
# a pkgIndex.tcl file or anything else at extension build time.
#--------------------------------------------------------------------

TEA_PROG_TCLSH
#TEA_PROG_WISH

#--------------------------------------------------------------------
# Setup a *Config.sh.in configuration file.
#--------------------------------------------------------------------
# Finally, substitute all of the various values into the Makefile.
# You may alternatively have a special pkgIndex.tcl.in or other files
# which require substituting th AC variables in.  Include these here.

#TEA_EXPORT_CONFIG([sample])
#AC_SUBST(SAMPLE_VAR)

#--------------------------------------------------------------------
# Specify files to substitute AC variables in. You may alternatively
# have a special pkgIndex.tcl.in or other files which require
# substituting the AC variables in. Include these here.
#--------------------------------------------------------------------

AC_OUTPUT([Makefile pkgIndex.tcl])
AC_CONFIG_FILES([Makefile pkgIndex.tcl])
#AC_CONFIG_FILES([sampleConfig.sh])

#--------------------------------------------------------------------
# Finally, substitute all of the various values into the files
# specified with AC_CONFIG_FILES.
#--------------------------------------------------------------------

AC_OUTPUT

Changes to autoconf/tea/pkgIndex.tcl.in.

1
2


3

4

5
6
7







1
2
3
4

5



6
7
8
9
10
-
-
+
+

+
-
+
-
-
-
+
+
+
+
+
#
# Tcl package index file
# -*- tcl -*-
# Tcl package index file, version 1.1
#
if {[package vsatisfies [package provide Tcl] 9.0-]} {
# Note sqlite*3* init specifically
    package ifneeded sqlite3 @PACKAGE_VERSION@ \
#
package ifneeded sqlite3 @PACKAGE_VERSION@ \
    [list load [file join $dir @PKG_LIB_FILE@] Sqlite3]
	    [list load [file join $dir @PKG_LIB_FILE9@] sqlite3]
} else {
    package ifneeded sqlite3 @PACKAGE_VERSION@ \
	    [list load [file join $dir @PKG_LIB_FILE8@] sqlite3]
}

Changes to autoconf/tea/tclconfig/tcl.m4.

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











-
+
-
-
-
-





+







# tcl.m4 --
#
#	This file provides a set of autoconf macros to help TEA-enable
#	a Tcl extension.
#
# Copyright (c) 1999-2000 Ajuba Solutions.
# Copyright (c) 2002-2005 ActiveState Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

AC_PREREQ(2.57)
AC_PREREQ([2.69])

dnl TEA extensions pass us the version of TEA they think they
dnl are compatible with (must be set in TEA_INIT below)
dnl TEA_VERSION="3.9"

# Possible values for key variables defined:
#
# TEA_WINDOWINGSYSTEM - win32 aqua x11 (mirrors 'tk windowingsystem')
# TEA_PLATFORM        - windows unix
# TEA_TK_EXTENSION    - True if this is a Tk extension
#

#------------------------------------------------------------------------
# TEA_PATH_TCLCONFIG --
#
#	Locate the tclConfig.sh file and perform a sanity check on
#	the Tcl compile flags
49
50
51
52
53
54
55
56

57
58

59
60
61
62
63
64
65
46
47
48
49
50
51
52

53
54

55
56
57
58
59
60
61
62







-
+

-
+







    # the alternative search directory is invoked by --with-tcl
    #

    if test x"${no_tcl}" = x ; then
	# we reset no_tcl in case something fails here
	no_tcl=true
	AC_ARG_WITH(tcl,
	    AC_HELP_STRING([--with-tcl],
	    AS_HELP_STRING([--with-tcl],
		[directory containing tcl configuration (tclConfig.sh)]),
	    with_tclconfig="${withval}")
	    [with_tclconfig="${withval}"])
	AC_MSG_CHECKING([for Tcl configuration])
	AC_CACHE_VAL(ac_cv_c_tclconfig,[

	    # First check to see if --with-tcl was specified.
	    if test x"${with_tclconfig}" != x ; then
		case "${with_tclconfig}" in
		    */tclConfig.sh )
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







+
+
-
+







	    fi

	    # on Darwin, check in Framework installation locations
	    if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tclconfig}" = x ; then
		for i in `ls -d ~/Library/Frameworks 2>/dev/null` \
			`ls -d /Library/Frameworks 2>/dev/null` \
			`ls -d /Network/Library/Frameworks 2>/dev/null` \
			`ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/Library/Frameworks/Tcl.framework 2>/dev/null` \
			`ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/Network/Library/Frameworks/Tcl.framework 2>/dev/null` \
			`ls -d /System/Library/Frameworks 2>/dev/null` \
			`ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Tcl.framework 2>/dev/null` \
			; do
		    if test -f "$i/Tcl.framework/tclConfig.sh" ; then
			ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`"
			break
		    fi
		done
	    fi
132
133
134
135
136
137
138

139
140
141
142




143
144
145
146
147
148
149
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153







+




+
+
+
+







	    # check in a few common install locations
	    if test x"${ac_cv_c_tclconfig}" = x ; then
		for i in `ls -d ${libdir} 2>/dev/null` \
			`ls -d ${exec_prefix}/lib 2>/dev/null` \
			`ls -d ${prefix}/lib 2>/dev/null` \
			`ls -d /usr/local/lib 2>/dev/null` \
			`ls -d /usr/contrib/lib 2>/dev/null` \
			`ls -d /usr/pkg/lib 2>/dev/null` \
			`ls -d /usr/lib 2>/dev/null` \
			`ls -d /usr/lib64 2>/dev/null` \
			`ls -d /usr/lib/tcl8.6 2>/dev/null` \
			`ls -d /usr/lib/tcl8.5 2>/dev/null` \
			`ls -d /usr/local/lib/tcl8.6 2>/dev/null` \
			`ls -d /usr/local/lib/tcl8.5 2>/dev/null` \
			`ls -d /usr/local/lib/tcl/tcl8.6 2>/dev/null` \
			`ls -d /usr/local/lib/tcl/tcl8.5 2>/dev/null` \
			; do
		    if test -f "$i/tclConfig.sh" ; then
			ac_cv_c_tclconfig="`(cd $i; pwd)`"
			break
		    fi
		done
	    fi
204
205
206
207
208
209
210
211

212
213

214
215
216
217
218
219
220
208
209
210
211
212
213
214

215
216

217
218
219
220
221
222
223
224







-
+

-
+







    # the alternative search directory is invoked by --with-tk
    #

    if test x"${no_tk}" = x ; then
	# we reset no_tk in case something fails here
	no_tk=true
	AC_ARG_WITH(tk,
	    AC_HELP_STRING([--with-tk],
	    AS_HELP_STRING([--with-tk],
		[directory containing tk configuration (tkConfig.sh)]),
	    with_tkconfig="${withval}")
	    [with_tkconfig="${withval}"])
	AC_MSG_CHECKING([for Tk configuration])
	AC_CACHE_VAL(ac_cv_c_tkconfig,[

	    # First check to see if --with-tkconfig was specified.
	    if test x"${with_tkconfig}" != x ; then
		case "${with_tkconfig}" in
		    */tkConfig.sh )
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
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







-















+
+
+


+
+
+
+







	    fi

	    # on Darwin, check in Framework installation locations
	    if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tkconfig}" = x ; then
		for i in `ls -d ~/Library/Frameworks 2>/dev/null` \
			`ls -d /Library/Frameworks 2>/dev/null` \
			`ls -d /Network/Library/Frameworks 2>/dev/null` \
			`ls -d /System/Library/Frameworks 2>/dev/null` \
			; do
		    if test -f "$i/Tk.framework/tkConfig.sh" ; then
			ac_cv_c_tkconfig="`(cd $i/Tk.framework; pwd)`"
			break
		    fi
		done
	    fi

	    # check in a few common install locations
	    if test x"${ac_cv_c_tkconfig}" = x ; then
		for i in `ls -d ${libdir} 2>/dev/null` \
			`ls -d ${exec_prefix}/lib 2>/dev/null` \
			`ls -d ${prefix}/lib 2>/dev/null` \
			`ls -d /usr/local/lib 2>/dev/null` \
			`ls -d /usr/contrib/lib 2>/dev/null` \
			`ls -d /usr/pkg/lib 2>/dev/null` \
			`ls -d /usr/lib/tk8.6 2>/dev/null` \
			`ls -d /usr/lib/tk8.5 2>/dev/null` \
			`ls -d /usr/lib 2>/dev/null` \
			`ls -d /usr/lib64 2>/dev/null` \
			`ls -d /usr/local/lib/tk8.6 2>/dev/null` \
			`ls -d /usr/local/lib/tk8.5 2>/dev/null` \
			`ls -d /usr/local/lib/tcl/tk8.6 2>/dev/null` \
			`ls -d /usr/local/lib/tcl/tk8.5 2>/dev/null` \
			; do
		    if test -f "$i/tkConfig.sh" ; then
			ac_cv_c_tkconfig="`(cd $i; pwd)`"
			break
		    fi
		done
	    fi
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
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







+
+












-
-
-
-







#
# Results:
#
#	Substitutes the following vars:
#		TCL_BIN_DIR
#		TCL_SRC_DIR
#		TCL_LIB_FILE
#		TCL_ZIP_FILE
#		TCL_ZIPFS_SUPPORT
#------------------------------------------------------------------------

AC_DEFUN([TEA_LOAD_TCLCONFIG], [
    AC_MSG_CHECKING([for existence of ${TCL_BIN_DIR}/tclConfig.sh])

    if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then
        AC_MSG_RESULT([loading])
	. "${TCL_BIN_DIR}/tclConfig.sh"
    else
        AC_MSG_RESULT([could not find ${TCL_BIN_DIR}/tclConfig.sh])
    fi

    # eval is required to do the TCL_DBGX substitution
    eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\""
    eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\""

    # If the TCL_BIN_DIR is the build directory (not the install directory),
    # then set the common variable name to the value of the build variables.
    # For example, the variable TCL_LIB_SPEC will be set to the value
    # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC
    # instead of TCL_BUILD_LIB_SPEC since it will work with both an
    # installed and uninstalled version of Tcl.
    if test -f "${TCL_BIN_DIR}/Makefile" ; then
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
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







-
-
-
-
-
-















-
+



+
+
-
+
+
+

-
+
+







		    TCL_STUB_LIB_SPEC="-L`echo "${TCL_BIN_DIR}"  | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}"
		    TCL_STUB_LIB_PATH="${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"
		fi
		;;
	esac
    fi

    # eval is required to do the TCL_DBGX substitution
    eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\""
    eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\""
    eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\""
    eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\""

    AC_SUBST(TCL_VERSION)
    AC_SUBST(TCL_PATCH_LEVEL)
    AC_SUBST(TCL_BIN_DIR)
    AC_SUBST(TCL_SRC_DIR)

    AC_SUBST(TCL_LIB_FILE)
    AC_SUBST(TCL_LIB_FLAG)
    AC_SUBST(TCL_LIB_SPEC)

    AC_SUBST(TCL_STUB_LIB_FILE)
    AC_SUBST(TCL_STUB_LIB_FLAG)
    AC_SUBST(TCL_STUB_LIB_SPEC)

    AC_MSG_CHECKING([platform])
    hold_cc=$CC; CC="$TCL_CC"
    AC_TRY_COMPILE(,[
    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
	    #ifdef _WIN32
		#error win32
	    #endif
	]])],[
	    # first test we've already retrieved platform (cross-compile), fallback to unix otherwise:
    ], TEA_PLATFORM="unix",
	    TEA_PLATFORM="${TEA_PLATFORM-unix}"
	    CYGPATH=echo
	],[
	    TEA_PLATFORM="windows"
    )
	    AC_CHECK_PROG(CYGPATH, cygpath, cygpath -m, echo)
    ])
    CC=$hold_cc
    AC_MSG_RESULT($TEA_PLATFORM)

    # The BUILD_$pkg is to define the correct extern storage class
    # handling when making this package
    AC_DEFINE_UNQUOTED(BUILD_${PACKAGE_NAME}, [],
	    [Building extension source?])
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
476
477
478
479
480
481
482




483
484
485
486
487
488
489







-
-
-
-







    if test -f "${TK_BIN_DIR}/tkConfig.sh" ; then
        AC_MSG_RESULT([loading])
	. "${TK_BIN_DIR}/tkConfig.sh"
    else
        AC_MSG_RESULT([could not find ${TK_BIN_DIR}/tkConfig.sh])
    fi

    # eval is required to do the TK_DBGX substitution
    eval "TK_LIB_FILE=\"${TK_LIB_FILE}\""
    eval "TK_STUB_LIB_FILE=\"${TK_STUB_LIB_FILE}\""

    # If the TK_BIN_DIR is the build directory (not the install directory),
    # then set the common variable name to the value of the build variables.
    # For example, the variable TK_LIB_SPEC will be set to the value
    # of TK_BUILD_LIB_SPEC. An extension should make use of TK_LIB_SPEC
    # instead of TK_BUILD_LIB_SPEC since it will work with both an
    # installed and uninstalled version of Tcl.
    if test -f "${TK_BIN_DIR}/Makefile" ; then
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
509
510
511
512
513
514
515






516
517
518
519
520
521
522







-
-
-
-
-
-







		    TK_STUB_LIB_SPEC="-L` echo "${TK_BIN_DIR}"  | sed -e 's/ /\\\\ /g'` ${TK_STUB_LIB_FLAG}"
		    TK_STUB_LIB_PATH="${TK_BIN_DIR}/${TK_STUB_LIB_FILE}"
		fi
		;;
	esac
    fi

    # eval is required to do the TK_DBGX substitution
    eval "TK_LIB_FLAG=\"${TK_LIB_FLAG}\""
    eval "TK_LIB_SPEC=\"${TK_LIB_SPEC}\""
    eval "TK_STUB_LIB_FLAG=\"${TK_STUB_LIB_FLAG}\""
    eval "TK_STUB_LIB_SPEC=\"${TK_STUB_LIB_SPEC}\""

    # TEA specific: Ensure windowingsystem is defined
    if test "${TEA_PLATFORM}" = "unix" ; then
	case ${TK_DEFS} in
	    *MAC_OSX_TK*)
		AC_DEFINE(MAC_OSX_TK, 1, [Are we building against Mac OS X TkAqua?])
		TEA_WINDOWINGSYSTEM="aqua"
		;;
568
569
570
571
572
573
574

575








576
577
578
579
580
581
582

583
584

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







+
-
+
+
+
+
+
+
+
+






-
+

-
+







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

AC_DEFUN([TEA_PROG_TCLSH], [
    AC_MSG_CHECKING([for tclsh])
    if test -f "${TCL_BIN_DIR}/Makefile" ; then
        # tclConfig.sh is in Tcl build directory
        if test "${TEA_PLATFORM}" = "windows"; then
          if test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}" ; then
            TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}"
            TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}"
          elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}s${EXEEXT}" ; then
            TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}s${EXEEXT}"
          elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}t${EXEEXT}" ; then
            TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}t${EXEEXT}"
          elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}st${EXEEXT}" ; then
            TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}st${EXEEXT}"
          fi
        else
            TCLSH_PROG="${TCL_BIN_DIR}/tclsh"
        fi
    else
        # tclConfig.sh is in install location
        if test "${TEA_PLATFORM}" = "windows"; then
            TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}"
            TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}"
        else
            TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}${TCL_DBGX}"
            TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}"
        fi
        list="`ls -d ${TCL_BIN_DIR}/../bin 2>/dev/null` \
              `ls -d ${TCL_BIN_DIR}/..     2>/dev/null` \
              `ls -d ${TCL_PREFIX}/bin     2>/dev/null`"
        for i in $list ; do
            if test -f "$i/${TCLSH_PROG}" ; then
                REAL_TCL_BIN_DIR="`cd "$i"; pwd`/"
618
619
620
621
622
623
624

625








626
627
628
629
630
631
632

633
634

635
636
637
638
639
640
641
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







+
-
+
+
+
+
+
+
+
+






-
+

-
+







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

AC_DEFUN([TEA_PROG_WISH], [
    AC_MSG_CHECKING([for wish])
    if test -f "${TK_BIN_DIR}/Makefile" ; then
        # tkConfig.sh is in Tk build directory
        if test "${TEA_PLATFORM}" = "windows"; then
          if test -f "${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${EXEEXT}" ; then
            WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}"
            WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${EXEEXT}"
          elif test -f "${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}s${EXEEXT}" ; then
            WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}$s{EXEEXT}"
          elif test -f "${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}t${EXEEXT}" ; then
            WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}t${EXEEXT}"
          elif test -f "${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}st${EXEEXT}" ; then
            WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}st${EXEEXT}"
          fi
        else
            WISH_PROG="${TK_BIN_DIR}/wish"
        fi
    else
        # tkConfig.sh is in install location
        if test "${TEA_PLATFORM}" = "windows"; then
            WISH_PROG="wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}"
            WISH_PROG="wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${EXEEXT}"
        else
            WISH_PROG="wish${TK_MAJOR_VERSION}.${TK_MINOR_VERSION}${TK_DBGX}"
            WISH_PROG="wish${TK_MAJOR_VERSION}.${TK_MINOR_VERSION}"
        fi
        list="`ls -d ${TK_BIN_DIR}/../bin 2>/dev/null` \
              `ls -d ${TK_BIN_DIR}/..     2>/dev/null` \
              `ls -d ${TK_PREFIX}/bin     2>/dev/null`"
        for i in $list ; do
            if test -f "$i/${WISH_PROG}" ; then
                REAL_TK_BIN_DIR="`cd "$i"; pwd`/"
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
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







+







+
+
+
+
+

-



-
+

-
+



-
+

-
+


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


+



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

+







# Arguments:
#	none
#
# Results:
#
#	Adds the following arguments to configure:
#		--enable-shared=yes|no
#		--enable-stubs=yes|no
#
#	Defines the following vars:
#		STATIC_BUILD	Used for building import/export libraries
#				on Windows.
#
#	Sets the following vars:
#		SHARED_BUILD	Value of 1 or 0
#               STUBS_BUILD     Value if 1 or 0
#               USE_TCL_STUBS   Value true: if SHARED_BUILD or --enable-stubs
#               USE_TCLOO_STUBS Value true: if SHARED_BUILD or --enable-stubs
#               USE_TK_STUBS    Value true: if SHARED_BUILD or --enable-stubs
#                                AND TEA_WINDOWING_SYSTEM != ""
#------------------------------------------------------------------------

AC_DEFUN([TEA_ENABLE_SHARED], [
    AC_MSG_CHECKING([how to build libraries])
    AC_ARG_ENABLE(shared,
	AC_HELP_STRING([--enable-shared],
	AS_HELP_STRING([--enable-shared],
	    [build and link with shared libraries (default: on)]),
	[tcl_ok=$enableval], [tcl_ok=yes])
	[shared_ok=$enableval], [shared_ok=yes])

    if test "${enable_shared+set}" = set; then
	enableval="$enable_shared"
	tcl_ok=$enableval
	shared_ok=$enableval
    else
	tcl_ok=yes
	shared_ok=yes
    fi

    AC_ARG_ENABLE(stubs,
	AS_HELP_STRING([--enable-stubs],
	    [build and link with stub libraries. Always true for shared builds (default: on)]),
	[stubs_ok=$enableval], [stubs_ok=yes])

    if test "${enable_stubs+set}" = set; then
	enableval="$enable_stubs"
	stubs_ok=$enableval
    else
	stubs_ok=yes
    fi

    # Stubs are always enabled for shared builds
    if test "$tcl_ok" = "yes" ; then
    if test "$shared_ok" = "yes" ; then
	AC_MSG_RESULT([shared])
	SHARED_BUILD=1
        STUBS_BUILD=1
    else
	AC_MSG_RESULT([static])
	SHARED_BUILD=0
	AC_DEFINE(STATIC_BUILD, 1, [Is this a static build?])
    fi
	AC_DEFINE(STATIC_BUILD, 1, [This a static build])
        if test "$stubs_ok" = "yes" ; then
          STUBS_BUILD=1
        else
          STUBS_BUILD=0
        fi
    fi
    if test "${STUBS_BUILD}" = "1" ; then
      AC_DEFINE(USE_TCL_STUBS, 1, [Use Tcl stubs])
      AC_DEFINE(USE_TCLOO_STUBS, 1, [Use TclOO stubs])
      if test "${TEA_WINDOWINGSYSTEM}" != ""; then
        AC_DEFINE(USE_TK_STUBS, 1, [Use Tk stubs])
      fi
    fi

    AC_SUBST(SHARED_BUILD)
    AC_SUBST(STUBS_BUILD)
])

#------------------------------------------------------------------------
# TEA_ENABLE_THREADS --
#
#	Specify if thread support should be enabled.  If "yes" is specified
#	as an arg (optional), threads are enabled by default, "no" means
724
725
726
727
728
729
730
731
732


733
734
735
736
737
738
739
770
771
772
773
774
775
776


777
778
779
780
781
782
783
784
785







-
-
+
+







#		TCL_THREADS
#		_REENTRANT
#		_THREAD_SAFE
#------------------------------------------------------------------------

AC_DEFUN([TEA_ENABLE_THREADS], [
    AC_ARG_ENABLE(threads,
	AC_HELP_STRING([--enable-threads],
	    [build with threads]),
	AS_HELP_STRING([--enable-threads],
	    [build with threads (default: on)]),
	[tcl_ok=$enableval], [tcl_ok=yes])

    if test "${enable_threads+set}" = set; then
	enableval="$enable_threads"
	tcl_ok=$enableval
    else
	tcl_ok=yes
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
855
856
857
858
859
860
861








862
863
864
865
866
867
868







-
-
-
-
-
-
-
-







	*THREADS=1*)
	    if test "${TCL_THREADS}" = "0"; then
		AC_MSG_WARN([
    Building ${PACKAGE_NAME} without threads enabled, but building against Tcl
    that IS thread-enabled.  It is recommended to use --enable-threads.])
	    fi
	    ;;
	*)
	    if test "${TCL_THREADS}" = "1"; then
		AC_MSG_WARN([
    --enable-threads requested, but building against a Tcl that is NOT
    thread-enabled.  This is an OK configuration that will also run in
    a thread-enabled core.])
	    fi
	    ;;
    esac
    AC_SUBST(TCL_THREADS)
])

#------------------------------------------------------------------------
# TEA_ENABLE_SYMBOLS --
#
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
884
885
886
887
888
889
890


891
892
893
894
895
896
897

898
899
900

901
902
903
904
905
906
907
908
909
910
911
912




913
914

915
916
917
918
919
920
921







-
-







-
+


-




+







-
-
-
-


-







#		--enable-symbols
#
#	Defines the following vars:
#		CFLAGS_DEFAULT	Sets to $(CFLAGS_DEBUG) if true
#				Sets to "$(CFLAGS_OPTIMIZE) -DNDEBUG" if false
#		LDFLAGS_DEFAULT	Sets to $(LDFLAGS_DEBUG) if true
#				Sets to $(LDFLAGS_OPTIMIZE) if false
#		DBGX		Formerly used as debug library extension;
#				always blank now.
#------------------------------------------------------------------------

AC_DEFUN([TEA_ENABLE_SYMBOLS], [
    dnl TEA specific: Make sure we are initialized
    AC_REQUIRE([TEA_CONFIG_CFLAGS])
    AC_MSG_CHECKING([for build with symbols])
    AC_ARG_ENABLE(symbols,
	AC_HELP_STRING([--enable-symbols],
	AS_HELP_STRING([--enable-symbols],
	    [build with debugging symbols (default: off)]),
	[tcl_ok=$enableval], [tcl_ok=no])
    DBGX=""
    if test "$tcl_ok" = "no"; then
	CFLAGS_DEFAULT="${CFLAGS_OPTIMIZE} -DNDEBUG"
	LDFLAGS_DEFAULT="${LDFLAGS_OPTIMIZE}"
	AC_MSG_RESULT([no])
	AC_DEFINE(TCL_CFG_OPTIMIZED, 1, [Is this an optimized build?])
    else
	CFLAGS_DEFAULT="${CFLAGS_DEBUG}"
	LDFLAGS_DEFAULT="${LDFLAGS_DEBUG}"
	if test "$tcl_ok" = "yes"; then
	    AC_MSG_RESULT([yes (standard debugging)])
	fi
    fi
    # TEA specific:
    if test "${TEA_PLATFORM}" != "windows" ; then
	LDFLAGS_DEFAULT="${LDFLAGS}"
    fi
    AC_SUBST(CFLAGS_DEFAULT)
    AC_SUBST(LDFLAGS_DEFAULT)
    AC_SUBST(TCL_DBGX)

    if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then
	AC_DEFINE(TCL_MEM_DEBUG, 1, [Is memory debugging enabled?])
    fi

    if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then
	if test "$tcl_ok" = "all"; then
911
912
913
914
915
916
917
918

919
920
921
922
923
924
925
926
927
928
929

930
931
932
933
934
935
936
942
943
944
945
946
947
948

949
950
951
952
953
954
955
956
957
958
959

960
961
962
963
964
965
966
967







-
+










-
+







#
#	Defines the following vars:
#		HAVE_LANGINFO	Triggers use of nl_langinfo if defined.
#------------------------------------------------------------------------

AC_DEFUN([TEA_ENABLE_LANGINFO], [
    AC_ARG_ENABLE(langinfo,
	AC_HELP_STRING([--enable-langinfo],
	AS_HELP_STRING([--enable-langinfo],
	    [use nl_langinfo if possible to determine encoding at startup, otherwise use old heuristic (default: on)]),
	[langinfo_ok=$enableval], [langinfo_ok=yes])

    HAVE_LANGINFO=0
    if test "$langinfo_ok" = "yes"; then
	AC_CHECK_HEADER(langinfo.h,[langinfo_ok=yes],[langinfo_ok=no])
    fi
    AC_MSG_CHECKING([whether to use nl_langinfo])
    if test "$langinfo_ok" = "yes"; then
	AC_CACHE_VAL(tcl_cv_langinfo_h, [
	    AC_TRY_COMPILE([#include <langinfo.h>], [nl_langinfo(CODESET);],
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <langinfo.h>]], [[nl_langinfo(CODESET);]])],
		    [tcl_cv_langinfo_h=yes],[tcl_cv_langinfo_h=no])])
	AC_MSG_RESULT([$tcl_cv_langinfo_h])
	if test $tcl_cv_langinfo_h = yes; then
	    AC_DEFINE(HAVE_LANGINFO, 1, [Do we have nl_langinfo()?])
	fi
    else
	AC_MSG_RESULT([$langinfo_ok])
947
948
949
950
951
952
953

954
955
956
957
958
959
960
961
962
963
964
965
966
967
968



969
970
971
972
973
974
975
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010







+















+
+
+







# Arguments:
#	none
#
# Results:
#	Defines the following var:
#
#	system -	System/platform/version identification code.
#
#--------------------------------------------------------------------

AC_DEFUN([TEA_CONFIG_SYSTEM], [
    AC_CACHE_CHECK([system version], tcl_cv_sys_version, [
	# TEA specific:
	if test "${TEA_PLATFORM}" = "windows" ; then
	    tcl_cv_sys_version=windows
	else
	    tcl_cv_sys_version=`uname -s`-`uname -r`
	    if test "$?" -ne 0 ; then
		AC_MSG_WARN([can't find uname command])
		tcl_cv_sys_version=unknown
	    else
		if test "`uname -s`" = "AIX" ; then
		    tcl_cv_sys_version=AIX-`uname -v`.`uname -r`
		fi
		if test "`uname -s`" = "NetBSD" -a -f /etc/debian_version ; then
		    tcl_cv_sys_version=NetBSD-Debian
		fi
	    fi
	fi
    ])
    system=$tcl_cv_sys_version
])

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







-
+








-
+












-
+

-
-
+
+












-
+




-
-
-
-
-
-
-
-
-
-
-







    dnl TEA specific: Make sure we are initialized
    AC_REQUIRE([TEA_INIT])

    # Step 0.a: Enable 64 bit support?

    AC_MSG_CHECKING([if 64bit support is requested])
    AC_ARG_ENABLE(64bit,
	AC_HELP_STRING([--enable-64bit],
	AS_HELP_STRING([--enable-64bit],
	    [enable 64bit support (default: off)]),
	[do64bit=$enableval], [do64bit=no])
    AC_MSG_RESULT([$do64bit])

    # Step 0.b: Enable Solaris 64 bit VIS support?

    AC_MSG_CHECKING([if 64bit Sparc VIS support is requested])
    AC_ARG_ENABLE(64bit-vis,
	AC_HELP_STRING([--enable-64bit-vis],
	AS_HELP_STRING([--enable-64bit-vis],
	    [enable 64bit Sparc VIS support (default: off)]),
	[do64bitVIS=$enableval], [do64bitVIS=no])
    AC_MSG_RESULT([$do64bitVIS])
    # Force 64bit on with VIS
    AS_IF([test "$do64bitVIS" = "yes"], [do64bit=yes])

    # Step 0.c: Check if visibility support is available. Do this here so
    # that platform specific alternatives can be used below if this fails.

    AC_CACHE_CHECK([if compiler supports visibility "hidden"],
	tcl_cv_cc_visibility_hidden, [
	hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
	AC_TRY_LINK([
	AC_LINK_IFELSE([AC_LANG_PROGRAM([[
	    extern __attribute__((__visibility__("hidden"))) void f(void);
	    void f(void) {}], [f();], tcl_cv_cc_visibility_hidden=yes,
	    tcl_cv_cc_visibility_hidden=no)
	    void f(void) {}]], [[f();]])],[tcl_cv_cc_visibility_hidden=yes],
	    [tcl_cv_cc_visibility_hidden=no])
	CFLAGS=$hold_cflags])
    AS_IF([test $tcl_cv_cc_visibility_hidden = yes], [
	AC_DEFINE(MODULE_SCOPE,
	    [extern __attribute__((__visibility__("hidden")))],
	    [Compiler support for module scope symbols])
	AC_DEFINE(HAVE_HIDDEN, [1], [Compiler support for module scope symbols])
    ])

    # Step 0.d: Disable -rpath support?

    AC_MSG_CHECKING([if rpath support is requested])
    AC_ARG_ENABLE(rpath,
	AC_HELP_STRING([--disable-rpath],
	AS_HELP_STRING([--disable-rpath],
	    [disable rpath support (default: on)]),
	[doRpath=$enableval], [doRpath=yes])
    AC_MSG_RESULT([$doRpath])

    # TEA specific: Cross-compiling options for Windows/CE builds?

    AS_IF([test "${TEA_PLATFORM}" = windows], [
	AC_MSG_CHECKING([if Windows/CE build is requested])
	AC_ARG_ENABLE(wince,
	    AC_HELP_STRING([--enable-wince],
		[enable Win/CE support (where applicable)]),
	    [doWince=$enableval], [doWince=no])
	AC_MSG_RESULT([$doWince])
    ])

    # Set the variable "system" to hold the name and version number
    # for the system.

    TEA_CONFIG_SYSTEM

    # Require ranlib early so we can override it in special cases below.

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
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
1318
1319
1320
1321
1322
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







-
+



-
-
-
-
-


-
-
-
-
-



-
+
+
+



-


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-








+
+
+
+
+
+
+
+


-
-
+
-
-
-
-
+
+
+





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

-
+


















-
+



-
-
-
+
+
+




-
+





+
+
+
+
+
+
+

-
+







    ], [
	CFLAGS_OPTIMIZE=-O
	CFLAGS_WARNING=""
    ])
    AC_CHECK_TOOL(AR, ar)
    STLIB_LD='${AR} cr'
    LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH"
    AS_IF([test "x$SHLIB_VERSION" = x],[SHLIB_VERSION="1.0"])
    AS_IF([test "x$SHLIB_VERSION" = x],[SHLIB_VERSION=""],[SHLIB_VERSION=".$SHLIB_VERSION"])
    case $system in
	# TEA specific:
	windows)
	    # This is a 2-stage check to make sure we have the 64-bit SDK
	    # We have to know where the SDK is installed.
	    # This magic is based on MS Platform SDK for Win2003 SP1 - hobbs
	    # MACHINE is IX86 for LINK, but this is used by the manifest,
	    # which requires x86|amd64|ia64.
	    MACHINE="X86"
	    if test "$do64bit" != "no" ; then
		if test "x${MSSDK}x" = "xx" ; then
		    MSSDK="C:/Progra~1/Microsoft Platform SDK"
		fi
		MSSDK=`echo "$MSSDK" | sed -e  's!\\\!/!g'`
		PATH64=""
		case "$do64bit" in
		    amd64|x64|yes)
			MACHINE="AMD64" ; # default to AMD64 64-bit build
			PATH64="${MSSDK}/Bin/Win64/x86/AMD64"
			;;
		    arm64|aarch64)
			MACHINE="ARM64"
			;;
		    ia64)
			MACHINE="IA64"
			PATH64="${MSSDK}/Bin/Win64"
			;;
		esac
		if test "$GCC" != "yes" -a ! -d "${PATH64}" ; then
		    AC_MSG_WARN([Could not find 64-bit $MACHINE SDK to enable 64bit mode])
		    AC_MSG_WARN([Ensure latest Platform SDK is installed])
		    do64bit="no"
		else
		    AC_MSG_RESULT([   Using 64-bit $MACHINE mode])
		    do64bit_ok="yes"
		fi
	    fi

	    if test "$doWince" != "no" ; then
		if test "$do64bit" != "no" ; then
		    AC_MSG_ERROR([Windows/CE and 64-bit builds incompatible])
		fi
		if test "$GCC" = "yes" ; then
		    AC_MSG_ERROR([Windows/CE and GCC builds incompatible])
		fi
		TEA_PATH_CELIB
		# Set defaults for common evc4/PPC2003 setup
		# Currently Tcl requires 300+, possibly 420+ for sockets
		CEVERSION=420; 		# could be 211 300 301 400 420 ...
		TARGETCPU=ARMV4;	# could be ARMV4 ARM MIPS SH3 X86 ...
		ARCH=ARM;		# could be ARM MIPS X86EM ...
		PLATFORM="Pocket PC 2003"; # or "Pocket PC 2002"
		if test "$doWince" != "yes"; then
		    # If !yes then the user specified something
		    # Reset ARCH to allow user to skip specifying it
		    ARCH=
		    eval `echo $doWince | awk -F, '{ \
	    if (length([$]1)) { printf "CEVERSION=\"%s\"\n", [$]1; \
	    if ([$]1 < 400)   { printf "PLATFORM=\"Pocket PC 2002\"\n" } }; \
	    if (length([$]2)) { printf "TARGETCPU=\"%s\"\n", toupper([$]2) }; \
	    if (length([$]3)) { printf "ARCH=\"%s\"\n", toupper([$]3) }; \
	    if (length([$]4)) { printf "PLATFORM=\"%s\"\n", [$]4 }; \
		    }'`
		    if test "x${ARCH}" = "x" ; then
			ARCH=$TARGETCPU;
		    fi
		fi
		OSVERSION=WCE$CEVERSION;
	    	if test "x${WCEROOT}" = "x" ; then
			WCEROOT="C:/Program Files/Microsoft eMbedded C++ 4.0"
		    if test ! -d "${WCEROOT}" ; then
			WCEROOT="C:/Program Files/Microsoft eMbedded Tools"
		    fi
		fi
		if test "x${SDKROOT}" = "x" ; then
		    SDKROOT="C:/Program Files/Windows CE Tools"
		    if test ! -d "${SDKROOT}" ; then
			SDKROOT="C:/Windows CE Tools"
		    fi
		fi
		WCEROOT=`echo "$WCEROOT" | sed -e 's!\\\!/!g'`
		SDKROOT=`echo "$SDKROOT" | sed -e 's!\\\!/!g'`
		if test ! -d "${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}" \
		    -o ! -d "${WCEROOT}/EVC/${OSVERSION}/bin"; then
		    AC_MSG_ERROR([could not find PocketPC SDK or target compiler to enable WinCE mode [$CEVERSION,$TARGETCPU,$ARCH,$PLATFORM]])
		    doWince="no"
		else
		    # We could PATH_NOSPACE these, but that's not important,
		    # as long as we quote them when used.
		    CEINCLUDE="${SDKROOT}/${OSVERSION}/${PLATFORM}/include"
		    if test -d "${CEINCLUDE}/${TARGETCPU}" ; then
			CEINCLUDE="${CEINCLUDE}/${TARGETCPU}"
		    fi
		    CELIBPATH="${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}"
    		fi
	    fi

	    if test "$GCC" != "yes" ; then
	        if test "${SHARED_BUILD}" = "0" ; then
		    runtime=-MT
	        else
		    runtime=-MD
	        fi
	        case "x`echo \${VisualStudioVersion}`" in
	            x1[[4-9]]*)
		        lflags="${lflags} -nodefaultlib:libucrt.lib"
		        TEA_ADD_LIBS([ucrt.lib])
	            ;;
	            *)
	            ;;
	        esac

                if test "$do64bit" != "no" ; then
		    # All this magic is necessary for the Win64 SDK RC1 - hobbs
		    CC="\"${PATH64}/cl.exe\""
		    CC="cl.exe"
		    CFLAGS="${CFLAGS} -I\"${MSSDK}/Include\" -I\"${MSSDK}/Include/crt\" -I\"${MSSDK}/Include/crt/sys\""
		    RC="\"${MSSDK}/bin/rc.exe\""
		    lflags="-nologo -MACHINE:${MACHINE} -LIBPATH:\"${MSSDK}/Lib/${MACHINE}\""
		    LINKBIN="\"${PATH64}/link.exe\""
		    RC="rc.exe"
		    lflags="${lflags} -nologo -MACHINE:${MACHINE} "
		    LINKBIN="link.exe"
		    CFLAGS_DEBUG="-nologo -Zi -Od -W3 ${runtime}d"
		    CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}"
		    # Avoid 'unresolved external symbol __security_cookie'
		    # errors, c.f. http://support.microsoft.com/?id=894573
		    TEA_ADD_LIBS([bufferoverflowU.lib])
		elif test "$doWince" != "no" ; then
		    CEBINROOT="${WCEROOT}/EVC/${OSVERSION}/bin"
		    if test "${TARGETCPU}" = "X86"; then
			CC="\"${CEBINROOT}/cl.exe\""
		    else
		else
			CC="\"${CEBINROOT}/cl${ARCH}.exe\""
		    fi
		    CFLAGS="$CFLAGS -I\"${CELIB_DIR}/inc\" -I\"${CEINCLUDE}\""
		    RC="\"${WCEROOT}/Common/EVC/bin/rc.exe\""
		    arch=`echo ${ARCH} | awk '{print tolower([$]0)}'`
		    defs="${ARCH} _${ARCH}_ ${arch} PALM_SIZE _MT _WINDOWS"
		    if test "${SHARED_BUILD}" = "1" ; then
			# Static CE builds require static celib as well
		    	defs="${defs} _DLL"
		    fi
		    for i in $defs ; do
			AC_DEFINE_UNQUOTED($i, 1, [WinCE def ]$i)
		    done
		    AC_DEFINE_UNQUOTED(_WIN32_WCE, $CEVERSION, [_WIN32_WCE version])
		    AC_DEFINE_UNQUOTED(UNDER_CE, $CEVERSION, [UNDER_CE version])
		    CFLAGS_DEBUG="-nologo -Zi -Od"
		    CFLAGS_OPTIMIZE="-nologo -Ox"
		    lversion=`echo ${CEVERSION} | sed -e 's/\(.\)\(..\)/\1\.\2/'`
		    lflags="-MACHINE:${ARCH} -LIBPATH:\"${CELIBPATH}\" -subsystem:windowsce,${lversion} -nologo"
		    LINKBIN="\"${CEBINROOT}/link.exe\""
		    AC_SUBST(CELIB_DIR)
		else
		    RC="rc"
		    lflags="-nologo"
		    lflags="${lflags} -nologo"
		    LINKBIN="link"
		    CFLAGS_DEBUG="-nologo -Z7 -Od -W3 -WX ${runtime}d"
		    CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}"
		fi
	    fi

	    if test "$GCC" = "yes"; then
		# mingw gcc mode
		AC_CHECK_TOOL(RC, windres)
		CFLAGS_DEBUG="-g"
		CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer"
		SHLIB_LD='${CC} -shared'
		UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
		LDFLAGS_CONSOLE="-wl,--subsystem,console ${lflags}"
		LDFLAGS_WINDOW="-wl,--subsystem,windows ${lflags}"

		AC_CACHE_CHECK(for cross-compile version of gcc,
			ac_cv_cross,
			AC_TRY_COMPILE([
			AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
			    #ifdef _WIN32
				#error cross-compiler
			    #endif
			], [],
			ac_cv_cross=yes,
			ac_cv_cross=no)
			]], [[]])],
			[ac_cv_cross=yes],
			[ac_cv_cross=no])
		      )
		      if test "$ac_cv_cross" = "yes"; then
			case "$do64bit" in
			    amd64|x64|yes)
				CC="x86_64-w64-mingw32-gcc"
				CC="x86_64-w64-mingw32-${CC}"
				LD="x86_64-w64-mingw32-ld"
				AR="x86_64-w64-mingw32-ar"
				RANLIB="x86_64-w64-mingw32-ranlib"
				RC="x86_64-w64-mingw32-windres"
			    ;;
			    arm64|aarch64)
				CC="aarch64-w64-mingw32-clang"
				LD="aarch64-w64-mingw32-ld"
				AR="aarch64-w64-mingw32-ar"
				RANLIB="aarch64-w64-mingw32-ranlib"
				RC="aarch64-w64-mingw32-windres"
			    ;;
			    *)
				CC="i686-w64-mingw32-gcc"
				CC="i686-w64-mingw32-${CC}"
				LD="i686-w64-mingw32-ld"
				AR="i686-w64-mingw32-ar"
				RANLIB="i686-w64-mingw32-ranlib"
				RC="i686-w64-mingw32-windres"
			    ;;
			esac
		fi
1330
1331
1332
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
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







-
-
-
-
-
-
+
+
-








-
+







		# For information on what debugtype is most useful, see:
		# http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp
		# and also
		# http://msdn2.microsoft.com/en-us/library/y0zzbyt4%28VS.80%29.aspx
		# This essentially turns it all on.
		LDFLAGS_DEBUG="-debug -debugtype:cv"
		LDFLAGS_OPTIMIZE="-release"
		if test "$doWince" != "no" ; then
		    LDFLAGS_CONSOLE="-link ${lflags}"
		    LDFLAGS_WINDOW=${LDFLAGS_CONSOLE}
		else
		    LDFLAGS_CONSOLE="-link -subsystem:console ${lflags}"
		    LDFLAGS_WINDOW="-link -subsystem:windows ${lflags}"
		LDFLAGS_CONSOLE="-link -subsystem:console ${lflags}"
		LDFLAGS_WINDOW="-link -subsystem:windows ${lflags}"
		fi
	    fi

	    SHLIB_SUFFIX=".dll"
	    SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.dll'

	    TCL_LIB_VERSIONS_OK=nodots
    	    ;;
	AIX-*)
	    AS_IF([test "${TCL_THREADS}" = "1" -a "$GCC" != "yes"], [
	    AS_IF([test "$GCC" != "yes"], [
		# AIX requires the _r compiler when gcc isn't being used
		case "${CC}" in
		    *_r|*_r\ *)
			# ok ...
			;;
		    *)
			# Make sure only first arg gets _r
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

1430
1431








1432
1433
1434
1435
1436
1437
1438
1439

1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459


1460
1461
1462


1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485

1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497





















1498
1499
1500
1501
1502
1503
1504


1505
1506
1507
1508
1509
1510
1511
1312
1313
1314
1315
1316
1317
1318

1319
1320

1321
1322

1323
1324
1325
1326
1327
1328
1329
1330
1331

1332
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
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463


1464
1465
1466
1467
1468
1469
1470
1471
1472







-
+

-
+

-
+








-
+















+
+
+
+
+
+
+












+


+
+
+
+
+
+
+
+







-
+











-
-
-
-





+
+

-
-
+
+







-
-
-
-











-
+












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





-
-
+
+







		])
	    ])

	    AS_IF([test "`uname -m`" = ia64], [
		# AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC
		SHLIB_LD="/usr/ccs/bin/ld -G -z text"
		AS_IF([test "$GCC" = yes], [
		    CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
		    CC_SEARCH_FLAGS='"-Wl,-R,${LIB_RUNTIME_DIR}"'
		], [
		    CC_SEARCH_FLAGS='-R${LIB_RUNTIME_DIR}'
		    CC_SEARCH_FLAGS='"-R${LIB_RUNTIME_DIR}"'
		])
		LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS='-R "${LIB_RUNTIME_DIR}"'
	    ], [
		AS_IF([test "$GCC" = yes], [
		    SHLIB_LD='${CC} -shared -Wl,-bexpall'
		], [
		    SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry"
		    LDFLAGS="$LDFLAGS -brtl"
		])
		SHLIB_LD="${SHLIB_LD} ${SHLIB_LD_FLAGS}"
		CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
		CC_SEARCH_FLAGS='"-L${LIB_RUNTIME_DIR}"'
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    ])
	    ;;
	BeOS*)
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_LD='${CC} -nostart'
	    SHLIB_SUFFIX=".so"

	    #-----------------------------------------------------------
	    # Check for inet_ntoa in -lbind, for BeOS (which also needs
	    # -lsocket, even if the network functions are in -lnet which
	    # is always linked to, for compatibility.
	    #-----------------------------------------------------------
	    AC_CHECK_LIB(bind, inet_ntoa, [LIBS="$LIBS -lbind -lsocket"])
	    ;;
	BSD/OS-2.1*|BSD/OS-3*)
	    SHLIB_CFLAGS=""
	    SHLIB_LD="shlicc -r"
	    SHLIB_SUFFIX=".so"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	BSD/OS-4.*)
	    SHLIB_CFLAGS="-export-dynamic -fPIC"
	    SHLIB_LD='${CC} -shared'
	    SHLIB_SUFFIX=".so"
	    LDFLAGS="$LDFLAGS -export-dynamic"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	CYGWIN_*)
	    SHLIB_CFLAGS=""
	    SHLIB_LD='${CC} -shared'
	    SHLIB_SUFFIX=".dll"
	    SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--out-implib,\$[@].a"
	    EXEEXT=".exe"
	    do64bit_ok=yes
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	dgux*)
	    SHLIB_CFLAGS="-K PIC"
	    SHLIB_LD='${CC} -G'
	    SHLIB_LD_LIBS=""
	    SHLIB_SUFFIX=".so"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	Haiku*)
	    LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_SUFFIX=".so"
	    SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS}'
	    SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS} -shared'
	    AC_CHECK_LIB(network, inet_ntoa, [LIBS="$LIBS -lnetwork"])
	    ;;
	HP-UX-*.11.*)
	    # Use updated header definitions where possible
	    AC_DEFINE(_XOPEN_SOURCE_EXTENDED, 1, [Do we want to use the XOPEN network library?])
	    # TEA specific: Needed by Tcl, but not most extensions
	    #AC_DEFINE(_XOPEN_SOURCE, 1, [Do we want to use the XOPEN network library?])
	    #LIBS="$LIBS -lxnet"               # Use the XOPEN network library

	    AS_IF([test "`uname -m`" = ia64], [
		SHLIB_SUFFIX=".so"
		# Use newer C++ library for C++ extensions
		#if test "$GCC" != "yes" ; then
		#   CPPFLAGS="-AA"
		#fi
	    ], [
		SHLIB_SUFFIX=".sl"
	    ])
	    AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no)
	    AS_IF([test "$tcl_ok" = yes], [
		SHLIB_CFLAGS="+z"
		SHLIB_LD="ld -b"
		LDFLAGS="$LDFLAGS -Wl,-E"
		CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.'
		LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.'
		CC_SEARCH_FLAGS='"-Wl,+s,+b,${LIB_RUNTIME_DIR}:."'
		LD_SEARCH_FLAGS='+s +b "${LIB_RUNTIME_DIR}:."'
		LD_LIBRARY_PATH_VAR="SHLIB_PATH"
	    ])
	    AS_IF([test "$GCC" = yes], [
		SHLIB_LD='${CC} -shared'
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    ], [
		CFLAGS="$CFLAGS -z"
		# Users may want PA-RISC 1.1/2.0 portable code - needs HP cc
		#CFLAGS="$CFLAGS +DAportable"
		SHLIB_CFLAGS="+z"
		SHLIB_LD="ld -b"
	    ])

	    # Check to enable 64-bit flags for compiler/linker
	    AS_IF([test "$do64bit" = "yes"], [
		AS_IF([test "$GCC" = yes], [
		    case `${CC} -dumpmachine` in
			hppa64*)
			    # 64-bit gcc in use.  Fix flags for GNU ld.
			    do64bit_ok=yes
			    SHLIB_LD='${CC} -shared'
			    AS_IF([test $doRpath = yes], [
				CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
				CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'])
			    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
			    ;;
			*)
			    AC_MSG_WARN([64bit mode not supported with GCC on $system])
			    ;;
		    esac
		], [
		    do64bit_ok=yes
		    CFLAGS="$CFLAGS +DD64"
		    LDFLAGS_ARCH="+DD64"
		])
	    ]) ;;
	HP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*)
	    SHLIB_SUFFIX=".sl"
	    AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no)
	    AS_IF([test "$tcl_ok" = yes], [
		SHLIB_CFLAGS="+z"
		SHLIB_LD="ld -b"
		SHLIB_LD_LIBS=""
		LDFLAGS="$LDFLAGS -Wl,-E"
		CC_SEARCH_FLAGS='"-Wl,+s,+b,${LIB_RUNTIME_DIR}:."'
		LD_SEARCH_FLAGS='+s +b "${LIB_RUNTIME_DIR}:."'
		LD_LIBRARY_PATH_VAR="SHLIB_PATH"
	    ]) ;;
	IRIX-5.*)
	    SHLIB_CFLAGS=""
	    SHLIB_LD="ld -shared -rdata_shared"
	    SHLIB_SUFFIX=".so"
	    AC_LIBOBJ(mkstemp)
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
		LD_SEARCH_FLAGS='-rpath "${LIB_RUNTIME_DIR}"'])
	    ;;
	IRIX-6.*)
	    SHLIB_CFLAGS=""
	    SHLIB_LD="ld -n32 -shared -rdata_shared"
	    SHLIB_SUFFIX=".so"
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
		LD_SEARCH_FLAGS='-rpath "${LIB_RUNTIME_DIR}"'])
	    AS_IF([test "$GCC" = yes], [
		CFLAGS="$CFLAGS -mabi=n32"
		LDFLAGS="$LDFLAGS -mabi=n32"
	    ], [
		case $system in
		    IRIX-6.3)
			# Use to build 6.2 compatible binaries on 6.3.
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
1546
1547
1548
1549
1550

1551











1552
1553

1554
1555
1556
1557
1558
1559

1560

1561
1562
1563
1564
1565
1566
1567
1480
1481
1482
1483
1484
1485
1486


1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502

1503
1504
1505
1506
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







-
-
+
+














-
+







-
+

+
+
+
+
+
+
+
+
+
+
+

-
+






+
-
+







	    ])
	    ;;
	IRIX64-6.*)
	    SHLIB_CFLAGS=""
	    SHLIB_LD="ld -n32 -shared -rdata_shared"
	    SHLIB_SUFFIX=".so"
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
		LD_SEARCH_FLAGS='-rpath "${LIB_RUNTIME_DIR}"'])

	    # Check to enable 64-bit flags for compiler/linker

	    AS_IF([test "$do64bit" = yes], [
	        AS_IF([test "$GCC" = yes], [
	            AC_MSG_WARN([64bit mode not supported by gcc])
	        ], [
	            do64bit_ok=yes
	            SHLIB_LD="ld -64 -shared -rdata_shared"
	            CFLAGS="$CFLAGS -64"
	            LDFLAGS_ARCH="-64"
	        ])
	    ])
	    ;;
	Linux*|GNU*|NetBSD-Debian)
	Linux*|GNU*|NetBSD-Debian|DragonFly-*|FreeBSD-*)
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_SUFFIX=".so"

	    # TEA specific:
	    CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer"

	    # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS
	    SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS_DEFAULT}'
	    SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS_DEFAULT} -shared'
	    LDFLAGS="$LDFLAGS -Wl,--export-dynamic"

	    case $system in
	    DragonFly-*|FreeBSD-*)
		AS_IF([test "${TCL_THREADS}" = "1"], [
		    # The -pthread needs to go in the LDFLAGS, not LIBS
		    LIBS=`echo $LIBS | sed s/-pthread//`
		    CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
		    LDFLAGS="$LDFLAGS $PTHREAD_LIBS"])
	    ;;
            esac

	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'])
	    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    AS_IF([test "`uname -m`" = "alpha"], [CFLAGS="$CFLAGS -mieee"])
	    AS_IF([test $do64bit = yes], [
		AC_CACHE_CHECK([if compiler accepts -m64 flag], tcl_cv_cc_m64, [
		    hold_cflags=$CFLAGS
		    CFLAGS="$CFLAGS -m64"
		    AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
		    AC_TRY_LINK(,, tcl_cv_cc_m64=yes, tcl_cv_cc_m64=no)
			    [tcl_cv_cc_m64=yes],[tcl_cv_cc_m64=no])
		    CFLAGS=$hold_cflags])
		AS_IF([test $tcl_cv_cc_m64 = yes], [
		    CFLAGS="$CFLAGS -m64"
		    do64bit_ok=yes
		])
	   ])

1576
1577
1578
1579
1580
1581
1582
1583
1584


1585
1586
1587
1588
1589

1590
1591
1592

1593
1594
1595
1596
1597
1598
1599
1600
1601
1602










1603
1604
1605
1606
1607
1608
1609
1610

1611
1612
1613
1614
1615
1616
1617




1618
1619
1620
1621
1622
1623
1624
1625
1626

1627
1628
1629
1630

1631
1632
1633
1634
1635
1636




1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685


1686
1687
1688
1689
1690
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
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
1574
1575








1576







1577
1578
1579
1580

1581
1582
1583
1584
1585
1586
1587

1588
1589
1590
1591

1592
1593





1594
1595
1596
1597



























1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617


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


1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651

1652
1653
1654
1655
1656
1657
1658
1659
1660




1661
1662
1663
1664
1665


1666
1667
1668
1669
1670
1671
1672
1673
1674







-
-
+
+




-
+
-
-
-
+


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







-
+



-
+

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




















-
-
+
+










-
-
+
+



















+
-
+








-
-
-
-





-
-
+
+







	Lynx*)
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_SUFFIX=".so"
	    CFLAGS_OPTIMIZE=-02
	    SHLIB_LD='${CC} -shared'
	    LD_FLAGS="-Wl,--export-dynamic"
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
		LD_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'])
	    ;;
	OpenBSD-*)
	    arch=`arch -s`
	    case "$arch" in
	    vax)
	    alpha|sparc64)
		SHLIB_SUFFIX=""
		SHARED_LIB_SUFFIX=""
		LDFLAGS=""
		SHLIB_CFLAGS="-fPIC"
		;;
	    *)
		SHLIB_CFLAGS="-fPIC"
		SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
		SHLIB_SUFFIX=".so"
		AS_IF([test $doRpath = yes], [
		    CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
		SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}'
		LDFLAGS="-Wl,-export-dynamic"
		SHLIB_CFLAGS="-fpic"
		;;
	    esac
	    SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared'
	    SHLIB_SUFFIX=".so"
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'])
	    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so${SHLIB_VERSION}'
	    LDFLAGS="$LDFLAGS -Wl,-export-dynamic"
		;;
	    esac
	    case "$arch" in
	    vax)
		CFLAGS_OPTIMIZE="-O1"
		;;
	    *)
		CFLAGS_OPTIMIZE="-O2"
	    CFLAGS_OPTIMIZE="-O2"
		;;
	    esac
	    AS_IF([test "${TCL_THREADS}" = "1"], [
		# On OpenBSD:	Compile with -pthread
		#		Don't link with -lpthread
		LIBS=`echo $LIBS | sed s/-lpthread//`
		CFLAGS="$CFLAGS -pthread"
	    # On OpenBSD:	Compile with -pthread
	    #		Don't link with -lpthread
	    LIBS=`echo $LIBS | sed s/-lpthread//`
	    CFLAGS="$CFLAGS -pthread"
	    ])
	    # OpenBSD doesn't do version numbers with dots.
	    UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
	    TCL_LIB_VERSIONS_OK=nodots
	    ;;
	NetBSD-*)
	    # NetBSD has ELF and can use 'cc -shared' to build shared libs
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
	    SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared'
	    SHLIB_SUFFIX=".so"
	    LDFLAGS="$LDFLAGS -export-dynamic"
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'])
	    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    AS_IF([test "${TCL_THREADS}" = "1"], [
		# The -pthread needs to go in the CFLAGS, not LIBS
		LIBS=`echo $LIBS | sed s/-pthread//`
		CFLAGS="$CFLAGS -pthread"
	    	LDFLAGS="$LDFLAGS -pthread"
	    # The -pthread needs to go in the CFLAGS, not LIBS
	    LIBS=`echo $LIBS | sed s/-pthread//`
	    CFLAGS="$CFLAGS -pthread"
	    LDFLAGS="$LDFLAGS -pthread"
	    ])
	    ;;
	FreeBSD-*)
	    # This configuration from FreeBSD Ports.
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_LD="${CC} -shared"
	    TCL_SHLIB_LD_EXTRAS="-Wl,-soname=\$[@]"
	    TK_SHLIB_LD_EXTRAS="-Wl,-soname,\$[@]"
	    SHLIB_SUFFIX=".so"
	    LDFLAGS=""
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
	    AS_IF([test "${TCL_THREADS}" = "1"], [
		# The -pthread needs to go in the LDFLAGS, not LIBS
		LIBS=`echo $LIBS | sed s/-pthread//`
		CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
		LDFLAGS="$LDFLAGS $PTHREAD_LIBS"])
	    case $system in
	    FreeBSD-3.*)
		# Version numbers are dot-stripped by system policy.
		TCL_TRIM_DOTS=`echo ${VERSION} | tr -d .`
		UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
		SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so'
		TCL_LIB_VERSIONS_OK=nodots
		;;
	    esac
	    ;;
	Darwin-*)
	    CFLAGS_OPTIMIZE="-Os"
	    SHLIB_CFLAGS="-fno-common"
	    # To avoid discrepancies between what headers configure sees during
	    # preprocessing tests and compiling tests, move any -isysroot and
	    # -mmacosx-version-min flags from CFLAGS to CPPFLAGS:
	    CPPFLAGS="${CPPFLAGS} `echo " ${CFLAGS}" | \
		awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \
		if ([$]i~/^(isysroot|mmacosx-version-min)/) print "-"[$]i}'`"
	    CFLAGS="`echo " ${CFLAGS}" | \
		awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \
		if (!([$]i~/^(isysroot|mmacosx-version-min)/)) print "-"[$]i}'`"
	    AS_IF([test $do64bit = yes], [
		case `arch` in
		    ppc)
			AC_CACHE_CHECK([if compiler accepts -arch ppc64 flag],
				tcl_cv_cc_arch_ppc64, [
			    hold_cflags=$CFLAGS
			    CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"
			    AC_TRY_LINK(,, tcl_cv_cc_arch_ppc64=yes,
				    tcl_cv_cc_arch_ppc64=no)
			    AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
				    [tcl_cv_cc_arch_ppc64=yes],[tcl_cv_cc_arch_ppc64=no])
			    CFLAGS=$hold_cflags])
			AS_IF([test $tcl_cv_cc_arch_ppc64 = yes], [
			    CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"
			    do64bit_ok=yes
			]);;
		    i386)
			AC_CACHE_CHECK([if compiler accepts -arch x86_64 flag],
				tcl_cv_cc_arch_x86_64, [
			    hold_cflags=$CFLAGS
			    CFLAGS="$CFLAGS -arch x86_64"
			    AC_TRY_LINK(,, tcl_cv_cc_arch_x86_64=yes,
				    tcl_cv_cc_arch_x86_64=no)
			    AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
				    [tcl_cv_cc_arch_x86_64=yes],[tcl_cv_cc_arch_x86_64=no])
			    CFLAGS=$hold_cflags])
			AS_IF([test $tcl_cv_cc_arch_x86_64 = yes], [
			    CFLAGS="$CFLAGS -arch x86_64"
			    do64bit_ok=yes
			]);;
		    *)
			AC_MSG_WARN([Don't know how enable 64-bit on architecture `arch`]);;
		esac
	    ], [
		# Check for combined 32-bit and 64-bit fat build
		AS_IF([echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64) ' \
		    && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) '], [
		    fat_32_64=yes])
	    ])
	    # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS
	    SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS_DEFAULT}'
	    AC_CACHE_CHECK([if ld accepts -single_module flag], tcl_cv_ld_single_module, [
		hold_ldflags=$LDFLAGS
		LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module"
		AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[int i;]])],
		AC_TRY_LINK(, [int i;], tcl_cv_ld_single_module=yes, tcl_cv_ld_single_module=no)
			[tcl_cv_ld_single_module=yes],[tcl_cv_ld_single_module=no])
		LDFLAGS=$hold_ldflags])
	    AS_IF([test $tcl_cv_ld_single_module = yes], [
		SHLIB_LD="${SHLIB_LD} -Wl,-single_module"
	    ])
	    # TEA specific: link shlib with current and compatibility version flags
	    vers=`echo ${PACKAGE_VERSION} | sed -e 's/^\([[0-9]]\{1,5\}\)\(\(\.[[0-9]]\{1,3\}\)\{0,2\}\).*$/\1\2/p' -e d`
	    SHLIB_LD="${SHLIB_LD} -current_version ${vers:-0} -compatibility_version ${vers:-0}"
	    SHLIB_SUFFIX=".dylib"
	    # Don't use -prebind when building for Mac OS X 10.4 or later only:
	    AS_IF([test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F '10\\.' '{print int([$]2)}'`" -lt 4 -a \
		"`echo "${CPPFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int([$]2)}'`" -lt 4], [
		LDFLAGS="$LDFLAGS -prebind"])
	    LDFLAGS="$LDFLAGS -headerpad_max_install_names"
	    AC_CACHE_CHECK([if ld accepts -search_paths_first flag],
		    tcl_cv_ld_search_paths_first, [
		hold_ldflags=$LDFLAGS
		LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
		AC_TRY_LINK(, [int i;], tcl_cv_ld_search_paths_first=yes,
			tcl_cv_ld_search_paths_first=no)
		AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[int i;]])],
			[tcl_cv_ld_search_paths_first=yes],[tcl_cv_ld_search_paths_first=no])
		LDFLAGS=$hold_ldflags])
	    AS_IF([test $tcl_cv_ld_search_paths_first = yes], [
		LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
	    ])
	    AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [
		AC_DEFINE(MODULE_SCOPE, [__private_extern__],
		    [Compiler support for module scope symbols])
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
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







-
-
+
+











-
-
+
+







		AS_IF([test "${TEA_WINDOWINGSYSTEM}" = x11], [
		    AC_CACHE_CHECK([for 64-bit X11], tcl_cv_lib_x11_64, [
			for v in CFLAGS CPPFLAGS LDFLAGS; do
			    eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"'
			done
			CPPFLAGS="$CPPFLAGS -I/usr/X11R6/include"
			LDFLAGS="$LDFLAGS -L/usr/X11R6/lib -lX11"
			AC_TRY_LINK([#include <X11/Xlib.h>], [XrmInitialize();],
			    tcl_cv_lib_x11_64=yes, tcl_cv_lib_x11_64=no)
			AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <X11/Xlib.h>]], [[XrmInitialize();]])],
			    [tcl_cv_lib_x11_64=yes],[tcl_cv_lib_x11_64=no])
			for v in CFLAGS CPPFLAGS LDFLAGS; do
			    eval $v'="$hold_'$v'"'
			done])
		])
		AS_IF([test "${TEA_WINDOWINGSYSTEM}" = aqua], [
		    AC_CACHE_CHECK([for 64-bit Tk], tcl_cv_lib_tk_64, [
			for v in CFLAGS CPPFLAGS LDFLAGS; do
			    eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"'
			done
			CPPFLAGS="$CPPFLAGS -DUSE_TCL_STUBS=1 -DUSE_TK_STUBS=1 ${TCL_INCLUDES} ${TK_INCLUDES}"
			LDFLAGS="$LDFLAGS ${TCL_STUB_LIB_SPEC} ${TK_STUB_LIB_SPEC}"
			AC_TRY_LINK([#include <tk.h>], [Tk_InitStubs(NULL, "", 0);],
			    tcl_cv_lib_tk_64=yes, tcl_cv_lib_tk_64=no)
			AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <tk.h>]], [[Tk_InitStubs(NULL, "", 0);]])],
			    [tcl_cv_lib_tk_64=yes],[tcl_cv_lib_tk_64=no])
			for v in CFLAGS CPPFLAGS LDFLAGS; do
			    eval $v'="$hold_'$v'"'
			done])
		])
		# remove 64-bit arch flags from CFLAGS et al. if configuration
		# does not support 64-bit.
		AS_IF([test "$tcl_cv_lib_tk_64" = no -o "$tcl_cv_lib_x11_64" = no], [
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
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







-
+




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







	    AS_IF([test "$SHARED_BUILD" = 1], [
	        SHLIB_LD='ld -shared -expect_unresolved "*"'
	    ], [
	        SHLIB_LD='ld -non_shared -expect_unresolved "*"'
	    ])
	    SHLIB_SUFFIX=".so"
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
		LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
	    AS_IF([test "$GCC" = yes], [CFLAGS="$CFLAGS -mieee"], [
		CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee"])
	    # see pthread_intro(3) for pthread support on osf1, k.furukawa
	    AS_IF([test "${TCL_THREADS}" = 1], [
		CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE"
		CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64"
		LIBS=`echo $LIBS | sed s/-lpthreads//`
		AS_IF([test "$GCC" = yes], [
		    LIBS="$LIBS -lpthread -lmach -lexc"
		], [
		    CFLAGS="$CFLAGS -pthread"
		    LDFLAGS="$LDFLAGS -pthread"
	    CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE"
	    CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64"
	    LIBS=`echo $LIBS | sed s/-lpthreads//`
	    AS_IF([test "$GCC" = yes], [
		LIBS="$LIBS -lpthread -lmach -lexc"
	    ], [
		CFLAGS="$CFLAGS -pthread"
		LDFLAGS="$LDFLAGS -pthread"
		])
	    ])
	    ;;
	QNX-6*)
	    # QNX RTP
	    # This may work for all QNX, but it was only reported for v6.
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_LD="ld -Bshareable -x"
1850
1851
1852
1853
1854
1855
1856
1857

1858
1859
1860
1861

1862
1863
1864
1865
1866
1867
1868
1779
1780
1781
1782
1783
1784
1785

1786
1787
1788
1789

1790
1791
1792
1793
1794
1795
1796
1797







-
+



-
+







	    AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1,
		[Do we really want to follow the standard? Yes we do!])

	    SHLIB_CFLAGS="-KPIC"
	    SHLIB_SUFFIX=".so"
	    AS_IF([test "$GCC" = yes], [
		SHLIB_LD='${CC} -shared'
		CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
		CC_SEARCH_FLAGS='"-Wl,-R,${LIB_RUNTIME_DIR}"'
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    ], [
		SHLIB_LD="/usr/ccs/bin/ld -G -z text"
		CC_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
		CC_SEARCH_FLAGS='-R "${LIB_RUNTIME_DIR}"'
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    ])
	    ;;
	SunOS-5*)
	    # Note: If _REENTRANT isn't defined, then Solaris
	    # won't define thread-safe library routines.

1920
1921
1922
1923
1924
1925
1926
1927

1928
1929
1930
1931
1932
1933
1934
1849
1850
1851
1852
1853
1854
1855

1856
1857
1858
1859
1860
1861
1862
1863







-
+







		    ])
		], [AC_MSG_WARN([64bit mode not supported for $arch])])])
	    ])

	    SHLIB_SUFFIX=".so"
	    AS_IF([test "$GCC" = yes], [
		SHLIB_LD='${CC} -shared'
		CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
		CC_SEARCH_FLAGS='"-Wl,-R,${LIB_RUNTIME_DIR}"'
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
		AS_IF([test "$do64bit_ok" = yes], [
		    AS_IF([test "$arch" = "sparcv9 sparc"], [
			# We need to specify -static-libgcc or we need to
			# add the path to the sparv9 libgcc.
			# JH: static-libgcc is necessary for core Tcl, but may
			# not be necessary for extensions.
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
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







-
-
+
+












+
-
+







		case $system in
		    SunOS-5.[[1-9]][[0-9]]*)
			# TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS
			SHLIB_LD='${CC} -G -z text ${LDFLAGS_DEFAULT}';;
		    *)
			SHLIB_LD='/usr/ccs/bin/ld -G -z text';;
		esac
		CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
		CC_SEARCH_FLAGS='"-Wl,-R,${LIB_RUNTIME_DIR}"'
		LD_SEARCH_FLAGS='-R "${LIB_RUNTIME_DIR}"'
	    ])
	    ;;
	UNIX_SV* | UnixWare-5*)
	    SHLIB_CFLAGS="-KPIC"
	    SHLIB_LD='${CC} -G'
	    SHLIB_LD_LIBS=""
	    SHLIB_SUFFIX=".so"
	    # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers
	    # that don't grok the -Bexport option.  Test that it does.
	    AC_CACHE_CHECK([for ld accepts -Bexport flag], tcl_cv_ld_Bexport, [
		hold_ldflags=$LDFLAGS
		LDFLAGS="$LDFLAGS -Wl,-Bexport"
		AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[int i;]])],
		AC_TRY_LINK(, [int i;], tcl_cv_ld_Bexport=yes, tcl_cv_ld_Bexport=no)
			[tcl_cv_ld_Bexport=yes],[tcl_cv_ld_Bexport=no])
	        LDFLAGS=$hold_ldflags])
	    AS_IF([test $tcl_cv_ld_Bexport = yes], [
		LDFLAGS="$LDFLAGS -Wl,-Bexport"
	    ])
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
1993
1994
1995
1996
1997
1998
1999
2000

2001
2002

2003
2004
2005
2006
2007
2008
2009
1923
1924
1925
1926
1927
1928
1929

1930
1931

1932
1933
1934
1935
1936
1937
1938
1939







-
+

-
+







    # libraries to the right flags for gcc, instead of those for the
    # standard manufacturer compiler.

    AS_IF([test "$GCC" = yes], [
	case $system in
	    AIX-*) ;;
	    BSD/OS*) ;;
	    CYGWIN_*|MINGW32_*) ;;
	    CYGWIN_*|MINGW32_*|MINGW64_*|MSYS_*) ;;
	    IRIX*) ;;
	    NetBSD-*|FreeBSD-*|OpenBSD-*) ;;
	    NetBSD-*|DragonFly-*|FreeBSD-*|OpenBSD-*) ;;
	    Darwin-*) ;;
	    SCO_SV-3.2*) ;;
	    windows) ;;
	    *) SHLIB_CFLAGS="-fPIC" ;;
	esac])

    AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [
2017
2018
2019
2020
2021
2022
2023
2024

2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042




2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057

2058
2059
2060
2061

2062
2063
2064
2065



2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078

2079
2080
2081
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
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
1984
1985
1986

1987
1988
1989
1990

1991
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



2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032

2033

2034
2035



2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058







-
+














-
-
-
-
+
+
+
+














-
+



-
+

-
-
-
+
+
+












-
+




-
+



-
-
-
+
+
+













-
+
-


-
-
-
+
+
+






+
+



+
+







    AS_IF([test "$UNSHARED_LIB_SUFFIX" = ""], [
    # TEA specific: use PACKAGE_VERSION instead of VERSION
    UNSHARED_LIB_SUFFIX='${PACKAGE_VERSION}.a'])

    if test "${GCC}" = "yes" -a ${SHLIB_SUFFIX} = ".dll"; then
	AC_CACHE_CHECK(for SEH support in compiler,
	    tcl_cv_seh,
	AC_TRY_RUN([
	AC_RUN_IFELSE([AC_LANG_SOURCE([[
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN

	    int main(int argc, char** argv) {
		int a, b = 0;
		__try {
		    a = 666 / b;
		}
		__except (EXCEPTION_EXECUTE_HANDLER) {
		    return 0;
		}
		return 1;
	    }
	],
	    tcl_cv_seh=yes,
	    tcl_cv_seh=no,
	    tcl_cv_seh=no)
	]])],
	    [tcl_cv_seh=yes],
	    [tcl_cv_seh=no],
	    [tcl_cv_seh=no])
	)
	if test "$tcl_cv_seh" = "no" ; then
	    AC_DEFINE(HAVE_NO_SEH, 1,
		    [Defined when mingw does not support SEH])
	fi

	#
	# Check to see if the excpt.h include file provided contains the
	# definition for EXCEPTION_DISPOSITION; if not, which is the case
	# with Cygwin's version as of 2002-04-10, define it to be int,
	# sufficient for getting the current code to work.
	#
	AC_CACHE_CHECK(for EXCEPTION_DISPOSITION support in include files,
	    tcl_cv_eh_disposition,
	    AC_TRY_COMPILE([
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#	    define WIN32_LEAN_AND_MEAN
#	    include <windows.h>
#	    undef WIN32_LEAN_AND_MEAN
	    ],[
	    ]], [[
		EXCEPTION_DISPOSITION x;
	    ],
		tcl_cv_eh_disposition=yes,
		tcl_cv_eh_disposition=no)
	    ]])],
		[tcl_cv_eh_disposition=yes],
		[tcl_cv_eh_disposition=no])
	)
	if test "$tcl_cv_eh_disposition" = "no" ; then
	AC_DEFINE(EXCEPTION_DISPOSITION, int,
		[Defined when cygwin/mingw does not support EXCEPTION DISPOSITION])
	fi

	# Check to see if winnt.h defines CHAR, SHORT, and LONG
	# even if VOID has already been #defined. The win32api
	# used by mingw and cygwin is known to do this.

	AC_CACHE_CHECK(for winnt.h that ignores VOID define,
	    tcl_cv_winnt_ignore_void,
	    AC_TRY_COMPILE([
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#define VOID void
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
	    ], [
	    ]], [[
		CHAR c;
		SHORT s;
		LONG l;
	    ],
        tcl_cv_winnt_ignore_void=yes,
        tcl_cv_winnt_ignore_void=no)
	    ]])],
        [tcl_cv_winnt_ignore_void=yes],
        [tcl_cv_winnt_ignore_void=no])
	)
	if test "$tcl_cv_winnt_ignore_void" = "yes" ; then
	    AC_DEFINE(HAVE_WINNT_IGNORE_VOID, 1,
		    [Defined when cygwin/mingw ignores VOID define in winnt.h])
	fi
    fi

	# See if the compiler supports casting to a union type.
	# This is used to stop gcc from printing a compiler
	# warning when initializing a union member.

	AC_CACHE_CHECK(for cast to union support,
	    tcl_cv_cast_to_union,
	    AC_TRY_COMPILE([],
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
	    [
		  union foo { int i; double d; };
		  union foo f = (union foo) (int) 0;
	    ],
	    tcl_cv_cast_to_union=yes,
	    tcl_cv_cast_to_union=no)
	    ]])],
	    [tcl_cv_cast_to_union=yes],
	    [tcl_cv_cast_to_union=no])
	)
	if test "$tcl_cv_cast_to_union" = "yes"; then
	    AC_DEFINE(HAVE_CAST_TO_UNION, 1,
		    [Defined when compiler supports casting to union type.])
	fi

	AC_CHECK_HEADER(stdbool.h, [AC_DEFINE(HAVE_STDBOOL_H, 1, [Do we have <stdbool.h>?])],)

    AC_SUBST(CFLAGS_DEBUG)
    AC_SUBST(CFLAGS_OPTIMIZE)
    AC_SUBST(CFLAGS_WARNING)
    AC_SUBST(LDFLAGS_DEBUG)
    AC_SUBST(LDFLAGS_OPTIMIZE)

    AC_SUBST(STLIB_LD)
    AC_SUBST(SHLIB_LD)

    AC_SUBST(SHLIB_LD_LIBS)
    AC_SUBST(SHLIB_CFLAGS)

2151
2152
2153
2154
2155
2156
2157
2158

2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169

2170
2171

2172
2173
2174
2175
2176
2177
2178
2179
2180
2181

2182
2183
2184

2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195

2196
2197
2198

2199
2200
2201
2202
2203
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
2234
2235
2236
2237
2238
2239
2240
2241
2242

2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
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
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







-
+










-
+

-
+









-
+


-
+










-
+


-
+












-
+


-
+











-
+


-
+












-
+








-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







#		USE_TERMIO
#		USE_SGTTY
#--------------------------------------------------------------------

AC_DEFUN([TEA_SERIAL_PORT], [
    AC_CHECK_HEADERS(sys/modem.h)
    AC_CACHE_CHECK([termios vs. termio vs. sgtty], tcl_cv_api_serial, [
    AC_TRY_RUN([
    AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <termios.h>

int main() {
    struct termios t;
    if (tcgetattr(0, &t) == 0) {
	cfsetospeed(&t, 0);
	t.c_cflag |= PARENB | PARODD | CSIZE | CSTOPB;
	return 0;
    }
    return 1;
}], tcl_cv_api_serial=termios, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
}]])],[tcl_cv_api_serial=termios],[tcl_cv_api_serial=no],[tcl_cv_api_serial=no])
    if test $tcl_cv_api_serial = no ; then
	AC_TRY_RUN([
	AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <termio.h>

int main() {
    struct termio t;
    if (ioctl(0, TCGETA, &t) == 0) {
	t.c_cflag |= CBAUD | PARENB | PARODD | CSIZE | CSTOPB;
	return 0;
    }
    return 1;
}], tcl_cv_api_serial=termio, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
}]])],[tcl_cv_api_serial=termio],[tcl_cv_api_serial=no],[tcl_cv_api_serial=no])
    fi
    if test $tcl_cv_api_serial = no ; then
	AC_TRY_RUN([
	AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <sgtty.h>

int main() {
    struct sgttyb t;
    if (ioctl(0, TIOCGETP, &t) == 0) {
	t.sg_ospeed = 0;
	t.sg_flags |= ODDP | EVENP | RAW;
	return 0;
    }
    return 1;
}], tcl_cv_api_serial=sgtty, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
}]])],[tcl_cv_api_serial=sgtty],[tcl_cv_api_serial=no],[tcl_cv_api_serial=no])
    fi
    if test $tcl_cv_api_serial = no ; then
	AC_TRY_RUN([
	AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <termios.h>
#include <errno.h>

int main() {
    struct termios t;
    if (tcgetattr(0, &t) == 0
	|| errno == ENOTTY || errno == ENXIO || errno == EINVAL) {
	cfsetospeed(&t, 0);
	t.c_cflag |= PARENB | PARODD | CSIZE | CSTOPB;
	return 0;
    }
    return 1;
}], tcl_cv_api_serial=termios, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
}]])],[tcl_cv_api_serial=termios],[tcl_cv_api_serial=no],[tcl_cv_api_serial=no])
    fi
    if test $tcl_cv_api_serial = no; then
	AC_TRY_RUN([
	AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <termio.h>
#include <errno.h>

int main() {
    struct termio t;
    if (ioctl(0, TCGETA, &t) == 0
	|| errno == ENOTTY || errno == ENXIO || errno == EINVAL) {
	t.c_cflag |= CBAUD | PARENB | PARODD | CSIZE | CSTOPB;
	return 0;
    }
    return 1;
    }], tcl_cv_api_serial=termio, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
    }]])],[tcl_cv_api_serial=termio],[tcl_cv_api_serial=no],[tcl_cv_api_serial=no])
    fi
    if test $tcl_cv_api_serial = no; then
	AC_TRY_RUN([
	AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <sgtty.h>
#include <errno.h>

int main() {
    struct sgttyb t;
    if (ioctl(0, TIOCGETP, &t) == 0
	|| errno == ENOTTY || errno == ENXIO || errno == EINVAL) {
	t.sg_ospeed = 0;
	t.sg_flags |= ODDP | EVENP | RAW;
	return 0;
    }
    return 1;
}], tcl_cv_api_serial=sgtty, tcl_cv_api_serial=none, tcl_cv_api_serial=none)
}]])],[tcl_cv_api_serial=sgtty],[tcl_cv_api_serial=none],[tcl_cv_api_serial=none])
    fi])
    case $tcl_cv_api_serial in
	termios) AC_DEFINE(USE_TERMIOS, 1, [Use the termios API for serial lines]);;
	termio)  AC_DEFINE(USE_TERMIO, 1, [Use the termio API for serial lines]);;
	sgtty)   AC_DEFINE(USE_SGTTY, 1, [Use the sgtty API for serial lines]);;
    esac
])

#--------------------------------------------------------------------
# TEA_MISSING_POSIX_HEADERS
#
#	Supply substitutes for missing POSIX header files.  Special
#	notes:
#	    - stdlib.h doesn't define strtol, strtoul, or
#	      strtod in some versions of SunOS
#	    - some versions of string.h don't declare procedures such
#	      as strstr
#
# Arguments:
#	none
#
# Results:
#
#	Defines some of the following vars:
#		NO_DIRENT_H
#		NO_ERRNO_H
#		NO_VALUES_H
#		HAVE_LIMITS_H or NO_LIMITS_H
#		NO_STDLIB_H
#		NO_STRING_H
#		NO_SYS_WAIT_H
#		NO_DLFCN_H
#		HAVE_SYS_PARAM_H
#
#		HAVE_STRING_H ?
#
# tkUnixPort.h checks for HAVE_LIMITS_H, so do both HAVE and
# CHECK on limits.h
#--------------------------------------------------------------------

AC_DEFUN([TEA_MISSING_POSIX_HEADERS], [
    AC_CACHE_CHECK([dirent.h], tcl_cv_dirent_h, [
    AC_TRY_LINK([#include <sys/types.h>
#include <dirent.h>], [
#ifndef _POSIX_SOURCE
#   ifdef __Lynx__
	/*
	 * Generate compilation error to make the test fail:  Lynx headers
	 * are only valid if really in the POSIX environment.
	 */

	missing_procedure();
#   endif
#endif
DIR *d;
struct dirent *entryPtr;
char *p;
d = opendir("foobar");
entryPtr = readdir(d);
p = entryPtr->d_name;
closedir(d);
], tcl_cv_dirent_h=yes, tcl_cv_dirent_h=no)])

    if test $tcl_cv_dirent_h = no; then
	AC_DEFINE(NO_DIRENT_H, 1, [Do we have <dirent.h>?])
    fi

    # TEA specific:
    AC_CHECK_HEADER(errno.h, , [AC_DEFINE(NO_ERRNO_H, 1, [Do we have <errno.h>?])])
    AC_CHECK_HEADER(float.h, , [AC_DEFINE(NO_FLOAT_H, 1, [Do we have <float.h>?])])
    AC_CHECK_HEADER(values.h, , [AC_DEFINE(NO_VALUES_H, 1, [Do we have <values.h>?])])
    AC_CHECK_HEADER(limits.h,
	[AC_DEFINE(HAVE_LIMITS_H, 1, [Do we have <limits.h>?])],
	[AC_DEFINE(NO_LIMITS_H, 1, [Do we have <limits.h>?])])
    AC_CHECK_HEADER(stdlib.h, tcl_ok=1, tcl_ok=0)
    AC_EGREP_HEADER(strtol, stdlib.h, , tcl_ok=0)
    AC_EGREP_HEADER(strtoul, stdlib.h, , tcl_ok=0)
    AC_EGREP_HEADER(strtod, stdlib.h, , tcl_ok=0)
    if test $tcl_ok = 0; then
	AC_DEFINE(NO_STDLIB_H, 1, [Do we have <stdlib.h>?])
    fi
    AC_CHECK_HEADER(string.h, tcl_ok=1, tcl_ok=0)
    AC_EGREP_HEADER(strstr, string.h, , tcl_ok=0)
    AC_EGREP_HEADER(strerror, string.h, , tcl_ok=0)

    # See also memmove check below for a place where NO_STRING_H can be
    # set and why.

    if test $tcl_ok = 0; then
	AC_DEFINE(NO_STRING_H, 1, [Do we have <string.h>?])
    fi

    AC_CHECK_HEADER(sys/wait.h, , [AC_DEFINE(NO_SYS_WAIT_H, 1, [Do we have <sys/wait.h>?])])
    AC_CHECK_HEADER(dlfcn.h, , [AC_DEFINE(NO_DLFCN_H, 1, [Do we have <dlfcn.h>?])])

    # OS/390 lacks sys/param.h (and doesn't need it, by chance).
    AC_HAVE_HEADERS(sys/param.h)
])

#--------------------------------------------------------------------
# TEA_PATH_X
#
#	Locate the X11 header files and the X11 library archive.  Try
#	the ac_path_x macro first, but if it doesn't find the X stuff
#	(e.g. because there's no xmkmf program) then check through
#	a list of possible directories.  Under some conditions the
2370
2371
2372
2373
2374
2375
2376
2377

2378
2379
2380
2381
2382
2383
2384
2385
2386
2387

2388
2389
2390
2391
2392
2393
2394
2212
2213
2214
2215
2216
2217
2218

2219
2220
2221
2222
2223
2224
2225
2226
2227
2228

2229
2230
2231
2232
2233
2234
2235
2236







-
+









-
+







])

AC_DEFUN([TEA_PATH_UNIX_X], [
    AC_PATH_X
    not_really_there=""
    if test "$no_x" = ""; then
	if test "$x_includes" = ""; then
	    AC_TRY_CPP([#include <X11/Xlib.h>], , not_really_there="yes")
	    AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include <X11/Xlib.h>]])],[],[not_really_there="yes"])
	else
	    if test ! -r $x_includes/X11/Xlib.h; then
		not_really_there="yes"
	    fi
	fi
    fi
    if test "$no_x" = "yes" -o "$not_really_there" = "yes"; then
	AC_MSG_CHECKING([for X11 header files])
	found_xincludes="no"
	AC_TRY_CPP([#include <X11/Xlib.h>], found_xincludes="yes", found_xincludes="no")
	AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include <X11/Xlib.h>]])],[found_xincludes="yes"],[found_xincludes="no"])
	if test "$found_xincludes" = "no"; then
	    dirs="/usr/unsupported/include /usr/local/include /usr/X386/include /usr/X11R6/include /usr/X11R5/include /usr/include/X11R5 /usr/include/X11R4 /usr/openwin/include /usr/X11/include /usr/sww/include"
	    for i in $dirs ; do
		if test -r $i/X11/Xlib.h; then
		    AC_MSG_RESULT([$i])
		    XINCLUDES=" -I$i"
		    found_xincludes="yes"
2486
2487
2488
2489
2490
2491
2492

2493
2494
2495
2496
2497
2498
2499
2500

2501
2502
2503
2504



2505
2506
2507
2508
2509
2510
2511



2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522



2523
2524
2525


2526
2527
2528
2529
2530
2531
2532
2533
2534



2535
2536
2537


2538
2539
2540
2541
2542
2543
2544
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342

2343
2344
2345


2346
2347
2348
2349
2350
2351
2352
2353


2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365


2366
2367
2368
2369


2370
2371
2372
2373
2374
2375
2376
2377
2378


2379
2380
2381
2382


2383
2384
2385
2386
2387
2388
2389
2390
2391







+







-
+


-
-
+
+
+





-
-
+
+
+









-
-
+
+
+

-
-
+
+







-
-
+
+
+

-
-
+
+







# Results:
#
#	Defines some of the following vars:
#		USE_DELTA_FOR_TZ
#		HAVE_TM_GMTOFF
#		HAVE_TM_TZADJ
#		HAVE_TIMEZONE_VAR
#
#--------------------------------------------------------------------

AC_DEFUN([TEA_TIME_HANDLER], [
    AC_CHECK_HEADERS(sys/time.h)
    AC_HEADER_TIME
    AC_STRUCT_TIMEZONE

    AC_CHECK_FUNCS(gmtime_r localtime_r)
    AC_CHECK_FUNCS(gmtime_r localtime_r mktime)

    AC_CACHE_CHECK([tm_tzadj in struct tm], tcl_cv_member_tm_tzadj, [
	AC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_tzadj;],
	    tcl_cv_member_tm_tzadj=yes, tcl_cv_member_tm_tzadj=no)])
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <time.h>]], [[struct tm tm; (void)tm.tm_tzadj;]])],
	    [tcl_cv_member_tm_tzadj=yes],
	    [tcl_cv_member_tm_tzadj=no])])
    if test $tcl_cv_member_tm_tzadj = yes ; then
	AC_DEFINE(HAVE_TM_TZADJ, 1, [Should we use the tm_tzadj field of struct tm?])
    fi

    AC_CACHE_CHECK([tm_gmtoff in struct tm], tcl_cv_member_tm_gmtoff, [
	AC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_gmtoff;],
	    tcl_cv_member_tm_gmtoff=yes, tcl_cv_member_tm_gmtoff=no)])
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <time.h>]], [[struct tm tm; (void)tm.tm_gmtoff;]])],
	    [tcl_cv_member_tm_gmtoff=yes],
	    [tcl_cv_member_tm_gmtoff=no])])
    if test $tcl_cv_member_tm_gmtoff = yes ; then
	AC_DEFINE(HAVE_TM_GMTOFF, 1, [Should we use the tm_gmtoff field of struct tm?])
    fi

    #
    # Its important to include time.h in this check, as some systems
    # (like convex) have timezone functions, etc.
    #
    AC_CACHE_CHECK([long timezone variable], tcl_cv_timezone_long, [
	AC_TRY_COMPILE([#include <time.h>],
	    [extern long timezone;
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <time.h>
#include <stdlib.h>]],
	[[extern long timezone;
	    timezone += 1;
	    exit (0);],
	    tcl_cv_timezone_long=yes, tcl_cv_timezone_long=no)])
	    exit (0);]])],
	    [tcl_cv_timezone_long=yes], [tcl_cv_timezone_long=no])])
    if test $tcl_cv_timezone_long = yes ; then
	AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?])
    else
	#
	# On some systems (eg IRIX 6.2), timezone is a time_t and not a long.
	#
	AC_CACHE_CHECK([time_t timezone variable], tcl_cv_timezone_time, [
	    AC_TRY_COMPILE([#include <time.h>],
		[extern time_t timezone;
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <time.h>
#include <stdlib.h>]],
	    [[extern time_t timezone;
		timezone += 1;
		exit (0);],
		tcl_cv_timezone_time=yes, tcl_cv_timezone_time=no)])
		exit (0);]])],
		[tcl_cv_timezone_time=yes], [tcl_cv_timezone_time=no])])
	if test $tcl_cv_timezone_time = yes ; then
	    AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?])
	fi
    fi
])

#--------------------------------------------------------------------
2560
2561
2562
2563
2564
2565
2566
2567


2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587


2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601


2602
2603




2604

2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619

2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2407
2408
2409
2410
2411
2412
2413

2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433


2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447


2448
2449
2450
2451
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







-
+
+


















-
-
+
+












-
-
+
+


+
+
+
+
-
+
-



-
-
-
-
-
-
-
-
-


+






-
-



-







#		strtod (=fixstrtod)
#--------------------------------------------------------------------

AC_DEFUN([TEA_BUGGY_STRTOD], [
    AC_CHECK_FUNC(strtod, tcl_strtod=1, tcl_strtod=0)
    if test "$tcl_strtod" = 1; then
	AC_CACHE_CHECK([for Solaris2.4/Tru64 strtod bugs], tcl_cv_strtod_buggy,[
	    AC_TRY_RUN([
	    AC_RUN_IFELSE([AC_LANG_SOURCE([[
		#include <stdlib.h>
		extern double strtod();
		int main() {
		    char *infString="Inf", *nanString="NaN", *spaceString=" ";
		    char *term;
		    double value;
		    value = strtod(infString, &term);
		    if ((term != infString) && (term[-1] == 0)) {
			exit(1);
		    }
		    value = strtod(nanString, &term);
		    if ((term != nanString) && (term[-1] == 0)) {
			exit(1);
		    }
		    value = strtod(spaceString, &term);
		    if (term == (spaceString+1)) {
			exit(1);
		    }
		    exit(0);
		}], tcl_cv_strtod_buggy=ok, tcl_cv_strtod_buggy=buggy,
		    tcl_cv_strtod_buggy=buggy)])
		}]])], [tcl_cv_strtod_buggy=ok], [tcl_cv_strtod_buggy=buggy],
		    [tcl_cv_strtod_buggy=buggy])])
	if test "$tcl_cv_strtod_buggy" = buggy; then
	    AC_LIBOBJ([fixstrtod])
	    USE_COMPAT=1
	    AC_DEFINE(strtod, fixstrtod, [Do we want to use the strtod() in compat?])
	fi
    fi
])

#--------------------------------------------------------------------
# TEA_TCL_LINK_LIBS
#
#	Search for the libraries needed to link the Tcl shell.
#	Things like the math library (-lm) and socket stuff (-lsocket vs.
#	-lnsl) are dealt with here.
#	Things like the math library (-lm), socket stuff (-lsocket vs.
#	-lnsl), zlib (-lz) and libtommath (-ltommath) are dealt with here.
#
# Arguments:
#	None.
#
# Results:
#
#	Requires the following vars to be set in the Makefile:
#	Might append to the following vars:
#		DL_LIBS (not in TEA, only needed in core)
#		LIBS
#		MATH_LIBS
#
# Results:
#
#	Substitutes the following vars:
#		TCL_LIBS
#		MATH_LIBS
#
#	Might append to the following vars:
#		LIBS
#
#	Might define the following vars:
#		HAVE_NET_ERRNO_H
#
#--------------------------------------------------------------------

AC_DEFUN([TEA_TCL_LINK_LIBS], [
    #--------------------------------------------------------------------
    # On a few very rare systems, all of the libm.a stuff is
    # already in libc.a.  Set compiler flags accordingly.
    # Also, Linux requires the "ieee" library for math to work
    # right (and it must appear before "-lm").
    #--------------------------------------------------------------------

    AC_CHECK_FUNC(sin, MATH_LIBS="", MATH_LIBS="-lm")
    AC_CHECK_LIB(ieee, main, [MATH_LIBS="-lieee $MATH_LIBS"])

    #--------------------------------------------------------------------
    # Interactive UNIX requires -linet instead of -lsocket, plus it
    # needs net/errno.h to define the socket-related error codes.
    #--------------------------------------------------------------------

    AC_CHECK_LIB(inet, main, [LIBS="$LIBS -linet"])
2666
2667
2668
2669
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
2704
2705



2706
2707
2708
2709
2710
2711
2712
2506
2507
2508
2509
2510
2511
2512

2513



2514
2515


2516

2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539

2540




2541
2542
2543
2544
2545
2546
2547
2548
2549
2550







-
+
-
-
-
+
+
-
-
+
-

















+




+
-
+
-
-
-
-
+
+
+







    if test "$tcl_checkBoth" = 1; then
	tk_oldLibs=$LIBS
	LIBS="$LIBS -lsocket -lnsl"
	AC_CHECK_FUNC(accept, tcl_checkNsl=0, [LIBS=$tk_oldLibs])
    fi
    AC_CHECK_FUNC(gethostbyname, , [AC_CHECK_LIB(nsl, gethostbyname,
	    [LIBS="$LIBS -lnsl"])])

    AC_CHECK_FUNC(mp_log_u32, , [AC_CHECK_LIB(tommath, mp_log_u32,
    # TEA specific: Don't perform the eval of the libraries here because
    # DL_LIBS won't be set until we call TEA_CONFIG_CFLAGS

	    [LIBS="$LIBS -ltommath"])])
    AC_CHECK_FUNC(deflateSetHeader, , [AC_CHECK_LIB(z, deflateSetHeader,
    TCL_LIBS='${DL_LIBS} ${LIBS} ${MATH_LIBS}'
    AC_SUBST(TCL_LIBS)
	    [LIBS="$LIBS -lz"])])
    AC_SUBST(MATH_LIBS)
])

#--------------------------------------------------------------------
# TEA_TCL_EARLY_FLAGS
#
#	Check for what flags are needed to be passed so the correct OS
#	features are available.
#
# Arguments:
#	None
#
# Results:
#
#	Might define the following vars:
#		_ISOC99_SOURCE
#		_LARGEFILE64_SOURCE
#		_LARGEFILE_SOURCE64
#
#--------------------------------------------------------------------

AC_DEFUN([TEA_TCL_EARLY_FLAG],[
    AC_CACHE_VAL([tcl_cv_flag_]translit($1,[A-Z],[a-z]),
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[$2]], [[$3]])],
	AC_TRY_COMPILE([$2], $3, [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no,
	    [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no,[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[[#define ]$1[ 1
	    AC_TRY_COMPILE([[#define ]$1[ 1
]$2], $3,
		[tcl_cv_flag_]translit($1,[A-Z],[a-z])=yes,
		[tcl_cv_flag_]translit($1,[A-Z],[a-z])=no)))
]$2]], [[$3]])],
	[tcl_cv_flag_]translit($1,[A-Z],[a-z])=yes,
	[tcl_cv_flag_]translit($1,[A-Z],[a-z])=no)]))
    if test ["x${tcl_cv_flag_]translit($1,[A-Z],[a-z])[}" = "xyes"] ; then
	AC_DEFINE($1, 1, [Add the ]$1[ flag when building])
	tcl_flags="$tcl_flags $1"
    fi
])

AC_DEFUN([TEA_TCL_EARLY_FLAGS],[
2734
2735
2736
2737
2738
2739
2740
2741

2742
2743

2744
2745
2746
2747
2748
2749
2750
2751
2752
2753



2754
2755
2756
2757
2758



2759
2760
2761


2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
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
2572
2573
2574
2575
2576
2577
2578

2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589



2590
2591
2592
2593
2594



2595
2596
2597
2598


2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612



2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629



2630
2631
2632
2633
2634
2635
2636
2637
2638
2639



2640
2641
2642
2643
2644
2645
2646
2647
2648
2649







-
+


+







-
-
-
+
+
+


-
-
-
+
+
+

-
-
+
+












-
-
-
+
+
+




+
+
+
+
+
+
+
+
+

-
-
-
+
+
+







-
-
-
+
+
+







#	None
#
# Results:
#
#	Might define the following vars:
#		TCL_WIDE_INT_IS_LONG
#		TCL_WIDE_INT_TYPE
#		HAVE_STRUCT_DIRENT64
#		HAVE_STRUCT_DIRENT64, HAVE_DIR64
#		HAVE_STRUCT_STAT64
#		HAVE_TYPE_OFF64_T
#
#--------------------------------------------------------------------

AC_DEFUN([TEA_TCL_64BIT_FLAGS], [
    AC_MSG_CHECKING([for 64-bit integer type])
    AC_CACHE_VAL(tcl_cv_type_64bit,[
	tcl_cv_type_64bit=none
	# See if the compiler knows natively about __int64
	AC_TRY_COMPILE(,[__int64 value = (__int64) 0;],
	    tcl_type_64bit=__int64, tcl_type_64bit="long long")
	# See if we should use long anyway  Note that we substitute in the
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[__int64 value = (__int64) 0;]])],
	    [tcl_type_64bit=__int64],[tcl_type_64bit="long long"])
	# See if we could use long anyway  Note that we substitute in the
	# type that is our current guess for a 64-bit type inside this check
	# program, so it should be modified only carefully...
        AC_TRY_COMPILE(,[switch (0) {
            case 1: case (sizeof(]${tcl_type_64bit}[)==sizeof(long)): ;
        }],tcl_cv_type_64bit=${tcl_type_64bit})])
        AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[switch (0) {
            case 1: case (sizeof(${tcl_type_64bit})==sizeof(long)): ;
        }]])],[tcl_cv_type_64bit=${tcl_type_64bit}],[])])
    if test "${tcl_cv_type_64bit}" = none ; then
	AC_DEFINE(TCL_WIDE_INT_IS_LONG, 1, [Are wide integers to be implemented with C 'long's?])
	AC_MSG_RESULT([using long])
	AC_DEFINE(TCL_WIDE_INT_IS_LONG, 1, [Do 'long' and 'long long' have the same size (64-bit)?])
	AC_MSG_RESULT([yes])
    elif test "${tcl_cv_type_64bit}" = "__int64" \
		-a "${TEA_PLATFORM}" = "windows" ; then
	# TEA specific: We actually want to use the default tcl.h checks in
	# this case to handle both TCL_WIDE_INT_TYPE and TCL_LL_MODIFIER*
	AC_MSG_RESULT([using Tcl header defaults])
    else
	AC_DEFINE_UNQUOTED(TCL_WIDE_INT_TYPE,${tcl_cv_type_64bit},
	    [What type should be used to define wide integers?])
	AC_MSG_RESULT([${tcl_cv_type_64bit}])

	# Now check for auxiliary declarations
	AC_CACHE_CHECK([for struct dirent64], tcl_cv_struct_dirent64,[
	    AC_TRY_COMPILE([#include <sys/types.h>
#include <dirent.h>],[struct dirent64 p;],
		tcl_cv_struct_dirent64=yes,tcl_cv_struct_dirent64=no)])
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
#include <dirent.h>]], [[struct dirent64 p;]])],
		[tcl_cv_struct_dirent64=yes],[tcl_cv_struct_dirent64=no])])
	if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then
	    AC_DEFINE(HAVE_STRUCT_DIRENT64, 1, [Is 'struct dirent64' in <sys/types.h>?])
	fi

	AC_CACHE_CHECK([for DIR64], tcl_cv_DIR64,[
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
#include <dirent.h>]], [[struct dirent64 *p; DIR64 d = opendir64(".");
            p = readdir64(d); rewinddir64(d); closedir64(d);]])],
		[tcl_cv_DIR64=yes], [tcl_cv_DIR64=no])])
	if test "x${tcl_cv_DIR64}" = "xyes" ; then
	    AC_DEFINE(HAVE_DIR64, 1, [Is 'DIR64' in <sys/types.h>?])
	fi

	AC_CACHE_CHECK([for struct stat64], tcl_cv_struct_stat64,[
	    AC_TRY_COMPILE([#include <sys/stat.h>],[struct stat64 p;
],
		tcl_cv_struct_stat64=yes,tcl_cv_struct_stat64=no)])
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/stat.h>]], [[struct stat64 p;
]])],
		[tcl_cv_struct_stat64=yes], [tcl_cv_struct_stat64=no])])
	if test "x${tcl_cv_struct_stat64}" = "xyes" ; then
	    AC_DEFINE(HAVE_STRUCT_STAT64, 1, [Is 'struct stat64' in <sys/stat.h>?])
	fi

	AC_CHECK_FUNCS(open64 lseek64)
	AC_MSG_CHECKING([for off64_t])
	AC_CACHE_VAL(tcl_cv_type_off64_t,[
	    AC_TRY_COMPILE([#include <sys/types.h>],[off64_t offset;
],
		tcl_cv_type_off64_t=yes,tcl_cv_type_off64_t=no)])
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>]], [[off64_t offset;
]])],
		[tcl_cv_type_off64_t=yes], [tcl_cv_type_off64_t=no])])
	dnl Define HAVE_TYPE_OFF64_T only when the off64_t type and the
	dnl functions lseek64 and open64 are defined.
	if test "x${tcl_cv_type_off64_t}" = "xyes" && \
	        test "x${ac_cv_func_lseek64}" = "xyes" && \
	        test "x${ac_cv_func_open64}" = "xyes" ; then
	    AC_DEFINE(HAVE_TYPE_OFF64_T, 1, [Is off64_t in <sys/types.h>?])
	    AC_MSG_RESULT([yes])
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845

2846
2847

2848
2849
2850

2851
2852
2853
2854
2855
2856
2857
2858

2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869


2870
2871
2872
2873
2874
2875
2876

2877
2878
2879
2880
2881
2882
2883
2684
2685
2686
2687
2688
2689
2690



2691
2692

2693
2694
2695

2696
2697







2698

2699
2700
2701
2702
2703
2704
2705
2706


2707
2708
2709
2710
2711
2712

2713

2714
2715
2716
2717
2718
2719
2720
2721







-
-
-
+

-
+


-
+

-
-
-
-
-
-
-
+
-








-
-
+
+




-

-
+







# EXEEXT
#	Select the executable extension based on the host type.  This
#	is a lightweight replacement for AC_EXEEXT that doesn't require
#	a compiler.
#------------------------------------------------------------------------

AC_DEFUN([TEA_INIT], [
    # TEA extensions pass this us the version of TEA they think they
    # are compatible with.
    TEA_VERSION="3.9"
    TEA_VERSION="3.13"

    AC_MSG_CHECKING([for correct TEA configuration])
    AC_MSG_CHECKING([TEA configuration])
    if test x"${PACKAGE_NAME}" = x ; then
	AC_MSG_ERROR([
The PACKAGE_NAME variable must be defined by your TEA configure.in])
The PACKAGE_NAME variable must be defined by your TEA configure.ac])
    fi
    if test x"$1" = x ; then
	AC_MSG_ERROR([
TEA version not specified.])
    elif test "$1" != "${TEA_VERSION}" ; then
	AC_MSG_RESULT([warning: requested TEA version "$1", have "${TEA_VERSION}"])
    else
	AC_MSG_RESULT([ok (TEA ${TEA_VERSION})])
    AC_MSG_RESULT([ok (TEA ${TEA_VERSION})])
    fi

    # If the user did not set CFLAGS, set it now to keep macros
    # like AC_PROG_CC and AC_TRY_COMPILE from adding "-g -O2".
    if test "${CFLAGS+set}" != "set" ; then
	CFLAGS=""
    fi

    case "`uname -s`" in
	*win32*|*WIN32*|*MINGW32_*)
	    AC_CHECK_PROG(CYGPATH, cygpath, cygpath -w, echo)
	*win32*|*WIN32*|*MINGW32_*|*MINGW64_*|*MSYS_*)
	    AC_CHECK_PROG(CYGPATH, cygpath, cygpath -m, echo)
	    EXEEXT=".exe"
	    TEA_PLATFORM="windows"
	    ;;
	*CYGWIN_*)
	    CYGPATH=echo
	    EXEEXT=".exe"
	    # TEA_PLATFORM is determined later in LOAD_TCLCONFIG
	    # CYGPATH and TEA_PLATFORM are determined later in LOAD_TCLCONFIG
	    ;;
	*)
	    CYGPATH=echo
	    # Maybe we are cross-compiling....
	    case ${host_alias} in
		*mingw32*)
		EXEEXT=".exe"
2903
2904
2905
2906
2907
2908
2909


2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921



2922
2923
2924
2925
2926
2927
2928
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771







+
+












+
+
+







    AC_MSG_NOTICE([configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}])

    AC_SUBST(EXEEXT)
    AC_SUBST(CYGPATH)

    # This package name must be replaced statically for AC_SUBST to work
    AC_SUBST(PKG_LIB_FILE)
    AC_SUBST(PKG_LIB_FILE8)
    AC_SUBST(PKG_LIB_FILE9)
    # Substitute STUB_LIB_FILE in case package creates a stub library too.
    AC_SUBST(PKG_STUB_LIB_FILE)

    # We AC_SUBST these here to ensure they are subst'ed,
    # in case the user doesn't call TEA_ADD_...
    AC_SUBST(PKG_STUB_SOURCES)
    AC_SUBST(PKG_STUB_OBJECTS)
    AC_SUBST(PKG_TCL_SOURCES)
    AC_SUBST(PKG_HEADERS)
    AC_SUBST(PKG_INCLUDES)
    AC_SUBST(PKG_LIBS)
    AC_SUBST(PKG_CFLAGS)

    # Configure the installer.
    TEA_INSTALLER
])

#------------------------------------------------------------------------
# TEA_ADD_SOURCES --
#
#	Specify one or more source files.  Users should check for
#	the right platform before adding to their list.
3107
3108
3109
3110
3111
3112
3113
3114

3115
3116
3117
3118
3119
3120
3121
2950
2951
2952
2953
2954
2955
2956

2957
2958
2959
2960
2961
2962
2963
2964







-
+







#		PKG_LIBS
#------------------------------------------------------------------------
AC_DEFUN([TEA_ADD_LIBS], [
    vars="$@"
    for i in $vars; do
	if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then
	    # Convert foo.lib to -lfoo for GCC.  No-op if not *.lib
	    i=`echo "$i" | sed -e 's/^\([[^-]].*\)\.lib[$]/-l\1/i'`
	    i=`echo "$i" | sed -e 's/^\([[^-]].*\)\.[[lL]][[iI]][[bB]][$]/-l\1/'`
	fi
	PKG_LIBS="$PKG_LIBS $i"
    done
    AC_SUBST(PKG_LIBS)
])

#------------------------------------------------------------------------
3190
3191
3192
3193
3194
3195
3196
3197

3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3033
3034
3035
3036
3037
3038
3039

3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055









3056
3057
3058
3059
3060
3061
3062







-
+















-
-
-
-
-
-
-
-
-







    fi
])

#------------------------------------------------------------------------
# TEA_SETUP_COMPILER_CC --
#
#	Do compiler checks the way we want.  This is just a replacement
#	for AC_PROG_CC in TEA configure.in files to make them cleaner.
#	for AC_PROG_CC in TEA configure.ac files to make them cleaner.
#
# Arguments:
#	none
#
# Results:
#
#	Sets up CC var and other standard bits we need to make executables.
#------------------------------------------------------------------------
AC_DEFUN([TEA_SETUP_COMPILER_CC], [
    # Don't put any macros that use the compiler (e.g. AC_TRY_COMPILE)
    # in this macro, they need to go into TEA_SETUP_COMPILER instead.

    AC_PROG_CC
    AC_PROG_CPP

    INSTALL="\$(SHELL) \$(srcdir)/tclconfig/install-sh -c"
    AC_SUBST(INSTALL)
    INSTALL_DATA="\${INSTALL} -m 644"
    AC_SUBST(INSTALL_DATA)
    INSTALL_PROGRAM="\${INSTALL}"
    AC_SUBST(INSTALL_PROGRAM)
    INSTALL_SCRIPT="\${INSTALL}"
    AC_SUBST(INSTALL_SCRIPT)

    #--------------------------------------------------------------------
    # Checks to see if the make program sets the $MAKE variable.
    #--------------------------------------------------------------------

    AC_PROG_MAKE_SET

    #--------------------------------------------------------------------
3261
3262
3263
3264
3265
3266
3267
3268

3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3095
3096
3097
3098
3099
3100
3101

3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113








3114
3115
3116
3117
3118
3119
3120







-
+











-
-
-
-
-
-
-
-







    # It makes compiling go faster.  (This is only a performance feature.)
    #------------------------------------------------------------------------

    if test -z "$no_pipe" -a -n "$GCC"; then
	AC_CACHE_CHECK([if the compiler understands -pipe],
	    tcl_cv_cc_pipe, [
	    hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe"
	    AC_TRY_COMPILE(,, tcl_cv_cc_pipe=yes, tcl_cv_cc_pipe=no)
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[tcl_cv_cc_pipe=yes],[tcl_cv_cc_pipe=no])
	    CFLAGS=$hold_cflags])
	if test $tcl_cv_cc_pipe = yes; then
	    CFLAGS="$CFLAGS -pipe"
	fi
    fi

    #--------------------------------------------------------------------
    # Common compiler flag setup
    #--------------------------------------------------------------------

    AC_C_BIGENDIAN
    if test "${TEA_PLATFORM}" = "unix" ; then
	TEA_TCL_LINK_LIBS
	TEA_MISSING_POSIX_HEADERS
	# Let the user call this, because if it triggers, they will
	# need a compat/strtod.c that is correct.  Users can also
	# use Tcl_GetDouble(FromObj) instead.
	#TEA_BUGGY_STRTOD
    fi
])

#------------------------------------------------------------------------
# TEA_MAKE_LIB --
#
#	Generate a line that can be used to build a shared/unshared library
#	in a platform independent manner.
3311
3312
3313
3314
3315
3316
3317
3318

3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333

3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348







3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359


3360

3361
3362
3363
3364

3365



3366
3367
3368

3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381


3382

3383
3384


3385

3386
3387
3388

3389
3390
3391
3392
3393
3394
3395
3137
3138
3139
3140
3141
3142
3143

3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158

3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194

3195
3196

3197

3198
3199
3200
3201
3202
3203
3204

3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220

3221
3222
3223
3224
3225

3226
3227
3228

3229
3230
3231
3232
3233
3234
3235
3236







-
+














-
+















+
+
+
+
+
+
+











+
+
-
+

-

-
+

+
+
+


-
+













+
+
-
+


+
+
-
+


-
+







#	VC_MANIFEST_EMBED_DLL Makefile rule for embedded VC manifest in DLL
#	VC_MANIFEST_EMBED_EXE Makefile rule for embedded VC manifest in EXE
#------------------------------------------------------------------------

AC_DEFUN([TEA_MAKE_LIB], [
    if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes"; then
	MAKE_STATIC_LIB="\${STLIB_LD} -out:\[$]@ \$(PKG_OBJECTS)"
	MAKE_SHARED_LIB="\${SHLIB_LD} \${SHLIB_LD_LIBS} \${LDFLAGS_DEFAULT} -out:\[$]@ \$(PKG_OBJECTS)"
	MAKE_SHARED_LIB="\${SHLIB_LD} \${LDFLAGS} \${LDFLAGS_DEFAULT} -out:\[$]@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}"
	AC_EGREP_CPP([manifest needed], [
#if defined(_MSC_VER) && _MSC_VER >= 1400
print("manifest needed")
#endif
	], [
	# Could do a CHECK_PROG for mt, but should always be with MSVC8+
	VC_MANIFEST_EMBED_DLL="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest -outputresource:\[$]@\;2 ; fi"
	VC_MANIFEST_EMBED_EXE="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest -outputresource:\[$]@\;1 ; fi"
	MAKE_SHARED_LIB="${MAKE_SHARED_LIB} ; ${VC_MANIFEST_EMBED_DLL}"
	TEA_ADD_CLEANFILES([*.manifest])
	])
	MAKE_STUB_LIB="\${STLIB_LD} -nodefaultlib -out:\[$]@ \$(PKG_STUB_OBJECTS)"
    else
	MAKE_STATIC_LIB="\${STLIB_LD} \[$]@ \$(PKG_OBJECTS)"
	MAKE_SHARED_LIB="\${SHLIB_LD} -o \[$]@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}"
	MAKE_SHARED_LIB="\${SHLIB_LD} \${LDFLAGS} \${LDFLAGS_DEFAULT} -o \[$]@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}"
	MAKE_STUB_LIB="\${STLIB_LD} \[$]@ \$(PKG_STUB_OBJECTS)"
    fi

    if test "${SHARED_BUILD}" = "1" ; then
	MAKE_LIB="${MAKE_SHARED_LIB} "
    else
	MAKE_LIB="${MAKE_STATIC_LIB} "
    fi

    #--------------------------------------------------------------------
    # Shared libraries and static libraries have different names.
    # Use the double eval to make sure any variables in the suffix is
    # substituted. (@@@ Might not be necessary anymore)
    #--------------------------------------------------------------------

    PACKAGE_LIB_PREFIX8="${PACKAGE_LIB_PREFIX}"
    PACKAGE_LIB_PREFIX9="${PACKAGE_LIB_PREFIX}tcl9"
    if test "${TCL_MAJOR_VERSION}" -gt 8 ; then
	PACKAGE_LIB_PREFIX="${PACKAGE_LIB_PREFIX9}"
    else
	PACKAGE_LIB_PREFIX="${PACKAGE_LIB_PREFIX8}"
    fi
    if test "${TEA_PLATFORM}" = "windows" ; then
	if test "${SHARED_BUILD}" = "1" ; then
	    # We force the unresolved linking of symbols that are really in
	    # the private libraries of Tcl and Tk.
	    if test x"${TK_BIN_DIR}" != x ; then
		SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}`\""
	    fi
	    SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}`\""
	    if test "$GCC" = "yes"; then
		SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -static-libgcc"
	    fi
	    eval eval "PKG_LIB_FILE8=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}"
	    eval eval "PKG_LIB_FILE9=${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}"
	    eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${SHARED_LIB_SUFFIX}"
	    eval eval "PKG_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}"
	else
	    eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}"
	    if test "$GCC" = "yes"; then
		PKG_LIB_FILE=lib${PKG_LIB_FILE}
		PACKAGE_LIB_PREFIX=lib${PACKAGE_LIB_PREFIX}
	    fi
	    eval eval "PKG_LIB_FILE8=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}"
	    eval eval "PKG_LIB_FILE9=${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}"
	    eval eval "PKG_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}"
	fi
	# Some packages build their own stubs libraries
	eval eval "PKG_STUB_LIB_FILE=${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}"
	eval eval "PKG_STUB_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}"
	if test "$GCC" = "yes"; then
	    PKG_STUB_LIB_FILE=lib${PKG_STUB_LIB_FILE}
	fi
	# These aren't needed on Windows (either MSVC or gcc)
	RANLIB=:
	RANLIB_STUB=:
    else
	RANLIB_STUB="${RANLIB}"
	if test "${SHARED_BUILD}" = "1" ; then
	    SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TCL_STUB_LIB_SPEC}"
	    if test x"${TK_BIN_DIR}" != x ; then
		SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TK_STUB_LIB_SPEC}"
	    fi
	    eval eval "PKG_LIB_FILE8=lib${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}"
	    eval eval "PKG_LIB_FILE9=lib${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}"
	    eval eval "PKG_LIB_FILE=lib${PACKAGE_NAME}${SHARED_LIB_SUFFIX}"
	    eval eval "PKG_LIB_FILE=lib${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}"
	    RANLIB=:
	else
	    eval eval "PKG_LIB_FILE=lib${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}"
	    eval eval "PKG_LIB_FILE=lib${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}"
	    eval eval "PKG_LIB_FILE=lib${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}"
	    eval eval "PKG_LIB_FILE=lib${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}"
	fi
	# Some packages build their own stubs libraries
	eval eval "PKG_STUB_LIB_FILE=lib${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}"
	eval eval "PKG_STUB_LIB_FILE=lib${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}"
    fi

    # These are escaped so that only CFLAGS is picked up at configure time.
    # The other values will be substituted at make time.
    CFLAGS="${CFLAGS} \${CFLAGS_DEFAULT} \${CFLAGS_WARNING}"
    if test "${SHARED_BUILD}" = "1" ; then
	CFLAGS="${CFLAGS} \${SHLIB_CFLAGS}"
3926
3927
3928
3929
3930
3931
3932

3933
3934
3935
3936
3937
3938
3939
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781







+







	    # check in a few common install locations
	    if test x"${ac_cv_c_$1config}" = x ; then
		for i in `ls -d ${libdir} 2>/dev/null` \
			`ls -d ${exec_prefix}/lib 2>/dev/null` \
			`ls -d ${prefix}/lib 2>/dev/null` \
			`ls -d /usr/local/lib 2>/dev/null` \
			`ls -d /usr/contrib/lib 2>/dev/null` \
			`ls -d /usr/pkg/lib 2>/dev/null` \
			`ls -d /usr/lib 2>/dev/null` \
			`ls -d /usr/lib64 2>/dev/null` \
			; do
		    if test -f "$i/$1Config.sh" ; then
			ac_cv_c_$1config=`(cd $i; pwd)`
			break
		    fi
4067
4068
4069
4070
4071
4072
4073
4074
4075


4076
4077
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
4107
4108








4109
4110
4111
4112
4113


































4114
4115





4116
4117
4118

4119
4120





4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132










4133
4134
4135
4136
















4137
4138

4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152




4153
4154
4155
4156
4157
4158
4159


















4160
4161
4162
4163


4164





4165

4166
4167
4168
3909
3910
3911
3912
3913
3914
3915


3916
3917
3918


3919
3920
3921






3922
3923
3924
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
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

4000


4001
4002
4003
4004
4005
4006











4007
4008
4009
4010
4011
4012
4013
4014
4015
4016




4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032


4033














4034
4035
4036
4037







4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055




4056
4057

4058
4059
4060
4061
4062
4063
4064
4065
4066
4067







-
-
+
+

-
-
+
+

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















-
+

-
+





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


-
+
-
-
+
+
+
+
+

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

+



    #--------------------------------------------------------------------
    # These are for $1Config.sh
    #--------------------------------------------------------------------

    # pkglibdir must be a fully qualified path and (not ${exec_prefix}/lib)
    eval pkglibdir="[$]{libdir}/$1${PACKAGE_VERSION}"
    if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then
	eval $1_LIB_FLAG="-l$1${PACKAGE_VERSION}${DBGX}"
	eval $1_STUB_LIB_FLAG="-l$1stub${PACKAGE_VERSION}${DBGX}"
	eval $1_LIB_FLAG="-l$1${PACKAGE_VERSION}"
	eval $1_STUB_LIB_FLAG="-l$1stub${PACKAGE_VERSION}"
    else
	eval $1_LIB_FLAG="-l$1`echo ${PACKAGE_VERSION} | tr -d .`${DBGX}"
	eval $1_STUB_LIB_FLAG="-l$1stub`echo ${PACKAGE_VERSION} | tr -d .`${DBGX}"
	eval $1_LIB_FLAG="-l$1`echo ${PACKAGE_VERSION} | tr -d .`"
	eval $1_STUB_LIB_FLAG="-l$1stub`echo ${PACKAGE_VERSION} | tr -d .`"
    fi
    $1_BUILD_LIB_SPEC="-L`pwd` ${$1_LIB_FLAG}"
    $1_LIB_SPEC="-L${pkglibdir} ${$1_LIB_FLAG}"
    $1_BUILD_STUB_LIB_SPEC="-L`pwd` [$]{$1_STUB_LIB_FLAG}"
    $1_STUB_LIB_SPEC="-L${pkglibdir} [$]{$1_STUB_LIB_FLAG}"
    $1_BUILD_STUB_LIB_PATH="`pwd`/[$]{PKG_STUB_LIB_FILE}"
    $1_STUB_LIB_PATH="${pkglibdir}/[$]{PKG_STUB_LIB_FILE}"
    $1_BUILD_LIB_SPEC="-L`$CYGPATH $(pwd)` ${$1_LIB_FLAG}"
    $1_LIB_SPEC="-L`$CYGPATH ${pkglibdir}` ${$1_LIB_FLAG}"
    $1_BUILD_STUB_LIB_SPEC="-L`$CYGPATH $(pwd)` [$]{$1_STUB_LIB_FLAG}"
    $1_STUB_LIB_SPEC="-L`$CYGPATH ${pkglibdir}` [$]{$1_STUB_LIB_FLAG}"
    $1_BUILD_STUB_LIB_PATH="`$CYGPATH $(pwd)`/[$]{PKG_STUB_LIB_FILE}"
    $1_STUB_LIB_PATH="`$CYGPATH ${pkglibdir}`/[$]{PKG_STUB_LIB_FILE}"

    AC_SUBST($1_BUILD_LIB_SPEC)
    AC_SUBST($1_LIB_SPEC)
    AC_SUBST($1_BUILD_STUB_LIB_SPEC)
    AC_SUBST($1_STUB_LIB_SPEC)
    AC_SUBST($1_BUILD_STUB_LIB_PATH)
    AC_SUBST($1_STUB_LIB_PATH)

    AC_SUBST(MAJOR_VERSION)
    AC_SUBST(MINOR_VERSION)
    AC_SUBST(PATCHLEVEL)
])


#------------------------------------------------------------------------
# TEA_PATH_CELIB --
# TEA_INSTALLER --
#
#	Locate Keuchel's celib emulation layer for targeting Win/CE
#	Configure the installer.
#
# Arguments:
#	none
#
# Results:
#	Substitutes the following vars:
#		INSTALL
#		INSTALL_DATA_DIR
#		INSTALL_DATA
#		INSTALL_PROGRAM
#		INSTALL_SCRIPT
#		INSTALL_LIBRARY
#------------------------------------------------------------------------
#
#	Adds the following arguments to configure:
#		--with-celib=...
#
#	Defines the following vars:

AC_DEFUN([TEA_INSTALLER], [
    INSTALL='$(SHELL) $(srcdir)/tclconfig/install-sh -c'
    INSTALL_DATA_DIR='${INSTALL} -d -m 755'
    INSTALL_DATA='${INSTALL} -m 644'
    INSTALL_PROGRAM='${INSTALL} -m 755'
    INSTALL_SCRIPT='${INSTALL} -m 755'

    TEA_CONFIG_SYSTEM
    case $system in
	HP-UX-*) INSTALL_LIBRARY='${INSTALL} -m 755' ;;
	      *) INSTALL_LIBRARY='${INSTALL} -m 644' ;;
    esac

    AC_SUBST(INSTALL)
    AC_SUBST(INSTALL_DATA_DIR)
    AC_SUBST(INSTALL_DATA)
    AC_SUBST(INSTALL_PROGRAM)
    AC_SUBST(INSTALL_SCRIPT)
    AC_SUBST(INSTALL_LIBRARY)
])

###
# Tip 430 - ZipFS Modifications
###
#------------------------------------------------------------------------
# TEA_ZIPFS_SUPPORT
#	Locate a zip encoder installed on the system path, or none.
#
# Arguments:
#	none
#
# Results:
#	Substitutes the following vars:
#		CELIB_DIR	Full path to the directory containing
#				the include and platform lib files
#       MACHER_PROG
#       ZIP_PROG
#       ZIP_PROG_OPTIONS
#       ZIP_PROG_VFSSEARCH
#       ZIP_INSTALL_OBJS
#------------------------------------------------------------------------

AC_DEFUN([TEA_PATH_CELIB], [
AC_DEFUN([TEA_ZIPFS_SUPPORT], [
    # First, look for one uninstalled.
    # the alternative search directory is invoked by --with-celib
    MACHER_PROG=""
    ZIP_PROG=""
    ZIP_PROG_OPTIONS=""
    ZIP_PROG_VFSSEARCH=""
    ZIP_INSTALL_OBJS=""

    if test x"${no_celib}" = x ; then
	# we reset no_celib in case something fails here
	no_celib=true
	AC_ARG_WITH(celib,[  --with-celib=DIR        use Windows/CE support library from DIR], with_celibconfig=${withval})
	AC_MSG_CHECKING([for Windows/CE celib directory])
	AC_CACHE_VAL(ac_cv_c_celibconfig,[
	    # First check to see if --with-celibconfig was specified.
	    if test x"${with_celibconfig}" != x ; then
		if test -d "${with_celibconfig}/inc" ; then
		    ac_cv_c_celibconfig=`(cd ${with_celibconfig}; pwd)`
		else
    AC_MSG_CHECKING([for macher])
    AC_CACHE_VAL(ac_cv_path_macher, [
    search_path=`echo ${PATH} | sed -e 's/:/ /g'`
    for dir in $search_path ; do
        for j in `ls -r $dir/macher 2> /dev/null` \
            `ls -r $dir/macher 2> /dev/null` ; do
        if test x"$ac_cv_path_macher" = x ; then
            if test -f "$j" ; then
            ac_cv_path_macher=$j
            break
		    AC_MSG_ERROR([${with_celibconfig} directory doesn't contain inc directory])
		fi
	    fi

            fi
        fi
        done
    done
    ])
    if test -f "$ac_cv_path_macher" ; then
        MACHER_PROG="$ac_cv_path_macher"
        AC_MSG_RESULT([$MACHER_PROG])
        AC_MSG_RESULT([Found macher in environment])
    fi
    AC_MSG_CHECKING([for zip])
    AC_CACHE_VAL(ac_cv_path_zip, [
    search_path=`echo ${PATH} | sed -e 's/:/ /g'`
    for dir in $search_path ; do
        for j in `ls -r $dir/zip 2> /dev/null` \
            `ls -r $dir/zip 2> /dev/null` ; do
	    # then check for a celib library
	    if test x"${ac_cv_c_celibconfig}" = x ; then
        if test x"$ac_cv_path_zip" = x ; then
		for i in \
			../celib-palm-3.0 \
			../celib \
			../../celib-palm-3.0 \
			../../celib \
			`ls -dr ../celib-*3.[[0-9]]* 2>/dev/null` \
			${srcdir}/../celib-palm-3.0 \
			${srcdir}/../celib \
			`ls -dr ${srcdir}/../celib-*3.[[0-9]]* 2>/dev/null` \
			; do
		    if test -d "$i/inc" ; then
			ac_cv_c_celibconfig=`(cd $i; pwd)`
			break
		    fi
            if test -f "$j" ; then
            ac_cv_path_zip=$j
            break
            fi
		done
	    fi
	])
	if test x"${ac_cv_c_celibconfig}" = x ; then
	    AC_MSG_ERROR([Cannot find celib support library directory])
	else
	    no_celib=
        fi
        done
    done
    ])
    if test -f "$ac_cv_path_zip" ; then
        ZIP_PROG="$ac_cv_path_zip"
        AC_MSG_RESULT([$ZIP_PROG])
        ZIP_PROG_OPTIONS="-rq"
        ZIP_PROG_VFSSEARCH="*"
        AC_MSG_RESULT([Found INFO Zip in environment])
        # Use standard arguments for zip
    else
        # It is not an error if an installed version of Zip can't be located.
        # We can use the locally distributed minizip instead
        ZIP_PROG="./minizip${EXEEXT_FOR_BUILD}"
        ZIP_PROG_OPTIONS="-o -r"
        ZIP_PROG_VFSSEARCH="*"
        ZIP_INSTALL_OBJS="minizip${EXEEXT_FOR_BUILD}"
	    CELIB_DIR=${ac_cv_c_celibconfig}
	    CELIB_DIR=`echo "$CELIB_DIR" | sed -e 's!\\\!/!g'`
	    AC_MSG_RESULT([found $CELIB_DIR])
	fi
        AC_MSG_RESULT([No zip found on PATH. Building minizip])
    fi
    fi
    AC_SUBST(MACHER_PROG)
    AC_SUBST(ZIP_PROG)
    AC_SUBST(ZIP_PROG_OPTIONS)
    AC_SUBST(ZIP_PROG_VFSSEARCH)
    AC_SUBST(ZIP_INSTALL_OBJS)
])

# Local Variables:
# mode: autoconf
# End:

Changes to autoconf/tea/win/makefile.vc.

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







-
+

-
+






-
-
-








-
+




















+
+
+
+
+
+
+
+
+
+
+




















-
+















-
-
+
+


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








# nmakehelp -V <file> <tag> will search the file for tag, skips until a
#	number and returns all character until a character not in [0-9.ab]
#	is read.

!if [echo REM = This file is generated from Makefile.vc > versions.vc]
!endif
# get project version from row "AC_INIT([sqlite], [3.7.14])"
# get project version from row "AC_INIT([sqlite], [3.x.y])"
!if [echo DOTVERSION = \>> versions.vc] \
   && [nmakehlp -V ..\configure.in AC_INIT >> versions.vc]
   && [nmakehlp -V ..\configure.ac AC_INIT >> versions.vc]
!endif
!include "versions.vc"

VERSION         = $(DOTVERSION:.=)
STUBPREFIX      = $(PROJECT)stub

DLLOBJS = \
	$(TMP_DIR)\tclsqlite3.obj

#-------------------------------------------------------------------------
# Target names and paths ( shouldn't need changing )
#-------------------------------------------------------------------------

BINROOT		= .
ROOT            = ..

PRJIMPLIB	= $(OUT_DIR)\$(PROJECT)$(VERSION)$(SUFX).lib
PRJLIBNAME	= $(PROJECT)$(VERSION)$(SUFX).$(EXT)
PRJLIBNAME	= $(PROJECT).$(EXT)
PRJLIB		= $(OUT_DIR)\$(PRJLIBNAME)

PRJSTUBLIBNAME	= $(STUBPREFIX)$(VERSION).lib
PRJSTUBLIB	= $(OUT_DIR)\$(PRJSTUBLIBNAME)

### Make sure we use backslash only.
PRJ_INSTALL_DIR         = $(_INSTALLDIR)\$(PROJECT)$(DOTVERSION)
LIB_INSTALL_DIR		= $(PRJ_INSTALL_DIR)
BIN_INSTALL_DIR		= $(PRJ_INSTALL_DIR)
DOC_INSTALL_DIR		= $(PRJ_INSTALL_DIR)
SCRIPT_INSTALL_DIR	= $(PRJ_INSTALL_DIR)
INCLUDE_INSTALL_DIR	= $(_TCLDIR)\include

### The following paths CANNOT have spaces in them.
GENERICDIR	= $(ROOT)\generic
WINDIR		= $(ROOT)\win
LIBDIR          = $(ROOT)\library
DOCDIR		= $(ROOT)\doc
TOOLSDIR	= $(ROOT)\tools
COMPATDIR	= $(ROOT)\compat

### Figure out where the primary source code file(s) is/are.
!if exist("$(ROOT)\..\..\sqlite3.c") && exist("$(ROOT)\..\..\src\tclsqlite.c")
SQL_INCLUDES = -I"$(ROOT)\..\.."
SQLITE_SRCDIR = $(ROOT)\..\..
TCLSQLITE_SRCDIR = $(ROOT)\..\..\src
DLLOBJS = $(TMP_DIR)\sqlite3.obj $(TMP_DIR)\tclsqlite.obj
!else
TCLSQLITE_SRCDIR = $(ROOT)\generic
DLLOBJS = $(TMP_DIR)\tclsqlite3.obj
!endif

#---------------------------------------------------------------------
# Compile flags
#---------------------------------------------------------------------

!if !$(DEBUG)
!if $(OPTIMIZING)
### This cranks the optimization level to maximize speed
cdebug	= -O2 -Op -Gs
!else
cdebug	=
!endif
!else if "$(MACHINE)" == "IA64"
### Warnings are too many, can't support warnings into errors.
cdebug	= -Z7 -Od -GZ
!else
cdebug	= -Z7 -WX -Od -GZ
!endif

### Declarations common to all compiler options
cflags = -nologo -c -W3 -YX -Fp$(TMP_DIR)^\
cflags = -nologo -c -W3 -D_CRT_SECURE_NO_WARNINGS -YX -Fp$(TMP_DIR)^\

!if $(MSVCRT)
!if $(DEBUG)
crt = -MDd
!else
crt = -MD
!endif
!else
!if $(DEBUG)
crt = -MTd
!else
crt = -MT
!endif
!endif

INCLUDES	= $(TCL_INCLUDES) -I"$(WINDIR)" -I"$(GENERICDIR)" \
                  -I"$(ROOT)\.."
INCLUDES	= $(SQL_INCLUDES) $(TCL_INCLUDES) -I"$(WINDIR)" \
                  -I"$(GENERICDIR)" -I"$(ROOT)\.."
BASE_CLFAGS	= $(cflags) $(cdebug) $(crt) $(INCLUDES) \
                  -DSQLITE_3_SUFFIX_ONLY=1 -DSQLITE_ENABLE_RTREE=1 \
                  -DSQLITE_ENABLE_FTS3=1 -DSQLITE_OMIT_DEPRECATED=1
                  -DSQLITE_ENABLE_FTS3=1 -DSQLITE_OMIT_DEPRECATED=1 \
                  -DSQLITE_ENABLE_FTS4=1 \
                  -DSQLITE_ENABLE_FTS5=1 \
                  -DSQLITE_3_SUFFIX_ONLY=1 \
                  -DSQLITE_ENABLE_RTREE=1 \
                  -DSQLITE_ENABLE_GEOPOLY=1 \
                  -DSQLITE_ENABLE_MATH_FUNCTIONS=1 \
                  -DSQLITE_ENABLE_DESERIALIZE=1 \
                  -DSQLITE_ENABLE_DBPAGE_VTAB=1 \
                  -DSQLITE_ENABLE_BYTECODE_VTAB=1 \
                  -DSQLITE_ENABLE_DBSTAT_VTAB=1 

CON_CFLAGS	= $(cflags) $(cdebug) $(crt) -DCONSOLE -DSQLITE_ENABLE_FTS3=1
TCL_CFLAGS	= -DBUILD_sqlite -DUSE_TCL_STUBS \
                  -DPACKAGE_VERSION="\"$(DOTVERSION)\"" $(BASE_CLFAGS) \
                  $(OPTDEFINES)

#---------------------------------------------------------------------
# Link flags
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
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







-
-
-
+
+
+
-

-
-
+
+
-
-
+

-
-
+
+
-
-
+







$(PRJSTUBLIB): $(PRJSTUBOBJS)
	$(lib32) -nologo -out:$@ $(PRJSTUBOBJS)

#---------------------------------------------------------------------
# Implicit rules
#---------------------------------------------------------------------

{$(WINDIR)}.c{$(TMP_DIR)}.obj::
    $(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ @<<
$<
$(TMP_DIR)\sqlite3.obj:		$(SQLITE_SRCDIR)\sqlite3.c
	$(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ \
		-c $(SQLITE_SRCDIR)\sqlite3.c
<<

{$(GENERICDIR)}.c{$(TMP_DIR)}.obj::
    $(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ @<<
$(TMP_DIR)\tclsqlite.obj:	$(TCLSQLITE_SRCDIR)\tclsqlite.c
	$(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ \
$<
<<
		-c $(TCLSQLITE_SRCDIR)\tclsqlite.c

{$(COMPATDIR)}.c{$(TMP_DIR)}.obj::
    $(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ @<<
$(TMP_DIR)\tclsqlite3.obj:	$(TCLSQLITE_SRCDIR)\tclsqlite3.c
	$(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ \
$<
<<
		-c $(TCLSQLITE_SRCDIR)\tclsqlite3.c

{$(WINDIR)}.rc{$(TMP_DIR)}.res:
	$(rc32) -fo $@ -r -i "$(GENERICDIR)" -D__WIN32__ \
!if $(DEBUG)
	-d DEBUG \
!endif
!if $(TCL_THREADS)

Changes to autoconf/tea/win/nmakehlp.c.

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







-
+
-
-
-


-
+


















-



-
+



+
-
+











-
-
+
+













+







 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 * ----------------------------------------------------------------------------
 */

#define _CRT_SECURE_NO_DEPRECATE
#include <windows.h>
#define NO_SHLWAPI_GDI
#ifdef _MSC_VER
#define NO_SHLWAPI_STREAM
#define NO_SHLWAPI_REG
#include <shlwapi.h>
#pragma comment (lib, "user32.lib")
#pragma comment (lib, "kernel32.lib")
#pragma comment (lib, "shlwapi.lib")
#endif
#include <stdio.h>
#include <math.h>

/*
 * This library is required for x64 builds with _some_ versions of MSVC
 */
#if defined(_M_IA64) || defined(_M_AMD64)
#if _MSC_VER >= 1400 && _MSC_VER < 1500
#pragma comment(lib, "bufferoverflowU")
#endif
#endif

/* ISO hack for dumb VC++ */
#ifdef _MSC_VER
#define   snprintf	_snprintf
#endif



/* protos */

static int CheckForCompilerFeature(const char *option);
static int CheckForLinkerFeature(const char *option);
static int CheckForLinkerFeature(char **options, int count);
static int IsIn(const char *string, const char *substring);
static int SubstituteFile(const char *substs, const char *filename);
static int QualifyPath(const char *path);
static int LocateDependency(const char *keyfile);
static const char *GetVersionFromFile(const char *filename, const char *match);
static const char *GetVersionFromFile(const char *filename, const char *match, int numdots);
static DWORD WINAPI ReadFromPipe(LPVOID args);

/* globals */

#define CHUNK	25
#define STATICBUFFERSIZE    1000
typedef struct {
    HANDLE pipe;
    char buffer[STATICBUFFERSIZE];
} pipeinfo;

pipeinfo Out = {INVALID_HANDLE_VALUE, '\0'};
pipeinfo Err = {INVALID_HANDLE_VALUE, '\0'};
pipeinfo Out = {INVALID_HANDLE_VALUE, ""};
pipeinfo Err = {INVALID_HANDLE_VALUE, ""};

/*
 * exitcodes: 0 == no, 1 == yes, 2 == error
 */

int
main(
    int argc,
    char *argv[])
{
    char msg[300];
    DWORD dwWritten;
    int chars;
    const char *s;

    /*
     * Make sure children (cl.exe and link.exe) are kept quiet.
     */

    SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);

98
99
100
101
102
103
104
105

106
107

108
109
110
111
112
113
114

115
116
117
118
119
120
121
96
97
98
99
100
101
102

103
104

105
106
107
108
109
110
111

112
113
114
115
116
117
118
119







-
+

-
+






-
+







			"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
			&dwWritten, NULL);
		return 2;
	    }
	    return CheckForCompilerFeature(argv[2]);
	case 'l':
	    if (argc != 3) {
	    if (argc < 3) {
		chars = snprintf(msg, sizeof(msg) - 1,
	       		"usage: %s -l <linker option>\n"
	       		"usage: %s -l <linker option> ?<mandatory option> ...?\n"
			"Tests for whether link.exe supports an option\n"
			"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
			&dwWritten, NULL);
		return 2;
	    }
	    return CheckForLinkerFeature(argv[2]);
	    return CheckForLinkerFeature(&argv[2], argc-2);
	case 'f':
	    if (argc == 2) {
		chars = snprintf(msg, sizeof(msg) - 1,
			"usage: %s -f <string> <substring>\n"
			"Find a substring within another\n"
			"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
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
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







+
+
-
-
+
+
+
+
+











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







		    "Extract a version from a file:\n"
		    "eg: pkgIndex.tcl \"package ifneeded http\"",
		    argv[0]);
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
		    &dwWritten, NULL);
		return 0;
	    }
	    s = GetVersionFromFile(argv[2], argv[3], *(argv[1]+2) - '0');
	    if (s && *s) {
	    printf("%s\n", GetVersionFromFile(argv[2], argv[3]));
	    return 0;
		printf("%s\n", s);
		return 0;
	    } else
		return 1; /* Version not found. Return non-0 exit code */

	case 'Q':
	    if (argc != 3) {
		chars = snprintf(msg, sizeof(msg) - 1,
		    "usage: %s -Q path\n"
		    "Emit the fully qualified path\n"
		    "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
		    &dwWritten, NULL);
		return 2;
	    }
	    return QualifyPath(argv[2]);

	case 'L':
	    if (argc != 3) {
		chars = snprintf(msg, sizeof(msg) - 1,
		    "usage: %s -L keypath\n"
		    "Emit the fully qualified path of directory containing keypath\n"
		    "exitcodes: 0 == success, 1 == not found, 2 == error\n", argv[0]);
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
		    &dwWritten, NULL);
		return 2;
	    }
	    return LocateDependency(argv[2]);
	}
    }
    chars = snprintf(msg, sizeof(msg) - 1,
	    "usage: %s -c|-f|-l|-Q|-s|-V ...\n"
	    "This is a little helper app to equalize shell differences between WinNT and\n"
	    "Win9x and get nmake.exe to accomplish its job.\n",
	    argv[0]);
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







-
+








    if (!ok) {
	DWORD err = GetLastError();
	int chars = snprintf(msg, sizeof(msg) - 1,
		"Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);

	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
		FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars],
		FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPSTR)&msg[chars],
		(300-chars), 0);
	WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
	return 2;
    }

    /*
     * Close our references to the write handles that have now been inherited.
309
310
311
312
313
314
315
316


317
318
319
320
321
322
323
324

325

326
327
328
329
330
331
332
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







-
+
+








+
-
+







             || strstr(Err.buffer, "D9002") != NULL
             || strstr(Out.buffer, "D2021") != NULL
             || strstr(Err.buffer, "D2021") != NULL);
}

static int
CheckForLinkerFeature(
    const char *option)
    char **options,
    int count)
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    SECURITY_ATTRIBUTES sa;
    DWORD threadID;
    char msg[300];
    BOOL ok;
    HANDLE hProcess, h, pipeThreads[2];
    int i;
    char cmdline[100];
    char cmdline[255];

    hProcess = GetCurrentProcess();

    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
    ZeroMemory(&si, sizeof(STARTUPINFO));
    si.cb = sizeof(STARTUPINFO);
    si.dwFlags   = STARTF_USESTDHANDLES;
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
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







+
-
+
+
+
+



















-
+








    lstrcpy(cmdline, "link.exe -nologo ");

    /*
     * Append our option for testing.
     */

    for (i = 0; i < count; i++) {
    lstrcat(cmdline, option);
	lstrcat(cmdline, " \"");
	lstrcat(cmdline, options[i]);
	lstrcat(cmdline, "\"");
    }

    ok = CreateProcess(
	    NULL,	    /* Module name. */
	    cmdline,	    /* Command line. */
	    NULL,	    /* Process handle not inheritable. */
	    NULL,	    /* Thread handle not inheritable. */
	    TRUE,	    /* yes, inherit handles. */
	    DETACHED_PROCESS, /* No console for you. */
	    NULL,	    /* Use parent's environment block. */
	    NULL,	    /* Use parent's starting directory. */
	    &si,	    /* Pointer to STARTUPINFO structure. */
	    &pi);	    /* Pointer to PROCESS_INFORMATION structure. */

    if (!ok) {
	DWORD err = GetLastError();
	int chars = snprintf(msg, sizeof(msg) - 1,
		"Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);

	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
		FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars],
		FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPSTR)&msg[chars],
		(300-chars), 0);
	WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
	return 2;
    }

    /*
     * Close our references to the write handles that have now been inherited.
429
430
431
432
433
434
435
436



437
438
439
440
441
442
443
450
451
452
453
454
455
456

457
458
459
460
461
462
463
464
465
466







-
+
+
+







    /*
     * Look for the commandline warning code in the stderr stream.
     */

    return !(strstr(Out.buffer, "LNK1117") != NULL ||
	    strstr(Err.buffer, "LNK1117") != NULL ||
	    strstr(Out.buffer, "LNK4044") != NULL ||
	    strstr(Err.buffer, "LNK4044") != NULL);
	    strstr(Err.buffer, "LNK4044") != NULL ||
	    strstr(Out.buffer, "LNK4224") != NULL ||
	    strstr(Err.buffer, "LNK4224") != NULL);
}

static DWORD WINAPI
ReadFromPipe(
    LPVOID args)
{
    pipeinfo *pi = (pipeinfo *) args;
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
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







-
+
+

-









-
+





-
+


+
-
+








-
+
+



-
-
-
+
+







 * 	following the match where a version is anything acceptable to
 * 	package provide or package ifneeded.
 */

static const char *
GetVersionFromFile(
    const char *filename,
    const char *match)
    const char *match,
    int numdots)
{
    size_t cbBuffer = 100;
    static char szBuffer[100];
    char *szResult = NULL;
    FILE *fp = fopen(filename, "rt");

    if (fp != NULL) {
	/*
	 * Read data until we see our match string.
	 */

	while (fgets(szBuffer, cbBuffer, fp) != NULL) {
	while (fgets(szBuffer, sizeof(szBuffer), fp) != NULL) {
	    LPSTR p, q;

	    p = strstr(szBuffer, match);
	    if (p != NULL) {
		/*
		 * Skip to first digit.
		 * Skip to first digit after the match.
		 */

		p += strlen(match);
		while (*p && !isdigit(*p)) {
		while (*p && !isdigit((unsigned char)*p)) {
		    ++p;
		}

		/*
		 * Find ending whitespace.
		 */

		q = p;
		while (*q && (isalnum(*q) || *q == '.')) {
		while (*q && (strchr("0123456789.ab", *q)) && (((!strchr(".ab", *q)
			    && !strchr("ab", q[-1])) || --numdots))) {
		    ++q;
		}

		memcpy(szBuffer, p, q - p);
		szBuffer[q-p] = 0;
		szResult = szBuffer;
		*q = 0;
		szResult = p;
		break;
	    }
	}
	fclose(fp);
    }
    return szResult;
}
534
535
536
537
538
539
540
541

542
543
544
545
546
547
548
558
559
560
561
562
563
564

565
566
567
568
569
570
571
572







-
+







    char * value;
} list_item_t;

/* insert a list item into the list (list may be null) */
static list_item_t *
list_insert(list_item_t **listPtrPtr, const char *key, const char *value)
{
    list_item_t *itemPtr = malloc(sizeof(list_item_t));
    list_item_t *itemPtr = (list_item_t *)malloc(sizeof(list_item_t));
    if (itemPtr) {
	itemPtr->key = strdup(key);
	itemPtr->value = strdup(value);
	itemPtr->nextPtr = NULL;

	while(*listPtrPtr) {
	    listPtrPtr = &(*listPtrPtr)->nextPtr;
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605

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

623
624
625
626
627
628
629
630
631

632
633
634
635
636


637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653

654
655

656
657
658
659
660
661











662
663
664
665
666
667
668
669
670
671
672
673
674

















675
676
677
678
679
680
681
682
683
684

















































































685
686
687
688
689
690
691
692
693
694
607
608
609
610
611
612
613

614

615
616
617
618
619
620
621
622
623
624
625
626

627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643

644
645
646
647
648
649
650
651
652

653
654
655
656


657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674

675
676

677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724










725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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







-

-












-
+
















-
+








-
+



-
-
+
+
















-
+

-
+






+
+
+
+
+
+
+
+
+
+
+













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










 */

static int
SubstituteFile(
    const char *substitutions,
    const char *filename)
{
    size_t cbBuffer = 1024;
    static char szBuffer[1024], szCopy[1024];
    char *szResult = NULL;
    list_item_t *substPtr = NULL;
    FILE *fp, *sp;

    fp = fopen(filename, "rt");
    if (fp != NULL) {

	/*
	 * Build a list of substutitions from the first filename
	 */

	sp = fopen(substitutions, "rt");
	if (sp != NULL) {
	    while (fgets(szBuffer, cbBuffer, sp) != NULL) {
	    while (fgets(szBuffer, sizeof(szBuffer), sp) != NULL) {
		unsigned char *ks, *ke, *vs, *ve;
		ks = (unsigned char*)szBuffer;
		while (ks && *ks && isspace(*ks)) ++ks;
		ke = ks;
		while (ke && *ke && !isspace(*ke)) ++ke;
		vs = ke;
		while (vs && *vs && isspace(*vs)) ++vs;
		ve = vs;
		while (ve && *ve && !(*ve == '\r' || *ve == '\n')) ++ve;
		*ke = 0, *ve = 0;
		list_insert(&substPtr, (char*)ks, (char*)vs);
	    }
	    fclose(sp);
	}

	/* debug: dump the list */
#ifdef _DEBUG
#ifndef NDEBUG
	{
	    int n = 0;
	    list_item_t *p = NULL;
	    for (p = substPtr; p != NULL; p = p->nextPtr, ++n) {
		fprintf(stderr, "% 3d '%s' => '%s'\n", n, p->key, p->value);
	    }
	}
#endif
	

	/*
	 * Run the substitutions over each line of the input
	 */
	
	while (fgets(szBuffer, cbBuffer, fp) != NULL) {

	while (fgets(szBuffer, sizeof(szBuffer), fp) != NULL) {
	    list_item_t *p = NULL;
	    for (p = substPtr; p != NULL; p = p->nextPtr) {
		char *m = strstr(szBuffer, p->key);
		if (m) {
		    char *cp, *op, *sp;
		    cp = szCopy;
		    op = szBuffer;
		    while (op != m) *cp++ = *op++;
		    sp = p->value;
		    while (sp && *sp) *cp++ = *sp++;
		    op += strlen(p->key);
		    while (*op) *cp++ = *op++;
		    *cp = 0;
		    memcpy(szBuffer, szCopy, sizeof(szCopy));
		}
	    }
	    printf(szBuffer);
	    printf("%s", szBuffer);
	}
	

	list_free(&substPtr);
    }
    fclose(fp);
    return 0;
}

BOOL FileExists(LPCTSTR szPath)
{
#ifndef INVALID_FILE_ATTRIBUTES
    #define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
#endif
    DWORD pathAttr = GetFileAttributes(szPath);
    return (pathAttr != INVALID_FILE_ATTRIBUTES &&
	    !(pathAttr & FILE_ATTRIBUTE_DIRECTORY));
}


/*
 * QualifyPath --
 *
 *	This composes the current working directory with a provided path
 *	and returns the fully qualified and normalized path.
 *	Mostly needed to setup paths for testing.
 */

static int
QualifyPath(
    const char *szPath)
{
    char szCwd[MAX_PATH + 1];

    GetFullPathName(szPath, sizeof(szCwd)-1, szCwd, NULL);
    printf("%s\n", szCwd);
    return 0;
}

/*
 * Implements LocateDependency for a single directory. See that command
 * for an explanation.
 * Returns 0 if found after printing the directory.
 * Returns 1 if not found but no errors.
 * Returns 2 on any kind of error
 * Basically, these are used as exit codes for the process.
 */
static int LocateDependencyHelper(const char *dir, const char *keypath)
{
    HANDLE hSearch;
    char szTmp[MAX_PATH + 1];
    char *p;
    GetCurrentDirectory(MAX_PATH, szCwd);
    while ((p = strchr(szPath, '/')) && *p)
	*p = '\\';
    PathCombine(szTmp, szCwd, szPath);
    PathCanonicalize(szCwd, szTmp);
    printf("%s\n", szCwd);
    return 0;
}
    char path[MAX_PATH+1];
    size_t dirlen;
    int keylen, ret;
    WIN32_FIND_DATA finfo;

    if (dir == NULL || keypath == NULL)
	return 2; /* Have no real error reporting mechanism into nmake */
    dirlen = strlen(dir);
    if ((dirlen + 3) > sizeof(path))
	return 2;
    strncpy(path, dir, dirlen);
    strncpy(path+dirlen, "\\*", 3);	/* Including terminating \0 */
    keylen = strlen(keypath);

#if 0 /* This function is not available in Visual C++ 6 */
    /*
     * Use numerics 0 -> FindExInfoStandard,
     * 1 -> FindExSearchLimitToDirectories,
     * as these are not defined in Visual C++ 6
     */
    hSearch = FindFirstFileEx(path, 0, &finfo, 1, NULL, 0);
#else
    hSearch = FindFirstFile(path, &finfo);
#endif
    if (hSearch == INVALID_HANDLE_VALUE)
	return 1; /* Not found */

    /* Loop through all subdirs checking if the keypath is under there */
    ret = 1; /* Assume not found */
    do {
	int sublen;
	/*
	 * We need to check it is a directory despite the
	 * FindExSearchLimitToDirectories in the above call. See SDK docs
	 */
	if ((finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
	    continue;
	sublen = strlen(finfo.cFileName);
	if ((dirlen+1+sublen+1+keylen+1) > sizeof(path))
	    continue;		/* Path does not fit, assume not matched */
	strncpy(path+dirlen+1, finfo.cFileName, sublen);
	path[dirlen+1+sublen] = '\\';
	strncpy(path+dirlen+1+sublen+1, keypath, keylen+1);
	if (FileExists(path)) {
	    /* Found a match, print to stdout */
	    path[dirlen+1+sublen] = '\0';
	    QualifyPath(path);
	    ret = 0;
	    break;
	}
    } while (FindNextFile(hSearch, &finfo));
    FindClose(hSearch);
    return ret;
}

/*
 * LocateDependency --
 *
 *	Locates a dependency for a package.
 *        keypath - a relative path within the package directory
 *          that is used to confirm it is the correct directory.
 *	The search path for the package directory is currently only
 *      the parent and grandparent of the current working directory.
 *      If found, the command prints
 *         name_DIRPATH=<full path of located directory>
 *      and returns 0. If not found, does not print anything and returns 1.
 */
static int LocateDependency(const char *keypath)
{
    size_t i;
    int ret;
    static const char *paths[] = {"..", "..\\..", "..\\..\\.."};

    for (i = 0; i < (sizeof(paths)/sizeof(paths[0])); ++i) {
	ret = LocateDependencyHelper(paths[i], keypath);
	if (ret == 0)
	    return ret;
    }
    return ret;
}


/*
 * Local variables:
 *   mode: c
 *   c-basic-offset: 4
 *   fill-column: 78
 *   indent-tabs-mode: t
 *   tab-width: 8
 * End:
 */

Changes to config.guess.

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


-
-
+
-

-
+



-
+








-
+
-
-




-
-
-
-
+
+
+
+
+
-
-

+
-
+
-
-

+
-
+
-








-
+










-
-
+







#! /bin/sh
# Attempt to guess a canonical system name.
#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
#   2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
#   Copyright 1992-2019 Free Software Foundation, Inc.
#   Inc.

timestamp='2007-07-22'
timestamp='2019-05-28'

# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# along with this program; if not, see <https://www.gnu.org/licenses/>.
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
# 02110-1301, USA.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.


# Originally written by Per Bothner <per@bothner.com>.
# the same distribution terms that you use for the rest of that
# program.  This Exception is an additional permission under section 7
# of the GNU General Public License, version 3 ("GPLv3").
#
# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
# Please send patches to <config-patches@gnu.org>.  Submit a context
# diff and a properly formatted ChangeLog entry.
#
# You can get the latest version of this script from:
# This script attempts to guess a canonical system name similar to
# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
# config.sub.  If it succeeds, it prints the system name on stdout, and
# exits with 0.  Otherwise, it exits with 1.
#
# Please send patches to <config-patches@gnu.org>.
# The plan is that this can be called by configure scripts if you

# don't specify an explicit build system type.

me=`echo "$0" | sed -e 's,.*/,,'`

usage="\
Usage: $0 [OPTION]

Output the configuration name of the system \`$me' is run on.

Operation modes:
Options:
  -h, --help         print this help, then exit
  -t, --time-stamp   print date of last modification, then exit
  -v, --version      print version number, then exit

Report bugs and patches to <config-patches@gnu.org>."

version="\
GNU config.guess ($timestamp)

Originally written by Per Bothner.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
Copyright 1992-2019 Free Software Foundation, Inc.

This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."

help="
Try \`$me --help' for more information."

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







-
-










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


-
+








-
-
-
+
+
+
+
+
+
+
+

-
+
-
-
-

+
-
+



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



-
+


-
+









-
-
-
+
+
+
+
+





+
+
+
+
+
-
+


-
-
+
+
+
+
+

-
+

-
+









-
+
+
+
+
+
+
+
+







-
+




-
+





-
+
+
+
+
+



+
+
+
-
+
+

+
+
+

-
+


-
+


-
+


+
+
+
-
+

+
+
+
+
+
+






-
+









-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+






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




-
+


-
+








-
+


-
+

-
+







done

if test $# != 0; then
  echo "$me: too many arguments$help" >&2
  exit 1
fi

trap 'exit 1' 1 2 15

# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
# compiler to aid in system detection is discouraged as it requires
# temporary files to be created and, as you can see below, it is a
# headache to deal with in a portable fashion.

# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
# use `HOST_CC' if defined, but it is deprecated.

# Portable tmp directory creation inspired by the Autoconf team.

tmp=
# shellcheck disable=SC2172
trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15

set_cc_for_build='
set_cc_for_build() {
trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
: ${TMPDIR=/tmp} ;
 { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
 { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
 { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
 { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
dummy=$tmp/dummy ;
    : "${TMPDIR=/tmp}"
    # shellcheck disable=SC2039
    { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
	{ test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } ||
	{ tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } ||
	{ echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; }
    dummy=$tmp/dummy
tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
case $CC_FOR_BUILD,$HOST_CC,$CC in
 ,,)    echo "int x;" > $dummy.c ;
	for c in cc gcc c89 c99 ; do
	  if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
	     CC_FOR_BUILD="$c"; break ;
	  fi ;
	done ;
	if test x"$CC_FOR_BUILD" = x ; then
	  CC_FOR_BUILD=no_compiler_found ;
	fi
	;;
 ,,*)   CC_FOR_BUILD=$CC ;;
 ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
esac ; set_cc_for_build= ;'

    case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in
	,,)    echo "int x;" > "$dummy.c"
	       for driver in cc gcc c89 c99 ; do
		   if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then
		       CC_FOR_BUILD="$driver"
		       break
		   fi
	       done
	       if test x"$CC_FOR_BUILD" = x ; then
		   CC_FOR_BUILD=no_compiler_found
	       fi
	       ;;
	,,*)   CC_FOR_BUILD=$CC ;;
	,*,*)  CC_FOR_BUILD=$HOST_CC ;;
    esac
}

# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
# (ghazi@noc.rutgers.edu 1994-08-24)
if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
if test -f /.attbin/uname ; then
	PATH=$PATH:/.attbin ; export PATH
fi

UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown

if [ "${UNAME_SYSTEM}" = "Linux" ] ; then
	eval $set_cc_for_build
	cat << EOF > $dummy.c
case "$UNAME_SYSTEM" in
Linux|GNU|GNU/*)
	# If the system lacks a compiler, then just pick glibc.
	# We could probably try harder.
	LIBC=gnu

	set_cc_for_build
	cat <<-EOF > "$dummy.c"
	#include <features.h>
	#ifdef __UCLIBC__
	#if defined(__UCLIBC__)
	# ifdef __UCLIBC_CONFIG_VERSION__
	LIBC=uclibc __UCLIBC_CONFIG_VERSION__
	# else
	LIBC=uclibc
	#elif defined(__dietlibc__)
	# endif
	LIBC=dietlibc
	#else
	LIBC=gnu
	#endif
EOF
	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep LIBC= | sed -e 's: ::g'`
fi
	EOF
	eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`"

	# If ldd exists, use it to detect musl libc.
	if command -v ldd >/dev/null && \
		ldd --version 2>&1 | grep -q ^musl
	then
	    LIBC=musl
	fi
	;;
esac

# Note: order is significant - the case branches are not exclusive.

case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
    *:NetBSD:*:*)
	# NetBSD (nbsd) targets should (where applicable) match one or
	# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
	# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
	# switched to ELF, *-*-netbsd* would select the old
	# object file format.  This provides both forward
	# compatibility and a consistent mechanism for selecting the
	# object file format.
	#
	# Note: NetBSD doesn't particularly care about the vendor
	# portion of the name.  We always set it to "unknown".
	sysctl="sysctl -n hw.machine_arch"
	UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
	    /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
	case "${UNAME_MACHINE_ARCH}" in
	UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
	    "/sbin/$sysctl" 2>/dev/null || \
	    "/usr/sbin/$sysctl" 2>/dev/null || \
	    echo unknown)`
	case "$UNAME_MACHINE_ARCH" in
	    armeb) machine=armeb-unknown ;;
	    arm*) machine=arm-unknown ;;
	    sh3el) machine=shl-unknown ;;
	    sh3eb) machine=sh-unknown ;;
	    sh5el) machine=sh5le-unknown ;;
	    earmv*)
		arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
		endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'`
		machine="${arch}${endian}"-unknown
		;;
	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
	    *) machine="$UNAME_MACHINE_ARCH"-unknown ;;
	esac
	# The Operating System including object format, if it has switched
	# to ELF recently, or will in the future.
	case "${UNAME_MACHINE_ARCH}" in
	# to ELF recently (or will in the future) and ABI.
	case "$UNAME_MACHINE_ARCH" in
	    earm*)
		os=netbsdelf
		;;
	    arm*|i386|m68k|ns32k|sh3*|sparc|vax)
		eval $set_cc_for_build
		set_cc_for_build
		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
			| grep __ELF__ >/dev/null
			| grep -q __ELF__
		then
		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
		    # Return netbsd for either.  FIX?
		    os=netbsd
		else
		    os=netbsdelf
		fi
		;;
	    *)
	        os=netbsd
		os=netbsd
		;;
	esac
	# Determine ABI tags.
	case "$UNAME_MACHINE_ARCH" in
	    earm*)
		expr='s/^earmv[0-9]/-eabi/;s/eb$//'
		abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"`
		;;
	esac
	# The OS release
	# Debian GNU/NetBSD machines have a different userland, and
	# thus, need a distinct triplet. However, they do not need
	# kernel version information, so it can be replaced with a
	# suitable tag, in the style of linux-gnu.
	case "${UNAME_VERSION}" in
	case "$UNAME_VERSION" in
	    Debian*)
		release='-gnu'
		;;
	    *)
		release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
		release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2`
		;;
	esac
	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
	# contains redundant information, the shorter form:
	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
	echo "${machine}-${os}${release}"
	echo "$machine-${os}${release}${abi-}"
	exit ;;
    *:Bitrig:*:*)
	UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
	echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE"
	exit ;;
    *:OpenBSD:*:*)
	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
	echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE"
	exit ;;
    *:LibertyBSD:*:*)
	echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
	UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
	echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE"
	exit ;;
    *:MidnightBSD:*:*)
	echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE"
	exit ;;
    *:ekkoBSD:*:*)
	echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
	echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE"
	exit ;;
    *:SolidBSD:*:*)
	echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
	echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE"
	exit ;;
    macppc:MirBSD:*:*)
	echo powerpc-unknown-mirbsd${UNAME_RELEASE}
	echo powerpc-unknown-mirbsd"$UNAME_RELEASE"
	exit ;;
    *:MirBSD:*:*)
	echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE"
	exit ;;
    *:Sortix:*:*)
	echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
	echo "$UNAME_MACHINE"-unknown-sortix
	exit ;;
    *:Redox:*:*)
	echo "$UNAME_MACHINE"-unknown-redox
	exit ;;
    mips:OSF1:*.*)
        echo mips-dec-osf1
        exit ;;
    alpha:OSF1:*:*)
	case $UNAME_RELEASE in
	*4.0)
		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
		;;
	*5.*)
	        UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
		;;
	esac
	# According to Compaq, /usr/sbin/psrinfo has been available on
	# OSF/1 and Tru64 systems produced since 1995.  I hope that
	# covers most systems running today.  This code pipes the CPU
	# types through head -n 1, so we only detect the type of CPU 0.
	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
	case "$ALPHA_CPU_TYPE" in
	    "EV4 (21064)")
		UNAME_MACHINE="alpha" ;;
		UNAME_MACHINE=alpha ;;
	    "EV4.5 (21064)")
		UNAME_MACHINE="alpha" ;;
		UNAME_MACHINE=alpha ;;
	    "LCA4 (21066/21068)")
		UNAME_MACHINE="alpha" ;;
		UNAME_MACHINE=alpha ;;
	    "EV5 (21164)")
		UNAME_MACHINE="alphaev5" ;;
		UNAME_MACHINE=alphaev5 ;;
	    "EV5.6 (21164A)")
		UNAME_MACHINE="alphaev56" ;;
		UNAME_MACHINE=alphaev56 ;;
	    "EV5.6 (21164PC)")
		UNAME_MACHINE="alphapca56" ;;
		UNAME_MACHINE=alphapca56 ;;
	    "EV5.7 (21164PC)")
		UNAME_MACHINE="alphapca57" ;;
		UNAME_MACHINE=alphapca57 ;;
	    "EV6 (21264)")
		UNAME_MACHINE="alphaev6" ;;
		UNAME_MACHINE=alphaev6 ;;
	    "EV6.7 (21264A)")
		UNAME_MACHINE="alphaev67" ;;
		UNAME_MACHINE=alphaev67 ;;
	    "EV6.8CB (21264C)")
		UNAME_MACHINE="alphaev68" ;;
		UNAME_MACHINE=alphaev68 ;;
	    "EV6.8AL (21264B)")
		UNAME_MACHINE="alphaev68" ;;
		UNAME_MACHINE=alphaev68 ;;
	    "EV6.8CX (21264D)")
		UNAME_MACHINE="alphaev68" ;;
		UNAME_MACHINE=alphaev68 ;;
	    "EV6.9A (21264/EV69A)")
		UNAME_MACHINE="alphaev69" ;;
		UNAME_MACHINE=alphaev69 ;;
	    "EV7 (21364)")
		UNAME_MACHINE="alphaev7" ;;
		UNAME_MACHINE=alphaev7 ;;
	    "EV7.9 (21364A)")
		UNAME_MACHINE="alphaev79" ;;
		UNAME_MACHINE=alphaev79 ;;
	esac
	# A Pn.n version is a patched version.
	# A Vn.n version is a released version.
	# A Tn.n version is a released field test version.
	# A Xn.n version is an unreleased experimental baselevel.
	# 1.2 uses "1.2" for uname -r.
	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
	exit ;;
	echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`"
	# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
	exitcode=$?
    Alpha\ *:Windows_NT*:*)
	# How do we know it's Interix rather than the generic POSIX subsystem?
	# Should we change UNAME_MACHINE based on the output of uname instead
	# of the specific Alpha model?
	echo alpha-pc-interix
	exit ;;
	trap '' 0
    21064:Windows_NT:50:3)
	echo alpha-dec-winnt3.5
	exit ;;
	exit $exitcode ;;
    Amiga*:UNIX_System_V:4.0:*)
	echo m68k-unknown-sysv4
	exit ;;
    *:[Aa]miga[Oo][Ss]:*:*)
	echo ${UNAME_MACHINE}-unknown-amigaos
	echo "$UNAME_MACHINE"-unknown-amigaos
	exit ;;
    *:[Mm]orph[Oo][Ss]:*:*)
	echo ${UNAME_MACHINE}-unknown-morphos
	echo "$UNAME_MACHINE"-unknown-morphos
	exit ;;
    *:OS/390:*:*)
	echo i370-ibm-openedition
	exit ;;
    *:z/VM:*:*)
	echo s390-ibm-zvmoe
	exit ;;
    *:OS400:*:*)
        echo powerpc-ibm-os400
	echo powerpc-ibm-os400
	exit ;;
    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
	echo arm-acorn-riscix${UNAME_RELEASE}
	echo arm-acorn-riscix"$UNAME_RELEASE"
	exit ;;
    arm:riscos:*:*|arm:RISCOS:*:*)
    arm*:riscos:*:*|arm*:RISCOS:*:*)
	echo arm-unknown-riscos
	exit ;;
    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
	echo hppa1.1-hitachi-hiuxmpp
	exit ;;
    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
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
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







+
+
+

-
+


-
+

+
+
+

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





-
+








-
+


-
+



-
+


-
+


-
+




-
+










-
+


-
-
+
+

-
+


-
-
+
+

-
-
+
+

-
-
+
+

-
+


-
+





-
+


-
+


-
+


-
-
+
+








-
+


-
+


-
+





-
-
-
+
+
+

-
+







    DRS?6000:unix:4.0:6*)
	echo sparc-icl-nx6
	exit ;;
    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
	case `/usr/bin/uname -p` in
	    sparc) echo sparc-icl-nx7; exit ;;
	esac ;;
    s390x:SunOS:*:*)
	echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`"
	exit ;;
    sun4H:SunOS:5.*:*)
	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
	echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
	exit ;;
    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
	echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`"
	exit ;;
    i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
	echo i386-pc-auroraux"$UNAME_RELEASE"
	exit ;;
    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
	set_cc_for_build
	SUN_ARCH=i386
	# If there is a compiler, see if it is configured for 64-bit objects.
	# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
	# This test works for both compilers.
	if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
	    if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
		(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
		grep IS_64BIT_ARCH >/dev/null
	    then
		SUN_ARCH=x86_64
	    fi
	fi
	echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
	echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
	exit ;;
    sun4*:SunOS:6*:*)
	# According to config.sub, this is the proper way to canonicalize
	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
	# it's likely to be more like Solaris than SunOS4.
	echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
	echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
	exit ;;
    sun4*:SunOS:*:*)
	case "`/usr/bin/arch -k`" in
	    Series*|S4*)
		UNAME_RELEASE=`uname -v`
		;;
	esac
	# Japanese Language versions have a version number like `4.1.3-JL'.
	echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
	echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`"
	exit ;;
    sun3*:SunOS:*:*)
	echo m68k-sun-sunos${UNAME_RELEASE}
	echo m68k-sun-sunos"$UNAME_RELEASE"
	exit ;;
    sun*:*:4.2BSD:*)
	UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
	test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
	test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3
	case "`/bin/arch`" in
	    sun3)
		echo m68k-sun-sunos${UNAME_RELEASE}
		echo m68k-sun-sunos"$UNAME_RELEASE"
		;;
	    sun4)
		echo sparc-sun-sunos${UNAME_RELEASE}
		echo sparc-sun-sunos"$UNAME_RELEASE"
		;;
	esac
	exit ;;
    aushp:SunOS:*:*)
	echo sparc-auspex-sunos${UNAME_RELEASE}
	echo sparc-auspex-sunos"$UNAME_RELEASE"
	exit ;;
    # The situation for MiNT is a little confusing.  The machine name
    # can be virtually everything (everything which is not
    # "atarist" or "atariste" at least should have a processor
    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
    # to the lowercase version "mint" (or "freemint").  Finally
    # the system name "TOS" denotes a system which is actually not
    # MiNT.  But MiNT is downward compatible to TOS, so this should
    # be no problem.
    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
        echo m68k-atari-mint${UNAME_RELEASE}
	echo m68k-atari-mint"$UNAME_RELEASE"
	exit ;;
    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
	echo m68k-atari-mint${UNAME_RELEASE}
        exit ;;
	echo m68k-atari-mint"$UNAME_RELEASE"
	exit ;;
    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
        echo m68k-atari-mint${UNAME_RELEASE}
	echo m68k-atari-mint"$UNAME_RELEASE"
	exit ;;
    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
        echo m68k-milan-mint${UNAME_RELEASE}
        exit ;;
	echo m68k-milan-mint"$UNAME_RELEASE"
	exit ;;
    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
        echo m68k-hades-mint${UNAME_RELEASE}
        exit ;;
	echo m68k-hades-mint"$UNAME_RELEASE"
	exit ;;
    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
        echo m68k-unknown-mint${UNAME_RELEASE}
        exit ;;
	echo m68k-unknown-mint"$UNAME_RELEASE"
	exit ;;
    m68k:machten:*:*)
	echo m68k-apple-machten${UNAME_RELEASE}
	echo m68k-apple-machten"$UNAME_RELEASE"
	exit ;;
    powerpc:machten:*:*)
	echo powerpc-apple-machten${UNAME_RELEASE}
	echo powerpc-apple-machten"$UNAME_RELEASE"
	exit ;;
    RISC*:Mach:*:*)
	echo mips-dec-mach_bsd4.3
	exit ;;
    RISC*:ULTRIX:*:*)
	echo mips-dec-ultrix${UNAME_RELEASE}
	echo mips-dec-ultrix"$UNAME_RELEASE"
	exit ;;
    VAX*:ULTRIX*:*:*)
	echo vax-dec-ultrix${UNAME_RELEASE}
	echo vax-dec-ultrix"$UNAME_RELEASE"
	exit ;;
    2020:CLIX:*:* | 2430:CLIX:*:*)
	echo clipper-intergraph-clix${UNAME_RELEASE}
	echo clipper-intergraph-clix"$UNAME_RELEASE"
	exit ;;
    mips:*:*:UMIPS | mips:*:*:RISCos)
	eval $set_cc_for_build
	sed 's/^	//' << EOF >$dummy.c
	set_cc_for_build
	sed 's/^	//' << EOF > "$dummy.c"
#ifdef __cplusplus
#include <stdio.h>  /* for printf() prototype */
	int main (int argc, char *argv[]) {
#else
	int main (argc, argv) int argc; char *argv[]; {
#endif
	#if defined (host_mips) && defined (MIPSEB)
	#if defined (SYSTYPE_SYSV)
	  printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
	  printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0);
	#endif
	#if defined (SYSTYPE_SVR4)
	  printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
	  printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0);
	#endif
	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
	  printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
	  printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0);
	#endif
	#endif
	  exit (-1);
	}
EOF
	$CC_FOR_BUILD -o $dummy $dummy.c &&
	  dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
	  SYSTEM_NAME=`$dummy $dummyarg` &&
	$CC_FOR_BUILD -o "$dummy" "$dummy.c" &&
	  dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` &&
	  SYSTEM_NAME=`"$dummy" "$dummyarg"` &&
	    { echo "$SYSTEM_NAME"; exit; }
	echo mips-mips-riscos${UNAME_RELEASE}
	echo mips-mips-riscos"$UNAME_RELEASE"
	exit ;;
    Motorola:PowerMAX_OS:*:*)
	echo powerpc-motorola-powermax
	exit ;;
    Motorola:*:4.3:PL8-*)
	echo powerpc-harris-powermax
	exit ;;
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
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
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
638
639
640
641
642
643
644




645
646
647
648
649
650
651











652
653
654
655
656
657
658
659
660
661
662
663



664
665
666
667



668
669
670
671






672
673
674
675
676
677
678



















679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698

699
700
701
702

703
704

705
706
707
708
709
710
711
712
713
714
715


716
717
718

719
720

721
722
723

724
725
726


727
728
729
730


731
732
733
734
735
736
737
738
739







-
-
-
+
+
+

-
-
+
+

-
+

-
+


-
+

-
+














-
+











-
+

-
+



-
-
+
+










-
+











-
+

-
+




-
-
+
+
+

-
+

-
+




-
+



-
+














-
-
-
-
+
+
+
+



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

-
-
-
+
+
+

-
-
-
+
+
+

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

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

-
+



-
+

-
+










-
-
+
+

-
+

-
+


-
+


-
-
+
+


-
-
+
+







    m88k:*:4*:R4*)
	echo m88k-motorola-sysv4
	exit ;;
    m88k:*:3*:R3*)
	echo m88k-motorola-sysv3
	exit ;;
    AViiON:dgux:*:*)
        # DG/UX returns AViiON for all architectures
        UNAME_PROCESSOR=`/usr/bin/uname -p`
	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
	# DG/UX returns AViiON for all architectures
	UNAME_PROCESSOR=`/usr/bin/uname -p`
	if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ]
	then
	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
	       [ ${TARGET_BINARY_INTERFACE}x = x ]
	    if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \
	       [ "$TARGET_BINARY_INTERFACE"x = x ]
	    then
		echo m88k-dg-dgux${UNAME_RELEASE}
		echo m88k-dg-dgux"$UNAME_RELEASE"
	    else
		echo m88k-dg-dguxbcs${UNAME_RELEASE}
		echo m88k-dg-dguxbcs"$UNAME_RELEASE"
	    fi
	else
	    echo i586-dg-dgux${UNAME_RELEASE}
	    echo i586-dg-dgux"$UNAME_RELEASE"
	fi
 	exit ;;
	exit ;;
    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
	echo m88k-dolphin-sysv3
	exit ;;
    M88*:*:R3*:*)
	# Delta 88k system running SVR3
	echo m88k-motorola-sysv3
	exit ;;
    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
	echo m88k-tektronix-sysv3
	exit ;;
    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
	echo m68k-tektronix-bsd
	exit ;;
    *:IRIX*:*:*)
	echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
	echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`"
	exit ;;
    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
	echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
	exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
    i*86:AIX:*:*)
	echo i386-ibm-aix
	exit ;;
    ia64:AIX:*:*)
	if [ -x /usr/bin/oslevel ] ; then
		IBM_REV=`/usr/bin/oslevel`
	else
		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
		IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
	fi
	echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
	echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV"
	exit ;;
    *:AIX:2:3)
	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
		eval $set_cc_for_build
		sed 's/^		//' << EOF >$dummy.c
		set_cc_for_build
		sed 's/^		//' << EOF > "$dummy.c"
		#include <sys/systemcfg.h>

		main()
			{
			if (!__power_pc())
				exit(1);
			puts("powerpc-ibm-aix3.2.5");
			exit(0);
			}
EOF
		if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
		if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"`
		then
			echo "$SYSTEM_NAME"
		else
			echo rs6000-ibm-aix3.2.5
		fi
	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
		echo rs6000-ibm-aix3.2.4
	else
		echo rs6000-ibm-aix3.2
	fi
	exit ;;
    *:AIX:*:[45])
    *:AIX:*:[4567])
	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
	if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then
		IBM_ARCH=rs6000
	else
		IBM_ARCH=powerpc
	fi
	if [ -x /usr/bin/oslevel ] ; then
		IBM_REV=`/usr/bin/oslevel`
	if [ -x /usr/bin/lslpp ] ; then
		IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
			   awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
	else
		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
		IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
	fi
	echo ${IBM_ARCH}-ibm-aix${IBM_REV}
	echo "$IBM_ARCH"-ibm-aix"$IBM_REV"
	exit ;;
    *:AIX:*:*)
	echo rs6000-ibm-aix
	exit ;;
    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
    ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*)
	echo romp-ibm-bsd4.4
	exit ;;
    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
	echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
	echo romp-ibm-bsd"$UNAME_RELEASE"   # 4.3 with uname added to
	exit ;;                             # report: romp-ibm BSD 4.3
    *:BOSX:*:*)
	echo rs6000-bull-bosx
	exit ;;
    DPX/2?00:B.O.S.:*:*)
	echo m68k-bull-sysv3
	exit ;;
    9000/[34]??:4.3bsd:1.*:*)
	echo m68k-hp-bsd
	exit ;;
    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
	echo m68k-hp-bsd4.4
	exit ;;
    9000/[34678]??:HP-UX:*:*)
	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
	case "${UNAME_MACHINE}" in
	    9000/31? )            HP_ARCH=m68000 ;;
	    9000/[34]?? )         HP_ARCH=m68k ;;
	HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'`
	case "$UNAME_MACHINE" in
	    9000/31?)            HP_ARCH=m68000 ;;
	    9000/[34]??)         HP_ARCH=m68k ;;
	    9000/[678][0-9][0-9])
		if [ -x /usr/bin/getconf ]; then
		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
                    case "${sc_cpu_version}" in
                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
                      532)                      # CPU_PA_RISC2_0
                        case "${sc_kernel_bits}" in
                          32) HP_ARCH="hppa2.0n" ;;
                          64) HP_ARCH="hppa2.0w" ;;
			  '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
                        esac ;;
                    esac
		    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
		    case "$sc_cpu_version" in
		      523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
		      528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
		      532)                      # CPU_PA_RISC2_0
			case "$sc_kernel_bits" in
			  32) HP_ARCH=hppa2.0n ;;
			  64) HP_ARCH=hppa2.0w ;;
			  '') HP_ARCH=hppa2.0 ;;   # HP-UX 10.20
			esac ;;
		    esac
		fi
		if [ "${HP_ARCH}" = "" ]; then
		    eval $set_cc_for_build
		    sed 's/^              //' << EOF >$dummy.c
		if [ "$HP_ARCH" = "" ]; then
		    set_cc_for_build
		    sed 's/^		//' << EOF > "$dummy.c"

              #define _HPUX_SOURCE
              #include <stdlib.h>
              #include <unistd.h>
		#define _HPUX_SOURCE
		#include <stdlib.h>
		#include <unistd.h>

              int main ()
              {
              #if defined(_SC_KERNEL_BITS)
                  long bits = sysconf(_SC_KERNEL_BITS);
              #endif
                  long cpu  = sysconf (_SC_CPU_VERSION);
		int main ()
		{
		#if defined(_SC_KERNEL_BITS)
		    long bits = sysconf(_SC_KERNEL_BITS);
		#endif
		    long cpu  = sysconf (_SC_CPU_VERSION);

                  switch (cpu)
              	{
              	case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
              	case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
              	case CPU_PA_RISC2_0:
              #if defined(_SC_KERNEL_BITS)
              	    switch (bits)
              		{
              		case 64: puts ("hppa2.0w"); break;
              		case 32: puts ("hppa2.0n"); break;
              		default: puts ("hppa2.0"); break;
              		} break;
              #else  /* !defined(_SC_KERNEL_BITS) */
              	    puts ("hppa2.0"); break;
              #endif
              	default: puts ("hppa1.0"); break;
              	}
                  exit (0);
              }
		    switch (cpu)
			{
			case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
			case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
			case CPU_PA_RISC2_0:
		#if defined(_SC_KERNEL_BITS)
			    switch (bits)
				{
				case 64: puts ("hppa2.0w"); break;
				case 32: puts ("hppa2.0n"); break;
				default: puts ("hppa2.0"); break;
				} break;
		#else  /* !defined(_SC_KERNEL_BITS) */
			    puts ("hppa2.0"); break;
		#endif
			default: puts ("hppa1.0"); break;
			}
		    exit (0);
		}
EOF
		    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
		    (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"`
		    test -z "$HP_ARCH" && HP_ARCH=hppa
		fi ;;
	esac
	if [ ${HP_ARCH} = "hppa2.0w" ]
	if [ "$HP_ARCH" = hppa2.0w ]
	then
	    eval $set_cc_for_build
	    set_cc_for_build

	    # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
	    # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
	    # generating 64-bit code.  GNU and HP use different nomenclature:
	    #
	    # $ CC_FOR_BUILD=cc ./config.guess
	    # => hppa2.0w-hp-hpux11.23
	    # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
	    # => hppa64-hp-hpux11.23

	    if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
		grep __LP64__ >/dev/null
	    if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) |
		grep -q __LP64__
	    then
		HP_ARCH="hppa2.0w"
		HP_ARCH=hppa2.0w
	    else
		HP_ARCH="hppa64"
		HP_ARCH=hppa64
	    fi
	fi
	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
	echo "$HP_ARCH"-hp-hpux"$HPUX_REV"
	exit ;;
    ia64:HP-UX:*:*)
	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
	echo ia64-hp-hpux${HPUX_REV}
	HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'`
	echo ia64-hp-hpux"$HPUX_REV"
	exit ;;
    3050*:HI-UX:*:*)
	eval $set_cc_for_build
	sed 's/^	//' << EOF >$dummy.c
	set_cc_for_build
	sed 's/^	//' << EOF > "$dummy.c"
	#include <unistd.h>
	int
	main ()
	{
	  long cpu = sysconf (_SC_CPU_VERSION);
	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
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
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943






















































































































944
945
946
947
948
949
950



951
952
953
954


955












956
957

958
959
960

961
962
963

964
965
966

967



968
969

970
971
972

973
974
975


976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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
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
1318

1319
1320
1321
1322


1323
1324
1325
1326
1327
1328
1329
1330
1331

1332
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
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

900
901
902
903

904
905
906
907

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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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
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
1318
1319
1320
1321

1322
1323
1324

1325
1326
1327

1328
1329
1330
1331
1332
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

1430
1431
1432

1433
1434
1435


1436
1437
1438
1439
1440
1441
1442
1443
1444
1445

1446
1447
1448

1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464

1465




1466
1467
1468


1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490

1491
1492

1493
1494

1495
1496








1497
1498
1499
1500
1501
1502
1503







-
+



-
+








-
+







-
+

-
+







-
+





-
+


-
+


-
+


-
+

-
+


-
+





-
+


-
+


-
+


-
+


-
-
-
-
-
+
+
+
+
+

-
-
-
+
+
+


-
+


-
+


-
+

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

-
+
-
-
+
+

+


-
+

+
+
+

-
+

-
+
-
-
+


-
+

-
-
+
+

-
+

-
-
+
+

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

-
+


-
+

-
-
-

-
+



-
+



-
+

-
-
+
+

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

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










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




-
-
-
+
+
+


-
-
+
+

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

-
+


-
+


-
+


-
+

+
+
+

-
+


-
+

-
-
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







-
-
-
+
+
+

-
-
+
+




-
+


-
+


-
+


-
+

-
-
+
+


-
+

-
-
+
+

-
+

-
+



-
+





-
+




-
+









-
+

-
+




-
-
-
-
+
+
+
+
+
+
+








-
+

-
+



















-
+

-
+

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

-
+





-
+


-
+

-
-
+
+


-
+










-
+




-
-
-
-
+
+
+
+











-
+






-
+






-
+

-
+

-
+









+
+
+
+
+
+

-
+


-
+


-
+


-
+


-
+


-
+

+
+
+

-
+


-
+


-
+



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



-
+



-
+




-
-
+
+
+
+
+

-
-
+
+
+
+
+
+
+
+








-
+





+
-
+




-
+




















-
+


-
+


-
-
+
+








-
+


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



-
+
-
-
-
-
+
+

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












-
+

-
+

-
+

-
-
-
-
-
-
-
-







	    }
	  else if (CPU_IS_HP_MC68K (cpu))
	    puts ("m68k-hitachi-hiuxwe2");
	  else puts ("unknown-hitachi-hiuxwe2");
	  exit (0);
	}
EOF
	$CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
	$CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` &&
		{ echo "$SYSTEM_NAME"; exit; }
	echo unknown-hitachi-hiuxwe2
	exit ;;
    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*)
	echo hppa1.1-hp-bsd
	exit ;;
    9000/8??:4.3bsd:*:*)
	echo hppa1.0-hp-bsd
	exit ;;
    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
	echo hppa1.0-hp-mpeix
	exit ;;
    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*)
	echo hppa1.1-hp-osf
	exit ;;
    hp8??:OSF1:*:*)
	echo hppa1.0-hp-osf
	exit ;;
    i*86:OSF1:*:*)
	if [ -x /usr/sbin/sysversion ] ; then
	    echo ${UNAME_MACHINE}-unknown-osf1mk
	    echo "$UNAME_MACHINE"-unknown-osf1mk
	else
	    echo ${UNAME_MACHINE}-unknown-osf1
	    echo "$UNAME_MACHINE"-unknown-osf1
	fi
	exit ;;
    parisc*:Lites*:*:*)
	echo hppa1.1-hp-lites
	exit ;;
    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
	echo c1-convex-bsd
        exit ;;
	exit ;;
    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
	if getsysinfo -f scalar_acc
	then echo c32-convex-bsd
	else echo c2-convex-bsd
	fi
        exit ;;
	exit ;;
    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
	echo c34-convex-bsd
        exit ;;
	exit ;;
    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
	echo c38-convex-bsd
        exit ;;
	exit ;;
    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
	echo c4-convex-bsd
        exit ;;
	exit ;;
    CRAY*Y-MP:*:*:*)
	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
	echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
	exit ;;
    CRAY*[A-Z]90:*:*:*)
	echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
	echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \
	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
	      -e 's/\.[^.]*$/.X/'
	exit ;;
    CRAY*TS:*:*:*)
	echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
	echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
	exit ;;
    CRAY*T3E:*:*:*)
	echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
	echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
	exit ;;
    CRAY*SV1:*:*:*)
	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
	echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
	exit ;;
    *:UNICOS/mp:*:*)
	echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
	echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
	exit ;;
    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
        exit ;;
	FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
	FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
	FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'`
	echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
	exit ;;
    5000:UNIX_System_V:4.*:*)
        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
        FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
        echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
	FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
	FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
	echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
	exit ;;
    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
	echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE"
	exit ;;
    sparc*:BSD/OS:*:*)
	echo sparc-unknown-bsdi${UNAME_RELEASE}
	echo sparc-unknown-bsdi"$UNAME_RELEASE"
	exit ;;
    *:BSD/OS:*:*)
	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
	echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE"
	exit ;;
    *:FreeBSD:*:*)
	case ${UNAME_MACHINE} in
	    pc98)
		echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
    arm:FreeBSD:*:*)
	UNAME_PROCESSOR=`uname -p`
	set_cc_for_build
	if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
	    | grep -q __ARM_PCS_VFP
	then
	    echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabi
	else
	    echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabihf
	fi
	exit ;;
    *:FreeBSD:*:*)
	UNAME_PROCESSOR=`/usr/bin/uname -p`
	case "$UNAME_PROCESSOR" in
	    amd64)
		echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
		UNAME_PROCESSOR=x86_64 ;;
	    *)
		echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
	    i386)
		UNAME_PROCESSOR=i586 ;;
	esac
	echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`"
	exit ;;
    i*:CYGWIN*:*)
	echo ${UNAME_MACHINE}-pc-cygwin
	echo "$UNAME_MACHINE"-pc-cygwin
	exit ;;
    *:MINGW64*:*)
	echo "$UNAME_MACHINE"-pc-mingw64
	exit ;;
    *:MINGW*:*)
	echo ${UNAME_MACHINE}-pc-mingw32
	echo "$UNAME_MACHINE"-pc-mingw32
	exit ;;
    i*:windows32*:*)
    *:MSYS*:*)
    	# uname -m includes "-pc" on this system.
    	echo ${UNAME_MACHINE}-mingw32
	echo "$UNAME_MACHINE"-pc-msys
	exit ;;
    i*:PW*:*)
	echo ${UNAME_MACHINE}-pc-pw32
	echo "$UNAME_MACHINE"-pc-pw32
	exit ;;
    *:Interix*:[3456]*)
    	case ${UNAME_MACHINE} in
    *:Interix*:*)
	case "$UNAME_MACHINE" in
	    x86)
		echo i586-pc-interix${UNAME_RELEASE}
		echo i586-pc-interix"$UNAME_RELEASE"
		exit ;;
	    EM64T | authenticamd)
		echo x86_64-unknown-interix${UNAME_RELEASE}
	    authenticamd | genuineintel | EM64T)
		echo x86_64-unknown-interix"$UNAME_RELEASE"
		exit ;;
	esac ;;
    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
	echo i${UNAME_MACHINE}-pc-mks
	exit ;;
	    IA64)
		echo ia64-unknown-interix"$UNAME_RELEASE"
		exit ;;
    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
	# How do we know it's Interix rather than the generic POSIX subsystem?
	# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
	# UNAME_MACHINE based on the output of uname instead of i386?
	echo i586-pc-interix
	exit ;;
	esac ;;
    i*:UWIN*:*)
	echo ${UNAME_MACHINE}-pc-uwin
	echo "$UNAME_MACHINE"-pc-uwin
	exit ;;
    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
	echo x86_64-unknown-cygwin
	echo x86_64-pc-cygwin
	exit ;;
    p*:CYGWIN*:*)
	echo powerpcle-unknown-cygwin
	exit ;;
    prep*:SunOS:5.*:*)
	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
	echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
	exit ;;
    *:GNU:*:*)
	# the GNU system
	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
	echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`"
	exit ;;
    *:GNU/*:*:*)
	# other systems with GNU libc and userland
	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
	echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC"
	exit ;;
    i*86:Minix:*:*)
	echo ${UNAME_MACHINE}-pc-minix
    *:Minix:*:*)
	echo "$UNAME_MACHINE"-unknown-minix
	exit ;;
    arm*:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    avr32*:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    cris:Linux:*:*)
	echo cris-axis-linux-${LIBC}
	exit ;;
    crisv32:Linux:*:*)
	echo crisv32-axis-linux-${LIBC}
	exit ;;
    frv:Linux:*:*)
    	echo frv-unknown-linux-${LIBC}
	exit ;;
    ia64:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
    aarch64:Linux:*:*)
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    m32r*:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
    aarch64_be:Linux:*:*)
	UNAME_MACHINE=aarch64_be
	exit ;;
    m68*:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    mips:Linux:*:*)
	eval $set_cc_for_build
	sed 's/^	//' << EOF >$dummy.c
	#undef CPU
	#undef mips
	#undef mipsel
	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
	CPU=mipsel
	#else
	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
	CPU=mips
	#else
	CPU=
	#endif
	#endif
EOF
	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
	    /^CPU/{
		s: ::g
		p
	    }'`"
	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
	;;
    mips64:Linux:*:*)
	eval $set_cc_for_build
	sed 's/^	//' << EOF >$dummy.c
	#undef CPU
	#undef mips64
	#undef mips64el
	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
	CPU=mips64el
	#else
	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
	CPU=mips64
	#else
	CPU=
	#endif
	#endif
EOF
	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
	    /^CPU/{
		s: ::g
		p
	    }'`"
	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
	;;
    or32:Linux:*:*)
	echo or32-unknown-linux-${LIBC}
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    ppc:Linux:*:*)
	echo powerpc-unknown-linux-${LIBC}
	exit ;;
    ppc64:Linux:*:*)
	echo powerpc64-unknown-linux-${LIBC}
	exit ;;
    alpha:Linux:*:*)
	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
	  EV5)   UNAME_MACHINE=alphaev5 ;;
	  EV56)  UNAME_MACHINE=alphaev56 ;;
	  PCA56) UNAME_MACHINE=alphapca56 ;;
	  PCA57) UNAME_MACHINE=alphapca56 ;;
	  EV6)   UNAME_MACHINE=alphaev6 ;;
	  EV67)  UNAME_MACHINE=alphaev67 ;;
	  EV68*) UNAME_MACHINE=alphaev68 ;;
        esac
	objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
	if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	esac
	objdump --private-headers /bin/sh | grep -q ld.so.1
	if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    arc:Linux:*:* | arceb:Linux:*:*)
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    arm*:Linux:*:*)
	set_cc_for_build
	if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
	    | grep -q __ARM_EABI__
	then
	    echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	else
	    if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
		| grep -q __ARM_PCS_VFP
	    then
		echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi
	    else
		echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf
	    fi
	fi
	exit ;;
    avr32*:Linux:*:*)
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    cris:Linux:*:*)
	echo "$UNAME_MACHINE"-axis-linux-"$LIBC"
	exit ;;
    crisv32:Linux:*:*)
	echo "$UNAME_MACHINE"-axis-linux-"$LIBC"
	exit ;;
    e2k:Linux:*:*)
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    frv:Linux:*:*)
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    hexagon:Linux:*:*)
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    i*86:Linux:*:*)
	echo "$UNAME_MACHINE"-pc-linux-"$LIBC"
	exit ;;
    ia64:Linux:*:*)
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    k1om:Linux:*:*)
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    m32r*:Linux:*:*)
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    m68*:Linux:*:*)
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    mips:Linux:*:* | mips64:Linux:*:*)
	set_cc_for_build
	IS_GLIBC=0
	test x"${LIBC}" = xgnu && IS_GLIBC=1
	sed 's/^	//' << EOF > "$dummy.c"
	#undef CPU
	#undef mips
	#undef mipsel
	#undef mips64
	#undef mips64el
	#if ${IS_GLIBC} && defined(_ABI64)
	LIBCABI=gnuabi64
	#else
	#if ${IS_GLIBC} && defined(_ABIN32)
	LIBCABI=gnuabin32
	#else
	LIBCABI=${LIBC}
	#endif
	#endif

	#if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
	CPU=mipsisa64r6
	#else
	#if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
	CPU=mipsisa32r6
	#else
	#if defined(__mips64)
	CPU=mips64
	#else
	CPU=mips
	#endif
	#endif
	#endif

	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
	MIPS_ENDIAN=el
	#else
	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
	MIPS_ENDIAN=
	#else
	MIPS_ENDIAN=
	#endif
	#endif
EOF
	eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'`"
	test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; }
	;;
    mips64el:Linux:*:*)
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    openrisc*:Linux:*:*)
	echo or1k-unknown-linux-"$LIBC"
	exit ;;
    or32:Linux:*:* | or1k*:Linux:*:*)
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    padre:Linux:*:*)
	echo sparc-unknown-linux-"$LIBC"
	exit ;;
    parisc64:Linux:*:* | hppa64:Linux:*:*)
	echo hppa64-unknown-linux-"$LIBC"
	exit ;;
    parisc:Linux:*:* | hppa:Linux:*:*)
	# Look for CPU level
	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
	  PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
	  PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
	  *)    echo hppa-unknown-linux-${LIBC} ;;
	  PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;;
	  PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;;
	  *)    echo hppa-unknown-linux-"$LIBC" ;;
	esac
	exit ;;
    parisc64:Linux:*:* | hppa64:Linux:*:*)
	echo hppa64-unknown-linux-${LIBC}
    ppc64:Linux:*:*)
	echo powerpc64-unknown-linux-"$LIBC"
	exit ;;
    ppc:Linux:*:*)
	echo powerpc-unknown-linux-"$LIBC"
	exit ;;
    ppc64le:Linux:*:*)
	echo powerpc64le-unknown-linux-"$LIBC"
	exit ;;
    ppcle:Linux:*:*)
	echo powerpcle-unknown-linux-"$LIBC"
	exit ;;
    riscv32:Linux:*:* | riscv64:Linux:*:*)
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    s390:Linux:*:* | s390x:Linux:*:*)
	echo ${UNAME_MACHINE}-ibm-linux
	echo "$UNAME_MACHINE"-ibm-linux-"$LIBC"
	exit ;;
    sh64*:Linux:*:*)
    	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    sh*:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    sparc:Linux:*:* | sparc64:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    tile*:Linux:*:*)
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    vax:Linux:*:*)
	echo ${UNAME_MACHINE}-dec-linux-${LIBC}
	echo "$UNAME_MACHINE"-dec-linux-"$LIBC"
	exit ;;
    x86_64:Linux:*:*)
	echo x86_64-unknown-linux-${LIBC}
	echo "$UNAME_MACHINE"-pc-linux-"$LIBC"
	exit ;;
    xtensa:Linux:*:*)
    	echo xtensa-unknown-linux-${LIBC}
    xtensa*:Linux:*:*)
	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
	exit ;;
    i*86:Linux:*:*)
	# The BFD linker knows what the default object file format is, so
	# first see if it will tell us. cd to the root directory to prevent
	# problems with other programs or directories called `ld' in the path.
	# Set LC_ALL=C to ensure ld outputs messages in English.
	ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
			 | sed -ne '/supported targets:/!d
				    s/[ 	][ 	]*/ /g
				    s/.*supported targets: *//
				    s/ .*//
				    p'`
        case "$ld_supported_targets" in
	  elf32-i386)
		TENTATIVE="${UNAME_MACHINE}-pc-linux-${LIBC}"
		;;
	  a.out-i386-linux)
		echo "${UNAME_MACHINE}-pc-linux-${LIBC}aout"
		exit ;;
	  coff-i386)
		echo "${UNAME_MACHINE}-pc-linux-${LIBC}coff"
		exit ;;
	  "")
		# Either a pre-BFD a.out linker (linux-gnuoldld) or
		# one that does not give us useful --help.
		echo "${UNAME_MACHINE}-pc-linux-${LIBC}oldld"
		exit ;;
	esac
	# This should get integrated into the C code below, but now we hack
	if [ "$LIBC" != "gnu" ] ; then echo "$TENTATIVE" && exit 0 ; fi
	# Determine whether the default compiler is a.out or elf
	eval $set_cc_for_build
	sed 's/^	//' << EOF >$dummy.c
	#include <features.h>
	#ifdef __ELF__
	# ifdef __GLIBC__
	#  if __GLIBC__ >= 2
	LIBC=gnu
	#  else
	LIBC=gnulibc1
	#  endif
	# else
	LIBC=gnulibc1
	# endif
	#else
	#if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
	LIBC=gnu
	#else
	LIBC=gnuaout
	#endif
	#endif
	#ifdef __dietlibc__
	LIBC=dietlibc
	#endif
EOF
	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
	    /^LIBC/{
		s: ::g
		p
	    }'`"
	test x"${LIBC}" != x && {
		echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
		exit
	}
	test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
	;;
    i*86:DYNIX/ptx:4*:*)
	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
	# earlier versions are messed up and put the nodename in both
	# sysname and nodename.
	echo i386-sequent-sysv4
	exit ;;
    i*86:UNIX_SV:4.2MP:2.*)
        # Unixware is an offshoot of SVR4, but it has its own version
        # number series starting with 2...
        # I am not positive that other SVR4 systems won't match this,
	# Unixware is an offshoot of SVR4, but it has its own version
	# number series starting with 2...
	# I am not positive that other SVR4 systems won't match this,
	# I just have to hope.  -- rms.
        # Use sysv4.2uw... so that sysv4* matches it.
	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
	# Use sysv4.2uw... so that sysv4* matches it.
	echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION"
	exit ;;
    i*86:OS/2:*:*)
	# If we were able to find `uname', then EMX Unix compatibility
	# is probably installed.
	echo ${UNAME_MACHINE}-pc-os2-emx
	echo "$UNAME_MACHINE"-pc-os2-emx
	exit ;;
    i*86:XTS-300:*:STOP)
	echo ${UNAME_MACHINE}-unknown-stop
	echo "$UNAME_MACHINE"-unknown-stop
	exit ;;
    i*86:atheos:*:*)
	echo ${UNAME_MACHINE}-unknown-atheos
	echo "$UNAME_MACHINE"-unknown-atheos
	exit ;;
    i*86:syllable:*:*)
	echo ${UNAME_MACHINE}-pc-syllable
	echo "$UNAME_MACHINE"-pc-syllable
	exit ;;
    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
	echo i386-unknown-lynxos${UNAME_RELEASE}
    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
	echo i386-unknown-lynxos"$UNAME_RELEASE"
	exit ;;
    i*86:*DOS:*:*)
	echo ${UNAME_MACHINE}-pc-msdosdjgpp
	echo "$UNAME_MACHINE"-pc-msdosdjgpp
	exit ;;
    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
	UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
    i*86:*:4.*:*)
	UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'`
	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
		echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
		echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL"
	else
		echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
		echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL"
	fi
	exit ;;
    i*86:*:5:[678]*)
    	# UnixWare 7.x, OpenUNIX and OpenServer 6.
	# UnixWare 7.x, OpenUNIX and OpenServer 6.
	case `/bin/uname -X | grep "^Machine"` in
	    *486*)	     UNAME_MACHINE=i486 ;;
	    *Pentium)	     UNAME_MACHINE=i586 ;;
	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
	esac
	echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
	echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}"
	exit ;;
    i*86:*:3.2:*)
	if test -f /usr/options/cb.name; then
		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
		echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
		echo "$UNAME_MACHINE"-pc-isc"$UNAME_REL"
	elif /bin/uname -X 2>/dev/null >/dev/null ; then
		UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
		(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
		(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
			&& UNAME_MACHINE=i586
		(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
			&& UNAME_MACHINE=i686
		(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
			&& UNAME_MACHINE=i686
		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
		echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL"
	else
		echo ${UNAME_MACHINE}-pc-sysv32
		echo "$UNAME_MACHINE"-pc-sysv32
	fi
	exit ;;
    pc:*:*:*)
	# Left here for compatibility:
        # uname -m prints for DJGPP always 'pc', but it prints nothing about
        # the processor, so we play safe by assuming i386.
	echo i386-pc-msdosdjgpp
        exit ;;
	# uname -m prints for DJGPP always 'pc', but it prints nothing about
	# the processor, so we play safe by assuming i586.
	# Note: whatever this is, it MUST be the same as what config.sub
	# prints for the "djgpp" host, or else GDB configure will decide that
	# this is a cross-build.
	echo i586-pc-msdosdjgpp
	exit ;;
    Intel:Mach:3*:*)
	echo i386-pc-mach3
	exit ;;
    paragon:*:*:*)
	echo i860-intel-osf1
	exit ;;
    i860:*:4.*:*) # i860-SVR4
	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
	  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
	  echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4
	else # Add other i860-SVR4 vendors below as they are discovered.
	  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
	  echo i860-unknown-sysv"$UNAME_RELEASE"  # Unknown i860-SVR4
	fi
	exit ;;
    mini*:CTIX:SYS*5:*)
	# "miniframe"
	echo m68010-convergent-sysv
	exit ;;
    mc68k:UNIX:SYSTEM5:3.51m)
	echo m68k-convergent-sysv
	exit ;;
    M680?0:D-NIX:5.3:*)
	echo m68k-diab-dnix
	exit ;;
    M68*:*:R3V[5678]*:*)
	test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
	OS_REL=''
	test -r /etc/.relid \
	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
	  && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
	  && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
	  && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
	  && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
          && { echo i486-ncr-sysv4; exit; } ;;
	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
	  && { echo i486-ncr-sysv4; exit; } ;;
    NCR*:*:4.2:* | MPRAS*:*:4.2:*)
	OS_REL='.3'
	test -r /etc/.relid \
	    && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
	    && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
	    && { echo i586-ncr-sysv4.3"$OS_REL"; exit; }
	/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
	    && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
	echo m68k-unknown-lynxos${UNAME_RELEASE}
	echo m68k-unknown-lynxos"$UNAME_RELEASE"
	exit ;;
    mc68030:UNIX_System_V:4.*:*)
	echo m68k-atari-sysv4
	exit ;;
    TSUNAMI:LynxOS:2.*:*)
	echo sparc-unknown-lynxos${UNAME_RELEASE}
	echo sparc-unknown-lynxos"$UNAME_RELEASE"
	exit ;;
    rs6000:LynxOS:2.*:*)
	echo rs6000-unknown-lynxos${UNAME_RELEASE}
	echo rs6000-unknown-lynxos"$UNAME_RELEASE"
	exit ;;
    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
	echo powerpc-unknown-lynxos${UNAME_RELEASE}
    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
	echo powerpc-unknown-lynxos"$UNAME_RELEASE"
	exit ;;
    SM[BE]S:UNIX_SV:*:*)
	echo mips-dde-sysv${UNAME_RELEASE}
	echo mips-dde-sysv"$UNAME_RELEASE"
	exit ;;
    RM*:ReliantUNIX-*:*:*)
	echo mips-sni-sysv4
	exit ;;
    RM*:SINIX-*:*:*)
	echo mips-sni-sysv4
	exit ;;
    *:SINIX-*:*:*)
	if uname -p 2>/dev/null >/dev/null ; then
		UNAME_MACHINE=`(uname -p) 2>/dev/null`
		echo ${UNAME_MACHINE}-sni-sysv4
		echo "$UNAME_MACHINE"-sni-sysv4
	else
		echo ns32k-sni-sysv
	fi
	exit ;;
    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
                      # says <Richard.M.Bartel@ccMail.Census.GOV>
        echo i586-unisys-sysv4
        exit ;;
    PENTIUM:*:4.0*:*)	# Unisys `ClearPath HMP IX 4000' SVR4/MP effort
			# says <Richard.M.Bartel@ccMail.Census.GOV>
	echo i586-unisys-sysv4
	exit ;;
    *:UNIX_System_V:4*:FTX*)
	# From Gerald Hewes <hewes@openmarket.com>.
	# How about differentiating between stratus architectures? -djm
	echo hppa1.1-stratus-sysv4
	exit ;;
    *:*:*:FTX*)
	# From seanf@swdc.stratus.com.
	echo i860-stratus-sysv4
	exit ;;
    i*86:VOS:*:*)
	# From Paul.Green@stratus.com.
	echo ${UNAME_MACHINE}-stratus-vos
	echo "$UNAME_MACHINE"-stratus-vos
	exit ;;
    *:VOS:*:*)
	# From Paul.Green@stratus.com.
	echo hppa1.1-stratus-vos
	exit ;;
    mc68*:A/UX:*:*)
	echo m68k-apple-aux${UNAME_RELEASE}
	echo m68k-apple-aux"$UNAME_RELEASE"
	exit ;;
    news*:NEWS-OS:6*:*)
	echo mips-sony-newsos6
	exit ;;
    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
	if [ -d /usr/nec ]; then
	        echo mips-nec-sysv${UNAME_RELEASE}
		echo mips-nec-sysv"$UNAME_RELEASE"
	else
	        echo mips-unknown-sysv${UNAME_RELEASE}
		echo mips-unknown-sysv"$UNAME_RELEASE"
	fi
        exit ;;
	exit ;;
    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
	echo powerpc-be-beos
	exit ;;
    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
	echo powerpc-apple-beos
	exit ;;
    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
	echo i586-pc-beos
	exit ;;
    BePC:Haiku:*:*)	# Haiku running on Intel PC compatible.
	echo i586-pc-haiku
	exit ;;
    x86_64:Haiku:*:*)
	echo x86_64-unknown-haiku
	exit ;;
    SX-4:SUPER-UX:*:*)
	echo sx4-nec-superux${UNAME_RELEASE}
	echo sx4-nec-superux"$UNAME_RELEASE"
	exit ;;
    SX-5:SUPER-UX:*:*)
	echo sx5-nec-superux${UNAME_RELEASE}
	echo sx5-nec-superux"$UNAME_RELEASE"
	exit ;;
    SX-6:SUPER-UX:*:*)
	echo sx6-nec-superux${UNAME_RELEASE}
	echo sx6-nec-superux"$UNAME_RELEASE"
	exit ;;
    SX-7:SUPER-UX:*:*)
	echo sx7-nec-superux${UNAME_RELEASE}
	echo sx7-nec-superux"$UNAME_RELEASE"
	exit ;;
    SX-8:SUPER-UX:*:*)
	echo sx8-nec-superux${UNAME_RELEASE}
	echo sx8-nec-superux"$UNAME_RELEASE"
	exit ;;
    SX-8R:SUPER-UX:*:*)
	echo sx8r-nec-superux${UNAME_RELEASE}
	echo sx8r-nec-superux"$UNAME_RELEASE"
	exit ;;
    SX-ACE:SUPER-UX:*:*)
	echo sxace-nec-superux"$UNAME_RELEASE"
	exit ;;
    Power*:Rhapsody:*:*)
	echo powerpc-apple-rhapsody${UNAME_RELEASE}
	echo powerpc-apple-rhapsody"$UNAME_RELEASE"
	exit ;;
    *:Rhapsody:*:*)
	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
	echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE"
	exit ;;
    *:Darwin:*:*)
	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
	UNAME_PROCESSOR=`uname -p`
	case $UNAME_PROCESSOR in
	    unknown) UNAME_PROCESSOR=powerpc ;;
	esac
	if command -v xcode-select > /dev/null 2> /dev/null && \
		! xcode-select --print-path > /dev/null 2> /dev/null ; then
	    # Avoid executing cc if there is no toolchain installed as
	    # cc will be a stub that puts up a graphical alert
	    # prompting the user to install developer tools.
	    CC_FOR_BUILD=no_compiler_found
	else
	    set_cc_for_build
	fi
	if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
	    if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
		   (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
		   grep IS_64BIT_ARCH >/dev/null
	    then
		case $UNAME_PROCESSOR in
		    i386) UNAME_PROCESSOR=x86_64 ;;
		    powerpc) UNAME_PROCESSOR=powerpc64 ;;
		esac
	    fi
	    # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
	    if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
		   (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
		   grep IS_PPC >/dev/null
	    then
	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
		UNAME_PROCESSOR=powerpc
	    fi
	elif test "$UNAME_PROCESSOR" = i386 ; then
	    # uname -m returns i386 or x86_64
	    UNAME_PROCESSOR=$UNAME_MACHINE
	fi
	echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE"
	exit ;;
    *:procnto*:*:* | *:QNX:[0123456789]*:*)
	UNAME_PROCESSOR=`uname -p`
	if test "$UNAME_PROCESSOR" = "x86"; then
	if test "$UNAME_PROCESSOR" = x86; then
		UNAME_PROCESSOR=i386
		UNAME_MACHINE=pc
	fi
	echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
	echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE"
	exit ;;
    *:QNX:*:4*)
	echo i386-pc-qnx
	exit ;;
    NSE-?:NONSTOP_KERNEL:*:*)
	echo nse-tandem-nsk${UNAME_RELEASE}
    NEO-*:NONSTOP_KERNEL:*:*)
	echo neo-tandem-nsk"$UNAME_RELEASE"
	exit ;;
    NSE-*:NONSTOP_KERNEL:*:*)
	echo nse-tandem-nsk"$UNAME_RELEASE"
	exit ;;
    NSR-?:NONSTOP_KERNEL:*:*)
	echo nsr-tandem-nsk${UNAME_RELEASE}
    NSR-*:NONSTOP_KERNEL:*:*)
	echo nsr-tandem-nsk"$UNAME_RELEASE"
	exit ;;
    NSV-*:NONSTOP_KERNEL:*:*)
	echo nsv-tandem-nsk"$UNAME_RELEASE"
	exit ;;
    NSX-*:NONSTOP_KERNEL:*:*)
	echo nsx-tandem-nsk"$UNAME_RELEASE"
	exit ;;
    *:NonStop-UX:*:*)
	echo mips-compaq-nonstopux
	exit ;;
    BS2000:POSIX*:*:*)
	echo bs2000-siemens-sysv
	exit ;;
    DS/*:UNIX_System_V:*:*)
	echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
	echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE"
	exit ;;
    *:Plan9:*:*)
	# "uname -m" is not consistent, so use $cputype instead. 386
	# is converted to i386 for consistency with other x86
	# operating systems.
	# shellcheck disable=SC2154
	if test "$cputype" = "386"; then
	if test "$cputype" = 386; then
	    UNAME_MACHINE=i386
	else
	    UNAME_MACHINE="$cputype"
	fi
	echo ${UNAME_MACHINE}-unknown-plan9
	echo "$UNAME_MACHINE"-unknown-plan9
	exit ;;
    *:TOPS-10:*:*)
	echo pdp10-unknown-tops10
	exit ;;
    *:TENEX:*:*)
	echo pdp10-unknown-tenex
	exit ;;
    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
	echo pdp10-dec-tops20
	exit ;;
    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
	echo pdp10-xkl-tops20
	exit ;;
    *:TOPS-20:*:*)
	echo pdp10-unknown-tops20
	exit ;;
    *:ITS:*:*)
	echo pdp10-unknown-its
	exit ;;
    SEI:*:*:SEIUX)
        echo mips-sei-seiux${UNAME_RELEASE}
	echo mips-sei-seiux"$UNAME_RELEASE"
	exit ;;
    *:DragonFly:*:*)
	echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
	echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`"
	exit ;;
    *:*VMS:*:*)
    	UNAME_MACHINE=`(uname -p) 2>/dev/null`
	case "${UNAME_MACHINE}" in
	UNAME_MACHINE=`(uname -p) 2>/dev/null`
	case "$UNAME_MACHINE" in
	    A*) echo alpha-dec-vms ; exit ;;
	    I*) echo ia64-dec-vms ; exit ;;
	    V*) echo vax-dec-vms ; exit ;;
	esac ;;
    *:XENIX:*:SysV)
	echo i386-pc-xenix
	exit ;;
    i*86:skyos:*:*)
	echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
	echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`"
	exit ;;
    i*86:rdos:*:*)
	echo ${UNAME_MACHINE}-pc-rdos
	echo "$UNAME_MACHINE"-pc-rdos
	exit ;;
    i*86:AROS:*:*)
	echo "$UNAME_MACHINE"-pc-aros
	exit ;;
    x86_64:VMkernel:*:*)
	echo "$UNAME_MACHINE"-unknown-esx
	exit ;;
    amd64:Isilon\ OneFS:*:*)
	echo x86_64-unknown-onefs
	exit ;;
    *:Unleashed:*:*)
	echo "$UNAME_MACHINE"-unknown-unleashed"$UNAME_RELEASE"
	exit ;;
esac

#echo '(No uname command or uname output not recognized.)' 1>&2
# No uname command or uname output not recognized.
#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2

eval $set_cc_for_build
cat >$dummy.c <<EOF
set_cc_for_build
cat > "$dummy.c" <<EOF
#ifdef _SEQUENT_
# include <sys/types.h>
# include <sys/utsname.h>
#include <sys/types.h>
#include <sys/utsname.h>
#endif
#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
#include <signal.h>
#if defined(_SIZE_T_) || defined(SIGLOST)
#include <sys/utsname.h>
#endif
#endif
#endif
main ()
{
#if defined (sony)
#if defined (MIPSEB)
  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
     I don't know....  */
  printf ("mips-sony-bsd\n"); exit (0);
#else
#include <sys/param.h>
  printf ("m68k-sony-newsos%s\n",
#ifdef NEWSOS4
          "4"
  "4"
#else
	  ""
  ""
#endif
         ); exit (0);
  ); exit (0);
#endif
#endif

#if defined (__arm) && defined (__acorn) && defined (__unix)
  printf ("arm-acorn-riscix\n"); exit (0);
#endif

#if defined (hp300) && !defined (hpux)
  printf ("m68k-hp-bsd\n"); exit (0);
#endif

#if defined (NeXT)
#if !defined (__ARCHITECTURE__)
#define __ARCHITECTURE__ "m68k"
#endif
  int version;
1406
1407
1408
1409
1410
1411
1412
1413

1414
1415

1416
1417
1418
1419
1420
1421
1422
1423







1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445



































1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456

1457
1458
1459

1460
1461

1462
1463




1464
1465
1466


1467
1468
1469
1470


1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486

1487
1488
1489
1490
1491
1492
1493
1494



1495
1496

1497
1498

1499
1500
1501
1502
1503



1504
1505
1506
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
1531
1532
1533
1534
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
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595

1596
1597
1598
1599
1600
1601

1602
1603

1604
1605
1606
1607
1608


1609
1610




1611
1612
















1613

1614
1615

1616



1617
1618
1619
1620

1621
1622

1623
1624




1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645




1646
1647
1648
1649
1650
1651
1652
1653
1654

1655
1656
1657
1658
1659







-
+

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



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










-
+



+

-
+

-
+
+
+
+

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


-

-
-
-
+
+
+

-
+

-
+

-
-
-
-
+
+
+


















-
-
-
-
+
+
+
+





-
+




#endif
#if defined (ns32000)
  printf ("ns32k-sequent-dynix\n"); exit (0);
#endif
#endif

#if defined (_SEQUENT_)
    struct utsname un;
  struct utsname un;

    uname(&un);
  uname(&un);

    if (strncmp(un.version, "V2", 2) == 0) {
	printf ("i386-sequent-ptx2\n"); exit (0);
    }
    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
	printf ("i386-sequent-ptx1\n"); exit (0);
    }
    printf ("i386-sequent-ptx\n"); exit (0);
  if (strncmp(un.version, "V2", 2) == 0) {
    printf ("i386-sequent-ptx2\n"); exit (0);
  }
  if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
    printf ("i386-sequent-ptx1\n"); exit (0);
  }
  printf ("i386-sequent-ptx\n"); exit (0);

#endif

#if defined (vax)
# if !defined (ultrix)
#  include <sys/param.h>
#  if defined (BSD)
#   if BSD == 43
      printf ("vax-dec-bsd4.3\n"); exit (0);
#   else
#    if BSD == 199006
      printf ("vax-dec-bsd4.3reno\n"); exit (0);
#    else
      printf ("vax-dec-bsd\n"); exit (0);
#    endif
#   endif
#  else
    printf ("vax-dec-bsd\n"); exit (0);
#  endif
# else
    printf ("vax-dec-ultrix\n"); exit (0);
# endif
#if !defined (ultrix)
#include <sys/param.h>
#if defined (BSD)
#if BSD == 43
  printf ("vax-dec-bsd4.3\n"); exit (0);
#else
#if BSD == 199006
  printf ("vax-dec-bsd4.3reno\n"); exit (0);
#else
  printf ("vax-dec-bsd\n"); exit (0);
#endif
#endif
#else
  printf ("vax-dec-bsd\n"); exit (0);
#endif
#else
#if defined(_SIZE_T_) || defined(SIGLOST)
  struct utsname un;
  uname (&un);
  printf ("vax-dec-ultrix%s\n", un.release); exit (0);
#else
  printf ("vax-dec-ultrix\n"); exit (0);
#endif
#endif
#endif
#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
#if defined(_SIZE_T_) || defined(SIGLOST)
  struct utsname *un;
  uname (&un);
  printf ("mips-dec-ultrix%s\n", un.release); exit (0);
#else
  printf ("mips-dec-ultrix\n"); exit (0);
#endif
#endif
#endif

#if defined (alliant) && defined (i860)
  printf ("i860-alliant-bsd\n"); exit (0);
#endif

  exit (1);
}
EOF

$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`$dummy` &&
	{ echo "$SYSTEM_NAME"; exit; }

# Apollos put the system type in the environment.
test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; }

test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
echo "$0: unable to guess system type" >&2

# Convex versions that predate uname can use getsysinfo(1)
case "$UNAME_MACHINE:$UNAME_SYSTEM" in
    mips:Linux | mips64:Linux)
	# If we got here on MIPS GNU/Linux, output extra information.
	cat >&2 <<EOF

if [ -x /usr/convex/getsysinfo ]
then
NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize
the system type. Please install a C compiler and try again.
    case `getsysinfo -f cpu_type` in
    c1*)
	echo c1-convex-bsd
	exit ;;
EOF
	;;
    c2*)
	if getsysinfo -f scalar_acc
	then echo c32-convex-bsd
	else echo c2-convex-bsd
	fi
	exit ;;
    c34*)
	echo c34-convex-bsd
	exit ;;
    c38*)
	echo c38-convex-bsd
	exit ;;
    c4*)
	echo c4-convex-bsd
	exit ;;
    esac
esac
fi

cat >&2 <<EOF
$0: unable to guess system type

This script, last modified $timestamp, has failed to recognize
the operating system you are using. It is advised that you
download the most up to date version of the config scripts from
This script (version $timestamp), has failed to recognize the
operating system you are using. If your script is old, overwrite *all*
copies of config.guess and config.sub with the latest versions from:

  http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
  https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
and
  http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
  https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub

If the version you run ($0) is already up to date, please
send the following data and any information you think might be
pertinent to <config-patches@gnu.org> in order to provide the needed
information to handle your system.
If $0 has already been updated, send the following data and any
information you think might be pertinent to config-patches@gnu.org to
provide the necessary information to handle your system.

config.guess timestamp = $timestamp

uname -m = `(uname -m) 2>/dev/null || echo unknown`
uname -r = `(uname -r) 2>/dev/null || echo unknown`
uname -s = `(uname -s) 2>/dev/null || echo unknown`
uname -v = `(uname -v) 2>/dev/null || echo unknown`

/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`

hostinfo               = `(hostinfo) 2>/dev/null`
/bin/universe          = `(/bin/universe) 2>/dev/null`
/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
/bin/arch              = `(/bin/arch) 2>/dev/null`
/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`

UNAME_MACHINE = ${UNAME_MACHINE}
UNAME_RELEASE = ${UNAME_RELEASE}
UNAME_SYSTEM  = ${UNAME_SYSTEM}
UNAME_VERSION = ${UNAME_VERSION}
UNAME_MACHINE = "$UNAME_MACHINE"
UNAME_RELEASE = "$UNAME_RELEASE"
UNAME_SYSTEM  = "$UNAME_SYSTEM"
UNAME_VERSION = "$UNAME_VERSION"
EOF

exit 1

# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"
# End:

Deleted config.h.in.

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



































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/* config.h.in.  Generated from configure.ac by autoheader.  */

/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H

/* Define to 1 if you have the `fdatasync' function. */
#undef HAVE_FDATASYNC

/* Define to 1 if you have the `gmtime_r' function. */
#undef HAVE_GMTIME_R

/* Define to 1 if the system has the type `int16_t'. */
#undef HAVE_INT16_T

/* Define to 1 if the system has the type `int32_t'. */
#undef HAVE_INT32_T

/* Define to 1 if the system has the type `int64_t'. */
#undef HAVE_INT64_T

/* Define to 1 if the system has the type `int8_t'. */
#undef HAVE_INT8_T

/* Define to 1 if the system has the type `intptr_t'. */
#undef HAVE_INTPTR_T

/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H

/* Define to 1 if you have the `isnan' function. */
#undef HAVE_ISNAN

/* Define to 1 if you have the `localtime_r' function. */
#undef HAVE_LOCALTIME_R

/* Define to 1 if you have the `localtime_s' function. */
#undef HAVE_LOCALTIME_S

/* Define to 1 if you have the <malloc.h> header file. */
#undef HAVE_MALLOC_H

/* Define to 1 if you have the `malloc_usable_size' function. */
#undef HAVE_MALLOC_USABLE_SIZE

/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H

/* Define to 1 if you have the pread() function. */
#undef HAVE_PREAD

/* Define to 1 if you have the pread64() function. */
#undef HAVE_PREAD64

/* Define to 1 if you have the pwrite() function. */
#undef HAVE_PWRITE

/* Define to 1 if you have the pwrite64() function. */
#undef HAVE_PWRITE64

/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H

/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H

/* Define to 1 if you have the strchrnul() function */
#undef HAVE_STRCHRNUL

/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H

/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H

/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H

/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H

/* Define to 1 if the system has the type `uint16_t'. */
#undef HAVE_UINT16_T

/* Define to 1 if the system has the type `uint32_t'. */
#undef HAVE_UINT32_T

/* Define to 1 if the system has the type `uint64_t'. */
#undef HAVE_UINT64_T

/* Define to 1 if the system has the type `uint8_t'. */
#undef HAVE_UINT8_T

/* Define to 1 if the system has the type `uintptr_t'. */
#undef HAVE_UINTPTR_T

/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H

/* Define to 1 if you have the `usleep' function. */
#undef HAVE_USLEEP

/* Define to 1 if you have the utime() library function. */
#undef HAVE_UTIME

/* Define to the sub-directory in which libtool stores uninstalled libraries.
   */
#undef LT_OBJDIR

/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT

/* Define to the full name of this package. */
#undef PACKAGE_NAME

/* Define to the full name and version of this package. */
#undef PACKAGE_STRING

/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME

/* Define to the version of this package. */
#undef PACKAGE_VERSION

/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS

/* Number of bits in a file offset, on hosts where this is settable. */
#undef _FILE_OFFSET_BITS

/* Define for large files, on AIX-style hosts. */
#undef _LARGE_FILES

Changes to config.sub.

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


-
-
+
-

-
+

-
-
-
-
-
-
-
+
+
+


-
-
-
-
+
+
+
+


-
+
-
-




-
+
+
+


-
+
-






+
+
+


















-
+
-



-
+









-
-
+







#! /bin/sh
# Configuration validation subroutine script.
#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
#   2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
#   Copyright 1992-2019 Free Software Foundation, Inc.
#   Inc.

timestamp='2007-06-28'
timestamp='2019-05-23'

# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
# can handle that machine.  It does not imply ALL GNU software can.
#
# This file is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# along with this program; if not, see <https://www.gnu.org/licenses/>.
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
# 02110-1301, USA.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# the same distribution terms that you use for the rest of that
# program.  This Exception is an additional permission under section 7
# of the GNU General Public License, version 3 ("GPLv3").


# Please send patches to <config-patches@gnu.org>.  Submit a context
# Please send patches to <config-patches@gnu.org>.
# diff and a properly formatted ChangeLog entry.
#
# Configuration subroutine to validate and canonicalize a configuration type.
# Supply the specified configuration type as an argument.
# If it is invalid, we print an error message on stderr and exit with code 1.
# Otherwise, we print the canonical config type on stdout and succeed.

# You can get the latest version of this script from:
# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub

# This file is supposed to be the same for all GNU packages
# and recognize all the CPU types, system types and aliases
# that are meaningful with *any* GNU software.
# Each package is responsible for reporting which valid configurations
# it does not support.  The user should be able to distinguish
# a failure to support a valid configuration from a meaningless
# configuration.

# The goal of this file is to map all the various variations of a given
# machine specification into a single specification in the form:
#	CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
# or in some cases, the newer four-part form:
#	CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
# It is wrong to echo any other type of specification.

me=`echo "$0" | sed -e 's,.*/,,'`

usage="\
Usage: $0 [OPTION] CPU-MFR-OPSYS
Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
       $0 [OPTION] ALIAS

Canonicalize a configuration name.

Operation modes:
Options:
  -h, --help         print this help, then exit
  -t, --time-stamp   print date of last modification, then exit
  -v, --version      print version number, then exit

Report bugs and patches to <config-patches@gnu.org>."

version="\
GNU config.sub ($timestamp)

Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
Copyright 1992-2019 Free Software Foundation, Inc.

This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."

help="
Try \`$me --help' for more information."

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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662

663
664
665

666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702

703
704
705

706
707
708
709

710
711
712
713
714
715
716
717
718

719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734

735
736
737
738



739




740

741
742




743







744
745







746
747

748

749
750



751
752
753
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
900
901
902
903
904
905

906
907
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
935

936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964

965
966
967
968

969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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
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
1318
1319

1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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
1430
1431

1432
1433
1434

1435
1436
1437
1438
1439
1440

1441
1442
1443


1444
1445
1446

1447
1448
1449

1450
1451
1452

1453
1454
1455

1456
1457
1458

1459
1460
1461


1462
1463
1464


1465
1466
1467

1468
1469
1470


1471
1472
1473

1474
1475
1476

1477
1478
1479

1480
1481
1482

1483
1484
1485

1486
1487
1488

1489
1490
1491

1492
1493
1494

1495
1496
1497

1498
1499
1500

1501
1502
1503

1504
1505
1506


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

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
1574

1575
1576
1577

1578
1579
1580

1581
1582
1583

1584
1585
1586

1587
1588
1589

1590
1591
1592

1593
1594
1595

1596
1597
1598

1599
1600



1601

1602
1603
1604

1605
1606
1607

1608
1609
1610

1611
1612
1613

1614
1615
1616

1617
1618
1619

1620
1621
1622

1623
1624
1625

1626
1627
1628

1629
1630
1631
1632
1633
1634
1635
1636

1637
1638
1639
1640

1641
1642
1643
1644
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
638
639
640
641
642

643
644




645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667








668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693





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




712
713
714
715
716
717
718




719
720
721
722















723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
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
935




936
937
938
939
940
941
942
943
944
945


946
947







948




949
950
951
















952
953
954
955
956
957
958
959
960
961




962
963
964
965



966
967
968



969
970




971




972
973
974
975
976
977
978
979









980
981
982



983


984





985
986
987


988
989
990
991
992
993


994
995
996



997
998
999


1000
1001
1002
1003



1004
1005
1006
1007


1008








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
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
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
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
1574

1575
1576
1577

1578
1579
1580

1581
1582
1583

1584
1585
1586

1587
1588
1589

1590



1591
1592

1593
1594


1595
1596
1597
1598

1599
1600
1601

1602
1603
1604

1605
1606
1607

1608
1609
1610

1611
1612


1613
1614
1615


1616
1617
1618
1619

1620
1621


1622
1623
1624
1625

1626
1627
1628

1629
1630
1631

1632
1633
1634

1635
1636
1637

1638
1639
1640

1641
1642
1643

1644
1645
1646

1647
1648
1649

1650
1651
1652

1653
1654
1655

1656
1657


1658
1659
1660
1661

1662
1663
1664

1665
1666
1667

1668
1669
1670

1671
1672



1673

1674
1675
1676

1677
1678
1679

1680
1681
1682

1683
1684
1685

1686
1687
1688

1689
1690
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

1744
1745
1746

1747
1748
1749

1750
1751
1752
1753
1754
1755

1756
1757
1758

1759
1760
1761

1762
1763
1764

1765
1766
1767

1768
1769
1770

1771
1772
1773

1774
1775
1776

1777
1778
1779

1780
1781
1782

1783
1784
1785
1786

1787
1788
1789

1790
1791
1792
1793

1794
1795
1796
1797
1798







-
+




-
+















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

-
+

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

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

-
+
+
+

+
-
-
+
+


+
+
+
+
+
+




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

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

-
-
-
-
-
+
+

-
-
+
+

+
+
+
-
-
+
+

-
-
-
+
+

-
-
+
+
+

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

-
+
-
-
+

-
+

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

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

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

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

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


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


-
+

-
-
-
+
+
+

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

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

+
-
+
-
-
+
+
+

-
-
-
+
+

+
+
+
-
-
+
+
-

-
-
+
+
-

-
+
-
-
+
+
+
+

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

-
-
-
+
+
+
+
+
+
+
+

-
-
-
+
+
+

+
-
+
-
-
+

-
-
-
+
+

-
-
-
+
+
+

-
-
+
+
+


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

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

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

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

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

-
+
-
-
+

-
-
-
-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

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


-
-
+
+
-
+

-
-
+
+







-
+


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


-
-
+
+

-
-
-
-
-
+
+

-
+


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

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


-
-
-
+
+
+


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



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

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

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

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


-
-
-
+















-
-
-
+
+
+

-
-
+
+


-
+


-
+


-
+

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



-
+


-
+


-
+


-
+


-
+


-
+
-
-
-


-
+

-
-
+
+


-
+


-
+


-
+


-
+


-
+

-
-
+
+

-
-
+
+


-
+

-
-
+
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+

-
-
+
+


-
+


-
+


-
+


-
+

-
-
-

-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+

+
+
+

-
+






-
+
-
-
+

-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


+
+
+
-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+



-



-
+



-
+




    --help | --h* | -h )
       echo "$usage"; exit ;;
    -- )     # Stop option processing
       shift; break ;;
    - )	# Use stdin as input.
       break ;;
    -* )
       echo "$me: invalid option $1$help"
       echo "$me: invalid option $1$help" >&2
       exit 1 ;;

    *local*)
       # First pass through any local machine types.
       echo $1
       echo "$1"
       exit ;;

    * )
       break ;;
  esac
done

case $# in
 0) echo "$me: missing argument$help" >&2
    exit 1;;
 1) ;;
 *) echo "$me: too many arguments$help" >&2
    exit 1;;
esac

# Split fields of configuration type
# shellcheck disable=SC2162
IFS="-" read field1 field2 field3 field4 <<EOF
$1
EOF
# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
# Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
  nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
  uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
  storm-chaos* | os2-emx* | rtmk-nova*)
    os=-$maybe_os
    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
    ;;
  *)
    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
    if [ $basic_machine != $1 ]
    then os=`echo $1 | sed 's/.*-/-/'`
    else os=; fi
    ;;
esac

### Let's recognize common machines as not being operating systems so
### that things like config.sub decstation-3100 work.  We also

# Separate into logical components for further validation
case $1 in
	*-*-*-*-*)
		echo Invalid configuration \`"$1"\': more than four components >&2
		exit 1
		;;
	*-*-*-*)
		basic_machine=$field1-$field2
		os=$field3-$field4
		;;
	*-*-*)
		# Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two
		# parts
		maybe_os=$field2-$field3
		case $maybe_os in
			nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc \
			| linux-newlib* | linux-musl* | linux-uclibc* | uclinux-uclibc* \
			| uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \
			| netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \
			| storm-chaos* | os2-emx* | rtmk-nova*)
				basic_machine=$field1
				os=$maybe_os
				;;
			android-linux)
				basic_machine=$field1-unknown
				os=linux-android
				;;
			*)
				basic_machine=$field1-$field2
				os=$field3
				;;
		esac
		;;
	*-*)
		# A lone config we happen to match not fitting any pattern
		case $field1-$field2 in
			decstation-3100)
				basic_machine=mips-dec
				os=
				;;
			*-*)
				# Second component is usually, but not always the OS
				case $field2 in
					# Prevent following clause from handling this valid os
					sun*os*)
						basic_machine=$field1
						os=$field2
						;;
					# Manufacturers
					dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \
					| att* | 7300* | 3300* | delta* | motorola* | sun[234]* \
					| unicom* | ibm* | next | hp | isi* | apollo | altos* \
					| convergent* | ncr* | news | 32* | 3600* | 3100* \
					| hitachi* | c[123]* | convex* | sun | crds | omron* | dg \
					| ultra | tti* | harris | dolphin | highlevel | gould \
					| cbm | ns | masscomp | apple | axis | knuth | cray \
					| microblaze* | sim | cisco \
					| oki | wec | wrs | winbond)
						basic_machine=$field1-$field2
						os=
						;;
					*)
						basic_machine=$field1
						os=$field2
						;;
				esac
			;;
		esac
		;;
	*)
		# Convert single-component short-hands not valid as part of
		# multi-component configurations.
		case $field1 in
			386bsd)
				basic_machine=i386-pc
				os=bsd
				;;
			a29khif)
				basic_machine=a29k-amd
				os=udi
				;;
			adobe68k)
				basic_machine=m68010-adobe
				os=scout
				;;
			alliant)
				basic_machine=fx80-alliant
				os=
				;;
			altos | altos3068)
				basic_machine=m68k-altos
				os=
				;;
			am29k)
				basic_machine=a29k-none
				os=bsd
### recognize some manufacturers as not being operating systems, so we
### can provide default operating systems below.
case $os in
	-sun*os*)
		# Prevent following clause from handling this invalid input.
		;;
				;;
			amdahl)
				basic_machine=580-amdahl
				os=sysv
				;;
			amiga)
				basic_machine=m68k-unknown
				os=
				;;
			amigaos | amigados)
				basic_machine=m68k-unknown
				os=amigaos
				;;
			amigaunix | amix)
				basic_machine=m68k-unknown
				os=sysv4
				;;
			apollo68)
				basic_machine=m68k-apollo
				os=sysv
				;;
	-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
	-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
	-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
			apollo68bsd)
	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
	-apple | -axis | -knuth | -cray)
		os=
		basic_machine=$1
		;;
	-sim | -cisco | -oki | -wec | -winbond)
		os=
		basic_machine=$1
		;;
	-scout)
		;;
	-wrs)
		os=-vxworks
		basic_machine=$1
		;;
	-chorusos*)
		os=-chorusos
		basic_machine=$1
		;;
 	-chorusrdb)
 		os=-chorusrdb
		basic_machine=$1
 		;;
	-hiux*)
		os=-hiuxwe2
		;;
	-sco6)
		os=-sco5v6
		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
		;;
	-sco5)
		os=-sco3.2v5
		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
		;;
	-sco4)
		os=-sco3.2v4
		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
		;;
	-sco3.2.[4-9]*)
		os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
		;;
	-sco3.2v[4-9]*)
				basic_machine=m68k-apollo
				os=bsd
				;;
			aros)
				basic_machine=i386-pc
				os=aros
				;;
			aux)
				basic_machine=m68k-apple
				os=aux
				;;
			balance)
				basic_machine=ns32k-sequent
				os=dynix
				;;
			blackfin)
				basic_machine=bfin-unknown
				os=linux
				;;
			cegcc)
				basic_machine=arm-unknown
				os=cegcc
				;;
			convex-c1)
				basic_machine=c1-convex
				os=bsd
				;;
			convex-c2)
				basic_machine=c2-convex
				os=bsd
				;;
			convex-c32)
				basic_machine=c32-convex
				os=bsd
				;;
			convex-c34)
				basic_machine=c34-convex
				os=bsd
				;;
			convex-c38)
				basic_machine=c38-convex
				os=bsd
				;;
			cray)
				basic_machine=j90-cray
				os=unicos
				;;
			crds | unos)
				basic_machine=m68k-crds
				os=
				;;
			da30)
				basic_machine=m68k-da30
				os=
				;;
			decstation | pmax | pmin | dec3100 | decstatn)
				basic_machine=mips-dec
				os=
				;;
			delta88)
				basic_machine=m88k-motorola
				os=sysv3
				;;
			dicos)
				basic_machine=i686-pc
				os=dicos
				;;
			djgpp)
				basic_machine=i586-pc
				os=msdosdjgpp
				;;
			ebmon29k)
				basic_machine=a29k-amd
				os=ebmon
				;;
			es1800 | OSE68k | ose68k | ose | OSE)
				basic_machine=m68k-ericsson
				os=ose
				;;
			gmicro)
				basic_machine=tron-gmicro
				os=sysv
				;;
			go32)
				basic_machine=i386-pc
				os=go32
				;;
			h8300hms)
				basic_machine=h8300-hitachi
				os=hms
				;;
			h8300xray)
				basic_machine=h8300-hitachi
				os=xray
				;;
			h8500hms)
				basic_machine=h8500-hitachi
				os=hms
				;;
			harris)
				basic_machine=m88k-harris
				os=sysv3
				;;
			hp300)
				basic_machine=m68k-hp
				;;
			hp300bsd)
				basic_machine=m68k-hp
				os=bsd
				;;
			hp300hpux)
				basic_machine=m68k-hp
				os=hpux
				;;
			hppaosf)
				basic_machine=hppa1.1-hp
				os=osf
				;;
			hppro)
				basic_machine=hppa1.1-hp
				os=proelf
				;;
			i386mach)
				basic_machine=i386-mach
				os=mach
				;;
			vsta)
				basic_machine=i386-pc
				os=vsta
				;;
			isi68 | isi)
				basic_machine=m68k-isi
				os=sysv
				;;
			m68knommu)
				basic_machine=m68k-unknown
				os=linux
				;;
			magnum | m3230)
				basic_machine=mips-mips
				os=sysv
				;;
			merlin)
				basic_machine=ns32k-utek
				os=sysv
				;;
			mingw64)
				basic_machine=x86_64-pc
				os=mingw64
				;;
			mingw32)
				basic_machine=i686-pc
				os=mingw32
				;;
			mingw32ce)
				basic_machine=arm-unknown
				os=mingw32ce
				;;
			monitor)
				basic_machine=m68k-rom68k
				os=coff
				;;
			morphos)
				basic_machine=powerpc-unknown
				os=morphos
				;;
			moxiebox)
				basic_machine=moxie-unknown
				os=moxiebox
				;;
			msdos)
				basic_machine=i386-pc
				os=msdos
				;;
			msys)
				basic_machine=i686-pc
				os=msys
				;;
			mvs)
				basic_machine=i370-ibm
				os=mvs
				;;
			nacl)
				basic_machine=le32-unknown
				os=nacl
				;;
			ncr3000)
				basic_machine=i486-ncr
				os=sysv4
				;;
			netbsd386)
				basic_machine=i386-pc
				os=netbsd
				;;
			netwinder)
				basic_machine=armv4l-rebel
				os=linux
				;;
			news | news700 | news800 | news900)
				basic_machine=m68k-sony
				os=newsos
				;;
			news1000)
				basic_machine=m68030-sony
				os=newsos
				;;
			necv70)
				basic_machine=v70-nec
				os=sysv
				;;
			nh3000)
				basic_machine=m68k-harris
				os=cxux
				;;
			nh[45]000)
		# Don't forget version if it is 3.2v4 or newer.
		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
		;;
	-sco5v6*)
				basic_machine=m88k-harris
				os=cxux
				;;
			nindy960)
				basic_machine=i960-intel
				os=nindy
				;;
			mon960)
				basic_machine=i960-intel
				os=mon960
				;;
			nonstopux)
				basic_machine=mips-compaq
				os=nonstopux
				;;
			os400)
				basic_machine=powerpc-ibm
				os=os400
				;;
			OSE68000 | ose68000)
				basic_machine=m68000-ericsson
				os=ose
				;;
			os68k)
				basic_machine=m68k-none
				os=os68k
				;;
			paragon)
				basic_machine=i860-intel
				os=osf
				;;
			parisc)
		# Don't forget version if it is 3.2v4 or newer.
		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
		;;
	-sco*)
		os=-sco3.2v2
		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
		;;
	-udk*)
		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
		;;
	-isc)
		os=-isc2.2
		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
		;;
	-clix*)
		basic_machine=clipper-intergraph
		;;
	-isc*)
		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
		;;
	-lynx*)
		os=-lynxos
		;;
	-ptx*)
		basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
		;;
	-windowsnt*)
		os=`echo $os | sed -e 's/windowsnt/winnt/'`
		;;
	-psos*)
		os=-psos
		;;
	-mint | -mint[0-9]*)
		basic_machine=m68k-atari
		os=-mint
		;;
esac
				basic_machine=hppa-unknown
				os=linux
				;;
			pw32)
				basic_machine=i586-unknown
				os=pw32
				;;
			rdos | rdos64)
				basic_machine=x86_64-pc
				os=rdos
				;;
			rdos32)
				basic_machine=i386-pc
				os=rdos
				;;
			rom68k)
				basic_machine=m68k-rom68k
				os=coff
				;;
			sa29200)
				basic_machine=a29k-amd
				os=udi
				;;
			sei)
				basic_machine=mips-sei
				os=seiux
				;;
			sequent)
				basic_machine=i386-sequent
				os=
				;;
			sps7)
				basic_machine=m68k-bull
				os=sysv2
				;;
			st2000)
				basic_machine=m68k-tandem
				os=
				;;
			stratus)
				basic_machine=i860-stratus
				os=sysv4
				;;
			sun2)
				basic_machine=m68000-sun
				os=
				;;
			sun2os3)
				basic_machine=m68000-sun
				os=sunos3
				;;
			sun2os4)
				basic_machine=m68000-sun
				os=sunos4
				;;
			sun3)
				basic_machine=m68k-sun
				os=
				;;
			sun3os3)
				basic_machine=m68k-sun
				os=sunos3
				;;
			sun3os4)
				basic_machine=m68k-sun
				os=sunos4
				;;
			sun4)
				basic_machine=sparc-sun
				os=
				;;
			sun4os3)
				basic_machine=sparc-sun
				os=sunos3
				;;
			sun4os4)
				basic_machine=sparc-sun
				os=sunos4
				;;
			sun4sol2)
				basic_machine=sparc-sun
				os=solaris2
				;;
			sun386 | sun386i | roadrunner)
				basic_machine=i386-sun
				os=
				;;
			sv1)
				basic_machine=sv1-cray
				os=unicos
				;;
			symmetry)
				basic_machine=i386-sequent
				os=dynix
				;;
			t3e)
				basic_machine=alphaev5-cray
				os=unicos
				;;
			t90)
				basic_machine=t90-cray
				os=unicos
				;;
			toad1)
				basic_machine=pdp10-xkl
				os=tops20
				;;
			tpf)
				basic_machine=s390x-ibm
				os=tpf
				;;
			udi29k)
				basic_machine=a29k-amd
				os=udi
				;;
			ultra3)
				basic_machine=a29k-nyu
				os=sym1
				;;
			v810 | necv810)
				basic_machine=v810-nec
				os=none
				;;
			vaxv)
				basic_machine=vax-dec
				os=sysv
				;;
			vms)
				basic_machine=vax-dec
				os=vms
				;;
			vxworks960)
				basic_machine=i960-wrs
				os=vxworks
				;;
			vxworks68)
				basic_machine=m68k-wrs
				os=vxworks
				;;
			vxworks29k)
				basic_machine=a29k-wrs
				os=vxworks
				;;
			xbox)
				basic_machine=i686-pc
				os=mingw32
				;;
			ymp)
				basic_machine=ymp-cray
				os=unicos
				;;
			*)
				basic_machine=$1
				os=
				;;
		esac
		;;
esac

# Decode aliases for certain CPU-COMPANY combinations.
# Decode 1-component or ad-hoc basic machines
case $basic_machine in
	# Recognize the basic CPU types without company name.
	# Some are omitted here because they have special meanings below.
	1750a | 580 \
	| a29k \
	# Here we handle the default manufacturer of certain CPU types.  It is in
	# some cases the only manufacturer, in others, it is the most popular.
	w89k)
		cpu=hppa1.1
		vendor=winbond
		;;
	op50n)
		cpu=hppa1.1
		vendor=oki
		;;
	op60c)
		cpu=hppa1.1
		vendor=oki
		;;
	ibm*)
		cpu=i370
		vendor=ibm
		;;
	orion105)
		cpu=clipper
		vendor=highlevel
		;;
	mac | mpw | mac-mpw)
	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
	| am33_2.0 \
	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
	| bfin \
	| c4x | clipper \
	| d10v | d30v | dlx | dsp16xx | dvp \
	| fido | fr30 | frv \
		cpu=m68k
		vendor=apple
		;;
	pmac | pmac-mpw)
		cpu=powerpc
		vendor=apple
		;;

	# Recognize the various machine names and aliases which stand
	# for a CPU type and a company and sometimes even an OS.
	3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
		cpu=m68000
		vendor=att
		;;
	3b*)
		cpu=we32k
		vendor=att
		;;
	bluegene*)
		cpu=powerpc
		vendor=ibm
		os=cnk
		;;
	decsystem10* | dec10*)
		cpu=pdp10
		vendor=dec
	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
	| i370 | i860 | i960 | ia64 \
	| ip2k | iq2000 \
	| m32c | m32r | m32rle | m68000 | m68k | m88k \
	| maxq | mb | microblaze | mcore | mep \
		os=tops10
		;;
	decsystem20* | dec20*)
		cpu=pdp10
		vendor=dec
		os=tops20
		;;
	delta | 3300 | motorola-3300 | motorola-delta \
	      | 3300-motorola | delta-motorola)
		cpu=m68k
		vendor=motorola
		;;
	dpx2*)
		cpu=m68k
		vendor=bull
		os=sysv3
		;;
	encore | umax | mmax)
	| mips | mipsbe | mipseb | mipsel | mipsle \
	| mips16 \
	| mips64 | mips64el \
	| mips64vr | mips64vrel \
		cpu=ns32k
		vendor=encore
		;;
	elxsi)
		cpu=elxsi
		vendor=elxsi
		os=${os:-bsd}
	| mips64orion | mips64orionel \
	| mips64vr4100 | mips64vr4100el \
	| mips64vr4300 | mips64vr4300el \
	| mips64vr5000 | mips64vr5000el \
		;;
	fx2800)
		cpu=i860
		vendor=alliant
	| mips64vr5900 | mips64vr5900el \
	| mipsisa32 | mipsisa32el \
	| mipsisa32r2 | mipsisa32r2el \
	| mipsisa64 | mipsisa64el \
	| mipsisa64r2 | mipsisa64r2el \
	| mipsisa64sb1 | mipsisa64sb1el \
	| mipsisa64sr71k | mipsisa64sr71kel \
	| mipstx39 | mipstx39el \
	| mn10200 | mn10300 \
	| mt \
	| msp430 \
	| nios | nios2 \
	| ns16k | ns32k \
	| or32 \
	| pdp10 | pdp11 | pj | pjl \
		;;
	genix)
		cpu=ns32k
		vendor=ns
		;;
	h3050r* | hiux*)
		cpu=hppa1.1
		vendor=hitachi
		os=hiuxwe2
		;;
	hp3k9[0-9][0-9] | hp9[0-9][0-9])
		cpu=hppa1.0
		vendor=hp
		;;
	hp9k2[0-9][0-9] | hp9k31[0-9])
		cpu=m68000
		vendor=hp
		;;
	hp9k3[2-9][0-9])
		cpu=m68k
		vendor=hp
		;;
	hp9k6[0-9][0-9] | hp6[0-9][0-9])
		cpu=hppa1.0
		vendor=hp
		;;
	hp9k7[0-79][0-9] | hp7[0-79][0-9])
		cpu=hppa1.1
		vendor=hp
		;;
	hp9k78[0-9] | hp78[0-9])
		# FIXME: really hppa2.0-hp
		cpu=hppa1.1
		vendor=hp
		;;
	hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
		# FIXME: really hppa2.0-hp
		cpu=hppa1.1
		vendor=hp
		;;
	hp9k8[0-9][13679] | hp8[0-9][13679])
		cpu=hppa1.1
		vendor=hp
		;;
	hp9k8[0-9][0-9] | hp8[0-9][0-9])
		cpu=hppa1.0
		vendor=hp
		;;
	i*86v32)
		cpu=`echo "$1" | sed -e 's/86.*/86/'`
		vendor=pc
		os=sysv32
		;;
	i*86v4*)
		cpu=`echo "$1" | sed -e 's/86.*/86/'`
		vendor=pc
		os=sysv4
		;;
	i*86v)
		cpu=`echo "$1" | sed -e 's/86.*/86/'`
		vendor=pc
		os=sysv
		;;
	i*86sol2)
		cpu=`echo "$1" | sed -e 's/86.*/86/'`
		vendor=pc
		os=solaris2
		;;
	j90 | j90-cray)
		cpu=j90
		vendor=cray
		os=${os:-unicos}
		;;
	iris | iris4d)
		cpu=mips
		vendor=sgi
		case $os in
		    irix*)
			;;
		    *)
			os=irix4
			;;
		esac
		;;
	miniframe)
		cpu=m68000
		vendor=convergent
		;;
	*mint | mint[0-9]* | *MiNT | *MiNT[0-9]*)
		cpu=m68k
		vendor=atari
		os=mint
		;;
	news-3600 | risc-news)
	| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
	| pyramid \
	| score \
		cpu=mips
		vendor=sony
		os=newsos
		;;
	next | m*-next)
		cpu=m68k
		vendor=next
	| sh | sh[1234] | sh[24]a | sh[24]a*eb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
	| sh64 | sh64le \
	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
		case $os in
		    openstep*)
	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
	| spu | strongarm \
		        ;;
		    nextstep*)
			;;
		    ns2*)
		      os=nextstep2
			;;
		    *)
		      os=nextstep3
			;;
		esac
		;;
	np1)
		cpu=np1
	| tahoe | thumb | tic4x | tic80 | tron \
	| v850 | v850e \
	| we32k \
		vendor=gould
		;;
	op50n-* | op60c-*)
		cpu=hppa1.1
		vendor=oki
		os=proelf
		;;
	pa-hitachi)
		cpu=hppa1.1
		vendor=hitachi
		os=hiuxwe2
	| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
	| z8k)
		;;
	pbd)
		cpu=sparc
		vendor=tti
		;;
	pbb)
		cpu=m68k
		basic_machine=$basic_machine-unknown
		vendor=tti
		;;
	m6811 | m68hc11 | m6812 | m68hc12)
		# Motorola 68HC11/12.
		basic_machine=$basic_machine-unknown
		os=-none
	pc532)
		cpu=ns32k
		vendor=pc532
		;;
	pn)
		cpu=pn
		vendor=gould
		;;
	power)
		cpu=power
		vendor=ibm
		;;
	ps2)
		cpu=i386
		vendor=ibm
		;;
	rm[46]00)
		cpu=mips
		vendor=siemens
		;;
	rtpc | rtpc-*)
		cpu=romp
		vendor=ibm
		;;
	sde)
		cpu=mipsisa32
		vendor=sde
		os=${os:-elf}
		;;
	simso-wrs)
		cpu=sparclite
		vendor=wrs
		os=vxworks
		;;
	tower | tower-32)
		cpu=m68k
		vendor=ncr
		;;
	vpp*|vx|vx-*)
		cpu=f301
		vendor=fujitsu
		;;
	w65)
		cpu=w65
		vendor=wdc
		;;
	w89k-*)
		cpu=hppa1.1
		vendor=winbond
		os=proelf
		;;
	none)
		cpu=none
		vendor=none
		;;
	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
	leon|leon[3-9])
		cpu=sparc
		vendor=$basic_machine
		;;
	leon-*|leon[3-9]-*)
	ms1)
		basic_machine=mt-unknown
		cpu=sparc
		vendor=`echo "$basic_machine" | sed 's/-.*//'`
		;;

	*-*)
		# shellcheck disable=SC2162
		IFS="-" read cpu vendor <<EOF
$basic_machine
EOF
		;;
	# We use `pc' rather than `unknown'
	# because (1) that's what they normally are, and
	# (2) the word "unknown" tends to confuse beginning users.
	i*86 | x86_64)
	  basic_machine=$basic_machine-pc
	  ;;
		cpu=$basic_machine
		vendor=pc
		;;
	# Object if more than one company name word.
	*-*-*)
		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
		exit 1
	# These rules are duplicated from below for sake of the special case above;
	# i.e. things that normalized to x86 arches should also default to "pc"
	pc98)
		cpu=i386
		vendor=pc
		;;
	x64 | amd64)
		cpu=x86_64
		vendor=pc
		;;
	# Recognize the basic CPU types with company name.
	580-* \
	# Recognize the basic CPU types without company name.
	*)
	| a29k-* \
	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
	| avr-* | avr32-* \
	| bfin-* | bs2000-* \
		cpu=$basic_machine
	| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
	| clipper-* | craynv-* | cydra-* \
	| d10v-* | d30v-* | dlx-* \
	| elxsi-* \
		vendor=unknown
		;;
esac
	| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
	| h8300-* | h8500-* \
	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
	| i*86-* | i860-* | i960-* | ia64-* \
	| ip2k-* | iq2000-* \
	| m32c-* | m32r-* | m32rle-* \
	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
	| m88110-* | m88k-* | maxq-* | mcore-* \
	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
	| mips16-* \
	| mips64-* | mips64el-* \
	| mips64vr-* | mips64vrel-* \
	| mips64orion-* | mips64orionel-* \
	| mips64vr4100-* | mips64vr4100el-* \
	| mips64vr4300-* | mips64vr4300el-* \
	| mips64vr5000-* | mips64vr5000el-* \

unset -v basic_machine

# Decode basic machines in the full and proper CPU-Company form.
case $cpu-$vendor in
	# Here we handle the default manufacturer of certain CPU types in canonical form. It is in
	# some cases the only manufacturer, in others, it is the most popular.
	craynv-unknown)
		vendor=cray
		os=${os:-unicosmp}
	| mips64vr5900-* | mips64vr5900el-* \
	| mipsisa32-* | mipsisa32el-* \
	| mipsisa32r2-* | mipsisa32r2el-* \
	| mipsisa64-* | mipsisa64el-* \
		;;
	c90-unknown | c90-cray)
		vendor=cray
		os=${os:-unicos}
	| mipsisa64r2-* | mipsisa64r2el-* \
	| mipsisa64sb1-* | mipsisa64sb1el-* \
	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
		;;
	fx80-unknown)
		vendor=alliant
	| mipstx39-* | mipstx39el-* \
	| mmix-* \
	| mt-* \
		;;
	romp-unknown)
	| msp430-* \
	| nios-* | nios2-* \
	| none-* | np1-* | ns16k-* | ns32k-* \
	| orion-* \
		vendor=ibm
	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
	| pyramid-* \
	| romp-* | rs6000-* \
		;;
	mmix-unknown)
		vendor=knuth
		;;
	microblaze-unknown | microblazeel-unknown)
		vendor=xilinx
		;;
	rs6000-unknown)
	| sh-* | sh[1234]-* | sh[24]a-* | sh[24]a*eb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
	| sparclite-* \
	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
	| tahoe-* | thumb-* \
	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
	| tron-* \
	| v850-* | v850e-* | vax-* \
		vendor=ibm
		;;
	vax-unknown)
	| we32k-* \
	| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
	| xstormy16-* | xtensa-* \
		vendor=dec
	| ymp-* \
	| z8k-*)
		;;
	# Recognize the various machine names and aliases which stand
	# for a CPU type and a company and sometimes even an OS.
	386bsd)
		basic_machine=i386-unknown
		os=-bsd
	pdp11-unknown)
		vendor=dec
		;;
	3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
		basic_machine=m68000-att
	we32k-unknown)
		vendor=att
		;;
	cydra-unknown)
		vendor=cydrome
		;;
	3b*)
		basic_machine=we32k-att
	i370-ibm*)
		vendor=ibm
		;;
	a29khif)
		basic_machine=a29k-amd
		os=-udi
	orion-unknown)
		vendor=highlevel
		;;
    	abacus)
		basic_machine=abacus-unknown
	xps-unknown | xps100-unknown)
		cpu=xps100
		vendor=honeywell
		;;
	adobe68k)
		basic_machine=m68010-adobe
		os=-scout

	# Here we normalize CPU types with a missing or matching vendor
	dpx20-unknown | dpx20-bull)
		cpu=rs6000
		;;
	alliant | fx80)
		vendor=bull
		basic_machine=fx80-alliant
		;;
	altos | altos3068)
		basic_machine=m68k-altos
		;;
	am29k)
		basic_machine=a29k-none
		os=-bsd
		os=${os:-bosx}
		;;
	amd64)

		basic_machine=x86_64-pc
		;;
	# Here we normalize CPU types irrespective of the vendor
	amd64-*)
		basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
		cpu=x86_64
		;;
	amdahl)
		basic_machine=580-amdahl
		os=-sysv
		;;
	amiga | amiga-*)
	blackfin-*)
		basic_machine=m68k-unknown
		;;
	amigaos | amigados)
		basic_machine=m68k-unknown
		os=-amigaos
		;;
	amigaunix | amix)
		basic_machine=m68k-unknown
		os=-sysv4
		;;
	apollo68)
		basic_machine=m68k-apollo
		os=-sysv
		;;
	apollo68bsd)
		basic_machine=m68k-apollo
		os=-bsd
		;;
	aux)
		cpu=bfin
		basic_machine=m68k-apple
		os=-aux
		os=linux
		;;
	balance)
		basic_machine=ns32k-sequent
		os=-dynix
		;;
	c90)
		basic_machine=c90-cray
		os=-unicos
		;;
	convex-c1)
		basic_machine=c1-convex
		os=-bsd
		;;
	convex-c2)
		basic_machine=c2-convex
		os=-bsd
		;;
	convex-c32)
		basic_machine=c32-convex
		os=-bsd
		;;
	convex-c34)
		basic_machine=c34-convex
		os=-bsd
		;;
	convex-c38)
		basic_machine=c38-convex
		os=-bsd
		;;
	cray | j90)
		basic_machine=j90-cray
		os=-unicos
		;;
	craynv)
		basic_machine=craynv-cray
		os=-unicosmp
		;;
	cr16)
		basic_machine=cr16-unknown
		os=-elf
		;;
	crds | unos)
		basic_machine=m68k-crds
		;;
	crisv32 | crisv32-* | etraxfs*)
		basic_machine=crisv32-axis
		;;
	cris | cris-* | etrax*)
		basic_machine=cris-axis
		;;
	crx)
		basic_machine=crx-unknown
		os=-elf
		;;
	da30 | da30-*)
	c54x-*)
		basic_machine=m68k-da30
		;;
	decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
		basic_machine=mips-dec
		;;
	decsystem10* | dec10*)
		basic_machine=pdp10-dec
		os=-tops10
		;;
	decsystem20* | dec20*)
		basic_machine=pdp10-dec
		os=-tops20
		;;
	delta | 3300 | motorola-3300 | motorola-delta \
	      | 3300-motorola | delta-motorola)
		basic_machine=m68k-motorola
		;;
	delta88)
		basic_machine=m88k-motorola
		os=-sysv3
		;;
	djgpp)
		basic_machine=i586-pc
		cpu=tic54x
		os=-msdosdjgpp
		;;
	dpx20 | dpx20-*)
	c55x-*)
		basic_machine=rs6000-bull
		os=-bosx
		;;
	dpx2* | dpx2*-bull)
		basic_machine=m68k-bull
		os=-sysv3
		;;
	ebmon29k)
		basic_machine=a29k-amd
		os=-ebmon
		;;
	elxsi)
		basic_machine=elxsi-elxsi
		os=-bsd
		;;
	encore | umax | mmax)
		basic_machine=ns32k-encore
		;;
	es1800 | OSE68k | ose68k | ose | OSE)
		basic_machine=m68k-ericsson
		os=-ose
		;;
	fx2800)
		basic_machine=i860-alliant
		;;
	genix)
		basic_machine=ns32k-ns
		;;
	gmicro)
		basic_machine=tron-gmicro
		os=-sysv
		;;
	go32)
		basic_machine=i386-pc
		os=-go32
		;;
	h3050r* | hiux*)
		basic_machine=hppa1.1-hitachi
		os=-hiuxwe2
		;;
	h8300hms)
		basic_machine=h8300-hitachi
		os=-hms
		;;
	h8300xray)
		basic_machine=h8300-hitachi
		os=-xray
		;;
	h8500hms)
		basic_machine=h8500-hitachi
		os=-hms
		;;
	harris)
		basic_machine=m88k-harris
		os=-sysv3
		;;
	hp300-*)
		basic_machine=m68k-hp
		;;
	hp300bsd)
		basic_machine=m68k-hp
		os=-bsd
		;;
	hp300hpux)
		basic_machine=m68k-hp
		os=-hpux
		cpu=tic55x
		;;
	hp3k9[0-9][0-9] | hp9[0-9][0-9])
		basic_machine=hppa1.0-hp
		;;
	hp9k2[0-9][0-9] | hp9k31[0-9])
		basic_machine=m68000-hp
		;;
	hp9k3[2-9][0-9])
		basic_machine=m68k-hp
		;;
	hp9k6[0-9][0-9] | hp6[0-9][0-9])
		basic_machine=hppa1.0-hp
		;;
	hp9k7[0-79][0-9] | hp7[0-79][0-9])
		basic_machine=hppa1.1-hp
		;;
	hp9k78[0-9] | hp78[0-9])
		# FIXME: really hppa2.0-hp
		basic_machine=hppa1.1-hp
		;;
	hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
		# FIXME: really hppa2.0-hp
		basic_machine=hppa1.1-hp
		;;
	hp9k8[0-9][13679] | hp8[0-9][13679])
		basic_machine=hppa1.1-hp
		;;
	hp9k8[0-9][0-9] | hp8[0-9][0-9])
		basic_machine=hppa1.0-hp
		;;
	hppa-next)
		os=-nextstep3
		;;
	hppaosf)
		basic_machine=hppa1.1-hp
		os=-osf
		;;
	hppro)
		basic_machine=hppa1.1-hp
		os=-proelf
		;;
	i370-ibm* | ibm*)
		basic_machine=i370-ibm
		;;
# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
	i*86v32)
		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
		os=-sysv32
		;;
	i*86v4*)
		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
		os=-sysv4
		;;
	i*86v)
		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
		os=-sysv
		;;
	i*86sol2)
		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
		os=-solaris2
		;;
	i386mach)
		basic_machine=i386-mach
		os=-mach
		;;
	i386-vsta | vsta)
		basic_machine=i386-unknown
		os=-vsta
		;;
	iris | iris4d)
		basic_machine=mips-sgi
		case $os in
		    -irix*)
			;;
		    *)
	c6x-*)
			os=-irix4
			;;
		esac
		cpu=tic6x
		;;
	isi68 | isi)
		basic_machine=m68k-isi
		os=-sysv
		;;
	m88k-omron*)
		basic_machine=m88k-omron
		;;
	magnum | m3230)
		basic_machine=mips-mips
		os=-sysv
		;;
	merlin)
		basic_machine=ns32k-utek
		os=-sysv
		;;
	mingw32)
		basic_machine=i386-pc
		os=-mingw32
		;;
	mingw32ce)
		basic_machine=arm-unknown
		os=-mingw32ce
		;;
	miniframe)
		basic_machine=m68000-convergent
		;;
	*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
		basic_machine=m68k-atari
		os=-mint
		;;
	mipsEE* | ee | ps2)
		basic_machine=mips64r5900el-scei
		case $os in
		    -linux*)
			;;
		    *)
	e500v[12]-*)
			os=-elf
			;;
		esac
		cpu=powerpc
		;;
	iop)
		basic_machine=mipsel-scei
		os=-irx
		os=$os"spe"
		;;
	dvp)
		basic_machine=dvp-scei
		os=-elf
		;;
	mips3*-*)
		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
		;;
	mips3*)
		cpu=mips64
		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
		;;
	monitor)
		basic_machine=m68k-rom68k
		os=-coff
		;;
	morphos)
		basic_machine=powerpc-unknown
		os=-morphos
		;;
	msdos)
		basic_machine=i386-pc
		os=-msdos
		;;
	ms1-*)
		basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
		cpu=mt
		;;
	mvs)
		basic_machine=i370-ibm
		os=-mvs
	m68knommu-*)
		cpu=m68k
		os=linux
		;;
	m9s12z-* | m68hcs12z-* | hcs12z-* | s12z-*)
		cpu=s12z
		;;
	openrisc-*)
	ncr3000)
		cpu=or32
		basic_machine=i486-ncr
		os=-sysv4
		;;
	parisc-*)
		cpu=hppa
		os=linux
		;;
	pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
		cpu=i586
		;;
	pentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*)
		cpu=i686
		;;
	pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
	netbsd386)
		basic_machine=i386-unknown
		cpu=i686
		;;
	pentium4-*)
		cpu=i786
		;;
	pc98-*)
		cpu=i386
		os=-netbsd
		;;
	ppc-* | ppcbe-*)
	netwinder)
		cpu=powerpc
		basic_machine=armv4l-rebel
		os=-linux
		;;
	ppcle-* | powerpclittle-*)
		cpu=powerpcle
		;;
	news | news700 | news800 | news900)
		basic_machine=m68k-sony
		os=-newsos
	ppc64-*)
		cpu=powerpc64
		;;
	ppc64le-* | powerpc64little-*)
		cpu=powerpc64le
		;;
	news1000)
		basic_machine=m68030-sony
	sb1-*)
		cpu=mipsisa64sb1
		os=-newsos
		;;
	news-3600 | risc-news)
		basic_machine=mips-sony
	sb1el-*)
		cpu=mipsisa64sb1el
		os=-newsos
		;;
	necv70)
	sh5e[lb]-*)
		basic_machine=v70-nec
		os=-sysv
		cpu=`echo "$cpu" | sed 's/^\(sh.\)e\(.\)$/\1\2e/'`
		;;
	spur-*)
		cpu=spur
		;;
	next | m*-next )
	strongarm-* | thumb-*)
		basic_machine=m68k-next
		case $os in
		cpu=arm
		    -nextstep* )
			;;
		    -ns2*)
		      os=-nextstep2
			;;
		    *)
		      os=-nextstep3
			;;
		esac
		;;
	tx39-*)
		cpu=mipstx39
		;;
	tx39el-*)
		cpu=mipstx39el
		;;
	x64-*)
		cpu=x86_64
		;;
	nh3000)
		basic_machine=m68k-harris
		os=-cxux
	xscale-* | xscalee[bl]-*)
		cpu=`echo "$cpu" | sed 's/^xscale/arm/'`
		;;

	# Recognize the canonical CPU Types that limit and/or modify the
	# company names they are paired with.
	cr16-*)
		os=${os:-elf}
		;;
	nh[45]000)
		basic_machine=m88k-harris
		os=-cxux
	crisv32-* | etraxfs*-*)
		cpu=crisv32
		vendor=axis
		;;
	cris-* | etrax*-*)
	nindy960)
		cpu=cris
		basic_machine=i960-intel
		os=-nindy
		vendor=axis
		;;
	mon960)
		basic_machine=i960-intel
		os=-mon960
	crx-*)
		os=${os:-elf}
		;;
	nonstopux)
		basic_machine=mips-compaq
		os=-nonstopux
	neo-tandem)
		cpu=neo
		vendor=tandem
		;;
	np1)
		basic_machine=np1-gould
	nse-tandem)
		cpu=nse
		vendor=tandem
		;;
	nsr-tandem)
		basic_machine=nsr-tandem
		cpu=nsr
		;;
	op50n-* | op60c-*)
		basic_machine=hppa1.1-oki
		os=-proelf
		;;
	openrisc | openrisc-*)
		basic_machine=or32-unknown
		;;
	os400)
		basic_machine=powerpc-ibm
		os=-os400
		;;
	OSE68000 | ose68000)
		basic_machine=m68000-ericsson
		os=-ose
		;;
	os68k)
		basic_machine=m68k-none
		os=-os68k
		;;
	pa-hitachi)
		basic_machine=hppa1.1-hitachi
		os=-hiuxwe2
		;;
	paragon)
		basic_machine=i860-intel
		os=-osf
		;;
	pbd)
		basic_machine=sparc-tti
		;;
	pbb)
		basic_machine=m68k-tti
		;;
	pc532 | pc532-*)
		basic_machine=ns32k-pc532
		;;
	pc98)
		basic_machine=i386-pc
		;;
	pc98-*)
		basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
		;;
	pentium | p5 | k5 | k6 | nexgen | viac3)
		basic_machine=i586-pc
		;;
	pentiumpro | p6 | 6x86 | athlon | athlon_*)
		basic_machine=i686-pc
		;;
	pentiumii | pentium2 | pentiumiii | pentium3)
		basic_machine=i686-pc
		;;
	pentium4)
		vendor=tandem
		basic_machine=i786-pc
		;;
	pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
		basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
		;;
	pentiumpro-* | p6-* | 6x86-* | athlon-*)
		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
		;;
	pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
		;;
	pentium4-*)
		basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
		;;
	pn)
	nsv-tandem)
		basic_machine=pn-gould
		;;
	power)	basic_machine=power-ibm
		;;
	ppc)	basic_machine=powerpc-unknown
		;;
	ppc-*)	basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
		;;
	ppcle | powerpclittle | ppc-le | powerpc-little)
		basic_machine=powerpcle-unknown
		;;
	ppcle-* | powerpclittle-*)
		basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
		;;
	ppc64)	basic_machine=powerpc64-unknown
		;;
	ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
		;;
	ppc64le | powerpc64little | ppc64-le | powerpc64-little)
		basic_machine=powerpc64le-unknown
		;;
	ppc64le-* | powerpc64little-*)
		basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
		;;
	ps2)
		cpu=nsv
		basic_machine=i386-ibm
		;;
	pw32)
		basic_machine=i586-unknown
		os=-pw32
		;;
	rdos)
		vendor=tandem
		basic_machine=i386-pc
		os=-rdos
		;;
	rom68k)
		basic_machine=m68k-rom68k
		os=-coff
		;;
	rm[46]00)
		basic_machine=mips-siemens
		;;
	rtpc | rtpc-*)
		basic_machine=romp-ibm
		;;
	s390 | s390-*)
		basic_machine=s390-ibm
		;;
	s390x | s390x-*)
		basic_machine=s390x-ibm
		;;
	sa29200)
		basic_machine=a29k-amd
		os=-udi
		;;
	sb1)
		basic_machine=mipsisa64sb1-unknown
		;;
	sb1el)
		basic_machine=mipsisa64sb1el-unknown
		;;
	sde)
	nsx-tandem)
		basic_machine=mipsisa32-sde
		os=-elf
		;;
	sei)
		basic_machine=mips-sei
		os=-seiux
		;;
	sequent)
		basic_machine=i386-sequent
		;;
	sh)
		basic_machine=sh-hitachi
		os=-hms
		;;
	sh5el)
		basic_machine=sh5le-unknown
		;;
	sh64)
		basic_machine=sh64-unknown
		;;
	sparclite-wrs | simso-wrs)
		basic_machine=sparclite-wrs
		os=-vxworks
		;;
	sps7)
		basic_machine=m68k-bull
		os=-sysv2
		;;
	spur)
		cpu=nsx
		basic_machine=spur-unknown
		;;
	st2000)
		basic_machine=m68k-tandem
		vendor=tandem
		;;
	stratus)
		basic_machine=i860-stratus
		os=-sysv4
		;;
	sun2)
		basic_machine=m68000-sun
		;;
	sun2os3)
		basic_machine=m68000-sun
		os=-sunos3
		;;
	sun2os4)
		basic_machine=m68000-sun
		os=-sunos4
		;;
	sun3os3)
		basic_machine=m68k-sun
		os=-sunos3
		;;
	sun3os4)
		basic_machine=m68k-sun
		os=-sunos4
		;;
	sun4os3)
		basic_machine=sparc-sun
		os=-sunos3
		;;
	sun4os4)
		basic_machine=sparc-sun
		os=-sunos4
		;;
	sun4sol2)
		basic_machine=sparc-sun
		os=-solaris2
		;;
	sun3 | sun3-*)
		basic_machine=m68k-sun
		;;
	sun4)
		basic_machine=sparc-sun
		;;
	sun386 | sun386i | roadrunner)
		basic_machine=i386-sun
		;;
	sv1)
		basic_machine=sv1-cray
		os=-unicos
		;;
	symmetry)
		basic_machine=i386-sequent
		os=-dynix
		;;
	t3e)
		basic_machine=alphaev5-cray
		os=-unicos
		;;
	t90)
	s390-*)
		basic_machine=t90-cray
		os=-unicos
		;;
	tic54x | c54x*)
		basic_machine=tic54x-unknown
		os=-coff
		;;
	tic55x | c55x*)
		basic_machine=tic55x-unknown
		os=-coff
		;;
	tic6x | c6x*)
		basic_machine=tic6x-unknown
		os=-coff
		;;
	tx39)
		cpu=s390
		basic_machine=mipstx39-unknown
		;;
	tx39el)
		basic_machine=mipstx39el-unknown
		;;
	toad1)
		basic_machine=pdp10-xkl
		os=-tops20
		;;
	tower | tower-32)
		basic_machine=m68k-ncr
		;;
	tpf)
		basic_machine=s390x-ibm
		os=-tpf
		;;
	udi29k)
		basic_machine=a29k-amd
		os=-udi
		;;
	ultra3)
		basic_machine=a29k-nyu
		os=-sym1
		;;
	v810 | necv810)
		basic_machine=v810-nec
		os=-none
		;;
	vaxv)
		basic_machine=vax-dec
		os=-sysv
		;;
	vms)
		basic_machine=vax-dec
		os=-vms
		;;
	vpp*|vx|vx-*)
		basic_machine=f301-fujitsu
		;;
	vxworks960)
		vendor=ibm
		basic_machine=i960-wrs
		os=-vxworks
		;;
	vxworks68)
		basic_machine=m68k-wrs
		os=-vxworks
		;;
	vxworks29k)
		basic_machine=a29k-wrs
		os=-vxworks
		;;
	w65*)
		basic_machine=w65-wdc
		os=-none
		;;
	w89k-*)
	s390x-*)
		basic_machine=hppa1.1-winbond
		os=-proelf
		;;
	xbox)
		basic_machine=i686-pc
		os=-mingw32
		;;
	xps | xps100)
		basic_machine=xps100-honeywell
		;;
	ymp)
		cpu=s390x
		basic_machine=ymp-cray
		os=-unicos
		vendor=ibm
		;;
	z8k-*-coff)
	tile*-*)
		basic_machine=z8k-unknown
		os=-sim
		os=${os:-linux-gnu}
		;;
	none)
		basic_machine=none-none
		os=-none
		;;

# Here we handle the default manufacturer of certain CPU types.  It is in
# some cases the only manufacturer, in others, it is the most popular.
	w89k)
		basic_machine=hppa1.1-winbond
		;;
	op50n)
		basic_machine=hppa1.1-oki
		;;
	op60c)
		basic_machine=hppa1.1-oki
		;;
	romp)
		basic_machine=romp-ibm
		;;
	mmix)
		basic_machine=mmix-knuth
		;;
	rs6000)
		basic_machine=rs6000-ibm
		;;
	vax)
		basic_machine=vax-dec
		;;
	pdp10)
		# there are many clones, so DEC is not a safe bet
		basic_machine=pdp10-unknown
		;;
	pdp11)
		basic_machine=pdp11-dec
		;;
	we32k)
		basic_machine=we32k-att
		;;
	sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
		basic_machine=sh-unknown
		;;
	sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
		basic_machine=sparc-sun
		;;
	cydra)
		basic_machine=cydra-cydrome
		;;
	orion)
		basic_machine=orion-highlevel
		;;
	orion105)
		basic_machine=clipper-highlevel
		;;
	mac | mpw | mac-mpw)
		basic_machine=m68k-apple
		;;
	pmac | pmac-mpw)
		basic_machine=powerpc-apple
		;;
	*-unknown)
		# Make sure to match an already-canonicalized machine name.
		;;
	*)
		# Recognize the canonical CPU types that are allowed with any
		# company name.
		case $cpu in
			1750a | 580 \
			| a29k \
			| aarch64 | aarch64_be \
			| abacus \
			| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \
			| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \
			| alphapca5[67] | alpha64pca5[67] \
			| am33_2.0 \
			| amdgcn \
			| arc | arceb \
			| arm  | arm[lb]e | arme[lb] | armv* \
			| avr | avr32 \
			| asmjs \
			| ba \
			| be32 | be64 \
			| bfin | bpf | bs2000 \
			| c[123]* | c30 | [cjt]90 | c4x \
			| c8051 | clipper | craynv | csky | cydra \
			| d10v | d30v | dlx | dsp16xx \
			| e2k | elxsi | epiphany \
			| f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \
			| h8300 | h8500 \
			| hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
			| hexagon \
			| i370 | i*86 | i860 | i960 | ia16 | ia64 \
			| ip2k | iq2000 \
			| k1om \
			| le32 | le64 \
			| lm32 \
			| m32c | m32r | m32rle \
			| m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \
			| m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \
			| m88110 | m88k | maxq | mb | mcore | mep | metag \
			| microblaze | microblazeel \
			| mips | mipsbe | mipseb | mipsel | mipsle \
			| mips16 \
			| mips64 | mips64eb | mips64el \
			| mips64octeon | mips64octeonel \
			| mips64orion | mips64orionel \
			| mips64r5900 | mips64r5900el \
			| mips64vr | mips64vrel \
			| mips64vr4100 | mips64vr4100el \
			| mips64vr4300 | mips64vr4300el \
			| mips64vr5000 | mips64vr5000el \
			| mips64vr5900 | mips64vr5900el \
			| mipsisa32 | mipsisa32el \
			| mipsisa32r2 | mipsisa32r2el \
			| mipsisa32r6 | mipsisa32r6el \
			| mipsisa64 | mipsisa64el \
			| mipsisa64r2 | mipsisa64r2el \
			| mipsisa64r6 | mipsisa64r6el \
			| mipsisa64sb1 | mipsisa64sb1el \
			| mipsisa64sr71k | mipsisa64sr71kel \
			| mipsr5900 | mipsr5900el \
			| mipstx39 | mipstx39el \
			| mmix \
			| mn10200 | mn10300 \
			| moxie \
			| mt \
			| msp430 \
			| nds32 | nds32le | nds32be \
			| nfp \
			| nios | nios2 | nios2eb | nios2el \
			| none | np1 | ns16k | ns32k | nvptx \
			| open8 \
			| or1k* \
			| or32 \
			| orion \
			| picochip \
			| pdp10 | pdp11 | pj | pjl | pn | power \
			| powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \
			| pru \
			| pyramid \
			| riscv | riscv32 | riscv64 \
			| rl78 | romp | rs6000 | rx \
			| score \
			| sh | shl \
			| sh[1234] | sh[24]a | sh[24]ae[lb] | sh[23]e | she[lb] | sh[lb]e \
			| sh[1234]e[lb] |  sh[12345][lb]e | sh[23]ele | sh64 | sh64le \
			| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet \
			| sparclite \
			| sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \
			| spu \
			| tahoe \
			| tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \
			| tron \
			| ubicom32 \
			| v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \
			| vax \
			| visium \
			| w65 \
			| wasm32 | wasm64 \
			| we32k \
			| x86 | x86_64 | xc16x | xgate | xps100 \
			| xstormy16 | xtensa* \
			| ymp \
			| z8k | z80)
				;;

			*)
		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
		exit 1
		;;
esac
				echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2
				exit 1
				;;
		esac
		;;
esac

# Here we canonicalize certain aliases for manufacturers.
case $basic_machine in
	*-digital*)
case $vendor in
	digital*)
		basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
		vendor=dec
		;;
	*-commodore*)
		basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
	commodore*)
		vendor=cbm
		;;
	*)
		;;
esac

# Decode manufacturer-specific aliases for certain operating systems.

if [ x"$os" != x"" ]
if [ x$os != x ]
then
case $os in
        # First match some system type aliases
        # that might get confused with valid system types.
	# -solaris* is a basic system type, with this one exception.
	-solaris1 | -solaris1.*)
	# First match some system type aliases that might get confused
	# with valid system types.
	# solaris* is a basic system type, with this one exception.
	auroraux)
		os=auroraux
		;;
	bluegene*)
		os=cnk
		;;
	solaris1 | solaris1.*)
		os=`echo $os | sed -e 's|solaris1|sunos4|'`
		;;
	-solaris)
		os=-solaris2
	solaris)
		os=solaris2
		;;
	-svr4*)
		os=-sysv4
		;;
	-unixware*)
		os=-sysv4.2uw
	unixware*)
		os=sysv4.2uw
		;;
	-gnu/linux*)
	gnu/linux*)
		os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
		;;
	# es1800 is here to avoid being matched by es* (a different OS)
	es1800*)
		os=ose
		;;
	# Some version numbers need modification
	chorusos*)
		os=chorusos
		;;
	isc)
		os=isc2.2
		;;
	sco6)
		os=sco5v6
		;;
	sco5)
		os=sco3.2v5
		;;
	sco4)
		os=sco3.2v4
		;;
	sco3.2.[4-9]*)
		os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
		;;
	sco3.2v[4-9]* | sco5v6*)
		# Don't forget version if it is 3.2v4 or newer.
		;;
	scout)
		# Don't match below
		;;
	sco*)
		os=sco3.2v2
		;;
	psos*)
		os=psos
		;;
	# First accept the basic system types.
	# Now accept the basic system types.
	# The portable systems comes first.
	# Each alternative MUST END IN A *, to match a version number.
	# -sysv* is not here because it comes later, after sysvr4.
	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
	      | -aos* \
	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
	      | -openbsd* | -solidbsd* \
	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
	      | -chorusos* | -chorusrdb* \
	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
	      | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
	      | -uxpv* | -beos* | -mpeix* | -udk* \
	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -irx*)
	# Each alternative MUST end in a * to match a version number.
	# sysv* is not here because it comes later, after sysvr4.
	gnu* | bsd* | mach* | minix* | genix* | ultrix* | irix* \
	     | *vms* | esix* | aix* | cnk* | sunos | sunos[34]*\
	     | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \
	     | sym* | kopensolaris* | plan9* \
	     | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \
	     | aos* | aros* | cloudabi* | sortix* \
	     | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \
	     | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \
	     | knetbsd* | mirbsd* | netbsd* \
	     | bitrig* | openbsd* | solidbsd* | libertybsd* \
	     | ekkobsd* | kfreebsd* | freebsd* | riscix* | lynxos* \
	     | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \
	     | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \
	     | udi* | eabi* | lites* | ieee* | go32* | aux* | hcos* \
	     | chorusrdb* | cegcc* | glidix* \
	     | cygwin* | msys* | pe* | moss* | proelf* | rtems* \
	     | midipix* | mingw32* | mingw64* | linux-gnu* | linux-android* \
	     | linux-newlib* | linux-musl* | linux-uclibc* \
	     | uxpv* | beos* | mpeix* | udk* | moxiebox* \
	     | interix* | uwin* | mks* | rhapsody* | darwin* \
	     | openstep* | oskit* | conix* | pw32* | nonstopux* \
	     | storm-chaos* | tops10* | tenex* | tops20* | its* \
	     | os2* | vos* | palmos* | uclinux* | nucleus* \
	     | morphos* | superux* | rtmk* | windiss* \
	     | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \
	     | skyos* | haiku* | rdos* | toppers* | drops* | es* \
	     | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
	     | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi*)
	# Remember, each alternative MUST END IN *, to match a version number.
		;;
	-qnx*)
		case $basic_machine in
		    x86-* | i*86-*)
	qnx*)
		case $cpu in
		    x86 | i*86)
			;;
		    *)
			os=nto-$os
			;;
		esac
		;;
	hiux*)
		os=hiuxwe2
		;;
	nto-qnx*)
		;;
			os=-nto$os
	nto*)
		os=`echo $os | sed -e 's|nto|nto-qnx|'`
		;;
	sim | xray | os68k* | v88r* \
	    | windows* | osx | abug | netware* | os9* \
	    | macos* | mpw* | magic* | mmixware* | mon960* | lnews*)
		;;
	linux-dietlibc)
		os=linux-dietlibc
		;;
	linux*)
		os=`echo $os | sed -e 's|linux|linux-gnu|'`
		;;
	lynx*178)
		os=lynxos178
		;;
	lynx*5)
		os=lynxos5
		;;
	lynx*)
		os=lynxos
		;;
	mac*)
		os=`echo "$os" | sed -e 's|mac|macos|'`
		;;
	opened*)
		os=openedition
		;;
	os400*)
		os=os400
		;;
	sunos5*)
		os=`echo "$os" | sed -e 's|sunos5|solaris2|'`
		;;
	sunos6*)
		os=`echo "$os" | sed -e 's|sunos6|solaris3|'`
		;;
	wince*)
		os=wince
		;;
	utek*)
		os=bsd
		;;
	dynix*)
		os=bsd
		;;
	acis*)
		os=aos
		;;
	atheos*)
		os=atheos
		;;
	syllable*)
		os=syllable
		;;
	386bsd)
		os=bsd
		;;
	ctix* | uts*)
		os=sysv
		;;
	nova*)
		os=rtmk-nova
		;;
	ns2)
		os=nextstep2
		;;
	nsk*)
		os=nsk
		;;
	# Preserve the version number of sinix5.
	sinix5.*)
		os=`echo $os | sed -e 's|sinix|sysv|'`
		;;
	sinix*)
		os=sysv4
		;;
	tpf*)
		os=tpf
		;;
	triton*)
		os=sysv3
		;;
	oss*)
		os=sysv3
		;;
	svr4*)
		os=sysv4
		;;
	svr3)
		os=sysv3
		;;
	sysvr4)
		os=sysv4
		;;
	# This must come after sysvr4.
	sysv*)
		;;
	ose*)
		os=ose
		;;
	*mint | mint[0-9]* | *MiNT | MiNT[0-9]*)
		os=mint
		;;
	zvmoe)
		os=zvmoe
		;;
	dicos*)
		os=dicos
		;;
	pikeos*)
		# Until real need of OS specific support for
		# particular features comes up, bare metal
		# configurations are quite functional.
		case $cpu in
		    arm*)
			os=eabi
			;;
		    *)
			os=elf
			;;
		esac
		;;
	-nto-qnx*)
		;;
	-nto*)
		os=`echo $os | sed -e 's|nto|nto-qnx|'`
		;;
	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
	      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
		;;
	-mac*)
	nacl*)
		os=`echo $os | sed -e 's|mac|macos|'`
		;;
	-linux-dietlibc)
		os=-linux-dietlibc
		;;
	-linux*)
		os=`echo $os | sed -e 's|linux|linux-gnu|'`
		;;
	-sunos5*)
		os=`echo $os | sed -e 's|sunos5|solaris2|'`
		;;
	-sunos6*)
		os=`echo $os | sed -e 's|sunos6|solaris3|'`
		;;
	-opened*)
		os=-openedition
		;;
        -os400*)
		os=-os400
		;;
	-wince*)
		os=-wince
		;;
	-osfrose*)
		os=-osfrose
		;;
	-osf*)
	ios)
		os=-osf
		;;
	-utek*)
		os=-bsd
		;;
	-dynix*)
		os=-bsd
		;;
	-acis*)
		os=-aos
		;;
	-atheos*)
		os=-atheos
		;;
	-syllable*)
		os=-syllable
		;;
	-386bsd)
		os=-bsd
		;;
	-ctix* | -uts*)
		os=-sysv
		;;
	-nova*)
	none)
		os=-rtmk-nova
		;;
	-ns2 )
		os=-nextstep2
		;;
	-nsk*)
		os=-nsk
		;;
	# Preserve the version number of sinix5.
	-sinix5.*)
		os=`echo $os | sed -e 's|sinix|sysv|'`
		;;
	-sinix*)
		os=-sysv4
		;;
        -tpf*)
		os=-tpf
		;;
	-triton*)
		os=-sysv3
		;;
	-oss*)
		os=-sysv3
		;;
	-svr4)
		os=-sysv4
		;;
	-svr3)
		os=-sysv3
		;;
	-sysvr4)
		os=-sysv4
		;;
	# This must come after -sysvr4.
	-sysv*)
		;;
	-ose*)
		os=-ose
		;;
	-es1800*)
	*-eabi)
		os=-ose
		;;
	-xenix)
		os=-xenix
		;;
	-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
		os=-mint
		;;
	-aros*)
		os=-aros
		;;
	-kaos*)
		os=-kaos
		;;
	-zvmoe)
		os=-zvmoe
		;;
	-none)
		;;
	*)
		# Get rid of the `-' at the beginning of $os.
		os=`echo $os | sed 's/[^-]*-//'`
		echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
		echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2
		exit 1
		;;
esac
else

# Here we handle the default operating systems that come with various machines.
# The value should be what the vendor currently ships out the door with their
# machine or put another way, the most popular os provided with the machine.

# Note that if you're going to try to match "-MANUFACTURER" here (say,
# "-sun"), then you have to tell the case statement up towards the top
# that MANUFACTURER isn't an operating system.  Otherwise, code above
# will signal an error saying that MANUFACTURER isn't an operating
# system, and we'll never get to this point.

case $basic_machine in
        score-*)
		os=-elf
case $cpu-$vendor in
	score-*)
		os=elf
		;;
        spu-*)
		os=-elf
	spu-*)
		os=elf
		;;
	*-acorn)
		os=-riscix1.2
		os=riscix1.2
		;;
	arm*-rebel)
		os=-linux
		os=linux
		;;
	arm*-semi)
		os=-aout
		os=aout
		;;
        c4x-* | tic4x-*)
        	os=-coff
	c4x-* | tic4x-*)
		os=coff
		;;
	c8051-*)
		os=elf
		;;
	clipper-intergraph)
		os=clix
		;;
	hexagon-*)
		os=elf
		;;
	tic54x-*)
		os=coff
		;;
	tic55x-*)
		os=coff
		;;
	tic6x-*)
		os=coff
		;;
	# This must come before the *-dec entry.
	pdp10-*)
		os=-tops20
		os=tops20
		;;
	pdp11-*)
		os=-none
		os=none
		;;
	*-dec | vax-*)
		os=-ultrix4.2
		os=ultrix4.2
		;;
	m68*-apollo)
		os=-domain
		os=domain
		;;
	i386-sun)
		os=-sunos4.0.2
		os=sunos4.0.2
		;;
	m68000-sun)
		os=-sunos3
		os=sunos3
		# This also exists in the configure program, but was not the
		# default.
		# os=-sunos4
		;;
	m68*-cisco)
		os=-aout
		os=aout
		;;
        mep-*)
		os=-elf
	mep-*)
		os=elf
		;;
	mips*-cisco)
		os=-elf
		os=elf
		;;
	mips*-*)
		os=-elf
		os=elf
		;;
	or32-*)
		os=-coff
		os=coff
		;;
	*-tti)	# must be before sparc entry or we get the wrong os.
		os=-sysv3
		os=sysv3
		;;
	sparc-* | *-sun)
		os=-sunos4.1.1
		os=sunos4.1.1
		;;
	*-be)
		os=-beos
	pru-*)
		os=elf
		;;
	*-haiku)
		os=-haiku
	*-be)
		os=beos
		;;
	*-ibm)
		os=-aix
		os=aix
		;;
    	*-knuth)
		os=-mmixware
	*-knuth)
		os=mmixware
		;;
	*-wec)
		os=-proelf
		os=proelf
		;;
	*-winbond)
		os=-proelf
		os=proelf
		;;
	*-oki)
		os=-proelf
		os=proelf
		;;
	*-hp)
		os=-hpux
		os=hpux
		;;
	*-hitachi)
		os=-hiux
		os=hiux
		;;
	i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
		os=-sysv
		os=sysv
		;;
	*-cbm)
		os=-amigaos
		os=amigaos
		;;
	*-dg)
		os=-dgux
		os=dgux
		;;
	*-dolphin)
		os=-sysv3
		os=sysv3
		;;
	m68k-ccur)
		os=-rtu
		os=rtu
		;;
	m88k-omron*)
		os=-luna
		os=luna
		;;
	*-next )
		os=-nextstep
	*-next)
		os=nextstep
		;;
	*-sequent)
		os=-ptx
		os=ptx
		;;
	*-crds)
		os=-unos
		os=unos
		;;
	*-ns)
		os=-genix
		os=genix
		;;
	i370-*)
		os=-mvs
		os=mvs
		;;
	*-next)
		os=-nextstep3
		;;
	*-gould)
		os=-sysv
		os=sysv
		;;
	*-highlevel)
		os=-bsd
		os=bsd
		;;
	*-encore)
		os=-bsd
		os=bsd
		;;
	*-sgi)
		os=-irix
		os=irix
		;;
	*-siemens)
		os=-sysv4
		os=sysv4
		;;
	*-masscomp)
		os=-rtu
		os=rtu
		;;
	f30[01]-fujitsu | f700-fujitsu)
		os=-uxpv
		os=uxpv
		;;
	*-rom68k)
		os=-coff
		os=coff
		;;
	*-*bug)
		os=-coff
		os=coff
		;;
	*-apple)
		os=-macos
		os=macos
		;;
	*-atari*)
		os=-mint
		os=mint
		;;
	*-wrs)
		os=vxworks
		;;
	*)
		os=-none
		os=none
		;;
esac
fi

# Here we handle the case where we know the os, and the CPU type, but not the
# manufacturer.  We pick the logical manufacturer.
vendor=unknown
case $vendor in
case $basic_machine in
	*-unknown)
	unknown)
		case $os in
			-riscix*)
			riscix*)
				vendor=acorn
				;;
			-sunos*)
			sunos*)
				vendor=sun
				;;
			-aix*)
			cnk*|-aix*)
				vendor=ibm
				;;
			-beos*)
			beos*)
				vendor=be
				;;
			-hpux*)
			hpux*)
				vendor=hp
				;;
			-mpeix*)
			mpeix*)
				vendor=hp
				;;
			-hiux*)
			hiux*)
				vendor=hitachi
				;;
			-unos*)
			unos*)
				vendor=crds
				;;
			-dgux*)
			dgux*)
				vendor=dg
				;;
			-luna*)
			luna*)
				vendor=omron
				;;
			-genix*)
			genix*)
				vendor=ns
				;;
			clix*)
				vendor=intergraph
				;;
			-mvs* | -opened*)
			mvs* | opened*)
				vendor=ibm
				;;
			-os400*)
			os400*)
				vendor=ibm
				;;
			-ptx*)
			ptx*)
				vendor=sequent
				;;
			-tpf*)
			tpf*)
				vendor=ibm
				;;
			-vxsim* | -vxworks* | -windiss*)
			vxsim* | vxworks* | windiss*)
				vendor=wrs
				;;
			-aux*)
			aux*)
				vendor=apple
				;;
			-hms*)
			hms*)
				vendor=hitachi
				;;
			-mpw* | -macos*)
			mpw* | macos*)
				vendor=apple
				;;
			-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
			*mint | mint[0-9]* | *MiNT | MiNT[0-9]*)
				vendor=atari
				;;
			-vos*)
			vos*)
				vendor=stratus
				;;
		esac
		basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
		;;
esac

echo $basic_machine$os
echo "$cpu-$vendor-$os"
exit

# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"
# End:

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.27.0.
# Generated by GNU Autoconf 2.69 for sqlite 3.41.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.27.0'
PACKAGE_STRING='sqlite 3.27.0'
PACKAGE_VERSION='3.41.0'
PACKAGE_STRING='sqlite 3.41.0'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''

# Factoring default headers for most tests.
ac_includes_default="\
#include <stdio.h>
#ifdef HAVE_SYS_TYPES_H
766
767
768
769
770
771
772

773
774
775
776
777
778
779
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780







+







#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif"

ac_subst_vars='LTLIBOBJS
LIBOBJS
BUILD_CFLAGS
AMALGAMATION_LINE_MACROS
USE_GCOV
OPT_FEATURE_FLAGS
HAVE_ZLIB
USE_AMALGAMATION
TARGET_DEBUG
TARGET_HAVE_EDITLINE
TARGET_HAVE_READLINE
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







-







SQLITE_OS_WIN
SQLITE_OS_UNIX
BUILD_EXEEXT
TEMP_STORE
ALLOWRELEASE
SQLITE_THREADSAFE
BUILD_CC
VERSION_NUMBER
RELEASE
VERSION
program_prefix
TCLLIBDIR
TCLSH_CMD
INSTALL_DATA
INSTALL_SCRIPT
900
901
902
903
904
905
906



907
908
909
910
911
912
913
914
915
916
917
918
919
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914

915
916
917
918
919
920
921







+
+
+





-







enable_editline
enable_readline
with_readline_lib
with_readline_inc
enable_debug
enable_amalgamation
enable_load_extension
enable_math
enable_json
enable_all
enable_memsys5
enable_memsys3
enable_fts3
enable_fts4
enable_fts5
enable_json1
enable_update_limit
enable_geopoly
enable_rtree
enable_session
enable_gcov
'
      ac_precious_vars='build_alias
1462
1463
1464
1465
1466
1467
1468
1469

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

1471
1472
1473
1474
1475
1476
1477
1478







-
+







#
# 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.27.0 to adapt to many kinds of systems.
\`configure' configures sqlite 3.41.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.
1527
1528
1529
1530
1531
1532
1533
1534

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

1536
1537
1538
1539
1540
1541
1542
1543







-
+







  --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.27.0:";;
     short | recursive ) echo "Configuration of sqlite 3.41.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]
1553
1554
1555
1556
1557
1558
1559



1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569

1570
1571
1572
1573
1574
1575
1576







+
+
+





-







  --enable-editline       enable BSD editline support
  --disable-readline      disable readline support
  --enable-debug          enable debugging & verbose explain
  --disable-amalgamation  Disable the amalgamation and instead build all files
                          separately
  --disable-load-extension
                          Disable loading of external extensions
  --disable-math          Disable math functions
  --disable-json          Disable JSON functions
  --enable-all            Enable FTS4, FTS5, Geopoly, RTree, Sessions
  --enable-memsys5        Enable MEMSYS5
  --enable-memsys3        Enable MEMSYS3
  --enable-fts3           Enable the FTS3 extension
  --enable-fts4           Enable the FTS4 extension
  --enable-fts5           Enable the FTS5 extension
  --enable-json1          Enable the JSON1 extension
  --enable-update-limit   Enable the UPDATE/DELETE LIMIT clause
  --enable-geopoly        Enable the GEOPOLY extension
  --enable-rtree          Enable the RTREE extension
  --enable-session        Enable the SESSION extension
  --enable-gcov           Enable coverage testing using gcov

Optional Packages:
1653
1654
1655
1656
1657
1658
1659
1660

1661
1662
1663
1664
1665
1666
1667
1657
1658
1659
1660
1661
1662
1663

1664
1665
1666
1667
1668
1669
1670
1671







-
+







    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.27.0
sqlite configure 3.41.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
2072
2073
2074
2075
2076
2077
2078
2079

2080
2081
2082
2083
2084
2085
2086
2076
2077
2078
2079
2080
2081
2082

2083
2084
2085
2086
2087
2088
2089
2090







-
+







  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.27.0, which was
It was created by sqlite $as_me 3.41.0, which was
generated by GNU Autoconf 2.69.  Invocation command line was

  $ $0 $@

_ACEOF
exec 5>>config.log
{
3930
3931
3932
3933
3934
3935
3936
3937

3938
3939
3940

3941
3942
3943

3944
3945
3946
3947
3948
3949
3950
3934
3935
3936
3937
3938
3939
3940

3941
3942
3943

3944
3945
3946

3947
3948
3949
3950
3951
3952
3953
3954







-
+


-
+


-
+







{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5
$as_echo_n "checking the name lister ($NM) interface... " >&6; }
if ${lt_cv_nm_interface+:} false; then :
  $as_echo_n "(cached) " >&6
else
  lt_cv_nm_interface="BSD nm"
  echo "int some_variable = 0;" > conftest.$ac_ext
  (eval echo "\"\$as_me:3937: $ac_compile\"" >&5)
  (eval echo "\"\$as_me:3941: $ac_compile\"" >&5)
  (eval "$ac_compile" 2>conftest.err)
  cat conftest.err >&5
  (eval echo "\"\$as_me:3940: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
  (eval echo "\"\$as_me:3944: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
  (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
  cat conftest.err >&5
  (eval echo "\"\$as_me:3943: output\"" >&5)
  (eval echo "\"\$as_me:3947: output\"" >&5)
  cat conftest.out >&5
  if $GREP 'External.*some_variable' conftest.out > /dev/null; then
    lt_cv_nm_interface="MS dumpbin"
  fi
  rm -f conftest*
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5
5142
5143
5144
5145
5146
5147
5148
5149

5150
5151
5152
5153
5154
5155
5156
5146
5147
5148
5149
5150
5151
5152

5153
5154
5155
5156
5157
5158
5159
5160







-
+







	;;
    esac
  fi
  rm -rf conftest*
  ;;
*-*-irix6*)
  # Find out which ABI we are using.
  echo '#line 5149 "configure"' > conftest.$ac_ext
  echo '#line 5153 "configure"' > conftest.$ac_ext
  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
  (eval $ac_compile) 2>&5
  ac_status=$?
  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }; then
    if test "$lt_cv_prog_gnu_ld" = yes; then
      case `/usr/bin/file conftest.$ac_objext` in
6667
6668
6669
6670
6671
6672
6673
6674

6675
6676
6677
6678

6679
6680
6681
6682
6683
6684
6685
6671
6672
6673
6674
6675
6676
6677

6678
6679
6680
6681

6682
6683
6684
6685
6686
6687
6688
6689







-
+



-
+







   # Note that $ac_compile itself does not contain backslashes and begins
   # with a dollar sign (not a hyphen), so the echo should work correctly.
   # The option is referenced via a variable to avoid confusing sed.
   lt_compile=`echo "$ac_compile" | $SED \
   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
   -e 's:$: $lt_compiler_flag:'`
   (eval echo "\"\$as_me:6674: $lt_compile\"" >&5)
   (eval echo "\"\$as_me:6678: $lt_compile\"" >&5)
   (eval "$lt_compile" 2>conftest.err)
   ac_status=$?
   cat conftest.err >&5
   echo "$as_me:6678: \$? = $ac_status" >&5
   echo "$as_me:6682: \$? = $ac_status" >&5
   if (exit $ac_status) && test -s "$ac_outfile"; then
     # The compiler can only warn and ignore the option if not recognized
     # So say no if there are warnings other than the usual output.
     $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
       lt_cv_prog_compiler_rtti_exceptions=yes
7006
7007
7008
7009
7010
7011
7012
7013

7014
7015
7016
7017

7018
7019
7020
7021
7022
7023
7024
7010
7011
7012
7013
7014
7015
7016

7017
7018
7019
7020

7021
7022
7023
7024
7025
7026
7027
7028







-
+



-
+







   # Note that $ac_compile itself does not contain backslashes and begins
   # with a dollar sign (not a hyphen), so the echo should work correctly.
   # The option is referenced via a variable to avoid confusing sed.
   lt_compile=`echo "$ac_compile" | $SED \
   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
   -e 's:$: $lt_compiler_flag:'`
   (eval echo "\"\$as_me:7013: $lt_compile\"" >&5)
   (eval echo "\"\$as_me:7017: $lt_compile\"" >&5)
   (eval "$lt_compile" 2>conftest.err)
   ac_status=$?
   cat conftest.err >&5
   echo "$as_me:7017: \$? = $ac_status" >&5
   echo "$as_me:7021: \$? = $ac_status" >&5
   if (exit $ac_status) && test -s "$ac_outfile"; then
     # The compiler can only warn and ignore the option if not recognized
     # So say no if there are warnings other than the usual output.
     $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
       lt_cv_prog_compiler_pic_works=yes
7111
7112
7113
7114
7115
7116
7117
7118

7119
7120
7121
7122

7123
7124
7125
7126
7127
7128
7129
7115
7116
7117
7118
7119
7120
7121

7122
7123
7124
7125

7126
7127
7128
7129
7130
7131
7132
7133







-
+



-
+







   # (2) before a word containing "conftest.", or (3) at the end.
   # Note that $ac_compile itself does not contain backslashes and begins
   # with a dollar sign (not a hyphen), so the echo should work correctly.
   lt_compile=`echo "$ac_compile" | $SED \
   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
   -e 's:$: $lt_compiler_flag:'`
   (eval echo "\"\$as_me:7118: $lt_compile\"" >&5)
   (eval echo "\"\$as_me:7122: $lt_compile\"" >&5)
   (eval "$lt_compile" 2>out/conftest.err)
   ac_status=$?
   cat out/conftest.err >&5
   echo "$as_me:7122: \$? = $ac_status" >&5
   echo "$as_me:7126: \$? = $ac_status" >&5
   if (exit $ac_status) && test -s out/conftest2.$ac_objext
   then
     # The compiler can only warn and ignore the option if not recognized
     # So say no if there are warnings
     $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
7166
7167
7168
7169
7170
7171
7172
7173

7174
7175
7176
7177

7178
7179
7180
7181
7182
7183
7184
7170
7171
7172
7173
7174
7175
7176

7177
7178
7179
7180

7181
7182
7183
7184
7185
7186
7187
7188







-
+



-
+







   # (2) before a word containing "conftest.", or (3) at the end.
   # Note that $ac_compile itself does not contain backslashes and begins
   # with a dollar sign (not a hyphen), so the echo should work correctly.
   lt_compile=`echo "$ac_compile" | $SED \
   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
   -e 's:$: $lt_compiler_flag:'`
   (eval echo "\"\$as_me:7173: $lt_compile\"" >&5)
   (eval echo "\"\$as_me:7177: $lt_compile\"" >&5)
   (eval "$lt_compile" 2>out/conftest.err)
   ac_status=$?
   cat out/conftest.err >&5
   echo "$as_me:7177: \$? = $ac_status" >&5
   echo "$as_me:7181: \$? = $ac_status" >&5
   if (exit $ac_status) && test -s out/conftest2.$ac_objext
   then
     # The compiler can only warn and ignore the option if not recognized
     # So say no if there are warnings
     $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
9546
9547
9548
9549
9550
9551
9552
9553

9554
9555
9556
9557
9558
9559
9560
9550
9551
9552
9553
9554
9555
9556

9557
9558
9559
9560
9561
9562
9563
9564







-
+







else
  	  if test "$cross_compiling" = yes; then :
  lt_cv_dlopen_self=cross
else
  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
  lt_status=$lt_dlunknown
  cat > conftest.$ac_ext <<_LT_EOF
#line 9553 "configure"
#line 9557 "configure"
#include "confdefs.h"

#if HAVE_DLFCN_H
#include <dlfcn.h>
#endif

#include <stdio.h>
9642
9643
9644
9645
9646
9647
9648
9649

9650
9651
9652
9653
9654
9655
9656
9646
9647
9648
9649
9650
9651
9652

9653
9654
9655
9656
9657
9658
9659
9660







-
+







else
  	  if test "$cross_compiling" = yes; then :
  lt_cv_dlopen_self_static=cross
else
  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
  lt_status=$lt_dlunknown
  cat > conftest.$ac_ext <<_LT_EOF
#line 9649 "configure"
#line 9653 "configure"
#include "confdefs.h"

#if HAVE_DLFCN_H
#include <dlfcn.h>
#endif

#include <stdio.h>
10359
10360
10361
10362
10363
10364
10365

10366
10367



10368
10369
10370
10371
10372
10373
10374
10363
10364
10365
10366
10367
10368
10369
10370


10371
10372
10373
10374
10375
10376
10377
10378
10379
10380







+
-
-
+
+
+







fi



if test "x${TCLLIBDIR+set}" != "xset" ; then
  TCLLIBDIR='$(libdir)'
  for i in `echo 'puts stdout $auto_path' | ${TCLSH_CMD}` ; do
    if test -d $i ; then
    TCLLIBDIR=$i
    break
      TCLLIBDIR=$i
      break
    fi
  done
  TCLLIBDIR="${TCLLIBDIR}/sqlite3"
fi


#########
# Set up an appropriate program prefix
10382
10383
10384
10385
10386
10387
10388
10389
10390
10391
10392
10393
10394
10395
10396
10397
10398
10399
10400
10401
10388
10389
10390
10391
10392
10393
10394






10395
10396
10397
10398
10399
10400
10401







-
-
-
-
-
-







{ $as_echo "$as_me:${as_lineno-$LINENO}: Version set to $VERSION" >&5
$as_echo "$as_me: Version set to $VERSION" >&6;}

RELEASE=`cat $srcdir/VERSION`
{ $as_echo "$as_me:${as_lineno-$LINENO}: Release set to $RELEASE" >&5
$as_echo "$as_me: Release set to $RELEASE" >&6;}

VERSION_NUMBER=`cat $srcdir/VERSION \
                           | sed 's/[^0-9]/ /g' \
                | awk '{printf "%d%03d%03d",$1,$2,$3}'`
{ $as_echo "$as_me:${as_lineno-$LINENO}: Version number set to $VERSION_NUMBER" >&5
$as_echo "$as_me: Version number set to $VERSION_NUMBER" >&6;}


#########
# Locate a compiler for the build machine.  This compiler should
# generate command-line programs that run on the build machine.
#
if test x"$cross_compiling" = xno; then
	BUILD_CC=$CC
11248
11249
11250
11251
11252
11253
11254


11255
11256


11257
11258


11259
11260
11261
11262
11263
11264
11265
11266
11267
11268
11269

11270
11271
11272
11273
11274
11275
11276
11248
11249
11250
11251
11252
11253
11254
11255
11256
11257
11258
11259
11260
11261
11262
11263
11264
11265
11266
11267
11268
11269
11270
11271
11272
11273
11274

11275
11276
11277
11278
11279
11280
11281
11282







+
+


+
+


+
+










-
+







#########
# check for debug enabled
# Check whether --enable-debug was given.
if test "${enable_debug+set}" = set; then :
  enableval=$enable_debug;
fi

{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build type" >&5
$as_echo_n "checking build type... " >&6; }
if test "${enable_debug}" = "yes" ; then
  TARGET_DEBUG="-DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE -O0"
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: debug" >&5
$as_echo "debug" >&6; }
else
  TARGET_DEBUG="-DNDEBUG"
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: release" >&5
$as_echo "release" >&6; }
fi


#########
# See whether we should use the amalgamation to build
# Check whether --enable-amalgamation was given.
if test "${enable_amalgamation+set}" = set; then :
  enableval=$enable_amalgamation;
fi

if test "${enable_amalgamation}" == "no" ; then
if test "${enable_amalgamation}" = "no" ; then
  USE_AMALGAMATION=0
fi


#########
# Look for zlib.  Only needed by extensions and by the sqlite3.exe shell
for ac_header in zlib.h
11411
11412
11413
11414
11415
11416
11417







































































































11418
11419
11420
11421
11422
11423
11424
11417
11418
11419
11420
11421
11422
11423
11424
11425
11426
11427
11428
11429
11430
11431
11432
11433
11434
11435
11436
11437
11438
11439
11440
11441
11442
11443
11444
11445
11446
11447
11448
11449
11450
11451
11452
11453
11454
11455
11456
11457
11458
11459
11460
11461
11462
11463
11464
11465
11466
11467
11468
11469
11470
11471
11472
11473
11474
11475
11476
11477
11478
11479
11480
11481
11482
11483
11484
11485
11486
11487
11488
11489
11490
11491
11492
11493
11494
11495
11496
11497
11498
11499
11500
11501
11502
11503
11504
11505
11506
11507
11508
11509
11510
11511
11512
11513
11514
11515
11516
11517
11518
11519
11520
11521
11522
11523
11524
11525
11526
11527
11528
11529
11530
11531
11532
11533







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







  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"

fi

else
  OPT_FEATURE_FLAGS="-DSQLITE_OMIT_LOAD_EXTENSION=1"
fi

##########
# Do we want to support math functions
#
# Check whether --enable-math was given.
if test "${enable_math+set}" = set; then :
  enableval=$enable_math;
fi

{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support math functions" >&5
$as_echo_n "checking whether to support math functions... " >&6; }
if test "$enable_math" = "no"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
  OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MATH_FUNCTIONS"
  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing ceil" >&5
$as_echo_n "checking for library containing ceil... " >&6; }
if ${ac_cv_search_ceil+:} false; then :
  $as_echo_n "(cached) " >&6
else
  ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

/* Override any GCC internal prototype to avoid an error.
   Use char because int might match the return type of a GCC
   builtin and then its argument prototype would still apply.  */
#ifdef __cplusplus
extern "C"
#endif
char ceil ();
int
main ()
{
return ceil ();
  ;
  return 0;
}
_ACEOF
for ac_lib in '' m; do
  if test -z "$ac_lib"; then
    ac_res="none required"
  else
    ac_res=-l$ac_lib
    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
  fi
  if ac_fn_c_try_link "$LINENO"; then :
  ac_cv_search_ceil=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext
  if ${ac_cv_search_ceil+:} false; then :
  break
fi
done
if ${ac_cv_search_ceil+:} false; then :

else
  ac_cv_search_ceil=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_ceil" >&5
$as_echo "$ac_cv_search_ceil" >&6; }
ac_res=$ac_cv_search_ceil
if test "$ac_res" != no; then :
  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"

fi

fi

##########
# Do we want to support JSON functions
#
# Check whether --enable-json was given.
if test "${enable_json+set}" = set; then :
  enableval=$enable_json;
fi

{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support JSON functions" >&5
$as_echo_n "checking whether to support JSON functions... " >&6; }
if test "$enable_json" = "no"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
  OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_OMIT_JSON"
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
fi

########
# The --enable-all argument is short-hand to enable
# multiple extensions.
# Check whether --enable-all was given.
if test "${enable_all+set}" = set; then :
  enableval=$enable_all;
fi


##########
# Do we want to support memsys3 and/or memsys5
#
# Check whether --enable-memsys5 was given.
if test "${enable_memsys5+set}" = set; then :
  enableval=$enable_memsys5;
11453
11454
11455
11456
11457
11458
11459


11460
11461





11462
11463
11464
11465
11466
11467


11468



11469
11470
11471
11472
11473
11474
11475
11562
11563
11564
11565
11566
11567
11568
11569
11570
11571
11572
11573
11574
11575
11576
11577
11578
11579
11580
11581
11582
11583
11584
11585

11586
11587
11588
11589
11590
11591
11592
11593
11594
11595







+
+


+
+
+
+
+






+
+
-
+
+
+







#########
# See whether we should enable Full Text Search extensions
# Check whether --enable-fts3 was given.
if test "${enable_fts3+set}" = set; then :
  enableval=$enable_fts3;
fi

{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support FTS3" >&5
$as_echo_n "checking whether to support FTS3... " >&6; }
if test "${enable_fts3}" = "yes" ; then
  OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS3"
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# Check whether --enable-fts4 was given.
if test "${enable_fts4+set}" = set; then :
  enableval=$enable_fts4;
fi

{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support FTS4" >&5
$as_echo_n "checking whether to support FTS4... " >&6; }
if test "${enable_fts4}" = "yes" ; then
if test "${enable_fts4}" = "yes" -o "${enable_all}" = "yes" ; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
  OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS4"
  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing log" >&5
$as_echo_n "checking for library containing log... " >&6; }
if ${ac_cv_search_log+:} false; then :
  $as_echo_n "(cached) " >&6
else
  ac_func_search_save_LIBS=$LIBS
11519
11520
11521
11522
11523
11524
11525



11526
11527
11528
11529
11530
11531


11532



11533
11534
11535
11536
11537
11538
11539
11639
11640
11641
11642
11643
11644
11645
11646
11647
11648
11649
11650
11651
11652
11653
11654
11655
11656

11657
11658
11659
11660
11661
11662
11663
11664
11665
11666







+
+
+






+
+
-
+
+
+







$as_echo "$ac_cv_search_log" >&6; }
ac_res=$ac_cv_search_log
if test "$ac_res" != no; then :
  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"

fi

else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# Check whether --enable-fts5 was given.
if test "${enable_fts5+set}" = set; then :
  enableval=$enable_fts5;
fi

{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support FTS5" >&5
$as_echo_n "checking whether to support FTS5... " >&6; }
if test "${enable_fts5}" = "yes" ; then
if test "${enable_fts5}" = "yes" -o "${enable_all}" = "yes" ; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
  OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS5"
  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing log" >&5
$as_echo_n "checking for library containing log... " >&6; }
if ${ac_cv_search_log+:} false; then :
  $as_echo_n "(cached) " >&6
else
  ac_func_search_save_LIBS=$LIBS
11583
11584
11585
11586
11587
11588
11589
11590
11591

11592
11593
11594
11595
11596
11597
11598

11599
11600

11601
11602
11603
11604
11605
11606
11607
11608
11609
11610


11611

11612





11613
11614
11615
11616
11617
11618
11619
11620
11621
11622
11623


11624

11625
11626





11627
11628
11629
11630
11631
11632
11633
11634
11635


11636
11637





11638
11639
11640
11641
11642
11643
11644
11645
11646


11647

11648
11649





11650
11651
11652
11653
11654
11655
11656
11710
11711
11712
11713
11714
11715
11716


11717







11718


11719
11720
11721
11722
11723
11724
11725
11726
11727
11728
11729
11730
11731

11732
11733
11734
11735
11736
11737
11738
11739
11740
11741
11742
11743
11744
11745
11746
11747
11748
11749
11750
11751

11752
11753
11754
11755
11756
11757
11758
11759
11760
11761
11762
11763
11764
11765
11766
11767
11768
11769
11770
11771
11772
11773
11774
11775
11776
11777
11778
11779
11780
11781
11782
11783
11784
11785
11786
11787
11788

11789
11790
11791
11792
11793
11794
11795
11796
11797
11798
11799
11800
11801
11802
11803







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










+
+
-
+

+
+
+
+
+











+
+
-
+


+
+
+
+
+









+
+


+
+
+
+
+









+
+
-
+


+
+
+
+
+







$as_echo "$ac_cv_search_log" >&6; }
ac_res=$ac_cv_search_log
if test "$ac_res" != no; then :
  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"

fi

fi

else
#########
# See whether we should enable JSON1
# Check whether --enable-json1 was given.
if test "${enable_json1+set}" = set; then :
  enableval=$enable_json1;
fi

  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
if test "${enable_json1}" = "yes" ; then
  OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1"
$as_echo "no" >&6; }
fi

#########
# See whether we should enable the LIMIT clause on UPDATE and DELETE
# statements.
# Check whether --enable-update-limit was given.
if test "${enable_update_limit+set}" = set; then :
  enableval=$enable_update_limit;
fi

{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support LIMIT on UPDATE and DELETE statements" >&5
$as_echo_n "checking whether to support LIMIT on UPDATE and DELETE statements... " >&6; }
if test "${enable_udlimit}" = "yes" ; then
if test "${enable_update_limit}" = "yes" ; then
  OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT"
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi

#########
# See whether we should enable GEOPOLY
# Check whether --enable-geopoly was given.
if test "${enable_geopoly+set}" = set; then :
  enableval=$enable_geopoly; enable_geopoly=yes
else
  enable_geopoly=no
fi

{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support GEOPOLY" >&5
$as_echo_n "checking whether to support GEOPOLY... " >&6; }
if test "${enable_geopoly}" = "yes" ; then
if test "${enable_geopoly}" = "yes" -o "${enable_all}" = "yes" ; then
  OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_GEOPOLY"
  enable_rtree=yes
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi

#########
# See whether we should enable RTREE
# Check whether --enable-rtree was given.
if test "${enable_rtree+set}" = set; then :
  enableval=$enable_rtree;
fi

{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support RTREE" >&5
$as_echo_n "checking whether to support RTREE... " >&6; }
if test "${enable_rtree}" = "yes" ; then
  OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_RTREE"
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi

#########
# See whether we should enable the SESSION extension
# Check whether --enable-session was given.
if test "${enable_session+set}" = set; then :
  enableval=$enable_session;
fi

{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support SESSION" >&5
$as_echo_n "checking whether to support SESSION... " >&6; }
if test "${enable_session}" = "yes" ; then
if test "${enable_session}" = "yes" -o "${enable_all}" = "yes" ; then
  OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_SESSION"
  OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_PREUPDATE_HOOK"
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi

#########
# attempt to duplicate any OMITS and ENABLES into the ${OPT_FEATURE_FLAGS} parameter
for option in $CFLAGS $CPPFLAGS
do
  case $option in
11710
11711
11712
11713
11714
11715
11716











11717
11718
11719
11720

11721
11722
11723
11724
11725
11726
11727
11857
11858
11859
11860
11861
11862
11863
11864
11865
11866
11867
11868
11869
11870
11871
11872
11873
11874
11875
11876
11877

11878
11879
11880
11881
11882
11883
11884
11885







+
+
+
+
+
+
+
+
+
+
+



-
+







if test "${use_gcov}" = "yes" ; then
  USE_GCOV=1
else
  USE_GCOV=0
fi


#########
# Enable/disabled amalagamation line macros
########
AMALGAMATION_LINE_MACROS=--linemacros=0
if test "${amalgamation_line_macros}" = "yes" ; then
  AMALGAMATION_LINE_MACROS=--linemacros=1
fi
if test "${amalgamation_line_macros}" = "no" ; then
  AMALGAMATION_LINE_MACROS=--linemacros=0
fi


#########
# Output the config header
ac_config_headers="$ac_config_headers config.h"
ac_config_headers="$ac_config_headers sqlite_cfg.h"


#########
# Generate the output files.
#

ac_config_files="$ac_config_files Makefile sqlite3.pc"
12228
12229
12230
12231
12232
12233
12234
12235

12236
12237
12238
12239
12240
12241
12242
12386
12387
12388
12389
12390
12391
12392

12393
12394
12395
12396
12397
12398
12399
12400







-
+







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.27.0, which was
This file was extended by sqlite $as_me 3.41.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 $@
12294
12295
12296
12297
12298
12299
12300
12301

12302
12303
12304
12305
12306
12307
12308
12452
12453
12454
12455
12456
12457
12458

12459
12460
12461
12462
12463
12464
12465
12466







-
+








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.27.0
sqlite config.status 3.41.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."

12676
12677
12678
12679
12680
12681
12682
12683

12684
12685
12686
12687
12688
12689
12690
12834
12835
12836
12837
12838
12839
12840

12841
12842
12843
12844
12845
12846
12847
12848







-
+







cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1

# Handling of arguments.
for ac_config_target in $ac_config_targets
do
  case $ac_config_target in
    "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
    "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
    "sqlite_cfg.h") CONFIG_HEADERS="$CONFIG_HEADERS sqlite_cfg.h" ;;
    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
    "sqlite3.pc") CONFIG_FILES="$CONFIG_FILES sqlite3.pc" ;;

  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
  esac
done

Changes to configure.ac.

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







+
-
-
+
+
+



















-
-
-
-
-







fi
AC_SUBST(TCLSH_CMD)

AC_ARG_VAR([TCLLIBDIR], [Where to install tcl plugin])
if test "x${TCLLIBDIR+set}" != "xset" ; then
  TCLLIBDIR='$(libdir)'
  for i in `echo 'puts stdout $auto_path' | ${TCLSH_CMD}` ; do
    if test -d $i ; then
    TCLLIBDIR=$i
    break
      TCLLIBDIR=$i
      break
    fi
  done
  TCLLIBDIR="${TCLLIBDIR}/sqlite3"
fi


#########
# Set up an appropriate program prefix
#
if test "$program_prefix" = "NONE"; then
  program_prefix=""
fi
AC_SUBST(program_prefix)

VERSION=[`cat $srcdir/VERSION | sed 's/^\([0-9]*\.*[0-9]*\).*/\1/'`]
AC_MSG_NOTICE(Version set to $VERSION)
AC_SUBST(VERSION)
RELEASE=`cat $srcdir/VERSION`
AC_MSG_NOTICE(Release set to $RELEASE)
AC_SUBST(RELEASE)
VERSION_NUMBER=[`cat $srcdir/VERSION \
                           | sed 's/[^0-9]/ /g' \
                | awk '{printf "%d%03d%03d",$1,$2,$3}'`]
AC_MSG_NOTICE(Version number set to $VERSION_NUMBER)
AC_SUBST(VERSION_NUMBER)

#########
# Locate a compiler for the build machine.  This compiler should
# generate command-line programs that run on the build machine.
#
if test x"$cross_compiling" = xno; then
	BUILD_CC=$CC
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
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







+


+


+







-
+







# that use "fdatasync()" function.
#
AC_SEARCH_LIBS(fdatasync, [rt])

#########
# check for debug enabled
AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug],[enable debugging & verbose explain]))
AC_MSG_CHECKING([build type])
if test "${enable_debug}" = "yes" ; then
  TARGET_DEBUG="-DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE -O0"
  AC_MSG_RESULT([debug])
else
  TARGET_DEBUG="-DNDEBUG"
  AC_MSG_RESULT([release])
fi
AC_SUBST(TARGET_DEBUG)

#########
# See whether we should use the amalgamation to build
AC_ARG_ENABLE(amalgamation, AC_HELP_STRING([--disable-amalgamation],
      [Disable the amalgamation and instead build all files separately]))
if test "${enable_amalgamation}" == "no" ; then
if test "${enable_amalgamation}" = "no" ; then
  USE_AMALGAMATION=0
fi
AC_SUBST(USE_AMALGAMATION)

#########
# Look for zlib.  Only needed by extensions and by the sqlite3.exe shell
AC_CHECK_HEADERS(zlib.h)
587
588
589
590
591
592
593

































594
595
596
597
598
599
600
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







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







if test "${enable_load_extension}" = "yes" ; then
  OPT_FEATURE_FLAGS=""
  AC_SEARCH_LIBS(dlopen, dl)
else
  OPT_FEATURE_FLAGS="-DSQLITE_OMIT_LOAD_EXTENSION=1"
fi

##########
# Do we want to support math functions
#
AC_ARG_ENABLE(math, 
AC_HELP_STRING([--disable-math],[Disable math functions]))
AC_MSG_CHECKING([whether to support math functions])
if test "$enable_math" = "no"; then
  AC_MSG_RESULT([no])
else
  AC_MSG_RESULT([yes])
  OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MATH_FUNCTIONS"
  AC_SEARCH_LIBS(ceil, m)
fi

##########
# Do we want to support JSON functions
#
AC_ARG_ENABLE(json, 
AC_HELP_STRING([--disable-json],[Disable JSON functions]))
AC_MSG_CHECKING([whether to support JSON functions])
if test "$enable_json" = "no"; then
  AC_MSG_RESULT([no])
  OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_OMIT_JSON"
else
  AC_MSG_RESULT([yes])
fi

########
# The --enable-all argument is short-hand to enable
# multiple extensions.
AC_ARG_ENABLE(all, AC_HELP_STRING([--enable-all],
      [Enable FTS4, FTS5, Geopoly, RTree, Sessions]))

##########
# Do we want to support memsys3 and/or memsys5
#
AC_ARG_ENABLE(memsys5, 
  AC_HELP_STRING([--enable-memsys5],[Enable MEMSYS5]))
AC_MSG_CHECKING([whether to support MEMSYS5])
if test "${enable_memsys5}" = "yes"; then
613
614
615
616
617
618
619

620
621



622
623
624

625


626
627


628
629
630

631


632
633
634
635

636
637

638
639
640
641
642
643
644
645
646
647

648

649



650
651
652
653
654
655
656

657

658
659



660
661
662
663
664
665

666
667



668
669
670
671
672
673

674

675
676



677
678
679
680
681
682
683
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







+


+
+
+



+
-
+
+


+
+



+
-
+
+


-
-
+
-
-
+
-
-
-







+
-
+

+
+
+







+
-
+


+
+
+






+


+
+
+






+
-
+


+
+
+







  AC_MSG_RESULT([no])
fi

#########
# See whether we should enable Full Text Search extensions
AC_ARG_ENABLE(fts3, AC_HELP_STRING([--enable-fts3],
      [Enable the FTS3 extension]))
AC_MSG_CHECKING([whether to support FTS3])
if test "${enable_fts3}" = "yes" ; then
  OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS3"
  AC_MSG_RESULT([yes])
else
  AC_MSG_RESULT([no])
fi
AC_ARG_ENABLE(fts4, AC_HELP_STRING([--enable-fts4],
      [Enable the FTS4 extension]))
AC_MSG_CHECKING([whether to support FTS4])
if test "${enable_fts4}" = "yes" ; then
if test "${enable_fts4}" = "yes" -o "${enable_all}" = "yes" ; then
  AC_MSG_RESULT([yes])
  OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS4"
  AC_SEARCH_LIBS([log],[m])
else
  AC_MSG_RESULT([no])
fi
AC_ARG_ENABLE(fts5, AC_HELP_STRING([--enable-fts5],
      [Enable the FTS5 extension]))
AC_MSG_CHECKING([whether to support FTS5])
if test "${enable_fts5}" = "yes" ; then
if test "${enable_fts5}" = "yes" -o "${enable_all}" = "yes" ; then
  AC_MSG_RESULT([yes])
  OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS5"
  AC_SEARCH_LIBS([log],[m])
fi

else
#########
# See whether we should enable JSON1
  AC_MSG_RESULT([no])
AC_ARG_ENABLE(json1, AC_HELP_STRING([--enable-json1],[Enable the JSON1 extension]))
if test "${enable_json1}" = "yes" ; then
  OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1"
fi

#########
# See whether we should enable the LIMIT clause on UPDATE and DELETE
# statements.
AC_ARG_ENABLE(update-limit, AC_HELP_STRING([--enable-update-limit],
      [Enable the UPDATE/DELETE LIMIT clause]))
AC_MSG_CHECKING([whether to support LIMIT on UPDATE and DELETE statements])
if test "${enable_udlimit}" = "yes" ; then
if test "${enable_update_limit}" = "yes" ; then
  OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT"
  AC_MSG_RESULT([yes])
else
  AC_MSG_RESULT([no])
fi

#########
# See whether we should enable GEOPOLY
AC_ARG_ENABLE(geopoly, AC_HELP_STRING([--enable-geopoly],
      [Enable the GEOPOLY extension]),
      [enable_geopoly=yes],[enable_geopoly=no])
AC_MSG_CHECKING([whether to support GEOPOLY])
if test "${enable_geopoly}" = "yes" ; then
if test "${enable_geopoly}" = "yes" -o "${enable_all}" = "yes" ; then
  OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_GEOPOLY"
  enable_rtree=yes
  AC_MSG_RESULT([yes])
else
  AC_MSG_RESULT([no])
fi

#########
# See whether we should enable RTREE
AC_ARG_ENABLE(rtree, AC_HELP_STRING([--enable-rtree],
      [Enable the RTREE extension]))
AC_MSG_CHECKING([whether to support RTREE])
if test "${enable_rtree}" = "yes" ; then
  OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_RTREE"
  AC_MSG_RESULT([yes])
else
  AC_MSG_RESULT([no])
fi

#########
# See whether we should enable the SESSION extension
AC_ARG_ENABLE(session, AC_HELP_STRING([--enable-session],
      [Enable the SESSION extension]))
AC_MSG_CHECKING([whether to support SESSION])
if test "${enable_session}" = "yes" ; then
if test "${enable_session}" = "yes" -o "${enable_all}" = "yes" ; then
  OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_SESSION"
  OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_PREUPDATE_HOOK"
  AC_MSG_RESULT([yes])
else
  AC_MSG_RESULT([no])
fi

#########
# attempt to duplicate any OMITS and ENABLES into the ${OPT_FEATURE_FLAGS} parameter
for option in $CFLAGS $CPPFLAGS
do
  case $option in
734
735
736
737
738
739
740











741
742
743
744

745
746
747
748
749
750
751
752
753
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







+
+
+
+
+
+
+
+
+
+
+



-
+









if test "${use_gcov}" = "yes" ; then
  USE_GCOV=1
else
  USE_GCOV=0
fi
AC_SUBST(USE_GCOV)

#########
# Enable/disabled amalagamation line macros
########
AMALGAMATION_LINE_MACROS=--linemacros=0
if test "${amalgamation_line_macros}" = "yes" ; then
  AMALGAMATION_LINE_MACROS=--linemacros=1
fi
if test "${amalgamation_line_macros}" = "no" ; then
  AMALGAMATION_LINE_MACROS=--linemacros=0
fi
AC_SUBST(AMALGAMATION_LINE_MACROS)

#########
# Output the config header
AC_CONFIG_HEADERS(config.h)
AC_CONFIG_HEADERS(sqlite_cfg.h)

#########
# Generate the output files.
#
AC_SUBST(BUILD_CFLAGS)
AC_OUTPUT([
Makefile
sqlite3.pc
])

Added doc/begin_concurrent.md.












































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

Begin Concurrent
================

## Overview

Usually, SQLite allows at most one writer to proceed concurrently. The
BEGIN CONCURRENT enhancement allows multiple writers to process write
transactions simultanously if the database is in "wal" or "wal2" mode,
although the system still serializes COMMIT commands.

When a write-transaction is opened with "BEGIN CONCURRENT", actually 
locking the database is deferred until a COMMIT is executed. This means
that any number of transactions started with BEGIN CONCURRENT may proceed
concurrently. The system uses optimistic page-level-locking to prevent
conflicting concurrent transactions from being committed.

When a BEGIN CONCURRENT transaction is committed, the system checks whether 
or not any of the database pages that the transaction has read have been
modified since the BEGIN CONCURRENT was opened. In other words - it asks 
if the transaction being committed operates on a different set of data than
all other concurrently executing transactions. If the answer is "yes, this
transaction did not read or modify any data modified by any concurrent
transaction", then the transaction is committed as normal. Otherwise, if the
transaction does conflict, it cannot be committed and an SQLITE&#95;BUSY&#95;SNAPSHOT
error is returned. At this point, all the client can do is ROLLBACK the
transaction.

If SQLITE&#95;BUSY&#95;SNAPSHOT is returned, messages are output via the sqlite3&#95;log
mechanism indicating the page and table or index on which the conflict
occurred. This can be useful when optimizing concurrency.

## Application Programming Notes

In order to serialize COMMIT processing, SQLite takes a lock on the database
as part of each COMMIT command and releases it before returning. At most one
writer may hold this lock at any one time. If a writer cannot obtain the lock,
it uses SQLite's busy-handler to pause and retry for a while:

  <a href=https://www.sqlite.org/c3ref/busy_handler.html>
      https://www.sqlite.org/c3ref/busy_handler.html
  </a>

If there is significant contention for the writer lock, this mechanism can be
inefficient. In this case it is better for the application to use a mutex or
some other mechanism that supports blocking to ensure that at most one writer
is attempting to COMMIT a BEGIN CONCURRENT transaction at a time. This is
usually easier if all writers are part of the same operating system process.

If all database clients (readers and writers) are located in the same OS
process, and if that OS is a Unix variant, then it can be more efficient to
the built-in VFS "unix-excl" instead of the default "unix". This is because it
uses more efficient locking primitives.

The key to maximizing concurrency using BEGIN CONCURRENT is to ensure that
there are a large number of non-conflicting transactions. In SQLite, each
table and each index is stored as a separate b-tree, each of which is
distributed over a discrete set of database pages. This means that:

  * Two transactions that write to different sets of tables never 
    conflict, and that

  * Two transactions that write to the same tables or indexes only 
    conflict if the values of the keys (either primary keys or indexed 
    rows) are fairly close together. For example, given a large 
    table with the schema:

      <pre>     CREATE TABLE t1(a INTEGER PRIMARY KEY, b BLOB);</pre>

    writing two rows with adjacent values for "a" probably will cause a
    conflict (as the two keys are stored on the same page), but writing two
    rows with vastly different values for "a" will not (as the keys will likly
    be stored on different pages).

Note that, in SQLite, if values are not explicitly supplied for an INTEGER
PRIMARY KEY, as for example in:

>
     INSERT INTO t1(b) VALUES(&lt;blob-value>);

then monotonically increasing values are assigned automatically. This is
terrible for concurrency, as it all but ensures that all new rows are 
added to the same database page. In such situations, it is better to
explicitly assign random values to INTEGER PRIMARY KEY fields.

This problem also comes up for non-WITHOUT ROWID tables that do not have an
explicit INTEGER PRIMARY KEY column. In these cases each table has an implicit
INTEGER PRIMARY KEY column that is assigned increasing values, leading to the
same problem as omitting to assign a value to an explicit INTEGER PRIMARY KEY
column.

For both explicit and implicit INTEGER PRIMARY KEYs, it is possible to have
SQLite assign values at random (instead of the monotonically increasing
values) by writing a row with a rowid equal to the largest possible signed
64-bit integer to the table. For example:

     INSERT INTO t1(a) VALUES(9223372036854775807);

Applications should take care not to malfunction due to the presence of such
rows.

The nature of some types of indexes, for example indexes on timestamp fields,
can also cause problems (as concurrent transactions may assign similar
timestamps that will be stored on the same db page to new records). In these
cases the database schema may need to be rethought to increase the concurrency
provided by page-level-locking.

Added doc/json-enhancements.md.

















































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# JSON Functions Enhancements (2022)

This document summaries enhancements to the SQLite JSON support added in
early 2022.

## 1.0 Change summary:

  1.  New **->** and **->>** operators that work like MySQL and PostgreSQL (PG).
  2.  JSON functions are built-in rather than being an extension.  They
      are included by default, but can be omitted using the
      -DSQLITE_OMIT_JSON compile-time option.


## 2.0 New operators **->** and **->>**

The SQLite language adds two new binary operators **->** and **->>**.
Both operators are similar to json_extract().  The left operand is
JSON and the right operand is a JSON path expression (possibly abbreviated
for compatibility with PG - see below).  So they are similar to a
two-argument call to json_extract().

The difference between -> and ->> (and json_extract()) is as follows:

  *  The -> operator always returns JSON.

  *  The ->> operator converts the answer into a primitive SQL datatype
     such as TEXT, INTEGER, REAL, or NULL.  If a JSON object or array
     is selected, that object or array is rendered as text.  If a JSON
     value is selected, that value is converted into its corresponding
     SQL type

  *  The json_extract() interface returns JSON when a JSON object or
     array is selected, or a primitive SQL datatype when a JSON value
     is selected.  This is different from MySQL, in which json_extract()
     always returns JSON, but the difference is retained because it has
     worked that way for 6 years and changing it now would likely break
     a lot of legacy code.

In MySQL and PG, the ->> operator always returns TEXT (or NULL) and never
INTEGER or REAL.  This is due to limitations in the type handling capabilities
of those systems.  In MySQL and PG, the result type a function or operator
may only depend on the type of its arguments, never the value of its arguments.
But the underlying JSON type depends on the value of the JSON path
expression, not the type of the JSON path expression (which is always TEXT).
Hence, the result type of ->> in MySQL and PG is unable to vary according
to the type of the JSON value being extracted.

The type system in SQLite is more general.  Functions in SQLite are able
to return different datatypes depending on the value of their arguments.
So the ->> operator in SQLite is able to return TEXT, INTEGER, REAL, or NULL
depending on the JSON type of the value being extracted.  This means that
the behavior of the ->> is slightly different in SQLite versus MySQL and PG
in that it will sometimes return INTEGER and REAL values, depending on its
inputs.  It is possible to implement the ->> operator in SQLite so that it
always operates exactly like MySQL and PG and always returns TEXT or NULL,
but I have been unable to think of any situations where returning the
actual JSON value this would cause problems, so I'm including the enhanced
functionality in SQLite.

The table below attempts to summarize the differences between the
-> and ->> operators and the json_extract() function, for SQLite, MySQL,
and PG.  JSON values are shown using their SQL text representation but
in a bold font.


<table border=1 cellpadding=5 cellspacing=0>
<tr><th>JSON<th>PATH<th>-&gt; operator<br>(all)<th>-&gt;&gt; operator<br>(MySQL/PG)
    <th>-&gt;&gt; operator<br>(SQLite)<th>json_extract()<br>(SQLite)
<tr><td> **'{"a":123}'**     <td>'$.a'<td> **'123'**     <td> '123'          <td> 123           <td> 123
<tr><td> **'{"a":4.5}'**     <td>'$.a'<td> **'4.5'**     <td> '4.5'          <td> 4.5           <td> 4.5
<tr><td> **'{"a":"xyz"}'**   <td>'$.a'<td> **'"xyz"'**   <td> 'xyz'          <td> 'xyz'         <td> 'xyz'
<tr><td> **'{"a":null}'**    <td>'$.a'<td> **'null'**    <td> NULL           <td> NULL          <td> NULL
<tr><td> **'{"a":[6,7,8]}'** <td>'$.a'<td> **'[6,7,8]'** <td> '[6,7,8]'      <td> '[6,7,8]'     <td> **'[6,7,8]'**
<tr><td> **'{"a":{"x":9}}'** <td>'$.a'<td> **'{"x":9}'** <td> '{"x":9}'      <td> '{"x":9}'     <td> **'{"x":9}'**
<tr><td> **'{"b":999}'**     <td>'$.a'<td> NULL          <td> NULL           <td> NULL          <td> NULL
</table>

Important points about the table above:

  *  The -> operator always returns either JSON or NULL.

  *  The ->> operator never returns JSON.  It always returns TEXT or NULL, or in the
     case of SQLite, INTEGER or REAL.

  *  The MySQL json_extract() function works exactly the same
     as the MySQL -> operator.

  *  The SQLite json_extract() operator works like -> for JSON objects and
     arrays, and like ->> for JSON values.

  *  The -> operator works the same for all systems.

  *  The only difference in ->> between SQLite and other systems is that
     when the JSON value is numeric, SQLite returns a numeric SQL value,
     whereas the other systems return a text representation of the numeric
     value.

### 2.1 Abbreviated JSON path expressions for PG compatibility

The table above always shows the full JSON path expression: '$.a'.  But
PG does not accept this syntax.  PG only allows a single JSON object label
name or a single integer array index.  In order to provide compatibility
with PG, The -> and ->> operators in SQLite are extended to also support
a JSON object label or an integer array index for the right-hand side
operand, in addition to a full JSON path expression.

Thus, a -> or ->> operator that works on MySQL will work in
SQLite.  And a -> or ->> operator that works in PG will work in SQLite.
But because SQLite supports the union of the disjoint capabilities of
MySQL and PG, there will always be -> and ->> operators that work in
SQLite that do not work in one of MySQL and PG.  This is an unavoidable
consequence of the different syntax for -> and ->> in MySQL and PG.

In the following table, assume that "value1" is a JSON object and
"value2" is a JSON array.

<table border=1 cellpadding=5 cellspacing=0>
<tr><th>SQL expression     <th>Works in MySQL?<th>Works in PG?<th>Works in SQLite
<tr><td>value1-&gt;'$.a'   <td> yes           <td>  no        <td> yes
<tr><td>value1-&gt;'a'     <td> no            <td>  yes       <td> yes
<tr><td>value2-&gt;'$[2]'  <td> yes           <td>  no        <td> yes
<tr><td>value2-&gt;2       <td> no            <td>  yes       <td> yes
</table>

The abbreviated JSON path expressions only work for the -> and ->> operators
in SQLite.  The json_extract() function, and all other built-in SQLite
JSON functions, continue to require complete JSON path expressions for their
PATH arguments.

## 3.0 JSON moved into the core

The JSON interface is now moved into the SQLite core.

When originally written in 2015, the JSON functions were an extension
that could be optionally included at compile-time, or loaded at run-time.
The implementation was in a source file named ext/misc/json1.c in the
source tree.  JSON functions were only compiled in if the
-DSQLITE_ENABLE_JSON1 compile-time option was used.

After these enhancements, the JSON functions are now built-ins.
The source file that implements the JSON functions is moved to src/json.c.
No special compile-time options are needed to load JSON into the build.
Instead, there is a new -DSQLITE_OMIT_JSON compile-time option to leave
them out.

Changes to doc/lemon.html.

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
1
2
3
4

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

57
58
59
60

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77

78
79

80
81
82

83
84
85
86
87




88
89
90
91
92
93
94

95
96


97
98
99
100
101
102

103
104
105
106
107
108
109

110
111
112
113

114
115
116
117
118
119
120
121

122
123
124
125

126
127
128
129

130
131
132
133
134
135
136
137
138
139
140
141


142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164

165
166
167
168
169
170
171
172

173
174
175
176
177
178
179
180
181
182

183
184
185
186

187
188
189
190
191
192
193
194
195
196

197
198
199
200

201
202
203
204
205
206
207

208
209
210
211

212
213
214
215
216
217
218
219




-
+
+




















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



-
+















+
-
+

-
+


-
+




-
-
-
-
+
+
+
+
+


-
+

-
-
+
+
+



-
+






-
+



-
+






+
-
+



-
+



-
+











-
-
+
+
+

+
+
+
















-
+






+
-
+









-
+



-
+









-
+



-
+






-
+



-
+







<html>
<head>
<title>The Lemon Parser Generator</title>
</head>
<body bgcolor='white'>
<body>
<a id="main"></a>
<h1 align='center'>The Lemon Parser Generator</h1>

<p>Lemon is an LALR(1) parser generator for C.
It does the same job as "bison" and "yacc".
But Lemon is not a bison or yacc clone.  Lemon
uses a different grammar syntax which is designed to
reduce the number of coding errors.  Lemon also uses a
parsing engine that is faster than yacc and
bison and which is both reentrant and threadsafe.
(Update: Since the previous sentence was written, bison
has also been updated so that it too can generate a
reentrant and threadsafe parser.)
Lemon also implements features that can be used
to eliminate resource leaks, making it suitable for use
in long-running programs such as graphical user interfaces
or embedded controllers.</p>

<p>This document is an introduction to the Lemon
parser generator.</p>

<a id="toc"></a>
<h2>1.0 Table of Contents</h2>
<ul>
<li><a href="#main">Introduction</a>
<li><a href="#toc">1.0 Table of Contents</a>
<li><a href="#secnot">2.0 Security Notes</a><br>
<li><a href="#optheory">3.0 Theory of Operation</a>
    <ul>
    <li><a href="#options">3.1 Command Line Options</a>
    <li><a href="#interface">3.2 The Parser Interface</a>
        <ul>
        <li><a href="#onstack">3.2.1 Allocating The Parse Object On Stack</a>
        <li><a href="#ifsum">3.2.2 Interface Summary</a>
        </ul>
    <li><a href="#yaccdiff">3.3 Differences With YACC and BISON</a>
    <li><a href="#build">3.4 Building The "lemon" Or "lemon.exe" Executable</a>
    </ul>
<li><a href="#syntax">4.0 Input File Syntax</a>
    <ul>
    <li><a href="#tnt">4.1 Terminals and Nonterminals</a>
    <li><a href="#rules">4.2 Grammar Rules</a>
    <li><a href="#precrules">4.3 Precedence Rules</a>
    <li><a href="#special">4.4 Special Directives</a>
    </ul>
<li><a href="#errors">5.0 Error Processing</a>
<li><a href="#history">6.0 History of Lemon</a>
<li><a href="#copyright">7.0 Copyright</a>
</ul>

<a id="secnot"></a>
<h2>Security Note</h2>
<h2>2.0 Security Note</h2>

<p>The language parser code created by Lemon is very robust and
is well-suited for use in internet-facing applications that need to
safely process maliciously crafted inputs.
safely process maliciously crafted inputs.</p>

<p>The "lemon.exe" command-line tool itself works great when given a valid
input grammar file and almost always gives helpful
error messages for malformed inputs.  However,  it is possible for
a malicious user to craft a grammar file that will cause 
lemon.exe to crash.
We do not see this as a problem, as lemon.exe is not intended to be used
with hostile inputs.
To summarize:</p>

<ul>
<li>Parser code generated by lemon &rarr; Robust and secure
<li>The "lemon.exe" command line tool itself &rarr; Not so much
</ul>

<a id="optheory"></a>
<h2>Theory of Operation</h2>
<h2>3.0 Theory of Operation</h2>

<p>The main goal of Lemon is to translate a context free grammar (CFG)
<p>Lemon is computer program that translates a context free grammar (CFG)
for a particular language into C code that implements a parser for
that language.
The program has two inputs:
The Lemon program has two inputs:</p>
<ul>
<li>The grammar specification.
<li>A parser template file.
</ul>
Typically, only the grammar specification is supplied by the programmer.
Lemon comes with a default parser template which works fine for most
applications.  But the user is free to substitute a different parser
template if desired.</p>
<p>Typically, only the grammar specification is supplied by the programmer.
Lemon comes with a default parser template
("<a href="https://sqlite.org/src/file/tool/lempar.c">lempar.c</a>")
that works fine for most applications.  But the user is free to substitute
a different parser template if desired.</p>

<p>Depending on command-line options, Lemon will generate up to
three output files.
three output files.</p>
<ul>
<li>C code to implement the parser.
<li>A header file defining an integer ID for each terminal symbol.
<li>C code to implement a parser for the input grammar.
<li>A header file defining an integer ID for each terminal symbol
    (or "token").
<li>An information file that describes the states of the generated parser
    automaton.
</ul>
By default, all three of these output files are generated.
<p>By default, all three of these output files are generated.
The header file is suppressed if the "-m" command-line option is
used and the report file is omitted when "-q" is selected.</p>

<p>The grammar specification file uses a ".y" suffix, by convention.
In the examples used in this document, we'll assume the name of the
grammar file is "gram.y".  A typical use of Lemon would be the
following command:
following command:</p>
<pre>
   lemon gram.y
</pre>
This command will generate three output files named "gram.c",
<p>This command will generate three output files named "gram.c",
"gram.h" and "gram.out".
The first is C code to implement the parser.  The second
is the header file that defines numerical values for all
terminal symbols, and the last is the report that explains
the states used by the parser automaton.</p>

<a id="options"></a>
<h3>Command Line Options</h3>
<h3>3.1 Command Line Options</h3>

<p>The behavior of Lemon can be modified using command-line options.
You can obtain a list of the available command-line options together
with a brief explanation of what each does by typing
with a brief explanation of what each does by typing</p>
<pre>
   lemon "-?"
</pre>
As of this writing, the following command-line options are supported:
<p>As of this writing, the following command-line options are supported:</p>
<ul>
<li><b>-b</b>
Show only the basis for each parser state in the report file.
<li><b>-c</b>
Do not compress the generated action tables.  The parser will be a
little larger and slower, but it will detect syntax errors sooner.
<li><b>-d</b><i>directory</i>
Write all output files into <i>directory</i>.  Normally, output files
are written into the directory that contains the input grammar file.
<li><b>-D<i>name</i></b>
Define C preprocessor macro <i>name</i>.  This macro is usable by
"<tt><a href='#pifdef'>%ifdef</a></tt>" and
"<tt><a href='#pifdef'>%ifndef</a></tt>" lines
"<tt><a href='#pifdef'>%ifdef</a></tt>",
"<tt><a href='#pifdef'>%ifndef</a></tt>", and
"<tt><a href="#pifdef">%if</a></tt> lines
in the grammar file.
<li><b>-E</b>
Run the "%if" preprocessor step only and print the revised grammar
file.
<li><b>-g</b>
Do not generate a parser.  Instead write the input grammar to standard
output with all comments, actions, and other extraneous text removed.
<li><b>-l</b>
Omit "#line" directives in the generated parser C code.
<li><b>-m</b>
Cause the output C source code to be compatible with the "makeheaders"
program.
<li><b>-p</b>
Display all conflicts that are resolved by
<a href='#precrules'>precedence rules</a>.
<li><b>-q</b>
Suppress generation of the report file.
<li><b>-r</b>
Do not sort or renumber the parser states as part of optimization.
<li><b>-s</b>
Show parser statistics before existing.
Show parser statistics before exiting.
<li><b>-T<i>file</i></b>
Use <i>file</i> as the template for the generated C-code parser implementation.
<li><b>-x</b>
Print the Lemon version number.
</ul>

<a id="interface"></a>
<h3>The Parser Interface</h3>
<h3>3.2 The Parser Interface</h3>

<p>Lemon doesn't generate a complete, working program.  It only generates
a few subroutines that implement a parser.  This section describes
the interface to those subroutines.  It is up to the programmer to
call these subroutines in an appropriate way in order to produce a
complete system.</p>

<p>Before a program begins using a Lemon-generated parser, the program
must first create the parser.
A new parser is created as follows:
A new parser is created as follows:</p>
<pre>
   void *pParser = ParseAlloc( malloc );
</pre>
The ParseAlloc() routine allocates and initializes a new parser and
<p>The ParseAlloc() routine allocates and initializes a new parser and
returns a pointer to it.
The actual data structure used to represent a parser is opaque &mdash;
its internal structure is not visible or usable by the calling routine.
For this reason, the ParseAlloc() routine returns a pointer to void
rather than a pointer to some particular structure.
The sole argument to the ParseAlloc() routine is a pointer to the
subroutine used to allocate memory.  Typically this means malloc().</p>

<p>After a program is finished using a parser, it can reclaim all
memory allocated by that parser by calling
memory allocated by that parser by calling</p>
<pre>
   ParseFree(pParser, free);
</pre>
The first argument is the same pointer returned by ParseAlloc().  The
<p>The first argument is the same pointer returned by ParseAlloc().  The
second argument is a pointer to the function used to release bulk
memory back to the system.</p>

<p>After a parser has been allocated using ParseAlloc(), the programmer
must supply the parser with a sequence of tokens (terminal symbols) to
be parsed.  This is accomplished by calling the following function
once for each token:
once for each token:<p>
<pre>
   Parse(pParser, hTokenID, sTokenData, pArg);
</pre>
The first argument to the Parse() routine is the pointer returned by
<p>The first argument to the Parse() routine is the pointer returned by
ParseAlloc().
The second argument is a small positive integer that tells the parser the
type of the next token in the data stream.
There is one token type for each terminal symbol in the grammar.
The gram.h file generated by Lemon contains #define statements that
map symbolic terminal symbol names into appropriate integer values.
A value of 0 for the second argument is a special flag to the
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
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







-
+




















-
+











-
+










-
+










-
+










-
+



-
+





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



-
+








-
+







-
+


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







-
+

-
-
-
+
+
+

+
-
+







the Parse() function will have a fourth parameter that can be
of any type chosen by the programmer.  The parser doesn't do anything
with this argument except to pass it through to action routines.
This is a convenient mechanism for passing state information down
to the action routines without having to use global variables.</p>

<p>A typical use of a Lemon parser might look something like the
following:
following:</p>
<pre>
    1 ParseTree *ParseFile(const char *zFilename){
    2    Tokenizer *pTokenizer;
    3    void *pParser;
    4    Token sToken;
    5    int hTokenId;
    6    ParserState sState;
    7
    8    pTokenizer = TokenizerCreate(zFilename);
    9    pParser = ParseAlloc( malloc );
   10    InitParserState(&amp;sState);
   11    while( GetNextToken(pTokenizer, &amp;hTokenId, &amp;sToken) ){
   12       Parse(pParser, hTokenId, sToken, &amp;sState);
   13    }
   14    Parse(pParser, 0, sToken, &amp;sState);
   15    ParseFree(pParser, free );
   16    TokenizerFree(pTokenizer);
   17    return sState.treeRoot;
   18 }
</pre>
This example shows a user-written routine that parses a file of
<p>This example shows a user-written routine that parses a file of
text and returns a pointer to the parse tree.
(All error-handling code is omitted from this example to keep it
simple.)
We assume the existence of some kind of tokenizer which is created
using TokenizerCreate() on line 8 and deleted by TokenizerFree()
on line 16.  The GetNextToken() function on line 11 retrieves the
next token from the input file and puts its type in the
integer variable hTokenId.  The sToken variable is assumed to be
some kind of structure that contains details about each token,
such as its complete text, what line it occurs on, etc.</p>

<p>This example also assumes the existence of structure of type
<p>This example also assumes the existence of a structure of type
ParserState that holds state information about a particular parse.
An instance of such a structure is created on line 6 and initialized
on line 10.  A pointer to this structure is passed into the Parse()
routine as the optional 4th argument.
The action routine specified by the grammar for the parser can use
the ParserState structure to hold whatever information is useful and
appropriate.  In the example, we note that the treeRoot field of
the ParserState structure is left pointing to the root of the parse
tree.</p>

<p>The core of this example as it relates to Lemon is as follows:
<p>The core of this example as it relates to Lemon is as follows:</p>
<pre>
   ParseFile(){
      pParser = ParseAlloc( malloc );
      while( GetNextToken(pTokenizer,&amp;hTokenId, &amp;sToken) ){
         Parse(pParser, hTokenId, sToken);
      }
      Parse(pParser, 0, sToken);
      ParseFree(pParser, free );
   }
</pre>
Basically, what a program has to do to use a Lemon-generated parser
<p>Basically, what a program has to do to use a Lemon-generated parser
is first create the parser, then send it lots of tokens obtained by
tokenizing an input source.  When the end of input is reached, the
Parse() routine should be called one last time with a token type
of 0.  This step is necessary to inform the parser that the end of
input has been reached.  Finally, we reclaim memory used by the
parser by calling ParseFree().</p>

<p>There is one other interface routine that should be mentioned
before we move on.
The ParseTrace() function can be used to generate debugging output
from the parser.  A prototype for this routine is as follows:
from the parser.  A prototype for this routine is as follows:</p>
<pre>
   ParseTrace(FILE *stream, char *zPrefix);
</pre>
After this routine is called, a short (one-line) message is written
<p>After this routine is called, a short (one-line) message is written
to the designated output stream every time the parser changes states
or calls an action routine.  Each such message is prefaced using
the text given by zPrefix.  This debugging output can be turned off
by calling ParseTrace() again with a first argument of NULL (0).</p>

<a id="onstack"></a>
<h4>3.2.1 Allocating The Parse Object On Stack</h4>

<p>If all calls to the Parse() interface are made from within
<a href="#pcode"><tt>%code</tt> directives</a>, then the parse
object can be allocated from the stack rather than from the heap.
These are the steps:

<ul>
<li> Declare a local variable of type "yyParser"
<li> Initialize the variable using ParseInit()
<li> Pass a pointer to the variable in calls ot Parse()
<li> Deallocate substructure in the parse variable using ParseFinalize().
</ul>

<p>The following code illustrates how this is done:

<pre>
   ParseFile(){
      yyParser x;
      ParseInit( &x );
      while( GetNextToken(pTokenizer,&amp;hTokenId, &amp;sToken) ){
         Parse(&x, hTokenId, sToken);
      }
      Parse(&x, 0, sToken);
      ParseFinalize( &x );
   }
</pre>

<a id="ifsum"></a>
<h4>3.2.2 Interface Summary</h4>

<p>Here is a quick overview of the C-language interface to a
Lemon-generated parser:</p>

<blockquote><pre>
void *ParseAlloc( (void*(*malloc)(size_t) );
void ParseFree(void *pParser, (void(*free)(void*) );
void Parse(void *pParser, int tokenCode, ParseTOKENTYPE token, ...);
void ParseTrace(FILE *stream, char *zPrefix);
</pre></blockquote>

<p>Notes:</p>
<ul>
<li> Use the <a href="#pname"><tt>%name</tt> directive</a> to change
the "Parse" prefix names of the procedures in the interface.
<li> Use the <a href="#token_type"><tt>%token_type</tt> directive</a>
to define the "ParseTOKENTYPE" type.
<li> Use the <a href="#extraarg"><tt>%extra_argument</tt> directive</a>
to specify the type and name of the 4th parameter to the
Parse() function.
</ul>

<a id="yaccdiff"></a>
<h3>Differences With YACC and BISON</h3>
<h3>3.3 Differences With YACC and BISON</h3>

<p>Programmers who have previously used the yacc or bison parser
generator will notice several important differences between yacc and/or
bison and Lemon.
bison and Lemon.</p>
<ul>
<li>In yacc and bison, the parser calls the tokenizer.  In Lemon,
    the tokenizer calls the parser.
<li>Lemon uses no global variables.  Yacc and bison use global variables
    to pass information between the tokenizer and parser.
<li>Lemon allows multiple parsers to be running simultaneously.  Yacc
    and bison do not.
</ul>
These differences may cause some initial confusion for programmers
<p>These differences may cause some initial confusion for programmers
with prior yacc and bison experience.
But after years of experience using Lemon, I firmly
believe that the Lemon way of doing things is better.</p>

<p><i>Updated as of 2016-02-16:</i>
The text above was written in the 1990s.
We are told that Bison has lately been enhanced to support the
tokenizer-calls-parser paradigm used by Lemon, and to obviate the
tokenizer-calls-parser paradigm used by Lemon, eliminating the
need for global variables.</p>

<a id="build"><a>
<h3>3.4 Building The "lemon" or "lemon.exe" Executable</h3>

<p>The "lemon" or "lemon.exe" program is built from a single file
of C-code named 
"<a href="https://sqlite.org/src/tool/lemon.c">lemon.c</a>". 
The Lemon source code is generic C89 code that uses
no unusual or non-standard libraries.  Any
reasonable C compiler should suffice to compile the lemon program.  
A command-line like the following will usually work:</p>

<blockquote><pre>
cc -o lemon lemon.c
</pre></blockquote

<p>On Windows machines with Visual C++ installed, bring up a
"VS20<i>NN</i> x64 Native Tools Command Prompt" window and enter:

<blockquote><pre>
cl lemon.c
</pre></blockquote>

<p>Compiling Lemon really is that simple. 
Additional compiler options such as
"-O2" or "-g" or "-Wall" can be added if desired, but they are not
necessary.</p>


<a id="syntax"></a>
<h2>Input File Syntax</h2>
<h2>4.0 Input File Syntax</h2>

<p>The main purpose of the grammar specification file for Lemon is
to define the grammar for the parser.  But the input file also
specifies additional information Lemon requires to do its job.
Most of the work in using Lemon is in writing an appropriate
grammar file.</p>

<p>The grammar file for Lemon is, for the most part, free format.
<p>The grammar file for Lemon is, for the most part, a free format.
It does not have sections or divisions like yacc or bison.  Any
declaration can occur at any point in the file.
Lemon ignores whitespace (except where it is needed to separate
tokens), and it honors the same commenting conventions as C and C++.</p>
declaration can occur at any point in the file.  Lemon ignores
whitespace (except where it is needed to separate tokens), and it
honors the same commenting conventions as C and C++.</p>

<a id="tnt"></a>
<h3>Terminals and Nonterminals</h3>
<h3>4.1 Terminals and Nonterminals</h3>

<p>A terminal symbol (token) is any string of alphanumeric
and/or underscore characters
that begins with an uppercase letter.
A terminal can contain lowercase letters after the first character,
but the usual convention is to make terminals all uppercase.
A nonterminal, on the other hand, is any string of alphanumeric
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
638

639
640
641
642
643
644

645
646
647
648
649
650
651
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
638
639
640
641
642
643
644
645
646
647
648
649

650
651
652
653
654
655
656
657
658
659
660
661
662
663

664
665
666
667
668
669
670
671
672
673
674
675

676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707

708
709
710


711
712
713
714
715
716
717
718
719
720
721
722
723
724
725


726
727
728
729
730
731

732
733
734
735
736
737
738
739


740
741
742
743
744
745
746


747
748
749
750
751
752
753
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







+
-
+












-
+






-











-
+



-
















-
+



-
+



-
+


-
+









-
+



-
+







-
-
+
+

















-
+






-
+




-
+



-
+



-
+

-
+



-
+



-
+



-
+



-
-
+
+



-
+





-
+




-
+

-
+








-
+



















-
+












+
-
+











-
+





+



+













+







-
+


-
-
+
+










+
+
+
-
-
+
+




-
+







-
-
+
+





-
-
+
+








-
+






-
+



-
+





-
+








<p>Yacc and bison allow terminal symbols to have either alphanumeric
names or to be individual characters included in single quotes, like
this: ')' or '$'.  Lemon does not allow this alternative form for
terminal symbols.  With Lemon, all symbols, terminals and nonterminals,
must have alphanumeric names.</p>

<a id="rules"></a>
<h3>Grammar Rules</h3>
<h3>4.2 Grammar Rules</h3>

<p>The main component of a Lemon grammar file is a sequence of grammar
rules.
Each grammar rule consists of a nonterminal symbol followed by
the special symbol "::=" and then a list of terminals and/or nonterminals.
The rule is terminated by a period.
The list of terminals and nonterminals on the right-hand side of the
rule can be empty.
Rules can occur in any order, except that the left-hand side of the
first rule is assumed to be the start symbol for the grammar (unless
specified otherwise using the <tt><a href='#start_symbol'>%start_symbol</a></tt>
directive described below.)
A typical sequence of grammar rules might look something like this:
A typical sequence of grammar rules might look something like this:</p>
<pre>
  expr ::= expr PLUS expr.
  expr ::= expr TIMES expr.
  expr ::= LPAREN expr RPAREN.
  expr ::= VALUE.
</pre>
</p>

<p>There is one non-terminal in this example, "expr", and five
terminal symbols or tokens: "PLUS", "TIMES", "LPAREN",
"RPAREN" and "VALUE".</p>

<p>Like yacc and bison, Lemon allows the grammar to specify a block
of C code that will be executed whenever a grammar rule is reduced
by the parser.
In Lemon, this action is specified by putting the C code (contained
within curly braces <tt>{...}</tt>) immediately after the
period that closes the rule.
For example:
For example:</p>
<pre>
  expr ::= expr PLUS expr.   { printf("Doing an addition...\n"); }
</pre>
</p>

<p>In order to be useful, grammar actions must normally be linked to
their associated grammar rules.
In yacc and bison, this is accomplished by embedding a "$$" in the
action to stand for the value of the left-hand side of the rule and
symbols "$1", "$2", and so forth to stand for the value of
the terminal or nonterminal at position 1, 2 and so forth on the
right-hand side of the rule.
This idea is very powerful, but it is also very error-prone.  The
single most common source of errors in a yacc or bison grammar is
to miscount the number of symbols on the right-hand side of a grammar
rule and say "$7" when you really mean "$8".</p>

<p>Lemon avoids the need to count grammar symbols by assigning symbolic
names to each symbol in a grammar rule and then using those symbolic
names in the action.
In yacc or bison, one would write this:
In yacc or bison, one would write this:</p>
<pre>
  expr -&gt; expr PLUS expr  { $$ = $1 + $3; };
</pre>
But in Lemon, the same rule becomes the following:
<p>But in Lemon, the same rule becomes the following:</p>
<pre>
  expr(A) ::= expr(B) PLUS expr(C).  { A = B+C; }
</pre>
In the Lemon rule, any symbol in parentheses after a grammar rule
<p>In the Lemon rule, any symbol in parentheses after a grammar rule
symbol becomes a place holder for that symbol in the grammar rule.
This place holder can then be used in the associated C action to
stand for the value of that symbol.<p>
stand for the value of that symbol.</p>

<p>The Lemon notation for linking a grammar rule with its reduce
action is superior to yacc/bison on several counts.
First, as mentioned above, the Lemon method avoids the need to
count grammar symbols.
Secondly, if a terminal or nonterminal in a Lemon grammar rule
includes a linking symbol in parentheses but that linking symbol
is not actually used in the reduce action, then an error message
is generated.
For example, the rule
For example, the rule</p>
<pre>
  expr(A) ::= expr(B) PLUS expr(C).  { A = B; }
</pre>
will generate an error because the linking symbol "C" is used
<p>will generate an error because the linking symbol "C" is used
in the grammar rule but not in the reduce action.</p>

<p>The Lemon notation for linking grammar rules to reduce actions
also facilitates the use of destructors for reclaiming memory
allocated by the values of terminals and nonterminals on the
right-hand side of a rule.</p>

<a name='precrules'></a>
<h3>Precedence Rules</h3>
<a id='precrules'></a>
<h3>4.3 Precedence Rules</h3>

<p>Lemon resolves parsing ambiguities in exactly the same way as
yacc and bison.  A shift-reduce conflict is resolved in favor
of the shift, and a reduce-reduce conflict is resolved by reducing
whichever rule comes first in the grammar file.</p>

<p>Just like in
yacc and bison, Lemon allows a measure of control
over the resolution of parsing conflicts using precedence rules.
A precedence value can be assigned to any terminal symbol
using the
<tt><a href='#pleft'>%left</a></tt>,
<tt><a href='#pright'>%right</a></tt> or
<tt><a href='#pnonassoc'>%nonassoc</a></tt> directives.  Terminal symbols
mentioned in earlier directives have a lower precedence than
terminal symbols mentioned in later directives.  For example:</p>

<p><pre>
<pre>
   %left AND.
   %left OR.
   %nonassoc EQ NE GT GE LT LE.
   %left PLUS MINUS.
   %left TIMES DIVIDE MOD.
   %right EXP NOT.
</pre></p>
</pre>

<p>In the preceding sequence of directives, the AND operator is
defined to have the lowest precedence.  The OR operator is one
precedence level higher.  And so forth.  Hence, the grammar would
attempt to group the ambiguous expression
attempt to group the ambiguous expression</p>
<pre>
     a AND b OR c
</pre>
like this
<p>like this</p>
<pre>
     a AND (b OR c).
</pre>
The associativity (left, right or nonassoc) is used to determine
<p>The associativity (left, right or nonassoc) is used to determine
the grouping when the precedence is the same.  AND is left-associative
in our example, so
in our example, so</p>
<pre>
     a AND b AND c
</pre>
is parsed like this
<p>is parsed like this</p>
<pre>
     (a AND b) AND c.
</pre>
The EXP operator is right-associative, though, so
<p>The EXP operator is right-associative, though, so</p>
<pre>
     a EXP b EXP c
</pre>
is parsed like this
<p>is parsed like this</p>
<pre>
     a EXP (b EXP c).
</pre>
The nonassoc precedence is used for non-associative operators.
So
<p>The nonassoc precedence is used for non-associative operators.
So</p>
<pre>
     a EQ b EQ c
</pre>
is an error.</p>
<p>is an error.</p>

<p>The precedence of non-terminals is transferred to rules as follows:
The precedence of a grammar rule is equal to the precedence of the
left-most terminal symbol in the rule for which a precedence is
defined.  This is normally what you want, but in those cases where
you want to precedence of a grammar rule to be something different,
you want the precedence of a grammar rule to be something different,
you can specify an alternative precedence symbol by putting the
symbol in square braces after the period at the end of the rule and
before any C-code.  For example:</p>

<p><pre>
<pre>
   expr = MINUS expr.  [NOT]
</pre></p>
</pre>

<p>This rule has a precedence equal to that of the NOT symbol, not the
MINUS symbol as would have been the case by default.</p>

<p>With the knowledge of how precedence is assigned to terminal
symbols and individual
grammar rules, we can now explain precisely how parsing conflicts
are resolved in Lemon.  Shift-reduce conflicts are resolved
as follows:
as follows:</p>
<ul>
<li> If either the token to be shifted or the rule to be reduced
     lacks precedence information, then resolve in favor of the
     shift, but report a parsing conflict.
<li> If the precedence of the token to be shifted is greater than
     the precedence of the rule to reduce, then resolve in favor
     of the shift.  No parsing conflict is reported.
<li> If the precedence of the token to be shifted is less than the
     precedence of the rule to reduce, then resolve in favor of the
     reduce action.  No parsing conflict is reported.
<li> If the precedences are the same and the shift token is
     right-associative, then resolve in favor of the shift.
     No parsing conflict is reported.
<li> If the precedences are the same and the shift token is
     left-associative, then resolve in favor of the reduce.
     No parsing conflict is reported.
<li> Otherwise, resolve the conflict by doing the shift, and
     report a parsing conflict.
</ul>
Reduce-reduce conflicts are resolved this way:
<p>Reduce-reduce conflicts are resolved this way:</p>
<ul>
<li> If either reduce rule
     lacks precedence information, then resolve in favor of the
     rule that appears first in the grammar, and report a parsing
     conflict.
<li> If both rules have precedence and the precedence is different,
     then resolve the dispute in favor of the rule with the highest
     precedence, and do not report a conflict.
<li> Otherwise, resolve the conflict by reducing by the rule that
     appears first in the grammar, and report a parsing conflict.
</ul>

<a id="special"></a>
<h3>Special Directives</h3>
<h3>4.4 Special Directives</h3>

<p>The input grammar to Lemon consists of grammar rules and special
directives.  We've described all the grammar rules, so now we'll
talk about the special directives.</p>

<p>Directives in Lemon can occur in any order.  You can put them before
the grammar rules, or after the grammar rules, or in the midst of the
grammar rules.  It doesn't matter.  The relative order of
directives used to assign precedence to terminals is important, but
other than that, the order of directives in Lemon is arbitrary.</p>

<p>Lemon supports the following special directives:
<p>Lemon supports the following special directives:</p>
<ul>
<li><tt><a href='#pcode'>%code</a></tt>
<li><tt><a href='#default_destructor'>%default_destructor</a></tt>
<li><tt><a href='#default_type'>%default_type</a></tt>
<li><tt><a href='#destructor'>%destructor</a></tt>
<li><tt><a href='#pifdef'>%else</a></tt>
<li><tt><a href='#pifdef'>%endif</a></tt>
<li><tt><a href='#extraarg'>%extra_argument</a></tt>
<li><tt><a href='#pfallback'>%fallback</a></tt>
<li><tt><a href='#pifdef'>%if</a></tt>
<li><tt><a href='#pifdef'>%ifdef</a></tt>
<li><tt><a href='#pifdef'>%ifndef</a></tt>
<li><tt><a href='#pinclude'>%include</a></tt>
<li><tt><a href='#pleft'>%left</a></tt>
<li><tt><a href='#pname'>%name</a></tt>
<li><tt><a href='#pnonassoc'>%nonassoc</a></tt>
<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>
Each of these directives will be described separately in the
<p>Each of these directives will be described separately in the
following sections:</p>

<a name='pcode'></a>
<h4>The <tt>%code</tt> directive</h4>
<a id='pcode'></a>
<h4>4.4.1 The <tt>%code</tt> directive</h4>

<p>The <tt>%code</tt> directive is used to specify additional C code that
is added to the end of the main output file.  This is similar to
the <tt><a href='#pinclude'>%include</a></tt> directive except that
<tt>%include</tt> is inserted at the beginning of the main output file.</p>

<p><tt>%code</tt> is typically used to include some action routines or perhaps
a tokenizer or even the "main()" function
as part of the output file.</p>

<p>There can be multiple <tt>%code</tt> directives.  The arguments of
all <tt>%code</tt> directives are concatenated.</p>

<a name='default_destructor'></a>
<h4>The <tt>%default_destructor</tt> directive</h4>
<a id='default_destructor'></a>
<h4>4.4.2 The <tt>%default_destructor</tt> directive</h4>

<p>The <tt>%default_destructor</tt> directive specifies a destructor to
use for non-terminals that do not have their own destructor
specified by a separate <tt>%destructor</tt> directive.  See the documentation
on the <tt><a name='#destructor'>%destructor</a></tt> directive below for
on the <tt><a href='#destructor'>%destructor</a></tt> directive below for
additional information.</p>

<p>In some grammars, many different non-terminal symbols have the
same data type and hence the same destructor.  This directive is
a convenient way to specify the same destructor for all those
non-terminals using a single statement.</p>

<a name='default_type'></a>
<h4>The <tt>%default_type</tt> directive</h4>
<a id='default_type'></a>
<h4>4.4.3 The <tt>%default_type</tt> directive</h4>

<p>The <tt>%default_type</tt> directive specifies the data type of non-terminal
symbols that do not have their own data type defined using a separate
<tt><a href='#ptype'>%type</a></tt> directive.</p>

<a name='destructor'></a>
<h4>The <tt>%destructor</tt> directive</h4>
<a id='destructor'></a>
<h4>4.4.4 The <tt>%destructor</tt> directive</h4>

<p>The <tt>%destructor</tt> directive is used to specify a destructor for
a non-terminal symbol.
(See also the <tt><a href='#token_destructor'>%token_destructor</a></tt>
directive which is used to specify a destructor for terminal symbols.)</p>

<p>A non-terminal's destructor is called to dispose of the
non-terminal's value whenever the non-terminal is popped from
the stack.  This includes all of the following circumstances:
the stack.  This includes all of the following circumstances:</p>
<ul>
<li> When a rule reduces and the value of a non-terminal on
     the right-hand side is not linked to C code.
<li> When the stack is popped during error processing.
<li> When the ParseFree() function runs.
</ul>
The destructor can do whatever it wants with the value of
<p>The destructor can do whatever it wants with the value of
the non-terminal, but its design is to deallocate memory
or other resources held by that non-terminal.</p>

<p>Consider an example:
<p>Consider an example:</p>
<pre>
   %type nt {void*}
   %destructor nt { free($$); }
   nt(A) ::= ID NUM.   { A = malloc( 100 ); }
</pre>
This example is a bit contrived, but it serves to illustrate how
<p>This example is a bit contrived, but it serves to illustrate how
destructors work.  The example shows a non-terminal named
"nt" that holds values of type "void*".  When the rule for
an "nt" reduces, it sets the value of the non-terminal to
space obtained from malloc().  Later, when the nt non-terminal
is popped from the stack, the destructor will fire and call
free() on this malloced space, thus avoiding a memory leak.
(Note that the symbol "$$" in the destructor code is replaced
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
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
900
901

902
903
904
905
906

907
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
935

936
937
938


939
940

941























942
943


944
945
946
947
948
949


950
951
952
953
954
955
956
957

958
959
960
961
962
963
964
965


966
967
968
969
970
971
972

973
974
975
976
977
978
979

980
981
982
983

984
985
986
987
988
989

990
991
992


993
994
995
996
997
998
999

1000
1001
1002

1003
1004

1005
1006
1007
1008
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
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


900
901
902
903
904
905
906
907
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
935

936
937
938
939
940
941
942

943
944
945
946
947
948
949
950
951
952
953


954
955
956
957
958
959
960

961
962

963
964
965

966
967
968
969
970
971
972

973
974
975


976
977
978
979
980
981
982
983
984


985
986
987
988
989
990
991
992
993
994

995
996
997
998

999
1000


1001
1002
1003
1004
1005
1006
1007
1008
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







-
-
+
+

-
+





-
+

-
+








-
+

-
-
+
+

-
-
+
+




-
+

-
+

-
+

-
+


-
+

-
-
+
+















-
+












-
-
+
+

+
-
-
+
+








-
+

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

-
-
+
+












-
+

-
+







-
-
+
+










-
+






-
+










-
-
+
+





-
+

-
+


-
+






-
+


-
-
+
+







-
-
+
+








-
+



-
+

-
-
+
+







-
+



-
+

-
-
+
+






-
-
+
+






-
+



-
+





-
+




-
+



-
+

-
-
+
+







-
+

-
+

-
-
+
+






-
+

-
+

-
-
+
+

-
+

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




-
-
+
+







-
+






-
-
+
+






-
+






-
+



-
+





-
+

-
-
+
+






-
+


-
+

-
+









-
+

-
+











-
-
+
+









-
-
+
+







larger structure, and we don't want to destroy it, which is why
the destructor is not called in this circumstance.</p>

<p>Destructors help avoid memory leaks by automatically freeing
allocated objects when they go out of scope.
To do the same using yacc or bison is much more difficult.</p>

<a name='extraarg'></a>
<h4>The <tt>%extra_argument</tt> directive</h4>
<a id='extraarg'></a>
<h4>4.4.5 The <tt>%extra_argument</tt> directive</h4>

The <tt>%extra_argument</tt> directive instructs Lemon to add a 4th parameter
<p>The <tt>%extra_argument</tt> directive instructs Lemon to add a 4th parameter
to the parameter list of the Parse() function it generates.  Lemon
doesn't do anything itself with this extra argument, but it does
make the argument available to C-code action routines, destructors,
and so forth.  For example, if the grammar file contains:</p>

<p><pre>
<pre>
    %extra_argument { MyStruct *pAbc }
</pre></p>
</pre>

<p>Then the Parse() function generated will have an 4th parameter
of type "MyStruct*" and all action routines will have access to
a variable named "pAbc" that is the value of the 4th parameter
in the most recent call to Parse().</p>

<p>The <tt>%extra_context</tt> directive works the same except that it
is passed in on the ParseAlloc() or ParseInit() routines instead of
on Parse().
on Parse().</p>

<a name='extractx'></a>
<h4>The <tt>%extra_context</tt> directive</h4>
<a id='extractx'></a>
<h4>4.4.6 The <tt>%extra_context</tt> directive</h4>

The <tt>%extra_context</tt> directive instructs Lemon to add a 2th parameter
to the parameter list of the ParseAlloc() and ParseInif() functions.  Lemon
<p>The <tt>%extra_context</tt> directive instructs Lemon to add a 2nd parameter
to the parameter list of the ParseAlloc() and ParseInit() functions.  Lemon
doesn't do anything itself with these extra argument, but it does
store the value make it available to C-code action routines, destructors,
and so forth.  For example, if the grammar file contains:</p>

<p><pre>
<pre>
    %extra_context { MyStruct *pAbc }
</pre></p>
</pre>

<p>Then the ParseAlloc() and ParseInit() functions will have an 2th parameter
<p>Then the ParseAlloc() and ParseInit() functions will have an 2nd parameter
of type "MyStruct*" and all action routines will have access to
a variable named "pAbc" that is the value of that 2th parameter.</p>
a variable named "pAbc" that is the value of that 2nd parameter.</p>

<p>The <tt>%extra_argument</tt> directive works the same except that it
is passed in on the Parse() routine instead of on ParseAlloc()/ParseInit().
is passed in on the Parse() routine instead of on ParseAlloc()/ParseInit().</p>

<a name='pfallback'></a>
<h4>The <tt>%fallback</tt> directive</h4>
<a id='pfallback'></a>
<h4>4.4.7 The <tt>%fallback</tt> directive</h4>

<p>The <tt>%fallback</tt> directive specifies an alternative meaning for one
or more tokens.  The alternative meaning is tried if the original token
would have generated a syntax error.</p>

<p>The <tt>%fallback</tt> directive was added to support robust parsing of SQL
syntax in <a href='https://www.sqlite.org/'>SQLite</a>.
The SQL language contains a large assortment of keywords, each of which
appears as a different token to the language parser.  SQL contains so
many keywords that it can be difficult for programmers to keep up with
them all.  Programmers will, therefore, sometimes mistakenly use an
obscure language keyword for an identifier.  The <tt>%fallback</tt> directive
provides a mechanism to tell the parser:  "If you are unable to parse
this keyword, try treating it as an identifier instead."</p>

<p>The syntax of <tt>%fallback</tt> is as follows:
<p>The syntax of <tt>%fallback</tt> is as follows:</p>

<blockquote>
<tt>%fallback</tt> <i>ID</i> <i>TOKEN...</i> <b>.</b>
</blockquote></p>

<p>In words, the <tt>%fallback</tt> directive is followed by a list of token
names terminated by a period.
The first token name is the fallback token &mdash; the
token to which all the other tokens fall back to.  The second and subsequent
arguments are tokens which fall back to the token identified by the first
argument.</p>

<a name='pifdef'></a>
<h4>The <tt>%ifdef</tt>, <tt>%ifndef</tt>, and <tt>%endif</tt> directives</h4>
<a id='pifdef'></a>
<h4>4.4.8 The <tt>%if</tt> directive and its friends</h4>

<p>The <tt>%if</tt>, <tt>%ifdef</tt>, <tt>%ifndef</tt>, <tt>%else</tt>,
<p>The <tt>%ifdef</tt>, <tt>%ifndef</tt>, and <tt>%endif</tt> directives
are similar to #ifdef, #ifndef, and #endif in the C-preprocessor,
and <tt>%endif</tt> directives
are similar to #if, #ifdef, #ifndef, #else, and #endif in the C-preprocessor,
just not as general.
Each of these directives must begin at the left margin.  No whitespace
is allowed between the "%" and the directive name.</p>

<p>Grammar text in between "<tt>%ifdef MACRO</tt>" and the next nested
"<tt>%endif</tt>" is
ignored unless the "-DMACRO" command-line option is used.  Grammar text
betwen "<tt>%ifndef MACRO</tt>" and the next nested "<tt>%endif</tt>" is
included except when the "-DMACRO" command-line option is used.</p>
included except when the "-DMACRO" command-line option is used.<p>

<p>The text in between "<tt>%if</tt> <i>CONDITIONAL</i>" and its
corresponding <tt>%endif</tt> is included only if <i>CONDITIONAL</i>
is true.  The CONDITION is one or more macro names, optionally connected
using the "||" and "&amp;&amp;" binary operators, the "!" unary operator,
and grouped using balanced parentheses.  Each term is true if the
corresponding macro exists, and false if it does not exist.</p>

<p>An optional "<tt>%else</tt>" directive can occur anywhere in between a 
<tt>%ifdef</tt>, <tt>%ifndef</tt>, or <tt>%if</tt> directive and
its corresponding <tt>%endif</tt>.</p>

<p>Note that the argument to <tt>%ifdef</tt> and <tt>%ifndef</tt> must
be a single preprocessor symbol name, not a general expression.
<p>Note that the argument to <tt>%ifdef</tt> and <tt>%ifndef</tt> is
intended to be a single preprocessor symbol name, not a general expression.
There is no "<tt>%else</tt>" directive.</p>

Use the "<tt>%if</tt>" directive for general expressions.</p>

<a name='pinclude'></a>
<h4>The <tt>%include</tt> directive</h4>
<a id='pinclude'></a>
<h4>4.4.9 The <tt>%include</tt> directive</h4>

<p>The <tt>%include</tt> directive specifies C code that is included at the
top of the generated parser.  You can include any text you want &mdash;
the Lemon parser generator copies it blindly.  If you have multiple
<tt>%include</tt> directives in your grammar file, their values are concatenated
so that all <tt>%include</tt> code ultimately appears near the top of the
generated parser, in the same order as it appeared in the grammar.</p>

<p>The <tt>%include</tt> directive is very handy for getting some extra #include
preprocessor statements at the beginning of the generated parser.
For example:</p>

<p><pre>
<pre>
   %include {#include &lt;unistd.h&gt;}
</pre></p>
</pre>

<p>This might be needed, for example, if some of the C actions in the
grammar call functions that are prototyped in unistd.h.</p>

<p>Use the <tt><a href="#pcode">%code</a></tt> directive to add code to
the end of the generated parser.</p>

<a name='pleft'></a>
<h4>The <tt>%left</tt> directive</h4>
<a id='pleft'></a>
<h4>4.4.10 The <tt>%left</tt> directive</h4>

The <tt>%left</tt> directive is used (along with the
<tt><a href='#pright'>%right</a></tt> and
<tt><a href='#pnonassoc'>%nonassoc</a></tt> directives) to declare
precedences of terminal symbols.
Every terminal symbol whose name appears after
a <tt>%left</tt> directive but before the next period (".") is
given the same left-associative precedence value.  Subsequent
<tt>%left</tt> directives have higher precedence.  For example:</p>

<p><pre>
<pre>
   %left AND.
   %left OR.
   %nonassoc EQ NE GT GE LT LE.
   %left PLUS MINUS.
   %left TIMES DIVIDE MOD.
   %right EXP NOT.
</pre></p>
</pre>

<p>Note the period that terminates each <tt>%left</tt>,
<tt>%right</tt> or <tt>%nonassoc</tt>
directive.</p>

<p>LALR(1) grammars can get into a situation where they require
a large amount of stack space if you make heavy use or right-associative
operators.  For this reason, it is recommended that you use <tt>%left</tt>
rather than <tt>%right</tt> whenever possible.</p>

<a name='pname'></a>
<h4>The <tt>%name</tt> directive</h4>
<a id='pname'></a>
<h4>4.4.11 The <tt>%name</tt> directive</h4>

<p>By default, the functions generated by Lemon all begin with the
five-character string "Parse".  You can change this string to something
different using the <tt>%name</tt> directive.  For instance:</p>

<p><pre>
<pre>
   %name Abcde
</pre></p>
</pre>

<p>Putting this directive in the grammar file will cause Lemon to generate
functions named
functions named</p>
<ul>
<li> AbcdeAlloc(),
<li> AbcdeFree(),
<li> AbcdeTrace(), and
<li> Abcde().
</ul>
The <tt>%name</tt> directive allows you to generate two or more different
</p>The <tt>%name</tt> directive allows you to generate two or more different
parsers and link them all into the same executable.</p>

<a name='pnonassoc'></a>
<h4>The <tt>%nonassoc</tt> directive</h4>
<a id='pnonassoc'></a>
<h4>4.4.12 The <tt>%nonassoc</tt> directive</h4>

<p>This directive is used to assign non-associative precedence to
one or more terminal symbols.  See the section on
<a href='#precrules'>precedence rules</a>
or on the <tt><a href='#pleft'>%left</a></tt> directive
for additional information.</p>

<a name='parse_accept'></a>
<h4>The <tt>%parse_accept</tt> directive</h4>
<a id='parse_accept'></a>
<h4>4.4.13 The <tt>%parse_accept</tt> directive</h4>

<p>The <tt>%parse_accept</tt> directive specifies a block of C code that is
executed whenever the parser accepts its input string.  To "accept"
an input string means that the parser was able to process all tokens
without error.</p>

<p>For example:</p>

<p><pre>
<pre>
   %parse_accept {
      printf("parsing complete!\n");
   }
</pre></p>
</pre>

<a name='parse_failure'></a>
<h4>The <tt>%parse_failure</tt> directive</h4>
<a id='parse_failure'></a>
<h4>4.4.14 The <tt>%parse_failure</tt> directive</h4>

<p>The <tt>%parse_failure</tt> directive specifies a block of C code that
is executed whenever the parser fails complete.  This code is not
executed until the parser has tried and failed to resolve an input
error using is usual error recovery strategy.  The routine is
only invoked when parsing is unable to continue.</p>

<p><pre>
<pre>
   %parse_failure {
     fprintf(stderr,"Giving up.  Parser is hopelessly lost...\n");
   }
</pre></p>
</pre>

<a name='pright'></a>
<h4>The <tt>%right</tt> directive</h4>
<a id='pright'></a>
<h4>4.4.15 The <tt>%right</tt> directive</h4>

<p>This directive is used to assign right-associative precedence to
one or more terminal symbols.  See the section on
<a href='#precrules'>precedence rules</a>
or on the <a href='#pleft'>%left</a> directive for additional information.</p>

<a name='stack_overflow'></a>
<h4>The <tt>%stack_overflow</tt> directive</h4>
<a id='stack_overflow'></a>
<h4>4.4.16 The <tt>%stack_overflow</tt> directive</h4>

<p>The <tt>%stack_overflow</tt> directive specifies a block of C code that
is executed if the parser's internal stack ever overflows.  Typically
this just prints an error message.  After a stack overflow, the parser
will be unable to continue and must be reset.</p>

<p><pre>
<pre>
   %stack_overflow {
     fprintf(stderr,"Giving up.  Parser stack overflow\n");
   }
</pre></p>
</pre>

<p>You can help prevent parser stack overflows by avoiding the use
of right recursion and right-precedence operators in your grammar.
Use left recursion and and left-precedence operators instead to
encourage rules to reduce sooner and keep the stack size down.
For example, do rules like this:
For example, do rules like this:</p>
<pre>
   list ::= list element.      // left-recursion.  Good!
   list ::= .
</pre>
Not like this:
<p>Not like this:</p>
<pre>
   list ::= element list.      // right-recursion.  Bad!
   list ::= .
</pre></p>
</pre>

<a name='stack_size'></a>
<h4>The <tt>%stack_size</tt> directive</h4>
<a id='stack_size'></a>
<h4>4.4.17 The <tt>%stack_size</tt> directive</h4>

<p>If stack overflow is a problem and you can't resolve the trouble
by using left-recursion, then you might want to increase the size
of the parser's stack using this directive.  Put an positive integer
after the <tt>%stack_size</tt> directive and Lemon will generate a parse
with a stack of the requested size.  The default value is 100.</p>

<p><pre>
<pre>
   %stack_size 2000
</pre></p>
</pre>

<a name='start_symbol'></a>
<h4>The <tt>%start_symbol</tt> directive</h4>
<a id='start_symbol'></a>
<h4>4.4.18 The <tt>%start_symbol</tt> directive</h4>

<p>By default, the start symbol for the grammar that Lemon generates
is the first non-terminal that appears in the grammar file.  But you
can choose a different start symbol using the
<tt>%start_symbol</tt> directive.</p>

<p><pre>
<pre>
   %start_symbol  prog
</pre></p>
</pre>

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

<p>See <a href='#error_processing'>Error Processing</a>.</p>
<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 name='token_class'></a>
<h4>The <tt>%token_class</tt> directive</h4>
<a id='token_class'></a>
<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 name='token_destructor'></a>
<h4>The <tt>%token_destructor</tt> directive</h4>
<a id='token_destructor'></a>
<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
<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 name='token_prefix'></a>
<h4>The <tt>%token_prefix</tt> directive</h4>
<a id='token_prefix'></a>
<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>So if the default output of Lemon looked like this:</p>
<pre>
    #define AND              1
    #define MINUS            2
    #define OR               3
    #define PLUS             4
</pre>
You can insert a statement into the grammar like this:
<p>You can insert a statement into the grammar like this:</p>
<pre>
    %token_prefix    TOKEN_
</pre>
to cause Lemon to produce these symbols instead:
<p>to cause Lemon to produce these symbols instead:</p>
<pre>
    #define TOKEN_AND        1
    #define TOKEN_MINUS      2
    #define TOKEN_OR         3
    #define TOKEN_PLUS       4
</pre></p>
</pre>

<a name='token_type'></a><a name='ptype'></a>
<h4>The <tt>%token_type</tt> and <tt>%type</tt> directives</h4>
<a id='token_type'></a><a id='ptype'></a>
<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 by a pointer to some kind of
make the value of a terminal symbol be a pointer to some kind of
token structure.  Like this:</p>

<p><pre>
<pre>
   %token_type    {Token*}
</pre></p>
</pre>

<p>If the data type of terminals is not specified, the default value
is "void*".</p>

<p>Non-terminal symbols can each have their own data types.  Typically
the data type of a non-terminal is a pointer to the root of a parse tree
structure that contains all information about that non-terminal.
For example:</p>

<p><pre>
<pre>
   %type   expr  {Expr*}
</pre></p>
</pre>

<p>Each entry on the parser's stack is actually a union containing
instances of all data types for every non-terminal and terminal symbol.
Lemon will automatically use the correct element of this union depending
on what the corresponding non-terminal or terminal symbol is.  But
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 name='pwildcard'></a>
<h4>The <tt>%wildcard</tt> directive</h4>
<a id='pwildcard'></a>
<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.
The wildcard token is only matched if there are no alternatives.</p>

<a name='error_processing'></a>
<h3>Error Processing</h3>
<a id='errors'></a>
<h2>5.0 Error Processing</h2>

<p>After extensive experimentation over several years, it has been
discovered that the error recovery strategy used by yacc is about
as good as it gets.  And so that is what Lemon uses.</p>

<p>When a Lemon-generated parser encounters a syntax error, it
first invokes the code specified by the <tt>%syntax_error</tt> directive, if
1055
1056
1057
1058
1059
1060
1061
1062




































1063
1064
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








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


<p>If the parser pops its stack until the stack is empty, and it still
is unable to shift the error symbol, then the
<tt><a href='#parse_failure'>%parse_failure</a></tt> routine
is invoked and the parser resets itself to its start state, ready
to begin parsing a new file.  This is what will happen at the very
first syntax error, of course, if there are no instances of the
"error" non-terminal in your grammar.</p>

<a id='history'></a>
<h2>6.0 History of Lemon</h2>

<p>Lemon was originally written by Richard Hipp sometime in the late
1980s on a Sun4 Workstation using K&amp;R C.  
There was a companion LL(1) parser generator program named "Lime", the
source code to which as been lost.</p>

<p>The lemon.c source file was originally many separate files that were
compiled together to generate the "lemon" executable.  Sometime in the
1990s, the individual source code files were combined together into
the current single large "lemon.c" source file.  You can still see traces
of original filenames in the code.</p>

<p>Since 2001, Lemon has been part of the 
<a href="https://sqlite.org/">SQLite project</a> and the source code
to Lemon has been managed as a part of the 
<a href="https://sqlite.org/src">SQLite source tree</a> in the following
files:</p>

<ul>
<li> <a href="https://sqlite.org/src/file/tool/lemon.c">tool/lemon.c</a>
<li> <a href="https://sqlite.org/src/file/tool/lempar.c">tool/lempar.c</a>
<li> <a href="https://sqlite.org/src/file/doc/lemon.html">doc/lemon.html</a>
</ul>

<a id="copyright"></a>
<h2>7.0 Copyright</h2>

<p>All of the source code to Lemon, including the template parser file
"lempar.c" and this documentation file ("lemon.html") are in the public
domain.  You can use the code for any purpose and without attribution.</p>

<p>The code comes with no warranty.  If it breaks, you get to keep both
pieces.</p>

</body>
</html>

Added doc/trusted-schema.md.















































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# The new-security-options branch

## The problem that the [new-security-options](/timeline?r=new-security-options) branch tries to solve

An attacker might modify the schema of an SQLite database by adding
structures that cause code to run when some other application opens and
reads the database.  For example, the attacker might replace a table
definition with a view.  Or the attacker might add triggers to tables
or views, or add new CHECK constraints or generated columns or indexes
with expressions in the index list or in the WHERE clause.  If the
added features invoke SQL functions or virtual tables with side effects,
that might cause harm to the system if run by a high-privilege victim.
Or, the added features might exfiltrate information if the database is
read by a high-privilege victim.

The changes in this branch strive to make it easier for high-privilege
applications to safely read SQLite database files that might have been
maliciously corrupted by an attacker.

## Overview of changes in [new-security-options](/timeline?r=new-security-options)

The basic idea is to tag every SQL function and virtual table with one
of three risk levels:

  1.  Innocuous
  2.  Normal
  3.  Direct-Only

Innocuous functions/vtabs are safe and can be used at any time.
Direct-only elements, in contrast, might have cause side-effects and
should only be used from top-level SQL, not from within triggers or views nor
in elements of the schema such as CHECK constraint, DEFAULT values, 
generated columns, index expressions, or in the WHERE clause of a 
partial index that are potentially under the control of an attacker.
Normal elements behave like Innocuous if TRUSTED\_SCHEMA=on
and behave like direct-only if TRUSTED\_SCHEMA=off.

Application-defined functions and virtual tables go in as Normal unless
the application takes deliberate steps to change the risk level.

For backwards compatibility, the default is TRUSTED\_SCHEMA=on.  Documentation
will be updated to recommend applications turn TRUSTED\_SCHEMA to off.

An innocuous function or virtual table is one that can only read content
from the database file in which it resides, and can only alter the database
in which it resides.  Most SQL functions are innocuous.  For example, there
is no harm in an attacker running the abs() function.

Direct-only elements that have side-effects that go outside the database file
in which it lives, or return information from outside of the database file.
Examples of direct-only elements include:

  1.  The fts3\_tokenizer() function
  2.  The writefile() function
  3.  The readfile() function
  4.  The zipvfs virtual table
  5.  The csv virtual table

We do not want an attacker to be able to add these kinds of things to
the database schema and possibly trick a high-privilege application 
from performing any of these actions.  Therefore, functions and vtabs
with side-effects are marked as Direct-Only.

Legacy applications might add other risky functions or vtabs.  Those will
go in as "Normal" by default.  For optimal security, we want those risky
app-defined functions and vtabs to be direct-only, but making that the
default might break some legacy applications.  Hence, all app-defined
functions and vtabs go in as Normal, but the application can switch them
over to "Direct-Only" behavior using a single pragma.

The restrictions on the use of functions and virtual tables do not apply
to TEMP.  A TEMP VIEW or a TEMP TRIGGER can use any valid SQL function
or virtual table.  The idea is that TEMP views and triggers must be
directly created by the application and are thus under the control of the
application.  TEMP views and triggers cannot be created by an attacker who
corrupts the schema of a persistent database file.  Hence TEMP views and
triggers are safe.

## Specific changes

  1.  New sqlite3\_db\_config() option SQLITE\_DBCONFIG\_TRUSTED\_SCHEMA for
      turning TRUSTED\_SCHEMA on and off.  It defaults to ON.

  2.  Compile-time option -DSQLITE\_TRUSTED\_SCHEMA=0 causes the default
      TRUSTED\_SCHEMA setting to be off.

  3.  New pragma "PRAGMA trusted\_schema=(ON\|OFF);".  This provides access
      to the TRUSTED_SCHEMA setting for application coded using scripting
      languages or other secondary languages where they are unable to make
      calls to sqlite3\_db\_config().

  4.  New options for the "enc" parameter to sqlite3\_create\_function() and
      its kin:
      <ol type="a">
      <li>  _SQLITE\_INNOCUOUS_  &rarr; tags the new functions as Innocuous
      <li>  _SQLITE\_DIRECTONLY_ &rarr; tags the new functions as Direct-Only
      </ol>

  5.  New options to sqlite3\_vtab\_config():
      <ol type="a">
      <li>  _SQLITE\_VTAB\_INNOCUOUS_   &rarr; tags the vtab as Innocuous
      <li>  _SQLITE\_VTAB\_DIRECTONLY_  &rarr; tags the vtab as Direct-Only
      </ol>

  6.  Change many of the functions and virtual tables in the SQLite source
      tree to use one of the tags above.

  7.  Enhanced PRAGMA function\_list and virtual-table "pragma\_function\_list"
      with additional columns.  The columns now are:
      <ul>
      <li> _name_      &rarr;  Name of the function
      <li> _builtin_   &rarr;  1 for built-in functions.  0 otherwise.
      <li> _type_      &rarr;  's'=Scalar, 'a'=Aggregate, 'w'=Window
      <li> _enc_       &rarr;  'utf8', 'utf16le', or 'utf16be'
      <li> _narg_      &rarr;  number of argument
      <li> _flags_     &rarr;  Bitmask of SQLITE\_INNOCUOUS, SQLITE\_DIRECTONLY,
                               SQLITE\_DETERMINISTIC, SQLITE\_SUBTYPE, and
                               SQLITE\_FUNC\_INTERNAL flags.
      </ul>
      <p>The last four columns are new.

  8.  The function\_list PRAGMA now also shows all entries for each function.
      So, for example, if a function can take either 2 or 3 arguments,
      there are separate rows for the 2-argument and 3-argument versions of
      the function.

## Additional Notes

The function_list enhancements allow the application to query the set
of SQL functions that meet various criteria.  For example, to see all
SQL functions that are never allowed to be used in the schema or in
trigger or views:

~~~
    SELECT DISTINCT name FROM pragma_function_list
     WHERE (flags & 0x80000)!=0
     ORDER BY name;
~~~

Doing the same is not possible for virtual tables, as a virtual table
might be Innocuous, Normal, or Direct-Only depending on the arguments
passed into the xConnect method.

Added doc/vdbesort-memory.md.


















































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

20-11-2020

# Memory Allocation In vdbesort.c

Memory allocation is slightly different depending on:

  * whether or not SQLITE_CONFIG_SMALL_MALLOC is set, and
  * whether or not worker threads are enabled.

## SQLITE_CONFIG_SMALL_MALLOC=0

Assuming SQLITE_CONFIG_SMALL_MALLOC is not set, keys passed to the sorter are
added to an in-memory buffer. This buffer is grown using sqlite3Realloc() as
required it reaches the size configured for the main pager cache using "PRAGMA
cache_size". i.e. if the user has executed "PRAGMA main.cache_size = -2048",
then this buffer is allowed to grow up to 2MB in size.

Once the buffer has grown to its threshold, keys are sorted and written to
a temp file. If worker threads are not enabled, this is the only significant
allocation the sorter module makes. After keys are sorted and flushed out to
the temp file, the buffer is reused to accumulate the next batch of keys.

If worker threads are available, then the buffer is passed to a worker thread
to sort and flush once it is full, and a new buffer allocated to allow the
main thread to continue to accumulate keys. Buffers are reused once they
have been flushed, so in this case at most (nWorker+1) buffers are allocated
and used, where nWorker is the number of configured worker threads.

There are no other significant users of heap memory in the sorter module. 
Once sorted buffers of keys have been flushed to disk, they are read back
either by mapping the file (via sqlite3_file.xFetch()) or else read back
in one page at a time.

All buffers are allocated by the main thread. A sorter object is associated
with a single database connection, to which it holds a pointer.

## SQLITE_CONFIG_SMALL_MALLOC=1

This case is similar to the above, except that instead of accumulating
multiple keys in a single large buffer, sqlite3VdbeSorterWrite() stores
keys in a regular heap-memory linked list (one allocation per element).
List elements are freed as they are flushed to disk, either by the main
thread or by a worker thread.

Each time a key is added the sorter (and an allocation made),
sqlite3HeapNearlyFull() is called. If it returns true, the current
list of keys is flushed to a temporary file, even if it has not yet
reached the size threshold.

Added doc/wal-lock.md.

























































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# Wal-Mode Blocking Locks

On some Unix-like systems, SQLite may be configured to use POSIX blocking locks
by:

  * building the library with SQLITE\_ENABLE\_SETLK\_TIMEOUT defined, and 
  * configuring a timeout in ms using the sqlite3\_busy\_timeout() API.

Blocking locks may be advantageous as (a) waiting database clients do not
need to continuously poll the database lock, and (b) using blocking locks
facilitates transfer of OS priority between processes when a high priority
process is blocked by a lower priority one.

Only read/write clients use blocking locks. Clients that have read-only access
to the \*-shm file nevery use blocking locks.

Threads or processes that access a single database at a time never deadlock as
a result of blocking database locks. But it is of course possible for threads
that lock multiple databases simultaneously to do so. In most cases the OS will
detect the deadlock and return an error.

## Wal Recovery

Wal database "recovery" is a process required when the number of connected
database clients changes from zero to one. In this case, a client is 
considered to connect to the database when it first reads data from it.
Before recovery commences, an exclusive WRITER lock is taken. 

Without blocking locks, if two clients attempt recovery simultaneously, one
fails to obtain the WRITER lock and either invokes the busy-handler callback or
returns SQLITE\_BUSY to the user. With blocking locks configured, the second
client blocks on the WRITER lock.

## Database Readers

Usually, read-only are not blocked by any other database clients, so they 
have no need of blocking locks.

If a read-only transaction is being opened on a snapshot, the CHECKPOINTER
lock is required briefly as part of opening the transaction (to check that a
checkpointer is not currently overwriting the snapshot being opened). A
blocking lock is used to obtain the CHECKPOINTER lock in this case. A snapshot
opener may therefore block on and transfer priority to a checkpointer in some
cases.

## Database Writers

A database writer must obtain the exclusive WRITER lock. It uses a blocking
lock to do so if any of the following are true:

  * the transaction is an implicit one consisting of a single DML or DDL
    statement, or
  * the transaction is opened using BEGIN IMMEDIATE or BEGIN EXCLUSIVE, or
  * the first SQL statement executed following the BEGIN command is a DML or
    DDL statement (not a read-only statement like a SELECT).

In other words, in all cases except when an open read-transaction is upgraded
to a write-transaction. In that case a non-blocking lock is used.

## Database Checkpointers

Database checkpointers takes the following locks, in order:

  * The exclusive CHECKPOINTER lock.
  * The exclusive WRITER lock (FULL, RESTART and TRUNCATE only).
  * Exclusive lock on read-mark slots 1-N. These are immediately released after being taken.
  * Exclusive lock on read-mark 0.
  * Exclusive lock on read-mark slots 1-N again. These are immediately released
    after being taken (RESTART and TRUNCATE only).

All of the above use blocking locks.

## Summary

With blocking locks configured, the only cases in which clients should see an
SQLITE\_BUSY error are:

  * if the OS does not grant a blocking lock before the configured timeout
    expires, and
  * when an open read-transaction is upgraded to a write-transaction.

In all other cases the blocking locks implementation should prevent clients
from having to handle SQLITE\_BUSY errors and facilitate appropriate transfer
of priorities between competing clients.

Clients that lock multiple databases simultaneously must be wary of deadlock.


Added doc/wal2.md.



































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

Wal2 Mode Notes
===============

## Activating/Deactivating Wal2 Mode

"Wal2" mode is very similar to "wal" mode. To change a database to wal2 mode,
use the command:

>
     PRAGMA journal_mode = wal2;

It is not possible to change a database directly from "wal" mode to "wal2"
mode. Instead, it must first be changed to rollback mode. So, to change a wal
mode database to wal2 mode, the following two commands may be used:

>
     PRAGMA journal_mode = delete;
     PRAGMA journal_mode = wal2;

A database in wal2 mode may only be accessed by versions of SQLite compiled
from this branch. Attempting to use any other version of SQLite results in an
SQLITE&#95;NOTADB error. A wal2 mode database may be changed back to rollback mode
(making it accessible by all versions of SQLite) using:

>
     PRAGMA journal_mode = delete;

## The Advantage of Wal2 Mode

In legacy wal mode, when a writer writes data to the database, it doesn't
modify the database file directly. Instead, it appends new data to the
"&lt;database>-wal" file. Readers read data from both the original database
file and the "&lt;database>-wal" file. At some point, data is copied from the
"&lt;database>-wal" file into the database file, after which the wal file can
be deleted or overwritten. Copying data from the wal file into the database
file is called a "checkpoint", and may be done explictly (either by "PRAGMA
wal&#95;checkpoint" or sqlite3&#95;wal&#95;checkpoint&#95;v2()), or
automatically (by configuring "PRAGMA wal&#95;autocheckpoint" - this is the
default).

Checkpointers do not block writers, and writers do not block checkpointers.
However, if a writer writes to the database while a checkpoint is ongoing,
then the new data is appended to the end of the wal file. This means that,
even following the checkpoint, the wal file cannot be overwritten or deleted,
and so all subsequent transactions must also be appended to the wal file. The
work of the checkpointer is not wasted - SQLite remembers which parts of the
wal file have already been copied into the db file so that the next checkpoint
does not have to do so again - but it does mean that the wal file may grow
indefinitely if the checkpointer never gets a chance to finish without a
writer appending to the wal file. There are also circumstances in which
long-running readers may prevent a checkpointer from checkpointing the entire
wal file - also causing the wal file to grow indefinitely in a busy system.

Wal2 mode does not have this problem. In wal2 mode, wal files do not grow
indefinitely even if the checkpointer never has a chance to finish
uninterrupted.

In wal2 mode, the system uses two wal files instead of one. The files are named
"&lt;database>-wal" and "&lt;database>-wal2", where "&lt;database>" is of
course the name of the database file. When data is written to the database, the
writer begins by appending the new data to the first wal file. Once the first
wal file has grown large enough, writers switch to appending data to the second
wal file. At this point the first wal file can be checkpointed (after which it
can be overwritten). Then, once the second wal file has grown large enough and
the first wal file has been checkpointed, writers switch back to the first wal
file. And so on.

## Application Programming

From the point of view of the user, the main differences between wal and 
wal2 mode are to do with checkpointing:

  * In wal mode, a checkpoint may be attempted at any time. In wal2 
    mode, the checkpointer has to wait until writers have switched 
    to the "other" wal file before a checkpoint can take place.

  * In wal mode, the wal-hook (callback registered using
    sqlite3&#95;wal&#95;hook()) is invoked after a transaction is committed
    with the total number of pages in the wal file as an argument. In wal2
    mode, the argument is either the total number of uncheckpointed pages in
    both wal files, or - if the "other" wal file is empty or already
    checkpointed - 0.

Clients are recommended to use the same strategies for checkpointing wal2 mode
databases as for wal databases - by registering a wal-hook using
sqlite3&#95;wal&#95;hook() and attempting a checkpoint when the parameter
exceeds a certain threshold.

However, it should be noted that although the wal-hook is invoked after each
transaction is committed to disk and database locks released, it is still
invoked from within the sqlite3&#95;step() call used to execute the "COMMIT"
command. In BEGIN CONCURRENT systems, where the "COMMIT" is often protected by
an application mutex, this may reduce concurrency. In such systems, instead of
executing a checkpoint from within the wal-hook, a thread might defer this
action until after the application mutex has been released.


Changes to ext/async/sqlite3async.c.

1700
1701
1702
1703
1704
1705
1706
1707
1700
1701
1702
1703
1704
1705
1706








-
      break;
  }
  va_end(ap);
  return rc;
}

#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ASYNCIO) */

Changes to ext/async/sqlite3async.h.

216
217
218
219
220
221
222
223
216
217
218
219
220
221
222








-
#define SQLITEASYNC_HALT_NOW   1       /* Halt as soon as possible */
#define SQLITEASYNC_HALT_IDLE  2       /* Halt when write-queue is empty */

#ifdef __cplusplus
}  /* End of the 'extern "C"' block */
#endif
#endif        /* ifndef __SQLITEASYNC_H_ */

Changes to ext/expert/expert1.test.

23
24
25
26
27
28
29

30
31
32
33
34
35
36
37
38
39



40
41
42
43
44
45
46
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







+










+
+
+







source $testdir/tester.tcl
set testprefix expert1

if {[info commands sqlite3_expert_new]==""} {
  finish_test
  return
}


set CLI [test_binary_name sqlite3]
set CMD [test_binary_name sqlite3_expert]

proc squish {txt} {
  regsub -all {[[:space:]]+} $txt { }
}

proc do_setup_rec_test {tn setup sql res} {
  reset_db
  if {[info exists ::set_main_db_name]} {
    dbconfig_maindbname_icecube db
  }
  db eval $setup
  uplevel [list do_rec_test $tn $sql $res]
}

foreach {tn setup} {
  1 {
    if {![file executable $CMD]} { continue }
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
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







+
+
+
+



















-
+








-
+








-
+








-
+








-
+


+






-
+
+








-
+








-
+








-
+







-
+










-
-
+
+







-
-
+
+










-
+








-
+












-
-
+
+












+
-
-
+
+
+










-
+







-
+







-
+














-
+















-
-
+
+








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



















-
+









-
+








-
+






-
+



















-

      $expert destroy

      set tst [subst -nocommands {set {} [squish [join {$result}]]}]
      uplevel [list do_test $tn $tst [string trim [squish $res]]]
    }
  }
  3 {
    if {[info commands sqlite3_expert_new]==""} { continue }
    set ::set_main_db_name 1
  }
  4 {
    if {![file executable $CLI]} { continue }

    proc do_rec_test {tn sql res} {
      set res [squish [string trim $res]]
      set tst [subst -nocommands { 
        squish [string trim [exec $::CLI test.db ".expert" {$sql;}]]
      }]
      uplevel [list do_test $tn $tst $res]
    }
  }
} {

  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=?) 
  CREATE INDEX "t t_idx_00000061" ON "t t"(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<?)
  CREATE INDEX "t t_idx_00000062" ON "t t"(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 TABLE t7 USING INDEX t7_idx_00000062 (b=?)
      SEARCH t7 USING INDEX t7_idx_00000061 (a=?) 
    INDEX 2
      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 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 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 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 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 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 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 SomeObject USING COVERING INDEX SomeObject_idx_00000078 (x=?)
}


do_setup_rec_test $tn.19.0 {
  CREATE TABLE t1("index");
} {
  SELECT * FROM t1 ORDER BY "index";
} {
  CREATE INDEX t1_idx_01a7214e ON t1('index');
  SCAN t1 USING COVERING INDEX t1_idx_01a7214e
}

}

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

  set expert [sqlite3_expert_new db]
  $expert sql $sql
  $expert analyze

  set candidates [squish [string trim [$expert report 0 candidates]]]
  $expert destroy

  uplevel [list do_test $tn [list set {} $candidates] $res]
}


reset_db
do_execsql_test 4.0 {
do_execsql_test 5.0 {
  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;
}
do_candidates_test 4.1 {
do_candidates_test 5.1 {
  SELECT * FROM t1,t2 WHERE (b=? OR a=?) AND (c=? OR d=?)
} {
  CREATE INDEX t1_idx_00000062 ON t1(b); -- stat1: 100 20 
  CREATE INDEX t1_idx_00000061 ON t1(a); -- stat1: 100 50 
  CREATE INDEX t2_idx_00000063 ON t2(c); -- stat1: 100 20 
  CREATE INDEX t2_idx_00000064 ON t2(d); -- stat1: 100 5
}

do_candidates_test 4.2 {
do_candidates_test 5.2 {
  SELECT * FROM t1,t2 WHERE a=? AND b=? AND c=? AND d=?
} {
  CREATE INDEX t1_idx_000123a7 ON t1(a, b); -- stat1: 100 50 17
  CREATE INDEX t2_idx_0001295b ON t2(c, d); -- stat1: 100 20 5
}

do_execsql_test 4.3 {
do_execsql_test 5.3 {
  CREATE INDEX t1_idx_00000061 ON t1(a); -- stat1: 100 50 
  CREATE INDEX t1_idx_00000062 ON t1(b); -- stat1: 100 20 
  CREATE INDEX t1_idx_000123a7 ON t1(a, b); -- stat1: 100 50 16

  CREATE INDEX t2_idx_00000063 ON t2(c); -- stat1: 100 20 
  CREATE INDEX t2_idx_00000064 ON t2(d); -- stat1: 100 5
  CREATE INDEX t2_idx_0001295b ON t2(c, d); -- stat1: 100 20 5

  ANALYZE;
  SELECT * FROM sqlite_stat1 ORDER BY 1, 2;
} {
  t1 t1_idx_00000061 {100 50} 
  t1 t1_idx_00000062 {100 20}
  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/expert/sqlite3expert.c.

10
11
12
13
14
15
16

















17
18
19
20
21
22
23
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







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







**
*************************************************************************
*/
#include "sqlite3expert.h"
#include <assert.h>
#include <string.h>
#include <stdio.h>

#if !defined(SQLITE_AMALGAMATION)
#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
# define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1
#endif
#if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
# define ALWAYS(X)      (1)
# define NEVER(X)       (0)
#elif !defined(NDEBUG)
# define ALWAYS(X)      ((X)?1:(assert(0),0))
# define NEVER(X)       ((X)?(assert(0),1):0)
#else
# define ALWAYS(X)      (X)
# define NEVER(X)       (X)
#endif
#endif /* !defined(SQLITE_AMALGAMATION) */


#ifndef SQLITE_OMIT_VIRTUALTABLE 

typedef sqlite3_int64 i64;
typedef sqlite3_uint64 u64;

typedef struct IdxColumn IdxColumn;
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
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
775
776
777
778
779
780







-
-
+
+



+

+
+
+
+
-
+


+
+
+
+
+


-
+

+
-
+

+

















+
+
+
-
+

-
+




-
+


+
-
+

-
+










-
+

-
+







  sqlite3 *db,                    /* Database connection to read details from */
  const char *zTab,               /* Table name */
  IdxTable **ppOut,               /* OUT: New object (if successful) */
  char **pzErrmsg                 /* OUT: Error message (if not) */
){
  sqlite3_stmt *p1 = 0;
  int nCol = 0;
  int nTab = STRLEN(zTab);
  int nByte = sizeof(IdxTable) + nTab + 1;
  int nTab;
  int nByte;
  IdxTable *pNew = 0;
  int rc, rc2;
  char *pCsr = 0;
  int nPk = 0;

  *ppOut = 0;
  if( zTab==0 ) return SQLITE_ERROR;
  nTab = STRLEN(zTab);
  nByte = sizeof(IdxTable) + nTab + 1;
  rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_info=%Q", zTab);
  rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_xinfo=%Q", zTab);
  while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
    const char *zCol = (const char*)sqlite3_column_text(p1, 1);
    const char *zColSeq = 0;
    if( zCol==0 ){
      rc = SQLITE_ERROR;
      break;
    }
    nByte += 1 + STRLEN(zCol);
    rc = sqlite3_table_column_metadata(
        db, "main", zTab, zCol, 0, &zCol, 0, 0, 0
        db, "main", zTab, zCol, 0, &zColSeq, 0, 0, 0
    );
    if( zColSeq==0 ) zColSeq = "binary";
    nByte += 1 + STRLEN(zCol);
    nByte += 1 + STRLEN(zColSeq);
    nCol++;
    nPk += (sqlite3_column_int(p1, 5)>0);
  }
  rc2 = sqlite3_reset(p1);
  if( rc==SQLITE_OK ) rc = rc2;

  nByte += sizeof(IdxColumn) * nCol;
  if( rc==SQLITE_OK ){
    pNew = idxMalloc(&rc, nByte);
  }
  if( rc==SQLITE_OK ){
    pNew->aCol = (IdxColumn*)&pNew[1];
    pNew->nCol = nCol;
    pCsr = (char*)&pNew->aCol[nCol];
  }

  nCol = 0;
  while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
    const char *zCol = (const char*)sqlite3_column_text(p1, 1);
    const char *zColSeq = 0;
    int nCopy;
    if( zCol==0 ) continue;
    int nCopy = STRLEN(zCol) + 1;
    nCopy = STRLEN(zCol) + 1;
    pNew->aCol[nCol].zName = pCsr;
    pNew->aCol[nCol].iPk = sqlite3_column_int(p1, 5);
    pNew->aCol[nCol].iPk = (sqlite3_column_int(p1, 5)==1 && nPk==1);
    memcpy(pCsr, zCol, nCopy);
    pCsr += nCopy;

    rc = sqlite3_table_column_metadata(
        db, "main", zTab, zCol, 0, &zCol, 0, 0, 0
        db, "main", zTab, zCol, 0, &zColSeq, 0, 0, 0
    );
    if( rc==SQLITE_OK ){
      if( zColSeq==0 ) zColSeq = "binary";
      nCopy = STRLEN(zCol) + 1;
      nCopy = STRLEN(zColSeq) + 1;
      pNew->aCol[nCol].zColl = pCsr;
      memcpy(pCsr, zCol, nCopy);
      memcpy(pCsr, zColSeq, nCopy);
      pCsr += nCopy;
    }

    nCol++;
  }
  idxFinalize(&rc, p1);

  if( rc!=SQLITE_OK ){
    sqlite3_free(pNew);
    pNew = 0;
  }else{
  }else if( ALWAYS(pNew!=0) ){
    pNew->zName = pCsr;
    memcpy(pNew->zName, zTab, nTab+1);
    if( ALWAYS(pNew->zName!=0) ) memcpy(pNew->zName, zTab, nTab+1);
  }

  *ppOut = pNew;
  return rc;
}

/*
783
784
785
786
787
788
789




790
791
792
793
794
795
796
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833







+
+
+
+








/*
** Return true if zId must be quoted in order to use it as an SQL
** identifier, or false otherwise.
*/
static int idxIdentifierRequiresQuotes(const char *zId){
  int i;
  int nId = STRLEN(zId);
  
  if( sqlite3_keyword_check(zId, nId) ) return 1;

  for(i=0; zId[i]; i++){
    if( !(zId[i]=='_')
     && !(zId[i]>='0' && zId[i]<='9')
     && !(zId[i]>='a' && zId[i]<='z')
     && !(zId[i]>='A' && zId[i]<='Z')
    ){
      return 1;
859
860
861
862
863
864
865

866
867
868
869
870
871
872
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910







+








  rc = idxPrintfPrepareStmt(dbm, &pIdxList, 0, "PRAGMA index_list=%Q", zTbl);
  while( rc==SQLITE_OK && sqlite3_step(pIdxList)==SQLITE_ROW ){
    int bMatch = 1;
    IdxConstraint *pT = pTail;
    sqlite3_stmt *pInfo = 0;
    const char *zIdx = (const char*)sqlite3_column_text(pIdxList, 1);
    if( zIdx==0 ) continue;

    /* Zero the IdxConstraint.bFlag values in the pEq list */
    for(pIter=pEq; pIter; pIter=pIter->pLink) pIter->bFlag = 0;

    rc = idxPrintfPrepareStmt(dbm, &pInfo, 0, "PRAGMA index_xInfo=%Q", zIdx);
    while( rc==SQLITE_OK && sqlite3_step(pInfo)==SQLITE_ROW ){
      int iIdx = sqlite3_column_int(pInfo, 0);
903
904
905
906
907
908
909













910
911
912
913
914
915
916
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967







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







    }
  }
  idxFinalize(&rc, pIdxList);

  *pRc = rc;
  return 0;
}

/* Callback for sqlite3_exec() with query with leading count(*) column.
 * The first argument is expected to be an int*, referent to be incremented
 * if that leading column is not exactly '0'.
 */
static int countNonzeros(void* pCount, int nc,
                         char* azResults[], char* azColumns[]){
  (void)azColumns;  /* Suppress unused parameter warning */
  if( nc>0 && (azResults[0][0]!='0' || azResults[0][1]!=0) ){
    *((int *)pCount) += 1;
  }
  return 0;
}

static int idxCreateFromCons(
  sqlite3expert *p,
  IdxScan *pScan,
  IdxConstraint *pEq, 
  IdxConstraint *pTail
){
930
931
932
933
934
935
936

937
938
939
940
941
942
943





























944
945
946
947


948
949
950
951
952
953
954
955



956


957
958
959
960
961
962
963
981
982
983
984
985
986
987
988







989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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







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


-
-
+
+








+
+
+
-
+
+







    for(pCons=pTail; pCons; pCons=pCons->pLink){
      zCols = idxAppendColDefn(&rc, zCols, pTab, pCons);
    }

    if( rc==SQLITE_OK ){
      /* Hash the list of columns to come up with a name for the index */
      const char *zTable = pScan->pTab->zName;
      int quoteTable = idxIdentifierRequiresQuotes(zTable);
      char *zName;                /* Index name */
      int i;
      for(i=0; zCols[i]; i++){
        h += ((h<<3) + zCols[i]);
      }
      zName = sqlite3_mprintf("%s_idx_%08x", zTable, h);
      if( zName==0 ){ 
      char *zName = 0;          /* Index name */
      int collisions = 0;
      do{
        int i;
        char *zFind;
        for(i=0; zCols[i]; i++){
          h += ((h<<3) + zCols[i]);
        }
        sqlite3_free(zName);
        zName = sqlite3_mprintf("%s_idx_%08x", zTable, h);
        if( zName==0 ) break;
        /* Is is unique among table, view and index names? */
        zFmt = "SELECT count(*) FROM sqlite_schema WHERE name=%Q"
          " AND type in ('index','table','view')";
        zFind = sqlite3_mprintf(zFmt, zName);
        i = 0;
        rc = sqlite3_exec(dbm, zFind, countNonzeros, &i, 0);
        assert(rc==SQLITE_OK);
        sqlite3_free(zFind);
        if( i==0 ){
          collisions = 0;
          break;
        }
        ++collisions;
      }while( collisions<50 && zName!=0 );
      if( collisions ){
        /* This return means "Gave up trying to find a unique index name." */
        rc = SQLITE_BUSY_TIMEOUT;
      }else if( zName==0 ){
        rc = SQLITE_NOMEM;
      }else{
        if( idxIdentifierRequiresQuotes(zTable) ){
          zFmt = "CREATE INDEX '%q' ON %Q(%s)";
        if( quoteTable ){
          zFmt = "CREATE INDEX \"%w\" ON \"%w\"(%s)";
        }else{
          zFmt = "CREATE INDEX %s ON %s(%s)";
        }
        zIdx = sqlite3_mprintf(zFmt, zName, zTable, zCols);
        if( !zIdx ){
          rc = SQLITE_NOMEM;
        }else{
          rc = sqlite3_exec(dbm, zIdx, 0, 0, p->pzErrmsg);
          if( rc!=SQLITE_OK ){
            rc = SQLITE_BUSY_TIMEOUT;
          }else{
          idxHashAdd(&rc, &p->hIdx, zName, zIdx);
            idxHashAdd(&rc, &p->hIdx, zName, zIdx);
          }
        }
        sqlite3_free(zName);
        sqlite3_free(zIdx);
      }
    }

    sqlite3_free(zCols);
1101
1102
1103
1104
1105
1106
1107
1108

1109
1110
1111
1112
1113
1114
1115
1179
1180
1181
1182
1183
1184
1185

1186
1187
1188
1189
1190
1191
1192
1193







-
+









/*
** This function is called after candidate indexes have been created. It
** runs all the queries to see which indexes they prefer, and populates
** IdxStatement.zIdx and IdxStatement.zEQP with the results.
*/
int idxFindIndexes(
static int idxFindIndexes(
  sqlite3expert *p,
  char **pzErr                         /* OUT: Error message (sqlite3_malloc) */
){
  IdxStatement *pStmt;
  sqlite3 *dbm = p->dbm;
  int rc = SQLITE_OK;

1124
1125
1126
1127
1128
1129
1130
1131

1132
1133



1134
1135
1136

1137

1138


1139
1140
1141
1142
1143
1144
1145
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







-
+


+
+
+


-
+

+
-
+
+







        "EXPLAIN QUERY PLAN %s", pStmt->zSql
    );
    while( rc==SQLITE_OK && sqlite3_step(pExplain)==SQLITE_ROW ){
      /* int iId = sqlite3_column_int(pExplain, 0); */
      /* int iParent = sqlite3_column_int(pExplain, 1); */
      /* int iNotUsed = sqlite3_column_int(pExplain, 2); */
      const char *zDetail = (const char*)sqlite3_column_text(pExplain, 3);
      int nDetail = STRLEN(zDetail);
      int nDetail;
      int i;

      if( !zDetail ) continue;
      nDetail = STRLEN(zDetail);

      for(i=0; i<nDetail; i++){
        const char *zIdx = 0;
        if( memcmp(&zDetail[i], " USING INDEX ", 13)==0 ){
        if( i+13<nDetail && memcmp(&zDetail[i], " USING INDEX ", 13)==0 ){
          zIdx = &zDetail[i+13];
        }else if( i+22<nDetail 
        }else if( memcmp(&zDetail[i], " USING COVERING INDEX ", 22)==0 ){
            && memcmp(&zDetail[i], " USING COVERING INDEX ", 22)==0 
        ){
          zIdx = &zDetail[i+22];
        }
        if( zIdx ){
          const char *zSql;
          int nIdx = 0;
          while( zIdx[nIdx]!='\0' && (zIdx[nIdx]!=' ' || zIdx[nIdx+1]!='(') ){
            nIdx++;
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
1297
1298
1299
1300
1301
1302
1303

1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322







-
+










+







  char **pzErr
){
  static const char *zInt = UNIQUE_TABLE_NAME;
  static const char *zDrop = "DROP TABLE " UNIQUE_TABLE_NAME;
  IdxTable *pTab = pWrite->pTab;
  const char *zTab = pTab->zName;
  const char *zSql = 
    "SELECT 'CREATE TEMP' || substr(sql, 7) FROM sqlite_master "
    "SELECT 'CREATE TEMP' || substr(sql, 7) FROM sqlite_schema "
    "WHERE tbl_name = %Q AND type IN ('table', 'trigger') "
    "ORDER BY type;";
  sqlite3_stmt *pSelect = 0;
  int rc = SQLITE_OK;
  char *zWrite = 0;

  /* Create the table and its triggers in the temp schema */
  rc = idxPrintfPrepareStmt(p->db, &pSelect, pzErr, zSql, zTab, zTab);
  while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSelect) ){
    const char *zCreate = (const char*)sqlite3_column_text(pSelect, 0);
    if( zCreate==0 ) continue;
    rc = sqlite3_exec(p->dbv, zCreate, 0, 0, pzErr);
  }
  idxFinalize(&rc, pSelect);

  /* Rename the table in the temp schema to zInt */
  if( rc==SQLITE_OK ){
    char *z = sqlite3_mprintf("ALTER TABLE temp.%Q RENAME TO %Q", zTab, zInt);
1314
1315
1316
1317
1318
1319
1320
1321

1322
1323
1324

1325
1326

1327
1328
1329
1330
1331
1332
1333

1334
1335

1336
1337
1338
1339
1340
1341
1342
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







-
+


-
+

-
+







+

-
+








  /* For each table in the main db schema:
  **
  **   1) Add an entry to the p->pTable list, and
  **   2) Create the equivalent virtual table in dbv.
  */
  rc = idxPrepareStmt(p->db, &pSchema, pzErrmsg,
      "SELECT type, name, sql, 1 FROM sqlite_master "
      "SELECT type, name, sql, 1 FROM sqlite_schema "
      "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%%' "
      " UNION ALL "
      "SELECT type, name, sql, 2 FROM sqlite_master "
      "SELECT type, name, sql, 2 FROM sqlite_schema "
      "WHERE type = 'trigger'"
      "  AND tbl_name IN(SELECT name FROM sqlite_master WHERE type = 'view') "
      "  AND tbl_name IN(SELECT name FROM sqlite_schema WHERE type = 'view') "
      "ORDER BY 4, 1"
  );
  while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSchema) ){
    const char *zType = (const char*)sqlite3_column_text(pSchema, 0);
    const char *zName = (const char*)sqlite3_column_text(pSchema, 1);
    const char *zSql = (const char*)sqlite3_column_text(pSchema, 2);

    if( zType==0 || zName==0 ) continue;
    if( zType[0]=='v' || zType[1]=='r' ){
      rc = sqlite3_exec(p->dbv, zSql, 0, 0, pzErrmsg);
      if( zSql ) rc = sqlite3_exec(p->dbv, zSql, 0, 0, pzErrmsg);
    }else{
      IdxTable *pTab;
      rc = idxGetTableInfo(p->db, zName, &pTab, pzErrmsg);
      if( rc==SQLITE_OK ){
        int i;
        char *zInner = 0;
        char *zOuter = 0;
1465
1466
1467
1468
1469
1470
1471

1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483


1484
1485


1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496

1497
1498
1499
1500
1501
1502
1503
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568

1569
1570
1571

1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583

1584
1585
1586
1587
1588
1589
1590
1591







+











-
+
+

-
+
+










-
+







    case SQLITE_FLOAT:
      pSlot->rVal = sqlite3_value_double(argv[1]);
      break;

    case SQLITE_BLOB:
    case SQLITE_TEXT: {
      int nByte = sqlite3_value_bytes(argv[1]);
      const void *pData = 0;
      if( nByte>pSlot->nByte ){
        char *zNew = (char*)sqlite3_realloc(pSlot->z, nByte*2);
        if( zNew==0 ){
          sqlite3_result_error_nomem(pCtx);
          return;
        }
        pSlot->nByte = nByte*2;
        pSlot->z = zNew;
      }
      pSlot->n = nByte;
      if( pSlot->eType==SQLITE_BLOB ){
        memcpy(pSlot->z, sqlite3_value_blob(argv[1]), nByte);
        pData = sqlite3_value_blob(argv[1]);
        if( pData ) memcpy(pSlot->z, pData, nByte);
      }else{
        memcpy(pSlot->z, sqlite3_value_text(argv[1]), nByte);
        pData = sqlite3_value_text(argv[1]);
        memcpy(pSlot->z, pData, nByte);
      }
      break;
    }
  }
}

static int idxLargestIndex(sqlite3 *db, int *pnMax, char **pzErr){
  int rc = SQLITE_OK;
  const char *zMax = 
    "SELECT max(i.seqno) FROM "
    "  sqlite_master AS s, "
    "  sqlite_schema AS s, "
    "  pragma_index_list(s.name) AS l, "
    "  pragma_index_info(l.name) AS i "
    "WHERE s.type = 'table'";
  sqlite3_stmt *pMax = 0;

  *pnMax = 0;
  rc = idxPrepareStmt(db, &pMax, pzErr, zMax);
1642
1643
1644
1645
1646
1647
1648
1649

1650
1651
1652
1653
1654
1655
1656
1730
1731
1732
1733
1734
1735
1736

1737
1738
1739
1740
1741
1742
1743
1744







-
+







  i64 iPrev = -100000;
  sqlite3_stmt *pAllIndex = 0;
  sqlite3_stmt *pIndexXInfo = 0;
  sqlite3_stmt *pWrite = 0;

  const char *zAllIndex =
    "SELECT s.rowid, s.name, l.name FROM "
    "  sqlite_master AS s, "
    "  sqlite_schema AS s, "
    "  pragma_index_list(s.name) AS l "
    "WHERE s.type = 'table'";
  const char *zIndexXInfo = 
    "SELECT name, coll FROM pragma_index_xinfo(?) WHERE key";
  const char *zWrite = "INSERT INTO sqlite_stat1 VALUES(?, ?, ?)";

  /* If iSample==0, no sqlite_stat1 data is required. */
1689
1690
1691
1692
1693
1694
1695

1696
1697
1698
1699
1700
1701
1702
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791







+







    rc = idxPrepareStmt(p->dbm, &pWrite, pzErr, zWrite);
  }

  while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pAllIndex) ){
    i64 iRowid = sqlite3_column_int64(pAllIndex, 0);
    const char *zTab = (const char*)sqlite3_column_text(pAllIndex, 1);
    const char *zIdx = (const char*)sqlite3_column_text(pAllIndex, 2);
    if( zTab==0 || zIdx==0 ) continue;
    if( p->iSample<100 && iPrev!=iRowid ){
      samplectx.target = (double)p->iSample / 100.0;
      samplectx.iTarget = p->iSample;
      samplectx.nRow = 0.0;
      samplectx.nRet = 0.0;
      rc = idxBuildSampleTable(p, zTab);
      if( rc!=SQLITE_OK ) break;
1710
1711
1712
1713
1714
1715
1716

1717
1718
1719
1720
1721






1722
1723

1724
1725
1726
1727
1728
1729
1730
1799
1800
1801
1802
1803
1804
1805
1806





1807
1808
1809
1810
1811
1812
1813

1814
1815
1816
1817
1818
1819
1820
1821







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

-
+







    );
  }

  idxFinalize(&rc, pAllIndex);
  idxFinalize(&rc, pIndexXInfo);
  idxFinalize(&rc, pWrite);

  if( pCtx ){
  for(i=0; i<pCtx->nSlot; i++){
    sqlite3_free(pCtx->aSlot[i].z);
  }
  sqlite3_free(pCtx);

    for(i=0; i<pCtx->nSlot; i++){
      sqlite3_free(pCtx->aSlot[i].z);
    }
    sqlite3_free(pCtx);
  }

  if( rc==SQLITE_OK ){
    rc = sqlite3_exec(p->dbm, "ANALYZE sqlite_master", 0, 0, 0);
    rc = sqlite3_exec(p->dbm, "ANALYZE sqlite_schema", 0, 0, 0);
  }

  sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp."UNIQUE_TABLE_NAME,0,0,0);
  return rc;
}

/*
1753
1754
1755
1756
1757
1758
1759
1760

1761
1762

1763
1764
1765
1766
1767

1768
1769
1770
1771
1772
1773
1774
1844
1845
1846
1847
1848
1849
1850

1851
1852

1853
1854
1855
1856
1857

1858
1859
1860
1861
1862
1863
1864
1865







-
+

-
+




-
+







      sqlite3_db_config(pNew->dbm, SQLITE_DBCONFIG_TRIGGER_EQP, 1, (int*)0);
    }
  }
  

  /* Copy the entire schema of database [db] into [dbm]. */
  if( rc==SQLITE_OK ){
    sqlite3_stmt *pSql;
    sqlite3_stmt *pSql = 0;
    rc = idxPrintfPrepareStmt(pNew->db, &pSql, pzErrmsg, 
        "SELECT sql FROM sqlite_master WHERE name NOT LIKE 'sqlite_%%'"
        "SELECT sql FROM sqlite_schema WHERE name NOT LIKE 'sqlite_%%'"
        " AND sql NOT LIKE 'CREATE VIRTUAL %%'"
    );
    while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
      const char *zSql = (const char*)sqlite3_column_text(pSql, 0);
      rc = sqlite3_exec(pNew->dbm, zSql, 0, 0, pzErrmsg);
      if( zSql ) rc = sqlite3_exec(pNew->dbm, zSql, 0, 0, pzErrmsg);
    }
    idxFinalize(&rc, pSql);
  }

  /* Create the vtab schema */
  if( rc==SQLITE_OK ){
    rc = idxCreateVtabSchema(pNew, pzErrmsg);
1866
1867
1868
1869
1870
1871
1872




1873
1874
1875
1876
1877
1878
1879
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974







+
+
+
+








  /* Do trigger processing to collect any extra IdxScan structures */
  rc = idxProcessTriggers(p, pzErr);

  /* Create candidate indexes within the in-memory database file */
  if( rc==SQLITE_OK ){
    rc = idxCreateCandidates(p);
  }else if ( rc==SQLITE_BUSY_TIMEOUT ){
    if( pzErr )
      *pzErr = sqlite3_mprintf("Cannot find a unique index name to propose.");
    return rc;
  }

  /* Generate the stat1 data */
  if( rc==SQLITE_OK ){
    rc = idxPopulateStat1(p, pzErr);
  }

1946
1947
1948
1949
1950
1951
1952
1953

2041
2042
2043
2044
2045
2046
2047

2048







-
+
    idxWriteFree(p->pWrite);
    idxHashClear(&p->hIdx);
    sqlite3_free(p->zCandidates);
    sqlite3_free(p);
  }
}

#endif /* ifndef SQLITE_OMIT_VIRTUAL_TABLE */
#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */

Changes to ext/expert/sqlite3expert.h.

1
2
3
4
5
6
7
8
9
10
11
12
13
14


15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12


13
14
15
16
17
18
19
20
21












-
-
+
+







/*
** 2017 April 07
**
** 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.
**
*************************************************************************
*/


#if !defined(SQLITEEXPERT_H)
#define SQLITEEXPERT_H 1
#include "sqlite3.h"

typedef struct sqlite3expert sqlite3expert;

/*
** Create a new sqlite3expert object.
**
161
162
163
164
165
166
167
168

161
162
163
164
165
166
167

168







-
+
/*
** Free an (sqlite3expert*) handle and all associated resources. There 
** should be one call to this function for each successful call to 
** sqlite3-expert_new().
*/
void sqlite3_expert_destroy(sqlite3expert*);


#endif  /* !defined(SQLITEEXPERT_H) */

Deleted ext/fts1/README.txt.

1
2


-
-
This folder contains source code to the first full-text search
extension for SQLite.

Deleted ext/fts1/ft_hash.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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




















































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
** 2001 September 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 is the implementation of generic hash-tables used in SQLite.
** We've modified it slightly to serve as a standalone hash table
** implementation for the full-text indexing module.
*/
#include <assert.h>
#include <stdlib.h>
#include <string.h>

#include "ft_hash.h"

void *malloc_and_zero(int n){
  void *p = malloc(n);
  if( p ){
    memset(p, 0, n);
  }
  return p;
}

/* Turn bulk memory into a hash table object by initializing the
** fields of the Hash structure.
**
** "pNew" is a pointer to the hash table that is to be initialized.
** keyClass is one of the constants HASH_INT, HASH_POINTER,
** HASH_BINARY, or HASH_STRING.  The value of keyClass 
** determines what kind of key the hash table will use.  "copyKey" is
** true if the hash table should make its own private copy of keys and
** false if it should just use the supplied pointer.  CopyKey only makes
** sense for HASH_STRING and HASH_BINARY and is ignored
** for other key classes.
*/
void HashInit(Hash *pNew, int keyClass, int copyKey){
  assert( pNew!=0 );
  assert( keyClass>=HASH_STRING && keyClass<=HASH_BINARY );
  pNew->keyClass = keyClass;
#if 0
  if( keyClass==HASH_POINTER || keyClass==HASH_INT ) copyKey = 0;
#endif
  pNew->copyKey = copyKey;
  pNew->first = 0;
  pNew->count = 0;
  pNew->htsize = 0;
  pNew->ht = 0;
  pNew->xMalloc = malloc_and_zero;
  pNew->xFree = free;
}

/* Remove all entries from a hash table.  Reclaim all memory.
** Call this routine to delete a hash table or to reset a hash table
** to the empty state.
*/
void HashClear(Hash *pH){
  HashElem *elem;         /* For looping over all elements of the table */

  assert( pH!=0 );
  elem = pH->first;
  pH->first = 0;
  if( pH->ht ) pH->xFree(pH->ht);
  pH->ht = 0;
  pH->htsize = 0;
  while( elem ){
    HashElem *next_elem = elem->next;
    if( pH->copyKey && elem->pKey ){
      pH->xFree(elem->pKey);
    }
    pH->xFree(elem);
    elem = next_elem;
  }
  pH->count = 0;
}

#if 0 /* NOT USED */
/*
** Hash and comparison functions when the mode is HASH_INT
*/
static int intHash(const void *pKey, int nKey){
  return nKey ^ (nKey<<8) ^ (nKey>>8);
}
static int intCompare(const void *pKey1, int n1, const void *pKey2, int n2){
  return n2 - n1;
}
#endif

#if 0 /* NOT USED */
/*
** Hash and comparison functions when the mode is HASH_POINTER
*/
static int ptrHash(const void *pKey, int nKey){
  uptr x = Addr(pKey);
  return x ^ (x<<8) ^ (x>>8);
}
static int ptrCompare(const void *pKey1, int n1, const void *pKey2, int n2){
  if( pKey1==pKey2 ) return 0;
  if( pKey1<pKey2 ) return -1;
  return 1;
}
#endif

/*
** Hash and comparison functions when the mode is HASH_STRING
*/
static int strHash(const void *pKey, int nKey){
  const char *z = (const char *)pKey;
  int h = 0;
  if( nKey<=0 ) nKey = (int) strlen(z);
  while( nKey > 0  ){
    h = (h<<3) ^ h ^ *z++;
    nKey--;
  }
  return h & 0x7fffffff;
}
static int strCompare(const void *pKey1, int n1, const void *pKey2, int n2){
  if( n1!=n2 ) return 1;
  return strncmp((const char*)pKey1,(const char*)pKey2,n1);
}

/*
** Hash and comparison functions when the mode is HASH_BINARY
*/
static int binHash(const void *pKey, int nKey){
  int h = 0;
  const char *z = (const char *)pKey;
  while( nKey-- > 0 ){
    h = (h<<3) ^ h ^ *(z++);
  }
  return h & 0x7fffffff;
}
static int binCompare(const void *pKey1, int n1, const void *pKey2, int n2){
  if( n1!=n2 ) return 1;
  return memcmp(pKey1,pKey2,n1);
}

/*
** Return a pointer to the appropriate hash function given the key class.
**
** The C syntax in this function definition may be unfamilar to some 
** programmers, so we provide the following additional explanation:
**
** The name of the function is "hashFunction".  The function takes a
** single parameter "keyClass".  The return value of hashFunction()
** is a pointer to another function.  Specifically, the return value
** of hashFunction() is a pointer to a function that takes two parameters
** with types "const void*" and "int" and returns an "int".
*/
static int (*hashFunction(int keyClass))(const void*,int){
#if 0  /* HASH_INT and HASH_POINTER are never used */
  switch( keyClass ){
    case HASH_INT:     return &intHash;
    case HASH_POINTER: return &ptrHash;
    case HASH_STRING:  return &strHash;
    case HASH_BINARY:  return &binHash;;
    default: break;
  }
  return 0;
#else
  if( keyClass==HASH_STRING ){
    return &strHash;
  }else{
    assert( keyClass==HASH_BINARY );
    return &binHash;
  }
#endif
}

/*
** Return a pointer to the appropriate hash function given the key class.
**
** For help in interpreted the obscure C code in the function definition,
** see the header comment on the previous function.
*/
static int (*compareFunction(int keyClass))(const void*,int,const void*,int){
#if 0 /* HASH_INT and HASH_POINTER are never used */
  switch( keyClass ){
    case HASH_INT:     return &intCompare;
    case HASH_POINTER: return &ptrCompare;
    case HASH_STRING:  return &strCompare;
    case HASH_BINARY:  return &binCompare;
    default: break;
  }
  return 0;
#else
  if( keyClass==HASH_STRING ){
    return &strCompare;
  }else{
    assert( keyClass==HASH_BINARY );
    return &binCompare;
  }
#endif
}

/* Link an element into the hash table
*/
static void insertElement(
  Hash *pH,              /* The complete hash table */
  struct _ht *pEntry,    /* The entry into which pNew is inserted */
  HashElem *pNew         /* The element to be inserted */
){
  HashElem *pHead;       /* First element already in pEntry */
  pHead = pEntry->chain;
  if( pHead ){
    pNew->next = pHead;
    pNew->prev = pHead->prev;
    if( pHead->prev ){ pHead->prev->next = pNew; }
    else             { pH->first = pNew; }
    pHead->prev = pNew;
  }else{
    pNew->next = pH->first;
    if( pH->first ){ pH->first->prev = pNew; }
    pNew->prev = 0;
    pH->first = pNew;
  }
  pEntry->count++;
  pEntry->chain = pNew;
}


/* Resize the hash table so that it cantains "new_size" buckets.
** "new_size" must be a power of 2.  The hash table might fail 
** to resize if sqliteMalloc() fails.
*/
static void rehash(Hash *pH, int new_size){
  struct _ht *new_ht;            /* The new hash table */
  HashElem *elem, *next_elem;    /* For looping over existing elements */
  int (*xHash)(const void*,int); /* The hash function */

  assert( (new_size & (new_size-1))==0 );
  new_ht = (struct _ht *)pH->xMalloc( new_size*sizeof(struct _ht) );
  if( new_ht==0 ) return;
  if( pH->ht ) pH->xFree(pH->ht);
  pH->ht = new_ht;
  pH->htsize = new_size;
  xHash = hashFunction(pH->keyClass);
  for(elem=pH->first, pH->first=0; elem; elem = next_elem){
    int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1);
    next_elem = elem->next;
    insertElement(pH, &new_ht[h], elem);
  }
}

/* This function (for internal use only) locates an element in an
** hash table that matches the given key.  The hash for this key has
** already been computed and is passed as the 4th parameter.
*/
static HashElem *findElementGivenHash(
  const Hash *pH,     /* The pH to be searched */
  const void *pKey,   /* The key we are searching for */
  int nKey,
  int h               /* The hash for this key. */
){
  HashElem *elem;                /* Used to loop thru the element list */
  int count;                     /* Number of elements left to test */
  int (*xCompare)(const void*,int,const void*,int);  /* comparison function */

  if( pH->ht ){
    struct _ht *pEntry = &pH->ht[h];
    elem = pEntry->chain;
    count = pEntry->count;
    xCompare = compareFunction(pH->keyClass);
    while( count-- && elem ){
      if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){ 
        return elem;
      }
      elem = elem->next;
    }
  }
  return 0;
}

/* Remove a single entry from the hash table given a pointer to that
** element and a hash on the element's key.
*/
static void removeElementGivenHash(
  Hash *pH,         /* The pH containing "elem" */
  HashElem* elem,   /* The element to be removed from the pH */
  int h             /* Hash value for the element */
){
  struct _ht *pEntry;
  if( elem->prev ){
    elem->prev->next = elem->next; 
  }else{
    pH->first = elem->next;
  }
  if( elem->next ){
    elem->next->prev = elem->prev;
  }
  pEntry = &pH->ht[h];
  if( pEntry->chain==elem ){
    pEntry->chain = elem->next;
  }
  pEntry->count--;
  if( pEntry->count<=0 ){
    pEntry->chain = 0;
  }
  if( pH->copyKey && elem->pKey ){
    pH->xFree(elem->pKey);
  }
  pH->xFree( elem );
  pH->count--;
  if( pH->count<=0 ){
    assert( pH->first==0 );
    assert( pH->count==0 );
    HashClear(pH);
  }
}

/* Attempt to locate an element of the hash table pH with a key
** that matches pKey,nKey.  Return the data for this element if it is
** found, or NULL if there is no match.
*/
void *HashFind(const Hash *pH, const void *pKey, int nKey){
  int h;             /* A hash on key */
  HashElem *elem;    /* The element that matches key */
  int (*xHash)(const void*,int);  /* The hash function */

  if( pH==0 || pH->ht==0 ) return 0;
  xHash = hashFunction(pH->keyClass);
  assert( xHash!=0 );
  h = (*xHash)(pKey,nKey);
  assert( (pH->htsize & (pH->htsize-1))==0 );
  elem = findElementGivenHash(pH,pKey,nKey, h & (pH->htsize-1));
  return elem ? elem->data : 0;
}

/* Insert an element into the hash table pH.  The key is pKey,nKey
** and the data is "data".
**
** If no element exists with a matching key, then a new
** element is created.  A copy of the key is made if the copyKey
** flag is set.  NULL is returned.
**
** If another element already exists with the same key, then the
** new data replaces the old data and the old data is returned.
** The key is not copied in this instance.  If a malloc fails, then
** the new data is returned and the hash table is unchanged.
**
** If the "data" parameter to this function is NULL, then the
** element corresponding to "key" is removed from the hash table.
*/
void *HashInsert(Hash *pH, const void *pKey, int nKey, void *data){
  int hraw;             /* Raw hash value of the key */
  int h;                /* the hash of the key modulo hash table size */
  HashElem *elem;       /* Used to loop thru the element list */
  HashElem *new_elem;   /* New element added to the pH */
  int (*xHash)(const void*,int);  /* The hash function */

  assert( pH!=0 );
  xHash = hashFunction(pH->keyClass);
  assert( xHash!=0 );
  hraw = (*xHash)(pKey, nKey);
  assert( (pH->htsize & (pH->htsize-1))==0 );
  h = hraw & (pH->htsize-1);
  elem = findElementGivenHash(pH,pKey,nKey,h);
  if( elem ){
    void *old_data = elem->data;
    if( data==0 ){
      removeElementGivenHash(pH,elem,h);
    }else{
      elem->data = data;
    }
    return old_data;
  }
  if( data==0 ) return 0;
  new_elem = (HashElem*)pH->xMalloc( sizeof(HashElem) );
  if( new_elem==0 ) return data;
  if( pH->copyKey && pKey!=0 ){
    new_elem->pKey = pH->xMalloc( nKey );
    if( new_elem->pKey==0 ){
      pH->xFree(new_elem);
      return data;
    }
    memcpy((void*)new_elem->pKey, pKey, nKey);
  }else{
    new_elem->pKey = (void*)pKey;
  }
  new_elem->nKey = nKey;
  pH->count++;
  if( pH->htsize==0 ){
    rehash(pH,8);
    if( pH->htsize==0 ){
      pH->count = 0;
      pH->xFree(new_elem);
      return data;
    }
  }
  if( pH->count > pH->htsize ){
    rehash(pH,pH->htsize*2);
  }
  assert( pH->htsize>0 );
  assert( (pH->htsize & (pH->htsize-1))==0 );
  h = hraw & (pH->htsize-1);
  insertElement(pH, &pH->ht[h], new_elem);
  new_elem->data = data;
  return 0;
}

Deleted ext/fts1/ft_hash.h.

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















































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
** 2001 September 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 is the header file for the generic hash-table implementation
** used in SQLite.  We've modified it slightly to serve as a standalone
** hash table implementation for the full-text indexing module.
**
*/
#ifndef _HASH_H_
#define _HASH_H_

/* Forward declarations of structures. */
typedef struct Hash Hash;
typedef struct HashElem HashElem;

/* A complete hash table is an instance of the following structure.
** The internals of this structure are intended to be opaque -- client
** code should not attempt to access or modify the fields of this structure
** directly.  Change this structure only by using the routines below.
** However, many of the "procedures" and "functions" for modifying and
** accessing this structure are really macros, so we can't really make
** this structure opaque.
*/
struct Hash {
  char keyClass;          /* HASH_INT, _POINTER, _STRING, _BINARY */
  char copyKey;           /* True if copy of key made on insert */
  int count;              /* Number of entries in this table */
  HashElem *first;        /* The first element of the array */
  void *(*xMalloc)(int);  /* malloc() function to use */
  void (*xFree)(void *);  /* free() function to use */
  int htsize;             /* Number of buckets in the hash table */
  struct _ht {            /* the hash table */
    int count;               /* Number of entries with this hash */
    HashElem *chain;         /* Pointer to first entry with this hash */
  } *ht;
};

/* Each element in the hash table is an instance of the following 
** structure.  All elements are stored on a single doubly-linked list.
**
** Again, this structure is intended to be opaque, but it can't really
** be opaque because it is used by macros.
*/
struct HashElem {
  HashElem *next, *prev;   /* Next and previous elements in the table */
  void *data;              /* Data associated with this element */
  void *pKey; int nKey;    /* Key associated with this element */
};

/*
** There are 4 different modes of operation for a hash table:
**
**   HASH_INT         nKey is used as the key and pKey is ignored.
**
**   HASH_POINTER     pKey is used as the key and nKey is ignored.
**
**   HASH_STRING      pKey points to a string that is nKey bytes long
**                           (including the null-terminator, if any).  Case
**                           is respected in comparisons.
**
**   HASH_BINARY      pKey points to binary data nKey bytes long. 
**                           memcmp() is used to compare keys.
**
** A copy of the key is made for HASH_STRING and HASH_BINARY
** if the copyKey parameter to HashInit is 1.  
*/
/* #define HASH_INT       1 // NOT USED */
/* #define HASH_POINTER   2 // NOT USED */
#define HASH_STRING    3
#define HASH_BINARY    4

/*
** Access routines.  To delete, insert a NULL pointer.
*/
void HashInit(Hash*, int keytype, int copyKey);
void *HashInsert(Hash*, const void *pKey, int nKey, void *pData);
void *HashFind(const Hash*, const void *pKey, int nKey);
void HashClear(Hash*);

/*
** Macros for looping over all elements of a hash table.  The idiom is
** like this:
**
**   Hash h;
**   HashElem *p;
**   ...
**   for(p=HashFirst(&h); p; p=HashNext(p)){
**     SomeStructure *pData = HashData(p);
**     // do something with pData
**   }
*/
#define HashFirst(H)  ((H)->first)
#define HashNext(E)   ((E)->next)
#define HashData(E)   ((E)->data)
#define HashKey(E)    ((E)->pKey)
#define HashKeysize(E) ((E)->nKey)

/*
** Number of entries in a hash table
*/
#define HashCount(H)  ((H)->count)

#endif /* _HASH_H_ */

Deleted ext/fts1/fts1.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
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
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
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
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
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
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
1984
1985
1986
1987
1988
1989
1990
1991
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
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
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
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
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
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
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
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
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
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
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
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348




















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/* fts1 has a design flaw which can lead to database corruption (see
** below).  It is recommended not to use it any longer, instead use
** fts3 (or higher).  If you believe that your use of fts1 is safe,
** add -DSQLITE_ENABLE_BROKEN_FTS1=1 to your CFLAGS.
*/
#if (!defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS1)) \
        && !defined(SQLITE_ENABLE_BROKEN_FTS1)
#error fts1 has a design flaw and has been deprecated.
#endif
/* The flaw is that fts1 uses the content table's unaliased rowid as
** the unique docid.  fts1 embeds the rowid in the index it builds,
** and expects the rowid to not change.  The SQLite VACUUM operation
** will renumber such rowids, thereby breaking fts1.  If you are using
** fts1 in a system which has disabled VACUUM, then you can continue
** to use it safely.  Note that PRAGMA auto_vacuum does NOT disable
** VACUUM, though systems using auto_vacuum are unlikely to invoke
** VACUUM.
**
** fts1 should be safe even across VACUUM if you only insert documents
** and never delete.
*/

/* The author disclaims copyright to this source code.
 *
 * This is an SQLite module implementing full-text search.
 */

/*
** The code in this file is only compiled if:
**
**     * The FTS1 module is being built as an extension
**       (in which case SQLITE_CORE is not defined), or
**
**     * The FTS1 module is being built into the core of
**       SQLite (in which case SQLITE_ENABLE_FTS1 is defined).
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS1)

#if defined(SQLITE_ENABLE_FTS1) && !defined(SQLITE_CORE)
# define SQLITE_CORE 1
#endif

#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

#include "fts1.h"
#include "fts1_hash.h"
#include "fts1_tokenizer.h"
#include "sqlite3.h"
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1


#if 0
# define TRACE(A)  printf A; fflush(stdout)
#else
# define TRACE(A)
#endif

/* utility functions */

typedef struct StringBuffer {
  int len;      /* length, not including null terminator */
  int alloced;  /* Space allocated for s[] */ 
  char *s;      /* Content of the string */
} StringBuffer;

static void initStringBuffer(StringBuffer *sb){
  sb->len = 0;
  sb->alloced = 100;
  sb->s = malloc(100);
  sb->s[0] = '\0';
}

static void nappend(StringBuffer *sb, const char *zFrom, int nFrom){
  if( sb->len + nFrom >= sb->alloced ){
    sb->alloced = sb->len + nFrom + 100;
    sb->s = realloc(sb->s, sb->alloced+1);
    if( sb->s==0 ){
      initStringBuffer(sb);
      return;
    }
  }
  memcpy(sb->s + sb->len, zFrom, nFrom);
  sb->len += nFrom;
  sb->s[sb->len] = 0;
}
static void append(StringBuffer *sb, const char *zFrom){
  nappend(sb, zFrom, strlen(zFrom));
}

/* We encode variable-length integers in little-endian order using seven bits
 * per byte as follows:
**
** KEY:
**         A = 0xxxxxxx    7 bits of data and one flag bit
**         B = 1xxxxxxx    7 bits of data and one flag bit
**
**  7 bits - A
** 14 bits - BA
** 21 bits - BBA
** and so on.
*/

/* We may need up to VARINT_MAX bytes to store an encoded 64-bit integer. */
#define VARINT_MAX 10

/* Write a 64-bit variable-length integer to memory starting at p[0].
 * The length of data written will be between 1 and VARINT_MAX bytes.
 * The number of bytes written is returned. */
static int putVarint(char *p, sqlite_int64 v){
  unsigned char *q = (unsigned char *) p;
  sqlite_uint64 vu = v;
  do{
    *q++ = (unsigned char) ((vu & 0x7f) | 0x80);
    vu >>= 7;
  }while( vu!=0 );
  q[-1] &= 0x7f;  /* turn off high bit in final byte */
  assert( q - (unsigned char *)p <= VARINT_MAX );
  return (int) (q - (unsigned char *)p);
}

/* Read a 64-bit variable-length integer from memory starting at p[0].
 * Return the number of bytes read, or 0 on error.
 * The value is stored in *v. */
static int getVarint(const char *p, sqlite_int64 *v){
  const unsigned char *q = (const unsigned char *) p;
  sqlite_uint64 x = 0, y = 1;
  while( (*q & 0x80) == 0x80 ){
    x += y * (*q++ & 0x7f);
    y <<= 7;
    if( q - (unsigned char *)p >= VARINT_MAX ){  /* bad data */
      assert( 0 );
      return 0;
    }
  }
  x += y * (*q++);
  *v = (sqlite_int64) x;
  return (int) (q - (unsigned char *)p);
}

static int getVarint32(const char *p, int *pi){
 sqlite_int64 i;
 int ret = getVarint(p, &i);
 *pi = (int) i;
 assert( *pi==i );
 return ret;
}

/*** Document lists ***
 *
 * A document list holds a sorted list of varint-encoded document IDs.
 *
 * A doclist with type DL_POSITIONS_OFFSETS is stored like this:
 *
 * array {
 *   varint docid;
 *   array {
 *     varint position;     (delta from previous position plus POS_BASE)
 *     varint startOffset;  (delta from previous startOffset)
 *     varint endOffset;    (delta from startOffset)
 *   }
 * }
 *
 * Here, array { X } means zero or more occurrences of X, adjacent in memory.
 *
 * A position list may hold positions for text in multiple columns.  A position
 * POS_COLUMN is followed by a varint containing the index of the column for
 * following positions in the list.  Any positions appearing before any
 * occurrences of POS_COLUMN are for column 0.
 *
 * A doclist with type DL_POSITIONS is like the above, but holds only docids
 * and positions without offset information.
 *
 * A doclist with type DL_DOCIDS is like the above, but holds only docids
 * without positions or offset information.
 *
 * On disk, every document list has positions and offsets, so we don't bother
 * to serialize a doclist's type.
 * 
 * We don't yet delta-encode document IDs; doing so will probably be a
 * modest win.
 *
 * NOTE(shess) I've thought of a slightly (1%) better offset encoding.
 * After the first offset, estimate the next offset by using the
 * current token position and the previous token position and offset,
 * offset to handle some variance.  So the estimate would be
 * (iPosition*w->iStartOffset/w->iPosition-64), which is delta-encoded
 * as normal.  Offsets more than 64 chars from the estimate are
 * encoded as the delta to the previous start offset + 128.  An
 * additional tiny increment can be gained by using the end offset of
 * the previous token to make the estimate a tiny bit more precise.
*/

/* It is not safe to call isspace(), tolower(), or isalnum() on
** hi-bit-set characters.  This is the same solution used in the
** tokenizer.
*/
/* TODO(shess) The snippet-generation code should be using the
** tokenizer-generated tokens rather than doing its own local
** tokenization.
*/
/* TODO(shess) Is __isascii() a portable version of (c&0x80)==0? */
static int safe_isspace(char c){
  return (c&0x80)==0 ? isspace((unsigned char)c) : 0;
}
static int safe_tolower(char c){
  return (c&0x80)==0 ? tolower((unsigned char)c) : c;
}
static int safe_isalnum(char c){
  return (c&0x80)==0 ? isalnum((unsigned char)c) : 0;
}

typedef enum DocListType {
  DL_DOCIDS,              /* docids only */
  DL_POSITIONS,           /* docids + positions */
  DL_POSITIONS_OFFSETS    /* docids + positions + offsets */
} DocListType;

/*
** By default, only positions and not offsets are stored in the doclists.
** To change this so that offsets are stored too, compile with
**
**          -DDL_DEFAULT=DL_POSITIONS_OFFSETS
**
*/
#ifndef DL_DEFAULT
# define DL_DEFAULT DL_POSITIONS
#endif

typedef struct DocList {
  char *pData;
  int nData;
  DocListType iType;
  int iLastColumn;    /* the last column written */
  int iLastPos;       /* the last position written */
  int iLastOffset;    /* the last start offset written */
} DocList;

enum {
  POS_END = 0,        /* end of this position list */
  POS_COLUMN,         /* followed by new column number */
  POS_BASE
};

/* Initialize a new DocList to hold the given data. */
static void docListInit(DocList *d, DocListType iType,
                        const char *pData, int nData){
  d->nData = nData;
  if( nData>0 ){
    d->pData = malloc(nData);
    memcpy(d->pData, pData, nData);
  } else {
    d->pData = NULL;
  }
  d->iType = iType;
  d->iLastColumn = 0;
  d->iLastPos = d->iLastOffset = 0;
}

/* Create a new dynamically-allocated DocList. */
static DocList *docListNew(DocListType iType){
  DocList *d = (DocList *) malloc(sizeof(DocList));
  docListInit(d, iType, 0, 0);
  return d;
}

static void docListDestroy(DocList *d){
  free(d->pData);
#ifndef NDEBUG
  memset(d, 0x55, sizeof(*d));
#endif
}

static void docListDelete(DocList *d){
  docListDestroy(d);
  free(d);
}

static char *docListEnd(DocList *d){
  return d->pData + d->nData;
}

/* Append a varint to a DocList's data. */
static void appendVarint(DocList *d, sqlite_int64 i){
  char c[VARINT_MAX];
  int n = putVarint(c, i);
  d->pData = realloc(d->pData, d->nData + n);
  memcpy(d->pData + d->nData, c, n);
  d->nData += n;
}

static void docListAddDocid(DocList *d, sqlite_int64 iDocid){
  appendVarint(d, iDocid);
  if( d->iType>=DL_POSITIONS ){
    appendVarint(d, POS_END);  /* initially empty position list */
    d->iLastColumn = 0;
    d->iLastPos = d->iLastOffset = 0;
  }
}

/* helper function for docListAddPos and docListAddPosOffset */
static void addPos(DocList *d, int iColumn, int iPos){
  assert( d->nData>0 );
  --d->nData;  /* remove previous terminator */
  if( iColumn!=d->iLastColumn ){
    assert( iColumn>d->iLastColumn );
    appendVarint(d, POS_COLUMN);
    appendVarint(d, iColumn);
    d->iLastColumn = iColumn;
    d->iLastPos = d->iLastOffset = 0;
  }
  assert( iPos>=d->iLastPos );
  appendVarint(d, iPos-d->iLastPos+POS_BASE);
  d->iLastPos = iPos;
}

/* Add a position to the last position list in a doclist. */
static void docListAddPos(DocList *d, int iColumn, int iPos){
  assert( d->iType==DL_POSITIONS );
  addPos(d, iColumn, iPos);
  appendVarint(d, POS_END);  /* add new terminator */
}

/*
** Add a position and starting and ending offsets to a doclist.
**
** If the doclist is setup to handle only positions, then insert
** the position only and ignore the offsets.
*/
static void docListAddPosOffset(
  DocList *d,             /* Doclist under construction */
  int iColumn,            /* Column the inserted term is part of */
  int iPos,               /* Position of the inserted term */
  int iStartOffset,       /* Starting offset of inserted term */
  int iEndOffset          /* Ending offset of inserted term */
){
  assert( d->iType>=DL_POSITIONS );
  addPos(d, iColumn, iPos);
  if( d->iType==DL_POSITIONS_OFFSETS ){
    assert( iStartOffset>=d->iLastOffset );
    appendVarint(d, iStartOffset-d->iLastOffset);
    d->iLastOffset = iStartOffset;
    assert( iEndOffset>=iStartOffset );
    appendVarint(d, iEndOffset-iStartOffset);
  }
  appendVarint(d, POS_END);  /* add new terminator */
}

/*
** A DocListReader object is a cursor into a doclist.  Initialize
** the cursor to the beginning of the doclist by calling readerInit().
** Then use routines
**
**      peekDocid()
**      readDocid()
**      readPosition()
**      skipPositionList()
**      and so forth...
**
** to read information out of the doclist.  When we reach the end
** of the doclist, atEnd() returns TRUE.
*/
typedef struct DocListReader {
  DocList *pDoclist;  /* The document list we are stepping through */
  char *p;            /* Pointer to next unread byte in the doclist */
  int iLastColumn;
  int iLastPos;  /* the last position read, or -1 when not in a position list */
} DocListReader;

/*
** Initialize the DocListReader r to point to the beginning of pDoclist.
*/
static void readerInit(DocListReader *r, DocList *pDoclist){
  r->pDoclist = pDoclist;
  if( pDoclist!=NULL ){
    r->p = pDoclist->pData;
  }
  r->iLastColumn = -1;
  r->iLastPos = -1;
}

/*
** Return TRUE if we have reached then end of pReader and there is
** nothing else left to read.
*/
static int atEnd(DocListReader *pReader){
  return pReader->pDoclist==0 || (pReader->p >= docListEnd(pReader->pDoclist));
}

/* Peek at the next docid without advancing the read pointer. 
*/
static sqlite_int64 peekDocid(DocListReader *pReader){
  sqlite_int64 ret;
  assert( !atEnd(pReader) );
  assert( pReader->iLastPos==-1 );
  getVarint(pReader->p, &ret);
  return ret;
}

/* Read the next docid.   See also nextDocid().
*/
static sqlite_int64 readDocid(DocListReader *pReader){
  sqlite_int64 ret;
  assert( !atEnd(pReader) );
  assert( pReader->iLastPos==-1 );
  pReader->p += getVarint(pReader->p, &ret);
  if( pReader->pDoclist->iType>=DL_POSITIONS ){
    pReader->iLastColumn = 0;
    pReader->iLastPos = 0;
  }
  return ret;
}

/* Read the next position and column index from a position list.
 * Returns the position, or -1 at the end of the list. */
static int readPosition(DocListReader *pReader, int *iColumn){
  int i;
  int iType = pReader->pDoclist->iType;

  if( pReader->iLastPos==-1 ){
    return -1;
  }
  assert( !atEnd(pReader) );

  if( iType<DL_POSITIONS ){
    return -1;
  }
  pReader->p += getVarint32(pReader->p, &i);
  if( i==POS_END ){
    pReader->iLastColumn = pReader->iLastPos = -1;
    *iColumn = -1;
    return -1;
  }
  if( i==POS_COLUMN ){
    pReader->p += getVarint32(pReader->p, &pReader->iLastColumn);
    pReader->iLastPos = 0;
    pReader->p += getVarint32(pReader->p, &i);
    assert( i>=POS_BASE );
  }
  pReader->iLastPos += ((int) i)-POS_BASE;
  if( iType>=DL_POSITIONS_OFFSETS ){
    /* Skip over offsets, ignoring them for now. */
    int iStart, iEnd;
    pReader->p += getVarint32(pReader->p, &iStart);
    pReader->p += getVarint32(pReader->p, &iEnd);
  }
  *iColumn = pReader->iLastColumn;
  return pReader->iLastPos;
}

/* Skip past the end of a position list. */
static void skipPositionList(DocListReader *pReader){
  DocList *p = pReader->pDoclist;
  if( p && p->iType>=DL_POSITIONS ){
    int iColumn;
    while( readPosition(pReader, &iColumn)!=-1 ){}
  }
}

/* Skip over a docid, including its position list if the doclist has
 * positions. */
static void skipDocument(DocListReader *pReader){
  readDocid(pReader);
  skipPositionList(pReader);
}

/* Skip past all docids which are less than [iDocid].  Returns 1 if a docid
 * matching [iDocid] was found.  */
static int skipToDocid(DocListReader *pReader, sqlite_int64 iDocid){
  sqlite_int64 d = 0;
  while( !atEnd(pReader) && (d=peekDocid(pReader))<iDocid ){
    skipDocument(pReader);
  }
  return !atEnd(pReader) && d==iDocid;
}

/* Return the first document in a document list.
*/
static sqlite_int64 firstDocid(DocList *d){
  DocListReader r;
  readerInit(&r, d);
  return readDocid(&r);
}

#ifdef SQLITE_DEBUG
/*
** This routine is used for debugging purpose only.
**
** Write the content of a doclist to standard output.
*/
static void printDoclist(DocList *p){
  DocListReader r;
  const char *zSep = "";

  readerInit(&r, p);
  while( !atEnd(&r) ){
    sqlite_int64 docid = readDocid(&r);
    if( docid==0 ){
      skipPositionList(&r);
      continue;
    }
    printf("%s%lld", zSep, docid);
    zSep =  ",";
    if( p->iType>=DL_POSITIONS ){
      int iPos, iCol;
      const char *zDiv = "";
      printf("(");
      while( (iPos = readPosition(&r, &iCol))>=0 ){
        printf("%s%d:%d", zDiv, iCol, iPos);
        zDiv = ":";
      }
      printf(")");
    }
  }
  printf("\n");
  fflush(stdout);
}
#endif /* SQLITE_DEBUG */

/* Trim the given doclist to contain only positions in column
 * [iRestrictColumn]. */
static void docListRestrictColumn(DocList *in, int iRestrictColumn){
  DocListReader r;
  DocList out;

  assert( in->iType>=DL_POSITIONS );
  readerInit(&r, in);
  docListInit(&out, DL_POSITIONS, NULL, 0);

  while( !atEnd(&r) ){
    sqlite_int64 iDocid = readDocid(&r);
    int iPos, iColumn;

    docListAddDocid(&out, iDocid);
    while( (iPos = readPosition(&r, &iColumn)) != -1 ){
      if( iColumn==iRestrictColumn ){
        docListAddPos(&out, iColumn, iPos);
      }
    }
  }

  docListDestroy(in);
  *in = out;
}

/* Trim the given doclist by discarding any docids without any remaining
 * positions. */
static void docListDiscardEmpty(DocList *in) {
  DocListReader r;
  DocList out;

  /* TODO: It would be nice to implement this operation in place; that
   * could save a significant amount of memory in queries with long doclists. */
  assert( in->iType>=DL_POSITIONS );
  readerInit(&r, in);
  docListInit(&out, DL_POSITIONS, NULL, 0);

  while( !atEnd(&r) ){
    sqlite_int64 iDocid = readDocid(&r);
    int match = 0;
    int iPos, iColumn;
    while( (iPos = readPosition(&r, &iColumn)) != -1 ){
      if( !match ){
        docListAddDocid(&out, iDocid);
        match = 1;
      }
      docListAddPos(&out, iColumn, iPos);
    }
  }

  docListDestroy(in);
  *in = out;
}

/* Helper function for docListUpdate() and docListAccumulate().
** Splices a doclist element into the doclist represented by r,
** leaving r pointing after the newly spliced element.
*/
static void docListSpliceElement(DocListReader *r, sqlite_int64 iDocid,
                                 const char *pSource, int nSource){
  DocList *d = r->pDoclist;
  char *pTarget;
  int nTarget, found;

  found = skipToDocid(r, iDocid);

  /* Describe slice in d to place pSource/nSource. */
  pTarget = r->p;
  if( found ){
    skipDocument(r);
    nTarget = r->p-pTarget;
  }else{
    nTarget = 0;
  }

  /* The sense of the following is that there are three possibilities.
  ** If nTarget==nSource, we should not move any memory nor realloc.
  ** If nTarget>nSource, trim target and realloc.
  ** If nTarget<nSource, realloc then expand target.
  */
  if( nTarget>nSource ){
    memmove(pTarget+nSource, pTarget+nTarget, docListEnd(d)-(pTarget+nTarget));
  }
  if( nTarget!=nSource ){
    int iDoclist = pTarget-d->pData;
    d->pData = realloc(d->pData, d->nData+nSource-nTarget);
    pTarget = d->pData+iDoclist;
  }
  if( nTarget<nSource ){
    memmove(pTarget+nSource, pTarget+nTarget, docListEnd(d)-(pTarget+nTarget));
  }

  memcpy(pTarget, pSource, nSource);
  d->nData += nSource-nTarget;
  r->p = pTarget+nSource;
}

/* Insert/update pUpdate into the doclist. */
static void docListUpdate(DocList *d, DocList *pUpdate){
  DocListReader reader;

  assert( d!=NULL && pUpdate!=NULL );
  assert( d->iType==pUpdate->iType);

  readerInit(&reader, d);
  docListSpliceElement(&reader, firstDocid(pUpdate),
                       pUpdate->pData, pUpdate->nData);
}

/* Propagate elements from pUpdate to pAcc, overwriting elements with
** matching docids.
*/
static void docListAccumulate(DocList *pAcc, DocList *pUpdate){
  DocListReader accReader, updateReader;

  /* Handle edge cases where one doclist is empty. */
  assert( pAcc!=NULL );
  if( pUpdate==NULL || pUpdate->nData==0 ) return;
  if( pAcc->nData==0 ){
    pAcc->pData = malloc(pUpdate->nData);
    memcpy(pAcc->pData, pUpdate->pData, pUpdate->nData);
    pAcc->nData = pUpdate->nData;
    return;
  }

  readerInit(&accReader, pAcc);
  readerInit(&updateReader, pUpdate);

  while( !atEnd(&updateReader) ){
    char *pSource = updateReader.p;
    sqlite_int64 iDocid = readDocid(&updateReader);
    skipPositionList(&updateReader);
    docListSpliceElement(&accReader, iDocid, pSource, updateReader.p-pSource);
  }
}

/*
** Read the next docid off of pIn.  Return 0 if we reach the end.
*
* TODO: This assumes that docids are never 0, but they may actually be 0 since
* users can choose docids when inserting into a full-text table.  Fix this.
*/
static sqlite_int64 nextDocid(DocListReader *pIn){
  skipPositionList(pIn);
  return atEnd(pIn) ? 0 : readDocid(pIn);
}

/*
** pLeft and pRight are two DocListReaders that are pointing to
** positions lists of the same document: iDocid. 
**
** If there are no instances in pLeft or pRight where the position
** of pLeft is one less than the position of pRight, then this
** routine adds nothing to pOut.
**
** If there are one or more instances where positions from pLeft
** are exactly one less than positions from pRight, then add a new
** document record to pOut.  If pOut wants to hold positions, then
** include the positions from pRight that are one more than a
** position in pLeft.  In other words:  pRight.iPos==pLeft.iPos+1.
**
** pLeft and pRight are left pointing at the next document record.
*/
static void mergePosList(
  DocListReader *pLeft,    /* Left position list */
  DocListReader *pRight,   /* Right position list */
  sqlite_int64 iDocid,     /* The docid from pLeft and pRight */
  DocList *pOut            /* Write the merged document record here */
){
  int iLeftCol, iLeftPos = readPosition(pLeft, &iLeftCol);
  int iRightCol, iRightPos = readPosition(pRight, &iRightCol);
  int match = 0;

  /* Loop until we've reached the end of both position lists. */
  while( iLeftPos!=-1 && iRightPos!=-1 ){
    if( iLeftCol==iRightCol && iLeftPos+1==iRightPos ){
      if( !match ){
        docListAddDocid(pOut, iDocid);
        match = 1;
      }
      if( pOut->iType>=DL_POSITIONS ){
        docListAddPos(pOut, iRightCol, iRightPos);
      }
      iLeftPos = readPosition(pLeft, &iLeftCol);
      iRightPos = readPosition(pRight, &iRightCol);
    }else if( iRightCol<iLeftCol ||
              (iRightCol==iLeftCol && iRightPos<iLeftPos+1) ){
      iRightPos = readPosition(pRight, &iRightCol);
    }else{
      iLeftPos = readPosition(pLeft, &iLeftCol);
    }
  }
  if( iLeftPos>=0 ) skipPositionList(pLeft);
  if( iRightPos>=0 ) skipPositionList(pRight);
}

/* We have two doclists:  pLeft and pRight.
** Write the phrase intersection of these two doclists into pOut.
**
** A phrase intersection means that two documents only match
** if pLeft.iPos+1==pRight.iPos.
**
** The output pOut may or may not contain positions.  If pOut
** does contain positions, they are the positions of pRight.
*/
static void docListPhraseMerge(
  DocList *pLeft,    /* Doclist resulting from the words on the left */
  DocList *pRight,   /* Doclist for the next word to the right */
  DocList *pOut      /* Write the combined doclist here */
){
  DocListReader left, right;
  sqlite_int64 docidLeft, docidRight;

  readerInit(&left, pLeft);
  readerInit(&right, pRight);
  docidLeft = nextDocid(&left);
  docidRight = nextDocid(&right);

  while( docidLeft>0 && docidRight>0 ){
    if( docidLeft<docidRight ){
      docidLeft = nextDocid(&left);
    }else if( docidRight<docidLeft ){
      docidRight = nextDocid(&right);
    }else{
      mergePosList(&left, &right, docidLeft, pOut);
      docidLeft = nextDocid(&left);
      docidRight = nextDocid(&right);
    }
  }
}

/* We have two doclists:  pLeft and pRight.
** Write the intersection of these two doclists into pOut.
** Only docids are matched.  Position information is ignored.
**
** The output pOut never holds positions.
*/
static void docListAndMerge(
  DocList *pLeft,    /* Doclist resulting from the words on the left */
  DocList *pRight,   /* Doclist for the next word to the right */
  DocList *pOut      /* Write the combined doclist here */
){
  DocListReader left, right;
  sqlite_int64 docidLeft, docidRight;

  assert( pOut->iType<DL_POSITIONS );

  readerInit(&left, pLeft);
  readerInit(&right, pRight);
  docidLeft = nextDocid(&left);
  docidRight = nextDocid(&right);

  while( docidLeft>0 && docidRight>0 ){
    if( docidLeft<docidRight ){
      docidLeft = nextDocid(&left);
    }else if( docidRight<docidLeft ){
      docidRight = nextDocid(&right);
    }else{
      docListAddDocid(pOut, docidLeft);
      docidLeft = nextDocid(&left);
      docidRight = nextDocid(&right);
    }
  }
}

/* We have two doclists:  pLeft and pRight.
** Write the union of these two doclists into pOut.
** Only docids are matched.  Position information is ignored.
**
** The output pOut never holds positions.
*/
static void docListOrMerge(
  DocList *pLeft,    /* Doclist resulting from the words on the left */
  DocList *pRight,   /* Doclist for the next word to the right */
  DocList *pOut      /* Write the combined doclist here */
){
  DocListReader left, right;
  sqlite_int64 docidLeft, docidRight, priorLeft;

  readerInit(&left, pLeft);
  readerInit(&right, pRight);
  docidLeft = nextDocid(&left);
  docidRight = nextDocid(&right);

  while( docidLeft>0 && docidRight>0 ){
    if( docidLeft<=docidRight ){
      docListAddDocid(pOut, docidLeft);
    }else{
      docListAddDocid(pOut, docidRight);
    }
    priorLeft = docidLeft;
    if( docidLeft<=docidRight ){
      docidLeft = nextDocid(&left);
    }
    if( docidRight>0 && docidRight<=priorLeft ){
      docidRight = nextDocid(&right);
    }
  }
  while( docidLeft>0 ){
    docListAddDocid(pOut, docidLeft);
    docidLeft = nextDocid(&left);
  }
  while( docidRight>0 ){
    docListAddDocid(pOut, docidRight);
    docidRight = nextDocid(&right);
  }
}

/* We have two doclists:  pLeft and pRight.
** Write into pOut all documents that occur in pLeft but not
** in pRight.
**
** Only docids are matched.  Position information is ignored.
**
** The output pOut never holds positions.
*/
static void docListExceptMerge(
  DocList *pLeft,    /* Doclist resulting from the words on the left */
  DocList *pRight,   /* Doclist for the next word to the right */
  DocList *pOut      /* Write the combined doclist here */
){
  DocListReader left, right;
  sqlite_int64 docidLeft, docidRight, priorLeft;

  readerInit(&left, pLeft);
  readerInit(&right, pRight);
  docidLeft = nextDocid(&left);
  docidRight = nextDocid(&right);

  while( docidLeft>0 && docidRight>0 ){
    priorLeft = docidLeft;
    if( docidLeft<docidRight ){
      docListAddDocid(pOut, docidLeft);
    }
    if( docidLeft<=docidRight ){
      docidLeft = nextDocid(&left);
    }
    if( docidRight>0 && docidRight<=priorLeft ){
      docidRight = nextDocid(&right);
    }
  }
  while( docidLeft>0 ){
    docListAddDocid(pOut, docidLeft);
    docidLeft = nextDocid(&left);
  }
}

static char *string_dup_n(const char *s, int n){
  char *str = malloc(n + 1);
  memcpy(str, s, n);
  str[n] = '\0';
  return str;
}

/* Duplicate a string; the caller must free() the returned string.
 * (We don't use strdup() since it is not part of the standard C library and
 * may not be available everywhere.) */
static char *string_dup(const char *s){
  return string_dup_n(s, strlen(s));
}

/* Format a string, replacing each occurrence of the % character with
 * zDb.zName.  This may be more convenient than sqlite_mprintf()
 * when one string is used repeatedly in a format string.
 * The caller must free() the returned string. */
static char *string_format(const char *zFormat,
                           const char *zDb, const char *zName){
  const char *p;
  size_t len = 0;
  size_t nDb = strlen(zDb);
  size_t nName = strlen(zName);
  size_t nFullTableName = nDb+1+nName;
  char *result;
  char *r;

  /* first compute length needed */
  for(p = zFormat ; *p ; ++p){
    len += (*p=='%' ? nFullTableName : 1);
  }
  len += 1;  /* for null terminator */

  r = result = malloc(len);
  for(p = zFormat; *p; ++p){
    if( *p=='%' ){
      memcpy(r, zDb, nDb);
      r += nDb;
      *r++ = '.';
      memcpy(r, zName, nName);
      r += nName;
    } else {
      *r++ = *p;
    }
  }
  *r++ = '\0';
  assert( r == result + len );
  return result;
}

static int sql_exec(sqlite3 *db, const char *zDb, const char *zName,
                    const char *zFormat){
  char *zCommand = string_format(zFormat, zDb, zName);
  int rc;
  TRACE(("FTS1 sql: %s\n", zCommand));
  rc = sqlite3_exec(db, zCommand, NULL, 0, NULL);
  free(zCommand);
  return rc;
}

static int sql_prepare(sqlite3 *db, const char *zDb, const char *zName,
                       sqlite3_stmt **ppStmt, const char *zFormat){
  char *zCommand = string_format(zFormat, zDb, zName);
  int rc;
  TRACE(("FTS1 prepare: %s\n", zCommand));
  rc = sqlite3_prepare(db, zCommand, -1, ppStmt, NULL);
  free(zCommand);
  return rc;
}

/* end utility functions */

/* Forward reference */
typedef struct fulltext_vtab fulltext_vtab;

/* A single term in a query is represented by an instances of
** the following structure.
*/
typedef struct QueryTerm {
  short int nPhrase; /* How many following terms are part of the same phrase */
  short int iPhrase; /* This is the i-th term of a phrase. */
  short int iColumn; /* Column of the index that must match this term */
  signed char isOr;  /* this term is preceded by "OR" */
  signed char isNot; /* this term is preceded by "-" */
  char *pTerm;       /* text of the term.  '\000' terminated.  malloced */
  int nTerm;         /* Number of bytes in pTerm[] */
} QueryTerm;


/* A query string is parsed into a Query structure.
 *
 * We could, in theory, allow query strings to be complicated
 * nested expressions with precedence determined by parentheses.
 * But none of the major search engines do this.  (Perhaps the
 * feeling is that an parenthesized expression is two complex of
 * an idea for the average user to grasp.)  Taking our lead from
 * the major search engines, we will allow queries to be a list
 * of terms (with an implied AND operator) or phrases in double-quotes,
 * with a single optional "-" before each non-phrase term to designate
 * negation and an optional OR connector.
 *
 * OR binds more tightly than the implied AND, which is what the
 * major search engines seem to do.  So, for example:
 * 
 *    [one two OR three]     ==>    one AND (two OR three)
 *    [one OR two three]     ==>    (one OR two) AND three
 *
 * A "-" before a term matches all entries that lack that term.
 * The "-" must occur immediately before the term with in intervening
 * space.  This is how the search engines do it.
 *
 * A NOT term cannot be the right-hand operand of an OR.  If this
 * occurs in the query string, the NOT is ignored:
 *
 *    [one OR -two]          ==>    one OR two
 *
 */
typedef struct Query {
  fulltext_vtab *pFts;  /* The full text index */
  int nTerms;           /* Number of terms in the query */
  QueryTerm *pTerms;    /* Array of terms.  Space obtained from malloc() */
  int nextIsOr;         /* Set the isOr flag on the next inserted term */
  int nextColumn;       /* Next word parsed must be in this column */
  int dfltColumn;       /* The default column */
} Query;


/*
** An instance of the following structure keeps track of generated
** matching-word offset information and snippets.
*/
typedef struct Snippet {
  int nMatch;     /* Total number of matches */
  int nAlloc;     /* Space allocated for aMatch[] */
  struct snippetMatch { /* One entry for each matching term */
    char snStatus;       /* Status flag for use while constructing snippets */
    short int iCol;      /* The column that contains the match */
    short int iTerm;     /* The index in Query.pTerms[] of the matching term */
    short int nByte;     /* Number of bytes in the term */
    int iStart;          /* The offset to the first character of the term */
  } *aMatch;      /* Points to space obtained from malloc */
  char *zOffset;  /* Text rendering of aMatch[] */
  int nOffset;    /* strlen(zOffset) */
  char *zSnippet; /* Snippet text */
  int nSnippet;   /* strlen(zSnippet) */
} Snippet;


typedef enum QueryType {
  QUERY_GENERIC,   /* table scan */
  QUERY_ROWID,     /* lookup by rowid */
  QUERY_FULLTEXT   /* QUERY_FULLTEXT + [i] is a full-text search for column i*/
} QueryType;

/* TODO(shess) CHUNK_MAX controls how much data we allow in segment 0
** before we start aggregating into larger segments.  Lower CHUNK_MAX
** means that for a given input we have more individual segments per
** term, which means more rows in the table and a bigger index (due to
** both more rows and bigger rowids).  But it also reduces the average
** cost of adding new elements to the segment 0 doclist, and it seems
** to reduce the number of pages read and written during inserts.  256
** was chosen by measuring insertion times for a certain input (first
** 10k documents of Enron corpus), though including query performance
** in the decision may argue for a larger value.
*/
#define CHUNK_MAX 256

typedef enum fulltext_statement {
  CONTENT_INSERT_STMT,
  CONTENT_SELECT_STMT,
  CONTENT_UPDATE_STMT,
  CONTENT_DELETE_STMT,

  TERM_SELECT_STMT,
  TERM_SELECT_ALL_STMT,
  TERM_INSERT_STMT,
  TERM_UPDATE_STMT,
  TERM_DELETE_STMT,

  MAX_STMT                     /* Always at end! */
} fulltext_statement;

/* These must exactly match the enum above. */
/* TODO(adam): Is there some risk that a statement (in particular,
** pTermSelectStmt) will be used in two cursors at once, e.g.  if a
** query joins a virtual table to itself?  If so perhaps we should
** move some of these to the cursor object.
*/
static const char *const fulltext_zStatement[MAX_STMT] = {
  /* CONTENT_INSERT */ NULL,  /* generated in contentInsertStatement() */
  /* CONTENT_SELECT */ "select * from %_content where rowid = ?",
  /* CONTENT_UPDATE */ NULL,  /* generated in contentUpdateStatement() */
  /* CONTENT_DELETE */ "delete from %_content where rowid = ?",

  /* TERM_SELECT */
  "select rowid, doclist from %_term where term = ? and segment = ?",
  /* TERM_SELECT_ALL */
  "select doclist from %_term where term = ? order by segment",
  /* TERM_INSERT */
  "insert into %_term (rowid, term, segment, doclist) values (?, ?, ?, ?)",
  /* TERM_UPDATE */ "update %_term set doclist = ? where rowid = ?",
  /* TERM_DELETE */ "delete from %_term where rowid = ?",
};

/*
** A connection to a fulltext index is an instance of the following
** structure.  The xCreate and xConnect methods create an instance
** of this structure and xDestroy and xDisconnect free that instance.
** All other methods receive a pointer to the structure as one of their
** arguments.
*/
struct fulltext_vtab {
  sqlite3_vtab base;               /* Base class used by SQLite core */
  sqlite3 *db;                     /* The database connection */
  const char *zDb;                 /* logical database name */
  const char *zName;               /* virtual table name */
  int nColumn;                     /* number of columns in virtual table */
  char **azColumn;                 /* column names.  malloced */
  char **azContentColumn;          /* column names in content table; malloced */
  sqlite3_tokenizer *pTokenizer;   /* tokenizer for inserts and queries */

  /* Precompiled statements which we keep as long as the table is
  ** open.
  */
  sqlite3_stmt *pFulltextStatements[MAX_STMT];
};

/*
** When the core wants to do a query, it create a cursor using a
** call to xOpen.  This structure is an instance of a cursor.  It
** is destroyed by xClose.
*/
typedef struct fulltext_cursor {
  sqlite3_vtab_cursor base;        /* Base class used by SQLite core */
  QueryType iCursorType;           /* Copy of sqlite3_index_info.idxNum */
  sqlite3_stmt *pStmt;             /* Prepared statement in use by the cursor */
  int eof;                         /* True if at End Of Results */
  Query q;                         /* Parsed query string */
  Snippet snippet;                 /* Cached snippet for the current row */
  int iColumn;                     /* Column being searched */
  DocListReader result;  /* used when iCursorType == QUERY_FULLTEXT */ 
} fulltext_cursor;

static struct fulltext_vtab *cursor_vtab(fulltext_cursor *c){
  return (fulltext_vtab *) c->base.pVtab;
}

static const sqlite3_module fulltextModule;   /* forward declaration */

/* Append a list of strings separated by commas to a StringBuffer. */
static void appendList(StringBuffer *sb, int nString, char **azString){
  int i;
  for(i=0; i<nString; ++i){
    if( i>0 ) append(sb, ", ");
    append(sb, azString[i]);
  }
}

/* Return a dynamically generated statement of the form
 *   insert into %_content (rowid, ...) values (?, ...)
 */
static const char *contentInsertStatement(fulltext_vtab *v){
  StringBuffer sb;
  int i;

  initStringBuffer(&sb);
  append(&sb, "insert into %_content (rowid, ");
  appendList(&sb, v->nColumn, v->azContentColumn);
  append(&sb, ") values (?");
  for(i=0; i<v->nColumn; ++i)
    append(&sb, ", ?");
  append(&sb, ")");
  return sb.s;
}

/* Return a dynamically generated statement of the form
 *   update %_content set [col_0] = ?, [col_1] = ?, ...
 *                    where rowid = ?
 */
static const char *contentUpdateStatement(fulltext_vtab *v){
  StringBuffer sb;
  int i;

  initStringBuffer(&sb);
  append(&sb, "update %_content set ");
  for(i=0; i<v->nColumn; ++i) {
    if( i>0 ){
      append(&sb, ", ");
    }
    append(&sb, v->azContentColumn[i]);
    append(&sb, " = ?");
  }
  append(&sb, " where rowid = ?");
  return sb.s;
}

/* Puts a freshly-prepared statement determined by iStmt in *ppStmt.
** If the indicated statement has never been prepared, it is prepared
** and cached, otherwise the cached version is reset.
*/
static int sql_get_statement(fulltext_vtab *v, fulltext_statement iStmt,
                             sqlite3_stmt **ppStmt){
  assert( iStmt<MAX_STMT );
  if( v->pFulltextStatements[iStmt]==NULL ){
    const char *zStmt;
    int rc;
    switch( iStmt ){
      case CONTENT_INSERT_STMT:
        zStmt = contentInsertStatement(v); break;
      case CONTENT_UPDATE_STMT:
        zStmt = contentUpdateStatement(v); break;
      default:
        zStmt = fulltext_zStatement[iStmt];
    }
    rc = sql_prepare(v->db, v->zDb, v->zName, &v->pFulltextStatements[iStmt],
                         zStmt);
    if( zStmt != fulltext_zStatement[iStmt]) free((void *) zStmt);
    if( rc!=SQLITE_OK ) return rc;
  } else {
    int rc = sqlite3_reset(v->pFulltextStatements[iStmt]);
    if( rc!=SQLITE_OK ) return rc;
  }

  *ppStmt = v->pFulltextStatements[iStmt];
  return SQLITE_OK;
}

/* Step the indicated statement, handling errors SQLITE_BUSY (by
** retrying) and SQLITE_SCHEMA (by re-preparing and transferring
** bindings to the new statement).
** TODO(adam): We should extend this function so that it can work with
** statements declared locally, not only globally cached statements.
*/
static int sql_step_statement(fulltext_vtab *v, fulltext_statement iStmt,
                              sqlite3_stmt **ppStmt){
  int rc;
  sqlite3_stmt *s = *ppStmt;
  assert( iStmt<MAX_STMT );
  assert( s==v->pFulltextStatements[iStmt] );

  while( (rc=sqlite3_step(s))!=SQLITE_DONE && rc!=SQLITE_ROW ){
    if( rc==SQLITE_BUSY ) continue;
    if( rc!=SQLITE_ERROR ) return rc;

    /* If an SQLITE_SCHEMA error has occurred, then finalizing this
     * statement is going to delete the fulltext_vtab structure. If
     * the statement just executed is in the pFulltextStatements[]
     * array, it will be finalized twice. So remove it before
     * calling sqlite3_finalize().
     */
    v->pFulltextStatements[iStmt] = NULL;
    rc = sqlite3_finalize(s);
    break;
  }
  return rc;

 err:
  sqlite3_finalize(s);
  return rc;
}

/* Like sql_step_statement(), but convert SQLITE_DONE to SQLITE_OK.
** Useful for statements like UPDATE, where we expect no results.
*/
static int sql_single_step_statement(fulltext_vtab *v,
                                     fulltext_statement iStmt,
                                     sqlite3_stmt **ppStmt){
  int rc = sql_step_statement(v, iStmt, ppStmt);
  return (rc==SQLITE_DONE) ? SQLITE_OK : rc;
}

/* insert into %_content (rowid, ...) values ([rowid], [pValues]) */
static int content_insert(fulltext_vtab *v, sqlite3_value *rowid,
                          sqlite3_value **pValues){
  sqlite3_stmt *s;
  int i;
  int rc = sql_get_statement(v, CONTENT_INSERT_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_value(s, 1, rowid);
  if( rc!=SQLITE_OK ) return rc;

  for(i=0; i<v->nColumn; ++i){
    rc = sqlite3_bind_value(s, 2+i, pValues[i]);
    if( rc!=SQLITE_OK ) return rc;
  }

  return sql_single_step_statement(v, CONTENT_INSERT_STMT, &s);
}

/* update %_content set col0 = pValues[0], col1 = pValues[1], ...
 *                  where rowid = [iRowid] */
static int content_update(fulltext_vtab *v, sqlite3_value **pValues,
                          sqlite_int64 iRowid){
  sqlite3_stmt *s;
  int i;
  int rc = sql_get_statement(v, CONTENT_UPDATE_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  for(i=0; i<v->nColumn; ++i){
    rc = sqlite3_bind_value(s, 1+i, pValues[i]);
    if( rc!=SQLITE_OK ) return rc;
  }

  rc = sqlite3_bind_int64(s, 1+v->nColumn, iRowid);
  if( rc!=SQLITE_OK ) return rc;

  return sql_single_step_statement(v, CONTENT_UPDATE_STMT, &s);
}

static void freeStringArray(int nString, const char **pString){
  int i;

  for (i=0 ; i < nString ; ++i) {
    if( pString[i]!=NULL ) free((void *) pString[i]);
  }
  free((void *) pString);
}

/* select * from %_content where rowid = [iRow]
 * The caller must delete the returned array and all strings in it.
 * null fields will be NULL in the returned array.
 *
 * TODO: Perhaps we should return pointer/length strings here for consistency
 * with other code which uses pointer/length. */
static int content_select(fulltext_vtab *v, sqlite_int64 iRow,
                          const char ***pValues){
  sqlite3_stmt *s;
  const char **values;
  int i;
  int rc;

  *pValues = NULL;

  rc = sql_get_statement(v, CONTENT_SELECT_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_int64(s, 1, iRow);
  if( rc!=SQLITE_OK ) return rc;

  rc = sql_step_statement(v, CONTENT_SELECT_STMT, &s);
  if( rc!=SQLITE_ROW ) return rc;

  values = (const char **) malloc(v->nColumn * sizeof(const char *));
  for(i=0; i<v->nColumn; ++i){
    if( sqlite3_column_type(s, i)==SQLITE_NULL ){
      values[i] = NULL;
    }else{
      values[i] = string_dup((char*)sqlite3_column_text(s, i));
    }
  }

  /* We expect only one row.  We must execute another sqlite3_step()
   * to complete the iteration; otherwise the table will remain locked. */
  rc = sqlite3_step(s);
  if( rc==SQLITE_DONE ){
    *pValues = values;
    return SQLITE_OK;
  }

  freeStringArray(v->nColumn, values);
  return rc;
}

/* delete from %_content where rowid = [iRow ] */
static int content_delete(fulltext_vtab *v, sqlite_int64 iRow){
  sqlite3_stmt *s;
  int rc = sql_get_statement(v, CONTENT_DELETE_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_int64(s, 1, iRow);
  if( rc!=SQLITE_OK ) return rc;

  return sql_single_step_statement(v, CONTENT_DELETE_STMT, &s);
}

/* select rowid, doclist from %_term
 *  where term = [pTerm] and segment = [iSegment]
 * If found, returns SQLITE_ROW; the caller must free the
 * returned doclist.  If no rows found, returns SQLITE_DONE. */
static int term_select(fulltext_vtab *v, const char *pTerm, int nTerm,
                       int iSegment,
                       sqlite_int64 *rowid, DocList *out){
  sqlite3_stmt *s;
  int rc = sql_get_statement(v, TERM_SELECT_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_text(s, 1, pTerm, nTerm, SQLITE_STATIC);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_int(s, 2, iSegment);
  if( rc!=SQLITE_OK ) return rc;

  rc = sql_step_statement(v, TERM_SELECT_STMT, &s);
  if( rc!=SQLITE_ROW ) return rc;

  *rowid = sqlite3_column_int64(s, 0);
  docListInit(out, DL_DEFAULT,
              sqlite3_column_blob(s, 1), sqlite3_column_bytes(s, 1));

  /* We expect only one row.  We must execute another sqlite3_step()
   * to complete the iteration; otherwise the table will remain locked. */
  rc = sqlite3_step(s);
  return rc==SQLITE_DONE ? SQLITE_ROW : rc;
}

/* Load the segment doclists for term pTerm and merge them in
** appropriate order into out.  Returns SQLITE_OK if successful.  If
** there are no segments for pTerm, successfully returns an empty
** doclist in out.
**
** Each document consists of 1 or more "columns".  The number of
** columns is v->nColumn.  If iColumn==v->nColumn, then return
** position information about all columns.  If iColumn<v->nColumn,
** then only return position information about the iColumn-th column
** (where the first column is 0).
*/
static int term_select_all(
  fulltext_vtab *v,     /* The fulltext index we are querying against */
  int iColumn,          /* If <nColumn, only look at the iColumn-th column */
  const char *pTerm,    /* The term whose posting lists we want */
  int nTerm,            /* Number of bytes in pTerm */
  DocList *out          /* Write the resulting doclist here */
){
  DocList doclist;
  sqlite3_stmt *s;
  int rc = sql_get_statement(v, TERM_SELECT_ALL_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_text(s, 1, pTerm, nTerm, SQLITE_STATIC);
  if( rc!=SQLITE_OK ) return rc;

  docListInit(&doclist, DL_DEFAULT, 0, 0);

  /* TODO(shess) Handle schema and busy errors. */
  while( (rc=sql_step_statement(v, TERM_SELECT_ALL_STMT, &s))==SQLITE_ROW ){
    DocList old;

    /* TODO(shess) If we processed doclists from oldest to newest, we
    ** could skip the malloc() involved with the following call.  For
    ** now, I'd rather keep this logic similar to index_insert_term().
    ** We could additionally drop elements when we see deletes, but
    ** that would require a distinct version of docListAccumulate().
    */
    docListInit(&old, DL_DEFAULT,
                sqlite3_column_blob(s, 0), sqlite3_column_bytes(s, 0));

    if( iColumn<v->nColumn ){   /* querying a single column */
      docListRestrictColumn(&old, iColumn);
    }

    /* doclist contains the newer data, so write it over old.  Then
    ** steal accumulated result for doclist.
    */
    docListAccumulate(&old, &doclist);
    docListDestroy(&doclist);
    doclist = old;
  }
  if( rc!=SQLITE_DONE ){
    docListDestroy(&doclist);
    return rc;
  }

  docListDiscardEmpty(&doclist);
  *out = doclist;
  return SQLITE_OK;
}

/* insert into %_term (rowid, term, segment, doclist)
               values ([piRowid], [pTerm], [iSegment], [doclist])
** Lets sqlite select rowid if piRowid is NULL, else uses *piRowid.
**
** NOTE(shess) piRowid is IN, with values of "space of int64" plus
** null, it is not used to pass data back to the caller.
*/
static int term_insert(fulltext_vtab *v, sqlite_int64 *piRowid,
                       const char *pTerm, int nTerm,
                       int iSegment, DocList *doclist){
  sqlite3_stmt *s;
  int rc = sql_get_statement(v, TERM_INSERT_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  if( piRowid==NULL ){
    rc = sqlite3_bind_null(s, 1);
  }else{
    rc = sqlite3_bind_int64(s, 1, *piRowid);
  }
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_text(s, 2, pTerm, nTerm, SQLITE_STATIC);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_int(s, 3, iSegment);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_blob(s, 4, doclist->pData, doclist->nData, SQLITE_STATIC);
  if( rc!=SQLITE_OK ) return rc;

  return sql_single_step_statement(v, TERM_INSERT_STMT, &s);
}

/* update %_term set doclist = [doclist] where rowid = [rowid] */
static int term_update(fulltext_vtab *v, sqlite_int64 rowid,
                       DocList *doclist){
  sqlite3_stmt *s;
  int rc = sql_get_statement(v, TERM_UPDATE_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_blob(s, 1, doclist->pData, doclist->nData, SQLITE_STATIC);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_int64(s, 2, rowid);
  if( rc!=SQLITE_OK ) return rc;

  return sql_single_step_statement(v, TERM_UPDATE_STMT, &s);
}

static int term_delete(fulltext_vtab *v, sqlite_int64 rowid){
  sqlite3_stmt *s;
  int rc = sql_get_statement(v, TERM_DELETE_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_int64(s, 1, rowid);
  if( rc!=SQLITE_OK ) return rc;

  return sql_single_step_statement(v, TERM_DELETE_STMT, &s);
}

/*
** Free the memory used to contain a fulltext_vtab structure.
*/
static void fulltext_vtab_destroy(fulltext_vtab *v){
  int iStmt, i;

  TRACE(("FTS1 Destroy %p\n", v));
  for( iStmt=0; iStmt<MAX_STMT; iStmt++ ){
    if( v->pFulltextStatements[iStmt]!=NULL ){
      sqlite3_finalize(v->pFulltextStatements[iStmt]);
      v->pFulltextStatements[iStmt] = NULL;
    }
  }

  if( v->pTokenizer!=NULL ){
    v->pTokenizer->pModule->xDestroy(v->pTokenizer);
    v->pTokenizer = NULL;
  }
  
  free(v->azColumn);
  for(i = 0; i < v->nColumn; ++i) {
    sqlite3_free(v->azContentColumn[i]);
  }
  free(v->azContentColumn);
  free(v);
}

/*
** Token types for parsing the arguments to xConnect or xCreate.
*/
#define TOKEN_EOF         0    /* End of file */
#define TOKEN_SPACE       1    /* Any kind of whitespace */
#define TOKEN_ID          2    /* An identifier */
#define TOKEN_STRING      3    /* A string literal */
#define TOKEN_PUNCT       4    /* A single punctuation character */

/*
** If X is a character that can be used in an identifier then
** IdChar(X) will be true.  Otherwise it is false.
**
** For ASCII, any character with the high-order bit set is
** allowed in an identifier.  For 7-bit characters, 
** sqlite3IsIdChar[X] must be 1.
**
** Ticket #1066.  the SQL standard does not allow '$' in the
** middle of identfiers.  But many SQL implementations do. 
** SQLite will allow '$' in identifiers for compatibility.
** But the feature is undocumented.
*/
static const char isIdChar[] = {
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
    0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 2x */
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,  /* 3x */
    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 4x */
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,  /* 5x */
    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 6x */
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,  /* 7x */
};
#define IdChar(C)  (((c=C)&0x80)!=0 || (c>0x1f && isIdChar[c-0x20]))


/*
** Return the length of the token that begins at z[0]. 
** Store the token type in *tokenType before returning.
*/
static int getToken(const char *z, int *tokenType){
  int i, c;
  switch( *z ){
    case 0: {
      *tokenType = TOKEN_EOF;
      return 0;
    }
    case ' ': case '\t': case '\n': case '\f': case '\r': {
      for(i=1; safe_isspace(z[i]); i++){}
      *tokenType = TOKEN_SPACE;
      return i;
    }
    case '`':
    case '\'':
    case '"': {
      int delim = z[0];
      for(i=1; (c=z[i])!=0; i++){
        if( c==delim ){
          if( z[i+1]==delim ){
            i++;
          }else{
            break;
          }
        }
      }
      *tokenType = TOKEN_STRING;
      return i + (c!=0);
    }
    case '[': {
      for(i=1, c=z[0]; c!=']' && (c=z[i])!=0; i++){}
      *tokenType = TOKEN_ID;
      return i;
    }
    default: {
      if( !IdChar(*z) ){
        break;
      }
      for(i=1; IdChar(z[i]); i++){}
      *tokenType = TOKEN_ID;
      return i;
    }
  }
  *tokenType = TOKEN_PUNCT;
  return 1;
}

/*
** A token extracted from a string is an instance of the following
** structure.
*/
typedef struct Token {
  const char *z;       /* Pointer to token text.  Not '\000' terminated */
  short int n;         /* Length of the token text in bytes. */
} Token;

/*
** Given a input string (which is really one of the argv[] parameters
** passed into xConnect or xCreate) split the string up into tokens.
** Return an array of pointers to '\000' terminated strings, one string
** for each non-whitespace token.
**
** The returned array is terminated by a single NULL pointer.
**
** Space to hold the returned array is obtained from a single
** malloc and should be freed by passing the return value to free().
** The individual strings within the token list are all a part of
** the single memory allocation and will all be freed at once.
*/
static char **tokenizeString(const char *z, int *pnToken){
  int nToken = 0;
  Token *aToken = malloc( strlen(z) * sizeof(aToken[0]) );
  int n = 1;
  int e, i;
  int totalSize = 0;
  char **azToken;
  char *zCopy;
  while( n>0 ){
    n = getToken(z, &e);
    if( e!=TOKEN_SPACE ){
      aToken[nToken].z = z;
      aToken[nToken].n = n;
      nToken++;
      totalSize += n+1;
    }
    z += n;
  }
  azToken = (char**)malloc( nToken*sizeof(char*) + totalSize );
  zCopy = (char*)&azToken[nToken];
  nToken--;
  for(i=0; i<nToken; i++){
    azToken[i] = zCopy;
    n = aToken[i].n;
    memcpy(zCopy, aToken[i].z, n);
    zCopy[n] = 0;
    zCopy += n+1;
  }
  azToken[nToken] = 0;
  free(aToken);
  *pnToken = nToken;
  return azToken;
}

/*
** Convert an SQL-style quoted string into a normal string by removing
** the quote characters.  The conversion is done in-place.  If the
** input does not begin with a quote character, then this routine
** is a no-op.
**
** Examples:
**
**     "abc"   becomes   abc
**     'xyz'   becomes   xyz
**     [pqr]   becomes   pqr
**     `mno`   becomes   mno
*/
static void dequoteString(char *z){
  int quote;
  int i, j;
  if( z==0 ) return;
  quote = z[0];
  switch( quote ){
    case '\'':  break;
    case '"':   break;
    case '`':   break;                /* For MySQL compatibility */
    case '[':   quote = ']';  break;  /* For MS SqlServer compatibility */
    default:    return;
  }
  for(i=1, j=0; z[i]; i++){
    if( z[i]==quote ){
      if( z[i+1]==quote ){
        z[j++] = quote;
        i++;
      }else{
        z[j++] = 0;
        break;
      }
    }else{
      z[j++] = z[i];
    }
  }
}

/*
** The input azIn is a NULL-terminated list of tokens.  Remove the first
** token and all punctuation tokens.  Remove the quotes from
** around string literal tokens.
**
** Example:
**
**     input:      tokenize chinese ( 'simplifed' , 'mixed' )
**     output:     chinese simplifed mixed
**
** Another example:
**
**     input:      delimiters ( '[' , ']' , '...' )
**     output:     [ ] ...
*/
static void tokenListToIdList(char **azIn){
  int i, j;
  if( azIn ){
    for(i=0, j=-1; azIn[i]; i++){
      if( safe_isalnum(azIn[i][0]) || azIn[i][1] ){
        dequoteString(azIn[i]);
        if( j>=0 ){
          azIn[j] = azIn[i];
        }
        j++;
      }
    }
    azIn[j] = 0;
  }
}


/*
** Find the first alphanumeric token in the string zIn.  Null-terminate
** this token.  Remove any quotation marks.  And return a pointer to
** the result.
*/
static char *firstToken(char *zIn, char **pzTail){
  int n, ttype;
  while(1){
    n = getToken(zIn, &ttype);
    if( ttype==TOKEN_SPACE ){
      zIn += n;
    }else if( ttype==TOKEN_EOF ){
      *pzTail = zIn;
      return 0;
    }else{
      zIn[n] = 0;
      *pzTail = &zIn[1];
      dequoteString(zIn);
      return zIn;
    }
  }
  /*NOTREACHED*/
}

/* Return true if...
**
**   *  s begins with the string t, ignoring case
**   *  s is longer than t
**   *  The first character of s beyond t is not a alphanumeric
** 
** Ignore leading space in *s.
**
** To put it another way, return true if the first token of
** s[] is t[].
*/
static int startsWith(const char *s, const char *t){
  while( safe_isspace(*s) ){ s++; }
  while( *t ){
    if( safe_tolower(*s++)!=safe_tolower(*t++) ) return 0;
  }
  return *s!='_' && !safe_isalnum(*s);
}

/*
** An instance of this structure defines the "spec" of a
** full text index.  This structure is populated by parseSpec
** and use by fulltextConnect and fulltextCreate.
*/
typedef struct TableSpec {
  const char *zDb;         /* Logical database name */
  const char *zName;       /* Name of the full-text index */
  int nColumn;             /* Number of columns to be indexed */
  char **azColumn;         /* Original names of columns to be indexed */
  char **azContentColumn;  /* Column names for %_content */
  char **azTokenizer;      /* Name of tokenizer and its arguments */
} TableSpec;

/*
** Reclaim all of the memory used by a TableSpec
*/
static void clearTableSpec(TableSpec *p) {
  free(p->azColumn);
  free(p->azContentColumn);
  free(p->azTokenizer);
}

/* Parse a CREATE VIRTUAL TABLE statement, which looks like this:
 *
 * CREATE VIRTUAL TABLE email
 *        USING fts1(subject, body, tokenize mytokenizer(myarg))
 *
 * We return parsed information in a TableSpec structure.
 * 
 */
static int parseSpec(TableSpec *pSpec, int argc, const char *const*argv,
                     char**pzErr){
  int i, n;
  char *z, *zDummy;
  char **azArg;
  const char *zTokenizer = 0;    /* argv[] entry describing the tokenizer */

  assert( argc>=3 );
  /* Current interface:
  ** argv[0] - module name
  ** argv[1] - database name
  ** argv[2] - table name
  ** argv[3..] - columns, optionally followed by tokenizer specification
  **             and snippet delimiters specification.
  */

  /* Make a copy of the complete argv[][] array in a single allocation.
  ** The argv[][] array is read-only and transient.  We can write to the
  ** copy in order to modify things and the copy is persistent.
  */
  memset(pSpec, 0, sizeof(*pSpec));
  for(i=n=0; i<argc; i++){
    n += strlen(argv[i]) + 1;
  }
  azArg = malloc( sizeof(char*)*argc + n );
  if( azArg==0 ){
    return SQLITE_NOMEM;
  }
  z = (char*)&azArg[argc];
  for(i=0; i<argc; i++){
    azArg[i] = z;
    strcpy(z, argv[i]);
    z += strlen(z)+1;
  }

  /* Identify the column names and the tokenizer and delimiter arguments
  ** in the argv[][] array.
  */
  pSpec->zDb = azArg[1];
  pSpec->zName = azArg[2];
  pSpec->nColumn = 0;
  pSpec->azColumn = azArg;
  zTokenizer = "tokenize simple";
  for(i=3; i<argc; ++i){
    if( startsWith(azArg[i],"tokenize") ){
      zTokenizer = azArg[i];
    }else{
      z = azArg[pSpec->nColumn] = firstToken(azArg[i], &zDummy);
      pSpec->nColumn++;
    }
  }
  if( pSpec->nColumn==0 ){
    azArg[0] = "content";
    pSpec->nColumn = 1;
  }

  /*
  ** Construct the list of content column names.
  **
  ** Each content column name will be of the form cNNAAAA
  ** where NN is the column number and AAAA is the sanitized
  ** column name.  "sanitized" means that special characters are
  ** converted to "_".  The cNN prefix guarantees that all column
  ** names are unique.
  **
  ** The AAAA suffix is not strictly necessary.  It is included
  ** for the convenience of people who might examine the generated
  ** %_content table and wonder what the columns are used for.
  */
  pSpec->azContentColumn = malloc( pSpec->nColumn * sizeof(char *) );
  if( pSpec->azContentColumn==0 ){
    clearTableSpec(pSpec);
    return SQLITE_NOMEM;
  }
  for(i=0; i<pSpec->nColumn; i++){
    char *p;
    pSpec->azContentColumn[i] = sqlite3_mprintf("c%d%s", i, azArg[i]);
    for (p = pSpec->azContentColumn[i]; *p ; ++p) {
      if( !safe_isalnum(*p) ) *p = '_';
    }
  }

  /*
  ** Parse the tokenizer specification string.
  */
  pSpec->azTokenizer = tokenizeString(zTokenizer, &n);
  tokenListToIdList(pSpec->azTokenizer);

  return SQLITE_OK;
}

/*
** Generate a CREATE TABLE statement that describes the schema of
** the virtual table.  Return a pointer to this schema string.
**
** Space is obtained from sqlite3_mprintf() and should be freed
** using sqlite3_free().
*/
static char *fulltextSchema(
  int nColumn,                  /* Number of columns */
  const char *const* azColumn,  /* List of columns */
  const char *zTableName        /* Name of the table */
){
  int i;
  char *zSchema, *zNext;
  const char *zSep = "(";
  zSchema = sqlite3_mprintf("CREATE TABLE x");
  for(i=0; i<nColumn; i++){
    zNext = sqlite3_mprintf("%s%s%Q", zSchema, zSep, azColumn[i]);
    sqlite3_free(zSchema);
    zSchema = zNext;
    zSep = ",";
  }
  zNext = sqlite3_mprintf("%s,%Q)", zSchema, zTableName);
  sqlite3_free(zSchema);
  return zNext;
}

/*
** Build a new sqlite3_vtab structure that will describe the
** fulltext index defined by spec.
*/
static int constructVtab(
  sqlite3 *db,              /* The SQLite database connection */
  TableSpec *spec,          /* Parsed spec information from parseSpec() */
  sqlite3_vtab **ppVTab,    /* Write the resulting vtab structure here */
  char **pzErr              /* Write any error message here */
){
  int rc;
  int n;
  fulltext_vtab *v = 0;
  const sqlite3_tokenizer_module *m = NULL;
  char *schema;

  v = (fulltext_vtab *) malloc(sizeof(fulltext_vtab));
  if( v==0 ) return SQLITE_NOMEM;
  memset(v, 0, sizeof(*v));
  /* sqlite will initialize v->base */
  v->db = db;
  v->zDb = spec->zDb;       /* Freed when azColumn is freed */
  v->zName = spec->zName;   /* Freed when azColumn is freed */
  v->nColumn = spec->nColumn;
  v->azContentColumn = spec->azContentColumn;
  spec->azContentColumn = 0;
  v->azColumn = spec->azColumn;
  spec->azColumn = 0;

  if( spec->azTokenizer==0 ){
    return SQLITE_NOMEM;
  }
  /* TODO(shess) For now, add new tokenizers as else if clauses. */
  if( spec->azTokenizer[0]==0 || startsWith(spec->azTokenizer[0], "simple") ){
    sqlite3Fts1SimpleTokenizerModule(&m);
  }else if( startsWith(spec->azTokenizer[0], "porter") ){
    sqlite3Fts1PorterTokenizerModule(&m);
  }else{
    *pzErr = sqlite3_mprintf("unknown tokenizer: %s", spec->azTokenizer[0]);
    rc = SQLITE_ERROR;
    goto err;
  }
  for(n=0; spec->azTokenizer[n]; n++){}
  if( n ){
    rc = m->xCreate(n-1, (const char*const*)&spec->azTokenizer[1],
                    &v->pTokenizer);
  }else{
    rc = m->xCreate(0, 0, &v->pTokenizer);
  }
  if( rc!=SQLITE_OK ) goto err;
  v->pTokenizer->pModule = m;

  /* TODO: verify the existence of backing tables foo_content, foo_term */

  schema = fulltextSchema(v->nColumn, (const char*const*)v->azColumn,
                          spec->zName);
  rc = sqlite3_declare_vtab(db, schema);
  sqlite3_free(schema);
  if( rc!=SQLITE_OK ) goto err;

  memset(v->pFulltextStatements, 0, sizeof(v->pFulltextStatements));

  *ppVTab = &v->base;
  TRACE(("FTS1 Connect %p\n", v));

  return rc;

err:
  fulltext_vtab_destroy(v);
  return rc;
}

static int fulltextConnect(
  sqlite3 *db,
  void *pAux,
  int argc, const char *const*argv,
  sqlite3_vtab **ppVTab,
  char **pzErr
){
  TableSpec spec;
  int rc = parseSpec(&spec, argc, argv, pzErr);
  if( rc!=SQLITE_OK ) return rc;

  rc = constructVtab(db, &spec, ppVTab, pzErr);
  clearTableSpec(&spec);
  return rc;
}

  /* The %_content table holds the text of each document, with
  ** the rowid used as the docid.
  **
  ** The %_term table maps each term to a document list blob
  ** containing elements sorted by ascending docid, each element
  ** encoded as:
  **
  **   docid varint-encoded
  **   token elements:
  **     position+1 varint-encoded as delta from previous position
  **     start offset varint-encoded as delta from previous start offset
  **     end offset varint-encoded as delta from start offset
  **
  ** The sentinel position of 0 indicates the end of the token list.
  **
  ** Additionally, doclist blobs are chunked into multiple segments,
  ** using segment to order the segments.  New elements are added to
  ** the segment at segment 0, until it exceeds CHUNK_MAX.  Then
  ** segment 0 is deleted, and the doclist is inserted at segment 1.
  ** If there is already a doclist at segment 1, the segment 0 doclist
  ** is merged with it, the segment 1 doclist is deleted, and the
  ** merged doclist is inserted at segment 2, repeating those
  ** operations until an insert succeeds.
  **
  ** Since this structure doesn't allow us to update elements in place
  ** in case of deletion or update, these are simply written to
  ** segment 0 (with an empty token list in case of deletion), with
  ** docListAccumulate() taking care to retain lower-segment
  ** information in preference to higher-segment information.
  */
  /* TODO(shess) Provide a VACUUM type operation which both removes
  ** deleted elements which are no longer necessary, and duplicated
  ** elements.  I suspect this will probably not be necessary in
  ** practice, though.
  */
static int fulltextCreate(sqlite3 *db, void *pAux,
                          int argc, const char * const *argv,
                          sqlite3_vtab **ppVTab, char **pzErr){
  int rc;
  TableSpec spec;
  StringBuffer schema;
  TRACE(("FTS1 Create\n"));

  rc = parseSpec(&spec, argc, argv, pzErr);
  if( rc!=SQLITE_OK ) return rc;

  initStringBuffer(&schema);
  append(&schema, "CREATE TABLE %_content(");
  appendList(&schema, spec.nColumn, spec.azContentColumn);
  append(&schema, ")");
  rc = sql_exec(db, spec.zDb, spec.zName, schema.s);
  free(schema.s);
  if( rc!=SQLITE_OK ) goto out;

  rc = sql_exec(db, spec.zDb, spec.zName,
    "create table %_term(term text, segment integer, doclist blob, "
                        "primary key(term, segment));");
  if( rc!=SQLITE_OK ) goto out;

  rc = constructVtab(db, &spec, ppVTab, pzErr);

out:
  clearTableSpec(&spec);
  return rc;
}

/* Decide how to handle an SQL query. */
static int fulltextBestIndex(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
  int i;
  TRACE(("FTS1 BestIndex\n"));

  for(i=0; i<pInfo->nConstraint; ++i){
    const struct sqlite3_index_constraint *pConstraint;
    pConstraint = &pInfo->aConstraint[i];
    if( pConstraint->usable ) {
      if( pConstraint->iColumn==-1 &&
          pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
        pInfo->idxNum = QUERY_ROWID;      /* lookup by rowid */
        TRACE(("FTS1 QUERY_ROWID\n"));
      } else if( pConstraint->iColumn>=0 &&
                 pConstraint->op==SQLITE_INDEX_CONSTRAINT_MATCH ){
        /* full-text search */
        pInfo->idxNum = QUERY_FULLTEXT + pConstraint->iColumn;
        TRACE(("FTS1 QUERY_FULLTEXT %d\n", pConstraint->iColumn));
      } else continue;

      pInfo->aConstraintUsage[i].argvIndex = 1;
      pInfo->aConstraintUsage[i].omit = 1;

      /* An arbitrary value for now.
       * TODO: Perhaps rowid matches should be considered cheaper than
       * full-text searches. */
      pInfo->estimatedCost = 1.0;   

      return SQLITE_OK;
    }
  }
  pInfo->idxNum = QUERY_GENERIC;
  return SQLITE_OK;
}

static int fulltextDisconnect(sqlite3_vtab *pVTab){
  TRACE(("FTS1 Disconnect %p\n", pVTab));
  fulltext_vtab_destroy((fulltext_vtab *)pVTab);
  return SQLITE_OK;
}

static int fulltextDestroy(sqlite3_vtab *pVTab){
  fulltext_vtab *v = (fulltext_vtab *)pVTab;
  int rc;

  TRACE(("FTS1 Destroy %p\n", pVTab));
  rc = sql_exec(v->db, v->zDb, v->zName,
                "drop table if exists %_content;"
                "drop table if exists %_term;"
                );
  if( rc!=SQLITE_OK ) return rc;

  fulltext_vtab_destroy((fulltext_vtab *)pVTab);
  return SQLITE_OK;
}

static int fulltextOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
  fulltext_cursor *c;

  c = (fulltext_cursor *) calloc(sizeof(fulltext_cursor), 1);
  /* sqlite will initialize c->base */
  *ppCursor = &c->base;
  TRACE(("FTS1 Open %p: %p\n", pVTab, c));

  return SQLITE_OK;
}


/* Free all of the dynamically allocated memory held by *q
*/
static void queryClear(Query *q){
  int i;
  for(i = 0; i < q->nTerms; ++i){
    free(q->pTerms[i].pTerm);
  }
  free(q->pTerms);
  memset(q, 0, sizeof(*q));
}

/* Free all of the dynamically allocated memory held by the
** Snippet
*/
static void snippetClear(Snippet *p){
  free(p->aMatch);
  free(p->zOffset);
  free(p->zSnippet);
  memset(p, 0, sizeof(*p));
}
/*
** Append a single entry to the p->aMatch[] log.
*/
static void snippetAppendMatch(
  Snippet *p,               /* Append the entry to this snippet */
  int iCol, int iTerm,      /* The column and query term */
  int iStart, int nByte     /* Offset and size of the match */
){
  int i;
  struct snippetMatch *pMatch;
  if( p->nMatch+1>=p->nAlloc ){
    p->nAlloc = p->nAlloc*2 + 10;
    p->aMatch = realloc(p->aMatch, p->nAlloc*sizeof(p->aMatch[0]) );
    if( p->aMatch==0 ){
      p->nMatch = 0;
      p->nAlloc = 0;
      return;
    }
  }
  i = p->nMatch++;
  pMatch = &p->aMatch[i];
  pMatch->iCol = iCol;
  pMatch->iTerm = iTerm;
  pMatch->iStart = iStart;
  pMatch->nByte = nByte;
}

/*
** Sizing information for the circular buffer used in snippetOffsetsOfColumn()
*/
#define FTS1_ROTOR_SZ   (32)
#define FTS1_ROTOR_MASK (FTS1_ROTOR_SZ-1)

/*
** Add entries to pSnippet->aMatch[] for every match that occurs against
** document zDoc[0..nDoc-1] which is stored in column iColumn.
*/
static void snippetOffsetsOfColumn(
  Query *pQuery,
  Snippet *pSnippet,
  int iColumn,
  const char *zDoc,
  int nDoc
){
  const sqlite3_tokenizer_module *pTModule;  /* The tokenizer module */
  sqlite3_tokenizer *pTokenizer;             /* The specific tokenizer */
  sqlite3_tokenizer_cursor *pTCursor;        /* Tokenizer cursor */
  fulltext_vtab *pVtab;                /* The full text index */
  int nColumn;                         /* Number of columns in the index */
  const QueryTerm *aTerm;              /* Query string terms */
  int nTerm;                           /* Number of query string terms */  
  int i, j;                            /* Loop counters */
  int rc;                              /* Return code */
  unsigned int match, prevMatch;       /* Phrase search bitmasks */
  const char *zToken;                  /* Next token from the tokenizer */
  int nToken;                          /* Size of zToken */
  int iBegin, iEnd, iPos;              /* Offsets of beginning and end */

  /* The following variables keep a circular buffer of the last
  ** few tokens */
  unsigned int iRotor = 0;             /* Index of current token */
  int iRotorBegin[FTS1_ROTOR_SZ];      /* Beginning offset of token */
  int iRotorLen[FTS1_ROTOR_SZ];        /* Length of token */

  pVtab = pQuery->pFts;
  nColumn = pVtab->nColumn;
  pTokenizer = pVtab->pTokenizer;
  pTModule = pTokenizer->pModule;
  rc = pTModule->xOpen(pTokenizer, zDoc, nDoc, &pTCursor);
  if( rc ) return;
  pTCursor->pTokenizer = pTokenizer;
  aTerm = pQuery->pTerms;
  nTerm = pQuery->nTerms;
  if( nTerm>=FTS1_ROTOR_SZ ){
    nTerm = FTS1_ROTOR_SZ - 1;
  }
  prevMatch = 0;
  while(1){
    rc = pTModule->xNext(pTCursor, &zToken, &nToken, &iBegin, &iEnd, &iPos);
    if( rc ) break;
    iRotorBegin[iRotor&FTS1_ROTOR_MASK] = iBegin;
    iRotorLen[iRotor&FTS1_ROTOR_MASK] = iEnd-iBegin;
    match = 0;
    for(i=0; i<nTerm; i++){
      int iCol;
      iCol = aTerm[i].iColumn;
      if( iCol>=0 && iCol<nColumn && iCol!=iColumn ) continue;
      if( aTerm[i].nTerm!=nToken ) continue;
      if( memcmp(aTerm[i].pTerm, zToken, nToken) ) continue;
      if( aTerm[i].iPhrase>1 && (prevMatch & (1<<i))==0 ) continue;
      match |= 1<<i;
      if( i==nTerm-1 || aTerm[i+1].iPhrase==1 ){
        for(j=aTerm[i].iPhrase-1; j>=0; j--){
          int k = (iRotor-j) & FTS1_ROTOR_MASK;
          snippetAppendMatch(pSnippet, iColumn, i-j,
                iRotorBegin[k], iRotorLen[k]);
        }
      }
    }
    prevMatch = match<<1;
    iRotor++;
  }
  pTModule->xClose(pTCursor);  
}


/*
** Compute all offsets for the current row of the query.  
** If the offsets have already been computed, this routine is a no-op.
*/
static void snippetAllOffsets(fulltext_cursor *p){
  int nColumn;
  int iColumn, i;
  int iFirst, iLast;
  fulltext_vtab *pFts;

  if( p->snippet.nMatch ) return;
  if( p->q.nTerms==0 ) return;
  pFts = p->q.pFts;
  nColumn = pFts->nColumn;
  iColumn = p->iCursorType - QUERY_FULLTEXT;
  if( iColumn<0 || iColumn>=nColumn ){
    iFirst = 0;
    iLast = nColumn-1;
  }else{
    iFirst = iColumn;
    iLast = iColumn;
  }
  for(i=iFirst; i<=iLast; i++){
    const char *zDoc;
    int nDoc;
    zDoc = (const char*)sqlite3_column_text(p->pStmt, i+1);
    nDoc = sqlite3_column_bytes(p->pStmt, i+1);
    snippetOffsetsOfColumn(&p->q, &p->snippet, i, zDoc, nDoc);
  }
}

/*
** Convert the information in the aMatch[] array of the snippet
** into the string zOffset[0..nOffset-1].
*/
static void snippetOffsetText(Snippet *p){
  int i;
  int cnt = 0;
  StringBuffer sb;
  char zBuf[200];
  if( p->zOffset ) return;
  initStringBuffer(&sb);
  for(i=0; i<p->nMatch; i++){
    struct snippetMatch *pMatch = &p->aMatch[i];
    zBuf[0] = ' ';
    sqlite3_snprintf(sizeof(zBuf)-1, &zBuf[cnt>0], "%d %d %d %d",
        pMatch->iCol, pMatch->iTerm, pMatch->iStart, pMatch->nByte);
    append(&sb, zBuf);
    cnt++;
  }
  p->zOffset = sb.s;
  p->nOffset = sb.len;
}

/*
** zDoc[0..nDoc-1] is phrase of text.  aMatch[0..nMatch-1] are a set
** of matching words some of which might be in zDoc.  zDoc is column
** number iCol.
**
** iBreak is suggested spot in zDoc where we could begin or end an
** excerpt.  Return a value similar to iBreak but possibly adjusted
** to be a little left or right so that the break point is better.
*/
static int wordBoundary(
  int iBreak,                   /* The suggested break point */
  const char *zDoc,             /* Document text */
  int nDoc,                     /* Number of bytes in zDoc[] */
  struct snippetMatch *aMatch,  /* Matching words */
  int nMatch,                   /* Number of entries in aMatch[] */
  int iCol                      /* The column number for zDoc[] */
){
  int i;
  if( iBreak<=10 ){
    return 0;
  }
  if( iBreak>=nDoc-10 ){
    return nDoc;
  }
  for(i=0; i<nMatch && aMatch[i].iCol<iCol; i++){}
  while( i<nMatch && aMatch[i].iStart+aMatch[i].nByte<iBreak ){ i++; }
  if( i<nMatch ){
    if( aMatch[i].iStart<iBreak+10 ){
      return aMatch[i].iStart;
    }
    if( i>0 && aMatch[i-1].iStart+aMatch[i-1].nByte>=iBreak ){
      return aMatch[i-1].iStart;
    }
  }
  for(i=1; i<=10; i++){
    if( safe_isspace(zDoc[iBreak-i]) ){
      return iBreak - i + 1;
    }
    if( safe_isspace(zDoc[iBreak+i]) ){
      return iBreak + i + 1;
    }
  }
  return iBreak;
}

/*
** If the StringBuffer does not end in white space, add a single
** space character to the end.
*/
static void appendWhiteSpace(StringBuffer *p){
  if( p->len==0 ) return;
  if( safe_isspace(p->s[p->len-1]) ) return;
  append(p, " ");
}

/*
** Remove white space from teh end of the StringBuffer
*/
static void trimWhiteSpace(StringBuffer *p){
  while( p->len>0 && safe_isspace(p->s[p->len-1]) ){
    p->len--;
  }
}



/*
** Allowed values for Snippet.aMatch[].snStatus
*/
#define SNIPPET_IGNORE  0   /* It is ok to omit this match from the snippet */
#define SNIPPET_DESIRED 1   /* We want to include this match in the snippet */

/*
** Generate the text of a snippet.
*/
static void snippetText(
  fulltext_cursor *pCursor,   /* The cursor we need the snippet for */
  const char *zStartMark,     /* Markup to appear before each match */
  const char *zEndMark,       /* Markup to appear after each match */
  const char *zEllipsis       /* Ellipsis mark */
){
  int i, j;
  struct snippetMatch *aMatch;
  int nMatch;
  int nDesired;
  StringBuffer sb;
  int tailCol;
  int tailOffset;
  int iCol;
  int nDoc;
  const char *zDoc;
  int iStart, iEnd;
  int tailEllipsis = 0;
  int iMatch;
  

  free(pCursor->snippet.zSnippet);
  pCursor->snippet.zSnippet = 0;
  aMatch = pCursor->snippet.aMatch;
  nMatch = pCursor->snippet.nMatch;
  initStringBuffer(&sb);

  for(i=0; i<nMatch; i++){
    aMatch[i].snStatus = SNIPPET_IGNORE;
  }
  nDesired = 0;
  for(i=0; i<pCursor->q.nTerms; i++){
    for(j=0; j<nMatch; j++){
      if( aMatch[j].iTerm==i ){
        aMatch[j].snStatus = SNIPPET_DESIRED;
        nDesired++;
        break;
      }
    }
  }

  iMatch = 0;
  tailCol = -1;
  tailOffset = 0;
  for(i=0; i<nMatch && nDesired>0; i++){
    if( aMatch[i].snStatus!=SNIPPET_DESIRED ) continue;
    nDesired--;
    iCol = aMatch[i].iCol;
    zDoc = (const char*)sqlite3_column_text(pCursor->pStmt, iCol+1);
    nDoc = sqlite3_column_bytes(pCursor->pStmt, iCol+1);
    iStart = aMatch[i].iStart - 40;
    iStart = wordBoundary(iStart, zDoc, nDoc, aMatch, nMatch, iCol);
    if( iStart<=10 ){
      iStart = 0;
    }
    if( iCol==tailCol && iStart<=tailOffset+20 ){
      iStart = tailOffset;
    }
    if( (iCol!=tailCol && tailCol>=0) || iStart!=tailOffset ){
      trimWhiteSpace(&sb);
      appendWhiteSpace(&sb);
      append(&sb, zEllipsis);
      appendWhiteSpace(&sb);
    }
    iEnd = aMatch[i].iStart + aMatch[i].nByte + 40;
    iEnd = wordBoundary(iEnd, zDoc, nDoc, aMatch, nMatch, iCol);
    if( iEnd>=nDoc-10 ){
      iEnd = nDoc;
      tailEllipsis = 0;
    }else{
      tailEllipsis = 1;
    }
    while( iMatch<nMatch && aMatch[iMatch].iCol<iCol ){ iMatch++; }
    while( iStart<iEnd ){
      while( iMatch<nMatch && aMatch[iMatch].iStart<iStart
             && aMatch[iMatch].iCol<=iCol ){
        iMatch++;
      }
      if( iMatch<nMatch && aMatch[iMatch].iStart<iEnd
             && aMatch[iMatch].iCol==iCol ){
        nappend(&sb, &zDoc[iStart], aMatch[iMatch].iStart - iStart);
        iStart = aMatch[iMatch].iStart;
        append(&sb, zStartMark);
        nappend(&sb, &zDoc[iStart], aMatch[iMatch].nByte);
        append(&sb, zEndMark);
        iStart += aMatch[iMatch].nByte;
        for(j=iMatch+1; j<nMatch; j++){
          if( aMatch[j].iTerm==aMatch[iMatch].iTerm
              && aMatch[j].snStatus==SNIPPET_DESIRED ){
            nDesired--;
            aMatch[j].snStatus = SNIPPET_IGNORE;
          }
        }
      }else{
        nappend(&sb, &zDoc[iStart], iEnd - iStart);
        iStart = iEnd;
      }
    }
    tailCol = iCol;
    tailOffset = iEnd;
  }
  trimWhiteSpace(&sb);
  if( tailEllipsis ){
    appendWhiteSpace(&sb);
    append(&sb, zEllipsis);
  }
  pCursor->snippet.zSnippet = sb.s;
  pCursor->snippet.nSnippet = sb.len;  
}


/*
** Close the cursor.  For additional information see the documentation
** on the xClose method of the virtual table interface.
*/
static int fulltextClose(sqlite3_vtab_cursor *pCursor){
  fulltext_cursor *c = (fulltext_cursor *) pCursor;
  TRACE(("FTS1 Close %p\n", c));
  sqlite3_finalize(c->pStmt);
  queryClear(&c->q);
  snippetClear(&c->snippet);
  if( c->result.pDoclist!=NULL ){
    docListDelete(c->result.pDoclist);
  }
  free(c);
  return SQLITE_OK;
}

static int fulltextNext(sqlite3_vtab_cursor *pCursor){
  fulltext_cursor *c = (fulltext_cursor *) pCursor;
  sqlite_int64 iDocid;
  int rc;

  TRACE(("FTS1 Next %p\n", pCursor));
  snippetClear(&c->snippet);
  if( c->iCursorType < QUERY_FULLTEXT ){
    /* TODO(shess) Handle SQLITE_SCHEMA AND SQLITE_BUSY. */
    rc = sqlite3_step(c->pStmt);
    switch( rc ){
      case SQLITE_ROW:
        c->eof = 0;
        return SQLITE_OK;
      case SQLITE_DONE:
        c->eof = 1;
        return SQLITE_OK;
      default:
        c->eof = 1;
        return rc;
    }
  } else {  /* full-text query */
    rc = sqlite3_reset(c->pStmt);
    if( rc!=SQLITE_OK ) return rc;

    iDocid = nextDocid(&c->result);
    if( iDocid==0 ){
      c->eof = 1;
      return SQLITE_OK;
    }
    rc = sqlite3_bind_int64(c->pStmt, 1, iDocid);
    if( rc!=SQLITE_OK ) return rc;
    /* TODO(shess) Handle SQLITE_SCHEMA AND SQLITE_BUSY. */
    rc = sqlite3_step(c->pStmt);
    if( rc==SQLITE_ROW ){   /* the case we expect */
      c->eof = 0;
      return SQLITE_OK;
    }
    /* an error occurred; abort */
    return rc==SQLITE_DONE ? SQLITE_ERROR : rc;
  }
}


/* Return a DocList corresponding to the query term *pTerm.  If *pTerm
** is the first term of a phrase query, go ahead and evaluate the phrase
** query and return the doclist for the entire phrase query.
**
** The result is stored in pTerm->doclist.
*/
static int docListOfTerm(
  fulltext_vtab *v,     /* The full text index */
  int iColumn,          /* column to restrict to.  No restrition if >=nColumn */
  QueryTerm *pQTerm,    /* Term we are looking for, or 1st term of a phrase */
  DocList **ppResult    /* Write the result here */
){
  DocList *pLeft, *pRight, *pNew;
  int i, rc;

  pLeft = docListNew(DL_POSITIONS);
  rc = term_select_all(v, iColumn, pQTerm->pTerm, pQTerm->nTerm, pLeft);
  if( rc ){
    docListDelete(pLeft);
    return rc;
  }
  for(i=1; i<=pQTerm->nPhrase; i++){
    pRight = docListNew(DL_POSITIONS);
    rc = term_select_all(v, iColumn, pQTerm[i].pTerm, pQTerm[i].nTerm, pRight);
    if( rc ){
      docListDelete(pLeft);
      return rc;
    }
    pNew = docListNew(i<pQTerm->nPhrase ? DL_POSITIONS : DL_DOCIDS);
    docListPhraseMerge(pLeft, pRight, pNew);
    docListDelete(pLeft);
    docListDelete(pRight);
    pLeft = pNew;
  }
  *ppResult = pLeft;
  return SQLITE_OK;
}

/* Add a new term pTerm[0..nTerm-1] to the query *q.
*/
static void queryAdd(Query *q, const char *pTerm, int nTerm){
  QueryTerm *t;
  ++q->nTerms;
  q->pTerms = realloc(q->pTerms, q->nTerms * sizeof(q->pTerms[0]));
  if( q->pTerms==0 ){
    q->nTerms = 0;
    return;
  }
  t = &q->pTerms[q->nTerms - 1];
  memset(t, 0, sizeof(*t));
  t->pTerm = malloc(nTerm+1);
  memcpy(t->pTerm, pTerm, nTerm);
  t->pTerm[nTerm] = 0;
  t->nTerm = nTerm;
  t->isOr = q->nextIsOr;
  q->nextIsOr = 0;
  t->iColumn = q->nextColumn;
  q->nextColumn = q->dfltColumn;
}

/*
** Check to see if the string zToken[0...nToken-1] matches any
** column name in the virtual table.   If it does,
** return the zero-indexed column number.  If not, return -1.
*/
static int checkColumnSpecifier(
  fulltext_vtab *pVtab,    /* The virtual table */
  const char *zToken,      /* Text of the token */
  int nToken               /* Number of characters in the token */
){
  int i;
  for(i=0; i<pVtab->nColumn; i++){
    if( memcmp(pVtab->azColumn[i], zToken, nToken)==0
        && pVtab->azColumn[i][nToken]==0 ){
      return i;
    }
  }
  return -1;
}

/*
** Parse the text at pSegment[0..nSegment-1].  Add additional terms
** to the query being assemblied in pQuery.
**
** inPhrase is true if pSegment[0..nSegement-1] is contained within
** double-quotes.  If inPhrase is true, then the first term
** is marked with the number of terms in the phrase less one and
** OR and "-" syntax is ignored.  If inPhrase is false, then every
** term found is marked with nPhrase=0 and OR and "-" syntax is significant.
*/
static int tokenizeSegment(
  sqlite3_tokenizer *pTokenizer,          /* The tokenizer to use */
  const char *pSegment, int nSegment,     /* Query expression being parsed */
  int inPhrase,                           /* True if within "..." */
  Query *pQuery                           /* Append results here */
){
  const sqlite3_tokenizer_module *pModule = pTokenizer->pModule;
  sqlite3_tokenizer_cursor *pCursor;
  int firstIndex = pQuery->nTerms;
  int iCol;
  int nTerm = 1;
  
  int rc = pModule->xOpen(pTokenizer, pSegment, nSegment, &pCursor);
  if( rc!=SQLITE_OK ) return rc;
  pCursor->pTokenizer = pTokenizer;

  while( 1 ){
    const char *pToken;
    int nToken, iBegin, iEnd, iPos;

    rc = pModule->xNext(pCursor,
                        &pToken, &nToken,
                        &iBegin, &iEnd, &iPos);
    if( rc!=SQLITE_OK ) break;
    if( !inPhrase &&
        pSegment[iEnd]==':' &&
         (iCol = checkColumnSpecifier(pQuery->pFts, pToken, nToken))>=0 ){
      pQuery->nextColumn = iCol;
      continue;
    }
    if( !inPhrase && pQuery->nTerms>0 && nToken==2
         && pSegment[iBegin]=='O' && pSegment[iBegin+1]=='R' ){
      pQuery->nextIsOr = 1;
      continue;
    }
    queryAdd(pQuery, pToken, nToken);
    if( !inPhrase && iBegin>0 && pSegment[iBegin-1]=='-' ){
      pQuery->pTerms[pQuery->nTerms-1].isNot = 1;
    }
    pQuery->pTerms[pQuery->nTerms-1].iPhrase = nTerm;
    if( inPhrase ){
      nTerm++;
    }
  }

  if( inPhrase && pQuery->nTerms>firstIndex ){
    pQuery->pTerms[firstIndex].nPhrase = pQuery->nTerms - firstIndex - 1;
  }

  return pModule->xClose(pCursor);
}

/* Parse a query string, yielding a Query object pQuery.
**
** The calling function will need to queryClear() to clean up
** the dynamically allocated memory held by pQuery.
*/
static int parseQuery(
  fulltext_vtab *v,        /* The fulltext index */
  const char *zInput,      /* Input text of the query string */
  int nInput,              /* Size of the input text */
  int dfltColumn,          /* Default column of the index to match against */
  Query *pQuery            /* Write the parse results here. */
){
  int iInput, inPhrase = 0;

  if( zInput==0 ) nInput = 0;
  if( nInput<0 ) nInput = strlen(zInput);
  pQuery->nTerms = 0;
  pQuery->pTerms = NULL;
  pQuery->nextIsOr = 0;
  pQuery->nextColumn = dfltColumn;
  pQuery->dfltColumn = dfltColumn;
  pQuery->pFts = v;

  for(iInput=0; iInput<nInput; ++iInput){
    int i;
    for(i=iInput; i<nInput && zInput[i]!='"'; ++i){}
    if( i>iInput ){
      tokenizeSegment(v->pTokenizer, zInput+iInput, i-iInput, inPhrase,
                       pQuery);
    }
    iInput = i;
    if( i<nInput ){
      assert( zInput[i]=='"' );
      inPhrase = !inPhrase;
    }
  }

  if( inPhrase ){
    /* unmatched quote */
    queryClear(pQuery);
    return SQLITE_ERROR;
  }
  return SQLITE_OK;
}

/* Perform a full-text query using the search expression in
** zInput[0..nInput-1].  Return a list of matching documents
** in pResult.
**
** Queries must match column iColumn.  Or if iColumn>=nColumn
** they are allowed to match against any column.
*/
static int fulltextQuery(
  fulltext_vtab *v,      /* The full text index */
  int iColumn,           /* Match against this column by default */
  const char *zInput,    /* The query string */
  int nInput,            /* Number of bytes in zInput[] */
  DocList **pResult,     /* Write the result doclist here */
  Query *pQuery          /* Put parsed query string here */
){
  int i, iNext, rc;
  DocList *pLeft = NULL;
  DocList *pRight, *pNew, *pOr;
  int nNot = 0;
  QueryTerm *aTerm;

  rc = parseQuery(v, zInput, nInput, iColumn, pQuery);
  if( rc!=SQLITE_OK ) return rc;

  /* Merge AND terms. */
  aTerm = pQuery->pTerms;
  for(i = 0; i<pQuery->nTerms; i=iNext){
    if( aTerm[i].isNot ){
      /* Handle all NOT terms in a separate pass */
      nNot++;
      iNext = i + aTerm[i].nPhrase+1;
      continue;
    }
    iNext = i + aTerm[i].nPhrase + 1;
    rc = docListOfTerm(v, aTerm[i].iColumn, &aTerm[i], &pRight);
    if( rc ){
      queryClear(pQuery);
      return rc;
    }
    while( iNext<pQuery->nTerms && aTerm[iNext].isOr ){
      rc = docListOfTerm(v, aTerm[iNext].iColumn, &aTerm[iNext], &pOr);
      iNext += aTerm[iNext].nPhrase + 1;
      if( rc ){
        queryClear(pQuery);
        return rc;
      }
      pNew = docListNew(DL_DOCIDS);
      docListOrMerge(pRight, pOr, pNew);
      docListDelete(pRight);
      docListDelete(pOr);
      pRight = pNew;
    }
    if( pLeft==0 ){
      pLeft = pRight;
    }else{
      pNew = docListNew(DL_DOCIDS);
      docListAndMerge(pLeft, pRight, pNew);
      docListDelete(pRight);
      docListDelete(pLeft);
      pLeft = pNew;
    }
  }

  if( nNot && pLeft==0 ){
    /* We do not yet know how to handle a query of only NOT terms */
    return SQLITE_ERROR;
  }

  /* Do the EXCEPT terms */
  for(i=0; i<pQuery->nTerms;  i += aTerm[i].nPhrase + 1){
    if( !aTerm[i].isNot ) continue;
    rc = docListOfTerm(v, aTerm[i].iColumn, &aTerm[i], &pRight);
    if( rc ){
      queryClear(pQuery);
      docListDelete(pLeft);
      return rc;
    }
    pNew = docListNew(DL_DOCIDS);
    docListExceptMerge(pLeft, pRight, pNew);
    docListDelete(pRight);
    docListDelete(pLeft);
    pLeft = pNew;
  }

  *pResult = pLeft;
  return rc;
}

/*
** This is the xFilter interface for the virtual table.  See
** the virtual table xFilter method documentation for additional
** information.
**
** If idxNum==QUERY_GENERIC then do a full table scan against
** the %_content table.
**
** If idxNum==QUERY_ROWID then do a rowid lookup for a single entry
** in the %_content table.
**
** If idxNum>=QUERY_FULLTEXT then use the full text index.  The
** column on the left-hand side of the MATCH operator is column
** number idxNum-QUERY_FULLTEXT, 0 indexed.  argv[0] is the right-hand
** side of the MATCH operator.
*/
/* TODO(shess) Upgrade the cursor initialization and destruction to
** account for fulltextFilter() being called multiple times on the
** same cursor.  The current solution is very fragile.  Apply fix to
** fts2 as appropriate.
*/
static int fulltextFilter(
  sqlite3_vtab_cursor *pCursor,     /* The cursor used for this query */
  int idxNum, const char *idxStr,   /* Which indexing scheme to use */
  int argc, sqlite3_value **argv    /* Arguments for the indexing scheme */
){
  fulltext_cursor *c = (fulltext_cursor *) pCursor;
  fulltext_vtab *v = cursor_vtab(c);
  int rc;
  char *zSql;

  TRACE(("FTS1 Filter %p\n",pCursor));

  zSql = sqlite3_mprintf("select rowid, * from %%_content %s",
                          idxNum==QUERY_GENERIC ? "" : "where rowid=?");
  sqlite3_finalize(c->pStmt);
  rc = sql_prepare(v->db, v->zDb, v->zName, &c->pStmt, zSql);
  sqlite3_free(zSql);
  if( rc!=SQLITE_OK ) return rc;

  c->iCursorType = idxNum;
  switch( idxNum ){
    case QUERY_GENERIC:
      break;

    case QUERY_ROWID:
      rc = sqlite3_bind_int64(c->pStmt, 1, sqlite3_value_int64(argv[0]));
      if( rc!=SQLITE_OK ) return rc;
      break;

    default:   /* full-text search */
    {
      const char *zQuery = (const char *)sqlite3_value_text(argv[0]);
      DocList *pResult;
      assert( idxNum<=QUERY_FULLTEXT+v->nColumn);
      assert( argc==1 );
      queryClear(&c->q);
      rc = fulltextQuery(v, idxNum-QUERY_FULLTEXT, zQuery, -1, &pResult, &c->q);
      if( rc!=SQLITE_OK ) return rc;
      if( c->result.pDoclist!=NULL ) docListDelete(c->result.pDoclist);
      readerInit(&c->result, pResult);
      break;
    }
  }

  return fulltextNext(pCursor);
}

/* This is the xEof method of the virtual table.  The SQLite core
** calls this routine to find out if it has reached the end of
** a query's results set.
*/
static int fulltextEof(sqlite3_vtab_cursor *pCursor){
  fulltext_cursor *c = (fulltext_cursor *) pCursor;
  return c->eof;
}

/* This is the xColumn method of the virtual table.  The SQLite
** core calls this method during a query when it needs the value
** of a column from the virtual table.  This method needs to use
** one of the sqlite3_result_*() routines to store the requested
** value back in the pContext.
*/
static int fulltextColumn(sqlite3_vtab_cursor *pCursor,
                          sqlite3_context *pContext, int idxCol){
  fulltext_cursor *c = (fulltext_cursor *) pCursor;
  fulltext_vtab *v = cursor_vtab(c);

  if( idxCol<v->nColumn ){
    sqlite3_value *pVal = sqlite3_column_value(c->pStmt, idxCol+1);
    sqlite3_result_value(pContext, pVal);
  }else if( idxCol==v->nColumn ){
    /* The extra column whose name is the same as the table.
    ** Return a blob which is a pointer to the cursor
    */
    sqlite3_result_blob(pContext, &c, sizeof(c), SQLITE_TRANSIENT);
  }
  return SQLITE_OK;
}

/* This is the xRowid method.  The SQLite core calls this routine to
** retrive the rowid for the current row of the result set.  The
** rowid should be written to *pRowid.
*/
static int fulltextRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
  fulltext_cursor *c = (fulltext_cursor *) pCursor;

  *pRowid = sqlite3_column_int64(c->pStmt, 0);
  return SQLITE_OK;
}

/* Add all terms in [zText] to the given hash table.  If [iColumn] > 0,
 * we also store positions and offsets in the hash table using the given
 * column number. */
static int buildTerms(fulltext_vtab *v, fts1Hash *terms, sqlite_int64 iDocid,
                      const char *zText, int iColumn){
  sqlite3_tokenizer *pTokenizer = v->pTokenizer;
  sqlite3_tokenizer_cursor *pCursor;
  const char *pToken;
  int nTokenBytes;
  int iStartOffset, iEndOffset, iPosition;
  int rc;

  rc = pTokenizer->pModule->xOpen(pTokenizer, zText, -1, &pCursor);
  if( rc!=SQLITE_OK ) return rc;

  pCursor->pTokenizer = pTokenizer;
  while( SQLITE_OK==pTokenizer->pModule->xNext(pCursor,
                                               &pToken, &nTokenBytes,
                                               &iStartOffset, &iEndOffset,
                                               &iPosition) ){
    DocList *p;

    /* Positions can't be negative; we use -1 as a terminator internally. */
    if( iPosition<0 ){
      pTokenizer->pModule->xClose(pCursor);
      return SQLITE_ERROR;
    }

    p = fts1HashFind(terms, pToken, nTokenBytes);
    if( p==NULL ){
      p = docListNew(DL_DEFAULT);
      docListAddDocid(p, iDocid);
      fts1HashInsert(terms, pToken, nTokenBytes, p);
    }
    if( iColumn>=0 ){
      docListAddPosOffset(p, iColumn, iPosition, iStartOffset, iEndOffset);
    }
  }

  /* TODO(shess) Check return?  Should this be able to cause errors at
  ** this point?  Actually, same question about sqlite3_finalize(),
  ** though one could argue that failure there means that the data is
  ** not durable.  *ponder*
  */
  pTokenizer->pModule->xClose(pCursor);
  return rc;
}

/* Update the %_terms table to map the term [pTerm] to the given rowid. */
static int index_insert_term(fulltext_vtab *v, const char *pTerm, int nTerm,
                             DocList *d){
  sqlite_int64 iIndexRow;
  DocList doclist;
  int iSegment = 0, rc;

  rc = term_select(v, pTerm, nTerm, iSegment, &iIndexRow, &doclist);
  if( rc==SQLITE_DONE ){
    docListInit(&doclist, DL_DEFAULT, 0, 0);
    docListUpdate(&doclist, d);
    /* TODO(shess) Consider length(doclist)>CHUNK_MAX? */
    rc = term_insert(v, NULL, pTerm, nTerm, iSegment, &doclist);
    goto err;
  }
  if( rc!=SQLITE_ROW ) return SQLITE_ERROR;

  docListUpdate(&doclist, d);
  if( doclist.nData<=CHUNK_MAX ){
    rc = term_update(v, iIndexRow, &doclist);
    goto err;
  }

  /* Doclist doesn't fit, delete what's there, and accumulate
  ** forward.
  */
  rc = term_delete(v, iIndexRow);
  if( rc!=SQLITE_OK ) goto err;

  /* Try to insert the doclist into a higher segment bucket.  On
  ** failure, accumulate existing doclist with the doclist from that
  ** bucket, and put results in the next bucket.
  */
  iSegment++;
  while( (rc=term_insert(v, &iIndexRow, pTerm, nTerm, iSegment,
                         &doclist))!=SQLITE_OK ){
    sqlite_int64 iSegmentRow;
    DocList old;
    int rc2;

    /* Retain old error in case the term_insert() error was really an
    ** error rather than a bounced insert.
    */
    rc2 = term_select(v, pTerm, nTerm, iSegment, &iSegmentRow, &old);
    if( rc2!=SQLITE_ROW ) goto err;

    rc = term_delete(v, iSegmentRow);
    if( rc!=SQLITE_OK ) goto err;

    /* Reusing lowest-number deleted row keeps the index smaller. */
    if( iSegmentRow<iIndexRow ) iIndexRow = iSegmentRow;

    /* doclist contains the newer data, so accumulate it over old.
    ** Then steal accumulated data for doclist.
    */
    docListAccumulate(&old, &doclist);
    docListDestroy(&doclist);
    doclist = old;

    iSegment++;
  }

 err:
  docListDestroy(&doclist);
  return rc;
}

/* Add doclists for all terms in [pValues] to the hash table [terms]. */
static int insertTerms(fulltext_vtab *v, fts1Hash *terms, sqlite_int64 iRowid,
                sqlite3_value **pValues){
  int i;
  for(i = 0; i < v->nColumn ; ++i){
    char *zText = (char*)sqlite3_value_text(pValues[i]);
    int rc = buildTerms(v, terms, iRowid, zText, i);
    if( rc!=SQLITE_OK ) return rc;
  }
  return SQLITE_OK;
}

/* Add empty doclists for all terms in the given row's content to the hash
 * table [pTerms]. */
static int deleteTerms(fulltext_vtab *v, fts1Hash *pTerms, sqlite_int64 iRowid){
  const char **pValues;
  int i;

  int rc = content_select(v, iRowid, &pValues);
  if( rc!=SQLITE_OK ) return rc;

  for(i = 0 ; i < v->nColumn; ++i) {
    rc = buildTerms(v, pTerms, iRowid, pValues[i], -1);
    if( rc!=SQLITE_OK ) break;
  }

  freeStringArray(v->nColumn, pValues);
  return SQLITE_OK;
}

/* Insert a row into the %_content table; set *piRowid to be the ID of the
 * new row.  Fill [pTerms] with new doclists for the %_term table. */
static int index_insert(fulltext_vtab *v, sqlite3_value *pRequestRowid,
                        sqlite3_value **pValues,
                        sqlite_int64 *piRowid, fts1Hash *pTerms){
  int rc;

  rc = content_insert(v, pRequestRowid, pValues);  /* execute an SQL INSERT */
  if( rc!=SQLITE_OK ) return rc;
  *piRowid = sqlite3_last_insert_rowid(v->db);
  return insertTerms(v, pTerms, *piRowid, pValues);
}

/* Delete a row from the %_content table; fill [pTerms] with empty doclists
 * to be written to the %_term table. */
static int index_delete(fulltext_vtab *v, sqlite_int64 iRow, fts1Hash *pTerms){
  int rc = deleteTerms(v, pTerms, iRow);
  if( rc!=SQLITE_OK ) return rc;
  return content_delete(v, iRow);  /* execute an SQL DELETE */
}

/* Update a row in the %_content table; fill [pTerms] with new doclists for the
 * %_term table. */
static int index_update(fulltext_vtab *v, sqlite_int64 iRow,
                        sqlite3_value **pValues, fts1Hash *pTerms){
  /* Generate an empty doclist for each term that previously appeared in this
   * row. */
  int rc = deleteTerms(v, pTerms, iRow);
  if( rc!=SQLITE_OK ) return rc;

  rc = content_update(v, pValues, iRow);  /* execute an SQL UPDATE */
  if( rc!=SQLITE_OK ) return rc;

  /* Now add positions for terms which appear in the updated row. */
  return insertTerms(v, pTerms, iRow, pValues);
}

/* This function implements the xUpdate callback; it is the top-level entry
 * point for inserting, deleting or updating a row in a full-text table. */
static int fulltextUpdate(sqlite3_vtab *pVtab, int nArg, sqlite3_value **ppArg,
                   sqlite_int64 *pRowid){
  fulltext_vtab *v = (fulltext_vtab *) pVtab;
  fts1Hash terms;   /* maps term string -> PosList */
  int rc;
  fts1HashElem *e;

  TRACE(("FTS1 Update %p\n", pVtab));
  
  fts1HashInit(&terms, FTS1_HASH_STRING, 1);

  if( nArg<2 ){
    rc = index_delete(v, sqlite3_value_int64(ppArg[0]), &terms);
  } else if( sqlite3_value_type(ppArg[0]) != SQLITE_NULL ){
    /* An update:
     * ppArg[0] = old rowid
     * ppArg[1] = new rowid
     * ppArg[2..2+v->nColumn-1] = values
     * ppArg[2+v->nColumn] = value for magic column (we ignore this)
     */
    sqlite_int64 rowid = sqlite3_value_int64(ppArg[0]);
    if( sqlite3_value_type(ppArg[1]) != SQLITE_INTEGER ||
      sqlite3_value_int64(ppArg[1]) != rowid ){
      rc = SQLITE_ERROR;  /* we don't allow changing the rowid */
    } else {
      assert( nArg==2+v->nColumn+1);
      rc = index_update(v, rowid, &ppArg[2], &terms);
    }
  } else {
    /* An insert:
     * ppArg[1] = requested rowid
     * ppArg[2..2+v->nColumn-1] = values
     * ppArg[2+v->nColumn] = value for magic column (we ignore this)
     */
    assert( nArg==2+v->nColumn+1);
    rc = index_insert(v, ppArg[1], &ppArg[2], pRowid, &terms);
  }

  if( rc==SQLITE_OK ){
    /* Write updated doclists to disk. */
    for(e=fts1HashFirst(&terms); e; e=fts1HashNext(e)){
      DocList *p = fts1HashData(e);
      rc = index_insert_term(v, fts1HashKey(e), fts1HashKeysize(e), p);
      if( rc!=SQLITE_OK ) break;
    }
  }

  /* clean up */
  for(e=fts1HashFirst(&terms); e; e=fts1HashNext(e)){
    DocList *p = fts1HashData(e);
    docListDelete(p);
  }
  fts1HashClear(&terms);

  return rc;
}

/*
** Implementation of the snippet() function for FTS1
*/
static void snippetFunc(
  sqlite3_context *pContext,
  int argc,
  sqlite3_value **argv
){
  fulltext_cursor *pCursor;
  if( argc<1 ) return;
  if( sqlite3_value_type(argv[0])!=SQLITE_BLOB ||
      sqlite3_value_bytes(argv[0])!=sizeof(pCursor) ){
    sqlite3_result_error(pContext, "illegal first argument to html_snippet",-1);
  }else{
    const char *zStart = "<b>";
    const char *zEnd = "</b>";
    const char *zEllipsis = "<b>...</b>";
    memcpy(&pCursor, sqlite3_value_blob(argv[0]), sizeof(pCursor));
    if( argc>=2 ){
      zStart = (const char*)sqlite3_value_text(argv[1]);
      if( argc>=3 ){
        zEnd = (const char*)sqlite3_value_text(argv[2]);
        if( argc>=4 ){
          zEllipsis = (const char*)sqlite3_value_text(argv[3]);
        }
      }
    }
    snippetAllOffsets(pCursor);
    snippetText(pCursor, zStart, zEnd, zEllipsis);
    sqlite3_result_text(pContext, pCursor->snippet.zSnippet,
                        pCursor->snippet.nSnippet, SQLITE_STATIC);
  }
}

/*
** Implementation of the offsets() function for FTS1
*/
static void snippetOffsetsFunc(
  sqlite3_context *pContext,
  int argc,
  sqlite3_value **argv
){
  fulltext_cursor *pCursor;
  if( argc<1 ) return;
  if( sqlite3_value_type(argv[0])!=SQLITE_BLOB ||
      sqlite3_value_bytes(argv[0])!=sizeof(pCursor) ){
    sqlite3_result_error(pContext, "illegal first argument to offsets",-1);
  }else{
    memcpy(&pCursor, sqlite3_value_blob(argv[0]), sizeof(pCursor));
    snippetAllOffsets(pCursor);
    snippetOffsetText(&pCursor->snippet);
    sqlite3_result_text(pContext,
                        pCursor->snippet.zOffset, pCursor->snippet.nOffset,
                        SQLITE_STATIC);
  }
}

/*
** This routine implements the xFindFunction method for the FTS1
** virtual table.
*/
static int fulltextFindFunction(
  sqlite3_vtab *pVtab,
  int nArg,
  const char *zName,
  void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
  void **ppArg
){
  if( strcmp(zName,"snippet")==0 ){
    *pxFunc = snippetFunc;
    return 1;
  }else if( strcmp(zName,"offsets")==0 ){
    *pxFunc = snippetOffsetsFunc;
    return 1;
  }
  return 0;
}

/*
** Rename an fts1 table.
*/
static int fulltextRename(
  sqlite3_vtab *pVtab,
  const char *zName
){
  fulltext_vtab *p = (fulltext_vtab *)pVtab;
  int rc = SQLITE_NOMEM;
  char *zSql = sqlite3_mprintf(
    "ALTER TABLE %Q.'%q_content'  RENAME TO '%q_content';"
    "ALTER TABLE %Q.'%q_term' RENAME TO '%q_term';"
    , p->zDb, p->zName, zName
    , p->zDb, p->zName, zName
  );
  if( zSql ){
    rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
    sqlite3_free(zSql);
  }
  return rc;
}

static const sqlite3_module fulltextModule = {
  /* iVersion      */ 0,
  /* xCreate       */ fulltextCreate,
  /* xConnect      */ fulltextConnect,
  /* xBestIndex    */ fulltextBestIndex,
  /* xDisconnect   */ fulltextDisconnect,
  /* xDestroy      */ fulltextDestroy,
  /* xOpen         */ fulltextOpen,
  /* xClose        */ fulltextClose,
  /* xFilter       */ fulltextFilter,
  /* xNext         */ fulltextNext,
  /* xEof          */ fulltextEof,
  /* xColumn       */ fulltextColumn,
  /* xRowid        */ fulltextRowid,
  /* xUpdate       */ fulltextUpdate,
  /* xBegin        */ 0, 
  /* xSync         */ 0,
  /* xCommit       */ 0,
  /* xRollback     */ 0,
  /* xFindFunction */ fulltextFindFunction,
  /* xRename       */ fulltextRename,
};

int sqlite3Fts1Init(sqlite3 *db){
  sqlite3_overload_function(db, "snippet", -1);
  sqlite3_overload_function(db, "offsets", -1);
  return sqlite3_create_module(db, "fts1", &fulltextModule, 0);
}

#if !SQLITE_CORE
#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_fts1_init(sqlite3 *db, char **pzErrMsg,
                      const sqlite3_api_routines *pApi){
  SQLITE_EXTENSION_INIT2(pApi)
  return sqlite3Fts1Init(db);
}
#endif

#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS1) */

Deleted ext/fts1/fts1.h.

1
2
3
4
5
6
7
8
9
10
11











-
-
-
-
-
-
-
-
-
-
-
#include "sqlite3.h"

#ifdef __cplusplus
extern "C" {
#endif  /* __cplusplus */

int sqlite3Fts1Init(sqlite3 *db);

#ifdef __cplusplus
}  /* extern "C" */
#endif  /* __cplusplus */

Deleted ext/fts1/fts1_hash.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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

















































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
** 2001 September 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 is the implementation of generic hash-tables used in SQLite.
** We've modified it slightly to serve as a standalone hash table
** implementation for the full-text indexing module.
*/
#include <assert.h>
#include <stdlib.h>
#include <string.h>

/*
** The code in this file is only compiled if:
**
**     * The FTS1 module is being built as an extension
**       (in which case SQLITE_CORE is not defined), or
**
**     * The FTS1 module is being built into the core of
**       SQLite (in which case SQLITE_ENABLE_FTS1 is defined).
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS1)


#include "fts1_hash.h"

static void *malloc_and_zero(int n){
  void *p = malloc(n);
  if( p ){
    memset(p, 0, n);
  }
  return p;
}

/* Turn bulk memory into a hash table object by initializing the
** fields of the Hash structure.
**
** "pNew" is a pointer to the hash table that is to be initialized.
** keyClass is one of the constants 
** FTS1_HASH_BINARY or FTS1_HASH_STRING.  The value of keyClass 
** determines what kind of key the hash table will use.  "copyKey" is
** true if the hash table should make its own private copy of keys and
** false if it should just use the supplied pointer.
*/
void sqlite3Fts1HashInit(fts1Hash *pNew, int keyClass, int copyKey){
  assert( pNew!=0 );
  assert( keyClass>=FTS1_HASH_STRING && keyClass<=FTS1_HASH_BINARY );
  pNew->keyClass = keyClass;
  pNew->copyKey = copyKey;
  pNew->first = 0;
  pNew->count = 0;
  pNew->htsize = 0;
  pNew->ht = 0;
  pNew->xMalloc = malloc_and_zero;
  pNew->xFree = free;
}

/* Remove all entries from a hash table.  Reclaim all memory.
** Call this routine to delete a hash table or to reset a hash table
** to the empty state.
*/
void sqlite3Fts1HashClear(fts1Hash *pH){
  fts1HashElem *elem;         /* For looping over all elements of the table */

  assert( pH!=0 );
  elem = pH->first;
  pH->first = 0;
  if( pH->ht ) pH->xFree(pH->ht);
  pH->ht = 0;
  pH->htsize = 0;
  while( elem ){
    fts1HashElem *next_elem = elem->next;
    if( pH->copyKey && elem->pKey ){
      pH->xFree(elem->pKey);
    }
    pH->xFree(elem);
    elem = next_elem;
  }
  pH->count = 0;
}

/*
** Hash and comparison functions when the mode is FTS1_HASH_STRING
*/
static int strHash(const void *pKey, int nKey){
  const char *z = (const char *)pKey;
  int h = 0;
  if( nKey<=0 ) nKey = (int) strlen(z);
  while( nKey > 0  ){
    h = (h<<3) ^ h ^ *z++;
    nKey--;
  }
  return h & 0x7fffffff;
}
static int strCompare(const void *pKey1, int n1, const void *pKey2, int n2){
  if( n1!=n2 ) return 1;
  return strncmp((const char*)pKey1,(const char*)pKey2,n1);
}

/*
** Hash and comparison functions when the mode is FTS1_HASH_BINARY
*/
static int binHash(const void *pKey, int nKey){
  int h = 0;
  const char *z = (const char *)pKey;
  while( nKey-- > 0 ){
    h = (h<<3) ^ h ^ *(z++);
  }
  return h & 0x7fffffff;
}
static int binCompare(const void *pKey1, int n1, const void *pKey2, int n2){
  if( n1!=n2 ) return 1;
  return memcmp(pKey1,pKey2,n1);
}

/*
** Return a pointer to the appropriate hash function given the key class.
**
** The C syntax in this function definition may be unfamilar to some 
** programmers, so we provide the following additional explanation:
**
** The name of the function is "hashFunction".  The function takes a
** single parameter "keyClass".  The return value of hashFunction()
** is a pointer to another function.  Specifically, the return value
** of hashFunction() is a pointer to a function that takes two parameters
** with types "const void*" and "int" and returns an "int".
*/
static int (*hashFunction(int keyClass))(const void*,int){
  if( keyClass==FTS1_HASH_STRING ){
    return &strHash;
  }else{
    assert( keyClass==FTS1_HASH_BINARY );
    return &binHash;
  }
}

/*
** Return a pointer to the appropriate hash function given the key class.
**
** For help in interpreted the obscure C code in the function definition,
** see the header comment on the previous function.
*/
static int (*compareFunction(int keyClass))(const void*,int,const void*,int){
  if( keyClass==FTS1_HASH_STRING ){
    return &strCompare;
  }else{
    assert( keyClass==FTS1_HASH_BINARY );
    return &binCompare;
  }
}

/* Link an element into the hash table
*/
static void insertElement(
  fts1Hash *pH,            /* The complete hash table */
  struct _fts1ht *pEntry,  /* The entry into which pNew is inserted */
  fts1HashElem *pNew       /* The element to be inserted */
){
  fts1HashElem *pHead;     /* First element already in pEntry */
  pHead = pEntry->chain;
  if( pHead ){
    pNew->next = pHead;
    pNew->prev = pHead->prev;
    if( pHead->prev ){ pHead->prev->next = pNew; }
    else             { pH->first = pNew; }
    pHead->prev = pNew;
  }else{
    pNew->next = pH->first;
    if( pH->first ){ pH->first->prev = pNew; }
    pNew->prev = 0;
    pH->first = pNew;
  }
  pEntry->count++;
  pEntry->chain = pNew;
}


/* Resize the hash table so that it cantains "new_size" buckets.
** "new_size" must be a power of 2.  The hash table might fail 
** to resize if sqliteMalloc() fails.
*/
static void rehash(fts1Hash *pH, int new_size){
  struct _fts1ht *new_ht;          /* The new hash table */
  fts1HashElem *elem, *next_elem;  /* For looping over existing elements */
  int (*xHash)(const void*,int);   /* The hash function */

  assert( (new_size & (new_size-1))==0 );
  new_ht = (struct _fts1ht *)pH->xMalloc( new_size*sizeof(struct _fts1ht) );
  if( new_ht==0 ) return;
  if( pH->ht ) pH->xFree(pH->ht);
  pH->ht = new_ht;
  pH->htsize = new_size;
  xHash = hashFunction(pH->keyClass);
  for(elem=pH->first, pH->first=0; elem; elem = next_elem){
    int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1);
    next_elem = elem->next;
    insertElement(pH, &new_ht[h], elem);
  }
}

/* This function (for internal use only) locates an element in an
** hash table that matches the given key.  The hash for this key has
** already been computed and is passed as the 4th parameter.
*/
static fts1HashElem *findElementGivenHash(
  const fts1Hash *pH, /* The pH to be searched */
  const void *pKey,   /* The key we are searching for */
  int nKey,
  int h               /* The hash for this key. */
){
  fts1HashElem *elem;            /* Used to loop thru the element list */
  int count;                     /* Number of elements left to test */
  int (*xCompare)(const void*,int,const void*,int);  /* comparison function */

  if( pH->ht ){
    struct _fts1ht *pEntry = &pH->ht[h];
    elem = pEntry->chain;
    count = pEntry->count;
    xCompare = compareFunction(pH->keyClass);
    while( count-- && elem ){
      if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){ 
        return elem;
      }
      elem = elem->next;
    }
  }
  return 0;
}

/* Remove a single entry from the hash table given a pointer to that
** element and a hash on the element's key.
*/
static void removeElementGivenHash(
  fts1Hash *pH,         /* The pH containing "elem" */
  fts1HashElem* elem,   /* The element to be removed from the pH */
  int h                 /* Hash value for the element */
){
  struct _fts1ht *pEntry;
  if( elem->prev ){
    elem->prev->next = elem->next; 
  }else{
    pH->first = elem->next;
  }
  if( elem->next ){
    elem->next->prev = elem->prev;
  }
  pEntry = &pH->ht[h];
  if( pEntry->chain==elem ){
    pEntry->chain = elem->next;
  }
  pEntry->count--;
  if( pEntry->count<=0 ){
    pEntry->chain = 0;
  }
  if( pH->copyKey && elem->pKey ){
    pH->xFree(elem->pKey);
  }
  pH->xFree( elem );
  pH->count--;
  if( pH->count<=0 ){
    assert( pH->first==0 );
    assert( pH->count==0 );
    fts1HashClear(pH);
  }
}

/* Attempt to locate an element of the hash table pH with a key
** that matches pKey,nKey.  Return the data for this element if it is
** found, or NULL if there is no match.
*/
void *sqlite3Fts1HashFind(const fts1Hash *pH, const void *pKey, int nKey){
  int h;                 /* A hash on key */
  fts1HashElem *elem;    /* The element that matches key */
  int (*xHash)(const void*,int);  /* The hash function */

  if( pH==0 || pH->ht==0 ) return 0;
  xHash = hashFunction(pH->keyClass);
  assert( xHash!=0 );
  h = (*xHash)(pKey,nKey);
  assert( (pH->htsize & (pH->htsize-1))==0 );
  elem = findElementGivenHash(pH,pKey,nKey, h & (pH->htsize-1));
  return elem ? elem->data : 0;
}

/* Insert an element into the hash table pH.  The key is pKey,nKey
** and the data is "data".
**
** If no element exists with a matching key, then a new
** element is created.  A copy of the key is made if the copyKey
** flag is set.  NULL is returned.
**
** If another element already exists with the same key, then the
** new data replaces the old data and the old data is returned.
** The key is not copied in this instance.  If a malloc fails, then
** the new data is returned and the hash table is unchanged.
**
** If the "data" parameter to this function is NULL, then the
** element corresponding to "key" is removed from the hash table.
*/
void *sqlite3Fts1HashInsert(
  fts1Hash *pH,        /* The hash table to insert into */
  const void *pKey,    /* The key */
  int nKey,            /* Number of bytes in the key */
  void *data           /* The data */
){
  int hraw;                 /* Raw hash value of the key */
  int h;                    /* the hash of the key modulo hash table size */
  fts1HashElem *elem;       /* Used to loop thru the element list */
  fts1HashElem *new_elem;   /* New element added to the pH */
  int (*xHash)(const void*,int);  /* The hash function */

  assert( pH!=0 );
  xHash = hashFunction(pH->keyClass);
  assert( xHash!=0 );
  hraw = (*xHash)(pKey, nKey);
  assert( (pH->htsize & (pH->htsize-1))==0 );
  h = hraw & (pH->htsize-1);
  elem = findElementGivenHash(pH,pKey,nKey,h);
  if( elem ){
    void *old_data = elem->data;
    if( data==0 ){
      removeElementGivenHash(pH,elem,h);
    }else{
      elem->data = data;
    }
    return old_data;
  }
  if( data==0 ) return 0;
  new_elem = (fts1HashElem*)pH->xMalloc( sizeof(fts1HashElem) );
  if( new_elem==0 ) return data;
  if( pH->copyKey && pKey!=0 ){
    new_elem->pKey = pH->xMalloc( nKey );
    if( new_elem->pKey==0 ){
      pH->xFree(new_elem);
      return data;
    }
    memcpy((void*)new_elem->pKey, pKey, nKey);
  }else{
    new_elem->pKey = (void*)pKey;
  }
  new_elem->nKey = nKey;
  pH->count++;
  if( pH->htsize==0 ){
    rehash(pH,8);
    if( pH->htsize==0 ){
      pH->count = 0;
      pH->xFree(new_elem);
      return data;
    }
  }
  if( pH->count > pH->htsize ){
    rehash(pH,pH->htsize*2);
  }
  assert( pH->htsize>0 );
  assert( (pH->htsize & (pH->htsize-1))==0 );
  h = hraw & (pH->htsize-1);
  insertElement(pH, &pH->ht[h], new_elem);
  new_elem->data = data;
  return 0;
}

#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS1) */

Deleted ext/fts1/fts1_hash.h.

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
















































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
** 2001 September 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 is the header file for the generic hash-table implementation
** used in SQLite.  We've modified it slightly to serve as a standalone
** hash table implementation for the full-text indexing module.
**
*/
#ifndef _FTS1_HASH_H_
#define _FTS1_HASH_H_

/* Forward declarations of structures. */
typedef struct fts1Hash fts1Hash;
typedef struct fts1HashElem fts1HashElem;

/* A complete hash table is an instance of the following structure.
** The internals of this structure are intended to be opaque -- client
** code should not attempt to access or modify the fields of this structure
** directly.  Change this structure only by using the routines below.
** However, many of the "procedures" and "functions" for modifying and
** accessing this structure are really macros, so we can't really make
** this structure opaque.
*/
struct fts1Hash {
  char keyClass;          /* HASH_INT, _POINTER, _STRING, _BINARY */
  char copyKey;           /* True if copy of key made on insert */
  int count;              /* Number of entries in this table */
  fts1HashElem *first;    /* The first element of the array */
  void *(*xMalloc)(int);  /* malloc() function to use */
  void (*xFree)(void *);  /* free() function to use */
  int htsize;             /* Number of buckets in the hash table */
  struct _fts1ht {        /* the hash table */
    int count;               /* Number of entries with this hash */
    fts1HashElem *chain;     /* Pointer to first entry with this hash */
  } *ht;
};

/* Each element in the hash table is an instance of the following 
** structure.  All elements are stored on a single doubly-linked list.
**
** Again, this structure is intended to be opaque, but it can't really
** be opaque because it is used by macros.
*/
struct fts1HashElem {
  fts1HashElem *next, *prev; /* Next and previous elements in the table */
  void *data;                /* Data associated with this element */
  void *pKey; int nKey;      /* Key associated with this element */
};

/*
** There are 2 different modes of operation for a hash table:
**
**   FTS1_HASH_STRING        pKey points to a string that is nKey bytes long
**                           (including the null-terminator, if any).  Case
**                           is respected in comparisons.
**
**   FTS1_HASH_BINARY        pKey points to binary data nKey bytes long. 
**                           memcmp() is used to compare keys.
**
** A copy of the key is made if the copyKey parameter to fts1HashInit is 1.  
*/
#define FTS1_HASH_STRING    1
#define FTS1_HASH_BINARY    2

/*
** Access routines.  To delete, insert a NULL pointer.
*/
void sqlite3Fts1HashInit(fts1Hash*, int keytype, int copyKey);
void *sqlite3Fts1HashInsert(fts1Hash*, const void *pKey, int nKey, void *pData);
void *sqlite3Fts1HashFind(const fts1Hash*, const void *pKey, int nKey);
void sqlite3Fts1HashClear(fts1Hash*);

/*
** Shorthand for the functions above
*/
#define fts1HashInit   sqlite3Fts1HashInit
#define fts1HashInsert sqlite3Fts1HashInsert
#define fts1HashFind   sqlite3Fts1HashFind
#define fts1HashClear  sqlite3Fts1HashClear

/*
** Macros for looping over all elements of a hash table.  The idiom is
** like this:
**
**   fts1Hash h;
**   fts1HashElem *p;
**   ...
**   for(p=fts1HashFirst(&h); p; p=fts1HashNext(p)){
**     SomeStructure *pData = fts1HashData(p);
**     // do something with pData
**   }
*/
#define fts1HashFirst(H)  ((H)->first)
#define fts1HashNext(E)   ((E)->next)
#define fts1HashData(E)   ((E)->data)
#define fts1HashKey(E)    ((E)->pKey)
#define fts1HashKeysize(E) ((E)->nKey)

/*
** Number of entries in a hash table
*/
#define fts1HashCount(H)  ((H)->count)

#endif /* _FTS1_HASH_H_ */

Deleted ext/fts1/fts1_porter.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
638
639
640
641
642
643



































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
** 2006 September 30
**
** 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.
**
*************************************************************************
** Implementation of the full-text-search tokenizer that implements
** a Porter stemmer.
*/

/*
** The code in this file is only compiled if:
**
**     * The FTS1 module is being built as an extension
**       (in which case SQLITE_CORE is not defined), or
**
**     * The FTS1 module is being built into the core of
**       SQLite (in which case SQLITE_ENABLE_FTS1 is defined).
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS1)


#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

#include "fts1_tokenizer.h"

/*
** Class derived from sqlite3_tokenizer
*/
typedef struct porter_tokenizer {
  sqlite3_tokenizer base;      /* Base class */
} porter_tokenizer;

/*
** Class derived from sqlit3_tokenizer_cursor
*/
typedef struct porter_tokenizer_cursor {
  sqlite3_tokenizer_cursor base;
  const char *zInput;          /* input we are tokenizing */
  int nInput;                  /* size of the input */
  int iOffset;                 /* current position in zInput */
  int iToken;                  /* index of next token to be returned */
  char *zToken;                /* storage for current token */
  int nAllocated;              /* space allocated to zToken buffer */
} porter_tokenizer_cursor;


/* Forward declaration */
static const sqlite3_tokenizer_module porterTokenizerModule;


/*
** Create a new tokenizer instance.
*/
static int porterCreate(
  int argc, const char * const *argv,
  sqlite3_tokenizer **ppTokenizer
){
  porter_tokenizer *t;
  t = (porter_tokenizer *) calloc(sizeof(*t), 1);
  if( t==NULL ) return SQLITE_NOMEM;

  *ppTokenizer = &t->base;
  return SQLITE_OK;
}

/*
** Destroy a tokenizer
*/
static int porterDestroy(sqlite3_tokenizer *pTokenizer){
  free(pTokenizer);
  return SQLITE_OK;
}

/*
** Prepare to begin tokenizing a particular string.  The input
** string to be tokenized is zInput[0..nInput-1].  A cursor
** used to incrementally tokenize this string is returned in 
** *ppCursor.
*/
static int porterOpen(
  sqlite3_tokenizer *pTokenizer,         /* The tokenizer */
  const char *zInput, int nInput,        /* String to be tokenized */
  sqlite3_tokenizer_cursor **ppCursor    /* OUT: Tokenization cursor */
){
  porter_tokenizer_cursor *c;

  c = (porter_tokenizer_cursor *) malloc(sizeof(*c));
  if( c==NULL ) return SQLITE_NOMEM;

  c->zInput = zInput;
  if( zInput==0 ){
    c->nInput = 0;
  }else if( nInput<0 ){
    c->nInput = (int)strlen(zInput);
  }else{
    c->nInput = nInput;
  }
  c->iOffset = 0;                 /* start tokenizing at the beginning */
  c->iToken = 0;
  c->zToken = NULL;               /* no space allocated, yet. */
  c->nAllocated = 0;

  *ppCursor = &c->base;
  return SQLITE_OK;
}

/*
** Close a tokenization cursor previously opened by a call to
** porterOpen() above.
*/
static int porterClose(sqlite3_tokenizer_cursor *pCursor){
  porter_tokenizer_cursor *c = (porter_tokenizer_cursor *) pCursor;
  free(c->zToken);
  free(c);
  return SQLITE_OK;
}
/*
** Vowel or consonant
*/
static const char cType[] = {
   0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0,
   1, 1, 1, 2, 1
};

/*
** isConsonant() and isVowel() determine if their first character in
** the string they point to is a consonant or a vowel, according
** to Porter ruls.  
**
** A consonate is any letter other than 'a', 'e', 'i', 'o', or 'u'.
** 'Y' is a consonant unless it follows another consonant,
** in which case it is a vowel.
**
** In these routine, the letters are in reverse order.  So the 'y' rule
** is that 'y' is a consonant unless it is followed by another
** consonent.
*/
static int isVowel(const char*);
static int isConsonant(const char *z){
  int j;
  char x = *z;
  if( x==0 ) return 0;
  assert( x>='a' && x<='z' );
  j = cType[x-'a'];
  if( j<2 ) return j;
  return z[1]==0 || isVowel(z + 1);
}
static int isVowel(const char *z){
  int j;
  char x = *z;
  if( x==0 ) return 0;
  assert( x>='a' && x<='z' );
  j = cType[x-'a'];
  if( j<2 ) return 1-j;
  return isConsonant(z + 1);
}

/*
** Let any sequence of one or more vowels be represented by V and let
** C be sequence of one or more consonants.  Then every word can be
** represented as:
**
**           [C] (VC){m} [V]
**
** In prose:  A word is an optional consonant followed by zero or
** vowel-consonant pairs followed by an optional vowel.  "m" is the
** number of vowel consonant pairs.  This routine computes the value
** of m for the first i bytes of a word.
**
** Return true if the m-value for z is 1 or more.  In other words,
** return true if z contains at least one vowel that is followed
** by a consonant.
**
** In this routine z[] is in reverse order.  So we are really looking
** for an instance of of a consonant followed by a vowel.
*/
static int m_gt_0(const char *z){
  while( isVowel(z) ){ z++; }
  if( *z==0 ) return 0;
  while( isConsonant(z) ){ z++; }
  return *z!=0;
}

/* Like mgt0 above except we are looking for a value of m which is
** exactly 1
*/
static int m_eq_1(const char *z){
  while( isVowel(z) ){ z++; }
  if( *z==0 ) return 0;
  while( isConsonant(z) ){ z++; }
  if( *z==0 ) return 0;
  while( isVowel(z) ){ z++; }
  if( *z==0 ) return 1;
  while( isConsonant(z) ){ z++; }
  return *z==0;
}

/* Like mgt0 above except we are looking for a value of m>1 instead
** or m>0
*/
static int m_gt_1(const char *z){
  while( isVowel(z) ){ z++; }
  if( *z==0 ) return 0;
  while( isConsonant(z) ){ z++; }
  if( *z==0 ) return 0;
  while( isVowel(z) ){ z++; }
  if( *z==0 ) return 0;
  while( isConsonant(z) ){ z++; }
  return *z!=0;
}

/*
** Return TRUE if there is a vowel anywhere within z[0..n-1]
*/
static int hasVowel(const char *z){
  while( isConsonant(z) ){ z++; }
  return *z!=0;
}

/*
** Return TRUE if the word ends in a double consonant.
**
** The text is reversed here. So we are really looking at
** the first two characters of z[].
*/
static int doubleConsonant(const char *z){
  return isConsonant(z) && z[0]==z[1] && isConsonant(z+1);
}

/*
** Return TRUE if the word ends with three letters which
** are consonant-vowel-consonent and where the final consonant
** is not 'w', 'x', or 'y'.
**
** The word is reversed here.  So we are really checking the
** first three letters and the first one cannot be in [wxy].
*/
static int star_oh(const char *z){
  return
    z[0]!=0 && isConsonant(z) &&
    z[0]!='w' && z[0]!='x' && z[0]!='y' &&
    z[1]!=0 && isVowel(z+1) &&
    z[2]!=0 && isConsonant(z+2);
}

/*
** If the word ends with zFrom and xCond() is true for the stem
** of the word that preceeds the zFrom ending, then change the 
** ending to zTo.
**
** The input word *pz and zFrom are both in reverse order.  zTo
** is in normal order. 
**
** Return TRUE if zFrom matches.  Return FALSE if zFrom does not
** match.  Not that TRUE is returned even if xCond() fails and
** no substitution occurs.
*/
static int stem(
  char **pz,             /* The word being stemmed (Reversed) */
  const char *zFrom,     /* If the ending matches this... (Reversed) */
  const char *zTo,       /* ... change the ending to this (not reversed) */
  int (*xCond)(const char*)   /* Condition that must be true */
){
  char *z = *pz;
  while( *zFrom && *zFrom==*z ){ z++; zFrom++; }
  if( *zFrom!=0 ) return 0;
  if( xCond && !xCond(z) ) return 1;
  while( *zTo ){
    *(--z) = *(zTo++);
  }
  *pz = z;
  return 1;
}

/*
** This is the fallback stemmer used when the porter stemmer is
** inappropriate.  The input word is copied into the output with
** US-ASCII case folding.  If the input word is too long (more
** than 20 bytes if it contains no digits or more than 6 bytes if
** it contains digits) then word is truncated to 20 or 6 bytes
** by taking 10 or 3 bytes from the beginning and end.
*/
static void copy_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){
  int i, mx, j;
  int hasDigit = 0;
  for(i=0; i<nIn; i++){
    int c = zIn[i];
    if( c>='A' && c<='Z' ){
      zOut[i] = c - 'A' + 'a';
    }else{
      if( c>='0' && c<='9' ) hasDigit = 1;
      zOut[i] = c;
    }
  }
  mx = hasDigit ? 3 : 10;
  if( nIn>mx*2 ){
    for(j=mx, i=nIn-mx; i<nIn; i++, j++){
      zOut[j] = zOut[i];
    }
    i = j;
  }
  zOut[i] = 0;
  *pnOut = i;
}


/*
** Stem the input word zIn[0..nIn-1].  Store the output in zOut.
** zOut is at least big enough to hold nIn bytes.  Write the actual
** size of the output word (exclusive of the '\0' terminator) into *pnOut.
**
** Any upper-case characters in the US-ASCII character set ([A-Z])
** are converted to lower case.  Upper-case UTF characters are
** unchanged.
**
** Words that are longer than about 20 bytes are stemmed by retaining
** a few bytes from the beginning and the end of the word.  If the
** word contains digits, 3 bytes are taken from the beginning and
** 3 bytes from the end.  For long words without digits, 10 bytes
** are taken from each end.  US-ASCII case folding still applies.
** 
** If the input word contains not digits but does characters not 
** in [a-zA-Z] then no stemming is attempted and this routine just 
** copies the input into the input into the output with US-ASCII
** case folding.
**
** Stemming never increases the length of the word.  So there is
** no chance of overflowing the zOut buffer.
*/
static void porter_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){
  int i, j, c;
  char zReverse[28];
  char *z, *z2;
  if( nIn<3 || nIn>=sizeof(zReverse)-7 ){
    /* The word is too big or too small for the porter stemmer.
    ** Fallback to the copy stemmer */
    copy_stemmer(zIn, nIn, zOut, pnOut);
    return;
  }
  for(i=0, j=sizeof(zReverse)-6; i<nIn; i++, j--){
    c = zIn[i];
    if( c>='A' && c<='Z' ){
      zReverse[j] = c + 'a' - 'A';
    }else if( c>='a' && c<='z' ){
      zReverse[j] = c;
    }else{
      /* The use of a character not in [a-zA-Z] means that we fallback
      ** to the copy stemmer */
      copy_stemmer(zIn, nIn, zOut, pnOut);
      return;
    }
  }
  memset(&zReverse[sizeof(zReverse)-5], 0, 5);
  z = &zReverse[j+1];


  /* Step 1a */
  if( z[0]=='s' ){
    if(
     !stem(&z, "sess", "ss", 0) &&
     !stem(&z, "sei", "i", 0)  &&
     !stem(&z, "ss", "ss", 0)
    ){
      z++;
    }
  }

  /* Step 1b */  
  z2 = z;
  if( stem(&z, "dee", "ee", m_gt_0) ){
    /* Do nothing.  The work was all in the test */
  }else if( 
     (stem(&z, "gni", "", hasVowel) || stem(&z, "de", "", hasVowel))
      && z!=z2
  ){
     if( stem(&z, "ta", "ate", 0) ||
         stem(&z, "lb", "ble", 0) ||
         stem(&z, "zi", "ize", 0) ){
       /* Do nothing.  The work was all in the test */
     }else if( doubleConsonant(z) && (*z!='l' && *z!='s' && *z!='z') ){
       z++;
     }else if( m_eq_1(z) && star_oh(z) ){
       *(--z) = 'e';
     }
  }

  /* Step 1c */
  if( z[0]=='y' && hasVowel(z+1) ){
    z[0] = 'i';
  }

  /* Step 2 */
  switch( z[1] ){
   case 'a':
     stem(&z, "lanoita", "ate", m_gt_0) ||
     stem(&z, "lanoit", "tion", m_gt_0);
     break;
   case 'c':
     stem(&z, "icne", "ence", m_gt_0) ||
     stem(&z, "icna", "ance", m_gt_0);
     break;
   case 'e':
     stem(&z, "rezi", "ize", m_gt_0);
     break;
   case 'g':
     stem(&z, "igol", "log", m_gt_0);
     break;
   case 'l':
     stem(&z, "ilb", "ble", m_gt_0) ||
     stem(&z, "illa", "al", m_gt_0) ||
     stem(&z, "iltne", "ent", m_gt_0) ||
     stem(&z, "ile", "e", m_gt_0) ||
     stem(&z, "ilsuo", "ous", m_gt_0);
     break;
   case 'o':
     stem(&z, "noitazi", "ize", m_gt_0) ||
     stem(&z, "noita", "ate", m_gt_0) ||
     stem(&z, "rota", "ate", m_gt_0);
     break;
   case 's':
     stem(&z, "msila", "al", m_gt_0) ||
     stem(&z, "ssenevi", "ive", m_gt_0) ||
     stem(&z, "ssenluf", "ful", m_gt_0) ||
     stem(&z, "ssensuo", "ous", m_gt_0);
     break;
   case 't':
     stem(&z, "itila", "al", m_gt_0) ||
     stem(&z, "itivi", "ive", m_gt_0) ||
     stem(&z, "itilib", "ble", m_gt_0);
     break;
  }

  /* Step 3 */
  switch( z[0] ){
   case 'e':
     stem(&z, "etaci", "ic", m_gt_0) ||
     stem(&z, "evita", "", m_gt_0)   ||
     stem(&z, "ezila", "al", m_gt_0);
     break;
   case 'i':
     stem(&z, "itici", "ic", m_gt_0);
     break;
   case 'l':
     stem(&z, "laci", "ic", m_gt_0) ||
     stem(&z, "luf", "", m_gt_0);
     break;
   case 's':
     stem(&z, "ssen", "", m_gt_0);
     break;
  }

  /* Step 4 */
  switch( z[1] ){
   case 'a':
     if( z[0]=='l' && m_gt_1(z+2) ){
       z += 2;
     }
     break;
   case 'c':
     if( z[0]=='e' && z[2]=='n' && (z[3]=='a' || z[3]=='e')  && m_gt_1(z+4)  ){
       z += 4;
     }
     break;
   case 'e':
     if( z[0]=='r' && m_gt_1(z+2) ){
       z += 2;
     }
     break;
   case 'i':
     if( z[0]=='c' && m_gt_1(z+2) ){
       z += 2;
     }
     break;
   case 'l':
     if( z[0]=='e' && z[2]=='b' && (z[3]=='a' || z[3]=='i') && m_gt_1(z+4) ){
       z += 4;
     }
     break;
   case 'n':
     if( z[0]=='t' ){
       if( z[2]=='a' ){
         if( m_gt_1(z+3) ){
           z += 3;
         }
       }else if( z[2]=='e' ){
         stem(&z, "tneme", "", m_gt_1) ||
         stem(&z, "tnem", "", m_gt_1) ||
         stem(&z, "tne", "", m_gt_1);
       }
     }
     break;
   case 'o':
     if( z[0]=='u' ){
       if( m_gt_1(z+2) ){
         z += 2;
       }
     }else if( z[3]=='s' || z[3]=='t' ){
       stem(&z, "noi", "", m_gt_1);
     }
     break;
   case 's':
     if( z[0]=='m' && z[2]=='i' && m_gt_1(z+3) ){
       z += 3;
     }
     break;
   case 't':
     stem(&z, "eta", "", m_gt_1) ||
     stem(&z, "iti", "", m_gt_1);
     break;
   case 'u':
     if( z[0]=='s' && z[2]=='o' && m_gt_1(z+3) ){
       z += 3;
     }
     break;
   case 'v':
   case 'z':
     if( z[0]=='e' && z[2]=='i' && m_gt_1(z+3) ){
       z += 3;
     }
     break;
  }

  /* Step 5a */
  if( z[0]=='e' ){
    if( m_gt_1(z+1) ){
      z++;
    }else if( m_eq_1(z+1) && !star_oh(z+1) ){
      z++;
    }
  }

  /* Step 5b */
  if( m_gt_1(z) && z[0]=='l' && z[1]=='l' ){
    z++;
  }

  /* z[] is now the stemmed word in reverse order.  Flip it back
  ** around into forward order and return.
  */
  *pnOut = i = strlen(z);
  zOut[i] = 0;
  while( *z ){
    zOut[--i] = *(z++);
  }
}

/*
** Characters that can be part of a token.  We assume any character
** whose value is greater than 0x80 (any UTF character) can be
** part of a token.  In other words, delimiters all must have
** values of 0x7f or lower.
*/
static const char isIdChar[] = {
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,  /* 3x */
    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 4x */
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,  /* 5x */
    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 6x */
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,  /* 7x */
};
#define idChar(C)  (((ch=C)&0x80)!=0 || (ch>0x2f && isIdChar[ch-0x30]))
#define isDelim(C) (((ch=C)&0x80)==0 && (ch<0x30 || !isIdChar[ch-0x30]))

/*
** Extract the next token from a tokenization cursor.  The cursor must
** have been opened by a prior call to porterOpen().
*/
static int porterNext(
  sqlite3_tokenizer_cursor *pCursor,  /* Cursor returned by porterOpen */
  const char **pzToken,               /* OUT: *pzToken is the token text */
  int *pnBytes,                       /* OUT: Number of bytes in token */
  int *piStartOffset,                 /* OUT: Starting offset of token */
  int *piEndOffset,                   /* OUT: Ending offset of token */
  int *piPosition                     /* OUT: Position integer of token */
){
  porter_tokenizer_cursor *c = (porter_tokenizer_cursor *) pCursor;
  const char *z = c->zInput;

  while( c->iOffset<c->nInput ){
    int iStartOffset, ch;

    /* Scan past delimiter characters */
    while( c->iOffset<c->nInput && isDelim(z[c->iOffset]) ){
      c->iOffset++;
    }

    /* Count non-delimiter characters. */
    iStartOffset = c->iOffset;
    while( c->iOffset<c->nInput && !isDelim(z[c->iOffset]) ){
      c->iOffset++;
    }

    if( c->iOffset>iStartOffset ){
      int n = c->iOffset-iStartOffset;
      if( n>c->nAllocated ){
        c->nAllocated = n+20;
        c->zToken = realloc(c->zToken, c->nAllocated);
        if( c->zToken==NULL ) return SQLITE_NOMEM;
      }
      porter_stemmer(&z[iStartOffset], n, c->zToken, pnBytes);
      *pzToken = c->zToken;
      *piStartOffset = iStartOffset;
      *piEndOffset = c->iOffset;
      *piPosition = c->iToken++;
      return SQLITE_OK;
    }
  }
  return SQLITE_DONE;
}

/*
** The set of routines that implement the porter-stemmer tokenizer
*/
static const sqlite3_tokenizer_module porterTokenizerModule = {
  0,
  porterCreate,
  porterDestroy,
  porterOpen,
  porterClose,
  porterNext,
};

/*
** Allocate a new porter tokenizer.  Return a pointer to the new
** tokenizer in *ppModule
*/
void sqlite3Fts1PorterTokenizerModule(
  sqlite3_tokenizer_module const**ppModule
){
  *ppModule = &porterTokenizerModule;
}

#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS1) */

Deleted ext/fts1/fts1_tokenizer.h.

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


























































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
** 2006 July 10
**
** The author disclaims copyright to this source code.
**
*************************************************************************
** Defines the interface to tokenizers used by fulltext-search.  There
** are three basic components:
**
** sqlite3_tokenizer_module is a singleton defining the tokenizer
** interface functions.  This is essentially the class structure for
** tokenizers.
**
** sqlite3_tokenizer is used to define a particular tokenizer, perhaps
** including customization information defined at creation time.
**
** sqlite3_tokenizer_cursor is generated by a tokenizer to generate
** tokens from a particular input.
*/
#ifndef _FTS1_TOKENIZER_H_
#define _FTS1_TOKENIZER_H_

/* TODO(shess) Only used for SQLITE_OK and SQLITE_DONE at this time.
** If tokenizers are to be allowed to call sqlite3_*() functions, then
** we will need a way to register the API consistently.
*/
#include "sqlite3.h"

/*
** Structures used by the tokenizer interface.
*/
typedef struct sqlite3_tokenizer sqlite3_tokenizer;
typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor;
typedef struct sqlite3_tokenizer_module sqlite3_tokenizer_module;

struct sqlite3_tokenizer_module {
  int iVersion;                  /* currently 0 */

  /*
  ** Create and destroy a tokenizer.  argc/argv are passed down from
  ** the fulltext virtual table creation to allow customization.
  */
  int (*xCreate)(int argc, const char *const*argv,
                 sqlite3_tokenizer **ppTokenizer);
  int (*xDestroy)(sqlite3_tokenizer *pTokenizer);

  /*
  ** Tokenize a particular input.  Call xOpen() to prepare to
  ** tokenize, xNext() repeatedly until it returns SQLITE_DONE, then
  ** xClose() to free any internal state.  The pInput passed to
  ** xOpen() must exist until the cursor is closed.  The ppToken
  ** result from xNext() is only valid until the next call to xNext()
  ** or until xClose() is called.
  */
  /* TODO(shess) current implementation requires pInput to be
  ** nul-terminated.  This should either be fixed, or pInput/nBytes
  ** should be converted to zInput.
  */
  int (*xOpen)(sqlite3_tokenizer *pTokenizer,
               const char *pInput, int nBytes,
               sqlite3_tokenizer_cursor **ppCursor);
  int (*xClose)(sqlite3_tokenizer_cursor *pCursor);
  int (*xNext)(sqlite3_tokenizer_cursor *pCursor,
               const char **ppToken, int *pnBytes,
               int *piStartOffset, int *piEndOffset, int *piPosition);
};

struct sqlite3_tokenizer {
  const sqlite3_tokenizer_module *pModule;  /* The module for this tokenizer */
  /* Tokenizer implementations will typically add additional fields */
};

struct sqlite3_tokenizer_cursor {
  sqlite3_tokenizer *pTokenizer;       /* Tokenizer for this cursor. */
  /* Tokenizer implementations will typically add additional fields */
};

/*
** Get the module for a tokenizer which generates tokens based on a
** set of non-token characters.  The default is to break tokens at any
** non-alnum character, though the set of delimiters can also be
** specified by the first argv argument to xCreate().
*/
/* TODO(shess) This doesn't belong here.  Need some sort of
** registration process.
*/
void sqlite3Fts1SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule);
void sqlite3Fts1PorterTokenizerModule(sqlite3_tokenizer_module const**ppModule);

#endif /* _FTS1_TOKENIZER_H_ */

Deleted ext/fts1/fts1_tokenizer1.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221





























































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
** The author disclaims copyright to this source code.
**
*************************************************************************
** Implementation of the "simple" full-text-search tokenizer.
*/

/*
** The code in this file is only compiled if:
**
**     * The FTS1 module is being built as an extension
**       (in which case SQLITE_CORE is not defined), or
**
**     * The FTS1 module is being built into the core of
**       SQLite (in which case SQLITE_ENABLE_FTS1 is defined).
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS1)


#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

#include "fts1_tokenizer.h"

typedef struct simple_tokenizer {
  sqlite3_tokenizer base;
  char delim[128];             /* flag ASCII delimiters */
} simple_tokenizer;

typedef struct simple_tokenizer_cursor {
  sqlite3_tokenizer_cursor base;
  const char *pInput;          /* input we are tokenizing */
  int nBytes;                  /* size of the input */
  int iOffset;                 /* current position in pInput */
  int iToken;                  /* index of next token to be returned */
  char *pToken;                /* storage for current token */
  int nTokenAllocated;         /* space allocated to zToken buffer */
} simple_tokenizer_cursor;


/* Forward declaration */
static const sqlite3_tokenizer_module simpleTokenizerModule;

static int isDelim(simple_tokenizer *t, unsigned char c){
  return c<0x80 && t->delim[c];
}

/*
** Create a new tokenizer instance.
*/
static int simpleCreate(
  int argc, const char * const *argv,
  sqlite3_tokenizer **ppTokenizer
){
  simple_tokenizer *t;

  t = (simple_tokenizer *) calloc(sizeof(*t), 1);
  if( t==NULL ) return SQLITE_NOMEM;

  /* TODO(shess) Delimiters need to remain the same from run to run,
  ** else we need to reindex.  One solution would be a meta-table to
  ** track such information in the database, then we'd only want this
  ** information on the initial create.
  */
  if( argc>1 ){
    int i, n = strlen(argv[1]);
    for(i=0; i<n; i++){
      unsigned char ch = argv[1][i];
      /* We explicitly don't support UTF-8 delimiters for now. */
      if( ch>=0x80 ){
        free(t);
        return SQLITE_ERROR;
      }
      t->delim[ch] = 1;
    }
  } else {
    /* Mark non-alphanumeric ASCII characters as delimiters */
    int i;
    for(i=1; i<0x80; i++){
      t->delim[i] = !isalnum(i);
    }
  }

  *ppTokenizer = &t->base;
  return SQLITE_OK;
}

/*
** Destroy a tokenizer
*/
static int simpleDestroy(sqlite3_tokenizer *pTokenizer){
  free(pTokenizer);
  return SQLITE_OK;
}

/*
** Prepare to begin tokenizing a particular string.  The input
** string to be tokenized is pInput[0..nBytes-1].  A cursor
** used to incrementally tokenize this string is returned in 
** *ppCursor.
*/
static int simpleOpen(
  sqlite3_tokenizer *pTokenizer,         /* The tokenizer */
  const char *pInput, int nBytes,        /* String to be tokenized */
  sqlite3_tokenizer_cursor **ppCursor    /* OUT: Tokenization cursor */
){
  simple_tokenizer_cursor *c;

  c = (simple_tokenizer_cursor *) malloc(sizeof(*c));
  if( c==NULL ) return SQLITE_NOMEM;

  c->pInput = pInput;
  if( pInput==0 ){
    c->nBytes = 0;
  }else if( nBytes<0 ){
    c->nBytes = (int)strlen(pInput);
  }else{
    c->nBytes = nBytes;
  }
  c->iOffset = 0;                 /* start tokenizing at the beginning */
  c->iToken = 0;
  c->pToken = NULL;               /* no space allocated, yet. */
  c->nTokenAllocated = 0;

  *ppCursor = &c->base;
  return SQLITE_OK;
}

/*
** Close a tokenization cursor previously opened by a call to
** simpleOpen() above.
*/
static int simpleClose(sqlite3_tokenizer_cursor *pCursor){
  simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor;
  free(c->pToken);
  free(c);
  return SQLITE_OK;
}

/*
** Extract the next token from a tokenization cursor.  The cursor must
** have been opened by a prior call to simpleOpen().
*/
static int simpleNext(
  sqlite3_tokenizer_cursor *pCursor,  /* Cursor returned by simpleOpen */
  const char **ppToken,               /* OUT: *ppToken is the token text */
  int *pnBytes,                       /* OUT: Number of bytes in token */
  int *piStartOffset,                 /* OUT: Starting offset of token */
  int *piEndOffset,                   /* OUT: Ending offset of token */
  int *piPosition                     /* OUT: Position integer of token */
){
  simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor;
  simple_tokenizer *t = (simple_tokenizer *) pCursor->pTokenizer;
  unsigned char *p = (unsigned char *)c->pInput;

  while( c->iOffset<c->nBytes ){
    int iStartOffset;

    /* Scan past delimiter characters */
    while( c->iOffset<c->nBytes && isDelim(t, p[c->iOffset]) ){
      c->iOffset++;
    }

    /* Count non-delimiter characters. */
    iStartOffset = c->iOffset;
    while( c->iOffset<c->nBytes && !isDelim(t, p[c->iOffset]) ){
      c->iOffset++;
    }

    if( c->iOffset>iStartOffset ){
      int i, n = c->iOffset-iStartOffset;
      if( n>c->nTokenAllocated ){
        c->nTokenAllocated = n+20;
        c->pToken = realloc(c->pToken, c->nTokenAllocated);
        if( c->pToken==NULL ) return SQLITE_NOMEM;
      }
      for(i=0; i<n; i++){
        /* TODO(shess) This needs expansion to handle UTF-8
        ** case-insensitivity.
        */
        unsigned char ch = p[iStartOffset+i];
        c->pToken[i] = ch<0x80 ? tolower(ch) : ch;
      }
      *ppToken = c->pToken;
      *pnBytes = n;
      *piStartOffset = iStartOffset;
      *piEndOffset = c->iOffset;
      *piPosition = c->iToken++;

      return SQLITE_OK;
    }
  }
  return SQLITE_DONE;
}

/*
** The set of routines that implement the simple tokenizer
*/
static const sqlite3_tokenizer_module simpleTokenizerModule = {
  0,
  simpleCreate,
  simpleDestroy,
  simpleOpen,
  simpleClose,
  simpleNext,
};

/*
** Allocate a new simple tokenizer.  Return a pointer to the new
** tokenizer in *ppModule
*/
void sqlite3Fts1SimpleTokenizerModule(
  sqlite3_tokenizer_module const**ppModule
){
  *ppModule = &simpleTokenizerModule;
}

#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS1) */

Deleted ext/fts1/fulltext.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511







































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/* The author disclaims copyright to this source code.
 *
 * This is an SQLite module implementing full-text search.
 */

#include <assert.h>
#if !defined(__APPLE__)
#include <malloc.h>
#else
#include <stdlib.h>
#endif
#include <stdio.h>
#include <string.h>
#include <ctype.h>

#include "fulltext.h"
#include "ft_hash.h"
#include "tokenizer.h"
#include "sqlite3.h"
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1

/* utility functions */

/* We encode variable-length integers in little-endian order using seven bits
 * per byte as follows:
**
** KEY:
**         A = 0xxxxxxx    7 bits of data and one flag bit
**         B = 1xxxxxxx    7 bits of data and one flag bit
**
**  7 bits - A
** 14 bits - BA
** 21 bits - BBA
** and so on.
*/

/* We may need up to VARINT_MAX bytes to store an encoded 64-bit integer. */
#define VARINT_MAX 10

/* Write a 64-bit variable-length integer to memory starting at p[0].
 * The length of data written will be between 1 and VARINT_MAX bytes.
 * The number of bytes written is returned. */
static int putVarint(char *p, sqlite_int64 v){
  unsigned char *q = (unsigned char *) p;
  sqlite_uint64 vu = v;
  do{
    *q++ = (unsigned char) ((vu & 0x7f) | 0x80);
    vu >>= 7;
  }while( vu!=0 );
  q[-1] &= 0x7f;  /* turn off high bit in final byte */
  assert( q - (unsigned char *)p <= VARINT_MAX );
  return (int) (q - (unsigned char *)p);
}

/* Read a 64-bit variable-length integer from memory starting at p[0].
 * Return the number of bytes read, or 0 on error.
 * The value is stored in *v. */
static int getVarint(const char *p, sqlite_int64 *v){
  const unsigned char *q = (const unsigned char *) p;
  sqlite_uint64 x = 0, y = 1;
  while( (*q & 0x80) == 0x80 ){
    x += y * (*q++ & 0x7f);
    y <<= 7;
    if( q - (unsigned char *)p >= VARINT_MAX ){  /* bad data */
      assert( 0 );
      return 0;
    }
  }
  x += y * (*q++);
  *v = (sqlite_int64) x;
  return (int) (q - (unsigned char *)p);
}

static int getVarint32(const char *p, int *pi){
 sqlite_int64 i;
 int ret = getVarint(p, &i);
 *pi = (int) i;
 assert( *pi==i );
 return ret;
}

/*** Document lists ***
 *
 * A document list holds a sorted list of varint-encoded document IDs.
 *
 * A doclist with type DL_POSITIONS_OFFSETS is stored like this:
 *
 * array {
 *   varint docid;
 *   array {
 *     varint position;     (delta from previous position plus 1, or 0 for end)
 *     varint startOffset;  (delta from previous startOffset)
 *     varint endOffset;    (delta from startOffset)
 *   }
 * }
 *
 * Here, array { X } means zero or more occurrences of X, adjacent in memory.
 *
 * A doclist with type DL_POSITIONS is like the above, but holds only docids
 * and positions without offset information.
 *
 * A doclist with type DL_DOCIDS is like the above, but holds only docids
 * without positions or offset information.
 *
 * On disk, every document list has positions and offsets, so we don't bother
 * to serialize a doclist's type.
 * 
 * We don't yet delta-encode document IDs; doing so will probably be a
 * modest win.
 *
 * NOTE(shess) I've thought of a slightly (1%) better offset encoding.
 * After the first offset, estimate the next offset by using the
 * current token position and the previous token position and offset,
 * offset to handle some variance.  So the estimate would be
 * (iPosition*w->iStartOffset/w->iPosition-64), which is delta-encoded
 * as normal.  Offsets more than 64 chars from the estimate are
 * encoded as the delta to the previous start offset + 128.  An
 * additional tiny increment can be gained by using the end offset of
 * the previous token to make the estimate a tiny bit more precise.
*/

typedef enum DocListType {
  DL_DOCIDS,              /* docids only */
  DL_POSITIONS,           /* docids + positions */
  DL_POSITIONS_OFFSETS    /* docids + positions + offsets */
} DocListType;

typedef struct DocList {
  char *pData;
  int nData;
  DocListType iType;
  int iLastPos;       /* the last position written */
  int iLastOffset;    /* the last start offset written */
} DocList;

/* Initialize a new DocList to hold the given data. */
static void docListInit(DocList *d, DocListType iType,
                        const char *pData, int nData){
  d->nData = nData;
  if( nData>0 ){
    d->pData = malloc(nData);
    memcpy(d->pData, pData, nData);
  } else {
    d->pData = NULL;
  }
  d->iType = iType;
  d->iLastPos = 0;
  d->iLastOffset = 0;
}

/* Create a new dynamically-allocated DocList. */
static DocList *docListNew(DocListType iType){
  DocList *d = (DocList *) malloc(sizeof(DocList));
  docListInit(d, iType, 0, 0);
  return d;
}

static void docListDestroy(DocList *d){
  free(d->pData);
#ifndef NDEBUG
  memset(d, 0x55, sizeof(*d));
#endif
}

static void docListDelete(DocList *d){
  docListDestroy(d);
  free(d);
}

static char *docListEnd(DocList *d){
  return d->pData + d->nData;
}

/* Append a varint to a DocList's data. */
static void appendVarint(DocList *d, sqlite_int64 i){
  char c[VARINT_MAX];
  int n = putVarint(c, i);
  d->pData = realloc(d->pData, d->nData + n);
  memcpy(d->pData + d->nData, c, n);
  d->nData += n;
}

static void docListAddDocid(DocList *d, sqlite_int64 iDocid){
  appendVarint(d, iDocid);
  d->iLastPos = 0;
}

/* Add a position to the last position list in a doclist. */
static void docListAddPos(DocList *d, int iPos){
  assert( d->iType>=DL_POSITIONS );
  appendVarint(d, iPos-d->iLastPos+1);
  d->iLastPos = iPos;
}

static void docListAddPosOffset(DocList *d, int iPos,
                                int iStartOffset, int iEndOffset){
  assert( d->iType==DL_POSITIONS_OFFSETS );
  docListAddPos(d, iPos);
  appendVarint(d, iStartOffset-d->iLastOffset);
  d->iLastOffset = iStartOffset;
  appendVarint(d, iEndOffset-iStartOffset);
}

/* Terminate the last position list in the given doclist. */
static void docListAddEndPos(DocList *d){
  appendVarint(d, 0);
}

typedef struct DocListReader {
  DocList *pDoclist;
  char *p;
  int iLastPos;    /* the last position read */
} DocListReader;

static void readerInit(DocListReader *r, DocList *pDoclist){
  r->pDoclist = pDoclist;
  if( pDoclist!=NULL ){
    r->p = pDoclist->pData;
  }
  r->iLastPos = 0;
}

static int readerAtEnd(DocListReader *pReader){
  return pReader->p >= docListEnd(pReader->pDoclist);
}

/* Peek at the next docid without advancing the read pointer. */
static sqlite_int64 peekDocid(DocListReader *pReader){
  sqlite_int64 ret;
  assert( !readerAtEnd(pReader) );
  getVarint(pReader->p, &ret);
  return ret;
}

/* Read the next docid. */
static sqlite_int64 readDocid(DocListReader *pReader){
  sqlite_int64 ret;
  assert( !readerAtEnd(pReader) );
  pReader->p += getVarint(pReader->p, &ret);
  pReader->iLastPos = 0;
  return ret;
}

/* Read the next position from a position list.
 * Returns the position, or -1 at the end of the list. */
static int readPosition(DocListReader *pReader){
  int i;
  int iType = pReader->pDoclist->iType;
  assert( iType>=DL_POSITIONS );
  assert( !readerAtEnd(pReader) );

  pReader->p += getVarint32(pReader->p, &i);
  if( i==0 ){
    pReader->iLastPos = -1;
    return -1;
  }
  pReader->iLastPos += ((int) i)-1;
  if( iType>=DL_POSITIONS_OFFSETS ){
    /* Skip over offsets, ignoring them for now. */
    int iStart, iEnd;
    pReader->p += getVarint32(pReader->p, &iStart);
    pReader->p += getVarint32(pReader->p, &iEnd);
  }
  return pReader->iLastPos;
}

/* Skip past the end of a position list. */
static void skipPositionList(DocListReader *pReader){
  while( readPosition(pReader)!=-1 )
    ;
}

/* Skip over a docid, including its position list if the doclist has
 * positions. */
static void skipDocument(DocListReader *pReader){
  readDocid(pReader);
  if( pReader->pDoclist->iType >= DL_POSITIONS ){
    skipPositionList(pReader);
  }
}

static sqlite_int64 firstDocid(DocList *d){
  DocListReader r;
  readerInit(&r, d);
  return readDocid(&r);
}

/* Doclist multi-tool.  Pass pUpdate==NULL to delete the indicated docid;
 * otherwise pUpdate, which must contain only the single docid [iDocid], is
 * inserted (if not present) or updated (if already present). */
static int docListUpdate(DocList *d, sqlite_int64 iDocid, DocList *pUpdate){
  int modified = 0;
  DocListReader reader;
  char *p;

  if( pUpdate!=NULL ){
    assert( d->iType==pUpdate->iType);
    assert( iDocid==firstDocid(pUpdate) );
  }

  readerInit(&reader, d);
  while( !readerAtEnd(&reader) && peekDocid(&reader)<iDocid ){
    skipDocument(&reader);
  }

  p = reader.p;
  /* Delete if there is a matching element. */
  if( !readerAtEnd(&reader) && iDocid==peekDocid(&reader) ){
    skipDocument(&reader);
    memmove(p, reader.p, docListEnd(d) - reader.p);
    d->nData -= (reader.p - p);
    modified = 1;
  }

  /* Insert if indicated. */
  if( pUpdate!=NULL ){
    int iDoclist = p-d->pData;
    docListAddEndPos(pUpdate);

    d->pData = realloc(d->pData, d->nData+pUpdate->nData);
    p = d->pData + iDoclist;

    memmove(p+pUpdate->nData, p, docListEnd(d) - p);
    memcpy(p, pUpdate->pData, pUpdate->nData);
    d->nData += pUpdate->nData;
    modified = 1;
  }

  return modified;
}

/* Split the second half of doclist d into a separate doclist d2.  Returns 1
 * if successful, or 0 if d contains a single document and hence can't be
 * split. */
static int docListSplit(DocList *d, DocList *d2){
  const char *pSplitPoint = d->pData + d->nData / 2;
  DocListReader reader;

  readerInit(&reader, d);
  while( reader.p<pSplitPoint ){
    skipDocument(&reader);
  }
  if( readerAtEnd(&reader) ) return 0;
  docListInit(d2, d->iType, reader.p, docListEnd(d) - reader.p);
  d->nData = reader.p - d->pData;
  d->pData = realloc(d->pData, d->nData);
  return 1;
}

/* A DocListMerge computes the AND of an in-memory DocList [in] and a chunked
 * on-disk doclist, resulting in another in-memory DocList [out].  [in]
 * and [out] may or may not store position information according to the
 * caller's wishes.  The on-disk doclist always comes with positions.
 *
 * The caller must read each chunk of the on-disk doclist in succession and
 * pass it to mergeBlock().
 *
 * If [in] has positions, then the merge output contains only documents with
 * matching positions in the two input doclists.  If [in] does not have
 * positions, then the merge output contains all documents common to the two
 * input doclists.
 *
 * If [in] is NULL, then the on-disk doclist is copied to [out] directly.
 *
 * A merge is performed using an integer [iOffset] provided by the caller.
 * [iOffset] is subtracted from each position in the on-disk doclist for the
 * purpose of position comparison; this is helpful in implementing phrase
 * searches.
 *
 * A DocListMerge is not yet able to propagate offsets through query
 * processing; we should add that capability soon.
*/
typedef struct DocListMerge {
  DocListReader in;
  DocList *pOut;
  int iOffset;
} DocListMerge;

static void mergeInit(DocListMerge *m,
                      DocList *pIn, int iOffset, DocList *pOut){
  readerInit(&m->in, pIn);
  m->pOut = pOut;
  m->iOffset = iOffset;

  /* can't handle offsets yet */
  assert( pIn==NULL || pIn->iType <= DL_POSITIONS );
  assert( pOut->iType <= DL_POSITIONS );
}

/* A helper function for mergeBlock(), below.  Merge the position lists
 * pointed to by m->in and pBlockReader.
 * If the merge matches, write [iDocid] to m->pOut; if m->pOut
 * has positions then write all matching positions as well. */
static void mergePosList(DocListMerge *m, sqlite_int64 iDocid,
                  DocListReader *pBlockReader){
  int block_pos = readPosition(pBlockReader);
  int in_pos = readPosition(&m->in);
  int match = 0;
  while( block_pos!=-1 || in_pos!=-1 ){
    if( block_pos-m->iOffset==in_pos ){
      if( !match ){
        docListAddDocid(m->pOut, iDocid);
        match = 1;
      }
      if( m->pOut->iType >= DL_POSITIONS ){
        docListAddPos(m->pOut, in_pos);
      }
      block_pos = readPosition(pBlockReader);
      in_pos = readPosition(&m->in);
    } else if( in_pos==-1 || (block_pos!=-1 && block_pos-m->iOffset<in_pos) ){
      block_pos = readPosition(pBlockReader);
    } else {
      in_pos = readPosition(&m->in);
    }
  }
  if( m->pOut->iType >= DL_POSITIONS && match ){
    docListAddEndPos(m->pOut);
  }
}

/* Merge one block of an on-disk doclist into a DocListMerge. */
static void mergeBlock(DocListMerge *m, DocList *pBlock){
  DocListReader blockReader;
  assert( pBlock->iType >= DL_POSITIONS );
  readerInit(&blockReader, pBlock);
  while( !readerAtEnd(&blockReader) ){
    sqlite_int64 iDocid = readDocid(&blockReader);
    if( m->in.pDoclist!=NULL ){
      while( 1 ){
        if( readerAtEnd(&m->in) ) return;  /* nothing more to merge */
        if( peekDocid(&m->in)>=iDocid ) break;
        skipDocument(&m->in);
      }
      if( peekDocid(&m->in)>iDocid ){  /* [pIn] has no match with iDocid */
        skipPositionList(&blockReader);  /* skip this docid in the block */
        continue;
      }
      readDocid(&m->in);
    }
    /* We have a document match. */
    if( m->in.pDoclist==NULL || m->in.pDoclist->iType < DL_POSITIONS ){
      /* We don't need to do a poslist merge. */
      docListAddDocid(m->pOut, iDocid);
      if( m->pOut->iType >= DL_POSITIONS ){
        /* Copy all positions to the output doclist. */
        while( 1 ){
          int pos = readPosition(&blockReader);
          if( pos==-1 ) break;
          docListAddPos(m->pOut, pos);
        }
        docListAddEndPos(m->pOut);
      } else skipPositionList(&blockReader);
      continue;
    }
    mergePosList(m, iDocid, &blockReader);
  }
}

static char *string_dup_n(const char *s, int n){
  char *str = malloc(n + 1);
  memcpy(str, s, n);
  str[n] = '\0';
  return str;
}

/* Duplicate a string; the caller must free() the returned string.
 * (We don't use strdup() since it's not part of the standard C library and
 * may not be available everywhere.) */
static char *string_dup(const char *s){
  return string_dup_n(s, strlen(s));
}

/* Format a string, replacing each occurrence of the % character with
 * zName.  This may be more convenient than sqlite_mprintf()
 * when one string is used repeatedly in a format string.
 * The caller must free() the returned string. */
static char *string_format(const char *zFormat, const char *zName){
  const char *p;
  size_t len = 0;
  size_t nName = strlen(zName);
  char *result;
  char *r;

  /* first compute length needed */
  for(p = zFormat ; *p ; ++p){
    len += (*p=='%' ? nName : 1);
  }
  len += 1;  /* for null terminator */

  r = result = malloc(len);
  for(p = zFormat; *p; ++p){
    if( *p=='%' ){
      memcpy(r, zName, nName);
      r += nName;
    } else {
      *r++ = *p;
    }
  }
  *r++ = '\0';
  assert( r == result + len );
  return result;
}

static int sql_exec(sqlite3 *db, const char *zName, const char *zFormat){
  char *zCommand = string_format(zFormat, zName);
  int rc = sqlite3_exec(db, zCommand, NULL, 0, NULL);
  free(zCommand);
  return rc;
}

static int sql_prepare(sqlite3 *db, const char *zName, sqlite3_stmt **ppStmt,
                const char *zFormat){
  char *zCommand = string_format(zFormat, zName);
  int rc = sqlite3_prepare(db, zCommand, -1, ppStmt, NULL);
  free(zCommand);
  return rc;
}

/* end utility functions */

#define QUERY_GENERIC 0
#define QUERY_FULLTEXT 1

#define CHUNK_MAX 1024

typedef enum fulltext_statement {
  CONTENT_INSERT_STMT,
  CONTENT_SELECT_STMT,
  CONTENT_DELETE_STMT,

  TERM_SELECT_STMT,
  TERM_CHUNK_SELECT_STMT,
  TERM_INSERT_STMT,
  TERM_UPDATE_STMT,
  TERM_DELETE_STMT,

  MAX_STMT                     /* Always at end! */
} fulltext_statement;

/* These must exactly match the enum above. */
/* TODO(adam): Is there some risk that a statement (in particular,
** pTermSelectStmt) will be used in two cursors at once, e.g.  if a
** query joins a virtual table to itself?  If so perhaps we should
** move some of these to the cursor object.
*/
static const char *fulltext_zStatement[MAX_STMT] = {
  /* CONTENT_INSERT */ "insert into %_content (rowid, content) values (?, ?)",
  /* CONTENT_SELECT */ "select content from %_content where rowid = ?",
  /* CONTENT_DELETE */ "delete from %_content where rowid = ?",

  /* TERM_SELECT */
  "select rowid, doclist from %_term where term = ? and first = ?",
  /* TERM_CHUNK_SELECT */
  "select max(first) from %_term where term = ? and first <= ?",
  /* TERM_INSERT */
  "insert into %_term (term, first, doclist) values (?, ?, ?)",
  /* TERM_UPDATE */ "update %_term set doclist = ? where rowid = ?",
  /* TERM_DELETE */ "delete from %_term where rowid = ?",
};

typedef struct fulltext_vtab {
  sqlite3_vtab base;
  sqlite3 *db;
  const char *zName;               /* virtual table name */
  sqlite3_tokenizer *pTokenizer;   /* tokenizer for inserts and queries */

  /* Precompiled statements which we keep as long as the table is
  ** open.
  */
  sqlite3_stmt *pFulltextStatements[MAX_STMT];
} fulltext_vtab;

typedef struct fulltext_cursor {
  sqlite3_vtab_cursor base;
  int iCursorType;  /* QUERY_GENERIC or QUERY_FULLTEXT */

  sqlite3_stmt *pStmt;

  int eof;

  /* The following is used only when iCursorType == QUERY_FULLTEXT. */
  DocListReader result;
} fulltext_cursor;

static struct fulltext_vtab *cursor_vtab(fulltext_cursor *c){
  return (fulltext_vtab *) c->base.pVtab;
}

static sqlite3_module fulltextModule;   /* forward declaration */

/* Puts a freshly-prepared statement determined by iStmt in *ppStmt.
** If the indicated statement has never been prepared, it is prepared
** and cached, otherwise the cached version is reset.
*/
static int sql_get_statement(fulltext_vtab *v, fulltext_statement iStmt,
                             sqlite3_stmt **ppStmt){
  assert( iStmt<MAX_STMT );
  if( v->pFulltextStatements[iStmt]==NULL ){
    int rc = sql_prepare(v->db, v->zName, &v->pFulltextStatements[iStmt],
                         fulltext_zStatement[iStmt]);
    if( rc!=SQLITE_OK ) return rc;
  } else {
    int rc = sqlite3_reset(v->pFulltextStatements[iStmt]);
    if( rc!=SQLITE_OK ) return rc;
  }

  *ppStmt = v->pFulltextStatements[iStmt];
  return SQLITE_OK;
}

/* Step the indicated statement, handling errors SQLITE_BUSY (by
** retrying) and SQLITE_SCHEMA (by re-preparing and transferring
** bindings to the new statement).
** TODO(adam): We should extend this function so that it can work with
** statements declared locally, not only globally cached statements.
*/
static int sql_step_statement(fulltext_vtab *v, fulltext_statement iStmt,
                              sqlite3_stmt **ppStmt){
  int rc;
  sqlite3_stmt *s = *ppStmt;
  assert( iStmt<MAX_STMT );
  assert( s==v->pFulltextStatements[iStmt] );

  while( (rc=sqlite3_step(s))!=SQLITE_DONE && rc!=SQLITE_ROW ){
    sqlite3_stmt *pNewStmt;

    if( rc==SQLITE_BUSY ) continue;
    if( rc!=SQLITE_ERROR ) return rc;

    rc = sqlite3_reset(s);
    if( rc!=SQLITE_SCHEMA ) return SQLITE_ERROR;

    v->pFulltextStatements[iStmt] = NULL;   /* Still in s */
    rc = sql_get_statement(v, iStmt, &pNewStmt);
    if( rc!=SQLITE_OK ) goto err;
    *ppStmt = pNewStmt;

    rc = sqlite3_transfer_bindings(s, pNewStmt);
    if( rc!=SQLITE_OK ) goto err;

    rc = sqlite3_finalize(s);
    if( rc!=SQLITE_OK ) return rc;
    s = pNewStmt;
  }
  return rc;

 err:
  sqlite3_finalize(s);
  return rc;
}

/* Like sql_step_statement(), but convert SQLITE_DONE to SQLITE_OK.
** Useful for statements like UPDATE, where we expect no results.
*/
static int sql_single_step_statement(fulltext_vtab *v,
                                     fulltext_statement iStmt,
                                     sqlite3_stmt **ppStmt){
  int rc = sql_step_statement(v, iStmt, ppStmt);
  return (rc==SQLITE_DONE) ? SQLITE_OK : rc;
}

/* insert into %_content (rowid, content) values ([rowid], [zContent]) */
static int content_insert(fulltext_vtab *v, sqlite3_value *rowid,
                          const char *zContent, int nContent){
  sqlite3_stmt *s;
  int rc = sql_get_statement(v, CONTENT_INSERT_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_value(s, 1, rowid);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_text(s, 2, zContent, nContent, SQLITE_STATIC);
  if( rc!=SQLITE_OK ) return rc;

  return sql_single_step_statement(v, CONTENT_INSERT_STMT, &s);
}

/* select content from %_content where rowid = [iRow]
 * The caller must delete the returned string. */
static int content_select(fulltext_vtab *v, sqlite_int64 iRow,
                          char **pzContent){
  sqlite3_stmt *s;
  int rc = sql_get_statement(v, CONTENT_SELECT_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_int64(s, 1, iRow);
  if( rc!=SQLITE_OK ) return rc;

  rc = sql_step_statement(v, CONTENT_SELECT_STMT, &s);
  if( rc!=SQLITE_ROW ) return rc;

  *pzContent = string_dup((const char *)sqlite3_column_text(s, 0));

  /* We expect only one row.  We must execute another sqlite3_step()
   * to complete the iteration; otherwise the table will remain locked. */
  rc = sqlite3_step(s);
  if( rc==SQLITE_DONE ) return SQLITE_OK;

  free(*pzContent);
  return rc;
}

/* delete from %_content where rowid = [iRow ] */
static int content_delete(fulltext_vtab *v, sqlite_int64 iRow){
  sqlite3_stmt *s;
  int rc = sql_get_statement(v, CONTENT_DELETE_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_int64(s, 1, iRow);
  if( rc!=SQLITE_OK ) return rc;

  return sql_single_step_statement(v, CONTENT_DELETE_STMT, &s);
}

/* select rowid, doclist from %_term where term = [zTerm] and first = [iFirst]
 * If found, returns SQLITE_OK; the caller must free the returned doclist.
 * If no rows found, returns SQLITE_ERROR. */
static int term_select(fulltext_vtab *v, const char *zTerm, int nTerm,
                       sqlite_int64 iFirst,
                       sqlite_int64 *rowid,
                       DocList *out){
  sqlite3_stmt *s;
  int rc = sql_get_statement(v, TERM_SELECT_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_text(s, 1, zTerm, nTerm, SQLITE_TRANSIENT);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_int64(s, 2, iFirst);
  if( rc!=SQLITE_OK ) return rc;

  rc = sql_step_statement(v, TERM_SELECT_STMT, &s);
  if( rc!=SQLITE_ROW ) return rc==SQLITE_DONE ? SQLITE_ERROR : rc;

  *rowid = sqlite3_column_int64(s, 0);
  docListInit(out, DL_POSITIONS_OFFSETS,
              sqlite3_column_blob(s, 1), sqlite3_column_bytes(s, 1));

  /* We expect only one row.  We must execute another sqlite3_step()
   * to complete the iteration; otherwise the table will remain locked. */
  rc = sqlite3_step(s);
  return rc==SQLITE_DONE ? SQLITE_OK : rc;
}

/* select max(first) from %_term where term = [zTerm] and first <= [iFirst]
 * If found, returns SQLITE_ROW and result in *piResult; if the query returns
 * NULL (meaning no row found) returns SQLITE_DONE.
 */
static int term_chunk_select(fulltext_vtab *v, const char *zTerm, int nTerm,
                           sqlite_int64 iFirst, sqlite_int64 *piResult){
  sqlite3_stmt *s;
  int rc = sql_get_statement(v, TERM_CHUNK_SELECT_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_text(s, 1, zTerm, nTerm, SQLITE_STATIC);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_int64(s, 2, iFirst);
  if( rc!=SQLITE_OK ) return rc;

  rc = sql_step_statement(v, TERM_CHUNK_SELECT_STMT, &s);
  if( rc!=SQLITE_ROW ) return rc==SQLITE_DONE ? SQLITE_ERROR : rc;

  switch( sqlite3_column_type(s, 0) ){
    case SQLITE_NULL:
      rc = SQLITE_DONE;
      break;
    case SQLITE_INTEGER:
     *piResult = sqlite3_column_int64(s, 0);
     break;
    default:
      return SQLITE_ERROR;
  }
  /* We expect only one row.  We must execute another sqlite3_step()
   * to complete the iteration; otherwise the table will remain locked. */
  if( sqlite3_step(s) != SQLITE_DONE ) return SQLITE_ERROR;
  return rc;
}

/* insert into %_term (term, first, doclist)
               values ([zTerm], [iFirst], [doclist]) */
static int term_insert(fulltext_vtab *v, const char *zTerm, int nTerm,
                       sqlite_int64 iFirst, DocList *doclist){
  sqlite3_stmt *s;
  int rc = sql_get_statement(v, TERM_INSERT_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_text(s, 1, zTerm, nTerm, SQLITE_STATIC);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_int64(s, 2, iFirst);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_blob(s, 3, doclist->pData, doclist->nData, SQLITE_STATIC);
  if( rc!=SQLITE_OK ) return rc;

  return sql_single_step_statement(v, TERM_INSERT_STMT, &s);
}

/* update %_term set doclist = [doclist] where rowid = [rowid] */
static int term_update(fulltext_vtab *v, sqlite_int64 rowid,
                       DocList *doclist){
  sqlite3_stmt *s;
  int rc = sql_get_statement(v, TERM_UPDATE_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_blob(s, 1, doclist->pData, doclist->nData,
                         SQLITE_STATIC);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_int64(s, 2, rowid);
  if( rc!=SQLITE_OK ) return rc;

  return sql_single_step_statement(v, TERM_UPDATE_STMT, &s);
}

static int term_delete(fulltext_vtab *v, sqlite_int64 rowid){
  sqlite3_stmt *s;
  int rc = sql_get_statement(v, TERM_DELETE_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_int64(s, 1, rowid);
  if( rc!=SQLITE_OK ) return rc;

  return sql_single_step_statement(v, TERM_DELETE_STMT, &s);
}

static void fulltext_vtab_destroy(fulltext_vtab *v){
  int iStmt;

  for( iStmt=0; iStmt<MAX_STMT; iStmt++ ){
    if( v->pFulltextStatements[iStmt]!=NULL ){
      sqlite3_finalize(v->pFulltextStatements[iStmt]);
      v->pFulltextStatements[iStmt] = NULL;
    }
  }

  if( v->pTokenizer!=NULL ){
    v->pTokenizer->pModule->xDestroy(v->pTokenizer);
    v->pTokenizer = NULL;
  }

  free((void *) v->zName);
  free(v);
}

/* Current interface:
** argv[0] - module name
** argv[1] - database name
** argv[2] - table name
** argv[3] - tokenizer name (optional, a sensible default is provided)
** argv[4..] - passed to tokenizer (optional based on tokenizer)
**/
static int fulltextConnect(
  sqlite3 *db,
  void *pAux,
  int argc,
  const char * const *argv,
  sqlite3_vtab **ppVTab,
  char **pzErr
){
  int rc;
  fulltext_vtab *v;
  sqlite3_tokenizer_module *m = NULL;

  assert( argc>=3 );
  v = (fulltext_vtab *) malloc(sizeof(fulltext_vtab));
  /* sqlite will initialize v->base */
  v->db = db;
  v->zName = string_dup(argv[2]);
  v->pTokenizer = NULL;

  if( argc==3 ){
    get_simple_tokenizer_module(&m);
  } else {
    /* TODO(shess) For now, add new tokenizers as else if clauses. */
    if( !strcmp(argv[3], "simple") ){
      get_simple_tokenizer_module(&m);
    } else {
      assert( "unrecognized tokenizer"==NULL );
    }
  }

  /* TODO(shess) Since tokenization impacts the index, the parameters
  ** to the tokenizer need to be identical when a persistent virtual
  ** table is re-created.  One solution would be a meta-table to track
  ** such information in the database.  Then we could verify that the
  ** information is identical on subsequent creates.
  */
  /* TODO(shess) Why isn't argv already (const char **)? */
  rc = m->xCreate(argc-3, (const char **) (argv+3), &v->pTokenizer);
  if( rc!=SQLITE_OK ) return rc;
  v->pTokenizer->pModule = m;

  /* TODO: verify the existence of backing tables foo_content, foo_term */

  rc = sqlite3_declare_vtab(db, "create table x(content text)");
  if( rc!=SQLITE_OK ) return rc;

  memset(v->pFulltextStatements, 0, sizeof(v->pFulltextStatements));

  *ppVTab = &v->base;
  return SQLITE_OK;
}

static int fulltextCreate(
  sqlite3 *db,
  void *pAux,
  int argc,
  const char * const *argv,
  sqlite3_vtab **ppVTab,
  char **pzErr
){
  int rc;
  assert( argc>=3 );

  /* The %_content table holds the text of each full-text item, with
  ** the rowid used as the docid.
  **
  ** The %_term table maps each term to a document list blob
  ** containing elements sorted by ascending docid, each element
  ** encoded as:
  **
  **   docid varint-encoded
  **   token count varint-encoded
  **   "count" token elements (poslist):
  **     position varint-encoded as delta from previous position
  **     start offset varint-encoded as delta from previous start offset
  **     end offset varint-encoded as delta from start offset
  **
  ** Additionally, doclist blobs can be chunked into multiple rows,
  ** using "first" to order the blobs.  "first" is simply the first
  ** docid in the blob.
  */
  /*
  ** NOTE(shess) That last sentence is incorrect in the face of
  ** deletion, which can leave a doclist that doesn't contain the
  ** first from that row.  I _believe_ this does not matter to the
  ** operation of the system, but it might be reasonable to update
  ** appropriately in case this assumption becomes more important.
  */
  rc = sql_exec(db, argv[2],
    "create table %_content(content text);"
    "create table %_term(term text, first integer, doclist blob);"
    "create index %_index on %_term(term, first)");
  if( rc!=SQLITE_OK ) return rc;

  return fulltextConnect(db, pAux, argc, argv, ppVTab, pzErr);
}

/* Decide how to handle an SQL query.
 * At the moment, MATCH queries can include implicit boolean ANDs; we
 * haven't implemented phrase searches or OR yet. */
static int fulltextBestIndex(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
  int i;

  for(i=0; i<pInfo->nConstraint; ++i){
    const struct sqlite3_index_constraint *pConstraint;
    pConstraint = &pInfo->aConstraint[i];
    if( pConstraint->iColumn==0 &&
        pConstraint->op==SQLITE_INDEX_CONSTRAINT_MATCH &&
        pConstraint->usable ){   /* a full-text search */
      pInfo->aConstraintUsage[i].argvIndex = 1;
      pInfo->aConstraintUsage[i].omit = 1;
      pInfo->idxNum = QUERY_FULLTEXT;
      pInfo->estimatedCost = 1.0;   /* an arbitrary value for now */
      return SQLITE_OK;
    }
  }
  pInfo->idxNum = QUERY_GENERIC;
  return SQLITE_OK;
}

static int fulltextDisconnect(sqlite3_vtab *pVTab){
  fulltext_vtab_destroy((fulltext_vtab *)pVTab);
  return SQLITE_OK;
}

static int fulltextDestroy(sqlite3_vtab *pVTab){
  fulltext_vtab *v = (fulltext_vtab *)pVTab;

  int rc = sql_exec(v->db, v->zName,
                    "drop table %_content; drop table %_term");
  if( rc!=SQLITE_OK ) return rc;

  fulltext_vtab_destroy((fulltext_vtab *)pVTab);
  return SQLITE_OK;
}

static int fulltextOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
  fulltext_cursor *c;

  c = (fulltext_cursor *) calloc(sizeof(fulltext_cursor), 1);
  /* sqlite will initialize c->base */
  *ppCursor = &c->base;

  return SQLITE_OK;
}

static int fulltextClose(sqlite3_vtab_cursor *pCursor){
  fulltext_cursor *c = (fulltext_cursor *) pCursor;
  sqlite3_finalize(c->pStmt);
  if( c->result.pDoclist!=NULL ){
    docListDelete(c->result.pDoclist);
  }
  free(c);
  return SQLITE_OK;
}

static int fulltextNext(sqlite3_vtab_cursor *pCursor){
  fulltext_cursor *c = (fulltext_cursor *) pCursor;
  sqlite_int64 iDocid;
  int rc;

  switch( c->iCursorType ){
    case QUERY_GENERIC:
      /* TODO(shess) Handle SQLITE_SCHEMA AND SQLITE_BUSY. */
      rc = sqlite3_step(c->pStmt);
      switch( rc ){
        case SQLITE_ROW:
          c->eof = 0;
          return SQLITE_OK;
        case SQLITE_DONE:
          c->eof = 1;
          return SQLITE_OK;
        default:
          c->eof = 1;
          return rc;
      }
    case QUERY_FULLTEXT:
      rc = sqlite3_reset(c->pStmt);
      if( rc!=SQLITE_OK ) return rc;

      if( readerAtEnd(&c->result)){
        c->eof = 1;
        return SQLITE_OK;
      }
      iDocid = readDocid(&c->result);
      rc = sqlite3_bind_int64(c->pStmt, 1, iDocid);
      if( rc!=SQLITE_OK ) return rc;
      /* TODO(shess) Handle SQLITE_SCHEMA AND SQLITE_BUSY. */
      rc = sqlite3_step(c->pStmt);
      if( rc==SQLITE_ROW ){   /* the case we expect */
        c->eof = 0;
        return SQLITE_OK;
      }
      /* an error occurred; abort */
      return rc==SQLITE_DONE ? SQLITE_ERROR : rc;
    default:
      assert( 0 );
      return SQLITE_ERROR;  /* not reached */
  }
}

static int term_select_doclist(fulltext_vtab *v, const char *pTerm, int nTerm,
                               sqlite3_stmt **ppStmt){
  int rc;
  if( *ppStmt ){
    rc = sqlite3_reset(*ppStmt);
  } else {
    rc = sql_prepare(v->db, v->zName, ppStmt,
      "select doclist from %_term where term = ? order by first");
  }
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_text(*ppStmt, 1, pTerm, nTerm, SQLITE_TRANSIENT);
  if( rc!=SQLITE_OK ) return rc;

  return sqlite3_step(*ppStmt);   /* TODO(adamd): handle schema error */
}

/* Read the posting list for [zTerm]; AND it with the doclist [in] to
 * produce the doclist [out], using the given offset [iOffset] for phrase
 * matching.
 * (*pSelect) is used to hold an SQLite statement used inside this function;
 * the caller should initialize *pSelect to NULL before the first call.
 */
static int query_merge(fulltext_vtab *v, sqlite3_stmt **pSelect,
                       const char *zTerm,
                       DocList *pIn, int iOffset, DocList *out){
  int rc;
  DocListMerge merge;

  if( pIn!=NULL && !pIn->nData ){
    /* If [pIn] is already empty, there's no point in reading the
     * posting list to AND it in; return immediately. */
      return SQLITE_OK;
  }

  rc = term_select_doclist(v, zTerm, -1, pSelect);
  if( rc!=SQLITE_ROW && rc!=SQLITE_DONE ) return rc;

  mergeInit(&merge, pIn, iOffset, out);
  while( rc==SQLITE_ROW ){
    DocList block;
    docListInit(&block, DL_POSITIONS_OFFSETS,
                sqlite3_column_blob(*pSelect, 0),
                sqlite3_column_bytes(*pSelect, 0));
    mergeBlock(&merge, &block);
    docListDestroy(&block);

    rc = sqlite3_step(*pSelect);
    if( rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
      return rc;
    }
  }
  
  return SQLITE_OK;
}

typedef struct QueryTerm {
  int is_phrase;    /* true if this term begins a new phrase */
  const char *zTerm;
} QueryTerm;

/* A parsed query.
 *
 * As an example, parsing the query ["four score" years "new nation"] will
 * yield a Query with 5 terms:
 *   "four",   is_phrase = 1
 *   "score",  is_phrase = 0
 *   "years",  is_phrase = 1
 *   "new",    is_phrase = 1
 *   "nation", is_phrase = 0
 */
typedef struct Query {
  int nTerms;
  QueryTerm *pTerm;
} Query;

static void query_add(Query *q, int is_phrase, const char *zTerm){
  QueryTerm *t;
  ++q->nTerms;
  q->pTerm = realloc(q->pTerm, q->nTerms * sizeof(q->pTerm[0]));
  t = &q->pTerm[q->nTerms - 1];
  t->is_phrase = is_phrase;
  t->zTerm = zTerm;
}
    
static void query_free(Query *q){
  int i;
  for(i = 0; i < q->nTerms; ++i){
    free((void *) q->pTerm[i].zTerm);
  }
  free(q->pTerm);
}

static int tokenize_segment(sqlite3_tokenizer *pTokenizer,
                            const char *zQuery, int in_phrase,
                            Query *pQuery){
  sqlite3_tokenizer_module *pModule = pTokenizer->pModule;
  sqlite3_tokenizer_cursor *pCursor;
  int is_first = 1;
  
  int rc = pModule->xOpen(pTokenizer, zQuery, -1, &pCursor);
  if( rc!=SQLITE_OK ) return rc;
  pCursor->pTokenizer = pTokenizer;

  while( 1 ){
    const char *zToken;
    int nToken, iStartOffset, iEndOffset, dummy_pos;

    rc = pModule->xNext(pCursor,
                        &zToken, &nToken,
                        &iStartOffset, &iEndOffset,
                        &dummy_pos);
    if( rc!=SQLITE_OK ) break;
    query_add(pQuery, !in_phrase || is_first, string_dup_n(zToken, nToken));
    is_first = 0;
  }

  return pModule->xClose(pCursor);
}

/* Parse a query string, yielding a Query object. */
static int parse_query(fulltext_vtab *v, const char *zQuery, Query *pQuery){
  char *zQuery1 = string_dup(zQuery);
  int in_phrase = 0;
  char *s = zQuery1;
  pQuery->nTerms = 0;
  pQuery->pTerm = NULL;

  while( *s ){
    char *t = s;
    while( *t ){
      if( *t=='"' ){
        *t++ = '\0';
        break;
      }
      ++t;
    }
    if( *s ){
      tokenize_segment(v->pTokenizer, s, in_phrase, pQuery);
    }
    s = t;
    in_phrase = !in_phrase;
  }
  
  free(zQuery1);
  return SQLITE_OK;
}

/* Perform a full-text query; return a list of documents in [pResult]. */
static int fulltext_query(fulltext_vtab *v, const char *zQuery,
                          DocList **pResult){
  Query q;
  int phrase_start = -1;
  int i;
  sqlite3_stmt *pSelect = NULL;
  DocList *d = NULL;

  int rc = parse_query(v, zQuery, &q);
  if( rc!=SQLITE_OK ) return rc;

  /* Merge terms. */
  for(i = 0 ; i < q.nTerms ; ++i){
    /* In each merge step, we need to generate positions whenever we're
     * processing a phrase which hasn't ended yet. */
    int need_positions = i<q.nTerms-1 && !q.pTerm[i+1].is_phrase;
    DocList *next = docListNew(need_positions ? DL_POSITIONS : DL_DOCIDS);
    if( q.pTerm[i].is_phrase ){
      phrase_start = i;
    }
    rc = query_merge(v, &pSelect, q.pTerm[i].zTerm, d, i - phrase_start, next);
    if( rc!=SQLITE_OK ) break;
    if( d!=NULL ){
      docListDelete(d);
    }
    d = next;
  }

  sqlite3_finalize(pSelect);
  query_free(&q);
  *pResult = d;
  return rc;
}

static int fulltextFilter(sqlite3_vtab_cursor *pCursor,
                          int idxNum, const char *idxStr,
                          int argc, sqlite3_value **argv){
  fulltext_cursor *c = (fulltext_cursor *) pCursor;
  fulltext_vtab *v = cursor_vtab(c);
  int rc;
  const char *zStatement;

  c->iCursorType = idxNum;
  switch( idxNum ){
    case QUERY_GENERIC:
      zStatement = "select rowid, content from %_content";
      break;

    case QUERY_FULLTEXT:   /* full-text search */
    {
      const char *zQuery = (const char *)sqlite3_value_text(argv[0]);
      DocList *pResult;
      assert( argc==1 );
      rc = fulltext_query(v, zQuery, &pResult);
      if( rc!=SQLITE_OK ) return rc;
      readerInit(&c->result, pResult);
      zStatement = "select rowid, content from %_content where rowid = ?";
      break;
    }

    default:
      assert( 0 );
  }

  rc = sql_prepare(v->db, v->zName, &c->pStmt, zStatement);
  if( rc!=SQLITE_OK ) return rc;

  return fulltextNext(pCursor);
}

static int fulltextEof(sqlite3_vtab_cursor *pCursor){
  fulltext_cursor *c = (fulltext_cursor *) pCursor;
  return c->eof;
}

static int fulltextColumn(sqlite3_vtab_cursor *pCursor,
                          sqlite3_context *pContext, int idxCol){
  fulltext_cursor *c = (fulltext_cursor *) pCursor;
  const char *s;

  assert( idxCol==0 );
  s = (const char *) sqlite3_column_text(c->pStmt, 1);
  sqlite3_result_text(pContext, s, -1, SQLITE_TRANSIENT);

  return SQLITE_OK;
}

static int fulltextRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
  fulltext_cursor *c = (fulltext_cursor *) pCursor;

  *pRowid = sqlite3_column_int64(c->pStmt, 0);
  return SQLITE_OK;
}

/* Build a hash table containing all terms in zText. */
static int build_terms(Hash *terms, sqlite3_tokenizer *pTokenizer,
                       const char *zText, sqlite_int64 iDocid){
  sqlite3_tokenizer_cursor *pCursor;
  const char *pToken;
  int nTokenBytes;
  int iStartOffset, iEndOffset, iPosition;

  int rc = pTokenizer->pModule->xOpen(pTokenizer, zText, -1, &pCursor);
  if( rc!=SQLITE_OK ) return rc;

  pCursor->pTokenizer = pTokenizer;
  HashInit(terms, HASH_STRING, 1);
  while( SQLITE_OK==pTokenizer->pModule->xNext(pCursor,
                                               &pToken, &nTokenBytes,
                                               &iStartOffset, &iEndOffset,
                                               &iPosition) ){
    DocList *p;

    /* Positions can't be negative; we use -1 as a terminator internally. */
    if( iPosition<0 ) {
      rc = SQLITE_ERROR;  
      goto err;
    }

    p = HashFind(terms, pToken, nTokenBytes);
    if( p==NULL ){
      p = docListNew(DL_POSITIONS_OFFSETS);
      docListAddDocid(p, iDocid);
      HashInsert(terms, pToken, nTokenBytes, p);
    }
    docListAddPosOffset(p, iPosition, iStartOffset, iEndOffset);
  }

err:
  /* TODO(shess) Check return?  Should this be able to cause errors at
  ** this point?  Actually, same question about sqlite3_finalize(),
  ** though one could argue that failure there means that the data is
  ** not durable.  *ponder*
  */
  pTokenizer->pModule->xClose(pCursor);
  return rc;
}
/* Update the %_terms table to map the term [zTerm] to the given rowid. */
static int index_insert_term(fulltext_vtab *v, const char *zTerm, int nTerm,
                             sqlite_int64 iDocid, DocList *p){
  sqlite_int64 iFirst;
  sqlite_int64 iIndexRow;
  DocList doclist;

  int rc = term_chunk_select(v, zTerm, nTerm, iDocid, &iFirst);
  if( rc==SQLITE_DONE ){
    docListInit(&doclist, DL_POSITIONS_OFFSETS, 0, 0);
    if( docListUpdate(&doclist, iDocid, p) ){
      rc = term_insert(v, zTerm, nTerm, iDocid, &doclist);
      docListDestroy(&doclist);
      return rc;
    }
    return SQLITE_OK;
  }
  if( rc!=SQLITE_ROW ) return SQLITE_ERROR;

  /* This word is in the index; add this document ID to its blob. */

  rc = term_select(v, zTerm, nTerm, iFirst, &iIndexRow, &doclist);
  if( rc!=SQLITE_OK ) return rc;

  if( docListUpdate(&doclist, iDocid, p) ){
    /* If the blob is too big, split it in half. */
    if( doclist.nData>CHUNK_MAX ){
      DocList half;
      if( docListSplit(&doclist, &half) ){
        rc = term_insert(v, zTerm, nTerm, firstDocid(&half), &half);
        docListDestroy(&half);
        if( rc!=SQLITE_OK ) goto err;
      }
    }
    rc = term_update(v, iIndexRow, &doclist);
  }

err:
  docListDestroy(&doclist);
  return rc;
}

/* Insert a row into the full-text index; set *piRowid to be the ID of the
 * new row. */
static int index_insert(fulltext_vtab *v,
                        sqlite3_value *pRequestRowid, const char *zText,
                        sqlite_int64 *piRowid){
  Hash terms;  /* maps term string -> PosList */
  HashElem *e;

  int rc = content_insert(v, pRequestRowid, zText, -1);
  if( rc!=SQLITE_OK ) return rc;
  *piRowid = sqlite3_last_insert_rowid(v->db);

  if( !zText ) return SQLITE_OK;   /* nothing to index */

  rc = build_terms(&terms, v->pTokenizer, zText, *piRowid);
  if( rc!=SQLITE_OK ) return rc;

  for(e=HashFirst(&terms); e; e=HashNext(e)){
    DocList *p = HashData(e);
    rc = index_insert_term(v, HashKey(e), HashKeysize(e), *piRowid, p);
    if( rc!=SQLITE_OK ) break;
  }

  for(e=HashFirst(&terms); e; e=HashNext(e)){
    DocList *p = HashData(e);
    docListDelete(p);
  }
  HashClear(&terms);
  return rc;
}

static int index_delete_term(fulltext_vtab *v, const char *zTerm, int nTerm,
                             sqlite_int64 iDocid){
  sqlite_int64 iFirst;
  sqlite_int64 iIndexRow;
  DocList doclist;

  int rc = term_chunk_select(v, zTerm, nTerm, iDocid, &iFirst);
  if( rc!=SQLITE_ROW ) return SQLITE_ERROR;

  rc = term_select(v, zTerm, nTerm, iFirst, &iIndexRow, &doclist);
  if( rc!=SQLITE_OK ) return rc;

  if( docListUpdate(&doclist, iDocid, NULL) ){
    if( doclist.nData>0 ){
      rc = term_update(v, iIndexRow, &doclist);
    } else {  /* empty posting list */
      rc = term_delete(v, iIndexRow);
    }
  }
  docListDestroy(&doclist);
  return rc;
}

/* Delete a row from the full-text index. */
static int index_delete(fulltext_vtab *v, sqlite_int64 iRow){
  char *zText;
  Hash terms;
  HashElem *e;

  int rc = content_select(v, iRow, &zText);
  if( rc!=SQLITE_OK ) return rc;

  rc = build_terms(&terms, v->pTokenizer, zText, iRow);
  free(zText);
  if( rc!=SQLITE_OK ) return rc;

  for(e=HashFirst(&terms); e; e=HashNext(e)){
    rc = index_delete_term(v, HashKey(e), HashKeysize(e), iRow);
    if( rc!=SQLITE_OK ) break;
  }
  for(e=HashFirst(&terms); e; e=HashNext(e)){
    DocList *p = HashData(e);
    docListDelete(p);
  }
  HashClear(&terms);

  return content_delete(v, iRow);
}

static int fulltextUpdate(sqlite3_vtab *pVtab, int nArg, sqlite3_value **ppArg,
                   sqlite_int64 *pRowid){
  fulltext_vtab *v = (fulltext_vtab *) pVtab;

  if( nArg<2 ){
    return index_delete(v, sqlite3_value_int64(ppArg[0]));
  }

  if( sqlite3_value_type(ppArg[0]) != SQLITE_NULL ){
    return SQLITE_ERROR;   /* an update; not yet supported */
  }

  assert( nArg==3 );    /* ppArg[1] = rowid, ppArg[2] = content */
  return index_insert(v, ppArg[1],
                      (const char *)sqlite3_value_text(ppArg[2]), pRowid);
}

static sqlite3_module fulltextModule = {
  0,
  fulltextCreate,
  fulltextConnect,
  fulltextBestIndex,
  fulltextDisconnect,
  fulltextDestroy,
  fulltextOpen,
  fulltextClose,
  fulltextFilter,
  fulltextNext,
  fulltextEof,
  fulltextColumn,
  fulltextRowid,
  fulltextUpdate
};

int fulltext_init(sqlite3 *db){
 return sqlite3_create_module(db, "fulltext", &fulltextModule, 0);
}

#if !SQLITE_CORE
#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_fulltext_init(sqlite3 *db, char **pzErrMsg,
                          const sqlite3_api_routines *pApi){
 SQLITE_EXTENSION_INIT2(pApi)
 return fulltext_init(db);
}
#endif

Deleted ext/fts1/fulltext.h.

1
2
3
4
5
6
7
8
9
10
11











-
-
-
-
-
-
-
-
-
-
-
#include "sqlite3.h"

#ifdef __cplusplus
extern "C" {
#endif  /* __cplusplus */

int fulltext_init(sqlite3 *db);

#ifdef __cplusplus
}  /* extern "C" */
#endif  /* __cplusplus */

Deleted ext/fts1/simple_tokenizer.c.

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














































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
** The author disclaims copyright to this source code.
**
*************************************************************************
** Implementation of the "simple" full-text-search tokenizer.
*/

#include <assert.h>
#if !defined(__APPLE__)
#include <malloc.h>
#else
#include <stdlib.h>
#endif
#include <stdio.h>
#include <string.h>
#include <ctype.h>

#include "tokenizer.h"

/* Duplicate a string; the caller must free() the returned string.
 * (We don't use strdup() since it's not part of the standard C library and
 * may not be available everywhere.) */
/* TODO(shess) Copied from fulltext.c, consider util.c for such
** things. */
static char *string_dup(const char *s){
  char *str = malloc(strlen(s) + 1);
  strcpy(str, s);
  return str;
}

typedef struct simple_tokenizer {
  sqlite3_tokenizer base;
  const char *zDelim;          /* token delimiters */
} simple_tokenizer;

typedef struct simple_tokenizer_cursor {
  sqlite3_tokenizer_cursor base;
  const char *pInput;          /* input we are tokenizing */
  int nBytes;                  /* size of the input */
  const char *pCurrent;        /* current position in pInput */
  int iToken;                  /* index of next token to be returned */
  char *zToken;                /* storage for current token */
  int nTokenBytes;             /* actual size of current token */
  int nTokenAllocated;         /* space allocated to zToken buffer */
} simple_tokenizer_cursor;

static sqlite3_tokenizer_module simpleTokenizerModule;/* forward declaration */

static int simpleCreate(
  int argc, const char **argv,
  sqlite3_tokenizer **ppTokenizer
){
  simple_tokenizer *t;

  t = (simple_tokenizer *) malloc(sizeof(simple_tokenizer));
  /* TODO(shess) Delimiters need to remain the same from run to run,
  ** else we need to reindex.  One solution would be a meta-table to
  ** track such information in the database, then we'd only want this
  ** information on the initial create.
  */
  if( argc>1 ){
    t->zDelim = string_dup(argv[1]);
  } else {
    /* Build a string excluding alphanumeric ASCII characters */
    char zDelim[0x80];               /* nul-terminated, so nul not a member */
    int i, j;
    for(i=1, j=0; i<0x80; i++){
      if( !isalnum(i) ){
        zDelim[j++] = i;
      }
    }
    zDelim[j++] = '\0';
    assert( j<=sizeof(zDelim) );
    t->zDelim = string_dup(zDelim);
  }

  *ppTokenizer = &t->base;
  return SQLITE_OK;
}

static int simpleDestroy(sqlite3_tokenizer *pTokenizer){
  simple_tokenizer *t = (simple_tokenizer *) pTokenizer;

  free((void *) t->zDelim);
  free(t);

  return SQLITE_OK;
}

static int simpleOpen(
  sqlite3_tokenizer *pTokenizer,
  const char *pInput, int nBytes,
  sqlite3_tokenizer_cursor **ppCursor
){
  simple_tokenizer_cursor *c;

  c = (simple_tokenizer_cursor *) malloc(sizeof(simple_tokenizer_cursor));
  c->pInput = pInput;
  c->nBytes = nBytes<0 ? (int) strlen(pInput) : nBytes;
  c->pCurrent = c->pInput;        /* start tokenizing at the beginning */
  c->iToken = 0;
  c->zToken = NULL;               /* no space allocated, yet. */
  c->nTokenBytes = 0;
  c->nTokenAllocated = 0;

  *ppCursor = &c->base;
  return SQLITE_OK;
}

static int simpleClose(sqlite3_tokenizer_cursor *pCursor){
  simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor;

  if( NULL!=c->zToken ){
    free(c->zToken);
  }
  free(c);

  return SQLITE_OK;
}

static int simpleNext(
  sqlite3_tokenizer_cursor *pCursor,
  const char **ppToken, int *pnBytes,
  int *piStartOffset, int *piEndOffset, int *piPosition
){
  simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor;
  simple_tokenizer *t = (simple_tokenizer *) pCursor->pTokenizer;
  int ii;

  while( c->pCurrent-c->pInput<c->nBytes ){
    int n = (int) strcspn(c->pCurrent, t->zDelim);
    if( n>0 ){
      if( n+1>c->nTokenAllocated ){
        c->zToken = realloc(c->zToken, n+1);
      }
      for(ii=0; ii<n; ii++){
        /* TODO(shess) This needs expansion to handle UTF-8
        ** case-insensitivity.
        */
        char ch = c->pCurrent[ii];
        c->zToken[ii] = (unsigned char)ch<0x80 ? tolower((unsigned char)ch):ch;
      }
      c->zToken[n] = '\0';
      *ppToken = c->zToken;
      *pnBytes = n;
      *piStartOffset = (int) (c->pCurrent-c->pInput);
      *piEndOffset = *piStartOffset+n;
      *piPosition = c->iToken++;
      c->pCurrent += n + 1;

      return SQLITE_OK;
    }
    c->pCurrent += n + 1;
    /* TODO(shess) could strspn() to skip delimiters en masse.  Needs
    ** to happen in two places, though, which is annoying.
    */
  }
  return SQLITE_DONE;
}

static sqlite3_tokenizer_module simpleTokenizerModule = {
  0,
  simpleCreate,
  simpleDestroy,
  simpleOpen,
  simpleClose,
  simpleNext,
};

void get_simple_tokenizer_module(
  sqlite3_tokenizer_module **ppModule
){
  *ppModule = &simpleTokenizerModule;
}

Deleted ext/fts1/tokenizer.h.

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

























































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
** 2006 July 10
**
** The author disclaims copyright to this source code.
**
*************************************************************************
** Defines the interface to tokenizers used by fulltext-search.  There
** are three basic components:
**
** sqlite3_tokenizer_module is a singleton defining the tokenizer
** interface functions.  This is essentially the class structure for
** tokenizers.
**
** sqlite3_tokenizer is used to define a particular tokenizer, perhaps
** including customization information defined at creation time.
**
** sqlite3_tokenizer_cursor is generated by a tokenizer to generate
** tokens from a particular input.
*/
#ifndef _TOKENIZER_H_
#define _TOKENIZER_H_

/* TODO(shess) Only used for SQLITE_OK and SQLITE_DONE at this time.
** If tokenizers are to be allowed to call sqlite3_*() functions, then
** we will need a way to register the API consistently.
*/
#include "sqlite3.h"

/*
** Structures used by the tokenizer interface.
*/
typedef struct sqlite3_tokenizer sqlite3_tokenizer;
typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor;
typedef struct sqlite3_tokenizer_module sqlite3_tokenizer_module;

struct sqlite3_tokenizer_module {
  int iVersion;                  /* currently 0 */

  /*
  ** Create and destroy a tokenizer.  argc/argv are passed down from
  ** the fulltext virtual table creation to allow customization.
  */
  int (*xCreate)(int argc, const char **argv,
                 sqlite3_tokenizer **ppTokenizer);
  int (*xDestroy)(sqlite3_tokenizer *pTokenizer);

  /*
  ** Tokenize a particular input.  Call xOpen() to prepare to
  ** tokenize, xNext() repeatedly until it returns SQLITE_DONE, then
  ** xClose() to free any internal state.  The pInput passed to
  ** xOpen() must exist until the cursor is closed.  The ppToken
  ** result from xNext() is only valid until the next call to xNext()
  ** or until xClose() is called.
  */
  /* TODO(shess) current implementation requires pInput to be
  ** nul-terminated.  This should either be fixed, or pInput/nBytes
  ** should be converted to zInput.
  */
  int (*xOpen)(sqlite3_tokenizer *pTokenizer,
               const char *pInput, int nBytes,
               sqlite3_tokenizer_cursor **ppCursor);
  int (*xClose)(sqlite3_tokenizer_cursor *pCursor);
  int (*xNext)(sqlite3_tokenizer_cursor *pCursor,
               const char **ppToken, int *pnBytes,
               int *piStartOffset, int *piEndOffset, int *piPosition);
};

struct sqlite3_tokenizer {
  sqlite3_tokenizer_module *pModule;  /* The module for this tokenizer */
  /* Tokenizer implementations will typically add additional fields */
};

struct sqlite3_tokenizer_cursor {
  sqlite3_tokenizer *pTokenizer;       /* Tokenizer for this cursor. */
  /* Tokenizer implementations will typically add additional fields */
};

/*
** Get the module for a tokenizer which generates tokens based on a
** set of non-token characters.  The default is to break tokens at any
** non-alnum character, though the set of delimiters can also be
** specified by the first argv argument to xCreate().
*/
/* TODO(shess) This doesn't belong here.  Need some sort of
** registration process.
*/
void get_simple_tokenizer_module(sqlite3_tokenizer_module **ppModule);

#endif /* _TOKENIZER_H_ */

Deleted ext/fts2/README.tokenizers.

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





































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

1. FTS2 Tokenizers

  When creating a new full-text table, FTS2 allows the user to select
  the text tokenizer implementation to be used when indexing text
  by specifying a "tokenizer" clause as part of the CREATE VIRTUAL TABLE
  statement:

    CREATE VIRTUAL TABLE <table-name> USING fts2(
      <columns ...> [, tokenizer <tokenizer-name> [<tokenizer-args>]]
    );

  The built-in tokenizers (valid values to pass as <tokenizer name>) are
  "simple" and "porter".

  <tokenizer-args> should consist of zero or more white-space separated
  arguments to pass to the selected tokenizer implementation. The 
  interpretation of the arguments, if any, depends on the individual 
  tokenizer.

2. Custom Tokenizers

  FTS2 allows users to provide custom tokenizer implementations. The 
  interface used to create a new tokenizer is defined and described in 
  the fts2_tokenizer.h source file.

  Registering a new FTS2 tokenizer is similar to registering a new 
  virtual table module with SQLite. The user passes a pointer to a
  structure containing pointers to various callback functions that
  make up the implementation of the new tokenizer type. For tokenizers,
  the structure (defined in fts2_tokenizer.h) is called
  "sqlite3_tokenizer_module".

  FTS2 does not expose a C-function that users call to register new
  tokenizer types with a database handle. Instead, the pointer must
  be encoded as an SQL blob value and passed to FTS2 through the SQL
  engine by evaluating a special scalar function, "fts2_tokenizer()".
  The fts2_tokenizer() function may be called with one or two arguments,
  as follows:

    SELECT fts2_tokenizer(<tokenizer-name>);
    SELECT fts2_tokenizer(<tokenizer-name>, <sqlite3_tokenizer_module ptr>);
  
  Where <tokenizer-name> is a string identifying the tokenizer and
  <sqlite3_tokenizer_module ptr> is a pointer to an sqlite3_tokenizer_module
  structure encoded as an SQL blob. If the second argument is present,
  it is registered as tokenizer <tokenizer-name> and a copy of it
  returned. If only one argument is passed, a pointer to the tokenizer
  implementation currently registered as <tokenizer-name> is returned,
  encoded as a blob. Or, if no such tokenizer exists, an SQL exception
  (error) is raised.

  SECURITY: If the fts2 extension is used in an environment where potentially
    malicious users may execute arbitrary SQL (i.e. gears), they should be
    prevented from invoking the fts2_tokenizer() function, possibly using the
    authorisation callback.

  See "Sample code" below for an example of calling the fts2_tokenizer()
  function from C code.

3. ICU Library Tokenizers

  If this extension is compiled with the SQLITE_ENABLE_ICU pre-processor 
  symbol defined, then there exists a built-in tokenizer named "icu" 
  implemented using the ICU library. The first argument passed to the
  xCreate() method (see fts2_tokenizer.h) of this tokenizer may be
  an ICU locale identifier. For example "tr_TR" for Turkish as used
  in Turkey, or "en_AU" for English as used in Australia. For example:

    "CREATE VIRTUAL TABLE thai_text USING fts2(text, tokenizer icu th_TH)"

  The ICU tokenizer implementation is very simple. It splits the input
  text according to the ICU rules for finding word boundaries and discards
  any tokens that consist entirely of white-space. This may be suitable
  for some applications in some locales, but not all. If more complex
  processing is required, for example to implement stemming or 
  discard punctuation, this can be done by creating a tokenizer 
  implementation that uses the ICU tokenizer as part of its implementation.

  When using the ICU tokenizer this way, it is safe to overwrite the
  contents of the strings returned by the xNext() method (see
  fts2_tokenizer.h).

4. Sample code.

  The following two code samples illustrate the way C code should invoke
  the fts2_tokenizer() scalar function:

      int registerTokenizer(
        sqlite3 *db, 
        char *zName, 
        const sqlite3_tokenizer_module *p
      ){
        int rc;
        sqlite3_stmt *pStmt;
        const char zSql[] = "SELECT fts2_tokenizer(?, ?)";
      
        rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
        if( rc!=SQLITE_OK ){
          return rc;
        }
      
        sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC);
        sqlite3_bind_blob(pStmt, 2, &p, sizeof(p), SQLITE_STATIC);
        sqlite3_step(pStmt);
      
        return sqlite3_finalize(pStmt);
      }
      
      int queryTokenizer(
        sqlite3 *db, 
        char *zName,  
        const sqlite3_tokenizer_module **pp
      ){
        int rc;
        sqlite3_stmt *pStmt;
        const char zSql[] = "SELECT fts2_tokenizer(?)";
      
        *pp = 0;
        rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
        if( rc!=SQLITE_OK ){
          return rc;
        }
      
        sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC);
        if( SQLITE_ROW==sqlite3_step(pStmt) ){
          if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){
            memcpy(pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp));
          }
        }
      
        return sqlite3_finalize(pStmt);
      }

Deleted ext/fts2/README.txt.

1
2
3
4




-
-
-
-
This folder contains source code to the second full-text search
extension for SQLite.  While the API is the same, this version uses a
substantially different storage schema from fts1, so tables will need
to be rebuilt.

Deleted ext/fts2/fts2.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
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
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
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
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
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
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
1984
1985
1986
1987
1988
1989
1990
1991
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
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
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
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
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
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
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
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
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
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
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
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
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
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
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
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
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
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
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
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
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
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
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
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
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
4360
4361
4362
4363
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
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
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
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
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
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
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
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
6457
6458
6459
6460
6461
6462
6463
6464
6465
6466
6467
6468
6469
6470
6471
6472
6473
6474
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485
6486
6487
6488
6489
6490
6491
6492
6493
6494
6495
6496
6497
6498
6499
6500
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516
6517
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561
6562
6563
6564
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583
6584
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621
6622
6623
6624
6625
6626
6627
6628
6629
6630
6631
6632
6633
6634
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
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
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
6735
6736
6737
6738
6739
6740
6741
6742
6743
6744
6745
6746
6747
6748
6749
6750
6751
6752
6753
6754
6755
6756
6757
6758
6759
6760
6761
6762
6763
6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774
6775
6776
6777
6778
6779
6780
6781
6782
6783
6784
6785
6786
6787
6788
6789
6790
6791
6792
6793
6794
6795
6796
6797
6798
6799
6800
6801
6802
6803
6804
6805
6806
6807
6808
6809
6810
6811
6812
6813
6814
6815
6816
6817
6818
6819
6820
6821
6822
6823
6824
6825
6826
6827
6828
6829
6830
6831
6832
6833
6834
6835
6836
6837
6838
6839
6840
6841
6842
6843
6844
6845
6846
6847
6848
6849
6850
6851
6852
6853
6854
6855
6856
6857
6858
6859
6860












































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/* fts2 has a design flaw which can lead to database corruption (see
** below).  It is recommended not to use it any longer, instead use
** fts3 (or higher).  If you believe that your use of fts2 is safe,
** add -DSQLITE_ENABLE_BROKEN_FTS2=1 to your CFLAGS.
*/
#if (!defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2)) \
        && !defined(SQLITE_ENABLE_BROKEN_FTS2)
#error fts2 has a design flaw and has been deprecated.
#endif
/* The flaw is that fts2 uses the content table's unaliased rowid as
** the unique docid.  fts2 embeds the rowid in the index it builds,
** and expects the rowid to not change.  The SQLite VACUUM operation
** will renumber such rowids, thereby breaking fts2.  If you are using
** fts2 in a system which has disabled VACUUM, then you can continue
** to use it safely.  Note that PRAGMA auto_vacuum does NOT disable
** VACUUM, though systems using auto_vacuum are unlikely to invoke
** VACUUM.
**
** Unlike fts1, which is safe across VACUUM if you never delete
** documents, fts2 has a second exposure to this flaw, in the segments
** table.  So fts2 should be considered unsafe across VACUUM in all
** cases.
*/

/*
** 2006 Oct 10
**
** 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 is an SQLite module implementing full-text search.
*/

/*
** The code in this file is only compiled if:
**
**     * The FTS2 module is being built as an extension
**       (in which case SQLITE_CORE is not defined), or
**
**     * The FTS2 module is being built into the core of
**       SQLite (in which case SQLITE_ENABLE_FTS2 is defined).
*/

/* TODO(shess) Consider exporting this comment to an HTML file or the
** wiki.
*/
/* The full-text index is stored in a series of b+tree (-like)
** structures called segments which map terms to doclists.  The
** structures are like b+trees in layout, but are constructed from the
** bottom up in optimal fashion and are not updatable.  Since trees
** are built from the bottom up, things will be described from the
** bottom up.
**
**
**** Varints ****
** The basic unit of encoding is a variable-length integer called a
** varint.  We encode variable-length integers in little-endian order
** using seven bits * per byte as follows:
**
** KEY:
**         A = 0xxxxxxx    7 bits of data and one flag bit
**         B = 1xxxxxxx    7 bits of data and one flag bit
**
**  7 bits - A
** 14 bits - BA
** 21 bits - BBA
** and so on.
**
** This is identical to how sqlite encodes varints (see util.c).
**
**
**** Document lists ****
** A doclist (document list) holds a docid-sorted list of hits for a
** given term.  Doclists hold docids, and can optionally associate
** token positions and offsets with docids.
**
** A DL_POSITIONS_OFFSETS doclist is stored like this:
**
** array {
**   varint docid;
**   array {                (position list for column 0)
**     varint position;     (delta from previous position plus POS_BASE)
**     varint startOffset;  (delta from previous startOffset)
**     varint endOffset;    (delta from startOffset)
**   }
**   array {
**     varint POS_COLUMN;   (marks start of position list for new column)
**     varint column;       (index of new column)
**     array {
**       varint position;   (delta from previous position plus POS_BASE)
**       varint startOffset;(delta from previous startOffset)
**       varint endOffset;  (delta from startOffset)
**     }
**   }
**   varint POS_END;        (marks end of positions for this document.
** }
**
** Here, array { X } means zero or more occurrences of X, adjacent in
** memory.  A "position" is an index of a token in the token stream
** generated by the tokenizer, while an "offset" is a byte offset,
** both based at 0.  Note that POS_END and POS_COLUMN occur in the
** same logical place as the position element, and act as sentinals
** ending a position list array.
**
** A DL_POSITIONS doclist omits the startOffset and endOffset
** information.  A DL_DOCIDS doclist omits both the position and
** offset information, becoming an array of varint-encoded docids.
**
** On-disk data is stored as type DL_DEFAULT, so we don't serialize
** the type.  Due to how deletion is implemented in the segmentation
** system, on-disk doclists MUST store at least positions.
**
**
**** Segment leaf nodes ****
** Segment leaf nodes store terms and doclists, ordered by term.  Leaf
** nodes are written using LeafWriter, and read using LeafReader (to
** iterate through a single leaf node's data) and LeavesReader (to
** iterate through a segment's entire leaf layer).  Leaf nodes have
** the format:
**
** varint iHeight;             (height from leaf level, always 0)
** varint nTerm;               (length of first term)
** char pTerm[nTerm];          (content of first term)
** varint nDoclist;            (length of term's associated doclist)
** char pDoclist[nDoclist];    (content of doclist)
** array {
**                             (further terms are delta-encoded)
**   varint nPrefix;           (length of prefix shared with previous term)
**   varint nSuffix;           (length of unshared suffix)
**   char pTermSuffix[nSuffix];(unshared suffix of next term)
**   varint nDoclist;          (length of term's associated doclist)
**   char pDoclist[nDoclist];  (content of doclist)
** }
**
** Here, array { X } means zero or more occurrences of X, adjacent in
** memory.
**
** Leaf nodes are broken into blocks which are stored contiguously in
** the %_segments table in sorted order.  This means that when the end
** of a node is reached, the next term is in the node with the next
** greater node id.
**
** New data is spilled to a new leaf node when the current node
** exceeds LEAF_MAX bytes (default 2048).  New data which itself is
** larger than STANDALONE_MIN (default 1024) is placed in a standalone
** node (a leaf node with a single term and doclist).  The goal of
** these settings is to pack together groups of small doclists while
** making it efficient to directly access large doclists.  The
** assumption is that large doclists represent terms which are more
** likely to be query targets.
**
** TODO(shess) It may be useful for blocking decisions to be more
** dynamic.  For instance, it may make more sense to have a 2.5k leaf
** node rather than splitting into 2k and .5k nodes.  My intuition is
** that this might extend through 2x or 4x the pagesize.
**
**
**** Segment interior nodes ****
** Segment interior nodes store blockids for subtree nodes and terms
** to describe what data is stored by the each subtree.  Interior
** nodes are written using InteriorWriter, and read using
** InteriorReader.  InteriorWriters are created as needed when
** SegmentWriter creates new leaf nodes, or when an interior node
** itself grows too big and must be split.  The format of interior
** nodes:
**
** varint iHeight;           (height from leaf level, always >0)
** varint iBlockid;          (block id of node's leftmost subtree)
** optional {
**   varint nTerm;           (length of first term)
**   char pTerm[nTerm];      (content of first term)
**   array {
**                                (further terms are delta-encoded)
**     varint nPrefix;            (length of shared prefix with previous term)
**     varint nSuffix;            (length of unshared suffix)
**     char pTermSuffix[nSuffix]; (unshared suffix of next term)
**   }
** }
**
** Here, optional { X } means an optional element, while array { X }
** means zero or more occurrences of X, adjacent in memory.
**
** An interior node encodes n terms separating n+1 subtrees.  The
** subtree blocks are contiguous, so only the first subtree's blockid
** is encoded.  The subtree at iBlockid will contain all terms less
** than the first term encoded (or all terms if no term is encoded).
** Otherwise, for terms greater than or equal to pTerm[i] but less
** than pTerm[i+1], the subtree for that term will be rooted at
** iBlockid+i.  Interior nodes only store enough term data to
** distinguish adjacent children (if the rightmost term of the left
** child is "something", and the leftmost term of the right child is
** "wicked", only "w" is stored).
**
** New data is spilled to a new interior node at the same height when
** the current node exceeds INTERIOR_MAX bytes (default 2048).
** INTERIOR_MIN_TERMS (default 7) keeps large terms from monopolizing
** interior nodes and making the tree too skinny.  The interior nodes
** at a given height are naturally tracked by interior nodes at
** height+1, and so on.
**
**
**** Segment directory ****
** The segment directory in table %_segdir stores meta-information for
** merging and deleting segments, and also the root node of the
** segment's tree.
**
** The root node is the top node of the segment's tree after encoding
** the entire segment, restricted to ROOT_MAX bytes (default 1024).
** This could be either a leaf node or an interior node.  If the top
** node requires more than ROOT_MAX bytes, it is flushed to %_segments
** and a new root interior node is generated (which should always fit
** within ROOT_MAX because it only needs space for 2 varints, the
** height and the blockid of the previous root).
**
** The meta-information in the segment directory is:
**   level               - segment level (see below)
**   idx                 - index within level
**                       - (level,idx uniquely identify a segment)
**   start_block         - first leaf node
**   leaves_end_block    - last leaf node
**   end_block           - last block (including interior nodes)
**   root                - contents of root node
**
** If the root node is a leaf node, then start_block,
** leaves_end_block, and end_block are all 0.
**
**
**** Segment merging ****
** To amortize update costs, segments are groups into levels and
** merged in matches.  Each increase in level represents exponentially
** more documents.
**
** New documents (actually, document updates) are tokenized and
** written individually (using LeafWriter) to a level 0 segment, with
** incrementing idx.  When idx reaches MERGE_COUNT (default 16), all
** level 0 segments are merged into a single level 1 segment.  Level 1
** is populated like level 0, and eventually MERGE_COUNT level 1
** segments are merged to a single level 2 segment (representing
** MERGE_COUNT^2 updates), and so on.
**
** A segment merge traverses all segments at a given level in
** parallel, performing a straightforward sorted merge.  Since segment
** leaf nodes are written in to the %_segments table in order, this
** merge traverses the underlying sqlite disk structures efficiently.
** After the merge, all segment blocks from the merged level are
** deleted.
**
** MERGE_COUNT controls how often we merge segments.  16 seems to be
** somewhat of a sweet spot for insertion performance.  32 and 64 show
** very similar performance numbers to 16 on insertion, though they're
** a tiny bit slower (perhaps due to more overhead in merge-time
** sorting).  8 is about 20% slower than 16, 4 about 50% slower than
** 16, 2 about 66% slower than 16.
**
** At query time, high MERGE_COUNT increases the number of segments
** which need to be scanned and merged.  For instance, with 100k docs
** inserted:
**
**    MERGE_COUNT   segments
**       16           25
**        8           12
**        4           10
**        2            6
**
** This appears to have only a moderate impact on queries for very
** frequent terms (which are somewhat dominated by segment merge
** costs), and infrequent and non-existent terms still seem to be fast
** even with many segments.
**
** TODO(shess) That said, it would be nice to have a better query-side
** argument for MERGE_COUNT of 16.  Also, it is possible/likely that
** optimizations to things like doclist merging will swing the sweet
** spot around.
**
**
**
**** Handling of deletions and updates ****
** Since we're using a segmented structure, with no docid-oriented
** index into the term index, we clearly cannot simply update the term
** index when a document is deleted or updated.  For deletions, we
** write an empty doclist (varint(docid) varint(POS_END)), for updates
** we simply write the new doclist.  Segment merges overwrite older
** data for a particular docid with newer data, so deletes or updates
** will eventually overtake the earlier data and knock it out.  The
** query logic likewise merges doclists so that newer data knocks out
** older data.
**
** TODO(shess) Provide a VACUUM type operation to clear out all
** deletions and duplications.  This would basically be a forced merge
** into a single segment.
*/

#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2)

#if defined(SQLITE_ENABLE_FTS2) && !defined(SQLITE_CORE)
# define SQLITE_CORE 1
#endif

#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "fts2.h"
#include "fts2_hash.h"
#include "fts2_tokenizer.h"
#include "sqlite3.h"
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1


/* TODO(shess) MAN, this thing needs some refactoring.  At minimum, it
** would be nice to order the file better, perhaps something along the
** lines of:
**
**  - utility functions
**  - table setup functions
**  - table update functions
**  - table query functions
**
** Put the query functions last because they're likely to reference
** typedefs or functions from the table update section.
*/

#if 0
# define TRACE(A)  printf A; fflush(stdout)
#else
# define TRACE(A)
#endif

/* It is not safe to call isspace(), tolower(), or isalnum() on
** hi-bit-set characters.  This is the same solution used in the
** tokenizer.
*/
/* TODO(shess) The snippet-generation code should be using the
** tokenizer-generated tokens rather than doing its own local
** tokenization.
*/
/* TODO(shess) Is __isascii() a portable version of (c&0x80)==0? */
static int safe_isspace(char c){
  return c==' ' || c=='\t' || c=='\n' || c=='\r' || c=='\v' || c=='\f';
}
static int safe_tolower(char c){
  return (c>='A' && c<='Z') ? (c - 'A' + 'a') : c;
}
static int safe_isalnum(char c){
  return (c>='0' && c<='9') || (c>='A' && c<='Z') || (c>='a' && c<='z');
}

typedef enum DocListType {
  DL_DOCIDS,              /* docids only */
  DL_POSITIONS,           /* docids + positions */
  DL_POSITIONS_OFFSETS    /* docids + positions + offsets */
} DocListType;

/*
** By default, only positions and not offsets are stored in the doclists.
** To change this so that offsets are stored too, compile with
**
**          -DDL_DEFAULT=DL_POSITIONS_OFFSETS
**
** If DL_DEFAULT is set to DL_DOCIDS, your table can only be inserted
** into (no deletes or updates).
*/
#ifndef DL_DEFAULT
# define DL_DEFAULT DL_POSITIONS
#endif

enum {
  POS_END = 0,        /* end of this position list */
  POS_COLUMN,         /* followed by new column number */
  POS_BASE
};

/* MERGE_COUNT controls how often we merge segments (see comment at
** top of file).
*/
#define MERGE_COUNT 16

/* utility functions */

/* CLEAR() and SCRAMBLE() abstract memset() on a pointer to a single
** record to prevent errors of the form:
**
** my_function(SomeType *b){
**   memset(b, '\0', sizeof(b));  // sizeof(b)!=sizeof(*b)
** }
*/
/* TODO(shess) Obvious candidates for a header file. */
#define CLEAR(b) memset(b, '\0', sizeof(*(b)))

#ifndef NDEBUG
#  define SCRAMBLE(b) memset(b, 0x55, sizeof(*(b)))
#else
#  define SCRAMBLE(b)
#endif

/* We may need up to VARINT_MAX bytes to store an encoded 64-bit integer. */
#define VARINT_MAX 10

/* Write a 64-bit variable-length integer to memory starting at p[0].
 * The length of data written will be between 1 and VARINT_MAX bytes.
 * The number of bytes written is returned. */
static int putVarint(char *p, sqlite_int64 v){
  unsigned char *q = (unsigned char *) p;
  sqlite_uint64 vu = v;
  do{
    *q++ = (unsigned char) ((vu & 0x7f) | 0x80);
    vu >>= 7;
  }while( vu!=0 );
  q[-1] &= 0x7f;  /* turn off high bit in final byte */
  assert( q - (unsigned char *)p <= VARINT_MAX );
  return (int) (q - (unsigned char *)p);
}

/* Read a 64-bit variable-length integer from memory starting at p[0].
 * Return the number of bytes read, or 0 on error.
 * The value is stored in *v. */
static int getVarint(const char *p, sqlite_int64 *v){
  const unsigned char *q = (const unsigned char *) p;
  sqlite_uint64 x = 0, y = 1;
  while( (*q & 0x80) == 0x80 ){
    x += y * (*q++ & 0x7f);
    y <<= 7;
    if( q - (unsigned char *)p >= VARINT_MAX ){  /* bad data */
      assert( 0 );
      return 0;
    }
  }
  x += y * (*q++);
  *v = (sqlite_int64) x;
  return (int) (q - (unsigned char *)p);
}

static int getVarint32(const char *p, int *pi){
 sqlite_int64 i;
 int ret = getVarint(p, &i);
 *pi = (int) i;
 assert( *pi==i );
 return ret;
}

/*******************************************************************/
/* DataBuffer is used to collect data into a buffer in piecemeal
** fashion.  It implements the usual distinction between amount of
** data currently stored (nData) and buffer capacity (nCapacity).
**
** dataBufferInit - create a buffer with given initial capacity.
** dataBufferReset - forget buffer's data, retaining capacity.
** dataBufferDestroy - free buffer's data.
** dataBufferSwap - swap contents of two buffers.
** dataBufferExpand - expand capacity without adding data.
** dataBufferAppend - append data.
** dataBufferAppend2 - append two pieces of data at once.
** dataBufferReplace - replace buffer's data.
*/
typedef struct DataBuffer {
  char *pData;          /* Pointer to malloc'ed buffer. */
  int nCapacity;        /* Size of pData buffer. */
  int nData;            /* End of data loaded into pData. */
} DataBuffer;

static void dataBufferInit(DataBuffer *pBuffer, int nCapacity){
  assert( nCapacity>=0 );
  pBuffer->nData = 0;
  pBuffer->nCapacity = nCapacity;
  pBuffer->pData = nCapacity==0 ? NULL : sqlite3_malloc(nCapacity);
}
static void dataBufferReset(DataBuffer *pBuffer){
  pBuffer->nData = 0;
}
static void dataBufferDestroy(DataBuffer *pBuffer){
  if( pBuffer->pData!=NULL ) sqlite3_free(pBuffer->pData);
  SCRAMBLE(pBuffer);
}
static void dataBufferSwap(DataBuffer *pBuffer1, DataBuffer *pBuffer2){
  DataBuffer tmp = *pBuffer1;
  *pBuffer1 = *pBuffer2;
  *pBuffer2 = tmp;
}
static void dataBufferExpand(DataBuffer *pBuffer, int nAddCapacity){
  assert( nAddCapacity>0 );
  /* TODO(shess) Consider expanding more aggressively.  Note that the
  ** underlying malloc implementation may take care of such things for
  ** us already.
  */
  if( pBuffer->nData+nAddCapacity>pBuffer->nCapacity ){
    pBuffer->nCapacity = pBuffer->nData+nAddCapacity;
    pBuffer->pData = sqlite3_realloc(pBuffer->pData, pBuffer->nCapacity);
  }
}
static void dataBufferAppend(DataBuffer *pBuffer,
                             const char *pSource, int nSource){
  assert( nSource>0 && pSource!=NULL );
  dataBufferExpand(pBuffer, nSource);
  memcpy(pBuffer->pData+pBuffer->nData, pSource, nSource);
  pBuffer->nData += nSource;
}
static void dataBufferAppend2(DataBuffer *pBuffer,
                              const char *pSource1, int nSource1,
                              const char *pSource2, int nSource2){
  assert( nSource1>0 && pSource1!=NULL );
  assert( nSource2>0 && pSource2!=NULL );
  dataBufferExpand(pBuffer, nSource1+nSource2);
  memcpy(pBuffer->pData+pBuffer->nData, pSource1, nSource1);
  memcpy(pBuffer->pData+pBuffer->nData+nSource1, pSource2, nSource2);
  pBuffer->nData += nSource1+nSource2;
}
static void dataBufferReplace(DataBuffer *pBuffer,
                              const char *pSource, int nSource){
  dataBufferReset(pBuffer);
  dataBufferAppend(pBuffer, pSource, nSource);
}

/* StringBuffer is a null-terminated version of DataBuffer. */
typedef struct StringBuffer {
  DataBuffer b;            /* Includes null terminator. */
} StringBuffer;

static void initStringBuffer(StringBuffer *sb){
  dataBufferInit(&sb->b, 100);
  dataBufferReplace(&sb->b, "", 1);
}
static int stringBufferLength(StringBuffer *sb){
  return sb->b.nData-1;
}
static char *stringBufferData(StringBuffer *sb){
  return sb->b.pData;
}
static void stringBufferDestroy(StringBuffer *sb){
  dataBufferDestroy(&sb->b);
}

static void nappend(StringBuffer *sb, const char *zFrom, int nFrom){
  assert( sb->b.nData>0 );
  if( nFrom>0 ){
    sb->b.nData--;
    dataBufferAppend2(&sb->b, zFrom, nFrom, "", 1);
  }
}
static void append(StringBuffer *sb, const char *zFrom){
  nappend(sb, zFrom, strlen(zFrom));
}

/* Append a list of strings separated by commas. */
static void appendList(StringBuffer *sb, int nString, char **azString){
  int i;
  for(i=0; i<nString; ++i){
    if( i>0 ) append(sb, ", ");
    append(sb, azString[i]);
  }
}

static int endsInWhiteSpace(StringBuffer *p){
  return stringBufferLength(p)>0 &&
    safe_isspace(stringBufferData(p)[stringBufferLength(p)-1]);
}

/* If the StringBuffer ends in something other than white space, add a
** single space character to the end.
*/
static void appendWhiteSpace(StringBuffer *p){
  if( stringBufferLength(p)==0 ) return;
  if( !endsInWhiteSpace(p) ) append(p, " ");
}

/* Remove white space from the end of the StringBuffer */
static void trimWhiteSpace(StringBuffer *p){
  while( endsInWhiteSpace(p) ){
    p->b.pData[--p->b.nData-1] = '\0';
  }
}

/*******************************************************************/
/* DLReader is used to read document elements from a doclist.  The
** current docid is cached, so dlrDocid() is fast.  DLReader does not
** own the doclist buffer.
**
** dlrAtEnd - true if there's no more data to read.
** dlrDocid - docid of current document.
** dlrDocData - doclist data for current document (including docid).
** dlrDocDataBytes - length of same.
** dlrAllDataBytes - length of all remaining data.
** dlrPosData - position data for current document.
** dlrPosDataLen - length of pos data for current document (incl POS_END).
** dlrStep - step to current document.
** dlrInit - initial for doclist of given type against given data.
** dlrDestroy - clean up.
**
** Expected usage is something like:
**
**   DLReader reader;
**   dlrInit(&reader, pData, nData);
**   while( !dlrAtEnd(&reader) ){
**     // calls to dlrDocid() and kin.
**     dlrStep(&reader);
**   }
**   dlrDestroy(&reader);
*/
typedef struct DLReader {
  DocListType iType;
  const char *pData;
  int nData;

  sqlite_int64 iDocid;
  int nElement;
} DLReader;

static int dlrAtEnd(DLReader *pReader){
  assert( pReader->nData>=0 );
  return pReader->nData==0;
}
static sqlite_int64 dlrDocid(DLReader *pReader){
  assert( !dlrAtEnd(pReader) );
  return pReader->iDocid;
}
static const char *dlrDocData(DLReader *pReader){
  assert( !dlrAtEnd(pReader) );
  return pReader->pData;
}
static int dlrDocDataBytes(DLReader *pReader){
  assert( !dlrAtEnd(pReader) );
  return pReader->nElement;
}
static int dlrAllDataBytes(DLReader *pReader){
  assert( !dlrAtEnd(pReader) );
  return pReader->nData;
}
/* TODO(shess) Consider adding a field to track iDocid varint length
** to make these two functions faster.  This might matter (a tiny bit)
** for queries.
*/
static const char *dlrPosData(DLReader *pReader){
  sqlite_int64 iDummy;
  int n = getVarint(pReader->pData, &iDummy);
  assert( !dlrAtEnd(pReader) );
  return pReader->pData+n;
}
static int dlrPosDataLen(DLReader *pReader){
  sqlite_int64 iDummy;
  int n = getVarint(pReader->pData, &iDummy);
  assert( !dlrAtEnd(pReader) );
  return pReader->nElement-n;
}
static void dlrStep(DLReader *pReader){
  assert( !dlrAtEnd(pReader) );

  /* Skip past current doclist element. */
  assert( pReader->nElement<=pReader->nData );
  pReader->pData += pReader->nElement;
  pReader->nData -= pReader->nElement;

  /* If there is more data, read the next doclist element. */
  if( pReader->nData!=0 ){
    sqlite_int64 iDocidDelta;
    int iDummy, n = getVarint(pReader->pData, &iDocidDelta);
    pReader->iDocid += iDocidDelta;
    if( pReader->iType>=DL_POSITIONS ){
      assert( n<pReader->nData );
      while( 1 ){
        n += getVarint32(pReader->pData+n, &iDummy);
        assert( n<=pReader->nData );
        if( iDummy==POS_END ) break;
        if( iDummy==POS_COLUMN ){
          n += getVarint32(pReader->pData+n, &iDummy);
          assert( n<pReader->nData );
        }else if( pReader->iType==DL_POSITIONS_OFFSETS ){
          n += getVarint32(pReader->pData+n, &iDummy);
          n += getVarint32(pReader->pData+n, &iDummy);
          assert( n<pReader->nData );
        }
      }
    }
    pReader->nElement = n;
    assert( pReader->nElement<=pReader->nData );
  }
}
static void dlrInit(DLReader *pReader, DocListType iType,
                    const char *pData, int nData){
  assert( pData!=NULL && nData!=0 );
  pReader->iType = iType;
  pReader->pData = pData;
  pReader->nData = nData;
  pReader->nElement = 0;
  pReader->iDocid = 0;

  /* Load the first element's data.  There must be a first element. */
  dlrStep(pReader);
}
static void dlrDestroy(DLReader *pReader){
  SCRAMBLE(pReader);
}

#ifndef NDEBUG
/* Verify that the doclist can be validly decoded.  Also returns the
** last docid found because it is convenient in other assertions for
** DLWriter.
*/
static void docListValidate(DocListType iType, const char *pData, int nData,
                            sqlite_int64 *pLastDocid){
  sqlite_int64 iPrevDocid = 0;
  assert( nData>0 );
  assert( pData!=0 );
  assert( pData+nData>pData );
  while( nData!=0 ){
    sqlite_int64 iDocidDelta;
    int n = getVarint(pData, &iDocidDelta);
    iPrevDocid += iDocidDelta;
    if( iType>DL_DOCIDS ){
      int iDummy;
      while( 1 ){
        n += getVarint32(pData+n, &iDummy);
        if( iDummy==POS_END ) break;
        if( iDummy==POS_COLUMN ){
          n += getVarint32(pData+n, &iDummy);
        }else if( iType>DL_POSITIONS ){
          n += getVarint32(pData+n, &iDummy);
          n += getVarint32(pData+n, &iDummy);
        }
        assert( n<=nData );
      }
    }
    assert( n<=nData );
    pData += n;
    nData -= n;
  }
  if( pLastDocid ) *pLastDocid = iPrevDocid;
}
#define ASSERT_VALID_DOCLIST(i, p, n, o) docListValidate(i, p, n, o)
#else
#define ASSERT_VALID_DOCLIST(i, p, n, o) assert( 1 )
#endif

/*******************************************************************/
/* DLWriter is used to write doclist data to a DataBuffer.  DLWriter
** always appends to the buffer and does not own it.
**
** dlwInit - initialize to write a given type doclistto a buffer.
** dlwDestroy - clear the writer's memory.  Does not free buffer.
** dlwAppend - append raw doclist data to buffer.
** dlwCopy - copy next doclist from reader to writer.
** dlwAdd - construct doclist element and append to buffer.
**    Only apply dlwAdd() to DL_DOCIDS doclists (else use PLWriter).
*/
typedef struct DLWriter {
  DocListType iType;
  DataBuffer *b;
  sqlite_int64 iPrevDocid;
#ifndef NDEBUG
  int has_iPrevDocid;
#endif
} DLWriter;

static void dlwInit(DLWriter *pWriter, DocListType iType, DataBuffer *b){
  pWriter->b = b;
  pWriter->iType = iType;
  pWriter->iPrevDocid = 0;
#ifndef NDEBUG
  pWriter->has_iPrevDocid = 0;
#endif
}
static void dlwDestroy(DLWriter *pWriter){
  SCRAMBLE(pWriter);
}
/* iFirstDocid is the first docid in the doclist in pData.  It is
** needed because pData may point within a larger doclist, in which
** case the first item would be delta-encoded.
**
** iLastDocid is the final docid in the doclist in pData.  It is
** needed to create the new iPrevDocid for future delta-encoding.  The
** code could decode the passed doclist to recreate iLastDocid, but
** the only current user (docListMerge) already has decoded this
** information.
*/
/* TODO(shess) This has become just a helper for docListMerge.
** Consider a refactor to make this cleaner.
*/
static void dlwAppend(DLWriter *pWriter,
                      const char *pData, int nData,
                      sqlite_int64 iFirstDocid, sqlite_int64 iLastDocid){
  sqlite_int64 iDocid = 0;
  char c[VARINT_MAX];
  int nFirstOld, nFirstNew;     /* Old and new varint len of first docid. */
#ifndef NDEBUG
  sqlite_int64 iLastDocidDelta;
#endif

  /* Recode the initial docid as delta from iPrevDocid. */
  nFirstOld = getVarint(pData, &iDocid);
  assert( nFirstOld<nData || (nFirstOld==nData && pWriter->iType==DL_DOCIDS) );
  nFirstNew = putVarint(c, iFirstDocid-pWriter->iPrevDocid);

  /* Verify that the incoming doclist is valid AND that it ends with
  ** the expected docid.  This is essential because we'll trust this
  ** docid in future delta-encoding.
  */
  ASSERT_VALID_DOCLIST(pWriter->iType, pData, nData, &iLastDocidDelta);
  assert( iLastDocid==iFirstDocid-iDocid+iLastDocidDelta );

  /* Append recoded initial docid and everything else.  Rest of docids
  ** should have been delta-encoded from previous initial docid.
  */
  if( nFirstOld<nData ){
    dataBufferAppend2(pWriter->b, c, nFirstNew,
                      pData+nFirstOld, nData-nFirstOld);
  }else{
    dataBufferAppend(pWriter->b, c, nFirstNew);
  }
  pWriter->iPrevDocid = iLastDocid;
}
static void dlwCopy(DLWriter *pWriter, DLReader *pReader){
  dlwAppend(pWriter, dlrDocData(pReader), dlrDocDataBytes(pReader),
            dlrDocid(pReader), dlrDocid(pReader));
}
static void dlwAdd(DLWriter *pWriter, sqlite_int64 iDocid){
  char c[VARINT_MAX];
  int n = putVarint(c, iDocid-pWriter->iPrevDocid);

  /* Docids must ascend. */
  assert( !pWriter->has_iPrevDocid || iDocid>pWriter->iPrevDocid );
  assert( pWriter->iType==DL_DOCIDS );

  dataBufferAppend(pWriter->b, c, n);
  pWriter->iPrevDocid = iDocid;
#ifndef NDEBUG
  pWriter->has_iPrevDocid = 1;
#endif
}

/*******************************************************************/
/* PLReader is used to read data from a document's position list.  As
** the caller steps through the list, data is cached so that varints
** only need to be decoded once.
**
** plrInit, plrDestroy - create/destroy a reader.
** plrColumn, plrPosition, plrStartOffset, plrEndOffset - accessors
** plrAtEnd - at end of stream, only call plrDestroy once true.
** plrStep - step to the next element.
*/
typedef struct PLReader {
  /* These refer to the next position's data.  nData will reach 0 when
  ** reading the last position, so plrStep() signals EOF by setting
  ** pData to NULL.
  */
  const char *pData;
  int nData;

  DocListType iType;
  int iColumn;         /* the last column read */
  int iPosition;       /* the last position read */
  int iStartOffset;    /* the last start offset read */
  int iEndOffset;      /* the last end offset read */
} PLReader;

static int plrAtEnd(PLReader *pReader){
  return pReader->pData==NULL;
}
static int plrColumn(PLReader *pReader){
  assert( !plrAtEnd(pReader) );
  return pReader->iColumn;
}
static int plrPosition(PLReader *pReader){
  assert( !plrAtEnd(pReader) );
  return pReader->iPosition;
}
static int plrStartOffset(PLReader *pReader){
  assert( !plrAtEnd(pReader) );
  return pReader->iStartOffset;
}
static int plrEndOffset(PLReader *pReader){
  assert( !plrAtEnd(pReader) );
  return pReader->iEndOffset;
}
static void plrStep(PLReader *pReader){
  int i, n;

  assert( !plrAtEnd(pReader) );

  if( pReader->nData==0 ){
    pReader->pData = NULL;
    return;
  }

  n = getVarint32(pReader->pData, &i);
  if( i==POS_COLUMN ){
    n += getVarint32(pReader->pData+n, &pReader->iColumn);
    pReader->iPosition = 0;
    pReader->iStartOffset = 0;
    n += getVarint32(pReader->pData+n, &i);
  }
  /* Should never see adjacent column changes. */
  assert( i!=POS_COLUMN );

  if( i==POS_END ){
    pReader->nData = 0;
    pReader->pData = NULL;
    return;
  }

  pReader->iPosition += i-POS_BASE;
  if( pReader->iType==DL_POSITIONS_OFFSETS ){
    n += getVarint32(pReader->pData+n, &i);
    pReader->iStartOffset += i;
    n += getVarint32(pReader->pData+n, &i);
    pReader->iEndOffset = pReader->iStartOffset+i;
  }
  assert( n<=pReader->nData );
  pReader->pData += n;
  pReader->nData -= n;
}

static void plrInit(PLReader *pReader, DLReader *pDLReader){
  pReader->pData = dlrPosData(pDLReader);
  pReader->nData = dlrPosDataLen(pDLReader);
  pReader->iType = pDLReader->iType;
  pReader->iColumn = 0;
  pReader->iPosition = 0;
  pReader->iStartOffset = 0;
  pReader->iEndOffset = 0;
  plrStep(pReader);
}
static void plrDestroy(PLReader *pReader){
  SCRAMBLE(pReader);
}

/*******************************************************************/
/* PLWriter is used in constructing a document's position list.  As a
** convenience, if iType is DL_DOCIDS, PLWriter becomes a no-op.
** PLWriter writes to the associated DLWriter's buffer.
**
** plwInit - init for writing a document's poslist.
** plwDestroy - clear a writer.
** plwAdd - append position and offset information.
** plwCopy - copy next position's data from reader to writer.
** plwTerminate - add any necessary doclist terminator.
**
** Calling plwAdd() after plwTerminate() may result in a corrupt
** doclist.
*/
/* TODO(shess) Until we've written the second item, we can cache the
** first item's information.  Then we'd have three states:
**
** - initialized with docid, no positions.
** - docid and one position.
** - docid and multiple positions.
**
** Only the last state needs to actually write to dlw->b, which would
** be an improvement in the DLCollector case.
*/
typedef struct PLWriter {
  DLWriter *dlw;

  int iColumn;    /* the last column written */
  int iPos;       /* the last position written */
  int iOffset;    /* the last start offset written */
} PLWriter;

/* TODO(shess) In the case where the parent is reading these values
** from a PLReader, we could optimize to a copy if that PLReader has
** the same type as pWriter.
*/
static void plwAdd(PLWriter *pWriter, int iColumn, int iPos,
                   int iStartOffset, int iEndOffset){
  /* Worst-case space for POS_COLUMN, iColumn, iPosDelta,
  ** iStartOffsetDelta, and iEndOffsetDelta.
  */
  char c[5*VARINT_MAX];
  int n = 0;

  /* Ban plwAdd() after plwTerminate(). */
  assert( pWriter->iPos!=-1 );

  if( pWriter->dlw->iType==DL_DOCIDS ) return;

  if( iColumn!=pWriter->iColumn ){
    n += putVarint(c+n, POS_COLUMN);
    n += putVarint(c+n, iColumn);
    pWriter->iColumn = iColumn;
    pWriter->iPos = 0;
    pWriter->iOffset = 0;
  }
  assert( iPos>=pWriter->iPos );
  n += putVarint(c+n, POS_BASE+(iPos-pWriter->iPos));
  pWriter->iPos = iPos;
  if( pWriter->dlw->iType==DL_POSITIONS_OFFSETS ){
    assert( iStartOffset>=pWriter->iOffset );
    n += putVarint(c+n, iStartOffset-pWriter->iOffset);
    pWriter->iOffset = iStartOffset;
    assert( iEndOffset>=iStartOffset );
    n += putVarint(c+n, iEndOffset-iStartOffset);
  }
  dataBufferAppend(pWriter->dlw->b, c, n);
}
static void plwCopy(PLWriter *pWriter, PLReader *pReader){
  plwAdd(pWriter, plrColumn(pReader), plrPosition(pReader),
         plrStartOffset(pReader), plrEndOffset(pReader));
}
static void plwInit(PLWriter *pWriter, DLWriter *dlw, sqlite_int64 iDocid){
  char c[VARINT_MAX];
  int n;

  pWriter->dlw = dlw;

  /* Docids must ascend. */
  assert( !pWriter->dlw->has_iPrevDocid || iDocid>pWriter->dlw->iPrevDocid );
  n = putVarint(c, iDocid-pWriter->dlw->iPrevDocid);
  dataBufferAppend(pWriter->dlw->b, c, n);
  pWriter->dlw->iPrevDocid = iDocid;
#ifndef NDEBUG
  pWriter->dlw->has_iPrevDocid = 1;
#endif

  pWriter->iColumn = 0;
  pWriter->iPos = 0;
  pWriter->iOffset = 0;
}
/* TODO(shess) Should plwDestroy() also terminate the doclist?  But
** then plwDestroy() would no longer be just a destructor, it would
** also be doing work, which isn't consistent with the overall idiom.
** Another option would be for plwAdd() to always append any necessary
** terminator, so that the output is always correct.  But that would
** add incremental work to the common case with the only benefit being
** API elegance.  Punt for now.
*/
static void plwTerminate(PLWriter *pWriter){
  if( pWriter->dlw->iType>DL_DOCIDS ){
    char c[VARINT_MAX];
    int n = putVarint(c, POS_END);
    dataBufferAppend(pWriter->dlw->b, c, n);
  }
#ifndef NDEBUG
  /* Mark as terminated for assert in plwAdd(). */
  pWriter->iPos = -1;
#endif
}
static void plwDestroy(PLWriter *pWriter){
  SCRAMBLE(pWriter);
}

/*******************************************************************/
/* DLCollector wraps PLWriter and DLWriter to provide a
** dynamically-allocated doclist area to use during tokenization.
**
** dlcNew - malloc up and initialize a collector.
** dlcDelete - destroy a collector and all contained items.
** dlcAddPos - append position and offset information.
** dlcAddDoclist - add the collected doclist to the given buffer.
** dlcNext - terminate the current document and open another.
*/
typedef struct DLCollector {
  DataBuffer b;
  DLWriter dlw;
  PLWriter plw;
} DLCollector;

/* TODO(shess) This could also be done by calling plwTerminate() and
** dataBufferAppend().  I tried that, expecting nominal performance
** differences, but it seemed to pretty reliably be worth 1% to code
** it this way.  I suspect it is the incremental malloc overhead (some
** percentage of the plwTerminate() calls will cause a realloc), so
** this might be worth revisiting if the DataBuffer implementation
** changes.
*/
static void dlcAddDoclist(DLCollector *pCollector, DataBuffer *b){
  if( pCollector->dlw.iType>DL_DOCIDS ){
    char c[VARINT_MAX];
    int n = putVarint(c, POS_END);
    dataBufferAppend2(b, pCollector->b.pData, pCollector->b.nData, c, n);
  }else{
    dataBufferAppend(b, pCollector->b.pData, pCollector->b.nData);
  }
}
static void dlcNext(DLCollector *pCollector, sqlite_int64 iDocid){
  plwTerminate(&pCollector->plw);
  plwDestroy(&pCollector->plw);
  plwInit(&pCollector->plw, &pCollector->dlw, iDocid);
}
static void dlcAddPos(DLCollector *pCollector, int iColumn, int iPos,
                      int iStartOffset, int iEndOffset){
  plwAdd(&pCollector->plw, iColumn, iPos, iStartOffset, iEndOffset);
}

static DLCollector *dlcNew(sqlite_int64 iDocid, DocListType iType){
  DLCollector *pCollector = sqlite3_malloc(sizeof(DLCollector));
  dataBufferInit(&pCollector->b, 0);
  dlwInit(&pCollector->dlw, iType, &pCollector->b);
  plwInit(&pCollector->plw, &pCollector->dlw, iDocid);
  return pCollector;
}
static void dlcDelete(DLCollector *pCollector){
  plwDestroy(&pCollector->plw);
  dlwDestroy(&pCollector->dlw);
  dataBufferDestroy(&pCollector->b);
  SCRAMBLE(pCollector);
  sqlite3_free(pCollector);
}


/* Copy the doclist data of iType in pData/nData into *out, trimming
** unnecessary data as we go.  Only columns matching iColumn are
** copied, all columns copied if iColumn is -1.  Elements with no
** matching columns are dropped.  The output is an iOutType doclist.
*/
/* NOTE(shess) This code is only valid after all doclists are merged.
** If this is run before merges, then doclist items which represent
** deletion will be trimmed, and will thus not effect a deletion
** during the merge.
*/
static void docListTrim(DocListType iType, const char *pData, int nData,
                        int iColumn, DocListType iOutType, DataBuffer *out){
  DLReader dlReader;
  DLWriter dlWriter;

  assert( iOutType<=iType );

  dlrInit(&dlReader, iType, pData, nData);
  dlwInit(&dlWriter, iOutType, out);

  while( !dlrAtEnd(&dlReader) ){
    PLReader plReader;
    PLWriter plWriter;
    int match = 0;

    plrInit(&plReader, &dlReader);

    while( !plrAtEnd(&plReader) ){
      if( iColumn==-1 || plrColumn(&plReader)==iColumn ){
        if( !match ){
          plwInit(&plWriter, &dlWriter, dlrDocid(&dlReader));
          match = 1;
        }
        plwAdd(&plWriter, plrColumn(&plReader), plrPosition(&plReader),
               plrStartOffset(&plReader), plrEndOffset(&plReader));
      }
      plrStep(&plReader);
    }
    if( match ){
      plwTerminate(&plWriter);
      plwDestroy(&plWriter);
    }

    plrDestroy(&plReader);
    dlrStep(&dlReader);
  }
  dlwDestroy(&dlWriter);
  dlrDestroy(&dlReader);
}

/* Used by docListMerge() to keep doclists in the ascending order by
** docid, then ascending order by age (so the newest comes first).
*/
typedef struct OrderedDLReader {
  DLReader *pReader;

  /* TODO(shess) If we assume that docListMerge pReaders is ordered by
  ** age (which we do), then we could use pReader comparisons to break
  ** ties.
  */
  int idx;
} OrderedDLReader;

/* Order eof to end, then by docid asc, idx desc. */
static int orderedDLReaderCmp(OrderedDLReader *r1, OrderedDLReader *r2){
  if( dlrAtEnd(r1->pReader) ){
    if( dlrAtEnd(r2->pReader) ) return 0;  /* Both atEnd(). */
    return 1;                              /* Only r1 atEnd(). */
  }
  if( dlrAtEnd(r2->pReader) ) return -1;   /* Only r2 atEnd(). */

  if( dlrDocid(r1->pReader)<dlrDocid(r2->pReader) ) return -1;
  if( dlrDocid(r1->pReader)>dlrDocid(r2->pReader) ) return 1;

  /* Descending on idx. */
  return r2->idx-r1->idx;
}

/* Bubble p[0] to appropriate place in p[1..n-1].  Assumes that
** p[1..n-1] is already sorted.
*/
/* TODO(shess) Is this frequent enough to warrant a binary search?
** Before implementing that, instrument the code to check.  In most
** current usage, I expect that p[0] will be less than p[1] a very
** high proportion of the time.
*/
static void orderedDLReaderReorder(OrderedDLReader *p, int n){
  while( n>1 && orderedDLReaderCmp(p, p+1)>0 ){
    OrderedDLReader tmp = p[0];
    p[0] = p[1];
    p[1] = tmp;
    n--;
    p++;
  }
}

/* Given an array of doclist readers, merge their doclist elements
** into out in sorted order (by docid), dropping elements from older
** readers when there is a duplicate docid.  pReaders is assumed to be
** ordered by age, oldest first.
*/
/* TODO(shess) nReaders must be <= MERGE_COUNT.  This should probably
** be fixed.
*/
static void docListMerge(DataBuffer *out,
                         DLReader *pReaders, int nReaders){
  OrderedDLReader readers[MERGE_COUNT];
  DLWriter writer;
  int i, n;
  const char *pStart = 0;
  int nStart = 0;
  sqlite_int64 iFirstDocid = 0, iLastDocid = 0;

  assert( nReaders>0 );
  if( nReaders==1 ){
    dataBufferAppend(out, dlrDocData(pReaders), dlrAllDataBytes(pReaders));
    return;
  }

  assert( nReaders<=MERGE_COUNT );
  n = 0;
  for(i=0; i<nReaders; i++){
    assert( pReaders[i].iType==pReaders[0].iType );
    readers[i].pReader = pReaders+i;
    readers[i].idx = i;
    n += dlrAllDataBytes(&pReaders[i]);
  }
  /* Conservatively size output to sum of inputs.  Output should end
  ** up strictly smaller than input.
  */
  dataBufferExpand(out, n);

  /* Get the readers into sorted order. */
  while( i-->0 ){
    orderedDLReaderReorder(readers+i, nReaders-i);
  }

  dlwInit(&writer, pReaders[0].iType, out);
  while( !dlrAtEnd(readers[0].pReader) ){
    sqlite_int64 iDocid = dlrDocid(readers[0].pReader);

    /* If this is a continuation of the current buffer to copy, extend
    ** that buffer.  memcpy() seems to be more efficient if it has a
    ** lots of data to copy.
    */
    if( dlrDocData(readers[0].pReader)==pStart+nStart ){
      nStart += dlrDocDataBytes(readers[0].pReader);
    }else{
      if( pStart!=0 ){
        dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid);
      }
      pStart = dlrDocData(readers[0].pReader);
      nStart = dlrDocDataBytes(readers[0].pReader);
      iFirstDocid = iDocid;
    }
    iLastDocid = iDocid;
    dlrStep(readers[0].pReader);

    /* Drop all of the older elements with the same docid. */
    for(i=1; i<nReaders &&
             !dlrAtEnd(readers[i].pReader) &&
             dlrDocid(readers[i].pReader)==iDocid; i++){
      dlrStep(readers[i].pReader);
    }

    /* Get the readers back into order. */
    while( i-->0 ){
      orderedDLReaderReorder(readers+i, nReaders-i);
    }
  }

  /* Copy over any remaining elements. */
  if( nStart>0 ) dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid);
  dlwDestroy(&writer);
}

/* Helper function for posListUnion().  Compares the current position
** between left and right, returning as standard C idiom of <0 if
** left<right, >0 if left>right, and 0 if left==right.  "End" always
** compares greater.
*/
static int posListCmp(PLReader *pLeft, PLReader *pRight){
  assert( pLeft->iType==pRight->iType );
  if( pLeft->iType==DL_DOCIDS ) return 0;

  if( plrAtEnd(pLeft) ) return plrAtEnd(pRight) ? 0 : 1;
  if( plrAtEnd(pRight) ) return -1;

  if( plrColumn(pLeft)<plrColumn(pRight) ) return -1;
  if( plrColumn(pLeft)>plrColumn(pRight) ) return 1;

  if( plrPosition(pLeft)<plrPosition(pRight) ) return -1;
  if( plrPosition(pLeft)>plrPosition(pRight) ) return 1;
  if( pLeft->iType==DL_POSITIONS ) return 0;

  if( plrStartOffset(pLeft)<plrStartOffset(pRight) ) return -1;
  if( plrStartOffset(pLeft)>plrStartOffset(pRight) ) return 1;

  if( plrEndOffset(pLeft)<plrEndOffset(pRight) ) return -1;
  if( plrEndOffset(pLeft)>plrEndOffset(pRight) ) return 1;

  return 0;
}

/* Write the union of position lists in pLeft and pRight to pOut.
** "Union" in this case meaning "All unique position tuples".  Should
** work with any doclist type, though both inputs and the output
** should be the same type.
*/
static void posListUnion(DLReader *pLeft, DLReader *pRight, DLWriter *pOut){
  PLReader left, right;
  PLWriter writer;

  assert( dlrDocid(pLeft)==dlrDocid(pRight) );
  assert( pLeft->iType==pRight->iType );
  assert( pLeft->iType==pOut->iType );

  plrInit(&left, pLeft);
  plrInit(&right, pRight);
  plwInit(&writer, pOut, dlrDocid(pLeft));

  while( !plrAtEnd(&left) || !plrAtEnd(&right) ){
    int c = posListCmp(&left, &right);
    if( c<0 ){
      plwCopy(&writer, &left);
      plrStep(&left);
    }else if( c>0 ){
      plwCopy(&writer, &right);
      plrStep(&right);
    }else{
      plwCopy(&writer, &left);
      plrStep(&left);
      plrStep(&right);
    }
  }

  plwTerminate(&writer);
  plwDestroy(&writer);
  plrDestroy(&left);
  plrDestroy(&right);
}

/* Write the union of doclists in pLeft and pRight to pOut.  For
** docids in common between the inputs, the union of the position
** lists is written.  Inputs and outputs are always type DL_DEFAULT.
*/
static void docListUnion(
  const char *pLeft, int nLeft,
  const char *pRight, int nRight,
  DataBuffer *pOut      /* Write the combined doclist here */
){
  DLReader left, right;
  DLWriter writer;

  if( nLeft==0 ){
    if( nRight!=0) dataBufferAppend(pOut, pRight, nRight);
    return;
  }
  if( nRight==0 ){
    dataBufferAppend(pOut, pLeft, nLeft);
    return;
  }

  dlrInit(&left, DL_DEFAULT, pLeft, nLeft);
  dlrInit(&right, DL_DEFAULT, pRight, nRight);
  dlwInit(&writer, DL_DEFAULT, pOut);

  while( !dlrAtEnd(&left) || !dlrAtEnd(&right) ){
    if( dlrAtEnd(&right) ){
      dlwCopy(&writer, &left);
      dlrStep(&left);
    }else if( dlrAtEnd(&left) ){
      dlwCopy(&writer, &right);
      dlrStep(&right);
    }else if( dlrDocid(&left)<dlrDocid(&right) ){
      dlwCopy(&writer, &left);
      dlrStep(&left);
    }else if( dlrDocid(&left)>dlrDocid(&right) ){
      dlwCopy(&writer, &right);
      dlrStep(&right);
    }else{
      posListUnion(&left, &right, &writer);
      dlrStep(&left);
      dlrStep(&right);
    }
  }

  dlrDestroy(&left);
  dlrDestroy(&right);
  dlwDestroy(&writer);
}

/* pLeft and pRight are DLReaders positioned to the same docid.
**
** If there are no instances in pLeft or pRight where the position
** of pLeft is one less than the position of pRight, then this
** routine adds nothing to pOut.
**
** If there are one or more instances where positions from pLeft
** are exactly one less than positions from pRight, then add a new
** document record to pOut.  If pOut wants to hold positions, then
** include the positions from pRight that are one more than a
** position in pLeft.  In other words:  pRight.iPos==pLeft.iPos+1.
*/
static void posListPhraseMerge(DLReader *pLeft, DLReader *pRight,
                               DLWriter *pOut){
  PLReader left, right;
  PLWriter writer;
  int match = 0;

  assert( dlrDocid(pLeft)==dlrDocid(pRight) );
  assert( pOut->iType!=DL_POSITIONS_OFFSETS );

  plrInit(&left, pLeft);
  plrInit(&right, pRight);

  while( !plrAtEnd(&left) && !plrAtEnd(&right) ){
    if( plrColumn(&left)<plrColumn(&right) ){
      plrStep(&left);
    }else if( plrColumn(&left)>plrColumn(&right) ){
      plrStep(&right);
    }else if( plrPosition(&left)+1<plrPosition(&right) ){
      plrStep(&left);
    }else if( plrPosition(&left)+1>plrPosition(&right) ){
      plrStep(&right);
    }else{
      if( !match ){
        plwInit(&writer, pOut, dlrDocid(pLeft));
        match = 1;
      }
      plwAdd(&writer, plrColumn(&right), plrPosition(&right), 0, 0);
      plrStep(&left);
      plrStep(&right);
    }
  }

  if( match ){
    plwTerminate(&writer);
    plwDestroy(&writer);
  }

  plrDestroy(&left);
  plrDestroy(&right);
}

/* We have two doclists with positions:  pLeft and pRight.
** Write the phrase intersection of these two doclists into pOut.
**
** A phrase intersection means that two documents only match
** if pLeft.iPos+1==pRight.iPos.
**
** iType controls the type of data written to pOut.  If iType is
** DL_POSITIONS, the positions are those from pRight.
*/
static void docListPhraseMerge(
  const char *pLeft, int nLeft,
  const char *pRight, int nRight,
  DocListType iType,
  DataBuffer *pOut      /* Write the combined doclist here */
){
  DLReader left, right;
  DLWriter writer;

  if( nLeft==0 || nRight==0 ) return;

  assert( iType!=DL_POSITIONS_OFFSETS );

  dlrInit(&left, DL_POSITIONS, pLeft, nLeft);
  dlrInit(&right, DL_POSITIONS, pRight, nRight);
  dlwInit(&writer, iType, pOut);

  while( !dlrAtEnd(&left) && !dlrAtEnd(&right) ){
    if( dlrDocid(&left)<dlrDocid(&right) ){
      dlrStep(&left);
    }else if( dlrDocid(&right)<dlrDocid(&left) ){
      dlrStep(&right);
    }else{
      posListPhraseMerge(&left, &right, &writer);
      dlrStep(&left);
      dlrStep(&right);
    }
  }

  dlrDestroy(&left);
  dlrDestroy(&right);
  dlwDestroy(&writer);
}

/* We have two DL_DOCIDS doclists:  pLeft and pRight.
** Write the intersection of these two doclists into pOut as a
** DL_DOCIDS doclist.
*/
static void docListAndMerge(
  const char *pLeft, int nLeft,
  const char *pRight, int nRight,
  DataBuffer *pOut      /* Write the combined doclist here */
){
  DLReader left, right;
  DLWriter writer;

  if( nLeft==0 || nRight==0 ) return;

  dlrInit(&left, DL_DOCIDS, pLeft, nLeft);
  dlrInit(&right, DL_DOCIDS, pRight, nRight);
  dlwInit(&writer, DL_DOCIDS, pOut);

  while( !dlrAtEnd(&left) && !dlrAtEnd(&right) ){
    if( dlrDocid(&left)<dlrDocid(&right) ){
      dlrStep(&left);
    }else if( dlrDocid(&right)<dlrDocid(&left) ){
      dlrStep(&right);
    }else{
      dlwAdd(&writer, dlrDocid(&left));
      dlrStep(&left);
      dlrStep(&right);
    }
  }

  dlrDestroy(&left);
  dlrDestroy(&right);
  dlwDestroy(&writer);
}

/* We have two DL_DOCIDS doclists:  pLeft and pRight.
** Write the union of these two doclists into pOut as a
** DL_DOCIDS doclist.
*/
static void docListOrMerge(
  const char *pLeft, int nLeft,
  const char *pRight, int nRight,
  DataBuffer *pOut      /* Write the combined doclist here */
){
  DLReader left, right;
  DLWriter writer;

  if( nLeft==0 ){
    if( nRight!=0 ) dataBufferAppend(pOut, pRight, nRight);
    return;
  }
  if( nRight==0 ){
    dataBufferAppend(pOut, pLeft, nLeft);
    return;
  }

  dlrInit(&left, DL_DOCIDS, pLeft, nLeft);
  dlrInit(&right, DL_DOCIDS, pRight, nRight);
  dlwInit(&writer, DL_DOCIDS, pOut);

  while( !dlrAtEnd(&left) || !dlrAtEnd(&right) ){
    if( dlrAtEnd(&right) ){
      dlwAdd(&writer, dlrDocid(&left));
      dlrStep(&left);
    }else if( dlrAtEnd(&left) ){
      dlwAdd(&writer, dlrDocid(&right));
      dlrStep(&right);
    }else if( dlrDocid(&left)<dlrDocid(&right) ){
      dlwAdd(&writer, dlrDocid(&left));
      dlrStep(&left);
    }else if( dlrDocid(&right)<dlrDocid(&left) ){
      dlwAdd(&writer, dlrDocid(&right));
      dlrStep(&right);
    }else{
      dlwAdd(&writer, dlrDocid(&left));
      dlrStep(&left);
      dlrStep(&right);
    }
  }

  dlrDestroy(&left);
  dlrDestroy(&right);
  dlwDestroy(&writer);
}

/* We have two DL_DOCIDS doclists:  pLeft and pRight.
** Write into pOut as DL_DOCIDS doclist containing all documents that
** occur in pLeft but not in pRight.
*/
static void docListExceptMerge(
  const char *pLeft, int nLeft,
  const char *pRight, int nRight,
  DataBuffer *pOut      /* Write the combined doclist here */
){
  DLReader left, right;
  DLWriter writer;

  if( nLeft==0 ) return;
  if( nRight==0 ){
    dataBufferAppend(pOut, pLeft, nLeft);
    return;
  }

  dlrInit(&left, DL_DOCIDS, pLeft, nLeft);
  dlrInit(&right, DL_DOCIDS, pRight, nRight);
  dlwInit(&writer, DL_DOCIDS, pOut);

  while( !dlrAtEnd(&left) ){
    while( !dlrAtEnd(&right) && dlrDocid(&right)<dlrDocid(&left) ){
      dlrStep(&right);
    }
    if( dlrAtEnd(&right) || dlrDocid(&left)<dlrDocid(&right) ){
      dlwAdd(&writer, dlrDocid(&left));
    }
    dlrStep(&left);
  }

  dlrDestroy(&left);
  dlrDestroy(&right);
  dlwDestroy(&writer);
}

static char *string_dup_n(const char *s, int n){
  char *str = sqlite3_malloc(n + 1);
  memcpy(str, s, n);
  str[n] = '\0';
  return str;
}

/* Duplicate a string; the caller must free() the returned string.
 * (We don't use strdup() since it is not part of the standard C library and
 * may not be available everywhere.) */
static char *string_dup(const char *s){
  return string_dup_n(s, strlen(s));
}

/* Format a string, replacing each occurrence of the % character with
 * zDb.zName.  This may be more convenient than sqlite_mprintf()
 * when one string is used repeatedly in a format string.
 * The caller must free() the returned string. */
static char *string_format(const char *zFormat,
                           const char *zDb, const char *zName){
  const char *p;
  size_t len = 0;
  size_t nDb = strlen(zDb);
  size_t nName = strlen(zName);
  size_t nFullTableName = nDb+1+nName;
  char *result;
  char *r;

  /* first compute length needed */
  for(p = zFormat ; *p ; ++p){
    len += (*p=='%' ? nFullTableName : 1);
  }
  len += 1;  /* for null terminator */

  r = result = sqlite3_malloc(len);
  for(p = zFormat; *p; ++p){
    if( *p=='%' ){
      memcpy(r, zDb, nDb);
      r += nDb;
      *r++ = '.';
      memcpy(r, zName, nName);
      r += nName;
    } else {
      *r++ = *p;
    }
  }
  *r++ = '\0';
  assert( r == result + len );
  return result;
}

static int sql_exec(sqlite3 *db, const char *zDb, const char *zName,
                    const char *zFormat){
  char *zCommand = string_format(zFormat, zDb, zName);
  int rc;
  TRACE(("FTS2 sql: %s\n", zCommand));
  rc = sqlite3_exec(db, zCommand, NULL, 0, NULL);
  sqlite3_free(zCommand);
  return rc;
}

static int sql_prepare(sqlite3 *db, const char *zDb, const char *zName,
                       sqlite3_stmt **ppStmt, const char *zFormat){
  char *zCommand = string_format(zFormat, zDb, zName);
  int rc;
  TRACE(("FTS2 prepare: %s\n", zCommand));
  rc = sqlite3_prepare_v2(db, zCommand, -1, ppStmt, NULL);
  sqlite3_free(zCommand);
  return rc;
}

/* end utility functions */

/* Forward reference */
typedef struct fulltext_vtab fulltext_vtab;

/* A single term in a query is represented by an instances of
** the following structure.
*/
typedef struct QueryTerm {
  short int nPhrase; /* How many following terms are part of the same phrase */
  short int iPhrase; /* This is the i-th term of a phrase. */
  short int iColumn; /* Column of the index that must match this term */
  signed char isOr;  /* this term is preceded by "OR" */
  signed char isNot; /* this term is preceded by "-" */
  signed char isPrefix; /* this term is followed by "*" */
  char *pTerm;       /* text of the term.  '\000' terminated.  malloced */
  int nTerm;         /* Number of bytes in pTerm[] */
} QueryTerm;


/* A query string is parsed into a Query structure.
 *
 * We could, in theory, allow query strings to be complicated
 * nested expressions with precedence determined by parentheses.
 * But none of the major search engines do this.  (Perhaps the
 * feeling is that an parenthesized expression is two complex of
 * an idea for the average user to grasp.)  Taking our lead from
 * the major search engines, we will allow queries to be a list
 * of terms (with an implied AND operator) or phrases in double-quotes,
 * with a single optional "-" before each non-phrase term to designate
 * negation and an optional OR connector.
 *
 * OR binds more tightly than the implied AND, which is what the
 * major search engines seem to do.  So, for example:
 * 
 *    [one two OR three]     ==>    one AND (two OR three)
 *    [one OR two three]     ==>    (one OR two) AND three
 *
 * A "-" before a term matches all entries that lack that term.
 * The "-" must occur immediately before the term with in intervening
 * space.  This is how the search engines do it.
 *
 * A NOT term cannot be the right-hand operand of an OR.  If this
 * occurs in the query string, the NOT is ignored:
 *
 *    [one OR -two]          ==>    one OR two
 *
 */
typedef struct Query {
  fulltext_vtab *pFts;  /* The full text index */
  int nTerms;           /* Number of terms in the query */
  QueryTerm *pTerms;    /* Array of terms.  Space obtained from malloc() */
  int nextIsOr;         /* Set the isOr flag on the next inserted term */
  int nextColumn;       /* Next word parsed must be in this column */
  int dfltColumn;       /* The default column */
} Query;


/*
** An instance of the following structure keeps track of generated
** matching-word offset information and snippets.
*/
typedef struct Snippet {
  int nMatch;     /* Total number of matches */
  int nAlloc;     /* Space allocated for aMatch[] */
  struct snippetMatch { /* One entry for each matching term */
    char snStatus;       /* Status flag for use while constructing snippets */
    short int iCol;      /* The column that contains the match */
    short int iTerm;     /* The index in Query.pTerms[] of the matching term */
    short int nByte;     /* Number of bytes in the term */
    int iStart;          /* The offset to the first character of the term */
  } *aMatch;      /* Points to space obtained from malloc */
  char *zOffset;  /* Text rendering of aMatch[] */
  int nOffset;    /* strlen(zOffset) */
  char *zSnippet; /* Snippet text */
  int nSnippet;   /* strlen(zSnippet) */
} Snippet;


typedef enum QueryType {
  QUERY_GENERIC,   /* table scan */
  QUERY_ROWID,     /* lookup by rowid */
  QUERY_FULLTEXT   /* QUERY_FULLTEXT + [i] is a full-text search for column i*/
} QueryType;

typedef enum fulltext_statement {
  CONTENT_INSERT_STMT,
  CONTENT_SELECT_STMT,
  CONTENT_UPDATE_STMT,
  CONTENT_DELETE_STMT,
  CONTENT_EXISTS_STMT,

  BLOCK_INSERT_STMT,
  BLOCK_SELECT_STMT,
  BLOCK_DELETE_STMT,
  BLOCK_DELETE_ALL_STMT,

  SEGDIR_MAX_INDEX_STMT,
  SEGDIR_SET_STMT,
  SEGDIR_SELECT_LEVEL_STMT,
  SEGDIR_SPAN_STMT,
  SEGDIR_DELETE_STMT,
  SEGDIR_SELECT_SEGMENT_STMT,
  SEGDIR_SELECT_ALL_STMT,
  SEGDIR_DELETE_ALL_STMT,
  SEGDIR_COUNT_STMT,

  MAX_STMT                     /* Always at end! */
} fulltext_statement;

/* These must exactly match the enum above. */
/* TODO(shess): Is there some risk that a statement will be used in two
** cursors at once, e.g.  if a query joins a virtual table to itself?
** If so perhaps we should move some of these to the cursor object.
*/
static const char *const fulltext_zStatement[MAX_STMT] = {
  /* CONTENT_INSERT */ NULL,  /* generated in contentInsertStatement() */
  /* CONTENT_SELECT */ "select * from %_content where rowid = ?",
  /* CONTENT_UPDATE */ NULL,  /* generated in contentUpdateStatement() */
  /* CONTENT_DELETE */ "delete from %_content where rowid = ?",
  /* CONTENT_EXISTS */ "select rowid from %_content limit 1",

  /* BLOCK_INSERT */ "insert into %_segments values (?)",
  /* BLOCK_SELECT */ "select block from %_segments where rowid = ?",
  /* BLOCK_DELETE */ "delete from %_segments where rowid between ? and ?",
  /* BLOCK_DELETE_ALL */ "delete from %_segments",

  /* SEGDIR_MAX_INDEX */ "select max(idx) from %_segdir where level = ?",
  /* SEGDIR_SET */ "insert into %_segdir values (?, ?, ?, ?, ?, ?)",
  /* SEGDIR_SELECT_LEVEL */
  "select start_block, leaves_end_block, root from %_segdir "
  " where level = ? order by idx",
  /* SEGDIR_SPAN */
  "select min(start_block), max(end_block) from %_segdir "
  " where level = ? and start_block <> 0",
  /* SEGDIR_DELETE */ "delete from %_segdir where level = ?",

  /* NOTE(shess): The first three results of the following two
  ** statements must match.
  */
  /* SEGDIR_SELECT_SEGMENT */
  "select start_block, leaves_end_block, root from %_segdir "
  " where level = ? and idx = ?",
  /* SEGDIR_SELECT_ALL */
  "select start_block, leaves_end_block, root from %_segdir "
  " order by level desc, idx asc",
  /* SEGDIR_DELETE_ALL */ "delete from %_segdir",
  /* SEGDIR_COUNT */ "select count(*), ifnull(max(level),0) from %_segdir",
};

/*
** A connection to a fulltext index is an instance of the following
** structure.  The xCreate and xConnect methods create an instance
** of this structure and xDestroy and xDisconnect free that instance.
** All other methods receive a pointer to the structure as one of their
** arguments.
*/
struct fulltext_vtab {
  sqlite3_vtab base;               /* Base class used by SQLite core */
  sqlite3 *db;                     /* The database connection */
  const char *zDb;                 /* logical database name */
  const char *zName;               /* virtual table name */
  int nColumn;                     /* number of columns in virtual table */
  char **azColumn;                 /* column names.  malloced */
  char **azContentColumn;          /* column names in content table; malloced */
  sqlite3_tokenizer *pTokenizer;   /* tokenizer for inserts and queries */

  /* Precompiled statements which we keep as long as the table is
  ** open.
  */
  sqlite3_stmt *pFulltextStatements[MAX_STMT];

  /* Precompiled statements used for segment merges.  We run a
  ** separate select across the leaf level of each tree being merged.
  */
  sqlite3_stmt *pLeafSelectStmts[MERGE_COUNT];
  /* The statement used to prepare pLeafSelectStmts. */
#define LEAF_SELECT \
  "select block from %_segments where rowid between ? and ? order by rowid"

  /* These buffer pending index updates during transactions.
  ** nPendingData estimates the memory size of the pending data.  It
  ** doesn't include the hash-bucket overhead, nor any malloc
  ** overhead.  When nPendingData exceeds kPendingThreshold, the
  ** buffer is flushed even before the transaction closes.
  ** pendingTerms stores the data, and is only valid when nPendingData
  ** is >=0 (nPendingData<0 means pendingTerms has not been
  ** initialized).  iPrevDocid is the last docid written, used to make
  ** certain we're inserting in sorted order.
  */
  int nPendingData;
#define kPendingThreshold (1*1024*1024)
  sqlite_int64 iPrevDocid;
  fts2Hash pendingTerms;
};

/*
** When the core wants to do a query, it create a cursor using a
** call to xOpen.  This structure is an instance of a cursor.  It
** is destroyed by xClose.
*/
typedef struct fulltext_cursor {
  sqlite3_vtab_cursor base;        /* Base class used by SQLite core */
  QueryType iCursorType;           /* Copy of sqlite3_index_info.idxNum */
  sqlite3_stmt *pStmt;             /* Prepared statement in use by the cursor */
  int eof;                         /* True if at End Of Results */
  Query q;                         /* Parsed query string */
  Snippet snippet;                 /* Cached snippet for the current row */
  int iColumn;                     /* Column being searched */
  DataBuffer result;               /* Doclist results from fulltextQuery */
  DLReader reader;                 /* Result reader if result not empty */
} fulltext_cursor;

static struct fulltext_vtab *cursor_vtab(fulltext_cursor *c){
  return (fulltext_vtab *) c->base.pVtab;
}

static const sqlite3_module fts2Module;   /* forward declaration */

/* Return a dynamically generated statement of the form
 *   insert into %_content (rowid, ...) values (?, ...)
 */
static const char *contentInsertStatement(fulltext_vtab *v){
  StringBuffer sb;
  int i;

  initStringBuffer(&sb);
  append(&sb, "insert into %_content (rowid, ");
  appendList(&sb, v->nColumn, v->azContentColumn);
  append(&sb, ") values (?");
  for(i=0; i<v->nColumn; ++i)
    append(&sb, ", ?");
  append(&sb, ")");
  return stringBufferData(&sb);
}

/* Return a dynamically generated statement of the form
 *   update %_content set [col_0] = ?, [col_1] = ?, ...
 *                    where rowid = ?
 */
static const char *contentUpdateStatement(fulltext_vtab *v){
  StringBuffer sb;
  int i;

  initStringBuffer(&sb);
  append(&sb, "update %_content set ");
  for(i=0; i<v->nColumn; ++i) {
    if( i>0 ){
      append(&sb, ", ");
    }
    append(&sb, v->azContentColumn[i]);
    append(&sb, " = ?");
  }
  append(&sb, " where rowid = ?");
  return stringBufferData(&sb);
}

/* Puts a freshly-prepared statement determined by iStmt in *ppStmt.
** If the indicated statement has never been prepared, it is prepared
** and cached, otherwise the cached version is reset.
*/
static int sql_get_statement(fulltext_vtab *v, fulltext_statement iStmt,
                             sqlite3_stmt **ppStmt){
  assert( iStmt<MAX_STMT );
  if( v->pFulltextStatements[iStmt]==NULL ){
    const char *zStmt;
    int rc;
    switch( iStmt ){
      case CONTENT_INSERT_STMT:
        zStmt = contentInsertStatement(v); break;
      case CONTENT_UPDATE_STMT:
        zStmt = contentUpdateStatement(v); break;
      default:
        zStmt = fulltext_zStatement[iStmt];
    }
    rc = sql_prepare(v->db, v->zDb, v->zName, &v->pFulltextStatements[iStmt],
                         zStmt);
    if( zStmt != fulltext_zStatement[iStmt]) sqlite3_free((void *) zStmt);
    if( rc!=SQLITE_OK ) return rc;
  } else {
    int rc = sqlite3_reset(v->pFulltextStatements[iStmt]);
    if( rc!=SQLITE_OK ) return rc;
  }

  *ppStmt = v->pFulltextStatements[iStmt];
  return SQLITE_OK;
}

/* Like sqlite3_step(), but convert SQLITE_DONE to SQLITE_OK and
** SQLITE_ROW to SQLITE_ERROR.  Useful for statements like UPDATE,
** where we expect no results.
*/
static int sql_single_step(sqlite3_stmt *s){
  int rc = sqlite3_step(s);
  return (rc==SQLITE_DONE) ? SQLITE_OK : rc;
}

/* Like sql_get_statement(), but for special replicated LEAF_SELECT
** statements.  idx -1 is a special case for an uncached version of
** the statement (used in the optimize implementation).
*/
/* TODO(shess) Write version for generic statements and then share
** that between the cached-statement functions.
*/
static int sql_get_leaf_statement(fulltext_vtab *v, int idx,
                                  sqlite3_stmt **ppStmt){
  assert( idx>=-1 && idx<MERGE_COUNT );
  if( idx==-1 ){
    return sql_prepare(v->db, v->zDb, v->zName, ppStmt, LEAF_SELECT);
  }else if( v->pLeafSelectStmts[idx]==NULL ){
    int rc = sql_prepare(v->db, v->zDb, v->zName, &v->pLeafSelectStmts[idx],
                         LEAF_SELECT);
    if( rc!=SQLITE_OK ) return rc;
  }else{
    int rc = sqlite3_reset(v->pLeafSelectStmts[idx]);
    if( rc!=SQLITE_OK ) return rc;
  }

  *ppStmt = v->pLeafSelectStmts[idx];
  return SQLITE_OK;
}

/* insert into %_content (rowid, ...) values ([rowid], [pValues]) */
static int content_insert(fulltext_vtab *v, sqlite3_value *rowid,
                          sqlite3_value **pValues){
  sqlite3_stmt *s;
  int i;
  int rc = sql_get_statement(v, CONTENT_INSERT_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_value(s, 1, rowid);
  if( rc!=SQLITE_OK ) return rc;

  for(i=0; i<v->nColumn; ++i){
    rc = sqlite3_bind_value(s, 2+i, pValues[i]);
    if( rc!=SQLITE_OK ) return rc;
  }

  return sql_single_step(s);
}

/* update %_content set col0 = pValues[0], col1 = pValues[1], ...
 *                  where rowid = [iRowid] */
static int content_update(fulltext_vtab *v, sqlite3_value **pValues,
                          sqlite_int64 iRowid){
  sqlite3_stmt *s;
  int i;
  int rc = sql_get_statement(v, CONTENT_UPDATE_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  for(i=0; i<v->nColumn; ++i){
    rc = sqlite3_bind_value(s, 1+i, pValues[i]);
    if( rc!=SQLITE_OK ) return rc;
  }

  rc = sqlite3_bind_int64(s, 1+v->nColumn, iRowid);
  if( rc!=SQLITE_OK ) return rc;

  return sql_single_step(s);
}

static void freeStringArray(int nString, const char **pString){
  int i;

  for (i=0 ; i < nString ; ++i) {
    if( pString[i]!=NULL ) sqlite3_free((void *) pString[i]);
  }
  sqlite3_free((void *) pString);
}

/* select * from %_content where rowid = [iRow]
 * The caller must delete the returned array and all strings in it.
 * null fields will be NULL in the returned array.
 *
 * TODO: Perhaps we should return pointer/length strings here for consistency
 * with other code which uses pointer/length. */
static int content_select(fulltext_vtab *v, sqlite_int64 iRow,
                          const char ***pValues){
  sqlite3_stmt *s;
  const char **values;
  int i;
  int rc;

  *pValues = NULL;

  rc = sql_get_statement(v, CONTENT_SELECT_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_int64(s, 1, iRow);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_step(s);
  if( rc!=SQLITE_ROW ) return rc;

  values = (const char **) sqlite3_malloc(v->nColumn * sizeof(const char *));
  for(i=0; i<v->nColumn; ++i){
    if( sqlite3_column_type(s, i)==SQLITE_NULL ){
      values[i] = NULL;
    }else{
      values[i] = string_dup((char*)sqlite3_column_text(s, i));
    }
  }

  /* We expect only one row.  We must execute another sqlite3_step()
   * to complete the iteration; otherwise the table will remain locked. */
  rc = sqlite3_step(s);
  if( rc==SQLITE_DONE ){
    *pValues = values;
    return SQLITE_OK;
  }

  freeStringArray(v->nColumn, values);
  return rc;
}

/* delete from %_content where rowid = [iRow ] */
static int content_delete(fulltext_vtab *v, sqlite_int64 iRow){
  sqlite3_stmt *s;
  int rc = sql_get_statement(v, CONTENT_DELETE_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_int64(s, 1, iRow);
  if( rc!=SQLITE_OK ) return rc;

  return sql_single_step(s);
}

/* Returns SQLITE_ROW if any rows exist in %_content, SQLITE_DONE if
** no rows exist, and any error in case of failure.
*/
static int content_exists(fulltext_vtab *v){
  sqlite3_stmt *s;
  int rc = sql_get_statement(v, CONTENT_EXISTS_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_step(s);
  if( rc!=SQLITE_ROW ) return rc;

  /* We expect only one row.  We must execute another sqlite3_step()
   * to complete the iteration; otherwise the table will remain locked. */
  rc = sqlite3_step(s);
  if( rc==SQLITE_DONE ) return SQLITE_ROW;
  if( rc==SQLITE_ROW ) return SQLITE_ERROR;
  return rc;
}

/* insert into %_segments values ([pData])
**   returns assigned rowid in *piBlockid
*/
static int block_insert(fulltext_vtab *v, const char *pData, int nData,
                        sqlite_int64 *piBlockid){
  sqlite3_stmt *s;
  int rc = sql_get_statement(v, BLOCK_INSERT_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_blob(s, 1, pData, nData, SQLITE_STATIC);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_step(s);
  if( rc==SQLITE_ROW ) return SQLITE_ERROR;
  if( rc!=SQLITE_DONE ) return rc;

  *piBlockid = sqlite3_last_insert_rowid(v->db);
  return SQLITE_OK;
}

/* delete from %_segments
**   where rowid between [iStartBlockid] and [iEndBlockid]
**
** Deletes the range of blocks, inclusive, used to delete the blocks
** which form a segment.
*/
static int block_delete(fulltext_vtab *v,
                        sqlite_int64 iStartBlockid, sqlite_int64 iEndBlockid){
  sqlite3_stmt *s;
  int rc = sql_get_statement(v, BLOCK_DELETE_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_int64(s, 1, iStartBlockid);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_int64(s, 2, iEndBlockid);
  if( rc!=SQLITE_OK ) return rc;

  return sql_single_step(s);
}

/* Returns SQLITE_ROW with *pidx set to the maximum segment idx found
** at iLevel.  Returns SQLITE_DONE if there are no segments at
** iLevel.  Otherwise returns an error.
*/
static int segdir_max_index(fulltext_vtab *v, int iLevel, int *pidx){
  sqlite3_stmt *s;
  int rc = sql_get_statement(v, SEGDIR_MAX_INDEX_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_int(s, 1, iLevel);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_step(s);
  /* Should always get at least one row due to how max() works. */
  if( rc==SQLITE_DONE ) return SQLITE_DONE;
  if( rc!=SQLITE_ROW ) return rc;

  /* NULL means that there were no inputs to max(). */
  if( SQLITE_NULL==sqlite3_column_type(s, 0) ){
    rc = sqlite3_step(s);
    if( rc==SQLITE_ROW ) return SQLITE_ERROR;
    return rc;
  }

  *pidx = sqlite3_column_int(s, 0);

  /* We expect only one row.  We must execute another sqlite3_step()
   * to complete the iteration; otherwise the table will remain locked. */
  rc = sqlite3_step(s);
  if( rc==SQLITE_ROW ) return SQLITE_ERROR;
  if( rc!=SQLITE_DONE ) return rc;
  return SQLITE_ROW;
}

/* insert into %_segdir values (
**   [iLevel], [idx],
**   [iStartBlockid], [iLeavesEndBlockid], [iEndBlockid],
**   [pRootData]
** )
*/
static int segdir_set(fulltext_vtab *v, int iLevel, int idx,
                      sqlite_int64 iStartBlockid,
                      sqlite_int64 iLeavesEndBlockid,
                      sqlite_int64 iEndBlockid,
                      const char *pRootData, int nRootData){
  sqlite3_stmt *s;
  int rc = sql_get_statement(v, SEGDIR_SET_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_int(s, 1, iLevel);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_int(s, 2, idx);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_int64(s, 3, iStartBlockid);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_int64(s, 4, iLeavesEndBlockid);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_int64(s, 5, iEndBlockid);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_blob(s, 6, pRootData, nRootData, SQLITE_STATIC);
  if( rc!=SQLITE_OK ) return rc;

  return sql_single_step(s);
}

/* Queries %_segdir for the block span of the segments in level
** iLevel.  Returns SQLITE_DONE if there are no blocks for iLevel,
** SQLITE_ROW if there are blocks, else an error.
*/
static int segdir_span(fulltext_vtab *v, int iLevel,
                       sqlite_int64 *piStartBlockid,
                       sqlite_int64 *piEndBlockid){
  sqlite3_stmt *s;
  int rc = sql_get_statement(v, SEGDIR_SPAN_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_int(s, 1, iLevel);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_step(s);
  if( rc==SQLITE_DONE ) return SQLITE_DONE;  /* Should never happen */
  if( rc!=SQLITE_ROW ) return rc;

  /* This happens if all segments at this level are entirely inline. */
  if( SQLITE_NULL==sqlite3_column_type(s, 0) ){
    /* We expect only one row.  We must execute another sqlite3_step()
     * to complete the iteration; otherwise the table will remain locked. */
    int rc2 = sqlite3_step(s);
    if( rc2==SQLITE_ROW ) return SQLITE_ERROR;
    return rc2;
  }

  *piStartBlockid = sqlite3_column_int64(s, 0);
  *piEndBlockid = sqlite3_column_int64(s, 1);

  /* We expect only one row.  We must execute another sqlite3_step()
   * to complete the iteration; otherwise the table will remain locked. */
  rc = sqlite3_step(s);
  if( rc==SQLITE_ROW ) return SQLITE_ERROR;
  if( rc!=SQLITE_DONE ) return rc;
  return SQLITE_ROW;
}

/* Delete the segment blocks and segment directory records for all
** segments at iLevel.
*/
static int segdir_delete(fulltext_vtab *v, int iLevel){
  sqlite3_stmt *s;
  sqlite_int64 iStartBlockid, iEndBlockid;
  int rc = segdir_span(v, iLevel, &iStartBlockid, &iEndBlockid);
  if( rc!=SQLITE_ROW && rc!=SQLITE_DONE ) return rc;

  if( rc==SQLITE_ROW ){
    rc = block_delete(v, iStartBlockid, iEndBlockid);
    if( rc!=SQLITE_OK ) return rc;
  }

  /* Delete the segment directory itself. */
  rc = sql_get_statement(v, SEGDIR_DELETE_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_int64(s, 1, iLevel);
  if( rc!=SQLITE_OK ) return rc;

  return sql_single_step(s);
}

/* Delete entire fts index, SQLITE_OK on success, relevant error on
** failure.
*/
static int segdir_delete_all(fulltext_vtab *v){
  sqlite3_stmt *s;
  int rc = sql_get_statement(v, SEGDIR_DELETE_ALL_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  rc = sql_single_step(s);
  if( rc!=SQLITE_OK ) return rc;

  rc = sql_get_statement(v, BLOCK_DELETE_ALL_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  return sql_single_step(s);
}

/* Returns SQLITE_OK with *pnSegments set to the number of entries in
** %_segdir and *piMaxLevel set to the highest level which has a
** segment.  Otherwise returns the SQLite error which caused failure.
*/
static int segdir_count(fulltext_vtab *v, int *pnSegments, int *piMaxLevel){
  sqlite3_stmt *s;
  int rc = sql_get_statement(v, SEGDIR_COUNT_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_step(s);
  /* TODO(shess): This case should not be possible?  Should stronger
  ** measures be taken if it happens?
  */
  if( rc==SQLITE_DONE ){
    *pnSegments = 0;
    *piMaxLevel = 0;
    return SQLITE_OK;
  }
  if( rc!=SQLITE_ROW ) return rc;

  *pnSegments = sqlite3_column_int(s, 0);
  *piMaxLevel = sqlite3_column_int(s, 1);

  /* We expect only one row.  We must execute another sqlite3_step()
   * to complete the iteration; otherwise the table will remain locked. */
  rc = sqlite3_step(s);
  if( rc==SQLITE_DONE ) return SQLITE_OK;
  if( rc==SQLITE_ROW ) return SQLITE_ERROR;
  return rc;
}

/* TODO(shess) clearPendingTerms() is far down the file because
** writeZeroSegment() is far down the file because LeafWriter is far
** down the file.  Consider refactoring the code to move the non-vtab
** code above the vtab code so that we don't need this forward
** reference.
*/
static int clearPendingTerms(fulltext_vtab *v);

/*
** Free the memory used to contain a fulltext_vtab structure.
*/
static void fulltext_vtab_destroy(fulltext_vtab *v){
  int iStmt, i;

  TRACE(("FTS2 Destroy %p\n", v));
  for( iStmt=0; iStmt<MAX_STMT; iStmt++ ){
    if( v->pFulltextStatements[iStmt]!=NULL ){
      sqlite3_finalize(v->pFulltextStatements[iStmt]);
      v->pFulltextStatements[iStmt] = NULL;
    }
  }

  for( i=0; i<MERGE_COUNT; i++ ){
    if( v->pLeafSelectStmts[i]!=NULL ){
      sqlite3_finalize(v->pLeafSelectStmts[i]);
      v->pLeafSelectStmts[i] = NULL;
    }
  }

  if( v->pTokenizer!=NULL ){
    v->pTokenizer->pModule->xDestroy(v->pTokenizer);
    v->pTokenizer = NULL;
  }

  clearPendingTerms(v);

  sqlite3_free(v->azColumn);
  for(i = 0; i < v->nColumn; ++i) {
    sqlite3_free(v->azContentColumn[i]);
  }
  sqlite3_free(v->azContentColumn);
  sqlite3_free(v);
}

/*
** Token types for parsing the arguments to xConnect or xCreate.
*/
#define TOKEN_EOF         0    /* End of file */
#define TOKEN_SPACE       1    /* Any kind of whitespace */
#define TOKEN_ID          2    /* An identifier */
#define TOKEN_STRING      3    /* A string literal */
#define TOKEN_PUNCT       4    /* A single punctuation character */

/*
** If X is a character that can be used in an identifier then
** IdChar(X) will be true.  Otherwise it is false.
**
** For ASCII, any character with the high-order bit set is
** allowed in an identifier.  For 7-bit characters, 
** sqlite3IsIdChar[X] must be 1.
**
** Ticket #1066.  the SQL standard does not allow '$' in the
** middle of identfiers.  But many SQL implementations do. 
** SQLite will allow '$' in identifiers for compatibility.
** But the feature is undocumented.
*/
static const char isIdChar[] = {
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
    0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 2x */
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,  /* 3x */
    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 4x */
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,  /* 5x */
    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 6x */
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,  /* 7x */
};
#define IdChar(C)  (((c=C)&0x80)!=0 || (c>0x1f && isIdChar[c-0x20]))


/*
** Return the length of the token that begins at z[0]. 
** Store the token type in *tokenType before returning.
*/
static int getToken(const char *z, int *tokenType){
  int i, c;
  switch( *z ){
    case 0: {
      *tokenType = TOKEN_EOF;
      return 0;
    }
    case ' ': case '\t': case '\n': case '\f': case '\r': {
      for(i=1; safe_isspace(z[i]); i++){}
      *tokenType = TOKEN_SPACE;
      return i;
    }
    case '`':
    case '\'':
    case '"': {
      int delim = z[0];
      for(i=1; (c=z[i])!=0; i++){
        if( c==delim ){
          if( z[i+1]==delim ){
            i++;
          }else{
            break;
          }
        }
      }
      *tokenType = TOKEN_STRING;
      return i + (c!=0);
    }
    case '[': {
      for(i=1, c=z[0]; c!=']' && (c=z[i])!=0; i++){}
      *tokenType = TOKEN_ID;
      return i;
    }
    default: {
      if( !IdChar(*z) ){
        break;
      }
      for(i=1; IdChar(z[i]); i++){}
      *tokenType = TOKEN_ID;
      return i;
    }
  }
  *tokenType = TOKEN_PUNCT;
  return 1;
}

/*
** A token extracted from a string is an instance of the following
** structure.
*/
typedef struct Token {
  const char *z;       /* Pointer to token text.  Not '\000' terminated */
  short int n;         /* Length of the token text in bytes. */
} Token;

/*
** Given a input string (which is really one of the argv[] parameters
** passed into xConnect or xCreate) split the string up into tokens.
** Return an array of pointers to '\000' terminated strings, one string
** for each non-whitespace token.
**
** The returned array is terminated by a single NULL pointer.
**
** Space to hold the returned array is obtained from a single
** malloc and should be freed by passing the return value to free().
** The individual strings within the token list are all a part of
** the single memory allocation and will all be freed at once.
*/
static char **tokenizeString(const char *z, int *pnToken){
  int nToken = 0;
  Token *aToken = sqlite3_malloc( strlen(z) * sizeof(aToken[0]) );
  int n = 1;
  int e, i;
  int totalSize = 0;
  char **azToken;
  char *zCopy;
  while( n>0 ){
    n = getToken(z, &e);
    if( e!=TOKEN_SPACE ){
      aToken[nToken].z = z;
      aToken[nToken].n = n;
      nToken++;
      totalSize += n+1;
    }
    z += n;
  }
  azToken = (char**)sqlite3_malloc( nToken*sizeof(char*) + totalSize );
  zCopy = (char*)&azToken[nToken];
  nToken--;
  for(i=0; i<nToken; i++){
    azToken[i] = zCopy;
    n = aToken[i].n;
    memcpy(zCopy, aToken[i].z, n);
    zCopy[n] = 0;
    zCopy += n+1;
  }
  azToken[nToken] = 0;
  sqlite3_free(aToken);
  *pnToken = nToken;
  return azToken;
}

/*
** Convert an SQL-style quoted string into a normal string by removing
** the quote characters.  The conversion is done in-place.  If the
** input does not begin with a quote character, then this routine
** is a no-op.
**
** Examples:
**
**     "abc"   becomes   abc
**     'xyz'   becomes   xyz
**     [pqr]   becomes   pqr
**     `mno`   becomes   mno
*/
static void dequoteString(char *z){
  int quote;
  int i, j;
  if( z==0 ) return;
  quote = z[0];
  switch( quote ){
    case '\'':  break;
    case '"':   break;
    case '`':   break;                /* For MySQL compatibility */
    case '[':   quote = ']';  break;  /* For MS SqlServer compatibility */
    default:    return;
  }
  for(i=1, j=0; z[i]; i++){
    if( z[i]==quote ){
      if( z[i+1]==quote ){
        z[j++] = quote;
        i++;
      }else{
        z[j++] = 0;
        break;
      }
    }else{
      z[j++] = z[i];
    }
  }
}

/*
** The input azIn is a NULL-terminated list of tokens.  Remove the first
** token and all punctuation tokens.  Remove the quotes from
** around string literal tokens.
**
** Example:
**
**     input:      tokenize chinese ( 'simplifed' , 'mixed' )
**     output:     chinese simplifed mixed
**
** Another example:
**
**     input:      delimiters ( '[' , ']' , '...' )
**     output:     [ ] ...
*/
static void tokenListToIdList(char **azIn){
  int i, j;
  if( azIn ){
    for(i=0, j=-1; azIn[i]; i++){
      if( safe_isalnum(azIn[i][0]) || azIn[i][1] ){
        dequoteString(azIn[i]);
        if( j>=0 ){
          azIn[j] = azIn[i];
        }
        j++;
      }
    }
    azIn[j] = 0;
  }
}


/*
** Find the first alphanumeric token in the string zIn.  Null-terminate
** this token.  Remove any quotation marks.  And return a pointer to
** the result.
*/
static char *firstToken(char *zIn, char **pzTail){
  int n, ttype;
  while(1){
    n = getToken(zIn, &ttype);
    if( ttype==TOKEN_SPACE ){
      zIn += n;
    }else if( ttype==TOKEN_EOF ){
      *pzTail = zIn;
      return 0;
    }else{
      zIn[n] = 0;
      *pzTail = &zIn[1];
      dequoteString(zIn);
      return zIn;
    }
  }
  /*NOTREACHED*/
}

/* Return true if...
**
**   *  s begins with the string t, ignoring case
**   *  s is longer than t
**   *  The first character of s beyond t is not a alphanumeric
** 
** Ignore leading space in *s.
**
** To put it another way, return true if the first token of
** s[] is t[].
*/
static int startsWith(const char *s, const char *t){
  while( safe_isspace(*s) ){ s++; }
  while( *t ){
    if( safe_tolower(*s++)!=safe_tolower(*t++) ) return 0;
  }
  return *s!='_' && !safe_isalnum(*s);
}

/*
** An instance of this structure defines the "spec" of a
** full text index.  This structure is populated by parseSpec
** and use by fulltextConnect and fulltextCreate.
*/
typedef struct TableSpec {
  const char *zDb;         /* Logical database name */
  const char *zName;       /* Name of the full-text index */
  int nColumn;             /* Number of columns to be indexed */
  char **azColumn;         /* Original names of columns to be indexed */
  char **azContentColumn;  /* Column names for %_content */
  char **azTokenizer;      /* Name of tokenizer and its arguments */
} TableSpec;

/*
** Reclaim all of the memory used by a TableSpec
*/
static void clearTableSpec(TableSpec *p) {
  sqlite3_free(p->azColumn);
  sqlite3_free(p->azContentColumn);
  sqlite3_free(p->azTokenizer);
}

/* Parse a CREATE VIRTUAL TABLE statement, which looks like this:
 *
 * CREATE VIRTUAL TABLE email
 *        USING fts2(subject, body, tokenize mytokenizer(myarg))
 *
 * We return parsed information in a TableSpec structure.
 * 
 */
static int parseSpec(TableSpec *pSpec, int argc, const char *const*argv,
                     char**pzErr){
  int i, n;
  char *z, *zDummy;
  char **azArg;
  const char *zTokenizer = 0;    /* argv[] entry describing the tokenizer */

  assert( argc>=3 );
  /* Current interface:
  ** argv[0] - module name
  ** argv[1] - database name
  ** argv[2] - table name
  ** argv[3..] - columns, optionally followed by tokenizer specification
  **             and snippet delimiters specification.
  */

  /* Make a copy of the complete argv[][] array in a single allocation.
  ** The argv[][] array is read-only and transient.  We can write to the
  ** copy in order to modify things and the copy is persistent.
  */
  CLEAR(pSpec);
  for(i=n=0; i<argc; i++){
    n += strlen(argv[i]) + 1;
  }
  azArg = sqlite3_malloc( sizeof(char*)*argc + n );
  if( azArg==0 ){
    return SQLITE_NOMEM;
  }
  z = (char*)&azArg[argc];
  for(i=0; i<argc; i++){
    azArg[i] = z;
    strcpy(z, argv[i]);
    z += strlen(z)+1;
  }

  /* Identify the column names and the tokenizer and delimiter arguments
  ** in the argv[][] array.
  */
  pSpec->zDb = azArg[1];
  pSpec->zName = azArg[2];
  pSpec->nColumn = 0;
  pSpec->azColumn = azArg;
  zTokenizer = "tokenize simple";
  for(i=3; i<argc; ++i){
    if( startsWith(azArg[i],"tokenize") ){
      zTokenizer = azArg[i];
    }else{
      z = azArg[pSpec->nColumn] = firstToken(azArg[i], &zDummy);
      pSpec->nColumn++;
    }
  }
  if( pSpec->nColumn==0 ){
    azArg[0] = "content";
    pSpec->nColumn = 1;
  }

  /*
  ** Construct the list of content column names.
  **
  ** Each content column name will be of the form cNNAAAA
  ** where NN is the column number and AAAA is the sanitized
  ** column name.  "sanitized" means that special characters are
  ** converted to "_".  The cNN prefix guarantees that all column
  ** names are unique.
  **
  ** The AAAA suffix is not strictly necessary.  It is included
  ** for the convenience of people who might examine the generated
  ** %_content table and wonder what the columns are used for.
  */
  pSpec->azContentColumn = sqlite3_malloc( pSpec->nColumn * sizeof(char *) );
  if( pSpec->azContentColumn==0 ){
    clearTableSpec(pSpec);
    return SQLITE_NOMEM;
  }
  for(i=0; i<pSpec->nColumn; i++){
    char *p;
    pSpec->azContentColumn[i] = sqlite3_mprintf("c%d%s", i, azArg[i]);
    for (p = pSpec->azContentColumn[i]; *p ; ++p) {
      if( !safe_isalnum(*p) ) *p = '_';
    }
  }

  /*
  ** Parse the tokenizer specification string.
  */
  pSpec->azTokenizer = tokenizeString(zTokenizer, &n);
  tokenListToIdList(pSpec->azTokenizer);

  return SQLITE_OK;
}

/*
** Generate a CREATE TABLE statement that describes the schema of
** the virtual table.  Return a pointer to this schema string.
**
** Space is obtained from sqlite3_mprintf() and should be freed
** using sqlite3_free().
*/
static char *fulltextSchema(
  int nColumn,                  /* Number of columns */
  const char *const* azColumn,  /* List of columns */
  const char *zTableName        /* Name of the table */
){
  int i;
  char *zSchema, *zNext;
  const char *zSep = "(";
  zSchema = sqlite3_mprintf("CREATE TABLE x");
  for(i=0; i<nColumn; i++){
    zNext = sqlite3_mprintf("%s%s%Q", zSchema, zSep, azColumn[i]);
    sqlite3_free(zSchema);
    zSchema = zNext;
    zSep = ",";
  }
  zNext = sqlite3_mprintf("%s,%Q)", zSchema, zTableName);
  sqlite3_free(zSchema);
  return zNext;
}

/*
** Build a new sqlite3_vtab structure that will describe the
** fulltext index defined by spec.
*/
static int constructVtab(
  sqlite3 *db,              /* The SQLite database connection */
  fts2Hash *pHash,          /* Hash table containing tokenizers */
  TableSpec *spec,          /* Parsed spec information from parseSpec() */
  sqlite3_vtab **ppVTab,    /* Write the resulting vtab structure here */
  char **pzErr              /* Write any error message here */
){
  int rc;
  int n;
  fulltext_vtab *v = 0;
  const sqlite3_tokenizer_module *m = NULL;
  char *schema;

  char const *zTok;         /* Name of tokenizer to use for this fts table */
  int nTok;                 /* Length of zTok, including nul terminator */

  v = (fulltext_vtab *) sqlite3_malloc(sizeof(fulltext_vtab));
  if( v==0 ) return SQLITE_NOMEM;
  CLEAR(v);
  /* sqlite will initialize v->base */
  v->db = db;
  v->zDb = spec->zDb;       /* Freed when azColumn is freed */
  v->zName = spec->zName;   /* Freed when azColumn is freed */
  v->nColumn = spec->nColumn;
  v->azContentColumn = spec->azContentColumn;
  spec->azContentColumn = 0;
  v->azColumn = spec->azColumn;
  spec->azColumn = 0;

  if( spec->azTokenizer==0 ){
    return SQLITE_NOMEM;
  }

  zTok = spec->azTokenizer[0]; 
  if( !zTok ){
    zTok = "simple";
  }
  nTok = strlen(zTok)+1;

  m = (sqlite3_tokenizer_module *)sqlite3Fts2HashFind(pHash, zTok, nTok);
  if( !m ){
    *pzErr = sqlite3_mprintf("unknown tokenizer: %s", spec->azTokenizer[0]);
    rc = SQLITE_ERROR;
    goto err;
  }

  for(n=0; spec->azTokenizer[n]; n++){}
  if( n ){
    rc = m->xCreate(n-1, (const char*const*)&spec->azTokenizer[1],
                    &v->pTokenizer);
  }else{
    rc = m->xCreate(0, 0, &v->pTokenizer);
  }
  if( rc!=SQLITE_OK ) goto err;
  v->pTokenizer->pModule = m;

  /* TODO: verify the existence of backing tables foo_content, foo_term */

  schema = fulltextSchema(v->nColumn, (const char*const*)v->azColumn,
                          spec->zName);
  rc = sqlite3_declare_vtab(db, schema);
  sqlite3_free(schema);
  if( rc!=SQLITE_OK ) goto err;

  memset(v->pFulltextStatements, 0, sizeof(v->pFulltextStatements));

  /* Indicate that the buffer is not live. */
  v->nPendingData = -1;

  *ppVTab = &v->base;
  TRACE(("FTS2 Connect %p\n", v));

  return rc;

err:
  fulltext_vtab_destroy(v);
  return rc;
}

static int fulltextConnect(
  sqlite3 *db,
  void *pAux,
  int argc, const char *const*argv,
  sqlite3_vtab **ppVTab,
  char **pzErr
){
  TableSpec spec;
  int rc = parseSpec(&spec, argc, argv, pzErr);
  if( rc!=SQLITE_OK ) return rc;

  rc = constructVtab(db, (fts2Hash *)pAux, &spec, ppVTab, pzErr);
  clearTableSpec(&spec);
  return rc;
}

/* The %_content table holds the text of each document, with
** the rowid used as the docid.
*/
/* TODO(shess) This comment needs elaboration to match the updated
** code.  Work it into the top-of-file comment at that time.
*/
static int fulltextCreate(sqlite3 *db, void *pAux,
                          int argc, const char * const *argv,
                          sqlite3_vtab **ppVTab, char **pzErr){
  int rc;
  TableSpec spec;
  StringBuffer schema;
  TRACE(("FTS2 Create\n"));

  rc = parseSpec(&spec, argc, argv, pzErr);
  if( rc!=SQLITE_OK ) return rc;

  initStringBuffer(&schema);
  append(&schema, "CREATE TABLE %_content(");
  appendList(&schema, spec.nColumn, spec.azContentColumn);
  append(&schema, ")");
  rc = sql_exec(db, spec.zDb, spec.zName, stringBufferData(&schema));
  stringBufferDestroy(&schema);
  if( rc!=SQLITE_OK ) goto out;

  rc = sql_exec(db, spec.zDb, spec.zName,
                "create table %_segments(block blob);");
  if( rc!=SQLITE_OK ) goto out;

  rc = sql_exec(db, spec.zDb, spec.zName,
                "create table %_segdir("
                "  level integer,"
                "  idx integer,"
                "  start_block integer,"
                "  leaves_end_block integer,"
                "  end_block integer,"
                "  root blob,"
                "  primary key(level, idx)"
                ");");
  if( rc!=SQLITE_OK ) goto out;

  rc = constructVtab(db, (fts2Hash *)pAux, &spec, ppVTab, pzErr);

out:
  clearTableSpec(&spec);
  return rc;
}

/* Decide how to handle an SQL query. */
static int fulltextBestIndex(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
  int i;
  TRACE(("FTS2 BestIndex\n"));

  for(i=0; i<pInfo->nConstraint; ++i){
    const struct sqlite3_index_constraint *pConstraint;
    pConstraint = &pInfo->aConstraint[i];
    if( pConstraint->usable ) {
      if( pConstraint->iColumn==-1 &&
          pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
        pInfo->idxNum = QUERY_ROWID;      /* lookup by rowid */
        TRACE(("FTS2 QUERY_ROWID\n"));
      } else if( pConstraint->iColumn>=0 &&
                 pConstraint->op==SQLITE_INDEX_CONSTRAINT_MATCH ){
        /* full-text search */
        pInfo->idxNum = QUERY_FULLTEXT + pConstraint->iColumn;
        TRACE(("FTS2 QUERY_FULLTEXT %d\n", pConstraint->iColumn));
      } else continue;

      pInfo->aConstraintUsage[i].argvIndex = 1;
      pInfo->aConstraintUsage[i].omit = 1;

      /* An arbitrary value for now.
       * TODO: Perhaps rowid matches should be considered cheaper than
       * full-text searches. */
      pInfo->estimatedCost = 1.0;   

      return SQLITE_OK;
    }
  }
  pInfo->idxNum = QUERY_GENERIC;
  return SQLITE_OK;
}

static int fulltextDisconnect(sqlite3_vtab *pVTab){
  TRACE(("FTS2 Disconnect %p\n", pVTab));
  fulltext_vtab_destroy((fulltext_vtab *)pVTab);
  return SQLITE_OK;
}

static int fulltextDestroy(sqlite3_vtab *pVTab){
  fulltext_vtab *v = (fulltext_vtab *)pVTab;
  int rc;

  TRACE(("FTS2 Destroy %p\n", pVTab));
  rc = sql_exec(v->db, v->zDb, v->zName,
                "drop table if exists %_content;"
                "drop table if exists %_segments;"
                "drop table if exists %_segdir;"
                );
  if( rc!=SQLITE_OK ) return rc;

  fulltext_vtab_destroy((fulltext_vtab *)pVTab);
  return SQLITE_OK;
}

static int fulltextOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
  fulltext_cursor *c;

  c = (fulltext_cursor *) sqlite3_malloc(sizeof(fulltext_cursor));
  if( c ){
    memset(c, 0, sizeof(fulltext_cursor));
    /* sqlite will initialize c->base */
    *ppCursor = &c->base;
    TRACE(("FTS2 Open %p: %p\n", pVTab, c));
    return SQLITE_OK;
  }else{
    return SQLITE_NOMEM;
  }
}


/* Free all of the dynamically allocated memory held by *q
*/
static void queryClear(Query *q){
  int i;
  for(i = 0; i < q->nTerms; ++i){
    sqlite3_free(q->pTerms[i].pTerm);
  }
  sqlite3_free(q->pTerms);
  CLEAR(q);
}

/* Free all of the dynamically allocated memory held by the
** Snippet
*/
static void snippetClear(Snippet *p){
  sqlite3_free(p->aMatch);
  sqlite3_free(p->zOffset);
  sqlite3_free(p->zSnippet);
  CLEAR(p);
}
/*
** Append a single entry to the p->aMatch[] log.
*/
static void snippetAppendMatch(
  Snippet *p,               /* Append the entry to this snippet */
  int iCol, int iTerm,      /* The column and query term */
  int iStart, int nByte     /* Offset and size of the match */
){
  int i;
  struct snippetMatch *pMatch;
  if( p->nMatch+1>=p->nAlloc ){
    p->nAlloc = p->nAlloc*2 + 10;
    p->aMatch = sqlite3_realloc(p->aMatch, p->nAlloc*sizeof(p->aMatch[0]) );
    if( p->aMatch==0 ){
      p->nMatch = 0;
      p->nAlloc = 0;
      return;
    }
  }
  i = p->nMatch++;
  pMatch = &p->aMatch[i];
  pMatch->iCol = iCol;
  pMatch->iTerm = iTerm;
  pMatch->iStart = iStart;
  pMatch->nByte = nByte;
}

/*
** Sizing information for the circular buffer used in snippetOffsetsOfColumn()
*/
#define FTS2_ROTOR_SZ   (32)
#define FTS2_ROTOR_MASK (FTS2_ROTOR_SZ-1)

/*
** Add entries to pSnippet->aMatch[] for every match that occurs against
** document zDoc[0..nDoc-1] which is stored in column iColumn.
*/
static void snippetOffsetsOfColumn(
  Query *pQuery,
  Snippet *pSnippet,
  int iColumn,
  const char *zDoc,
  int nDoc
){
  const sqlite3_tokenizer_module *pTModule;  /* The tokenizer module */
  sqlite3_tokenizer *pTokenizer;             /* The specific tokenizer */
  sqlite3_tokenizer_cursor *pTCursor;        /* Tokenizer cursor */
  fulltext_vtab *pVtab;                /* The full text index */
  int nColumn;                         /* Number of columns in the index */
  const QueryTerm *aTerm;              /* Query string terms */
  int nTerm;                           /* Number of query string terms */  
  int i, j;                            /* Loop counters */
  int rc;                              /* Return code */
  unsigned int match, prevMatch;       /* Phrase search bitmasks */
  const char *zToken;                  /* Next token from the tokenizer */
  int nToken;                          /* Size of zToken */
  int iBegin, iEnd, iPos;              /* Offsets of beginning and end */

  /* The following variables keep a circular buffer of the last
  ** few tokens */
  unsigned int iRotor = 0;             /* Index of current token */
  int iRotorBegin[FTS2_ROTOR_SZ];      /* Beginning offset of token */
  int iRotorLen[FTS2_ROTOR_SZ];        /* Length of token */

  pVtab = pQuery->pFts;
  nColumn = pVtab->nColumn;
  pTokenizer = pVtab->pTokenizer;
  pTModule = pTokenizer->pModule;
  rc = pTModule->xOpen(pTokenizer, zDoc, nDoc, &pTCursor);
  if( rc ) return;
  pTCursor->pTokenizer = pTokenizer;
  aTerm = pQuery->pTerms;
  nTerm = pQuery->nTerms;
  if( nTerm>=FTS2_ROTOR_SZ ){
    nTerm = FTS2_ROTOR_SZ - 1;
  }
  prevMatch = 0;
  while(1){
    rc = pTModule->xNext(pTCursor, &zToken, &nToken, &iBegin, &iEnd, &iPos);
    if( rc ) break;
    iRotorBegin[iRotor&FTS2_ROTOR_MASK] = iBegin;
    iRotorLen[iRotor&FTS2_ROTOR_MASK] = iEnd-iBegin;
    match = 0;
    for(i=0; i<nTerm; i++){
      int iCol;
      iCol = aTerm[i].iColumn;
      if( iCol>=0 && iCol<nColumn && iCol!=iColumn ) continue;
      if( aTerm[i].nTerm>nToken ) continue;
      if( !aTerm[i].isPrefix && aTerm[i].nTerm<nToken ) continue;
      assert( aTerm[i].nTerm<=nToken );
      if( memcmp(aTerm[i].pTerm, zToken, aTerm[i].nTerm) ) continue;
      if( aTerm[i].iPhrase>1 && (prevMatch & (1<<i))==0 ) continue;
      match |= 1<<i;
      if( i==nTerm-1 || aTerm[i+1].iPhrase==1 ){
        for(j=aTerm[i].iPhrase-1; j>=0; j--){
          int k = (iRotor-j) & FTS2_ROTOR_MASK;
          snippetAppendMatch(pSnippet, iColumn, i-j,
                iRotorBegin[k], iRotorLen[k]);
        }
      }
    }
    prevMatch = match<<1;
    iRotor++;
  }
  pTModule->xClose(pTCursor);  
}


/*
** Compute all offsets for the current row of the query.  
** If the offsets have already been computed, this routine is a no-op.
*/
static void snippetAllOffsets(fulltext_cursor *p){
  int nColumn;
  int iColumn, i;
  int iFirst, iLast;
  fulltext_vtab *pFts;

  if( p->snippet.nMatch ) return;
  if( p->q.nTerms==0 ) return;
  pFts = p->q.pFts;
  nColumn = pFts->nColumn;
  iColumn = (p->iCursorType - QUERY_FULLTEXT);
  if( iColumn<0 || iColumn>=nColumn ){
    iFirst = 0;
    iLast = nColumn-1;
  }else{
    iFirst = iColumn;
    iLast = iColumn;
  }
  for(i=iFirst; i<=iLast; i++){
    const char *zDoc;
    int nDoc;
    zDoc = (const char*)sqlite3_column_text(p->pStmt, i+1);
    nDoc = sqlite3_column_bytes(p->pStmt, i+1);
    snippetOffsetsOfColumn(&p->q, &p->snippet, i, zDoc, nDoc);
  }
}

/*
** Convert the information in the aMatch[] array of the snippet
** into the string zOffset[0..nOffset-1].
*/
static void snippetOffsetText(Snippet *p){
  int i;
  int cnt = 0;
  StringBuffer sb;
  char zBuf[200];
  if( p->zOffset ) return;
  initStringBuffer(&sb);
  for(i=0; i<p->nMatch; i++){
    struct snippetMatch *pMatch = &p->aMatch[i];
    zBuf[0] = ' ';
    sqlite3_snprintf(sizeof(zBuf)-1, &zBuf[cnt>0], "%d %d %d %d",
        pMatch->iCol, pMatch->iTerm, pMatch->iStart, pMatch->nByte);
    append(&sb, zBuf);
    cnt++;
  }
  p->zOffset = stringBufferData(&sb);
  p->nOffset = stringBufferLength(&sb);
}

/*
** zDoc[0..nDoc-1] is phrase of text.  aMatch[0..nMatch-1] are a set
** of matching words some of which might be in zDoc.  zDoc is column
** number iCol.
**
** iBreak is suggested spot in zDoc where we could begin or end an
** excerpt.  Return a value similar to iBreak but possibly adjusted
** to be a little left or right so that the break point is better.
*/
static int wordBoundary(
  int iBreak,                   /* The suggested break point */
  const char *zDoc,             /* Document text */
  int nDoc,                     /* Number of bytes in zDoc[] */
  struct snippetMatch *aMatch,  /* Matching words */
  int nMatch,                   /* Number of entries in aMatch[] */
  int iCol                      /* The column number for zDoc[] */
){
  int i;
  if( iBreak<=10 ){
    return 0;
  }
  if( iBreak>=nDoc-10 ){
    return nDoc;
  }
  for(i=0; i<nMatch && aMatch[i].iCol<iCol; i++){}
  while( i<nMatch && aMatch[i].iStart+aMatch[i].nByte<iBreak ){ i++; }
  if( i<nMatch ){
    if( aMatch[i].iStart<iBreak+10 ){
      return aMatch[i].iStart;
    }
    if( i>0 && aMatch[i-1].iStart+aMatch[i-1].nByte>=iBreak ){
      return aMatch[i-1].iStart;
    }
  }
  for(i=1; i<=10; i++){
    if( safe_isspace(zDoc[iBreak-i]) ){
      return iBreak - i + 1;
    }
    if( safe_isspace(zDoc[iBreak+i]) ){
      return iBreak + i + 1;
    }
  }
  return iBreak;
}



/*
** Allowed values for Snippet.aMatch[].snStatus
*/
#define SNIPPET_IGNORE  0   /* It is ok to omit this match from the snippet */
#define SNIPPET_DESIRED 1   /* We want to include this match in the snippet */

/*
** Generate the text of a snippet.
*/
static void snippetText(
  fulltext_cursor *pCursor,   /* The cursor we need the snippet for */
  const char *zStartMark,     /* Markup to appear before each match */
  const char *zEndMark,       /* Markup to appear after each match */
  const char *zEllipsis       /* Ellipsis mark */
){
  int i, j;
  struct snippetMatch *aMatch;
  int nMatch;
  int nDesired;
  StringBuffer sb;
  int tailCol;
  int tailOffset;
  int iCol;
  int nDoc;
  const char *zDoc;
  int iStart, iEnd;
  int tailEllipsis = 0;
  int iMatch;
  

  sqlite3_free(pCursor->snippet.zSnippet);
  pCursor->snippet.zSnippet = 0;
  aMatch = pCursor->snippet.aMatch;
  nMatch = pCursor->snippet.nMatch;
  initStringBuffer(&sb);

  for(i=0; i<nMatch; i++){
    aMatch[i].snStatus = SNIPPET_IGNORE;
  }
  nDesired = 0;
  for(i=0; i<pCursor->q.nTerms; i++){
    for(j=0; j<nMatch; j++){
      if( aMatch[j].iTerm==i ){
        aMatch[j].snStatus = SNIPPET_DESIRED;
        nDesired++;
        break;
      }
    }
  }

  iMatch = 0;
  tailCol = -1;
  tailOffset = 0;
  for(i=0; i<nMatch && nDesired>0; i++){
    if( aMatch[i].snStatus!=SNIPPET_DESIRED ) continue;
    nDesired--;
    iCol = aMatch[i].iCol;
    zDoc = (const char*)sqlite3_column_text(pCursor->pStmt, iCol+1);
    nDoc = sqlite3_column_bytes(pCursor->pStmt, iCol+1);
    iStart = aMatch[i].iStart - 40;
    iStart = wordBoundary(iStart, zDoc, nDoc, aMatch, nMatch, iCol);
    if( iStart<=10 ){
      iStart = 0;
    }
    if( iCol==tailCol && iStart<=tailOffset+20 ){
      iStart = tailOffset;
    }
    if( (iCol!=tailCol && tailCol>=0) || iStart!=tailOffset ){
      trimWhiteSpace(&sb);
      appendWhiteSpace(&sb);
      append(&sb, zEllipsis);
      appendWhiteSpace(&sb);
    }
    iEnd = aMatch[i].iStart + aMatch[i].nByte + 40;
    iEnd = wordBoundary(iEnd, zDoc, nDoc, aMatch, nMatch, iCol);
    if( iEnd>=nDoc-10 ){
      iEnd = nDoc;
      tailEllipsis = 0;
    }else{
      tailEllipsis = 1;
    }
    while( iMatch<nMatch && aMatch[iMatch].iCol<iCol ){ iMatch++; }
    while( iStart<iEnd ){
      while( iMatch<nMatch && aMatch[iMatch].iStart<iStart
             && aMatch[iMatch].iCol<=iCol ){
        iMatch++;
      }
      if( iMatch<nMatch && aMatch[iMatch].iStart<iEnd
             && aMatch[iMatch].iCol==iCol ){
        nappend(&sb, &zDoc[iStart], aMatch[iMatch].iStart - iStart);
        iStart = aMatch[iMatch].iStart;
        append(&sb, zStartMark);
        nappend(&sb, &zDoc[iStart], aMatch[iMatch].nByte);
        append(&sb, zEndMark);
        iStart += aMatch[iMatch].nByte;
        for(j=iMatch+1; j<nMatch; j++){
          if( aMatch[j].iTerm==aMatch[iMatch].iTerm
              && aMatch[j].snStatus==SNIPPET_DESIRED ){
            nDesired--;
            aMatch[j].snStatus = SNIPPET_IGNORE;
          }
        }
      }else{
        nappend(&sb, &zDoc[iStart], iEnd - iStart);
        iStart = iEnd;
      }
    }
    tailCol = iCol;
    tailOffset = iEnd;
  }
  trimWhiteSpace(&sb);
  if( tailEllipsis ){
    appendWhiteSpace(&sb);
    append(&sb, zEllipsis);
  }
  pCursor->snippet.zSnippet = stringBufferData(&sb);
  pCursor->snippet.nSnippet = stringBufferLength(&sb);
}


/*
** Close the cursor.  For additional information see the documentation
** on the xClose method of the virtual table interface.
*/
static int fulltextClose(sqlite3_vtab_cursor *pCursor){
  fulltext_cursor *c = (fulltext_cursor *) pCursor;
  TRACE(("FTS2 Close %p\n", c));
  sqlite3_finalize(c->pStmt);
  queryClear(&c->q);
  snippetClear(&c->snippet);
  if( c->result.nData!=0 ) dlrDestroy(&c->reader);
  dataBufferDestroy(&c->result);
  sqlite3_free(c);
  return SQLITE_OK;
}

static int fulltextNext(sqlite3_vtab_cursor *pCursor){
  fulltext_cursor *c = (fulltext_cursor *) pCursor;
  int rc;

  TRACE(("FTS2 Next %p\n", pCursor));
  snippetClear(&c->snippet);
  if( c->iCursorType < QUERY_FULLTEXT ){
    /* TODO(shess) Handle SQLITE_SCHEMA AND SQLITE_BUSY. */
    rc = sqlite3_step(c->pStmt);
    switch( rc ){
      case SQLITE_ROW:
        c->eof = 0;
        return SQLITE_OK;
      case SQLITE_DONE:
        c->eof = 1;
        return SQLITE_OK;
      default:
        c->eof = 1;
        return rc;
    }
  } else {  /* full-text query */
    rc = sqlite3_reset(c->pStmt);
    if( rc!=SQLITE_OK ) return rc;

    if( c->result.nData==0 || dlrAtEnd(&c->reader) ){
      c->eof = 1;
      return SQLITE_OK;
    }
    rc = sqlite3_bind_int64(c->pStmt, 1, dlrDocid(&c->reader));
    dlrStep(&c->reader);
    if( rc!=SQLITE_OK ) return rc;
    /* TODO(shess) Handle SQLITE_SCHEMA AND SQLITE_BUSY. */
    rc = sqlite3_step(c->pStmt);
    if( rc==SQLITE_ROW ){   /* the case we expect */
      c->eof = 0;
      return SQLITE_OK;
    }
    /* an error occurred; abort */
    return rc==SQLITE_DONE ? SQLITE_ERROR : rc;
  }
}


/* TODO(shess) If we pushed LeafReader to the top of the file, or to
** another file, term_select() could be pushed above
** docListOfTerm().
*/
static int termSelect(fulltext_vtab *v, int iColumn,
                      const char *pTerm, int nTerm, int isPrefix,
                      DocListType iType, DataBuffer *out);

/* Return a DocList corresponding to the query term *pTerm.  If *pTerm
** is the first term of a phrase query, go ahead and evaluate the phrase
** query and return the doclist for the entire phrase query.
**
** The resulting DL_DOCIDS doclist is stored in pResult, which is
** overwritten.
*/
static int docListOfTerm(
  fulltext_vtab *v,   /* The full text index */
  int iColumn,        /* column to restrict to.  No restriction if >=nColumn */
  QueryTerm *pQTerm,  /* Term we are looking for, or 1st term of a phrase */
  DataBuffer *pResult /* Write the result here */
){
  DataBuffer left, right, new;
  int i, rc;

  /* No phrase search if no position info. */
  assert( pQTerm->nPhrase==0 || DL_DEFAULT!=DL_DOCIDS );

  /* This code should never be called with buffered updates. */
  assert( v->nPendingData<0 );

  dataBufferInit(&left, 0);
  rc = termSelect(v, iColumn, pQTerm->pTerm, pQTerm->nTerm, pQTerm->isPrefix,
                  0<pQTerm->nPhrase ? DL_POSITIONS : DL_DOCIDS, &left);
  if( rc ) return rc;
  for(i=1; i<=pQTerm->nPhrase && left.nData>0; i++){
    dataBufferInit(&right, 0);
    rc = termSelect(v, iColumn, pQTerm[i].pTerm, pQTerm[i].nTerm,
                    pQTerm[i].isPrefix, DL_POSITIONS, &right);
    if( rc ){
      dataBufferDestroy(&left);
      return rc;
    }
    dataBufferInit(&new, 0);
    docListPhraseMerge(left.pData, left.nData, right.pData, right.nData,
                       i<pQTerm->nPhrase ? DL_POSITIONS : DL_DOCIDS, &new);
    dataBufferDestroy(&left);
    dataBufferDestroy(&right);
    left = new;
  }
  *pResult = left;
  return SQLITE_OK;
}

/* Add a new term pTerm[0..nTerm-1] to the query *q.
*/
static void queryAdd(Query *q, const char *pTerm, int nTerm){
  QueryTerm *t;
  ++q->nTerms;
  q->pTerms = sqlite3_realloc(q->pTerms, q->nTerms * sizeof(q->pTerms[0]));
  if( q->pTerms==0 ){
    q->nTerms = 0;
    return;
  }
  t = &q->pTerms[q->nTerms - 1];
  CLEAR(t);
  t->pTerm = sqlite3_malloc(nTerm+1);
  memcpy(t->pTerm, pTerm, nTerm);
  t->pTerm[nTerm] = 0;
  t->nTerm = nTerm;
  t->isOr = q->nextIsOr;
  t->isPrefix = 0;
  q->nextIsOr = 0;
  t->iColumn = q->nextColumn;
  q->nextColumn = q->dfltColumn;
}

/*
** Check to see if the string zToken[0...nToken-1] matches any
** column name in the virtual table.   If it does,
** return the zero-indexed column number.  If not, return -1.
*/
static int checkColumnSpecifier(
  fulltext_vtab *pVtab,    /* The virtual table */
  const char *zToken,      /* Text of the token */
  int nToken               /* Number of characters in the token */
){
  int i;
  for(i=0; i<pVtab->nColumn; i++){
    if( memcmp(pVtab->azColumn[i], zToken, nToken)==0
        && pVtab->azColumn[i][nToken]==0 ){
      return i;
    }
  }
  return -1;
}

/*
** Parse the text at pSegment[0..nSegment-1].  Add additional terms
** to the query being assemblied in pQuery.
**
** inPhrase is true if pSegment[0..nSegement-1] is contained within
** double-quotes.  If inPhrase is true, then the first term
** is marked with the number of terms in the phrase less one and
** OR and "-" syntax is ignored.  If inPhrase is false, then every
** term found is marked with nPhrase=0 and OR and "-" syntax is significant.
*/
static int tokenizeSegment(
  sqlite3_tokenizer *pTokenizer,          /* The tokenizer to use */
  const char *pSegment, int nSegment,     /* Query expression being parsed */
  int inPhrase,                           /* True if within "..." */
  Query *pQuery                           /* Append results here */
){
  const sqlite3_tokenizer_module *pModule = pTokenizer->pModule;
  sqlite3_tokenizer_cursor *pCursor;
  int firstIndex = pQuery->nTerms;
  int iCol;
  int nTerm = 1;
  
  int rc = pModule->xOpen(pTokenizer, pSegment, nSegment, &pCursor);
  if( rc!=SQLITE_OK ) return rc;
  pCursor->pTokenizer = pTokenizer;

  while( 1 ){
    const char *pToken;
    int nToken, iBegin, iEnd, iPos;

    rc = pModule->xNext(pCursor,
                        &pToken, &nToken,
                        &iBegin, &iEnd, &iPos);
    if( rc!=SQLITE_OK ) break;
    if( !inPhrase &&
        pSegment[iEnd]==':' &&
         (iCol = checkColumnSpecifier(pQuery->pFts, pToken, nToken))>=0 ){
      pQuery->nextColumn = iCol;
      continue;
    }
    if( !inPhrase && pQuery->nTerms>0 && nToken==2
         && pSegment[iBegin]=='O' && pSegment[iBegin+1]=='R' ){
      pQuery->nextIsOr = 1;
      continue;
    }
    queryAdd(pQuery, pToken, nToken);
    if( !inPhrase && iBegin>0 && pSegment[iBegin-1]=='-' ){
      pQuery->pTerms[pQuery->nTerms-1].isNot = 1;
    }
    if( iEnd<nSegment && pSegment[iEnd]=='*' ){
      pQuery->pTerms[pQuery->nTerms-1].isPrefix = 1;
    }
    pQuery->pTerms[pQuery->nTerms-1].iPhrase = nTerm;
    if( inPhrase ){
      nTerm++;
    }
  }

  if( inPhrase && pQuery->nTerms>firstIndex ){
    pQuery->pTerms[firstIndex].nPhrase = pQuery->nTerms - firstIndex - 1;
  }

  return pModule->xClose(pCursor);
}

/* Parse a query string, yielding a Query object pQuery.
**
** The calling function will need to queryClear() to clean up
** the dynamically allocated memory held by pQuery.
*/
static int parseQuery(
  fulltext_vtab *v,        /* The fulltext index */
  const char *zInput,      /* Input text of the query string */
  int nInput,              /* Size of the input text */
  int dfltColumn,          /* Default column of the index to match against */
  Query *pQuery            /* Write the parse results here. */
){
  int iInput, inPhrase = 0;

  if( zInput==0 ) nInput = 0;
  if( nInput<0 ) nInput = strlen(zInput);
  pQuery->nTerms = 0;
  pQuery->pTerms = NULL;
  pQuery->nextIsOr = 0;
  pQuery->nextColumn = dfltColumn;
  pQuery->dfltColumn = dfltColumn;
  pQuery->pFts = v;

  for(iInput=0; iInput<nInput; ++iInput){
    int i;
    for(i=iInput; i<nInput && zInput[i]!='"'; ++i){}
    if( i>iInput ){
      tokenizeSegment(v->pTokenizer, zInput+iInput, i-iInput, inPhrase,
                       pQuery);
    }
    iInput = i;
    if( i<nInput ){
      assert( zInput[i]=='"' );
      inPhrase = !inPhrase;
    }
  }

  if( inPhrase ){
    /* unmatched quote */
    queryClear(pQuery);
    return SQLITE_ERROR;
  }
  return SQLITE_OK;
}

/* TODO(shess) Refactor the code to remove this forward decl. */
static int flushPendingTerms(fulltext_vtab *v);

/* Perform a full-text query using the search expression in
** zInput[0..nInput-1].  Return a list of matching documents
** in pResult.
**
** Queries must match column iColumn.  Or if iColumn>=nColumn
** they are allowed to match against any column.
*/
static int fulltextQuery(
  fulltext_vtab *v,      /* The full text index */
  int iColumn,           /* Match against this column by default */
  const char *zInput,    /* The query string */
  int nInput,            /* Number of bytes in zInput[] */
  DataBuffer *pResult,   /* Write the result doclist here */
  Query *pQuery          /* Put parsed query string here */
){
  int i, iNext, rc;
  DataBuffer left, right, or, new;
  int nNot = 0;
  QueryTerm *aTerm;

  /* TODO(shess) Instead of flushing pendingTerms, we could query for
  ** the relevant term and merge the doclist into what we receive from
  ** the database.  Wait and see if this is a common issue, first.
  **
  ** A good reason not to flush is to not generate update-related
  ** error codes from here.
  */

  /* Flush any buffered updates before executing the query. */
  rc = flushPendingTerms(v);
  if( rc!=SQLITE_OK ) return rc;

  /* TODO(shess) I think that the queryClear() calls below are not
  ** necessary, because fulltextClose() already clears the query.
  */
  rc = parseQuery(v, zInput, nInput, iColumn, pQuery);
  if( rc!=SQLITE_OK ) return rc;

  /* Empty or NULL queries return no results. */
  if( pQuery->nTerms==0 ){
    dataBufferInit(pResult, 0);
    return SQLITE_OK;
  }

  /* Merge AND terms. */
  /* TODO(shess) I think we can early-exit if( i>nNot && left.nData==0 ). */
  aTerm = pQuery->pTerms;
  for(i = 0; i<pQuery->nTerms; i=iNext){
    if( aTerm[i].isNot ){
      /* Handle all NOT terms in a separate pass */
      nNot++;
      iNext = i + aTerm[i].nPhrase+1;
      continue;
    }
    iNext = i + aTerm[i].nPhrase + 1;
    rc = docListOfTerm(v, aTerm[i].iColumn, &aTerm[i], &right);
    if( rc ){
      if( i!=nNot ) dataBufferDestroy(&left);
      queryClear(pQuery);
      return rc;
    }
    while( iNext<pQuery->nTerms && aTerm[iNext].isOr ){
      rc = docListOfTerm(v, aTerm[iNext].iColumn, &aTerm[iNext], &or);
      iNext += aTerm[iNext].nPhrase + 1;
      if( rc ){
        if( i!=nNot ) dataBufferDestroy(&left);
        dataBufferDestroy(&right);
        queryClear(pQuery);
        return rc;
      }
      dataBufferInit(&new, 0);
      docListOrMerge(right.pData, right.nData, or.pData, or.nData, &new);
      dataBufferDestroy(&right);
      dataBufferDestroy(&or);
      right = new;
    }
    if( i==nNot ){           /* first term processed. */
      left = right;
    }else{
      dataBufferInit(&new, 0);
      docListAndMerge(left.pData, left.nData, right.pData, right.nData, &new);
      dataBufferDestroy(&right);
      dataBufferDestroy(&left);
      left = new;
    }
  }

  if( nNot==pQuery->nTerms ){
    /* We do not yet know how to handle a query of only NOT terms */
    return SQLITE_ERROR;
  }

  /* Do the EXCEPT terms */
  for(i=0; i<pQuery->nTerms;  i += aTerm[i].nPhrase + 1){
    if( !aTerm[i].isNot ) continue;
    rc = docListOfTerm(v, aTerm[i].iColumn, &aTerm[i], &right);
    if( rc ){
      queryClear(pQuery);
      dataBufferDestroy(&left);
      return rc;
    }
    dataBufferInit(&new, 0);
    docListExceptMerge(left.pData, left.nData, right.pData, right.nData, &new);
    dataBufferDestroy(&right);
    dataBufferDestroy(&left);
    left = new;
  }

  *pResult = left;
  return rc;
}

/*
** This is the xFilter interface for the virtual table.  See
** the virtual table xFilter method documentation for additional
** information.
**
** If idxNum==QUERY_GENERIC then do a full table scan against
** the %_content table.
**
** If idxNum==QUERY_ROWID then do a rowid lookup for a single entry
** in the %_content table.
**
** If idxNum>=QUERY_FULLTEXT then use the full text index.  The
** column on the left-hand side of the MATCH operator is column
** number idxNum-QUERY_FULLTEXT, 0 indexed.  argv[0] is the right-hand
** side of the MATCH operator.
*/
/* TODO(shess) Upgrade the cursor initialization and destruction to
** account for fulltextFilter() being called multiple times on the
** same cursor.  The current solution is very fragile.  Apply fix to
** fts2 as appropriate.
*/
static int fulltextFilter(
  sqlite3_vtab_cursor *pCursor,     /* The cursor used for this query */
  int idxNum, const char *idxStr,   /* Which indexing scheme to use */
  int argc, sqlite3_value **argv    /* Arguments for the indexing scheme */
){
  fulltext_cursor *c = (fulltext_cursor *) pCursor;
  fulltext_vtab *v = cursor_vtab(c);
  int rc;

  TRACE(("FTS2 Filter %p\n",pCursor));

  /* If the cursor has a statement that was not prepared according to
  ** idxNum, clear it.  I believe all calls to fulltextFilter with a
  ** given cursor will have the same idxNum , but in this case it's
  ** easy to be safe.
  */
  if( c->pStmt && c->iCursorType!=idxNum ){
    sqlite3_finalize(c->pStmt);
    c->pStmt = NULL;
  }

  /* Get a fresh statement appropriate to idxNum. */
  /* TODO(shess): Add a prepared-statement cache in the vt structure.
  ** The cache must handle multiple open cursors.  Easier to cache the
  ** statement variants at the vt to reduce malloc/realloc/free here.
  ** Or we could have a StringBuffer variant which allowed stack
  ** construction for small values.
  */
  if( !c->pStmt ){
    char *zSql = sqlite3_mprintf("select rowid, * from %%_content %s",
                                 idxNum==QUERY_GENERIC ? "" : "where rowid=?");
    rc = sql_prepare(v->db, v->zDb, v->zName, &c->pStmt, zSql);
    sqlite3_free(zSql);
    if( rc!=SQLITE_OK ) return rc;
    c->iCursorType = idxNum;
  }else{
    sqlite3_reset(c->pStmt);
    assert( c->iCursorType==idxNum );
  }

  switch( idxNum ){
    case QUERY_GENERIC:
      break;

    case QUERY_ROWID:
      rc = sqlite3_bind_int64(c->pStmt, 1, sqlite3_value_int64(argv[0]));
      if( rc!=SQLITE_OK ) return rc;
      break;

    default:   /* full-text search */
    {
      const char *zQuery = (const char *)sqlite3_value_text(argv[0]);
      assert( idxNum<=QUERY_FULLTEXT+v->nColumn);
      assert( argc==1 );
      queryClear(&c->q);
      if( c->result.nData!=0 ){
        /* This case happens if the same cursor is used repeatedly. */
        dlrDestroy(&c->reader);
        dataBufferReset(&c->result);
      }else{
        dataBufferInit(&c->result, 0);
      }
      rc = fulltextQuery(v, idxNum-QUERY_FULLTEXT, zQuery, -1, &c->result, &c->q);
      if( rc!=SQLITE_OK ) return rc;
      if( c->result.nData!=0 ){
        dlrInit(&c->reader, DL_DOCIDS, c->result.pData, c->result.nData);
      }
      break;
    }
  }

  return fulltextNext(pCursor);
}

/* This is the xEof method of the virtual table.  The SQLite core
** calls this routine to find out if it has reached the end of
** a query's results set.
*/
static int fulltextEof(sqlite3_vtab_cursor *pCursor){
  fulltext_cursor *c = (fulltext_cursor *) pCursor;
  return c->eof;
}

/* This is the xColumn method of the virtual table.  The SQLite
** core calls this method during a query when it needs the value
** of a column from the virtual table.  This method needs to use
** one of the sqlite3_result_*() routines to store the requested
** value back in the pContext.
*/
static int fulltextColumn(sqlite3_vtab_cursor *pCursor,
                          sqlite3_context *pContext, int idxCol){
  fulltext_cursor *c = (fulltext_cursor *) pCursor;
  fulltext_vtab *v = cursor_vtab(c);

  if( idxCol<v->nColumn ){
    sqlite3_value *pVal = sqlite3_column_value(c->pStmt, idxCol+1);
    sqlite3_result_value(pContext, pVal);
  }else if( idxCol==v->nColumn ){
    /* The extra column whose name is the same as the table.
    ** Return a blob which is a pointer to the cursor
    */
    sqlite3_result_blob(pContext, &c, sizeof(c), SQLITE_TRANSIENT);
  }
  return SQLITE_OK;
}

/* This is the xRowid method.  The SQLite core calls this routine to
** retrive the rowid for the current row of the result set.  The
** rowid should be written to *pRowid.
*/
static int fulltextRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
  fulltext_cursor *c = (fulltext_cursor *) pCursor;

  *pRowid = sqlite3_column_int64(c->pStmt, 0);
  return SQLITE_OK;
}

/* Add all terms in [zText] to pendingTerms table.  If [iColumn] > 0,
** we also store positions and offsets in the hash table using that
** column number.
*/
static int buildTerms(fulltext_vtab *v, sqlite_int64 iDocid,
                      const char *zText, int iColumn){
  sqlite3_tokenizer *pTokenizer = v->pTokenizer;
  sqlite3_tokenizer_cursor *pCursor;
  const char *pToken;
  int nTokenBytes;
  int iStartOffset, iEndOffset, iPosition;
  int rc;

  rc = pTokenizer->pModule->xOpen(pTokenizer, zText, -1, &pCursor);
  if( rc!=SQLITE_OK ) return rc;

  pCursor->pTokenizer = pTokenizer;
  while( SQLITE_OK==(rc=pTokenizer->pModule->xNext(pCursor,
                                                   &pToken, &nTokenBytes,
                                                   &iStartOffset, &iEndOffset,
                                                   &iPosition)) ){
    DLCollector *p;
    int nData;                   /* Size of doclist before our update. */

    /* Positions can't be negative; we use -1 as a terminator
     * internally.  Token can't be NULL or empty. */
    if( iPosition<0 || pToken == NULL || nTokenBytes == 0 ){
      rc = SQLITE_ERROR;
      break;
    }

    p = fts2HashFind(&v->pendingTerms, pToken, nTokenBytes);
    if( p==NULL ){
      nData = 0;
      p = dlcNew(iDocid, DL_DEFAULT);
      fts2HashInsert(&v->pendingTerms, pToken, nTokenBytes, p);

      /* Overhead for our hash table entry, the key, and the value. */
      v->nPendingData += sizeof(struct fts2HashElem)+sizeof(*p)+nTokenBytes;
    }else{
      nData = p->b.nData;
      if( p->dlw.iPrevDocid!=iDocid ) dlcNext(p, iDocid);
    }
    if( iColumn>=0 ){
      dlcAddPos(p, iColumn, iPosition, iStartOffset, iEndOffset);
    }

    /* Accumulate data added by dlcNew or dlcNext, and dlcAddPos. */
    v->nPendingData += p->b.nData-nData;
  }

  /* TODO(shess) Check return?  Should this be able to cause errors at
  ** this point?  Actually, same question about sqlite3_finalize(),
  ** though one could argue that failure there means that the data is
  ** not durable.  *ponder*
  */
  pTokenizer->pModule->xClose(pCursor);
  if( SQLITE_DONE == rc ) return SQLITE_OK;
  return rc;
}

/* Add doclists for all terms in [pValues] to pendingTerms table. */
static int insertTerms(fulltext_vtab *v, sqlite_int64 iRowid,
                       sqlite3_value **pValues){
  int i;
  for(i = 0; i < v->nColumn ; ++i){
    char *zText = (char*)sqlite3_value_text(pValues[i]);
    int rc = buildTerms(v, iRowid, zText, i);
    if( rc!=SQLITE_OK ) return rc;
  }
  return SQLITE_OK;
}

/* Add empty doclists for all terms in the given row's content to
** pendingTerms.
*/
static int deleteTerms(fulltext_vtab *v, sqlite_int64 iRowid){
  const char **pValues;
  int i, rc;

  /* TODO(shess) Should we allow such tables at all? */
  if( DL_DEFAULT==DL_DOCIDS ) return SQLITE_ERROR;

  rc = content_select(v, iRowid, &pValues);
  if( rc!=SQLITE_OK ) return rc;

  for(i = 0 ; i < v->nColumn; ++i) {
    rc = buildTerms(v, iRowid, pValues[i], -1);
    if( rc!=SQLITE_OK ) break;
  }

  freeStringArray(v->nColumn, pValues);
  return SQLITE_OK;
}

/* TODO(shess) Refactor the code to remove this forward decl. */
static int initPendingTerms(fulltext_vtab *v, sqlite_int64 iDocid);

/* Insert a row into the %_content table; set *piRowid to be the ID of the
** new row.  Add doclists for terms to pendingTerms.
*/
static int index_insert(fulltext_vtab *v, sqlite3_value *pRequestRowid,
                        sqlite3_value **pValues, sqlite_int64 *piRowid){
  int rc;

  rc = content_insert(v, pRequestRowid, pValues);  /* execute an SQL INSERT */
  if( rc!=SQLITE_OK ) return rc;

  *piRowid = sqlite3_last_insert_rowid(v->db);
  rc = initPendingTerms(v, *piRowid);
  if( rc!=SQLITE_OK ) return rc;

  return insertTerms(v, *piRowid, pValues);
}

/* Delete a row from the %_content table; add empty doclists for terms
** to pendingTerms.
*/
static int index_delete(fulltext_vtab *v, sqlite_int64 iRow){
  int rc = initPendingTerms(v, iRow);
  if( rc!=SQLITE_OK ) return rc;

  rc = deleteTerms(v, iRow);
  if( rc!=SQLITE_OK ) return rc;

  return content_delete(v, iRow);  /* execute an SQL DELETE */
}

/* Update a row in the %_content table; add delete doclists to
** pendingTerms for old terms not in the new data, add insert doclists
** to pendingTerms for terms in the new data.
*/
static int index_update(fulltext_vtab *v, sqlite_int64 iRow,
                        sqlite3_value **pValues){
  int rc = initPendingTerms(v, iRow);
  if( rc!=SQLITE_OK ) return rc;

  /* Generate an empty doclist for each term that previously appeared in this
   * row. */
  rc = deleteTerms(v, iRow);
  if( rc!=SQLITE_OK ) return rc;

  rc = content_update(v, pValues, iRow);  /* execute an SQL UPDATE */
  if( rc!=SQLITE_OK ) return rc;

  /* Now add positions for terms which appear in the updated row. */
  return insertTerms(v, iRow, pValues);
}

/*******************************************************************/
/* InteriorWriter is used to collect terms and block references into
** interior nodes in %_segments.  See commentary at top of file for
** format.
*/

/* How large interior nodes can grow. */
#define INTERIOR_MAX 2048

/* Minimum number of terms per interior node (except the root). This
** prevents large terms from making the tree too skinny - must be >0
** so that the tree always makes progress.  Note that the min tree
** fanout will be INTERIOR_MIN_TERMS+1.
*/
#define INTERIOR_MIN_TERMS 7
#if INTERIOR_MIN_TERMS<1
# error INTERIOR_MIN_TERMS must be greater than 0.
#endif

/* ROOT_MAX controls how much data is stored inline in the segment
** directory.
*/
/* TODO(shess) Push ROOT_MAX down to whoever is writing things.  It's
** only here so that interiorWriterRootInfo() and leafWriterRootInfo()
** can both see it, but if the caller passed it in, we wouldn't even
** need a define.
*/
#define ROOT_MAX 1024
#if ROOT_MAX<VARINT_MAX*2
# error ROOT_MAX must have enough space for a header.
#endif

/* InteriorBlock stores a linked-list of interior blocks while a lower
** layer is being constructed.
*/
typedef struct InteriorBlock {
  DataBuffer term;           /* Leftmost term in block's subtree. */
  DataBuffer data;           /* Accumulated data for the block. */
  struct InteriorBlock *next;
} InteriorBlock;

static InteriorBlock *interiorBlockNew(int iHeight, sqlite_int64 iChildBlock,
                                       const char *pTerm, int nTerm){
  InteriorBlock *block = sqlite3_malloc(sizeof(InteriorBlock));
  char c[VARINT_MAX+VARINT_MAX];
  int n;

  if( block ){
    memset(block, 0, sizeof(*block));
    dataBufferInit(&block->term, 0);
    dataBufferReplace(&block->term, pTerm, nTerm);

    n = putVarint(c, iHeight);
    n += putVarint(c+n, iChildBlock);
    dataBufferInit(&block->data, INTERIOR_MAX);
    dataBufferReplace(&block->data, c, n);
  }
  return block;
}

#ifndef NDEBUG
/* Verify that the data is readable as an interior node. */
static void interiorBlockValidate(InteriorBlock *pBlock){
  const char *pData = pBlock->data.pData;
  int nData = pBlock->data.nData;
  int n, iDummy;
  sqlite_int64 iBlockid;

  assert( nData>0 );
  assert( pData!=0 );
  assert( pData+nData>pData );

  /* Must lead with height of node as a varint(n), n>0 */
  n = getVarint32(pData, &iDummy);
  assert( n>0 );
  assert( iDummy>0 );
  assert( n<nData );
  pData += n;
  nData -= n;

  /* Must contain iBlockid. */
  n = getVarint(pData, &iBlockid);
  assert( n>0 );
  assert( n<=nData );
  pData += n;
  nData -= n;

  /* Zero or more terms of positive length */
  if( nData!=0 ){
    /* First term is not delta-encoded. */
    n = getVarint32(pData, &iDummy);
    assert( n>0 );
    assert( iDummy>0 );
    assert( n+iDummy>0);
    assert( n+iDummy<=nData );
    pData += n+iDummy;
    nData -= n+iDummy;

    /* Following terms delta-encoded. */
    while( nData!=0 ){
      /* Length of shared prefix. */
      n = getVarint32(pData, &iDummy);
      assert( n>0 );
      assert( iDummy>=0 );
      assert( n<nData );
      pData += n;
      nData -= n;

      /* Length and data of distinct suffix. */
      n = getVarint32(pData, &iDummy);
      assert( n>0 );
      assert( iDummy>0 );
      assert( n+iDummy>0);
      assert( n+iDummy<=nData );
      pData += n+iDummy;
      nData -= n+iDummy;
    }
  }
}
#define ASSERT_VALID_INTERIOR_BLOCK(x) interiorBlockValidate(x)
#else
#define ASSERT_VALID_INTERIOR_BLOCK(x) assert( 1 )
#endif

typedef struct InteriorWriter {
  int iHeight;                   /* from 0 at leaves. */
  InteriorBlock *first, *last;
  struct InteriorWriter *parentWriter;

  DataBuffer term;               /* Last term written to block "last". */
  sqlite_int64 iOpeningChildBlock; /* First child block in block "last". */
#ifndef NDEBUG
  sqlite_int64 iLastChildBlock;  /* for consistency checks. */
#endif
} InteriorWriter;

/* Initialize an interior node where pTerm[nTerm] marks the leftmost
** term in the tree.  iChildBlock is the leftmost child block at the
** next level down the tree.
*/
static void interiorWriterInit(int iHeight, const char *pTerm, int nTerm,
                               sqlite_int64 iChildBlock,
                               InteriorWriter *pWriter){
  InteriorBlock *block;
  assert( iHeight>0 );
  CLEAR(pWriter);

  pWriter->iHeight = iHeight;
  pWriter->iOpeningChildBlock = iChildBlock;
#ifndef NDEBUG
  pWriter->iLastChildBlock = iChildBlock;
#endif
  block = interiorBlockNew(iHeight, iChildBlock, pTerm, nTerm);
  pWriter->last = pWriter->first = block;
  ASSERT_VALID_INTERIOR_BLOCK(pWriter->last);
  dataBufferInit(&pWriter->term, 0);
}

/* Append the child node rooted at iChildBlock to the interior node,
** with pTerm[nTerm] as the leftmost term in iChildBlock's subtree.
*/
static void interiorWriterAppend(InteriorWriter *pWriter,
                                 const char *pTerm, int nTerm,
                                 sqlite_int64 iChildBlock){
  char c[VARINT_MAX+VARINT_MAX];
  int n, nPrefix = 0;

  ASSERT_VALID_INTERIOR_BLOCK(pWriter->last);

  /* The first term written into an interior node is actually
  ** associated with the second child added (the first child was added
  ** in interiorWriterInit, or in the if clause at the bottom of this
  ** function).  That term gets encoded straight up, with nPrefix left
  ** at 0.
  */
  if( pWriter->term.nData==0 ){
    n = putVarint(c, nTerm);
  }else{
    while( nPrefix<pWriter->term.nData &&
           pTerm[nPrefix]==pWriter->term.pData[nPrefix] ){
      nPrefix++;
    }

    n = putVarint(c, nPrefix);
    n += putVarint(c+n, nTerm-nPrefix);
  }

#ifndef NDEBUG
  pWriter->iLastChildBlock++;
#endif
  assert( pWriter->iLastChildBlock==iChildBlock );

  /* Overflow to a new block if the new term makes the current block
  ** too big, and the current block already has enough terms.
  */
  if( pWriter->last->data.nData+n+nTerm-nPrefix>INTERIOR_MAX &&
      iChildBlock-pWriter->iOpeningChildBlock>INTERIOR_MIN_TERMS ){
    pWriter->last->next = interiorBlockNew(pWriter->iHeight, iChildBlock,
                                           pTerm, nTerm);
    pWriter->last = pWriter->last->next;
    pWriter->iOpeningChildBlock = iChildBlock;
    dataBufferReset(&pWriter->term);
  }else{
    dataBufferAppend2(&pWriter->last->data, c, n,
                      pTerm+nPrefix, nTerm-nPrefix);
    dataBufferReplace(&pWriter->term, pTerm, nTerm);
  }
  ASSERT_VALID_INTERIOR_BLOCK(pWriter->last);
}

/* Free the space used by pWriter, including the linked-list of
** InteriorBlocks, and parentWriter, if present.
*/
static int interiorWriterDestroy(InteriorWriter *pWriter){
  InteriorBlock *block = pWriter->first;

  while( block!=NULL ){
    InteriorBlock *b = block;
    block = block->next;
    dataBufferDestroy(&b->term);
    dataBufferDestroy(&b->data);
    sqlite3_free(b);
  }
  if( pWriter->parentWriter!=NULL ){
    interiorWriterDestroy(pWriter->parentWriter);
    sqlite3_free(pWriter->parentWriter);
  }
  dataBufferDestroy(&pWriter->term);
  SCRAMBLE(pWriter);
  return SQLITE_OK;
}

/* If pWriter can fit entirely in ROOT_MAX, return it as the root info
** directly, leaving *piEndBlockid unchanged.  Otherwise, flush
** pWriter to %_segments, building a new layer of interior nodes, and
** recursively ask for their root into.
*/
static int interiorWriterRootInfo(fulltext_vtab *v, InteriorWriter *pWriter,
                                  char **ppRootInfo, int *pnRootInfo,
                                  sqlite_int64 *piEndBlockid){
  InteriorBlock *block = pWriter->first;
  sqlite_int64 iBlockid = 0;
  int rc;

  /* If we can fit the segment inline */
  if( block==pWriter->last && block->data.nData<ROOT_MAX ){
    *ppRootInfo = block->data.pData;
    *pnRootInfo = block->data.nData;
    return SQLITE_OK;
  }

  /* Flush the first block to %_segments, and create a new level of
  ** interior node.
  */
  ASSERT_VALID_INTERIOR_BLOCK(block);
  rc = block_insert(v, block->data.pData, block->data.nData, &iBlockid);
  if( rc!=SQLITE_OK ) return rc;
  *piEndBlockid = iBlockid;

  pWriter->parentWriter = sqlite3_malloc(sizeof(*pWriter->parentWriter));
  interiorWriterInit(pWriter->iHeight+1,
                     block->term.pData, block->term.nData,
                     iBlockid, pWriter->parentWriter);

  /* Flush additional blocks and append to the higher interior
  ** node.
  */
  for(block=block->next; block!=NULL; block=block->next){
    ASSERT_VALID_INTERIOR_BLOCK(block);
    rc = block_insert(v, block->data.pData, block->data.nData, &iBlockid);
    if( rc!=SQLITE_OK ) return rc;
    *piEndBlockid = iBlockid;

    interiorWriterAppend(pWriter->parentWriter,
                         block->term.pData, block->term.nData, iBlockid);
  }

  /* Parent node gets the chance to be the root. */
  return interiorWriterRootInfo(v, pWriter->parentWriter,
                                ppRootInfo, pnRootInfo, piEndBlockid);
}

/****************************************************************/
/* InteriorReader is used to read off the data from an interior node
** (see comment at top of file for the format).
*/
typedef struct InteriorReader {
  const char *pData;
  int nData;

  DataBuffer term;          /* previous term, for decoding term delta. */

  sqlite_int64 iBlockid;
} InteriorReader;

static void interiorReaderDestroy(InteriorReader *pReader){
  dataBufferDestroy(&pReader->term);
  SCRAMBLE(pReader);
}

/* TODO(shess) The assertions are great, but what if we're in NDEBUG
** and the blob is empty or otherwise contains suspect data?
*/
static void interiorReaderInit(const char *pData, int nData,
                               InteriorReader *pReader){
  int n, nTerm;

  /* Require at least the leading flag byte */
  assert( nData>0 );
  assert( pData[0]!='\0' );

  CLEAR(pReader);

  /* Decode the base blockid, and set the cursor to the first term. */
  n = getVarint(pData+1, &pReader->iBlockid);
  assert( 1+n<=nData );
  pReader->pData = pData+1+n;
  pReader->nData = nData-(1+n);

  /* A single-child interior node (such as when a leaf node was too
  ** large for the segment directory) won't have any terms.
  ** Otherwise, decode the first term.
  */
  if( pReader->nData==0 ){
    dataBufferInit(&pReader->term, 0);
  }else{
    n = getVarint32(pReader->pData, &nTerm);
    dataBufferInit(&pReader->term, nTerm);
    dataBufferReplace(&pReader->term, pReader->pData+n, nTerm);
    assert( n+nTerm<=pReader->nData );
    pReader->pData += n+nTerm;
    pReader->nData -= n+nTerm;
  }
}

static int interiorReaderAtEnd(InteriorReader *pReader){
  return pReader->term.nData==0;
}

static sqlite_int64 interiorReaderCurrentBlockid(InteriorReader *pReader){
  return pReader->iBlockid;
}

static int interiorReaderTermBytes(InteriorReader *pReader){
  assert( !interiorReaderAtEnd(pReader) );
  return pReader->term.nData;
}
static const char *interiorReaderTerm(InteriorReader *pReader){
  assert( !interiorReaderAtEnd(pReader) );
  return pReader->term.pData;
}

/* Step forward to the next term in the node. */
static void interiorReaderStep(InteriorReader *pReader){
  assert( !interiorReaderAtEnd(pReader) );

  /* If the last term has been read, signal eof, else construct the
  ** next term.
  */
  if( pReader->nData==0 ){
    dataBufferReset(&pReader->term);
  }else{
    int n, nPrefix, nSuffix;

    n = getVarint32(pReader->pData, &nPrefix);
    n += getVarint32(pReader->pData+n, &nSuffix);

    /* Truncate the current term and append suffix data. */
    pReader->term.nData = nPrefix;
    dataBufferAppend(&pReader->term, pReader->pData+n, nSuffix);

    assert( n+nSuffix<=pReader->nData );
    pReader->pData += n+nSuffix;
    pReader->nData -= n+nSuffix;
  }
  pReader->iBlockid++;
}

/* Compare the current term to pTerm[nTerm], returning strcmp-style
** results.  If isPrefix, equality means equal through nTerm bytes.
*/
static int interiorReaderTermCmp(InteriorReader *pReader,
                                 const char *pTerm, int nTerm, int isPrefix){
  const char *pReaderTerm = interiorReaderTerm(pReader);
  int nReaderTerm = interiorReaderTermBytes(pReader);
  int c, n = nReaderTerm<nTerm ? nReaderTerm : nTerm;

  if( n==0 ){
    if( nReaderTerm>0 ) return -1;
    if( nTerm>0 ) return 1;
    return 0;
  }

  c = memcmp(pReaderTerm, pTerm, n);
  if( c!=0 ) return c;
  if( isPrefix && n==nTerm ) return 0;
  return nReaderTerm - nTerm;
}

/****************************************************************/
/* LeafWriter is used to collect terms and associated doclist data
** into leaf blocks in %_segments (see top of file for format info).
** Expected usage is:
**
** LeafWriter writer;
** leafWriterInit(0, 0, &writer);
** while( sorted_terms_left_to_process ){
**   // data is doclist data for that term.
**   rc = leafWriterStep(v, &writer, pTerm, nTerm, pData, nData);
**   if( rc!=SQLITE_OK ) goto err;
** }
** rc = leafWriterFinalize(v, &writer);
**err:
** leafWriterDestroy(&writer);
** return rc;
**
** leafWriterStep() may write a collected leaf out to %_segments.
** leafWriterFinalize() finishes writing any buffered data and stores
** a root node in %_segdir.  leafWriterDestroy() frees all buffers and
** InteriorWriters allocated as part of writing this segment.
**
** TODO(shess) Document leafWriterStepMerge().
*/

/* Put terms with data this big in their own block. */
#define STANDALONE_MIN 1024

/* Keep leaf blocks below this size. */
#define LEAF_MAX 2048

typedef struct LeafWriter {
  int iLevel;
  int idx;
  sqlite_int64 iStartBlockid;     /* needed to create the root info */
  sqlite_int64 iEndBlockid;       /* when we're done writing. */

  DataBuffer term;                /* previous encoded term */
  DataBuffer data;                /* encoding buffer */

  /* bytes of first term in the current node which distinguishes that
  ** term from the last term of the previous node.
  */
  int nTermDistinct;

  InteriorWriter parentWriter;    /* if we overflow */
  int has_parent;
} LeafWriter;

static void leafWriterInit(int iLevel, int idx, LeafWriter *pWriter){
  CLEAR(pWriter);
  pWriter->iLevel = iLevel;
  pWriter->idx = idx;

  dataBufferInit(&pWriter->term, 32);

  /* Start out with a reasonably sized block, though it can grow. */
  dataBufferInit(&pWriter->data, LEAF_MAX);
}

#ifndef NDEBUG
/* Verify that the data is readable as a leaf node. */
static void leafNodeValidate(const char *pData, int nData){
  int n, iDummy;

  if( nData==0 ) return;
  assert( nData>0 );
  assert( pData!=0 );
  assert( pData+nData>pData );

  /* Must lead with a varint(0) */
  n = getVarint32(pData, &iDummy);
  assert( iDummy==0 );
  assert( n>0 );
  assert( n<nData );
  pData += n;
  nData -= n;

  /* Leading term length and data must fit in buffer. */
  n = getVarint32(pData, &iDummy);
  assert( n>0 );
  assert( iDummy>0 );
  assert( n+iDummy>0 );
  assert( n+iDummy<nData );
  pData += n+iDummy;
  nData -= n+iDummy;

  /* Leading term's doclist length and data must fit. */
  n = getVarint32(pData, &iDummy);
  assert( n>0 );
  assert( iDummy>0 );
  assert( n+iDummy>0 );
  assert( n+iDummy<=nData );
  ASSERT_VALID_DOCLIST(DL_DEFAULT, pData+n, iDummy, NULL);
  pData += n+iDummy;
  nData -= n+iDummy;

  /* Verify that trailing terms and doclists also are readable. */
  while( nData!=0 ){
    n = getVarint32(pData, &iDummy);
    assert( n>0 );
    assert( iDummy>=0 );
    assert( n<nData );
    pData += n;
    nData -= n;
    n = getVarint32(pData, &iDummy);
    assert( n>0 );
    assert( iDummy>0 );
    assert( n+iDummy>0 );
    assert( n+iDummy<nData );
    pData += n+iDummy;
    nData -= n+iDummy;

    n = getVarint32(pData, &iDummy);
    assert( n>0 );
    assert( iDummy>0 );
    assert( n+iDummy>0 );
    assert( n+iDummy<=nData );
    ASSERT_VALID_DOCLIST(DL_DEFAULT, pData+n, iDummy, NULL);
    pData += n+iDummy;
    nData -= n+iDummy;
  }
}
#define ASSERT_VALID_LEAF_NODE(p, n) leafNodeValidate(p, n)
#else
#define ASSERT_VALID_LEAF_NODE(p, n) assert( 1 )
#endif

/* Flush the current leaf node to %_segments, and adding the resulting
** blockid and the starting term to the interior node which will
** contain it.
*/
static int leafWriterInternalFlush(fulltext_vtab *v, LeafWriter *pWriter,
                                   int iData, int nData){
  sqlite_int64 iBlockid = 0;
  const char *pStartingTerm;
  int nStartingTerm, rc, n;

  /* Must have the leading varint(0) flag, plus at least some
  ** valid-looking data.
  */
  assert( nData>2 );
  assert( iData>=0 );
  assert( iData+nData<=pWriter->data.nData );
  ASSERT_VALID_LEAF_NODE(pWriter->data.pData+iData, nData);

  rc = block_insert(v, pWriter->data.pData+iData, nData, &iBlockid);
  if( rc!=SQLITE_OK ) return rc;
  assert( iBlockid!=0 );

  /* Reconstruct the first term in the leaf for purposes of building
  ** the interior node.
  */
  n = getVarint32(pWriter->data.pData+iData+1, &nStartingTerm);
  pStartingTerm = pWriter->data.pData+iData+1+n;
  assert( pWriter->data.nData>iData+1+n+nStartingTerm );
  assert( pWriter->nTermDistinct>0 );
  assert( pWriter->nTermDistinct<=nStartingTerm );
  nStartingTerm = pWriter->nTermDistinct;

  if( pWriter->has_parent ){
    interiorWriterAppend(&pWriter->parentWriter,
                         pStartingTerm, nStartingTerm, iBlockid);
  }else{
    interiorWriterInit(1, pStartingTerm, nStartingTerm, iBlockid,
                       &pWriter->parentWriter);
    pWriter->has_parent = 1;
  }

  /* Track the span of this segment's leaf nodes. */
  if( pWriter->iEndBlockid==0 ){
    pWriter->iEndBlockid = pWriter->iStartBlockid = iBlockid;
  }else{
    pWriter->iEndBlockid++;
    assert( iBlockid==pWriter->iEndBlockid );
  }

  return SQLITE_OK;
}
static int leafWriterFlush(fulltext_vtab *v, LeafWriter *pWriter){
  int rc = leafWriterInternalFlush(v, pWriter, 0, pWriter->data.nData);
  if( rc!=SQLITE_OK ) return rc;

  /* Re-initialize the output buffer. */
  dataBufferReset(&pWriter->data);

  return SQLITE_OK;
}

/* Fetch the root info for the segment.  If the entire leaf fits
** within ROOT_MAX, then it will be returned directly, otherwise it
** will be flushed and the root info will be returned from the
** interior node.  *piEndBlockid is set to the blockid of the last
** interior or leaf node written to disk (0 if none are written at
** all).
*/
static int leafWriterRootInfo(fulltext_vtab *v, LeafWriter *pWriter,
                              char **ppRootInfo, int *pnRootInfo,
                              sqlite_int64 *piEndBlockid){
  /* we can fit the segment entirely inline */
  if( !pWriter->has_parent && pWriter->data.nData<ROOT_MAX ){
    *ppRootInfo = pWriter->data.pData;
    *pnRootInfo = pWriter->data.nData;
    *piEndBlockid = 0;
    return SQLITE_OK;
  }

  /* Flush remaining leaf data. */
  if( pWriter->data.nData>0 ){
    int rc = leafWriterFlush(v, pWriter);
    if( rc!=SQLITE_OK ) return rc;
  }

  /* We must have flushed a leaf at some point. */
  assert( pWriter->has_parent );

  /* Tenatively set the end leaf blockid as the end blockid.  If the
  ** interior node can be returned inline, this will be the final
  ** blockid, otherwise it will be overwritten by
  ** interiorWriterRootInfo().
  */
  *piEndBlockid = pWriter->iEndBlockid;

  return interiorWriterRootInfo(v, &pWriter->parentWriter,
                                ppRootInfo, pnRootInfo, piEndBlockid);
}

/* Collect the rootInfo data and store it into the segment directory.
** This has the effect of flushing the segment's leaf data to
** %_segments, and also flushing any interior nodes to %_segments.
*/
static int leafWriterFinalize(fulltext_vtab *v, LeafWriter *pWriter){
  sqlite_int64 iEndBlockid;
  char *pRootInfo;
  int rc, nRootInfo;

  rc = leafWriterRootInfo(v, pWriter, &pRootInfo, &nRootInfo, &iEndBlockid);
  if( rc!=SQLITE_OK ) return rc;

  /* Don't bother storing an entirely empty segment. */
  if( iEndBlockid==0 && nRootInfo==0 ) return SQLITE_OK;

  return segdir_set(v, pWriter->iLevel, pWriter->idx,
                    pWriter->iStartBlockid, pWriter->iEndBlockid,
                    iEndBlockid, pRootInfo, nRootInfo);
}

static void leafWriterDestroy(LeafWriter *pWriter){
  if( pWriter->has_parent ) interiorWriterDestroy(&pWriter->parentWriter);
  dataBufferDestroy(&pWriter->term);
  dataBufferDestroy(&pWriter->data);
}

/* Encode a term into the leafWriter, delta-encoding as appropriate.
** Returns the length of the new term which distinguishes it from the
** previous term, which can be used to set nTermDistinct when a node
** boundary is crossed.
*/
static int leafWriterEncodeTerm(LeafWriter *pWriter,
                                const char *pTerm, int nTerm){
  char c[VARINT_MAX+VARINT_MAX];
  int n, nPrefix = 0;

  assert( nTerm>0 );
  while( nPrefix<pWriter->term.nData &&
         pTerm[nPrefix]==pWriter->term.pData[nPrefix] ){
    nPrefix++;
    /* Failing this implies that the terms weren't in order. */
    assert( nPrefix<nTerm );
  }

  if( pWriter->data.nData==0 ){
    /* Encode the node header and leading term as:
    **  varint(0)
    **  varint(nTerm)
    **  char pTerm[nTerm]
    */
    n = putVarint(c, '\0');
    n += putVarint(c+n, nTerm);
    dataBufferAppend2(&pWriter->data, c, n, pTerm, nTerm);
  }else{
    /* Delta-encode the term as:
    **  varint(nPrefix)
    **  varint(nSuffix)
    **  char pTermSuffix[nSuffix]
    */
    n = putVarint(c, nPrefix);
    n += putVarint(c+n, nTerm-nPrefix);
    dataBufferAppend2(&pWriter->data, c, n, pTerm+nPrefix, nTerm-nPrefix);
  }
  dataBufferReplace(&pWriter->term, pTerm, nTerm);

  return nPrefix+1;
}

/* Used to avoid a memmove when a large amount of doclist data is in
** the buffer.  This constructs a node and term header before
** iDoclistData and flushes the resulting complete node using
** leafWriterInternalFlush().
*/
static int leafWriterInlineFlush(fulltext_vtab *v, LeafWriter *pWriter,
                                 const char *pTerm, int nTerm,
                                 int iDoclistData){
  char c[VARINT_MAX+VARINT_MAX];
  int iData, n = putVarint(c, 0);
  n += putVarint(c+n, nTerm);

  /* There should always be room for the header.  Even if pTerm shared
  ** a substantial prefix with the previous term, the entire prefix
  ** could be constructed from earlier data in the doclist, so there
  ** should be room.
  */
  assert( iDoclistData>=n+nTerm );

  iData = iDoclistData-(n+nTerm);
  memcpy(pWriter->data.pData+iData, c, n);
  memcpy(pWriter->data.pData+iData+n, pTerm, nTerm);

  return leafWriterInternalFlush(v, pWriter, iData, pWriter->data.nData-iData);
}

/* Push pTerm[nTerm] along with the doclist data to the leaf layer of
** %_segments.
*/
static int leafWriterStepMerge(fulltext_vtab *v, LeafWriter *pWriter,
                               const char *pTerm, int nTerm,
                               DLReader *pReaders, int nReaders){
  char c[VARINT_MAX+VARINT_MAX];
  int iTermData = pWriter->data.nData, iDoclistData;
  int i, nData, n, nActualData, nActual, rc, nTermDistinct;

  ASSERT_VALID_LEAF_NODE(pWriter->data.pData, pWriter->data.nData);
  nTermDistinct = leafWriterEncodeTerm(pWriter, pTerm, nTerm);

  /* Remember nTermDistinct if opening a new node. */
  if( iTermData==0 ) pWriter->nTermDistinct = nTermDistinct;

  iDoclistData = pWriter->data.nData;

  /* Estimate the length of the merged doclist so we can leave space
  ** to encode it.
  */
  for(i=0, nData=0; i<nReaders; i++){
    nData += dlrAllDataBytes(&pReaders[i]);
  }
  n = putVarint(c, nData);
  dataBufferAppend(&pWriter->data, c, n);

  docListMerge(&pWriter->data, pReaders, nReaders);
  ASSERT_VALID_DOCLIST(DL_DEFAULT,
                       pWriter->data.pData+iDoclistData+n,
                       pWriter->data.nData-iDoclistData-n, NULL);

  /* The actual amount of doclist data at this point could be smaller
  ** than the length we encoded.  Additionally, the space required to
  ** encode this length could be smaller.  For small doclists, this is
  ** not a big deal, we can just use memmove() to adjust things.
  */
  nActualData = pWriter->data.nData-(iDoclistData+n);
  nActual = putVarint(c, nActualData);
  assert( nActualData<=nData );
  assert( nActual<=n );

  /* If the new doclist is big enough for force a standalone leaf
  ** node, we can immediately flush it inline without doing the
  ** memmove().
  */
  /* TODO(shess) This test matches leafWriterStep(), which does this
  ** test before it knows the cost to varint-encode the term and
  ** doclist lengths.  At some point, change to
  ** pWriter->data.nData-iTermData>STANDALONE_MIN.
  */
  if( nTerm+nActualData>STANDALONE_MIN ){
    /* Push leaf node from before this term. */
    if( iTermData>0 ){
      rc = leafWriterInternalFlush(v, pWriter, 0, iTermData);
      if( rc!=SQLITE_OK ) return rc;

      pWriter->nTermDistinct = nTermDistinct;
    }

    /* Fix the encoded doclist length. */
    iDoclistData += n - nActual;
    memcpy(pWriter->data.pData+iDoclistData, c, nActual);

    /* Push the standalone leaf node. */
    rc = leafWriterInlineFlush(v, pWriter, pTerm, nTerm, iDoclistData);
    if( rc!=SQLITE_OK ) return rc;

    /* Leave the node empty. */
    dataBufferReset(&pWriter->data);

    return rc;
  }

  /* At this point, we know that the doclist was small, so do the
  ** memmove if indicated.
  */
  if( nActual<n ){
    memmove(pWriter->data.pData+iDoclistData+nActual,
            pWriter->data.pData+iDoclistData+n,
            pWriter->data.nData-(iDoclistData+n));
    pWriter->data.nData -= n-nActual;
  }

  /* Replace written length with actual length. */
  memcpy(pWriter->data.pData+iDoclistData, c, nActual);

  /* If the node is too large, break things up. */
  /* TODO(shess) This test matches leafWriterStep(), which does this
  ** test before it knows the cost to varint-encode the term and
  ** doclist lengths.  At some point, change to
  ** pWriter->data.nData>LEAF_MAX.
  */
  if( iTermData+nTerm+nActualData>LEAF_MAX ){
    /* Flush out the leading data as a node */
    rc = leafWriterInternalFlush(v, pWriter, 0, iTermData);
    if( rc!=SQLITE_OK ) return rc;

    pWriter->nTermDistinct = nTermDistinct;

    /* Rebuild header using the current term */
    n = putVarint(pWriter->data.pData, 0);
    n += putVarint(pWriter->data.pData+n, nTerm);
    memcpy(pWriter->data.pData+n, pTerm, nTerm);
    n += nTerm;

    /* There should always be room, because the previous encoding
    ** included all data necessary to construct the term.
    */
    assert( n<iDoclistData );
    /* So long as STANDALONE_MIN is half or less of LEAF_MAX, the
    ** following memcpy() is safe (as opposed to needing a memmove).
    */
    assert( 2*STANDALONE_MIN<=LEAF_MAX );
    assert( n+pWriter->data.nData-iDoclistData<iDoclistData );
    memcpy(pWriter->data.pData+n,
           pWriter->data.pData+iDoclistData,
           pWriter->data.nData-iDoclistData);
    pWriter->data.nData -= iDoclistData-n;
  }
  ASSERT_VALID_LEAF_NODE(pWriter->data.pData, pWriter->data.nData);

  return SQLITE_OK;
}

/* Push pTerm[nTerm] along with the doclist data to the leaf layer of
** %_segments.
*/
/* TODO(shess) Revise writeZeroSegment() so that doclists are
** constructed directly in pWriter->data.
*/
static int leafWriterStep(fulltext_vtab *v, LeafWriter *pWriter,
                          const char *pTerm, int nTerm,
                          const char *pData, int nData){
  int rc;
  DLReader reader;

  dlrInit(&reader, DL_DEFAULT, pData, nData);
  rc = leafWriterStepMerge(v, pWriter, pTerm, nTerm, &reader, 1);
  dlrDestroy(&reader);

  return rc;
}


/****************************************************************/
/* LeafReader is used to iterate over an individual leaf node. */
typedef struct LeafReader {
  DataBuffer term;          /* copy of current term. */

  const char *pData;        /* data for current term. */
  int nData;
} LeafReader;

static void leafReaderDestroy(LeafReader *pReader){
  dataBufferDestroy(&pReader->term);
  SCRAMBLE(pReader);
}

static int leafReaderAtEnd(LeafReader *pReader){
  return pReader->nData<=0;
}

/* Access the current term. */
static int leafReaderTermBytes(LeafReader *pReader){
  return pReader->term.nData;
}
static const char *leafReaderTerm(LeafReader *pReader){
  assert( pReader->term.nData>0 );
  return pReader->term.pData;
}

/* Access the doclist data for the current term. */
static int leafReaderDataBytes(LeafReader *pReader){
  int nData;
  assert( pReader->term.nData>0 );
  getVarint32(pReader->pData, &nData);
  return nData;
}
static const char *leafReaderData(LeafReader *pReader){
  int n, nData;
  assert( pReader->term.nData>0 );
  n = getVarint32(pReader->pData, &nData);
  return pReader->pData+n;
}

static void leafReaderInit(const char *pData, int nData,
                           LeafReader *pReader){
  int nTerm, n;

  assert( nData>0 );
  assert( pData[0]=='\0' );

  CLEAR(pReader);

  /* Read the first term, skipping the header byte. */
  n = getVarint32(pData+1, &nTerm);
  dataBufferInit(&pReader->term, nTerm);
  dataBufferReplace(&pReader->term, pData+1+n, nTerm);

  /* Position after the first term. */
  assert( 1+n+nTerm<nData );
  pReader->pData = pData+1+n+nTerm;
  pReader->nData = nData-1-n-nTerm;
}

/* Step the reader forward to the next term. */
static void leafReaderStep(LeafReader *pReader){
  int n, nData, nPrefix, nSuffix;
  assert( !leafReaderAtEnd(pReader) );

  /* Skip previous entry's data block. */
  n = getVarint32(pReader->pData, &nData);
  assert( n+nData<=pReader->nData );
  pReader->pData += n+nData;
  pReader->nData -= n+nData;

  if( !leafReaderAtEnd(pReader) ){
    /* Construct the new term using a prefix from the old term plus a
    ** suffix from the leaf data.
    */
    n = getVarint32(pReader->pData, &nPrefix);
    n += getVarint32(pReader->pData+n, &nSuffix);
    assert( n+nSuffix<pReader->nData );
    pReader->term.nData = nPrefix;
    dataBufferAppend(&pReader->term, pReader->pData+n, nSuffix);

    pReader->pData += n+nSuffix;
    pReader->nData -= n+nSuffix;
  }
}

/* strcmp-style comparison of pReader's current term against pTerm.
** If isPrefix, equality means equal through nTerm bytes.
*/
static int leafReaderTermCmp(LeafReader *pReader,
                             const char *pTerm, int nTerm, int isPrefix){
  int c, n = pReader->term.nData<nTerm ? pReader->term.nData : nTerm;
  if( n==0 ){
    if( pReader->term.nData>0 ) return -1;
    if(nTerm>0 ) return 1;
    return 0;
  }

  c = memcmp(pReader->term.pData, pTerm, n);
  if( c!=0 ) return c;
  if( isPrefix && n==nTerm ) return 0;
  return pReader->term.nData - nTerm;
}


/****************************************************************/
/* LeavesReader wraps LeafReader to allow iterating over the entire
** leaf layer of the tree.
*/
typedef struct LeavesReader {
  int idx;                  /* Index within the segment. */

  sqlite3_stmt *pStmt;      /* Statement we're streaming leaves from. */
  int eof;                  /* we've seen SQLITE_DONE from pStmt. */

  LeafReader leafReader;    /* reader for the current leaf. */
  DataBuffer rootData;      /* root data for inline. */
} LeavesReader;

/* Access the current term. */
static int leavesReaderTermBytes(LeavesReader *pReader){
  assert( !pReader->eof );
  return leafReaderTermBytes(&pReader->leafReader);
}
static const char *leavesReaderTerm(LeavesReader *pReader){
  assert( !pReader->eof );
  return leafReaderTerm(&pReader->leafReader);
}

/* Access the doclist data for the current term. */
static int leavesReaderDataBytes(LeavesReader *pReader){
  assert( !pReader->eof );
  return leafReaderDataBytes(&pReader->leafReader);
}
static const char *leavesReaderData(LeavesReader *pReader){
  assert( !pReader->eof );
  return leafReaderData(&pReader->leafReader);
}

static int leavesReaderAtEnd(LeavesReader *pReader){
  return pReader->eof;
}

/* loadSegmentLeaves() may not read all the way to SQLITE_DONE, thus
** leaving the statement handle open, which locks the table.
*/
/* TODO(shess) This "solution" is not satisfactory.  Really, there
** should be check-in function for all statement handles which
** arranges to call sqlite3_reset().  This most likely will require
** modification to control flow all over the place, though, so for now
** just punt.
**
** Note the current system assumes that segment merges will run to
** completion, which is why this particular probably hasn't arisen in
** this case.  Probably a brittle assumption.
*/
static int leavesReaderReset(LeavesReader *pReader){
  return sqlite3_reset(pReader->pStmt);
}

static void leavesReaderDestroy(LeavesReader *pReader){
  /* If idx is -1, that means we're using a non-cached statement
  ** handle in the optimize() case, so we need to release it.
  */
  if( pReader->pStmt!=NULL && pReader->idx==-1 ){
    sqlite3_finalize(pReader->pStmt);
  }
  leafReaderDestroy(&pReader->leafReader);
  dataBufferDestroy(&pReader->rootData);
  SCRAMBLE(pReader);
}

/* Initialize pReader with the given root data (if iStartBlockid==0
** the leaf data was entirely contained in the root), or from the
** stream of blocks between iStartBlockid and iEndBlockid, inclusive.
*/
static int leavesReaderInit(fulltext_vtab *v,
                            int idx,
                            sqlite_int64 iStartBlockid,
                            sqlite_int64 iEndBlockid,
                            const char *pRootData, int nRootData,
                            LeavesReader *pReader){
  CLEAR(pReader);
  pReader->idx = idx;

  dataBufferInit(&pReader->rootData, 0);
  if( iStartBlockid==0 ){
    /* Entire leaf level fit in root data. */
    dataBufferReplace(&pReader->rootData, pRootData, nRootData);
    leafReaderInit(pReader->rootData.pData, pReader->rootData.nData,
                   &pReader->leafReader);
  }else{
    sqlite3_stmt *s;
    int rc = sql_get_leaf_statement(v, idx, &s);
    if( rc!=SQLITE_OK ) return rc;

    rc = sqlite3_bind_int64(s, 1, iStartBlockid);
    if( rc!=SQLITE_OK ) return rc;

    rc = sqlite3_bind_int64(s, 2, iEndBlockid);
    if( rc!=SQLITE_OK ) return rc;

    rc = sqlite3_step(s);
    if( rc==SQLITE_DONE ){
      pReader->eof = 1;
      return SQLITE_OK;
    }
    if( rc!=SQLITE_ROW ) return rc;

    pReader->pStmt = s;
    leafReaderInit(sqlite3_column_blob(pReader->pStmt, 0),
                   sqlite3_column_bytes(pReader->pStmt, 0),
                   &pReader->leafReader);
  }
  return SQLITE_OK;
}

/* Step the current leaf forward to the next term.  If we reach the
** end of the current leaf, step forward to the next leaf block.
*/
static int leavesReaderStep(fulltext_vtab *v, LeavesReader *pReader){
  assert( !leavesReaderAtEnd(pReader) );
  leafReaderStep(&pReader->leafReader);

  if( leafReaderAtEnd(&pReader->leafReader) ){
    int rc;
    if( pReader->rootData.pData ){
      pReader->eof = 1;
      return SQLITE_OK;
    }
    rc = sqlite3_step(pReader->pStmt);
    if( rc!=SQLITE_ROW ){
      pReader->eof = 1;
      return rc==SQLITE_DONE ? SQLITE_OK : rc;
    }
    leafReaderDestroy(&pReader->leafReader);
    leafReaderInit(sqlite3_column_blob(pReader->pStmt, 0),
                   sqlite3_column_bytes(pReader->pStmt, 0),
                   &pReader->leafReader);
  }
  return SQLITE_OK;
}

/* Order LeavesReaders by their term, ignoring idx.  Readers at eof
** always sort to the end.
*/
static int leavesReaderTermCmp(LeavesReader *lr1, LeavesReader *lr2){
  if( leavesReaderAtEnd(lr1) ){
    if( leavesReaderAtEnd(lr2) ) return 0;
    return 1;
  }
  if( leavesReaderAtEnd(lr2) ) return -1;

  return leafReaderTermCmp(&lr1->leafReader,
                           leavesReaderTerm(lr2), leavesReaderTermBytes(lr2),
                           0);
}

/* Similar to leavesReaderTermCmp(), with additional ordering by idx
** so that older segments sort before newer segments.
*/
static int leavesReaderCmp(LeavesReader *lr1, LeavesReader *lr2){
  int c = leavesReaderTermCmp(lr1, lr2);
  if( c!=0 ) return c;
  return lr1->idx-lr2->idx;
}

/* Assume that pLr[1]..pLr[nLr] are sorted.  Bubble pLr[0] into its
** sorted position.
*/
static void leavesReaderReorder(LeavesReader *pLr, int nLr){
  while( nLr>1 && leavesReaderCmp(pLr, pLr+1)>0 ){
    LeavesReader tmp = pLr[0];
    pLr[0] = pLr[1];
    pLr[1] = tmp;
    nLr--;
    pLr++;
  }
}

/* Initializes pReaders with the segments from level iLevel, returning
** the number of segments in *piReaders.  Leaves pReaders in sorted
** order.
*/
static int leavesReadersInit(fulltext_vtab *v, int iLevel,
                             LeavesReader *pReaders, int *piReaders){
  sqlite3_stmt *s;
  int i, rc = sql_get_statement(v, SEGDIR_SELECT_LEVEL_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_int(s, 1, iLevel);
  if( rc!=SQLITE_OK ) return rc;

  i = 0;
  while( (rc = sqlite3_step(s))==SQLITE_ROW ){
    sqlite_int64 iStart = sqlite3_column_int64(s, 0);
    sqlite_int64 iEnd = sqlite3_column_int64(s, 1);
    const char *pRootData = sqlite3_column_blob(s, 2);
    int nRootData = sqlite3_column_bytes(s, 2);

    assert( i<MERGE_COUNT );
    rc = leavesReaderInit(v, i, iStart, iEnd, pRootData, nRootData,
                          &pReaders[i]);
    if( rc!=SQLITE_OK ) break;

    i++;
  }
  if( rc!=SQLITE_DONE ){
    while( i-->0 ){
      leavesReaderDestroy(&pReaders[i]);
    }
    return rc;
  }

  *piReaders = i;

  /* Leave our results sorted by term, then age. */
  while( i-- ){
    leavesReaderReorder(pReaders+i, *piReaders-i);
  }
  return SQLITE_OK;
}

/* Merge doclists from pReaders[nReaders] into a single doclist, which
** is written to pWriter.  Assumes pReaders is ordered oldest to
** newest.
*/
/* TODO(shess) Consider putting this inline in segmentMerge(). */
static int leavesReadersMerge(fulltext_vtab *v,
                              LeavesReader *pReaders, int nReaders,
                              LeafWriter *pWriter){
  DLReader dlReaders[MERGE_COUNT];
  const char *pTerm = leavesReaderTerm(pReaders);
  int i, nTerm = leavesReaderTermBytes(pReaders);

  assert( nReaders<=MERGE_COUNT );

  for(i=0; i<nReaders; i++){
    dlrInit(&dlReaders[i], DL_DEFAULT,
            leavesReaderData(pReaders+i),
            leavesReaderDataBytes(pReaders+i));
  }

  return leafWriterStepMerge(v, pWriter, pTerm, nTerm, dlReaders, nReaders);
}

/* Forward ref due to mutual recursion with segdirNextIndex(). */
static int segmentMerge(fulltext_vtab *v, int iLevel);

/* Put the next available index at iLevel into *pidx.  If iLevel
** already has MERGE_COUNT segments, they are merged to a higher
** level to make room.
*/
static int segdirNextIndex(fulltext_vtab *v, int iLevel, int *pidx){
  int rc = segdir_max_index(v, iLevel, pidx);
  if( rc==SQLITE_DONE ){              /* No segments at iLevel. */
    *pidx = 0;
  }else if( rc==SQLITE_ROW ){
    if( *pidx==(MERGE_COUNT-1) ){
      rc = segmentMerge(v, iLevel);
      if( rc!=SQLITE_OK ) return rc;
      *pidx = 0;
    }else{
      (*pidx)++;
    }
  }else{
    return rc;
  }
  return SQLITE_OK;
}

/* Merge MERGE_COUNT segments at iLevel into a new segment at
** iLevel+1.  If iLevel+1 is already full of segments, those will be
** merged to make room.
*/
static int segmentMerge(fulltext_vtab *v, int iLevel){
  LeafWriter writer;
  LeavesReader lrs[MERGE_COUNT];
  int i, rc, idx = 0;

  /* Determine the next available segment index at the next level,
  ** merging as necessary.
  */
  rc = segdirNextIndex(v, iLevel+1, &idx);
  if( rc!=SQLITE_OK ) return rc;

  /* TODO(shess) This assumes that we'll always see exactly
  ** MERGE_COUNT segments to merge at a given level.  That will be
  ** broken if we allow the developer to request preemptive or
  ** deferred merging.
  */
  memset(&lrs, '\0', sizeof(lrs));
  rc = leavesReadersInit(v, iLevel, lrs, &i);
  if( rc!=SQLITE_OK ) return rc;
  assert( i==MERGE_COUNT );

  leafWriterInit(iLevel+1, idx, &writer);

  /* Since leavesReaderReorder() pushes readers at eof to the end,
  ** when the first reader is empty, all will be empty.
  */
  while( !leavesReaderAtEnd(lrs) ){
    /* Figure out how many readers share their next term. */
    for(i=1; i<MERGE_COUNT && !leavesReaderAtEnd(lrs+i); i++){
      if( 0!=leavesReaderTermCmp(lrs, lrs+i) ) break;
    }

    rc = leavesReadersMerge(v, lrs, i, &writer);
    if( rc!=SQLITE_OK ) goto err;

    /* Step forward those that were merged. */
    while( i-->0 ){
      rc = leavesReaderStep(v, lrs+i);
      if( rc!=SQLITE_OK ) goto err;

      /* Reorder by term, then by age. */
      leavesReaderReorder(lrs+i, MERGE_COUNT-i);
    }
  }

  for(i=0; i<MERGE_COUNT; i++){
    leavesReaderDestroy(&lrs[i]);
  }

  rc = leafWriterFinalize(v, &writer);
  leafWriterDestroy(&writer);
  if( rc!=SQLITE_OK ) return rc;

  /* Delete the merged segment data. */
  return segdir_delete(v, iLevel);

 err:
  for(i=0; i<MERGE_COUNT; i++){
    leavesReaderDestroy(&lrs[i]);
  }
  leafWriterDestroy(&writer);
  return rc;
}

/* Accumulate the union of *acc and *pData into *acc. */
static void docListAccumulateUnion(DataBuffer *acc,
                                   const char *pData, int nData) {
  DataBuffer tmp = *acc;
  dataBufferInit(acc, tmp.nData+nData);
  docListUnion(tmp.pData, tmp.nData, pData, nData, acc);
  dataBufferDestroy(&tmp);
}

/* TODO(shess) It might be interesting to explore different merge
** strategies, here.  For instance, since this is a sorted merge, we
** could easily merge many doclists in parallel.  With some
** comprehension of the storage format, we could merge all of the
** doclists within a leaf node directly from the leaf node's storage.
** It may be worthwhile to merge smaller doclists before larger
** doclists, since they can be traversed more quickly - but the
** results may have less overlap, making them more expensive in a
** different way.
*/

/* Scan pReader for pTerm/nTerm, and merge the term's doclist over
** *out (any doclists with duplicate docids overwrite those in *out).
** Internal function for loadSegmentLeaf().
*/
static int loadSegmentLeavesInt(fulltext_vtab *v, LeavesReader *pReader,
                                const char *pTerm, int nTerm, int isPrefix,
                                DataBuffer *out){
  /* doclist data is accumulated into pBuffers similar to how one does
  ** increment in binary arithmetic.  If index 0 is empty, the data is
  ** stored there.  If there is data there, it is merged and the
  ** results carried into position 1, with further merge-and-carry
  ** until an empty position is found.
  */
  DataBuffer *pBuffers = NULL;
  int nBuffers = 0, nMaxBuffers = 0, rc;

  assert( nTerm>0 );

  for(rc=SQLITE_OK; rc==SQLITE_OK && !leavesReaderAtEnd(pReader);
      rc=leavesReaderStep(v, pReader)){
    /* TODO(shess) Really want leavesReaderTermCmp(), but that name is
    ** already taken to compare the terms of two LeavesReaders.  Think
    ** on a better name.  [Meanwhile, break encapsulation rather than
    ** use a confusing name.]
    */
    int c = leafReaderTermCmp(&pReader->leafReader, pTerm, nTerm, isPrefix);
    if( c>0 ) break;      /* Past any possible matches. */
    if( c==0 ){
      const char *pData = leavesReaderData(pReader);
      int iBuffer, nData = leavesReaderDataBytes(pReader);

      /* Find the first empty buffer. */
      for(iBuffer=0; iBuffer<nBuffers; ++iBuffer){
        if( 0==pBuffers[iBuffer].nData ) break;
      }

      /* Out of buffers, add an empty one. */
      if( iBuffer==nBuffers ){
        if( nBuffers==nMaxBuffers ){
          DataBuffer *p;
          nMaxBuffers += 20;

          /* Manual realloc so we can handle NULL appropriately. */
          p = sqlite3_malloc(nMaxBuffers*sizeof(*pBuffers));
          if( p==NULL ){
            rc = SQLITE_NOMEM;
            break;
          }

          if( nBuffers>0 ){
            assert(pBuffers!=NULL);
            memcpy(p, pBuffers, nBuffers*sizeof(*pBuffers));
            sqlite3_free(pBuffers);
          }
          pBuffers = p;
        }
        dataBufferInit(&(pBuffers[nBuffers]), 0);
        nBuffers++;
      }

      /* At this point, must have an empty at iBuffer. */
      assert(iBuffer<nBuffers && pBuffers[iBuffer].nData==0);

      /* If empty was first buffer, no need for merge logic. */
      if( iBuffer==0 ){
        dataBufferReplace(&(pBuffers[0]), pData, nData);
      }else{
        /* pAcc is the empty buffer the merged data will end up in. */
        DataBuffer *pAcc = &(pBuffers[iBuffer]);
        DataBuffer *p = &(pBuffers[0]);

        /* Handle position 0 specially to avoid need to prime pAcc
        ** with pData/nData.
        */
        dataBufferSwap(p, pAcc);
        docListAccumulateUnion(pAcc, pData, nData);

        /* Accumulate remaining doclists into pAcc. */
        for(++p; p<pAcc; ++p){
          docListAccumulateUnion(pAcc, p->pData, p->nData);

          /* dataBufferReset() could allow a large doclist to blow up
          ** our memory requirements.
          */
          if( p->nCapacity<1024 ){
            dataBufferReset(p);
          }else{
            dataBufferDestroy(p);
            dataBufferInit(p, 0);
          }
        }
      }
    }
  }

  /* Union all the doclists together into *out. */
  /* TODO(shess) What if *out is big?  Sigh. */
  if( rc==SQLITE_OK && nBuffers>0 ){
    int iBuffer;
    for(iBuffer=0; iBuffer<nBuffers; ++iBuffer){
      if( pBuffers[iBuffer].nData>0 ){
        if( out->nData==0 ){
          dataBufferSwap(out, &(pBuffers[iBuffer]));
        }else{
          docListAccumulateUnion(out, pBuffers[iBuffer].pData,
                                 pBuffers[iBuffer].nData);
        }
      }
    }
  }

  while( nBuffers-- ){
    dataBufferDestroy(&(pBuffers[nBuffers]));
  }
  if( pBuffers!=NULL ) sqlite3_free(pBuffers);

  return rc;
}

/* Call loadSegmentLeavesInt() with pData/nData as input. */
static int loadSegmentLeaf(fulltext_vtab *v, const char *pData, int nData,
                           const char *pTerm, int nTerm, int isPrefix,
                           DataBuffer *out){
  LeavesReader reader;
  int rc;

  assert( nData>1 );
  assert( *pData=='\0' );
  rc = leavesReaderInit(v, 0, 0, 0, pData, nData, &reader);
  if( rc!=SQLITE_OK ) return rc;

  rc = loadSegmentLeavesInt(v, &reader, pTerm, nTerm, isPrefix, out);
  leavesReaderReset(&reader);
  leavesReaderDestroy(&reader);
  return rc;
}

/* Call loadSegmentLeavesInt() with the leaf nodes from iStartLeaf to
** iEndLeaf (inclusive) as input, and merge the resulting doclist into
** out.
*/
static int loadSegmentLeaves(fulltext_vtab *v,
                             sqlite_int64 iStartLeaf, sqlite_int64 iEndLeaf,
                             const char *pTerm, int nTerm, int isPrefix,
                             DataBuffer *out){
  int rc;
  LeavesReader reader;

  assert( iStartLeaf<=iEndLeaf );
  rc = leavesReaderInit(v, 0, iStartLeaf, iEndLeaf, NULL, 0, &reader);
  if( rc!=SQLITE_OK ) return rc;

  rc = loadSegmentLeavesInt(v, &reader, pTerm, nTerm, isPrefix, out);
  leavesReaderReset(&reader);
  leavesReaderDestroy(&reader);
  return rc;
}

/* Taking pData/nData as an interior node, find the sequence of child
** nodes which could include pTerm/nTerm/isPrefix.  Note that the
** interior node terms logically come between the blocks, so there is
** one more blockid than there are terms (that block contains terms >=
** the last interior-node term).
*/
/* TODO(shess) The calling code may already know that the end child is
** not worth calculating, because the end may be in a later sibling
** node.  Consider whether breaking symmetry is worthwhile.  I suspect
** it is not worthwhile.
*/
static void getChildrenContaining(const char *pData, int nData,
                                  const char *pTerm, int nTerm, int isPrefix,
                                  sqlite_int64 *piStartChild,
                                  sqlite_int64 *piEndChild){
  InteriorReader reader;

  assert( nData>1 );
  assert( *pData!='\0' );
  interiorReaderInit(pData, nData, &reader);

  /* Scan for the first child which could contain pTerm/nTerm. */
  while( !interiorReaderAtEnd(&reader) ){
    if( interiorReaderTermCmp(&reader, pTerm, nTerm, 0)>0 ) break;
    interiorReaderStep(&reader);
  }
  *piStartChild = interiorReaderCurrentBlockid(&reader);

  /* Keep scanning to find a term greater than our term, using prefix
  ** comparison if indicated.  If isPrefix is false, this will be the
  ** same blockid as the starting block.
  */
  while( !interiorReaderAtEnd(&reader) ){
    if( interiorReaderTermCmp(&reader, pTerm, nTerm, isPrefix)>0 ) break;
    interiorReaderStep(&reader);
  }
  *piEndChild = interiorReaderCurrentBlockid(&reader);

  interiorReaderDestroy(&reader);

  /* Children must ascend, and if !prefix, both must be the same. */
  assert( *piEndChild>=*piStartChild );
  assert( isPrefix || *piStartChild==*piEndChild );
}

/* Read block at iBlockid and pass it with other params to
** getChildrenContaining().
*/
static int loadAndGetChildrenContaining(
  fulltext_vtab *v,
  sqlite_int64 iBlockid,
  const char *pTerm, int nTerm, int isPrefix,
  sqlite_int64 *piStartChild, sqlite_int64 *piEndChild
){
  sqlite3_stmt *s = NULL;
  int rc;

  assert( iBlockid!=0 );
  assert( pTerm!=NULL );
  assert( nTerm!=0 );        /* TODO(shess) Why not allow this? */
  assert( piStartChild!=NULL );
  assert( piEndChild!=NULL );

  rc = sql_get_statement(v, BLOCK_SELECT_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_bind_int64(s, 1, iBlockid);
  if( rc!=SQLITE_OK ) return rc;

  rc = sqlite3_step(s);
  if( rc==SQLITE_DONE ) return SQLITE_ERROR;
  if( rc!=SQLITE_ROW ) return rc;

  getChildrenContaining(sqlite3_column_blob(s, 0), sqlite3_column_bytes(s, 0),
                        pTerm, nTerm, isPrefix, piStartChild, piEndChild);

  /* We expect only one row.  We must execute another sqlite3_step()
   * to complete the iteration; otherwise the table will remain
   * locked. */
  rc = sqlite3_step(s);
  if( rc==SQLITE_ROW ) return SQLITE_ERROR;
  if( rc!=SQLITE_DONE ) return rc;

  return SQLITE_OK;
}

/* Traverse the tree represented by pData[nData] looking for
** pTerm[nTerm], placing its doclist into *out.  This is internal to
** loadSegment() to make error-handling cleaner.
*/
static int loadSegmentInt(fulltext_vtab *v, const char *pData, int nData,
                          sqlite_int64 iLeavesEnd,
                          const char *pTerm, int nTerm, int isPrefix,
                          DataBuffer *out){
  /* Special case where root is a leaf. */
  if( *pData=='\0' ){
    return loadSegmentLeaf(v, pData, nData, pTerm, nTerm, isPrefix, out);
  }else{
    int rc;
    sqlite_int64 iStartChild, iEndChild;

    /* Process pData as an interior node, then loop down the tree
    ** until we find the set of leaf nodes to scan for the term.
    */
    getChildrenContaining(pData, nData, pTerm, nTerm, isPrefix,
                          &iStartChild, &iEndChild);
    while( iStartChild>iLeavesEnd ){
      sqlite_int64 iNextStart, iNextEnd;
      rc = loadAndGetChildrenContaining(v, iStartChild, pTerm, nTerm, isPrefix,
                                        &iNextStart, &iNextEnd);
      if( rc!=SQLITE_OK ) return rc;

      /* If we've branched, follow the end branch, too. */
      if( iStartChild!=iEndChild ){
        sqlite_int64 iDummy;
        rc = loadAndGetChildrenContaining(v, iEndChild, pTerm, nTerm, isPrefix,
                                          &iDummy, &iNextEnd);
        if( rc!=SQLITE_OK ) return rc;
      }

      assert( iNextStart<=iNextEnd );
      iStartChild = iNextStart;
      iEndChild = iNextEnd;
    }
    assert( iStartChild<=iLeavesEnd );
    assert( iEndChild<=iLeavesEnd );

    /* Scan through the leaf segments for doclists. */
    return loadSegmentLeaves(v, iStartChild, iEndChild,
                             pTerm, nTerm, isPrefix, out);
  }
}

/* Call loadSegmentInt() to collect the doclist for pTerm/nTerm, then
** merge its doclist over *out (any duplicate doclists read from the
** segment rooted at pData will overwrite those in *out).
*/
/* TODO(shess) Consider changing this to determine the depth of the
** leaves using either the first characters of interior nodes (when
** ==1, we're one level above the leaves), or the first character of
** the root (which will describe the height of the tree directly).
** Either feels somewhat tricky to me.
*/
/* TODO(shess) The current merge is likely to be slow for large
** doclists (though it should process from newest/smallest to
** oldest/largest, so it may not be that bad).  It might be useful to
** modify things to allow for N-way merging.  This could either be
** within a segment, with pairwise merges across segments, or across
** all segments at once.
*/
static int loadSegment(fulltext_vtab *v, const char *pData, int nData,
                       sqlite_int64 iLeavesEnd,
                       const char *pTerm, int nTerm, int isPrefix,
                       DataBuffer *out){
  DataBuffer result;
  int rc;

  assert( nData>1 );

  /* This code should never be called with buffered updates. */
  assert( v->nPendingData<0 );

  dataBufferInit(&result, 0);
  rc = loadSegmentInt(v, pData, nData, iLeavesEnd,
                      pTerm, nTerm, isPrefix, &result);
  if( rc==SQLITE_OK && result.nData>0 ){
    if( out->nData==0 ){
      DataBuffer tmp = *out;
      *out = result;
      result = tmp;
    }else{
      DataBuffer merged;
      DLReader readers[2];

      dlrInit(&readers[0], DL_DEFAULT, out->pData, out->nData);
      dlrInit(&readers[1], DL_DEFAULT, result.pData, result.nData);
      dataBufferInit(&merged, out->nData+result.nData);
      docListMerge(&merged, readers, 2);
      dataBufferDestroy(out);
      *out = merged;
      dlrDestroy(&readers[0]);
      dlrDestroy(&readers[1]);
    }
  }
  dataBufferDestroy(&result);
  return rc;
}

/* Scan the database and merge together the posting lists for the term
** into *out.
*/
static int termSelect(fulltext_vtab *v, int iColumn,
                      const char *pTerm, int nTerm, int isPrefix,
                      DocListType iType, DataBuffer *out){
  DataBuffer doclist;
  sqlite3_stmt *s;
  int rc = sql_get_statement(v, SEGDIR_SELECT_ALL_STMT, &s);
  if( rc!=SQLITE_OK ) return rc;

  /* This code should never be called with buffered updates. */
  assert( v->nPendingData<0 );

  dataBufferInit(&doclist, 0);

  /* Traverse the segments from oldest to newest so that newer doclist
  ** elements for given docids overwrite older elements.
  */
  while( (rc = sqlite3_step(s))==SQLITE_ROW ){
    const char *pData = sqlite3_column_blob(s, 2);
    const int nData = sqlite3_column_bytes(s, 2);
    const sqlite_int64 iLeavesEnd = sqlite3_column_int64(s, 1);
    rc = loadSegment(v, pData, nData, iLeavesEnd, pTerm, nTerm, isPrefix,
                     &doclist);
    if( rc!=SQLITE_OK ) goto err;
  }
  if( rc==SQLITE_DONE ){
    if( doclist.nData!=0 ){
      /* TODO(shess) The old term_select_all() code applied the column
      ** restrict as we merged segments, leading to smaller buffers.
      ** This is probably worthwhile to bring back, once the new storage
      ** system is checked in.
      */
      if( iColumn==v->nColumn) iColumn = -1;
      docListTrim(DL_DEFAULT, doclist.pData, doclist.nData,
                  iColumn, iType, out);
    }
    rc = SQLITE_OK;
  }

 err:
  dataBufferDestroy(&doclist);
  return rc;
}

/****************************************************************/
/* Used to hold hashtable data for sorting. */
typedef struct TermData {
  const char *pTerm;
  int nTerm;
  DLCollector *pCollector;
} TermData;

/* Orders TermData elements in strcmp fashion ( <0 for less-than, 0
** for equal, >0 for greater-than).
*/
static int termDataCmp(const void *av, const void *bv){
  const TermData *a = (const TermData *)av;
  const TermData *b = (const TermData *)bv;
  int n = a->nTerm<b->nTerm ? a->nTerm : b->nTerm;
  int c = memcmp(a->pTerm, b->pTerm, n);
  if( c!=0 ) return c;
  return a->nTerm-b->nTerm;
}

/* Order pTerms data by term, then write a new level 0 segment using
** LeafWriter.
*/
static int writeZeroSegment(fulltext_vtab *v, fts2Hash *pTerms){
  fts2HashElem *e;
  int idx, rc, i, n;
  TermData *pData;
  LeafWriter writer;
  DataBuffer dl;

  /* Determine the next index at level 0, merging as necessary. */
  rc = segdirNextIndex(v, 0, &idx);
  if( rc!=SQLITE_OK ) return rc;

  n = fts2HashCount(pTerms);
  pData = sqlite3_malloc(n*sizeof(TermData));

  for(i = 0, e = fts2HashFirst(pTerms); e; i++, e = fts2HashNext(e)){
    assert( i<n );
    pData[i].pTerm = fts2HashKey(e);
    pData[i].nTerm = fts2HashKeysize(e);
    pData[i].pCollector = fts2HashData(e);
  }
  assert( i==n );

  /* TODO(shess) Should we allow user-defined collation sequences,
  ** here?  I think we only need that once we support prefix searches.
  */
  if( n>1 ) qsort(pData, n, sizeof(*pData), termDataCmp);

  /* TODO(shess) Refactor so that we can write directly to the segment
  ** DataBuffer, as happens for segment merges.
  */
  leafWriterInit(0, idx, &writer);
  dataBufferInit(&dl, 0);
  for(i=0; i<n; i++){
    dataBufferReset(&dl);
    dlcAddDoclist(pData[i].pCollector, &dl);
    rc = leafWriterStep(v, &writer,
                        pData[i].pTerm, pData[i].nTerm, dl.pData, dl.nData);
    if( rc!=SQLITE_OK ) goto err;
  }
  rc = leafWriterFinalize(v, &writer);

 err:
  dataBufferDestroy(&dl);
  sqlite3_free(pData);
  leafWriterDestroy(&writer);
  return rc;
}

/* If pendingTerms has data, free it. */
static int clearPendingTerms(fulltext_vtab *v){
  if( v->nPendingData>=0 ){
    fts2HashElem *e;
    for(e=fts2HashFirst(&v->pendingTerms); e; e=fts2HashNext(e)){
      dlcDelete(fts2HashData(e));
    }
    fts2HashClear(&v->pendingTerms);
    v->nPendingData = -1;
  }
  return SQLITE_OK;
}

/* If pendingTerms has data, flush it to a level-zero segment, and
** free it.
*/
static int flushPendingTerms(fulltext_vtab *v){
  if( v->nPendingData>=0 ){
    int rc = writeZeroSegment(v, &v->pendingTerms);
    if( rc==SQLITE_OK ) clearPendingTerms(v);
    return rc;
  }
  return SQLITE_OK;
}

/* If pendingTerms is "too big", or docid is out of order, flush it.
** Regardless, be certain that pendingTerms is initialized for use.
*/
static int initPendingTerms(fulltext_vtab *v, sqlite_int64 iDocid){
  /* TODO(shess) Explore whether partially flushing the buffer on
  ** forced-flush would provide better performance.  I suspect that if
  ** we ordered the doclists by size and flushed the largest until the
  ** buffer was half empty, that would let the less frequent terms
  ** generate longer doclists.
  */
  if( iDocid<=v->iPrevDocid || v->nPendingData>kPendingThreshold ){
    int rc = flushPendingTerms(v);
    if( rc!=SQLITE_OK ) return rc;
  }
  if( v->nPendingData<0 ){
    fts2HashInit(&v->pendingTerms, FTS2_HASH_STRING, 1);
    v->nPendingData = 0;
  }
  v->iPrevDocid = iDocid;
  return SQLITE_OK;
}

/* This function implements the xUpdate callback; it is the top-level entry
 * point for inserting, deleting or updating a row in a full-text table. */
static int fulltextUpdate(sqlite3_vtab *pVtab, int nArg, sqlite3_value **ppArg,
                   sqlite_int64 *pRowid){
  fulltext_vtab *v = (fulltext_vtab *) pVtab;
  int rc;

  TRACE(("FTS2 Update %p\n", pVtab));

  if( nArg<2 ){
    rc = index_delete(v, sqlite3_value_int64(ppArg[0]));
    if( rc==SQLITE_OK ){
      /* If we just deleted the last row in the table, clear out the
      ** index data.
      */
      rc = content_exists(v);
      if( rc==SQLITE_ROW ){
        rc = SQLITE_OK;
      }else if( rc==SQLITE_DONE ){
        /* Clear the pending terms so we don't flush a useless level-0
        ** segment when the transaction closes.
        */
        rc = clearPendingTerms(v);
        if( rc==SQLITE_OK ){
          rc = segdir_delete_all(v);
        }
      }
    }
  } else if( sqlite3_value_type(ppArg[0]) != SQLITE_NULL ){
    /* An update:
     * ppArg[0] = old rowid
     * ppArg[1] = new rowid
     * ppArg[2..2+v->nColumn-1] = values
     * ppArg[2+v->nColumn] = value for magic column (we ignore this)
     */
    sqlite_int64 rowid = sqlite3_value_int64(ppArg[0]);
    if( sqlite3_value_type(ppArg[1]) != SQLITE_INTEGER ||
      sqlite3_value_int64(ppArg[1]) != rowid ){
      rc = SQLITE_ERROR;  /* we don't allow changing the rowid */
    } else {
      assert( nArg==2+v->nColumn+1);
      rc = index_update(v, rowid, &ppArg[2]);
    }
  } else {
    /* An insert:
     * ppArg[1] = requested rowid
     * ppArg[2..2+v->nColumn-1] = values
     * ppArg[2+v->nColumn] = value for magic column (we ignore this)
     */
    assert( nArg==2+v->nColumn+1);
    rc = index_insert(v, ppArg[1], &ppArg[2], pRowid);
  }

  return rc;
}

static int fulltextSync(sqlite3_vtab *pVtab){
  TRACE(("FTS2 xSync()\n"));
  return flushPendingTerms((fulltext_vtab *)pVtab);
}

static int fulltextBegin(sqlite3_vtab *pVtab){
  fulltext_vtab *v = (fulltext_vtab *) pVtab;
  TRACE(("FTS2 xBegin()\n"));

  /* Any buffered updates should have been cleared by the previous
  ** transaction.
  */
  assert( v->nPendingData<0 );
  return clearPendingTerms(v);
}

static int fulltextCommit(sqlite3_vtab *pVtab){
  fulltext_vtab *v = (fulltext_vtab *) pVtab;
  TRACE(("FTS2 xCommit()\n"));

  /* Buffered updates should have been cleared by fulltextSync(). */
  assert( v->nPendingData<0 );
  return clearPendingTerms(v);
}

static int fulltextRollback(sqlite3_vtab *pVtab){
  TRACE(("FTS2 xRollback()\n"));
  return clearPendingTerms((fulltext_vtab *)pVtab);
}

/*
** Implementation of the snippet() function for FTS2
*/
static void snippetFunc(
  sqlite3_context *pContext,
  int argc,
  sqlite3_value **argv
){
  fulltext_cursor *pCursor;
  if( argc<1 ) return;
  if( sqlite3_value_type(argv[0])!=SQLITE_BLOB ||
      sqlite3_value_bytes(argv[0])!=sizeof(pCursor) ){
    sqlite3_result_error(pContext, "illegal first argument to html_snippet",-1);
  }else{
    const char *zStart = "<b>";
    const char *zEnd = "</b>";
    const char *zEllipsis = "<b>...</b>";
    memcpy(&pCursor, sqlite3_value_blob(argv[0]), sizeof(pCursor));
    if( argc>=2 ){
      zStart = (const char*)sqlite3_value_text(argv[1]);
      if( argc>=3 ){
        zEnd = (const char*)sqlite3_value_text(argv[2]);
        if( argc>=4 ){
          zEllipsis = (const char*)sqlite3_value_text(argv[3]);
        }
      }
    }
    snippetAllOffsets(pCursor);
    snippetText(pCursor, zStart, zEnd, zEllipsis);
    sqlite3_result_text(pContext, pCursor->snippet.zSnippet,
                        pCursor->snippet.nSnippet, SQLITE_STATIC);
  }
}

/*
** Implementation of the offsets() function for FTS2
*/
static void snippetOffsetsFunc(
  sqlite3_context *pContext,
  int argc,
  sqlite3_value **argv
){
  fulltext_cursor *pCursor;
  if( argc<1 ) return;
  if( sqlite3_value_type(argv[0])!=SQLITE_BLOB ||
      sqlite3_value_bytes(argv[0])!=sizeof(pCursor) ){
    sqlite3_result_error(pContext, "illegal first argument to offsets",-1);
  }else{
    memcpy(&pCursor, sqlite3_value_blob(argv[0]), sizeof(pCursor));
    snippetAllOffsets(pCursor);
    snippetOffsetText(&pCursor->snippet);
    sqlite3_result_text(pContext,
                        pCursor->snippet.zOffset, pCursor->snippet.nOffset,
                        SQLITE_STATIC);
  }
}

/* OptLeavesReader is nearly identical to LeavesReader, except that
** where LeavesReader is geared towards the merging of complete
** segment levels (with exactly MERGE_COUNT segments), OptLeavesReader
** is geared towards implementation of the optimize() function, and
** can merge all segments simultaneously.  This version may be
** somewhat less efficient than LeavesReader because it merges into an
** accumulator rather than doing an N-way merge, but since segment
** size grows exponentially (so segment count logrithmically) this is
** probably not an immediate problem.
*/
/* TODO(shess): Prove that assertion, or extend the merge code to
** merge tree fashion (like the prefix-searching code does).
*/
/* TODO(shess): OptLeavesReader and LeavesReader could probably be
** merged with little or no loss of performance for LeavesReader.  The
** merged code would need to handle >MERGE_COUNT segments, and would
** also need to be able to optionally optimize away deletes.
*/
typedef struct OptLeavesReader {
  /* Segment number, to order readers by age. */
  int segment;
  LeavesReader reader;
} OptLeavesReader;

static int optLeavesReaderAtEnd(OptLeavesReader *pReader){
  return leavesReaderAtEnd(&pReader->reader);
}
static int optLeavesReaderTermBytes(OptLeavesReader *pReader){
  return leavesReaderTermBytes(&pReader->reader);
}
static const char *optLeavesReaderData(OptLeavesReader *pReader){
  return leavesReaderData(&pReader->reader);
}
static int optLeavesReaderDataBytes(OptLeavesReader *pReader){
  return leavesReaderDataBytes(&pReader->reader);
}
static const char *optLeavesReaderTerm(OptLeavesReader *pReader){
  return leavesReaderTerm(&pReader->reader);
}
static int optLeavesReaderStep(fulltext_vtab *v, OptLeavesReader *pReader){
  return leavesReaderStep(v, &pReader->reader);
}
static int optLeavesReaderTermCmp(OptLeavesReader *lr1, OptLeavesReader *lr2){
  return leavesReaderTermCmp(&lr1->reader, &lr2->reader);
}
/* Order by term ascending, segment ascending (oldest to newest), with
** exhausted readers to the end.
*/
static int optLeavesReaderCmp(OptLeavesReader *lr1, OptLeavesReader *lr2){
  int c = optLeavesReaderTermCmp(lr1, lr2);
  if( c!=0 ) return c;
  return lr1->segment-lr2->segment;
}
/* Bubble pLr[0] to appropriate place in pLr[1..nLr-1].  Assumes that
** pLr[1..nLr-1] is already sorted.
*/
static void optLeavesReaderReorder(OptLeavesReader *pLr, int nLr){
  while( nLr>1 && optLeavesReaderCmp(pLr, pLr+1)>0 ){
    OptLeavesReader tmp = pLr[0];
    pLr[0] = pLr[1];
    pLr[1] = tmp;
    nLr--;
    pLr++;
  }
}

/* optimize() helper function.  Put the readers in order and iterate
** through them, merging doclists for matching terms into pWriter.
** Returns SQLITE_OK on success, or the SQLite error code which
** prevented success.
*/
static int optimizeInternal(fulltext_vtab *v,
                            OptLeavesReader *readers, int nReaders,
                            LeafWriter *pWriter){
  int i, rc = SQLITE_OK;
  DataBuffer doclist, merged, tmp;

  /* Order the readers. */
  i = nReaders;
  while( i-- > 0 ){
    optLeavesReaderReorder(&readers[i], nReaders-i);
  }

  dataBufferInit(&doclist, LEAF_MAX);
  dataBufferInit(&merged, LEAF_MAX);

  /* Exhausted readers bubble to the end, so when the first reader is
  ** at eof, all are at eof.
  */
  while( !optLeavesReaderAtEnd(&readers[0]) ){

    /* Figure out how many readers share the next term. */
    for(i=1; i<nReaders && !optLeavesReaderAtEnd(&readers[i]); i++){
      if( 0!=optLeavesReaderTermCmp(&readers[0], &readers[i]) ) break;
    }

    /* Special-case for no merge. */
    if( i==1 ){
      /* Trim deletions from the doclist. */
      dataBufferReset(&merged);
      docListTrim(DL_DEFAULT,
                  optLeavesReaderData(&readers[0]),
                  optLeavesReaderDataBytes(&readers[0]),
                  -1, DL_DEFAULT, &merged);
    }else{
      DLReader dlReaders[MERGE_COUNT];
      int iReader, nReaders;

      /* Prime the pipeline with the first reader's doclist.  After
      ** one pass index 0 will reference the accumulated doclist.
      */
      dlrInit(&dlReaders[0], DL_DEFAULT,
              optLeavesReaderData(&readers[0]),
              optLeavesReaderDataBytes(&readers[0]));
      iReader = 1;

      assert( iReader<i );  /* Must execute the loop at least once. */
      while( iReader<i ){
        /* Merge 16 inputs per pass. */
        for( nReaders=1; iReader<i && nReaders<MERGE_COUNT;
             iReader++, nReaders++ ){
          dlrInit(&dlReaders[nReaders], DL_DEFAULT,
                  optLeavesReaderData(&readers[iReader]),
                  optLeavesReaderDataBytes(&readers[iReader]));
        }

        /* Merge doclists and swap result into accumulator. */
        dataBufferReset(&merged);
        docListMerge(&merged, dlReaders, nReaders);
        tmp = merged;
        merged = doclist;
        doclist = tmp;

        while( nReaders-- > 0 ){
          dlrDestroy(&dlReaders[nReaders]);
        }

        /* Accumulated doclist to reader 0 for next pass. */
        dlrInit(&dlReaders[0], DL_DEFAULT, doclist.pData, doclist.nData);
      }

      /* Destroy reader that was left in the pipeline. */
      dlrDestroy(&dlReaders[0]);

      /* Trim deletions from the doclist. */
      dataBufferReset(&merged);
      docListTrim(DL_DEFAULT, doclist.pData, doclist.nData,
                  -1, DL_DEFAULT, &merged);
    }

    /* Only pass doclists with hits (skip if all hits deleted). */
    if( merged.nData>0 ){
      rc = leafWriterStep(v, pWriter,
                          optLeavesReaderTerm(&readers[0]),
                          optLeavesReaderTermBytes(&readers[0]),
                          merged.pData, merged.nData);
      if( rc!=SQLITE_OK ) goto err;
    }

    /* Step merged readers to next term and reorder. */
    while( i-- > 0 ){
      rc = optLeavesReaderStep(v, &readers[i]);
      if( rc!=SQLITE_OK ) goto err;

      optLeavesReaderReorder(&readers[i], nReaders-i);
    }
  }

 err:
  dataBufferDestroy(&doclist);
  dataBufferDestroy(&merged);
  return rc;
}

/* Implement optimize() function for FTS3.  optimize(t) merges all
** segments in the fts index into a single segment.  't' is the magic
** table-named column.
*/
static void optimizeFunc(sqlite3_context *pContext,
                         int argc, sqlite3_value **argv){
  fulltext_cursor *pCursor;
  if( argc>1 ){
    sqlite3_result_error(pContext, "excess arguments to optimize()",-1);
  }else if( sqlite3_value_type(argv[0])!=SQLITE_BLOB ||
            sqlite3_value_bytes(argv[0])!=sizeof(pCursor) ){
    sqlite3_result_error(pContext, "illegal first argument to optimize",-1);
  }else{
    fulltext_vtab *v;
    int i, rc, iMaxLevel;
    OptLeavesReader *readers;
    int nReaders;
    LeafWriter writer;
    sqlite3_stmt *s;

    memcpy(&pCursor, sqlite3_value_blob(argv[0]), sizeof(pCursor));
    v = cursor_vtab(pCursor);

    /* Flush any buffered updates before optimizing. */
    rc = flushPendingTerms(v);
    if( rc!=SQLITE_OK ) goto err;

    rc = segdir_count(v, &nReaders, &iMaxLevel);
    if( rc!=SQLITE_OK ) goto err;
    if( nReaders==0 || nReaders==1 ){
      sqlite3_result_text(pContext, "Index already optimal", -1,
                          SQLITE_STATIC);
      return;
    }

    rc = sql_get_statement(v, SEGDIR_SELECT_ALL_STMT, &s);
    if( rc!=SQLITE_OK ) goto err;

    readers = sqlite3_malloc(nReaders*sizeof(readers[0]));
    if( readers==NULL ) goto err;

    /* Note that there will already be a segment at this position
    ** until we call segdir_delete() on iMaxLevel.
    */
    leafWriterInit(iMaxLevel, 0, &writer);

    i = 0;
    while( (rc = sqlite3_step(s))==SQLITE_ROW ){
      sqlite_int64 iStart = sqlite3_column_int64(s, 0);
      sqlite_int64 iEnd = sqlite3_column_int64(s, 1);
      const char *pRootData = sqlite3_column_blob(s, 2);
      int nRootData = sqlite3_column_bytes(s, 2);

      assert( i<nReaders );
      rc = leavesReaderInit(v, -1, iStart, iEnd, pRootData, nRootData,
                            &readers[i].reader);
      if( rc!=SQLITE_OK ) break;

      readers[i].segment = i;
      i++;
    }

    /* If we managed to successfully read them all, optimize them. */
    if( rc==SQLITE_DONE ){
      assert( i==nReaders );
      rc = optimizeInternal(v, readers, nReaders, &writer);
    }

    while( i-- > 0 ){
      leavesReaderDestroy(&readers[i].reader);
    }
    sqlite3_free(readers);

    /* If we've successfully gotten to here, delete the old segments
    ** and flush the interior structure of the new segment.
    */
    if( rc==SQLITE_OK ){
      for( i=0; i<=iMaxLevel; i++ ){
        rc = segdir_delete(v, i);
        if( rc!=SQLITE_OK ) break;
      }

      if( rc==SQLITE_OK ) rc = leafWriterFinalize(v, &writer);
    }

    leafWriterDestroy(&writer);

    if( rc!=SQLITE_OK ) goto err;

    sqlite3_result_text(pContext, "Index optimized", -1, SQLITE_STATIC);
    return;

    /* TODO(shess): Error-handling needs to be improved along the
    ** lines of the dump_ functions.
    */
 err:
    {
      char buf[512];
      sqlite3_snprintf(sizeof(buf), buf, "Error in optimize: %s",
                       sqlite3_errmsg(sqlite3_context_db_handle(pContext)));
      sqlite3_result_error(pContext, buf, -1);
    }
  }
}

#ifdef SQLITE_TEST
/* Generate an error of the form "<prefix>: <msg>".  If msg is NULL,
** pull the error from the context's db handle.
*/
static void generateError(sqlite3_context *pContext,
                          const char *prefix, const char *msg){
  char buf[512];
  if( msg==NULL ) msg = sqlite3_errmsg(sqlite3_context_db_handle(pContext));
  sqlite3_snprintf(sizeof(buf), buf, "%s: %s", prefix, msg);
  sqlite3_result_error(pContext, buf, -1);
}

/* Helper function to collect the set of terms in the segment into
** pTerms.  The segment is defined by the leaf nodes between
** iStartBlockid and iEndBlockid, inclusive, or by the contents of
** pRootData if iStartBlockid is 0 (in which case the entire segment
** fit in a leaf).
*/
static int collectSegmentTerms(fulltext_vtab *v, sqlite3_stmt *s,
                               fts2Hash *pTerms){
  const sqlite_int64 iStartBlockid = sqlite3_column_int64(s, 0);
  const sqlite_int64 iEndBlockid = sqlite3_column_int64(s, 1);
  const char *pRootData = sqlite3_column_blob(s, 2);
  const int nRootData = sqlite3_column_bytes(s, 2);
  LeavesReader reader;
  int rc = leavesReaderInit(v, 0, iStartBlockid, iEndBlockid,
                            pRootData, nRootData, &reader);
  if( rc!=SQLITE_OK ) return rc;

  while( rc==SQLITE_OK && !leavesReaderAtEnd(&reader) ){
    const char *pTerm = leavesReaderTerm(&reader);
    const int nTerm = leavesReaderTermBytes(&reader);
    void *oldValue = sqlite3Fts2HashFind(pTerms, pTerm, nTerm);
    void *newValue = (void *)((char *)oldValue+1);

    /* From the comment before sqlite3Fts2HashInsert in fts2_hash.c,
    ** the data value passed is returned in case of malloc failure.
    */
    if( newValue==sqlite3Fts2HashInsert(pTerms, pTerm, nTerm, newValue) ){
      rc = SQLITE_NOMEM;
    }else{
      rc = leavesReaderStep(v, &reader);
    }
  }

  leavesReaderDestroy(&reader);
  return rc;
}

/* Helper function to build the result string for dump_terms(). */
static int generateTermsResult(sqlite3_context *pContext, fts2Hash *pTerms){
  int iTerm, nTerms, nResultBytes, iByte;
  char *result;
  TermData *pData;
  fts2HashElem *e;

  /* Iterate pTerms to generate an array of terms in pData for
  ** sorting.
  */
  nTerms = fts2HashCount(pTerms);
  assert( nTerms>0 );
  pData = sqlite3_malloc(nTerms*sizeof(TermData));
  if( pData==NULL ) return SQLITE_NOMEM;

  nResultBytes = 0;
  for(iTerm = 0, e = fts2HashFirst(pTerms); e; iTerm++, e = fts2HashNext(e)){
    nResultBytes += fts2HashKeysize(e)+1;   /* Term plus trailing space */
    assert( iTerm<nTerms );
    pData[iTerm].pTerm = fts2HashKey(e);
    pData[iTerm].nTerm = fts2HashKeysize(e);
    pData[iTerm].pCollector = fts2HashData(e);  /* unused */
  }
  assert( iTerm==nTerms );

  assert( nResultBytes>0 );   /* nTerms>0, nResultsBytes must be, too. */
  result = sqlite3_malloc(nResultBytes);
  if( result==NULL ){
    sqlite3_free(pData);
    return SQLITE_NOMEM;
  }

  if( nTerms>1 ) qsort(pData, nTerms, sizeof(*pData), termDataCmp);

  /* Read the terms in order to build the result. */
  iByte = 0;
  for(iTerm=0; iTerm<nTerms; ++iTerm){
    memcpy(result+iByte, pData[iTerm].pTerm, pData[iTerm].nTerm);
    iByte += pData[iTerm].nTerm;
    result[iByte++] = ' ';
  }
  assert( iByte==nResultBytes );
  assert( result[nResultBytes-1]==' ' );
  result[nResultBytes-1] = '\0';

  /* Passes away ownership of result. */
  sqlite3_result_text(pContext, result, nResultBytes-1, sqlite3_free);
  sqlite3_free(pData);
  return SQLITE_OK;
}

/* Implements dump_terms() for use in inspecting the fts2 index from
** tests.  TEXT result containing the ordered list of terms joined by
** spaces.  dump_terms(t, level, idx) dumps the terms for the segment
** specified by level, idx (in %_segdir), while dump_terms(t) dumps
** all terms in the index.  In both cases t is the fts table's magic
** table-named column.
*/
static void dumpTermsFunc(
  sqlite3_context *pContext,
  int argc, sqlite3_value **argv
){
  fulltext_cursor *pCursor;
  if( argc!=3 && argc!=1 ){
    generateError(pContext, "dump_terms", "incorrect arguments");
  }else if( sqlite3_value_type(argv[0])!=SQLITE_BLOB ||
            sqlite3_value_bytes(argv[0])!=sizeof(pCursor) ){
    generateError(pContext, "dump_terms", "illegal first argument");
  }else{
    fulltext_vtab *v;
    fts2Hash terms;
    sqlite3_stmt *s = NULL;
    int rc;

    memcpy(&pCursor, sqlite3_value_blob(argv[0]), sizeof(pCursor));
    v = cursor_vtab(pCursor);

    /* If passed only the cursor column, get all segments.  Otherwise
    ** get the segment described by the following two arguments.
    */
    if( argc==1 ){
      rc = sql_get_statement(v, SEGDIR_SELECT_ALL_STMT, &s);
    }else{
      rc = sql_get_statement(v, SEGDIR_SELECT_SEGMENT_STMT, &s);
      if( rc==SQLITE_OK ){
        rc = sqlite3_bind_int(s, 1, sqlite3_value_int(argv[1]));
        if( rc==SQLITE_OK ){
          rc = sqlite3_bind_int(s, 2, sqlite3_value_int(argv[2]));
        }
      }
    }

    if( rc!=SQLITE_OK ){
      generateError(pContext, "dump_terms", NULL);
      return;
    }

    /* Collect the terms for each segment. */
    sqlite3Fts2HashInit(&terms, FTS2_HASH_STRING, 1);
    while( (rc = sqlite3_step(s))==SQLITE_ROW ){
      rc = collectSegmentTerms(v, s, &terms);
      if( rc!=SQLITE_OK ) break;
    }

    if( rc!=SQLITE_DONE ){
      sqlite3_reset(s);
      generateError(pContext, "dump_terms", NULL);
    }else{
      const int nTerms = fts2HashCount(&terms);
      if( nTerms>0 ){
        rc = generateTermsResult(pContext, &terms);
        if( rc==SQLITE_NOMEM ){
          generateError(pContext, "dump_terms", "out of memory");
        }else{
          assert( rc==SQLITE_OK );
        }
      }else if( argc==3 ){
        /* The specific segment asked for could not be found. */
        generateError(pContext, "dump_terms", "segment not found");
      }else{
        /* No segments found. */
        /* TODO(shess): It should be impossible to reach this.  This
        ** case can only happen for an empty table, in which case
        ** SQLite has no rows to call this function on.
        */
        sqlite3_result_null(pContext);
      }
    }
    sqlite3Fts2HashClear(&terms);
  }
}

/* Expand the DL_DEFAULT doclist in pData into a text result in
** pContext.
*/
static void createDoclistResult(sqlite3_context *pContext,
                                const char *pData, int nData){
  DataBuffer dump;
  DLReader dlReader;

  assert( pData!=NULL && nData>0 );

  dataBufferInit(&dump, 0);
  dlrInit(&dlReader, DL_DEFAULT, pData, nData);
  for( ; !dlrAtEnd(&dlReader); dlrStep(&dlReader) ){
    char buf[256];
    PLReader plReader;

    plrInit(&plReader, &dlReader);
    if( DL_DEFAULT==DL_DOCIDS || plrAtEnd(&plReader) ){
      sqlite3_snprintf(sizeof(buf), buf, "[%lld] ", dlrDocid(&dlReader));
      dataBufferAppend(&dump, buf, strlen(buf));
    }else{
      int iColumn = plrColumn(&plReader);

      sqlite3_snprintf(sizeof(buf), buf, "[%lld %d[",
                       dlrDocid(&dlReader), iColumn);
      dataBufferAppend(&dump, buf, strlen(buf));

      for( ; !plrAtEnd(&plReader); plrStep(&plReader) ){
        if( plrColumn(&plReader)!=iColumn ){
          iColumn = plrColumn(&plReader);
          sqlite3_snprintf(sizeof(buf), buf, "] %d[", iColumn);
          assert( dump.nData>0 );
          dump.nData--;                     /* Overwrite trailing space. */
          assert( dump.pData[dump.nData]==' ');
          dataBufferAppend(&dump, buf, strlen(buf));
        }
        if( DL_DEFAULT==DL_POSITIONS_OFFSETS ){
          sqlite3_snprintf(sizeof(buf), buf, "%d,%d,%d ",
                           plrPosition(&plReader),
                           plrStartOffset(&plReader), plrEndOffset(&plReader));
        }else if( DL_DEFAULT==DL_POSITIONS ){
          sqlite3_snprintf(sizeof(buf), buf, "%d ", plrPosition(&plReader));
        }else{
          assert( NULL=="Unhandled DL_DEFAULT value");
        }
        dataBufferAppend(&dump, buf, strlen(buf));
      }
      plrDestroy(&plReader);

      assert( dump.nData>0 );
      dump.nData--;                     /* Overwrite trailing space. */
      assert( dump.pData[dump.nData]==' ');
      dataBufferAppend(&dump, "]] ", 3);
    }
  }
  dlrDestroy(&dlReader);

  assert( dump.nData>0 );
  dump.nData--;                     /* Overwrite trailing space. */
  assert( dump.pData[dump.nData]==' ');
  dump.pData[dump.nData] = '\0';
  assert( dump.nData>0 );

  /* Passes ownership of dump's buffer to pContext. */
  sqlite3_result_text(pContext, dump.pData, dump.nData, sqlite3_free);
  dump.pData = NULL;
  dump.nData = dump.nCapacity = 0;
}

/* Implements dump_doclist() for use in inspecting the fts2 index from
** tests.  TEXT result containing a string representation of the
** doclist for the indicated term.  dump_doclist(t, term, level, idx)
** dumps the doclist for term from the segment specified by level, idx
** (in %_segdir), while dump_doclist(t, term) dumps the logical
** doclist for the term across all segments.  The per-segment doclist
** can contain deletions, while the full-index doclist will not
** (deletions are omitted).
**
** Result formats differ with the setting of DL_DEFAULTS.  Examples:
**
** DL_DOCIDS: [1] [3] [7]
** DL_POSITIONS: [1 0[0 4] 1[17]] [3 1[5]]
** DL_POSITIONS_OFFSETS: [1 0[0,0,3 4,23,26] 1[17,102,105]] [3 1[5,20,23]]
**
** In each case the number after the outer '[' is the docid.  In the
** latter two cases, the number before the inner '[' is the column
** associated with the values within.  For DL_POSITIONS the numbers
** within are the positions, for DL_POSITIONS_OFFSETS they are the
** position, the start offset, and the end offset.
*/
static void dumpDoclistFunc(
  sqlite3_context *pContext,
  int argc, sqlite3_value **argv
){
  fulltext_cursor *pCursor;
  if( argc!=2 && argc!=4 ){
    generateError(pContext, "dump_doclist", "incorrect arguments");
  }else if( sqlite3_value_type(argv[0])!=SQLITE_BLOB ||
            sqlite3_value_bytes(argv[0])!=sizeof(pCursor) ){
    generateError(pContext, "dump_doclist", "illegal first argument");
  }else if( sqlite3_value_text(argv[1])==NULL ||
            sqlite3_value_text(argv[1])[0]=='\0' ){
    generateError(pContext, "dump_doclist", "empty second argument");
  }else{
    const char *pTerm = (const char *)sqlite3_value_text(argv[1]);
    const int nTerm = strlen(pTerm);
    fulltext_vtab *v;
    int rc;
    DataBuffer doclist;

    memcpy(&pCursor, sqlite3_value_blob(argv[0]), sizeof(pCursor));
    v = cursor_vtab(pCursor);

    dataBufferInit(&doclist, 0);

    /* termSelect() yields the same logical doclist that queries are
    ** run against.
    */
    if( argc==2 ){
      rc = termSelect(v, v->nColumn, pTerm, nTerm, 0, DL_DEFAULT, &doclist);
    }else{
      sqlite3_stmt *s = NULL;

      /* Get our specific segment's information. */
      rc = sql_get_statement(v, SEGDIR_SELECT_SEGMENT_STMT, &s);
      if( rc==SQLITE_OK ){
        rc = sqlite3_bind_int(s, 1, sqlite3_value_int(argv[2]));
        if( rc==SQLITE_OK ){
          rc = sqlite3_bind_int(s, 2, sqlite3_value_int(argv[3]));
        }
      }

      if( rc==SQLITE_OK ){
        rc = sqlite3_step(s);

        if( rc==SQLITE_DONE ){
          dataBufferDestroy(&doclist);
          generateError(pContext, "dump_doclist", "segment not found");
          return;
        }

        /* Found a segment, load it into doclist. */
        if( rc==SQLITE_ROW ){
          const sqlite_int64 iLeavesEnd = sqlite3_column_int64(s, 1);
          const char *pData = sqlite3_column_blob(s, 2);
          const int nData = sqlite3_column_bytes(s, 2);

          /* loadSegment() is used by termSelect() to load each
          ** segment's data.
          */
          rc = loadSegment(v, pData, nData, iLeavesEnd, pTerm, nTerm, 0,
                           &doclist);
          if( rc==SQLITE_OK ){
            rc = sqlite3_step(s);

            /* Should not have more than one matching segment. */
            if( rc!=SQLITE_DONE ){
              sqlite3_reset(s);
              dataBufferDestroy(&doclist);
              generateError(pContext, "dump_doclist", "invalid segdir");
              return;
            }
            rc = SQLITE_OK;
          }
        }
      }

      sqlite3_reset(s);
    }

    if( rc==SQLITE_OK ){
      if( doclist.nData>0 ){
        createDoclistResult(pContext, doclist.pData, doclist.nData);
      }else{
        /* TODO(shess): This can happen if the term is not present, or
        ** if all instances of the term have been deleted and this is
        ** an all-index dump.  It may be interesting to distinguish
        ** these cases.
        */
        sqlite3_result_text(pContext, "", 0, SQLITE_STATIC);
      }
    }else if( rc==SQLITE_NOMEM ){
      /* Handle out-of-memory cases specially because if they are
      ** generated in fts2 code they may not be reflected in the db
      ** handle.
      */
      /* TODO(shess): Handle this more comprehensively.
      ** sqlite3ErrStr() has what I need, but is internal.
      */
      generateError(pContext, "dump_doclist", "out of memory");
    }else{
      generateError(pContext, "dump_doclist", NULL);
    }

    dataBufferDestroy(&doclist);
  }
}
#endif

/*
** This routine implements the xFindFunction method for the FTS2
** virtual table.
*/
static int fulltextFindFunction(
  sqlite3_vtab *pVtab,
  int nArg,
  const char *zName,
  void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
  void **ppArg
){
  if( strcmp(zName,"snippet")==0 ){
    *pxFunc = snippetFunc;
    return 1;
  }else if( strcmp(zName,"offsets")==0 ){
    *pxFunc = snippetOffsetsFunc;
    return 1;
  }else if( strcmp(zName,"optimize")==0 ){
    *pxFunc = optimizeFunc;
    return 1;
#ifdef SQLITE_TEST
    /* NOTE(shess): These functions are present only for testing
    ** purposes.  No particular effort is made to optimize their
    ** execution or how they build their results.
    */
  }else if( strcmp(zName,"dump_terms")==0 ){
    /* fprintf(stderr, "Found dump_terms\n"); */
    *pxFunc = dumpTermsFunc;
    return 1;
  }else if( strcmp(zName,"dump_doclist")==0 ){
    /* fprintf(stderr, "Found dump_doclist\n"); */
    *pxFunc = dumpDoclistFunc;
    return 1;
#endif
  }
  return 0;
}

/*
** Rename an fts2 table.
*/
static int fulltextRename(
  sqlite3_vtab *pVtab,
  const char *zName
){
  fulltext_vtab *p = (fulltext_vtab *)pVtab;
  int rc = SQLITE_NOMEM;
  char *zSql = sqlite3_mprintf(
    "ALTER TABLE %Q.'%q_content'  RENAME TO '%q_content';"
    "ALTER TABLE %Q.'%q_segments' RENAME TO '%q_segments';"
    "ALTER TABLE %Q.'%q_segdir'   RENAME TO '%q_segdir';"
    , p->zDb, p->zName, zName 
    , p->zDb, p->zName, zName 
    , p->zDb, p->zName, zName
  );
  if( zSql ){
    rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
    sqlite3_free(zSql);
  }
  return rc;
}

static const sqlite3_module fts2Module = {
  /* iVersion      */ 0,
  /* xCreate       */ fulltextCreate,
  /* xConnect      */ fulltextConnect,
  /* xBestIndex    */ fulltextBestIndex,
  /* xDisconnect   */ fulltextDisconnect,
  /* xDestroy      */ fulltextDestroy,
  /* xOpen         */ fulltextOpen,
  /* xClose        */ fulltextClose,
  /* xFilter       */ fulltextFilter,
  /* xNext         */ fulltextNext,
  /* xEof          */ fulltextEof,
  /* xColumn       */ fulltextColumn,
  /* xRowid        */ fulltextRowid,
  /* xUpdate       */ fulltextUpdate,
  /* xBegin        */ fulltextBegin,
  /* xSync         */ fulltextSync,
  /* xCommit       */ fulltextCommit,
  /* xRollback     */ fulltextRollback,
  /* xFindFunction */ fulltextFindFunction,
  /* xRename */       fulltextRename,
};

static void hashDestroy(void *p){
  fts2Hash *pHash = (fts2Hash *)p;
  sqlite3Fts2HashClear(pHash);
  sqlite3_free(pHash);
}

/*
** The fts2 built-in tokenizers - "simple" and "porter" - are implemented
** in files fts2_tokenizer1.c and fts2_porter.c respectively. The following
** two forward declarations are for functions declared in these files
** used to retrieve the respective implementations.
**
** Calling sqlite3Fts2SimpleTokenizerModule() sets the value pointed
** to by the argument to point a the "simple" tokenizer implementation.
** Function ...PorterTokenizerModule() sets *pModule to point to the
** porter tokenizer/stemmer implementation.
*/
void sqlite3Fts2SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule);
void sqlite3Fts2PorterTokenizerModule(sqlite3_tokenizer_module const**ppModule);
void sqlite3Fts2IcuTokenizerModule(sqlite3_tokenizer_module const**ppModule);

int sqlite3Fts2InitHashTable(sqlite3 *, fts2Hash *, const char *);

/*
** Initialize the fts2 extension. If this extension is built as part
** of the sqlite library, then this function is called directly by
** SQLite. If fts2 is built as a dynamically loadable extension, this
** function is called by the sqlite3_extension_init() entry point.
*/
int sqlite3Fts2Init(sqlite3 *db){
  int rc = SQLITE_OK;
  fts2Hash *pHash = 0;
  const sqlite3_tokenizer_module *pSimple = 0;
  const sqlite3_tokenizer_module *pPorter = 0;
  const sqlite3_tokenizer_module *pIcu = 0;

  sqlite3Fts2SimpleTokenizerModule(&pSimple);
  sqlite3Fts2PorterTokenizerModule(&pPorter);
#ifdef SQLITE_ENABLE_ICU
  sqlite3Fts2IcuTokenizerModule(&pIcu);
#endif

  /* Allocate and initialize the hash-table used to store tokenizers. */
  pHash = sqlite3_malloc(sizeof(fts2Hash));
  if( !pHash ){
    rc = SQLITE_NOMEM;
  }else{
    sqlite3Fts2HashInit(pHash, FTS2_HASH_STRING, 1);
  }

  /* Load the built-in tokenizers into the hash table */
  if( rc==SQLITE_OK ){
    if( sqlite3Fts2HashInsert(pHash, "simple", 7, (void *)pSimple)
     || sqlite3Fts2HashInsert(pHash, "porter", 7, (void *)pPorter) 
     || (pIcu && sqlite3Fts2HashInsert(pHash, "icu", 4, (void *)pIcu))
    ){
      rc = SQLITE_NOMEM;
    }
  }

  /* Create the virtual table wrapper around the hash-table and overload 
  ** the two scalar functions. If this is successful, register the
  ** module with sqlite.
  */
  if( SQLITE_OK==rc 
   && SQLITE_OK==(rc = sqlite3Fts2InitHashTable(db, pHash, "fts2_tokenizer"))
   && SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1))
   && SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", -1))
   && SQLITE_OK==(rc = sqlite3_overload_function(db, "optimize", -1))
#ifdef SQLITE_TEST
   && SQLITE_OK==(rc = sqlite3_overload_function(db, "dump_terms", -1))
   && SQLITE_OK==(rc = sqlite3_overload_function(db, "dump_doclist", -1))
#endif
  ){
    return sqlite3_create_module_v2(
        db, "fts2", &fts2Module, (void *)pHash, hashDestroy
    );
  }

  /* An error has occurred. Delete the hash table and return the error code. */
  assert( rc!=SQLITE_OK );
  if( pHash ){
    sqlite3Fts2HashClear(pHash);
    sqlite3_free(pHash);
  }
  return rc;
}

#if !SQLITE_CORE
#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_fts2_init(
  sqlite3 *db, 
  char **pzErrMsg,
  const sqlite3_api_routines *pApi
){
  SQLITE_EXTENSION_INIT2(pApi)
  return sqlite3Fts2Init(db);
}
#endif

#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) */

Deleted ext/fts2/fts2.h.

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


























-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
** 2006 Oct 10
**
** 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 header file is used by programs that want to link against the
** FTS2 library.  All it does is declare the sqlite3Fts2Init() interface.
*/
#include "sqlite3.h"

#ifdef __cplusplus
extern "C" {
#endif  /* __cplusplus */

int sqlite3Fts2Init(sqlite3 *db);

#ifdef __cplusplus
}  /* extern "C" */
#endif  /* __cplusplus */

Deleted ext/fts2/fts2_hash.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
























































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
** 2001 September 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 is the implementation of generic hash-tables used in SQLite.
** We've modified it slightly to serve as a standalone hash table
** implementation for the full-text indexing module.
*/

/*
** The code in this file is only compiled if:
**
**     * The FTS2 module is being built as an extension
**       (in which case SQLITE_CORE is not defined), or
**
**     * The FTS2 module is being built into the core of
**       SQLite (in which case SQLITE_ENABLE_FTS2 is defined).
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2)

#include <assert.h>
#include <stdlib.h>
#include <string.h>

#include "sqlite3.h"
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT3
#include "fts2_hash.h"

/*
** Malloc and Free functions
*/
static void *fts2HashMalloc(int n){
  void *p = sqlite3_malloc(n);
  if( p ){
    memset(p, 0, n);
  }
  return p;
}
static void fts2HashFree(void *p){
  sqlite3_free(p);
}

/* Turn bulk memory into a hash table object by initializing the
** fields of the Hash structure.
**
** "pNew" is a pointer to the hash table that is to be initialized.
** keyClass is one of the constants 
** FTS2_HASH_BINARY or FTS2_HASH_STRING.  The value of keyClass 
** determines what kind of key the hash table will use.  "copyKey" is
** true if the hash table should make its own private copy of keys and
** false if it should just use the supplied pointer.
*/
void sqlite3Fts2HashInit(fts2Hash *pNew, int keyClass, int copyKey){
  assert( pNew!=0 );
  assert( keyClass>=FTS2_HASH_STRING && keyClass<=FTS2_HASH_BINARY );
  pNew->keyClass = keyClass;
  pNew->copyKey = copyKey;
  pNew->first = 0;
  pNew->count = 0;
  pNew->htsize = 0;
  pNew->ht = 0;
}

/* Remove all entries from a hash table.  Reclaim all memory.
** Call this routine to delete a hash table or to reset a hash table
** to the empty state.
*/
void sqlite3Fts2HashClear(fts2Hash *pH){
  fts2HashElem *elem;         /* For looping over all elements of the table */

  assert( pH!=0 );
  elem = pH->first;
  pH->first = 0;
  fts2HashFree(pH->ht);
  pH->ht = 0;
  pH->htsize = 0;
  while( elem ){
    fts2HashElem *next_elem = elem->next;
    if( pH->copyKey && elem->pKey ){
      fts2HashFree(elem->pKey);
    }
    fts2HashFree(elem);
    elem = next_elem;
  }
  pH->count = 0;
}

/*
** Hash and comparison functions when the mode is FTS2_HASH_STRING
*/
static int strHash(const void *pKey, int nKey){
  const char *z = (const char *)pKey;
  int h = 0;
  if( nKey<=0 ) nKey = (int) strlen(z);
  while( nKey > 0  ){
    h = (h<<3) ^ h ^ *z++;
    nKey--;
  }
  return h & 0x7fffffff;
}
static int strCompare(const void *pKey1, int n1, const void *pKey2, int n2){
  if( n1!=n2 ) return 1;
  return strncmp((const char*)pKey1,(const char*)pKey2,n1);
}

/*
** Hash and comparison functions when the mode is FTS2_HASH_BINARY
*/
static int binHash(const void *pKey, int nKey){
  int h = 0;
  const char *z = (const char *)pKey;
  while( nKey-- > 0 ){
    h = (h<<3) ^ h ^ *(z++);
  }
  return h & 0x7fffffff;
}
static int binCompare(const void *pKey1, int n1, const void *pKey2, int n2){
  if( n1!=n2 ) return 1;
  return memcmp(pKey1,pKey2,n1);
}

/*
** Return a pointer to the appropriate hash function given the key class.
**
** The C syntax in this function definition may be unfamilar to some 
** programmers, so we provide the following additional explanation:
**
** The name of the function is "hashFunction".  The function takes a
** single parameter "keyClass".  The return value of hashFunction()
** is a pointer to another function.  Specifically, the return value
** of hashFunction() is a pointer to a function that takes two parameters
** with types "const void*" and "int" and returns an "int".
*/
static int (*hashFunction(int keyClass))(const void*,int){
  if( keyClass==FTS2_HASH_STRING ){
    return &strHash;
  }else{
    assert( keyClass==FTS2_HASH_BINARY );
    return &binHash;
  }
}

/*
** Return a pointer to the appropriate hash function given the key class.
**
** For help in interpreted the obscure C code in the function definition,
** see the header comment on the previous function.
*/
static int (*compareFunction(int keyClass))(const void*,int,const void*,int){
  if( keyClass==FTS2_HASH_STRING ){
    return &strCompare;
  }else{
    assert( keyClass==FTS2_HASH_BINARY );
    return &binCompare;
  }
}

/* Link an element into the hash table
*/
static void insertElement(
  fts2Hash *pH,            /* The complete hash table */
  struct _fts2ht *pEntry,  /* The entry into which pNew is inserted */
  fts2HashElem *pNew       /* The element to be inserted */
){
  fts2HashElem *pHead;     /* First element already in pEntry */
  pHead = pEntry->chain;
  if( pHead ){
    pNew->next = pHead;
    pNew->prev = pHead->prev;
    if( pHead->prev ){ pHead->prev->next = pNew; }
    else             { pH->first = pNew; }
    pHead->prev = pNew;
  }else{
    pNew->next = pH->first;
    if( pH->first ){ pH->first->prev = pNew; }
    pNew->prev = 0;
    pH->first = pNew;
  }
  pEntry->count++;
  pEntry->chain = pNew;
}


/* Resize the hash table so that it cantains "new_size" buckets.
** "new_size" must be a power of 2.  The hash table might fail 
** to resize if sqliteMalloc() fails.
*/
static void rehash(fts2Hash *pH, int new_size){
  struct _fts2ht *new_ht;          /* The new hash table */
  fts2HashElem *elem, *next_elem;  /* For looping over existing elements */
  int (*xHash)(const void*,int);   /* The hash function */

  assert( (new_size & (new_size-1))==0 );
  new_ht = (struct _fts2ht *)fts2HashMalloc( new_size*sizeof(struct _fts2ht) );
  if( new_ht==0 ) return;
  fts2HashFree(pH->ht);
  pH->ht = new_ht;
  pH->htsize = new_size;
  xHash = hashFunction(pH->keyClass);
  for(elem=pH->first, pH->first=0; elem; elem = next_elem){
    int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1);
    next_elem = elem->next;
    insertElement(pH, &new_ht[h], elem);
  }
}

/* This function (for internal use only) locates an element in an
** hash table that matches the given key.  The hash for this key has
** already been computed and is passed as the 4th parameter.
*/
static fts2HashElem *findElementGivenHash(
  const fts2Hash *pH, /* The pH to be searched */
  const void *pKey,   /* The key we are searching for */
  int nKey,
  int h               /* The hash for this key. */
){
  fts2HashElem *elem;            /* Used to loop thru the element list */
  int count;                     /* Number of elements left to test */
  int (*xCompare)(const void*,int,const void*,int);  /* comparison function */

  if( pH->ht ){
    struct _fts2ht *pEntry = &pH->ht[h];
    elem = pEntry->chain;
    count = pEntry->count;
    xCompare = compareFunction(pH->keyClass);
    while( count-- && elem ){
      if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){ 
        return elem;
      }
      elem = elem->next;
    }
  }
  return 0;
}

/* Remove a single entry from the hash table given a pointer to that
** element and a hash on the element's key.
*/
static void removeElementGivenHash(
  fts2Hash *pH,         /* The pH containing "elem" */
  fts2HashElem* elem,   /* The element to be removed from the pH */
  int h                 /* Hash value for the element */
){
  struct _fts2ht *pEntry;
  if( elem->prev ){
    elem->prev->next = elem->next; 
  }else{
    pH->first = elem->next;
  }
  if( elem->next ){
    elem->next->prev = elem->prev;
  }
  pEntry = &pH->ht[h];
  if( pEntry->chain==elem ){
    pEntry->chain = elem->next;
  }
  pEntry->count--;
  if( pEntry->count<=0 ){
    pEntry->chain = 0;
  }
  if( pH->copyKey && elem->pKey ){
    fts2HashFree(elem->pKey);
  }
  fts2HashFree( elem );
  pH->count--;
  if( pH->count<=0 ){
    assert( pH->first==0 );
    assert( pH->count==0 );
    fts2HashClear(pH);
  }
}

/* Attempt to locate an element of the hash table pH with a key
** that matches pKey,nKey.  Return the data for this element if it is
** found, or NULL if there is no match.
*/
void *sqlite3Fts2HashFind(const fts2Hash *pH, const void *pKey, int nKey){
  int h;                 /* A hash on key */
  fts2HashElem *elem;    /* The element that matches key */
  int (*xHash)(const void*,int);  /* The hash function */

  if( pH==0 || pH->ht==0 ) return 0;
  xHash = hashFunction(pH->keyClass);
  assert( xHash!=0 );
  h = (*xHash)(pKey,nKey);
  assert( (pH->htsize & (pH->htsize-1))==0 );
  elem = findElementGivenHash(pH,pKey,nKey, h & (pH->htsize-1));
  return elem ? elem->data : 0;
}

/* Insert an element into the hash table pH.  The key is pKey,nKey
** and the data is "data".
**
** If no element exists with a matching key, then a new
** element is created.  A copy of the key is made if the copyKey
** flag is set.  NULL is returned.
**
** If another element already exists with the same key, then the
** new data replaces the old data and the old data is returned.
** The key is not copied in this instance.  If a malloc fails, then
** the new data is returned and the hash table is unchanged.
**
** If the "data" parameter to this function is NULL, then the
** element corresponding to "key" is removed from the hash table.
*/
void *sqlite3Fts2HashInsert(
  fts2Hash *pH,        /* The hash table to insert into */
  const void *pKey,    /* The key */
  int nKey,            /* Number of bytes in the key */
  void *data           /* The data */
){
  int hraw;                 /* Raw hash value of the key */
  int h;                    /* the hash of the key modulo hash table size */
  fts2HashElem *elem;       /* Used to loop thru the element list */
  fts2HashElem *new_elem;   /* New element added to the pH */
  int (*xHash)(const void*,int);  /* The hash function */

  assert( pH!=0 );
  xHash = hashFunction(pH->keyClass);
  assert( xHash!=0 );
  hraw = (*xHash)(pKey, nKey);
  assert( (pH->htsize & (pH->htsize-1))==0 );
  h = hraw & (pH->htsize-1);
  elem = findElementGivenHash(pH,pKey,nKey,h);
  if( elem ){
    void *old_data = elem->data;
    if( data==0 ){
      removeElementGivenHash(pH,elem,h);
    }else{
      elem->data = data;
    }
    return old_data;
  }
  if( data==0 ) return 0;
  new_elem = (fts2HashElem*)fts2HashMalloc( sizeof(fts2HashElem) );
  if( new_elem==0 ) return data;
  if( pH->copyKey && pKey!=0 ){
    new_elem->pKey = fts2HashMalloc( nKey );
    if( new_elem->pKey==0 ){
      fts2HashFree(new_elem);
      return data;
    }
    memcpy((void*)new_elem->pKey, pKey, nKey);
  }else{
    new_elem->pKey = (void*)pKey;
  }
  new_elem->nKey = nKey;
  pH->count++;
  if( pH->htsize==0 ){
    rehash(pH,8);
    if( pH->htsize==0 ){
      pH->count = 0;
      fts2HashFree(new_elem);
      return data;
    }
  }
  if( pH->count > pH->htsize ){
    rehash(pH,pH->htsize*2);
  }
  assert( pH->htsize>0 );
  assert( (pH->htsize & (pH->htsize-1))==0 );
  h = hraw & (pH->htsize-1);
  insertElement(pH, &pH->ht[h], new_elem);
  new_elem->data = data;
  return 0;
}

#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) */

Deleted ext/fts2/fts2_hash.h.

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














































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
** 2001 September 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 is the header file for the generic hash-table implementation
** used in SQLite.  We've modified it slightly to serve as a standalone
** hash table implementation for the full-text indexing module.
**
*/
#ifndef _FTS2_HASH_H_
#define _FTS2_HASH_H_

/* Forward declarations of structures. */
typedef struct fts2Hash fts2Hash;
typedef struct fts2HashElem fts2HashElem;

/* A complete hash table is an instance of the following structure.
** The internals of this structure are intended to be opaque -- client
** code should not attempt to access or modify the fields of this structure
** directly.  Change this structure only by using the routines below.
** However, many of the "procedures" and "functions" for modifying and
** accessing this structure are really macros, so we can't really make
** this structure opaque.
*/
struct fts2Hash {
  char keyClass;          /* HASH_INT, _POINTER, _STRING, _BINARY */
  char copyKey;           /* True if copy of key made on insert */
  int count;              /* Number of entries in this table */
  fts2HashElem *first;    /* The first element of the array */
  int htsize;             /* Number of buckets in the hash table */
  struct _fts2ht {        /* the hash table */
    int count;               /* Number of entries with this hash */
    fts2HashElem *chain;     /* Pointer to first entry with this hash */
  } *ht;
};

/* Each element in the hash table is an instance of the following 
** structure.  All elements are stored on a single doubly-linked list.
**
** Again, this structure is intended to be opaque, but it can't really
** be opaque because it is used by macros.
*/
struct fts2HashElem {
  fts2HashElem *next, *prev; /* Next and previous elements in the table */
  void *data;                /* Data associated with this element */
  void *pKey; int nKey;      /* Key associated with this element */
};

/*
** There are 2 different modes of operation for a hash table:
**
**   FTS2_HASH_STRING        pKey points to a string that is nKey bytes long
**                           (including the null-terminator, if any).  Case
**                           is respected in comparisons.
**
**   FTS2_HASH_BINARY        pKey points to binary data nKey bytes long. 
**                           memcmp() is used to compare keys.
**
** A copy of the key is made if the copyKey parameter to fts2HashInit is 1.  
*/
#define FTS2_HASH_STRING    1
#define FTS2_HASH_BINARY    2

/*
** Access routines.  To delete, insert a NULL pointer.
*/
void sqlite3Fts2HashInit(fts2Hash*, int keytype, int copyKey);
void *sqlite3Fts2HashInsert(fts2Hash*, const void *pKey, int nKey, void *pData);
void *sqlite3Fts2HashFind(const fts2Hash*, const void *pKey, int nKey);
void sqlite3Fts2HashClear(fts2Hash*);

/*
** Shorthand for the functions above
*/
#define fts2HashInit   sqlite3Fts2HashInit
#define fts2HashInsert sqlite3Fts2HashInsert
#define fts2HashFind   sqlite3Fts2HashFind
#define fts2HashClear  sqlite3Fts2HashClear

/*
** Macros for looping over all elements of a hash table.  The idiom is
** like this:
**
**   fts2Hash h;
**   fts2HashElem *p;
**   ...
**   for(p=fts2HashFirst(&h); p; p=fts2HashNext(p)){
**     SomeStructure *pData = fts2HashData(p);
**     // do something with pData
**   }
*/
#define fts2HashFirst(H)  ((H)->first)
#define fts2HashNext(E)   ((E)->next)
#define fts2HashData(E)   ((E)->data)
#define fts2HashKey(E)    ((E)->pKey)
#define fts2HashKeysize(E) ((E)->nKey)

/*
** Number of entries in a hash table
*/
#define fts2HashCount(H)  ((H)->count)

#endif /* _FTS2_HASH_H_ */

Deleted ext/fts2/fts2_icu.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260




































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
** 2007 June 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 a tokenizer for fts2 based on the ICU library.
** 
** $Id: fts2_icu.c,v 1.3 2008/12/18 05:30:26 danielk1977 Exp $
*/

#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2)
#ifdef SQLITE_ENABLE_ICU

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

#include <unicode/ubrk.h>
#include <unicode/ucol.h>
#include <unicode/ustring.h>
#include <unicode/utf16.h>

typedef struct IcuTokenizer IcuTokenizer;
typedef struct IcuCursor IcuCursor;

struct IcuTokenizer {
  sqlite3_tokenizer base;
  char *zLocale;
};

struct IcuCursor {
  sqlite3_tokenizer_cursor base;

  UBreakIterator *pIter;      /* ICU break-iterator object */
  int nChar;                  /* Number of UChar elements in pInput */
  UChar *aChar;               /* Copy of input using utf-16 encoding */
  int *aOffset;               /* Offsets of each character in utf-8 input */

  int nBuffer;
  char *zBuffer;

  int iToken;
};

/*
** Create a new tokenizer instance.
*/
static int icuCreate(
  int argc,                            /* Number of entries in argv[] */
  const char * const *argv,            /* Tokenizer creation arguments */
  sqlite3_tokenizer **ppTokenizer      /* OUT: Created tokenizer */
){
  IcuTokenizer *p;
  int n = 0;

  if( argc>0 ){
    n = strlen(argv[0])+1;
  }
  p = (IcuTokenizer *)sqlite3_malloc(sizeof(IcuTokenizer)+n);
  if( !p ){
    return SQLITE_NOMEM;
  }
  memset(p, 0, sizeof(IcuTokenizer));

  if( n ){
    p->zLocale = (char *)&p[1];
    memcpy(p->zLocale, argv[0], n);
  }

  *ppTokenizer = (sqlite3_tokenizer *)p;

  return SQLITE_OK;
}

/*
** Destroy a tokenizer
*/
static int icuDestroy(sqlite3_tokenizer *pTokenizer){
  IcuTokenizer *p = (IcuTokenizer *)pTokenizer;
  sqlite3_free(p);
  return SQLITE_OK;
}

/*
** Prepare to begin tokenizing a particular string.  The input
** string to be tokenized is pInput[0..nBytes-1].  A cursor
** used to incrementally tokenize this string is returned in 
** *ppCursor.
*/
static int icuOpen(
  sqlite3_tokenizer *pTokenizer,         /* The tokenizer */
  const char *zInput,                    /* Input string */
  int nInput,                            /* Length of zInput in bytes */
  sqlite3_tokenizer_cursor **ppCursor    /* OUT: Tokenization cursor */
){
  IcuTokenizer *p = (IcuTokenizer *)pTokenizer;
  IcuCursor *pCsr;

  const int32_t opt = U_FOLD_CASE_DEFAULT;
  UErrorCode status = U_ZERO_ERROR;
  int nChar;

  UChar32 c;
  int iInput = 0;
  int iOut = 0;

  *ppCursor = 0;

  if( nInput<0 ){
    nInput = strlen(zInput);
  }
  nChar = nInput+1;
  pCsr = (IcuCursor *)sqlite3_malloc(
      sizeof(IcuCursor) +                /* IcuCursor */
      ((nChar+3)&~3) * sizeof(UChar) +   /* IcuCursor.aChar[] */
      (nChar+1) * sizeof(int)            /* IcuCursor.aOffset[] */
  );
  if( !pCsr ){
    return SQLITE_NOMEM;
  }
  memset(pCsr, 0, sizeof(IcuCursor));
  pCsr->aChar = (UChar *)&pCsr[1];
  pCsr->aOffset = (int *)&pCsr->aChar[(nChar+3)&~3];

  pCsr->aOffset[iOut] = iInput;
  U8_NEXT(zInput, iInput, nInput, c); 
  while( c>0 ){
    int isError = 0;
    c = u_foldCase(c, opt);
    U16_APPEND(pCsr->aChar, iOut, nChar, c, isError);
    if( isError ){
      sqlite3_free(pCsr);
      return SQLITE_ERROR;
    }
    pCsr->aOffset[iOut] = iInput;

    if( iInput<nInput ){
      U8_NEXT(zInput, iInput, nInput, c);
    }else{
      c = 0;
    }
  }

  pCsr->pIter = ubrk_open(UBRK_WORD, p->zLocale, pCsr->aChar, iOut, &status);
  if( !U_SUCCESS(status) ){
    sqlite3_free(pCsr);
    return SQLITE_ERROR;
  }
  pCsr->nChar = iOut;

  ubrk_first(pCsr->pIter);
  *ppCursor = (sqlite3_tokenizer_cursor *)pCsr;
  return SQLITE_OK;
}

/*
** Close a tokenization cursor previously opened by a call to icuOpen().
*/
static int icuClose(sqlite3_tokenizer_cursor *pCursor){
  IcuCursor *pCsr = (IcuCursor *)pCursor;
  ubrk_close(pCsr->pIter);
  sqlite3_free(pCsr->zBuffer);
  sqlite3_free(pCsr);
  return SQLITE_OK;
}

/*
** Extract the next token from a tokenization cursor.
*/
static int icuNext(
  sqlite3_tokenizer_cursor *pCursor,  /* Cursor returned by simpleOpen */
  const char **ppToken,               /* OUT: *ppToken is the token text */
  int *pnBytes,                       /* OUT: Number of bytes in token */
  int *piStartOffset,                 /* OUT: Starting offset of token */
  int *piEndOffset,                   /* OUT: Ending offset of token */
  int *piPosition                     /* OUT: Position integer of token */
){
  IcuCursor *pCsr = (IcuCursor *)pCursor;

  int iStart = 0;
  int iEnd = 0;
  int nByte = 0;

  while( iStart==iEnd ){
    UChar32 c;

    iStart = ubrk_current(pCsr->pIter);
    iEnd = ubrk_next(pCsr->pIter);
    if( iEnd==UBRK_DONE ){
      return SQLITE_DONE;
    }

    while( iStart<iEnd ){
      int iWhite = iStart;
      U8_NEXT(pCsr->aChar, iWhite, pCsr->nChar, c);
      if( u_isspace(c) ){
        iStart = iWhite;
      }else{
        break;
      }
    }
    assert(iStart<=iEnd);
  }

  do {
    UErrorCode status = U_ZERO_ERROR;
    if( nByte ){
      char *zNew = sqlite3_realloc(pCsr->zBuffer, nByte);
      if( !zNew ){
        return SQLITE_NOMEM;
      }
      pCsr->zBuffer = zNew;
      pCsr->nBuffer = nByte;
    }

    u_strToUTF8(
        pCsr->zBuffer, pCsr->nBuffer, &nByte,    /* Output vars */
        &pCsr->aChar[iStart], iEnd-iStart,       /* Input vars */
        &status                                  /* Output success/failure */
    );
  } while( nByte>pCsr->nBuffer );

  *ppToken = pCsr->zBuffer;
  *pnBytes = nByte;
  *piStartOffset = pCsr->aOffset[iStart];
  *piEndOffset = pCsr->aOffset[iEnd];
  *piPosition = pCsr->iToken++;

  return SQLITE_OK;
}

/*
** The set of routines that implement the simple tokenizer
*/
static const sqlite3_tokenizer_module icuTokenizerModule = {
  0,                           /* iVersion */
  icuCreate,                   /* xCreate  */
  icuDestroy,                  /* xCreate  */
  icuOpen,                     /* xOpen    */
  icuClose,                    /* xClose   */
  icuNext,                     /* xNext    */
};

/*
** Set *ppModule to point at the implementation of the ICU tokenizer.
*/
void sqlite3Fts2IcuTokenizerModule(
  sqlite3_tokenizer_module const**ppModule
){
  *ppModule = &icuTokenizerModule;
}

#endif /* defined(SQLITE_ENABLE_ICU) */
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) */

Deleted ext/fts2/fts2_porter.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
638
639
640
641
642
643
644




































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
** 2006 September 30
**
** 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.
**
*************************************************************************
** Implementation of the full-text-search tokenizer that implements
** a Porter stemmer.
*/

/*
** The code in this file is only compiled if:
**
**     * The FTS2 module is being built as an extension
**       (in which case SQLITE_CORE is not defined), or
**
**     * The FTS2 module is being built into the core of
**       SQLite (in which case SQLITE_ENABLE_FTS2 is defined).
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2)


#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "sqlite3.h"
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT3
#include "fts2_tokenizer.h"

/*
** Class derived from sqlite3_tokenizer
*/
typedef struct porter_tokenizer {
  sqlite3_tokenizer base;      /* Base class */
} porter_tokenizer;

/*
** Class derived from sqlit3_tokenizer_cursor
*/
typedef struct porter_tokenizer_cursor {
  sqlite3_tokenizer_cursor base;
  const char *zInput;          /* input we are tokenizing */
  int nInput;                  /* size of the input */
  int iOffset;                 /* current position in zInput */
  int iToken;                  /* index of next token to be returned */
  char *zToken;                /* storage for current token */
  int nAllocated;              /* space allocated to zToken buffer */
} porter_tokenizer_cursor;


/* Forward declaration */
static const sqlite3_tokenizer_module porterTokenizerModule;


/*
** Create a new tokenizer instance.
*/
static int porterCreate(
  int argc, const char * const *argv,
  sqlite3_tokenizer **ppTokenizer
){
  porter_tokenizer *t;
  t = (porter_tokenizer *) sqlite3_malloc(sizeof(*t));
  if( t==NULL ) return SQLITE_NOMEM;
  memset(t, 0, sizeof(*t));
  *ppTokenizer = &t->base;
  return SQLITE_OK;
}

/*
** Destroy a tokenizer
*/
static int porterDestroy(sqlite3_tokenizer *pTokenizer){
  sqlite3_free(pTokenizer);
  return SQLITE_OK;
}

/*
** Prepare to begin tokenizing a particular string.  The input
** string to be tokenized is zInput[0..nInput-1].  A cursor
** used to incrementally tokenize this string is returned in 
** *ppCursor.
*/
static int porterOpen(
  sqlite3_tokenizer *pTokenizer,         /* The tokenizer */
  const char *zInput, int nInput,        /* String to be tokenized */
  sqlite3_tokenizer_cursor **ppCursor    /* OUT: Tokenization cursor */
){
  porter_tokenizer_cursor *c;

  c = (porter_tokenizer_cursor *) sqlite3_malloc(sizeof(*c));
  if( c==NULL ) return SQLITE_NOMEM;

  c->zInput = zInput;
  if( zInput==0 ){
    c->nInput = 0;
  }else if( nInput<0 ){
    c->nInput = (int)strlen(zInput);
  }else{
    c->nInput = nInput;
  }
  c->iOffset = 0;                 /* start tokenizing at the beginning */
  c->iToken = 0;
  c->zToken = NULL;               /* no space allocated, yet. */
  c->nAllocated = 0;

  *ppCursor = &c->base;
  return SQLITE_OK;
}

/*
** Close a tokenization cursor previously opened by a call to
** porterOpen() above.
*/
static int porterClose(sqlite3_tokenizer_cursor *pCursor){
  porter_tokenizer_cursor *c = (porter_tokenizer_cursor *) pCursor;
  sqlite3_free(c->zToken);
  sqlite3_free(c);
  return SQLITE_OK;
}
/*
** Vowel or consonant
*/
static const char cType[] = {
   0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0,
   1, 1, 1, 2, 1
};

/*
** isConsonant() and isVowel() determine if their first character in
** the string they point to is a consonant or a vowel, according
** to Porter ruls.  
**
** A consonate is any letter other than 'a', 'e', 'i', 'o', or 'u'.
** 'Y' is a consonant unless it follows another consonant,
** in which case it is a vowel.
**
** In these routine, the letters are in reverse order.  So the 'y' rule
** is that 'y' is a consonant unless it is followed by another
** consonent.
*/
static int isVowel(const char*);
static int isConsonant(const char *z){
  int j;
  char x = *z;
  if( x==0 ) return 0;
  assert( x>='a' && x<='z' );
  j = cType[x-'a'];
  if( j<2 ) return j;
  return z[1]==0 || isVowel(z + 1);
}
static int isVowel(const char *z){
  int j;
  char x = *z;
  if( x==0 ) return 0;
  assert( x>='a' && x<='z' );
  j = cType[x-'a'];
  if( j<2 ) return 1-j;
  return isConsonant(z + 1);
}

/*
** Let any sequence of one or more vowels be represented by V and let
** C be sequence of one or more consonants.  Then every word can be
** represented as:
**
**           [C] (VC){m} [V]
**
** In prose:  A word is an optional consonant followed by zero or
** vowel-consonant pairs followed by an optional vowel.  "m" is the
** number of vowel consonant pairs.  This routine computes the value
** of m for the first i bytes of a word.
**
** Return true if the m-value for z is 1 or more.  In other words,
** return true if z contains at least one vowel that is followed
** by a consonant.
**
** In this routine z[] is in reverse order.  So we are really looking
** for an instance of of a consonant followed by a vowel.
*/
static int m_gt_0(const char *z){
  while( isVowel(z) ){ z++; }
  if( *z==0 ) return 0;
  while( isConsonant(z) ){ z++; }
  return *z!=0;
}

/* Like mgt0 above except we are looking for a value of m which is
** exactly 1
*/
static int m_eq_1(const char *z){
  while( isVowel(z) ){ z++; }
  if( *z==0 ) return 0;
  while( isConsonant(z) ){ z++; }
  if( *z==0 ) return 0;
  while( isVowel(z) ){ z++; }
  if( *z==0 ) return 1;
  while( isConsonant(z) ){ z++; }
  return *z==0;
}

/* Like mgt0 above except we are looking for a value of m>1 instead
** or m>0
*/
static int m_gt_1(const char *z){
  while( isVowel(z) ){ z++; }
  if( *z==0 ) return 0;
  while( isConsonant(z) ){ z++; }
  if( *z==0 ) return 0;
  while( isVowel(z) ){ z++; }
  if( *z==0 ) return 0;
  while( isConsonant(z) ){ z++; }
  return *z!=0;
}

/*
** Return TRUE if there is a vowel anywhere within z[0..n-1]
*/
static int hasVowel(const char *z){
  while( isConsonant(z) ){ z++; }
  return *z!=0;
}

/*
** Return TRUE if the word ends in a double consonant.
**
** The text is reversed here. So we are really looking at
** the first two characters of z[].
*/
static int doubleConsonant(const char *z){
  return isConsonant(z) && z[0]==z[1] && isConsonant(z+1);
}

/*
** Return TRUE if the word ends with three letters which
** are consonant-vowel-consonent and where the final consonant
** is not 'w', 'x', or 'y'.
**
** The word is reversed here.  So we are really checking the
** first three letters and the first one cannot be in [wxy].
*/
static int star_oh(const char *z){
  return
    z[0]!=0 && isConsonant(z) &&
    z[0]!='w' && z[0]!='x' && z[0]!='y' &&
    z[1]!=0 && isVowel(z+1) &&
    z[2]!=0 && isConsonant(z+2);
}

/*
** If the word ends with zFrom and xCond() is true for the stem
** of the word that preceeds the zFrom ending, then change the 
** ending to zTo.
**
** The input word *pz and zFrom are both in reverse order.  zTo
** is in normal order. 
**
** Return TRUE if zFrom matches.  Return FALSE if zFrom does not
** match.  Not that TRUE is returned even if xCond() fails and
** no substitution occurs.
*/
static int stem(
  char **pz,             /* The word being stemmed (Reversed) */
  const char *zFrom,     /* If the ending matches this... (Reversed) */
  const char *zTo,       /* ... change the ending to this (not reversed) */
  int (*xCond)(const char*)   /* Condition that must be true */
){
  char *z = *pz;
  while( *zFrom && *zFrom==*z ){ z++; zFrom++; }
  if( *zFrom!=0 ) return 0;
  if( xCond && !xCond(z) ) return 1;
  while( *zTo ){
    *(--z) = *(zTo++);
  }
  *pz = z;
  return 1;
}

/*
** This is the fallback stemmer used when the porter stemmer is
** inappropriate.  The input word is copied into the output with
** US-ASCII case folding.  If the input word is too long (more
** than 20 bytes if it contains no digits or more than 6 bytes if
** it contains digits) then word is truncated to 20 or 6 bytes
** by taking 10 or 3 bytes from the beginning and end.
*/
static void copy_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){
  int i, mx, j;
  int hasDigit = 0;
  for(i=0; i<nIn; i++){
    int c = zIn[i];
    if( c>='A' && c<='Z' ){
      zOut[i] = c - 'A' + 'a';
    }else{
      if( c>='0' && c<='9' ) hasDigit = 1;
      zOut[i] = c;
    }
  }
  mx = hasDigit ? 3 : 10;
  if( nIn>mx*2 ){
    for(j=mx, i=nIn-mx; i<nIn; i++, j++){
      zOut[j] = zOut[i];
    }
    i = j;
  }
  zOut[i] = 0;
  *pnOut = i;
}


/*
** Stem the input word zIn[0..nIn-1].  Store the output in zOut.
** zOut is at least big enough to hold nIn bytes.  Write the actual
** size of the output word (exclusive of the '\0' terminator) into *pnOut.
**
** Any upper-case characters in the US-ASCII character set ([A-Z])
** are converted to lower case.  Upper-case UTF characters are
** unchanged.
**
** Words that are longer than about 20 bytes are stemmed by retaining
** a few bytes from the beginning and the end of the word.  If the
** word contains digits, 3 bytes are taken from the beginning and
** 3 bytes from the end.  For long words without digits, 10 bytes
** are taken from each end.  US-ASCII case folding still applies.
** 
** If the input word contains not digits but does characters not 
** in [a-zA-Z] then no stemming is attempted and this routine just 
** copies the input into the input into the output with US-ASCII
** case folding.
**
** Stemming never increases the length of the word.  So there is
** no chance of overflowing the zOut buffer.
*/
static void porter_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){
  int i, j, c;
  char zReverse[28];
  char *z, *z2;
  if( nIn<3 || nIn>=sizeof(zReverse)-7 ){
    /* The word is too big or too small for the porter stemmer.
    ** Fallback to the copy stemmer */
    copy_stemmer(zIn, nIn, zOut, pnOut);
    return;
  }
  for(i=0, j=sizeof(zReverse)-6; i<nIn; i++, j--){
    c = zIn[i];
    if( c>='A' && c<='Z' ){
      zReverse[j] = c + 'a' - 'A';
    }else if( c>='a' && c<='z' ){
      zReverse[j] = c;
    }else{
      /* The use of a character not in [a-zA-Z] means that we fallback
      ** to the copy stemmer */
      copy_stemmer(zIn, nIn, zOut, pnOut);
      return;
    }
  }
  memset(&zReverse[sizeof(zReverse)-5], 0, 5);
  z = &zReverse[j+1];


  /* Step 1a */
  if( z[0]=='s' ){
    if(
     !stem(&z, "sess", "ss", 0) &&
     !stem(&z, "sei", "i", 0)  &&
     !stem(&z, "ss", "ss", 0)
    ){
      z++;
    }
  }

  /* Step 1b */  
  z2 = z;
  if( stem(&z, "dee", "ee", m_gt_0) ){
    /* Do nothing.  The work was all in the test */
  }else if( 
     (stem(&z, "gni", "", hasVowel) || stem(&z, "de", "", hasVowel))
      && z!=z2
  ){
     if( stem(&z, "ta", "ate", 0) ||
         stem(&z, "lb", "ble", 0) ||
         stem(&z, "zi", "ize", 0) ){
       /* Do nothing.  The work was all in the test */
     }else if( doubleConsonant(z) && (*z!='l' && *z!='s' && *z!='z') ){
       z++;
     }else if( m_eq_1(z) && star_oh(z) ){
       *(--z) = 'e';
     }
  }

  /* Step 1c */
  if( z[0]=='y' && hasVowel(z+1) ){
    z[0] = 'i';
  }

  /* Step 2 */
  switch( z[1] ){
   case 'a':
     stem(&z, "lanoita", "ate", m_gt_0) ||
     stem(&z, "lanoit", "tion", m_gt_0);
     break;
   case 'c':
     stem(&z, "icne", "ence", m_gt_0) ||
     stem(&z, "icna", "ance", m_gt_0);
     break;
   case 'e':
     stem(&z, "rezi", "ize", m_gt_0);
     break;
   case 'g':
     stem(&z, "igol", "log", m_gt_0);
     break;
   case 'l':
     stem(&z, "ilb", "ble", m_gt_0) ||
     stem(&z, "illa", "al", m_gt_0) ||
     stem(&z, "iltne", "ent", m_gt_0) ||
     stem(&z, "ile", "e", m_gt_0) ||
     stem(&z, "ilsuo", "ous", m_gt_0);
     break;
   case 'o':
     stem(&z, "noitazi", "ize", m_gt_0) ||
     stem(&z, "noita", "ate", m_gt_0) ||
     stem(&z, "rota", "ate", m_gt_0);
     break;
   case 's':
     stem(&z, "msila", "al", m_gt_0) ||
     stem(&z, "ssenevi", "ive", m_gt_0) ||
     stem(&z, "ssenluf", "ful", m_gt_0) ||
     stem(&z, "ssensuo", "ous", m_gt_0);
     break;
   case 't':
     stem(&z, "itila", "al", m_gt_0) ||
     stem(&z, "itivi", "ive", m_gt_0) ||
     stem(&z, "itilib", "ble", m_gt_0);
     break;
  }

  /* Step 3 */
  switch( z[0] ){
   case 'e':
     stem(&z, "etaci", "ic", m_gt_0) ||
     stem(&z, "evita", "", m_gt_0)   ||
     stem(&z, "ezila", "al", m_gt_0);
     break;
   case 'i':
     stem(&z, "itici", "ic", m_gt_0);
     break;
   case 'l':
     stem(&z, "laci", "ic", m_gt_0) ||
     stem(&z, "luf", "", m_gt_0);
     break;
   case 's':
     stem(&z, "ssen", "", m_gt_0);
     break;
  }

  /* Step 4 */
  switch( z[1] ){
   case 'a':
     if( z[0]=='l' && m_gt_1(z+2) ){
       z += 2;
     }
     break;
   case 'c':
     if( z[0]=='e' && z[2]=='n' && (z[3]=='a' || z[3]=='e')  && m_gt_1(z+4)  ){
       z += 4;
     }
     break;
   case 'e':
     if( z[0]=='r' && m_gt_1(z+2) ){
       z += 2;
     }
     break;
   case 'i':
     if( z[0]=='c' && m_gt_1(z+2) ){
       z += 2;
     }
     break;
   case 'l':
     if( z[0]=='e' && z[2]=='b' && (z[3]=='a' || z[3]=='i') && m_gt_1(z+4) ){
       z += 4;
     }
     break;
   case 'n':
     if( z[0]=='t' ){
       if( z[2]=='a' ){
         if( m_gt_1(z+3) ){
           z += 3;
         }
       }else if( z[2]=='e' ){
         stem(&z, "tneme", "", m_gt_1) ||
         stem(&z, "tnem", "", m_gt_1) ||
         stem(&z, "tne", "", m_gt_1);
       }
     }
     break;
   case 'o':
     if( z[0]=='u' ){
       if( m_gt_1(z+2) ){
         z += 2;
       }
     }else if( z[3]=='s' || z[3]=='t' ){
       stem(&z, "noi", "", m_gt_1);
     }
     break;
   case 's':
     if( z[0]=='m' && z[2]=='i' && m_gt_1(z+3) ){
       z += 3;
     }
     break;
   case 't':
     stem(&z, "eta", "", m_gt_1) ||
     stem(&z, "iti", "", m_gt_1);
     break;
   case 'u':
     if( z[0]=='s' && z[2]=='o' && m_gt_1(z+3) ){
       z += 3;
     }
     break;
   case 'v':
   case 'z':
     if( z[0]=='e' && z[2]=='i' && m_gt_1(z+3) ){
       z += 3;
     }
     break;
  }

  /* Step 5a */
  if( z[0]=='e' ){
    if( m_gt_1(z+1) ){
      z++;
    }else if( m_eq_1(z+1) && !star_oh(z+1) ){
      z++;
    }
  }

  /* Step 5b */
  if( m_gt_1(z) && z[0]=='l' && z[1]=='l' ){
    z++;
  }

  /* z[] is now the stemmed word in reverse order.  Flip it back
  ** around into forward order and return.
  */
  *pnOut = i = strlen(z);
  zOut[i] = 0;
  while( *z ){
    zOut[--i] = *(z++);
  }
}

/*
** Characters that can be part of a token.  We assume any character
** whose value is greater than 0x80 (any UTF character) can be
** part of a token.  In other words, delimiters all must have
** values of 0x7f or lower.
*/
static const char porterIdChar[] = {
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,  /* 3x */
    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 4x */
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,  /* 5x */
    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 6x */
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,  /* 7x */
};
#define isDelim(C) (((ch=C)&0x80)==0 && (ch<0x30 || !porterIdChar[ch-0x30]))

/*
** Extract the next token from a tokenization cursor.  The cursor must
** have been opened by a prior call to porterOpen().
*/
static int porterNext(
  sqlite3_tokenizer_cursor *pCursor,  /* Cursor returned by porterOpen */
  const char **pzToken,               /* OUT: *pzToken is the token text */
  int *pnBytes,                       /* OUT: Number of bytes in token */
  int *piStartOffset,                 /* OUT: Starting offset of token */
  int *piEndOffset,                   /* OUT: Ending offset of token */
  int *piPosition                     /* OUT: Position integer of token */
){
  porter_tokenizer_cursor *c = (porter_tokenizer_cursor *) pCursor;
  const char *z = c->zInput;

  while( c->iOffset<c->nInput ){
    int iStartOffset, ch;

    /* Scan past delimiter characters */
    while( c->iOffset<c->nInput && isDelim(z[c->iOffset]) ){
      c->iOffset++;
    }

    /* Count non-delimiter characters. */
    iStartOffset = c->iOffset;
    while( c->iOffset<c->nInput && !isDelim(z[c->iOffset]) ){
      c->iOffset++;
    }

    if( c->iOffset>iStartOffset ){
      int n = c->iOffset-iStartOffset;
      if( n>c->nAllocated ){
        c->nAllocated = n+20;
        c->zToken = sqlite3_realloc(c->zToken, c->nAllocated);
        if( c->zToken==NULL ) return SQLITE_NOMEM;
      }
      porter_stemmer(&z[iStartOffset], n, c->zToken, pnBytes);
      *pzToken = c->zToken;
      *piStartOffset = iStartOffset;
      *piEndOffset = c->iOffset;
      *piPosition = c->iToken++;
      return SQLITE_OK;
    }
  }
  return SQLITE_DONE;
}

/*
** The set of routines that implement the porter-stemmer tokenizer
*/
static const sqlite3_tokenizer_module porterTokenizerModule = {
  0,
  porterCreate,
  porterDestroy,
  porterOpen,
  porterClose,
  porterNext,
};

/*
** Allocate a new porter tokenizer.  Return a pointer to the new
** tokenizer in *ppModule
*/
void sqlite3Fts2PorterTokenizerModule(
  sqlite3_tokenizer_module const**ppModule
){
  *ppModule = &porterTokenizerModule;
}

#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) */

Deleted ext/fts2/fts2_tokenizer.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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























































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
** 2007 June 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 is part of an SQLite module implementing full-text search.
** This particular file implements the generic tokenizer interface.
*/

/*
** The code in this file is only compiled if:
**
**     * The FTS2 module is being built as an extension
**       (in which case SQLITE_CORE is not defined), or
**
**     * The FTS2 module is being built into the core of
**       SQLite (in which case SQLITE_ENABLE_FTS2 is defined).
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2)


#include "sqlite3.h"
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT3

#include "fts2_hash.h"
#include "fts2_tokenizer.h"
#include <assert.h>

/*
** Implementation of the SQL scalar function for accessing the underlying 
** hash table. This function may be called as follows:
**
**   SELECT <function-name>(<key-name>);
**   SELECT <function-name>(<key-name>, <pointer>);
**
** where <function-name> is the name passed as the second argument
** to the sqlite3Fts2InitHashTable() function (e.g. 'fts2_tokenizer').
**
** If the <pointer> argument is specified, it must be a blob value
** containing a pointer to be stored as the hash data corresponding
** to the string <key-name>. If <pointer> is not specified, then
** the string <key-name> must already exist in the has table. Otherwise,
** an error is returned.
**
** Whether or not the <pointer> argument is specified, the value returned
** is a blob containing the pointer stored as the hash data corresponding
** to string <key-name> (after the hash-table is updated, if applicable).
*/
static void scalarFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  fts2Hash *pHash;
  void *pPtr = 0;
  const unsigned char *zName;
  int nName;

  assert( argc==1 || argc==2 );

  pHash = (fts2Hash *)sqlite3_user_data(context);

  zName = sqlite3_value_text(argv[0]);
  nName = sqlite3_value_bytes(argv[0])+1;

  if( argc==2 ){
    void *pOld;
    int n = sqlite3_value_bytes(argv[1]);
    if( n!=sizeof(pPtr) ){
      sqlite3_result_error(context, "argument type mismatch", -1);
      return;
    }
    pPtr = *(void **)sqlite3_value_blob(argv[1]);
    pOld = sqlite3Fts2HashInsert(pHash, (void *)zName, nName, pPtr);
    if( pOld==pPtr ){
      sqlite3_result_error(context, "out of memory", -1);
      return;
    }
  }else{
    pPtr = sqlite3Fts2HashFind(pHash, zName, nName);
    if( !pPtr ){
      char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName);
      sqlite3_result_error(context, zErr, -1);
      sqlite3_free(zErr);
      return;
    }
  }

  sqlite3_result_blob(context, (void *)&pPtr, sizeof(pPtr), SQLITE_TRANSIENT);
}

#ifdef SQLITE_TEST

#if defined(INCLUDE_SQLITE_TCL_H)
#  include "sqlite_tcl.h"
#else
#  include "tcl.h"
#endif
#include <string.h>

/*
** Implementation of a special SQL scalar function for testing tokenizers 
** designed to be used in concert with the Tcl testing framework. This
** function must be called with two arguments:
**
**   SELECT <function-name>(<key-name>, <input-string>);
**   SELECT <function-name>(<key-name>, <pointer>);
**
** where <function-name> is the name passed as the second argument
** to the sqlite3Fts2InitHashTable() function (e.g. 'fts2_tokenizer')
** concatenated with the string '_test' (e.g. 'fts2_tokenizer_test').
**
** The return value is a string that may be interpreted as a Tcl
** list. For each token in the <input-string>, three elements are
** added to the returned list. The first is the token position, the 
** second is the token text (folded, stemmed, etc.) and the third is the
** substring of <input-string> associated with the token. For example, 
** using the built-in "simple" tokenizer:
**
**   SELECT fts_tokenizer_test('simple', 'I don't see how');
**
** will return the string:
**
**   "{0 i I 1 dont don't 2 see see 3 how how}"
**   
*/
static void testFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  fts2Hash *pHash;
  sqlite3_tokenizer_module *p;
  sqlite3_tokenizer *pTokenizer = 0;
  sqlite3_tokenizer_cursor *pCsr = 0;

  const char *zErr = 0;

  const char *zName;
  int nName;
  const char *zInput;
  int nInput;

  const char *zArg = 0;

  const char *zToken;
  int nToken;
  int iStart;
  int iEnd;
  int iPos;

  Tcl_Obj *pRet;

  assert( argc==2 || argc==3 );

  nName = sqlite3_value_bytes(argv[0]);
  zName = (const char *)sqlite3_value_text(argv[0]);
  nInput = sqlite3_value_bytes(argv[argc-1]);
  zInput = (const char *)sqlite3_value_text(argv[argc-1]);

  if( argc==3 ){
    zArg = (const char *)sqlite3_value_text(argv[1]);
  }

  pHash = (fts2Hash *)sqlite3_user_data(context);
  p = (sqlite3_tokenizer_module *)sqlite3Fts2HashFind(pHash, zName, nName+1);

  if( !p ){
    char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName);
    sqlite3_result_error(context, zErr, -1);
    sqlite3_free(zErr);
    return;
  }

  pRet = Tcl_NewObj();
  Tcl_IncrRefCount(pRet);

  if( SQLITE_OK!=p->xCreate(zArg ? 1 : 0, &zArg, &pTokenizer) ){
    zErr = "error in xCreate()";
    goto finish;
  }
  pTokenizer->pModule = p;
  if( SQLITE_OK!=p->xOpen(pTokenizer, zInput, nInput, &pCsr) ){
    zErr = "error in xOpen()";
    goto finish;
  }
  pCsr->pTokenizer = pTokenizer;

  while( SQLITE_OK==p->xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos) ){
    Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(iPos));
    Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zToken, nToken));
    zToken = &zInput[iStart];
    nToken = iEnd-iStart;
    Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zToken, nToken));
  }

  if( SQLITE_OK!=p->xClose(pCsr) ){
    zErr = "error in xClose()";
    goto finish;
  }
  if( SQLITE_OK!=p->xDestroy(pTokenizer) ){
    zErr = "error in xDestroy()";
    goto finish;
  }

finish:
  if( zErr ){
    sqlite3_result_error(context, zErr, -1);
  }else{
    sqlite3_result_text(context, Tcl_GetString(pRet), -1, SQLITE_TRANSIENT);
  }
  Tcl_DecrRefCount(pRet);
}

static
int registerTokenizer(
  sqlite3 *db, 
  char *zName, 
  const sqlite3_tokenizer_module *p
){
  int rc;
  sqlite3_stmt *pStmt;
  const char zSql[] = "SELECT fts2_tokenizer(?, ?)";

  rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
  if( rc!=SQLITE_OK ){
    return rc;
  }

  sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC);
  sqlite3_bind_blob(pStmt, 2, &p, sizeof(p), SQLITE_STATIC);
  sqlite3_step(pStmt);

  return sqlite3_finalize(pStmt);
}

static
int queryFts2Tokenizer(
  sqlite3 *db, 
  char *zName,  
  const sqlite3_tokenizer_module **pp
){
  int rc;
  sqlite3_stmt *pStmt;
  const char zSql[] = "SELECT fts2_tokenizer(?)";

  *pp = 0;
  rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
  if( rc!=SQLITE_OK ){
    return rc;
  }

  sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC);
  if( SQLITE_ROW==sqlite3_step(pStmt) ){
    if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){
      memcpy(pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp));
    }
  }

  return sqlite3_finalize(pStmt);
}

void sqlite3Fts2SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule);

/*
** Implementation of the scalar function fts2_tokenizer_internal_test().
** This function is used for testing only, it is not included in the
** build unless SQLITE_TEST is defined.
**
** The purpose of this is to test that the fts2_tokenizer() function
** can be used as designed by the C-code in the queryFts2Tokenizer and
** registerTokenizer() functions above. These two functions are repeated
** in the README.tokenizer file as an example, so it is important to
** test them.
**
** To run the tests, evaluate the fts2_tokenizer_internal_test() scalar
** function with no arguments. An assert() will fail if a problem is
** detected. i.e.:
**
**     SELECT fts2_tokenizer_internal_test();
**
*/
static void intTestFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  int rc;
  const sqlite3_tokenizer_module *p1;
  const sqlite3_tokenizer_module *p2;
  sqlite3 *db = (sqlite3 *)sqlite3_user_data(context);

  /* Test the query function */
  sqlite3Fts2SimpleTokenizerModule(&p1);
  rc = queryFts2Tokenizer(db, "simple", &p2);
  assert( rc==SQLITE_OK );
  assert( p1==p2 );
  rc = queryFts2Tokenizer(db, "nosuchtokenizer", &p2);
  assert( rc==SQLITE_ERROR );
  assert( p2==0 );
  assert( 0==strcmp(sqlite3_errmsg(db), "unknown tokenizer: nosuchtokenizer") );

  /* Test the storage function */
  rc = registerTokenizer(db, "nosuchtokenizer", p1);
  assert( rc==SQLITE_OK );
  rc = queryFts2Tokenizer(db, "nosuchtokenizer", &p2);
  assert( rc==SQLITE_OK );
  assert( p2==p1 );

  sqlite3_result_text(context, "ok", -1, SQLITE_STATIC);
}

#endif

/*
** Set up SQL objects in database db used to access the contents of
** the hash table pointed to by argument pHash. The hash table must
** been initialized to use string keys, and to take a private copy 
** of the key when a value is inserted. i.e. by a call similar to:
**
**    sqlite3Fts2HashInit(pHash, FTS2_HASH_STRING, 1);
**
** This function adds a scalar function (see header comment above
** scalarFunc() in this file for details) and, if ENABLE_TABLE is
** defined at compilation time, a temporary virtual table (see header 
** comment above struct HashTableVtab) to the database schema. Both 
** provide read/write access to the contents of *pHash.
**
** The third argument to this function, zName, is used as the name
** of both the scalar and, if created, the virtual table.
*/
int sqlite3Fts2InitHashTable(
  sqlite3 *db, 
  fts2Hash *pHash, 
  const char *zName
){
  int rc = SQLITE_OK;
  void *p = (void *)pHash;
  const int any = SQLITE_ANY;
  char *zTest = 0;
  char *zTest2 = 0;

#ifdef SQLITE_TEST
  void *pdb = (void *)db;
  zTest = sqlite3_mprintf("%s_test", zName);
  zTest2 = sqlite3_mprintf("%s_internal_test", zName);
  if( !zTest || !zTest2 ){
    rc = SQLITE_NOMEM;
  }
#endif

  if( rc!=SQLITE_OK
   || (rc = sqlite3_create_function(db, zName, 1, any, p, scalarFunc, 0, 0))
   || (rc = sqlite3_create_function(db, zName, 2, any, p, scalarFunc, 0, 0))
#ifdef SQLITE_TEST
   || (rc = sqlite3_create_function(db, zTest, 2, any, p, testFunc, 0, 0))
   || (rc = sqlite3_create_function(db, zTest, 3, any, p, testFunc, 0, 0))
   || (rc = sqlite3_create_function(db, zTest2, 0, any, pdb, intTestFunc, 0, 0))
#endif
  );

  sqlite3_free(zTest);
  sqlite3_free(zTest2);
  return rc;
}

#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) */

Deleted ext/fts2/fts2_tokenizer.h.

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

















































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
** 2006 July 10
**
** The author disclaims copyright to this source code.
**
*************************************************************************
** Defines the interface to tokenizers used by fulltext-search.  There
** are three basic components:
**
** sqlite3_tokenizer_module is a singleton defining the tokenizer
** interface functions.  This is essentially the class structure for
** tokenizers.
**
** sqlite3_tokenizer is used to define a particular tokenizer, perhaps
** including customization information defined at creation time.
**
** sqlite3_tokenizer_cursor is generated by a tokenizer to generate
** tokens from a particular input.
*/
#ifndef _FTS2_TOKENIZER_H_
#define _FTS2_TOKENIZER_H_

/* TODO(shess) Only used for SQLITE_OK and SQLITE_DONE at this time.
** If tokenizers are to be allowed to call sqlite3_*() functions, then
** we will need a way to register the API consistently.
*/
#include "sqlite3.h"

/*
** Structures used by the tokenizer interface. When a new tokenizer
** implementation is registered, the caller provides a pointer to
** an sqlite3_tokenizer_module containing pointers to the callback
** functions that make up an implementation.
**
** When an fts2 table is created, it passes any arguments passed to
** the tokenizer clause of the CREATE VIRTUAL TABLE statement to the
** sqlite3_tokenizer_module.xCreate() function of the requested tokenizer
** implementation. The xCreate() function in turn returns an 
** sqlite3_tokenizer structure representing the specific tokenizer to
** be used for the fts2 table (customized by the tokenizer clause arguments).
**
** To tokenize an input buffer, the sqlite3_tokenizer_module.xOpen()
** method is called. It returns an sqlite3_tokenizer_cursor object
** that may be used to tokenize a specific input buffer based on
** the tokenization rules supplied by a specific sqlite3_tokenizer
** object.
*/
typedef struct sqlite3_tokenizer_module sqlite3_tokenizer_module;
typedef struct sqlite3_tokenizer sqlite3_tokenizer;
typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor;

struct sqlite3_tokenizer_module {

  /*
  ** Structure version. Should always be set to 0.
  */
  int iVersion;

  /*
  ** Create a new tokenizer. The values in the argv[] array are the
  ** arguments passed to the "tokenizer" clause of the CREATE VIRTUAL
  ** TABLE statement that created the fts2 table. For example, if
  ** the following SQL is executed:
  **
  **   CREATE .. USING fts2( ... , tokenizer <tokenizer-name> arg1 arg2)
  **
  ** then argc is set to 2, and the argv[] array contains pointers
  ** to the strings "arg1" and "arg2".
  **
  ** This method should return either SQLITE_OK (0), or an SQLite error 
  ** code. If SQLITE_OK is returned, then *ppTokenizer should be set
  ** to point at the newly created tokenizer structure. The generic
  ** sqlite3_tokenizer.pModule variable should not be initialized by
  ** this callback. The caller will do so.
  */
  int (*xCreate)(
    int argc,                           /* Size of argv array */
    const char *const*argv,             /* Tokenizer argument strings */
    sqlite3_tokenizer **ppTokenizer     /* OUT: Created tokenizer */
  );

  /*
  ** Destroy an existing tokenizer. The fts2 module calls this method
  ** exactly once for each successful call to xCreate().
  */
  int (*xDestroy)(sqlite3_tokenizer *pTokenizer);

  /*
  ** Create a tokenizer cursor to tokenize an input buffer. The caller
  ** is responsible for ensuring that the input buffer remains valid
  ** until the cursor is closed (using the xClose() method). 
  */
  int (*xOpen)(
    sqlite3_tokenizer *pTokenizer,       /* Tokenizer object */
    const char *pInput, int nBytes,      /* Input buffer */
    sqlite3_tokenizer_cursor **ppCursor  /* OUT: Created tokenizer cursor */
  );

  /*
  ** Destroy an existing tokenizer cursor. The fts2 module calls this 
  ** method exactly once for each successful call to xOpen().
  */
  int (*xClose)(sqlite3_tokenizer_cursor *pCursor);

  /*
  ** Retrieve the next token from the tokenizer cursor pCursor. This
  ** method should either return SQLITE_OK and set the values of the
  ** "OUT" variables identified below, or SQLITE_DONE to indicate that
  ** the end of the buffer has been reached, or an SQLite error code.
  **
  ** *ppToken should be set to point at a buffer containing the 
  ** normalized version of the token (i.e. after any case-folding and/or
  ** stemming has been performed). *pnBytes should be set to the length
  ** of this buffer in bytes. The input text that generated the token is
  ** identified by the byte offsets returned in *piStartOffset and
  ** *piEndOffset.
  **
  ** The buffer *ppToken is set to point at is managed by the tokenizer
  ** implementation. It is only required to be valid until the next call
  ** to xNext() or xClose(). 
  */
  /* TODO(shess) current implementation requires pInput to be
  ** nul-terminated.  This should either be fixed, or pInput/nBytes
  ** should be converted to zInput.
  */
  int (*xNext)(
    sqlite3_tokenizer_cursor *pCursor,   /* Tokenizer cursor */
    const char **ppToken, int *pnBytes,  /* OUT: Normalized text for token */
    int *piStartOffset,  /* OUT: Byte offset of token in input buffer */
    int *piEndOffset,    /* OUT: Byte offset of end of token in input buffer */
    int *piPosition      /* OUT: Number of tokens returned before this one */
  );
};

struct sqlite3_tokenizer {
  const sqlite3_tokenizer_module *pModule;  /* The module for this tokenizer */
  /* Tokenizer implementations will typically add additional fields */
};

struct sqlite3_tokenizer_cursor {
  sqlite3_tokenizer *pTokenizer;       /* Tokenizer for this cursor. */
  /* Tokenizer implementations will typically add additional fields */
};

#endif /* _FTS2_TOKENIZER_H_ */

Deleted ext/fts2/fts2_tokenizer1.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233









































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
** 2006 Oct 10
**
** 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.
**
******************************************************************************
**
** Implementation of the "simple" full-text-search tokenizer.
*/

/*
** The code in this file is only compiled if:
**
**     * The FTS2 module is being built as an extension
**       (in which case SQLITE_CORE is not defined), or
**
**     * The FTS2 module is being built into the core of
**       SQLite (in which case SQLITE_ENABLE_FTS2 is defined).
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2)


#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "sqlite3.h"
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT3
#include "fts2_tokenizer.h"

typedef struct simple_tokenizer {
  sqlite3_tokenizer base;
  char delim[128];             /* flag ASCII delimiters */
} simple_tokenizer;

typedef struct simple_tokenizer_cursor {
  sqlite3_tokenizer_cursor base;
  const char *pInput;          /* input we are tokenizing */
  int nBytes;                  /* size of the input */
  int iOffset;                 /* current position in pInput */
  int iToken;                  /* index of next token to be returned */
  char *pToken;                /* storage for current token */
  int nTokenAllocated;         /* space allocated to zToken buffer */
} simple_tokenizer_cursor;


/* Forward declaration */
static const sqlite3_tokenizer_module simpleTokenizerModule;

static int simpleDelim(simple_tokenizer *t, unsigned char c){
  return c<0x80 && t->delim[c];
}

/*
** Create a new tokenizer instance.
*/
static int simpleCreate(
  int argc, const char * const *argv,
  sqlite3_tokenizer **ppTokenizer
){
  simple_tokenizer *t;

  t = (simple_tokenizer *) sqlite3_malloc(sizeof(*t));
  if( t==NULL ) return SQLITE_NOMEM;
  memset(t, 0, sizeof(*t));

  /* TODO(shess) Delimiters need to remain the same from run to run,
  ** else we need to reindex.  One solution would be a meta-table to
  ** track such information in the database, then we'd only want this
  ** information on the initial create.
  */
  if( argc>1 ){
    int i, n = strlen(argv[1]);
    for(i=0; i<n; i++){
      unsigned char ch = argv[1][i];
      /* We explicitly don't support UTF-8 delimiters for now. */
      if( ch>=0x80 ){
        sqlite3_free(t);
        return SQLITE_ERROR;
      }
      t->delim[ch] = 1;
    }
  } else {
    /* Mark non-alphanumeric ASCII characters as delimiters */
    int i;
    for(i=1; i<0x80; i++){
      t->delim[i] = !((i>='0' && i<='9') || (i>='A' && i<='Z') ||
                      (i>='a' && i<='z'));
    }
  }

  *ppTokenizer = &t->base;
  return SQLITE_OK;
}

/*
** Destroy a tokenizer
*/
static int simpleDestroy(sqlite3_tokenizer *pTokenizer){
  sqlite3_free(pTokenizer);
  return SQLITE_OK;
}

/*
** Prepare to begin tokenizing a particular string.  The input
** string to be tokenized is pInput[0..nBytes-1].  A cursor
** used to incrementally tokenize this string is returned in 
** *ppCursor.
*/
static int simpleOpen(
  sqlite3_tokenizer *pTokenizer,         /* The tokenizer */
  const char *pInput, int nBytes,        /* String to be tokenized */
  sqlite3_tokenizer_cursor **ppCursor    /* OUT: Tokenization cursor */
){
  simple_tokenizer_cursor *c;

  c = (simple_tokenizer_cursor *) sqlite3_malloc(sizeof(*c));
  if( c==NULL ) return SQLITE_NOMEM;

  c->pInput = pInput;
  if( pInput==0 ){
    c->nBytes = 0;
  }else if( nBytes<0 ){
    c->nBytes = (int)strlen(pInput);
  }else{
    c->nBytes = nBytes;
  }
  c->iOffset = 0;                 /* start tokenizing at the beginning */
  c->iToken = 0;
  c->pToken = NULL;               /* no space allocated, yet. */
  c->nTokenAllocated = 0;

  *ppCursor = &c->base;
  return SQLITE_OK;
}

/*
** Close a tokenization cursor previously opened by a call to
** simpleOpen() above.
*/
static int simpleClose(sqlite3_tokenizer_cursor *pCursor){
  simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor;
  sqlite3_free(c->pToken);
  sqlite3_free(c);
  return SQLITE_OK;
}

/*
** Extract the next token from a tokenization cursor.  The cursor must
** have been opened by a prior call to simpleOpen().
*/
static int simpleNext(
  sqlite3_tokenizer_cursor *pCursor,  /* Cursor returned by simpleOpen */
  const char **ppToken,               /* OUT: *ppToken is the token text */
  int *pnBytes,                       /* OUT: Number of bytes in token */
  int *piStartOffset,                 /* OUT: Starting offset of token */
  int *piEndOffset,                   /* OUT: Ending offset of token */
  int *piPosition                     /* OUT: Position integer of token */
){
  simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor;
  simple_tokenizer *t = (simple_tokenizer *) pCursor->pTokenizer;
  unsigned char *p = (unsigned char *)c->pInput;

  while( c->iOffset<c->nBytes ){
    int iStartOffset;

    /* Scan past delimiter characters */
    while( c->iOffset<c->nBytes && simpleDelim(t, p[c->iOffset]) ){
      c->iOffset++;
    }

    /* Count non-delimiter characters. */
    iStartOffset = c->iOffset;
    while( c->iOffset<c->nBytes && !simpleDelim(t, p[c->iOffset]) ){
      c->iOffset++;
    }

    if( c->iOffset>iStartOffset ){
      int i, n = c->iOffset-iStartOffset;
      if( n>c->nTokenAllocated ){
        c->nTokenAllocated = n+20;
        c->pToken = sqlite3_realloc(c->pToken, c->nTokenAllocated);
        if( c->pToken==NULL ) return SQLITE_NOMEM;
      }
      for(i=0; i<n; i++){
        /* TODO(shess) This needs expansion to handle UTF-8
        ** case-insensitivity.
        */
        unsigned char ch = p[iStartOffset+i];
        c->pToken[i] = (ch>='A' && ch<='Z') ? (ch - 'A' + 'a') : ch;
      }
      *ppToken = c->pToken;
      *pnBytes = n;
      *piStartOffset = iStartOffset;
      *piEndOffset = c->iOffset;
      *piPosition = c->iToken++;

      return SQLITE_OK;
    }
  }
  return SQLITE_DONE;
}

/*
** The set of routines that implement the simple tokenizer
*/
static const sqlite3_tokenizer_module simpleTokenizerModule = {
  0,
  simpleCreate,
  simpleDestroy,
  simpleOpen,
  simpleClose,
  simpleNext,
};

/*
** Allocate a new simple tokenizer.  Return a pointer to the new
** tokenizer in *ppModule
*/
void sqlite3Fts2SimpleTokenizerModule(
  sqlite3_tokenizer_module const**ppModule
){
  *ppModule = &simpleTokenizerModule;
}

#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) */

Deleted ext/fts2/mkfts2amal.tcl.

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




















































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#!/usr/bin/tclsh
#
# This script builds a single C code file holding all of FTS2 code.
# The name of the output file is fts2amal.c.  To build this file,
# first do:
#
#      make target_source
#
# The make target above moves all of the source code files into
# a subdirectory named "tsrc".  (This script expects to find the files
# there and will not work if they are not found.)
#
# After the "tsrc" directory has been created and populated, run
# this script:
#
#      tclsh mkfts2amal.tcl
#
# The amalgamated FTS2 code will be written into fts2amal.c
#

# Open the output file and write a header comment at the beginning
# of the file.
#
set out [open fts2amal.c w]
set today [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S UTC" -gmt 1]
puts $out [subst \
{/******************************************************************************
** This file is an amalgamation of separate C source files from the SQLite
** Full Text Search extension 2 (fts2).  By combining all the individual C 
** code  files into this single large file, the entire code can be compiled 
** as a one translation unit.  This allows many compilers to do optimizations
** that would not be possible if the files were compiled separately.  It also
** makes the code easier to import into other projects.
**
** This amalgamation was generated on $today.
*/}]

# These are the header files used by FTS2.  The first time any of these 
# files are seen in a #include statement in the C code, include the complete
# text of the file in-line.  The file only needs to be included once.
#
foreach hdr {
   fts2.h
   fts2_hash.h
   fts2_tokenizer.h
   sqlite3.h
   sqlite3ext.h
} {
  set available_hdr($hdr) 1
}

# 78 stars used for comment formatting.
set s78 \
{*****************************************************************************}

# Insert a comment into the code
#
proc section_comment {text} {
  global out s78
  set n [string length $text]
  set nstar [expr {60 - $n}]
  set stars [string range $s78 0 $nstar]
  puts $out "/************** $text $stars/"
}

# Read the source file named $filename and write it into the
# sqlite3.c output file.  If any #include statements are seen,
# process them approprately.
#
proc copy_file {filename} {
  global seen_hdr available_hdr out
  set tail [file tail $filename]
  section_comment "Begin file $tail"
  set in [open $filename r]
  while {![eof $in]} {
    set line [gets $in]
    if {[regexp {^#\s*include\s+["<]([^">]+)[">]} $line all hdr]} {
      if {[info exists available_hdr($hdr)]} {
        if {$available_hdr($hdr)} {
          section_comment "Include $hdr in the middle of $tail"
          copy_file tsrc/$hdr
          section_comment "Continuing where we left off in $tail"
        }
      } elseif {![info exists seen_hdr($hdr)]} {
        set seen_hdr($hdr) 1
        puts $out $line
      }
    } elseif {[regexp {^#ifdef __cplusplus} $line]} {
      puts $out "#if 0"
    } elseif {[regexp {^#line} $line]} {
      # Skip #line directives.
    } else {
      puts $out $line
    }
  }
  close $in
  section_comment "End of $tail"
}


# Process the source files.  Process files containing commonly
# used subroutines first in order to help the compiler find
# inlining opportunities.
#
foreach file {
   fts2.c
   fts2_hash.c
   fts2_porter.c
   fts2_tokenizer.c
   fts2_tokenizer1.c
   fts2_icu.c
} {
  copy_file tsrc/$file
}

close $out

Changes to ext/fts3/README.content.

170
171
172
173
174
175
176
177
178
170
171
172
173
174
175
176









-
-

    INSERT INTO t3(t3) VALUES('rebuild');

  This command may also be used with ordinary FTS4 tables, although it may
  only be useful if the full-text index has somehow become corrupt. It is an
  error to attempt to rebuild the full-text index maintained by a contentless
  FTS4 table.


Changes to ext/fts3/README.tokenizers.

48
49
50
51
52
53
54
55
56




57
58
59
60
61
62
63
48
49
50
51
52
53
54


55
56
57
58
59
60
61
62
63
64
65







-
-
+
+
+
+







  returned. If only one argument is passed, a pointer to the tokenizer
  implementation currently registered as <tokenizer-name> is returned,
  encoded as a blob. Or, if no such tokenizer exists, an SQL exception
  (error) is raised.

  SECURITY: If the fts3 extension is used in an environment where potentially
    malicious users may execute arbitrary SQL (i.e. gears), they should be
    prevented from invoking the fts3_tokenizer() function, possibly using the
    authorisation callback.
    prevented from invoking the fts3_tokenizer() function.  The
    fts3_tokenizer() function is disabled by default. It is only enabled
    by SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER. Do not enable it in
    security sensitive environments.

  See "Sample code" below for an example of calling the fts3_tokenizer()
  function from C code.

3. ICU Library Tokenizers

  If this extension is compiled with the SQLITE_ENABLE_ICU pre-processor 

Changes to ext/fts3/fts3.c.

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







+
+
+
+
+
+






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




















-
+





-
-
-
-
-
-
+




















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






+



-
+

-
+



-
-
-
+
+
+

-
+







#include <stdarg.h>

#include "fts3.h"
#ifndef SQLITE_CORE 
# include "sqlite3ext.h"
  SQLITE_EXTENSION_INIT1
#endif

typedef struct Fts3HashWrapper Fts3HashWrapper;
struct Fts3HashWrapper {
  Fts3Hash hash;                  /* Hash table */
  int nRef;                       /* Number of pointers to this object */
};

static int fts3EvalNext(Fts3Cursor *pCsr);
static int fts3EvalStart(Fts3Cursor *pCsr);
static int fts3TermSegReaderCursor(
    Fts3Cursor *, const char *, int, int, Fts3MultiSegReader **);

#ifndef SQLITE_AMALGAMATION
# if defined(SQLITE_DEBUG)
int sqlite3Fts3Always(int b) { assert( b ); return b; }
/*
** 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;
int sqlite3Fts3Never(int b)  { assert( !b ); return b; }
# endif
#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){
  unsigned char *q = (unsigned char *) p;
  sqlite_uint64 vu = v;
  do{
    *q++ = (unsigned char) ((vu & 0x7f) | 0x80);
    vu >>= 7;
  }while( vu!=0 );
  q[-1] &= 0x7f;  /* turn off high bit in final byte */
  assert( q - (unsigned char *)p <= FTS3_VARINT_MAX );
  return (int) (q - (unsigned char *)p);
}

#define GETVARINT_STEP(v, ptr, shift, mask1, mask2, var, ret) \
  v = (v & mask1) | ( (*ptr++) << shift );                    \
  v = (v & mask1) | ( (*(const unsigned char*)(ptr++)) << shift );  \
  if( (v & mask2)==0 ){ var = v; return ret; }
#define GETVARINT_INIT(v, ptr, shift, mask1, mask2, var, ret) \
  v = (*ptr++);                                               \
  if( (v & mask2)==0 ){ var = v; return ret; }

/* 
** Read a 64-bit variable-length integer from memory starting at p[0].
** Return the number of bytes read, or 0 on error.
** The value is stored in *v.
*/
int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){
int sqlite3Fts3GetVarintU(const char *pBuf, sqlite_uint64 *v){
  const unsigned char *p = (const unsigned char*)pBuf;
  const unsigned char *pStart = p;
  u32 a;
  u64 b;
  int shift;

  GETVARINT_INIT(a, p, 0,  0x00,     0x80, *v, 1);
  GETVARINT_STEP(a, p, 7,  0x7F,     0x4000, *v, 2);
  GETVARINT_STEP(a, p, 14, 0x3FFF,   0x200000, *v, 3);
  GETVARINT_STEP(a, p, 21, 0x1FFFFF, 0x10000000, *v, 4);
  b = (a & 0x0FFFFFFF );

  for(shift=28; shift<=63; shift+=7){
    u64 c = *p++;
    b += (c&0x7F) << shift;
    if( (c & 0x80)==0 ) break;
  }
  *v = b;
  return (int)(p - pStart);
}

/* 
** Read a 64-bit variable-length integer from memory starting at p[0].
** Return the number of bytes read, or 0 on error.
** The value is stored in *v.
*/
int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){
  return sqlite3Fts3GetVarintU(pBuf, (sqlite3_uint64*)v);
}

/* 
** Read a 64-bit variable-length integer from memory starting at p[0] and
** not extending past pEnd[-1].
** Return the number of bytes read, or 0 on error.
** The value is stored in *v.
*/
int sqlite3Fts3GetVarintBounded(
  const char *pBuf,
  const char *pEnd,
  sqlite_int64 *v
){
  const unsigned char *p = (const unsigned char*)pBuf;
  const unsigned char *pStart = p;
  const unsigned char *pX = (const unsigned char*)pEnd;
  u64 b = 0;
  int shift;
  for(shift=0; shift<=63; shift+=7){
    u64 c = p<pX ? *p : 0;
    p++;
    b += (c&0x7F) << shift;
    if( (c & 0x80)==0 ) break;
  }
  *v = b;
  return (int)(p - pStart);
}

/*
** Similar to sqlite3Fts3GetVarint(), except that the output is truncated to 
** a non-negative 32-bit integer before it is returned.
*/
int sqlite3Fts3GetVarint32(const char *p, int *pi){
  const unsigned char *ptr = (const unsigned char*)p;
  u32 a;

#ifndef fts3GetVarint32
  GETVARINT_INIT(a, p, 0,  0x00,     0x80, *pi, 1);
  GETVARINT_INIT(a, ptr, 0,  0x00,     0x80, *pi, 1);
#else
  a = (*p++);
  a = (*ptr++);
  assert( a & 0x80 );
#endif

  GETVARINT_STEP(a, p, 7,  0x7F,     0x4000, *pi, 2);
  GETVARINT_STEP(a, p, 14, 0x3FFF,   0x200000, *pi, 3);
  GETVARINT_STEP(a, p, 21, 0x1FFFFF, 0x10000000, *pi, 4);
  GETVARINT_STEP(a, ptr, 7,  0x7F,     0x4000, *pi, 2);
  GETVARINT_STEP(a, ptr, 14, 0x3FFF,   0x200000, *pi, 3);
  GETVARINT_STEP(a, ptr, 21, 0x1FFFFF, 0x10000000, *pi, 4);
  a = (a & 0x0FFFFFFF );
  *pi = (int)(a | ((u32)(*p & 0x07) << 28));
  *pi = (int)(a | ((u32)(*ptr & 0x07) << 28));
  assert( 0==(a & 0x80000000) );
  assert( *pi>=0 );
  return 5;
}

/*
** Return the number of bytes required to encode v as a varint
556
557
558
559
560
561
562
563
564

565
566
567
568
569











570
571
572
573
574
575
576
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







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







static int fts3DestroyMethod(sqlite3_vtab *pVtab){
  Fts3Table *p = (Fts3Table *)pVtab;
  int rc = SQLITE_OK;              /* Return code */
  const char *zDb = p->zDb;        /* Name of database (e.g. "main", "temp") */
  sqlite3 *db = p->db;             /* Database handle */

  /* Drop the shadow tables */
  if( p->zContentTbl==0 ){
    fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_content'", zDb, p->zName);
  fts3DbExec(&rc, db, 
  }
  fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segments'", zDb,p->zName);
  fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segdir'", zDb, p->zName);
  fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_docsize'", zDb, p->zName);
  fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_stat'", zDb, p->zName);
    "DROP TABLE IF EXISTS %Q.'%q_segments';"
    "DROP TABLE IF EXISTS %Q.'%q_segdir';"
    "DROP TABLE IF EXISTS %Q.'%q_docsize';"
    "DROP TABLE IF EXISTS %Q.'%q_stat';"
    "%s DROP TABLE IF EXISTS %Q.'%q_content';",
    zDb, p->zName,
    zDb, p->zName,
    zDb, p->zName,
    zDb, p->zName,
    (p->zContentTbl ? "--" : ""), zDb,p->zName
  );

  /* If everything has worked, invoke fts3DisconnectMethod() to free the
  ** memory associated with the Fts3Table structure and return SQLITE_OK.
  ** Otherwise, return an SQLite error code.
  */
  return (rc==SQLITE_OK ? fts3DisconnectMethod(pVtab) : rc);
}
794
795
796
797
798
799
800
801

802
803
804

805
806
807
808
809
810
811
839
840
841
842
843
844
845

846
847
848

849
850
851
852
853
854
855
856







-
+


-
+







**     fts3QuoteId("un \"zip\"")   ->    "un \"\"zip\"\""
**
** The pointer returned points to memory obtained from sqlite3_malloc(). It
** is the callers responsibility to call sqlite3_free() to release this
** memory.
*/
static char *fts3QuoteId(char const *zInput){
  int nRet;
  sqlite3_int64 nRet;
  char *zRet;
  nRet = 2 + (int)strlen(zInput)*2 + 1;
  zRet = sqlite3_malloc(nRet);
  zRet = sqlite3_malloc64(nRet);
  if( zRet ){
    int i;
    char *z = zRet;
    *(z++) = '"';
    for(i=0; zInput[i]; i++){
      if( zInput[i]=='"' ) *(z++) = '"';
      *(z++) = zInput[i];
913
914
915
916
917
918
919
















920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938

939
940
941
942



943
944



945
946
947
948

949
950
951
952
953
954
955
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996

997

998




999
1000
1001


1002
1003
1004
1005

1006

1007
1008
1009
1010
1011
1012
1013
1014







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
















-

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

-

-
+







  }
  if( p->zLanguageid ){
    fts3Appendf(pRc, &zRet, ", ?");
  }
  sqlite3_free(zFree);
  return zRet;
}

/*
** Buffer z contains a positive integer value encoded as utf-8 text.
** Decode this value and store it in *pnOut, returning the number of bytes
** consumed. If an overflow error occurs return a negative value.
*/
int sqlite3Fts3ReadInt(const char *z, int *pnOut){
  u64 iVal = 0;
  int i;
  for(i=0; z[i]>='0' && z[i]<='9'; i++){
    iVal = iVal*10 + (z[i] - '0');
    if( iVal>0x7FFFFFFF ) return -1;
  }
  *pnOut = (int)iVal;
  return i;
}

/*
** This function interprets the string at (*pp) as a non-negative integer
** value. It reads the integer and sets *pnOut to the value read, then 
** sets *pp to point to the byte immediately following the last byte of
** the integer value.
**
** Only decimal digits ('0'..'9') may be part of an integer value. 
**
** If *pp does not being with a decimal digit SQLITE_ERROR is returned and
** the output value undefined. Otherwise SQLITE_OK is returned.
**
** This function is used when parsing the "prefix=" FTS4 parameter.
*/
static int fts3GobbleInt(const char **pp, int *pnOut){
  const int MAX_NPREFIX = 10000000;
  const char *p;                  /* Iterator pointer */
  int nInt = 0;                   /* Output value */

  int nByte;
  for(p=*pp; p[0]>='0' && p[0]<='9'; p++){
    nInt = nInt * 10 + (p[0] - '0');
    if( nInt>MAX_NPREFIX ){
      nInt = 0;
  nByte = sqlite3Fts3ReadInt(*pp, &nInt);
  if( nInt>MAX_NPREFIX ){
    nInt = 0;
      break;
    }
  }
  if( nByte==0 ){
    return SQLITE_ERROR;
  }
  if( p==*pp ) return SQLITE_ERROR;
  *pnOut = nInt;
  *pp = p;
  *pp += nByte;
  return SQLITE_OK;
}

/*
** This function is called to allocate an array of Fts3Index structures
** representing the indexes maintained by the current FTS table. FTS tables
** always maintain the main "terms" index, but may also maintain one or
978
979
980
981
982
983
984
985

986
987
988
989
990
991
992
1037
1038
1039
1040
1041
1042
1043

1044
1045
1046
1047
1048
1049
1050
1051







-
+







    const char *p;
    nIndex++;
    for(p=zParam; *p; p++){
      if( *p==',' ) nIndex++;
    }
  }

  aIndex = sqlite3_malloc(sizeof(struct Fts3Index) * nIndex);
  aIndex = sqlite3_malloc64(sizeof(struct Fts3Index) * nIndex);
  *apIndex = aIndex;
  if( !aIndex ){
    return SQLITE_NOMEM;
  }

  memset(aIndex, 0, sizeof(struct Fts3Index) * nIndex);
  if( zParam ){
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
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







-
+









-
+



-
+







      sqlite3Fts3ErrMsg(pzErr, "%s", sqlite3_errmsg(db));
    }
  }
  sqlite3_free(zSql);

  if( rc==SQLITE_OK ){
    const char **azCol;           /* Output array */
    int nStr = 0;                 /* Size of all column names (incl. 0x00) */
    sqlite3_int64 nStr = 0;       /* Size of all column names (incl. 0x00) */
    int nCol;                     /* Number of table columns */
    int i;                        /* Used to iterate through columns */

    /* Loop through the returned columns. Set nStr to the number of bytes of
    ** space required to store a copy of each column name, including the
    ** nul-terminator byte.  */
    nCol = sqlite3_column_count(pStmt);
    for(i=0; i<nCol; i++){
      const char *zCol = sqlite3_column_name(pStmt, i);
      nStr += (int)strlen(zCol) + 1;
      nStr += strlen(zCol) + 1;
    }

    /* Allocate and populate the array to return. */
    azCol = (const char **)sqlite3_malloc(sizeof(char *) * nCol + nStr);
    azCol = (const char **)sqlite3_malloc64(sizeof(char *) * nCol + nStr);
    if( azCol==0 ){
      rc = SQLITE_NOMEM;
    }else{
      char *p = (char *)&azCol[nCol];
      for(i=0; i<nCol; i++){
        const char *zCol = sqlite3_column_name(pStmt, i);
        int n = (int)strlen(zCol)+1;
1115
1116
1117
1118
1119
1120
1121
1122

1123
1124
1125
1126

1127
1128
1129
1130
1131
1132
1133
1174
1175
1176
1177
1178
1179
1180

1181
1182
1183
1184

1185
1186
1187
1188
1189
1190
1191
1192







-
+



-
+







  sqlite3 *db,                    /* The SQLite database connection */
  void *pAux,                     /* Hash table containing tokenizers */
  int argc,                       /* Number of elements in argv array */
  const char * const *argv,       /* xCreate/xConnect argument array */
  sqlite3_vtab **ppVTab,          /* Write the resulting vtab structure here */
  char **pzErr                    /* Write any error message here */
){
  Fts3Hash *pHash = (Fts3Hash *)pAux;
  Fts3Hash *pHash = &((Fts3HashWrapper*)pAux)->hash;
  Fts3Table *p = 0;               /* Pointer to allocated vtab */
  int rc = SQLITE_OK;             /* Return code */
  int i;                          /* Iterator variable */
  int nByte;                      /* Size of allocation used for *p */
  sqlite3_int64 nByte;            /* Size of allocation used for *p */
  int iCol;                       /* Column index */
  int nString = 0;                /* Bytes required to hold all column names */
  int nCol = 0;                   /* Number of columns in the FTS table */
  char *zCsr;                     /* Space for holding column names */
  int nDb;                        /* Bytes required to hold database name */
  int nName;                      /* Bytes required to hold table name */
  int isFts4 = (argv[0][3]=='4'); /* True for FTS4, false for FTS3 */
1153
1154
1155
1156
1157
1158
1159
1160

1161
1162
1163

1164
1165
1166
1167
1168
1169
1170
1212
1213
1214
1215
1216
1217
1218

1219
1220
1221

1222
1223
1224
1225
1226
1227
1228
1229







-
+


-
+







       || (sqlite3_strnicmp(argv[0], "fts3", 4)==0 && !isFts4)
  );

  nDb = (int)strlen(argv[1]) + 1;
  nName = (int)strlen(argv[2]) + 1;

  nByte = sizeof(const char *) * (argc-2);
  aCol = (const char **)sqlite3_malloc(nByte);
  aCol = (const char **)sqlite3_malloc64(nByte);
  if( aCol ){
    memset((void*)aCol, 0, nByte);
    azNotindexed = (char **)sqlite3_malloc(nByte);
    azNotindexed = (char **)sqlite3_malloc64(nByte);
  }
  if( azNotindexed ){
    memset(azNotindexed, 0, nByte);
  }
  if( !aCol || !azNotindexed ){
    rc = SQLITE_NOMEM;
    goto fts3_init_out;
1351
1352
1353
1354
1355
1356
1357
1358

1359
1360
1361
1362
1363
1364
1365
1410
1411
1412
1413
1414
1415
1416

1417
1418
1419
1420
1421
1422
1423
1424







-
+







  nByte = sizeof(Fts3Table) +                  /* Fts3Table */
          nCol * sizeof(char *) +              /* azColumn */
          nIndex * sizeof(struct Fts3Index) +  /* aIndex */
          nCol * sizeof(u8) +                  /* abNotindexed */
          nName +                              /* zName */
          nDb +                                /* zDb */
          nString;                             /* Space for azColumn strings */
  p = (Fts3Table*)sqlite3_malloc(nByte);
  p = (Fts3Table*)sqlite3_malloc64(nByte);
  if( p==0 ){
    rc = SQLITE_NOMEM;
    goto fts3_init_out;
  }
  memset(p, 0, nByte);
  p->db = db;
  p->nColumn = nCol;
1455
1456
1457
1458
1459
1460
1461




1462
1463
1464
1465
1466
1467
1468
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531







+
+
+
+







    p->bHasStat = 2;
  }

  /* Figure out the page-size for the database. This is required in order to
  ** estimate the cost of loading large doclists from the database.  */
  fts3DatabasePageSize(&rc, p);
  p->nNodeSize = p->nPgsz-35;

#if defined(SQLITE_DEBUG)||defined(SQLITE_TEST)
  p->nMergeCount = FTS3_MERGE_COUNT;
#endif

  /* Declare the table schema to SQLite. */
  fts3DeclareVtab(&rc, p);

fts3_init_out:
  sqlite3_free(zPrefix);
  sqlite3_free(aIndex);
1550
1551
1552
1553
1554
1555
1556




1557
1558
1559
1560
1561
1562
1563
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630







+
+
+
+







  int i;                          /* Iterator variable */
  int iCons = -1;                 /* Index of constraint to use */

  int iLangidCons = -1;           /* Index of langid=x constraint, if present */
  int iDocidGe = -1;              /* Index of docid>=x constraint, if present */
  int iDocidLe = -1;              /* Index of docid<=x constraint, if present */
  int iIdx;

  if( p->bLock ){
    return SQLITE_ERROR;
  }

  /* By default use a full table scan. This is an expensive option,
  ** so search through the constraints to see if a more efficient 
  ** strategy is possible.
  */
  pInfo->idxNum = FTS3_FULLSCAN_SEARCH;
  pInfo->estimatedCost = 5000000;
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
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







+
+
-
+
+
+

















+
+



+


+







    char *zSql;
    if( p->pSeekStmt ){
      pCsr->pStmt = p->pSeekStmt;
      p->pSeekStmt = 0;
    }else{
      zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist);
      if( !zSql ) return SQLITE_NOMEM;
      p->bLock++;
      rc = sqlite3_prepare_v3(
      rc = sqlite3_prepare_v3(p->db, zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0);
          p->db, zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0
      );
      p->bLock--;
      sqlite3_free(zSql);
    }
    if( rc==SQLITE_OK ) pCsr->bSeekStmt = 1;
  }
  return rc;
}

/*
** Position the pCsr->pStmt statement so that it is on the row
** of the %_content table that contains the last match.  Return
** SQLITE_OK on success.  
*/
static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){
  int rc = SQLITE_OK;
  if( pCsr->isRequireSeek ){
    rc = fts3CursorSeekStmt(pCsr);
    if( rc==SQLITE_OK ){
      Fts3Table *pTab = (Fts3Table*)pCsr->base.pVtab;
      pTab->bLock++;
      sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId);
      pCsr->isRequireSeek = 0;
      if( SQLITE_ROW==sqlite3_step(pCsr->pStmt) ){
        pTab->bLock--;
        return SQLITE_OK;
      }else{
        pTab->bLock--;
        rc = sqlite3_reset(pCsr->pStmt);
        if( rc==SQLITE_OK && ((Fts3Table *)pCsr->base.pVtab)->zContentTbl==0 ){
          /* If no row was found and no error has occurred, then the %_content
          ** table is missing a row that is present in the full-text index.
          ** The data structures are corrupt.  */
          rc = FTS_CORRUPT_VTAB;
          pCsr->isEof = 1;
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
1894
1895
1896
1897
1898
1899
1900

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


1917
1918
1919
1920
1921
1922
1923
1924
1925
1926

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

1941
1942
1943
1944
1945
1946
1947
1948







-
+
+














-
-
+
+








-





+
+
+
+





-
+







){
  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 */
    int nPrefix = 0;              /* Size of term prefix */
    int nBuffer;                  /* Total term size */
  
    /* Load the next term on the node into zBuffer. Use realloc() to expand
    ** the size of zBuffer if required.  */
    if( !isFirstTerm ){
      zCsr += fts3GetVarint32(zCsr, &nPrefix);
      if( nPrefix>nBuffer ){
        rc = FTS_CORRUPT_VTAB;
        goto finish_scan;
      }
    }
    isFirstTerm = 0;
    zCsr += fts3GetVarint32(zCsr, &nSuffix);
    
    assert( nPrefix>=0 && nSuffix>=0 );
    if( nPrefix>zCsr-zNode || nSuffix>zEnd-zCsr ){
    if( nPrefix>zCsr-zNode || nSuffix>zEnd-zCsr || nSuffix==0 ){
      rc = FTS_CORRUPT_VTAB;
      goto finish_scan;
    }
    if( (i64)nPrefix+nSuffix>nAlloc ){
      char *zNew;
      nAlloc = ((i64)nPrefix+nSuffix) * 2;
      zNew = (char *)sqlite3_realloc64(zBuffer, nAlloc);
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
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
1991







-
+




-
+






-
-
+
+







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


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
1984
1985
1986
1987

1988
1989
1990
1991
1992
1993
1994
2022
2023
2024
2025
2026
2027
2028

2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053

2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071

2072
2073
2074
2075
2076
2077
2078
2079







-
+



















+
+
+
+
+
-
+
+
















-
+







  int rc = SQLITE_OK;             /* Return code */
  int iHeight;                    /* Height of this node in tree */

  assert( piLeaf || piLeaf2 );

  fts3GetVarint32(zNode, &iHeight);
  rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2);
  assert( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) );
  assert_fts3_nc( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) );

  if( rc==SQLITE_OK && iHeight>1 ){
    char *zBlob = 0;              /* Blob read from %_segments table */
    int nBlob = 0;                /* Size of zBlob in bytes */

    if( piLeaf && piLeaf2 && (*piLeaf!=*piLeaf2) ){
      rc = sqlite3Fts3ReadBlock(p, *piLeaf, &zBlob, &nBlob, 0);
      if( rc==SQLITE_OK ){
        rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, 0);
      }
      sqlite3_free(zBlob);
      piLeaf = 0;
      zBlob = 0;
    }

    if( rc==SQLITE_OK ){
      rc = sqlite3Fts3ReadBlock(p, piLeaf?*piLeaf:*piLeaf2, &zBlob, &nBlob, 0);
    }
    if( rc==SQLITE_OK ){
      int iNewHeight = 0;
      fts3GetVarint32(zBlob, &iNewHeight);
      if( iNewHeight>=iHeight ){
        rc = FTS_CORRUPT_VTAB;
      }else{
      rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, piLeaf2);
        rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, piLeaf2);
      }
    }
    sqlite3_free(zBlob);
  }

  return rc;
}

/*
** This function is used to create delta-encoded serialized lists of FTS3 
** varints. Each call to this function appends a single varint to a list.
*/
static void fts3PutDeltaVarint(
  char **pp,                      /* IN/OUT: Output pointer */
  sqlite3_int64 *piPrev,          /* IN/OUT: Previous value written to list */
  sqlite3_int64 iVal              /* Write this value to the list */
){
  assert( iVal-*piPrev > 0 || (*piPrev==0 && iVal==0) );
  assert_fts3_nc( iVal-*piPrev > 0 || (*piPrev==0 && iVal==0) );
  *pp += sqlite3Fts3PutVarint(*pp, iVal-*piPrev);
  *piPrev = iVal;
}

/*
** When this function is called, *ppPoslist is assumed to point to the 
** start of a position-list. After it returns, *ppPoslist points to the
2068
2069
2070
2071
2072
2073
2074
2075
2076



2077
2078

2079
2080
2081
2082
2083
2084
2085
2153
2154
2155
2156
2157
2158
2159


2160
2161
2162
2163

2164
2165
2166
2167
2168
2169
2170
2171







-
-
+
+
+

-
+







    p += n;
    *pp = p;
  }
  *ppPoslist = pEnd;
}

/*
** Value used to signify the end of an position-list. This is safe because
** it is not possible to have a document with 2^31 terms.
** Value used to signify the end of an position-list. This must be
** as large or larger than any value that might appear on the
** position-list, even a position list that has been corrupted.
*/
#define POSITION_LIST_END 0x7fffffff
#define POSITION_LIST_END LARGEST_INT64

/*
** This function is used to help parse position-lists. When this function is
** called, *pp may point to the start of the next varint in the position-list
** being parsed, or it may point to 1 byte past the end of the position-list
** (in which case **pp will be a terminator bytes POS_END (0) or
** (1)).
2096
2097
2098
2099
2100
2101
2102

2103


2104
2105
2106
2107
2108
2109
2110
2182
2183
2184
2185
2186
2187
2188
2189

2190
2191
2192
2193
2194
2195
2196
2197
2198







+
-
+
+







** the next position.
*/
static void fts3ReadNextPos(
  char **pp,                    /* IN/OUT: Pointer into position-list buffer */
  sqlite3_int64 *pi             /* IN/OUT: Value read from position-list */
){
  if( (**pp)&0xFE ){
    int iVal;
    fts3GetDeltaVarint(pp, pi);
    *pp += fts3GetVarint32((*pp), &iVal);
    *pi += iVal;
    *pi -= 2;
  }else{
    *pi = POSITION_LIST_END;
  }
}

/*
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
2218
2219
2220
2221
2222
2223
2224

2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237


2238
2239
2240
2241
2242
2243
2244


2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256







-
+












-
-
+
+
+
+
+


-
-
+
+
+
+
+







/*
** Compute the union of two position lists.  The output written
** into *pp contains all positions of both *pp1 and *pp2 in sorted
** order and with any duplicates removed.  All pointers are
** updated appropriately.   The caller is responsible for insuring
** that there is enough space in *pp to hold the complete output.
*/
static void fts3PoslistMerge(
static int fts3PoslistMerge(
  char **pp,                      /* Output buffer */
  char **pp1,                     /* Left input list */
  char **pp2                      /* Right input list */
){
  char *p = *pp;
  char *p1 = *pp1;
  char *p2 = *pp2;

  while( *p1 || *p2 ){
    int iCol1;         /* The current column index in pp1 */
    int iCol2;         /* The current column index in pp2 */

    if( *p1==POS_COLUMN ) fts3GetVarint32(&p1[1], &iCol1);
    else if( *p1==POS_END ) iCol1 = POSITION_LIST_END;
    if( *p1==POS_COLUMN ){ 
      fts3GetVarint32(&p1[1], &iCol1);
      if( iCol1==0 ) return FTS_CORRUPT_VTAB;
    }
    else if( *p1==POS_END ) iCol1 = 0x7fffffff;
    else iCol1 = 0;

    if( *p2==POS_COLUMN ) fts3GetVarint32(&p2[1], &iCol2);
    else if( *p2==POS_END ) iCol2 = POSITION_LIST_END;
    if( *p2==POS_COLUMN ){
      fts3GetVarint32(&p2[1], &iCol2);
      if( iCol2==0 ) return FTS_CORRUPT_VTAB;
    }
    else if( *p2==POS_END ) iCol2 = 0x7fffffff;
    else iCol2 = 0;

    if( iCol1==iCol2 ){
      sqlite3_int64 i1 = 0;       /* Last position from pp1 */
      sqlite3_int64 i2 = 0;       /* Last position from pp2 */
      sqlite3_int64 iPrev = 0;
      int n = fts3PutColNumber(&p, iCol1);
2170
2171
2172
2173
2174
2175
2176



2177
2178
2179
2180
2181
2182
2183
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280







+
+
+







      ** POS_END (0) or POS_COLUMN (1). The following block merges the two lists
      ** and writes the results to buffer p. p is left pointing to the byte
      ** after the list written. No terminator (POS_END or POS_COLUMN) is
      ** written to the output.
      */
      fts3GetDeltaVarint(&p1, &i1);
      fts3GetDeltaVarint(&p2, &i2);
      if( i1<2 || i2<2 ){
        break;
      }
      do {
        fts3PutDeltaVarint(&p, &iPrev, (i1<i2) ? i1 : i2); 
        iPrev -= 2;
        if( i1==i2 ){
          fts3ReadNextPos(&p1, &i1);
          fts3ReadNextPos(&p2, &i2);
        }else if( i1<i2 ){
2195
2196
2197
2198
2199
2200
2201

2202
2203
2204
2205
2206
2207
2208
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306







+







    }
  }

  *p++ = POS_END;
  *pp = p;
  *pp1 = p1 + 1;
  *pp2 = p2 + 1;
  return SQLITE_OK;
}

/*
** This function is used to merge two position lists into one. When it is
** called, *pp1 and *pp2 must both point to position lists. A position-list is
** the part of a doclist that follows each document id. For example, if a row
** contains:
2237
2238
2239
2240
2241
2242
2243
2244

2245
2246
2247
2248
2249
2250
2251
2335
2336
2337
2338
2339
2340
2341

2342
2343
2344
2345
2346
2347
2348
2349







-
+







  char *p2 = *pp2;
  int iCol1 = 0;
  int iCol2 = 0;

  /* Never set both isSaveLeft and isExact for the same invocation. */
  assert( isSaveLeft==0 || isExact==0 );

  assert( p!=0 && *p1!=0 && *p2!=0 );
  assert_fts3_nc( p!=0 && *p1!=0 && *p2!=0 );
  if( *p1==POS_COLUMN ){ 
    p1++;
    p1 += fts3GetVarint32(p1, &iCol1);
  }
  if( *p2==POS_COLUMN ){ 
    p2++;
    p2 += fts3GetVarint32(p2, &iCol2);
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269

2270
2271
2272
2273
2274
2275
2276
2357
2358
2359
2360
2361
2362
2363


2364
2365
2366
2367
2368
2369
2370
2371
2372
2373







-
-


+







      sqlite3_int64 iPos2 = 0;

      if( iCol1 ){
        *p++ = POS_COLUMN;
        p += sqlite3Fts3PutVarint(p, iCol1);
      }

      assert( *p1!=POS_END && *p1!=POS_COLUMN );
      assert( *p2!=POS_END && *p2!=POS_COLUMN );
      fts3GetDeltaVarint(&p1, &iPos1); iPos1 -= 2;
      fts3GetDeltaVarint(&p2, &iPos2); iPos2 -= 2;
      if( iPos1<0 || iPos2<0 ) break;

      while( 1 ){
        if( iPos2==iPos1+nToken 
         || (isExact==0 && iPos2>iPos1 && iPos2<=iPos1+nToken) 
        ){
          sqlite3_int64 iSave;
          iSave = isSaveLeft ? iPos1 : iPos2;
2411
2412
2413
2414
2415
2416
2417
2418
2419


2420
2421

2422
2423

2424
2425
2426
2427
2428
2429
2430
2508
2509
2510
2511
2512
2513
2514


2515
2516
2517

2518
2519

2520
2521
2522
2523
2524
2525
2526
2527







-
-
+
+

-
+

-
+







  char *pEnd,                     /* End of buffer */
  int bDescIdx,                   /* True if docids are descending */
  sqlite3_int64 *pVal             /* IN/OUT: Integer value */
){
  if( *pp>=pEnd ){
    *pp = 0;
  }else{
    sqlite3_int64 iVal;
    *pp += sqlite3Fts3GetVarint(*pp, &iVal);
    u64 iVal;
    *pp += sqlite3Fts3GetVarintU(*pp, &iVal);
    if( bDescIdx ){
      *pVal -= iVal;
      *pVal = (i64)((u64)*pVal - iVal);
    }else{
      *pVal += iVal;
      *pVal = (i64)((u64)*pVal + iVal);
    }
  }
}

/*
** This function is used to write a single varint to a buffer. The varint
** is written to *pp. Before returning, *pp is set to point 1 byte past the
2443
2444
2445
2446
2447
2448
2449
2450

2451

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
2540
2541
2542
2543
2544
2545
2546

2547
2548
2549

2550
2551
2552

2553
2554
2555

2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572

2573
2574
2575
2576
2577
2578
2579
2580







-
+

+
-
+

+
-
+


-
+















+
-
+







static void fts3PutDeltaVarint3(
  char **pp,                      /* IN/OUT: Output pointer */
  int bDescIdx,                   /* True for descending docids */
  sqlite3_int64 *piPrev,          /* IN/OUT: Previous value written to list */
  int *pbFirst,                   /* IN/OUT: True after first int written */
  sqlite3_int64 iVal              /* Write this value to the list */
){
  sqlite3_int64 iWrite;
  sqlite3_uint64 iWrite;
  if( bDescIdx==0 || *pbFirst==0 ){
    assert_fts3_nc( *pbFirst==0 || iVal>=*piPrev );
    iWrite = iVal - *piPrev;
    iWrite = (u64)iVal - (u64)*piPrev;
  }else{
    assert_fts3_nc( *piPrev>=iVal );
    iWrite = *piPrev - iVal;
    iWrite = (u64)*piPrev - (u64)iVal;
  }
  assert( *pbFirst || *piPrev==0 );
  assert( *pbFirst==0 || iWrite>0 );
  assert_fts3_nc( *pbFirst==0 || iWrite>0 );
  *pp += sqlite3Fts3PutVarint(*pp, iWrite);
  *piPrev = iVal;
  *pbFirst = 1;
}


/*
** This macro is used by various functions that merge doclists. The two
** arguments are 64-bit docid values. If the value of the stack variable
** bDescDoclist is 0 when this macro is invoked, then it returns (i1-i2). 
** Otherwise, (i2-i1).
**
** Using this makes it easier to write code that can merge doclists that are
** sorted in either ascending or descending order.
*/
/* #define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i64)((u64)i1-i2)) */
#define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i1-i2))
#define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i1>i2?1:((i1==i2)?0:-1)))

/*
** This function does an "OR" merge of two doclists (output contains all
** positions contained in either argument doclist). If the docids in the 
** input doclists are sorted in ascending order, parameter bDescDoclist
** should be false. If they are sorted in ascending order, it should be
** passed a non-zero value.
2488
2489
2490
2491
2492
2493
2494

2495
2496
2497
2498
2499
2500
2501
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602







+







*/
static int fts3DoclistOrMerge(
  int bDescDoclist,               /* True if arguments are desc */
  char *a1, int n1,               /* First doclist */
  char *a2, int n2,               /* Second doclist */
  char **paOut, int *pnOut        /* OUT: Malloc'd doclist */
){
  int rc = SQLITE_OK;
  sqlite3_int64 i1 = 0;
  sqlite3_int64 i2 = 0;
  sqlite3_int64 iPrev = 0;
  char *pEnd1 = &a1[n1];
  char *pEnd2 = &a2[n2];
  char *p1 = a1;
  char *p2 = a2;
2531
2532
2533
2534
2535
2536
2537
2538

2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549


2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562











2563
2564
2565
2566

2567
2568
2569
2570
2571
2572
2573
2632
2633
2634
2635
2636
2637
2638

2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649

2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662


2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675


2676
2677
2678
2679
2680
2681
2682
2683







-
+










-
+
+











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


-
-
+







  ** The space required to store the output is therefore the sum of the
  ** sizes of the two inputs, plus enough space for exactly one of the input
  ** docids to grow. 
  **
  ** A symetric argument may be made if the doclists are in descending 
  ** order.
  */
  aOut = sqlite3_malloc(n1+n2+FTS3_VARINT_MAX-1);
  aOut = sqlite3_malloc64((i64)n1+n2+FTS3_VARINT_MAX-1+FTS3_BUFFER_PADDING);
  if( !aOut ) return SQLITE_NOMEM;

  p = aOut;
  fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
  fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);
  while( p1 || p2 ){
    sqlite3_int64 iDiff = DOCID_CMP(i1, i2);

    if( p2 && p1 && iDiff==0 ){
      fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1);
      fts3PoslistMerge(&p, &p1, &p2);
      rc = fts3PoslistMerge(&p, &p1, &p2);
      if( rc ) break;
      fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
      fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
    }else if( !p2 || (p1 && iDiff<0) ){
      fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1);
      fts3PoslistCopy(&p, &p1);
      fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
    }else{
      fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i2);
      fts3PoslistCopy(&p, &p2);
      fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
    }
  }

    
    assert( (p-aOut)<=((p1?(p1-a1):n1)+(p2?(p2-a2):n2)+FTS3_VARINT_MAX-1) );
  }

  if( rc!=SQLITE_OK ){
    sqlite3_free(aOut);
    p = aOut = 0;
  }else{
    assert( (p-aOut)<=n1+n2+FTS3_VARINT_MAX-1 );
    memset(&aOut[(p-aOut)], 0, FTS3_BUFFER_PADDING);
  }
  *paOut = aOut;
  *pnOut = (int)(p-aOut);
  assert( *pnOut<=n1+n2+FTS3_VARINT_MAX-1 );
  return SQLITE_OK;
  return rc;
}

/*
** This function does a "phrase" merge of two doclists. In a phrase merge,
** the output contains a copy of each position from the right-hand input
** doclist for which there is a position in the left-hand input doclist
** exactly nDist tokens before it.
2594
2595
2596
2597
2598
2599
2600
2601

2602
2603
2604
2605
2606
2607
2608
2704
2705
2706
2707
2708
2709
2710

2711
2712
2713
2714
2715
2716
2717
2718







-
+







  char *p2 = aRight;
  char *p;
  int bFirstOut = 0;
  char *aOut;

  assert( nDist>0 );
  if( bDescDoclist ){
    aOut = sqlite3_malloc(*pnRight + FTS3_VARINT_MAX);
    aOut = sqlite3_malloc64((sqlite3_int64)*pnRight + FTS3_VARINT_MAX);
    if( aOut==0 ) return SQLITE_NOMEM;
  }else{
    aOut = aRight;
  }
  p = aOut;

  fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
2774
2775
2776
2777
2778
2779
2780
2781

2782
2783
2784

2785
2786
2787
2788
2789
2790
2791
2884
2885
2886
2887
2888
2889
2890

2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902







-
+



+







    ** not true for order=DESC. For example, a doclist containing (1, -1) 
    ** may be smaller than (-1), as in the first example the -1 may be stored
    ** as a single-byte delta, whereas in the second it must be stored as a
    ** FTS3_VARINT_MAX byte varint.
    **
    ** Similar padding is added in the fts3DoclistOrMerge() function.
    */
    pTS->aaOutput[0] = sqlite3_malloc(nDoclist + FTS3_VARINT_MAX + 1);
    pTS->aaOutput[0] = sqlite3_malloc64((i64)nDoclist + FTS3_VARINT_MAX + 1);
    pTS->anOutput[0] = nDoclist;
    if( pTS->aaOutput[0] ){
      memcpy(pTS->aaOutput[0], aDoclist, nDoclist);
      memset(&pTS->aaOutput[0][nDoclist], 0, FTS3_VARINT_MAX);
    }else{
      return SQLITE_NOMEM;
    }
  }else{
    char *aMerge = aDoclist;
    int nMerge = nDoclist;
    int iOut;
2829
2830
2831
2832
2833
2834
2835
2836
2837


2838
2839
2840
2841
2842
2843
2844
2940
2941
2942
2943
2944
2945
2946


2947
2948
2949
2950
2951
2952
2953
2954
2955







-
-
+
+







*/
static int fts3SegReaderCursorAppend(
  Fts3MultiSegReader *pCsr, 
  Fts3SegReader *pNew
){
  if( (pCsr->nSegment%16)==0 ){
    Fts3SegReader **apNew;
    int nByte = (pCsr->nSegment + 16)*sizeof(Fts3SegReader*);
    apNew = (Fts3SegReader **)sqlite3_realloc(pCsr->apSegment, nByte);
    sqlite3_int64 nByte = (pCsr->nSegment + 16)*sizeof(Fts3SegReader*);
    apNew = (Fts3SegReader **)sqlite3_realloc64(pCsr->apSegment, nByte);
    if( !apNew ){
      sqlite3Fts3SegReaderFree(pNew);
      return SQLITE_NOMEM;
    }
    pCsr->apSegment = apNew;
  }
  pCsr->apSegment[pCsr->nSegment++] = pNew;
2869
2870
2871
2872
2873
2874
2875
2876

2877
2878
2879
2880
2881
2882
2883
2980
2981
2982
2983
2984
2985
2986

2987
2988
2989
2990
2991
2992
2993
2994







-
+








  /* If iLevel is less than 0 and this is not a scan, include a seg-reader 
  ** for the pending-terms. If this is a scan, then this call must be being
  ** made by an fts4aux module, not an FTS table. In this case calling
  ** Fts3SegReaderPending might segfault, as the data structures used by 
  ** fts4aux are not completely populated. So it's easiest to filter these
  ** calls out here.  */
  if( iLevel<0 && p->aIndex ){
  if( iLevel<0 && p->aIndex && p->iPrevLangid==iLangid ){
    Fts3SegReader *pSeg = 0;
    rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix||isScan, &pSeg);
    if( rc==SQLITE_OK && pSeg ){
      rc = fts3SegReaderCursorAppend(pCsr, pSeg);
    }
  }

2894
2895
2896
2897
2898
2899
2900
2901

2902
2903
2904
2905
2906
2907
2908
3005
3006
3007
3008
3009
3010
3011

3012
3013
3014
3015
3016
3017
3018
3019







-
+







      sqlite3_int64 iLeavesEndBlock = sqlite3_column_int64(pStmt, 2);
      sqlite3_int64 iEndBlock = sqlite3_column_int64(pStmt, 3);
      int nRoot = sqlite3_column_bytes(pStmt, 4);
      char const *zRoot = sqlite3_column_blob(pStmt, 4);

      /* If zTerm is not NULL, and this segment is not stored entirely on its
      ** root node, the range of leaves scanned can be reduced. Do this. */
      if( iStartBlock && zTerm ){
      if( iStartBlock && zTerm && zRoot ){
        sqlite3_int64 *pi = (isPrefix ? &iLeavesEndBlock : 0);
        rc = fts3SelectLeaf(p, zTerm, nTerm, zRoot, nRoot, &iStartBlock, pi);
        if( rc!=SQLITE_OK ) goto finished;
        if( isPrefix==0 && isScan==0 ) iLeavesEndBlock = iStartBlock;
      }
 
      rc = sqlite3Fts3SegReaderNew(pCsr->nSegment+1, 
3132
3133
3134
3135
3136
3137
3138


3139
3140
3141
3142
3143
3144
3145

3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266












3267
3268
3269
3270
3271
3272
3273







+
+







+







-
-
-
-
-
-
-
-
-
-
-
-







** even if we reach end-of-file.  The fts3EofMethod() will be called
** subsequently to determine whether or not an EOF was hit.
*/
static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){
  int rc;
  Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
  if( pCsr->eSearch==FTS3_DOCID_SEARCH || pCsr->eSearch==FTS3_FULLSCAN_SEARCH ){
    Fts3Table *pTab = (Fts3Table*)pCursor->pVtab;
    pTab->bLock++;
    if( SQLITE_ROW!=sqlite3_step(pCsr->pStmt) ){
      pCsr->isEof = 1;
      rc = sqlite3_reset(pCsr->pStmt);
    }else{
      pCsr->iPrevId = sqlite3_column_int64(pCsr->pStmt, 0);
      rc = SQLITE_OK;
    }
    pTab->bLock--;
  }else{
    rc = fts3EvalNext((Fts3Cursor *)pCursor);
  }
  assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
  return rc;
}

/*
** The following are copied from sqliteInt.h.
**
** Constants for the largest and smallest possible 64-bit signed integers.
** These macros are designed to work correctly on both 32-bit and 64-bit
** compilers.
*/
#ifndef SQLITE_AMALGAMATION
# define LARGEST_INT64  (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32))
# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64)
#endif

/*
** If the numeric type of argument pVal is "integer", then return it
** converted to a 64-bit signed integer. Otherwise, return a copy of
** the second parameter, iDefault.
*/
static sqlite3_int64 fts3DocidRange(sqlite3_value *pVal, i64 iDefault){
  if( pVal ){
3210
3211
3212
3213
3214
3215
3216




3217
3218
3219
3220
3221
3222
3223
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329







+
+
+
+







  sqlite3_value *pLangid = 0;     /* The "langid = ?" constraint, if any */
  sqlite3_value *pDocidGe = 0;    /* The "docid >= ?" constraint, if any */
  sqlite3_value *pDocidLe = 0;    /* The "docid <= ?" constraint, if any */
  int iIdx;

  UNUSED_PARAMETER(idxStr);
  UNUSED_PARAMETER(nVal);

  if( p->bLock ){
    return SQLITE_ERROR;
  }

  eSearch = (idxNum & 0x0000FFFF);
  assert( eSearch>=0 && eSearch<=(FTS3_FULLTEXT_SEARCH+p->nColumn) );
  assert( p->pSegments==0 );

  /* Collect arguments into local variables */
  iIdx = 0;
3282
3283
3284
3285
3286
3287
3288


3289



3290
3291
3292
3293
3294
3295
3296
3388
3389
3390
3391
3392
3393
3394
3395
3396

3397
3398
3399
3400
3401
3402
3403
3404
3405
3406







+
+
-
+
+
+







      );
    }else{
      zSql = sqlite3_mprintf("SELECT %s ORDER BY rowid %s", 
          p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC")
      );
    }
    if( zSql ){
      p->bLock++;
      rc = sqlite3_prepare_v3(
      rc = sqlite3_prepare_v3(p->db,zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0);
          p->db,zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0
      );
      p->bLock--;
      sqlite3_free(zSql);
    }else{
      rc = SQLITE_NOMEM;
    }
  }else if( eSearch==FTS3_DOCID_SEARCH ){
    rc = fts3CursorSeekStmt(pCsr);
    if( rc==SQLITE_OK ){
3366
3367
3368
3369
3370
3371
3372
3373

3374
3375
3376
3377
3378
3379
3380
3476
3477
3478
3479
3480
3481
3482

3483
3484
3485
3486
3487
3488
3489
3490







-
+







        sqlite3_result_int64(pCtx, pCsr->iLangid);
        break;
      }else if( p->zLanguageid==0 ){
        sqlite3_result_int(pCtx, 0);
        break;
      }else{
        iCol = p->nColumn;
        /* fall-through */
        /* no break */ deliberate_fall_through
      }

    default:
      /* A user column. Or, if this is a full-table scan, possibly the
      ** language-id column. Seek the cursor. */
      rc = fts3CursorSeek(0, pCsr);
      if( rc==SQLITE_OK && sqlite3_data_count(pCsr->pStmt)-1>iCol ){
3473
3474
3475
3476
3477
3478
3479

3480
3481
3482
3483




3484
3485


3486
3487



3488
3489
3490
3491
3492
3493
3494
3583
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







+




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







}

/*
** 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().
*/
3609
3610
3611
3612
3613
3614
3615

3616

3617

3618

3619
3620
3621
3622
3623
3624
3625
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745







+

+

+

+







        "wrong number of arguments to function snippet()", -1);
    return;
  }
  if( fts3FunctionArg(pContext, "snippet", apVal[0], &pCsr) ) return;

  switch( nVal ){
    case 6: nToken = sqlite3_value_int(apVal[5]);
            /* no break */ deliberate_fall_through
    case 5: iCol = sqlite3_value_int(apVal[4]);
            /* no break */ deliberate_fall_through
    case 4: zEllipsis = (const char*)sqlite3_value_text(apVal[3]);
            /* no break */ deliberate_fall_through
    case 3: zEnd = (const char*)sqlite3_value_text(apVal[2]);
            /* no break */ deliberate_fall_through
    case 2: zStart = (const char*)sqlite3_value_text(apVal[1]);
  }
  if( !zEllipsis || !zEnd || !zStart ){
    sqlite3_result_error_nomem(pContext);
  }else if( nToken==0 ){
    sqlite3_result_text(pContext, "", -1, SQLITE_STATIC);
  }else if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3956
3957
3958
3959
3960
3961
3962

3963
3964
3965
3966
3967
3968
3969







-







**
** Discard the contents of the pending terms table.
*/
static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
  Fts3Table *p = (Fts3Table*)pVtab;
  UNUSED_PARAMETER(iSavepoint);
  assert( p->inTransaction );
  assert( p->mxSavepoint >= iSavepoint );
  TESTONLY( p->mxSavepoint = iSavepoint );
  sqlite3Fts3PendingTermsClear(p);
  return SQLITE_OK;
}

/*
** Return true if zName is the extension on one of the shadow tables used
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899






3900
3901
3902
3903
3904
3905
3906
4009
4010
4011
4012
4013
4014
4015



4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028







-
-
-
+
+
+
+
+
+








/*
** This function is registered as the module destructor (called when an
** FTS3 enabled database connection is closed). It frees the memory
** allocated for the tokenizer hash table.
*/
static void hashDestroy(void *p){
  Fts3Hash *pHash = (Fts3Hash *)p;
  sqlite3Fts3HashClear(pHash);
  sqlite3_free(pHash);
  Fts3HashWrapper *pHash = (Fts3HashWrapper *)p;
  pHash->nRef--;
  if( pHash->nRef<=0 ){
    sqlite3Fts3HashClear(&pHash->hash);
    sqlite3_free(pHash);
  }
}

/*
** The fts3 built-in tokenizers - "simple", "porter" and "icu"- are 
** implemented in files fts3_tokenizer1.c, fts3_porter.c and fts3_icu.c
** respectively. The following three forward declarations are for functions
** declared in these files used to retrieve the respective implementations.
3922
3923
3924
3925
3926
3927
3928
3929

3930
3931
3932
3933
3934
3935
3936
4044
4045
4046
4047
4048
4049
4050

4051
4052
4053
4054
4055
4056
4057
4058







-
+







** Initialize the fts3 extension. If this extension is built as part
** of the sqlite library, then this function is called directly by
** SQLite. If fts3 is built as a dynamically loadable extension, this
** function is called by the sqlite3_extension_init() entry point.
*/
int sqlite3Fts3Init(sqlite3 *db){
  int rc = SQLITE_OK;
  Fts3Hash *pHash = 0;
  Fts3HashWrapper *pHash = 0;
  const sqlite3_tokenizer_module *pSimple = 0;
  const sqlite3_tokenizer_module *pPorter = 0;
#ifndef SQLITE_DISABLE_FTS3_UNICODE
  const sqlite3_tokenizer_module *pUnicode = 0;
#endif

#ifdef SQLITE_ENABLE_ICU
3950
3951
3952
3953
3954
3955
3956
3957

3958
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
4000
4001

4002
4003

4004
4005
4006

4007

4008
4009
4010
4011
4012
4013
4014
4015
4016

4017
4018
4019
4020
4021
4022
4023
4072
4073
4074
4075
4076
4077
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
4107
4108
4109
4110
4111
4112
4113

4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127

4128
4129
4130
4131
4132

4133
4134
4135
4136
4137
4138
4139
4140
4141

4142
4143
4144
4145
4146
4147
4148
4149







-
+



-
+
+




-
-
+
+


-
+


-
+








-
+








-
+






+




+

-
+



+
-
+








-
+







  rc = sqlite3Fts3InitAux(db);
  if( rc!=SQLITE_OK ) return rc;

  sqlite3Fts3SimpleTokenizerModule(&pSimple);
  sqlite3Fts3PorterTokenizerModule(&pPorter);

  /* Allocate and initialize the hash-table used to store tokenizers. */
  pHash = sqlite3_malloc(sizeof(Fts3Hash));
  pHash = sqlite3_malloc(sizeof(Fts3HashWrapper));
  if( !pHash ){
    rc = SQLITE_NOMEM;
  }else{
    sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1);
    sqlite3Fts3HashInit(&pHash->hash, FTS3_HASH_STRING, 1);
    pHash->nRef = 0;
  }

  /* Load the built-in tokenizers into the hash table */
  if( rc==SQLITE_OK ){
    if( sqlite3Fts3HashInsert(pHash, "simple", 7, (void *)pSimple)
     || sqlite3Fts3HashInsert(pHash, "porter", 7, (void *)pPorter) 
    if( sqlite3Fts3HashInsert(&pHash->hash, "simple", 7, (void *)pSimple)
     || sqlite3Fts3HashInsert(&pHash->hash, "porter", 7, (void *)pPorter) 

#ifndef SQLITE_DISABLE_FTS3_UNICODE
     || sqlite3Fts3HashInsert(pHash, "unicode61", 10, (void *)pUnicode) 
     || sqlite3Fts3HashInsert(&pHash->hash, "unicode61", 10, (void *)pUnicode) 
#endif
#ifdef SQLITE_ENABLE_ICU
     || (pIcu && sqlite3Fts3HashInsert(pHash, "icu", 4, (void *)pIcu))
     || (pIcu && sqlite3Fts3HashInsert(&pHash->hash, "icu", 4, (void *)pIcu))
#endif
    ){
      rc = SQLITE_NOMEM;
    }
  }

#ifdef SQLITE_TEST
  if( rc==SQLITE_OK ){
    rc = sqlite3Fts3ExprInitTestInterface(db, pHash);
    rc = sqlite3Fts3ExprInitTestInterface(db, &pHash->hash);
  }
#endif

  /* Create the virtual table wrapper around the hash-table and overload 
  ** the four scalar functions. If this is successful, register the
  ** module with sqlite.
  */
  if( SQLITE_OK==rc 
   && SQLITE_OK==(rc = sqlite3Fts3InitHashTable(db, pHash, "fts3_tokenizer"))
   && SQLITE_OK==(rc=sqlite3Fts3InitHashTable(db,&pHash->hash,"fts3_tokenizer"))
   && SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1))
   && SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", 1))
   && SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 1))
   && SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 2))
   && SQLITE_OK==(rc = sqlite3_overload_function(db, "optimize", 1))
  ){
    pHash->nRef++;
    rc = sqlite3_create_module_v2(
        db, "fts3", &fts3Module, (void *)pHash, hashDestroy
    );
    if( rc==SQLITE_OK ){
      pHash->nRef++;
      rc = sqlite3_create_module_v2(
          db, "fts4", &fts3Module, (void *)pHash, 0
          db, "fts4", &fts3Module, (void *)pHash, hashDestroy
      );
    }
    if( rc==SQLITE_OK ){
      pHash->nRef++;
      rc = sqlite3Fts3InitTok(db, (void *)pHash);
      rc = sqlite3Fts3InitTok(db, (void *)pHash, hashDestroy);
    }
    return rc;
  }


  /* An error has occurred. Delete the hash table and return the error code. */
  assert( rc!=SQLITE_OK );
  if( pHash ){
    sqlite3Fts3HashClear(pHash);
    sqlite3Fts3HashClear(&pHash->hash);
    sqlite3_free(pHash);
  }
  return rc;
}

/*
** Allocate an Fts3MultiSegReader for each token in the expression headed
4178
4179
4180
4181
4182
4183
4184
4185
4186

4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199

4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219

4220
4221
4222
4223
4224
4225
4226
4304
4305
4306
4307
4308
4309
4310


4311
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







-
-
+













+




















+







** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
*/
static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
  int iToken;                     /* Used to iterate through phrase tokens */
  char *aPoslist = 0;             /* Position list for deferred tokens */
  int nPoslist = 0;               /* Number of bytes in aPoslist */
  int iPrev = -1;                 /* Token number of previous deferred token */

  assert( pPhrase->doclist.bFreeList==0 );
  char *aFree = (pPhrase->doclist.bFreeList ? pPhrase->doclist.pList : 0);

  for(iToken=0; iToken<pPhrase->nToken; iToken++){
    Fts3PhraseToken *pToken = &pPhrase->aToken[iToken];
    Fts3DeferredToken *pDeferred = pToken->pDeferred;

    if( pDeferred ){
      char *pList;
      int nList;
      int rc = sqlite3Fts3DeferredTokenList(pDeferred, &pList, &nList);
      if( rc!=SQLITE_OK ) return rc;

      if( pList==0 ){
        sqlite3_free(aPoslist);
        sqlite3_free(aFree);
        pPhrase->doclist.pList = 0;
        pPhrase->doclist.nList = 0;
        return SQLITE_OK;

      }else if( aPoslist==0 ){
        aPoslist = pList;
        nPoslist = nList;

      }else{
        char *aOut = pList;
        char *p1 = aPoslist;
        char *p2 = aOut;

        assert( iPrev>=0 );
        fts3PoslistPhraseMerge(&aOut, iToken-iPrev, 0, 1, &p1, &p2);
        sqlite3_free(aPoslist);
        aPoslist = pList;
        nPoslist = (int)(aOut - aPoslist);
        if( nPoslist==0 ){
          sqlite3_free(aPoslist);
          sqlite3_free(aFree);
          pPhrase->doclist.pList = 0;
          pPhrase->doclist.nList = 0;
          return SQLITE_OK;
        }
      }
      iPrev = iToken;
    }
4245
4246
4247
4248
4249
4250
4251
4252

4253
4254
4255
4256
4257
4258

4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270

4271
4272
4273
4274
4275
4276
4277
4372
4373
4374
4375
4376
4377
4378

4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406







-
+






+












+







        nDistance = nMaxUndeferred - iPrev;
      }else{
        p1 = pPhrase->doclist.pList;
        p2 = aPoslist;
        nDistance = iPrev - nMaxUndeferred;
      }

      aOut = (char *)sqlite3_malloc(nPoslist+8);
      aOut = (char *)sqlite3Fts3MallocZero(nPoslist+FTS3_BUFFER_PADDING);
      if( !aOut ){
        sqlite3_free(aPoslist);
        return SQLITE_NOMEM;
      }
      
      pPhrase->doclist.pList = aOut;
      assert( p1 && p2 );
      if( fts3PoslistPhraseMerge(&aOut, nDistance, 0, 1, &p1, &p2) ){
        pPhrase->doclist.bFreeList = 1;
        pPhrase->doclist.nList = (int)(aOut - pPhrase->doclist.pList);
      }else{
        sqlite3_free(aOut);
        pPhrase->doclist.pList = 0;
        pPhrase->doclist.nList = 0;
      }
      sqlite3_free(aPoslist);
    }
  }

  if( pPhrase->doclist.pList!=aFree ) sqlite3_free(aFree);
  return SQLITE_OK;
}
#endif /* SQLITE_DISABLE_FTS4_DEFERRED */

/*
** Maximum number of tokens a phrase may have to be considered for the
** incremental doclists strategy.
4300
4301
4302
4303
4304
4305
4306
4307

4308
4309
4310
4311
4312
4313
4314
4429
4430
4431
4432
4433
4434
4435

4436
4437
4438
4439
4440
4441
4442
4443







-
+







  ** scanned in forward order, and the phrase consists of 
  ** MAX_INCR_PHRASE_TOKENS or fewer tokens, none of which are are "^first"
  ** tokens or prefix tokens that cannot use a prefix-index.  */
  int bHaveIncr = 0;
  int bIncrOk = (bOptOk 
   && pCsr->bDesc==pTab->bDescIdx 
   && p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0
#ifdef SQLITE_TEST
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
   && pTab->bNoIncrDoclist==0
#endif
  );
  for(i=0; bIncrOk==1 && i<p->nToken; i++){
    Fts3PhraseToken *pToken = &p->aToken[i];
    if( pToken->bFirst || (pToken->pSegcsr!=0 && !pToken->pSegcsr->bLookup) ){
      bIncrOk = 0;
4356
4357
4358
4359
4360
4361
4362
4363

4364
4365
4366
4367
4368
4369
4370
4485
4486
4487
4488
4489
4490
4491

4492
4493
4494
4495
4496
4497
4498
4499







-
+







  int *pnList,                    /* OUT: List length pointer */
  u8 *pbEof                       /* OUT: End-of-file flag */
){
  char *p = *ppIter;

  assert( nDoclist>0 );
  assert( *pbEof==0 );
  assert( p || *piDocid==0 );
  assert_fts3_nc( p || *piDocid==0 );
  assert( !p || (p>aDoclist && p<&aDoclist[nDoclist]) );

  if( p==0 ){
    sqlite3_int64 iDocid = 0;
    char *pNext = 0;
    char *pDocid = aDoclist;
    char *pEnd = &aDoclist[nDoclist];
4411
4412
4413
4414
4415
4416
4417
4418

4419
4420
4421
4422
4423
4424
4425
4540
4541
4542
4543
4544
4545
4546

4547
4548
4549
4550
4551
4552
4553
4554







-
+







  sqlite3_int64 *piDocid,         /* IN/OUT: Docid pointer */
  u8 *pbEof                       /* OUT: End-of-file flag */
){
  char *p = *ppIter;

  assert( nDoclist>0 );
  assert( *pbEof==0 );
  assert( p || *piDocid==0 );
  assert_fts3_nc( p || *piDocid==0 );
  assert( !p || (p>=aDoclist && p<=&aDoclist[nDoclist]) );

  if( p==0 ){
    p = aDoclist;
    p += sqlite3Fts3GetVarint(p, piDocid);
  }else{
    fts3PoslistCopy(0, &p);
4442
4443
4444
4445
4446
4447
4448
4449

4450
4451
4452

4453
4454
4455
4456
4457

4458
4459
4460
4461
4462
4463
4464
4571
4572
4573
4574
4575
4576
4577

4578
4579
4580
4581
4582
4583
4584
4585
4586

4587
4588
4589
4590
4591
4592
4593
4594







-
+



+




-
+







*/
static void fts3EvalDlPhraseNext(
  Fts3Table *pTab,
  Fts3Doclist *pDL,
  u8 *pbEof
){
  char *pIter;                            /* Used to iterate through aAll */
  char *pEnd = &pDL->aAll[pDL->nAll];     /* 1 byte past end of aAll */
  char *pEnd;                             /* 1 byte past end of aAll */
 
  if( pDL->pNextDocid ){
    pIter = pDL->pNextDocid;
    assert( pDL->aAll!=0 || pIter==0 );
  }else{
    pIter = pDL->aAll;
  }

  if( pIter>=pEnd ){
  if( pIter==0 || pIter>=(pEnd = pDL->aAll + pDL->nAll) ){
    /* We have already reached the end of this doclist. EOF. */
    *pbEof = 1;
  }else{
    sqlite3_int64 iDelta;
    pIter += sqlite3Fts3GetVarint(pIter, &iDelta);
    if( pTab->bDescIdx==0 || pDL->pNextDocid==0 ){
      pDL->iDocid += iDelta;
4611
4612
4613
4614
4615
4616
4617
4618

4619
4620

4621
4622
4623
4624
4625
4626
4627
4741
4742
4743
4744
4745
4746
4747

4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758







-
+


+







        }
      }

      /* Check if the current entries really are a phrase match */
      if( bEof==0 ){
        int nList = 0;
        int nByte = a[p->nToken-1].nList;
        char *aDoclist = sqlite3_malloc(nByte+1);
        char *aDoclist = sqlite3_malloc64((i64)nByte+FTS3_BUFFER_PADDING);
        if( !aDoclist ) return SQLITE_NOMEM;
        memcpy(aDoclist, a[p->nToken-1].pList, nByte+1);
        memset(&aDoclist[nByte], 0, FTS3_BUFFER_PADDING);

        for(i=0; i<(p->nToken-1); i++){
          if( a[i].bIgnore==0 ){
            char *pL = a[i].pList;
            char *pR = aDoclist;
            char *pOut = aDoclist;
            int nDist = p->nToken-1-i;
4821
4822
4823
4824
4825
4826
4827

4828

4829
4830
4831
4832
4833





4834
4835
4836
4837
4838
4839
4840
4952
4953
4954
4955
4956
4957
4958
4959

4960





4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972







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







    sqlite3_int64 nByte = 0;
    const char *pEnd;
    const char *a;

    rc = sqlite3Fts3SelectDoctotal(p, &pStmt);
    if( rc!=SQLITE_OK ) return rc;
    a = sqlite3_column_blob(pStmt, 0);
    testcase( a==0 );  /* If %_stat.value set to X'' */
    assert( a );
    if( a ){

    pEnd = &a[sqlite3_column_bytes(pStmt, 0)];
    a += sqlite3Fts3GetVarint(a, &nDoc);
    while( a<pEnd ){
      a += sqlite3Fts3GetVarint(a, &nByte);
      pEnd = &a[sqlite3_column_bytes(pStmt, 0)];
      a += sqlite3Fts3GetVarintBounded(a, pEnd, &nDoc);
      while( a<pEnd ){
        a += sqlite3Fts3GetVarintBounded(a, pEnd, &nByte);
      }
    }
    if( nDoc==0 || nByte==0 ){
      sqlite3_reset(pStmt);
      return FTS_CORRUPT_VTAB;
    }

    pCsr->nDoc = nDoc;
5003
5004
5005
5006
5007
5008
5009
5010
5011

5012
5013
5014
5015
5016
5017
5018
5019

5020
5021
5022
5023
5024
5025
5026
5135
5136
5137
5138
5139
5140
5141


5142
5143
5144
5145

5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157







-
-
+



-




+







  /* 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_malloc(
    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);
5058
5059
5060
5061
5062
5063
5064
5065

5066
5067
5068
5069
5070
5071
5072
5189
5190
5191
5192
5193
5194
5195

5196
5197
5198
5199
5200
5201
5202
5203







-
+







** the phrase object passed as the fifth argument according to a NEAR
** condition. For example:
**
**     abc NEAR/5 "def ghi"
**
** Parameter nNear is passed the NEAR distance of the expression (5 in
** the example above). When this function is called, *paPoslist points to
** the position list, and *pnToken is the number of phrase tokens in, the
** the position list, and *pnToken is the number of phrase tokens in the
** phrase on the other side of the NEAR operator to pPhrase. For example,
** if pPhrase refers to the "def ghi" phrase, then *paPoslist points to
** the position list associated with phrase "abc".
**
** All positions in the pPhrase position list that are not sufficiently
** close to a position in the *paPoslist position list are removed. If this
** leaves 0 positions, zero is returned. Otherwise, non-zero.
5093
5094
5095
5096
5097
5098
5099


5100

5101
5102
5103



5104
5105
5106
5107
5108
5109
5110
5224
5225
5226
5227
5228
5229
5230
5231
5232

5233



5234
5235
5236
5237
5238
5239
5240
5241
5242
5243







+
+
-
+
-
-
-
+
+
+








  p2 = pOut = pPhrase->doclist.pList;
  res = fts3PoslistNearMerge(
    &pOut, aTmp, nParam1, nParam2, paPoslist, &p2
  );
  if( res ){
    nNew = (int)(pOut - pPhrase->doclist.pList) - 1;
    assert_fts3_nc( nNew<=pPhrase->doclist.nList && nNew>0 );
    if( nNew>=0 && nNew<=pPhrase->doclist.nList ){
    assert( pPhrase->doclist.pList[nNew]=='\0' );
      assert( pPhrase->doclist.pList[nNew]=='\0' );
    assert( nNew<=pPhrase->doclist.nList && nNew>0 );
    memset(&pPhrase->doclist.pList[nNew], 0, pPhrase->doclist.nList - nNew);
    pPhrase->doclist.nList = nNew;
      memset(&pPhrase->doclist.pList[nNew], 0, pPhrase->doclist.nList - nNew);
      pPhrase->doclist.nList = nNew;
    }
    *paPoslist = pPhrase->doclist.pList;
    *pnToken = pPhrase->nToken;
  }

  return res;
}

5150
5151
5152
5153
5154
5155
5156
5157

5158
5159
5160
5161
5162
5163
5164
5165
5166
5283
5284
5285
5286
5287
5288
5289

5290
5291

5292
5293
5294
5295
5296
5297
5298







-
+

-







** really a match, taking into account deferred tokens and NEAR operators.
*/
static void fts3EvalNextRow(
  Fts3Cursor *pCsr,               /* FTS Cursor handle */
  Fts3Expr *pExpr,                /* Expr. to advance to next matching row */
  int *pRc                        /* IN/OUT: Error code */
){
  if( *pRc==SQLITE_OK ){
  if( *pRc==SQLITE_OK && pExpr->bEof==0 ){
    int bDescDoclist = pCsr->bDesc;         /* Used by DOCID_CMP() macro */
    assert( pExpr->bEof==0 );
    pExpr->bStart = 1;

    switch( pExpr->eType ){
      case FTSQUERY_NEAR:
      case FTSQUERY_AND: {
        Fts3Expr *pLeft = pExpr->pLeft;
        Fts3Expr *pRight = pExpr->pRight;
5205
5206
5207
5208
5209
5210
5211

5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223


5224
5225
5226
5227
5228
5229
5230
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354


5355
5356
5357
5358
5359
5360
5361
5362
5363







+










-
-
+
+







            if( pLeft->pPhrase && pLeft->pPhrase->doclist.aAll ){
              Fts3Doclist *pDl = &pLeft->pPhrase->doclist;
              while( *pRc==SQLITE_OK && pLeft->bEof==0 ){
                memset(pDl->pList, 0, pDl->nList);
                fts3EvalNextRow(pCsr, pLeft, pRc);
              }
            }
            pRight->bEof = pLeft->bEof = 1;
          }
        }
        break;
      }
  
      case FTSQUERY_OR: {
        Fts3Expr *pLeft = pExpr->pLeft;
        Fts3Expr *pRight = pExpr->pRight;
        sqlite3_int64 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);

        assert( pLeft->bStart || pLeft->iDocid==pRight->iDocid );
        assert( pRight->bStart || pLeft->iDocid==pRight->iDocid );
        assert_fts3_nc( pLeft->bStart || pLeft->iDocid==pRight->iDocid );
        assert_fts3_nc( pRight->bStart || pLeft->iDocid==pRight->iDocid );

        if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
          fts3EvalNextRow(pCsr, pLeft, pRc);
        }else if( pLeft->bEof || iCmp>0 ){
          fts3EvalNextRow(pCsr, pRight, pRc);
        }else{
          fts3EvalNextRow(pCsr, pLeft, pRc);
5315
5316
5317
5318
5319
5320
5321
5322

5323
5324
5325
5326
5327
5328
5329
5330
5331

5332
5333
5334
5335
5336
5337
5338
5448
5449
5450
5451
5452
5453
5454

5455
5456
5457
5458
5459
5460
5461
5462
5463

5464
5465
5466
5467
5468
5469
5470
5471







-
+








-
+







  ** no exceptions to this - it's the way the parser in fts3_expr.c works.
  */
  if( *pRc==SQLITE_OK 
   && pExpr->eType==FTSQUERY_NEAR 
   && (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
  ){
    Fts3Expr *p; 
    int nTmp = 0;                 /* Bytes of temp space */
    sqlite3_int64 nTmp = 0;       /* Bytes of temp space */
    char *aTmp;                   /* Temp space for PoslistNearMerge() */

    /* Allocate temporary working space. */
    for(p=pExpr; p->pLeft; p=p->pLeft){
      assert( p->pRight->pPhrase->doclist.nList>0 );
      nTmp += p->pRight->pPhrase->doclist.nList;
    }
    nTmp += p->pPhrase->doclist.nList;
    aTmp = sqlite3_malloc(nTmp*2);
    aTmp = sqlite3_malloc64(nTmp*2);
    if( !aTmp ){
      *pRc = SQLITE_NOMEM;
      res = 0;
    }else{
      char *aPoslist = p->pPhrase->doclist.pList;
      int nToken = p->pPhrase->nToken;

5433
5434
5435
5436
5437
5438
5439
5440
5441
5442



5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453

5454



5455
5456
5457
5458
5459
5460
5461
5566
5567
5568
5569
5570
5571
5572



5573
5574
5575
5576

5577
5578
5579
5580
5581
5582
5583
5584
5585
5586

5587
5588
5589
5590
5591
5592
5593
5594
5595
5596







-
-
-
+
+
+

-









+
-
+
+
+







            fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc)
         && !fts3EvalTestExpr(pCsr, pExpr->pRight, pRc)
        );
        break;

      default: {
#ifndef SQLITE_DISABLE_FTS4_DEFERRED
        if( pCsr->pDeferred 
         && (pExpr->iDocid==pCsr->iPrevId || pExpr->bDeferred)
        ){
        if( pCsr->pDeferred && (pExpr->bDeferred || (
            pExpr->iDocid==pCsr->iPrevId && pExpr->pPhrase->doclist.pList
        ))){
          Fts3Phrase *pPhrase = pExpr->pPhrase;
          assert( pExpr->bDeferred || pPhrase->doclist.bFreeList==0 );
          if( pExpr->bDeferred ){
            fts3EvalInvalidatePoslist(pPhrase);
          }
          *pRc = fts3EvalDeferredPhrase(pCsr, pPhrase);
          bHit = (pPhrase->doclist.pList!=0);
          pExpr->iDocid = pCsr->iPrevId;
        }else
#endif
        {
          bHit = ( 
          bHit = (pExpr->bEof==0 && pExpr->iDocid==pCsr->iPrevId);
              pExpr->bEof==0 && pExpr->iDocid==pCsr->iPrevId
           && pExpr->pPhrase->doclist.nList>0
          );
        }
        break;
      }
    }
  }
  return bHit;
}
5594
5595
5596
5597
5598
5599
5600
5601

5602
5603
5604
5605
5606
5607
5608
5609

5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625

5626
5627
5628
5629


5630
















5631
5632
5633
5634
5635
5636
5637
5729
5730
5731
5732
5733
5734
5735

5736
5737
5738
5739
5740
5741
5742


5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758

5759
5760
5761


5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787







-
+






-
-
+















-
+


-
-
+
+

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







** After allocating the Fts3Expr.aMI[] array for each phrase in the 
** expression rooted at pExpr, the cursor iterates through all rows matched
** by pExpr, calling this function for each row. This function increments
** the values in Fts3Expr.aMI[] according to the position-list currently
** found in Fts3Expr.pPhrase->doclist.pList for each of the phrase 
** expression nodes.
*/
static void fts3EvalUpdateCounts(Fts3Expr *pExpr){
static void fts3EvalUpdateCounts(Fts3Expr *pExpr, int nCol){
  if( pExpr ){
    Fts3Phrase *pPhrase = pExpr->pPhrase;
    if( pPhrase && pPhrase->doclist.pList ){
      int iCol = 0;
      char *p = pPhrase->doclist.pList;

      assert( *p );
      while( 1 ){
      do{
        u8 c = 0;
        int iCnt = 0;
        while( 0xFE & (*p | c) ){
          if( (c&0x80)==0 ) iCnt++;
          c = *p++ & 0x80;
        }

        /* aMI[iCol*3 + 1] = Number of occurrences
        ** aMI[iCol*3 + 2] = Number of rows containing at least one instance
        */
        pExpr->aMI[iCol*3 + 1] += iCnt;
        pExpr->aMI[iCol*3 + 2] += (iCnt>0);
        if( *p==0x00 ) break;
        p++;
        p += fts3GetVarint32(p, &iCol);
      }
      }while( iCol<nCol );
    }

    fts3EvalUpdateCounts(pExpr->pLeft);
    fts3EvalUpdateCounts(pExpr->pRight);
    fts3EvalUpdateCounts(pExpr->pLeft, nCol);
    fts3EvalUpdateCounts(pExpr->pRight, nCol);
  }
}

/*
** This is an sqlite3Fts3ExprIterate() callback. If the Fts3Expr.aMI[] array
** has not yet been allocated, allocate and zero it. Otherwise, just zero
** it.
*/
static int fts3AllocateMSI(Fts3Expr *pExpr, int iPhrase, void *pCtx){
  Fts3Table *pTab = (Fts3Table*)pCtx;
  UNUSED_PARAMETER(iPhrase);
  if( pExpr->aMI==0 ){
    pExpr->aMI = (u32 *)sqlite3_malloc64(pTab->nColumn * 3 * sizeof(u32));
    if( pExpr->aMI==0 ) return SQLITE_NOMEM;
  }
  memset(pExpr->aMI, 0, pTab->nColumn * 3 * sizeof(u32));
  return SQLITE_OK;
}

/*
** Expression pExpr must be of type FTSQUERY_PHRASE.
**
** If it is not already allocated and populated, this function allocates and
** populates the Fts3Expr.aMI[] array for expression pExpr. If pExpr is part
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662



5663
5664
5665
5666
5667
5668
5669
5670
5671

5672
5673
5674
5675
5676
5677

5678
5679
5680
5681
5682
5683
5684
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






5822
5823
5824
5825
5826
5827
5828
5829







-







-
+
+
+







-
-
+
-
-
-
-
-
-
+







){
  int rc = SQLITE_OK;             /* Return code */

  assert( pExpr->eType==FTSQUERY_PHRASE );
  if( pExpr->aMI==0 ){
    Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
    Fts3Expr *pRoot;                /* Root of NEAR expression */
    Fts3Expr *p;                    /* Iterator used for several purposes */

    sqlite3_int64 iPrevId = pCsr->iPrevId;
    sqlite3_int64 iDocid;
    u8 bEof;

    /* Find the root of the NEAR expression */
    pRoot = pExpr;
    while( pRoot->pParent && pRoot->pParent->eType==FTSQUERY_NEAR ){
    while( pRoot->pParent 
        && (pRoot->pParent->eType==FTSQUERY_NEAR || pRoot->bDeferred) 
    ){
      pRoot = pRoot->pParent;
    }
    iDocid = pRoot->iDocid;
    bEof = pRoot->bEof;
    assert( pRoot->bStart );

    /* Allocate space for the aMSI[] array of each FTSQUERY_PHRASE node */
    for(p=pRoot; p; p=p->pLeft){
      Fts3Expr *pE = (p->eType==FTSQUERY_PHRASE?p:p->pRight);
    rc = sqlite3Fts3ExprIterate(pRoot, fts3AllocateMSI, (void*)pTab);
      assert( pE->aMI==0 );
      pE->aMI = (u32 *)sqlite3_malloc(pTab->nColumn * 3 * sizeof(u32));
      if( !pE->aMI ) return SQLITE_NOMEM;
      memset(pE->aMI, 0, pTab->nColumn * 3 * sizeof(u32));
    }

    if( rc!=SQLITE_OK ) return rc;
    fts3EvalRestart(pCsr, pRoot, &rc);

    while( pCsr->isEof==0 && rc==SQLITE_OK ){

      do {
        /* Ensure the %_content statement is reset. */
        if( pCsr->isRequireSeek==0 ) sqlite3_reset(pCsr->pStmt);
5692
5693
5694
5695
5696
5697
5698
5699

5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718


5719
5720
5721
5722
5723
5724
5725
5837
5838
5839
5840
5841
5842
5843

5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862

5863
5864
5865
5866
5867
5868
5869
5870
5871







-
+


















-
+
+







        pCsr->iPrevId = pRoot->iDocid;
      }while( pCsr->isEof==0 
           && pRoot->eType==FTSQUERY_NEAR 
           && sqlite3Fts3EvalTestDeferred(pCsr, &rc) 
      );

      if( rc==SQLITE_OK && pCsr->isEof==0 ){
        fts3EvalUpdateCounts(pRoot);
        fts3EvalUpdateCounts(pRoot, pTab->nColumn);
      }
    }

    pCsr->isEof = 0;
    pCsr->iPrevId = iPrevId;

    if( bEof ){
      pRoot->bEof = bEof;
    }else{
      /* Caution: pRoot may iterate through docids in ascending or descending
      ** order. For this reason, even though it seems more defensive, the 
      ** do loop can not be written:
      **
      **   do {...} while( pRoot->iDocid<iDocid && rc==SQLITE_OK );
      */
      fts3EvalRestart(pCsr, pRoot, &rc);
      do {
        fts3EvalNextRow(pCsr, pRoot, &rc);
        assert( pRoot->bEof==0 );
        assert_fts3_nc( pRoot->bEof==0 );
        if( pRoot->bEof ) rc = FTS_CORRUPT_VTAB;
      }while( pRoot->iDocid!=iDocid && rc==SQLITE_OK );
    }
  }
  return rc;
}

/*
5825
5826
5827
5828
5829
5830
5831

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





5846
5847
5848
5849
5850
5851
5852
5853
5854
5855





5856
5857


5858


5859
5860
5861


5862
5863
5864
5865
5866
5867
5868
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002





6003
6004
6005
6006
6007
6008
6009
6010
6011

6012
6013
6014


6015
6016
6017
6018
6019
6020
6021
6022
6023







+














+
+
+
+
+





-
-
-
-
-
+
+
+
+
+


+
+
-
+
+

-
-
+
+







  if( iDocid!=pCsr->iPrevId || pExpr->bEof ){
    int rc = SQLITE_OK;
    int bDescDoclist = pTab->bDescIdx;      /* For DOCID_CMP macro */
    int bOr = 0;
    u8 bTreeEof = 0;
    Fts3Expr *p;                  /* Used to iterate from pExpr to root */
    Fts3Expr *pNear;              /* Most senior NEAR ancestor (or pExpr) */
    Fts3Expr *pRun;               /* Closest non-deferred ancestor of pNear */
    int bMatch;

    /* Check if this phrase descends from an OR expression node. If not, 
    ** return NULL. Otherwise, the entry that corresponds to docid 
    ** pCsr->iPrevId may lie earlier in the doclist buffer. Or, if the
    ** tree that the node is part of has been marked as EOF, but the node
    ** itself is not EOF, then it may point to an earlier entry. */
    pNear = pExpr;
    for(p=pExpr->pParent; p; p=p->pParent){
      if( p->eType==FTSQUERY_OR ) bOr = 1;
      if( p->eType==FTSQUERY_NEAR ) pNear = p;
      if( p->bEof ) bTreeEof = 1;
    }
    if( bOr==0 ) return SQLITE_OK;
    pRun = pNear;
    while( pRun->bDeferred ){
      assert( pRun->pParent );
      pRun = pRun->pParent;
    }

    /* This is the descendent of an OR node. In this case we cannot use
    ** an incremental phrase. Load the entire doclist for the phrase
    ** into memory in this case.  */
    if( pPhrase->bIncr ){
      int bEofSave = pNear->bEof;
      fts3EvalRestart(pCsr, pNear, &rc);
      while( rc==SQLITE_OK && !pNear->bEof ){
        fts3EvalNextRow(pCsr, pNear, &rc);
        if( bEofSave==0 && pNear->iDocid==iDocid ) break;
      int bEofSave = pRun->bEof;
      fts3EvalRestart(pCsr, pRun, &rc);
      while( rc==SQLITE_OK && !pRun->bEof ){
        fts3EvalNextRow(pCsr, pRun, &rc);
        if( bEofSave==0 && pRun->iDocid==iDocid ) break;
      }
      assert( rc!=SQLITE_OK || pPhrase->bIncr==0 );
      if( rc==SQLITE_OK && pRun->bEof!=bEofSave ){
        rc = FTS_CORRUPT_VTAB;
    }
      }
    }
    if( bTreeEof ){
      while( rc==SQLITE_OK && !pNear->bEof ){
        fts3EvalNextRow(pCsr, pNear, &rc);
      while( rc==SQLITE_OK && !pRun->bEof ){
        fts3EvalNextRow(pCsr, pRun, &rc);
      }
    }
    if( rc!=SQLITE_OK ) return rc;

    bMatch = 1;
    for(p=pNear; p; p=p->pLeft){
      u8 bEof = 0;

Changes to ext/fts3/fts3Int.h.

91
92
93
94
95
96
97


98
99
100
101
102
103
104
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106







+
+








/*
** Maximum length of a varint encoded integer. The varint format is different
** from that used by SQLite, so the maximum length is 10, not 9.
*/
#define FTS3_VARINT_MAX 10

#define FTS3_BUFFER_PADDING 8

/*
** FTS4 virtual tables may maintain multiple indexes - one index of all terms
** in the document set and zero or more prefix indexes. All indexes are stored
** as one or more b+-trees in the %_segments and %_segdir tables. 
**
** It is possible to determine which index a b+-tree belongs to based on the
** value stored in the "%_segdir.level" column. Given this value L, the index
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
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







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










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

-
-
+
+








/*
** Terminator values for position-lists and column-lists.
*/
#define POS_COLUMN  (1)     /* Column-list terminator */
#define POS_END     (0)     /* Position-list terminator */ 

/*
** The assert_fts3_nc() macro is similar to the assert() macro, except that it
** is used for assert() conditions that are true only if it can be 
** guranteed that the database is not corrupt.
*/
#ifdef SQLITE_DEBUG
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

/*
** This section provides definitions to allow the
** FTS3 extension to be compiled outside of the 
** amalgamation.
*/
#ifndef SQLITE_AMALGAMATION
/*
** Macros indicating that conditional expressions are always true or
** false.
*/
#ifdef SQLITE_COVERAGE_TEST
# define ALWAYS(x) (1)
# define NEVER(X)  (0)
#elif defined(SQLITE_DEBUG)
# define ALWAYS(x) sqlite3Fts3Always((x)!=0)
# define NEVER(x) sqlite3Fts3Never((x)!=0)
#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
# define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1
#endif
#if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
# define ALWAYS(X)      (1)
# define NEVER(X)       (0)
#elif !defined(NDEBUG)
# define ALWAYS(X)      ((X)?1:(assert(0),0))
# define NEVER(X)       ((X)?(assert(0),1):0)
int sqlite3Fts3Always(int b);
int sqlite3Fts3Never(int b);
#else
# define ALWAYS(x) (x)
# define NEVER(x)  (x)
# define ALWAYS(X)      (X)
# define NEVER(X)       (X)
#endif

/*
** Internal types used by SQLite.
*/
typedef unsigned char u8;         /* 1-byte (or larger) unsigned integer */
typedef short int i16;            /* 2-byte (or larger) signed integer */
177
178
179
180
181
182
183





184
185
186
187
188
189
190
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210







+
+
+
+
+







** within testcase() and assert() macros.
*/
#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
# define TESTONLY(X)  X
#else
# define TESTONLY(X)
#endif

#define LARGEST_INT64  (0xffffffff|(((i64)0x7fffffff)<<32))
#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64)

#define deliberate_fall_through

#endif /* SQLITE_AMALGAMATION */

#ifdef SQLITE_DEBUG
int sqlite3Fts3Corrupt(void);
# define FTS_CORRUPT_VTAB sqlite3Fts3Corrupt()
#else
221
222
223
224
225
226
227

228
229
230
231
232
233
234
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255







+







  char **azColumn;                /* column names.  malloced */
  u8 *abNotindexed;               /* True for 'notindexed' columns */
  sqlite3_tokenizer *pTokenizer;  /* tokenizer for inserts and queries */
  char *zContentTbl;              /* content=xxx option, or NULL */
  char *zLanguageid;              /* languageid=xxx option, or NULL */
  int nAutoincrmerge;             /* Value configured by 'automerge' */
  u32 nLeafAdd;                   /* Number of leaf blocks added this trans */
  int bLock;                      /* Used to prevent recursive content= tbls */

  /* Precompiled statements used by the implementation. Each of these 
  ** statements is run and reset within a single virtual table API call. 
  */
  sqlite3_stmt *aStmt[40];
  sqlite3_stmt *pSeekStmt;        /* Cache for fts3CursorSeekStmt() */

279
280
281
282
283
284
285
286

287
288
289



290
291







292
293
294
295
296
297
298
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







-
+



+
+
+


+
+
+
+
+
+
+







  ** values do not contribute to FTS functionality; they are used for
  ** verifying the operation of the SQLite core.
  */
  int inTransaction;     /* True after xBegin but before xCommit/xRollback */
  int mxSavepoint;       /* Largest valid xSavepoint integer */
#endif

#ifdef SQLITE_TEST
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
  /* True to disable the incremental doclist optimization. This is controled
  ** by special insert command 'test-no-incr-doclist'.  */
  int bNoIncrDoclist;

  /* Number of segments in a level */
  int nMergeCount;
#endif
};

/* Macro to find the number of segments to merge */
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
# define MergeCount(P) ((P)->nMergeCount)
#else
# define MergeCount(P) FTS3_MERGE_COUNT
#endif

/*
** When the core wants to read from the virtual table, it creates a
** virtual table cursor (an instance of the following structure) using
** the xOpen method. Cursors are destroyed using the xClose method.
*/
struct Fts3Cursor {
523
524
525
526
527
528
529
530

531
532
533
534
535
536
537
554
555
556
557
558
559
560

561
562
563
564
565
566
567
568







-
+







struct Fts3MultiSegReader {
  /* Used internally by sqlite3Fts3SegReaderXXX() calls */
  Fts3SegReader **apSegment;      /* Array of Fts3SegReader objects */
  int nSegment;                   /* Size of apSegment array */
  int nAdvance;                   /* How many seg-readers to advance */
  Fts3SegFilter *pFilter;         /* Pointer to filter object */
  char *aBuffer;                  /* Buffer to merge doclists in */
  int nBuffer;                    /* Allocated size of aBuffer[] in bytes */
  i64 nBuffer;                    /* Allocated size of aBuffer[] in bytes */

  int iColFilter;                 /* If >=0, filter for this column */
  int bRestart;

  /* Used by fts3.c only. */
  int nCost;                      /* Cost of running iterator */
  int bLookup;                    /* True if a lookup of a single entry. */
549
550
551
552
553
554
555


556
557
558
559
560
561
562
563

564
565
566
567
568
569
570
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







+
+








+







  (*(u8*)(p)&0x80) ? sqlite3Fts3GetVarint32(p, piVal) : (*piVal=*(u8*)(p), 1) \
)

/* fts3.c */
void sqlite3Fts3ErrMsg(char**,const char*,...);
int sqlite3Fts3PutVarint(char *, sqlite3_int64);
int sqlite3Fts3GetVarint(const char *, sqlite_int64 *);
int sqlite3Fts3GetVarintU(const char *, sqlite_uint64 *);
int sqlite3Fts3GetVarintBounded(const char*,const char*,sqlite3_int64*);
int sqlite3Fts3GetVarint32(const char *, int *);
int sqlite3Fts3VarintLen(sqlite3_uint64);
void sqlite3Fts3Dequote(char *);
void sqlite3Fts3DoclistPrev(int,char*,int,char**,sqlite3_int64*,int*,u8*);
int sqlite3Fts3EvalPhraseStats(Fts3Cursor *, Fts3Expr *, u32 *);
int sqlite3Fts3FirstFilter(sqlite3_int64, char *, int, char *);
void sqlite3Fts3CreateStatTable(int*, Fts3Table*);
int sqlite3Fts3EvalTestDeferred(Fts3Cursor *pCsr, int *pRc);
int sqlite3Fts3ReadInt(const char *z, int *pnOut);

/* fts3_tokenizer.c */
const char *sqlite3Fts3NextToken(const char *, int *);
int sqlite3Fts3InitHashTable(sqlite3 *, Fts3Hash *, const char *);
int sqlite3Fts3InitTokenizer(Fts3Hash *pHash, const char *, 
    sqlite3_tokenizer **, char **
);
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
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







+



















-
+







+
+



  char **, int, int, int, const char *, int, Fts3Expr **, char **
);
void sqlite3Fts3ExprFree(Fts3Expr *);
#ifdef SQLITE_TEST
int sqlite3Fts3ExprInitTestInterface(sqlite3 *db, Fts3Hash*);
int sqlite3Fts3InitTerm(sqlite3 *db);
#endif
void *sqlite3Fts3MallocZero(i64 nByte);

int sqlite3Fts3OpenTokenizer(sqlite3_tokenizer *, int, const char *, int,
  sqlite3_tokenizer_cursor **
);

/* fts3_aux.c */
int sqlite3Fts3InitAux(sqlite3 *db);

void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *);

int sqlite3Fts3MsrIncrStart(
    Fts3Table*, Fts3MultiSegReader*, int, const char*, int);
int sqlite3Fts3MsrIncrNext(
    Fts3Table *, Fts3MultiSegReader *, sqlite3_int64 *, char **, int *);
int sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol, char **); 
int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *);
int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr);

/* fts3_tokenize_vtab.c */
int sqlite3Fts3InitTok(sqlite3*, Fts3Hash *);
int sqlite3Fts3InitTok(sqlite3*, Fts3Hash *, void(*xDestroy)(void*));

/* fts3_unicode2.c (functions generated by parsing unicode text files) */
#ifndef SQLITE_DISABLE_FTS3_UNICODE
int sqlite3FtsUnicodeFold(int, int);
int sqlite3FtsUnicodeIsalnum(int);
int sqlite3FtsUnicodeIsdiacritic(int);
#endif

int sqlite3Fts3ExprIterate(Fts3Expr*, int (*x)(Fts3Expr*,int,void*), void*);

#endif /* !SQLITE_CORE || SQLITE_ENABLE_FTS3 */
#endif /* _FTSINT_H */

Changes to ext/fts3/fts3_aux.c.

62
63
64
65
66
67
68
69

70
71
72
73
74
75
76
62
63
64
65
66
67
68

69
70
71
72
73
74
75
76







-
+







  sqlite3_vtab **ppVtab,          /* OUT: New sqlite3_vtab object */
  char **pzErr                    /* OUT: sqlite3_malloc'd error message */
){
  char const *zDb;                /* Name of database (e.g. "main") */
  char const *zFts3;              /* Name of fts3 table */
  int nDb;                        /* Result of strlen(zDb) */
  int nFts3;                      /* Result of strlen(zFts3) */
  int nByte;                      /* Bytes of space to allocate here */
  sqlite3_int64 nByte;            /* Bytes of space to allocate here */
  int rc;                         /* value returned by declare_vtab() */
  Fts3auxTable *p;                /* Virtual table object to return */

  UNUSED_PARAMETER(pUnused);

  /* The user should invoke this in one of two forms:
  **
94
95
96
97
98
99
100
101

102
103
104
105
106
107
108
94
95
96
97
98
99
100

101
102
103
104
105
106
107
108







-
+







  }
  nFts3 = (int)strlen(zFts3);

  rc = sqlite3_declare_vtab(db, FTS3_AUX_SCHEMA);
  if( rc!=SQLITE_OK ) return rc;

  nByte = sizeof(Fts3auxTable) + sizeof(Fts3Table) + nDb + nFts3 + 2;
  p = (Fts3auxTable *)sqlite3_malloc(nByte);
  p = (Fts3auxTable *)sqlite3_malloc64(nByte);
  if( !p ) return SQLITE_NOMEM;
  memset(p, 0, nByte);

  p->pFts3Tab = (Fts3Table *)&p[1];
  p->pFts3Tab->zDb = (char *)&p->pFts3Tab[1];
  p->pFts3Tab->zName = &p->pFts3Tab->zDb[nDb+1];
  p->pFts3Tab->db = db;
244
245
246
247
248
249
250
251

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

251
252
253
254
255
256
257
258







-
+







  sqlite3_free(pCsr);
  return SQLITE_OK;
}

static int fts3auxGrowStatArray(Fts3auxCursor *pCsr, int nSize){
  if( nSize>pCsr->nStat ){
    struct Fts3auxColstats *aNew;
    aNew = (struct Fts3auxColstats *)sqlite3_realloc(pCsr->aStat, 
    aNew = (struct Fts3auxColstats *)sqlite3_realloc64(pCsr->aStat, 
        sizeof(struct Fts3auxColstats) * nSize
    );
    if( aNew==0 ) return SQLITE_NOMEM;
    memset(&aNew[pCsr->nStat], 0, 
        sizeof(struct Fts3auxColstats) * (nSize - pCsr->nStat)
    );
    pCsr->aStat = aNew;
293
294
295
296
297
298
299

300
301
302
303
304
305
306
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307







+







        return SQLITE_OK;
      }
    }

    if( fts3auxGrowStatArray(pCsr, 2) ) return SQLITE_NOMEM;
    memset(pCsr->aStat, 0, sizeof(struct Fts3auxColstats) * pCsr->nStat);
    iCol = 0;
    rc = SQLITE_OK;

    while( i<nDoclist ){
      sqlite3_int64 v = 0;

      i += sqlite3Fts3GetVarint(&aDoclist[i], &v);
      switch( eState ){
        /* State 0. In this state the integer just read was a docid. */
336
337
338
339
340
341
342




343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
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







+
+
+
+








-







            pCsr->aStat[0].nOcc++;
          }
          break;

        /* State 3. The integer just read is a column number. */
        default: assert( eState==3 );
          iCol = (int)v;
          if( iCol<1 ){
            rc = SQLITE_CORRUPT_VTAB;
            break;
          }
          if( fts3auxGrowStatArray(pCsr, iCol+2) ) return SQLITE_NOMEM;
          pCsr->aStat[iCol+1].nDoc++;
          eState = 2;
          break;
      }
    }

    pCsr->iCol = 0;
    rc = SQLITE_OK;
  }else{
    pCsr->isEof = 1;
  }
  return rc;
}

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







+










-

+





-

+







  }

  /* 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]);
    assert( (iEq==0 && iGe==-1) || (iEq==-1 && iGe==0) );
    if( zStr ){
      pCsr->filter.zTerm = sqlite3_mprintf("%s", zStr);
      pCsr->filter.nTerm = sqlite3_value_bytes(apVal[0]);
      if( pCsr->filter.zTerm==0 ) return SQLITE_NOMEM;
      pCsr->filter.nTerm = (int)strlen(pCsr->filter.zTerm);
    }
  }

  if( iLe>=0 ){
    pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iLe]));
    pCsr->nStop = sqlite3_value_bytes(apVal[iLe]);
    if( pCsr->zStop==0 ) return SQLITE_NOMEM;
    pCsr->nStop = (int)strlen(pCsr->zStop);
  }
  
  if( iLangid>=0 ){
    iLangVal = sqlite3_value_int(apVal[iLangid]);

    /* If the user specified a negative value for the languageid, use zero
    ** instead. This works, as the "languageid=?" constraint will also

Changes to ext/fts3/fts3_expr.c.

118
119
120
121
122
123
124
125
126


127
128
129
130
131
132
133
118
119
120
121
122
123
124


125
126
127
128
129
130
131
132
133







-
-
+
+







}

/*
** Allocate nByte bytes of memory using sqlite3_malloc(). If successful,
** zero the memory before returning a pointer to it. If unsuccessful, 
** return NULL.
*/
static void *fts3MallocZero(int nByte){
  void *pRet = sqlite3_malloc(nByte);
void *sqlite3Fts3MallocZero(sqlite3_int64 nByte){
  void *pRet = sqlite3_malloc64(nByte);
  if( pRet ) memset(pRet, 0, nByte);
  return pRet;
}

int sqlite3Fts3OpenTokenizer(
  sqlite3_tokenizer *pTokenizer,
  int iLangid,
194
195
196
197
198
199
200
201

202
203
204
205
206

207
208
209
210
211
212
213
194
195
196
197
198
199
200

201
202
203
204
205

206
207
208
209
210
211
212
213







-
+




-
+







  }

  *pnConsumed = i;
  rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, i, &pCursor);
  if( rc==SQLITE_OK ){
    const char *zToken;
    int nToken = 0, iStart = 0, iEnd = 0, iPosition = 0;
    int nByte;                               /* total space to allocate */
    sqlite3_int64 nByte;                    /* total space to allocate */

    rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition);
    if( rc==SQLITE_OK ){
      nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken;
      pRet = (Fts3Expr *)fts3MallocZero(nByte);
      pRet = (Fts3Expr *)sqlite3Fts3MallocZero(nByte);
      if( !pRet ){
        rc = SQLITE_NOMEM;
      }else{
        pRet->eType = FTSQUERY_PHRASE;
        pRet->pPhrase = (Fts3Phrase *)&pRet[1];
        pRet->pPhrase->nToken = 1;
        pRet->pPhrase->iColumn = iCol;
248
249
250
251
252
253
254
255
256


257
258
259
260
261
262
263
248
249
250
251
252
253
254


255
256
257
258
259
260
261
262
263







-
-
+
+







}


/*
** Enlarge a memory allocation.  If an out-of-memory allocation occurs,
** then free the old allocation.
*/
static void *fts3ReallocOrFree(void *pOrig, int nNew){
  void *pRet = sqlite3_realloc(pOrig, nNew);
static void *fts3ReallocOrFree(void *pOrig, sqlite3_int64 nNew){
  void *pRet = sqlite3_realloc64(pOrig, nNew);
  if( !pRet ){
    sqlite3_free(pOrig);
  }
  return pRet;
}

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







-
-
-
+
-











-
+







      int nKey = pKey->n;
      char cNext;

      /* If this is a "NEAR" keyword, check for an explicit nearness. */
      if( pKey->eType==FTSQUERY_NEAR ){
        assert( nKey==4 );
        if( zInput[4]=='/' && zInput[5]>='0' && zInput[5]<='9' ){
          nNear = 0;
          for(nKey=5; zInput[nKey]>='0' && zInput[nKey]<='9'; nKey++){
            nNear = nNear * 10 + (zInput[nKey] - '0');
          nKey += 1+sqlite3Fts3ReadInt(&zInput[nKey+1], &nNear);
          }
        }
      }

      /* At this point this is probably a keyword. But for that to be true,
      ** the next byte must contain either whitespace, an open or close
      ** parenthesis, a quote character, or EOF. 
      */
      cNext = zInput[nKey];
      if( fts3isspace(cNext) 
       || cNext=='"' || cNext=='(' || cNext==')' || cNext==0
      ){
        pRet = (Fts3Expr *)fts3MallocZero(sizeof(Fts3Expr));
        pRet = (Fts3Expr *)sqlite3Fts3MallocZero(sizeof(Fts3Expr));
        if( !pRet ){
          return SQLITE_NOMEM;
        }
        pRet->eType = pKey->eType;
        pRet->nNear = nNear;
        *ppExpr = pRet;
        *pnConsumed = (int)((zInput - z) + nKey);
492
493
494
495
496
497
498





499
500
501
502
503
504
505
506
507
489
490
491
492
493
494
495
496
497
498
499
500
501

502
503
504
505
506
507
508







+
+
+
+
+

-







    return getNextString(pParse, &zInput[1], ii-1, ppExpr);
  }

  if( sqlite3_fts3_enable_parentheses ){
    if( *zInput=='(' ){
      int nConsumed = 0;
      pParse->nNest++;
#if !defined(SQLITE_MAX_EXPR_DEPTH)
      if( pParse->nNest>1000 ) return SQLITE_ERROR;
#elif SQLITE_MAX_EXPR_DEPTH>0
      if( pParse->nNest>SQLITE_MAX_EXPR_DEPTH ) return SQLITE_ERROR;
#endif
      rc = fts3ExprParse(pParse, zInput+1, nInput-1, ppExpr, &nConsumed);
      if( rc==SQLITE_OK && !*ppExpr ){ rc = SQLITE_DONE; }
      *pnConsumed = (int)(zInput - z) + 1 + nConsumed;
      return rc;
    }else if( *zInput==')' ){
      pParse->nNest--;
      *pnConsumed = (int)((zInput - z) + 1);
      *ppExpr = 0;
      return SQLITE_DONE;
632
633
634
635
636
637
638
639

640
641
642
643
644
645
646
633
634
635
636
637
638
639

640
641
642
643
644
645
646
647







-
+







      if( p ){
        int isPhrase;

        if( !sqlite3_fts3_enable_parentheses 
            && p->eType==FTSQUERY_PHRASE && pParse->isNot 
        ){
          /* Create an implicit NOT operator. */
          Fts3Expr *pNot = fts3MallocZero(sizeof(Fts3Expr));
          Fts3Expr *pNot = sqlite3Fts3MallocZero(sizeof(Fts3Expr));
          if( !pNot ){
            sqlite3Fts3ExprFree(p);
            rc = SQLITE_NOMEM;
            goto exprparse_out;
          }
          pNot->eType = FTSQUERY_NOT;
          pNot->pRight = p;
666
667
668
669
670
671
672
673

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

674
675
676
677
678
679
680
681







-
+







            goto exprparse_out;
          }

          if( isPhrase && !isRequirePhrase ){
            /* Insert an implicit AND operator. */
            Fts3Expr *pAnd;
            assert( pRet && pPrev );
            pAnd = fts3MallocZero(sizeof(Fts3Expr));
            pAnd = sqlite3Fts3MallocZero(sizeof(Fts3Expr));
            if( !pAnd ){
              sqlite3Fts3ExprFree(p);
              rc = SQLITE_NOMEM;
              goto exprparse_out;
            }
            pAnd->eType = FTSQUERY_AND;
            insertBinaryOperator(&pRet, pPrev, pAnd);
792
793
794
795
796
797
798
799

800
801
802
803
804
805
806
793
794
795
796
797
798
799

800
801
802
803
804
805
806
807







-
+







  if( nMaxDepth==0 ){
    rc = SQLITE_ERROR;
  }

  if( rc==SQLITE_OK ){
    if( (eType==FTSQUERY_AND || eType==FTSQUERY_OR) ){
      Fts3Expr **apLeaf;
      apLeaf = (Fts3Expr **)sqlite3_malloc(sizeof(Fts3Expr *) * nMaxDepth);
      apLeaf = (Fts3Expr **)sqlite3_malloc64(sizeof(Fts3Expr *) * nMaxDepth);
      if( 0==apLeaf ){
        rc = SQLITE_NOMEM;
      }else{
        memset(apLeaf, 0, sizeof(Fts3Expr *) * nMaxDepth);
      }

      if( rc==SQLITE_OK ){
1212
1213
1214
1215
1216
1217
1218
1219

1220
1221
1222
1223
1224
1225
1226
1213
1214
1215
1216
1217
1218
1219

1220
1221
1222
1223
1224
1225
1226
1227







-
+







    sqlite3_free(zErr);
    return;
  }

  zExpr = (const char *)sqlite3_value_text(argv[1]);
  nExpr = sqlite3_value_bytes(argv[1]);
  nCol = argc-2;
  azCol = (char **)sqlite3_malloc(nCol*sizeof(char *));
  azCol = (char **)sqlite3_malloc64(nCol*sizeof(char *));
  if( !azCol ){
    sqlite3_result_error_nomem(context);
    goto exprtest_out;
  }
  for(ii=0; ii<nCol; ii++){
    azCol[ii] = (char *)sqlite3_value_text(argv[ii+2]);
  }

Changes to ext/fts3/fts3_hash.c.

31
32
33
34
35
36
37
38
39


40
41
42
43
44
45
46
31
32
33
34
35
36
37


38
39
40
41
42
43
44
45
46







-
-
+
+







#include <string.h>

#include "fts3_hash.h"

/*
** Malloc and Free functions
*/
static void *fts3HashMalloc(int n){
  void *p = sqlite3_malloc(n);
static void *fts3HashMalloc(sqlite3_int64 n){
  void *p = sqlite3_malloc64(n);
  if( p ){
    memset(p, 0, n);
  }
  return p;
}
static void fts3HashFree(void *p){
  sqlite3_free(p);

Changes to ext/fts3/fts3_icu.c.

56
57
58
59
60
61
62
63

64
65
66
67
68
69
70
56
57
58
59
60
61
62

63
64
65
66
67
68
69
70







-
+







){
  IcuTokenizer *p;
  int n = 0;

  if( argc>0 ){
    n = strlen(argv[0])+1;
  }
  p = (IcuTokenizer *)sqlite3_malloc(sizeof(IcuTokenizer)+n);
  p = (IcuTokenizer *)sqlite3_malloc64(sizeof(IcuTokenizer)+n);
  if( !p ){
    return SQLITE_NOMEM;
  }
  memset(p, 0, sizeof(IcuTokenizer));

  if( n ){
    p->zLocale = (char *)&p[1];
113
114
115
116
117
118
119
120

121
122
123
124
125
126
127
113
114
115
116
117
118
119

120
121
122
123
124
125
126
127







-
+







  if( zInput==0 ){
    nInput = 0;
    zInput = "";
  }else if( nInput<0 ){
    nInput = strlen(zInput);
  }
  nChar = nInput+1;
  pCsr = (IcuCursor *)sqlite3_malloc(
  pCsr = (IcuCursor *)sqlite3_malloc64(
      sizeof(IcuCursor) +                /* IcuCursor */
      ((nChar+3)&~3) * sizeof(UChar) +   /* IcuCursor.aChar[] */
      (nChar+1) * sizeof(int)            /* IcuCursor.aOffset[] */
  );
  if( !pCsr ){
    return SQLITE_NOMEM;
  }

Changes to ext/fts3/fts3_porter.c.

617
618
619
620
621
622
623
624

625
626
627
628
629
630
631
617
618
619
620
621
622
623

624
625
626
627
628
629
630
631







-
+







    }

    if( c->iOffset>iStartOffset ){
      int n = c->iOffset-iStartOffset;
      if( n>c->nAllocated ){
        char *pNew;
        c->nAllocated = n+20;
        pNew = sqlite3_realloc(c->zToken, c->nAllocated);
        pNew = sqlite3_realloc64(c->zToken, c->nAllocated);
        if( !pNew ) return SQLITE_NOMEM;
        c->zToken = pNew;
      }
      porter_stemmer(&z[iStartOffset], n, c->zToken, pnBytes);
      *pzToken = c->zToken;
      *piStartOffset = iStartOffset;
      *piEndOffset = c->iOffset;

Changes to ext/fts3/fts3_snippet.c.

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







+
+
+
+




















-
+








#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 */
#define FTS3_MATCHINFO_LENGTH    'l'        /* nCol values */
#define FTS3_MATCHINFO_LCS       's'        /* nCol values */
#define FTS3_MATCHINFO_HITS      'x'        /* 3*nCol*nPhrase values */
#define FTS3_MATCHINFO_LHITS     'y'        /* nCol*nPhrase values */
#define FTS3_MATCHINFO_LHITS_BM  'b'        /* nCol*nPhrase values */

/*
** The default value for the second argument to matchinfo(). 
*/
#define FTS3_MATCHINFO_DEFAULT   "pcx"


/*
** Used as an fts3ExprIterate() context when loading phrase doclists to
** Used as an sqlite3Fts3ExprIterate() context when loading phrase doclists to
** Fts3Expr.aDoclist[]/nDoclist.
*/
typedef struct LoadDoclistCtx LoadDoclistCtx;
struct LoadDoclistCtx {
  Fts3Cursor *pCsr;               /* FTS3 Cursor */
  int nPhrase;                    /* Number of phrases seen so far */
  int nToken;                     /* Number of tokens seen so far */
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
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







-
+

-
+











-
+







  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 */
  u64 hlmask;                     /* Mask of snippet terms to highlight */
};

/*
** This type is used as an fts3ExprIterate() context object while 
** This type is used as an sqlite3Fts3ExprIterate() context object while 
** accumulating the data returned by the matchinfo() function.
*/
typedef struct MatchInfo MatchInfo;
struct MatchInfo {
  Fts3Cursor *pCursor;            /* FTS3 Cursor */
  int nCol;                       /* Number of columns in table */
  int nPhrase;                    /* Number of matchable phrases in query */
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
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







-
+

+
-
-
+
+

-
+

-

-
-
+
+
+







/*************************************************************************
** Start of MatchinfoBuffer code.
*/

/*
** Allocate a two-slot MatchinfoBuffer object.
*/
static MatchinfoBuffer *fts3MIBufferNew(int nElem, const char *zMatchinfo){
static MatchinfoBuffer *fts3MIBufferNew(size_t nElem, const char *zMatchinfo){
  MatchinfoBuffer *pRet;
  sqlite3_int64 nByte = sizeof(u32) * (2*(sqlite3_int64)nElem + 1)
  int nByte = sizeof(u32) * (2*nElem + 1) + sizeof(MatchinfoBuffer);
  int nStr = (int)strlen(zMatchinfo);
                           + sizeof(MatchinfoBuffer);
  sqlite3_int64 nStr = strlen(zMatchinfo);

  pRet = sqlite3_malloc(nByte + nStr+1);
  pRet = sqlite3Fts3MallocZero(nByte + nStr+1);
  if( pRet ){
    memset(pRet, 0, nByte);
    pRet->aMatchinfo[0] = (u8*)(&pRet->aMatchinfo[1]) - (u8*)pRet;
    pRet->aMatchinfo[1+nElem] = pRet->aMatchinfo[0] + sizeof(u32)*(nElem+1);
    pRet->nElem = nElem;
    pRet->aMatchinfo[1+nElem] = pRet->aMatchinfo[0]
                                      + sizeof(u32)*((int)nElem+1);
    pRet->nElem = (int)nElem;
    pRet->zMatchinfo = ((char*)pRet) + nByte;
    memcpy(pRet->zMatchinfo, zMatchinfo, nStr+1);
    pRet->aRef[0] = 1;
  }

  return pRet;
}
174
175
176
177
178
179
180
181

182
183
184
185
186
187
188
179
180
181
182
183
184
185

186
187
188
189
190
191
192
193







-
+







    xRet = fts3MIBufferFree;
  }
  else if( p->aRef[2]==0 ){
    p->aRef[2] = 1;
    aOut = &p->aMatchinfo[p->nElem+2];
    xRet = fts3MIBufferFree;
  }else{
    aOut = (u32*)sqlite3_malloc(p->nElem * sizeof(u32));
    aOut = (u32*)sqlite3_malloc64(p->nElem * sizeof(u32));
    if( aOut ){
      xRet = sqlite3_free;
      if( p->bGlobal ) memcpy(aOut, &p->aMatchinfo[1], p->nElem*sizeof(u32));
    }
  }

  *paOut = aOut;
228
229
230
231
232
233
234
235

236
237
238
239
240
241
242

243
244
245
246
247
248
249
233
234
235
236
237
238
239

240
241
242
243
244
245
246

247
248
249
250
251
252
253
254







-
+






-
+







** 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).
** Helper function for sqlite3Fts3ExprIterate() (see below).
*/
static int fts3ExprIterate2(
  Fts3Expr *pExpr,                /* Expression to iterate phrases of */
  int *piPhrase,                  /* Pointer to phrase counter */
  int (*x)(Fts3Expr*,int,void*),  /* Callback function to invoke for phrases */
  void *pCtx                      /* Second argument to pass to callback */
){
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
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







-
+








-

-
-
+
+







** For each phrase node found, the supplied callback function is invoked.
**
** If the callback function returns anything other than SQLITE_OK, 
** the iteration is abandoned and the error code returned immediately.
** Otherwise, SQLITE_OK is returned after a callback has been made for
** all eligible phrase nodes.
*/
static int fts3ExprIterate(
int sqlite3Fts3ExprIterate(
  Fts3Expr *pExpr,                /* Expression to iterate phrases of */
  int (*x)(Fts3Expr*,int,void*),  /* Callback function to invoke for phrases */
  void *pCtx                      /* Second argument to pass to callback */
){
  int iPhrase = 0;                /* Variable used as the phrase counter */
  return fts3ExprIterate2(pExpr, &iPhrase, x, pCtx);
}


/*
** This is an fts3ExprIterate() callback used while loading the doclists
** for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also
** This is an sqlite3Fts3ExprIterate() callback used while loading the 
** doclists for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also
** fts3ExprLoadDoclists().
*/
static int fts3ExprLoadDoclistsCb(Fts3Expr *pExpr, int iPhrase, void *ctx){
  int rc = SQLITE_OK;
  Fts3Phrase *pPhrase = pExpr->pPhrase;
  LoadDoclistCtx *p = (LoadDoclistCtx *)ctx;

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







-
+

-
+












-
+








-
+


-
+







*/
static int fts3ExprLoadDoclists(
  Fts3Cursor *pCsr,               /* Fts3 cursor for current query */
  int *pnPhrase,                  /* OUT: Number of phrases in query */
  int *pnToken                    /* OUT: Number of tokens in query */
){
  int rc;                         /* Return Code */
  LoadDoclistCtx sCtx = {0,0,0};  /* Context for fts3ExprIterate() */
  LoadDoclistCtx sCtx = {0,0,0};  /* Context for sqlite3Fts3ExprIterate() */
  sCtx.pCsr = pCsr;
  rc = fts3ExprIterate(pCsr->pExpr, fts3ExprLoadDoclistsCb, (void *)&sCtx);
  rc = sqlite3Fts3ExprIterate(pCsr->pExpr,fts3ExprLoadDoclistsCb,(void*)&sCtx);
  if( pnPhrase ) *pnPhrase = sCtx.nPhrase;
  if( pnToken ) *pnToken = sCtx.nToken;
  return rc;
}

static int fts3ExprPhraseCountCb(Fts3Expr *pExpr, int iPhrase, void *ctx){
  (*(int *)ctx)++;
  pExpr->iPhrase = iPhrase;
  return SQLITE_OK;
}
static int fts3ExprPhraseCount(Fts3Expr *pExpr){
  int nPhrase = 0;
  (void)fts3ExprIterate(pExpr, fts3ExprPhraseCountCb, (void *)&nPhrase);
  (void)sqlite3Fts3ExprIterate(pExpr, fts3ExprPhraseCountCb, (void *)&nPhrase);
  return nPhrase;
}

/*
** 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;
      }
423
424
425
426
427
428
429
430

431
432

433
434

435
436


437
438
439
440
441
442
443
427
428
429
430
431
432
433

434
435

436
437

438
439

440
441
442
443
444
445
446
447
448







-
+

-
+

-
+

-
+
+







  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) ){
      while( iCsr<(iStart+pIter->nSnippet) && iCsr>=iStart ){
        int j;
        u64 mPhrase = (u64)1 << i;
        u64 mPhrase = (u64)1 << (i%64);
        u64 mPos = (u64)1 << (iCsr - iStart);
        assert( iCsr>=iStart );
        assert( iCsr>=iStart && (iCsr - iStart)<=64 );
        assert( i>=0 );
        if( (mCover|mCovered)&mPhrase ){
          iScore++;
        }else{
          iScore += 1000;
        }
        mCover |= mPhrase;

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







-
-
+
+
+











-
+


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







  *piToken = iStart;
  *piScore = iScore;
  *pmCover = mCover;
  *pmHighlight = mHighlight;
}

/*
** This function is an fts3ExprIterate() callback used by fts3BestSnippet().
** Each invocation populates an element of the SnippetIter.aPhrase[] array.
** This function is an sqlite3Fts3ExprIterate() callback used by
** fts3BestSnippet().  Each invocation populates an element of the
** SnippetIter.aPhrase[] array.
*/
static int fts3SnippetFindPositions(Fts3Expr *pExpr, int iPhrase, void *ctx){
  SnippetIter *p = (SnippetIter *)ctx;
  SnippetPhrase *pPhrase = &p->aPhrase[iPhrase];
  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);
    assert( iFirst>=0 );
    pPhrase->pHead = pCsr;
    pPhrase->pTail = pCsr;
    pPhrase->iHead = iFirst;
    pPhrase->iTail = iFirst;
    if( iFirst<0 ){
      rc = FTS_CORRUPT_VTAB;
    }else{
      pPhrase->pHead = pCsr;
      pPhrase->pTail = pCsr;
      pPhrase->iHead = iFirst;
      pPhrase->iTail = iFirst;
    }
  }else{
    assert( rc!=SQLITE_OK || (
       pPhrase->pList==0 && pPhrase->pHead==0 && pPhrase->pTail==0 
    ));
  }

  return rc;
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
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







-
+

















-
+



-









+
-
+
+





-
+







  u64 *pmSeen,                    /* IN/OUT: Mask of phrases seen */
  SnippetFragment *pFragment,     /* OUT: Best snippet found */
  int *piScore                    /* OUT: Score of snippet pFragment */
){
  int rc;                         /* Return Code */
  int nList;                      /* Number of phrases in expression */
  SnippetIter sIter;              /* Iterates through snippet candidates */
  int nByte;                      /* Number of bytes of space to allocate */
  sqlite3_int64 nByte;            /* Number of bytes of space to allocate */
  int iBestScore = -1;            /* Best snippet score found so far */
  int i;                          /* Loop counter */

  memset(&sIter, 0, sizeof(sIter));

  /* Iterate through the phrases in the expression to count them. The same
  ** callback makes sure the doclists are loaded for each phrase.
  */
  rc = fts3ExprLoadDoclists(pCsr, &nList, 0);
  if( rc!=SQLITE_OK ){
    return rc;
  }

  /* Now that it is known how many phrases there are, allocate and zero
  ** the required space using malloc().
  */
  nByte = sizeof(SnippetPhrase) * nList;
  sIter.aPhrase = (SnippetPhrase *)sqlite3_malloc(nByte);
  sIter.aPhrase = (SnippetPhrase *)sqlite3Fts3MallocZero(nByte);
  if( !sIter.aPhrase ){
    return SQLITE_NOMEM;
  }
  memset(sIter.aPhrase, 0, nByte);

  /* Initialize the contents of the SnippetIter object. Then iterate through
  ** the set of phrases in the expression to populate the aPhrase[] array.
  */
  sIter.pCsr = pCsr;
  sIter.iCol = iCol;
  sIter.nSnippet = nSnippet;
  sIter.nPhrase = nList;
  sIter.iCurrent = -1;
  rc = sqlite3Fts3ExprIterate(
  rc = fts3ExprIterate(pCsr->pExpr, fts3SnippetFindPositions, (void*)&sIter);
      pCsr->pExpr, fts3SnippetFindPositions, (void*)&sIter
  );
  if( rc==SQLITE_OK ){

    /* Set the *pmSeen output variable. */
    for(i=0; i<nList; i++){
      if( sIter.aPhrase[i].pHead ){
        *pmSeen |= (u64)1 << i;
        *pmSeen |= (u64)1 << (i%64);
      }
    }

    /* Loop through all candidate snippets. Store the best snippet in 
     ** *pFragment. Store its associated 'score' in iBestScore.
     */
    pFragment->iCol = iCol;
600
601
602
603
604
605
606
607
608


609
610
611
612
613
614
615
610
611
612
613
614
615
616


617
618
619
620
621
622
623
624
625







-
-
+
+







  }

  /* If there is insufficient space allocated at StrBuffer.z, use realloc()
  ** to grow the buffer until so that it is big enough to accomadate the
  ** appended data.
  */
  if( pStr->n+nAppend+1>=pStr->nAlloc ){
    int nAlloc = pStr->nAlloc+nAppend+100;
    char *zNew = sqlite3_realloc(pStr->z, nAlloc);
    sqlite3_int64 nAlloc = pStr->nAlloc+(sqlite3_int64)nAppend+100;
    char *zNew = sqlite3_realloc64(pStr->z, nAlloc);
    if( !zNew ){
      return SQLITE_NOMEM;
    }
    pStr->z = zNew;
    pStr->nAlloc = nAlloc;
  }
  assert( pStr->z!=0 && (pStr->nAlloc >= pStr->n+nAppend+1) );
656
657
658
659
660
661
662

663
664
665
666
667
668
669
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680







+







  if( hlmask ){
    int nLeft;                    /* Tokens to the left of first highlight */
    int nRight;                   /* Tokens to the right of last highlight */
    int nDesired;                 /* Ideal number of tokens to shift forward */

    for(nLeft=0; !(hlmask & ((u64)1 << nLeft)); nLeft++);
    for(nRight=0; !(hlmask & ((u64)1 << (nSnippet-1-nRight))); nRight++);
    assert( (nSnippet-1-nRight)<=63 && (nSnippet-1-nRight)>=0 );
    nDesired = (nLeft-nRight)/2;

    /* Ideally, the start of the snippet should be pushed forward in the
    ** document nDesired tokens. This block checks if there are actually
    ** nDesired tokens to the right of the snippet. If so, *piPos and
    ** *pHlMask are updated to shift the snippet nDesired tokens to the
    ** right. Otherwise, the snippet is shifted by the number of tokens
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


900
901

902
903

904
905
906
907
908


909
910

911
912
913
914
915
916
917
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
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







-
+
















-
+












+

+





-
+



+



-
-
+
+

-
+


+



-
-
+
+

-
+







  *ppCollist = pEnd;
  return nEntry;
}

/*
** This function gathers 'y' or 'b' data for a single phrase.
*/
static void fts3ExprLHits(
static int fts3ExprLHits(
  Fts3Expr *pExpr,                /* Phrase expression node */
  MatchInfo *p                    /* Matchinfo context */
){
  Fts3Table *pTab = (Fts3Table *)p->pCursor->base.pVtab;
  int iStart;
  Fts3Phrase *pPhrase = pExpr->pPhrase;
  char *pIter = pPhrase->doclist.pList;
  int iCol = 0;

  assert( p->flag==FTS3_MATCHINFO_LHITS_BM || p->flag==FTS3_MATCHINFO_LHITS );
  if( p->flag==FTS3_MATCHINFO_LHITS ){
    iStart = pExpr->iPhrase * p->nCol;
  }else{
    iStart = pExpr->iPhrase * ((p->nCol + 31) / 32);
  }

  while( 1 ){
  if( pIter ) while( 1 ){
    int nHit = fts3ColumnlistCount(&pIter);
    if( (pPhrase->iColumn>=pTab->nColumn || pPhrase->iColumn==iCol) ){
      if( p->flag==FTS3_MATCHINFO_LHITS ){
        p->aMatchinfo[iStart + iCol] = (u32)nHit;
      }else if( nHit ){
        p->aMatchinfo[iStart + (iCol+1)/32] |= (1 << (iCol&0x1F));
      }
    }
    assert( *pIter==0x00 || *pIter==0x01 );
    if( *pIter!=0x01 ) break;
    pIter++;
    pIter += fts3GetVarint32(pIter, &iCol);
    if( iCol>=p->nCol ) return FTS_CORRUPT_VTAB;
  }
  return SQLITE_OK;
}

/*
** Gather the results for matchinfo directives 'y' and 'b'.
*/
static void fts3ExprLHitGather(
static int fts3ExprLHitGather(
  Fts3Expr *pExpr,
  MatchInfo *p
){
  int rc = SQLITE_OK;
  assert( (pExpr->pLeft==0)==(pExpr->pRight==0) );
  if( pExpr->bEof==0 && pExpr->iDocid==p->pCursor->iPrevId ){
    if( pExpr->pLeft ){
      fts3ExprLHitGather(pExpr->pLeft, p);
      fts3ExprLHitGather(pExpr->pRight, p);
      rc = fts3ExprLHitGather(pExpr->pLeft, p);
      if( rc==SQLITE_OK ) rc = fts3ExprLHitGather(pExpr->pRight, p);
    }else{
      fts3ExprLHits(pExpr, p);
      rc = fts3ExprLHits(pExpr, p);
    }
  }
  return rc;
}

/*
** fts3ExprIterate() callback used to collect the "global" matchinfo stats
** for a single query. 
** sqlite3Fts3ExprIterate() callback used to collect the "global" matchinfo
** stats for a single query. 
**
** fts3ExprIterate() callback to load the 'global' elements of a
** sqlite3Fts3ExprIterate() callback to load the 'global' elements of a
** FTS3_MATCHINFO_HITS matchinfo array. The global stats are those elements 
** of the matchinfo array that are constant for all rows returned by the 
** current query.
**
** Argument pCtx is actually a pointer to a struct of type MatchInfo. This
** function populates Matchinfo.aMatchinfo[] as follows:
**
938
939
940
941
942
943
944
945

946
947
948
949
950
951
952
953
954
955
956
957
958
959

960
961
962
963
964
965
966
967







-
+







  MatchInfo *p = (MatchInfo *)pCtx;
  return sqlite3Fts3EvalPhraseStats(
      p->pCursor, pExpr, &p->aMatchinfo[3*iPhrase*p->nCol]
  );
}

/*
** fts3ExprIterate() callback used to collect the "local" part of the
** sqlite3Fts3ExprIterate() callback used to collect the "local" part of the
** FTS3_MATCHINFO_HITS array. The local stats are those elements of the 
** array that are different for each row returned by the query.
*/
static int fts3ExprLocalHitsCb(
  Fts3Expr *pExpr,                /* Phrase expression node */
  int iPhrase,                    /* Phrase number */
  void *pCtx                      /* Pointer to MatchInfo structure */
986
987
988
989
990
991
992
993
994


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


1008
1009
1010
1011
1012
1013
1014
1015
1016







-
-
+
+







  ){
    return SQLITE_OK;
  }
  sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo request: %c", cArg);
  return SQLITE_ERROR;
}

static int fts3MatchinfoSize(MatchInfo *pInfo, char cArg){
  int nVal;                       /* Number of integers output by cArg */
static size_t fts3MatchinfoSize(MatchInfo *pInfo, char cArg){
  size_t nVal;                      /* Number of integers output by cArg */

  switch( cArg ){
    case FTS3_MATCHINFO_NDOC:
    case FTS3_MATCHINFO_NPHRASE: 
    case FTS3_MATCHINFO_NCOL: 
      nVal = 1;
      break;
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
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







-
+
+



+

+
+








+

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


+







  return nVal;
}

static int fts3MatchinfoSelectDoctotal(
  Fts3Table *pTab,
  sqlite3_stmt **ppStmt,
  sqlite3_int64 *pnDoc,
  const char **paLen
  const char **paLen,
  const char **ppEnd
){
  sqlite3_stmt *pStmt;
  const char *a;
  const char *pEnd;
  sqlite3_int64 nDoc;
  int n;


  if( !*ppStmt ){
    int rc = sqlite3Fts3SelectDoctotal(pTab, ppStmt);
    if( rc!=SQLITE_OK ) return rc;
  }
  pStmt = *ppStmt;
  assert( sqlite3_data_count(pStmt)==1 );

  n = sqlite3_column_bytes(pStmt, 0);
  a = sqlite3_column_blob(pStmt, 0);
  if( a==0 ){
    return FTS_CORRUPT_VTAB;
  }
  pEnd = a + n;
  a += sqlite3Fts3GetVarint(a, &nDoc);
  if( nDoc==0 ) return FTS_CORRUPT_VTAB;
  *pnDoc = (u32)nDoc;
  a += sqlite3Fts3GetVarintBounded(a, pEnd, &nDoc);
  if( nDoc<=0 || a>pEnd ){
    return FTS_CORRUPT_VTAB;
  }
  *pnDoc = nDoc;

  if( paLen ) *paLen = a;
  if( ppEnd ) *ppEnd = pEnd;
  return SQLITE_OK;
}

/*
** An instance of the following structure is used to store state while 
** iterating through a multi-column position-list corresponding to the
** hits for a single phrase on a single row in order to calculate the
1081
1082
1083
1084
1085
1086
1087
1088

1089
1090
1091


1092
1093
1094
1095
1096
1097
1098
1108
1109
1110
1111
1112
1113
1114

1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127







-
+



+
+








/*
** Advance the iterator passed as an argument to the next position. Return
** 1 if the iterator is at EOF or if it now points to the start of the
** position list for the next column.
*/
static int fts3LcsIteratorAdvance(LcsIterator *pIter){
  char *pRead = pIter->pRead;
  char *pRead;
  sqlite3_int64 iRead;
  int rc = 0;

  if( NEVER(pIter==0) ) return 1;
  pRead = pIter->pRead;
  pRead += sqlite3Fts3GetVarint(pRead, &iRead);
  if( iRead==0 || iRead==1 ){
    pRead = 0;
    rc = 1;
  }else{
    pIter->iPos += (int)(iRead-2);
  }
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
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







+




-
+

-
-
+












-


-
+


-
+
+
+
+
+







** undefined.
*/
static int fts3MatchinfoLcs(Fts3Cursor *pCsr, MatchInfo *pInfo){
  LcsIterator *aIter;
  int i;
  int iCol;
  int nToken = 0;
  int rc = SQLITE_OK;

  /* Allocate and populate the array of LcsIterator objects. The array
  ** contains one element for each matchable phrase in the query.
  **/
  aIter = sqlite3_malloc(sizeof(LcsIterator) * pCsr->nPhrase);
  aIter = sqlite3Fts3MallocZero(sizeof(LcsIterator) * pCsr->nPhrase);
  if( !aIter ) return SQLITE_NOMEM;
  memset(aIter, 0, sizeof(LcsIterator) * pCsr->nPhrase);
  (void)fts3ExprIterate(pCsr->pExpr, fts3MatchinfoLcsCb, (void*)aIter);
  (void)sqlite3Fts3ExprIterate(pCsr->pExpr, fts3MatchinfoLcsCb, (void*)aIter);

  for(i=0; i<pInfo->nPhrase; i++){
    LcsIterator *pIter = &aIter[i];
    nToken -= pIter->pExpr->pPhrase->nToken;
    pIter->iPosOffset = nToken;
  }

  for(iCol=0; iCol<pInfo->nCol; iCol++){
    int nLcs = 0;                 /* LCS value for this column */
    int nLive = 0;                /* Number of iterators in aIter not at EOF */

    for(i=0; i<pInfo->nPhrase; i++){
      int rc;
      LcsIterator *pIt = &aIter[i];
      rc = sqlite3Fts3EvalPhrasePoslist(pCsr, pIt->pExpr, iCol, &pIt->pRead);
      if( rc!=SQLITE_OK ) return rc;
      if( rc!=SQLITE_OK ) goto matchinfo_lcs_out;
      if( pIt->pRead ){
        pIt->iPos = pIt->iPosOffset;
        fts3LcsIteratorAdvance(&aIter[i]);
        fts3LcsIteratorAdvance(pIt);
        if( pIt->pRead==0 ){
          rc = FTS_CORRUPT_VTAB;
          goto matchinfo_lcs_out;
        }
        nLive++;
      }
    }

    while( nLive>0 ){
      LcsIterator *pAdv = 0;      /* The iterator to advance by one position */
      int nThisLcs = 0;           /* LCS for the current iterator positions */
1171
1172
1173
1174
1175
1176
1177

1178
1179

1180
1181
1182
1183
1184
1185
1186
1203
1204
1205
1206
1207
1208
1209
1210
1211

1212
1213
1214
1215
1216
1217
1218
1219







+

-
+







      }
      if( fts3LcsIteratorAdvance(pAdv) ) nLive--;
    }

    pInfo->aMatchinfo[iCol] = nLcs;
  }

 matchinfo_lcs_out:
  sqlite3_free(aIter);
  return SQLITE_OK;
  return rc;
}

/*
** Populate the buffer pInfo->aMatchinfo[] with an array of integers to
** be returned by the matchinfo() function. Argument zArg contains the 
** format string passed as the second argument to matchinfo (or the
** default value "pcx" if no second argument was specified). The format
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
1286
1287

1288
1289
1290

1291
1292
1293
1294

1295
1296
1297
1298
1299
1300
1301
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
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

1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329

1330
1331
1332

1333
1334
1335
1336

1337
1338
1339
1340
1341
1342
1343
1344







-
+








+

-
+






+
+
+
+













+


-
+
+
+
+
+
















-
+

-
+











-
+


-
+



-
+







      case FTS3_MATCHINFO_NCOL:
        if( bGlobal ) pInfo->aMatchinfo[0] = pInfo->nCol;
        break;
        
      case FTS3_MATCHINFO_NDOC:
        if( bGlobal ){
          sqlite3_int64 nDoc = 0;
          rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, 0);
          rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, 0, 0);
          pInfo->aMatchinfo[0] = (u32)nDoc;
        }
        break;

      case FTS3_MATCHINFO_AVGLENGTH: 
        if( bGlobal ){
          sqlite3_int64 nDoc;     /* Number of rows in table */
          const char *a;          /* Aggregate column length array */
          const char *pEnd;       /* First byte past end of length array */

          rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, &a);
          rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, &a, &pEnd);
          if( rc==SQLITE_OK ){
            int iCol;
            for(iCol=0; iCol<pInfo->nCol; iCol++){
              u32 iVal;
              sqlite3_int64 nToken;
              a += sqlite3Fts3GetVarint(a, &nToken);
              if( a>pEnd ){
                rc = SQLITE_CORRUPT_VTAB;
                break;
              }
              iVal = (u32)(((u32)(nToken&0xffffffff)+nDoc/2)/nDoc);
              pInfo->aMatchinfo[iCol] = iVal;
            }
          }
        }
        break;

      case FTS3_MATCHINFO_LENGTH: {
        sqlite3_stmt *pSelectDocsize = 0;
        rc = sqlite3Fts3SelectDocsize(pTab, pCsr->iPrevId, &pSelectDocsize);
        if( rc==SQLITE_OK ){
          int iCol;
          const char *a = sqlite3_column_blob(pSelectDocsize, 0);
          const char *pEnd = a + sqlite3_column_bytes(pSelectDocsize, 0);
          for(iCol=0; iCol<pInfo->nCol; iCol++){
            sqlite3_int64 nToken;
            a += sqlite3Fts3GetVarint(a, &nToken);
            a += sqlite3Fts3GetVarintBounded(a, pEnd, &nToken);
            if( a>pEnd ){
              rc = SQLITE_CORRUPT_VTAB;
              break;
            }
            pInfo->aMatchinfo[iCol] = (u32)nToken;
          }
        }
        sqlite3_reset(pSelectDocsize);
        break;
      }

      case FTS3_MATCHINFO_LCS:
        rc = fts3ExprLoadDoclists(pCsr, 0, 0);
        if( rc==SQLITE_OK ){
          rc = fts3MatchinfoLcs(pCsr, pInfo);
        }
        break;

      case FTS3_MATCHINFO_LHITS_BM:
      case FTS3_MATCHINFO_LHITS: {
        int nZero = fts3MatchinfoSize(pInfo, zArg[i]) * sizeof(u32);
        size_t nZero = fts3MatchinfoSize(pInfo, zArg[i]) * sizeof(u32);
        memset(pInfo->aMatchinfo, 0, nZero);
        fts3ExprLHitGather(pCsr->pExpr, pInfo);
        rc = fts3ExprLHitGather(pCsr->pExpr, pInfo);
        break;
      }

      default: {
        Fts3Expr *pExpr;
        assert( zArg[i]==FTS3_MATCHINFO_HITS );
        pExpr = pCsr->pExpr;
        rc = fts3ExprLoadDoclists(pCsr, 0, 0);
        if( rc!=SQLITE_OK ) break;
        if( bGlobal ){
          if( pCsr->pDeferred ){
            rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &pInfo->nDoc, 0);
            rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &pInfo->nDoc,0,0);
            if( rc!=SQLITE_OK ) break;
          }
          rc = fts3ExprIterate(pExpr, fts3ExprGlobalHitsCb,(void*)pInfo);
          rc = sqlite3Fts3ExprIterate(pExpr, fts3ExprGlobalHitsCb,(void*)pInfo);
          sqlite3Fts3EvalTestDeferred(pCsr, &rc);
          if( rc!=SQLITE_OK ) break;
        }
        (void)fts3ExprIterate(pExpr, fts3ExprLocalHitsCb,(void*)pInfo);
        (void)sqlite3Fts3ExprIterate(pExpr, fts3ExprLocalHitsCb,(void*)pInfo);
        break;
      }
    }

    pInfo->aMatchinfo += fts3MatchinfoSize(pInfo, zArg[i]);
  }

1335
1336
1337
1338
1339
1340
1341
1342

1343
1344
1345
1346
1347
1348
1349
1378
1379
1380
1381
1382
1383
1384

1385
1386
1387
1388
1389
1390
1391
1392







-
+








  /* If Fts3Cursor.pMIBuffer is NULL, then this is the first time the
  ** matchinfo function has been called for this query. In this case 
  ** allocate the array used to accumulate the matchinfo data and
  ** initialize those elements that are constant for every row.
  */
  if( pCsr->pMIBuffer==0 ){
    int nMatchinfo = 0;           /* Number of u32 elements in match-info */
    size_t nMatchinfo = 0;        /* Number of u32 elements in match-info */
    int i;                        /* Used to iterate through zArg */

    /* Determine the number of phrases in the query */
    pCsr->nPhrase = fts3ExprPhraseCount(pCsr->pExpr);
    sInfo.nPhrase = pCsr->nPhrase;

    /* Determine the number of integers in the buffer returned by this call. */
1419
1420
1421
1422
1423
1424
1425




1426
1427
1428
1429
1430
1431
1432
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479







+
+
+
+







  SnippetFragment aSnippet[4];    /* Maximum of 4 fragments per snippet */
  int nFToken = -1;               /* Number of tokens in each fragment */

  if( !pCsr->pExpr ){
    sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC);
    return;
  }

  /* Limit the snippet length to 64 tokens. */
  if( nToken<-64 ) nToken = -64;
  if( nToken>+64 ) nToken = +64;

  for(nSnippet=1; 1; nSnippet++){

    int iSnip;                    /* Loop counter 0..nSnippet-1 */
    u64 mCovered = 0;             /* Bitmask of phrases covered by snippet */
    u64 mSeen = 0;                /* Bitmask of phrases seen by BestSnippet() */

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
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
1574

1575
1576
1577
1578
1579
1580
1581
1582







-
-
+
+











-
+






-
+







-
+









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().
** This function is an sqlite3Fts3ExprIterate() 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);
    assert( iPos>=0 );
    assert_fts3_nc( iPos>=0 );
  }

  for(iTerm=0; iTerm<nTerm; iTerm++){
    TermOffset *pT = &p->aTerm[p->iTerm++];
    pT->iOff = nTerm-iTerm-1;
    pT->pList = pList;
    pT->iPos = iPos;
1562
1563
1564
1565
1566
1567
1568
1569

1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591


1592
1593
1594
1595

1596



1597
1598
1599
1600
1601
1602
1603
1609
1610
1611
1612
1613
1614
1615

1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636


1637
1638

1639
1640
1641
1642

1643
1644
1645
1646
1647
1648
1649
1650
1651
1652







-
+




















-
-
+
+
-



+
-
+
+
+







  assert( pCsr->isRequireSeek==0 );

  /* Count the number of terms in the query */
  rc = fts3ExprLoadDoclists(pCsr, 0, &nToken);
  if( rc!=SQLITE_OK ) goto offsets_out;

  /* Allocate the array of TermOffset iterators. */
  sCtx.aTerm = (TermOffset *)sqlite3_malloc(sizeof(TermOffset)*nToken);
  sCtx.aTerm = (TermOffset *)sqlite3Fts3MallocZero(sizeof(TermOffset)*nToken);
  if( 0==sCtx.aTerm ){
    rc = SQLITE_NOMEM;
    goto offsets_out;
  }
  sCtx.iDocid = pCsr->iPrevId;
  sCtx.pCsr = pCsr;

  /* Loop through the table columns, appending offset information to 
  ** string-buffer res for each column.
  */
  for(iCol=0; iCol<pTab->nColumn; iCol++){
    sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor */
    const char *ZDUMMY;           /* Dummy argument used with xNext() */
    int NDUMMY = 0;               /* Dummy argument used with xNext() */
    int iStart = 0;
    int iEnd = 0;
    int iCurrent = 0;
    const char *zDoc;
    int nDoc;

    /* Initialize the contents of sCtx.aTerm[] for column iCol. There is 
    ** no way that this operation can fail, so the return code from
    /* Initialize the contents of sCtx.aTerm[] for column iCol. This 
    ** operation may fail if the database contains corrupt records.
    ** fts3ExprIterate() can be discarded.
    */
    sCtx.iCol = iCol;
    sCtx.iTerm = 0;
    rc = sqlite3Fts3ExprIterate(
    (void)fts3ExprIterate(pCsr->pExpr, fts3ExprTermOffsetInit, (void*)&sCtx);
        pCsr->pExpr, fts3ExprTermOffsetInit, (void*)&sCtx
    );
    if( rc!=SQLITE_OK ) goto offsets_out;

    /* Retreive the text stored in column iCol. If an SQL NULL is stored 
    ** in column iCol, jump immediately to the next iteration of the loop.
    ** If an OOM occurs while retrieving the data (this can happen if SQLite
    ** needs to transform the data from utf-16 to utf-8), return SQLITE_NOMEM 
    ** to the caller. 
    */
1631
1632
1633
1634
1635
1636
1637
1638

1639
1640
1641
1642
1643
1644
1645
1680
1681
1682
1683
1684
1685
1686

1687
1688
1689
1690
1691
1692
1693
1694







-
+







        }
      }

      if( !pTerm ){
        /* All offsets for this column have been gathered. */
        rc = SQLITE_DONE;
      }else{
        assert( iCurrent<=iMinPos );
        assert_fts3_nc( iCurrent<=iMinPos );
        if( 0==(0xFE&*pTerm->pList) ){
          pTerm->pList = 0;
        }else{
          fts3GetDeltaPosition(&pTerm->pList, &pTerm->iPos);
        }
        while( rc==SQLITE_OK && iCurrent<iMinPos ){
          rc = pMod->xNext(pC, &ZDUMMY, &NDUMMY, &iStart, &iEnd, &iCurrent);

Changes to ext/fts3/fts3_term.c.

64
65
66
67
68
69
70
71

72
73

74
75
76
77
78
79
80
64
65
66
67
68
69
70

71
72

73
74
75
76
77
78
79
80







-
+

-
+







  sqlite3_vtab **ppVtab,          /* OUT: New sqlite3_vtab object */
  char **pzErr                    /* OUT: sqlite3_malloc'd error message */
){
  char const *zDb;                /* Name of database (e.g. "main") */
  char const *zFts3;              /* Name of fts3 table */
  int nDb;                        /* Result of strlen(zDb) */
  int nFts3;                      /* Result of strlen(zFts3) */
  int nByte;                      /* Bytes of space to allocate here */
  sqlite3_int64 nByte;            /* Bytes of space to allocate here */
  int rc;                         /* value returned by declare_vtab() */
  Fts3termTable *p;                /* Virtual table object to return */
  Fts3termTable *p;               /* Virtual table object to return */
  int iIndex = 0;

  UNUSED_PARAMETER(pCtx);
  if( argc==5 ){
    iIndex = atoi(argv[4]);
    argc--;
  }
92
93
94
95
96
97
98
99

100
101

102
103
104
105
106
107
108
92
93
94
95
96
97
98

99
100

101
102
103
104
105
106
107
108







-
+

-
+







  zFts3 = argv[3];
  nFts3 = (int)strlen(zFts3);

  rc = sqlite3_declare_vtab(db, FTS3_TERMS_SCHEMA);
  if( rc!=SQLITE_OK ) return rc;

  nByte = sizeof(Fts3termTable) + sizeof(Fts3Table) + nDb + nFts3 + 2;
  p = (Fts3termTable *)sqlite3_malloc(nByte);
  p = (Fts3termTable *)sqlite3_malloc64(nByte);
  if( !p ) return SQLITE_NOMEM;
  memset(p, 0, nByte);
  memset(p, 0, (size_t)nByte);

  p->pFts3Tab = (Fts3Table *)&p[1];
  p->pFts3Tab->zDb = (char *)&p->pFts3Tab[1];
  p->pFts3Tab->zName = &p->pFts3Tab->zDb[nDb+1];
  p->pFts3Tab->db = db;
  p->pFts3Tab->nIndex = iIndex+1;
  p->iIndex = iIndex;

Changes to ext/fts3/fts3_test.c.

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







-
+

-
+




-
+















-
+







  while( p<pEnd && testIsTokenChar(*p)==0 ) p++;

  if( p==pEnd ){
    rc = SQLITE_DONE;
  }else{
    /* Advance to the end of the token */
    const char *pToken = p;
    int nToken;
    sqlite3_int64 nToken;
    while( p<pEnd && testIsTokenChar(*p) ) p++;
    nToken = (int)(p-pToken);
    nToken = (sqlite3_int64)(p-pToken);

    /* Copy the token into the buffer */
    if( nToken>pCsr->nBuffer ){
      sqlite3_free(pCsr->aBuffer);
      pCsr->aBuffer = sqlite3_malloc(nToken);
      pCsr->aBuffer = sqlite3_malloc64(nToken);
    }
    if( pCsr->aBuffer==0 ){
      rc = SQLITE_NOMEM;
    }else{
      int i;

      if( pCsr->iLangid & 0x00000001 ){
        for(i=0; i<nToken; i++) pCsr->aBuffer[i] = pToken[i];
      }else{
        for(i=0; i<nToken; i++) pCsr->aBuffer[i] = (char)testTolower(pToken[i]);
      }
      pCsr->iToken++;
      pCsr->iInput = (int)(p - pCsr->aInput);

      *ppToken = pCsr->aBuffer;
      *pnBytes = nToken;
      *pnBytes = (int)nToken;
      *piStartOffset = (int)(pToken - pCsr->aInput);
      *piEndOffset = (int)(p - pCsr->aInput);
      *piPosition = pCsr->iToken;
    }
  }

  return rc;
569
570
571
572
573
574
575





























576
577
578
579
580
581
582
583
584
585
586
587
588



589
590
591
592
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







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









-



+
+
+




  UNUSED_PARAMETER(clientData);
  return TCL_OK;
}

/* 
** End of tokenizer code.
**************************************************************************/ 

/*
**      sqlite3_fts3_may_be_corrupt BOOLEAN
**
** Set or clear the global "may-be-corrupt" flag. Return the old value.
*/
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
  );
  Tcl_CreateObjCommand(
      interp, "fts3_test_tokenizer", fts3_test_tokenizer_cmd, 0, 0
  );

  Tcl_CreateObjCommand(
      interp, "fts3_test_varint", fts3_test_varint_cmd, 0, 0
  );
  Tcl_CreateObjCommand(
      interp, "sqlite3_fts3_may_be_corrupt", fts3_may_be_corrupt, 0, 0
  );
  return TCL_OK;
}
#endif                  /* SQLITE_ENABLE_FTS3 || SQLITE_ENABLE_FTS4 */
#endif                  /* ifdef SQLITE_TEST */

Changes to ext/fts3/fts3_tokenize_vtab.c.

118
119
120
121
122
123
124
125

126
127
128
129
130
131
132
118
119
120
121
122
123
124

125
126
127
128
129
130
131
132







-
+







    int nByte = 0;
    char **azDequote;

    for(i=0; i<argc; i++){
      nByte += (int)(strlen(argv[i]) + 1);
    }

    *pazDequote = azDequote = sqlite3_malloc(sizeof(char *)*argc + nByte);
    *pazDequote = azDequote = sqlite3_malloc64(sizeof(char *)*argc + nByte);
    if( azDequote==0 ){
      rc = SQLITE_NOMEM;
    }else{
      char *pSpace = (char *)&azDequote[argc];
      for(i=0; i<argc; i++){
        int n = (int)strlen(argv[i]);
        azDequote[i] = pSpace;
184
185
186
187
188
189
190
191


192
193
194
195
196
197
198
184
185
186
187
188
189
190

191
192
193
194
195
196
197
198
199







-
+
+







      zModule = azDequote[0];
    }
    rc = fts3tokQueryTokenizer((Fts3Hash*)pHash, zModule, &pMod, pzErr);
  }

  assert( (rc==SQLITE_OK)==(pMod!=0) );
  if( rc==SQLITE_OK ){
    const char * const *azArg = (const char * const *)&azDequote[1];
    const char * const *azArg = 0;
    if( nDequote>1 ) azArg = (const char * const *)&azDequote[1];
    rc = pMod->xCreate((nDequote>1 ? nDequote-1 : 0), azArg, &pTok);
  }

  if( rc==SQLITE_OK ){
    pTab = (Fts3tokTable *)sqlite3_malloc(sizeof(Fts3tokTable));
    if( pTab==0 ){
      rc = SQLITE_NOMEM;
342
343
344
345
346
347
348
349

350
351
352
353

354
355
356
357
358
359
360
343
344
345
346
347
348
349

350
351
352
353

354
355
356
357
358
359
360
361







-
+



-
+







  UNUSED_PARAMETER(idxStr);
  UNUSED_PARAMETER(nVal);

  fts3tokResetCursor(pCsr);
  if( idxNum==1 ){
    const char *zByte = (const char *)sqlite3_value_text(apVal[0]);
    int nByte = sqlite3_value_bytes(apVal[0]);
    pCsr->zInput = sqlite3_malloc(nByte+1);
    pCsr->zInput = sqlite3_malloc64(nByte+1);
    if( pCsr->zInput==0 ){
      rc = SQLITE_NOMEM;
    }else{
      memcpy(pCsr->zInput, zByte, nByte);
      if( nByte>0 ) memcpy(pCsr->zInput, zByte, nByte);
      pCsr->zInput[nByte] = 0;
      rc = pTab->pMod->xOpen(pTab->pTok, pCsr->zInput, nByte, &pCsr->pCsr);
      if( rc==SQLITE_OK ){
        pCsr->pCsr->pTokenizer = pTab->pTok;
      }
    }
  }
415
416
417
418
419
420
421
422

423
424
425
426
427
428
429
416
417
418
419
420
421
422

423
424
425
426
427
428
429
430







-
+







  return SQLITE_OK;
}

/*
** Register the fts3tok module with database connection db. Return SQLITE_OK
** if successful or an error code if sqlite3_create_module() fails.
*/
int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash){
int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash, void(*xDestroy)(void*)){
  static const sqlite3_module fts3tok_module = {
     0,                           /* iVersion      */
     fts3tokConnectMethod,        /* xCreate       */
     fts3tokConnectMethod,        /* xConnect      */
     fts3tokBestIndexMethod,      /* xBestIndex    */
     fts3tokDisconnectMethod,     /* xDisconnect   */
     fts3tokDisconnectMethod,     /* xDestroy      */
444
445
446
447
448
449
450
451



452
453
454
455
445
446
447
448
449
450
451

452
453
454
455
456
457
458







-
+
+
+




     0,                           /* xSavepoint    */
     0,                           /* xRelease      */
     0,                           /* xRollbackTo   */
     0                            /* xShadowName   */
  };
  int rc;                         /* Return code */

  rc = sqlite3_create_module(db, "fts3tokenize", &fts3tok_module, (void*)pHash);
  rc = sqlite3_create_module_v2(
      db, "fts3tokenize", &fts3tok_module, (void*)pHash, xDestroy
  );
  return rc;
}

#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */

Changes to ext/fts3/fts3_tokenizer.c.

75
76
77
78
79
80
81
82

83
84
85
86
87
88
89
75
76
77
78
79
80
81

82
83
84
85
86
87
88
89







-
+








  pHash = (Fts3Hash *)sqlite3_user_data(context);

  zName = sqlite3_value_text(argv[0]);
  nName = sqlite3_value_bytes(argv[0])+1;

  if( argc==2 ){
    if( fts3TokenizerEnabled(context) ){
    if( fts3TokenizerEnabled(context) || sqlite3_value_frombind(argv[1]) ){
      void *pOld;
      int n = sqlite3_value_bytes(argv[1]);
      if( zName==0 || n!=sizeof(pPtr) ){
        sqlite3_result_error(context, "argument type mismatch", -1);
        return;
      }
      pPtr = *(void **)sqlite3_value_blob(argv[1]);
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
118







+
-
+
+







    if( !pPtr ){
      char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName);
      sqlite3_result_error(context, zErr, -1);
      sqlite3_free(zErr);
      return;
    }
  }
  if( fts3TokenizerEnabled(context) || sqlite3_value_frombind(argv[0]) ){
  sqlite3_result_blob(context, (void *)&pPtr, sizeof(pPtr), SQLITE_TRANSIENT);
    sqlite3_result_blob(context, (void *)&pPtr, sizeof(pPtr), SQLITE_TRANSIENT);
  }
}

int sqlite3Fts3IsIdChar(char c){
  static const char isFtsIdChar[] = {
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0x */
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 1x */
      0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 2x */
190
191
192
193
194
195
196
197
198


199
200
201
202
203
204
205
192
193
194
195
196
197
198


199
200
201
202
203
204
205
206
207







-
-
+
+







    sqlite3Fts3ErrMsg(pzErr, "unknown tokenizer: %s", z);
    rc = SQLITE_ERROR;
  }else{
    char const **aArg = 0;
    int iArg = 0;
    z = &z[n+1];
    while( z<zEnd && (NULL!=(z = (char *)sqlite3Fts3NextToken(z, &n))) ){
      int nNew = sizeof(char *)*(iArg+1);
      char const **aNew = (const char **)sqlite3_realloc((void *)aArg, nNew);
      sqlite3_int64 nNew = sizeof(char *)*(iArg+1);
      char const **aNew = (const char **)sqlite3_realloc64((void *)aArg, nNew);
      if( !aNew ){
        sqlite3_free(zCopy);
        sqlite3_free((void *)aArg);
        return SQLITE_NOMEM;
      }
      aArg = aNew;
      aArg[iArg++] = z;
384
385
386
387
388
389
390
391



392
393
394
395
396
397
398
386
387
388
389
390
391
392

393
394
395
396
397
398
399
400
401
402







-
+
+
+







  rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
  if( rc!=SQLITE_OK ){
    return rc;
  }

  sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC);
  if( SQLITE_ROW==sqlite3_step(pStmt) ){
    if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){
    if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB
     && sqlite3_column_bytes(pStmt, 0)==sizeof(*pp)
    ){
      memcpy((void *)pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp));
    }
  }

  return sqlite3_finalize(pStmt);
}

473
474
475
476
477
478
479
480

481
482
483
484
485
486
487
477
478
479
480
481
482
483

484
485
486
487
488
489
490
491







-
+







int sqlite3Fts3InitHashTable(
  sqlite3 *db, 
  Fts3Hash *pHash, 
  const char *zName
){
  int rc = SQLITE_OK;
  void *p = (void *)pHash;
  const int any = SQLITE_ANY;
  const int any = SQLITE_UTF8|SQLITE_DIRECTONLY;

#ifdef SQLITE_TEST
  char *zTest = 0;
  char *zTest2 = 0;
  void *pdb = (void *)db;
  zTest = sqlite3_mprintf("%s_test", zName);
  zTest2 = sqlite3_mprintf("%s_internal_test", zName);

Changes to ext/fts3/fts3_tokenizer1.c.

181
182
183
184
185
186
187
188

189
190
191
192
193
194
195
181
182
183
184
185
186
187

188
189
190
191
192
193
194
195







-
+







    }

    if( c->iOffset>iStartOffset ){
      int i, n = c->iOffset-iStartOffset;
      if( n>c->nTokenAllocated ){
        char *pNew;
        c->nTokenAllocated = n+20;
        pNew = sqlite3_realloc(c->pToken, c->nTokenAllocated);
        pNew = sqlite3_realloc64(c->pToken, c->nTokenAllocated);
        if( !pNew ) return SQLITE_NOMEM;
        c->pToken = pNew;
      }
      for(i=0; i<n; i++){
        /* TODO(shess) This needs expansion to handle UTF-8
        ** case-insensitivity.
        */

Changes to ext/fts3/fts3_unicode.c.

151
152
153
154
155
156
157
158

159
160
161
162
163
164
165
151
152
153
154
155
156
157

158
159
160
161
162
163
164
165







-
+







    }
  }

  if( nEntry ){
    int *aNew;                    /* New aiException[] array */
    int nNew;                     /* Number of valid entries in array aNew[] */

    aNew = sqlite3_realloc(p->aiException, (p->nException+nEntry)*sizeof(int));
    aNew = sqlite3_realloc64(p->aiException,(p->nException+nEntry)*sizeof(int));
    if( aNew==0 ) return SQLITE_NOMEM;
    nNew = p->nException;

    z = (const unsigned char *)zIn;
    while( z<zTerm ){
      READ_UTF8(z, zTerm, iCode);
      if( sqlite3FtsUnicodeIsalnum((int)iCode)!=bAlnum 
281
282
283
284
285
286
287

288
289
290
291
292
293
294
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295







+







    return SQLITE_NOMEM;
  }
  memset(pCsr, 0, sizeof(unicode_cursor));

  pCsr->aInput = (const unsigned char *)aInput;
  if( aInput==0 ){
    pCsr->nInput = 0;
    pCsr->aInput = (const unsigned char*)"";
  }else if( nInput<0 ){
    pCsr->nInput = (int)strlen(aInput);
  }else{
    pCsr->nInput = nInput;
  }

  *pp = &pCsr->base;
340
341
342
343
344
345
346
347

348
349
350
351
352
353
354
341
342
343
344
345
346
347

348
349
350
351
352
353
354
355







-
+








  zOut = pCsr->zToken;
  do {
    int iOut;

    /* Grow the output buffer if required. */
    if( (zOut-pCsr->zToken)>=(pCsr->nAlloc-4) ){
      char *zNew = sqlite3_realloc(pCsr->zToken, pCsr->nAlloc+64);
      char *zNew = sqlite3_realloc64(pCsr->zToken, pCsr->nAlloc+64);
      if( !zNew ) return SQLITE_NOMEM;
      zOut = &zNew[zOut - pCsr->zToken];
      pCsr->zToken = zNew;
      pCsr->nAlloc += 64;
    }

    /* Write the folded case of the last character read to the output */

Changes to ext/fts3/fts3_unicode2.c.

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
** 2012 May 25
** 2012-05-25
**
** 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.
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
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







-
-
+
+




















-
+







    61726, 61784, 61800, 61816, 61836, 61880, 61896, 61914, 
    61948, 61998, 62062, 62122, 62154, 62184, 62200, 62218, 
    62252, 62302, 62364, 62410, 62442, 62478, 62536, 62554, 
    62584, 62604, 62640, 62648, 62656, 62664, 62730, 62766, 
    62830, 62890, 62924, 62974, 63032, 63050, 63082, 63118, 
    63182, 63242, 63274, 63310, 63368, 63390, 
  };
#define HIBIT ((char)0x80)
  char aChar[] = {
#define HIBIT ((unsigned char)0x80)
  unsigned char aChar[] = {
    '\0',      'a',       'c',       'e',       'i',       'n',       
    'o',       'u',       'y',       'y',       'a',       'c',       
    'd',       'e',       'e',       'g',       'h',       'i',       
    'j',       'k',       'l',       'n',       'o',       'r',       
    's',       't',       'u',       'u',       'w',       'y',       
    'z',       'o',       'u',       'a',       'i',       'o',       
    'u',       'u'|HIBIT, 'a'|HIBIT, 'g',       'k',       'o',       
    'o'|HIBIT, 'j',       'g',       'n',       'a'|HIBIT, 'a',       
    'e',       'i',       'o',       'r',       'u',       's',       
    't',       'h',       'a',       'e',       'o'|HIBIT, 'o',       
    'o'|HIBIT, 'y',       '\0',      '\0',      '\0',      '\0',      
    '\0',      '\0',      '\0',      '\0',      'a',       'b',       
    'c'|HIBIT, 'd',       'd',       'e'|HIBIT, 'e',       'e'|HIBIT, 
    'f',       'g',       'h',       'h',       'i',       'i'|HIBIT, 
    'k',       'l',       'l'|HIBIT, 'l',       'm',       'n',       
    'o'|HIBIT, 'p',       'r',       'r'|HIBIT, 'r',       's',       
    's'|HIBIT, 't',       'u',       'u'|HIBIT, 'v',       'w',       
    'w',       'x',       'y',       'z',       'h',       't',       
    'w',       'y',       'a',       'a'|HIBIT, 'a'|HIBIT, 'a'|HIBIT, 
    'e',       'e'|HIBIT, 'e'|HIBIT, 'i',       'o',       'o'|HIBIT, 
    'o'|HIBIT, 'o'|HIBIT, 'u',       'u'|HIBIT, 'u'|HIBIT, 'y',  
    'o'|HIBIT, 'o'|HIBIT, 'u',       'u'|HIBIT, 'u'|HIBIT, 'y',       
  };

  unsigned int key = (((unsigned int)c)<<3) | 0x00000007;
  int iRes = 0;
  int iHi = sizeof(aDia)/sizeof(aDia[0]) - 1;
  int iLo = 0;
  while( iHi>=iLo ){
227
228
229
230
231
232
233
234
235


236
237
238
239
240
241
242
227
228
229
230
231
232
233


234
235
236
237
238
239
240
241
242







-
-
+
+







** is a diacritical modifier character.
*/
int sqlite3FtsUnicodeIsdiacritic(int c){
  unsigned int mask0 = 0x08029FDF;
  unsigned int mask1 = 0x000361F8;
  if( c<768 || c>817 ) return 0;
  return (c < 768+32) ?
      (mask0 & (1 << (c-768))) :
      (mask1 & (1 << (c-768-32)));
      (mask0 & ((unsigned int)1 << (c-768))) :
      (mask1 & ((unsigned int)1 << (c-768-32)));
}


/*
** Interpret the argument as a unicode codepoint. If the codepoint
** is an upper case character that has a lower case equivalent,
** return the codepoint corresponding to the lower case version.

Changes to ext/fts3/fts3_write.c.

19
20
21
22
23
24
25
26

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

26
27
28
29
30
31
32
33







-
+








#include "fts3Int.h"
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)

#include <string.h>
#include <assert.h>
#include <stdlib.h>

#include <stdio.h>

#define FTS_MAX_APPENDABLE_HEIGHT 16

/*
** When full-text index nodes are loaded from disk, the buffer that they
** are loaded into has the following number of bytes of padding at the end 
** of it. i.e. if a full-text index node is 900 bytes in size, then a buffer
63
64
65
66
67
68
69
70

71
72
73
74
75
76
77
63
64
65
66
67
68
69

70
71
72
73
74
75
76
77







-
+







# define FTS3_NODE_CHUNK_THRESHOLD test_fts3_node_chunk_threshold
#else
# define FTS3_NODE_CHUNKSIZE (4*1024) 
# define FTS3_NODE_CHUNK_THRESHOLD (FTS3_NODE_CHUNKSIZE*4)
#endif

/*
** The two values that may be meaningfully bound to the :1 parameter in
** The values that may be meaningfully bound to the :1 parameter in
** statements SQL_REPLACE_STAT and SQL_SELECT_STAT.
*/
#define FTS_STAT_DOCTOTAL      0
#define FTS_STAT_INCRMERGEHINT 1
#define FTS_STAT_AUTOINCRMERGE 2

/*
331
332
333
334
335
336
337
338

339
340
341
342
343
344



345
346
347
348
349
350
351
331
332
333
334
335
336
337

338
339
340
341
342
343

344
345
346
347
348
349
350
351
352
353







-
+





-
+
+
+







/* This statement is used to determine which level to read the input from
** when performing an incremental merge. It returns the absolute level number
** of the oldest level in the db that contains at least ? segments. Or,
** if no level in the FTS index contains more than ? segments, the statement
** returns zero rows.  */
/* 28 */ "SELECT level, count(*) AS cnt FROM %Q.'%q_segdir' "
         "  GROUP BY level HAVING cnt>=?"
         "  ORDER BY (level %% 1024) ASC LIMIT 1",
         "  ORDER BY (level %% 1024) ASC, 2 DESC LIMIT 1",

/* Estimate the upper limit on the number of leaf nodes in a new segment
** created by merging the oldest :2 segments from absolute level :1. See 
** function sqlite3Fts3Incrmerge() for details.  */
/* 29 */ "SELECT 2 * total(1 + leaves_end_block - start_block) "
         "  FROM %Q.'%q_segdir' WHERE level = ? AND idx < ?",
         "  FROM (SELECT * FROM %Q.'%q_segdir' "
         "        WHERE level = ? ORDER BY idx ASC LIMIT ?"
         "  )",

/* SQL_DELETE_SEGDIR_ENTRY
**   Delete the %_segdir entry on absolute level :1 with index :2.  */
/* 30 */ "DELETE FROM %Q.'%q_segdir' WHERE level = ? AND idx = ?",

/* SQL_SHIFT_SEGDIR_ENTRY
**   Modify the idx value for the segment with idx=:3 on absolute level :2
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
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







+




+







-
+
-







  sqlite3_stmt *pStmt;

  assert( SizeofArray(azSql)==SizeofArray(p->aStmt) );
  assert( eStmt<SizeofArray(azSql) && eStmt>=0 );
  
  pStmt = p->aStmt[eStmt];
  if( !pStmt ){
    int f = SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_NO_VTAB;
    char *zSql;
    if( eStmt==SQL_CONTENT_INSERT ){
      zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName, p->zWriteExprlist);
    }else if( eStmt==SQL_SELECT_CONTENT_BY_ROWID ){
      f &= ~SQLITE_PREPARE_NO_VTAB;
      zSql = sqlite3_mprintf(azSql[eStmt], p->zReadExprlist);
    }else{
      zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName);
    }
    if( !zSql ){
      rc = SQLITE_NOMEM;
    }else{
      rc = sqlite3_prepare_v3(p->db, zSql, -1, SQLITE_PREPARE_PERSISTENT,
      rc = sqlite3_prepare_v3(p->db, zSql, -1, f, &pStmt, NULL);
                              &pStmt, NULL);
      sqlite3_free(zSql);
      assert( rc==SQLITE_OK || pStmt==0 );
      p->aStmt[eStmt] = pStmt;
    }
  }
  if( apVal ){
    int i;
562
563
564
565
566
567
568
569

570
571
572
573
574
575
576
565
566
567
568
569
570
571

572
573
574
575
576
577
578
579







-
+







static sqlite3_int64 getAbsoluteLevel(
  Fts3Table *p,                   /* FTS3 table handle */
  int iLangid,                    /* Language id */
  int iIndex,                     /* Index in p->aIndex[] */
  int iLevel                      /* Level of segments */
){
  sqlite3_int64 iBase;            /* First absolute level for iLangid/iIndex */
  assert( iLangid>=0 );
  assert_fts3_nc( iLangid>=0 );
  assert( p->nIndex>0 );
  assert( iIndex>=0 && iIndex<p->nIndex );

  iBase = ((sqlite3_int64)iLangid * p->nIndex + iIndex) * FTS3_SEGDIR_MAXLEVEL;
  return iBase + iLevel;
}

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







-
+








-
-
+
+





-
+







  PendingList **pp,               /* IN/OUT: Pointer to PendingList struct */
  sqlite3_int64 i                 /* Value to append to data */
){
  PendingList *p = *pp;

  /* Allocate or grow the PendingList as required. */
  if( !p ){
    p = sqlite3_malloc(sizeof(*p) + 100);
    p = sqlite3_malloc64(sizeof(*p) + 100);
    if( !p ){
      return SQLITE_NOMEM;
    }
    p->nSpace = 100;
    p->aData = (char *)&p[1];
    p->nData = 0;
  }
  else if( p->nData+FTS3_VARINT_MAX+1>p->nSpace ){
    int nNew = p->nSpace * 2;
    p = sqlite3_realloc(p, sizeof(*p) + nNew);
    i64 nNew = p->nSpace * 2;
    p = sqlite3_realloc64(p, sizeof(*p) + nNew);
    if( !p ){
      sqlite3_free(*pp);
      *pp = 0;
      return SQLITE_NOMEM;
    }
    p->nSpace = nNew;
    p->nSpace = (int)nNew;
    p->aData = (char *)&p[1];
  }

  /* Append the new serialized varint to the end of the list. */
  p->nData += sqlite3Fts3PutVarint(&p->aData[p->nData], i);
  p->aData[p->nData] = '\0';
  *pp = p;
691
692
693
694
695
696
697
698

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

701
702
703
704
705
706
707
708







-
+







){
  PendingList *p = *pp;
  int rc = SQLITE_OK;

  assert( !p || p->iLastDocid<=iDocid );

  if( !p || p->iLastDocid!=iDocid ){
    sqlite3_int64 iDelta = iDocid - (p ? p->iLastDocid : 0);
    u64 iDelta = (u64)iDocid - (u64)(p ? p->iLastDocid : 0);
    if( p ){
      assert( p->nData<p->nSpace );
      assert( p->aData[p->nData]==0 );
      p->nData++;
    }
    if( SQLITE_OK!=(rc = fts3PendingListAppendVarint(&p, iDelta)) ){
      goto pendinglistappend_out;
1148
1149
1150
1151
1152
1153
1154
1155

1156
1157
1158
1159
1160
1161
1162
1151
1152
1153
1154
1155
1156
1157

1158
1159
1160
1161
1162
1163
1164
1165







-
+








  if( rc==SQLITE_OK ){
    /* If iNext is FTS3_MERGE_COUNT, indicating that level iLevel is already
    ** full, merge all segments in level iLevel into a single iLevel+1
    ** segment and allocate (newly freed) index 0 at level iLevel. Otherwise,
    ** if iNext is less than FTS3_MERGE_COUNT, allocate index iNext.
    */
    if( iNext>=FTS3_MERGE_COUNT ){
    if( iNext>=MergeCount(p) ){
      fts3LogMerge(16, getAbsoluteLevel(p, iLangid, iIndex, iLevel));
      rc = fts3SegmentMerge(p, iLangid, iIndex, iLevel);
      *piIdx = 0;
    }else{
      *piIdx = iNext;
    }
  }
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
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







-
+
















+
+







    );
  }

  if( rc==SQLITE_OK ){
    int nByte = sqlite3_blob_bytes(p->pSegments);
    *pnBlob = nByte;
    if( paBlob ){
      char *aByte = sqlite3_malloc(nByte + FTS3_NODE_PADDING);
      char *aByte = sqlite3_malloc64((i64)nByte + FTS3_NODE_PADDING);
      if( !aByte ){
        rc = SQLITE_NOMEM;
      }else{
        if( pnLoad && nByte>(FTS3_NODE_CHUNK_THRESHOLD) ){
          nByte = FTS3_NODE_CHUNKSIZE;
          *pnLoad = nByte;
        }
        rc = sqlite3_blob_read(p->pSegments, aByte, nByte, 0);
        memset(&aByte[nByte], 0, FTS3_NODE_PADDING);
        if( rc!=SQLITE_OK ){
          sqlite3_free(aByte);
          aByte = 0;
        }
      }
      *paBlob = aByte;
    }
  }else if( rc==SQLITE_ERROR ){
    rc = FTS_CORRUPT_VTAB;
  }

  return rc;
}

/*
** Close the blob handle at p->pSegments, if it is open. See comments above
1326
1327
1328
1329
1330
1331
1332




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
1331
1332
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







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














+
-
+
+







      Fts3HashElem *pElem = *(pReader->ppNextElem);
      sqlite3_free(pReader->aNode);
      pReader->aNode = 0;
      if( pElem ){
        char *aCopy;
        PendingList *pList = (PendingList *)fts3HashData(pElem);
        int nCopy = pList->nData+1;

        int nTerm = fts3HashKeysize(pElem);
        if( (nTerm+1)>pReader->nTermAlloc ){
          sqlite3_free(pReader->zTerm);
        pReader->zTerm = (char *)fts3HashKey(pElem);
        pReader->nTerm = fts3HashKeysize(pElem);
        aCopy = (char*)sqlite3_malloc(nCopy);
          pReader->zTerm = (char*)sqlite3_malloc64(((i64)nTerm+1)*2);
          if( !pReader->zTerm ) return SQLITE_NOMEM;
          pReader->nTermAlloc = (nTerm+1)*2;
        }
        memcpy(pReader->zTerm, fts3HashKey(pElem), nTerm);
        pReader->zTerm[nTerm] = '\0';
        pReader->nTerm = nTerm;

        aCopy = (char*)sqlite3_malloc64(nCopy);
        if( !aCopy ) return SQLITE_NOMEM;
        memcpy(aCopy, pList->aData, nCopy);
        pReader->nNode = pReader->nDoclist = nCopy;
        pReader->aNode = pReader->aDoclist = aCopy;
        pReader->ppNextElem++;
        assert( pReader->aNode );
      }
      return SQLITE_OK;
    }

    fts3SegReaderSetEof(pReader);

    /* If iCurrentBlock>=iLeafEndBlock, this is an EOF condition. All leaf 
    ** blocks have already been traversed.  */
#ifdef CORRUPT_DB
    assert( pReader->iCurrentBlock<=pReader->iLeafEndBlock );
    assert( pReader->iCurrentBlock<=pReader->iLeafEndBlock || CORRUPT_DB );
#endif
    if( pReader->iCurrentBlock>=pReader->iLeafEndBlock ){
      return SQLITE_OK;
    }

    rc = sqlite3Fts3ReadBlock(
        p, ++pReader->iCurrentBlock, &pReader->aNode, &pReader->nNode, 
        (bIncr ? &pReader->nPopulate : 0)
1372
1373
1374
1375
1376
1377
1378
1379

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

1396
1397
1398
1399
1400
1401
1402
1403







-
+







  
  /* Because of the FTS3_NODE_PADDING bytes of padding, the following is 
  ** safe (no risk of overread) even if the node data is corrupted. */
  pNext += fts3GetVarint32(pNext, &nPrefix);
  pNext += fts3GetVarint32(pNext, &nSuffix);
  if( nSuffix<=0 
   || (&pReader->aNode[pReader->nNode] - pNext)<nSuffix
   || nPrefix>pReader->nTermAlloc
   || nPrefix>pReader->nTerm
  ){
    return FTS_CORRUPT_VTAB;
  }

  /* Both nPrefix and nSuffix were read by fts3GetVarint32() and so are
  ** between 0 and 0x7FFFFFFF. But the sum of the two may cause integer
  ** overflow - hence the (i64) casts.  */
1404
1405
1406
1407
1408
1409
1410
1411

1412

1413
1414
1415
1416
1417
1418
1419
1421
1422
1423
1424
1425
1426
1427

1428
1429
1430
1431
1432
1433
1434
1435
1436
1437







-
+

+







  pReader->aDoclist = pNext;
  pReader->pOffsetList = 0;

  /* Check that the doclist does not appear to extend past the end of the
  ** b-tree node. And that the final byte of the doclist is 0x00. If either 
  ** of these statements is untrue, then the data structure is corrupt.
  */
  if( (&pReader->aNode[pReader->nNode] - pReader->aDoclist)<pReader->nDoclist
  if( pReader->nDoclist > pReader->nNode-(pReader->aDoclist-pReader->aNode)
   || (pReader->nPopulate==0 && pReader->aDoclist[pReader->nDoclist-1])
   || pReader->nDoclist==0
  ){
    return FTS_CORRUPT_VTAB;
  }
  return SQLITE_OK;
}

/*
1522
1523
1524
1525
1526
1527
1528
1529
1530


1531
1532

1533
1534

1535
1536
1537
1538
1539
1540

1541
1542
1543
1544
1545
1546
1547
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







-
-
+
+

-
+

-
+





-
+







    ** returning.
    */
    if( p>=pEnd ){
      pReader->pOffsetList = 0;
    }else{
      rc = fts3SegReaderRequire(pReader, p, FTS3_VARINT_MAX);
      if( rc==SQLITE_OK ){
        sqlite3_int64 iDelta;
        pReader->pOffsetList = p + sqlite3Fts3GetVarint(p, &iDelta);
        u64 iDelta;
        pReader->pOffsetList = p + sqlite3Fts3GetVarintU(p, &iDelta);
        if( pTab->bDescIdx ){
          pReader->iDocid -= iDelta;
          pReader->iDocid = (i64)((u64)pReader->iDocid - iDelta);
        }else{
          pReader->iDocid += iDelta;
          pReader->iDocid = (i64)((u64)pReader->iDocid + iDelta);
        }
      }
    }
  }

  return SQLITE_OK;
  return rc;
}


int sqlite3Fts3MsrOvfl(
  Fts3Cursor *pCsr, 
  Fts3MultiSegReader *pMsr,
  int *pnOvfl
1577
1578
1579
1580
1581
1582
1583
1584
1585

1586
1587
1588
1589
1590
1591
1592
1593
1595
1596
1597
1598
1599
1600
1601


1602

1603
1604
1605
1606
1607
1608
1609







-
-
+
-








/*
** Free all allocations associated with the iterator passed as the 
** second argument.
*/
void sqlite3Fts3SegReaderFree(Fts3SegReader *pReader){
  if( pReader ){
    if( !fts3SegReaderIsPending(pReader) ){
      sqlite3_free(pReader->zTerm);
    sqlite3_free(pReader->zTerm);
    }
    if( !fts3SegReaderIsRootOnly(pReader) ){
      sqlite3_free(pReader->aNode);
    }
    sqlite3_blob_close(pReader->pBlob);
  }
  sqlite3_free(pReader);
}
1604
1605
1606
1607
1608
1609
1610




1611

1612

1613
1614
1615
1616

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

1633
1634
1635
1636
1637
1638
1639
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630

1631
1632
1633
1634
1635
1636

1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652

1653
1654
1655
1656
1657
1658
1659
1660







+
+
+
+
-
+

+



-
+















-
+







  const char *zRoot,              /* Buffer containing root node */
  int nRoot,                      /* Size of buffer containing root node */
  Fts3SegReader **ppReader        /* OUT: Allocated Fts3SegReader */
){
  Fts3SegReader *pReader;         /* Newly allocated SegReader object */
  int nExtra = 0;                 /* Bytes to allocate segment root node */

  assert( zRoot!=0 || nRoot==0 );
#ifdef CORRUPT_DB
  assert( zRoot!=0 || CORRUPT_DB );
#endif
  assert( iStartLeaf<=iEndLeaf );

  if( iStartLeaf==0 ){
    if( iEndLeaf!=0 ) return FTS_CORRUPT_VTAB;
    nExtra = nRoot + FTS3_NODE_PADDING;
  }

  pReader = (Fts3SegReader *)sqlite3_malloc(sizeof(Fts3SegReader) + nExtra);
  pReader = (Fts3SegReader *)sqlite3_malloc64(sizeof(Fts3SegReader) + nExtra);
  if( !pReader ){
    return SQLITE_NOMEM;
  }
  memset(pReader, 0, sizeof(Fts3SegReader));
  pReader->iIdx = iAge;
  pReader->bLookup = bLookup!=0;
  pReader->iStartBlock = iStartLeaf;
  pReader->iLeafEndBlock = iEndLeaf;
  pReader->iEndBlock = iEndBlock;

  if( nExtra ){
    /* The entire segment is stored in the root node. */
    pReader->aNode = (char *)&pReader[1];
    pReader->rootOnly = 1;
    pReader->nNode = nRoot;
    memcpy(pReader->aNode, zRoot, nRoot);
    if( nRoot ) memcpy(pReader->aNode, zRoot, nRoot);
    memset(&pReader->aNode[nRoot], 0, FTS3_NODE_PADDING);
  }else{
    pReader->iCurrentBlock = iStartLeaf-1;
  }
  *ppReader = pReader;
  return SQLITE_OK;
}
1701
1702
1703
1704
1705
1706
1707
1708

1709
1710
1711
1712
1713
1714
1715
1722
1723
1724
1725
1726
1727
1728

1729
1730
1731
1732
1733
1734
1735
1736







-
+







    for(pE=fts3HashFirst(pHash); pE; pE=fts3HashNext(pE)){
      char *zKey = (char *)fts3HashKey(pE);
      int nKey = fts3HashKeysize(pE);
      if( nTerm==0 || (nKey>=nTerm && 0==memcmp(zKey, zTerm, nTerm)) ){
        if( nElem==nAlloc ){
          Fts3HashElem **aElem2;
          nAlloc += 16;
          aElem2 = (Fts3HashElem **)sqlite3_realloc(
          aElem2 = (Fts3HashElem **)sqlite3_realloc64(
              aElem, nAlloc*sizeof(Fts3HashElem *)
          );
          if( !aElem2 ){
            rc = SQLITE_NOMEM;
            nElem = 0;
            break;
          }
1740
1741
1742
1743
1744
1745
1746

1747
1748


1749
1750
1751
1752
1753
1754
1755
1761
1762
1763
1764
1765
1766
1767
1768


1769
1770
1771
1772
1773
1774
1775
1776
1777







+
-
-
+
+







    if( pE ){
      aElem = &pE;
      nElem = 1;
    }
  }

  if( nElem>0 ){
    sqlite3_int64 nByte;
    int nByte = sizeof(Fts3SegReader) + (nElem+1)*sizeof(Fts3HashElem *);
    pReader = (Fts3SegReader *)sqlite3_malloc(nByte);
    nByte = sizeof(Fts3SegReader) + (nElem+1)*sizeof(Fts3HashElem *);
    pReader = (Fts3SegReader *)sqlite3_malloc64(nByte);
    if( !pReader ){
      rc = SQLITE_NOMEM;
    }else{
      memset(pReader, 0, nByte);
      pReader->iIdx = 0x7FFFFFFF;
      pReader->ppNextElem = (Fts3HashElem **)&pReader[1];
      memcpy(pReader->ppNextElem, aElem, nElem*sizeof(Fts3HashElem *));
1789
1790
1791
1792
1793
1794
1795
1796

1797
1798
1799
1800
1801
1802
1803
1811
1812
1813
1814
1815
1816
1817

1818
1819
1820
1821
1822
1823
1824
1825







-
+







    }
  }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:
1985
1986
1987
1988
1989
1990
1991
1992
1993


1994
1995
1996
1997
1998
1999
2000
2007
2008
2009
2010
2011
2012
2013


2014
2015
2016
2017
2018
2019
2020
2021
2022







-
-
+
+







static int fts3PrefixCompress(
  const char *zPrev,              /* Buffer containing previous term */
  int nPrev,                      /* Size of buffer zPrev in bytes */
  const char *zNext,              /* Buffer containing next term */
  int nNext                       /* Size of buffer zNext in bytes */
){
  int n;
  UNUSED_PARAMETER(nNext);
  for(n=0; n<nPrev && zPrev[n]==zNext[n]; n++);
  for(n=0; n<nPrev && n<nNext && zPrev[n]==zNext[n]; n++);
  assert_fts3_nc( n<nNext );
  return n;
}

/*
** Add term zTerm to the SegmentNode. It is guaranteed that zTerm is larger
** (according to memcmp) than the previous term.
*/
2016
2017
2018
2019
2020
2021
2022





2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036

2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054

2055
2056
2057
2058
2059
2060
2061
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







+
+
+
+
+













-
+

















-
+







    int nData = pTree->nData;     /* Current size of node in bytes */
    int nReq = nData;             /* Required space after adding zTerm */
    int nPrefix;                  /* Number of bytes of prefix compression */
    int nSuffix;                  /* Suffix length */

    nPrefix = fts3PrefixCompress(pTree->zTerm, pTree->nTerm, zTerm, nTerm);
    nSuffix = nTerm-nPrefix;

    /* If nSuffix is zero or less, then zTerm/nTerm must be a prefix of 
    ** pWriter->zTerm/pWriter->nTerm. i.e. must be equal to or less than when
    ** compared with BINARY collation. This indicates corruption.  */
    if( nSuffix<=0 ) return FTS_CORRUPT_VTAB;

    nReq += sqlite3Fts3VarintLen(nPrefix)+sqlite3Fts3VarintLen(nSuffix)+nSuffix;
    if( nReq<=p->nNodeSize || !pTree->zTerm ){

      if( nReq>p->nNodeSize ){
        /* An unusual case: this is the first term to be added to the node
        ** and the static node buffer (p->nNodeSize bytes) is not large
        ** enough. Use a separately malloced buffer instead This wastes
        ** p->nNodeSize bytes, but since this scenario only comes about when
        ** the database contain two terms that share a prefix of almost 2KB, 
        ** this is not expected to be a serious problem. 
        */
        assert( pTree->aData==(char *)&pTree[1] );
        pTree->aData = (char *)sqlite3_malloc(nReq);
        pTree->aData = (char *)sqlite3_malloc64(nReq);
        if( !pTree->aData ){
          return SQLITE_NOMEM;
        }
      }

      if( pTree->zTerm ){
        /* There is no prefix-length field for first term in a node */
        nData += sqlite3Fts3PutVarint(&pTree->aData[nData], nPrefix);
      }

      nData += sqlite3Fts3PutVarint(&pTree->aData[nData], nSuffix);
      memcpy(&pTree->aData[nData], &zTerm[nPrefix], nSuffix);
      pTree->nData = nData + nSuffix;
      pTree->nEntry++;

      if( isCopyTerm ){
        if( pTree->nMalloc<nTerm ){
          char *zNew = sqlite3_realloc(pTree->zMalloc, nTerm*2);
          char *zNew = sqlite3_realloc64(pTree->zMalloc, (i64)nTerm*2);
          if( !zNew ){
            return SQLITE_NOMEM;
          }
          pTree->nMalloc = nTerm*2;
          pTree->zMalloc = zNew;
        }
        pTree->zTerm = pTree->zMalloc;
2073
2074
2075
2076
2077
2078
2079
2080

2081
2082
2083
2084
2085
2086
2087
2100
2101
2102
2103
2104
2105
2106

2107
2108
2109
2110
2111
2112
2113
2114







-
+







  ** current node. Create a new node (a right-sibling of the current node).
  ** If this is the first node in the tree, the term is added to it.
  **
  ** Otherwise, the term is not added to the new node, it is left empty for
  ** now. Instead, the term is inserted into the parent of pTree. If pTree 
  ** has no parent, one is created here.
  */
  pNew = (SegmentNode *)sqlite3_malloc(sizeof(SegmentNode) + p->nNodeSize);
  pNew = (SegmentNode *)sqlite3_malloc64(sizeof(SegmentNode) + p->nNodeSize);
  if( !pNew ){
    return SQLITE_NOMEM;
  }
  memset(pNew, 0, sizeof(SegmentNode));
  pNew->nData = 1 + FTS3_VARINT_MAX;
  pNew->aData = (char *)&pNew[1];

2211
2212
2213
2214
2215
2216
2217
2218

2219
2220
2221
2222
2223
2224
2225
2226
2227

2228
2229
2230
2231
2232
2233

2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250





2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262

2263
2264
2265
2266
2267
2268
2269
2238
2239
2240
2241
2242
2243
2244

2245
2246
2247
2248
2249
2250
2251
2252
2253

2254
2255
2256
2257
2258
2259

2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302







-
+








-
+





-
+

















+
+
+
+
+












+







  const char *zTerm,              /* Pointer to buffer containing term */
  int nTerm,                      /* Size of term in bytes */
  const char *aDoclist,           /* Pointer to buffer containing doclist */
  int nDoclist                    /* Size of doclist in bytes */
){
  int nPrefix;                    /* Size of term prefix in bytes */
  int nSuffix;                    /* Size of term suffix in bytes */
  int nReq;                       /* Number of bytes required on leaf page */
  i64 nReq;                       /* Number of bytes required on leaf page */
  int nData;
  SegmentWriter *pWriter = *ppWriter;

  if( !pWriter ){
    int rc;
    sqlite3_stmt *pStmt;

    /* Allocate the SegmentWriter structure */
    pWriter = (SegmentWriter *)sqlite3_malloc(sizeof(SegmentWriter));
    pWriter = (SegmentWriter *)sqlite3_malloc64(sizeof(SegmentWriter));
    if( !pWriter ) return SQLITE_NOMEM;
    memset(pWriter, 0, sizeof(SegmentWriter));
    *ppWriter = pWriter;

    /* Allocate a buffer in which to accumulate data */
    pWriter->aData = (char *)sqlite3_malloc(p->nNodeSize);
    pWriter->aData = (char *)sqlite3_malloc64(p->nNodeSize);
    if( !pWriter->aData ) return SQLITE_NOMEM;
    pWriter->nSize = p->nNodeSize;

    /* Find the next free blockid in the %_segments table */
    rc = fts3SqlStmt(p, SQL_NEXT_SEGMENTS_ID, &pStmt, 0);
    if( rc!=SQLITE_OK ) return rc;
    if( SQLITE_ROW==sqlite3_step(pStmt) ){
      pWriter->iFree = sqlite3_column_int64(pStmt, 0);
      pWriter->iFirst = pWriter->iFree;
    }
    rc = sqlite3_reset(pStmt);
    if( rc!=SQLITE_OK ) return rc;
  }
  nData = pWriter->nData;

  nPrefix = fts3PrefixCompress(pWriter->zTerm, pWriter->nTerm, zTerm, nTerm);
  nSuffix = nTerm-nPrefix;

  /* If nSuffix is zero or less, then zTerm/nTerm must be a prefix of 
  ** pWriter->zTerm/pWriter->nTerm. i.e. must be equal to or less than when
  ** compared with BINARY collation. This indicates corruption.  */
  if( nSuffix<=0 ) return FTS_CORRUPT_VTAB;

  /* Figure out how many bytes are required by this new entry */
  nReq = sqlite3Fts3VarintLen(nPrefix) +    /* varint containing prefix size */
    sqlite3Fts3VarintLen(nSuffix) +         /* varint containing suffix size */
    nSuffix +                               /* Term suffix */
    sqlite3Fts3VarintLen(nDoclist) +        /* Size of doclist */
    nDoclist;                               /* Doclist data */

  if( nData>0 && nData+nReq>p->nNodeSize ){
    int rc;

    /* The current leaf node is full. Write it out to the database. */
    if( pWriter->iFree==LARGEST_INT64 ) return FTS_CORRUPT_VTAB;
    rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, nData);
    if( rc!=SQLITE_OK ) return rc;
    p->nLeafAdd++;

    /* Add the current term to the interior node tree. The term added to
    ** the interior tree must:
    **
2295
2296
2297
2298
2299
2300
2301
2302

2303
2304
2305
2306
2307
2308
2309
2310
2311

2312
2313
2314

2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325

2326
2327
2328
2329
2330
2331
2332
2333

2334
2335
2336
2337
2338
2339
2340
2328
2329
2330
2331
2332
2333
2334

2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359

2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376







-
+









+



+










-
+








+







  /* Increase the total number of bytes written to account for the new entry. */
  pWriter->nLeafData += nReq;

  /* If the buffer currently allocated is too small for this entry, realloc
  ** the buffer to make it large enough.
  */
  if( nReq>pWriter->nSize ){
    char *aNew = sqlite3_realloc(pWriter->aData, nReq);
    char *aNew = sqlite3_realloc64(pWriter->aData, nReq);
    if( !aNew ) return SQLITE_NOMEM;
    pWriter->aData = aNew;
    pWriter->nSize = nReq;
  }
  assert( nData+nReq<=pWriter->nSize );

  /* Append the prefix-compressed term and doclist to the buffer. */
  nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nPrefix);
  nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nSuffix);
  assert( nSuffix>0 );
  memcpy(&pWriter->aData[nData], &zTerm[nPrefix], nSuffix);
  nData += nSuffix;
  nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nDoclist);
  assert( nDoclist>0 );
  memcpy(&pWriter->aData[nData], aDoclist, nDoclist);
  pWriter->nData = nData + nDoclist;

  /* Save the current term so that it can be used to prefix-compress the next.
  ** If the isCopyTerm parameter is true, then the buffer pointed to by
  ** zTerm is transient, so take a copy of the term data. Otherwise, just
  ** store a copy of the pointer.
  */
  if( isCopyTerm ){
    if( nTerm>pWriter->nMalloc ){
      char *zNew = sqlite3_realloc(pWriter->zMalloc, nTerm*2);
      char *zNew = sqlite3_realloc64(pWriter->zMalloc, (i64)nTerm*2);
      if( !zNew ){
        return SQLITE_NOMEM;
      }
      pWriter->nMalloc = nTerm*2;
      pWriter->zMalloc = zNew;
      pWriter->zTerm = zNew;
    }
    assert( pWriter->zTerm==pWriter->zMalloc );
    assert( nTerm>0 );
    memcpy(pWriter->zTerm, zTerm, nTerm);
  }else{
    pWriter->zTerm = (char *)zTerm;
  }
  pWriter->nTerm = nTerm;

  return SQLITE_OK;
2473
2474
2475
2476
2477
2478
2479
2480

2481
2482
2483
2484
2485
2486
2487
2509
2510
2511
2512
2513
2514
2515

2516
2517
2518
2519
2520
2521
2522
2523







-
+







  ** (1024 is actually the value of macro FTS3_SEGDIR_PREFIXLEVEL_STR).
  */
  sqlite3_stmt *pStmt;
  int rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_MAX_LEVEL, &pStmt, 0);
  if( rc!=SQLITE_OK ) return rc;
  sqlite3_bind_int64(pStmt, 1, iAbsLevel+1);
  sqlite3_bind_int64(pStmt, 2, 
      ((iAbsLevel/FTS3_SEGDIR_MAXLEVEL)+1) * FTS3_SEGDIR_MAXLEVEL
      (((u64)iAbsLevel/FTS3_SEGDIR_MAXLEVEL)+1) * FTS3_SEGDIR_MAXLEVEL
  );

  *pbMax = 0;
  if( SQLITE_ROW==sqlite3_step(pStmt) ){
    *pbMax = sqlite3_column_type(pStmt, 0)==SQLITE_NULL;
  }
  return sqlite3_reset(pStmt);
2601
2602
2603
2604
2605
2606
2607
2608

2609
2610
2611
2612
2613
2614
2615

2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632

2633
2634
2635
2636
2637

2638
2639
2640
2641

2642
2643
2644
2645
2646
2647
2648
2637
2638
2639
2640
2641
2642
2643

2644
2645
2646
2647
2648
2649
2650

2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667

2668
2669
2670
2671
2672

2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685







-
+






-
+
















-
+




-
+




+







    if( iCol==iCurrent ){
      nList = (int)(p - pList);
      break;
    }

    nList -= (int)(p - pList);
    pList = p;
    if( nList==0 ){
    if( nList<=0 ){
      break;
    }
    p = &pList[1];
    p += fts3GetVarint32(p, &iCurrent);
  }

  if( bZero && &pList[nList]!=pEnd ){
  if( bZero && (pEnd - &pList[nList])>0){
    memset(&pList[nList], 0, pEnd - &pList[nList]);
  }
  *ppList = pList;
  *pnList = nList;
}

/*
** Cache data in the Fts3MultiSegReader.aBuffer[] buffer (overwriting any
** existing data). Grow the buffer if required.
**
** If successful, return SQLITE_OK. Otherwise, if an OOM error is encountered
** trying to resize the buffer, return SQLITE_NOMEM.
*/
static int fts3MsrBufferData(
  Fts3MultiSegReader *pMsr,       /* Multi-segment-reader handle */
  char *pList,
  int nList
  i64 nList
){
  if( nList>pMsr->nBuffer ){
    char *pNew;
    pMsr->nBuffer = nList*2;
    pNew = (char *)sqlite3_realloc(pMsr->aBuffer, pMsr->nBuffer);
    pNew = (char *)sqlite3_realloc64(pMsr->aBuffer, pMsr->nBuffer);
    if( !pNew ) return SQLITE_NOMEM;
    pMsr->aBuffer = pNew;
  }

  assert( nList>0 );
  memcpy(pMsr->aBuffer, pList, nList);
  return SQLITE_OK;
}

int sqlite3Fts3MsrIncrNext(
  Fts3Table *p,                   /* Virtual table handle */
  Fts3MultiSegReader *pMsr,       /* Multi-segment-reader handle */
2685
2686
2687
2688
2689
2690
2691
2692

2693
2694
2695
2696
2697
2698
2699
2722
2723
2724
2725
2726
2727
2728

2729
2730
2731
2732
2733
2734
2735
2736







-
+







        rc = fts3SegReaderNextDocid(p, apSegment[j], 0, 0);
        j++;
      }
      if( rc!=SQLITE_OK ) return rc;
      fts3SegReaderSort(pMsr->apSegment, nMerge, j, xCmp);

      if( nList>0 && fts3SegReaderIsPending(apSegment[0]) ){
        rc = fts3MsrBufferData(pMsr, pList, nList+1);
        rc = fts3MsrBufferData(pMsr, pList, (i64)nList+1);
        if( rc!=SQLITE_OK ) return rc;
        assert( (pMsr->aBuffer[nList] & 0xFE)==0x00 );
        pList = pMsr->aBuffer;
      }

      if( pMsr->iColFilter>=0 ){
        fts3ColumnFilter(pMsr->iColFilter, 1, &pList, &nList);
2822
2823
2824
2825
2826
2827
2828













2829
2830
2831
2832
2833
2834
2835
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885







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







    pCsr->apSegment[i]->nOffsetList = 0;
    pCsr->apSegment[i]->iDocid = 0;
  }

  return SQLITE_OK;
}

static int fts3GrowSegReaderBuffer(Fts3MultiSegReader *pCsr, i64 nReq){
  if( nReq>pCsr->nBuffer ){
    char *aNew;
    pCsr->nBuffer = nReq*2;
    aNew = sqlite3_realloc64(pCsr->aBuffer, pCsr->nBuffer);
    if( !aNew ){
      return SQLITE_NOMEM;
    }
    pCsr->aBuffer = aNew;
  }
  return SQLITE_OK;
}


int sqlite3Fts3SegReaderStep(
  Fts3Table *p,                   /* Virtual table handle */
  Fts3MultiSegReader *pCsr        /* Cursor object */
){
  int rc = SQLITE_OK;

2904
2905
2906
2907
2908
2909
2910
2911


2912
2913
2914
2915
2916
2917
2918
2954
2955
2956
2957
2958
2959
2960

2961
2962
2963
2964
2965
2966
2967
2968
2969







-
+
+







    if( nMerge==1 
     && !isIgnoreEmpty 
     && !isFirst 
     && (p->bDescIdx==0 || fts3SegReaderIsPending(apSegment[0])==0)
    ){
      pCsr->nDoclist = apSegment[0]->nDoclist;
      if( fts3SegReaderIsPending(apSegment[0]) ){
        rc = fts3MsrBufferData(pCsr, apSegment[0]->aDoclist, pCsr->nDoclist);
        rc = fts3MsrBufferData(pCsr, apSegment[0]->aDoclist,
                               (i64)pCsr->nDoclist);
        pCsr->aDoclist = pCsr->aBuffer;
      }else{
        pCsr->aDoclist = apSegment[0]->aDoclist;
      }
      if( rc==SQLITE_OK ) rc = SQLITE_ROW;
    }else{
      int nDoclist = 0;           /* Size of doclist */
2948
2949
2950
2951
2952
2953
2954

2955

2956

2957

2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970


2971


2972
2973
2974
2975
2976
2977
2978
2999
3000
3001
3002
3003
3004
3005
3006

3007
3008
3009

3010
3011


3012
3013








3014
3015

3016
3017
3018
3019
3020
3021
3022
3023
3024







+
-
+

+
-
+

-
-


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








        if( !isIgnoreEmpty || nList>0 ){

          /* Calculate the 'docid' delta value to write into the merged 
          ** doclist. */
          sqlite3_int64 iDelta;
          if( p->bDescIdx && nDoclist>0 ){
            if( iPrev<=iDocid ) return FTS_CORRUPT_VTAB;
            iDelta = iPrev - iDocid;
            iDelta = (i64)((u64)iPrev - (u64)iDocid);
          }else{
            if( nDoclist>0 && iPrev>=iDocid ) return FTS_CORRUPT_VTAB;
            iDelta = iDocid - iPrev;
            iDelta = (i64)((u64)iDocid - (u64)iPrev);
          }
          assert( iDelta>0 || (nDoclist==0 && iDelta==iDocid) );
          assert( nDoclist>0 || iDelta==iDocid );

          nByte = sqlite3Fts3VarintLen(iDelta) + (isRequirePos?nList+1:0);
          if( nDoclist+nByte>pCsr->nBuffer ){
            char *aNew;
            pCsr->nBuffer = (nDoclist+nByte)*2;
            aNew = sqlite3_realloc(pCsr->aBuffer, pCsr->nBuffer);
            if( !aNew ){
              return SQLITE_NOMEM;
            }
            pCsr->aBuffer = aNew;

          rc = fts3GrowSegReaderBuffer(pCsr, 
          }
                                   (i64)nByte+nDoclist+FTS3_NODE_PADDING);
          if( rc ) return rc;

          if( isFirst ){
            char *a = &pCsr->aBuffer[nDoclist];
            int nWrite;
           
            nWrite = sqlite3Fts3FirstFilter(iDelta, pList, nList, a);
            if( nWrite ){
2989
2990
2991
2992
2993
2994
2995



2996
2997
2998
2999
3000
3001
3002
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051







+
+
+







            }
          }
        }

        fts3SegReaderSort(apSegment, nMerge, j, xCmp);
      }
      if( nDoclist>0 ){
        rc = fts3GrowSegReaderBuffer(pCsr, (i64)nDoclist+FTS3_NODE_PADDING);
        if( rc ) return rc;
        memset(&pCsr->aBuffer[nDoclist], 0, FTS3_NODE_PADDING);
        pCsr->aDoclist = pCsr->aBuffer;
        pCsr->nDoclist = nDoclist;
        rc = SQLITE_ROW;
      }
    }
    pCsr->nAdvance = nMerge;
  }while( rc==SQLITE_OK );
3038
3039
3040
3041
3042
3043
3044
3045

3046
3047
3048
3049

3050
3051
3052
3053
3054
3055
3056
3057
3058
3059

3060
3061
3062
3063
3064
3065
3066
3087
3088
3089
3090
3091
3092
3093

3094
3095
3096
3097

3098
3099
3100
3101
3102
3103
3104
3105
3106
3107

3108
3109
3110
3111
3112
3113
3114
3115







-
+



-
+









-
+







  i64 *piEndBlock,
  i64 *pnByte
){
  const unsigned char *zText = sqlite3_column_text(pStmt, iCol);
  if( zText ){
    int i;
    int iMul = 1;
    i64 iVal = 0;
    u64 iVal = 0;
    for(i=0; zText[i]>='0' && zText[i]<='9'; i++){
      iVal = iVal*10 + (zText[i] - '0');
    }
    *piEndBlock = iVal;
    *piEndBlock = (i64)iVal;
    while( zText[i]==' ' ) i++;
    iVal = 0;
    if( zText[i]=='-' ){
      i++;
      iMul = -1;
    }
    for(/* no-op */; zText[i]>='0' && zText[i]<='9'; i++){
      iVal = iVal*10 + (zText[i] - '0');
    }
    *pnByte = (iVal * (i64)iMul);
    *pnByte = ((i64)iVal * (i64)iMul);
  }
}


/*
** A segment of size nByte bytes has just been written to absolute level
** iAbsLevel. Promote any segments that should be promoted as a result.
3218
3219
3220
3221
3222
3223
3224
3225
3226




3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240

3241
3242
3243
3244
3245
3246
3247
3267
3268
3269
3270
3271
3272
3273


3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290

3291
3292
3293
3294
3295
3296
3297
3298







-
-
+
+
+
+













-
+







    iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, iLevel+1);
    rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, iLevel+1, &iIdx);
    bIgnoreEmpty = (iLevel!=FTS3_SEGCURSOR_PENDING) && (iNewLevel>iMaxLevel);
  }
  if( rc!=SQLITE_OK ) goto finished;

  assert( csr.nSegment>0 );
  assert( iNewLevel>=getAbsoluteLevel(p, iLangid, iIndex, 0) );
  assert( iNewLevel<getAbsoluteLevel(p, iLangid, iIndex,FTS3_SEGDIR_MAXLEVEL) );
  assert_fts3_nc( iNewLevel>=getAbsoluteLevel(p, iLangid, iIndex, 0) );
  assert_fts3_nc( 
    iNewLevel<getAbsoluteLevel(p, iLangid, iIndex,FTS3_SEGDIR_MAXLEVEL) 
  );

  memset(&filter, 0, sizeof(Fts3SegFilter));
  filter.flags = FTS3_SEGMENT_REQUIRE_POS;
  filter.flags |= (bIgnoreEmpty ? FTS3_SEGMENT_IGNORE_EMPTY : 0);

  rc = sqlite3Fts3SegReaderStart(p, &csr, &filter);
  while( SQLITE_OK==rc ){
    rc = sqlite3Fts3SegReaderStep(p, &csr);
    if( rc!=SQLITE_ROW ) break;
    rc = fts3SegWriterAdd(p, &pWriter, 1, 
        csr.zTerm, csr.nTerm, csr.aDoclist, csr.nDoclist);
  }
  if( rc!=SQLITE_OK ) goto finished;
  assert( pWriter || bIgnoreEmpty );
  assert_fts3_nc( pWriter || bIgnoreEmpty );

  if( iLevel!=FTS3_SEGCURSOR_PENDING ){
    rc = fts3DeleteSegdir(
        p, iLangid, iIndex, iLevel, csr.apSegment, csr.nSegment
    );
    if( rc!=SQLITE_OK ) goto finished;
  }
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329






3330
3331
3332




3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351

3352
3353
3354
3355
3356
3357
3358
3369
3370
3371
3372
3373
3374
3375





3376
3377
3378
3379
3380
3381



3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403

3404
3405
3406
3407
3408
3409
3410
3411







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


















-
+







*/
static void fts3DecodeIntArray(
  int N,             /* The number of integers to decode */
  u32 *a,            /* Write the integer values */
  const char *zBuf,  /* The BLOB containing the varints */
  int nBuf           /* size of the BLOB */
){
  int i, j;
  UNUSED_PARAMETER(nBuf);
  for(i=j=0; i<N; i++){
    sqlite3_int64 x;
    j += sqlite3Fts3GetVarint(&zBuf[j], &x);
  int i = 0;
  if( nBuf && (zBuf[nBuf-1]&0x80)==0 ){
    int j;
    for(i=j=0; i<N && j<nBuf; i++){
      sqlite3_int64 x;
      j += sqlite3Fts3GetVarint(&zBuf[j], &x);
    assert(j<=nBuf);
    a[i] = (u32)(x & 0xffffffff);
  }
      a[i] = (u32)(x & 0xffffffff);
    }
  }
  while( i<N ) a[i++] = 0;
}

/*
** Insert the sizes (in tokens) for each column of the document
** with docid equal to p->iPrevDocid.  The sizes are encoded as
** a blob of varints.
*/
static void fts3InsertDocsize(
  int *pRC,                       /* Result code */
  Fts3Table *p,                   /* Table into which to insert */
  u32 *aSz                        /* Sizes of each column, in tokens */
){
  char *pBlob;             /* The BLOB encoding of the document size */
  int nBlob;               /* Number of bytes in the BLOB */
  sqlite3_stmt *pStmt;     /* Statement used to insert the encoding */
  int rc;                  /* Result code from subfunctions */

  if( *pRC ) return;
  pBlob = sqlite3_malloc( 10*p->nColumn );
  pBlob = sqlite3_malloc64( 10*(sqlite3_int64)p->nColumn );
  if( pBlob==0 ){
    *pRC = SQLITE_NOMEM;
    return;
  }
  fts3EncodeIntArray(p->nColumn, aSz, pBlob, &nBlob);
  rc = fts3SqlStmt(p, SQL_REPLACE_DOCSIZE, &pStmt, 0);
  if( rc ){
3394
3395
3396
3397
3398
3399
3400
3401

3402
3403
3404
3405
3406
3407
3408
3447
3448
3449
3450
3451
3452
3453

3454
3455
3456
3457
3458
3459
3460
3461







-
+







  sqlite3_stmt *pStmt;     /* Statement for reading and writing */
  int i;                   /* Loop counter */
  int rc;                  /* Result code from subfunctions */

  const int nStat = p->nColumn+2;

  if( *pRC ) return;
  a = sqlite3_malloc( (sizeof(u32)+10)*nStat );
  a = sqlite3_malloc64( (sizeof(u32)+10)*(sqlite3_int64)nStat );
  if( a==0 ){
    *pRC = SQLITE_NOMEM;
    return;
  }
  pBlob = (char*)&a[nStat];
  rc = fts3SqlStmt(p, SQL_SELECT_STAT, &pStmt, 0);
  if( rc ){
3458
3459
3460
3461
3462
3463
3464


3465


3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3511
3512
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







+
+
-
+
+




















-







** iIndex/iLangid combination.
*/
static int fts3DoOptimize(Fts3Table *p, int bReturnDone){
  int bSeenDone = 0;
  int rc;
  sqlite3_stmt *pAllLangid = 0;

  rc = sqlite3Fts3PendingTermsFlush(p);
  if( rc==SQLITE_OK ){
  rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
    rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
  }
  if( rc==SQLITE_OK ){
    int rc2;
    sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid);
    sqlite3_bind_int(pAllLangid, 2, p->nIndex);
    while( sqlite3_step(pAllLangid)==SQLITE_ROW ){
      int i;
      int iLangid = sqlite3_column_int(pAllLangid, 0);
      for(i=0; rc==SQLITE_OK && i<p->nIndex; i++){
        rc = fts3SegmentMerge(p, iLangid, i, FTS3_SEGCURSOR_ALL);
        if( rc==SQLITE_DONE ){
          bSeenDone = 1;
          rc = SQLITE_OK;
        }
      }
    }
    rc2 = sqlite3_reset(pAllLangid);
    if( rc==SQLITE_OK ) rc = rc2;
  }

  sqlite3Fts3SegmentsClose(p);
  sqlite3Fts3PendingTermsClear(p);

  return (rc==SQLITE_OK && bReturnDone && bSeenDone) ? SQLITE_DONE : rc;
}

/*
** This function is called when the user executes the following statement:
**
3515
3516
3517
3518
3519
3520
3521
3522
3523


3524
3525
3526
3527
3528
3529
3530
3570
3571
3572
3573
3574
3575
3576


3577
3578
3579
3580
3581
3582
3583
3584
3585







-
-
+
+







      rc = SQLITE_NOMEM;
    }else{
      rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
      sqlite3_free(zSql);
    }

    if( rc==SQLITE_OK ){
      int nByte = sizeof(u32) * (p->nColumn+1)*3;
      aSz = (u32 *)sqlite3_malloc(nByte);
      sqlite3_int64 nByte = sizeof(u32) * ((sqlite3_int64)p->nColumn+1)*3;
      aSz = (u32 *)sqlite3_malloc64(nByte);
      if( aSz==0 ){
        rc = SQLITE_NOMEM;
      }else{
        memset(aSz, 0, nByte);
        aSzIns = &aSz[p->nColumn+1];
        aSzDel = &aSzIns[p->nColumn+1];
      }
3582
3583
3584
3585
3586
3587
3588
3589

3590
3591
3592
3593
3594

3595
3596
3597
3598
3599
3600
3601
3637
3638
3639
3640
3641
3642
3643

3644
3645
3646
3647
3648

3649
3650
3651
3652
3653
3654
3655
3656







-
+




-
+







  Fts3Table *p,                   /* FTS3 table handle */
  sqlite3_int64 iAbsLevel,        /* Absolute level to open */
  int nSeg,                       /* Number of segments to merge */
  Fts3MultiSegReader *pCsr        /* Cursor object to populate */
){
  int rc;                         /* Return Code */
  sqlite3_stmt *pStmt = 0;        /* Statement used to read %_segdir entry */  
  int nByte;                      /* Bytes allocated at pCsr->apSegment[] */
  sqlite3_int64 nByte;            /* Bytes allocated at pCsr->apSegment[] */

  /* Allocate space for the Fts3MultiSegReader.aCsr[] array */
  memset(pCsr, 0, sizeof(*pCsr));
  nByte = sizeof(Fts3SegReader *) * nSeg;
  pCsr->apSegment = (Fts3SegReader **)sqlite3_malloc(nByte);
  pCsr->apSegment = (Fts3SegReader **)sqlite3_malloc64(nByte);

  if( pCsr->apSegment==0 ){
    rc = SQLITE_NOMEM;
  }else{
    memset(pCsr->apSegment, 0, nByte);
    rc = fts3SqlStmt(p, SQL_SELECT_LEVEL, &pStmt, 0);
  }
3693
3694
3695
3696
3697
3698
3699
3700

3701
3702
3703
3704
3705
3706
3707
3748
3749
3750
3751
3752
3753
3754

3755
3756
3757
3758
3759
3760
3761
3762







-
+







** If an OOM error occurs, set *pRc to SQLITE_NOMEM and leave pBlob->a
** unmodified. Otherwise, if the allocation succeeds, update pBlob->nAlloc
** to reflect the new size of the pBlob->a[] buffer.
*/
static void blobGrowBuffer(Blob *pBlob, int nMin, int *pRc){
  if( *pRc==SQLITE_OK && nMin>pBlob->nAlloc ){
    int nAlloc = nMin;
    char *a = (char *)sqlite3_realloc(pBlob->a, nAlloc);
    char *a = (char *)sqlite3_realloc64(pBlob->a, nAlloc);
    if( a ){
      pBlob->nAlloc = nAlloc;
      pBlob->a = a;
    }else{
      *pRc = SQLITE_NOMEM;
    }
  }
3730
3731
3732
3733
3734
3735
3736
3737
3738


3739
3740
3741

3742
3743
3744
3745
3746
3747
3748

3749
3750
3751
3752
3753
3754
3755
3756

3757
3758
3759
3760
3761
3762
3763
3785
3786
3787
3788
3789
3790
3791


3792
3793
3794
3795

3796
3797
3798
3799
3800
3801
3802

3803
3804
3805
3806
3807
3808
3809
3810

3811
3812
3813
3814
3815
3816
3817
3818







-
-
+
+


-
+






-
+







-
+







    p->aNode = 0;
  }else{
    if( bFirst==0 ){
      p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &nPrefix);
    }
    p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &nSuffix);

    if( nPrefix>p->iOff || nSuffix>p->nNode-p->iOff ){
      return SQLITE_CORRUPT_VTAB;
    if( nPrefix>p->term.n || nSuffix>p->nNode-p->iOff || nSuffix==0 ){
      return FTS_CORRUPT_VTAB;
    }
    blobGrowBuffer(&p->term, nPrefix+nSuffix, &rc);
    if( rc==SQLITE_OK ){
    if( rc==SQLITE_OK && ALWAYS(p->term.a!=0) ){
      memcpy(&p->term.a[nPrefix], &p->aNode[p->iOff], nSuffix);
      p->term.n = nPrefix+nSuffix;
      p->iOff += nSuffix;
      if( p->iChild==0 ){
        p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &p->nDoclist);
        if( (p->nNode-p->iOff)<p->nDoclist ){
          return SQLITE_CORRUPT_VTAB;
          return FTS_CORRUPT_VTAB;
        }
        p->aDoclist = &p->aNode[p->iOff];
        p->iOff += p->nDoclist;
      }
    }
  }

  assert( p->iOff<=p->nNode );
  assert_fts3_nc( p->iOff<=p->nNode );
  return rc;
}

/*
** Release all dynamic resources held by node-reader object *p.
*/
static void nodeReaderRelease(NodeReader *p){
3773
3774
3775
3776
3777
3778
3779
3780

3781
3782
3783
3784
3785
3786
3787

3788
3789
3790
3791
3792
3793
3794
3828
3829
3830
3831
3832
3833
3834

3835
3836
3837
3838
3839
3840
3841

3842
3843
3844
3845
3846
3847
3848
3849







-
+






-
+







*/
static int nodeReaderInit(NodeReader *p, const char *aNode, int nNode){
  memset(p, 0, sizeof(NodeReader));
  p->aNode = aNode;
  p->nNode = nNode;

  /* Figure out if this is a leaf or an internal node. */
  if( p->aNode[0] ){
  if( aNode && aNode[0] ){
    /* An internal node. */
    p->iOff = 1 + sqlite3Fts3GetVarint(&p->aNode[1], &p->iChild);
  }else{
    p->iOff = 1;
  }

  return nodeReaderNext(p);
  return aNode ? nodeReaderNext(p) : SQLITE_OK;
}

/*
** This function is called while writing an FTS segment each time a leaf o
** node is finished and written to disk. The key (zTerm/nTerm) is guaranteed
** to be greater than the largest key on the node just written, but smaller
** than or equal to the first key that will be written to the next leaf
3817
3818
3819
3820
3821
3822
3823

3824
3825
3826
3827
3828
3829
3830
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886







+








    /* Figure out how much space the key will consume if it is written to
    ** the current node of layer iLayer. Due to the prefix compression, 
    ** the space required changes depending on which node the key is to
    ** be added to.  */
    nPrefix = fts3PrefixCompress(pNode->key.a, pNode->key.n, zTerm, nTerm);
    nSuffix = nTerm - nPrefix;
    if(nSuffix<=0 ) return FTS_CORRUPT_VTAB;
    nSpace  = sqlite3Fts3VarintLen(nPrefix);
    nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix;

    if( pNode->key.n==0 || (pNode->block.n + nSpace)<=p->nNodeSize ){ 
      /* If the current node of layer iLayer contains zero keys, or if adding
      ** the key to it will not cause it to grow to larger than nNodeSize 
      ** bytes in size, write the key here.  */
3841
3842
3843
3844
3845
3846
3847


3848
3849
3850
3851
3852
3853
3854
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912







+
+







      blobGrowBuffer(&pNode->key, nTerm, &rc);

      if( rc==SQLITE_OK ){
        if( pNode->key.n ){
          pBlk->n += sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nPrefix);
        }
        pBlk->n += sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nSuffix);
        assert( nPrefix+nSuffix<=nTerm );
        assert( nPrefix>=0 );
        memcpy(&pBlk->a[pBlk->n], &zTerm[nPrefix], nSuffix);
        pBlk->n += nSuffix;

        memcpy(pNode->key.a, zTerm, nTerm);
        pNode->key.n = nTerm;
      }
    }else{
3910
3911
3912
3913
3914
3915
3916
3917

3918
3919
3920
3921
3922
3923

3924
3925
3926
3927
3928
3929
3930
3968
3969
3970
3971
3972
3973
3974

3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989







-
+






+







  int bFirst = (pPrev->n==0);     /* True if this is the first term written */
  int nPrefix;                    /* Size of term prefix in bytes */
  int nSuffix;                    /* Size of term suffix in bytes */

  /* Node must have already been started. There must be a doclist for a
  ** leaf node, and there must not be a doclist for an internal node.  */
  assert( pNode->n>0 );
  assert( (pNode->a[0]=='\0')==(aDoclist!=0) );
  assert_fts3_nc( (pNode->a[0]=='\0')==(aDoclist!=0) );

  blobGrowBuffer(pPrev, nTerm, &rc);
  if( rc!=SQLITE_OK ) return rc;

  nPrefix = fts3PrefixCompress(pPrev->a, pPrev->n, zTerm, nTerm);
  nSuffix = nTerm - nPrefix;
  if( nSuffix<=0 ) return FTS_CORRUPT_VTAB;
  memcpy(pPrev->a, zTerm, nTerm);
  pPrev->n = nTerm;

  if( bFirst==0 ){
    pNode->n += sqlite3Fts3PutVarint(&pNode->a[pNode->n], nPrefix);
  }
  pNode->n += sqlite3Fts3PutVarint(&pNode->a[pNode->n], nSuffix);
3962
3963
3964
3965
3966
3967
3968

3969
3970
3971
3972
3973
3974
3975
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035







+







  int nPrefix;                  /* Size of prefix shared with previous term */
  int nSuffix;                  /* Size of suffix (nTerm - nPrefix) */
  NodeWriter *pLeaf;            /* Object used to write leaf nodes */

  pLeaf = &pWriter->aNodeWriter[0];
  nPrefix = fts3PrefixCompress(pLeaf->key.a, pLeaf->key.n, zTerm, nTerm);
  nSuffix = nTerm - nPrefix;
  if(nSuffix<=0 ) return FTS_CORRUPT_VTAB;

  nSpace  = sqlite3Fts3VarintLen(nPrefix);
  nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix;
  nSpace += sqlite3Fts3VarintLen(nDoclist) + nDoclist;

  /* If the current block is not empty, and if adding this term/doclist
  ** to the current block would make it larger than Fts3Table.nNodeSize
4126
4127
4128
4129
4130
4131
4132

4133




4134
4135
4136
4137
4138
4139
4140
4186
4187
4188
4189
4190
4191
4192
4193

4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204







+
-
+
+
+
+







static int fts3TermCmp(
  const char *zLhs, int nLhs,     /* LHS of comparison */
  const char *zRhs, int nRhs      /* RHS of comparison */
){
  int nCmp = MIN(nLhs, nRhs);
  int res;

  if( nCmp && ALWAYS(zLhs) && ALWAYS(zRhs) ){
  res = memcmp(zLhs, zRhs, nCmp);
    res = memcmp(zLhs, zRhs, nCmp);
  }else{
    res = 0;
  }
  if( res==0 ) res = nLhs - nRhs;

  return res;
}


/*
4210
4211
4212
4213
4214
4215
4216




4217
4218
4219
4220
4221
4222
4223
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291







+
+
+
+







      fts3ReadEndBlockField(pSelect, 3, &iEnd, &pWriter->nLeafData);
      if( pWriter->nLeafData<0 ){
        pWriter->nLeafData = pWriter->nLeafData * -1;
      }
      pWriter->bNoLeafData = (pWriter->nLeafData==0);
      nRoot = sqlite3_column_bytes(pSelect, 4);
      aRoot = sqlite3_column_blob(pSelect, 4);
      if( aRoot==0 ){
        sqlite3_reset(pSelect);
        return nRoot ? SQLITE_NOMEM : FTS_CORRUPT_VTAB;
      }
    }else{
      return sqlite3_reset(pSelect);
    }

    /* Check for the zero-length marker in the %_segments table */
    rc = fts3IsAppendable(p, iEnd, &bAppendable);

4245
4246
4247
4248
4249
4250
4251




4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265



4266
4267
4268

4269
4270
4271
4272
4273
4274

4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292

























4293
4294
4295
4296
4297
4298
4299
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
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382







+
+
+
+













-
+
+
+



+






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








    if( rc==SQLITE_OK && bAppendable ){
      /* It is possible to append to this segment. Set up the IncrmergeWriter
      ** object to do so.  */
      int i;
      int nHeight = (int)aRoot[0];
      NodeWriter *pNode;
      if( nHeight<1 || nHeight>=FTS_MAX_APPENDABLE_HEIGHT ){
        sqlite3_reset(pSelect);
        return FTS_CORRUPT_VTAB;
      }

      pWriter->nLeafEst = (int)((iEnd - iStart) + 1)/FTS_MAX_APPENDABLE_HEIGHT;
      pWriter->iStart = iStart;
      pWriter->iEnd = iEnd;
      pWriter->iAbsLevel = iAbsLevel;
      pWriter->iIdx = iIdx;

      for(i=nHeight+1; i<FTS_MAX_APPENDABLE_HEIGHT; i++){
        pWriter->aNodeWriter[i].iBlock = pWriter->iStart + i*pWriter->nLeafEst;
      }

      pNode = &pWriter->aNodeWriter[nHeight];
      pNode->iBlock = pWriter->iStart + pWriter->nLeafEst*nHeight;
      blobGrowBuffer(&pNode->block, MAX(nRoot, p->nNodeSize), &rc);
      blobGrowBuffer(&pNode->block, 
          MAX(nRoot, p->nNodeSize)+FTS3_NODE_PADDING, &rc
      );
      if( rc==SQLITE_OK ){
        memcpy(pNode->block.a, aRoot, nRoot);
        pNode->block.n = nRoot;
        memset(&pNode->block.a[nRoot], 0, FTS3_NODE_PADDING);
      }

      for(i=nHeight; i>=0 && rc==SQLITE_OK; i--){
        NodeReader reader;
        pNode = &pWriter->aNodeWriter[i];

        if( pNode->block.a){
        rc = nodeReaderInit(&reader, pNode->block.a, pNode->block.n);
        while( reader.aNode && rc==SQLITE_OK ) rc = nodeReaderNext(&reader);
        blobGrowBuffer(&pNode->key, reader.term.n, &rc);
        if( rc==SQLITE_OK ){
          memcpy(pNode->key.a, reader.term.a, reader.term.n);
          pNode->key.n = reader.term.n;
          if( i>0 ){
            char *aBlock = 0;
            int nBlock = 0;
            pNode = &pWriter->aNodeWriter[i-1];
            pNode->iBlock = reader.iChild;
            rc = sqlite3Fts3ReadBlock(p, reader.iChild, &aBlock, &nBlock, 0);
            blobGrowBuffer(&pNode->block, MAX(nBlock, p->nNodeSize), &rc);
            if( rc==SQLITE_OK ){
              memcpy(pNode->block.a, aBlock, nBlock);
              pNode->block.n = nBlock;
            }
            sqlite3_free(aBlock);
          rc = nodeReaderInit(&reader, pNode->block.a, pNode->block.n);
          while( reader.aNode && rc==SQLITE_OK ) rc = nodeReaderNext(&reader);
          blobGrowBuffer(&pNode->key, reader.term.n, &rc);
          if( rc==SQLITE_OK ){
            assert_fts3_nc( reader.term.n>0 || reader.aNode==0 );
            if( reader.term.n>0 ){
              memcpy(pNode->key.a, reader.term.a, reader.term.n);
            }
            pNode->key.n = reader.term.n;
            if( i>0 ){
              char *aBlock = 0;
              int nBlock = 0;
              pNode = &pWriter->aNodeWriter[i-1];
              pNode->iBlock = reader.iChild;
              rc = sqlite3Fts3ReadBlock(p, reader.iChild, &aBlock, &nBlock,0);
              blobGrowBuffer(&pNode->block, 
                  MAX(nBlock, p->nNodeSize)+FTS3_NODE_PADDING, &rc
                  );
              if( rc==SQLITE_OK ){
                memcpy(pNode->block.a, aBlock, nBlock);
                pNode->block.n = nBlock;
                memset(&pNode->block.a[nBlock], 0, FTS3_NODE_PADDING);
              }
              sqlite3_free(aBlock);
            }
          }
        }
        nodeReaderRelease(&reader);
      }
    }

    rc2 = sqlite3_reset(pSelect);
4462
4463
4464
4465
4466
4467
4468
4469

4470
4471
4472
4473
4474
4475
4476
4545
4546
4547
4548
4549
4550
4551

4552
4553
4554
4555
4556
4557
4558
4559







-
+







  if( rc==SQLITE_OK ){
    int rc2;
    sqlite3_bind_int64(pSelect, 1, iAbsLevel);
    while( SQLITE_ROW==sqlite3_step(pSelect) ){
      if( nIdx>=nAlloc ){
        int *aNew;
        nAlloc += 16;
        aNew = sqlite3_realloc(aIdx, nAlloc*sizeof(int));
        aNew = sqlite3_realloc64(aIdx, nAlloc*sizeof(int));
        if( !aNew ){
          rc = SQLITE_NOMEM;
          break;
        }
        aIdx = aNew;
      }
      aIdx[nIdx++] = sqlite3_column_int(pSelect, 0);
4528
4529
4530
4531
4532
4533
4534



4535

4536
4537
4538
4539
4540
4541
4542
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620

4621
4622
4623
4624
4625
4626
4627
4628







+
+
+
-
+







  const char *zTerm,              /* Omit all terms smaller than this */
  int nTerm,                      /* Size of zTerm in bytes */
  sqlite3_int64 *piBlock          /* OUT: Block number in next layer down */
){
  NodeReader reader;              /* Reader object */
  Blob prev = {0, 0, 0};          /* Previous term written to new node */
  int rc = SQLITE_OK;             /* Return code */
  int bLeaf;                       /* True for a leaf node */

  if( nNode<1 ) return FTS_CORRUPT_VTAB;
  int bLeaf = aNode[0]=='\0';     /* True for a leaf node */
  bLeaf = aNode[0]=='\0';

  /* Allocate required output space */
  blobGrowBuffer(pNew, nNode, &rc);
  if( rc!=SQLITE_OK ) return rc;
  pNew->n = 0;

  /* Populate new node buffer */
4748
4749
4750
4751
4752
4753
4754
4755

4756
4757
4758
4759
4760
4761
4762
4834
4835
4836
4837
4838
4839
4840

4841
4842
4843
4844
4845
4846
4847
4848







-
+







    sqlite3_bind_int(pSelect, 1, FTS_STAT_INCRMERGEHINT);
    if( SQLITE_ROW==sqlite3_step(pSelect) ){
      const char *aHint = sqlite3_column_blob(pSelect, 0);
      int nHint = sqlite3_column_bytes(pSelect, 0);
      if( aHint ){
        blobGrowBuffer(pHint, nHint, &rc);
        if( rc==SQLITE_OK ){
          memcpy(pHint->a, aHint, nHint);
          if( ALWAYS(pHint->a!=0) ) memcpy(pHint->a, aHint, nHint);
          pHint->n = nHint;
        }
      }
    }
    rc2 = sqlite3_reset(pSelect);
    if( rc==SQLITE_OK ) rc = rc2;
  }
4794
4795
4796
4797
4798
4799
4800
4801


4802


4803
4804
4805
4806
4807

4808
4809
4810
4811
4812
4813
4814
4880
4881
4882
4883
4884
4885
4886

4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904







-
+
+

+
+





+







** If no error occurs, return SQLITE_OK. If the hint blob in *pHint does
** not contain at least two valid varints, return SQLITE_CORRUPT_VTAB.
*/
static int fts3IncrmergeHintPop(Blob *pHint, i64 *piAbsLevel, int *pnInput){
  const int nHint = pHint->n;
  int i;

  i = pHint->n-2;
  i = pHint->n-1;
  if( (pHint->a[i] & 0x80) ) return FTS_CORRUPT_VTAB;
  while( i>0 && (pHint->a[i-1] & 0x80) ) i--;
  if( i==0 ) return FTS_CORRUPT_VTAB;
  i--;
  while( i>0 && (pHint->a[i-1] & 0x80) ) i--;

  pHint->n = i;
  i += sqlite3Fts3GetVarint(&pHint->a[i], piAbsLevel);
  i += fts3GetVarint32(&pHint->a[i], pnInput);
  assert( i<=nHint );
  if( i!=nHint ) return FTS_CORRUPT_VTAB;

  return SQLITE_OK;
}


/*
4829
4830
4831
4832
4833
4834
4835
4836

4837
4838
4839
4840
4841
4842
4843
4919
4920
4921
4922
4923
4924
4925

4926
4927
4928
4929
4930
4931
4932
4933







-
+







  int nSeg = 0;                   /* Number of input segments */
  sqlite3_int64 iAbsLevel = 0;    /* Absolute level number to work on */
  Blob hint = {0, 0, 0};          /* Hint read from %_stat table */
  int bDirtyHint = 0;             /* True if blob 'hint' has been modified */

  /* Allocate space for the cursor, filter and writer objects */
  const int nAlloc = sizeof(*pCsr) + sizeof(*pFilter) + sizeof(*pWriter);
  pWriter = (IncrmergeWriter *)sqlite3_malloc(nAlloc);
  pWriter = (IncrmergeWriter *)sqlite3_malloc64(nAlloc);
  if( !pWriter ) return SQLITE_NOMEM;
  pFilter = (Fts3SegFilter *)&pWriter[1];
  pCsr = (Fts3MultiSegReader *)&pFilter[1];

  rc = fts3IncrmergeHintLoad(p, &hint);
  while( rc==SQLITE_OK && nRem>0 ){
    const i64 nMod = FTS3_SEGDIR_MAXLEVEL * p->nIndex;
4870
4871
4872
4873
4874
4875
4876






4877
4878

4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890





4891


4892
4893
4894
4895
4896
4897
4898
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973

4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991

4992
4993
4994
4995
4996
4997
4998
4999
5000







+
+
+
+
+
+

-
+












+
+
+
+
+
-
+
+







    if( rc==SQLITE_OK && hint.n ){
      int nHint = hint.n;
      sqlite3_int64 iHintAbsLevel = 0;      /* Hint level */
      int nHintSeg = 0;                     /* Hint number of segments */

      rc = fts3IncrmergeHintPop(&hint, &iHintAbsLevel, &nHintSeg);
      if( nSeg<0 || (iAbsLevel % nMod) >= (iHintAbsLevel % nMod) ){
        /* Based on the scan in the block above, it is known that there
        ** are no levels with a relative level smaller than that of
        ** iAbsLevel with more than nSeg segments, or if nSeg is -1, 
        ** no levels with more than nMin segments. Use this to limit the
        ** value of nHintSeg to avoid a large memory allocation in case the 
        ** merge-hint is corrupt*/
        iAbsLevel = iHintAbsLevel;
        nSeg = nHintSeg;
        nSeg = MIN(MAX(nMin,nSeg), nHintSeg);
        bUseHint = 1;
        bDirtyHint = 1;
      }else{
        /* This undoes the effect of the HintPop() above - so that no entry
        ** is removed from the hint blob.  */
        hint.n = nHint;
      }
    }

    /* If nSeg is less that zero, then there is no level with at least
    ** nMin segments and no hint in the %_stat table. No work to do.
    ** Exit early in this case.  */
    if( nSeg<=0 ) break;

    assert( nMod<=0x7FFFFFFF );
    if( iAbsLevel<0 || iAbsLevel>(nMod<<32) ){
      rc = FTS_CORRUPT_VTAB;
    if( nSeg<0 ) break;
      break;
    }

    /* Open a cursor to iterate through the contents of the oldest nSeg 
    ** indexes of absolute level iAbsLevel. If this cursor is opened using 
    ** the 'hint' parameters, it is possible that there are less than nSeg
    ** segments available in level iAbsLevel. In this case, no work is
    ** done on iAbsLevel - fall through to the next iteration of the loop 
    ** to start work on some other level.  */
4912
4913
4914
4915
4916
4917
4918
4919
4920








4921
4922
4923
4924
4925
4926
4927
4928
4929
4930

4931
4932
4933
4934
4935






4936
4937
4938
4939
4940
4941
4942
5014
5015
5016
5017
5018
5019
5020

5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040





5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053







-

+
+
+
+
+
+
+
+










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







    }

    if( rc==SQLITE_OK ){
      rc = fts3IncrmergeCsr(p, iAbsLevel, nSeg, pCsr);
    }
    if( SQLITE_OK==rc && pCsr->nSegment==nSeg
     && SQLITE_OK==(rc = sqlite3Fts3SegReaderStart(p, pCsr, pFilter))
     && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pCsr))
    ){
      int bEmpty = 0;
      rc = sqlite3Fts3SegReaderStep(p, pCsr);
      if( rc==SQLITE_OK ){
        bEmpty = 1;
      }else if( rc!=SQLITE_ROW ){
        sqlite3Fts3SegReaderFinish(pCsr);
        break;
      }
      if( bUseHint && iIdx>0 ){
        const char *zKey = pCsr->zTerm;
        int nKey = pCsr->nTerm;
        rc = fts3IncrmergeLoad(p, iAbsLevel, iIdx-1, zKey, nKey, pWriter);
      }else{
        rc = fts3IncrmergeWriter(p, iAbsLevel, iIdx, pCsr, pWriter);
      }

      if( rc==SQLITE_OK && pWriter->nLeafEst ){
        fts3LogMerge(nSeg, iAbsLevel);
        if( bEmpty==0 ){
        do {
          rc = fts3IncrmergeAppend(p, pWriter, pCsr);
          if( rc==SQLITE_OK ) rc = sqlite3Fts3SegReaderStep(p, pCsr);
          if( pWriter->nWork>=nRem && rc==SQLITE_ROW ) rc = SQLITE_OK;
        }while( rc==SQLITE_ROW );
          do {
            rc = fts3IncrmergeAppend(p, pWriter, pCsr);
            if( rc==SQLITE_OK ) rc = sqlite3Fts3SegReaderStep(p, pCsr);
            if( pWriter->nWork>=nRem && rc==SQLITE_ROW ) rc = SQLITE_OK;
          }while( rc==SQLITE_ROW );
        }

        /* Update or delete the input segments */
        if( rc==SQLITE_OK ){
          nRem -= (1 + pWriter->nWork);
          rc = fts3IncrmergeChomp(p, iAbsLevel, pCsr, &nSeg);
          if( nSeg!=0 ){
            bDirtyHint = 1;
4993
4994
4995
4996
4997
4998
4999
5000

5001
5002
5003
5004
5005
5006
5007
5104
5105
5106
5107
5108
5109
5110

5111
5112
5113
5114
5115
5116
5117
5118







-
+







** before it will be selected for a merge, respectively.
*/
static int fts3DoIncrmerge(
  Fts3Table *p,                   /* FTS3 table handle */
  const char *zParam              /* Nul-terminated string containing "A,B" */
){
  int rc;
  int nMin = (FTS3_MERGE_COUNT / 2);
  int nMin = (MergeCount(p) / 2);
  int nMerge = 0;
  const char *z = zParam;

  /* Read the first integer value */
  nMerge = fts3Getint(&z);

  /* If the first integer value is followed by a ',',  read the second
5038
5039
5040
5041
5042
5043
5044
5045

5046
5047
5048
5049
5050
5051
5052
5149
5150
5151
5152
5153
5154
5155

5156
5157
5158
5159
5160
5161
5162
5163







-
+







static int fts3DoAutoincrmerge(
  Fts3Table *p,                   /* FTS3 table handle */
  const char *zParam              /* Nul-terminated string containing boolean */
){
  int rc = SQLITE_OK;
  sqlite3_stmt *pStmt = 0;
  p->nAutoincrmerge = fts3Getint(&zParam);
  if( p->nAutoincrmerge==1 || p->nAutoincrmerge>FTS3_MERGE_COUNT ){
  if( p->nAutoincrmerge==1 || p->nAutoincrmerge>MergeCount(p) ){
    p->nAutoincrmerge = 8;
  }
  if( !p->bHasStat ){
    assert( p->bFts4==0 );
    sqlite3Fts3CreateStatTable(&rc, p);
    if( rc ) return rc;
  }
5121
5122
5123
5124
5125
5126
5127
5128

5129
5130
5131
5132
5133


5134
5135
5136
5137
5138
5139
5140
5141
5142






5143
5144
5145
5146
5147
5148
5149
5232
5233
5234
5235
5236
5237
5238

5239
5240
5241
5242


5243
5244
5245
5246
5247
5248
5249
5250
5251


5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264







-
+



-
-
+
+







-
-
+
+
+
+
+
+







  if( rc==SQLITE_OK ){
    while( SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, &csr)) ){
      char *pCsr = csr.aDoclist;
      char *pEnd = &pCsr[csr.nDoclist];

      i64 iDocid = 0;
      i64 iCol = 0;
      i64 iPos = 0;
      u64 iPos = 0;

      pCsr += sqlite3Fts3GetVarint(pCsr, &iDocid);
      while( pCsr<pEnd ){
        i64 iVal = 0;
        pCsr += sqlite3Fts3GetVarint(pCsr, &iVal);
        u64 iVal = 0;
        pCsr += sqlite3Fts3GetVarintU(pCsr, &iVal);
        if( pCsr<pEnd ){
          if( iVal==0 || iVal==1 ){
            iCol = 0;
            iPos = 0;
            if( iVal ){
              pCsr += sqlite3Fts3GetVarint(pCsr, &iCol);
            }else{
              pCsr += sqlite3Fts3GetVarint(pCsr, &iVal);
              iDocid += iVal;
              pCsr += sqlite3Fts3GetVarintU(pCsr, &iVal);
              if( p->bDescIdx ){
                iDocid = (i64)((u64)iDocid - iVal);
              }else{
                iDocid = (i64)((u64)iDocid + iVal);
              }
            }
          }else{
            iPos += (iVal - 2);
            cksum = cksum ^ fts3ChecksumEntry(
                csr.zTerm, csr.nTerm, iLangid, iIndex, iDocid,
                (int)iCol, (int)iPos
            );
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218

5219
5220
5221
5222
5223
5224
5225
5323
5324
5325
5326
5327
5328
5329

5330
5331

5332
5333
5334
5335
5336
5337
5338
5339







-


-
+







      i64 iDocid = sqlite3_column_int64(pStmt, 0);
      int iLang = langidFromSelect(p, pStmt);
      int iCol;

      for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){
        if( p->abNotindexed[iCol]==0 ){
          const char *zText = (const char *)sqlite3_column_text(pStmt, iCol+1);
          int nText = sqlite3_column_bytes(pStmt, iCol+1);
          sqlite3_tokenizer_cursor *pT = 0;

          rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, nText,&pT);
          rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, -1, &pT);
          while( rc==SQLITE_OK ){
            char const *zToken;       /* Buffer containing token */
            int nToken = 0;           /* Number of bytes in token */
            int iDum1 = 0, iDum2 = 0; /* Dummy variables */
            int iPos = 0;             /* Position of token in zText */

            rc = pModule->xNext(pT, &zToken, &nToken, &iDum1, &iDum2, &iPos);
5296
5297
5298
5299
5300
5301
5302
5303

5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328














5329
5330
5331
5332
5333







5334
5335
5336
5337
5338
5339
5340
5410
5411
5412
5413
5414
5415
5416

5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432










5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446





5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460







-
+















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







**
**   "INSERT INTO tbl(tbl) VALUES(<expr>)"
**
** Argument pVal contains the result of <expr>. Currently the only 
** meaningful value to insert is the text 'optimize'.
*/
static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){
  int rc;                         /* Return Code */
  int rc = SQLITE_ERROR;           /* Return Code */
  const char *zVal = (const char *)sqlite3_value_text(pVal);
  int nVal = sqlite3_value_bytes(pVal);

  if( !zVal ){
    return SQLITE_NOMEM;
  }else if( nVal==8 && 0==sqlite3_strnicmp(zVal, "optimize", 8) ){
    rc = fts3DoOptimize(p, 0);
  }else if( nVal==7 && 0==sqlite3_strnicmp(zVal, "rebuild", 7) ){
    rc = fts3DoRebuild(p);
  }else if( nVal==15 && 0==sqlite3_strnicmp(zVal, "integrity-check", 15) ){
    rc = fts3DoIntegrityCheck(p);
  }else if( nVal>6 && 0==sqlite3_strnicmp(zVal, "merge=", 6) ){
    rc = fts3DoIncrmerge(p, &zVal[6]);
  }else if( nVal>10 && 0==sqlite3_strnicmp(zVal, "automerge=", 10) ){
    rc = fts3DoAutoincrmerge(p, &zVal[10]);
#ifdef SQLITE_TEST
  }else if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){
    p->nNodeSize = atoi(&zVal[9]);
    rc = SQLITE_OK;
  }else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){
    p->nMaxPendingData = atoi(&zVal[11]);
    rc = SQLITE_OK;
  }else if( nVal>21 && 0==sqlite3_strnicmp(zVal, "test-no-incr-doclist=", 21) ){
    p->bNoIncrDoclist = atoi(&zVal[21]);
    rc = SQLITE_OK;
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
  }else{
    int v;
    if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){
      v = atoi(&zVal[9]);
      if( v>=24 && v<=p->nPgsz-35 ) p->nNodeSize = v;
      rc = SQLITE_OK;
    }else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){
      v = atoi(&zVal[11]);
      if( v>=64 && v<=FTS3_MAX_PENDING_DATA ) p->nMaxPendingData = v;
      rc = SQLITE_OK;
    }else if( nVal>21 && 0==sqlite3_strnicmp(zVal,"test-no-incr-doclist=",21) ){
      p->bNoIncrDoclist = atoi(&zVal[21]);
      rc = SQLITE_OK;
#endif
  }else{
    rc = SQLITE_ERROR;
  }

    }else if( nVal>11 && 0==sqlite3_strnicmp(zVal,"mergecount=",11) ){
      v = atoi(&zVal[11]);
      if( v>=4 && v<=FTS3_MERGE_COUNT && (v&1)==0 ) p->nMergeCount = v;
      rc = SQLITE_OK;
    }
#endif
  }
  return rc;
}

#ifndef SQLITE_DISABLE_FTS4_DEFERRED
/*
** Delete all cached deferred doclists. Deferred doclists are cached
** (allocated) by the sqlite3Fts3CacheDeferredDoclists() function.
5435
5436
5437
5438
5439
5440
5441
5442

5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462

5463
5464
5465
5466
5467
5468
5469
5555
5556
5557
5558
5559
5560
5561

5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581

5582
5583
5584
5585
5586
5587
5588
5589







-
+



















-
+







  *ppData = 0;
  *pnData = 0;

  if( p->pList==0 ){
    return SQLITE_OK;
  }

  pRet = (char *)sqlite3_malloc(p->pList->nData);
  pRet = (char *)sqlite3_malloc64(p->pList->nData);
  if( !pRet ) return SQLITE_NOMEM;

  nSkip = sqlite3Fts3GetVarint(p->pList->aData, &dummy);
  *pnData = p->pList->nData - nSkip;
  *ppData = pRet;
  
  memcpy(pRet, &p->pList->aData[nSkip], *pnData);
  return SQLITE_OK;
}

/*
** Add an entry for token pToken to the pCsr->pDeferred list.
*/
int sqlite3Fts3DeferToken(
  Fts3Cursor *pCsr,               /* Fts3 table cursor */
  Fts3PhraseToken *pToken,        /* Token to defer */
  int iCol                        /* Column that token must appear in (or -1) */
){
  Fts3DeferredToken *pDeferred;
  pDeferred = sqlite3_malloc(sizeof(*pDeferred));
  pDeferred = sqlite3_malloc64(sizeof(*pDeferred));
  if( !pDeferred ){
    return SQLITE_NOMEM;
  }
  memset(pDeferred, 0, sizeof(*pDeferred));
  pDeferred->pToken = pToken;
  pDeferred->pNext = pCsr->pDeferred; 
  pDeferred->iCol = iCol;
5567
5568
5569
5570
5571
5572
5573
5574

5575
5576
5577
5578
5579
5580
5581
5687
5688
5689
5690
5691
5692
5693

5694
5695
5696
5697
5698
5699
5700
5701







-
+








  if( nArg>1 && sqlite3_value_int(apVal[2 + p->nColumn + 2])<0 ){
    rc = SQLITE_CONSTRAINT;
    goto update_out;
  }

  /* Allocate space to hold the change in document sizes */
  aSzDel = sqlite3_malloc( sizeof(aSzDel[0])*(p->nColumn+1)*2 );
  aSzDel = sqlite3_malloc64(sizeof(aSzDel[0])*((sqlite3_int64)p->nColumn+1)*2);
  if( aSzDel==0 ){
    rc = SQLITE_NOMEM;
    goto update_out;
  }
  aSzIns = &aSzDel[p->nColumn+1];
  memset(aSzDel, 0, sizeof(aSzDel[0])*(p->nColumn+1)*2);

Deleted ext/fts3/mkfts3amal.tcl.

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



















































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#!/usr/bin/tclsh
#
# This script builds a single C code file holding all of FTS3 code.
# The name of the output file is fts3amal.c.  To build this file,
# first do:
#
#      make target_source
#
# The make target above moves all of the source code files into
# a subdirectory named "tsrc".  (This script expects to find the files
# there and will not work if they are not found.)
#
# After the "tsrc" directory has been created and populated, run
# this script:
#
#      tclsh mkfts3amal.tcl
#
# The amalgamated FTS3 code will be written into fts3amal.c
#

# Open the output file and write a header comment at the beginning
# of the file.
#
set out [open fts3amal.c w]
set today [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S UTC" -gmt 1]
puts $out [subst \
{/******************************************************************************
** This file is an amalgamation of separate C source files from the SQLite
** Full Text Search extension 2 (fts3).  By combining all the individual C 
** code  files into this single large file, the entire code can be compiled 
** as a one translation unit.  This allows many compilers to do optimizations
** that would not be possible if the files were compiled separately.  It also
** makes the code easier to import into other projects.
**
** This amalgamation was generated on $today.
*/}]

# These are the header files used by FTS3.  The first time any of these 
# files are seen in a #include statement in the C code, include the complete
# text of the file in-line.  The file only needs to be included once.
#
foreach hdr {
   fts3.h
   fts3_hash.h
   fts3_tokenizer.h
   sqlite3.h
   sqlite3ext.h
} {
  set available_hdr($hdr) 1
}

# 78 stars used for comment formatting.
set s78 \
{*****************************************************************************}

# Insert a comment into the code
#
proc section_comment {text} {
  global out s78
  set n [string length $text]
  set nstar [expr {60 - $n}]
  set stars [string range $s78 0 $nstar]
  puts $out "/************** $text $stars/"
}

# Read the source file named $filename and write it into the
# sqlite3.c output file.  If any #include statements are seen,
# process them approprately.
#
proc copy_file {filename} {
  global seen_hdr available_hdr out
  set tail [file tail $filename]
  section_comment "Begin file $tail"
  set in [open $filename r]
  while {![eof $in]} {
    set line [gets $in]
    if {[regexp {^#\s*include\s+["<]([^">]+)[">]} $line all hdr]} {
      if {[info exists available_hdr($hdr)]} {
        if {$available_hdr($hdr)} {
          section_comment "Include $hdr in the middle of $tail"
          copy_file tsrc/$hdr
          section_comment "Continuing where we left off in $tail"
        }
      } elseif {![info exists seen_hdr($hdr)]} {
        set seen_hdr($hdr) 1
        puts $out $line
      }
    } elseif {[regexp {^#ifdef __cplusplus} $line]} {
      puts $out "#if 0"
    } elseif {[regexp {^#line} $line]} {
      # Skip #line directives.
    } else {
      puts $out $line
    }
  }
  close $in
  section_comment "End of $tail"
}


# Process the source files.  Process files containing commonly
# used subroutines first in order to help the compiler find
# inlining opportunities.
#
foreach file {
   fts3.c
   fts3_hash.c
   fts3_porter.c
   fts3_tokenizer.c
   fts3_tokenizer1.c
} {
  copy_file tsrc/$file
}

close $out

Changes to ext/fts3/tool/fts3view.c.

89
90
91
92
93
94
95
96

97
98
99
100
101
102
103
89
90
91
92
93
94
95

96
97
98
99
100
101
102
103







-
+








/*
** Show the table schema
*/
static void showSchema(sqlite3 *db, const char *zTab){
  sqlite3_stmt *pStmt;
  pStmt = prepare(db,
            "SELECT sql FROM sqlite_master"
            "SELECT sql FROM sqlite_schema"
            " WHERE name LIKE '%q%%'"
            " ORDER BY 1",
            zTab);
  while( sqlite3_step(pStmt)==SQLITE_ROW ){
    printf("%s;\n", sqlite3_column_text(pStmt, 0));
  }
  sqlite3_finalize(pStmt);
827
828
829
830
831
832
833
834

835
836
837
838
839
840
841
827
828
829
830
831
832
833

834
835
836
837
838
839
840
841







-
+







    fprintf(stderr, "Cannot open %s\n", argv[1]);
    exit(1);
  }
  if( argc==2 ){
    sqlite3_stmt *pStmt;
    int cnt = 0;
    pStmt = prepare(db, "SELECT b.sql"
                        "  FROM sqlite_master a, sqlite_master b"
                        "  FROM sqlite_schema a, sqlite_schema b"
                        " WHERE a.name GLOB '*_segdir'"
                        "   AND b.name=substr(a.name,1,length(a.name)-7)"
                        " ORDER BY 1");
    while( sqlite3_step(pStmt)==SQLITE_ROW ){
      cnt++;
      printf("%s;\n", sqlite3_column_text(pStmt, 0));
    }

Changes to ext/fts3/unicode/mkunicode.tcl.

59
60
61
62
63
64
65

66

67
68
69
70
71

72
73

74
75
76
77
78
79
80
59
60
61
62
63
64
65
66

67
68
69
70
71

72
73

74
75
76
77
78
79
80
81







+
-
+




-
+

-
+







    incr i

    puts -nonewline [format "%5d" [expr ($iCode<<3) + $nRange-1]]
    puts -nonewline ", "
  }
  puts ""
  puts "  \};"
  puts "#define HIBIT ((unsigned char)0x80)"
  puts "  char aChar\[\] = \{"
  puts "  unsigned char aChar\[\] = \{"
  puts -nonewline "    '\\0',      "
  set i 1
  foreach c $aChar f $aFlag {
    if { $f } {
      set str "'$c'|0x80,  "
      set str "'$c'|HIBIT, "
    } else {
      set str "'$c'|0x00,  "
      set str "'$c',       "
    }
    if {$c == ""} { set str "'\\0',      " }

    if {($i % 6)==0} {puts "" ; puts -nonewline "    " }
    incr i
    puts -nonewline "$str"
  }
130
131
132
133
134
135
136
137
138


139
140
141
142
143
144
145
131
132
133
134
135
136
137


138
139
140
141
142
143
144
145
146







-
-
+
+







  puts "*/"
  puts "int ${zFunc}\(int c)\{"
  puts "  unsigned int mask0 = [format "0x%08X" $i1];"
  puts "  unsigned int mask1 = [format "0x%08X" $i2];"

  puts "  if( c<$iFirst || c>$iLast ) return 0;"
  puts "  return (c < $iFirst+32) ?"
  puts "      (mask0 & (1 << (c-$iFirst))) :"
  puts "      (mask1 & (1 << (c-$iFirst-32)));"
  puts "      (mask0 & ((unsigned int)1 << (c-$iFirst))) :"
  puts "      (mask1 & ((unsigned int)1 << (c-$iFirst-32)));"
  puts "\}"
}


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

proc an_load_separator_ranges {} {
695
696
697
698
699
700
701
702

703
704
705
706
707
708
709
696
697
698
699
700
701
702

703
704
705
706
707
708
709
710







-
+







  set aMapArray [intarray $aMap]
  set aDataArray [intarray $aData]
  puts [code {
    static u16 aFts5UnicodeBlock[] = {$aBlockArray};
    static u16 aFts5UnicodeMap[] = {$aMapArray};
    static u16 aFts5UnicodeData[] = {$aDataArray};

    int sqlite3Fts5UnicodeCategory(int iCode) { 
    int sqlite3Fts5UnicodeCategory(u32 iCode) { 
      int iRes = -1;
      int iHi;
      int iLo;
      int ret;
      u16 iKey;

      if( iCode>=(1<<20) ){
733
734
735
736
737
738
739
740

741
742
743

744
745
746
747
748
749
750
734
735
736
737
738
739
740

741
742
743
744
745
746
747
748
749
750
751
752







-
+



+







    void sqlite3Fts5UnicodeAscii(u8 *aArray, u8 *aAscii){
      int i = 0;
      int iTbl = 0;
      while( i<128 ){
        int bToken = aArray[ aFts5UnicodeData[iTbl] & 0x1F ];
        int n = (aFts5UnicodeData[iTbl] >> 5) + i;
        for(; i<128 && i<n; i++){
          aAscii[i] = bToken;
          aAscii[i] = (u8)bToken;
        }
        iTbl++;
      }
      aAscii[0] = 0;                  /* 0x00 is never a token character */
    }
  }]
}

proc print_test_categories {lMap} {

  set lCP [list]
778
779
780
781
782
783
784
785

786
787
788
789
790
791
792
780
781
782
783
784
785
786

787
788
789
790
791
792
793
794







-
+







        if( aCP[iCP].iCode==i ){
          sqlite3Fts5UnicodeCatParse(aCP[iCP].zCat, aArray);
          iCP++;
        }else{
          aArray[0] = 1;
        }

        c = sqlite3Fts5UnicodeCategory(i);
        c = sqlite3Fts5UnicodeCategory((u32)i);
        if( aArray[c]==0 ){
          *piCode = i;
          return 1;
        }
      }

      return 0;
833
834
835
836
837
838
839
840

841
842
843
844
845
846
847
835
836
837
838
839
840
841

842
843
844
845
846
847
848
849







-
+







  puts "\}"
}


proc print_fileheader {} {
  puts [string trim {
/*
** 2012 May 25
** 2012-05-25
**
** 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.

Changes to ext/fts5/fts5.h.

116
117
118
119
120
121
122
123
124
125
126
127
128


129
130
131
132
133
134
135
116
117
118
119
120
121
122






123
124
125
126
127
128
129
130
131







-
-
-
-
-
-
+
+







**   Query for the details of phrase match iIdx within the current row.
**   Phrase matches are numbered starting from zero, so the iIdx argument
**   should be greater than or equal to zero and smaller than the value
**   output by xInstCount().
**
**   Usually, output parameter *piPhrase is set to the phrase number, *piCol
**   to the column in which it occurs and *piOff the token offset of the
**   first token of the phrase. The exception is if the table was created
**   with the offsets=0 option specified. In this case *piOff is always
**   set to -1.
**
**   Returns SQLITE_OK if successful, or an error code (i.e. SQLITE_NOMEM) 
**   if an error occurs.
**   first token of the phrase. Returns SQLITE_OK if successful, or an error
**   code (i.e. SQLITE_NOMEM) if an error occurs.
**
**   This API can be quite slow if used with an FTS5 table created with the
**   "detail=none" or "detail=column" option. 
**
** xRowid:
**   Returns the rowid of the current row.
**
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
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







-
+


-
+














-
+







**   If the query runs to completion without incident, SQLITE_OK is returned.
**   Or, if some error occurs before the query completes or is aborted by
**   the callback, an SQLite error code is returned.
**
**
** xSetAuxdata(pFts5, pAux, xDelete)
**
**   Save the pointer passed as the second argument as the extension functions 
**   Save the pointer passed as the second argument as the extension function's 
**   "auxiliary data". The pointer may then be retrieved by the current or any
**   future invocation of the same fts5 extension function made as part of
**   of the same MATCH query using the xGetAuxdata() API.
**   the same MATCH query using the xGetAuxdata() API.
**
**   Each extension function is allocated a single auxiliary data slot for
**   each FTS query (MATCH expression). If the extension function is invoked 
**   more than once for a single FTS query, then all invocations share a 
**   single auxiliary data context.
**
**   If there is already an auxiliary data pointer when this function is
**   invoked, then it is replaced by the new pointer. If an xDelete callback
**   was specified along with the original pointer, it is invoked at this
**   point.
**
**   The xDelete callback, if one is specified, is also invoked on the
**   auxiliary data pointer after the FTS5 query has finished.
**
**   If an error (e.g. an OOM condition) occurs within this function, an
**   If an error (e.g. an OOM condition) occurs within this function,
**   the auxiliary data is set to NULL and an error code returned. If the
**   xDelete parameter was not NULL, it is invoked on the auxiliary data
**   pointer before returning.
**
**
** xGetAuxdata(pFts5, bClear)
**
401
402
403
404
405
406
407
408
409


410
411
412
413
414
415
416
397
398
399
400
401
402
403


404
405
406
407
408
409
410
411
412







-
-
+
+







**   of "first place" within the document set, but not alternative forms
**   such as "1st place". In some applications, it would be better to match
**   all instances of "first place" or "1st place" regardless of which form
**   the user specified in the MATCH query text.
**
**   There are several ways to approach this in FTS5:
**
**   <ol><li> By mapping all synonyms to a single token. In this case, the 
**            In the above example, this means that the tokenizer returns the
**   <ol><li> By mapping all synonyms to a single token. In this case, using
**            the above example, this means that the tokenizer returns the
**            same token for inputs "first" and "1st". Say that token is in
**            fact "first", so that when the user inserts the document "I won
**            1st place" entries are added to the index for tokens "i", "won",
**            "first" and "place". If the user then queries for '1st + place',
**            the tokenizer substitutes "first" for "1st" and the query works
**            as expected.
**

Changes to ext/fts5/fts5Int.h.

31
32
33
34
35
36
37





38
39









40
41
42
43
44
45
46
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







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







typedef sqlite3_uint64 u64;

#ifndef ArraySize
# define ArraySize(x) ((int)(sizeof(x) / sizeof(x[0])))
#endif

#define testcase(x)

#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
# define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1
#endif
#if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
#define ALWAYS(x) 1
#define NEVER(x) 0
# define ALWAYS(X)      (1)
# define NEVER(X)       (0)
#elif !defined(NDEBUG)
# define ALWAYS(X)      ((X)?1:(assert(0),0))
# define NEVER(X)       ((X)?(assert(0),1):0)
#else
# define ALWAYS(X)      (X)
# define NEVER(X)       (X)
#endif

#define MIN(x,y) (((x) < (y)) ? (x) : (y))
#define MAX(x,y) (((x) > (y)) ? (x) : (y))

/*
** Constants for the largest and smallest possible 64-bit signed integers.
*/
57
58
59
60
61
62
63





64
65
66
67
68
69
70
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87







+
+
+
+
+







/*
** Maximum number of prefix indexes on single FTS5 table. This must be
** less than 32. If it is set to anything large than that, an #error
** directive in fts5_index.c will cause the build to fail.
*/
#define FTS5_MAX_PREFIX_INDEXES 31

/*
** Maximum segments permitted in a single index 
*/
#define FTS5_MAX_SEGMENT 2000

#define FTS5_DEFAULT_NEARDIST 10
#define FTS5_DEFAULT_RANK     "bm25"

/* Name of rank and rowid columns */
#define FTS5_RANK_NAME "rank"
#define FTS5_ROWID_NAME "rowid"

83
84
85
86
87
88
89






90
91
92
93
94
95
96
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119







+
+
+
+
+
+







#ifdef SQLITE_DEBUG
extern int sqlite3_fts5_may_be_corrupt;
# define assert_nc(x) assert(sqlite3_fts5_may_be_corrupt || (x))
#else
# define assert_nc(x) assert(x)
#endif

/*
** A version of memcmp() that does not cause asan errors if one of the pointer
** parameters is NULL and the number of bytes to compare is zero.
*/
#define fts5Memcmp(s1, s2, n) ((n)<=0 ? 0 : memcmp((s1), (s2), (n)))

/* Mark a function parameter as unused, to suppress nuisance compiler
** warnings. */
#ifndef UNUSED_PARAM
# define UNUSED_PARAM(X)  (void)(X)
#endif

#ifndef UNUSED_PARAM2
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
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







+
+




















-
+





-
-
-
+
+
+

-
+
+
+







  char *zContent;                 /* content table */ 
  char *zContentRowid;            /* "content_rowid=" option value */ 
  int bColumnsize;                /* "columnsize=" option value (dflt==1) */
  int eDetail;                    /* FTS5_DETAIL_XXX value */
  char *zContentExprlist;
  Fts5Tokenizer *pTok;
  fts5_tokenizer *pTokApi;
  int bLock;                      /* True when table is preparing statement */
  int ePattern;                   /* FTS_PATTERN_XXX constant */

  /* Values loaded from the %_config table */
  int iCookie;                    /* Incremented when %_config is modified */
  int pgsz;                       /* Approximate page size used in %_data */
  int nAutomerge;                 /* 'automerge' setting */
  int nCrisisMerge;               /* Maximum allowed segments per level */
  int nUsermerge;                 /* 'usermerge' setting */
  int nHashSize;                  /* Bytes of memory for in-memory hash */
  char *zRank;                    /* Name of rank function */
  char *zRankArgs;                /* Arguments to rank function */

  /* If non-NULL, points to sqlite3_vtab.base.zErrmsg. Often NULL. */
  char **pzErrmsg;

#ifdef SQLITE_DEBUG
  int bPrefixIndex;               /* True to use prefix-indexes */
#endif
};

/* Current expected value of %_config table 'version' field */
#define FTS5_CURRENT_VERSION 4
#define FTS5_CURRENT_VERSION  4

#define FTS5_CONTENT_NORMAL   0
#define FTS5_CONTENT_NONE     1
#define FTS5_CONTENT_EXTERNAL 2

#define FTS5_DETAIL_FULL    0
#define FTS5_DETAIL_NONE    1
#define FTS5_DETAIL_COLUMNS 2
#define FTS5_DETAIL_FULL      0
#define FTS5_DETAIL_NONE      1
#define FTS5_DETAIL_COLUMNS   2


#define FTS5_PATTERN_NONE     0
#define FTS5_PATTERN_LIKE     65  /* matches SQLITE_INDEX_CONSTRAINT_LIKE */
#define FTS5_PATTERN_GLOB     66  /* matches SQLITE_INDEX_CONSTRAINT_GLOB */

int sqlite3Fts5ConfigParse(
    Fts5Global*, sqlite3*, int, const char **, Fts5Config**, char**
);
void sqlite3Fts5ConfigFree(Fts5Config*);

int sqlite3Fts5ConfigDeclareVtab(Fts5Config *pConfig);
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
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







-
+














-
+







void sqlite3Fts5BufferZero(Fts5Buffer*);
void sqlite3Fts5BufferSet(int*, Fts5Buffer*, int, const u8*);
void sqlite3Fts5BufferAppendPrintf(int *, Fts5Buffer*, char *zFmt, ...);

char *sqlite3Fts5Mprintf(int *pRc, const char *zFmt, ...);

#define fts5BufferZero(x)             sqlite3Fts5BufferZero(x)
#define fts5BufferAppendVarint(a,b,c) sqlite3Fts5BufferAppendVarint(a,b,c)
#define fts5BufferAppendVarint(a,b,c) sqlite3Fts5BufferAppendVarint(a,b,(i64)c)
#define fts5BufferFree(a)             sqlite3Fts5BufferFree(a)
#define fts5BufferAppendBlob(a,b,c,d) sqlite3Fts5BufferAppendBlob(a,b,c,d)
#define fts5BufferSet(a,b,c,d)        sqlite3Fts5BufferSet(a,b,c,d)

#define fts5BufferGrow(pRc,pBuf,nn) ( \
  (u32)((pBuf)->n) + (u32)(nn) <= (u32)((pBuf)->nSpace) ? 0 : \
    sqlite3Fts5BufferSize((pRc),(pBuf),(nn)+(pBuf)->n) \
)

/* Write and decode big-endian 32-bit integer values */
void sqlite3Fts5Put32(u8*, int);
int sqlite3Fts5Get32(const u8*);

#define FTS5_POS2COLUMN(iPos) (int)(iPos >> 32)
#define FTS5_POS2OFFSET(iPos) (int)(iPos & 0xFFFFFFFF)
#define FTS5_POS2OFFSET(iPos) (int)(iPos & 0x7FFFFFFF)

typedef struct Fts5PoslistReader Fts5PoslistReader;
struct Fts5PoslistReader {
  /* Variables used only by sqlite3Fts5PoslistIterXXX() functions. */
  const u8 *a;                    /* Position list to iterate through */
  int n;                          /* Size of buffer at a[] in bytes */
  int i;                          /* Current offset in a[] */
305
306
307
308
309
310
311
312

313
314
315
316
317
318
319
332
333
334
335
336
337
338

339
340
341
342
343
344
345
346







-
+







int sqlite3Fts5PoslistNext64(
  const u8 *a, int n,             /* Buffer containing poslist */
  int *pi,                        /* IN/OUT: Offset within a[] */
  i64 *piOff                      /* IN/OUT: Current offset */
);

/* Malloc utility */
void *sqlite3Fts5MallocZero(int *pRc, int nByte);
void *sqlite3Fts5MallocZero(int *pRc, sqlite3_int64 nByte);
char *sqlite3Fts5Strndup(int *pRc, const char *pIn, int nIn);

/* Character set tests (like isspace(), isalpha() etc.) */
int sqlite3Fts5IsBareword(char t);


/* Bucket of terms object used by the integrity-check in offsets=0 mode. */
406
407
408
409
410
411
412





413
414
415
416
417



418
419
420
421
422
423
424
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







+
+
+
+
+





+
+
+







int sqlite3Fts5IterNextFrom(Fts5IndexIter*, i64 iMatch);

/*
** Close an iterator opened by sqlite3Fts5IndexQuery().
*/
void sqlite3Fts5IterClose(Fts5IndexIter*);

/*
** Close the reader blob handle, if it is open.
*/
void sqlite3Fts5IndexCloseReader(Fts5Index*);

/*
** This interface is used by the fts5vocab module.
*/
const char *sqlite3Fts5IterTerm(Fts5IndexIter*, int*);
int sqlite3Fts5IterNextScan(Fts5IndexIter*);
void *sqlite3Fts5StructureRef(Fts5Index*);
void sqlite3Fts5StructureRelease(void*);
int sqlite3Fts5StructureTest(Fts5Index*, void*);


/*
** Insert or remove data to or from the index. Each time a document is 
** added to or removed from the index, this function is called one or more
** times.
**
463
464
465
466
467
468
469
470

471
472
473
474
475
476
477
498
499
500
501
502
503
504

505
506
507
508
509
510
511
512







-
+







*/
int sqlite3Fts5IndexGetAverages(Fts5Index *p, i64 *pnRow, i64 *anSize);
int sqlite3Fts5IndexSetAverages(Fts5Index *p, const u8*, int);

/*
** Functions called by the storage module as part of integrity-check.
*/
int sqlite3Fts5IndexIntegrityCheck(Fts5Index*, u64 cksum);
int sqlite3Fts5IndexIntegrityCheck(Fts5Index*, u64 cksum, int bUseCksum);

/* 
** Called during virtual module initialization to register UDF 
** fts5_decode() with SQLite 
*/
int sqlite3Fts5IndexInit(sqlite3*);

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







-
+

+
+
+
+
+
+
+
+
+
+





-
+
-



-
+
+
+








/*
** End of interface to code in fts5_varint.c.
**************************************************************************/


/**************************************************************************
** Interface to code in fts5.c. 
** Interface to code in fts5_main.c. 
*/

/*
** Virtual-table object.
*/
typedef struct Fts5Table Fts5Table;
struct Fts5Table {
  sqlite3_vtab base;              /* Base class used by SQLite core */
  Fts5Config *pConfig;            /* Virtual table configuration */
  Fts5Index *pIndex;              /* Full-text index */
};

int sqlite3Fts5GetTokenizer(
  Fts5Global*, 
  const char **azArg,
  int nArg,
  Fts5Tokenizer**,
  Fts5Config*,
  fts5_tokenizer**,
  char **pzErr
);

Fts5Index *sqlite3Fts5IndexFromCsrid(Fts5Global*, i64, Fts5Config **);
Fts5Table *sqlite3Fts5TableFromCsrid(Fts5Global*, i64);

int sqlite3Fts5FlushToDisk(Fts5Table*);

/*
** End of interface to code in fts5.c.
**************************************************************************/

/**************************************************************************
** Interface to code in fts5_hash.c. 
561
562
563
564
565
566
567

568
569

570
571
572
573
574
575
576
607
608
609
610
611
612
613
614
615

616
617
618
619
620
621
622
623







+

-
+







/*
** Empty (but do not delete) a hash table.
*/
void sqlite3Fts5HashClear(Fts5Hash*);

int sqlite3Fts5HashQuery(
  Fts5Hash*,                      /* Hash table to query */
  int nPre,
  const char *pTerm, int nTerm,   /* Query term */
  const u8 **ppDoclist,           /* OUT: Pointer to doclist for pTerm */
  void **ppObj,                   /* OUT: Pointer to doclist for pTerm */
  int *pnDoclist                  /* OUT: Size of doclist in bytes */
);

int sqlite3Fts5HashScanInit(
  Fts5Hash*,                      /* Hash table to query */
  const char *pTerm, int nTerm    /* Query prefix */
);
605
606
607
608
609
610
611
612

613
614
615
616
617
618
619
652
653
654
655
656
657
658

659
660
661
662
663
664
665
666







-
+







int sqlite3Fts5DropAll(Fts5Config*);
int sqlite3Fts5CreateTable(Fts5Config*, const char*, const char*, int, char **);

int sqlite3Fts5StorageDelete(Fts5Storage *p, i64, sqlite3_value**);
int sqlite3Fts5StorageContentInsert(Fts5Storage *p, sqlite3_value**, i64*);
int sqlite3Fts5StorageIndexInsert(Fts5Storage *p, sqlite3_value**, i64);

int sqlite3Fts5StorageIntegrity(Fts5Storage *p);
int sqlite3Fts5StorageIntegrity(Fts5Storage *p, int iArg);

int sqlite3Fts5StorageStmt(Fts5Storage *p, int eStmt, sqlite3_stmt**, char**);
void sqlite3Fts5StorageStmtRelease(Fts5Storage *p, int eStmt, sqlite3_stmt*);

int sqlite3Fts5StorageDocsize(Fts5Storage *p, i64 iRowid, int *aCol);
int sqlite3Fts5StorageSize(Fts5Storage *p, int iCol, i64 *pnAvg);
int sqlite3Fts5StorageRowCount(Fts5Storage *p, i64 *pnRow);
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
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







+




+
+
+
+
+
+
+

















+







  const char *p;                  /* Token text (not NULL terminated) */
  int n;                          /* Size of buffer p in bytes */
};

/* Parse a MATCH expression. */
int sqlite3Fts5ExprNew(
  Fts5Config *pConfig, 
  int bPhraseToAnd,
  int iCol,                       /* Column on LHS of MATCH operator */
  const char *zExpr,
  Fts5Expr **ppNew, 
  char **pzErr
);
int sqlite3Fts5ExprPattern(
  Fts5Config *pConfig, 
  int bGlob, 
  int iCol, 
  const char *zText, 
  Fts5Expr **pp
);

/*
** for(rc = sqlite3Fts5ExprFirst(pExpr, pIdx, bDesc);
**     rc==SQLITE_OK && 0==sqlite3Fts5ExprEof(pExpr);
**     rc = sqlite3Fts5ExprNext(pExpr)
** ){
**   // The document with rowid iRowid matches the expression!
**   i64 iRowid = sqlite3Fts5ExprRowid(pExpr);
** }
*/
int sqlite3Fts5ExprFirst(Fts5Expr*, Fts5Index *pIdx, i64 iMin, int bDesc);
int sqlite3Fts5ExprNext(Fts5Expr*, i64 iMax);
int sqlite3Fts5ExprEof(Fts5Expr*);
i64 sqlite3Fts5ExprRowid(Fts5Expr*);

void sqlite3Fts5ExprFree(Fts5Expr*);
int sqlite3Fts5ExprAnd(Fts5Expr **pp1, Fts5Expr *p2);

/* Called during startup to register a UDF with SQLite */
int sqlite3Fts5ExprInit(Fts5Global*, sqlite3*);

int sqlite3Fts5ExprPhraseCount(Fts5Expr*);
int sqlite3Fts5ExprPhraseSize(Fts5Expr*, int iPhrase);
int sqlite3Fts5ExprPoslist(Fts5Expr*, int, const u8 **);
762
763
764
765
766
767
768




769
770
771
772
773
774
775
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835







+
+
+
+







**************************************************************************/

/**************************************************************************
** Interface to code in fts5_tokenizer.c. 
*/

int sqlite3Fts5TokenizerInit(fts5_api*);
int sqlite3Fts5TokenizerPattern(
    int (*xCreate)(void*, const char**, int, Fts5Tokenizer**),
    Fts5Tokenizer *pTok
);
/*
** End of interface to code in fts5_tokenizer.c.
**************************************************************************/

/**************************************************************************
** Interface to code in fts5_vocab.c. 
*/
784
785
786
787
788
789
790
791

792
793
794
795
796
797
844
845
846
847
848
849
850

851
852
853
854
855
856
857







-
+






/**************************************************************************
** Interface to automatically generated code in fts5_unicode2.c. 
*/
int sqlite3Fts5UnicodeIsdiacritic(int c);
int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic);

int sqlite3Fts5UnicodeCatParse(const char*, u8*);
int sqlite3Fts5UnicodeCategory(int iCode);
int sqlite3Fts5UnicodeCategory(u32 iCode);
void sqlite3Fts5UnicodeAscii(u8*, u8*);
/*
** End of interface to code in fts5_unicode2.c.
**************************************************************************/

#endif

Changes to ext/fts5/fts5_aux.c.

132
133
134
135
136
137
138
139

140
141
142
143
144
145
146
132
133
134
135
136
137
138

139
140
141
142
143
144
145
146







-
+







** *pRc is set to an error code before returning. 
*/
static void fts5HighlightAppend(
  int *pRc, 
  HighlightContext *p, 
  const char *z, int n
){
  if( *pRc==SQLITE_OK ){
  if( *pRc==SQLITE_OK && z ){
    if( n<0 ) n = (int)strlen(z);
    p->zOut = sqlite3_mprintf("%z%.*s", p->zOut, n, z);
    if( p->zOut==0 ) *pRc = SQLITE_NOMEM;
  }
}

/*
264
265
266
267
268
269
270
271

272
273
274
275
276
277
278
264
265
266
267
268
269
270

271
272
273
274
275
276
277
278







-
+







** error occurs.
*/
static int fts5SentenceFinderAdd(Fts5SFinder *p, int iAdd){
  if( p->nFirstAlloc==p->nFirst ){
    int nNew = p->nFirstAlloc ? p->nFirstAlloc*2 : 64;
    int *aNew;

    aNew = (int*)sqlite3_realloc(p->aFirst, nNew*sizeof(int));
    aNew = (int*)sqlite3_realloc64(p->aFirst, nNew*sizeof(int));
    if( aNew==0 ) return SQLITE_NOMEM;
    p->aFirst = aNew;
    p->nFirstAlloc = nNew;
  }
  p->aFirst[p->nFirst++] = iAdd;
  return SQLITE_OK;
}
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
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







+




-
+









-
+


-
+







  int ip = 0;
  int ic = 0;
  int iOff = 0;
  int iFirst = -1;
  int nInst;
  int nScore = 0;
  int iLast = 0;
  sqlite3_int64 iEnd = (sqlite3_int64)iPos + nToken;

  rc = pApi->xInstCount(pFts, &nInst);
  for(i=0; i<nInst && rc==SQLITE_OK; i++){
    rc = pApi->xInst(pFts, i, &ip, &ic, &iOff);
    if( rc==SQLITE_OK && ic==iCol && iOff>=iPos && iOff<(iPos+nToken) ){
    if( rc==SQLITE_OK && ic==iCol && iOff>=iPos && iOff<iEnd ){
      nScore += (aSeen[ip] ? 1 : 1000);
      aSeen[ip] = 1;
      if( iFirst<0 ) iFirst = iOff;
      iLast = iOff + pApi->xPhraseSize(pFts, ip);
    }
  }

  *pnScore = nScore;
  if( piPos ){
    int iAdj = iFirst - (nToken - (iLast-iFirst)) / 2;
    sqlite3_int64 iAdj = iFirst - (nToken - (iLast-iFirst)) / 2;
    if( (iAdj+nToken)>nDocsize ) iAdj = nDocsize - nToken;
    if( iAdj<0 ) iAdj = 0;
    *piPos = iAdj;
    *piPos = (int)iAdj;
  }

  return rc;
}

/*
** Return the value in pVal interpreted as utf-8 text. Except, if pVal 
438
439
440
441
442
443
444


445

446
447
448
449
450
451
452
439
440
441
442
443
444
445
446
447

448
449
450
451
452
453
454
455







+
+
-
+







      for(ii=0; rc==SQLITE_OK && ii<nInst; ii++){
        int ip, ic, io;
        int iAdj;
        int nScore;
        int jj;

        rc = pApi->xInst(pFts, ii, &ip, &ic, &io);
        if( ic!=i ) continue;
        if( io>nDocsize ) rc = FTS5_CORRUPT;
        if( ic!=i || rc!=SQLITE_OK ) continue;
        if( rc!=SQLITE_OK ) continue;
        memset(aSeen, 0, nPhrase);
        rc = fts5SnippetScore(pApi, pFts, nDocsize, aSeen, i,
            io, nToken, &nScore, &iAdj
        );
        if( rc==SQLITE_OK && nScore>nBestScore ){
          nBestScore = nScore;
          iBestCol = i;
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
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







-
+




-
+





-
+



-
+







+







  const Fts5ExtensionApi *pApi, 
  Fts5Context *pFts,
  Fts5Bm25Data **ppData           /* OUT: bm25-data object for this query */
){
  int rc = SQLITE_OK;             /* Return code */
  Fts5Bm25Data *p;                /* Object to return */

  p = pApi->xGetAuxdata(pFts, 0);
  p = (Fts5Bm25Data*)pApi->xGetAuxdata(pFts, 0);
  if( p==0 ){
    int nPhrase;                  /* Number of phrases in query */
    sqlite3_int64 nRow = 0;       /* Number of rows in table */
    sqlite3_int64 nToken = 0;     /* Number of tokens in table */
    int nByte;                    /* Bytes of space to allocate */
    sqlite3_int64 nByte;          /* Bytes of space to allocate */
    int i;

    /* Allocate the Fts5Bm25Data object */
    nPhrase = pApi->xPhraseCount(pFts);
    nByte = sizeof(Fts5Bm25Data) + nPhrase*2*sizeof(double);
    p = (Fts5Bm25Data*)sqlite3_malloc(nByte);
    p = (Fts5Bm25Data*)sqlite3_malloc64(nByte);
    if( p==0 ){
      rc = SQLITE_NOMEM;
    }else{
      memset(p, 0, nByte);
      memset(p, 0, (size_t)nByte);
      p->nPhrase = nPhrase;
      p->aIDF = (double*)&p[1];
      p->aFreq = &p->aIDF[nPhrase];
    }

    /* Calculate the average document length for this FTS5 table */
    if( rc==SQLITE_OK ) rc = pApi->xRowCount(pFts, &nRow);
    assert( rc!=SQLITE_OK || nRow>0 );
    if( rc==SQLITE_OK ) rc = pApi->xColumnTotalSize(pFts, -1, &nToken);
    if( rc==SQLITE_OK ) p->avgdl = (double)nToken  / (double)nRow;

    /* Calculate an IDF for each phrase in the query */
    for(i=0; rc==SQLITE_OK && i<nPhrase; i++){
      sqlite3_int64 nHit = 0;
      rc = pApi->xQueryPhrase(pFts, i, (void*)&nHit, fts5CountCb);
632
633
634
635
636
637
638
639

640
641
642
643
644
645
646
636
637
638
639
640
641
642

643
644
645
646
647
648
649
650







-
+







  Fts5Context *pFts,              /* First arg to pass to pApi functions */
  sqlite3_context *pCtx,          /* Context for returning result/error */
  int nVal,                       /* Number of values in apVal[] array */
  sqlite3_value **apVal           /* Array of trailing arguments */
){
  const double k1 = 1.2;          /* Constant "k1" from BM25 formula */
  const double b = 0.75;          /* Constant "b" from BM25 formula */
  int rc = SQLITE_OK;             /* Error code */
  int rc;                         /* Error code */
  double score = 0.0;             /* SQL function return value */
  Fts5Bm25Data *pData;            /* Values allocated/calculated once only */
  int i;                          /* Iterator variable */
  int nInst = 0;                  /* Value returned by xInstCount() */
  double D = 0.0;                 /* Total number of tokens in row */
  double *aFreq = 0;              /* Array of phrase freq. for current row */

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
668
669
670
671
672
673
674







675
676
677
678
679
680
681
682
683




684
685
686
687
688
689
690







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







  /* Figure out the total size of the current row in tokens. */
  if( rc==SQLITE_OK ){
    int nTok;
    rc = pApi->xColumnSize(pFts, -1, &nTok);
    D = (double)nTok;
  }

  /* Determine the BM25 score for the current row. */
  for(i=0; rc==SQLITE_OK && i<pData->nPhrase; i++){
    score += pData->aIDF[i] * (
      ( aFreq[i] * (k1 + 1.0) ) / 
      ( aFreq[i] + k1 * (1 - b + b * D / pData->avgdl) )
    );
  }
  /* Determine and return the BM25 score for the current row. Or, if an
  ** error has occurred, throw an exception. */
  if( rc==SQLITE_OK ){
    for(i=0; i<pData->nPhrase; i++){
      score += pData->aIDF[i] * (
          ( aFreq[i] * (k1 + 1.0) ) / 
          ( aFreq[i] + k1 * (1 - b + b * D / pData->avgdl) )
      );
    }
  
  /* If no error has occurred, return the calculated score. Otherwise,
  ** throw an SQL exception.  */
  if( rc==SQLITE_OK ){
    sqlite3_result_double(pCtx, -1.0 * score);
  }else{
    sqlite3_result_error_code(pCtx, rc);
  }
}

int sqlite3Fts5AuxInit(fts5_api *pApi){
706
707
708
709
710
711
712
713
714
708
709
710
711
712
713
714









-
-
        aBuiltin[i].xFunc,
        aBuiltin[i].xDestroy
    );
  }

  return rc;
}


Changes to ext/fts5/fts5_buffer.c.

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







-
+




-
+




-
+










#include "fts5Int.h"

int sqlite3Fts5BufferSize(int *pRc, Fts5Buffer *pBuf, u32 nByte){
  if( (u32)pBuf->nSpace<nByte ){
    u32 nNew = pBuf->nSpace ? pBuf->nSpace : 64;
    u64 nNew = pBuf->nSpace ? pBuf->nSpace : 64;
    u8 *pNew;
    while( nNew<nByte ){
      nNew = nNew * 2;
    }
    pNew = sqlite3_realloc(pBuf->p, nNew);
    pNew = sqlite3_realloc64(pBuf->p, nNew);
    if( pNew==0 ){
      *pRc = SQLITE_NOMEM;
      return 1;
    }else{
      pBuf->nSpace = nNew;
      pBuf->nSpace = (int)nNew;
      pBuf->p = pNew;
    }
  }
  return 0;
}


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







-
+













-







  aBuf[0] = (iVal>>24) & 0x00FF;
  aBuf[1] = (iVal>>16) & 0x00FF;
  aBuf[2] = (iVal>> 8) & 0x00FF;
  aBuf[3] = (iVal>> 0) & 0x00FF;
}

int sqlite3Fts5Get32(const u8 *aBuf){
  return (aBuf[0] << 24) + (aBuf[1] << 16) + (aBuf[2] << 8) + aBuf[3];
  return (int)((((u32)aBuf[0])<<24) + (aBuf[1]<<16) + (aBuf[2]<<8) + aBuf[3]);
}

/*
** Append buffer nData/pData to buffer pBuf. If an OOM error occurs, set 
** the error code in p. If an error has already occurred when this function
** is called, it is a no-op.
*/
void sqlite3Fts5BufferAppendBlob(
  int *pRc,
  Fts5Buffer *pBuf, 
  u32 nData, 
  const u8 *pData
){
  assert_nc( *pRc || nData>=0 );
  if( nData ){
    if( fts5BufferGrow(pRc, pBuf, nData) ) return;
    memcpy(&pBuf->p[pBuf->n], pData, nData);
    pBuf->n += nData;
  }
}

172
173
174
175
176
177
178
179

180
181





182
183

184




185
186





187

188
189
190
191
192
193
194
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







-
+

-
+
+
+
+
+


+

+
+
+
+
-
-
+
+
+
+
+

+







  int i = *pi;
  if( i>=n ){
    /* EOF */
    *piOff = -1;
    return 1;  
  }else{
    i64 iOff = *piOff;
    int iVal;
    u32 iVal;
    fts5FastGetVarint32(a, i, iVal);
    if( iVal==1 ){
    if( iVal<=1 ){
      if( iVal==0 ){
        *pi = i;
        return 0;
      }
      fts5FastGetVarint32(a, i, iVal);
      iOff = ((i64)iVal) << 32;
      assert( iOff>=0 );
      fts5FastGetVarint32(a, i, iVal);
      if( iVal<2 ){
        /* This is a corrupt record. So stop parsing it here. */
        *piOff = -1;
        return 1;
    }
    *piOff = iOff + (iVal-2);
      }
      *piOff = iOff + ((iVal-2) & 0x7FFFFFFF);
    }else{
      *piOff = (iOff & (i64)0x7FFFFFFF<<32)+((iOff + (iVal-2)) & 0x7FFFFFFF);
    }
    *pi = i;
    assert_nc( *piOff>=iOff );
    return 0;
  }
}


/*
** Advance the iterator object passed as the only argument. Return true
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
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







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













-
+


-
+



-
+







** to iPos before returning.
*/
void sqlite3Fts5PoslistSafeAppend(
  Fts5Buffer *pBuf, 
  i64 *piPrev, 
  i64 iPos
){
  if( iPos>=*piPrev ){
  static const i64 colmask = ((i64)(0x7FFFFFFF)) << 32;
  if( (iPos & colmask) != (*piPrev & colmask) ){
    pBuf->p[pBuf->n++] = 1;
    pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos>>32));
    *piPrev = (iPos & colmask);
  }
  pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos-*piPrev)+2);
  *piPrev = iPos;
    static const i64 colmask = ((i64)(0x7FFFFFFF)) << 32;
    if( (iPos & colmask) != (*piPrev & colmask) ){
      pBuf->p[pBuf->n++] = 1;
      pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos>>32));
      *piPrev = (iPos & colmask);
    }
    pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos-*piPrev)+2);
    *piPrev = iPos;
  }
}

int sqlite3Fts5PoslistWriterAppend(
  Fts5Buffer *pBuf, 
  Fts5PoslistWriter *pWriter,
  i64 iPos
){
  int rc = 0;   /* Initialized only to suppress erroneous warning from Clang */
  if( fts5BufferGrow(&rc, pBuf, 5+5+5) ) return rc;
  sqlite3Fts5PoslistSafeAppend(pBuf, &pWriter->iPrev, iPos);
  return SQLITE_OK;
}

void *sqlite3Fts5MallocZero(int *pRc, int nByte){
void *sqlite3Fts5MallocZero(int *pRc, sqlite3_int64 nByte){
  void *pRet = 0;
  if( *pRc==SQLITE_OK ){
    pRet = sqlite3_malloc(nByte);
    pRet = sqlite3_malloc64(nByte);
    if( pRet==0 ){
      if( nByte>0 ) *pRc = SQLITE_NOMEM;
    }else{
      memset(pRet, 0, nByte);
      memset(pRet, 0, (size_t)nByte);
    }
  }
  return pRet;
}

/*
** Return a nul-terminated copy of the string indicated by pIn. If nIn

Changes to ext/fts5/fts5_config.c.

19
20
21
22
23
24
25
26

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

26
27
28
29
30
31
32
33







-
+







#define FTS5_DEFAULT_PAGE_SIZE   4050
#define FTS5_DEFAULT_AUTOMERGE      4
#define FTS5_DEFAULT_USERMERGE      4
#define FTS5_DEFAULT_CRISISMERGE   16
#define FTS5_DEFAULT_HASHSIZE    (1024*1024)

/* Maximum allowed page size */
#define FTS5_MAX_PAGE_SIZE (128*1024)
#define FTS5_MAX_PAGE_SIZE (64*1024)

static int fts5_iswhitespace(char x){
  return (x==' ');
}

static int fts5_isopenquote(char x){
  return (x=='"' || x=='\'' || x=='[' || x=='`');
146
147
148
149
150
151
152
153

154
155
156
157
158
159
160
146
147
148
149
150
151
152

153
154
155
156
157
158
159
160







-
+







  int iOut = 0;
  q = z[0];

  /* Set stack variable q to the close-quote character */
  assert( q=='[' || q=='\'' || q=='"' || q=='`' );
  if( q=='[' ) q = ']';  

  while( ALWAYS(z[iIn]) ){
  while( z[iIn] ){
    if( z[iIn]==q ){
      if( z[iIn+1]!=q ){
        /* Character iIn was the close quote. */
        iIn++;
        break;
      }else{
        /* Character iIn and iIn+1 form an escaped quote character. Skip
291
292
293
294
295
296
297
298

299
300
301
302
303
304
305
291
292
293
294
295
296
297

298
299
300
301
302
303
304
305







-
+







    }
    assert( pConfig->nPrefix<=FTS5_MAX_PREFIX_INDEXES );
    return rc;
  }

  if( sqlite3_strnicmp("tokenize", zCmd, nCmd)==0 ){
    const char *p = (const char*)zArg;
    int nArg = (int)strlen(zArg) + 1;
    sqlite3_int64 nArg = strlen(zArg) + 1;
    char **azArg = sqlite3Fts5MallocZero(&rc, sizeof(char*) * nArg);
    char *pDel = sqlite3Fts5MallocZero(&rc, nArg * 2);
    char *pSpace = pDel;

    if( azArg && pSpace ){
      if( pConfig->pTok ){
        *pzErr = sqlite3_mprintf("multiple tokenize=... directives");
321
322
323
324
325
326
327
328

329
330
331
332
333
334
335
321
322
323
324
325
326
327

328
329
330
331
332
333
334
335







-
+







          }
        }
        if( p==0 ){
          *pzErr = sqlite3_mprintf("parse error in tokenize directive");
          rc = SQLITE_ERROR;
        }else{
          rc = sqlite3Fts5GetTokenizer(pGlobal, 
              (const char**)azArg, nArg, &pConfig->pTok, &pConfig->pTokApi,
              (const char**)azArg, (int)nArg, pConfig,
              pzErr
          );
        }
      }
    }

    sqlite3_free(azArg);
393
394
395
396
397
398
399
400

401
402
403
404
405
406
407
408
409
393
394
395
396
397
398
399

400


401
402
403
404
405
406
407







-
+
-
-







/*
** Allocate an instance of the default tokenizer ("simple") at 
** Fts5Config.pTokenizer. Return SQLITE_OK if successful, or an SQLite error
** code if an error occurs.
*/
static int fts5ConfigDefaultTokenizer(Fts5Global *pGlobal, Fts5Config *pConfig){
  assert( pConfig->pTok==0 && pConfig->pTokApi==0 );
  return sqlite3Fts5GetTokenizer(
  return sqlite3Fts5GetTokenizer(pGlobal, 0, 0, pConfig, 0);
      pGlobal, 0, 0, &pConfig->pTok, &pConfig->pTokApi, 0
  );
}

/*
** Gobble up the first bareword or quoted word from the input buffer zIn.
** Return a pointer to the character immediately following the last in
** the gobbled word if successful, or a NULL pointer otherwise (failed
** to find close-quote character).
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
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







-
-
+
+








-
+







  int *pRc,                       /* IN/OUT: Error code */
  const char *zIn,                /* Buffer to gobble string/bareword from */
  char **pzOut,                   /* OUT: malloc'd buffer containing str/bw */
  int *pbQuoted                   /* OUT: Set to true if dequoting required */
){
  const char *zRet = 0;

  int nIn = (int)strlen(zIn);
  char *zOut = sqlite3_malloc(nIn+1);
  sqlite3_int64 nIn = strlen(zIn);
  char *zOut = sqlite3_malloc64(nIn+1);

  assert( *pRc==SQLITE_OK );
  *pbQuoted = 0;
  *pzOut = 0;

  if( zOut==0 ){
    *pRc = SQLITE_NOMEM;
  }else{
    memcpy(zOut, zIn, nIn+1);
    memcpy(zOut, zIn, (size_t)(nIn+1));
    if( fts5_isopenquote(zOut[0]) ){
      int ii = fts5Dequote(zOut);
      zRet = &zIn[ii];
      *pbQuoted = 1;
    }else{
      zRet = fts5ConfigSkipBareword(zIn);
      if( zRet ){
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
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







-
+









-
+







  const char **azArg,             /* Array of nArg CREATE VIRTUAL TABLE args */
  Fts5Config **ppOut,             /* OUT: Results of parse */
  char **pzErr                    /* OUT: Error message */
){
  int rc = SQLITE_OK;             /* Return code */
  Fts5Config *pRet;               /* New object to return */
  int i;
  int nByte;
  sqlite3_int64 nByte;

  *ppOut = pRet = (Fts5Config*)sqlite3_malloc(sizeof(Fts5Config));
  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
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
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







+
















-
+
+
+
+
+







    int bOption = 0;
    int bMustBeCol = 0;

    z = fts5ConfigGobbleWord(&rc, zOrig, &zOne, &bMustBeCol);
    z = fts5ConfigSkipWhitespace(z);
    if( z && *z=='=' ){
      bOption = 1;
      assert( zOne!=0 );
      z++;
      if( bMustBeCol ) z = 0;
    }
    z = fts5ConfigSkipWhitespace(z);
    if( z && z[0] ){
      int bDummy;
      z = fts5ConfigGobbleWord(&rc, z, &zTwo, &bDummy);
      if( z && z[0] ) z = 0;
    }

    if( rc==SQLITE_OK ){
      if( z==0 ){
        *pzErr = sqlite3_mprintf("parse error in \"%s\"", zOrig);
        rc = SQLITE_ERROR;
      }else{
        if( bOption ){
          rc = fts5ConfigParseSpecial(pGlobal, pRet, zOne, zTwo?zTwo:"", pzErr);
          rc = fts5ConfigParseSpecial(pGlobal, pRet, 
            ALWAYS(zOne)?zOne:"",
            zTwo?zTwo:"",
            pzErr
          );
        }else{
          rc = fts5ConfigParseColumn(pRet, zOne, zTwo, pzErr);
          zOne = 0;
        }
      }
    }

679
680
681
682
683
684
685
686

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

689
690
691
692
693
694
695
696







-
+







  );

  assert( zSql || rc==SQLITE_NOMEM );
  if( zSql ){
    rc = sqlite3_declare_vtab(pConfig->db, zSql);
    sqlite3_free(zSql);
  }
  
 
  return rc;
}

/*
** Tokenize the text passed via the second and third arguments.
**
** The callback is invoked once for each token in the input text. The
824
825
826
827
828
829
830
831

832
833
834
835
836
837
838
827
828
829
830
831
832
833

834
835
836
837
838
839
840
841







-
+







  int rc = SQLITE_OK;

  if( 0==sqlite3_stricmp(zKey, "pgsz") ){
    int pgsz = 0;
    if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){
      pgsz = sqlite3_value_int(pVal);
    }
    if( pgsz<=0 || pgsz>FTS5_MAX_PAGE_SIZE ){
    if( pgsz<32 || pgsz>FTS5_MAX_PAGE_SIZE ){
      *pbBadkey = 1;
    }else{
      pConfig->pgsz = pgsz;
    }
  }

  else if( 0==sqlite3_stricmp(zKey, "hashsize") ){
877
878
879
880
881
882
883

884
885
886
887
888
889
890
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894







+







    if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){
      nCrisisMerge = sqlite3_value_int(pVal);
    }
    if( nCrisisMerge<0 ){
      *pbBadkey = 1;
    }else{
      if( nCrisisMerge<=1 ) nCrisisMerge = FTS5_DEFAULT_CRISISMERGE;
      if( nCrisisMerge>=FTS5_MAX_SEGMENT ) nCrisisMerge = FTS5_MAX_SEGMENT-1;
      pConfig->nCrisisMerge = nCrisisMerge;
    }
  }

  else if( 0==sqlite3_stricmp(zKey, "rank") ){
    const char *zIn = (const char*)sqlite3_value_text(pVal);
    char *zRank;

Changes to ext/fts5/fts5_expr.c.

124
125
126
127
128
129
130

131
132
133
134
135
136

137
138
139
140
141
142
143
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145







+






+







struct Fts5Parse {
  Fts5Config *pConfig;
  char *zErr;
  int rc;
  int nPhrase;                    /* Size of apPhrase array */
  Fts5ExprPhrase **apPhrase;      /* Array of all phrases */
  Fts5ExprNode *pExpr;            /* Result of a successful parse */
  int bPhraseToAnd;               /* Convert "a+b" to "a AND b" */
};

void sqlite3Fts5ParseError(Fts5Parse *pParse, const char *zFmt, ...){
  va_list ap;
  va_start(ap, zFmt);
  if( pParse->rc==SQLITE_OK ){
    assert( pParse->zErr==0 );
    pParse->zErr = sqlite3_vmprintf(zFmt, ap);
    pParse->rc = SQLITE_ERROR;
  }
  va_end(ap);
}

static int fts5ExprIsspace(char t){
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
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







-
+




+















+







    }
  }

  *pz = &pToken->p[pToken->n];
  return tok;
}

static void *fts5ParseAlloc(u64 t){ return sqlite3_malloc((int)t); }
static void *fts5ParseAlloc(u64 t){ return sqlite3_malloc64((sqlite3_int64)t);}
static void fts5ParseFree(void *p){ sqlite3_free(p); }

int sqlite3Fts5ExprNew(
  Fts5Config *pConfig,            /* FTS5 Configuration */
  int bPhraseToAnd,
  int iCol,
  const char *zExpr,              /* Expression text */
  Fts5Expr **ppNew, 
  char **pzErr
){
  Fts5Parse sParse;
  Fts5Token token;
  const char *z = zExpr;
  int t;                          /* Next token type */
  void *pEngine;
  Fts5Expr *pNew;

  *ppNew = 0;
  *pzErr = 0;
  memset(&sParse, 0, sizeof(sParse));
  sParse.bPhraseToAnd = bPhraseToAnd;
  pEngine = sqlite3Fts5ParserAlloc(fts5ParseAlloc);
  if( pEngine==0 ){ return SQLITE_NOMEM; }
  sParse.pConfig = pConfig;

  do {
    t = fts5ExprGetToken(&sParse, &z, &token);
    sqlite3Fts5Parser(pEngine, t, token, &sParse);
269
270
271
272
273
274
275

276
277
278
279
280
281
282
283
284
285











































































286
287
288
289
290
291
292
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







+










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







      }else{
        pNew->pRoot = sParse.pExpr;
      }
      pNew->pIndex = 0;
      pNew->pConfig = pConfig;
      pNew->apExprPhrase = sParse.apPhrase;
      pNew->nPhrase = sParse.nPhrase;
      pNew->bDesc = 0;
      sParse.apPhrase = 0;
    }
  }else{
    sqlite3Fts5ParseNodeFree(sParse.pExpr);
  }

  sqlite3_free(sParse.apPhrase);
  *pzErr = sParse.zErr;
  return sParse.rc;
}

/*
** This function is only called when using the special 'trigram' tokenizer.
** Argument zText contains the text of a LIKE or GLOB pattern matched
** against column iCol. This function creates and compiles an FTS5 MATCH
** expression that will match a superset of the rows matched by the LIKE or
** GLOB. If successful, SQLITE_OK is returned. Otherwise, an SQLite error
** code.
*/
int sqlite3Fts5ExprPattern(
  Fts5Config *pConfig, int bGlob, int iCol, const char *zText, Fts5Expr **pp
){
  i64 nText = strlen(zText);
  char *zExpr = (char*)sqlite3_malloc64(nText*4 + 1);
  int rc = SQLITE_OK;

  if( zExpr==0 ){
    rc = SQLITE_NOMEM;
  }else{
    char aSpec[3];
    int iOut = 0;
    int i = 0;
    int iFirst = 0;

    if( bGlob==0 ){
      aSpec[0] = '_';
      aSpec[1] = '%';
      aSpec[2] = 0;
    }else{
      aSpec[0] = '*';
      aSpec[1] = '?';
      aSpec[2] = '[';
    }

    while( i<=nText ){
      if( i==nText 
       || zText[i]==aSpec[0] || zText[i]==aSpec[1] || zText[i]==aSpec[2] 
      ){
        if( i-iFirst>=3 ){
          int jj;
          zExpr[iOut++] = '"';
          for(jj=iFirst; jj<i; jj++){
            zExpr[iOut++] = zText[jj];
            if( zText[jj]=='"' ) zExpr[iOut++] = '"';
          }
          zExpr[iOut++] = '"';
          zExpr[iOut++] = ' ';
        }
        if( zText[i]==aSpec[2] ){
          i += 2;
          if( zText[i-1]=='^' ) i++;
          while( i<nText && zText[i]!=']' ) i++;
        }
        iFirst = i+1;
      }
      i++;
    }
    if( iOut>0 ){
      int bAnd = 0;
      if( pConfig->eDetail!=FTS5_DETAIL_FULL ){
        bAnd = 1;
        if( pConfig->eDetail==FTS5_DETAIL_NONE ){
          iCol = pConfig->nCol;
        }
      }
      zExpr[iOut] = '\0';
      rc = sqlite3Fts5ExprNew(pConfig, bAnd, iCol, zExpr, pp,pConfig->pzErrmsg);
    }else{
      *pp = 0;
    }
    sqlite3_free(zExpr);
  }

  return rc;
}

/*
** Free the expression node object passed as the only argument.
*/
void sqlite3Fts5ParseNodeFree(Fts5ExprNode *p){
  if( p ){
    int i;
304
305
306
307
308
309
310




































311
312
313
314
315
316
317
318
319
320

321
322
323
324
325
326
327
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







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










+







void sqlite3Fts5ExprFree(Fts5Expr *p){
  if( p ){
    sqlite3Fts5ParseNodeFree(p->pRoot);
    sqlite3_free(p->apExprPhrase);
    sqlite3_free(p);
  }
}

int sqlite3Fts5ExprAnd(Fts5Expr **pp1, Fts5Expr *p2){
  Fts5Parse sParse;
  memset(&sParse, 0, sizeof(sParse));

  if( *pp1 ){
    Fts5Expr *p1 = *pp1;
    int nPhrase = p1->nPhrase + p2->nPhrase;

    p1->pRoot = sqlite3Fts5ParseNode(&sParse, FTS5_AND, p1->pRoot, p2->pRoot,0);
    p2->pRoot = 0;

    if( sParse.rc==SQLITE_OK ){
      Fts5ExprPhrase **ap = (Fts5ExprPhrase**)sqlite3_realloc(
          p1->apExprPhrase, nPhrase * sizeof(Fts5ExprPhrase*)
      );
      if( ap==0 ){
        sParse.rc = SQLITE_NOMEM;
      }else{
        int i;
        memmove(&ap[p2->nPhrase], ap, p1->nPhrase*sizeof(Fts5ExprPhrase*));
        for(i=0; i<p2->nPhrase; i++){
          ap[i] = p2->apExprPhrase[i];
        }
        p1->nPhrase = nPhrase;
        p1->apExprPhrase = ap;
      }
    }
    sqlite3_free(p2->apExprPhrase);
    sqlite3_free(p2);
  }else{
    *pp1 = p2;
  }

  return sParse.rc;
}

/*
** Argument pTerm must be a synonym iterator. Return the current rowid
** that it points to.
*/
static i64 fts5ExprSynonymRowid(Fts5ExprTerm *pTerm, int bDesc, int *pbEof){
  i64 iRet = 0;
  int bRetValid = 0;
  Fts5ExprTerm *p;

  assert( pTerm );
  assert( pTerm->pSynonym );
  assert( bDesc==0 || bDesc==1 );
  for(p=pTerm; p; p=p->pSynonym){
    if( 0==sqlite3Fts5IterEof(p->pIter) ){
      i64 iRowid = p->pIter->iRowid;
      if( bRetValid==0 || (bDesc!=(iRowid<iRet)) ){
        iRet = iRowid;
352
353
354
355
356
357
358
359
360


361
362
363
364
365
366
367
469
470
471
472
473
474
475


476
477
478
479
480
481
482
483
484







-
-
+
+








  assert( pTerm->pSynonym );
  for(p=pTerm; p; p=p->pSynonym){
    Fts5IndexIter *pIter = p->pIter;
    if( sqlite3Fts5IterEof(pIter)==0 && pIter->iRowid==iRowid ){
      if( pIter->nData==0 ) continue;
      if( nIter==nAlloc ){
        int nByte = sizeof(Fts5PoslistReader) * nAlloc * 2;
        Fts5PoslistReader *aNew = (Fts5PoslistReader*)sqlite3_malloc(nByte);
        sqlite3_int64 nByte = sizeof(Fts5PoslistReader) * nAlloc * 2;
        Fts5PoslistReader *aNew = (Fts5PoslistReader*)sqlite3_malloc64(nByte);
        if( aNew==0 ){
          rc = SQLITE_NOMEM;
          goto synonym_poslist_out;
        }
        memcpy(aNew, aIter, sizeof(Fts5PoslistReader) * nIter);
        nAlloc = nAlloc*2;
        if( aIter!=aStatic ) sqlite3_free(aIter);
433
434
435
436
437
438
439
440
441


442
443
444
445
446
447
448
550
551
552
553
554
555
556


557
558
559
560
561
562
563
564
565







-
-
+
+







  int bFirst = pPhrase->aTerm[0].bFirst;
  
  fts5BufferZero(&pPhrase->poslist);

  /* If the aStatic[] array is not large enough, allocate a large array
  ** using sqlite3_malloc(). This approach could be improved upon. */
  if( pPhrase->nTerm>ArraySize(aStatic) ){
    int nByte = sizeof(Fts5PoslistReader) * pPhrase->nTerm;
    aIter = (Fts5PoslistReader*)sqlite3_malloc(nByte);
    sqlite3_int64 nByte = sizeof(Fts5PoslistReader) * pPhrase->nTerm;
    aIter = (Fts5PoslistReader*)sqlite3_malloc64(nByte);
    if( !aIter ) return SQLITE_NOMEM;
  }
  memset(aIter, 0, sizeof(Fts5PoslistReader) * pPhrase->nTerm);

  /* Initialize a term iterator for each term in the phrase */
  for(i=0; i<pPhrase->nTerm; i++){
    Fts5ExprTerm *pTerm = &pPhrase->aTerm[i];
568
569
570
571
572
573
574
575

576
577
578
579
580
581
582
685
686
687
688
689
690
691

692
693
694
695
696
697
698
699







-
+







  int bMatch;

  assert( pNear->nPhrase>1 );

  /* If the aStatic[] array is not large enough, allocate a large array
  ** using sqlite3_malloc(). This approach could be improved upon. */
  if( pNear->nPhrase>ArraySize(aStatic) ){
    int nByte = sizeof(Fts5NearTrimmer) * pNear->nPhrase;
    sqlite3_int64 nByte = sizeof(Fts5NearTrimmer) * pNear->nPhrase;
    a = (Fts5NearTrimmer*)sqlite3Fts5MallocZero(&rc, nByte);
  }else{
    memset(aStatic, 0, sizeof(aStatic));
  }
  if( rc!=SQLITE_OK ){
    *pRc = rc;
    return 0;
1381
1382
1383
1384
1385
1386
1387
1388
1389


1390
1391
1392
1393
1394
1395
1396
1498
1499
1500
1501
1502
1503
1504


1505
1506
1507
1508
1509
1510
1511
1512
1513







-
-
+
+







   && 0==pRoot->bEof 
   && fts5RowidCmp(p, pRoot->iRowid, iFirst)<0 
  ){
    rc = fts5ExprNodeNext(p, pRoot, 1, iFirst);
  }

  /* If the iterator is not at a real match, skip forward until it is. */
  while( pRoot->bNomatch ){
    assert( pRoot->bEof==0 && rc==SQLITE_OK );
  while( pRoot->bNomatch && rc==SQLITE_OK ){
    assert( pRoot->bEof==0 );
    rc = fts5ExprNodeNext(p, pRoot, 0, 0);
  }
  return rc;
}

/*
** Move to the next document 
1477
1478
1479
1480
1481
1482
1483

1484
1485


1486
1487
1488
1489

1490
1491
1492
1493

1494

1495

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



1511
1512
1513
1514
1515
1516
1517
1594
1595
1596
1597
1598
1599
1600
1601


1602
1603
1604
1605
1606

1607
1608
1609
1610

1611
1612
1613

1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639







+
-
-
+
+



-
+



-
+

+
-
+















+
+
+







  Fts5ExprNearset *pRet = 0;

  if( pParse->rc==SQLITE_OK ){
    if( pPhrase==0 ){
      return pNear;
    }
    if( pNear==0 ){
      sqlite3_int64 nByte;
      int nByte = sizeof(Fts5ExprNearset) + SZALLOC * sizeof(Fts5ExprPhrase*);
      pRet = sqlite3_malloc(nByte);
      nByte = sizeof(Fts5ExprNearset) + SZALLOC * sizeof(Fts5ExprPhrase*);
      pRet = sqlite3_malloc64(nByte);
      if( pRet==0 ){
        pParse->rc = SQLITE_NOMEM;
      }else{
        memset(pRet, 0, nByte);
        memset(pRet, 0, (size_t)nByte);
      }
    }else if( (pNear->nPhrase % SZALLOC)==0 ){
      int nNew = pNear->nPhrase + SZALLOC;
      int nByte = sizeof(Fts5ExprNearset) + nNew * sizeof(Fts5ExprPhrase*);
      sqlite3_int64 nByte;

      nByte = sizeof(Fts5ExprNearset) + nNew * sizeof(Fts5ExprPhrase*);
      pRet = (Fts5ExprNearset*)sqlite3_realloc(pNear, nByte);
      pRet = (Fts5ExprNearset*)sqlite3_realloc64(pNear, nByte);
      if( pRet==0 ){
        pParse->rc = SQLITE_NOMEM;
      }
    }else{
      pRet = pNear;
    }
  }

  if( pRet==0 ){
    assert( pParse->rc!=SQLITE_OK );
    sqlite3Fts5ParseNearsetFree(pNear);
    sqlite3Fts5ParsePhraseFree(pPhrase);
  }else{
    if( pRet->nPhrase>0 ){
      Fts5ExprPhrase *pLast = pRet->apPhrase[pRet->nPhrase-1];
      assert( pParse!=0 );
      assert( pParse->apPhrase!=0 );
      assert( pParse->nPhrase>=2 );
      assert( pLast==pParse->apPhrase[pParse->nPhrase-2] );
      if( pPhrase->nTerm==0 ){
        fts5ExprPhraseFree(pPhrase);
        pRet->nPhrase--;
        pParse->nPhrase--;
        pPhrase = pLast;
      }else if( pLast->nTerm==0 ){
1552
1553
1554
1555
1556
1557
1558
1559
1560


1561
1562
1563
1564

1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576

1577
1578
1579
1580
1581
1582
1583
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







-
-
+
+



-
+











-
+








  /* If an error has already occurred, this is a no-op */
  if( pCtx->rc!=SQLITE_OK ) return pCtx->rc;
  if( nToken>FTS5_MAX_TOKEN_SIZE ) nToken = FTS5_MAX_TOKEN_SIZE;

  if( pPhrase && pPhrase->nTerm>0 && (tflags & FTS5_TOKEN_COLOCATED) ){
    Fts5ExprTerm *pSyn;
    int nByte = sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer) + nToken+1;
    pSyn = (Fts5ExprTerm*)sqlite3_malloc(nByte);
    sqlite3_int64 nByte = sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer) + nToken+1;
    pSyn = (Fts5ExprTerm*)sqlite3_malloc64(nByte);
    if( pSyn==0 ){
      rc = SQLITE_NOMEM;
    }else{
      memset(pSyn, 0, nByte);
      memset(pSyn, 0, (size_t)nByte);
      pSyn->zTerm = ((char*)pSyn) + sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer);
      memcpy(pSyn->zTerm, pToken, nToken);
      pSyn->pSynonym = pPhrase->aTerm[pPhrase->nTerm-1].pSynonym;
      pPhrase->aTerm[pPhrase->nTerm-1].pSynonym = pSyn;
    }
  }else{
    Fts5ExprTerm *pTerm;
    if( pPhrase==0 || (pPhrase->nTerm % SZALLOC)==0 ){
      Fts5ExprPhrase *pNew;
      int nNew = SZALLOC + (pPhrase ? pPhrase->nTerm : 0);

      pNew = (Fts5ExprPhrase*)sqlite3_realloc(pPhrase, 
      pNew = (Fts5ExprPhrase*)sqlite3_realloc64(pPhrase, 
          sizeof(Fts5ExprPhrase) + sizeof(Fts5ExprTerm) * nNew
      );
      if( pNew==0 ){
        rc = SQLITE_NOMEM;
      }else{
        if( pPhrase==0 ) memset(pNew, 0, sizeof(Fts5ExprPhrase));
        pCtx->pPhrase = pPhrase = pNew;
1618
1619
1620
1621
1622
1623
1624














1625
1626
1627
1628
1629
1630
1631
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767







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







  }
}

void sqlite3Fts5ParseFinished(Fts5Parse *pParse, Fts5ExprNode *p){
  assert( pParse->pExpr==0 );
  pParse->pExpr = p;
}

static int parseGrowPhraseArray(Fts5Parse *pParse){
  if( (pParse->nPhrase % 8)==0 ){
    sqlite3_int64 nByte = sizeof(Fts5ExprPhrase*) * (pParse->nPhrase + 8);
    Fts5ExprPhrase **apNew;
    apNew = (Fts5ExprPhrase**)sqlite3_realloc64(pParse->apPhrase, nByte);
    if( apNew==0 ){
      pParse->rc = SQLITE_NOMEM;
      return SQLITE_NOMEM;
    }
    pParse->apPhrase = apNew;
  }
  return SQLITE_OK;
}

/*
** This function is called by the parser to process a string token. The
** string may or may not be quoted. In any case it is tokenized and a
** phrase object consisting of all tokens returned.
*/
Fts5ExprPhrase *sqlite3Fts5ParseTerm(
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663

1664
1665
1666
1667
1668


1669
1670
1671
1672
1673
1674
1675
1676
1677
1790
1791
1792
1793
1794
1795
1796



1797





1798
1799


1800
1801
1802
1803
1804
1805
1806







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







  if( rc || (rc = sCtx.rc) ){
    pParse->rc = rc;
    fts5ExprPhraseFree(sCtx.pPhrase);
    sCtx.pPhrase = 0;
  }else{

    if( pAppend==0 ){
      if( (pParse->nPhrase % 8)==0 ){
        int nByte = sizeof(Fts5ExprPhrase*) * (pParse->nPhrase + 8);
        Fts5ExprPhrase **apNew;
      if( parseGrowPhraseArray(pParse) ){
        apNew = (Fts5ExprPhrase**)sqlite3_realloc(pParse->apPhrase, nByte);
        if( apNew==0 ){
          pParse->rc = SQLITE_NOMEM;
          fts5ExprPhraseFree(sCtx.pPhrase);
          return 0;
        fts5ExprPhraseFree(sCtx.pPhrase);
        return 0;
        }
        pParse->apPhrase = apNew;
      }
      pParse->nPhrase++;
    }

    if( sCtx.pPhrase==0 ){
      /* This happens when parsing a token or quoted phrase that contains
      ** no token characters at all. (e.g ... MATCH '""'). */
1712
1713
1714
1715
1716
1717
1718


1719
1720


1721
1722

1723
1724
1725
1726
1727
1728
1729
1841
1842
1843
1844
1845
1846
1847
1848
1849


1850
1851
1852

1853
1854
1855
1856
1857
1858
1859
1860







+
+
-
-
+
+

-
+







  if( rc==SQLITE_OK ){
    pNew->pRoot->pNear = (Fts5ExprNearset*)sqlite3Fts5MallocZero(&rc, 
        sizeof(Fts5ExprNearset) + sizeof(Fts5ExprPhrase*));
  }
  if( rc==SQLITE_OK ){
    Fts5Colset *pColsetOrig = pOrig->pNode->pNear->pColset;
    if( pColsetOrig ){
      sqlite3_int64 nByte;
      Fts5Colset *pColset;
      int nByte = sizeof(Fts5Colset) + (pColsetOrig->nCol-1) * sizeof(int);
      Fts5Colset *pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&rc, nByte);
      nByte = sizeof(Fts5Colset) + (pColsetOrig->nCol-1) * sizeof(int);
      pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&rc, nByte);
      if( pColset ){ 
        memcpy(pColset, pColsetOrig, nByte);
        memcpy(pColset, pColsetOrig, (size_t)nByte);
      }
      pNew->pRoot->pNear->pColset = pColset;
    }
  }

  if( pOrig->nTerm ){
    int i;                          /* Used to iterate through phrase terms */
1743
1744
1745
1746
1747
1748
1749
1750

1751
1752
1753
1754
1755
1756
1757
1874
1875
1876
1877
1878
1879
1880

1881
1882
1883
1884
1885
1886
1887
1888







-
+







    }
  }else{
    /* This happens when parsing a token or quoted phrase that contains
    ** no token characters at all. (e.g ... MATCH '""'). */
    sCtx.pPhrase = sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprPhrase));
  }

  if( rc==SQLITE_OK ){
  if( rc==SQLITE_OK && ALWAYS(sCtx.pPhrase) ){
    /* All the allocations succeeded. Put the expression object together. */
    pNew->pIndex = pExpr->pIndex;
    pNew->pConfig = pExpr->pConfig;
    pNew->nPhrase = 1;
    pNew->apExprPhrase[0] = sCtx.pPhrase;
    pNew->pRoot->pNear->apPhrase[0] = sCtx.pPhrase;
    pNew->pRoot->pNear->nPhrase = 1;
1833
1834
1835
1836
1837
1838
1839
1840

1841
1842
1843
1844
1845
1846
1847
1964
1965
1966
1967
1968
1969
1970

1971
1972
1973
1974
1975
1976
1977
1978







-
+







){
  int nCol = p ? p->nCol : 0;     /* Num. columns already in colset object */
  Fts5Colset *pNew;               /* New colset object to return */

  assert( pParse->rc==SQLITE_OK );
  assert( iCol>=0 && iCol<pParse->pConfig->nCol );

  pNew = sqlite3_realloc(p, sizeof(Fts5Colset) + sizeof(int)*nCol);
  pNew = sqlite3_realloc64(p, sizeof(Fts5Colset) + sizeof(int)*nCol);
  if( pNew==0 ){
    pParse->rc = SQLITE_NOMEM;
  }else{
    int *aiCol = pNew->aiCol;
    int i, j;
    for(i=0; i<nCol; i++){
      if( aiCol[i]==iCol ) return pNew;
1929
1930
1931
1932
1933
1934
1935
1936

1937
1938
1939

1940
1941
1942
1943
1944
1945
1946
2060
2061
2062
2063
2064
2065
2066

2067
2068
2069

2070
2071
2072
2073
2074
2075
2076
2077







-
+


-
+







** Otherwise, a copy of (*pOrig) is made into memory obtained from
** sqlite3Fts5MallocZero() and a pointer to it returned. If the allocation
** fails, (*pRc) is set to SQLITE_NOMEM and NULL is returned.
*/
static Fts5Colset *fts5CloneColset(int *pRc, Fts5Colset *pOrig){
  Fts5Colset *pRet;
  if( pOrig ){
    int nByte = sizeof(Fts5Colset) + (pOrig->nCol-1) * sizeof(int);
    sqlite3_int64 nByte = sizeof(Fts5Colset) + (pOrig->nCol-1) * sizeof(int);
    pRet = (Fts5Colset*)sqlite3Fts5MallocZero(pRc, nByte);
    if( pRet ){ 
      memcpy(pRet, pOrig, nByte);
      memcpy(pRet, pOrig, (size_t)nByte);
    }
  }else{
    pRet = 0;
  }
  return pRet;
}

2014
2015
2016
2017
2018
2019
2020
2021
2022
2023


2024
2025
2026
2027
2028
2029
2030
2145
2146
2147
2148
2149
2150
2151



2152
2153
2154
2155
2156
2157
2158
2159
2160







-
-
-
+
+







void sqlite3Fts5ParseSetColset(
  Fts5Parse *pParse, 
  Fts5ExprNode *pExpr, 
  Fts5Colset *pColset 
){
  Fts5Colset *pFree = pColset;
  if( pParse->pConfig->eDetail==FTS5_DETAIL_NONE ){
    pParse->rc = SQLITE_ERROR;
    pParse->zErr = sqlite3_mprintf(
      "fts5: column queries are not supported (detail=none)"
    sqlite3Fts5ParseError(pParse, 
        "fts5: column queries are not supported (detail=none)"
    );
  }else{
    fts5ParseSetColset(pParse, pExpr, pColset, &pFree);
  }
  sqlite3_free(pFree);
}

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
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
2197
2198
2199
2200
2201
2202
2203
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
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280

2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295







2296
2297
2298
2299
2300
2301
2302
2303


2304
2305
2306













2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320






2321
2322
2323
2324
2325
2326














2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345







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
















-
+








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

-
-
+
+

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

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







    memcpy(&p->apChild[p->nChild], pSub->apChild, nByte);
    p->nChild += pSub->nChild;
    sqlite3_free(pSub);
  }else{
    p->apChild[p->nChild++] = pSub;
  }
}

/*
** This function is used when parsing LIKE or GLOB patterns against
** trigram indexes that specify either detail=column or detail=none.
** It converts a phrase:
**
**     abc + def + ghi
**
** into an AND tree:
**
**     abc AND def AND ghi
*/
static Fts5ExprNode *fts5ParsePhraseToAnd(
  Fts5Parse *pParse, 
  Fts5ExprNearset *pNear
){
  int nTerm = pNear->apPhrase[0]->nTerm;
  int ii;
  int nByte;
  Fts5ExprNode *pRet;

  assert( pNear->nPhrase==1 );
  assert( pParse->bPhraseToAnd );

  nByte = sizeof(Fts5ExprNode) + nTerm*sizeof(Fts5ExprNode*);
  pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
  if( pRet ){
    pRet->eType = FTS5_AND;
    pRet->nChild = nTerm;
    fts5ExprAssignXNext(pRet);
    pParse->nPhrase--;
    for(ii=0; ii<nTerm; ii++){
      Fts5ExprPhrase *pPhrase = (Fts5ExprPhrase*)sqlite3Fts5MallocZero(
          &pParse->rc, sizeof(Fts5ExprPhrase)
      );
      if( pPhrase ){
        if( parseGrowPhraseArray(pParse) ){
          fts5ExprPhraseFree(pPhrase);
        }else{
          pParse->apPhrase[pParse->nPhrase++] = pPhrase;
          pPhrase->nTerm = 1;
          pPhrase->aTerm[0].zTerm = sqlite3Fts5Strndup(
              &pParse->rc, pNear->apPhrase[0]->aTerm[ii].zTerm, -1
          );
          pRet->apChild[ii] = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 
              0, 0, sqlite3Fts5ParseNearset(pParse, 0, pPhrase)
          );
        }
      }
    }
  
    if( pParse->rc ){
      sqlite3Fts5ParseNodeFree(pRet);
      pRet = 0;
    }else{
      sqlite3Fts5ParseNearsetFree(pNear);
    }
  }

  return pRet;
}

/*
** Allocate and return a new expression object. If anything goes wrong (i.e.
** OOM error), leave an error code in pParse and return NULL.
*/
Fts5ExprNode *sqlite3Fts5ParseNode(
  Fts5Parse *pParse,              /* Parse context */
  int eType,                      /* FTS5_STRING, AND, OR or NOT */
  Fts5ExprNode *pLeft,            /* Left hand child expression */
  Fts5ExprNode *pRight,           /* Right hand child expression */
  Fts5ExprNearset *pNear          /* For STRING expressions, the near cluster */
){
  Fts5ExprNode *pRet = 0;

  if( pParse->rc==SQLITE_OK ){
    int nChild = 0;               /* Number of children of returned node */
    int nByte;                    /* Bytes of space to allocate for this node */
    sqlite3_int64 nByte;          /* Bytes of space to allocate for this node */
 
    assert( (eType!=FTS5_STRING && !pNear)
         || (eType==FTS5_STRING && !pLeft && !pRight)
    );
    if( eType==FTS5_STRING && pNear==0 ) return 0;
    if( eType!=FTS5_STRING && pLeft==0 ) return pRight;
    if( eType!=FTS5_STRING && pRight==0 ) return pLeft;

    if( eType==FTS5_STRING 
     && pParse->bPhraseToAnd 
     && pNear->apPhrase[0]->nTerm>1
    ){
      pRet = fts5ParsePhraseToAnd(pParse, pNear);
    }else{
    if( eType==FTS5_NOT ){
      nChild = 2;
    }else if( eType==FTS5_AND || eType==FTS5_OR ){
      nChild = 2;
      if( pLeft->eType==eType ) nChild += pLeft->nChild-1;
      if( pRight->eType==eType ) nChild += pRight->nChild-1;
    }
      if( eType==FTS5_NOT ){
        nChild = 2;
      }else if( eType==FTS5_AND || eType==FTS5_OR ){
        nChild = 2;
        if( pLeft->eType==eType ) nChild += pLeft->nChild-1;
        if( pRight->eType==eType ) nChild += pRight->nChild-1;
      }

    nByte = sizeof(Fts5ExprNode) + sizeof(Fts5ExprNode*)*(nChild-1);
    pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
      nByte = sizeof(Fts5ExprNode) + sizeof(Fts5ExprNode*)*(nChild-1);
      pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);

    if( pRet ){
      pRet->eType = eType;
      pRet->pNear = pNear;
      fts5ExprAssignXNext(pRet);
      if( eType==FTS5_STRING ){
        int iPhrase;
        for(iPhrase=0; iPhrase<pNear->nPhrase; iPhrase++){
          pNear->apPhrase[iPhrase]->pNode = pRet;
          if( pNear->apPhrase[iPhrase]->nTerm==0 ){
            pRet->xNext = 0;
            pRet->eType = FTS5_EOF;
          }
        }
      if( pRet ){
        pRet->eType = eType;
        pRet->pNear = pNear;
        fts5ExprAssignXNext(pRet);
        if( eType==FTS5_STRING ){
          int iPhrase;
          for(iPhrase=0; iPhrase<pNear->nPhrase; iPhrase++){
            pNear->apPhrase[iPhrase]->pNode = pRet;
            if( pNear->apPhrase[iPhrase]->nTerm==0 ){
              pRet->xNext = 0;
              pRet->eType = FTS5_EOF;
            }
          }

        if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL ){
          Fts5ExprPhrase *pPhrase = pNear->apPhrase[0];
          if( pNear->nPhrase!=1 
           || pPhrase->nTerm>1
           || (pPhrase->nTerm>0 && pPhrase->aTerm[0].bFirst)
          ){
          if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL ){
            Fts5ExprPhrase *pPhrase = pNear->apPhrase[0];
            if( pNear->nPhrase!=1 
                || pPhrase->nTerm>1
                || (pPhrase->nTerm>0 && pPhrase->aTerm[0].bFirst)
              ){
            assert( pParse->rc==SQLITE_OK );
            pParse->rc = SQLITE_ERROR;
            assert( pParse->zErr==0 );
            pParse->zErr = sqlite3_mprintf(
                "fts5: %s queries are not supported (detail!=full)", 
                pNear->nPhrase==1 ? "phrase": "NEAR"
                );
            sqlite3_free(pRet);
            pRet = 0;
          }
        }
      }else{
        fts5ExprAddChildren(pRet, pLeft);
        fts5ExprAddChildren(pRet, pRight);
              sqlite3Fts5ParseError(pParse, 
                  "fts5: %s queries are not supported (detail!=full)", 
                  pNear->nPhrase==1 ? "phrase": "NEAR"
              );
              sqlite3_free(pRet);
              pRet = 0;
            }
          }
        }else{
          fts5ExprAddChildren(pRet, pLeft);
          fts5ExprAddChildren(pRet, pRight);
        }
      }
    }
  }

  if( pRet==0 ){
    assert( pParse->rc!=SQLITE_OK );
    sqlite3Fts5ParseNodeFree(pLeft);
2214
2215
2216
2217
2218
2219
2220

2221
2222

2223
2224
2225
2226
2227
2228
2229
2230

2231
2232
2233
2234
2235
2236
2237
2409
2410
2411
2412
2413
2414
2415
2416
2417

2418
2419
2420
2421
2422
2423
2424
2425

2426
2427
2428
2429
2430
2431
2432
2433







+

-
+







-
+







      pRet = sqlite3Fts5ParseNode(pParse, FTS5_AND, pLeft, pRight, 0);
    }
  }

  return pRet;
}

#ifdef SQLITE_TEST
static char *fts5ExprTermPrint(Fts5ExprTerm *pTerm){
  int nByte = 0;
  sqlite3_int64 nByte = 0;
  Fts5ExprTerm *p;
  char *zQuoted;

  /* Determine the maximum amount of space required. */
  for(p=pTerm; p; p=p->pSynonym){
    nByte += (int)strlen(pTerm->zTerm) * 2 + 3 + 2;
  }
  zQuoted = sqlite3_malloc(nByte);
  zQuoted = sqlite3_malloc64(nByte);

  if( zQuoted ){
    int i = 0;
    for(p=pTerm; p; p=p->pSynonym){
      char *zIn = p->zTerm;
      zQuoted[i++] = '"';
      while( *zIn ){
2357
2358
2359
2360
2361
2362
2363

2364
2365










2366
2367
2368
2369
2370
2371
2372
2553
2554
2555
2556
2557
2558
2559
2560


2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577







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







  }else
  if( pExpr->eType==FTS5_STRING || pExpr->eType==FTS5_TERM ){
    Fts5ExprNearset *pNear = pExpr->pNear;
    int i; 
    int iTerm;

    if( pNear->pColset ){
      int ii;
      int iCol = pNear->pColset->aiCol[0];
      zRet = fts5PrintfAppend(zRet, "%s : ", pConfig->azCol[iCol]);
      Fts5Colset *pColset = pNear->pColset;
      if( pColset->nCol>1 ) zRet = fts5PrintfAppend(zRet, "{");
      for(ii=0; ii<pColset->nCol; ii++){
        zRet = fts5PrintfAppend(zRet, "%s%s", 
            pConfig->azCol[pColset->aiCol[ii]], ii==pColset->nCol-1 ? "" : " "
        );
      }
      if( zRet ){
        zRet = fts5PrintfAppend(zRet, "%s : ", pColset->nCol>1 ? "}" : "");
      }
      if( zRet==0 ) return 0;
    }

    if( pNear->nPhrase>1 ){
      zRet = fts5PrintfAppend(zRet, "NEAR(");
      if( zRet==0 ) return 0;
    }
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
2493
2668
2669
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







-
+








-
+
+



+



-
+








  if( bTcl && nArg>1 ){
    zNearsetCmd = (const char*)sqlite3_value_text(apVal[1]);
    iArg = 2;
  }

  nConfig = 3 + (nArg-iArg);
  azConfig = (const char**)sqlite3_malloc(sizeof(char*) * nConfig);
  azConfig = (const char**)sqlite3_malloc64(sizeof(char*) * nConfig);
  if( azConfig==0 ){
    sqlite3_result_error_nomem(pCtx);
    return;
  }
  azConfig[0] = 0;
  azConfig[1] = "main";
  azConfig[2] = "tbl";
  for(i=3; iArg<nArg; iArg++){
    azConfig[i++] = (const char*)sqlite3_value_text(apVal[iArg]);
    const char *z = (const char*)sqlite3_value_text(apVal[iArg]);
    azConfig[i++] = (z ? z : "");
  }

  zExpr = (const char*)sqlite3_value_text(apVal[0]);
  if( zExpr==0 ) zExpr = "";

  rc = sqlite3Fts5ConfigParse(pGlobal, db, nConfig, azConfig, &pConfig, &zErr);
  if( rc==SQLITE_OK ){
    rc = sqlite3Fts5ExprNew(pConfig, pConfig->nCol, zExpr, &pExpr, &zErr);
    rc = sqlite3Fts5ExprNew(pConfig, 0, pConfig->nCol, zExpr, &pExpr, &zErr);
  }
  if( rc==SQLITE_OK ){
    char *zText;
    if( pExpr->pRoot->xNext==0 ){
      zText = sqlite3_mprintf("");
    }else if( bTcl ){
      zText = fts5ExprPrintTcl(pConfig, zNearsetCmd, pExpr->pRoot);
2549
2550
2551
2552
2553
2554
2555
2556

2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575

2576
2577
2578
2579
2580
2581

2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598




2599
2600
2601
2602
2603
2604
2605
2756
2757
2758
2759
2760
2761
2762

2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
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
2818







-
+



















+






+

















+
+
+
+







    return;
  }
  memset(aArr, 0, sizeof(aArr));
  sqlite3Fts5UnicodeCatParse("L*", aArr);
  sqlite3Fts5UnicodeCatParse("N*", aArr);
  sqlite3Fts5UnicodeCatParse("Co", aArr);
  iCode = sqlite3_value_int(apVal[0]);
  sqlite3_result_int(pCtx, aArr[sqlite3Fts5UnicodeCategory(iCode)]);
  sqlite3_result_int(pCtx, aArr[sqlite3Fts5UnicodeCategory((u32)iCode)]);
}

static void fts5ExprFold(
  sqlite3_context *pCtx,          /* Function call context */
  int nArg,                       /* Number of args */
  sqlite3_value **apVal           /* Function arguments */
){
  if( nArg!=1 && nArg!=2 ){
    sqlite3_result_error(pCtx, 
        "wrong number of arguments to function fts5_fold", -1
    );
  }else{
    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;
2642
2643
2644
2645
2646
2647
2648









2649
2650
2651

2652
2653
2654
2655
2656
2657
2658

2659
2660
2661
2662
2663
2664
2665
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872

2873
2874
2875
2876
2877
2878
2879

2880
2881
2882
2883
2884
2885
2886
2887







+
+
+
+
+
+
+
+
+


-
+






-
+








struct Fts5PoslistPopulator {
  Fts5PoslistWriter writer;
  int bOk;                        /* True if ok to populate */
  int bMiss;
};

/*
** Clear the position lists associated with all phrases in the expression
** passed as the first argument. Argument bLive is true if the expression
** might be pointing to a real entry, otherwise it has just been reset.
**
** At present this function is only used for detail=col and detail=none
** fts5 tables. This implies that all phrases must be at most 1 token
** in size, as phrase matches are not supported without detail=full.
*/
Fts5PoslistPopulator *sqlite3Fts5ExprClearPoslists(Fts5Expr *pExpr, int bLive){
  Fts5PoslistPopulator *pRet;
  pRet = sqlite3_malloc(sizeof(Fts5PoslistPopulator)*pExpr->nPhrase);
  pRet = sqlite3_malloc64(sizeof(Fts5PoslistPopulator)*pExpr->nPhrase);
  if( pRet ){
    int i;
    memset(pRet, 0, sizeof(Fts5PoslistPopulator)*pExpr->nPhrase);
    for(i=0; i<pExpr->nPhrase; i++){
      Fts5Buffer *pBuf = &pExpr->apExprPhrase[i]->poslist;
      Fts5ExprNode *pNode = pExpr->apExprPhrase[i]->pNode;
      assert( pExpr->apExprPhrase[i]->nTerm==1 );
      assert( pExpr->apExprPhrase[i]->nTerm<=1 );
      if( bLive && 
          (pBuf->n==0 || pNode->iRowid!=pExpr->pRoot->iRowid || pNode->bEof)
      ){
        pRet[i].bMiss = 1;
      }else{
        pBuf->n = 0;
      }
2843
2844
2845
2846
2847
2848
2849
2850
3065
3066
3067
3068
3069
3070
3071








-
  }else{
    *ppCollist = 0;
    *pnCollist = 0;
  }

  return rc;
}

Changes to ext/fts5/fts5_hash.c.

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







-
+






-
+





-
+







  int rc = SQLITE_OK;
  Fts5Hash *pNew;

  *ppNew = pNew = (Fts5Hash*)sqlite3_malloc(sizeof(Fts5Hash));
  if( pNew==0 ){
    rc = SQLITE_NOMEM;
  }else{
    int nByte;
    sqlite3_int64 nByte;
    memset(pNew, 0, sizeof(Fts5Hash));
    pNew->pnByte = pnByte;
    pNew->eDetail = pConfig->eDetail;

    pNew->nSlot = 1024;
    nByte = sizeof(Fts5HashEntry*) * pNew->nSlot;
    pNew->aSlot = (Fts5HashEntry**)sqlite3_malloc(nByte);
    pNew->aSlot = (Fts5HashEntry**)sqlite3_malloc64(nByte);
    if( pNew->aSlot==0 ){
      sqlite3_free(pNew);
      *ppNew = 0;
      rc = SQLITE_NOMEM;
    }else{
      memset(pNew->aSlot, 0, nByte);
      memset(pNew->aSlot, 0, (size_t)nByte);
    }
  }
  return rc;
}

/*
** Free a hash table object.
161
162
163
164
165
166
167
168

169
170
171
172
173
174
175
161
162
163
164
165
166
167

168
169
170
171
172
173
174
175







-
+







*/
static int fts5HashResize(Fts5Hash *pHash){
  int nNew = pHash->nSlot*2;
  int i;
  Fts5HashEntry **apNew;
  Fts5HashEntry **apOld = pHash->aSlot;

  apNew = (Fts5HashEntry**)sqlite3_malloc(nNew*sizeof(Fts5HashEntry*));
  apNew = (Fts5HashEntry**)sqlite3_malloc64(nNew*sizeof(Fts5HashEntry*));
  if( !apNew ) return SQLITE_NOMEM;
  memset(apNew, 0, nNew*sizeof(Fts5HashEntry*));

  for(i=0; i<pHash->nSlot; i++){
    while( apOld[i] ){
      unsigned int iHash;
      Fts5HashEntry *p = apOld[i];
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
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







-
+
+
+
+
+
+

-
+
+

-
+

-
+

-
+



-
+









-
+



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








  sqlite3_free(apOld);
  pHash->nSlot = nNew;
  pHash->aSlot = apNew;
  return SQLITE_OK;
}

static void fts5HashAddPoslistSize(Fts5Hash *pHash, Fts5HashEntry *p){
static int fts5HashAddPoslistSize(
  Fts5Hash *pHash, 
  Fts5HashEntry *p,
  Fts5HashEntry *p2
){
  int nRet = 0;
  if( p->iSzPoslist ){
    u8 *pPtr = (u8*)p;
    u8 *pPtr = p2 ? (u8*)p2 : (u8*)p;
    int nData = p->nData;
    if( pHash->eDetail==FTS5_DETAIL_NONE ){
      assert( p->nData==p->iSzPoslist );
      assert( nData==p->iSzPoslist );
      if( p->bDel ){
        pPtr[p->nData++] = 0x00;
        pPtr[nData++] = 0x00;
        if( p->bContent ){
          pPtr[p->nData++] = 0x00;
          pPtr[nData++] = 0x00;
        }
      }
    }else{
      int nSz = (p->nData - p->iSzPoslist - 1);       /* Size in bytes */
      int nSz = (nData - p->iSzPoslist - 1);       /* Size in bytes */
      int nPos = nSz*2 + p->bDel;                     /* Value of nPos field */

      assert( p->bDel==0 || p->bDel==1 );
      if( nPos<=127 ){
        pPtr[p->iSzPoslist] = (u8)nPos;
      }else{
        int nByte = sqlite3Fts5GetVarintLen((u32)nPos);
        memmove(&pPtr[p->iSzPoslist + nByte], &pPtr[p->iSzPoslist + 1], nSz);
        sqlite3Fts5PutVarint(&pPtr[p->iSzPoslist], nPos);
        p->nData += (nByte-1);
        nData += (nByte-1);
      }
    }

    nRet = nData - p->nData;
    if( p2==0 ){
    p->iSzPoslist = 0;
    p->bDel = 0;
    p->bContent = 0;
  }
      p->iSzPoslist = 0;
      p->bDel = 0;
      p->bContent = 0;
      p->nData = nData;
    }
  }
  return nRet;
}

/*
** Add an entry to the in-memory hash table. The key is the concatenation
** of bByte and (pToken/nToken). The value is (iRowid/iCol/iPos).
**
**     (bByte || pToken) -> (iRowid,iCol,iPos)
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
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







-
+










-
+


-
+







    }
  }

  /* If an existing hash entry cannot be found, create a new one. */
  if( p==0 ){
    /* Figure out how much space to allocate */
    char *zKey;
    int nByte = sizeof(Fts5HashEntry) + (nToken+1) + 1 + 64;
    sqlite3_int64 nByte = sizeof(Fts5HashEntry) + (nToken+1) + 1 + 64;
    if( nByte<128 ) nByte = 128;

    /* Grow the Fts5Hash.aSlot[] array if necessary. */
    if( (pHash->nEntry*2)>=pHash->nSlot ){
      int rc = fts5HashResize(pHash);
      if( rc!=SQLITE_OK ) return rc;
      iHash = fts5HashKey2(pHash->nSlot, (u8)bByte, (const u8*)pToken, nToken);
    }

    /* Allocate new Fts5HashEntry and add it to the hash table. */
    p = (Fts5HashEntry*)sqlite3_malloc(nByte);
    p = (Fts5HashEntry*)sqlite3_malloc64(nByte);
    if( !p ) return SQLITE_NOMEM;
    memset(p, 0, sizeof(Fts5HashEntry));
    p->nAlloc = nByte;
    p->nAlloc = (int)nByte;
    zKey = fts5EntryKey(p);
    zKey[0] = bByte;
    memcpy(&zKey[1], pToken, nToken);
    assert( iHash==fts5HashKey(pHash->nSlot, (u8*)zKey, nToken+1) );
    p->nKey = nToken;
    zKey[nToken+1] = '\0';
    p->nData = nToken+1 + 1 + sizeof(Fts5HashEntry);
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
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







-













-
+


-
+

-
+













+
-
-
+
+















-
+








    p->iSzPoslist = p->nData;
    if( pHash->eDetail!=FTS5_DETAIL_NONE ){
      p->nData += 1;
      p->iCol = (pHash->eDetail==FTS5_DETAIL_FULL ? 0 : -1);
    }

    nIncr += p->nData;
  }else{

    /* Appending to an existing hash-entry. Check that there is enough 
    ** space to append the largest possible new entry. Worst case scenario 
    ** is:
    **
    **     + 9 bytes for a new rowid,
    **     + 4 byte reserved for the "poslist size" varint.
    **     + 1 byte for a "new column" byte,
    **     + 3 bytes for a new column number (16-bit max) as a varint,
    **     + 5 bytes for the new position offset (32-bit max).
    */
    if( (p->nAlloc - p->nData) < (9 + 4 + 1 + 3 + 5) ){
      int nNew = p->nAlloc * 2;
      sqlite3_int64 nNew = p->nAlloc * 2;
      Fts5HashEntry *pNew;
      Fts5HashEntry **pp;
      pNew = (Fts5HashEntry*)sqlite3_realloc(p, nNew);
      pNew = (Fts5HashEntry*)sqlite3_realloc64(p, nNew);
      if( pNew==0 ) return SQLITE_NOMEM;
      pNew->nAlloc = nNew;
      pNew->nAlloc = (int)nNew;
      for(pp=&pHash->aSlot[iHash]; *pp!=p; pp=&(*pp)->pHashNext);
      *pp = pNew;
      p = pNew;
    }
    nIncr -= p->nData;
  }
  assert( (p->nAlloc - p->nData) >= (9 + 4 + 1 + 3 + 5) );

  pPtr = (u8*)p;

  /* If this is a new rowid, append the 4-byte size field for the previous
  ** entry, and the new rowid for this entry.  */
  if( iRowid!=p->iRowid ){
    u64 iDiff = (u64)iRowid - (u64)p->iRowid;
    fts5HashAddPoslistSize(pHash, p);
    p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iRowid - p->iRowid);
    fts5HashAddPoslistSize(pHash, p, 0);
    p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iDiff);
    p->iRowid = iRowid;
    bNew = 1;
    p->iSzPoslist = p->nData;
    if( pHash->eDetail!=FTS5_DETAIL_NONE ){
      p->nData += 1;
      p->iCol = (pHash->eDetail==FTS5_DETAIL_FULL ? 0 : -1);
      p->iPos = 0;
    }
  }

  if( iCol>=0 ){
    if( pHash->eDetail==FTS5_DETAIL_NONE ){
      p->bContent = 1;
    }else{
      /* Append a new column value, if necessary */
      assert( iCol>=p->iCol );
      assert_nc( iCol>=p->iCol );
      if( iCol!=p->iCol ){
        if( pHash->eDetail==FTS5_DETAIL_FULL ){
          pPtr[p->nData++] = 0x01;
          p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iCol);
          p->iCol = (i16)iCol;
          p->iPos = 0;
        }else{
434
435
436
437
438
439
440
441

442
443
444
445
446
447

448


449
450
451
452
453
454
455
445
446
447
448
449
450
451

452
453
454
455
456
457
458
459

460
461
462
463
464
465
466
467
468







-
+






+
-
+
+







  const int nMergeSlot = 32;
  Fts5HashEntry **ap;
  Fts5HashEntry *pList;
  int iSlot;
  int i;

  *ppSorted = 0;
  ap = sqlite3_malloc(sizeof(Fts5HashEntry*) * nMergeSlot);
  ap = sqlite3_malloc64(sizeof(Fts5HashEntry*) * nMergeSlot);
  if( !ap ) return SQLITE_NOMEM;
  memset(ap, 0, sizeof(Fts5HashEntry*) * nMergeSlot);

  for(iSlot=0; iSlot<pHash->nSlot; iSlot++){
    Fts5HashEntry *pIter;
    for(pIter=pHash->aSlot[iSlot]; pIter; pIter=pIter->pHashNext){
      if( pTerm==0 
      if( pTerm==0 || 0==memcmp(fts5EntryKey(pIter), pTerm, nTerm) ){
       || (pIter->nKey+1>=nTerm && 0==memcmp(fts5EntryKey(pIter), pTerm, nTerm))
      ){
        Fts5HashEntry *pEntry = pIter;
        pEntry->pScanNext = 0;
        for(i=0; ap[i]; i++){
          pEntry = fts5HashEntryMerge(pEntry, ap[i]);
          ap[i] = 0;
        }
        ap[i] = pEntry;
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
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







+

-
+








+
-
+



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

-
+







}

/*
** Query the hash table for a doclist associated with term pTerm/nTerm.
*/
int sqlite3Fts5HashQuery(
  Fts5Hash *pHash,                /* Hash table to query */
  int nPre,
  const char *pTerm, int nTerm,   /* Query term */
  const u8 **ppDoclist,           /* OUT: Pointer to doclist for pTerm */
  void **ppOut,                   /* OUT: Pointer to new object */
  int *pnDoclist                  /* OUT: Size of doclist in bytes */
){
  unsigned int iHash = fts5HashKey(pHash->nSlot, (const u8*)pTerm, nTerm);
  char *zKey = 0;
  Fts5HashEntry *p;

  for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){
    zKey = fts5EntryKey(p);
    assert( p->nKey+1==(int)strlen(zKey) );
    if( memcmp(zKey, pTerm, nTerm)==0 && zKey[nTerm]==0 ) break;
    if( nTerm==p->nKey+1 && memcmp(zKey, pTerm, nTerm)==0 ) break;
  }

  if( p ){
    int nHashPre = sizeof(Fts5HashEntry) + nTerm + 1;
    int nList = p->nData - nHashPre;
    u8 *pRet = (u8*)(*ppOut = sqlite3_malloc64(nPre + nList + 10));
    if( pRet ){
      Fts5HashEntry *pFaux = (Fts5HashEntry*)&pRet[nPre-nHashPre];
      memcpy(&pRet[nPre], &((u8*)p)[nHashPre], nList);
    fts5HashAddPoslistSize(pHash, p);
    *ppDoclist = (const u8*)&zKey[nTerm+1];
    *pnDoclist = p->nData - (sizeof(Fts5HashEntry) + nTerm + 1);
      nList += fts5HashAddPoslistSize(pHash, p, pFaux);
      *pnDoclist = nList;
    }else{
      *pnDoclist = 0;
      return SQLITE_NOMEM;
    }
  }else{
    *ppDoclist = 0;
    *ppOut = 0;
    *pnDoclist = 0;
  }

  return SQLITE_OK;
}

int sqlite3Fts5HashScanInit(
520
521
522
523
524
525
526
527

528
529
530
531
532
533
534
535
536
537
544
545
546
547
548
549
550

551
552
553
554
555
556
557
558
559
560








-
+









-
  const u8 **ppDoclist,           /* OUT: pointer to doclist */
  int *pnDoclist                  /* OUT: size of doclist in bytes */
){
  Fts5HashEntry *p;
  if( (p = pHash->pScan) ){
    char *zKey = fts5EntryKey(p);
    int nTerm = (int)strlen(zKey);
    fts5HashAddPoslistSize(pHash, p);
    fts5HashAddPoslistSize(pHash, p, 0);
    *pzTerm = zKey;
    *ppDoclist = (const u8*)&zKey[nTerm+1];
    *pnDoclist = p->nData - (sizeof(Fts5HashEntry) + nTerm + 1);
  }else{
    *pzTerm = 0;
    *ppDoclist = 0;
    *pnDoclist = 0;
  }
}

Changes to ext/fts5/fts5_index.c.

235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
235
236
237
238
239
240
241





242
243
244
245
246
247
248







-
-
-
-
-







 ((i64)(height) << (FTS5_DATA_PAGE_B)) +                                       \
 ((i64)(pgno))                                                                 \
)

#define FTS5_SEGMENT_ROWID(segid, pgno)       fts5_dri(segid, 0, 0, pgno)
#define FTS5_DLIDX_ROWID(segid, height, pgno) fts5_dri(segid, 1, height, pgno)

/*
** Maximum segments permitted in a single index 
*/
#define FTS5_MAX_SEGMENT 2000

#ifdef SQLITE_DEBUG
int sqlite3Fts5Corrupt() { return SQLITE_CORRUPT_VTAB; }
#endif


/*
** Each time a blob is read from the %_data table, it is padded with this
297
298
299
300
301
302
303
304

305
306
307
308
309
310
311
292
293
294
295
296
297
298

299
300
301
302
303
304
305
306







-
+







  int rc;                         /* Current error code */

  /* State used by the fts5DataXXX() functions. */
  sqlite3_blob *pReader;          /* RO incr-blob open on %_data table */
  sqlite3_stmt *pWriter;          /* "INSERT ... %_data VALUES(?,?)" */
  sqlite3_stmt *pDeleter;         /* "DELETE FROM %_data ... id>=? AND id<=?" */
  sqlite3_stmt *pIdxWriter;       /* "INSERT ... %_idx VALUES(?,?,?,?)" */
  sqlite3_stmt *pIdxDeleter;      /* "DELETE FROM %_idx WHERE segid=? */
  sqlite3_stmt *pIdxDeleter;      /* "DELETE FROM %_idx WHERE segid=?" */
  sqlite3_stmt *pIdxSelect;
  int nRead;                      /* Total number of blocks read */

  sqlite3_stmt *pDataVersion;
  i64 iStructVersion;             /* data_version when pStruct read */
  Fts5Structure *pStruct;         /* Current db structure (or NULL) */
};
432
433
434
435
436
437
438
439

440
441
442
443
444
445
446
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;
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
503
504
505
506
507
508
509

510
511
512
513
514
515
516







-







**   Used by sqlite3Fts5IterPoslist() when the poslist needs to be buffered.
**   There is no way to tell if this is populated or not.
*/
struct Fts5Iter {
  Fts5IndexIter base;             /* Base class containing output vars */

  Fts5Index *pIndex;              /* Index that owns this iterator */
  Fts5Structure *pStruct;         /* Database structure for this iterator */
  Fts5Buffer poslist;             /* Buffer containing current poslist */
  Fts5Colset *pColset;            /* Restrict matches to these columns */

  /* Invoked to set output variables. */
  void (*xSetOutputs)(Fts5Iter*, Fts5SegIter*);

  int nSeg;                       /* Size of aSeg[] array */
569
570
571
572
573
574
575
576

577
578
579
580
581
582
583
563
564
565
566
567
568
569

570
571
572
573
574
575
576
577







-
+








/*
** Allocate and return a buffer at least nByte bytes in size.
**
** If an OOM error is encountered, return NULL and set the error code in
** the Fts5Index handle passed as the first argument.
*/
static void *fts5IdxMalloc(Fts5Index *p, int nByte){
static void *fts5IdxMalloc(Fts5Index *p, sqlite3_int64 nByte){
  return sqlite3Fts5MallocZero(&p->rc, nByte);
}

/*
** Compare the contents of the pLeft buffer with the pRight/nRight blob.
**
** Return -ve if pLeft is smaller than pRight, 0 if they are equal or
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
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







+
-
-
+
+
+
+












-
+







**
** Return -ve if pLeft is smaller than pRight, 0 if they are equal or
** +ve if pRight is smaller than pLeft. In other words:
**
**     res = *pLeft - *pRight
*/
static int fts5BufferCompare(Fts5Buffer *pLeft, Fts5Buffer *pRight){
  int nCmp, res;
  int nCmp = MIN(pLeft->n, pRight->n);
  int res = memcmp(pLeft->p, pRight->p, nCmp);
  nCmp = MIN(pLeft->n, pRight->n);
  assert( nCmp<=0 || pLeft->p!=0 );
  assert( nCmp<=0 || pRight->p!=0 );
  res = fts5Memcmp(pLeft->p, pRight->p, nCmp);
  return (res==0 ? (pLeft->n - pRight->n) : res);
}

static int fts5LeafFirstTermOff(Fts5Data *pLeaf){
  int ret;
  fts5GetVarint32(&pLeaf->p[pLeaf->szLeaf], ret);
  return ret;
}

/*
** Close the read-only blob handle, if it is open.
*/
static void fts5CloseReader(Fts5Index *p){
void sqlite3Fts5IndexCloseReader(Fts5Index *p){
  if( p->pReader ){
    sqlite3_blob *pReader = p->pReader;
    p->pReader = 0;
    sqlite3_blob_close(pReader);
  }
}

645
646
647
648
649
650
651
652

653
654
655
656
657
658
659
642
643
644
645
646
647
648

649
650
651
652
653
654
655
656







-
+







      ** is required.  */
      sqlite3_blob *pBlob = p->pReader;
      p->pReader = 0;
      rc = sqlite3_blob_reopen(pBlob, iRowid);
      assert( p->pReader==0 );
      p->pReader = pBlob;
      if( rc!=SQLITE_OK ){
        fts5CloseReader(p);
        sqlite3Fts5IndexCloseReader(p);
      }
      if( rc==SQLITE_ABORT ) rc = SQLITE_OK;
    }

    /* If the blob handle is not open at this point, open it and seek 
    ** to the requested entry.  */
    if( p->pReader==0 && rc==SQLITE_OK ){
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
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







-
-
+
+















+
+










+












-
+
















-
+
+







    ** table, missing row, non-blob/text in block column - indicate 
    ** backing store corruption.  */
    if( rc==SQLITE_ERROR ) rc = FTS5_CORRUPT;

    if( rc==SQLITE_OK ){
      u8 *aOut = 0;               /* Read blob data into this buffer */
      int nByte = sqlite3_blob_bytes(p->pReader);
      int nAlloc = sizeof(Fts5Data) + nByte + FTS5_DATA_PADDING;
      pRet = (Fts5Data*)sqlite3_malloc(nAlloc);
      sqlite3_int64 nAlloc = sizeof(Fts5Data) + nByte + FTS5_DATA_PADDING;
      pRet = (Fts5Data*)sqlite3_malloc64(nAlloc);
      if( pRet ){
        pRet->nn = nByte;
        aOut = pRet->p = (u8*)&pRet[1];
      }else{
        rc = SQLITE_NOMEM;
      }

      if( rc==SQLITE_OK ){
        rc = sqlite3_blob_read(p->pReader, aOut, nByte, 0);
      }
      if( rc!=SQLITE_OK ){
        sqlite3_free(pRet);
        pRet = 0;
      }else{
        /* TODO1: Fix this */
        pRet->p[nByte] = 0x00;
        pRet->p[nByte+1] = 0x00;
        pRet->szLeaf = fts5GetU16(&pRet->p[2]);
      }
    }
    p->rc = rc;
    p->nRead++;
  }

  assert( (pRet==0)==(p->rc!=SQLITE_OK) );
  return pRet;
}


/*
** Release a reference to data record returned by an earlier call to
** fts5DataRead().
*/
static void fts5DataRelease(Fts5Data *pData){
  sqlite3_free(pData);
}

static Fts5Data *fts5LeafRead(Fts5Index *p, i64 iRowid){
  Fts5Data *pRet = fts5DataRead(p, iRowid);
  if( pRet ){
    if( pRet->szLeaf>pRet->nn ){
    if( pRet->nn<4 || pRet->szLeaf>pRet->nn ){
      p->rc = FTS5_CORRUPT;
      fts5DataRelease(pRet);
      pRet = 0;
    }
  }
  return pRet;
}

static int fts5IndexPrepareStmt(
  Fts5Index *p,
  sqlite3_stmt **ppStmt,
  char *zSql
){
  if( p->rc==SQLITE_OK ){
    if( zSql ){
      p->rc = sqlite3_prepare_v3(p->pConfig->db, zSql, -1,
                                 SQLITE_PREPARE_PERSISTENT, ppStmt, 0);
          SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_NO_VTAB,
          ppStmt, 0);
    }else{
      p->rc = SQLITE_NOMEM;
    }
  }
  sqlite3_free(zSql);
  return p->rc;
}
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
767
768
769
770
771
772
773

774
775
776
777
778





779






780
781
782
783
784
785
786







-





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







**
**     DELETE FROM %_data WHERE id BETWEEN $iFirst AND $iLast
*/
static void fts5DataDelete(Fts5Index *p, i64 iFirst, i64 iLast){
  if( p->rc!=SQLITE_OK ) return;

  if( p->pDeleter==0 ){
    int rc;
    Fts5Config *pConfig = p->pConfig;
    char *zSql = sqlite3_mprintf(
        "DELETE FROM '%q'.'%q_data' WHERE id>=? AND id<=?", 
          pConfig->zDb, pConfig->zName
    );
    if( zSql==0 ){
      rc = SQLITE_NOMEM;
    }else{
      rc = sqlite3_prepare_v3(pConfig->db, zSql, -1,
                              SQLITE_PREPARE_PERSISTENT, &p->pDeleter, 0);
    if( fts5IndexPrepareStmt(p, &p->pDeleter, zSql) ) return;
      sqlite3_free(zSql);
    }
    if( rc!=SQLITE_OK ){
      p->rc = rc;
      return;
    }
  }

  sqlite3_bind_int64(p->pDeleter, 1, iFirst);
  sqlite3_bind_int64(p->pDeleter, 2, iLast);
  sqlite3_step(p->pDeleter);
  p->rc = sqlite3_reset(p->pDeleter);
}
830
831
832
833
834
835
836




















































837
838
839
840
841
842
843
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







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







    sqlite3_free(pStruct);
  }
}

static void fts5StructureRef(Fts5Structure *pStruct){
  pStruct->nRef++;
}

void *sqlite3Fts5StructureRef(Fts5Index *p){
  fts5StructureRef(p->pStruct);
  return (void*)p->pStruct;
}
void sqlite3Fts5StructureRelease(void *p){
  if( p ){
    fts5StructureRelease((Fts5Structure*)p);
  }
}
int sqlite3Fts5StructureTest(Fts5Index *p, void *pStruct){
  if( p->pStruct!=(Fts5Structure*)pStruct ){
    return SQLITE_ABORT;
  }
  return SQLITE_OK;
}

/*
** Ensure that structure object (*pp) is writable.
**
** This function is a no-op if (*pRc) is not SQLITE_OK when it is called. If
** an error occurs, (*pRc) is set to an SQLite error code before returning.
*/
static void fts5StructureMakeWritable(int *pRc, Fts5Structure **pp){
  Fts5Structure *p = *pp;
  if( *pRc==SQLITE_OK && p->nRef>1 ){
    i64 nByte = sizeof(Fts5Structure)+(p->nLevel-1)*sizeof(Fts5StructureLevel);
    Fts5Structure *pNew;
    pNew = (Fts5Structure*)sqlite3Fts5MallocZero(pRc, nByte);
    if( pNew ){
      int i;
      memcpy(pNew, p, nByte);
      for(i=0; i<p->nLevel; i++) pNew->aLevel[i].aSeg = 0;
      for(i=0; i<p->nLevel; i++){
        Fts5StructureLevel *pLvl = &pNew->aLevel[i];
        nByte = sizeof(Fts5StructureSegment) * pNew->aLevel[i].nSeg;
        pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(pRc, nByte);
        if( pLvl->aSeg==0 ){
          for(i=0; i<p->nLevel; i++){
            sqlite3_free(pNew->aLevel[i].aSeg);
          }
          sqlite3_free(pNew);
          return;
        }
        memcpy(pLvl->aSeg, p->aLevel[i].aSeg, nByte);
      }
      p->nRef--;
      pNew->nRef = 1;
    }
    *pp = pNew;
  }
}

/*
** Deserialize and return the structure record currently stored in serialized
** form within buffer pData/nData.
**
** The Fts5Structure.aLevel[] and each Fts5StructureLevel.aSeg[] array
** are over-allocated by one slot. This allows the structure contents
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
896
897
898
899
900
901
902

903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925







-
+










+
+
+
+
+







  Fts5Structure **ppOut           /* OUT: Deserialized object */
){
  int rc = SQLITE_OK;
  int i = 0;
  int iLvl;
  int nLevel = 0;
  int nSegment = 0;
  int nByte;                      /* Bytes of space to allocate at pRet */
  sqlite3_int64 nByte;            /* Bytes of space to allocate at pRet */
  Fts5Structure *pRet = 0;        /* Structure object to return */

  /* Grab the cookie value */
  if( piCookie ) *piCookie = sqlite3Fts5Get32(pData);
  i = 4;

  /* Read the total number of levels and segments from the start of the
  ** structure record.  */
  i += fts5GetVarint32(&pData[i], nLevel);
  i += fts5GetVarint32(&pData[i], nSegment);
  if( nLevel>FTS5_MAX_SEGMENT   || nLevel<0
   || nSegment>FTS5_MAX_SEGMENT || nSegment<0
  ){
    return FTS5_CORRUPT;
  }
  nByte = (
      sizeof(Fts5Structure) +                    /* Main structure */
      sizeof(Fts5StructureLevel) * (nLevel-1)    /* aLevel[] array */
  );
  pRet = (Fts5Structure*)sqlite3Fts5MallocZero(&rc, nByte);

  if( pRet ){
887
888
889
890
891
892
893
894

895
896
897

898
899
900
901
902

903
904
905
906
907
908
909
910
911
912














913
914
915
916
917
918
919
920
921
922
923

924

925
926

927
928
929
930

931
932
933
934
935

936
937
938
939
940
941
942
934
935
936
937
938
939
940

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






956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981

982
983
984
985
986
987
988

989
990
991
992
993

994
995
996
997
998
999
1000
1001







-
+



+





+




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











+
-
+


+



-
+




-
+







      int iSeg;

      if( i>=nData ){
        rc = FTS5_CORRUPT;
      }else{
        i += fts5GetVarint32(&pData[i], pLvl->nMerge);
        i += fts5GetVarint32(&pData[i], nTotal);
        assert( nTotal>=pLvl->nMerge );
        if( nTotal<pLvl->nMerge ) rc = FTS5_CORRUPT;
        pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(&rc, 
            nTotal * sizeof(Fts5StructureSegment)
        );
        nSegment -= nTotal;
      }

      if( rc==SQLITE_OK ){
        pLvl->nSeg = nTotal;
        for(iSeg=0; iSeg<nTotal; iSeg++){
          Fts5StructureSegment *pSeg = &pLvl->aSeg[iSeg];
          if( i>=nData ){
            rc = FTS5_CORRUPT;
            break;
          }
          i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].iSegid);
          i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].pgnoFirst);
          i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].pgnoLast);
        }
      }
    }
          i += fts5GetVarint32(&pData[i], pSeg->iSegid);
          i += fts5GetVarint32(&pData[i], pSeg->pgnoFirst);
          i += fts5GetVarint32(&pData[i], pSeg->pgnoLast);
          if( pSeg->pgnoLast<pSeg->pgnoFirst ){
            rc = FTS5_CORRUPT;
            break;
          }
        }
        if( iLvl>0 && pLvl[-1].nMerge && nTotal==0 ) rc = FTS5_CORRUPT;
        if( iLvl==nLevel-1 && pLvl->nMerge ) rc = FTS5_CORRUPT;
      }
    }
    if( nSegment!=0 && rc==SQLITE_OK ) rc = FTS5_CORRUPT;

    if( rc!=SQLITE_OK ){
      fts5StructureRelease(pRet);
      pRet = 0;
    }
  }

  *ppOut = pRet;
  return rc;
}

/*
** Add a level to the Fts5Structure.aLevel[] array of structure object
**
** (*ppStruct).
*/
static void fts5StructureAddLevel(int *pRc, Fts5Structure **ppStruct){
  fts5StructureMakeWritable(pRc, ppStruct);
  if( *pRc==SQLITE_OK ){
    Fts5Structure *pStruct = *ppStruct;
    int nLevel = pStruct->nLevel;
    int nByte = (
    sqlite3_int64 nByte = (
        sizeof(Fts5Structure) +                  /* Main structure */
        sizeof(Fts5StructureLevel) * (nLevel+1)  /* aLevel[] array */
    );

    pStruct = sqlite3_realloc(pStruct, nByte);
    pStruct = sqlite3_realloc64(pStruct, nByte);
    if( pStruct ){
      memset(&pStruct->aLevel[nLevel], 0, sizeof(Fts5StructureLevel));
      pStruct->nLevel++;
      *ppStruct = pStruct;
    }else{
      *pRc = SQLITE_NOMEM;
    }
953
954
955
956
957
958
959
960

961
962
963

964
965
966
967
968
969
970
1012
1013
1014
1015
1016
1017
1018

1019
1020
1021

1022
1023
1024
1025
1026
1027
1028
1029







-
+


-
+







  int iLvl, 
  int nExtra, 
  int bInsert
){
  if( *pRc==SQLITE_OK ){
    Fts5StructureLevel *pLvl = &pStruct->aLevel[iLvl];
    Fts5StructureSegment *aNew;
    int nByte;
    sqlite3_int64 nByte;

    nByte = (pLvl->nSeg + nExtra) * sizeof(Fts5StructureSegment);
    aNew = sqlite3_realloc(pLvl->aSeg, nByte);
    aNew = sqlite3_realloc64(pLvl->aSeg, nByte);
    if( aNew ){
      if( bInsert==0 ){
        memset(&aNew[pLvl->nSeg], 0, sizeof(Fts5StructureSegment) * nExtra);
      }else{
        int nMove = pLvl->nSeg * sizeof(Fts5StructureSegment);
        memmove(&aNew[nExtra], aNew, nMove);
        memset(aNew, 0, sizeof(Fts5StructureSegment) * nExtra);
983
984
985
986
987
988
989
990

991
992
993
994
995
996
997
1042
1043
1044
1045
1046
1047
1048

1049
1050
1051
1052
1053
1054
1055
1056







-
+







  Fts5Data *pData;

  pData = fts5DataRead(p, FTS5_STRUCTURE_ROWID);
  if( p->rc==SQLITE_OK ){
    /* TODO: Do we need this if the leaf-index is appended? Probably... */
    memset(&pData->p[pData->nn], 0, FTS5_DATA_PADDING);
    p->rc = fts5StructureDecode(pData->p, pData->nn, &iCookie, &pRet);
    if( p->rc==SQLITE_OK && pConfig->iCookie!=iCookie ){
    if( p->rc==SQLITE_OK && (pConfig->pgsz==0 || pConfig->iCookie!=iCookie) ){
      p->rc = sqlite3Fts5ConfigLoad(pConfig, iCookie);
    }
    fts5DataRelease(pData);
    if( p->rc!=SQLITE_OK ){
      fts5StructureRelease(pRet);
      pRet = 0;
    }
1470
1471
1472
1473
1474
1475
1476
1477

1478
1479
1480

1481
1482
1483
1484
1485
1486
1487
1529
1530
1531
1532
1533
1534
1535

1536
1537
1538

1539
1540
1541
1542
1543
1544
1545
1546







-
+


-
+







  int iLeafPg                     /* Leaf page number to load dlidx for */
){
  Fts5DlidxIter *pIter = 0;
  int i;
  int bDone = 0;

  for(i=0; p->rc==SQLITE_OK && bDone==0; i++){
    int nByte = sizeof(Fts5DlidxIter) + i * sizeof(Fts5DlidxLvl);
    sqlite3_int64 nByte = sizeof(Fts5DlidxIter) + i * sizeof(Fts5DlidxLvl);
    Fts5DlidxIter *pNew;

    pNew = (Fts5DlidxIter*)sqlite3_realloc(pIter, nByte);
    pNew = (Fts5DlidxIter*)sqlite3_realloc64(pIter, nByte);
    if( pNew==0 ){
      p->rc = SQLITE_NOMEM;
    }else{
      i64 iRowid = FTS5_DLIDX_ROWID(iSegid, i, iLeafPg);
      Fts5DlidxLvl *pLvl = &pNew->aLvl[i];
      pIter = pNew;
      memset(pLvl, 0, sizeof(Fts5DlidxLvl));
1606
1607
1608
1609
1610
1611
1612
1613

1614
1615
1616
1617
1618
1619
1620
1665
1666
1667
1668
1669
1670
1671

1672
1673
1674
1675
1676
1677
1678
1679







-
+







    }
    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;
1639
1640
1641
1642
1643
1644
1645
1646

1647
1648
1649
1650

1651
1652
1653
1654
1655

1656
1657
1658
1659
1660
1661
1662
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







-
+



-
+





+







**
** 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->nn ){
  if( iOff+nNew>pIter->pLeaf->szLeaf || nKeep>pIter->term.n || nNew==0 ){
    p->rc = FTS5_CORRUPT;
    return;
  }
  pIter->term.n = nKeep;
  fts5BufferAppendBlob(&p->rc, &pIter->term, nNew, &a[iOff]);
  assert( pIter->term.n<=pIter->term.nSpace );
  iOff += nNew;
  pIter->iTermLeafOffset = iOff;
  pIter->iTermLeafPgno = pIter->iLeafPgno;
  pIter->iLeafOffset = iOff;

  if( pIter->iPgidxOff>=pIter->pLeaf->nn ){
    pIter->iEndofDoclist = pIter->pLeaf->nn+1;
1712
1713
1714
1715
1716
1717
1718

1719
1720

1721
1722
1723
1724
1725
1726
1727
1772
1773
1774
1775
1776
1777
1778
1779
1780

1781
1782
1783
1784
1785
1786
1787
1788







+

-
+







    pIter->pSeg = pSeg;
    pIter->iLeafPgno = pSeg->pgnoFirst-1;
    fts5SegIterNextPage(p, pIter);
  }

  if( p->rc==SQLITE_OK ){
    pIter->iLeafOffset = 4;
    assert( pIter->pLeaf!=0 );
    assert_nc( pIter->pLeaf->nn>4 );
    assert( fts5LeafFirstTermOff(pIter->pLeaf)==4 );
    assert_nc( fts5LeafFirstTermOff(pIter->pLeaf)==4 );
    pIter->iPgidxOff = pIter->pLeaf->szLeaf+1;
    fts5SegIterLoadTerm(p, pIter, 0);
    fts5SegIterLoadNPos(p, pIter);
  }
}

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







-
+














-
+





-
+








  if( n>pIter->iEndofDoclist ){
    n = pIter->iEndofDoclist;
  }

  ASSERT_SZLEAF_OK(pIter->pLeaf);
  while( 1 ){
    i64 iDelta = 0;
    u64 iDelta = 0;

    if( eDetail==FTS5_DETAIL_NONE ){
      /* todo */
      if( i<n && a[i]==0 ){
        i++;
        if( i<n && a[i]==0 ) i++;
      }
    }else{
      int nPos;
      int bDummy;
      i += fts5GetPoslistSize(&a[i], &nPos, &bDummy);
      i += nPos;
    }
    if( i>=n ) break;
    i += fts5GetVarint(&a[i], (u64*)&iDelta);
    i += fts5GetVarint(&a[i], &iDelta);
    pIter->iRowid += iDelta;

    /* If necessary, grow the pIter->aRowidOffset[] array. */
    if( iRowidOffset>=pIter->nRowidOffset ){
      int nNew = pIter->nRowidOffset + 8;
      int *aNew = (int*)sqlite3_realloc(pIter->aRowidOffset, nNew*sizeof(int));
      int *aNew = (int*)sqlite3_realloc64(pIter->aRowidOffset,nNew*sizeof(int));
      if( aNew==0 ){
        p->rc = SQLITE_NOMEM;
        break;
      }
      pIter->aRowidOffset = aNew;
      pIter->nRowidOffset = nNew;
    }
1814
1815
1816
1817
1818
1819
1820



1821
1822



1823
1824
1825
1826
1827
1828
1829
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884


1885
1886
1887
1888
1889
1890
1891
1892
1893
1894







+
+
+
-
-
+
+
+







          pIter->pLeaf = pNew;
          pIter->iLeafOffset = pIter->iTermLeafOffset;
        }
      }else{
        int iRowidOff;
        iRowidOff = fts5LeafFirstRowidOff(pNew);
        if( iRowidOff ){
          if( iRowidOff>=pNew->szLeaf ){
            p->rc = FTS5_CORRUPT;
          }else{
          pIter->pLeaf = pNew;
          pIter->iLeafOffset = iRowidOff;
            pIter->pLeaf = pNew;
            pIter->iLeafOffset = iRowidOff;
          }
        }
      }

      if( pIter->pLeaf ){
        u8 *a = &pIter->pLeaf->p[pIter->iLeafOffset];
        pIter->iLeafOffset += fts5GetVarint(a, (u64*)&pIter->iRowid);
        break;
1862
1863
1864
1865
1866
1867
1868
1869

1870
1871
1872
1873
1874
1875
1876
1877
1878

1879
1880
1881
1882
1883
1884
1885
1927
1928
1929
1930
1931
1932
1933

1934
1935
1936
1937
1938
1939
1940
1941
1942

1943
1944
1945
1946
1947
1948
1949
1950







-
+








-
+







  assert( pIter->flags & FTS5_SEGITER_REVERSE );
  assert( pIter->pNextLeaf==0 );
  UNUSED_PARAM(pbUnused);

  if( pIter->iRowidOffset>0 ){
    u8 *a = pIter->pLeaf->p;
    int iOff;
    i64 iDelta;
    u64 iDelta;

    pIter->iRowidOffset--;
    pIter->iLeafOffset = pIter->aRowidOffset[pIter->iRowidOffset];
    fts5SegIterLoadNPos(p, pIter);
    iOff = pIter->iLeafOffset;
    if( p->pConfig->eDetail!=FTS5_DETAIL_NONE ){
      iOff += pIter->nPos;
    }
    fts5GetVarint(&a[iOff], (u64*)&iDelta);
    fts5GetVarint(&a[iOff], &iDelta);
    pIter->iRowid -= iDelta;
  }else{
    fts5SegIterReverseNewPage(p, pIter);
  }
}

/*
2064
2065
2066
2067
2068
2069
2070
2071

2072
2073
2074
2075
2076
2077
2078

2079
2080
2081
2082
2083
2084
2085
2129
2130
2131
2132
2133
2134
2135

2136




2137


2138
2139
2140
2141
2142
2143
2144
2145







-
+
-
-
-
-

-
-
+







        fts5SegIterLoadTerm(p, pIter, nKeep);
        fts5SegIterLoadNPos(p, pIter);
        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. 
      ** code is inlined.  */
      **
      ** Later: Switched back to fts5SegIterLoadNPos() because it supports
      ** detail=none mode. Not ideal.
      */
      int nSz;
      assert( p->rc==SQLITE_OK );
      assert( pIter->iLeafOffset<=pIter->pLeaf->nn );
      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 );
    }
  }
}
2100
2101
2102
2103
2104
2105
2106
2107

2108
2109
2110
2111
2112
2113
2114
2160
2161
2162
2163
2164
2165
2166

2167
2168
2169
2170
2171
2172
2173
2174







-
+







  Fts5DlidxIter *pDlidx = pIter->pDlidx;
  Fts5Data *pLast = 0;
  int pgnoLast = 0;

  if( pDlidx ){
    int iSegid = pIter->pSeg->iSegid;
    pgnoLast = fts5DlidxIterPgno(pDlidx);
    pLast = fts5DataRead(p, FTS5_SEGMENT_ROWID(iSegid, pgnoLast));
    pLast = fts5LeafRead(p, FTS5_SEGMENT_ROWID(iSegid, pgnoLast));
  }else{
    Fts5Data *pLeaf = pIter->pLeaf;         /* Current leaf data */

    /* Currently, Fts5SegIter.iLeafOffset points to the first byte of
    ** position-list content for the current rowid. Back it up so that it
    ** points to the start of the position-list size field. */
    int iPoslist;
2127
2128
2129
2130
2131
2132
2133
2134

2135
2136
2137
2138
2139
2140
2141
2187
2188
2189
2190
2191
2192
2193

2194
2195
2196
2197
2198
2199
2200
2201







-
+







      int pgno;
      Fts5StructureSegment *pSeg = pIter->pSeg;

      /* The last rowid in the doclist may not be on the current page. Search
      ** forward to find the page containing the last rowid.  */
      for(pgno=pIter->iLeafPgno+1; !p->rc && pgno<=pSeg->pgnoLast; pgno++){
        i64 iAbs = FTS5_SEGMENT_ROWID(pSeg->iSegid, pgno);
        Fts5Data *pNew = fts5DataRead(p, iAbs);
        Fts5Data *pNew = fts5LeafRead(p, iAbs);
        if( pNew ){
          int iRowid, bTermless;
          iRowid = fts5LeafFirstRowidOff(pNew);
          bTermless = fts5LeafIsTermless(pNew);
          if( iRowid ){
            SWAPVAL(Fts5Data*, pNew, pLast);
            pgnoLast = pgno;
2158
2159
2160
2161
2162
2163
2164




2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236

2237
2238
2239
2240
2241
2242
2243







+
+
+
+








-







  */
  if( pLast ){
    int iOff;
    fts5DataRelease(pIter->pLeaf);
    pIter->pLeaf = pLast;
    pIter->iLeafPgno = pgnoLast;
    iOff = fts5LeafFirstRowidOff(pLast);
    if( iOff>pLast->szLeaf ){
      p->rc = FTS5_CORRUPT;
      return;
    }
    iOff += fts5GetVarint(&pLast->p[iOff], (u64*)&pIter->iRowid);
    pIter->iLeafOffset = iOff;

    if( fts5LeafIsTermless(pLast) ){
      pIter->iEndofDoclist = pLast->nn+1;
    }else{
      pIter->iEndofDoclist = fts5LeafFirstTermOff(pLast);
    }

  }

  fts5SegIterReverseInitPage(p, pIter);
}

/*
** Iterator pIter currently points to the first rowid of a doclist.
2218
2219
2220
2221
2222
2223
2224
2225

2226
2227
2228

2229
2230
2231
2232
2233
2234





2235
2236
2237
2238
2239

2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259



2260
2261
2262
2263
2264
2265

2266
2267
2268
2269
2270
2271
2272
2281
2282
2283
2284
2285
2286
2287

2288
2289


2290
2291





2292
2293
2294
2295
2296
2297
2298
2299
2300

2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318



2319
2320
2321
2322
2323
2324
2325
2326

2327
2328
2329
2330
2331
2332
2333
2334







-
+

-
-
+

-
-
-
-
-
+
+
+
+
+




-
+

















-
-
-
+
+
+





-
+







*/
static void fts5LeafSeek(
  Fts5Index *p,                   /* Leave any error code here */
  int bGe,                        /* True for a >= search */
  Fts5SegIter *pIter,             /* Iterator to seek */
  const u8 *pTerm, int nTerm      /* Term to search for */
){
  int iOff;
  u32 iOff;
  const u8 *a = pIter->pLeaf->p;
  int szLeaf = pIter->pLeaf->szLeaf;
  int n = pIter->pLeaf->nn;
  u32 n = (u32)pIter->pLeaf->nn;

  int nMatch = 0;
  int nKeep = 0;
  int nNew = 0;
  int iTermOff;
  int iPgidx;                     /* Current offset in pgidx */
  u32 nMatch = 0;
  u32 nKeep = 0;
  u32 nNew = 0;
  u32 iTermOff;
  u32 iPgidx;                     /* Current offset in pgidx */
  int bEndOfPage = 0;

  assert( p->rc==SQLITE_OK );

  iPgidx = szLeaf;
  iPgidx = (u32)pIter->pLeaf->szLeaf;
  iPgidx += fts5GetVarint32(&a[iPgidx], iTermOff);
  iOff = iTermOff;
  if( iOff>n ){
    p->rc = FTS5_CORRUPT;
    return;
  }

  while( 1 ){

    /* Figure out how many new bytes are in this term */
    fts5FastGetVarint32(a, iOff, nNew);
    if( nKeep<nMatch ){
      goto search_failed;
    }

    assert( nKeep>=nMatch );
    if( nKeep==nMatch ){
      int nCmp;
      int i;
      nCmp = MIN(nNew, nTerm-nMatch);
      u32 nCmp;
      u32 i;
      nCmp = (u32)MIN(nNew, nTerm-nMatch);
      for(i=0; i<nCmp; i++){
        if( a[iOff+i]!=pTerm[nMatch+i] ) break;
      }
      nMatch += i;

      if( nTerm==nMatch ){
      if( (u32)nTerm==nMatch ){
        if( i==nNew ){
          goto search_success;
        }else{
          goto search_failed;
        }
      }else if( i<nNew && a[iOff+i]>pTerm[nMatch] ){
        goto search_failed;
2298
2299
2300
2301
2302
2303
2304
2305

2306
2307

2308

2309
2310
2311
2312

2313
2314
2315
2316
2317
2318
2319
2320



2321

2322
2323
2324
2325
2326
2327
2328
2360
2361
2362
2363
2364
2365
2366

2367
2368

2369
2370
2371
2372
2373
2374

2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386

2387
2388
2389
2390
2391
2392
2393
2394







-
+

-
+

+



-
+








+
+
+
-
+







    return;
  }else if( bEndOfPage ){
    do {
      fts5SegIterNextPage(p, pIter);
      if( pIter->pLeaf==0 ) return;
      a = pIter->pLeaf->p;
      if( fts5LeafIsTermless(pIter->pLeaf)==0 ){
        iPgidx = pIter->pLeaf->szLeaf;
        iPgidx = (u32)pIter->pLeaf->szLeaf;
        iPgidx += fts5GetVarint32(&pIter->pLeaf->p[iPgidx], iOff);
        if( iOff<4 || iOff>=pIter->pLeaf->szLeaf ){
        if( iOff<4 || (i64)iOff>=pIter->pLeaf->szLeaf ){
          p->rc = FTS5_CORRUPT;
          return;
        }else{
          nKeep = 0;
          iTermOff = iOff;
          n = pIter->pLeaf->nn;
          n = (u32)pIter->pLeaf->nn;
          iOff += fts5GetVarint32(&a[iOff], nNew);
          break;
        }
      }
    }while( 1 );
  }

 search_success:
  if( (i64)iOff+nNew>n || nNew<1 ){
    p->rc = FTS5_CORRUPT;
    return;

  }
  pIter->iLeafOffset = iOff + nNew;
  pIter->iTermLeafOffset = pIter->iLeafOffset;
  pIter->iTermLeafPgno = pIter->iLeafPgno;

  fts5BufferSet(&p->rc, &pIter->term, nKeep, pTerm);
  fts5BufferAppendBlob(&p->rc, &pIter->term, nNew, &a[iOff]);

2422
2423
2424
2425
2426
2427
2428
2429

2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
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
2481
2488
2489
2490
2491
2492
2493
2494

2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515

2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536


2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547

2548

2549



2550
2551
2552
2553
2554
2555
2556







-
+




















-



+





+
+



+
+
+
+
+
+

-
-
+
+
+
+
+
+


+


-
+
-

-
-
-







  **
  **   1) an error has occurred, or
  **   2) the iterator points to EOF, or
  **   3) the iterator points to an entry with term (pTerm/nTerm), or
  **   4) the FTS5INDEX_QUERY_SCAN flag was set and the iterator points
  **      to an entry with a term greater than or equal to (pTerm/nTerm).
  */
  assert( p->rc!=SQLITE_OK                                          /* 1 */
  assert_nc( p->rc!=SQLITE_OK                                       /* 1 */
   || pIter->pLeaf==0                                               /* 2 */
   || fts5BufferCompareBlob(&pIter->term, pTerm, nTerm)==0          /* 3 */
   || (bGe && fts5BufferCompareBlob(&pIter->term, pTerm, nTerm)>0)  /* 4 */
  );
}

/*
** Initialize the object pIter to point to term pTerm/nTerm within the
** in-memory hash table. If there is no such term in the hash-table, the 
** iterator is set to EOF.
**
** If an error occurs, Fts5Index.rc is set to an appropriate error code. If 
** an error has already occurred when this function is called, it is a no-op.
*/
static void fts5SegIterHashInit(
  Fts5Index *p,                   /* FTS5 backend */
  const u8 *pTerm, int nTerm,     /* Term to seek to */
  int flags,                      /* Mask of FTS5INDEX_XXX flags */
  Fts5SegIter *pIter              /* Object to populate */
){
  const u8 *pList = 0;
  int nList = 0;
  const u8 *z = 0;
  int n = 0;
  Fts5Data *pLeaf = 0;

  assert( p->pHash );
  assert( p->rc==SQLITE_OK );

  if( pTerm==0 || (flags & FTS5INDEX_QUERY_SCAN) ){
    const u8 *pList = 0;

    p->rc = sqlite3Fts5HashScanInit(p->pHash, (const char*)pTerm, nTerm);
    sqlite3Fts5HashScanEntry(p->pHash, (const char**)&z, &pList, &nList);
    n = (z ? (int)strlen((const char*)z) : 0);
    if( pList ){
      pLeaf = fts5IdxMalloc(p, sizeof(Fts5Data));
      if( pLeaf ){
        pLeaf->p = (u8*)pList;
      }
    }
  }else{
    pIter->flags |= FTS5_SEGITER_ONETERM;
    sqlite3Fts5HashQuery(p->pHash, (const char*)pTerm, nTerm, &pList, &nList);
    p->rc = sqlite3Fts5HashQuery(p->pHash, sizeof(Fts5Data), 
        (const char*)pTerm, nTerm, (void**)&pLeaf, &nList
    );
    if( pLeaf ){
      pLeaf->p = (u8*)&pLeaf[1];
    }
    z = pTerm;
    n = nTerm;
    pIter->flags |= FTS5_SEGITER_ONETERM;
  }

  if( pList ){
  if( pLeaf ){
    Fts5Data *pLeaf;
    sqlite3Fts5BufferSet(&p->rc, &pIter->term, n, z);
    pLeaf = fts5IdxMalloc(p, sizeof(Fts5Data));
    if( pLeaf==0 ) return;
    pLeaf->p = (u8*)pList;
    pLeaf->nn = pLeaf->szLeaf = nList;
    pIter->pLeaf = pLeaf;
    pIter->iLeafOffset = fts5GetVarint(pLeaf->p, (u64*)&pIter->iRowid);
    pIter->iEndofDoclist = pLeaf->nn;

    if( flags & FTS5INDEX_QUERY_DESC ){
      pIter->flags |= FTS5_SEGITER_REVERSE;
2520
2521
2522
2523
2524
2525
2526
2527

2528
2529
2530
2531
2532
2533
2534
2595
2596
2597
2598
2599
2600
2601

2602
2603
2604
2605
2606
2607
2608
2609







-
+







  if( p1->pLeaf || p2->pLeaf ){
    if( p1->pLeaf==0 ){
      assert( pRes->iFirst==i2 );
    }else if( p2->pLeaf==0 ){
      assert( pRes->iFirst==i1 );
    }else{
      int nMin = MIN(p1->term.n, p2->term.n);
      int res = memcmp(p1->term.p, p2->term.p, nMin);
      int res = fts5Memcmp(p1->term.p, p2->term.p, nMin);
      if( res==0 ) res = p1->term.n - p2->term.n;

      if( res==0 ){
        assert( pRes->bTermEq==1 );
        assert( p1->iRowid!=p2->iRowid );
        res = ((p1->iRowid > p2->iRowid)==pIter->bRev) ? -1 : 1;
      }else{
2620
2621
2622
2623
2624
2625
2626
2627
2628


2629
2630
2631
2632
2633
2634
2635
2695
2696
2697
2698
2699
2700
2701


2702
2703
2704
2705
2706
2707
2708
2709
2710







-
-
+
+







  if( p1->pLeaf==0 ){           /* If p1 is at EOF */
    iRes = i2;
  }else if( p2->pLeaf==0 ){     /* If p2 is at EOF */
    iRes = i1;
  }else{
    int res = fts5BufferCompare(&p1->term, &p2->term);
    if( res==0 ){
      assert( i2>i1 );
      assert( i2!=0 );
      assert_nc( i2>i1 );
      assert_nc( i2!=0 );
      pRes->bTermEq = 1;
      if( p1->iRowid==p2->iRowid ){
        p1->bDel = p2->bDel;
        return i2;
      }
      res = ((p1->iRowid > p2->iRowid)==pIter->bRev) ? -1 : +1;
    }
2661
2662
2663
2664
2665
2666
2667
2668

2669
2670
2671
2672
2673
2674
2675
2736
2737
2738
2739
2740
2741
2742

2743
2744
2745
2746
2747
2748
2749
2750







-
+







  }else{
    fts5DataRelease(pIter->pNextLeaf);
    pIter->pNextLeaf = 0;
    pIter->iLeafPgno = iLeafPgno-1;
    fts5SegIterNextPage(p, pIter);
    assert( p->rc!=SQLITE_OK || pIter->iLeafPgno==iLeafPgno );

    if( p->rc==SQLITE_OK ){
    if( p->rc==SQLITE_OK && ALWAYS(pIter->pLeaf!=0) ){
      int iOff;
      u8 *a = pIter->pLeaf->p;
      int n = pIter->pLeaf->szLeaf;

      iOff = fts5LeafFirstRowidOff(pIter->pLeaf);
      if( iOff<4 || iOff>=n ){
        p->rc = FTS5_CORRUPT;
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2818
2819
2820
2821
2822
2823
2824

2825
2826
2827
2828
2829
2830
2831







-







*/
static void fts5MultiIterFree(Fts5Iter *pIter){
  if( pIter ){
    int i;
    for(i=0; i<pIter->nSeg; i++){
      fts5SegIterClear(&pIter->aSeg[i]);
    }
    fts5StructureRelease(pIter->pStruct);
    fts5BufferFree(&pIter->poslist);
    sqlite3_free(pIter);
  }
}

static void fts5MultiIterAdvanced(
  Fts5Index *p,                   /* FTS5 backend to iterate within */
3051
3052
3053
3054
3055
3056
3057
3058

3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070



3071
3072
3073
3074
3075
3076
3077
3125
3126
3127
3128
3129
3130
3131

3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154







-
+












+
+
+







  int nRem = pSeg->nPos;          /* Number of bytes still to come */
  Fts5Data *pData = 0;
  u8 *pChunk = &pSeg->pLeaf->p[pSeg->iLeafOffset];
  int nChunk = MIN(nRem, pSeg->pLeaf->szLeaf - pSeg->iLeafOffset);
  int pgno = pSeg->iLeafPgno;
  int pgnoSave = 0;

  /* This function does notmwork with detail=none databases. */
  /* This function does not work with detail=none databases. */
  assert( p->pConfig->eDetail!=FTS5_DETAIL_NONE );

  if( (pSeg->flags & FTS5_SEGITER_REVERSE)==0 ){
    pgnoSave = pgno+1;
  }

  while( 1 ){
    xChunk(p, pCtx, pChunk, nChunk);
    nRem -= nChunk;
    fts5DataRelease(pData);
    if( nRem<=0 ){
      break;
    }else if( pSeg->pSeg==0 ){
      p->rc = FTS5_CORRUPT;
      return;
    }else{
      pgno++;
      pData = fts5LeafRead(p, FTS5_SEGMENT_ROWID(pSeg->pSeg->iSegid, pgno));
      if( pData==0 ) break;
      pChunk = &pData->p[4];
      nChunk = MIN(nRem, pData->szLeaf - 4);
      if( pgno==pgnoSave ){
3091
3092
3093
3094
3095
3096
3097


3098




3099
3100
3101
3102
3103
3104
3105
3168
3169
3170
3171
3172
3173
3174
3175
3176

3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187







+
+
-
+
+
+
+







*/
static void fts5SegiterPoslist(
  Fts5Index *p,
  Fts5SegIter *pSeg,
  Fts5Colset *pColset,
  Fts5Buffer *pBuf
){
  assert( pBuf!=0 );
  assert( pSeg!=0 );
  if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos) ){
  if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos+FTS5_DATA_ZERO_PADDING) ){
    assert( pBuf->p!=0 );
    assert( pBuf->nSpace >= pBuf->n+pSeg->nPos+FTS5_DATA_ZERO_PADDING );
    memset(&pBuf->p[pBuf->n+pSeg->nPos], 0, FTS5_DATA_ZERO_PADDING);
    if( pColset==0 ){
      fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback);
    }else{
      if( p->pConfig->eDetail==FTS5_DETAIL_FULL ){
        PoslistCallbackCtx sCtx;
        sCtx.pBuf = pBuf;
        sCtx.pColset = pColset;
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124




3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135


3136
3137
3138
3139
3140
3141

3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154

3155
3156
3157
3158
3159
3160
3161


3162
3163

3164
3165
3166
3167
3168

3169
3170



3171
3172
3173
3174
3175
3176
3177






























3178




3179
3180










3181
3182
3183
3184
3185
3186
3187
3196
3197
3198
3199
3200
3201
3202




3203
3204
3205
3206











3207
3208






3209













3210







3211
3212


3213
3214
3215
3216
3217

3218
3219
3220
3221
3222
3223







3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258


3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275







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




-
+


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

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







        fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistOffsetsCallback);
      }
    }
  }
}

/*
** IN/OUT parameter (*pa) points to a position list n bytes in size. If
** the position list contains entries for column iCol, then (*pa) is set
** to point to the sub-position-list for that column and the number of
** bytes in it returned. Or, if the argument position list does not
** Parameter pPos points to a buffer containing a position list, size nPos.
** This function filters it according to pColset (which must be non-NULL)
** and sets pIter->base.pData/nData to point to the new position list.
** If memory is required for the new position list, use buffer pIter->poslist.
** contain any entries for column iCol, return 0.
*/
static int fts5IndexExtractCol(
  const u8 **pa,                  /* IN/OUT: Pointer to poslist */
  int n,                          /* IN: Size of poslist in bytes */
  int iCol                        /* Column to extract from poslist */
){
  int iCurrent = 0;               /* Anything before the first 0x01 is col 0 */
  const u8 *p = *pa;
  const u8 *pEnd = &p[n];         /* One byte past end of position list */

** Or, if the new position list is a contiguous subset of the input, set
** pIter->base.pData/nData to point directly to it.
  while( iCol>iCurrent ){
    /* Advance pointer p until it points to pEnd or an 0x01 byte that is
    ** not part of a varint. Note that it is not possible for a negative
    ** or extremely large varint to occur within an uncorrupted position 
    ** list. So the last byte of each varint may be assumed to have a clear
    ** 0x80 bit.  */
**
    while( *p!=0x01 ){
      while( *p++ & 0x80 );
      if( p>=pEnd ) return 0;
    }
    *pa = p++;
    iCurrent = *p++;
    if( iCurrent & 0x80 ){
      p--;
      p += fts5GetVarint32(p, iCurrent);
    }
  }
  if( iCol!=iCurrent ) return 0;

** This function is a no-op if *pRc is other than SQLITE_OK when it is
  /* Advance pointer p until it points to pEnd or an 0x01 byte that is
  ** not part of a varint */
  while( p<pEnd && *p!=0x01 ){
    while( *p++ & 0x80 );
  }

  return p - (*pa);
** called. If an OOM error is encountered, *pRc is set to SQLITE_NOMEM
** before returning.
}

*/
static void fts5IndexExtractColset(
  int *pRc,
  Fts5Colset *pColset,            /* Colset to filter on */
  const u8 *pPos, int nPos,       /* Position list */
  Fts5Buffer *pBuf                /* Output buffer */
  Fts5Iter *pIter
){
  if( *pRc==SQLITE_OK ){
    const u8 *p = pPos;
    const u8 *aCopy = p;
    const u8 *pEnd = &p[nPos];    /* One byte past end of position list */
    int i;
    fts5BufferZero(pBuf);
    for(i=0; i<pColset->nCol; i++){
      const u8 *pSub = pPos;
      int nSub = fts5IndexExtractCol(&pSub, nPos, pColset->aiCol[i]);
      if( nSub ){
        fts5BufferAppendBlob(pRc, pBuf, nSub, pSub);
    int i = 0;
    int iCurrent = 0;

    if( pColset->nCol>1 && sqlite3Fts5BufferSize(pRc, &pIter->poslist, nPos) ){
      return;
    }

    while( 1 ){
      while( pColset->aiCol[i]<iCurrent ){
        i++;
        if( i==pColset->nCol ){
          pIter->base.pData = pIter->poslist.p;
          pIter->base.nData = pIter->poslist.n;
          return;
        }
      }

      /* Advance pointer p until it points to pEnd or an 0x01 byte that is
      ** not part of a varint */
      while( p<pEnd && *p!=0x01 ){
        while( *p++ & 0x80 );
      }

      if( pColset->aiCol[i]==iCurrent ){
        if( pColset->nCol==1 ){
          pIter->base.pData = aCopy;
          pIter->base.nData = p-aCopy;
          return;
        }
        fts5BufferSafeAppendBlob(&pIter->poslist, aCopy, p-aCopy);
      }
      if( p>=pEnd ){
        pIter->base.pData = pIter->poslist.p;
        pIter->base.nData = pIter->poslist.n;
        return;
    }
  }
      }
      aCopy = p++;
      iCurrent = *p++;
      if( iCurrent & 0x80 ){
        p--;
        p += fts5GetVarint32(p, iCurrent);
      }
    }
  }

}

/*
** xSetOutputs callback used by detail=none tables.
*/
static void fts5IterSetOutputs_None(Fts5Iter *pIter, Fts5SegIter *pSeg){
  assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_NONE );
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306



3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321

3322
3323
3324
3325
3326
3327
3328
3381
3382
3383
3384
3385
3386
3387







3388
3389
3390



3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410







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












+







  assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_FULL );
  assert( pColset );

  if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){
    /* All data is stored on the current page. Populate the output 
    ** variables to point into the body of the page object. */
    const u8 *a = &pSeg->pLeaf->p[pSeg->iLeafOffset];
    if( pColset->nCol==1 ){
      pIter->base.nData = fts5IndexExtractCol(&a, pSeg->nPos,pColset->aiCol[0]);
      pIter->base.pData = a;
    }else{
      int *pRc = &pIter->pIndex->rc;
      fts5BufferZero(&pIter->poslist);
      fts5IndexExtractColset(pRc, pColset, a, pSeg->nPos, &pIter->poslist);
    int *pRc = &pIter->pIndex->rc;
    fts5BufferZero(&pIter->poslist);
    fts5IndexExtractColset(pRc, pColset, a, pSeg->nPos, pIter);
      pIter->base.pData = pIter->poslist.p;
      pIter->base.nData = pIter->poslist.n;
    }
  }else{
    /* The data is distributed over two or more pages. Copy it into the
    ** Fts5Iter.poslist buffer and then set the output pointer to point
    ** to this buffer.  */
    fts5BufferZero(&pIter->poslist);
    fts5SegiterPoslist(pIter->pIndex, pSeg, pColset, &pIter->poslist);
    pIter->base.pData = pIter->poslist.p;
    pIter->base.nData = pIter->poslist.n;
  }
}

static void fts5IterSetOutputCb(int *pRc, Fts5Iter *pIter){
  assert( pIter!=0 || (*pRc)!=SQLITE_OK );
  if( *pRc==SQLITE_OK ){
    Fts5Config *pConfig = pIter->pIndex->pConfig;
    if( pConfig->eDetail==FTS5_DETAIL_NONE ){
      pIter->xSetOutputs = fts5IterSetOutputs_None;
    }

    else if( pIter->pColset==0 ){
3386
3387
3388
3389
3390
3391
3392
3393




3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3468
3469
3470
3471
3472
3473
3474

3475
3476
3477
3478
3479
3480

3481

3482
3483
3484
3485
3486
3487
3488







-
+
+
+
+


-

-







      nSeg = pStruct->nSegment;
      nSeg += (p->pHash ? 1 : 0);
    }else{
      nSeg = MIN(pStruct->aLevel[iLevel].nSeg, nSegment);
    }
  }
  *ppOut = pNew = fts5MultiIterAlloc(p, nSeg);
  if( pNew==0 ) return;
  if( pNew==0 ){
    assert( p->rc!=SQLITE_OK );
    goto fts5MultiIterNew_post_check;
  }
  pNew->bRev = (0!=(flags & FTS5INDEX_QUERY_DESC));
  pNew->bSkipEmpty = (0!=(flags & FTS5INDEX_QUERY_SKIPEMPTY));
  pNew->pStruct = pStruct;
  pNew->pColset = pColset;
  fts5StructureRef(pStruct);
  if( (flags & FTS5INDEX_QUERY_NOOUTPUT)==0 ){
    fts5IterSetOutputCb(&p->rc, pNew);
  }

  /* Initialize each of the component segment iterators. */
  if( p->rc==SQLITE_OK ){
    if( iLevel<0 ){
3452
3453
3454
3455
3456
3457
3458




3459
3460
3461
3462
3463
3464
3465
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552







+
+
+
+







      pNew->xSetOutputs(pNew, pSeg);
    }

  }else{
    fts5MultiIterFree(pNew);
    *ppOut = 0;
  }

fts5MultiIterNew_post_check:
  assert( (*ppOut)!=0 || p->rc!=SQLITE_OK );
  return;
}

/*
** Create an Fts5Iter that iterates through the doclist provided
** as the second argument.
*/
static void fts5MultiIterNew2(
3499
3500
3501
3502
3503
3504
3505

3506

3507
3508
3509
3510
3511
3512
3513
3586
3587
3588
3589
3590
3591
3592
3593

3594
3595
3596
3597
3598
3599
3600
3601







+
-
+







}

/*
** Return true if the iterator is at EOF or if an error has occurred. 
** False otherwise.
*/
static int fts5MultiIterEof(Fts5Index *p, Fts5Iter *pIter){
  assert( pIter!=0 || p->rc!=SQLITE_OK );
  assert( p->rc 
  assert( p->rc!=SQLITE_OK
      || (pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf==0)==pIter->base.bEof 
  );
  return (p->rc || pIter->base.bEof);
}

/*
** Return the rowid of the entry that the iterator currently points
3569
3570
3571
3572
3573
3574
3575
3576
3577


3578
3579
3580
3581
3582
3583
3584

3585
3586
3587
3588
3589
3590

3591
3592
3593

3594
3595
3596
3597
3598
3599
3600
3601

3602
3603
3604
3605
3606
3607
3608
3657
3658
3659
3660
3661
3662
3663


3664
3665
3666
3667
3668
3669
3670
3671

3672
3673
3674
3675
3676
3677

3678
3679
3680

3681
3682
3683
3684
3685
3686
3687
3688

3689
3690
3691
3692
3693
3694
3695
3696







-
-
+
+






-
+





-
+


-
+







-
+







      int iLvl, iSeg;
      int i;
      u32 mask;
      memset(aUsed, 0, sizeof(aUsed));
      for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
        for(iSeg=0; iSeg<pStruct->aLevel[iLvl].nSeg; iSeg++){
          int iId = pStruct->aLevel[iLvl].aSeg[iSeg].iSegid;
          if( iId<=FTS5_MAX_SEGMENT ){
            aUsed[(iId-1) / 32] |= 1 << ((iId-1) % 32);
          if( iId<=FTS5_MAX_SEGMENT && iId>0 ){
            aUsed[(iId-1) / 32] |= (u32)1 << ((iId-1) % 32);
          }
        }
      }

      for(i=0; aUsed[i]==0xFFFFFFFF; i++);
      mask = aUsed[i];
      for(iSegid=0; mask & (1 << iSegid); iSegid++);
      for(iSegid=0; mask & ((u32)1 << iSegid); iSegid++);
      iSegid += 1 + i*32;

#ifdef SQLITE_DEBUG
      for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
        for(iSeg=0; iSeg<pStruct->aLevel[iLvl].nSeg; iSeg++){
          assert( iSegid!=pStruct->aLevel[iLvl].aSeg[iSeg].iSegid );
          assert_nc( iSegid!=pStruct->aLevel[iLvl].aSeg[iSeg].iSegid );
        }
      }
      assert( iSegid>0 && iSegid<=FTS5_MAX_SEGMENT );
      assert_nc( iSegid>0 && iSegid<=FTS5_MAX_SEGMENT );

      {
        sqlite3_stmt *pIdxSelect = fts5IdxSelectStmt(p);
        if( p->rc==SQLITE_OK ){
          u8 aBlob[2] = {0xff, 0xff};
          sqlite3_bind_int(pIdxSelect, 1, iSegid);
          sqlite3_bind_blob(pIdxSelect, 2, aBlob, 2, SQLITE_STATIC);
          assert( sqlite3_step(pIdxSelect)!=SQLITE_ROW );
          assert_nc( sqlite3_step(pIdxSelect)!=SQLITE_ROW );
          p->rc = sqlite3_reset(pIdxSelect);
          sqlite3_bind_null(pIdxSelect, 2);
        }
      }
#endif
    }
  }
3664
3665
3666
3667
3668
3669
3670
3671

3672
3673
3674
3675
3676
3677

3678
3679
3680
3681
3682
3683
3684
3752
3753
3754
3755
3756
3757
3758

3759
3760
3761
3762
3763
3764

3765
3766
3767
3768
3769
3770
3771
3772







-
+





-
+







*/
static int fts5WriteDlidxGrow(
  Fts5Index *p,
  Fts5SegWriter *pWriter,
  int nLvl
){
  if( p->rc==SQLITE_OK && nLvl>=pWriter->nDlidx ){
    Fts5DlidxWriter *aDlidx = (Fts5DlidxWriter*)sqlite3_realloc(
    Fts5DlidxWriter *aDlidx = (Fts5DlidxWriter*)sqlite3_realloc64(
        pWriter->aDlidx, sizeof(Fts5DlidxWriter) * nLvl
    );
    if( aDlidx==0 ){
      p->rc = SQLITE_NOMEM;
    }else{
      int nByte = sizeof(Fts5DlidxWriter) * (nLvl - pWriter->nDlidx);
      size_t nByte = sizeof(Fts5DlidxWriter) * (nLvl - pWriter->nDlidx);
      memset(&aDlidx[pWriter->nDlidx], 0, nByte);
      pWriter->aDlidx = aDlidx;
      pWriter->nDlidx = nLvl;
    }
  }
  return p->rc;
}
3743
3744
3745
3746
3747
3748
3749

3750
3751



3752
3753
3754
3755
3756
3757
3758
3831
3832
3833
3834
3835
3836
3837
3838


3839
3840
3841
3842
3843
3844
3845
3846
3847
3848







+
-
-
+
+
+







*/
static void fts5WriteBtreeTerm(
  Fts5Index *p,                   /* FTS5 backend object */
  Fts5SegWriter *pWriter,         /* Writer object */
  int nTerm, const u8 *pTerm      /* First term on new page */
){
  fts5WriteFlushBtree(p, pWriter);
  if( p->rc==SQLITE_OK ){
  fts5BufferSet(&p->rc, &pWriter->btterm, nTerm, pTerm);
  pWriter->iBtPage = pWriter->writer.pgno;
    fts5BufferSet(&p->rc, &pWriter->btterm, nTerm, pTerm);
    pWriter->iBtPage = pWriter->writer.pgno;
  }
}

/*
** This function is called when flushing a leaf page that contains no
** terms at all to disk.
*/
static void fts5WriteBtreeNoTerm(
3895
3896
3897
3898
3899
3900
3901

3902
3903
3904
3905
3906
3907
3908
3909
3910

3911
3912
3913
3914
3915
3916
3917
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009







+









+







  Fts5Index *p, 
  Fts5SegWriter *pWriter,
  int nTerm, const u8 *pTerm 
){
  int nPrefix;                    /* Bytes of prefix compression for term */
  Fts5PageWriter *pPage = &pWriter->writer;
  Fts5Buffer *pPgidx = &pWriter->writer.pgidx;
  int nMin = MIN(pPage->term.n, nTerm);

  assert( p->rc==SQLITE_OK );
  assert( pPage->buf.n>=4 );
  assert( pPage->buf.n>4 || pWriter->bFirstTermInPage );

  /* If the current leaf page is full, flush it to disk. */
  if( (pPage->buf.n + pPgidx->n + nTerm + 2)>=p->pConfig->pgsz ){
    if( pPage->buf.n>4 ){
      fts5WriteFlushLeaf(p, pWriter);
      if( p->rc!=SQLITE_OK ) return;
    }
    fts5BufferGrow(&p->rc, &pPage->buf, nTerm+FTS5_DATA_PADDING);
  }
  
  /* TODO1: Updating pgidx here. */
  pPgidx->n += sqlite3Fts5PutVarint(
      &pPgidx->p[pPgidx->n], pPage->buf.n - pPage->iPrevPgidx
3936
3937
3938
3939
3940
3941
3942
3943

3944
3945

3946
3947
3948
3949

3950
3951
3952
3953
3954
3955
3956
4028
4029
4030
4031
4032
4033
4034

4035
4036
4037
4038
4039
4040
4041

4042
4043
4044
4045
4046
4047
4048
4049







-
+


+



-
+







      ** Usually, the previous term is available in pPage->term. The exception
      ** is if this is the first term written in an incremental-merge step.
      ** In this case the previous term is not available, so just write a
      ** copy of (pTerm/nTerm) into the parent node. This is slightly
      ** inefficient, but still correct.  */
      int n = nTerm;
      if( pPage->term.n ){
        n = 1 + fts5PrefixCompress(pPage->term.n, pPage->term.p, pTerm);
        n = 1 + fts5PrefixCompress(nMin, pPage->term.p, pTerm);
      }
      fts5WriteBtreeTerm(p, pWriter, n, pTerm);
      if( p->rc!=SQLITE_OK ) return;
      pPage = &pWriter->writer;
    }
  }else{
    nPrefix = fts5PrefixCompress(pPage->term.n, pPage->term.p, pTerm);
    nPrefix = fts5PrefixCompress(nMin, pPage->term.p, pTerm);
    fts5BufferAppendVarint(&p->rc, &pPage->buf, nPrefix);
  }

  /* Append the number of bytes of new data, then the term data itself
  ** to the page. */
  fts5BufferAppendVarint(&p->rc, &pPage->buf, nTerm - nPrefix);
  fts5BufferAppendBlob(&p->rc, &pPage->buf, nTerm - nPrefix, &pTerm[nPrefix]);
3989
3990
3991
3992
3993
3994
3995
3996
3997




3998
3999
4000
4001
4002
4003
4004
4082
4083
4084
4085
4086
4087
4088


4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099







-
-
+
+
+
+







      fts5WriteDlidxAppend(p, pWriter, iRowid);
    }

    /* Write the rowid. */
    if( pWriter->bFirstRowidInDoclist || pWriter->bFirstRowidInPage ){
      fts5BufferAppendVarint(&p->rc, &pPage->buf, iRowid);
    }else{
      assert( p->rc || iRowid>pWriter->iPrevRowid );
      fts5BufferAppendVarint(&p->rc, &pPage->buf, iRowid - pWriter->iPrevRowid);
      assert_nc( p->rc || iRowid>pWriter->iPrevRowid );
      fts5BufferAppendVarint(&p->rc, &pPage->buf, 
          (u64)iRowid - (u64)pWriter->iPrevRowid
      );
    }
    pWriter->iPrevRowid = iRowid;
    pWriter->bFirstRowidInDoclist = 0;
    pWriter->bFirstRowidInPage = 0;
  }
}

4111
4112
4113
4114
4115
4116
4117
4118

4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136

4137







4138
4139
4140
4141
4142
4143
4144
4145
4146
4147










4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159












4160
4161
4162
4163
4164





4165
4166
4167
4168
4169
4170
4171
4206
4207
4208
4209
4210
4211
4212

4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230

4231
4232
4233
4234
4235
4236
4237
4238
4239










4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250











4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263




4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275







-
+

















-
+

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

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

-
-
-
-
+
+
+
+
+







** incremental merge operation. This function is called if the incremental
** merge step has finished but the input has not been completely exhausted.
*/
static void fts5TrimSegments(Fts5Index *p, Fts5Iter *pIter){
  int i;
  Fts5Buffer buf;
  memset(&buf, 0, sizeof(Fts5Buffer));
  for(i=0; i<pIter->nSeg; i++){
  for(i=0; i<pIter->nSeg && p->rc==SQLITE_OK; i++){
    Fts5SegIter *pSeg = &pIter->aSeg[i];
    if( pSeg->pSeg==0 ){
      /* no-op */
    }else if( pSeg->pLeaf==0 ){
      /* All keys from this input segment have been transfered to the output.
      ** Set both the first and last page-numbers to 0 to indicate that the
      ** segment is now empty. */
      pSeg->pSeg->pgnoLast = 0;
      pSeg->pSeg->pgnoFirst = 0;
    }else{
      int iOff = pSeg->iTermLeafOffset;     /* Offset on new first leaf page */
      i64 iLeafRowid;
      Fts5Data *pData;
      int iId = pSeg->pSeg->iSegid;
      u8 aHdr[4] = {0x00, 0x00, 0x00, 0x00};

      iLeafRowid = FTS5_SEGMENT_ROWID(iId, pSeg->iTermLeafPgno);
      pData = fts5DataRead(p, iLeafRowid);
      pData = fts5LeafRead(p, iLeafRowid);
      if( pData ){
        if( iOff>pData->szLeaf ){
          /* This can occur if the pages that the segments occupy overlap - if
          ** a single page has been assigned to more than one segment. In
          ** this case a prior iteration of this loop may have corrupted the
          ** segment currently being trimmed.  */
          p->rc = FTS5_CORRUPT;
        }else{
        fts5BufferZero(&buf);
        fts5BufferGrow(&p->rc, &buf, pData->nn);
        fts5BufferAppendBlob(&p->rc, &buf, sizeof(aHdr), aHdr);
        fts5BufferAppendVarint(&p->rc, &buf, pSeg->term.n);
        fts5BufferAppendBlob(&p->rc, &buf, pSeg->term.n, pSeg->term.p);
        fts5BufferAppendBlob(&p->rc, &buf, pData->szLeaf-iOff, &pData->p[iOff]);
        if( p->rc==SQLITE_OK ){
          /* Set the szLeaf field */
          fts5PutU16(&buf.p[2], (u16)buf.n);
        }
          fts5BufferZero(&buf);
          fts5BufferGrow(&p->rc, &buf, pData->nn);
          fts5BufferAppendBlob(&p->rc, &buf, sizeof(aHdr), aHdr);
          fts5BufferAppendVarint(&p->rc, &buf, pSeg->term.n);
          fts5BufferAppendBlob(&p->rc, &buf, pSeg->term.n, pSeg->term.p);
          fts5BufferAppendBlob(&p->rc, &buf, pData->szLeaf-iOff,&pData->p[iOff]);
          if( p->rc==SQLITE_OK ){
            /* Set the szLeaf field */
            fts5PutU16(&buf.p[2], (u16)buf.n);
          }

        /* Set up the new page-index array */
        fts5BufferAppendVarint(&p->rc, &buf, 4);
        if( pSeg->iLeafPgno==pSeg->iTermLeafPgno 
         && pSeg->iEndofDoclist<pData->szLeaf 
        ){
          int nDiff = pData->szLeaf - pSeg->iEndofDoclist;
          fts5BufferAppendVarint(&p->rc, &buf, buf.n - 1 - nDiff - 4);
          fts5BufferAppendBlob(&p->rc, &buf, 
              pData->nn - pSeg->iPgidxOff, &pData->p[pSeg->iPgidxOff]
          );
        }
          /* Set up the new page-index array */
          fts5BufferAppendVarint(&p->rc, &buf, 4);
          if( pSeg->iLeafPgno==pSeg->iTermLeafPgno 
           && pSeg->iEndofDoclist<pData->szLeaf
           && pSeg->iPgidxOff<=pData->nn
          ){
            int nDiff = pData->szLeaf - pSeg->iEndofDoclist;
            fts5BufferAppendVarint(&p->rc, &buf, buf.n - 1 - nDiff - 4);
            fts5BufferAppendBlob(&p->rc, &buf, 
                pData->nn - pSeg->iPgidxOff, &pData->p[pSeg->iPgidxOff]
            );
          }

        fts5DataRelease(pData);
        pSeg->pSeg->pgnoFirst = pSeg->iTermLeafPgno;
        fts5DataDelete(p, FTS5_SEGMENT_ROWID(iId, 1), iLeafRowid);
        fts5DataWrite(p, iLeafRowid, buf.p, buf.n);
          pSeg->pSeg->pgnoFirst = pSeg->iTermLeafPgno;
          fts5DataDelete(p, FTS5_SEGMENT_ROWID(iId, 1), iLeafRowid);
          fts5DataWrite(p, iLeafRowid, buf.p, buf.n);
        }
        fts5DataRelease(pData);
      }
    }
  }
  fts5BufferFree(&buf);
}

static void fts5MergeChunkCallback(
4249
4250
4251
4252
4253
4254
4255
4256

4257
4258
4259
4260
4261
4262
4263
4353
4354
4355
4356
4357
4358
4359

4360
4361
4362
4363
4364
4365
4366
4367







-
+







  ){
    Fts5SegIter *pSegIter = &pIter->aSeg[ pIter->aFirst[1].iFirst ];
    int nPos;                     /* position-list size field value */
    int nTerm;
    const u8 *pTerm;

    pTerm = fts5MultiIterTerm(pIter, &nTerm);
    if( nTerm!=term.n || memcmp(pTerm, term.p, nTerm) ){
    if( nTerm!=term.n || fts5Memcmp(pTerm, term.p, nTerm) ){
      if( pnRem && writer.nLeafWritten>nRem ){
        break;
      }
      fts5BufferSet(&p->rc, &term, nTerm, pTerm);
      bTermWritten =0;
    }

4289
4290
4291
4292
4293
4294
4295

4296
4297
4298
4299
4300
4301
4302
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407







+







    }
  }

  /* Flush the last leaf page to disk. Set the output segment b-tree height
  ** and last leaf page number at the same time.  */
  fts5WriteFinish(p, &writer, &pSeg->pgnoLast);

  assert( pIter!=0 || p->rc!=SQLITE_OK );
  if( fts5MultiIterEof(p, pIter) ){
    int i;

    /* Remove the redundant segments from the %_data table */
    for(i=0; i<nInput; i++){
      fts5DataRemoveSegment(p, pLvl->aSeg[i].iSegid);
    }
4389
4390
4391
4392
4393
4394
4395
4396

4397
4398
4399
4400
4401
4402
4403
4494
4495
4496
4497
4498
4499
4500

4501
4502
4503
4504
4505
4506
4507
4508







-
+







** already occurred, this function is a no-op.
*/
static void fts5IndexAutomerge(
  Fts5Index *p,                   /* FTS5 backend object */
  Fts5Structure **ppStruct,       /* IN/OUT: Current structure of index */
  int nLeaf                       /* Number of output leaves just written */
){
  if( p->rc==SQLITE_OK && p->pConfig->nAutomerge>0 ){
  if( p->rc==SQLITE_OK && p->pConfig->nAutomerge>0 && ALWAYS((*ppStruct)!=0) ){
    Fts5Structure *pStruct = *ppStruct;
    u64 nWrite;                   /* Initial value of write-counter */
    int nWork;                    /* Number of work-quanta to perform */
    int nRem;                     /* Number of leaf pages left to write */

    /* Update the write-counter. While doing so, set nWork. */
    nWrite = pStruct->nWriteCounter;
4504
4505
4506
4507
4508
4509
4510

4511
4512
4513
4514
4515
4516
4517
4518

4519
4520
4521
4522
4523
4524
4525

4526
4527
4528
4529
4530
4531
4532

4533
4534
4535
4536
4537
4538
4539
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623

4624
4625
4626
4627
4628
4629
4630

4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646







+







-
+






-
+







+







      const char *zTerm;          /* Buffer containing term */
      const u8 *pDoclist;         /* Pointer to doclist for this term */
      int nDoclist;               /* Size of doclist in bytes */

      /* Write the term for this entry to disk. */
      sqlite3Fts5HashScanEntry(pHash, &zTerm, &pDoclist, &nDoclist);
      fts5WriteAppendTerm(p, &writer, (int)strlen(zTerm), (const u8*)zTerm);
      if( p->rc!=SQLITE_OK ) break;

      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);
            if( p->rc!=SQLITE_OK ) break;
          }else{
            pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iDelta);
          }
          assert( pBuf->n<=pBuf->nSpace );

          if( eDetail==FTS5_DETAIL_NONE ){
            if( iOff<nDoclist && pDoclist[iOff]==0 ){
4583
4584
4585
4586
4587
4588
4589
4590

4591
4592
4593
4594
4595
4596
4597
4690
4691
4692
4693
4694
4695
4696

4697
4698
4699
4700
4701
4702
4703
4704







-
+







          }
        }
      }

      /* TODO2: Doclist terminator written here. */
      /* pBuf->p[pBuf->n++] = '\0'; */
      assert( pBuf->n<=pBuf->nSpace );
      sqlite3Fts5HashScanNext(pHash);
      if( p->rc==SQLITE_OK ) sqlite3Fts5HashScanNext(pHash);
    }
    sqlite3Fts5HashClear(pHash);
    fts5WriteFinish(p, &writer, &pgnoLast);

    /* Update the Fts5Structure. It is written back to the database by the
    ** fts5StructureRelease() call below.  */
    if( pStruct->nLevel==0 ){
4627
4628
4629
4630
4631
4632
4633
4634

4635
4636
4637
4638
4639
4640
4641
4734
4735
4736
4737
4738
4739
4740

4741
4742
4743
4744
4745
4746
4747
4748







-
+







}

static Fts5Structure *fts5IndexOptimizeStruct(
  Fts5Index *p, 
  Fts5Structure *pStruct
){
  Fts5Structure *pNew = 0;
  int nByte = sizeof(Fts5Structure);
  sqlite3_int64 nByte = sizeof(Fts5Structure);
  int nSeg = pStruct->nSegment;
  int i;

  /* Figure out if this structure requires optimization. A structure does
  ** not require optimization if either:
  **
  **  + it consists of fewer than two segments, or 
4742
4743
4744
4745
4746
4747
4748
4749

4750
4751
4752
4753
4754
4755
4756
4757
4758
4759

4760
4761
4762
4763

4764
4765

4766
4767
4768

4769
4770
4771
4772
4773
4774
4775
4776

4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795



4796
4797
4798
4799
4800
4801
4802
4803

4804
4805
4806




4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830




4831
4832
4833
4834
4835
4836
4837
4849
4850
4851
4852
4853
4854
4855

4856
4857
4858
4859
4860
4861
4862
4863
4864
4865

4866
4867
4868
4869
4870
4871
4872

4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884

4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916



4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940




4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951







-
+









-
+




+

-
+



+







-
+



















+
+
+








+
-
-
-
+
+
+
+




















-
-
-
-
+
+
+
+







    fts5StructureRelease(pStruct);
  }
  return fts5IndexReturn(p);
}

static void fts5AppendRowid(
  Fts5Index *p,
  i64 iDelta,
  u64 iDelta,
  Fts5Iter *pUnused,
  Fts5Buffer *pBuf
){
  UNUSED_PARAM(pUnused);
  fts5BufferAppendVarint(&p->rc, pBuf, iDelta);
}

static void fts5AppendPoslist(
  Fts5Index *p,
  i64 iDelta,
  u64 iDelta,
  Fts5Iter *pMulti,
  Fts5Buffer *pBuf
){
  int nData = pMulti->base.nData;
  int nByte = nData + 9 + 9 + FTS5_DATA_ZERO_PADDING;
  assert( nData>0 );
  if( p->rc==SQLITE_OK && 0==fts5BufferGrow(&p->rc, pBuf, nData+9+9) ){
  if( p->rc==SQLITE_OK && 0==fts5BufferGrow(&p->rc, pBuf, nByte) ){
    fts5BufferSafeAppendVarint(pBuf, iDelta);
    fts5BufferSafeAppendVarint(pBuf, nData*2);
    fts5BufferSafeAppendBlob(pBuf, pMulti->base.pData, nData);
    memset(&pBuf->p[pBuf->n], 0, FTS5_DATA_ZERO_PADDING);
  }
}


static void fts5DoclistIterNext(Fts5DoclistIter *pIter){
  u8 *p = pIter->aPoslist + pIter->nSize + pIter->nPoslist;

  assert( pIter->aPoslist );
  assert( pIter->aPoslist || (p==0 && pIter->aPoslist==0) );
  if( p>=pIter->aEof ){
    pIter->aPoslist = 0;
  }else{
    i64 iDelta;

    p += fts5GetVarint(p, (u64*)&iDelta);
    pIter->iRowid += iDelta;

    /* Read position list size */
    if( p[0] & 0x80 ){
      int nPos;
      pIter->nSize = fts5GetVarint32(p, nPos);
      pIter->nPoslist = (nPos>>1);
    }else{
      pIter->nPoslist = ((int)(p[0])) >> 1;
      pIter->nSize = 1;
    }

    pIter->aPoslist = p;
    if( &pIter->aPoslist[pIter->nPoslist]>pIter->aEof ){
      pIter->aPoslist = 0;
    }
  }
}

static void fts5DoclistIterInit(
  Fts5Buffer *pBuf, 
  Fts5DoclistIter *pIter
){
  memset(pIter, 0, sizeof(*pIter));
  if( pBuf->n>0 ){
  pIter->aPoslist = pBuf->p;
  pIter->aEof = &pBuf->p[pBuf->n];
  fts5DoclistIterNext(pIter);
    pIter->aPoslist = pBuf->p;
    pIter->aEof = &pBuf->p[pBuf->n];
    fts5DoclistIterNext(pIter);
  }
}

#if 0
/*
** Append a doclist to buffer pBuf.
**
** This function assumes that space within the buffer has already been
** allocated.
*/
static void fts5MergeAppendDocid(
  Fts5Buffer *pBuf,               /* Buffer to write to */
  i64 *piLastRowid,               /* IN/OUT: Previous rowid written (if any) */
  i64 iRowid                      /* Rowid to append */
){
  assert( pBuf->n!=0 || (*piLastRowid)==0 );
  fts5BufferSafeAppendVarint(pBuf, iRowid - *piLastRowid);
  *piLastRowid = iRowid;
}
#endif

#define fts5MergeAppendDocid(pBuf, iLastRowid, iRowid) {       \
  assert( (pBuf)->n!=0 || (iLastRowid)==0 );                   \
  fts5BufferSafeAppendVarint((pBuf), (iRowid) - (iLastRowid)); \
  (iLastRowid) = (iRowid);                                     \
#define fts5MergeAppendDocid(pBuf, iLastRowid, iRowid) {                 \
  assert( (pBuf)->n!=0 || (iLastRowid)==0 );                             \
  fts5BufferSafeAppendVarint((pBuf), (u64)(iRowid) - (u64)(iLastRowid)); \
  (iLastRowid) = (iRowid);                                               \
}

/*
** Swap the contents of buffer *p1 with that of *p2.
*/
static void fts5BufferSwap(Fts5Buffer *p1, Fts5Buffer *p2){
  Fts5Buffer tmp = *p1;
4853
4854
4855
4856
4857
4858
4859

4860

4861
4862
4863
4864
4865
4866
4867

4868


4869

4870
4871
4872
4873
4874
4875
4876
4967
4968
4969
4970
4971
4972
4973
4974

4975
4976
4977
4978
4979
4980
4981

4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994







+
-
+






-
+

+
+

+







/*
** This is the equivalent of fts5MergePrefixLists() for detail=none mode.
** In this case the buffers consist of a delta-encoded list of rowids only.
*/
static void fts5MergeRowidLists(
  Fts5Index *p,                   /* FTS5 backend object */
  Fts5Buffer *p1,                 /* First list to merge */
  int nBuf,                       /* Number of entries in apBuf[] */
  Fts5Buffer *p2                  /* Second list to merge */
  Fts5Buffer *aBuf                /* Array of other lists to merge into p1 */
){
  int i1 = 0;
  int i2 = 0;
  i64 iRowid1 = 0;
  i64 iRowid2 = 0;
  i64 iOut = 0;

  Fts5Buffer *p2 = &aBuf[0];
  Fts5Buffer out;

  (void)nBuf;
  memset(&out, 0, sizeof(out));
  assert( nBuf==1 );
  sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n);
  if( p->rc ) return;

  fts5NextRowid(p1, &i1, &iRowid1);
  fts5NextRowid(p2, &i2, &iRowid2);
  while( i1>=0 || i2>=0 ){
    if( i1>=0 && (i2<0 || iRowid1<iRowid2) ){
4888
4889
4890
4891
4892
4893
4894
4895





4896
4897
4898
4899
4900
4901
4902




































4903
4904
4905
4906

4907

4908
4909
4910
4911






4912
4913
4914




4915















4916
4917
4918
4919
4920
4921
4922













4923
4924
4925
4926

4927
4928
4929

4930
4931
4932
4933
4934
4935
4936






4937
4938
4939


4940
4941


4942
4943
4944
4945
4946
4947
4948
4949
4950











4951
4952
4953

4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964









4965
4966

4967
4968
4969


4970





4971
4972


4973
4974
4975
4976




4977
4978
4979
4980
4981







4982
4983
4984
4985



4986
4987
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
5024
5025
5026

5027

5028
5029
5030
5031
5032
5033
5034


5035
5036
5037


5038
5039
5040
5041


5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060





















5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080


5081
5082
5083
5084
5085
5086
5087













5088
5089
5090
5091
5092
5093

5094
5095
5096

5097


5098
5099

5100

5101


5102
5103
5104
5105

5106
5107
5108
5109
5110
5111
5112
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018







5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059

5060
5061



5062
5063
5064
5065
5066
5067



5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087







5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100


5101

5102



5103







5104
5105
5106
5107
5108
5109



5110
5111


5112
5113









5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124



5125




5126






5127
5128
5129
5130
5131
5132
5133
5134
5135


5136



5137
5138
5139
5140
5141
5142
5143
5144


5145
5146




5147
5148
5149
5150





5151
5152
5153
5154
5155
5156
5157




5158
5159
5160








5161
5162
5163
5164
5165
5166
5167
5168
5169
5170




5171
5172
5173
5174





5175
5176
5177
5178
5179



5180
5181
5182
5183



5184
5185
5186
5187
5188
5189
5190
5191




5192

5193



5194
5195

5196
5197
5198
5199
5200
5201
5202
5203

5204
5205
5206
5207
5208
5209
5210

5211
5212
5213


5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283







5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301

5302
5303
5304
5305
5306

5307
5308
5309

5310
5311
5312

5313
5314
5315
5316
5317

5318
5319
5320
5321
5322
5323
5324
5325








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




+
-
+

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

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

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

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

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

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

+
-
-
-
+
+
+
+
+
+
+

-
-
-
-
+
-

-
-
-
+
+
-
+
+





+
-
+






-
+
+

-
-
+
+




+
+



















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




















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





-
+



+
-
+
+

-
+

+
-
+
+



-
+







      fts5NextRowid(p2, &i2, &iRowid2);
    }
  }

  fts5BufferSwap(&out, p1);
  fts5BufferFree(&out);
}

typedef struct PrefixMerger PrefixMerger;
struct PrefixMerger {
  Fts5DoclistIter iter;           /* Doclist iterator */
  i64 iPos;                       /* For iterating through a position list */
  int iOff;
/*
** Buffers p1 and p2 contain doclists. This function merges the content
** of the two doclists together and sets buffer p1 to the result before
** returning.
**
** If an error occurs, an error code is left in p->rc. If an error has
** already occurred, this function is a no-op.
  u8 *aPos;
  PrefixMerger *pNext;            /* Next in docid/poslist order */
};

static void fts5PrefixMergerInsertByRowid(
  PrefixMerger **ppHead, 
  PrefixMerger *p
){
  if( p->iter.aPoslist ){
    PrefixMerger **pp = ppHead;
    while( *pp && p->iter.iRowid>(*pp)->iter.iRowid ){
      pp = &(*pp)->pNext;
    }
    p->pNext = *pp;
    *pp = p;
  }
}

static void fts5PrefixMergerInsertByPosition(
  PrefixMerger **ppHead, 
  PrefixMerger *p
){
  if( p->iPos>=0 ){
    PrefixMerger **pp = ppHead;
    while( *pp && p->iPos>(*pp)->iPos ){
      pp = &(*pp)->pNext;
    }
    p->pNext = *pp;
    *pp = p;
  }
}


/*
** Array aBuf[] contains nBuf doclists. These are all merged in with the
** doclist in buffer p1.
*/
static void fts5MergePrefixLists(
  Fts5Index *p,                   /* FTS5 backend object */
  Fts5Buffer *p1,                 /* First list to merge */
  int nBuf,                       /* Number of buffers in array aBuf[] */
  Fts5Buffer *p2                  /* Second list to merge */
  Fts5Buffer *aBuf                /* Other lists to merge in */ 
){
  if( p2->n ){
    i64 iLastRowid = 0;
    Fts5DoclistIter i1;
#define fts5PrefixMergerNextPosition(p) \
  sqlite3Fts5PoslistNext64((p)->aPos,(p)->iter.nPoslist,&(p)->iOff,&(p)->iPos)
#define FTS5_MERGE_NLIST 16
  PrefixMerger aMerger[FTS5_MERGE_NLIST];
  PrefixMerger *pHead = 0;
  int i;
    Fts5DoclistIter i2;
    Fts5Buffer out = {0, 0, 0};
    Fts5Buffer tmp = {0, 0, 0};
  int nOut = 0;
  Fts5Buffer out = {0, 0, 0};
  Fts5Buffer tmp = {0, 0, 0};
  i64 iLastRowid = 0;

  /* Initialize a doclist-iterator for each input buffer. Arrange them in
  ** a linked-list starting at pHead in ascending order of rowid. Avoid
  ** linking any iterators already at EOF into the linked list at all. */ 
  assert( nBuf+1<=(int)(sizeof(aMerger)/sizeof(aMerger[0])) );
  memset(aMerger, 0, sizeof(PrefixMerger)*(nBuf+1));
  pHead = &aMerger[nBuf];
  fts5DoclistIterInit(p1, &pHead->iter);
  for(i=0; i<nBuf; i++){
    fts5DoclistIterInit(&aBuf[i], &aMerger[i].iter);
    fts5PrefixMergerInsertByRowid(&pHead, &aMerger[i]);
    nOut += aBuf[i].n;
  }
  if( nOut==0 ) return;
  nOut += p1->n + 9 + 10*nBuf;

    /* The maximum size of the output is equal to the sum of the two 
    ** input sizes + 1 varint (9 bytes). The extra varint is because if the
    ** first rowid in one input is a large negative number, and the first in
    ** the other a non-negative number, the delta for the non-negative
    ** number will be larger on disk than the literal integer value
    ** was.  */
    if( sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n + 9) ) return;
  /* The maximum size of the output is equal to the sum of the
  ** input sizes + 1 varint (9 bytes). The extra varint is because if the
  ** first rowid in one input is a large negative number, and the first in
  ** the other a non-negative number, the delta for the non-negative
  ** number will be larger on disk than the literal integer value
  ** was.  
  **
  ** Or, if the input position-lists are corrupt, then the output might
  ** include up to (nBuf+1) extra 10-byte positions created by interpreting -1
  ** (the value PoslistNext64() uses for EOF) as a position and appending
  ** it to the output. This can happen at most once for each input 
  ** position-list, hence (nBuf+1) 10 byte paddings.  */
  if( sqlite3Fts5BufferSize(&p->rc, &out, nOut) ) return;
    fts5DoclistIterInit(p1, &i1);
    fts5DoclistIterInit(p2, &i2);

    while( 1 ){
  while( pHead ){
      if( i1.iRowid<i2.iRowid ){
        /* Copy entry from i1 */
        fts5MergeAppendDocid(&out, iLastRowid, i1.iRowid);
    fts5MergeAppendDocid(&out, iLastRowid, pHead->iter.iRowid);
        fts5BufferSafeAppendBlob(&out, i1.aPoslist, i1.nPoslist+i1.nSize);
        fts5DoclistIterNext(&i1);
        if( i1.aPoslist==0 ) break;
      }
      else if( i2.iRowid!=i1.iRowid ){
        /* Copy entry from i2 */
        fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);

    if( pHead->pNext && iLastRowid==pHead->pNext->iter.iRowid ){
      /* Merge data from two or more poslists */
      i64 iPrev = 0;
      int nTmp = FTS5_DATA_ZERO_PADDING;
      int nMerge = 0;
        fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.nPoslist+i2.nSize);
        fts5DoclistIterNext(&i2);
        if( i2.aPoslist==0 ) break;
      PrefixMerger *pSave = pHead;
      PrefixMerger *pThis = 0;
      }
      else{
      int nTail = 0;

        /* Merge the two position lists. */ 
        i64 iPos1 = 0;
        i64 iPos2 = 0;
        int iOff1 = 0;
        int iOff2 = 0;
        u8 *a1 = &i1.aPoslist[i1.nSize];
        u8 *a2 = &i2.aPoslist[i2.nSize];

        i64 iPrev = 0;
      pHead = 0;
      while( pSave && pSave->iter.iRowid==iLastRowid ){
        PrefixMerger *pNext = pSave->pNext;
        pSave->iOff = 0;
        pSave->iPos = 0;
        pSave->aPos = &pSave->iter.aPoslist[pSave->iter.nSize];
        fts5PrefixMergerNextPosition(pSave);
        nTmp += pSave->iter.nPoslist + 10;
        nMerge++;
        fts5PrefixMergerInsertByPosition(&pHead, pSave);
        pSave = pNext;
        Fts5PoslistWriter writer;
        memset(&writer, 0, sizeof(writer));

      }
        fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
        fts5BufferZero(&tmp);
        sqlite3Fts5BufferSize(&p->rc, &tmp, i1.nPoslist + i2.nPoslist);
        if( p->rc ) break;

        sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
        sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
        assert( iPos1>=0 && iPos2>=0 );

        if( iPos1<iPos2 ){
          sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1);
      if( pHead==0 || pHead->pNext==0 ){
        p->rc = FTS5_CORRUPT;
        break;
      }

      /* See the earlier comment in this function for an explanation of why
      ** corrupt input position lists might cause the output to consume
      ** at most nMerge*10 bytes of unexpected space. */
      if( sqlite3Fts5BufferSize(&p->rc, &tmp, nTmp+nMerge*10) ){
          sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
        }else{
        break;
          sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2);
          sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
        }
      }
      fts5BufferZero(&tmp);

      pThis = pHead;
      pHead = pThis->pNext;
      sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, pThis->iPos);
      fts5PrefixMergerNextPosition(pThis);
      fts5PrefixMergerInsertByPosition(&pHead, pThis);
        if( iPos1>=0 && iPos2>=0 ){
          while( 1 ){

      while( pHead->pNext ){
            if( iPos1<iPos2 ){
              if( iPos1!=iPrev ){
                sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1);
              }
        pThis = pHead;
        if( pThis->iPos!=iPrev ){
          sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, pThis->iPos);
        }
              sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
              if( iPos1<0 ) break;
            }else{
              assert( iPos2!=iPrev );
              sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2);
        fts5PrefixMergerNextPosition(pThis);
        pHead = pThis->pNext;
        fts5PrefixMergerInsertByPosition(&pHead, pThis);
      }

      if( pHead->iPos!=iPrev ){
        sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, pHead->iPos);
              sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
              if( iPos2<0 ) break;
            }
          }
      }
      nTail = pHead->iter.nPoslist - pHead->iOff;

        }

        if( iPos1>=0 ){
          if( iPos1!=iPrev ){
            sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1);
          }
          fts5BufferSafeAppendBlob(&tmp, &a1[iOff1], i1.nPoslist-iOff1);
        }else{
      /* WRITEPOSLISTSIZE */
      assert_nc( tmp.n+nTail<=nTmp );
      assert( tmp.n+nTail<=nTmp+nMerge*10 );
      if( tmp.n+nTail>nTmp-FTS5_DATA_ZERO_PADDING ){
        if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT;
        break;
      }
      fts5BufferSafeAppendVarint(&out, (tmp.n+nTail) * 2);
      fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n);
      if( nTail>0 ){
          assert( iPos2>=0 && iPos2!=iPrev );
          sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2);
          fts5BufferSafeAppendBlob(&tmp, &a2[iOff2], i2.nPoslist-iOff2);
        }
        fts5BufferSafeAppendBlob(&out, &pHead->aPos[pHead->iOff], nTail);
      }

      pHead = pSave;
        /* WRITEPOSLISTSIZE */
        fts5BufferSafeAppendVarint(&out, tmp.n * 2);
        fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n);
        fts5DoclistIterNext(&i1);
        fts5DoclistIterNext(&i2);
      for(i=0; i<nBuf+1; i++){
        PrefixMerger *pX = &aMerger[i];
        if( pX->iter.aPoslist && pX->iter.iRowid==iLastRowid ){
          fts5DoclistIterNext(&pX->iter);
          fts5PrefixMergerInsertByRowid(&pHead, pX);
        if( i1.aPoslist==0 || i2.aPoslist==0 ) break;
      }
    }
        }
      }

    }else{
    if( i1.aPoslist ){
      fts5MergeAppendDocid(&out, iLastRowid, i1.iRowid);
      fts5BufferSafeAppendBlob(&out, i1.aPoslist, i1.aEof - i1.aPoslist);
      /* Copy poslist from pHead to output */
      PrefixMerger *pThis = pHead;
      Fts5DoclistIter *pI = &pThis->iter;
      fts5BufferSafeAppendBlob(&out, pI->aPoslist, pI->nPoslist+pI->nSize);
      fts5DoclistIterNext(pI);
      pHead = pThis->pNext;
      fts5PrefixMergerInsertByRowid(&pHead, pThis);
    }
    else if( i2.aPoslist ){
      fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
      fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.aEof - i2.aPoslist);
    }
  }
    assert( out.n<=(p1->n+p2->n+9) );

    fts5BufferSet(&p->rc, p1, out.n, out.p);
    fts5BufferFree(&tmp);
    fts5BufferFree(&out);
  fts5BufferFree(p1);
  fts5BufferFree(&tmp);
  }
  memset(&out.p[out.n], 0, FTS5_DATA_ZERO_PADDING);
  *p1 = out;
}

static void fts5SetupPrefixIter(
  Fts5Index *p,                   /* Index to read from */
  int bDesc,                      /* True for "ORDER BY rowid DESC" */
  int iIdx,                       /* Index to scan for data */
  const u8 *pToken,               /* Buffer containing prefix to match */
  u8 *pToken,                     /* Buffer containing prefix to match */
  int nToken,                     /* Size of buffer pToken in bytes */
  Fts5Colset *pColset,            /* Restrict matches to these columns */
  Fts5Iter **ppIter          /* OUT: New iterator */
){
  Fts5Structure *pStruct;
  Fts5Buffer *aBuf;
  const int nBuf = 32;
  int nBuf = 32;
  int nMerge = 1;

  void (*xMerge)(Fts5Index*, Fts5Buffer*, Fts5Buffer*);
  void (*xAppend)(Fts5Index*, i64, Fts5Iter*, Fts5Buffer*);
  void (*xMerge)(Fts5Index*, Fts5Buffer*, int, Fts5Buffer*);
  void (*xAppend)(Fts5Index*, u64, Fts5Iter*, Fts5Buffer*);
  if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){
    xMerge = fts5MergeRowidLists;
    xAppend = fts5AppendRowid;
  }else{
    nMerge = FTS5_MERGE_NLIST-1;
    nBuf = nMerge*8;   /* Sufficient to merge (16^8)==(2^32) lists */
    xMerge = fts5MergePrefixLists;
    xAppend = fts5AppendPoslist;
  }

  aBuf = (Fts5Buffer*)fts5IdxMalloc(p, sizeof(Fts5Buffer)*nBuf);
  pStruct = fts5StructureRead(p);

  if( aBuf && pStruct ){
    const int flags = FTS5INDEX_QUERY_SCAN 
                    | FTS5INDEX_QUERY_SKIPEMPTY 
                    | FTS5INDEX_QUERY_NOOUTPUT;
    int i;
    i64 iLastRowid = 0;
    Fts5Iter *p1 = 0;     /* Iterator used to gather data from index */
    Fts5Data *pData;
    Fts5Buffer doclist;
    int bNewTerm = 1;

    memset(&doclist, 0, sizeof(doclist));
    if( iIdx!=0 ){
      int dummy = 0;
      const int f2 = FTS5INDEX_QUERY_SKIPEMPTY|FTS5INDEX_QUERY_NOOUTPUT;
      pToken[0] = FTS5_MAIN_PREFIX;
      fts5MultiIterNew(p, pStruct, f2, pColset, pToken, nToken, -1, 0, &p1);
      fts5IterSetOutputCb(&p->rc, p1);
      for(;
        fts5MultiIterEof(p, p1)==0;
        fts5MultiIterNext2(p, p1, &dummy)
      ){
        Fts5SegIter *pSeg = &p1->aSeg[ p1->aFirst[1].iFirst ];
        p1->xSetOutputs(p1, pSeg);
        if( p1->base.nData ){
          xAppend(p, (u64)p1->base.iRowid-(u64)iLastRowid, p1, &doclist);
          iLastRowid = p1->base.iRowid;
        }
      }
      fts5MultiIterFree(p1);
    }

    pToken[0] = FTS5_MAIN_PREFIX + iIdx;
    fts5MultiIterNew(p, pStruct, flags, pColset, pToken, nToken, -1, 0, &p1);
    fts5IterSetOutputCb(&p->rc, p1);
    for( /* no-op */ ;
        fts5MultiIterEof(p, p1)==0;
        fts5MultiIterNext2(p, p1, &bNewTerm)
    ){
      Fts5SegIter *pSeg = &p1->aSeg[ p1->aFirst[1].iFirst ];
      int nTerm = pSeg->term.n;
      const u8 *pTerm = pSeg->term.p;
      p1->xSetOutputs(p1, pSeg);

      assert_nc( memcmp(pToken, pTerm, MIN(nToken, nTerm))<=0 );
      if( bNewTerm ){
        if( nTerm<nToken || memcmp(pToken, pTerm, nToken) ) break;
      }

      if( p1->base.nData==0 ) continue;

      if( p1->base.iRowid<=iLastRowid && doclist.n>0 ){
        for(i=0; p->rc==SQLITE_OK && doclist.n; i++){
          int i1 = i*nMerge;
          int iStore;
          assert( i<nBuf );
          if( aBuf[i].n==0 ){
            fts5BufferSwap(&doclist, &aBuf[i]);
            fts5BufferZero(&doclist);
          }else{
            xMerge(p, &doclist, &aBuf[i]);
            fts5BufferZero(&aBuf[i]);
          assert( i1+nMerge<=nBuf );
          for(iStore=i1; iStore<i1+nMerge; iStore++){
            if( aBuf[iStore].n==0 ){
              fts5BufferSwap(&doclist, &aBuf[iStore]);
              fts5BufferZero(&doclist);
              break;
            }
          }
          if( iStore==i1+nMerge ){
            xMerge(p, &doclist, nMerge, &aBuf[i1]);
            for(iStore=i1; iStore<i1+nMerge; iStore++){
              fts5BufferZero(&aBuf[iStore]);
            }
          }
        }
        iLastRowid = 0;
      }

      xAppend(p, p1->base.iRowid-iLastRowid, p1, &doclist);
      xAppend(p, (u64)p1->base.iRowid-(u64)iLastRowid, p1, &doclist);
      iLastRowid = p1->base.iRowid;
    }

    assert( (nBuf%nMerge)==0 );
    for(i=0; i<nBuf; i++){
    for(i=0; i<nBuf; i+=nMerge){
      int iFree;
      if( p->rc==SQLITE_OK ){
        xMerge(p, &doclist, &aBuf[i]);
        xMerge(p, &doclist, nMerge, &aBuf[i]);
      }
      for(iFree=i; iFree<i+nMerge; iFree++){
      fts5BufferFree(&aBuf[i]);
        fts5BufferFree(&aBuf[iFree]);
      }
    }
    fts5MultiIterFree(p1);

    pData = fts5IdxMalloc(p, sizeof(Fts5Data) + doclist.n);
    pData = fts5IdxMalloc(p, sizeof(Fts5Data)+doclist.n+FTS5_DATA_ZERO_PADDING);
    if( pData ){
      pData->p = (u8*)&pData[1];
      pData->nn = pData->szLeaf = doclist.n;
      if( doclist.n ) memcpy(pData->p, doclist.p, doclist.n);
      fts5MultiIterNew2(p, pData, bDesc, ppIter);
    }
    fts5BufferFree(&doclist);
5144
5145
5146
5147
5148
5149
5150
5151

5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162

5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176

5177
5178
5179
5180
5181
5182
5183
5357
5358
5359
5360
5361
5362
5363

5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374

5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397







-
+










-
+














+








/*
** Commit data to disk.
*/
int sqlite3Fts5IndexSync(Fts5Index *p){
  assert( p->rc==SQLITE_OK );
  fts5IndexFlush(p);
  fts5CloseReader(p);
  sqlite3Fts5IndexCloseReader(p);
  return fts5IndexReturn(p);
}

/*
** Discard any data stored in the in-memory hash tables. Do not write it
** to the database. Additionally, assume that the contents of the %_data
** table may have changed on disk. So any in-memory caches of %_data 
** records must be invalidated.
*/
int sqlite3Fts5IndexRollback(Fts5Index *p){
  fts5CloseReader(p);
  sqlite3Fts5IndexCloseReader(p);
  fts5IndexDiscardData(p);
  fts5StructureInvalidate(p);
  /* assert( p->rc==SQLITE_OK ); */
  return SQLITE_OK;
}

/*
** The %_data table is completely empty when this function is called. This
** function populates it with the initial structure objects for each index,
** and the initial version of the "averages" record (a zero-byte blob).
*/
int sqlite3Fts5IndexReinit(Fts5Index *p){
  Fts5Structure s;
  fts5StructureInvalidate(p);
  fts5IndexDiscardData(p);
  memset(&s, 0, sizeof(Fts5Structure));
  fts5DataWrite(p, FTS5_AVERAGES_ROWID, (const u8*)"", 0);
  fts5StructureWrite(p, &s);
  return fts5IndexReturn(p);
}

/*
5257
5258
5259
5260
5261
5262
5263

5264
5265
5266




5267
5268
5269
5270
5271
5272
5273
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480

5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491







+


-
+
+
+
+







  int nChar
){
  int n = 0;
  int i;
  for(i=0; i<nChar; i++){
    if( n>=nByte ) return 0;      /* Input contains fewer than nChar chars */
    if( (unsigned char)p[n++]>=0xc0 ){
      if( n>=nByte ) return 0;
      while( (p[n] & 0xc0)==0x80 ){
        n++;
        if( n>=nByte ) break;
        if( n>=nByte ){
          if( i+1==nChar ) break;
          return 0;
        }
      }
    }
  }
  return n;
}

/*
5344
5345
5346
5347
5348
5349
5350

5351

5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372



5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395










5396
5397
5398
5399
5400
5401
5402

5403
5404
5405
5406
5407
5408
5409
5562
5563
5564
5565
5566
5567
5568
5569

5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590

5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609







5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625

5626
5627
5628
5629
5630
5631
5632
5633







+
-
+




















-
+
+
+
















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






-
+







  Fts5Buffer buf = {0, 0, 0};

  /* If the QUERY_SCAN flag is set, all other flags must be clear. */
  assert( (flags & FTS5INDEX_QUERY_SCAN)==0 || flags==FTS5INDEX_QUERY_SCAN );

  if( sqlite3Fts5BufferSize(&p->rc, &buf, nToken+1)==0 ){
    int iIdx = 0;                 /* Index to search */
    int iPrefixIdx = 0;           /* +1 prefix index */
    if( nToken ) memcpy(&buf.p[1], pToken, nToken);
    if( nToken>0 ) memcpy(&buf.p[1], pToken, nToken);

    /* Figure out which index to search and set iIdx accordingly. If this
    ** is a prefix query for which there is no prefix index, set iIdx to
    ** greater than pConfig->nPrefix to indicate that the query will be
    ** satisfied by scanning multiple terms in the main index.
    **
    ** If the QUERY_TEST_NOIDX flag was specified, then this must be a
    ** prefix-query. Instead of using a prefix-index (if one exists), 
    ** evaluate the prefix query using the main FTS index. This is used
    ** for internal sanity checking by the integrity-check in debug 
    ** mode only.  */
#ifdef SQLITE_DEBUG
    if( pConfig->bPrefixIndex==0 || (flags & FTS5INDEX_QUERY_TEST_NOIDX) ){
      assert( flags & FTS5INDEX_QUERY_PREFIX );
      iIdx = 1+pConfig->nPrefix;
    }else
#endif
    if( flags & FTS5INDEX_QUERY_PREFIX ){
      int nChar = fts5IndexCharlen(pToken, nToken);
      for(iIdx=1; iIdx<=pConfig->nPrefix; iIdx++){
        if( pConfig->aPrefix[iIdx-1]==nChar ) break;
        int nIdxChar = pConfig->aPrefix[iIdx-1];
        if( nIdxChar==nChar ) break;
        if( nIdxChar==nChar+1 ) iPrefixIdx = iIdx;
      }
    }

    if( iIdx<=pConfig->nPrefix ){
      /* Straight index lookup */
      Fts5Structure *pStruct = fts5StructureRead(p);
      buf.p[0] = (u8)(FTS5_MAIN_PREFIX + iIdx);
      if( pStruct ){
        fts5MultiIterNew(p, pStruct, flags | FTS5INDEX_QUERY_SKIPEMPTY, 
            pColset, buf.p, nToken+1, -1, 0, &pRet
        );
        fts5StructureRelease(pStruct);
      }
    }else{
      /* Scan multiple terms in the main index */
      int bDesc = (flags & FTS5INDEX_QUERY_DESC)!=0;
      buf.p[0] = FTS5_MAIN_PREFIX;
      fts5SetupPrefixIter(p, bDesc, buf.p, nToken+1, pColset, &pRet);
      assert( p->rc!=SQLITE_OK || pRet->pColset==0 );
      fts5IterSetOutputCb(&p->rc, pRet);
      if( p->rc==SQLITE_OK ){
        Fts5SegIter *pSeg = &pRet->aSeg[pRet->aFirst[1].iFirst];
        if( pSeg->pLeaf ) pRet->xSetOutputs(pRet, pSeg);
      fts5SetupPrefixIter(p, bDesc, iPrefixIdx, buf.p, nToken+1, pColset,&pRet);
      if( pRet==0 ){
        assert( p->rc!=SQLITE_OK );
      }else{
        assert( pRet->pColset==0 );
        fts5IterSetOutputCb(&p->rc, pRet);
        if( p->rc==SQLITE_OK ){
          Fts5SegIter *pSeg = &pRet->aSeg[pRet->aFirst[1].iFirst];
          if( pSeg->pLeaf ) pRet->xSetOutputs(pRet, pSeg);
        }
      }
    }

    if( p->rc ){
      sqlite3Fts5IterClose((Fts5IndexIter*)pRet);
      pRet = 0;
      fts5CloseReader(p);
      sqlite3Fts5IndexCloseReader(p);
    }

    *ppIter = (Fts5IndexIter*)pRet;
    sqlite3Fts5BufferFree(&buf);
  }
  return fts5IndexReturn(p);
}
5456
5457
5458
5459
5460
5461
5462

5463
5464

5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475

5476
5477
5478
5479
5480
5481
5482
5680
5681
5682
5683
5684
5685
5686
5687
5688

5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699

5700
5701
5702
5703
5704
5705
5706
5707







+

-
+










-
+








/*
** Return the current term.
*/
const char *sqlite3Fts5IterTerm(Fts5IndexIter *pIndexIter, int *pn){
  int n;
  const char *z = (const char*)fts5MultiIterTerm((Fts5Iter*)pIndexIter, &n);
  assert_nc( z || n<=1 );
  *pn = n-1;
  return &z[1];
  return (z ? &z[1] : 0);
}

/*
** Close an iterator opened by an earlier call to sqlite3Fts5IndexQuery().
*/
void sqlite3Fts5IterClose(Fts5IndexIter *pIndexIter){
  if( pIndexIter ){
    Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
    Fts5Index *pIndex = pIter->pIndex;
    fts5MultiIterFree(pIter);
    fts5CloseReader(pIndex);
    sqlite3Fts5IndexCloseReader(pIndex);
  }
}

/*
** Read and decode the "averages" record from the database. 
**
** Parameter anSize must point to an array of size nCol, where nCol is
5635
5636
5637
5638
5639
5640
5641
5642

5643
5644
5645
5646
5647
5648
5649
5860
5861
5862
5863
5864
5865
5866

5867
5868
5869
5870
5871
5872
5873
5874







-
+







  u64 *pCksum                     /* IN/OUT: Checksum value */
){
  int eDetail = p->pConfig->eDetail;
  u64 cksum = *pCksum;
  Fts5IndexIter *pIter = 0;
  int rc = sqlite3Fts5IndexQuery(p, z, n, flags, 0, &pIter);

  while( rc==SQLITE_OK && 0==sqlite3Fts5IterEof(pIter) ){
  while( rc==SQLITE_OK && ALWAYS(pIter!=0) && 0==sqlite3Fts5IterEof(pIter) ){
    i64 rowid = pIter->iRowid;

    if( eDetail==FTS5_DETAIL_NONE ){
      cksum ^= sqlite3Fts5IndexEntryCksum(rowid, 0, 0, iIdx, z, n);
    }else{
      Fts5PoslistReader sReader;
      for(sqlite3Fts5PoslistReaderInit(pIter->pData, pIter->nData, &sReader);
5661
5662
5663
5664
5665
5666
5667































5668
5669
5670
5671
5672
5673
5674
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930







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







  }
  sqlite3Fts5IterClose(pIter);

  *pCksum = cksum;
  return rc;
}

/*
** Check if buffer z[], size n bytes, contains as series of valid utf-8
** encoded codepoints. If so, return 0. Otherwise, if the buffer does not
** contain valid utf-8, return non-zero.
*/
static int fts5TestUtf8(const char *z, int n){
  int i = 0;
  assert_nc( n>0 );
  while( i<n ){
    if( (z[i] & 0x80)==0x00 ){
      i++;
    }else
    if( (z[i] & 0xE0)==0xC0 ){
      if( i+1>=n || (z[i+1] & 0xC0)!=0x80 ) return 1;
      i += 2;
    }else
    if( (z[i] & 0xF0)==0xE0 ){
      if( i+2>=n || (z[i+1] & 0xC0)!=0x80 || (z[i+2] & 0xC0)!=0x80 ) return 1;
      i += 3;
    }else
    if( (z[i] & 0xF8)==0xF0 ){
      if( i+3>=n || (z[i+1] & 0xC0)!=0x80 || (z[i+2] & 0xC0)!=0x80 ) return 1;
      if( (z[i+2] & 0xC0)!=0x80 ) return 1;
      i += 3;
    }else{
      return 1;
    }
  }

  return 0;
}

/*
** This function is also purely an internal test. It does not contribute to 
** FTS functionality, or even the integrity-check, in any way.
*/
static void fts5TestTerm(
  Fts5Index *p, 
5701
5702
5703
5704
5705
5706
5707
5708
5709








5710
5711
5712
5713
5714
5715
5716
5957
5958
5959
5960
5961
5962
5963


5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978







-
-
+
+
+
+
+
+
+
+








    /* If this is a prefix query, check that the results returned if the
    ** the index is disabled are the same. In both ASC and DESC order. 
    **
    ** This check may only be performed if the hash table is empty. This
    ** is because the hash table only supports a single scan query at
    ** a time, and the multi-iter loop from which this function is called
    ** is already performing such a scan. */
    if( p->nPendingData==0 ){
    ** is already performing such a scan. 
    **
    ** Also only do this if buffer zTerm contains nTerm bytes of valid
    ** utf-8. Otherwise, the last part of the buffer contents might contain
    ** a non-utf-8 sequence that happens to be a prefix of a valid utf-8
    ** character stored in the main fts index, which will cause the
    ** test to fail.  */
    if( p->nPendingData==0 && 0==fts5TestUtf8(zTerm, nTerm) ){
      if( iIdx>0 && rc==SQLITE_OK ){
        int f = flags|FTS5INDEX_QUERY_TEST_NOIDX;
        ck2 = 0;
        rc = fts5QueryCksum(p, iIdx, zTerm, nTerm, f, &ck2);
        if( rc==SQLITE_OK && ck1!=ck2 ) rc = FTS5_CORRUPT;
      }
      if( iIdx>0 && rc==SQLITE_OK ){
5825
5826
5827
5828
5829
5830
5831
5832


5833
5834
5835
5836
5837
5838
5839
5840

5841
5842
5843
5844
5845
5846
5847
5848
5849
6087
6088
6089
6090
6091
6092
6093

6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105

6106
6107
6108
6109
6110
6111
6112







-
+
+








+

-







  int rc2;
  int iIdxPrevLeaf = pSeg->pgnoFirst-1;
  int iDlidxPrevLeaf = pSeg->pgnoLast;

  if( pSeg->pgnoFirst==0 ) return;

  fts5IndexPrepareStmt(p, &pStmt, sqlite3_mprintf(
      "SELECT segid, term, (pgno>>1), (pgno&1) FROM %Q.'%q_idx' WHERE segid=%d",
      "SELECT segid, term, (pgno>>1), (pgno&1) FROM %Q.'%q_idx' WHERE segid=%d "
      "ORDER BY 1, 2",
      pConfig->zDb, pConfig->zName, pSeg->iSegid
  ));

  /* Iterate through the b-tree hierarchy.  */
  while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
    i64 iRow;                     /* Rowid for this leaf */
    Fts5Data *pLeaf;              /* Data for this leaf */

    const char *zIdxTerm = (const char*)sqlite3_column_blob(pStmt, 1);
    int nIdxTerm = sqlite3_column_bytes(pStmt, 1);
    const char *zIdxTerm = (const char*)sqlite3_column_text(pStmt, 1);
    int iIdxLeaf = sqlite3_column_int(pStmt, 2);
    int bIdxDlidx = sqlite3_column_int(pStmt, 3);

    /* If the leaf in question has already been trimmed from the segment, 
    ** ignore this b-tree entry. Otherwise, load it into memory. */
    if( iIdxLeaf<pSeg->pgnoFirst ) continue;
    iRow = FTS5_SEGMENT_ROWID(pSeg->iSegid, iIdxLeaf);
5860
5861
5862
5863
5864
5865
5866
5867

5868
5869
5870
5871

5872
5873
5874
5875
5876
5877
5878
6123
6124
6125
6126
6127
6128
6129

6130
6131
6132
6133

6134
6135
6136
6137
6138
6139
6140
6141







-
+



-
+







      int iOff;                   /* Offset of first term on leaf */
      int iRowidOff;              /* Offset of first rowid on leaf */
      int nTerm;                  /* Size of term on leaf in bytes */
      int res;                    /* Comparison of term and split-key */

      iOff = fts5LeafFirstTermOff(pLeaf);
      iRowidOff = fts5LeafFirstRowidOff(pLeaf);
      if( iRowidOff>=iOff ){
      if( iRowidOff>=iOff || iOff>=pLeaf->szLeaf ){
        p->rc = FTS5_CORRUPT;
      }else{
        iOff += fts5GetVarint32(&pLeaf->p[iOff], nTerm);
        res = memcmp(&pLeaf->p[iOff], zIdxTerm, MIN(nTerm, nIdxTerm));
        res = fts5Memcmp(&pLeaf->p[iOff], zIdxTerm, MIN(nTerm, nIdxTerm));
        if( res==0 ) res = nTerm - nIdxTerm;
        if( res<0 ) p->rc = FTS5_CORRUPT;
      }

      fts5IntegrityCheckPgidx(p, pLeaf);
    }
    fts5DataRelease(pLeaf);
5956
5957
5958
5959
5960
5961
5962
5963

5964
5965
5966
5967
5968

5969
5970
5971
5972
5973
5974
5975
5976
5977
5978



5979


5980
5981
5982
5983
5984
5985
5986




5987
5988
5989
5990
5991
5992
5993
5994
6219
6220
6221
6222
6223
6224
6225

6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245

6246
6247
6248






6249
6250
6251
6252

6253
6254
6255
6256
6257
6258
6259







-
+





+










+
+
+
-
+
+

-
-
-
-
-
-
+
+
+
+
-







** as calculated by sqlite3Fts5IndexEntryCksum() is cksum.
**
** Return SQLITE_CORRUPT if any of the internal checks fail, or if the
** checksum does not match. Return SQLITE_OK if all checks pass without
** error, or some other SQLite error code if another error (e.g. OOM)
** occurs.
*/
int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum){
int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int bUseCksum){
  int eDetail = p->pConfig->eDetail;
  u64 cksum2 = 0;                 /* Checksum based on contents of indexes */
  Fts5Buffer poslist = {0,0,0};   /* Buffer used to hold a poslist */
  Fts5Iter *pIter;                /* Used to iterate through entire index */
  Fts5Structure *pStruct;         /* Index structure */
  int iLvl, iSeg;

#ifdef SQLITE_DEBUG
  /* Used by extra internal tests only run if NDEBUG is not defined */
  u64 cksum3 = 0;                 /* Checksum based on contents of indexes */
  Fts5Buffer term = {0,0,0};      /* Buffer used to hold most recent term */
#endif
  const int flags = FTS5INDEX_QUERY_NOOUTPUT;
  
  /* Load the FTS index structure */
  pStruct = fts5StructureRead(p);
  if( pStruct==0 ){
    assert( p->rc!=SQLITE_OK );
    return fts5IndexReturn(p);

  }

  /* Check that the internal nodes of each segment match the leaves */
  if( pStruct ){
    int iLvl, iSeg;
    for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
      for(iSeg=0; iSeg<pStruct->aLevel[iLvl].nSeg; iSeg++){
        Fts5StructureSegment *pSeg = &pStruct->aLevel[iLvl].aSeg[iSeg];
        fts5IndexIntegrityCheckSegment(p, pSeg);
  for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
    for(iSeg=0; iSeg<pStruct->aLevel[iLvl].nSeg; iSeg++){
      Fts5StructureSegment *pSeg = &pStruct->aLevel[iLvl].aSeg[iSeg];
      fts5IndexIntegrityCheckSegment(p, pSeg);
      }
    }
  }

  /* The cksum argument passed to this function is a checksum calculated
  ** based on all expected entries in the FTS index (including prefix index
  ** entries). This block checks that a checksum calculated based on the
  ** actual contents of FTS index is identical.
6009
6010
6011
6012
6013
6014
6015

6016
6017
6018
6019
6020
6021
6022
6023

6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034

6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049

6050
6051
6052
6053
6054
6055
6056
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300

6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324







+








+










-
+















+







    i64 iPos = 0;               /* Position read from poslist */
    int iOff = 0;               /* Offset within poslist */
    i64 iRowid = fts5MultiIterRowid(pIter);
    char *z = (char*)fts5MultiIterTerm(pIter, &n);

    /* If this is a new term, query for it. Update cksum3 with the results. */
    fts5TestTerm(p, &term, z, n, cksum2, &cksum3);
    if( p->rc ) break;

    if( eDetail==FTS5_DETAIL_NONE ){
      if( 0==fts5MultiIterIsEmpty(p, pIter) ){
        cksum2 ^= sqlite3Fts5IndexEntryCksum(iRowid, 0, 0, -1, z, n);
      }
    }else{
      poslist.n = 0;
      fts5SegiterPoslist(p, &pIter->aSeg[pIter->aFirst[1].iFirst], 0, &poslist);
      fts5BufferAppendBlob(&p->rc, &poslist, 4, (const u8*)"\0\0\0\0");
      while( 0==sqlite3Fts5PoslistNext64(poslist.p, poslist.n, &iOff, &iPos) ){
        int iCol = FTS5_POS2COLUMN(iPos);
        int iTokOff = FTS5_POS2OFFSET(iPos);
        cksum2 ^= sqlite3Fts5IndexEntryCksum(iRowid, iCol, iTokOff, -1, z, n);
      }
    }
  }
  fts5TestTerm(p, &term, 0, 0, cksum2, &cksum3);

  fts5MultiIterFree(pIter);
  if( p->rc==SQLITE_OK && cksum!=cksum2 ) p->rc = FTS5_CORRUPT;
  if( p->rc==SQLITE_OK && bUseCksum && cksum!=cksum2 ) p->rc = FTS5_CORRUPT;

  fts5StructureRelease(pStruct);
#ifdef SQLITE_DEBUG
  fts5BufferFree(&term);
#endif
  fts5BufferFree(&poslist);
  return fts5IndexReturn(p);
}

/*************************************************************************
**************************************************************************
** 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 */
6065
6066
6067
6068
6069
6070
6071

6072

6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089

6090

6091
6092
6093
6094
6095
6096
6097
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369







+

+

















+

+







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

6105
6106
6107
6108
6109
6110
6111

6112

6113
6114
6115
6116
6117
6118
6119
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393







+

+







      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. 
*/
6130
6131
6132
6133
6134
6135
6136

6137

6138
6139
6140
6141
6142
6143
6144
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420







+

+







    *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. 
*/
6153
6154
6155
6156
6157
6158
6159

6160

6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176

6177

6178
6179
6180
6181
6182
6183
6184
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







+

+
















+

+







  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.
6203
6204
6205
6206
6207
6208
6209

6210

6211
6212
6213
6214
6215
6216
6217
6483
6484
6485
6486
6487
6488
6489
6490
6491
6492
6493
6494
6495
6496
6497
6498
6499







+

+







      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.
6244
6245
6246
6247
6248
6249
6250

6251

6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266

6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282

6283
6284
6285
6286
6287
6288
6289
6290
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







+

+














-
+















-
+
-







        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 */
){
  i64 iRowid;                     /* Rowid for record being decoded */
  int iSegid,iHeight,iPgno,bDlidx;/* Rowid components */
  const u8 *aBlob; int n;         /* Record to decode */
  u8 *a = 0;
  Fts5Buffer s;                   /* Build up text to return here */
  int rc = SQLITE_OK;             /* Return code */
  int nSpace = 0;
  sqlite3_int64 nSpace = 0;
  int eDetailNone = (sqlite3_user_data(pCtx)!=0);

  assert( nArg==2 );
  UNUSED_PARAM(nArg);
  memset(&s, 0, sizeof(Fts5Buffer));
  iRowid = sqlite3_value_int64(apVal[0]);

  /* Make a copy of the second argument (a blob) in aBlob[]. The aBlob[]
  ** copy is followed by FTS5_DATA_ZERO_PADDING 0x00 bytes, which prevents
  ** buffer overreads even if the record is corrupt.  */
  n = sqlite3_value_bytes(apVal[1]);
  aBlob = sqlite3_value_blob(apVal[1]);
  nSpace = n + FTS5_DATA_ZERO_PADDING;
  a = (u8*)sqlite3Fts5MallocZero(&rc, nSpace);
  if( a==0 ) goto decode_out;
  memcpy(a, aBlob, n);
  if( n>0 ) memcpy(a, aBlob, n);


  fts5DecodeRowid(iRowid, &iSegid, &bDlidx, &iHeight, &iPgno);

  fts5DebugRowid(&rc, &s, iRowid);
  if( bDlidx ){
    Fts5Data dlidx;
    Fts5DlidxLvl lvl;
6371
6372
6373
6374
6375
6376
6377



6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388




6389
6390
6391
6392
6393




6394
6395
6396

6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410




6411
6412
6413




6414
6415
6416




6417
6418
6419
6420
6421
6422
6423
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
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
6710
6711
6712
6713
6714
6715
6716
6717
6718
6719
6720
6721
6722
6723
6724
6725
6726
6727
6728
6729







+
+
+











+
+
+
+





+
+
+
+


-
+














+
+
+
+



+
+
+
+



+
+
+
+







      sqlite3Fts5BufferSet(&rc, &s, 7, (const u8*)"corrupt");
      goto decode_out;
    }else{
      iRowidOff = fts5GetU16(&a[0]);
      iPgidxOff = szLeaf = fts5GetU16(&a[2]);
      if( iPgidxOff<n ){
        fts5GetVarint32(&a[iPgidxOff], iTermOff);
      }else if( iPgidxOff>n ){
        rc = FTS5_CORRUPT;
        goto decode_out;
      }
    }

    /* Decode the position list tail at the start of the page */
    if( iRowidOff!=0 ){
      iOff = iRowidOff;
    }else if( iTermOff!=0 ){
      iOff = iTermOff;
    }else{
      iOff = szLeaf;
    }
    if( iOff>n ){
      rc = FTS5_CORRUPT;
      goto decode_out;
    }
    fts5DecodePoslist(&rc, &s, &a[4], iOff-4);

    /* Decode any more doclist data that appears on the page before the
    ** first term. */
    nDoclist = (iTermOff ? iTermOff : szLeaf) - iOff;
    if( nDoclist+iOff>n ){
      rc = FTS5_CORRUPT;
      goto decode_out;
    }
    fts5DecodeDoclist(&rc, &s, &a[iOff], nDoclist);

    while( iPgidxOff<n ){
    while( iPgidxOff<n && rc==SQLITE_OK ){
      int bFirst = (iPgidxOff==szLeaf);     /* True for first term on page */
      int nByte;                            /* Bytes of data */
      int iEnd;
      
      iPgidxOff += fts5GetVarint32(&a[iPgidxOff], nByte);
      iPgidxPrev += nByte;
      iOff = iPgidxPrev;

      if( iPgidxOff<n ){
        fts5GetVarint32(&a[iPgidxOff], nByte);
        iEnd = iPgidxPrev + nByte;
      }else{
        iEnd = szLeaf;
      }
      if( iEnd>szLeaf ){
        rc = FTS5_CORRUPT;
        break;
      }

      if( bFirst==0 ){
        iOff += fts5GetVarint32(&a[iOff], nByte);
        if( nByte>term.n ){
          rc = FTS5_CORRUPT;
          break;
        }
        term.n = nByte;
      }
      iOff += fts5GetVarint32(&a[iOff], nByte);
      if( iOff+nByte>n ){
        rc = FTS5_CORRUPT;
        break;
      }
      fts5BufferAppendBlob(&rc, &term, nByte, &a[iOff]);
      iOff += nByte;

      sqlite3Fts5BufferAppendPrintf(
          &rc, &s, " term=%.*s", term.n, (const char*)term.p
      );
      iOff += fts5DecodeDoclist(&rc, &s, &a[iOff], iEnd-iOff);
6431
6432
6433
6434
6435
6436
6437

6438

6439
6440
6441
6442
6443
6444
6445
6737
6738
6739
6740
6741
6742
6743
6744
6745
6746
6747
6748
6749
6750
6751
6752
6753







+

+







  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 */
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
6773
6774
6775
6776
6777
6778
6779
6780
6781
6782
6783
6784
6785
6786
6787
6788
6789
6790
6791
6792
6793
6794
6795
6796
6797
6798
6799
6800
6801
6802
6803
6804
6805
6806
6807
6808
6809
6810
6811
6812
6813
6814
6815
6816
6817
6818
6819
6820
6821
6822







+










+

















+
+
+
+










    }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


33
34
35
36
37
38
39
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32


33
34
35
36
37
38
39
40
41







+

+





-
-
+
+








/*
** 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 Fts5Sorter Fts5Sorter;
typedef struct Fts5Table Fts5Table;
typedef struct Fts5FullTable Fts5FullTable;
typedef struct Fts5Sorter Fts5Sorter;
typedef struct Fts5TokenizerModule Fts5TokenizerModule;

/*
** NOTES ON TRANSACTIONS: 
**
** SQLite invokes the following virtual table methods as transactions are 
** opened and closed by the user:
106
107
108
109
110
111
112
113
114
115
116

117
118
119

120
121
122
123
124
125
126
108
109
110
111
112
113
114




115



116
117
118
119
120
121
122
123







-
-
-
-
+
-
-
-
+







  char *zName;                    /* Name of tokenizer */
  void *pUserData;                /* User pointer passed to xCreate() */
  fts5_tokenizer x;               /* Tokenizer functions */
  void (*xDestroy)(void*);        /* Destructor function */
  Fts5TokenizerModule *pNext;     /* Next registered tokenizer module */
};

/*
** Virtual-table object.
*/
struct Fts5Table {
struct Fts5FullTable {
  sqlite3_vtab base;              /* Base class used by SQLite core */
  Fts5Config *pConfig;            /* Virtual table configuration */
  Fts5Index *pIndex;              /* Full-text index */
  Fts5Table p;                    /* Public class members from fts5Int.h */
  Fts5Storage *pStorage;          /* Document store */
  Fts5Global *pGlobal;            /* Global (connection wide) data */
  Fts5Cursor *pSortCsr;           /* Sort data from this cursor */
#ifdef SQLITE_DEBUG
  struct Fts5TransactionState ts;
#endif
};
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
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







-
+








-
+














-
+






-
+






-
-
-
+
+
+
+
+
+











-
-
+
+





-
+

-
+

-
+








-
+










-
+







#define FTS5_BEGIN      1
#define FTS5_SYNC       2
#define FTS5_COMMIT     3
#define FTS5_ROLLBACK   4
#define FTS5_SAVEPOINT  5
#define FTS5_RELEASE    6
#define FTS5_ROLLBACKTO 7
static void fts5CheckTransactionState(Fts5Table *p, int op, int iSavepoint){
static void fts5CheckTransactionState(Fts5FullTable *p, int op, int iSavepoint){
  switch( op ){
    case FTS5_BEGIN:
      assert( p->ts.eState==0 );
      p->ts.eState = 1;
      p->ts.iSavepoint = -1;
      break;

    case FTS5_SYNC:
      assert( p->ts.eState==1 );
      assert( p->ts.eState==1 || p->ts.eState==2 );
      p->ts.eState = 2;
      break;

    case FTS5_COMMIT:
      assert( p->ts.eState==2 );
      p->ts.eState = 0;
      break;

    case FTS5_ROLLBACK:
      assert( p->ts.eState==1 || p->ts.eState==2 || p->ts.eState==0 );
      p->ts.eState = 0;
      break;

    case FTS5_SAVEPOINT:
      assert( p->ts.eState==1 );
      assert( p->ts.eState>=1 );
      assert( iSavepoint>=0 );
      assert( iSavepoint>=p->ts.iSavepoint );
      p->ts.iSavepoint = iSavepoint;
      break;
      
    case FTS5_RELEASE:
      assert( p->ts.eState==1 );
      assert( p->ts.eState>=1 );
      assert( iSavepoint>=0 );
      assert( iSavepoint<=p->ts.iSavepoint );
      p->ts.iSavepoint = iSavepoint-1;
      break;

    case FTS5_ROLLBACKTO:
      assert( p->ts.eState==1 );
      assert( iSavepoint>=0 );
      assert( iSavepoint<=p->ts.iSavepoint );
      assert( p->ts.eState>=1 );
      assert( iSavepoint>=-1 );
      /* The following assert() can fail if another vtab strikes an error
      ** within an xSavepoint() call then SQLite calls xRollbackTo() - without
      ** having called xSavepoint() on this vtab.  */
      /* assert( iSavepoint<=p->ts.iSavepoint ); */
      p->ts.iSavepoint = iSavepoint;
      break;
  }
}
#else
# define fts5CheckTransactionState(x,y,z)
#endif

/*
** Return true if pTab is a contentless table.
*/
static int fts5IsContentless(Fts5Table *pTab){
  return pTab->pConfig->eContent==FTS5_CONTENT_NONE;
static int fts5IsContentless(Fts5FullTable *pTab){
  return pTab->p.pConfig->eContent==FTS5_CONTENT_NONE;
}

/*
** Delete a virtual table handle allocated by fts5InitVtab(). 
*/
static void fts5FreeVtab(Fts5Table *pTab){
static void fts5FreeVtab(Fts5FullTable *pTab){
  if( pTab ){
    sqlite3Fts5IndexClose(pTab->pIndex);
    sqlite3Fts5IndexClose(pTab->p.pIndex);
    sqlite3Fts5StorageClose(pTab->pStorage);
    sqlite3Fts5ConfigFree(pTab->pConfig);
    sqlite3Fts5ConfigFree(pTab->p.pConfig);
    sqlite3_free(pTab);
  }
}

/*
** The xDisconnect() virtual table method.
*/
static int fts5DisconnectMethod(sqlite3_vtab *pVtab){
  fts5FreeVtab((Fts5Table*)pVtab);
  fts5FreeVtab((Fts5FullTable*)pVtab);
  return SQLITE_OK;
}

/*
** The xDestroy() virtual table method.
*/
static int fts5DestroyMethod(sqlite3_vtab *pVtab){
  Fts5Table *pTab = (Fts5Table*)pVtab;
  int rc = sqlite3Fts5DropAll(pTab->pConfig);
  if( rc==SQLITE_OK ){
    fts5FreeVtab((Fts5Table*)pVtab);
    fts5FreeVtab((Fts5FullTable*)pVtab);
  }
  return rc;
}

/*
** This function is the implementation of both the xConnect and xCreate
** methods of the FTS3 virtual table.
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
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







-
+


-
+





-
+





-
+





-
+












-
-
+
+







  sqlite3_vtab **ppVTab,          /* Write the resulting vtab structure here */
  char **pzErr                    /* Write any error message here */
){
  Fts5Global *pGlobal = (Fts5Global*)pAux;
  const char **azConfig = (const char**)argv;
  int rc = SQLITE_OK;             /* Return code */
  Fts5Config *pConfig = 0;        /* Results of parsing argc/argv */
  Fts5Table *pTab = 0;            /* New virtual table object */
  Fts5FullTable *pTab = 0;        /* New virtual table object */

  /* Allocate the new vtab object and parse the configuration */
  pTab = (Fts5Table*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Table));
  pTab = (Fts5FullTable*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5FullTable));
  if( rc==SQLITE_OK ){
    rc = sqlite3Fts5ConfigParse(pGlobal, db, argc, azConfig, &pConfig, pzErr);
    assert( (rc==SQLITE_OK && *pzErr==0) || pConfig==0 );
  }
  if( rc==SQLITE_OK ){
    pTab->pConfig = pConfig;
    pTab->p.pConfig = pConfig;
    pTab->pGlobal = pGlobal;
  }

  /* Open the index sub-system */
  if( rc==SQLITE_OK ){
    rc = sqlite3Fts5IndexOpen(pConfig, bCreate, &pTab->pIndex, pzErr);
    rc = sqlite3Fts5IndexOpen(pConfig, bCreate, &pTab->p.pIndex, pzErr);
  }

  /* Open the storage sub-system */
  if( rc==SQLITE_OK ){
    rc = sqlite3Fts5StorageOpen(
        pConfig, pTab->pIndex, bCreate, &pTab->pStorage, pzErr
        pConfig, pTab->p.pIndex, bCreate, &pTab->pStorage, pzErr
    );
  }

  /* Call sqlite3_declare_vtab() */
  if( rc==SQLITE_OK ){
    rc = sqlite3Fts5ConfigDeclareVtab(pConfig);
  }

  /* Load the initial configuration */
  if( rc==SQLITE_OK ){
    assert( pConfig->pzErrmsg==0 );
    pConfig->pzErrmsg = pzErr;
    rc = sqlite3Fts5IndexLoadConfig(pTab->pIndex);
    sqlite3Fts5IndexRollback(pTab->pIndex);
    rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex);
    sqlite3Fts5IndexRollback(pTab->p.pIndex);
    pConfig->pzErrmsg = 0;
  }

  if( rc!=SQLITE_OK ){
    fts5FreeVtab(pTab);
    pTab = 0;
  }else if( bCreate ){
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
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







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





-
+

+
-
-
-
+
+
+

-
+



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







  if( sqlite3_libversion_number()>=3008012 )
#endif
  {
    pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_UNIQUE;
  }
#endif
}

static int fts5UsePatternMatch(
  Fts5Config *pConfig, 
  struct sqlite3_index_constraint *p
){
  assert( FTS5_PATTERN_GLOB==SQLITE_INDEX_CONSTRAINT_GLOB );
  assert( FTS5_PATTERN_LIKE==SQLITE_INDEX_CONSTRAINT_LIKE );
  if( pConfig->ePattern==FTS5_PATTERN_GLOB && p->op==FTS5_PATTERN_GLOB ){
    return 1;
  }
  if( pConfig->ePattern==FTS5_PATTERN_LIKE 
   && (p->op==FTS5_PATTERN_LIKE || p->op==FTS5_PATTERN_GLOB)
  ){
    return 1;
  }
  return 0;
}

/*
** Implementation of the xBestIndex method for FTS5 tables. Within the 
** WHERE constraint, it searches for the following:
**
**   1. A MATCH constraint against the special column.
**   1. A MATCH constraint against the table column.
**   2. A MATCH constraint against the "rank" column.
**   3. A MATCH constraint against some other column.
**   3. An == constraint against the rowid column.
**   4. A < or <= constraint against the rowid column.
**   5. A > or >= constraint against the rowid column.
**   4. An == constraint against the rowid column.
**   5. A < or <= constraint against the rowid column.
**   6. A > or >= constraint against the rowid column.
**
** Within the ORDER BY, either:
** Within the ORDER BY, the following are supported:
**
**   5. ORDER BY rank [ASC|DESC]
**   6. ORDER BY rowid [ASC|DESC]
**
** Information for the xFilter call is passed via both the idxNum and 
** idxStr variables. Specifically, idxNum is a bitmask of the following
** flags used to encode the ORDER BY clause:
**
**     FTS5_BI_ORDER_RANK
**     FTS5_BI_ORDER_ROWID
**     FTS5_BI_ORDER_DESC
**
** idxStr is used to encode data from the WHERE clause. For each argument
** passed to the xFilter method, the following is appended to idxStr:
**
**   Match against table column:            "m"
**   Match against rank column:             "r"
**   Match against other column:            "M<column-number>"
**   LIKE  against other column:            "L<column-number>"
**   GLOB  against other column:            "G<column-number>"
**   Equality constraint against the rowid: "="
**   A < or <= against the rowid:           "<"
**   A > or >= against the rowid:           ">"
**
** This function ensures that there is at most one "r" or "=". And that if
** there exists an "=" then there is no "<" or ">".
**
** Costs are assigned as follows:
**
**  a) If an unusable MATCH operator is present in the WHERE clause, the
**     cost is unconditionally set to 1e50 (a really big number).
**
**  a) If a MATCH operator is present, the cost depends on the other
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
638

639
640
641

642
643
644
645
646
647
648
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652

653
654
655
656
657
658
659
660
661
662
663
664
665
666








667
668
669
670
671
672
673
674

675










676
677
678
679
680
681

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


694
695
696

697
698
699
700
701
702

703
704
705

706
707
708
709
710
711
712
713







-
-


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

-
-
-
-
+
+
+
+
+
+







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



-
-
-
+
+


-
+
-
-
-



+
+

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




+




-
+













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

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






-
+











-
-
+
+

-
+





-
+


-
+







** Costs are not modified by the ORDER BY clause.
*/
static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
  Fts5Table *pTab = (Fts5Table*)pVTab;
  Fts5Config *pConfig = pTab->pConfig;
  const int nCol = pConfig->nCol;
  int idxFlags = 0;               /* Parameter passed through to xFilter() */
  int bHasMatch;
  int iNext;
  int i;

  struct Constraint {
  char *idxStr;
    int op;                       /* Mask against sqlite3_index_constraint.op */
    int fts5op;                   /* FTS5 mask for idxFlags */
    int iCol;                     /* 0==rowid, 1==tbl, 2==rank */
  int iIdxStr = 0;
    int omit;                     /* True to omit this if found */
    int iConsIndex;               /* Index in pInfo->aConstraint[] */
  int iCons = 0;
  } aConstraint[] = {
    {SQLITE_INDEX_CONSTRAINT_MATCH|SQLITE_INDEX_CONSTRAINT_EQ, 
                                    FTS5_BI_MATCH,    1, 1, -1},
    {SQLITE_INDEX_CONSTRAINT_MATCH|SQLITE_INDEX_CONSTRAINT_EQ, 
                                    FTS5_BI_RANK,     2, 1, -1},
    {SQLITE_INDEX_CONSTRAINT_EQ,    FTS5_BI_ROWID_EQ, 0, 0, -1},
    {SQLITE_INDEX_CONSTRAINT_LT|SQLITE_INDEX_CONSTRAINT_LE, 
                                    FTS5_BI_ROWID_LE, 0, 0, -1},
    {SQLITE_INDEX_CONSTRAINT_GT|SQLITE_INDEX_CONSTRAINT_GE, 
                                    FTS5_BI_ROWID_GE, 0, 0, -1},
  };

  int aColMap[3];
  aColMap[0] = -1;
  aColMap[1] = nCol;
  aColMap[2] = nCol+1;
  int bSeenEq = 0;
  int bSeenGt = 0;
  int bSeenLt = 0;
  int bSeenMatch = 0;
  int bSeenRank = 0;


  assert( SQLITE_INDEX_CONSTRAINT_EQ<SQLITE_INDEX_CONSTRAINT_MATCH );
  assert( SQLITE_INDEX_CONSTRAINT_GT<SQLITE_INDEX_CONSTRAINT_MATCH );
  assert( SQLITE_INDEX_CONSTRAINT_LE<SQLITE_INDEX_CONSTRAINT_MATCH );
  assert( SQLITE_INDEX_CONSTRAINT_GE<SQLITE_INDEX_CONSTRAINT_MATCH );
  assert( SQLITE_INDEX_CONSTRAINT_LE<SQLITE_INDEX_CONSTRAINT_MATCH );

  if( pConfig->bLock ){
    pTab->base.zErrMsg = sqlite3_mprintf(
        "recursively defined fts5 content table"
    );
    return SQLITE_ERROR;
  }
  /* Set idxFlags flags for all WHERE clause terms that will be used. */

  idxStr = (char*)sqlite3_malloc(pInfo->nConstraint * 8 + 1);
  if( idxStr==0 ) return SQLITE_NOMEM;
  pInfo->idxStr = idxStr;
  pInfo->needToFreeIdxStr = 1;

  for(i=0; i<pInfo->nConstraint; i++){
    struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
    int iCol = p->iColumn;

    if( (p->op==SQLITE_INDEX_CONSTRAINT_MATCH && iCol>=0 && iCol<=nCol)
     || (p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol==nCol)
    if( p->op==SQLITE_INDEX_CONSTRAINT_MATCH
     || (p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol>=nCol)
    ){
      /* A MATCH operator or equivalent */
      if( p->usable ){
      if( p->usable==0 || iCol<0 ){
        idxFlags = (idxFlags & 0xFFFF) | FTS5_BI_MATCH | (iCol << 16);
        aConstraint[0].iConsIndex = i;
      }else{
        /* As there exists an unusable MATCH constraint this is an 
        ** unusable plan. Set a prohibitively high cost. */
        pInfo->estimatedCost = 1e50;
        assert( iIdxStr < pInfo->nConstraint*6 + 1 );
        idxStr[iIdxStr] = 0;
        return SQLITE_OK;
      }else{
        if( iCol==nCol+1 ){
          if( bSeenRank ) continue;
          idxStr[iIdxStr++] = 'r';
          bSeenRank = 1;
        }else if( iCol>=0 ){
          bSeenMatch = 1;
          idxStr[iIdxStr++] = 'M';
          sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
          idxStr += strlen(&idxStr[iIdxStr]);
          assert( idxStr[iIdxStr]=='\0' );
      }
    }else if( p->op<=SQLITE_INDEX_CONSTRAINT_MATCH ){
      int j;
      for(j=1; j<ArraySize(aConstraint); j++){
        struct Constraint *pC = &aConstraint[j];
        if( iCol==aColMap[pC->iCol] && (p->op & pC->op) && p->usable ){
          pC->iConsIndex = i;
          idxFlags |= pC->fts5op;
        }
        pInfo->aConstraintUsage[i].argvIndex = ++iCons;
        pInfo->aConstraintUsage[i].omit = 1;
      }
    }else if( p->usable ){
      if( iCol>=0 && iCol<nCol && fts5UsePatternMatch(pConfig, p) ){
        assert( p->op==FTS5_PATTERN_LIKE || p->op==FTS5_PATTERN_GLOB );
        idxStr[iIdxStr++] = p->op==FTS5_PATTERN_LIKE ? 'L' : 'G';
        sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
        idxStr += strlen(&idxStr[iIdxStr]);
        pInfo->aConstraintUsage[i].argvIndex = ++iCons;
        assert( idxStr[iIdxStr]=='\0' );
      }else if( bSeenEq==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol<0 ){
        idxStr[iIdxStr++] = '=';
        bSeenEq = 1;
        pInfo->aConstraintUsage[i].argvIndex = ++iCons;
      }
    }
  }

  if( bSeenEq==0 ){
    for(i=0; i<pInfo->nConstraint; i++){
      struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
      if( p->iColumn<0 && p->usable ){
        int op = p->op;
        if( op==SQLITE_INDEX_CONSTRAINT_LT || op==SQLITE_INDEX_CONSTRAINT_LE ){
          if( bSeenLt ) continue;
          idxStr[iIdxStr++] = '<';
          pInfo->aConstraintUsage[i].argvIndex = ++iCons;
          bSeenLt = 1;
        }else
        if( op==SQLITE_INDEX_CONSTRAINT_GT || op==SQLITE_INDEX_CONSTRAINT_GE ){
          if( bSeenGt ) continue;
          idxStr[iIdxStr++] = '>';
          pInfo->aConstraintUsage[i].argvIndex = ++iCons;
          bSeenGt = 1;
        }
      }
    }
  }
  idxStr[iIdxStr] = '\0';

  /* Set idxFlags flags for the ORDER BY clause */
  if( pInfo->nOrderBy==1 ){
    int iSort = pInfo->aOrderBy[0].iColumn;
    if( iSort==(pConfig->nCol+1) && BitFlagTest(idxFlags, FTS5_BI_MATCH) ){
    if( iSort==(pConfig->nCol+1) && bSeenMatch ){
      idxFlags |= FTS5_BI_ORDER_RANK;
    }else if( iSort==-1 ){
      idxFlags |= FTS5_BI_ORDER_ROWID;
    }
    if( BitFlagTest(idxFlags, FTS5_BI_ORDER_RANK|FTS5_BI_ORDER_ROWID) ){
      pInfo->orderByConsumed = 1;
      if( pInfo->aOrderBy[0].desc ){
        idxFlags |= FTS5_BI_ORDER_DESC;
      }
    }
  }

  /* Calculate the estimated cost based on the flags set in idxFlags. */
  bHasMatch = BitFlagTest(idxFlags, FTS5_BI_MATCH);
  if( BitFlagTest(idxFlags, FTS5_BI_ROWID_EQ) ){
    pInfo->estimatedCost = bHasMatch ? 100.0 : 10.0;
    if( bHasMatch==0 ) fts5SetUniqueFlag(pInfo);
  }else if( BitFlagAllTest(idxFlags, FTS5_BI_ROWID_LE|FTS5_BI_ROWID_GE) ){
    pInfo->estimatedCost = bHasMatch ? 500.0 : 250000.0;
  }else if( BitFlagTest(idxFlags, FTS5_BI_ROWID_LE|FTS5_BI_ROWID_GE) ){
    pInfo->estimatedCost = bHasMatch ? 750.0 : 750000.0;
  if( bSeenEq ){
    pInfo->estimatedCost = bSeenMatch ? 100.0 : 10.0;
    if( bSeenMatch==0 ) fts5SetUniqueFlag(pInfo);
  }else if( bSeenLt && bSeenGt ){
    pInfo->estimatedCost = bSeenMatch ? 500.0 : 250000.0;
  }else if( bSeenLt || bSeenGt ){
    pInfo->estimatedCost = bSeenMatch ? 750.0 : 750000.0;
  }else{
    pInfo->estimatedCost = bHasMatch ? 1000.0 : 1000000.0;
    pInfo->estimatedCost = bSeenMatch ? 1000.0 : 1000000.0;
  }

  /* Assign argvIndex values to each constraint in use. */
  iNext = 1;
  for(i=0; i<ArraySize(aConstraint); i++){
    struct Constraint *pC = &aConstraint[i];
    if( pC->iConsIndex>=0 ){
      pInfo->aConstraintUsage[pC->iConsIndex].argvIndex = iNext++;
      pInfo->aConstraintUsage[pC->iConsIndex].omit = (unsigned char)pC->omit;
    }
  }

  pInfo->idxNum = idxFlags;
  return SQLITE_OK;
}

static int fts5NewTransaction(Fts5Table *pTab){
static int fts5NewTransaction(Fts5FullTable *pTab){
  Fts5Cursor *pCsr;
  for(pCsr=pTab->pGlobal->pCsr; pCsr; pCsr=pCsr->pNext){
    if( pCsr->base.pVtab==(sqlite3_vtab*)pTab ) return SQLITE_OK;
  }
  return sqlite3Fts5StorageReset(pTab->pStorage);
}

/*
** Implementation of xOpen method.
*/
static int fts5OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
  Fts5Table *pTab = (Fts5Table*)pVTab;
  Fts5Config *pConfig = pTab->pConfig;
  Fts5FullTable *pTab = (Fts5FullTable*)pVTab;
  Fts5Config *pConfig = pTab->p.pConfig;
  Fts5Cursor *pCsr = 0;           /* New cursor object */
  int nByte;                      /* Bytes of space to allocate */
  sqlite3_int64 nByte;            /* Bytes of space to allocate */
  int rc;                         /* Return code */

  rc = fts5NewTransaction(pTab);
  if( rc==SQLITE_OK ){
    nByte = sizeof(Fts5Cursor) + pConfig->nCol * sizeof(int);
    pCsr = (Fts5Cursor*)sqlite3_malloc(nByte);
    pCsr = (Fts5Cursor*)sqlite3_malloc64(nByte);
    if( pCsr ){
      Fts5Global *pGlobal = pTab->pGlobal;
      memset(pCsr, 0, nByte);
      memset(pCsr, 0, (size_t)nByte);
      pCsr->aColumnSize = (int*)&pCsr[1];
      pCsr->pNext = pGlobal->pCsr;
      pGlobal->pCsr = pCsr;
      pCsr->iCsrId = ++pGlobal->iNextId;
    }else{
      rc = SQLITE_NOMEM;
    }
669
670
671
672
673
674
675
676

677
678
679
680
681
682
683
734
735
736
737
738
739
740

741
742
743
744
745
746
747
748







-
+







    | FTS5CSR_REQUIRE_DOCSIZE 
    | FTS5CSR_REQUIRE_INST 
    | FTS5CSR_REQUIRE_POSLIST 
  );
}

static void fts5FreeCursorComponents(Fts5Cursor *pCsr){
  Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
  Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
  Fts5Auxdata *pData;
  Fts5Auxdata *pNext;

  sqlite3_free(pCsr->aInstIter);
  sqlite3_free(pCsr->aInst);
  if( pCsr->pStmt ){
    int eStmt = fts5StmtType(pCsr);
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
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







+










-
+




















-
+







  sqlite3_free(pCsr->apRankArg);

  if( CsrFlagTest(pCsr, FTS5CSR_FREE_ZRANK) ){
    sqlite3_free(pCsr->zRank);
    sqlite3_free(pCsr->zRankArgs);
  }

  sqlite3Fts5IndexCloseReader(pTab->p.pIndex);
  memset(&pCsr->ePlan, 0, sizeof(Fts5Cursor) - ((u8*)&pCsr->ePlan - (u8*)pCsr));
}


/*
** Close the cursor.  For additional information see the documentation
** on the xClose method of the virtual table interface.
*/
static int fts5CloseMethod(sqlite3_vtab_cursor *pCursor){
  if( pCursor ){
    Fts5Table *pTab = (Fts5Table*)(pCursor->pVtab);
    Fts5FullTable *pTab = (Fts5FullTable*)(pCursor->pVtab);
    Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
    Fts5Cursor **pp;

    fts5FreeCursorComponents(pCsr);
    /* Remove the cursor from the Fts5Global.pCsr list */
    for(pp=&pTab->pGlobal->pCsr; (*pp)!=pCsr; pp=&(*pp)->pNext);
    *pp = pCsr->pNext;

    sqlite3_free(pCsr);
  }
  return SQLITE_OK;
}

static int fts5SorterNext(Fts5Cursor *pCsr){
  Fts5Sorter *pSorter = pCsr->pSorter;
  int rc;

  rc = sqlite3_step(pSorter->pStmt);
  if( rc==SQLITE_DONE ){
    rc = SQLITE_OK;
    CsrFlagSet(pCsr, FTS5CSR_EOF);
    CsrFlagSet(pCsr, FTS5CSR_EOF|FTS5CSR_REQUIRE_CONTENT);
  }else if( rc==SQLITE_ROW ){
    const u8 *a;
    const u8 *aBlob;
    int nBlob;
    int i;
    int iOff = 0;
    rc = SQLITE_OK;
770
771
772
773
774
775
776
777

778
779
780
781
782
783
784
836
837
838
839
840
841
842

843
844
845
846
847
848
849
850







-
+







}


/*
** Set the FTS5CSR_REQUIRE_RESEEK flag on all FTS5_PLAN_MATCH cursors 
** open on table pTab.
*/
static void fts5TripCursors(Fts5Table *pTab){
static void fts5TripCursors(Fts5FullTable *pTab){
  Fts5Cursor *pCsr;
  for(pCsr=pTab->pGlobal->pCsr; pCsr; pCsr=pCsr->pNext){
    if( pCsr->ePlan==FTS5_PLAN_MATCH
     && pCsr->base.pVtab==(sqlite3_vtab*)pTab 
    ){
      CsrFlagSet(pCsr, FTS5CSR_REQUIRE_RESEEK);
    }
797
798
799
800
801
802
803
804

805
806
807
808

809
810
811
812
813
814
815
863
864
865
866
867
868
869

870
871
872
873

874
875
876
877
878
879
880
881







-
+



-
+







** Return SQLITE_OK if successful or if no reseek was required, or an 
** error code if an error occurred.
*/
static int fts5CursorReseek(Fts5Cursor *pCsr, int *pbSkip){
  int rc = SQLITE_OK;
  assert( *pbSkip==0 );
  if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_RESEEK) ){
    Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
    Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
    int bDesc = pCsr->bDesc;
    i64 iRowid = sqlite3Fts5ExprRowid(pCsr->pExpr);

    rc = sqlite3Fts5ExprFirst(pCsr->pExpr, pTab->pIndex, iRowid, bDesc);
    rc = sqlite3Fts5ExprFirst(pCsr->pExpr, pTab->p.pIndex, iRowid, bDesc);
    if( rc==SQLITE_OK &&  iRowid!=sqlite3Fts5ExprRowid(pCsr->pExpr) ){
      *pbSkip = 1;
    }

    CsrFlagClear(pCsr, FTS5CSR_REQUIRE_RESEEK);
    fts5CsrNewrow(pCsr);
    if( sqlite3Fts5ExprEof(pCsr->pExpr) ){
853
854
855
856
857
858
859
860



861

862
863
864





865
866
867
868

869
870
871
872
873
874
875
919
920
921
922
923
924
925

926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950







-
+
+
+

+



+
+
+
+
+




+







      }
  
      case FTS5_PLAN_SORTED_MATCH: {
        rc = fts5SorterNext(pCsr);
        break;
      }
  
      default:
      default: {
        Fts5Config *pConfig = ((Fts5Table*)pCursor->pVtab)->pConfig;
        pConfig->bLock++;
        rc = sqlite3_step(pCsr->pStmt);
        pConfig->bLock--;
        if( rc!=SQLITE_ROW ){
          CsrFlagSet(pCsr, FTS5CSR_EOF);
          rc = sqlite3_reset(pCsr->pStmt);
          if( rc!=SQLITE_OK ){
            pCursor->pVtab->zErrMsg = sqlite3_mprintf(
                "%s", sqlite3_errmsg(pConfig->db)
            );
          }
        }else{
          rc = SQLITE_OK;
        }
        break;
      }
    }
  }
  
  return rc;
}


898
899
900
901
902
903
904
905
906






907
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
935
936
973
974
975
976
977
978
979


980
981
982
983
984
985
986
987

988
989
990
991
992
993
994

995
996

997
998
999
1000
1001
1002
1003
1004
1005
1006
1007

1008
1009
1010
1011
1012
1013
1014
1015







-
-
+
+
+
+
+
+


-
+






-
+

-
+










-
+







  }

  va_end(ap);
  *ppStmt = pRet;
  return rc;
} 

static int fts5CursorFirstSorted(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){
  Fts5Config *pConfig = pTab->pConfig;
static int fts5CursorFirstSorted(
  Fts5FullTable *pTab, 
  Fts5Cursor *pCsr, 
  int bDesc
){
  Fts5Config *pConfig = pTab->p.pConfig;
  Fts5Sorter *pSorter;
  int nPhrase;
  int nByte;
  sqlite3_int64 nByte;
  int rc;
  const char *zRank = pCsr->zRank;
  const char *zRankArgs = pCsr->zRankArgs;
  
  nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
  nByte = sizeof(Fts5Sorter) + sizeof(int) * (nPhrase-1);
  pSorter = (Fts5Sorter*)sqlite3_malloc(nByte);
  pSorter = (Fts5Sorter*)sqlite3_malloc64(nByte);
  if( pSorter==0 ) return SQLITE_NOMEM;
  memset(pSorter, 0, nByte);
  memset(pSorter, 0, (size_t)nByte);
  pSorter->nIdx = nPhrase;

  /* TODO: It would be better to have some system for reusing statement
  ** handles here, rather than preparing a new one for each query. But that
  ** is not possible as SQLite reference counts the virtual table objects.
  ** And since the statement required here reads from this very virtual 
  ** table, saving it creates a circular reference.
  **
  ** If SQLite a built-in statement cache, this wouldn't be a problem. */
  rc = fts5PrepareStatement(&pSorter->pStmt, pConfig,
      "SELECT rowid, rank FROM %Q.%Q ORDER BY %s(%s%s%s) %s",
      "SELECT rowid, rank FROM %Q.%Q ORDER BY %s(\"%w\"%s%s) %s",
      pConfig->zDb, pConfig->zName, zRank, pConfig->zName,
      (zRankArgs ? ", " : ""),
      (zRankArgs ? zRankArgs : ""),
      bDesc ? "DESC" : "ASC"
  );

  pCsr->pSorter = pSorter;
946
947
948
949
950
951
952
953

954
955
956

957
958
959
960
961
962
963
964
965
966
967
968
969
970
971

972
973
974
975
976
977
978
979
980
981
982

983
984
985
986


987
988

989
990
991
992
993

994
995
996
997
998
999
1000
1001
1002
1003
1004
1005

1006
1007
1008
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
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







-
+


-
+














-
+










-
+


-
-
+
+

-
+




-
+











-
+












-
-
+
+















-
+







    sqlite3_free(pSorter);
    pCsr->pSorter = 0;
  }

  return rc;
}

static int fts5CursorFirst(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){
static int fts5CursorFirst(Fts5FullTable *pTab, Fts5Cursor *pCsr, int bDesc){
  int rc;
  Fts5Expr *pExpr = pCsr->pExpr;
  rc = sqlite3Fts5ExprFirst(pExpr, pTab->pIndex, pCsr->iFirstRowid, bDesc);
  rc = sqlite3Fts5ExprFirst(pExpr, pTab->p.pIndex, pCsr->iFirstRowid, bDesc);
  if( sqlite3Fts5ExprEof(pExpr) ){
    CsrFlagSet(pCsr, FTS5CSR_EOF);
  }
  fts5CsrNewrow(pCsr);
  return rc;
}

/*
** Process a "special" query. A special query is identified as one with a
** MATCH expression that begins with a '*' character. The remainder of
** the text passed to the MATCH operator are used as  the special query
** parameters.
*/
static int fts5SpecialMatch(
  Fts5Table *pTab, 
  Fts5FullTable *pTab, 
  Fts5Cursor *pCsr, 
  const char *zQuery
){
  int rc = SQLITE_OK;             /* Return code */
  const char *z = zQuery;         /* Special query text */
  int n;                          /* Number of bytes in text at z */

  while( z[0]==' ' ) z++;
  for(n=0; z[n] && z[n]!=' '; n++);

  assert( pTab->base.zErrMsg==0 );
  assert( pTab->p.base.zErrMsg==0 );
  pCsr->ePlan = FTS5_PLAN_SPECIAL;

  if( 0==sqlite3_strnicmp("reads", z, n) ){
    pCsr->iSpecial = sqlite3Fts5IndexReads(pTab->pIndex);
  if( n==5 && 0==sqlite3_strnicmp("reads", z, n) ){
    pCsr->iSpecial = sqlite3Fts5IndexReads(pTab->p.pIndex);
  }
  else if( 0==sqlite3_strnicmp("id", z, n) ){
  else if( n==2 && 0==sqlite3_strnicmp("id", z, n) ){
    pCsr->iSpecial = pCsr->iCsrId;
  }
  else{
    /* An unrecognized directive. Return an error message. */
    pTab->base.zErrMsg = sqlite3_mprintf("unknown special query: %.*s", n, z);
    pTab->p.base.zErrMsg = sqlite3_mprintf("unknown special query: %.*s", n, z);
    rc = SQLITE_ERROR;
  }

  return rc;
}

/*
** Search for an auxiliary function named zName that can be used with table
** pTab. If one is found, return a pointer to the corresponding Fts5Auxiliary
** structure. Otherwise, if no such function exists, return NULL.
*/
static Fts5Auxiliary *fts5FindAuxiliary(Fts5Table *pTab, const char *zName){
static Fts5Auxiliary *fts5FindAuxiliary(Fts5FullTable *pTab, const char *zName){
  Fts5Auxiliary *pAux;

  for(pAux=pTab->pGlobal->pAux; pAux; pAux=pAux->pNext){
    if( sqlite3_stricmp(zName, pAux->zFunc)==0 ) return pAux;
  }

  /* No function of the specified name was found. Return 0. */
  return 0;
}


static int fts5FindRankFunction(Fts5Cursor *pCsr){
  Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
  Fts5Config *pConfig = pTab->pConfig;
  Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
  Fts5Config *pConfig = pTab->p.pConfig;
  int rc = SQLITE_OK;
  Fts5Auxiliary *pAux = 0;
  const char *zRank = pCsr->zRank;
  const char *zRankArgs = pCsr->zRankArgs;

  if( zRankArgs ){
    char *zSql = sqlite3Fts5Mprintf(&rc, "SELECT %s", zRankArgs);
    if( zSql ){
      sqlite3_stmt *pStmt = 0;
      rc = sqlite3_prepare_v3(pConfig->db, zSql, -1,
                              SQLITE_PREPARE_PERSISTENT, &pStmt, 0);
      sqlite3_free(zSql);
      assert( rc==SQLITE_OK || pCsr->pRankArgStmt==0 );
      if( rc==SQLITE_OK ){
        if( SQLITE_ROW==sqlite3_step(pStmt) ){
          int nByte;
          sqlite3_int64 nByte;
          pCsr->nRankArg = sqlite3_column_count(pStmt);
          nByte = sizeof(sqlite3_value*)*pCsr->nRankArg;
          pCsr->apRankArg = (sqlite3_value**)sqlite3Fts5MallocZero(&rc, nByte);
          if( rc==SQLITE_OK ){
            int i;
            for(i=0; i<pCsr->nRankArg; i++){
              pCsr->apRankArg[i] = sqlite3_column_value(pStmt, i);
1050
1051
1052
1053
1054
1055
1056
1057
1058


1059
1060
1061
1062
1063
1064
1065
1129
1130
1131
1132
1133
1134
1135


1136
1137
1138
1139
1140
1141
1142
1143
1144







-
-
+
+







      }
    }
  }

  if( rc==SQLITE_OK ){
    pAux = fts5FindAuxiliary(pTab, zRank);
    if( pAux==0 ){
      assert( pTab->base.zErrMsg==0 );
      pTab->base.zErrMsg = sqlite3_mprintf("no such function: %s", zRank);
      assert( pTab->p.base.zErrMsg==0 );
      pTab->p.base.zErrMsg = sqlite3_mprintf("no such function: %s", zRank);
      rc = SQLITE_ERROR;
    }
  }

  pCsr->pRank = pAux;
  return rc;
}
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
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
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
1318
1319
1320







-
+



-
-
+
+


-


-






+
+
+

-
-
+
+
+
+
+
+












+

-
-
+
+

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







**   1. Full-text search using a MATCH operator.
**   2. A by-rowid lookup.
**   3. A full-table scan.
*/
static int fts5FilterMethod(
  sqlite3_vtab_cursor *pCursor,   /* The cursor used for this query */
  int idxNum,                     /* Strategy index */
  const char *zUnused,            /* Unused */
  const char *idxStr,             /* Unused */
  int nVal,                       /* Number of elements in apVal */
  sqlite3_value **apVal           /* Arguments for the indexing scheme */
){
  Fts5Table *pTab = (Fts5Table*)(pCursor->pVtab);
  Fts5Config *pConfig = pTab->pConfig;
  Fts5FullTable *pTab = (Fts5FullTable*)(pCursor->pVtab);
  Fts5Config *pConfig = pTab->p.pConfig;
  Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
  int rc = SQLITE_OK;             /* Error code */
  int iVal = 0;                   /* Counter for apVal[] */
  int bDesc;                      /* True if ORDER BY [rank|rowid] DESC */
  int bOrderByRank;               /* True if ORDER BY rank */
  sqlite3_value *pMatch = 0;      /* <tbl> MATCH ? expression (or NULL) */
  sqlite3_value *pRank = 0;       /* rank MATCH ? expression (or NULL) */
  sqlite3_value *pRowidEq = 0;    /* rowid = ? expression (or NULL) */
  sqlite3_value *pRowidLe = 0;    /* rowid <= ? expression (or NULL) */
  sqlite3_value *pRowidGe = 0;    /* rowid >= ? expression (or NULL) */
  int iCol;                       /* Column on LHS of MATCH operator */
  char **pzErrmsg = pConfig->pzErrmsg;
  int i;
  int iIdxStr = 0;
  Fts5Expr *pExpr = 0;

  UNUSED_PARAM(zUnused);
  UNUSED_PARAM(nVal);
  if( pConfig->bLock ){
    pTab->p.base.zErrMsg = sqlite3_mprintf(
        "recursively defined fts5 content table"
    );
    return SQLITE_ERROR;
  }

  if( pCsr->ePlan ){
    fts5FreeCursorComponents(pCsr);
    memset(&pCsr->ePlan, 0, sizeof(Fts5Cursor) - ((u8*)&pCsr->ePlan-(u8*)pCsr));
  }

  assert( pCsr->pStmt==0 );
  assert( pCsr->pExpr==0 );
  assert( pCsr->csrflags==0 );
  assert( pCsr->pRank==0 );
  assert( pCsr->zRank==0 );
  assert( pCsr->zRankArgs==0 );
  assert( pTab->pSortCsr==0 || nVal==0 );

  assert( pzErrmsg==0 || pzErrmsg==&pTab->base.zErrMsg );
  pConfig->pzErrmsg = &pTab->base.zErrMsg;
  assert( pzErrmsg==0 || pzErrmsg==&pTab->p.base.zErrMsg );
  pConfig->pzErrmsg = &pTab->p.base.zErrMsg;

  /* Decode the arguments passed through to this function.
  /* Decode the arguments passed through to this function. */
  **
  ** Note: The following set of if(...) statements must be in the same
  ** order as the corresponding entries in the struct at the top of
  ** fts5BestIndexMethod().  */
  for(i=0; i<nVal; i++){
    switch( idxStr[iIdxStr++] ){
      case 'r':
  if( BitFlagTest(idxNum, FTS5_BI_MATCH) ) pMatch = apVal[iVal++];
  if( BitFlagTest(idxNum, FTS5_BI_RANK) ) pRank = apVal[iVal++];
  if( BitFlagTest(idxNum, FTS5_BI_ROWID_EQ) ) pRowidEq = apVal[iVal++];
  if( BitFlagTest(idxNum, FTS5_BI_ROWID_LE) ) pRowidLe = apVal[iVal++];
  if( BitFlagTest(idxNum, FTS5_BI_ROWID_GE) ) pRowidGe = apVal[iVal++];
  iCol = (idxNum>>16);
  assert( iCol>=0 && iCol<=pConfig->nCol );
  assert( iVal==nVal );
        pRank = apVal[i];
        break;
      case 'M': {
        const char *zText = (const char*)sqlite3_value_text(apVal[i]);
        if( zText==0 ) zText = "";
        iCol = 0;
        do{
          iCol = iCol*10 + (idxStr[iIdxStr]-'0');
          iIdxStr++;
        }while( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' );

        if( zText[0]=='*' ){
          /* The user has issued a query of the form "MATCH '*...'". This
          ** indicates that the MATCH expression is not a full text query,
          ** but a request for an internal parameter.  */
          rc = fts5SpecialMatch(pTab, pCsr, &zText[1]);
          goto filter_out;
        }else{
          char **pzErr = &pTab->p.base.zErrMsg;
          rc = sqlite3Fts5ExprNew(pConfig, 0, iCol, zText, &pExpr, pzErr);
          if( rc==SQLITE_OK ){
            rc = sqlite3Fts5ExprAnd(&pCsr->pExpr, pExpr);
            pExpr = 0;
          }
          if( rc!=SQLITE_OK ) goto filter_out;
        }

        break;
      }
      case 'L':
      case 'G': {
        int bGlob = (idxStr[iIdxStr-1]=='G');
        const char *zText = (const char*)sqlite3_value_text(apVal[i]);
        iCol = 0;
        do{
          iCol = iCol*10 + (idxStr[iIdxStr]-'0');
          iIdxStr++;
        }while( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' );
        if( zText ){
          rc = sqlite3Fts5ExprPattern(pConfig, bGlob, iCol, zText, &pExpr);
        }
        if( rc==SQLITE_OK ){
          rc = sqlite3Fts5ExprAnd(&pCsr->pExpr, pExpr);
          pExpr = 0;
        }
        if( rc!=SQLITE_OK ) goto filter_out;
        break;
      }
      case '=':
        pRowidEq = apVal[i];
        break;
      case '<':
        pRowidLe = apVal[i];
        break;
      default: assert( idxStr[iIdxStr-1]=='>' );
        pRowidGe = apVal[i];
        break;
    }
  }
  bOrderByRank = ((idxNum & FTS5_BI_ORDER_RANK) ? 1 : 0);
  pCsr->bDesc = bDesc = ((idxNum & FTS5_BI_ORDER_DESC) ? 1 : 0);

  /* Set the cursor upper and lower rowid limits. Only some strategies 
  ** actually use them. This is ok, as the xBestIndex() method leaves the
  ** sqlite3_index_constraint.omit flag clear for range constraints
  ** on the rowid field.  */
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
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







-
+












-
+
-
-
-


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












-
+


+
-
-
+
+








+
+







    /* If pSortCsr is non-NULL, then this call is being made as part of 
    ** processing for a "... MATCH <expr> ORDER BY rank" query (ePlan is
    ** set to FTS5_PLAN_SORTED_MATCH). pSortCsr is the cursor that will
    ** return results to the user for this query. The current cursor 
    ** (pCursor) is used to execute the query issued by function 
    ** fts5CursorFirstSorted() above.  */
    assert( pRowidEq==0 && pRowidLe==0 && pRowidGe==0 && pRank==0 );
    assert( nVal==0 && pMatch==0 && bOrderByRank==0 && bDesc==0 );
    assert( nVal==0 && bOrderByRank==0 && bDesc==0 );
    assert( pCsr->iLastRowid==LARGEST_INT64 );
    assert( pCsr->iFirstRowid==SMALLEST_INT64 );
    if( pTab->pSortCsr->bDesc ){
      pCsr->iLastRowid = pTab->pSortCsr->iFirstRowid;
      pCsr->iFirstRowid = pTab->pSortCsr->iLastRowid;
    }else{
      pCsr->iLastRowid = pTab->pSortCsr->iLastRowid;
      pCsr->iFirstRowid = pTab->pSortCsr->iFirstRowid;
    }
    pCsr->ePlan = FTS5_PLAN_SOURCE;
    pCsr->pExpr = pTab->pSortCsr->pExpr;
    rc = fts5CursorFirst(pTab, pCsr, bDesc);
  }else if( pMatch ){
  }else if( pCsr->pExpr ){
    const char *zExpr = (const char*)sqlite3_value_text(apVal[0]);
    if( zExpr==0 ) zExpr = "";

    rc = fts5CursorParseRank(pConfig, pCsr, pRank);
    if( rc==SQLITE_OK ){
      if( zExpr[0]=='*' ){
        /* The user has issued a query of the form "MATCH '*...'". This
        ** indicates that the MATCH expression is not a full text query,
        ** but a request for an internal parameter.  */
        rc = fts5SpecialMatch(pTab, pCsr, &zExpr[1]);
      }else{
        char **pzErr = &pTab->base.zErrMsg;
        rc = sqlite3Fts5ExprNew(pConfig, iCol, zExpr, &pCsr->pExpr, pzErr);
        if( rc==SQLITE_OK ){
          if( bOrderByRank ){
            pCsr->ePlan = FTS5_PLAN_SORTED_MATCH;
            rc = fts5CursorFirstSorted(pTab, pCsr, bDesc);
          }else{
            pCsr->ePlan = FTS5_PLAN_MATCH;
            rc = fts5CursorFirst(pTab, pCsr, bDesc);
      if( bOrderByRank ){
        pCsr->ePlan = FTS5_PLAN_SORTED_MATCH;
        rc = fts5CursorFirstSorted(pTab, pCsr, bDesc);
      }else{
        pCsr->ePlan = FTS5_PLAN_MATCH;
        rc = fts5CursorFirst(pTab, pCsr, bDesc);
          }
        }
      }
    }
  }else if( pConfig->zContent==0 ){
    *pConfig->pzErrmsg = sqlite3_mprintf(
        "%s: table does not support scanning", pConfig->zName
    );
    rc = SQLITE_ERROR;
  }else{
    /* This is either a full-table scan (ePlan==FTS5_PLAN_SCAN) or a lookup
    ** by rowid (ePlan==FTS5_PLAN_ROWID).  */
    pCsr->ePlan = (pRowidEq ? FTS5_PLAN_ROWID : FTS5_PLAN_SCAN);
    rc = sqlite3Fts5StorageStmt(
        pTab->pStorage, fts5StmtType(pCsr), &pCsr->pStmt, &pTab->base.zErrMsg
        pTab->pStorage, fts5StmtType(pCsr), &pCsr->pStmt, &pTab->p.base.zErrMsg
    );
    if( rc==SQLITE_OK ){
      if( pRowidEq!=0 ){
      if( pCsr->ePlan==FTS5_PLAN_ROWID ){
        sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]);
        assert( pCsr->ePlan==FTS5_PLAN_ROWID );
        sqlite3_bind_value(pCsr->pStmt, 1, pRowidEq);
      }else{
        sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iFirstRowid);
        sqlite3_bind_int64(pCsr->pStmt, 2, pCsr->iLastRowid);
      }
      rc = fts5NextMethod(pCursor);
    }
  }

 filter_out:
  sqlite3Fts5ExprFree(pExpr);
  pConfig->pzErrmsg = pzErrmsg;
  return rc;
}

/* 
** This is the xEof method of the virtual table. SQLite calls this 
** routine to find out if it has reached the end of a result set.
1329
1330
1331
1332
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
1453
1454
1455
1456
1457
1458
1459

1460
1461
1462

1463
1464

1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493

1494
1495
1496


1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517

1518
1519
1520
1521

1522
1523
1524
1525
1526
1527
1528
1529







-
+


-
+

-
+




+



+

+







+
+
+
+






-
+


-
-
+
+



















-
+



-
+







** be left in sqlite3_vtab.zErrMsg.
*/
static int fts5SeekCursor(Fts5Cursor *pCsr, int bErrormsg){
  int rc = SQLITE_OK;

  /* If the cursor does not yet have a statement handle, obtain one now. */ 
  if( pCsr->pStmt==0 ){
    Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
    Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
    int eStmt = fts5StmtType(pCsr);
    rc = sqlite3Fts5StorageStmt(
        pTab->pStorage, eStmt, &pCsr->pStmt, (bErrormsg?&pTab->base.zErrMsg:0)
        pTab->pStorage, eStmt, &pCsr->pStmt, (bErrormsg?&pTab->p.base.zErrMsg:0)
    );
    assert( rc!=SQLITE_OK || pTab->base.zErrMsg==0 );
    assert( rc!=SQLITE_OK || pTab->p.base.zErrMsg==0 );
    assert( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_CONTENT) );
  }

  if( rc==SQLITE_OK && CsrFlagTest(pCsr, FTS5CSR_REQUIRE_CONTENT) ){
    Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
    assert( pCsr->pExpr );
    sqlite3_reset(pCsr->pStmt);
    sqlite3_bind_int64(pCsr->pStmt, 1, fts5CursorRowid(pCsr));
    pTab->pConfig->bLock++;
    rc = sqlite3_step(pCsr->pStmt);
    pTab->pConfig->bLock--;
    if( rc==SQLITE_ROW ){
      rc = SQLITE_OK;
      CsrFlagClear(pCsr, FTS5CSR_REQUIRE_CONTENT);
    }else{
      rc = sqlite3_reset(pCsr->pStmt);
      if( rc==SQLITE_OK ){
        rc = FTS5_CORRUPT;
      }else if( pTab->pConfig->pzErrmsg ){
        *pTab->pConfig->pzErrmsg = sqlite3_mprintf(
            "%s", sqlite3_errmsg(pTab->pConfig->db)
        );
      }
    }
  }
  return rc;
}

static void fts5SetVtabError(Fts5Table *p, const char *zFormat, ...){
static void fts5SetVtabError(Fts5FullTable *p, const char *zFormat, ...){
  va_list ap;                     /* ... printf arguments */
  va_start(ap, zFormat);
  assert( p->base.zErrMsg==0 );
  p->base.zErrMsg = sqlite3_vmprintf(zFormat, ap);
  assert( p->p.base.zErrMsg==0 );
  p->p.base.zErrMsg = sqlite3_vmprintf(zFormat, ap);
  va_end(ap);
}

/*
** This function is called to handle an FTS INSERT command. In other words,
** an INSERT statement of the form:
**
**     INSERT INTO fts(fts) VALUES($pCmd)
**     INSERT INTO fts(fts, rank) VALUES($pCmd, $pVal)
**
** Argument pVal is the value assigned to column "fts" by the INSERT 
** statement. This function returns SQLITE_OK if successful, or an SQLite
** error code if an error occurs.
**
** The commands implemented by this function are documented in the "Special
** INSERT Directives" section of the documentation. It should be updated if
** more commands are added to this function.
*/
static int fts5SpecialInsert(
  Fts5Table *pTab,                /* Fts5 table object */
  Fts5FullTable *pTab,            /* Fts5 table object */
  const char *zCmd,               /* Text inserted into table-name column */
  sqlite3_value *pVal             /* Value inserted into rank column */
){
  Fts5Config *pConfig = pTab->pConfig;
  Fts5Config *pConfig = pTab->p.pConfig;
  int rc = SQLITE_OK;
  int bError = 0;

  if( 0==sqlite3_stricmp("delete-all", zCmd) ){
    if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
      fts5SetVtabError(pTab, 
          "'delete-all' may only be used with a "
1413
1414
1415
1416
1417
1418
1419

1420

1421
1422
1423
1424
1425
1426

1427
1428

1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442

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

1457
1458
1459
1460
1461
1462
1463
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

1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587

1588
1589
1590
1591
1592
1593
1594
1595







+
-
+





-
+

-
+













-
+













-
+







    }
  }else if( 0==sqlite3_stricmp("optimize", zCmd) ){
    rc = sqlite3Fts5StorageOptimize(pTab->pStorage);
  }else if( 0==sqlite3_stricmp("merge", zCmd) ){
    int nMerge = sqlite3_value_int(pVal);
    rc = sqlite3Fts5StorageMerge(pTab->pStorage, nMerge);
  }else if( 0==sqlite3_stricmp("integrity-check", zCmd) ){
    int iArg = sqlite3_value_int(pVal);
    rc = sqlite3Fts5StorageIntegrity(pTab->pStorage);
    rc = sqlite3Fts5StorageIntegrity(pTab->pStorage, iArg);
#ifdef SQLITE_DEBUG
  }else if( 0==sqlite3_stricmp("prefix-index", zCmd) ){
    pConfig->bPrefixIndex = sqlite3_value_int(pVal);
#endif
  }else{
    rc = sqlite3Fts5IndexLoadConfig(pTab->pIndex);
    rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex);
    if( rc==SQLITE_OK ){
      rc = sqlite3Fts5ConfigSetValue(pTab->pConfig, zCmd, pVal, &bError);
      rc = sqlite3Fts5ConfigSetValue(pTab->p.pConfig, zCmd, pVal, &bError);
    }
    if( rc==SQLITE_OK ){
      if( bError ){
        rc = SQLITE_ERROR;
      }else{
        rc = sqlite3Fts5StorageConfigValue(pTab->pStorage, zCmd, pVal, 0);
      }
    }
  }
  return rc;
}

static int fts5SpecialDelete(
  Fts5Table *pTab, 
  Fts5FullTable *pTab, 
  sqlite3_value **apVal
){
  int rc = SQLITE_OK;
  int eType1 = sqlite3_value_type(apVal[1]);
  if( eType1==SQLITE_INTEGER ){
    sqlite3_int64 iDel = sqlite3_value_int64(apVal[1]);
    rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, &apVal[2]);
  }
  return rc;
}

static void fts5StorageInsert(
  int *pRc, 
  Fts5Table *pTab, 
  Fts5FullTable *pTab, 
  sqlite3_value **apVal, 
  i64 *piRowid
){
  int rc = *pRc;
  if( rc==SQLITE_OK ){
    rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, apVal, piRowid);
  }
1483
1484
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
1615
1616
1617
1618
1619
1620
1621


1622
1623
1624
1625
1626
1627

1628
1629
1630
1631



1632
1633
1634


1635
1636
1637
1638
1639
1640
1641
1642
1643







-
-
+
+




-
+



-
-
-
+
+

-
-
+
+







*/
static int fts5UpdateMethod(
  sqlite3_vtab *pVtab,            /* Virtual table handle */
  int nArg,                       /* Size of argument array */
  sqlite3_value **apVal,          /* Array of arguments */
  sqlite_int64 *pRowid            /* OUT: The affected (or effected) rowid */
){
  Fts5Table *pTab = (Fts5Table*)pVtab;
  Fts5Config *pConfig = pTab->pConfig;
  Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
  Fts5Config *pConfig = pTab->p.pConfig;
  int eType0;                     /* value_type() of apVal[0] */
  int rc = SQLITE_OK;             /* Return code */

  /* A transaction must be open when this is called. */
  assert( pTab->ts.eState==1 );
  assert( pTab->ts.eState==1 || pTab->ts.eState==2 );

  assert( pVtab->zErrMsg==0 );
  assert( nArg==1 || nArg==(2+pConfig->nCol+2) );
  assert( nArg==1 
      || sqlite3_value_type(apVal[1])==SQLITE_INTEGER 
      || sqlite3_value_type(apVal[1])==SQLITE_NULL 
  assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER 
       || sqlite3_value_type(apVal[0])==SQLITE_NULL 
  );
  assert( pTab->pConfig->pzErrmsg==0 );
  pTab->pConfig->pzErrmsg = &pTab->base.zErrMsg;
  assert( pTab->p.pConfig->pzErrmsg==0 );
  pTab->p.pConfig->pzErrmsg = &pTab->p.base.zErrMsg;

  /* Put any active cursors into REQUIRE_SEEK state. */
  fts5TripCursors(pTab);

  eType0 = sqlite3_value_type(apVal[0]);
  if( eType0==SQLITE_NULL 
   && sqlite3_value_type(apVal[2+pConfig->nCol])!=SQLITE_NULL 
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
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598






























1599
1600
1601
1602
1603
1604
1605
1606
1607

1608
1609

1610
1611
1612

1613
1614
1615
1616
1617
1618
1619
1620
1621


1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632

1633
1634
1635
1636
1637
1638
1639
1640
1641
1642

1643
1644
1645
1646
1647
1648
1649
1670
1671
1672
1673
1674
1675
1676

1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689




1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700







1701
1702
1703
1704
1705
1706




























1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744

1745
1746

1747
1748
1749

1750
1751
1752
1753
1754
1755
1756
1757


1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769

1770
1771
1772
1773
1774
1775
1776
1777
1778
1779

1780
1781
1782
1783
1784
1785
1786
1787







-
+












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

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








-
+

-
+


-
+







-
-
+
+










-
+









-
+








    assert( eType0==SQLITE_INTEGER || eType0==SQLITE_NULL );
    assert( nArg!=1 || eType0==SQLITE_INTEGER );

    /* Filter out attempts to run UPDATE or DELETE on contentless tables.
    ** This is not suported.  */
    if( eType0==SQLITE_INTEGER && fts5IsContentless(pTab) ){
      pTab->base.zErrMsg = sqlite3_mprintf(
      pTab->p.base.zErrMsg = sqlite3_mprintf(
          "cannot %s contentless fts5 table: %s", 
          (nArg>1 ? "UPDATE" : "DELETE from"), pConfig->zName
      );
      rc = SQLITE_ERROR;
    }

    /* DELETE */
    else if( nArg==1 ){
      i64 iDel = sqlite3_value_int64(apVal[0]);  /* Rowid to delete */
      rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, 0);
    }

    /* INSERT */
    else if( eType0!=SQLITE_INTEGER ){     
      /* If this is a REPLACE, first remove the current entry (if any) */
      if( eConflict==SQLITE_REPLACE 
    /* INSERT or UPDATE */
    else{
      int eType1 = sqlite3_value_numeric_type(apVal[1]);

      if( eType1!=SQLITE_INTEGER && eType1!=SQLITE_NULL ){
        rc = SQLITE_MISMATCH;
      }

      else if( eType0!=SQLITE_INTEGER ){     
        /* If this is a REPLACE, first remove the current entry (if any) */
        if( eConflict==SQLITE_REPLACE && eType1==SQLITE_INTEGER ){
       && sqlite3_value_type(apVal[1])==SQLITE_INTEGER 
      ){
        i64 iNew = sqlite3_value_int64(apVal[1]);  /* Rowid to delete */
        rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
      }
      fts5StorageInsert(&rc, pTab, apVal, pRowid);
    }
          i64 iNew = sqlite3_value_int64(apVal[1]);  /* Rowid to delete */
          rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
        }
        fts5StorageInsert(&rc, pTab, apVal, pRowid);
      }

    /* UPDATE */
    else{
      i64 iOld = sqlite3_value_int64(apVal[0]);  /* Old rowid */
      i64 iNew = sqlite3_value_int64(apVal[1]);  /* New rowid */
      if( iOld!=iNew ){
        if( eConflict==SQLITE_REPLACE ){
          rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
          if( rc==SQLITE_OK ){
            rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
          }
          fts5StorageInsert(&rc, pTab, apVal, pRowid);
        }else{
          rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, apVal, pRowid);
          if( rc==SQLITE_OK ){
            rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
          }
          if( rc==SQLITE_OK ){
            rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal, *pRowid);
          }
        }
      }else{
        rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
        fts5StorageInsert(&rc, pTab, apVal, pRowid);
      }
    }
  }

  pTab->pConfig->pzErrmsg = 0;
      /* UPDATE */
      else{
        i64 iOld = sqlite3_value_int64(apVal[0]);  /* Old rowid */
        i64 iNew = sqlite3_value_int64(apVal[1]);  /* New rowid */
        if( eType1==SQLITE_INTEGER && iOld!=iNew ){
          if( eConflict==SQLITE_REPLACE ){
            rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
            if( rc==SQLITE_OK ){
              rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
            }
            fts5StorageInsert(&rc, pTab, apVal, pRowid);
          }else{
            rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, apVal, pRowid);
            if( rc==SQLITE_OK ){
              rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
            }
            if( rc==SQLITE_OK ){
              rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal,*pRowid);
            }
          }
        }else{
          rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
          fts5StorageInsert(&rc, pTab, apVal, pRowid);
        }
      }
    }
  }

  sqlite3Fts5IndexCloseReader(pTab->p.pIndex);
  pTab->p.pConfig->pzErrmsg = 0;
  return rc;
}

/*
** Implementation of xSync() method. 
*/
static int fts5SyncMethod(sqlite3_vtab *pVtab){
  int rc;
  Fts5Table *pTab = (Fts5Table*)pVtab;
  Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
  fts5CheckTransactionState(pTab, FTS5_SYNC, 0);
  pTab->pConfig->pzErrmsg = &pTab->base.zErrMsg;
  pTab->p.pConfig->pzErrmsg = &pTab->p.base.zErrMsg;
  fts5TripCursors(pTab);
  rc = sqlite3Fts5StorageSync(pTab->pStorage);
  pTab->pConfig->pzErrmsg = 0;
  pTab->p.pConfig->pzErrmsg = 0;
  return rc;
}

/*
** Implementation of xBegin() method. 
*/
static int fts5BeginMethod(sqlite3_vtab *pVtab){
  fts5CheckTransactionState((Fts5Table*)pVtab, FTS5_BEGIN, 0);
  fts5NewTransaction((Fts5Table*)pVtab);
  fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_BEGIN, 0);
  fts5NewTransaction((Fts5FullTable*)pVtab);
  return SQLITE_OK;
}

/*
** 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 fts5SyncMethod().
*/
static int fts5CommitMethod(sqlite3_vtab *pVtab){
  UNUSED_PARAM(pVtab);  /* Call below is a no-op for NDEBUG builds */
  fts5CheckTransactionState((Fts5Table*)pVtab, FTS5_COMMIT, 0);
  fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_COMMIT, 0);
  return SQLITE_OK;
}

/*
** Implementation of xRollback(). Discard the contents of the pending-terms
** hash-table. Any changes made to the database are reverted by SQLite.
*/
static int fts5RollbackMethod(sqlite3_vtab *pVtab){
  int rc;
  Fts5Table *pTab = (Fts5Table*)pVtab;
  Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
  fts5CheckTransactionState(pTab, FTS5_ROLLBACK, 0);
  rc = sqlite3Fts5StorageRollback(pTab->pStorage);
  return rc;
}

static int fts5CsrPoslist(Fts5Cursor*, int, const u8**, int*);

1659
1660
1661
1662
1663
1664
1665
1666

1667
1668
1669
1670
1671
1672

1673
1674
1675
1676
1677
1678
1679
1797
1798
1799
1800
1801
1802
1803

1804
1805
1806
1807
1808
1809

1810
1811
1812
1813
1814
1815
1816
1817







-
+





-
+








static int fts5ApiColumnTotalSize(
  Fts5Context *pCtx, 
  int iCol, 
  sqlite3_int64 *pnToken
){
  Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
  Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
  Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
  return sqlite3Fts5StorageSize(pTab->pStorage, iCol, pnToken);
}

static int fts5ApiRowCount(Fts5Context *pCtx, i64 *pnRow){
  Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
  Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
  Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
  return sqlite3Fts5StorageRowCount(pTab->pStorage, pnRow);
}

static int fts5ApiTokenize(
  Fts5Context *pCtx, 
  const char *pText, int nText, 
  void *pUserData,
1700
1701
1702
1703
1704
1705
1706
1707



1708
1709
1710
1711
1712
1713
1714
1838
1839
1840
1841
1842
1843
1844

1845
1846
1847
1848
1849
1850
1851
1852
1853
1854







-
+
+
+







  Fts5Context *pCtx, 
  int iCol, 
  const char **pz, 
  int *pn
){
  int rc = SQLITE_OK;
  Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
  if( fts5IsContentless((Fts5Table*)(pCsr->base.pVtab)) ){
  if( fts5IsContentless((Fts5FullTable*)(pCsr->base.pVtab)) 
   || pCsr->ePlan==FTS5_PLAN_SPECIAL 
  ){
    *pz = 0;
    *pn = 0;
  }else{
    rc = fts5SeekCursor(pCsr, 0);
    if( rc==SQLITE_OK ){
      *pz = (const char*)sqlite3_column_text(pCsr->pStmt, iCol+1);
      *pn = sqlite3_column_bytes(pCsr->pStmt, iCol+1);
1769
1770
1771
1772
1773
1774
1775

1776
1777
1778
1779

1780
1781
1782
1783
1784
1785
1786
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919

1920
1921
1922
1923
1924
1925
1926
1927







+



-
+







** correctly for the current view. Return SQLITE_OK if successful, or an
** SQLite error code otherwise.
*/
static int fts5CacheInstArray(Fts5Cursor *pCsr){
  int rc = SQLITE_OK;
  Fts5PoslistReader *aIter;       /* One iterator for each phrase */
  int nIter;                      /* Number of iterators/phrases */
  int nCol = ((Fts5Table*)pCsr->base.pVtab)->pConfig->nCol;
  
  nIter = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
  if( pCsr->aInstIter==0 ){
    int nByte = sizeof(Fts5PoslistReader) * nIter;
    sqlite3_int64 nByte = sizeof(Fts5PoslistReader) * nIter;
    pCsr->aInstIter = (Fts5PoslistReader*)sqlite3Fts5MallocZero(&rc, nByte);
  }
  aIter = pCsr->aInstIter;

  if( aIter ){
    int nInst = 0;                /* Number instances seen so far */
    int i;
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
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







-
-
-
+
+
+



+

+









+
+
+
+







            iBest = i;
          }
        }
        if( iBest<0 ) break;

        nInst++;
        if( nInst>=pCsr->nInstAlloc ){
          pCsr->nInstAlloc = pCsr->nInstAlloc ? pCsr->nInstAlloc*2 : 32;
          aInst = (int*)sqlite3_realloc(
              pCsr->aInst, pCsr->nInstAlloc*sizeof(int)*3
          int nNewSize = pCsr->nInstAlloc ? pCsr->nInstAlloc*2 : 32;
          aInst = (int*)sqlite3_realloc64(
              pCsr->aInst, nNewSize*sizeof(int)*3
              );
          if( aInst ){
            pCsr->aInst = aInst;
            pCsr->nInstAlloc = nNewSize;
          }else{
            nInst--;
            rc = SQLITE_NOMEM;
            break;
          }
        }

        aInst = &pCsr->aInst[3 * (nInst-1)];
        aInst[0] = iBest;
        aInst[1] = FTS5_POS2COLUMN(aIter[iBest].iPos);
        aInst[2] = FTS5_POS2OFFSET(aIter[iBest].iPos);
        if( aInst[1]<0 || aInst[1]>=nCol ){
          rc = FTS5_CORRUPT;
          break;
        }
        sqlite3Fts5PoslistReaderNext(&aIter[iBest]);
      }
    }

    pCsr->nInstCount = nInst;
    CsrFlagClear(pCsr, FTS5CSR_REQUIRE_INST);
  }
1894
1895
1896
1897
1898
1899
1900
1901
1902


1903
1904
1905
1906
1907
1908
1909
2041
2042
2043
2044
2045
2046
2047


2048
2049
2050
2051
2052
2053
2054
2055
2056







-
-
+
+







    (*pCnt)++;
  }
  return SQLITE_OK;
}

static int fts5ApiColumnSize(Fts5Context *pCtx, int iCol, int *pnToken){
  Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
  Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
  Fts5Config *pConfig = pTab->pConfig;
  Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
  Fts5Config *pConfig = pTab->p.pConfig;
  int rc = SQLITE_OK;

  if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_DOCSIZE) ){
    if( pConfig->bColumnsize ){
      i64 iRowid = fts5CursorRowid(pCsr);
      rc = sqlite3Fts5StorageDocsize(pTab->pStorage, iRowid, pCsr->aColumnSize);
    }else if( pConfig->zContent==0 ){
2032
2033
2034
2035
2036
2037
2038

2039

2040
2041
2042
2043
2044
2045
2046
2179
2180
2181
2182
2183
2184
2185
2186

2187
2188
2189
2190
2191
2192
2193
2194







+
-
+







  Fts5PhraseIter *pIter, 
  int *piCol, int *piOff
){
  Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
  int n;
  int rc = fts5CsrPoslist(pCsr, iPhrase, &pIter->a, &n);
  if( rc==SQLITE_OK ){
    assert( pIter->a || n==0 );
    pIter->b = &pIter->a[n];
    pIter->b = (pIter->a ? &pIter->a[n] : 0);
    *piCol = 0;
    *piOff = 0;
    fts5ApiPhraseNext(pCtx, pIter, piCol, piOff);
  }
  return rc;
}

2091
2092
2093
2094
2095
2096
2097

2098

2099
2100
2101
2102
2103
2104
2105

2106

2107
2108
2109
2110
2111
2112
2113
2239
2240
2241
2242
2243
2244
2245
2246

2247
2248
2249
2250
2251
2252
2253
2254
2255

2256
2257
2258
2259
2260
2261
2262
2263







+
-
+







+
-
+







      int i1 = (iPhrase==0 ? 0 : pSorter->aIdx[iPhrase-1]);
      n = pSorter->aIdx[iPhrase] - i1;
      pIter->a = &pSorter->aPoslist[i1];
    }else{
      rc = sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, iPhrase, &pIter->a, &n);
    }
    if( rc==SQLITE_OK ){
      assert( pIter->a || n==0 );
      pIter->b = &pIter->a[n];
      pIter->b = (pIter->a ? &pIter->a[n] : 0);
      *piCol = 0;
      fts5ApiPhraseNextColumn(pCtx, pIter, piCol);
    }
  }else{
    int n;
    rc = fts5CsrPoslist(pCsr, iPhrase, &pIter->a, &n);
    if( rc==SQLITE_OK ){
      assert( pIter->a || n==0 );
      pIter->b = &pIter->a[n];
      pIter->b = (pIter->a ? &pIter->a[n] : 0);
      if( n<=0 ){
        *piCol = -1;
      }else if( pIter->a[0]==0x01 ){
        pIter->a += 1 + fts5GetVarint32(&pIter->a[1], *piCol);
      }else{
        *piCol = 0;
      }
2151
2152
2153
2154
2155
2156
2157
2158

2159
2160
2161
2162
2163
2164
2165
2301
2302
2303
2304
2305
2306
2307

2308
2309
2310
2311
2312
2313
2314
2315







-
+







static int fts5ApiQueryPhrase(
  Fts5Context *pCtx, 
  int iPhrase, 
  void *pUserData,
  int(*xCallback)(const Fts5ExtensionApi*, Fts5Context*, void*)
){
  Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
  Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
  Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
  int rc;
  Fts5Cursor *pNew = 0;

  rc = fts5OpenMethod(pCsr->base.pVtab, (sqlite3_vtab_cursor**)&pNew);
  if( rc==SQLITE_OK ){
    pNew->ePlan = FTS5_PLAN_MATCH;
    pNew->iFirstRowid = SMALLEST_INT64;
2217
2218
2219
2220
2221
2222
2223
2224

2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235

2236
2237
2238
2239
2240
2241

2242
2243

2244
2245
2246
2247
2248
2249

2250

2251
2252
2253


2254
2255
2256
2257
2258
2259
2260
2367
2368
2369
2370
2371
2372
2373

2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384

2385
2386



2387

2388
2389

2390

2391
2392


2393
2394

2395



2396
2397
2398
2399
2400
2401
2402
2403
2404







-
+










-
+

-
-
-

-
+

-
+
-


-
-

+
-
+
-
-
-
+
+







  i64 iCsrId;

  assert( argc>=1 );
  pAux = (Fts5Auxiliary*)sqlite3_user_data(context);
  iCsrId = sqlite3_value_int64(argv[0]);

  pCsr = fts5CursorFromCsrid(pAux->pGlobal, iCsrId);
  if( pCsr==0 ){
  if( pCsr==0 || pCsr->ePlan==0 ){
    char *zErr = sqlite3_mprintf("no such cursor: %lld", iCsrId);
    sqlite3_result_error(context, zErr, -1);
    sqlite3_free(zErr);
  }else{
    fts5ApiInvoke(pAux, pCsr, context, argc-1, &argv[1]);
  }
}


/*
** Given cursor id iId, return a pointer to the corresponding Fts5Index 
** Given cursor id iId, return a pointer to the corresponding Fts5Table 
** object. Or NULL If the cursor id does not exist.
**
** If successful, set *ppConfig to point to the associated config object 
** before returning.
*/
Fts5Index *sqlite3Fts5IndexFromCsrid(
Fts5Table *sqlite3Fts5TableFromCsrid(
  Fts5Global *pGlobal,            /* FTS5 global context for db handle */
  i64 iCsrId,                     /* Id of cursor to find */
  i64 iCsrId                      /* Id of cursor to find */
  Fts5Config **ppConfig           /* OUT: Configuration object */
){
  Fts5Cursor *pCsr;
  Fts5Table *pTab;

  pCsr = fts5CursorFromCsrid(pGlobal, iCsrId);
  if( pCsr ){
  pTab = (Fts5Table*)pCsr->base.pVtab;
    return (Fts5Table*)pCsr->base.pVtab;
  *ppConfig = pTab->pConfig;

  return pTab->pIndex;
  }
  return 0;
}

/*
** Return a "position-list blob" corresponding to the current position of
** cursor pCsr via sqlite3_result_blob(). A position-list blob contains
** the current position-list for each phrase in the query associated with
** cursor pCsr.
2326
2327
2328
2329
2330
2331
2332
2333
2334


2335
2336
2337
2338
2339
2340
2341
2470
2471
2472
2473
2474
2475
2476


2477
2478
2479
2480
2481
2482
2483
2484
2485







-
-
+
+







** the row that the supplied cursor currently points to.
*/
static int fts5ColumnMethod(
  sqlite3_vtab_cursor *pCursor,   /* Cursor to retrieve value from */
  sqlite3_context *pCtx,          /* Context for sqlite3_result_xxx() calls */
  int iCol                        /* Index of column to read value from */
){
  Fts5Table *pTab = (Fts5Table*)(pCursor->pVtab);
  Fts5Config *pConfig = pTab->pConfig;
  Fts5FullTable *pTab = (Fts5FullTable*)(pCursor->pVtab);
  Fts5Config *pConfig = pTab->p.pConfig;
  Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
  int rc = SQLITE_OK;
  
  assert( CsrFlagTest(pCsr, FTS5CSR_EOF)==0 );

  if( pCsr->ePlan==FTS5_PLAN_SPECIAL ){
    if( iCol==pConfig->nCol ){
2359
2360
2361
2362
2363
2364
2365

2366
2367
2368
2369

2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386

2387
2388
2389
2390
2391
2392
2393
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531

2532
2533
2534
2535
2536
2537
2538
2539







+




+
















-
+







     || pCsr->ePlan==FTS5_PLAN_SORTED_MATCH
    ){
      if( pCsr->pRank || SQLITE_OK==(rc = fts5FindRankFunction(pCsr)) ){
        fts5ApiInvoke(pCsr->pRank, pCsr, pCtx, pCsr->nRankArg, pCsr->apRankArg);
      }
    }
  }else if( !fts5IsContentless(pTab) ){
    pConfig->pzErrmsg = &pTab->p.base.zErrMsg;
    rc = fts5SeekCursor(pCsr, 1);
    if( rc==SQLITE_OK ){
      sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1));
    }
    pConfig->pzErrmsg = 0;
  }
  return rc;
}


/*
** This routine implements the xFindFunction method for the FTS3
** virtual table.
*/
static int fts5FindFunctionMethod(
  sqlite3_vtab *pVtab,            /* Virtual table handle */
  int nUnused,                    /* Number of SQL function arguments */
  const char *zName,              /* Name of SQL function */
  void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */
  void **ppArg                    /* OUT: User data for *pxFunc */
){
  Fts5Table *pTab = (Fts5Table*)pVtab;
  Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
  Fts5Auxiliary *pAux;

  UNUSED_PARAM(nUnused);
  pAux = fts5FindAuxiliary(pTab, zName);
  if( pAux ){
    *pxFunc = fts5ApiCallback;
    *ppArg = (void*)pAux;
2401
2402
2403
2404
2405
2406
2407
2408

2409
2410





2411
2412
2413
2414
2415
2416
2417
2418
2419
2420

2421
2422

2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433

2434
2435

2436
2437
2438
2439
2440
2441
2442
2443
2444

2445
2446
2447
2448
2449
2450
2451
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
2547
2548
2549
2550
2551
2552
2553

2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568

2569

2570


2571
2572
2573
2574
2575
2576
2577
2578
2579

2580

2581


2582
2583
2584
2585
2586
2587
2588
2589
2590

2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611


2612
2613
2614

2615
2616

2617
2618

2619
2620
2621
2622
2623
2624
2625
2626







-
+


+
+
+
+
+







-

-
+
-
-
+








-

-
+
-
-
+








-
+




















-
-
+
+

-
+

-
+

-
+







/*
** Implementation of FTS5 xRename method. Rename an fts5 table.
*/
static int fts5RenameMethod(
  sqlite3_vtab *pVtab,            /* Virtual table handle */
  const char *zName               /* New name of table */
){
  Fts5Table *pTab = (Fts5Table*)pVtab;
  Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
  return sqlite3Fts5StorageRename(pTab->pStorage, zName);
}

int sqlite3Fts5FlushToDisk(Fts5Table *pTab){
  fts5TripCursors((Fts5FullTable*)pTab);
  return sqlite3Fts5StorageSync(((Fts5FullTable*)pTab)->pStorage);
}

/*
** The xSavepoint() method.
**
** Flush the contents of the pending-terms table to disk.
*/
static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
  Fts5Table *pTab = (Fts5Table*)pVtab;
  UNUSED_PARAM(iSavepoint);  /* Call below is a no-op for NDEBUG builds */
  fts5CheckTransactionState(pTab, FTS5_SAVEPOINT, iSavepoint);
  fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_SAVEPOINT, iSavepoint);
  fts5TripCursors(pTab);
  return sqlite3Fts5StorageSync(pTab->pStorage);
  return sqlite3Fts5FlushToDisk((Fts5Table*)pVtab);
}

/*
** The xRelease() method.
**
** This is a no-op.
*/
static int fts5ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
  Fts5Table *pTab = (Fts5Table*)pVtab;
  UNUSED_PARAM(iSavepoint);  /* Call below is a no-op for NDEBUG builds */
  fts5CheckTransactionState(pTab, FTS5_RELEASE, iSavepoint);
  fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_RELEASE, iSavepoint);
  fts5TripCursors(pTab);
  return sqlite3Fts5StorageSync(pTab->pStorage);
  return sqlite3Fts5FlushToDisk((Fts5Table*)pVtab);
}

/*
** The xRollbackTo() method.
**
** Discard the contents of the pending terms table.
*/
static int fts5RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
  Fts5Table *pTab = (Fts5Table*)pVtab;
  Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
  UNUSED_PARAM(iSavepoint);  /* Call below is a no-op for NDEBUG builds */
  fts5CheckTransactionState(pTab, FTS5_ROLLBACKTO, iSavepoint);
  fts5TripCursors(pTab);
  return sqlite3Fts5StorageRollback(pTab->pStorage);
}

/*
** Register a new auxiliary function with global context pGlobal.
*/
static int fts5CreateAux(
  fts5_api *pApi,                 /* Global context (one per db handle) */
  const char *zName,              /* Name of new function */
  void *pUserData,                /* User data for aux. function */
  fts5_extension_function xFunc,  /* Aux. function implementation */
  void(*xDestroy)(void*)          /* Destructor for pUserData */
){
  Fts5Global *pGlobal = (Fts5Global*)pApi;
  int rc = sqlite3_overload_function(pGlobal->db, zName, -1);
  if( rc==SQLITE_OK ){
    Fts5Auxiliary *pAux;
    int nName;                      /* Size of zName in bytes, including \0 */
    int nByte;                      /* Bytes of space to allocate */
    sqlite3_int64 nName;            /* Size of zName in bytes, including \0 */
    sqlite3_int64 nByte;            /* Bytes of space to allocate */

    nName = (int)strlen(zName) + 1;
    nName = strlen(zName) + 1;
    nByte = sizeof(Fts5Auxiliary) + nName;
    pAux = (Fts5Auxiliary*)sqlite3_malloc(nByte);
    pAux = (Fts5Auxiliary*)sqlite3_malloc64(nByte);
    if( pAux ){
      memset(pAux, 0, nByte);
      memset(pAux, 0, (size_t)nByte);
      pAux->zFunc = (char*)&pAux[1];
      memcpy(pAux->zFunc, zName, nName);
      pAux->pGlobal = pGlobal;
      pAux->pUserData = pUserData;
      pAux->xFunc = xFunc;
      pAux->xDestroy = xDestroy;
      pAux->pNext = pGlobal->pAux;
2495
2496
2497
2498
2499
2500
2501
2502
2503


2504
2505
2506

2507
2508

2509
2510

2511
2512
2513
2514
2515
2516
2517
2642
2643
2644
2645
2646
2647
2648


2649
2650
2651
2652

2653
2654

2655
2656

2657
2658
2659
2660
2661
2662
2663
2664







-
-
+
+


-
+

-
+

-
+







  const char *zName,              /* Name of new function */
  void *pUserData,                /* User data for aux. function */
  fts5_tokenizer *pTokenizer,     /* Tokenizer implementation */
  void(*xDestroy)(void*)          /* Destructor for pUserData */
){
  Fts5Global *pGlobal = (Fts5Global*)pApi;
  Fts5TokenizerModule *pNew;
  int nName;                      /* Size of zName and its \0 terminator */
  int nByte;                      /* Bytes of space to allocate */
  sqlite3_int64 nName;            /* Size of zName and its \0 terminator */
  sqlite3_int64 nByte;            /* Bytes of space to allocate */
  int rc = SQLITE_OK;

  nName = (int)strlen(zName) + 1;
  nName = strlen(zName) + 1;
  nByte = sizeof(Fts5TokenizerModule) + nName;
  pNew = (Fts5TokenizerModule*)sqlite3_malloc(nByte);
  pNew = (Fts5TokenizerModule*)sqlite3_malloc64(nByte);
  if( pNew ){
    memset(pNew, 0, nByte);
    memset(pNew, 0, (size_t)nByte);
    pNew->zName = (char*)&pNew[1];
    memcpy(pNew->zName, zName, nName);
    pNew->pUserData = pUserData;
    pNew->x = *pTokenizer;
    pNew->xDestroy = xDestroy;
    pNew->pNext = pGlobal->pTok;
    pGlobal->pTok = pNew;
2567
2568
2569
2570
2571
2572
2573
2574

2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590










2591
2592
2593
2594
2595
2596


2597
2598
2599
2600
2601
2602
2603
2714
2715
2716
2717
2718
2719
2720

2721

2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732




2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746


2747
2748
2749
2750
2751
2752
2753
2754
2755







-
+
-











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




-
-
+
+







  return rc;
}

int sqlite3Fts5GetTokenizer(
  Fts5Global *pGlobal, 
  const char **azArg,
  int nArg,
  Fts5Tokenizer **ppTok,
  Fts5Config *pConfig,
  fts5_tokenizer **ppTokApi,
  char **pzErr
){
  Fts5TokenizerModule *pMod;
  int rc = SQLITE_OK;

  pMod = fts5LocateTokenizer(pGlobal, nArg==0 ? 0 : azArg[0]);
  if( pMod==0 ){
    assert( nArg>0 );
    rc = SQLITE_ERROR;
    *pzErr = sqlite3_mprintf("no such tokenizer: %s", azArg[0]);
  }else{
    rc = pMod->x.xCreate(pMod->pUserData, &azArg[1], (nArg?nArg-1:0), ppTok);
    *ppTokApi = &pMod->x;
    if( rc!=SQLITE_OK && pzErr ){
      *pzErr = sqlite3_mprintf("error in tokenizer constructor");
    rc = pMod->x.xCreate(
        pMod->pUserData, (azArg?&azArg[1]:0), (nArg?nArg-1:0), &pConfig->pTok
    );
    pConfig->pTokApi = &pMod->x;
    if( rc!=SQLITE_OK ){
      if( pzErr ) *pzErr = sqlite3_mprintf("error in tokenizer constructor");
    }else{
      pConfig->ePattern = sqlite3Fts5TokenizerPattern(
          pMod->x.xCreate, pConfig->pTok
      );
    }
  }

  if( rc!=SQLITE_OK ){
    *ppTokApi = 0;
    *ppTok = 0;
    pConfig->pTokApi = 0;
    pConfig->pTok = 0;
  }

  return rc;
}

static void fts5ModuleDestroy(void *pCtx){
  Fts5TokenizerModule *pTok, *pNextTok;
2711
2712
2713
2714
2715
2716
2717
2718



2719
2720
2721
2722
2723
2724
2725
2863
2864
2865
2866
2867
2868
2869

2870
2871
2872
2873
2874
2875
2876
2877
2878
2879







-
+
+
+







    if( rc==SQLITE_OK ){
      rc = sqlite3_create_function(
          db, "fts5", 1, SQLITE_UTF8, p, fts5Fts5Func, 0, 0
      );
    }
    if( rc==SQLITE_OK ){
      rc = sqlite3_create_function(
          db, "fts5_source_id", 0, SQLITE_UTF8, p, fts5SourceIdFunc, 0, 0
          db, "fts5_source_id", 0, 
          SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS,
          p, fts5SourceIdFunc, 0, 0
      );
    }
  }

  /* If SQLITE_FTS5_ENABLE_TEST_MI is defined, assume that the file
  ** fts5_test_mi.c is compiled and linked into the executable. And call
  ** its entry point to enable the matchinfo() demo.  */

Changes to ext/fts5/fts5_storage.c.

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







-
+




















+
+
+
-
+
-
+








      case FTS5_STMT_INSERT_CONTENT: 
      case FTS5_STMT_REPLACE_CONTENT: {
        int nCol = pC->nCol + 1;
        char *zBind;
        int i;

        zBind = sqlite3_malloc(1 + nCol*2);
        zBind = sqlite3_malloc64(1 + nCol*2);
        if( zBind ){
          for(i=0; i<nCol; i++){
            zBind[i*2] = '?';
            zBind[i*2 + 1] = ',';
          }
          zBind[i*2-1] = '\0';
          zSql = sqlite3_mprintf(azStmt[eStmt], pC->zDb, pC->zName, zBind);
          sqlite3_free(zBind);
        }
        break;
      }

      default:
        zSql = sqlite3_mprintf(azStmt[eStmt], pC->zDb, pC->zName);
        break;
    }

    if( zSql==0 ){
      rc = SQLITE_NOMEM;
    }else{
      int f = SQLITE_PREPARE_PERSISTENT;
      if( eStmt>FTS5_STMT_LOOKUP ) f |= SQLITE_PREPARE_NO_VTAB;
      p->pConfig->bLock++;
      rc = sqlite3_prepare_v3(pC->db, zSql, -1,
      rc = sqlite3_prepare_v3(pC->db, zSql, -1, f, &p->aStmt[eStmt], 0);
                              SQLITE_PREPARE_PERSISTENT, &p->aStmt[eStmt], 0);
      p->pConfig->bLock--;
      sqlite3_free(zSql);
      if( rc!=SQLITE_OK && pzErrMsg ){
        *pzErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pC->db));
      }
    }
  }

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







-
+



-
+


-
+







-
+







  Fts5Index *pIndex, 
  int bCreate, 
  Fts5Storage **pp,
  char **pzErr                    /* OUT: Error message */
){
  int rc = SQLITE_OK;
  Fts5Storage *p;                 /* New object */
  int nByte;                      /* Bytes of space to allocate */
  sqlite3_int64 nByte;            /* Bytes of space to allocate */

  nByte = sizeof(Fts5Storage)               /* Fts5Storage object */
        + pConfig->nCol * sizeof(i64);      /* Fts5Storage.aTotalSize[] */
  *pp = p = (Fts5Storage*)sqlite3_malloc(nByte);
  *pp = p = (Fts5Storage*)sqlite3_malloc64(nByte);
  if( !p ) return SQLITE_NOMEM;

  memset(p, 0, nByte);
  memset(p, 0, (size_t)nByte);
  p->aTotalSize = (i64*)&p[1];
  p->pConfig = pConfig;
  p->pIndex = pIndex;

  if( bCreate ){
    if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
      int nDefn = 32 + pConfig->nCol*10;
      char *zDefn = sqlite3_malloc(32 + pConfig->nCol * 10);
      char *zDefn = sqlite3_malloc64(32 + (sqlite3_int64)pConfig->nCol * 10);
      if( zDefn==0 ){
        rc = SQLITE_NOMEM;
      }else{
        int i;
        int iOff;
        sqlite3_snprintf(nDefn, zDefn, "id INTEGER PRIMARY KEY");
        iOff = (int)strlen(zDefn);
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
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







+
+



-
+


+
+






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







  ctx.pStorage = p;
  ctx.iCol = -1;
  rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 1, iDel);
  for(iCol=1; rc==SQLITE_OK && iCol<=pConfig->nCol; iCol++){
    if( pConfig->abUnindexed[iCol-1]==0 ){
      const char *zText;
      int nText;
      assert( pSeek==0 || apVal==0 );
      assert( pSeek!=0 || apVal!=0 );
      if( pSeek ){
        zText = (const char*)sqlite3_column_text(pSeek, iCol);
        nText = sqlite3_column_bytes(pSeek, iCol);
      }else{
      }else if( ALWAYS(apVal) ){
        zText = (const char*)sqlite3_value_text(apVal[iCol-1]);
        nText = sqlite3_value_bytes(apVal[iCol-1]);
      }else{
        continue;
      }
      ctx.szCol = 0;
      rc = sqlite3Fts5Tokenize(pConfig, FTS5_TOKENIZE_DOCUMENT, 
          zText, nText, (void*)&ctx, fts5StorageInsertCallback
      );
      p->aTotalSize[iCol-1] -= (i64)ctx.szCol;
      if( p->aTotalSize[iCol-1]<0 ){
        rc = FTS5_CORRUPT;
    }
  }
  p->nTotalRow--;
      }
    }
  }
  if( rc==SQLITE_OK && p->nTotalRow<1 ){
    rc = FTS5_CORRUPT;
  }else{
    p->nTotalRow--;
  }

  rc2 = sqlite3_reset(pSeek);
  if( rc==SQLITE_OK ) rc = rc2;
  return rc;
}


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







+
+








/*
** Delete all entries in the FTS5 index.
*/
int sqlite3Fts5StorageDeleteAll(Fts5Storage *p){
  Fts5Config *pConfig = p->pConfig;
  int rc;

  p->bTotalsValid = 0;

  /* Delete the contents of the %_data and %_docsize tables. */
  rc = fts5ExecPrintf(pConfig->db, 0,
      "DELETE FROM %Q.'%q_data';" 
      "DELETE FROM %Q.'%q_idx';",
      pConfig->zDb, pConfig->zName,
      pConfig->zDb, pConfig->zName
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
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







-
+




















+
+


-
-
+














+
+







}

int sqlite3Fts5StorageRebuild(Fts5Storage *p){
  Fts5Buffer buf = {0,0,0};
  Fts5Config *pConfig = p->pConfig;
  sqlite3_stmt *pScan = 0;
  Fts5InsertCtx ctx;
  int rc;
  int rc, rc2;

  memset(&ctx, 0, sizeof(Fts5InsertCtx));
  ctx.pStorage = p;
  rc = sqlite3Fts5StorageDeleteAll(p);
  if( rc==SQLITE_OK ){
    rc = fts5StorageLoadTotals(p, 1);
  }

  if( rc==SQLITE_OK ){
    rc = fts5StorageGetStmt(p, FTS5_STMT_SCAN, &pScan, 0);
  }

  while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pScan) ){
    i64 iRowid = sqlite3_column_int64(pScan, 0);

    sqlite3Fts5BufferZero(&buf);
    rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 0, iRowid);
    for(ctx.iCol=0; rc==SQLITE_OK && ctx.iCol<pConfig->nCol; ctx.iCol++){
      ctx.szCol = 0;
      if( pConfig->abUnindexed[ctx.iCol]==0 ){
        const char *zText = (const char*)sqlite3_column_text(pScan, ctx.iCol+1);
        int nText = sqlite3_column_bytes(pScan, ctx.iCol+1);
        rc = sqlite3Fts5Tokenize(pConfig, 
            FTS5_TOKENIZE_DOCUMENT,
            (const char*)sqlite3_column_text(pScan, ctx.iCol+1),
            sqlite3_column_bytes(pScan, ctx.iCol+1),
            zText, nText,
            (void*)&ctx,
            fts5StorageInsertCallback
        );
      }
      sqlite3Fts5BufferAppendVarint(&rc, &buf, ctx.szCol);
      p->aTotalSize[ctx.iCol] += (i64)ctx.szCol;
    }
    p->nTotalRow++;

    if( rc==SQLITE_OK ){
      rc = fts5StorageInsertDocsize(p, iRowid, &buf);
    }
  }
  sqlite3_free(buf.p);
  rc2 = sqlite3_reset(pScan);
  if( rc==SQLITE_OK ) rc = rc2;

  /* Write the averages record */
  if( rc==SQLITE_OK ){
    rc = fts5StorageSaveTotals(p);
  }
  return rc;
}
727
728
729
730
731
732
733


734
735
736
737

738
739
740
741
742
743
744
746
747
748
749
750
751
752
753
754
755
756


757
758
759
760
761
762
763
764







+
+


-
-
+








  if( rc==SQLITE_OK ){
    rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 0, iRowid);
  }
  for(ctx.iCol=0; rc==SQLITE_OK && ctx.iCol<pConfig->nCol; ctx.iCol++){
    ctx.szCol = 0;
    if( pConfig->abUnindexed[ctx.iCol]==0 ){
      const char *zText = (const char*)sqlite3_value_text(apVal[ctx.iCol+2]);
      int nText = sqlite3_value_bytes(apVal[ctx.iCol+2]);
      rc = sqlite3Fts5Tokenize(pConfig, 
          FTS5_TOKENIZE_DOCUMENT,
          (const char*)sqlite3_value_text(apVal[ctx.iCol+2]),
          sqlite3_value_bytes(apVal[ctx.iCol+2]),
          zText, nText,
          (void*)&ctx,
          fts5StorageInsertCallback
      );
    }
    sqlite3Fts5BufferAppendVarint(&rc, &buf, ctx.szCol);
    p->aTotalSize[ctx.iCol] += (i64)ctx.szCol;
  }
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
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
935
936
937
938
939








940
941
942
943
944
945
946
947
948
949
950
951












952
953
954
955
956
957
958

959
960
961
962
963
964
965
881
882
883
884
885
886
887

888
889

890
891
892
893
894
895
896
897
898

899
900
901
902
903
904
905
906
907


























908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935






















936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957








958
959
960
961
962
963
964
965
966











967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984

985
986
987
988
989
990
991
992







-
+

-
+




+



-
+




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

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

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






-
+








/*
** Check that the contents of the FTS index match that of the %_content
** table. Return SQLITE_OK if they do, or SQLITE_CORRUPT if not. Return
** some other SQLite error code if an error occurs while attempting to
** determine this.
*/
int sqlite3Fts5StorageIntegrity(Fts5Storage *p){
int sqlite3Fts5StorageIntegrity(Fts5Storage *p, int iArg){
  Fts5Config *pConfig = p->pConfig;
  int rc;                         /* Return code */
  int rc = SQLITE_OK;             /* Return code */
  int *aColSize;                  /* Array of size pConfig->nCol */
  i64 *aTotalSize;                /* Array of size pConfig->nCol */
  Fts5IntegrityCtx ctx;
  sqlite3_stmt *pScan;
  int bUseCksum;

  memset(&ctx, 0, sizeof(Fts5IntegrityCtx));
  ctx.pConfig = p->pConfig;
  aTotalSize = (i64*)sqlite3_malloc(pConfig->nCol * (sizeof(int)+sizeof(i64)));
  aTotalSize = (i64*)sqlite3_malloc64(pConfig->nCol*(sizeof(int)+sizeof(i64)));
  if( !aTotalSize ) return SQLITE_NOMEM;
  aColSize = (int*)&aTotalSize[pConfig->nCol];
  memset(aTotalSize, 0, sizeof(i64) * pConfig->nCol);

  bUseCksum = (pConfig->eContent==FTS5_CONTENT_NORMAL
           || (pConfig->eContent==FTS5_CONTENT_EXTERNAL && iArg)
  );
  if( bUseCksum ){
  /* Generate the expected index checksum based on the contents of the
  ** %_content table. This block stores the checksum in ctx.cksum. */
  rc = fts5StorageGetStmt(p, FTS5_STMT_SCAN, &pScan, 0);
  if( rc==SQLITE_OK ){
    int rc2;
    while( SQLITE_ROW==sqlite3_step(pScan) ){
      int i;
      ctx.iRowid = sqlite3_column_int64(pScan, 0);
      ctx.szCol = 0;
      if( pConfig->bColumnsize ){
        rc = sqlite3Fts5StorageDocsize(p, ctx.iRowid, aColSize);
      }
      if( rc==SQLITE_OK && pConfig->eDetail==FTS5_DETAIL_NONE ){
        rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
      }
      for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
        if( pConfig->abUnindexed[i] ) continue;
        ctx.iCol = i;
        ctx.szCol = 0;
        if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
          rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
        }
        if( rc==SQLITE_OK ){
          rc = sqlite3Fts5Tokenize(pConfig, 
              FTS5_TOKENIZE_DOCUMENT,
              (const char*)sqlite3_column_text(pScan, i+1),
    /* Generate the expected index checksum based on the contents of the
    ** %_content table. This block stores the checksum in ctx.cksum. */
    rc = fts5StorageGetStmt(p, FTS5_STMT_SCAN, &pScan, 0);
    if( rc==SQLITE_OK ){
      int rc2;
      while( SQLITE_ROW==sqlite3_step(pScan) ){
        int i;
        ctx.iRowid = sqlite3_column_int64(pScan, 0);
        ctx.szCol = 0;
        if( pConfig->bColumnsize ){
          rc = sqlite3Fts5StorageDocsize(p, ctx.iRowid, aColSize);
        }
        if( rc==SQLITE_OK && pConfig->eDetail==FTS5_DETAIL_NONE ){
          rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
        }
        for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
          if( pConfig->abUnindexed[i] ) continue;
          ctx.iCol = i;
          ctx.szCol = 0;
          if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
            rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
          }
          if( rc==SQLITE_OK ){
            const char *zText = (const char*)sqlite3_column_text(pScan, i+1);
            int nText = sqlite3_column_bytes(pScan, i+1);
            rc = sqlite3Fts5Tokenize(pConfig, 
                FTS5_TOKENIZE_DOCUMENT,
                zText, nText,
              sqlite3_column_bytes(pScan, i+1),
              (void*)&ctx,
              fts5StorageIntegrityCallback
          );
        }
        if( rc==SQLITE_OK && pConfig->bColumnsize && ctx.szCol!=aColSize[i] ){
          rc = FTS5_CORRUPT;
        }
        aTotalSize[i] += ctx.szCol;
        if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
          sqlite3Fts5TermsetFree(ctx.pTermset);
          ctx.pTermset = 0;
        }
      }
      sqlite3Fts5TermsetFree(ctx.pTermset);
      ctx.pTermset = 0;

      if( rc!=SQLITE_OK ) break;
    }
    rc2 = sqlite3_reset(pScan);
    if( rc==SQLITE_OK ) rc = rc2;
  }
                (void*)&ctx,
                fts5StorageIntegrityCallback
            );
          }
          if( rc==SQLITE_OK && pConfig->bColumnsize && ctx.szCol!=aColSize[i] ){
            rc = FTS5_CORRUPT;
          }
          aTotalSize[i] += ctx.szCol;
          if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
            sqlite3Fts5TermsetFree(ctx.pTermset);
            ctx.pTermset = 0;
          }
        }
        sqlite3Fts5TermsetFree(ctx.pTermset);
        ctx.pTermset = 0;
  
        if( rc!=SQLITE_OK ) break;
      }
      rc2 = sqlite3_reset(pScan);
      if( rc==SQLITE_OK ) rc = rc2;
    }

  /* Test that the "totals" (sometimes called "averages") record looks Ok */
  if( rc==SQLITE_OK ){
    int i;
    rc = fts5StorageLoadTotals(p, 0);
    for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
      if( p->aTotalSize[i]!=aTotalSize[i] ) rc = FTS5_CORRUPT;
    }
  }
    /* Test that the "totals" (sometimes called "averages") record looks Ok */
    if( rc==SQLITE_OK ){
      int i;
      rc = fts5StorageLoadTotals(p, 0);
      for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
        if( p->aTotalSize[i]!=aTotalSize[i] ) rc = FTS5_CORRUPT;
      }
    }

  /* Check that the %_docsize and %_content tables contain the expected
  ** number of rows.  */
  if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){
    i64 nRow = 0;
    rc = fts5StorageCount(p, "content", &nRow);
    if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT;
  }
  if( rc==SQLITE_OK && pConfig->bColumnsize ){
    i64 nRow = 0;
    rc = fts5StorageCount(p, "docsize", &nRow);
    if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT;
    /* Check that the %_docsize and %_content tables contain the expected
    ** number of rows.  */
    if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){
      i64 nRow = 0;
      rc = fts5StorageCount(p, "content", &nRow);
      if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT;
    }
    if( rc==SQLITE_OK && pConfig->bColumnsize ){
      i64 nRow = 0;
      rc = fts5StorageCount(p, "docsize", &nRow);
      if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT;
    }
  }

  /* Pass the expected checksum down to the FTS index module. It will
  ** verify, amongst other things, that it matches the checksum generated by
  ** inspecting the index itself.  */
  if( rc==SQLITE_OK ){
    rc = sqlite3Fts5IndexIntegrityCheck(p->pIndex, ctx.cksum);
    rc = sqlite3Fts5IndexIntegrityCheck(p->pIndex, ctx.cksum, bUseCksum);
  }

  sqlite3_free(aTotalSize);
  return rc;
}

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







-
+

+












+
+







int sqlite3Fts5StorageDocsize(Fts5Storage *p, i64 iRowid, int *aCol){
  int nCol = p->pConfig->nCol;    /* Number of user columns in table */
  sqlite3_stmt *pLookup = 0;      /* Statement to query %_docsize */
  int rc;                         /* Return Code */

  assert( p->pConfig->bColumnsize );
  rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP_DOCSIZE, &pLookup, 0);
  if( rc==SQLITE_OK ){
  if( pLookup ){
    int bCorrupt = 1;
    assert( rc==SQLITE_OK );
    sqlite3_bind_int64(pLookup, 1, iRowid);
    if( SQLITE_ROW==sqlite3_step(pLookup) ){
      const u8 *aBlob = sqlite3_column_blob(pLookup, 0);
      int nBlob = sqlite3_column_bytes(pLookup, 0);
      if( 0==fts5StorageDecodeSizeArray(aCol, nCol, aBlob, nBlob) ){
        bCorrupt = 0;
      }
    }
    rc = sqlite3_reset(pLookup);
    if( bCorrupt && rc==SQLITE_OK ){
      rc = FTS5_CORRUPT;
    }
  }else{
    assert( rc!=SQLITE_OK );
  }

  return rc;
}

int sqlite3Fts5StorageSize(Fts5Storage *p, int iCol, i64 *pnToken){
  int rc = fts5StorageLoadTotals(p, 0);
1071
1072
1073
1074
1075
1076
1077





1078

1079
1080
1081
1082
1083
1084
1085
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121







+
+
+
+
+

+







  }
  return rc;
}

int sqlite3Fts5StorageRowCount(Fts5Storage *p, i64 *pnRow){
  int rc = fts5StorageLoadTotals(p, 0);
  if( rc==SQLITE_OK ){
    /* nTotalRow being zero does not necessarily indicate a corrupt 
    ** database - it might be that the FTS5 table really does contain zero
    ** rows. However this function is only called from the xRowCount() API,
    ** and there is no way for that API to be invoked if the table contains
    ** no rows. Hence the FTS5_CORRUPT return.  */
    *pnRow = p->nTotalRow;
    if( p->nTotalRow<=0 ) rc = FTS5_CORRUPT;
  }
  return rc;
}

/*
** Flush any data currently held in-memory to disk.
*/

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/fts5_test_mi.c.

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







-
+




















-
+







  const char *zArg                /* Matchinfo flag string */
){
  Fts5MatchinfoCtx *p;
  int nCol;
  int nPhrase;
  int i;
  int nInt;
  int nByte;
  sqlite3_int64 nByte;
  int rc;

  nCol = pApi->xColumnCount(pFts);
  nPhrase = pApi->xPhraseCount(pFts);

  nInt = 0;
  for(i=0; zArg[i]; i++){
    int n = fts5MatchinfoFlagsize(nCol, nPhrase, zArg[i]);
    if( n<0 ){
      char *zErr = sqlite3_mprintf("unrecognized matchinfo flag: %c", zArg[i]);
      sqlite3_result_error(pCtx, zErr, -1);
      sqlite3_free(zErr);
      return 0;
    }
    nInt += n;
  }

  nByte = sizeof(Fts5MatchinfoCtx)          /* The struct itself */
         + sizeof(u32) * nInt               /* The p->aRet[] array */
         + (i+1);                           /* The p->zArg string */
  p = (Fts5MatchinfoCtx*)sqlite3_malloc(nByte);
  p = (Fts5MatchinfoCtx*)sqlite3_malloc64(nByte);
  if( p==0 ){
    sqlite3_result_error_nomem(pCtx);
    return 0;
  }
  memset(p, 0, nByte);

  p->nCol = nCol;

Changes to ext/fts5/fts5_test_tok.c.

133
134
135
136
137
138
139
140

141
142
143
144
145
146
147
133
134
135
136
137
138
139

140
141
142
143
144
145
146
147







-
+







    int nByte = 0;
    char **azDequote;

    for(i=0; i<argc; i++){
      nByte += (int)(strlen(argv[i]) + 1);
    }

    *pazDequote = azDequote = sqlite3_malloc(sizeof(char *)*argc + nByte);
    *pazDequote = azDequote = sqlite3_malloc64(sizeof(char *)*argc + nByte);
    if( azDequote==0 ){
      rc = SQLITE_NOMEM;
    }else{
      char *pSpace = (char *)&azDequote[argc];
      for(i=0; i<argc; i++){
        int n = (int)strlen(argv[i]);
        azDequote[i] = pSpace;
207
208
209
210
211
212
213
214

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

214
215
216
217
218
219
220
221







-
+







    const char *zModule = 0;
    if( nDequote>0 ){
      zModule = azDequote[0];
    }

    rc = pApi->xFindTokenizer(pApi, zModule, &pTokCtx, &pTab->tok);
    if( rc==SQLITE_OK ){
      const char **azArg = (const char **)&azDequote[1];
      const char **azArg = (nDequote>1 ? (const char **)&azDequote[1] : 0);
      int nArg = nDequote>0 ? nDequote-1 : 0;
      rc = pTab->tok.xCreate(pTokCtx, azArg, nArg, &pTab->pTok);
    }
  }

  if( rc!=SQLITE_OK ){
    sqlite3_free(pTab);
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







-
+







){
  Fts5tokCursor *pCsr = (Fts5tokCursor*)pCtx;
  Fts5tokRow *pRow;

  if( (pCsr->nRow & (pCsr->nRow-1))==0 ){
    int nNew = pCsr->nRow ? pCsr->nRow*2 : 32;
    Fts5tokRow *aNew;
    aNew = (Fts5tokRow*)sqlite3_realloc(pCsr->aRow, nNew*sizeof(Fts5tokRow));
    aNew = (Fts5tokRow*)sqlite3_realloc64(pCsr->aRow, nNew*sizeof(Fts5tokRow));
    if( aNew==0 ) return SQLITE_NOMEM;
    memset(&aNew[pCsr->nRow], 0, sizeof(Fts5tokRow)*(nNew-pCsr->nRow));
    pCsr->aRow = aNew;
  }

  pRow = &pCsr->aRow[pCsr->nRow];
  pRow->iStart = iStart;
374
375
376
377
378
379
380
381

382
383
384
385
386
387
388
374
375
376
377
378
379
380

381
382
383
384
385
386
387
388







-
+







  if( idxNum==1 ){
    const char *zByte = (const char *)sqlite3_value_text(apVal[0]);
    int nByte = sqlite3_value_bytes(apVal[0]);
    pCsr->zInput = sqlite3_malloc(nByte+1);
    if( pCsr->zInput==0 ){
      rc = SQLITE_NOMEM;
    }else{
      memcpy(pCsr->zInput, zByte, nByte);
      if( nByte>0 ) memcpy(pCsr->zInput, zByte, nByte);
      pCsr->zInput[nByte] = 0;
      rc = pTab->tok.xTokenize(
          pTab->pTok, (void*)pCsr, 0, zByte, nByte, fts5tokCb
      );
    }
  }

Changes to ext/fts5/fts5_tokenize.c.

148
149
150
151
152
153
154
155

156
157
158
159
160
161
162
148
149
150
151
152
153
154

155
156
157
158
159
160
161
162







-
+







      ie++;
    }

    /* Fold to lower case */
    nByte = ie-is;
    if( nByte>nFold ){
      if( pFold!=aFold ) sqlite3_free(pFold);
      pFold = sqlite3_malloc(nByte*2);
      pFold = sqlite3_malloc64((sqlite3_int64)nByte*2);
      if( pFold==0 ){
        rc = SQLITE_NOMEM;
        break;
      }
      nFold = nByte*2;
    }
    asciiFold(pFold, &pText[is], nByte);
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
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







-
+
+





-
+











-
+







  int bTokenChars                 /* 1 for 'tokenchars', 0 for 'separators' */
){
  int rc = SQLITE_OK;
  int n = (int)strlen(z);
  int *aNew;

  if( n>0 ){
    aNew = (int*)sqlite3_realloc(p->aiException, (n+p->nException)*sizeof(int));
    aNew = (int*)sqlite3_realloc64(p->aiException,
                                   (n+p->nException)*sizeof(int));
    if( aNew ){
      int nNew = p->nException;
      const unsigned char *zCsr = (const unsigned char*)z;
      const unsigned char *zTerm = (const unsigned char*)&z[n];
      while( zCsr<zTerm ){
        int iCode;
        u32 iCode;
        int bToken;
        READ_UTF8(zCsr, zTerm, iCode);
        if( iCode<128 ){
          p->aTokenChar[iCode] = (unsigned char)bTokenChars;
        }else{
          bToken = p->aCategory[sqlite3Fts5UnicodeCategory(iCode)];
          assert( (bToken==0 || bToken==1) ); 
          assert( (bTokenChars==0 || bTokenChars==1) );
          if( bToken!=bTokenChars && sqlite3Fts5UnicodeIsdiacritic(iCode)==0 ){
            int i;
            for(i=0; i<nNew; i++){
              if( aNew[i]>iCode ) break;
              if( (u32)aNew[i]>iCode ) break;
            }
            memmove(&aNew[i+1], &aNew[i], (nNew-i)*sizeof(int));
            aNew[i] = iCode;
            nNew++;
          }
        }
      }
364
365
366
367
368
369
370
371

372
373
374
375
376
377
378
365
366
367
368
369
370
371

372
373
374
375
376
377
378
379







-
+







    if( p ){
      const char *zCat = "L* N* Co";
      int i;
      memset(p, 0, sizeof(Unicode61Tokenizer));

      p->eRemoveDiacritic = FTS5_REMOVE_DIACRITICS_SIMPLE;
      p->nFold = 64;
      p->aFold = sqlite3_malloc(p->nFold * sizeof(char));
      p->aFold = sqlite3_malloc64(p->nFold * sizeof(char));
      if( p->aFold==0 ){
        rc = SQLITE_NOMEM;
      }

      /* Search for a "categories" argument */
      for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
        if( 0==sqlite3_stricmp(azArg[i], "categories") ){
425
426
427
428
429
430
431
432

433
434
435
436
437
438
439
426
427
428
429
430
431
432

433
434
435
436
437
438
439
440







-
+







/*
** Return true if, for the purposes of tokenizing with the tokenizer
** passed as the first argument, codepoint iCode is considered a token 
** character (not a separator).
*/
static int fts5UnicodeIsAlnum(Unicode61Tokenizer *p, int iCode){
  return (
    p->aCategory[sqlite3Fts5UnicodeCategory(iCode)]
    p->aCategory[sqlite3Fts5UnicodeCategory((u32)iCode)]
    ^ fts5UnicodeIsException(p, iCode)
  );
}

static int fts5UnicodeTokenize(
  Fts5Tokenizer *pTokenizer,
  void *pCtx,
454
455
456
457
458
459
460
461

462
463
464
465
466
467
468
455
456
457
458
459
460
461

462
463
464
465
466
467
468
469







-
+







  const char *pEnd = &aFold[nFold-6];

  UNUSED_PARAM(iUnused);

  /* Each iteration of this loop gobbles up a contiguous run of separators,
  ** then the next token.  */
  while( rc==SQLITE_OK ){
    int iCode;                    /* non-ASCII codepoint read from input */
    u32 iCode;                    /* non-ASCII codepoint read from input */
    char *zOut = aFold;
    int is;
    int ie;

    /* Skip any separator characters. */
    while( 1 ){
      if( zCsr>=zTerm ) goto tokenize_done;
486
487
488
489
490
491
492
493

494
495
496
497
498
499
500
487
488
489
490
491
492
493

494
495
496
497
498
499
500
501







-
+







    /* Run through the tokenchars. Fold them into the output buffer along
    ** the way.  */
    while( zCsr<zTerm ){

      /* Grow the output buffer so that there is sufficient space to fit the
      ** largest possible utf-8 character.  */
      if( zOut>pEnd ){
        aFold = sqlite3_malloc(nFold*2);
        aFold = sqlite3_malloc64((sqlite3_int64)nFold*2);
        if( aFold==0 ){
          rc = SQLITE_NOMEM;
          goto tokenize_done;
        }
        zOut = &aFold[zOut - p->aFold];
        memcpy(aFold, p->aFold, nFold);
        sqlite3_free(p->aFold);
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
1286
1287
1288
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
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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









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












+
















-
-
  sCtx.xToken = xToken;
  sCtx.pCtx = pCtx;
  sCtx.aBuf = p->aBuf;
  return p->tokenizer.xTokenize(
      p->pTokenizer, (void*)&sCtx, flags, pText, nText, fts5PorterCb
  );
}

/**************************************************************************
** Start of trigram implementation.
*/
typedef struct TrigramTokenizer TrigramTokenizer;
struct TrigramTokenizer {
  int bFold;                      /* True to fold to lower-case */
};

/*
** Free a trigram tokenizer.
*/
static void fts5TriDelete(Fts5Tokenizer *p){
  sqlite3_free(p);
}

/*
** Allocate a trigram tokenizer.
*/
static int fts5TriCreate(
  void *pUnused,
  const char **azArg,
  int nArg,
  Fts5Tokenizer **ppOut
){
  int rc = SQLITE_OK;
  TrigramTokenizer *pNew = (TrigramTokenizer*)sqlite3_malloc(sizeof(*pNew));
  UNUSED_PARAM(pUnused);
  if( pNew==0 ){
    rc = SQLITE_NOMEM;
  }else{
    int i;
    pNew->bFold = 1;
    for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
      const char *zArg = azArg[i+1];
      if( 0==sqlite3_stricmp(azArg[i], "case_sensitive") ){
        if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1] ){
          rc = SQLITE_ERROR;
        }else{
          pNew->bFold = (zArg[0]=='0');
        }
      }else{
        rc = SQLITE_ERROR;
      }
    }
    if( rc!=SQLITE_OK ){
      fts5TriDelete((Fts5Tokenizer*)pNew);
      pNew = 0;
    }
  }
  *ppOut = (Fts5Tokenizer*)pNew;
  return rc;
}

/*
** Trigram tokenizer tokenize routine.
*/
static int fts5TriTokenize(
  Fts5Tokenizer *pTok,
  void *pCtx,
  int unusedFlags,
  const char *pText, int nText,
  int (*xToken)(void*, int, const char*, int, int, int)
){
  TrigramTokenizer *p = (TrigramTokenizer*)pTok;
  int rc = SQLITE_OK;
  char aBuf[32];
  const unsigned char *zIn = (const unsigned char*)pText;
  const unsigned char *zEof = &zIn[nText];
  u32 iCode;

  UNUSED_PARAM(unusedFlags);
  while( 1 ){
    char *zOut = aBuf;
    int iStart = zIn - (const unsigned char*)pText;
    const unsigned char *zNext; 

    READ_UTF8(zIn, zEof, iCode);
    if( iCode==0 ) break;
    zNext = zIn;
    if( zIn<zEof ){
      if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, 0);
      WRITE_UTF8(zOut, iCode);
      READ_UTF8(zIn, zEof, iCode);
      if( iCode==0 ) break;
    }else{
      break;
    }
    if( zIn<zEof ){
      if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, 0);
      WRITE_UTF8(zOut, iCode);
      READ_UTF8(zIn, zEof, iCode);
      if( iCode==0 ) break;
      if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, 0);
      WRITE_UTF8(zOut, iCode);
    }else{
      break;
    }
    rc = xToken(pCtx, 0, aBuf, zOut-aBuf, iStart, iStart + zOut-aBuf);
    if( rc!=SQLITE_OK ) break;
    zIn = zNext;
  }

  return rc;
}

/*
** Argument xCreate is a pointer to a constructor function for a tokenizer.
** pTok is a tokenizer previously created using the same method. This function
** returns one of FTS5_PATTERN_NONE, FTS5_PATTERN_LIKE or FTS5_PATTERN_GLOB
** indicating the style of pattern matching that the tokenizer can support.
** In practice, this is:
**
**     "trigram" tokenizer, case_sensitive=1 - FTS5_PATTERN_GLOB
**     "trigram" tokenizer, case_sensitive=0 (the default) - FTS5_PATTERN_LIKE
**     all other tokenizers - FTS5_PATTERN_NONE
*/
int sqlite3Fts5TokenizerPattern(
    int (*xCreate)(void*, const char**, int, Fts5Tokenizer**),
    Fts5Tokenizer *pTok
){
  if( xCreate==fts5TriCreate ){
    TrigramTokenizer *p = (TrigramTokenizer*)pTok;
    return p->bFold ? FTS5_PATTERN_LIKE : FTS5_PATTERN_GLOB;
  }
  return FTS5_PATTERN_NONE;
}

/*
** Register all built-in tokenizers with FTS5.
*/
int sqlite3Fts5TokenizerInit(fts5_api *pApi){
  struct BuiltinTokenizer {
    const char *zName;
    fts5_tokenizer x;
  } aBuiltin[] = {
    { "unicode61", {fts5UnicodeCreate, fts5UnicodeDelete, fts5UnicodeTokenize}},
    { "ascii",     {fts5AsciiCreate, fts5AsciiDelete, fts5AsciiTokenize }},
    { "porter",    {fts5PorterCreate, fts5PorterDelete, fts5PorterTokenize }},
    { "trigram",   {fts5TriCreate, fts5TriDelete, fts5TriTokenize}},
  };
  
  int rc = SQLITE_OK;             /* Return code */
  int i;                          /* To iterate through builtin functions */

  for(i=0; rc==SQLITE_OK && i<ArraySize(aBuiltin); i++){
    rc = pApi->xCreateTokenizer(pApi,
        aBuiltin[i].zName,
        (void*)pApi,
        &aBuiltin[i].x,
        0
    );
  }

  return rc;
}


Changes to ext/fts5/fts5_unicode2.c.

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
** 2012 May 25
** 2012-05-25
**
** 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.
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
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







-
-
+
+




















-
+







    61726, 61784, 61800, 61816, 61836, 61880, 61896, 61914, 
    61948, 61998, 62062, 62122, 62154, 62184, 62200, 62218, 
    62252, 62302, 62364, 62410, 62442, 62478, 62536, 62554, 
    62584, 62604, 62640, 62648, 62656, 62664, 62730, 62766, 
    62830, 62890, 62924, 62974, 63032, 63050, 63082, 63118, 
    63182, 63242, 63274, 63310, 63368, 63390, 
  };
#define HIBIT ((char)0x80)
  char aChar[] = {
#define HIBIT ((unsigned char)0x80)
  unsigned char aChar[] = {
    '\0',      'a',       'c',       'e',       'i',       'n',       
    'o',       'u',       'y',       'y',       'a',       'c',       
    'd',       'e',       'e',       'g',       'h',       'i',       
    'j',       'k',       'l',       'n',       'o',       'r',       
    's',       't',       'u',       'u',       'w',       'y',       
    'z',       'o',       'u',       'a',       'i',       'o',       
    'u',       'u'|HIBIT, 'a'|HIBIT, 'g',       'k',       'o',       
    'o'|HIBIT, 'j',       'g',       'n',       'a'|HIBIT, 'a',       
    'e',       'i',       'o',       'r',       'u',       's',       
    't',       'h',       'a',       'e',       'o'|HIBIT, 'o',       
    'o'|HIBIT, 'y',       '\0',      '\0',      '\0',      '\0',      
    '\0',      '\0',      '\0',      '\0',      'a',       'b',       
    'c'|HIBIT, 'd',       'd',       'e'|HIBIT, 'e',       'e'|HIBIT, 
    'f',       'g',       'h',       'h',       'i',       'i'|HIBIT, 
    'k',       'l',       'l'|HIBIT, 'l',       'm',       'n',       
    'o'|HIBIT, 'p',       'r',       'r'|HIBIT, 'r',       's',       
    's'|HIBIT, 't',       'u',       'u'|HIBIT, 'v',       'w',       
    'w',       'x',       'y',       'z',       'h',       't',       
    'w',       'y',       'a',       'a'|HIBIT, 'a'|HIBIT, 'a'|HIBIT, 
    'e',       'e'|HIBIT, 'e'|HIBIT, 'i',       'o',       'o'|HIBIT, 
    'o'|HIBIT, 'o'|HIBIT, 'u',       'u'|HIBIT, 'u'|HIBIT, 'y',  
    'o'|HIBIT, 'o'|HIBIT, 'u',       'u'|HIBIT, 'u'|HIBIT, 'y',       
  };

  unsigned int key = (((unsigned int)c)<<3) | 0x00000007;
  int iRes = 0;
  int iHi = sizeof(aDia)/sizeof(aDia[0]) - 1;
  int iLo = 0;
  while( iHi>=iLo ){
96
97
98
99
100
101
102
103
104


105
106
107
108
109
110
111
96
97
98
99
100
101
102


103
104
105
106
107
108
109
110
111







-
-
+
+







** is a diacritical modifier character.
*/
int sqlite3Fts5UnicodeIsdiacritic(int c){
  unsigned int mask0 = 0x08029FDF;
  unsigned int mask1 = 0x000361F8;
  if( c<768 || c>817 ) return 0;
  return (c < 768+32) ?
      (mask0 & (1 << (c-768))) :
      (mask1 & (1 << (c-768-32)));
      (mask0 & ((unsigned int)1 << (c-768))) :
      (mask1 & ((unsigned int)1 << (c-768-32)));
}


/*
** Interpret the argument as a unicode codepoint. If the codepoint
** is an upper case character that has a lower case equivalent,
** return the codepoint corresponding to the lower case version.
244
245
246
247
248
249
250

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







+







  
  else if( c>=66560 && c<66600 ){
    ret = c + 40;
  }

  return ret;
}


int sqlite3Fts5UnicodeCatParse(const char *zCat, u8 *aArray){ 
  aArray[0] = 1;
  switch( zCat[0] ){
    case 'C':
          switch( zCat[1] ){
            case 'c': aArray[1] = 1; break;
726
727
728
729
730
731
732
733

734
735
736
737
738
739
740
727
728
729
730
731
732
733

734
735
736
737
738
739
740
741







-
+







    89,    1434,  3226,  506,   474,   506,   506,   367,   1018,  1946,  
    1402,  954,   1402,  314,   90,    1082,  218,   2266,  666,   1210,  
    186,   570,   2042,  58,    5850,  154,   2010,  154,   794,   2266,  
    378,   2266,  3738,  39,    39,    39,    39,    39,    39,    17351, 
    34,    3074,  7692,  63,    63,    
  };

int sqlite3Fts5UnicodeCategory(int iCode) { 
int sqlite3Fts5UnicodeCategory(u32 iCode) { 
  int iRes = -1;
  int iHi;
  int iLo;
  int ret;
  u16 iKey;

  if( iCode>=(1<<20) ){
764
765
766
767
768
769
770
771

772
773
774

775

765
766
767
768
769
770
771

772
773
774
775
776
777
778







-
+



+

+
void sqlite3Fts5UnicodeAscii(u8 *aArray, u8 *aAscii){
  int i = 0;
  int iTbl = 0;
  while( i<128 ){
    int bToken = aArray[ aFts5UnicodeData[iTbl] & 0x1F ];
    int n = (aFts5UnicodeData[iTbl] >> 5) + i;
    for(; i<128 && i<n; i++){
      aAscii[i] = bToken;
      aAscii[i] = (u8)bToken;
    }
    iTbl++;
  }
  aAscii[0] = 0;                  /* 0x00 is never a token character */
}

Changes to ext/fts5/fts5_varint.c.

72
73
74
75
76
77
78
79

80
81
82
83
84
85
86
72
73
74
75
76
77
78

79
80
81
82
83
84
85
86







-
+







  ** routine.
  */
  {
    u64 v64;
    u8 n;
    p -= 2;
    n = sqlite3Fts5GetVarint(p, &v64);
    *v = (u32)v64;
    *v = ((u32)v64) & 0x7FFFFFFF;
    assert( n>3 && n<=9 );
    return n;
  }
}


/*
338
339
340
341
342
343
344
345
338
339
340
341
342
343
344








-
#endif
  assert( iVal>=(1 << 7) );
  if( iVal<(1 << 14) ) return 2;
  if( iVal<(1 << 21) ) return 3;
  if( iVal<(1 << 28) ) return 4;
  return 5;
}

Changes to ext/fts5/fts5_vocab.c.

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







+





-
+



+





-







struct Fts5VocabTable {
  sqlite3_vtab base;
  char *zFts5Tbl;                 /* Name of fts5 table */
  char *zFts5Db;                  /* Db containing fts5 table */
  sqlite3 *db;                    /* Database handle */
  Fts5Global *pGlobal;            /* FTS5 global object for this database */
  int eType;                      /* FTS5_VOCAB_COL, ROW or INSTANCE */
  unsigned bBusy;                 /* True if busy */
};

struct Fts5VocabCursor {
  sqlite3_vtab_cursor base;
  sqlite3_stmt *pStmt;            /* Statement holding lock on pIndex */
  Fts5Index *pIndex;              /* Associated FTS5 index */
  Fts5Table *pFts5;               /* Associated FTS5 table */

  int bEof;                       /* True if this cursor is at EOF */
  Fts5IndexIter *pIter;           /* Term/rowid iterator object */
  void *pStruct;                  /* From sqlite3Fts5StructureRef() */

  int nLeTerm;                    /* Size of zLeTerm in bytes */
  char *zLeTerm;                  /* (term <= $zLeTerm) paramater, or NULL */

  /* These are used by 'col' tables only */
  Fts5Config *pConfig;            /* Fts5 table configuration */
  int iCol;
  i64 *aCnt;
  i64 *aDoc;

  /* Output values used by all tables. */
  i64 rowid;                      /* This table's current rowid value */
  Fts5Buffer term;                /* Current value of 'term' column */
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
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







-
+
-





+
+
+
+
+
+











+


-
+

+

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




-
+




-
+

-

-
+











+
+




+







** Implementation of xOpen method.
*/
static int fts5VocabOpenMethod(
  sqlite3_vtab *pVTab, 
  sqlite3_vtab_cursor **ppCsr
){
  Fts5VocabTable *pTab = (Fts5VocabTable*)pVTab;
  Fts5Index *pIndex = 0;
  Fts5Table *pFts5 = 0;
  Fts5Config *pConfig = 0;
  Fts5VocabCursor *pCsr = 0;
  int rc = SQLITE_OK;
  sqlite3_stmt *pStmt = 0;
  char *zSql = 0;

  if( pTab->bBusy ){
    pVTab->zErrMsg = sqlite3_mprintf(
       "recursive definition for %s.%s", pTab->zFts5Db, pTab->zFts5Tbl
    );
    return SQLITE_ERROR;
  }
  zSql = sqlite3Fts5Mprintf(&rc,
      "SELECT t.%Q FROM %Q.%Q AS t WHERE t.%Q MATCH '*id'",
      pTab->zFts5Tbl, pTab->zFts5Db, pTab->zFts5Tbl, pTab->zFts5Tbl
  );
  if( zSql ){
    rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pStmt, 0);
  }
  sqlite3_free(zSql);
  assert( rc==SQLITE_OK || pStmt==0 );
  if( rc==SQLITE_ERROR ) rc = SQLITE_OK;

  pTab->bBusy = 1;
  if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
    i64 iId = sqlite3_column_int64(pStmt, 0);
    pIndex = sqlite3Fts5IndexFromCsrid(pTab->pGlobal, iId, &pConfig);
    pFts5 = sqlite3Fts5TableFromCsrid(pTab->pGlobal, iId);
  }
  pTab->bBusy = 0;

  if( rc==SQLITE_OK && pIndex==0 ){
    rc = sqlite3_finalize(pStmt);
    pStmt = 0;
    if( rc==SQLITE_OK ){
      pVTab->zErrMsg = sqlite3_mprintf(
          "no such fts5 table: %s.%s", pTab->zFts5Db, pTab->zFts5Tbl
      );
      rc = SQLITE_ERROR;
  if( rc==SQLITE_OK ){
    if( pFts5==0 ){
      rc = sqlite3_finalize(pStmt);
      pStmt = 0;
      if( rc==SQLITE_OK ){
        pVTab->zErrMsg = sqlite3_mprintf(
            "no such fts5 table: %s.%s", pTab->zFts5Db, pTab->zFts5Tbl
            );
        rc = SQLITE_ERROR;
      }
    }else{
      rc = sqlite3Fts5FlushToDisk(pFts5);
    }
  }

  if( rc==SQLITE_OK ){
    int nByte = pConfig->nCol * sizeof(i64) * 2 + sizeof(Fts5VocabCursor);
    i64 nByte = pFts5->pConfig->nCol * sizeof(i64)*2 + sizeof(Fts5VocabCursor);
    pCsr = (Fts5VocabCursor*)sqlite3Fts5MallocZero(&rc, nByte);
  }

  if( pCsr ){
    pCsr->pIndex = pIndex;
    pCsr->pFts5 = pFts5;
    pCsr->pStmt = pStmt;
    pCsr->pConfig = pConfig;
    pCsr->aCnt = (i64*)&pCsr[1];
    pCsr->aDoc = &pCsr->aCnt[pConfig->nCol];
    pCsr->aDoc = &pCsr->aCnt[pFts5->pConfig->nCol];
  }else{
    sqlite3_finalize(pStmt);
  }

  *ppCsr = (sqlite3_vtab_cursor*)pCsr;
  return rc;
}

static void fts5VocabResetCursor(Fts5VocabCursor *pCsr){
  pCsr->rowid = 0;
  sqlite3Fts5IterClose(pCsr->pIter);
  sqlite3Fts5StructureRelease(pCsr->pStruct);
  pCsr->pStruct = 0;
  pCsr->pIter = 0;
  sqlite3_free(pCsr->zLeTerm);
  pCsr->nLeTerm = -1;
  pCsr->zLeTerm = 0;
  pCsr->bEof = 0;
}

/*
** Close the cursor.  For additional information see the documentation
** on the xClose method of the virtual table interface.
*/
static int fts5VocabCloseMethod(sqlite3_vtab_cursor *pCursor){
421
422
423
424
425
426
427
428

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

442
443
444
445
446
447
448
449







-
+








    sqlite3Fts5BufferSet(&rc, &pCsr->term, nTerm, (const u8*)zTerm);
  }
  return rc;
}

static int fts5VocabInstanceNext(Fts5VocabCursor *pCsr){
  int eDetail = pCsr->pConfig->eDetail;
  int eDetail = pCsr->pFts5->pConfig->eDetail;
  int rc = SQLITE_OK;
  Fts5IndexIter *pIter = pCsr->pIter;
  i64 *pp = &pCsr->iInstPos;
  int *po = &pCsr->iInstOff;
  
  assert( sqlite3Fts5IterEof(pIter)==0 );
  assert( pCsr->bEof==0 );
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
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







-
-
+
+

+
+




















+
















-
+








/*
** Advance the cursor to the next row in the table.
*/
static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
  Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
  Fts5VocabTable *pTab = (Fts5VocabTable*)pCursor->pVtab;
  int rc = SQLITE_OK;
  int nCol = pCsr->pConfig->nCol;
  int nCol = pCsr->pFts5->pConfig->nCol;
  int rc;

  rc = sqlite3Fts5StructureTest(pCsr->pFts5->pIndex, pCsr->pStruct);
  if( rc!=SQLITE_OK ) return rc;
  pCsr->rowid++;

  if( pTab->eType==FTS5_VOCAB_INSTANCE ){
    return fts5VocabInstanceNext(pCsr);
  }

  if( pTab->eType==FTS5_VOCAB_COL ){
    for(pCsr->iCol++; pCsr->iCol<nCol; pCsr->iCol++){
      if( pCsr->aDoc[pCsr->iCol] ) break;
    }
  }

  if( pTab->eType!=FTS5_VOCAB_COL || pCsr->iCol>=nCol ){
    if( sqlite3Fts5IterEof(pCsr->pIter) ){
      pCsr->bEof = 1;
    }else{
      const char *zTerm;
      int nTerm;

      zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
      assert( nTerm>=0 );
      if( pCsr->nLeTerm>=0 ){
        int nCmp = MIN(nTerm, pCsr->nLeTerm);
        int bCmp = memcmp(pCsr->zLeTerm, zTerm, nCmp);
        if( bCmp<0 || (bCmp==0 && pCsr->nLeTerm<nTerm) ){
          pCsr->bEof = 1;
          return SQLITE_OK;
        }
      }

      sqlite3Fts5BufferSet(&rc, &pCsr->term, nTerm, (const u8*)zTerm);
      memset(pCsr->aCnt, 0, nCol * sizeof(i64));
      memset(pCsr->aDoc, 0, nCol * sizeof(i64));
      pCsr->iCol = 0;

      assert( pTab->eType==FTS5_VOCAB_COL || pTab->eType==FTS5_VOCAB_ROW );
      while( rc==SQLITE_OK ){
        int eDetail = pCsr->pConfig->eDetail;
        int eDetail = pCsr->pFts5->pConfig->eDetail;
        const u8 *pPos; int nPos;   /* Position list */
        i64 iPos = 0;               /* 64-bit position read from poslist */
        int iOff = 0;               /* Current offset within position list */

        pPos = pCsr->pIter->pData;
        nPos = pCsr->pIter->nData;

517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532

533
534
535
536
537
538
539
534
535
536
537
538
539
540

541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556







-








+







            break;

          case FTS5_VOCAB_COL:
            if( eDetail==FTS5_DETAIL_FULL ){
              int iCol = -1;
              while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
                int ii = FTS5_POS2COLUMN(iPos);
                pCsr->aCnt[ii]++;
                if( iCol!=ii ){
                  if( ii>=nCol ){
                    rc = FTS5_CORRUPT;
                    break;
                  }
                  pCsr->aDoc[ii]++;
                  iCol = ii;
                }
                pCsr->aCnt[ii]++;
              }
            }else if( eDetail==FTS5_DETAIL_COLUMNS ){
              while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff,&iPos) ){
                assert_nc( iPos>=0 && iPos<nCol );
                if( iPos>=nCol ){
                  rc = FTS5_CORRUPT;
                  break;
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
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( rc==SQLITE_OK ){
          rc = sqlite3Fts5IterNextScan(pCsr->pIter);
        }
        if( pTab->eType==FTS5_VOCAB_INSTANCE ) break;

        if( rc==SQLITE_OK ){
          zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
          if( nTerm!=pCsr->term.n || memcmp(zTerm, pCsr->term.p, nTerm) ){
          if( nTerm!=pCsr->term.n 
          || (nTerm>0 && memcmp(zTerm, pCsr->term.p, nTerm)) 
          ){
            break;
          }
          if( sqlite3Fts5IterEof(pCsr->pIter) ) break;
        }
      }
    }
  }

  if( rc==SQLITE_OK && pCsr->bEof==0 && pTab->eType==FTS5_VOCAB_COL ){
    while( pCsr->aDoc[pCsr->iCol]==0 ) pCsr->iCol++;
    assert( pCsr->iCol<pCsr->pConfig->nCol );
    for(/* noop */; pCsr->iCol<nCol && pCsr->aDoc[pCsr->iCol]==0; pCsr->iCol++);
    if( pCsr->iCol==nCol ){
      rc = FTS5_CORRUPT;
    }
  }
  return rc;
}

/*
** This is the xFilter implementation for the virtual table.
*/
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
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







+











+
-
+
+
+
+




-
+
-
-
+
+







  }else{
    if( pGe ){
      zTerm = (const char *)sqlite3_value_text(pGe);
      nTerm = sqlite3_value_bytes(pGe);
    }
    if( pLe ){
      const char *zCopy = (const char *)sqlite3_value_text(pLe);
      if( zCopy==0 ) zCopy = "";
      pCsr->nLeTerm = sqlite3_value_bytes(pLe);
      pCsr->zLeTerm = sqlite3_malloc(pCsr->nLeTerm+1);
      if( pCsr->zLeTerm==0 ){
        rc = SQLITE_NOMEM;
      }else{
        memcpy(pCsr->zLeTerm, zCopy, pCsr->nLeTerm+1);
      }
    }
  }

  if( rc==SQLITE_OK ){
    Fts5Index *pIndex = pCsr->pFts5->pIndex;
    rc = sqlite3Fts5IndexQuery(pCsr->pIndex, zTerm, nTerm, f, 0, &pCsr->pIter);
    rc = sqlite3Fts5IndexQuery(pIndex, zTerm, nTerm, f, 0, &pCsr->pIter);
    if( rc==SQLITE_OK ){
      pCsr->pStruct = sqlite3Fts5StructureRef(pIndex);
    }
  }
  if( rc==SQLITE_OK && eType==FTS5_VOCAB_INSTANCE ){
    rc = fts5VocabInstanceNewTerm(pCsr);
  }
  if( rc==SQLITE_OK 
  if( rc==SQLITE_OK && !pCsr->bEof 
   && !pCsr->bEof 
   && (eType!=FTS5_VOCAB_INSTANCE || pCsr->pConfig->eDetail!=FTS5_DETAIL_NONE)
   && (eType!=FTS5_VOCAB_INSTANCE 
    || pCsr->pFts5->pConfig->eDetail!=FTS5_DETAIL_NONE)
  ){
    rc = fts5VocabNextMethod(pCursor);
  }

  return rc;
}

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







-
+











-
+








static int fts5VocabColumnMethod(
  sqlite3_vtab_cursor *pCursor,   /* Cursor to retrieve value from */
  sqlite3_context *pCtx,          /* Context for sqlite3_result_xxx() calls */
  int iCol                        /* Index of column to read value from */
){
  Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
  int eDetail = pCsr->pConfig->eDetail;
  int eDetail = pCsr->pFts5->pConfig->eDetail;
  int eType = ((Fts5VocabTable*)(pCursor->pVtab))->eType;
  i64 iVal = 0;

  if( iCol==0 ){
    sqlite3_result_text(
        pCtx, (const char*)pCsr->term.p, pCsr->term.n, SQLITE_TRANSIENT
    );
  }else if( eType==FTS5_VOCAB_COL ){
    assert( iCol==1 || iCol==2 || iCol==3 );
    if( iCol==1 ){
      if( eDetail!=FTS5_DETAIL_NONE ){
        const char *z = pCsr->pConfig->azCol[pCsr->iCol];
        const char *z = pCsr->pFts5->pConfig->azCol[pCsr->iCol];
        sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC);
      }
    }else if( iCol==2 ){
      iVal = pCsr->aDoc[pCsr->iCol];
    }else{
      iVal = pCsr->aCnt[pCsr->iCol];
    }
693
694
695
696
697
698
699
700
701


702
703
704
705
706
707
708
719
720
721
722
723
724
725


726
727
728
729
730
731
732
733
734







-
-
+
+







      case 2: {
        int ii = -1;
        if( eDetail==FTS5_DETAIL_FULL ){
          ii = FTS5_POS2COLUMN(pCsr->iInstPos);
        }else if( eDetail==FTS5_DETAIL_COLUMNS ){
          ii = (int)pCsr->iInstPos;
        }
        if( ii>=0 && ii<pCsr->pConfig->nCol ){
          const char *z = pCsr->pConfig->azCol[ii];
        if( ii>=0 && ii<pCsr->pFts5->pConfig->nCol ){
          const char *z = pCsr->pFts5->pConfig->azCol[ii];
          sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC);
        }
        break;
      }
      default: {
        assert( iCol==3 );
        if( eDetail==FTS5_DETAIL_FULL ){

Changes to ext/fts5/test/fts5aa.test.

34
35
36
37
38
39
40
41

42
43
44
45
46
47
48
49
34
35
36
37
38
39
40

41

42
43
44
45
46
47
48







-
+
-







  t1_docsize {CREATE TABLE 't1_docsize'(id INTEGER PRIMARY KEY, sz BLOB)}
  t1_config {CREATE TABLE 't1_config'(k PRIMARY KEY, v) WITHOUT ROWID}
}

do_execsql_test 1.1 {
  DROP TABLE t1;
  SELECT name, sql FROM sqlite_master;
} {
} {}
}

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

do_execsql_test 2.0 {
  CREATE VIRTUAL TABLE t1 USING fts5(x, y, detail=%DETAIL%);
}
424
425
426
427
428
429
430
431

432
433
434
435
436
437
438
423
424
425
426
427
428
429

430
431
432
433
434
435
436
437







-
+







  INSERT INTO n1 VALUES('a b c d');
}

proc funk {} {
  db eval { UPDATE n1_config SET v=50 WHERE k='version' }
  set fd [db incrblob main n1_data block 10]
  fconfigure $fd -encoding binary -translation binary
  puts -nonewline $fd "\x44\x45"
#  puts -nonewline $fd "\x44\x45"
  close $fd
}
db func funk funk

# This test case corrupts the structure record within the first invocation
# of function funk(). Which used to cause the bm25() function to throw an
# exception. But since bm25() can now used the cached structure record,
599
600
601
602
603
604
605
































606
607
608
609
610
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







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





}
do_execsql_test 23.1 {
  SELECT * FROM t11, t10 WHERE t11.x = t10.x AND t10.rowid IS NULL;
}
do_execsql_test 23.2 {
  SELECT * FROM t11, t10 WHERE t10.rowid IS NULL;
}

#-------------------------------------------------------------------------
do_execsql_test 24.0 {
  CREATE VIRTUAL TABLE t12 USING fts5(x, detail=%DETAIL%);
  INSERT INTO t12 VALUES('aaaa');
}
do_execsql_test 24.1 {
  BEGIN;
    DELETE FROM t12 WHERE rowid=1;
    SELECT * FROM t12('aaaa');
    INSERT INTO t12 VALUES('aaaa');
  END;
}
do_execsql_test 24.2 {
  INSERT INTO t12(t12) VALUES('integrity-check');
}
do_execsql_test 24.3 {
    SELECT * FROM t12('aaaa');
} {aaaa}

#-------------------------------------------------------------------------
do_execsql_test 25.0 {
  CREATE VIRTUAL TABLE t13 USING fts5(x, detail=%DETAIL%);
}
do_execsql_test 25.1 {
  BEGIN;
  INSERT INTO t13 VALUES('AAAA');
SELECT * FROM t13('BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB*');

  END;
}


}

expand_all_sql db
finish_test

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







-
+


















+
+
+
+
+
+




  INSERT INTO x1 VALUES('xyz', '1 2 3 4 5 6 7 8 9 10 11 12 13');
  SELECT snippet(x1, 1, '[', ']', '...', 5) FROM x1('xyz');
} {
  {1 2 3 4 5...}
}

do_execsql_test 5.0 {
  CREATE VIRTUAL TABLE p1 USING fts5(a, b);
  CREATE VIRTUAL TABLE p1 USING fts5(a, b, detail=%DETAIL%);
  INSERT INTO p1 VALUES(
    'x a a a a a a a a a a',
    'a a a a a a a a a a a a a a a a a a a x'
  );
}
do_execsql_test 5.1 {
  SELECT snippet(p1, 0, '[', ']', '...', 6) FROM p1('x');
} {{[x] a a a a a...}}

do_execsql_test 5.2 {
  SELECT snippet(p1, 0, '[', ']', NULL, 6) FROM p1('x');
} {{[x] a a a a a}}
do_execsql_test 5.3 {
  SELECT snippet(p1, 0, NULL, ']', '...', 6) FROM p1('x');
} {{x] a a a a a...}}
do_execsql_test 5.4 {
  SELECT snippet(p1, 0, '[', NULL, '...', 6) FROM p1('x');
} {{[x a a a a a...}}
do_execsql_test 5.5 {
  SELECT snippet(p1, 0, '[', NULL, '...', 6) FROM p1('x OR ""');
} {{[x a a a a a...}}
do_execsql_test 5.6 {
  SELECT snippet(p1, 0, '[', NULL, '...', 6) FROM p1('x OR ' || x'DB');
} {{[x a a a a a...}}

} ;# foreach_detail_mode 

finish_test

Changes to ext/fts5/test/fts5ah.test.

1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21













+







# 2014 June 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.  The
# focus of this script is testing the FTS5 module.
#
# TESTRUNNER: slow

source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5ah

# If SQLITE_ENABLE_FTS5 is defined, omit this file.
ifcapable !fts5 {
  finish_test

Changes to ext/fts5/test/fts5ai.test.

47
48
49
50
51
52
53






54
55
56
57
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63







+
+
+
+
+
+




    ROLLBACK TO one;
  COMMIT;
}

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

do_execsql_test 1.3 {
  SAVEPOINT one;
    INSERT INTO t1 VALUES('v w x');
  ROLLBACK TO one;
}
}


finish_test

Changes to ext/fts5/test/fts5ak.test.

139
140
141
142
143
144
145








146
147
148
149
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157







+
+
+
+
+
+
+
+




  --   '[a b c d e]'
  SELECT highlight(ft, 0, '[', ']') FROM ft WHERE ft MATCH 'a+b+c AND c+d+e';
} {
  {[a b c] x [c d e]}
  {[a b c] [c d e]}
  {[a b c d e]}
}

do_execsql_test 3.2 {
  SELECT highlight(ft, 0, NULL, NULL) FROM ft WHERE ft MATCH 'a+b+c AND c+d+e';
} {
  {a b c x c d e}
  {a b c c d e}
  {a b c d e}
}

}

finish_test

Changes to ext/fts5/test/fts5aux.test.

271
272
273
274
275
276
277


278
279






























280

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







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

+

do_execsql_test 9.3 {
  SELECT rowid FROM t1('b:a AND b:b') ORDER BY rank;
} {
  9 10
}

#-------------------------------------------------------------------------
# Test that aux. functions may not be used in aggregate queries.


#
reset_db
do_execsql_test 10.0 {
  CREATE VIRTUAL TABLE t1 USING fts5(x, y, z);
  INSERT INTO t1 VALUES('a', 'one two', 1);
  INSERT INTO t1 VALUES('b', 'two three', 2);
  INSERT INTO t1 VALUES('c', 'three four', 1);
  INSERT INTO t1 VALUES('d', 'four five', 2);
  INSERT INTO t1 VALUES('e', 'five six', 1);
  INSERT INTO t1 VALUES('f', 'six seven', 2);
}

proc firstcol {cmd} { $cmd xColumnText 0 }
sqlite3_fts5_create_function db firstcol firstcol

do_execsql_test 10.1.1 {
  SELECT firstcol(t1) FROM t1
} {a b c d e f}
do_execsql_test 10.1.2 {
  SELECT group_concat(x, '.') FROM t1
} {a.b.c.d.e.f}

do_catchsql_test 10.1.3 {
  SELECT group_concat(firstcol(t1), '.') FROM t1
} {1 {unable to use function firstcol in the requested context}}

do_catchsql_test 10.1.4 {
  SELECT group_concat(firstcol(t1), '.') FROM t1 GROUP BY rowid
} {1 {unable to use function firstcol in the requested context}}

finish_test

Added ext/fts5/test/fts5circref.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2018 Dec 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.  The
# focus of this script is testing the FTS5 module.
#

source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5circref

# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
ifcapable !fts5 {
  finish_test
  return
}

do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE tt USING fts5(a);
  SELECT name FROM sqlite_master ORDER BY 1;
} {
  tt tt_config tt_content tt_data tt_docsize tt_idx
}
db_save_and_close

foreach {tn schema sql} {
  1 {
    CREATE TRIGGER tr1 AFTER INSERT ON tt_config BEGIN
      SELECT * FROM tt;
    END;
  } {
    INSERT INTO tt(tt, rank) VALUES('usermerge', 4);
  }

  2 {
    CREATE TRIGGER tr1 AFTER INSERT ON tt_docsize BEGIN
      SELECT * FROM tt;
    END;
  } {
    INSERT INTO tt(a) VALUES('one two three');
  }

  3 {
    CREATE TRIGGER tr1 AFTER INSERT ON tt_content BEGIN
      SELECT * FROM tt;
    END;
  } {
    INSERT INTO tt(a) VALUES('one two three');
  }

  4 {
    CREATE TRIGGER tr1 AFTER INSERT ON tt_data BEGIN
      SELECT * FROM tt;
    END;
  } {
    INSERT INTO tt(a) VALUES('one two three');
  }

  5 {
    CREATE TRIGGER tr1 AFTER INSERT ON tt_idx BEGIN
      SELECT * FROM tt;
    END;
  } {
    INSERT INTO tt(a) VALUES('one two three');
  }
} {
  db_restore_and_reopen
  do_execsql_test 1.1.$tn.1 $schema
  do_catchsql_test 1.1.$tn.2 $sql {1 {SQL logic error}}
  db close
}


finish_test

Changes to ext/fts5/test/fts5colset.test.

77
78
79
80
81
82
83



















84
85
86
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







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



    " $res
  }

  do_catchsql_test 4.1 {
    SELECT * FROM t1 WHERE rowid MATCH 'a'
  } {1 {unable to use function MATCH in the requested context}}
}

#-------------------------------------------------------------------------
# Confirm that the expression parser creates the same expression tree
# for:
#
#     {a b} : (abc AND def)
#    -{c d} : (abc AND def)
#
# Assuming that the table columns are (a, b, c, d).
#
do_execsql_test 5.1 {
  SELECT fts5_expr('abcd AND cdef');
} {{"abcd" AND "cdef"}}
do_execsql_test 5.2 {
  SELECT fts5_expr('{a b} : (abcd AND cdef)', 'a', 'b', 'c', 'd');
} {{{a b} : "abcd" AND {a b} : "cdef"}}
do_execsql_test 5.3 {
  SELECT fts5_expr('-{c d} : (abcd AND cdef)', 'a', 'b', 'c', 'd');
} {{{a b} : "abcd" AND {a b} : "cdef"}}


finish_test

Added ext/fts5/test/fts5concurrent.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022 May 09
#
# 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 script is testing the FTS5 module.
#

source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5concurrent

# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
ifcapable !fts5 {
  finish_test
  return
}

do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE ft USING fts5(line, tokenize=trigram);
}

do_execsql_test 1.1 {
  BEGIN CONCURRENT;
    INSERT INTO ft VALUES( hex(randomblob(50)) );
  COMMIT
} {}

do_execsql_test 1.2 {
  BEGIN CONCURRENT;
    WITH s(i) AS (
      SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<50
    )
    INSERT INTO ft SELECT hex(randomblob(50)) FROM s;

    WITH s(i) AS (
      SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<50
    )
    INSERT INTO ft SELECT hex(randomblob(50)) FROM s;

    WITH s(i) AS (
      SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<50
    )
    INSERT INTO ft SELECT hex(randomblob(50)) FROM s;
  COMMIT;
}


finish_test

Changes to ext/fts5/test/fts5content.test.

249
250
251
252
253
254
255


256






































257

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







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

+
  SELECT name FROM sqlite_master;
} {xx xx_data xx_idx xx_docsize xx_config}
do_execsql_test 6.2 {
  DROP TABLE xx;
  SELECT name FROM sqlite_master;
} {}

#---------------------------------------------------------------------------
# Check that an fts5 table cannot be its own content table.

#
reset_db
do_execsql_test 7.1.1 {
  CREATE VIRTUAL TABLE t1 USING fts5(a, c=t1 );
  INSERT INTO t1( a ) VALUES('abc');
}
do_catchsql_test 7.1.2 { 
  SELECT * FROM t1; 
} {1 {recursively defined fts5 content table}}
do_catchsql_test 7.1.3 { 
  SELECT * FROM t1('abc'); 
} {1 {recursively defined fts5 content table}}
do_catchsql_test 7.1.4 { 
  SELECT count(*) FROM t1;
} {1 {recursively defined fts5 content table}}
do_catchsql_test 7.1.5 { 
  SELECT * FROM t1('abc') ORDER BY rank;
} {1 {recursively defined fts5 content table}}

reset_db
do_execsql_test 7.2.1 {
  CREATE VIRTUAL TABLE t1 USING fts5(a, c=t2 );
  CREATE VIRTUAL TABLE t2 USING fts5(a, c=t1 );
  INSERT INTO t1( a ) VALUES('abc');
}
do_catchsql_test 7.2.2 { 
  SELECT * FROM t1; 
} {1 {recursively defined fts5 content table}}
do_catchsql_test 7.2.3 { 
  SELECT * FROM t1('abc'); 
} {1 {recursively defined fts5 content table}}
do_catchsql_test 7.2.4 { 
  SELECT count(*) FROM t1;
} {1 {recursively defined fts5 content table}}
do_catchsql_test 7.2.5 { 
  SELECT * FROM t1('abc') ORDER BY rank;
} {1 {recursively defined fts5 content table}}

finish_test

Changes to ext/fts5/test/fts5corrupt3.test.

more than 10,000 changes

Added ext/fts5/test/fts5corrupt4.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019 May 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.
#
#***********************************************************************
#
#

source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5corrupt4

# If SQLITE_ENABLE_FTS5 is defined, omit this file.
ifcapable !fts5 {
  finish_test
  return
}
sqlite3_fts5_may_be_corrupt 1

do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE ttt USING fts5(a, b); 
  INSERT INTO ttt 
     VALUES('e ee eee e ee eee e ee eee', 'eee ee e e e ee eee ee ee');
  INSERT INTO ttt SELECT a||a, b||b FROM ttt;   
  INSERT INTO ttt SELECT a||a, b||b FROM ttt;   
}

expr srand(1)

proc mutate {blob i} {
  set o [expr {$i % [string length $blob]}]
  set a [string range $blob 0 $o-1]
  set b [string range $blob $o+1 end]
  set v [expr int(rand()*255) - 127]
  return "$a[binary format c $v]$b"
}
db func mutate mutate

for {set j 1000} {$j <= 5000} {incr j 1000} {
  do_test 1.$j {
    for {set i 0} {$i < 1000} {incr i} {
      execsql {
        BEGIN;
          UPDATE ttt_data SET block = mutate(block, $i) WHERE id>10;
      }
      foreach sql {
        {SELECT snippet(ttt, -1, '.', '..', '[', ']'), * FROM ttt('e*')}
        {SELECT snippet(ttt, -1, '.', '..', '[', ']'), * FROM ttt('e* NOT ee*')}
      } {
        catch { execsql $sql }
      }
      execsql ROLLBACK
    }
  } {}
}

sqlite3_fts5_may_be_corrupt 0
finish_test

Added ext/fts5/test/fts5corrupt5.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
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2015 Apr 24
#
# 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 tests that FTS5 handles corrupt databases (i.e. internal
# inconsistencies in the backing tables) correctly. In this case 
# "correctly" means without crashing.
#

source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5corrupt3

# If SQLITE_ENABLE_FTS5 is defined, omit this file.
ifcapable !fts5 {
  finish_test
  return
}
sqlite3_fts5_may_be_corrupt 1
database_may_be_corrupt

#-------------------------------------------------------------------------
# dbsqlfuzz crash-0f47112aa7520cf08c6a835a88fdff8c2a32a188
#
reset_db
do_test 1.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
.open --hexdb
| size 24576 pagesize 4096 filename crash-0f47112aa7520c.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 06 0e 0f 00 0f aa 0f 53   ...............S
|    112: 0e e8 0e 8b 0e 33 0e 0f 00 00 00 00 00 00 00 00   .....3..........
|   3584: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 22   ................
|   3600: 06 06 17 11 11 01 31 74 61 62 6c 65 62 62 62 62   ......1tablebbbb
|   3616: 06 43 52 45 41 54 45 20 54 41 42 4c 45 20 62 62   .CREATE TABLE bb
|   3632: 28 61 29 56 05 06 17 1f 1f 01 7d 74 61 62 6c 65   (a)V.......table
|   3648: 74 31 5f 63 6f 6e 66 69 67 74 31 5f 63 6f 6e 66   t1_configt1_conf
|   3664: 69 67 05 43 52 45 41 54 45 20 54 41 42 4c 45 20   ig.CREATE TABLE 
|   3680: 27 74 31 5f 63 6f 6e 66 69 67 27 28 6b 20 50 52   't1_config'(k PR
|   3696: 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 20 57 49   IMARY KEY, v) WI
|   3712: 54 48 4f 55 54 20 52 4f 57 49 44 5b 04 07 17 21   THOUT ROWID[...!
|   3728: 21 01 81 01 74 61 62 6c 65 74 31 5f 64 6f 63 73   !...tablet1_docs
|   3744: 69 7a 65 74 31 5f 64 6f 63 73 69 7a 65 04 43 52   izet1_docsize.CR
|   3760: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 64   EATE TABLE 't1_d
|   3776: 6f 63 73 69 7a 65 27 28 69 64 20 49 4e 54 45 47   ocsize'(id INTEG
|   3792: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20   ER PRIMARY KEY, 
|   3808: 73 7a 20 42 4c 4f 42 29 69 03 07 17 19 19 01 81   sz BLOB)i.......
|   3824: 2d 74 61 62 6c 65 74 31 5f 69 64 78 74 31 5f 69   -tablet1_idxt1_i
|   3840: 64 78 03 43 52 45 41 54 45 20 54 41 42 4c 45 20   dx.CREATE TABLE 
|   3856: 27 74 31 5f 69 64 78 27 28 73 65 67 69 64 2c 20   't1_idx'(segid, 
|   3872: 74 65 72 6d 2c 20 70 67 6e 6f 2c 20 50 52 49 4d   term, pgno, PRIM
|   3888: 41 52 59 20 4b 45 59 28 73 65 67 69 64 2c 20 74   ARY KEY(segid, t
|   3904: 65 72 6d 29 29 20 57 49 54 48 4f 55 54 20 52 4f   erm)) WITHOUT RO
|   3920: 57 49 44 55 02 07 17 1b 1b 01 81 01 74 61 62 6c   WIDU........tabl
|   3936: 65 74 31 5f 64 61 74 61 74 31 5f 64 61 74 61 02   et1_datat1_data.
|   3952: 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 31   CREATE TABLE 't1
|   3968: 5f 64 61 74 61 27 28 69 64 20 49 4e 54 45 47 45   _data'(id INTEGE
|   3984: 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 62   R PRIMARY KEY, b
|   4000: 6c 6f 63 6b 20 42 4c 4f 42 29 54 01 07 17 11 11   lock BLOB)T.....
|   4016: 08 81 15 74 61 62 6c 65 74 31 74 31 43 52 45 41   ...tablet1t1CREA
|   4032: 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 4c 45   TE VIRTUAL TABLE
|   4048: 20 74 31 20 55 53 49 4e 47 20 66 74 73 35 28 61    t1 USING fts5(a
|   4064: 2c 62 2c 70 72 65 66 69 78 3d 22 31 2c 32 2c 33   ,b,prefix=.1,2,3
|   4080: 2c 34 22 2c 20 63 6f 6e 74 65 6e 74 3d 22 22 29   ,4., content=..)
| page 2 offset 4096
|      0: 0d 0b 6a 00 37 09 4c 02 0f e7 09 4c 0f c6 0f a4   ..j.7.L....L....
|     16: 0f 88 0f 6d 0f 4b 0f 2c 0f 0e 0e ec 0e cd 0e ad   ...m.K.,........
|     32: 0e 8e 0e 6c 0e 4b 0e 29 0e 08 0d e6 0d c4 0d b5   ...l.K.)........
|     48: 0d 97 0d 76 0d 54 0d 31 0d 15 0c f3 0c d3 0c b5   ...v.T.1........
|     64: 0c 95 0c 73 0c 54 0c 32 0c 10 0b ee 0b cc 0b b0   ...s.T.2........
|     80: 0b 8d 0b 7e 0b 48 0b 2e 0b 0b 0a ef 00 00 00 00   ...~.H..........
|   2368: 00 00 00 00 00 00 00 00 00 00 00 00 15 0a 03 00   ................
|   2384: 30 00 00 00 01 01 03 35 00 03 01 11 12 02 01 12   0......5........
|   2400: 03 01 11 1c 8c 80 80 80 80 10 03 00 3e 00 00 00   ............>...
|   2416: 17 01 05 05 34 74 61 62 6c 03 02 03 01 04 77 68   ....4tabl.....wh
|   2432: 65 72 03 02 06 09 1b 8c 80 80 80 80 0f 03 00 3c   er.............<
|   2448: 00 00 00 16 05 34 66 74 73 34 03 02 02 01 04 6e   .....4fts4.....n
|   2464: 75 6d 62 03 06 01 04 09 1b 8c 80 80 80 80 0e 03   umb.............
|   2480: 00 3c 00 00 00 16 04 33 74 68 65 03 06 01 01 04   .<.....3the.....
|   2496: 01 03 77 68 65 03 02 04 04 0a 1b 8c 80 80 80 80   ..whe...........
|   2512: 0d 03 00 3c 00 00 00 16 04 33 6e 75 6d 03 06 01   ...<.....3num...
|   2528: 01 05 01 03 74 61 62 03 02 03 04 0a 19 8c 80 80   ....tab.........
|   2544: 80 80 0c 03 00 38 00 00 00 14 03 32 77 68 03 02   .....8.....2wh..
|   2560: 04 00 04 33 66 74 73 03 02 02 04 07 18 8c 80 80   ...3fts.........
|   2576: 80 80 0b 03 00 36 00 00 00 13 03 32 74 61 03 02   .....6.....2ta..
|   2592: 03 02 01 68 03 06 01 01 04 04 07 1b 8c 80 80 80   ...h............
|   2608: 80 0a 03 00 3c 00 00 00 16 03 32 6e 75 03 06 01   ....<.....2nu...
|   2624: 01 05 01 02 6f 66 03 06 01 01 06 04 09 19 8c 80   ....of..........
|   2640: 80 80 80 09 03 00 38 00 00 00 14 03 32 66 74 03   ......8.....2ft.
|   2656: 02 02 01 02 69 73 03 06 01 01 03 04 07 18 8c 80   ....is..........
|   2672: 80 80 80 08 03 00 36 00 00 00 13 02 31 74 03 08   ......6.....1t..
|   2688: 03 01 01 04 01 01 77 03 02 04 04 09 1a 8c 80 80   ......w.........
|   2704: 80 80 07 03 00 3a 00 00 00 15 02 31 6e 03 08 01   .....:.....1n...
|   2720: 01 02 05 01 00 6f 03 06 01 01 06 04 09 18 8c 80   .....o..........
|   2736: 80 80 80 06 03 00 36 00 00 00 03 04 02 31 66 03   ......6......1f.
|   2752: 02 02 01 01 69 03 06 01 01 03 04 f6 1c 8c 80 80   ....i...........
|   2768: 80 80 05 03 00 3e 00 00 00 17 04 30 74 68 65 03   .....>.....0the.
|   2784: f6 01 01 04 01 05 77 68 65 72 65 03 02 04 0a 15   ......where.....
|   2800: 8c 80 80 80 80 04 03 00 30 00 00 00 11 01 01 06   ........0.......
|   2816: 06 30 74 61 62 6c 65 0f 42 03 07 1c 8c 81 80 80   .0table.B.......
|   2832: 80 03 03 00 3e 00 00 00 17 07 30 6e 75 6d 62 65   ....>.....0numbe
|   2848: 72 03 06 01 01 05 01 02 6f 66 03 06 04 0d 13 8c   r.......of......
|   2864: 80 80 80 80 02 03 00 2c 00 00 00 0f 01 01 03 02   .......,........
|   2880: 30 6e 03 06 01 01 02 07 1b 8c 80 80 80 80 01 03   0n..............
|   2896: 00 3c 00 00 00 16 08 30 66 74 73 34 61 75 78 03   .<.....0fts4aux.
|   2912: 02 02 01 02 69 73 03 06 04 0c 00 00 00 14 2a 00   ....is........*.
|   2928: 00 00 01 01 02 24 00 02 01 01 12 02 01 12 08 88   .....$..........
|   2944: 80 80 80 80 12 03 00 16 00 00 00 05 02 1c 88 80   ................
|   2960: 80 80 80 11 03 00 3e 00 00 00 17 05 34 72 6f 77   ......>.....4row
|   2976: 73 02 06 01 01 05 01 04 74 68 65 72 02 02 04 0b   s.......ther....
|   2992: 15 88 80 80 80 80 10 03 00 30 00 00 00 11 02 01   .........0......
|   3008: 01 07 05 34 62 65 74 77 02 02 04 08 1b 88 80 80   ...4betw........
|   3024: 80 80 0f 03 00 3c 00 00 00 16 04 04 33 72 6f 77   .....<......3row
|   3040: 02 06 01 01 05 01 03 74 68 65 02 08 05 0a 1b 88   .......the......
|   3056: 80 80 80 80 0e 03 00 3c 00 00 00 16 01 01 02 04   .......<........
|   3072: 33 61 72 65 02 02 03 01 03 62 65 74 02 02 07 08   3are.....bet....
|   3088: 1b 88 80 80 80 80 0d 03 00 3c 00 00 00 16 13 32   .........<.....2
|   3104: 74 68 02 08 02 01 01 07 00 04 33 61 6e 64 02 06   th........3and..
|   3120: 04 0a 1b 88 80 80 80 80 0c 03 00 3c 00 00 00 16   ...........<....
|   3136: 03 32 69 6e 02 06 01 01 06 01 02 72 6f 02 06 01   .2in.......ro...
|   3152: 01 05 04 09 18 88 80 80 80 80 0b 03 00 36 00 00   .............6..
|   3168: 00 13 02 03 32 61 72 02 02 03 01 02 62 65 02 02   ....2ar.....be..
|   3184: 04 05 07 1b 88 80 80 80 80 0a 03 00 3c 00 9e 00   ............<...
|   3200: 16 02 31 74 02 08 02 01 01 07 00 03 32 61 6e 02   ..1t........2an.
|   3216: 06 01 01 04 09 19 88 80 80 80 80 09 03 00 38 00   ..............8.
|   3232: 00 00 14 02 31 6e 02 06 01 01 03 01 01 72 02 06   ....1n.......r..
|   3248: 01 01 05 04 08 17 88 80 80 80 80 08 03 00 34 00   ..............4.
|   3264: 00 00 12 02 31 62 02 02 04 01 01 69 02 06 01 01   ....1b.....i....
|   3280: 06 04 06 19 88 80 80 80 80 07 03 00 38 00 00 00   ............8...
|   3296: 14 04 02 31 32 02 02 05 01 01 61 02 08 03 01 01   ...12.....a.....
|   3312: 02 05 06 1b 88 80 80 80 80 06 03 00 3c 00 00 00   ............<...
|   3328: 16 06 30 74 68 65 72 65 02 02 02 00 02 31 31 02   ..0there.....11.
|   3344: 06 01 01 04 0a 15 88 80 80 80 80 05 03 00 30 00   ..............0.
|   3360: 00 00 11 01 01 05 04 30 74 68 65 02 06 01 01 07   .......0the.....
|   3376: 07 1c 88 80 80 80 80 04 03 00 3e 00 00 00 17 01   ..........>.....
|   3392: 01 06 02 30 6e 02 06 01 01 03 01 04 72 6f 77 73   ...0n.......rows
|   3408: 02 06 07 08 1b 88 80 80 80 80 03 03 00 3c 00 00   .............<..
|   3424: 00 16 08 30 62 65 74 77 65 65 6e 02 02 04 01 02   ...0between.....
|   3440: 69 6e 02 06 04 0c 1a 88 80 80 80 80 02 03 00 3a   in.............:
|   3456: 00 00 00 15 04 30 61 6e 64 02 06 01 01 02 02 02   .....0and.......
|   3472: 72 65 02 02 03 04 0a 17 88 80 80 80 80 01 03 00   re..............
|   3488: 34 00 00 00 12 02 30 31 02 06 01 01 04 01 01 32   4.....01.......2
|   3504: 02 02 05 04 08 08 84 80 80 80 80 12 03 00 16 00   ................
|   3520: 00 00 05 04 1b 84 80 80 80 80 11 03 00 3c 00 00   .............<..
|   3536: 00 16 05 34 74 61 62 6c 01 06 01 01 05 02 03 65   ...4tabl.......e
|   3552: 72 6d 01 02 04 0b 1b 84 80 80 80 80 10 03 00 3c   rm.............<
|   3568: 00 00 00 16 05 34 65 61 63 68 01 02 03 01 04 70   .....4each.....p
|   3584: 72 65 73 01 02 05 04 08 1a 84 80 80 80 80 0f 03   res.............
|   3600: 00 3a 00 00 00 15 04 33 74 65 72 01 02 04 02 02   .:.....3ter.....
|   3616: 68 65 01 06 01 01 03 04 08 1b 84 80 80 80 80 0e   he..............
|   3632: 03 00 3c 00 00 00 16 04 33 80 72 65 01 02 05 01   ..<.....3.re....
|   3648: 03 74 61 62 01 06 01 01 05 04 08 1a 84 80 80 80   .tab............
|   3664: 80 0d 03 00 3a 00 00 00 15 04 33 66 6f 72 01 02   ....:.....3for..
|   3680: 02 02 02 74 73 01 06 01 01 04 04 08 1b 84 80 80   ...ts...........
|   3696: 80 80 0c 03 00 3c 00 00 00 17 03 32 74 68 01 06   .....<.....2th..
|   3712: 01 01 03 00 04 33 65 61 63 01 02 03 04 09 18 84   .....3eac.......
|   3728: 80 80 80 80 0b 03 00 36 00 00 00 13 03 32 74 61   .......6.....2ta
|   3744: 01 06 01 01 05 02 01 65 01 02 04 04 09 19 84 80   .......e........
|   3760: 80 80 80 0a 03 00 38 00 00 00 14 03 32 69 6e 01   ......8.....2in.
|   3776: 06 01 01 02 01 02 70 72 01 02 05 04 09 18 84 80   ......pr........
|   3792: 80 80 80 09 03 00 36 00 00 00 13 03 32 66 6f 01   ......6.....2fo.
|   3808: 02 02 02 01 74 01 06 01 01 04 04 07 1b 84 80 80   ....t...........
|   3824: 80 80 08 03 00 3c 00 00 00 16 02 31 74 01 0a 04   .....<.....1t...
|   3840: 01 01 03 04 00 03 32 65 61 01 02 03 04 0a 17 84   ......2ea.......
|   3856: 80 80 80 80 07 03 00 34 00 00 00 12 02 31 69 01   .......4.....1i.
|   3872: 06 01 01 02 01 01 70 01 02 05 04 08 18 84 80 80   ......p.........
|   3888: 80 80 06 03 00 36 00 00 00 13 02 31 65 01 02 03   .....6.....1e...
|   3904: 01 01 66 01 08 02 01 01 04 04 06 1b 84 80 80 80   ..f.............
|   3920: 80 05 03 00 3c 00 00 00 16 05 30 74 65 72 6d 01   ....<.....0term.
|   3936: 02 04 02 02 68 65 01 06 01 01 03 04 09 14 84 80   ....he..........
|   3952: 80 80 80 04 03 00 2e 00 00 00 10 06 30 64 61 62   ............0dab
|   3968: 6c 65 01 06 01 01 05 04 15 84 80 80 80 80 03 03   le..............
|   3984: 00 30 00 00 00 11 02 08 30 70 72 65 73 65 6e 74   .0......0present
|   4000: 01 02 05 05 1b 84 80 80 80 80 02 03 00 3c 00 00   .............<..
|   4016: 00 16 04 30 66 74 73 01 06 01 01 04 01 02 69 6e   ...0fts.......in
|   4032: 01 06 01 01 04 0a 1a 84 80 80 80 80 01 03 00 3a   ...............:
|   4048: 00 00 00 15 05 30 65 61 63 68 01 02 03 01 13 66   .....0each.....f
|   4064: 6f 72 01 02 02 04 09 06 01 03 00 12 03 0b 0f 00   or..............
|   4080: 00 08 8c 80 80 80 80 11 03 00 16 00 00 00 05 04   ................
| page 3 offset 8192
|      0: 0a 00 00 00 32 0e 4f 00 0f fa 0f f1 0f e9 0f e1   ....2.O.........
|     16: 0f d8 0f d1 0f c9 0f c1 0f b9 0f b1 0f a9 0f a0   ................
|     32: 0f 98 0f 90 0f 87 0f 80 0f 78 0f 71 0f 68 0f 5f   .........x.q.h._
|     48: 0f 56 0f 4d 0f 41 0f 38 0f 2f 0f 26 0f 1d 0f 13   .V.M.A.8./.&....
|     64: 0f 0a 0f 01 0e f7 0e ee 0e e6 0e dd 0e d6 0e cd   ................
|     80: 0e c3 0e ba 0e 00 00 00 00 00 00 00 00 00 00 00   ................
|   3648: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08   ................
|   3664: 04 01 10 01 03 34 74 20 07 04 01 0e 01 03 34 1e   .....4t ......4.
|   3680: 09 04 01 12 01 03 33 74 68 1c 08 04 01 10 01 03   ......3th.......
|   3696: 33 6e 1a 08 04 01 10 01 03 32 77 18 08 04 01 10   3n.......2w.....
|   3712: 01 03 32 74 16 08 04 01 10 01 03 32 6e 14 07 04   ..2t.......2n...
|   3728: 01 0e 01 03 32 12 08 04 01 10 01 03 31 74 10 08   ....2.......1t..
|   3744: 04 01 10 01 03 31 6e 0e 07 04 01 0e 01 03 31 0c   .....1n.......1.
|   3760: 09 04 01 12 01 03 30 74 68 0a 08 04 01 10 01 03   ......0th.......
|   3776: 30 74 08 09 04 01 12 01 03 30 6e 75 06 08 04 01   0t.......0nu....
|   3792: 10 01 03 30 6e 04 06 04 01 0c 01 03 02 08 04 01   ...0n...........
|   3808: 10 01 02 34 72 22 07 04 01 0e 01 02 34 20 08 04   ...4r.......4 ..
|   3824: 01 10 01 02 33 72 1e 09 04 01 12 01 02 33 61 72   ....3r.......3ar
|   3840: 1c 08 04 01 10 01 02 32 74 1a 08 04 01 10 01 02   .......2t.......
|   3856: 32 69 18 09 04 01 12 01 02 32 61 72 16 08 04 01   2i.......2ar....
|   3872: 10 01 02 31 74 14 08 04 01 10 01 02 31 6e 12 08   ...1t.......1n..
|   3888: 04 01 10 01 02 31 62 10 08 04 01 10 01 02 31 32   .....1b.......12
|   3904: 0e 0b 04 01 16 01 02 30 74 68 65 72 0c 08 04 01   .......0ther....
|   3920: 10 01 02 30 74 0a 08 04 01 10 01 02 30 6e 08 08   ...0t.......0n..
|   3936: 14 01 10 01 02 30 62 06 08 04 01 10 01 02 30 61   .....0b.......0a
|   3952: 04 06 04 01 0c 01 02 02 07 04 09 10 01 34 74 22   .............4t.
|   3968: 06 04 09 0e 01 34 20 08 04 09 12 01 33 74 65 1e   .....4 .....3te.
|   3984: 07 04 09 10 01 33 70 1c 07 04 09 10 01 33 66 1a   .....3p......3f.
|   4000: 08 04 09 12 01 32 74 68 18 07 04 09 10 01 32 74   .....2th......2t
|   4016: 16 01 64 09 10 01 32 69 14 07 04 09 10 01 32 66   ..d...2i......2f
|   4032: 12 07 04 09 10 01 31 74 10 07 04 09 10 01 31 69   ......1t......1i
|   4048: 0e 06 04 09 0e 01 31 0c 08 04 09 12 01 30 74 65   ......1......0te
|   4064: 0a 06 04 09 10 01 30 74 08 07 04 09 10 01 30 70   ......0t......0p
|   4080: 06 08 04 09 12 00 00 00 00 00 00 00 00 00 00 00   ................
| page 4 offset 12288
|   4064: 00 00 00 00 00 00 00 00 00 00 00 05 03 03 00 10   ................
|   4080: 03 05 05 02 03 00 10 04 06 05 01 03 00 10 04 04   ................
| page 5 offset 16384
|      0: 0a 00 00 00 02 0f eb 00 0f eb 0f f4 00 00 00 00   ................
|   4064: 00 00 00 00 00 00 00 00 00 00 00 08 03 15 01 70   ...............p
|   4080: 67 73 7a 18 0b 03 1b 01 76 65 72 73 69 6f 6e 04   gsz.....version.
| page 6 offset 20480
|      0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   4080: 00 00 03 03 02 01 03 03 02 02 01 00 00 00 00 00   ................
| end crash-0f47112aa7520c.db
  }]
} {}

do_catchsql_test 1.1 {
  SELECT * FROM t1('R*') WHERE (a,b)<=(current_date,0) ORDER BY rowid DESC;
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
#
reset_db
do_test 2.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {

.open --hexdb
| size 24576 pagesize 4096 filename sql047467.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 00   .....@  ........
|     96: 00 00 00 00 0d 00 00 00 06 0e 0f 00 0f aa 0f 53   ...............S
|    112: 0e e8 0e 8b 0e 33 0e 0f 01 00 00 00 00 00 00 00   .....3..........
|   3584: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 22   ................
|   3600: 06 06 17 11 11 01 31 74 61 62 6c 65 62 62 62 62   ......1tablebbbb
|   3616: 06 43 52 45 41 54 45 20 54 41 42 4c 45 20 62 62   .CREATE TABLE bb
|   3632: 28 61 29 56 05 06 17 1f 1f 01 7d 74 61 62 6c 65   (a)V.......table
|   3648: 74 31 5f 63 6f 6e 66 69 67 74 31 5f 63 6f 6e 66   t1_configt1_conf
|   3664: 69 67 05 43 52 45 41 54 45 20 54 41 42 4c 45 20   ig.CREATE TABLE 
|   3680: 27 74 31 5f 63 6f 6e 66 69 67 27 28 6b 20 50 52   't1_config'(k PR
|   3696: 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 20 57 49   IMARY KEY, v) WI
|   3712: 54 48 4f 55 54 20 52 4f 57 49 44 5b 04 07 17 21   THOUT ROWID[...!
|   3728: 21 01 81 01 74 61 62 6c 65 74 31 5f 64 6f 63 73   !...tablet1_docs
|   3744: 69 7a 65 74 31 5f 64 6f 63 73 69 7a 65 04 43 52   izet1_docsize.CR
|   3760: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 64   EATE TABLE 't1_d
|   3776: 6f 63 73 69 7a 65 27 28 69 64 20 49 4e 54 45 47   ocsize'(id INTEG
|   3792: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20   ER PRIMARY KEY, 
|   3808: 73 7a 20 42 4c 4f 42 29 69 03 07 17 19 19 01 81   sz BLOB)i.......
|   3824: 2d 74 61 62 6c 65 74 31 5f 69 64 78 74 31 5f 69   -tablet1_idxt1_i
|   3840: 64 78 03 43 52 45 41 54 45 20 54 41 42 4c 45 20   dx.CREATE TABLE 
|   3856: 27 74 31 5f 69 64 78 27 28 73 65 67 69 64 2c 20   't1_idx'(segid, 
|   3872: 74 65 72 6d 2c 20 70 67 6e 6f 2c 20 50 52 49 4d   term, pgno, PRIM
|   3888: 41 52 59 20 4b 45 59 28 73 65 67 69 64 2c 20 74   ARY KEY(segid, t
|   3904: 65 72 6d 29 29 20 57 49 54 48 4f 55 54 20 52 4f   erm)) WITHOUT RO
|   3920: 57 49 44 55 02 07 17 1b 1b 01 81 01 74 61 62 6c   WIDU........tabl
|   3936: 65 74 31 5f 64 61 74 61 74 31 5f 64 61 74 61 02   et1_datat1_data.
|   3952: 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 31   CREATE TABLE 't1
|   3968: 5f 64 61 74 61 27 28 69 64 20 49 4e 54 45 47 45   _data'(id INTEGE
|   3984: 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 62   R PRIMARY KEY, b
|   4000: 6c 6f 63 6b 20 42 4c 4f 42 29 54 01 07 17 11 11   lock BLOB)T.....
|   4016: 08 81 15 74 61 62 6c 65 74 31 74 31 43 52 45 41   ...tablet1t1CREA
|   4032: 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 4c 45   TE VIRTUAL TABLE
|   4048: 20 74 31 20 55 53 49 4e 47 20 66 74 73 35 28 61    t1 USING fts5(a
|   4064: 2c 62 2c 70 72 65 66 69 78 3d 22 31 2c 32 2c 33   ,b,prefix=.1,2,3
|   4080: 2c 34 22 2c 20 63 6f 6e 74 65 6e 74 3d 22 22 29   ,4., content=..)
| page 2 offset 4096
|      0: 0d 0b 6a 00 37 09 4c 02 0f e7 09 4c 0f c6 0f a4   ..j.7.L....L....
|     16: 0f 88 0f 6d 0f 4b 0f 2c 0f 0e 0e ec 0e cd 0e ad   ...m.K.,........
|     32: 0e 8e 0e 6c 0e 4b 0e 29 0e 08 0d e6 0d c4 0d b5   ...l.K.)........
|     48: 0d 97 0d 76 0d 54 0d 31 0d 15 0c f3 0c d3 0c b5   ...v.T.1........
|     64: 0c 95 0c 73 0c 54 0c 32 0c 10 0b ee 0b cc 0b b0   ...s.T.2........
|     80: 0b 8d 0b 7e 0b 48 0b 2e 0b 0b 0a ef 00 00 00 00   ...~.H..........
|   2368: 00 00 00 00 00 00 00 00 00 00 00 00 15 0a 03 00   ................
|   2384: 30 00 00 00 01 01 03 35 00 03 01 11 12 02 01 12   0......5........
|   2400: 03 01 11 1c 8c 80 80 80 80 10 03 00 3e 00 00 00   ............>...
|   2416: 17 01 05 05 34 74 61 62 6c 03 02 03 01 04 77 68   ....4tabl.....wh
|   2432: 65 72 03 02 06 09 1b 8c 80 80 80 80 0f 03 00 3c   er.............<
|   2448: 00 00 00 16 05 34 66 74 73 34 03 02 02 01 04 6e   .....4fts4.....n
|   2464: 75 6d 62 03 06 01 04 09 1b 8c 80 80 80 80 0e 03   umb.............
|   2480: 00 3b ff f0 00 16 04 33 74 68 65 03 06 01 01 04   .;.....3the.....
|   2496: 01 03 77 68 65 03 02 04 04 0a 1b 8c 80 80 80 80   ..whe...........
|   2512: 0d 03 00 3c 00 00 00 16 04 33 6e 75 6d 03 06 01   ...<.....3num...
|   2528: 01 05 01 03 74 61 62 03 02 03 04 0a 19 8c 80 80   ....tab.........
|   2544: 80 80 0c 03 00 38 00 00 00 14 03 32 77 68 03 02   .....8.....2wh..
|   2560: 04 00 04 33 66 74 73 03 02 02 04 07 18 8c 80 80   ...3fts.........
|   2576: 80 80 0b 03 00 36 00 00 00 13 03 32 74 61 03 02   .....6.....2ta..
|   2592: 03 02 01 68 03 06 01 01 04 04 07 1b 8c 80 80 80   ...h............
|   2608: 80 0a 03 00 3c 00 00 00 16 03 32 6e 75 03 06 01   ....<.....2nu...
|   2624: 01 05 01 02 6f 66 03 06 01 01 06 04 09 19 8c 80   ....of..........
|   2640: 80 80 80 09 03 00 38 00 00 00 14 03 32 66 74 03   ......8.....2ft.
|   2656: 02 02 01 02 69 73 03 06 01 01 03 04 07 18 8c 80   ....is..........
|   2672: 80 80 80 08 03 00 36 00 00 00 13 02 31 74 03 08   ......6.....1t..
|   2688: 03 01 01 04 01 01 77 03 02 04 04 09 1a 8c 80 80   ......w.........
|   2704: 80 80 07 03 00 3a 00 00 00 15 02 31 6e 03 08 01   .....:.....1n...
|   2720: 01 02 05 01 00 6f 03 06 01 01 06 14 09 18 8c 80   .....o..........
|   2736: 80 80 80 06 03 00 36 00 00 00 03 04 02 31 66 03   ......6......1f.
|   2752: 02 02 01 01 69 03 06 01 01 03 04 f6 1c 8c 80 80   ....i...........
|   2768: 80 80 05 03 00 3e 00 00 00 17 04 30 74 68 65 03   .....>.....0the.
|   2784: f6 01 01 04 01 05 77 68 65 72 65 03 02 04 0a 15   ......where.....
|   2800: 8c 80 80 80 80 04 03 00 30 00 00 00 11 01 01 06   ........0.......
|   2816: 06 30 74 61 62 6c 65 0f 42 03 07 1c 8c 81 80 80   .0table.B.......
|   2832: 80 03 03 00 3e 00 00 00 17 07 30 6e 75 6d 62 65   ....>.....0numbe
|   2848: 72 03 06 01 01 05 01 02 6f 66 03 06 04 0d 13 8c   r.......of......
|   2864: 80 80 80 80 02 03 00 2c 00 00 00 0f 01 01 03 02   .......,........
|   2880: 30 6e 03 06 01 01 02 07 1b 8c 80 80 80 80 01 03   0n..............
|   2896: 00 3c 00 00 00 16 08 30 66 74 73 34 61 75 78 03   .<.....0fts4aux.
|   2912: 02 02 01 02 69 73 03 06 04 0c 00 00 00 14 2a 00   ....is........*.
|   2928: 00 00 01 01 02 24 00 02 01 01 12 02 01 12 08 88   .....$..........
|   2944: 80 80 80 80 12 03 00 16 00 00 00 05 02 1c 88 80   ................
|   2960: 80 80 80 11 03 00 3e 00 00 00 17 05 34 72 6f 77   ......>.....4row
|   2976: 73 02 06 01 01 05 01 04 74 68 65 72 02 02 04 0b   s.......ther....
|   2992: 15 88 80 80 80 80 10 03 00 30 00 00 00 11 02 01   .........0......
|   3008: 01 07 05 34 62 65 74 77 02 02 04 08 1b 88 80 80   ...4betw........
|   3024: 80 80 0f 03 00 3c 00 00 00 16 04 04 33 72 6f 77   .....<......3row
|   3040: 02 06 01 01 05 01 03 74 68 65 02 08 05 0a 1b 88   .......the......
|   3056: 80 80 80 80 0e 03 00 3c 00 00 00 16 01 01 02 04   .......<........
|   3072: 33 61 72 65 02 02 03 01 03 62 65 74 02 02 07 08   3are.....bet....
|   3088: 1b 88 80 80 80 80 0d 03 00 3c 00 00 00 16 13 32   .........<.....2
|   3104: 74 68 02 08 02 01 01 07 00 04 33 61 6e 64 02 06   th........3and..
|   3120: 04 0a 1b 88 80 80 80 80 0c 03 00 3c 00 00 00 16   ...........<....
|   3136: 03 32 69 6e 02 06 01 01 06 01 02 72 6f 02 06 01   .2in.......ro...
|   3152: 01 05 04 09 18 88 80 80 80 80 0b 03 00 36 00 00   .............6..
|   3168: 00 13 02 03 32 61 72 02 02 03 01 02 62 65 02 02   ....2ar.....be..
|   3184: 04 05 07 1b 88 80 80 80 80 0a 03 00 3c 00 94 50   ............<..P
|   3200: 16 02 31 74 02 08 02 01 01 07 00 03 32 61 6e 02   ..1t........2an.
|   3216: 06 01 01 04 09 19 88 80 80 80 80 09 03 00 38 00   ..............8.
|   3232: 00 00 14 02 31 6e 02 06 01 01 03 01 01 72 02 06   ....1n.......r..
|   3248: 01 01 05 04 08 17 88 80 80 80 80 08 03 00 34 00   ..............4.
|   3264: 00 00 12 02 31 62 02 02 04 01 01 69 02 06 01 01   ....1b.....i....
|   3280: 06 04 06 19 88 80 80 80 80 07 03 00 38 00 00 00   ............8...
|   3296: 14 04 02 31 32 02 02 05 01 01 61 02 08 03 01 01   ...12.....a.....
|   3312: 02 05 06 1b 88 80 80 80 80 06 03 00 3c 00 00 00   ............<...
|   3328: 16 06 30 74 68 65 72 65 02 02 02 00 02 31 31 02   ..0there.....11.
|   3344: 06 01 01 04 0a 15 88 80 80 80 80 05 03 00 30 00   ..............0.
|   3360: 00 00 11 01 01 05 04 30 74 68 65 02 06 01 01 07   .......0the.....
|   3376: 07 1c 88 80 80 80 80 04 03 00 3e 00 00 00 17 01   ..........>.....
|   3392: 01 06 02 30 6e 02 06 01 01 03 01 04 72 6f 77 73   ...0n.......rows
|   3408: 02 06 07 08 1b 88 80 80 80 80 03 03 00 3c 00 00   .............<..
|   3424: 00 16 08 30 62 65 74 77 65 65 6e 02 02 04 01 02   ...0between.....
|   3440: 69 6e 02 06 04 0c 1a 88 80 80 80 80 02 03 00 3a   in.............:
|   3456: 00 00 00 15 04 30 61 6e 64 02 06 01 01 02 02 02   .....0and.......
|   3472: 72 65 02 02 03 04 0a 17 88 80 80 80 80 01 03 00   re..............
|   3488: 34 00 00 00 12 02 30 31 02 06 01 01 04 01 01 32   4.....01.......2
|   3504: 02 02 05 04 08 08 84 80 80 80 80 12 03 00 16 00   ................
|   3520: 00 00 05 04 1b 84 80 80 80 80 11 03 00 3c 00 00   .............<..
|   3536: 00 16 05 34 74 61 62 6c 01 06 01 01 05 02 03 65   ...4tabl.......e
|   3552: 72 6d 01 02 04 0b 1b 84 80 80 80 80 10 03 00 3c   rm.............<
|   3568: 00 00 00 16 05 34 65 61 63 68 01 02 03 01 04 70   .....4each.....p
|   3584: 72 65 73 01 02 05 04 08 1a 84 80 80 80 80 0f 03   res.............
|   3600: 00 3a 00 00 00 15 04 33 74 65 72 01 02 04 02 02   .:.....3ter.....
|   3616: 68 65 01 06 01 01 03 04 08 1b 84 80 80 80 80 0e   he..............
|   3632: 03 00 3c 00 00 00 16 04 33 80 72 65 01 02 05 01   ..<.....3.re....
|   3648: 03 74 61 62 01 06 01 01 05 04 08 1a 84 80 80 80   .tab............
|   3664: 80 0d 03 00 3a 00 00 00 15 04 33 66 6f 72 01 02   ....:.....3for..
|   3680: 02 02 02 74 73 01 06 01 01 04 04 08 1b 84 80 80   ...ts...........
|   3696: 80 80 0c 03 00 3c 00 00 00 17 03 32 74 68 01 06   .....<.....2th..
|   3712: 01 01 03 00 04 33 65 61 63 01 02 03 04 09 18 84   .....3eac.......
|   3728: 80 80 80 80 0b 03 00 36 00 00 00 13 03 32 74 61   .......6.....2ta
|   3744: 01 06 01 01 05 02 01 65 01 02 04 04 09 19 84 80   .......e........
|   3760: 80 80 80 0a 03 00 38 00 00 00 14 03 32 69 6e 01   ......8.....2in.
|   3776: 06 01 01 02 01 02 70 72 01 02 05 04 09 18 84 80   ......pr........
|   3792: 80 80 80 09 03 00 36 00 00 00 13 03 32 66 6f 01   ......6.....2fo.
|   3808: 02 02 02 01 74 01 06 01 01 04 04 07 1b 84 80 80   ....t...........
|   3824: 80 80 08 03 00 3c 00 00 00 16 02 31 74 01 0a 04   .....<.....1t...
|   3840: 01 01 03 04 00 03 32 65 61 01 02 03 04 0a 17 84   ......2ea.......
|   3856: 80 80 80 80 07 03 00 34 00 00 00 12 02 31 69 01   .......4.....1i.
|   3872: 06 01 01 02 01 01 70 01 02 05 04 08 18 84 80 80   ......p.........
|   3888: 80 80 06 03 00 36 00 00 00 13 02 31 65 01 02 03   .....6.....1e...
|   3904: 01 01 66 01 08 02 01 01 04 04 06 1b 84 80 80 80   ..f.............
|   3920: 80 05 03 00 3c 00 00 00 16 05 30 74 65 72 6d 01   ....<.....0term.
|   3936: 02 04 02 02 68 65 01 06 01 01 03 04 09 14 84 80   ....he..........
|   3952: 80 80 80 04 03 00 2e 00 00 00 10 06 30 64 61 62   ............0dab
|   3968: 6c 65 01 06 01 01 05 04 15 84 80 80 80 80 03 03   le..............
|   3984: 00 30 00 00 00 11 02 08 30 70 72 65 73 65 6e 74   .0......0present
|   4000: 01 02 05 05 1b 84 80 80 80 80 02 03 00 3c 00 00   .............<..
|   4016: 00 16 04 30 66 74 73 01 06 01 01 04 01 02 69 6e   ...0fts.......in
|   4032: 01 06 01 01 04 0a 1a 84 80 80 80 80 01 03 00 3a   ...............:
|   4048: 00 00 00 15 05 30 65 61 63 68 01 02 03 01 13 66   .....0each.....f
|   4064: 6f 72 01 02 02 04 09 06 01 03 00 12 03 0b 0f 00   or..............
|   4080: 00 08 8c 80 80 80 80 11 03 00 16 00 00 00 05 04   ................
| page 3 offset 8192
|      0: 0a 00 00 00 32 0e 4f 00 0f fa 0f f1 0f e9 0f e1   ....2.O.........
|     16: 0f d8 0f d1 0f c9 0f c1 0f b9 0f b1 0f a9 0f a0   ................
|     32: 0f 98 0f 90 0f 87 0f 80 0f 78 0f 71 0f 68 0f 5f   .........x.q.h._
|     48: 0f 56 0f 4d 0f 41 0f 38 0f 2f 0f 26 0f 1d 0f 13   .V.M.A.8./.&....
|     64: 0f 0a 0f 01 0e f7 0e ee 0e e6 0e dd 0e d6 0e cd   ................
|     80: 0e c3 0e ba 0e 00 00 00 00 00 00 00 00 00 00 00   ................
|   3648: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08   ................
|   3664: 04 01 10 01 03 34 74 20 07 04 01 0e 01 03 34 1e   .....4t ......4.
|   3680: 09 04 01 12 01 03 33 74 68 1c 08 04 01 10 01 03   ......3th.......
|   3696: 33 6e 1a 08 04 01 10 01 03 32 77 18 08 04 01 10   3n.......2w.....
|   3712: 01 03 32 74 16 08 04 01 10 01 03 32 6e 14 07 04   ..2t.......2n...
|   3728: 01 0e 01 03 32 12 08 04 01 10 01 03 31 74 10 08   ....2.......1t..
|   3744: 04 01 10 01 03 31 6e 0e 07 04 01 0e 01 03 31 0c   .....1n.......1.
|   3760: 09 04 01 12 01 03 30 74 68 0a 08 04 01 10 01 03   ......0th.......
|   3776: 30 74 08 09 04 01 12 01 03 30 6e 75 06 08 04 01   0t.......0nu....
|   3792: 10 01 03 30 6e 04 06 04 01 0c 01 03 02 08 04 01   ...0n...........
|   3808: 10 01 02 34 72 22 07 04 01 0e 01 02 34 20 08 04   ...4r.......4 ..
|   3824: 01 10 01 02 33 72 1e 09 04 01 12 01 02 33 61 72   ....3r.......3ar
|   3840: 1c 08 04 01 10 01 02 32 74 1a 08 04 01 10 01 02   .......2t.......
|   3856: 32 69 18 09 04 01 12 01 02 32 61 72 16 08 04 01   2i.......2ar....
|   3872: 10 01 02 31 74 14 08 04 01 10 01 02 31 6e 12 08   ...1t.......1n..
|   3888: 04 01 10 01 02 31 62 10 08 04 01 10 01 02 31 32   .....1b.......12
|   3904: 0e 0b 04 01 16 01 02 30 74 68 65 72 0c 08 04 01   .......0ther....
|   3920: 10 01 02 30 74 0a 08 04 01 10 01 02 30 6e 08 08   ...0t.......0n..
|   3936: 14 01 10 01 02 30 62 06 08 04 01 10 01 02 30 61   .....0b.......0a
|   3952: 04 06 04 01 0c 01 02 02 07 04 09 10 01 34 74 22   .............4t.
|   3968: 06 04 09 0e 01 34 20 08 04 09 12 01 33 74 65 1e   .....4 .....3te.
|   3984: 07 04 09 10 01 33 70 1c 07 04 09 10 01 33 66 1a   .....3p......3f.
|   4000: 08 04 09 12 01 32 74 68 18 07 04 09 10 01 32 74   .....2th......2t
|   4016: 16 01 64 09 10 01 32 69 14 07 04 09 10 01 32 66   ..d...2i......2f
|   4032: 12 07 04 09 10 01 31 74 10 07 04 09 10 01 31 69   ......1t......1i
|   4048: 0e 06 04 09 0e 01 31 0c 08 04 09 12 01 30 74 65   ......1......0te
|   4064: 0a 06 04 09 10 01 30 74 08 07 04 09 10 01 30 70   ......0t......0p
|   4080: 06 08 04 09 12 00 00 00 00 00 00 00 00 00 00 00   ................
| page 4 offset 12288
|   4064: 00 00 00 00 00 00 00 00 00 00 00 05 03 03 00 10   ................
|   4080: 03 05 05 02 03 00 10 04 06 05 01 03 00 10 04 04   ................
| page 5 offset 16384
|      0: 0a 00 00 00 02 0f eb 00 0f eb 0f f4 00 00 00 00   ................
|   4064: 00 00 00 00 00 00 00 00 00 00 00 08 03 15 01 70   ...............p
|   4080: 67 73 7a 18 0b 03 1b 01 76 65 72 73 69 6f 6e 04   gsz.....version.
| page 6 offset 20480
|      0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   4080: 00 00 03 03 02 01 03 03 02 02 01 00 00 00 00 00   ................
| end sql047467.txt.db
}]} {}

do_catchsql_test 2.1 {
SELECT * FROM t1('R*R*R*R*') WHERE (a,b)<=(current_date,0) ORDER BY rowid DESC;
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
reset_db
do_test 3.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
.open --hexdb
| size 32768 pagesize 4096 filename crash-c69fcaceff1e50.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 08   .....@  ........
|     32: 00 00 00 02 00 00 00 01 00 00 00 09 00 00 00 04   ................
|     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 0d 92 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 41 52 59 20 4b 45   TEGER PRIMARY 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 20 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 94 00 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 01 bb 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 30 31 36 30   ...........20160
|   3264: 36 30 39 01 02 07 01 02 07 01 02 07 01 01 34 01   609...........4.
|   3280: 02 05 01 02 05 01 02 05 01 01 35 01 02 04 01 02   ..........5.....
|   3296: 04 01 02 04 02 07 30 30 30 30 30 30 30 1c 02 04   ......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 02 02 03 06 01 02 02 03 06 01   ................
|   3344: 02 02 03 06 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 03 01 02 03 02 04   bstat...........
|   3424: 65 62 75 67 04 02 02 01 02 02 01 02 02 01 06 65   ebug...........e
|   3440: 6b b1 62 6c 65 07 02 02 01 02 02 01 02 02 01 02   k.ble...........
|   3456: 02 01 02 02 01 02 02 01 02 02 01 02 02 01 02 02   ................
|   3472: 01 02 02 01 02 02 05 02 02 01 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 1a 02 03   .........fts4...
|   3536: 01 02 03 01 02 03 04 01 35 0d 02 03 01 02 03 01   ........5.......
|   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 10 02 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: 01 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 03 06 01 02 02 03   ocase...........
|   3680: 06 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06   ................
|   3696: 01 02 02 03 06 01 02 02 03 06 01 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 01   ...omit.........
|   3744: ff ff ff ff ff ff ff ff ff ff ff ff ff ff f1 02   ................
|   3760: 58 81 96 4d 01 06 01 02 02 03 06 01 02 02 03 06   X..M............
|   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 c6 02 01 06 01 01 02 01 06 01 01 02   ................
|   3888: 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01   ................
|   3904: 06 01 01 02 00 f6 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 02 01 06 01 01 02 01 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 02 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 0f 0c 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 01 0f fa 00 0f fa 00 00 00 00 00 00   ................
|   4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02   ................
| 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.
| end crash-c69fcaceff1e50.db
}]} {}

do_catchsql_test 3.1 {
  UPDATE t1 SET b=quote(zeroblob(200)) WHERE a MATCH 'thra*T';
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
reset_db
do_test 4.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
.open --hexdb
| size 24576 pagesize 4096 filename crash-ef6738247b1344.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 10 00 06 40 00 00 06   .....@  ....@...
|     32: 00 00 00 00 00 00 00 00 00 00 00 06 00 00 00 00   ................
|     96: 00 00 00 00 0d 00 00 00 06 0e 0f 00 0f aa 0f 53   ...............S
|    112: 0e e8 0e 8b 0e 33 0e 0f 00 00 00 00 00 00 00 00   .....3..........
|   3584: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 22   ................
|   3600: 06 06 17 11 11 01 31 74 61 62 6c 65 62 62 62 62   ......1tablebbbb
|   3616: 06 43 52 45 41 54 45 20 54 41 42 4c 45 20 62 62   .CREATE TABLE bb
|   3632: 28 61 29 56 05 06 17 1f 1f 01 7d 74 61 62 6c 65   (a)V.......table
|   3648: 74 31 5f 63 6f 6e 66 69 67 74 31 5f 63 6f 6e 66   t1_configt1_conf
|   3664: 69 67 05 43 52 45 41 54 45 20 54 41 42 4c 45 20   ig.CREATE TABLE 
|   3680: 27 74 31 5f 63 6f 6e 66 69 67 27 28 6b 20 50 52   't1_config'(k PR
|   3696: 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 20 57 49   IMARY KEY, v) WI
|   3712: 54 48 4f 55 54 20 52 4f 57 49 44 5b 04 07 17 21   THOUT ROWID[...!
|   3728: 21 01 81 01 74 61 62 6c 65 74 31 5f 64 6f 63 73   !...tablet1_docs
|   3744: 69 7a 65 74 31 5f 64 6f 63 73 69 7a 65 04 43 52   izet1_docsize.CR
|   3760: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 64   EATE TABLE 't1_d
|   3776: 6f 63 73 69 7a 65 27 28 69 64 20 49 4e 54 45 47   ocsize'(id INTEG
|   3792: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20   ER PRIMARY KEY, 
|   3808: 73 7a 20 42 4c 4f 42 29 69 03 07 17 19 19 01 81   sz BLOB)i.......
|   3824: 2d 74 61 62 6c 65 74 31 5f 69 64 78 74 31 5f 69   -tablet1_idxt1_i
|   3840: 64 78 03 43 52 45 41 54 45 20 54 41 42 4c 45 20   dx.CREATE TABLE 
|   3856: 27 74 31 5f 69 64 78 27 28 73 65 67 69 64 2c 20   't1_idx'(segid, 
|   3872: 74 65 72 6d 2c 20 6f 67 6e 6f 2c 20 50 52 49 4d   term, ogno, PRIM
|   3888: 41 52 59 20 4b 45 59 28 73 65 67 69 64 2c 20 74   ARY KEY(segid, t
|   3904: 65 72 6d 29 29 20 57 49 54 48 4f 55 54 20 52 4f   erm)) WITHOUT RO
|   3920: 57 49 44 55 35 07 17 1b 1b 01 81 01 74 61 62 6c   WIDU5.......tabl
|   3936: 65 74 31 5f 64 61 74 61 74 31 5f 64 61 74 61 02   et1_datat1_data.
|   3952: 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 31   CREATE TABLE 't1
|   3968: 5f 64 61 74 61 27 28 69 64 20 49 4e 54 45 47 45   _data'(id INTEGE
|   3984: 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 62   R PRIMARY KEY, b
|   4000: 6c 6f 63 6b 20 42 4c 4f 42 29 54 01 07 17 11 11   lock BLOB)T.....
|   4016: 08 81 15 74 61 62 6c 65 74 31 74 31 43 52 45 41   ...tablet1t1CREA
|   4032: 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 4c 45   TE VIRTUAL TABLE
|   4048: 20 74 31 20 55 53 49 4e 47 20 66 74 73 35 28 61    t1 USING fts5(a
|   4064: 2c 62 2c 70 72 65 66 69 78 3d 22 31 2c 32 2c 33   ,b,prefix=.1,2,3
|   4080: 2c 34 22 2c 20 63 6f 6e 74 65 6e 74 3d 22 22 29   ,4., content=..)
| page 2 offset 4096
|      0: 0d 0b 6a 00 37 09 4c 02 0f e7 09 4c 0f c6 0f a4   ..j.7.L....L....
|     16: 0f 88 0f 6d 0f 4b 0f 2c 0f 0e 0e ec 0e cd 0e ad   ...m.K.,........
|     32: 0e 8e 0e 6c 0e 4b 0e 29 0e 08 0d e6 0d c4 0d b5   ...l.K.)........
|     48: 0d 97 0d 76 0d 54 0d 31 0d 15 0c f3 0c d3 0c b5   ...v.T.1........
|     64: 0c 95 0c 73 0c 54 0c 32 0c 10 0b ee 0b cc 0b b0   ...s.T.2........
|     80: 0b 8d 0b 7e 0b 48 0b 2e 0b 0b 0a ef 0a cc 0a 00   ...~.H..........
|   2368: 00 00 00 00 00 00 00 00 00 00 00 00 15 0a 03 00   ................
|   2384: 30 00 00 00 01 01 03 35 00 03 01 01 12 02 01 12   0......5........
|   2400: 03 01 11 1c 8c 80 80 80 80 10 02 9c 3e 00 00 00   ............>...
|   2416: 17 01 05 05 34 74 61 62 6c 03 02 03 01 04 77 68   ....4tabl.....wh
|   2432: 65 72 03 02 06 09 1b 8c 80 80 80 80 0f 03 00 3c   er.............<
|   2448: 00 00 00 16 05 34 66 74 73 34 03 02 02 01 04 6e   .....4fts4.....n
|   2464: 75 6d 62 03 06 01 04 09 1b 8c 80 80 80 80 0e 03   umb.............
|   2480: 00 3c 00 00 00 16 04 33 74 68 65 03 06 01 01 04   .<.....3the.....
|   2496: 01 03 77 68 65 03 02 04 04 0a 1b 8c 80 80 80 80   ..whe...........
|   2512: 0d 03 00 3c 00 00 00 16 04 33 6e 75 6d 03 06 01   ...<.....3num...
|   2528: 01 05 01 03 74 61 62 03 02 03 04 0a 19 8c 80 80   ....tab.........
|   2544: 80 80 0c 03 00 38 00 00 00 14 03 32 77 68 03 02   .....8.....2wh..
|   2560: 04 00 04 33 66 74 73 03 12 02 04 07 18 8c 80 80   ...3fts.........
|   2576: 80 80 0b 03 00 36 00 00 00 13 03 32 74 61 03 02   .....6.....2ta..
|   2592: 03 02 01 68 03 06 01 01 04 04 07 1b 8c 80 80 80   ...h............
|   2608: 80 0a 03 00 3c 00 00 00 16 03 32 6e 75 03 06 01   ....<.....2nu...
|   2624: 01 05 01 02 6f 66 03 06 01 01 06 04 09 19 8c 80   ....of..........
|   2640: 82 d0 80 09 03 00 38 00 00 00 14 03 32 66 74 03   ......8.....2ft.
|   2656: 02 02 01 02 69 73 03 06 01 01 03 04 07 18 8c 80   ....is..........
|   2672: 80 80 80 08 03 00 36 00 00 00 13 02 31 74 03 08   ......6.....1t..
|   2688: 03 01 01 04 01 01 77 03 02 04 04 09 1a 8c 80 80   ......w.........
|   2704: 80 80 07 03 00 3a 00 00 00 15 02 31 6e 03 08 01   .....:.....1n...
|   2720: 01 02 05 01 01 6f 03 06 01 01 06 04 09 18 8c 80   .....o..........
|   2736: 81 80 80 06 03 00 36 00 00 00 13 04 12 31 66 03   ......6......1f.
|   2752: 02 02 01 01 69 03 06 01 01 03 05 06 1c 8c 80 80   ....i...........
|   2768: 80 80 05 03 00 3e 00 00 00 17 04 30 74 68 65 03   .....>.....0the.
|   2784: 06 01 01 04 01 05 77 68 65 72 65 03 02 04 0a 15   ......where.....
|   2800: 8c 80 65 80 80 04 03 00 30 00 00 00 11 01 01 06   ..e.....0.......
|   2816: 06 30 74 61 62 6c 65 03 02 03 07 1c 8c 80 80 80   .0table.........
|   2832: 80 03 03 00 3e 00 00 00 17 07 30 6e 75 6d 62 65   ....>.....0numbe
|   2848: 72 03 06 01 01 05 01 02 6f 66 03 06 04 0d 13 8c   r.......of......
|   2864: 80 80 80 80 02 03 00 2c 00 00 00 0f fc 01 03 02   .......,........
|   2880: 30 6e 03 06 01 00 f2 07 1b 8c 80 80 80 80 01 03   0n..............
|   2896: 00 3c 00 00 00 16 08 30 66 74 73 34 61 75 78 03   .<.....0fts4aux.
|   2912: 03 02 01 02 69 73 03 06 04 0c 00 00 00 18 ea 00   ....is..........
|   2928: 00 00 01 01 02 24 00 02 01 01 12 02 01 12 08 88   .....$..........
|   2944: 80 80 80 80 12 03 00 12 10 00 00 05 02 1c 88 80   ................
|   2960: 80 80 80 11 03 00 3e 00 00 00 17 05 34 72 6f 77   ......>.....4row
|   2976: 73 02 06 01 01 05 01 04 74 68 65 72 02 02 04 0b   s.......ther....
|   2992: 15 88 80 80 80 80 10 03 00 2f ff ff f0 11 02 01   ........./......
|   3008: 01 07 05 34 62 65 74 77 02 02 04 08 1b 88 80 80   ...4betw........
|   3024: 80 80 0f cf 00 3c 00 00 00 16 04 04 33 72 6f 77   .....<......3row
|   3040: 02 06 01 01 05 01 03 74 68 65 02 08 05 0a 1b 88   .......the......
|   3056: 80 80 80 80 0d 03 00 3c 00 00 00 16 00 01 02 04   .......<........
|   3072: 33 61 72 65 02 02 03 01 03 62 65 74 02 02 07 08   3are.....bet....
|   3088: 1b 88 80 80 80 80 0d 03 00 3c 00 00 00 16 03 32   .........<.....2
|   3104: 74 68 02 08 02 01 01 07 00 04 33 61 6e 64 02 06   th........3and..
|   3120: 04 0a 1b 88 80 80 80 80 0c 03 00 3c 00 00 00 16   ...........<....
|   3136: 03 32 69 6e 02 06 01 01 06 01 02 72 6f 02 06 01   .2in.......ro...
|   3152: 01 05 04 09 18 88 80 80 80 80 0b 03 00 36 00 00   .............6..
|   3168: 00 13 02 03 32 61 72 02 02 03 01 02 62 65 02 02   ....2ar.....be..
|   3184: 04 05 07 1b 88 80 80 80 80 0a 03 00 3c 00 00 00   ............<...
|   3200: 16 12 31 74 02 08 02 01 01 07 00 03 32 61 6e 02   ..1t........2an.
|   3216: 06 01 01 04 09 19 88 80 80 80 80 09 03 00 38 00   ..............8.
|   3232: 00 00 14 02 31 6e 02 06 01 01 03 01 01 72 02 06   ....1n.......r..
|   3248: 01 01 05 04 08 17 78 80 80 80 80 08 03 00 34 10   ......x.......4.
|   3264: 01 00 12 02 31 62 02 02 04 01 01 69 02 06 01 01   ....1b.....i....
|   3280: 06 04 06 19 88 80 80 80 80 07 03 00 38 00 00 00   ............8...
|   3296: 14 04 02 31 32 02 02 05 01 01 61 02 08 03 01 01   ...12.....a.....
|   3312: 02 05 06 1b 88 80 80 80 80 06 03 00 3c 00 00 00   ............<...
|   3328: 16 06 30 74 68 65 72 65 e7 02 02 00 02 31 31 02   ..0there.....11.
|   3344: 06 01 01 04 0a 15 88 80 80 80 80 05 03 00 30 00   ..............0.
|   3360: 00 00 11 01 01 05 e5 30 74 68 65 02 06 01 01 07   .......0the.....
|   3376: 07 1c 88 80 80 80 80 04 03 00 3e 00 00 00 17 01   ..........>.....
|   3392: 01 06 02 30 6e 02 06 01 01 03 01 04 72 6f 77 73   ...0n.......rows
|   3408: 02 06 07 08 1b 88 80 80 80 80 03 03 00 3c 00 00   .............<..
|   3424: 00 16 08 30 62 65 74 77 65 65 6e 02 02 04 01 02   ...0between.....
|   3440: 69 6e 02 06 04 0c 1a 88 80 80 80 80 02 03 00 3a   in.............:
|   3456: 00 00 00 15 04 30 61 6e 64 02 06 01 01 02 02 02   .....0and.......
|   3472: 72 65 02 02 03 04 0a 17 88 80 80 80 80 01 03 00   re..............
|   3488: 34 01 00 00 12 02 30 31 02 06 01 01 04 01 01 32   4.....01.......2
|   3504: 02 02 05 04 08 08 84 80 80 80 80 12 03 00 16 00   ................
|   3520: 00 00 05 04 1b 84 80 80 80 80 11 03 00 3c 00 00   .............<..
|   3536: 00 16 05 34 74 61 62 6c 01 06 01 01 05 02 03 65   ...4tabl.......e
|   3552: 72 6d 01 02 04 0b 1b 84 80 80 80 80 10 03 00 3c   rm.............<
|   3568: 00 00 00 16 05 34 65 61 63 68 01 02 02 01 04 70   .....4each.....p
|   3584: 72 65 73 01 02 05 04 09 1a 84 80 80 80 80 0f 03   res.............
|   3600: 00 3a 00 00 00 15 04 33 74 65 72 01 02 04 02 02   .:.....3ter.....
|   3616: 68 65 01 06 01 01 03 04 08 1b 84 80 80 80 80 0e   he..............
|   3632: 03 00 3c 00 00 00 16 04 33 70 72 65 01 02 05 01   ..<.....3pre....
|   3648: 03 74 61 62 01 06 01 01 05 04 08 1a 84 80 80 80   .tab............
|   3664: 80 0d 03 0d 1a 00 00 00 15 04 33 66 6e 72 01 02   ..........3fnr..
|   3680: 02 02 02 74 73 01 06 01 01 04 04 08 1b 84 80 80   ...ts...........
|   3696: 80 80 0c 03 00 3c 00 00 00 16 03 32 74 68 01 06   .....<.....2th..
|   3712: 01 01 03 00 04 33 65 61 63 01 02 03 04 09 18 84   .....3eac.......
|   3728: 80 80 80 80 0b 03 00 36 00 00 00 13 03 32 74 61   .......6.....2ta
|   3744: 01 06 01 01 05 02 01 65 01 02 04 04 09 19 84 80   .......e........
|   3760: 80 80 80 0a 03 00 38 00 00 00 14 03 30 c9 6e 01   ......8.....0.n.
|   3776: 06 01 01 02 01 02 70 72 01 02 05 04 09 18 84 80   ......pr........
|   3792: 80 80 80 09 03 00 36 00 00 00 13 03 32 66 6f 01   ......6.....2fo.
|   3808: 02 0b e2 01 74 01 06 01 01 04 04 07 1b 84 80 80   ....t...........
|   3824: 86 f0 08 03 00 3c 00 00 00 16 02 31 74 01 0a 04   .....<.....1t...
|   3840: 01 01 03 04 00 03 32 65 61 01 02 03 04 0a 17 84   ......2ea.......
|   3856: 80 80 80 80 07 03 00 34 00 00 00 12 02 31 69 01   .......4.....1i.
|   3872: 06 01 01 02 01 01 70 01 02 05 04 08 18 84 80 80   ......p.........
|   3888: 80 80 06 03 00 36 00 00 00 13 02 31 65 01 02 03   .....6.....1e...
|   3904: 01 01 66 01 08 02 01 01 04 04 06 1b 84 80 80 80   ..f.............
|   3920: 80 05 03 00 3c 00 00 00 16 05 30 74 65 72 6d 01   ....<.....0term.
|   3936: 02 04 02 02 68 65 01 06 01 01 03 04 09 14 84 80   ....he..........
|   3952: 80 80 80 04 03 00 2e 00 00 00 10 06 30 74 61 62   ............0tab
|   3968: 6c 65 01 06 01 01 05 04 15 84 7f 80 80 80 03 03   le..............
|   3984: 00 30 00 00 00 11 02 08 30 70 72 65 73 65 6e 74   .0......0present
|   4000: 01 02 05 05 1b 84 80 22 80 80 02 03 00 3c 00 00   .............<..
|   4016: 00 16 04 30 66 74 73 01 06 01 01 04 01 02 69 6e   ...0fts.......in
|   4032: 01 06 01 01 04 0a 1a 84 80 80 80 80 01 03 00 3a   ...............:
|   4048: 00 00 00 15 05 30 65 61 63 68 01 02 03 01 03 66   .....0each.....f
|   4064: 6f 72 01 02 02 04 09 06 01 03 00 12 03 0b 0f 00   or..............
|   4080: 00 08 8c 80 80 80 80 11 03 00 16 00 00 00 05 04   ................
| page 3 offset 8192
|      0: 0a 00 00 00 32 0e 4f 00 0f fa 0f f1 0f e9 0f e1   ....2.O.........
|     16: 0f d8 0f d1 0f c9 0f c1 0f b9 0f b1 0f a9 0f a0   ................
|     32: 0f 98 0f 90 0f 87 0f 80 0f 78 0f 71 0f 68 0f 5f   .........x.q.h._
|     48: 0f 56 0f 00 00 00 00 00 00 00 00 00 00 00 00 00   .V..............
|   3392: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08   ................
|   3408: 04 01 10 01 03 34 74 20 07 04 01 0e 01 03 34 1e   .....4t ......4.
|   3424: 09 04 01 12 01 03 33 74 68 1c 08 04 01 10 01 03   ......3th.......
|   3440: 34 6e 1a 08 04 01 10 01 03 32 67 18 08 04 01 10   4n.......2g.....
|   3456: 01 03 32 74 16 08 04 01 10 01 03 32 6e 14 07 04   ..2t.......2n...
|   3472: 01 0e 01 03 32 12 08 04 01 10 01 03 31 74 10 08   ....2.......1t..
|   3488: 04 01 10 01 03 31 6e 0e 07 04 01 0e 01 03 31 0c   .....1n.......1.
|   3504: 09 04 01 12 01 03 30 74 68 0a 08 04 01 10 01 03   ......0th.......
|   3520: 30 74 08 09 04 01 12 01 03 30 6e 75 06 08 04 01   0t.......0nu....
|   3536: 10 01 03 30 6e 04 06 04 01 0c 01 03 02 08 04 01   ...0n...........
|   3552: 10 01 02 34 72 22 07 04 01 0e 01 02 34 20 08 04   ...4r.......4 ..
|   3568: 01 10 01 02 33 72 1e 09 04 01 12 01 02 33 61 72   ....3r.......3ar
|   3584: 1c 18 04 01 10 01 02 32 74 1a 08 04 01 10 01 02   .......2t.......
|   3600: 32 69 18 09 04 01 12 01 02 32 61 72 16 08 04 01   2i.......2ar....
|   3616: 10 01 02 31 74 2a 08 04 01 0f 01 02 31 6e 12 0a   ...1t*......1n..
|   3632: d4 01 10 01 02 31 62 10 08 04 01 10 01 02 31 32   .....1b.......12
|   3648: 0e 0b 04 01 16 01 02 30 74 68 65 72 0c 08 04 01   .......0ther....
|   3664: 10 01 02 30 74 0a 08 04 01 10 01 02 30 6e 08 08   ...0t.......0n..
|   3680: 04 01 10 01 02 30 62 06 08 04 01 10 01 02 30 61   .....0b.......0a
|   3696: 04 06 03 f1 0c 01 02 02 07 04 09 10 01 34 74 22   .............4t.
|   3712: 06 04 09 0e 01 34 20 08 04 09 12 01 33 74 65 1e   .....4 .....3te.
|   3728: 07 04 09 10 01 33 70 1c 07 04 09 10 01 33 66 1a   .....3p......3f.
|   3744: 08 04 09 12 01 32 74 68 18 07 04 09 10 01 32 74   .....2th......2t
|   3760: 16 07 04 09 10 01 32 69 14 07 04 09 10 01 32 66   ......2i......2f
|   3776: 12 07 04 09 10 01 31 74 10 07 04 09 10 01 31 69   ......1t......1i
|   3792: 0e 06 04 09 0e 01 31 0c 08 04 09 12 01 30 74 65   ......1......0te
|   3808: 0a 07 04 09 10 01 30 74 08 07 04 09 10 01 30 70   ......0t......0p
|   3824: 06 08 04 09 1e 61 30 66 74 04 05 00 00 00 00 00   .....a0ft.......
| page 4 offset 12288
|   4064: 00 00 00 00 00 00 00 00 00 00 00 05 03 03 00 10   ................
|   4080: 03 05 05 02 03 00 10 04 06 05 01 03 00 10 04 04   ................
| page 5 offset 16384
|      0: 0a 00 00 00 02 0f eb 00 0f eb 0f f4 00 00 00 00   ................
|   4064: 00 00 00 00 00 00 00 00 00 00 00 08 03 15 01 70   ...............p
|   4080: 67 73 7a 18 0b 03 1b 01 76 65 72 73 69 6f 6e 04   gsz.....version.
| end crash-ef6738247b1344.db
}]} {}


do_catchsql_test 4.1 {
  BEGIN;
  REPLACE INTO t1(rowid,b,a,rowid) VALUES(200,1,2,3);
} {1 {database disk image is malformed}}

do_catchsql_test 4.2 {
  INSERT INTO t1(t1) VALUES('delete-all');
} {1 {database disk image is malformed}}
do_catchsql_test 4.3 {
  REPLACE INTO t1(rowid,b,rowid,a) VALUES(200,1,2,3);
} {1 {database disk image is malformed}}
do_catchsql_test 4.4 {
  REPLACE INTO t1(rowid,b,a,rowid) VALUES(0,1,2,3);
} {1 {database disk image is malformed}}
do_catchsql_test 4.5 {
  REPLACE INTO t1(rowid,a,b,rowid) VALUES(200,1,2,3);
} {1 {database disk image is malformed}}

sqlite3_fts5_may_be_corrupt 0
finish_test

Added ext/fts5/test/fts5corrupt6.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2015 Apr 24
#
# 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 tests that FTS5 handles corrupt databases (i.e. internal
# inconsistencies in the backing tables) correctly. In this case 
# "correctly" means without crashing.
#

source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5corrupt6

# If SQLITE_ENABLE_FTS5 is defined, omit this file.
ifcapable !fts5 {
  finish_test
  return
}
sqlite3_fts5_may_be_corrupt 1
database_may_be_corrupt

proc editblock {block} {
  binary format Sa* 20000 [string range $block 2 end]
}
db func editblock editblock

do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE ft USING fts5(abc, def);
  WITH a(i) AS (
    SELECT 1 UNION ALL SELECT i+1 FROM a WHERE i<1000
  )
  INSERT INTO ft SELECT 
      'abc abc abc abc abc abc abc abc abc abc',
      'def def def def def def def def def def'
  FROM a;
  UPDATE ft_data SET block = editblock(block) WHERE id=(
    SELECT id FROM ft_data ORDER BY id LIMIT 1 OFFSET 5
  );
}

do_catchsql_test 1.1 {
  SELECT rowid FROM ft('def') ORDER BY rowid DESC LIMIT 1 OFFSET 9999;
} {1 {database disk image is malformed}}


sqlite3_fts5_may_be_corrupt 0
finish_test

Changes to ext/fts5/test/fts5delete.test.

45
46
47
48
49
50
51
52































































53

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








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

+
do_test 1.2 {
  execsql { INSERT INTO t1(t1, rank) VALUES('usermerge', 2); }
  for {set i 0} {$i < 5} {incr i} {
    execsql { INSERT INTO t1(t1, rank) VALUES('merge', 1) }
    execsql { INSERT INTO t1(t1) VALUES('integrity-check') }
  }
} {}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.0 {
  CREATE TABLE test (
      id INTEGER PRIMARY KEY,
      name TEXT,
      value TEXT
  );
  CREATE VIRTUAL TABLE test_idx USING fts5(
      name, content=test, content_rowid=id
  );
}

do_catchsql_test 2.1 {
  INSERT INTO test_idx (test_idx, rowid, name) VALUES('delete', 1, 'quick');
} {1 {database disk image is malformed}}

do_catchsql_test 2.2 {
  INSERT INTO test_idx(rowid, name) VALUES(123, 'one one one');
  INSERT INTO test_idx (test_idx, rowid, name) VALUES('delete', 123, 'one');
  INSERT INTO test_idx (test_idx, rowid, name) VALUES('delete', 123, 'one');
} {1 {database disk image is malformed}}

do_execsql_test 2.3 {
  DROP TABLE test_idx;
  CREATE VIRTUAL TABLE test_idx USING fts5(
      name, content=test, content_rowid=id
  );

  INSERT INTO test_idx(rowid, name) VALUES(123, 'one one one');
  INSERT INTO test_idx(rowid, name) VALUES(124, 'two two two');
  INSERT INTO test_idx(rowid, name) VALUES(125, 'two two two');
  INSERT INTO test_idx (test_idx, rowid, name) VALUES('delete', 123, 'one');
  INSERT INTO test_idx (test_idx, rowid, name) VALUES('delete', 123, 'one');
  INSERT INTO test_idx (test_idx, rowid, name) VALUES('delete', 123, 'one');
}

do_catchsql_test 2.4 {
  SELECT rowid FROM test_idx WHERE test_idx MATCH 'two' ORDER BY rank;
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 3.0 {
  CREATE VIRTUAL TABLE tx USING fts5(a, b, c, d, content=);
  INSERT INTO tx(rowid, a, c) VALUES(1, 'abc def', 'a b c');
  INSERT INTO tx(rowid, a, c) VALUES(5, 'a b c', 'a b d def');
}
do_execsql_test 3.1 {
  INSERT INTO tx(tx, rowid, a, b, c, d) 
    VALUES('delete', 5, 'a b c', NULL, 'a b d def', NULL);
}
do_execsql_test 3.2 {
  INSERT INTO tx(tx) VALUES('integrity-check');
}
do_execsql_test 3.3 {
  INSERT INTO tx(tx, rowid, a, b, c, d) 
    VALUES('delete', 1, 'abc def', NULL, 'a b c', NULL);
}
do_execsql_test 3.4 {
  INSERT INTO tx(tx) VALUES('integrity-check');
}

finish_test

Changes to ext/fts5/test/fts5detail.test.

208
209
210
211
212
213
214




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







+
+
+
+







  INSERT INTO t4 VALUES('1 2 3', '4 5 6', '7 8 9');
}

do_catchsql_test 4.1 {
  SELECT * FROM t4('a:a')
} {1 {fts5: column queries are not supported (detail=none)}}

do_catchsql_test 4.2 {
  SELECT * FROM t4('a:a &')
} {1 {fts5: syntax error near "&"}}

#-------------------------------------------------------------------------
# Test that for the same content detail=none uses less space than 
# detail=col, and that detail=col uses less space than detail=full
#
reset_db
do_test 5.1 {
  foreach {tbl detail} {t1 none t2 col t3 full} {

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/fts5eb.test.

55
56
57
58
59
60
61
62

63
64
65

















66
67
68
69

70
71
72
73
74
75
76
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







-
+



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



-
+







  do_execsql_test 1.$tn {SELECT fts5_expr($expr)} [list $res]
}

do_catchsql_test 2.1 {
  SELECT fts5_expr()
} {1 {wrong number of arguments to function fts5_expr}}

do_catchsql_test 2.1 {
do_catchsql_test 2.2 {
  SELECT fts5_expr_tcl()
} {1 {wrong number of arguments to function fts5_expr_tcl}}

do_catchsql_test 2.3 {
  SELECT fts5_expr('')
} {1 {fts5: syntax error near ""}}

do_catchsql_test 2.4 {
  SELECT fts5_expr(NULL)
} {1 {fts5: syntax error near ""}}

do_catchsql_test 2.5 {
  SELECT fts5_expr(NULL, NULL)
} {1 {parse error in ""}}

for {set i 0} {$i < 255} {incr i} {
  do_test 2.6.$i {
    lindex [catchsql {sELECT fts5_expr(NULL, char($i));}] 0
  } 1
}

do_execsql_test 3.0 {
  CREATE VIRTUAL TABLE e1 USING fts5(text, tokenize = 'porter unicode61');
  INSERT INTO e1 VALUES ("just a few words with a / inside");
  INSERT INTO e1 VALUES ('just a few words with a / inside');
}
do_execsql_test 3.1 {
  SELECT rowid, bm25(e1) FROM e1 WHERE e1 MATCH '"just"' ORDER BY rank;
} {1 -1e-06}
do_execsql_test 3.2 {
  SELECT rowid FROM e1 WHERE e1 MATCH '"/" OR "just"'
} 1

Changes to ext/fts5/test/fts5fault4.test.

12
13
14
15
16
17
18
19

20
21
22
23




24
25
26
27
28
29
30
12
13
14
15
16
17
18

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







-
+




+
+
+
+







# This file is focused on OOM errors.
#

source [file join [file dirname [info script]] fts5_common.tcl]
source $testdir/malloc_common.tcl
set testprefix fts5fault4

# If SQLITE_ENABLE_FTS3 is defined, omit this file.
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
ifcapable !fts5 {
  finish_test
  return
}

set ::TMPDBERROR [list 1 \
  {unable to open a temporary database file for storing temporary tables}
]

#-------------------------------------------------------------------------
# An OOM while dropping an fts5 table.
#
db func rnddoc fts5_rnddoc 
do_test 1.0 {
  execsql { CREATE VIRTUAL TABLE xx USING fts5(x) }
387
388
389
390
391
392
393
394

395
396
397
391
392
393
394
395
396
397

398
399
400
401







-
+



faultsim_save_and_close
do_faultsim_test 14.1 -faults oom-t* -prep {
  faultsim_restore_and_reopen
  db eval { SELECT * FROM "tbl one" }
} -body {
  db eval { ALTER TABLE "tbl one" RENAME TO "tbl two" }
} -test {
  faultsim_test_result {0 {}}
  faultsim_test_result {0 {}} $::TMPDBERROR
}

finish_test

Changes to ext/fts5/test/fts5faultB.test.

142
143
144
145
146
147
148






















149
150
151
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







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



  INSERT INTO t1 VALUES('b c d a');  -- 4
}
do_faultsim_test 5.1 -faults oom* -body {
  execsql { SELECT rowid FROM t1('^a OR ^b') }
} -test {
  faultsim_test_result {0 {1 4}}
}

#-------------------------------------------------------------------------
# Test OOM injection in a query with two MATCH expressions
#
reset_db
do_execsql_test 6.0 {
  CREATE VIRTUAL TABLE t1 USING fts5(a);
  INSERT INTO t1 VALUES('a b c d');  -- 1
  INSERT INTO t1 VALUES('d a b c');  -- 2
  INSERT INTO t1 VALUES('c d a b');  -- 3
  INSERT INTO t1 VALUES('b c d a');  -- 4
}
do_faultsim_test 6.1 -faults oom* -body {
  execsql { SELECT rowid FROM t1 WHERE t1 MATCH 'a' AND t1 MATCH 'b' }
} -test {
  faultsim_test_result {0 {1 2 3 4}}
}
do_faultsim_test 6.2 -faults oom* -body {
  execsql { SELECT rowid FROM t1 WHERE t1 MATCH 'a OR b' AND t1 MATCH 'c OR d' }
} -test {
  faultsim_test_result {0 {1 2 3 4}}
}


finish_test

Changes to ext/fts5/test/fts5faultD.test.

10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
10
11
12
13
14
15
16

17
18
19
20
21
22
23
24







-
+







#*************************************************************************
#
# This file is focused on OOM errors.
#

source [file join [file dirname [info script]] fts5_common.tcl]
source $testdir/malloc_common.tcl
set testprefix fts5faultA
set testprefix fts5faultD

# If SQLITE_ENABLE_FTS3 is defined, omit this file.
ifcapable !fts5 {
  finish_test
  return
}

Added ext/fts5/test/fts5faultE.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2016 February 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.
#
#*************************************************************************
#
# This file is focused on OOM errors.
#

source [file join [file dirname [info script]] fts5_common.tcl]
source $testdir/malloc_common.tcl
set testprefix fts5faultE

# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
ifcapable !fts5 {
  finish_test
  return
}

faultsim_save_and_close
do_faultsim_test 1 -prep {
  faultsim_restore_and_reopen
} -body {
  execsql { CREATE VIRTUAL TABLE t1 USING fts5(x, y, tokenize=trigram) }
} -test {
  faultsim_test_result {0 {}} {1 {vtable constructor failed: t1}} 
}

reset_db
do_execsql_test 2.0 {
  CREATE VIRTUAL TABLE t1 USING fts5(x, y, tokenize=trigram);
}

faultsim_save_and_close
do_faultsim_test 2 -prep {
  faultsim_restore_and_reopen
} -body {
  execsql { 
    INSERT INTO t1 VALUES('abcdefghijklmnopqrstuvwxyz', NULL);
    SELECT count(*) FROM t1 WHERE x LIKE '%mnop%' AND t1 MATCH 'jkl';
  }
} -test {
  faultsim_test_result {0 1} {1 {vtable constructor failed: t1}}
}

reset_db
do_execsql_test 3.0 {
  CREATE VIRTUAL TABLE t1 USING fts5(x, y, tokenize=trigram, detail=none);
  INSERT INTO t1 VALUES('abcdefghijklmnopqrstuvwxyz', NULL);
}

faultsim_save_and_close
do_faultsim_test 3 -prep {
  faultsim_restore_and_reopen
} -body {
  execsql { 
    SELECT count(*) FROM t1 WHERE x LIKE '%mnopqrs%' AND t1 MATCH 'abc'
  }
} -test {
  faultsim_test_result {0 1} {1 {vtable constructor failed: t1}}
}



finish_test

Changes to ext/fts5/test/fts5full.test.

32
33
34
35
36
37
38
39

40
41
42
32
33
34
35
36
37
38

39
40
41
42







-
+



db func rnddoc fts5_rnddoc
do_test 1.1 {
  list [catch {
    for {set i 0} {$i < 2500} {incr i} {
      execsql { INSERT INTO x8 VALUES( rnddoc(5) ); }
    }
  } msg] $msg
} {1 {database or disk is full}}
} {0 {}}


finish_test

Changes to ext/fts5/test/fts5hash.test.

108
109
110
111
112
113
114
115

116
117
118
119
120
121
122
123
124
125
126
127
128
129
130





































131
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







-
+















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

    INSERT INTO eee(eee) VALUES('integrity-check');
  }

  #-----------------------------------------------------------------------
  # Add a small and very large token with the same hash value to an
  # empty table. At one point this would provoke an asan error.
  #
  do_test 2.0 {
  do_test 1.5 {
    set big [string repeat 12345 40]
    set hash [sqlite3_fts5_token_hash 1024 $big]
    while {1} {
      set small [random_token]
      if {[sqlite3_fts5_token_hash 1024 $small]==$hash} break
    }

    execsql { CREATE VIRTUAL TABLE t2 USING fts5(x, detail=%DETAIL%) }
    execsql {
      INSERT INTO t2 VALUES($small || ' ' || $big);
    }
  } {}

} ;# foreach_detail_mode

#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.1 {
  CREATE VIRTUAL TABLE t1 USING fts5(x);
  INSERT INTO t1(t1, rank) VALUES('hashsize', 1024);
  INSERT INTO t1(t1, rank) VALUES('automerge', 0);
  INSERT INTO t1(t1, rank) VALUES('crisismerge', 1000);
}

do_execsql_test 2.2 {
  BEGIN;
    INSERT INTO t1 VALUES('abc def ghi');
    SELECT count(*) FROM t1_data;
} {2}

do_execsql_test 2.3 {
  WITH s(i) AS (
    SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<1024
  )
  INSERT INTO t1 SELECT 'abc def ghi' FROM s;
  SELECT (SELECT count(*) FROM t1_data) > 10;
} {1}

do_execsql_test 2.4 {
  COMMIT;
  DROP TABLE t1;
  CREATE VIRTUAL TABLE t1 USING fts5(x);
  INSERT INTO t1(t1, rank) VALUES('hashsize', 1024);
  INSERT INTO t1(t1, rank) VALUES('automerge', 0);
  INSERT INTO t1(t1, rank) VALUES('crisismerge', 1000);
  WITH s(i) AS (
    SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<1024
  )
  INSERT INTO t1 SELECT 'abc' || i || ' def' || i || ' ghi' || i FROM s;
  SELECT (SELECT count(*) FROM t1_data) > 100;
} {1}

finish_test

Changes to ext/fts5/test/fts5integrity.test.

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







-
+



-
+

















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

} {
  do_execsql_test 6.$tn.1 {
    DROP TABLE IF EXISTS hh;
    CREATE VIRTUAL TABLE hh USING fts5(y);
    INSERT INTO hh(hh, rank) VALUES('pgsz', $pgsz);

    WITH s(i) AS (SELECT 0 UNION ALL SELECT i+1 FROM s WHERE i<999)
     INSERT INTO hh SELECT printf("%.3d%.3d%.3d %.3d%.3d%.3d",i,i,i,i+1,i+1,i+1)
     INSERT INTO hh SELECT printf('%.3d%.3d%.3d %.3d%.3d%.3d',i,i,i,i+1,i+1,i+1)
     FROM s;

    WITH s(i) AS (SELECT 0 UNION ALL SELECT i+1 FROM s WHERE i<999)
     INSERT INTO hh SELECT printf("%.3d%.3d%.3d %.3d%.3d%.3d",i,i,i,i+1,i+1,i+1)
     INSERT INTO hh SELECT printf('%.3d%.3d%.3d %.3d%.3d%.3d',i,i,i,i+1,i+1,i+1)
     FROM s;

    INSERT INTO hh(hh) VALUES('optimize');
  }

  do_test 6.$tn.2 {
    set ok 0
    for {set i 0} {$i < 1000} {incr i} {
      set T [format %.3d%.3d%.3d $i $i $i]
      set res  [db eval { SELECT rowid FROM hh($T) ORDER BY rowid ASC  }]
      set res2 [db eval { SELECT rowid FROM hh($T) ORDER BY rowid DESC }]
      if {$res == [lsort -integer $res2]} { incr ok }
    }
    set ok
  } {1000}
}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 7.0 {
  PRAGMA encoding = 'UTF-16';
  CREATE VIRTUAL TABLE vt0 USING fts5(c0);
  INSERT INTO vt0 VALUES (x'46f0');
  SELECT quote(c0) FROM vt0;
} {X'46F0'}
do_execsql_test 7.1 {
  INSERT INTO vt0(vt0) VALUES('integrity-check');
}
do_execsql_test 7.2 {
  INSERT INTO vt0(vt0) VALUES('rebuild');
}
do_execsql_test 7.3 {
  INSERT INTO vt0(vt0) VALUES('integrity-check');
}
do_execsql_test 7.4 {
  UPDATE vt0 SET c0='';
}
do_execsql_test 7.5 {
  INSERT INTO vt0(vt0) VALUES('integrity-check');
}

#-------------------------------------------------------------------------
# Ticket 7a458c2a5f4
#
reset_db
do_execsql_test 8.0 {
  PRAGMA locking_mode = EXCLUSIVE;
  PRAGMA journal_mode = PERSIST;
  CREATE VIRTUAL TABLE vt0 USING fts5(c0);
} {exclusive persist}
do_execsql_test 8.1 {
  PRAGMA data_version
} {1}
do_execsql_test 8.2 {
  INSERT INTO vt0(vt0) VALUES('integrity-check');
  PRAGMA data_version;
} {1}
do_execsql_test 8.1 {
  INSERT INTO vt0(vt0, rank) VALUES('usermerge', 2);
}

#-------------------------------------------------------------------------
# Ticket [771fe617]
#
reset_db
do_execsql_test 9.0 {
  PRAGMA encoding = 'UTF16';
  CREATE VIRTUAL TABLE vt0 USING fts5(c0);
}

#explain_i { SELECT quote(SUBSTR(x'37', 0)); }
#execsql { PRAGMA vdbe_trace = 1 }
do_execsql_test 9.1.1 {
  SELECT quote(SUBSTR(x'37', 0));
} {X'37'}
do_execsql_test 9.1.2 {
  SELECT quote(x'37');
} {X'37'}

do_execsql_test 9.2 {
  INSERT INTO vt0 VALUES (SUBSTR(x'37', 0));
--  INSERT INTO vt0 VALUES (x'37');
}
do_execsql_test 9.3 {
  INSERT INTO vt0(vt0) VALUES('integrity-check');
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 10.0 {
  CREATE TABLE t1(i INTEGER PRIMARY KEY, a, b);
  CREATE VIRTUAL TABLE vt0 USING fts5(a, b, content=t1);
  INSERT INTO vt0(rowid, a, b) VALUES(1, 'abc', 'def');
}
do_catchsql_test 10.1 {
  INSERT INTO vt0(vt0) VALUES('integrity-check');
} {0 {}}
do_catchsql_test 10.2 {
  INSERT INTO vt0(vt0, rank) VALUES('integrity-check', 0);
} {0 {}}
do_catchsql_test 10.3 {
  INSERT INTO vt0(vt0, rank) VALUES('integrity-check', 1);
} {1 {database disk image is malformed}}
do_catchsql_test 10.3 {
  INSERT INTO t1 VALUES(1, 'abc', 'def');
  INSERT INTO vt0(vt0, rank) VALUES('integrity-check', 1);
} {0 {}}

do_execsql_test 10.4 {
  CREATE VIRTUAL TABLE vt1 USING fts5(a, b, content=);
  INSERT INTO vt1(rowid, a, b) VALUES(1, 'abc', 'def');
}

do_catchsql_test 10.5.1 {
  INSERT INTO vt0(vt0, rank) VALUES('integrity-check', 0);
} {0 {}}
do_catchsql_test 10.5.2 {
  INSERT INTO vt0(vt0, rank) VALUES('integrity-check', 1);
} {0 {}}
do_catchsql_test 10.5.3 {
  INSERT INTO vt0(vt0) VALUES('integrity-check');
} {0 {}}

finish_test

Added ext/fts5/test/fts5interrupt.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019 Jan 4
#
# 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 script is testing the FTS5 module.
#

source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5interrupt

# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
ifcapable !fts5 {
  finish_test
  return
}

do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE t1 USING fts5(a);
  INSERT INTO t1(t1, rank) VALUES('pgsz', 40);
}
db_save_and_close

proc progress_handler {args} {
  incr ::progress_handler_delay -1
  if {$::progress_handler_delay<=0} { return 1 } 
  return 0
}

foreach {tn sql} {
  1 { INSERT INTO t1(rowid, a) VALUES(0, 'z z z z') }
  2 { COMMIT }
} {
  set bDone 0
  for {set i 1} {$bDone==0} {incr i} {
    do_test 1.$tn.$i {
      db_restore_and_reopen
      execsql {
        BEGIN;
          INSERT INTO t1(rowid, a) VALUES(1, 'a b c d');
          INSERT INTO t1(rowid, a) VALUES(2, 'd e f g');
          INSERT INTO t1(rowid, a) VALUES(3, 'h i j k');
          INSERT INTO t1(rowid, a) VALUES(4, 'l m n o');
      }
  
      set ::progress_handler_delay $i
      db progress 1 progress_handler
      set res [catchsql $sql]
      db close
      if {$res=="0 {}"} {
        set bDone 1
      } else {
        if {$res!="1 interrupted"} { error "got: $res" }
      }
      set {} {}
    } {}
  }
}

finish_test

Changes to ext/fts5/test/fts5matchinfo.test.

486
487
488
489
490
491
492





























493
494
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







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


  CREATE VIRTUAL TABLE x1 USING fts5(z);
  INSERT INTO x1 VALUES('a b c a b c a b c');
} {}

do_catchsql_test 14.2 {
  SELECT matchinfo(x1, 'd') FROM x1('a b c');
} {1 {unrecognized matchinfo flag: d}}

#-------------------------------------------------------------------------
# Test using matchinfo() and similar on a non-full-text query
#
do_execsql_test 15.0 {
  CREATE VIRTUAL TABLE t1 USING fts5(x, y);
  INSERT INTO t1 VALUES('a', 'b');
  INSERT INTO t1 VALUES('c', 'd');
}

if {$tcl_platform(byteOrder)=="littleEndian"} {
  set res {X'02000000'}
} else {
  set res {X'00000002'}
}
do_execsql_test 15.1 {
  SELECT quote(matchinfo(t1, 'n')) FROM t1 LIMIT 1;
} $res
do_execsql_test 15.2 {
  DELETE FROM t1_content WHERE rowid=1;
  SELECT quote(matchinfo(t1, 'n')) FROM t1 LIMIT 1;
} $res

fts5_aux_test_functions db
do_execsql_test 15.3 {
  SELECT fts5_test_all(t1) FROM t1 LIMIT 1;
} {
  {columnsize {0 0} columntext {c d} columntotalsize {2 2} poslist {} tokenize {c d} rowcount 2}
}

finish_test

Added ext/fts5/test/fts5misc.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019 September 02
#
# 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 script is testing the FTS5 module.
#

source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5misc

# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
ifcapable !fts5 {
  finish_test
  return
}

do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE t1 USING fts5(a);
}

do_catchsql_test 1.1.1 { 
  SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*'); 
} {1 {unknown special query: }}
do_catchsql_test 1.1.2 {
  SELECT a FROM t1
    WHERE rank = (SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*'));
} {1 {unknown special query: }}

do_catchsql_test 1.2.1 { 
  SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*id'); 
} {0 {{}}}

do_catchsql_test 1.2.2 {
  SELECT a FROM t1
    WHERE rank = (SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*id'));
} {0 {}}

do_catchsql_test 1.3.1 { 
  SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*reads'); 
} {1 {no such cursor: 1}}

do_catchsql_test 1.3.2 {
  SELECT a FROM t1
    WHERE rank = (SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*reads'));
} {1 {no such cursor: 1}}

db close
sqlite3 db test.db

do_catchsql_test 1.3.3 {
  SELECT a FROM t1
    WHERE rank = (SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*reads'));
} {1 {no such cursor: 1}}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.0 {
  CREATE TABLE t0(c0);
  CREATE VIRTUAL TABLE vt0 USING fts5(c0);
}
do_execsql_test 2.1.1 {
  BEGIN TRANSACTION;
  INSERT INTO vt0(c0) VALUES ('xyz');
}
do_execsql_test 2.1.2 {
  ALTER TABLE t0 ADD COLUMN c5;
}
do_execsql_test 2.1.3 {
  INSERT INTO vt0(vt0) VALUES('integrity-check');
}
do_execsql_test 2.1.4 {
  INSERT INTO vt0(c0) VALUES ('abc');
  COMMIT
}
do_execsql_test 2.1.5 {
  INSERT INTO vt0(vt0) VALUES('integrity-check');
}

reset_db
do_execsql_test 2.2.1 {
  CREATE TABLE t0(c0);
  CREATE VIRTUAL TABLE vt0 USING fts5(c0);
  BEGIN TRANSACTION;
  INSERT INTO vt0(c0) VALUES ('xyz');
}

breakpoint
do_execsql_test 2.2.2 {
  ALTER TABLE t0 RENAME TO t1;
}
do_execsql_test 2.2.3 {
  INSERT INTO vt0(vt0) VALUES('integrity-check');
}
do_execsql_test 2.2.4 {
  INSERT INTO vt0(c0) VALUES ('abc');
  COMMIT;
}
do_execsql_test 2.2.5 {
  INSERT INTO vt0(vt0) VALUES('integrity-check');
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 3.0 {
  CREATE VIRTUAL TABLE vt0 USING fts5(a);
  PRAGMA reverse_unordered_selects = true;
  INSERT INTO vt0 VALUES('365062398'), (0), (0);
  INSERT INTO vt0(vt0, rank) VALUES('pgsz', '38');
}
do_execsql_test 3.1 {
  UPDATE vt0 SET a = 399905135; -- unexpected: database disk image is malformed
}
do_execsql_test 3.2 {
  INSERT INTO vt0(vt0) VALUES('integrity-check');
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 4.0 {
  CREATE VIRTUAL TABLE vt0 USING fts5(c0);
  INSERT INTO vt0(c0) VALUES ('xyz');
}

do_execsql_test 4.1 {
  BEGIN;
    INSERT INTO vt0(c0) VALUES ('abc');
    INSERT INTO vt0(vt0) VALUES('rebuild');
  COMMIT;
}

do_execsql_test 4.2 {
  INSERT INTO vt0(vt0) VALUES('integrity-check');
}

do_execsql_test 4.3 {
  BEGIN;
    INSERT INTO vt0(vt0) VALUES('rebuild');
    INSERT INTO vt0(vt0) VALUES('rebuild');
  COMMIT;
}

do_execsql_test 4.4 {
  INSERT INTO vt0(vt0) VALUES('integrity-check');
}

#-------------------------------------------------------------------------
# Ticket [81a7f7b9].
#
reset_db
do_execsql_test 5.0 {
  CREATE VIRTUAL TABLE vt0 USING fts5(c0, c1);
  INSERT INTO vt0(vt0, rank) VALUES('pgsz', '65536');
  WITH s(i) AS (
    SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<1236
  )
  INSERT INTO vt0(c0) SELECT '0' FROM s;
} {}

do_execsql_test 5.1 {
  UPDATE vt0 SET c1 = 'T,D&p^y/7#3*v<b<4j7|f';
}

do_execsql_test 5.2 {
  INSERT INTO vt0(vt0) VALUES('integrity-check');
}

do_catchsql_test 5.3 {
  INSERT INTO vt0(vt0, rank) VALUES('pgsz', '65537');
} {1 {SQL logic error}}

#-------------------------------------------------------------------------
# Ticket [d392017c].
#
reset_db
do_execsql_test 6.0 {
  CREATE VIRTUAL TABLE vt0 USING fts5(c0);
  WITH s(i) AS (
    SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<10000
  )
  INSERT INTO vt0(c0) SELECT '0' FROM s;
  INSERT INTO vt0(vt0, rank) VALUES('crisismerge', 2000);
  INSERT INTO vt0(vt0, rank) VALUES('automerge', 0);
} {}

do_execsql_test 6.1 {
  INSERT INTO vt0(vt0) VALUES('rebuild');
}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 7.0 {
  CREATE VIRTUAL TABLE t1 USING fts5(x);
  INSERT INTO t1(rowid, x) VALUES(1, 'hello world');
  INSERT INTO t1(rowid, x) VALUES(2, 'well said');
  INSERT INTO t1(rowid, x) VALUES(3, 'hello said');
  INSERT INTO t1(rowid, x) VALUES(4, 'well world');

  CREATE TABLE t2 (a, b);
  INSERT INTO t2 VALUES(1, 'hello');
  INSERT INTO t2 VALUES(2, 'world');
  INSERT INTO t2 VALUES(3, 'said');
  INSERT INTO t2 VALUES(4, 'hello');
}

do_execsql_test 7.1 {
  SELECT rowid FROM t1 WHERE (rowid, x) IN (SELECT a, b FROM t2); 
}

do_execsql_test 7.2 {
  SELECT rowid FROM t1 WHERE rowid=2 AND t1 = 'hello';
}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 8.0 {
  CREATE VIRTUAL TABLE vt0 USING fts5(c0, tokenize = "ascii", prefix = 1);
  INSERT INTO vt0(c0) VALUES (x'd1');
}

do_execsql_test 8.1 {
  INSERT INTO vt0(vt0) VALUES('integrity-check');
}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 9.0 {
  CREATE VIRTUAL TABLE t1 using FTS5(mailcontent);
  insert into t1(rowid, mailcontent) values
      (-4764623217061966105, 'we are going to upgrade'),
      (8324454597464624651, 'we are going to upgrade');
}

do_execsql_test 9.1 {
  INSERT INTO t1(t1) VALUES('integrity-check');
}

do_execsql_test 9.2 {
  SELECT rowid FROM t1('upgrade');
} {
  -4764623217061966105 8324454597464624651
}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 10.0 {
  CREATE VIRTUAL TABLE vt1 USING fts5(c1, c2, prefix = 1, tokenize = "ascii");
  INSERT INTO vt1 VALUES (x'e4', '䔬');
}

do_execsql_test 10.1 {
  SELECT quote(CAST(c1 AS blob)), quote(CAST(c2 AS blob)) FROM vt1
} {X'E4' X'E494AC'}

do_execsql_test 10.2 {
  INSERT INTO vt1(vt1) VALUES('integrity-check');
}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 11.0 {
  CREATE VIRTUAL TABLE vt0 USING fts5(
      c0, prefix = 71, tokenize = "porter ascii", prefix = 9
  );
} {}
do_execsql_test 11.1 {
  BEGIN;
  INSERT INTO vt0(c0) VALUES (x'e8');
}
do_execsql_test 11.2 {
  INSERT INTO vt0(vt0) VALUES('integrity-check');
}

#-------------------------------------------------------------------------
# Ticket [752fdbf6] 
#
reset_db
do_execsql_test 11.0 {
  PRAGMA encoding = 'UTF-16';
  CREATE VIRTUAL TABLE vt0 USING fts5(c0, c1);
  INSERT INTO vt0(vt0, rank) VALUES('pgsz', '37');
  INSERT INTO vt0(c0, c1) VALUES (0.66077, 1957391816);
}
do_execsql_test 11.1 {
  INSERT INTO vt0(vt0) VALUES('integrity-check');
}

#-------------------------------------------------------------------------
# Ticket [7c0e06b16] 
#
do_execsql_test 12.0 {
  CREATE TABLE t1(a, b, rank);
  INSERT INTO t1 VALUES('a', 'hello', '');
  INSERT INTO t1 VALUES('b', 'world', '');

  CREATE VIRTUAL TABLE ft USING fts5(a);
  INSERT INTO ft VALUES('b');
  INSERT INTO ft VALUES('y');

  CREATE TABLE t2(x, y, ft);
  INSERT INTO t2 VALUES(1, 2, 'x');
  INSERT INTO t2 VALUES(3, 4, 'b');
}

do_execsql_test 12.1 {
  SELECT * FROM t1 NATURAL JOIN ft WHERE ft MATCH('b')
} {b world {}}
do_execsql_test 12.2 {
  SELECT * FROM ft NATURAL JOIN t1 WHERE ft MATCH('b')
} {b world {}}
do_execsql_test 12.3 {
  SELECT * FROM t2 JOIN ft USING (ft)
} {3 4 b b}

#-------------------------------------------------------------------------
# Forum post https://sqlite.org/forum/forumpost/21127c1160
#
reset_db
sqlite3_db_config db DEFENSIVE 1

do_execsql_test 13.0 {
  CREATE TABLE a (id INTEGER PRIMARY KEY, name TEXT);
  CREATE VIRTUAL TABLE b USING fts5(name);
  CREATE TRIGGER a_trigger AFTER INSERT ON a BEGIN 
    INSERT INTO b (name) VALUES ('foo');
  END;
}

do_test 13.1 {
  set ::STMT [
    sqlite3_prepare db "INSERT INTO a VALUES (1, 'foo') RETURNING id;" -1 dummy
  ]
  sqlite3_step $::STMT
} {SQLITE_ROW}

do_test 13.2 {
  sqlite3_finalize $::STMT
} {SQLITE_OK}

do_test 13.3 {
  sqlite3_errmsg db
} {not an error}

#-------------------------------------------------------------------------
reset_db
db close
sqlite3 db test.db -uri 1

do_execsql_test 14.0 {
  PRAGMA locking_mode=EXCLUSIVE;
  BEGIN;
  ATTACH 'file:/one?vfs=memdb' AS aux1;
  ATTACH 'file:/one?vfs=memdb' AS aux2;
  CREATE VIRTUAL TABLE t1 USING fts5(x);
} {exclusive}
do_catchsql_test 14.1 {
  ANALYZE;
} {1 {database is locked}}
do_catchsql_test 14.2 {
  COMMIT;
} {1 {database is locked}}
do_catchsql_test 14.3 {
  COMMIT;
} {1 {database is locked}}
do_catchsql_test 14.4 {
  ROLLBACK;
} {0 {}}

#-------------------------------------------------------------------------
reset_db
sqlite3 db2 test.db

do_execsql_test 15.0 {
  CREATE TABLE t1(a, b);
  BEGIN;
    SELECT * FROM t1;
}

do_execsql_test -db db2 15.1 {
  BEGIN; 
    CREATE VIRTUAL TABLE x1 USING fts5(y);
}
do_test 15.2 {
  list [catch { db2 eval COMMIT } msg] $msg
} {1 {database is locked}}
do_execsql_test -db db2 15.3 {
  SAVEPOINT one;
} {}
do_execsql_test 15.4 END
do_test 15.4 {
  list [catch { db2 eval COMMIT } msg] $msg
} {0 {}}

#-------------------------------------------------------------------------
reset_db
forcedelete test.db2
sqlite3 db2 test.db
do_execsql_test 16.0 {

  ATTACH 'test.db2' AS aux;
  CREATE TABLE aux.t2(x,y);
  INSERT INTO t2 VALUES(1, 2);
  CREATE VIRTUAL TABLE x1 USING fts5(a);
  BEGIN;
    INSERT INTO x1 VALUES('abc');
    INSERT INTO t2 VALUES(3, 4);
}

do_execsql_test -db db2 16.1 {
  ATTACH 'test.db2' AS aux;
  BEGIN;
    SELECT * FROM t2
} {1 2}

do_catchsql_test 16.2 {
  COMMIT;
} {1 {database is locked}}

do_execsql_test 16.3 {
  INSERT INTO x1 VALUES('def');
}

do_execsql_test -db db2 16.4 { 
  END 
}

do_execsql_test 16.5 {
  COMMIT
}

do_execsql_test -db db2 16.6 {
  SELECT * FROM x1
} {abc def}

finish_test

Added ext/fts5/test/fts5multi.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2014 September 13
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#*************************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is testing the FTS5 module.
#

source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5multi

# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
ifcapable !fts5 {
  finish_test
  return
}

fts5_aux_test_functions db

do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE t1 USING fts5(a, b, c);
  INSERT INTO t1 VALUES('gg bb bb'   ,'gg ff gg'   ,'ii ii');
  INSERT INTO t1 VALUES('dd dd hh kk','jj'         ,'aa');
  INSERT INTO t1 VALUES('kk gg ee'   ,'hh cc'      ,'hh jj aa cc');
  INSERT INTO t1 VALUES('hh'         ,'bb jj cc'   ,'kk ii');
  INSERT INTO t1 VALUES('kk dd kk ii','aa ee aa'   ,'ee');
  INSERT INTO t1 VALUES('ee'         ,'ff gg kk aa','ee ff ee');
  INSERT INTO t1 VALUES('ff jj'      ,'gg ee'      ,'kk ee gg kk');
  INSERT INTO t1 VALUES('ff ee dd hh','kk ee'      ,'gg dd');
  INSERT INTO t1 VALUES('bb'         ,'aa'         ,'bb aa');
  INSERT INTO t1 VALUES('hh cc bb'   ,'ff bb'      ,'cc');
  INSERT INTO t1 VALUES('jj'         ,'ff dd bb aa','dd dd ff ff');
  INSERT INTO t1 VALUES('ff dd gg dd','gg aa bb ff','cc');
  INSERT INTO t1 VALUES('ff aa cc jj','kk'         ,'ii dd');
  INSERT INTO t1 VALUES('jj dd'      ,'cc'         ,'ii hh ee aa');
  INSERT INTO t1 VALUES('ff ii hh'   ,'dd'         ,'gg');
  INSERT INTO t1 VALUES('ff dd gg hh','hh'         ,'ff dd');
  INSERT INTO t1 VALUES('cc cc'      ,'ff dd ff'   ,'bb');
  INSERT INTO t1 VALUES('ii'         ,'bb ii'      ,'jj kk');
  INSERT INTO t1 VALUES('ff hh'      ,'hh bb'      ,'bb dd ee');
  INSERT INTO t1 VALUES('jj kk'      ,'jj'         ,'gg ff cc');
  INSERT INTO t1 VALUES('dd kk'      ,'ii gg'      ,'dd');
  INSERT INTO t1 VALUES('cc'         ,'aa ff'      ,'ii');
  INSERT INTO t1 VALUES('bb ff bb ii','bb kk bb aa','hh ff ii dd');
  INSERT INTO t1 VALUES('aa'         ,'ee bb jj jj','dd');
  INSERT INTO t1 VALUES('kk dd cc'   ,'aa jj'      ,'ee aa ff');
  INSERT INTO t1 VALUES('aa gg aa'   ,'jj'         ,'ii kk hh gg');
  INSERT INTO t1 VALUES('ff hh aa'   ,'jj ii'      ,'hh dd bb jj');
  INSERT INTO t1 VALUES('hh'         ,'aa gg kk'   ,'bb ee');
  INSERT INTO t1 VALUES('bb'         ,'ee'         ,'gg');
  INSERT INTO t1 VALUES('dd kk'      ,'kk bb aa'   ,'ee');
}

foreach {tn c1 e1 c2 e2} {
  1     t1 aa     t1 bb
  2     a  aa     b  bb
  3     a  "aa OR bb OR cc"    b  "jj OR ii OR hh"
  4     t1  "aa AND bb"       t1  "cc"
  5     c   "kk"               b  "aa OR bb OR cc OR dd OR ee"
} {
  if {$c1=="t1"} {
    set lhs "( $e1 )"
  } else {
    set lhs "$c1 : ( $e1 )"
  }
  if {$c2=="t1"} {
    set rhs "( $e2 )"
  } else {
    set rhs "$c2 : ( $e2 )"
  }

  set q1 "t1 MATCH '($lhs) AND ($rhs)'"
  set q2 "$c1 MATCH '$e1' AND $c2 MATCH '$e2'"

  set ret [execsql "SELECT rowid FROM t1 WHERE $q1"]
  set N [llength $ret]
  do_execsql_test 1.$tn.1.($N) "SELECT rowid FROM t1 WHERE $q2" $ret

  set ret [execsql "SELECT fts5_test_poslist(t1) FROM t1 WHERE $q1"]
  do_execsql_test 1.$tn.2.($N) "
    SELECT fts5_test_poslist(t1) FROM t1 WHERE $q2
  " $ret
}

do_catchsql_test 2.1.1 {
  SELECT rowid FROM t1 WHERE t1 MATCH '(NOT' AND t1 MATCH 'aa bb';
} {1 {fts5: syntax error near "NOT"}}
do_catchsql_test 2.1.2 {
  SELECT rowid FROM t1 WHERE t1 MATCH 'aa bb' AND t1 MATCH '(NOT';
} {1 {fts5: syntax error near "NOT"}}

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 65537:
  |--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 65537:
  |--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 2:}
} {SCAN f1 VIRTUAL TABLE INDEX 0:r}

finish_test

Added ext/fts5/test/fts5prefix2.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2020 Dec 3
#
# 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 contains tests focused on prefix indexes.
#

source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5prefix2

# If SQLITE_ENABLE_FTS5 is defined, omit this file.
ifcapable !fts5 {
  finish_test
  return
}

foreach p {3 2 1} {
  reset_db
    do_execsql_test 1.$p.0 "
    CREATE VIRTUAL TABLE t1 USING fts5(xyz, prefix=$p);
  "
  do_execsql_test 1.$p.1 {
    INSERT INTO t1 VALUES
      ('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 f.');
  }

  do_execsql_test 1.$p.2 {
    SELECT highlight(t1, 0, '[', ']') FROM t1('f*');
  } {
    {May you [find] [forgiveness] [for] yourself and [forgive] others.}
    {May you share [freely], never taking more than you give [f].}
  }
}

do_execsql_test 2.0 {
  CREATE VIRTUAL TABLE t2 USING fts5(one, prefix=3);
  INSERT INTO t2 VALUES('top');
  INSERT INTO t2 VALUES('to');
  INSERT INTO t2 VALUES('tommy');
}

do_execsql_test 2.1 {
  SELECT * FROM t2('to*');
} {top to tommy}



finish_test

Changes to ext/fts5/test/fts5rank.test.

157
158
159
160
161
162
163


















164
165
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







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


  )
  INSERT INTO ttt SELECT 'word ' || i FROM s;
}

do_execsql_test 5.1 {
  SELECT rowid FROM ttt('word') WHERE rowid BETWEEN 30 AND 40 ORDER BY rank;
} {30 31 32 33 34 35 36 37 38 39 40}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 6.0 {
  CREATE VIRTUAL TABLE "My.Table" USING fts5(Text);

  INSERT INTO "My.Table" VALUES ('hello this is a test');
  INSERT INTO "My.Table" VALUES ('of trying to order by');
  INSERT INTO "My.Table" VALUES ('rank on an fts5 table');
  INSERT INTO "My.Table" VALUES ('that have periods in');
  INSERT INTO "My.Table" VALUES ('the table names.');
  INSERT INTO "My.Table" VALUES ('table table table');
}
do_execsql_test 6.1 {
  SELECT * FROM "My.Table" WHERE Text MATCH 'table' ORDER BY rank;
} {
  {table table table} {the table names.} {rank on an fts5 table}
}

finish_test

Added ext/fts5/test/fts5savepoint.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019 Dec 26
#
# 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.
#
#***********************************************************************
#

source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5savepoint

# If SQLITE_ENABLE_FTS5 is defined, omit this file.
ifcapable !fts5 {
  finish_test
  return
}

do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE ft USING fts5(c);
  BEGIN;
    SAVEPOINT one;
      INSERT INTO ft VALUES('a');
      SAVEPOINT two;
        INSERT INTO ft VALUES('b');
      RELEASE two;
      SAVEPOINT four;
        INSERT INTO ft VALUES('c');
      RELEASE four;
      SAVEPOINT three;
        INSERT INTO ft VALUES('d');
      ROLLBACK TO three;
  COMMIT;
  SELECT * FROM ft
} {a b c}

reset_db
do_catchsql_test 2.0 {
  CREATE VIRTUAL TABLE ft1 USING fts5(c);
  CREATE VIRTUAL TABLE ft2 USING fts5(c);
  DROP TABLE ft2_idx;
  BEGIN;
      INSERT INTO ft2 VALUES('a');
      INSERT INTO ft1 VALUES('a');
      SAVEPOINT two;
        INSERT INTO ft1 VALUES('b');
  COMMIT;
} {1 {SQL logic error}}

reset_db
ifcapable fts3 {
  do_execsql_test 3.0 {
    CREATE VIRTUAL TABLE vt0 USING fts5(c0);
    CREATE VIRTUAL TABLE vt1 USING fts4(c0);
    INSERT INTO vt1(c0) VALUES(0);
  }

  do_execsql_test 3.1 {
    BEGIN;
      UPDATE vt1 SET c0 = 0;
      INSERT INTO vt1(c0) VALUES (0), (0);
      UPDATE vt0 SET c0 = 0;
      INSERT INTO vt1(c0) VALUES (0);
      UPDATE vt1 SET c0 = 0;
      INSERT INTO vt1(vt1) VALUES('automerge=1');
      UPDATE vt1 SET c0 = 0;
  }

  do_catchsql_test 3.2 {
    DROP TABLE vt1;
  } {1 {SQL logic error}}

  do_execsql_test 3.3 {
    SAVEPOINT x;
      INSERT INTO vt0 VALUES('x');
    COMMIT;
    INSERT INTO vt0(vt0) VALUES('integrity-check');
  }
}

finish_test

Changes to ext/fts5/test/fts5simple.test.

463
464
465
466
467
468
469













470
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483







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

} {11111 11112}
do_execsql_test 21.3 {
  DELETE FROM x1 WHERE rowid=11111;
  INSERT INTO x1(x1) VALUES('integrity-check');
  SELECT rowid FROM x1($doc);
} {11112}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 22.0 {
  CREATE VIRTUAL TABLE x1 USING fts5(x);
  INSERT INTO x1(x) VALUES('a b c');
  INSERT INTO x1(x) VALUES('x y z');
  INSERT INTO x1(x) VALUES('c b a');
  INSERT INTO x1(x) VALUES('z y x');
}

do_catchsql_test 22.1 {SELECT * FROM x1('')}   {1 {fts5: syntax error near ""}}
do_catchsql_test 22.2 {SELECT * FROM x1(NULL)} {1 {fts5: syntax error near ""}}

finish_test

Changes to ext/fts5/test/fts5tok1.test.

106
107
108
109
110
111
112



































113
114
115
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







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



  CREATE VIRTUAL TABLE tX USING fts5tokenize(nosuchtokenizer);
} {1 {vtable constructor failed: tX}}

do_catchsql_test 2.1 {
  CREATE VIRTUAL TABLE t4 USING fts5tokenize;
  SELECT * FROM t4;
} {1 {SQL logic error}}

#-------------------------------------------------------------------------
# Embedded 0x00 characters.
#
reset_db
do_execsql_test 3.1.0 {
  CREATE VIRTUAL TABLE t1 USING fts5(z);
  CREATE VIRTUAL TABLE tt USING fts5vocab(t1, 'instance');
  INSERT INTO t1 VALUES('abc' || char(0) || 'def');
  SELECT * FROM tt;
} { abc 1 z 0 def 1 z 1 }
do_execsql_test 3.1.1 {
  SELECT hex(z) FROM t1;
} {61626300646566}
do_execsql_test 3.1.2 {
  INSERT INTO t1(t1) VALUES('integrity-check');
} {}

do_execsql_test 3.2.0 {
  CREATE VIRTUAL TABLE t2 USING fts5(z, 
      tokenize="unicode61 categories 'L* N* Co Cc'"
  );
  CREATE VIRTUAL TABLE tu USING fts5vocab(t2, 'instance');

  INSERT INTO t2 VALUES('abc' || char(0) || 'def');
  SELECT * FROM tu;
} { abc 1 z 0 def 1 z 1 }

do_execsql_test 3.2.1 {
  SELECT hex(z) FROM t1;
} {61626300646566}

do_execsql_test 3.2.2 {
  INSERT INTO t1(t1) VALUES('integrity-check');
} {}


finish_test

Added ext/fts5/test/fts5trigram.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
189
190
191
192
193
194
195
196
197
198
199
200
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2020 September 30
#
# 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.
#
#*************************************************************************
#
# Tests for the fts5 "trigram" tokenizer.
#

source [file join [file dirname [info script]] fts5_common.tcl]
ifcapable !fts5 { finish_test ; return }
set ::testprefix fts5trigram

do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE t1 USING fts5(y, tokenize=trigram);
  INSERT INTO t1 VALUES('abcdefghijklm');
  INSERT INTO t1 VALUES('กรุงเทพมหานคร');
}

foreach {tn s res} {
  1 abc           "(abc)defghijklm"
  2 defgh         "abc(defgh)ijklm"
  3 abcdefghijklm "(abcdefghijklm)"
  4 กรุ            "(กรุ)งเทพมหานคร"
  5 งเทพมห        "กรุ(งเทพมห)านคร"
  6 กรุงเทพมหานคร  "(กรุงเทพมหานคร)"
  7 Abc           "(abc)defghijklm"
  8 deFgh         "abc(defgh)ijklm"
  9 aBcdefGhijKlm "(abcdefghijklm)"
} {
  do_execsql_test 1.1.$tn {
    SELECT highlight(t1, 0, '(', ')') FROM t1($s)
  } $res
}

do_execsql_test 1.2.0 {
  SELECT fts5_expr('ABCD', 'tokenize=trigram')
} {{"abc" + "bcd"}}

do_execsql_test 1.2.1 {
  SELECT * FROM t1 WHERE y LIKE ? ESCAPE 'a'
}

foreach {tn like res} {
  1 {%cDef%}   1
  2 {cDef%}    {}
  3 {%f%}      1
  4 {%f_h%}    1
  5 {%f_g%}    {}
  6 {abc%klm}  1
  7 {ABCDEFG%} 1
  8 {%รุงเ%}    2
} {
  do_execsql_test 1.3.$tn {
    SELECT rowid FROM t1 WHERE y LIKE $like
  } $res
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.0 {
  CREATE VIRTUAL TABLE t1 USING fts5(y, tokenize="trigram case_sensitive 1");
  INSERT INTO t1 VALUES('abcdefghijklm');
  INSERT INTO t1 VALUES('กรุงเทพมหานคร');
}

foreach {tn s res} {
  1 abc           "(abc)defghijklm"
  2 defgh         "abc(defgh)ijklm"
  3 abcdefghijklm "(abcdefghijklm)"
  4 กรุ            "(กรุ)งเทพมหานคร"
  5 งเทพมห        "กรุ(งเทพมห)านคร"
  6 กรุงเทพมหานคร  "(กรุงเทพมหานคร)"
  7 Abc           ""
  8 deFgh         ""
  9 aBcdefGhijKlm ""
} {
  do_execsql_test 2.1.$tn {
    SELECT highlight(t1, 0, '(', ')') FROM t1($s)
  } $res
}
foreach {tn like res} {
  1 {%cDef%}   1
  2 {cDef%}    {}
  3 {%f%}      1
  4 {%f_h%}    1
  5 {%f_g%}    {}
  6 {abc%klm}  1
  7 {ABCDEFG%} 1
  8 {%รุงเ%}    2
} {
  do_execsql_test 2.2.$tn {
    SELECT rowid FROM t1 WHERE y LIKE $like
  } $res
}
foreach {tn like res} {
  1 {*cdef*}     1
  2 {cdef*}      {}
  3 {*f*}        1
  4 {*f?h*}      1
  5 {*f?g*}      {}
  6 {abc*klm}    1
  7 {abcdefg*}   1
  8 {*รุงเ*}      2
  9 {abc[d]efg*} 1
 10 {abc[]d]efg*} 1
 11 {abc[^]d]efg*} {}
 12 {abc[^]XYZ]efg*} 1
} {
  do_execsql_test 2.3.$tn {
    SELECT rowid FROM t1 WHERE y GLOB $like
  } $res
}

do_execsql_test 2.3.null.1 {
  SELECT rowid FROM t1 WHERE y LIKE NULL
}

#-------------------------------------------------------------------------
reset_db
do_catchsql_test 3.1 {
  CREATE VIRTUAL TABLE ttt USING fts5(c, tokenize="trigram case_sensitive 2");
} {1 {error in tokenizer constructor}}
do_catchsql_test 3.2 {
  CREATE VIRTUAL TABLE ttt USING fts5(c, tokenize="trigram case_sensitive 11");
} {1 {error in tokenizer constructor}}
do_catchsql_test 3.3 {
  CREATE VIRTUAL TABLE ttt USING fts5(c, "tokenize=trigram case_sensitive 1");
} {0 {}}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 4.0 {
  CREATE VIRTUAL TABLE t0 USING fts5(b, tokenize = "trigram");
}
do_execsql_test 4.1 {
  INSERT INTO t0 VALUES (x'000b01');
}
do_execsql_test 4.2 {
  INSERT INTO t0(t0) VALUES('integrity-check');
}

#-------------------------------------------------------------------------
reset_db
foreach_detail_mode $::testprefix {
  foreach {ci} {0 1} {
    reset_db
    do_execsql_test 5.cs=$ci.0.1 "
      CREATE VIRTUAL TABLE t1 USING fts5(
          y, tokenize=\"trigram case_sensitive $ci\", detail=%DETAIL%
      );
    "
    do_execsql_test 5.cs=$ci.0.2 {
      INSERT INTO t1 VALUES('abcdefghijklm');
      INSERT INTO t1 VALUES('กรุงเทพมหานคร');
    }

    foreach {tn like res} {
      1 {%cDef%}   1
      2 {cDef%}    {}
      3 {%f%}      1
      4 {%f_h%}    1
      5 {%f_g%}    {}
      6 {abc%klm}  1
      7 {ABCDEFG%} 1
      8 {%รุงเ%}    2
    } {
      do_execsql_test 5.cs=$ci.1.$tn {
        SELECT rowid FROM t1 WHERE y LIKE $like
      } $res
    }
  }
}

do_execsql_test 6.0 {
  CREATE VIRTUAL TABLE ci0 USING fts5(x, tokenize="trigram");
  CREATE VIRTUAL TABLE ci1 USING fts5(x, tokenize="trigram case_sensitive 1");
}

# LIKE and GLOB both work with case-insensitive tokenizers. Only GLOB works
# with case-sensitive.
do_eqp_test 6.1 {
  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 ci1 VIRTUAL TABLE INDEX 0:}}
do_eqp_test 6.4 {
  SELECT * FROM ci1 WHERE x GLOB ?
} {VIRTUAL TABLE INDEX 0:G0}

finish_test

Added ext/fts5/test/fts5ubsan.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022 August 9
#
# 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 test is focused on edge cases that cause ubsan errors.
#

source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5ubsan

# If SQLITE_ENABLE_FTS5 is defined, omit this file.
ifcapable !fts5 {
  finish_test
  return
}

do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE x1 USING fts5(x);
}

set BIG    9000000000000000000
set SMALL -9000000000000000000

do_execsql_test 1.1 {
  BEGIN;
    INSERT INTO x1 (rowid, x) VALUES($BIG,   'aaa aba acc');
    INSERT INTO x1 (rowid, x) VALUES($SMALL, 'aaa abc acb');
  COMMIT;
}

do_execsql_test 1.2 {
  SELECT rowid, x FROM x1('ab*');
} [list $SMALL {aaa abc acb} $BIG {aaa aba acc}]

do_execsql_test 1.3 {
  SELECT rowid, x FROM x1('ac*');
} [list $SMALL {aaa abc acb} $BIG {aaa aba acc}]

reset_db
do_execsql_test 2.0 {
  CREATE VIRTUAL TABLE x1 USING fts5(x);
}

do_execsql_test 2.1 {
  INSERT INTO x1 (rowid, x) VALUES($BIG,   'aaa aba acc');
  INSERT INTO x1 (rowid, x) VALUES($SMALL, 'aaa abc acb');
}

do_execsql_test 2.2 {
  INSERT INTO x1 (x1) VALUES('optimize');
}

finish_test

Changes to ext/fts5/test/fts5unicode3.test.

17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
17
18
19
20
21
22
23

24
25
26
27
28
29
30
31







-
+







# If SQLITE_ENABLE_FTS5 is defined, omit this file.
ifcapable !fts5 {
  finish_test
  return
}

proc fts3_unicode_path {file} {
  file join [file dirname [info script]] .. .. fts3 unicode $file
  file join .. [file dirname [info script]] .. .. fts3 unicode $file
}

source [fts3_unicode_path parseunicode.tcl]
set testprefix fts5unicode3

set CF [fts3_unicode_path CaseFolding.txt]
set UD [fts3_unicode_path UnicodeData.txt]

Changes to ext/fts5/test/fts5update.test.

110
111
112
113
114
115
116
117









118





























119
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








+
+
+
+
+
+
+
+
+

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

  for {set i 0} {$i < 1000} {incr i} {
    execsql { UPDATE x2 SET x=x WHERE rowid=2 }
  }
} {}
do_execsql_test 2.2.integrity {
  INSERT INTO x2(x2) VALUES('integrity-check');
}

#-------------------------------------------------------------------------
#
do_execsql_test 3.0 {
  CREATE VIRTUAL TABLE x3 USING fts5(x, detail=%DETAIL%);
  INSERT INTO x3 VALUES('one');
  INSERT INTO x3 VALUES('two');
  INSERT INTO x3 VALUES('one');
  INSERT INTO x3 VALUES('two');
  INSERT INTO x3 VALUES('one');
}

do_test 3.1 {
  db eval { SELECT * FROM x3('one') } {
    db eval {
      INSERT INTO x3(x3) VALUES('optimize');
    }
  }
} {}

do_execsql_test 4.0 {
  CREATE VIRTUAL TABLE x4 USING fts5(a, detail=%DETAIL%);
  INSERT INTO x4 VALUES('one two three');
  INSERT INTO x4(rowid, a) VALUES('2', 'one two three');
  INSERT INTO x4(rowid, a) VALUES('3.0', 'one two three');
}
do_catchsql_test 4.1 {
  INSERT INTO x4(rowid, a) VALUES('four', 'one two three');
} {1 {datatype mismatch}}

do_catchsql_test 4.2 {
  UPDATE x4 SET rowid = 'four' WHERE rowid=1;
} {1 {datatype mismatch}}


}

reset_db
do_catchsql_test 4.0 { CREATE VIRTUAL TABLE t1 USING fts5(a,b,c); } {0 {}}
do_catchsql_test 4.1 { DELETE FROM t1 WHERE t1 MATCH 'f*'; } {0 {}}
finish_test

Changes to ext/fts5/test/fts5vocab.test.

75
76
77
78
79
80
81
82
83


84
85
86
87
88
89
90
75
76
77
78
79
80
81


82
83
84
85
86
87
88
89
90







-
-
+
+







} {
  0 term {} 0 {} 0
  1 col {} 0 {} 0
  2 doc {} 0 {} 0
  3 cnt {} 0 {} 0
}

do_execsql_test 1.2.1 { SELECT * FROM v1 } { }
do_execsql_test 1.2.2 { SELECT * FROM v2 } { }
do_execsql_test 1.2.1 { SELECT * FROM v1 } {}
do_execsql_test 1.2.2 { SELECT * FROM v2 } {}

do_execsql_test 1.3 {
  INSERT INTO t1 VALUES('x y z');
  INSERT INTO t1 VALUES('x x x');
}

do_execsql_test 1.4.1 {
475
476
477
478
479
480
481





482

483




































































484
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







+
+
+
+
+
-
+

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

  expr [lsearch $e2 SorterSort]<0
} 1
do_test 9.6 {
  set e2 [db eval { EXPLAIN SELECT * FROM rrr ORDER BY term DESC }]
  expr [lsearch $e2 SorterSort]<0
} 0

#-------------------------------------------------------------------------
do_execsql_test 10.0 {
  CREATE VIRTUAL TABLE ft USING fts5(a, b, c);
  CREATE VIRTUAL TABLE t2 USING fts5vocab('ft','row');
  CREATE VIRTUAL TABLE t3 USING fts5vocab('ft','row');

}

do_execsql_test 10.1 {
  BEGIN;
    INSERT INTO ft(b) VALUES('x y');
}

do_execsql_test 10.2 {
  SELECT t2.term FROM t2;
} {x y}

do_execsql_test 10.3 {
  SELECT t2.term, t3.term FROM t2, t3;
} {x x x y y x y y}

do_execsql_test 10.4 {
  COMMIT;
}

do_execsql_test 10.5 {
  BEGIN;
    INSERT INTO ft(a) VALUES('1 2 3');
    INSERT INTO ft(a) VALUES('4 5 6');
    INSERT INTO ft(a) VALUES('1 2 3');
    INSERT INTO ft(a) VALUES('4 5 6');
    INSERT INTO ft(a) VALUES('1 2 3');
    INSERT INTO ft(a) VALUES('4 5 6');
}

do_test 10.6 {
  set res [list]
  db eval { SELECT rowid FROM ft('4') } x {
    db eval { SELECT * FROM t2 }
    lappend res $x(rowid)
  }
  db eval COMMIT
  set res
} {3 5 7}

do_execsql_test 10.6.1 {
  SELECT * FROM t2 WHERE term<NULL;
}
do_execsql_test 10.6.2 {
  SELECT * FROM t2 WHERE term>NULL;
}
do_execsql_test 10.6.3 {
  SELECT * FROM t2 WHERE term=NULL;
}
do_execsql_test 10.7.1 {
  SELECT * FROM t2 WHERE term<?;
}
do_execsql_test 10.7.2 {
  SELECT * FROM t2 WHERE term>?;
}
do_execsql_test 10.7.3 {
  SELECT * FROM t2 WHERE term=?;
}

# 2020-02-16  Detect recursively define fts5vocab() tables.
# Error found by dbsqlfuzz.
#
reset_db
do_execsql_test 11.100 {
  CREATE VIRTUAL TABLE t3 USING fts5vocab(rowid , 'col');
  CREATE VIRTUAL TABLE rowid USING fts5vocab(rowid , 'instance');
} {}
do_catchsql_test 11.110 {
  SELECT rowid+1,rowid, * FROM t3 WHERE null>rowid ;
} {1 {SQL logic error}}

finish_test

Changes to ext/fts5/test/fts5vocab2.test.

76
77
78
79
80
81
82
83

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

83

84
85
86
87
88
89
90







-
+
-







  four  2 b 0
  three 2 a 0
}

do_execsql_test 1.5 {
  DELETE FROM t1;
  SELECT * FROM v1;
} {
} {}
}

#-------------------------------------------------------------------------
#
do_execsql_test 2.0 {
  DROP TABLE IF EXISTS t1;
  DROP TABLE IF EXISTS v1;

139
140
141
142
143
144
145
146

147
148
149
150
151
152
153
154
138
139
140
141
142
143
144

145

146
147
148
149
150
151
152







-
+
-







  four  2 b {}
  three 2 a {}
}

do_execsql_test 2.5 {
  DELETE FROM t1;
  SELECT * FROM v1;
} {
} {}
}

#-------------------------------------------------------------------------
#
do_execsql_test 3.0 {
  DROP TABLE IF EXISTS t1;
  DROP TABLE IF EXISTS v1;

198
199
200
201
202
203
204
205
206
207

















































































208


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







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

+
+
  four  2 {} {}
  three 2 {} {}
}

do_execsql_test 3.5 {
  DELETE FROM t1;
  SELECT * FROM v1;
} {
}

} {}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 4.0 {
  CREATE VIRTUAL TABLE v1 USING fts5vocab(nosuchtable, col);
}

do_catchsql_test 4.1 {
  SELECT * FROM v1 WHERE term=='nosuchterm';
} {1 {no such fts5 table: main.nosuchtable}}

do_execsql_test 4.2.1 {
  CREATE TABLE nosuchtable(nosuchtable, y, z);
}
do_catchsql_test 4.2.2 {
  SELECT * FROM v1 WHERE term=='nosuchterm';
} {1 {no such fts5 table: main.nosuchtable}}

ifcapable fts3 {
  do_execsql_test 4.3.1 {
    DROP TABLE nosuchtable;
    CREATE VIRTUAL TABLE nosuchtable USING fts3(a, b);
  } {}
  do_catchsql_test 4.3.2 {
    SELECT * FROM v1 WHERE term=='nosuchterm';
  } {1 {no such fts5 table: main.nosuchtable}}
  do_catchsql_test 4.3.3 {
    INSERT INTO nosuchtable VALUES('id', '*id');
    SELECT * FROM v1 WHERE term=='nosuchterm';
  } {1 {no such fts5 table: main.nosuchtable}}
}

#-------------------------------------------------------------------------
# Check that the fts5 table cannot be written while there are vocab 
# cursors open.
reset_db
do_execsql_test 5.0 {
  CREATE VIRTUAL TABLE t1 USING fts5(a);
  CREATE VIRTUAL TABLE v1 USING fts5vocab(t1, instance);
  INSERT INTO t1 VALUES('one'), ('two'), ('three'), ('four');
}

do_test 5.1 {
  list [catch {
    db eval { SELECT * FROM v1 } {
      db eval {INSERT INTO t1 VALUES('five')}
    }
  } msg] $msg
} {1 {query aborted}}

do_execsql_test 5.2 {
  SELECT * FROM t1
} {one two three four five}

#-------------------------------------------------------------------------
# Check that the fts5 table cannot be written while there are vocab 
# cursors open.
reset_db
do_execsql_test 5.0 {
  CREATE VIRTUAL TABLE t1 USING fts5(a);
  CREATE VIRTUAL TABLE v1 USING fts5vocab(t1, instance);
  WITH s(i) AS (
    VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<10000
  )
  INSERT INTO t1 SELECT 
    'State Emergency Service (SES), Rural Fire Service (RFS) and Volunteers'
  FROM s;
}

do_catchsql_test 5.1 {
  INSERT INTO t1 SELECT rowid FROM v1
} {1 {query aborted}}

do_catchsql_test 5.2 {
  DELETE FROM t1 WHERE rowid>100;
  INSERT INTO t1 SELECT randomblob(3000) FROM v1
} {1 {query aborted}}


finish_test


Changes to ext/fts5/tool/fts5txt2db.tcl.

8
9
10
11
12
13
14

15
16
17
18
19
20
21
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22







+







#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
proc process_cmdline {} { 
  cmdline::process ::A $::argv {
    {fts5                 "use fts5 (this is the default)"}
    {fts4                 "use fts4"}
    {trigram              "Use tokenize=trigram"}
    {colsize   "10 10 10" "list of column sizes"}
    {tblname   "t1"       "table name to create"}
    {detail    "full"     "Fts5 detail mode to use"}
    {repeat    1          "Load each file this many times"}
    {prefix    ""         "Fts prefix= option"}
    {trans     1          "True to use a transaction"}
    database
171
172
173
174
175
176
177

178
179
180
181
182
183
184
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186







+








  set nCol [llength $A(colsize)]
  set cols [lrange $cols 0 [expr $nCol-1]]

  set sql    "CREATE VIRTUAL TABLE IF NOT EXISTS $A(tblname) USING $A(fts) ("
  append sql [join $cols ,]
  if {$A(fts)=="fts5"} { append sql ",detail=$A(detail)" }
  if {$A(trigram)} { append sql ",tokenize=trigram" }
  append sql ", prefix='$A(prefix)');"

  db eval $sql
  return $cols
}

# Return a list of tokens from the named file.

Changes to ext/fts5/tool/mkfts5c.tcl.

56
57
58
59
60
61
62

63

64
65
66
67
68
69
70
56
57
58
59
60
61
62
63

64
65
66
67
68
69
70
71







+
-
+







#
proc fts5_source_id {zDir} {
  set top [file dirname [file dirname $zDir]]
  set uuid [string trim [readfile [file join $top manifest.uuid]]]

  set L [split [readfile [file join $top manifest]]] 
  set date [lindex $L [expr [lsearch -exact $L D]+1]]
  set idx [expr {[string last . $date]-1}]
  set date [string range $date 0 [string last . $date]-1]
  set date [string range $date 0 $idx]
  set date [string map {T { }} $date]

  return "fts5: $date $uuid"
}

proc fts5c_init {zOut} {
  global G

Changes to ext/icu/README.txt.

112
113
114
115
116
117
118

119

120
121
122
123
124
125
126
112
113
114
115
116
117
118
119

120
121
122
123
124
125
126
127







+
-
+








2  COMPILATION AND USAGE

  The easiest way to compile and use the ICU extension is to build
  and use it as a dynamically loadable SQLite extension. To do this
  using gcc on *nix:

    gcc -fPIC -shared icu.c `pkg-config --libs --cflags icu-uc icu-io` \
    gcc -shared icu.c `icu-config --ldflags` -o libSqliteIcu.so
        -o libSqliteIcu.so

  You may need to add "-I" flags so that gcc can find sqlite3ext.h
  and sqlite3.h. The resulting shared lib, libSqliteIcu.so, may be
  loaded into sqlite in the same way as any other dynamically loadable
  extension.


148
149
150
151
152
153
154
155

156
157
158
159
160
161

162
163
164
165

166
167
168

169
149
150
151
152
153
154
155

156
157
158
159
160
161

162




163



164








-
+





-
+
-
-
-
-
+
-
-
-
+
-
    problem and uses the same solution. However, since the ICU extension
    code does not include the SQLite file "limits.h", modifying
    the default value therein does not affect the ICU extension.
    The default value of SQLITE_MAX_LIKE_PATTERN_LENGTH used by
    the ICU extension LIKE operator is 50000, defined in source 
    file "icu.c".

  3.3 Collation Sequence Security Issue
  3.3 Collation Sequence Security

    Internally, SQLite assumes that indices stored in database files
    are sorted according to the collation sequence indicated by the
    SQL schema. Changing the definition of a collation sequence after
    an index has been built is therefore equivalent to database
    corruption. The SQLite library is not very well tested under
    corruption. The SQLite library is well tested for robustness in
    these conditions, and may contain potential buffer overruns
    or other programming errors that could be exploited by a malicious
    programmer.

    the fact of database corruption.  Database corruption may well
    If the ICU extension is used in an environment where potentially
    malicious users may execute arbitrary SQL (i.e. gears), they
    should be prevented from invoking the icu_load_collation() function,
    lead to incorrect answers, but should not cause memory errors.
    possibly using the authorisation callback.

Changes to ext/icu/icu.c.

139
140
141
142
143
144
145
146

147
148
149
150
151
152
153
139
140
141
142
143
144
145

146
147
148
149
150
151
152
153







-
+







    /* There are now 4 possibilities:
    **
    **     1. uPattern is an unescaped match-all character "%",
    **     2. uPattern is an unescaped match-one character "_",
    **     3. uPattern is an unescaped escape character, or
    **     4. uPattern is to be handled as an ordinary character
    */
    if( !prevEscape && uPattern==MATCH_ALL ){
    if( uPattern==MATCH_ALL && !prevEscape && uPattern!=(uint32_t)uEsc ){
      /* Case 1. */
      uint8_t c;

      /* Skip any MATCH_ALL or MATCH_ONE characters that follow a
      ** MATCH_ALL. For each MATCH_ONE, skip one character in the 
      ** test string.
      */
165
166
167
168
169
170
171
172

173
174
175
176
177

178
179
180
181
182
183
184
165
166
167
168
169
170
171

172
173
174
175
176

177
178
179
180
181
182
183
184







-
+




-
+







        if( icuLikeCompare(zPattern, zString, uEsc) ){
          return 1;
        }
        SQLITE_ICU_SKIP_UTF8(zString);
      }
      return 0;

    }else if( !prevEscape && uPattern==MATCH_ONE ){
    }else if( uPattern==MATCH_ONE && !prevEscape && uPattern!=(uint32_t)uEsc ){
      /* Case 2. */
      if( *zString==0 ) return 0;
      SQLITE_ICU_SKIP_UTF8(zString);

    }else if( !prevEscape && uPattern==(uint32_t)uEsc){
    }else if( uPattern==(uint32_t)uEsc && !prevEscape ){
      /* Case 3. */
      prevEscape = 1;

    }else{
      /* Case 4. */
      uint32_t uString;
      SQLITE_ICU_READ_UTF8(zString, uString);
295
296
297
298
299
300
301
302
303



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


302
303
304
305
306
307
308
309
310
311







-
-
+
+
+







    if( !zPattern ){
      return;
    }
    pExpr = uregex_open(zPattern, -1, 0, 0, &status);

    if( U_SUCCESS(status) ){
      sqlite3_set_auxdata(p, 0, pExpr, icuRegexpDelete);
    }else{
      assert(!pExpr);
      pExpr = sqlite3_get_auxdata(p, 0);
    }
    if( !pExpr ){
      icuFunctionError(p, "uregex_open", status);
      return;
    }
  }

  /* Configure the text that the regular expression operates on. */
  uregex_setText(pExpr, zString, -1, &status);
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
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







+



-
+



-
+

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







  }
}

/*
** Register the ICU extension functions with database db.
*/
int sqlite3IcuInit(sqlite3 *db){
# define SQLITEICU_EXTRAFLAGS (SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS)
  static const struct IcuScalar {
    const char *zName;                        /* Function name */
    unsigned char nArg;                       /* Number of arguments */
    unsigned short enc;                       /* Optimal text encoding */
    unsigned int enc;                         /* Optimal text encoding */
    unsigned char iContext;                   /* sqlite3_user_data() context */
    void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
  } scalars[] = {
    {"icu_load_collation",  2, SQLITE_UTF8,                1, icuLoadCollation},
    {"icu_load_collation",2,SQLITE_UTF8|SQLITE_DIRECTONLY,1, icuLoadCollation},
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU)
    {"regexp", 2, SQLITE_ANY|SQLITE_DETERMINISTIC,         0, icuRegexpFunc},
    {"lower",  1, SQLITE_UTF16|SQLITE_DETERMINISTIC,       0, icuCaseFunc16},
    {"lower",  2, SQLITE_UTF16|SQLITE_DETERMINISTIC,       0, icuCaseFunc16},
    {"upper",  1, SQLITE_UTF16|SQLITE_DETERMINISTIC,       1, icuCaseFunc16},
    {"upper",  2, SQLITE_UTF16|SQLITE_DETERMINISTIC,       1, icuCaseFunc16},
    {"lower",  1, SQLITE_UTF8|SQLITE_DETERMINISTIC,        0, icuCaseFunc16},
    {"lower",  2, SQLITE_UTF8|SQLITE_DETERMINISTIC,        0, icuCaseFunc16},
    {"upper",  1, SQLITE_UTF8|SQLITE_DETERMINISTIC,        1, icuCaseFunc16},
    {"upper",  2, SQLITE_UTF8|SQLITE_DETERMINISTIC,        1, icuCaseFunc16},
    {"like",   2, SQLITE_UTF8|SQLITE_DETERMINISTIC,        0, icuLikeFunc},
    {"like",   3, SQLITE_UTF8|SQLITE_DETERMINISTIC,        0, icuLikeFunc},
    {"regexp", 2, SQLITE_ANY|SQLITEICU_EXTRAFLAGS,         0, icuRegexpFunc},
    {"lower",  1, SQLITE_UTF16|SQLITEICU_EXTRAFLAGS,       0, icuCaseFunc16},
    {"lower",  2, SQLITE_UTF16|SQLITEICU_EXTRAFLAGS,       0, icuCaseFunc16},
    {"upper",  1, SQLITE_UTF16|SQLITEICU_EXTRAFLAGS,       1, icuCaseFunc16},
    {"upper",  2, SQLITE_UTF16|SQLITEICU_EXTRAFLAGS,       1, icuCaseFunc16},
    {"lower",  1, SQLITE_UTF8|SQLITEICU_EXTRAFLAGS,        0, icuCaseFunc16},
    {"lower",  2, SQLITE_UTF8|SQLITEICU_EXTRAFLAGS,        0, icuCaseFunc16},
    {"upper",  1, SQLITE_UTF8|SQLITEICU_EXTRAFLAGS,        1, icuCaseFunc16},
    {"upper",  2, SQLITE_UTF8|SQLITEICU_EXTRAFLAGS,        1, icuCaseFunc16},
    {"like",   2, SQLITE_UTF8|SQLITEICU_EXTRAFLAGS,        0, icuLikeFunc},
    {"like",   3, SQLITE_UTF8|SQLITEICU_EXTRAFLAGS,        0, icuLikeFunc},
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU) */
  };
  int rc = SQLITE_OK;
  int i;
  
  for(i=0; rc==SQLITE_OK && i<(int)(sizeof(scalars)/sizeof(scalars[0])); i++){
    const struct IcuScalar *p = &scalars[i];

Changes to ext/icu/sqliteicu.h.

20
21
22
23
24
25
26
27
20
21
22
23
24
25
26








-
#endif  /* __cplusplus */

int sqlite3IcuInit(sqlite3 *db);

#ifdef __cplusplus
}  /* extern "C" */
#endif  /* __cplusplus */

Changes to ext/lsm1/Makefile.

39
40
41
42
43
44
45
46

47
48
49

50
51
52
53
54
55
56
39
40
41
42
43
44
45

46
47
48

49
50
51
52
53
54
55
56







-
+


-
+







             $(LSMDIR)/lsm-test/lsmtest_main.c $(LSMDIR)/lsm-test/lsmtest_mem.c \
             $(LSMDIR)/lsm-test/lsmtest_tdb.c $(LSMDIR)/lsm-test/lsmtest_tdb3.c \
             $(LSMDIR)/lsm-test/lsmtest_util.c $(LSMDIR)/lsm-test/lsmtest_win32.c


# all: lsm.so

LSMOPTS += -DLSM_MUTEX_PTHREADS=1 -I$(LSMDIR) -DHAVE_ZLIB
LSMOPTS += -fPIC -DLSM_MUTEX_PTHREADS=1 -I$(LSMDIR) -DHAVE_ZLIB

lsm.so:	$(LSMOBJ)
	$(TCCX) -shared -o lsm.so $(LSMOBJ)
	$(TCCX) -shared -fPIC -o lsm.so $(LSMOBJ)

%.o:	$(LSMDIR)/%.c $(LSMHDR) sqlite3.h
	$(TCCX) $(LSMOPTS) -c $<
	
lsmtest$(EXE): $(LSMOBJ) $(LSMTESTSRC) $(LSMTESTHDR) sqlite3.o
	# $(TCPPX) -c $(TOP)/lsm-test/lsmtest_tdb2.cc
	$(TCCX) $(LSMOPTS) $(LSMTESTSRC) $(LSMOBJ) sqlite3.o -o lsmtest$(EXE) $(THREADLIB) -lz

Changes to ext/lsm1/lsm-test/lsmtest1.c.

650
651
652
653
654
655
656
657
658
650
651
652
653
654
655
656









-
-
    char *zName = getName3(zSystem, &aTest[i]);
    if( testCaseBegin(pRc, zPattern, "%s", zName) ){
      doDataTest3(zSystem, &aTest[i], pRc);
    }
    testFree(zName);
  }
}


Changes to ext/lsm1/lsm-test/lsmtest8.c.

318
319
320
321
322
323
324
325
326
318
319
320
321
322
323
324









-
-
    if( testCaseBegin(pRc, zPattern, p->zName) ){
      p->xFunc(pRc);
      testCaseFinish(*pRc);
    }
  }

}


Changes to ext/lsm1/lsm-test/lsmtest9.c.

134
135
136
137
138
139
140
141
142
143
134
135
136
137
138
139
140










-
-
-
    char *zName = getName4(zSystem, &aTest[i]);
    if( testCaseBegin(pRc, zPattern, "%s", zName) ){
      doDataTest4(zSystem, &aTest[i], pRc);
    }
    testFree(zName);
  }
}



Changes to ext/lsm1/lsm-test/lsmtest_bt.c.

65
66
67
68
69
70
71
72
73
74
75
65
66
67
68
69
70
71











-
-
-
-
    return -4;
  }

  printf("%s\n", (char*)buf.output.p);
  sqlite4_buffer_clear(&buf.output);
  return 0;
}




Changes to ext/lsm1/lsm-test/lsmtest_tdb.c.

549
550
551
552
553
554
555
556

557
558
559
560
561
562
563
549
550
551
552
553
554
555

556
557
558
559
560
561
562
563







-
+








  /* iLevel==0 is a no-op */
  if( iLevel==0 ) return 0;

  /* If there are no transactions at all open, open a read transaction. */
  if( pDb->nOpenTrans==0 ){
    int rc = sqlite3_exec(pDb->db, 
        "BEGIN; SELECT * FROM sqlite_master LIMIT 1;" , 0, 0, 0
        "BEGIN; SELECT * FROM sqlite_schema LIMIT 1;" , 0, 0, 0
    );
    if( rc!=0 ) return rc;
    pDb->nOpenTrans = 1;
  }

  /* Open any required write transactions */
  for(i=pDb->nOpenTrans; i<iLevel; i++){

Changes to ext/lsm1/lsm-test/lsmtest_tdb2.cc.

363
364
365
366
367
368
369
370
363
364
365
366
367
368
369








-
    }
  }

  return rc;
}

#endif /* HAVE_MDB */

Changes to ext/lsm1/lsm-test/lsmtest_tdb4.c.

974
975
976
977
978
979
980
981
982
974
975
976
977
978
979
980









-
-
  }
  return rc;
}

/*
** End of background checkpointer.
*************************************************************************/


Changes to ext/lsm1/lsmInt.h.

40
41
42
43
44
45
46


47
48
49
50
51
52
53
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55







+
+







# endif
#else
# ifndef LSM_DEBUG
#  define LSM_DEBUG
# endif
#endif

/* #define LSM_DEBUG_EXPENSIVE 1 */

/*
** Default values for various data structure parameters. These may be
** overridden by calls to lsm_config().
*/
#define LSM_DFLT_PAGE_SIZE          (4 * 1024)
#define LSM_DFLT_BLOCK_SIZE         (1 * 1024 * 1024)
#define LSM_DFLT_AUTOFLUSH          (1 * 1024 * 1024)
401
402
403
404
405
406
407
408

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

410
411
412
413
414
415
416
417







-
+







  u32 aSnapshot[LSM_META_PAGE_SIZE / sizeof(u32)];
};

struct Segment {
  LsmPgno iFirst;                  /* First page of this run */
  LsmPgno iLastPg;                 /* Last page of this run */
  LsmPgno iRoot;                   /* Root page number (if any) */
  int nSize;                       /* Size of this run in pages */
  LsmPgno nSize;                   /* Size of this run in pages */

  Redirect *pRedirect;             /* Block redirects (or NULL) */
};

/*
** iSplitTopic/pSplitKey/nSplitKey:
**   If nRight>0, this buffer contains a copy of the largest key that has
848
849
850
851
852
853
854


855
856
857
858
859
860
861
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865







+
+







/*
** Functions from "lsm_varint.c".
*/
int lsmVarintPut32(u8 *, int);
int lsmVarintGet32(u8 *, int *);
int lsmVarintPut64(u8 *aData, i64 iVal);
int lsmVarintGet64(const u8 *aData, i64 *piVal);

int lsmVarintLen64(i64);

int lsmVarintLen32(int);
int lsmVarintSize(u8 c);

/* 
** Functions from file "main.c".
*/

Changes to ext/lsm1/lsm_ckpt.c.

507
508
509
510
511
512
513
514

515
516
517
518
519
520
521
507
508
509
510
511
512
513

514
515
516
517
518
519
520
521







-
+







  Segment *pSegment               /* Populate this structure */
){
  assert( pSegment->iFirst==0 && pSegment->iLastPg==0 );
  assert( pSegment->nSize==0 && pSegment->iRoot==0 );
  pSegment->iFirst = ckptGobble64(aIn, piIn);
  pSegment->iLastPg = ckptGobble64(aIn, piIn);
  pSegment->iRoot = ckptGobble64(aIn, piIn);
  pSegment->nSize = (int)ckptGobble64(aIn, piIn);
  pSegment->nSize = ckptGobble64(aIn, piIn);
  assert( pSegment->iFirst );
}

static int ckptSetupMerge(lsm_db *pDb, u32 *aInt, int *piIn, Level *pLevel){
  Merge *pMerge;                  /* Allocated Merge object */
  int nInput;                     /* Number of input segments in merge */
  int iIn = *piIn;                /* Next value to read from aInt[] */

Changes to ext/lsm1/lsm_file.c.

211
212
213
214
215
216
217
218
219


220
221
222
223
224
225
226
211
212
213
214
215
216
217


218
219
220
221
222
223
224
225
226







-
-
+
+







struct FileSystem {
  lsm_db *pDb;                    /* Database handle that owns this object */
  lsm_env *pEnv;                  /* Environment pointer */
  char *zDb;                      /* Database file name */
  char *zLog;                     /* Database file name */
  int nMetasize;                  /* Size of meta pages in bytes */
  int nMetaRwSize;                /* Read/written size of meta pages in bytes */
  int nPagesize;                  /* Database page-size in bytes */
  int nBlocksize;                 /* Database block-size in bytes */
  i64 nPagesize;                  /* Database page-size in bytes */
  i64 nBlocksize;                 /* Database block-size in bytes */

  /* r/w file descriptors for both files. */
  LsmFile *pLsmFile;              /* Used after lsm_close() to link into list */
  lsm_file *fdDb;                 /* Database file */
  lsm_file *fdLog;                /* Log file */
  int szSector;                   /* Database file sector size */

885
886
887
888
889
890
891
892

893
894
895
896
897
898
899
885
886
887
888
889
890
891

892
893
894
895
896
897
898
899







-
+







  if( pFS->pCompress ){
    if( iBlock==1 ){
      iPg = pFS->nMetasize * 2 + 4;
    }else{
      iPg = pFS->nBlocksize * (LsmPgno)(iBlock-1) + 4;
    }
  }else{
    const int nPagePerBlock = (pFS->nBlocksize / pFS->nPagesize);
    const i64 nPagePerBlock = (pFS->nBlocksize / pFS->nPagesize);
    if( iBlock==1 ){
      iPg = 1 + ((pFS->nMetasize*2 + pFS->nPagesize - 1) / pFS->nPagesize);
    }else{
      iPg = 1 + (iBlock-1) * nPagePerBlock;
    }
  }
  return iPg;
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1127
1128
1129
1130
1131
1132
1133

1134
1135
1136
1137
1138
1139
1140







-







** This function is never called in compressed database mode.
*/
static void fsGrowMapping(
  FileSystem *pFS,                /* File system object */
  i64 iSz,                        /* Minimum size to extend mapping to */
  int *pRc                        /* IN/OUT: Error code */
){
  assert( pFS->pCompress==0 );
  assert( PAGE_HASPREV==4 );

  if( *pRc==LSM_OK && iSz>pFS->nMap ){
    int rc;
    u8 *aOld = pFS->pMap;
    rc = lsmEnvRemap(pFS->pEnv, pFS->fdDb, iSz, &pFS->pMap, &pFS->nMap);
    if( rc==LSM_OK && pFS->pMap!=aOld ){
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
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







-
+










-
+





-
+







  int iBlk;

  assert( pRun->nSize>0 );
  assert( 0==fsSegmentRedirects(pFS, pRun) );
  assert( nPgno>0 && 0==fsPageRedirects(pFS, pRun, aPgno[0]) );

  iBlk = fsPageToBlock(pFS, pRun->iFirst);
  pRun->nSize += (int)(pRun->iFirst - fsFirstPageOnBlock(pFS, iBlk));
  pRun->nSize += (pRun->iFirst - fsFirstPageOnBlock(pFS, iBlk));

  while( rc==LSM_OK ){
    int iNext = 0;
    LsmPgno iFirst = firstOnBlock(pFS, iBlk, aPgno, nPgno);
    if( iFirst ){
      pRun->iFirst = iFirst;
      break;
    }
    rc = fsBlockNext(pFS, pRun, iBlk, &iNext);
    if( rc==LSM_OK ) rc = fsFreeBlock(pFS, pSnapshot, pRun, iBlk);
    pRun->nSize -= (int)(
    pRun->nSize -= (
        1 + fsLastPageOnBlock(pFS, iBlk) - fsFirstPageOnBlock(pFS, iBlk)
    );
    iBlk = iNext;
  }

  pRun->nSize -= (int)(pRun->iFirst - fsFirstPageOnBlock(pFS, iBlk));
  pRun->nSize -= (pRun->iFirst - fsFirstPageOnBlock(pFS, iBlk));
  assert( pRun->nSize>0 );
}

/*
** This function is only used in compressed database mode.
**
** Argument iPg is the page number (byte offset) of a page within segment

Changes to ext/lsm1/lsm_main.c.

428
429
430
431
432
433
434
435

436
437
438
439
440
441
442
428
429
430
431
432
433
434

435
436
437
438
439
440
441
442







-
+







  }

  va_end(ap);
  return rc;
}

void lsmAppendSegmentList(LsmString *pStr, char *zPre, Segment *pSeg){
  lsmStringAppendf(pStr, "%s{%d %d %d %d}", zPre, 
  lsmStringAppendf(pStr, "%s{%lld %lld %lld %lld}", zPre, 
        pSeg->iFirst, pSeg->iLastPg, pSeg->iRoot, pSeg->nSize
  );
}

static int infoGetWorker(lsm_db *pDb, Snapshot **pp, int *pbUnlock){
  int rc = LSM_OK;

Changes to ext/lsm1/lsm_shared.c.

1301
1302
1303
1304
1305
1306
1307


















1308
1309
1310
1311
1312
1313
1314
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332







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







      if( rc==LSM_OK ){
        rc = lsmShmCacheChunks(db, 1);
        if( rc==LSM_OK ){
          db->pShmhdr = (ShmHeader *)db->apShm[0];
        }
      }
    }

    /* In 'lsm_open()' we don't update the page and block sizes in the
    ** Filesystem for 'readonly' connection. Because member 'db->pShmhdr' is a
    ** nullpointer, this prevents loading a checkpoint. Now that the system is 
    ** live this member should be set. So we can update both values in 
    ** the Filesystem.
    **
    ** Configure the file-system connection with the page-size and block-size
    ** of this database. Even if the database file is zero bytes in size
    ** on disk, these values have been set in shared-memory by now, and so
    ** are guaranteed not to change during the lifetime of this connection. */
    if( LSM_OK==rc
     && 0==lsmCheckpointClientCacheOk(db)
     && LSM_OK==(rc=lsmCheckpointLoad(db, 0)) 
    ){
      lsmFsSetPageSize(db->pFS, lsmCheckpointPgsz(db->aSnapshot));
      lsmFsSetBlockSize(db->pFS, lsmCheckpointBlksz(db->aSnapshot));
    }

    if( rc==LSM_OK ){
      rc = lsmBeginReadTrans(db);
    }
  }

  return rc;

Changes to ext/lsm1/lsm_sorted.c.

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







-
+











-
+


-
+







  Page *pPg,                      /* Page to read from */
  int iCell,                      /* Index of cell on page to read */
  int *piTopic,                   /* OUT: Topic associated with this key */
  int *pnKey,                     /* OUT: Size of key in bytes */
  LsmBlob *pBlob                  /* If required, use this for dynamic memory */
){
  u8 *pKey;
  int nDummy;
  i64 nDummy;
  int eType;
  u8 *aData;
  int nData;

  aData = fsPageData(pPg, &nData);

  assert( !(pageGetFlags(aData, nData) & SEGMENT_BTREE_FLAG) );
  assert( iCell<pageGetNRec(aData, nData) );

  pKey = pageGetCell(aData, nData, iCell);
  eType = *pKey++;
  pKey += lsmVarintGet32(pKey, &nDummy);
  pKey += lsmVarintGet64(pKey, &nDummy);
  pKey += lsmVarintGet32(pKey, pnKey);
  if( rtIsWrite(eType) ){
    pKey += lsmVarintGet32(pKey, &nDummy);
    pKey += lsmVarintGet64(pKey, &nDummy);
  }
  *piTopic = rtTopic(eType);

  sortedReadData(pSeg, pPg, pKey-aData, *pnKey, (void **)&pKey, pBlob);
  return pKey;
}

653
654
655
656
657
658
659
660

661
662
663
664
665

666
667

668
669
670
671
672
673
674
653
654
655
656
657
658
659

660
661
662
663
664

665
666

667
668
669
670
671
672
673
674







-
+




-
+

-
+







    );
    pCsr->eType |= LSM_SEPARATOR;
  }

  return rc;
}

static int btreeCursorPtr(u8 *aData, int nData, int iCell){
static LsmPgno btreeCursorPtr(u8 *aData, int nData, int iCell){
  int nCell;

  nCell = pageGetNRec(aData, nData);
  if( iCell>=nCell ){
    return (int)pageGetPtr(aData, nData);
    return pageGetPtr(aData, nData);
  }
  return (int)pageGetRecordPtr(aData, nData, iCell);
  return pageGetRecordPtr(aData, nData, iCell);
}

static int btreeCursorNext(BtreeCursor *pCsr){
  int rc = LSM_OK;

  BtreePg *pPg = &pCsr->aPg[pCsr->iPg];
  int nCell; 
747
748
749
750
751
752
753
754

755
756
757
758
759
760
761
747
748
749
750
751
752
753

754
755
756
757
758
759
760
761







-
+







}

static int btreeCursorFirst(BtreeCursor *pCsr){
  int rc;

  Page *pPg = 0;
  FileSystem *pFS = pCsr->pFS;
  int iPg = (int)pCsr->pSeg->iRoot;
  LsmPgno iPg = pCsr->pSeg->iRoot;

  do {
    rc = lsmFsDbPageGet(pFS, pCsr->pSeg, iPg, &pPg);
    assert( (rc==LSM_OK)==(pPg!=0) );
    if( rc==LSM_OK ){
      u8 *aData;
      int nData;
775
776
777
778
779
780
781
782

783
784
785
786
787
788
789
775
776
777
778
779
780
781

782
783
784
785
786
787
788
789







-
+







        }
      }

      if( rc==LSM_OK ){
        assert( pCsr->aPg[pCsr->nDepth].iCell==0 );
        pCsr->aPg[pCsr->nDepth].pPage = pPg;
        pCsr->nDepth++;
        iPg = (int)pageGetRecordPtr(aData, nData, 0);
        iPg = pageGetRecordPtr(aData, nData, 0);
      }
    }
  }while( rc==LSM_OK );
  lsmFsPageRelease(pPg);
  pCsr->iPg = pCsr->nDepth-1;

  if( rc==LSM_OK && pCsr->nDepth ){
867
868
869
870
871
872
873
874

875
876
877
878
879
880
881
867
868
869
870
871
872
873

874
875
876
877
878
879
880
881







-
+







    /* Populate any other aPg[] array entries */
    if( rc==LSM_OK && nDepth>1 ){
      LsmBlob blob = {0,0,0};
      void *pSeek;
      int nSeek;
      int iTopicSeek;
      int iPg = 0;
      int iLoad = (int)pSeg->iRoot;
      LsmPgno iLoad = pSeg->iRoot;
      Page *pPg = pCsr->aPg[nDepth-1].pPage;
 
      if( pageObjGetNRec(pPg)==0 ){
        /* This can happen when pPg is the right-most leaf in the b-tree.
        ** In this case, set the iTopicSeek/pSeek/nSeek key to a value
        ** greater than any real key.  */
        assert( iCell==-1 );
899
900
901
902
903
904
905
906

907
908
909
910
911
912
913
899
900
901
902
903
904
905

906
907
908
909
910
911
912
913







-
+







          int iMin;
          int iMax;
          int iCell2;

          aData = fsPageData(pPg2, &nData);
          assert( (pageGetFlags(aData, nData) & SEGMENT_BTREE_FLAG) );

          iLoad = (int)pageGetPtr(aData, nData);
          iLoad = pageGetPtr(aData, nData);
          iCell2 = pageGetNRec(aData, nData); 
          iMax = iCell2-1;
          iMin = 0;

          while( iMax>=iMin ){
            int iTry = (iMin+iMax)/2;
            void *pKey; int nKey;         /* Key for cell iTry */
922
923
924
925
926
927
928
929

930
931
932
933
934
935
936
922
923
924
925
926
927
928

929
930
931
932
933
934
935
936







-
+








            res = sortedKeyCompare(
                xCmp, iTopicSeek, pSeek, nSeek, iTopic, pKey, nKey
            );
            assert( res!=0 );

            if( res<0 ){
              iLoad = (int)iPtr;
              iLoad = iPtr;
              iCell2 = iTry;
              iMax = iTry-1;
            }else{
              iMin = iTry+1;
            }
          }

1009
1010
1011
1012
1013
1014
1015
1016

1017
1018
1019
1020
1021
1022
1023
1009
1010
1011
1012
1013
1014
1015

1016
1017
1018
1019
1020
1021
1022
1023







-
+








/*
** Load a new page into the SegmentPtr object pPtr.
*/
static int segmentPtrLoadPage(
  FileSystem *pFS,
  SegmentPtr *pPtr,              /* Load page into this SegmentPtr object */
  int iNew                       /* Page number of new page */
  LsmPgno iNew                       /* Page number of new page */
){
  Page *pPg = 0;                 /* The new page */
  int rc;                        /* Return Code */

  rc = lsmFsDbPageGet(pFS, pPtr->pSeg, iNew, &pPg);
  assert( rc==LSM_OK || pPg==0 );
  segmentPtrSetPage(pPtr, pPg);
1629
1630
1631
1632
1633
1634
1635
1636

1637
1638
1639
1640
1641
1642
1643
1629
1630
1631
1632
1633
1634
1635

1636
1637
1638
1639
1640
1641
1642
1643







-
+








static int segmentPtrSeek(
  MultiCursor *pCsr,              /* Cursor context */
  SegmentPtr *pPtr,               /* Pointer to seek */
  int iTopic,                     /* Key topic to seek to */
  void *pKey, int nKey,           /* Key to seek to */
  int eSeek,                      /* Search bias - see above */
  int *piPtr,                     /* OUT: FC pointer */
  LsmPgno *piPtr,                 /* OUT: FC pointer */
  int *pbStop
){
  int (*xCmp)(void *, int, void *, int) = pCsr->pDb->xCmp;
  int res = 0;                        /* Result of comparison operation */
  int rc = LSM_OK;
  int iMin;
  int iMax;
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
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







-
+













-
+



-
+







    ){
      assert( eSeek!=LSM_SEEK_EQ );
      rc = segmentPtrAdvance(pCsr, pPtr, eSeek==LSM_SEEK_LE);
    }
  }

  assert( rc!=LSM_OK || assertSeekResult(pCsr,pPtr,iTopic,pKey,nKey,eSeek) );
  *piPtr = (int)iPtrOut;
  *piPtr = iPtrOut;
  return rc;
}

static int seekInBtree(
  MultiCursor *pCsr,              /* Multi-cursor object */
  Segment *pSeg,                  /* Seek within this segment */
  int iTopic,
  void *pKey, int nKey,           /* Key to seek to */
  LsmPgno *aPg,                   /* OUT: Page numbers */
  Page **ppPg                     /* OUT: Leaf (sorted-run) page reference */
){
  int i = 0;
  int rc;
  int iPg;
  LsmPgno iPg;
  Page *pPg = 0;
  LsmBlob blob = {0, 0, 0};

  iPg = (int)pSeg->iRoot;
  iPg = pSeg->iRoot;
  do {
    LsmPgno *piFirst = 0;
    if( aPg ){
      aPg[i++] = iPg;
      piFirst = &aPg[i];
    }

1795
1796
1797
1798
1799
1800
1801
1802

1803
1804
1805
1806
1807
1808
1809
1795
1796
1797
1798
1799
1800
1801

1802
1803
1804
1805
1806
1807
1808
1809







-
+







      int nRec;
      int flags;

      aData = fsPageData(pPg, &nData);
      flags = pageGetFlags(aData, nData);
      if( (flags & SEGMENT_BTREE_FLAG)==0 ) break;

      iPg = (int)pageGetPtr(aData, nData);
      iPg = pageGetPtr(aData, nData);
      nRec = pageGetNRec(aData, nData);

      iMin = 0;
      iMax = nRec-1;
      while( iMax>=iMin ){
        int iTry = (iMin+iMax)/2;
        void *pKeyT; int nKeyT;       /* Key for cell iTry */
1821
1822
1823
1824
1825
1826
1827
1828

1829
1830
1831
1832
1833
1834
1835
1821
1822
1823
1824
1825
1826
1827

1828
1829
1830
1831
1832
1833
1834
1835







-
+







          i++;
        }

        res = sortedKeyCompare(
            pCsr->pDb->xCmp, iTopic, pKey, nKey, iTopicT, pKeyT, nKeyT
        );
        if( res<0 ){
          iPg = (int)iPtr;
          iPg = iPtr;
          iMax = iTry-1;
        }else{
          iMin = iTry+1;
        }
      }
      lsmFsPageRelease(pPg);
      pPg = 0;
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
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







-
+

-
+


-
+









-
+







}

static int seekInSegment(
  MultiCursor *pCsr, 
  SegmentPtr *pPtr,
  int iTopic,
  void *pKey, int nKey,
  int iPg,                        /* Page to search */
  LsmPgno iPg,                    /* Page to search */
  int eSeek,                      /* Search bias - see above */
  int *piPtr,                     /* OUT: FC pointer */
  LsmPgno *piPtr,                 /* OUT: FC pointer */
  int *pbStop                     /* OUT: Stop search flag */
){
  int iPtr = iPg;
  LsmPgno iPtr = iPg;
  int rc = LSM_OK;

  if( pPtr->pSeg->iRoot ){
    Page *pPg;
    assert( pPtr->pSeg->iRoot!=0 );
    rc = seekInBtree(pCsr, pPtr->pSeg, iTopic, pKey, nKey, 0, &pPg);
    if( rc==LSM_OK ) segmentPtrSetPage(pPtr, pPg);
  }else{
    if( iPtr==0 ){
      iPtr = (int)pPtr->pSeg->iFirst;
      iPtr = pPtr->pSeg->iFirst;
    }
    if( rc==LSM_OK ){
      rc = segmentPtrLoadPage(pCsr->pDb->pFS, pPtr, iPtr);
    }
  }

  if( rc==LSM_OK ){
1900
1901
1902
1903
1904
1905
1906
1907

1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927


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

1943
1944
1945
1946
1947
1948
1949
1900
1901
1902
1903
1904
1905
1906

1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925


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

1942
1943
1944
1945
1946
1947
1948
1949







-
+


















-
-
+
+














-
+







  int iTopic,                     /* Key topic to search for */
  void *pKey, int nKey,           /* Key to search for */
  LsmPgno *piPgno,                /* IN/OUT: fraction cascade pointer (or 0) */
  int *pbStop                     /* OUT: See above */
){
  Level *pLvl = aPtr[0].pLevel;   /* Level to seek within */
  int rc = LSM_OK;                /* Return code */
  int iOut = 0;                   /* Pointer to return to caller */
  LsmPgno iOut = 0;               /* Pointer to return to caller */
  int res = -1;                   /* Result of xCmp(pKey, split) */
  int nRhs = pLvl->nRight;        /* Number of right-hand-side segments */
  int bStop = 0;

  /* If this is a composite level (one currently undergoing an incremental
  ** merge), figure out if the search key is larger or smaller than the
  ** levels split-key.  */
  if( nRhs ){
    res = sortedKeyCompare(pCsr->pDb->xCmp, iTopic, pKey, nKey, 
        pLvl->iSplitTopic, pLvl->pSplitKey, pLvl->nSplitKey
    );
  }

  /* If (res<0), then key pKey/nKey is smaller than the split-key (or this
  ** is not a composite level and there is no split-key). Search the 
  ** left-hand-side of the level in this case.  */
  if( res<0 ){
    int i;
    int iPtr = 0;
    if( nRhs==0 ) iPtr = (int)*piPgno;
    LsmPgno iPtr = 0;
    if( nRhs==0 ) iPtr = *piPgno;

    rc = seekInSegment(
        pCsr, &aPtr[0], iTopic, pKey, nKey, iPtr, eSeek, &iOut, &bStop
    );
    if( rc==LSM_OK && nRhs>0 && eSeek==LSM_SEEK_GE && aPtr[0].pPg==0 ){
      res = 0;
    }
    for(i=1; i<=nRhs; i++){
      segmentPtrReset(&aPtr[i], LSM_SEGMENTPTR_FREE_THRESHOLD);
    }
  }
  
  if( res>=0 ){
    int bHit = 0;                 /* True if at least one rhs is not EOF */
    int iPtr = (int)*piPgno;
    LsmPgno iPtr = *piPgno;
    int i;
    segmentPtrReset(&aPtr[0], LSM_SEGMENTPTR_FREE_THRESHOLD);
    for(i=1; rc==LSM_OK && i<=nRhs && bStop==0; i++){
      SegmentPtr *pPtr = &aPtr[i];
      iOut = 0;
      rc = seekInSegment(
          pCsr, pPtr, iTopic, pKey, nKey, iPtr, eSeek, &iOut, &bStop
3357
3358
3359
3360
3361
3362
3363


3364
3365
3366
3367
3368
3369
3370
3371
3372
3373

3374
3375
3376
3377
3378
3379
3380
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374

3375
3376
3377
3378
3379
3380
3381
3382







+
+









-
+







** space).
*/
static int mergeWorkerPageOffset(u8 *aData, int nData){
  int nRec;
  int iOff;
  int nKey;
  int eType;
  i64 nDummy;


  nRec = lsmGetU16(&aData[SEGMENT_NRECORD_OFFSET(nData)]);
  iOff = lsmGetU16(&aData[SEGMENT_CELLPTR_OFFSET(nData, nRec-1)]);
  eType = aData[iOff++];
  assert( eType==0 
       || eType==(LSM_SYSTEMKEY|LSM_SEPARATOR) 
       || eType==(LSM_SEPARATOR)
  );

  iOff += lsmVarintGet32(&aData[iOff], &nKey);
  iOff += lsmVarintGet64(&aData[iOff], &nDummy);
  iOff += lsmVarintGet32(&aData[iOff], &nKey);

  return iOff + (eType ? nKey : 0);
}

/*
** Following a checkpoint operation, database pages that are part of the
3476
3477
3478
3479
3480
3481
3482
3483

3484
3485
3486
3487
3488
3489
3490
3478
3479
3480
3481
3482
3483
3484

3485
3486
3487
3488
3489
3490
3491
3492







-
+







  p = &pMW->hier;

  if( p->apHier==0 && pSeg->iRoot!=0 ){
    FileSystem *pFS = pMW->pDb->pFS;
    lsm_env *pEnv = pMW->pDb->pEnv;
    Page **apHier = 0;
    int nHier = 0;
    int iPg = (int)pSeg->iRoot;
    LsmPgno iPg = pSeg->iRoot;

    do {
      Page *pPg = 0;
      u8 *aData;
      int nData;
      int flags;

3502
3503
3504
3505
3506
3507
3508
3509

3510
3511
3512
3513
3514
3515
3516
3504
3505
3506
3507
3508
3509
3510

3511
3512
3513
3514
3515
3516
3517
3518







-
+







          break;
        }
        apHier = apNew;
        memmove(&apHier[1], &apHier[0], sizeof(Page *) * nHier);
        nHier++;

        apHier[0] = pPg;
        iPg = (int)pageGetPtr(aData, nData);
        iPg = pageGetPtr(aData, nData);
      }else{
        lsmFsPageRelease(pPg);
        break;
      }
    }while( 1 );

    if( rc==LSM_OK ){
3621
3622
3623
3624
3625
3626
3627
3628

3629
3630

3631

3632
3633
3634
3635
3636
3637
3638
3623
3624
3625
3626
3627
3628
3629

3630
3631

3632
3633
3634
3635
3636
3637
3638
3639
3640
3641







-
+

-
+

+








      /* If the key will fit on this page, break out of the loop here.
      ** The new entry will be written to page apHier[iLevel]. */
      pOld = p->apHier[iLevel];
      assert( lsmFsPageWritable(pOld) );
      aData = fsPageData(pOld, &nData);
      if( eType==0 ){
        nByte = 2 + 1 + lsmVarintLen32((int)iPtr) + lsmVarintLen32((int)iKeyPg);
        nByte = 2 + 1 + lsmVarintLen64(iPtr) + lsmVarintLen64(iKeyPg);
      }else{
        nByte = 2 + 1 + lsmVarintLen32((int)iPtr) + lsmVarintLen32(nKey) + nKey;
        nByte = 2 + 1 + lsmVarintLen64(iPtr) + lsmVarintLen32(nKey) + nKey;
      }

      nRec = pageGetNRec(aData, nData);
      nFree = SEGMENT_EOF(nData, nRec) - mergeWorkerPageOffset(aData, nData);
      if( nByte<=nFree ) break;

      /* Otherwise, this page is full. Set the right-hand-child pointer
      ** to iPtr and release it.  */
      lsmPutU64(&aData[SEGMENT_POINTER_OFFSET(nData)], iPtr);
3668
3669
3670
3671
3672
3673
3674
3675
3676


3677
3678
3679

3680
3681
3682
3683
3684
3685
3686
3671
3672
3673
3674
3675
3676
3677


3678
3679
3680
3681

3682
3683
3684
3685
3686
3687
3688
3689







-
-
+
+


-
+







  aData = fsPageData(p->apHier[iLevel], &nData);
  iOff = mergeWorkerPageOffset(aData, nData);
  nRec = pageGetNRec(aData, nData);
  lsmPutU16(&aData[SEGMENT_CELLPTR_OFFSET(nData, nRec)], (u16)iOff);
  lsmPutU16(&aData[SEGMENT_NRECORD_OFFSET(nData)], (u16)(nRec+1));
  if( eType==0 ){
    aData[iOff++] = 0x00;
    iOff += lsmVarintPut32(&aData[iOff], (int)iPtr);
    iOff += lsmVarintPut32(&aData[iOff], (int)iKeyPg);
    iOff += lsmVarintPut64(&aData[iOff], iPtr);
    iOff += lsmVarintPut64(&aData[iOff], iKeyPg);
  }else{
    aData[iOff++] = eType;
    iOff += lsmVarintPut32(&aData[iOff], (int)iPtr);
    iOff += lsmVarintPut64(&aData[iOff], iPtr);
    iOff += lsmVarintPut32(&aData[iOff], nKey);
    memcpy(&aData[iOff], pKey, nKey);
  }

  return rc;
}

3868
3869
3870
3871
3872
3873
3874
3875

3876
3877
3878
3879
3880
3881
3882
3871
3872
3873
3874
3875
3876
3877

3878
3879
3880
3881
3882
3883
3884
3885







-
+







** array. Otherwise, the main array.
**
** This function is used to write the blobs of data for keys and values.
*/
static int mergeWorkerData(
  MergeWorker *pMW,               /* Merge worker object */
  int bSep,                       /* True to write to separators run */
  int iFPtr,                      /* Footer ptr for new pages */
  LsmPgno iFPtr,                  /* Footer ptr for new pages */
  u8 *aWrite,                     /* Write data from this buffer */
  int nWrite                      /* Size of aWrite[] in bytes */
){
  int rc = LSM_OK;                /* Return code */
  int nRem = nWrite;              /* Number of bytes still to write */

  while( rc==LSM_OK && nRem>0 ){
3912
3913
3914
3915
3916
3917
3918
3919

3920
3921
3922
3923
3924
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
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
4000

4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013


4014
4015
4016
4017
4018
4019
4020
3915
3916
3917
3918
3919
3920
3921

3922
3923
3924
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
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
4000
4001
4002

4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014


4015
4016
4017
4018
4019
4020
4021
4022
4023







-
+






-
+








-
+


















-
+








-
-
+
+
















-
-
+
+

















-
+











-
-
+
+







** The MergeWorker passed as the only argument is working to merge two or
** more existing segments together (not to flush an in-memory tree). It
** has not yet written the first key to the first page of the output.
*/
static int mergeWorkerFirstPage(MergeWorker *pMW){
  int rc = LSM_OK;                /* Return code */
  Page *pPg = 0;                  /* First page of run pSeg */
  int iFPtr = 0;                  /* Pointer value read from footer of pPg */
  LsmPgno iFPtr = 0;              /* Pointer value read from footer of pPg */
  MultiCursor *pCsr = pMW->pCsr;

  assert( pMW->pPage==0 );

  if( pCsr->pBtCsr ){
    rc = LSM_OK;
    iFPtr = (int)pMW->pLevel->pNext->lhs.iFirst;
    iFPtr = pMW->pLevel->pNext->lhs.iFirst;
  }else if( pCsr->nPtr>0 ){
    Segment *pSeg;
    pSeg = pCsr->aPtr[pCsr->nPtr-1].pSeg;
    rc = lsmFsDbPageGet(pMW->pDb->pFS, pSeg, pSeg->iFirst, &pPg);
    if( rc==LSM_OK ){
      u8 *aData;                    /* Buffer for page pPg */
      int nData;                    /* Size of aData[] in bytes */
      aData = fsPageData(pPg, &nData);
      iFPtr = (int)pageGetPtr(aData, nData);
      iFPtr = pageGetPtr(aData, nData);
      lsmFsPageRelease(pPg);
    }
  }

  if( rc==LSM_OK ){
    rc = mergeWorkerNextPage(pMW, iFPtr);
    if( pCsr->pPrevMergePtr ) *pCsr->pPrevMergePtr = iFPtr;
    pMW->aSave[0].bStore = 1;
  }

  return rc;
}

static int mergeWorkerWrite(
  MergeWorker *pMW,               /* Merge worker object to write into */
  int eType,                      /* One of SORTED_SEPARATOR, WRITE or DELETE */
  void *pKey, int nKey,           /* Key value */
  void *pVal, int nVal,           /* Value value */
  int iPtr                        /* Absolute value of page pointer, or 0 */
  LsmPgno iPtr                    /* Absolute value of page pointer, or 0 */
){
  int rc = LSM_OK;                /* Return code */
  Merge *pMerge;                  /* Persistent part of level merge state */
  int nHdr;                       /* Space required for this record header */
  Page *pPg;                      /* Page to write to */
  u8 *aData;                      /* Data buffer for page pWriter->pPage */
  int nData = 0;                  /* Size of buffer aData[] in bytes */
  int nRec = 0;                   /* Number of records on page pPg */
  int iFPtr = 0;                  /* Value of pointer in footer of pPg */
  int iRPtr = 0;                  /* Value of pointer written into record */
  LsmPgno iFPtr = 0;              /* Value of pointer in footer of pPg */
  LsmPgno iRPtr = 0;              /* Value of pointer written into record */
  int iOff = 0;                   /* Current write offset within page pPg */
  Segment *pSeg;                  /* Segment being written */
  int flags = 0;                  /* If != 0, flags value for page footer */
  int bFirst = 0;                 /* True for first key of output run */

  pMerge = pMW->pLevel->pMerge;    
  pSeg = &pMW->pLevel->lhs;

  if( pSeg->iFirst==0 && pMW->pPage==0 ){
    rc = mergeWorkerFirstPage(pMW);
    bFirst = 1;
  }
  pPg = pMW->pPage;
  if( pPg ){
    aData = fsPageData(pPg, &nData);
    nRec = pageGetNRec(aData, nData);
    iFPtr = (int)pageGetPtr(aData, nData);
    iRPtr = iPtr - iFPtr;
    iFPtr = pageGetPtr(aData, nData);
    iRPtr = iPtr ? (iPtr - iFPtr) : 0;
  }
     
  /* Figure out how much space is required by the new record. The space
  ** required is divided into two sections: the header and the body. The
  ** header consists of the intial varint fields. The body are the blobs 
  ** of data that correspond to the key and value data. The entire header 
  ** must be stored on the page. The body may overflow onto the next and
  ** subsequent pages.
  **
  ** The header space is:
  **
  **     1) record type - 1 byte.
  **     2) Page-pointer-offset - 1 varint
  **     3) Key size - 1 varint
  **     4) Value size - 1 varint (only if LSM_INSERT flag is set)
  */
  if( rc==LSM_OK ){
    nHdr = 1 + lsmVarintLen32(iRPtr) + lsmVarintLen32(nKey);
    nHdr = 1 + lsmVarintLen64(iRPtr) + lsmVarintLen32(nKey);
    if( rtIsWrite(eType) ) nHdr += lsmVarintLen32(nVal);

    /* If the entire header will not fit on page pPg, or if page pPg is 
    ** marked read-only, advance to the next page of the output run. */
    iOff = pMerge->iOutputOff;
    if( iOff<0 || pPg==0 || iOff+nHdr > SEGMENT_EOF(nData, nRec+1) ){
      if( iOff>=0 && pPg ){
        /* Zero any free space on the page */
        assert( aData );
        memset(&aData[iOff], 0, SEGMENT_EOF(nData, nRec)-iOff);
      }
      iFPtr = (int)*pMW->pCsr->pPrevMergePtr;
      iRPtr = iPtr - iFPtr;
      iFPtr = *pMW->pCsr->pPrevMergePtr;
      iRPtr = iPtr ? (iPtr - iFPtr) : 0;
      iOff = 0;
      nRec = 0;
      rc = mergeWorkerNextPage(pMW, iFPtr);
      pPg = pMW->pPage;
    }
  }

4045
4046
4047
4048
4049
4050
4051
4052

4053
4054
4055
4056
4057
4058
4059
4048
4049
4050
4051
4052
4053
4054

4055
4056
4057
4058
4059
4060
4061
4062







-
+







    /* Update the page footer. */
    lsmPutU16(&aData[SEGMENT_NRECORD_OFFSET(nData)], (u16)(nRec+1));
    lsmPutU16(&aData[SEGMENT_CELLPTR_OFFSET(nData, nRec)], (u16)iOff);
    if( flags ) lsmPutU16(&aData[SEGMENT_FLAGS_OFFSET(nData)], (u16)flags);

    /* Write the entry header into the current page. */
    aData[iOff++] = (u8)eType;                                           /* 1 */
    iOff += lsmVarintPut32(&aData[iOff], iRPtr);                         /* 2 */
    iOff += lsmVarintPut64(&aData[iOff], iRPtr);                         /* 2 */
    iOff += lsmVarintPut32(&aData[iOff], nKey);                          /* 3 */
    if( rtIsWrite(eType) ) iOff += lsmVarintPut32(&aData[iOff], nVal);   /* 4 */
    pMerge->iOutputOff = iOff;

    /* Write the key and data into the segment. */
    assert( iFPtr==pageGetPtr(aData, nData) );
    rc = mergeWorkerData(pMW, 0, iFPtr+iRPtr, pKey, nKey);
4279
4280
4281
4282
4283
4284
4285
4286

4287
4288
4289
4290
4291
4292
4293
4282
4283
4284
4285
4286
4287
4288

4289
4290
4291
4292
4293
4294
4295
4296







-
+







      rc = multiCursorGetVal(pCsr, iVal, &pVal, &nVal);
      if( pVal && rc==LSM_OK ){
        assert( nVal>=0 );
        rc = sortedBlobSet(pDb->pEnv, &pCsr->val, pVal, nVal);
        pVal = pCsr->val.pData;
      }
      if( rc==LSM_OK ){
        rc = mergeWorkerWrite(pMW, eType, pKey, nKey, pVal, nVal, (int)iPtr);
        rc = mergeWorkerWrite(pMW, eType, pKey, nKey, pVal, nVal, iPtr);
      }
    }
  }

  /* Advance the cursor to the next input record (assuming one exists). */
  assert( lsmMCursorValid(pMW->pCsr) );
  if( rc==LSM_OK ) rc = lsmMCursorNext(pMW->pCsr);
4600
4601
4602
4603
4604
4605
4606
4607

4608
4609
4610
4611
4612
4613
4614
4603
4604
4605
4606
4607
4608
4609

4610
4611
4612
4613
4614
4615
4616
4617







-
+







      int i;
      for(i=0; rc==LSM_OK && i<pCsr->nPtr; i++){
        MergeInput *pInput = &pMerge->aInput[i];
        if( pInput->iPg ){
          SegmentPtr *pPtr;
          assert( pCsr->aPtr[i].pPg==0 );
          pPtr = &pCsr->aPtr[i];
          rc = segmentPtrLoadPage(pDb->pFS, pPtr, (int)pInput->iPg);
          rc = segmentPtrLoadPage(pDb->pFS, pPtr, pInput->iPg);
          if( rc==LSM_OK && pPtr->nCell>0 ){
            rc = segmentPtrLoadCell(pPtr, pInput->iCell);
          }
        }
      }

      if( rc==LSM_OK && pCsr->pBtCsr ){
5465
5466
5467
5468
5469
5470
5471
5472

5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484

5485
5486

5487
5488
5489
5490
5491
5492
5493
5468
5469
5470
5471
5472
5473
5474

5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486

5487
5488

5489
5490
5491
5492
5493
5494
5495
5496







-
+











-
+

-
+








/*
** Return a string representation of the segment passed as the only argument.
** Space for the returned string is allocated using lsmMalloc(), and should
** be freed by the caller using lsmFree().
*/
static char *segToString(lsm_env *pEnv, Segment *pSeg, int nMin){
  int nSize = pSeg->nSize;
  LsmPgno nSize = pSeg->nSize;
  LsmPgno iRoot = pSeg->iRoot;
  LsmPgno iFirst = pSeg->iFirst;
  LsmPgno iLast = pSeg->iLastPg;
  char *z;

  char *z1;
  char *z2;
  int nPad;

  z1 = lsmMallocPrintf(pEnv, "%d.%d", iFirst, iLast);
  if( iRoot ){
    z2 = lsmMallocPrintf(pEnv, "root=%d", iRoot);
    z2 = lsmMallocPrintf(pEnv, "root=%lld", iRoot);
  }else{
    z2 = lsmMallocPrintf(pEnv, "size=%d", nSize);
    z2 = lsmMallocPrintf(pEnv, "size=%lld", nSize);
  }

  nPad = nMin - 2 - strlen(z1) - 1 - strlen(z2);
  nPad = LSM_MAX(0, nPad);

  if( iRoot ){
    z = lsmMallocPrintf(pEnv, "/%s %*s%s\\", z1, nPad, "", z2);
5532
5533
5534
5535
5536
5537
5538
5539

5540
5541
5542
5543
5544
5545
5546
5547

5548
5549
5550
5551

5552
5553
5554
5555
5556
5557
5558
5559
5560
5561

5562
5563
5564
5565
5566
5567

5568
5569
5570
5571
5572
5573
5574
5535
5536
5537
5538
5539
5540
5541

5542
5543
5544
5545
5546
5547
5548
5549

5550
5551
5552
5553

5554
5555
5556
5557
5558
5559
5560
5561
5562
5563

5564
5565
5566
5567
5568
5569

5570
5571
5572
5573
5574
5575
5576
5577







-
+







-
+



-
+









-
+





-
+








void sortedDumpPage(lsm_db *pDb, Segment *pRun, Page *pPg, int bVals){
  LsmBlob blob = {0, 0, 0};       /* LsmBlob used for keys */
  LsmString s;
  int i;

  int nRec;
  int iPtr;
  LsmPgno iPtr;
  int flags;
  u8 *aData;
  int nData;

  aData = fsPageData(pPg, &nData);

  nRec = pageGetNRec(aData, nData);
  iPtr = (int)pageGetPtr(aData, nData);
  iPtr = pageGetPtr(aData, nData);
  flags = pageGetFlags(aData, nData);

  lsmStringInit(&s, pDb->pEnv);
  lsmStringAppendf(&s,"nCell=%d iPtr=%d flags=%d {", nRec, iPtr, flags);
  lsmStringAppendf(&s,"nCell=%d iPtr=%lld flags=%d {", nRec, iPtr, flags);
  if( flags&SEGMENT_BTREE_FLAG ) iPtr = 0;

  for(i=0; i<nRec; i++){
    Page *pRef = 0;               /* Pointer to page iRef */
    int iChar;
    u8 *aKey; int nKey = 0;       /* Key */
    u8 *aVal = 0; int nVal = 0;   /* Value */
    int iTopic;
    u8 *aCell;
    int iPgPtr;
    i64 iPgPtr;
    int eType;

    aCell = pageGetCell(aData, nData, i);
    eType = *aCell++;
    assert( (flags & SEGMENT_BTREE_FLAG) || eType!=0 );
    aCell += lsmVarintGet32(aCell, &iPgPtr);
    aCell += lsmVarintGet64(aCell, &iPgPtr);

    if( eType==0 ){
      LsmPgno iRef;               /* Page number of referenced page */
      aCell += lsmVarintGet64(aCell, &iRef);
      lsmFsDbPageGet(pDb->pFS, pRun, iRef, &pRef);
      aKey = pageGetKey(pRun, pRef, 0, &iTopic, &nKey, &blob);
    }else{
5586
5587
5588
5589
5590
5591
5592
5593

5594
5595
5596
5597
5598
5599
5600
5589
5590
5591
5592
5593
5594
5595

5596
5597
5598
5599
5600
5601
5602
5603







-
+







    if( nVal>0 && bVals ){
      lsmStringAppendf(&s, "##");
      for(iChar=0; iChar<nVal; iChar++){
        lsmStringAppendf(&s, "%c", isalnum(aVal[iChar]) ? aVal[iChar] : '.');
      }
    }

    lsmStringAppendf(&s, " %d", iPgPtr+iPtr);
    lsmStringAppendf(&s, " %lld", iPgPtr+iPtr);
    lsmFsPageRelease(pRef);
  }
  lsmStringAppend(&s, "}", 1);

  lsmLogMessage(pDb, LSM_OK, "      Page %d: %s", lsmFsPageNumber(pPg), s.z);
  lsmStringClear(&s);

5716
5717
5718
5719
5720
5721
5722
5723

5724
5725
5726
5727
5728
5729
5730

5731
5732
5733
5734
5735
5736

5737
5738
5739
5740
5741
5742
5743
5719
5720
5721
5722
5723
5724
5725

5726
5727
5728
5729
5730
5731
5732

5733
5734
5735
5736
5737
5738

5739
5740
5741
5742
5743
5744
5745
5746







-
+






-
+





-
+







  }

  if( rc==LSM_OK ){
    LsmBlob blob = {0, 0, 0, 0};
    int nKeyWidth = 0;
    LsmString str;
    int nRec;
    int iPtr;
    LsmPgno iPtr;
    int flags2;
    int iCell;
    u8 *aData; int nData;         /* Page data and size thereof */

    aData = fsPageData(pPg, &nData);
    nRec = pageGetNRec(aData, nData);
    iPtr = (int)pageGetPtr(aData, nData);
    iPtr = pageGetPtr(aData, nData);
    flags2 = pageGetFlags(aData, nData);

    lsmStringInit(&str, pDb->pEnv);
    lsmStringAppendf(&str, "Page : %lld  (%d bytes)\n", iPg, nData);
    lsmStringAppendf(&str, "nRec : %d\n", nRec);
    lsmStringAppendf(&str, "iPtr : %d\n", iPtr);
    lsmStringAppendf(&str, "iPtr : %lld\n", iPtr);
    lsmStringAppendf(&str, "flags: %04x\n", flags2);
    lsmStringAppendf(&str, "\n");

    for(iCell=0; iCell<nRec; iCell++){
      int nKey;
      infoCellDump(
          pDb, pSeg, bIndirect, pPg, iCell, 0, 0, 0, &nKey, 0, 0, &blob

Changes to ext/lsm1/lsm_unix.c.

224
225
226
227
228
229
230




231
232
233
234
235
236
237
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241







+
+
+
+







    if( iSz<iMin ){
      iSz = ((iMin + nIncrSz-1) / nIncrSz) * nIncrSz;
      prc = ftruncate(p->fd, iSz);
      if( prc!=0 ) return LSM_IOERR_BKPT;
    }

    p->pMap = mmap(0, iSz, PROT_READ|PROT_WRITE, MAP_SHARED, p->fd, 0);
    if( p->pMap==MAP_FAILED ){
      p->pMap = 0;
      return LSM_IOERR_BKPT;
    }
    p->nMap = iSz;
  }

  *ppOut = p->pMap;
  *pnOut = p->nMap;
  return LSM_OK;
}
409
410
411
412
413
414
415
416




417
418
419
420
421
422
423
413
414
415
416
417
418
419

420
421
422
423
424
425
426
427
428
429
430







-
+
+
+
+







    p->nShm = nNew;
  }

  if( p->apShm[iChunk]==0 ){
    p->apShm[iChunk] = mmap(0, LSM_SHM_CHUNK_SIZE, 
        PROT_READ|PROT_WRITE, MAP_SHARED, p->shmfd, iChunk*LSM_SHM_CHUNK_SIZE
    );
    if( p->apShm[iChunk]==0 ) return LSM_IOERR_BKPT;
    if( p->apShm[iChunk]==MAP_FAILED ){
      p->apShm[iChunk] = 0;
      return LSM_IOERR_BKPT;
    }
  }

  *ppShm = p->apShm[iChunk];
  return LSM_OK;
}

static void lsmPosixOsShmBarrier(void){

Changes to ext/lsm1/lsm_varint.c.

180
181
182
183
184
185
186





187
188
189
190
191
192
193
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198







+
+
+
+
+







  return ret;
}

int lsmVarintLen32(int n){
  u8 aData[9];
  return lsmVarintPut32(aData, n);
}

int lsmVarintLen64(i64 n){
  u8 aData[9];
  return lsmVarintPut64(aData, n);
}

/*
** The argument is the first byte of a varint. This function returns the
** total number of bytes in the entire varint (including the first byte).
*/
int lsmVarintSize(u8 c){
  if( c<241 ) return 1;

Changes to ext/lsm1/lsm_vtab.c.

22
23
24
25
26
27
28
29

30
31
32
33
34
35
36
22
23
24
25
26
27
28

29
30
31
32
33
34
35
36







-
+







**
** The keytype must be one of: UINT, TEXT, BLOB.  All keys must be of that
** one type.  "UINT" means unsigned integer.  The values may be of any
** SQLite datatype: BLOB, TEXT, INTEGER, FLOAT, or NULL.
**
** The virtual table contains read-only hidden columns:
**
**     lsm1_key	      A BLOB which is the raw LSM key.  If the "keytype"
**     lsm1_key       A BLOB which is the raw LSM key.  If the "keytype"
**                    is BLOB or TEXT then this column is exactly the
**                    same as the key.  For the UINT keytype, this column
**                    will be a variable-length integer encoding of the key.
**
**     lsm1_value     A BLOB which is the raw LSM value.  All of the value
**                    columns are packed into this BLOB using the encoding
**                    described below.
838
839
840
841
842
843
844
845

846
847
848
849
850
851
852
838
839
840
841
842
843
844

845
846
847
848
849
850
851
852







-
+







  int argIdx = -1;       /* Index of the key== constraint, or -1 if none */
  int iIdx2 = -1;        /* The index of the second key */
  int omit1 = 0;
  int omit2 = 0;

  const struct sqlite3_index_constraint *pConstraint;
  pConstraint = pIdxInfo->aConstraint;
  for(i=0; i<pIdxInfo->nConstraint && idxNum<16; i++, pConstraint++){
  for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
    if( pConstraint->usable==0 ) continue;
    if( pConstraint->iColumn!=0 ) continue;
    switch( pConstraint->op ){
      case SQLITE_INDEX_CONSTRAINT_EQ: {
        if( idxNum>0 ){
          argIdx = i;
          iIdx2 = -1;

Changes to ext/lsm1/test/lsm1_simple.test.

84
85
86
87
88
89
90



91
























































92
93
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







+
+
+

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


  INSERT INTO x1(a,b,c,d) VALUES(15, 11, 22, 33),(8,'banjo',x'333231',NULL),
      (12,NULL,3.25,-559281390);
  SELECT quote(a), quote(b), quote(c), quote(d), '|' FROM x1;
} {'12' NULL 3.25 -559281390 | '15' 11 22 33 | '8' 'banjo' X'333231' NULL |}
do_execsql_test 211 {
  SELECT quote(a), quote(lsm1_key), quote(lsm1_value), '|' FROM x1;
} {'12' X'3132' X'05320000000000000A401FFB42ABE9DB' | '15' X'3135' X'4284C6' | '8' X'38' X'2162616E6A6F1633323105' |}
do_execsql_test 212 {
  SELECT quote(a), quote(lsm1_key), quote(lsm1_value) FROM x1 WHERE a='12';
} {'12' X'3132' X'05320000000000000A401FFB42ABE9DB'}

#-------------------------------------------------------------------------
reset_db
forcedelete testlsm.db
load_lsm1_vtab db
do_execsql_test 300 {
  CREATE VIRTUAL TABLE x1 USING lsm1(testlsm.db,a,TEXT,b,c,d);
}
do_eqp_test 310 {
  SELECT * FROM x1 WHERE a=?
} {SCAN TABLE x1 VIRTUAL TABLE INDEX 0:}

do_eqp_test 320 {
  SELECT * FROM x1 WHERE a>?
} {SCAN TABLE x1 VIRTUAL TABLE INDEX 2:}

do_eqp_test 330 {
  SELECT * FROM x1 WHERE a<?
} {SCAN TABLE x1 VIRTUAL TABLE INDEX 3:}
do_eqp_test 340 {
  SELECT * FROM x1 WHERE a BETWEEN ? AND ?
} {SCAN TABLE x1 VIRTUAL TABLE INDEX 1:}

#-------------------------------------------------------------------------
reset_db
forcedelete testlsm.db
load_lsm1_vtab db
do_execsql_test 400 {
  CREATE VIRTUAL TABLE x1 USING lsm1(testlsm.db,a,TEXT,b);
  INSERT INTO x1 VALUES('one', 1);
  INSERT INTO x1 VALUES('two', 2);
  INSERT INTO x1 VALUES('three', 3);
  INSERT INTO x1 VALUES('four', 4);
  INSERT INTO x1 VALUES('five', 5);
}
do_execsql_test 410 {
  SELECT b FROM x1 WHERE a = 'two'
} {2}
do_execsql_test 411 {
  SELECT b FROM x1 WHERE a = 'one'
} {1}
do_execsql_test 412 {
  SELECT b FROM x1 WHERE a = 'five'
} {5}

do_execsql_test 420 {
  SELECT b FROM x1 WHERE a BETWEEN 'one' AND 'three';
} {1 3}
do_execsql_test 421 {
  SELECT b FROM x1 WHERE a BETWEEN 'five' AND 'two';
} {5 4 1 3 2}
do_execsql_test 421 {
  SELECT b FROM x1 WHERE a > 'five';
} {4 1 3 2}
do_execsql_test 421 {
  SELECT b FROM x1 WHERE a <= 'three';
} {3 1 4 5}

finish_test

Changes to ext/misc/amatch.c.

615
616
617
618
619
620
621
622

623
624
625
626
627
628
629
615
616
617
618
619
620
621

622
623
624
625
626
627
628
629







-
+







  if( strcmp(zFrom,"")==0 && strcmp(zTo,"?")==0 ){
    if( p->rIns==0 || p->rIns>rCost ) p->rIns = rCost;
  }else
  if( strcmp(zFrom,"?")==0 && strcmp(zTo,"")==0 ){
    if( p->rDel==0 || p->rDel>rCost ) p->rDel = rCost;
  }else
  {
    pRule = sqlite3_malloc( sizeof(*pRule) + nFrom + nTo );
    pRule = sqlite3_malloc64( sizeof(*pRule) + nFrom + nTo );
    if( pRule==0 ){
      rc = SQLITE_NOMEM;
    }else{
      memset(pRule, 0, sizeof(*pRule));
      pRule->zFrom = &pRule->zTo[nTo+1];
      pRule->nFrom = (amatch_len)nFrom;
      memcpy(pRule->zFrom, zFrom, nFrom+1);
734
735
736
737
738
739
740
741

742
743
744
745


746
747
748
749
750

751
752
753
754
755
756
757
734
735
736
737
738
739
740

741
742
743


744
745
746
747
748
749

750
751
752
753
754
755
756
757







-
+


-
-
+
+




-
+







**
**     "abc"   becomes   abc
**     'xyz'   becomes   xyz
**     [pqr]   becomes   pqr
**     `mno`   becomes   mno
*/
static char *amatchDequote(const char *zIn){
  int nIn;                        /* Size of input string, in bytes */
  sqlite3_int64 nIn;              /* Size of input string, in bytes */
  char *zOut;                     /* Output (dequoted) string */

  nIn = (int)strlen(zIn);
  zOut = sqlite3_malloc(nIn+1);
  nIn = strlen(zIn);
  zOut = sqlite3_malloc64(nIn+1);
  if( zOut ){
    char q = zIn[0];              /* Quote character (if any ) */

    if( q!='[' && q!= '\'' && q!='"' && q!='`' ){
      memcpy(zOut, zIn, nIn+1);
      memcpy(zOut, zIn, (size_t)(nIn+1));
    }else{
      int iOut = 0;               /* Index of next byte to write to output */
      int iIn;                    /* Index of next byte to read from input */

      if( q=='[' ) q = ']';
      for(iIn=1; iIn<nIn; iIn++){
        if( zIn[iIn]==q ) iIn++;
896
897
898
899
900
901
902

903
904
905
906
907
908
909
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910







+







  if( pNew->zCostTab==0 ){
    *pzErr = sqlite3_mprintf("no edit_distances table specified");
    rc = SQLITE_ERROR;
  }else{
    rc = amatchLoadRules(db, pNew, pzErr);
  }
  if( rc==SQLITE_OK ){
    sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
    rc = sqlite3_declare_vtab(db,
           "CREATE TABLE x(word,distance,language,"
           "command HIDDEN,nword HIDDEN)"
         );
#define AMATCH_COL_WORD       0
#define AMATCH_COL_DISTANCE   1
#define AMATCH_COL_LANGUAGE   2
1065
1066
1067
1068
1069
1070
1071
1072

1073
1074
1075
1076
1077
1078
1079
1066
1067
1068
1069
1070
1071
1072

1073
1074
1075
1076
1077
1078
1079
1080







-
+







             pWord->rCost, pWord->zWord, pWord->zCost);
#endif
      pOther = amatchAvlInsert(&pCur->pCost, &pWord->sCost);
      assert( pOther==0 ); (void)pOther;
    }
    return;
  }
  pWord = sqlite3_malloc( sizeof(*pWord) + nBase + nTail - 1 );
  pWord = sqlite3_malloc64( sizeof(*pWord) + nBase + nTail - 1 );
  if( pWord==0 ) return;
  memset(pWord, 0, sizeof(*pWord));
  pWord->rCost = rCost;
  pWord->iSeq = pCur->nWord++;
  amatchWriteCost(pWord);
  pWord->nMatch = (short)nMatch;
  pWord->pNext = pCur->pAllWords;

Changes to ext/misc/appendvfs.c.

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







-
-
-
+
+
+
+


-
-
-
+
+
+
-
-

-
-
+
-

-
-
-
+
+
+
+
+







-
-
-
-
+
+
+
+

-
-
+
+












-
+



+
-
+





-
+
+
+
+
+
+
+
+
+
+













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

-
-
-
+
+
+
+







**
******************************************************************************
**
** This file implements a VFS shim that allows an SQLite database to be
** appended onto the end of some other file, such as an executable.
**
** A special record must appear at the end of the file that identifies the
** file as an appended database and provides an offset to page 1.  For
** best performance page 1 should be located at a disk page boundary, though
** that is not required.
** file as an appended database and provides the offset to the first page
** of the exposed content. (Or, it is the length of the content prefix.)
** For best performance page 1 should be located at a disk page boundary,
** though that is not required.
**
** When opening a database using this VFS, the connection might treat
** the file as an ordinary SQLite database, or it might treat is as a
** database appended onto some other file.  Here are the rules:
**
** the file as an ordinary SQLite database, or it might treat it as a
** database appended onto some other file.  The decision is made by
** applying the following rules in order:
**  (1)  When opening a new empty file, that file is treated as an ordinary
**       database.
**
**  (2)  When opening a file that begins with the standard SQLite prefix
**       string "SQLite format 3", that file is treated as an ordinary
**  (1)  An empty file is an ordinary database.
**       database.
**
**  (3)  When opening a file that ends with the appendvfs trailer string
**       "Start-Of-SQLite3-NNNNNNNN" that file is treated as an appended
**       database.
**  (2)  If the file ends with the appendvfs trailer string
**       "Start-Of-SQLite3-NNNNNNNN" that file is an appended database.
**
**  (3)  If the file begins with the standard SQLite prefix string
**       "SQLite format 3", that file is an ordinary database.
**
**  (4)  If none of the above apply and the SQLITE_OPEN_CREATE flag is
**       set, then a new database is appended to the already existing file.
**
**  (5)  Otherwise, SQLITE_CANTOPEN is returned.
**
** To avoid unnecessary complications with the PENDING_BYTE, the size of
** the file containing the database is limited to 1GB.  This VFS will refuse
** to read or write past the 1GB mark.  This restriction might be lifted in
** future versions.  For now, if you need a large database, then keep the
** database in a separate file.
** the file containing the database is limited to 1GiB. (1073741824 bytes)
** This VFS will not read or write past the 1GiB mark.  This restriction
** might be lifted in future versions.  For now, if you need a larger
** database, then keep it in a separate file.
**
** If the file being opened is not an appended database, then this shim is
** a pass-through into the default underlying VFS.
** If the file being opened is a plain database (not an appended one), then
** this shim is a pass-through into the default underlying VFS. (rule 3)
**/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#include <string.h>
#include <assert.h>

/* The append mark at the end of the database is:
**
**     Start-Of-SQLite3-NNNNNNNN
**     123456789 123456789 12345
**
** The NNNNNNNN represents a 64-bit big-endian unsigned integer which is
** the offset to page 1.
** the offset to page 1, and also the length of the prefix content.
*/
#define APND_MARK_PREFIX     "Start-Of-SQLite3-"
#define APND_MARK_PREFIX_SZ  17
#define APND_MARK_FOS_SZ      8
#define APND_MARK_SIZE       25
#define APND_MARK_SIZE       (APND_MARK_PREFIX_SZ+APND_MARK_FOS_SZ)

/*
** Maximum size of the combined prefix + database + append-mark.  This
** must be less than 0x40000000 to avoid locking issues on Windows.
*/
#define APND_MAX_SIZE  (65536*15259)
#define APND_MAX_SIZE  (0x40000000)

/*
** Try to align the database to an even multiple of APND_ROUNDUP bytes.
*/
#ifndef APND_ROUNDUP
#define APND_ROUNDUP 4096
#endif
#define APND_ALIGN_MASK         ((sqlite3_int64)(APND_ROUNDUP-1))
#define APND_START_ROUNDUP(fsz) (((fsz)+APND_ALIGN_MASK) & ~APND_ALIGN_MASK)

/*
** Forward declaration of objects used by this utility
*/
typedef struct sqlite3_vfs ApndVfs;
typedef struct ApndFile ApndFile;

/* Access to a lower-level VFS that (might) implement dynamic loading,
** access to randomness, etc.
*/
#define ORIGVFS(p)  ((sqlite3_vfs*)((p)->pAppData))
#define ORIGFILE(p) ((sqlite3_file*)(((ApndFile*)(p))+1))

/* An open file */
/* An open appendvfs file
**
** An instance of this structure describes the appended database file.
** A separate sqlite3_file object is always appended. The appended
** sqlite3_file object (which can be accessed using ORIGFILE()) describes
** the entire file, including the prefix, the database, and the
** append-mark.
**
** The structure of an AppendVFS database is like this:
**
**   +-------------+---------+----------+-------------+
**   | prefix-file | padding | database | append-mark |
**   +-------------+---------+----------+-------------+
**                           ^          ^
**                           |          |
**                         iPgOne      iMark
**
**
** "prefix file" -  file onto which the database has been appended.
** "padding"     -  zero or more bytes inserted so that "database"
**                  starts on an APND_ROUNDUP boundary
** "database"    -  The SQLite database file
** "append-mark" -  The 25-byte "Start-Of-SQLite3-NNNNNNNN" that indicates
**                  the offset from the start of prefix-file to the start
**                  of "database".
**
** The size of the database is iMark - iPgOne.
**
** The NNNNNNNN in the "Start-Of-SQLite3-NNNNNNNN" suffix is the value
** of iPgOne stored as a big-ending 64-bit integer.
**
** iMark will be the size of the underlying file minus 25 (APND_MARKSIZE).
** Or, iMark is -1 to indicate that it has not yet been written.
*/
struct ApndFile {
  sqlite3_file base;              /* IO methods */
  sqlite3_int64 iPgOne;           /* File offset to page 1 */
  sqlite3_int64 iMark;            /* Start of the append-mark */
  sqlite3_file base;        /* Subclass.  MUST BE FIRST! */
  sqlite3_int64 iPgOne;     /* Offset to the start of the database */
  sqlite3_int64 iMark;      /* Offset of the append mark.  -1 if unwritten */
  /* Always followed by another sqlite3_file that describes the whole file */
};

/*
** Methods for ApndFile
*/
static int apndClose(sqlite3_file*);
static int apndRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
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
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







-
-

















-
+

-
+



-
+
+
+

-
-
+
+
+
+
+
+

+
+
+

-
-
+
+
+

+
+
-
+
+
+
+











-
-
+
+
+

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






-
-
+

-
-
-
-
+
+
-
-
+
+












+


-
+
-
-
-
-
-
+
-
-
+







  apndShmLock,                    /* xShmLock */
  apndShmBarrier,                 /* xShmBarrier */
  apndShmUnmap,                   /* xShmUnmap */
  apndFetch,                      /* xFetch */
  apndUnfetch                     /* xUnfetch */
};



/*
** Close an apnd-file.
*/
static int apndClose(sqlite3_file *pFile){
  pFile = ORIGFILE(pFile);
  return pFile->pMethods->xClose(pFile);
}

/*
** Read data from an apnd-file.
*/
static int apndRead(
  sqlite3_file *pFile, 
  void *zBuf, 
  int iAmt, 
  sqlite_int64 iOfst
){
  ApndFile *p = (ApndFile *)pFile;
  ApndFile *paf = (ApndFile *)pFile;
  pFile = ORIGFILE(pFile);
  return pFile->pMethods->xRead(pFile, zBuf, iAmt, iOfst+p->iPgOne);
  return pFile->pMethods->xRead(pFile, zBuf, iAmt, paf->iPgOne+iOfst);
}

/*
** Add the append-mark onto the end of the file.
** Add the append-mark onto what should become the end of the file.
*  If and only if this succeeds, internal ApndFile.iMark is updated.
*  Parameter iWriteEnd is the appendvfs-relative offset of the new mark.
*/
static int apndWriteMark(ApndFile *p, sqlite3_file *pFile){
  int i;
static int apndWriteMark(
  ApndFile *paf,
  sqlite3_file *pFile,
  sqlite_int64 iWriteEnd
){
  sqlite_int64 iPgOne = paf->iPgOne;
  unsigned char a[APND_MARK_SIZE];
  int i = APND_MARK_FOS_SZ;
  int rc;
  assert(pFile == ORIGFILE(paf));
  memcpy(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ);
  for(i=0; i<8; i++){
    a[APND_MARK_PREFIX_SZ+i] = (p->iPgOne >> (56 - i*8)) & 0xff;
  while( --i >= 0 ){
    a[APND_MARK_PREFIX_SZ+i] = (unsigned char)(iPgOne & 0xff);
    iPgOne >>= 8;
  }
  iWriteEnd += paf->iPgOne;
  if( SQLITE_OK==(rc = pFile->pMethods->xWrite
  return pFile->pMethods->xWrite(pFile, a, APND_MARK_SIZE, p->iMark);
                  (pFile, a, APND_MARK_SIZE, iWriteEnd)) ){
    paf->iMark = iWriteEnd;
  }
  return rc;
}

/*
** Write data to an apnd-file.
*/
static int apndWrite(
  sqlite3_file *pFile,
  const void *zBuf,
  int iAmt,
  sqlite_int64 iOfst
){
  int rc;
  ApndFile *p = (ApndFile *)pFile;
  ApndFile *paf = (ApndFile *)pFile;
  sqlite_int64 iWriteEnd = iOfst + iAmt;
  if( iWriteEnd>=APND_MAX_SIZE ) return SQLITE_FULL;
  pFile = ORIGFILE(pFile);
  if( iOfst+iAmt>=APND_MAX_SIZE ) return SQLITE_FULL;
  rc = pFile->pMethods->xWrite(pFile, zBuf, iAmt, iOfst+p->iPgOne);
  /* If append-mark is absent or will be overwritten, write it. */
  if( rc==SQLITE_OK &&  iOfst + iAmt + p->iPgOne > p->iMark ){
    sqlite3_int64 sz = 0;
    rc = pFile->pMethods->xFileSize(pFile, &sz);
    if( rc==SQLITE_OK ){
      p->iMark = sz - APND_MARK_SIZE;
      if( iOfst + iAmt + p->iPgOne > p->iMark ){
        p->iMark = p->iPgOne + iOfst + iAmt;
        rc = apndWriteMark(p, pFile);
      }
  if( paf->iMark < 0 || paf->iPgOne + iWriteEnd > paf->iMark ){
    int rc = apndWriteMark(paf, pFile, iWriteEnd);
    if( SQLITE_OK!=rc ) return rc;
  }
    }
  }
  return rc;
  return pFile->pMethods->xWrite(pFile, zBuf, iAmt, paf->iPgOne+iOfst);
}

/*
** Truncate an apnd-file.
*/
static int apndTruncate(sqlite3_file *pFile, sqlite_int64 size){
  int rc;
  ApndFile *p = (ApndFile *)pFile;
  ApndFile *paf = (ApndFile *)pFile;
  pFile = ORIGFILE(pFile);
  rc = pFile->pMethods->xTruncate(pFile, size+p->iPgOne+APND_MARK_SIZE);
  if( rc==SQLITE_OK ){
    p->iMark = p->iPgOne+size;
    rc = apndWriteMark(p, pFile);
  /* The append mark goes out first so truncate failure does not lose it. */
  if( SQLITE_OK!=apndWriteMark(paf, pFile, size) ) return SQLITE_IOERR;
  }
  return rc;
  /* Truncate underlying file just past append mark */
  return pFile->pMethods->xTruncate(pFile, paf->iMark+APND_MARK_SIZE);
}

/*
** Sync an apnd-file.
*/
static int apndSync(sqlite3_file *pFile, int flags){
  pFile = ORIGFILE(pFile);
  return pFile->pMethods->xSync(pFile, flags);
}

/*
** Return the current file-size of an apnd-file.
** If the append mark is not yet there, the file-size is 0.
*/
static int apndFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
  ApndFile *p = (ApndFile *)pFile;
  ApndFile *paf = (ApndFile *)pFile;
  int rc;
  pFile = ORIGFILE(p);
  rc = pFile->pMethods->xFileSize(pFile, pSize);
  if( rc==SQLITE_OK && p->iPgOne ){
    *pSize -= p->iPgOne + APND_MARK_SIZE;
  *pSize = ( paf->iMark >= 0 )? (paf->iMark - paf->iPgOne) : 0;
  }
  return rc;
  return SQLITE_OK;
}

/*
** Lock an apnd-file.
*/
static int apndLock(sqlite3_file *pFile, int eLock){
  pFile = ORIGFILE(pFile);
304
305
306
307
308
309
310
311

312
313

314
315
316

317
318
319
320
321
322
323
346
347
348
349
350
351
352

353
354
355
356
357
358

359
360
361
362
363
364
365
366







-
+


+


-
+







  return pFile->pMethods->xCheckReservedLock(pFile, pResOut);
}

/*
** File control method. For custom operations on an apnd-file.
*/
static int apndFileControl(sqlite3_file *pFile, int op, void *pArg){
  ApndFile *p = (ApndFile *)pFile;
  ApndFile *paf = (ApndFile *)pFile;
  int rc;
  pFile = ORIGFILE(pFile);
  if( op==SQLITE_FCNTL_SIZE_HINT ) *(sqlite3_int64*)pArg += paf->iPgOne;
  rc = pFile->pMethods->xFileControl(pFile, op, pArg);
  if( rc==SQLITE_OK && op==SQLITE_FCNTL_VFSNAME ){
    *(char**)pArg = sqlite3_mprintf("apnd(%lld)/%z", p->iPgOne, *(char**)pArg);
    *(char**)pArg = sqlite3_mprintf("apnd(%lld)/%z", paf->iPgOne,*(char**)pArg);
  }
  return rc;
}

/*
** Return the sector-size in bytes for an apnd-file.
*/
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
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







+
+
+












-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
+
+
+
+
+
+




+


-
+



-
-
-
+
+
+
+

+
+



+

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



-
+





-
-
-
+
+
+

-
+
-

+
+
+
+
-
+

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

-
+
-
+

-
-
+
+
+
+
+


-
-
-
+
+
+



-
+

+
+
+
+
+
+
+
+

-
-
-


+
+
+
+
+
+
+
+
+
+




-
-
-







static int apndFetch(
  sqlite3_file *pFile,
  sqlite3_int64 iOfst,
  int iAmt,
  void **pp
){
  ApndFile *p = (ApndFile *)pFile;
  if( p->iMark < 0 || iOfst+iAmt > p->iMark ){
    return SQLITE_IOERR; /* Cannot read what is not yet there. */
  }
  pFile = ORIGFILE(pFile);
  return pFile->pMethods->xFetch(pFile, iOfst+p->iPgOne, iAmt, pp);
}

/* Release a memory-mapped page */
static int apndUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
  ApndFile *p = (ApndFile *)pFile;
  pFile = ORIGFILE(pFile);
  return pFile->pMethods->xUnfetch(pFile, iOfst+p->iPgOne, pPage);
}

/*
** Check to see if the file is an ordinary SQLite database file.
*/
static int apndIsOrdinaryDatabaseFile(sqlite3_int64 sz, sqlite3_file *pFile){
  int rc;
  char zHdr[16];
  static const char aSqliteHdr[] = "SQLite format 3";
  if( sz<512 ) return 0;
  rc = pFile->pMethods->xRead(pFile, zHdr, sizeof(zHdr), 0);
  if( rc ) return 0;
  return memcmp(zHdr, aSqliteHdr, sizeof(zHdr))==0;
}

/*
** Try to read the append-mark off the end of a file.  Return the
** start of the appended database if the append-mark is present.  If
** there is no append-mark, return -1;
** start of the appended database if the append-mark is present.
** If there is no valid append-mark, return -1;
**
** An append-mark is only valid if the NNNNNNNN start-of-database offset
** indicates that the appended database contains at least one page.  The
** start-of-database value must be a multiple of 512.
*/
static sqlite3_int64 apndReadMark(sqlite3_int64 sz, sqlite3_file *pFile){
  int rc, i;
  sqlite3_int64 iMark;
  int msbs = 8 * (APND_MARK_FOS_SZ-1);
  unsigned char a[APND_MARK_SIZE];

  if( sz<=APND_MARK_SIZE ) return -1;
  if( APND_MARK_SIZE!=(sz & 0x1ff) ) return -1;
  rc = pFile->pMethods->xRead(pFile, a, APND_MARK_SIZE, sz-APND_MARK_SIZE);
  if( rc ) return -1;
  if( memcmp(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ)!=0 ) return -1;
  iMark = ((sqlite3_int64)(a[APND_MARK_PREFIX_SZ]&0x7f))<<56;
  for(i=1; i<8; i++){    
    iMark += (sqlite3_int64)a[APND_MARK_PREFIX_SZ+i]<<(56-8*i);
  iMark = ((sqlite3_int64)(a[APND_MARK_PREFIX_SZ] & 0x7f)) << msbs;
  for(i=1; i<8; i++){
    msbs -= 8;
    iMark |= (sqlite3_int64)a[APND_MARK_PREFIX_SZ+i]<<msbs;
  }
  if( iMark > (sz - APND_MARK_SIZE - 512) ) return -1;
  if( iMark & 0x1ff ) return -1;
  return iMark;
}

static const char apvfsSqliteHdr[] = "SQLite format 3";
/*
** Check to see if the file is an appendvfs SQLite database file.
** Return true iff it is such. Parameter sz is the file's size.
*/
static int apndIsAppendvfsDatabase(sqlite3_int64 sz, sqlite3_file *pFile){
  int rc;
  char zHdr[16];
  sqlite3_int64 iMark = apndReadMark(sz, pFile);
  if( iMark>=0 ){
    /* If file has the correct end-marker, the expected odd size, and the
    ** SQLite DB type marker where the end-marker puts it, then it
    ** is an appendvfs database.
    */
    rc = pFile->pMethods->xRead(pFile, zHdr, sizeof(zHdr), iMark);
    if( SQLITE_OK==rc
     && memcmp(zHdr, apvfsSqliteHdr, sizeof(zHdr))==0
     && (sz & 0x1ff) == APND_MARK_SIZE
     && sz>=512+APND_MARK_SIZE
    ){
      return 1; /* It's an appendvfs database */
    }
  }
  return 0;
}

/*
** Check to see if the file is an ordinary SQLite database file.
** Return true iff so. Parameter sz is the file's size.
*/
static int apndIsOrdinaryDatabaseFile(sqlite3_int64 sz, sqlite3_file *pFile){
  char zHdr[16];
  if( apndIsAppendvfsDatabase(sz, pFile) /* rule 2 */
   || (sz & 0x1ff) != 0
   || SQLITE_OK!=pFile->pMethods->xRead(pFile, zHdr, sizeof(zHdr), 0)
   || memcmp(zHdr, apvfsSqliteHdr, sizeof(zHdr))!=0
  ){
    return 0;
  }else{
    return 1;
  }
}

/*
** Open an apnd file handle.
*/
static int apndOpen(
  sqlite3_vfs *pVfs,
  sqlite3_vfs *pApndVfs,
  const char *zName,
  sqlite3_file *pFile,
  int flags,
  int *pOutFlags
){
  ApndFile *p;
  sqlite3_file *pSubFile;
  sqlite3_vfs *pSubVfs;
  ApndFile *pApndFile = (ApndFile*)pFile;
  sqlite3_file *pBaseFile = ORIGFILE(pFile);
  sqlite3_vfs *pBaseVfs = ORIGVFS(pApndVfs);
  int rc;
  sqlite3_int64 sz;
  sqlite3_int64 sz = 0;
  pSubVfs = ORIGVFS(pVfs);
  if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){
    /* The appendvfs is not to be used for transient or temporary databases.
    ** Just use the base VFS open to initialize the given file object and
    ** open the underlying file. (Appendvfs is then unused for this file.)
    */
    return pSubVfs->xOpen(pSubVfs, zName, pFile, flags, pOutFlags);
    return pBaseVfs->xOpen(pBaseVfs, zName, pFile, flags, pOutFlags);
  }
  p = (ApndFile*)pFile;
  memset(p, 0, sizeof(*p));
  memset(pApndFile, 0, sizeof(ApndFile));
  pSubFile = ORIGFILE(pFile);
  p->base.pMethods = &apnd_io_methods;
  rc = pSubVfs->xOpen(pSubVfs, zName, pSubFile, flags, pOutFlags);
  if( rc ) goto apnd_open_done;
  rc = pSubFile->pMethods->xFileSize(pSubFile, &sz);
  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 ){
    pSubFile->pMethods->xClose(pSubFile);
    pFile->pMethods = 0;
    goto apnd_open_done;
    return rc;
  }
  if( apndIsOrdinaryDatabaseFile(sz, pSubFile) ){
    memmove(pFile, pSubFile, pSubVfs->szOsFile);
  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. 
    */
    memmove(pApndFile, pBaseFile, pBaseVfs->szOsFile);
    return SQLITE_OK;
  }
  p->iMark = 0;
  p->iPgOne = apndReadMark(sz, pFile);
  if( p->iPgOne>0 ){
  pApndFile->iPgOne = apndReadMark(sz, pFile);
  if( pApndFile->iPgOne>=0 ){
    pApndFile->iMark = sz - APND_MARK_SIZE; /* Append mark found */
    return SQLITE_OK;
  }
  if( (flags & SQLITE_OPEN_CREATE)==0 ){
    pSubFile->pMethods->xClose(pSubFile);
    pBaseFile->pMethods->xClose(pBaseFile);
    rc = SQLITE_CANTOPEN;
    pFile->pMethods = 0;
  }else{
    /* Round newly added appendvfs location to #define'd page boundary. 
    ** Note that nothing has yet been written to the underlying file.
    ** The append mark will be written along with first content write.
    ** Until then, paf->iMark value indicates it is not yet written.
    */
    pApndFile->iPgOne = APND_START_ROUNDUP(sz);
  }
  p->iPgOne = (sz+0xfff) & ~(sqlite3_int64)0xfff;
apnd_open_done:
  if( rc ) pFile->pMethods = 0;
  return rc;
}

/*
** Delete an apnd file.
** For an appendvfs, this could mean delete the appendvfs portion,
** leaving the appendee as it was before it gained an appendvfs.
** For now, this code deletes the underlying file too.
*/
static int apndDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
  return ORIGVFS(pVfs)->xDelete(ORIGVFS(pVfs), zPath, dirSync);
}

/*
** All other VFS methods are pass-thrus.
*/
static int apndDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
  return ORIGVFS(pVfs)->xDelete(ORIGVFS(pVfs), zPath, dirSync);
}
static int apndAccess(
  sqlite3_vfs *pVfs, 
  const char *zPath, 
  int flags, 
  int *pResOut
){
  return ORIGVFS(pVfs)->xAccess(ORIGVFS(pVfs), zPath, flags, pResOut);
547
548
549
550
551
552
553

554
555
556
557
558
559
560
561
562
563
564
565
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672







+












){
  int rc = SQLITE_OK;
  sqlite3_vfs *pOrig;
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg;
  (void)db;
  pOrig = sqlite3_vfs_find(0);
  if( pOrig==0 ) return SQLITE_ERROR;
  apnd_vfs.iVersion = pOrig->iVersion;
  apnd_vfs.pAppData = pOrig;
  apnd_vfs.szOsFile = pOrig->szOsFile + sizeof(ApndFile);
  rc = sqlite3_vfs_register(&apnd_vfs, 0);
#ifdef APPENDVFS_TEST
  if( rc==SQLITE_OK ){
    rc = sqlite3_auto_extension((void(*)(void))apndvfsRegister);
  }
#endif
  if( rc==SQLITE_OK ) rc = SQLITE_OK_LOAD_PERMANENTLY;
  return rc;
}

Added ext/misc/base64.c.






















































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2022-11-18
**
** 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 is a SQLite extension for converting in either direction
** between a (binary) blob and base64 text. Base64 can transit a
** sane USASCII channel unmolested. It also plays nicely in CSV or
** written as TCL brace-enclosed literals or SQL string literals,
** and can be used unmodified in XML-like documents.
**
** This is an independent implementation of conversions specified in
** RFC 4648, done on the above date by the author (Larry Brasfield)
** who thereby has the right to put this into the public domain.
**
** The conversions meet RFC 4648 requirements, provided that this
** C source specifies that line-feeds are included in the encoded
** data to limit visible line lengths to 72 characters and to
** terminate any encoded blob having non-zero length.
**
** Length limitations are not imposed except that the runtime
** SQLite string or blob length limits are respected. Otherwise,
** any length binary sequence can be represented and recovered.
** Generated base64 sequences, with their line-feeds included,
** can be concatenated; the result converted back to binary will
** be the concatenation of the represented binary sequences.
**
** This SQLite3 extension creates a function, base64(x), which
** either: converts text x containing base64 to a returned blob;
** or converts a blob x to returned text containing base64. An
** error will be thrown for other input argument types.
**
** This code relies on UTF-8 encoding only with respect to the
** meaning of the first 128 (7-bit) codes matching that of USASCII.
** It will fail miserably if somehow made to try to convert EBCDIC.
** Because it is table-driven, it could be enhanced to handle that,
** but the world and SQLite have moved on from that anachronism.
**
** To build the extension:
** Set shell variable SQDIR=<your favorite SQLite checkout directory>
** *Nix: gcc -O2 -shared -I$SQDIR -fPIC -o base64.so base64.c
** OSX: gcc -O2 -dynamiclib -fPIC -I$SQDIR -o base64.dylib base64.c
** Win32: gcc -O2 -shared -I%SQDIR% -o base64.dll base64.c
** Win32: cl /Os -I%SQDIR% base64.c -link -dll -out:base64.dll
*/

#include <assert.h>

#include "sqlite3ext.h"

#ifndef deliberate_fall_through
/* Quiet some compilers about some of our intentional code. */
# if GCC_VERSION>=7000000
#  define deliberate_fall_through __attribute__((fallthrough));
# else
#  define deliberate_fall_through
# endif
#endif

SQLITE_EXTENSION_INIT1;

#define PC 0x80 /* pad character */
#define WS 0x81 /* whitespace */
#define ND 0x82 /* Not above or digit-value */
#define PAD_CHAR '='

#ifndef U8_TYPEDEF
typedef unsigned char u8;
#define U8_TYPEDEF
#endif

static const u8 b64DigitValues[128] = {
  /*                             HT LF VT  FF CR       */
    ND,ND,ND,ND, ND,ND,ND,ND, ND,WS,WS,WS, WS,WS,ND,ND,
  /*                                                US */
    ND,ND,ND,ND, ND,ND,ND,ND, ND,ND,ND,ND, ND,ND,ND,ND,
  /*sp                                  +            / */
    WS,ND,ND,ND, ND,ND,ND,ND, ND,ND,ND,62, ND,ND,ND,63,
  /* 0  1            5            9            =       */
    52,53,54,55, 56,57,58,59, 60,61,ND,ND, ND,PC,ND,ND,
  /*    A                                            O */
    ND, 0, 1, 2,  3, 4, 5, 6,  7, 8, 9,10, 11,12,13,14,
  /* P                               Z                 */
    15,16,17,18, 19,20,21,22, 23,24,25,ND, ND,ND,ND,ND,
  /*    a                                            o */
    ND,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
  /* p                               z                 */
    41,42,43,44, 45,46,47,48, 49,50,51,ND, ND,ND,ND,ND
};

static const char b64Numerals[64+1]
= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

#define BX_DV_PROTO(c) \
  ((((u8)(c))<0x80)? (u8)(b64DigitValues[(u8)(c)]) : 0x80)
#define IS_BX_DIGIT(bdp) (((u8)(bdp))<0x80)
#define IS_BX_WS(bdp) ((bdp)==WS)
#define IS_BX_PAD(bdp) ((bdp)==PC)
#define BX_NUMERAL(dv) (b64Numerals[(u8)(dv)])
/* Width of base64 lines. Should be an integer multiple of 4. */
#define B64_DARK_MAX 72

/* Encode a byte buffer into base64 text with linefeeds appended to limit
** encoded group lengths to B64_DARK_MAX or to terminate the last group.
*/
static char* toBase64( u8 *pIn, int nbIn, char *pOut ){
  int nCol = 0;
  while( nbIn >= 3 ){
    /* Do the bit-shuffle, exploiting unsigned input to avoid masking. */
    pOut[0] = BX_NUMERAL(pIn[0]>>2);
    pOut[1] = BX_NUMERAL(((pIn[0]<<4)|(pIn[1]>>4))&0x3f);
    pOut[2] = BX_NUMERAL(((pIn[1]&0xf)<<2)|(pIn[2]>>6));
    pOut[3] = BX_NUMERAL(pIn[2]&0x3f);
    pOut += 4;
    nbIn -= 3;
    pIn += 3;
    if( (nCol += 4)>=B64_DARK_MAX || nbIn<=0 ){
      *pOut++ = '\n';
      nCol = 0;
    }
  }
  if( nbIn > 0 ){
    signed char nco = nbIn+1;
    int nbe;
    unsigned long qv = *pIn++;
    for( nbe=1; nbe<3; ++nbe ){
      qv <<= 8;
      if( nbe<nbIn ) qv |= *pIn++;
    }
    for( nbe=3; nbe>=0; --nbe ){
      char ce = (nbe<nco)? BX_NUMERAL((u8)(qv & 0x3f)) : PAD_CHAR;
      qv >>= 6;
      pOut[nbe] = ce;
    }
    pOut += 4;
    *pOut++ = '\n';
  }
  *pOut = 0;
  return pOut;
}

/* Skip over text which is not base64 numeral(s). */
static char * skipNonB64( char *s ){
  char c;
  while( (c = *s) && !IS_BX_DIGIT(BX_DV_PROTO(c)) ) ++s;
  return s;
}

/* Decode base64 text into a byte buffer. */
static u8* fromBase64( char *pIn, int ncIn, u8 *pOut ){
  if( ncIn>0 && pIn[ncIn-1]=='\n' ) --ncIn;
  while( ncIn>0 && *pIn!=PAD_CHAR ){
    static signed char nboi[] = { 0, 0, 1, 2, 3 };
    char *pUse = skipNonB64(pIn);
    unsigned long qv = 0L;
    int nti, nbo, nac;
    ncIn -= (pUse - pIn);
    pIn = pUse;
    nti = (ncIn>4)? 4 : ncIn;
    ncIn -= nti;
    nbo = nboi[nti];
    if( nbo==0 ) break;
    for( nac=0; nac<4; ++nac ){
      char c = (nac<nti)? *pIn++ : b64Numerals[0];
      u8 bdp = BX_DV_PROTO(c);
      switch( bdp ){
      case ND:
        /*  Treat dark non-digits as pad, but they terminate decode too. */
        ncIn = 0;
        deliberate_fall_through;
      case WS:
        /* Treat whitespace as pad and terminate this group.*/
        nti = nac;
        deliberate_fall_through;
      case PC:
        bdp = 0;
        --nbo;
        deliberate_fall_through;
      default: /* bdp is the digit value. */
        qv = qv<<6 | bdp;
        break;
      }
    }
    switch( nbo ){
    case 3:
      pOut[2] = (qv) & 0xff;
    case 2:
      pOut[1] = (qv>>8) & 0xff;
    case 1:
      pOut[0] = (qv>>16) & 0xff;
    }
    pOut += nbo;
  }
  return pOut;
}

/* This function does the work for the SQLite base64(x) UDF. */
static void base64(sqlite3_context *context, int na, sqlite3_value *av[]){
  int nb, nc, nv = sqlite3_value_bytes(av[0]);
  int nvMax = sqlite3_limit(sqlite3_context_db_handle(context),
                            SQLITE_LIMIT_LENGTH, -1);
  char *cBuf;
  u8 *bBuf;
  assert(na==1);
  switch( sqlite3_value_type(av[0]) ){
  case SQLITE_BLOB:
    nb = nv;
    nc = 4*(nv+2/3); /* quads needed */
    nc += (nc+(B64_DARK_MAX-1))/B64_DARK_MAX + 1; /* LFs and a 0-terminator */
    if( nvMax < nc ){
      sqlite3_result_error(context, "blob expanded to base64 too big", -1);
      return;
    }
    cBuf = sqlite3_malloc(nc);
    if( !cBuf ) goto memFail;
    bBuf = (u8*)sqlite3_value_blob(av[0]);
    nc = (int)(toBase64(bBuf, nb, cBuf) - cBuf);
    sqlite3_result_text(context, cBuf, nc, sqlite3_free);
    break;
  case SQLITE_TEXT:
    nc = nv;
    nb = 3*((nv+3)/4); /* may overestimate due to LF and padding */
    if( nvMax < nb ){
      sqlite3_result_error(context, "blob from base64 may be too big", -1);
      return;
    }else if( nb<1 ){
      nb = 1;
    }
    bBuf = sqlite3_malloc(nb);
    if( !bBuf ) goto memFail;
    cBuf = (char *)sqlite3_value_text(av[0]);
    nb = (int)(fromBase64(cBuf, nc, bBuf) - bBuf);
    sqlite3_result_blob(context, bBuf, nb, sqlite3_free);
    break;
  default:
    sqlite3_result_error(context, "base64 accepts only blob or text", -1);
    return;
  }
  return;
 memFail:
  sqlite3_result_error(context, "base64 OOM", -1);
}

/*
** Establish linkage to running SQLite library.
*/
#ifndef SQLITE_SHELL_EXTFUNCS
#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_base_init
#else
static int sqlite3_base64_init
#endif
(sqlite3 *db, char **pzErr, const sqlite3_api_routines *pApi){
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErr;
  return sqlite3_create_function
    (db, "base64", 1,
     SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS|SQLITE_DIRECTONLY|SQLITE_UTF8,
     0, base64, 0, 0);
}

/*
** Define some macros to allow this extension to be built into the shell
** conveniently, in conjunction with use of SQLITE_SHELL_EXTFUNCS. This
** allows shell.c, as distributed, to have this extension built in.
*/
#define BASE64_INIT(db) sqlite3_base64_init(db, 0, 0)
#define BASE64_EXPOSE(db, pzErr) /* Not needed, ..._init() does this. */

Added ext/misc/base85.c.





















































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2022-11-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 is a utility for converting binary to base85 or vice-versa.
** It can be built as a standalone program or an SQLite3 extension.
**
** Much like base64 representations, base85 can be sent through a
** sane USASCII channel unmolested. It also plays nicely in CSV or
** written as TCL brace-enclosed literals or SQL string literals.
** It is not suited for unmodified use in XML-like documents.
**
** The encoding used resembles Ascii85, but was devised by the author
** (Larry Brasfield) before Mozilla, Adobe, ZMODEM or other Ascii85
** variant sources existed, in the 1984 timeframe on a VAX mainframe.
** Further, this is an independent implementation of a base85 system.
** Hence, the author has rightfully put this into the public domain.
**
** Base85 numerals are taken from the set of 7-bit USASCII codes,
** excluding control characters and Space ! " ' ( ) { | } ~ Del
** in code order representing digit values 0 to 84 (base 10.)
**
** Groups of 4 bytes, interpreted as big-endian 32-bit values,
** are represented as 5-digit base85 numbers with MS to LS digit
** order. Groups of 1-3 bytes are represented with 2-4 digits,
** still big-endian but 8-24 bit values. (Using big-endian yields
** the simplest transition to byte groups smaller than 4 bytes.
** These byte groups can also be considered base-256 numbers.)
** Groups of 0 bytes are represented with 0 digits and vice-versa.
** No pad characters are used; Encoded base85 numeral sequence
** (aka "group") length maps 1-to-1 to the decoded binary length.
**
** Any character not in the base85 numeral set delimits groups.
** When base85 is streamed or stored in containers of indefinite
** size, newline is used to separate it into sub-sequences of no
** more than 80 digits so that fgets() can be used to read it.
**
** Length limitations are not imposed except that the runtime
** SQLite string or blob length limits are respected. Otherwise,
** any length binary sequence can be represented and recovered.
** Base85 sequences can be concatenated by separating them with
** a non-base85 character; the conversion to binary will then
** be the concatenation of the represented binary sequences.

** The standalone program either converts base85 on stdin to create
** a binary file or converts a binary file to base85 on stdout.
** Read or make it blurt its help for invocation details.
**
** The SQLite3 extension creates a function, base85(x), which will
** either convert text base85 to a blob or a blob to text base85
** and return the result (or throw an error for other types.)
** Unless built with OMIT_BASE85_CHECKER defined, it also creates a
** function, is_base85(t), which returns 1 iff the text t contains
** nothing other than base85 numerals and whitespace, or 0 otherwise.
**
** To build the extension:
** Set shell variable SQDIR=<your favorite SQLite checkout directory>
** and variable OPTS to -DOMIT_BASE85_CHECKER if is_base85() unwanted.
** *Nix: gcc -O2 -shared -I$SQDIR $OPTS -fPIC -o base85.so base85.c
** OSX: gcc -O2 -dynamiclib -fPIC -I$SQDIR $OPTS -o base85.dylib base85.c
** Win32: gcc -O2 -shared -I%SQDIR% %OPTS% -o base85.dll base85.c
** Win32: cl /Os -I%SQDIR% %OPTS% base85.c -link -dll -out:base85.dll
**
** To build the standalone program, define PP symbol BASE85_STANDALONE. Eg.
** *Nix or OSX: gcc -O2 -DBASE85_STANDALONE base85.c -o base85
** Win32: gcc -O2 -DBASE85_STANDALONE -o base85.exe base85.c
** Win32: cl /Os /MD -DBASE85_STANDALONE base85.c
*/

#include <stdio.h>
#include <memory.h>
#include <string.h>
#include <assert.h>
#ifndef OMIT_BASE85_CHECKER
# include <ctype.h>
#endif

#ifndef BASE85_STANDALONE

# include "sqlite3ext.h"

SQLITE_EXTENSION_INIT1;

#else

# ifdef _WIN32
#  include <io.h>
#  include <fcntl.h>
# else
#  define setmode(fd,m)
# endif

static char *zHelp =
  "Usage: base85 <dirFlag> <binFile>\n"
  " <dirFlag> is either -r to read or -w to write <binFile>,\n"
  "   content to be converted to/from base85 on stdout/stdin.\n"
  " <binFile> names a binary file to be rendered or created.\n"
  "   Or, the name '-' refers to the stdin or stdout stream.\n"
  ;

static void sayHelp(){
  printf("%s", zHelp);
}
#endif

#ifndef U8_TYPEDEF
typedef unsigned char u8;
#define U8_TYPEDEF
#endif

/* Classify c according to interval within USASCII set w.r.t. base85
 * Values of 1 and 3 are base85 numerals. Values of 0, 2, or 4 are not.
 */
#define B85_CLASS( c ) (((c)>='#')+((c)>'&')+((c)>='*')+((c)>'z'))

/* Provide digitValue to b85Numeral offset as a function of above class. */
static u8 b85_cOffset[] = { 0, '#', 0, '*'-4, 0 };
#define B85_DNOS( c ) b85_cOffset[B85_CLASS(c)]

/* Say whether c is a base85 numeral. */
#define IS_B85( c ) (B85_CLASS(c) & 1)

#if 0 /* Not used, */
static u8 base85DigitValue( char c ){
  u8 dv = (u8)(c - '#');
  if( dv>87 ) return 0xff;
  return (dv > 3)? dv-3 : dv;
}
#endif

/* Width of base64 lines. Should be an integer multiple of 5. */
#define B85_DARK_MAX 80


static char * skipNonB85( char *s ){
  char c;
  while( (c = *s) && !IS_B85(c) ) ++s;
  return s;
}

/* Convert small integer, known to be in 0..84 inclusive, to base85 numeral.
 * Do not use the macro form with argument expression having a side-effect.*/
#if 0
static char base85Numeral( u8 b ){
  return (b < 4)? (char)(b + '#') : (char)(b - 4 + '*');
}
#else
# define base85Numeral( dn )\
  ((char)(((dn) < 4)? (char)((dn) + '#') : (char)((dn) - 4 + '*')))
#endif

static char *putcs(char *pc, char *s){
  char c;
  while( (c = *s++)!=0 ) *pc++ = c;
  return pc;
}

/* Encode a byte buffer into base85 text. If pSep!=0, it's a C string
** to be appended to encoded groups to limit their length to B85_DARK_MAX
** or to terminate the last group (to aid concatenation.)
*/
static char* toBase85( u8 *pIn, int nbIn, char *pOut, char *pSep ){
  int nCol = 0;
  while( nbIn >= 4 ){
    int nco = 5;
    unsigned long qbv = (((unsigned long)pIn[0])<<24) |
                        (pIn[1]<<16) | (pIn[2]<<8) | pIn[3];
    while( nco > 0 ){
      unsigned nqv = (unsigned)(qbv/85UL);
      unsigned char dv = qbv - 85UL*nqv;
      qbv = nqv;
      pOut[--nco] = base85Numeral(dv);
    }
    nbIn -= 4;
    pIn += 4;
    pOut += 5;
    if( pSep && (nCol += 5)>=B85_DARK_MAX ){
      pOut = putcs(pOut, pSep);
      nCol = 0;
    }
  }
  if( nbIn > 0 ){
    int nco = nbIn + 1;
    unsigned long qv = *pIn++;
    int nbe = 1;
    while( nbe++ < nbIn ){
      qv = (qv<<8) | *pIn++;
    }
    nCol += nco;
    while( nco > 0 ){
      u8 dv = (u8)(qv % 85);
      qv /= 85;
      pOut[--nco] = base85Numeral(dv);
    }
    pOut += (nbIn+1);
  }
  if( pSep && nCol>0 ) pOut = putcs(pOut, pSep);
  *pOut = 0;
  return pOut;
}

/* Decode base85 text into a byte buffer. */
static u8* fromBase85( char *pIn, int ncIn, u8 *pOut ){
  if( ncIn>0 && pIn[ncIn-1]=='\n' ) --ncIn;
  while( ncIn>0 ){
    static signed char nboi[] = { 0, 0, 1, 2, 3, 4 };
    char *pUse = skipNonB85(pIn);
    unsigned long qv = 0L;
    int nti, nbo;
    ncIn -= (pUse - pIn);
    pIn = pUse;
    nti = (ncIn>5)? 5 : ncIn;
    nbo = nboi[nti];
    if( nbo==0 ) break;
    while( nti>0 ){
      char c = *pIn++;
      u8 cdo = B85_DNOS(c);
      --ncIn;
      if( cdo==0 ) break;
      qv = 85 * qv + (c - cdo);
      --nti;
    }
    nbo -= nti; /* Adjust for early (non-digit) end of group. */
    switch( nbo ){
    case 4:
      *pOut++ = (qv >> 24)&0xff;
    case 3:
      *pOut++ = (qv >> 16)&0xff;
    case 2:
      *pOut++ = (qv >> 8)&0xff;
    case 1:
      *pOut++ = qv&0xff;
    case 0:
      break;
    }
  }
  return pOut;
}

#ifndef OMIT_BASE85_CHECKER
/* Say whether input char sequence is all (base85 and/or whitespace).*/
static int allBase85( char *p, int len ){
  char c;
  while( len-- > 0 && (c = *p++) != 0 ){
    if( !IS_B85(c) && !isspace(c) ) return 0;
  }
  return 1;
}
#endif

#ifndef BASE85_STANDALONE

# ifndef OMIT_BASE85_CHECKER
/* This function does the work for the SQLite is_base85(t) UDF. */
static void is_base85(sqlite3_context *context, int na, sqlite3_value *av[]){
  assert(na==1);
  switch( sqlite3_value_type(av[0]) ){
  case SQLITE_TEXT:
    {
      int rv = allBase85( (char *)sqlite3_value_text(av[0]),
                          sqlite3_value_bytes(av[0]) );
      sqlite3_result_int(context, rv);
    }
    break;
  case SQLITE_NULL:
    sqlite3_result_null(context);
    break;
  default:
    sqlite3_result_error(context, "is_base85 accepts only text or NULL", -1);
    return;
  }
}
# endif

/* This function does the work for the SQLite base85(x) UDF. */
static void base85(sqlite3_context *context, int na, sqlite3_value *av[]){
  int nb, nc, nv = sqlite3_value_bytes(av[0]);
  int nvMax = sqlite3_limit(sqlite3_context_db_handle(context),
                            SQLITE_LIMIT_LENGTH, -1);
  char *cBuf;
  u8 *bBuf;
  assert(na==1);
  switch( sqlite3_value_type(av[0]) ){
  case SQLITE_BLOB:
    nb = nv;
    /*    ulongs    tail   newlines  tailenc+nul*/
    nc = 5*(nv/4) + nv%4 + nv/64+1 + 2;
    if( nvMax < nc ){
      sqlite3_result_error(context, "blob expanded to base85 too big", -1);
      return;
    }
    cBuf = sqlite3_malloc(nc);
    if( !cBuf ) goto memFail;
    bBuf = (u8*)sqlite3_value_blob(av[0]);
    nc = (int)(toBase85(bBuf, nb, cBuf, "\n") - cBuf);
    sqlite3_result_text(context, cBuf, nc, sqlite3_free);
    break;
  case SQLITE_TEXT:
    nc = nv;
    nb = 4*(nv/5) + nv%5; /* may overestimate */
    if( nvMax < nb ){
      sqlite3_result_error(context, "blob from base85 may be too big", -1);
      return;
    }else if( nb<1 ){
      nb = 1;
    }
    bBuf = sqlite3_malloc(nb);
    if( !bBuf ) goto memFail;
    cBuf = (char *)sqlite3_value_text(av[0]);
    nb = (int)(fromBase85(cBuf, nc, bBuf) - bBuf);
    sqlite3_result_blob(context, bBuf, nb, sqlite3_free);
    break;
  default:
    sqlite3_result_error(context, "base85 accepts only blob or text.", -1);
    return;
  }
  return;
 memFail:
  sqlite3_result_error(context, "base85 OOM", -1);
}

/*
** Establish linkage to running SQLite library.
*/
#ifndef SQLITE_SHELL_EXTFUNCS
#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_base_init
#else
static int sqlite3_base85_init
#endif
(sqlite3 *db, char **pzErr, const sqlite3_api_routines *pApi){
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErr;
# ifndef OMIT_BASE85_CHECKER
  {
    int rc = sqlite3_create_function
      (db, "is_base85", 1,
       SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS|SQLITE_UTF8,
       0, is_base85, 0, 0);
    if( rc!=SQLITE_OK ) return rc;
  }
# endif
  return sqlite3_create_function
    (db, "base85", 1,
     SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS|SQLITE_DIRECTONLY|SQLITE_UTF8,
     0, base85, 0, 0);
}

/*
** Define some macros to allow this extension to be built into the shell
** conveniently, in conjunction with use of SQLITE_SHELL_EXTFUNCS. This
** allows shell.c, as distributed, to have this extension built in.
*/
# define BASE85_INIT(db) sqlite3_base85_init(db, 0, 0)
# define BASE85_EXPOSE(db, pzErr) /* Not needed, ..._init() does this. */

#else /* standalone program */

int main(int na, char *av[]){
  int cin;
  int rc = 0;
  u8 bBuf[4*(B85_DARK_MAX/5)];
  char cBuf[5*(sizeof(bBuf)/4)+2];
  size_t nio;
# ifndef OMIT_BASE85_CHECKER
  int b85Clean = 1;
# endif
  char rw;
  FILE *fb = 0, *foc = 0;
  char fmode[3] = "xb";
  if( na < 3 || av[1][0]!='-' || (rw = av[1][1])==0 || (rw!='r' && rw!='w') ){
    sayHelp();
    return 0;
  }
  fmode[0] = rw;
  if( av[2][0]=='-' && av[2][1]==0 ){
    switch( rw ){
    case 'r':
      fb = stdin;
      setmode(fileno(stdin), O_BINARY);
      break;
    case 'w':
      fb = stdout;
      setmode(fileno(stdout), O_BINARY);
      break;
    }
  }else{
    fb = fopen(av[2], fmode);
    foc = fb;
  }
  if( !fb ){
    fprintf(stderr, "Cannot open %s for %c\n", av[2], rw);
    rc = 1;
  }else{
    switch( rw ){
    case 'r':
      while( (nio = fread( bBuf, 1, sizeof(bBuf), fb))>0 ){
        toBase85( bBuf, (int)nio, cBuf, 0 );
        fprintf(stdout, "%s\n", cBuf);
      }
      break;
    case 'w':
      while( 0 != fgets(cBuf, sizeof(cBuf), stdin) ){
        int nc = strlen(cBuf);
        size_t nbo = fromBase85( cBuf, nc, bBuf ) - bBuf;
        if( 1 != fwrite(bBuf, nbo, 1, fb) ) rc = 1;
# ifndef OMIT_BASE85_CHECKER
        b85Clean &= allBase85( cBuf, nc );
# endif
      }
      break;
    default:
      sayHelp();
      rc = 1;
    }
    if( foc ) fclose(foc);
  }
# ifndef OMIT_BASE85_CHECKER
  if( !b85Clean ){
    fprintf(stderr, "Base85 input had non-base85 dark or control content.\n");
  }
# endif
  return rc;
}

#endif

Added ext/misc/basexx.c.























































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2022-11-20
**
** 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 source allows multiple SQLite extensions to be either: combined
** into a single runtime-loadable library; or built into the SQLite shell
** using a preprocessing convention set by src/shell.c.in (and shell.c).
**
** Presently, it combines the base64.c and base85.c extensions. However,
** it can be used as a template for other combinations.
**
** Example usages:
**
**  - Build a runtime-loadable extension from SQLite checkout directory:
** *Nix, OSX: gcc -O2 -shared -I. -fPIC -o basexx.so ext/misc/basexx.c
** Win32: cl /Os -I. ext/misc/basexx.c -link -dll -out:basexx.dll
**
**  - Incorporate as built-in in sqlite3 shell:
** *Nix, OSX with gcc on a like platform:
**  export mop1=-DSQLITE_SHELL_EXTSRC=ext/misc/basexx.c
**  export mop2=-DSQLITE_SHELL_EXTFUNCS=BASEXX
**  make sqlite3 "OPTS=$mop1 $mop2"
** Win32 with Microsoft toolset on Windows:
**  set mop1=-DSQLITE_SHELL_EXTSRC=ext/misc/basexx.c
**  set mop2=-DSQLITE_SHELL_EXTFUNCS=BASEXX
**  set mops="OPTS=%mop1% %mop2%"
**  nmake -f Makefile.msc sqlite3.exe %mops%
*/

#ifndef SQLITE_SHELL_EXTFUNCS /* Guard for #include as built-in extension. */
# include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1;
#endif

static void init_api_ptr(const sqlite3_api_routines *pApi){
  SQLITE_EXTENSION_INIT2(pApi);
}

#undef SQLITE_EXTENSION_INIT1
#define SQLITE_EXTENSION_INIT1 /* */
#undef SQLITE_EXTENSION_INIT2
#define SQLITE_EXTENSION_INIT2(v) (void)v

typedef unsigned char u8;
#define U8_TYPEDEF

/* These next 2 undef's are only needed because the entry point names
 * collide when formulated per the rules stated for loadable extension
 * entry point names that will be deduced from the file basenames.
 */
#undef sqlite3_base_init
#define sqlite3_base_init sqlite3_base64_init
#include "base64.c"

#undef sqlite3_base_init
#define sqlite3_base_init sqlite3_base85_init
#include "base85.c"

#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_basexx_init(sqlite3 *db, char **pzErr,
                               const sqlite3_api_routines *pApi){
  init_api_ptr(pApi);
  int rc1 = BASE64_INIT(db);
  int rc2 = BASE85_INIT(db);

  if( rc1==SQLITE_OK && rc2==SQLITE_OK ){
    BASE64_EXPOSE(db, pzErr);
    BASE64_EXPOSE(db, pzErr);
    return SQLITE_OK;
  }else{
    return SQLITE_ERROR;
  }
}

# define BASEXX_INIT(db) sqlite3_basexx_init(db, 0, 0)
# define BASEXX_EXPOSE(db, pzErr) /* Not needed, ..._init() does this. */

Added ext/misc/bgckpt.c.





















































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2017-10-11
**
** 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.
**
******************************************************************************
**
*/

#if !defined(SQLITE_TEST) || defined(SQLITE_OS_UNIX)

#include "sqlite3.h"
#include <string.h>
#include <pthread.h>

/*
** API declarations.
*/
typedef struct Checkpointer Checkpointer;
int sqlite3_bgckpt_create(const char *zFilename, Checkpointer **pp);
int sqlite3_bgckpt_checkpoint(Checkpointer *p, int bBlock);
void sqlite3_bgckpt_destroy(Checkpointer *p);


struct Checkpointer {
  sqlite3 *db;                    /* Database handle */

  pthread_t thread;               /* Background thread */
  pthread_mutex_t mutex;
  pthread_cond_t cond;

  int rc;                         /* Error from "PRAGMA wal_checkpoint" */
  int bCkpt;                      /* True if checkpoint requested */
  int bExit;                      /* True if exit requested */
};

static void *bgckptThreadMain(void *pCtx){
  int rc = SQLITE_OK;
  Checkpointer *p = (Checkpointer*)pCtx;

  while( rc==SQLITE_OK ){
    int bExit;

    pthread_mutex_lock(&p->mutex);
    if( p->bCkpt==0 && p->bExit==0 ){
      pthread_cond_wait(&p->cond, &p->mutex);
    }
    p->bCkpt = 0;
    bExit = p->bExit;
    pthread_mutex_unlock(&p->mutex);

    if( bExit ) break;
    rc = sqlite3_exec(p->db, "PRAGMA wal_checkpoint", 0, 0, 0);
    if( rc==SQLITE_BUSY ){
      rc = SQLITE_OK;
    }
  }

  pthread_mutex_lock(&p->mutex);
  p->rc = rc;
  pthread_mutex_unlock(&p->mutex);
  return 0;
}

void sqlite3_bgckpt_destroy(Checkpointer *p){
  if( p ){
    void *ret = 0;

    /* Signal the background thread to exit */
    pthread_mutex_lock(&p->mutex);
    p->bExit = 1;
    pthread_cond_broadcast(&p->cond);
    pthread_mutex_unlock(&p->mutex);

    pthread_join(p->thread, &ret);
    sqlite3_close(p->db);
    sqlite3_free(p);
  }
}


int sqlite3_bgckpt_create(const char *zFilename, Checkpointer **pp){
  Checkpointer *pNew = 0;
  int rc;

  pNew = (Checkpointer*)sqlite3_malloc(sizeof(Checkpointer));
  if( pNew==0 ){
    rc = SQLITE_NOMEM;
  }else{
    memset(pNew, 0, sizeof(Checkpointer));
    rc = sqlite3_open(zFilename, &pNew->db);
  }

  if( rc==SQLITE_OK ){
    pthread_mutex_init(&pNew->mutex, 0);
    pthread_cond_init(&pNew->cond, 0);
    pthread_create(&pNew->thread, 0, bgckptThreadMain, (void*)pNew);
  }

  if( rc!=SQLITE_OK ){
    sqlite3_bgckpt_destroy(pNew);
    pNew = 0;
  }
  *pp = pNew;
  return rc;
}

int sqlite3_bgckpt_checkpoint(Checkpointer *p, int bBlock){
  int rc;
  pthread_mutex_lock(&p->mutex);
  rc = p->rc;
  if( rc==SQLITE_OK ){
    p->bCkpt = 1;
    pthread_cond_broadcast(&p->cond);
  }
  pthread_mutex_unlock(&p->mutex);
  return rc;
}

#ifdef SQLITE_TEST

#if defined(INCLUDE_SQLITE_TCL_H)
#  include "sqlite_tcl.h"
#else
#  include "tcl.h"
#  ifndef SQLITE_TCLAPI
#    define SQLITE_TCLAPI
#  endif
#endif

const char *sqlite3ErrName(int rc);

static void SQLITE_TCLAPI bgckpt_del(void * clientData){
  Checkpointer *pCkpt = (Checkpointer*)clientData;
  sqlite3_bgckpt_destroy(pCkpt);
}

/*
** Tclcmd: $ckpt SUBCMD ...
*/
static int SQLITE_TCLAPI bgckpt_obj_cmd(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  Checkpointer *pCkpt = (Checkpointer*)clientData;
  const char *aCmd[] = { "checkpoint", "destroy", 0 };
  int iCmd;

  if( objc<2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "SUBCMD ...");
    return TCL_ERROR;
  }

  if( Tcl_GetIndexFromObj(interp, objv[1], aCmd, "sub-command", 0, &iCmd) ){
    return TCL_ERROR;
  }

  switch( iCmd ){
    case 0: {
      int rc;
      int bBlock = 0;

      if( objc>3 ){
        Tcl_WrongNumArgs(interp, 2, objv, "?BLOCKING?");
        return TCL_ERROR;
      }
      if( objc==3 && Tcl_GetBooleanFromObj(interp, objv[2], &bBlock) ){
        return TCL_ERROR;
      }

      rc = sqlite3_bgckpt_checkpoint(pCkpt, bBlock);
      if( rc!=SQLITE_OK ){
        Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
        return TCL_ERROR;
      }
      break;
    }

    case 1: {
      Tcl_DeleteCommand(interp, Tcl_GetString(objv[0]));
      break;
    }
  }

  return TCL_OK;
}

/*
** Tclcmd: bgckpt CMDNAME FILENAME
*/
static int SQLITE_TCLAPI bgckpt_cmd(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  const char *zCmd;
  const char *zFilename;
  int rc;
  Checkpointer *pCkpt;

  if( objc!=3 ){
    Tcl_WrongNumArgs(interp, 1, objv, "CMDNAME FILENAME");
    return TCL_ERROR;
  }
  zCmd = Tcl_GetString(objv[1]);
  zFilename = Tcl_GetString(objv[2]);

  rc = sqlite3_bgckpt_create(zFilename, &pCkpt);
  if( rc!=SQLITE_OK ){
    Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
    return TCL_ERROR;
  }

  Tcl_CreateObjCommand(interp, zCmd, bgckpt_obj_cmd, (void*)pCkpt, bgckpt_del);
  Tcl_SetObjResult(interp, objv[1]);
  return TCL_OK;
}

int Bgckpt_Init(Tcl_Interp *interp){
  Tcl_CreateObjCommand(interp, "bgckpt", bgckpt_cmd, 0, 0);
  return TCL_OK;
}
#endif   /* SQLITE_TEST */

#else
#if defined(INCLUDE_SQLITE_TCL_H)
#  include "sqlite_tcl.h"
#else
#  include "tcl.h"
#  ifndef SQLITE_TCLAPI
#    define SQLITE_TCLAPI
#  endif
#endif
int Bgckpt_Init(Tcl_Interp *interp){ return TCL_OK; }
#endif

Added ext/misc/blobio.c.

























































































































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2019-03-30
**
** 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.
**
******************************************************************************
**
** An SQL function that uses the incremental BLOB I/O mechanism of SQLite
** to read or write part of a blob.  This is intended for debugging use
** in the CLI.
**
**      readblob(SCHEMA,TABLE,COLUMN,ROWID,OFFSET,N)
**
** Returns N bytes of the blob starting at OFFSET.
**
**      writeblob(SCHEMA,TABLE,COLUMN,ROWID,OFFSET,NEWDATA)
**
** NEWDATA must be a blob.  The content of NEWDATA overwrites the
** existing BLOB data at SCHEMA.TABLE.COLUMN for row ROWID beginning
** at OFFSET bytes into the blob.
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>

static void readblobFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  sqlite3_blob *pBlob = 0;
  const char *zSchema;
  const char *zTable;
  const char *zColumn;
  sqlite3_int64 iRowid;
  int iOfst;
  unsigned char *aData;
  int nData;
  sqlite3 *db;
  int rc;

  zSchema = (const char*)sqlite3_value_text(argv[0]);
  zTable = (const char*)sqlite3_value_text(argv[1]);
  if( zTable==0 ){
    sqlite3_result_error(context, "bad table name", -1);
    return;
  }
  zColumn = (const char*)sqlite3_value_text(argv[2]);
  if( zTable==0 ){
    sqlite3_result_error(context, "bad column name", -1);
    return;
  }
  iRowid = sqlite3_value_int64(argv[3]);
  iOfst = sqlite3_value_int(argv[4]);
  nData = sqlite3_value_int(argv[5]);
  if( nData<=0 ) return;
  aData = sqlite3_malloc64( nData+1 );
  if( aData==0 ){
    sqlite3_result_error_nomem(context);
    return;
  }
  db = sqlite3_context_db_handle(context);
  rc = sqlite3_blob_open(db, zSchema, zTable, zColumn, iRowid, 0, &pBlob);
  if( rc ){
    sqlite3_free(aData);
    sqlite3_result_error(context, "cannot open BLOB pointer", -1);
    return;
  }
  rc = sqlite3_blob_read(pBlob, aData, nData, iOfst);
  sqlite3_blob_close(pBlob);
  if( rc ){
    sqlite3_free(aData);
    sqlite3_result_error(context, "BLOB read failed", -1);
  }else{
    sqlite3_result_blob(context, aData, nData, sqlite3_free);
  }
}    

static void writeblobFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  sqlite3_blob *pBlob = 0;
  const char *zSchema;
  const char *zTable;
  const char *zColumn;
  sqlite3_int64 iRowid;
  int iOfst;
  unsigned char *aData;
  int nData;
  sqlite3 *db;
  int rc;

  zSchema = (const char*)sqlite3_value_text(argv[0]);
  zTable = (const char*)sqlite3_value_text(argv[1]);
  if( zTable==0 ){
    sqlite3_result_error(context, "bad table name", -1);
    return;
  }
  zColumn = (const char*)sqlite3_value_text(argv[2]);
  if( zTable==0 ){
    sqlite3_result_error(context, "bad column name", -1);
    return;
  }
  iRowid = sqlite3_value_int64(argv[3]);
  iOfst = sqlite3_value_int(argv[4]);
  if( sqlite3_value_type(argv[5])!=SQLITE_BLOB ){
    sqlite3_result_error(context, "6th argument must be a BLOB", -1);
    return;
  }
  nData = sqlite3_value_bytes(argv[5]);
  aData = (unsigned char *)sqlite3_value_blob(argv[5]);
  db = sqlite3_context_db_handle(context);
  rc = sqlite3_blob_open(db, zSchema, zTable, zColumn, iRowid, 1, &pBlob);
  if( rc ){
    sqlite3_result_error(context, "cannot open BLOB pointer", -1);
    return;
  }
  rc = sqlite3_blob_write(pBlob, aData, nData, iOfst);
  sqlite3_blob_close(pBlob);
  if( rc ){
    sqlite3_result_error(context, "BLOB write failed", -1);
  }
}    


#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_blobio_init(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg;  /* Unused parameter */
  rc = sqlite3_create_function(db, "readblob", 6, SQLITE_UTF8, 0,
                               readblobFunc, 0, 0);
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "writeblob", 6, SQLITE_UTF8, 0,
                               writeblobFunc, 0, 0);
  }
  return rc;
}

Changes to ext/misc/btreeinfo.c.

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







-
+

-
+






-
+

-
+







** The schema is like this:
**
** CREATE TABLE sqlite_btreeinfo(
**    type TEXT,                   -- "table" or "index"
**    name TEXT,                   -- Name of table or index for this btree.
**    tbl_name TEXT,               -- Associated table
**    rootpage INT,                -- The root page of the btree
**    sql TEXT,                    -- SQL for this btree - from sqlite_master
**    sql TEXT,                    -- SQL for this btree - from sqlite_schema
**    hasRowid BOOLEAN,            -- True if the btree has a rowid
**    nEntry INT,                  -- Estimated number of enteries
**    nEntry INT,                  -- Estimated number of entries
**    nPage INT,                   -- Estimated number of pages
**    depth INT,                   -- Depth of the btree
**    szPage INT,                  -- Size of each page in bytes
**    zSchema TEXT HIDDEN          -- The schema to which this btree belongs
** );
**
** The first 5 fields are taken directly from the sqlite_master table.
** The first 5 fields are taken directly from the sqlite_schema table.
** Considering only the first 5 fields, the only difference between 
** this virtual table and the sqlite_master table is that this virtual
** this virtual table and the sqlite_schema table is that this virtual
** table omits all entries that have a 0 or NULL rowid - in other words
** it omits triggers and views.
**
** The value added by this table comes in the next 5 fields.
**
** Note that nEntry and nPage are *estimated*.  They are computed doing
** a single search from the root to a leaf, counting the number of cells
84
85
86
87
88
89
90
91

92
93
94
95
96
97
98
84
85
86
87
88
89
90

91
92
93
94
95
96
97
98







-
+







/* Forward declarations */
typedef struct BinfoTable BinfoTable;
typedef struct BinfoCursor BinfoCursor;

/* A cursor for the sqlite_btreeinfo table */
struct BinfoCursor {
  sqlite3_vtab_cursor base;       /* Base class.  Must be first */
  sqlite3_stmt *pStmt;            /* Query against sqlite_master */
  sqlite3_stmt *pStmt;            /* Query against sqlite_schema */
  int rc;                         /* Result of previous sqlite_step() call */
  int hasRowid;                   /* hasRowid value.  Negative if unknown. */
  sqlite3_int64 nEntry;           /* nEntry value */
  int nPage;                      /* nPage value */
  int depth;                      /* depth value */
  int szPage;                     /* size of a btree page.  0 if unknown */
  char *zSchema;                  /* Schema being interrogated */
238
239
240
241
242
243
244
245

246
247
248

249
250
251
252
253
254
255
238
239
240
241
242
243
244

245
246
247

248
249
250
251
252
253
254
255







-
+


-
+







  sqlite3_free(pCsr->zSchema);
  if( idxNum==1 && sqlite3_value_type(argv[0])!=SQLITE_NULL ){
    pCsr->zSchema = sqlite3_mprintf("%s", sqlite3_value_text(argv[0]));
  }else{
    pCsr->zSchema = sqlite3_mprintf("main");
  }
  zSql = sqlite3_mprintf(
      "SELECT 0, 'table','sqlite_master','sqlite_master',1,NULL "
      "SELECT 0, 'table','sqlite_schema','sqlite_schema',1,NULL "
      "UNION ALL "
      "SELECT rowid, type, name, tbl_name, rootpage, sql"
      " FROM \"%w\".sqlite_master WHERE rootpage>=1",
      " FROM \"%w\".sqlite_schema WHERE rootpage>=1",
       pCsr->zSchema);
  sqlite3_finalize(pCsr->pStmt);
  pCsr->pStmt = 0;
  pCsr->hasRowid = -1;
  rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pStmt, 0);
  sqlite3_free(zSql);
  if( rc==SQLITE_OK ){

Changes to ext/misc/carray.c.

20
21
22
23
24
25
26
27

28
29
30
31

32
33
34
35
36
37
38
20
21
22
23
24
25
26

27
28
29
30

31
32
33
34
35
36
37
38







-
+



-
+







** at the address $ptr.  $ptr is a pointer to the array of integers.
** The pointer value must be assigned to $ptr using the
** sqlite3_bind_pointer() interface with a pointer type of "carray".
** For example:
**
**    static int aX[] = { 53, 9, 17, 2231, 4, 99 };
**    int i = sqlite3_bind_parameter_index(pStmt, "$ptr");
**    sqlite3_bind_value(pStmt, i, aX, "carray", 0);
**    sqlite3_bind_pointer(pStmt, i, aX, "carray", 0);
**
** There is an optional third parameter to determine the datatype of
** the C-language array.  Allowed values of the third parameter are
** 'int32', 'int64', 'double', 'char*'.  Example:
** 'int32', 'int64', 'double', 'char*', 'struct iovec'.  Example:
**
**      SELECT * FROM carray($ptr,10,'char*');
**
** The default value of the third parameter is 'int32'.
**
** HOW IT WORKS
**
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
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







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




-
+

-
-
+
+
-
-


-
+

+
+
-
+
+
+
+
+







** as the number of elements in the array.  The virtual table steps through
** the array, element by element.
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
#ifdef _WIN32
  struct iovec {
    void *iov_base;
    size_t iov_len;
  };
#else
# include <sys/uio.h>
#endif
 
/* Allowed values for the mFlags parameter to sqlite3_carray_bind().
** Must exactly match the definitions in carray.h.
*/
#ifndef CARRAY_INT32
# define CARRAY_INT32     0      /* Data is 32-bit signed integers */
# define CARRAY_INT64     1      /* Data is 64-bit signed integers */
# define CARRAY_DOUBLE    2      /* Data is doubles */
# define CARRAY_TEXT      3      /* Data is char* */
# define CARRAY_BLOB      4      /* Data is struct iovec* */
#endif

#ifndef SQLITE_API
# ifdef _WIN32
#  define SQLITE_API __declspec(dllexport)
# else
#  define SQLITE_API
# endif
#endif

#ifndef SQLITE_OMIT_VIRTUALTABLE

/*
** Allowed datatypes
** Names of allowed datatypes
*/
#define CARRAY_INT32    0
#define CARRAY_INT64    1
static const char *azType[] = { "int32", "int64", "double", "char*",
                                "struct iovec" };
#define CARRAY_DOUBLE   2
#define CARRAY_TEXT     3

/*
** Names of types
** Structure used to hold the sqlite3_carray_bind() information
*/
typedef struct carray_bind carray_bind;
struct carray_bind {
static const char *azType[] = { "int32", "int64", "double", "char*" };
  void *aData;                /* The data */
  int nData;                  /* Number of elements */
  int mFlags;                 /* Control flags */
  void (*xDel)(void*);        /* Destructor for aData */
};


/* carray_cursor is a subclass of sqlite3_vtab_cursor which will
** serve as the underlying representation of a cursor that scans
** over rows of the result
*/
typedef struct carray_cursor carray_cursor;
199
200
201
202
203
204
205






206
207
208
209
210
211
212
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249







+
+
+
+
+
+







          return SQLITE_OK;
        }
        case CARRAY_TEXT: {
          const char **p = (const char**)pCur->pPtr;
          sqlite3_result_text(ctx, p[pCur->iRowid-1], -1, SQLITE_TRANSIENT);
          return SQLITE_OK;
        }
        case CARRAY_BLOB: {
          const struct iovec *p = (struct iovec*)pCur->pPtr;
          sqlite3_result_blob(ctx, p[pCur->iRowid-1].iov_base,
                               (int)p[pCur->iRowid-1].iov_len, SQLITE_TRANSIENT);
          return SQLITE_OK;
        }
      }
    }
  }
  sqlite3_result_int64(ctx, x);
  return SQLITE_OK;
}

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







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














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







*/
static int carrayFilter(
  sqlite3_vtab_cursor *pVtabCursor, 
  int idxNum, const char *idxStr,
  int argc, sqlite3_value **argv
){
  carray_cursor *pCur = (carray_cursor *)pVtabCursor;
  pCur->pPtr = 0;
  pCur->iCnt = 0;
  if( idxNum ){
    pCur->pPtr = sqlite3_value_pointer(argv[0], "carray");
    pCur->iCnt = pCur->pPtr ? sqlite3_value_int64(argv[1]) : 0;
    if( idxNum<3 ){
      pCur->eType = CARRAY_INT32;
    }else{
      unsigned char i;
      const char *zType = (const char*)sqlite3_value_text(argv[2]);
      for(i=0; i<sizeof(azType)/sizeof(azType[0]); i++){
        if( sqlite3_stricmp(zType, azType[i])==0 ) break;
      }
      if( i>=sizeof(azType)/sizeof(azType[0]) ){
        pVtabCursor->pVtab->zErrMsg = sqlite3_mprintf(
          "unknown datatype: %Q", zType);
        return SQLITE_ERROR;
      }else{
        pCur->eType = i;
      }
    }
  }else{
  switch( idxNum ){
    case 1: {
      carray_bind *pBind = sqlite3_value_pointer(argv[0], "carray-bind");
      if( pBind==0 ) break;
      pCur->pPtr = pBind->aData;
      pCur->iCnt = pBind->nData;
      pCur->eType = pBind->mFlags & 0x07;
      break;
    }
    case 2:
    case 3: {
      pCur->pPtr = sqlite3_value_pointer(argv[0], "carray");
      pCur->iCnt = pCur->pPtr ? sqlite3_value_int64(argv[1]) : 0;
      if( idxNum<3 ){
        pCur->eType = CARRAY_INT32;
      }else{
        unsigned char i;
        const char *zType = (const char*)sqlite3_value_text(argv[2]);
        for(i=0; i<sizeof(azType)/sizeof(azType[0]); i++){
          if( sqlite3_stricmp(zType, azType[i])==0 ) break;
        }
        if( i>=sizeof(azType)/sizeof(azType[0]) ){
          pVtabCursor->pVtab->zErrMsg = sqlite3_mprintf(
            "unknown datatype: %Q", zType);
          return SQLITE_ERROR;
        }else{
          pCur->eType = i;
        }
      }
      break;
    pCur->pPtr = 0;
    pCur->iCnt = 0;
    }
  }
  pCur->iRowid = 1;
  return SQLITE_OK;
}

/*
** SQLite will invoke this method one or more times while planning a query
** that uses the carray virtual table.  This routine needs to create
** a query plan for each invocation and compute an estimated cost for that
** plan.
**
** In this implementation idxNum is used to represent the
** query plan.  idxStr is unused.
**
** idxNum is:
**
**    1    If only the pointer= constraint exists.  In this case, the
**         parameter must be bound using sqlite3_carray_bind().
**
** idxNum is 2 if the pointer= and count= constraints exist,
** 3 if the ctype= constraint also exists, and is 0 otherwise.
** If idxNum is 0, then carray becomes an empty table.
**    2    if the pointer= and count= constraints exist.
**
**    3    if the ctype= constraint also exists.
**
** idxNum is 0 otherwise and carray becomes an empty table.
*/
static int carrayBestIndex(
  sqlite3_vtab *tab,
  sqlite3_index_info *pIdxInfo
){
  int i;                 /* Loop over constraints */
  int ptrIdx = -1;       /* Index of the pointer= constraint, or -1 if none */
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
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







-
+


-
-


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







        cntIdx = i;
        break;
      case CARRAY_COLUMN_CTYPE:
        ctypeIdx = i;
        break;
    }
  }
  if( ptrIdx>=0 && cntIdx>=0 ){
  if( ptrIdx>=0 ){
    pIdxInfo->aConstraintUsage[ptrIdx].argvIndex = 1;
    pIdxInfo->aConstraintUsage[ptrIdx].omit = 1;
    pIdxInfo->aConstraintUsage[cntIdx].argvIndex = 2;
    pIdxInfo->aConstraintUsage[cntIdx].omit = 1;
    pIdxInfo->estimatedCost = (double)1;
    pIdxInfo->estimatedRows = 100;
    pIdxInfo->idxNum = 1;
    if( cntIdx>=0 ){
      pIdxInfo->aConstraintUsage[cntIdx].argvIndex = 2;
      pIdxInfo->aConstraintUsage[cntIdx].omit = 1;
    pIdxInfo->idxNum = 2;
    if( ctypeIdx>=0 ){
      pIdxInfo->aConstraintUsage[ctypeIdx].argvIndex = 3;
      pIdxInfo->aConstraintUsage[ctypeIdx].omit = 1;
      pIdxInfo->idxNum = 3;
      pIdxInfo->idxNum = 2;
      if( ctypeIdx>=0 ){
        pIdxInfo->aConstraintUsage[ctypeIdx].argvIndex = 3;
        pIdxInfo->aConstraintUsage[ctypeIdx].omit = 1;
        pIdxInfo->idxNum = 3;
      }
    }
  }else{
    pIdxInfo->estimatedCost = (double)2147483647;
    pIdxInfo->estimatedRows = 2147483647;
    pIdxInfo->idxNum = 0;
  }
  return SQLITE_OK;
348
349
350
351
352
353
354































































































355
356
357
358
359
360
361
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







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







  0,                         /* xBegin */
  0,                         /* xSync */
  0,                         /* xCommit */
  0,                         /* xRollback */
  0,                         /* xFindMethod */
  0,                         /* xRename */
};

/*
** Destructor for the carray_bind object
*/
static void carrayBindDel(void *pPtr){
  carray_bind *p = (carray_bind*)pPtr;
  if( p->xDel!=SQLITE_STATIC ){
     p->xDel(p->aData);
  }
  sqlite3_free(p);
}

/*
** Invoke this interface in order to bind to the single-argument
** version of CARRAY().
*/
SQLITE_API int sqlite3_carray_bind(
  sqlite3_stmt *pStmt,
  int idx,
  void *aData,
  int nData,
  int mFlags,
  void (*xDestroy)(void*)
){
  carray_bind *pNew;
  int i;
  pNew = sqlite3_malloc64(sizeof(*pNew));
  if( pNew==0 ){
    if( xDestroy!=SQLITE_STATIC && xDestroy!=SQLITE_TRANSIENT ){
      xDestroy(aData);
    }
    return SQLITE_NOMEM;
  }
  pNew->nData = nData;
  pNew->mFlags = mFlags;
  if( xDestroy==SQLITE_TRANSIENT ){
    sqlite3_int64 sz = nData;
    switch( mFlags & 0x07 ){
      case CARRAY_INT32:   sz *= 4;                     break;
      case CARRAY_INT64:   sz *= 8;                     break;
      case CARRAY_DOUBLE:  sz *= 8;                     break;
      case CARRAY_TEXT:    sz *= sizeof(char*);         break;
      case CARRAY_BLOB:    sz *= sizeof(struct iovec);  break;
    }
    if( (mFlags & 0x07)==CARRAY_TEXT ){
      for(i=0; i<nData; i++){
        const char *z = ((char**)aData)[i];
        if( z ) sz += strlen(z) + 1;
      }
    }else if( (mFlags & 0x07)==CARRAY_BLOB ){
      for(i=0; i<nData; i++){
        sz += ((struct iovec*)aData)[i].iov_len;
      }
    } 
    pNew->aData = sqlite3_malloc64( sz );
    if( pNew->aData==0 ){
      sqlite3_free(pNew);
      return SQLITE_NOMEM;
    }
    if( (mFlags & 0x07)==CARRAY_TEXT ){
      char **az = (char**)pNew->aData;
      char *z = (char*)&az[nData];
      for(i=0; i<nData; i++){
        const char *zData = ((char**)aData)[i];
        sqlite3_int64 n;
        if( zData==0 ){
          az[i] = 0;
          continue;
        }
        az[i] = z;
        n = strlen(zData);
        memcpy(z, zData, n+1);
        z += n+1;
      }
    }else if( (mFlags & 0x07)==CARRAY_BLOB ){
      struct iovec *p = (struct iovec*)pNew->aData;
      unsigned char *z = (unsigned char*)&p[nData];
      for(i=0; i<nData; i++){
        size_t n = ((struct iovec*)aData)[i].iov_len;
        p[i].iov_len = n;
        p[i].iov_base = z;
        z += n;
        memcpy(p[i].iov_base, ((struct iovec*)aData)[i].iov_base, n);
      }
    }else{
      memcpy(pNew->aData, aData, sz);
    }
    pNew->xDel = sqlite3_free;
  }else{
    pNew->aData = aData;
    pNew->xDel = xDestroy;
  }
  return sqlite3_bind_pointer(pStmt, idx, pNew, "carray-bind", carrayBindDel);
}


/*
** For testing purpose in the TCL test harness, we need a method for
** setting the pointer value.  The inttoptr(X) SQL function accomplishes
** this.  Tcl script will bind an integer to X and the inttoptr() SQL
** function will use sqlite3_result_pointer() to convert that integer into
** a pointer.
379
380
381
382
383
384
385
386
387
388
389

390
391
392
393
394
395
396
532
533
534
535
536
537
538




539
540
541
542
543
544
545
546







-
-
-
-
+







  }
  sqlite3_result_pointer(context, p, "carray", 0);
}
#endif /* SQLITE_TEST */

#endif /* SQLITE_OMIT_VIRTUALTABLE */

#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_carray_init(
SQLITE_API int sqlite3_carray_init(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  SQLITE_EXTENSION_INIT2(pApi);
#ifndef SQLITE_OMIT_VIRTUALTABLE

Added ext/misc/carray.h.



















































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2020-11-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.
**
*************************************************************************
**
** Interface definitions for the CARRAY table-valued function
** extension.
*/

#ifndef _CARRAY_H
#define _CARRAY_H

#include "sqlite3.h"              /* Required for error code definitions */

#ifdef __cplusplus
extern "C" {
#endif

/* Use this interface to bind an array to the single-argument version
** of CARRAY().
*/
SQLITE_API int sqlite3_carray_bind(
  sqlite3_stmt *pStmt,        /* Statement to be bound */
  int i,                      /* Parameter index */
  void *aData,                /* Pointer to array data */
  int nData,                  /* Number of data elements */
  int mFlags,                 /* CARRAY flags */
  void (*xDel)(void*)         /* Destructgor for aData*/
);

/* Allowed values for the mFlags parameter to sqlite3_carray_bind().
*/
#define CARRAY_INT32     0    /* Data is 32-bit signed integers */
#define CARRAY_INT64     1    /* Data is 64-bit signed integers */
#define CARRAY_DOUBLE    2    /* Data is doubles */
#define CARRAY_TEXT      3    /* Data is char* */
#define CARRAY_BLOB      4    /* Data is struct iovec */

#ifdef __cplusplus
}  /* end of the 'extern "C"' block */
#endif

#endif /* ifndef _CARRAY_H */

Added ext/misc/cksumvfs.c.

















































































































































































































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2020-04-20
**
** 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 a VFS shim that writes a checksum on each page
** of an SQLite database file.  When reading pages, the checksum is verified
** and an error is raised if the checksum is incorrect.
**
** COMPILING
**
** This extension requires SQLite 3.32.0 or later.  It uses the
** sqlite3_database_file_object() interface which was added in
** version 3.32.0, so it will not link with an earlier version of
** SQLite.
**
** To build this extension as a separately loaded shared library or
** DLL, use compiler command-lines similar to the following:
**
**   (linux)    gcc -fPIC -shared cksumvfs.c -o cksumvfs.so
**   (mac)      clang -fPIC -dynamiclib cksumvfs.c -o cksumvfs.dylib
**   (windows)  cl cksumvfs.c -link -dll -out:cksumvfs.dll
**
** You may want to add additional compiler options, of course,
** according to the needs of your project.
**
** If you want to statically link this extension with your product,
** then compile it like any other C-language module but add the
** "-DSQLITE_CKSUMVFS_STATIC" option so that this module knows that
** it is being statically linked rather than dynamically linked
**
** LOADING
**
** To load this extension as a shared library, you first have to
** bring up a dummy SQLite database connection to use as the argument
** to the sqlite3_load_extension() API call.  Then you invoke the
** sqlite3_load_extension() API and shutdown the dummy database
** connection.  All subsequent database connections that are opened
** will include this extension.  For example:
**
**     sqlite3 *db;
**     sqlite3_open(":memory:", &db);
**     sqlite3_load_extension(db, "./cksumvfs");
**     sqlite3_close(db);
**
** If this extension is compiled with -DSQLITE_CKSUMVFS_STATIC and
** statically linked against the application, initialize it using
** a single API call as follows:
**
**     sqlite3_register_cksumvfs();
**
** Cksumvfs is a VFS Shim. When loaded, "cksmvfs" becomes the new
** default VFS and it uses the prior default VFS as the next VFS
** down in the stack.  This is normally what you want.  However, in
** complex situations where multiple VFS shims are being loaded,
** it might be important to ensure that cksumvfs is loaded in the
** correct order so that it sequences itself into the default VFS
** Shim stack in the right order.
**
** USING
**
** Open database connections using the sqlite3_open() or 
** sqlite3_open_v2() interfaces, as normal.  Ordinary database files
** (without a checksum) will operate normally.  Databases with 
** checksums will return an SQLITE_IOERR_DATA error if a page is
** encountered that contains an invalid checksum.
**
** Checksumming only works on databases that have a reserve-bytes
** value of exactly 8.  The default value for reserve-bytes is 0.
** Hence, newly created database files will omit the checksum by
** default.  To create a database that includes a checksum, change
** the reserve-bytes value to 8 by runing:
**
**    int n = 8;
**    sqlite3_file_control(db, 0, SQLITE_FCNTL_RESERVE_BYTES, &n);
**
** If you do this immediately after creating a new database file,
** before anything else has been written into the file, then that
** might be all that you need to do.  Otherwise, the API call
** above should be followed by:
**
**    sqlite3_exec(db, "VACUUM", 0, 0, 0);
**
** It never hurts to run the VACUUM, even if you don't need it.
** If the database is in WAL mode, you should shutdown and
** reopen all database connections before continuing.
**
** From the CLI, use the ".filectrl reserve_bytes 8" command, 
** followed by "VACUUM;".
**
** Note that SQLite allows the number of reserve-bytes to be
** increased but not decreased.  So if a database file already
** has a reserve-bytes value greater than 8, there is no way to
** activate checksumming on that database, other than to dump
** and restore the database file.  Note also that other extensions
** might also make use of the reserve-bytes.  Checksumming will
** be incompatible with those other extensions.
**
** VERIFICATION OF CHECKSUMS
**
** If any checksum is incorrect, the "PRAGMA quick_check" command
** will find it.  To verify that checksums are actually enabled
** and running, use the following query:
**
**   SELECT count(*), verify_checksum(data)
**     FROM sqlite_dbpage
**    GROUP BY 2;
**
** There are three possible outputs form the verify_checksum()
** function: 1, 0, and NULL.  1 is returned if the checksum is
** correct.  0 is returned if the checksum is incorrect.  NULL
** is returned if the page is unreadable.  If checksumming is
** enabled, the read will fail if the checksum is wrong, so the
** usual result from verify_checksum() on a bad checksum is NULL.
**
** If everything is OK, the query above should return a single
** row where the second column is 1.  Any other result indicates
** either that there is a checksum error, or checksum validation
** is disabled.
**
** CONTROLLING CHECKSUM VERIFICATION
**
** The cksumvfs extension implements a new PRAGMA statement that can
** be used to disable, re-enable, or query the status of checksum
** verification:
**
**    PRAGMA checksum_verification;          -- query status
**    PRAGMA checksum_verification=OFF;      -- disable verification
**    PRAGMA checksum_verification=ON;       -- re-enable verification
**
** The "checksum_verification" pragma will return "1" (true) or "0"
** (false) if checksum verification is enabled or disabled, respectively.
** "Verification" in this context means the feature that causes
** SQLITE_IOERR_DATA errors if a checksum mismatch is detected while
** reading.  Checksums are always kept up-to-date as long as the
** reserve-bytes value of the database is 8, regardless of the setting
** of this pragma.  Checksum verification can be disabled (for example)
** to do forensic analysis of a database that has previously reported
** a checksum error.
**
** The "checksum_verification" pragma will always respond with "0" if
** the database file does not have a reserve-bytes value of 8.  The
** pragma will return no rows at all if the cksumvfs extension is
** not loaded.
**
** IMPLEMENTATION NOTES
**
** The checksum is stored in the last 8 bytes of each page.  This
** module only operates if the "bytes of reserved space on each page"
** value at offset 20 the SQLite database header is exactly 8.  If
** the reserved-space value is not 8, this module is a no-op.
*/
#if defined(SQLITE_AMALGAMATION) && !defined(SQLITE_CKSUMVFS_STATIC)
# define SQLITE_CKSUMVFS_STATIC
#endif
#ifdef SQLITE_CKSUMVFS_STATIC
# include "sqlite3.h"
#else
# include "sqlite3ext.h"
  SQLITE_EXTENSION_INIT1
#endif
#include <string.h>
#include <assert.h>


/*
** Forward declaration of objects used by this utility
*/
typedef struct sqlite3_vfs CksmVfs;
typedef struct CksmFile CksmFile;

/*
** Useful datatype abbreviations
*/
#if !defined(SQLITE_AMALGAMATION)
  typedef unsigned char u8;
  typedef unsigned int u32;
#endif

/* Access to a lower-level VFS that (might) implement dynamic loading,
** access to randomness, etc.
*/
#define ORIGVFS(p)  ((sqlite3_vfs*)((p)->pAppData))
#define ORIGFILE(p) ((sqlite3_file*)(((CksmFile*)(p))+1))

/* An open file */
struct CksmFile {
  sqlite3_file base;    /* IO methods */
  const char *zFName;   /* Original name of the file */
  char computeCksm;     /* True to compute checksums.
                        ** Always true if reserve size is 8. */
  char verifyCksm;      /* True to verify checksums */
  char isWal;           /* True if processing a WAL file */
  char inCkpt;          /* Currently doing a checkpoint */
  CksmFile *pPartner;   /* Ptr from WAL to main-db, or from main-db to WAL */
};

/*
** Methods for CksmFile
*/
static int cksmClose(sqlite3_file*);
static int cksmRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
static int cksmWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
static int cksmTruncate(sqlite3_file*, sqlite3_int64 size);
static int cksmSync(sqlite3_file*, int flags);
static int cksmFileSize(sqlite3_file*, sqlite3_int64 *pSize);
static int cksmLock(sqlite3_file*, int);
static int cksmUnlock(sqlite3_file*, int);
static int cksmCheckReservedLock(sqlite3_file*, int *pResOut);
static int cksmFileControl(sqlite3_file*, int op, void *pArg);
static int cksmSectorSize(sqlite3_file*);
static int cksmDeviceCharacteristics(sqlite3_file*);
static int cksmShmMap(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
static int cksmShmLock(sqlite3_file*, int offset, int n, int flags);
static void cksmShmBarrier(sqlite3_file*);
static int cksmShmUnmap(sqlite3_file*, int deleteFlag);
static int cksmFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
static int cksmUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p);

/*
** Methods for CksmVfs
*/
static int cksmOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
static int cksmDelete(sqlite3_vfs*, const char *zName, int syncDir);
static int cksmAccess(sqlite3_vfs*, const char *zName, int flags, int *);
static int cksmFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
static void *cksmDlOpen(sqlite3_vfs*, const char *zFilename);
static void cksmDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
static void (*cksmDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
static void cksmDlClose(sqlite3_vfs*, void*);
static int cksmRandomness(sqlite3_vfs*, int nByte, char *zOut);
static int cksmSleep(sqlite3_vfs*, int microseconds);
static int cksmCurrentTime(sqlite3_vfs*, double*);
static int cksmGetLastError(sqlite3_vfs*, int, char *);
static int cksmCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
static int cksmSetSystemCall(sqlite3_vfs*, const char*,sqlite3_syscall_ptr);
static sqlite3_syscall_ptr cksmGetSystemCall(sqlite3_vfs*, const char *z);
static const char *cksmNextSystemCall(sqlite3_vfs*, const char *zName);

static sqlite3_vfs cksm_vfs = {
  3,                            /* iVersion (set when registered) */
  0,                            /* szOsFile (set when registered) */
  1024,                         /* mxPathname */
  0,                            /* pNext */
  "cksmvfs",                    /* zName */
  0,                            /* pAppData (set when registered) */ 
  cksmOpen,                     /* xOpen */
  cksmDelete,                   /* xDelete */
  cksmAccess,                   /* xAccess */
  cksmFullPathname,             /* xFullPathname */
  cksmDlOpen,                   /* xDlOpen */
  cksmDlError,                  /* xDlError */
  cksmDlSym,                    /* xDlSym */
  cksmDlClose,                  /* xDlClose */
  cksmRandomness,               /* xRandomness */
  cksmSleep,                    /* xSleep */
  cksmCurrentTime,              /* xCurrentTime */
  cksmGetLastError,             /* xGetLastError */
  cksmCurrentTimeInt64,         /* xCurrentTimeInt64 */
  cksmSetSystemCall,            /* xSetSystemCall */
  cksmGetSystemCall,            /* xGetSystemCall */
  cksmNextSystemCall            /* xNextSystemCall */
};

static const sqlite3_io_methods cksm_io_methods = {
  3,                              /* iVersion */
  cksmClose,                      /* xClose */
  cksmRead,                       /* xRead */
  cksmWrite,                      /* xWrite */
  cksmTruncate,                   /* xTruncate */
  cksmSync,                       /* xSync */
  cksmFileSize,                   /* xFileSize */
  cksmLock,                       /* xLock */
  cksmUnlock,                     /* xUnlock */
  cksmCheckReservedLock,          /* xCheckReservedLock */
  cksmFileControl,                /* xFileControl */
  cksmSectorSize,                 /* xSectorSize */
  cksmDeviceCharacteristics,      /* xDeviceCharacteristics */
  cksmShmMap,                     /* xShmMap */
  cksmShmLock,                    /* xShmLock */
  cksmShmBarrier,                 /* xShmBarrier */
  cksmShmUnmap,                   /* xShmUnmap */
  cksmFetch,                      /* xFetch */
  cksmUnfetch                     /* xUnfetch */
};

/* Do byte swapping on a unsigned 32-bit integer */
#define BYTESWAP32(x) ( \
    (((x)&0x000000FF)<<24) + (((x)&0x0000FF00)<<8)  \
  + (((x)&0x00FF0000)>>8)  + (((x)&0xFF000000)>>24) \
)

/* Compute a checksum on a buffer */
static void cksmCompute(
  u8 *a,           /* Content to be checksummed */
  int nByte,       /* Bytes of content in a[].  Must be a multiple of 8. */
  u8 *aOut         /* OUT: Final 8-byte checksum value output */
){
  u32 s1 = 0, s2 = 0;
  u32 *aData = (u32*)a;
  u32 *aEnd = (u32*)&a[nByte];
  u32 x = 1;

  assert( nByte>=8 );
  assert( (nByte&0x00000007)==0 );
  assert( nByte<=65536 );

  if( 1 == *(u8*)&x ){
    /* Little-endian */
    do {
      s1 += *aData++ + s2;
      s2 += *aData++ + s1;
    }while( aData<aEnd );
  }else{
    /* Big-endian */
    do {
      s1 += BYTESWAP32(aData[0]) + s2;
      s2 += BYTESWAP32(aData[1]) + s1;
      aData += 2;
    }while( aData<aEnd );
    s1 = BYTESWAP32(s1);
    s2 = BYTESWAP32(s2);
  }
  memcpy(aOut, &s1, 4);
  memcpy(aOut+4, &s2, 4);
}

/*
** SQL function:    verify_checksum(BLOB)
**
** Return 0 or 1 if the checksum is invalid or valid.  Or return
** NULL if the input is not a BLOB that is the right size for a
** database page.
*/
static void cksmVerifyFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  int nByte;
  u8 *data;
  u8 cksum[8];
  data = (u8*)sqlite3_value_blob(argv[0]);
  if( data==0 ) return;
  if( sqlite3_value_type(argv[0])!=SQLITE_BLOB ) return;
  nByte = sqlite3_value_bytes(argv[0]);
  if( nByte<512 || nByte>65536 || (nByte & (nByte-1))!=0 ) return;
  cksmCompute(data, nByte-8, cksum);
  sqlite3_result_int(context, memcmp(data+nByte-8,cksum,8)==0);
}

#ifdef SQLITE_CKSUMVFS_INIT_FUNCNAME
/*
** SQL function:    initialize_cksumvfs(SCHEMANAME)
**
** This SQL functions (whose name is actually determined at compile-time
** by the value of the SQLITE_CKSUMVFS_INIT_FUNCNAME macro) invokes:
**
**   sqlite3_file_control(db, SCHEMANAME, SQLITE_FCNTL_RESERVE_BYTE, &n);
**
** In order to set the reserve bytes value to 8, so that cksumvfs will
** operation.  This feature is provided (if and only if the
** SQLITE_CKSUMVFS_INIT_FUNCNAME compile-time option is set to a string
** which is the name of the SQL function) so as to provide the ability
** to invoke the file-control in programming languages that lack
** direct access to the sqlite3_file_control() interface (ex: Java).
**
** This interface is undocumented, apart from this comment.  Usage
** example:
**
**    1.  Compile with -DSQLITE_CKSUMVFS_INIT_FUNCNAME="ckvfs_init"
**    2.  Run:  "SELECT cksum_init('main'); VACUUM;"
*/
static void cksmInitFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  int nByte = 8;
  const char *zSchemaName = (const char*)sqlite3_value_text(argv[0]);
  sqlite3 *db = sqlite3_context_db_handle(context);
  sqlite3_file_control(db, zSchemaName, SQLITE_FCNTL_RESERVE_BYTES, &nByte);
  /* Return NULL */
}
#endif /* SQLITE_CKSUMBFS_INIT_FUNCNAME */

/*
** Close a cksm-file.
*/
static int cksmClose(sqlite3_file *pFile){
  CksmFile *p = (CksmFile *)pFile;
  if( p->pPartner ){
    assert( p->pPartner->pPartner==p );
    p->pPartner->pPartner = 0;
    p->pPartner = 0;
  }
  pFile = ORIGFILE(pFile);
  return pFile->pMethods->xClose(pFile);
}

/*
** Set the computeCkSm and verifyCksm flags, if they need to be
** changed.
*/
static void cksmSetFlags(CksmFile *p, int hasCorrectReserveSize){
  if( hasCorrectReserveSize!=p->computeCksm ){
    p->computeCksm = p->verifyCksm = hasCorrectReserveSize;
    if( p->pPartner ){
      p->pPartner->verifyCksm = hasCorrectReserveSize;
      p->pPartner->computeCksm = hasCorrectReserveSize;
    }
  }
}

/*
** Read data from a cksm-file.
*/
static int cksmRead(
  sqlite3_file *pFile, 
  void *zBuf, 
  int iAmt, 
  sqlite_int64 iOfst
){
  int rc;
  CksmFile *p = (CksmFile *)pFile;
  pFile = ORIGFILE(pFile);
  rc = pFile->pMethods->xRead(pFile, zBuf, iAmt, iOfst);
  if( rc==SQLITE_OK ){
    if( iOfst==0 && iAmt>=100 && (
          memcmp(zBuf,"SQLite format 3",16)==0 || memcmp(zBuf,"ZV-",3)==0 
    )){
      u8 *d = (u8*)zBuf;
      char hasCorrectReserveSize = (d[20]==8);
      cksmSetFlags(p, hasCorrectReserveSize);
    }
    /* Verify the checksum if
    **    (1) the size indicates that we are dealing with a complete
    **        database page
    **    (2) checksum verification is enabled
    **    (3) we are not in the middle of checkpoint
    */
    if( iAmt>=512           /* (1) */
     && p->verifyCksm       /* (2) */
     && !p->inCkpt          /* (3) */
    ){
      u8 cksum[8];
      cksmCompute((u8*)zBuf, iAmt-8, cksum);
      if( memcmp((u8*)zBuf+iAmt-8, cksum, 8)!=0 ){
        sqlite3_log(SQLITE_IOERR_DATA,
           "checksum fault offset %lld of \"%s\"",
           iOfst, p->zFName);
        rc = SQLITE_IOERR_DATA;
      }
    }
  }
  return rc;
}

/*
** Write data to a cksm-file.
*/
static int cksmWrite(
  sqlite3_file *pFile,
  const void *zBuf,
  int iAmt,
  sqlite_int64 iOfst
){
  CksmFile *p = (CksmFile *)pFile;
  pFile = ORIGFILE(pFile);
  if( iOfst==0 && iAmt>=100 && (
        memcmp(zBuf,"SQLite format 3",16)==0 || memcmp(zBuf,"ZV-",3)==0 
  )){
    u8 *d = (u8*)zBuf;
    char hasCorrectReserveSize = (d[20]==8);
    cksmSetFlags(p, hasCorrectReserveSize);
  }
  /* If the write size is appropriate for a database page and if
  ** checksums where ever enabled, then it will be safe to compute
  ** the checksums.  The reserve byte size might have increased, but
  ** it will never decrease.  And because it cannot decrease, the
  ** checksum will not overwrite anything.
  */
  if( iAmt>=512
   && p->computeCksm
   && !p->inCkpt
  ){
    cksmCompute((u8*)zBuf, iAmt-8, ((u8*)zBuf)+iAmt-8);
  }
  return pFile->pMethods->xWrite(pFile, zBuf, iAmt, iOfst);
}

/*
** Truncate a cksm-file.
*/
static int cksmTruncate(sqlite3_file *pFile, sqlite_int64 size){
  pFile = ORIGFILE(pFile);
  return pFile->pMethods->xTruncate(pFile, size);
}

/*
** Sync a cksm-file.
*/
static int cksmSync(sqlite3_file *pFile, int flags){
  pFile = ORIGFILE(pFile);
  return pFile->pMethods->xSync(pFile, flags);
}

/*
** Return the current file-size of a cksm-file.
*/
static int cksmFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
  CksmFile *p = (CksmFile *)pFile;
  pFile = ORIGFILE(p);
  return pFile->pMethods->xFileSize(pFile, pSize);
}

/*
** Lock a cksm-file.
*/
static int cksmLock(sqlite3_file *pFile, int eLock){
  pFile = ORIGFILE(pFile);
  return pFile->pMethods->xLock(pFile, eLock);
}

/*
** Unlock a cksm-file.
*/
static int cksmUnlock(sqlite3_file *pFile, int eLock){
  pFile = ORIGFILE(pFile);
  return pFile->pMethods->xUnlock(pFile, eLock);
}

/*
** Check if another file-handle holds a RESERVED lock on a cksm-file.
*/
static int cksmCheckReservedLock(sqlite3_file *pFile, int *pResOut){
  pFile = ORIGFILE(pFile);
  return pFile->pMethods->xCheckReservedLock(pFile, pResOut);
}

/*
** File control method. For custom operations on a cksm-file.
*/
static int cksmFileControl(sqlite3_file *pFile, int op, void *pArg){
  int rc;
  CksmFile *p = (CksmFile*)pFile;
  pFile = ORIGFILE(pFile);
  if( op==SQLITE_FCNTL_PRAGMA ){
    char **azArg = (char**)pArg;
    assert( azArg[1]!=0 );
    if( sqlite3_stricmp(azArg[1],"checksum_verification")==0 ){
      char *zArg = azArg[2];
      if( zArg!=0 ){
        if( (zArg[0]>='1' && zArg[0]<='9')
         || sqlite3_strlike("enable%",zArg,0)==0
         || sqlite3_stricmp("yes",zArg)==0
         || sqlite3_stricmp("on",zArg)==0
        ){
          p->verifyCksm = p->computeCksm;
        }else{
          p->verifyCksm = 0;
        }
        if( p->pPartner ) p->pPartner->verifyCksm = p->verifyCksm;
      }
      azArg[0] = sqlite3_mprintf("%d",p->verifyCksm);
      return SQLITE_OK;
    }else if( p->computeCksm && azArg[2]!=0
           && 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;
}

/*
** Return the sector-size in bytes for a cksm-file.
*/
static int cksmSectorSize(sqlite3_file *pFile){
  pFile = ORIGFILE(pFile);
  return pFile->pMethods->xSectorSize(pFile);
}

/*
** Return the device characteristic flags supported by a cksm-file.
*/
static int cksmDeviceCharacteristics(sqlite3_file *pFile){
  pFile = ORIGFILE(pFile);
  return pFile->pMethods->xDeviceCharacteristics(pFile);
}

/* Create a shared memory file mapping */
static int cksmShmMap(
  sqlite3_file *pFile,
  int iPg,
  int pgsz,
  int bExtend,
  void volatile **pp
){
  pFile = ORIGFILE(pFile);
  return pFile->pMethods->xShmMap(pFile,iPg,pgsz,bExtend,pp);
}

/* Perform locking on a shared-memory segment */
static int cksmShmLock(sqlite3_file *pFile, int offset, int n, int flags){
  pFile = ORIGFILE(pFile);
  return pFile->pMethods->xShmLock(pFile,offset,n,flags);
}

/* Memory barrier operation on shared memory */
static void cksmShmBarrier(sqlite3_file *pFile){
  pFile = ORIGFILE(pFile);
  pFile->pMethods->xShmBarrier(pFile);
}

/* Unmap a shared memory segment */
static int cksmShmUnmap(sqlite3_file *pFile, int deleteFlag){
  pFile = ORIGFILE(pFile);
  return pFile->pMethods->xShmUnmap(pFile,deleteFlag);
}

/* Fetch a page of a memory-mapped file */
static int cksmFetch(
  sqlite3_file *pFile,
  sqlite3_int64 iOfst,
  int iAmt,
  void **pp
){
  CksmFile *p = (CksmFile *)pFile;
  if( p->computeCksm ){
    *pp = 0;
    return SQLITE_OK;
  }
  pFile = ORIGFILE(pFile);
  if( pFile->pMethods->iVersion>2 && pFile->pMethods->xFetch ){
    return pFile->pMethods->xFetch(pFile, iOfst, iAmt, pp);
  }
  *pp = 0;
  return SQLITE_OK;
}

/* Release a memory-mapped page */
static int cksmUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
  pFile = ORIGFILE(pFile);
  if( pFile->pMethods->iVersion>2 && pFile->pMethods->xUnfetch ){
    return pFile->pMethods->xUnfetch(pFile, iOfst, pPage);
  }
  return SQLITE_OK;
}

/*
** Open a cksm file handle.
*/
static int cksmOpen(
  sqlite3_vfs *pVfs,
  const char *zName,
  sqlite3_file *pFile,
  int flags,
  int *pOutFlags
){
  CksmFile *p;
  sqlite3_file *pSubFile;
  sqlite3_vfs *pSubVfs;
  int rc;
  pSubVfs = ORIGVFS(pVfs);
  if( (flags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_WAL))==0 ){
    return pSubVfs->xOpen(pSubVfs, zName, pFile, flags, pOutFlags);
  }
  p = (CksmFile*)pFile;
  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;
    p->computeCksm = 0;
  }
  p->zFName = zName;
cksm_open_done:
  if( rc ) pFile->pMethods = 0;
  return rc;
}

/*
** All other VFS methods are pass-thrus.
*/
static int cksmDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
  return ORIGVFS(pVfs)->xDelete(ORIGVFS(pVfs), zPath, dirSync);
}
static int cksmAccess(
  sqlite3_vfs *pVfs, 
  const char *zPath, 
  int flags, 
  int *pResOut
){
  return ORIGVFS(pVfs)->xAccess(ORIGVFS(pVfs), zPath, flags, pResOut);
}
static int cksmFullPathname(
  sqlite3_vfs *pVfs, 
  const char *zPath, 
  int nOut, 
  char *zOut
){
  return ORIGVFS(pVfs)->xFullPathname(ORIGVFS(pVfs),zPath,nOut,zOut);
}
static void *cksmDlOpen(sqlite3_vfs *pVfs, const char *zPath){
  return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath);
}
static void cksmDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
  ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg);
}
static void (*cksmDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
  return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym);
}
static void cksmDlClose(sqlite3_vfs *pVfs, void *pHandle){
  ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle);
}
static int cksmRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
  return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut);
}
static int cksmSleep(sqlite3_vfs *pVfs, int nMicro){
  return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro);
}
static int cksmCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
  return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut);
}
static int cksmGetLastError(sqlite3_vfs *pVfs, int a, char *b){
  return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b);
}
static int cksmCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
  sqlite3_vfs *pOrig = ORIGVFS(pVfs);
  int rc;
  assert( pOrig->iVersion>=2 );
  if( pOrig->xCurrentTimeInt64 ){
    rc = pOrig->xCurrentTimeInt64(pOrig, p);
  }else{
    double r;
    rc = pOrig->xCurrentTime(pOrig, &r);
    *p = (sqlite3_int64)(r*86400000.0);
  }
  return rc;
}
static int cksmSetSystemCall(
  sqlite3_vfs *pVfs,
  const char *zName,
  sqlite3_syscall_ptr pCall
){
  return ORIGVFS(pVfs)->xSetSystemCall(ORIGVFS(pVfs),zName,pCall);
}
static sqlite3_syscall_ptr cksmGetSystemCall(
  sqlite3_vfs *pVfs,
  const char *zName
){
  return ORIGVFS(pVfs)->xGetSystemCall(ORIGVFS(pVfs),zName);
}
static const char *cksmNextSystemCall(sqlite3_vfs *pVfs, const char *zName){
  return ORIGVFS(pVfs)->xNextSystemCall(ORIGVFS(pVfs), zName);
}

/* Register the verify_checksum() SQL function.
*/
static int cksmRegisterFunc(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  int rc;
  if( db==0 ) return SQLITE_OK;
  rc = sqlite3_create_function(db, "verify_checksum", 1,
                   SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
                   0, cksmVerifyFunc, 0, 0);
#ifdef SQLITE_CKSUMVFS_INIT_FUNCNAME
  (void)sqlite3_create_function(db, SQLITE_CKSUMVFS_INIT_FUNCNAME, 1,
                   SQLITE_UTF8|SQLITE_DIRECTONLY,
                   0, cksmInitFunc, 0, 0);
#endif
  return rc;
}

/*
** Register the cksum VFS as the default VFS for the system.
** Also make arrangements to automatically register the "verify_checksum()"
** SQL function on each new database connection.
*/
static int cksmRegisterVfs(void){
  int rc = SQLITE_OK;
  sqlite3_vfs *pOrig;
  if( sqlite3_vfs_find("cksmvfs")!=0 ) return SQLITE_OK;
  pOrig = sqlite3_vfs_find(0);
  if( pOrig==0 ) return SQLITE_ERROR;
  cksm_vfs.iVersion = pOrig->iVersion;
  cksm_vfs.pAppData = pOrig;
  cksm_vfs.szOsFile = pOrig->szOsFile + sizeof(CksmFile);
  rc = sqlite3_vfs_register(&cksm_vfs, 1);
  if( rc==SQLITE_OK ){
    rc = sqlite3_auto_extension((void(*)(void))cksmRegisterFunc);
  }
  return rc;
}

#if defined(SQLITE_CKSUMVFS_STATIC)
/* This variant of the initializer runs when the extension is
** statically linked.
*/
int sqlite3_register_cksumvfs(const char *NotUsed){
  (void)NotUsed;
  return cksmRegisterVfs();
}
int sqlite3_unregister_cksumvfs(void){
  if( sqlite3_vfs_find("cksmvfs") ){
    sqlite3_vfs_unregister(&cksm_vfs);
    sqlite3_cancel_auto_extension((void(*)(void))cksmRegisterFunc);
  }
  return SQLITE_OK;
}
#endif /* defined(SQLITE_CKSUMVFS_STATIC */

#if !defined(SQLITE_CKSUMVFS_STATIC)
/* This variant of the initializer function is used when the
** extension is shared library to be loaded at run-time.
*/
#ifdef _WIN32
__declspec(dllexport)
#endif
/* 
** This routine is called by sqlite3_load_extension() when the
** extension is first loaded.
***/
int sqlite3_cksumvfs_init(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  int rc;
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg; /* not used */
  rc = cksmRegisterFunc(db, 0, 0);
  if( rc==SQLITE_OK ){
    rc = cksmRegisterVfs();
  }
  if( rc==SQLITE_OK ) rc = SQLITE_OK_LOAD_PERMANENTLY;
  return rc;
}
#endif /* !defined(SQLITE_CKSUMVFS_STATIC) */

Changes to ext/misc/closure.c.

418
419
420
421
422
423
424
425

426
427
428
429


430
431
432
433
434

435
436
437
438
439
440
441
418
419
420
421
422
423
424

425
426
427


428
429
430
431
432
433

434
435
436
437
438
439
440
441







-
+


-
-
+
+




-
+







**
**     "abc"   becomes   abc
**     'xyz'   becomes   xyz
**     [pqr]   becomes   pqr
**     `mno`   becomes   mno
*/
static char *closureDequote(const char *zIn){
  int nIn;                        /* Size of input string, in bytes */
  sqlite3_int64 nIn;              /* Size of input string, in bytes */
  char *zOut;                     /* Output (dequoted) string */

  nIn = (int)strlen(zIn);
  zOut = sqlite3_malloc(nIn+1);
  nIn = strlen(zIn);
  zOut = sqlite3_malloc64(nIn+1);
  if( zOut ){
    char q = zIn[0];              /* Quote character (if any ) */

    if( q!='[' && q!= '\'' && q!='"' && q!='`' ){
      memcpy(zOut, zIn, nIn+1);
      memcpy(zOut, zIn, (size_t)(nIn+1));
    }else{
      int iOut = 0;               /* Index of next byte to write to output */
      int iIn;                    /* Index of next byte to read from input */

      if( q=='[' ) q = ']';
      for(iIn=1; iIn<nIn; iIn++){
        if( zIn[iIn]==q ) iIn++;

Changes to ext/misc/completion.c.

114
115
116
117
118
119
120

121
122
123
124
125
126
127
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128







+








/* Column numbers */
#define COMPLETION_COLUMN_CANDIDATE 0  /* Suggested completion of the input */
#define COMPLETION_COLUMN_PREFIX    1  /* Prefix of the word to be completed */
#define COMPLETION_COLUMN_WHOLELINE 2  /* Entire line seen so far */
#define COMPLETION_COLUMN_PHASE     3  /* ePhase - used for debugging only */

  sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
  rc = sqlite3_declare_vtab(db,
      "CREATE TABLE x("
      "  candidate TEXT,"
      "  prefix TEXT HIDDEN,"
      "  wholeline TEXT HIDDEN,"
      "  phase INT HIDDEN"        /* Used for debugging only */
      ")");
221
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







-
+







          char *zSql = 0;
          const char *zSep = "";
          sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0);
          while( sqlite3_step(pS2)==SQLITE_ROW ){
            const char *zDb = (const char*)sqlite3_column_text(pS2, 1);
            zSql = sqlite3_mprintf(
               "%z%s"
               "SELECT name FROM \"%w\".sqlite_master",
               "SELECT name FROM \"%w\".sqlite_schema",
               zSql, zSep, zDb
            );
            if( zSql==0 ) return SQLITE_NOMEM;
            zSep = " UNION ";
          }
          sqlite3_finalize(pS2);
          sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0);
245
246
247
248
249
250
251
252

253
254
255
256
257
258
259
246
247
248
249
250
251
252

253
254
255
256
257
258
259
260







-
+







          char *zSql = 0;
          const char *zSep = "";
          sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0);
          while( sqlite3_step(pS2)==SQLITE_ROW ){
            const char *zDb = (const char*)sqlite3_column_text(pS2, 1);
            zSql = sqlite3_mprintf(
               "%z%s"
               "SELECT pti.name FROM \"%w\".sqlite_master AS sm"
               "SELECT pti.name FROM \"%w\".sqlite_schema AS sm"
                       " JOIN pragma_table_info(sm.name,%Q) AS pti"
               " WHERE sm.type='table'",
               zSql, zSep, zDb, zDb
            );
            if( zSql==0 ) return SQLITE_NOMEM;
            zSep = " UNION ";
          }

Changes to ext/misc/compress.c.

115
116
117
118
119
120
121
122
123



124
125
126



127
128
129
115
116
117
118
119
120
121


122
123
124
125


126
127
128
129
130
131







-
-
+
+
+

-
-
+
+
+



  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg;  /* Unused parameter */
  rc = sqlite3_create_function(db, "compress", 1, SQLITE_UTF8, 0,
                               compressFunc, 0, 0);
  rc = sqlite3_create_function(db, "compress", 1, 
                    SQLITE_UTF8 | SQLITE_INNOCUOUS,
                    0, compressFunc, 0, 0);
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "uncompress", 1, SQLITE_UTF8, 0,
                                 uncompressFunc, 0, 0);
    rc = sqlite3_create_function(db, "uncompress", 1,
                    SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC,
                    0, uncompressFunc, 0, 0);
  }
  return rc;
}

Changes to ext/misc/csv.c.

276
277
278
279
280
281
282

283
284
285
286
287
288
289
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290







+







    }
    if( c=='\n' ){
      p->nLine++;
      if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--;
    }
    p->cTerm = (char)c;
  }
  assert( p->z==0 || p->n<p->nAlloc );
  if( p->z ) p->z[p->n] = 0;
  p->bNotFirst = 1;
  return p->z;
}


/* Forward references to the various virtual table methods implemented
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
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







-
+










+
+
+
+
+
+
+
+
+







  pNew->tstFlags = tstFlags;
#endif
  if( bHeader!=1 ){
    pNew->iStart = 0;
  }else if( pNew->zData ){
    pNew->iStart = (int)sRdr.iIn;
  }else{
    pNew->iStart = ftell(sRdr.in);
    pNew->iStart = (int)(ftell(sRdr.in) - sRdr.nIn + sRdr.iIn);
  }
  csv_reader_reset(&sRdr);
  rc = sqlite3_declare_vtab(db, CSV_SCHEMA);
  if( rc ){
    csv_errmsg(&sRdr, "bad schema: '%s' - %s", CSV_SCHEMA, sqlite3_errmsg(db));
    goto csvtab_connect_error;
  }
  for(i=0; i<sizeof(azPValue)/sizeof(azPValue[0]); i++){
    sqlite3_free(azPValue[i]);
  }
  /* Rationale for DIRECTONLY:
  ** An attacker who controls a database schema could use this vtab
  ** to exfiltrate sensitive data from other files in the filesystem.
  ** And, recommended practice is to put all CSV virtual tables in the
  ** TEMP namespace, so they should still be usable from within TEMP
  ** views, so there shouldn't be a serious loss of functionality by
  ** prohibiting the use of this vtab from persistent triggers and views.
  */
  sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY);
  return SQLITE_OK;

csvtab_connect_oom:
  rc = SQLITE_NOMEM;
  csv_errmsg(&sRdr, "out of memory");

csvtab_connect_error:
737
738
739
740
741
742
743
744

745
746
747
748
749
750
751
747
748
749
750
751
752
753

754
755
756
757
758
759
760
761







-
+







        pCur->azVal[i] = zNew;
        pCur->aLen[i] = pCur->rdr.n+1;
      }
      memcpy(pCur->azVal[i], z, pCur->rdr.n+1);
      i++;
    }
  }while( pCur->rdr.cTerm==',' );
  if( z==0 || (pCur->rdr.cTerm==EOF && i<pTab->nCol) ){
  if( z==0 && i==0 ){
    pCur->iRowid = -1;
  }else{
    pCur->iRowid++;
    while( i<pTab->nCol ){
      sqlite3_free(pCur->azVal[i]);
      pCur->azVal[i] = 0;
      pCur->aLen[i] = 0;
763
764
765
766
767
768
769
770

771
772
773
774
775
776
777
773
774
775
776
777
778
779

780
781
782
783
784
785
786
787







-
+







  sqlite3_vtab_cursor *cur,   /* The cursor */
  sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
  int i                       /* Which column to return */
){
  CsvCursor *pCur = (CsvCursor*)cur;
  CsvTable *pTab = (CsvTable*)cur->pVtab;
  if( i>=0 && i<pTab->nCol && pCur->azVal[i]!=0 ){
    sqlite3_result_text(ctx, pCur->azVal[i], -1, SQLITE_STATIC);
    sqlite3_result_text(ctx, pCur->azVal[i], -1, SQLITE_TRANSIENT);
  }
  return SQLITE_OK;
}

/*
** Return the rowid for the current row.
*/
798
799
800
801
802
803
804






805
806
807
808
809
810
811
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827







+
+
+
+
+
+







  sqlite3_vtab_cursor *pVtabCursor, 
  int idxNum, const char *idxStr,
  int argc, sqlite3_value **argv
){
  CsvCursor *pCur = (CsvCursor*)pVtabCursor;
  CsvTable *pTab = (CsvTable*)pVtabCursor->pVtab;
  pCur->iRowid = 0;

  /* Ensure the field buffer is always allocated. Otherwise, if the
  ** first field is zero bytes in size, this may be mistaken for an OOM
  ** error in csvtabNext(). */
  if( csv_append(&pCur->rdr, 0) ) return SQLITE_NOMEM;

  if( pCur->rdr.in==0 ){
    assert( pCur->rdr.zIn==pTab->zData );
    assert( pTab->iStart>=0 );
    assert( (size_t)pTab->iStart<=pCur->rdr.nIn );
    pCur->rdr.iIn = pTab->iStart;
  }else{
    fseek(pCur->rdr.in, pTab->iStart, SEEK_SET);
928
929
930
931
932
933
934
935

936
937
938
939
940
941
942
943
944
945
946
947
948
944
945
946
947
948
949
950

951
952
953
954
955
956
957
958
959
960
961
962
963
964







-
+













** connection.
*/
int sqlite3_csv_init(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
#ifndef SQLITE_OMIT_VIRTUALTABLE	
#ifndef SQLITE_OMIT_VIRTUALTABLE
  int rc;
  SQLITE_EXTENSION_INIT2(pApi);
  rc = sqlite3_create_module(db, "csv", &CsvModule, 0);
#ifdef SQLITE_TEST
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_module(db, "csv_wr", &CsvModuleFauxWrite, 0);
  }
#endif
  return rc;
#else
  return SQLITE_OK;
#endif
}

Changes to ext/misc/dbdump.c.

191
192
193
194
195
196
197
198

199
200
201
202
203
204
205
191
192
193
194
195
196
197

198
199
200
201
202
203
204
205







-
+







  rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
  sqlite3_free(zSql);
  if( rc ) return 0;
  while( sqlite3_step(pStmt)==SQLITE_ROW ){
    if( nCol>=nAlloc-2 ){
      char **azNew;
      nAlloc = nAlloc*2 + nCol + 10;
      azNew = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0]));
      azNew = sqlite3_realloc64(azCol, nAlloc*sizeof(azCol[0]));
      if( azNew==0 ) goto col_oom;
      azCol = azNew;
      azCol[0] = 0;
    }
    azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
    if( azCol[nCol]==0 ) goto col_oom;
    if( sqlite3_column_int(pStmt, 5) ){
391
392
393
394
395
396
397
398

399
400
401
402
403
404
405
406
407

408
409
410
411
412
413
414
391
392
393
394
395
396
397

398
399
400
401
402
403
404
405
406

407
408
409
410
411
412
413
414







-
+








-
+







  zTable = azArg[0];
  zType = azArg[1];
  zSql = azArg[2];

  if( strcmp(zTable, "sqlite_sequence")==0 ){
    p->xCallback("DELETE FROM sqlite_sequence;\n", p->pArg);
  }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){
    p->xCallback("ANALYZE sqlite_master;\n", p->pArg);
    p->xCallback("ANALYZE sqlite_schema;\n", p->pArg);
  }else if( strncmp(zTable, "sqlite_", 7)==0 ){
    return 0;
  }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
    if( !p->writableSchema ){
      p->xCallback("PRAGMA writable_schema=ON;\n", p->pArg);
      p->writableSchema = 1;
    }
    output_formatted(p,
       "INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)"
       "INSERT INTO sqlite_schema(type,name,tbl_name,rootpage,sql)"
       "VALUES('table','%q','%q',0,'%q');",
       zTable, zTable, zSql);
    return 0;
  }else{
    if( sqlite3_strglob("CREATE TABLE ['\"]*", zSql)==0 ){
      p->xCallback("CREATE TABLE IF NOT EXISTS ", p->pArg);
      p->xCallback(zSql+13, p->pArg);
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
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







-
+




-
+



-
+




-
+





-
+







  if( x.rc ) return x.rc;
  x.db = db;
  x.xCallback = xCallback;
  x.pArg = pArg;
  xCallback("PRAGMA foreign_keys=OFF;\nBEGIN TRANSACTION;\n", pArg);
  if( zTable==0 ){
    run_schema_dump_query(&x,
      "SELECT name, type, sql FROM \"%w\".sqlite_master "
      "SELECT name, type, sql FROM \"%w\".sqlite_schema "
      "WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'",
      zSchema
    );
    run_schema_dump_query(&x,
      "SELECT name, type, sql FROM \"%w\".sqlite_master "
      "SELECT name, type, sql FROM \"%w\".sqlite_schema "
      "WHERE name=='sqlite_sequence'", zSchema
    );
    output_sql_from_query(&x,
      "SELECT sql FROM sqlite_master "
      "SELECT sql FROM sqlite_schema "
      "WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0
    );
  }else{
    run_schema_dump_query(&x,
      "SELECT name, type, sql FROM \"%w\".sqlite_master "
      "SELECT name, type, sql FROM \"%w\".sqlite_schema "
      "WHERE tbl_name=%Q COLLATE nocase AND type=='table'"
      "  AND sql NOT NULL",
      zSchema, zTable
    );
    output_sql_from_query(&x,
      "SELECT sql FROM \"%w\".sqlite_master "
      "SELECT sql FROM \"%w\".sqlite_schema "
      "WHERE sql NOT NULL"
      "  AND type IN ('index','trigger','view')"
      "  AND tbl_name=%Q COLLATE nocase",
      zSchema, zTable
    ); 
  }
  if( x.writableSchema ){

Added ext/misc/decimal.c.




























































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2020-06-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.
**
******************************************************************************
**
** Routines to implement arbitrary-precision decimal math.
**
** The focus here is on simplicity and correctness, not performance.
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>

/* Mark a function parameter as unused, to suppress nuisance compiler
** warnings. */
#ifndef UNUSED_PARAMETER
# define UNUSED_PARAMETER(X)  (void)(X)
#endif


/* A decimal object */
typedef struct Decimal Decimal;
struct Decimal {
  char sign;        /* 0 for positive, 1 for negative */
  char oom;         /* True if an OOM is encountered */
  char isNull;      /* True if holds a NULL rather than a number */
  char isInit;      /* True upon initialization */
  int nDigit;       /* Total number of digits */
  int nFrac;        /* Number of digits to the right of the decimal point */
  signed char *a;   /* Array of digits.  Most significant first. */
};

/*
** Release memory held by a Decimal, but do not free the object itself.
*/
static void decimal_clear(Decimal *p){
  sqlite3_free(p->a);
}

/*
** Destroy a Decimal object
*/
static void decimal_free(Decimal *p){
  if( p ){
    decimal_clear(p);
    sqlite3_free(p);
  }
}

/*
** Allocate a new Decimal object.  Initialize it to the number given
** by the input string.
*/
static Decimal *decimal_new(
  sqlite3_context *pCtx,
  sqlite3_value *pIn,
  int nAlt,
  const unsigned char *zAlt
){
  Decimal *p;
  int n, i;
  const unsigned char *zIn;
  int iExp = 0;
  p = sqlite3_malloc( sizeof(*p) );
  if( p==0 ) goto new_no_mem;
  p->sign = 0;
  p->oom = 0;
  p->isInit = 1;
  p->isNull = 0;
  p->nDigit = 0;
  p->nFrac = 0;
  if( zAlt ){
    n = nAlt,
    zIn = zAlt;
  }else{
    if( sqlite3_value_type(pIn)==SQLITE_NULL ){
      p->a = 0;
      p->isNull = 1;
      return p;
    }
    n = sqlite3_value_bytes(pIn);
    zIn = sqlite3_value_text(pIn);
  }
  p->a = sqlite3_malloc64( n+1 );
  if( p->a==0 ) goto new_no_mem;
  for(i=0; isspace(zIn[i]); i++){}
  if( zIn[i]=='-' ){
    p->sign = 1;
    i++;
  }else if( zIn[i]=='+' ){
    i++;
  }
  while( i<n && zIn[i]=='0' ) i++;
  while( i<n ){
    char c = zIn[i];
    if( c>='0' && c<='9' ){
      p->a[p->nDigit++] = c - '0';
    }else if( c=='.' ){
      p->nFrac = p->nDigit + 1;
    }else if( c=='e' || c=='E' ){
      int j = i+1;
      int neg = 0;
      if( j>=n ) break;
      if( zIn[j]=='-' ){
        neg = 1;
        j++;
      }else if( zIn[j]=='+' ){
        j++;
      }
      while( j<n && iExp<1000000 ){
        if( zIn[j]>='0' && zIn[j]<='9' ){
          iExp = iExp*10 + zIn[j] - '0';
        }
        j++;
      }
      if( neg ) iExp = -iExp;
      break;
    }
    i++;
  }
  if( p->nFrac ){
    p->nFrac = p->nDigit - (p->nFrac - 1);
  }
  if( iExp>0 ){
    if( p->nFrac>0 ){
      if( iExp<=p->nFrac ){
        p->nFrac -= iExp;
        iExp = 0;
      }else{
        iExp -= p->nFrac;
        p->nFrac = 0;
      }
    }
    if( iExp>0 ){   
      p->a = sqlite3_realloc64(p->a, p->nDigit + iExp + 1 );
      if( p->a==0 ) goto new_no_mem;
      memset(p->a+p->nDigit, 0, iExp);
      p->nDigit += iExp;
    }
  }else if( iExp<0 ){
    int nExtra;
    iExp = -iExp;
    nExtra = p->nDigit - p->nFrac - 1;
    if( nExtra ){
      if( nExtra>=iExp ){
        p->nFrac += iExp;
        iExp  = 0;
      }else{
        iExp -= nExtra;
        p->nFrac = p->nDigit - 1;
      }
    }
    if( iExp>0 ){
      p->a = sqlite3_realloc64(p->a, p->nDigit + iExp + 1 );
      if( p->a==0 ) goto new_no_mem;
      memmove(p->a+iExp, p->a, p->nDigit);
      memset(p->a, 0, iExp);
      p->nDigit += iExp;
      p->nFrac += iExp;
    }
  }
  return p;

new_no_mem:
  if( pCtx ) sqlite3_result_error_nomem(pCtx);
  sqlite3_free(p);
  return 0;
}

/*
** Make the given Decimal the result.
*/
static void decimal_result(sqlite3_context *pCtx, Decimal *p){
  char *z;
  int i, j;
  int n;
  if( p==0 || p->oom ){
    sqlite3_result_error_nomem(pCtx);
    return;
  }
  if( p->isNull ){
    sqlite3_result_null(pCtx);
    return;
  }
  z = sqlite3_malloc( p->nDigit+4 );
  if( z==0 ){
    sqlite3_result_error_nomem(pCtx);
    return;
  }
  i = 0;
  if( p->nDigit==0 || (p->nDigit==1 && p->a[0]==0) ){
    p->sign = 0;
  }
  if( p->sign ){
    z[0] = '-';
    i = 1;
  }
  n = p->nDigit - p->nFrac;
  if( n<=0 ){
    z[i++] = '0';
  }
  j = 0;
  while( n>1 && p->a[j]==0 ){
    j++;
    n--;
  }
  while( n>0  ){
    z[i++] = p->a[j] + '0';
    j++;
    n--;
  }
  if( p->nFrac ){
    z[i++] = '.';
    do{
      z[i++] = p->a[j] + '0';
      j++;
    }while( j<p->nDigit );
  }
  z[i] = 0;
  sqlite3_result_text(pCtx, z, i, sqlite3_free);
}

/*
** SQL Function:   decimal(X)
**
** Convert input X into decimal and then back into text
*/
static void decimalFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  Decimal *p = decimal_new(context, argv[0], 0, 0);
  UNUSED_PARAMETER(argc);
  decimal_result(context, p);
  decimal_free(p);
}

/*
** Compare to Decimal objects.  Return negative, 0, or positive if the
** first object is less than, equal to, or greater than the second.
**
** Preconditions for this routine:
**
**    pA!=0
**    pA->isNull==0
**    pB!=0
**    pB->isNull==0
*/
static int decimal_cmp(const Decimal *pA, const Decimal *pB){
  int nASig, nBSig, rc, n;
  if( pA->sign!=pB->sign ){
    return pA->sign ? -1 : +1;
  }
  if( pA->sign ){
    const Decimal *pTemp = pA;
    pA = pB;
    pB = pTemp;
  }
  nASig = pA->nDigit - pA->nFrac;
  nBSig = pB->nDigit - pB->nFrac;
  if( nASig!=nBSig ){
    return nASig - nBSig;
  }
  n = pA->nDigit;
  if( n>pB->nDigit ) n = pB->nDigit;
  rc = memcmp(pA->a, pB->a, n);
  if( rc==0 ){
    rc = pA->nDigit - pB->nDigit;
  }
  return rc;
}

/*
** SQL Function:   decimal_cmp(X, Y)
**
** Return negative, zero, or positive if X is less then, equal to, or
** greater than Y.
*/
static void decimalCmpFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  Decimal *pA = 0, *pB = 0;
  int rc;

  UNUSED_PARAMETER(argc);
  pA = decimal_new(context, argv[0], 0, 0);
  if( pA==0 || pA->isNull ) goto cmp_done;
  pB = decimal_new(context, argv[1], 0, 0);
  if( pB==0 || pB->isNull ) goto cmp_done;
  rc = decimal_cmp(pA, pB);
  if( rc<0 ) rc = -1;
  else if( rc>0 ) rc = +1;
  sqlite3_result_int(context, rc);
cmp_done:
  decimal_free(pA);
  decimal_free(pB);
}

/*
** Expand the Decimal so that it has a least nDigit digits and nFrac
** digits to the right of the decimal point.
*/
static void decimal_expand(Decimal *p, int nDigit, int nFrac){
  int nAddSig;
  int nAddFrac;
  if( p==0 ) return;
  nAddFrac = nFrac - p->nFrac;
  nAddSig = (nDigit - p->nDigit) - nAddFrac;
  if( nAddFrac==0 && nAddSig==0 ) return;
  p->a = sqlite3_realloc64(p->a, nDigit+1);
  if( p->a==0 ){
    p->oom = 1;
    return;
  }
  if( nAddSig ){
    memmove(p->a+nAddSig, p->a, p->nDigit);
    memset(p->a, 0, nAddSig);
    p->nDigit += nAddSig;
  }
  if( nAddFrac ){
    memset(p->a+p->nDigit, 0, nAddFrac);
    p->nDigit += nAddFrac;
    p->nFrac += nAddFrac;
  }
}

/*
** Add the value pB into pA.
**
** Both pA and pB might become denormalized by this routine.
*/
static void decimal_add(Decimal *pA, Decimal *pB){
  int nSig, nFrac, nDigit;
  int i, rc;
  if( pA==0 ){
    return;
  }
  if( pA->oom || pB==0 || pB->oom ){
    pA->oom = 1;
    return;
  }
  if( pA->isNull || pB->isNull ){
    pA->isNull = 1;
    return;
  }
  nSig = pA->nDigit - pA->nFrac;
  if( nSig && pA->a[0]==0 ) nSig--;
  if( nSig<pB->nDigit-pB->nFrac ){
    nSig = pB->nDigit - pB->nFrac;
  }
  nFrac = pA->nFrac;
  if( nFrac<pB->nFrac ) nFrac = pB->nFrac;
  nDigit = nSig + nFrac + 1;
  decimal_expand(pA, nDigit, nFrac);
  decimal_expand(pB, nDigit, nFrac);
  if( pA->oom || pB->oom ){
    pA->oom = 1;
  }else{
    if( pA->sign==pB->sign ){
      int carry = 0;
      for(i=nDigit-1; i>=0; i--){
        int x = pA->a[i] + pB->a[i] + carry;
        if( x>=10 ){
          carry = 1;
          pA->a[i] = x - 10;
        }else{
          carry = 0;
          pA->a[i] = x;
        }
      }
    }else{
      signed char *aA, *aB;
      int borrow = 0;
      rc = memcmp(pA->a, pB->a, nDigit);
      if( rc<0 ){
        aA = pB->a;
        aB = pA->a;
        pA->sign = !pA->sign;
      }else{
        aA = pA->a;
        aB = pB->a;
      }
      for(i=nDigit-1; i>=0; i--){
        int x = aA[i] - aB[i] - borrow;
        if( x<0 ){
          pA->a[i] = x+10;
          borrow = 1;
        }else{
          pA->a[i] = x;
          borrow = 0;
        }
      }
    }
  }
}

/*
** Compare text in decimal order.
*/
static int decimalCollFunc(
  void *notUsed,
  int nKey1, const void *pKey1,
  int nKey2, const void *pKey2
){
  const unsigned char *zA = (const unsigned char*)pKey1;
  const unsigned char *zB = (const unsigned char*)pKey2;
  Decimal *pA = decimal_new(0, 0, nKey1, zA);
  Decimal *pB = decimal_new(0, 0, nKey2, zB);
  int rc;
  UNUSED_PARAMETER(notUsed);
  if( pA==0 || pB==0 ){
    rc = 0;
  }else{
    rc = decimal_cmp(pA, pB);
  }
  decimal_free(pA);
  decimal_free(pB);
  return rc;
}


/*
** SQL Function:   decimal_add(X, Y)
**                 decimal_sub(X, Y)
**
** Return the sum or difference of X and Y.
*/
static void decimalAddFunc(
  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);
  decimal_add(pA, pB);
  decimal_result(context, pA);
  decimal_free(pA);
  decimal_free(pB);
}
static void decimalSubFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  Decimal *pA = decimal_new(context, argv[0], 0, 0);
  Decimal *pB = decimal_new(context, argv[1], 0, 0);
  UNUSED_PARAMETER(argc);
  if( pB ){
    pB->sign = !pB->sign;
    decimal_add(pA, pB);
    decimal_result(context, pA);
  }
  decimal_free(pA);
  decimal_free(pB);
}

/* Aggregate funcion:   decimal_sum(X)
**
** Works like sum() except that it uses decimal arithmetic for unlimited
** precision.
*/
static void decimalSumStep(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  Decimal *p;
  Decimal *pArg;
  UNUSED_PARAMETER(argc);
  p = sqlite3_aggregate_context(context, sizeof(*p));
  if( p==0 ) return;
  if( !p->isInit ){
    p->isInit = 1;
    p->a = sqlite3_malloc(2);
    if( p->a==0 ){
      p->oom = 1;
    }else{
      p->a[0] = 0;
    }
    p->nDigit = 1;
    p->nFrac = 0;
  }
  if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
  pArg = decimal_new(context, argv[0], 0, 0);
  decimal_add(p, pArg);
  decimal_free(pArg);
}
static void decimalSumInverse(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  Decimal *p;
  Decimal *pArg;
  UNUSED_PARAMETER(argc);
  p = sqlite3_aggregate_context(context, sizeof(*p));
  if( p==0 ) return;
  if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
  pArg = decimal_new(context, argv[0], 0, 0);
  if( pArg ) pArg->sign = !pArg->sign;
  decimal_add(p, pArg);
  decimal_free(pArg);
}
static void decimalSumValue(sqlite3_context *context){
  Decimal *p = sqlite3_aggregate_context(context, 0);
  if( p==0 ) return;
  decimal_result(context, p);
}
static void decimalSumFinalize(sqlite3_context *context){
  Decimal *p = sqlite3_aggregate_context(context, 0);
  if( p==0 ) return;
  decimal_result(context, p);
  decimal_clear(p);
}

/*
** SQL Function:   decimal_mul(X, Y)
**
** Return the product of X and Y.
**
** All significant digits after the decimal point are retained.
** Trailing zeros after the decimal point are omitted as long as
** the number of digits after the decimal point is no less than
** either the number of digits in either input.
*/
static void decimalMulFunc(
  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);
  signed char *acc = 0;
  int i, j, k;
  int minFrac;
  UNUSED_PARAMETER(argc);
  if( pA==0 || pA->oom || pA->isNull
   || pB==0 || pB->oom || pB->isNull 
  ){
    goto mul_end;
  }
  acc = sqlite3_malloc64( pA->nDigit + pB->nDigit + 2 );
  if( acc==0 ){
    sqlite3_result_error_nomem(context);
    goto mul_end;
  }
  memset(acc, 0, pA->nDigit + pB->nDigit + 2);
  minFrac = pA->nFrac;
  if( pB->nFrac<minFrac ) minFrac = pB->nFrac;
  for(i=pA->nDigit-1; i>=0; i--){
    signed char f = pA->a[i];
    int carry = 0, x;
    for(j=pB->nDigit-1, k=i+j+3; j>=0; j--, k--){
      x = acc[k] + f*pB->a[j] + carry;
      acc[k] = x%10;
      carry = x/10;
    }
    x = acc[k] + carry;
    acc[k] = x%10;
    acc[k-1] += x/10;
  }
  sqlite3_free(pA->a);
  pA->a = acc;
  acc = 0;
  pA->nDigit += pB->nDigit + 2;
  pA->nFrac += pB->nFrac;
  pA->sign ^= pB->sign;
  while( pA->nFrac>minFrac && pA->a[pA->nDigit-1]==0 ){
    pA->nFrac--;
    pA->nDigit--;
  }
  decimal_result(context, pA);

mul_end:
  sqlite3_free(acc);
  decimal_free(pA);
  decimal_free(pB);
}

#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_decimal_init(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  static const struct {
    const char *zFuncName;
    int nArg;
    void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
  } aFunc[] = {
    { "decimal",       1,   decimalFunc        },
    { "decimal_cmp",   2,   decimalCmpFunc     },
    { "decimal_add",   2,   decimalAddFunc     },
    { "decimal_sub",   2,   decimalSubFunc     },
    { "decimal_mul",   2,   decimalMulFunc     },
  };
  unsigned int i;
  (void)pzErrMsg;  /* Unused parameter */

  SQLITE_EXTENSION_INIT2(pApi);

  for(i=0; i<(int)(sizeof(aFunc)/sizeof(aFunc[0])) && rc==SQLITE_OK; i++){
    rc = sqlite3_create_function(db, aFunc[i].zFuncName, aFunc[i].nArg,
                   SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
                   0, aFunc[i].xFunc, 0, 0);
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_window_function(db, "decimal_sum", 1,
                   SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC, 0,
                   decimalSumStep, decimalSumFinalize,
                   decimalSumValue, decimalSumInverse, 0);
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_collation(db, "decimal", SQLITE_UTF8,
                                  0, decimalCollFunc);
  }
  return rc;
}

Changes to ext/misc/eval.c.

40
41
42
43
44
45
46
47

48
49
50
51
52
53
54
40
41
42
43
44
45
46

47
48
49
50
51
52
53
54







-
+







    size_t sz = strlen(z);
    if( (sqlite3_int64)sz+p->nUsed+p->szSep+1 > p->nAlloc ){
      char *zNew;
      p->nAlloc = p->nAlloc*2 + sz + p->szSep + 1;
      /* Using sqlite3_realloc64() would be better, but it is a recent
      ** addition and will cause a segfault if loaded by an older version
      ** of SQLite.  */
      zNew = p->nAlloc<=0x7fffffff ? sqlite3_realloc(p->z, (int)p->nAlloc) : 0;
      zNew = p->nAlloc<=0x7fffffff ? sqlite3_realloc64(p->z, p->nAlloc) : 0;
      if( zNew==0 ){
        sqlite3_free(p->z);
        memset(p, 0, sizeof(*p));
        return 1;
      }
      p->z = zNew;
    }
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
124
125







-
+
+


-
+
+




  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg;  /* Unused parameter */
  rc = sqlite3_create_function(db, "eval", 1, SQLITE_UTF8, 0,
  rc = sqlite3_create_function(db, "eval", 1, 
                               SQLITE_UTF8|SQLITE_DIRECTONLY, 0,
                               sqlEvalFunc, 0, 0);
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "eval", 2, SQLITE_UTF8, 0,
    rc = sqlite3_create_function(db, "eval", 2,
                                 SQLITE_UTF8|SQLITE_DIRECTONLY, 0,
                                 sqlEvalFunc, 0, 0);
  }
  return rc;
}

Changes to ext/misc/explain.c.

12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
12
13
14
15
16
17
18

19
20
21
22
23
24
25
26







-
+







**
** This file demonstrates an eponymous virtual table that returns the
** EXPLAIN output from an SQL statement.
**
** Usage example:
**
**     .load ./explain
**     SELECT p2 FROM explain('SELECT * FROM sqlite_master')
**     SELECT p2 FROM explain('SELECT * FROM sqlite_schema')
**      WHERE opcode='OpenRead';
**
** This module was originally written to help simplify SQLite testing,
** by providing an easier means of verifying certain patterns in the
** generated bytecode.
*/
#if !defined(SQLITEINT_H)

Changes to ext/misc/fileio.c.

68
69
70
71
72
73
74





75
76
77
78
79
80
81
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86







+
+
+
+
+







**            symlink, a text value containing the text of the link. For a
**            directory, NULL.
**
**   If a non-NULL value is specified for the optional $dir parameter and
**   $path is a relative path, then $path is interpreted relative to $dir. 
**   And the paths returned in the "name" column of the table are also 
**   relative to directory $dir.
**
** Notes on building this extension for Windows:
**   Unless linked statically with the SQLite library, a preprocessor
**   symbol, FILEIO_WIN32_DLL, must be #define'd to create a stand-alone
**   DLL form of this extension for WIN32. See its use below for details.
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#include <stdio.h>
#include <string.h>
#include <assert.h>

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







-
+
+
+
+
+
+
+
+



-
+

+
+


-
+
+
+
+



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

+







#define FSDIR_COLUMN_DATA     3     /* File content */
#define FSDIR_COLUMN_PATH     4     /* Path to top of search */
#define FSDIR_COLUMN_DIR      5     /* Path is relative to this directory */


/*
** Set the result stored by context ctx to a blob containing the 
** contents of file zName.
** contents of file zName.  Or, leave the result unchanged (NULL)
** if the file does not exist or is unreadable.
**
** If the file exceeds the SQLite blob size limit, through an
** SQLITE_TOOBIG error.
**
** Throw an SQLITE_IOERR if there are difficulties pulling the file
** off of disk.
*/
static void readFileContents(sqlite3_context *ctx, const char *zName){
  FILE *in;
  long nIn;
  sqlite3_int64 nIn;
  void *pBuf;
  sqlite3 *db;
  int mxBlob;

  in = fopen(zName, "rb");
  if( in==0 ) return;
  if( in==0 ){
    /* File does not exist or is unreadable. Leave the result set to NULL. */
    return;
  }
  fseek(in, 0, SEEK_END);
  nIn = ftell(in);
  rewind(in);
  db = sqlite3_context_db_handle(ctx);
  mxBlob = sqlite3_limit(db, SQLITE_LIMIT_LENGTH, -1);
  if( nIn>mxBlob ){
    sqlite3_result_error_code(ctx, SQLITE_TOOBIG);
    fclose(in);
    return;
  }
  pBuf = sqlite3_malloc( nIn );
  if( pBuf && 1==fread(pBuf, nIn, 1, in) ){
    sqlite3_result_blob(ctx, pBuf, nIn, sqlite3_free);
  pBuf = sqlite3_malloc64( nIn ? nIn : 1 );
  if( pBuf==0 ){
    sqlite3_result_error_nomem(ctx);
    fclose(in);
    return;
  }
  if( nIn==(sqlite3_int64)fread(pBuf, 1, (size_t)nIn, in) ){
    sqlite3_result_blob64(ctx, pBuf, nIn, sqlite3_free);
  }else{
    sqlite3_result_error_code(ctx, SQLITE_IOERR);
    sqlite3_free(pBuf);
  }
  fclose(in);
}

/*
** Implementation of the "readfile(X)" SQL function.  The entire content
196
197
198
199
200
201
202
















203
204
205
206
207
208
209
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







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








  fileIntervals.LowPart = pFileTime->dwLowDateTime;
  fileIntervals.HighPart = pFileTime->dwHighDateTime;

  return (fileIntervals.QuadPart - epochIntervals.QuadPart) / 10000000;
}


#if defined(FILEIO_WIN32_DLL) && (defined(_WIN32) || defined(WIN32))
#  /* To allow a standalone DLL, use this next replacement function: */
#  undef sqlite3_win32_utf8_to_unicode
#  define sqlite3_win32_utf8_to_unicode utf8_to_utf16
#
LPWSTR utf8_to_utf16(const char *z){
  int nAllot = MultiByteToWideChar(CP_UTF8, 0, z, -1, NULL, 0);
  LPWSTR rv = sqlite3_malloc(nAllot * sizeof(WCHAR));
  if( rv!=0 && 0 < MultiByteToWideChar(CP_UTF8, 0, z, -1, rv, nAllot) )
    return rv;
  sqlite3_free(rv);
  return 0;
}
#endif

/*
** This function attempts to normalize the time values found in the stat()
** buffer to UTC.  This is necessary on Win32, where the runtime library
** appears to return these values as local times.
*/
static void statTimesToUtc(
  const char *zPath,
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
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







-
+
+






-
+
-




















-
+







#endif
}

/*
** Argument zFile is the name of a file that will be created and/or written
** by SQL function writefile(). This function ensures that the directory
** zFile will be written to exists, creating it if required. The permissions
** for any path components created by this function are set to (mode&0777).
** for any path components created by this function are set in accordance
** with the current umask.
**
** If an OOM condition is encountered, SQLITE_NOMEM is returned. Otherwise,
** SQLITE_OK is returned if the directory is successfully created, or
** SQLITE_ERROR otherwise.
*/
static int makeDirectory(
  const char *zFile,
  const char *zFile
  mode_t mode
){
  char *zCopy = sqlite3_mprintf("%s", zFile);
  int rc = SQLITE_OK;

  if( zCopy==0 ){
    rc = SQLITE_NOMEM;
  }else{
    int nCopy = (int)strlen(zCopy);
    int i = 1;

    while( rc==SQLITE_OK ){
      struct stat sStat;
      int rc2;

      for(; zCopy[i]!='/' && i<nCopy; i++);
      if( i==nCopy ) break;
      zCopy[i] = '\0';

      rc2 = fileStat(zCopy, &sStat);
      if( rc2!=0 ){
        if( mkdir(zCopy, mode & 0777) ) rc = SQLITE_ERROR;
        if( mkdir(zCopy, 0777) ) rc = SQLITE_ERROR;
      }else{
        if( !S_ISDIR(sStat.st_mode) ) rc = SQLITE_ERROR;
      }
      zCopy[i] = '/';
      i++;
    }

318
319
320
321
322
323
324

325
326
327
328

329
330
331
332
333
334
335
364
365
366
367
368
369
370
371
372
373
374

375
376
377
378
379
380
381
382







+



-
+







static int writeFile(
  sqlite3_context *pCtx,          /* Context to return bytes written in */
  const char *zFile,              /* File to write */
  sqlite3_value *pData,           /* Data to write */
  mode_t mode,                    /* MODE parameter passed to writefile() */
  sqlite3_int64 mtime             /* MTIME parameter (or -1 to not set time) */
){
  if( zFile==0 ) return 1;
#if !defined(_WIN32) && !defined(WIN32)
  if( S_ISLNK(mode) ){
    const char *zTo = (const char*)sqlite3_value_text(pData);
    if( symlink(zTo, zFile)<0 ) return 1;
    if( zTo==0 || symlink(zTo, zFile)<0 ) return 1;
  }else
#endif
  {
    if( S_ISDIR(mode) ){
      if( mkdir(zFile, mode) ){
        /* The mkdir() call to create the directory failed. This might not
        ** be an error though - if there is already a directory at the same
365
366
367
368
369
370
371

372
373
374
375
376
377
378
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426







+







      if( rc ) return 2;
      sqlite3_result_int64(pCtx, nWrite);
    }
  }

  if( mtime>=0 ){
#if defined(_WIN32)
#if !SQLITE_OS_WINRT
    /* Windows */
    FILETIME lastAccess;
    FILETIME lastWrite;
    SYSTEMTIME currentTime;
    LONGLONG intervals;
    HANDLE hFile;
    LPWSTR zUnicodeName;
395
396
397
398
399
400
401

402
403
404
405
406
407
408
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457







+







    if( hFile!=INVALID_HANDLE_VALUE ){
      BOOL bResult = SetFileTime(hFile, NULL, &lastAccess, &lastWrite);
      CloseHandle(hFile);
      return !bResult;
    }else{
      return 1;
    }
#endif
#elif defined(AT_FDCWD) && 0 /* utimensat() is not universally available */
    /* Recent unix */
    struct timespec times[2];
    times[0].tv_nsec = times[1].tv_nsec = 0;
    times[0].tv_sec = time(0);
    times[1].tv_sec = mtime;
    if( utimensat(AT_FDCWD, zFile, times, AT_SYMLINK_NOFOLLOW) ){
451
452
453
454
455
456
457
458

459
460
461
462
463
464
465
500
501
502
503
504
505
506

507
508
509
510
511
512
513
514







-
+







  }
  if( argc==4 ){
    mtime = sqlite3_value_int64(argv[3]);
  }

  res = writeFile(context, zFile, argv[1], mode, mtime);
  if( res==1 && errno==ENOENT ){
    if( makeDirectory(zFile, mode)==SQLITE_OK ){
    if( makeDirectory(zFile)==SQLITE_OK ){
      res = writeFile(context, zFile, argv[1], mode, mtime);
    }
  }

  if( argc>2 && res!=0 ){
    if( S_ISLNK(mode) ){
      ctxErrorMsg(context, "failed to create symlink: %s", zFile);
556
557
558
559
560
561
562

563
564
565
566
567
568
569
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619







+







  (void)argv;
  (void)pzErr;
  rc = sqlite3_declare_vtab(db, "CREATE TABLE x" FSDIR_SCHEMA);
  if( rc==SQLITE_OK ){
    pNew = (fsdir_tab*)sqlite3_malloc( sizeof(*pNew) );
    if( pNew==0 ) return SQLITE_NOMEM;
    memset(pNew, 0, sizeof(*pNew));
    sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY);
  }
  *ppVtab = (sqlite3_vtab*)pNew;
  return rc;
}

/*
** This method is the destructor for fsdir vtab objects.
642
643
644
645
646
647
648
649
650


651
652
653
654
655
656
657
692
693
694
695
696
697
698


699
700
701
702
703
704
705
706
707







-
-
+
+







  pCur->iRowid++;
  if( S_ISDIR(m) ){
    /* Descend into this directory */
    int iNew = pCur->iLvl + 1;
    FsdirLevel *pLvl;
    if( iNew>=pCur->nLvl ){
      int nNew = iNew+1;
      int nByte = nNew*sizeof(FsdirLevel);
      FsdirLevel *aNew = (FsdirLevel*)sqlite3_realloc(pCur->aLvl, nByte);
      sqlite3_int64 nByte = nNew*sizeof(FsdirLevel);
      FsdirLevel *aNew = (FsdirLevel*)sqlite3_realloc64(pCur->aLvl, nByte);
      if( aNew==0 ) return SQLITE_NOMEM;
      memset(&aNew[pCur->nLvl], 0, sizeof(FsdirLevel)*(nNew-pCur->nLvl));
      pCur->aLvl = aNew;
      pCur->nLvl = nNew;
    }
    pCur->iLvl = iNew;
    pLvl = &pCur->aLvl[iNew];
723
724
725
726
727
728
729
730

731
732
733
734
735
736
737
738

739
740
741
742
743
744
745
773
774
775
776
777
778
779

780
781
782
783
784
785
786
787

788
789
790
791
792
793
794
795







-
+







-
+







      mode_t m = pCur->sStat.st_mode;
      if( S_ISDIR(m) ){
        sqlite3_result_null(ctx);
#if !defined(_WIN32) && !defined(WIN32)
      }else if( S_ISLNK(m) ){
        char aStatic[64];
        char *aBuf = aStatic;
        int nBuf = 64;
        sqlite3_int64 nBuf = 64;
        int n;

        while( 1 ){
          n = readlink(pCur->zPath, aBuf, nBuf);
          if( n<nBuf ) break;
          if( aBuf!=aStatic ) sqlite3_free(aBuf);
          nBuf = nBuf*2;
          aBuf = sqlite3_malloc(nBuf);
          aBuf = sqlite3_malloc64(nBuf);
          if( aBuf==0 ){
            sqlite3_result_error_nomem(ctx);
            return SQLITE_NOMEM;
          }
        }

        sqlite3_result_text(ctx, aBuf, n, SQLITE_TRANSIENT);
949
950
951
952
953
954
955
956


957
958
959


960
961
962
963
964
965
966
967
968
969
970








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







-
+
+


-
+
+











+
+
+
+
+
+
+
+
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg;  /* Unused parameter */
  rc = sqlite3_create_function(db, "readfile", 1, SQLITE_UTF8, 0,
  rc = sqlite3_create_function(db, "readfile", 1, 
                               SQLITE_UTF8|SQLITE_DIRECTONLY, 0,
                               readfileFunc, 0, 0);
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "writefile", -1, SQLITE_UTF8, 0,
    rc = sqlite3_create_function(db, "writefile", -1,
                                 SQLITE_UTF8|SQLITE_DIRECTONLY, 0,
                                 writefileFunc, 0, 0);
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "lsmode", 1, SQLITE_UTF8, 0,
                                 lsModeFunc, 0, 0);
  }
  if( rc==SQLITE_OK ){
    rc = fsdirRegister(db);
  }
  return rc;
}

#if defined(FILEIO_WIN32_DLL) && (defined(_WIN32) || defined(WIN32))
/* To allow a standalone DLL, make test_windirent.c use the same
 * redefined SQLite API calls as the above extension code does.
 * Just pull in this .c to accomplish this. As a beneficial side
 * effect, this extension becomes a single translation unit. */
#  include "test_windirent.c"
#endif

Added ext/misc/fossildelta.c.





































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2019-02-19
**
** 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 SQLite extension implements the delta functions used by the RBU
** extension. Three scalar functions and one table-valued function are
** implemented here:
**
**   delta_apply(X,D)     -- apply delta D to file X and return the result
**   delta_create(X,Y)    -- compute and return a delta that carries X into Y
**   delta_output_size(D) -- blob size in bytes output from applying delta D
**   delta_parse(D)       -- returns rows describing delta D
**
** The delta format is the Fossil delta format, described in a comment
** on the delete_create() function implementation below, and also at
**
**    https://www.fossil-scm.org/fossil/doc/trunk/www/delta_format.wiki
**
** This delta format is used by the RBU extension, which is the main
** reason that these routines are included in the extension library.
** RBU does not use this extension directly.  Rather, this extension is
** provided as a convenience to developers who want to analyze RBU files 
** that contain deltas.
*/
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1

#ifndef SQLITE_AMALGAMATION
/*
** The "u32" type must be an unsigned 32-bit integer.  Adjust this
*/
typedef unsigned int u32;

/*
** Must be a 16-bit value
*/
typedef short int s16;
typedef unsigned short int u16;

#endif /* SQLITE_AMALGAMATION */


/*
** The width of a hash window in bytes.  The algorithm only works if this
** is a power of 2.
*/
#define NHASH 16

/*
** The current state of the rolling hash.
**
** z[] holds the values that have been hashed.  z[] is a circular buffer.
** z[i] is the first entry and z[(i+NHASH-1)%NHASH] is the last entry of
** the window.
**
** Hash.a is the sum of all elements of hash.z[].  Hash.b is a weighted
** sum.  Hash.b is z[i]*NHASH + z[i+1]*(NHASH-1) + ... + z[i+NHASH-1]*1.
** (Each index for z[] should be module NHASH, of course.  The %NHASH operator
** is omitted in the prior expression for brevity.)
*/
typedef struct hash hash;
struct hash {
  u16 a, b;         /* Hash values */
  u16 i;            /* Start of the hash window */
  char z[NHASH];    /* The values that have been hashed */
};

/*
** Initialize the rolling hash using the first NHASH characters of z[]
*/
static void hash_init(hash *pHash, const char *z){
  u16 a, b, i;
  a = b = z[0];
  for(i=1; i<NHASH; i++){
    a += z[i];
    b += a;
  }
  memcpy(pHash->z, z, NHASH);
  pHash->a = a & 0xffff;
  pHash->b = b & 0xffff;
  pHash->i = 0;
}

/*
** Advance the rolling hash by a single character "c"
*/
static void hash_next(hash *pHash, int c){
  u16 old = pHash->z[pHash->i];
  pHash->z[pHash->i] = c;
  pHash->i = (pHash->i+1)&(NHASH-1);
  pHash->a = pHash->a - old + c;
  pHash->b = pHash->b - NHASH*old + pHash->a;
}

/*
** Return a 32-bit hash value
*/
static u32 hash_32bit(hash *pHash){
  return (pHash->a & 0xffff) | (((u32)(pHash->b & 0xffff))<<16);
}

/*
** Compute a hash on NHASH bytes.
**
** This routine is intended to be equivalent to:
**    hash h;
**    hash_init(&h, zInput);
**    return hash_32bit(&h);
*/
static u32 hash_once(const char *z){
  u16 a, b, i;
  a = b = z[0];
  for(i=1; i<NHASH; i++){
    a += z[i];
    b += a;
  }
  return a | (((u32)b)<<16);
}

/*
** Write an base-64 integer into the given buffer.
*/
static void putInt(unsigned int v, char **pz){
  static const char zDigits[] =
    "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~";
  /*  123456789 123456789 123456789 123456789 123456789 123456789 123 */
  int i, j;
  char zBuf[20];
  if( v==0 ){
    *(*pz)++ = '0';
    return;
  }
  for(i=0; v>0; i++, v>>=6){
    zBuf[i] = zDigits[v&0x3f];
  }
  for(j=i-1; j>=0; j--){
    *(*pz)++ = zBuf[j];
  }
}

/*
** Read bytes from *pz and convert them into a positive integer.  When
** finished, leave *pz pointing to the first character past the end of
** the integer.  The *pLen parameter holds the length of the string
** in *pz and is decremented once for each character in the integer.
*/
static unsigned int deltaGetInt(const char **pz, int *pLen){
  static const signed char zValue[] = {
    -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1,
     0,  1,  2,  3,  4,  5,  6,  7,    8,  9, -1, -1, -1, -1, -1, -1,
    -1, 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, -1, -1, -1, -1, 36,
    -1, 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, -1, -1, -1, 63, -1,
  };
  unsigned int v = 0;
  int c;
  unsigned char *z = (unsigned char*)*pz;
  unsigned char *zStart = z;
  while( (c = zValue[0x7f&*(z++)])>=0 ){
     v = (v<<6) + c;
  }
  z--;
  *pLen -= z - zStart;
  *pz = (char*)z;
  return v;
}

/*
** Return the number digits in the base-64 representation of a positive integer
*/
static int digit_count(int v){
  unsigned int i, x;
  for(i=1, x=64; v>=x; i++, x <<= 6){}
  return i;
}

#ifdef __GNUC__
# define GCC_VERSION (__GNUC__*1000000+__GNUC_MINOR__*1000+__GNUC_PATCHLEVEL__)
#else
# define GCC_VERSION 0
#endif

/*
** Compute a 32-bit big-endian checksum on the N-byte buffer.  If the
** buffer is not a multiple of 4 bytes length, compute the sum that would
** have occurred if the buffer was padded with zeros to the next multiple
** of four bytes.
*/
static unsigned int checksum(const char *zIn, size_t N){
  static const int byteOrderTest = 1;
  const unsigned char *z = (const unsigned char *)zIn;
  const unsigned char *zEnd = (const unsigned char*)&zIn[N&~3];
  unsigned sum = 0;
  assert( (z - (const unsigned char*)0)%4==0 );  /* Four-byte alignment */
  if( 0==*(char*)&byteOrderTest ){
    /* This is a big-endian machine */
    while( z<zEnd ){
      sum += *(unsigned*)z;
      z += 4;
    }
  }else{
    /* A little-endian machine */
#if GCC_VERSION>=4003000
    while( z<zEnd ){
      sum += __builtin_bswap32(*(unsigned*)z);
      z += 4;
    }
#elif defined(_MSC_VER) && _MSC_VER>=1300
    while( z<zEnd ){
      sum += _byteswap_ulong(*(unsigned*)z);
      z += 4;
    }
#else
    unsigned sum0 = 0;
    unsigned sum1 = 0;
    unsigned sum2 = 0;
    while(N >= 16){
      sum0 += ((unsigned)z[0] + z[4] + z[8] + z[12]);
      sum1 += ((unsigned)z[1] + z[5] + z[9] + z[13]);
      sum2 += ((unsigned)z[2] + z[6] + z[10]+ z[14]);
      sum  += ((unsigned)z[3] + z[7] + z[11]+ z[15]);
      z += 16;
      N -= 16;
    }
    while(N >= 4){
      sum0 += z[0];
      sum1 += z[1];
      sum2 += z[2];
      sum  += z[3];
      z += 4;
      N -= 4;
    }
    sum += (sum2 << 8) + (sum1 << 16) + (sum0 << 24);
#endif
  }
  switch(N&3){
    case 3:   sum += (z[2] << 8);
    case 2:   sum += (z[1] << 16);
    case 1:   sum += (z[0] << 24);
    default:  ;
  }
  return sum;
}

/*
** Create a new delta.
**
** The delta is written into a preallocated buffer, zDelta, which
** should be at least 60 bytes longer than the target file, zOut.
** The delta string will be NUL-terminated, but it might also contain
** embedded NUL characters if either the zSrc or zOut files are
** binary.  This function returns the length of the delta string
** in bytes, excluding the final NUL terminator character.
**
** Output Format:
**
** The delta begins with a base64 number followed by a newline.  This
** number is the number of bytes in the TARGET file.  Thus, given a
** delta file z, a program can compute the size of the output file
** simply by reading the first line and decoding the base-64 number
** found there.  The delta_output_size() routine does exactly this.
**
** After the initial size number, the delta consists of a series of
** literal text segments and commands to copy from the SOURCE file.
** A copy command looks like this:
**
**     NNN@MMM,
**
** where NNN is the number of bytes to be copied and MMM is the offset
** into the source file of the first byte (both base-64).   If NNN is 0
** it means copy the rest of the input file.  Literal text is like this:
**
**     NNN:TTTTT
**
** where NNN is the number of bytes of text (base-64) and TTTTT is the text.
**
** The last term is of the form
**
**     NNN;
**
** In this case, NNN is a 32-bit bigendian checksum of the output file
** that can be used to verify that the delta applied correctly.  All
** numbers are in base-64.
**
** Pure text files generate a pure text delta.  Binary files generate a
** delta that may contain some binary data.
**
** Algorithm:
**
** The encoder first builds a hash table to help it find matching
** patterns in the source file.  16-byte chunks of the source file
** sampled at evenly spaced intervals are used to populate the hash
** table.
**
** Next we begin scanning the target file using a sliding 16-byte
** window.  The hash of the 16-byte window in the target is used to
** search for a matching section in the source file.  When a match
** is found, a copy command is added to the delta.  An effort is
** made to extend the matching section to regions that come before
** and after the 16-byte hash window.  A copy command is only issued
** if the result would use less space that just quoting the text
** literally. Literal text is added to the delta for sections that
** do not match or which can not be encoded efficiently using copy
** commands.
*/
static int delta_create(
  const char *zSrc,      /* The source or pattern file */
  unsigned int lenSrc,   /* Length of the source file */
  const char *zOut,      /* The target file */
  unsigned int lenOut,   /* Length of the target file */
  char *zDelta           /* Write the delta into this buffer */
){
  int i, base;
  char *zOrigDelta = zDelta;
  hash h;
  int nHash;                 /* Number of hash table entries */
  int *landmark;             /* Primary hash table */
  int *collide;              /* Collision chain */
  int lastRead = -1;         /* Last byte of zSrc read by a COPY command */

  /* Add the target file size to the beginning of the delta
  */
  putInt(lenOut, &zDelta);
  *(zDelta++) = '\n';

  /* If the source file is very small, it means that we have no
  ** chance of ever doing a copy command.  Just output a single
  ** literal segment for the entire target and exit.
  */
  if( lenSrc<=NHASH ){
    putInt(lenOut, &zDelta);
    *(zDelta++) = ':';
    memcpy(zDelta, zOut, lenOut);
    zDelta += lenOut;
    putInt(checksum(zOut, lenOut), &zDelta);
    *(zDelta++) = ';';
    return zDelta - zOrigDelta;
  }

  /* Compute the hash table used to locate matching sections in the
  ** source file.
  */
  nHash = lenSrc/NHASH;
  collide = sqlite3_malloc64( (sqlite3_int64)nHash*2*sizeof(int) );
  memset(collide, -1, nHash*2*sizeof(int));
  landmark = &collide[nHash];
  for(i=0; i<lenSrc-NHASH; i+=NHASH){
    int hv = hash_once(&zSrc[i]) % nHash;
    collide[i/NHASH] = landmark[hv];
    landmark[hv] = i/NHASH;
  }

  /* Begin scanning the target file and generating copy commands and
  ** literal sections of the delta.
  */
  base = 0;    /* We have already generated everything before zOut[base] */
  while( base+NHASH<lenOut ){
    int iSrc, iBlock;
    unsigned int bestCnt, bestOfst=0, bestLitsz=0;
    hash_init(&h, &zOut[base]);
    i = 0;     /* Trying to match a landmark against zOut[base+i] */
    bestCnt = 0;
    while( 1 ){
      int hv;
      int limit = 250;

      hv = hash_32bit(&h) % nHash;
      iBlock = landmark[hv];
      while( iBlock>=0 && (limit--)>0 ){
        /*
        ** The hash window has identified a potential match against
        ** landmark block iBlock.  But we need to investigate further.
        **
        ** Look for a region in zOut that matches zSrc. Anchor the search
        ** at zSrc[iSrc] and zOut[base+i].  Do not include anything prior to
        ** zOut[base] or after zOut[outLen] nor anything after zSrc[srcLen].
        **
        ** Set cnt equal to the length of the match and set ofst so that
        ** zSrc[ofst] is the first element of the match.  litsz is the number
        ** of characters between zOut[base] and the beginning of the match.
        ** sz will be the overhead (in bytes) needed to encode the copy
        ** command.  Only generate copy command if the overhead of the
        ** copy command is less than the amount of literal text to be copied.
        */
        int cnt, ofst, litsz;
        int j, k, x, y;
        int sz;
        int limitX;

        /* Beginning at iSrc, match forwards as far as we can.  j counts
        ** the number of characters that match */
        iSrc = iBlock*NHASH;
        y = base+i;
        limitX = ( lenSrc-iSrc <= lenOut-y ) ? lenSrc : iSrc + lenOut - y;
        for(x=iSrc; x<limitX; x++, y++){
          if( zSrc[x]!=zOut[y] ) break;
        }
        j = x - iSrc - 1;

        /* Beginning at iSrc-1, match backwards as far as we can.  k counts
        ** the number of characters that match */
        for(k=1; k<iSrc && k<=i; k++){
          if( zSrc[iSrc-k]!=zOut[base+i-k] ) break;
        }
        k--;

        /* Compute the offset and size of the matching region */
        ofst = iSrc-k;
        cnt = j+k+1;
        litsz = i-k;  /* Number of bytes of literal text before the copy */
        /* sz will hold the number of bytes needed to encode the "insert"
        ** command and the copy command, not counting the "insert" text */
        sz = digit_count(i-k)+digit_count(cnt)+digit_count(ofst)+3;
        if( cnt>=sz && cnt>bestCnt ){
          /* Remember this match only if it is the best so far and it
          ** does not increase the file size */
          bestCnt = cnt;
          bestOfst = iSrc-k;
          bestLitsz = litsz;
        }

        /* Check the next matching block */
        iBlock = collide[iBlock];
      }

      /* We have a copy command that does not cause the delta to be larger
      ** than a literal insert.  So add the copy command to the delta.
      */
      if( bestCnt>0 ){
        if( bestLitsz>0 ){
          /* Add an insert command before the copy */
          putInt(bestLitsz,&zDelta);
          *(zDelta++) = ':';
          memcpy(zDelta, &zOut[base], bestLitsz);
          zDelta += bestLitsz;
          base += bestLitsz;
        }
        base += bestCnt;
        putInt(bestCnt, &zDelta);
        *(zDelta++) = '@';
        putInt(bestOfst, &zDelta);
        *(zDelta++) = ',';
        if( bestOfst + bestCnt -1 > lastRead ){
          lastRead = bestOfst + bestCnt - 1;
        }
        bestCnt = 0;
        break;
      }

      /* If we reach this point, it means no match is found so far */
      if( base+i+NHASH>=lenOut ){
        /* We have reached the end of the file and have not found any
        ** matches.  Do an "insert" for everything that does not match */
        putInt(lenOut-base, &zDelta);
        *(zDelta++) = ':';
        memcpy(zDelta, &zOut[base], lenOut-base);
        zDelta += lenOut-base;
        base = lenOut;
        break;
      }

      /* Advance the hash by one character.  Keep looking for a match */
      hash_next(&h, zOut[base+i+NHASH]);
      i++;
    }
  }
  /* Output a final "insert" record to get all the text at the end of
  ** the file that does not match anything in the source file.
  */
  if( base<lenOut ){
    putInt(lenOut-base, &zDelta);
    *(zDelta++) = ':';
    memcpy(zDelta, &zOut[base], lenOut-base);
    zDelta += lenOut-base;
  }
  /* Output the final checksum record. */
  putInt(checksum(zOut, lenOut), &zDelta);
  *(zDelta++) = ';';
  sqlite3_free(collide);
  return zDelta - zOrigDelta;
}

/*
** Return the size (in bytes) of the output from applying
** a delta.
**
** This routine is provided so that an procedure that is able
** to call delta_apply() can learn how much space is required
** for the output and hence allocate nor more space that is really
** needed.
*/
static int delta_output_size(const char *zDelta, int lenDelta){
  int size;
  size = deltaGetInt(&zDelta, &lenDelta);
  if( *zDelta!='\n' ){
    /* ERROR: size integer not terminated by "\n" */
    return -1;
  }
  return size;
}


/*
** Apply a delta.
**
** The output buffer should be big enough to hold the whole output
** file and a NUL terminator at the end.  The delta_output_size()
** routine will determine this size for you.
**
** The delta string should be null-terminated.  But the delta string
** may contain embedded NUL characters (if the input and output are
** binary files) so we also have to pass in the length of the delta in
** the lenDelta parameter.
**
** This function returns the size of the output file in bytes (excluding
** the final NUL terminator character).  Except, if the delta string is
** malformed or intended for use with a source file other than zSrc,
** then this routine returns -1.
**
** Refer to the delta_create() documentation above for a description
** of the delta file format.
*/
static int delta_apply(
  const char *zSrc,      /* The source or pattern file */
  int lenSrc,            /* Length of the source file */
  const char *zDelta,    /* Delta to apply to the pattern */
  int lenDelta,          /* Length of the delta */
  char *zOut             /* Write the output into this preallocated buffer */
){
  unsigned int limit;
  unsigned int total = 0;
#ifdef FOSSIL_ENABLE_DELTA_CKSUM_TEST
  char *zOrigOut = zOut;
#endif

  limit = deltaGetInt(&zDelta, &lenDelta);
  if( *zDelta!='\n' ){
    /* ERROR: size integer not terminated by "\n" */
    return -1;
  }
  zDelta++; lenDelta--;
  while( *zDelta && lenDelta>0 ){
    unsigned int cnt, ofst;
    cnt = deltaGetInt(&zDelta, &lenDelta);
    switch( zDelta[0] ){
      case '@': {
        zDelta++; lenDelta--;
        ofst = deltaGetInt(&zDelta, &lenDelta);
        if( lenDelta>0 && zDelta[0]!=',' ){
          /* ERROR: copy command not terminated by ',' */
          return -1;
        }
        zDelta++; lenDelta--;
        total += cnt;
        if( total>limit ){
          /* ERROR: copy exceeds output file size */
          return -1;
        }
        if( ofst+cnt > lenSrc ){
          /* ERROR: copy extends past end of input */
          return -1;
        }
        memcpy(zOut, &zSrc[ofst], cnt);
        zOut += cnt;
        break;
      }
      case ':': {
        zDelta++; lenDelta--;
        total += cnt;
        if( total>limit ){
          /* ERROR:  insert command gives an output larger than predicted */
          return -1;
        }
        if( cnt>lenDelta ){
          /* ERROR: insert count exceeds size of delta */
          return -1;
        }
        memcpy(zOut, zDelta, cnt);
        zOut += cnt;
        zDelta += cnt;
        lenDelta -= cnt;
        break;
      }
      case ';': {
        zDelta++; lenDelta--;
        zOut[0] = 0;
#ifdef FOSSIL_ENABLE_DELTA_CKSUM_TEST
        if( cnt!=checksum(zOrigOut, total) ){
          /* ERROR:  bad checksum */
          return -1;
        }
#endif
        if( total!=limit ){
          /* ERROR: generated size does not match predicted size */
          return -1;
        }
        return total;
      }
      default: {
        /* ERROR: unknown delta operator */
        return -1;
      }
    }
  }
  /* ERROR: unterminated delta */
  return -1;
}

/*
** SQL functions:  delta_create(X,Y)
**
** Return a delta for carrying X into Y.
*/
static void deltaCreateFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const char *aOrig; int nOrig;  /* old blob */
  const char *aNew;  int nNew;   /* new blob */
  char *aOut;        int nOut;   /* output delta */

  assert( argc==2 );
  if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
  if( sqlite3_value_type(argv[1])==SQLITE_NULL ) return;
  nOrig = sqlite3_value_bytes(argv[0]);
  aOrig = (const char*)sqlite3_value_blob(argv[0]);
  nNew = sqlite3_value_bytes(argv[1]);
  aNew = (const char*)sqlite3_value_blob(argv[1]);
  aOut = sqlite3_malloc64(nNew+70);
  if( aOut==0 ){
    sqlite3_result_error_nomem(context);
  }else{
    nOut = delta_create(aOrig, nOrig, aNew, nNew, aOut);
    if( nOut<0 ){
      sqlite3_free(aOut);
      sqlite3_result_error(context, "cannot create fossil delta", -1);
    }else{
      sqlite3_result_blob(context, aOut, nOut, sqlite3_free);
    }
  }
}

/*
** SQL functions:  delta_apply(X,D)
**
** Return the result of applying delta D to input X.
*/
static void deltaApplyFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const char *aOrig;   int nOrig;        /* The X input */
  const char *aDelta;  int nDelta;       /* The input delta (D) */
  char *aOut;          int nOut, nOut2;  /* The output */

  assert( argc==2 );
  if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
  if( sqlite3_value_type(argv[1])==SQLITE_NULL ) return;
  nOrig = sqlite3_value_bytes(argv[0]);
  aOrig = (const char*)sqlite3_value_blob(argv[0]);
  nDelta = sqlite3_value_bytes(argv[1]);
  aDelta = (const char*)sqlite3_value_blob(argv[1]);

  /* Figure out the size of the output */
  nOut = delta_output_size(aDelta, nDelta);
  if( nOut<0 ){
    sqlite3_result_error(context, "corrupt fossil delta", -1);
    return;
  }
  aOut = sqlite3_malloc64((sqlite3_int64)nOut+1);
  if( aOut==0 ){
    sqlite3_result_error_nomem(context);
  }else{
    nOut2 = delta_apply(aOrig, nOrig, aDelta, nDelta, aOut);
    if( nOut2!=nOut ){
      sqlite3_free(aOut);
      sqlite3_result_error(context, "corrupt fossil delta", -1);
    }else{
      sqlite3_result_blob(context, aOut, nOut, sqlite3_free);
    }
  }
}


/*
** SQL functions:  delta_output_size(D)
**
** Return the size of the output that results from applying delta D.
*/
static void deltaOutputSizeFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const char *aDelta;  int nDelta;       /* The input delta (D) */
  int nOut;                              /* Size of output */
  assert( argc==1 );
  if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
  nDelta = sqlite3_value_bytes(argv[0]);
  aDelta = (const char*)sqlite3_value_blob(argv[0]);

  /* Figure out the size of the output */
  nOut = delta_output_size(aDelta, nDelta);
  if( nOut<0 ){
    sqlite3_result_error(context, "corrupt fossil delta", -1);
    return;
  }else{
    sqlite3_result_int(context, nOut);
  }
}

/*****************************************************************************
** Table-valued SQL function:   delta_parse(DELTA)
**
** Schema:
**
**     CREATE TABLE delta_parse(
**       op TEXT,
**       a1 INT,
**       a2 ANY,
**       delta HIDDEN BLOB
**     );
**
** Given an input DELTA, this function parses the delta and returns
** rows for each entry in the delta.  The op column has one of the
** values SIZE, COPY, INSERT, CHECKSUM, ERROR.
**
** Assuming no errors, the first row has op='SIZE'.  a1 is the size of
** the output in bytes and a2 is NULL.
**
** After the initial SIZE row, there are zero or more 'COPY' and/or 'INSERT'
** rows.  A COPY row means content is copied from the source into the
** output.  Column a1 is the number of bytes to copy and a2 is the offset
** into source from which to begin copying.  An INSERT row means to
** insert text into the output stream.  Column a1 is the number of bytes
** to insert and column is a BLOB that contains the text to be inserted.
**
** The last row of a well-formed delta will have an op value of 'CHECKSUM'.
** The a1 column will be the value of the checksum and a2 will be NULL.
**
** If the input delta is not well-formed, then a row with an op value
** of 'ERROR' is returned.  The a1 value of the ERROR row is the offset
** into the delta where the error was encountered and a2 is NULL.
*/
typedef struct deltaparsevtab_vtab deltaparsevtab_vtab;
typedef struct deltaparsevtab_cursor deltaparsevtab_cursor;
struct deltaparsevtab_vtab {
  sqlite3_vtab base;  /* Base class - must be first */
  /* No additional information needed */
};
struct deltaparsevtab_cursor {
  sqlite3_vtab_cursor base;  /* Base class - must be first */
  char *aDelta;              /* The delta being parsed */
  int nDelta;                /* Number of bytes in the delta */
  int iCursor;               /* Current cursor location */
  int eOp;                   /* Name of current operator */
  unsigned int a1, a2;       /* Arguments to current operator */
  int iNext;                 /* Next cursor value */
};

/* Operator names:
*/
static const char *azOp[] = {
  "SIZE", "COPY", "INSERT", "CHECKSUM", "ERROR", "EOF"
};
#define DELTAPARSE_OP_SIZE         0
#define DELTAPARSE_OP_COPY         1
#define DELTAPARSE_OP_INSERT       2
#define DELTAPARSE_OP_CHECKSUM     3
#define DELTAPARSE_OP_ERROR        4
#define DELTAPARSE_OP_EOF          5

/*
** The deltaparsevtabConnect() method is invoked to create a new
** deltaparse virtual table.
**
** Think of this routine as the constructor for deltaparsevtab_vtab objects.
**
** All this routine needs to do is:
**
**    (1) Allocate the deltaparsevtab_vtab object and initialize all fields.
**
**    (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
**        result set of queries against the virtual table will look like.
*/
static int deltaparsevtabConnect(
  sqlite3 *db,
  void *pAux,
  int argc, const char *const*argv,
  sqlite3_vtab **ppVtab,
  char **pzErr
){
  deltaparsevtab_vtab *pNew;
  int rc;

  rc = sqlite3_declare_vtab(db,
           "CREATE TABLE x(op,a1,a2,delta HIDDEN)"
       );
  /* For convenience, define symbolic names for the index to each column. */
#define DELTAPARSEVTAB_OP     0
#define DELTAPARSEVTAB_A1     1
#define DELTAPARSEVTAB_A2     2
#define DELTAPARSEVTAB_DELTA  3
  if( rc==SQLITE_OK ){
    pNew = sqlite3_malloc64( sizeof(*pNew) );
    *ppVtab = (sqlite3_vtab*)pNew;
    if( pNew==0 ) return SQLITE_NOMEM;
    memset(pNew, 0, sizeof(*pNew));
    sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
  }
  return rc;
}

/*
** This method is the destructor for deltaparsevtab_vtab objects.
*/
static int deltaparsevtabDisconnect(sqlite3_vtab *pVtab){
  deltaparsevtab_vtab *p = (deltaparsevtab_vtab*)pVtab;
  sqlite3_free(p);
  return SQLITE_OK;
}

/*
** Constructor for a new deltaparsevtab_cursor object.
*/
static int deltaparsevtabOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
  deltaparsevtab_cursor *pCur;
  pCur = sqlite3_malloc( sizeof(*pCur) );
  if( pCur==0 ) return SQLITE_NOMEM;
  memset(pCur, 0, sizeof(*pCur));
  *ppCursor = &pCur->base;
  return SQLITE_OK;
}

/*
** Destructor for a deltaparsevtab_cursor.
*/
static int deltaparsevtabClose(sqlite3_vtab_cursor *cur){
  deltaparsevtab_cursor *pCur = (deltaparsevtab_cursor*)cur;
  sqlite3_free(pCur->aDelta);
  sqlite3_free(pCur);
  return SQLITE_OK;
}


/*
** Advance a deltaparsevtab_cursor to its next row of output.
*/
static int deltaparsevtabNext(sqlite3_vtab_cursor *cur){
  deltaparsevtab_cursor *pCur = (deltaparsevtab_cursor*)cur;
  const char *z;
  int i = 0;

  pCur->iCursor = pCur->iNext;
  z = pCur->aDelta + pCur->iCursor;
  pCur->a1 = deltaGetInt(&z, &i);
  switch( z[0] ){
    case '@': {
      z++;
      pCur->a2 = deltaGetInt(&z, &i);
      pCur->eOp = DELTAPARSE_OP_COPY;
      pCur->iNext = (int)(&z[1] - pCur->aDelta);
      break;
    }
    case ':': {
      z++;
      pCur->a2 = (unsigned int)(z - pCur->aDelta);
      pCur->eOp = DELTAPARSE_OP_INSERT;
      pCur->iNext = (int)(&z[pCur->a1] - pCur->aDelta);
      break;
    }
    case ';': {
      pCur->eOp = DELTAPARSE_OP_CHECKSUM;
      pCur->iNext = pCur->nDelta;
      break;
    }
    default: {
      if( pCur->iNext==pCur->nDelta ){
        pCur->eOp = DELTAPARSE_OP_EOF;
      }else{
        pCur->eOp = DELTAPARSE_OP_ERROR;
        pCur->iNext = pCur->nDelta;
      }
      break;
    }
  }
  return SQLITE_OK;
}

/*
** Return values of columns for the row at which the deltaparsevtab_cursor
** is currently pointing.
*/
static int deltaparsevtabColumn(
  sqlite3_vtab_cursor *cur,   /* The cursor */
  sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
  int i                       /* Which column to return */
){
  deltaparsevtab_cursor *pCur = (deltaparsevtab_cursor*)cur;
  switch( i ){
    case DELTAPARSEVTAB_OP: {
      sqlite3_result_text(ctx, azOp[pCur->eOp], -1, SQLITE_STATIC);
      break;
    }
    case DELTAPARSEVTAB_A1: {
      sqlite3_result_int(ctx, pCur->a1);
      break;
    }
    case DELTAPARSEVTAB_A2: {
      if( pCur->eOp==DELTAPARSE_OP_COPY ){
        sqlite3_result_int(ctx, pCur->a2);
      }else if( pCur->eOp==DELTAPARSE_OP_INSERT ){
        sqlite3_result_blob(ctx, pCur->aDelta+pCur->a2, pCur->a1,
                            SQLITE_TRANSIENT);
      }
      break;
    }
    case DELTAPARSEVTAB_DELTA: {
      sqlite3_result_blob(ctx, pCur->aDelta, pCur->nDelta, SQLITE_TRANSIENT);
      break;
    }
  }
  return SQLITE_OK;
}

/*
** Return the rowid for the current row.  In this implementation, the
** rowid is the same as the output value.
*/
static int deltaparsevtabRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
  deltaparsevtab_cursor *pCur = (deltaparsevtab_cursor*)cur;
  *pRowid = pCur->iCursor;
  return SQLITE_OK;
}

/*
** Return TRUE if the cursor has been moved off of the last
** row of output.
*/
static int deltaparsevtabEof(sqlite3_vtab_cursor *cur){
  deltaparsevtab_cursor *pCur = (deltaparsevtab_cursor*)cur;
  return pCur->eOp==DELTAPARSE_OP_EOF;
}

/*
** This method is called to "rewind" the deltaparsevtab_cursor object back
** to the first row of output.  This method is always called at least
** once prior to any call to deltaparsevtabColumn() or deltaparsevtabRowid() or 
** deltaparsevtabEof().
*/
static int deltaparsevtabFilter(
  sqlite3_vtab_cursor *pVtabCursor, 
  int idxNum, const char *idxStr,
  int argc, sqlite3_value **argv
){
  deltaparsevtab_cursor *pCur = (deltaparsevtab_cursor *)pVtabCursor;
  const char *a;
  int i = 0;
  pCur->eOp = DELTAPARSE_OP_ERROR;
  if( idxNum!=1 ){
    return SQLITE_OK;
  }
  pCur->nDelta = sqlite3_value_bytes(argv[0]);
  a = (const char*)sqlite3_value_blob(argv[0]);
  if( pCur->nDelta==0 || a==0 ){
    return SQLITE_OK;
  }
  pCur->aDelta = sqlite3_malloc64( pCur->nDelta+1 );
  if( pCur->aDelta==0 ){
    pCur->nDelta = 0;
    return SQLITE_NOMEM;
  }
  memcpy(pCur->aDelta, a, pCur->nDelta);
  pCur->aDelta[pCur->nDelta] = 0;
  a = pCur->aDelta;
  pCur->eOp = DELTAPARSE_OP_SIZE;
  pCur->a1 = deltaGetInt(&a, &i);
  if( a[0]!='\n' ){
    pCur->eOp = DELTAPARSE_OP_ERROR;
    pCur->a1 = pCur->a2 = 0;
    pCur->iNext = pCur->nDelta;
    return SQLITE_OK;
  }
  a++;
  pCur->iNext = (unsigned int)(a - pCur->aDelta);
  return SQLITE_OK;
}

/*
** SQLite will invoke this method one or more times while planning a query
** that uses the virtual table.  This routine needs to create
** a query plan for each invocation and compute an estimated cost for that
** plan.
*/
static int deltaparsevtabBestIndex(
  sqlite3_vtab *tab,
  sqlite3_index_info *pIdxInfo
){
  int i;
  for(i=0; i<pIdxInfo->nConstraint; i++){
    if( pIdxInfo->aConstraint[i].iColumn != DELTAPARSEVTAB_DELTA ) continue;
    if( pIdxInfo->aConstraint[i].usable==0 ) continue;
    if( pIdxInfo->aConstraint[i].op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
    pIdxInfo->aConstraintUsage[i].argvIndex = 1;
    pIdxInfo->aConstraintUsage[i].omit = 1;
    pIdxInfo->estimatedCost = (double)1;
    pIdxInfo->estimatedRows = 10;
    pIdxInfo->idxNum = 1;
    return SQLITE_OK;
  }
  pIdxInfo->idxNum = 0;
  pIdxInfo->estimatedCost = (double)0x7fffffff;
  pIdxInfo->estimatedRows = 0x7fffffff;
  return SQLITE_CONSTRAINT;
}

/*
** This following structure defines all the methods for the 
** virtual table.
*/
static sqlite3_module deltaparsevtabModule = {
  /* iVersion    */ 0,
  /* xCreate     */ 0,
  /* xConnect    */ deltaparsevtabConnect,
  /* xBestIndex  */ deltaparsevtabBestIndex,
  /* xDisconnect */ deltaparsevtabDisconnect,
  /* xDestroy    */ 0,
  /* xOpen       */ deltaparsevtabOpen,
  /* xClose      */ deltaparsevtabClose,
  /* xFilter     */ deltaparsevtabFilter,
  /* xNext       */ deltaparsevtabNext,
  /* xEof        */ deltaparsevtabEof,
  /* xColumn     */ deltaparsevtabColumn,
  /* xRowid      */ deltaparsevtabRowid,
  /* xUpdate     */ 0,
  /* xBegin      */ 0,
  /* xSync       */ 0,
  /* xCommit     */ 0,
  /* xRollback   */ 0,
  /* xFindMethod */ 0,
  /* xRename     */ 0,
  /* xSavepoint  */ 0,
  /* xRelease    */ 0,
  /* xRollbackTo */ 0,
  /* xShadowName */ 0
};



#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_fossildelta_init(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  static const int enc = SQLITE_UTF8|SQLITE_INNOCUOUS;
  int rc = SQLITE_OK;
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg;  /* Unused parameter */
  rc = sqlite3_create_function(db, "delta_create", 2, enc, 0,
                               deltaCreateFunc, 0, 0);
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "delta_apply", 2, enc, 0,
                                 deltaApplyFunc, 0, 0);
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "delta_output_size", 1, enc, 0,
                                 deltaOutputSizeFunc, 0, 0);
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_module(db, "delta_parse", &deltaparsevtabModule, 0);
  }
  return rc;
}

Changes to ext/misc/fuzzer.c.

333
334
335
336
337
338
339
340

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

340
341
342
343
344
345
346
347







-
+







  if( iRuleset<0 || iRuleset>FUZZER_MX_RULEID ){
    *pzErr = sqlite3_mprintf("%s: ruleset must be between 0 and %d", 
        p->zClassName, FUZZER_MX_RULEID
    );
    rc = SQLITE_ERROR;    
  }else{

    pRule = sqlite3_malloc( sizeof(*pRule) + nFrom + nTo );
    pRule = sqlite3_malloc64( sizeof(*pRule) + nFrom + nTo );
    if( pRule==0 ){
      rc = SQLITE_NOMEM;
    }else{
      memset(pRule, 0, sizeof(*pRule));
      pRule->zFrom = pRule->zTo;
      pRule->zFrom += nTo + 1;
      pRule->nFrom = (fuzzer_len)nFrom;
443
444
445
446
447
448
449
450

451
452
453
454


455
456
457
458
459

460
461
462
463
464
465
466
443
444
445
446
447
448
449

450
451
452


453
454
455
456
457
458

459
460
461
462
463
464
465
466







-
+


-
-
+
+




-
+







**
**     "abc"   becomes   abc
**     'xyz'   becomes   xyz
**     [pqr]   becomes   pqr
**     `mno`   becomes   mno
*/
static char *fuzzerDequote(const char *zIn){
  int nIn;                        /* Size of input string, in bytes */
  sqlite3_int64 nIn;              /* Size of input string, in bytes */
  char *zOut;                     /* Output (dequoted) string */

  nIn = (int)strlen(zIn);
  zOut = sqlite3_malloc(nIn+1);
  nIn = strlen(zIn);
  zOut = sqlite3_malloc64(nIn+1);
  if( zOut ){
    char q = zIn[0];              /* Quote character (if any ) */

    if( q!='[' && q!= '\'' && q!='"' && q!='`' ){
      memcpy(zOut, zIn, nIn+1);
      memcpy(zOut, zIn, (size_t)(nIn+1));
    }else{
      int iOut = 0;               /* Index of next byte to write to output */
      int iIn;                    /* Index of next byte to read from input */

      if( q=='[' ) q = ']';
      for(iIn=1; iIn<nIn; iIn++){
        if( zIn[iIn]==q ) iIn++;
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
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







-
+

-
-
+
+







-
+















+
+








  if( argc!=4 ){
    *pzErr = sqlite3_mprintf(
        "%s: wrong number of CREATE VIRTUAL TABLE arguments", zModule
    );
    rc = SQLITE_ERROR;
  }else{
    int nModule;                  /* Length of zModule, in bytes */
    sqlite3_int64 nModule;        /* Length of zModule, in bytes */

    nModule = (int)strlen(zModule);
    pNew = sqlite3_malloc( sizeof(*pNew) + nModule + 1);
    nModule = strlen(zModule);
    pNew = sqlite3_malloc64( sizeof(*pNew) + nModule + 1);
    if( pNew==0 ){
      rc = SQLITE_NOMEM;
    }else{
      char *zTab;                 /* Dequoted name of fuzzer data table */

      memset(pNew, 0, sizeof(*pNew));
      pNew->zClassName = (char*)&pNew[1];
      memcpy(pNew->zClassName, zModule, nModule+1);
      memcpy(pNew->zClassName, zModule, (size_t)(nModule+1));

      zTab = fuzzerDequote(argv[3]);
      if( zTab==0 ){
        rc = SQLITE_NOMEM;
      }else{
        rc = fuzzerLoadRules(db, pNew, zDb, zTab, pzErr);
        sqlite3_free(zTab);
      }

      if( rc==SQLITE_OK ){
        rc = sqlite3_declare_vtab(db, "CREATE TABLE x(word,distance,ruleset)");
      }
      if( rc!=SQLITE_OK ){
        fuzzerDisconnect((sqlite3_vtab *)pNew);
        pNew = 0;
      }else{
        sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
      }
    }
  }

  *ppVtab = (sqlite3_vtab *)pNew;
  return rc;
}
868
869
870
871
872
873
874
875

876
877
878
879
880
881
882
870
871
872
873
874
875
876

877
878
879
880
881
882
883
884







-
+







  const char *zWord,
  fuzzer_cost rBaseCost
){
  fuzzer_stem *pNew;
  fuzzer_rule *pRule;
  unsigned int h;

  pNew = sqlite3_malloc( sizeof(*pNew) + (int)strlen(zWord) + 1 );
  pNew = sqlite3_malloc64( sizeof(*pNew) + strlen(zWord) + 1 );
  if( pNew==0 ) return 0;
  memset(pNew, 0, sizeof(*pNew));
  pNew->zBasis = (char*)&pNew[1];
  pNew->nBasis = (fuzzer_len)strlen(zWord);
  memcpy(pNew->zBasis, zWord, pNew->nBasis+1);
  pRule = pCur->pVtab->pRule;
  while( fuzzerSkipRule(pRule, pNew, pCur->iRuleset) ){

Changes to ext/misc/ieee754.c.

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
22
23
24
25
26
27
28




29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113


114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142

143
144
145
146
147
148
149
150
151
152




153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181

182
183
184
185
186
187
188
189
190
191
192
193
194


195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286

287


288


289
290
291
292
293







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





+
+
+
+
+
+
















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













+
+
+
-
+
+






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





+
+
+
+
+
+
+
+




-
+












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







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










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



+
-
+
-
-
+
-
-
+
+



**
** In the second form, Y and Z are integers which are the mantissa and
** base-2 exponent of a new floating point number.  The function returns
** a floating-point value equal to Y*pow(2,Z).
**
** Examples:
**
**     ieee754(2.0)       ->     'ieee754(2,0)'
**     ieee754(45.25)     ->     'ieee754(181,-2)'
**     ieee754(2, 0)      ->     2.0
**     ieee754(181, -2)   ->     45.25
**     ieee754(2.0)             ->     'ieee754(2,0)'
**     ieee754(45.25)           ->     'ieee754(181,-2)'
**     ieee754(2, 0)            ->     2.0
**     ieee754(181, -2)         ->     45.25
**
** Two additional functions break apart the one-argument ieee754()
** result into separate integer values:
**
**     ieee754_mantissa(45.25)  ->     181
**     ieee754_exponent(45.25)  ->     -2
**
** These functions convert binary64 numbers into blobs and back again.
**
**     ieee754_from_blob(x'3ff0000000000000')  ->  1.0
**     ieee754_to_blob(1.0)                    ->  x'3ff0000000000000'
**
** In all single-argument functions, if the argument is an 8-byte blob
** then that blob is interpreted as a big-endian binary64 value.
**
**
** EXACT DECIMAL REPRESENTATION OF BINARY64 VALUES
** -----------------------------------------------
**
** This extension in combination with the separate 'decimal' extension
** can be used to compute the exact decimal representation of binary64
** values.  To begin, first compute a table of exponent values:
**
**    CREATE TABLE pow2(x INTEGER PRIMARY KEY, v TEXT);
**    WITH RECURSIVE c(x,v) AS (
**      VALUES(0,'1')
**      UNION ALL
**      SELECT x+1, decimal_mul(v,'2') FROM c WHERE x+1<=971
**    ) INSERT INTO pow2(x,v) SELECT x, v FROM c;
**    WITH RECURSIVE c(x,v) AS (
**      VALUES(-1,'0.5')
**      UNION ALL
**      SELECT x-1, decimal_mul(v,'0.5') FROM c WHERE x-1>=-1075
**    ) INSERT INTO pow2(x,v) SELECT x, v FROM c;
**
** Then, to compute the exact decimal representation of a floating
** point value (the value 47.49 is used in the example) do:
**
**    WITH c(n) AS (VALUES(47.49))
**          ---------------^^^^^---- Replace with whatever you want
**    SELECT decimal_mul(ieee754_mantissa(c.n),pow2.v)
**      FROM pow2, c WHERE pow2.x=ieee754_exponent(c.n);
**
** Here is a query to show various boundry values for the binary64
** number format:
**
**    WITH c(name,bin) AS (VALUES
**       ('minimum positive value',        x'0000000000000001'),
**       ('maximum subnormal value',       x'000fffffffffffff'),
**       ('mininum positive nornal value', x'0010000000000000'),
**       ('maximum value',                 x'7fefffffffffffff'))
**    SELECT c.name, decimal_mul(ieee754_mantissa(c.bin),pow2.v)
**      FROM pow2, c WHERE pow2.x=ieee754_exponent(c.bin);
**
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>

/* Mark a function parameter as unused, to suppress nuisance compiler
** warnings. */
#ifndef UNUSED_PARAMETER
# define UNUSED_PARAMETER(X)  (void)(X)
#endif

/*
** Implementation of the ieee754() function
*/
static void ieee754func(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  if( argc==1 ){
    sqlite3_int64 m, a;
    double r;
    int e;
    int isNeg;
    char zResult[100];
    assert( sizeof(m)==sizeof(r) );
    if( sqlite3_value_type(argv[0])!=SQLITE_FLOAT ) return;
    r = sqlite3_value_double(argv[0]);
    if( sqlite3_value_type(argv[0])==SQLITE_BLOB
     && sqlite3_value_bytes(argv[0])==sizeof(r)
    ){
      const unsigned char *x = sqlite3_value_blob(argv[0]);
      unsigned int i;
      sqlite3_uint64 v = 0;
      for(i=0; i<sizeof(r); i++){
        v = (v<<8) | x[i];
      }
      memcpy(&r, &v, sizeof(r));
    }else{
      r = sqlite3_value_double(argv[0]);
    }
    if( r<0.0 ){
      isNeg = 1;
      r = -r;
    }else{
      isNeg = 0;
    }
    memcpy(&a,&r,sizeof(a));
    if( a==0 ){
      e = 0;
      m = 0;
    }else{
      e = a>>52;
      m = a & ((((sqlite3_int64)1)<<52)-1);
      if( e==0 ){
        m <<= 1;
      }else{
      m |= ((sqlite3_int64)1)<<52;
        m |= ((sqlite3_int64)1)<<52;
      }
      while( e<1075 && m>0 && (m&1)==0 ){
        m >>= 1;
        e++;
      }
      if( isNeg ) m = -m;
    }
    switch( *(int*)sqlite3_user_data(context) ){
      case 0:
    sqlite3_snprintf(sizeof(zResult), zResult, "ieee754(%lld,%d)",
                     m, e-1075);
    sqlite3_result_text(context, zResult, -1, SQLITE_TRANSIENT);
  }else if( argc==2 ){
        sqlite3_snprintf(sizeof(zResult), zResult, "ieee754(%lld,%d)",
                         m, e-1075);
        sqlite3_result_text(context, zResult, -1, SQLITE_TRANSIENT);
        break;
      case 1:
        sqlite3_result_int64(context, m);
        break;
      case 2:
        sqlite3_result_int(context, e-1075);
        break;
    }
  }else{
    sqlite3_int64 m, e, a;
    double r;
    int isNeg = 0;
    m = sqlite3_value_int64(argv[0]);
    e = sqlite3_value_int64(argv[1]);

    /* Limit the range of e.  Ticket 22dea1cfdb9151e4 2021-03-02 */
    if( e>10000 ){
      e = 10000;
    }else if( e<-10000 ){
      e = -10000;
    }

    if( m<0 ){
      isNeg = 1;
      m = -m;
      if( m<0 ) return;
    }else if( m==0 && e>1000 && e<1000 ){
    }else if( m==0 && e>-1000 && e<1000 ){
      sqlite3_result_double(context, 0.0);
      return;
    }
    while( (m>>32)&0xffe00000 ){
      m >>= 1;
      e++;
    }
    while( m!=0 && ((m>>32)&0xfff00000)==0 ){
      m <<= 1;
      e--;
    }
    e += 1075;
    if( e<0 ) e = m = 0;
    if( e>0x7ff ) e = 0x7ff;
    if( e<=0 ){
      /* Subnormal */
      if( 1-e >= 64 ){
        m = 0;
      }else{
        m >>= 1-e;
      }
      e = 0;
    }else if( e>0x7ff ){
      e = 0x7ff;
    }
    a = m & ((((sqlite3_int64)1)<<52)-1);
    a |= e<<52;
    if( isNeg ) a |= ((sqlite3_uint64)1)<<63;
    memcpy(&r, &a, sizeof(r));
    sqlite3_result_double(context, r);
  }
}

/*
** Functions to convert between blobs and floats.
*/
static void ieee754func_from_blob(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  UNUSED_PARAMETER(argc);
  if( sqlite3_value_type(argv[0])==SQLITE_BLOB
   && sqlite3_value_bytes(argv[0])==sizeof(double)
  ){
    double r;
    const unsigned char *x = sqlite3_value_blob(argv[0]);
    unsigned int i;
    sqlite3_uint64 v = 0;
    for(i=0; i<sizeof(r); i++){
      v = (v<<8) | x[i];
    }
    memcpy(&r, &v, sizeof(r));
    sqlite3_result_double(context, r);
  }
}
static void ieee754func_to_blob(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  UNUSED_PARAMETER(argc);
  if( sqlite3_value_type(argv[0])==SQLITE_FLOAT
   || sqlite3_value_type(argv[0])==SQLITE_INTEGER
  ){
    double r = sqlite3_value_double(argv[0]);
    sqlite3_uint64 v;
    unsigned char a[sizeof(r)];
    unsigned int i;
    memcpy(&v, &r, sizeof(r));
    for(i=1; i<=sizeof(r); i++){
      a[sizeof(r)-i] = v&0xff;
      v >>= 8;
    }
    sqlite3_result_blob(context, a, sizeof(r), SQLITE_TRANSIENT);
  }
}


#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_ieee_init(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  static const struct {
    char *zFName;
    int nArg;
    int iAux;
    void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
  } aFunc[] = {
    { "ieee754",           1,   0, ieee754func },
    { "ieee754",           2,   0, ieee754func },
    { "ieee754_mantissa",  1,   1, ieee754func },
    { "ieee754_exponent",  1,   2, ieee754func },
    { "ieee754_to_blob",   1,   0, ieee754func_to_blob },
    { "ieee754_from_blob", 1,   0, ieee754func_from_blob },

  };
  unsigned int i;
  int rc = SQLITE_OK;
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg;  /* Unused parameter */
  for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
  rc = sqlite3_create_function(db, "ieee754", 1, SQLITE_UTF8, 0,
    rc = sqlite3_create_function(db, aFunc[i].zFName, aFunc[i].nArg,
                               ieee754func, 0, 0);
  if( rc==SQLITE_OK ){
                               SQLITE_UTF8|SQLITE_INNOCUOUS,
    rc = sqlite3_create_function(db, "ieee754", 2, SQLITE_UTF8, 0,
                                 ieee754func, 0, 0);
                               (void*)&aFunc[i].iAux,
                               aFunc[i].xFunc, 0, 0);
  }
  return rc;
}

Deleted ext/misc/json1.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
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
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
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
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
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
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
1984
1985
1986
1987
1988
1989
1990
1991
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
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
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
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
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
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
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
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541













































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
** 2015-08-12
**
** 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 SQLite extension implements JSON functions.  The interface is
** modeled after MySQL JSON functions:
**
**     https://dev.mysql.com/doc/refman/5.7/en/json.html
**
** For the time being, all JSON is stored as pure text.  (We might add
** a JSONB type in the future which stores a binary encoding of JSON in
** a BLOB, but there is no support for JSONB in the current implementation.
** This implementation parses JSON text at 250 MB/s, so it is hard to see
** how JSONB might improve on that.)
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_JSON1)
#if !defined(SQLITEINT_H)
#include "sqlite3ext.h"
#endif
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>

/* Mark a function parameter as unused, to suppress nuisance compiler
** warnings. */
#ifndef UNUSED_PARAM
# define UNUSED_PARAM(X)  (void)(X)
#endif

#ifndef LARGEST_INT64
# define LARGEST_INT64  (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32))
# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64)
#endif

/*
** Versions of isspace(), isalnum() and isdigit() to which it is safe
** to pass signed char values.
*/
#ifdef sqlite3Isdigit
   /* Use the SQLite core versions if this routine is part of the
   ** SQLite amalgamation */
#  define safe_isdigit(x)  sqlite3Isdigit(x)
#  define safe_isalnum(x)  sqlite3Isalnum(x)
#  define safe_isxdigit(x) sqlite3Isxdigit(x)
#else
   /* Use the standard library for separate compilation */
#include <ctype.h>  /* amalgamator: keep */
#  define safe_isdigit(x)  isdigit((unsigned char)(x))
#  define safe_isalnum(x)  isalnum((unsigned char)(x))
#  define safe_isxdigit(x) isxdigit((unsigned char)(x))
#endif

/*
** Growing our own isspace() routine this way is twice as fast as
** the library isspace() function, resulting in a 7% overall performance
** increase for the parser.  (Ubuntu14.10 gcc 4.8.4 x64 with -Os).
*/
static const char jsonIsSpace[] = {
  0, 0, 0, 0, 0, 0, 0, 0,     0, 1, 1, 0, 0, 1, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
  1, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
};
#define safe_isspace(x) (jsonIsSpace[(unsigned char)x])

#ifndef SQLITE_AMALGAMATION
  /* Unsigned integer types.  These are already defined in the sqliteInt.h,
  ** but the definitions need to be repeated for separate compilation. */
  typedef sqlite3_uint64 u64;
  typedef unsigned int u32;
  typedef unsigned short int u16;
  typedef unsigned char u8;
#endif

/* Objects */
typedef struct JsonString JsonString;
typedef struct JsonNode JsonNode;
typedef struct JsonParse JsonParse;

/* An instance of this object represents a JSON string
** under construction.  Really, this is a generic string accumulator
** that can be and is used to create strings other than JSON.
*/
struct JsonString {
  sqlite3_context *pCtx;   /* Function context - put error messages here */
  char *zBuf;              /* Append JSON content here */
  u64 nAlloc;              /* Bytes of storage available in zBuf[] */
  u64 nUsed;               /* Bytes of zBuf[] currently used */
  u8 bStatic;              /* True if zBuf is static space */
  u8 bErr;                 /* True if an error has been encountered */
  char zSpace[100];        /* Initial static space */
};

/* JSON type values
*/
#define JSON_NULL     0
#define JSON_TRUE     1
#define JSON_FALSE    2
#define JSON_INT      3
#define JSON_REAL     4
#define JSON_STRING   5
#define JSON_ARRAY    6
#define JSON_OBJECT   7

/* The "subtype" set for JSON values */
#define JSON_SUBTYPE  74    /* Ascii for "J" */

/*
** Names of the various JSON types:
*/
static const char * const jsonType[] = {
  "null", "true", "false", "integer", "real", "text", "array", "object"
};

/* Bit values for the JsonNode.jnFlag field
*/
#define JNODE_RAW     0x01         /* Content is raw, not JSON encoded */
#define JNODE_ESCAPE  0x02         /* Content is text with \ escapes */
#define JNODE_REMOVE  0x04         /* Do not output */
#define JNODE_REPLACE 0x08         /* Replace with JsonNode.u.iReplace */
#define JNODE_PATCH   0x10         /* Patch with JsonNode.u.pPatch */
#define JNODE_APPEND  0x20         /* More ARRAY/OBJECT entries at u.iAppend */
#define JNODE_LABEL   0x40         /* Is a label of an object */


/* A single node of parsed JSON
*/
struct JsonNode {
  u8 eType;              /* One of the JSON_ type values */
  u8 jnFlags;            /* JNODE flags */
  u32 n;                 /* Bytes of content, or number of sub-nodes */
  union {
    const char *zJContent; /* Content for INT, REAL, and STRING */
    u32 iAppend;           /* More terms for ARRAY and OBJECT */
    u32 iKey;              /* Key for ARRAY objects in json_tree() */
    u32 iReplace;          /* Replacement content for JNODE_REPLACE */
    JsonNode *pPatch;      /* Node chain of patch for JNODE_PATCH */
  } u;
};

/* A completely parsed JSON string
*/
struct JsonParse {
  u32 nNode;         /* Number of slots of aNode[] used */
  u32 nAlloc;        /* Number of slots of aNode[] allocated */
  JsonNode *aNode;   /* Array of nodes containing the parse */
  const char *zJson; /* Original JSON string */
  u32 *aUp;          /* Index of parent of each node */
  u8 oom;            /* Set to true if out of memory */
  u8 nErr;           /* Number of errors seen */
  u16 iDepth;        /* Nesting depth */
  int nJson;         /* Length of the zJson string in bytes */
  u32 iHold;         /* Replace cache line with the lowest iHold value */
};

/*
** Maximum nesting depth of JSON for this implementation.
**
** This limit is needed to avoid a stack overflow in the recursive
** descent parser.  A depth of 2000 is far deeper than any sane JSON
** should go.
*/
#define JSON_MAX_DEPTH  2000

/**************************************************************************
** Utility routines for dealing with JsonString objects
**************************************************************************/

/* Set the JsonString object to an empty string
*/
static void jsonZero(JsonString *p){
  p->zBuf = p->zSpace;
  p->nAlloc = sizeof(p->zSpace);
  p->nUsed = 0;
  p->bStatic = 1;
}

/* Initialize the JsonString object
*/
static void jsonInit(JsonString *p, sqlite3_context *pCtx){
  p->pCtx = pCtx;
  p->bErr = 0;
  jsonZero(p);
}


/* Free all allocated memory and reset the JsonString object back to its
** initial state.
*/
static void jsonReset(JsonString *p){
  if( !p->bStatic ) sqlite3_free(p->zBuf);
  jsonZero(p);
}


/* Report an out-of-memory (OOM) condition 
*/
static void jsonOom(JsonString *p){
  p->bErr = 1;
  sqlite3_result_error_nomem(p->pCtx);
  jsonReset(p);
}

/* Enlarge pJson->zBuf so that it can hold at least N more bytes.
** Return zero on success.  Return non-zero on an OOM error
*/
static int jsonGrow(JsonString *p, u32 N){
  u64 nTotal = N<p->nAlloc ? p->nAlloc*2 : p->nAlloc+N+10;
  char *zNew;
  if( p->bStatic ){
    if( p->bErr ) return 1;
    zNew = sqlite3_malloc64(nTotal);
    if( zNew==0 ){
      jsonOom(p);
      return SQLITE_NOMEM;
    }
    memcpy(zNew, p->zBuf, (size_t)p->nUsed);
    p->zBuf = zNew;
    p->bStatic = 0;
  }else{
    zNew = sqlite3_realloc64(p->zBuf, nTotal);
    if( zNew==0 ){
      jsonOom(p);
      return SQLITE_NOMEM;
    }
    p->zBuf = zNew;
  }
  p->nAlloc = nTotal;
  return SQLITE_OK;
}

/* Append N bytes from zIn onto the end of the JsonString string.
*/
static void jsonAppendRaw(JsonString *p, const char *zIn, u32 N){
  if( (N+p->nUsed >= p->nAlloc) && jsonGrow(p,N)!=0 ) return;
  memcpy(p->zBuf+p->nUsed, zIn, N);
  p->nUsed += N;
}

/* Append formatted text (not to exceed N bytes) to the JsonString.
*/
static void jsonPrintf(int N, JsonString *p, const char *zFormat, ...){
  va_list ap;
  if( (p->nUsed + N >= p->nAlloc) && jsonGrow(p, N) ) return;
  va_start(ap, zFormat);
  sqlite3_vsnprintf(N, p->zBuf+p->nUsed, zFormat, ap);
  va_end(ap);
  p->nUsed += (int)strlen(p->zBuf+p->nUsed);
}

/* Append a single character
*/
static void jsonAppendChar(JsonString *p, char c){
  if( p->nUsed>=p->nAlloc && jsonGrow(p,1)!=0 ) return;
  p->zBuf[p->nUsed++] = c;
}

/* Append a comma separator to the output buffer, if the previous
** character is not '[' or '{'.
*/
static void jsonAppendSeparator(JsonString *p){
  char c;
  if( p->nUsed==0 ) return;
  c = p->zBuf[p->nUsed-1];
  if( c!='[' && c!='{' ) jsonAppendChar(p, ',');
}

/* 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;
  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++] = '\\';
    }else if( c<=0x1f ){
      static const char aSpecial[] = {
         0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0,   0,   0, 0, 0
      };
      assert( sizeof(aSpecial)==32 );
      assert( aSpecial['\b']=='b' );
      assert( aSpecial['\f']=='f' );
      assert( aSpecial['\n']=='n' );
      assert( aSpecial['\r']=='r' );
      assert( aSpecial['\t']=='t' );
      if( aSpecial[c] ){
        c = aSpecial[c];
        goto json_simple_escape;
      }
      if( (p->nUsed+N+7+i > p->nAlloc) && jsonGrow(p,N+7-i)!=0 ) return;
      p->zBuf[p->nUsed++] = '\\';
      p->zBuf[p->nUsed++] = 'u';
      p->zBuf[p->nUsed++] = '0';
      p->zBuf[p->nUsed++] = '0';
      p->zBuf[p->nUsed++] = '0' + (c>>4);
      c = "0123456789abcdef"[c&0xf];
    }
    p->zBuf[p->nUsed++] = c;
  }
  p->zBuf[p->nUsed++] = '"';
  assert( p->nUsed<p->nAlloc );
}

/*
** Append a function parameter value to the JSON string under 
** construction.
*/
static void jsonAppendValue(
  JsonString *p,                 /* Append to this JSON string */
  sqlite3_value *pValue          /* Value to append */
){
  switch( sqlite3_value_type(pValue) ){
    case SQLITE_NULL: {
      jsonAppendRaw(p, "null", 4);
      break;
    }
    case SQLITE_INTEGER:
    case SQLITE_FLOAT: {
      const char *z = (const char*)sqlite3_value_text(pValue);
      u32 n = (u32)sqlite3_value_bytes(pValue);
      jsonAppendRaw(p, z, n);
      break;
    }
    case SQLITE_TEXT: {
      const char *z = (const char*)sqlite3_value_text(pValue);
      u32 n = (u32)sqlite3_value_bytes(pValue);
      if( sqlite3_value_subtype(pValue)==JSON_SUBTYPE ){
        jsonAppendRaw(p, z, n);
      }else{
        jsonAppendString(p, z, n);
      }
      break;
    }
    default: {
      if( p->bErr==0 ){
        sqlite3_result_error(p->pCtx, "JSON cannot hold BLOB values", -1);
        p->bErr = 2;
        jsonReset(p);
      }
      break;
    }
  }
}


/* Make the JSON in p the result of the SQL function.
*/
static void jsonResult(JsonString *p){
  if( p->bErr==0 ){
    sqlite3_result_text64(p->pCtx, p->zBuf, p->nUsed, 
                          p->bStatic ? SQLITE_TRANSIENT : sqlite3_free,
                          SQLITE_UTF8);
    jsonZero(p);
  }
  assert( p->bStatic );
}

/**************************************************************************
** Utility routines for dealing with JsonNode and JsonParse objects
**************************************************************************/

/*
** Return the number of consecutive JsonNode slots need to represent
** the parsed JSON at pNode.  The minimum answer is 1.  For ARRAY and
** OBJECT types, the number might be larger.
**
** Appended elements are not counted.  The value returned is the number
** by which the JsonNode counter should increment in order to go to the
** next peer value.
*/
static u32 jsonNodeSize(JsonNode *pNode){
  return pNode->eType>=JSON_ARRAY ? pNode->n+1 : 1;
}

/*
** Reclaim all memory allocated by a JsonParse object.  But do not
** delete the JsonParse object itself.
*/
static void jsonParseReset(JsonParse *pParse){
  sqlite3_free(pParse->aNode);
  pParse->aNode = 0;
  pParse->nNode = 0;
  pParse->nAlloc = 0;
  sqlite3_free(pParse->aUp);
  pParse->aUp = 0;
}

/*
** Free a JsonParse object that was obtained from sqlite3_malloc().
*/
static void jsonParseFree(JsonParse *pParse){
  jsonParseReset(pParse);
  sqlite3_free(pParse);
}

/*
** Convert the JsonNode pNode into a pure JSON string and
** append to pOut.  Subsubstructure is also included.  Return
** the number of JsonNode objects that are encoded.
*/
static void jsonRenderNode(
  JsonNode *pNode,               /* The node to render */
  JsonString *pOut,              /* Write JSON here */
  sqlite3_value **aReplace       /* Replacement values */
){
  if( pNode->jnFlags & (JNODE_REPLACE|JNODE_PATCH) ){
    if( pNode->jnFlags & JNODE_REPLACE ){
      jsonAppendValue(pOut, aReplace[pNode->u.iReplace]);
      return;
    }
    pNode = pNode->u.pPatch;
  }
  switch( pNode->eType ){
    default: {
      assert( pNode->eType==JSON_NULL );
      jsonAppendRaw(pOut, "null", 4);
      break;
    }
    case JSON_TRUE: {
      jsonAppendRaw(pOut, "true", 4);
      break;
    }
    case JSON_FALSE: {
      jsonAppendRaw(pOut, "false", 5);
      break;
    }
    case JSON_STRING: {
      if( pNode->jnFlags & JNODE_RAW ){
        jsonAppendString(pOut, pNode->u.zJContent, pNode->n);
        break;
      }
      /* Fall through into the next case */
    }
    case JSON_REAL:
    case JSON_INT: {
      jsonAppendRaw(pOut, pNode->u.zJContent, pNode->n);
      break;
    }
    case JSON_ARRAY: {
      u32 j = 1;
      jsonAppendChar(pOut, '[');
      for(;;){
        while( j<=pNode->n ){
          if( (pNode[j].jnFlags & JNODE_REMOVE)==0 ){
            jsonAppendSeparator(pOut);
            jsonRenderNode(&pNode[j], pOut, aReplace);
          }
          j += jsonNodeSize(&pNode[j]);
        }
        if( (pNode->jnFlags & JNODE_APPEND)==0 ) break;
        pNode = &pNode[pNode->u.iAppend];
        j = 1;
      }
      jsonAppendChar(pOut, ']');
      break;
    }
    case JSON_OBJECT: {
      u32 j = 1;
      jsonAppendChar(pOut, '{');
      for(;;){
        while( j<=pNode->n ){
          if( (pNode[j+1].jnFlags & JNODE_REMOVE)==0 ){
            jsonAppendSeparator(pOut);
            jsonRenderNode(&pNode[j], pOut, aReplace);
            jsonAppendChar(pOut, ':');
            jsonRenderNode(&pNode[j+1], pOut, aReplace);
          }
          j += 1 + jsonNodeSize(&pNode[j+1]);
        }
        if( (pNode->jnFlags & JNODE_APPEND)==0 ) break;
        pNode = &pNode[pNode->u.iAppend];
        j = 1;
      }
      jsonAppendChar(pOut, '}');
      break;
    }
  }
}

/*
** Return a JsonNode and all its descendents as a JSON string.
*/
static void jsonReturnJson(
  JsonNode *pNode,            /* Node to return */
  sqlite3_context *pCtx,      /* Return value for this function */
  sqlite3_value **aReplace    /* Array of replacement values */
){
  JsonString s;
  jsonInit(&s, pCtx);
  jsonRenderNode(pNode, &s, aReplace);
  jsonResult(&s);
  sqlite3_result_subtype(pCtx, JSON_SUBTYPE);
}

/*
** Make the JsonNode the return value of the function.
*/
static void jsonReturn(
  JsonNode *pNode,            /* Node to return */
  sqlite3_context *pCtx,      /* Return value for this function */
  sqlite3_value **aReplace    /* Array of replacement values */
){
  switch( pNode->eType ){
    default: {
      assert( pNode->eType==JSON_NULL );
      sqlite3_result_null(pCtx);
      break;
    }
    case JSON_TRUE: {
      sqlite3_result_int(pCtx, 1);
      break;
    }
    case JSON_FALSE: {
      sqlite3_result_int(pCtx, 0);
      break;
    }
    case JSON_INT: {
      sqlite3_int64 i = 0;
      const char *z = pNode->u.zJContent;
      if( z[0]=='-' ){ z++; }
      while( z[0]>='0' && z[0]<='9' ){
        unsigned v = *(z++) - '0';
        if( i>=LARGEST_INT64/10 ){
          if( i>LARGEST_INT64/10 ) goto int_as_real;
          if( z[0]>='0' && z[0]<='9' ) goto int_as_real;
          if( v==9 ) goto int_as_real;
          if( v==8 ){
            if( pNode->u.zJContent[0]=='-' ){
              sqlite3_result_int64(pCtx, SMALLEST_INT64);
              goto int_done;
            }else{
              goto int_as_real;
            }
          }
        }
        i = i*10 + v;
      }
      if( pNode->u.zJContent[0]=='-' ){ i = -i; }
      sqlite3_result_int64(pCtx, i);
      int_done:
      break;
      int_as_real: /* fall through to real */;
    }
    case JSON_REAL: {
      double r;
#ifdef SQLITE_AMALGAMATION
      const char *z = pNode->u.zJContent;
      sqlite3AtoF(z, &r, sqlite3Strlen30(z), SQLITE_UTF8);
#else
      r = strtod(pNode->u.zJContent, 0);
#endif
      sqlite3_result_double(pCtx, r);
      break;
    }
    case JSON_STRING: {
#if 0 /* Never happens because JNODE_RAW is only set by json_set(),
      ** json_insert() and json_replace() and those routines do not
      ** call jsonReturn() */
      if( pNode->jnFlags & JNODE_RAW ){
        sqlite3_result_text(pCtx, pNode->u.zJContent, pNode->n,
                            SQLITE_TRANSIENT);
      }else 
#endif
      assert( (pNode->jnFlags & JNODE_RAW)==0 );
      if( (pNode->jnFlags & JNODE_ESCAPE)==0 ){
        /* JSON formatted without any backslash-escapes */
        sqlite3_result_text(pCtx, pNode->u.zJContent+1, pNode->n-2,
                            SQLITE_TRANSIENT);
      }else{
        /* Translate JSON formatted string into raw text */
        u32 i;
        u32 n = pNode->n;
        const char *z = pNode->u.zJContent;
        char *zOut;
        u32 j;
        zOut = sqlite3_malloc( n+1 );
        if( zOut==0 ){
          sqlite3_result_error_nomem(pCtx);
          break;
        }
        for(i=1, j=0; i<n-1; i++){
          char c = z[i];
          if( c!='\\' ){
            zOut[j++] = c;
          }else{
            c = z[++i];
            if( c=='u' ){
              u32 v = 0, k;
              for(k=0; k<4; i++, k++){
                assert( i<n-2 );
                c = z[i+1];
                assert( safe_isxdigit(c) );
                if( c<='9' ) v = v*16 + c - '0';
                else if( c<='F' ) v = v*16 + c - 'A' + 10;
                else v = v*16 + c - 'a' + 10;
              }
              if( v==0 ) break;
              if( v<=0x7f ){
                zOut[j++] = (char)v;
              }else if( v<=0x7ff ){
                zOut[j++] = (char)(0xc0 | (v>>6));
                zOut[j++] = 0x80 | (v&0x3f);
              }else{
                zOut[j++] = (char)(0xe0 | (v>>12));
                zOut[j++] = 0x80 | ((v>>6)&0x3f);
                zOut[j++] = 0x80 | (v&0x3f);
              }
            }else{
              if( c=='b' ){
                c = '\b';
              }else if( c=='f' ){
                c = '\f';
              }else if( c=='n' ){
                c = '\n';
              }else if( c=='r' ){
                c = '\r';
              }else if( c=='t' ){
                c = '\t';
              }
              zOut[j++] = c;
            }
          }
        }
        zOut[j] = 0;
        sqlite3_result_text(pCtx, zOut, j, sqlite3_free);
      }
      break;
    }
    case JSON_ARRAY:
    case JSON_OBJECT: {
      jsonReturnJson(pNode, pCtx, aReplace);
      break;
    }
  }
}

/* Forward reference */
static int jsonParseAddNode(JsonParse*,u32,u32,const char*);

/*
** A macro to hint to the compiler that a function should not be
** inlined.
*/
#if defined(__GNUC__)
#  define JSON_NOINLINE  __attribute__((noinline))
#elif defined(_MSC_VER) && _MSC_VER>=1310
#  define JSON_NOINLINE  __declspec(noinline)
#else
#  define JSON_NOINLINE
#endif


static JSON_NOINLINE int jsonParseAddNodeExpand(
  JsonParse *pParse,        /* Append the node to this object */
  u32 eType,                /* Node type */
  u32 n,                    /* Content size or sub-node count */
  const char *zContent      /* Content */
){
  u32 nNew;
  JsonNode *pNew;
  assert( pParse->nNode>=pParse->nAlloc );
  if( pParse->oom ) return -1;
  nNew = pParse->nAlloc*2 + 10;
  pNew = sqlite3_realloc(pParse->aNode, sizeof(JsonNode)*nNew);
  if( pNew==0 ){
    pParse->oom = 1;
    return -1;
  }
  pParse->nAlloc = nNew;
  pParse->aNode = pNew;
  assert( pParse->nNode<pParse->nAlloc );
  return jsonParseAddNode(pParse, eType, n, zContent);
}

/*
** Create a new JsonNode instance based on the arguments and append that
** instance to the JsonParse.  Return the index in pParse->aNode[] of the
** new node, or -1 if a memory allocation fails.
*/
static int jsonParseAddNode(
  JsonParse *pParse,        /* Append the node to this object */
  u32 eType,                /* Node type */
  u32 n,                    /* Content size or sub-node count */
  const char *zContent      /* Content */
){
  JsonNode *p;
  if( pParse->nNode>=pParse->nAlloc ){
    return jsonParseAddNodeExpand(pParse, eType, n, zContent);
  }
  p = &pParse->aNode[pParse->nNode];
  p->eType = (u8)eType;
  p->jnFlags = 0;
  p->n = n;
  p->u.zJContent = zContent;
  return pParse->nNode++;
}

/*
** Return true if z[] begins with 4 (or more) hexadecimal digits
*/
static int jsonIs4Hex(const char *z){
  int i;
  for(i=0; i<4; i++) if( !safe_isxdigit(z[i]) ) return 0;
  return 1;
}

/*
** Parse a single JSON value which begins at pParse->zJson[i].  Return the
** index of the first character past the end of the value parsed.
**
** Return negative for a syntax error.  Special cases:  return -2 if the
** first non-whitespace character is '}' and return -3 if the first
** non-whitespace character is ']'.
*/
static int jsonParseValue(JsonParse *pParse, u32 i){
  char c;
  u32 j;
  int iThis;
  int x;
  JsonNode *pNode;
  const char *z = pParse->zJson;
  while( safe_isspace(z[i]) ){ i++; }
  if( (c = z[i])=='{' ){
    /* Parse object */
    iThis = jsonParseAddNode(pParse, JSON_OBJECT, 0, 0);
    if( iThis<0 ) return -1;
    for(j=i+1;;j++){
      while( safe_isspace(z[j]) ){ j++; }
      if( ++pParse->iDepth > JSON_MAX_DEPTH ) return -1;
      x = jsonParseValue(pParse, j);
      if( x<0 ){
        pParse->iDepth--;
        if( x==(-2) && pParse->nNode==(u32)iThis+1 ) return j+1;
        return -1;
      }
      if( pParse->oom ) return -1;
      pNode = &pParse->aNode[pParse->nNode-1];
      if( pNode->eType!=JSON_STRING ) return -1;
      pNode->jnFlags |= JNODE_LABEL;
      j = x;
      while( safe_isspace(z[j]) ){ j++; }
      if( z[j]!=':' ) return -1;
      j++;
      x = jsonParseValue(pParse, j);
      pParse->iDepth--;
      if( x<0 ) return -1;
      j = x;
      while( safe_isspace(z[j]) ){ j++; }
      c = z[j];
      if( c==',' ) continue;
      if( c!='}' ) return -1;
      break;
    }
    pParse->aNode[iThis].n = pParse->nNode - (u32)iThis - 1;
    return j+1;
  }else if( c=='[' ){
    /* Parse array */
    iThis = jsonParseAddNode(pParse, JSON_ARRAY, 0, 0);
    if( iThis<0 ) return -1;
    for(j=i+1;;j++){
      while( safe_isspace(z[j]) ){ j++; }
      if( ++pParse->iDepth > JSON_MAX_DEPTH ) return -1;
      x = jsonParseValue(pParse, j);
      pParse->iDepth--;
      if( x<0 ){
        if( x==(-3) && pParse->nNode==(u32)iThis+1 ) return j+1;
        return -1;
      }
      j = x;
      while( safe_isspace(z[j]) ){ j++; }
      c = z[j];
      if( c==',' ) continue;
      if( c!=']' ) return -1;
      break;
    }
    pParse->aNode[iThis].n = pParse->nNode - (u32)iThis - 1;
    return j+1;
  }else if( c=='"' ){
    /* Parse string */
    u8 jnFlags = 0;
    j = i+1;
    for(;;){
      c = z[j];
      if( (c & ~0x1f)==0 ){
        /* Control characters are not allowed in strings */
        return -1;
      }
      if( c=='\\' ){
        c = z[++j];
        if( c=='"' || c=='\\' || c=='/' || c=='b' || c=='f'
           || c=='n' || c=='r' || c=='t'
           || (c=='u' && jsonIs4Hex(z+j+1)) ){
          jnFlags = JNODE_ESCAPE;
        }else{
          return -1;
        }
      }else if( c=='"' ){
        break;
      }
      j++;
    }
    jsonParseAddNode(pParse, JSON_STRING, j+1-i, &z[i]);
    if( !pParse->oom ) pParse->aNode[pParse->nNode-1].jnFlags = jnFlags;
    return j+1;
  }else if( c=='n'
         && strncmp(z+i,"null",4)==0
         && !safe_isalnum(z[i+4]) ){
    jsonParseAddNode(pParse, JSON_NULL, 0, 0);
    return i+4;
  }else if( c=='t'
         && strncmp(z+i,"true",4)==0
         && !safe_isalnum(z[i+4]) ){
    jsonParseAddNode(pParse, JSON_TRUE, 0, 0);
    return i+4;
  }else if( c=='f'
         && strncmp(z+i,"false",5)==0
         && !safe_isalnum(z[i+5]) ){
    jsonParseAddNode(pParse, JSON_FALSE, 0, 0);
    return i+5;
  }else if( c=='-' || (c>='0' && c<='9') ){
    /* Parse number */
    u8 seenDP = 0;
    u8 seenE = 0;
    assert( '-' < '0' );
    if( c<='0' ){
      j = c=='-' ? i+1 : i;
      if( z[j]=='0' && z[j+1]>='0' && z[j+1]<='9' ) return -1;
    }
    j = i+1;
    for(;; j++){
      c = z[j];
      if( c>='0' && c<='9' ) continue;
      if( c=='.' ){
        if( z[j-1]=='-' ) return -1;
        if( seenDP ) return -1;
        seenDP = 1;
        continue;
      }
      if( c=='e' || c=='E' ){
        if( z[j-1]<'0' ) return -1;
        if( seenE ) return -1;
        seenDP = seenE = 1;
        c = z[j+1];
        if( c=='+' || c=='-' ){
          j++;
          c = z[j+1];
        }
        if( c<'0' || c>'9' ) return -1;
        continue;
      }
      break;
    }
    if( z[j-1]<'0' ) return -1;
    jsonParseAddNode(pParse, seenDP ? JSON_REAL : JSON_INT,
                        j - i, &z[i]);
    return j;
  }else if( c=='}' ){
    return -2;  /* End of {...} */
  }else if( c==']' ){
    return -3;  /* End of [...] */
  }else if( c==0 ){
    return 0;   /* End of file */
  }else{
    return -1;  /* Syntax error */
  }
}

/*
** Parse a complete JSON string.  Return 0 on success or non-zero if there
** are any errors.  If an error occurs, free all memory associated with
** pParse.
**
** pParse is uninitialized when this routine is called.
*/
static int jsonParse(
  JsonParse *pParse,           /* Initialize and fill this JsonParse object */
  sqlite3_context *pCtx,       /* Report errors here */
  const char *zJson            /* Input JSON text to be parsed */
){
  int i;
  memset(pParse, 0, sizeof(*pParse));
  if( zJson==0 ) return 1;
  pParse->zJson = zJson;
  i = jsonParseValue(pParse, 0);
  if( pParse->oom ) i = -1;
  if( i>0 ){
    assert( pParse->iDepth==0 );
    while( safe_isspace(zJson[i]) ) i++;
    if( zJson[i] ) i = -1;
  }
  if( i<=0 ){
    if( pCtx!=0 ){
      if( pParse->oom ){
        sqlite3_result_error_nomem(pCtx);
      }else{
        sqlite3_result_error(pCtx, "malformed JSON", -1);
      }
    }
    jsonParseReset(pParse);
    return 1;
  }
  return 0;
}

/* Mark node i of pParse as being a child of iParent.  Call recursively
** to fill in all the descendants of node i.
*/
static void jsonParseFillInParentage(JsonParse *pParse, u32 i, u32 iParent){
  JsonNode *pNode = &pParse->aNode[i];
  u32 j;
  pParse->aUp[i] = iParent;
  switch( pNode->eType ){
    case JSON_ARRAY: {
      for(j=1; j<=pNode->n; j += jsonNodeSize(pNode+j)){
        jsonParseFillInParentage(pParse, i+j, i);
      }
      break;
    }
    case JSON_OBJECT: {
      for(j=1; j<=pNode->n; j += jsonNodeSize(pNode+j+1)+1){
        pParse->aUp[i+j] = i;
        jsonParseFillInParentage(pParse, i+j+1, i);
      }
      break;
    }
    default: {
      break;
    }
  }
}

/*
** Compute the parentage of all nodes in a completed parse.
*/
static int jsonParseFindParents(JsonParse *pParse){
  u32 *aUp;
  assert( pParse->aUp==0 );
  aUp = pParse->aUp = sqlite3_malloc( sizeof(u32)*pParse->nNode );
  if( aUp==0 ){
    pParse->oom = 1;
    return SQLITE_NOMEM;
  }
  jsonParseFillInParentage(pParse, 0, 0);
  return SQLITE_OK;
}

/*
** Magic number used for the JSON parse cache in sqlite3_get_auxdata()
*/
#define JSON_CACHE_ID  (-429938)  /* First cache entry */
#define JSON_CACHE_SZ  4          /* Max number of cache entries */

/*
** Obtain a complete parse of the JSON found in the first argument
** of the argv array.  Use the sqlite3_get_auxdata() cache for this
** parse if it is available.  If the cache is not available or if it
** is no longer valid, parse the JSON again and return the new parse,
** and also register the new parse so that it will be available for
** future sqlite3_get_auxdata() calls.
*/
static JsonParse *jsonParseCached(
  sqlite3_context *pCtx,
  sqlite3_value **argv,
  sqlite3_context *pErrCtx
){
  const char *zJson = (const char*)sqlite3_value_text(argv[0]);
  int nJson = sqlite3_value_bytes(argv[0]);
  JsonParse *p;
  JsonParse *pMatch = 0;
  int iKey;
  int iMinKey = 0;
  u32 iMinHold = 0xffffffff;
  u32 iMaxHold = 0;
  if( zJson==0 ) return 0;
  for(iKey=0; iKey<JSON_CACHE_SZ; iKey++){
    p = (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID+iKey);
    if( p==0 ){
      iMinKey = iKey;
      break;
    }
    if( pMatch==0
     && p->nJson==nJson
     && memcmp(p->zJson,zJson,nJson)==0
    ){
      p->nErr = 0;
      pMatch = p;
    }else if( p->iHold<iMinHold ){
      iMinHold = p->iHold;
      iMinKey = iKey;
    }
    if( p->iHold>iMaxHold ){
      iMaxHold = p->iHold;
    }
  }
  if( pMatch ){
    pMatch->nErr = 0;
    pMatch->iHold = iMaxHold+1;
    return pMatch;
  }
  p = sqlite3_malloc( sizeof(*p) + nJson + 1 );
  if( p==0 ){
    sqlite3_result_error_nomem(pCtx);
    return 0;
  }
  memset(p, 0, sizeof(*p));
  p->zJson = (char*)&p[1];
  memcpy((char*)p->zJson, zJson, nJson+1);
  if( jsonParse(p, pErrCtx, p->zJson) ){
    sqlite3_free(p);
    return 0;
  }
  p->nJson = nJson;
  p->iHold = iMaxHold+1;
  sqlite3_set_auxdata(pCtx, JSON_CACHE_ID+iMinKey, p,
                      (void(*)(void*))jsonParseFree);
  return (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID+iMinKey);
}

/*
** Compare the OBJECT label at pNode against zKey,nKey.  Return true on
** a match.
*/
static int jsonLabelCompare(JsonNode *pNode, const char *zKey, u32 nKey){
  if( pNode->jnFlags & JNODE_RAW ){
    if( pNode->n!=nKey ) return 0;
    return strncmp(pNode->u.zJContent, zKey, nKey)==0;
  }else{
    if( pNode->n!=nKey+2 ) return 0;
    return strncmp(pNode->u.zJContent+1, zKey, nKey)==0;
  }
}

/* forward declaration */
static JsonNode *jsonLookupAppend(JsonParse*,const char*,int*,const char**);

/*
** Search along zPath to find the node specified.  Return a pointer
** to that node, or NULL if zPath is malformed or if there is no such
** node.
**
** If pApnd!=0, then try to append new nodes to complete zPath if it is
** possible to do so and if no existing node corresponds to zPath.  If
** new nodes are appended *pApnd is set to 1.
*/
static JsonNode *jsonLookupStep(
  JsonParse *pParse,      /* The JSON to search */
  u32 iRoot,              /* Begin the search at this node */
  const char *zPath,      /* The path to search */
  int *pApnd,             /* Append nodes to complete path if not NULL */
  const char **pzErr      /* Make *pzErr point to any syntax error in zPath */
){
  u32 i, j, nKey;
  const char *zKey;
  JsonNode *pRoot = &pParse->aNode[iRoot];
  if( zPath[0]==0 ) return pRoot;
  if( zPath[0]=='.' ){
    if( pRoot->eType!=JSON_OBJECT ) return 0;
    zPath++;
    if( zPath[0]=='"' ){
      zKey = zPath + 1;
      for(i=1; zPath[i] && zPath[i]!='"'; i++){}
      nKey = i-1;
      if( zPath[i] ){
        i++;
      }else{
        *pzErr = zPath;
        return 0;
      }
    }else{
      zKey = zPath;
      for(i=0; zPath[i] && zPath[i]!='.' && zPath[i]!='['; i++){}
      nKey = i;
    }
    if( nKey==0 ){
      *pzErr = zPath;
      return 0;
    }
    j = 1;
    for(;;){
      while( j<=pRoot->n ){
        if( jsonLabelCompare(pRoot+j, zKey, nKey) ){
          return jsonLookupStep(pParse, iRoot+j+1, &zPath[i], pApnd, pzErr);
        }
        j++;
        j += jsonNodeSize(&pRoot[j]);
      }
      if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break;
      iRoot += pRoot->u.iAppend;
      pRoot = &pParse->aNode[iRoot];
      j = 1;
    }
    if( pApnd ){
      u32 iStart, iLabel;
      JsonNode *pNode;
      iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0);
      iLabel = jsonParseAddNode(pParse, JSON_STRING, i, zPath);
      zPath += i;
      pNode = jsonLookupAppend(pParse, zPath, pApnd, pzErr);
      if( pParse->oom ) return 0;
      if( pNode ){
        pRoot = &pParse->aNode[iRoot];
        pRoot->u.iAppend = iStart - iRoot;
        pRoot->jnFlags |= JNODE_APPEND;
        pParse->aNode[iLabel].jnFlags |= JNODE_RAW;
      }
      return pNode;
    }
  }else if( zPath[0]=='[' && safe_isdigit(zPath[1]) ){
    if( pRoot->eType!=JSON_ARRAY ) return 0;
    i = 0;
    j = 1;
    while( safe_isdigit(zPath[j]) ){
      i = i*10 + zPath[j] - '0';
      j++;
    }
    if( zPath[j]!=']' ){
      *pzErr = zPath;
      return 0;
    }
    zPath += j + 1;
    j = 1;
    for(;;){
      while( j<=pRoot->n && (i>0 || (pRoot[j].jnFlags & JNODE_REMOVE)!=0) ){
        if( (pRoot[j].jnFlags & JNODE_REMOVE)==0 ) i--;
        j += jsonNodeSize(&pRoot[j]);
      }
      if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break;
      iRoot += pRoot->u.iAppend;
      pRoot = &pParse->aNode[iRoot];
      j = 1;
    }
    if( j<=pRoot->n ){
      return jsonLookupStep(pParse, iRoot+j, zPath, pApnd, pzErr);
    }
    if( i==0 && pApnd ){
      u32 iStart;
      JsonNode *pNode;
      iStart = jsonParseAddNode(pParse, JSON_ARRAY, 1, 0);
      pNode = jsonLookupAppend(pParse, zPath, pApnd, pzErr);
      if( pParse->oom ) return 0;
      if( pNode ){
        pRoot = &pParse->aNode[iRoot];
        pRoot->u.iAppend = iStart - iRoot;
        pRoot->jnFlags |= JNODE_APPEND;
      }
      return pNode;
    }
  }else{
    *pzErr = zPath;
  }
  return 0;
}

/*
** Append content to pParse that will complete zPath.  Return a pointer
** to the inserted node, or return NULL if the append fails.
*/
static JsonNode *jsonLookupAppend(
  JsonParse *pParse,     /* Append content to the JSON parse */
  const char *zPath,     /* Description of content to append */
  int *pApnd,            /* Set this flag to 1 */
  const char **pzErr     /* Make this point to any syntax error */
){
  *pApnd = 1;
  if( zPath[0]==0 ){
    jsonParseAddNode(pParse, JSON_NULL, 0, 0);
    return pParse->oom ? 0 : &pParse->aNode[pParse->nNode-1];
  }
  if( zPath[0]=='.' ){
    jsonParseAddNode(pParse, JSON_OBJECT, 0, 0);
  }else if( strncmp(zPath,"[0]",3)==0 ){
    jsonParseAddNode(pParse, JSON_ARRAY, 0, 0);
  }else{
    return 0;
  }
  if( pParse->oom ) return 0;
  return jsonLookupStep(pParse, pParse->nNode-1, zPath, pApnd, pzErr);
}

/*
** Return the text of a syntax error message on a JSON path.  Space is
** obtained from sqlite3_malloc().
*/
static char *jsonPathSyntaxError(const char *zErr){
  return sqlite3_mprintf("JSON path error near '%q'", zErr);
}

/*
** Do a node lookup using zPath.  Return a pointer to the node on success.
** Return NULL if not found or if there is an error.
**
** On an error, write an error message into pCtx and increment the
** pParse->nErr counter.
**
** If pApnd!=NULL then try to append missing nodes and set *pApnd = 1 if
** nodes are appended.
*/
static JsonNode *jsonLookup(
  JsonParse *pParse,      /* The JSON to search */
  const char *zPath,      /* The path to search */
  int *pApnd,             /* Append nodes to complete path if not NULL */
  sqlite3_context *pCtx   /* Report errors here, if not NULL */
){
  const char *zErr = 0;
  JsonNode *pNode = 0;
  char *zMsg;

  if( zPath==0 ) return 0;
  if( zPath[0]!='$' ){
    zErr = zPath;
    goto lookup_err;
  }
  zPath++;
  pNode = jsonLookupStep(pParse, 0, zPath, pApnd, &zErr);
  if( zErr==0 ) return pNode;

lookup_err:
  pParse->nErr++;
  assert( zErr!=0 && pCtx!=0 );
  zMsg = jsonPathSyntaxError(zErr);
  if( zMsg ){
    sqlite3_result_error(pCtx, zMsg, -1);
    sqlite3_free(zMsg);
  }else{
    sqlite3_result_error_nomem(pCtx);
  }
  return 0;
}


/*
** Report the wrong number of arguments for json_insert(), json_replace()
** or json_set().
*/
static void jsonWrongNumArgs(
  sqlite3_context *pCtx,
  const char *zFuncName
){
  char *zMsg = sqlite3_mprintf("json_%s() needs an odd number of arguments",
                               zFuncName);
  sqlite3_result_error(pCtx, zMsg, -1);
  sqlite3_free(zMsg);     
}

/*
** Mark all NULL entries in the Object passed in as JNODE_REMOVE.
*/
static void jsonRemoveAllNulls(JsonNode *pNode){
  int i, n;
  assert( pNode->eType==JSON_OBJECT );
  n = pNode->n;
  for(i=2; i<=n; i += jsonNodeSize(&pNode[i])+1){
    switch( pNode[i].eType ){
      case JSON_NULL:
        pNode[i].jnFlags |= JNODE_REMOVE;
        break;
      case JSON_OBJECT:
        jsonRemoveAllNulls(&pNode[i]);
        break;
    }
  }
}


/****************************************************************************
** SQL functions used for testing and debugging
****************************************************************************/

#ifdef SQLITE_DEBUG
/*
** The json_parse(JSON) function returns a string which describes
** a parse of the JSON provided.  Or it returns NULL if JSON is not
** well-formed.
*/
static void jsonParseFunc(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  JsonString s;       /* Output string - not real JSON */
  JsonParse x;        /* The parse */
  u32 i;

  assert( argc==1 );
  if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
  jsonParseFindParents(&x);
  jsonInit(&s, ctx);
  for(i=0; i<x.nNode; i++){
    const char *zType;
    if( x.aNode[i].jnFlags & JNODE_LABEL ){
      assert( x.aNode[i].eType==JSON_STRING );
      zType = "label";
    }else{
      zType = jsonType[x.aNode[i].eType];
    }
    jsonPrintf(100, &s,"node %3u: %7s n=%-4d up=%-4d",
               i, zType, x.aNode[i].n, x.aUp[i]);
    if( x.aNode[i].u.zJContent!=0 ){
      jsonAppendRaw(&s, " ", 1);
      jsonAppendRaw(&s, x.aNode[i].u.zJContent, x.aNode[i].n);
    }
    jsonAppendRaw(&s, "\n", 1);
  }
  jsonParseReset(&x);
  jsonResult(&s);
}

/*
** The json_test1(JSON) function return true (1) if the input is JSON
** text generated by another json function.  It returns (0) if the input
** is not known to be JSON.
*/
static void jsonTest1Func(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  UNUSED_PARAM(argc);
  sqlite3_result_int(ctx, sqlite3_value_subtype(argv[0])==JSON_SUBTYPE);
}
#endif /* SQLITE_DEBUG */

/****************************************************************************
** Scalar SQL function implementations
****************************************************************************/

/*
** Implementation of the json_QUOTE(VALUE) function.  Return a JSON value
** corresponding to the SQL value input.  Mostly this means putting 
** double-quotes around strings and returning the unquoted string "null"
** when given a NULL input.
*/
static void jsonQuoteFunc(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  JsonString jx;
  UNUSED_PARAM(argc);

  jsonInit(&jx, ctx);
  jsonAppendValue(&jx, argv[0]);
  jsonResult(&jx);
  sqlite3_result_subtype(ctx, JSON_SUBTYPE);
}

/*
** Implementation of the json_array(VALUE,...) function.  Return a JSON
** array that contains all values given in arguments.  Or if any argument
** is a BLOB, throw an error.
*/
static void jsonArrayFunc(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  int i;
  JsonString jx;

  jsonInit(&jx, ctx);
  jsonAppendChar(&jx, '[');
  for(i=0; i<argc; i++){
    jsonAppendSeparator(&jx);
    jsonAppendValue(&jx, argv[i]);
  }
  jsonAppendChar(&jx, ']');
  jsonResult(&jx);
  sqlite3_result_subtype(ctx, JSON_SUBTYPE);
}


/*
** json_array_length(JSON)
** json_array_length(JSON, PATH)
**
** Return the number of elements in the top-level JSON array.  
** Return 0 if the input is not a well-formed JSON array.
*/
static void jsonArrayLengthFunc(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  JsonParse *p;          /* The parse */
  sqlite3_int64 n = 0;
  u32 i;
  JsonNode *pNode;

  p = jsonParseCached(ctx, argv, ctx);
  if( p==0 ) return;
  assert( p->nNode );
  if( argc==2 ){
    const char *zPath = (const char*)sqlite3_value_text(argv[1]);
    pNode = jsonLookup(p, zPath, 0, ctx);
  }else{
    pNode = p->aNode;
  }
  if( pNode==0 ){
    return;
  }
  if( pNode->eType==JSON_ARRAY ){
    assert( (pNode->jnFlags & JNODE_APPEND)==0 );
    for(i=1; i<=pNode->n; n++){
      i += jsonNodeSize(&pNode[i]);
    }
  }
  sqlite3_result_int64(ctx, n);
}

/*
** json_extract(JSON, PATH, ...)
**
** Return the element described by PATH.  Return NULL if there is no
** PATH element.  If there are multiple PATHs, then return a JSON array
** with the result from each path.  Throw an error if the JSON or any PATH
** is malformed.
*/
static void jsonExtractFunc(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  JsonParse *p;          /* The parse */
  JsonNode *pNode;
  const char *zPath;
  JsonString jx;
  int i;

  if( argc<2 ) return;
  p = jsonParseCached(ctx, argv, ctx);
  if( p==0 ) return;
  jsonInit(&jx, ctx);
  jsonAppendChar(&jx, '[');
  for(i=1; i<argc; i++){
    zPath = (const char*)sqlite3_value_text(argv[i]);
    pNode = jsonLookup(p, zPath, 0, ctx);
    if( p->nErr ) break;
    if( argc>2 ){
      jsonAppendSeparator(&jx);
      if( pNode ){
        jsonRenderNode(pNode, &jx, 0);
      }else{
        jsonAppendRaw(&jx, "null", 4);
      }
    }else if( pNode ){
      jsonReturn(pNode, ctx, 0);
    }
  }
  if( argc>2 && i==argc ){
    jsonAppendChar(&jx, ']');
    jsonResult(&jx);
    sqlite3_result_subtype(ctx, JSON_SUBTYPE);
  }
  jsonReset(&jx);
}

/* This is the RFC 7396 MergePatch algorithm.
*/
static JsonNode *jsonMergePatch(
  JsonParse *pParse,   /* The JSON parser that contains the TARGET */
  u32 iTarget,         /* Node of the TARGET in pParse */
  JsonNode *pPatch     /* The PATCH */
){
  u32 i, j;
  u32 iRoot;
  JsonNode *pTarget;
  if( pPatch->eType!=JSON_OBJECT ){
    return pPatch;
  }
  assert( iTarget>=0 && iTarget<pParse->nNode );
  pTarget = &pParse->aNode[iTarget];
  assert( (pPatch->jnFlags & JNODE_APPEND)==0 );
  if( pTarget->eType!=JSON_OBJECT ){
    jsonRemoveAllNulls(pPatch);
    return pPatch;
  }
  iRoot = iTarget;
  for(i=1; i<pPatch->n; i += jsonNodeSize(&pPatch[i+1])+1){
    u32 nKey;
    const char *zKey;
    assert( pPatch[i].eType==JSON_STRING );
    assert( pPatch[i].jnFlags & JNODE_LABEL );
    nKey = pPatch[i].n;
    zKey = pPatch[i].u.zJContent;
    assert( (pPatch[i].jnFlags & JNODE_RAW)==0 );
    for(j=1; j<pTarget->n; j += jsonNodeSize(&pTarget[j+1])+1 ){
      assert( pTarget[j].eType==JSON_STRING );
      assert( pTarget[j].jnFlags & JNODE_LABEL );
      assert( (pPatch[i].jnFlags & JNODE_RAW)==0 );
      if( pTarget[j].n==nKey && strncmp(pTarget[j].u.zJContent,zKey,nKey)==0 ){
        if( pTarget[j+1].jnFlags & (JNODE_REMOVE|JNODE_PATCH) ) break;
        if( pPatch[i+1].eType==JSON_NULL ){
          pTarget[j+1].jnFlags |= JNODE_REMOVE;
        }else{
          JsonNode *pNew = jsonMergePatch(pParse, iTarget+j+1, &pPatch[i+1]);
          if( pNew==0 ) return 0;
          pTarget = &pParse->aNode[iTarget];
          if( pNew!=&pTarget[j+1] ){
            pTarget[j+1].u.pPatch = pNew;
            pTarget[j+1].jnFlags |= JNODE_PATCH;
          }
        }
        break;
      }
    }
    if( j>=pTarget->n && pPatch[i+1].eType!=JSON_NULL ){
      int iStart, iPatch;
      iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0);
      jsonParseAddNode(pParse, JSON_STRING, nKey, zKey);
      iPatch = jsonParseAddNode(pParse, JSON_TRUE, 0, 0);
      if( pParse->oom ) return 0;
      jsonRemoveAllNulls(pPatch);
      pTarget = &pParse->aNode[iTarget];
      pParse->aNode[iRoot].jnFlags |= JNODE_APPEND;
      pParse->aNode[iRoot].u.iAppend = iStart - iRoot;
      iRoot = iStart;
      pParse->aNode[iPatch].jnFlags |= JNODE_PATCH;
      pParse->aNode[iPatch].u.pPatch = &pPatch[i+1];
    }
  }
  return pTarget;
}

/*
** Implementation of the json_mergepatch(JSON1,JSON2) function.  Return a JSON
** object that is the result of running the RFC 7396 MergePatch() algorithm
** on the two arguments.
*/
static void jsonPatchFunc(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  JsonParse x;     /* The JSON that is being patched */
  JsonParse y;     /* The patch */
  JsonNode *pResult;   /* The result of the merge */

  UNUSED_PARAM(argc);
  if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
  if( jsonParse(&y, ctx, (const char*)sqlite3_value_text(argv[1])) ){
    jsonParseReset(&x);
    return;
  }
  pResult = jsonMergePatch(&x, 0, y.aNode);
  assert( pResult!=0 || x.oom );
  if( pResult ){
    jsonReturnJson(pResult, ctx, 0);
  }else{
    sqlite3_result_error_nomem(ctx);
  }
  jsonParseReset(&x);
  jsonParseReset(&y);
}


/*
** Implementation of the json_object(NAME,VALUE,...) function.  Return a JSON
** object that contains all name/value given in arguments.  Or if any name
** is not a string or if any value is a BLOB, throw an error.
*/
static void jsonObjectFunc(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  int i;
  JsonString jx;
  const char *z;
  u32 n;

  if( argc&1 ){
    sqlite3_result_error(ctx, "json_object() requires an even number "
                                  "of arguments", -1);
    return;
  }
  jsonInit(&jx, ctx);
  jsonAppendChar(&jx, '{');
  for(i=0; i<argc; i+=2){
    if( sqlite3_value_type(argv[i])!=SQLITE_TEXT ){
      sqlite3_result_error(ctx, "json_object() labels must be TEXT", -1);
      jsonReset(&jx);
      return;
    }
    jsonAppendSeparator(&jx);
    z = (const char*)sqlite3_value_text(argv[i]);
    n = (u32)sqlite3_value_bytes(argv[i]);
    jsonAppendString(&jx, z, n);
    jsonAppendChar(&jx, ':');
    jsonAppendValue(&jx, argv[i+1]);
  }
  jsonAppendChar(&jx, '}');
  jsonResult(&jx);
  sqlite3_result_subtype(ctx, JSON_SUBTYPE);
}


/*
** json_remove(JSON, PATH, ...)
**
** Remove the named elements from JSON and return the result.  malformed
** JSON or PATH arguments result in an error.
*/
static void jsonRemoveFunc(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  JsonParse x;          /* The parse */
  JsonNode *pNode;
  const char *zPath;
  u32 i;

  if( argc<1 ) return;
  if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
  assert( x.nNode );
  for(i=1; i<(u32)argc; i++){
    zPath = (const char*)sqlite3_value_text(argv[i]);
    if( zPath==0 ) goto remove_done;
    pNode = jsonLookup(&x, zPath, 0, ctx);
    if( x.nErr ) goto remove_done;
    if( pNode ) pNode->jnFlags |= JNODE_REMOVE;
  }
  if( (x.aNode[0].jnFlags & JNODE_REMOVE)==0 ){
    jsonReturnJson(x.aNode, ctx, 0);
  }
remove_done:
  jsonParseReset(&x);
}

/*
** json_replace(JSON, PATH, VALUE, ...)
**
** Replace the value at PATH with VALUE.  If PATH does not already exist,
** this routine is a no-op.  If JSON or PATH is malformed, throw an error.
*/
static void jsonReplaceFunc(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  JsonParse x;          /* The parse */
  JsonNode *pNode;
  const char *zPath;
  u32 i;

  if( argc<1 ) return;
  if( (argc&1)==0 ) {
    jsonWrongNumArgs(ctx, "replace");
    return;
  }
  if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
  assert( x.nNode );
  for(i=1; i<(u32)argc; i+=2){
    zPath = (const char*)sqlite3_value_text(argv[i]);
    pNode = jsonLookup(&x, zPath, 0, ctx);
    if( x.nErr ) goto replace_err;
    if( pNode ){
      pNode->jnFlags |= (u8)JNODE_REPLACE;
      pNode->u.iReplace = i + 1;
    }
  }
  if( x.aNode[0].jnFlags & JNODE_REPLACE ){
    sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]);
  }else{
    jsonReturnJson(x.aNode, ctx, argv);
  }
replace_err:
  jsonParseReset(&x);
}

/*
** json_set(JSON, PATH, VALUE, ...)
**
** Set the value at PATH to VALUE.  Create the PATH if it does not already
** exist.  Overwrite existing values that do exist.
** If JSON or PATH is malformed, throw an error.
**
** json_insert(JSON, PATH, VALUE, ...)
**
** Create PATH and initialize it to VALUE.  If PATH already exists, this
** routine is a no-op.  If JSON or PATH is malformed, throw an error.
*/
static void jsonSetFunc(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  JsonParse x;          /* The parse */
  JsonNode *pNode;
  const char *zPath;
  u32 i;
  int bApnd;
  int bIsSet = *(int*)sqlite3_user_data(ctx);

  if( argc<1 ) return;
  if( (argc&1)==0 ) {
    jsonWrongNumArgs(ctx, bIsSet ? "set" : "insert");
    return;
  }
  if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
  assert( x.nNode );
  for(i=1; i<(u32)argc; i+=2){
    zPath = (const char*)sqlite3_value_text(argv[i]);
    bApnd = 0;
    pNode = jsonLookup(&x, zPath, &bApnd, ctx);
    if( x.oom ){
      sqlite3_result_error_nomem(ctx);
      goto jsonSetDone;
    }else if( x.nErr ){
      goto jsonSetDone;
    }else if( pNode && (bApnd || bIsSet) ){
      pNode->jnFlags |= (u8)JNODE_REPLACE;
      pNode->u.iReplace = i + 1;
    }
  }
  if( x.aNode[0].jnFlags & JNODE_REPLACE ){
    sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]);
  }else{
    jsonReturnJson(x.aNode, ctx, argv);
  }
jsonSetDone:
  jsonParseReset(&x);
}

/*
** json_type(JSON)
** json_type(JSON, PATH)
**
** Return the top-level "type" of a JSON string.  Throw an error if
** either the JSON or PATH inputs are not well-formed.
*/
static void jsonTypeFunc(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  JsonParse *p;          /* The parse */
  const char *zPath;
  JsonNode *pNode;

  p = jsonParseCached(ctx, argv, ctx);
  if( p==0 ) return;
  if( argc==2 ){
    zPath = (const char*)sqlite3_value_text(argv[1]);
    pNode = jsonLookup(p, zPath, 0, ctx);
  }else{
    pNode = p->aNode;
  }
  if( pNode ){
    sqlite3_result_text(ctx, jsonType[pNode->eType], -1, SQLITE_STATIC);
  }
}

/*
** json_valid(JSON)
**
** Return 1 if JSON is a well-formed JSON string according to RFC-7159.
** Return 0 otherwise.
*/
static void jsonValidFunc(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  JsonParse *p;          /* The parse */
  UNUSED_PARAM(argc);
  p = jsonParseCached(ctx, argv, 0);
  sqlite3_result_int(ctx, p!=0);
}


/****************************************************************************
** Aggregate SQL function implementations
****************************************************************************/
/*
** json_group_array(VALUE)
**
** Return a JSON array composed of all values in the aggregate.
*/
static void jsonArrayStep(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  JsonString *pStr;
  UNUSED_PARAM(argc);
  pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
  if( pStr ){
    if( pStr->zBuf==0 ){
      jsonInit(pStr, ctx);
      jsonAppendChar(pStr, '[');
    }else{
      jsonAppendChar(pStr, ',');
      pStr->pCtx = ctx;
    }
    jsonAppendValue(pStr, argv[0]);
  }
}
static void jsonArrayCompute(sqlite3_context *ctx, int isFinal){
  JsonString *pStr;
  pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
  if( pStr ){
    pStr->pCtx = ctx;
    jsonAppendChar(pStr, ']');
    if( pStr->bErr ){
      if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx);
      assert( pStr->bStatic );
    }else if( isFinal ){
      sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed,
                          pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free);
      pStr->bStatic = 1;
    }else{
      sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT);
      pStr->nUsed--;
    }
  }else{
    sqlite3_result_text(ctx, "[]", 2, SQLITE_STATIC);
  }
  sqlite3_result_subtype(ctx, JSON_SUBTYPE);
}
static void jsonArrayValue(sqlite3_context *ctx){
  jsonArrayCompute(ctx, 0);
}
static void jsonArrayFinal(sqlite3_context *ctx){
  jsonArrayCompute(ctx, 1);
}

#ifndef SQLITE_OMIT_WINDOWFUNC
/*
** This method works for both json_group_array() and json_group_object().
** It works by removing the first element of the group by searching forward
** to the first comma (",") that is not within a string and deleting all
** text through that comma.
*/
static void jsonGroupInverse(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  int i;
  int inStr = 0;
  char *z;
  JsonString *pStr;
  UNUSED_PARAM(argc);
  UNUSED_PARAM(argv);
  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; z[i]!=',' || inStr; i++){
    assert( i<pStr->nUsed );
    if( z[i]=='"' ){
      inStr = !inStr;
    }else if( z[i]=='\\' ){
      i++;
    }
  }
  pStr->nUsed -= i;      
  memmove(&z[1], &z[i+1], (size_t)pStr->nUsed-1);
}
#else
# define jsonGroupInverse 0
#endif


/*
** json_group_obj(NAME,VALUE)
**
** Return a JSON object composed of all names and values in the aggregate.
*/
static void jsonObjectStep(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  JsonString *pStr;
  const char *z;
  u32 n;
  UNUSED_PARAM(argc);
  pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
  if( pStr ){
    if( pStr->zBuf==0 ){
      jsonInit(pStr, ctx);
      jsonAppendChar(pStr, '{');
    }else{
      jsonAppendChar(pStr, ',');
      pStr->pCtx = ctx;
    }
    z = (const char*)sqlite3_value_text(argv[0]);
    n = (u32)sqlite3_value_bytes(argv[0]);
    jsonAppendString(pStr, z, n);
    jsonAppendChar(pStr, ':');
    jsonAppendValue(pStr, argv[1]);
  }
}
static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){
  JsonString *pStr;
  pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
  if( pStr ){
    jsonAppendChar(pStr, '}');
    if( pStr->bErr ){
      if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx);
      assert( pStr->bStatic );
    }else if( isFinal ){
      sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed,
                          pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free);
      pStr->bStatic = 1;
    }else{
      sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT);
      pStr->nUsed--;
    }
  }else{
    sqlite3_result_text(ctx, "{}", 2, SQLITE_STATIC);
  }
  sqlite3_result_subtype(ctx, JSON_SUBTYPE);
}
static void jsonObjectValue(sqlite3_context *ctx){
  jsonObjectCompute(ctx, 0);
}
static void jsonObjectFinal(sqlite3_context *ctx){
  jsonObjectCompute(ctx, 1);
}



#ifndef SQLITE_OMIT_VIRTUALTABLE
/****************************************************************************
** The json_each virtual table
****************************************************************************/
typedef struct JsonEachCursor JsonEachCursor;
struct JsonEachCursor {
  sqlite3_vtab_cursor base;  /* Base class - must be first */
  u32 iRowid;                /* The rowid */
  u32 iBegin;                /* The first node of the scan */
  u32 i;                     /* Index in sParse.aNode[] of current row */
  u32 iEnd;                  /* EOF when i equals or exceeds this value */
  u8 eType;                  /* Type of top-level element */
  u8 bRecursive;             /* True for json_tree().  False for json_each() */
  char *zJson;               /* Input JSON */
  char *zRoot;               /* Path by which to filter zJson */
  JsonParse sParse;          /* Parse of the input JSON */
};

/* Constructor for the json_each virtual table */
static int jsonEachConnect(
  sqlite3 *db,
  void *pAux,
  int argc, const char *const*argv,
  sqlite3_vtab **ppVtab,
  char **pzErr
){
  sqlite3_vtab *pNew;
  int rc;

/* Column numbers */
#define JEACH_KEY     0
#define JEACH_VALUE   1
#define JEACH_TYPE    2
#define JEACH_ATOM    3
#define JEACH_ID      4
#define JEACH_PARENT  5
#define JEACH_FULLKEY 6
#define JEACH_PATH    7
/* The xBestIndex method assumes that the JSON and ROOT columns are
** the last two columns in the table.  Should this ever changes, be
** sure to update the xBestIndex method. */
#define JEACH_JSON    8
#define JEACH_ROOT    9

  UNUSED_PARAM(pzErr);
  UNUSED_PARAM(argv);
  UNUSED_PARAM(argc);
  UNUSED_PARAM(pAux);
  rc = sqlite3_declare_vtab(db, 
     "CREATE TABLE x(key,value,type,atom,id,parent,fullkey,path,"
                    "json HIDDEN,root HIDDEN)");
  if( rc==SQLITE_OK ){
    pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) );
    if( pNew==0 ) return SQLITE_NOMEM;
    memset(pNew, 0, sizeof(*pNew));
  }
  return rc;
}

/* destructor for json_each virtual table */
static int jsonEachDisconnect(sqlite3_vtab *pVtab){
  sqlite3_free(pVtab);
  return SQLITE_OK;
}

/* constructor for a JsonEachCursor object for json_each(). */
static int jsonEachOpenEach(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
  JsonEachCursor *pCur;

  UNUSED_PARAM(p);
  pCur = sqlite3_malloc( sizeof(*pCur) );
  if( pCur==0 ) return SQLITE_NOMEM;
  memset(pCur, 0, sizeof(*pCur));
  *ppCursor = &pCur->base;
  return SQLITE_OK;
}

/* constructor for a JsonEachCursor object for json_tree(). */
static int jsonEachOpenTree(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
  int rc = jsonEachOpenEach(p, ppCursor);
  if( rc==SQLITE_OK ){
    JsonEachCursor *pCur = (JsonEachCursor*)*ppCursor;
    pCur->bRecursive = 1;
  }
  return rc;
}

/* Reset a JsonEachCursor back to its original state.  Free any memory
** held. */
static void jsonEachCursorReset(JsonEachCursor *p){
  sqlite3_free(p->zJson);
  sqlite3_free(p->zRoot);
  jsonParseReset(&p->sParse);
  p->iRowid = 0;
  p->i = 0;
  p->iEnd = 0;
  p->eType = 0;
  p->zJson = 0;
  p->zRoot = 0;
}

/* Destructor for a jsonEachCursor object */
static int jsonEachClose(sqlite3_vtab_cursor *cur){
  JsonEachCursor *p = (JsonEachCursor*)cur;
  jsonEachCursorReset(p);
  sqlite3_free(cur);
  return SQLITE_OK;
}

/* Return TRUE if the jsonEachCursor object has been advanced off the end
** of the JSON object */
static int jsonEachEof(sqlite3_vtab_cursor *cur){
  JsonEachCursor *p = (JsonEachCursor*)cur;
  return p->i >= p->iEnd;
}

/* Advance the cursor to the next element for json_tree() */
static int jsonEachNext(sqlite3_vtab_cursor *cur){
  JsonEachCursor *p = (JsonEachCursor*)cur;
  if( p->bRecursive ){
    if( p->sParse.aNode[p->i].jnFlags & JNODE_LABEL ) p->i++;
    p->i++;
    p->iRowid++;
    if( p->i<p->iEnd ){
      u32 iUp = p->sParse.aUp[p->i];
      JsonNode *pUp = &p->sParse.aNode[iUp];
      p->eType = pUp->eType;
      if( pUp->eType==JSON_ARRAY ){
        if( iUp==p->i-1 ){
          pUp->u.iKey = 0;
        }else{
          pUp->u.iKey++;
        }
      }
    }
  }else{
    switch( p->eType ){
      case JSON_ARRAY: {
        p->i += jsonNodeSize(&p->sParse.aNode[p->i]);
        p->iRowid++;
        break;
      }
      case JSON_OBJECT: {
        p->i += 1 + jsonNodeSize(&p->sParse.aNode[p->i+1]);
        p->iRowid++;
        break;
      }
      default: {
        p->i = p->iEnd;
        break;
      }
    }
  }
  return SQLITE_OK;
}

/* Append the name of the path for element i to pStr
*/
static void jsonEachComputePath(
  JsonEachCursor *p,       /* The cursor */
  JsonString *pStr,        /* Write the path here */
  u32 i                    /* Path to this element */
){
  JsonNode *pNode, *pUp;
  u32 iUp;
  if( i==0 ){
    jsonAppendChar(pStr, '$');
    return;
  }
  iUp = p->sParse.aUp[i];
  jsonEachComputePath(p, pStr, iUp);
  pNode = &p->sParse.aNode[i];
  pUp = &p->sParse.aNode[iUp];
  if( pUp->eType==JSON_ARRAY ){
    jsonPrintf(30, pStr, "[%d]", pUp->u.iKey);
  }else{
    assert( pUp->eType==JSON_OBJECT );
    if( (pNode->jnFlags & JNODE_LABEL)==0 ) pNode--;
    assert( pNode->eType==JSON_STRING );
    assert( pNode->jnFlags & JNODE_LABEL );
    jsonPrintf(pNode->n+1, pStr, ".%.*s", pNode->n-2, pNode->u.zJContent+1);
  }
}

/* Return the value of a column */
static int jsonEachColumn(
  sqlite3_vtab_cursor *cur,   /* The cursor */
  sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
  int i                       /* Which column to return */
){
  JsonEachCursor *p = (JsonEachCursor*)cur;
  JsonNode *pThis = &p->sParse.aNode[p->i];
  switch( i ){
    case JEACH_KEY: {
      if( p->i==0 ) break;
      if( p->eType==JSON_OBJECT ){
        jsonReturn(pThis, ctx, 0);
      }else if( p->eType==JSON_ARRAY ){
        u32 iKey;
        if( p->bRecursive ){
          if( p->iRowid==0 ) break;
          iKey = p->sParse.aNode[p->sParse.aUp[p->i]].u.iKey;
        }else{
          iKey = p->iRowid;
        }
        sqlite3_result_int64(ctx, (sqlite3_int64)iKey);
      }
      break;
    }
    case JEACH_VALUE: {
      if( pThis->jnFlags & JNODE_LABEL ) pThis++;
      jsonReturn(pThis, ctx, 0);
      break;
    }
    case JEACH_TYPE: {
      if( pThis->jnFlags & JNODE_LABEL ) pThis++;
      sqlite3_result_text(ctx, jsonType[pThis->eType], -1, SQLITE_STATIC);
      break;
    }
    case JEACH_ATOM: {
      if( pThis->jnFlags & JNODE_LABEL ) pThis++;
      if( pThis->eType>=JSON_ARRAY ) break;
      jsonReturn(pThis, ctx, 0);
      break;
    }
    case JEACH_ID: {
      sqlite3_result_int64(ctx, 
         (sqlite3_int64)p->i + ((pThis->jnFlags & JNODE_LABEL)!=0));
      break;
    }
    case JEACH_PARENT: {
      if( p->i>p->iBegin && p->bRecursive ){
        sqlite3_result_int64(ctx, (sqlite3_int64)p->sParse.aUp[p->i]);
      }
      break;
    }
    case JEACH_FULLKEY: {
      JsonString x;
      jsonInit(&x, ctx);
      if( p->bRecursive ){
        jsonEachComputePath(p, &x, p->i);
      }else{
        if( p->zRoot ){
          jsonAppendRaw(&x, p->zRoot, (int)strlen(p->zRoot));
        }else{
          jsonAppendChar(&x, '$');
        }
        if( p->eType==JSON_ARRAY ){
          jsonPrintf(30, &x, "[%d]", p->iRowid);
        }else if( p->eType==JSON_OBJECT ){
          jsonPrintf(pThis->n, &x, ".%.*s", pThis->n-2, pThis->u.zJContent+1);
        }
      }
      jsonResult(&x);
      break;
    }
    case JEACH_PATH: {
      if( p->bRecursive ){
        JsonString x;
        jsonInit(&x, ctx);
        jsonEachComputePath(p, &x, p->sParse.aUp[p->i]);
        jsonResult(&x);
        break;
      }
      /* For json_each() path and root are the same so fall through
      ** into the root case */
    }
    default: {
      const char *zRoot = p->zRoot;
      if( zRoot==0 ) zRoot = "$";
      sqlite3_result_text(ctx, zRoot, -1, SQLITE_STATIC);
      break;
    }
    case JEACH_JSON: {
      assert( i==JEACH_JSON );
      sqlite3_result_text(ctx, p->sParse.zJson, -1, SQLITE_STATIC);
      break;
    }
  }
  return SQLITE_OK;
}

/* Return the current rowid value */
static int jsonEachRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
  JsonEachCursor *p = (JsonEachCursor*)cur;
  *pRowid = p->iRowid;
  return SQLITE_OK;
}

/* The query strategy is to look for an equality constraint on the json
** column.  Without such a constraint, the table cannot operate.  idxNum is
** 1 if the constraint is found, 3 if the constraint and zRoot are found,
** and 0 otherwise.
*/
static int jsonEachBestIndex(
  sqlite3_vtab *tab,
  sqlite3_index_info *pIdxInfo
){
  int i;                     /* Loop counter or computed array index */
  int aIdx[2];               /* Index of constraints for JSON and ROOT */
  int unusableMask = 0;      /* Mask of unusable JSON and ROOT constraints */
  int idxMask = 0;           /* Mask of usable == constraints JSON and ROOT */
  const struct sqlite3_index_constraint *pConstraint;

  /* This implementation assumes that JSON and ROOT are the last two
  ** columns in the table */
  assert( JEACH_ROOT == JEACH_JSON+1 );
  UNUSED_PARAM(tab);
  aIdx[0] = aIdx[1] = -1;
  pConstraint = pIdxInfo->aConstraint;
  for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
    int iCol;
    int iMask;
    if( pConstraint->iColumn < JEACH_JSON ) continue;
    iCol = pConstraint->iColumn - JEACH_JSON;
    assert( iCol==0 || iCol==1 );
    iMask = 1 << iCol;
    if( pConstraint->usable==0 ){
      unusableMask |= iMask;
    }else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
      aIdx[iCol] = i;
      idxMask |= iMask;
    }
  }
  if( (unusableMask & ~idxMask)!=0 ){
    /* If there are any unusable constraints on JSON or ROOT, then reject
    ** this entire plan */
    return SQLITE_CONSTRAINT;
  }
  if( aIdx[0]<0 ){
    /* No JSON input.  Leave estimatedCost at the huge value that it was
    ** initialized to to discourage the query planner from selecting this
    ** plan. */
    pIdxInfo->idxNum = 0;
  }else{
    pIdxInfo->estimatedCost = 1.0;
    i = aIdx[0];
    pIdxInfo->aConstraintUsage[i].argvIndex = 1;
    pIdxInfo->aConstraintUsage[i].omit = 1;
    if( aIdx[1]<0 ){
      pIdxInfo->idxNum = 1;  /* Only JSON supplied.  Plan 1 */
    }else{
      i = aIdx[1];
      pIdxInfo->aConstraintUsage[i].argvIndex = 2;
      pIdxInfo->aConstraintUsage[i].omit = 1;
      pIdxInfo->idxNum = 3;  /* Both JSON and ROOT are supplied.  Plan 3 */
    }
  }
  return SQLITE_OK;
}

/* Start a search on a new JSON string */
static int jsonEachFilter(
  sqlite3_vtab_cursor *cur,
  int idxNum, const char *idxStr,
  int argc, sqlite3_value **argv
){
  JsonEachCursor *p = (JsonEachCursor*)cur;
  const char *z;
  const char *zRoot = 0;
  sqlite3_int64 n;

  UNUSED_PARAM(idxStr);
  UNUSED_PARAM(argc);
  jsonEachCursorReset(p);
  if( idxNum==0 ) return SQLITE_OK;
  z = (const char*)sqlite3_value_text(argv[0]);
  if( z==0 ) return SQLITE_OK;
  n = sqlite3_value_bytes(argv[0]);
  p->zJson = sqlite3_malloc64( n+1 );
  if( p->zJson==0 ) return SQLITE_NOMEM;
  memcpy(p->zJson, z, (size_t)n+1);
  if( jsonParse(&p->sParse, 0, p->zJson) ){
    int rc = SQLITE_NOMEM;
    if( p->sParse.oom==0 ){
      sqlite3_free(cur->pVtab->zErrMsg);
      cur->pVtab->zErrMsg = sqlite3_mprintf("malformed JSON");
      if( cur->pVtab->zErrMsg ) rc = SQLITE_ERROR;
    }
    jsonEachCursorReset(p);
    return rc;
  }else if( p->bRecursive && jsonParseFindParents(&p->sParse) ){
    jsonEachCursorReset(p);
    return SQLITE_NOMEM;
  }else{
    JsonNode *pNode = 0;
    if( idxNum==3 ){
      const char *zErr = 0;
      zRoot = (const char*)sqlite3_value_text(argv[1]);
      if( zRoot==0 ) return SQLITE_OK;
      n = sqlite3_value_bytes(argv[1]);
      p->zRoot = sqlite3_malloc64( n+1 );
      if( p->zRoot==0 ) return SQLITE_NOMEM;
      memcpy(p->zRoot, zRoot, (size_t)n+1);
      if( zRoot[0]!='$' ){
        zErr = zRoot;
      }else{
        pNode = jsonLookupStep(&p->sParse, 0, p->zRoot+1, 0, &zErr);
      }
      if( zErr ){
        sqlite3_free(cur->pVtab->zErrMsg);
        cur->pVtab->zErrMsg = jsonPathSyntaxError(zErr);
        jsonEachCursorReset(p);
        return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM;
      }else if( pNode==0 ){
        return SQLITE_OK;
      }
    }else{
      pNode = p->sParse.aNode;
    }
    p->iBegin = p->i = (int)(pNode - p->sParse.aNode);
    p->eType = pNode->eType;
    if( p->eType>=JSON_ARRAY ){
      pNode->u.iKey = 0;
      p->iEnd = p->i + pNode->n + 1;
      if( p->bRecursive ){
        p->eType = p->sParse.aNode[p->sParse.aUp[p->i]].eType;
        if( p->i>0 && (p->sParse.aNode[p->i-1].jnFlags & JNODE_LABEL)!=0 ){
          p->i--;
        }
      }else{
        p->i++;
      }
    }else{
      p->iEnd = p->i+1;
    }
  }
  return SQLITE_OK;
}

/* The methods of the json_each virtual table */
static sqlite3_module jsonEachModule = {
  0,                         /* iVersion */
  0,                         /* xCreate */
  jsonEachConnect,           /* xConnect */
  jsonEachBestIndex,         /* xBestIndex */
  jsonEachDisconnect,        /* xDisconnect */
  0,                         /* xDestroy */
  jsonEachOpenEach,          /* xOpen - open a cursor */
  jsonEachClose,             /* xClose - close a cursor */
  jsonEachFilter,            /* xFilter - configure scan constraints */
  jsonEachNext,              /* xNext - advance a cursor */
  jsonEachEof,               /* xEof - check for end of scan */
  jsonEachColumn,            /* xColumn - read data */
  jsonEachRowid,             /* xRowid - read data */
  0,                         /* xUpdate */
  0,                         /* xBegin */
  0,                         /* xSync */
  0,                         /* xCommit */
  0,                         /* xRollback */
  0,                         /* xFindMethod */
  0,                         /* xRename */
  0,                         /* xSavepoint */
  0,                         /* xRelease */
  0,                         /* xRollbackTo */
  0                          /* xShadowName */
};

/* The methods of the json_tree virtual table. */
static sqlite3_module jsonTreeModule = {
  0,                         /* iVersion */
  0,                         /* xCreate */
  jsonEachConnect,           /* xConnect */
  jsonEachBestIndex,         /* xBestIndex */
  jsonEachDisconnect,        /* xDisconnect */
  0,                         /* xDestroy */
  jsonEachOpenTree,          /* xOpen - open a cursor */
  jsonEachClose,             /* xClose - close a cursor */
  jsonEachFilter,            /* xFilter - configure scan constraints */
  jsonEachNext,              /* xNext - advance a cursor */
  jsonEachEof,               /* xEof - check for end of scan */
  jsonEachColumn,            /* xColumn - read data */
  jsonEachRowid,             /* xRowid - read data */
  0,                         /* xUpdate */
  0,                         /* xBegin */
  0,                         /* xSync */
  0,                         /* xCommit */
  0,                         /* xRollback */
  0,                         /* xFindMethod */
  0,                         /* xRename */
  0,                         /* xSavepoint */
  0,                         /* xRelease */
  0,                         /* xRollbackTo */
  0                          /* xShadowName */
};
#endif /* SQLITE_OMIT_VIRTUALTABLE */

/****************************************************************************
** The following routines are the only publically visible identifiers in this
** file.  Call the following routines in order to register the various SQL
** functions and the virtual table implemented by this file.
****************************************************************************/

int sqlite3Json1Init(sqlite3 *db){
  int rc = SQLITE_OK;
  unsigned int i;
  static const struct {
     const char *zName;
     int nArg;
     int flag;
     void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
  } aFunc[] = {
    { "json",                 1, 0,   jsonRemoveFunc        },
    { "json_array",          -1, 0,   jsonArrayFunc         },
    { "json_array_length",    1, 0,   jsonArrayLengthFunc   },
    { "json_array_length",    2, 0,   jsonArrayLengthFunc   },
    { "json_extract",        -1, 0,   jsonExtractFunc       },
    { "json_insert",         -1, 0,   jsonSetFunc           },
    { "json_object",         -1, 0,   jsonObjectFunc        },
    { "json_patch",           2, 0,   jsonPatchFunc         },
    { "json_quote",           1, 0,   jsonQuoteFunc         },
    { "json_remove",         -1, 0,   jsonRemoveFunc        },
    { "json_replace",        -1, 0,   jsonReplaceFunc       },
    { "json_set",            -1, 1,   jsonSetFunc           },
    { "json_type",            1, 0,   jsonTypeFunc          },
    { "json_type",            2, 0,   jsonTypeFunc          },
    { "json_valid",           1, 0,   jsonValidFunc         },

#if SQLITE_DEBUG
    /* DEBUG and TESTING functions */
    { "json_parse",           1, 0,   jsonParseFunc         },
    { "json_test1",           1, 0,   jsonTest1Func         },
#endif
  };
  static const struct {
     const char *zName;
     int nArg;
     void (*xStep)(sqlite3_context*,int,sqlite3_value**);
     void (*xFinal)(sqlite3_context*);
     void (*xValue)(sqlite3_context*);
  } aAgg[] = {
    { "json_group_array",     1,
      jsonArrayStep,   jsonArrayFinal,  jsonArrayValue  },
    { "json_group_object",    2,
      jsonObjectStep,  jsonObjectFinal, jsonObjectValue },
  };
#ifndef SQLITE_OMIT_VIRTUALTABLE
  static const struct {
     const char *zName;
     sqlite3_module *pModule;
  } aMod[] = {
    { "json_each",            &jsonEachModule               },
    { "json_tree",            &jsonTreeModule               },
  };
#endif
  for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
    rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg,
                                 SQLITE_UTF8 | SQLITE_DETERMINISTIC, 
                                 (void*)&aFunc[i].flag,
                                 aFunc[i].xFunc, 0, 0);
  }
#ifndef SQLITE_OMIT_WINDOWFUNC
  for(i=0; i<sizeof(aAgg)/sizeof(aAgg[0]) && rc==SQLITE_OK; i++){
    rc = sqlite3_create_window_function(db, aAgg[i].zName, aAgg[i].nArg,
                                 SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
                                 aAgg[i].xStep, aAgg[i].xFinal,
                                 aAgg[i].xValue, jsonGroupInverse, 0);
  }
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
  for(i=0; i<sizeof(aMod)/sizeof(aMod[0]) && rc==SQLITE_OK; i++){
    rc = sqlite3_create_module(db, aMod[i].zName, aMod[i].pModule, 0);
  }
#endif
  return rc;
}


#ifndef SQLITE_CORE
#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_json_init(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg;  /* Unused parameter */
  return sqlite3Json1Init(db);
}
#endif
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_JSON1) */

Changes to ext/misc/memstat.c.

139
140
141
142
143
144
145
146

147
148
149
150
151
152
153
139
140
141
142
143
144
145

146
147
148
149
150
151
152
153







-
+







  rc = sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pStmt, 0);
  if( rc ){
    sqlite3_finalize(pStmt);
    return rc;
  }
  while( sqlite3_step(pStmt)==SQLITE_ROW ){
    char **az, *z;
    az = sqlite3_realloc(pCur->azDb, sizeof(char*)*(pCur->nDb+1));
    az = sqlite3_realloc64(pCur->azDb, sizeof(char*)*(pCur->nDb+1));
    if( az==0 ){
      memstatClearSchema(pCur);
      return SQLITE_NOMEM;
    }
    pCur->azDb = az;
    z = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
    if( z==0 ){

Added ext/misc/memtrace.c.













































































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2019-01-21
**
** 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 an extension that uses the SQLITE_CONFIG_MALLOC
** mechanism to add a tracing layer on top of SQLite.  If this extension
** is registered prior to sqlite3_initialize(), it will cause all memory
** allocation activities to be logged on standard output, or to some other
** FILE specified by the initializer.
**
** This file needs to be compiled into the application that uses it.
**
** This extension is used to implement the --memtrace option of the
** command-line shell.
*/
#include <assert.h>
#include <string.h>
#include <stdio.h>

/* The original memory allocation routines */
static sqlite3_mem_methods memtraceBase;
static FILE *memtraceOut;

/* Methods that trace memory allocations */
static void *memtraceMalloc(int n){
  if( memtraceOut ){
    fprintf(memtraceOut, "MEMTRACE: allocate %d bytes\n", 
            memtraceBase.xRoundup(n));
  }
  return memtraceBase.xMalloc(n);
}
static void memtraceFree(void *p){
  if( p==0 ) return;
  if( memtraceOut ){
    fprintf(memtraceOut, "MEMTRACE: free %d bytes\n", memtraceBase.xSize(p));
  }
  memtraceBase.xFree(p);
}
static void *memtraceRealloc(void *p, int n){
  if( p==0 ) return memtraceMalloc(n);
  if( n==0 ){
    memtraceFree(p);
    return 0;
  }
  if( memtraceOut ){
    fprintf(memtraceOut, "MEMTRACE: resize %d -> %d bytes\n",
            memtraceBase.xSize(p), memtraceBase.xRoundup(n));
  }
  return memtraceBase.xRealloc(p, n);
}
static int memtraceSize(void *p){
  return memtraceBase.xSize(p);
}
static int memtraceRoundup(int n){
  return memtraceBase.xRoundup(n);
}
static int memtraceInit(void *p){
  return memtraceBase.xInit(p);
}
static void memtraceShutdown(void *p){
  memtraceBase.xShutdown(p);
}

/* The substitute memory allocator */
static sqlite3_mem_methods ersaztMethods = {
  memtraceMalloc,
  memtraceFree,
  memtraceRealloc,
  memtraceSize,
  memtraceRoundup,
  memtraceInit,
  memtraceShutdown,
  0
};

/* Begin tracing memory allocations to out. */
int sqlite3MemTraceActivate(FILE *out){
  int rc = SQLITE_OK;
  if( memtraceBase.xMalloc==0 ){
    rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memtraceBase);
    if( rc==SQLITE_OK ){
      rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &ersaztMethods);
    }
  }
  memtraceOut = out;
  return rc;
}

/* Deactivate memory tracing */
int sqlite3MemTraceDeactivate(void){
  int rc = SQLITE_OK;
  if( memtraceBase.xMalloc!=0 ){
    rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memtraceBase);
    if( rc==SQLITE_OK ){
      memset(&memtraceBase, 0, sizeof(memtraceBase));
    }
  }
  memtraceOut = 0;
  return rc;
}

Changes to ext/misc/memvfs.c.

555
556
557
558
559
560
561

562
563
564
565
566
567
568
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569







+







  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  SQLITE_EXTENSION_INIT2(pApi);
  mem_vfs.pAppData = sqlite3_vfs_find(0);
  if( mem_vfs.pAppData==0 ) return SQLITE_ERROR;
  mem_vfs.szOsFile = sizeof(MemFile);
  rc = sqlite3_vfs_register(&mem_vfs, 1);
#ifdef MEMVFS_TEST
  if( rc==SQLITE_OK ){
    rc = sqlite3_auto_extension((void(*)(void))memvfsRegister);
  }
  if( rc==SQLITE_OK ){

Changes to ext/misc/mmapwarm.c.

39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
39
40
41
42
43
44
45

46
47
48
49
50
51
52
53







-
+







  char *zSql = 0;
  int pgsz = 0;
  int nTotal = 0;

  if( 0==sqlite3_get_autocommit(db) ) return SQLITE_MISUSE;

  /* Open a read-only transaction on the file in question */
  zSql = sqlite3_mprintf("BEGIN; SELECT * FROM %s%q%ssqlite_master", 
  zSql = sqlite3_mprintf("BEGIN; SELECT * FROM %s%q%ssqlite_schema", 
      (zDb ? "'" : ""), (zDb ? zDb : ""), (zDb ? "'." : "")
  );
  if( zSql==0 ) return SQLITE_NOMEM;
  rc = sqlite3_exec(db, zSql, 0, 0, 0);
  sqlite3_free(zSql);

  /* Find the SQLite page size of the file */
101
102
103
104
105
106
107
108
101
102
103
104
105
106
107








-

    rc2 = sqlite3_exec(db, "END", 0, 0, 0);
    if( rc==SQLITE_OK ) rc = rc2;
  }

  return rc;
}

Changes to ext/misc/nextchar.c.

81
82
83
84
85
86
87
88

89
90
91
92
93
94
95
81
82
83
84
85
86
87

88
89
90
91
92
93
94
95







-
+







  int i;
  for(i=0; i<p->nUsed; i++){
    if( p->aResult[i]==c ) return;
  }
  if( p->nUsed+1 > p->nAlloc ){
    unsigned int *aNew;
    int n = p->nAlloc*2 + 30;
    aNew = sqlite3_realloc(p->aResult, n*sizeof(unsigned int));
    aNew = sqlite3_realloc64(p->aResult, n*sizeof(unsigned int));
    if( aNew==0 ){
      p->mallocFailed = 1;
      return;
    }else{
      p->aResult = aNew;
      p->nAlloc = n;
    }
265
266
267
268
269
270
271
272

273
274
275
276
277
278
279
265
266
267
268
269
270
271

272
273
274
275
276
277
278
279







-
+







    return;
  }
  findNextChars(&c);
  if( c.mallocFailed ){
    sqlite3_result_error_nomem(context);
  }else{
    unsigned char *pRes;
    pRes = sqlite3_malloc( c.nUsed*4 + 1 );
    pRes = sqlite3_malloc64( c.nUsed*4 + 1 );
    if( pRes==0 ){
      sqlite3_result_error_nomem(context);
    }else{
      int i;
      int n = 0;
      for(i=0; i<c.nUsed; i++){
        n += writeUtf8(pRes+n, c.aResult[i]);
293
294
295
296
297
298
299
300


301
302
303


304
305
306
307


308
309
310
311
293
294
295
296
297
298
299

300
301
302
303

304
305
306
307
308

309
310
311
312
313
314







-
+
+


-
+
+



-
+
+




  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg;  /* Unused parameter */
  rc = sqlite3_create_function(db, "next_char", 3, SQLITE_UTF8, 0,
  rc = sqlite3_create_function(db, "next_char", 3,
                               SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
                               nextCharFunc, 0, 0);
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "next_char", 4, SQLITE_UTF8, 0,
    rc = sqlite3_create_function(db, "next_char", 4,
                                 SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
                                 nextCharFunc, 0, 0);
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "next_char", 5, SQLITE_UTF8, 0,
    rc = sqlite3_create_function(db, "next_char", 5,
                                 SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
                                 nextCharFunc, 0, 0);
  }
  return rc;
}

Added ext/misc/noop.c.





































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2020-01-08
**
** 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 SQLite extension implements a noop() function used for testing.
**
** Variants:
**
**    noop(X)           The default.  Deterministic.
**    noop_i(X)         Deterministic and innocuous.
**    noop_do(X)        Deterministic and direct-only.
**    noop_nd(X)        Non-deterministic.
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>

/*
** Implementation of the noop() function.
**
** The function returns its argument, unchanged.
*/
static void noopfunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  assert( argc==1 );
  sqlite3_result_value(context, argv[0]);
}

#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_noop_init(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg;  /* Unused parameter */
  rc = sqlite3_create_function(db, "noop", 1,
                     SQLITE_UTF8 | SQLITE_DETERMINISTIC,
                     0, noopfunc, 0, 0);
  if( rc ) return rc;
  rc = sqlite3_create_function(db, "noop_i", 1,
                     SQLITE_UTF8 | SQLITE_DETERMINISTIC | SQLITE_INNOCUOUS,
                     0, noopfunc, 0, 0);
  if( rc ) return rc;
  rc = sqlite3_create_function(db, "noop_do", 1,
                     SQLITE_UTF8 | SQLITE_DETERMINISTIC | SQLITE_DIRECTONLY,
                     0, noopfunc, 0, 0);
  if( rc ) return rc;
  rc = sqlite3_create_function(db, "noop_nd", 1,
                     SQLITE_UTF8,
                     0, noopfunc, 0, 0);
  return rc;
}

Changes to ext/misc/normalize.c.

282
283
284
285
286
287
288







289
290
291
292
293
294
295
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302







+
+
+
+
+
+
+







#define TK_ILLEGAL  TK_ERROR
#define TK_DOT      TK_PUNCT
#define TK_INTEGER  TK_LITERAL
#define TK_FLOAT    TK_LITERAL
#define TK_VARIABLE TK_LITERAL
#define TK_BLOB     TK_LITERAL

/* Disable nuisence warnings about case fall-through */
#if !defined(deliberate_fall_through) && defined(__GCC__) && __GCC__>=7
# define deliberate_fall_through __attribute__((fallthrough));
#else
# define deliberate_fall_through
#endif

/*
** Return the length (in bytes) of the token that begins at z[0]. 
** Store the token type in *tokenType before returning.
*/
static int sqlite3GetToken(const unsigned char *z, int *tokenType){
  int i, c;
  switch( aiClass[*z] ){  /* Switch on the character-class of the first byte
432
433
434
435
436
437
438

439
440
441
442
443
444
445
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453







+







    case CC_DOT: {
      if( !sqlite3Isdigit(z[1]) ){
        *tokenType = TK_DOT;
        return 1;
      }
      /* If the next character is a digit, this is a floating point
      ** number that begins with ".".  Fall thru into the next case */
      /* no break */ deliberate_fall_through
    }
    case CC_DIGIT: {
      *tokenType = TK_INTEGER;
      if( z[0]=='0' && (z[1]=='x' || z[1]=='X') && sqlite3Isxdigit(z[2]) ){
        for(i=3; sqlite3Isxdigit(z[i]); i++){}
        return i;
      }
524
525
526
527
528
529
530

531
532
533
534
535
536
537
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546







+







          while( z[i] && z[i]!='\'' ){ i++; }
        }
        if( z[i] ) i++;
        return i;
      }
      /* 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_ID: {
      i = 1;
      break;
    }
    default: {
      *tokenType = TK_ILLEGAL;

Changes to ext/misc/percentile.c.

104
105
106
107
108
109
110
111
112


113
114
115
116
117
118
119
104
105
106
107
108
109
110


111
112
113
114
115
116
117
118
119







-
-
+
+







  int eType;
  double y;
  assert( argc==2 );

  /* Requirement 3:  P must be a number between 0 and 100 */
  eType = sqlite3_value_numeric_type(argv[1]);
  rPct = sqlite3_value_double(argv[1]);
  if( (eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT) ||
      ((rPct = sqlite3_value_double(argv[1]))<0.0 || rPct>100.0) ){
  if( (eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT)
   || rPct<0.0 || rPct>100.0 ){
    sqlite3_result_error(pCtx, "2nd argument to percentile() is not "
                         "a number between 0.0 and 100.0", -1);
    return;
  }

  /* Allocate the session context. */
  p = (Percentile*)sqlite3_aggregate_context(pCtx, sizeof(*p));
147
148
149
150
151
152
153
154

155
156
157
158
159
160
161
147
148
149
150
151
152
153

154
155
156
157
158
159
160
161







-
+







    sqlite3_result_error(pCtx, "Inf input to percentile()", -1);
    return;
  }

  /* Allocate and store the Y */
  if( p->nUsed>=p->nAlloc ){
    unsigned n = p->nAlloc*2 + 250;
    double *a = sqlite3_realloc(p->a, sizeof(double)*n);
    double *a = sqlite3_realloc64(p->a, sizeof(double)*n);
    if( a==0 ){
      sqlite3_free(p->a);
      memset(p, 0, sizeof(*p));
      sqlite3_result_error_nomem(pCtx);
      return;
    }
    p->nAlloc = n;
209
210
211
212
213
214
215
216


217
218
219
209
210
211
212
213
214
215

216
217
218
219
220







-
+
+



  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg;  /* Unused parameter */
  rc = sqlite3_create_function(db, "percentile", 2, SQLITE_UTF8, 0,
  rc = sqlite3_create_function(db, "percentile", 2, 
                               SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
                               0, percentStep, percentFinal);
  return rc;
}

Added ext/misc/prefixes.c.

































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2018-04-19
**
** 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 a table-valued function:
**
**      prefixes('abcdefg')
**
** The function has a single (non-HIDDEN) column named prefix that takes
** on all prefixes of the string in its argument, including an empty string
** and the input string itself.  The order of prefixes is from longest
** to shortest.
*/
#if !defined(SQLITE_CORE) || !defined(SQLITE_OMIT_VIRTUALTABLE)
#if !defined(SQLITEINT_H)
#include "sqlite3ext.h"
#endif
SQLITE_EXTENSION_INIT1
#include <string.h>
#include <assert.h>

/* prefixes_vtab is a subclass of sqlite3_vtab which is
** underlying representation of the virtual table
*/
typedef struct prefixes_vtab prefixes_vtab;
struct prefixes_vtab {
  sqlite3_vtab base;  /* Base class - must be first */
  /* No additional fields are necessary */
};

/* prefixes_cursor is a subclass of sqlite3_vtab_cursor which will
** serve as the underlying representation of a cursor that scans
** over rows of the result
*/
typedef struct prefixes_cursor prefixes_cursor;
struct prefixes_cursor {
  sqlite3_vtab_cursor base;  /* Base class - must be first */
  sqlite3_int64 iRowid;      /* The rowid */
  char *zStr;                /* Original string to be prefixed */
  int nStr;                  /* Length of the string in bytes */
};

/*
** The prefixesConnect() method is invoked to create a new
** template virtual table.
**
** Think of this routine as the constructor for prefixes_vtab objects.
**
** All this routine needs to do is:
**
**    (1) Allocate the prefixes_vtab object and initialize all fields.
**
**    (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
**        result set of queries against the virtual table will look like.
*/
static int prefixesConnect(
  sqlite3 *db,
  void *pAux,
  int argc, const char *const*argv,
  sqlite3_vtab **ppVtab,
  char **pzErr
){
  prefixes_vtab *pNew;
  int rc;

  rc = sqlite3_declare_vtab(db,
           "CREATE TABLE prefixes(prefix TEXT, original_string TEXT HIDDEN)"
       );
  if( rc==SQLITE_OK ){
    pNew = sqlite3_malloc( sizeof(*pNew) );
    *ppVtab = (sqlite3_vtab*)pNew;
    if( pNew==0 ) return SQLITE_NOMEM;
    memset(pNew, 0, sizeof(*pNew));
    sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
  }
  return rc;
}

/*
** This method is the destructor for prefixes_vtab objects.
*/
static int prefixesDisconnect(sqlite3_vtab *pVtab){
  prefixes_vtab *p = (prefixes_vtab*)pVtab;
  sqlite3_free(p);
  return SQLITE_OK;
}

/*
** Constructor for a new prefixes_cursor object.
*/
static int prefixesOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
  prefixes_cursor *pCur;
  pCur = sqlite3_malloc( sizeof(*pCur) );
  if( pCur==0 ) return SQLITE_NOMEM;
  memset(pCur, 0, sizeof(*pCur));
  *ppCursor = &pCur->base;
  return SQLITE_OK;
}

/*
** Destructor for a prefixes_cursor.
*/
static int prefixesClose(sqlite3_vtab_cursor *cur){
  prefixes_cursor *pCur = (prefixes_cursor*)cur;
  sqlite3_free(pCur->zStr);
  sqlite3_free(pCur);
  return SQLITE_OK;
}


/*
** Advance a prefixes_cursor to its next row of output.
*/
static int prefixesNext(sqlite3_vtab_cursor *cur){
  prefixes_cursor *pCur = (prefixes_cursor*)cur;
  pCur->iRowid++;
  return SQLITE_OK;
}

/*
** Return values of columns for the row at which the prefixes_cursor
** is currently pointing.
*/
static int prefixesColumn(
  sqlite3_vtab_cursor *cur,   /* The cursor */
  sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
  int i                       /* Which column to return */
){
  prefixes_cursor *pCur = (prefixes_cursor*)cur;
  switch( i ){
    case 0:
      sqlite3_result_text(ctx, pCur->zStr, pCur->nStr - (int)pCur->iRowid,
                          0); 
      break;
    default:
      sqlite3_result_text(ctx, pCur->zStr, pCur->nStr, 0);
      break;
  }
  return SQLITE_OK;
}

/*
** Return the rowid for the current row.  In this implementation, the
** rowid is the same as the output value.
*/
static int prefixesRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
  prefixes_cursor *pCur = (prefixes_cursor*)cur;
  *pRowid = pCur->iRowid;
  return SQLITE_OK;
}

/*
** Return TRUE if the cursor has been moved off of the last
** row of output.
*/
static int prefixesEof(sqlite3_vtab_cursor *cur){
  prefixes_cursor *pCur = (prefixes_cursor*)cur;
  return pCur->iRowid>pCur->nStr;
}

/*
** This method is called to "rewind" the prefixes_cursor object back
** to the first row of output.  This method is always called at least
** once prior to any call to prefixesColumn() or prefixesRowid() or 
** prefixesEof().
*/
static int prefixesFilter(
  sqlite3_vtab_cursor *pVtabCursor, 
  int idxNum, const char *idxStr,
  int argc, sqlite3_value **argv
){
  prefixes_cursor *pCur = (prefixes_cursor *)pVtabCursor;
  sqlite3_free(pCur->zStr);
  if( argc>0 ){
    pCur->zStr = sqlite3_mprintf("%s", sqlite3_value_text(argv[0]));
    pCur->nStr = pCur->zStr ? (int)strlen(pCur->zStr) : 0;
  }else{
    pCur->zStr = 0;
    pCur->nStr = 0;
  }
  pCur->iRowid = 0;
  return SQLITE_OK;
}

/*
** SQLite will invoke this method one or more times while planning a query
** that uses the virtual table.  This routine needs to create
** a query plan for each invocation and compute an estimated cost for that
** plan.
*/
static int prefixesBestIndex(
  sqlite3_vtab *tab,
  sqlite3_index_info *pIdxInfo
){
  /* Search for a usable equality constraint against column 1 
  ** (original_string) and use it if at all possible */
  int i;
  const struct sqlite3_index_constraint *p;

  for(i=0, p=pIdxInfo->aConstraint; i<pIdxInfo->nConstraint; i++, p++){
    if( p->iColumn!=1 ) continue;
    if( p->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
    if( !p->usable ) continue;
    pIdxInfo->aConstraintUsage[i].argvIndex = 1;
    pIdxInfo->aConstraintUsage[i].omit = 1;
    pIdxInfo->estimatedCost = (double)10;
    pIdxInfo->estimatedRows = 10;
    return SQLITE_OK;
  }
  pIdxInfo->estimatedCost = (double)1000000000;
  pIdxInfo->estimatedRows = 1000000000;
  return SQLITE_OK;
}

/*
** This following structure defines all the methods for the 
** virtual table.
*/
static sqlite3_module prefixesModule = {
  /* iVersion    */ 0,
  /* xCreate     */ 0,
  /* xConnect    */ prefixesConnect,
  /* xBestIndex  */ prefixesBestIndex,
  /* xDisconnect */ prefixesDisconnect,
  /* xDestroy    */ 0,
  /* xOpen       */ prefixesOpen,
  /* xClose      */ prefixesClose,
  /* xFilter     */ prefixesFilter,
  /* xNext       */ prefixesNext,
  /* xEof        */ prefixesEof,
  /* xColumn     */ prefixesColumn,
  /* xRowid      */ prefixesRowid,
  /* xUpdate     */ 0,
  /* xBegin      */ 0,
  /* xSync       */ 0,
  /* xCommit     */ 0,
  /* xRollback   */ 0,
  /* xFindMethod */ 0,
  /* xRename     */ 0,
  /* xSavepoint  */ 0,
  /* xRelease    */ 0,
  /* xRollbackTo */ 0,
  /* xShadowName */ 0
};

/*
** This is a copy of the SQLITE_SKIP_UTF8(zIn) macro in sqliteInt.h.
**
** Assuming zIn points to the first byte of a UTF-8 character,
** advance zIn to point to the first byte of the next UTF-8 character.
*/
#define PREFIX_SKIP_UTF8(zIn) {                        \
  if( (*(zIn++))>=0xc0 ){                              \
    while( (*zIn & 0xc0)==0x80 ){ zIn++; }             \
  }                                                    \
}

/*
** Implementation of function prefix_length(). This function accepts two
** strings as arguments and returns the length in characters (not bytes), 
** of the longest prefix shared by the two strings. For example:
**
**   prefix_length('abcdxxx', 'abcyy') == 3
**   prefix_length('abcdxxx', 'bcyyy') == 0
**   prefix_length('abcdxxx', 'ab')    == 2
**   prefix_length('ab',      'abcd')  == 2
**
** This function assumes the input is well-formed utf-8. If it is not,
** it is possible for this function to return -1.
*/
static void prefixLengthFunc(
  sqlite3_context *ctx,
  int nVal,
  sqlite3_value **apVal
){
  int nByte;                      /* Number of bytes to compare */
  int nRet = 0;                   /* Return value */
  const unsigned char *zL = sqlite3_value_text(apVal[0]);
  const unsigned char *zR = sqlite3_value_text(apVal[1]);
  int nL = sqlite3_value_bytes(apVal[0]);
  int nR = sqlite3_value_bytes(apVal[1]);
  int i;

  nByte = (nL > nR ? nL : nR);
  for(i=0; i<nByte; i++){
    if( zL[i]!=zR[i] ) break;
    if( (zL[i] & 0xC0)!=0x80 ) nRet++;
  }

  if( (zL[i] & 0xC0)==0x80 ) nRet--;
  sqlite3_result_int(ctx, nRet);
}

#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_prefixes_init(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  SQLITE_EXTENSION_INIT2(pApi);
  rc = sqlite3_create_module(db, "prefixes", &prefixesModule, 0);
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(
        db, "prefix_length", 2, SQLITE_UTF8, 0, prefixLengthFunc, 0, 0
    );
  }
  return rc;
}
#endif /* !defined(SQLITE_CORE) || !defined(SQLITE_OMIT_VIRTUALTABLE) */

Added ext/misc/qpvtab.c.














































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2022-01-19
**
** 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 a virtual-table that returns information about
** how the query planner called the xBestIndex method.  This virtual table
** is intended for testing and debugging only.
**
** The schema of the virtual table is this:
**
**    CREATE TABLE qpvtab(
**      vn     TEXT,           -- Name of an sqlite3_index_info field
**      ix     INTEGER,        -- Array index or value
**      cn     TEXT,           -- Column name
**      op     INTEGER,        -- operator
**      ux     BOOLEAN,        -- "usable" field
**      rhs    TEXT,           -- sqlite3_vtab_rhs_value()
**
**      a, b, c, d, e,         -- Extra columns to attach constraints to
**
**      flags    INTEGER HIDDEN  -- control flags
**    );
**
** The virtual table returns a description of the sqlite3_index_info object
** that was provided to the (successful) xBestIndex method.  There is one
** row in the result table for each field in the sqlite3_index_info object.
**
** The values of the "a" through "e" columns are one of:
**
**    1.   TEXT - the same as the column name
**    2.   INTEGER - 1 for "a", 2 for "b", and so forth
**
** Option 1 is the default behavior.  2 is use if there is a usable
** constraint on "flags" with an integer right-hand side that where the
** value of the right-hand side has its 0x001 bit set.
**
** All constraints on columns "a" through "e" are marked as "omit".
**
** If there is a usable constraint on "flags" that has a RHS value that
** is an integer and that integer has its 0x02 bit set, then the
** orderByConsumed flag is set.
**
** FLAGS SUMMARY:
**
**   0x001               Columns 'a' through 'e' have INT values
**   0x002               orderByConsumed is set
**   0x004               OFFSET and LIMIT have omit set
**
** COMPILE:
**
**   gcc -Wall -g -shared -fPIC -I. qpvtab.c -o qqvtab.so
**
** EXAMPLE USAGE:
**
**   .load ./qpvtab
**   SELECT rowid, *, flags FROM qpvtab(102)
**    WHERE a=19
**      AND b BETWEEN 4.5 and 'hello'
**      AND c<>x'aabbcc'
**    ORDER BY d, e DESC;
*/
#if !defined(SQLITEINT_H)
#include "sqlite3ext.h"
#endif
SQLITE_EXTENSION_INIT1
#include <string.h>
#include <assert.h>
#include <stdlib.h>

#if !defined(SQLITE_OMIT_VIRTUALTABLE)

/* qpvtab_vtab is a subclass of sqlite3_vtab which is
** underlying representation of the virtual table
*/
typedef struct qpvtab_vtab qpvtab_vtab;
struct qpvtab_vtab {
  sqlite3_vtab base;  /* Base class - must be first */
};

/* qpvtab_cursor is a subclass of sqlite3_vtab_cursor which will
** serve as the underlying representation of a cursor that scans
** over rows of the result
*/
typedef struct qpvtab_cursor qpvtab_cursor;
struct qpvtab_cursor {
  sqlite3_vtab_cursor base;  /* Base class - must be first */
  sqlite3_int64 iRowid;      /* The rowid */
  const char *zData;         /* Data to return */
  int nData;                 /* Number of bytes of data */
  int flags;                 /* Flags value */
};

/*
** Names of columns
*/
static const char *azColname[] = {
  "vn",
  "ix",
  "cn",
  "op",
  "ux",
  "rhs",
  "a", "b", "c", "d", "e",
  "flags",
  ""
};

/*
** The qpvtabConnect() method is invoked to create a new
** qpvtab virtual table.
*/
static int qpvtabConnect(
  sqlite3 *db,
  void *pAux,
  int argc, const char *const*argv,
  sqlite3_vtab **ppVtab,
  char **pzErr
){
  qpvtab_vtab *pNew;
  int rc;

  rc = sqlite3_declare_vtab(db,
         "CREATE TABLE x("
         " vn TEXT,"
         " ix INT,"
         " cn TEXT,"
         " op INT,"
         " ux BOOLEAN,"
         " rhs TEXT,"
         " a, b, c, d, e,"
         " flags INT HIDDEN)"
       );
#define QPVTAB_VN      0
#define QPVTAB_IX      1
#define QPVTAB_CN      2
#define QPVTAB_OP      3
#define QPVTAB_UX      4
#define QPVTAB_RHS     5
#define QPVTAB_A       6
#define QPVTAB_B       7
#define QPVTAB_C       8
#define QPVTAB_D       9
#define QPVTAB_E      10
#define QPVTAB_FLAGS  11
#define QPVTAB_NONE   12
  if( rc==SQLITE_OK ){
    pNew = sqlite3_malloc( sizeof(*pNew) );
    *ppVtab = (sqlite3_vtab*)pNew;
    if( pNew==0 ) return SQLITE_NOMEM;
    memset(pNew, 0, sizeof(*pNew));
  }
  return rc;
}

/*
** This method is the destructor for qpvtab_vtab objects.
*/
static int qpvtabDisconnect(sqlite3_vtab *pVtab){
  qpvtab_vtab *p = (qpvtab_vtab*)pVtab;
  sqlite3_free(p);
  return SQLITE_OK;
}

/*
** Constructor for a new qpvtab_cursor object.
*/
static int qpvtabOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
  qpvtab_cursor *pCur;
  pCur = sqlite3_malloc( sizeof(*pCur) );
  if( pCur==0 ) return SQLITE_NOMEM;
  memset(pCur, 0, sizeof(*pCur));
  *ppCursor = &pCur->base;
  return SQLITE_OK;
}

/*
** Destructor for a qpvtab_cursor.
*/
static int qpvtabClose(sqlite3_vtab_cursor *cur){
  qpvtab_cursor *pCur = (qpvtab_cursor*)cur;
  sqlite3_free(pCur);
  return SQLITE_OK;
}


/*
** Advance a qpvtab_cursor to its next row of output.
*/
static int qpvtabNext(sqlite3_vtab_cursor *cur){
  qpvtab_cursor *pCur = (qpvtab_cursor*)cur;
  if( pCur->iRowid<pCur->nData ){
    const char *z = &pCur->zData[pCur->iRowid];
    const char *zEnd = strchr(z, '\n');
    if( zEnd ) zEnd++;
    pCur->iRowid = (int)(zEnd - pCur->zData);
  }
  return SQLITE_OK;
}

/*
** Return values of columns for the row at which the qpvtab_cursor
** is currently pointing.
*/
static int qpvtabColumn(
  sqlite3_vtab_cursor *cur,   /* The cursor */
  sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
  int i                       /* Which column to return */
){
  qpvtab_cursor *pCur = (qpvtab_cursor*)cur;
  if( i>=QPVTAB_VN && i<=QPVTAB_RHS && pCur->iRowid<pCur->nData ){
    const char *z = &pCur->zData[pCur->iRowid];
    const char *zEnd;
    int j;
    j = QPVTAB_VN;
    while(1){
      zEnd = strchr(z, j==QPVTAB_RHS ? '\n' : ',');
      if( j==i || zEnd==0 ) break;
      z = zEnd+1;
      j++;
    }
    if( zEnd==z ){
      sqlite3_result_null(ctx);
    }else if( i==QPVTAB_IX || i==QPVTAB_OP || i==QPVTAB_UX ){
      sqlite3_result_int(ctx, atoi(z));
    }else{
      sqlite3_result_text64(ctx, z, zEnd-z, SQLITE_TRANSIENT, SQLITE_UTF8);
    }
  }else if( i>=QPVTAB_A && i<=QPVTAB_E ){
    if( pCur->flags & 0x001 ){
      sqlite3_result_int(ctx, i-QPVTAB_A+1);
    }else{
      char x = 'a'+i-QPVTAB_A;
      sqlite3_result_text64(ctx, &x, 1, SQLITE_TRANSIENT, SQLITE_UTF8);
    }
  }else if( i==QPVTAB_FLAGS ){
    sqlite3_result_int(ctx, pCur->flags);
  }
  return SQLITE_OK;
}

/*
** Return the rowid for the current row.  In this implementation, the
** rowid is the same as the output value.
*/
static int qpvtabRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
  qpvtab_cursor *pCur = (qpvtab_cursor*)cur;
  *pRowid = pCur->iRowid;
  return SQLITE_OK;
}

/*
** Return TRUE if the cursor has been moved off of the last
** row of output.
*/
static int qpvtabEof(sqlite3_vtab_cursor *cur){
  qpvtab_cursor *pCur = (qpvtab_cursor*)cur;
  return pCur->iRowid>=pCur->nData;
}

/*
** This method is called to "rewind" the qpvtab_cursor object back
** to the first row of output.  This method is always called at least
** once prior to any call to qpvtabColumn() or qpvtabRowid() or 
** qpvtabEof().
*/
static int qpvtabFilter(
  sqlite3_vtab_cursor *pVtabCursor, 
  int idxNum, const char *idxStr,
  int argc, sqlite3_value **argv
){
  qpvtab_cursor *pCur = (qpvtab_cursor *)pVtabCursor;
  pCur->iRowid = 0;
  pCur->zData = idxStr;
  pCur->nData = (int)strlen(idxStr);
  pCur->flags = idxNum;
  return SQLITE_OK;
}

/*
** Append the text of a value to pStr
*/
static void qpvtabStrAppendValue(
  sqlite3_str *pStr,
  sqlite3_value *pVal
){
  switch( sqlite3_value_type(pVal) ){
    case SQLITE_NULL:
      sqlite3_str_appendf(pStr, "NULL");
      break;
    case SQLITE_INTEGER:
      sqlite3_str_appendf(pStr, "%lld", sqlite3_value_int64(pVal));
      break;
    case SQLITE_FLOAT:
      sqlite3_str_appendf(pStr, "%!f", sqlite3_value_double(pVal));
      break;
    case SQLITE_TEXT: {
      int i;
      const char *a = (const char*)sqlite3_value_text(pVal);
      int n = sqlite3_value_bytes(pVal);
      sqlite3_str_append(pStr, "'", 1);
      for(i=0; i<n; i++){
        char c = a[i];
        if( c=='\n' ) c = ' ';
        sqlite3_str_append(pStr, &c, 1);
        if( c=='\'' ) sqlite3_str_append(pStr, &c, 1);
      }
      sqlite3_str_append(pStr, "'", 1);
      break;
    }
    case SQLITE_BLOB: {
      int i;
      const unsigned char *a = sqlite3_value_blob(pVal);
      int n = sqlite3_value_bytes(pVal);
      sqlite3_str_append(pStr, "x'", 2);
      for(i=0; i<n; i++){
        sqlite3_str_appendf(pStr, "%02x", a[i]);
      }
      sqlite3_str_append(pStr, "'", 1);
      break;
    }
  }
}

/*
** SQLite will invoke this method one or more times while planning a query
** that uses the virtual table.  This routine needs to create
** a query plan for each invocation and compute an estimated cost for that
** plan.
*/
static int qpvtabBestIndex(
  sqlite3_vtab *tab,
  sqlite3_index_info *pIdxInfo
){
  sqlite3_str *pStr = sqlite3_str_new(0);
  int i, k = 0;
  int rc;
  sqlite3_str_appendf(pStr, "nConstraint,%d,,,,\n", pIdxInfo->nConstraint);
  for(i=0; i<pIdxInfo->nConstraint; i++){
    sqlite3_value *pVal;
    int iCol = pIdxInfo->aConstraint[i].iColumn;
    int op = pIdxInfo->aConstraint[i].op;
    if( iCol==QPVTAB_FLAGS &&  pIdxInfo->aConstraint[i].usable ){
      pVal = 0;
      rc = sqlite3_vtab_rhs_value(pIdxInfo, i, &pVal);
      assert( rc==SQLITE_OK || pVal==0 );
      if( pVal ){
        pIdxInfo->idxNum = sqlite3_value_int(pVal);
        if( pIdxInfo->idxNum & 0x002 ) pIdxInfo->orderByConsumed = 1;
      }
    }
    if( op==SQLITE_INDEX_CONSTRAINT_LIMIT
     || op==SQLITE_INDEX_CONSTRAINT_OFFSET
    ){
      iCol = QPVTAB_NONE;
    }
    sqlite3_str_appendf(pStr,"aConstraint,%d,%s,%d,%d,",
       i,
       azColname[iCol],
       op,
       pIdxInfo->aConstraint[i].usable);
    pVal = 0;
    rc = sqlite3_vtab_rhs_value(pIdxInfo, i, &pVal);
    assert( rc==SQLITE_OK || pVal==0 );
    if( pVal ){
      qpvtabStrAppendValue(pStr, pVal);
    }
    sqlite3_str_append(pStr, "\n", 1);
  }
  for(i=0; i<pIdxInfo->nConstraint; i++){
    int iCol = pIdxInfo->aConstraint[i].iColumn;
    int op = pIdxInfo->aConstraint[i].op;
    if( op==SQLITE_INDEX_CONSTRAINT_LIMIT
     || op==SQLITE_INDEX_CONSTRAINT_OFFSET
    ){
      iCol = QPVTAB_NONE;
    }
    if( iCol>=QPVTAB_A && pIdxInfo->aConstraint[i].usable ){
      pIdxInfo->aConstraintUsage[i].argvIndex = ++k;
      if( iCol<=QPVTAB_FLAGS || (pIdxInfo->idxNum & 0x004)!=0 ){
        pIdxInfo->aConstraintUsage[i].omit = 1;
      }
    }
  }
  sqlite3_str_appendf(pStr, "nOrderBy,%d,,,,\n", pIdxInfo->nOrderBy);
  for(i=0; i<pIdxInfo->nOrderBy; i++){
    int iCol = pIdxInfo->aOrderBy[i].iColumn;
    sqlite3_str_appendf(pStr, "aOrderBy,%d,%s,%d,,\n",i,
      iCol>=0 ? azColname[iCol] : "rowid",
      pIdxInfo->aOrderBy[i].desc
    );
  }
  sqlite3_str_appendf(pStr, "sqlite3_vtab_distinct,%d,,,,\n", 
                      sqlite3_vtab_distinct(pIdxInfo));
  sqlite3_str_appendf(pStr, "idxFlags,%d,,,,\n", pIdxInfo->idxFlags);
  sqlite3_str_appendf(pStr, "colUsed,%d,,,,\n", (int)pIdxInfo->colUsed);
  pIdxInfo->estimatedCost = (double)10;
  pIdxInfo->estimatedRows = 10;
  sqlite3_str_appendf(pStr, "idxNum,%d,,,,\n", pIdxInfo->idxNum);
  sqlite3_str_appendf(pStr, "orderByConsumed,%d,,,,\n",
                      pIdxInfo->orderByConsumed);
  pIdxInfo->idxStr = sqlite3_str_finish(pStr);
  pIdxInfo->needToFreeIdxStr = 1;
  return SQLITE_OK;
}

/*
** This following structure defines all the methods for the 
** virtual table.
*/
static sqlite3_module qpvtabModule = {
  /* iVersion    */ 0,
  /* xCreate     */ 0,
  /* xConnect    */ qpvtabConnect,
  /* xBestIndex  */ qpvtabBestIndex,
  /* xDisconnect */ qpvtabDisconnect,
  /* xDestroy    */ 0,
  /* xOpen       */ qpvtabOpen,
  /* xClose      */ qpvtabClose,
  /* xFilter     */ qpvtabFilter,
  /* xNext       */ qpvtabNext,
  /* xEof        */ qpvtabEof,
  /* xColumn     */ qpvtabColumn,
  /* xRowid      */ qpvtabRowid,
  /* xUpdate     */ 0,
  /* xBegin      */ 0,
  /* xSync       */ 0,
  /* xCommit     */ 0,
  /* xRollback   */ 0,
  /* xFindMethod */ 0,
  /* xRename     */ 0,
  /* xSavepoint  */ 0,
  /* xRelease    */ 0,
  /* xRollbackTo */ 0,
  /* xShadowName */ 0
};
#endif /* SQLITE_OMIT_VIRTUALTABLE */


#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_qpvtab_init(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  SQLITE_EXTENSION_INIT2(pApi);
#ifndef SQLITE_OMIT_VIRTUALTABLE
  rc = sqlite3_create_module(db, "qpvtab", &qpvtabModule, 0);
#endif
  return rc;
}

Changes to ext/misc/regexp.c.

68
69
70
71
72
73
74

75
76
77
78
79
80
81
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82







+







*/
#define re_match   sqlite3re_match
#define re_compile sqlite3re_compile
#define re_free    sqlite3re_free

/* The end-of-input character */
#define RE_EOF            0    /* End of input */
#define RE_START  0xfffffff    /* Start of input - larger than an UTF-8 */

/* The NFA is implemented as sequence of opcodes taken from the following
** set.  Each opcode has a single integer argument.
*/
#define RE_OP_MATCH       1    /* Match the one character in the argument */
#define RE_OP_ANY         2    /* Match any one character.  (Implements ".") */
#define RE_OP_ANYSTAR     3    /* Special optimized version of .* */
89
90
91
92
93
94
95



























96
97
98
99
100
101
102
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







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







#define RE_OP_WORD       11    /* Perl word character [A-Za-z0-9_] */
#define RE_OP_NOTWORD    12    /* Not a perl word character */
#define RE_OP_DIGIT      13    /* digit:  [0-9] */
#define RE_OP_NOTDIGIT   14    /* Not a digit */
#define RE_OP_SPACE      15    /* space:  [ \t\n\r\v\f] */
#define RE_OP_NOTSPACE   16    /* Not a digit */
#define RE_OP_BOUNDARY   17    /* Boundary between word and non-word */
#define RE_OP_ATSTART    18    /* Currently at the start of the string */

#if defined(SQLITE_DEBUG)
/* Opcode names used for symbolic debugging */
static const char *ReOpName[] = {
  "EOF",
  "MATCH",
  "ANY",
  "ANYSTAR",
  "FORK",
  "GOTO",
  "ACCEPT",
  "CC_INC",
  "CC_EXC",
  "CC_VALUE",
  "CC_RANGE",
  "WORD",
  "NOTWORD",
  "DIGIT",
  "NOTDIGIT",
  "SPACE",
  "NOTSPACE",
  "BOUNDARY",
  "ATSTART",
};
#endif /* SQLITE_DEBUG */


/* Each opcode is a "state" in the NFA */
typedef unsigned short ReStateNumber;

/* Because this is an NFA and not a DFA, multiple states can be active at
** once.  An instance of the following object records all active states in
** the NFA.  The implementation is optimized for the common case where the
123
124
125
126
127
128
129
130

131
132
133
134
135
136
137
151
152
153
154
155
156
157

158
159
160
161
162
163
164
165







-
+







struct ReCompiled {
  ReInput sIn;                /* Regular expression text */
  const char *zErr;           /* Error message to return */
  char *aOp;                  /* Operators for the virtual machine */
  int *aArg;                  /* Arguments to each operator */
  unsigned (*xNextChar)(ReInput*);  /* Next character function */
  unsigned char zInit[12];    /* Initial text to match */
  int nInit;                  /* Number of characters in zInit */
  int nInit;                  /* Number of bytes in zInit */
  unsigned nState;            /* Number of entries in aOp[] and aArg[] */
  unsigned nAlloc;            /* Slots allocated for aOp[] and aArg[] */
};

/* Add a state to the given state set if it is not already there */
static void re_add_state(ReStateSet *pSet, int newState){
  unsigned i;
152
153
154
155
156
157
158
159
160


161
162
163
164
165
166
167
180
181
182
183
184
185
186


187
188
189
190
191
192
193
194
195







-
-
+
+







    if( (c&0xe0)==0xc0 && p->i<p->mx && (p->z[p->i]&0xc0)==0x80 ){
      c = (c&0x1f)<<6 | (p->z[p->i++]&0x3f);
      if( c<0x80 ) c = 0xfffd;
    }else if( (c&0xf0)==0xe0 && p->i+1<p->mx && (p->z[p->i]&0xc0)==0x80
           && (p->z[p->i+1]&0xc0)==0x80 ){
      c = (c&0x0f)<<12 | ((p->z[p->i]&0x3f)<<6) | (p->z[p->i+1]&0x3f);
      p->i += 2;
      if( c<=0x3ff || (c>=0xd800 && c<=0xdfff) ) c = 0xfffd;
    }else if( (c&0xf8)==0xf0 && p->i+3<p->mx && (p->z[p->i]&0xc0)==0x80
      if( c<=0x7ff || (c>=0xd800 && c<=0xdfff) ) c = 0xfffd;
    }else if( (c&0xf8)==0xf0 && p->i+2<p->mx && (p->z[p->i]&0xc0)==0x80
           && (p->z[p->i+1]&0xc0)==0x80 && (p->z[p->i+2]&0xc0)==0x80 ){
      c = (c&0x07)<<18 | ((p->z[p->i]&0x3f)<<12) | ((p->z[p->i+1]&0x3f)<<6)
                       | (p->z[p->i+2]&0x3f);
      p->i += 3;
      if( c<=0xffff || c>0x10ffff ) c = 0xfffd;
    }else{
      c = 0xfffd;
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
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







-
+


















+






-
+





















+
+
+
+

-
+







-
+







-
+







-
+







*/
static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
  ReStateSet aStateSet[2], *pThis, *pNext;
  ReStateNumber aSpace[100];
  ReStateNumber *pToFree;
  unsigned int i = 0;
  unsigned int iSwap = 0;
  int c = RE_EOF+1;
  int c = RE_START;
  int cPrev = 0;
  int rc = 0;
  ReInput in;

  in.z = zIn;
  in.i = 0;
  in.mx = nIn>=0 ? nIn : (int)strlen((char const*)zIn);

  /* Look for the initial prefix match, if there is one. */
  if( pRe->nInit ){
    unsigned char x = pRe->zInit[0];
    while( in.i+pRe->nInit<=in.mx 
     && (zIn[in.i]!=x ||
         strncmp((const char*)zIn+in.i, (const char*)pRe->zInit, pRe->nInit)!=0)
    ){
      in.i++;
    }
    if( in.i+pRe->nInit>in.mx ) return 0;
    c = RE_START-1;
  }

  if( pRe->nState<=(sizeof(aSpace)/(sizeof(aSpace[0])*2)) ){
    pToFree = 0;
    aStateSet[0].aState = aSpace;
  }else{
    pToFree = sqlite3_malloc( sizeof(ReStateNumber)*2*pRe->nState );
    pToFree = sqlite3_malloc64( sizeof(ReStateNumber)*2*pRe->nState );
    if( pToFree==0 ) return -1;
    aStateSet[0].aState = pToFree;
  }
  aStateSet[1].aState = &aStateSet[0].aState[pRe->nState];
  pNext = &aStateSet[1];
  pNext->nState = 0;
  re_add_state(pNext, 0);
  while( c!=RE_EOF && pNext->nState>0 ){
    cPrev = c;
    c = pRe->xNextChar(&in);
    pThis = pNext;
    pNext = &aStateSet[iSwap];
    iSwap = 1 - iSwap;
    pNext->nState = 0;
    for(i=0; i<pThis->nState; i++){
      int x = pThis->aState[i];
      switch( pRe->aOp[x] ){
        case RE_OP_MATCH: {
          if( pRe->aArg[x]==c ) re_add_state(pNext, x+1);
          break;
        }
        case RE_OP_ATSTART: {
          if( cPrev==RE_START ) re_add_state(pThis, x+1);
          break;
        }
        case RE_OP_ANY: {
          re_add_state(pNext, x+1);
          if( c!=0 ) re_add_state(pNext, x+1);
          break;
        }
        case RE_OP_WORD: {
          if( re_word_char(c) ) re_add_state(pNext, x+1);
          break;
        }
        case RE_OP_NOTWORD: {
          if( !re_word_char(c) ) re_add_state(pNext, x+1);
          if( !re_word_char(c) && c!=0 ) re_add_state(pNext, x+1);
          break;
        }
        case RE_OP_DIGIT: {
          if( re_digit_char(c) ) re_add_state(pNext, x+1);
          break;
        }
        case RE_OP_NOTDIGIT: {
          if( !re_digit_char(c) ) re_add_state(pNext, x+1);
          if( !re_digit_char(c) && c!=0 ) re_add_state(pNext, x+1);
          break;
        }
        case RE_OP_SPACE: {
          if( re_space_char(c) ) re_add_state(pNext, x+1);
          break;
        }
        case RE_OP_NOTSPACE: {
          if( !re_space_char(c) ) re_add_state(pNext, x+1);
          if( !re_space_char(c) && c!=0 ) re_add_state(pNext, x+1);
          break;
        }
        case RE_OP_BOUNDARY: {
          if( re_word_char(c)!=re_word_char(cPrev) ) re_add_state(pThis, x+1);
          break;
        }
        case RE_OP_ANYSTAR: {
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
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







-
-
+
+
+
+
+




















-
+





+
+
-
+











-
+


-
+







          re_add_state(pThis, x+pRe->aArg[x]);
          break;
        }
        case RE_OP_ACCEPT: {
          rc = 1;
          goto re_match_end;
        }
        case RE_OP_CC_INC:
        case RE_OP_CC_EXC: {
        case RE_OP_CC_EXC: {
          if( c==0 ) break;
          /* fall-through */ goto re_op_cc_inc;
        }
        case RE_OP_CC_INC: re_op_cc_inc: {
          int j = 1;
          int n = pRe->aArg[x];
          int hit = 0;
          for(j=1; j>0 && j<n; j++){
            if( pRe->aOp[x+j]==RE_OP_CC_VALUE ){
              if( pRe->aArg[x+j]==c ){
                hit = 1;
                j = -1;
              }
            }else{
              if( pRe->aArg[x+j]<=c && pRe->aArg[x+j+1]>=c ){
                hit = 1;
                j = -1;
              }else{
                j++;
              }
            }
          }
          if( pRe->aOp[x]==RE_OP_CC_EXC ) hit = !hit;
          if( hit ) re_add_state(pNext, x+n);
          break;            
          break;
        }
      }
    }
  }
  for(i=0; i<pNext->nState; i++){
    int x = pNext->aState[i];
    while( pRe->aOp[x]==RE_OP_GOTO ) x += pRe->aArg[x];
    if( pRe->aOp[pNext->aState[i]]==RE_OP_ACCEPT ){ rc = 1; break; }
    if( pRe->aOp[x]==RE_OP_ACCEPT ){ rc = 1; break; }
  }
re_match_end:
  sqlite3_free(pToFree);
  return rc;
}

/* Resize the opcode and argument arrays for an RE under construction.
*/
static int re_resize(ReCompiled *p, int N){
  char *aOp;
  int *aArg;
  aOp = sqlite3_realloc(p->aOp, N*sizeof(p->aOp[0]));
  aOp = sqlite3_realloc64(p->aOp, N*sizeof(p->aOp[0]));
  if( aOp==0 ) return 1;
  p->aOp = aOp;
  aArg = sqlite3_realloc(p->aArg, N*sizeof(p->aArg[0]));
  aArg = sqlite3_realloc64(p->aArg, N*sizeof(p->aArg[0]));
  if( aArg==0 ) return 1;
  p->aArg = aArg;
  p->nAlloc = N;
  return 0;
}

/* Insert a new opcode and argument into an RE under construction.  The
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
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







-















-
+



















+
+
+
+
+
+
+
+



















+







  int iStart;
  unsigned c;
  const char *zErr;
  while( (c = p->xNextChar(&p->sIn))!=0 ){
    iStart = p->nState;
    switch( c ){
      case '|':
      case '$': 
      case ')': {
        p->sIn.i--;
        return 0;
      }
      case '(': {
        zErr = re_subcompile_re(p);
        if( zErr ) return zErr;
        if( rePeek(p)!=')' ) return "unmatched '('";
        p->sIn.i++;
        break;
      }
      case '.': {
        if( rePeek(p)=='*' ){
          re_append(p, RE_OP_ANYSTAR, 0);
          p->sIn.i++;
        }else{ 
        }else{
          re_append(p, RE_OP_ANY, 0);
        }
        break;
      }
      case '*': {
        if( iPrev<0 ) return "'*' without operand";
        re_insert(p, iPrev, RE_OP_GOTO, p->nState - iPrev + 1);
        re_append(p, RE_OP_FORK, iPrev - p->nState + 1);
        break;
      }
      case '+': {
        if( iPrev<0 ) return "'+' without operand";
        re_append(p, RE_OP_FORK, iPrev - p->nState);
        break;
      }
      case '?': {
        if( iPrev<0 ) return "'?' without operand";
        re_insert(p, iPrev, RE_OP_FORK, p->nState - iPrev+1);
        break;
      }
      case '$': {
        re_append(p, RE_OP_MATCH, RE_EOF);
        break;
      }
      case '^': {
        re_append(p, RE_OP_ATSTART, 0);
        break;
      }
      case '{': {
        int m = 0, n = 0;
        int sz, j;
        if( iPrev<0 ) return "'{m,n}' without operand";
        while( (c=rePeek(p))>='0' && c<='9' ){ m = m*10 + c - '0'; p->sIn.i++; }
        n = m;
        if( c==',' ){
          p->sIn.i++;
          n = 0;
          while( (c=rePeek(p))>='0' && c<='9' ){ n = n*10 + c-'0'; p->sIn.i++; }
        }
        if( c!='}' ) return "unmatched '{'";
        if( n>0 && n<m ) return "n less than m in '{m,n}'";
        p->sIn.i++;
        sz = p->nState - iPrev;
        if( m==0 ){
          if( n==0 ) return "both m and n are zero in '{m,n}'";
          re_insert(p, iPrev, RE_OP_FORK, sz+1);
          iPrev++;
          n--;
        }else{
          for(j=1; j<m; j++) re_copy(p, iPrev, sz);
        }
        for(j=m; j<n; j++){
          re_append(p, RE_OP_FORK, sz+1);
          re_copy(p, iPrev, sz);
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
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







-
+













-
+







  return 0;
}

/* Free and reclaim all the memory used by a previously compiled
** regular expression.  Applications should invoke this routine once
** for every call to re_compile() to avoid memory leaks.
*/
void re_free(ReCompiled *pRe){
static void re_free(ReCompiled *pRe){
  if( pRe ){
    sqlite3_free(pRe->aOp);
    sqlite3_free(pRe->aArg);
    sqlite3_free(pRe);
  }
}

/*
** Compile a textual regular expression in zIn[] into a compiled regular
** expression suitable for us by re_match() and return a pointer to the
** compiled regular expression in *ppRe.  Return NULL on success or an
** error message if something goes wrong.
*/
const char *re_compile(ReCompiled **ppRe, const char *zIn, int noCase){
static const char *re_compile(ReCompiled **ppRe, const char *zIn, int noCase){
  ReCompiled *pRe;
  const char *zErr;
  int i, j;

  *ppRe = 0;
  pRe = sqlite3_malloc( sizeof(*pRe) );
  if( pRe==0 ){
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
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







-
-
-
-
-
+












-
+


-
-
+
+

-
+

-
+



-
+







  pRe->sIn.i = 0;
  pRe->sIn.mx = (int)strlen(zIn);
  zErr = re_subcompile_re(pRe);
  if( zErr ){
    re_free(pRe);
    return zErr;
  }
  if( rePeek(pRe)=='$' && pRe->sIn.i+1>=pRe->sIn.mx ){
    re_append(pRe, RE_OP_MATCH, RE_EOF);
    re_append(pRe, RE_OP_ACCEPT, 0);
    *ppRe = pRe;
  }else if( pRe->sIn.i>=pRe->sIn.mx ){
  if( pRe->sIn.i>=pRe->sIn.mx ){
    re_append(pRe, RE_OP_ACCEPT, 0);
    *ppRe = pRe;
  }else{
    re_free(pRe);
    return "unrecognized character";
  }

  /* The following is a performance optimization.  If the regex begins with
  ** ".*" (if the input regex lacks an initial "^") and afterwards there are
  ** one or more matching characters, enter those matching characters into
  ** zInit[].  The re_match() routine can then search ahead in the input 
  ** string looking for the initial match without having to run the whole
  ** regex engine over the string.  Do not worry able trying to match
  ** regex engine over the string.  Do not worry about trying to match
  ** unicode characters beyond plane 0 - those are very rare and this is
  ** just an optimization. */
  if( pRe->aOp[0]==RE_OP_ANYSTAR ){
    for(j=0, i=1; j<sizeof(pRe->zInit)-2 && pRe->aOp[i]==RE_OP_MATCH; i++){
  if( pRe->aOp[0]==RE_OP_ANYSTAR && !noCase ){
    for(j=0, i=1; j<(int)sizeof(pRe->zInit)-2 && pRe->aOp[i]==RE_OP_MATCH; i++){
      unsigned x = pRe->aArg[i];
      if( x<=127 ){
      if( x<=0x7f ){
        pRe->zInit[j++] = (unsigned char)x;
      }else if( x<=0xfff ){
      }else if( x<=0x7ff ){
        pRe->zInit[j++] = (unsigned char)(0xc0 | (x>>6));
        pRe->zInit[j++] = 0x80 | (x&0x3f);
      }else if( x<=0xffff ){
        pRe->zInit[j++] = (unsigned char)(0xd0 | (x>>12));
        pRe->zInit[j++] = (unsigned char)(0xe0 | (x>>12));
        pRe->zInit[j++] = 0x80 | ((x>>6)&0x3f);
        pRe->zInit[j++] = 0x80 | (x&0x3f);
      }else{
        break;
      }
    }
    if( j>0 && pRe->zInit[j-1]==0 ) j--;
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
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







-
-
+
+








+




-
+



















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















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


** pattern and the second argument is the string.  So, the SQL statements:
**
**       A REGEXP B
**
** is implemented as regexp(B,A).
*/
static void re_sql_func(
  sqlite3_context *context, 
  int argc, 
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  ReCompiled *pRe;          /* Compiled regular expression */
  const char *zPattern;     /* The regular expression */
  const unsigned char *zStr;/* String being searched */
  const char *zErr;         /* Compile error message */
  int setAux = 0;           /* True to invoke sqlite3_set_auxdata() */

  (void)argc;  /* Unused */
  pRe = sqlite3_get_auxdata(context, 0);
  if( pRe==0 ){
    zPattern = (const char*)sqlite3_value_text(argv[0]);
    if( zPattern==0 ) return;
    zErr = re_compile(&pRe, zPattern, 0);
    zErr = re_compile(&pRe, zPattern, sqlite3_user_data(context)!=0);
    if( zErr ){
      re_free(pRe);
      sqlite3_result_error(context, zErr, -1);
      return;
    }
    if( pRe==0 ){
      sqlite3_result_error_nomem(context);
      return;
    }
    setAux = 1;
  }
  zStr = (const unsigned char*)sqlite3_value_text(argv[1]);
  if( zStr!=0 ){
    sqlite3_result_int(context, re_match(pRe, zStr, -1));
  }
  if( setAux ){
    sqlite3_set_auxdata(context, 0, pRe, (void(*)(void*))re_free);
  }
}

#if defined(SQLITE_DEBUG)
/*
** This function is used for testing and debugging only.  It is only available
** if the SQLITE_DEBUG compile-time option is used.
**
** Compile a regular expression and then convert the compiled expression into
** text and return that text.
*/
static void re_bytecode_func(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const char *zPattern;
  const char *zErr;
  ReCompiled *pRe;
  sqlite3_str *pStr;
  int i;
  int n;
  char *z;
  (void)argc;

  zPattern = (const char*)sqlite3_value_text(argv[0]);
  if( zPattern==0 ) return;
  zErr = re_compile(&pRe, zPattern, sqlite3_user_data(context)!=0);
  if( zErr ){
    re_free(pRe);
    sqlite3_result_error(context, zErr, -1);
    return;
  }
  if( pRe==0 ){
    sqlite3_result_error_nomem(context);
    return;
  }
  pStr = sqlite3_str_new(0);
  if( pStr==0 ) goto re_bytecode_func_err;
  if( pRe->nInit>0 ){
    sqlite3_str_appendf(pStr, "INIT     ");
    for(i=0; i<pRe->nInit; i++){
      sqlite3_str_appendf(pStr, "%02x", pRe->zInit[i]);
    }
    sqlite3_str_appendf(pStr, "\n");
  }
  for(i=0; (unsigned)i<pRe->nState; i++){
    sqlite3_str_appendf(pStr, "%-8s %4d\n",
         ReOpName[(unsigned char)pRe->aOp[i]], pRe->aArg[i]);
  }
  n = sqlite3_str_length(pStr);
  z = sqlite3_str_finish(pStr);
  if( n==0 ){
    sqlite3_free(z);
  }else{
    sqlite3_result_text(context, z, n-1, sqlite3_free);
  }

re_bytecode_func_err:
  re_free(pRe);
}

#endif /* SQLITE_DEBUG */


/*
** Invoke this routine to register the regexp() function with the
** SQLite database connection.
*/
#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_regexp_init(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg;  /* Unused */
  rc = sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8, 0,
                                 re_sql_func, 0, 0);
  rc = sqlite3_create_function(db, "regexp", 2, 
                            SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
                            0, re_sql_func, 0, 0);
  if( rc==SQLITE_OK ){
    /* The regexpi(PATTERN,STRING) function is a case-insensitive version
    ** of regexp(PATTERN,STRING). */
    rc = sqlite3_create_function(db, "regexpi", 2,
                            SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
                            (void*)db, re_sql_func, 0, 0);
#if defined(SQLITE_DEBUG)
    if( rc==SQLITE_OK ){
      rc = sqlite3_create_function(db, "regexp_bytecode", 1,
                            SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
                            0, re_bytecode_func, 0, 0);
    }
#endif /* SQLITE_DEBUG */
  }
  return rc;
}

Changes to ext/misc/rot13.c.

101
102
103
104
105
106
107
108
109



110
111
112
113
114
101
102
103
104
105
106
107


108
109
110
111
112
113
114
115







-
-
+
+
+





  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg;  /* Unused parameter */
  rc = sqlite3_create_function(db, "rot13", 1, SQLITE_UTF8, 0,
                               rot13func, 0, 0);
  rc = sqlite3_create_function(db, "rot13", 1,
                   SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
                   0, rot13func, 0, 0);
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_collation(db, "rot13", SQLITE_UTF8, 0, rot13CollFunc);
  }
  return rc;
}

Changes to ext/misc/scrub.c.

162
163
164
165
166
167
168
169

170
171
172
173
174
175
176
162
163
164
165
166
167
168

169
170
171
172
173
174
175
176







-
+







                 SQLITE_OPEN_READWRITE |
                 SQLITE_OPEN_URI | SQLITE_OPEN_PRIVATECACHE, 0);
  if( p->rcErr ){
    scrubBackupErr(p, "cannot open source database: %s",
                      sqlite3_errmsg(p->dbSrc));
    return;
  }
  p->rcErr = sqlite3_exec(p->dbSrc, "SELECT 1 FROM sqlite_master; BEGIN;",
  p->rcErr = sqlite3_exec(p->dbSrc, "SELECT 1 FROM sqlite_schema; BEGIN;",
                          0, 0, 0);
  if( p->rcErr ){
    scrubBackupErr(p,
       "cannot start a read transaction on the source database: %s",
       sqlite3_errmsg(p->dbSrc));
    return;
  }
531
532
533
534
535
536
537
538

539
540
541
542
543
544
545
531
532
533
534
535
536
537

538
539
540
541
542
543
544
545







-
+







  /* Copy ptrmap pages */
  n = scrubBackupInt32(&s.page1[52]);
  if( n ) scrubBackupPtrmap(&s);

  /* Copy all of the btrees */
  scrubBackupBtree(&s, 1, 0);
  pStmt = scrubBackupPrepare(&s, s.dbSrc,
       "SELECT rootpage FROM sqlite_master WHERE coalesce(rootpage,0)>0");
       "SELECT rootpage FROM sqlite_schema WHERE coalesce(rootpage,0)>0");
  if( pStmt==0 ) goto scrub_abort;
  while( sqlite3_step(pStmt)==SQLITE_ROW ){
    i = (u32)sqlite3_column_int(pStmt, 0);
    scrubBackupBtree(&s, i, 0);
  }
  sqlite3_finalize(pStmt);

Changes to ext/misc/series.c.

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







-
-
+
+

-
+










+
+
+
+






+















-
+

+







**    (1) Allocate the series_vtab object and initialize all fields.
**
**    (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
**        result set of queries against generate_series will look like.
*/
static int seriesConnect(
  sqlite3 *db,
  void *pAux,
  int argc, const char *const*argv,
  void *pUnused,
  int argcUnused, const char *const*argvUnused,
  sqlite3_vtab **ppVtab,
  char **pzErr
  char **pzErrUnused
){
  sqlite3_vtab *pNew;
  int rc;

/* Column numbers */
#define SERIES_COLUMN_VALUE 0
#define SERIES_COLUMN_START 1
#define SERIES_COLUMN_STOP  2
#define SERIES_COLUMN_STEP  3

  (void)pUnused;
  (void)argcUnused;
  (void)argvUnused;
  (void)pzErrUnused;
  rc = sqlite3_declare_vtab(db,
     "CREATE TABLE x(value,start hidden,stop hidden,step hidden)");
  if( rc==SQLITE_OK ){
    pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) );
    if( pNew==0 ) return SQLITE_NOMEM;
    memset(pNew, 0, sizeof(*pNew));
    sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
  }
  return rc;
}

/*
** This method is the destructor for series_cursor objects.
*/
static int seriesDisconnect(sqlite3_vtab *pVtab){
  sqlite3_free(pVtab);
  return SQLITE_OK;
}

/*
** Constructor for a new series_cursor object.
*/
static int seriesOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
static int seriesOpen(sqlite3_vtab *pUnused, sqlite3_vtab_cursor **ppCursor){
  series_cursor *pCur;
  (void)pUnused;
  pCur = sqlite3_malloc( sizeof(*pCur) );
  if( pCur==0 ) return SQLITE_NOMEM;
  memset(pCur, 0, sizeof(*pCur));
  *ppCursor = &pCur->base;
  return SQLITE_OK;
}

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







-
+
+







-
+




+












-
+
+
+
+
+
+







** is a bitmask showing which constraints are available:
**
**    1:    start=VALUE
**    2:    stop=VALUE
**    4:    step=VALUE
**
** Also, if bit 8 is set, that means that the series should be output
** in descending order rather than in ascending order.
** in descending order rather than in ascending order.  If bit 16 is
** set, then output must appear in ascending order.
**
** This routine should initialize the cursor and position it so that it
** is pointing at the first row, or pointing off the end of the table
** (so that seriesEof() will return true) if the table is empty.
*/
static int seriesFilter(
  sqlite3_vtab_cursor *pVtabCursor, 
  int idxNum, const char *idxStr,
  int idxNum, const char *idxStrUnused,
  int argc, sqlite3_value **argv
){
  series_cursor *pCur = (series_cursor *)pVtabCursor;
  int i = 0;
  (void)idxStrUnused;
  if( idxNum & 1 ){
    pCur->mnValue = sqlite3_value_int64(argv[i++]);
  }else{
    pCur->mnValue = 0;
  }
  if( idxNum & 2 ){
    pCur->mxValue = sqlite3_value_int64(argv[i++]);
  }else{
    pCur->mxValue = 0xffffffff;
  }
  if( idxNum & 4 ){
    pCur->iStep = sqlite3_value_int64(argv[i++]);
    if( pCur->iStep<1 ) pCur->iStep = 1;
    if( pCur->iStep==0 ){
      pCur->iStep = 1;
    }else if( pCur->iStep<0 ){
      pCur->iStep = -pCur->iStep;
      if( (idxNum & 16)==0 ) idxNum |= 8;
    }
  }else{
    pCur->iStep = 1;
  }
  for(i=0; i<argc; i++){
    if( sqlite3_value_type(argv[i])==SQLITE_NULL ){
      /* If any of the constraints have a NULL value, then return no rows.
      ** See ticket https://www.sqlite.org/src/info/fac496b61722daf2 */
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
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







-
+




+









+









+














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











-
-
+
+
+
+
+
+







**
**  (1)  start = $value  -- constraint exists
**  (2)  stop = $value   -- constraint exists
**  (4)  step = $value   -- constraint exists
**  (8)  output in descending order
*/
static int seriesBestIndex(
  sqlite3_vtab *tab,
  sqlite3_vtab *pVTab,
  sqlite3_index_info *pIdxInfo
){
  int i, j;              /* Loop over constraints */
  int idxNum = 0;        /* The query plan bitmask */
  int bStartSeen = 0;    /* EQ constraint seen on the START column */
  int unusableMask = 0;  /* Mask of unusable constraints */
  int nArg = 0;          /* Number of arguments that seriesFilter() expects */
  int aIdx[3];           /* Constraints on start, stop, and step */
  const struct sqlite3_index_constraint *pConstraint;

  /* This implementation assumes that the start, stop, and step columns
  ** are the last three columns in the virtual table. */
  assert( SERIES_COLUMN_STOP == SERIES_COLUMN_START+1 );
  assert( SERIES_COLUMN_STEP == SERIES_COLUMN_START+2 );

  aIdx[0] = aIdx[1] = aIdx[2] = -1;
  pConstraint = pIdxInfo->aConstraint;
  for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
    int iCol;    /* 0 for start, 1 for stop, 2 for step */
    int iMask;   /* bitmask for those column */
    if( pConstraint->iColumn<SERIES_COLUMN_START ) continue;
    iCol = pConstraint->iColumn - SERIES_COLUMN_START;
    assert( iCol>=0 && iCol<=2 );
    iMask = 1 << iCol;
    if( iCol==0 ) bStartSeen = 1;
    if( pConstraint->usable==0 ){
      unusableMask |=  iMask;
      continue;
    }else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
      idxNum |= iMask;
      aIdx[iCol] = i;
    }
  }
  for(i=0; i<3; i++){
    if( (j = aIdx[i])>=0 ){
      pIdxInfo->aConstraintUsage[j].argvIndex = ++nArg;
      pIdxInfo->aConstraintUsage[j].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY;
    }
  }
  /* The current generate_column() implementation requires at least one
  ** argument (the START value).  Legacy versions assumed START=0 if the
  ** first argument was omitted.  Compile with -DZERO_ARGUMENT_GENERATE_SERIES
  ** to obtain the legacy behavior */
#ifndef ZERO_ARGUMENT_GENERATE_SERIES
  if( !bStartSeen ){
    sqlite3_free(pVTab->zErrMsg);
    pVTab->zErrMsg = sqlite3_mprintf(
        "first argument to \"generate_series()\" missing or unusable");
    return SQLITE_ERROR;
  }
#endif
  if( (unusableMask & ~idxNum)!=0 ){
    /* The start, stop, and step columns are inputs.  Therefore if there
    ** are unusable constraints on any of start, stop, or step then
    ** this plan is unusable */
    return SQLITE_CONSTRAINT;
  }
  if( (idxNum & 3)==3 ){
    /* Both start= and stop= boundaries are available.  This is the 
    ** the preferred case */
    pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0));
    pIdxInfo->estimatedRows = 1000;
    if( pIdxInfo->nOrderBy==1 ){
      if( pIdxInfo->aOrderBy[0].desc ) idxNum |= 8;
    if( pIdxInfo->nOrderBy>=1 && pIdxInfo->aOrderBy[0].iColumn==0 ){
      if( pIdxInfo->aOrderBy[0].desc ){
        idxNum |= 8;
      }else{
        idxNum |= 16;
      }
      pIdxInfo->orderByConsumed = 1;
    }
  }else{
    /* If either boundary is missing, we have to generate a huge span
    ** of numbers.  Make this case very expensive so that the query
    ** planner will work hard to avoid it. */
    pIdxInfo->estimatedRows = 2147483647;
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
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







+
+
+
+















-
+








  0,                         /* xUpdate */
  0,                         /* xBegin */
  0,                         /* xSync */
  0,                         /* xCommit */
  0,                         /* xRollback */
  0,                         /* xFindMethod */
  0,                         /* xRename */
  0,                         /* xSavepoint */
  0,                         /* xRelease */
  0,                         /* xRollbackTo */
  0                          /* xShadowName */
};

#endif /* SQLITE_OMIT_VIRTUALTABLE */

#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_series_init(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  SQLITE_EXTENSION_INIT2(pApi);
#ifndef SQLITE_OMIT_VIRTUALTABLE
  if( sqlite3_libversion_number()<3008012 ){
  if( sqlite3_libversion_number()<3008012 && pzErrMsg!=0 ){
    *pzErrMsg = sqlite3_mprintf(
        "generate_series() requires SQLite 3.8.12 or later");
    return SQLITE_ERROR;
  }
  rc = sqlite3_create_module(db, "generate_series", &seriesModule, 0);
#endif
  return rc;
}

Changes to ext/misc/sha1.c.

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
35
36
37
38
39
40
41














42
43
44


45
46
47
48
49
50
51







-
-
-
-
-
-
-
-
-
-
-
-
-
-



-
-







typedef struct SHA1Context SHA1Context;
struct SHA1Context {
  unsigned int state[5];
  unsigned int count[2];
  unsigned char buffer[64];
};


#if __GNUC__ && (defined(__i386__) || defined(__x86_64__))
/*
 * GCC by itself only generates left rotates.  Use right rotates if
 * possible to be kinder to dinky implementations with iterative rotate
 * instructions.
 */
#define SHA_ROT(op, x, k) \
        ({ unsigned int y; asm(op " %1,%0" : "=r" (y) : "I" (k), "0" (x)); y; })
#define rol(x,k) SHA_ROT("roll", x, k)
#define ror(x,k) SHA_ROT("rorl", x, k)

#else
/* Generic C equivalent */
#define SHA_ROT(x,l,r) ((x) << (l) | (x) >> (r))
#define rol(x,k) SHA_ROT(x,k,32-(k))
#define ror(x,k) SHA_ROT(x,32-(k),k)
#endif


#define blk0le(i) (block[i] = (ror(block[i],8)&0xFF00FF00) \
    |(rol(block[i],8)&0x00FF00FF))
#define blk0be(i) block[i]
#define blk(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15] \
    ^block[(i+2)&15]^block[i&15],1))

83
84
85
86
87
88
89
90

91
92
93
94
95
96
97
67
68
69
70
71
72
73

74
75
76
77
78
79
80
81







-
+







    z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=ror(w,2);
#define R4(v,w,x,y,z,i) \
    z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=ror(w,2);

/*
 * Hash a single 512-bit block. This is the core of the algorithm.
 */
void SHA1Transform(unsigned int state[5], const unsigned char buffer[64]){
static void SHA1Transform(unsigned int state[5], const unsigned char buffer[64]){
  unsigned int qq[5]; /* a, b, c, d, e; */
  static int one = 1;
  unsigned int block[16];
  memcpy(block, buffer, 64);
  memcpy(qq,state,5*sizeof(unsigned int));

#define a qq[0]
393
394
395
396
397
398
399
400
401



402
403


404
405
406
407
377
378
379
380
381
382
383


384
385
386
387

388
389
390
391
392
393







-
-
+
+
+

-
+
+




  sqlite3 *db,
  char **pzErrMsg,
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg;  /* Unused parameter */
  rc = sqlite3_create_function(db, "sha1", 1, SQLITE_UTF8, 0,
                               sha1Func, 0, 0);
  rc = sqlite3_create_function(db, "sha1", 1, 
                       SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC,
                               0, sha1Func, 0, 0);
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "sha1_query", 1, SQLITE_UTF8, 0,
    rc = sqlite3_create_function(db, "sha1_query", 1, 
                                 SQLITE_UTF8|SQLITE_DIRECTONLY, 0,
                                 sha1QueryFunc, 0, 0);
  }
  return rc;
}

Changes to ext/misc/shathree.c.

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







-
+











+
+

+







**
**     sha3(X,SIZE)
**     sha3_query(Y,SIZE)
**
** The sha3(X) function computes the SHA3 hash of the input X, or NULL if
** X is NULL.
**
** The sha3_query(Y) function evalutes all queries in the SQL statements of Y
** The sha3_query(Y) function evaluates all queries in the SQL statements of Y
** and returns a hash of their results.
**
** The SIZE argument is optional.  If omitted, the SHA3-256 hash algorithm
** is used.  If SIZE is included it must be one of the integers 224, 256,
** 384, or 512, to determine SHA3 hash variant that is computed.
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
#include <stdarg.h>

#ifndef SQLITE_AMALGAMATION
typedef sqlite3_uint64 u64;
#endif /* SQLITE_AMALGAMATION */

/******************************************************************************
** The Hash Engine
*/
/*
** Macros to determine whether the machine is big or little endian,
** and whether or not that determination is run-time or compile-time.
429
430
431
432
433
434
435

436
437
438
439
440
441
442
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446







+







*/
static void SHA3Update(
  SHA3Context *p,
  const unsigned char *aData,
  unsigned int nData
){
  unsigned int i = 0;
  if( aData==0 ) return;
#if SHA3_BYTEORDER==1234
  if( (p->nLoaded % 8)==0 && ((aData - (const unsigned char*)0)&7)==0 ){
    for(; i+7<nData; i+=8){
      p->u.s[p->nLoaded/8] ^= *(u64*)&aData[i];
      p->nLoaded += 8;
      if( p->nLoaded>=p->nRate ){
        KeccakF1600Step(p);
523
524
525
526
527
528
529
530

531
532
533
534
535
536
537
527
528
529
530
531
532
533

534
535
536
537
538
539
540
541







-
+







  }
  sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT);
}

/* Compute a string using sqlite3_vsnprintf() with a maximum length
** of 50 bytes and add it to the hash.
*/
static void hash_step_vformat(
static void sha3_step_vformat(
  SHA3Context *p,                 /* Add content to this context */
  const char *zFormat,
  ...
){
  va_list ap;
  int n;
  char zBuf[50];
617
618
619
620
621
622
623

624
625
626




627
628
629
630
631
632
633
621
622
623
624
625
626
627
628



629
630
631
632
633
634
635
636
637
638
639







+
-
-
-
+
+
+
+







      sqlite3_finalize(pStmt);
      sqlite3_result_error(context, zMsg, -1);
      sqlite3_free(zMsg);
      return;
    }
    nCol = sqlite3_column_count(pStmt);
    z = sqlite3_sql(pStmt);
    if( z ){
    n = (int)strlen(z);
    hash_step_vformat(&cx,"S%d:",n);
    SHA3Update(&cx,(unsigned char*)z,n);
      n = (int)strlen(z);
      sha3_step_vformat(&cx,"S%d:",n);
      SHA3Update(&cx,(unsigned char*)z,n);
    }

    /* Compute a hash over the result of the query */
    while( SQLITE_ROW==sqlite3_step(pStmt) ){
      SHA3Update(&cx,(const unsigned char*)"R",1);
      for(i=0; i<nCol; i++){
        switch( sqlite3_column_type(pStmt,i) ){
          case SQLITE_NULL: {
661
662
663
664
665
666
667
668

669
670
671
672
673
674
675

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

674
675
676
677
678
679
680

681
682
683
684
685
686
687
688







-
+






-
+







            x[0] = 'F';
            SHA3Update(&cx,x,9);
            break;
          }
          case SQLITE_TEXT: {
            int n2 = sqlite3_column_bytes(pStmt, i);
            const unsigned char *z2 = sqlite3_column_text(pStmt, i);
            hash_step_vformat(&cx,"T%d:",n2);
            sha3_step_vformat(&cx,"T%d:",n2);
            SHA3Update(&cx, z2, n2);
            break;
          }
          case SQLITE_BLOB: {
            int n2 = sqlite3_column_bytes(pStmt, i);
            const unsigned char *z2 = sqlite3_column_blob(pStmt, i);
            hash_step_vformat(&cx,"B%d:",n2);
            sha3_step_vformat(&cx,"B%d:",n2);
            SHA3Update(&cx, z2, n2);
            break;
          }
        }
      }
    }
    sqlite3_finalize(pStmt);
692
693
694
695
696
697
698
699
700



701
702
703



704
705
706
707



708
709
710
711



712
713
714
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







-
-
+
+
+

-
-
+
+
+


-
-
+
+
+


-
-
+
+
+



  sqlite3 *db,
  char **pzErrMsg,
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg;  /* Unused parameter */
  rc = sqlite3_create_function(db, "sha3", 1, SQLITE_UTF8, 0,
                               sha3Func, 0, 0);
  rc = sqlite3_create_function(db, "sha3", 1,
                      SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC,
                      0, sha3Func, 0, 0);
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "sha3", 2, SQLITE_UTF8, 0,
                                 sha3Func, 0, 0);
    rc = sqlite3_create_function(db, "sha3", 2,
                      SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC,
                      0, sha3Func, 0, 0);
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "sha3_query", 1, SQLITE_UTF8, 0,
                                 sha3QueryFunc, 0, 0);
    rc = sqlite3_create_function(db, "sha3_query", 1,
                      SQLITE_UTF8 | SQLITE_DIRECTONLY,
                      0, sha3QueryFunc, 0, 0);
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "sha3_query", 2, SQLITE_UTF8, 0,
                                 sha3QueryFunc, 0, 0);
    rc = sqlite3_create_function(db, "sha3_query", 2,
                      SQLITE_UTF8 | SQLITE_DIRECTONLY,
                      0, sha3QueryFunc, 0, 0);
  }
  return rc;
}

Changes to ext/misc/spellfix.c.

2065
2066
2067
2068
2069
2070
2071

2072
2073
2074
2075
2076
2077
2078
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079







+







    pNew->zDbName = (char*)&pNew[1];
    memcpy(pNew->zDbName, zDbName, nDbName+1);
    pNew->zTableName = sqlite3_mprintf("%s", zTableName);
    pNew->db = db;
    if( pNew->zTableName==0 ){
      rc = SQLITE_NOMEM;
    }else{
      sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
      rc = sqlite3_declare_vtab(db, 
           "CREATE TABLE x(word,rank,distance,langid, "
           "score, matchlen, phonehash HIDDEN, "
           "top HIDDEN, scope HIDDEN, srchcnt HIDDEN, "
           "soundslike HIDDEN, command HIDDEN)"
      );
#define SPELLFIX_COL_WORD            0

Changes to ext/misc/sqlar.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







+







** Utility functions sqlar_compress() and sqlar_uncompress(). Useful
** for working with sqlar archives and used by the shell tool's built-in
** sqlar support.
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#include <zlib.h>
#include <assert.h>

/*
** Implementation of the "sqlar_compress(X)" SQL function.
**
** If the type of X is SQLITE_BLOB, and compressing that blob using
** zlib utility function compress() yields a smaller blob, return the
** compressed blob. Otherwise, return a copy of X.
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
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







+
+
-
+







-












-
+
+


-
+
+




  sz = sqlite3_value_int(argv[1]);

  if( sz<=0 || sz==(nData = sqlite3_value_bytes(argv[0])) ){
    sqlite3_result_value(context, argv[0]);
  }else{
    const Bytef *pData= sqlite3_value_blob(argv[0]);
    Bytef *pOut = sqlite3_malloc(sz);
    if( pOut==0 ){
      sqlite3_result_error_nomem(context);
    if( Z_OK!=uncompress(pOut, &sz, pData, nData) ){
    }else if( Z_OK!=uncompress(pOut, &sz, pData, nData) ){
      sqlite3_result_error(context, "error in uncompress()", -1);
    }else{
      sqlite3_result_blob(context, pOut, sz, SQLITE_TRANSIENT);
    }
    sqlite3_free(pOut);
  }
}


#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_sqlar_init(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg;  /* Unused parameter */
  rc = sqlite3_create_function(db, "sqlar_compress", 1, SQLITE_UTF8, 0,
  rc = sqlite3_create_function(db, "sqlar_compress", 1, 
                               SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
                               sqlarCompressFunc, 0, 0);
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "sqlar_uncompress", 2, SQLITE_UTF8, 0,
    rc = sqlite3_create_function(db, "sqlar_uncompress", 2,
                                 SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
                                 sqlarUncompressFunc, 0, 0);
  }
  return rc;
}

Changes to ext/misc/stmt.c.

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







+
+
+
+
+
+
+
+
+
+

















-
-
+







#endif
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>

#ifndef SQLITE_OMIT_VIRTUALTABLE


#define STMT_NUM_INTEGER_COLUMN 10
typedef struct StmtRow StmtRow;
struct StmtRow {
  sqlite3_int64 iRowid;                /* Rowid value */
  char *zSql;                          /* column "sql" */
  int aCol[STMT_NUM_INTEGER_COLUMN+1]; /* all other column values */
  StmtRow *pNext;                      /* Next row to return */
};

/* stmt_vtab is a subclass of sqlite3_vtab which will
** serve as the underlying representation of a stmt virtual table
*/
typedef struct stmt_vtab stmt_vtab;
struct stmt_vtab {
  sqlite3_vtab base;  /* Base class - must be first */
  sqlite3 *db;        /* Database connection for this stmt vtab */
};

/* stmt_cursor is a subclass of sqlite3_vtab_cursor which will
** serve as the underlying representation of a cursor that scans
** over rows of the result
*/
typedef struct stmt_cursor stmt_cursor;
struct stmt_cursor {
  sqlite3_vtab_cursor base;  /* Base class - must be first */
  sqlite3 *db;               /* Database connection for this cursor */
  sqlite3_stmt *pStmt;       /* Statement cursor is currently pointing at */
  sqlite3_int64 iRowid;      /* The rowid */
  StmtRow *pRow;             /* Current row */
};

/*
** The stmtConnect() method is invoked to create a new
** stmt_vtab that describes the stmt virtual table.
**
** Think of this routine as the constructor for stmt_vtab objects.
84
85
86
87
88
89
90




91
92
93
94
95

96
97
98
99
100
101
102
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107

108
109
110
111
112
113
114
115







+
+
+
+




-
+







#define STMT_COLUMN_NAIDX   6   /* SQLITE_STMTSTATUS_AUTOINDEX */
#define STMT_COLUMN_NSTEP   7   /* SQLITE_STMTSTATUS_VM_STEP */
#define STMT_COLUMN_REPREP  8   /* SQLITE_STMTSTATUS_REPREPARE */
#define STMT_COLUMN_RUN     9   /* SQLITE_STMTSTATUS_RUN */
#define STMT_COLUMN_MEM    10   /* SQLITE_STMTSTATUS_MEMUSED */


  (void)pAux;
  (void)argc;
  (void)argv;
  (void)pzErr;
  rc = sqlite3_declare_vtab(db,
     "CREATE TABLE x(sql,ncol,ro,busy,nscan,nsort,naidx,nstep,"
                    "reprep,run,mem)");
  if( rc==SQLITE_OK ){
    pNew = sqlite3_malloc( sizeof(*pNew) );
    pNew = sqlite3_malloc64( sizeof(*pNew) );
    *ppVtab = (sqlite3_vtab*)pNew;
    if( pNew==0 ) return SQLITE_NOMEM;
    memset(pNew, 0, sizeof(*pNew));
    pNew->db = db;
  }
  return rc;
}
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
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







-
+






+
+
+
+
+
+
+
+
+
+





+










+
-
-
+
+













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










-
+









-
+














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












+







}

/*
** Constructor for a new stmt_cursor object.
*/
static int stmtOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
  stmt_cursor *pCur;
  pCur = sqlite3_malloc( sizeof(*pCur) );
  pCur = sqlite3_malloc64( sizeof(*pCur) );
  if( pCur==0 ) return SQLITE_NOMEM;
  memset(pCur, 0, sizeof(*pCur));
  pCur->db = ((stmt_vtab*)p)->db;
  *ppCursor = &pCur->base;
  return SQLITE_OK;
}

static void stmtCsrReset(stmt_cursor *pCur){
  StmtRow *pRow = 0;
  StmtRow *pNext = 0;
  for(pRow=pCur->pRow; pRow; pRow=pNext){
    pNext = pRow->pNext;
    sqlite3_free(pRow);
  }
  pCur->pRow = 0;
}

/*
** Destructor for a stmt_cursor.
*/
static int stmtClose(sqlite3_vtab_cursor *cur){
  stmtCsrReset((stmt_cursor*)cur);
  sqlite3_free(cur);
  return SQLITE_OK;
}


/*
** Advance a stmt_cursor to its next row of output.
*/
static int stmtNext(sqlite3_vtab_cursor *cur){
  stmt_cursor *pCur = (stmt_cursor*)cur;
  StmtRow *pNext = pCur->pRow->pNext;
  pCur->iRowid++;
  pCur->pStmt = sqlite3_next_stmt(pCur->db, pCur->pStmt);
  sqlite3_free(pCur->pRow);
  pCur->pRow = pNext;
  return SQLITE_OK;
}

/*
** Return values of columns for the row at which the stmt_cursor
** is currently pointing.
*/
static int stmtColumn(
  sqlite3_vtab_cursor *cur,   /* The cursor */
  sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
  int i                       /* Which column to return */
){
  stmt_cursor *pCur = (stmt_cursor*)cur;
  switch( i ){
    case STMT_COLUMN_SQL: {
      sqlite3_result_text(ctx, sqlite3_sql(pCur->pStmt), -1, SQLITE_TRANSIENT);
  StmtRow *pRow = pCur->pRow;
  if( i==STMT_COLUMN_SQL ){
    sqlite3_result_text(ctx, pRow->zSql, -1, SQLITE_TRANSIENT);
      break;
    }
  }else{
    case STMT_COLUMN_NCOL: {
      sqlite3_result_int(ctx, sqlite3_column_count(pCur->pStmt));
      break;
    }
    case STMT_COLUMN_RO: {
      sqlite3_result_int(ctx, sqlite3_stmt_readonly(pCur->pStmt));
      break;
    }
    case STMT_COLUMN_BUSY: {
      sqlite3_result_int(ctx, sqlite3_stmt_busy(pCur->pStmt));
    sqlite3_result_int(ctx, pRow->aCol[i]);
      break;
    }
    case STMT_COLUMN_MEM: {
      i = SQLITE_STMTSTATUS_MEMUSED + 
            STMT_COLUMN_NSCAN - SQLITE_STMTSTATUS_FULLSCAN_STEP;
      /* Fall thru */
    }
    case STMT_COLUMN_NSCAN:
    case STMT_COLUMN_NSORT:
    case STMT_COLUMN_NAIDX:
    case STMT_COLUMN_NSTEP:
    case STMT_COLUMN_REPREP:
    case STMT_COLUMN_RUN: {
      sqlite3_result_int(ctx, sqlite3_stmt_status(pCur->pStmt,
                      i-STMT_COLUMN_NSCAN+SQLITE_STMTSTATUS_FULLSCAN_STEP, 0));
      break;
    }
  }
  return SQLITE_OK;
}

/*
** Return the rowid for the current row.  In this implementation, the
** rowid is the same as the output value.
*/
static int stmtRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
  stmt_cursor *pCur = (stmt_cursor*)cur;
  *pRowid = pCur->iRowid;
  *pRowid = pCur->pRow->iRowid;
  return SQLITE_OK;
}

/*
** Return TRUE if the cursor has been moved off of the last
** row of output.
*/
static int stmtEof(sqlite3_vtab_cursor *cur){
  stmt_cursor *pCur = (stmt_cursor*)cur;
  return pCur->pStmt==0;
  return pCur->pRow==0;
}

/*
** This method is called to "rewind" the stmt_cursor object back
** to the first row of output.  This method is always called at least
** once prior to any call to stmtColumn() or stmtRowid() or 
** stmtEof().
*/
static int stmtFilter(
  sqlite3_vtab_cursor *pVtabCursor, 
  int idxNum, const char *idxStr,
  int argc, sqlite3_value **argv
){
  stmt_cursor *pCur = (stmt_cursor *)pVtabCursor;
  sqlite3_stmt *p = 0;
  sqlite3_int64 iRowid = 1;
  StmtRow **ppRow = 0;

  (void)idxNum;
  (void)idxStr;
  (void)argc;
  (void)argv;
  stmtCsrReset(pCur);
  pCur->pStmt = 0;
  pCur->iRowid = 0;
  return stmtNext(pVtabCursor);
  ppRow = &pCur->pRow;
  for(p=sqlite3_next_stmt(pCur->db, 0); p; p=sqlite3_next_stmt(pCur->db, p)){
    const char *zSql = sqlite3_sql(p);
    sqlite3_int64 nSql = zSql ? strlen(zSql)+1 : 0;
    StmtRow *pNew = (StmtRow*)sqlite3_malloc64(sizeof(StmtRow) + nSql);

    if( pNew==0 ) return SQLITE_NOMEM;
    memset(pNew, 0, sizeof(StmtRow));
    if( zSql ){
      pNew->zSql = (char*)&pNew[1];
      memcpy(pNew->zSql, zSql, nSql);
    }
    pNew->aCol[STMT_COLUMN_NCOL] = sqlite3_column_count(p);
    pNew->aCol[STMT_COLUMN_RO] = sqlite3_stmt_readonly(p);
    pNew->aCol[STMT_COLUMN_BUSY] = sqlite3_stmt_busy(p);
    pNew->aCol[STMT_COLUMN_NSCAN] = sqlite3_stmt_status(
        p, SQLITE_STMTSTATUS_FULLSCAN_STEP, 0
    );
    pNew->aCol[STMT_COLUMN_NSORT] = sqlite3_stmt_status(
        p, SQLITE_STMTSTATUS_SORT, 0
    );
    pNew->aCol[STMT_COLUMN_NAIDX] = sqlite3_stmt_status(
        p, SQLITE_STMTSTATUS_AUTOINDEX, 0
    );
    pNew->aCol[STMT_COLUMN_NSTEP] = sqlite3_stmt_status(
        p, SQLITE_STMTSTATUS_VM_STEP, 0
    );
    pNew->aCol[STMT_COLUMN_REPREP] = sqlite3_stmt_status(
        p, SQLITE_STMTSTATUS_REPREPARE, 0
    );
    pNew->aCol[STMT_COLUMN_RUN] = sqlite3_stmt_status(
        p, SQLITE_STMTSTATUS_RUN, 0
    );
    pNew->aCol[STMT_COLUMN_MEM] = sqlite3_stmt_status(
        p, SQLITE_STMTSTATUS_MEMUSED, 0
    );
    pNew->iRowid = iRowid++;
    *ppRow = pNew;
    ppRow = &pNew->pNext;
  }

  return SQLITE_OK;
}

/*
** SQLite will invoke this method one or more times while planning a query
** that uses the stmt virtual table.  This routine needs to create
** a query plan for each invocation and compute an estimated cost for that
** plan.
*/
static int stmtBestIndex(
  sqlite3_vtab *tab,
  sqlite3_index_info *pIdxInfo
){
  (void)tab;
  pIdxInfo->estimatedCost = (double)500;
  pIdxInfo->estimatedRows = 500;
  return SQLITE_OK;
}

/*
** This following structure defines all the methods for the 

Changes to ext/misc/totype.c.

498
499
500
501
502
503
504
505
506



507
508
509



510
511
512
498
499
500
501
502
503
504


505
506
507
508


509
510
511
512
513
514







-
-
+
+
+

-
-
+
+
+



  sqlite3 *db,
  char **pzErrMsg,
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg;  /* Unused parameter */
  rc = sqlite3_create_function(db, "tointeger", 1, SQLITE_UTF8, 0,
                               tointegerFunc, 0, 0);
  rc = sqlite3_create_function(db, "tointeger", 1,
        SQLITE_UTF8 | SQLITE_DETERMINISTIC | SQLITE_INNOCUOUS, 0,
        tointegerFunc, 0, 0);
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "toreal", 1, SQLITE_UTF8, 0,
                                 torealFunc, 0, 0);
    rc = sqlite3_create_function(db, "toreal", 1,
        SQLITE_UTF8 | SQLITE_DETERMINISTIC | SQLITE_INNOCUOUS, 0,
        torealFunc, 0, 0);
  }
  return rc;
}

Added ext/misc/uint.c.





























































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2020-04-14
**
** 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 SQLite extension implements the UINT collating sequence.
**
** UINT works like BINARY for text, except that embedded strings
** of digits compare in numeric order.
**
**     *   Leading zeros are handled properly, in the sense that
**         they do not mess of the maginitude comparison of embedded
**         strings of digits.  "x00123y" is equal to "x123y".
**
**     *   Only unsigned integers are recognized.  Plus and minus
**         signs are ignored.  Decimal points and exponential notation
**         are ignored.
**
**     *   Embedded integers can be of arbitrary length.  Comparison
**         is *not* limited integers that can be expressed as a
**         64-bit machine integer.
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
#include <ctype.h>

/*
** Compare text in lexicographic order, except strings of digits
** compare in numeric order.
*/
static int uintCollFunc(
  void *notUsed,
  int nKey1, const void *pKey1,
  int nKey2, const void *pKey2
){
  const unsigned char *zA = (const unsigned char*)pKey1;
  const unsigned char *zB = (const unsigned char*)pKey2;
  int i=0, j=0, x;
  (void)notUsed;
  while( i<nKey1 && j<nKey2 ){
    x = zA[i] - zB[j];
    if( isdigit(zA[i]) ){
      int k;
      if( !isdigit(zB[j]) ) return x;
      while( i<nKey1 && zA[i]=='0' ){ i++; }
      while( j<nKey2 && zB[j]=='0' ){ j++; }
      k = 0;
      while( i+k<nKey1 && isdigit(zA[i+k])
             && j+k<nKey2 && isdigit(zB[j+k]) ){
        k++;
      }
      if( i+k<nKey1 && isdigit(zA[i+k]) ){
        return +1;
      }else if( j+k<nKey2 && isdigit(zB[j+k]) ){
        return -1;
      }else{
        x = memcmp(zA+i, zB+j, k);
        if( x ) return x;
        i += k;
        j += k;
      }
    }else if( x ){
      return x;
    }else{
      i++;
      j++;
    }
  }
  return (nKey1 - i) - (nKey2 - j);
}

#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_uint_init(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg;  /* Unused parameter */
  return sqlite3_create_collation(db, "uint", SQLITE_UTF8, 0, uintCollFunc);
}

Changes to ext/misc/unionvtab.c.

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







-
+



-
+

-
+



















-
+


-
+







/*
** If *pRc is other than SQLITE_OK when this function is called, it
** always returns NULL. Otherwise, it attempts to allocate and return
** a pointer to nByte bytes of zeroed memory. If the memory allocation
** is attempted but fails, NULL is returned and *pRc is set to 
** SQLITE_NOMEM.
*/
static void *unionMalloc(int *pRc, int nByte){
static void *unionMalloc(int *pRc, sqlite3_int64 nByte){
  void *pRet;
  assert( nByte>0 );
  if( *pRc==SQLITE_OK ){
    pRet = sqlite3_malloc(nByte);
    pRet = sqlite3_malloc64(nByte);
    if( pRet ){
      memset(pRet, 0, nByte);
      memset(pRet, 0, (size_t)nByte);
    }else{
      *pRc = SQLITE_NOMEM;
    }
  }else{
    pRet = 0;
  }
  return pRet;
}

/*
** If *pRc is other than SQLITE_OK when this function is called, it
** always returns NULL. Otherwise, it attempts to allocate and return
** a copy of the nul-terminated string passed as the second argument.
** If the allocation is attempted but fails, NULL is returned and *pRc is 
** set to SQLITE_NOMEM.
*/
static char *unionStrdup(int *pRc, const char *zIn){
  char *zRet = 0;
  if( zIn ){
    int nByte = (int)strlen(zIn) + 1;
    sqlite3_int64 nByte = strlen(zIn) + 1;
    zRet = unionMalloc(pRc, nByte);
    if( zRet ){
      memcpy(zRet, zIn, nByte);
      memcpy(zRet, zIn, (size_t)nByte);
    }
  }
  return zRet;
}

/*
** If the first character of the string passed as the only argument to this
935
936
937
938
939
940
941
942

943
944
945
946
947
948
949
935
936
937
938
939
940
941

942
943
944
945
946
947
948
949







-
+







      sqlite3_int64 iMin = sqlite3_column_int64(pStmt, 2);
      sqlite3_int64 iMax = sqlite3_column_int64(pStmt, 3);
      UnionSrc *pSrc;

      /* Grow the pTab->aSrc[] array if required. */
      if( nAlloc<=pTab->nSrc ){
        int nNew = nAlloc ? nAlloc*2 : 8;
        UnionSrc *aNew = (UnionSrc*)sqlite3_realloc(
        UnionSrc *aNew = (UnionSrc*)sqlite3_realloc64(
            pTab->aSrc, nNew*sizeof(UnionSrc)
        );
        if( aNew==0 ){
          rc = SQLITE_NOMEM;
          break;
        }else{
          memset(&aNew[pTab->nSrc], 0, (nNew-pTab->nSrc)*sizeof(UnionSrc));

Added ext/misc/urifuncs.c.


















































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2020-01-11
**
** 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 SQLite extension implements various SQL functions used to access
** the following SQLite C-language APIs:
**
**         sqlite3_uri_parameter()
**         sqlite3_uri_boolean()
**         sqlite3_uri_int64()
**         sqlite3_uri_key()
**         sqlite3_filename_database()
**         sqlite3_filename_journal()
**         sqlite3_filename_wal()
**         sqlite3_db_filename()
**
** These SQL functions are for testing and demonstration purposes only.
**
**
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>

/*
** SQL function:    sqlite3_db_filename(SCHEMA) 
**
** Return the filename corresponding to SCHEMA.
*/
static void func_db_filename(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const char *zSchema = (const char*)sqlite3_value_text(argv[0]);
  sqlite3 *db = sqlite3_context_db_handle(context);
  const char *zFile = sqlite3_db_filename(db, zSchema);
  sqlite3_result_text(context, zFile, -1, SQLITE_TRANSIENT);
}

/*
** SQL function:    sqlite3_uri_parameter(SCHEMA,NAME) 
**
** Return the value of the NAME query parameter to the database for SCHEMA
*/
static void func_uri_parameter(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const char *zSchema = (const char*)sqlite3_value_text(argv[0]);
  sqlite3 *db = sqlite3_context_db_handle(context);
  const char *zName = (const char*)sqlite3_value_text(argv[1]);
  const char *zFile = sqlite3_db_filename(db, zSchema);
  const char *zRes = sqlite3_uri_parameter(zFile, zName);
  sqlite3_result_text(context, zRes, -1, SQLITE_TRANSIENT);
}

/*
** SQL function:    sqlite3_uri_boolean(SCHEMA,NAME,DEFAULT) 
**
** Return the boolean value of the NAME query parameter to
** the database for SCHEMA
*/
static void func_uri_boolean(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const char *zSchema = (const char*)sqlite3_value_text(argv[0]);
  sqlite3 *db = sqlite3_context_db_handle(context);
  const char *zName = (const char*)sqlite3_value_text(argv[1]);
  const char *zFile = sqlite3_db_filename(db, zSchema);
  int iDflt = sqlite3_value_int(argv[2]);
  int iRes = sqlite3_uri_boolean(zFile, zName, iDflt);
  sqlite3_result_int(context, iRes);
}

/*
** SQL function:    sqlite3_uri_key(SCHEMA,N)
**
** Return the name of the Nth query parameter
*/
static void func_uri_key(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const char *zSchema = (const char*)sqlite3_value_text(argv[0]);
  sqlite3 *db = sqlite3_context_db_handle(context);
  int N = sqlite3_value_int(argv[1]);
  const char *zFile = sqlite3_db_filename(db, zSchema);
  const char *zRes = sqlite3_uri_key(zFile, N);
  sqlite3_result_text(context, zRes, -1, SQLITE_TRANSIENT);
}

/*
** SQL function:    sqlite3_uri_int64(SCHEMA,NAME,DEFAULT) 
**
** Return the int64 value of the NAME query parameter to
** the database for SCHEMA
*/
static void func_uri_int64(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const char *zSchema = (const char*)sqlite3_value_text(argv[0]);
  sqlite3 *db = sqlite3_context_db_handle(context);
  const char *zName = (const char*)sqlite3_value_text(argv[1]);
  const char *zFile = sqlite3_db_filename(db, zSchema);
  sqlite3_int64 iDflt = sqlite3_value_int64(argv[2]);
  sqlite3_int64 iRes = sqlite3_uri_int64(zFile, zName, iDflt);
  sqlite3_result_int64(context, iRes);
}

/*
** SQL function:    sqlite3_filename_database(SCHEMA)
**
** Return the database filename for SCHEMA
*/
static void func_filename_database(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const char *zSchema = (const char*)sqlite3_value_text(argv[0]);
  sqlite3 *db = sqlite3_context_db_handle(context);
  const char *zFile = sqlite3_db_filename(db, zSchema);
  const char *zRes = zFile ? sqlite3_filename_database(zFile) : 0;
  sqlite3_result_text(context, zRes, -1, SQLITE_TRANSIENT);
}

/*
** SQL function:    sqlite3_filename_journal(SCHEMA)
**
** Return the rollback journal filename for SCHEMA
*/
static void func_filename_journal(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const char *zSchema = (const char*)sqlite3_value_text(argv[0]);
  sqlite3 *db = sqlite3_context_db_handle(context);
  const char *zFile = sqlite3_db_filename(db, zSchema);
  const char *zRes = zFile ? sqlite3_filename_journal(zFile) : 0;
  sqlite3_result_text(context, zRes, -1, SQLITE_TRANSIENT);
}

/*
** SQL function:    sqlite3_filename_wal(SCHEMA)
**
** Return the WAL filename for SCHEMA
*/
static void func_filename_wal(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const char *zSchema = (const char*)sqlite3_value_text(argv[0]);
  sqlite3 *db = sqlite3_context_db_handle(context);
  const char *zFile = sqlite3_db_filename(db, zSchema);
  const char *zRes = zFile ? sqlite3_filename_wal(zFile) : 0;
  sqlite3_result_text(context, zRes, -1, SQLITE_TRANSIENT);
}

#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_urifuncs_init(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  static const struct {
    const char *zFuncName;
    int nArg;
    void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
  } aFunc[] = {
    { "sqlite3_db_filename",       1, func_db_filename       },
    { "sqlite3_uri_parameter",     2, func_uri_parameter     },
    { "sqlite3_uri_boolean",       3, func_uri_boolean       },
    { "sqlite3_uri_int64",         3, func_uri_int64         },
    { "sqlite3_uri_key",           2, func_uri_key           },
    { "sqlite3_filename_database", 1, func_filename_database },
    { "sqlite3_filename_journal",  1, func_filename_journal  },
    { "sqlite3_filename_wal",      1, func_filename_wal      },
  };
  int rc = SQLITE_OK;
  int i;
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg;  /* Unused parameter */
  for(i=0; rc==SQLITE_OK && i<sizeof(aFunc)/sizeof(aFunc[0]); i++){
    rc = sqlite3_create_function(db, aFunc[i].zFuncName, aFunc[i].nArg,
                     SQLITE_UTF8, 0,
                     aFunc[i].xFunc, 0, 0);
  }
  return rc;
}

Added ext/misc/uuid.c.










































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2019-10-23
**
** 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 SQLite extension implements functions that handling RFC-4122 UUIDs
** Three SQL functions are implemented:
**
**     uuid()        - generate a version 4 UUID as a string
**     uuid_str(X)   - convert a UUID X into a well-formed UUID string
**     uuid_blob(X)  - convert a UUID X into a 16-byte blob
**
** The output from uuid() and uuid_str(X) are always well-formed RFC-4122
** UUID strings in this format:
**
**        xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
**
** All of the 'x', 'M', and 'N' values are lower-case hexadecimal digits.
** The M digit indicates the "version".  For uuid()-generated UUIDs, the
** version is always "4" (a random UUID).  The upper three bits of N digit
** are the "variant".  This library only supports variant 1 (indicated
** by values of N between '8' and 'b') as those are overwhelming the most
** common.  Other variants are for legacy compatibility only.
**
** The output of uuid_blob(X) is always a 16-byte blob.  The UUID input
** string is converted in network byte order (big-endian) in accordance
** with RFC-4122 specifications for variant-1 UUIDs.  Note that network
** byte order is *always* used, even if the input self-identifies as a
** variant-2 UUID.
**
** The input X to the uuid_str() and uuid_blob() functions can be either
** a string or a BLOB.  If it is a BLOB it must be exactly 16 bytes in
** length or else a NULL is returned.  If the input is a string it must
** consist of 32 hexadecimal digits, upper or lower case, optionally
** surrounded by {...} and with optional "-" characters interposed in the
** middle.  The flexibility of input is inspired by the PostgreSQL
** implementation of UUID functions that accept in all of the following
** formats:
**
**     A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11
**     {a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11}
**     a0eebc999c0b4ef8bb6d6bb9bd380a11
**     a0ee-bc99-9c0b-4ef8-bb6d-6bb9-bd38-0a11
**     {a0eebc99-9c0b4ef8-bb6d6bb9-bd380a11}
**
** If any of the above inputs are passed into uuid_str(), the output will
** always be in the canonical RFC-4122 format:
**
**     a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11
**
** If the X input string has too few or too many digits or contains
** stray characters other than {, }, or -, then NULL is returned.
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
#include <ctype.h>

#if !defined(SQLITE_ASCII) && !defined(SQLITE_EBCDIC)
# define SQLITE_ASCII 1
#endif

/*
** Translate a single byte of Hex into an integer.
** This routine only works if h really is a valid hexadecimal
** character:  0..9a..fA..F
*/
static unsigned char sqlite3UuidHexToInt(int h){
  assert( (h>='0' && h<='9') ||  (h>='a' && h<='f') ||  (h>='A' && h<='F') );
#ifdef SQLITE_ASCII
  h += 9*(1&(h>>6));
#endif
#ifdef SQLITE_EBCDIC
  h += 9*(1&~(h>>4));
#endif
  return (unsigned char)(h & 0xf);
}

/*
** Convert a 16-byte BLOB into a well-formed RFC-4122 UUID.  The output
** buffer zStr should be at least 37 bytes in length.   The output will
** be zero-terminated.
*/
static void sqlite3UuidBlobToStr(
  const unsigned char *aBlob,  /* Input blob */
  unsigned char *zStr          /* Write the answer here */
){
  static const char zDigits[] = "0123456789abcdef";
  int i, k;
  unsigned char x;
  k = 0;
  for(i=0, k=0x550; i<16; i++, k=k>>1){
    if( k&1 ){
      zStr[0] = '-';
      zStr++;
    }
    x = aBlob[i];
    zStr[0] = zDigits[x>>4];
    zStr[1] = zDigits[x&0xf];
    zStr += 2;
  }
  *zStr = 0;
}

/*
** Attempt to parse a zero-terminated input string zStr into a binary
** UUID.  Return 0 on success, or non-zero if the input string is not
** parsable.
*/
static int sqlite3UuidStrToBlob(
  const unsigned char *zStr,   /* Input string */
  unsigned char *aBlob         /* Write results here */
){
  int i;
  if( zStr[0]=='{' ) zStr++;
  for(i=0; i<16; i++){
    if( zStr[0]=='-' ) zStr++;
    if( isxdigit(zStr[0]) && isxdigit(zStr[1]) ){
      aBlob[i] = (sqlite3UuidHexToInt(zStr[0])<<4)
                      + sqlite3UuidHexToInt(zStr[1]);
      zStr += 2;
    }else{
      return 1;
    }
  }
  if( zStr[0]=='}' ) zStr++;
  return zStr[0]!=0;
}

/*
** Render sqlite3_value pIn as a 16-byte UUID blob.  Return a pointer
** to the blob, or NULL if the input is not well-formed.
*/
static const unsigned char *sqlite3UuidInputToBlob(
  sqlite3_value *pIn,     /* Input text */
  unsigned char *pBuf     /* output buffer */
){
  switch( sqlite3_value_type(pIn) ){
    case SQLITE_TEXT: {
      const unsigned char *z = sqlite3_value_text(pIn);
      if( sqlite3UuidStrToBlob(z, pBuf) ) return 0;
      return pBuf;
    }
    case SQLITE_BLOB: {
      int n = sqlite3_value_bytes(pIn);
      return n==16 ? sqlite3_value_blob(pIn) : 0;
    }
    default: {
      return 0;
    }
  }
}

/* Implementation of uuid() */
static void sqlite3UuidFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  unsigned char aBlob[16];
  unsigned char zStr[37];
  (void)argc;
  (void)argv;
  sqlite3_randomness(16, aBlob);
  aBlob[6] = (aBlob[6]&0x0f) + 0x40;
  aBlob[8] = (aBlob[8]&0x3f) + 0x80;
  sqlite3UuidBlobToStr(aBlob, zStr);
  sqlite3_result_text(context, (char*)zStr, 36, SQLITE_TRANSIENT);
}

/* Implementation of uuid_str() */
static void sqlite3UuidStrFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  unsigned char aBlob[16];
  unsigned char zStr[37];
  const unsigned char *pBlob;
  (void)argc;
  pBlob = sqlite3UuidInputToBlob(argv[0], aBlob);
  if( pBlob==0 ) return;
  sqlite3UuidBlobToStr(pBlob, zStr);
  sqlite3_result_text(context, (char*)zStr, 36, SQLITE_TRANSIENT);
}

/* Implementation of uuid_blob() */
static void sqlite3UuidBlobFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  unsigned char aBlob[16];
  const unsigned char *pBlob;
  (void)argc;
  pBlob = sqlite3UuidInputToBlob(argv[0], aBlob);
  if( pBlob==0 ) return;
  sqlite3_result_blob(context, pBlob, 16, SQLITE_TRANSIENT);
}

#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_uuid_init(
  sqlite3 *db,
  char **pzErrMsg,
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg;  /* Unused parameter */
  rc = sqlite3_create_function(db, "uuid", 0, SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
                               sqlite3UuidFunc, 0, 0);
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "uuid_str", 1, 
                       SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
                       0, sqlite3UuidStrFunc, 0, 0);
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "uuid_blob", 1,
                       SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
                       0, sqlite3UuidBlobFunc, 0, 0);
  }
  return rc;
}

Changes to ext/misc/vfslog.c.

272
273
274
275
276
277
278
279

280
281
282
283
284
285
286
272
273
274
275
276
277
278

279
280
281
282
283
284
285
286







-
+







  if( nName>8 && strcmp(zFilename+nName-8,"-journal")==0 ){
    nName -= 8;
    isJournal = 1;
  }else if( nName>12 
         && sqlite3_strglob("-mj??????9??", zFilename+nName-12)==0 ){
    return 0;  /* Do not log master journal files */
  }
  pTemp = sqlite3_malloc( sizeof(*pLog)*2 + nName + 60 );
  pTemp = sqlite3_malloc64( sizeof(*pLog)*2 + nName + 60 );
  if( pTemp==0 ) return 0;
  pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
  sqlite3_mutex_enter(pMutex);
  for(pLog=allLogs; pLog; pLog=pLog->pNext){
    if( pLog->nFilename==nName && !memcmp(pLog->zFilename, zFilename, nName) ){
      break;
    }
750
751
752
753
754
755
756

757
758
759
750
751
752
753
754
755
756
757
758
759
760







+



}

/*
** Register debugvfs as the default VFS for this process.
*/
int sqlite3_register_vfslog(const char *zArg){
  vlog_vfs.pVfs = sqlite3_vfs_find(0);
  if( vlog_vfs.pVfs==0 ) return SQLITE_ERROR;
  vlog_vfs.base.szOsFile = sizeof(VLogFile) + vlog_vfs.pVfs->szOsFile;
  return sqlite3_vfs_register(&vlog_vfs.base, 1);
}

Changes to ext/misc/vfsstat.c.

779
780
781
782
783
784
785
786
787


788
789
790
791
792
793
794
779
780
781
782
783
784
785


786
787
788
789
790
791
792
793
794







-
-
+
+








/*
** This routine is an sqlite3_auto_extension() callback, invoked to register
** the vfsstat virtual table for all new database connections.
*/
static int vstatRegister(
  sqlite3 *db,
  const char **pzErrMsg,
  const struct sqlite3_api_routines *pThunk
  char **pzErrMsg,
  const sqlite3_api_routines *pThunk
){
  return sqlite3_create_module(db, "vfsstat", &VfsStatModule, 0);
}

#ifdef _WIN32
__declspec(dllexport)
#endif
802
803
804
805
806
807
808

809
810
811


812


813
814
815
816
802
803
804
805
806
807
808
809
810
811
812
813
814

815
816
817
818
819
820







+



+
+
-
+
+




  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  SQLITE_EXTENSION_INIT2(pApi);
  vstat_vfs.pVfs = sqlite3_vfs_find(0);
  if( vstat_vfs.pVfs==0 ) return SQLITE_ERROR;
  vstat_vfs.base.szOsFile = sizeof(VStatFile) + vstat_vfs.pVfs->szOsFile;
  rc = sqlite3_vfs_register(&vstat_vfs.base, 1);
  if( rc==SQLITE_OK ){
    rc = vstatRegister(db, pzErrMsg, pApi);
    if( rc==SQLITE_OK ){
    rc = sqlite3_auto_extension(vstatRegister);
      rc = sqlite3_auto_extension((void(*)(void))vstatRegister);
    }
  }
  if( rc==SQLITE_OK ) rc = SQLITE_OK_LOAD_PERMANENTLY;
  return rc;
}

Changes to ext/misc/wholenumber.c.

46
47
48
49
50
51
52

53
54
55
56
57
58
59
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60







+







  sqlite3_vtab **ppVtab,
  char **pzErr
){
  sqlite3_vtab *pNew;
  pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) );
  if( pNew==0 ) return SQLITE_NOMEM;
  sqlite3_declare_vtab(db, "CREATE TABLE x(value)");
  sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
  memset(pNew, 0, sizeof(*pNew));
  return SQLITE_OK;
}
/* Note that for this virtual table, the xCreate and xConnect
** methods are identical. */

static int wholenumberDisconnect(sqlite3_vtab *pVtab){
215
216
217
218
219
220
221
222

223
224
225
226
227
228
229
216
217
218
219
220
221
222

223
224
225
226
227
228
229
230







-
+







  }
  if( pIdxInfo->nOrderBy==1
   && pIdxInfo->aOrderBy[0].desc==0
  ){
    pIdxInfo->orderByConsumed = 1;
  }
  if( (idxNum & 12)==0 ){
    pIdxInfo->estimatedCost = (double)100000000;
    pIdxInfo->estimatedCost = 1e99;
  }else if( (idxNum & 3)==0 ){
    pIdxInfo->estimatedCost = (double)5;
  }else{
    pIdxInfo->estimatedCost = (double)1;
  }
  return SQLITE_OK;
}

Changes to ext/misc/zipfile.c.

32
33
34
35
36
37
38














39
40
41
42


43
44
45



46
47
48
49
50
51
52
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







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


-
-
+
+



+
+
+








#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 SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1
#endif
#if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
# define ALWAYS(X)      (1)
# define NEVER(X)       (0)
#elif !defined(NDEBUG)
# define ALWAYS(X)      ((X)?1:(assert(0),0))
# define NEVER(X)       ((X)?(assert(0),1):0)
#else
# define ALWAYS(X)      (X)
331
332
333
334
335
336
337

338
339
340
341
342
343
344
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362







+







  char **pzErr
){
  int nByte = sizeof(ZipfileTab) + ZIPFILE_BUFFER_SIZE;
  int nFile = 0;
  const char *zFile = 0;
  ZipfileTab *pNew = 0;
  int rc;
  (void)pAux;

  /* If the table name is not "zipfile", require that the argument be
  ** specified. This stops zipfile tables from being created as:
  **
  **   CREATE VIRTUAL TABLE zzz USING zipfile();
  **
  ** It does not prevent:
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
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







-
+










+







  if( argc>3 ){
    zFile = argv[3];
    nFile = (int)strlen(zFile)+1;
  }

  rc = sqlite3_declare_vtab(db, ZIPFILE_SCHEMA);
  if( rc==SQLITE_OK ){
    pNew = (ZipfileTab*)sqlite3_malloc(nByte+nFile);
    pNew = (ZipfileTab*)sqlite3_malloc64((sqlite3_int64)nByte+nFile);
    if( pNew==0 ) return SQLITE_NOMEM;
    memset(pNew, 0, nByte+nFile);
    pNew->db = db;
    pNew->aBuffer = (u8*)&pNew[1];
    if( zFile ){
      pNew->zFile = (char*)&pNew->aBuffer[ZIPFILE_BUFFER_SIZE];
      memcpy(pNew->zFile, zFile, nFile);
      zipfileDequote(pNew->zFile);
    }
  }
  sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY);
  *ppVtab = (sqlite3_vtab*)pNew;
  return rc;
}

/*
** Free the ZipfileEntry structure indicated by the only argument.
*/
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
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







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














+







}

static int zipfileAppendData(
  ZipfileTab *pTab,
  const u8 *aWrite,
  int nWrite
){
  if( nWrite>0 ){
  size_t n;
  fseek(pTab->pWriteFd, (long)pTab->szCurrent, SEEK_SET);
  n = fwrite(aWrite, 1, nWrite, pTab->pWriteFd);
  if( (int)n!=nWrite ){
    pTab->base.zErrMsg = sqlite3_mprintf("error in fwrite()");
    return SQLITE_ERROR;
  }
  pTab->szCurrent += nWrite;
    size_t n = nWrite;
    fseek(pTab->pWriteFd, (long)pTab->szCurrent, SEEK_SET);
    n = fwrite(aWrite, 1, nWrite, pTab->pWriteFd);
    if( (int)n!=nWrite ){
      pTab->base.zErrMsg = sqlite3_mprintf("error in fwrite()");
      return SQLITE_ERROR;
    }
    pTab->szCurrent += nWrite;
  }
  return SQLITE_OK;
}

/*
** Read and return a 16-bit little-endian unsigned integer from buffer aBuf.
*/
static u16 zipfileGetU16(const u8 *aBuf){
  return (aBuf[1] << 8) + aBuf[0];
}

/*
** Read and return a 32-bit little-endian unsigned integer from buffer aBuf.
*/
static u32 zipfileGetU32(const u8 *aBuf){
  if( aBuf==0 ) return 0;
  return ((u32)(aBuf[3]) << 24)
       + ((u32)(aBuf[2]) << 16)
       + ((u32)(aBuf[1]) <<  8)
       + ((u32)(aBuf[0]) <<  0);
}

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







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

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







**     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.
*/
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
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







+









-
+











-
+







  FILE *pFile,                    /* If aBlob==0, read from this file */
  i64 iOff,                       /* Offset of CDS record */
  ZipfileEntry **ppEntry          /* OUT: Pointer to new object */
){
  u8 *aRead;
  char **pzErr = &pTab->base.zErrMsg;
  int rc = SQLITE_OK;
  (void)nBlob;

  if( aBlob==0 ){
    aRead = pTab->aBuffer;
    rc = zipfileReadData(pFile, aRead, ZIPFILE_CDS_FIXED_SZ, iOff, pzErr);
  }else{
    aRead = (u8*)&aBlob[iOff];
  }

  if( rc==SQLITE_OK ){
    int nAlloc;
    sqlite3_int64 nAlloc;
    ZipfileEntry *pNew;

    int nFile = zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF]);
    int nExtra = zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF+2]);
    nExtra += zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF+4]);

    nAlloc = sizeof(ZipfileEntry) + nExtra;
    if( aBlob ){
      nAlloc += zipfileGetU32(&aRead[ZIPFILE_CDS_SZCOMPRESSED_OFF]);
    }

    pNew = (ZipfileEntry*)sqlite3_malloc(nAlloc);
    pNew = (ZipfileEntry*)sqlite3_malloc64(nAlloc);
    if( pNew==0 ){
      rc = SQLITE_NOMEM;
    }else{
      memset(pNew, 0, sizeof(ZipfileEntry));
      rc = zipfileReadCDS(aRead, &pNew->cds);
      if( rc!=SQLITE_OK ){
        *pzErr = sqlite3_mprintf("failed to read CDS at offset %lld", iOff);
852
853
854
855
856
857
858
859

860
861
862
863
864
865
866
865
866
867
868
869
870
871

872
873
874
875
876
877
878
879







-
+







      ZipfileLFH lfh;
      if( pFile ){
        rc = zipfileReadData(pFile, aRead, szFix, pNew->cds.iOffset, pzErr);
      }else{
        aRead = (u8*)&aBlob[pNew->cds.iOffset];
      }

      rc = zipfileReadLFH(aRead, &lfh);
      if( rc==SQLITE_OK ) rc = zipfileReadLFH(aRead, &lfh);
      if( rc==SQLITE_OK ){
        pNew->iDataOff =  pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ;
        pNew->iDataOff += lfh.nFile + lfh.nExtra;
        if( aBlob && pNew->cds.szCompressed ){
          pNew->aData = &pNew->aExtra[nExtra];
          memcpy(pNew->aData, &aBlob[pNew->iDataOff], pNew->cds.szCompressed);
        }
977
978
979
980
981
982
983

984


985
986





987

988

989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
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







+
-
+
+

-
+
+
+
+
+

+
-
+




-
-
-
-


-
-

-







** case.
*/
static int zipfileDeflate(
  const u8 *aIn, int nIn,         /* Input */
  u8 **ppOut, int *pnOut,         /* Output */
  char **pzErr                    /* OUT: Error message */
){
  int rc = SQLITE_OK;
  int nAlloc = (int)compressBound(nIn);
  sqlite3_int64 nAlloc;
  z_stream str;
  u8 *aOut;
  int rc = SQLITE_OK;

  memset(&str, 0, sizeof(str));
  str.next_in = (Bytef*)aIn;
  str.avail_in = nIn;
  deflateInit2(&str, 9, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);

  nAlloc = deflateBound(&str, nIn);
  aOut = (u8*)sqlite3_malloc(nAlloc);
  aOut = (u8*)sqlite3_malloc64(nAlloc);
  if( aOut==0 ){
    rc = SQLITE_NOMEM;
  }else{
    int res;
    z_stream str;
    memset(&str, 0, sizeof(str));
    str.next_in = (Bytef*)aIn;
    str.avail_in = nIn;
    str.next_out = aOut;
    str.avail_out = nAlloc;

    deflateInit2(&str, 9, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
    res = deflate(&str, Z_FINISH);

    if( res==Z_STREAM_END ){
      *ppOut = aOut;
      *pnOut = (int)str.total_out;
    }else{
      sqlite3_free(aOut);
      *pzErr = sqlite3_mprintf("zipfile: deflate() error");
      rc = SQLITE_ERROR;
1054
1055
1056
1057
1058
1059
1060
1061

1062
1063
1064
1065
1066
1067
1068
1067
1068
1069
1070
1071
1072
1073

1074
1075
1076
1077
1078
1079
1080
1081







-
+







        int szFinal = pCDS->szUncompressed;
        if( szFinal>0 ){
          u8 *aBuf;
          u8 *aFree = 0;
          if( pCsr->pCurrent->aData ){
            aBuf = pCsr->pCurrent->aData;
          }else{
            aBuf = aFree = sqlite3_malloc(sz);
            aBuf = aFree = sqlite3_malloc64(sz);
            if( aBuf==0 ){
              rc = SQLITE_NOMEM;
            }else{
              FILE *pFile = pCsr->pFile;
              if( pFile==0 ){
                pFile = ((ZipfileTab*)(pCsr->base.pVtab))->pWriteFd;
              }
1128
1129
1130
1131
1132
1133
1134

1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154

1155
1156
1157
1158
1159
1160
1161







+






-







  FILE *pFile,                    /* Read from this file if aBlob==0 */
  ZipfileEOCD *pEOCD              /* Object to populate */
){
  u8 *aRead = pTab->aBuffer;      /* Temporary buffer */
  int nRead;                      /* Bytes to read from file */
  int rc = SQLITE_OK;

  memset(pEOCD, 0, sizeof(ZipfileEOCD));
  if( aBlob==0 ){
    i64 iOff;                     /* Offset to read from */
    i64 szFile;                   /* Total size of file in bytes */
    fseek(pFile, 0, SEEK_END);
    szFile = (i64)ftell(pFile);
    if( szFile==0 ){
      memset(pEOCD, 0, sizeof(ZipfileEOCD));
      return SQLITE_OK;
    }
    nRead = (int)(MIN(szFile, ZIPFILE_BUFFER_SIZE));
    iOff = szFile - nRead;
    rc = zipfileReadData(pFile, aRead, nRead, iOff, &pTab->base.zErrMsg);
  }else{
    nRead = (int)(MIN(nBlob, ZIPFILE_BUFFER_SIZE));
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
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
1286
1287

1288
1289
1290
1291
1292
1293
1294
1295







+
+
+









+



+
+
+
+










-
+







  int argc, sqlite3_value **argv
){
  ZipfileTab *pTab = (ZipfileTab*)cur->pVtab;
  ZipfileCsr *pCsr = (ZipfileCsr*)cur;
  const char *zFile = 0;          /* Zip file to scan */
  int rc = SQLITE_OK;             /* Return Code */
  int bInMemory = 0;              /* True for an in-memory zipfile */

  (void)idxStr;
  (void)argc;

  zipfileResetCursor(pCsr);

  if( pTab->zFile ){
    zFile = pTab->zFile;
  }else if( idxNum==0 ){
    zipfileCursorErr(pCsr, "zipfile() function requires an argument");
    return SQLITE_ERROR;
  }else if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
    static const u8 aEmptyBlob = 0;
    const u8 *aBlob = (const u8*)sqlite3_value_blob(argv[0]);
    int nBlob = sqlite3_value_bytes(argv[0]);
    assert( pTab->pFirstEntry==0 );
    if( aBlob==0 ){
      aBlob = &aEmptyBlob;
      nBlob = 0;
    }
    rc = zipfileLoadDirectory(pTab, aBlob, nBlob);
    pCsr->pFreeEntry = pTab->pFirstEntry;
    pTab->pFirstEntry = pTab->pLastEntry = 0;
    if( rc!=SQLITE_OK ) return rc;
    bInMemory = 1;
  }else{
    zFile = (const char*)sqlite3_value_text(argv[0]);
  }

  if( 0==pTab->pWriteFd && 0==bInMemory ){
    pCsr->pFile = fopen(zFile, "rb");
    pCsr->pFile = zFile ? fopen(zFile, "rb") : 0;
    if( pCsr->pFile==0 ){
      zipfileCursorErr(pCsr, "cannot open file: %s", zFile);
      rc = SQLITE_ERROR;
    }else{
      rc = zipfileReadEOCD(pTab, 0, 0, pCsr->pFile, &pCsr->eocd);
      if( rc==SQLITE_OK ){
        if( pCsr->eocd.nEntry==0 ){
1294
1295
1296
1297
1298
1299
1300

1301
1302
1303
1304
1305
1306
1307
1308
1309
1310

1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336

1337
1338
1339
1340
1341
1342
1343







+










+



-







static int zipfileBestIndex(
  sqlite3_vtab *tab,
  sqlite3_index_info *pIdxInfo
){
  int i;
  int idx = -1;
  int unusable = 0;
  (void)tab;

  for(i=0; i<pIdxInfo->nConstraint; i++){
    const struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i];
    if( pCons->iColumn!=ZIPFILE_F_COLUMN_IDX ) continue;
    if( pCons->usable==0 ){
      unusable = 1;
    }else if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){
      idx = i;
    }
  }
  pIdxInfo->estimatedCost = 1000.0;
  if( idx>=0 ){
    pIdxInfo->aConstraintUsage[idx].argvIndex = 1;
    pIdxInfo->aConstraintUsage[idx].omit = 1;
    pIdxInfo->estimatedCost = 1000.0;
    pIdxInfo->idxNum = 1;
  }else if( unusable ){
    return SQLITE_CONSTRAINT;
  }
  return SQLITE_OK;
}

1429
1430
1431
1432
1433
1434
1435
1436
1437


1438
1439
1440
1441
1442
1443
1444
1445
1446




1447
1448
1449
1450
1451
1452
1453
1451
1452
1453
1454
1455
1456
1457


1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479







-
-
+
+









+
+
+
+








/*
** Both (const char*) arguments point to nul-terminated strings. Argument
** nB is the value of strlen(zB). This function returns 0 if the strings are
** identical, ignoring any trailing '/' character in either path.  */
static int zipfileComparePath(const char *zA, const char *zB, int nB){
  int nA = (int)strlen(zA);
  if( zA[nA-1]=='/' ) nA--;
  if( zB[nB-1]=='/' ) nB--;
  if( nA>0 && zA[nA-1]=='/' ) nA--;
  if( nB>0 && zB[nB-1]=='/' ) nB--;
  if( nA==nB && memcmp(zA, zB, nA)==0 ) return 0;
  return 1;
}

static int zipfileBegin(sqlite3_vtab *pVtab){
  ZipfileTab *pTab = (ZipfileTab*)pVtab;
  int rc = SQLITE_OK;

  assert( pTab->pWriteFd==0 );
  if( pTab->zFile==0 || pTab->zFile[0]==0 ){
    pTab->base.zErrMsg = sqlite3_mprintf("zipfile: missing filename");
    return SQLITE_ERROR;
  }

  /* Open a write fd on the file. Also load the entire central directory
  ** structure into memory. During the transaction any new file data is 
  ** appended to the archive file, but the central directory is accumulated
  ** in main-memory until the transaction is committed.  */
  pTab->pWriteFd = fopen(pTab->zFile, "ab+");
  if( pTab->pWriteFd==0 ){
1471
1472
1473
1474
1475
1476
1477

1478
1479
1480
1481
1482
1483
1484
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511







+







/*
** Return the current time as a 32-bit timestamp in UNIX epoch format (like
** time(2)).
*/
static u32 zipfileTime(void){
  sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
  u32 ret;
  if( pVfs==0 ) return 0;
  if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){
    i64 ms;
    pVfs->xCurrentTimeInt64(pVfs, &ms);
    ret = (u32)((ms/1000) - ((i64)24405875 * 8640));
  }else{
    double day;
    pVfs->xCurrentTime(pVfs, &day);
1538
1539
1540
1541
1542
1543
1544


1545
1546
1547
1548
1549
1550
1551
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580







+
+







  u8 *pFree = 0;                  /* Free this */
  char *zFree = 0;                /* Also free this */
  ZipfileEntry *pOld = 0;
  ZipfileEntry *pOld2 = 0;
  int bUpdate = 0;                /* True for an update that modifies "name" */
  int bIsDir = 0;
  u32 iCrc32 = 0;

  (void)pRowid;

  if( pTab->pWriteFd==0 ){
    rc = zipfileBegin(pVtab);
    if( rc!=SQLITE_OK ) return rc;
  }

  /* If this is a DELETE or UPDATE, find the archive entry to delete. */
1614
1615
1616
1617
1618
1619
1620

1621
1622
1623
1624
1625
1626
1627
1628
1629
1630

1631
1632
1633


1634




1635
1636
1637
1638
1639
1640
1641
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659

1660
1661

1662
1663
1664

1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675







+









-
+

-

+
+
-
+
+
+
+








    if( rc==SQLITE_OK ){
      rc = zipfileGetMode(apVal[3], bIsDir, &mode, &pTab->base.zErrMsg);
    }

    if( rc==SQLITE_OK ){
      zPath = (const char*)sqlite3_value_text(apVal[2]);
      if( zPath==0 ) zPath = "";
      nPath = (int)strlen(zPath);
      mTime = zipfileGetTime(apVal[4]);
    }

    if( rc==SQLITE_OK && bIsDir ){
      /* For a directory, check that the last character in the path is a
      ** '/'. This appears to be required for compatibility with info-zip
      ** (the unzip command on unix). It does not create directories
      ** otherwise.  */
      if( zPath[nPath-1]!='/' ){
      if( nPath<=0 || zPath[nPath-1]!='/' ){
        zFree = sqlite3_mprintf("%s/", zPath);
        if( zFree==0 ){ rc = SQLITE_NOMEM; }
        zPath = (const char*)zFree;
        if( zFree==0 ){
          rc = SQLITE_NOMEM;
        nPath++;
          nPath = 0;
        }else{
          nPath = (int)strlen(zPath);
        }
      }
    }

    /* Check that we're not inserting a duplicate entry -OR- updating an
    ** entry with a path, thereby making it into a duplicate. */
    if( (pOld==0 || bUpdate) && rc==SQLITE_OK ){
      ZipfileEntry *p;
1868
1869
1870
1871
1872
1873
1874

1875
1876
1877
1878
1879
1880
1881
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916







+







static int zipfileFindFunction(
  sqlite3_vtab *pVtab,            /* Virtual table handle */
  int nArg,                       /* Number of SQL function arguments */
  const char *zName,              /* Name of SQL function */
  void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */
  void **ppArg                    /* OUT: User data for *pxFunc */
){
  (void)nArg;
  if( sqlite3_stricmp("zipfile_cds", zName)==0 ){
    *pxFunc = zipfileFunctionCds;
    *ppArg = (void*)pVtab;
    return 1;
  }
  return 0;
}
1893
1894
1895
1896
1897
1898
1899
1900

1901
1902
1903
1904

1905
1906
1907

1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920

1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934

1935
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







-
+



-
+


-
+












-
+







  ZipfileBuffer body;
  ZipfileBuffer cds;
};

static int zipfileBufferGrow(ZipfileBuffer *pBuf, int nByte){
  if( pBuf->n+nByte>pBuf->nAlloc ){
    u8 *aNew;
    int nNew = pBuf->n ? pBuf->n*2 : 512;
    sqlite3_int64 nNew = pBuf->n ? pBuf->n*2 : 512;
    int nReq = pBuf->n + nByte;

    while( nNew<nReq ) nNew = nNew*2;
    aNew = sqlite3_realloc(pBuf->a, nNew);
    aNew = sqlite3_realloc64(pBuf->a, nNew);
    if( aNew==0 ) return SQLITE_NOMEM;
    pBuf->a = aNew;
    pBuf->nAlloc = nNew;
    pBuf->nAlloc = (int)nNew;
  }
  return SQLITE_OK;
}

/*
** xStep() callback for the zipfile() aggregate. This can be called in
** any of the following ways:
**
**   SELECT zipfile(name,data) ...
**   SELECT zipfile(name,mode,mtime,data) ...
**   SELECT zipfile(name,mode,mtime,data,method) ...
*/
void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){
static void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){
  ZipfileCtx *p;                  /* Aggregate function context */
  ZipfileEntry e;                 /* New entry to add to zip archive */

  sqlite3_value *pName = 0;
  sqlite3_value *pMode = 0;
  sqlite3_value *pMtime = 0;
  sqlite3_value *pData = 0;
2020
2021
2022
2023
2024
2025
2026
2027

2028
2029
2030
2031
2032
2033

2034
2035
2036
2037
2038
2039

2040
2041
2042
2043
2044
2045
2046
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







-
+





-
+

-




+







  /* Decode the "mtime" argument. */
  e.mUnixTime = zipfileGetTime(pMtime);

  /* If this is a directory entry, ensure that there is exactly one '/'
  ** at the end of the path. Or, if this is not a directory and the path
  ** ends in '/' it is an error. */
  if( bIsDir==0 ){
    if( zName[nName-1]=='/' ){
    if( nName>0 && zName[nName-1]=='/' ){
      zErr = sqlite3_mprintf("non-directory name must not end with /");
      rc = SQLITE_ERROR;
      goto zipfile_step_out;
    }
  }else{
    if( zName[nName-1]!='/' ){
    if( nName==0 || zName[nName-1]!='/' ){
      zName = zFree = sqlite3_mprintf("%s/", zName);
      nName++;
      if( zName==0 ){
        rc = SQLITE_NOMEM;
        goto zipfile_step_out;
      }
      nName = (int)strlen(zName);
    }else{
      while( nName>1 && zName[nName-2]=='/' ) nName--;
    }
  }

  /* Assemble the ZipfileEntry object for the new zip archive entry */
  e.cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY;
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
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







-
+


-
+












-
+






-
+







  }
  sqlite3_free(zErr);
}

/*
** xFinalize() callback for zipfile aggregate function.
*/
void zipfileFinal(sqlite3_context *pCtx){
static void zipfileFinal(sqlite3_context *pCtx){
  ZipfileCtx *p;
  ZipfileEOCD eocd;
  int nZip;
  sqlite3_int64 nZip;
  u8 *aZip;

  p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx));
  if( p==0 ) return;
  if( p->nEntry>0 ){
    memset(&eocd, 0, sizeof(eocd));
    eocd.nEntry = (u16)p->nEntry;
    eocd.nEntryTotal = (u16)p->nEntry;
    eocd.nSize = p->cds.n;
    eocd.iOffset = p->body.n;

    nZip = p->body.n + p->cds.n + ZIPFILE_EOCD_FIXED_SZ;
    aZip = (u8*)sqlite3_malloc(nZip);
    aZip = (u8*)sqlite3_malloc64(nZip);
    if( aZip==0 ){
      sqlite3_result_error_nomem(pCtx);
    }else{
      memcpy(aZip, p->body.a, p->body.n);
      memcpy(&aZip[p->body.n], p->cds.a, p->cds.n);
      zipfileSerializeEOCD(&eocd, &aZip[p->body.n + p->cds.n]);
      sqlite3_result_blob(pCtx, aZip, nZip, zipfileFree);
      sqlite3_result_blob(pCtx, aZip, (int)nZip, zipfileFree);
    }
  }

  sqlite3_free(p->body.a);
  sqlite3_free(p->cds.a);
}

2145
2146
2147
2148
2149
2150
2151




2152
2153
2154
2155
2156
2157
2158
2159
2160




2161
2162
2163
2164
2165
2166
2167
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210







+
+
+
+









+
+
+
+







    zipfileUpdate,             /* xUpdate */
    zipfileBegin,              /* xBegin */
    0,                         /* xSync */
    zipfileCommit,             /* xCommit */
    zipfileRollback,           /* xRollback */
    zipfileFindFunction,       /* xFindMethod */
    0,                         /* xRename */
    0,                         /* xSavepoint */
    0,                         /* xRelease */
    0,                         /* xRollback */
    0                          /* xShadowName */
  };

  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/rbu.c.

52
53
54
55
56
57
58
59

60
61
62
63
64
65
66
52
53
54
55
56
57
58

59
60
61
62
63
64
65
66







-
+







"\n"
, zArgv0);
  exit(1);
}

void report_default_vfs(){
  sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
  fprintf(stdout, "default vfs is \"%s\"\n", pVfs->zName);
  fprintf(stdout, "default vfs is \"%s\"\n", pVfs ? pVfs->zName : "NULL");
}

void report_rbu_vfs(sqlite3rbu *pRbu){
  sqlite3 *db = sqlite3rbu_db(pRbu, 0);
  if( db ){
    char *zName = 0;
    sqlite3_file_control(db, "main", SQLITE_FCNTL_VFSNAME, &zName);
178
179
180
181
182
183
184







185
186
187
188
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195







+
+
+
+
+
+
+




      fprintf(stdout, "%s", zBuf);
      break;

    default:
      fprintf(stderr, "error=%d: %s\n", rc, zErrmsg);
      break;
  }

  if( nStatStep>0 ){
    sqlite3_int64 nUsed;
    sqlite3_int64 nHighwater;
    sqlite3_status64(SQLITE_STATUS_MEMORY_USED, &nUsed, &nHighwater, 0);
    fprintf(stdout, "memory used=%lld highwater=%lld\n", nUsed, nHighwater);
  }

  sqlite3_free(zErrmsg);
  return (rc==SQLITE_OK || rc==SQLITE_DONE) ? 0 : 1;
}

Changes to ext/rbu/rbu1.test.

1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21













+







# 2014 August 30
#
# 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.
#
#***********************************************************************
#

source [file join [file dirname [info script]] rbu_common.tcl]
ifcapable !rbu { finish_test ; return }
set ::testprefix rbu1

db close
sqlite3_shutdown
sqlite3_config_uri 1

# Create a simple RBU database. That expects to write to a table:
128
129
130
131
132
133
134





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







+
+
+
+
+







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/rbu10.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
1
2
3
4
5
6
7
8
9
10
11
12


13


14
15

16
17
18
19
20
21
22












-
-
+
-
-
+

-







# 2014 August 30
#
# 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.
#
#***********************************************************************
#

if {![info exists testdir]} {
  set testdir [file join [file dirname [info script]] .. .. test]
source [file join [file dirname [info script]] rbu_common.tcl]
}
source $testdir/tester.tcl
ifcapable !rbu { finish_test ; return }
set ::testprefix rbu10


#--------------------------------------------------------------------
# Test that UPDATE commands work even if the input columns are in a 
# different order to the output columns. 
#
do_execsql_test 1.0 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
46
47
48
49
50
51
52
53

54
55
56
57
58
59
60
43
44
45
46
47
48
49

50
51
52
53
54
55
56
57







-
+








#--------------------------------------------------------------------
# Test that the hidden languageid column of an fts4 table can be 
# written.
#
ifcapable fts3 {
  do_execsql_test 2.0 {
    CREATE VIRTUAL TABLE ft USING fts4(a, b, languageid='langid');
    create virtual TABLE ft USING fts4(a, b, languageid='langid');
  }
  do_test 2.1 {
    apply_rbu {
      CREATE TABLE data_ft(a, b, rbu_rowid, langid, rbu_control);
      INSERT INTO data_ft VALUES('a', 'b', 22, 1, 0);    -- insert
      INSERT INTO data_ft VALUES('a', 'b', 23, 10, 0);   -- insert
      INSERT INTO data_ft VALUES('a', 'b', 24, 100, 0);  -- insert

Changes to ext/rbu/rbu11.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16

17
18
19
20
21
22
23
1
2
3
4
5
6
7
8
9
10
11
12


13


14
15
16
17
18
19
20
21












-
-
+
-
-
+







# 2015 February 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.
#
#***********************************************************************
#

if {![info exists testdir]} {
  set testdir [file join [file dirname [info script]] .. .. test]
source [file join [file dirname [info script]] rbu_common.tcl]
}
source $testdir/tester.tcl
ifcapable !rbu { finish_test ; return }
set ::testprefix rbu11


#--------------------------------------------------------------------
# Test that the xAccess() method of an rbu vfs handles queries other
# than SQLITE_ACCESS_EXISTS correctly. The test code below causes
# SQLite to call xAccess(SQLITE_ACCESS_READWRITE) on the directory

Changes to ext/rbu/rbu12.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16

17
18
19
20
21
22
23
1
2
3
4
5
6
7
8
9
10
11
12


13


14
15
16
17
18
19
20
21












-
-
+
-
-
+







# 2015 February 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.
#
#***********************************************************************
#

if {![info exists testdir]} {
  set testdir [file join [file dirname [info script]] .. .. test]
source [file join [file dirname [info script]] rbu_common.tcl]
}
source $testdir/tester.tcl
ifcapable !rbu { finish_test ; return }
source $testdir/lock_common.tcl
set ::testprefix rbu12

set setup_sql {
  DROP TABLE IF EXISTS xx;
  DROP TABLE IF EXISTS xy;
  CREATE TABLE xx(a, b, c PRIMARY KEY);

Changes to ext/rbu/rbu13.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







-
-
+
-
-
+







#
#***********************************************************************
#
# Test an RBU update that features lots of different rbu_control strings
# for UPDATE statements. This tests RBU's internal UPDATE statement cache.
#

if {![info exists testdir]} {
  set testdir [file join [file dirname [info script]] .. .. test]
source [file join [file dirname [info script]] rbu_common.tcl]
}
source $testdir/tester.tcl
ifcapable !rbu { finish_test ; return }
source $testdir/lock_common.tcl
set ::testprefix rbu13

do_execsql_test 1.0 {
  CREATE TABLE t1(a PRIMARY KEY, b, c, d, e, f, g, h);
  WITH ii(i) AS (SELECT 0 UNION ALL SELECT i+1 FROM ii WHERE i<127)
  INSERT INTO t1 SELECT i, 0, 0, 0, 0, 0, 0, 0 FROM ii;

Changes to ext/rbu/rbu14.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







-
-
+
-
-
+







#
#***********************************************************************
#
# Test that an RBU data_xxx table may be a view instead of a regular
# table.
#

if {![info exists testdir]} {
  set testdir [file join [file dirname [info script]] .. .. test]
source [file join [file dirname [info script]] rbu_common.tcl]
}
source $testdir/tester.tcl
ifcapable !rbu { finish_test ; return }
source $testdir/lock_common.tcl
set ::testprefix rbu14


foreach {tn schema} {
  1 {
    CREATE TABLE t1(a PRIMARY KEY, b, c);

Changes to ext/rbu/rbu3.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16

17
18
19
20
21
22
23
1
2
3
4
5
6
7
8
9
10
11
12


13


14
15
16
17
18
19
20
21












-
-
+
-
-
+







# 2014 August 30
#
# 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.
#
#***********************************************************************
#

if {![info exists testdir]} {
  set testdir [file join [file dirname [info script]] .. .. test]
source [file join [file dirname [info script]] rbu_common.tcl]
}
source $testdir/tester.tcl
ifcapable !rbu { finish_test ; return }
set ::testprefix rbu3


# Run the RBU in file $rbu on target database $target until completion.
#
proc run_rbu {target rbu} {
  sqlite3rbu rbu $target $rbu

Changes to ext/rbu/rbu5.test.

9
10
11
12
13
14
15

16
17
18
19
20
21
22
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23







+







#
#***********************************************************************
#
# Test some properties of the pager_rbu_mode and rbu_mode pragmas.
#

source [file join [file dirname [info script]] rbu_common.tcl]
ifcapable !rbu { finish_test ; return }
set ::testprefix rbu5


# Return a list of the primary key columns for table $tbl in the database
# opened by database handle $db.
#
proc pkcols {db tbl} {

Changes to ext/rbu/rbu6.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







-
-
+
-
-
+







#
#***********************************************************************
#
# This file contains tests for the RBU module. Specifically, it tests the
# outcome of some other client writing to the database while an RBU update
# is being applied.

if {![info exists testdir]} {
  set testdir [file join [file dirname [info script]] .. .. test]
source [file join [file dirname [info script]] rbu_common.tcl]
}
source $testdir/tester.tcl
ifcapable !rbu { finish_test ; return }
set ::testprefix rbu6

proc setup_test {} {
  reset_db
  execsql {
    CREATE TABLE t1(a INTEGER PRIMARY KEY, b UNIQUE);
    CREATE TABLE t2(a INTEGER PRIMARY KEY, b UNIQUE);

Changes to ext/rbu/rbu7.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







-
-
+
-
-
+







#
#***********************************************************************
#
# This file contains tests for the RBU module.
#


if {![info exists testdir]} {
  set testdir [file join [file dirname [info script]] .. .. test]
source [file join [file dirname [info script]] rbu_common.tcl]
}
source $testdir/tester.tcl
ifcapable !rbu { finish_test ; return }
set ::testprefix rbu7

# Test index:
#
#   1.*: That affinities are correctly applied to values within the 
#        RBU database.
#

Changes to ext/rbu/rbu8.test.

8
9
10
11
12
13
14
15
16

17
18

19
20
21
22
23
24
25
8
9
10
11
12
13
14


15


16
17
18
19
20
21
22
23







-
-
+
-
-
+







#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# Test the rbu_delta() feature.
#

if {![info exists testdir]} {
  set testdir [file join [file dirname [info script]] .. .. test]
source [file join [file dirname [info script]] rbu_common.tcl]
}
source $testdir/tester.tcl
ifcapable !rbu { finish_test ; return }
set ::testprefix rbu8

do_execsql_test 1.0 {
  CREATE TABLE t1(x, y PRIMARY KEY, z);
  INSERT INTO t1 VALUES(NULL, 1, 'one');
  INSERT INTO t1 VALUES(NULL, 2, 'two');
  INSERT INTO t1 VALUES(NULL, 3, 'three');

Changes to ext/rbu/rbu9.test.

8
9
10
11
12
13
14
15
16

17
18

19
20
21
22
23
24
25
8
9
10
11
12
13
14


15


16
17
18
19
20
21
22
23







-
-
+
-
-
+







#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# Test RBU with virtual tables. And tables with no PRIMARY KEY declarations.
#

if {![info exists testdir]} {
  set testdir [file join [file dirname [info script]] .. .. test]
source [file join [file dirname [info script]] rbu_common.tcl]
}
source $testdir/tester.tcl
ifcapable !rbu { finish_test ; return }
set ::testprefix rbu9

ifcapable !fts3 {
  finish_test
  return
}

Changes to ext/rbu/rbuA.test.

10
11
12
13
14
15
16
17
18

19
20

21
22
23
24
25
26
27
10
11
12
13
14
15
16


17


18
19
20
21
22
23
24
25







-
-
+
-
-
+







#***********************************************************************
#
# This file contains tests for the RBU module. More specifically, it
# contains tests to ensure that it is an error to attempt to update
# a wal mode database via RBU.
#

if {![info exists testdir]} {
  set testdir [file join [file dirname [info script]] .. .. test]
source [file join [file dirname [info script]] rbu_common.tcl]
}
source $testdir/tester.tcl
ifcapable !rbu { finish_test ; return }
set ::testprefix rbuA

set db_sql {
  CREATE TABLE t1(a PRIMARY KEY, b, c);
}
set rbu_sql {
  CREATE TABLE data_t1(a, b, c, rbu_control);

Changes to ext/rbu/rbuB.test.

8
9
10
11
12
13
14

15
16
17
18
19
20
21
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22







+







#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
#

source [file join [file dirname [info script]] rbu_common.tcl]
ifcapable !rbu { finish_test ; return }
set ::testprefix rbuB

db close
sqlite3_shutdown
test_sqlite3_log xLog
reset_db

44
45
46
47
48
49
50
51

52
53
54
55
56
57
58
59
60
61
45
46
47
48
49
50
51

52
53
54
55
56
57
58
59
60
61
62







-
+










proc xLog {err msg} { lappend ::errlog $err }
do_test 1.2 {
  run_rbu test.db rbu.db
} {SQLITE_DONE}

do_test 1.3 {
  set ::errlog
} {SQLITE_NOTICE_RECOVER_WAL SQLITE_INTERNAL}
} {SQLITE_NOTICE_RECOVER_WAL SQLITE_NOTICE_RBU}

do_execsql_test 1.4 {
  SELECT * FROM t1
} {1 2 3 4 5 6 7 8 9}

db close
sqlite3_shutdown
test_sqlite3_log 
sqlite3_initialize
finish_test

Changes to ext/rbu/rbuC.test.

9
10
11
12
13
14
15

16
17
18
19
20
21
22
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23







+







#
#***********************************************************************
# Tests for RBU focused on the REPLACE operation (rbu_control column
# contains integer value 2).
#

source [file join [file dirname [info script]] rbu_common.tcl]
ifcapable !rbu { finish_test ; return }
set ::testprefix rbuC

#-------------------------------------------------------------------------
# This test is actually of an UPDATE directive. Just to establish that
# these work with UNIQUE indexes before preceding to REPLACE.
#
do_execsql_test 1.0 {

Changes to ext/rbu/rbu_common.tcl.

85
86
87
88
89
90
91
92
93


94
95

96
97
98
99
100
101

102
103
104
105
106
107
108
85
86
87
88
89
90
91


92
93
94

95
96
97
98
99
100

101
102
103
104
105
106
107
108







-
-
+
+

-
+





-
+







  }
  set rc
}

proc do_rbu_vacuum_test {tn step {statedb state.db}} {
  forcedelete $statedb
  if {$statedb=="" && $step==1} breakpoint
  uplevel [list do_test $tn.1 [string map [list %state% $statedb] {
    if {$step==0} { sqlite3rbu_vacuum rbu test.db {%state%}}
  uplevel [list do_test $tn.1 [string map [list %state% $statedb %step% $step] {
    if {%step%==0} { sqlite3rbu_vacuum rbu test.db {%state%}}
    while 1 {
      if {$step==1} { sqlite3rbu_vacuum rbu test.db {%state%}}
      if {%step%==1} { sqlite3rbu_vacuum rbu test.db {%state%}}
      set state [rbu state]
      check_prestep_state test.db $state
      set rc [rbu step]
      check_poststep_state $rc test.db $state
      if {$rc!="SQLITE_OK"} break
      if {$step==1} { rbu close }
      if {%step%==1} { rbu close }
    }
    rbu close
  }] {SQLITE_DONE}]

  uplevel [list do_execsql_test $tn.2 {
    PRAGMA integrity_check
  } ok]

Added ext/rbu/rbubusy.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2014 August 30
#
# 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.
#
#***********************************************************************
#
#

source [file join [file dirname [info script]] rbu_common.tcl]
ifcapable !rbu { finish_test ; return }
set ::testprefix rbubusy

db close
sqlite3_shutdown
test_sqlite3_log xLog
reset_db

set db_sql {
  CREATE TABLE t1(a PRIMARY KEY, b, c);
  INSERT INTO t1 VALUES(1000, 2000, 3000);
}

set rbu_sql {
  CREATE TABLE data_t1(a, b, c, rbu_control);
  INSERT INTO data_t1 VALUES(1, 2, 3, 0);
  INSERT INTO data_t1 VALUES(4, 5, 6, 0);
  INSERT INTO data_t1 VALUES(7, 8, 9, 0);
}

do_test 1.1 {
  forcedelete rbu.db
  sqlite3 rbu rbu.db
  rbu eval $rbu_sql
  rbu close

  db eval $db_sql
} {}

do_execsql_test 1.2 {
  BEGIN;
    SELECT * FROM t1
} {1000 2000 3000}

do_test 1.3 {
  sqlite3rbu rbu test.db rbu.db
  rbu step
} {SQLITE_OK}

do_test 1.4 {
  while 1 {
    set rc [rbu step]
    if {$rc!="SQLITE_OK"} break
  }
  set rc
} {SQLITE_BUSY}

do_test 1.5 {
  rbu step
} {SQLITE_BUSY}

do_test 1.6 {
  db eval COMMIT
  rbu step
} {SQLITE_BUSY}
catch { rbu close }

do_test 1.7 {
  sqlite3rbu rbu test.db rbu.db
  while 1 {
    set rc [rbu step]
    if {$rc!="SQLITE_OK"} break
  }
  set rc
} {SQLITE_DONE}

rbu close

db close
sqlite3_shutdown
test_sqlite3_log 
sqlite3_initialize
finish_test

Changes to ext/rbu/rbucollate.test.

1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21













+







# 2018 March 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.
#
#***********************************************************************
#

source [file join [file dirname [info script]] rbu_common.tcl]
ifcapable !rbu { finish_test ; return }
set ::testprefix rbucollate

ifcapable !icu_collations {
  finish_test
  return
}

Changes to ext/rbu/rbucrash.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16

17
18
19
20
21
22
23
1
2
3
4
5
6
7
8
9
10
11
12


13


14
15
16
17
18
19
20
21












-
-
+
-
-
+







# 2014 October 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.
#
#***********************************************************************
#

if {![info exists testdir]} {
  set testdir [file join [file dirname [info script]] .. .. test]
source [file join [file dirname [info script]] rbu_common.tcl]
}
source $testdir/tester.tcl
ifcapable !rbu { finish_test ; return }
set ::testprefix rbucrash

db close
forcedelete test.db-oal rbu.db
sqlite3_shutdown
sqlite3_config_uri 1
reset_db

Changes to ext/rbu/rbucrash2.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16

17
18
19
20
21
22
23
1
2
3
4
5
6
7
8
9
10
11
12


13


14
15
16
17
18
19
20
21












-
-
+
-
-
+







# 2017 March 02
#
# 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.
#
#***********************************************************************
#

if {![info exists testdir]} {
  set testdir [file join [file dirname [info script]] .. .. test]
source [file join [file dirname [info script]] rbu_common.tcl]
}
source $testdir/tester.tcl
ifcapable !rbu { finish_test ; return }
set ::testprefix rbucrash2

db close
forcedelete test.db-oal rbu.db
sqlite3_shutdown
sqlite3_config_uri 1
reset_db

Changes to ext/rbu/rbudiff.test.

8
9
10
11
12
13
14
15
16
17
18



19
20
21
22
23
24
25
8
9
10
11
12
13
14




15
16
17
18
19
20
21
22
23
24







-
-
-
-
+
+
+







#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# Tests for the [sqldiff --rbu] command.
#
#
if {![info exists testdir]} {
  set testdir [file join [file dirname [info script]] .. .. test]
}
source $testdir/tester.tcl

source [file join [file dirname [info script]] rbu_common.tcl]
ifcapable !rbu { finish_test ; return }
set testprefix rbudiff

set PROG [test_find_sqldiff]
db close

proc get_rbudiff_sql {db1 db2} {
  exec $::PROG --rbu $db1 $db2
260
261
262
263
264
265
266








267
268
269
270
271
272
273
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280







+
+
+
+
+
+
+
+







    }

    3 {
      creAte    virTUal
tablE t1 USING FTs5(c);
      INSERT INTO t1 VALUES('a b c');
      INSERT INTO t1 VALUES('a b c');
    } {
      DELETE FROM t1 WHERE rowid = 1;
      INSERT INTO t1 VALUES('a b c');
    }
    4 {
      creAte virTUal tablE	t1	USING FTs5(c);
      INSERT INTO t1 VALUES('a b c');
      INSERT INTO t1 VALUES('a b c');
    } {
      DELETE FROM t1 WHERE rowid = 1;
      INSERT INTO t1 VALUES('a b c');
    }

  } {
    forcedelete test.db test.db2

Changes to ext/rbu/rbudor.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







-
-
+
-
-
+







#
#***********************************************************************
#
# This test file focuses on interactions between RBU and the feature
# enabled by SQLITE_DIRECT_OVERFLOW_READ - Direct Overflow Read.
#

if {![info exists testdir]} {
  set testdir [file join [file dirname [info script]] .. .. test]
source [file join [file dirname [info script]] rbu_common.tcl]
}
source $testdir/tester.tcl
ifcapable !rbu { finish_test ; return }
set ::testprefix rbudor

set bigA [string repeat a 5000]
set bigB [string repeat b 5000]
do_execsql_test 1.0 {
  PRAGMA page_size = 1024;
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b BLOB);

Added ext/rbu/rbuexlock.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
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2021 November 06
#
# 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.
#
#***********************************************************************
#

source [file join [file dirname [info script]] rbu_common.tcl]
ifcapable !rbu { finish_test ; return }
set ::testprefix rbuexlock

db close
sqlite3_shutdown
sqlite3_config_uri 1

# Create a simple RBU database. That expects to write to a table:
#
#   CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
#
proc create_rbu {filename} {
  forcedelete $filename
  sqlite3 rbu1 $filename  
  rbu1 eval {
    CREATE TABLE data_t1(a, b, c, rbu_control);
    INSERT INTO data_t1 VALUES(10, random(), random(), 0);
    INSERT INTO data_t1 VALUES(20, random(), random(), 0);
    INSERT INTO data_t1 VALUES(30, random(), random(), 0);
    INSERT INTO data_t1 VALUES(40, random(), random(), 0);
    INSERT INTO data_t1 VALUES(50, random(), random(), 0);
    INSERT INTO data_t1 VALUES(60, random(), random(), 0);
    INSERT INTO data_t1 VALUES(70, random(), random(), 0);
    INSERT INTO data_t1 VALUES(80, random(), random(), 0);
  }
  rbu1 close
  return $filename
}

reset_db

do_execsql_test 1.0 {
  CREATE TABLE t1(a PRIMARY KEY, b INT, c INT);
  CREATE INDEX t1b ON t1(b);
  CREATE INDEX t1c ON t1(c);
  INSERT INTO t1 VALUES(1, 2, 3);
}
create_rbu rbu1.db

do_test 1.1.0 {
  sqlite3rbu rbu file:test.db?rbu_exclusive_checkpoint=1 rbu1.db
  rbu step
} SQLITE_OK
do_catchsql_test 1.1.1 { SELECT * FROM t1 } {0 {1 2 3}}

do_test 1.2.0 {
  for {set ii 0} {$ii < 10} {incr ii} {
    rbu step
  }
  rbu step
} SQLITE_OK
do_catchsql_test 1.2.1 { SELECT * FROM t1 } {0 {1 2 3}}
do_test 1.2.2 {
  db eval {PRAGMA journal_mode}
} {delete}

do_test 1.3.0 {
  while {[file exists test.db-wal]==0} {
    rbu step
  }
} {}
do_catchsql_test 1.3.1 { SELECT * FROM t1 } {1 {database is locked}}
do_test 1.3.2 {
  db eval {PRAGMA journal_mode}
} {delete}


do_test 1.4.0 {
  rbu step
} SQLITE_OK
do_catchsql_test 1.4.1 { SELECT * FROM t1 } {1 {database is locked}}
do_test 1.4.2 {
  db eval {PRAGMA journal_mode}
} {delete}


rbu close

do_test 1.5.0 {
  file exists test.db-wal
} {1}
do_test 1.5.1 {
  sqlite3rbu rbu file:test.db?rbu_exclusive_checkpoint=1 rbu1.db
  file exists test.db-wal
} 1
do_catchsql_test 1.5.2 { SELECT * FROM t1 } {1 {database is locked}}
do_test 1.5.2 {
  db eval {PRAGMA journal_mode}
} {delete}


do_test 1.6.0 {
  rbu step
} SQLITE_OK
do_catchsql_test 1.6.1 { SELECT * FROM t1 } {1 {database is locked}}
do_test 1.6.2 {
  db eval {PRAGMA journal_mode}
} {delete}

do_test 1.7.0 {
  while {[rbu step]=="SQLITE_OK"} {}
  rbu close
} SQLITE_DONE
do_catchsql_test 1.7.2 { SELECT count(*) FROM t1 } {0 9}
do_test 1.7.2 {
  db eval {PRAGMA journal_mode}
} {delete}

reset_db
do_execsql_test 2.0 {
  CREATE TABLE t1(a PRIMARY KEY, b INT, c INT);
  CREATE INDEX t1b ON t1(b);
  CREATE INDEX t1c ON t1(c);
  INSERT INTO t1 VALUES(1, 2, 3);
}
create_rbu rbu1.db

do_test 2.1.0 {
  sqlite3rbu rbu file:test.db?rbu_exclusive_checkpoint=0 rbu1.db
  rbu step
} SQLITE_OK
do_catchsql_test 2.1.1 { SELECT * FROM t1 } {0 {1 2 3}}

do_test 2.2.0 {
  for {set ii 0} {$ii < 10} {incr ii} {
    rbu step
  }
  rbu step
} SQLITE_OK
do_catchsql_test 2.2.1 { SELECT * FROM t1 } {0 {1 2 3}}

do_test 2.3.0 {
  while {[file exists test.db-wal]==0} {
    rbu step
  }
} {}
do_test 2.3.1 {
  llength [db eval {SELECT * FROM t1}]
} {27}
do_test 2.3.2 {
  db eval {PRAGMA journal_mode}
} {wal}

do_test 2.4.0 {
  rbu step
} SQLITE_OK
do_test 2.4.1 {
  llength [db eval  {SELECT * FROM t1}]
} {27}
do_test 2.4.2 {
  db eval {PRAGMA journal_mode}
} {wal}

rbu close

do_test 2.5.0 {
  db eval {PRAGMA journal_mode}
} {wal}
do_execsql_test 2.5.1 {
  DELETE FROM t1;
} {}

create_rbu rbu1.db
do_test 3.1.0 {
  sqlite3rbu rbu file:test.db?rbu_exclusive_checkpoint=0 rbu1.db
  rbu step
} SQLITE_ERROR

do_test 3.1.1 {
  set rc [catch {rbu close} msg]
  lappend rc $msg
} {1 {SQLITE_ERROR - cannot update wal mode database}}
db eval {PRAGMA journal_mode=DELETE}

create_rbu rbu1.db
do_test 3.2.0 {
  sqlite3rbu rbu file:test.db?rbu_exclusive_checkpoint=0 rbu1.db
  rbu step
} SQLITE_OK

do_test 3.3.1 {
  set rc [catch {rbu close} msg]
  lappend rc $msg
} {0 SQLITE_OK}

db close
create_rbu rbu1.db
do_test 3.4.0 {
  sqlite3rbu rbu file:test.db?rbu_exclusive_checkpoint=0 rbu1.db
  rbu step
} SQLITE_OK
rbu close


finish_test

Added ext/rbu/rbuexpr.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2014 August 30
#
# 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.
#
#***********************************************************************
#

source [file join [file dirname [info script]] rbu_common.tcl]
ifcapable !rbu { finish_test ; return }
set ::testprefix rbuexpr

db close
sqlite3_shutdown
sqlite3_config_uri 1

sqlite3 db test.db

do_execsql_test 1.0 {
  CREATE TABLE t1(a, b, c PRIMARY KEY);
  CREATE INDEX i1 ON t1(a, null, b+1);
  CREATE INDEX i2 ON t1(a+1, b+1, c+1);

  INSERT INTO t1 VALUES(1, 2, 3);
  INSERT INTO t1 VALUES(4, 5, 6);
  INSERT INTO t1 VALUES(7, 8, 9);
  INSERT INTO t1 VALUES(10, 11, 12);

  PRAGMA integrity_check;
} {ok}

forcedelete rbu.db
sqlite3 db2 rbu.db
do_execsql_test -db db2 1.1 {
  CREATE TABLE data_t1(a, b, c, rbu_control);
  INSERT INTO data_t1 VALUES(13, 14, 15, 0);
  INSERT INTO data_t1 VALUES(NULL, NULL, 6, 1);
  INSERT INTO data_t1 VALUES(NULL, 'three', 3, '.x.');
}
db2 close
db close

do_test 1.2 {
  run_rbu test.db rbu.db
} {SQLITE_DONE}

sqlite3 db test.db

do_execsql_test 1.3 {
  SELECT * FROM t1 WHERE a=4;
}

integrity_check 1.4

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 2.0 {
  CREATE TABLE t1(c1, c2, c3, i INTEGER PRIMARY KEY);
  INSERT INTO t1 VALUES('one', 'one', 'one', 1);
  INSERT INTO t1 VALUES('two', 'two', 'two', 2);
  INSERT INTO t1 VALUES('three', 'three', 'three', 3);
  INSERT INTO t1 VALUES('four', 'four', 'four', 4);

  CREATE INDEX i1 ON t1( substr(c1, 1, 2) );
  CREATE INDEX i2 ON t1( c1 || c2 || c3 );
  CREATE INDEX i3 ON t1( length(c1) + length(c2) - 1, c3||i );
}

forcedelete rbu.db
sqlite3 db2 rbu.db
do_execsql_test -db db2 2.1 {
  CREATE TABLE data_t1(c1, c2, c3, i, rbu_control);
  INSERT INTO data_t1 VALUES(NULL, NULL, NULL, 2, 1);
  INSERT INTO data_t1 VALUES('thirty', NULL, NULL, 3, 'xx..');
  INSERT INTO data_t1 VALUES('five', 'five', 'five', 5, 0);
}
db2 close

db close

do_test 2.2 {
  run_rbu test.db rbu.db
} {SQLITE_DONE}

sqlite3 db test.db
integrity_check 2.3

finish_test

Changes to ext/rbu/rbufault.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16

17
18
19
20
21
22
23
1
2
3
4
5
6
7
8
9
10
11
12


13


14
15
16
17
18
19
20
21












-
-
+
-
-
+







# 2014 October 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.
#
#***********************************************************************
#

if {![info exists testdir]} {
  set testdir [file join [file dirname [info script]] .. .. test]
source [file join [file dirname [info script]] rbu_common.tcl]
}
source $testdir/tester.tcl
ifcapable !rbu { finish_test ; return }
source $testdir/malloc_common.tcl
set ::testprefix rbufault

proc copy_if_exists {src target} {
  if {[file exists $src]} {
    forcecopy $src $target
  } else {

Changes to ext/rbu/rbufault2.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16

17
18
19
20
21
22
23
1
2
3
4
5
6
7
8
9
10
11
12


13


14
15
16
17
18
19
20
21












-
-
+
-
-
+







# 2014 October 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.
#
#***********************************************************************
#

if {![info exists testdir]} {
  set testdir [file join [file dirname [info script]] .. .. test]
source [file join [file dirname [info script]] rbu_common.tcl]
}
source $testdir/tester.tcl
ifcapable !rbu { finish_test ; return }
source $testdir/malloc_common.tcl
set ::testprefix rbufault2

forcedelete rbu.db
do_execsql_test 1.0 {
  CREATE TABLE target(x UNIQUE, y, z, PRIMARY KEY(y));
  INSERT INTO target VALUES(1, 2, 3);
48
49
50
51
52
53
54









55
56
57
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64







+
+
+
+
+
+
+
+
+



      {1 SQLITE_CONSTRAINT} \
      {1 SQLITE_NOMEM} \
      {1 {SQLITE_NOMEM - unable to open a temporary database file for storing temporary tables}} \
      {1 {SQLITE_NOMEM - out of memory}} 
}


sqlite3rbu_create_vfs -default rbu ""
sqlite3 db test.db
set ::vfsname [file_control_vfsname db]
do_faultsim_test 2 -faults oom* -prep {
} -body {
  file_control_vfsname db
} 
db close
sqlite3rbu_destroy_vfs rbu


finish_test

Changes to ext/rbu/rbufault3.test.

9
10
11
12
13
14
15

16
17
18
19
20
21
22
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23







+







#
#***********************************************************************
#
# This file contains fault injection tests for RBU vacuum operations.
#

source [file join [file dirname [info script]] rbu_common.tcl]
ifcapable !rbu { finish_test ; return }
source $testdir/malloc_common.tcl
set ::testprefix rbufault3

foreach {fault errlist} {
  oom-* {
    {1 SQLITE_NOMEM}
    {1 SQLITE_IOERR_NOMEM}
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
80
81
82
83
84
85
86

87
88
89
90
91
92
93

94
95
96







-







-



  sqlite3rbu_vacuum rbu test.db test.db2
  rbu step
  rbu close
  faultsim_save_and_close

  do_faultsim_test 3 -faults $fault -prep {
    faultsim_restore_and_reopen
    forcedelete test.db2
  } -body {
    sqlite3rbu_vacuum rbu test.db test.db2
    rbu step
    rbu close
  } -test {
    eval [list faultsim_test_result {0 SQLITE_OK} {*}$::errlist]
  }

}

finish_test

Changes to ext/rbu/rbufault4.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16

17
18
19
20
21
22
23
1
2
3
4
5
6
7
8
9
10
11
12


13


14
15
16
17
18
19
20
21












-
-
+
-
-
+







# 2014 October 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.
#
#***********************************************************************
#

if {![info exists testdir]} {
  set testdir [file join [file dirname [info script]] .. .. test]
source [file join [file dirname [info script]] rbu_common.tcl]
}
source $testdir/tester.tcl
ifcapable !rbu { finish_test ; return }
source $testdir/malloc_common.tcl
set ::testprefix rbufault4

for {set tn 1} {1} {incr tn} {
  reset_db
  do_execsql_test 1.0 {
    CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);

Changes to ext/rbu/rbufts.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







-
-
+
-
-
+







#
#***********************************************************************
#
# This file contains tests for the RBU module. More specifically, it
# contains tests to ensure that RBU works with FTS tables.
#

if {![info exists testdir]} {
  set testdir [file join [file dirname [info script]] .. .. test]
source [file join [file dirname [info script]] rbu_common.tcl]
}
source $testdir/tester.tcl
ifcapable !rbu { finish_test ; return }
set ::testprefix rbufts

ifcapable !fts3 {
  finish_test
  return
}

Added ext/rbu/rbumisc.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2014 August 30
#
# 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.
#
#***********************************************************************
#

source [file join [file dirname [info script]] rbu_common.tcl]
ifcapable !rbu { finish_test ; return }
set ::testprefix rbumisc

db close
sqlite3_shutdown
sqlite3_config_uri 1
reset_db

proc populate_rbu_db {} {
  forcedelete rbu.db
  sqlite3 rbu rbu.db
  rbu eval {
    CREATE TABLE data_x1(a, b, c, rbu_control);
    INSERT INTO data_x1 VALUES(1, 1, 1, 0);
    INSERT INTO data_x1 VALUES(2, 2, 2, 0);

    CREATE TABLE dat(a, b, c, rbu_control);
    CREATE TABLE "data x1"(a, b, c, rbu_control);
    CREATE TABLE datax1(a, b, c, rbu_control);
    CREATE TABLE data_(a, b, c, rbu_control);

    INSERT INTO "data x1" VALUES(3, 3, 3, 0);
    INSERT INTO datax1 VALUES(3, 3, 3, 0);
    INSERT INTO data_ VALUES(3, 3, 3, 0);
    INSERT INTO dat VALUES(3, 3, 3, 0);
  }
  rbu close
}

#-------------------------------------------------------------------------
# Ensure that RBU is not confused by oddly named tables in an RBU 
# database.
#
do_execsql_test 1.0 {
  CREATE TABLE x1(a, b, c INTEGER PRIMARY KEY);
}
do_test 1.1 {
  populate_rbu_db
} {}

do_test 1.2 {
  step_rbu test.db rbu.db
  db eval { SELECT * FROM x1 }
} {1 1 1 2 2 2}

do_test 1.3 {
  db eval { DELETE FROM x1 }
  sqlite3 rbu rbu.db
  rbu eval { DELETE FROM rbu_state }
  rbu close
  step_rbu test.db rbu.db
  db eval { SELECT * FROM x1 }
} {1 1 1 2 2 2}

do_test 1.4 {
  db eval { DELETE FROM x1 }
  populate_rbu_db

  sqlite3rbu rbu test.db rbu.db
  rbu step
  rbu step
  rbu close

  forcecopy test.db-oal test.db-wal
  sqlite3rbu rbu test.db rbu.db
  rbu step
  list [catch { rbu close } msg] $msg
} {1 {SQLITE_ERROR - cannot update wal mode database}}

#-------------------------------------------------------------------------
# Test the effect of a wal file appearing after the target database has
# been opened, but before it has been locked.
#
catch { db close }
testvfs tvfs -default 1

for {set N 1} {$N < 10} {incr N} {
  reset_db
  populate_rbu_db
  do_execsql_test 2.$N.0 {
    CREATE TABLE x1(a, b, c INTEGER PRIMARY KEY);
  }
  
  set nAccessCnt 0
  do_test 2.$N.1 {
    sqlite3rbu rbu test.db rbu.db
    rbu step
    rbu step
    rbu close
  } {SQLITE_OK}
  
  tvfs script xAccess
  tvfs filter xAccess
  set nAccessCnt 0
  proc xAccess {method file args} {
    global nAccessCnt
    if {[file tail $file]=="test.db-wal"} {
      incr nAccessCnt -1
      if {$nAccessCnt==0} {
        set fd [open test.db-wal w]
        puts -nonewline $fd [string repeat 0 2000]
        close $fd
      }
    }
    return SQLITE_OK
  }

  foreach r {
     {1 {SQLITE_ERROR - cannot update wal mode database}}
     {0 SQLITE_OK}
     {1 {SQLITE_CANTOPEN - unable to open database file}}
  } {
    set RES($r) 1
  }
  do_test 2.$N.2 {
    set ::nAccessCnt $N
    set res [list [catch {
      sqlite3rbu rbu test.db rbu.db
      rbu step
      rbu close
    } msg ] $msg]
    set RES($res)
  } {1}
  catch {rbu close}
}
catch {db close}
catch {tvfs delete}

#-------------------------------------------------------------------------
testvfs tvfs -default 1
reset_db
populate_rbu_db
do_execsql_test 3.0 {
  CREATE TABLE x1(a, b, c INTEGER PRIMARY KEY);
}
  
tvfs script xFileControl
tvfs filter xFileControl

proc xFileControl {method file verb args} {
  if {$verb=="ZIPVFS" && [info exists ::zipvfs_filecontrol]} {
    return $::zipvfs_filecontrol 
  }
  return "SQLITE_NOTFOUND"
}

breakpoint
foreach {tn ret err} {
  1 SQLITE_OK           0
  2 SQLITE_ERROR        1
  3 SQLITE_NOTFOUND     0
  4 SQLITE_OMIT         1
} {
  set ::zipvfs_filecontrol $ret
  do_test 3.$tn.1 {
    catch {
      sqlite3rbu rbu test.db rbu.db
      rbu step
      rbu close
    }
  } $err
}
catch {db close}
catch {tvfs delete}

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

finish_test

Changes to ext/rbu/rbumulti.test.

1
2
3
4
5
6
7
8
9
10


11
12
13
14
15
16

17
18
19
20
21
22
23
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










+
+






+







# 2018 January 11
#
# 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.
#
#***********************************************************************
#
# TESTRUNNER: slow
#
# This file contains tests of multiple RBU operations running
# concurrently within the same process. 
#

source [file join [file dirname [info script]] rbu_common.tcl]
ifcapable !rbu { finish_test ; return }
set ::testprefix rbumulti

db close
sqlite3_shutdown
sqlite3_config_uri 1

autoinstall_test_functions

Added ext/rbu/rbupartial.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019 April 11
#
# 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.
#
#***********************************************************************
#

source [file join [file dirname [info script]] rbu_common.tcl]
ifcapable !rbu { finish_test ; return }
set ::testprefix rbupartial

db close
sqlite3_shutdown
sqlite3_config_uri 1

foreach {tn without_rowid a b c d} {
  1 ""              a b c d
  2 "WITHOUT ROWID" aaa bbb ccc ddd
  3 "WITHOUT ROWID" "\"hello\"" {"one'two"}  {[c]} ddd
  4 "WITHOUT ROWID" {`a b`} {"one'two"}  {[c c c]} ddd
  5 "" a b c {"d""d"}
  6 "" {'one''two'} b {"c""c"} {"d""d"}
} {
  eval [string map [list \
    %WITHOUT_ROWID% $without_rowid %A% $a %B% $b %C% $c %D% $d
  ] {
  reset_db
  do_execsql_test $tn.1.0 {
    CREATE TABLE t1(%A% PRIMARY KEY, %B%, %C%, %D%) %WITHOUT_ROWID% ;
    CREATE INDEX i1b  ON t1(%B%);
    CREATE INDEX i1b2 ON t1(%B%) WHERE %C%<5;
    CREATE INDEX i1b3 ON t1(%B%) WHERE %C%>=5;

    CREATE INDEX i1c  ON t1(%C%);
    CREATE INDEX i1c2 ON t1(%C%) WHERE %C% IS NULL;
    CREATE INDEX i1c3 ON t1(%C%) WHERE %C% IS NOT NULL;

    CREATE INDEX i1c4 ON t1(%C%) WHERE %D% < 'd';
    CREATE INDEX i1c5 ON t1(
        %C%                   -- for (c = ... expressions
    ) WHERE %D% < 'd';
    CREATE INDEX i1c6 ON t1(
        %C% /* Again, for (c=... expr */, %D%
    ) WHERE %D% < 'd';

    CREATE INDEX i1c7 ON t1(
        %C% /* As before, for (c=... "expr */) WHERE %D% < 'd';
  }

  do_execsql_test $tn.1.1 {
    INSERT INTO t1 VALUES(0, NULL, NULL, 'a');
    INSERT INTO t1 VALUES(1, 2, 3, 'b');
    INSERT INTO t1 VALUES(4, 5, 6, 'c');
    INSERT INTO t1 VALUES(7, 8, 9, 'd');
  }

  forcedelete rbu.db
  do_test $tn.1.2 {
    sqlite3 rbu rbu.db
    rbu eval {
      CREATE TABLE data_t1(%A%, %B%, %C%, %D%, rbu_control);

      INSERT INTO data_t1 VALUES(10, 11, 12, 'e', 0);
      INSERT INTO data_t1 VALUES(13, 14, NULL, 'f', 0);

      INSERT INTO data_t1 VALUES(0, NULL, NULL, NULL, 1);
      INSERT INTO data_t1 VALUES(4, NULL, NULL, NULL, 1);

      INSERT INTO data_t1 VALUES(7, NULL, 4, NULL, '..x.');
      INSERT INTO data_t1 VALUES(1, 10, NULL, NULL, '.xx.');
    }
    rbu close
  } {}

  do_test $tn.1.3 {
    run_rbu test.db rbu.db
    execsql { PRAGMA integrity_check }
  } {ok}

  do_execsql_test $tn.1.4 {
    SELECT * FROM t1 ORDER BY %A%;
  } {
    1 10 {} b   7 8 4 d   10 11 12 e   13 14 {} f
  }

  set step 0
  do_rbu_vacuum_test $tn.1.5 0

  do_test $tn.1.6 {
    execsql { PRAGMA integrity_check }
  } {ok}
  }]
}

finish_test

Added ext/rbu/rbupass.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2023 January 13
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#

source [file join [file dirname [info script]] rbu_common.tcl]
ifcapable !rbu { finish_test ; return }
set ::testprefix rbupass

if {[info commands register_demovfs]==""} {
  finish_test
  return
}

db close
sqlite3_shutdown
sqlite3_config_uri 1

register_demovfs
sqlite3rbu_create_vfs myvfs demo

sqlite3 db file:test.db?vfs=myvfs
do_execsql_test 1.0 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
  INSERT INTO t1 VALUES(1, 2);
  SELECT * FROM t1;
} {1 2}

do_execsql_test 1.1 {
  PRAGMA journal_mode = wal;
} {delete}

do_execsql_test 1.2 {
  SELECT * FROM t1;
} {1 2}

do_test 1.3 {
  forcedelete rbu.db
  sqlite3 rbu rbu.db
  rbu eval {
    CREATE TABLE data_t1(a, b, rbu_control);
    INSERT INTO data_t1 VALUES(2, 4, 0);
  }
  rbu close
} {}

do_test 1.4 {
  sqlite3rbu rbu test.db rbu.db
} {rbu}
do_test 1.5 {
  rbu step
} {SQLITE_CANTOPEN}
do_test 1.6 {
  list [catch { rbu close } msg] $msg
} {1 {SQLITE_CANTOPEN - unable to open database file}}

do_test 1.7 {
  sqlite3rbu_vacuum rbu test.db
} {rbu}
do_test 1.8 {
  rbu step
  catch { rbu close } 
} {1}

do_execsql_test 1.9 {
  SELECT * FROM t1;
} {1 2}

db close
sqlite3rbu_destroy_vfs myvfs 
unregister_demovfs
sqlite3_shutdown
finish_test

Changes to ext/rbu/rbuprogress.test.

1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21













+







# 2016 March 18
#
# 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.
#
#***********************************************************************
#

source [file join [file dirname [info script]] rbu_common.tcl]
ifcapable !rbu { finish_test ; return }
set ::testprefix rbuprogress


proc create_db_file {filename sql} {
  forcedelete $filename
  sqlite3 tmpdb $filename  
  tmpdb eval $sql
409
410
411
412
413
414
415
416



417






























418
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








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


      set R(nopk) $r1
      set R(vtab) $r2
      do_sp_test 5.$tn.$bReopen.$tn2.1 $bReopen test.db rbu.db $R($tn)
    }
  }
}

#-------------------------------------------------------------------------
# Test that sqlite3_bp_progress() works with an RBU vacuum if there
# is an rbu_count table in the db being vacuumed.

#
reset_db
do_execsql_test 6.0 {
  CREATE TABLE t1(a, b, c);
  CREATE INDEX i1 ON t1(a);
  CREATE INDEX i2 ON t1(b);
  WITH s(i) AS (
    SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<100
  )
  INSERT INTO t1 SELECT i, i, i FROM s;
  CREATE TABLE rbu_count(tbl TEXT PRIMARY KEY, cnt INTEGER) WITHOUT ROWID;
  INSERT INTO rbu_count VALUES('t1', (SELECT count(*) FROM t1));
  INSERT INTO rbu_count VALUES('rbu_count', 2);
}

forcedelete state.db
do_test 6.1 {
  set maxA 0
  set maxB 0
  sqlite3rbu_vacuum rbu test.db state.db
  while {[rbu step]=="SQLITE_OK"} {
    foreach {a b} [rbu bp_progress] {
      if {$a > $maxA} { set maxA $a }
      if {$b > $maxB} { set maxB $b }
    }
  }
  list [rbu close] $maxA $maxB
} {SQLITE_DONE 10000 10000}


finish_test

Added ext/rbu/rburename.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022 November 07
#
# 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.
#
#***********************************************************************
#
#

source [file join [file dirname [info script]] rbu_common.tcl]
ifcapable !rbu { finish_test ; return }
set ::testprefix rburename


do_execsql_test 1.0 {
  CREATE TABLE t1(a, b);
  INSERT INTO t1 VALUES(1, 2);
  INSERT INTO t1 VALUES(3, 4);
  INSERT INTO t1 VALUES(5, 6);
}

forcedelete test.db-vacuum

proc my_rename {old new} {
  lappend ::my_rename_calls [list [file tail $old] [file tail $new]]
  file rename $old $new
}

do_test 1.1 {
  sqlite3rbu_vacuum rbu test.db
  rbu rename_handler my_rename
  while {[rbu step]=="SQLITE_OK"} {}
  rbu close
} SQLITE_DONE

do_test 1.2 {
  set ::my_rename_calls
} {{test.db-oal test.db-wal}}

proc my_rename {old new} {
  error "something went wrong"
}

do_test 1.3 {
  sqlite3rbu_vacuum rbu test.db
  rbu rename_handler my_rename
  while {[rbu step]=="SQLITE_OK"} {}
  list [catch { rbu close } msg] $msg
} {1 SQLITE_IOERR}

finish_test

Changes to ext/rbu/rburesume.test.

1
2
3
4
5
6
7
8
9
10


11
12
13
14
15
16

17
18
19
20
21
22
23
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










+
+






+







# 2017 January 13
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# TESTRUNNER: slow
#
# This file contains tests for resumption of RBU operations in the
# case where the previous RBU process crashed.
#

source [file join [file dirname [info script]] rbu_common.tcl]
ifcapable !rbu { finish_test ; return }
set ::testprefix rburesume

forcedelete test.db-shm test.db-oal
do_execsql_test 1.0 {
  CREATE TABLE t1(a PRIMARY KEY, b, c);
  CREATE INDEX t1a ON t1(a);
  CREATE INDEX t1b ON t1(b);

Changes to ext/rbu/rbusave.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16

17
18
19
20
21
22
23
1
2
3
4
5
6
7
8
9
10
11
12


13


14
15
16
17
18
19
20
21












-
-
+
-
-
+







# 2015 August 14
#
# 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.
#
#***********************************************************************
#

if {![info exists testdir]} {
  set testdir [file join [file dirname [info script]] .. .. test]
source [file join [file dirname [info script]] rbu_common.tcl]
}
source $testdir/tester.tcl
ifcapable !rbu { finish_test ; return }
set ::testprefix rbusave

do_execsql_test 1.0 {
  CREATE TABLE t1(a PRIMARY KEY, b, c) WITHOUT ROWID;
  CREATE TABLE t2(a INTEGER PRIMARY KEY, b, c);
  CREATE INDEX i1 ON t1(b);
  CREATE INDEX i2 ON t2(c, b);

Changes to ext/rbu/rbusplit.test.

8
9
10
11
12
13
14

15
16
17
18
19
20
21
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22







+







#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
#

source [file join [file dirname [info script]] rbu_common.tcl]
ifcapable !rbu { finish_test ; return }
set ::testprefix rbusplit

db close
sqlite3_shutdown
sqlite3_config_uri 1

autoinstall_test_functions

Changes to ext/rbu/rbutemplimit.test.

1
2
3
4
5
6
7
8
9
10
11

12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22











+


+







# 2014 August 30
#
# 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.
#
#***********************************************************************
#
# TESTRUNNER: slow

source [file join [file dirname [info script]] rbu_common.tcl]
ifcapable !rbu { finish_test ; return }
set ::testprefix rbutemplimit

db close
sqlite3_shutdown
sqlite3_config_uri 1

proc setup_databases {} {
61
62
63
64
65
66
67

68
69
70
71
72
73
74
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77







+







}

proc step_rbu_cachesize {target rbu stepsize cachesize temp_limit} {
  set res ""
  while 1 {
    sqlite3rbu rbu $target $rbu
    rbu temp_size_limit $temp_limit
    if { [rbu temp_size_limit -1]!=$temp_limit } { error "round trip problem!" }
    sqlite3_exec_nr [rbu db 1] "PRAGMA cache_size = $cachesize"
    for {set i 0} {$i < $stepsize} {incr i} {
      set rc [rbu step]
      set ::A([rbu temp_size]) 1
      if {$rc!="SQLITE_OK"} break
    }
    set res [list [catch {rbu close} msg] $msg]

Changes to ext/rbu/rbuvacuum.test.

11
12
13
14
15
16
17

18
19
20
21
22
23
24
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25







+







#
# This file contains tests for the RBU module. More specifically, it
# contains tests to ensure that the sqlite3rbu_vacuum() API works as
# expected.
#

source [file join [file dirname [info script]] rbu_common.tcl]
ifcapable !rbu { finish_test ; return }
set ::testprefix rbuvacuum

foreach step {0 1} {

  set ::testprefix rbuvacuum-step=$step
  reset_db

Changes to ext/rbu/rbuvacuum2.test.

11
12
13
14
15
16
17

18
19
20
21
22
23
24
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25







+







#
# This file contains tests for the RBU module. More specifically, it
# contains tests to ensure that the sqlite3rbu_vacuum() API works as
# expected.
#

source [file join [file dirname [info script]] rbu_common.tcl]
ifcapable !rbu { finish_test ; return }

foreach {step} {0 1} {
foreach {ttt state} {
  s state.db t test.db-vacuum n {}
} {
  set ::testprefix rbuvacuum2-$step$ttt
  
194
195
196
197
198
199
200




201

202
203
204
205
206
207
208
195
196
197
198
199
200
201
202
203
204
205

206
207
208
209
210
211
212
213







+
+
+
+
-
+







    do_test 5.$tn.1 {
      file attributes test.db -permissions $perm
      sqlite3rbu_vacuum rbu test.db
      rbu step
    } {SQLITE_OK}

    do_test 5.$tn.2 { file exists test.db-vacuum } 1
    # The result pattern might be 00xxx or 0oxxx depending on which
    # version of TCL is being used.  So make perm2 into a regexp that
    # will match either
    regsub {^00} $perm {0.} perm2
    do_test 5.$tn.3 { file attributes test.db-vacuum -permissions} $perm
    do_test 5.$tn.3 { file attributes test.db-vacuum -permissions} /$perm2/
    rbu close
  }
}

#-------------------------------------------------------------------------
# Test the outcome of some other connection running a checkpoint while
# the incremental checkpoint is suspended.
219
220
221
222
223
224
225
226
227
228
229





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




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







-
-
-
-
+
+
+
+
+








do_test 6.1 {
  sqlite3rbu_vacuum rbu test.db test.db2
  while {[rbu state]!="checkpoint"} { rbu step }
  rbu close
} {SQLITE_OK}

do_execsql_test 6.2 {
  SELECT 1 FROM sqlite_master LIMIT 1;
  PRAGMA wal_checkpoint;
} {1 0 4 4}
do_test 6.2 {
  execsql { SELECT 1 FROM sqlite_master LIMIT 1 }
  execsql { PRAGMA wal_checkpoint }
  execsql { SELECT 1 FROM sqlite_master LIMIT 1 }
} {1}

do_test 6.3 {
  sqlite3rbu_vacuum rbu test.db test.db2
  while {[rbu step]!="SQLITE_DONE"} { rbu step }
  rbu close
  execsql { PRAGMA integrity_check }
} {ok}

Added ext/rbu/rbuvacuum3.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019 Jan 3
#
# 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 contains tests for the RBU module. More specifically, it
# contains tests to ensure that the sqlite3rbu_vacuum() API works as
# expected.
#

source [file join [file dirname [info script]] rbu_common.tcl]
ifcapable !rbu { finish_test ; return }
set testprefix rbuvacuum3

do_execsql_test 1.0 {
  CREATE TABLE t1(a PRIMARY KEY, b, c);
  CREATE INDEX i1b ON t1(b);
  CREATE INDEX i1c ON t1(c);
  
  WITH s(i) AS (
    VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<100
  )
  INSERT INTO t1 SELECT i, randomblob(100), randomblob(100) FROM s;
}

forcedelete state.db
do_test 1.1 {
  sqlite3rbu_vacuum rbu test.db state.db
  while {1} {
    set rc [rbu step]
    if {$rc!="SQLITE_OK"} break
    rbu savestate
  }
  rbu close
} {SQLITE_DONE}

do_test 1.2 {
  sqlite3rbu_vacuum rbu test.db state.db
  while {1} {
    set rc [rbu step]
    if {$rc!="SQLITE_OK"} break
    rbu savestate
  }
  rbu close
} {SQLITE_DONE}

do_test 1.3 {
  while {1} {
    sqlite3rbu_vacuum rbu test.db state.db
    set rc [rbu step]
    if {$rc!="SQLITE_OK"} break
    rbu savestate
    rbu close
  }
  rbu close
} {SQLITE_DONE}

finish_test

Added ext/rbu/rbuvacuum4.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019 Jan 3
#
# 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 contains tests for the RBU module. More specifically, it
# contains tests to ensure that the sqlite3rbu_vacuum() API works as
# expected.
#

source [file join [file dirname [info script]] rbu_common.tcl]
ifcapable !rbu { finish_test ; return }
set testprefix rbuvacuum4

set step 1

do_execsql_test 1.0 {
  CREATE TABLE t1(a PRIMARY KEY, b, c) WITHOUT ROWID;
  INSERT INTO t1 VALUES(1, 2, 3);
  INSERT INTO t1 VALUES(4, 5, 6);
  INSERT INTO t1 VALUES(7, 8, 9);
}
do_rbu_vacuum_test 1.1 1

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

do_execsql_test 2.0 {
  CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b, c)) WITHOUT ROWID;
  INSERT INTO t1 VALUES(1, 2, 3);
  INSERT INTO t1 VALUES(4, 5, 6);
  INSERT INTO t1 VALUES(7, 8, 9);
}
do_rbu_vacuum_test 2.1 1
do_execsql_test 2.2 {
  SELECT * FROM t1;
} {1 2 3 4 5 6 7 8 9}

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

do_execsql_test 3.0 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
  CREATE INDEX i1 oN t1(b, c);
  INSERT INTO t1 VALUES(1, 2, 3);
  INSERT INTO t1 VALUES(4, 5, 6);
  INSERT INTO t1 VALUES(7, 8, 9);

  CREATE TABLE t2(a, b, c INTEGER, PRIMARY KEY(c));
  CREATE INDEX i2 oN t2(b, a);
  INSERT INTO t2 VALUES('a', 'b', -1);
  INSERT INTO t2 VALUES('c', 'd', -2);
  INSERT INTO t2 VALUES('e', 'f', -3);
}

do_rbu_vacuum_test 3.1 1

do_execsql_test 3.2 {
  SELECT * FROM t1;
  SELECT * FROM t2;
} {1 2 3 4 5 6 7 8 9 e f -3 c d -2 a b -1}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 4.0 {
  CREATE TABLE x1(a, b, c, d, PRIMARY KEY(c, b)) WITHOUT ROWID;
  INSERT INTO x1 VALUES(1, 1, 1, 1);
  INSERT INTO x1 VALUES(1, 1, 2, 1);
  INSERT INTO x1 VALUES(1, 2, 2, 1);

  INSERT INTO x1 VALUES(NULL, 2, 3, NULL);
  INSERT INTO x1 VALUES(NULL, 2, 4, NULL);
  INSERT INTO x1 VALUES(NULL, 2, 5, NULL);

  CREATE INDEX x1ad ON x1(d, a);
  CREATE INDEX x1null ON x1(d, a) WHERE d>15;
}

do_rbu_vacuum_test 4.1.1 1

do_execsql_test 4.2 {
  SELECT count(*) fROM x1
} 6

do_rbu_vacuum_test 4.1.2 0

#-------------------------------------------------------------------------
reset_db
do_execsql_test 5.0 {
  CREATE TABLE "a b c"(a, "b b" PRIMARY KEY, "c c");
  CREATE INDEX abc1 ON "a b c"(a, "c c");

  INSERT INTO "a b c" VALUES(NULL, 'a', NULL);
  INSERT INTO "a b c" VALUES(NULL, 'b', NULL);
  INSERT INTO "a b c" VALUES(NULL, 'c', NULL);

  INSERT INTO "a b c" VALUES(1, 2, 3);
  INSERT INTO "a b c" VALUES(3, 9, 1);
  INSERT INTO "a b c" VALUES('aaa', 'bbb', 'ccc');

  CREATE INDEX abc2 ON "a b c"("c c" DESC, a);

  CREATE TABLE x(a);
  INSERT INTO x VALUES('a'), ('b'), ('d');
  CREATE UNIQUE INDEX y ON x(a);
}

do_rbu_vacuum_test 5.1 1

finish_test

Changes to ext/rbu/sqlite3rbu.c.

105
106
107
108
109
110
111







112
113
114
115
116
117
118
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125







+
+
+
+
+
+
+








/*
** Swap two objects of type TYPE.
*/
#if !defined(SQLITE_AMALGAMATION)
# define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;}
#endif

/*
** Name of the URI option that causes RBU to take an exclusive lock as
** part of the incremental checkpoint operation.
*/
#define RBU_EXCLUSIVE_CHECKPOINT "rbu_exclusive_checkpoint"


/*
** The rbu_state table is used to save the state of a partially applied
** update so that it can be resumed later. The table consists of integer
** keys mapped to values as follows:
**
** RBU_STATE_STAGE:
178
179
180
181
182
183
184

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







+








#define RBU_CREATE_STATE \
  "CREATE TABLE IF NOT EXISTS %s.rbu_state(k INTEGER PRIMARY KEY, v)"

typedef struct RbuFrame RbuFrame;
typedef struct RbuObjIter RbuObjIter;
typedef struct RbuState RbuState;
typedef struct RbuSpan RbuSpan;
typedef struct rbu_vfs rbu_vfs;
typedef struct rbu_file rbu_file;
typedef struct RbuUpdateStmt RbuUpdateStmt;

#if !defined(SQLITE_AMALGAMATION)
typedef unsigned int u32;
typedef unsigned short u16;
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
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







+
+
+
+
+














+
+
+
+
+








struct RbuUpdateStmt {
  char *zMask;                    /* Copy of update mask used with pUpdate */
  sqlite3_stmt *pUpdate;          /* Last update statement (or NULL) */
  RbuUpdateStmt *pNext;
};

struct RbuSpan {
  const char *zSpan;
  int nSpan;
};

/*
** An iterator of this type is used to iterate through all objects in
** the target database that require updating. For each such table, the
** iterator visits, in order:
**
**     * the table itself, 
**     * each index of the table (zero or more points to visit), and
**     * a special "cleanup table" state.
**
** abIndexed:
**   If the table has no indexes on it, abIndexed is set to NULL. Otherwise,
**   it points to an array of flags nTblCol elements in size. The flag is
**   set for each column that is either a part of the PK or a part of an
**   index. Or clear otherwise.
**
**   If there are one or more partial indexes on the table, all fields of
**   this array set set to 1. This is because in that case, the module has
**   no way to tell which fields will be required to add and remove entries
**   from the partial indexes.
**   
*/
struct RbuObjIter {
  sqlite3_stmt *pTblIter;         /* Iterate through tables */
  sqlite3_stmt *pIdxIter;         /* Index iterator */
  int nTblCol;                    /* Size of azTblCol[] array */
  char **azTblCol;                /* Array of unquoted target column names */
266
267
268
269
270
271
272



273
274
275
276
277
278
279
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300







+
+
+








  /* Statements created by rbuObjIterPrepareAll() */
  int nCol;                       /* Number of columns in current object */
  sqlite3_stmt *pSelect;          /* Source data */
  sqlite3_stmt *pInsert;          /* Statement for INSERT operations */
  sqlite3_stmt *pDelete;          /* Statement for DELETE ops */
  sqlite3_stmt *pTmpInsert;       /* Insert into rbu_tmp_$zDataTbl */
  int nIdxCol;
  RbuSpan *aIdxCol;
  char *zIdxSql;

  /* Last UPDATE used (for PK b-tree updates only), or NULL. */
  RbuUpdateStmt *pRbuUpdate;
};

/*
** Values for RbuObjIter.eType
368
369
370
371
372
373
374


375
376
377
378
379
380
381
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404







+
+







  int nProgress;                  /* Rows processed for all objects */
  RbuObjIter objiter;             /* Iterator for skipping through tbl/idx */
  const char *zVfsName;           /* Name of automatically created rbu vfs */
  rbu_file *pTargetFd;            /* File handle open on target db */
  int nPagePerSector;             /* Pages per sector for pTargetFd */
  i64 iOalSz;
  i64 nPhaseOneStep;
  void *pRenameArg;
  int (*xRename)(void*, const char*, const char*);

  /* The following state variables are used as part of the incremental
  ** checkpoint stage (eStage==RBU_STAGE_CKPT). See comments surrounding
  ** function rbuSetupCheckpoint() for details.  */
  u32 iMaxFrame;                  /* Largest iWalFrame value in aFrame[] */
  u32 mLock;
  int nFrame;                     /* Entries in aFrame[] array */
680
681
682
683
684
685
686

687
688
689
690
691
692
693
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717







+








  aOut = sqlite3_malloc(nOut+1);
  if( aOut==0 ){
    sqlite3_result_error_nomem(context);
  }else{
    nOut2 = rbuDeltaApply(aOrig, nOrig, aDelta, nDelta, aOut);
    if( nOut2!=nOut ){
      sqlite3_free(aOut);
      sqlite3_result_error(context, "corrupt fossil delta", -1);
    }else{
      sqlite3_result_blob(context, aOut, nOut, sqlite3_free);
    }
  }
}

799
800
801
802
803
804
805


806
807
808
809
810
811
812



813
814
815
816
817
818
819
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







+
+







+
+
+







  pUp = pIter->pRbuUpdate;
  while( pUp ){
    RbuUpdateStmt *pTmp = pUp->pNext;
    sqlite3_finalize(pUp->pUpdate);
    sqlite3_free(pUp);
    pUp = pTmp;
  }
  sqlite3_free(pIter->aIdxCol);
  sqlite3_free(pIter->zIdxSql);
  
  pIter->pSelect = 0;
  pIter->pInsert = 0;
  pIter->pDelete = 0;
  pIter->pRbuUpdate = 0;
  pIter->pTmpInsert = 0;
  pIter->nCol = 0;
  pIter->nIdxCol = 0;
  pIter->aIdxCol = 0;
  pIter->zIdxSql = 0;
}

/*
** Clean up any resources allocated as part of the iterator object passed
** as the only argument.
*/
static void rbuObjIterFinalize(RbuObjIter *pIter){
920
921
922
923
924
925
926

927
928
929
930
931
932
933
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963







+







  sqlite3rbu *p = sqlite3_user_data(pCtx);
  const char *zIn;
  assert( argc==1 || argc==2 );

  zIn = (const char*)sqlite3_value_text(argv[0]);
  if( zIn ){
    if( rbuIsVacuum(p) ){
      assert( argc==2 || argc==1 );
      if( argc==1 || 0==sqlite3_value_int(argv[1]) ){
        sqlite3_result_text(pCtx, zIn, -1, SQLITE_STATIC);
      }
    }else{
      if( strlen(zIn)>4 && memcmp("data", zIn, 4)==0 ){
        int i;
        for(i=4; zIn[i]>='0' && zIn[i]<='9'; i++);
950
951
952
953
954
955
956
957

958
959
960
961
962
963
964
965
966

967
968
969
970
971
972
973
980
981
982
983
984
985
986

987
988
989
990
991
992
993
994
995

996
997
998
999
1000
1001
1002
1003







-
+








-
+







static int rbuObjIterFirst(sqlite3rbu *p, RbuObjIter *pIter){
  int rc;
  memset(pIter, 0, sizeof(RbuObjIter));

  rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pTblIter, &p->zErrmsg, 
    sqlite3_mprintf(
      "SELECT rbu_target_name(name, type='view') AS target, name "
      "FROM sqlite_master "
      "FROM sqlite_schema "
      "WHERE type IN ('table', 'view') AND target IS NOT NULL "
      " %s "
      "ORDER BY name"
  , rbuIsVacuum(p) ? "AND rootpage!=0 AND rootpage IS NOT NULL" : ""));

  if( rc==SQLITE_OK ){
    rc = prepareAndCollectError(p->dbMain, &pIter->pIdxIter, &p->zErrmsg,
        "SELECT name, rootpage, sql IS NULL OR substr(8, 6)=='UNIQUE' "
        "  FROM main.sqlite_master "
        "  FROM main.sqlite_schema "
        "  WHERE type='index' AND tbl_name = ?"
    );
  }

  pIter->bCleanup = 1;
  p->rc = rc;
  return rbuObjIterNext(p, pIter);
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
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







-
+




















-
+







**
** If an error (i.e. an OOM condition) occurs, return NULL and leave an 
** error code in the rbu handle passed as the first argument. Or, if an 
** error has already occurred when this function is called, return NULL 
** immediately without attempting the allocation or modifying the stored
** error code.
*/
static void *rbuMalloc(sqlite3rbu *p, int nByte){
static void *rbuMalloc(sqlite3rbu *p, sqlite3_int64 nByte){
  void *pRet = 0;
  if( p->rc==SQLITE_OK ){
    assert( nByte>0 );
    pRet = sqlite3_malloc64(nByte);
    if( pRet==0 ){
      p->rc = SQLITE_NOMEM;
    }else{
      memset(pRet, 0, nByte);
    }
  }
  return pRet;
}


/*
** Allocate and zero the pIter->azTblCol[] and abTblPk[] arrays so that
** there is room for at least nCol elements. If an OOM occurs, store an
** error code in the RBU handle passed as the first argument.
*/
static void rbuAllocateIterArrays(sqlite3rbu *p, RbuObjIter *pIter, int nCol){
  int nByte = (2*sizeof(char*) + sizeof(int) + 3*sizeof(u8)) * nCol;
  sqlite3_int64 nByte = (2*sizeof(char*) + sizeof(int) + 3*sizeof(u8)) * nCol;
  char **azNew;

  azNew = (char**)rbuMalloc(p, nByte);
  if( azNew ){
    pIter->azTblCol = azNew;
    pIter->azTblType = &azNew[nCol];
    pIter->aiSrcOrder = (int*)&pIter->azTblType[nCol];
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092









1093
1094
1095
1096
1097
1098
1099
1108
1109
1110
1111
1112
1113
1114








1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130







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







** If an OOM condition is encountered when attempting to allocate memory,
** output variable (*pRc) is set to SQLITE_NOMEM before returning. Otherwise,
** if the allocation succeeds, (*pRc) is left unchanged.
*/
static char *rbuStrndup(const char *zStr, int *pRc){
  char *zRet = 0;

  assert( *pRc==SQLITE_OK );
  if( zStr ){
    size_t nCopy = strlen(zStr) + 1;
    zRet = (char*)sqlite3_malloc64(nCopy);
    if( zRet ){
      memcpy(zRet, zStr, nCopy);
    }else{
      *pRc = SQLITE_NOMEM;
  if( *pRc==SQLITE_OK ){
    if( zStr ){
      size_t nCopy = strlen(zStr) + 1;
      zRet = (char*)sqlite3_malloc64(nCopy);
      if( zRet ){
        memcpy(zRet, zStr, nCopy);
      }else{
        *pRc = SQLITE_NOMEM;
      }
    }
  }

  return zRet;
}

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







-
+




-
+



















-
+

-
+










-
-
+
+
+
+







**   (i.e. unless *peType is set to 3), then *piPk is set to zero. Or,
**   if the table does have an external primary key index, then *piPk
**   is set to the root page number of the primary key index before
**   returning.
**
** ALGORITHM:
**
**   if( no entry exists in sqlite_master ){
**   if( no entry exists in sqlite_schema ){
**     return RBU_PK_NOTABLE
**   }else if( sql for the entry starts with "CREATE VIRTUAL" ){
**     return RBU_PK_VTAB
**   }else if( "PRAGMA index_list()" for the table contains a "pk" index ){
**     if( the index that is the pk exists in sqlite_master ){
**     if( the index that is the pk exists in sqlite_schema ){
**       *piPK = rootpage of that index.
**       return RBU_PK_EXTERNAL
**     }else{
**       return RBU_PK_WITHOUT_ROWID
**     }
**   }else if( "PRAGMA table_info()" lists one or more "pk" columns ){
**     return RBU_PK_IPK
**   }else{
**     return RBU_PK_NONE
**   }
*/
static void rbuTableType(
  sqlite3rbu *p,
  const char *zTab,
  int *peType,
  int *piTnum,
  int *piPk
){
  /*
  ** 0) SELECT count(*) FROM sqlite_master where name=%Q AND IsVirtual(%Q)
  ** 0) SELECT count(*) FROM sqlite_schema where name=%Q AND IsVirtual(%Q)
  ** 1) PRAGMA index_list = ?
  ** 2) SELECT count(*) FROM sqlite_master where name=%Q 
  ** 2) SELECT count(*) FROM sqlite_schema where name=%Q 
  ** 3) PRAGMA table_info = ?
  */
  sqlite3_stmt *aStmt[4] = {0, 0, 0, 0};

  *peType = RBU_PK_NOTABLE;
  *piPk = 0;

  assert( p->rc==SQLITE_OK );
  p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[0], &p->zErrmsg, 
    sqlite3_mprintf(
          "SELECT (sql LIKE 'create virtual%%'), rootpage"
          "  FROM sqlite_master"
          "SELECT "
          " (sql COLLATE nocase BETWEEN 'CREATE VIRTUAL' AND 'CREATE VIRTUAM'),"
          " rootpage"
          "  FROM sqlite_schema"
          " WHERE name=%Q", zTab
  ));
  if( p->rc!=SQLITE_OK || sqlite3_step(aStmt[0])!=SQLITE_ROW ){
    /* Either an error, or no such table. */
    goto rbuTableType_end;
  }
  if( sqlite3_column_int(aStmt[0], 0) ){
1192
1193
1194
1195
1196
1197
1198
1199

1200
1201
1202
1203
1204
1205
1206
1225
1226
1227
1228
1229
1230
1231

1232
1233
1234
1235
1236
1237
1238
1239







-
+







  if( p->rc ) goto rbuTableType_end;
  while( sqlite3_step(aStmt[1])==SQLITE_ROW ){
    const u8 *zOrig = sqlite3_column_text(aStmt[1], 3);
    const u8 *zIdx = sqlite3_column_text(aStmt[1], 1);
    if( zOrig && zIdx && zOrig[0]=='p' ){
      p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[2], &p->zErrmsg, 
          sqlite3_mprintf(
            "SELECT rootpage FROM sqlite_master WHERE name = %Q", zIdx
            "SELECT rootpage FROM sqlite_schema WHERE name = %Q", zIdx
      ));
      if( p->rc==SQLITE_OK ){
        if( sqlite3_step(aStmt[2])==SQLITE_ROW ){
          *piPk = sqlite3_column_int(aStmt[2], 0);
          *peType = RBU_PK_EXTERNAL;
        }else{
          *peType = RBU_PK_WITHOUT_ROWID;
1245
1246
1247
1248
1249
1250
1251

1252
1253



1254
1255
1256
1257
1258
1259



1260
1261
1262
1263
1264
1265
1266
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







+


+
+
+






+
+
+







        sqlite3_mprintf("PRAGMA main.index_list = %Q", pIter->zTbl)
    );
  }

  pIter->nIndex = 0;
  while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pList) ){
    const char *zIdx = (const char*)sqlite3_column_text(pList, 1);
    int bPartial = sqlite3_column_int(pList, 4);
    sqlite3_stmt *pXInfo = 0;
    if( zIdx==0 ) break;
    if( bPartial ){
      memset(pIter->abIndexed, 0x01, sizeof(u8)*pIter->nTblCol);
    }
    p->rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg,
        sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", zIdx)
    );
    while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){
      int iCid = sqlite3_column_int(pXInfo, 1);
      if( iCid>=0 ) pIter->abIndexed[iCid] = 1;
      if( iCid==-2 ){
        memset(pIter->abIndexed, 0x01, sizeof(u8)*pIter->nTblCol);
      }
    }
    rbuFinalize(p, pXInfo);
    bIndex = 1;
    pIter->nIndex++;
  }

  if( pIter->eType==RBU_PK_WITHOUT_ROWID ){
1367
1368
1369
1370
1371
1372
1373

1374

1375
1376
1377
1378
1379
1380
1381
1407
1408
1409
1410
1411
1412
1413
1414

1415
1416
1417
1418
1419
1420
1421
1422







+
-
+








        if( i!=iOrder ){
          SWAP(int, pIter->aiSrcOrder[i], pIter->aiSrcOrder[iOrder]);
          SWAP(char*, pIter->azTblCol[i], pIter->azTblCol[iOrder]);
        }

        pIter->azTblType[iOrder] = rbuStrndup(zType, &p->rc);
        assert( iPk>=0 );
        pIter->abTblPk[iOrder] = (iPk!=0);
        pIter->abTblPk[iOrder] = (u8)iPk;
        pIter->abNotNull[iOrder] = (u8)bNotNull || (iPk!=0);
        iOrder++;
      }
    }

    rbuFinalize(p, pStmt);
    rbuObjIterCacheIndexedCols(p, pIter);
1401
1402
1403
1404
1405
1406
1407

















































































































































































































1408
1409
1410
1411
1412
1413
1414
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
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
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
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664







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







  for(i=0; i<pIter->nTblCol; i++){
    const char *z = pIter->azTblCol[i];
    zList = rbuMPrintf(p, "%z%s\"%w\"", zList, zSep, z);
    zSep = ", ";
  }
  return zList;
}

/*
** Return a comma separated list of the quoted PRIMARY KEY column names,
** in order, for the current table. Before each column name, add the text
** zPre. After each column name, add the zPost text. Use zSeparator as
** the separator text (usually ", ").
*/
static char *rbuObjIterGetPkList(
  sqlite3rbu *p,                  /* RBU object */
  RbuObjIter *pIter,              /* Object iterator for column names */
  const char *zPre,               /* Before each quoted column name */
  const char *zSeparator,         /* Separator to use between columns */
  const char *zPost               /* After each quoted column name */
){
  int iPk = 1;
  char *zRet = 0;
  const char *zSep = "";
  while( 1 ){
    int i;
    for(i=0; i<pIter->nTblCol; i++){
      if( (int)pIter->abTblPk[i]==iPk ){
        const char *zCol = pIter->azTblCol[i];
        zRet = rbuMPrintf(p, "%z%s%s\"%w\"%s", zRet, zSep, zPre, zCol, zPost);
        zSep = zSeparator;
        break;
      }
    }
    if( i==pIter->nTblCol ) break;
    iPk++;
  }
  return zRet;
}

/*
** This function is called as part of restarting an RBU vacuum within 
** stage 1 of the process (while the *-oal file is being built) while
** updating a table (not an index). The table may be a rowid table or
** a WITHOUT ROWID table. It queries the target database to find the 
** largest key that has already been written to the target table and
** constructs a WHERE clause that can be used to extract the remaining
** rows from the source table. For a rowid table, the WHERE clause
** is of the form:
**
**     "WHERE _rowid_ > ?"
**
** and for WITHOUT ROWID tables:
**
**     "WHERE (key1, key2) > (?, ?)"
**
** Instead of "?" placeholders, the actual WHERE clauses created by
** this function contain literal SQL values.
*/
static char *rbuVacuumTableStart(
  sqlite3rbu *p,                  /* RBU handle */
  RbuObjIter *pIter,              /* RBU iterator object */
  int bRowid,                     /* True for a rowid table */
  const char *zWrite              /* Target table name prefix */
){
  sqlite3_stmt *pMax = 0;
  char *zRet = 0;
  if( bRowid ){
    p->rc = prepareFreeAndCollectError(p->dbMain, &pMax, &p->zErrmsg, 
        sqlite3_mprintf(
          "SELECT max(_rowid_) FROM \"%s%w\"", zWrite, pIter->zTbl
        )
    );
    if( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pMax) ){
      sqlite3_int64 iMax = sqlite3_column_int64(pMax, 0);
      zRet = rbuMPrintf(p, " WHERE _rowid_ > %lld ", iMax);
    }
    rbuFinalize(p, pMax);
  }else{
    char *zOrder = rbuObjIterGetPkList(p, pIter, "", ", ", " DESC");
    char *zSelect = rbuObjIterGetPkList(p, pIter, "quote(", "||','||", ")");
    char *zList = rbuObjIterGetPkList(p, pIter, "", ", ", "");

    if( p->rc==SQLITE_OK ){
      p->rc = prepareFreeAndCollectError(p->dbMain, &pMax, &p->zErrmsg, 
          sqlite3_mprintf(
            "SELECT %s FROM \"%s%w\" ORDER BY %s LIMIT 1", 
                zSelect, zWrite, pIter->zTbl, zOrder
          )
      );
      if( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pMax) ){
        const char *zVal = (const char*)sqlite3_column_text(pMax, 0);
        zRet = rbuMPrintf(p, " WHERE (%s) > (%s) ", zList, zVal);
      }
      rbuFinalize(p, pMax);
    }

    sqlite3_free(zOrder);
    sqlite3_free(zSelect);
    sqlite3_free(zList);
  }
  return zRet;
}

/*
** This function is called as part of restating an RBU vacuum when the
** current operation is writing content to an index. If possible, it
** queries the target index b-tree for the largest key already written to
** it, then composes and returns an expression that can be used in a WHERE 
** clause to select the remaining required rows from the source table. 
** It is only possible to return such an expression if:
**
**   * The index contains no DESC columns, and
**   * The last key written to the index before the operation was 
**     suspended does not contain any NULL values.
**
** The expression is of the form:
**
**   (index-field1, index-field2, ...) > (?, ?, ...)
**
** except that the "?" placeholders are replaced with literal values.
**
** If the expression cannot be created, NULL is returned. In this case,
** the caller has to use an OFFSET clause to extract only the required 
** rows from the sourct table, just as it does for an RBU update operation.
*/
static char *rbuVacuumIndexStart(
  sqlite3rbu *p,                  /* RBU handle */
  RbuObjIter *pIter               /* RBU iterator object */
){
  char *zOrder = 0;
  char *zLhs = 0;
  char *zSelect = 0;
  char *zVector = 0;
  char *zRet = 0;
  int bFailed = 0;
  const char *zSep = "";
  int iCol = 0;
  sqlite3_stmt *pXInfo = 0;

  p->rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg,
      sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", pIter->zIdx)
  );
  while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){
    int iCid = sqlite3_column_int(pXInfo, 1);
    const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4);
    const char *zCol;
    if( sqlite3_column_int(pXInfo, 3) ){
      bFailed = 1;
      break;
    }

    if( iCid<0 ){
      if( pIter->eType==RBU_PK_IPK ){
        int i;
        for(i=0; pIter->abTblPk[i]==0; i++);
        assert( i<pIter->nTblCol );
        zCol = pIter->azTblCol[i];
      }else{
        zCol = "_rowid_";
      }
    }else{
      zCol = pIter->azTblCol[iCid];
    }

    zLhs = rbuMPrintf(p, "%z%s \"%w\" COLLATE %Q",
        zLhs, zSep, zCol, zCollate
        );
    zOrder = rbuMPrintf(p, "%z%s \"rbu_imp_%d%w\" COLLATE %Q DESC",
        zOrder, zSep, iCol, zCol, zCollate
        );
    zSelect = rbuMPrintf(p, "%z%s quote(\"rbu_imp_%d%w\")",
        zSelect, zSep, iCol, zCol
        );
    zSep = ", ";
    iCol++;
  }
  rbuFinalize(p, pXInfo);
  if( bFailed ) goto index_start_out;

  if( p->rc==SQLITE_OK ){
    sqlite3_stmt *pSel = 0;

    p->rc = prepareFreeAndCollectError(p->dbMain, &pSel, &p->zErrmsg,
        sqlite3_mprintf("SELECT %s FROM \"rbu_imp_%w\" ORDER BY %s LIMIT 1",
          zSelect, pIter->zTbl, zOrder
        )
    );
    if( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSel) ){
      zSep = "";
      for(iCol=0; iCol<pIter->nCol; iCol++){
        const char *zQuoted = (const char*)sqlite3_column_text(pSel, iCol);
        if( zQuoted==0 ){
          p->rc = SQLITE_NOMEM;
        }else if( zQuoted[0]=='N' ){
          bFailed = 1;
          break;
        }
        zVector = rbuMPrintf(p, "%z%s%s", zVector, zSep, zQuoted);
        zSep = ", ";
      }

      if( !bFailed ){
        zRet = rbuMPrintf(p, "(%s) > (%s)", zLhs, zVector);
      }
    }
    rbuFinalize(p, pSel);
  }

 index_start_out:
  sqlite3_free(zOrder);
  sqlite3_free(zSelect);
  sqlite3_free(zVector);
  sqlite3_free(zLhs);
  return zRet;
}

/*
** This function is used to create a SELECT list (the list of SQL 
** expressions that follows a SELECT keyword) for a SELECT statement 
** used to read from an data_xxx or rbu_tmp_xxx table while updating the 
** index object currently indicated by the iterator object passed as the 
** second argument. A "PRAGMA index_xinfo = <idxname>" statement is used 
1456
1457
1458
1459
1460
1461
1462
1463

1464
1465







1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485





















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







-
+


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







    );
  }

  while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){
    int iCid = sqlite3_column_int(pXInfo, 1);
    int bDesc = sqlite3_column_int(pXInfo, 3);
    const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4);
    const char *zCol;
    const char *zCol = 0;
    const char *zType;

    if( iCid==-2 ){
      int iSeq = sqlite3_column_int(pXInfo, 0);
      zRet = sqlite3_mprintf("%z%s(%.*s) COLLATE %Q", zRet, zCom,
          pIter->aIdxCol[iSeq].nSpan, pIter->aIdxCol[iSeq].zSpan, zCollate
      );
      zType = "";
    }else {
    if( iCid<0 ){
      /* An integer primary key. If the table has an explicit IPK, use
      ** its name. Otherwise, use "rbu_rowid".  */
      if( pIter->eType==RBU_PK_IPK ){
        int i;
        for(i=0; pIter->abTblPk[i]==0; i++);
        assert( i<pIter->nTblCol );
        zCol = pIter->azTblCol[i];
      }else if( rbuIsVacuum(p) ){
        zCol = "_rowid_";
      }else{
        zCol = "rbu_rowid";
      }
      zType = "INTEGER";
    }else{
      zCol = pIter->azTblCol[iCid];
      zType = pIter->azTblType[iCid];
    }

    zRet = sqlite3_mprintf("%z%s\"%w\" COLLATE %Q", zRet, zCom, zCol, zCollate);
      if( iCid<0 ){
        /* An integer primary key. If the table has an explicit IPK, use
        ** its name. Otherwise, use "rbu_rowid".  */
        if( pIter->eType==RBU_PK_IPK ){
          int i;
          for(i=0; pIter->abTblPk[i]==0; i++);
          assert( i<pIter->nTblCol );
          zCol = pIter->azTblCol[i];
        }else if( rbuIsVacuum(p) ){
          zCol = "_rowid_";
        }else{
          zCol = "rbu_rowid";
        }
        zType = "INTEGER";
      }else{
        zCol = pIter->azTblCol[iCid];
        zType = pIter->azTblType[iCid];
      }
      zRet = sqlite3_mprintf("%z%s\"%w\" COLLATE %Q", zRet, zCom,zCol,zCollate);
    }

    if( pIter->bUnique==0 || sqlite3_column_int(pXInfo, 5) ){
      const char *zOrder = (bDesc ? " DESC" : "");
      zImpPK = sqlite3_mprintf("%z%s\"rbu_imp_%d%w\"%s", 
          zImpPK, zCom, nBind, zCol, zOrder
      );
    }
    zImpCols = sqlite3_mprintf("%z%s\"rbu_imp_%d%w\" %s COLLATE %Q", 
1691
1692
1693
1694
1695
1696
1697
1698

1699
1700
1701
1702
1703
1704
1705
1949
1950
1951
1952
1953
1954
1955

1956
1957
1958
1959
1960
1961
1962
1963







-
+







** string, an error code is left in the rbu handle passed as the first
** argument and NULL is returned. Or, if an error has already occurred
** when this function is called, NULL is returned immediately, without
** attempting the allocation or modifying the stored error code.
*/
static char *rbuObjIterGetBindlist(sqlite3rbu *p, int nBind){
  char *zRet = 0;
  int nByte = nBind*2 + 1;
  sqlite3_int64 nByte = 2*(sqlite3_int64)nBind + 1;

  zRet = (char*)rbuMalloc(p, nByte);
  if( zRet ){
    int i;
    for(i=0; i<nBind; i++){
      zRet[i*2] = '?';
      zRet[i*2+1] = (i+1==nBind) ? '\0' : ',';
1789
1790
1791
1792
1793
1794
1795
1796

1797
1798
1799
1800
1801
1802
1803
2047
2048
2049
2050
2051
2052
2053

2054
2055
2056
2057
2058
2059
2060
2061







-
+







    char *zCols = 0;              /* Used to build up list of table cols */
    char *zPk = 0;                /* Used to build up table PK declaration */

    /* Figure out the name of the primary key index for the current table.
    ** This is needed for the argument to "PRAGMA index_xinfo". Set
    ** zIdx to point to a nul-terminated string containing this name. */
    p->rc = prepareAndCollectError(p->dbMain, &pQuery, &p->zErrmsg, 
        "SELECT name FROM sqlite_master WHERE rootpage = ?"
        "SELECT name FROM sqlite_schema WHERE rootpage = ?"
    );
    if( p->rc==SQLITE_OK ){
      sqlite3_bind_int(pQuery, 1, tnum);
      if( SQLITE_ROW==sqlite3_step(pQuery) ){
        zIdx = (const char*)sqlite3_column_text(pQuery, 0);
      }
    }
1952
1953
1954
1955
1956
1957
1958































































































1959
1960
1961
1962
1963
1964
1965
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318







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







    rc = sqlite3_reset(p->objiter.pTmpInsert);
  }

  if( rc!=SQLITE_OK ){
    sqlite3_result_error_code(pCtx, rc);
  }
}

static char *rbuObjIterGetIndexWhere(sqlite3rbu *p, RbuObjIter *pIter){
  sqlite3_stmt *pStmt = 0;
  int rc = p->rc;
  char *zRet = 0;

  assert( pIter->zIdxSql==0 && pIter->nIdxCol==0 && pIter->aIdxCol==0 );

  if( rc==SQLITE_OK ){
    rc = prepareAndCollectError(p->dbMain, &pStmt, &p->zErrmsg,
        "SELECT trim(sql) FROM sqlite_schema WHERE type='index' AND name=?"
    );
  }
  if( rc==SQLITE_OK ){
    int rc2;
    rc = sqlite3_bind_text(pStmt, 1, pIter->zIdx, -1, SQLITE_STATIC);
    if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
      char *zSql = (char*)sqlite3_column_text(pStmt, 0);
      if( zSql ){
        pIter->zIdxSql = zSql = rbuStrndup(zSql, &rc);
      }
      if( zSql ){
        int nParen = 0;           /* Number of open parenthesis */
        int i;
        int iIdxCol = 0;
        int nIdxAlloc = 0;
        for(i=0; zSql[i]; i++){
          char c = zSql[i];

          /* If necessary, grow the pIter->aIdxCol[] array */
          if( iIdxCol==nIdxAlloc ){
            RbuSpan *aIdxCol = (RbuSpan*)sqlite3_realloc(
                pIter->aIdxCol, (nIdxAlloc+16)*sizeof(RbuSpan)
            );
            if( aIdxCol==0 ){
              rc = SQLITE_NOMEM;
              break;
            }
            pIter->aIdxCol = aIdxCol;
            nIdxAlloc += 16;
          }

          if( c=='(' ){
            if( nParen==0 ){
              assert( iIdxCol==0 );
              pIter->aIdxCol[0].zSpan = &zSql[i+1];
            }
            nParen++;
          }
          else if( c==')' ){
            nParen--;
            if( nParen==0 ){
              int nSpan = &zSql[i] - pIter->aIdxCol[iIdxCol].zSpan;
              pIter->aIdxCol[iIdxCol++].nSpan = nSpan;
              i++;
              break;
            }
          }else if( c==',' && nParen==1 ){
            int nSpan = &zSql[i] - pIter->aIdxCol[iIdxCol].zSpan;
            pIter->aIdxCol[iIdxCol++].nSpan = nSpan;
            pIter->aIdxCol[iIdxCol].zSpan = &zSql[i+1];
          }else if( c=='"' || c=='\'' || c=='`' ){
            for(i++; 1; i++){
              if( zSql[i]==c ){
                if( zSql[i+1]!=c ) break;
                i++;
              }
            }
          }else if( c=='[' ){
            for(i++; 1; i++){
              if( zSql[i]==']' ) break;
            }
          }else if( c=='-' && zSql[i+1]=='-' ){
            for(i=i+2; zSql[i] && zSql[i]!='\n'; i++);
            if( zSql[i]=='\0' ) break;
          }else if( c=='/' && zSql[i+1]=='*' ){
            for(i=i+2; zSql[i] && (zSql[i]!='*' || zSql[i+1]!='/'); i++);
            if( zSql[i]=='\0' ) break;
            i++;
          }
        }
        if( zSql[i] ){
          zRet = rbuStrndup(&zSql[i], &rc);
        }
        pIter->nIdxCol = iIdxCol;
      }
    }

    rc2 = sqlite3_finalize(pStmt);
    if( rc==SQLITE_OK ) rc = rc2;
  }

  p->rc = rc;
  return zRet;
}

/*
** Ensure that the SQLite statement handles required to update the 
** target database object currently indicated by the iterator passed 
** as the second argument are available.
*/
static int rbuObjIterPrepareAll(
1982
1983
1984
1985
1986
1987
1988

1989
1990
1991

1992
1993
1994
1995
1996
1997
1998
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353







+



+








    if( zIdx ){
      const char *zTbl = pIter->zTbl;
      char *zImposterCols = 0;    /* Columns for imposter table */
      char *zImposterPK = 0;      /* Primary key declaration for imposter */
      char *zWhere = 0;           /* WHERE clause on PK columns */
      char *zBind = 0;
      char *zPart = 0;
      int nBind = 0;

      assert( pIter->eType!=RBU_PK_VTAB );
      zPart = rbuObjIterGetIndexWhere(p, pIter);
      zCollist = rbuObjIterGetIndexCols(
          p, pIter, &zImposterCols, &zImposterPK, &zWhere, &nBind
      );
      zBind = rbuObjIterGetBindlist(p, nBind);

      /* Create the imposter table used to write to this index. */
      sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 1);
2020
2021
2022
2023
2024
2025
2026









2027
2028

2029
2030


2031
2032

2033
2034
2035
2036
2037

2038
2039

2040
2041
2042
2043

2044
2045
2046

2047
2048

2049


2050
2051
2052

2053




2054
2055
2056
2057
2058
2059

2060
2061
2062
2063
2064
2065
2066
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391

2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403

2404
2405

2406
2407
2408
2409

2410
2411
2412

2413
2414

2415
2416
2417
2418
2419
2420
2421
2422

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







+
+
+
+
+
+
+
+
+

-
+


+
+


+




-
+

-
+



-
+


-
+

-
+

+
+



+
-
+
+
+
+






+







        );
      }

      /* Create the SELECT statement to read keys in sorted order */
      if( p->rc==SQLITE_OK ){
        char *zSql;
        if( rbuIsVacuum(p) ){
          char *zStart = 0;
          if( nOffset ){
            zStart = rbuVacuumIndexStart(p, pIter);
            if( zStart ){
              sqlite3_free(zLimit);
              zLimit = 0;
            }
          }

          zSql = sqlite3_mprintf(
              "SELECT %s, 0 AS rbu_control FROM '%q' ORDER BY %s%s",
              "SELECT %s, 0 AS rbu_control FROM '%q' %s %s %s ORDER BY %s%s",
              zCollist, 
              pIter->zDataTbl,
              zPart, 
              (zStart ? (zPart ? "AND" : "WHERE") : ""), zStart,
              zCollist, zLimit
          );
          sqlite3_free(zStart);
        }else

        if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){
          zSql = sqlite3_mprintf(
              "SELECT %s, rbu_control FROM %s.'rbu_tmp_%q' ORDER BY %s%s",
              "SELECT %s, rbu_control FROM %s.'rbu_tmp_%q' %s ORDER BY %s%s",
              zCollist, p->zStateDb, pIter->zDataTbl,
              zCollist, zLimit
              zPart, zCollist, zLimit
          );
        }else{
          zSql = sqlite3_mprintf(
              "SELECT %s, rbu_control FROM %s.'rbu_tmp_%q' "
              "SELECT %s, rbu_control FROM %s.'rbu_tmp_%q' %s "
              "UNION ALL "
              "SELECT %s, rbu_control FROM '%q' "
              "WHERE typeof(rbu_control)='integer' AND rbu_control!=1 "
              "%s %s typeof(rbu_control)='integer' AND rbu_control!=1 "
              "ORDER BY %s%s",
              zCollist, p->zStateDb, pIter->zDataTbl, 
              zCollist, p->zStateDb, pIter->zDataTbl, zPart,
              zCollist, pIter->zDataTbl, 
              zPart,
              (zPart ? "AND" : "WHERE"),
              zCollist, zLimit
          );
        }
        if( p->rc==SQLITE_OK ){
        p->rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pSelect, pz, zSql);
          p->rc = prepareFreeAndCollectError(p->dbRbu,&pIter->pSelect,pz,zSql);
        }else{
          sqlite3_free(zSql);
        }
      }

      sqlite3_free(zImposterCols);
      sqlite3_free(zImposterPK);
      sqlite3_free(zWhere);
      sqlite3_free(zBind);
      sqlite3_free(zPart);
    }else{
      int bRbuRowid = (pIter->eType==RBU_PK_VTAB)
                    ||(pIter->eType==RBU_PK_NONE)
                    ||(pIter->eType==RBU_PK_EXTERNAL && rbuIsVacuum(p));
      const char *zTbl = pIter->zTbl;       /* Table this step applies to */
      const char *zWrite;                   /* Imposter table name */

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
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547









2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568







+
+



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








        rbuObjIterPrepareTmpInsert(p, pIter, zCollist, zRbuRowid);
      }

      /* Create the SELECT statement to read keys from data_xxx */
      if( p->rc==SQLITE_OK ){
        const char *zRbuRowid = "";
        char *zStart = 0;
        char *zOrder = 0;
        if( bRbuRowid ){
          zRbuRowid = rbuIsVacuum(p) ? ",_rowid_ " : ",rbu_rowid";
        }

        if( rbuIsVacuum(p) ){
          if( nOffset ){
            zStart = rbuVacuumTableStart(p, pIter, bRbuRowid, zWrite);
            if( zStart ){
              sqlite3_free(zLimit);
              zLimit = 0;
            }
          }
          if( bRbuRowid ){
            zOrder = rbuMPrintf(p, "_rowid_");
          }else{
            zOrder = rbuObjIterGetPkList(p, pIter, "", ", ", "");
          }
        }

        if( p->rc==SQLITE_OK ){
        p->rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pSelect, pz,
            sqlite3_mprintf(
              "SELECT %s,%s rbu_control%s FROM '%q'%s", 
              zCollist, 
              (rbuIsVacuum(p) ? "0 AS " : ""),
              zRbuRowid,
              pIter->zDataTbl, zLimit
            )
        );
          p->rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pSelect, pz,
              sqlite3_mprintf(
                "SELECT %s,%s rbu_control%s FROM '%q'%s %s %s %s",
                zCollist, 
                (rbuIsVacuum(p) ? "0 AS " : ""),
                zRbuRowid,
                pIter->zDataTbl, (zStart ? zStart : ""), 
                (zOrder ? "ORDER BY" : ""), zOrder,
                zLimit
              )
          );
        }
        sqlite3_free(zStart);
        sqlite3_free(zOrder);
      }

      sqlite3_free(zWhere);
      sqlite3_free(zOldlist);
      sqlite3_free(zNewlist);
      sqlite3_free(zBindings);
    }
2336
2337
2338
2339
2340
2341
2342
2343

2344
2345
2346
2347
2348
2349
2350
2734
2735
2736
2737
2738
2739
2740

2741
2742
2743
2744
2745
2746
2747
2748







-
+







        break;

      case RBU_STATE_COOKIE:
        pRet->iCookie = (u32)sqlite3_column_int64(pStmt, 1);
        break;

      case RBU_STATE_OALSZ:
        pRet->iOalSz = (u32)sqlite3_column_int64(pStmt, 1);
        pRet->iOalSz = sqlite3_column_int64(pStmt, 1);
        break;

      case RBU_STATE_PHASEONESTEP:
        pRet->nPhaseOneStep = sqlite3_column_int64(pStmt, 1);
        break;

      case RBU_STATE_DATATBL:
2363
2364
2365
2366
2367
2368
2369




2370
2371

2372
2373

2374
2375
2376

2377
2378
2379
2380
2381
2382

2383
2384
2385
2386
2387
2388
2389
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772

2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785

2786
2787
2788
2789
2790
2791
2792
2793







+
+
+
+

-
+


+



+





-
+







  return pRet;
}


/*
** Open the database handle and attach the RBU database as "rbu". If an
** error occurs, leave an error code and message in the RBU handle.
**
** If argument dbMain is not NULL, then it is a database handle already
** open on the target database. Use this handle instead of opening a new
** one.
*/
static void rbuOpenDatabase(sqlite3rbu *p, int *pbRetry){
static void rbuOpenDatabase(sqlite3rbu *p, sqlite3 *dbMain, int *pbRetry){
  assert( p->rc || (p->dbMain==0 && p->dbRbu==0) );
  assert( p->rc || rbuIsVacuum(p) || p->zTarget!=0 );
  assert( dbMain==0 || rbuIsVacuum(p)==0 );

  /* Open the RBU database */
  p->dbRbu = rbuOpenDbhandle(p, p->zRbu, 1);
  p->dbMain = dbMain;

  if( p->rc==SQLITE_OK && rbuIsVacuum(p) ){
    sqlite3_file_control(p->dbRbu, "main", SQLITE_FCNTL_RBUCNT, (void*)p);
    if( p->zState==0 ){
      const char *zFile = sqlite3_db_filename(p->dbRbu, "main");
      p->zState = rbuMPrintf(p, "file://%s-vacuum?modeof=%s", zFile, zFile);
      p->zState = rbuMPrintf(p, "file:///%s-vacuum?modeof=%s", zFile, zFile);
    }
  }

  /* If using separate RBU and state databases, attach the state database to
  ** the RBU db handle now.  */
  if( p->zState ){
    rbuMPrintfExec(p, p->dbRbu, "ATTACH %Q AS stat", p->zState);
2404
2405
2406
2407
2408
2409
2410
2411

2412
2413
2414
2415
2416
2417
2418
2808
2809
2810
2811
2812
2813
2814

2815
2816
2817
2818
2819
2820
2821
2822







-
+







#if 0
  if( rbuIsVacuum(p) ){
    if( p->rc==SQLITE_OK ){
      int rc2;
      int bOk = 0;
      sqlite3_stmt *pCnt = 0;
      p->rc = prepareAndCollectError(p->dbRbu, &pCnt, &p->zErrmsg,
          "SELECT count(*) FROM stat.sqlite_master"
          "SELECT count(*) FROM stat.sqlite_schema"
      );
      if( p->rc==SQLITE_OK 
       && sqlite3_step(pCnt)==SQLITE_ROW
       && 1==sqlite3_column_int(pCnt, 0)
      ){
        bOk = 1;
      }
2508
2509
2510
2511
2512
2513
2514
2515

2516
2517
2518
2519
2520
2521
2522
2912
2913
2914
2915
2916
2917
2918

2919
2920
2921
2922
2923
2924
2925
2926







-
+







        "rbu_target_name", -1, SQLITE_UTF8, (void*)p, rbuTargetNameFunc, 0, 0
    );
  }

  if( p->rc==SQLITE_OK ){
    p->rc = sqlite3_file_control(p->dbMain, "main", SQLITE_FCNTL_RBU, (void*)p);
  }
  rbuMPrintfExec(p, p->dbMain, "SELECT * FROM sqlite_master");
  rbuMPrintfExec(p, p->dbMain, "SELECT * FROM sqlite_schema");

  /* Mark the database file just opened as an RBU target database. If 
  ** this call returns SQLITE_NOTFOUND, then the RBU vfs is not in use.
  ** This is an error.  */
  if( p->rc==SQLITE_OK ){
    p->rc = sqlite3_file_control(p->dbMain, "main", SQLITE_FCNTL_RBU, (void*)p);
  }
2601
2602
2603
2604
2605
2606
2607
2608

2609
2610
2611
2612
2613
2614
2615
3005
3006
3007
3008
3009
3010
3011

3012
3013
3014
3015
3016
3017
3018
3019







-
+








  /* If pState is NULL, then the wal file may not have been opened and
  ** recovered. Running a read-statement here to ensure that doing so
  ** does not interfere with the "capture" process below.  */
  if( pState==0 ){
    p->eStage = 0;
    if( p->rc==SQLITE_OK ){
      p->rc = sqlite3_exec(p->dbMain, "SELECT * FROM sqlite_master", 0, 0, 0);
      p->rc = sqlite3_exec(p->dbMain, "SELECT * FROM sqlite_schema", 0, 0, 0);
    }
  }

  /* Assuming no error has occurred, run a "restart" checkpoint with the
  ** sqlite3rbu.eStage variable set to CAPTURE. This turns on the following
  ** special behaviour in the rbu VFS:
  **
2623
2624
2625
2626
2627
2628
2629
2630

2631
2632
2633
2634

2635
2636
2637
2638
2639
2640
2641
2642
2643
2644

2645
2646
2647
2648
2649
2650
2651
3027
3028
3029
3030
3031
3032
3033

3034
3035
3036
3037

3038
3039
3040
3041
3042
3043
3044
3045
3046
3047

3048
3049
3050
3051
3052
3053
3054
3055







-
+



-
+









-
+







  **     array.
  **
  **   * Calls to xShmLock(UNLOCK) to release the exclusive shm WRITER, 
  **     READ0 and CHECKPOINT locks taken as part of the checkpoint are
  **     no-ops. These locks will not be released until the connection
  **     is closed.
  **
  **   * Attempting to xSync() the database file causes an SQLITE_INTERNAL 
  **   * Attempting to xSync() the database file causes an SQLITE_NOTICE 
  **     error.
  **
  ** As a result, unless an error (i.e. OOM or SQLITE_BUSY) occurs, the
  ** checkpoint below fails with SQLITE_INTERNAL, and leaves the aFrame[]
  ** checkpoint below fails with SQLITE_NOTICE, and leaves the aFrame[]
  ** array populated with a set of (frame -> page) mappings. Because the 
  ** WRITER, CHECKPOINT and READ0 locks are still held, it is safe to copy 
  ** data from the wal file into the database file according to the 
  ** contents of aFrame[].
  */
  if( p->rc==SQLITE_OK ){
    int rc2;
    p->eStage = RBU_STAGE_CAPTURE;
    rc2 = sqlite3_exec(p->dbMain, "PRAGMA main.wal_checkpoint=restart", 0, 0,0);
    if( rc2!=SQLITE_INTERNAL ) p->rc = rc2;
    if( rc2!=SQLITE_NOTICE ) p->rc = rc2;
  }

  if( p->rc==SQLITE_OK && p->nFrame>0 ){
    p->eStage = RBU_STAGE_CKPT;
    p->nStep = (pState ? pState->nRow : 0);
    p->aBuf = rbuMalloc(p, p->pgsz);
    p->iWalCksum = rbuShmChecksum(p);
2683
2684
2685
2686
2687
2688
2689
2690

2691
2692
2693
2694
2695
2696
2697
3087
3088
3089
3090
3091
3092
3093

3094
3095
3096
3097
3098
3099
3100
3101







-
+







*/
static int rbuCaptureWalRead(sqlite3rbu *pRbu, i64 iOff, int iAmt){
  const u32 mReq = (1<<WAL_LOCK_WRITE)|(1<<WAL_LOCK_CKPT)|(1<<WAL_LOCK_READ0);
  u32 iFrame;

  if( pRbu->mLock!=mReq ){
    pRbu->rc = SQLITE_BUSY;
    return SQLITE_INTERNAL;
    return SQLITE_NOTICE_RBU;
  }

  pRbu->pgsz = iAmt;
  if( pRbu->nFrame==pRbu->nFrameAlloc ){
    int nNew = (pRbu->nFrameAlloc ? pRbu->nFrameAlloc : 64) * 2;
    RbuFrame *aNew;
    aNew = (RbuFrame*)sqlite3_realloc64(pRbu->aFrame, nNew * sizeof(RbuFrame));
2735
2736
2737
2738
2739
2740
2741
2742


2743
2744
2745
2746
2747
2748
2749
2750






















2751
2752
2753
2754
2755
2756
2757
3139
3140
3141
3142
3143
3144
3145

3146
3147
3148







3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177







-
+
+

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








  iOff = (i64)(pFrame->iDbPage-1) * p->pgsz;
  p->rc = pDb->pMethods->xWrite(pDb, p->aBuf, p->pgsz, iOff);
}


/*
** Take an EXCLUSIVE lock on the database file.
** Take an EXCLUSIVE lock on the database file. Return SQLITE_OK if
** successful, or an SQLite error code otherwise.
*/
static void rbuLockDatabase(sqlite3rbu *p){
  sqlite3_file *pReal = p->pTargetFd->pReal;
  assert( p->rc==SQLITE_OK );
  p->rc = pReal->pMethods->xLock(pReal, SQLITE_LOCK_SHARED);
  if( p->rc==SQLITE_OK ){
    p->rc = pReal->pMethods->xLock(pReal, SQLITE_LOCK_EXCLUSIVE);
  }
static int rbuLockDatabase(sqlite3 *db){
  int rc = SQLITE_OK;
  sqlite3_file *fd = 0;
  sqlite3_file_control(db, "main", SQLITE_FCNTL_FILE_POINTER, &fd);

  if( fd->pMethods ){
    rc = fd->pMethods->xLock(fd, SQLITE_LOCK_SHARED);
    if( rc==SQLITE_OK ){
      rc = fd->pMethods->xLock(fd, SQLITE_LOCK_EXCLUSIVE);
    }
  }
  return rc;
}

/*
** Return true if the database handle passed as the only argument
** was opened with the rbu_exclusive_checkpoint=1 URI parameter
** specified. Or false otherwise.
*/
static int rbuExclusiveCheckpoint(sqlite3 *db){
  const char *zUri = sqlite3_db_filename(db, 0);
  return sqlite3_uri_boolean(zUri, RBU_EXCLUSIVE_CHECKPOINT, 0);
}

#if defined(_WIN32_WCE)
static LPWSTR rbuWinUtf8ToUnicode(const char *zFilename){
  int nChar;
  LPWSTR zWideFilename;

2801
2802
2803
2804
2805
2806
2807
2808

2809
2810
2811


2812
2813
2814
2815
2816
2817
2818






2819
2820
2821
2822
2823
2824

2825
2826

2827
2828
2829
2830

2831
2832
2833


2834
2835
2836
2837

2838
2839
2840
2841
2842




2843
2844
2845
2846
2847
2848
2849











2850
2851
2852
2853
2854
2855
2856
2857
3221
3222
3223
3224
3225
3226
3227

3228



3229
3230
3231






3232
3233
3234
3235
3236
3237
3238





3239


3240




3241



3242
3243




3244





3245
3246
3247
3248







3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259

3260
3261
3262
3263
3264
3265
3266







-
+
-
-
-
+
+

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

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







    /* Move the *-oal file to *-wal. At this point connection p->db is
    ** holding a SHARED lock on the target database file (because it is
    ** in WAL mode). So no other connection may be writing the db. 
    **
    ** In order to ensure that there are no database readers, an EXCLUSIVE
    ** lock is obtained here before the *-oal is moved to *-wal.
    */
    rbuLockDatabase(p);
    sqlite3 *dbMain = 0;
    if( p->rc==SQLITE_OK ){
      rbuFileSuffix3(zBase, zWal);
      rbuFileSuffix3(zBase, zOal);
    rbuFileSuffix3(zBase, zWal);
    rbuFileSuffix3(zBase, zOal);

      /* Re-open the databases. */
      rbuObjIterFinalize(&p->objiter);
      sqlite3_close(p->dbRbu);
      sqlite3_close(p->dbMain);
      p->dbMain = 0;
      p->dbRbu = 0;
    /* Re-open the databases. */
    rbuObjIterFinalize(&p->objiter);
    sqlite3_close(p->dbRbu);
    sqlite3_close(p->dbMain);
    p->dbMain = 0;
    p->dbRbu = 0;

#if defined(_WIN32_WCE)
      {
        LPWSTR zWideOal;
        LPWSTR zWideWal;

    dbMain = rbuOpenDbhandle(p, p->zTarget, 1);
        zWideOal = rbuWinUtf8ToUnicode(zOal);
        if( zWideOal ){
    if( dbMain ){
          zWideWal = rbuWinUtf8ToUnicode(zWal);
          if( zWideWal ){
            if( MoveFileW(zWideOal, zWideWal) ){
              p->rc = SQLITE_OK;
      assert( p->rc==SQLITE_OK );
            }else{
              p->rc = SQLITE_IOERR;
            }
      p->rc = rbuLockDatabase(dbMain);
    }
            sqlite3_free(zWideWal);
          }else{
            p->rc = SQLITE_IOERR_NOMEM;
          }

          sqlite3_free(zWideOal);
        }else{
          p->rc = SQLITE_IOERR_NOMEM;
        }
      }
    if( p->rc==SQLITE_OK ){
      p->rc = p->xRename(p->pRenameArg, zOal, zWal);
    }

#else
      p->rc = rename(zOal, zWal) ? SQLITE_IOERR : SQLITE_OK;
#endif

      if( p->rc==SQLITE_OK ){
        rbuOpenDatabase(p, 0);
        rbuSetupCheckpoint(p, 0);
    if( p->rc!=SQLITE_OK 
     || rbuIsVacuum(p) 
     || rbuExclusiveCheckpoint(dbMain)==0 
    ){
      sqlite3_close(dbMain);
      dbMain = 0;
    }

    if( p->rc==SQLITE_OK ){
      rbuOpenDatabase(p, dbMain, 0);
      rbuSetupCheckpoint(p, 0);
      }
    }
  }

  sqlite3_free(zWal);
  sqlite3_free(zOal);
}

3192
3193
3194
3195
3196
3197
3198
3199

3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214

3215
3216
3217
3218
3219
3220

3221
3222
3223
3224
3225
3226
3227
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







-
+














-
+





-
+







  sqlite3_stmt *pSql = 0;
  sqlite3_stmt *pInsert = 0;

  assert( rbuIsVacuum(p) );
  p->rc = sqlite3_exec(p->dbMain, "PRAGMA writable_schema=1", 0,0, &p->zErrmsg);
  if( p->rc==SQLITE_OK ){
    p->rc = prepareAndCollectError(p->dbRbu, &pSql, &p->zErrmsg, 
      "SELECT sql FROM sqlite_master WHERE sql!='' AND rootpage!=0"
      "SELECT sql FROM sqlite_schema WHERE sql!='' AND rootpage!=0"
      " AND name!='sqlite_sequence' "
      " ORDER BY type DESC"
    );
  }

  while( p->rc==SQLITE_OK && sqlite3_step(pSql)==SQLITE_ROW ){
    const char *zSql = (const char*)sqlite3_column_text(pSql, 0);
    p->rc = sqlite3_exec(p->dbMain, zSql, 0, 0, &p->zErrmsg);
  }
  rbuFinalize(p, pSql);
  if( p->rc!=SQLITE_OK ) return;

  if( p->rc==SQLITE_OK ){
    p->rc = prepareAndCollectError(p->dbRbu, &pSql, &p->zErrmsg, 
        "SELECT * FROM sqlite_master WHERE rootpage=0 OR rootpage IS NULL" 
        "SELECT * FROM sqlite_schema WHERE rootpage=0 OR rootpage IS NULL" 
    );
  }

  if( p->rc==SQLITE_OK ){
    p->rc = prepareAndCollectError(p->dbMain, &pInsert, &p->zErrmsg, 
        "INSERT INTO sqlite_master VALUES(?,?,?,?,?)"
        "INSERT INTO sqlite_schema VALUES(?,?,?,?,?)"
    );
  }

  while( p->rc==SQLITE_OK && sqlite3_step(pSql)==SQLITE_ROW ){
    int i;
    for(i=0; i<5; i++){
      sqlite3_bind_value(pInsert, i+1, sqlite3_column_value(pSql, i));
3417
3418
3419
3420
3421
3422
3423
3424


3425
3426
3427
3428
3429
3430
3431
3826
3827
3828
3829
3830
3831
3832

3833
3834
3835
3836
3837
3838
3839
3840
3841







-
+
+







** If there is a "*-oal" file in the file-system corresponding to the
** target database in the file-system, delete it. If an error occurs,
** leave an error code and error message in the rbu handle.
*/
static void rbuDeleteOalFile(sqlite3rbu *p){
  char *zOal = rbuMPrintf(p, "%s-oal", p->zTarget);
  if( zOal ){
    sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
    sqlite3_vfs *pVfs = 0;
    sqlite3_file_control(p->dbMain, "main", SQLITE_FCNTL_VFS_POINTER, &pVfs);
    assert( pVfs && p->rc==SQLITE_OK && p->zErrmsg==0 );
    pVfs->xDelete(pVfs, zOal, 0);
    sqlite3_free(zOal);
  }
}

/*
3471
3472
3473
3474
3475
3476
3477

3478
3479
3480
3481
3482


3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496

3497
3498
3499
3500
3501
3502
3503
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







+



-
-
+
+













-
+







  int nVal,
  sqlite3_value **apVal
){
  sqlite3rbu *p = (sqlite3rbu*)sqlite3_user_data(pCtx);
  sqlite3_stmt *pStmt = 0;
  char *zErrmsg = 0;
  int rc;
  sqlite3 *db = (rbuIsVacuum(p) ? p->dbRbu : p->dbMain);

  assert( nVal==1 );
  
  rc = prepareFreeAndCollectError(p->dbMain, &pStmt, &zErrmsg, 
      sqlite3_mprintf("SELECT count(*) FROM sqlite_master "
  rc = prepareFreeAndCollectError(db, &pStmt, &zErrmsg, 
      sqlite3_mprintf("SELECT count(*) FROM sqlite_schema "
        "WHERE type='index' AND tbl_name = %Q", sqlite3_value_text(apVal[0]))
  );
  if( rc!=SQLITE_OK ){
    sqlite3_result_error(pCtx, zErrmsg, -1);
  }else{
    int nIndex = 0;
    if( SQLITE_ROW==sqlite3_step(pStmt) ){
      nIndex = sqlite3_column_int(pStmt, 0);
    }
    rc = sqlite3_finalize(pStmt);
    if( rc==SQLITE_OK ){
      sqlite3_result_int(pCtx, nIndex);
    }else{
      sqlite3_result_error(pCtx, sqlite3_errmsg(p->dbMain), -1);
      sqlite3_result_error(pCtx, sqlite3_errmsg(db), -1);
    }
  }

  sqlite3_free(zErrmsg);
}

/*
3526
3527
3528
3529
3530
3531
3532
3533

3534
3535
3536
3537
3538
3539
3540
3937
3938
3939
3940
3941
3942
3943

3944
3945
3946
3947
3948
3949
3950
3951







-
+







        "rbu_index_cnt", 1, SQLITE_UTF8, (void*)p, rbuIndexCntFunc, 0, 0
    );
  
    /* Check for the rbu_count table. If it does not exist, or if an error
    ** occurs, nPhaseOneStep will be left set to -1. */
    if( p->rc==SQLITE_OK ){
      p->rc = prepareAndCollectError(p->dbRbu, &pStmt, &p->zErrmsg,
          "SELECT 1 FROM sqlite_master WHERE tbl_name = 'rbu_count'"
          "SELECT 1 FROM sqlite_schema WHERE tbl_name = 'rbu_count'"
      );
    }
    if( p->rc==SQLITE_OK ){
      if( SQLITE_ROW==sqlite3_step(pStmt) ){
        bExists = 1;
      }
      p->rc = sqlite3_finalize(pStmt);
3568
3569
3570
3571
3572
3573
3574

3575
3576
3577
3578
3579
3580
3581
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993







+








  p = (sqlite3rbu*)sqlite3_malloc64(nByte);
  if( p ){
    RbuState *pState = 0;

    /* Create the custom VFS. */
    memset(p, 0, sizeof(sqlite3rbu));
    sqlite3rbu_rename_handler(p, 0, 0);
    rbuCreateVfs(p);

    /* Open the target, RBU and state databases */
    if( p->rc==SQLITE_OK ){
      char *pCsr = (char*)&p[1];
      int bRetry = 0;
      if( zTarget ){
3593
3594
3595
3596
3597
3598
3599
3600

3601
3602

3603
3604
3605
3606
3607
3608
3609
4005
4006
4007
4008
4009
4010
4011

4012
4013

4014
4015
4016
4017
4018
4019
4020
4021







-
+

-
+







      /* If the first attempt to open the database file fails and the bRetry
      ** flag it set, this means that the db was not opened because it seemed
      ** to be a wal-mode db. But, this may have happened due to an earlier
      ** RBU vacuum operation leaving an old wal file in the directory.
      ** If this is the case, it will have been checkpointed and deleted
      ** when the handle was closed and a second attempt to open the 
      ** database may succeed.  */
      rbuOpenDatabase(p, &bRetry);
      rbuOpenDatabase(p, 0, &bRetry);
      if( bRetry ){
        rbuOpenDatabase(p, 0);
        rbuOpenDatabase(p, 0, 0);
      }
    }

    if( p->rc==SQLITE_OK ){
      pState = rbuLoadState(p);
      assert( pState || p->rc!=SQLITE_OK );
      if( p->rc==SQLITE_OK ){
3690
3691
3692
3693
3694
3695
3696








3697
3698
3699
3700
3701
3702
3703
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123







+
+
+
+
+
+
+
+







          if( p->rc==SQLITE_OK ){
            rbuSetupOal(p, pState);
          }
        }
      }else if( p->eStage==RBU_STAGE_MOVE ){
        /* no-op */
      }else if( p->eStage==RBU_STAGE_CKPT ){
        if( !rbuIsVacuum(p) && rbuExclusiveCheckpoint(p->dbMain) ){
          /* If the rbu_exclusive_checkpoint=1 URI parameter was specified
          ** and an incremental checkpoint is being resumed, attempt an
          ** exclusive lock on the db file. If this fails, so be it.  */
          p->eStage = RBU_STAGE_DONE;
          rbuLockDatabase(p->dbMain);
          p->eStage = RBU_STAGE_CKPT;
        }
        rbuSetupCheckpoint(p, pState);
      }else if( p->eStage==RBU_STAGE_DONE ){
        p->rc = SQLITE_DONE;
      }else{
        p->rc = SQLITE_CORRUPT;
      }
    }
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
4147
4148
4149
4150
4151
4152
4153

4154
4155
4156
4157
4158
4159
4160







-







*/
sqlite3rbu *sqlite3rbu_open(
  const char *zTarget, 
  const char *zRbu,
  const char *zState
){
  if( zTarget==0 || zRbu==0 ){ return rbuMisuseError(); }
  /* TODO: Check that zTarget and zRbu are non-NULL */
  return openRbuHandle(zTarget, zRbu, zState);
}

/*
** Open a handle to begin or resume an RBU VACUUM operation.
*/
sqlite3rbu *sqlite3rbu_vacuum(
3941
3942
3943
3944
3945
3946
3947
3948




3949
3950
3951
3952
3953
3954
















































3955
3956
3957
3958
3959
3960
3961
4360
4361
4362
4363
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
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431







-
+
+
+
+






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







  p->rc = rc;
  rbuSaveState(p, p->eStage);
  rc = p->rc;

  if( p->eStage==RBU_STAGE_OAL ){
    assert( rc!=SQLITE_DONE );
    if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbRbu, "COMMIT", 0, 0, 0);
    if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbRbu, "BEGIN IMMEDIATE", 0, 0, 0);
    if( rc==SQLITE_OK ){ 
      const char *zBegin = rbuIsVacuum(p) ? "BEGIN" : "BEGIN IMMEDIATE";
      rc = sqlite3_exec(p->dbRbu, zBegin, 0, 0, 0);
    }
    if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbMain, "BEGIN IMMEDIATE", 0, 0,0);
  }

  p->rc = rc;
  return rc;
}

/*
** Default xRename callback for RBU.
*/
static int xDefaultRename(void *pArg, const char *zOld, const char *zNew){
  int rc = SQLITE_OK;
#if defined(_WIN32_WCE)
  {
    LPWSTR zWideOld;
    LPWSTR zWideNew;

    zWideOld = rbuWinUtf8ToUnicode(zOld);
    if( zWideOld ){
      zWideNew = rbuWinUtf8ToUnicode(zNew);
      if( zWideNew ){
        if( MoveFileW(zWideOld, zWideNew) ){
          rc = SQLITE_OK;
        }else{
          rc = SQLITE_IOERR;
        }
        sqlite3_free(zWideNew);
      }else{
        rc = SQLITE_IOERR_NOMEM;
      }
      sqlite3_free(zWideOld);
    }else{
      rc = SQLITE_IOERR_NOMEM;
    }
  }
#else
  rc = rename(zOld, zNew) ? SQLITE_IOERR : SQLITE_OK;
#endif
  return rc;
}

void sqlite3rbu_rename_handler(
  sqlite3rbu *pRbu, 
  void *pArg,
  int (*xRename)(void *pArg, const char *zOld, const char *zNew)
){
  if( xRename ){
    pRbu->xRename = xRename;
    pRbu->pRenameArg = pArg;
  }else{
    pRbu->xRename = xDefaultRename;
    pRbu->pRenameArg = 0;
  }
}

/**************************************************************************
** Beginning of RBU VFS shim methods. The VFS shim modifies the behaviour
** of a standard VFS in the following ways:
**
** 1. Whenever the first page of a main database file is read or 
**    written, the value of the change-counter cookie is stored in
4005
4006
4007
4008
4009
4010
4011
4012

4013
4014
4015
4016
4017
4018
4019
4475
4476
4477
4478
4479
4480
4481

4482
4483
4484
4485
4486
4487
4488
4489







-
+







**     all xWrite() calls on the target database file perform no IO. 
**     Instead the frame and page numbers that would be read and written
**     are recorded. Additionally, successful attempts to obtain exclusive
**     xShmLock() WRITER, CHECKPOINTER and READ0 locks on the target 
**     database file are recorded. xShmLock() calls to unlock the same
**     locks are no-ops (so that once obtained, these locks are never
**     relinquished). Finally, calls to xSync() on the target database
**     file fail with SQLITE_INTERNAL errors.
**     file fail with SQLITE_NOTICE errors.
*/

static void rbuUnlockShm(rbu_file *p){
  assert( p->openFlags & SQLITE_OPEN_MAIN_DB );
  if( p->pRbu ){
    int (*xShmLock)(sqlite3_file*,int,int,int) = p->pReal->pMethods->xShmLock;
    int i;
4114
4115
4116
4117
4118
4119
4120

4121
4122

4123


4124
4125
4126
4127
4128
4129
4130
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594

4595
4596
4597
4598
4599
4600
4601
4602
4603







+


+
-
+
+







    sqlite3_free(p->apShm[i]);
  }
  sqlite3_free(p->apShm);
  p->apShm = 0;
  sqlite3_free(p->zDel);

  if( p->openFlags & SQLITE_OPEN_MAIN_DB ){
    const sqlite3_io_methods *pMeth = p->pReal->pMethods;
    rbuMainlistRemove(p);
    rbuUnlockShm(p);
    if( pMeth->iVersion>1 && pMeth->xShmUnmap ){
    p->pReal->pMethods->xShmUnmap(p->pReal, 0);
      pMeth->xShmUnmap(p->pReal, 0);
    }
  }
  else if( (p->openFlags & SQLITE_OPEN_DELETEONCLOSE) && p->pRbu ){
    rbuUpdateTempSize(p, 0);
  }
  assert( p->pMainNext==0 && p->pRbuVfs->pMain!=p );

  /* Close the underlying file handle */
4284
4285
4286
4287
4288
4289
4290
4291

4292
4293
4294
4295
4296
4297
4298
4757
4758
4759
4760
4761
4762
4763

4764
4765
4766
4767
4768
4769
4770
4771







-
+







/*
** Sync an rbuVfs-file.
*/
static int rbuVfsSync(sqlite3_file *pFile, int flags){
  rbu_file *p = (rbu_file *)pFile;
  if( p->pRbu && p->pRbu->eStage==RBU_STAGE_CAPTURE ){
    if( p->openFlags & SQLITE_OPEN_MAIN_DB ){
      return SQLITE_INTERNAL;
      return SQLITE_NOTICE_RBU;
    }
    return SQLITE_OK;
  }
  return p->pReal->pMethods->xSync(p->pReal, flags);
}

/*
4380
4381
4382
4383
4384
4385
4386
4387
4388

4389
4390
4391
4392
4393
4394
4395
4396
4853
4854
4855
4856
4857
4858
4859


4860

4861
4862
4863
4864
4865
4866
4867







-
-
+
-







      rc = xControl(p->pReal, SQLITE_FCNTL_ZIPVFS, &dummy);
      if( rc==SQLITE_OK ){
        rc = SQLITE_ERROR;
        pRbu->zErrmsg = sqlite3_mprintf("rbu/zipvfs setup error");
      }else if( rc==SQLITE_NOTFOUND ){
        pRbu->pTargetFd = p;
        p->pRbu = pRbu;
        if( p->openFlags & SQLITE_OPEN_MAIN_DB ){
          rbuMainlistAdd(p);
        rbuMainlistAdd(p);
        }
        if( p->pWalFd ) p->pWalFd->pRbu = pRbu;
        rc = SQLITE_OK;
      }
    }
    return rc;
  }
  else if( op==SQLITE_FCNTL_RBUCNT ){
4437
4438
4439
4440
4441
4442
4443


4444
4445




4446
4447
4448


4449
4450
4451
4452
4453

4454
4455
4456
4457
4458
4459
4460
4461
4462

4463
4464
4465
4466
4467
4468
4469
4908
4909
4910
4911
4912
4913
4914
4915
4916


4917
4918
4919
4920



4921
4922
4923
4924
4925


4926


4927
4928

4929
4930
4931

4932
4933
4934
4935
4936
4937
4938
4939







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



-
-
+
-
-


-



-
+







  int rc = SQLITE_OK;

#ifdef SQLITE_AMALGAMATION
    assert( WAL_CKPT_LOCK==1 );
#endif

  assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) );
  if( pRbu && (
       pRbu->eStage==RBU_STAGE_OAL 
  if( pRbu && (pRbu->eStage==RBU_STAGE_OAL || pRbu->eStage==RBU_STAGE_MOVE) ){
    /* Magic number 1 is the WAL_CKPT_LOCK lock. Preventing SQLite from
    || pRbu->eStage==RBU_STAGE_MOVE 
    || pRbu->eStage==RBU_STAGE_DONE
  )){
    /* Prevent SQLite from taking a shm-lock on the target file when it 
    ** taking this lock also prevents any checkpoints from occurring. 
    ** todo: really, it's not clear why this might occur, as 
    ** wal_autocheckpoint ought to be turned off.  */
    ** is supplying heap memory to the upper layer in place of *-shm 
    ** segments. */
    if( ofst==WAL_LOCK_CKPT && n==1 ) rc = SQLITE_BUSY;
  }else{
    int bCapture = 0;
    if( n==1 && (flags & SQLITE_SHM_EXCLUSIVE)
     && pRbu && pRbu->eStage==RBU_STAGE_CAPTURE
    if( pRbu && pRbu->eStage==RBU_STAGE_CAPTURE ){
     && (ofst==WAL_LOCK_WRITE || ofst==WAL_LOCK_CKPT || ofst==WAL_LOCK_READ0)
    ){
      bCapture = 1;
    }

    if( bCapture==0 || 0==(flags & SQLITE_SHM_UNLOCK) ){
      rc = p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags);
      if( bCapture && rc==SQLITE_OK ){
        pRbu->mLock |= (1 << ofst);
        pRbu->mLock |= ((1<<n) - 1) << ofst;
      }
    }
  }

  return rc;
}

4481
4482
4483
4484
4485
4486
4487
4488

4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
















4500
4501

4502
4503
4504
4505
4506
4507
4508
4951
4952
4953
4954
4955
4956
4957

4958











4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974


4975
4976
4977
4978
4979
4980
4981
4982







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







  int rc = SQLITE_OK;
  int eStage = (p->pRbu ? p->pRbu->eStage : 0);

  /* If not in RBU_STAGE_OAL, allow this call to pass through. Or, if this
  ** rbu is in the RBU_STAGE_OAL state, use heap memory for *-shm space 
  ** instead of a file on disk.  */
  assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) );
  if( eStage==RBU_STAGE_OAL || eStage==RBU_STAGE_MOVE ){
  if( eStage==RBU_STAGE_OAL ){
    if( iRegion<=p->nShm ){
      int nByte = (iRegion+1) * sizeof(char*);
      char **apNew = (char**)sqlite3_realloc64(p->apShm, nByte);
      if( apNew==0 ){
        rc = SQLITE_NOMEM;
      }else{
        memset(&apNew[p->nShm], 0, sizeof(char*) * (1 + iRegion - p->nShm));
        p->apShm = apNew;
        p->nShm = iRegion+1;
      }
    }
    sqlite3_int64 nByte = (iRegion+1) * sizeof(char*);
    char **apNew = (char**)sqlite3_realloc64(p->apShm, nByte);

    /* This is an RBU connection that uses its own heap memory for the
    ** pages of the *-shm file. Since no other process can have run
    ** recovery, the connection must request *-shm pages in order
    ** from start to finish.  */
    assert( iRegion==p->nShm );
    if( apNew==0 ){
      rc = SQLITE_NOMEM;
    }else{
      memset(&apNew[p->nShm], 0, sizeof(char*) * (1 + iRegion - p->nShm));
      p->apShm = apNew;
      p->nShm = iRegion+1;
    }


    if( rc==SQLITE_OK && p->apShm[iRegion]==0 ){
    if( rc==SQLITE_OK ){
      char *pNew = (char*)sqlite3_malloc64(szRegion);
      if( pNew==0 ){
        rc = SQLITE_NOMEM;
      }else{
        memset(pNew, 0, szRegion);
        p->apShm[iRegion] = pNew;
      }
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
5018
5019
5020
5021
5022
5023
5024



























5025
5026
5027
5028
5029
5030
5031







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







    /* Release the checkpointer and writer locks */
    rbuUnlockShm(p);
    rc = p->pReal->pMethods->xShmUnmap(p->pReal, delFlag);
  }
  return rc;
}

/* 
** A main database named zName has just been opened. The following 
** function returns a pointer to a buffer owned by SQLite that contains
** the name of the *-wal file this db connection will use. SQLite
** happens to pass a pointer to this buffer when using xAccess()
** or xOpen() to operate on the *-wal file.  
*/
static const char *rbuMainToWal(const char *zName, int flags){
  int n = (int)strlen(zName);
  const char *z = &zName[n];
  if( flags & SQLITE_OPEN_URI ){
    int odd = 0;
    while( 1 ){
      if( z[0]==0 ){
        odd = 1 - odd;
        if( odd && z[1]==0 ) break;
      }
      z++;
    }
    z += 2;
  }else{
    while( *z==0 ) z++;
  }
  z += (n + 8 + 1);
  return z;
}

/*
** Open an rbu file handle.
*/
static int rbuVfsOpen(
  sqlite3_vfs *pVfs,
  const char *zName,
  sqlite3_file *pFile,
4601
4602
4603
4604
4605
4606
4607



















4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626

4627
4628
4629
4630
4631
4632

4633
4634
4635
4636
4637

4638
4639
4640

4641

4642
4643

4644
4645
4646
4647

4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091

5092
5093
5094
5095
5096
5097

5098





5099

5100

5101

5102
5103

5104




5105






5106
5107
5108
5109
5110
5111
5112







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


















-
+





-
+
-
-
-
-
-
+
-

-
+
-
+

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







    rbuVfsDeviceCharacteristics,  /* xDeviceCharacteristics */
    rbuVfsShmMap,                 /* xShmMap */
    rbuVfsShmLock,                /* xShmLock */
    rbuVfsShmBarrier,             /* xShmBarrier */
    rbuVfsShmUnmap,               /* xShmUnmap */
    0, 0                          /* xFetch, xUnfetch */
  };
  static sqlite3_io_methods rbuvfs_io_methods1 = {
    1,                            /* iVersion */
    rbuVfsClose,                  /* xClose */
    rbuVfsRead,                   /* xRead */
    rbuVfsWrite,                  /* xWrite */
    rbuVfsTruncate,               /* xTruncate */
    rbuVfsSync,                   /* xSync */
    rbuVfsFileSize,               /* xFileSize */
    rbuVfsLock,                   /* xLock */
    rbuVfsUnlock,                 /* xUnlock */
    rbuVfsCheckReservedLock,      /* xCheckReservedLock */
    rbuVfsFileControl,            /* xFileControl */
    rbuVfsSectorSize,             /* xSectorSize */
    rbuVfsDeviceCharacteristics,  /* xDeviceCharacteristics */
    0, 0, 0, 0, 0, 0
  };



  rbu_vfs *pRbuVfs = (rbu_vfs*)pVfs;
  sqlite3_vfs *pRealVfs = pRbuVfs->pRealVfs;
  rbu_file *pFd = (rbu_file *)pFile;
  int rc = SQLITE_OK;
  const char *zOpen = zName;
  int oflags = flags;

  memset(pFd, 0, sizeof(rbu_file));
  pFd->pReal = (sqlite3_file*)&pFd[1];
  pFd->pRbuVfs = pRbuVfs;
  pFd->openFlags = flags;
  if( zName ){
    if( flags & SQLITE_OPEN_MAIN_DB ){
      /* A main database has just been opened. The following block sets
      ** (pFd->zWal) to point to a buffer owned by SQLite that contains
      ** the name of the *-wal file this db connection will use. SQLite
      ** happens to pass a pointer to this buffer when using xAccess()
      ** or xOpen() to operate on the *-wal file.  */
      pFd->zWal = rbuMainToWal(zName, flags);
      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");
            zOpen = sqlite3_db_filename(pDb->pRbu->dbRbu, "main");
            zBase = rbuMainToWal(zBase, SQLITE_OPEN_URI);
            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;
4669
4670
4671
4672
4673
4674
4675

4676
4677
4678



4679


4680
4681
4682
4683
4684
4685
4686
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134

5135
5136
5137
5138
5139
5140
5141
5142
5143







+



+
+
+
-
+
+







    zOpen = 0;
  }

  if( rc==SQLITE_OK ){
    rc = pRealVfs->xOpen(pRealVfs, zOpen, pFd->pReal, oflags, pOutFlags);
  }
  if( pFd->pReal->pMethods ){
    const sqlite3_io_methods *pMeth = pFd->pReal->pMethods;
    /* The xOpen() operation has succeeded. Set the sqlite3_file.pMethods
    ** pointer and, if the file is a main database file, link it into the
    ** mutex protected linked list of all such files.  */
    if( pMeth->iVersion<2 || pMeth->xShmLock==0 ){
      pFile->pMethods = &rbuvfs_io_methods1;
    }else{
    pFile->pMethods = &rbuvfs_io_methods;
      pFile->pMethods = &rbuvfs_io_methods;
    }
    if( flags & SQLITE_OPEN_MAIN_DB ){
      rbuMainlistAdd(pFd);
    }
  }else{
    sqlite3_free(pFd->zDel);
  }

4723
4724
4725
4726
4727
4728
4729
4730


4731
4732
4733
4734
4735
4736
4737
5180
5181
5182
5183
5184
5185
5186

5187
5188
5189
5190
5191
5192
5193
5194
5195







-
+
+







  **   b) if the *-wal file does not exist, claim that it does anyway,
  **      causing SQLite to call xOpen() to open it. This call will also
  **      be intercepted (see the rbuVfsOpen() function) and the *-oal
  **      file opened instead.
  */
  if( rc==SQLITE_OK && flags==SQLITE_ACCESS_EXISTS ){
    rbu_file *pDb = rbuFindMaindb(pRbuVfs, zPath, 1);
    if( pDb && pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){
    if( pDb && pDb->pRbu->eStage==RBU_STAGE_OAL ){
      assert( pDb->pRbu );
      if( *pResOut ){
        rc = SQLITE_CANTOPEN;
      }else{
        sqlite3_int64 sz = 0;
        rc = rbuVfsFileSize(&pDb->base, &sz);
        *pResOut = (sz>0);
      }

Changes to ext/rbu/sqlite3rbu.h.

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












-
+





-
+

-
+



-
-
+
+


-
+





-
+




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

-
-
+
+















-
+

-
+
















-
+


-
+














-
+

-
+


-
+






-
-
-
-
+
+
+
+







/*
** 2014 August 30
**
** 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 contains the public interface for the RBU extension. 
** This file contains the public interface for the RBU extension.
*/

/*
** SUMMARY
**
** Writing a transaction containing a large number of operations on 
** Writing a transaction containing a large number of operations on
** b-tree indexes that are collectively larger than the available cache
** memory can be very inefficient. 
** memory can be very inefficient.
**
** The problem is that in order to update a b-tree, the leaf page (at least)
** containing the entry being inserted or deleted must be modified. If the
** working set of leaves is larger than the available cache memory, then a 
** single leaf that is modified more than once as part of the transaction 
** working set of leaves is larger than the available cache memory, then a
** single leaf that is modified more than once as part of the transaction
** may be loaded from or written to the persistent media multiple times.
** Additionally, because the index updates are likely to be applied in
** random order, access to pages within the database is also likely to be in 
** random order, access to pages within the database is also likely to be in
** random order, which is itself quite inefficient.
**
** One way to improve the situation is to sort the operations on each index
** by index key before applying them to the b-tree. This leads to an IO
** pattern that resembles a single linear scan through the index b-tree,
** and all but guarantees each modified leaf page is loaded and stored 
** and all but guarantees each modified leaf page is loaded and stored
** exactly once. SQLite uses this trick to improve the performance of
** CREATE INDEX commands. This extension allows it to be used to improve
** the performance of large transactions on existing databases.
**
** Additionally, this extension allows the work involved in writing the 
** large transaction to be broken down into sub-transactions performed 
** sequentially by separate processes. This is useful if the system cannot 
** guarantee that a single update process will run for long enough to apply 
** the entire update, for example because the update is being applied on a 
** mobile device that is frequently rebooted. Even after the writer process 
** Additionally, this extension allows the work involved in writing the
** large transaction to be broken down into sub-transactions performed
** sequentially by separate processes. This is useful if the system cannot
** guarantee that a single update process will run for long enough to apply
** the entire update, for example because the update is being applied on a
** mobile device that is frequently rebooted. Even after the writer process
** has committed one or more sub-transactions, other database clients continue
** to read from the original database snapshot. In other words, partially 
** applied transactions are not visible to other clients. 
** to read from the original database snapshot. In other words, partially
** applied transactions are not visible to other clients.
**
** "RBU" stands for "Resumable Bulk Update". As in a large database update
** transmitted via a wireless network to a mobile device. A transaction
** applied using this extension is hence refered to as an "RBU update".
**
**
** LIMITATIONS
**
** An "RBU update" transaction is subject to the following limitations:
**
**   * The transaction must consist of INSERT, UPDATE and DELETE operations
**     only.
**
**   * INSERT statements may not use any default values.
**
**   * UPDATE and DELETE statements must identify their target rows by 
**   * UPDATE and DELETE statements must identify their target rows by
**     non-NULL PRIMARY KEY values. Rows with NULL values stored in PRIMARY
**     KEY fields may not be updated or deleted. If the table being written 
**     KEY fields may not be updated or deleted. If the table being written
**     has no PRIMARY KEY, affected rows must be identified by rowid.
**
**   * UPDATE statements may not modify PRIMARY KEY columns.
**
**   * No triggers will be fired.
**
**   * No foreign key violations are detected or reported.
**
**   * CHECK constraints are not enforced.
**
**   * No constraint handling mode except for "OR ROLLBACK" is supported.
**
**
** PREPARATION
**
** An "RBU update" is stored as a separate SQLite database. A database
** containing an RBU update is an "RBU database". For each table in the 
** containing an RBU update is an "RBU database". For each table in the
** target database to be updated, the RBU database should contain a table
** named "data_<target name>" containing the same set of columns as the
** target table, and one more - "rbu_control". The data_% table should 
** target table, and one more - "rbu_control". The data_% table should
** have no PRIMARY KEY or UNIQUE constraints, but each column should have
** the same type as the corresponding column in the target database.
** The "rbu_control" column should have no type at all. For example, if
** the target database contains:
**
**   CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT, c UNIQUE);
**
** Then the RBU database should contain:
**
**   CREATE TABLE data_t1(a INTEGER, b TEXT, c, rbu_control);
**
** The order of the columns in the data_% table does not matter.
**
** Instead of a regular table, the RBU database may also contain virtual
** tables or view named using the data_<target> naming scheme. 
** tables or views named using the data_<target> naming scheme.
**
** Instead of the plain data_<target> naming scheme, RBU database tables 
** Instead of the plain data_<target> naming scheme, RBU database tables
** may also be named data<integer>_<target>, where <integer> is any sequence
** of zero or more numeric characters (0-9). This can be significant because
** tables within the RBU database are always processed in order sorted by 
** tables within the RBU database are always processed in order sorted by
** name. By judicious selection of the <integer> portion of the names
** of the RBU tables the user can therefore control the order in which they
** are processed. This can be useful, for example, to ensure that "external
** content" FTS4 tables are updated before their underlying content tables.
**
** If the target database table is a virtual table or a table that has no
** PRIMARY KEY declaration, the data_% table must also contain a column 
** named "rbu_rowid". This column is mapped to the tables implicit primary 
** key column - "rowid". Virtual tables for which the "rowid" column does 
** not function like a primary key value cannot be updated using RBU. For 
** PRIMARY KEY declaration, the data_% table must also contain a column
** named "rbu_rowid". This column is mapped to the table's implicit primary
** key column - "rowid". Virtual tables for which the "rowid" column does
** not function like a primary key value cannot be updated using RBU. For
** example, if the target db contains either of the following:
**
**   CREATE VIRTUAL TABLE x1 USING fts3(a, b);
**   CREATE TABLE x1(a, b)
**
** then the RBU database should contain:
**
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
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







-
+


-
-
+
+

-
-
+
+


-
+






-
+


-
+

-
+


-
+


-
+













-
+






-
+



-
+



-
+




-
+


-
+







**   CREATE VIRTUAL TABLE ft1 USING fts4(a, b, languageid='langid');
**
** Either of the following input table schemas may be used:
**
**   CREATE TABLE data_ft1(a, b, langid, rbu_rowid, rbu_control);
**   CREATE TABLE data_ft1(a, b, rbu_rowid, rbu_control);
**
** For each row to INSERT into the target database as part of the RBU 
** For each row to INSERT into the target database as part of the RBU
** update, the corresponding data_% table should contain a single record
** with the "rbu_control" column set to contain integer value 0. The
** other columns should be set to the values that make up the new record 
** to insert. 
** other columns should be set to the values that make up the new record
** to insert.
**
** If the target database table has an INTEGER PRIMARY KEY, it is not 
** possible to insert a NULL value into the IPK column. Attempting to 
** If the target database table has an INTEGER PRIMARY KEY, it is not
** possible to insert a NULL value into the IPK column. Attempting to
** do so results in an SQLITE_MISMATCH error.
**
** For each row to DELETE from the target database as part of the RBU 
** For each row to DELETE from the target database as part of the RBU
** update, the corresponding data_% table should contain a single record
** with the "rbu_control" column set to contain integer value 1. The
** real primary key values of the row to delete should be stored in the
** corresponding columns of the data_% table. The values stored in the
** other columns are not used.
**
** For each row to UPDATE from the target database as part of the RBU 
** For each row to UPDATE from the target database as part of the RBU
** update, the corresponding data_% table should contain a single record
** with the "rbu_control" column set to contain a value of type text.
** The real primary key values identifying the row to update should be 
** The real primary key values identifying the row to update should be
** stored in the corresponding columns of the data_% table row, as should
** the new values of all columns being update. The text value in the 
** the new values of all columns being update. The text value in the
** "rbu_control" column must contain the same number of characters as
** there are columns in the target database table, and must consist entirely
** of 'x' and '.' characters (or in some special cases 'd' - see below). For 
** of 'x' and '.' characters (or in some special cases 'd' - see below). For
** each column that is being updated, the corresponding character is set to
** 'x'. For those that remain as they are, the corresponding character of the
** rbu_control value should be set to '.'. For example, given the tables 
** rbu_control value should be set to '.'. For example, given the tables
** above, the update statement:
**
**   UPDATE t1 SET c = 'usa' WHERE a = 4;
**
** is represented by the data_t1 row created by:
**
**   INSERT INTO data_t1(a, b, c, rbu_control) VALUES(4, NULL, 'usa', '..x');
**
** Instead of an 'x' character, characters of the rbu_control value specified
** for UPDATEs may also be set to 'd'. In this case, instead of updating the
** target table with the value stored in the corresponding data_% column, the
** user-defined SQL function "rbu_delta()" is invoked and the result stored in
** the target table column. rbu_delta() is invoked with two arguments - the
** original value currently stored in the target table column and the 
** original value currently stored in the target table column and the
** value specified in the data_xxx table.
**
** For example, this row:
**
**   INSERT INTO data_t1(a, b, c, rbu_control) VALUES(4, NULL, 'usa', '..d');
**
** is similar to an UPDATE statement such as: 
** is similar to an UPDATE statement such as:
**
**   UPDATE t1 SET c = rbu_delta(c, 'usa') WHERE a = 4;
**
** Finally, if an 'f' character appears in place of a 'd' or 's' in an 
** Finally, if an 'f' character appears in place of a 'd' or 's' in an
** ota_control string, the contents of the data_xxx table column is assumed
** to be a "fossil delta" - a patch to be applied to a blob value in the
** format used by the fossil source-code management system. In this case
** the existing value within the target database table must be of type BLOB. 
** the existing value within the target database table must be of type BLOB.
** It is replaced by the result of applying the specified fossil delta to
** itself.
**
** If the target database table is a virtual table or a table with no PRIMARY
** KEY, the rbu_control value should not include a character corresponding 
** KEY, the rbu_control value should not include a character corresponding
** to the rbu_rowid value. For example, this:
**
**   INSERT INTO data_ft1(a, b, rbu_rowid, rbu_control) 
**   INSERT INTO data_ft1(a, b, rbu_rowid, rbu_control)
**       VALUES(NULL, 'usa', 12, '.x');
**
** causes a result similar to:
**
**   UPDATE ft1 SET b = 'usa' WHERE rowid = 12;
**
** The data_xxx tables themselves should have no PRIMARY KEY declarations.
539
540
541
542
543
544
545




























546
547
548
549
550
551
552
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







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







#define SQLITE_RBU_STATE_OAL        1
#define SQLITE_RBU_STATE_MOVE       2
#define SQLITE_RBU_STATE_CHECKPOINT 3
#define SQLITE_RBU_STATE_DONE       4
#define SQLITE_RBU_STATE_ERROR      5

SQLITE_API int sqlite3rbu_state(sqlite3rbu *pRbu);

/*
** As part of applying an RBU update or performing an RBU vacuum operation,
** the system must at one point move the *-oal file to the equivalent *-wal
** path. Normally, it does this by invoking POSIX function rename(2) directly.
** Except on WINCE platforms, where it uses win32 API MoveFileW(). This 
** function may be used to register a callback that the RBU module will invoke
** instead of one of these APIs. 
**
** If a callback is registered with an RBU handle, it invokes it instead
** of rename(2) when it needs to move a file within the file-system. The
** first argument passed to the xRename() callback is a copy of the second
** argument (pArg) passed to this function. The second is the full path
** to the file to move and the third the full path to which it should be
** moved. The callback function should return SQLITE_OK to indicate 
** success. If an error occurs, it should return an SQLite error code.
** In this case the RBU operation will be abandoned and the error returned
** to the RBU user.
**
** Passing a NULL pointer in place of the xRename argument to this function
** restores the default behaviour.
*/
SQLITE_API void sqlite3rbu_rename_handler(
  sqlite3rbu *pRbu, 
  void *pArg,
  int (*xRename)(void *pArg, const char *zOld, const char *zNew)
);


/*
** Create an RBU VFS named zName that accesses the underlying file-system
** via existing VFS zParent. Or, if the zParent parameter is passed NULL, 
** then the new RBU VFS uses the default system VFS to access the file-system.
** The new object is registered as a non-default VFS with SQLite before 
** returning.

Changes to ext/rbu/test_rbu.c.

22
23
24
25
26
27
28








29
30
31
32
33
34
35
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43







+
+
+
+
+
+
+
+







#else
#  include "tcl.h"
#  ifndef SQLITE_TCLAPI
#    define SQLITE_TCLAPI
#  endif
#endif
#include <assert.h>
#include <string.h>

typedef struct TestRbu TestRbu;
struct TestRbu {
  sqlite3rbu *pRbu;
  Tcl_Interp *interp;
  Tcl_Obj *xRename;
};

/* From main.c */ 
extern const char *sqlite3ErrName(int);
extern int sqlite3TestMakePointerStr(Tcl_Interp*, char*, void*);

void test_rbu_delta(sqlite3_context *pCtx, int nArg, sqlite3_value **apVal){
  Tcl_Interp *interp = (Tcl_Interp*)sqlite3_user_data(pCtx);
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
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







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








+
-
+


















+







  }else{
    Tcl_BackgroundError(interp);
  }

  Tcl_DecrRefCount(pScript);
}

static int xRenameCallback(void *pArg, const char *zOld, const char *zNew){
  int rc = SQLITE_OK;
  TestRbu *pTest = (TestRbu*)pArg;
  Tcl_Obj *pEval = Tcl_DuplicateObj(pTest->xRename);

  Tcl_IncrRefCount(pEval);
  Tcl_ListObjAppendElement(pTest->interp, pEval, Tcl_NewStringObj(zOld, -1));
  Tcl_ListObjAppendElement(pTest->interp, pEval, Tcl_NewStringObj(zNew, -1));

  rc = Tcl_EvalObjEx(pTest->interp, pEval, TCL_GLOBAL_ONLY);
  Tcl_DecrRefCount(pEval);

  return rc ? SQLITE_IOERR : SQLITE_OK;
}

static int SQLITE_TCLAPI test_sqlite3rbu_cmd(
  ClientData clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  int ret = TCL_OK;
  TestRbu *pTest = (TestRbu*)clientData;
  sqlite3rbu *pRbu = (sqlite3rbu*)clientData;
  sqlite3rbu *pRbu = pTest->pRbu;
  struct RbuCmd {
    const char *zName;
    int nArg;
    const char *zUsage;
  } aCmd[] = {
    {"step", 2, ""},                 /* 0 */
    {"close", 2, ""},                /* 1 */
    {"create_rbu_delta", 2, ""},     /* 2 */
    {"savestate", 2, ""},            /* 3 */
    {"dbMain_eval", 3, "SQL"},       /* 4 */
    {"bp_progress", 2, ""},          /* 5 */
    {"db", 3, "RBU"},                /* 6 */
    {"state", 2, ""},                /* 7 */
    {"progress", 2, ""},             /* 8 */
    {"close_no_error", 2, ""},       /* 9 */
    {"temp_size_limit", 3, "LIMIT"}, /* 10 */
    {"temp_size", 2, ""},            /* 11 */
    {"dbRbu_eval", 3, "SQL"},        /* 12 */
    {"rename_handler", 3, "SCRIPT"},/* 13 */
    {0,0,0}
  };
  int iCmd;

  if( objc<2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "METHOD");
    return TCL_ERROR;
123
124
125
126
127
128
129


130
131
132
133
134
135
136
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162







+
+







        Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
        if( zErrmsg ){
          Tcl_AppendResult(interp, " - ", zErrmsg, 0);
          sqlite3_free(zErrmsg);
        }
        ret = TCL_ERROR;
      }
      if( pTest->xRename ) Tcl_DecrRefCount(pTest->xRename);
      ckfree(pTest);
      break;
    }

    case 2: /* create_rbu_delta */ {
      sqlite3 *db = sqlite3rbu_db(pRbu, 0);
      int rc = sqlite3_create_function(
          db, "rbu_delta", -1, SQLITE_UTF8, (void*)interp, test_rbu_delta, 0, 0
209
210
211
212
213
214
215













216
217
218
219
220
221
222
223












224
225
226
227
228
229
230
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







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








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







      break;
    }
    case 11: /* temp_size */ {
      sqlite3_int64 sz = sqlite3rbu_temp_size(pRbu);
      Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sz));
      break;
    }

    case 13: /* rename_handler */ {
      Tcl_Obj *pScript = objv[2];
      assert( !sqlite3_stricmp(aCmd[13].zName, "rename_handler") );
      if( Tcl_GetCharLength(pScript)==0 ){
        sqlite3rbu_rename_handler(pRbu, 0, 0);
      }else{
        pTest->xRename = Tcl_DuplicateObj(pScript);
        Tcl_IncrRefCount(pTest->xRename);
        sqlite3rbu_rename_handler(pRbu, pTest, xRenameCallback);
      }
      break;
    }

    default: /* seems unlikely */
      assert( !"cannot happen" );
      break;
  }

  return ret;
}

static void createRbuWrapper(
  Tcl_Interp *interp,
  const char *zCmd,
  sqlite3rbu *pRbu
){
  TestRbu *pTest = (TestRbu*)ckalloc(sizeof(TestRbu));
  memset(pTest, 0, sizeof(TestRbu));
  pTest->pRbu = pRbu;
  pTest->interp = interp;
  Tcl_CreateObjCommand(interp, zCmd, test_sqlite3rbu_cmd, (ClientData)pTest, 0);
}

/*
** Tclcmd: sqlite3rbu CMD <target-db> <rbu-db> ?<state-db>?
*/
static int SQLITE_TCLAPI test_sqlite3rbu(
  ClientData clientData,
  Tcl_Interp *interp,
243
244
245
246
247
248
249
250

251
252
253
254
255
256
257
294
295
296
297
298
299
300

301
302
303
304
305
306
307
308







-
+







  }
  zCmd = Tcl_GetString(objv[1]);
  zTarget = Tcl_GetString(objv[2]);
  zRbu = Tcl_GetString(objv[3]);
  if( objc==5 ) zStateDb = Tcl_GetString(objv[4]);

  pRbu = sqlite3rbu_open(zTarget, zRbu, zStateDb);
  Tcl_CreateObjCommand(interp, zCmd, test_sqlite3rbu_cmd, (ClientData)pRbu, 0);
  createRbuWrapper(interp, zCmd, pRbu);
  Tcl_SetObjResult(interp, objv[1]);
  return TCL_OK;
}

/*
** Tclcmd: sqlite3rbu_vacuum CMD <target-db> <state-db>
*/
272
273
274
275
276
277
278
279

280
281
282
283
284
285
286
323
324
325
326
327
328
329

330
331
332
333
334
335
336
337







-
+







  }
  zCmd = Tcl_GetString(objv[1]);
  zTarget = Tcl_GetString(objv[2]);
  if( objc==4 ) zStateDb = Tcl_GetString(objv[3]);
  if( zStateDb && zStateDb[0]=='\0' ) zStateDb = 0;

  pRbu = sqlite3rbu_vacuum(zTarget, zStateDb);
  Tcl_CreateObjCommand(interp, zCmd, test_sqlite3rbu_cmd, (ClientData)pRbu, 0);
  createRbuWrapper(interp, zCmd, pRbu);
  Tcl_SetObjResult(interp, objv[1]);
  return TCL_OK;
}

/*
** Tclcmd: sqlite3rbu_create_vfs ?-default? NAME PARENT
*/

Added ext/recover/dbdata.c.





















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2019-04-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 contains an implementation of two eponymous virtual tables,
** "sqlite_dbdata" and "sqlite_dbptr". Both modules require that the
** "sqlite_dbpage" eponymous virtual table be available.
**
** SQLITE_DBDATA:
**   sqlite_dbdata is used to extract data directly from a database b-tree
**   page and its associated overflow pages, bypassing the b-tree layer.
**   The table schema is equivalent to:
**
**     CREATE TABLE sqlite_dbdata(
**       pgno INTEGER,
**       cell INTEGER,
**       field INTEGER,
**       value ANY,
**       schema TEXT HIDDEN
**     );
**
**   IMPORTANT: THE VIRTUAL TABLE SCHEMA ABOVE IS SUBJECT TO CHANGE. IN THE
**   FUTURE NEW NON-HIDDEN COLUMNS MAY BE ADDED BETWEEN "value" AND
**   "schema".
**
**   Each page of the database is inspected. If it cannot be interpreted as
**   a b-tree page, or if it is a b-tree page containing 0 entries, the
**   sqlite_dbdata table contains no rows for that page.  Otherwise, the
**   table contains one row for each field in the record associated with
**   each cell on the page. For intkey b-trees, the key value is stored in
**   field -1.
**
**   For example, for the database:
**
**     CREATE TABLE t1(a, b);     -- root page is page 2
**     INSERT INTO t1(rowid, a, b) VALUES(5, 'v', 'five');
**     INSERT INTO t1(rowid, a, b) VALUES(10, 'x', 'ten');
**
**   the sqlite_dbdata table contains, as well as from entries related to 
**   page 1, content equivalent to:
**
**     INSERT INTO sqlite_dbdata(pgno, cell, field, value) VALUES
**         (2, 0, -1, 5     ),
**         (2, 0,  0, 'v'   ),
**         (2, 0,  1, 'five'),
**         (2, 1, -1, 10    ),
**         (2, 1,  0, 'x'   ),
**         (2, 1,  1, 'ten' );
**
**   If database corruption is encountered, this module does not report an
**   error. Instead, it attempts to extract as much data as possible and
**   ignores the corruption.
**
** SQLITE_DBPTR:
**   The sqlite_dbptr table has the following schema:
**
**     CREATE TABLE sqlite_dbptr(
**       pgno INTEGER,
**       child INTEGER,
**       schema TEXT HIDDEN
**     );
**
**   It contains one entry for each b-tree pointer between a parent and
**   child page in the database.
*/

#if !defined(SQLITEINT_H) 
#include "sqlite3ext.h"

typedef unsigned char u8;
typedef unsigned int u32;

#endif
SQLITE_EXTENSION_INIT1
#include <string.h>
#include <assert.h>

#ifndef SQLITE_OMIT_VIRTUALTABLE

#define DBDATA_PADDING_BYTES 100 

typedef struct DbdataTable DbdataTable;
typedef struct DbdataCursor DbdataCursor;

/* Cursor object */
struct DbdataCursor {
  sqlite3_vtab_cursor base;       /* Base class.  Must be first */
  sqlite3_stmt *pStmt;            /* For fetching database pages */

  int iPgno;                      /* Current page number */
  u8 *aPage;                      /* Buffer containing page */
  int nPage;                      /* Size of aPage[] in bytes */
  int nCell;                      /* Number of cells on aPage[] */
  int iCell;                      /* Current cell number */
  int bOnePage;                   /* True to stop after one page */
  int szDb;
  sqlite3_int64 iRowid;

  /* Only for the sqlite_dbdata table */
  u8 *pRec;                       /* Buffer containing current record */
  sqlite3_int64 nRec;             /* Size of pRec[] in bytes */
  sqlite3_int64 nHdr;             /* Size of header in bytes */
  int iField;                     /* Current field number */
  u8 *pHdrPtr;
  u8 *pPtr;
  u32 enc;                        /* Text encoding */
  
  sqlite3_int64 iIntkey;          /* Integer key value */
};

/* Table object */
struct DbdataTable {
  sqlite3_vtab base;              /* Base class.  Must be first */
  sqlite3 *db;                    /* The database connection */
  sqlite3_stmt *pStmt;            /* For fetching database pages */
  int bPtr;                       /* True for sqlite3_dbptr table */
};

/* Column and schema definitions for sqlite_dbdata */
#define DBDATA_COLUMN_PGNO        0
#define DBDATA_COLUMN_CELL        1
#define DBDATA_COLUMN_FIELD       2
#define DBDATA_COLUMN_VALUE       3
#define DBDATA_COLUMN_SCHEMA      4
#define DBDATA_SCHEMA             \
      "CREATE TABLE x("           \
      "  pgno INTEGER,"           \
      "  cell INTEGER,"           \
      "  field INTEGER,"          \
      "  value ANY,"              \
      "  schema TEXT HIDDEN"      \
      ")"

/* Column and schema definitions for sqlite_dbptr */
#define DBPTR_COLUMN_PGNO         0
#define DBPTR_COLUMN_CHILD        1
#define DBPTR_COLUMN_SCHEMA       2
#define DBPTR_SCHEMA              \
      "CREATE TABLE x("           \
      "  pgno INTEGER,"           \
      "  child INTEGER,"          \
      "  schema TEXT HIDDEN"      \
      ")"

/*
** Connect to an sqlite_dbdata (pAux==0) or sqlite_dbptr (pAux!=0) virtual 
** table.
*/
static int dbdataConnect(
  sqlite3 *db,
  void *pAux,
  int argc, const char *const*argv,
  sqlite3_vtab **ppVtab,
  char **pzErr
){
  DbdataTable *pTab = 0;
  int rc = sqlite3_declare_vtab(db, pAux ? DBPTR_SCHEMA : DBDATA_SCHEMA);

  (void)argc;
  (void)argv;
  (void)pzErr;
  if( rc==SQLITE_OK ){
    pTab = (DbdataTable*)sqlite3_malloc64(sizeof(DbdataTable));
    if( pTab==0 ){
      rc = SQLITE_NOMEM;
    }else{
      memset(pTab, 0, sizeof(DbdataTable));
      pTab->db = db;
      pTab->bPtr = (pAux!=0);
    }
  }

  *ppVtab = (sqlite3_vtab*)pTab;
  return rc;
}

/*
** Disconnect from or destroy a sqlite_dbdata or sqlite_dbptr virtual table.
*/
static int dbdataDisconnect(sqlite3_vtab *pVtab){
  DbdataTable *pTab = (DbdataTable*)pVtab;
  if( pTab ){
    sqlite3_finalize(pTab->pStmt);
    sqlite3_free(pVtab);
  }
  return SQLITE_OK;
}

/*
** This function interprets two types of constraints:
**
**       schema=?
**       pgno=?
**
** If neither are present, idxNum is set to 0. If schema=? is present,
** the 0x01 bit in idxNum is set. If pgno=? is present, the 0x02 bit
** in idxNum is set.
**
** If both parameters are present, schema is in position 0 and pgno in
** position 1.
*/
static int dbdataBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdx){
  DbdataTable *pTab = (DbdataTable*)tab;
  int i;
  int iSchema = -1;
  int iPgno = -1;
  int colSchema = (pTab->bPtr ? DBPTR_COLUMN_SCHEMA : DBDATA_COLUMN_SCHEMA);

  for(i=0; i<pIdx->nConstraint; i++){
    struct sqlite3_index_constraint *p = &pIdx->aConstraint[i];
    if( p->op==SQLITE_INDEX_CONSTRAINT_EQ ){
      if( p->iColumn==colSchema ){
        if( p->usable==0 ) return SQLITE_CONSTRAINT;
        iSchema = i;
      }
      if( p->iColumn==DBDATA_COLUMN_PGNO && p->usable ){
        iPgno = i;
      }
    }
  }

  if( iSchema>=0 ){
    pIdx->aConstraintUsage[iSchema].argvIndex = 1;
    pIdx->aConstraintUsage[iSchema].omit = 1;
  }
  if( iPgno>=0 ){
    pIdx->aConstraintUsage[iPgno].argvIndex = 1 + (iSchema>=0);
    pIdx->aConstraintUsage[iPgno].omit = 1;
    pIdx->estimatedCost = 100;
    pIdx->estimatedRows =  50;

    if( pTab->bPtr==0 && pIdx->nOrderBy && pIdx->aOrderBy[0].desc==0 ){
      int iCol = pIdx->aOrderBy[0].iColumn;
      if( pIdx->nOrderBy==1 ){
        pIdx->orderByConsumed = (iCol==0 || iCol==1);
      }else if( pIdx->nOrderBy==2 && pIdx->aOrderBy[1].desc==0 && iCol==0 ){
        pIdx->orderByConsumed = (pIdx->aOrderBy[1].iColumn==1);
      }
    }

  }else{
    pIdx->estimatedCost = 100000000;
    pIdx->estimatedRows = 1000000000;
  }
  pIdx->idxNum = (iSchema>=0 ? 0x01 : 0x00) | (iPgno>=0 ? 0x02 : 0x00);
  return SQLITE_OK;
}

/*
** Open a new sqlite_dbdata or sqlite_dbptr cursor.
*/
static int dbdataOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
  DbdataCursor *pCsr;

  pCsr = (DbdataCursor*)sqlite3_malloc64(sizeof(DbdataCursor));
  if( pCsr==0 ){
    return SQLITE_NOMEM;
  }else{
    memset(pCsr, 0, sizeof(DbdataCursor));
    pCsr->base.pVtab = pVTab;
  }

  *ppCursor = (sqlite3_vtab_cursor *)pCsr;
  return SQLITE_OK;
}

/*
** Restore a cursor object to the state it was in when first allocated 
** by dbdataOpen().
*/
static void dbdataResetCursor(DbdataCursor *pCsr){
  DbdataTable *pTab = (DbdataTable*)(pCsr->base.pVtab);
  if( pTab->pStmt==0 ){
    pTab->pStmt = pCsr->pStmt;
  }else{
    sqlite3_finalize(pCsr->pStmt);
  }
  pCsr->pStmt = 0;
  pCsr->iPgno = 1;
  pCsr->iCell = 0;
  pCsr->iField = 0;
  pCsr->bOnePage = 0;
  sqlite3_free(pCsr->aPage);
  sqlite3_free(pCsr->pRec);
  pCsr->pRec = 0;
  pCsr->aPage = 0;
}

/*
** Close an sqlite_dbdata or sqlite_dbptr cursor.
*/
static int dbdataClose(sqlite3_vtab_cursor *pCursor){
  DbdataCursor *pCsr = (DbdataCursor*)pCursor;
  dbdataResetCursor(pCsr);
  sqlite3_free(pCsr);
  return SQLITE_OK;
}

/* 
** Utility methods to decode 16 and 32-bit big-endian unsigned integers. 
*/
static u32 get_uint16(unsigned char *a){
  return (a[0]<<8)|a[1];
}
static u32 get_uint32(unsigned char *a){
  return ((u32)a[0]<<24)
       | ((u32)a[1]<<16)
       | ((u32)a[2]<<8)
       | ((u32)a[3]);
}

/*
** Load page pgno from the database via the sqlite_dbpage virtual table.
** If successful, set (*ppPage) to point to a buffer containing the page
** data, (*pnPage) to the size of that buffer in bytes and return
** SQLITE_OK. In this case it is the responsibility of the caller to
** eventually free the buffer using sqlite3_free().
**
** Or, if an error occurs, set both (*ppPage) and (*pnPage) to 0 and
** return an SQLite error code.
*/
static int dbdataLoadPage(
  DbdataCursor *pCsr,             /* Cursor object */
  u32 pgno,                       /* Page number of page to load */
  u8 **ppPage,                    /* OUT: pointer to page buffer */
  int *pnPage                     /* OUT: Size of (*ppPage) in bytes */
){
  int rc2;
  int rc = SQLITE_OK;
  sqlite3_stmt *pStmt = pCsr->pStmt;

  *ppPage = 0;
  *pnPage = 0;
  if( pgno>0 ){
    sqlite3_bind_int64(pStmt, 2, pgno);
    if( SQLITE_ROW==sqlite3_step(pStmt) ){
      int nCopy = sqlite3_column_bytes(pStmt, 0);
      if( nCopy>0 ){
        u8 *pPage;
        pPage = (u8*)sqlite3_malloc64(nCopy + DBDATA_PADDING_BYTES);
        if( pPage==0 ){
          rc = SQLITE_NOMEM;
        }else{
          const u8 *pCopy = sqlite3_column_blob(pStmt, 0);
          memcpy(pPage, pCopy, nCopy);
          memset(&pPage[nCopy], 0, DBDATA_PADDING_BYTES);
        }
        *ppPage = pPage;
        *pnPage = nCopy;
      }
    }
    rc2 = sqlite3_reset(pStmt);
    if( rc==SQLITE_OK ) rc = rc2;
  }

  return rc;
}

/*
** Read a varint.  Put the value in *pVal and return the number of bytes.
*/
static int dbdataGetVarint(const u8 *z, sqlite3_int64 *pVal){
  sqlite3_uint64 u = 0;
  int i;
  for(i=0; i<8; i++){
    u = (u<<7) + (z[i]&0x7f);
    if( (z[i]&0x80)==0 ){ *pVal = (sqlite3_int64)u; return i+1; }
  }
  u = (u<<8) + (z[i]&0xff);
  *pVal = (sqlite3_int64)u;
  return 9;
}

/*
** Like dbdataGetVarint(), but set the output to 0 if it is less than 0
** or greater than 0xFFFFFFFF. This can be used for all varints in an
** SQLite database except for key values in intkey tables.
*/
static int dbdataGetVarintU32(const u8 *z, sqlite3_int64 *pVal){
  sqlite3_int64 val;
  int nRet = dbdataGetVarint(z, &val);
  if( val<0 || val>0xFFFFFFFF ) val = 0;
  *pVal = val;
  return nRet;
}

/*
** Return the number of bytes of space used by an SQLite value of type
** eType.
*/
static int dbdataValueBytes(int eType){
  switch( eType ){
    case 0: case 8: case 9:
    case 10: case 11:
      return 0;
    case 1:
      return 1;
    case 2:
      return 2;
    case 3:
      return 3;
    case 4:
      return 4;
    case 5:
      return 6;
    case 6:
    case 7:
      return 8;
    default:
      if( eType>0 ){
        return ((eType-12) / 2);
      }
      return 0;
  }
}

/*
** Load a value of type eType from buffer pData and use it to set the
** result of context object pCtx.
*/
static void dbdataValue(
  sqlite3_context *pCtx, 
  u32 enc,
  int eType, 
  u8 *pData,
  sqlite3_int64 nData
){
  if( eType>=0 && dbdataValueBytes(eType)<=nData ){
    switch( eType ){
      case 0: 
      case 10: 
      case 11: 
        sqlite3_result_null(pCtx);
        break;
      
      case 8: 
        sqlite3_result_int(pCtx, 0);
        break;
      case 9:
        sqlite3_result_int(pCtx, 1);
        break;
  
      case 1: case 2: case 3: case 4: case 5: case 6: case 7: {
        sqlite3_uint64 v = (signed char)pData[0];
        pData++;
        switch( eType ){
          case 7:
          case 6:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
          case 5:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
          case 4:  v = (v<<8) + pData[0];  pData++;
          case 3:  v = (v<<8) + pData[0];  pData++;
          case 2:  v = (v<<8) + pData[0];  pData++;
        }
  
        if( eType==7 ){
          double r;
          memcpy(&r, &v, sizeof(r));
          sqlite3_result_double(pCtx, r);
        }else{
          sqlite3_result_int64(pCtx, (sqlite3_int64)v);
        }
        break;
      }
  
      default: {
        int n = ((eType-12) / 2);
        if( eType % 2 ){
          switch( enc ){
#ifndef SQLITE_OMIT_UTF16
            case SQLITE_UTF16BE:
              sqlite3_result_text16be(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
              break;
            case SQLITE_UTF16LE:
              sqlite3_result_text16le(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
              break;
#endif
            default:
              sqlite3_result_text(pCtx, (char*)pData, n, SQLITE_TRANSIENT);
              break;
          }
        }else{
          sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT);
        }
      }
    }
  }
}

/*
** Move an sqlite_dbdata or sqlite_dbptr cursor to the next entry.
*/
static int dbdataNext(sqlite3_vtab_cursor *pCursor){
  DbdataCursor *pCsr = (DbdataCursor*)pCursor;
  DbdataTable *pTab = (DbdataTable*)pCursor->pVtab;

  pCsr->iRowid++;
  while( 1 ){
    int rc;
    int iOff = (pCsr->iPgno==1 ? 100 : 0);
    int bNextPage = 0;

    if( pCsr->aPage==0 ){
      while( 1 ){
        if( pCsr->bOnePage==0 && pCsr->iPgno>pCsr->szDb ) return SQLITE_OK;
        rc = dbdataLoadPage(pCsr, pCsr->iPgno, &pCsr->aPage, &pCsr->nPage);
        if( rc!=SQLITE_OK ) return rc;
        if( pCsr->aPage ) break;
        if( pCsr->bOnePage ) return SQLITE_OK;
        pCsr->iPgno++;
      }
      pCsr->iCell = pTab->bPtr ? -2 : 0;
      pCsr->nCell = get_uint16(&pCsr->aPage[iOff+3]);
    }

    if( pTab->bPtr ){
      if( pCsr->aPage[iOff]!=0x02 && pCsr->aPage[iOff]!=0x05 ){
        pCsr->iCell = pCsr->nCell;
      }
      pCsr->iCell++;
      if( pCsr->iCell>=pCsr->nCell ){
        sqlite3_free(pCsr->aPage);
        pCsr->aPage = 0;
        if( pCsr->bOnePage ) return SQLITE_OK;
        pCsr->iPgno++;
      }else{
        return SQLITE_OK;
      }
    }else{
      /* If there is no record loaded, load it now. */
      if( pCsr->pRec==0 ){
        int bHasRowid = 0;
        int nPointer = 0;
        sqlite3_int64 nPayload = 0;
        sqlite3_int64 nHdr = 0;
        int iHdr;
        int U, X;
        int nLocal;
  
        switch( pCsr->aPage[iOff] ){
          case 0x02:
            nPointer = 4;
            break;
          case 0x0a:
            break;
          case 0x0d:
            bHasRowid = 1;
            break;
          default:
            /* This is not a b-tree page with records on it. Continue. */
            pCsr->iCell = pCsr->nCell;
            break;
        }

        if( pCsr->iCell>=pCsr->nCell ){
          bNextPage = 1;
        }else{
  
          iOff += 8 + nPointer + pCsr->iCell*2;
          if( iOff>pCsr->nPage ){
            bNextPage = 1;
          }else{
            iOff = get_uint16(&pCsr->aPage[iOff]);
          }
    
          /* For an interior node cell, skip past the child-page number */
          iOff += nPointer;
    
          /* Load the "byte of payload including overflow" field */
          if( bNextPage || iOff>pCsr->nPage ){
            bNextPage = 1;
          }else{
            iOff += dbdataGetVarintU32(&pCsr->aPage[iOff], &nPayload);
          }
    
          /* If this is a leaf intkey cell, load the rowid */
          if( bHasRowid && !bNextPage && iOff<pCsr->nPage ){
            iOff += dbdataGetVarint(&pCsr->aPage[iOff], &pCsr->iIntkey);
          }
    
          /* Figure out how much data to read from the local page */
          U = pCsr->nPage;
          if( bHasRowid ){
            X = U-35;
          }else{
            X = ((U-12)*64/255)-23;
          }
          if( nPayload<=X ){
            nLocal = nPayload;
          }else{
            int M, K;
            M = ((U-12)*32/255)-23;
            K = M+((nPayload-M)%(U-4));
            if( K<=X ){
              nLocal = K;
            }else{
              nLocal = M;
            }
          }

          if( bNextPage || nLocal+iOff>pCsr->nPage ){
            bNextPage = 1;
          }else{

            /* Allocate space for payload. And a bit more to catch small buffer
            ** overruns caused by attempting to read a varint or similar from 
            ** near the end of a corrupt record.  */
            pCsr->pRec = (u8*)sqlite3_malloc64(nPayload+DBDATA_PADDING_BYTES);
            if( pCsr->pRec==0 ) return SQLITE_NOMEM;
            memset(pCsr->pRec, 0, nPayload+DBDATA_PADDING_BYTES);
            pCsr->nRec = nPayload;

            /* Load the nLocal bytes of payload */
            memcpy(pCsr->pRec, &pCsr->aPage[iOff], nLocal);
            iOff += nLocal;

            /* Load content from overflow pages */
            if( nPayload>nLocal ){
              sqlite3_int64 nRem = nPayload - nLocal;
              u32 pgnoOvfl = get_uint32(&pCsr->aPage[iOff]);
              while( nRem>0 ){
                u8 *aOvfl = 0;
                int nOvfl = 0;
                int nCopy;
                rc = dbdataLoadPage(pCsr, pgnoOvfl, &aOvfl, &nOvfl);
                assert( rc!=SQLITE_OK || aOvfl==0 || nOvfl==pCsr->nPage );
                if( rc!=SQLITE_OK ) return rc;
                if( aOvfl==0 ) break;

                nCopy = U-4;
                if( nCopy>nRem ) nCopy = nRem;
                memcpy(&pCsr->pRec[nPayload-nRem], &aOvfl[4], nCopy);
                nRem -= nCopy;

                pgnoOvfl = get_uint32(aOvfl);
                sqlite3_free(aOvfl);
              }
            }
    
            iHdr = dbdataGetVarintU32(pCsr->pRec, &nHdr);
            if( nHdr>nPayload ) nHdr = 0;
            pCsr->nHdr = nHdr;
            pCsr->pHdrPtr = &pCsr->pRec[iHdr];
            pCsr->pPtr = &pCsr->pRec[pCsr->nHdr];
            pCsr->iField = (bHasRowid ? -1 : 0);
          }
        }
      }else{
        pCsr->iField++;
        if( pCsr->iField>0 ){
          sqlite3_int64 iType;
          if( pCsr->pHdrPtr>&pCsr->pRec[pCsr->nRec] ){
            bNextPage = 1;
          }else{
            pCsr->pHdrPtr += dbdataGetVarintU32(pCsr->pHdrPtr, &iType);
            pCsr->pPtr += dbdataValueBytes(iType);
          }
        }
      }

      if( bNextPage ){
        sqlite3_free(pCsr->aPage);
        sqlite3_free(pCsr->pRec);
        pCsr->aPage = 0;
        pCsr->pRec = 0;
        if( pCsr->bOnePage ) return SQLITE_OK;
        pCsr->iPgno++;
      }else{
        if( pCsr->iField<0 || pCsr->pHdrPtr<&pCsr->pRec[pCsr->nHdr] ){
          return SQLITE_OK;
        }

        /* Advance to the next cell. The next iteration of the loop will load
        ** the record and so on. */
        sqlite3_free(pCsr->pRec);
        pCsr->pRec = 0;
        pCsr->iCell++;
      }
    }
  }

  assert( !"can't get here" );
  return SQLITE_OK;
}

/* 
** Return true if the cursor is at EOF.
*/
static int dbdataEof(sqlite3_vtab_cursor *pCursor){
  DbdataCursor *pCsr = (DbdataCursor*)pCursor;
  return pCsr->aPage==0;
}

/*
** Return true if nul-terminated string zSchema ends in "()". Or false
** otherwise.
*/
static int dbdataIsFunction(const char *zSchema){
  size_t n = strlen(zSchema);
  if( n>2 && zSchema[n-2]=='(' && zSchema[n-1]==')' ){
    return (int)n-2;
  }
  return 0;
}

/* 
** Determine the size in pages of database zSchema (where zSchema is
** "main", "temp" or the name of an attached database) and set 
** pCsr->szDb accordingly. If successful, return SQLITE_OK. Otherwise,
** an SQLite error code.
*/
static int dbdataDbsize(DbdataCursor *pCsr, const char *zSchema){
  DbdataTable *pTab = (DbdataTable*)pCsr->base.pVtab;
  char *zSql = 0;
  int rc, rc2;
  int nFunc = 0;
  sqlite3_stmt *pStmt = 0;

  if( (nFunc = dbdataIsFunction(zSchema))>0 ){
    zSql = sqlite3_mprintf("SELECT %.*s(0)", nFunc, zSchema);
  }else{
    zSql = sqlite3_mprintf("PRAGMA %Q.page_count", zSchema);
  }
  if( zSql==0 ) return SQLITE_NOMEM;

  rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pStmt, 0);
  sqlite3_free(zSql);
  if( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
    pCsr->szDb = sqlite3_column_int(pStmt, 0);
  }
  rc2 = sqlite3_finalize(pStmt);
  if( rc==SQLITE_OK ) rc = rc2;
  return rc;
}

/*
** Attempt to figure out the encoding of the database by retrieving page 1
** and inspecting the header field. If successful, set the pCsr->enc variable
** and return SQLITE_OK. Otherwise, return an SQLite error code.
*/
static int dbdataGetEncoding(DbdataCursor *pCsr){
  int rc = SQLITE_OK;
  int nPg1 = 0;
  u8 *aPg1 = 0;
  rc = dbdataLoadPage(pCsr, 1, &aPg1, &nPg1);
  assert( rc!=SQLITE_OK || nPg1==0 || nPg1>=512 );
  if( rc==SQLITE_OK && nPg1>0 ){
    pCsr->enc = get_uint32(&aPg1[56]);
  }
  sqlite3_free(aPg1);
  return rc;
}


/* 
** xFilter method for sqlite_dbdata and sqlite_dbptr.
*/
static int dbdataFilter(
  sqlite3_vtab_cursor *pCursor, 
  int idxNum, const char *idxStr,
  int argc, sqlite3_value **argv
){
  DbdataCursor *pCsr = (DbdataCursor*)pCursor;
  DbdataTable *pTab = (DbdataTable*)pCursor->pVtab;
  int rc = SQLITE_OK;
  const char *zSchema = "main";
  (void)idxStr;
  (void)argc;

  dbdataResetCursor(pCsr);
  assert( pCsr->iPgno==1 );
  if( idxNum & 0x01 ){
    zSchema = (const char*)sqlite3_value_text(argv[0]);
    if( zSchema==0 ) zSchema = "";
  }
  if( idxNum & 0x02 ){
    pCsr->iPgno = sqlite3_value_int(argv[(idxNum & 0x01)]);
    pCsr->bOnePage = 1;
  }else{
    rc = dbdataDbsize(pCsr, zSchema);
  }

  if( rc==SQLITE_OK ){
    int nFunc = 0;
    if( pTab->pStmt ){
      pCsr->pStmt = pTab->pStmt;
      pTab->pStmt = 0;
    }else if( (nFunc = dbdataIsFunction(zSchema))>0 ){
      char *zSql = sqlite3_mprintf("SELECT %.*s(?2)", nFunc, zSchema);
      if( zSql==0 ){
        rc = SQLITE_NOMEM;
      }else{
        rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pStmt, 0);
        sqlite3_free(zSql);
      }
    }else{
      rc = sqlite3_prepare_v2(pTab->db, 
          "SELECT data FROM sqlite_dbpage(?) WHERE pgno=?", -1,
          &pCsr->pStmt, 0
      );
    }
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3_bind_text(pCsr->pStmt, 1, zSchema, -1, SQLITE_TRANSIENT);
  }else{
    pTab->base.zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db));
  }

  /* Try to determine the encoding of the db by inspecting the header
  ** field on page 1. */
  if( rc==SQLITE_OK ){
    rc = dbdataGetEncoding(pCsr);
  }

  if( rc==SQLITE_OK ){
    rc = dbdataNext(pCursor);
  }
  return rc;
}

/*
** Return a column for the sqlite_dbdata or sqlite_dbptr table.
*/
static int dbdataColumn(
  sqlite3_vtab_cursor *pCursor, 
  sqlite3_context *ctx, 
  int i
){
  DbdataCursor *pCsr = (DbdataCursor*)pCursor;
  DbdataTable *pTab = (DbdataTable*)pCursor->pVtab;
  if( pTab->bPtr ){
    switch( i ){
      case DBPTR_COLUMN_PGNO:
        sqlite3_result_int64(ctx, pCsr->iPgno);
        break;
      case DBPTR_COLUMN_CHILD: {
        int iOff = pCsr->iPgno==1 ? 100 : 0;
        if( pCsr->iCell<0 ){
          iOff += 8;
        }else{
          iOff += 12 + pCsr->iCell*2;
          if( iOff>pCsr->nPage ) return SQLITE_OK;
          iOff = get_uint16(&pCsr->aPage[iOff]);
        }
        if( iOff<=pCsr->nPage ){
          sqlite3_result_int64(ctx, get_uint32(&pCsr->aPage[iOff]));
        }
        break;
      }
    }
  }else{
    switch( i ){
      case DBDATA_COLUMN_PGNO:
        sqlite3_result_int64(ctx, pCsr->iPgno);
        break;
      case DBDATA_COLUMN_CELL:
        sqlite3_result_int(ctx, pCsr->iCell);
        break;
      case DBDATA_COLUMN_FIELD:
        sqlite3_result_int(ctx, pCsr->iField);
        break;
      case DBDATA_COLUMN_VALUE: {
        if( pCsr->iField<0 ){
          sqlite3_result_int64(ctx, pCsr->iIntkey);
        }else if( &pCsr->pRec[pCsr->nRec] >= pCsr->pPtr ){
          sqlite3_int64 iType;
          dbdataGetVarintU32(pCsr->pHdrPtr, &iType);
          dbdataValue(
              ctx, pCsr->enc, iType, pCsr->pPtr, 
              &pCsr->pRec[pCsr->nRec] - pCsr->pPtr
          );
        }
        break;
      }
    }
  }
  return SQLITE_OK;
}

/* 
** Return the rowid for an sqlite_dbdata or sqlite_dptr table.
*/
static int dbdataRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
  DbdataCursor *pCsr = (DbdataCursor*)pCursor;
  *pRowid = pCsr->iRowid;
  return SQLITE_OK;
}


/*
** Invoke this routine to register the "sqlite_dbdata" virtual table module
*/
static int sqlite3DbdataRegister(sqlite3 *db){
  static sqlite3_module dbdata_module = {
    0,                            /* iVersion */
    0,                            /* xCreate */
    dbdataConnect,                /* xConnect */
    dbdataBestIndex,              /* xBestIndex */
    dbdataDisconnect,             /* xDisconnect */
    0,                            /* xDestroy */
    dbdataOpen,                   /* xOpen - open a cursor */
    dbdataClose,                  /* xClose - close a cursor */
    dbdataFilter,                 /* xFilter - configure scan constraints */
    dbdataNext,                   /* xNext - advance a cursor */
    dbdataEof,                    /* xEof - check for end of scan */
    dbdataColumn,                 /* xColumn - read data */
    dbdataRowid,                  /* xRowid - read data */
    0,                            /* xUpdate */
    0,                            /* xBegin */
    0,                            /* xSync */
    0,                            /* xCommit */
    0,                            /* xRollback */
    0,                            /* xFindMethod */
    0,                            /* xRename */
    0,                            /* xSavepoint */
    0,                            /* xRelease */
    0,                            /* xRollbackTo */
    0                             /* xShadowName */
  };

  int rc = sqlite3_create_module(db, "sqlite_dbdata", &dbdata_module, 0);
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_module(db, "sqlite_dbptr", &dbdata_module, (void*)1);
  }
  return rc;
}

#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_dbdata_init(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg;
  return sqlite3DbdataRegister(db);
}

#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */

Added ext/recover/recover1.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022 August 28
#
# 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.
#
#***********************************************************************
#

source [file join [file dirname [info script]] recover_common.tcl]
set testprefix recover1

proc compare_result {db1 db2 sql} {
  set r1 [$db1 eval $sql]
  set r2 [$db2 eval $sql]
  if {$r1 != $r2} {
    puts "r1: $r1"
    puts "r2: $r2"
    error "mismatch for $sql"
  }
  return ""
}

proc compare_dbs {db1 db2} {
  compare_result $db1 $db2 "SELECT sql FROM sqlite_master ORDER BY 1"
  foreach tbl [$db1 eval {SELECT name FROM sqlite_master WHERE type='table'}] {
    compare_result $db1 $db2 "SELECT * FROM $tbl"
  }

  compare_result $db1 $db2 "PRAGMA page_size"
  compare_result $db1 $db2 "PRAGMA auto_vacuum"
  compare_result $db1 $db2 "PRAGMA encoding"
  compare_result $db1 $db2 "PRAGMA user_version"
  compare_result $db1 $db2 "PRAGMA application_id"
}

proc do_recover_test {tn} {
  forcedelete test.db2
  forcedelete rstate.db

  uplevel [list do_test $tn.1 {
    set R [sqlite3_recover_init db main test.db2]
    $R config testdb rstate.db
    $R run
    $R finish
  } {}]

  sqlite3 db2 test.db2
  uplevel [list do_test $tn.2 [list compare_dbs db db2] {}]
  db2 close

  forcedelete test.db2
  forcedelete rstate.db

  uplevel [list do_test $tn.3 {
    set ::sqlhook [list]
    set R [sqlite3_recover_init_sql db main my_sql_hook]
    $R config testdb rstate.db
    $R config rowids 1
    $R run
    $R finish
  } {}]

  sqlite3 db2 test.db2
  execsql [join $::sqlhook ";"] db2
  db2 close
  sqlite3 db2 test.db2
  uplevel [list do_test $tn.4 [list compare_dbs db db2] {}]
  db2 close
}

proc my_sql_hook {sql} {
  lappend ::sqlhook $sql
  return 0
}

do_execsql_test 1.0 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
  CREATE TABLE t2(a INTEGER PRIMARY KEY, b) WITHOUT ROWID;
  WITH s(i) AS (
    SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<10
  )
  INSERT INTO t1 SELECT i*2, hex(randomblob(250)) FROM s;
  INSERT INTO t2 SELECT * FROM t1;
}

do_recover_test 1

do_execsql_test 2.0 {
  ALTER TABLE t1 ADD COLUMN c DEFAULT 'xyz'
}
do_recover_test 2

do_execsql_test 3.0 {
  CREATE INDEX i1 ON t1(c);
}
do_recover_test 3

do_execsql_test 4.0 {
  CREATE VIEW v1 AS SELECT * FROM t2;
}
do_recover_test 4

do_execsql_test 5.0 {
  CREATE UNIQUE INDEX i2 ON t1(c, b);
}
do_recover_test 5

#--------------------------------------------------------------------------
#
reset_db
do_execsql_test 6.0 {
  CREATE TABLE t1(
      a INTEGER PRIMARY KEY,
      b INT,
      c TEXT,
      d INT GENERATED ALWAYS AS (a*abs(b)) VIRTUAL,
      e TEXT GENERATED ALWAYS AS (substr(c,b,b+1)) STORED,
      f TEXT GENERATED ALWAYS AS (substr(c,b,b+1)) STORED
  );

  INSERT INTO t1 VALUES(1, 2, 'hello world');
}
do_recover_test 6

do_execsql_test 7.0 {
  CREATE TABLE t2(i, j GENERATED ALWAYS AS (i+1) STORED, k);
  INSERT INTO t2 VALUES(10, 'ten');
}
do_execsql_test 7.1 {
  SELECT * FROM t2
} {10 11 ten}

do_recover_test 7.2

#--------------------------------------------------------------------------
#
reset_db
do_execsql_test 8.0 {
  CREATE TABLE x1(a INTEGER PRIMARY KEY AUTOINCREMENT, b, c);
  WITH s(i) AS (
    SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<2
  )
  INSERT INTO x1(b, c) SELECT hex(randomblob(100)), hex(randomblob(100)) FROM s;
  
  CREATE INDEX x1b ON x1(b);
  CREATE INDEX x1cb ON x1(c, b);
  DELETE FROM x1 WHERE a>50;

  ANALYZE;
}

do_recover_test 8

#-------------------------------------------------------------------------
reset_db
ifcapable fts5 {
  do_execsql_test 9.1 {
    CREATE VIRTUAL TABLE ft5 USING fts5(a, b);
    INSERT INTO ft5 VALUES('hello', 'world');
  }
  do_recover_test 9 
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 10.1 {
  CREATE TABLE x1(a PRIMARY KEY, str TEXT) WITHOUT ROWID;
  INSERT INTO x1 VALUES(1, '
    \nhello\012world(\n0)(\n1)
  ');
  INSERT INTO x1 VALUES(2, '
    \nhello
  ');
}
do_execsql_test 10.2 "
  INSERT INTO x1 VALUES(3, '\012hello there\015world');
  INSERT INTO x1 VALUES(4, '\015hello there\015world');
"
do_recover_test 10 

#-------------------------------------------------------------------------
reset_db
do_execsql_test 11.1 {
  PRAGMA page_size = 4096;
  PRAGMA encoding='utf16';
  PRAGMA auto_vacuum = 2;
  PRAGMA user_version = 45;
  PRAGMA application_id = 22;

  CREATE TABLE u1(u, v);
  INSERT INTO u1 VALUES('edvin marton', 'bond');
  INSERT INTO u1 VALUES(1, 4.0);
}
do_execsql_test 11.1a {
  PRAGMA auto_vacuum;
} {2}

do_recover_test 11 

do_test 12.1 {
  set R [sqlite3_recover_init db "" test.db2]
  $R config lostandfound ""
  $R config invalid xyz
} {12}
do_test 12.2 {
  $R run
  $R run
} {0}

do_test 12.3 {
  $R finish
} {}



#-------------------------------------------------------------------------
reset_db
file_control_reservebytes db 16
do_execsql_test 12.1 {
  PRAGMA auto_vacuum = 2;
  PRAGMA user_version = 45;
  PRAGMA application_id = 22;

  CREATE TABLE u1(u, v);
  CREATE UNIQUE INDEX i1 ON u1(u, v);
  INSERT INTO u1 VALUES(1, 2), (3, 4);

  CREATE TABLE u2(u, v);
  CREATE UNIQUE INDEX i2 ON u1(u, v);
  INSERT INTO u2 VALUES(hex(randomblob(500)), hex(randomblob(1000)));
  INSERT INTO u2 VALUES(hex(randomblob(500)), hex(randomblob(1000)));
  INSERT INTO u2 VALUES(hex(randomblob(500)), hex(randomblob(1000)));
  INSERT INTO u2 VALUES(hex(randomblob(50000)), hex(randomblob(20000)));
}

do_recover_test 12 

#-------------------------------------------------------------------------
reset_db
sqlite3 db "" 
do_recover_test 13

do_execsql_test 14.1 {
  PRAGMA auto_vacuum = 2;
  PRAGMA user_version = 45;
  PRAGMA application_id = 22;

  CREATE TABLE u1(u, v);
  CREATE UNIQUE INDEX i1 ON u1(u, v);
  INSERT INTO u1 VALUES(1, 2), (3, 4);

  CREATE TABLE u2(u, v);
  CREATE UNIQUE INDEX i2 ON u1(u, v);
  INSERT INTO u2 VALUES(hex(randomblob(500)), hex(randomblob(1000)));
  INSERT INTO u2 VALUES(hex(randomblob(500)), hex(randomblob(1000)));
  INSERT INTO u2 VALUES(hex(randomblob(500)), hex(randomblob(1000)));
  INSERT INTO u2 VALUES(hex(randomblob(50000)), hex(randomblob(20000)));
}
do_recover_test 14 

#-------------------------------------------------------------------------
reset_db
execsql {
  PRAGMA journal_mode=OFF;
  PRAGMA mmap_size=10;
}
do_execsql_test 15.1 {
  CREATE TABLE t1(x);
} {}
do_recover_test 15 

#-------------------------------------------------------------------------
reset_db
do_execsql_test 16.1 {
  PRAGMA journal_mode = wal;
  CREATE TABLE t1(x);
  INSERT INTO t1 VALUES(1), (2), (3);
} {wal}
do_test 16.2 {
  set R [sqlite3_recover_init db main test.db2]
  $R run
  $R finish
} {}
do_execsql_test 16.3 {
  SELECT * FROM t1;
} {1 2 3}

do_execsql_test 16.4 {
  BEGIN;
    SELECT * FROM t1;
} {1 2 3}
do_test 16.5 {
  set R [sqlite3_recover_init db main test.db2]
  $R run
  list [catch { $R finish } msg] $msg
} {1 {cannot start a transaction within a transaction}}
do_execsql_test 16.6 {
  SELECT * FROM t1;
} {1 2 3}
do_execsql_test 16.7 {
  INSERT INTO t1 VALUES(4);
}
do_test 16.8 {
  set R [sqlite3_recover_init db main test.db2]
  $R run
  list [catch { $R finish } msg] $msg
} {1 {cannot start a transaction within a transaction}}
do_execsql_test 16.9 {
  SELECT * FROM t1;
  COMMIT;
} {1 2 3 4}

finish_test

Added ext/recover/recover_common.tcl.















1
2
3
4
5
6
7
8
9
10
11
12
13
14
+
+
+
+
+
+
+
+
+
+
+
+
+
+


if {![info exists testdir]} {
  set testdir [file join [file dirname [info script]] .. .. test]
} 
source $testdir/tester.tcl

if {[info commands sqlite3_recover_init]==""} {
  finish_test
  return -code return
}



Added ext/recover/recoverclobber.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019 April 23
#
# 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.
#
#***********************************************************************
# 
# Tests for the SQLITE_RECOVER_ROWIDS option.
#

source [file join [file dirname [info script]] recover_common.tcl]
set testprefix recoverclobber

proc recover {db output} {
  set R [sqlite3_recover_init db main test.db2]
  $R run
  $R finish
}

forcedelete test.db2
do_execsql_test 1.0 {
  ATTACH 'test.db2' AS aux;
  CREATE TABLE aux.x1(x, one);
  INSERT INTO x1 VALUES(1, 'one'), (2, 'two'), (3, 'three');

  CREATE TABLE t1(a, b);
  INSERT INTO t1 VALUES(1, 1), (2, 2), (3, 3), (4, 4);

  DETACH aux;
}

breakpoint
do_test 1.1 {
  recover db test.db2
} {}

do_execsql_test 1.2 {
  ATTACH 'test.db2' AS aux;
  SELECT * FROM aux.t1;
} {1 1   2 2   3 3   4 4}

do_catchsql_test 1.3 {
  SELECT * FROM aux.x1;
} {1 {no such table: aux.x1}}

finish_test

Added ext/recover/recovercorrupt.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022 August 28
#
# 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.
#
#***********************************************************************
#

source [file join [file dirname [info script]] recover_common.tcl]
set testprefix recovercorrupt

database_may_be_corrupt

do_execsql_test 1.0 {
  PRAGMA page_size = 512;
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
  INSERT INTO t1 VALUES(1, 2, 3);
  INSERT INTO t1 VALUES(2, hex(randomblob(100)), randomblob(200));
  CREATE INDEX i1 ON t1(b, c);
  CREATE TABLE t2(a PRIMARY KEY, b, c) WITHOUT ROWID;
  INSERT INTO t2 VALUES(1, 2, 3);
  INSERT INTO t2 VALUES(2, hex(randomblob(100)), randomblob(200));
  ANALYZE;
  PRAGMA writable_schema = 1;
  DELETE FROM sqlite_schema WHERE name='t2';
}

do_test 1.1 {
  expr [file size test.db]>3072
} {1}

proc toggle_bit {blob bit} {
  set byte [expr {$bit / 8}]
  set bit [expr {$bit & 0x0F}]
  binary scan $blob a${byte}ca* A x B
  set x [expr {$x ^ (1 << $bit)}]
  binary format a*ca* $A $x $B
}


db_save_and_close
for {set ii 0} {$ii < 10000} {incr ii} {
  db_restore_and_reopen
  db func toggle_bit toggle_bit
  set bitsperpage [expr 512*8]

  set pg [expr {($ii / $bitsperpage)+1}]
  set byte [expr {$ii % $bitsperpage}]
  db eval {
    UPDATE sqlite_dbpage SET data = toggle_bit(data, $byte) WHERE pgno=$pg
  }

    set R [sqlite3_recover_init db main test.db2]
    $R config lostandfound lost_and_found
    $R run
  do_test 1.2.$ii {
    $R finish
  } {}
}


finish_test

Added ext/recover/recovercorrupt2.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022 August 28
#
# 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.
#
#***********************************************************************
#

source [file join [file dirname [info script]] recover_common.tcl]
set testprefix recovercorrupt2

do_execsql_test 1.0 {
  PRAGMA page_size = 512;
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
  INSERT INTO t1 VALUES(1, 2, 3);
  INSERT INTO t1 VALUES(2, hex(randomblob(100)), randomblob(200));
  CREATE INDEX i1 ON t1(b, c);
  CREATE TABLE t2(a PRIMARY KEY, b, c) WITHOUT ROWID;
  INSERT INTO t2 VALUES(1, 2, 3);
  INSERT INTO t2 VALUES(2, hex(randomblob(100)), randomblob(200));
  ANALYZE;
  PRAGMA writable_schema = 1;
  UPDATE sqlite_schema SET sql = 'CREATE INDEX i1 ON o(world)' WHERE name='i1'; 
  DELETE FROM sqlite_schema WHERE name='sqlite_stat4';
}

do_test 1.1 {
  set R [sqlite3_recover_init db main test.db2]
  $R run
  $R finish
} {}

sqlite3 db2 test.db2
do_execsql_test -db db2 1.2 {
  SELECT sql FROM sqlite_schema
} {
  {CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c)}
  {CREATE TABLE t2(a PRIMARY KEY, b, c) WITHOUT ROWID} 
  {CREATE TABLE sqlite_stat1(tbl,idx,stat)} 
}
db2 close

do_execsql_test 1.3 {
  PRAGMA writable_schema = 1;
  UPDATE sqlite_schema SET sql = 'CREATE TABLE t2 syntax error!' WHERE name='t2';
}

do_test 1.4 {
  set R [sqlite3_recover_init db main test.db2]
  $R run
  $R finish
} {}

sqlite3 db2 test.db2
do_execsql_test -db db2 1.5 {
  SELECT sql FROM sqlite_schema
} {
  {CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c)}
  {CREATE TABLE sqlite_stat1(tbl,idx,stat)} 
}
db2 close

#-------------------------------------------------------------------------
#
reset_db
do_test 2.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 8192 pagesize 4096 filename x3.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 02 00 00 00 02   .....@  ........
|     32: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 04   ................
|     48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00   ................
|     80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02   ................
|     96: 00 2e 63 00 0d 00 00 00 01 0f d8 00 0f d8 00 00   ..c.............
|   4048: 00 00 00 00 00 00 00 00 26 01 06 17 11 11 01 39   ........&......9
|   4064: 74 61 62 6c 65 74 31 74 31 02 43 52 45 41 54 45   tablet1t1.CREATE
|   4080: 20 54 41 42 4c 45 20 74 31 28 61 2c 62 2c 63 29    TABLE t1(a,b,c)
| page 2 offset 4096
|      0: 0d 00 00 00 01 0f ce 00 0f ce 00 00 00 00 00 00   ................
|   4032: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff ff   ..............(.
|   4048: ff ff ff ff ff ff ff 28 04 27 25 23 61 61 61 61   .........'%#aaaa
|   4064: 61 61 61 61 61 61 61 61 61 62 62 62 62 62 62 62   aaaaaaaaabbbbbbb
|   4080: 62 62 62 62 62 63 63 63 63 63 63 63 63 63 63 63   bbbbbccccccccccc
| end x3.db
}]} {}

do_test 2.1 {
  set R [sqlite3_recover_init db main test.db2]
  $R run
  $R finish
} {}

sqlite3 db2 test.db2
do_execsql_test -db db2 2.2 {
  SELECT sql FROM sqlite_schema
} {
  {CREATE TABLE t1(a,b,c)}
}
do_execsql_test -db db2 2.3 {
  SELECT * FROM t1
} {}
db2 close

#-------------------------------------------------------------------------
#
reset_db
do_test 3.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
  .open --hexdb
  | size 4096 pagesize 1024 filename corrupt032.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: 04 00 01 01 08 40 20 20 00 00 00 02 00 00 00 03   .....@  ........
  |     32: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 04   ................
  |     48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00   ................
  |     80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02   ................
  |     96: 00 2e 24 80 0d 00 00 00 01 03 d4 00 03 d4 00 00   ..$.............
  |    976: 00 00 00 00 22 01 06 17 11 11 01 31 74 61 62 6c   ...........1tabl
  |    992: 65 74 31 74 31 02 43 52 45 41 54 45 20 54 41 42   et1t1.CREATE TAB
  |   1008: 4c 45 20 74 31 28 78 29 00 00 00 00 00 00 00 00   LE t1(x)........
  | page 2 offset 1024
  |      0: 0d 00 00 00 01 02 06 00 02 06 00 00 00 00 00 00   ................
  |    512: 00 00 00 00 00 00 8b 60 01 03 97 46 00 00 00 00   .......`...F....
  |   1008: 00 00 00 00 00 00 00 03 00 00 00 00 00 00 00 00   ................
  | end corrupt032.txt.db
}]} {}

do_test 3.1 {
  set R [sqlite3_recover_init db main test.db2]
  $R run
  $R finish
} {}

#-------------------------------------------------------------------------
#
reset_db
do_test 4.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
  .open --hexdb
  | size 4096 pagesize 4096 filename crash-00f2d3627f1b43.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: 00 01 01 02 00 40 20 20 01 00 ff 00 42 01 10 01   .....@  ....B...
  |     32: ef 00 00 87 00 ff ff ff f0 01 01 10 ff ff 00 00   ................
  | end crash-00f2d3627f1b43.db
}]} {}

do_test 4.1 {
  set R [sqlite3_recover_init db main test.db2]
  catch { $R run }
  list [catch { $R finish } msg] $msg
} {1 {unable to open database file}}

#-------------------------------------------------------------------------
#
reset_db
do_test 5.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
.open --hexdb
| size 16384 pagesize 4096 filename crash-7b75760a4c5f15.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 00   ................
|     96: 00 00 00 00 0d 00 00 00 03 0f 4e 00 0f bc 0f 90   ..........N.....
|    112: 0f 4e 00 00 00 00 00 00 00 00 00 00 00 00 00 00   .N..............
|   3904: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 03   ..............@.
|   3920: 06 17 11 11 01 6d 74 61 62 6c 65 74 32 74 32 04   .....mtablet2t2.
|   3936: 43 52 45 41 54 45 20 54 41 42 4c 45 20 74 32 28   CREATE TABLE t2(
|   3952: 78 2c 79 2c 7a 20 50 52 49 4d 41 52 59 20 4b 45   x,y,z PRIMARY KE
|   3968: 59 29 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44   Y) WITHOUT ROWID
|   3984: 2a 02 06 17 13 11 01 3f 69 6e 64 65 78 74 31 61   *......?indext1a
|   4000: 74 31 03 43 52 45 41 54 45 20 49 4e 44 45 58 20   t1.CREATE INDEX 
|   4016: 74 31 61 20 4f 4e 20 74 31 28 61 29 42 01 06 17   t1a ON t1(a)B...
|   4032: 11 11 01 71 74 61 62 6c 65 74 31 74 31 02 43 52   ...qtablet1t1.CR
|   4048: 45 41 54 45 20 54 41 42 4c 45 20 74 31 28 61 20   EATE TABLE t1(a 
|   4064: 49 4e 54 2c 62 20 54 45 58 54 2c 63 20 42 4c 4f   INT,b TEXT,c BLO
|   4080: 42 2c 64 20 52 45 41 4c 29 20 53 54 52 49 43 54   B,d REAL) STRICT
| page 2 offset 4096
|      0: 0d 00 00 00 14 0c ae 00 0f df 0f bd 0f 9a 0f 76   ...............v
|     16: 0f 51 0f 2b 0f 04 0e dc 0e b3 0e 89 0e 5e 0e 32   .Q.+.........^.2
|     32: 0e 05 0d 1a 0d a8 0d 78 0d 47 0d 15 0c e2 00 00   .......x.G......
|   3232: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 32 14   ..............2.
|   3248: 05 06 3f 34 07 15 f4 c9 23 af e2 b3 b6 61 62 63   ..?4....#....abc
|   3264: 30 32 30 78 79 7a 01 00 00 00 00 00 00 00 00 00   020xyz..........
|   3280: 00 00 00 00 00 00 00 00 00 00 c3 b0 96 7e fb 4e   .............~.N
|   3296: c5 4c 31 13 05 06 1f 32 07 dd f2 2a a5 7e b2 4d   .L1....2...*.~.M
|   3312: 82 61 62 63 30 31 39 78 79 7a 01 00 00 00 00 00   .abc019xyz......
|   3328: 00 00 00 00 00 00 00 00 00 00 00 00 00 c3 a3 d6   ................
|   3344: e9 f1 c2 fd f3 30 12 05 06 1f 30 07 8f 8f f5 c4   .....0....0.....
|   3360: 35 b6 7f 8d 61 62 63 30 31 38 00 00 00 00 00 00   5...abc018......
|   3376: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 43   ...............C
|   3392: b2 13 1f 9d 56 8a 47 21 b1 05 06 1f 2e 07 7f 46   ....V.G!.......F
|   3408: 91 03 3f 97 fb f7 61 62 63 30 00 00 00 00 00 00   ..?...abc0......
|   3440: c3 bb d8 96 86 c2 e8 2b 2e 10 05 06 1f 2c 07 6d   .......+.....,.m
|   3456: 85 7b ce d0 32 d2 54 61 62 63 30 00 00 00 00 00   ....2.Tabc0.....
|   3488: 43 a1 eb 44 14 dc 03 7b 2d 0f 05 06 1f 2a 07 d9   C..D....-....*..
|   3504: ab ec bf 34 51 70 f3 61 62 63 30 31 35 78 79 7a   ...4Qp.abc015xyz
|   3520: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 c3   ................
|   3536: b6 3d f4 46 b1 6a af 2c 0e 05 06 1f 28 07 36 75   .=.F.j.,....(.6u
|   3552: e9 a2 bd 05 04 ea 61 62 63 30 31 34 78 79 7a 00   ......abc014xyz.
|   3568: 00 00 00 00 00 00 00 00 00 00 00 00 00 c3 ab 23   ...............#
|   3584: a7 6a 34 ca f8 2b 0d 05 06 1f 26 07 48 45 ab e0   .j4..+....&.HE..
|   3600: 8c 7c ff 0c 61 62 63 30 31 33 78 79 7a 00 00 00   .|..abc013xyz...
|   3616: 00 00 00 00 0d d0 00 00 00 00 43 b8 d3 93 f4 92   ..........C.....
|   3632: 5b 7a 2a 0c 05 06 1f 24 07 be 6d 1e db 61 5d 80   [z*....$..m..a].
|   3648: 9f 61 62 63 30 31 32 78 79 7a 00 00 00 00 00 00   .abc012xyz......
|   3664: 00 00 00 00 00 00 43 b5 a1 a4 af 7b c6 60 29 0b   ......C......`).
|   3680: 05 06 1f 22 07 6e a2 a3 64 68 d4 a6 bd 61 62 63   .....n..dh...abc
|   3696: 30 31 31 78 79 7a 00 00 00 00 00 00 00 00 00 00   011xyz..........
|   3712: 00 c3 c4 1e ff 0f fc e6 ff 28 0a 05 06 1f 20 07   .........(.... .
|   3728: 50 f9 4a bb a5 7a 1e ca 61 62 63 30 31 30 78 79   P.J..z..abc010xy
|   3744: 7a 00 00 00 00 00 00 00 00 00 00 c3 a7 90 ed d9   z...............
|   3760: 5c 2c d5 27 09 05 06 1f 1e 07 90 8e 1d d9 1c 3a   .,.'...........:
|   3776: e8 c1 61 62 63 30 30 39 78 79 7a 00 00 00 00 00   ..abc009xyz.....
|   3792: 00 00 00 00 43 a7 97 87 cf b0 ff 79 26 08 05 06   ....C......y&...
|   3808: 1f 1c 07 86 65 f6 7c 50 7a 2c 76 61 62 63 30 30   ....e.|Pz,vabc00
|   3824: 38 78 79 7a 00 00 00 00 00 00 00 00 c3 b0 e3 4c   8xyz...........L
|   3840: 4f d3 41 b5 25 07 05 06 1f 1a 07 8b 20 e5 68 11   O.A.%....... .h.
|   3856: 13 55 87 61 62 63 30 30 37 78 79 7a 00 00 00 00   .U.abc007xyz....
|   3872: 00 00 00 c3 b6 a3 74 f1 9c 33 f8 24 06 05 06 1f   ......t..3.$....
|   3888: 18 07 97 3c bc 34 49 94 54 ab 61 62 63 30 30 36   ...<.4I.T.abc006
|   3904: 78 79 7a 00 00 00 00 00 00 c3 88 00 c2 ca 4c 4d   xyz...........LM
|   3920: d3 23 05 05 06 1f 16 07 59 37 11 10 e9 e5 3d d5   .#......Y7....=.
|   3936: 61 62 63 30 30 35 78 79 7a 00 00 00 00 00 c3 c0   abc005xyz.......
|   3952: 15 12 67 ed 4b 79 22 04 05 06 1f 14 07 93 39 01   ..g.Ky........9.
|   3968: 7f b8 c7 99 58 61 62 63 30 30 34 78 79 7a 00 00   ....Xabc004xyz..
|   3984: 09 c0 43 bf e0 e7 6d 70 fd 61 21 03 05 06 1f 12   ..C...mp.a!.....
|   4000: 07 b6 df 8d 8b 27 08 22 5a 61 62 63 30 30 33 78   .....'..Zabc003x
|   4016: 79 7a 00 00 00 c3 c7 ea 0f dc dd 32 22 20 02 05   yz.........2. ..
|   4032: 06 1f 10 07 2f a6 da 71 df 66 b3 b5 61 62 63 30   ..../..q.f..abc0
|   4048: 30 32 78 79 7a 00 00 c3 ce d9 8d e9 ec 20 45 1f   02xyz........ E.
|   4064: 01 05 06 1f 0e 07 5a 47 53 20 3b 48 8f c0 61 62   ......ZGS ;H..ab
|   4080: 63 30 30 31 78 79 7a 00 c3 c9 e6 81 f8 d9 24 04   c001xyz.......$.
| page 3 offset 8192
|      0: 0a 00 00 00 14 0e fd 00 0f f3 0f e6 0f d9 0f cc   ................
|     16: 0f bf 0f b2 0f a5 0f 98 0f 8b 0f 7e 0f 71 0f 64   ...........~.q.d
|     32: 0f 57 0f 4a 0f 3d 0f 30 0f 24 00 00 00 00 00 00   .W.J.=.0.$......
|   3824: 00 00 00 00 00 00 00 00 00 00 00 00 00 0c 03 06   ................
|   3840: 01 7f 46 91 03 3f 97 fb f7 11 0c 03 06 01 6e a2   ..F..?........n.
|   3856: a3 64 68 d4 a6 bd 0b 0c 03 06 01 6d 85 7b ce d0   .dh........m....
|   3872: 32 d2 54 10 0b 03 06 09 5a 47 53 20 3b 48 8f c0   2.T.....ZGS ;H..
|   3888: 0c 03 06 01 59 37 11 10 e9 e5 3d d5 05 0c 03 06   ....Y7....=.....
|   3904: 01 50 f9 4a bb a5 7a 1e ca 0a 0c 03 06 01 48 45   .P.J..z.......HE
|   3920: ab e0 8c 7c ff 0c 0d 0c 03 06 01 36 75 e9 a2 bd   ...|.......6u...
|   3936: 05 04 ea 0e 0c 03 06 01 2f a6 da 71 df 66 b3 b5   ......../..q.f..
|   3952: 02 0c 03 06 01 15 f4 c9 23 af e2 b3 b6 14 0c 03   ........#.......
|   3968: 06 01 dd f2 2a a5 7e b2 4d 82 13 0c 03 06 01 d9   ....*.~.M.......
|   3984: ab ec bf 34 51 70 f3 0f 0c 03 06 01 be 6d 1e db   ...4Qp.......m..
|   4000: 61 5d 80 9f 0c 0c 03 06 01 b6 df 8d 8b 27 08 22   a]...........'..
|   4016: 5a 03 0c 03 06 01 97 3c bc 34 49 94 54 ab 06 0c   Z......<.4I.T...
|   4032: 03 06 01 93 39 01 7f b8 c7 99 58 04 0c 03 06 01   ....9.....X.....
|   4048: 90 8e 1d d9 1c 3a e8 c1 09 0c 03 06 01 8f 8f f5   .....:..........
|   4064: c4 35 b6 7f 8d 12 0c 03 06 01 8b 20 e5 68 11 13   .5......... .h..
|   4080: 55 87 07 0c 03 06 01 86 65 f6 7c 50 7a 2b 06 08   U.......e.|Pz+..
| page 4 offset 12288
|      0: 0a 00 00 00 14 0f 62 00 0f 7a 0f a1 0f c9 0f d9   ......b..z......
|     16: 0f 81 0f d1 0f f1 0f f9 0f e1 0f 89 0e 6a 0f c1   .............j..
|     32: 0f 91 0f 99 0f b9 0f 72 0f 62 0f e9 0f b1 0f a9   .......r.b......
|   3936: 00 00 07 04 01 01 01 11 0e 9e 07 04 01 01 01 0b   ................
|   3952: 31 16 07 04 01 01 01 10 37 36 06 04 09 01 01 ab   1.......76......
|   3968: 58 07 04 01 01 01 05 1c 28 07 04 01 01 01 0a 10   X.......(.......
|   3984: cf 07 04 01 01 01 0d b2 e3 07 04 01 01 01 0e d3   ................
|   4000: f2 07 04 01 01 01 02 41 ad 07 04 01 01 01 14 3e   .......A.......>
|   4016: 22 07 04 01 01 01 13 27 45 07 04 01 01 01 0f ad   .......'E.......
|   4032: dd 07 04 01 01 01 0c 2e a1 07 04 01 01 01 03 df   ................
|   4048: e1 07 04 01 01 01 06 59 a7 07 04 01 01 01 04 27   .......Y.......'
|   4064: bd 07 04 01 01 01 09 d0 e0 07 04 01 01 01 12 39   ...............9
|   4080: 4f 07 04 01 01 01 07 c4 11 06 04 00 00 00 00 00   O...............
| end crash-7b75760a4c5f15.db
}]} {}

do_test 5.1 {
  set R [sqlite3_recover_init db main test.db2]
  catch { $R run }
  list [catch { $R finish } msg] $msg
} {0 {}}

finish_test

Added ext/recover/recoverfault.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022 August 28
#
# 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.
#
#***********************************************************************
#

source [file join [file dirname [info script]] recover_common.tcl]
set testprefix recoverfault


#--------------------------------------------------------------------------
proc compare_result {db1 db2 sql} {
  set r1 [$db1 eval $sql]
  set r2 [$db2 eval $sql]
  if {$r1 != $r2} {
    puts "r1: $r1"
    puts "r2: $r2"
    error "mismatch for $sql"
  }
  return ""
}

proc compare_dbs {db1 db2} {
  compare_result $db1 $db2 "SELECT sql FROM sqlite_master ORDER BY 1"
  foreach tbl [$db1 eval {SELECT name FROM sqlite_master WHERE type='table'}] {
    compare_result $db1 $db2 "SELECT * FROM $tbl"
  }
}
#--------------------------------------------------------------------------

do_execsql_test 1.0 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
  INSERT INTO t1 VALUES(1, 2, 3);
  INSERT INTO t1 VALUES(2, hex(randomblob(1000)), randomblob(2000));
  CREATE INDEX i1 ON t1(b, c);
  ANALYZE;
}
faultsim_save_and_close

do_faultsim_test 1 -faults oom* -prep {
  catch { db2 close }
  faultsim_restore_and_reopen
} -body {
  set R [sqlite3_recover_init db main test.db2]
  $R run
  $R finish
} -test {
  faultsim_test_result {0 {}} {1 {}}
  if {$testrc==0} {
    sqlite3 db2 test.db2
    compare_dbs db db2
    db2 close
  }
}

faultsim_restore_and_reopen 
do_execsql_test 2.0 {
  CREATE TABLE t2(a INTEGER PRIMARY KEY, b, c);
  INSERT INTO t2 VALUES(1, 2, 3);
  INSERT INTO t2 VALUES(2, hex(randomblob(1000)), hex(randomblob(2000)));
  PRAGMA writable_schema = 1;
  DELETE FROM sqlite_schema WHERE name='t2';
}
faultsim_save_and_close

do_faultsim_test 2 -faults oom* -prep {
  faultsim_restore_and_reopen
} -body {
  set R [sqlite3_recover_init db main test.db2]
  $R config lostandfound lost_and_found
  $R run
  $R finish
} -test {
  faultsim_test_result {0 {}} {1 {}}
}

finish_test

Added ext/recover/recoverfault2.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022 August 28
#
# 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.
#
#***********************************************************************
#

source [file join [file dirname [info script]] recover_common.tcl]
set testprefix recoverfault2


#--------------------------------------------------------------------------
proc compare_result {db1 db2 sql} {
  set r1 [$db1 eval $sql]
  set r2 [$db2 eval $sql]
  if {$r1 != $r2} {
    puts "r1: $r1"
    puts "r2: $r2"
    error "mismatch for $sql"
  }
  return ""
}

proc compare_dbs {db1 db2} {
  compare_result $db1 $db2 "SELECT sql FROM sqlite_master ORDER BY 1"
  foreach tbl [$db1 eval {SELECT name FROM sqlite_master WHERE type='table'}] {
    compare_result $db1 $db2 "SELECT * FROM $tbl"
  }
}
#--------------------------------------------------------------------------

do_execsql_test 1.0 "
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
  INSERT INTO t1 VALUES(2, '\012hello\015world\012today\n');
"
faultsim_save_and_close

proc my_sql_hook {sql} {
  lappend ::lSql $sql
  return 0
}

do_faultsim_test 1 -faults oom* -prep {
  catch { db2 close }
  faultsim_restore_and_reopen
  set ::lSql [list]
} -body {
  set R [sqlite3_recover_init_sql db main my_sql_hook]
  $R run
  $R finish
} -test {
  faultsim_test_result {0 {}} {1 {}}
  if {$testrc==0} {
    sqlite3 db2 ""
    db2 eval [join $::lSql ";"]
    compare_dbs db db2
    db2 close
  }
}

ifcapable utf16 {
  reset_db
  do_execsql_test 2.0 "
    PRAGMA encoding='utf-16';
    CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
    INSERT INTO t1 VALUES(2, '\012hello\015world\012today\n');
  "
  faultsim_save_and_close
  
  proc my_sql_hook {sql} {
    lappend ::lSql $sql
    return 0
  }
  
  do_faultsim_test 2 -faults oom-t* -prep {
    catch { db2 close }
    faultsim_restore_and_reopen
    set ::lSql [list]
  } -body {
    set R [sqlite3_recover_init_sql db main my_sql_hook]
    $R run
    $R finish
  } -test {
    faultsim_test_result {0 {}} {1 {}}
    if {$testrc==0} {
      sqlite3 db2 ""
      db2 eval [join $::lSql ";"]
      compare_dbs db db2
      db2 close
    }
  }
}



finish_test

Added ext/recover/recoverold.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
189
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019 April 23
#
# 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.
#
#***********************************************************************
#
#

source [file join [file dirname [info script]] recover_common.tcl]
set testprefix recoverold

proc compare_result {db1 db2 sql} {
  set r1 [$db1 eval $sql]
  set r2 [$db2 eval $sql]
  if {$r1 != $r2} {
  puts "sql: $sql"
  puts "r1: $r1"
  puts "r2: $r2"
    error "mismatch for $sql"
  }
  return ""
}

proc compare_dbs {db1 db2} {
  compare_result $db1 $db2 "SELECT sql FROM sqlite_master ORDER BY 1"
  foreach tbl [$db1 eval {SELECT name FROM sqlite_master WHERE type='table'}] {
    compare_result $db1 $db2 "SELECT * FROM $tbl"
  }
}

proc do_recover_test {tn {tsql {}} {res {}}} {
  forcedelete test.db2
  forcedelete rstate.db

  set R [sqlite3_recover_init db main test.db2]
  $R config lostandfound lost_and_found
  $R run
  $R finish
  
  sqlite3 db2 test.db2

  if {$tsql==""} {
    uplevel [list do_test $tn.1 [list compare_dbs db db2] {}]
  } else {
    uplevel [list do_execsql_test -db db2 $tn.1 $tsql $res]
  }
  db2 close

  forcedelete test.db2
  forcedelete rstate.db

  set ::sqlhook [list]
  set R [sqlite3_recover_init_sql db main my_sql_hook]
  $R config lostandfound lost_and_found
  $R run
  $R finish
  
  sqlite3 db2 test.db2
  db2 eval [join $::sqlhook ";"]


  db cache flush
  if {$tsql==""} {
  compare_dbs db db2
    uplevel [list do_test $tn.sql [list compare_dbs db db2] {}]
  } else {
    uplevel [list do_execsql_test -db db2 $tn.sql $tsql $res]
  }
  db2 close
}

proc my_sql_hook {sql} {
  lappend ::sqlhook $sql
  return 0
}


set doc {
  hello
  world
}
do_execsql_test 1.1.1 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
  INSERT INTO t1 VALUES(1, 4, X'1234567800');
  INSERT INTO t1 VALUES(2, 'test', 8.1);
  INSERT INTO t1 VALUES(3, $doc, 8.4);
}
do_recover_test 1.1.2

do_execsql_test 1.2.1 "
  DELETE FROM t1;
  INSERT INTO t1 VALUES(13, 'hello\r\nworld', 13);
"
do_recover_test 1.2.2

do_execsql_test 1.3.1 "
  CREATE TABLE t2(i INTEGER PRIMARY KEY AUTOINCREMENT, b, c);
  INSERT INTO t2 VALUES(NULL, 1, 2);
  INSERT INTO t2 VALUES(NULL, 3, 4);
  INSERT INTO t2 VALUES(NULL, 5, 6);
  CREATE TABLE t3(i INTEGER PRIMARY KEY AUTOINCREMENT, b, c);
  INSERT INTO t3 VALUES(NULL, 1, 2);
  INSERT INTO t3 VALUES(NULL, 3, 4);
  INSERT INTO t3 VALUES(NULL, 5, 6);
  DELETE FROM t2;
"
do_recover_test 1.3.2

#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.1.0 {
  PRAGMA auto_vacuum = 0;
  CREATE TABLE t1(a, b, c, PRIMARY KEY(b, c)) WITHOUT ROWID;
  INSERT INTO t1 VALUES(1, 2, 3);
  INSERT INTO t1 VALUES(4, 5, 6);
  INSERT INTO t1 VALUES(7, 8, 9);
}

do_recover_test 2.1.1

do_execsql_test 2.2.0 {
  PRAGMA writable_schema = 1;
  DELETE FROM sqlite_master WHERE name='t1';
}
do_recover_test 2.2.1 {
  SELECT name FROM sqlite_master
} {lost_and_found}

do_execsql_test 2.3.0 {
  CREATE TABLE lost_and_found(a, b, c);
}
do_recover_test 2.3.1 {
  SELECT name FROM sqlite_master
} {lost_and_found lost_and_found_0}

do_execsql_test 2.4.0 {
  CREATE TABLE lost_and_found_0(a, b, c);
}
do_recover_test 2.4.1 {
  SELECT name FROM sqlite_master;
  SELECT * FROM lost_and_found_1;
} {lost_and_found lost_and_found_0 lost_and_found_1
  2 2 3 {} 2 3 1
  2 2 3 {} 5 6 4
  2 2 3 {} 8 9 7
}

do_execsql_test 2.5 {
  CREATE TABLE x1(a, b, c);
  WITH s(i) AS (
    SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<100
  )
  INSERT INTO x1 SELECT i, i, hex(randomblob(500)) FROM s;
  DROP TABLE x1;
}
do_recover_test 2.5.1 {
  SELECT name FROM sqlite_master;
  SELECT * FROM lost_and_found_1;
} {lost_and_found lost_and_found_0 lost_and_found_1
  2 2 3 {} 2 3 1
  2 2 3 {} 5 6 4
  2 2 3 {} 8 9 7
}

ifcapable !secure_delete {
  do_test 2.6 {
    forcedelete test.db2
    set R [sqlite3_recover_init db main test.db2]
    $R config lostandfound lost_and_found
    $R config freelistcorrupt 1
    $R run
    $R finish
    sqlite3 db2 test.db2
    execsql { SELECT count(*) FROM lost_and_found_1; } db2
  } {103}
  db2 close
}

#-------------------------------------------------------------------------
breakpoint
reset_db
do_recover_test 3.0

finish_test

Added ext/recover/recoverpgsz.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022 October 14
#
# 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.
#
#***********************************************************************
#

source [file join [file dirname [info script]] recover_common.tcl]

db close
sqlite3_test_control_pending_byte 0x1000000

set testprefix recoverpgsz

foreach {pgsz bOverflow} {
  512 0 1024 0 2048 0 4096 0 8192 0 16384 0 32768 0 65536 0
  512 1 1024 1 2048 1 4096 1 8192 1 16384 1 32768 1 65536 1
} {
  reset_db
  execsql "PRAGMA page_size = $pgsz"
  execsql "PRAGMA auto_vacuum = 0"
  do_execsql_test 1.$pgsz.$bOverflow.1 {
    CREATE TABLE t1(a, b, c);
    CREATE INDEX i1 ON t1(b, a, c);
    INSERT INTO t1(a, b) VALUES(1, 2), (3, 4), (5, 6);
    DELETE FROM t1 WHERE a=3;
  }
  if {$bOverflow} {
    do_execsql_test 1.$pgsz.$bOverflow.1a {
      UPDATE t1 SET c = randomblob(100000);
    }
  }
  db close


  set fd [open test.db]
  fconfigure $fd -encoding binary -translation binary
  seek $fd $pgsz
  set pg1 [read $fd $pgsz]
  set pg2 [read $fd $pgsz]
  close $fd

  set fd2 [open test.db2 w]
  fconfigure $fd2 -encoding binary -translation binary
  seek $fd2 $pgsz
  puts -nonewline $fd2 $pg1
  close $fd2

  sqlite3 db2 test.db2
  do_test 1.$pgsz.$bOverflow.2 {
    set R [sqlite3_recover_init db2 main test.db3]
    $R run
    $R finish
  } {}

  sqlite3 db3 test.db3
  do_test 1.$pgsz.$bOverflow.3 {
    db3 eval { SELECT * FROM sqlite_schema }
    db3 eval { PRAGMA page_size } 
  } $pgsz

  db2 close
  db3 close

  forcedelete test.db3
  forcedelete test.db2

  set fd2 [open test.db2 w]
  fconfigure $fd2 -encoding binary -translation binary
  seek $fd2 $pgsz
  puts -nonewline $fd2 $pg2
  close $fd2

  sqlite3 db2 test.db2
  do_test 1.$pgsz.$bOverflow.4 {
    set R [sqlite3_recover_init db2 main test.db3]
    $R run
    $R finish
  } {}

  sqlite3 db3 test.db3
  do_test 1.$pgsz.$bOverflow.5 {
    db3 eval { SELECT * FROM sqlite_schema }
    db3 eval { PRAGMA page_size } 
  } $pgsz

  db2 close
  db3 close
}


finish_test



Added ext/recover/recoverrowid.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022 September 07
#
# 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.
#
#***********************************************************************
# 
# Tests for the SQLITE_RECOVER_ROWIDS option.
#

source [file join [file dirname [info script]] recover_common.tcl]
set testprefix recoverrowid

proc recover {db bRowids output} {
  forcedelete $output

  set R [sqlite3_recover_init db main test.db2]
  $R config rowids $bRowids
  $R run
  $R finish
}

do_execsql_test 1.0 {
  CREATE TABLE t1(a, b);
  INSERT INTO t1 VALUES(1, 1), (2, 2), (3, 3), (4, 4);
  DELETE FROM t1 WHERE a IN (1, 3);
}

do_test 1.1 {
  recover db 0 test.db2
  sqlite3 db2 test.db2
  execsql { SELECT rowid, a, b FROM t1 ORDER BY rowid} db2
} {1 2 2 2 4 4}

do_test 1.2 {
  db2 close
  recover db 1 test.db2
  sqlite3 db2 test.db2
  execsql { SELECT rowid, a, b FROM t1 ORDER BY rowid} db2
} {2 2 2 4 4 4}
db2 close




finish_test

Added ext/recover/recoverslowidx.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022 September 25
#
# 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.
#
#***********************************************************************
# 
# Tests for the SQLITE_RECOVER_SLOWINDEXES option.
#

source [file join [file dirname [info script]] recover_common.tcl]
set testprefix recoverslowidx

do_execsql_test 1.0 {
  PRAGMA auto_vacuum = 0;
  CREATE TABLE t1(a, b);
  CREATE INDEX i1 ON t1(a);
  INSERT INTO t1 VALUES(1, 1), (2, 2), (3, 3), (4, 4);
}

proc my_sql_hook {sql} {
  lappend ::lSql $sql
  return 0
}

do_test 1.1 {
  set lSql [list]
  set R [sqlite3_recover_init_sql db main my_sql_hook]
  while {[$R step]==0} { }
  $R finish
} {}

do_test 1.2 {
  set lSql
} [list {*}{
  {BEGIN}
  {PRAGMA writable_schema = on}
  {PRAGMA encoding = 'UTF-8'}
  {PRAGMA page_size = '1024'}
  {PRAGMA auto_vacuum = '0'}
  {PRAGMA user_version = '0'}
  {PRAGMA application_id = '0'}
  {CREATE TABLE t1(a, b)}
  {INSERT OR IGNORE INTO 't1'(_rowid_, 'a', 'b') VALUES (1, 1, 1)}
  {INSERT OR IGNORE INTO 't1'(_rowid_, 'a', 'b') VALUES (2, 2, 2)}
  {INSERT OR IGNORE INTO 't1'(_rowid_, 'a', 'b') VALUES (3, 3, 3)}
  {INSERT OR IGNORE INTO 't1'(_rowid_, 'a', 'b') VALUES (4, 4, 4)}
  {CREATE INDEX i1 ON t1(a)}
  {PRAGMA writable_schema = off}
  {COMMIT}
}]

do_test 1.3 {
  set lSql [list]
  set R [sqlite3_recover_init_sql db main my_sql_hook]
  $R config slowindexes 1
  while {[$R step]==0} { }
  $R finish
} {}

do_test 1.4 {
  set lSql
} [list {*}{
  {BEGIN}
  {PRAGMA writable_schema = on}
  {PRAGMA encoding = 'UTF-8'}
  {PRAGMA page_size = '1024'}
  {PRAGMA auto_vacuum = '0'}
  {PRAGMA user_version = '0'}
  {PRAGMA application_id = '0'}
  {CREATE TABLE t1(a, b)}
  {CREATE INDEX i1 ON t1(a)}
  {INSERT OR IGNORE INTO 't1'(_rowid_, 'a', 'b') VALUES (1, 1, 1)}
  {INSERT OR IGNORE INTO 't1'(_rowid_, 'a', 'b') VALUES (2, 2, 2)}
  {INSERT OR IGNORE INTO 't1'(_rowid_, 'a', 'b') VALUES (3, 3, 3)}
  {INSERT OR IGNORE INTO 't1'(_rowid_, 'a', 'b') VALUES (4, 4, 4)}
  {PRAGMA writable_schema = off}
  {COMMIT}
}]


finish_test

Added ext/recover/recoversql.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022 September 13
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
#

source [file join [file dirname [info script]] recover_common.tcl]
set testprefix recoversql

do_execsql_test 1.0 {
  CREATE TABLE "x.1" (x, y);
  INSERT INTO "x.1" VALUES(1, 1), (2, 2), (3, 3);
  CREATE INDEX "i.1" ON "x.1"(y, x);
}

proc sql_hook {sql} {
  incr ::iSqlHook
  if {$::iSqlHook==$::sql_hook_cnt} { return 4 }
  return 0
}

do_test 1.1 {
  set ::sql_hook_cnt -1
  set ::iSqlHook 0
  set R [sqlite3_recover_init_sql db main sql_hook]
  $R run
  $R finish
} {}

set nSqlCall $iSqlHook

for {set ii 1} {$ii<$nSqlCall} {incr ii} {
  set iSqlHook 0
  set sql_hook_cnt $ii
  do_test 1.$ii.a {
    set R [sqlite3_recover_init_sql db main sql_hook]
    $R run
  } {1}
  do_test 1.$ii.b {
    list [catch { $R finish } msg] $msg
  } {1 {callback returned an error - 4}}
}


finish_test

Added ext/recover/sqlite3recover.c.























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
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
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
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
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
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
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
1984
1985
1986
1987
1988
1989
1990
1991
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
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
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
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
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
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
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
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
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
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
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
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2022-08-27
**
** 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.
**
*************************************************************************
**
*/


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

#ifndef SQLITE_OMIT_VIRTUALTABLE

/*
** Declaration for public API function in file dbdata.c. This may be called
** with NULL as the final two arguments to register the sqlite_dbptr and
** sqlite_dbdata virtual tables with a database handle.
*/
#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_dbdata_init(sqlite3*, char**, const sqlite3_api_routines*);

typedef unsigned int u32;
typedef unsigned char u8;
typedef sqlite3_int64 i64;

typedef struct RecoverTable RecoverTable;
typedef struct RecoverColumn RecoverColumn;

/*
** When recovering rows of data that can be associated with table
** definitions recovered from the sqlite_schema table, each table is
** represented by an instance of the following object.
**
** iRoot:
**   The root page in the original database. Not necessarily (and usually
**   not) the same in the recovered database.
**
** zTab:
**   Name of the table.
**
** nCol/aCol[]:
**   aCol[] is an array of nCol columns. In the order in which they appear 
**   in the table.
**
** bIntkey:
**   Set to true for intkey tables, false for WITHOUT ROWID.
**
** iRowidBind:
**   Each column in the aCol[] array has associated with it the index of
**   the bind parameter its values will be bound to in the INSERT statement
**   used to construct the output database. If the table does has a rowid
**   but not an INTEGER PRIMARY KEY column, then iRowidBind contains the
**   index of the bind paramater to which the rowid value should be bound.
**   Otherwise, it contains -1. If the table does contain an INTEGER PRIMARY 
**   KEY column, then the rowid value should be bound to the index associated
**   with the column.
**
** pNext:
**   All RecoverTable objects used by the recovery operation are allocated
**   and populated as part of creating the recovered database schema in
**   the output database, before any non-schema data are recovered. They
**   are then stored in a singly-linked list linked by this variable beginning
**   at sqlite3_recover.pTblList.
*/
struct RecoverTable {
  u32 iRoot;                      /* Root page in original database */
  char *zTab;                     /* Name of table */
  int nCol;                       /* Number of columns in table */
  RecoverColumn *aCol;            /* Array of columns */
  int bIntkey;                    /* True for intkey, false for without rowid */
  int iRowidBind;                 /* If >0, bind rowid to INSERT here */
  RecoverTable *pNext;
};

/*
** Each database column is represented by an instance of the following object
** stored in the RecoverTable.aCol[] array of the associated table.
**
** iField:
**   The index of the associated field within database records. Or -1 if
**   there is no associated field (e.g. for virtual generated columns).
**
** iBind:
**   The bind index of the INSERT statement to bind this columns values
**   to. Or 0 if there is no such index (iff (iField<0)).
**
** bIPK:
**   True if this is the INTEGER PRIMARY KEY column.
**
** zCol:
**   Name of column.
**
** eHidden:
**   A RECOVER_EHIDDEN_* constant value (see below for interpretation of each).
*/
struct RecoverColumn {
  int iField;                     /* Field in record on disk */
  int iBind;                      /* Binding to use in INSERT */
  int bIPK;                       /* True for IPK column */
  char *zCol;
  int eHidden;
};

#define RECOVER_EHIDDEN_NONE    0      /* Normal database column */
#define RECOVER_EHIDDEN_HIDDEN  1      /* Column is __HIDDEN__ */
#define RECOVER_EHIDDEN_VIRTUAL 2      /* Virtual generated column */
#define RECOVER_EHIDDEN_STORED  3      /* Stored generated column */

/*
** Bitmap object used to track pages in the input database. Allocated
** and manipulated only by the following functions:
**
**     recoverBitmapAlloc()
**     recoverBitmapFree()
**     recoverBitmapSet()
**     recoverBitmapQuery()
**
** nPg:
**   Largest page number that may be stored in the bitmap. The range
**   of valid keys is 1 to nPg, inclusive.
**
** aElem[]:
**   Array large enough to contain a bit for each key. For key value
**   iKey, the associated bit is the bit (iKey%32) of aElem[iKey/32].
**   In other words, the following is true if bit iKey is set, or 
**   false if it is clear:
**
**       (aElem[iKey/32] & (1 << (iKey%32))) ? 1 : 0
*/
typedef struct RecoverBitmap RecoverBitmap;
struct RecoverBitmap {
  i64 nPg;                        /* Size of bitmap */
  u32 aElem[1];                   /* Array of 32-bit bitmasks */
};

/*
** State variables (part of the sqlite3_recover structure) used while
** recovering data for tables identified in the recovered schema (state
** RECOVER_STATE_WRITING).
*/
typedef struct RecoverStateW1 RecoverStateW1;
struct RecoverStateW1 {
  sqlite3_stmt *pTbls;
  sqlite3_stmt *pSel;
  sqlite3_stmt *pInsert;
  int nInsert;

  RecoverTable *pTab;             /* Table currently being written */
  int nMax;                       /* Max column count in any schema table */
  sqlite3_value **apVal;          /* Array of nMax values */
  int nVal;                       /* Number of valid entries in apVal[] */
  int bHaveRowid;
  i64 iRowid;
  i64 iPrevPage;
  int iPrevCell;
};

/*
** State variables (part of the sqlite3_recover structure) used while
** recovering data destined for the lost and found table (states
** RECOVER_STATE_LOSTANDFOUND[123]).
*/
typedef struct RecoverStateLAF RecoverStateLAF;
struct RecoverStateLAF {
  RecoverBitmap *pUsed;
  i64 nPg;                        /* Size of db in pages */
  sqlite3_stmt *pAllAndParent;
  sqlite3_stmt *pMapInsert;
  sqlite3_stmt *pMaxField;
  sqlite3_stmt *pUsedPages;
  sqlite3_stmt *pFindRoot;
  sqlite3_stmt *pInsert;          /* INSERT INTO lost_and_found ... */
  sqlite3_stmt *pAllPage;
  sqlite3_stmt *pPageData;
  sqlite3_value **apVal;
  int nMaxField;
};

/*
** Main recover handle structure.
*/
struct sqlite3_recover {
  /* Copies of sqlite3_recover_init[_sql]() parameters */
  sqlite3 *dbIn;                  /* Input database */
  char *zDb;                      /* Name of input db ("main" etc.) */
  char *zUri;                     /* URI for output database */
  void *pSqlCtx;                  /* SQL callback context */
  int (*xSql)(void*,const char*); /* Pointer to SQL callback function */

  /* Values configured by sqlite3_recover_config() */
  char *zStateDb;                 /* State database to use (or NULL) */
  char *zLostAndFound;            /* Name of lost-and-found table (or NULL) */
  int bFreelistCorrupt;           /* SQLITE_RECOVER_FREELIST_CORRUPT setting */
  int bRecoverRowid;              /* SQLITE_RECOVER_ROWIDS setting */
  int bSlowIndexes;               /* SQLITE_RECOVER_SLOWINDEXES setting */

  int pgsz;
  int detected_pgsz;
  int nReserve;
  u8 *pPage1Disk;
  u8 *pPage1Cache;

  /* Error code and error message */
  int errCode;                    /* For sqlite3_recover_errcode() */
  char *zErrMsg;                  /* For sqlite3_recover_errmsg() */

  int eState;
  int bCloseTransaction;

  /* Variables used with eState==RECOVER_STATE_WRITING */
  RecoverStateW1 w1;

  /* Variables used with states RECOVER_STATE_LOSTANDFOUND[123] */
  RecoverStateLAF laf;

  /* Fields used within sqlite3_recover_run() */
  sqlite3 *dbOut;                 /* Output database */
  sqlite3_stmt *pGetPage;         /* SELECT against input db sqlite_dbdata */
  RecoverTable *pTblList;         /* List of tables recovered from schema */
};

/*
** The various states in which an sqlite3_recover object may exist:
**
**   RECOVER_STATE_INIT:
**    The object is initially created in this state. sqlite3_recover_step()
**    has yet to be called. This is the only state in which it is permitted
**    to call sqlite3_recover_config().
**
**   RECOVER_STATE_WRITING:
**
**   RECOVER_STATE_LOSTANDFOUND1:
**    State to populate the bitmap of pages used by other tables or the
**    database freelist.
**
**   RECOVER_STATE_LOSTANDFOUND2:
**    Populate the recovery.map table - used to figure out a "root" page
**    for each lost page from in the database from which records are
**    extracted.
**
**   RECOVER_STATE_LOSTANDFOUND3:
**    Populate the lost-and-found table itself.
*/
#define RECOVER_STATE_INIT           0
#define RECOVER_STATE_WRITING        1
#define RECOVER_STATE_LOSTANDFOUND1  2
#define RECOVER_STATE_LOSTANDFOUND2  3
#define RECOVER_STATE_LOSTANDFOUND3  4
#define RECOVER_STATE_SCHEMA2        5
#define RECOVER_STATE_DONE           6


/*
** Global variables used by this extension.
*/
typedef struct RecoverGlobal RecoverGlobal;
struct RecoverGlobal {
  const sqlite3_io_methods *pMethods;
  sqlite3_recover *p;
};
static RecoverGlobal recover_g;

/*
** Use this static SQLite mutex to protect the globals during the
** first call to sqlite3_recover_step().
*/ 
#define RECOVER_MUTEX_ID SQLITE_MUTEX_STATIC_APP2


/* 
** Default value for SQLITE_RECOVER_ROWIDS (sqlite3_recover.bRecoverRowid).
*/
#define RECOVER_ROWID_DEFAULT 1

/*
** Mutex handling:
**
**    recoverEnterMutex()       -   Enter the recovery mutex
**    recoverLeaveMutex()       -   Leave the recovery mutex
**    recoverAssertMutexHeld()  -   Assert that the recovery mutex is held
*/
#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE==0
# define recoverEnterMutex()
# define recoverLeaveMutex()
#else
static void recoverEnterMutex(void){
  sqlite3_mutex_enter(sqlite3_mutex_alloc(RECOVER_MUTEX_ID));
}
static void recoverLeaveMutex(void){
  sqlite3_mutex_leave(sqlite3_mutex_alloc(RECOVER_MUTEX_ID));
}
#endif
#if SQLITE_THREADSAFE+0>=1 && defined(SQLITE_DEBUG)
static void recoverAssertMutexHeld(void){
  assert( sqlite3_mutex_held(sqlite3_mutex_alloc(RECOVER_MUTEX_ID)) );
}
#else
# define recoverAssertMutexHeld()
#endif


/*
** Like strlen(). But handles NULL pointer arguments.
*/
static int recoverStrlen(const char *zStr){
  if( zStr==0 ) return 0;
  return (int)(strlen(zStr)&0x7fffffff);
}

/*
** This function is a no-op if the recover handle passed as the first 
** argument already contains an error (if p->errCode!=SQLITE_OK). 
**
** Otherwise, an attempt is made to allocate, zero and return a buffer nByte
** bytes in size. If successful, a pointer to the new buffer is returned. Or,
** if an OOM error occurs, NULL is returned and the handle error code
** (p->errCode) set to SQLITE_NOMEM.
*/
static void *recoverMalloc(sqlite3_recover *p, i64 nByte){
  void *pRet = 0;
  assert( nByte>0 );
  if( p->errCode==SQLITE_OK ){
    pRet = sqlite3_malloc64(nByte);
    if( pRet ){
      memset(pRet, 0, nByte);
    }else{
      p->errCode = SQLITE_NOMEM;
    }
  }
  return pRet;
}

/*
** Set the error code and error message for the recover handle passed as
** the first argument. The error code is set to the value of parameter
** errCode.
**
** Parameter zFmt must be a printf() style formatting string. The handle 
** error message is set to the result of using any trailing arguments for 
** parameter substitutions in the formatting string.
**
** For example:
**
**   recoverError(p, SQLITE_ERROR, "no such table: %s", zTablename);
*/
static int recoverError(
  sqlite3_recover *p, 
  int errCode, 
  const char *zFmt, ...
){
  char *z = 0;
  va_list ap;
  va_start(ap, zFmt);
  if( zFmt ){
    z = sqlite3_vmprintf(zFmt, ap);
    va_end(ap);
  }
  sqlite3_free(p->zErrMsg);
  p->zErrMsg = z;
  p->errCode = errCode;
  return errCode;
}


/*
** This function is a no-op if p->errCode is initially other than SQLITE_OK.
** In this case it returns NULL.
**
** Otherwise, an attempt is made to allocate and return a bitmap object
** large enough to store a bit for all page numbers between 1 and nPg,
** inclusive. The bitmap is initially zeroed.
*/
static RecoverBitmap *recoverBitmapAlloc(sqlite3_recover *p, i64 nPg){
  int nElem = (nPg+1+31) / 32;
  int nByte = sizeof(RecoverBitmap) + nElem*sizeof(u32);
  RecoverBitmap *pRet = (RecoverBitmap*)recoverMalloc(p, nByte);

  if( pRet ){
    pRet->nPg = nPg;
  }
  return pRet;
}

/*
** Free a bitmap object allocated by recoverBitmapAlloc().
*/
static void recoverBitmapFree(RecoverBitmap *pMap){
  sqlite3_free(pMap);
}

/*
** Set the bit associated with page iPg in bitvec pMap.
*/
static void recoverBitmapSet(RecoverBitmap *pMap, i64 iPg){
  if( iPg<=pMap->nPg ){
    int iElem = (iPg / 32);
    int iBit = (iPg % 32);
    pMap->aElem[iElem] |= (((u32)1) << iBit);
  }
}

/*
** Query bitmap object pMap for the state of the bit associated with page
** iPg. Return 1 if it is set, or 0 otherwise.
*/
static int recoverBitmapQuery(RecoverBitmap *pMap, i64 iPg){
  int ret = 1;
  if( iPg<=pMap->nPg && iPg>0 ){
    int iElem = (iPg / 32);
    int iBit = (iPg % 32);
    ret = (pMap->aElem[iElem] & (((u32)1) << iBit)) ? 1 : 0;
  }
  return ret;
}

/*
** Set the recover handle error to the error code and message returned by
** calling sqlite3_errcode() and sqlite3_errmsg(), respectively, on database
** handle db.
*/
static int recoverDbError(sqlite3_recover *p, sqlite3 *db){
  return recoverError(p, sqlite3_errcode(db), "%s", sqlite3_errmsg(db));
}

/*
** This function is a no-op if recover handle p already contains an error
** (if p->errCode!=SQLITE_OK). 
**
** Otherwise, it attempts to prepare the SQL statement in zSql against
** database handle db. If successful, the statement handle is returned.
** Or, if an error occurs, NULL is returned and an error left in the
** recover handle.
*/
static sqlite3_stmt *recoverPrepare(
  sqlite3_recover *p,
  sqlite3 *db, 
  const char *zSql
){
  sqlite3_stmt *pStmt = 0;
  if( p->errCode==SQLITE_OK ){
    if( sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0) ){
      recoverDbError(p, db);
    }
  }
  return pStmt;
}

/*
** This function is a no-op if recover handle p already contains an error
** (if p->errCode!=SQLITE_OK). 
**
** Otherwise, argument zFmt is used as a printf() style format string,
** along with any trailing arguments, to create an SQL statement. This
** SQL statement is prepared against database handle db and, if successful,
** the statment handle returned. Or, if an error occurs - either during
** the printf() formatting or when preparing the resulting SQL - an
** error code and message are left in the recover handle.
*/
static sqlite3_stmt *recoverPreparePrintf(
  sqlite3_recover *p,
  sqlite3 *db, 
  const char *zFmt, ...
){
  sqlite3_stmt *pStmt = 0;
  if( p->errCode==SQLITE_OK ){
    va_list ap;
    char *z;
    va_start(ap, zFmt);
    z = sqlite3_vmprintf(zFmt, ap);
    va_end(ap);
    if( z==0 ){
      p->errCode = SQLITE_NOMEM;
    }else{
      pStmt = recoverPrepare(p, db, z);
      sqlite3_free(z);
    }
  }
  return pStmt;
}

/*
** Reset SQLite statement handle pStmt. If the call to sqlite3_reset() 
** indicates that an error occurred, and there is not already an error
** in the recover handle passed as the first argument, set the error
** code and error message appropriately.
**
** This function returns a copy of the statement handle pointer passed
** as the second argument.
*/
static sqlite3_stmt *recoverReset(sqlite3_recover *p, sqlite3_stmt *pStmt){
  int rc = sqlite3_reset(pStmt);
  if( rc!=SQLITE_OK && rc!=SQLITE_CONSTRAINT && p->errCode==SQLITE_OK ){
    recoverDbError(p, sqlite3_db_handle(pStmt));
  }
  return pStmt;
}

/*
** Finalize SQLite statement handle pStmt. If the call to sqlite3_reset() 
** indicates that an error occurred, and there is not already an error
** in the recover handle passed as the first argument, set the error
** code and error message appropriately.
*/
static void recoverFinalize(sqlite3_recover *p, sqlite3_stmt *pStmt){
  sqlite3 *db = sqlite3_db_handle(pStmt);
  int rc = sqlite3_finalize(pStmt);
  if( rc!=SQLITE_OK && p->errCode==SQLITE_OK ){
    recoverDbError(p, db);
  }
}

/*
** This function is a no-op if recover handle p already contains an error
** (if p->errCode!=SQLITE_OK). A copy of p->errCode is returned in this 
** case.
**
** Otherwise, execute SQL script zSql. If successful, return SQLITE_OK.
** Or, if an error occurs, leave an error code and message in the recover
** handle and return a copy of the error code.
*/
static int recoverExec(sqlite3_recover *p, sqlite3 *db, const char *zSql){
  if( p->errCode==SQLITE_OK ){
    int rc = sqlite3_exec(db, zSql, 0, 0, 0);
    if( rc ){
      recoverDbError(p, db);
    }
  }
  return p->errCode;
}

/*
** Bind the value pVal to parameter iBind of statement pStmt. Leave an
** error in the recover handle passed as the first argument if an error
** (e.g. an OOM) occurs.
*/
static void recoverBindValue(
  sqlite3_recover *p, 
  sqlite3_stmt *pStmt, 
  int iBind, 
  sqlite3_value *pVal
){
  if( p->errCode==SQLITE_OK ){
    int rc = sqlite3_bind_value(pStmt, iBind, pVal);
    if( rc ) recoverError(p, rc, 0);
  }
}

/*
** This function is a no-op if recover handle p already contains an error
** (if p->errCode!=SQLITE_OK). NULL is returned in this case.
**
** Otherwise, an attempt is made to interpret zFmt as a printf() style
** formatting string and the result of using the trailing arguments for
** parameter substitution with it written into a buffer obtained from
** sqlite3_malloc(). If successful, a pointer to the buffer is returned.
** It is the responsibility of the caller to eventually free the buffer
** using sqlite3_free().
**
** Or, if an error occurs, an error code and message is left in the recover
** handle and NULL returned.
*/
static char *recoverMPrintf(sqlite3_recover *p, const char *zFmt, ...){
  va_list ap;
  char *z;
  va_start(ap, zFmt);
  z = sqlite3_vmprintf(zFmt, ap);
  va_end(ap);
  if( p->errCode==SQLITE_OK ){
    if( z==0 ) p->errCode = SQLITE_NOMEM;
  }else{
    sqlite3_free(z);
    z = 0;
  }
  return z;
}

/*
** This function is a no-op if recover handle p already contains an error
** (if p->errCode!=SQLITE_OK). Zero is returned in this case.
**
** Otherwise, execute "PRAGMA page_count" against the input database. If
** successful, return the integer result. Or, if an error occurs, leave an
** error code and error message in the sqlite3_recover handle and return
** zero.
*/
static i64 recoverPageCount(sqlite3_recover *p){
  i64 nPg = 0;
  if( p->errCode==SQLITE_OK ){
    sqlite3_stmt *pStmt = 0;
    pStmt = recoverPreparePrintf(p, p->dbIn, "PRAGMA %Q.page_count", p->zDb);
    if( pStmt ){
      sqlite3_step(pStmt);
      nPg = sqlite3_column_int64(pStmt, 0);
    }
    recoverFinalize(p, pStmt);
  }
  return nPg;
}

/*
** Implementation of SQL scalar function "read_i32". The first argument to 
** this function must be a blob. The second a non-negative integer. This 
** function reads and returns a 32-bit big-endian integer from byte
** offset (4*<arg2>) of the blob.
**
**     SELECT read_i32(<blob>, <idx>)
*/
static void recoverReadI32(
  sqlite3_context *context, 
  int argc, 
  sqlite3_value **argv
){
  const unsigned char *pBlob;
  int nBlob;
  int iInt;

  assert( argc==2 );
  nBlob = sqlite3_value_bytes(argv[0]);
  pBlob = (const unsigned char*)sqlite3_value_blob(argv[0]);
  iInt = sqlite3_value_int(argv[1]) & 0xFFFF;

  if( (iInt+1)*4<=nBlob ){
    const unsigned char *a = &pBlob[iInt*4];
    i64 iVal = ((i64)a[0]<<24)
             + ((i64)a[1]<<16)
             + ((i64)a[2]<< 8)
             + ((i64)a[3]<< 0);
    sqlite3_result_int64(context, iVal);
  }
}

/*
** Implementation of SQL scalar function "page_is_used". This function
** is used as part of the procedure for locating orphan rows for the
** lost-and-found table, and it depends on those routines having populated
** the sqlite3_recover.laf.pUsed variable.
**
** The only argument to this function is a page-number. It returns true 
** if the page has already been used somehow during data recovery, or false
** otherwise.
**
**     SELECT page_is_used(<pgno>);
*/
static void recoverPageIsUsed(
  sqlite3_context *pCtx,
  int nArg,
  sqlite3_value **apArg
){
  sqlite3_recover *p = (sqlite3_recover*)sqlite3_user_data(pCtx);
  i64 pgno = sqlite3_value_int64(apArg[0]);
  assert( nArg==1 );
  sqlite3_result_int(pCtx, recoverBitmapQuery(p->laf.pUsed, pgno));
}

/*
** The implementation of a user-defined SQL function invoked by the 
** sqlite_dbdata and sqlite_dbptr virtual table modules to access pages
** of the database being recovered.
**
** This function always takes a single integer argument. If the argument
** is zero, then the value returned is the number of pages in the db being
** recovered. If the argument is greater than zero, it is a page number. 
** The value returned in this case is an SQL blob containing the data for 
** the identified page of the db being recovered. e.g.
**
**     SELECT getpage(0);       -- return number of pages in db
**     SELECT getpage(4);       -- return page 4 of db as a blob of data 
*/
static void recoverGetPage(
  sqlite3_context *pCtx,
  int nArg,
  sqlite3_value **apArg
){
  sqlite3_recover *p = (sqlite3_recover*)sqlite3_user_data(pCtx);
  i64 pgno = sqlite3_value_int64(apArg[0]);
  sqlite3_stmt *pStmt = 0;

  assert( nArg==1 );
  if( pgno==0 ){
    i64 nPg = recoverPageCount(p);
    sqlite3_result_int64(pCtx, nPg);
    return;
  }else{
    if( p->pGetPage==0 ){
      pStmt = p->pGetPage = recoverPreparePrintf(
          p, p->dbIn, "SELECT data FROM sqlite_dbpage(%Q) WHERE pgno=?", p->zDb
      );
    }else if( p->errCode==SQLITE_OK ){
      pStmt = p->pGetPage;
    }

    if( pStmt ){
      sqlite3_bind_int64(pStmt, 1, pgno);
      if( SQLITE_ROW==sqlite3_step(pStmt) ){
        const u8 *aPg;
        int nPg;
        assert( p->errCode==SQLITE_OK );
        aPg = sqlite3_column_blob(pStmt, 0);
        nPg = sqlite3_column_bytes(pStmt, 0);
        if( pgno==1 && nPg==p->pgsz && 0==memcmp(p->pPage1Cache, aPg, nPg) ){
          aPg = p->pPage1Disk;
        }
        sqlite3_result_blob(pCtx, aPg, nPg-p->nReserve, SQLITE_TRANSIENT);
      }
      recoverReset(p, pStmt);
    }
  }

  if( p->errCode ){
    if( p->zErrMsg ) sqlite3_result_error(pCtx, p->zErrMsg, -1);
    sqlite3_result_error_code(pCtx, p->errCode);
  }
}

/*
** Find a string that is not found anywhere in z[].  Return a pointer
** to that string.
**
** Try to use zA and zB first.  If both of those are already found in z[]
** then make up some string and store it in the buffer zBuf.
*/
static const char *recoverUnusedString(
  const char *z,                    /* Result must not appear anywhere in z */
  const char *zA, const char *zB,   /* Try these first */
  char *zBuf                        /* Space to store a generated string */
){
  unsigned i = 0;
  if( strstr(z, zA)==0 ) return zA;
  if( strstr(z, zB)==0 ) return zB;
  do{
    sqlite3_snprintf(20,zBuf,"(%s%u)", zA, i++);
  }while( strstr(z,zBuf)!=0 );
  return zBuf;
}

/*
** Implementation of scalar SQL function "escape_crnl".  The argument passed to
** this function is the output of built-in function quote(). If the first
** character of the input is "'", indicating that the value passed to quote()
** was a text value, then this function searches the input for "\n" and "\r"
** characters and adds a wrapper similar to the following:
**
**   replace(replace(<input>, '\n', char(10), '\r', char(13));
**
** Or, if the first character of the input is not "'", then a copy of the input
** is returned.
*/
static void recoverEscapeCrnl(
  sqlite3_context *context, 
  int argc, 
  sqlite3_value **argv
){
  const char *zText = (const char*)sqlite3_value_text(argv[0]);
  (void)argc;
  if( zText && zText[0]=='\'' ){
    int nText = sqlite3_value_bytes(argv[0]);
    int i;
    char zBuf1[20];
    char zBuf2[20];
    const char *zNL = 0;
    const char *zCR = 0;
    int nCR = 0;
    int nNL = 0;

    for(i=0; zText[i]; i++){
      if( zNL==0 && zText[i]=='\n' ){
        zNL = recoverUnusedString(zText, "\\n", "\\012", zBuf1);
        nNL = (int)strlen(zNL);
      }
      if( zCR==0 && zText[i]=='\r' ){
        zCR = recoverUnusedString(zText, "\\r", "\\015", zBuf2);
        nCR = (int)strlen(zCR);
      }
    }

    if( zNL || zCR ){
      int iOut = 0;
      i64 nMax = (nNL > nCR) ? nNL : nCR;
      i64 nAlloc = nMax * nText + (nMax+64)*2;
      char *zOut = (char*)sqlite3_malloc64(nAlloc);
      if( zOut==0 ){
        sqlite3_result_error_nomem(context);
        return;
      }

      if( zNL && zCR ){
        memcpy(&zOut[iOut], "replace(replace(", 16);
        iOut += 16;
      }else{
        memcpy(&zOut[iOut], "replace(", 8);
        iOut += 8;
      }
      for(i=0; zText[i]; i++){
        if( zText[i]=='\n' ){
          memcpy(&zOut[iOut], zNL, nNL);
          iOut += nNL;
        }else if( zText[i]=='\r' ){
          memcpy(&zOut[iOut], zCR, nCR);
          iOut += nCR;
        }else{
          zOut[iOut] = zText[i];
          iOut++;
        }
      }

      if( zNL ){
        memcpy(&zOut[iOut], ",'", 2); iOut += 2;
        memcpy(&zOut[iOut], zNL, nNL); iOut += nNL;
        memcpy(&zOut[iOut], "', char(10))", 12); iOut += 12;
      }
      if( zCR ){
        memcpy(&zOut[iOut], ",'", 2); iOut += 2;
        memcpy(&zOut[iOut], zCR, nCR); iOut += nCR;
        memcpy(&zOut[iOut], "', char(13))", 12); iOut += 12;
      }

      sqlite3_result_text(context, zOut, iOut, SQLITE_TRANSIENT);
      sqlite3_free(zOut);
      return;
    }
  }

  sqlite3_result_value(context, argv[0]);
}

/*
** This function is a no-op if recover handle p already contains an error
** (if p->errCode!=SQLITE_OK). A copy of the error code is returned in
** this case. 
**
** Otherwise, attempt to populate temporary table "recovery.schema" with the
** parts of the database schema that can be extracted from the input database.
**
** If no error occurs, SQLITE_OK is returned. Otherwise, an error code
** and error message are left in the recover handle and a copy of the
** error code returned. It is not considered an error if part of all of
** the database schema cannot be recovered due to corruption.
*/
static int recoverCacheSchema(sqlite3_recover *p){
  return recoverExec(p, p->dbOut,
    "WITH RECURSIVE pages(p) AS ("
    "  SELECT 1"
    "    UNION"
    "  SELECT child FROM sqlite_dbptr('getpage()'), pages WHERE pgno=p"
    ")"
    "INSERT INTO recovery.schema SELECT"
    "  max(CASE WHEN field=0 THEN value ELSE NULL END),"
    "  max(CASE WHEN field=1 THEN value ELSE NULL END),"
    "  max(CASE WHEN field=2 THEN value ELSE NULL END),"
    "  max(CASE WHEN field=3 THEN value ELSE NULL END),"
    "  max(CASE WHEN field=4 THEN value ELSE NULL END)"
    "FROM sqlite_dbdata('getpage()') WHERE pgno IN ("
    "  SELECT p FROM pages"
    ") GROUP BY pgno, cell"
  );
}

/*
** If this recover handle is not in SQL callback mode (i.e. was not created 
** using sqlite3_recover_init_sql()) of if an error has already occurred, 
** this function is a no-op. Otherwise, issue a callback with SQL statement
** zSql as the parameter. 
**
** If the callback returns non-zero, set the recover handle error code to
** the value returned (so that the caller will abandon processing).
*/
static void recoverSqlCallback(sqlite3_recover *p, const char *zSql){
  if( p->errCode==SQLITE_OK && p->xSql ){
    int res = p->xSql(p->pSqlCtx, zSql);
    if( res ){
      recoverError(p, SQLITE_ERROR, "callback returned an error - %d", res);
    }
  }
}

/*
** Transfer the following settings from the input database to the output
** database:
**
**   + page-size,
**   + auto-vacuum settings,
**   + database encoding,
**   + user-version (PRAGMA user_version), and
**   + application-id (PRAGMA application_id), and
*/
static void recoverTransferSettings(sqlite3_recover *p){
  const char *aPragma[] = {
    "encoding",
    "page_size",
    "auto_vacuum",
    "user_version",
    "application_id"
  };
  int ii;

  /* Truncate the output database to 0 pages in size. This is done by 
  ** opening a new, empty, temp db, then using the backup API to clobber 
  ** any existing output db with a copy of it. */
  if( p->errCode==SQLITE_OK ){
    sqlite3 *db2 = 0;
    int rc = sqlite3_open("", &db2);
    if( rc!=SQLITE_OK ){
      recoverDbError(p, db2);
      return;
    }

    for(ii=0; ii<(int)(sizeof(aPragma)/sizeof(aPragma[0])); ii++){
      const char *zPrag = aPragma[ii];
      sqlite3_stmt *p1 = 0;
      p1 = recoverPreparePrintf(p, p->dbIn, "PRAGMA %Q.%s", p->zDb, zPrag);
      if( p->errCode==SQLITE_OK && sqlite3_step(p1)==SQLITE_ROW ){
        const char *zArg = (const char*)sqlite3_column_text(p1, 0);
        char *z2 = recoverMPrintf(p, "PRAGMA %s = %Q", zPrag, zArg);
        recoverSqlCallback(p, z2);
        recoverExec(p, db2, z2);
        sqlite3_free(z2);
        if( zArg==0 ){
          recoverError(p, SQLITE_NOMEM, 0);
        }
      }
      recoverFinalize(p, p1);
    }
    recoverExec(p, db2, "CREATE TABLE t1(a); DROP TABLE t1;");

    if( p->errCode==SQLITE_OK ){
      sqlite3 *db = p->dbOut;
      sqlite3_backup *pBackup = sqlite3_backup_init(db, "main", db2, "main");
      if( pBackup ){
        sqlite3_backup_step(pBackup, -1);
        p->errCode = sqlite3_backup_finish(pBackup);
      }else{
        recoverDbError(p, db);
      }
    }

    sqlite3_close(db2);
  }
}

/*
** This function is a no-op if recover handle p already contains an error
** (if p->errCode!=SQLITE_OK). A copy of the error code is returned in
** this case. 
**
** Otherwise, an attempt is made to open the output database, attach
** and create the schema of the temporary database used to store
** intermediate data, and to register all required user functions and
** virtual table modules with the output handle.
**
** If no error occurs, SQLITE_OK is returned. Otherwise, an error code
** and error message are left in the recover handle and a copy of the
** error code returned.
*/
static int recoverOpenOutput(sqlite3_recover *p){
  struct Func {
    const char *zName;
    int nArg;
    void (*xFunc)(sqlite3_context*,int,sqlite3_value **);
  } aFunc[] = {
    { "getpage", 1, recoverGetPage },
    { "page_is_used", 1, recoverPageIsUsed },
    { "read_i32", 2, recoverReadI32 },
    { "escape_crnl", 1, recoverEscapeCrnl },
  };

  const int flags = SQLITE_OPEN_URI|SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE;
  sqlite3 *db = 0;                /* New database handle */
  int ii;                         /* For iterating through aFunc[] */

  assert( p->dbOut==0 );

  if( sqlite3_open_v2(p->zUri, &db, flags, 0) ){
    recoverDbError(p, db);
  }

  /* Register the sqlite_dbdata and sqlite_dbptr virtual table modules.
  ** These two are registered with the output database handle - this
  ** module depends on the input handle supporting the sqlite_dbpage
  ** virtual table only.  */
  if( p->errCode==SQLITE_OK ){
    p->errCode = sqlite3_dbdata_init(db, 0, 0);
  }

  /* Register the custom user-functions with the output handle. */
  for(ii=0;
      p->errCode==SQLITE_OK && ii<(int)(sizeof(aFunc)/sizeof(aFunc[0]));
      ii++){
    p->errCode = sqlite3_create_function(db, aFunc[ii].zName, 
        aFunc[ii].nArg, SQLITE_UTF8, (void*)p, aFunc[ii].xFunc, 0, 0
    );
  }

  p->dbOut = db;
  return p->errCode;
}

/*
** Attach the auxiliary database 'recovery' to the output database handle.
** This temporary database is used during the recovery process and then 
** discarded.
*/
static void recoverOpenRecovery(sqlite3_recover *p){
  char *zSql = recoverMPrintf(p, "ATTACH %Q AS recovery;", p->zStateDb);
  recoverExec(p, p->dbOut, zSql);
  recoverExec(p, p->dbOut,
      "PRAGMA writable_schema = 1;"
      "CREATE TABLE recovery.map(pgno INTEGER PRIMARY KEY, parent INT);" 
      "CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql);"
  );
  sqlite3_free(zSql);
}


/*
** This function is a no-op if recover handle p already contains an error
** (if p->errCode!=SQLITE_OK).
**
** Otherwise, argument zName must be the name of a table that has just been
** created in the output database. This function queries the output db
** for the schema of said table, and creates a RecoverTable object to
** store the schema in memory. The new RecoverTable object is linked into
** the list at sqlite3_recover.pTblList.
**
** Parameter iRoot must be the root page of table zName in the INPUT 
** database.
*/
static void recoverAddTable(
  sqlite3_recover *p, 
  const char *zName,              /* Name of table created in output db */
  i64 iRoot                       /* Root page of same table in INPUT db */
){
  sqlite3_stmt *pStmt = recoverPreparePrintf(p, p->dbOut, 
      "PRAGMA table_xinfo(%Q)", zName
  );

  if( pStmt ){
    int iPk = -1;
    int iBind = 1;
    RecoverTable *pNew = 0;
    int nCol = 0;
    int nName = recoverStrlen(zName);
    int nByte = 0;
    while( sqlite3_step(pStmt)==SQLITE_ROW ){
      nCol++;
      nByte += (sqlite3_column_bytes(pStmt, 1)+1);
    }
    nByte += sizeof(RecoverTable) + nCol*sizeof(RecoverColumn) + nName+1;
    recoverReset(p, pStmt);

    pNew = recoverMalloc(p, nByte);
    if( pNew ){
      int i = 0;
      int iField = 0;
      char *csr = 0;
      pNew->aCol = (RecoverColumn*)&pNew[1];
      pNew->zTab = csr = (char*)&pNew->aCol[nCol];
      pNew->nCol = nCol;
      pNew->iRoot = iRoot;
      memcpy(csr, zName, nName);
      csr += nName+1;

      for(i=0; sqlite3_step(pStmt)==SQLITE_ROW; i++){
        int iPKF = sqlite3_column_int(pStmt, 5);
        int n = sqlite3_column_bytes(pStmt, 1);
        const char *z = (const char*)sqlite3_column_text(pStmt, 1);
        const char *zType = (const char*)sqlite3_column_text(pStmt, 2);
        int eHidden = sqlite3_column_int(pStmt, 6);

        if( iPk==-1 && iPKF==1 && !sqlite3_stricmp("integer", zType) ) iPk = i;
        if( iPKF>1 ) iPk = -2;
        pNew->aCol[i].zCol = csr;
        pNew->aCol[i].eHidden = eHidden;
        if( eHidden==RECOVER_EHIDDEN_VIRTUAL ){
          pNew->aCol[i].iField = -1;
        }else{
          pNew->aCol[i].iField = iField++;
        }
        if( eHidden!=RECOVER_EHIDDEN_VIRTUAL
         && eHidden!=RECOVER_EHIDDEN_STORED
        ){
          pNew->aCol[i].iBind = iBind++;
        }
        memcpy(csr, z, n);
        csr += (n+1);
      }

      pNew->pNext = p->pTblList;
      p->pTblList = pNew;
      pNew->bIntkey = 1;
    }

    recoverFinalize(p, pStmt);

    pStmt = recoverPreparePrintf(p, p->dbOut, "PRAGMA index_xinfo(%Q)", zName);
    while( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
      int iField = sqlite3_column_int(pStmt, 0);
      int iCol = sqlite3_column_int(pStmt, 1);

      assert( iField<pNew->nCol && iCol<pNew->nCol );
      pNew->aCol[iCol].iField = iField;

      pNew->bIntkey = 0;
      iPk = -2;
    }
    recoverFinalize(p, pStmt);

    if( p->errCode==SQLITE_OK ){
      if( iPk>=0 ){
        pNew->aCol[iPk].bIPK = 1;
      }else if( pNew->bIntkey ){
        pNew->iRowidBind = iBind++;
      }
    }
  }
}

/*
** This function is called after recoverCacheSchema() has cached those parts
** of the input database schema that could be recovered in temporary table
** "recovery.schema". This function creates in the output database copies
** of all parts of that schema that must be created before the tables can
** be populated. Specifically, this means:
**
**     * all tables that are not VIRTUAL, and
**     * UNIQUE indexes.
**
** If the recovery handle uses SQL callbacks, then callbacks containing
** the associated "CREATE TABLE" and "CREATE INDEX" statements are made.
**
** Additionally, records are added to the sqlite_schema table of the
** output database for any VIRTUAL tables. The CREATE VIRTUAL TABLE
** records are written directly to sqlite_schema, not actually executed.
** If the handle is in SQL callback mode, then callbacks are invoked 
** with equivalent SQL statements.
*/
static int recoverWriteSchema1(sqlite3_recover *p){
  sqlite3_stmt *pSelect = 0;
  sqlite3_stmt *pTblname = 0;

  pSelect = recoverPrepare(p, p->dbOut,
      "WITH dbschema(rootpage, name, sql, tbl, isVirtual, isIndex) AS ("
      "  SELECT rootpage, name, sql, "
      "    type='table', "
      "    sql LIKE 'create virtual%',"
      "    (type='index' AND (sql LIKE '%unique%' OR ?1))"
      "  FROM recovery.schema"
      ")"
      "SELECT rootpage, tbl, isVirtual, name, sql"
      " FROM dbschema "
      "  WHERE tbl OR isIndex"
      "  ORDER BY tbl DESC, name=='sqlite_sequence' DESC"
  );

  pTblname = recoverPrepare(p, p->dbOut,
      "SELECT name FROM sqlite_schema "
      "WHERE type='table' ORDER BY rowid DESC LIMIT 1"
  );

  if( pSelect ){
    sqlite3_bind_int(pSelect, 1, p->bSlowIndexes);
    while( sqlite3_step(pSelect)==SQLITE_ROW ){
      i64 iRoot = sqlite3_column_int64(pSelect, 0);
      int bTable = sqlite3_column_int(pSelect, 1);
      int bVirtual = sqlite3_column_int(pSelect, 2);
      const char *zName = (const char*)sqlite3_column_text(pSelect, 3);
      const char *zSql = (const char*)sqlite3_column_text(pSelect, 4);
      char *zFree = 0;
      int rc = SQLITE_OK;

      if( bVirtual ){
        zSql = (const char*)(zFree = recoverMPrintf(p,
            "INSERT INTO sqlite_schema VALUES('table', %Q, %Q, 0, %Q)",
            zName, zName, zSql
        ));
      }
      rc = sqlite3_exec(p->dbOut, zSql, 0, 0, 0);
      if( rc==SQLITE_OK ){
        recoverSqlCallback(p, zSql);
        if( bTable && !bVirtual ){
          if( SQLITE_ROW==sqlite3_step(pTblname) ){
            const char *zTbl = (const char*)sqlite3_column_text(pTblname, 0);
            recoverAddTable(p, zTbl, iRoot);
          }
          recoverReset(p, pTblname);
        }
      }else if( rc!=SQLITE_ERROR ){
        recoverDbError(p, p->dbOut);
      }
      sqlite3_free(zFree);
    }
  }
  recoverFinalize(p, pSelect);
  recoverFinalize(p, pTblname);

  return p->errCode;
}

/*
** This function is called after the output database has been populated. It
** adds all recovered schema elements that were not created in the output
** database by recoverWriteSchema1() - everything except for tables and
** UNIQUE indexes. Specifically:
**
**     * views,
**     * triggers,
**     * non-UNIQUE indexes.
**
** If the recover handle is in SQL callback mode, then equivalent callbacks
** are issued to create the schema elements.
*/
static int recoverWriteSchema2(sqlite3_recover *p){
  sqlite3_stmt *pSelect = 0;

  pSelect = recoverPrepare(p, p->dbOut,
      p->bSlowIndexes ?
      "SELECT rootpage, sql FROM recovery.schema "
      "  WHERE type!='table' AND type!='index'"
      :
      "SELECT rootpage, sql FROM recovery.schema "
      "  WHERE type!='table' AND (type!='index' OR sql NOT LIKE '%unique%')"
  );

  if( pSelect ){
    while( sqlite3_step(pSelect)==SQLITE_ROW ){
      const char *zSql = (const char*)sqlite3_column_text(pSelect, 1);
      int rc = sqlite3_exec(p->dbOut, zSql, 0, 0, 0);
      if( rc==SQLITE_OK ){
        recoverSqlCallback(p, zSql);
      }else if( rc!=SQLITE_ERROR ){
        recoverDbError(p, p->dbOut);
      }
    }
  }
  recoverFinalize(p, pSelect);

  return p->errCode;
}

/*
** This function is a no-op if recover handle p already contains an error
** (if p->errCode!=SQLITE_OK). In this case it returns NULL.
**
** Otherwise, if the recover handle is configured to create an output
** database (was created by sqlite3_recover_init()), then this function
** prepares and returns an SQL statement to INSERT a new record into table
** pTab, assuming the first nField fields of a record extracted from disk
** are valid.
**
** For example, if table pTab is:
**
**     CREATE TABLE name(a, b GENERATED ALWAYS AS (a+1) STORED, c, d, e);
**
** And nField is 4, then the SQL statement prepared and returned is:
**
**     INSERT INTO (a, c, d) VALUES (?1, ?2, ?3);
**
** In this case even though 4 values were extracted from the input db,
** only 3 are written to the output, as the generated STORED column 
** cannot be written.
**
** If the recover handle is in SQL callback mode, then the SQL statement
** prepared is such that evaluating it returns a single row containing
** a single text value - itself an SQL statement similar to the above,
** except with SQL literals in place of the variables. For example:
**
**     SELECT 'INSERT INTO (a, c, d) VALUES (' 
**          || quote(?1) || ', '
**          || quote(?2) || ', '
**          || quote(?3) || ')';
**
** In either case, it is the responsibility of the caller to eventually
** free the statement handle using sqlite3_finalize().
*/
static sqlite3_stmt *recoverInsertStmt(
  sqlite3_recover *p, 
  RecoverTable *pTab,
  int nField
){
  sqlite3_stmt *pRet = 0;
  const char *zSep = "";
  const char *zSqlSep = "";
  char *zSql = 0;
  char *zFinal = 0;
  char *zBind = 0;
  int ii;
  int bSql = p->xSql ? 1 : 0;

  if( nField<=0 ) return 0;

  assert( nField<=pTab->nCol );

  zSql = recoverMPrintf(p, "INSERT OR IGNORE INTO %Q(", pTab->zTab);

  if( pTab->iRowidBind ){
    assert( pTab->bIntkey );
    zSql = recoverMPrintf(p, "%z_rowid_", zSql);
    if( bSql ){
      zBind = recoverMPrintf(p, "%zquote(?%d)", zBind, pTab->iRowidBind);
    }else{
      zBind = recoverMPrintf(p, "%z?%d", zBind, pTab->iRowidBind);
    }
    zSqlSep = "||', '||";
    zSep = ", ";
  }

  for(ii=0; ii<nField; ii++){
    int eHidden = pTab->aCol[ii].eHidden;
    if( eHidden!=RECOVER_EHIDDEN_VIRTUAL
     && eHidden!=RECOVER_EHIDDEN_STORED
    ){
      assert( pTab->aCol[ii].iField>=0 && pTab->aCol[ii].iBind>=1 );
      zSql = recoverMPrintf(p, "%z%s%Q", zSql, zSep, pTab->aCol[ii].zCol);

      if( bSql ){
        zBind = recoverMPrintf(p, 
            "%z%sescape_crnl(quote(?%d))", zBind, zSqlSep, pTab->aCol[ii].iBind
        );
        zSqlSep = "||', '||";
      }else{
        zBind = recoverMPrintf(p, "%z%s?%d", zBind, zSep, pTab->aCol[ii].iBind);
      }
      zSep = ", ";
    }
  }

  if( bSql ){
    zFinal = recoverMPrintf(p, "SELECT %Q || ') VALUES (' || %s || ')'", 
        zSql, zBind
    );
  }else{
    zFinal = recoverMPrintf(p, "%s) VALUES (%s)", zSql, zBind);
  }

  pRet = recoverPrepare(p, p->dbOut, zFinal);
  sqlite3_free(zSql);
  sqlite3_free(zBind);
  sqlite3_free(zFinal);
  
  return pRet;
}


/*
** Search the list of RecoverTable objects at p->pTblList for one that
** has root page iRoot in the input database. If such an object is found,
** return a pointer to it. Otherwise, return NULL.
*/
static RecoverTable *recoverFindTable(sqlite3_recover *p, u32 iRoot){
  RecoverTable *pRet = 0;
  for(pRet=p->pTblList; pRet && pRet->iRoot!=iRoot; pRet=pRet->pNext);
  return pRet;
}

/*
** This function attempts to create a lost and found table within the 
** output db. If successful, it returns a pointer to a buffer containing
** the name of the new table. It is the responsibility of the caller to
** eventually free this buffer using sqlite3_free().
**
** If an error occurs, NULL is returned and an error code and error 
** message left in the recover handle.
*/
static char *recoverLostAndFoundCreate(
  sqlite3_recover *p,             /* Recover object */
  int nField                      /* Number of column fields in new table */
){
  char *zTbl = 0;
  sqlite3_stmt *pProbe = 0;
  int ii = 0;

  pProbe = recoverPrepare(p, p->dbOut,
    "SELECT 1 FROM sqlite_schema WHERE name=?"
  );
  for(ii=-1; zTbl==0 && p->errCode==SQLITE_OK && ii<1000; ii++){
    int bFail = 0;
    if( ii<0 ){
      zTbl = recoverMPrintf(p, "%s", p->zLostAndFound);
    }else{
      zTbl = recoverMPrintf(p, "%s_%d", p->zLostAndFound, ii);
    }

    if( p->errCode==SQLITE_OK ){
      sqlite3_bind_text(pProbe, 1, zTbl, -1, SQLITE_STATIC);
      if( SQLITE_ROW==sqlite3_step(pProbe) ){
        bFail = 1;
      }
      recoverReset(p, pProbe);
    }

    if( bFail ){
      sqlite3_clear_bindings(pProbe);
      sqlite3_free(zTbl);
      zTbl = 0;
    }
  }
  recoverFinalize(p, pProbe);

  if( zTbl ){
    const char *zSep = 0;
    char *zField = 0;
    char *zSql = 0;

    zSep = "rootpgno INTEGER, pgno INTEGER, nfield INTEGER, id INTEGER, ";
    for(ii=0; p->errCode==SQLITE_OK && ii<nField; ii++){
      zField = recoverMPrintf(p, "%z%sc%d", zField, zSep, ii);
      zSep = ", ";
    }

    zSql = recoverMPrintf(p, "CREATE TABLE %s(%s)", zTbl, zField);
    sqlite3_free(zField);

    recoverExec(p, p->dbOut, zSql);
    recoverSqlCallback(p, zSql);
    sqlite3_free(zSql);
  }else if( p->errCode==SQLITE_OK ){
    recoverError(
        p, SQLITE_ERROR, "failed to create %s output table", p->zLostAndFound
    );
  }

  return zTbl;
}

/*
** Synthesize and prepare an INSERT statement to write to the lost_and_found
** table in the output database. The name of the table is zTab, and it has
** nField c* fields.
*/
static sqlite3_stmt *recoverLostAndFoundInsert(
  sqlite3_recover *p,
  const char *zTab,
  int nField
){
  int nTotal = nField + 4;
  int ii;
  char *zBind = 0;
  sqlite3_stmt *pRet = 0;

  if( p->xSql==0 ){
    for(ii=0; ii<nTotal; ii++){
      zBind = recoverMPrintf(p, "%z%s?", zBind, zBind?", ":"", ii);
    }
    pRet = recoverPreparePrintf(
        p, p->dbOut, "INSERT INTO %s VALUES(%s)", zTab, zBind
    );
  }else{
    const char *zSep = "";
    for(ii=0; ii<nTotal; ii++){
      zBind = recoverMPrintf(p, "%z%squote(?)", zBind, zSep);
      zSep = "|| ', ' ||";
    }
    pRet = recoverPreparePrintf(
        p, p->dbOut, "SELECT 'INSERT INTO %s VALUES(' || %s || ')'", zTab, zBind
    );
  }

  sqlite3_free(zBind);
  return pRet;
}

/*
** Input database page iPg contains data that will be written to the
** lost-and-found table of the output database. This function attempts
** to identify the root page of the tree that page iPg belonged to.
** If successful, it sets output variable (*piRoot) to the page number
** of the root page and returns SQLITE_OK. Otherwise, if an error occurs,
** an SQLite error code is returned and the final value of *piRoot 
** undefined.
*/
static int recoverLostAndFoundFindRoot(
  sqlite3_recover *p, 
  i64 iPg,
  i64 *piRoot
){
  RecoverStateLAF *pLaf = &p->laf;

  if( pLaf->pFindRoot==0 ){
    pLaf->pFindRoot = recoverPrepare(p, p->dbOut,
        "WITH RECURSIVE p(pgno) AS ("
        "  SELECT ?"
        "    UNION"
        "  SELECT parent FROM recovery.map AS m, p WHERE m.pgno=p.pgno"
        ") "
        "SELECT p.pgno FROM p, recovery.map m WHERE m.pgno=p.pgno "
        "    AND m.parent IS NULL"
    );
  }
  if( p->errCode==SQLITE_OK ){
    sqlite3_bind_int64(pLaf->pFindRoot, 1, iPg);
    if( sqlite3_step(pLaf->pFindRoot)==SQLITE_ROW ){
      *piRoot = sqlite3_column_int64(pLaf->pFindRoot, 0);
    }else{
      *piRoot = iPg;
    }
    recoverReset(p, pLaf->pFindRoot);
  }
  return p->errCode;
}

/*
** Recover data from page iPage of the input database and write it to
** the lost-and-found table in the output database.
*/
static void recoverLostAndFoundOnePage(sqlite3_recover *p, i64 iPage){
  RecoverStateLAF *pLaf = &p->laf;
  sqlite3_value **apVal = pLaf->apVal;
  sqlite3_stmt *pPageData = pLaf->pPageData;
  sqlite3_stmt *pInsert = pLaf->pInsert;

  int nVal = -1;
  int iPrevCell = 0;
  i64 iRoot = 0;
  int bHaveRowid = 0;
  i64 iRowid = 0;
  int ii = 0;

  if( recoverLostAndFoundFindRoot(p, iPage, &iRoot) ) return;
  sqlite3_bind_int64(pPageData, 1, iPage);
  while( p->errCode==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPageData) ){
    int iCell = sqlite3_column_int64(pPageData, 0);
    int iField = sqlite3_column_int64(pPageData, 1);

    if( iPrevCell!=iCell && nVal>=0 ){
      /* Insert the new row */
      sqlite3_bind_int64(pInsert, 1, iRoot);      /* rootpgno */
      sqlite3_bind_int64(pInsert, 2, iPage);      /* pgno */
      sqlite3_bind_int(pInsert, 3, nVal);         /* nfield */
      if( bHaveRowid ){
        sqlite3_bind_int64(pInsert, 4, iRowid);   /* id */
      }
      for(ii=0; ii<nVal; ii++){
        recoverBindValue(p, pInsert, 5+ii, apVal[ii]);
      }
      if( sqlite3_step(pInsert)==SQLITE_ROW ){
        recoverSqlCallback(p, (const char*)sqlite3_column_text(pInsert, 0));
      }
      recoverReset(p, pInsert);

      /* Discard the accumulated row data */
      for(ii=0; ii<nVal; ii++){
        sqlite3_value_free(apVal[ii]);
        apVal[ii] = 0;
      }
      sqlite3_clear_bindings(pInsert);
      bHaveRowid = 0;
      nVal = -1;
    }

    if( iCell<0 ) break;

    if( iField<0 ){
      assert( nVal==-1 );
      iRowid = sqlite3_column_int64(pPageData, 2);
      bHaveRowid = 1;
      nVal = 0;
    }else if( iField<pLaf->nMaxField ){
      sqlite3_value *pVal = sqlite3_column_value(pPageData, 2);
      apVal[iField] = sqlite3_value_dup(pVal);
      assert( iField==nVal || (nVal==-1 && iField==0) );
      nVal = iField+1;
      if( apVal[iField]==0 ){
        recoverError(p, SQLITE_NOMEM, 0);
      }
    }

    iPrevCell = iCell;
  }
  recoverReset(p, pPageData);

  for(ii=0; ii<nVal; ii++){
    sqlite3_value_free(apVal[ii]);
    apVal[ii] = 0;
  }
}

/*
** Perform one step (sqlite3_recover_step()) of work for the connection 
** passed as the only argument, which is guaranteed to be in
** RECOVER_STATE_LOSTANDFOUND3 state - during which the lost-and-found 
** table of the output database is populated with recovered data that can 
** not be assigned to any recovered schema object.
*/ 
static int recoverLostAndFound3Step(sqlite3_recover *p){
  RecoverStateLAF *pLaf = &p->laf;
  if( p->errCode==SQLITE_OK ){
    if( pLaf->pInsert==0 ){
      return SQLITE_DONE;
    }else{
      if( p->errCode==SQLITE_OK ){
        int res = sqlite3_step(pLaf->pAllPage);
        if( res==SQLITE_ROW ){
          i64 iPage = sqlite3_column_int64(pLaf->pAllPage, 0);
          if( recoverBitmapQuery(pLaf->pUsed, iPage)==0 ){
            recoverLostAndFoundOnePage(p, iPage);
          }
        }else{
          recoverReset(p, pLaf->pAllPage);
          return SQLITE_DONE;
        }
      }
    }
  }
  return SQLITE_OK;
}

/*
** Initialize resources required in RECOVER_STATE_LOSTANDFOUND3 
** state - during which the lost-and-found table of the output database 
** is populated with recovered data that can not be assigned to any 
** recovered schema object.
*/ 
static void recoverLostAndFound3Init(sqlite3_recover *p){
  RecoverStateLAF *pLaf = &p->laf;

  if( pLaf->nMaxField>0 ){
    char *zTab = 0;               /* Name of lost_and_found table */

    zTab = recoverLostAndFoundCreate(p, pLaf->nMaxField);
    pLaf->pInsert = recoverLostAndFoundInsert(p, zTab, pLaf->nMaxField);
    sqlite3_free(zTab);

    pLaf->pAllPage = recoverPreparePrintf(p, p->dbOut,
        "WITH RECURSIVE seq(ii) AS ("
        "  SELECT 1 UNION ALL SELECT ii+1 FROM seq WHERE ii<%lld"
        ")"
        "SELECT ii FROM seq" , p->laf.nPg
    );
    pLaf->pPageData = recoverPrepare(p, p->dbOut,
        "SELECT cell, field, value "
        "FROM sqlite_dbdata('getpage()') d WHERE d.pgno=? "
        "UNION ALL "
        "SELECT -1, -1, -1"
    );

    pLaf->apVal = (sqlite3_value**)recoverMalloc(p, 
        pLaf->nMaxField*sizeof(sqlite3_value*)
    );
  }
}

/*
** Initialize resources required in RECOVER_STATE_WRITING state - during which
** tables recovered from the schema of the input database are populated with
** recovered data.
*/ 
static int recoverWriteDataInit(sqlite3_recover *p){
  RecoverStateW1 *p1 = &p->w1;
  RecoverTable *pTbl = 0;
  int nByte = 0;

  /* Figure out the maximum number of columns for any table in the schema */
  assert( p1->nMax==0 );
  for(pTbl=p->pTblList; pTbl; pTbl=pTbl->pNext){
    if( pTbl->nCol>p1->nMax ) p1->nMax = pTbl->nCol;
  }

  /* Allocate an array of (sqlite3_value*) in which to accumulate the values
  ** that will be written to the output database in a single row. */
  nByte = sizeof(sqlite3_value*) * (p1->nMax+1);
  p1->apVal = (sqlite3_value**)recoverMalloc(p, nByte);
  if( p1->apVal==0 ) return p->errCode;

  /* Prepare the SELECT to loop through schema tables (pTbls) and the SELECT
  ** to loop through cells that appear to belong to a single table (pSel). */
  p1->pTbls = recoverPrepare(p, p->dbOut,
      "SELECT rootpage FROM recovery.schema "
      "  WHERE type='table' AND (sql NOT LIKE 'create virtual%')"
      "  ORDER BY (tbl_name='sqlite_sequence') ASC"
  );
  p1->pSel = recoverPrepare(p, p->dbOut, 
      "WITH RECURSIVE pages(page) AS ("
      "  SELECT ?1"
      "    UNION"
      "  SELECT child FROM sqlite_dbptr('getpage()'), pages "
      "    WHERE pgno=page"
      ") "
      "SELECT page, cell, field, value "
      "FROM sqlite_dbdata('getpage()') d, pages p WHERE p.page=d.pgno "
      "UNION ALL "
      "SELECT 0, 0, 0, 0"
  );

  return p->errCode;
}

/*
** Clean up resources allocated by recoverWriteDataInit() (stuff in 
** sqlite3_recover.w1).
*/
static void recoverWriteDataCleanup(sqlite3_recover *p){
  RecoverStateW1 *p1 = &p->w1;
  int ii;
  for(ii=0; ii<p1->nVal; ii++){
    sqlite3_value_free(p1->apVal[ii]);
  }
  sqlite3_free(p1->apVal);
  recoverFinalize(p, p1->pInsert);
  recoverFinalize(p, p1->pTbls);
  recoverFinalize(p, p1->pSel);
  memset(p1, 0, sizeof(*p1));
}

/*
** Perform one step (sqlite3_recover_step()) of work for the connection 
** passed as the only argument, which is guaranteed to be in
** RECOVER_STATE_WRITING state - during which tables recovered from the
** schema of the input database are populated with recovered data.
*/ 
static int recoverWriteDataStep(sqlite3_recover *p){
  RecoverStateW1 *p1 = &p->w1;
  sqlite3_stmt *pSel = p1->pSel;
  sqlite3_value **apVal = p1->apVal;

  if( p->errCode==SQLITE_OK && p1->pTab==0 ){
    if( sqlite3_step(p1->pTbls)==SQLITE_ROW ){
      i64 iRoot = sqlite3_column_int64(p1->pTbls, 0);
      p1->pTab = recoverFindTable(p, iRoot);

      recoverFinalize(p, p1->pInsert);
      p1->pInsert = 0;

      /* If this table is unknown, return early. The caller will invoke this
      ** function again and it will move on to the next table.  */
      if( p1->pTab==0 ) return p->errCode;

      /* If this is the sqlite_sequence table, delete any rows added by
      ** earlier INSERT statements on tables with AUTOINCREMENT primary
      ** keys before recovering its contents. The p1->pTbls SELECT statement
      ** is rigged to deliver "sqlite_sequence" last of all, so we don't
      ** worry about it being modified after it is recovered. */
      if( sqlite3_stricmp("sqlite_sequence", p1->pTab->zTab)==0 ){
        recoverExec(p, p->dbOut, "DELETE FROM sqlite_sequence");
        recoverSqlCallback(p, "DELETE FROM sqlite_sequence");
      }

      /* Bind the root page of this table within the original database to 
      ** SELECT statement p1->pSel. The SELECT statement will then iterate
      ** through cells that look like they belong to table pTab.  */
      sqlite3_bind_int64(pSel, 1, iRoot);

      p1->nVal = 0;
      p1->bHaveRowid = 0;
      p1->iPrevPage = -1;
      p1->iPrevCell = -1;
    }else{
      return SQLITE_DONE;
    }
  }
  assert( p->errCode!=SQLITE_OK || p1->pTab );

  if( p->errCode==SQLITE_OK && sqlite3_step(pSel)==SQLITE_ROW ){
    RecoverTable *pTab = p1->pTab;

    i64 iPage = sqlite3_column_int64(pSel, 0);
    int iCell = sqlite3_column_int(pSel, 1);
    int iField = sqlite3_column_int(pSel, 2);
    sqlite3_value *pVal = sqlite3_column_value(pSel, 3);
    int bNewCell = (p1->iPrevPage!=iPage || p1->iPrevCell!=iCell);

    assert( bNewCell==0 || (iField==-1 || iField==0) );
    assert( bNewCell || iField==p1->nVal || p1->nVal==pTab->nCol );

    if( bNewCell ){
      int ii = 0;
      if( p1->nVal>=0 ){
        if( p1->pInsert==0 || p1->nVal!=p1->nInsert ){
          recoverFinalize(p, p1->pInsert);
          p1->pInsert = recoverInsertStmt(p, pTab, p1->nVal);
          p1->nInsert = p1->nVal;
        }
        if( p1->nVal>0 ){
          sqlite3_stmt *pInsert = p1->pInsert;
          for(ii=0; ii<pTab->nCol; ii++){
            RecoverColumn *pCol = &pTab->aCol[ii];
            int iBind = pCol->iBind;
            if( iBind>0 ){
              if( pCol->bIPK ){
                sqlite3_bind_int64(pInsert, iBind, p1->iRowid);
              }else if( pCol->iField<p1->nVal ){
                recoverBindValue(p, pInsert, iBind, apVal[pCol->iField]);
              }
            }
          }
          if( p->bRecoverRowid && pTab->iRowidBind>0 && p1->bHaveRowid ){
            sqlite3_bind_int64(pInsert, pTab->iRowidBind, p1->iRowid);
          }
          if( SQLITE_ROW==sqlite3_step(pInsert) ){
            const char *z = (const char*)sqlite3_column_text(pInsert, 0);
            recoverSqlCallback(p, z);
          }
          recoverReset(p, pInsert);
          assert( p->errCode || pInsert );
          if( pInsert ) sqlite3_clear_bindings(pInsert);
        }
      }

      for(ii=0; ii<p1->nVal; ii++){
        sqlite3_value_free(apVal[ii]);
        apVal[ii] = 0;
      }
      p1->nVal = -1;
      p1->bHaveRowid = 0;
    }

    if( iPage!=0 ){
      if( iField<0 ){
        p1->iRowid = sqlite3_column_int64(pSel, 3);
        assert( p1->nVal==-1 );
        p1->nVal = 0;
        p1->bHaveRowid = 1;
      }else if( iField<pTab->nCol ){
        assert( apVal[iField]==0 );
        apVal[iField] = sqlite3_value_dup( pVal );
        if( apVal[iField]==0 ){
          recoverError(p, SQLITE_NOMEM, 0);
        }
        p1->nVal = iField+1;
      }
      p1->iPrevCell = iCell;
      p1->iPrevPage = iPage;
    }
  }else{
    recoverReset(p, pSel);
    p1->pTab = 0;
  }

  return p->errCode;
}

/*
** Initialize resources required by sqlite3_recover_step() in
** RECOVER_STATE_LOSTANDFOUND1 state - during which the set of pages not
** already allocated to a recovered schema element is determined.
*/ 
static void recoverLostAndFound1Init(sqlite3_recover *p){
  RecoverStateLAF *pLaf = &p->laf;
  sqlite3_stmt *pStmt = 0;

  assert( p->laf.pUsed==0 );
  pLaf->nPg = recoverPageCount(p);
  pLaf->pUsed = recoverBitmapAlloc(p, pLaf->nPg);

  /* Prepare a statement to iterate through all pages that are part of any tree
  ** in the recoverable part of the input database schema to the bitmap. And,
  ** if !p->bFreelistCorrupt, add all pages that appear to be part of the
  ** freelist.  */
  pStmt = recoverPrepare(
      p, p->dbOut,
      "WITH trunk(pgno) AS ("
      "  SELECT read_i32(getpage(1), 8) AS x WHERE x>0"
      "    UNION"
      "  SELECT read_i32(getpage(trunk.pgno), 0) AS x FROM trunk WHERE x>0"
      "),"
      "trunkdata(pgno, data) AS ("
      "  SELECT pgno, getpage(pgno) FROM trunk"
      "),"
      "freelist(data, n, freepgno) AS ("
      "  SELECT data, min(16384, read_i32(data, 1)-1), pgno FROM trunkdata"
      "    UNION ALL"
      "  SELECT data, n-1, read_i32(data, 2+n) FROM freelist WHERE n>=0"
      "),"
      ""
      "roots(r) AS ("
      "  SELECT 1 UNION ALL"
      "  SELECT rootpage FROM recovery.schema WHERE rootpage>0"
      "),"
      "used(page) AS ("
      "  SELECT r FROM roots"
      "    UNION"
      "  SELECT child FROM sqlite_dbptr('getpage()'), used "
      "    WHERE pgno=page"
      ") "
      "SELECT page FROM used"
      " UNION ALL "
      "SELECT freepgno FROM freelist WHERE NOT ?"
  );
  if( pStmt ) sqlite3_bind_int(pStmt, 1, p->bFreelistCorrupt);
  pLaf->pUsedPages = pStmt;
}

/*
** Perform one step (sqlite3_recover_step()) of work for the connection 
** passed as the only argument, which is guaranteed to be in
** RECOVER_STATE_LOSTANDFOUND1 state - during which the set of pages not
** already allocated to a recovered schema element is determined.
*/ 
static int recoverLostAndFound1Step(sqlite3_recover *p){
  RecoverStateLAF *pLaf = &p->laf;
  int rc = p->errCode;
  if( rc==SQLITE_OK ){
    rc = sqlite3_step(pLaf->pUsedPages);
    if( rc==SQLITE_ROW ){
      i64 iPg = sqlite3_column_int64(pLaf->pUsedPages, 0);
      recoverBitmapSet(pLaf->pUsed, iPg);
      rc = SQLITE_OK;
    }else{
      recoverFinalize(p, pLaf->pUsedPages);
      pLaf->pUsedPages = 0;
    }
  }
  return rc;
}

/*
** Initialize resources required by RECOVER_STATE_LOSTANDFOUND2 
** state - during which the pages identified in RECOVER_STATE_LOSTANDFOUND1
** are sorted into sets that likely belonged to the same database tree.
*/ 
static void recoverLostAndFound2Init(sqlite3_recover *p){
  RecoverStateLAF *pLaf = &p->laf;

  assert( p->laf.pAllAndParent==0 );
  assert( p->laf.pMapInsert==0 );
  assert( p->laf.pMaxField==0 );
  assert( p->laf.nMaxField==0 );

  pLaf->pMapInsert = recoverPrepare(p, p->dbOut,
      "INSERT OR IGNORE INTO recovery.map(pgno, parent) VALUES(?, ?)"
  );
  pLaf->pAllAndParent = recoverPreparePrintf(p, p->dbOut,
      "WITH RECURSIVE seq(ii) AS ("
      "  SELECT 1 UNION ALL SELECT ii+1 FROM seq WHERE ii<%lld"
      ")"
      "SELECT pgno, child FROM sqlite_dbptr('getpage()') "
      " UNION ALL "
      "SELECT NULL, ii FROM seq", p->laf.nPg
  );
  pLaf->pMaxField = recoverPreparePrintf(p, p->dbOut,
      "SELECT max(field)+1 FROM sqlite_dbdata('getpage') WHERE pgno = ?"
  );
}

/*
** Perform one step (sqlite3_recover_step()) of work for the connection 
** passed as the only argument, which is guaranteed to be in
** RECOVER_STATE_LOSTANDFOUND2 state - during which the pages identified 
** in RECOVER_STATE_LOSTANDFOUND1 are sorted into sets that likely belonged 
** to the same database tree.
*/ 
static int recoverLostAndFound2Step(sqlite3_recover *p){
  RecoverStateLAF *pLaf = &p->laf;
  if( p->errCode==SQLITE_OK ){
    int res = sqlite3_step(pLaf->pAllAndParent);
    if( res==SQLITE_ROW ){
      i64 iChild = sqlite3_column_int(pLaf->pAllAndParent, 1);
      if( recoverBitmapQuery(pLaf->pUsed, iChild)==0 ){
        sqlite3_bind_int64(pLaf->pMapInsert, 1, iChild);
        sqlite3_bind_value(pLaf->pMapInsert, 2, 
            sqlite3_column_value(pLaf->pAllAndParent, 0)
        );
        sqlite3_step(pLaf->pMapInsert);
        recoverReset(p, pLaf->pMapInsert);
        sqlite3_bind_int64(pLaf->pMaxField, 1, iChild);
        if( SQLITE_ROW==sqlite3_step(pLaf->pMaxField) ){
          int nMax = sqlite3_column_int(pLaf->pMaxField, 0);
          if( nMax>pLaf->nMaxField ) pLaf->nMaxField = nMax;
        }
        recoverReset(p, pLaf->pMaxField);
      }
    }else{
      recoverFinalize(p, pLaf->pAllAndParent);
      pLaf->pAllAndParent =0;
      return SQLITE_DONE;
    }
  }
  return p->errCode;
}

/*
** Free all resources allocated as part of sqlite3_recover_step() calls
** in one of the RECOVER_STATE_LOSTANDFOUND[123] states.
*/
static void recoverLostAndFoundCleanup(sqlite3_recover *p){
  recoverBitmapFree(p->laf.pUsed);
  p->laf.pUsed = 0;
  sqlite3_finalize(p->laf.pUsedPages);
  sqlite3_finalize(p->laf.pAllAndParent);
  sqlite3_finalize(p->laf.pMapInsert);
  sqlite3_finalize(p->laf.pMaxField);
  sqlite3_finalize(p->laf.pFindRoot);
  sqlite3_finalize(p->laf.pInsert);
  sqlite3_finalize(p->laf.pAllPage);
  sqlite3_finalize(p->laf.pPageData);
  p->laf.pUsedPages = 0;
  p->laf.pAllAndParent = 0;
  p->laf.pMapInsert = 0;
  p->laf.pMaxField = 0;
  p->laf.pFindRoot = 0;
  p->laf.pInsert = 0;
  p->laf.pAllPage = 0;
  p->laf.pPageData = 0;
  sqlite3_free(p->laf.apVal);
  p->laf.apVal = 0;
}

/*
** Free all resources allocated as part of sqlite3_recover_step() calls.
*/
static void recoverFinalCleanup(sqlite3_recover *p){
  RecoverTable *pTab = 0;
  RecoverTable *pNext = 0;

  recoverWriteDataCleanup(p);
  recoverLostAndFoundCleanup(p);

  for(pTab=p->pTblList; pTab; pTab=pNext){
    pNext = pTab->pNext;
    sqlite3_free(pTab);
  }
  p->pTblList = 0;
  sqlite3_finalize(p->pGetPage);
  p->pGetPage = 0;
  sqlite3_file_control(p->dbIn, p->zDb, SQLITE_FCNTL_RESET_CACHE, 0);

  {
#ifndef NDEBUG
    int res = 
#endif
       sqlite3_close(p->dbOut);
    assert( res==SQLITE_OK );
  }
  p->dbOut = 0;
}

/*
** Decode and return an unsigned 16-bit big-endian integer value from 
** buffer a[].
*/
static u32 recoverGetU16(const u8 *a){
  return (((u32)a[0])<<8) + ((u32)a[1]);
}

/*
** Decode and return an unsigned 32-bit big-endian integer value from 
** buffer a[].
*/
static u32 recoverGetU32(const u8 *a){
  return (((u32)a[0])<<24) + (((u32)a[1])<<16) + (((u32)a[2])<<8) + ((u32)a[3]);
}

/*
** Decode an SQLite varint from buffer a[]. Write the decoded value to (*pVal)
** and return the number of bytes consumed.
*/
static int recoverGetVarint(const u8 *a, i64 *pVal){
  sqlite3_uint64 u = 0;
  int i;
  for(i=0; i<8; i++){
    u = (u<<7) + (a[i]&0x7f);
    if( (a[i]&0x80)==0 ){ *pVal = (sqlite3_int64)u; return i+1; }
  }
  u = (u<<8) + (a[i]&0xff);
  *pVal = (sqlite3_int64)u;
  return 9;
}

/*
** The second argument points to a buffer n bytes in size. If this buffer
** or a prefix thereof appears to contain a well-formed SQLite b-tree page, 
** return the page-size in bytes. Otherwise, if the buffer does not 
** appear to contain a well-formed b-tree page, return 0.
*/
static int recoverIsValidPage(u8 *aTmp, const u8 *a, int n){
  u8 *aUsed = aTmp;
  int nFrag = 0;
  int nActual = 0;
  int iFree = 0;
  int nCell = 0;                  /* Number of cells on page */
  int iCellOff = 0;               /* Offset of cell array in page */
  int iContent = 0;
  int eType = 0;
  int ii = 0;

  eType = (int)a[0];
  if( eType!=0x02 && eType!=0x05 && eType!=0x0A && eType!=0x0D ) return 0;

  iFree = (int)recoverGetU16(&a[1]);
  nCell = (int)recoverGetU16(&a[3]);
  iContent = (int)recoverGetU16(&a[5]);
  if( iContent==0 ) iContent = 65536;
  nFrag = (int)a[7];

  if( iContent>n ) return 0;

  memset(aUsed, 0, n);
  memset(aUsed, 0xFF, iContent);

  /* Follow the free-list. This is the same format for all b-tree pages. */
  if( iFree && iFree<=iContent ) return 0;
  while( iFree ){
    int iNext = 0;
    int nByte = 0;
    if( iFree>(n-4) ) return 0;
    iNext = recoverGetU16(&a[iFree]);
    nByte = recoverGetU16(&a[iFree+2]);
    if( iFree+nByte>n ) return 0;
    if( iNext && iNext<iFree+nByte ) return 0;
    memset(&aUsed[iFree], 0xFF, nByte);
    iFree = iNext;
  }

  /* Run through the cells */
  if( eType==0x02 || eType==0x05 ){
    iCellOff = 12;
  }else{
    iCellOff = 8;
  }
  if( (iCellOff + 2*nCell)>iContent ) return 0;
  for(ii=0; ii<nCell; ii++){
    int iByte;
    i64 nPayload = 0;
    int nByte = 0;
    int iOff = recoverGetU16(&a[iCellOff + 2*ii]);
    if( iOff<iContent || iOff>n ){
      return 0;
    }
    if( eType==0x05 || eType==0x02 ) nByte += 4;
    nByte += recoverGetVarint(&a[iOff+nByte], &nPayload);
    if( eType==0x0D ){
      i64 dummy = 0;
      nByte += recoverGetVarint(&a[iOff+nByte], &dummy);
    }
    if( eType!=0x05 ){
      int X = (eType==0x0D) ? n-35 : (((n-12)*64/255)-23);
      int M = ((n-12)*32/255)-23;
      int K = M+((nPayload-M)%(n-4));

      if( nPayload<X ){
        nByte += nPayload;
      }else if( K<=X ){
        nByte += K+4;
      }else{
        nByte += M+4;
      }
    }

    if( iOff+nByte>n ){
      return 0;
    }
    for(iByte=iOff; iByte<(iOff+nByte); iByte++){
      if( aUsed[iByte]!=0 ){
        return 0;
      }
      aUsed[iByte] = 0xFF;
    }
  }

  nActual = 0;
  for(ii=0; ii<n; ii++){
    if( aUsed[ii]==0 ) nActual++;
  }
  return (nActual==nFrag);
}


static int recoverVfsClose(sqlite3_file*);
static int recoverVfsRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
static int recoverVfsWrite(sqlite3_file*, const void*, int, sqlite3_int64);
static int recoverVfsTruncate(sqlite3_file*, sqlite3_int64 size);
static int recoverVfsSync(sqlite3_file*, int flags);
static int recoverVfsFileSize(sqlite3_file*, sqlite3_int64 *pSize);
static int recoverVfsLock(sqlite3_file*, int);
static int recoverVfsUnlock(sqlite3_file*, int);
static int recoverVfsCheckReservedLock(sqlite3_file*, int *pResOut);
static int recoverVfsFileControl(sqlite3_file*, int op, void *pArg);
static int recoverVfsSectorSize(sqlite3_file*);
static int recoverVfsDeviceCharacteristics(sqlite3_file*);
static int recoverVfsShmMap(sqlite3_file*, int, int, int, void volatile**);
static int recoverVfsShmLock(sqlite3_file*, int offset, int n, int flags);
static void recoverVfsShmBarrier(sqlite3_file*);
static int recoverVfsShmUnmap(sqlite3_file*, int deleteFlag);
static int recoverVfsFetch(sqlite3_file*, sqlite3_int64, int, void**);
static int recoverVfsUnfetch(sqlite3_file *pFd, sqlite3_int64 iOff, void *p);

static sqlite3_io_methods recover_methods = {
  2, /* iVersion */
  recoverVfsClose,
  recoverVfsRead,
  recoverVfsWrite,
  recoverVfsTruncate,
  recoverVfsSync,
  recoverVfsFileSize,
  recoverVfsLock,
  recoverVfsUnlock,
  recoverVfsCheckReservedLock,
  recoverVfsFileControl,
  recoverVfsSectorSize,
  recoverVfsDeviceCharacteristics,
  recoverVfsShmMap,
  recoverVfsShmLock,
  recoverVfsShmBarrier,
  recoverVfsShmUnmap,
  recoverVfsFetch,
  recoverVfsUnfetch
};

static int recoverVfsClose(sqlite3_file *pFd){
  assert( pFd->pMethods!=&recover_methods );
  return pFd->pMethods->xClose(pFd);
}

/*
** Write value v to buffer a[] as a 16-bit big-endian unsigned integer.
*/
static void recoverPutU16(u8 *a, u32 v){
  a[0] = (v>>8) & 0x00FF;
  a[1] = (v>>0) & 0x00FF;
}

/*
** Write value v to buffer a[] as a 32-bit big-endian unsigned integer.
*/
static void recoverPutU32(u8 *a, u32 v){
  a[0] = (v>>24) & 0x00FF;
  a[1] = (v>>16) & 0x00FF;
  a[2] = (v>>8) & 0x00FF;
  a[3] = (v>>0) & 0x00FF;
}

/*
** Detect the page-size of the database opened by file-handle pFd by 
** searching the first part of the file for a well-formed SQLite b-tree 
** page. If parameter nReserve is non-zero, then as well as searching for
** a b-tree page with zero reserved bytes, this function searches for one
** with nReserve reserved bytes at the end of it.
**
** If successful, set variable p->detected_pgsz to the detected page-size
** in bytes and return SQLITE_OK. Or, if no error occurs but no valid page
** can be found, return SQLITE_OK but leave p->detected_pgsz set to 0. Or,
** if an error occurs (e.g. an IO or OOM error), then an SQLite error code
** is returned. The final value of p->detected_pgsz is undefined in this
** case.
*/
static int recoverVfsDetectPagesize(
  sqlite3_recover *p,             /* Recover handle */
  sqlite3_file *pFd,              /* File-handle open on input database */
  u32 nReserve,                   /* Possible nReserve value */
  i64 nSz                         /* Size of database file in bytes */
){
  int rc = SQLITE_OK;
  const int nMin = 512;
  const int nMax = 65536;
  const int nMaxBlk = 4;
  u32 pgsz = 0;
  int iBlk = 0;
  u8 *aPg = 0;
  u8 *aTmp = 0;
  int nBlk = 0;

  aPg = (u8*)sqlite3_malloc(2*nMax);
  if( aPg==0 ) return SQLITE_NOMEM;
  aTmp = &aPg[nMax];

  nBlk = (nSz+nMax-1)/nMax;
  if( nBlk>nMaxBlk ) nBlk = nMaxBlk;

  do {
    for(iBlk=0; rc==SQLITE_OK && iBlk<nBlk; iBlk++){
      int nByte = (nSz>=((iBlk+1)*nMax)) ? nMax : (nSz % nMax);
      memset(aPg, 0, nMax);
      rc = pFd->pMethods->xRead(pFd, aPg, nByte, iBlk*nMax);
      if( rc==SQLITE_OK ){
        int pgsz2;
        for(pgsz2=(pgsz ? pgsz*2 : nMin); pgsz2<=nMax; pgsz2=pgsz2*2){
          int iOff;
          for(iOff=0; iOff<nMax; iOff+=pgsz2){
            if( recoverIsValidPage(aTmp, &aPg[iOff], pgsz2-nReserve) ){
              pgsz = pgsz2;
              break;
            }
          }
        }
      }
    }
    if( pgsz>(u32)p->detected_pgsz ){
      p->detected_pgsz = pgsz;
      p->nReserve = nReserve;
    }
    if( nReserve==0 ) break;
    nReserve = 0;
  }while( 1 );

  p->detected_pgsz = pgsz;
  sqlite3_free(aPg);
  return rc;
}

/*
** The xRead() method of the wrapper VFS. This is used to intercept calls
** to read page 1 of the input database.
*/
static int recoverVfsRead(sqlite3_file *pFd, void *aBuf, int nByte, i64 iOff){
  int rc = SQLITE_OK;
  if( pFd->pMethods==&recover_methods ){
    pFd->pMethods = recover_g.pMethods;
    rc = pFd->pMethods->xRead(pFd, aBuf, nByte, iOff);
    if( nByte==16 ){
      sqlite3_randomness(16, aBuf);
    }else
    if( rc==SQLITE_OK && iOff==0 && nByte>=108 ){
      /* Ensure that the database has a valid header file. The only fields
      ** that really matter to recovery are:
      **
      **   + Database page size (16-bits at offset 16)
      **   + Size of db in pages (32-bits at offset 28)
      **   + Database encoding (32-bits at offset 56)
      **
      ** Also preserved are:
      **
      **   + first freelist page (32-bits at offset 32)
      **   + size of freelist (32-bits at offset 36)
      **   + the wal-mode flags (16-bits at offset 18)
      **
      ** We also try to preserve the auto-vacuum, incr-value, user-version
      ** and application-id fields - all 32 bit quantities at offsets 
      ** 52, 60, 64 and 68. All other fields are set to known good values.
      **
      ** Byte offset 105 should also contain the page-size as a 16-bit 
      ** integer.
      */
      const int aPreserve[] = {32, 36, 52, 60, 64, 68};
      u8 aHdr[108] = {
        0x53, 0x51, 0x4c, 0x69, 0x74, 0x65, 0x20, 0x66, 
        0x6f, 0x72, 0x6d, 0x61, 0x74, 0x20, 0x33, 0x00,
        0xFF, 0xFF, 0x01, 0x01, 0x00, 0x40, 0x20, 0x20,
        0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
        0x00, 0x00, 0x10, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x2e, 0x5b, 0x30,

        0x0D, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00
      };
      u8 *a = (u8*)aBuf;

      u32 pgsz = recoverGetU16(&a[16]);
      u32 nReserve = a[20];
      u32 enc = recoverGetU32(&a[56]);
      u32 dbsz = 0;
      i64 dbFileSize = 0;
      int ii;
      sqlite3_recover *p = recover_g.p;

      if( pgsz==0x01 ) pgsz = 65536;
      rc = pFd->pMethods->xFileSize(pFd, &dbFileSize);

      if( rc==SQLITE_OK && p->detected_pgsz==0 ){
        rc = recoverVfsDetectPagesize(p, pFd, nReserve, dbFileSize);
      }
      if( p->detected_pgsz ){
        pgsz = p->detected_pgsz;
        nReserve = p->nReserve;
      }

      if( pgsz ){
        dbsz = dbFileSize / pgsz;
      }
      if( enc!=SQLITE_UTF8 && enc!=SQLITE_UTF16BE && enc!=SQLITE_UTF16LE ){
        enc = SQLITE_UTF8;
      }

      sqlite3_free(p->pPage1Cache);
      p->pPage1Cache = 0;
      p->pPage1Disk = 0;

      p->pgsz = nByte;
      p->pPage1Cache = (u8*)recoverMalloc(p, nByte*2);
      if( p->pPage1Cache ){
        p->pPage1Disk = &p->pPage1Cache[nByte];
        memcpy(p->pPage1Disk, aBuf, nByte);
        aHdr[18] = a[18];
        aHdr[19] = a[19];
        recoverPutU32(&aHdr[28], dbsz);
        recoverPutU32(&aHdr[56], enc);
        recoverPutU16(&aHdr[105], pgsz-nReserve);
        if( pgsz==65536 ) pgsz = 1;
        recoverPutU16(&aHdr[16], pgsz);
        aHdr[20] = nReserve;
        for(ii=0; ii<(int)(sizeof(aPreserve)/sizeof(aPreserve[0])); ii++){
          memcpy(&aHdr[aPreserve[ii]], &a[aPreserve[ii]], 4);
        }
        memcpy(aBuf, aHdr, sizeof(aHdr));
        memset(&((u8*)aBuf)[sizeof(aHdr)], 0, nByte-sizeof(aHdr));

        memcpy(p->pPage1Cache, aBuf, nByte);
      }else{
        rc = p->errCode;
      }

    }
    pFd->pMethods = &recover_methods;
  }else{
    rc = pFd->pMethods->xRead(pFd, aBuf, nByte, iOff);
  }
  return rc;
}

/*
** Used to make sqlite3_io_methods wrapper methods less verbose.
*/
#define RECOVER_VFS_WRAPPER(code)                         \
  int rc = SQLITE_OK;                                     \
  if( pFd->pMethods==&recover_methods ){                  \
    pFd->pMethods = recover_g.pMethods;                   \
    rc = code;                                            \
    pFd->pMethods = &recover_methods;                     \
  }else{                                                  \
    rc = code;                                            \
  }                                                       \
  return rc;                                              

/*
** Methods of the wrapper VFS. All methods except for xRead() and xClose()
** simply uninstall the sqlite3_io_methods wrapper, invoke the equivalent
** method on the lower level VFS, then reinstall the wrapper before returning.
** Those that return an integer value use the RECOVER_VFS_WRAPPER macro.
*/
static int recoverVfsWrite(
  sqlite3_file *pFd, const void *aBuf, int nByte, i64 iOff
){
  RECOVER_VFS_WRAPPER (
      pFd->pMethods->xWrite(pFd, aBuf, nByte, iOff)
  );
}
static int recoverVfsTruncate(sqlite3_file *pFd, sqlite3_int64 size){
  RECOVER_VFS_WRAPPER (
      pFd->pMethods->xTruncate(pFd, size)
  );
}
static int recoverVfsSync(sqlite3_file *pFd, int flags){
  RECOVER_VFS_WRAPPER (
      pFd->pMethods->xSync(pFd, flags)
  );
}
static int recoverVfsFileSize(sqlite3_file *pFd, sqlite3_int64 *pSize){
  RECOVER_VFS_WRAPPER (
      pFd->pMethods->xFileSize(pFd, pSize)
  );
}
static int recoverVfsLock(sqlite3_file *pFd, int eLock){
  RECOVER_VFS_WRAPPER (
      pFd->pMethods->xLock(pFd, eLock)
  );
}
static int recoverVfsUnlock(sqlite3_file *pFd, int eLock){
  RECOVER_VFS_WRAPPER (
      pFd->pMethods->xUnlock(pFd, eLock)
  );
}
static int recoverVfsCheckReservedLock(sqlite3_file *pFd, int *pResOut){
  RECOVER_VFS_WRAPPER (
      pFd->pMethods->xCheckReservedLock(pFd, pResOut)
  );
}
static int recoverVfsFileControl(sqlite3_file *pFd, int op, void *pArg){
  RECOVER_VFS_WRAPPER (
    (pFd->pMethods ?  pFd->pMethods->xFileControl(pFd, op, pArg) : SQLITE_NOTFOUND)
  );
}
static int recoverVfsSectorSize(sqlite3_file *pFd){
  RECOVER_VFS_WRAPPER (
      pFd->pMethods->xSectorSize(pFd)
  );
}
static int recoverVfsDeviceCharacteristics(sqlite3_file *pFd){
  RECOVER_VFS_WRAPPER (
      pFd->pMethods->xDeviceCharacteristics(pFd)
  );
}
static int recoverVfsShmMap(
  sqlite3_file *pFd, int iPg, int pgsz, int bExtend, void volatile **pp
){
  RECOVER_VFS_WRAPPER (
      pFd->pMethods->xShmMap(pFd, iPg, pgsz, bExtend, pp)
  );
}
static int recoverVfsShmLock(sqlite3_file *pFd, int offset, int n, int flags){
  RECOVER_VFS_WRAPPER (
      pFd->pMethods->xShmLock(pFd, offset, n, flags)
  );
}
static void recoverVfsShmBarrier(sqlite3_file *pFd){
  if( pFd->pMethods==&recover_methods ){
    pFd->pMethods = recover_g.pMethods;
    pFd->pMethods->xShmBarrier(pFd);
    pFd->pMethods = &recover_methods;
  }else{
    pFd->pMethods->xShmBarrier(pFd);
  }
}
static int recoverVfsShmUnmap(sqlite3_file *pFd, int deleteFlag){
  RECOVER_VFS_WRAPPER (
      pFd->pMethods->xShmUnmap(pFd, deleteFlag)
  );
}

static int recoverVfsFetch(
  sqlite3_file *pFd, 
  sqlite3_int64 iOff, 
  int iAmt, 
  void **pp
){
  (void)pFd;
  (void)iOff;
  (void)iAmt;
  *pp = 0;
  return SQLITE_OK;
}
static int recoverVfsUnfetch(sqlite3_file *pFd, sqlite3_int64 iOff, void *p){
  (void)pFd;
  (void)iOff;
  (void)p;
  return SQLITE_OK;
}

/*
** Install the VFS wrapper around the file-descriptor open on the input
** database for recover handle p. Mutex RECOVER_MUTEX_ID must be held
** when this function is called.
*/
static void recoverInstallWrapper(sqlite3_recover *p){
  sqlite3_file *pFd = 0;
  assert( recover_g.pMethods==0 );
  recoverAssertMutexHeld();
  sqlite3_file_control(p->dbIn, p->zDb, SQLITE_FCNTL_FILE_POINTER, (void*)&pFd);
  assert( pFd==0 || pFd->pMethods!=&recover_methods );
  if( pFd && pFd->pMethods ){
    int iVersion = 1 + (pFd->pMethods->iVersion>1 && pFd->pMethods->xShmMap!=0);
    recover_g.pMethods = pFd->pMethods;
    recover_g.p = p;
    recover_methods.iVersion = iVersion;
    pFd->pMethods = &recover_methods;
  }
}

/*
** Uninstall the VFS wrapper that was installed around the file-descriptor open
** on the input database for recover handle p. Mutex RECOVER_MUTEX_ID must be
** held when this function is called.
*/
static void recoverUninstallWrapper(sqlite3_recover *p){
  sqlite3_file *pFd = 0;
  recoverAssertMutexHeld();
  sqlite3_file_control(p->dbIn, p->zDb,SQLITE_FCNTL_FILE_POINTER,(void*)&pFd);
  if( pFd && pFd->pMethods ){
    pFd->pMethods = recover_g.pMethods;
    recover_g.pMethods = 0;
    recover_g.p = 0;
  }
}

/*
** This function does the work of a single sqlite3_recover_step() call. It
** is guaranteed that the handle is not in an error state when this
** function is called.
*/
static void recoverStep(sqlite3_recover *p){
  assert( p && p->errCode==SQLITE_OK );
  switch( p->eState ){
    case RECOVER_STATE_INIT:
      /* This is the very first call to sqlite3_recover_step() on this object.
      */
      recoverSqlCallback(p, "BEGIN");
      recoverSqlCallback(p, "PRAGMA writable_schema = on");

      recoverEnterMutex();
      recoverInstallWrapper(p);

      /* Open the output database. And register required virtual tables and 
      ** user functions with the new handle. */
      recoverOpenOutput(p);

      /* Open transactions on both the input and output databases. */
      sqlite3_file_control(p->dbIn, p->zDb, SQLITE_FCNTL_RESET_CACHE, 0);
      recoverExec(p, p->dbIn, "PRAGMA writable_schema = on");
      recoverExec(p, p->dbIn, "BEGIN");
      if( p->errCode==SQLITE_OK ) p->bCloseTransaction = 1;
      recoverExec(p, p->dbIn, "SELECT 1 FROM sqlite_schema");
      recoverTransferSettings(p);
      recoverOpenRecovery(p);
      recoverCacheSchema(p);

      recoverUninstallWrapper(p);
      recoverLeaveMutex();

      recoverExec(p, p->dbOut, "BEGIN");

      recoverWriteSchema1(p);
      p->eState = RECOVER_STATE_WRITING;
      break;
      
    case RECOVER_STATE_WRITING: {
      if( p->w1.pTbls==0 ){
        recoverWriteDataInit(p);
      }
      if( SQLITE_DONE==recoverWriteDataStep(p) ){
        recoverWriteDataCleanup(p);
        if( p->zLostAndFound ){
          p->eState = RECOVER_STATE_LOSTANDFOUND1;
        }else{
          p->eState = RECOVER_STATE_SCHEMA2;
        }
      }
      break;
    }

    case RECOVER_STATE_LOSTANDFOUND1: {
      if( p->laf.pUsed==0 ){
        recoverLostAndFound1Init(p);
      }
      if( SQLITE_DONE==recoverLostAndFound1Step(p) ){
        p->eState = RECOVER_STATE_LOSTANDFOUND2;
      }
      break;
    }
    case RECOVER_STATE_LOSTANDFOUND2: {
      if( p->laf.pAllAndParent==0 ){
        recoverLostAndFound2Init(p);
      }
      if( SQLITE_DONE==recoverLostAndFound2Step(p) ){
        p->eState = RECOVER_STATE_LOSTANDFOUND3;
      }
      break;
    }

    case RECOVER_STATE_LOSTANDFOUND3: {
      if( p->laf.pInsert==0 ){
        recoverLostAndFound3Init(p);
      }
      if( SQLITE_DONE==recoverLostAndFound3Step(p) ){
        p->eState = RECOVER_STATE_SCHEMA2;
      }
      break;
    }

    case RECOVER_STATE_SCHEMA2: {
      int rc = SQLITE_OK;

      recoverWriteSchema2(p);
      p->eState = RECOVER_STATE_DONE;

      /* If no error has occurred, commit the write transaction on the output
      ** database. Regardless of whether or not an error has occurred, make
      ** an attempt to end the read transaction on the input database.  */
      recoverExec(p, p->dbOut, "COMMIT");
      rc = sqlite3_exec(p->dbIn, "END", 0, 0, 0);
      if( p->errCode==SQLITE_OK ) p->errCode = rc;

      recoverSqlCallback(p, "PRAGMA writable_schema = off");
      recoverSqlCallback(p, "COMMIT");
      p->eState = RECOVER_STATE_DONE;
      recoverFinalCleanup(p);
      break;
    };

    case RECOVER_STATE_DONE: {
      /* no-op */
      break;
    };
  }
}


/*
** This is a worker function that does the heavy lifting for both init
** functions:
**
**     sqlite3_recover_init()
**     sqlite3_recover_init_sql()
**
** All this function does is allocate space for the recover handle and
** take copies of the input parameters. All the real work is done within
** sqlite3_recover_run().
*/
sqlite3_recover *recoverInit(
  sqlite3* db, 
  const char *zDb, 
  const char *zUri,               /* Output URI for _recover_init() */
  int (*xSql)(void*, const char*),/* SQL callback for _recover_init_sql() */
  void *pSqlCtx                   /* Context arg for _recover_init_sql() */
){
  sqlite3_recover *pRet = 0;
  int nDb = 0;
  int nUri = 0;
  int nByte = 0;

  if( zDb==0 ){ zDb = "main"; }

  nDb = recoverStrlen(zDb);
  nUri = recoverStrlen(zUri);

  nByte = sizeof(sqlite3_recover) + nDb+1 + nUri+1;
  pRet = (sqlite3_recover*)sqlite3_malloc(nByte);
  if( pRet ){
    memset(pRet, 0, nByte);
    pRet->dbIn = db;
    pRet->zDb = (char*)&pRet[1];
    pRet->zUri = &pRet->zDb[nDb+1];
    memcpy(pRet->zDb, zDb, nDb);
    if( nUri>0 && zUri ) memcpy(pRet->zUri, zUri, nUri);
    pRet->xSql = xSql;
    pRet->pSqlCtx = pSqlCtx;
    pRet->bRecoverRowid = RECOVER_ROWID_DEFAULT;
  }

  return pRet;
}

/*
** Initialize a recovery handle that creates a new database containing
** the recovered data.
*/
sqlite3_recover *sqlite3_recover_init(
  sqlite3* db, 
  const char *zDb, 
  const char *zUri
){
  return recoverInit(db, zDb, zUri, 0, 0);
}

/*
** Initialize a recovery handle that returns recovered data in the
** form of SQL statements via a callback.
*/
sqlite3_recover *sqlite3_recover_init_sql(
  sqlite3* db, 
  const char *zDb, 
  int (*xSql)(void*, const char*),
  void *pSqlCtx
){
  return recoverInit(db, zDb, 0, xSql, pSqlCtx);
}

/*
** Return the handle error message, if any.
*/
const char *sqlite3_recover_errmsg(sqlite3_recover *p){
  return (p && p->errCode!=SQLITE_NOMEM) ? p->zErrMsg : "out of memory";
}

/*
** Return the handle error code.
*/
int sqlite3_recover_errcode(sqlite3_recover *p){
  return p ? p->errCode : SQLITE_NOMEM;
}

/*
** Configure the handle.
*/
int sqlite3_recover_config(sqlite3_recover *p, int op, void *pArg){
  int rc = SQLITE_OK;
  if( p==0 ){
    rc = SQLITE_NOMEM;
  }else if( p->eState!=RECOVER_STATE_INIT ){
    rc = SQLITE_MISUSE;
  }else{
    switch( op ){
      case 789:
        /* This undocumented magic configuration option is used to set the
        ** name of the auxiliary database that is ATTACH-ed to the database
        ** connection and used to hold state information during the
        ** recovery process.  This option is for debugging use only and
        ** is subject to change or removal at any time. */
        sqlite3_free(p->zStateDb);
        p->zStateDb = recoverMPrintf(p, "%s", (char*)pArg);
        break;

      case SQLITE_RECOVER_LOST_AND_FOUND: {
        const char *zArg = (const char*)pArg;
        sqlite3_free(p->zLostAndFound);
        if( zArg ){
          p->zLostAndFound = recoverMPrintf(p, "%s", zArg);
        }else{
          p->zLostAndFound = 0;
        }
        break;
      }

      case SQLITE_RECOVER_FREELIST_CORRUPT:
        p->bFreelistCorrupt = *(int*)pArg;
        break;

      case SQLITE_RECOVER_ROWIDS:
        p->bRecoverRowid = *(int*)pArg;
        break;

      case SQLITE_RECOVER_SLOWINDEXES:
        p->bSlowIndexes = *(int*)pArg;
        break;

      default:
        rc = SQLITE_NOTFOUND;
        break;
    }
  }

  return rc;
}

/*
** Do a unit of work towards the recovery job. Return SQLITE_OK if
** no error has occurred but database recovery is not finished, SQLITE_DONE
** if database recovery has been successfully completed, or an SQLite
** error code if an error has occurred.
*/
int sqlite3_recover_step(sqlite3_recover *p){
  if( p==0 ) return SQLITE_NOMEM;
  if( p->errCode==SQLITE_OK ) recoverStep(p);
  if( p->eState==RECOVER_STATE_DONE && p->errCode==SQLITE_OK ){
    return SQLITE_DONE;
  }
  return p->errCode;
}

/*
** Do the configured recovery operation. Return SQLITE_OK if successful, or
** else an SQLite error code.
*/
int sqlite3_recover_run(sqlite3_recover *p){
  while( SQLITE_OK==sqlite3_recover_step(p) );
  return sqlite3_recover_errcode(p);
}


/*
** Free all resources associated with the recover handle passed as the only
** argument. The results of using a handle with any sqlite3_recover_**
** API function after it has been passed to this function are undefined.
**
** A copy of the value returned by the first call made to sqlite3_recover_run()
** on this handle is returned, or SQLITE_OK if sqlite3_recover_run() has
** not been called on this handle.
*/
int sqlite3_recover_finish(sqlite3_recover *p){
  int rc;
  if( p==0 ){
    rc = SQLITE_NOMEM;
  }else{
    recoverFinalCleanup(p);
    if( p->bCloseTransaction && sqlite3_get_autocommit(p->dbIn)==0 ){
      rc = sqlite3_exec(p->dbIn, "END", 0, 0, 0);
      if( p->errCode==SQLITE_OK ) p->errCode = rc;
    }
    rc = p->errCode;
    sqlite3_free(p->zErrMsg);
    sqlite3_free(p->zStateDb);
    sqlite3_free(p->zLostAndFound);
    sqlite3_free(p->pPage1Cache);
    sqlite3_free(p);
  }
  return rc;
}

#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */

Added ext/recover/sqlite3recover.h.


























































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2022-08-27
**
** 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 contains the public interface to the "recover" extension -
** an SQLite extension designed to recover data from corrupted database
** files.
*/

/*
** OVERVIEW:
**
** To use the API to recover data from a corrupted database, an
** application:
**
**   1) Creates an sqlite3_recover handle by calling either
**      sqlite3_recover_init() or sqlite3_recover_init_sql().
**
**   2) Configures the new handle using one or more calls to
**      sqlite3_recover_config().
**
**   3) Executes the recovery by repeatedly calling sqlite3_recover_step() on
**      the handle until it returns something other than SQLITE_OK. If it
**      returns SQLITE_DONE, then the recovery operation completed without 
**      error. If it returns some other non-SQLITE_OK value, then an error 
**      has occurred.
**
**   4) Retrieves any error code and English language error message using the
**      sqlite3_recover_errcode() and sqlite3_recover_errmsg() APIs,
**      respectively.
**
**   5) Destroys the sqlite3_recover handle and frees all resources
**      using sqlite3_recover_finish().
**
** The application may abandon the recovery operation at any point 
** before it is finished by passing the sqlite3_recover handle to
** sqlite3_recover_finish(). This is not an error, but the final state
** of the output database, or the results of running the partial script
** delivered to the SQL callback, are undefined.
*/

#ifndef _SQLITE_RECOVER_H
#define _SQLITE_RECOVER_H

#include "sqlite3.h"

#ifdef __cplusplus
extern "C" {
#endif

/*
** An instance of the sqlite3_recover object represents a recovery
** operation in progress.
**
** Constructors:
**
**    sqlite3_recover_init()
**    sqlite3_recover_init_sql()
**
** Destructor:
**
**    sqlite3_recover_finish()
**
** Methods:
**
**    sqlite3_recover_config()
**    sqlite3_recover_errcode()
**    sqlite3_recover_errmsg()
**    sqlite3_recover_run()
**    sqlite3_recover_step()
*/
typedef struct sqlite3_recover sqlite3_recover;

/* 
** These two APIs attempt to create and return a new sqlite3_recover object.
** In both cases the first two arguments identify the (possibly
** corrupt) database to recover data from. The first argument is an open
** database handle and the second the name of a database attached to that
** handle (i.e. "main", "temp" or the name of an attached database).
**
** If sqlite3_recover_init() is used to create the new sqlite3_recover
** handle, then data is recovered into a new database, identified by
** string parameter zUri. zUri may be an absolute or relative file path,
** or may be an SQLite URI. If the identified database file already exists,
** it is overwritten.
**
** If sqlite3_recover_init_sql() is invoked, then any recovered data will
** be returned to the user as a series of SQL statements. Executing these
** SQL statements results in the same database as would have been created
** had sqlite3_recover_init() been used. For each SQL statement in the
** output, the callback function passed as the third argument (xSql) is 
** invoked once. The first parameter is a passed a copy of the fourth argument
** to this function (pCtx) as its first parameter, and a pointer to a
** nul-terminated buffer containing the SQL statement formated as UTF-8 as 
** the second. If the xSql callback returns any value other than SQLITE_OK,
** then processing is immediately abandoned and the value returned used as
** the recover handle error code (see below).
**
** If an out-of-memory error occurs, NULL may be returned instead of
** a valid handle. In all other cases, it is the responsibility of the
** application to avoid resource leaks by ensuring that
** sqlite3_recover_finish() is called on all allocated handles.
*/
sqlite3_recover *sqlite3_recover_init(
  sqlite3* db, 
  const char *zDb, 
  const char *zUri
);
sqlite3_recover *sqlite3_recover_init_sql(
  sqlite3* db, 
  const char *zDb, 
  int (*xSql)(void*, const char*),
  void *pCtx
);

/*
** Configure an sqlite3_recover object that has just been created using
** sqlite3_recover_init() or sqlite3_recover_init_sql(). This function
** may only be called before the first call to sqlite3_recover_step()
** or sqlite3_recover_run() on the object.
**
** The second argument passed to this function must be one of the
** SQLITE_RECOVER_* symbols defined below. Valid values for the third argument
** depend on the specific SQLITE_RECOVER_* symbol in use.
**
** SQLITE_OK is returned if the configuration operation was successful,
** or an SQLite error code otherwise.
*/
int sqlite3_recover_config(sqlite3_recover*, int op, void *pArg);

/*
** SQLITE_RECOVER_LOST_AND_FOUND:
**   The pArg argument points to a string buffer containing the name
**   of a "lost-and-found" table in the output database, or NULL. If
**   the argument is non-NULL and the database contains seemingly
**   valid pages that cannot be associated with any table in the
**   recovered part of the schema, data is extracted from these
**   pages to add to the lost-and-found table.
**
** SQLITE_RECOVER_FREELIST_CORRUPT:
**   The pArg value must actually be a pointer to a value of type
**   int containing value 0 or 1 cast as a (void*). If this option is set
**   (argument is 1) and a lost-and-found table has been configured using
**   SQLITE_RECOVER_LOST_AND_FOUND, then is assumed that the freelist is 
**   corrupt and an attempt is made to recover records from pages that
**   appear to be linked into the freelist. Otherwise, pages on the freelist
**   are ignored. Setting this option can recover more data from the
**   database, but often ends up "recovering" deleted records. The default 
**   value is 0 (clear).
**
** SQLITE_RECOVER_ROWIDS:
**   The pArg value must actually be a pointer to a value of type
**   int containing value 0 or 1 cast as a (void*). If this option is set
**   (argument is 1), then an attempt is made to recover rowid values
**   that are not also INTEGER PRIMARY KEY values. If this option is
**   clear, then new rowids are assigned to all recovered rows. The
**   default value is 1 (set).
**
** SQLITE_RECOVER_SLOWINDEXES:
**   The pArg value must actually be a pointer to a value of type
**   int containing value 0 or 1 cast as a (void*). If this option is clear
**   (argument is 0), then when creating an output database, the recover 
**   module creates and populates non-UNIQUE indexes right at the end of the
**   recovery operation - after all recoverable data has been inserted
**   into the new database. This is faster overall, but means that the
**   final call to sqlite3_recover_step() for a recovery operation may
**   be need to create a large number of indexes, which may be very slow.
**
**   Or, if this option is set (argument is 1), then non-UNIQUE indexes
**   are created in the output database before it is populated with 
**   recovered data. This is slower overall, but avoids the slow call
**   to sqlite3_recover_step() at the end of the recovery operation.
**
**   The default option value is 0.
*/
#define SQLITE_RECOVER_LOST_AND_FOUND   1
#define SQLITE_RECOVER_FREELIST_CORRUPT 2
#define SQLITE_RECOVER_ROWIDS           3
#define SQLITE_RECOVER_SLOWINDEXES      4

/*
** Perform a unit of work towards the recovery operation. This function 
** must normally be called multiple times to complete database recovery.
**
** If no error occurs but the recovery operation is not completed, this
** function returns SQLITE_OK. If recovery has been completed successfully
** then SQLITE_DONE is returned. If an error has occurred, then an SQLite
** error code (e.g. SQLITE_IOERR or SQLITE_NOMEM) is returned. It is not
** considered an error if some or all of the data cannot be recovered
** due to database corruption.
**
** Once sqlite3_recover_step() has returned a value other than SQLITE_OK,
** all further such calls on the same recover handle are no-ops that return
** the same non-SQLITE_OK value.
*/
int sqlite3_recover_step(sqlite3_recover*);

/* 
** Run the recovery operation to completion. Return SQLITE_OK if successful,
** or an SQLite error code otherwise. Calling this function is the same
** as executing:
**
**     while( SQLITE_OK==sqlite3_recover_step(p) );
**     return sqlite3_recover_errcode(p);
*/
int sqlite3_recover_run(sqlite3_recover*);

/*
** If an error has been encountered during a prior call to
** sqlite3_recover_step(), then this function attempts to return a 
** pointer to a buffer containing an English language explanation of 
** the error. If no error message is available, or if an out-of memory 
** error occurs while attempting to allocate a buffer in which to format
** the error message, NULL is returned.
**
** The returned buffer remains valid until the sqlite3_recover handle is
** destroyed using sqlite3_recover_finish().
*/
const char *sqlite3_recover_errmsg(sqlite3_recover*);

/*
** If this function is called on an sqlite3_recover handle after
** an error occurs, an SQLite error code is returned. Otherwise, SQLITE_OK.
*/
int sqlite3_recover_errcode(sqlite3_recover*);

/* 
** Clean up a recovery object created by a call to sqlite3_recover_init().
** The results of using a recovery object with any API after it has been
** passed to this function are undefined.
**
** This function returns the same value as sqlite3_recover_errcode().
*/
int sqlite3_recover_finish(sqlite3_recover*);


#ifdef __cplusplus
}  /* end of the 'extern "C"' block */
#endif

#endif /* ifndef _SQLITE_RECOVER_H */

Added ext/recover/test_recover.c.
























































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2022-08-27
**
** 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.
**
*************************************************************************
**
*/

#include "sqlite3recover.h"
#include "sqliteInt.h"

#include <tcl.h>
#include <assert.h>

#ifndef SQLITE_OMIT_VIRTUALTABLE

typedef struct TestRecover TestRecover;
struct TestRecover {
  sqlite3_recover *p;
  Tcl_Interp *interp;
  Tcl_Obj *pScript;
};

static int xSqlCallback(void *pSqlArg, const char *zSql){
  TestRecover *p = (TestRecover*)pSqlArg;
  Tcl_Obj *pEval = 0;
  int res = 0;

  pEval = Tcl_DuplicateObj(p->pScript);
  Tcl_IncrRefCount(pEval);

  res = Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewStringObj(zSql, -1));
  if( res==TCL_OK ){
    res = Tcl_EvalObjEx(p->interp, pEval, 0);
  }

  Tcl_DecrRefCount(pEval);
  if( res ){
    Tcl_BackgroundError(p->interp);
    return TCL_ERROR;
  }else{
    Tcl_Obj *pObj = Tcl_GetObjResult(p->interp);
    if( Tcl_GetCharLength(pObj)==0 ){
      res = 0;
    }else if( Tcl_GetIntFromObj(p->interp, pObj, &res) ){
      Tcl_BackgroundError(p->interp);
      return TCL_ERROR;
    }
  }
  return res;
}

static int getDbPointer(Tcl_Interp *interp, Tcl_Obj *pObj, sqlite3 **pDb){
  Tcl_CmdInfo info;
  if( 0==Tcl_GetCommandInfo(interp, Tcl_GetString(pObj), &info) ){
    Tcl_AppendResult(interp, "no such handle: ", Tcl_GetString(pObj), 0);
    return TCL_ERROR;
  }
  *pDb = *(sqlite3 **)info.objClientData;
  return TCL_OK;
}

/*
** Implementation of the command created by [sqlite3_recover_init]:
**
**     $cmd config OP ARG
**     $cmd run
**     $cmd errmsg
**     $cmd errcode
**     $cmd finalize
*/
static int testRecoverCmd(
  void *clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  static struct RecoverSub {
    const char *zSub;
    int nArg;
    const char *zMsg;
  } aSub[] = {
    { "config",    2, "ARG"         }, /* 0 */
    { "run",      0, ""             }, /* 1 */
    { "errmsg",    0, ""            }, /* 2 */
    { "errcode",   0, ""            }, /* 3 */
    { "finish",  0, ""              }, /* 4 */
    { "step",  0, ""                }, /* 5 */
    { 0 }
  };
  int rc = TCL_OK;
  int iSub = 0;
  TestRecover *pTest = (TestRecover*)clientData;

  if( objc<2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
    return TCL_ERROR;
  }
  rc = Tcl_GetIndexFromObjStruct(interp, 
      objv[1], aSub, sizeof(aSub[0]), "sub-command", 0, &iSub
  );
  if( rc!=TCL_OK ) return rc;
  if( (objc-2)!=aSub[iSub].nArg ){
    Tcl_WrongNumArgs(interp, 2, objv, aSub[iSub].zMsg);
    return TCL_ERROR;
  }

  switch( iSub ){
    case 0:  assert( sqlite3_stricmp("config", aSub[iSub].zSub)==0 ); {
      const char *aOp[] = {
        "testdb",          /* 0 */
        "lostandfound",    /* 1 */
        "freelistcorrupt", /* 2 */
        "rowids",          /* 3 */
        "slowindexes",     /* 4 */
        "invalid",         /* 5 */
        0
      };
      int iOp = 0;
      int res = 0;
      if( Tcl_GetIndexFromObj(interp, objv[2], aOp, "option", 0, &iOp) ){
        return TCL_ERROR;
      }
      switch( iOp ){
        case 0:
          res = sqlite3_recover_config(pTest->p, 
              789, (void*)Tcl_GetString(objv[3]) /* MAGIC NUMBER! */
          );
          break;
        case 1: {
          const char *zStr = Tcl_GetString(objv[3]);
          res = sqlite3_recover_config(pTest->p, 
              SQLITE_RECOVER_LOST_AND_FOUND, (void*)(zStr[0] ? zStr : 0)
          );
          break;
        }
        case 2: {
          int iVal = 0;
          if( Tcl_GetBooleanFromObj(interp, objv[3], &iVal) ) return TCL_ERROR;
          res = sqlite3_recover_config(pTest->p, 
              SQLITE_RECOVER_FREELIST_CORRUPT, (void*)&iVal
          );
          break;
        }
        case 3: {
          int iVal = 0;
          if( Tcl_GetBooleanFromObj(interp, objv[3], &iVal) ) return TCL_ERROR;
          res = sqlite3_recover_config(pTest->p, 
              SQLITE_RECOVER_ROWIDS, (void*)&iVal
          );
          break;
        }
        case 4: {
          int iVal = 0;
          if( Tcl_GetBooleanFromObj(interp, objv[3], &iVal) ) return TCL_ERROR;
          res = sqlite3_recover_config(pTest->p, 
              SQLITE_RECOVER_SLOWINDEXES, (void*)&iVal
          );
          break;
        }
        case 5: {
          res = sqlite3_recover_config(pTest->p, 12345, 0);
          break;
        }
      }
      Tcl_SetObjResult(interp, Tcl_NewIntObj(res));
      break;
    }
    case 1:  assert( sqlite3_stricmp("run", aSub[iSub].zSub)==0 ); {
      int res = sqlite3_recover_run(pTest->p);
      Tcl_SetObjResult(interp, Tcl_NewIntObj(res));
      break;
    }
    case 2:  assert( sqlite3_stricmp("errmsg", aSub[iSub].zSub)==0 ); {
      const char *zErr = sqlite3_recover_errmsg(pTest->p);
      Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1));
      break;
    }
    case 3:  assert( sqlite3_stricmp("errcode", aSub[iSub].zSub)==0 ); {
      int errCode = sqlite3_recover_errcode(pTest->p);
      Tcl_SetObjResult(interp, Tcl_NewIntObj(errCode));
      break;
    }
    case 4:  assert( sqlite3_stricmp("finish", aSub[iSub].zSub)==0 ); {
      int res = sqlite3_recover_errcode(pTest->p);
      int res2;
      if( res!=SQLITE_OK ){
        const char *zErr = sqlite3_recover_errmsg(pTest->p);
        Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1));
      }
      res2 = sqlite3_recover_finish(pTest->p);
      assert( res2==res );
      if( res ) return TCL_ERROR;
      break;
    }
    case 5:  assert( sqlite3_stricmp("step", aSub[iSub].zSub)==0 ); {
      int res = sqlite3_recover_step(pTest->p);
      Tcl_SetObjResult(interp, Tcl_NewIntObj(res));
      break;
    }
  }

  return TCL_OK;
}

/*
** sqlite3_recover_init DB DBNAME URI
*/
static int test_sqlite3_recover_init(
  void *clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  static int iTestRecoverCmd = 1;

  TestRecover *pNew = 0;
  sqlite3 *db = 0;
  const char *zDb = 0;
  const char *zUri = 0;
  char zCmd[128];
  int bSql = clientData ? 1 : 0;

  if( objc!=4 ){
    const char *zErr = (bSql ? "DB DBNAME SCRIPT" : "DB DBNAME URI");
    Tcl_WrongNumArgs(interp, 1, objv, zErr);
    return TCL_ERROR;
  }
  if( getDbPointer(interp, objv[1], &db) ) return TCL_ERROR;
  zDb = Tcl_GetString(objv[2]);
  if( zDb[0]=='\0' ) zDb = 0;

  pNew = ckalloc(sizeof(TestRecover));
  if( bSql==0 ){
    zUri = Tcl_GetString(objv[3]);
    pNew->p = sqlite3_recover_init(db, zDb, zUri);
  }else{
    pNew->interp = interp;
    pNew->pScript = objv[3];
    Tcl_IncrRefCount(pNew->pScript);
    pNew->p = sqlite3_recover_init_sql(db, zDb, xSqlCallback, (void*)pNew);
  }

  sprintf(zCmd, "sqlite_recover%d", iTestRecoverCmd++);
  Tcl_CreateObjCommand(interp, zCmd, testRecoverCmd, (void*)pNew, 0);

  Tcl_SetObjResult(interp, Tcl_NewStringObj(zCmd, -1));
  return TCL_OK;
}

/*
** Declaration for public API function in file dbdata.c. This may be called
** with NULL as the final two arguments to register the sqlite_dbptr and
** sqlite_dbdata virtual tables with a database handle.
*/
#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_dbdata_init(sqlite3*, char**, const sqlite3_api_routines*);

/*
** sqlite3_recover_init DB DBNAME URI
*/
static int test_sqlite3_dbdata_init(
  void *clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  sqlite3 *db = 0;

  if( objc!=2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "DB");
    return TCL_ERROR;
  }
  if( getDbPointer(interp, objv[1], &db) ) return TCL_ERROR;
  sqlite3_dbdata_init(db, 0, 0);

  Tcl_ResetResult(interp);
  return TCL_OK;
}

#endif /* SQLITE_OMIT_VIRTUALTABLE */

int TestRecover_Init(Tcl_Interp *interp){
#ifndef SQLITE_OMIT_VIRTUALTABLE
  struct Cmd {
    const char *zCmd;
    Tcl_ObjCmdProc *xProc;
    void *pArg;
  } aCmd[] = {
    { "sqlite3_recover_init", test_sqlite3_recover_init, 0 },
    { "sqlite3_recover_init_sql", test_sqlite3_recover_init, (void*)1 },
    { "sqlite3_dbdata_init", test_sqlite3_dbdata_init, (void*)1 },
  };
  int i;

  for(i=0; i<sizeof(aCmd)/sizeof(struct Cmd); i++){
    struct Cmd *p = &aCmd[i];
    Tcl_CreateObjCommand(interp, p->zCmd, p->xProc, p->pArg, 0);
  }
#endif
  return TCL_OK;
}

Changes to ext/repair/checkfreelist.c.

40
41
42
43
44
45
46




47
48









49
50
51
52
53
54
55
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







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







SQLITE_EXTENSION_INIT1

#ifndef SQLITE_AMALGAMATION
# include <string.h>
# include <stdio.h>
# include <stdlib.h>
# include <assert.h>
# if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
#   define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1
# endif
# if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
# define ALWAYS(X)  1
# define NEVER(X)   0
#   define ALWAYS(X)      (1)
#   define NEVER(X)       (0)
# elif !defined(NDEBUG)
#   define ALWAYS(X)      ((X)?1:(assert(0),0))
#   define NEVER(X)       ((X)?(assert(0),1):0)
# else
#   define ALWAYS(X)      (X)
#   define NEVER(X)       (X)
# endif
  typedef unsigned char u8;
  typedef unsigned short u16;
  typedef unsigned int u32;
#define get4byte(x) (        \
    ((u32)((x)[0])<<24) +    \
    ((u32)((x)[1])<<16) +    \
    ((u32)((x)[2])<<8) +     \

Changes to ext/repair/checkindex.c.

469
470
471
472
473
474
475
476

477
478
479
480
481
482
483
469
470
471
472
473
474
475

476
477
478
479
480
481
482
483







-
+







  CidxIndex *pIdx = 0;

  sqlite3_stmt *pFindTab = 0;
  sqlite3_stmt *pInfo = 0;
    
  /* Find the table for this index. */
  pFindTab = cidxPrepare(&rc, pCsr, 
      "SELECT tbl_name, sql FROM sqlite_master WHERE name=%Q AND type='index'",
      "SELECT tbl_name, sql FROM sqlite_schema WHERE name=%Q AND type='index'",
      zIdx
  );
  if( rc==SQLITE_OK && sqlite3_step(pFindTab)==SQLITE_ROW ){
    const char *zSql = (const char*)sqlite3_column_text(pFindTab, 1);
    zTab = cidxStrdup(&rc, (const char*)sqlite3_column_text(pFindTab, 0));

    pInfo = cidxPrepare(&rc, pCsr, "PRAGMA index_xinfo(%Q)", zIdx);

Changes to ext/repair/sqlite3_checker.c.in.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13






-







/*
** Read an SQLite database file and analyze its space utilization.  Generate
** text on standard output.
*/
#define TCLSH_INIT_PROC sqlite3_checker_init_proc
#define SQLITE_ENABLE_DBPAGE_VTAB 1
#define SQLITE_ENABLE_JSON1 1
#undef SQLITE_THREADSAFE
#define SQLITE_THREADSAFE 0
#undef SQLITE_ENABLE_COLUMN_METADATA
#define SQLITE_OMIT_DECLTYPE 1
#define SQLITE_OMIT_DEPRECATED 1
#define SQLITE_OMIT_PROGRESS_CALLBACK 1
#define SQLITE_OMIT_SHARED_CACHE 1

Changes to ext/rtree/geopoly.c.

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







-
-
+
-
-
-














+







#ifdef GEOPOLY_ENABLE_DEBUG
  static int geo_debug = 0;
# define GEODEBUG(X) if(geo_debug)printf X
#else
# define GEODEBUG(X)
#endif

#ifndef JSON_NULL   /* The following stuff repeats things found in json1 */
/*
/* Character class routines */
** Versions of isspace(), isalnum() and isdigit() to which it is safe
** to pass signed char values.
*/
#ifdef sqlite3Isdigit
   /* Use the SQLite core versions if this routine is part of the
   ** SQLite amalgamation */
#  define safe_isdigit(x)  sqlite3Isdigit(x)
#  define safe_isalnum(x)  sqlite3Isalnum(x)
#  define safe_isxdigit(x) sqlite3Isxdigit(x)
#else
   /* Use the standard library for separate compilation */
#include <ctype.h>  /* amalgamator: keep */
#  define safe_isdigit(x)  isdigit((unsigned char)(x))
#  define safe_isalnum(x)  isalnum((unsigned char)(x))
#  define safe_isxdigit(x) isxdigit((unsigned char)(x))
#endif

#ifndef JSON_NULL   /* The following stuff repeats things found in json1 */
/*
** Growing our own isspace() routine this way is twice as fast as
** the library isspace() function.
*/
static const char geopolyIsSpace[] = {
  0, 0, 0, 0, 0, 0, 0, 0,     0, 1, 1, 0, 0, 1, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
63
64
65
66
67
68
69
70

71
72
73
74
75
76
77
60
61
62
63
64
65
66

67
68
69
70
71
72
73
74







-
+







  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
};
#define safe_isspace(x) (geopolyIsSpace[(unsigned char)x])
#define fast_isspace(x) (geopolyIsSpace[(unsigned char)x])
#endif /* JSON NULL - back to original code */

/* Compiler and version */
#ifndef GCC_VERSION
#if defined(__GNUC__) && !defined(SQLITE_DISABLE_INTRINSIC)
# define GCC_VERSION (__GNUC__*1000000+__GNUC_MINOR__*1000+__GNUC_PATCHLEVEL__)
#else
119
120
121
122
123
124
125








126
127
128
129
130
131
132
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137







+
+
+
+
+
+
+
+







  GeoCoord a[8];        /* 2*nVertex values. X (longitude) first, then Y */
};

/* The size of a memory allocation needed for a GeoPoly object sufficient
** to hold N coordinate pairs.
*/
#define GEOPOLY_SZ(N)  (sizeof(GeoPoly) + sizeof(GeoCoord)*2*((N)-4))

/* Macros to access coordinates of a GeoPoly.
** We have to use these macros, rather than just say p->a[i] in order
** to silence (incorrect) UBSAN warnings if the array index is too large.
*/
#define GeoX(P,I)  (((GeoCoord*)(P)->a)[(I)*2])
#define GeoY(P,I)  (((GeoCoord*)(P)->a)[(I)*2+1])


/*
** State of a parse of a GeoJSON input.
*/
typedef struct GeoParse GeoParse;
struct GeoParse {
  const unsigned char *z;   /* Unparsed input */
144
145
146
147
148
149
150
151

152
153
154
155
156
157
158
149
150
151
152
153
154
155

156
157
158
159
160
161
162
163







-
+







  t = a[1];
  a[1] = a[2];
  a[2] = t;
}

/* Skip whitespace.  Return the next non-whitespace character. */
static char geopolySkipSpace(GeoParse *p){
  while( safe_isspace(p->z[0]) ) p->z++;
  while( fast_isspace(p->z[0]) ) p->z++;
  return p->z[0];
}

/* Parse out a number.  Write the value into *pVal if pVal!=0.
** return non-zero on success and zero if the next token is not a number.
*/
static int geopolyParseNumber(GeoParse *p, GeoCoord *pVal){
257
258
259
260
261
262
263
264

265
266
267
268
269
270
271
262
263
264
265
266
267
268

269
270
271
272
273
274
275
276







-
+







     && s.a[0]==s.a[s.nVertex*2-2]
     && s.a[1]==s.a[s.nVertex*2-1]
     && (s.z++, geopolySkipSpace(&s)==0)
    ){
      GeoPoly *pOut;
      int x = 1;
      s.nVertex--;  /* Remove the redundant vertex at the end */
      pOut = sqlite3_malloc64( GEOPOLY_SZ(s.nVertex) );
      pOut = sqlite3_malloc64( GEOPOLY_SZ((sqlite3_int64)s.nVertex) );
      x = 1;
      if( pOut==0 ) goto parse_json_err;
      pOut->nVertex = s.nVertex;
      memcpy(pOut->a, s.a, s.nVertex*2*sizeof(GeoCoord));
      pOut->hdr[0] = *(unsigned char*)&x;
      pOut->hdr[1] = (s.nVertex>>16)&0xff;
      pOut->hdr[2] = (s.nVertex>>8)&0xff;
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
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







+

-
+



+
+
+
+














-
-
+
+
+







static GeoPoly *geopolyFuncParam(
  sqlite3_context *pCtx,      /* Context for error messages */
  sqlite3_value *pVal,        /* The value to decode */
  int *pRc                    /* Write error here */
){
  GeoPoly *p = 0;
  int nByte;
  testcase( pCtx==0 );
  if( sqlite3_value_type(pVal)==SQLITE_BLOB
   && (nByte = sqlite3_value_bytes(pVal))>=(4+6*sizeof(GeoCoord))
   && (nByte = sqlite3_value_bytes(pVal))>=(int)(4+6*sizeof(GeoCoord))
  ){
    const unsigned char *a = sqlite3_value_blob(pVal);
    int nVertex;
    if( a==0 ){
      if( pCtx ) sqlite3_result_error_nomem(pCtx);
      return 0;
    }
    nVertex = (a[1]<<16) + (a[2]<<8) + a[3];
    if( (a[0]==0 || a[0]==1)
     && (nVertex*2*sizeof(GeoCoord) + 4)==(unsigned int)nByte
    ){
      p = sqlite3_malloc64( sizeof(*p) + (nVertex-1)*2*sizeof(GeoCoord) );
      if( p==0 ){
        if( pRc ) *pRc = SQLITE_NOMEM;
        if( pCtx ) sqlite3_result_error_nomem(pCtx);
      }else{
        int x = 1;
        p->nVertex = nVertex;
        memcpy(p->hdr, a, nByte);
        if( a[0] != *(unsigned char*)&x ){
          int ii;
          for(ii=0; ii<nVertex*2; ii++){
            geopolySwab32((unsigned char*)&p->a[ii]);
          for(ii=0; ii<nVertex; ii++){
            geopolySwab32((unsigned char*)&GeoX(p,ii));
            geopolySwab32((unsigned char*)&GeoY(p,ii));
          }
          p->hdr[0] ^= 1;
        }
      }
    }
    if( pRc ) *pRc = SQLITE_OK;
    return p;
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
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







+



















+






-
+

-
+
















+
+
-
+







-
+


-
+







*/
static void geopolyBlobFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  GeoPoly *p = geopolyFuncParam(context, argv[0], 0);
  (void)argc;
  if( p ){
    sqlite3_result_blob(context, p->hdr, 
       4+8*p->nVertex, SQLITE_TRANSIENT);
    sqlite3_free(p);
  }
}

/*
** SQL function:     geopoly_json(X)
**
** Interpret X as a polygon and render it as a JSON array
** of coordinates.  Or, if X is not a valid polygon, return NULL.
*/
static void geopolyJsonFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  GeoPoly *p = geopolyFuncParam(context, argv[0], 0);
  (void)argc;
  if( p ){
    sqlite3 *db = sqlite3_context_db_handle(context);
    sqlite3_str *x = sqlite3_str_new(db);
    int i;
    sqlite3_str_append(x, "[", 1);
    for(i=0; i<p->nVertex; i++){
      sqlite3_str_appendf(x, "[%!g,%!g],", p->a[i*2], p->a[i*2+1]);
      sqlite3_str_appendf(x, "[%!g,%!g],", GeoX(p,i), GeoY(p,i));
    }
    sqlite3_str_appendf(x, "[%!g,%!g]]", p->a[0], p->a[1]);
    sqlite3_str_appendf(x, "[%!g,%!g]]", GeoX(p,0), GeoY(p,0));
    sqlite3_result_text(context, sqlite3_str_finish(x), -1, sqlite3_free);
    sqlite3_free(p);
  }
}

/*
** SQL function:     geopoly_svg(X, ....)
**
** Interpret X as a polygon and render it as a SVG <polyline>.
** Additional arguments are added as attributes to the <polyline>.
*/
static void geopolySvgFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  GeoPoly *p;
  if( argc<1 ) return;
  GeoPoly *p = geopolyFuncParam(context, argv[0], 0);
  p = geopolyFuncParam(context, argv[0], 0);
  if( p ){
    sqlite3 *db = sqlite3_context_db_handle(context);
    sqlite3_str *x = sqlite3_str_new(db);
    int i;
    char cSep = '\'';
    sqlite3_str_appendf(x, "<polyline points=");
    for(i=0; i<p->nVertex; i++){
      sqlite3_str_appendf(x, "%c%g,%g", cSep, p->a[i*2], p->a[i*2+1]);
      sqlite3_str_appendf(x, "%c%g,%g", cSep, GeoX(p,i), GeoY(p,i));
      cSep = ' ';
    }
    sqlite3_str_appendf(x, " %g,%g'", p->a[0], p->a[1]);
    sqlite3_str_appendf(x, " %g,%g'", GeoX(p,0), GeoY(p,0));
    for(i=1; i<argc; i++){
      const char *z = (const char*)sqlite3_value_text(argv[i]);
      if( z && z[0] ){
        sqlite3_str_appendf(x, " %s", z);
      }
    }
    sqlite3_str_appendf(x, "></polyline>");
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
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







+


-
-
+
+


-
-
+
+


















-
-
+
+


-
-
+
+


















+







  double B = sqlite3_value_double(argv[2]);
  double C = sqlite3_value_double(argv[3]);
  double D = sqlite3_value_double(argv[4]);
  double E = sqlite3_value_double(argv[5]);
  double F = sqlite3_value_double(argv[6]);
  GeoCoord x1, y1, x0, y0;
  int ii;
  (void)argc;
  if( p ){
    for(ii=0; ii<p->nVertex; ii++){
      x0 = p->a[ii*2];
      y0 = p->a[ii*2+1];
      x0 = GeoX(p,ii);
      y0 = GeoY(p,ii);
      x1 = (GeoCoord)(A*x0 + B*y0 + E);
      y1 = (GeoCoord)(C*x0 + D*y0 + F);
      p->a[ii*2] = x1;
      p->a[ii*2+1] = y1;
      GeoX(p,ii) = x1;
      GeoY(p,ii) = y1;
    }
    sqlite3_result_blob(context, p->hdr, 
       4+8*p->nVertex, SQLITE_TRANSIENT);
    sqlite3_free(p);
  }
}

/*
** Compute the area enclosed by the polygon.
**
** This routine can also be used to detect polygons that rotate in
** the wrong direction.  Polygons are suppose to be counter-clockwise (CCW).
** This routine returns a negative value for clockwise (CW) polygons.
*/
static double geopolyArea(GeoPoly *p){
  double rArea = 0.0;
  int ii;
  for(ii=0; ii<p->nVertex-1; ii++){
    rArea += (p->a[ii*2] - p->a[ii*2+2])           /* (x0 - x1) */
              * (p->a[ii*2+1] + p->a[ii*2+3])      /* (y0 + y1) */
    rArea += (GeoX(p,ii) - GeoX(p,ii+1))           /* (x0 - x1) */
              * (GeoY(p,ii) + GeoY(p,ii+1))        /* (y0 + y1) */
              * 0.5;
  }
  rArea += (p->a[ii*2] - p->a[0])                  /* (xN - x0) */
           * (p->a[ii*2+1] + p->a[1])              /* (yN + y0) */
  rArea += (GeoX(p,ii) - GeoX(p,0))                /* (xN - x0) */
           * (GeoY(p,ii) + GeoY(p,0))              /* (yN + y0) */
           * 0.5;
  return rArea;
}

/*
** Implementation of the geopoly_area(X) function.
**
** If the input is a well-formed Geopoly BLOB then return the area
** enclosed by the polygon.  If the polygon circulates clockwise instead
** of counterclockwise (as it should) then return the negative of the
** enclosed area.  Otherwise return NULL.
*/
static void geopolyAreaFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  GeoPoly *p = geopolyFuncParam(context, argv[0], 0);
  (void)argc;
  if( p ){
    sqlite3_result_double(context, geopolyArea(p));
    sqlite3_free(p);
  }            
}

/*
520
521
522
523
524
525
526

527
528
529
530
531
532
533
534
535
536







537
538
539
540
541
542
543
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







+



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







*/
static void geopolyCcwFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  GeoPoly *p = geopolyFuncParam(context, argv[0], 0);
  (void)argc;
  if( p ){
    if( geopolyArea(p)<0.0 ){
      int ii, jj;
      for(ii=2, jj=p->nVertex*2 - 2; ii<jj; ii+=2, jj-=2){
        GeoCoord t = p->a[ii];
        p->a[ii] = p->a[jj];
        p->a[jj] = t;
        t = p->a[ii+1];
        p->a[ii+1] = p->a[jj+1];
        p->a[jj+1] = t;
      for(ii=1, jj=p->nVertex-1; ii<jj; ii++, jj--){
        GeoCoord t = GeoX(p,ii);
        GeoX(p,ii) = GeoX(p,jj);
        GeoX(p,jj) = t;
        t = GeoY(p,ii);
        GeoY(p,ii) = GeoY(p,jj);
        GeoY(p,jj) = t;
      }
    }
    sqlite3_result_blob(context, p->hdr, 
       4+8*p->nVertex, SQLITE_TRANSIENT);
    sqlite3_free(p);
  }            
}
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
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







+















-
-
+
+







){
  double x = sqlite3_value_double(argv[0]);
  double y = sqlite3_value_double(argv[1]);
  double r = sqlite3_value_double(argv[2]);
  int n = sqlite3_value_int(argv[3]);
  int i;
  GeoPoly *p;
  (void)argc;

  if( n<3 || r<=0.0 ) return;
  if( n>1000 ) n = 1000;
  p = sqlite3_malloc64( sizeof(*p) + (n-1)*2*sizeof(GeoCoord) );
  if( p==0 ){
    sqlite3_result_error_nomem(context);
    return;
  }
  i = 1;
  p->hdr[0] = *(unsigned char*)&i;
  p->hdr[1] = 0;
  p->hdr[2] = (n>>8)&0xff;
  p->hdr[3] = n&0xff;
  for(i=0; i<n; i++){
    double rAngle = 2.0*GEOPOLY_PI*i/n;
    p->a[i*2] = x - r*geopolySine(rAngle-0.5*GEOPOLY_PI);
    p->a[i*2+1] = y + r*geopolySine(rAngle);
    GeoX(p,i) = x - r*geopolySine(rAngle-0.5*GEOPOLY_PI);
    GeoY(p,i) = y + r*geopolySine(rAngle);
  }
  sqlite3_result_blob(context, p->hdr, 4+8*n, SQLITE_TRANSIENT);
  sqlite3_free(p);
}

/*
** If pPoly is a polygon, compute its bounding box. Then:
627
628
629
630
631
632
633
634
635


636
637

638
639
640

641
642
643
644
645
646
647

648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667








668
669
670
671
672
673
674


675
676
677
678
679
680
681
682
683
684
685
686
687

688
689
690
691
692
693
694
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







-
-
+
+

-
+


-
+






-
+












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







+
+













+







    mxY = aCoord[3].f;
    goto geopolyBboxFill;
  }else{
    p = geopolyFuncParam(context, pPoly, pRc);
  }
  if( p ){
    int ii;
    mnX = mxX = p->a[0];
    mnY = mxY = p->a[1];
    mnX = mxX = GeoX(p,0);
    mnY = mxY = GeoY(p,0);
    for(ii=1; ii<p->nVertex; ii++){
      double r = p->a[ii*2];
      double r = GeoX(p,ii);
      if( r<mnX ) mnX = (float)r;
      else if( r>mxX ) mxX = (float)r;
      r = p->a[ii*2+1];
      r = GeoY(p,ii);
      if( r<mnY ) mnY = (float)r;
      else if( r>mxY ) mxY = (float)r;
    }
    if( pRc ) *pRc = SQLITE_OK;
    if( aCoord==0 ){
      geopolyBboxFill:
      pOut = sqlite3_realloc(p, GEOPOLY_SZ(4));
      pOut = sqlite3_realloc64(p, GEOPOLY_SZ(4));
      if( pOut==0 ){
        sqlite3_free(p);
        if( context ) sqlite3_result_error_nomem(context);
        if( pRc ) *pRc = SQLITE_NOMEM;
        return 0;
      }
      pOut->nVertex = 4;
      ii = 1;
      pOut->hdr[0] = *(unsigned char*)&ii;
      pOut->hdr[1] = 0;
      pOut->hdr[2] = 0;
      pOut->hdr[3] = 4;
      pOut->a[0] = mnX;
      pOut->a[1] = mnY;
      pOut->a[2] = mxX;
      pOut->a[3] = mnY;
      pOut->a[4] = mxX;
      pOut->a[5] = mxY;
      pOut->a[6] = mnX;
      pOut->a[7] = mxY;
      GeoX(pOut,0) = mnX;
      GeoY(pOut,0) = mnY;
      GeoX(pOut,1) = mxX;
      GeoY(pOut,1) = mnY;
      GeoX(pOut,2) = mxX;
      GeoY(pOut,2) = mxY;
      GeoX(pOut,3) = mnX;
      GeoY(pOut,3) = mxY;
    }else{
      sqlite3_free(p);
      aCoord[0].f = mnX;
      aCoord[1].f = mxX;
      aCoord[2].f = mnY;
      aCoord[3].f = mxY;
    }
  }else if( aCoord ){
    memset(aCoord, 0, sizeof(RtreeCoord)*4);
  }
  return pOut;
}

/*
** Implementation of the geopoly_bbox(X) SQL function.
*/
static void geopolyBBoxFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  GeoPoly *p = geopolyBBox(context, argv[0], 0, 0);
  (void)argc;
  if( p ){
    sqlite3_result_blob(context, p->hdr, 
       4+8*p->nVertex, SQLITE_TRANSIENT);
    sqlite3_free(p);
  }
}

708
709
710
711
712
713
714

715
716
717
718
719
720
721
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744







+







static void geopolyBBoxStep(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  RtreeCoord a[4];
  int rc = SQLITE_OK;
  (void)argc;
  (void)geopolyBBox(context, argv[0], a, &rc);
  if( rc==SQLITE_OK ){
    GeoBBox *pBBox;
    pBBox = (GeoBBox*)sqlite3_aggregate_context(context, sizeof(*pBBox));
    if( pBBox==0 ) return;
    if( pBBox->isInit==0 ){
      pBBox->isInit = 1;
796
797
798
799
800
801
802


803
804
805

806

807
808
809
810
811
812


813
814
815
816
817
818
819
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







+
+


-
+
-
+




-
-
+
+







){
  GeoPoly *p1 = geopolyFuncParam(context, argv[0], 0);
  double x0 = sqlite3_value_double(argv[1]);
  double y0 = sqlite3_value_double(argv[2]);
  int v = 0;
  int cnt = 0;
  int ii;
  (void)argc;
    
  if( p1==0 ) return;
  for(ii=0; ii<p1->nVertex-1; ii++){
    v = pointBeneathLine(x0,y0,p1->a[ii*2],p1->a[ii*2+1],
    v = pointBeneathLine(x0,y0,GeoX(p1,ii), GeoY(p1,ii),
                               p1->a[ii*2+2],p1->a[ii*2+3]);
                               GeoX(p1,ii+1),GeoY(p1,ii+1));
    if( v==2 ) break;
    cnt += v;
  }
  if( v!=2 ){
    v = pointBeneathLine(x0,y0,p1->a[ii*2],p1->a[ii*2+1],
                               p1->a[0],p1->a[1]);
    v = pointBeneathLine(x0,y0,GeoX(p1,ii), GeoY(p1,ii),
                               GeoX(p1,0),  GeoY(p1,0));
  }
  if( v==2 ){
    sqlite3_result_int(context, 1);
  }else if( ((v+cnt)&1)==0 ){
    sqlite3_result_int(context, 0);
  }else{
    sqlite3_result_int(context, 2);
835
836
837
838
839
840
841

842
843
844
845
846
847
848
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874







+







static void geopolyWithinFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  GeoPoly *p1 = geopolyFuncParam(context, argv[0], 0);
  GeoPoly *p2 = geopolyFuncParam(context, argv[1], 0);
  (void)argc;
  if( p1 && p2 ){
    int x = geopolyOverlap(p1, p2);
    if( x<0 ){
      sqlite3_result_error_nomem(context);
    }else{
      sqlite3_result_int(context, x==2 ? 1 : x==4 ? 2 : 0);
    }
927
928
929
930
931
932
933
934

935
936
937

938
939
940
941
942
943
944
953
954
955
956
957
958
959

960
961
962

963
964
965
966
967
968
969
970







-
+


-
+







  GeoOverlap *p,          /* Add segments to this Overlap object */
  GeoPoly *pPoly,         /* Take all segments from this polygon */
  unsigned char side      /* The side of pPoly */
){
  unsigned int i;
  GeoCoord *x;
  for(i=0; i<(unsigned)pPoly->nVertex-1; i++){
    x = pPoly->a + (i*2);
    x = &GeoX(pPoly,i);
    geopolyAddOneSegment(p, x[0], x[1], x[2], x[3], side, i);
  }
  x = pPoly->a + (i*2);
  x = &GeoX(pPoly,i);
  geopolyAddOneSegment(p, x[0], x[1], pPoly->a[0], pPoly->a[1], side, i);
}

/*
** Merge two lists of sorted events by X coordinate
*/
static GeoEvent *geopolyEventMerge(GeoEvent *pLeft, GeoEvent *pRight){
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
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







-
+

-
+











-
+







-
+







  return p;
}

/*
** Determine the overlap between two polygons
*/
static int geopolyOverlap(GeoPoly *p1, GeoPoly *p2){
  int nVertex = p1->nVertex + p2->nVertex + 2;
  sqlite3_int64 nVertex = p1->nVertex + p2->nVertex + 2;
  GeoOverlap *p;
  int nByte;
  sqlite3_int64 nByte;
  GeoEvent *pThisEvent;
  double rX;
  int rc = 0;
  int needSort = 0;
  GeoSegment *pActive = 0;
  GeoSegment *pSeg;
  unsigned char aOverlap[4];

  nByte = sizeof(GeoEvent)*nVertex*2 
           + sizeof(GeoSegment)*nVertex 
           + sizeof(GeoOverlap);
  p = sqlite3_malloc( nByte );
  p = sqlite3_malloc64( nByte );
  if( p==0 ) return -1;
  p->aEvent = (GeoEvent*)&p[1];
  p->aSegment = (GeoSegment*)&p->aEvent[nVertex*2];
  p->nEvent = p->nSegment = 0;
  geopolyAddSegments(p, p1, 1);
  geopolyAddSegments(p, p2, 2);
  pThisEvent = geopolySortEventsByX(p->aEvent, p->nEvent);
  rX = pThisEvent->x==0.0 ? -1.0 : 0.0;
  rX = pThisEvent && pThisEvent->x==0.0 ? -1.0 : 0.0;
  memset(aOverlap, 0, sizeof(aOverlap));
  while( pThisEvent ){
    if( pThisEvent->x!=rX ){
      GeoSegment *pPrev = 0;
      int iMask = 0;
      GEODEBUG(("Distinct X: %g\n", pThisEvent->x));
      rX = pThisEvent->x;
1117
1118
1119
1120
1121
1122
1123
1124

1125
1126
1127
1128

1129
1130
1131
1132
1133
1134
1135
1143
1144
1145
1146
1147
1148
1149

1150
1151
1152
1153

1154
1155
1156
1157
1158
1159
1160
1161







-
+



-
+







      pSeg->y = pSeg->y0;
      pSeg->pNext = pActive;
      pActive = pSeg;
      needSort = 1;
    }else{
      /* Remove a segment */
      if( pActive==pThisEvent->pSeg ){
        pActive = pActive->pNext;
        pActive = ALWAYS(pActive) ? pActive->pNext : 0;
      }else{
        for(pSeg=pActive; pSeg; pSeg=pSeg->pNext){
          if( pSeg->pNext==pThisEvent->pSeg ){
            pSeg->pNext = pSeg->pNext->pNext;
            pSeg->pNext = ALWAYS(pSeg->pNext) ? pSeg->pNext->pNext : 0;
            break;
          }
        }
      }
    }
    pThisEvent = pThisEvent->pNext;
  }
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
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







+




















+
+


+
+







static void geopolyOverlapFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  GeoPoly *p1 = geopolyFuncParam(context, argv[0], 0);
  GeoPoly *p2 = geopolyFuncParam(context, argv[1], 0);
  (void)argc;
  if( p1 && p2 ){
    int x = geopolyOverlap(p1, p2);
    if( x<0 ){
      sqlite3_result_error_nomem(context);
    }else{
      sqlite3_result_int(context, x);
    }
  }
  sqlite3_free(p1);
  sqlite3_free(p2);
}

/*
** Enable or disable debugging output
*/
static void geopolyDebugFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  (void)context;
  (void)argc;
#ifdef GEOPOLY_ENABLE_DEBUG
  geo_debug = sqlite3_value_int(argv[0]);
#else
  (void)argv;
#endif
}

/* 
** This function is the implementation of both the xConnect and xCreate
** methods of the geopoly virtual table.
**
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
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







-
-
+
+



+




-
-
-
+
+
+







  int argc, const char *const*argv,   /* Parameters to CREATE TABLE statement */
  sqlite3_vtab **ppVtab,              /* OUT: New virtual table */
  char **pzErr,                       /* OUT: Error message, if any */
  int isCreate                        /* True for xCreate, false for xConnect */
){
  int rc = SQLITE_OK;
  Rtree *pRtree;
  int nDb;              /* Length of string argv[1] */
  int nName;            /* Length of string argv[2] */
  sqlite3_int64 nDb;              /* Length of string argv[1] */
  sqlite3_int64 nName;            /* Length of string argv[2] */
  sqlite3_str *pSql;
  char *zSql;
  int ii;
  (void)pAux;

  sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1);

  /* Allocate the sqlite3_vtab structure */
  nDb = (int)strlen(argv[1]);
  nName = (int)strlen(argv[2]);
  pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2);
  nDb = strlen(argv[1]);
  nName = strlen(argv[2]);
  pRtree = (Rtree *)sqlite3_malloc64(sizeof(Rtree)+nDb+nName+2);
  if( !pRtree ){
    return SQLITE_NOMEM;
  }
  memset(pRtree, 0, sizeof(Rtree)+nDb+nName+2);
  pRtree->nBusy = 1;
  pRtree->base.pModule = &rtreeModule;
  pRtree->zDb = (char *)&pRtree[1];
1330
1331
1332
1333
1334
1335
1336
1337

1338
1339
1340
1341
1342

1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1362
1363
1364
1365
1366
1367
1368

1369
1370
1371
1372
1373

1374





1375
1376
1377
1378
1379
1380
1381







-
+




-
+
-
-
-
-
-







  int argc, sqlite3_value **argv        /* Parameters to the query plan */
){
  Rtree *pRtree = (Rtree *)pVtabCursor->pVtab;
  RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor;
  RtreeNode *pRoot = 0;
  int rc = SQLITE_OK;
  int iCell = 0;
  sqlite3_stmt *pStmt;
  (void)idxStr;

  rtreeReference(pRtree);

  /* Reset the cursor to the same state as rtreeOpen() leaves it in. */
  freeCursorConstraints(pCsr);
  resetCursor(pCsr);
  sqlite3_free(pCsr->aPoint);
  pStmt = pCsr->pReadAux;
  memset(pCsr, 0, sizeof(RtreeCursor));
  pCsr->base.pVtab = (sqlite3_vtab*)pRtree;
  pCsr->pReadAux = pStmt;

  pCsr->iStrategy = idxNum;
  if( idxNum==1 ){
    /* Special case - lookup by rowid. */
    RtreeNode *pLeaf;        /* Leaf on which the required cell resides */
    RtreeSearchPoint *p;     /* Search point for the leaf */
    i64 iRowid = sqlite3_value_int64(argv[0]);
1371
1372
1373
1374
1375
1376
1377

1378
1379
1380
1381
1382
1383
1384
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412







+







    ** with the configured constraints. 
    */
    rc = nodeAcquire(pRtree, 1, 0, &pRoot);
    if( rc==SQLITE_OK && idxNum<=3 ){
      RtreeCoord bbox[4];
      RtreeConstraint *p;
      assert( argc==1 );
      assert( argv[0]!=0 );
      geopolyBBox(0, argv[0], bbox, &rc);
      if( rc ){
        goto geopoly_filter_end;
      }
      pCsr->aConstraint = p = sqlite3_malloc(sizeof(RtreeConstraint)*4);
      pCsr->nConstraint = 4;
      if( p==0 ){
1461
1462
1463
1464
1465
1466
1467

1468
1469
1470
1471
1472
1473
1474
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503







+







**   ------------------------------------------------
*/
static int geopolyBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
  int ii;
  int iRowidTerm = -1;
  int iFuncTerm = -1;
  int idxNum = 0;
  (void)tab;

  for(ii=0; ii<pIdxInfo->nConstraint; ii++){
    struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii];
    if( !p->usable ) continue;
    if( p->iColumn<0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ  ){
      iRowidTerm = ii;
      break;
1598
1599
1600
1601
1602
1603
1604

1605
1606
1607
1608
1609
1610
1611
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641







+







  cell.iRowid = newRowid;

  if( nData>1                                 /* not a DELETE */
   && (!oldRowidValid                         /* INSERT */
        || !sqlite3_value_nochange(aData[2])  /* UPDATE _shape */
        || oldRowid!=newRowid)                /* Rowid change */
  ){
    assert( aData[2]!=0 );
    geopolyBBox(0, aData[2], cell.aCoord, &rc);
    if( rc ){
      if( rc==SQLITE_ERROR ){
        pVtab->zErrMsg =
          sqlite3_mprintf("_shape does not contain a valid polygon");
      }
      goto geopoly_update_end;
1680
1681
1682
1683
1684
1685
1686
1687

1688
1689
1690
1691
1692
1693
1694
1710
1711
1712
1713
1714
1715
1716

1717
1718
1719
1720
1721
1722
1723
1724







-
+







        sqlite3_bind_blob(pUp, 2, p->hdr, 4+8*p->nVertex, SQLITE_TRANSIENT);
      }else{
        sqlite3_bind_value(pUp, 2, aData[2]);
      }
      sqlite3_free(p);
      nChange = 1;
    }
    for(jj=1; jj<pRtree->nAux; jj++){
    for(jj=1; jj<nData-2; jj++){
      nChange++;
      sqlite3_bind_value(pUp, jj+2, aData[jj+2]);
    }
    if( nChange ){
      sqlite3_step(pUp);
      rc = sqlite3_reset(pUp);
    }
1706
1707
1708
1709
1710
1711
1712


1713
1714
1715
1716
1717
1718
1719
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751







+
+







static int geopolyFindFunction(
  sqlite3_vtab *pVtab,
  int nArg,
  const char *zName,
  void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
  void **ppArg
){
  (void)pVtab;
  (void)nArg;
  if( sqlite3_stricmp(zName, "geopoly_overlap")==0 ){
    *pxFunc = geopolyOverlapFunc;
    *ppArg = 0;
    return SQLITE_INDEX_CONSTRAINT_FUNCTION;
  }
  if( sqlite3_stricmp(zName, "geopoly_within")==0 ){
    *pxFunc = geopolyWithinFunc;
1775
1776
1777
1778
1779
1780
1781
1782

1783


1784




1785
1786
1787
1788
1789
1790
1791



1792
1793
1794
1795
1796
1797
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







-
+

+
+
-
+
+
+
+





-
-
+
+
+






  static const struct {
    void (*xStep)(sqlite3_context*,int,sqlite3_value**);
    void (*xFinal)(sqlite3_context*);
    const char *zName;
  } aAgg[] = {
     { geopolyBBoxStep, geopolyBBoxFinal, "geopoly_group_bbox"    },
  };
  int i;
  unsigned int i;
  for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
    int enc;
    if( aFunc[i].bPure ){
    int enc = aFunc[i].bPure ? SQLITE_UTF8|SQLITE_DETERMINISTIC : SQLITE_UTF8;
      enc = SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS;
    }else{
      enc = SQLITE_UTF8|SQLITE_DIRECTONLY;
    }
    rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg,
                                 enc, 0,
                                 aFunc[i].xFunc, 0, 0);
  }
  for(i=0; i<sizeof(aAgg)/sizeof(aAgg[0]) && rc==SQLITE_OK; i++){
    rc = sqlite3_create_function(db, aAgg[i].zName, 1, SQLITE_UTF8, 0,
                                 0, aAgg[i].xStep, aAgg[i].xFinal);
    rc = sqlite3_create_function(db, aAgg[i].zName, 1, 
              SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS, 0,
              0, aAgg[i].xStep, aAgg[i].xFinal);
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_module_v2(db, "geopoly", &geopolyModule, 0, 0);
  }
  return rc;
}

Changes to ext/rtree/rtree.c.

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







+

+
+
-
+
-
-
-
-
+
+






+
+

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








#ifndef SQLITE_CORE
  #include "sqlite3ext.h"
  SQLITE_EXTENSION_INIT1
#else
  #include "sqlite3.h"
#endif
int sqlite3GetToken(const unsigned char*,int*); /* In the SQLite core */

/*
** If building separately, we will need some setup that is normally
#include <string.h>
** found in sqliteInt.h
#include <assert.h>
#include <stdio.h>

#ifndef SQLITE_AMALGAMATION
*/
#if !defined(SQLITE_AMALGAMATION)
#include "sqlite3rtree.h"
typedef sqlite3_int64 i64;
typedef sqlite3_uint64 u64;
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
# define NDEBUG 1
#endif
#if defined(NDEBUG) && defined(SQLITE_DEBUG)
# undef NDEBUG
#endif
#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
# define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1
#endif
#if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
# define ALWAYS(X)      (1)
# define NEVER(X)       (0)
#elif !defined(NDEBUG)
# define ALWAYS(X)      ((X)?1:(assert(0),0))
# define NEVER(X)       ((X)?(assert(0),1):0)
#else
# define ALWAYS(X)      (X)
# define NEVER(X)       (X)
#endif
#endif /* !defined(SQLITE_AMALGAMATION) */

#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>

/*  The following macro is used to suppress compiler warnings.
*/
#ifndef UNUSED_PARAMETER
# define UNUSED_PARAMETER(x) (void)(x)
#endif

123
124
125
126
127
128
129

130




131
132
133
134
135
136
137
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167







+

+
+
+
+







  int iNodeSize;              /* Size in bytes of each node in the node table */
  u8 nDim;                    /* Number of dimensions */
  u8 nDim2;                   /* Twice the number of dimensions */
  u8 eCoordType;              /* RTREE_COORD_REAL32 or RTREE_COORD_INT32 */
  u8 nBytesPerCell;           /* Bytes consumed per cell */
  u8 inWrTrans;               /* True if inside write transaction */
  u8 nAux;                    /* # of auxiliary columns in %_rowid */
#ifdef SQLITE_ENABLE_GEOPOLY
  u8 nAuxNotNull;             /* Number of initial not-null aux columns */
#endif
#ifdef SQLITE_DEBUG
  u8 bCorrupt;                /* Shadow table corruption detected */
#endif
  int iDepth;                 /* Current depth of the r-tree structure */
  char *zDb;                  /* Name of database containing r-tree table */
  char *zName;                /* Name of r-tree table */ 
  u32 nBusy;                  /* Current number of users of this structure */
  i64 nRowEst;                /* Estimated number of rows in this table */
  u32 nCursor;                /* Number of open cursors */
  u32 nNodeRef;               /* Number RtreeNodes with positive nRef */
183
184
185
186
187
188
189









190
191
192
193
194
195
196
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235







+
+
+
+
+
+
+
+
+







# define RTREE_ZERO 0
#else
  typedef double RtreeDValue;              /* High accuracy coordinate */
  typedef float RtreeValue;                /* Low accuracy coordinate */
# define RTREE_ZERO 0.0
#endif

/*
** Set the Rtree.bCorrupt flag
*/
#ifdef SQLITE_DEBUG
# define RTREE_IS_CORRUPT(X) ((X)->bCorrupt = 1)
#else
# define RTREE_IS_CORRUPT(X)
#endif

/*
** When doing a search of an r-tree, instances of the following structure
** record intermediate results from the tree walk.
**
** The id is always a node-id.  For iLevel>=1 the id is the node-id of
** the node that the RtreeSearchPoint represents.  When iLevel==0, however,
** the id is of the parent node and the cell that RtreeSearchPoint
303
304
305
306
307
308
309






310
311
312
313
314
315
316
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361







+
+
+
+
+
+







#define RTREE_LE    0x42  /* B */
#define RTREE_LT    0x43  /* C */
#define RTREE_GE    0x44  /* D */
#define RTREE_GT    0x45  /* E */
#define RTREE_MATCH 0x46  /* F: Old-style sqlite3_rtree_geometry_callback() */
#define RTREE_QUERY 0x47  /* G: New-style sqlite3_rtree_query_callback() */

/* Special operators available only on cursors.  Needs to be consecutive
** with the normal values above, but must be less than RTREE_MATCH.  These
** are used in the cursor for contraints such as x=NULL (RTREE_FALSE) or
** x<'xyz' (RTREE_TRUE) */
#define RTREE_TRUE  0x3f  /* ? */
#define RTREE_FALSE 0x40  /* @ */

/* 
** An rtree structure node.
*/
struct RtreeNode {
  RtreeNode *pParent;         /* Parent node */
  i64 iNode;                  /* The node number */
387
388
389
390
391
392
393




394



















395
396
397
398
399
400
401
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







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







#endif
#endif

/* The testcase() macro should already be defined in the amalgamation.  If
** it is not, make it a no-op.
*/
#ifndef SQLITE_AMALGAMATION
# if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG)
    unsigned int sqlite3RtreeTestcase = 0;
#   define testcase(X)  if( X ){ sqlite3RtreeTestcase += __LINE__; }
# else
# define testcase(X)
#   define testcase(X)
# endif
#endif

/*
** Make sure that the compiler intrinsics we desire are enabled when
** compiling with an appropriate version of MSVC unless prevented by
** the SQLITE_DISABLE_INTRINSIC define.
*/
#if !defined(SQLITE_DISABLE_INTRINSIC)
#  if defined(_MSC_VER) && _MSC_VER>=1400
#    if !defined(_WIN32_WCE)
#      include <intrin.h>
#      pragma intrinsic(_byteswap_ulong)
#      pragma intrinsic(_byteswap_uint64)
#    else
#      include <cmnintrin.h>
#    endif
#  endif
#endif

/*
** Macros to determine whether the machine is big or little endian,
** and whether or not that determination is run-time or compile-time.
**
** For best performance, an attempt is made to guess at the byte-order
430
431
432
433
434
435
436
437

438
439
440
441
442
443
444
497
498
499
500
501
502
503

504
505
506
507
508
509
510
511







-
+







** Functions to deserialize a 16 bit integer, 32 bit real number and
** 64 bit integer. The deserialized value is returned.
*/
static int readInt16(u8 *p){
  return (p[0]<<8) + p[1];
}
static void readCoord(u8 *p, RtreeCoord *pCoord){
  assert( ((((char*)p) - (char*)0)&3)==0 );  /* p is always 4-byte aligned */
  assert( (((sqlite3_uint64)p)&3)==0 );  /* p is always 4-byte aligned */
#if SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
  pCoord->u = _byteswap_ulong(*(u32*)p);
#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
  pCoord->u = __builtin_bswap32(*(u32*)p);
#elif SQLITE_BYTEORDER==4321
  pCoord->u = *(u32*)p;
#else
484
485
486
487
488
489
490
491

492
493
494
495
496
497
498
551
552
553
554
555
556
557

558
559
560
561
562
563
564
565







-
+







*/
static void writeInt16(u8 *p, int i){
  p[0] = (i>> 8)&0xFF;
  p[1] = (i>> 0)&0xFF;
}
static int writeCoord(u8 *p, RtreeCoord *pCoord){
  u32 i;
  assert( ((((char*)p) - (char*)0)&3)==0 );  /* p is always 4-byte aligned */
  assert( (((sqlite3_uint64)p)&3)==0 );  /* p is always 4-byte aligned */
  assert( sizeof(RtreeCoord)==4 );
  assert( sizeof(u32)==4 );
#if SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
  i = __builtin_bswap32(pCoord->u);
  memcpy(p, &i, 4);
#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
  i = _byteswap_ulong(pCoord->u);
549
550
551
552
553
554
555
556
557


558
559
560
561
562
563
564
616
617
618
619
620
621
622


623
624
625
626
627
628
629
630
631







-
-
+
+







  p->isDirty = 1;
}

/*
** Given a node number iNode, return the corresponding key to use
** in the Rtree.aHash table.
*/
static int nodeHash(i64 iNode){
  return iNode % HASHSIZE;
static unsigned int nodeHash(i64 iNode){
  return ((unsigned)iNode) % HASHSIZE;
}

/*
** Search the node hash table for node iNode. If found, return a pointer
** to it. Otherwise, return 0.
*/
static RtreeNode *nodeHashLookup(Rtree *pRtree, i64 iNode){
595
596
597
598
599
600
601
602

603
604
605
606
607
608
609
662
663
664
665
666
667
668

669
670
671
672
673
674
675
676







-
+







** Allocate and return new r-tree node. Initially, (RtreeNode.iNode==0),
** indicating that node has not yet been assigned a node number. It is
** assigned a node number when nodeWrite() is called to write the
** node contents out to the database.
*/
static RtreeNode *nodeNew(Rtree *pRtree, RtreeNode *pParent){
  RtreeNode *pNode;
  pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode) + pRtree->iNodeSize);
  pNode = (RtreeNode *)sqlite3_malloc64(sizeof(RtreeNode) + pRtree->iNodeSize);
  if( pNode ){
    memset(pNode, 0, sizeof(RtreeNode) + pRtree->iNodeSize);
    pNode->zData = (u8 *)&pNode[1];
    pNode->nRef = 1;
    pRtree->nNodeRef++;
    pNode->pParent = pParent;
    pNode->isDirty = 1;
635
636
637
638
639
640
641
642
643
644


645

646
647
648
649
650
651
652
702
703
704
705
706
707
708



709
710

711
712
713
714
715
716
717
718







-
-
-
+
+
-
+







  int rc = SQLITE_OK;
  RtreeNode *pNode = 0;

  /* Check if the requested node is already in the hash table. If so,
  ** increase its reference count and return it.
  */
  if( (pNode = nodeHashLookup(pRtree, iNode))!=0 ){
    assert( !pParent || !pNode->pParent || pNode->pParent==pParent );
    if( pParent && !pNode->pParent ){
      pParent->nRef++;
    if( pParent && pParent!=pNode->pParent ){
      RTREE_IS_CORRUPT(pRtree);
      pNode->pParent = pParent;
      return SQLITE_CORRUPT_VTAB;
    }
    pNode->nRef++;
    *ppNode = pNode;
    return SQLITE_OK;
  }

  if( pRtree->pNodeBlob ){
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
733
734
735
736
737
738
739

740
741
742
743
744

745
746
747
748
749
750
751
752
753
754
755
756
757

758
759
760
761
762
763
764
765
766

767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799







-
+
+
+
+

-
+












-









-
+



+










+





+



+







    sqlite3_free(zTab);
  }
  if( rc ){
    nodeBlobReset(pRtree);
    *ppNode = 0;
    /* If unable to open an sqlite3_blob on the desired row, that can only
    ** be because the shadow tables hold erroneous data. */
    if( rc==SQLITE_ERROR ) rc = SQLITE_CORRUPT_VTAB;
    if( rc==SQLITE_ERROR ){
      rc = SQLITE_CORRUPT_VTAB;
      RTREE_IS_CORRUPT(pRtree);
    }
  }else if( pRtree->iNodeSize==sqlite3_blob_bytes(pRtree->pNodeBlob) ){
    pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode)+pRtree->iNodeSize);
    pNode = (RtreeNode *)sqlite3_malloc64(sizeof(RtreeNode)+pRtree->iNodeSize);
    if( !pNode ){
      rc = SQLITE_NOMEM;
    }else{
      pNode->pParent = pParent;
      pNode->zData = (u8 *)&pNode[1];
      pNode->nRef = 1;
      pRtree->nNodeRef++;
      pNode->iNode = iNode;
      pNode->isDirty = 0;
      pNode->pNext = 0;
      rc = sqlite3_blob_read(pRtree->pNodeBlob, pNode->zData,
                             pRtree->iNodeSize, 0);
      nodeReference(pParent);
    }
  }

  /* If the root node was just loaded, set pRtree->iDepth to the height
  ** of the r-tree structure. A height of zero means all data is stored on
  ** the root node. A height of one means the children of the root node
  ** are the leaves, and so on. If the depth as specified on the root node
  ** is greater than RTREE_MAX_DEPTH, the r-tree structure must be corrupt.
  */
  if( pNode && iNode==1 ){
  if( rc==SQLITE_OK && pNode && iNode==1 ){
    pRtree->iDepth = readInt16(pNode->zData);
    if( pRtree->iDepth>RTREE_MAX_DEPTH ){
      rc = SQLITE_CORRUPT_VTAB;
      RTREE_IS_CORRUPT(pRtree);
    }
  }

  /* If no error has occurred so far, check if the "number of entries"
  ** field on the node is too large. If so, set the return code to 
  ** SQLITE_CORRUPT_VTAB.
  */
  if( pNode && rc==SQLITE_OK ){
    if( NCELL(pNode)>((pRtree->iNodeSize-4)/pRtree->nBytesPerCell) ){
      rc = SQLITE_CORRUPT_VTAB;
      RTREE_IS_CORRUPT(pRtree);
    }
  }

  if( rc==SQLITE_OK ){
    if( pNode!=0 ){
      nodeReference(pParent);
      nodeHashInsert(pRtree, pNode);
    }else{
      rc = SQLITE_CORRUPT_VTAB;
      RTREE_IS_CORRUPT(pRtree);
    }
    *ppNode = pNode;
  }else{
    if( pNode ){
      pRtree->nNodeRef--;
      sqlite3_free(pNode);
    }
939
940
941
942
943
944
945
946

947
948
949
950
951
952
953
1011
1012
1013
1014
1015
1016
1017

1018
1019
1020
1021
1022
1023
1024
1025







-
+







*/
static void rtreeRelease(Rtree *pRtree){
  pRtree->nBusy--;
  if( pRtree->nBusy==0 ){
    pRtree->inWrTrans = 0;
    assert( pRtree->nCursor==0 );
    nodeBlobReset(pRtree);
    assert( pRtree->nNodeRef==0 );
    assert( pRtree->nNodeRef==0 || pRtree->bCorrupt );
    sqlite3_finalize(pRtree->pWriteNode);
    sqlite3_finalize(pRtree->pDeleteNode);
    sqlite3_finalize(pRtree->pReadRowid);
    sqlite3_finalize(pRtree->pWriteRowid);
    sqlite3_finalize(pRtree->pDeleteRowid);
    sqlite3_finalize(pRtree->pReadParent);
    sqlite3_finalize(pRtree->pWriteParent);
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
1046
1047
1048
1049
1050
1051
1052
1053
1054
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







-
+













-
+

-
+
+
+
+












+
+
+
+
+
+
+







-


-
+

-
-







** Rtree virtual table module xOpen method.
*/
static int rtreeOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
  int rc = SQLITE_NOMEM;
  Rtree *pRtree = (Rtree *)pVTab;
  RtreeCursor *pCsr;

  pCsr = (RtreeCursor *)sqlite3_malloc(sizeof(RtreeCursor));
  pCsr = (RtreeCursor *)sqlite3_malloc64(sizeof(RtreeCursor));
  if( pCsr ){
    memset(pCsr, 0, sizeof(RtreeCursor));
    pCsr->base.pVtab = pVTab;
    rc = SQLITE_OK;
    pRtree->nCursor++;
  }
  *ppCursor = (sqlite3_vtab_cursor *)pCsr;

  return rc;
}


/*
** Free the RtreeCursor.aConstraint[] array and its contents.
** Reset a cursor back to its initial state.
*/
static void freeCursorConstraints(RtreeCursor *pCsr){
static void resetCursor(RtreeCursor *pCsr){
  Rtree *pRtree = (Rtree *)(pCsr->base.pVtab);
  int ii;
  sqlite3_stmt *pStmt;
  if( pCsr->aConstraint ){
    int i;                        /* Used to iterate through constraint array */
    for(i=0; i<pCsr->nConstraint; i++){
      sqlite3_rtree_query_info *pInfo = pCsr->aConstraint[i].pInfo;
      if( pInfo ){
        if( pInfo->xDelUser ) pInfo->xDelUser(pInfo->pUser);
        sqlite3_free(pInfo);
      }
    }
    sqlite3_free(pCsr->aConstraint);
    pCsr->aConstraint = 0;
  }
  for(ii=0; ii<RTREE_CACHE_SZ; ii++) nodeRelease(pRtree, pCsr->aNode[ii]);
  sqlite3_free(pCsr->aPoint);
  pStmt = pCsr->pReadAux;
  memset(pCsr, 0, sizeof(RtreeCursor));
  pCsr->base.pVtab = (sqlite3_vtab*)pRtree;
  pCsr->pReadAux = pStmt;

}

/* 
** Rtree virtual table module xClose method.
*/
static int rtreeClose(sqlite3_vtab_cursor *cur){
  Rtree *pRtree = (Rtree *)(cur->pVtab);
  int ii;
  RtreeCursor *pCsr = (RtreeCursor *)cur;
  assert( pRtree->nCursor>0 );
  freeCursorConstraints(pCsr);
  resetCursor(pCsr);
  sqlite3_finalize(pCsr->pReadAux);
  sqlite3_free(pCsr->aPoint);
  for(ii=0; ii<RTREE_CACHE_SZ; ii++) nodeRelease(pRtree, pCsr->aNode[ii]);
  sqlite3_free(pCsr);
  pRtree->nCursor--;
  nodeBlobReset(pRtree);
  return SQLITE_OK;
}

/*
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
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
1318
1319







-
-
+
+
+

-
-
+
+



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

-
+




+








  /* p->iCoord might point to either a lower or upper bound coordinate
  ** in a coordinate pair.  But make pCellData point to the lower bound.
  */
  pCellData += 8 + 4*(p->iCoord&0xfe);

  assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE 
      || p->op==RTREE_GT || p->op==RTREE_EQ );
  assert( ((((char*)pCellData) - (char*)0)&3)==0 );  /* 4-byte aligned */
      || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_TRUE
      || p->op==RTREE_FALSE );
  assert( (((sqlite3_uint64)pCellData)&3)==0 );  /* 4-byte aligned */
  switch( p->op ){
    case RTREE_LE:
    case RTREE_LT:
    case RTREE_TRUE:  return;   /* Always satisfied */
    case RTREE_FALSE: break;    /* Never satisfied */
    case RTREE_EQ:
      RTREE_DECODE_COORD(eInt, pCellData, val);
      /* val now holds the lower bound of the coordinate pair */
      if( p->u.rValue>=val ) return;
      if( p->op!=RTREE_EQ ) break;  /* RTREE_LE and RTREE_LT end here */
      /* Fall through for the RTREE_EQ case */
      if( p->u.rValue>=val ){
        pCellData += 4;
        RTREE_DECODE_COORD(eInt, pCellData, val);
        /* val now holds the upper bound of the coordinate pair */
        if( p->u.rValue<=val ) return;
      }
      break;
    case RTREE_LE:
    case RTREE_LT:
      RTREE_DECODE_COORD(eInt, pCellData, val);
      /* val now holds the lower bound of the coordinate pair */
      if( p->u.rValue>=val ) return;
      break;

    default: /* RTREE_GT or RTREE_GE,  or fallthrough of RTREE_EQ */
    default:
      pCellData += 4;
      RTREE_DECODE_COORD(eInt, pCellData, val);
      /* val now holds the upper bound of the coordinate pair */
      if( p->u.rValue<=val ) return;
      break;
  }
  *peWithin = NOT_WITHIN;
}

/*
** Check the leaf RTree cell given by pCellData against constraint p.
** If this constraint is not satisfied, set *peWithin to NOT_WITHIN.
1238
1239
1240
1241
1242
1243
1244
1245


1246
1247

1248
1249


1250
1251
1252
1253
1254





1255
1256
1257
1258
1259
1260
1261
1329
1330
1331
1332
1333
1334
1335

1336
1337
1338

1339
1340
1341
1342
1343





1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355







-
+
+

-
+


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







  int eInt,                  /* True if RTree holds integer coordinates */
  u8 *pCellData,             /* Raw cell content as appears on disk */
  int *peWithin              /* Adjust downward, as appropriate */
){
  RtreeDValue xN;      /* Coordinate value converted to a double */

  assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE 
      || p->op==RTREE_GT || p->op==RTREE_EQ );
      || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_TRUE
      || p->op==RTREE_FALSE );
  pCellData += 8 + p->iCoord*4;
  assert( ((((char*)pCellData) - (char*)0)&3)==0 );  /* 4-byte aligned */
  assert( (((sqlite3_uint64)pCellData)&3)==0 );  /* 4-byte aligned */
  RTREE_DECODE_COORD(eInt, pCellData, xN);
  switch( p->op ){
    case RTREE_TRUE:  return;   /* Always satisfied */
    case RTREE_FALSE: break;    /* Never satisfied */
    case RTREE_LE: if( xN <= p->u.rValue ) return;  break;
    case RTREE_LT: if( xN <  p->u.rValue ) return;  break;
    case RTREE_GE: if( xN >= p->u.rValue ) return;  break;
    case RTREE_GT: if( xN >  p->u.rValue ) return;  break;
    default:       if( xN == p->u.rValue ) return;  break;
    case RTREE_LE:    if( xN <= p->u.rValue ) return;  break;
    case RTREE_LT:    if( xN <  p->u.rValue ) return;  break;
    case RTREE_GE:    if( xN >= p->u.rValue ) return;  break;
    case RTREE_GT:    if( xN >  p->u.rValue ) return;  break;
    default:          if( xN == p->u.rValue ) return;  break;
  }
  *peWithin = NOT_WITHIN;
}

/*
** One of the cells in node pNode is guaranteed to have a 64-bit 
** integer value equal to iRowid. Return the index of this cell.
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
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







+









-
+

-
-
-
+
+
+
+







  assert( nCell<200 );
  for(ii=0; ii<nCell; ii++){
    if( nodeGetRowid(pRtree, pNode, ii)==iRowid ){
      *piIndex = ii;
      return SQLITE_OK;
    }
  }
  RTREE_IS_CORRUPT(pRtree);
  return SQLITE_CORRUPT_VTAB;
}

/*
** Return the index of the cell containing a pointer to node pNode
** in its parent. If pNode is the root node, return -1.
*/
static int nodeParentIndex(Rtree *pRtree, RtreeNode *pNode, int *piIndex){
  RtreeNode *pParent = pNode->pParent;
  if( pParent ){
  if( ALWAYS(pParent) ){
    return nodeRowidIndex(pRtree, pParent, pNode->iNode, piIndex);
  }
  *piIndex = -1;
  return SQLITE_OK;
  }else{
    *piIndex = -1;
    return SQLITE_OK;
  }
}

/*
** Compare two search points.  Return negative, zero, or positive if the first
** is less than, equal to, or greater than the second.
**
** The rScore is the primary key.  Smaller rScore values come first.
1364
1365
1366
1367
1368
1369
1370
1371

1372
1373
1374
1375
1376
1377
1378
1460
1461
1462
1463
1464
1465
1466

1467
1468
1469
1470
1471
1472
1473
1474







-
+







  RtreeDValue rScore,   /* Score for the new search point */
  u8 iLevel             /* Level for the new search point */
){
  int i, j;
  RtreeSearchPoint *pNew;
  if( pCur->nPoint>=pCur->nPointAlloc ){
    int nNew = pCur->nPointAlloc*2 + 8;
    pNew = sqlite3_realloc(pCur->aPoint, nNew*sizeof(pCur->aPoint[0]));
    pNew = sqlite3_realloc64(pCur->aPoint, nNew*sizeof(pCur->aPoint[0]));
    if( pNew==0 ) return 0;
    pCur->aPoint = pNew;
    pCur->nPointAlloc = nNew;
  }
  i = pCur->nPoint++;
  pNew = pCur->aPoint + i;
  pNew->rScore = rScore;
1407
1408
1409
1410
1411
1412
1413

1414

1415
1416
1417
1418
1419
1420
1421
1503
1504
1505
1506
1507
1508
1509
1510

1511
1512
1513
1514
1515
1516
1517
1518







+
-
+







   || (pFirst->rScore==rScore && pFirst->iLevel>iLevel)
  ){
    if( pCur->bPoint ){
      int ii;
      pNew = rtreeEnqueue(pCur, rScore, iLevel);
      if( pNew==0 ) return 0;
      ii = (int)(pNew - pCur->aPoint) + 1;
      assert( ii==1 );
      if( ii<RTREE_CACHE_SZ ){
      if( ALWAYS(ii<RTREE_CACHE_SZ) ){
        assert( pCur->aNode[ii]==0 );
        pCur->aNode[ii] = pCur->aNode[0];
      }else{
        nodeRelease(RTREE_OF_CURSOR(pCur), pCur->aNode[0]);
      }
      pCur->aNode[0] = 0;
      *pNew = pCur->sPoint;
1468
1469
1470
1471
1472
1473
1474
1475

1476
1477
1478
1479
1480
1481
1482
1565
1566
1567
1568
1569
1570
1571

1572
1573
1574
1575
1576
1577
1578
1579







-
+







  if( p->aNode[i] ){
    nodeRelease(RTREE_OF_CURSOR(p), p->aNode[i]);
    p->aNode[i] = 0;
  }
  if( p->bPoint ){
    p->anQueue[p->sPoint.iLevel]--;
    p->bPoint = 0;
  }else if( p->nPoint ){
  }else if( ALWAYS(p->nPoint) ){
    p->anQueue[p->aPoint[0].iLevel]--;
    n = --p->nPoint;
    p->aPoint[0] = p->aPoint[n];
    if( n<RTREE_CACHE_SZ-1 ){
      p->aNode[1] = p->aNode[n+1];
      p->aNode[n+1] = 0;
    }
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

1546
1547





1548

1549
1550
1551






1552
1553
1554
1555
1556
1557
1558
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630

1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642

1643


1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666







+




+


-












-
+
-
-
+
+
+
+
+

+



+
+
+
+
+
+







  int nConstraint = pCur->nConstraint;
  int ii;
  int eInt;
  RtreeSearchPoint x;

  eInt = pRtree->eCoordType==RTREE_COORD_INT32;
  while( (p = rtreeSearchPointFirst(pCur))!=0 && p->iLevel>0 ){
    u8 *pCellData;
    pNode = rtreeNodeOfFirstSearchPoint(pCur, &rc);
    if( rc ) return rc;
    nCell = NCELL(pNode);
    assert( nCell<200 );
    pCellData = pNode->zData + (4+pRtree->nBytesPerCell*p->iCell);
    while( p->iCell<nCell ){
      sqlite3_rtree_dbl rScore = (sqlite3_rtree_dbl)-1;
      u8 *pCellData = pNode->zData + (4+pRtree->nBytesPerCell*p->iCell);
      eWithin = FULLY_WITHIN;
      for(ii=0; ii<nConstraint; ii++){
        RtreeConstraint *pConstraint = pCur->aConstraint + ii;
        if( pConstraint->op>=RTREE_MATCH ){
          rc = rtreeCallbackConstraint(pConstraint, eInt, pCellData, p,
                                       &rScore, &eWithin);
          if( rc ) return rc;
        }else if( p->iLevel==1 ){
          rtreeLeafConstraint(pConstraint, eInt, pCellData, &eWithin);
        }else{
          rtreeNonleafConstraint(pConstraint, eInt, pCellData, &eWithin);
        }
        if( eWithin==NOT_WITHIN ) break;
        if( eWithin==NOT_WITHIN ){
      }
      p->iCell++;
          p->iCell++;
          pCellData += pRtree->nBytesPerCell;
          break;
        }
      }
      if( eWithin==NOT_WITHIN ) continue;
      p->iCell++;
      x.iLevel = p->iLevel - 1;
      if( x.iLevel ){
        x.id = readInt64(pCellData);
        for(ii=0; ii<pCur->nPoint; ii++){
          if( pCur->aPoint[ii].id==x.id ){
            RTREE_IS_CORRUPT(pRtree);
            return SQLITE_CORRUPT_VTAB;
          }
        }
        x.iCell = 0;
      }else{
        x.id = p->id;
        x.iCell = p->iCell - 1;
      }
      if( p->iCell>=nCell ){
        RTREE_QUEUE_TRACE(pCur, "POP-S:");
1598
1599
1600
1601
1602
1603
1604
1605

1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623

1624
1625
1626
1627
1628
1629
1630
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







-
+

















-
+







** Rtree virtual table module xRowid method.
*/
static int rtreeRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *pRowid){
  RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor;
  RtreeSearchPoint *p = rtreeSearchPointFirst(pCsr);
  int rc = SQLITE_OK;
  RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc);
  if( rc==SQLITE_OK && p ){
  if( rc==SQLITE_OK && ALWAYS(p) ){
    *pRowid = nodeGetRowid(RTREE_OF_CURSOR(pCsr), pNode, p->iCell);
  }
  return rc;
}

/* 
** Rtree virtual table module xColumn method.
*/
static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
  Rtree *pRtree = (Rtree *)cur->pVtab;
  RtreeCursor *pCsr = (RtreeCursor *)cur;
  RtreeSearchPoint *p = rtreeSearchPointFirst(pCsr);
  RtreeCoord c;
  int rc = SQLITE_OK;
  RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc);

  if( rc ) return rc;
  if( p==0 ) return SQLITE_OK;
  if( NEVER(p==0) ) return SQLITE_OK;
  if( i==0 ){
    sqlite3_result_int64(ctx, nodeGetRowid(pRtree, pNode, p->iCell));
  }else if( i<=pRtree->nDim2 ){
    nodeGetCoord(pRtree, pNode, p->iCell, i-1, &c);
#ifndef SQLITE_RTREE_INT_ONLY
    if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
      sqlite3_result_double(ctx, c.f);
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





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
1836
1837
1838
1839
1840
1841
1842

1843
1844
1845
1846

1847





1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859

1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882

1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908

1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932

1933
1934
1935
1936
1937
1938
1939
1940
1941







-




-
+
-
-
-
-
-








+
+
+
+
-
+
+
+
+
+


















-
+










+














-
+





+
+
+
+
+
+
+
+
+






+

+
-
+
+







){
  Rtree *pRtree = (Rtree *)pVtabCursor->pVtab;
  RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor;
  RtreeNode *pRoot = 0;
  int ii;
  int rc = SQLITE_OK;
  int iCell = 0;
  sqlite3_stmt *pStmt;

  rtreeReference(pRtree);

  /* Reset the cursor to the same state as rtreeOpen() leaves it in. */
  freeCursorConstraints(pCsr);
  resetCursor(pCsr);
  sqlite3_free(pCsr->aPoint);
  pStmt = pCsr->pReadAux;
  memset(pCsr, 0, sizeof(RtreeCursor));
  pCsr->base.pVtab = (sqlite3_vtab*)pRtree;
  pCsr->pReadAux = pStmt;

  pCsr->iStrategy = idxNum;
  if( idxNum==1 ){
    /* Special case - lookup by rowid. */
    RtreeNode *pLeaf;        /* Leaf on which the required cell resides */
    RtreeSearchPoint *p;     /* Search point for the leaf */
    i64 iRowid = sqlite3_value_int64(argv[0]);
    i64 iNode = 0;
    int eType = sqlite3_value_numeric_type(argv[0]);
    if( eType==SQLITE_INTEGER
     || (eType==SQLITE_FLOAT && sqlite3_value_double(argv[0])==iRowid)
    ){
    rc = findLeafNode(pRtree, iRowid, &pLeaf, &iNode);
      rc = findLeafNode(pRtree, iRowid, &pLeaf, &iNode);
    }else{
      rc = SQLITE_OK;
      pLeaf = 0;
    }
    if( rc==SQLITE_OK && pLeaf!=0 ){
      p = rtreeSearchPointNew(pCsr, RTREE_ZERO, 0);
      assert( p!=0 );  /* Always returns pCsr->sPoint */
      pCsr->aNode[0] = pLeaf;
      p->id = iNode;
      p->eWithin = PARTLY_WITHIN;
      rc = nodeRowidIndex(pRtree, pLeaf, iRowid, &iCell);
      p->iCell = (u8)iCell;
      RTREE_QUEUE_TRACE(pCsr, "PUSH-F1:");
    }else{
      pCsr->atEOF = 1;
    }
  }else{
    /* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array 
    ** with the configured constraints. 
    */
    rc = nodeAcquire(pRtree, 1, 0, &pRoot);
    if( rc==SQLITE_OK && argc>0 ){
      pCsr->aConstraint = sqlite3_malloc(sizeof(RtreeConstraint)*argc);
      pCsr->aConstraint = sqlite3_malloc64(sizeof(RtreeConstraint)*argc);
      pCsr->nConstraint = argc;
      if( !pCsr->aConstraint ){
        rc = SQLITE_NOMEM;
      }else{
        memset(pCsr->aConstraint, 0, sizeof(RtreeConstraint)*argc);
        memset(pCsr->anQueue, 0, sizeof(u32)*(pRtree->iDepth + 1));
        assert( (idxStr==0 && argc==0)
                || (idxStr && (int)strlen(idxStr)==argc*2) );
        for(ii=0; ii<argc; ii++){
          RtreeConstraint *p = &pCsr->aConstraint[ii];
          int eType = sqlite3_value_numeric_type(argv[ii]);
          p->op = idxStr[ii*2];
          p->iCoord = idxStr[ii*2+1]-'0';
          if( p->op>=RTREE_MATCH ){
            /* A MATCH operator. The right-hand-side must be a blob that
            ** can be cast into an RtreeMatchArg object. One created using
            ** an sqlite3_rtree_geometry_callback() SQL user function.
            */
            rc = deserializeGeometry(argv[ii], p);
            if( rc!=SQLITE_OK ){
              break;
            }
            p->pInfo->nCoord = pRtree->nDim2;
            p->pInfo->anQueue = pCsr->anQueue;
            p->pInfo->mxLevel = pRtree->iDepth + 1;
          }else{
          }else if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
#ifdef SQLITE_RTREE_INT_ONLY
            p->u.rValue = sqlite3_value_int64(argv[ii]);
#else
            p->u.rValue = sqlite3_value_double(argv[ii]);
#endif
          }else{
            p->u.rValue = RTREE_ZERO;
            if( eType==SQLITE_NULL ){
              p->op = RTREE_FALSE;
            }else if( p->op==RTREE_LT || p->op==RTREE_LE ){
              p->op = RTREE_TRUE;
            }else{
              p->op = RTREE_FALSE;
            }
          }
        }
      }
    }
    if( rc==SQLITE_OK ){
      RtreeSearchPoint *pNew;
      assert( pCsr->bPoint==0 );  /* Due to the resetCursor() call above */
      pNew = rtreeSearchPointNew(pCsr, RTREE_ZERO, (u8)(pRtree->iDepth+1));
      if( NEVER(pNew==0) ){       /* Because pCsr->bPoint was FALSE */
      if( pNew==0 ) return SQLITE_NOMEM;
        return SQLITE_NOMEM;
      }
      pNew->id = 1;
      pNew->iCell = 0;
      pNew->eWithin = PARTLY_WITHIN;
      assert( pCsr->bPoint==1 );
      pCsr->aNode[0] = pRoot;
      pRoot = 0;
      RTREE_QUEUE_TRACE(pCsr, "PUSH-Fm:");
1881
1882
1883
1884
1885
1886
1887
1888

1889
1890
1891
1892
1893
1894
1895
2004
2005
2006
2007
2008
2009
2010

2011
2012
2013
2014
2015
2016
2017
2018







-
+







  }

  assert( pIdxInfo->idxStr==0 );
  for(ii=0; ii<pIdxInfo->nConstraint && iIdx<(int)(sizeof(zIdxStr)-1); ii++){
    struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii];

    if( bMatch==0 && p->usable 
     && p->iColumn==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ 
     && p->iColumn<=0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ 
    ){
      /* We have an equality constraint on the rowid. Use strategy 1. */
      int jj;
      for(jj=0; jj<ii; jj++){
        pIdxInfo->aConstraintUsage[jj].argvIndex = 0;
        pIdxInfo->aConstraintUsage[jj].omit = 0;
      }
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
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







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

+
-
-
-
-
+
+
+
+
+








    if( p->usable
    && ((p->iColumn>0 && p->iColumn<=pRtree->nDim2)
        || p->op==SQLITE_INDEX_CONSTRAINT_MATCH)
    ){
      u8 op;
      switch( p->op ){
        case SQLITE_INDEX_CONSTRAINT_EQ: op = RTREE_EQ; break;
        case SQLITE_INDEX_CONSTRAINT_GT: op = RTREE_GT; break;
        case SQLITE_INDEX_CONSTRAINT_LE: op = RTREE_LE; break;
        case SQLITE_INDEX_CONSTRAINT_LT: op = RTREE_LT; break;
        case SQLITE_INDEX_CONSTRAINT_GE: op = RTREE_GE; break;
        case SQLITE_INDEX_CONSTRAINT_EQ:    op = RTREE_EQ;    break;
        case SQLITE_INDEX_CONSTRAINT_GT:    op = RTREE_GT;    break;
        case SQLITE_INDEX_CONSTRAINT_LE:    op = RTREE_LE;    break;
        case SQLITE_INDEX_CONSTRAINT_LT:    op = RTREE_LT;    break;
        case SQLITE_INDEX_CONSTRAINT_GE:    op = RTREE_GE;    break;
        default:
          assert( p->op==SQLITE_INDEX_CONSTRAINT_MATCH );
        case SQLITE_INDEX_CONSTRAINT_MATCH: op = RTREE_MATCH; break;
          op = RTREE_MATCH; 
          break;
        default:                            op = 0;           break;
      }
      if( op ){
      zIdxStr[iIdx++] = op;
      zIdxStr[iIdx++] = (char)(p->iColumn - 1 + '0');
      pIdxInfo->aConstraintUsage[ii].argvIndex = (iIdx/2);
      pIdxInfo->aConstraintUsage[ii].omit = 1;
        zIdxStr[iIdx++] = op;
        zIdxStr[iIdx++] = (char)(p->iColumn - 1 + '0');
        pIdxInfo->aConstraintUsage[ii].argvIndex = (iIdx/2);
        pIdxInfo->aConstraintUsage[ii].omit = 1;
      }
    }
  }

  pIdxInfo->idxNum = 2;
  pIdxInfo->needToFreeIdxStr = 1;
  if( iIdx>0 && 0==(pIdxInfo->idxStr = sqlite3_mprintf("%s", zIdxStr)) ){
    return SQLITE_NOMEM;
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971





1972
1973
1974
1975
1976
1977
1978
2083
2084
2085
2086
2087
2088
2089





2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101







-
-
-
-
-
+
+
+
+
+







      case 2:  area *= p->aCoord[3].f - p->aCoord[2].f;
      default: area *= p->aCoord[1].f - p->aCoord[0].f;
    }
  }else
#endif
  {
    switch( pRtree->nDim ){
      case 5:  area  = p->aCoord[9].i - p->aCoord[8].i;
      case 4:  area *= p->aCoord[7].i - p->aCoord[6].i;
      case 3:  area *= p->aCoord[5].i - p->aCoord[4].i;
      case 2:  area *= p->aCoord[3].i - p->aCoord[2].i;
      default: area *= p->aCoord[1].i - p->aCoord[0].i;
      case 5:  area  = (i64)p->aCoord[9].i - (i64)p->aCoord[8].i;
      case 4:  area *= (i64)p->aCoord[7].i - (i64)p->aCoord[6].i;
      case 3:  area *= (i64)p->aCoord[5].i - (i64)p->aCoord[4].i;
      case 2:  area *= (i64)p->aCoord[3].i - (i64)p->aCoord[2].i;
      default: area *= (i64)p->aCoord[1].i - (i64)p->aCoord[0].i;
    }
  }
  return area;
}

/*
** Return the margin length of cell p. The margin length is the sum
2087
2088
2089
2090
2091
2092
2093
2094

2095
2096
2097
2098
2099
2100
2101
2210
2211
2212
2213
2214
2215
2216

2217
2218
2219
2220
2221
2222
2223
2224







-
+







    sqlite3_int64 iBest = 0;

    RtreeDValue fMinGrowth = RTREE_ZERO;
    RtreeDValue fMinArea = RTREE_ZERO;

    int nCell = NCELL(pNode);
    RtreeCell cell;
    RtreeNode *pChild;
    RtreeNode *pChild = 0;

    RtreeCell *aCell = 0;

    /* Select the child node which will be enlarged the least if pCell
    ** is inserted into it. Resolve ties by choosing the entry with
    ** the smallest area.
    */
2133
2134
2135
2136
2137
2138
2139


2140
2141
2142
2143
2144





2145



2146
2147
2148
2149
2150
2151
2152
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274

2275
2276
2277
2278
2279
2280
2281
2282
2283
2284







+
+





+
+
+
+
+
-
+
+
+







*/
static int AdjustTree(
  Rtree *pRtree,                    /* Rtree table */
  RtreeNode *pNode,                 /* Adjust ancestry of this node. */
  RtreeCell *pCell                  /* This cell was just inserted */
){
  RtreeNode *p = pNode;
  int cnt = 0;
  int rc;
  while( p->pParent ){
    RtreeNode *pParent = p->pParent;
    RtreeCell cell;
    int iCell;

    cnt++;
    if( NEVER(cnt>100) ){
      RTREE_IS_CORRUPT(pRtree);
      return SQLITE_CORRUPT_VTAB;
    }
    if( nodeParentIndex(pRtree, p, &iCell) ){
    rc = nodeParentIndex(pRtree, p, &iCell);
    if( NEVER(rc!=SQLITE_OK) ){
      RTREE_IS_CORRUPT(pRtree);
      return SQLITE_CORRUPT_VTAB;
    }

    nodeGetCell(pRtree, pParent, iCell, &cell);
    if( !cellContains(pRtree, &cell, pCell) ){
      cellUnion(pRtree, &cell, pCell);
      nodeOverwriteCell(pRtree, pParent, &cell, iCell);
2335
2336
2337
2338
2339
2340
2341
2342

2343
2344

2345
2346
2347
2348
2349
2350
2351
2467
2468
2469
2470
2471
2472
2473

2474
2475

2476
2477
2478
2479
2480
2481
2482
2483







-
+

-
+







  int *aSpare;
  int ii;

  int iBestDim = 0;
  int iBestSplit = 0;
  RtreeDValue fBestMargin = RTREE_ZERO;

  int nByte = (pRtree->nDim+1)*(sizeof(int*)+nCell*sizeof(int));
  sqlite3_int64 nByte = (pRtree->nDim+1)*(sizeof(int*)+nCell*sizeof(int));

  aaSorted = (int **)sqlite3_malloc(nByte);
  aaSorted = (int **)sqlite3_malloc64(nByte);
  if( !aaSorted ){
    return SQLITE_NOMEM;
  }

  aSpare = &((int *)&aaSorted[pRtree->nDim])[pRtree->nDim*nCell];
  memset(aaSorted, 0, nByte);
  for(ii=0; ii<pRtree->nDim; ii++){
2426
2427
2428
2429
2430
2431
2432




2433
2434
2435
2436
2437
2438

2439
2440
2441
2442
2443
2444
2445
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582







+
+
+
+






+







  RtreeNode *pNode, 
  int iHeight
){
  int (*xSetMapping)(Rtree *, sqlite3_int64, sqlite3_int64);
  xSetMapping = ((iHeight==0)?rowidWrite:parentWrite);
  if( iHeight>0 ){
    RtreeNode *pChild = nodeHashLookup(pRtree, iRowid);
    RtreeNode *p;
    for(p=pNode; p; p=p->pParent){
      if( p==pChild ) return SQLITE_CORRUPT_VTAB;
    }
    if( pChild ){
      nodeRelease(pRtree, pChild->pParent);
      nodeReference(pNode);
      pChild->pParent = pNode;
    }
  }
  if( NEVER(pNode==0) ) return SQLITE_ERROR;
  return xSetMapping(pRtree, iRowid, pNode->iNode);
}

static int SplitNode(
  Rtree *pRtree,
  RtreeNode *pNode,
  RtreeCell *pCell,
2458
2459
2460
2461
2462
2463
2464
2465

2466
2467
2468
2469
2470
2471
2472
2595
2596
2597
2598
2599
2600
2601

2602
2603
2604
2605
2606
2607
2608
2609







-
+








  RtreeCell leftbbox;
  RtreeCell rightbbox;

  /* Allocate an array and populate it with a copy of pCell and 
  ** all cells from node pLeft. Then zero the original node.
  */
  aCell = sqlite3_malloc((sizeof(RtreeCell)+sizeof(int))*(nCell+1));
  aCell = sqlite3_malloc64((sizeof(RtreeCell)+sizeof(int))*(nCell+1));
  if( !aCell ){
    rc = SQLITE_NOMEM;
    goto splitnode_out;
  }
  aiUsed = (int *)&aCell[nCell+1];
  memset(aiUsed, 0, sizeof(int)*(nCell+1));
  for(i=0; i<nCell; i++){
2521
2522
2523
2524
2525
2526
2527
2528

2529
2530

2531
2532

2533
2534
2535
2536
2537
2538
2539
2658
2659
2660
2661
2662
2663
2664

2665
2666
2667
2668
2669

2670
2671
2672
2673
2674
2675
2676
2677







-
+


+

-
+







    if( rc!=SQLITE_OK ){
      goto splitnode_out;
    }
  }else{
    RtreeNode *pParent = pLeft->pParent;
    int iCell;
    rc = nodeParentIndex(pRtree, pLeft, &iCell);
    if( rc==SQLITE_OK ){
    if( ALWAYS(rc==SQLITE_OK) ){
      nodeOverwriteCell(pRtree, pParent, &leftbbox, iCell);
      rc = AdjustTree(pRtree, pParent, &leftbbox);
      assert( rc==SQLITE_OK );
    }
    if( rc!=SQLITE_OK ){
    if( NEVER(rc!=SQLITE_OK) ){
      goto splitnode_out;
    }
  }
  if( (rc = rtreeInsertCell(pRtree, pRight->pParent, &rightbbox, iHeight+1)) ){
    goto splitnode_out;
  }

2600
2601
2602
2603
2604
2605
2606
2607

2608
2609
2610
2611
2612
2613




2614
2615
2616
2617
2618
2619
2620
2738
2739
2740
2741
2742
2743
2744

2745
2746
2747
2748
2749
2750

2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761







-
+





-
+
+
+
+







      /* Before setting pChild->pParent, test that we are not creating a
      ** loop of references (as we would if, say, pChild==pParent). We don't
      ** want to do this as it leads to a memory leak when trying to delete
      ** the referenced counted node structures.
      */
      iNode = sqlite3_column_int64(pRtree->pReadParent, 0);
      for(pTest=pLeaf; pTest && pTest->iNode!=iNode; pTest=pTest->pParent);
      if( !pTest ){
      if( pTest==0 ){
        rc2 = nodeAcquire(pRtree, iNode, 0, &pChild->pParent);
      }
    }
    rc = sqlite3_reset(pRtree->pReadParent);
    if( rc==SQLITE_OK ) rc = rc2;
    if( rc==SQLITE_OK && !pChild->pParent ) rc = SQLITE_CORRUPT_VTAB;
    if( rc==SQLITE_OK && !pChild->pParent ){
      RTREE_IS_CORRUPT(pRtree);
      rc = SQLITE_CORRUPT_VTAB;
    }
    pChild = pChild->pParent;
  }
  return rc;
}

static int deleteCell(Rtree *, RtreeNode *, int, int);

2628
2629
2630
2631
2632
2633
2634

2635
2636
2637
2638
2639
2640
2641
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783







+








  /* Remove the entry in the parent cell. */
  rc = nodeParentIndex(pRtree, pNode, &iCell);
  if( rc==SQLITE_OK ){
    pParent = pNode->pParent;
    pNode->pParent = 0;
    rc = deleteCell(pRtree, pParent, iCell, iHeight+1);
    testcase( rc!=SQLITE_OK );
  }
  rc2 = nodeRelease(pRtree, pParent);
  if( rc==SQLITE_OK ){
    rc = rc2;
  }
  if( rc!=SQLITE_OK ){
    return rc;
2746
2747
2748
2749
2750
2751
2752
2753

2754
2755
2756
2757
2758
2759
2760
2888
2889
2890
2891
2892
2893
2894

2895
2896
2897
2898
2899
2900
2901
2902







-
+








  nCell = NCELL(pNode)+1;
  n = (nCell+1)&(~1);

  /* Allocate the buffers used by this operation. The allocation is
  ** relinquished before this function returns.
  */
  aCell = (RtreeCell *)sqlite3_malloc(n * (
  aCell = (RtreeCell *)sqlite3_malloc64(n * (
    sizeof(RtreeCell)     +         /* aCell array */
    sizeof(int)           +         /* aOrder array */
    sizeof(int)           +         /* aSpare array */
    sizeof(RtreeDValue)             /* aDistance array */
  ));
  if( !aCell ){
    return SQLITE_NOMEM;
2850
2851
2852
2853
2854
2855
2856
2857

2858
2859
2860
2861
2862
2863
2864
2992
2993
2994
2995
2996
2997
2998

2999
3000
3001
3002
3003
3004
3005
3006







-
+







      rc = SplitNode(pRtree, pNode, pCell, iHeight);
    }else{
      pRtree->iReinsertHeight = iHeight;
      rc = Reinsert(pRtree, pNode, pCell, iHeight);
    }
  }else{
    rc = AdjustTree(pRtree, pNode, pCell);
    if( rc==SQLITE_OK ){
    if( ALWAYS(rc==SQLITE_OK) ){
      if( iHeight==0 ){
        rc = rowidWrite(pRtree, pCell->iRowid, pNode->iNode);
      }else{
        rc = parentWrite(pRtree, pCell->iRowid, pNode->iNode);
      }
    }
  }
2919
2920
2921
2922
2923
2924
2925
2926




2927
2928

2929
2930
2931
2932
2933
2934
2935
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073

3074
3075
3076
3077
3078
3079
3080
3081








+
+
+
+

-
+








  /* Obtain a reference to the leaf node that contains the entry 
  ** about to be deleted. 
  */
  if( rc==SQLITE_OK ){
    rc = findLeafNode(pRtree, iDelete, &pLeaf, 0);
  }

#ifdef CORRUPT_DB
  assert( pLeaf!=0 || rc!=SQLITE_OK || CORRUPT_DB );
#endif

  /* Delete the cell in question from the leaf node. */
  if( rc==SQLITE_OK ){
  if( rc==SQLITE_OK && pLeaf ){
    int rc2;
    rc = nodeRowidIndex(pRtree, pLeaf, iDelete, &iCell);
    if( rc==SQLITE_OK ){
      rc = deleteCell(pRtree, pLeaf, iCell, 0);
    }
    rc2 = nodeRelease(pRtree, pLeaf);
    if( rc==SQLITE_OK ){
2952
2953
2954
2955
2956
2957
2958
2959

2960
2961
2962
2963
2964
2965
2966
3098
3099
3100
3101
3102
3103
3104

3105
3106
3107
3108
3109
3110
3111
3112







-
+







  ** the root node (the operation that Gutman's paper says to perform 
  ** in this scenario).
  */
  if( rc==SQLITE_OK && pRtree->iDepth>0 && NCELL(pRoot)==1 ){
    int rc2;
    RtreeNode *pChild = 0;
    i64 iChild = nodeGetRowid(pRtree, pRoot, 0);
    rc = nodeAcquire(pRtree, iChild, pRoot, &pChild);
    rc = nodeAcquire(pRtree, iChild, pRoot, &pChild);  /* tag-20210916a */
    if( rc==SQLITE_OK ){
      rc = removeNode(pRtree, pChild, pRtree->iDepth-1);
    }
    rc2 = nodeRelease(pRtree, pChild);
    if( rc==SQLITE_OK ) rc = rc2;
    if( rc==SQLITE_OK ){
      pRtree->iDepth--;
3085
3086
3087
3088
3089
3090
3091
3092

3093
3094
3095
3096
3097
3098
3099
3231
3232
3233
3234
3235
3236
3237

3238
3239
3240
3241
3242
3243
3244
3245







-
+







    ** since the write might do a rebalance which would disrupt the read
    ** cursor. */
    return SQLITE_LOCKED_VTAB;
  }
  rtreeReference(pRtree);
  assert(nData>=1);

  cell.iRowid = 0;  /* Used only to suppress a compiler warning */
  memset(&cell, 0, sizeof(cell));

  /* Constraint handling. A write operation on an r-tree table may return
  ** SQLITE_CONSTRAINT for two reasons:
  **
  **   1. A duplicate rowid value, or
  **   2. The supplied data violates the "x2>=x1" constraint.
  **
3193
3194
3195
3196
3197
3198
3199
3200

3201
3202
3203
3204
3205
3206
3207
3339
3340
3341
3342
3343
3344
3345

3346
3347
3348
3349
3350
3351
3352
3353







-
+







      pRtree->iReinsertHeight = -1;
      rc = rtreeInsertCell(pRtree, pLeaf, &cell, 0);
      rc2 = nodeRelease(pRtree, pLeaf);
      if( rc==SQLITE_OK ){
        rc = rc2;
      }
    }
    if( pRtree->nAux ){
    if( rc==SQLITE_OK && pRtree->nAux ){
      sqlite3_stmt *pUp = pRtree->pWriteAux;
      int jj;
      sqlite3_bind_int64(pUp, 1, *pRowid);
      for(jj=0; jj<pRtree->nAux; jj++){
        sqlite3_bind_value(pUp, jj+2, aData[pRtree->nDim2+3+jj]);
      }
      sqlite3_step(pUp);
3287
3288
3289
3290
3291
3292
3293
3294

3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324

3325
3326
3327
3328
3329
3330
3331
3433
3434
3435
3436
3437
3438
3439

3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456










3457
3458
3459

3460
3461
3462
3463
3464
3465
3466
3467







-
+
















-
-
-
-
-
-
-
-
-
-



-
+







** on sqlite_stat1 data. Otherwise, use RTREE_DEFAULT_ROWEST.
*/
static int rtreeQueryStat1(sqlite3 *db, Rtree *pRtree){
  const char *zFmt = "SELECT stat FROM %Q.sqlite_stat1 WHERE tbl = '%q_rowid'";
  char *zSql;
  sqlite3_stmt *p;
  int rc;
  i64 nRow = 0;
  i64 nRow = RTREE_MIN_ROWEST;

  rc = sqlite3_table_column_metadata(
      db, pRtree->zDb, "sqlite_stat1",0,0,0,0,0,0
  );
  if( rc!=SQLITE_OK ){
    pRtree->nRowEst = RTREE_DEFAULT_ROWEST;
    return rc==SQLITE_ERROR ? SQLITE_OK : rc;
  }
  zSql = sqlite3_mprintf(zFmt, pRtree->zDb, pRtree->zName);
  if( zSql==0 ){
    rc = SQLITE_NOMEM;
  }else{
    rc = sqlite3_prepare_v2(db, zSql, -1, &p, 0);
    if( rc==SQLITE_OK ){
      if( sqlite3_step(p)==SQLITE_ROW ) nRow = sqlite3_column_int64(p, 0);
      rc = sqlite3_finalize(p);
    }else if( rc!=SQLITE_NOMEM ){
      rc = SQLITE_OK;
    }

    if( rc==SQLITE_OK ){
      if( nRow==0 ){
        pRtree->nRowEst = RTREE_DEFAULT_ROWEST;
      }else{
        pRtree->nRowEst = MAX(nRow, RTREE_MIN_ROWEST);
      }
    }
    sqlite3_free(zSql);
  }

  pRtree->nRowEst = MAX(nRow, RTREE_MIN_ROWEST);
  return rc;
}


/*
** Return true if zName is the extension on one of the shadow tables used
** by this module.
3391
3392
3393
3394
3395
3396
3397

3398
3399
3400
3401
3402
3403
3404
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541







+







    /* Read and write the xxx_parent table */
    "SELECT parentnode FROM '%q'.'%q_parent' WHERE nodeno = ?1",
    "INSERT OR REPLACE INTO '%q'.'%q_parent' VALUES(?1, ?2)",
    "DELETE FROM '%q'.'%q_parent' WHERE nodeno = ?1"
  };
  sqlite3_stmt **appStmt[N_STATEMENT];
  int i;
  const int f = SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_NO_VTAB;

  pRtree->db = db;

  if( isCreate ){
    char *zCreate;
    sqlite3_str *p = sqlite3_str_new(db);
    int ii;
3447
3448
3449
3450
3451
3452
3453
3454

3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473

3474
3475
3476



3477
3478
3479
3480
3481
3482
3483
3484
3485

3486
3487
3488
3489
3490
3491
3492
3493
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
3612

3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623

3624

3625
3626
3627
3628
3629
3630
3631







-
+
-


















+


-
+
+
+








-
+
-







       /* An UPSERT is very slightly slower than REPLACE, but it is needed
       ** if there are auxiliary columns */
       zFormat = "INSERT INTO\"%w\".\"%w_rowid\"(rowid,nodeno)VALUES(?1,?2)"
                  "ON CONFLICT(rowid)DO UPDATE SET nodeno=excluded.nodeno";
    }
    zSql = sqlite3_mprintf(zFormat, zDb, zPrefix);
    if( zSql ){
      rc = sqlite3_prepare_v3(db, zSql, -1, SQLITE_PREPARE_PERSISTENT,
      rc = sqlite3_prepare_v3(db, zSql, -1, f, appStmt[i], 0); 
                              appStmt[i], 0); 
    }else{
      rc = SQLITE_NOMEM;
    }
    sqlite3_free(zSql);
  }
  if( pRtree->nAux ){
    pRtree->zReadAuxSql = sqlite3_mprintf(
       "SELECT * FROM \"%w\".\"%w_rowid\" WHERE rowid=?1",
       zDb, zPrefix);
    if( pRtree->zReadAuxSql==0 ){
      rc = SQLITE_NOMEM;
    }else{
      sqlite3_str *p = sqlite3_str_new(db);
      int ii;
      char *zSql;
      sqlite3_str_appendf(p, "UPDATE \"%w\".\"%w_rowid\"SET ", zDb, zPrefix);
      for(ii=0; ii<pRtree->nAux; ii++){
        if( ii ) sqlite3_str_append(p, ",", 1);
#ifdef SQLITE_ENABLE_GEOPOLY
        if( ii<pRtree->nAuxNotNull ){
          sqlite3_str_appendf(p,"a%d=coalesce(?%d,a%d)",ii,ii+2,ii);
        }else{
        }else
#endif
        {
          sqlite3_str_appendf(p,"a%d=?%d",ii,ii+2);
        }
      }
      sqlite3_str_appendf(p, " WHERE rowid=?1");
      zSql = sqlite3_str_finish(p);
      if( zSql==0 ){
        rc = SQLITE_NOMEM;
      }else{
        rc = sqlite3_prepare_v3(db, zSql, -1, SQLITE_PREPARE_PERSISTENT,
        rc = sqlite3_prepare_v3(db, zSql, -1, f, &pRtree->pWriteAux, 0); 
                                &pRtree->pWriteAux, 0); 
        sqlite3_free(zSql);
      }
    }
  }

  return rc;
}
3555
3556
3557
3558
3559
3560
3561

3562
3563
3564
3565
3566
3567
3568
3569








3570
3571
3572
3573
3574
3575
3576
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723







+








+
+
+
+
+
+
+
+







        pRtree->zDb, pRtree->zName
    );
    rc = getIntFromStmt(db, zSql, &pRtree->iNodeSize);
    if( rc!=SQLITE_OK ){
      *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
    }else if( pRtree->iNodeSize<(512-64) ){
      rc = SQLITE_CORRUPT_VTAB;
      RTREE_IS_CORRUPT(pRtree);
      *pzErr = sqlite3_mprintf("undersize RTree blobs in \"%q_node\"",
                               pRtree->zName);
    }
  }

  sqlite3_free(zSql);
  return rc;
}

/*
** Return the length of a token
*/
static int rtreeTokenLength(const char *z){
  int dummy = 0;
  return sqlite3GetToken((const unsigned char*)z,&dummy);
}

/* 
** This function is the implementation of both the xConnect and xCreate
** methods of the r-tree virtual table.
**
**   argv[0]   -> module name
**   argv[1]   -> database name
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
3747
3748
3749
3750
3751
3752
3753


3754
3755
3756
3757
3758
3759
3760
3761
3762
3763

3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782

3783
3784
3785
3786

3787
3788

3789
3790
3791
3792
3793
3794

3795
3796
3797
3798
3799
3800
3801
3802
3803







-
-
+
+








-
+


















-
+
+

+
-
+

-
+



+

-
+
+







    "Wrong number of columns for an rtree table",         /* 1 */
    "Too few columns for an rtree table",                 /* 2 */
    "Too many columns for an rtree table",                /* 3 */
    "Auxiliary rtree columns must be last"                /* 4 */
  };

  assert( RTREE_MAX_AUX_COLUMN<256 ); /* Aux columns counted by a u8 */
  if( argc>RTREE_MAX_AUX_COLUMN+3 ){
    *pzErr = sqlite3_mprintf("%s", aErrMsg[3]);
  if( argc<6 || argc>RTREE_MAX_AUX_COLUMN+3 ){
    *pzErr = sqlite3_mprintf("%s", aErrMsg[2 + (argc>=6)]);
    return SQLITE_ERROR;
  }

  sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1);

  /* Allocate the sqlite3_vtab structure */
  nDb = (int)strlen(argv[1]);
  nName = (int)strlen(argv[2]);
  pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2);
  pRtree = (Rtree *)sqlite3_malloc64(sizeof(Rtree)+nDb+nName+2);
  if( !pRtree ){
    return SQLITE_NOMEM;
  }
  memset(pRtree, 0, sizeof(Rtree)+nDb+nName+2);
  pRtree->nBusy = 1;
  pRtree->base.pModule = &rtreeModule;
  pRtree->zDb = (char *)&pRtree[1];
  pRtree->zName = &pRtree->zDb[nDb+1];
  pRtree->eCoordType = (u8)eCoordType;
  memcpy(pRtree->zDb, argv[1], nDb);
  memcpy(pRtree->zName, argv[2], nName);


  /* Create/Connect to the underlying relational database schema. If
  ** that is successful, call sqlite3_declare_vtab() to configure
  ** the r-tree table schema.
  */
  pSql = sqlite3_str_new(db);
  sqlite3_str_appendf(pSql, "CREATE TABLE x(%s", argv[3]);
  sqlite3_str_appendf(pSql, "CREATE TABLE x(%.*s INT", 
                      rtreeTokenLength(argv[3]), argv[3]);
  for(ii=4; ii<argc; ii++){
    const char *zArg = argv[ii];
    if( argv[ii][0]=='+' ){
    if( zArg[0]=='+' ){
      pRtree->nAux++;
      sqlite3_str_appendf(pSql, ",%s", argv[ii]+1);
      sqlite3_str_appendf(pSql, ",%.*s", rtreeTokenLength(zArg+1), zArg+1);
    }else if( pRtree->nAux>0 ){
      break;
    }else{
      static const char *azFormat[] = {",%.*s REAL", ",%.*s INT"};
      pRtree->nDim2++;
      sqlite3_str_appendf(pSql, ",%s", argv[ii]);
      sqlite3_str_appendf(pSql, azFormat[eCoordType],
                          rtreeTokenLength(zArg), zArg);
    }
  }
  sqlite3_str_appendf(pSql, ");");
  zSql = sqlite3_str_finish(pSql);
  if( !zSql ){
    rc = SQLITE_NOMEM;
  }else if( ii<argc ){
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717



3718
3719
3720
3721
3722

3723
3724
3725




3726

3727
3728
3729
3730
3731
3732
3733

3734

3735
3736
3737
3738
3739

3740
3741
3742

3743
3744
3745
3746

3747
3748
3749
3750
3751
3752
3753

3754
3755
3756



3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771

3772
3773
3774
3775

3776




3777
3778
3779
3780
3781
3782
3783
3858
3859
3860
3861
3862
3863
3864

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

3899

3900







3901



3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925

3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936







-



+
+
+





+



+
+
+
+

+

-
-




+
-
+
-


-
-
+

-
-
+

-

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















+




+
-
+
+
+
+







**
** The human readable string takes the form of a Tcl list with one
** entry for each cell in the r-tree node. Each entry is itself a
** list, containing the 8-byte rowid/pageno followed by the 
** <num-dimension>*2 coordinates.
*/
static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
  char *zText = 0;
  RtreeNode node;
  Rtree tree;
  int ii;
  int nData;
  int errCode;
  sqlite3_str *pOut;

  UNUSED_PARAMETER(nArg);
  memset(&node, 0, sizeof(RtreeNode));
  memset(&tree, 0, sizeof(Rtree));
  tree.nDim = (u8)sqlite3_value_int(apArg[0]);
  if( tree.nDim<1 || tree.nDim>5 ) return;
  tree.nDim2 = tree.nDim*2;
  tree.nBytesPerCell = 8 + 8 * tree.nDim;
  node.zData = (u8 *)sqlite3_value_blob(apArg[1]);
  if( node.zData==0 ) return;
  nData = sqlite3_value_bytes(apArg[1]);
  if( nData<4 ) return;
  if( nData<NCELL(&node)*tree.nBytesPerCell ) return;

  pOut = sqlite3_str_new(0);
  for(ii=0; ii<NCELL(&node); ii++){
    char zCell[512];
    int nCell = 0;
    RtreeCell cell;
    int jj;

    nodeGetCell(&tree, &node, ii, &cell);
    if( ii>0 ) sqlite3_str_append(pOut, " ", 1);
    sqlite3_snprintf(512-nCell,&zCell[nCell],"%lld", cell.iRowid);
    sqlite3_str_appendf(pOut, "{%lld", cell.iRowid);
    nCell = (int)strlen(zCell);
    for(jj=0; jj<tree.nDim2; jj++){
#ifndef SQLITE_RTREE_INT_ONLY
      sqlite3_snprintf(512-nCell,&zCell[nCell], " %g",
                       (double)cell.aCoord[jj].f);
      sqlite3_str_appendf(pOut, " %g", (double)cell.aCoord[jj].f);
#else
      sqlite3_snprintf(512-nCell,&zCell[nCell], " %d",
                       cell.aCoord[jj].i);
      sqlite3_str_appendf(pOut, " %d", cell.aCoord[jj].i);
#endif
      nCell = (int)strlen(zCell);
    }

    sqlite3_str_append(pOut, "}", 1);
    if( zText ){
      char *zTextNew = sqlite3_mprintf("%s {%s}", zText, zCell);
      sqlite3_free(zText);
      zText = zTextNew;
    }else{
      zText = sqlite3_mprintf("{%s}", zCell);
    }
  }
  }
  
  sqlite3_result_text(ctx, zText, -1, sqlite3_free);
  errCode = sqlite3_str_errcode(pOut);
  sqlite3_result_text(ctx, sqlite3_str_finish(pOut), -1, sqlite3_free);
  sqlite3_result_error_code(ctx, errCode);
}

/* This routine implements an SQL function that returns the "depth" parameter
** from the front of a blob that is an r-tree node.  For example:
**
**     SELECT rtreedepth(data) FROM rt_node WHERE nodeno=1;
**
** The depth value is 0 for all nodes other than the root node, and the root
** 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().
*/
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
4031
4032
4033
4034
4035
4036
4037

4038

4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049

4050
4051
4052
4053
4054
4055
4056
4057







-
+
-











-
+







** Or, if an error does occur, NULL is returned and an error code left
** in the RtreeCheck object. The final value of *pnNode is undefined in
** this case.
*/
static u8 *rtreeCheckGetNode(RtreeCheck *pCheck, i64 iNode, int *pnNode){
  u8 *pRet = 0;                   /* Return value */

  assert( pCheck->rc==SQLITE_OK );
  if( pCheck->rc==SQLITE_OK && pCheck->pGetNode==0 ){
  if( pCheck->pGetNode==0 ){
    pCheck->pGetNode = rtreeCheckPrepare(pCheck,
        "SELECT data FROM %Q.'%q_node' WHERE nodeno=?", 
        pCheck->zDb, pCheck->zTab
    );
  }

  if( pCheck->rc==SQLITE_OK ){
    sqlite3_bind_int64(pCheck->pGetNode, 1, iNode);
    if( sqlite3_step(pCheck->pGetNode)==SQLITE_ROW ){
      int nNode = sqlite3_column_bytes(pCheck->pGetNode, 0);
      const u8 *pNode = (const u8*)sqlite3_column_blob(pCheck->pGetNode, 0);
      pRet = sqlite3_malloc(nNode);
      pRet = sqlite3_malloc64(nNode);
      if( pRet==0 ){
        pCheck->rc = SQLITE_NOMEM;
      }else{
        memcpy(pRet, pNode, nNode);
        *pnNode = nNode;
      }
    }
4136
4137
4138
4139
4140
4141
4142
4143
4144




4145
4146
4147
4148
4149
4150
4151
4288
4289
4290
4291
4292
4293
4294


4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305







-
-
+
+
+
+








  /* Find the number of auxiliary columns */
  if( check.rc==SQLITE_OK ){
    pStmt = rtreeCheckPrepare(&check, "SELECT * FROM %Q.'%q_rowid'", zDb, zTab);
    if( pStmt ){
      nAux = sqlite3_column_count(pStmt) - 2;
      sqlite3_finalize(pStmt);
    }
    check.rc = SQLITE_OK;
    }else 
    if( check.rc!=SQLITE_NOMEM ){
      check.rc = SQLITE_OK;
    }
  }

  /* Find number of dimensions in the rtree table. */
  pStmt = rtreeCheckPrepare(&check, "SELECT * FROM %Q.%Q", zDb, zTab);
  if( pStmt ){
    int rc;
    check.nDim = (sqlite3_column_count(pStmt) - 1 - nAux) / 2;
4324
4325
4326
4327
4328
4329
4330
4331

4332
4333
4334
4335
4336

4337
4338
4339
4340
4341
4342
4343
4478
4479
4480
4481
4482
4483
4484

4485
4486
4487
4488
4489

4490
4491
4492
4493
4494
4495
4496
4497







-
+




-
+







** The R-Tree MATCH operator will read the returned BLOB, deserialize
** the RtreeMatchArg object, and use the RtreeMatchArg object to figure
** out which elements of the R-Tree should be returned by the query.
*/
static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
  RtreeGeomCallback *pGeomCtx = (RtreeGeomCallback *)sqlite3_user_data(ctx);
  RtreeMatchArg *pBlob;
  int nBlob;
  sqlite3_int64 nBlob;
  int memErr = 0;

  nBlob = sizeof(RtreeMatchArg) + (nArg-1)*sizeof(RtreeDValue)
           + nArg*sizeof(sqlite3_value*);
  pBlob = (RtreeMatchArg *)sqlite3_malloc(nBlob);
  pBlob = (RtreeMatchArg *)sqlite3_malloc64(nBlob);
  if( !pBlob ){
    sqlite3_result_error_nomem(ctx);
  }else{
    int i;
    pBlob->iSize = nBlob;
    pBlob->cb = pGeomCtx[0];
    pBlob->apSqlParam = (sqlite3_value**)&pBlob->aParam[nArg];
4394
4395
4396
4397
4398
4399
4400
4401




4402
4403
4404
4405
4406
4407
4408
4548
4549
4550
4551
4552
4553
4554

4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565







-
+
+
+
+







  void *pContext,              /* Extra data passed into the callback */
  void (*xDestructor)(void*)   /* Destructor for the extra data */
){
  RtreeGeomCallback *pGeomCtx;      /* Context object for new user-function */

  /* Allocate and populate the context object. */
  pGeomCtx = (RtreeGeomCallback *)sqlite3_malloc(sizeof(RtreeGeomCallback));
  if( !pGeomCtx ) return SQLITE_NOMEM;
  if( !pGeomCtx ){
    if( xDestructor ) xDestructor(pContext);
    return SQLITE_NOMEM;
  }
  pGeomCtx->xGeom = 0;
  pGeomCtx->xQueryFunc = xQueryFunc;
  pGeomCtx->xDestructor = xDestructor;
  pGeomCtx->pContext = pContext;
  return sqlite3_create_function_v2(db, zQueryFunc, -1, SQLITE_ANY, 
      (void *)pGeomCtx, geomCallback, 0, 0, rtreeFreeCallback
  );

Changes to ext/rtree/rtree1.test.

53
54
55
56
57
58
59
60

61
62



63
64
65
66
67
68
69
53
54
55
56
57
58
59

60
61
62
63
64
65
66
67
68
69
70
71
72







-
+


+
+
+







#

# Test creating and dropping an rtree table.
#
do_test rtree-1.1.1 {
  execsql { CREATE VIRTUAL TABLE t1 USING rtree(ii, x1, x2, y1, y2) }
} {}
do_test rtree-1.1.2 {
do_test rtree-1.1.2a {
  execsql { SELECT name FROM sqlite_master ORDER BY name }
} {t1 t1_node t1_parent t1_rowid}
do_execsql_test rtree-1.1.2b {
  SELECT name FROM pragma_table_list WHERE type='shadow' ORDER BY name;
} {t1_node t1_parent t1_rowid}
do_test rtree-1.1.3 {
  execsql { 
    DROP TABLE t1; 
    SELECT name FROM sqlite_master ORDER BY name;
  }
} {}

108
109
110
111
112
113
114



115
116
117
118
119
120
121
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127







+
+
+







    catchsql " 
      CREATE VIRTUAL TABLE t1 USING rtree($columns);
    "
  } $X

  catchsql { DROP TABLE t1 }
}
do_catchsql_test rtree-1.3.1000 {
  CREATE VIRTUAL TABLE t1000 USING rtree;
} {1 {Too few columns for an rtree table}}

# Like execsql except display output as integer where that can be
# done without loss of information.
#
proc execsql_intout {sql} {
  set out {}
  foreach term [execsql $sql] {
370
371
372
373
374
375
376
377
378
379
380
381
382
383





































384
385
386
387
388
389
390
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







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







do_test rtree-8.1.1 {
  execsql {
    CREATE VIRTUAL TABLE t6 USING rtree(ii, x1, x2);
    INSERT INTO t6 VALUES(1, 3, 7);
    INSERT INTO t6 VALUES(2, 4, 6);
  }
} {}
do_test rtree-8.1.2 { execsql { SELECT ii FROM t6 WHERE x1>2 } } {1 2}
do_test rtree-8.1.3 { execsql { SELECT ii FROM t6 WHERE x1>3 } } {2}
do_test rtree-8.1.4 { execsql { SELECT ii FROM t6 WHERE x1>4 } } {}
do_test rtree-8.1.5 { execsql { SELECT ii FROM t6 WHERE x1>5 } } {}
do_test rtree-8.1.6 { execsql { SELECT ii FROM t6 WHERE x1<3 } } {}
do_test rtree-8.1.7 { execsql { SELECT ii FROM t6 WHERE x1<4 } } {1}
do_test rtree-8.1.8 { execsql { SELECT ii FROM t6 WHERE x1<5 } } {1 2}
do_test rtree-8.1.2 { execsql { SELECT ii FROM t6 WHERE x1>2 } }   {1 2}
do_test rtree-8.1.3 { execsql { SELECT ii FROM t6 WHERE x1>3 } }   {2}
do_test rtree-8.1.4 { execsql { SELECT ii FROM t6 WHERE x1>4 } }   {}
do_test rtree-8.1.5 { execsql { SELECT ii FROM t6 WHERE x1>5 } }   {}
do_test rtree-8.1.6 { execsql { SELECT ii FROM t6 WHERE x1>''} }   {}
do_test rtree-8.1.7 { execsql { SELECT ii FROM t6 WHERE x1>null}}  {}
do_test rtree-8.1.8 { execsql { SELECT ii FROM t6 WHERE x1>'2'} }   {1 2}
do_test rtree-8.1.9 { execsql { SELECT ii FROM t6 WHERE x1>'3'} }   {2}
do_test rtree-8.2.2 { execsql { SELECT ii FROM t6 WHERE x1>=2 } }  {1 2}
do_test rtree-8.2.3 { execsql { SELECT ii FROM t6 WHERE x1>=3 } }  {1 2}
do_test rtree-8.2.4 { execsql { SELECT ii FROM t6 WHERE x1>=4 } }  {2}
do_test rtree-8.2.5 { execsql { SELECT ii FROM t6 WHERE x1>=5 } }  {}
do_test rtree-8.2.6 { execsql { SELECT ii FROM t6 WHERE x1>=''} }  {}
do_test rtree-8.2.7 { execsql { SELECT ii FROM t6 WHERE x1>=null}} {}
do_test rtree-8.2.8 { execsql { SELECT ii FROM t6 WHERE x1>='4'} } {2}
do_test rtree-8.2.9 { execsql { SELECT ii FROM t6 WHERE x1>='5'} } {}
do_test rtree-8.3.2 { execsql { SELECT ii FROM t6 WHERE x1<2 } }   {}
do_test rtree-8.3.3 { execsql { SELECT ii FROM t6 WHERE x1<3 } }   {}
do_test rtree-8.3.4 { execsql { SELECT ii FROM t6 WHERE x1<4 } }   {1}
do_test rtree-8.3.5 { execsql { SELECT ii FROM t6 WHERE x1<5 } }   {1 2}
do_test rtree-8.3.6 { execsql { SELECT ii FROM t6 WHERE x1<''} }   {1 2}
do_test rtree-8.3.7 { execsql { SELECT ii FROM t6 WHERE x1<null}}  {}
do_test rtree-8.3.8 { execsql { SELECT ii FROM t6 WHERE x1<'3'} }  {}
do_test rtree-8.3.9 { execsql { SELECT ii FROM t6 WHERE x1<'4'} }  {1}
do_test rtree-8.4.2 { execsql { SELECT ii FROM t6 WHERE x1<=2 } }  {}
do_test rtree-8.4.3 { execsql { SELECT ii FROM t6 WHERE x1<=3 } }  {1}
do_test rtree-8.4.4 { execsql { SELECT ii FROM t6 WHERE x1<=4 } }  {1 2}
do_test rtree-8.4.5 { execsql { SELECT ii FROM t6 WHERE x1<=5 } }  {1 2}
do_test rtree-8.4.6 { execsql { SELECT ii FROM t6 WHERE x1<=''} }  {1 2}
do_test rtree-8.4.7 { execsql { SELECT ii FROM t6 WHERE x1<=null}} {}
do_test rtree-8.5.2 { execsql { SELECT ii FROM t6 WHERE x1=2 } }   {}
do_test rtree-8.5.3 { execsql { SELECT ii FROM t6 WHERE x1=3 } }   {1}
do_test rtree-8.5.4 { execsql { SELECT ii FROM t6 WHERE x1=4 } }   {2}
do_test rtree-8.5.5 { execsql { SELECT ii FROM t6 WHERE x1=5 } }   {}
do_test rtree-8.5.6 { execsql { SELECT ii FROM t6 WHERE x1=''} }   {}
do_test rtree-8.5.7 { execsql { SELECT ii FROM t6 WHERE x1=null}}  {}


#----------------------------------------------------------------------------
# Test cases rtree-9.*
#
# Test that ticket #3549 is fixed.
do_test rtree-9.1 {
  execsql {
574
575
576
577
578
579
580













581

582

583
584
585
586
587
588
589

590
591
592
593
594
595
596
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







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

+
-
+






-
+







}
do_execsql_test 14.5 {
  SELECT * FROM t10;
} {
  1 0.0 0.0
  2 52.0 81.0
}
do_execsql_test 14.6 {
  INSERT INTO t10 VALUES(0,10,20);
  SELECT * FROM t10 WHERE ii=NULL;
} {}
do_execsql_test 14.7 {
  SELECT * FROM t10 WHERE ii='xyz';
} {}
do_execsql_test 14.8 {
  SELECT * FROM t10 WHERE ii='0.0';
} {0 10.0 20.0}
do_execsql_test 14.9 {
  SELECT * FROM t10 WHERE ii=0.0;
} {0 10.0 20.0}


do_execsql_test 14.4 {
do_execsql_test 14.104 {
  DROP TABLE t10;
  CREATE VIRTUAL TABLE t10 USING rtree_i32(ii, x1, x2);
  INSERT INTO t10 VALUES(1, 'one', 'two');
  INSERT INTO t10 VALUES(2, '52xyz', '81...');
  INSERT INTO t10 VALUES(3, 42.3, 49.9);
}
do_execsql_test 14.5 {
do_execsql_test 14.105 {
  SELECT * FROM t10;
} {
  1 0 0
  2 52 81
  3 42 49
}

642
643
644
645
646
647
648
649






















650




































651
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








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

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

  CREATE VIRTUAL TABLE rt1 USING rtree(id, x1, x2, +aux);
  INSERT INTO rt1 VALUES(1, 1, 2, 'aux1');
  INSERT INTO rt1 VALUES(2, 2, 3, 'aux2');
  INSERT INTO rt1 VALUES(3, 3, 4, 'aux3');
  INSERT INTO rt1 VALUES(4, 4, 5, 'aux4');
  SELECT * FROM rt1 WHERE id IN (1, 2, 3, 4);
} {1 1.0 2.0 aux1 2 2.0 3.0 aux2 3 3.0 4.0 aux3 4 4.0 5.0 aux4}

reset_db
do_execsql_test 17.0 {
  CREATE VIRTUAL TABLE t1 USING rtree(id, x1 PRIMARY KEY, x2, y1, y2);
  CREATE VIRTUAL TABLE t2 USING rtree(id, x1, x2, y1, y2 UNIQUE);
}
do_execsql_test 17.1 {
  REINDEX t1;
  REINDEX t2;
} {}

do_execsql_test 17.2 {
  REINDEX;
} {}

reset_db
do_execsql_test 18.0 {
  CREATE VIRTUAL TABLE rt0 USING rtree(c0, c1, c2);
  INSERT INTO rt0(c0,c1,c2) VALUES(9,2,3);
  SELECT c0 FROM rt0 WHERE rt0.c1 > '-1'; 
  SELECT rt0.c1 > '-1' FROM rt0;
} {9 1}

expand_all_sql db

# 2020-02-28 ticket e63b4d1a65546532
reset_db
do_execsql_test 19.0 {
  CREATE VIRTUAL TABLE rt0 USING rtree(a,b,c);
  INSERT INTO rt0(a,b,c) VALUES(0,0.0,0.0);
  CREATE VIEW v0(x) AS SELECT DISTINCT rt0.b FROM rt0;
  SELECT v0.x FROM v0, rt0;
} {0.0}
do_execsql_test 19.1 {
  SELECT v0.x FROM v0, rt0 WHERE v0.x = rt0.b;
} {0.0}

# 2022-06-20 https://sqlite.org/forum/forumpost/57bdf2217d
#
reset_db
do_execsql_test 20.0 {
  CREATE VIRTUAL TABLE rt0 USING rtree(id, x0, x1);
  CREATE TABLE t0(a INT);
  CREATE TABLE t1(b INT);
  INSERT INTO rt0 VALUES(0, 0, 0);
}
do_catchsql_test 20.1 {
  SELECT * FROM t1 JOIN t0 ON x0>a RIGHT JOIN rt0 ON true WHERE +x0 = 0;
} {1 {ON clause references tables to its right}}
do_catchsql_test 20.2 {
  SELECT * FROM t1 JOIN t0 ON x0>a RIGHT JOIN rt0 ON true WHERE x0 = 0;
} {1 {ON clause references tables to its right}}
db null -
do_execsql_test 20.3 {
  SELECT * FROM t1 JOIN t0 ON true RIGHT JOIN rt0 ON x0>a WHERE +x0 = 0;
} {- - 0 0.0 0.0}
do_execsql_test 20.4 {
  SELECT * FROM t1 JOIN t0 ON true RIGHT JOIN rt0 ON x0>a WHERE x0 = 0;
} {- - 0 0.0 0.0}

finish_test

Changes to ext/rtree/rtree2.test.

29
30
31
32
33
34
35

36
37
38
39
40
41

42
43
44
45
46
47
48
29
30
31
32
33
34
35
36
37
38
39
40
41

42
43
44
45
46
47
48
49







+





-
+








if {[info exists G(isquick)] && $G(isquick)} {
  set ::NROW 100
  set ::NSELECT 10
}

foreach module {rtree_i32 rtree} {
  if {$module=="rtree_i32"} {set etype INT} {set etype REAL}
  for {set nDim 1} {$nDim <= 5} {incr nDim} {
  
    do_test rtree2-$module.$nDim.1 {
      set cols [list]
      foreach c [list c0 c1 c2 c3 c4 c5 c6 c7 c8 c9] {
        lappend cols "$c REAL"
        lappend cols "$c $etype"
      }
      set cols [join [lrange $cols 0 [expr {$nDim*2-1}]] ", "]
      execsql " 
        CREATE VIRTUAL TABLE t1 USING ${module}(ii, $cols);
        CREATE TABLE t2 (ii, $cols);
      "
    } {}

Changes to ext/rtree/rtree3.test.

18
19
20
21
22
23
24




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







+
+
+
+







} 
source $testdir/tester.tcl
source $testdir/malloc_common.tcl
ifcapable !rtree {
  finish_test
  return
}

set ::TMPDBERROR [list 1 \
  {unable to open a temporary database file for storing temporary tables}
]

# Test summary:
#
#   rtree3-1: Test OOM in simple CREATE TABLE, INSERT, DELETE and SELECT 
#             commands on an almost empty table.
#
#   rtree3-2: Test OOM in a DROP TABLE command.
192
193
194
195
196
197
198
199

200
201

202
203
204
205
206
207
208
196
197
198
199
200
201
202

203
204

205
206
207
208
209
210
211
212







-
+

-
+







  faultsim_delete_and_reopen
  execsql { CREATE VIRTUAL TABLE rt USING rtree(ii, x1, x2, y1, y2) }
  faultsim_save_and_close
} {}
do_faultsim_test rtree3-7 -faults oom-* -prep {
  faultsim_restore_and_reopen
} -body {
  execsql { ALTER TABLE rt RENAME TO rt2 }
  execsql { ALTER TABLE rt RENAME TO rt2 } 
} -test {
  faultsim_test_result {0 {}}
  faultsim_test_result {0 {}} $::TMPDBERROR
}

do_faultsim_test rtree3-8 -faults oom-* -prep {
  catch { db close }
} -body {
  sqlite3 db test.db
} 

Changes to ext/rtree/rtree6.test.

11
12
13
14
15
16
17

18
19
20
21
22
23
24
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25







+







# 
#

if {![info exists testdir]} {
  set testdir [file join [file dirname [info script]] .. .. test]
} 
source $testdir/tester.tcl
set testprefix rtree6

ifcapable {!rtree || rtree_int_only} {
  finish_test
  return
}

#   Operator    Byte Value
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
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







+
+
+

















-
-
+
+






-
-
+
+






-
-
+
+






-
-
+
+





-
-
+
+






-
-
+
+







    CREATE VIRTUAL TABLE t1 USING rtree(ii, x1, x2, y1, y2);
  }
} {}

do_test rtree6-1.2 {
  rtree_strategy {SELECT * FROM t1 WHERE x1>10}
} {E0}
do_test rtree6-1.2.1 {
  rtree_strategy {SELECT * FROM t1 WHERE x1>10 AND x2 LIKE '%x%'}
} {E0}

do_test rtree6-1.3 {
  rtree_strategy {SELECT * FROM t1 WHERE x1<10}
} {C0}

do_test rtree6-1.4 {
  rtree_strategy {SELECT * FROM t1,t2 WHERE k=ii AND x1<10}
} {C0}

do_test rtree6-1.5 {
  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 
159
160
161
162
163
164
165









166
167
168
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181







+
+
+
+
+
+
+
+
+



    x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND 
    x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND 
    x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND 
    x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND 
    x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND 
    x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>1.1
} {}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 4.0 {
  CREATE VIRTUAL TABLE t1 USING rtree(id,x0,x1,y0,y1);
}
do_execsql_test 4.1 {
  DELETE FROM t1 WHERE x0>1 AND x1<2 OR y0<92;
}

expand_all_sql db
finish_test

Changes to ext/rtree/rtree9.test.

32
33
34
35
36
37
38
39

40
41
42
43
44
45
46
32
33
34
35
36
37
38

39
40
41
42
43
44
45
46







-
+







do_execsql_test rtree9-1.3 {
  SELECT * FROM rt WHERE id MATCH cube(3, 3, 3, 2, 2, 2);
} {}
do_execsql_test rtree9-1.4 {
  DELETE FROM rt;
} {}


unset -nocomplain x
for {set i 0} {$i < 1000} {incr i} {
  set x [expr $i%10]
  set y [expr ($i/10)%10]
  set z [expr ($i/100)%10]
  execsql { INSERT INTO rt VALUES($i, $x, $x+1, $y, $y+1, $z, $z+1) }
}
do_rtree_integrity_test rtree9-2.0 rt

Changes to ext/rtree/rtreeA.test.

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







-
+














-
+




-
+





-
+











-
+



















-
+












-
+




-
+
















-
+







}

create_t1
populate_t1
do_test rtreeA-2.2.0 { truncate_node 1 200 } {}
do_corruption_tests rtreeA-2.2 {
  1   "SELECT * FROM t1"
  2   "SELECT * FROM t1 WHERE rowid=5"
  2   "SELECT * FROM t1 WHERE +rowid=5"
  3   "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)"
  4   "SELECT * FROM t1 WHERE x1<10 AND x2>12"
}

#-------------------------------------------------------------------------
# Set the "depth" of the tree stored on the root node incorrectly. Test
# that this does not cause any problems.
#
create_t1
populate_t1
do_test rtreeA-3.1.0.1 { set_tree_depth t1 } {1}
do_test rtreeA-3.1.0.2 { set_tree_depth t1 3 } {3}
do_corruption_tests rtreeA-3.1 {
  1   "SELECT * FROM t1"
  2   "SELECT * FROM t1 WHERE rowid=5"
  2   "SELECT * FROM t1 WHERE +rowid=5"
  3   "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)"
}

do_execsql_test rtreeA-3.1.0.3 {
  SELECT rtreecheck('main', 't1')!="ok"
  SELECT rtreecheck('main', 't1')!='ok'
} {1}

do_test rtreeA-3.2.0 { set_tree_depth t1 1000 } {1000}
do_corruption_tests rtreeA-3.2 {
  1   "SELECT * FROM t1"
  2   "SELECT * FROM t1 WHERE rowid=5"
  2   "SELECT * FROM t1 WHERE +rowid=5"
  3   "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)"
}

create_t1
populate_t1
do_test rtreeA-3.3.0 { 
  execsql { DELETE FROM t1 WHERE rowid = 0 }
  set_tree_depth t1 65535
} {65535}
do_corruption_tests rtreeA-3.3 {
  1   "SELECT * FROM t1"
  2   "SELECT * FROM t1 WHERE rowid=5"
  2   "SELECT * FROM t1 WHERE +rowid=5"
  3   "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)"
}

do_execsql_test rtreeA-3.3.3.4 {
  SELECT rtreecheck('main', 't1')
} {{Rtree depth out of range (65535)
Wrong number of entries in %_rowid table - expected 0, actual 499
Wrong number of entries in %_parent table - expected 0, actual 23}}

#-------------------------------------------------------------------------
# Set the "number of entries" field on some nodes incorrectly.
#
create_t1
populate_t1
do_test rtreeA-4.1.0 { 
  set_entry_count t1 1 4000
} {4000}
do_corruption_tests rtreeA-4.1 {
  1   "SELECT * FROM t1"
  2   "SELECT * FROM t1 WHERE rowid=5"
  2   "SELECT * FROM t1 WHERE +rowid=5"
  3   "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)"
  4   "SELECT * FROM t1 WHERE x1<10 AND x2>12"
}

#-------------------------------------------------------------------------
# Remove entries from the %_parent table and check that this does not
# cause a crash.
#
create_t1
populate_t1
do_execsql_test rtreeA-5.1.0 { DELETE FROM t1_parent } {}
do_corruption_tests rtreeA-5.1 {
  1   "DELETE FROM t1 WHERE rowid = 5"
  1   "DELETE FROM t1 WHERE +rowid = 5"
  2   "DELETE FROM t1"
}

do_execsql_test rtreeA-5.2 {
  SELECT rtreecheck('main', 't1')!="ok"
  SELECT rtreecheck('main', 't1')!='ok'
} {1}

#-------------------------------------------------------------------------
# Add some bad entries to the %_parent table.
#
create_t1
populate_t1
do_execsql_test rtreeA-6.1.0 { 
  UPDATE t1_parent set parentnode = parentnode+1
} {}
do_corruption_tests rtreeA-6.1 {
  1   "DELETE FROM t1 WHERE rowid = 5"
  2   "UPDATE t1 SET x1=x1+1, x2=x2+1"
}

do_execsql_test rtreeA-6.2 {
  SELECT rtreecheck('main', 't1')!="ok"
  SELECT rtreecheck('main', 't1')!='ok'
} {1}

#-------------------------------------------------------------------------
# Truncated blobs in the _node table.
#
create_t1
populate_t1

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
173
174
175
176
177
178
179
180

181
182
183
184
185
186
187
173
174
175
176
177
178
179

180
181
182
183
184
185
186
187







-
+







} {1 1 3 {}}

#--------------------------------------------------------------------
# Test that the sqlite_stat1 data is used correctly.
#
reset_db
do_execsql_test 5.1 {
  CREATE TABLE t1(x PRIMARY KEY, y);
  CREATE TABLE t1(x INT PRIMARY KEY, y);
  CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2, +d1);

  INSERT INTO t1(x) VALUES(1);
  INSERT INTO t1(x) SELECT x+1 FROM t1;   --   2
  INSERT INTO t1(x) SELECT x+2 FROM t1;   --   4
  INSERT INTO t1(x) SELECT x+4 FROM t1;   --   8
  INSERT INTO t1(x) SELECT x+8 FROM t1;   --  16
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 LEFT-JOIN
} {
  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/rtreeH.test.

39
40
41
42
43
44
45












46
47
48











49
50
51
52
53
54
55
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







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



+
+
+
+
+
+
+
+
+
+
+







do_execsql_test rtreeH-101 {
  SELECT * FROM t1_rowid ORDER BY rowid
} {1 1 {lower-left corner} {} 2 1 {upper-left corner} {} 3 1 {lower-right corner} {} 4 1 {upper-right corner} {} 5 1 center {} 6 1 {left edge} {} 7 1 {right edge} {} 8 1 {bottom edge} {} 9 1 {top edge} {} 10 1 {the whole thing} {} 11 1 {left half} {} 12 1 {right half} {} 13 1 {bottom half} {} 14 1 {top half} {}}

do_execsql_test rtreeH-102 {
  SELECT * FROM t1 WHERE rowid=5;
} {5 40.0 60.0 40.0 60.0 center {}}
do_execsql_test rtreeH-102b {
  SELECT * FROM t1 WHERE rowid=5.0;
} {5 40.0 60.0 40.0 60.0 center {}}
do_execsql_test rtreeH-102c {
  SELECT * FROM t1 WHERE rowid='5';
} {5 40.0 60.0 40.0 60.0 center {}}
do_execsql_test rtreeH-102d {
  SELECT * FROM t1 WHERE rowid='0005';
} {5 40.0 60.0 40.0 60.0 center {}}
do_execsql_test rtreeH-102e {
  SELECT * FROM t1 WHERE rowid='+5.0e+0';
} {5 40.0 60.0 40.0 60.0 center {}}
do_execsql_test rtreeH-103 {
  SELECT * FROM t1 WHERE label='center';
} {5 40.0 60.0 40.0 60.0 center {}}

do_execsql_test rtreeH-104 {
  SELECT * FROM t1 WHERE rowid='+5.0e+0x';
} {}
do_execsql_test rtreeH-105 {
  SELECT * FROM t1 WHERE rowid=x'35';
} {}
do_execsql_test rtreeH-106 {
  SELECT * FROM t1 WHERE rowid=null;
} {}


do_rtree_integrity_test rtreeH-110 t1

do_execsql_test rtreeH-120 {
  SELECT label FROM t1 WHERE x1<=50 ORDER BY id
} {{lower-left corner} {upper-left corner} {left edge} {left half}}
do_execsql_test rtreeH-121 {

Added ext/rtree/rtreeI.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019-12-05
#
# 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.
#
#***********************************************************************
# Additional test cases

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

# The following is a test of rowvalue handling on virtual tables that
# deal with inequalities and that set the OMIT flag on terms of the
# WHERE clause.  This is not specific to rtree.  We just use rtree because
# it is a convenient test platform since it has all the right
# characteristics.
#
do_execsql_test rtreeI-1.10 {
  CREATE TABLE t1(a);
  INSERT INTO t1 VALUES(2);
  CREATE VIRTUAL TABLE t2 USING rtree(id,x0,x1);
  INSERT INTO t2(id,x0,x1) VALUES(1,2,3);
} {}
do_execsql_test rtreeI-1.20 {
  SELECT 123 FROM t1, t2 WHERE (a,0)>(x0,0);
} {}
do_execsql_test rtreeI-1.21 {
  SELECT 123 FROM t1, t2 WHERE (a,0.1)>(x0,0);
} {123}
do_execsql_test rtreeI-1.22 {
  SELECT 123 FROM t1, t2 WHERE (a,0)>=(x0,0);
} {123}
do_execsql_test rtreeI-1.23 {
  SELECT 123 FROM t1, t2 WHERE (a,0)<=(x0,0);
} {123}
do_execsql_test rtreeI-1.24 {
  SELECT 123 FROM t1, t2 WHERE (a,0)<(x0,0);
} {}
do_execsql_test rtreeI-1.30 {
  SELECT 123 FROM t1, t2 WHERE (x0,0)<(a,0);
} {}
do_execsql_test rtreeI-1.31 {
  SELECT 123 FROM t1, t2 WHERE (x0,0)<(a,0.1);
} {123}
do_execsql_test rtreeI-1.40 {
  SELECT 123 FROM t1, t2 WHERE x1<5 AND id<99 AND (a,0)>(x0,0);
} {}
do_execsql_test rtreeI-1.41 {
  SELECT 123 FROM t1, t2 WHERE x1<5 AND id<99 AND (a,0.5)>(x0,0);
} {123}
do_execsql_test rtreeI-1.42 {
  SELECT 123 FROM t1, t2 WHERE x1<5 AND id<99 AND (a,0)>=(x0,0);
} {123}
do_execsql_test rtreeI-1.43 {
  SELECT 123 FROM t1, t2 WHERE x1<5 AND id<99 AND (a,0)<(x0,0);
} {}
do_execsql_test rtreeI-1.50 {
  SELECT 123 FROM t1, t2 WHERE 5>x1 AND 99>id AND (x0,0)<(a,0);
} {}
do_execsql_test rtreeI-1.51 {
  SELECT 123 FROM t1, t2 WHERE 5>x1 AND 99>id AND (x0,0)<(a,0.5);
} {123}



finish_test

Changes to ext/rtree/rtreecheck.test.

113
114
115
116
117
118
119
120

121
122
123
124
125
126

127
128
129
130
131
132
133
113
114
115
116
117
118
119

120
121
122
123
124
125

126
127
128
129
130
131
132
133







-
+





-
+







  SELECT rtreecheck('r2') 
} {ok}

sqlite3_db_config db DEFENSIVE 0
do_execsql_test 3.2 {
  BEGIN;
    UPDATE r2_node SET data = X'123456';
    SELECT rtreecheck('r2')!="ok";
    SELECT rtreecheck('r2')!='ok';
} {1}

do_execsql_test 3.3 {
  ROLLBACK;
  UPDATE r2_node SET data = X'00001234';
  SELECT rtreecheck('r2')!="ok";
  SELECT rtreecheck('r2')!='ok';
} {1}

do_execsql_test 4.0 {
  CREATE TABLE notanrtree(i);
  SELECT rtreecheck('notanrtree');
} {{Schema corrupt or not an rtree}}

153
154
155
156
157
158
159














160

153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175







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

+
  ROLLBACK;
  BEGIN;
    UPDATE r3_node SET data = set_int32(data, 3, 0);
    UPDATE r3_node SET data = set_int32(data, 4, 0);
    SELECT rtreecheck('r3')=='ok'
} 0

#-------------------------------------------------------------------------
# dbsqlfuzz 4a1399d39bf9feccbf6b290da51d3b30103a4bf6
#
reset_db
do_execsql_test 6.0 {
  PRAGMA encoding = 'utf16';
  CREATE VIRTUAL TABLE t1 USING rtree(id, x, y);
}
db close
sqlite3 db test.db
do_catchsql_test 6.1 {
  SELECT ( 'elvis' IN(SELECT rtreecheck('t1')) ) FROM (SELECT 1) GROUP BY 1;
} {1 {database table is locked}}

finish_test

Added ext/rtree/rtreecirc.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2018 Dec 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.  The
# focus of this script is testing the FTS5 module.
#

if {![info exists testdir]} {
  set testdir [file join [file dirname [info script]] .. .. test]
}
source [file join [file dirname [info script]] rtree_util.tcl]
source $testdir/tester.tcl
set testprefix rtreecirc

ifcapable !rtree {
  finish_test
  return
}

do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2, y1, y2);
  SELECT name FROM sqlite_master ORDER BY 1;
} {
  rt rt_node rt_parent rt_rowid
}
db_save_and_close

foreach {tn schema sql} {
  1 {
    CREATE TRIGGER tr1 AFTER INSERT ON rt_node BEGIN
      SELECT * FROM rt;
    END;
  } {
    INSERT INTO rt VALUES(1, 2, 3, 4, 5);
  }
  2 {
    CREATE TRIGGER tr1 AFTER INSERT ON rt_parent BEGIN
      SELECT * FROM rt;
    END;
  } {
    INSERT INTO rt VALUES(1, 2, 3, 4, 5);
  }
  3 {
    CREATE TRIGGER tr1 AFTER INSERT ON rt_rowid BEGIN
      SELECT * FROM rt;
    END;
  } {
    INSERT INTO rt VALUES(1, 2, 3, 4, 5);
  }
} {
  db_restore_and_reopen
  do_execsql_test  1.1.$tn.1 $schema
  do_catchsql_test 1.1.$tn.2 $sql {1 {no such table: main.rt}}
  db close
}


finish_test

Added ext/rtree/rtreedoc.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
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
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
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
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2021 September 13
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# The focus of this file is testing the r-tree extension.
#

if {![info exists testdir]} {
  set testdir [file join [file dirname [info script]] .. .. test]
}
source [file join [file dirname [info script]] rtree_util.tcl]
source $testdir/tester.tcl
set testprefix rtreedoc

ifcapable !rtree {
  finish_test
  return
}

# This command returns the number of columns in table $tbl within the
# database opened by database handle $db
proc column_count {db tbl} {
  set nCol 0
  $db eval "PRAGMA table_info = $tbl" { incr nCol }
  return $nCol
}

proc column_name_list {db tbl} {
  set lCol [list]
  $db eval "PRAGMA table_info = $tbl" { 
    lappend lCol $name
  }
  return $lCol
}
unset -nocomplain res

#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
# Section 3 of documentation.
#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
set testprefix rtreedoc-1

# EVIDENCE-OF: R-15060-13876 A 1-dimensional R*Tree thus has 3 columns.
do_execsql_test 1.1.1 { CREATE VIRTUAL TABLE rt1 USING rtree(id, x1,x2) }
do_test         1.1.2 { column_count db rt1 } 3

# EVIDENCE-OF: R-19353-19546 A 2-dimensional R*Tree has 5 columns.
do_execsql_test 1.2.1 { CREATE VIRTUAL TABLE rt2 USING rtree(id,x1,x2, y1,y2) }
do_test         1.2.2 { column_count db rt2 } 5

# EVIDENCE-OF: R-13615-19528 A 3-dimensional R*Tree has 7 columns.
do_execsql_test 1.3.1 { 
  CREATE VIRTUAL TABLE rt3 USING rtree(id, x1,x2, y1,y2, z1,z2) 
}
do_test         1.3.2 { column_count db rt3 } 7

# EVIDENCE-OF: R-53479-41922 A 4-dimensional R*Tree has 9 columns.
do_execsql_test 1.4.1 { 
  CREATE VIRTUAL TABLE rt4 USING rtree(id, x1,x2, y1,y2, z1,z2, v1,v2) 
}
do_test         1.4.2 { column_count db rt4 } 9

# EVIDENCE-OF: R-13981-28768 And a 5-dimensional R*Tree has 11 columns.
do_execsql_test 1.5.1 { 
  CREATE VIRTUAL TABLE rt5 USING rtree(id, x1,x2, y1,y2, z1,z2, v1,v2, w1,w2)
}
do_test         1.5.2 { column_count db rt5 } 11


# Attempt to create r-tree tables with 6 and 7 dimensions.
#
# EVIDENCE-OF: R-61533-25862 The SQLite R*Tree implementation does not
# support R*Trees wider than 5 dimensions.
do_catchsql_test 2.1.1 { 
  CREATE VIRTUAL TABLE rt6 USING rtree(
    id, x1,x2, y1,y2, z1,z2, v1,v2, w1,w2, a1,a2
  )
} {1 {Too many columns for an rtree table}}
do_catchsql_test 2.1.2 { 
  CREATE VIRTUAL TABLE rt6 USING rtree(
    id, x1,x2, y1,y2, z1,z2, v1,v2, w1,w2, a1,a2, b1, b2
  )
} {1 {Too many columns for an rtree table}}

# Attempt to create r-tree tables with no columns, a single column, or
# an even number of columns. This and the tests above establish that:
#
# EVIDENCE-OF: R-16717-50504 Each R*Tree index is a virtual table with
# an odd number of columns between 3 and 11.
foreach {tn cols err} {
  1 ""                        "Too few columns for an rtree table"
  2 "x"                       "Too few columns for an rtree table"
  3 "x,y"                     "Too few columns for an rtree table"
  4 "a,b,c,d"                 "Wrong number of columns for an rtree table"
  5 "a,b,c,d,e,f"             "Wrong number of columns for an rtree table"
  6 "a,b,c,d,e,f,g,h"         "Wrong number of columns for an rtree table"
  7 "a,b,c,d,e,f,g,h,i,j"     "Wrong number of columns for an rtree table"
  8 "a,b,c,d,e,f,g,h,i,j,k,l" "Too many columns for an rtree table"
} {
  do_catchsql_test 3.$tn "
    CREATE VIRTUAL TABLE xyz USING rtree($cols)
  " [list 1 $err]
}

# EVIDENCE-OF: R-17874-21123 The first column of an SQLite R*Tree is
# similar to an integer primary key column of a normal SQLite table.
#
# EVIDENCE-OF: R-46619-65417 The first column is always a 64-bit signed
# integer primary key.
#
# EVIDENCE-OF: R-46866-24036 It may only store a 64-bit signed integer
# value.
#
# EVIDENCE-OF: R-00250-64843 If an attempt is made to insert any other
# non-integer value into this column, the r-tree module silently
# converts it to an integer before writing it into the database.
#
do_execsql_test 4.0 { CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2) }
foreach {tn val res} {
  1 10    10
  2 10.6  10
  3 10.99 10
  4 '123' 123
  5 X'313233'  123
  6 -10   -10
  7  9223372036854775807 9223372036854775807 
  8 -9223372036854775808 -9223372036854775808 
  9  '9223372036854775807' 9223372036854775807
  10  '-9223372036854775808' -9223372036854775808
  11  'hello+world' 0
} {
  do_execsql_test 4.$tn.1 "
    DELETE FROM rt;
    INSERT INTO rt VALUES($val, 10, 20);
  "
  do_execsql_test 4.$tn.2 {
    SELECT typeof(id), id FROM rt
  } [list integer $res]
}

# EVIDENCE-OF: R-15544-29079 Inserting a NULL value into this column
# causes SQLite to automatically generate a new unique primary key
# value.
do_execsql_test 5.1 {
  DELETE FROM rt;
  INSERT INTO rt VALUES(100, 1, 2);
  INSERT INTO rt VALUES(NULL, 1, 2);
}
do_execsql_test 5.2 { SELECT id FROM rt } {100 101}
do_execsql_test 5.3 { 
  INSERT INTO rt VALUES(9223372036854775807, 1, 2);
  INSERT INTO rt VALUES(NULL, 1, 2);
}
do_execsql_test 5.4 {
  SELECT count(*) FROM rt;
} 4
do_execsql_test 5.5 {
  SELECT id IN(100, 101, 9223372036854775807) FROM rt ORDER BY 1;
} {0 1 1 1}


# EVIDENCE-OF: R-64317-38978 The other columns are pairs, one pair per
# dimension, containing the minimum and maximum values for that
# dimension, respectively.
#
# Show this by observing that attempts to insert rows with max>min fail.
#
do_execsql_test 6.1 {
  CREATE VIRTUAL TABLE rtF USING rtree(id, x1,x2, y1,y2);
  CREATE VIRTUAL TABLE rtI USING rtree_i32(id, x1,x2, y1,y2, z1,z2);
}
foreach {tn x1 x2 y1 y2 ok} {
  1   10.3 20.1   30.9 40.2   1
  2   10.3 20.1   40.2 30.9   0
  3   10.3 30.9   20.1 40.2   1
  4   20.1 10.3   30.9 40.2   0
} {
  do_test 6.2.$tn {
    catch { db eval { INSERT INTO rtF VALUES(NULL, $x1, $x2, $y1, $y2) } }
  } [expr $ok==0]
}
foreach {tn x1 x2 y1 y2 z1 z2 ok} {
  1   10 20   30 40  50 60  1
  2   10 20   30 40  60 50  0
  3   10 20   30 50  40 60  1
  4   10 20   40 30  50 60  0
  5   10 30   20 40  50 60  1
  6   20 10   30 40  50 60  0
} {
  do_test 6.3.$tn {
    catch { db eval { INSERT INTO rtI VALUES(NULL,$x1,$x2,$y1,$y2,$z1,$z2) } }
  } [expr $ok==0]
}

# EVIDENCE-OF: R-08054-15429 The min/max-value pair columns are stored
# as 32-bit floating point values for "rtree" virtual tables or as
# 32-bit signed integers in "rtree_i32" virtual tables.
#
# Show this by showing that large values are rounded in ways consistent
# with those two 32-bit types.
do_execsql_test 7.1 {
  DELETE FROM rtI;
  INSERT INTO rtI VALUES(
    0, -2000000000, 2000000000, -5000000000, 5000000000,
    -1000000000000, 10000000000000
  );
  SELECT * FROM rtI;
} {
  0 -2000000000 2000000000 -705032704 705032704 727379968 1316134912
}
do_execsql_test 7.2 {
  DELETE FROM rtF;
  INSERT INTO rtF VALUES(
    0, -2000000000, 2000000000, 
    -1000000000000, 10000000000000
  );
  SELECT * FROM rtF;
} {
  0 -2000000000.0 2000000000.0 -1000000126976.0 10000000876544.0
}

# EVIDENCE-OF: R-47371-54529 Unlike regular SQLite tables which can
# store data in a variety of datatypes and formats, the R*Tree rigidly
# enforce these storage types.
#
# EVIDENCE-OF: R-39153-14977 If any other type of value is inserted into
# such a column, the r-tree module silently converts it to the required
# type before writing the new record to the database.
do_execsql_test 8.1 {
  DELETE FROM rtI;
  INSERT INTO rtI VALUES(
    1, 'hello world', X'616263', NULL, 44.5, 1000, 9999.9999
  );
  SELECT * FROM rtI;
} {
  1   0 0    0 44    1000 9999
}

do_execsql_test 8.2 {
  SELECT 
    typeof(x1), typeof(x2), typeof(y1), typeof(y2), typeof(z1), typeof(z2)
  FROM rtI
} {integer integer integer integer integer integer}

do_execsql_test 8.3 {
  DELETE FROM rtF;
  INSERT INTO rtF VALUES(
    1, 'hello world', X'616263', NULL, 44
  );
  SELECT * FROM rtF;
} {
  1   0.0 0.0    0.0 44.0
}
do_execsql_test 8.4 {
  SELECT 
    typeof(x1), typeof(x2), typeof(y1), typeof(y2)
  FROM rtF
} {real real real real}




#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
# Section 3.1 of documentation.
#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
set testprefix rtreedoc-2
reset_db

foreach {tn name clist} {
  1 t1 "id x1 x2"
  2 t2 "id x1 x2   y1 y2   z1 z2"
} {
# EVIDENCE-OF: R-15142-18077 A new R*Tree index is created as follows:
# CREATE VIRTUAL TABLE <name> USING rtree(<column-names>);
  do_execsql_test 1.$tn.1 "
    CREATE VIRTUAL TABLE $name USING rtree([join $clist ,])
  "

# EVIDENCE-OF: R-51698-09302 The <name> is the name your
# application chooses for the R*Tree index and <column-names> is a
# comma separated list of between 3 and 11 columns.
  do_test 1.$tn.2 { column_name_list db $name } [list {*}$clist]

# EVIDENCE-OF: R-50130-53472 The virtual <name> table creates
# three shadow tables to actually store its content.
  do_execsql_test 1.$tn.3 {
    SELECT count(*) FROM sqlite_schema
  } [expr 1+3]

# EVIDENCE-OF: R-45256-35998 The names of these shadow tables are:
# <name>_node <name>_rowid <name>_parent
  do_execsql_test 1.$tn.4 {
    SELECT name FROM sqlite_schema WHERE rootpage>0 ORDER BY 1
  } [list ${name}_node ${name}_parent ${name}_rowid]

  do_execsql_test 1.$tn.5 "DROP TABLE $name"
}

# EVIDENCE-OF: R-11241-54478 As an example, consider creating a
# two-dimensional R*Tree index for use in spatial queries: CREATE
# VIRTUAL TABLE demo_index USING rtree( id, -- Integer primary key minX,
# maxX, -- Minimum and maximum X coordinate minY, maxY -- Minimum and
# maximum Y coordinate );
do_execsql_test 2.0 {
  CREATE VIRTUAL TABLE demo_index USING rtree(
      id,              -- Integer primary key
      minX, maxX,      -- Minimum and maximum X coordinate
      minY, maxY       -- Minimum and maximum Y coordinate
  );
  INSERT INTO demo_index VALUES(1,2,3,4,5);
  INSERT INTO demo_index VALUES(6,7,8,9,10);
}

# EVIDENCE-OF: R-02287-33529 The shadow tables are ordinary SQLite data
# tables.
#
# Ordinary tables. With ordinary sqlite_schema entries.
do_execsql_test 2.1 {
  SELECT type, name, sql FROM sqlite_schema WHERE sql NOT LIKE '%virtual%'
} {
  table demo_index_rowid 
    {CREATE TABLE "demo_index_rowid"(rowid INTEGER PRIMARY KEY,nodeno)} 
  table demo_index_node
    {CREATE TABLE "demo_index_node"(nodeno INTEGER PRIMARY KEY,data)} 
  table demo_index_parent
    {CREATE TABLE "demo_index_parent"(nodeno INTEGER PRIMARY KEY,parentnode)}
}

# EVIDENCE-OF: R-10863-13089 You can query them directly if you like,
# though this unlikely to reveal anything particularly useful.
#
# Querying:
do_execsql_test 2.2 {
  SELECT count(*) FROM demo_index_node;
  SELECT count(*) FROM demo_index_rowid;
  SELECT count(*) FROM demo_index_parent;
} {1 2 0}

# EVIDENCE-OF: R-05650-46070 And you can UPDATE, DELETE, INSERT or even
# DROP the shadow tables, though doing so will corrupt your R*Tree
# index.
do_execsql_test 2.3 {
  DELETE FROM demo_index_rowid;
  INSERT INTO demo_index_parent VALUES(2, 3);
  UPDATE demo_index_node SET data = 'hello world'
}
do_catchsql_test 2.4 {
  SELECT * FROM demo_index WHERE minX>10 AND maxX<30
} {1 {database disk image is malformed}}
do_execsql_test 2.5 {
  DROP TABLE demo_index_rowid
}

#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
# Section 3.1.1 of documentation.
#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
set testprefix rtreedoc-3
reset_db

# EVIDENCE-OF: R-44253-50720 In the argments to "rtree" in the CREATE
# VIRTUAL TABLE statement, the names of the columns are taken from the
# first token of each argument. All subsequent tokens within each
# argument are silently ignored.
#
foreach {tn cols lCol} {
  1 {(id TEXT, x1 TEXT, x2 TEXT, y1 TEXT, y2 TEXT)} {id x1 x2 y1 y2}
  2 {(id TEXT, x1 UNIQUE, x2 TEXT, y1 NOT NULL, y2 TEXT)} {id x1 x2 y1 y2}
  3 {(id, x1 DEFAULT 4, x2 TEXT, y1 NOT NULL, y2 TEXT)} {id x1 x2 y1 y2}
} {
  do_execsql_test 1.$tn.1 " CREATE VIRTUAL TABLE abc USING rtree $cols "
  do_test 1.$tn.2 { column_name_list db abc } $lCol

# EVIDENCE-OF: R-52032-06717 This means, for example, that if you try to
# give a column a type affinity or add a constraint such as UNIQUE or
# NOT NULL or DEFAULT to a column, those extra tokens are accepted as
# valid, but they do not change the behavior of the rtree.

  # Show there are no UNIQUE constraints
  do_execsql_test 1.$tn.3 {
    INSERT INTO abc VALUES(1, 10.0, 20.0, 10.0, 20.0);
    INSERT INTO abc VALUES(2, 10.0, 20.0, 10.0, 20.0);
  }

  # Show the default values have not been modified
  do_execsql_test 1.$tn.4 {
    INSERT INTO abc DEFAULT VALUES;
    SELECT * FROM abc WHERE rowid NOT IN (1,2)
  } {3 0.0 0.0 0.0 0.0}

  # Show that there are no NOT NULL constraints
  do_execsql_test 1.$tn.5 {
    INSERT INTO abc VALUES(NULL, NULL, NULL, NULL, NULL);
    SELECT * FROM abc WHERE rowid NOT IN (1,2,3)
  } {4 0.0 0.0 0.0 0.0}

# EVIDENCE-OF: R-06893-30579 In an RTREE virtual table, the first column
# always has a type affinity of INTEGER and all other data columns have
# a type affinity of REAL.
  do_execsql_test 1.$tn.5 {
    INSERT INTO abc VALUES('5', '5', '5', '5', '5');
    SELECT * FROM abc WHERE rowid NOT IN (1,2,3,4)
  } {5 5.0 5.0 5.0 5.0}
  do_execsql_test 1.$tn.6 {
    SELECT type FROM pragma_table_info('abc') ORDER BY cid
  } {INT REAL REAL REAL REAL}

  do_execsql_test 1.$tn.7 " CREATE VIRTUAL TABLE abc2 USING rtree_i32 $cols "

# EVIDENCE-OF: R-06224-52418 In an RTREE_I32 virtual table, all columns
# have type affinity of INTEGER.
  do_execsql_test 1.$tn.8 {
    INSERT INTO abc2 VALUES('6.0', '6.0', '6.0', '6.0', '6.0');
    SELECT * FROM abc2
  } {6 6 6 6 6}
  do_execsql_test 1.$tn.9 {
    SELECT type FROM pragma_table_info('abc2') ORDER BY cid
  } {INT INT INT INT INT}


  do_execsql_test 1.$tn.10 {
    DROP TABLE abc;
    DROP TABLE abc2;
  }
}

#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
# Section 3.2 of documentation.
#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
set testprefix rtreedoc-4
reset_db

# EVIDENCE-OF: R-36195-31555 The usual INSERT, UPDATE, and DELETE
# commands work on an R*Tree index just like on regular tables.
#
# Create a regular table and an rtree table. Perform INSERT, UPDATE and
# DELETE operations, then observe that the contents of the two tables
# are identical.
do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2);
  CREATE TABLE t1(id INTEGER PRIMARY KEY, x1 REAL, x2 REAL);
}
foreach {tn sql} {
  1 "INSERT INTO %TBL% VALUES(5, 11,12)"
  2 "INSERT INTO %TBL% VALUES(11, -11,14.5)"
  3 "UPDATE %TBL% SET x1=-99 WHERE id=11"
  4 "DELETE FROM %TBL% WHERE x2=14.5"
  5 "DELETE FROM %TBL%"
} {
  set sql1 [string map {%TBL% rt} $sql]
  set sql2 [string map {%TBL% t1} $sql]
  do_execsql_test 1.$tn.0 $sql1
  do_execsql_test 1.$tn.1 $sql2

  set data1 [execsql {SELECT * FROM rt ORDER BY 1}]
  set data2 [execsql {SELECT * FROM t1 ORDER BY 1}]

  set res [expr {$data1==$data2}]
  do_test 1.$tn.2 {set res} 1 
}

# EVIDENCE-OF: R-56987-45305
do_execsql_test 2.0 {
  CREATE VIRTUAL TABLE demo_index USING rtree(
      id,              -- Integer primary key
      minX, maxX,      -- Minimum and maximum X coordinate
      minY, maxY       -- Minimum and maximum Y coordinate
  );

  INSERT INTO demo_index VALUES
    (28215, -80.781227, -80.604706, 35.208813, 35.297367),
    (28216, -80.957283, -80.840599, 35.235920, 35.367825),
    (28217, -80.960869, -80.869431, 35.133682, 35.208233),
    (28226, -80.878983, -80.778275, 35.060287, 35.154446),
    (28227, -80.745544, -80.555382, 35.130215, 35.236916),
    (28244, -80.844208, -80.841988, 35.223728, 35.225471),
    (28262, -80.809074, -80.682938, 35.276207, 35.377747),
    (28269, -80.851471, -80.735718, 35.272560, 35.407925),
    (28270, -80.794983, -80.728966, 35.059872, 35.161823),
    (28273, -80.994766, -80.875259, 35.074734, 35.172836),
    (28277, -80.876793, -80.767586, 35.001709, 35.101063),
    (28278, -81.058029, -80.956375, 35.044701, 35.223812),
    (28280, -80.844208, -80.841972, 35.225468, 35.227203),
    (28282, -80.846382, -80.844193, 35.223972, 35.225655);
}

#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
# Section 3.3 of documentation.
#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
set testprefix rtreedoc-5

do_execsql_test 1.0 {
  INSERT INTO demo_index 
    SELECT NULL, minX, maxX, minY+0.2, maxY+0.2 FROM demo_index;
  INSERT INTO demo_index 
    SELECT NULL, minX+0.2, maxX+0.2, minY, maxY FROM demo_index;
  INSERT INTO demo_index 
    SELECT NULL, minX, maxX, minY+0.4, maxY+0.4 FROM demo_index;
  INSERT INTO demo_index 
    SELECT NULL, minX+0.4, maxX+0.4, minY, maxY FROM demo_index;
  INSERT INTO demo_index 
    SELECT NULL, minX, maxX, minY+0.8, maxY+0.8 FROM demo_index;
  INSERT INTO demo_index 
    SELECT NULL, minX+0.8, maxX+0.8, minY, maxY FROM demo_index;

  SELECT count(*) FROM demo_index;
} {896}

proc do_vmstep_test {tn sql expr} {
  execsql $sql
  set step [db status vmstep]
  do_test $tn.$step "expr {[subst $expr]}" 1
}

# EVIDENCE-OF: R-45880-07724 Any valid query will work against an R*Tree
# index.
do_execsql_test 1.1.0 {
  CREATE TABLE demo_tbl AS SELECT * FROM demo_index;
}
foreach {tn sql} {
  1  {SELECT * FROM %TBL% ORDER BY 1}
  2  {SELECT max(minX) FROM %TBL% ORDER BY 1}
  3  {SELECT max(minX) FROM %TBL% GROUP BY round(minY) ORDER BY 1}
} {
  set sql1 [string map {%TBL% demo_index} $sql]
  set sql2 [string map {%TBL% demo_tbl} $sql]

  do_execsql_test 1.1.$tn $sql1 [execsql $sql2]
}

# EVIDENCE-OF: R-60814-18273 The R*Tree implementation just makes some
# kinds of queries especially efficient.
#
# The second query is more efficient than the first.
do_vmstep_test 1.2.1 {SELECT * FROM demo_index WHERE +rowid=28269} {$step>2000}
do_vmstep_test 1.2.2 {SELECT * FROM demo_index WHERE rowid=28269} {$step<100}

# EVIDENCE-OF: R-37800-50174 Queries against the primary key are
# efficient: SELECT * FROM demo_index WHERE id=28269;
do_vmstep_test 2.2 { SELECT * FROM demo_index WHERE id=28269 } {$step < 100}

# EVIDENCE-OF: R-35847-18866 The big reason for using an R*Tree is so
# that you can efficiently do range queries against the coordinate
# ranges.
#
# EVIDENCE-OF: R-49927-54202
do_vmstep_test 2.3 { 
  SELECT id FROM demo_index
    WHERE minX<=-80.77470 AND maxX>=-80.77470
    AND minY<=35.37785  AND maxY>=35.37785;
} {$step < 100}

# EVIDENCE-OF: R-12823-37176 The query above will quickly locate all
# zipcodes that contain the SQLite main office in their bounding box,
# even if the R*Tree contains many entries.
#
do_execsql_test 2.4 { 
  SELECT id FROM demo_index
    WHERE minX<=-80.77470 AND maxX>=-80.77470
    AND minY<=35.37785  AND maxY>=35.37785;
} {
  28322 28269 
}

# EVIDENCE-OF: R-07351-00257 For example, to find all zipcode bounding
# boxes that overlap with the 28269 zipcode: SELECT A.id FROM demo_index
# AS A, demo_index AS B WHERE A.maxX>=B.minX AND A.minX<=B.maxX
# AND A.maxY>=B.minY AND A.minY<=B.maxY AND B.id=28269;
#
# Also check that it is efficient
#
# EVIDENCE-OF: R-39094-01937 This second query will find both 28269
# entry (since every bounding box overlaps with itself) and also other
# zipcode that is close enough to 28269 that their bounding boxes
# overlap.
#
# 28269 is there in the result.
#
do_vmstep_test 2.5.1 {
  SELECT A.id FROM demo_index AS A, demo_index AS B
    WHERE A.maxX>=B.minX AND A.minX<=B.maxX
    AND A.maxY>=B.minY AND A.minY<=B.maxY
    AND B.id=28269
} {$step < 100}
do_execsql_test 2.5.2 {
  SELECT A.id FROM demo_index AS A, demo_index AS B
    WHERE A.maxX>=B.minX AND A.minX<=B.maxX
    AND A.maxY>=B.minY AND A.minY<=B.maxY
    AND B.id=28269;
} {
  28293 28216 28322 28286 28269 
  28215 28336 28262 28291 28320 
  28313 28298 28287
}

# EVIDENCE-OF: R-02723-34107 Note that it is not necessary for all
# coordinates in an R*Tree index to be constrained in order for the
# index search to be efficient.
#
# EVIDENCE-OF: R-22490-27246 One might, for example, want to query all
# objects that overlap with the 35th parallel: SELECT id FROM demo_index
# WHERE maxY>=35.0 AND minY<=35.0;
do_vmstep_test 2.6.1 {
  SELECT id FROM demo_index
   WHERE maxY>=35.0  AND minY<=35.0;
} {$step < 100}
do_execsql_test 2.6.2 {
  SELECT id FROM demo_index
   WHERE maxY>=35.0  AND minY<=35.0;
} {}


#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
# Section 3.4 of documentation.
#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
set testprefix rtreedoc-6
reset_db

# EVIDENCE-OF: R-08327-00674 By default, coordinates are stored in an
# R*Tree using 32-bit floating point values.
#
# EVIDENCE-OF: R-22000-53613 The default virtual table ("rtree") stores
# coordinates as single-precision (4-byte) floating point numbers.
#
# Show this by showing that rounding is consistent with 32-bit float
# rounding.
do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE rt USING rtree(id, a,b);
}
do_execsql_test 1.1 {
  INSERT INTO rt VALUES(14, -1000000000000, 1000000000000);
  SELECT * FROM rt;
} {14 -1000000126976.0 1000000126976.0}

# EVIDENCE-OF: R-39127-51288 When a coordinate cannot be exactly
# represented by a 32-bit floating point number, the lower-bound
# coordinates are rounded down and the upper-bound coordinates are
# rounded up.
foreach {tn val} {
  1 100000000000
  2 200000000000
  3 300000000000
  4 400000000000

  5 -100000000000
  6 -200000000000
  7 -300000000000
  8 -400000000000
} {
  set val [expr $val]
  do_execsql_test 2.$tn.0 {DELETE FROM rt}
  do_execsql_test 2.$tn.1 {INSERT INTO rt VALUES(23, $val, $val)}
  do_execsql_test 2.$tn.2 {
    SELECT $val>=a, $val<=b, a!=b FROM rt
  } {1 1 1}
}

do_execsql_test 3.0 {
  DROP TABLE rt;
  CREATE VIRTUAL TABLE rt USING rtree(id, x1,x2, y1,y2);
}

# EVIDENCE-OF: R-45870-62834 Thus, bounding boxes might be slightly
# larger than specified, but will never be any smaller.
foreach {tn x1 x2 y1 y2} {
  1 100000000000 200000000000 300000000000 400000000000
} {
  set val [expr $val]
  do_execsql_test 3.$tn.0 {DELETE FROM rt}
  do_execsql_test 3.$tn.1 {INSERT INTO rt VALUES(23, $x1, $x2, $y1, $y2)}
  do_execsql_test 3.$tn.2 {
    SELECT (x2-x1)*(y2-y1) >= ($x2-$x1)*($y2-$y1) FROM rt
  } {1}
}

#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
# Section 3.5 of documentation.
#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
set testprefix rtreedoc-7
reset_db

# EVIDENCE-OF: R-55979-39402 It is the nature of the Guttman R-Tree
# algorithm that any write might radically restructure the tree, and in
# the process change the scan order of the nodes.
#
# In the test below, the INSERT marked "THIS INSERT!!" does not affect
# the results of queries with an ORDER BY, but does affect the results
# of one without an ORDER BY. Therefore the INSERT changed the scan 
# order.
do_execsql_test 1.0 { 
  CREATE VIRTUAL TABLE rt USING rtree(id, minX, maxX);
  WITH s(i) AS (
    SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<51
  )
  INSERT INTO rt SELECT NULL, i%10, (i%10)+5 FROM s
}
do_execsql_test 1.1 { SELECT count(*) FROM rt_node } 1
do_test 1.2 {
  set res1 [db eval {SELECT * FROM rt WHERE maxX < 30}]
  set res1o [db eval {SELECT * FROM rt WHERE maxX < 30 ORDER BY +id}]

  db eval { INSERT INTO rt VALUES(NULL, 50, 50) }   ;# THIS INSERT!!

  set res2 [db eval {SELECT * FROM rt WHERE maxX < 30}]
  set res2o [db eval {SELECT * FROM rt WHERE maxX < 30 ORDER BY +id}]
  list [expr {$res1==$res2}] [expr {$res1o==$res2o}]
} {0 1}

do_execsql_test 1.3 { SELECT count(*) FROM rt_node } 3

# EVIDENCE-OF: R-00683-48865 For this reason, it is not generally
# possible to modify the R-Tree in the middle of a query of the R-Tree.
# Attempts to do so will fail with a SQLITE_LOCKED "database table is
# locked" error.
#
# SQLITE_LOCKED==6
#
do_test 1.4 {
  set nCnt 3
  db eval { SELECT * FROM rt WHERE minX>0 AND maxX<12 } {
    incr nCnt -1
    if {$nCnt==0} {
      set rc [catch {db eval {
        INSERT INTO rt VALUES(NULL, 51, 51);
      }} msg]
      set errorcode [db errorcode]
      break
    }
  }

  list $errorcode $rc $msg
} {6 1 {database table is locked}}

# EVIDENCE-OF: R-19740-29710 So, for example, suppose an application
# runs one query against an R-Tree like this: SELECT id FROM demo_index
# WHERE maxY>=35.0 AND minY<=35.0; Then for each "id" value
# returned, suppose the application creates an UPDATE statement like the
# following and binds the "id" value returned against the "?1"
# parameter: UPDATE demo_index SET maxY=maxY+0.5 WHERE id=?1;
#
# EVIDENCE-OF: R-52919-32711 Then the UPDATE might fail with an
# SQLITE_LOCKED error.
do_execsql_test 2.0 {
  CREATE VIRTUAL TABLE demo_index USING rtree(
      id,              -- Integer primary key
      minX, maxX,      -- Minimum and maximum X coordinate
      minY, maxY       -- Minimum and maximum Y coordinate
  );
  INSERT INTO demo_index VALUES
    (28215, -80.781227, -80.604706, 35.208813, 35.297367),
    (28216, -80.957283, -80.840599, 35.235920, 35.367825),
    (28217, -80.960869, -80.869431, 35.133682, 35.208233),
    (28226, -80.878983, -80.778275, 35.060287, 35.154446);
}
do_test 2.1 {
  db eval { SELECT id FROM demo_index WHERE maxY>=35.0  AND minY<=35.0 } {
    set rc [catch { 
      db eval { UPDATE demo_index SET maxY=maxY+0.5 WHERE id=$id } 
    } msg]
    set errorcode [db errorcode]
    break
  }
  list $errorcode $rc $msg
} {6 1 {database table is locked}}

# EVIDENCE-OF: R-32604-49843 Ordinary tables in SQLite are able to read
# and write at the same time.
#
do_execsql_test 3.0 {
  CREATE TABLE x1(a INTEGER PRIMARY KEY, b, c);
  INSERT INTO x1 VALUES(1, 1, 1);
  INSERT INTO x1 VALUES(2, 2, 2);
  INSERT INTO x1 VALUES(3, 3, 3);
  INSERT INTO x1 VALUES(4, 4, 4);
}
do_test 3.1 {
  unset -nocomplain res
  set res [list]
  db eval { SELECT * FROM x1 } {
    lappend res $a $b $c
    switch -- $a {
      1 {
        db eval { INSERT INTO x1 VALUES(5, 5, 5) }
      }
      2 {
        db eval { UPDATE x1 SET c=20 WHERE a=2 }
      }
      3 {
        db eval { DELETE FROM x1 WHERE c IN (3,4) }
      }
    }
  }
  set res
} {1 1 1 2 2 2 3 3 3 5 5 5}
do_execsql_test 3.2 {
  SELECT * FROM x1
} {1 1 1  2 2 20  5 5 5}

# EVIDENCE-OF: R-06177-00576 And R-Tree can appear to read and write at
# the same time in some circumstances, if it can figure out how to
# reliably run the query to completion before starting the update.
#
# In 8.2, it can, it 8.1, it cannot.
do_test 8.1 {
  db eval { SELECT * FROM rt } {
    set rc [catch { db eval { INSERT INTO rt VALUES(53,53,53) } } msg]
    break;
  }
  list $rc $msg
} {1 {database table is locked}}
do_test 8.2 {
  db eval { SELECT * FROM rt ORDER BY +id } {
    set rc [catch { db eval { INSERT INTO rt VALUES(53,53,53) } } msg]
    break
  }
  list $rc $msg
} {0 {}}

#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
# Section 4 of documentation.
#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
set testprefix rtreedoc-8
reset_db

# EVIDENCE-OF: R-21062-30088 For the example above, one might create an
# auxiliary table as follows: CREATE TABLE demo_data( id INTEGER PRIMARY
# KEY, -- primary key objname TEXT, -- name of the object objtype TEXT,
# -- object type boundary BLOB -- detailed boundary of object );
#
# One might.
#
do_execsql_test 1.0 {
  CREATE TABLE demo_data(
      id INTEGER PRIMARY KEY,  -- primary key
      objname TEXT,            -- name of the object
      objtype TEXT,            -- object type
      boundary BLOB            -- detailed boundary of object
  );
}

do_execsql_test 1.1 {
  CREATE VIRTUAL TABLE demo_index USING rtree(
      id,              -- Integer primary key
      minX, maxX,      -- Minimum and maximum X coordinate
      minY, maxY       -- Minimum and maximum Y coordinate
  );

  INSERT INTO demo_index VALUES
    (28215, -80.781227, -80.604706, 35.208813, 35.297367),
    (28216, -80.957283, -80.840599, 35.235920, 35.367825),
    (28217, -80.960869, -80.869431, 35.133682, 35.208233),
    (28226, -80.878983, -80.778275, 35.060287, 35.154446),
    (28227, -80.745544, -80.555382, 35.130215, 35.236916),
    (28244, -80.844208, -80.841988, 35.223728, 35.225471),
    (28262, -80.809074, -80.682938, 35.276207, 35.377747),
    (28269, -80.851471, -80.735718, 35.272560, 35.407925),
    (28270, -80.794983, -80.728966, 35.059872, 35.161823),
    (28273, -80.994766, -80.875259, 35.074734, 35.172836),
    (28277, -80.876793, -80.767586, 35.001709, 35.101063),
    (28278, -81.058029, -80.956375, 35.044701, 35.223812),
    (28280, -80.844208, -80.841972, 35.225468, 35.227203),
    (28282, -80.846382, -80.844193, 35.223972, 35.225655);

  INSERT INTO demo_index 
    SELECT NULL, minX, maxX, minY+0.2, maxY+0.2 FROM demo_index;
  INSERT INTO demo_index 
    SELECT NULL, minX+0.2, maxX+0.2, minY, maxY FROM demo_index;
  INSERT INTO demo_index 
    SELECT NULL, minX, maxX, minY+0.4, maxY+0.4 FROM demo_index;
  INSERT INTO demo_index 
    SELECT NULL, minX+0.4, maxX+0.4, minY, maxY FROM demo_index;
  INSERT INTO demo_index 
    SELECT NULL, minX, maxX, minY+0.8, maxY+0.8 FROM demo_index;
  INSERT INTO demo_index 
    SELECT NULL, minX+0.8, maxX+0.8, minY, maxY FROM demo_index;

  INSERT INTO demo_data(id) SELECT id FROM demo_index;

  SELECT count(*) FROM demo_index;
} {896}

set ::contained_in 0
proc contained_in {args} {incr ::contained_in ; return 0}
db func contained_in contained_in

# EVIDENCE-OF: R-32671-43888 Then an efficient way to find the specific
# ZIP code for the main SQLite office would be to run a query like this:
# SELECT objname FROM demo_data, demo_index WHERE
# demo_data.id=demo_index.id AND contained_in(demo_data.boundary,
# 35.37785, -80.77470) AND minX<=-80.77470 AND maxX>=-80.77470 AND
# minY<=35.37785 AND maxY>=35.37785;
do_vmstep_test 1.2 {
  SELECT objname FROM demo_data, demo_index
    WHERE demo_data.id=demo_index.id
    AND contained_in(demo_data.boundary, 35.37785, -80.77470)
    AND minX<=-80.77470 AND maxX>=-80.77470
    AND minY<=35.37785  AND maxY>=35.37785;
} {$step<100}
set ::contained_in1 $::contained_in

# EVIDENCE-OF: R-32761-23915 One would get the same answer without the
# use of the R*Tree index using the following simpler query: SELECT
# objname FROM demo_data WHERE contained_in(demo_data.boundary,
# 35.37785, -80.77470);
set ::contained_in 0
do_vmstep_test 1.3 {
  SELECT objname FROM demo_data
    WHERE contained_in(demo_data.boundary, 35.37785, -80.77470);
} {$step>3200}

# EVIDENCE-OF: R-40261-32799 The problem with this latter query is that
# it must apply the contained_in() function to all entries in the
# demo_data table.
#
# 896 of them, IIRC.
do_test 1.4 {
  set ::contained_in
} 896

# EVIDENCE-OF: R-24212-52761 The use of the R*Tree in the penultimate
# query reduces the number of calls to contained_in() function to a
# small subset of the entire table.
#
# 2 is a small subset of 896.
#
# EVIDENCE-OF: R-39057-63901 The R*Tree index did not find the exact
# answer itself, it merely limited the search space.
#
# contained_in() filtered out those 2 rows.
do_test 1.5 {
  set ::contained_in1
} {2}


#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
# Section 4.1 of documentation.
#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
set testprefix rtreedoc-9
reset_db

# EVIDENCE-OF: R-46566-43213 Beginning with SQLite version 3.24.0
# (2018-06-04), r-tree tables can have auxiliary columns that store
# arbitrary data. Auxiliary columns can be used in place of secondary
# tables such as "demo_data".
#
# EVIDENCE-OF: R-41287-48160 Auxiliary columns are marked with a "+"
# symbol before the column name.
#
# This interface cannot conveniently be used to prove anything about 
# versions of SQLite prior to 3.24.0.
#
do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE rta USING rtree(
    id, u1,u2,  v1,v2,   +aux
  );

  INSERT INTO rta(aux) VALUES(NULL);
  INSERT INTO rta(aux) VALUES(45);
  INSERT INTO rta(aux) VALUES(22.3);
  INSERT INTO rta(aux) VALUES('hello');
  INSERT INTO rta(aux) VALUES(X'ABCD');

  SELECT typeof(aux), quote(aux) FROM rta;
} {
  null NULL
  integer 45
  real 22.3
  text 'hello'
  blob X'ABCD'
}

# EVIDENCE-OF: R-30514-26093 Auxiliary columns must come after all of
# the coordinate boundary columns.
foreach {tn cols} {
  1 "id x1,x2, +extra,  y1,y2"
  2 "extra, +id x1,x2, y1,y2"
  3 "id, x1,+x2, extra, y1,y2"
} {
  do_catchsql_test 2.$tn "
    CREATE VIRTUAL TABLE rrr USING rtree($cols)
  " {1 {Auxiliary rtree columns must be last}}
}
do_catchsql_test 3.0 {
  CREATE VIRTUAL TABLE rrr USING rtree(+id, extra, x1, x2);
} {1 {near "+": syntax error}}

# EVIDENCE-OF: R-01280-03635 An RTREE table can have no more than 100
# columns total. In other words, the count of columns including the
# integer primary key column, the coordinate boundary columns, and all
# auxiliary columns must be 100 or less.
do_catchsql_test 3.1 {
  CREATE VIRTUAL TABLE r1 USING rtree(intid, u1,u2,
    +c00, +c01, +c02, +c03, +c04, +c05, +c06, +c07, +c08, +c09,
    +c10, +c11, +c12, +c13, +c14, +c15, +c16, +c17, +c18, +c19,
    +c20, +c21, +c22, +c23, +c24, +c25, +c26, +c27, +c28, +c29,
    +c30, +c31, +c32, +c33, +c34, +c35, +c36, +c37, +c38, +c39,
    +c40, +c41, +c42, +c43, +c44, +c45, +c46, +c47, +c48, +c49,
    +c50, +c51, +c52, +c53, +c54, +c55, +c56, +c57, +c58, +c59,
    +c60, +c61, +c62, +c63, +c64, +c65, +c66, +c67, +c68, +c69,
    +c70, +c71, +c72, +c73, +c74, +c75, +c76, +c77, +c78, +c79,
    +c80, +c81, +c82, +c83, +c84, +c85, +c86, +c87, +c88, +c89,
    +c90, +c91, +c92, +c93, +c94, +c95, +c96
  );
} {0 {}}
do_catchsql_test 3.2 {
  DROP TABLE r1;
  CREATE VIRTUAL TABLE r1 USING rtree(intid, u1,u2,
    +c00, +c01, +c02, +c03, +c04, +c05, +c06, +c07, +c08, +c09,
    +c10, +c11, +c12, +c13, +c14, +c15, +c16, +c17, +c18, +c19,
    +c20, +c21, +c22, +c23, +c24, +c25, +c26, +c27, +c28, +c29,
    +c30, +c31, +c32, +c33, +c34, +c35, +c36, +c37, +c38, +c39,
    +c40, +c41, +c42, +c43, +c44, +c45, +c46, +c47, +c48, +c49,
    +c50, +c51, +c52, +c53, +c54, +c55, +c56, +c57, +c58, +c59,
    +c60, +c61, +c62, +c63, +c64, +c65, +c66, +c67, +c68, +c69,
    +c70, +c71, +c72, +c73, +c74, +c75, +c76, +c77, +c78, +c79,
    +c80, +c81, +c82, +c83, +c84, +c85, +c86, +c87, +c88, +c89,
    +c90, +c91, +c92, +c93, +c94, +c95, +c96, +c97
  );
} {1 {Too many columns for an rtree table}}
do_catchsql_test 3.3 {
  CREATE VIRTUAL TABLE r1 USING rtree(intid, u1,u2, v1,v2,
    +c00, +c01, +c02, +c03, +c04, +c05, +c06, +c07, +c08, +c09,
    +c10, +c11, +c12, +c13, +c14, +c15, +c16, +c17, +c18, +c19,
    +c20, +c21, +c22, +c23, +c24, +c25, +c26, +c27, +c28, +c29,
    +c30, +c31, +c32, +c33, +c34, +c35, +c36, +c37, +c38, +c39,
    +c40, +c41, +c42, +c43, +c44, +c45, +c46, +c47, +c48, +c49,
    +c50, +c51, +c52, +c53, +c54, +c55, +c56, +c57, +c58, +c59,
    +c60, +c61, +c62, +c63, +c64, +c65, +c66, +c67, +c68, +c69,
    +c70, +c71, +c72, +c73, +c74, +c75, +c76, +c77, +c78, +c79,
    +c80, +c81, +c82, +c83, +c84, +c85, +c86, +c87, +c88, +c89,
    +c90, +c91, +c92, +c93, +c94,
  );
} {0 {}}
do_catchsql_test 3.4 {
  DROP TABLE r1;
  CREATE VIRTUAL TABLE r1 USING rtree(intid, u1,u2, v1,v2,
    +c00, +c01, +c02, +c03, +c04, +c05, +c06, +c07, +c08, +c09,
    +c10, +c11, +c12, +c13, +c14, +c15, +c16, +c17, +c18, +c19,
    +c20, +c21, +c22, +c23, +c24, +c25, +c26, +c27, +c28, +c29,
    +c30, +c31, +c32, +c33, +c34, +c35, +c36, +c37, +c38, +c39,
    +c40, +c41, +c42, +c43, +c44, +c45, +c46, +c47, +c48, +c49,
    +c50, +c51, +c52, +c53, +c54, +c55, +c56, +c57, +c58, +c59,
    +c60, +c61, +c62, +c63, +c64, +c65, +c66, +c67, +c68, +c69,
    +c70, +c71, +c72, +c73, +c74, +c75, +c76, +c77, +c78, +c79,
    +c80, +c81, +c82, +c83, +c84, +c85, +c86, +c87, +c88, +c89,
    +c90, +c91, +c92, +c93, +c94, +c95,
  );
} {1 {Too many columns for an rtree table}}

# EVIDENCE-OF: R-05552-15084
do_execsql_test 4.0 {
  CREATE VIRTUAL TABLE demo_index2 USING rtree(
      id,              -- Integer primary key
      minX, maxX,      -- Minimum and maximum X coordinate
      minY, maxY,      -- Minimum and maximum Y coordinate
      +objname TEXT,   -- name of the object
      +objtype TEXT,   -- object type
      +boundary BLOB   -- detailed boundary of object
  );
}
do_execsql_test 4.1 {
  CREATE VIRTUAL TABLE demo_index USING rtree(
      id,              -- Integer primary key
      minX, maxX,      -- Minimum and maximum X coordinate
      minY, maxY       -- Minimum and maximum Y coordinate
  );
  CREATE TABLE demo_data(
      id INTEGER PRIMARY KEY,  -- primary key
      objname TEXT,            -- name of the object
      objtype TEXT,            -- object type
      boundary BLOB            -- detailed boundary of object
  );

  INSERT INTO demo_index2(id) VALUES(1);
  INSERT INTO demo_index(id) VALUES(1);
  INSERT INTO demo_data(id) VALUES(1);
}
do_test 4.2 {
  catch { array unset R }
  db eval {SELECT * FROM demo_index2} R { set r1 [array names R] }
  catch { array unset R }
  db eval {SELECT * FROM demo_index NATURAL JOIN demo_data } R { 
    set r2 [array names R] 
  }
  expr {$r1==$r2}
} {1}

# EVIDENCE-OF: R-26099-32169 SELECT objname FROM demo_index2 WHERE
# contained_in(boundary, 35.37785, -80.77470) AND minX<=-80.77470 AND
# maxX>=-80.77470 AND minY<=35.37785 AND maxY>=35.37785;
do_execsql_test 4.3.1 {
  DELETE FROM demo_index2;
  INSERT INTO demo_index2(id,minX,maxX,minY,maxY) VALUES
    (28215, -80.781227, -80.604706, 35.208813, 35.297367),
    (28216, -80.957283, -80.840599, 35.235920, 35.367825),
    (28217, -80.960869, -80.869431, 35.133682, 35.208233),
    (28226, -80.878983, -80.778275, 35.060287, 35.154446),
    (28227, -80.745544, -80.555382, 35.130215, 35.236916),
    (28244, -80.844208, -80.841988, 35.223728, 35.225471),
    (28262, -80.809074, -80.682938, 35.276207, 35.377747),
    (28269, -80.851471, -80.735718, 35.272560, 35.407925),
    (28270, -80.794983, -80.728966, 35.059872, 35.161823),
    (28273, -80.994766, -80.875259, 35.074734, 35.172836),
    (28277, -80.876793, -80.767586, 35.001709, 35.101063),
    (28278, -81.058029, -80.956375, 35.044701, 35.223812),
    (28280, -80.844208, -80.841972, 35.225468, 35.227203),
    (28282, -80.846382, -80.844193, 35.223972, 35.225655);
}
set ::contained_in 0
proc contained_in {args} {
  incr ::contained_in
  return 0
}
db func contained_in contained_in
do_execsql_test 4.3.2 {
  SELECT objname FROM demo_index2
    WHERE contained_in(boundary, 35.37785, -80.77470)
    AND minX<=-80.77470 AND maxX>=-80.77470
    AND minY<=35.37785  AND maxY>=35.37785;
}
do_test 4.3.3 {
  # Function invoked only once because r-tree filtering happened first.
  set ::contained_in
} 1
set ::contained_in 0
do_execsql_test 4.3.4 {
  SELECT objname FROM demo_index2
    WHERE contained_in(boundary, 35.37785, -80.77470)
}
do_test 4.3.3 {
  # Function invoked 14 times because no r-tree filtering. Inefficient.
  set ::contained_in
} 14

#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
# Section 4.1.1 of documentation.
#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
set testprefix rtreedoc-9
reset_db

# EVIDENCE-OF: R-24021-02490 For auxiliary columns, only the name of the
# column matters. The type affinity is ignored.
#
# EVIDENCE-OF: R-39906-44154 Constraints such as NOT NULL, UNIQUE,
# REFERENCES, or CHECK are also ignored.
do_execsql_test 1.0 { PRAGMA foreign_keys = on }
foreach {tn auxcol nm} {
  1 "+extra INTEGER" extra
  2 "+extra TEXT"    extra
  3 "+extra BLOB"    extra
  4 "+extra REAL"    extra

  5 "+col NOT NULL"                 col
  6 "+col CHECK (col IS NOT NULL)"  col
  7 "+col REFERENCES tbl(x)"        col
} {
  do_execsql_test 1.$tn.1 "
    CREATE VIRTUAL TABLE rt USING rtree_i32(k, a,b, $auxcol)
  "

  # Check that the aux column has no affinity. Or NOT NULL constraint.
  # And that the aux column is the child key of an FK constraint.
  #
  do_execsql_test 1.$tn.2 "
    INSERT INTO rt($nm) VALUES(NULL), (45), (-123.2), ('456'), (X'ABCD');
    SELECT typeof($nm), quote($nm) FROM rt;
  " {
    null NULL
    integer 45
    real -123.2
    text '456'
    blob X'ABCD'
  }

  # Check that there is no UNIQUE constraint either.
  #
  do_execsql_test 1.$tn.3 "
    INSERT INTO rt($nm) VALUES('xyz'), ('xyz'), ('xyz');
  "

  do_execsql_test 1.$tn.2 {
    DROP TABLE rt
  }
}

#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
# Section 5 of documentation.
#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
set testprefix rtreedoc-10

# EVIDENCE-OF: R-21011-43790 If integer coordinates are desired, declare
# the table using "rtree_i32" instead: CREATE VIRTUAL TABLE intrtree
# USING rtree_i32(id,x0,x1,y0,y1,z0,z1);
do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE intrtree USING rtree_i32(id,x0,x1,y0,y1,z0,z1);
  INSERT INTO intrtree DEFAULT VALUES;
  SELECT typeof(x0) FROM intrtree;
} {integer}

# EVIDENCE-OF: R-09193-49806 An rtree_i32 stores coordinates as 32-bit
# signed integers.
#
# Show that coordinates are cast in a way consistent with casting to
# a signed 32-bit integer.
do_execsql_test 1.1 {
  DELETE FROM intrtree;
  INSERT INTO intrtree VALUES(333,
      1<<44, (1<<44)+1,
      10000000000, 10000000001,
      -10000000001, -10000000000
  );
  SELECT * FROM intrtree;
} {
  333 0 1 1410065408 1410065409 -1410065409 -1410065408
}

#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
# Section 7.1 of documentation.
#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
set testprefix rtreedoc-11
reset_db

# This command assumes that the argument is a node blob for a 2 dimensional
# i32 r-tree table. It decodes and returns a list of cells from the node
# as a list. Each cell is itself a list of the following form:
#
#    {$rowid $minX $maxX $minY $maxY}
#
# For internal (non-leaf) nodes, the rowid is replaced by the child node
# number.
#
proc rnode {aData} {
  set nDim 2

  set nData [string length $aData]
  set nBytePerCell [expr (8 + 2*$nDim*4)]
  binary scan [string range $aData 2 3] S nCell

  set res [list]
  for {set i 0} {$i < $nCell} {incr i} {
    set iOff [expr $i*$nBytePerCell+4]
    set cell [string range $aData $iOff [expr $iOff+$nBytePerCell-1]]
    binary scan $cell WIIII rowid x1 x2 y1 y2
    lappend res [list $rowid $x1 $x2 $y1 $y2]
  }

  return $res
}

# aData must be a node blob. This command returns true if the node contains
# rowid $rowid, or false otherwise.
#
proc rnode_contains {aData rowid} {
  set L [rnode $aData]
  foreach cell $L {
    set r [lindex $cell 0]
    if {$r==$rowid} { return 1 }
  }
  return 0
}

proc rnode_replace_cell {aData iCell cell} {
  set aCell [binary format WIIII {*}$cell]
  set nDim 2
  set nBytePerCell [expr (8 + 2*$nDim*4)]
  set iOff [expr $iCell*$nBytePerCell+4]

  set aNew [binary format a*a*a* \
      [string range $aData 0 $iOff-1]     \
      $aCell     \
      [string range $aData $iOff+$nBytePerCell end] \
  ]
  return $aNew
}

db function rnode rnode
db function rnode_contains rnode_contains
db function rnode_replace_cell rnode_replace_cell

foreach {tn nm} {
  1 x1
  2 asdfghjkl
  3 hello_world
} {
  do_execsql_test 1.$tn.1 "
    CREATE VIRTUAL TABLE $nm USING rtree(a,b,c,d,e);
  "

  # EVIDENCE-OF: R-33789-46762 The content of an R*Tree index is actually
  # stored in three ordinary SQLite tables with names derived from the
  # name of the R*Tree.
  #
  # EVIDENCE-OF: R-39849-06566 This is their schema: CREATE TABLE
  # %_node(nodeno INTEGER PRIMARY KEY, data) CREATE TABLE %_parent(nodeno
  # INTEGER PRIMARY KEY, parentnode) CREATE TABLE %_rowid(rowid INTEGER
  # PRIMARY KEY, nodeno)
  #
  # EVIDENCE-OF: R-07489-10051 The "%" in the name of each shadow table is
  # replaced by the name of the R*Tree virtual table. So, if the name of
  # the R*Tree table is "xyz" then the three shadow tables would be
  # "xyz_node", "xyz_parent", and "xyz_rowid".
  do_execsql_test 1.$tn.2 {
    SELECT sql FROM sqlite_schema WHERE name!=$nm ORDER BY 1
  } [string map [list % $nm] "
    {CREATE TABLE \"%_node\"(nodeno INTEGER PRIMARY KEY,data)}
    {CREATE TABLE \"%_parent\"(nodeno INTEGER PRIMARY KEY,parentnode)}
    {CREATE TABLE \"%_rowid\"(rowid INTEGER PRIMARY KEY,nodeno)}
  "]

  do_execsql_test 1.$tn "DROP TABLE $nm"
}


# EVIDENCE-OF: R-51070-59303 There is one entry in the %_node table for
# each R*Tree node.
#
# The following creates a 6 node r-tree structure.
#
do_execsql_test 2.0 {
  CREATE VIRTUAL TABLE r1 USING rtree_i32(i, x1,x2, y1,y2);
  WITH t(i) AS (
    VALUES(1) UNION SELECT i+1 FROM t WHERE i<110
  )
  INSERT INTO r1 SELECT i, (i%10), (i%10)+2, (i%6), (i%7)+6 FROM t;
}
do_execsql_test 2.1 {
  SELECT count(*) FROM r1_node;
} 6

# EVIDENCE-OF: R-27261-09153 All nodes other than the root have an entry
# in the %_parent shadow table that identifies the parent node.
#
# In this case nodes 2-6 are the children of node 1.
#
do_execsql_test 2.3 {
  SELECT nodeno, parentnode FROM r1_parent
} {2 1  3 1  4 1  5 1  6 1}

# EVIDENCE-OF: R-02358-35037 The %_rowid shadow table maps entry rowids
# to the node that contains that entry.
#
do_execsql_test 2.4 {
  SELECT 'failed' FROM r1_rowid WHERE 0==rnode_contains(
    (SELECT data FROM r1_node WHERE nodeno=r1_rowid.nodeno), rowid
  )
}
do_test 2.5 {
  db eval { SELECT nodeno, data FROM r1_node WHERE nodeno!=1 } {
    set L [rnode $data]
    foreach cell $L {
      set rowid [lindex $cell 0]
      set rowid_nodeno 0
      db eval {SELECT nodeno AS rowid_nodeno FROM r1_rowid WHERE rowid=$rowid} {
        break
      }
      if {$rowid_nodeno!=$nodeno} { error "data mismatch!" }
    }
  }
} {}

# EVIDENCE-OF: R-65201-22208 Extra columns appended to the %_rowid table
# hold the content of auxiliary columns.
#
# EVIDENCE-OF: R-44161-28345 The names of these extra %_rowid columns
# are probably not the same as the actual auxiliary column names.
#
# In this case, the auxiliary columns are named "e1" and "e2". The
# extra %_rowid columns are named "a0" and "a1".
#
do_execsql_test 3.0 {
  CREATE VIRTUAL TABLE rtaux USING rtree(id, x1,x2, y1,y2, +e1, +e2);
  SELECT sql FROM sqlite_schema WHERE name='rtaux_rowid';
} {
  {CREATE TABLE "rtaux_rowid"(rowid INTEGER PRIMARY KEY,nodeno,a0,a1)}
}
do_execsql_test 3.1 {
  INSERT INTO rtaux(e1, e2) VALUES('hello', 'world'), (123, 456);
}
do_execsql_test 3.2 {
  SELECT a0, a1 FROM rtaux_rowid;
} {
  hello world  123 456
}

#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
# Section 7.2 of documentation.
#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
set testprefix rtreedoc-12
reset_db
forcedelete test.db2

db function rnode rnode
db function rnode_contains rnode_contains
db function rnode_replace_cell rnode_replace_cell

# EVIDENCE-OF: R-13571-45795 The scalar SQL function rtreecheck(R) or
# rtreecheck(S,R) runs an integrity check on the rtree table named R
# contained within database S.
#
# EVIDENCE-OF: R-36011-59963 The function returns a human-language
# description of any problems found, or the string 'ok' if everything is
# ok.
#
do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE rt1 USING rtree(id, a, b);
  WITH s(i) AS (
    VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<200
  )
  INSERT INTO rt1 SELECT i, i, i FROM s;

  ATTACH 'test.db2' AS 'aux';
  CREATE VIRTUAL TABLE aux.rt1 USING rtree(id, a, b);
  INSERT INTO aux.rt1 SELECT * FROM rt1;
}

do_execsql_test 1.1.1 { SELECT rtreecheck('rt1'); } {ok}
do_execsql_test 1.1.2 { SELECT rtreecheck('main', 'rt1'); } {ok}
do_execsql_test 1.1.3 { SELECT rtreecheck('aux', 'rt1'); } {ok}
do_catchsql_test 1.1.4 { 
  SELECT rtreecheck('nosuchdb', 'rt1'); 
} {1 {SQL logic error}}

# Corrupt the table in database 'main':
do_execsql_test 1.2.1 { UPDATE rt1_node SET nodeno=21 WHERE nodeno=3; }
do_execsql_test 1.2.1 { SELECT rtreecheck('rt1')=='ok'; } {0}
do_execsql_test 1.2.2 { SELECT rtreecheck('main', 'rt1')=='ok'; } {0}
do_execsql_test 1.2.3 { SELECT rtreecheck('aux', 'rt1')=='ok'; } {1}
do_execsql_test 1.2.4 { UPDATE rt1_node SET nodeno=3 WHERE nodeno=21; }

# Corrupt the table in database 'aux':
do_execsql_test 1.2.1 { UPDATE aux.rt1_node SET nodeno=21 WHERE nodeno=3; }
do_execsql_test 1.2.1 { SELECT rtreecheck('rt1')=='ok'; } {1}
do_execsql_test 1.2.2 { SELECT rtreecheck('main', 'rt1')=='ok'; } {1}
do_execsql_test 1.2.3 { SELECT rtreecheck('aux', 'rt1')=='ok'; } {0}
do_execsql_test 1.2.4 { UPDATE rt1_node SET nodeno=3 WHERE nodeno=21; }

# EVIDENCE-OF: R-45759-33459 Example: To verify that an R*Tree named
# "demo_index" is well-formed and internally consistent, run: SELECT
# rtreecheck('demo_index');
do_execsql_test 2.0 {
  CREATE VIRTUAL TABLE demo_index USING rtree(id, x1,x2, y1,y2);
  INSERT INTO demo_index SELECT id, a, b, a, b FROM rt1;
}
do_execsql_test 2.1 { SELECT rtreecheck('demo_index') } {ok}
do_execsql_test 2.2 {
  UPDATE demo_index_rowid SET nodeno=44 WHERE rowid=44;
  SELECT rtreecheck('demo_index');
} {{Found (44 -> 44) in %_rowid table, expected (44 -> 4)}}


do_execsql_test 3.0 {
  CREATE VIRTUAL TABLE rt2 USING rtree_i32(id, a, b, c, d);
  WITH s(i) AS (
    VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<200
  )
  INSERT INTO rt2 SELECT i, i, i+2, i, i+2 FROM s;
}

# EVIDENCE-OF: R-02555-31045 for each dimension, (coord1 <= coord2).
#
execsql BEGIN
do_test 3.1 {
  set cell [
    lindex [execsql {SELECT rnode(data) FROM rt2_node WHERE nodeno=3}] 0 3
  ]
  set cell [list [lindex $cell 0]       \
    [lindex $cell 2] [lindex $cell 1]   \
    [lindex $cell 3] [lindex $cell 4]   \
  ]
  execsql { 
    UPDATE rt2_node SET data=rnode_replace_cell(data, 3, $cell) WHERE nodeno=3 
  }
  execsql { SELECT rtreecheck('rt2') }
} {{Dimension 0 of cell 3 on node 3 is corrupt}}
execsql ROLLBACK

# EVIDENCE-OF: R-13844-15873 unless the cell is on the root node, that
# the cell is bounded by the parent cell on the parent node.
#
execsql BEGIN
do_test 3.2 {
  set cell [
    lindex [execsql {SELECT rnode(data) FROM rt2_node WHERE nodeno=3}] 0 3
  ]
  lset cell 3 450
  lset cell 4 451
  execsql { 
    UPDATE rt2_node SET data=rnode_replace_cell(data, 3, $cell) WHERE nodeno=3 
  }
  execsql { SELECT rtreecheck('rt2') }
} {{Dimension 1 of cell 3 on node 3 is corrupt relative to parent}}
execsql ROLLBACK

# EVIDENCE-OF: R-02505-03621 for leaf nodes, that there is an entry in
# the %_rowid table corresponding to the cell's rowid value that points
# to the correct node.
#
execsql BEGIN
do_test 3.3 {
  execsql { 
    UPDATE rt2_rowid SET rowid=452 WHERE rowid=100
  }
  execsql { SELECT rtreecheck('rt2') }
} {{Mapping (100 -> 6) missing from %_rowid table}}
execsql ROLLBACK

# EVIDENCE-OF: R-50927-02218 for cells on non-leaf nodes, that there is
# an entry in the %_parent table mapping from the cell's child node to
# the node that it resides on.
#
execsql BEGIN
do_test 3.4.1 {
  execsql { 
    UPDATE rt2_parent SET parentnode=123 WHERE nodeno=3
  }
  execsql { SELECT rtreecheck('rt2') }
} {{Found (3 -> 123) in %_parent table, expected (3 -> 1)}}
execsql ROLLBACK
execsql BEGIN
do_test 3.4.2 {
  execsql { 
    UPDATE rt2_parent SET nodeno=123 WHERE nodeno=3
  }
  execsql { SELECT rtreecheck('rt2') }
} {{Mapping (3 -> 1) missing from %_parent table}}
execsql ROLLBACK

# EVIDENCE-OF: R-23235-09153 That there are the same number of entries
# in the %_rowid table as there are leaf cells in the r-tree structure,
# and that there is a leaf cell that corresponds to each entry in the
# %_rowid table.
execsql BEGIN
do_test 3.5 {
  execsql { INSERT INTO rt2_rowid VALUES(1000, 1000) }
  execsql { SELECT rtreecheck('rt2') }
} {{Wrong number of entries in %_rowid table - expected 200, actual 201}}
execsql ROLLBACK

# EVIDENCE-OF: R-62800-43436 That there are the same number of entries
# in the %_parent table as there are non-leaf cells in the r-tree
# structure, and that there is a non-leaf cell that corresponds to each
# entry in the %_parent table.
execsql BEGIN
do_test 3.6 {
  execsql { INSERT INTO rt2_parent VALUES(1000, 1000) }
  execsql { SELECT rtreecheck('rt2') }
} {{Wrong number of entries in %_parent table - expected 9, actual 10}}
execsql ROLLBACK



finish_test

Added ext/rtree/rtreedoc2.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2021 September 13
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# The focus of this file is testing the r-tree extension.
#

if {![info exists testdir]} {
  set testdir [file join [file dirname [info script]] .. .. test]
}
source [file join [file dirname [info script]] rtree_util.tcl]
source $testdir/tester.tcl
set testprefix rtreedoc2

ifcapable !rtree {
  finish_test
  return
}

#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
# Section 6 of documentation.
#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
set testprefix rtreedoc2-1

# EVIDENCE-OF: R-35254-48865 A call to one of the above APIs creates a
# new SQL function named by the second parameter (zQueryFunc or zGeom).
#
# [register_circle_geom db] registers new geometry callback "Qcircle"
# and legacy implementation "circle". Test that these do actually appear.
#
do_execsql_test 1.1.0 {
  SELECT * FROM pragma_function_list WHERE name IN('circle', 'qcircle');
} {
}
do_test 1.1 {
  register_circle_geom db
} {SQLITE_OK}
do_execsql_test 1.1.2 {
  SELECT * FROM pragma_function_list WHERE name = 'circle' AND enc='utf8';
} {
  circle 0 s utf8 -1 0
}
do_execsql_test 1.1.3 {
  SELECT * FROM pragma_function_list WHERE name = 'qcircle' AND enc='utf8';
} {
  qcircle 0 s utf8 -1 0
} 

do_execsql_test 1.2.0 { SELECT circle(1, 2, 3); } {{}}
do_execsql_test 1.2.1 { SELECT qcircle(1, 2, 3); } {{}}

# EVIDENCE-OF: R-61427-46983
do_execsql_test 1.3.0 {
  CREATE VIRTUAL TABLE demo_index USING rtree(id, x1,x2, y1,y2);
  INSERT INTO demo_index VALUES(10, 45,45,  24,24);
  INSERT INTO demo_index VALUES(20, 50,50,  28,28);
  INSERT INTO demo_index VALUES(30, 43,43,  22,22);
}
do_execsql_test 1.3.1 {
  SELECT id FROM demo_index WHERE id MATCH circle(45.3, 22.9, 5.0)
} {10 30}

# EVIDENCE-OF: R-16907-50223 The SQL syntax for custom queries is the
# same regardless of which interface, sqlite3_rtree_geometry_callback()
# or sqlite3_rtree_query_callback(), is used to register the SQL
# function.
do_execsql_test 1.3.2 {
  SELECT id FROM demo_index WHERE id MATCH qcircle(45.3, 22.9, 5.0, 1)
} {10 30}


# EVIDENCE-OF: R-59634-51678 When that SQL function appears on the
# right-hand side of the MATCH operator and the left-hand side of the
# MATCH operator is any column in the R*Tree virtual table, then the
# callback defined by the third argument (xQueryFunc or xGeom) is
# invoked to determine if a particular object or subtree overlaps the
# desired region.
proc box_geom {args} {
  lappend ::box_geom [concat [lindex $args 0] [lrange $args 2 end-1]]
  return ""
}
register_box_geom db box_geom
set box_geom [list]
do_execsql_test 1.3.2 {
  SELECT id FROM demo_index WHERE id MATCH box(43,46, 21,25);
} {10 30}
do_test 1.3.3 {
  set ::box_geom
} [list {*}{
  {box {43.0 46.0 21.0 25.0} {45.0 45.0 24.0 24.0}}
  {box {43.0 46.0 21.0 25.0} {50.0 50.0 28.0 28.0}} 
  {box {43.0 46.0 21.0 25.0} {43.0 43.0 22.0 22.0}}
}]

#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
# Section 6 of documentation.
#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
set testprefix rtreedoc2-2

# EVIDENCE-OF: R-02424-24769 The second argument is the number of
# coordinates in each r-tree entry, and is always the same for any given
# R*Tree.
#
# EVIDENCE-OF: R-40260-16838 The number of coordinates is 2 for a
# 1-dimensional R*Tree, 4 for a 2-dimensional R*Tree, 6 for a
# 3-dimensional R*Tree, and so forth.
#
# The second argument refered to above is the length of the list passed
# as the 3rd parameter to the Tcl script.
#
do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE rt1 USING rtree(id, x1,x2);
  CREATE VIRTUAL TABLE rt2 USING rtree(id, x1,x2, y1,y2);
  CREATE VIRTUAL TABLE rt3 USING rtree(id, x1,x2, y1,y2, z1,z2);

  INSERT INTO rt1 DEFAULT VALUES;
  INSERT INTO rt2 DEFAULT VALUES;
  INSERT INTO rt3 DEFAULT VALUES;
}
foreach {tn tbl nCoord} {
  1 rt1 2     
  2 rt2 4
  3 rt3 6
} {
  set ::box_geom [list]
  do_catchsql_test 1.$tn.1 "
    SELECT id FROM $tbl WHERE id MATCH box();
  " {1 {SQL logic error}}

  do_test 1.$tn.2 {
    llength [lindex $::box_geom 0 2]
  } $nCoord
}

# EVIDENCE-OF: R-28051-48608 If xGeom returns anything other than
# SQLITE_OK, then the r-tree query will abort with an error.
proc box_geom {args} {
  error "an error!"
}
do_catchsql_test 2.0 {
  SELECT * FROM rt2 WHERE id MATCH box(22,23, 24,25); 
} {1 {SQL logic error}}

do_execsql_test 3.0 {
  INSERT INTO rt1 VALUES(10, 10, 10);
  INSERT INTO rt1 VALUES(11, 11, 11);
  INSERT INTO rt1 VALUES(12, 12, 12);
  INSERT INTO rt1 VALUES(13, 13, 13);
  INSERT INTO rt1 VALUES(14, 14, 14);
}

# EVIDENCE-OF: R-53759-57366 The exact same sqlite3_rtree_geometry
# structure is used for every callback for same MATCH operator in the
# same query.
proc box_geom {args} {
  lappend ::ptr_list [lindex $args 4]
  return 0
}
set ::ptr_list [list]
do_execsql_test 3.1 {
  SELECT * FROM rt1 WHERE id MATCH box(1,1);
}
do_test 3.2 {
  set val [lindex $::ptr_list 0]
  foreach p $::ptr_list {
    if {$p!=$val} {error "pointer mismatch"}
  }
} {}

# EVIDENCE-OF: R-60247-35692 The contents of the sqlite3_rtree_geometry
# structure are initialized by SQLite but are not subsequently modified.
proc box_geom {args} {
  lappend ::box_geom [concat [lindex $args 0] [lrange $args 2 end-1]]
  if {[llength $::box_geom]==3} {
    return "zero"
  }
  return ""
}
set ::box_geom [list]
do_catchsql_test 3.2 {
  SELECT * FROM rt1 WHERE id MATCH box(1,1);
} {1 {SQL logic error}}
do_test 3.3 {
  set ::box_geom
} [list {*}{
  {box {1.0 1.0} {0.0 0.0}} 
  {box {1.0 1.0} {10.0 10.0}} 
  {box {1.0 1.0} {11.0 11.0}} 
  {box 0.0 {12.0 12.0}}
}]

# EVIDENCE-OF: R-31246-29731 The pContext member of the
# sqlite3_rtree_geometry structure is always set to a copy of the
# pContext argument passed to sqlite3_rtree_geometry_callback() when the
# callback is registered.
reset_db
do_execsql_test 4.0 {
  CREATE VIRTUAL TABLE r1 USING rtree(id, minX,maxX, minY,maxY);
  WITH s(i) AS (
    VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<120
  )
  INSERT INTO r1 SELECT i,i,i+1,  200,201 FROM s;
}
set ctx [register_box_geom db box_geom]
set ::box_geom [list]
proc box_geom {args} {
  lappend ::box_geom [lindex $args 1]
  return ""
}
do_execsql_test 4.1 {
  SELECT count(*) FROM r1 WHERE id MATCH box(0,150,199,201)
} 120
do_test 4.2 {
  foreach g $::box_geom {
    if {$g!=$ctx} {error "pointer mismatch"}
  }
} {}

# EVIDENCE-OF: R-09904-19077 The aParam[] array (size nParam) contains
# the parameter values passed to the SQL function on the right-hand side
# of the MATCH operator.
proc box_geom {args} {
  set ::box_geom [lindex $args 2]
}
foreach {tn q vals} {
  1 "SELECT count(*) FROM r1 WHERE id MATCH box(1,2,3)" {1.0 2.0 3.0}
  2 "SELECT count(*) FROM r1 WHERE id MATCH box(10001)" {10001.0}
  3 "SELECT count(*) FROM r1 WHERE id MATCH box(-10001)" {-10001.0}
} {
  do_catchsql_test 5.$tn.1 $q {1 {SQL logic error}}
  do_test 5.$tn.2 { set ::box_geom } $vals
}

do_execsql_test 5.0 {
  CREATE VIRTUAL TABLE myrtree USING rtree(id, x1,x2);
  INSERT INTO myrtree VALUES(1, 1, 1);
  INSERT INTO myrtree VALUES(2, 2, 2);
  INSERT INTO myrtree VALUES(3, 3, 3);
}

# EVIDENCE-OF: R-44448-00687 The pUser and xDelUser members of the
# sqlite3_rtree_geometry structure are initially set to NULL.
set ::box_geom_calls 0
proc box_geom {args} {
  incr ::box_geom_calls
  return user_is_zero
}
do_execsql_test 5.1.1 {
  SELECT * FROM myrtree WHERE id MATCH box(4, 5);
} 
do_test 5.1.2 { set ::box_geom_calls } 3


# EVIDENCE-OF: R-55837-00155 The pUser variable may be set by the
# callback implementation to any arbitrary value that may be useful to
# subsequent invocations of the callback within the same query (for
# example, a pointer to a complicated data structure used to test for
# region intersection).
#
# EVIDENCE-OF: R-34745-08839 If the xDelUser variable is set to a
# non-NULL value, then after the query has finished running SQLite
# automatically invokes it with the value of the pUser variable as the
# only argument.
#
set ::box_geom_calls 0
proc box_geom {args} {
  incr ::box_geom_calls
  switch -- $::box_geom_calls {
    1 {
      return user_is_zero
    }
    2 {
      return [list user box_geom_finalizer]
    }
  }
  return ""
}
proc box_geom_finalizer {} {
  set ::box_geom_finalizer "::box_geom_calls is $::box_geom_calls"
}
do_execsql_test 5.1.1 {
  SELECT * FROM myrtree WHERE id MATCH box(4, 5);
} 
do_test 5.1.2 { set ::box_geom_calls } 3
do_test 5.1.3 {
  set ::box_geom_finalizer
} {::box_geom_calls is 3}
 

# EVIDENCE-OF: R-28176-28813 The xGeom callback always does a
# depth-first search of the r-tree.
#
# For a breadth first search, final test case would return "B L" only.
#
do_execsql_test 6.0 {
  CREATE VIRTUAL TABLE xyz USING rtree(x, x1,x2, y1,y2);
  WITH s(i) AS (
    VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<15
  )
  INSERT INTO xyz SELECT NULL, one.i,one.i+1,  two.i,two.i+1 FROM s one, s two;
}
do_execsql_test 6.1 {
  SELECT count(*) FROM xyz_node
} {10}
proc box_geom {args} {
  set coords [lindex $args 3]
  set area [expr {
    ([lindex $coords 1]-[lindex $coords 0]) * 
    ([lindex $coords 3]-[lindex $coords 2])
  }]
  if {$area==1} {
    lappend ::box_geom_calls L
  } else {
    lappend ::box_geom_calls B
  }
}
set ::box_geom_calls [list]
do_execsql_test 6.2 {
  SELECT count(*) FROM xyz WHERE x MATCH box(0,20,0,20)
} 225
do_test 6.3 {
  set prev ""
  set box_calls [list]
  foreach c $::box_geom_calls {
    if {$c!=$prev} {
      lappend ::box_calls $c
      set prev $c
    }
  }
  set ::box_calls
} {B L B L B L B L B L B L B L B L B L}


finish_test

Added ext/rtree/rtreedoc3.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2021 September 13
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# The focus of this file is testing the r-tree extension.
#

if {![info exists testdir]} {
  set testdir [file join [file dirname [info script]] .. .. test]
}
source [file join [file dirname [info script]] rtree_util.tcl]
source $testdir/tester.tcl
set testprefix rtreedoc3

ifcapable !rtree {
  finish_test
  return
}


# This command assumes that the argument is a node blob for a 2 dimensional
# i32 r-tree table. It decodes and returns a list of cells from the node
# as a list. Each cell is itself a list of the following form:
#
#    {$rowid $minX $maxX $minY $maxY}
#
# For internal (non-leaf) nodes, the rowid is replaced by the child node
# number.
#
proc rnode_cells {aData} {
  set nDim 2

  set nData [string length $aData]
  set nBytePerCell [expr (8 + 2*$nDim*4)]
  binary scan [string range $aData 2 3] S nCell

  set res [list]
  for {set i 0} {$i < $nCell} {incr i} {
    set iOff [expr $i*$nBytePerCell+4]
    set cell [string range $aData $iOff [expr $iOff+$nBytePerCell-1]]
    binary scan $cell WIIII rowid x1 x2 y1 y2
    lappend res [list $rowid $x1 $x2 $y1 $y2]
  }

  return $res
}

# Interpret the first two bytes of the blob passed as the only parameter
# as a 16-bit big-endian integer and return the value. If this blob is
# the root node of an r-tree, this value is the height of the tree.
#
proc rnode_height {aData} {
  binary scan [string range $aData 0 1] S nHeight
  return $nHeight
}

# Return a blob containing node iNode of r-tree "rt".
#
proc rt_node_get {iNode} {
  db one { SELECT data FROM rt_node WHERE nodeno=$iNode }
}


#--------------------------------------------------------------
# API:
#
#    pq_init 
#      Initialize a new test.
#
#    pq_test_callback
#      Invoked each time the xQueryCallback function is called. This Tcl
#      command checks that the arguments that SQLite passed to xQueryCallback
#      are as expected.
#
#    pq_test_row
#      Invoked each time a row is returned. Checks that the row returned
#      was predicted by the documentation.
#
# DATA STRUCTURE:
#    The priority queue is stored as a Tcl list. The order of elements in 
#    the list is unimportant - it is just used as a set here. Each element
#    in the priority queue is itself a list. The first element is the
#    priority value for the entry (a real). Following this is a list of
#    key-value pairs that make up the entries fields.
#
proc pq_init {} {
  global Q 
  set Q(pri_queue)  [list]

  set nHeight [rnode_height [rt_node_get 1]]
  set nCell [llength [rnode_cells [rt_node_get 1]]]

  # EVIDENCE-OF: R-54708-13595 An R*Tree query is initialized by making
  # the root node the only entry in a priority queue sorted by rScore.
  lappend Q(pri_queue) [list 0.0 [list \
    iLevel [expr $nHeight+1] \
    iChild 1                 \
    iCurrent   0             \
  ]]
}

proc pq_extract {} {
  global Q
  if {[llength $Q(pri_queue)]==0} {
    error "priority queue is empty!"
  }

  # Find the priority queue entry with the lowest score.
  #
  # EVIDENCE-OF: R-47257-47871 Smaller scores are processed first.
  set iBest 0
  set rBestScore [lindex $Q(pri_queue) 0 0]
  for {set ii 1} {$ii < [llength $Q(pri_queue)]} {incr ii} {
    set rScore [expr [lindex $Q(pri_queue) $ii 0]]
    if {$rScore<$rBestScore} {
      set rBestScore $rScore
      set iBest $ii
    }
  }

  # Extract the entry with the lowest score from the queue and return it. 
  #
  # EVIDENCE-OF: R-60002-49798 The query proceeds by extracting the entry
  # from the priority queue that has the lowest score.
  set ret [lindex $Q(pri_queue) $iBest]
  set Q(pri_queue) [lreplace $Q(pri_queue) $iBest $iBest]

  return $ret
}

proc pq_new_entry {rScore iLevel cell} {
  global Q

  set rowid_name "iChild"
  if {$iLevel==0} { set rowid_name "iRowid" }

  set kv [list]
  lappend kv aCoord [lrange $cell 1 end]
  lappend kv iLevel $iLevel

  if {$iLevel==0} {
    lappend kv iRowid [lindex $cell 0]
  } else {
    lappend kv iChild [lindex $cell 0]
    lappend kv iCurrent 0
  }

  lappend Q(pri_queue) [list $rScore $kv]
}

proc pq_test_callback {L res} {
  #pq_debug "pq_test_callback $L -> $res"
  global Q

  array set G $L    ;# "Got" - as in stuff passed to xQuery

  # EVIDENCE-OF: R-65127-42665 If the extracted priority queue entry is a
  # node (a subtree), then the next child of that node is passed to the
  # xQueryFunc callback.
  #
  # If it had been a leaf, the row should have been returned, instead of
  # xQueryCallback being called on a child - as is happening here.
  foreach {rParentScore parent} [pq_extract] {}
  array set P $parent ;# "Parent" - as in parent of expected cell
  if {$P(iLevel)==0} { error "query callback mismatch (1)" }
  set child_node [rnode_cells [rt_node_get $P(iChild)]]
  set expected_cell [lindex $child_node $P(iCurrent)]
  set expected_coords [lrange $expected_cell 1 end]
  if {[llength $expected_coords] != [llength $G(aCoord)]} {
  puts [array get P]
  puts "E: $expected_coords  G: $G(aCoord)"
    error "coordinate mismatch in query callback (1)"
  }
  foreach a [lrange $expected_cell 1 end] b $G(aCoord) {
    if {$a!=$b} { error "coordinate mismatch in query callback (2)" }
  }

  # Check level is as expected
  #
  if {$G(iLevel) != $P(iLevel)-1} {
    error "iLevel mismatch in query callback (1)"
  }

  # Unless the callback returned NOT_WITHIN, add the entry to the priority
  # queue.
  #
  # EVIDENCE-OF: R-28754-35153 Those subelements for which the xQueryFunc
  # callback sets eWithin to PARTLY_WITHIN or FULLY_WITHIN are added to
  # the priority queue using the score supplied by the callback.
  #
  # EVIDENCE-OF: R-08681-45277 Subelements that return NOT_WITHIN are
  # discarded.
  set r [lindex $res 0]
  set rScore [lindex $res 1]
  if {$r!="fully" && $r!="partly" && $r!="not"} {
    error "unknown result: $r - expected \"fully\", \"partly\" or \"not\""
  }
  if {$r!="not"} {
    pq_new_entry $rScore [expr $P(iLevel)-1] $expected_cell
  }

  # EVIDENCE-OF: R-07194-63805 If the node has more children then it is
  # returned to the priority queue. Otherwise it is discarded.
  incr P(iCurrent)
  if {$P(iCurrent)<[llength $child_node]} {
    lappend Q(pri_queue) [list $rParentScore [array get P]]
  }
}

proc pq_test_result {id x1 x2 y1 y2} {
  #pq_debug "pq_test_result $id $x1 $x2 $y1 $y2"
  foreach {rScore next} [pq_extract] {}

  # The extracted entry must be a leaf (otherwise, xQueryCallback would
  # have been called on the extracted entries children instead of just
  # returning the data).
  #
  # EVIDENCE-OF: R-13214-54017 If that entry is a leaf (meaning that it is
  # an actual R*Tree entry and not a subtree) then that entry is returned
  # as one row of the query result.
  array set N $next
  if {$N(iLevel)!=0} { error "result row mismatch (1)" }

  if {$x1!=[lindex $N(aCoord) 0] || $x2!=[lindex $N(aCoord) 1]
   || $y1!=[lindex $N(aCoord) 2] || $y2!=[lindex $N(aCoord) 3]
  } {
    if {$N(iLevel)!=0} { error "result row mismatch (2)" }
  }

  if {$id!=$N(iRowid)} { error "result row mismatch (3)" }
}

proc pq_done {} {
  global Q
  # EVIDENCE-OF: R-57438-45968 The query runs until the priority queue is
  # empty.
  if {[llength $Q(pri_queue)]>0} {
    error "priority queue is not empty!"
  }
}

proc pq_debug {caption} {
  global Q

  puts "**** $caption ****"
  set i 0
  foreach q [lsort -real -index 0 $Q(pri_queue)] { 
    puts "PQ $i: $q" 
    incr i
  }
}

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

proc box_query {a} {
  set res [list fully [expr rand()]]
  pq_test_callback $a $res
  return $res
}

register_box_query db box_query

do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE rt USING rtree_i32(id,  x1,x2,  y1,y2);
  WITH s(i) AS (
    SELECT 0 UNION ALL SELECT i+1 FROM s WHERE i<64
  )
  INSERT INTO rt SELECT NULL, a.i, a.i+1, b.i, b.i+1 FROM s a, s b;
}

proc box_query {a} {
  set res [list fully [expr rand()]]
  pq_test_callback $a $res
  return $res
}

pq_init
db eval { SELECT id, x1,x2, y1,y2 FROM rt WHERE id MATCH qbox() } {
  pq_test_result $id $x1 $x2 $y1 $y2
}
pq_done

finish_test


Added ext/rtree/rtreefuzz001.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
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2012-12-21
#
# 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.
#
#***********************************************************************
#
# Test cases for corrupt database files.

if {![info exists testdir]} {
  set testdir [file join [file dirname [info script]] .. .. test]
} 
source $testdir/tester.tcl

ifcapable !deserialize||!rtree {
  finish_test
  return
}
database_may_be_corrupt

do_test rtreefuzz001-100 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 24576 pagesize 4096 filename c1b.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 03 00 00 00 06   .....@  ........
|     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   ................
|     80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03   ................
|     96: 00 2e 30 38 0d 00 00 00 04 0e 9c 00 0f ad 0f 4f   ..08...........O
|    112: 0e fc 0e 9c 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   3728: 00 00 00 00 00 00 00 00 00 00 00 00 5e 04 07 17   ............^...
|   3744: 1f 1f 01 81 0b 74 61 62 6c 65 74 31 5f 70 61 72   .....tablet1_par
|   3760: 65 6e 74 74 31 5f 70 61 72 65 6e 74 04 43 52 45   entt1_parent.CRE
|   3776: 41 54 45 20 54 41 42 4c 45 20 22 74 31 5f 70 61   ATE TABLE .t1_pa
|   3792: 72 66 6e 74 22 28 6e 6f 64 65 6e 6f 20 49 4e 54   rfnt.(nodeno INT
|   3808: 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59   EGER PRIMARY KEY
|   3824: 2c 70 61 72 65 6e 74 6e 6f 64 65 29 51 03 06 17   ,parentnode)Q...
|   3840: 1b 1b 01 7b 74 61 62 6c 65 74 31 5f 6e 6f 64 65   ....tablet1_node
|   3856: 74 31 5f 6e 6f 64 65 03 43 52 45 41 54 45 20 54   t1_node.CREATE T
|   3872: 41 42 4c 45 20 22 74 31 5f 6e 6f 64 65 22 28 6e   ABLE .t1_node.(n
|   3888: 6f 64 65 6e 6f 20 49 4e 54 45 47 45 52 20 50 52   odeno INTEGER PR
|   3904: 49 4d 41 52 59 20 4b 45 59 2c 64 61 74 61 29 5c   IMARY KEY,data).
|   3920: 02 07 17 1d 1d 01 81 0b 74 61 62 6c 65 74 31 5f   ........tablet1_
|   3936: 72 6f 77 69 64 74 31 5f 72 6f 77 69 64 02 43 52   rowidt1_rowid.CR
|   3952: 45 41 54 45 20 54 41 42 4c 45 20 22 74 31 5f 72   EATE TABLE .t1_r
|   3968: 6f 77 69 64 22 28 72 6f 77 69 64 20 49 4e 54 45   owid.(rowid INTE
|   3984: 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c   GER PRIMARY KEY,
|   4000: 6e 6f 64 65 6e 6f 2c 61 30 2c 61 31 29 51 01 07   nodeno,a0,a1)Q..
|   4016: 17 11 11 08 81 0f 74 61 62 6c 65 74 31 74 31 43   ......tablet1t1C
|   4032: 52 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41   REATE VIRTUAL TA
|   4048: 42 4c 45 20 74 31 20 55 53 49 4e 47 20 72 74 72   BLE t1 USING rtr
|   4064: 65 65 28 69 64 2c 78 30 2c 78 31 2c 79 30 2c 79   ee(id,x0,x1,y0,y
|   4080: 31 2c 2b 6c 61 62 65 6c 2c 2b 6f 74 68 65 72 29   1,+label,+other)
| page 2 offset 4096
|      0: 0d 0c cd 00 74 08 75 01 0f e8 0c b3 0f d0 0f b7   ....t.u.........
|     16: 0f 9e 0f 91 0f 81 0f 70 0f 5e 0f 4f 0f 39 0f 29   .......p.^.O.9.)
|     32: 0f 18 0f 06 0e f7 0c 65 0e 58 0d c2 0d 2c 0c 25   .......e.X...,.%
|     48: 0b 85 0a e5 0a 45 09 a5 09 05 0c 83 0c 93 0c a3   .....E..........
|     64: 0f f0 0c 15 0b 75 0a d5 0a 35 09 95 08 f5 0e d8   .....u...5......
|     80: 0e 42 0d ac 0d 16 0c 05 0b 65 0a c5 0a 25 09 85   .B.......e...%..
|     96: 08 e5 0e c8 0e 32 0d 9c 0d 06 0b f5 0b 55 0a b5   .....2.......U..
|    112: 0a 15 09 75 08 d5 0e b8 0e 22 0d 8c 0c f6 0b e5   ...u............
|    128: 0b 45 0a a5 0a 05 09 65 08 c5 0e a8 0e 12 0d 7c   .E.....e.......|
|    144: 0c e6 0b d5 0b 35 0a 95 09 f5 09 55 08 b5 0e 98   .....5.....U....
|    160: 0e 02 0d 6c 0c d6 0b c5 0b 25 0a 85 09 e5 09 45   ...l.....%.....E
|    176: 08 a5 0e 88 0d f2 0d 5c 0c 55 0b b5 0b 15 0a 75   .........U.....u
|    192: 09 d5 09 35 08 95 0e 78 0d e2 0d 4c 0c 45 0b a5   ...5...x...L.E..
|    208: 0b 05 0a 65 09 c5 09 25 08 85 0e 68 0d d2 0d 3c   ...e...%...h...<
|    224: 0c 35 0b 95 0a f5 0a 55 09 b5 09 15 08 75 0c 75   .5.....U.....u.u
|   2160: 00 00 00 00 00 0d 8e 75 05 00 01 1b 00 04 62 6f   .......u......bo
|   2176: 78 2d 39 2c 39 0d 8e 11 05 00 01 1b 00 02 62 6f   x-9,9.........bo
|   2192: 78 2d 39 2c 38 0d 8d 2d 05 00 01 1b 00 02 62 6f   x-9,8..-......bo
|   2208: 78 2d 39 2c 37 0d 8c 49 05 00 01 1b 00 02 62 6f   x-9,7..I......bo
|   2224: 78 2d 39 2c 36 0d 8b 65 05 00 01 1b 00 02 62 6f   x-9,6..e......bo
|   2240: 78 2d 39 2c 35 0d 8b 01 05 00 01 1b 00 02 62 6f   x-9,5.........bo
|   2256: 78 2d 39 2c 34 0d 8a 1d 05 00 01 1b 00 02 62 6f   x-9,4.........bo
|   2272: 78 2d 39 2c 33 0d 89 39 05 00 01 1b 00 02 62 6f   x-9,3..9......bo
|   2288: 78 2d 39 2c 32 0d 88 55 05 00 01 1b 00 02 62 6f   x-9,2..U......bo
|   2304: 78 2d 39 2c 31 0d 87 71 05 00 01 1b 00 02 62 6f   x-9,1..q......bo
|   2320: 78 2d 39 2c 30 0d 8e 74 05 00 01 1b 00 04 62 6f   x-9,0..t......bo
|   2336: 78 2d 38 2c 39 0d 8e 10 05 00 01 1b 00 02 62 6f   x-8,9.........bo
|   2352: 78 2d 38 2c 38 0d 8d 2c 05 00 01 1b 00 02 62 6f   x-8,8..,......bo
|   2368: 78 2d 38 2c 37 0d 8c 48 05 00 01 1b 00 02 62 6f   x-8,7..H......bo
|   2384: 78 2d 38 2c 36 0d 8b 64 05 00 01 1b 00 02 62 6f   x-8,6..d......bo
|   2400: 78 2d 38 2c 35 0d 8b 00 05 00 01 1b 00 02 62 6f   x-8,5.........bo
|   2416: 78 2d 38 2c 34 0d 8a 1c 05 00 01 1b 00 02 62 6f   x-8,4.........bo
|   2432: 78 2d 38 2c 33 0d 89 38 05 00 01 1b 00 02 62 6f   x-8,3..8......bo
|   2448: 78 2d 38 2c 32 0d 88 54 05 00 01 1b 00 02 62 6f   x-8,2..T......bo
|   2464: 78 2d 38 2c 31 0d 87 70 05 00 01 1b 00 02 62 6f   x-8,1..p......bo
|   2480: 78 2d 38 2c 30 0d 8e 73 05 00 01 1b 00 05 62 6f   x-8,0..s......bo
|   2496: 78 2d 37 2c 39 0d 8e 0f 05 00 01 1b 00 05 62 6f   x-7,9.........bo
|   2512: 78 2d 37 2c 38 0d 8d 2b 05 00 01 1b 00 05 62 6f   x-7,8..+......bo
|   2528: 78 2d 37 2c 37 0d 8c 47 05 00 01 1b 00 05 62 6f   x-7,7..G......bo
|   2544: 78 2d 37 2c 36 0d 8b 63 05 00 01 1b 00 05 62 6f   x-7,6..c......bo
|   2560: 78 2d 37 2c 35 0d 8a 7f 05 00 01 1b 00 05 62 6f   x-7,5.........bo
|   2576: 78 2d 37 2c 34 0d 8a 1b 05 00 01 1b 00 05 62 6f   x-7,4.........bo
|   2592: 78 2d 37 2c 33 0d 89 37 05 00 01 1b 00 05 62 6f   x-7,3..7......bo
|   2608: 78 2d 37 2c 32 0d 88 53 05 00 01 1b 00 05 62 6f   x-7,2..S......bo
|   2624: 78 2d 37 2c 31 0d 87 6f 05 00 01 1b 00 05 62 6f   x-7,1..o......bo
|   2640: 78 2d 37 2c 30 0d 8e 72 05 00 01 1b 00 04 62 6f   x-7,0..r......bo
|   2656: 78 2d 36 2c 39 0d 8e 0e 05 00 01 1b 00 05 62 6f   x-6,9.........bo
|   2672: 78 2d 36 2c 38 0d 8d 2a 05 00 01 1b 00 05 62 6f   x-6,8..*......bo
|   2688: 78 2d 36 2c 37 0d 8c 46 05 00 01 1b 00 05 62 6f   x-6,7..F......bo
|   2704: 78 2d 36 2c 36 0d 8b 62 05 00 01 1b 00 05 62 6f   x-6,6..b......bo
|   2720: 78 2d 36 2c 35 0d 8a 7e 05 00 01 1b 00 05 62 6f   x-6,5..~......bo
|   2736: 78 2d 36 2c 34 0d 8a 1a 05 00 01 1b 00 05 62 6f   x-6,4.........bo
|   2752: 78 2d 36 2c 33 0d 89 36 05 00 01 1b 00 05 62 6f   x-6,3..6......bo
|   2768: 78 2d 36 2c 32 0d 88 52 05 00 01 1b 00 05 62 6f   x-6,2..R......bo
|   2784: 78 2d 36 2c 31 0d 87 6e 05 00 01 1b 00 05 62 6f   x-6,1..n......bo
|   2800: 78 2d 36 2c 30 0d 8e 71 05 00 01 1b 00 04 62 6f   x-6,0..q......bo
|   2816: 78 2d 35 2c 39 0d 8e 0d 05 00 01 1b 00 05 62 6f   x-5,9.........bo
|   2832: 78 2d 35 2c 38 0d 8d 29 05 00 01 1b 00 05 62 6f   x-5,8..)......bo
|   2848: 78 2d 35 2c 37 0d 8c 45 05 00 01 1b 00 05 62 6f   x-5,7..E......bo
|   2864: 78 2d 35 2c 36 0d 8b 61 05 00 01 1b 00 05 62 6f   x-5,6..a......bo
|   2880: 78 2d 35 2c 35 0d 8a 7d 05 00 01 1b 00 05 62 6f   x-5,5.........bo
|   2896: 78 2d 35 2c 34 0d 8a 19 05 00 01 1b 00 05 62 6f   x-5,4.........bo
|   2912: 78 2d 35 2c 33 0d 89 35 05 00 01 1b 00 05 62 6f   x-5,3..5......bo
|   2928: 78 2d 35 2c 32 0d 88 51 05 00 01 1b 00 05 62 6f   x-5,2..Q......bo
|   2944: 78 2d 35 2c 31 0d 87 6d 05 00 01 1b 00 05 62 6f   x-5,1..m......bo
|   2960: 78 2d 35 2c 30 0d 8e 70 05 00 01 1b 00 04 62 6f   x-5,0..p......bo
|   2976: 78 2d 34 2c 39 0d 8e 0c 05 00 01 1b 00 04 62 6f   x-4,9.........bo
|   2992: 78 2d 34 2c 38 0d 8d 28 05 00 01 1b 00 04 62 6f   x-4,8..(......bo
|   3008: 78 2d 34 2c 37 0d 8c 44 05 00 01 1b 00 04 62 6f   x-4,7..D......bo
|   3024: 78 2d 34 2c 36 0d 8b 60 05 00 01 1b 00 02 62 6f   x-4,6..`......bo
|   3040: 78 2d 34 2c 35 0d 8a 7c 05 00 01 1b 00 02 62 6f   x-4,5..|......bo
|   3056: 78 2d 34 2c 34 0d 8a 18 05 00 01 1b 00 02 62 6f   x-4,4.........bo
|   3072: 78 2d 34 2c 33 0d 89 34 05 00 01 1b 00 02 62 6f   x-4,3..4......bo
|   3088: 78 2d 34 2c 32 0d 88 50 05 00 01 1b 00 02 62 6f   x-4,2..P......bo
|   3104: 78 2d 34 2c 31 0d 87 6c 05 00 01 1b 00 02 62 6f   x-4,1..l......bo
|   3120: 78 2d 34 2c 30 0d 8e 6f 05 00 01 1b 00 04 62 6f   x-4,0..o......bo
|   3136: 78 2d 33 2c 39 0d 8e 0b 05 00 01 1b 00 04 62 6f   x-3,9.........bo
|   3152: 78 2d 33 2c 38 0d 8d 27 05 00 01 1b 00 04 62 6f   x-3,8..'......bo
|   3168: 78 2d 33 2c 37 0d 87 68 05 00 01 1b 00 03 62 6f   x-3,7..h......bo
|   3184: 78 2d 30 2c 30 06 90 d9 80 80 81 84 4c 05 00 01   x-0,0.......L...
|   3200: 00 00 03 0d 88 4c 05 00 01 1b 00 02 62 6f 78 2d   .....L......box-
|   3216: 30 2c 31 0d 88 4d 05 00 01 1b 00 02 62 6f 78 2d   0,1..M......box-
|   3232: 31 2c 31 0d 88 4e 05 00 01 1b 00 02 62 6f 78 2d   1,1..N......box-
|   3248: 32 2c 31 17 01 05 00 01 2f 00 02 6c 6f 77 65 72   2,1...../..lower
|   3264: 2d 6c 65 66 74 20 63 6f 72 6e 65 72 0d 0d 26 00   -left corner..&.
|   3280: 09 00 01 00 00 04 0d 8c 43 05 00 01 1b 00 04 62   ........C......b
|   3296: 6f 78 2d 33 2c 36 0d 8b 5f 05 00 01 1b 00 02 62   ox-3,6.._......b
|   3312: 6f 78 2d 33 2c 35 0d 8a 7b 05 00 01 1b 00 02 62   ox-3,5.........b
|   3328: 6f 78 2d 33 2c 34 0d 8a 17 05 00 01 1b 00 02 62   ox-3,4.........b
|   3344: 6f 78 2d 33 2c 33 0d 89 33 05 00 01 1b 00 02 62   ox-3,3..3......b
|   3360: 6f 78 2d 33 2c 32 0d bc 00 06 00 09 0d 87 6b 05   ox-3,2........k.
|   3376: 00 01 1b 00 03 62 6f 78 2d 33 2c 30 0d 8e 6e 05   .....box-3,0..n.
|   3392: 00 01 1b 00 04 62 6f 78 2d 32 2c 39 0d 8e 0a 05   .....box-2,9....
|   3408: 00 01 1b 00 04 62 6f 78 2d 32 2c 38 0d 8d 26 05   .....box-2,8..&.
|   3424: 00 01 1b 00 04 62 6f 78 2d 32 2c 37 0d 8c 42 05   .....box-2,7..B.
|   3440: 00 01 1b 00 04 62 6f 78 2d 32 2c 36 0d 8b 5e 05   .....box-2,6..^.
|   3456: 00 01 1b 00 02 62 6f 78 2d 32 2c 35 0d 8a 7a 05   .....box-2,5..z.
|   3472: 00 01 1b 00 02 62 6f 78 2d 32 2c 34 0d 8a 16 05   .....box-2,4....
|   3488: 00 01 1b 00 02 62 6f 78 2d 32 2c 33 0d 89 32 05   .....box-2,3..2.
|   3504: 00 01 1b 00 02 62 6f 78 2d 32 2c 32 0e 52 00 06   .....box-2,2.R..
|   3520: 00 09 0d 87 6a 05 00 01 1b 00 03 62 6f 78 2d 32   ....j......box-2
|   3536: 2c 30 0d 8e 6d 05 00 01 1b 00 04 62 6f 78 2d 31   ,0..m......box-1
|   3552: 2c 39 0d 8e 09 05 00 01 1b 00 04 62 6f 78 2d 31   ,9.........box-1
|   3568: 2c 38 0d 8d 25 05 00 01 1b 00 04 62 6f 78 2d 31   ,8..%......box-1
|   3584: 2c 37 0d 8c 41 05 00 01 1b 00 04 62 6f 78 2d 31   ,7..A......box-1
|   3600: 2c 36 0d 8b 5d 05 00 01 1b 00 02 62 6f 78 2d 31   ,6..]......box-1
|   3616: 2c 35 0d 8a 79 05 00 01 1b 00 02 62 6f 78 2d 31   ,5..y......box-1
|   3632: 2c 34 0d 8a 15 05 00 01 1b 00 02 62 6f 78 2d 31   ,4.........box-1
|   3648: 2c 33 0d 89 31 05 00 01 1b 00 02 62 6f 78 2d 31   ,3..1......box-1
|   3664: 2c 32 0e e8 00 06 00 09 0d 87 69 05 00 01 1b 00   ,2........i.....
|   3680: 03 62 6f 78 2d 31 2c 30 0d 8e 6c 05 00 01 1b 00   .box-1,0..l.....
|   3696: 04 62 6f 78 2d 30 2c 39 0d 8e 08 05 00 01 1b 00   .box-0,9........
|   3712: 04 62 6f 78 2d 30 2c 38 0d 8d 24 05 00 01 1b 00   .box-0,8..$.....
|   3728: 04 62 6f 78 2d 30 2c 37 0d 8c 40 05 00 01 1b 00   .box-0,7..@.....
|   3744: 04 62 6f 78 2d 30 2c 36 0d 8b 5c 05 00 01 1b 00   .box-0,6........
|   3760: 02 62 6f 78 2d 30 2c 35 0d 8a 78 05 00 01 1b 00   .box-0,5..x.....
|   3776: 02 62 6f 78 2d 30 2c 34 0d 8a 14 05 00 01 1b 00   .box-0,4........
|   3792: 02 62 6f 78 2d 30 2c 33 0d 89 30 05 00 01 1b 00   .box-0,3..0.....
|   3808: 02 62 6f 78 2d 30 2c 32 00 00 00 0f 00 09 1b 00   .box-0,2........
|   3824: 62 6f 78 2d 30 2c 30 0d 0e 05 00 09 1d 00 74 6f   box-0,0.......to
|   3840: 70 20 68 61 6c 66 10 0d 05 00 09 23 00 62 6f 74   p half.....#.bot
|   3856: 74 6f 6d 20 68 61 6c 66 0f 0c 02 05 09 01 00 72   tom half.......r
|   3872: 69 67 68 74 20 68 61 6c 66 0e 0b 05 00 09 1f 00   ight half.......
|   3888: 6c 65 66 74 20 68 61 6c 66 14 0a 05 00 09 2b 00   left half.....+.
|   3904: 74 68 65 20 77 68 6f 6c 65 20 74 68 69 6e 67 0d   the whole thing.
|   3920: 09 05 00 09 1d 00 74 6f 70 20 65 64 67 65 10 08   ......top edge..
|   3936: 05 00 09 23 00 62 6f 74 74 6f 6d 20 65 64 67 65   ...#.bottom edge
|   3952: 0f 07 05 00 09 21 00 72 69 67 68 74 20 65 64 67   .....!.right edg
|   3968: 65 0e 06 05 00 09 1f 00 6c 65 66 74 20 65 64 67   e.......left edg
|   3984: 65 0b 05 05 00 09 19 00 63 65 6e 74 65 72 17 04   e.......center..
|   4000: 05 00 09 31 00 75 70 70 65 72 2d 72 69 67 68 74   ...1.upper-right
|   4016: 20 63 6f 72 6e 65 72 17 03 05 00 09 31 00 6c 6f    corner.....1.lo
|   4032: 77 65 72 2d 72 69 67 68 74 20 63 6f 72 6e 65 72   wer-right corner
|   4048: 16 02 05 00 09 2f 00 75 70 70 65 72 2d 6c 65 66   ...../.upper-lef
|   4064: 74 20 63 6f 72 6e 65 72 06 00 05 00 01 00 00 03   t corner........
|   4080: 0d 88 4f 05 00 01 1b 00 02 62 6f 78 2d 33 2c 31   ..O......box-3,1
| page 3 offset 8192
|      0: 05 00 00 00 01 0f fb 00 00 00 00 06 0f fb 00 00   ................
|    384: 00 00 00 00 00 00 00 89 50 03 04 00 93 24 00 00   ........P....$..
|    400: 00 11 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|    688: 00 00 00 00 42 c8 00 00 42 4c 00 00 42 00 00 00   ....B...BL..B...
|    720: 03 eb 40 40 00 00 40 80 00 00 00 00 00 00 3f 80   ..@@..@.......?.
|    736: 00 00 00 00 00 00 00 00 03 ea 40 00 00 00 40 40   ..........@...@@
|    752: 00 00 00 00 00 00 3f 80 00 00 00 00 00 00 00 00   ......?.........
|    768: 03 e9 3f 80 00 00 40 00 00 00 00 00 00 00 3f 80   ..?...@.......?.
|    784: 00 00 00 00 00 00 00 00 03 e8 00 00 00 00 3f 80   ..............?.
|    800: 00 00 00 00 00 00 3f 80 00 00 00 00 00 00 00 00   ......?.........
|   1616: 00 00 00 00 00 00 00 00 00 00 89 50 02 04 00 93   ...........P....
|   1632: 24 00 00 00 33 00 00 00 00 00 00 00 01 00 00 00   $...3...........
|   1648: 00 41 20 00 00 00 00 00 00 41 0e 00 00 00 00 00   .A ......A......
|   1664: 00 00 00 04 4f 40 40 00 00 40 80 00 00 3f 80 00   ....O@@..@...?..
|   1680: 00 40 00 00 00 00 00 00 00 00 00 04 4e 40 00 00   .@..........N@..
|   1696: 00 40 40 00 00 3f 80 00 00 40 00 00 00 00 00 00   .@@..?...@......
|   1712: 00 00 00 04 4d 3f 80 00 00 40 00 00 00 3f 80 00   ....M?...@...?..
|   1728: 00 40 00 00 00 00 00 00 00 00 00 04 4c 00 00 00   .@..........L...
|   1744: 00 3f 80 00 00 3f 80 00 00 40 00 00 00 00 00 00   .?...?...@......
|   1760: 00 00 00 04 b3 40 40 00 00 40 80 00 00 40 00 00   .....@@..@...@..
|   1776: 00 40 40 00 00 00 00 00 00 00 00 04 b2 40 00 00   .@@..........@..
|   1792: 00 40 40 00 00 40 00 00 00 40 40 00 00 00 00 00   .@@..@...@@.....
|   1808: 00 00 00 04 b1 3f 80 00 00 40 00 00 00 40 00 00   .....?...@...@..
|   1824: 00 40 40 00 00 00 00 00 00 00 00 04 b0 00 00 00   .@@.............
|   1840: 00 3f 80 00 00 40 00 00 00 40 40 00 00 00 00 00   .?...@...@@.....
|   1856: 00 00 00 05 17 40 40 00 00 40 80 00 00 40 40 00   .....@@..@...@@.
|   1872: 00 40 80 00 00 00 00 00 00 00 00 05 16 40 00 00   .@...........@..
|   1888: 00 40 40 00 00 40 40 00 00 40 80 00 00 00 00 00   .@@..@@..@......
|   1904: 00 00 00 05 15 3f 80 00 00 40 00 00 00 40 40 00   .....?...@...@@.
|   1920: 00 40 80 00 00 00 00 00 00 00 00 05 14 00 00 00   .@..............
|   1936: 00 3f 80 00 00 40 40 00 00 40 80 00 00 00 00 00   .?...@@..@......
|   1952: 00 00 00 05 7b 40 40 00 00 40 80 00 00 40 80 00   .....@@..@...@..
|   1968: 00 40 a0 00 00 00 00 00 00 00 00 05 7a 40 00 00   .@..........z@..
|   1984: 00 40 40 00 00 40 80 00 00 40 a0 00 00 00 00 00   .@@..@...@......
|   2000: 00 00 00 05 79 3f 80 00 00 40 00 00 00 40 80 00   ....y?...@...@..
|   2016: 00 40 a0 00 00 00 00 00 00 00 00 05 78 00 00 00   .@..........x...
|   2032: 00 3f 80 00 00 40 80 00 00 40 a0 00 00 00 00 00   .?...@...@......
|   2048: 00 00 00 05 df 40 40 00 00 40 80 00 00 40 a0 00   .....@@..@...@..
|   2064: 00 40 c0 00 00 00 00 00 00 00 00 05 de 40 00 00   .@...........@..
|   2080: 00 40 40 00 00 40 a0 00 00 40 c0 00 00 00 00 00   .@@..@...@......
|   2096: 00 00 00 05 dd 3f 80 00 00 40 00 00 00 40 a0 00   .....?...@...@..
|   2112: 00 40 c0 00 00 00 00 00 00 00 00 05 dc 00 00 00   .@..............
|   2128: 00 3f 80 00 00 40 a0 00 00 40 c0 00 00 00 00 00   .?...@...@......
|   2144: 00 00 00 06 43 40 40 00 00 40 80 00 00 40 c0 00   ....C@@..@...@..
|   2160: 00 40 e0 00 00 00 00 00 00 00 00 06 42 40 00 00   .@..........B@..
|   2176: 00 40 40 00 00 40 c0 00 00 40 e0 00 00 00 00 00   .@@..@...@......
|   2192: 00 00 00 06 41 3f 80 00 00 40 00 00 00 40 c0 00   ....A?...@...@..
|   2208: 00 40 e0 00 00 00 00 00 00 00 00 06 40 00 00 00   .@..........@...
|   2224: 00 3f 80 00 00 40 c0 00 00 40 e0 00 00 00 00 00   .?...@...@......
|   2240: 00 00 00 06 a7 40 40 00 00 40 80 00 00 40 e0 00   .....@@..@...@..
|   2256: 00 41 00 00 00 00 00 00 00 00 00 06 a6 40 00 00   .A...........@..
|   2272: 00 40 40 00 00 40 e0 00 00 41 00 00 00 00 00 00   .@@..@...A......
|   2288: 00 00 00 06 a5 3f 80 00 00 40 00 00 00 40 e0 00   .....?...@...@..
|   2304: 00 41 00 00 00 00 00 00 00 00 00 06 a4 00 00 00   .A..............
|   2320: 00 3f 80 00 00 40 e0 00 00 41 00 00 00 00 00 00   .?...@...A......
|   2336: 00 00 00 07 0a 40 00 00 00 40 40 00 00 41 00 00   .....@...@@..A..
|   2352: 00 41 10 00 00 00 00 00 00 00 00 07 09 3f 80 00   .A...........?..
|   2368: 00 40 00 00 00 41 00 00 00 41 10 00 00 00 00 00   .@...A...A......
|   2384: 00 00 00 07 08 00 00 00 00 3f 80 00 00 41 00 00   .........?...A..
|   2400: 00 41 10 00 00 00 00 00 00 00 00 07 6e 40 00 00   .A..........n@..
|   2416: 00 40 40 00 00 41 10 00 00 41 20 00 00 00 00 00   .@@..A...A .....
|   2432: 00 00 00 07 6d 3f 80 00 00 40 00 00 00 41 10 00   ....m?...@...A..
|   2448: 00 41 20 00 00 00 00 00 00 00 00 07 6c 00 00 00   .A .........l...
|   2464: 00 3f 80 00 00 41 10 00 00 41 20 00 00 00 00 00   .?...A...A .....
|   2480: 00 00 00 07 0b 40 40 00 00 40 80 00 00 41 00 00   .....@@..@...A..
|   2496: 00 41 10 00 00 00 00 00 00 00 00 07 6f 40 40 00   .A..........o@@.
|   2512: 00 40 80 00 00 41 10 00 00 41 20 00 00 00 00 00   .@...A...A .....
|   2528: 00 00 00 03 ec 40 80 00 00 40 a0 00 00 00 00 00   .....@...@......
|   2544: 00 3f 80 00 00 00 00 00 00 00 00 04 50 40 80 00   .?..........P@..
|   2560: 00 40 a0 00 00 3f 80 00 00 40 00 00 00 00 00 00   .@...?...@......
|   2576: 00 00 00 04 b4 40 80 00 00 40 a0 00 00 40 00 00   .....@...@...@..
|   2592: 00 40 40 00 00 00 00 00 00 00 00 05 18 40 80 00   .@@..........@..
|   2608: 00 40 a0 00 00 40 40 00 00 40 80 00 00 00 00 00   .@...@@..@......
|   2624: 00 00 00 05 7c 40 80 00 00 40 a0 00 00 40 80 00   ....|@...@...@..
|   2640: 00 40 a0 00 00 00 00 00 00 00 00 05 e0 40 80 00   .@...........@..
|   2656: 00 40 a0 00 00 40 a0 00 00 40 c0 00 00 00 00 00   .@...@...@......
|   2672: 00 00 00 06 44 40 80 00 00 40 a0 00 00 40 c0 00   ....D@...@...@..
|   2688: 00 40 e0 00 00 00 00 00 00 00 00 06 a8 40 80 00   .@...........@..
|   2704: 00 40 a0 00 00 40 e0 00 00 41 00 00 00 00 00 00   .@...@...A......
|   2720: 00 00 00 07 0c 40 80 00 00 40 a0 00 00 41 00 00   .....@...@...A..
|   2736: 00 41 10 00 00 00 00 00 00 00 00 07 70 40 80 00   .A..........p@..
|   2752: 00 40 a0 00 00 41 10 00 00 41 20 00 00 00 00 00   .@...A...A .....
|   2768: 00 00 00 03 ed 40 a0 00 00 40 c0 00 00 00 00 00   .....@...@......
|   2784: 00 3f 80 00 00 00 00 00 00 00 00 04 51 40 a0 00   .?..........Q@..
|   2800: 00 40 c0 00 00 3f 80 00 00 40 00 00 00 00 00 00   .@...?...@......
|   2816: 00 00 00 04 b5 40 a0 00 00 40 c0 00 00 40 00 00   .....@...@...@..
|   2832: 00 40 40 00 00 00 00 00 00 00 00 05 19 40 a0 00   .@@..........@..
|   2848: 00 40 c0 00 00 40 40 00 00 40 80 00 00 89 50 01   .@...@@..@....P.
|   2864: 04 00 93 24 00 01 00 02 00 00 00 00 00 00 00 03   ...$............
|   2880: 00 00 00 00 40 80 00 00 00 00 00 00 3f 80 00 00   ....@.......?...
|   2896: 00 00 00 00 00 00 00 02 00 00 00 00 41 20 00 00   ............A ..
|   2912: 00 00 00 00 41 20 00 00 00 00 00 00 00 00 00 00   ....A ..........
|   4080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 03   ................
| 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 03 01 87 00 0b 2d 06 5a 01 87 00 00   .........-.Z....
|    384: 00 00 00 00 00 00 00 89 50 03 04 00 93 24 00 00   ........P....$..
|    400: 00 11 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|    688: 00 00 00 00 42 c8 00 00 42 4c 00 00 42 00 00 00   ....B...BL..B...
|    720: 03 eb 40 40 00 00 40 80 00 00 00 00 00 00 3f 80   ..@@..@.......?.
|    736: 00 00 00 00 00 00 00 00 03 ea 40 00 00 00 40 40   ..........@...@@
|    752: 00 00 00 00 00 00 3f 80 00 00 00 00 00 00 00 00   ......?.........
|    768: 03 e9 3f 80 00 00 40 00 00 00 00 00 00 00 3f 80   ..?...@.......?.
|    784: 00 00 00 00 00 00 00 00 03 e8 00 00 00 00 3f 80   ..............?.
|    800: 00 00 00 00 00 00 3f 80 00 00 00 00 00 00 00 00   ......?.........
|   1616: 00 00 00 00 00 00 00 00 00 00 89 50 02 04 00 93   ...........P....
|   1632: 24 00 00 00 2d 00 00 00 00 00 00 04 4c 00 00 00   $...-.......L...
|   1648: 00 3f 80 00 00 3f 80 00 00 40 00 00 00 00 00 00   .?...?...@......
|   1664: 00 00 00 04 b0 00 00 00 00 3f 80 00 00 40 00 00   .........?...@..
|   1680: 00 40 40 00 00 00 00 00 00 00 00 05 14 00 00 00   .@@.............
|   1696: 00 3f 80 00 00 40 40 00 00 40 80 00 00 00 00 00   .?...@@..@......
|   1712: 00 00 00 05 78 00 00 00 00 3f 80 00 00 40 80 00   ....x....?...@..
|   1728: 00 40 a0 00 00 00 00 00 00 00 00 05 dc 00 00 00   .@..............
|   1744: 00 3f 80 00 00 40 a0 00 00 40 c0 00 00 00 00 00   .?...@...@......
|   1760: 00 00 00 00 01 00 00 00 00 41 20 00 00 00 00 00   .........A .....
|   1776: 00 41 0e 00 00 00 00 00 00 00 00 04 4d 3f 80 00   .A..........M?..
|   1792: 00 40 00 00 00 3f 80 00 00 40 00 00 00 00 00 00   .@...?...@......
|   1808: 00 00 00 04 b1 3f 80 00 00 40 00 00 00 40 00 00   .....?...@...@..
|   1824: 00 40 40 00 00 00 00 00 00 00 00 05 15 3f 80 00   .@@..........?..
|   1840: 00 40 00 00 00 40 40 00 00 40 80 00 00 00 00 00   .@...@@..@......
|   1856: 00 00 00 05 79 3f 80 00 00 40 00 00 00 40 80 00   ....y?...@...@..
|   1872: 00 40 a0 00 00 00 00 00 00 00 00 05 dd 3f 80 00   .@...........?..
|   1888: 00 40 00 00 00 40 a0 00 00 40 c0 00 00 00 00 00   .@...@...@......
|   1904: 00 00 00 04 4e 40 00 00 00 40 40 00 00 3f 80 00   ....N@...@@..?..
|   1920: 00 40 00 00 00 00 00 00 00 00 00 04 b2 40 00 00   .@...........@..
|   1936: 00 40 40 00 00 40 00 00 00 40 40 00 00 00 00 00   .@@..@...@@.....
|   1952: 00 00 00 05 16 40 00 00 00 40 40 00 00 40 40 00   .....@...@@..@@.
|   1968: 00 40 80 00 00 00 00 00 00 00 00 05 7a 40 00 00   .@..........z@..
|   1984: 00 40 40 00 00 40 80 00 00 40 a0 00 00 00 00 00   .@@..@...@......
|   2000: 00 00 00 05 de 40 00 00 00 40 40 00 00 40 a0 00   .....@...@@..@..
|   2016: 00 40 c0 00 00 00 00 00 00 00 00 04 4f 40 40 00   .@..........O@@.
|   2032: 00 40 80 00 00 3f 80 00 00 40 00 00 00 00 00 00   .@...?...@......
|   2048: 00 00 00 04 b3 40 40 00 00 40 80 00 00 40 00 00   .....@@..@...@..
|   2064: 00 40 40 00 00 00 00 00 00 00 00 05 17 40 40 00   .@@..........@@.
|   2080: 00 40 80 00 00 40 40 00 00 40 80 00 00 00 00 00   .@...@@..@......
|   2096: 00 00 00 05 7b 40 40 00 00 40 80 00 00 40 80 00   .....@@..@...@..
|   2112: 00 40 a0 00 00 00 00 00 00 00 00 05 df 40 40 00   .@...........@@.
|   2128: 00 40 80 00 00 40 a0 00 00 40 c0 00 00 00 00 00   .@...@...@......
|   2144: 00 00 00 03 ec 40 80 00 00 40 a0 00 00 00 00 00   .....@...@......
|   2160: 00 3f 80 00 00 00 00 00 00 00 00 04 50 40 80 00   .?..........P@..
|   2176: 00 40 a0 00 00 3f 80 00 00 40 00 00 00 00 00 00   .@...?...@......
|   2192: 00 00 00 04 b4 40 80 00 00 40 a0 00 00 40 00 00   .....@...@...@..
|   2208: 00 40 40 00 00 00 00 00 00 00 00 05 18 40 80 00   .@@..........@..
|   2224: 00 40 a0 00 00 40 40 00 00 40 80 00 00 00 00 00   .@...@@..@......
|   2240: 00 00 00 05 7c 40 80 00 00 40 a0 00 00 40 80 00   ....|@...@...@..
|   2256: 00 40 a0 00 00 00 00 00 00 00 00 05 e0 40 80 00   .@...........@..
|   2272: 00 40 a0 00 00 40 a0 00 00 40 c0 00 00 00 00 00   .@...@...@......
|   2288: 00 00 00 03 f0 41 00 00 00 41 10 00 00 00 00 00   .....A...A......
|   2304: 00 3f 80 00 00 00 00 00 00 00 00 04 54 41 00 00   .?..........TA..
|   2320: 00 41 10 00 00 3f 80 00 00 40 00 00 00 00 00 00   .A...?...@......
|   2336: 00 00 00 04 b8 41 00 00 00 41 10 00 00 40 00 00   .....A...A...@..
|   2352: 00 40 40 00 00 00 00 00 00 00 00 05 1c 41 00 00   .@@..........A..
|   2368: 00 41 10 00 00 40 40 00 00 40 80 00 00 00 00 00   .A...@@..@......
|   2384: 00 00 00 05 80 41 00 00 00 41 10 00 00 40 80 00   .....A...A...@..
|   2400: 00 40 a0 00 00 00 00 00 00 00 00 05 e4 41 00 00   .@...........A..
|   2416: 00 41 10 00 00 40 a0 00 00 40 c0 00 00 00 00 00   .A...@...@......
|   2432: 00 00 00 06 48 41 00 00 00 41 10 00 00 40 c0 00   ....HA...A...@..
|   2448: 00 40 e0 00 00 00 00 00 00 00 00 06 ac 41 00 00   .@...........A..
|   2464: 00 41 10 00 00 40 e0 00 00 41 00 00 00 00 00 00   .A...@...A......
|   2480: 00 00 00 07 10 41 00 00 00 41 10 00 00 41 00 00   .....A...A...A..
|   2496: 00 41 10 00 00 00 00 00 00 00 00 03 f1 41 10 00   .A...........A..
|   2512: 00 41 20 00 00 00 00 00 00 3f 80 00 00 00 00 00   .A ......?......
|   2528: 00 00 00 04 55 41 10 00 00 41 20 00 00 3f 80 00   ....UA...A ..?..
|   2544: 00 40 00 00 00 00 00 00 00 00 00 04 b9 41 10 00   .@...........A..
|   2560: 00 41 20 00 00 40 00 00 00 40 40 00 00 00 00 00   .A ..@...@@.....
|   2576: 00 00 00 05 1d 41 10 00 00 41 20 00 00 40 40 00   .....A...A ..@@.
|   2592: 00 40 80 00 00 00 00 00 00 00 00 05 81 41 10 00   .@...........A..
|   2608: 00 41 20 00 00 40 80 00 00 40 a0 00 00 00 00 00   .A ..@...@......
|   2624: 00 00 00 05 e5 41 10 00 00 41 20 00 00 40 a0 00   .....A...A ..@..
|   2640: 00 40 c0 00 00 00 00 00 00 00 00 06 49 41 10 00   .@..........IA..
|   2656: 00 41 20 00 00 40 c0 00 00 40 e0 00 00 00 00 00   .A ..@...@......
|   2672: 00 00 00 06 ad 41 10 00 00 41 20 00 00 40 e0 00   .....A...A ..@..
|   2688: 00 41 00 00 00 00 00 00 00 00 00 07 11 41 10 00   .A...........A..
|   2704: 00 41 20 00 00 41 00 00 00 41 10 00 00 00 00 00   .A ..A...A......
|   2848: 00 00 00 00 00 00 00 00 00 00 00 00 00 89 50 01   ..............P.
|   2864: 04 00 93 24 00 01 00 04 00 00 00 00 00 00 00 03   ...$............
|   2880: 00 00 00 00 40 80 00 00 00 00 00 00 3f 80 00 00   ....@.......?...
|   2896: 00 00 00 00 00 00 00 02 00 00 00 00 41 20 00 00   ............A ..
|   2912: 00 00 00 00 41 10 00 00 00 00 00 00 00 00 00 04   ....A...........
|   2928: 00 00 00 00 41 20 00 00 40 c0 00 00 41 20 00 00   ....A ..@...A ..
|   2944: 00 00 00 00 00 00 00 05 40 a0 00 00 41 00 00 00   ........@...A...
|   2960: 00 00 00 00 41 20 00 00 00 00 00 00 00 00 00 00   ....A ..........
| page 6 offset 20480
|      0: 0d 00 00 00 02 06 5a 00 0b 2d 06 5a 00 00 00 00   ......Z..-.Z....
|   1616: 00 00 00 00 00 00 00 00 00 00 89 50 05 04 00 93   ...........P....
|   1632: 24 00 00 00 1c 00 00 00 00 00 00 03 ed 40 a0 00   $............@..
|   1648: 00 40 c0 00 00 00 00 00 00 3f 80 00 00 00 00 00   .@.......?......
|   1664: 00 00 00 04 51 40 a0 00 00 40 c0 00 00 3f 80 00   ....Q@...@...?..
|   1680: 00 40 00 00 00 00 00 00 00 00 00 04 b5 40 a0 00   .@...........@..
|   1696: 00 40 c0 00 00 40 00 00 00 40 40 00 00 00 00 00   .@...@...@@.....
|   1712: 00 00 00 05 19 40 a0 00 00 40 c0 00 00 40 40 00   .....@...@...@@.
|   1728: 00 40 80 00 00 00 00 00 00 00 00 05 7d 40 a0 00   .@...........@..
|   1744: 00 40 c0 00 00 40 80 00 00 40 a0 00 00 00 00 00   .@...@...@......
|   1760: 00 00 00 05 e1 40 a0 00 00 40 c0 00 00 40 a0 00   .....@...@...@..
|   1776: 00 40 c0 00 00 00 00 00 00 00 00 06 45 40 a0 00   .@..........E@..
|   1792: 00 40 c0 00 00 40 c0 00 00 40 e0 00 00 00 00 00   .@...@...@......
|   1808: 00 00 00 06 a9 40 a0 00 00 40 c0 00 00 40 e0 00   .....@...@...@..
|   1824: 00 41 00 00 00 00 00 00 00 00 00 07 0d 40 a0 00   .A...........@..
|   1840: 00 40 c0 00 00 41 00 00 00 41 10 00 00 00 00 00   .@...A...A......
|   1856: 00 00 00 03 ee 40 c0 00 00 40 e0 00 00 00 00 00   .....@...@......
|   1872: 00 3f 80 00 00 00 00 00 00 00 00 04 52 40 c0 00   .?..........R@..
|   1888: 00 40 e0 00 00 3f 80 00 00 40 00 00 00 00 00 00   .@...?...@......
|   1904: 00 00 00 04 b6 40 c0 00 00 40 e0 00 00 40 00 00   .....@...@...@..
|   1920: 00 40 40 00 00 00 00 00 00 00 00 05 1a 40 c0 00   .@@..........@..
|   1936: 00 40 e0 00 00 40 40 00 00 40 80 00 00 00 00 00   .@...@@..@......
|   1952: 00 00 00 05 7e 40 c0 00 00 40 e0 00 00 40 80 00   ....~@...@...@..
|   1968: 00 40 a0 00 00 00 00 00 00 00 00 05 e2 40 c0 00   .@...........@..
|   1984: 00 40 e0 00 00 40 a0 00 00 40 c0 00 00 00 00 00   .@...@...@......
|   2000: 00 00 00 06 46 40 c0 00 00 40 e0 00 00 40 c0 00   ....F@...@...@..
|   2016: 00 40 e0 00 00 00 00 00 00 00 00 06 aa 40 c0 00   .@...........@..
|   2032: 00 40 e0 00 00 40 e0 00 00 41 00 00 00 00 00 00   .@...@...A......
|   2048: 00 00 00 07 0e 40 c0 00 00 40 e0 00 00 41 00 00   .....@...@...A..
|   2064: 00 41 10 00 00 00 00 00 00 00 00 03 ef 40 e0 00   .A...........@..
|   2080: 00 41 00 00 00 00 00 00 00 3f 80 00 00 00 00 00   .A.......?......
|   2096: 00 00 00 04 53 40 e0 00 00 41 00 00 00 3f 80 00   ....S@...A...?..
|   2112: 00 40 00 00 00 00 00 00 00 00 00 04 b7 40 e0 00   .@...........@..
|   2128: 00 41 00 00 00 40 00 00 00 40 40 00 00 00 00 00   .A...@...@@.....
|   2144: 00 00 00 05 1b 40 e0 00 00 41 00 00 00 40 40 00   .....@...A...@@.
|   2160: 00 40 80 00 00 00 00 00 00 00 00 05 7f 40 e0 00   .@...........@..
|   2176: 00 41 00 00 00 40 80 00 00 40 a0 00 00 00 00 00   .A...@...@......
|   2192: 00 00 00 05 e3 40 e0 00 00 41 00 00 00 40 a0 00   .....@...A...@..
|   2208: 00 40 c0 00 00 00 00 00 00 00 00 06 47 40 e0 00   .@..........G@..
|   2224: 00 41 00 00 00 40 c0 00 00 40 e0 00 00 00 00 00   .A...@...@......
|   2240: 00 00 00 06 ab 40 e0 00 00 41 00 00 00 40 e0 00   .....@...A...@..
|   2256: 00 41 00 00 00 00 00 00 00 00 00 07 0f 40 e0 00   .A...........@..
|   2272: 00 41 00 00 00 41 00 00 00 41 10 00 00 00 00 00   .A...A...A......
|   2288: 00 00 00 07 73 40 e0 00 00 41 00 00 00 41 10 00   ....s@...A...A..
|   2304: 00 41 20 00 00 00 00 00 00 00 00 00 00 00 00 00   .A .............
|   2848: 00 00 00 00 00 00 00 00 00 00 00 00 00 89 50 04   ..............P.
|   2864: 04 00 93 24 00 00 00 18 00 00 00 00 00 00 06 43   ...$...........C
|   2880: 40 40 00 00 40 80 00 00 40 c0 00 00 40 e0 00 00   @@..@...@...@...
|   2896: 00 00 00 00 00 00 06 42 40 00 00 00 40 40 00 00   .......B@...@@..
|   2912: 40 c0 00 00 40 e0 00 00 00 00 00 00 00 00 06 41   @...@..........A
|   2928: 3f 80 00 00 40 00 00 00 40 c0 00 00 40 e0 00 00   ?...@...@...@...
|   2944: 00 00 00 00 00 00 06 40 00 00 00 00 3f 80 00 00   .......@....?...
|   2960: 40 c0 00 00 40 e0 00 00 00 00 00 00 00 00 06 44   @...@..........D
|   2976: 40 80 00 00 40 a0 00 00 40 c0 00 00 40 e0 00 00   @...@...@...@...
|   2992: 00 00 00 00 00 00 06 a7 40 40 00 00 40 80 00 00   ........@@..@...
|   3008: 40 e0 00 00 41 00 00 00 00 00 00 00 00 00 06 a6   @...A...........
|   3024: 40 00 00 00 40 40 00 00 40 e0 00 00 41 00 00 00   @...@@..@...A...
|   3040: 00 00 00 00 00 00 06 a5 3f 80 00 00 40 00 00 00   ........?...@...
|   3056: 40 e0 00 00 41 00 00 00 00 00 00 00 00 00 06 a4   @...A...........
|   3072: 00 00 00 00 3f 80 00 00 40 e0 00 00 41 00 00 00   ....?...@...A...
|   3088: 00 00 00 00 00 00 06 a8 40 80 00 00 40 a0 00 00   ........@...@...
|   3104: 40 e0 00 00 41 00 00 00 00 00 00 00 00 00 07 0a   @...A...........
|   3120: 40 00 00 00 40 40 00 00 41 00 00 00 41 10 00 00   @...@@..A...A...
|   3136: 00 00 00 00 00 00 07 09 3f 80 00 00 40 00 00 00   ........?...@...
|   3152: 41 00 00 00 41 10 00 00 00 00 00 00 00 00 07 08   A...A...........
|   3168: 00 00 00 00 3f 80 00 00 41 00 00 00 41 10 00 00   ....?...A...A...
|   3184: 00 00 00 00 00 00 07 0b 40 40 00 00 40 80 00 00   ........@@..@...
|   3200: 41 00 00 00 41 10 00 00 00 00 00 00 00 00 07 0c   A...A...........
|   3216: 40 80 00 00 40 a0 00 00 41 00 00 00 41 10 00 00   @...@...A...A...
|   3232: 00 00 00 00 00 00 07 6e 40 00 00 00 40 40 00 00   .......n@...@@..
|   3248: 41 10 00 00 41 20 00 00 00 00 00 00 00 00 07 6d   A...A .........m
|   3264: 3f 80 00 00 40 00 00 00 41 10 00 00 41 20 00 00   ?...@...A...A ..
|   3280: 00 00 00 00 00 00 07 6c 00 00 00 00 3f 80 00 00   .......l....?...
|   3296: 41 10 00 00 41 20 00 00 00 00 00 00 00 00 07 6f   A...A .........o
|   3312: 40 40 00 00 40 80 00 00 41 10 00 00 41 20 00 00   @@..@...A...A ..
|   3328: 00 00 00 00 00 00 07 70 40 80 00 00 40 a0 00 00   .......p@...@...
|   3344: 41 10 00 00 41 20 00 00 00 00 00 00 00 00 07 71   A...A .........q
|   3360: 40 a0 00 00 40 c0 00 00 41 10 00 00 41 20 00 00   @...@...A...A ..
|   3376: 00 00 00 00 00 00 07 72 40 c0 00 00 40 e0 00 00   .......r@...@...
|   3392: 41 10 00 00 41 20 00 00 00 00 00 00 00 00 07 74   A...A .........t
|   3408: 41 00 00 00 41 10 00 00 41 10 00 00 41 20 00 00   A...A...A...A ..
|   3424: 00 00 00 00 00 00 07 75 41 10 00 00 41 20 00 00   .......uA...A ..
|   3440: 41 10 00 00 41 20 00 00 00 00 00 00 00 00 00 00   A...A ..........
| end c1b.db
  }]
  catchsql {
     PRAGMA writable_schema = 1;
     SELECT rtreecheck('t1');
  }
} {1 {SQL logic error}}

do_test rtreefuzz001-200 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 16384 pagesize 4096 filename c3.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 01 00 00 00 00 00 00 04 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 00 00 00 04 0e 9c 00 0f ad 0f 4f   ...............O
|    112: 0e fc 0e 9c 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   3728: 00 00 00 00 00 00 00 00 00 00 00 00 5e 04 07 17   ............^...
|   3744: 1f 1f 01 81 0b 74 61 62 6c 65 74 31 5f 70 61 72   .....tablet1_par
|   3760: 65 6e 74 74 31 5f 70 61 72 65 6e 74 04 43 52 45   entt1_parent.CRE
|   3776: 41 54 45 20 54 41 42 4c 45 20 22 74 31 5f 70 61   ATE TABLE .t1_pa
|   3792: 72 65 6e 74 22 28 6e 6f 64 65 6e 6f 20 49 4e 54   rent.(nodeno INT
|   3808: 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59   EGER PRIMARY KEY
|   3824: 2c 70 61 72 65 6e 74 6e 6f 64 65 29 51 03 06 17   ,parentnode)Q...
|   3840: 1b 1b 01 7b 74 61 62 6c 65 74 31 5f 6e 6f 64 65   ....tablet1_node
|   3856: 74 31 5f 6e 6f 64 65 03 43 52 45 41 54 45 20 54   t1_node.CREATE T
|   3872: 41 42 4c 45 20 22 74 31 5f 6e 6f 64 65 22 28 6e   ABLE .t1_node.(n
|   3888: 6f 64 65 6e 6f 20 49 4e 54 45 47 45 52 20 50 52   odeno INTEGER PR
|   3904: 49 4d 41 52 59 20 4b 45 59 2c 64 61 74 61 29 5c   IMARY KEY,data).
|   3920: 02 07 17 1d 1d 01 81 0b 74 61 62 6c 65 74 31 5f   ........tablet1_
|   3936: 72 6f 77 69 64 74 31 5f 72 6f 77 69 64 02 43 52   rowidt1_rowid.CR
|   3952: 45 41 54 45 20 54 41 42 4c 45 20 22 74 31 5f 72   EATE TABLE .t1_r
|   3968: 6f 77 69 64 22 28 72 6f 77 69 64 20 49 4e 54 45   owid.(rowid INTE
|   3984: 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c   GER PRIMARY KEY,
|   4000: 6e 6f 64 65 6e 6f 2c 61 30 2c 61 31 29 51 01 07   nodeno,a0,a1)Q..
|   4016: 17 11 11 08 81 0f 74 61 62 6c 65 74 31 74 31 43   ......tablet1t1C
|   4032: 52 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41   REATE VIRTUAL TA
|   4048: 42 4c 45 20 74 31 20 55 53 49 4e 47 20 72 74 72   BLE t1 USING rtr
|   4064: 65 65 28 69 64 2c 78 30 2c 78 31 2c 79 30 2c 79   ee(id,x0,x1,y0,y
|   4080: 31 2c 2b 6c 61 62 65 6c 2c 2b 6f 74 68 65 72 29   1,+label,+other)
| page 2 offset 4096
|      0: 0d 00 00 00 0e 0e f7 00 0f e8 0f d0 0f b7 0f 9e   ................
|     16: 0f 91 0f 81 0f 70 0f 5e 0f 4f 0f 39 0f 29 0f 18   .....p.^.O.9.)..
|     32: 0f 06 0e f7 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   3824: 00 00 00 00 00 00 00 0d 0e 05 00 09 1d 00 74 6f   ..............to
|   3840: 70 20 68 61 6c 66 10 0d 05 00 09 23 00 62 6f 74   p half.....#.bot
|   3856: 74 6f 6d 20 68 61 6c 66 0f 0c 05 00 09 21 00 72   tom half.....!.r
|   3872: 69 67 68 74 20 68 61 6c 66 0e 0b 05 00 09 1f 00   ight half.......
|   3888: 6c 65 66 74 20 68 61 6c 66 14 0a 05 00 09 2b 00   left half.....+.
|   3904: 74 68 65 20 77 68 6f 6c 65 20 74 68 69 6e 67 0d   the whole thing.
|   3920: 09 05 00 09 1d 00 74 6f 70 20 65 64 67 65 10 08   ......top edge..
|   3936: 05 00 09 23 00 62 6f 74 74 6f 6d 20 65 64 67 65   ...#.bottom edge
|   3952: 0f 07 05 00 09 21 00 72 69 67 68 74 20 65 64 67   .....!.right edg
|   3968: 65 0e 06 05 00 09 1f 00 6c 65 66 74 20 65 64 67   e.......left edg
|   3984: 65 0b 05 05 00 09 19 00 63 65 6e 74 65 72 17 04   e.......center..
|   4000: 05 00 09 31 00 75 70 70 65 72 2d 72 69 67 68 74   ...1.upper-right
|   4016: 20 63 6f 72 6e 65 72 17 03 05 00 09 31 00 6c 6f    corner.....1.lo
|   4032: 77 65 72 2d 72 69 67 68 74 27 60 f6 32 6e 65 72   wer-right'`.2ner
|   4048: 16 02 05 00 09 2f 00 75 70 70 65 72 2d 6c 65 66   ...../.upper-lef
|   4064: 74 20 63 6f 72 6e 65 72 16 01 05 00 09 2f 00 6c   t corner...../.l
|   4080: 6f 77 65 72 2d 6c 65 66 74 20 63 6f 72 6e 65 72   ower-left corner
| page 3 offset 8192
|      0: 0d 00 00 00 02 0b 2d 00 0b 2d 00 00 00 00 00 00   ......-..-......
|   2848: 00 00 00 00 00 00 00 00 00 00 00 00 00 89 50 01   ..............P.
|   2864: 04 00 93 24 00 00 00 0e 00 00 00 00 00 00 00 01   ...$............
|   2880: 00 00 00 00 41 20 00 00 00 00 00 00 41 20 01 00   ....A ......A ..
|   2896: 00 00 00 00 00 00 00 02 00 00 00 00 41 00 00 04   ............A...
|   2912: 2b 40 00 0c 42 c8 00 00 00 00 00 00 00 00 00 03   +@..B...........
|   2928: 42 b4 00 00 42 c8 00 00 00 00 00 00 41 20 00 00   B...B.......A ..
|   2944: 00 00 00 00 00 00 00 04 42 b4 00 00 42 c8 00 00   ........B...B...
|   2960: 42 b4 00 00 42 c8 00 00 00 00 00 00 00 00 00 05   B...B...........
|   2976: 42 20 00 00 42 70 00 00 42 20 00 00 42 70 00 00   B ..Bp..B ..Bp..
|   2992: 00 00 00 00 00 00 00 60 00 00 00 04 0a 00 00 00   .......`........
|   3008: 00 00 00 42 c8 00 00 00 00 00 00 00 00 00 07 42   ...B...........B
|   3024: be 00 00 42 c8 00 00 00 00 00 00 42 c8 00 00 00   ...B.......B....
|   3040: 00 00 00 00 00 00 08 00 00 00 00 42 c8 00 00 00   ...........B....
|   3056: 00 00 00 40 a0 00 00 00 00 00 00 00 00 00 09 00   ...@............
|   3072: 00 00 00 42 c8 00 00 42 be 00 00 42 c8 00 00 00   ...B...B...B....
|   3088: 00 00 00 00 00 00 0a 00 00 00 00 42 c8 00 00 00   ...........B....
|   3104: 00 00 00 42 c8 00 00 00 00 00 00 00 00 00 0b 00   ...B............
|   3120: 00 00 00 42 48 00 00 00 00 00 04 2c 80 00 00 00   ...BH......,....
|   3136: 00 00 00 00 00 00 c4 24 c0 00 04 2c 80 00 00 00   .......$...,....
|   3152: 00 00 04 2c 80 00 00 00 00 00 00 00 00 00 d0 00   ...,............
|   3168: 00 00 04 2c 80 00 00 00 00 00 04 24 80 00 00 00   ...,.......$....
|   3184: 00 00 00 00 00 00 e0 00 00 00 04 2c 80 00 04 24   ...........,...$
|   3200: c0 00 04 2c 00 00 00 00 00 00 00 00 00 00 00 00   ...,............
| page 4 offset 12288
|      0: 0d 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00   ................
| end c3.db
  }]
  catchsql {
    WITH RECURSIVE
      c1(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c1 WHERE x<99),
      c2(y) AS (VALUES(0) UNION ALL SELECT y+1 FROM c2 WHERE y<99)
    INSERT INTO t1(id, x0,x1,y0,y1,label)
      SELECT 1000+x+y*100, x, x+1, y, y+1, printf('box-%d,%d',x,y) FROM c1, c2;
  }
} {1 {database disk image is malformed}}
do_test rtreefuzz001-210 {
  catchsql {
    SELECT rtreecheck('t1');
  }
} {/1 .*corrupt.*/}

do_test rtreefuzz001-300 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 16384 pagesize 4096 filename c4.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 04 00 00 00 04   ................
|     96: 00 00 00 00 0d 00 00 00 04 0e 9c 00 0f ad 0f 4f   ...............O
|    112: 0e fc 0e 9c 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   3728: 00 00 00 00 00 00 00 00 00 00 00 00 5e 04 07 17   ............^...
|   3744: 1f 1f 01 81 0b 74 61 62 6c 65 74 31 5f 70 61 72   .....tablet1_par
|   3760: 65 6e 74 74 31 5f 70 61 72 65 6e 74 04 43 52 45   entt1_parent.CRE
|   3776: 41 54 45 20 54 41 42 4c 45 20 22 74 31 5f 70 61   ATE TABLE .t1_pa
|   3792: 72 65 6e 74 22 28 6e 6f 64 65 6e 6f 20 49 4e 54   rent.(nodeno INT
|   3808: 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59   EGER PRIMARY KEY
|   3824: 2c 70 61 72 65 6e 74 6e 6f 64 65 29 51 03 06 17   ,parentnode)Q...
|   3840: 1b 1b 01 7b 74 61 62 6c 65 74 31 5f 6e 6f 64 65   ....tablet1_node
|   3856: 74 31 5f 6e 6f 64 65 03 43 52 45 41 54 45 20 54   t1_node.CREATE T
|   3872: 41 42 4c 45 20 22 74 31 5f 6e 6f 64 65 22 28 6e   ABLE .t1_node.(n
|   3888: 6f 64 65 6e 6f 20 49 4e 54 45 47 45 52 20 50 52   odeno INTEGER PR
|   3904: 49 4d 41 52 59 20 4b 45 59 2c 64 61 74 61 29 5c   IMARY KEY,data).
|   3920: 02 07 17 1d 1d 01 81 0b 74 61 62 6c 65 74 31 5f   ........tablet1_
|   3936: 72 6f 77 69 64 74 31 5f 72 6f 77 69 64 02 43 52   rowidt1_rowid.CR
|   3952: 45 41 54 45 20 54 41 42 4c 45 20 22 74 31 5f 72   EATE TABLE .t1_r
|   3968: 6f 77 69 64 22 28 72 6f 77 69 64 20 49 4e 54 45   owid.(rowid INTE
|   3984: 47 45 72 20 50 52 49 4d 41 52 59 20 4b 45 59 2c   GEr PRIMARY KEY,
|   4000: 6e 6f 64 65 6e 6f 2c 61 30 2c 61 31 29 51 01 07   nodeno,a0,a1)Q..
|   4016: 17 11 11 08 81 0f 74 61 62 6c 65 74 31 74 31 43   ......tablet1t1C
|   4032: 52 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41   REATE VIRTUAL TA
|   4048: 42 4c 45 20 74 31 20 55 53 49 4e 47 20 72 74 72   BLE t1 USING rtr
|   4064: 65 65 28 69 64 2c 78 30 2c 78 31 2c 79 30 2c 79   ee(id,x0,x1,y0,y
|   4080: 31 2c 2b 6c 61 62 65 6c 2c 2b 6f 74 68 65 72 29   1,+label,+other)
| page 2 offset 4096
|      0: 0d 00 00 00 0e 0e f7 00 0f e8 0f 00 fb 70 f9 e0   .............p..
|     16: f9 10 f8 10 f7 00 f5 e0 f4 f0 f3 90 f2 90 f1 80   ................
|     32: f0 60 ef 00 00 00 00 00 00 00 00 00 00 00 00 00   .`..............
|   3824: 00 00 00 00 00 00 00 0d 0e 05 00 09 1d 00 74 6f   ..............to
|   3840: 70 20 68 61 6c 66 10 0d 05 00 09 23 00 62 6f 74   p half.....#.bot
|   3856: 74 6f 6d 20 68 61 6c 66 0f 0c 05 00 09 21 00 72   tom half.....!.r
|   3872: 69 67 68 74 20 68 61 6c 66 0e 0b 05 00 09 1f 00   ight half.......
|   3888: 6c 65 66 74 20 68 61 6c 66 14 0a 05 00 09 2b 00   left half.....+.
|   3904: 00 03 98 20 49 98 2f 6c 62 05 74 68 69 6e 67 0d   ... I./lb.thing.
|   3920: 09 05 00 09 1d 00 74 6f 70 20 65 64 67 65 10 08   ......top edge..
|   3936: 05 00 09 23 00 62 6f 74 74 6f 6d 20 65 64 67 65   ...#.bottom edge
|   3952: 0f 07 05 00 09 21 00 72 69 67 68 74 20 65 64 67   .....!.right edg
|   3968: 65 0e 06 05 00 09 1f 00 6c 65 66 74 20 65 64 67   e.......left edg
|   3984: 65 0b 05 05 00 09 19 00 63 65 6e 74 65 72 17 04   e.......center..
|   4000: 05 00 09 31 00 75 70 70 65 72 2d 72 69 67 68 74   ...1.upper-right
|   4016: 20 63 6f 72 6e 65 72 17 03 05 00 09 31 00 6c 6f    corner.....1.lo
|   4032: 77 65 72 2d 72 69 67 68 74 20 63 6f 72 6e 65 72   wer-right corner
|   4048: 16 02 05 00 09 2f 00 75 70 70 65 72 2d 6c 65 66   ...../.upper-lef
|   4064: 74 20 63 6f 72 6e 65 72 16 01 05 00 09 2f 00 6c   t corner...../.l
|   4080: 6f 77 65 72 2d 6c 65 66 74 20 63 6f 72 6e 65 72   ower-left corner
| page 3 offset 8192
|      0: 0d 00 00 00 01 0b 2d 00 0b 2d 00 00 00 00 00 00   ......-..-......
|   2848: 00 00 00 00 00 00 00 00 00 00 00 00 00 89 50 01   ..............P.
|   2864: 04 00 93 24 00 00 00 0e 00 00 00 00 00 00 00 01   ...$............
|   2880: 00 00 00 04 01 20 00 00 00 00 00 04 12 00 00 00   ..... ..........
|   2896: 00 00 00 00 00 00 00 23 00 00 00 00 41 20 00 00   .......#....A ..
|   2912: 42 b4 00 00 42 c8 00 00 00 00 00 00 00 00 00 03   B...B...........
|   2928: 42 b4 00 00 42 c8 00 00 00 00 00 00 41 20 00 00   B...B.......A ..
|   2944: 00 00 00 00 00 00 00 04 42 b4 00 00 42 c8 00 00   ........B...B...
|   2960: 42 b4 00 00 42 c8 00 00 00 00 00 00 00 00 00 05   B...B...........
|   2976: 42 20 00 00 42 70 00 00 42 20 00 00 42 70 00 00   B ..Bp..B ..Bp..
|   2992: 00 00 00 00 00 00 00 06 00 00 00 00 40 a0 00 00   ............@...
|   3008: 00 00 00 04 2c 80 00 00 00 00 00 00 00 00 00 74   ....,..........t
|   3024: 2b e0 00 04 2c 80 00 04 2c 80 00 00 00 00 00 00   +...,...,.......
|   3040: 00 00 00 80 00 00 00 04 2c 80 00 00 00 00 00 04   ........,.......
|   3056: 0a 00 00 00 00 00 b0 80 00 00 04 2c 80 00 04 2b   ...........,...+
|   3072: e0 00 04 2c 80 00 00 00 00 00 00 00 00 00 a0 00   ...,............
|   3088: 00 00 04 2c 80 00 00 00 00 00 04 2c 80 00 00 00   ...,.......,....
|   3104: 00 00 00 00 00 00 b0 00 00 00 04 24 80 00 00 00   ...........$....
|   3120: 00 00 04 2c 80 00 00 00 00 00 00 00 50 00 91 f0   ...,........P...
|   3136: 06 c6 56 67 42 06 86 16 c6 61 40 a0 50 00 92 b0   ..VgB....a@.P...
|   3152: 07 46 86 52 07 76 86 f6 c6 52 07 46 86 96 e6 70   .F.R.v...R.F...p
|   3168: d0 90 50 00 91 d0 07 46 f7 02 06 56 46 76 51 00   ..P....F...VFvQ.
|   3184: 80 50 00 92 30 06 26 f7 47 46 f6 d2 06 56 46 76   .P..0.&.GF...VFv
|   3200: 50 f0 70 50 00 92 10 07 26 96 76 87 42 06 56 46   P.pP....&.v.B.VF
|   3216: 76 50 e0 60 50 00 91 f0 06 c6 56 67 42 06 56 46   vP.`P.....VgB.VF
|   3232: 76 50 b0 50 50 00 91 90 06 36 56 e7 46 57 21 70   vP.PP....6V.FW!p
|   3248: 40 50 00 93 10 07 57 07 06 57 22 d7 26 96 76 87   @P....W..W..&.v.
|   3264: 42 06 36 f7 26 e6 57 21 70 30 50 00 93 10 06 c6   B.6.&.W!p0P.....
|   3280: f7 76 57 22 d7 26 96 76 87 42 06 36 f7 26 e6 57   .vW..&.v.B.6.&.W
|   3296: 21 60 20 50 00 92 f0 07 57 07 06 57 22 d6 c6 56   !` P....W..W...V
|   3312: 60 00 00 c4 24 c0 00 04 2c 80 00 00 00 00 00 04   `...$...,.......
|   3328: 2c 80 00 00 00 00 00 00 00 00 00 d0 00 00 00 04   ,...............
|   3344: 2c 80 00 00 00 00 00 04 24 80 00 00 00 00 00 00   ,.......$.......
|   3360: 00 00 00 e0 00 00 00 04 2c 80 00 04 24 c0 00 04   ........,...$...
|   3376: 2c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ,...............
| page 4 offset 12288
|      0: 0d 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00   ................
| end c4.db
  }]
  catchsql {
    UPDATE t1 SET label='x';
  }
} {1 {rtree constraint failed: t1.(y0<=y1)}}
do_test rtreefuzz001-310 {
  catchsql {
    SELECT rtreecheck('t1');
  }
} {/1 .*corrupt.*/}

do_test rtreefuzz001-400 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 16384 pagesize 4096 filename c7.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 01 00 00 00 00 00 00 04 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 00 00 00 04 0e 9c 00 0f ad 0f 4f   ...............O
|    112: 0e fc 0e 9c 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   3728: 00 00 00 00 00 00 00 00 00 00 00 00 5e 04 07 17   ............^...
|   3744: 1f 1f 01 81 0b 74 61 62 6c 65 74 31 5f 70 61 72   .....tablet1_par
|   3760: 65 6e 74 74 31 5f 70 61 72 65 6e 74 04 43 52 45   entt1_parent.CRE
|   3776: 41 54 45 20 54 41 42 4c 45 20 22 74 31 5f 70 61   ATE TABLE .t1_pa
|   3792: 72 65 6e 74 22 28 6e 6f 64 65 6e 6f 20 49 4e 54   rent.(nodeno INT
|   3808: 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59   EGER PRIMARY KEY
|   3824: 2c 70 61 72 65 6e 74 6e 6f 64 65 29 51 03 06 17   ,parentnode)Q...
|   3840: 1b 1b 01 7b 74 61 62 6c 65 74 31 5f 6e 6f 64 65   ....tablet1_node
|   3856: 74 31 5f 6e 6f 64 65 03 43 52 45 41 54 45 20 54   t1_node.CREATE T
|   3872: 41 42 4c 45 20 22 74 31 5f 6e 6f 64 65 22 28 6e   ABLE .t1_node.(n
|   3888: 6f 64 65 6e 6f 20 49 4e 54 45 47 45 52 20 50 52   odeno INTEGER PR
|   3904: 49 4d 41 52 59 20 4b 45 59 2c 64 61 74 61 29 5c   IMARY KEY,data).
|   3920: 02 07 17 1d 1d 01 81 0b 74 61 62 6c 65 74 31 5f   ........tablet1_
|   3936: 72 6f 77 69 64 74 31 5f 72 6f 77 69 64 02 43 52   rowidt1_rowid.CR
|   3952: 45 41 54 45 20 54 41 42 4c 45 20 22 74 31 5f 72   EATE TABLE .t1_r
|   3968: 6f 77 69 64 22 28 72 6f 77 69 64 20 49 4e 54 45   owid.(rowid INTE
|   3984: 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c   GER PRIMARY KEY,
|   4000: 6e 6f 64 65 6e 6f 2c 61 30 2c 61 31 29 51 01 07   nodeno,a0,a1)Q..
|   4016: 17 11 11 08 81 0f 74 61 62 6c 65 74 31 74 31 43   ......tablet1t1C
|   4032: 52 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41   REATE VIRTUAL TA
|   4048: 42 4c 45 20 74 31 20 55 53 49 4e 47 20 72 74 72   BLE t1 USING rtr
|   4064: 65 65 28 69 64 2c 78 30 2c 78 31 2c 79 30 2c 79   ee(id,x0,x1,y0,y
|   4080: 31 2c 2b 6c 61 62 65 6c 2c 2b 6f 74 68 65 72 29   1,+label,+other)
| page 2 offset 4096
|      0: 0d 00 00 00 0e 0e f7 00 0f e8 0f d0 0f b7 0f 9e   ................
|     16: 0f 91 0f 81 0f 70 0f 5e 0f 4f 0f 39 0f 29 0f 18   .....p.^.O.9.)..
|     32: 0f 06 0e f7 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   3824: 00 00 00 00 00 00 00 0d 0e 05 00 09 1d 00 74 6f   ..............to
|   3840: 70 20 68 61 6c 66 10 0d 05 00 09 23 00 62 6f 74   p half.....#.bot
|   3856: 74 6f 6d 20 68 61 6c 66 0f 0c 05 00 09 21 00 72   tom half.....!.r
|   3872: 69 67 68 74 20 68 61 6c 66 0e 0b 05 00 09 1f 00   ight half.......
|   3888: 6c 65 66 74 20 68 61 6c 66 14 0a 05 00 09 2b 00   left half.....+.
|   3904: 74 68 65 20 77 68 6f 6c 65 20 74 68 69 6e 67 0d   the whole thing.
|   3920: 09 05 00 09 1d 00 74 6f 70 20 65 64 67 65 10 08   ......top edge..
|   3936: 05 00 09 23 00 62 6f 74 74 6f 6d 20 65 64 67 65   ...#.bottom edge
|   3952: 0f 07 05 00 09 21 00 72 69 67 68 74 20 65 64 67   .....!.right edg
|   3968: 65 0e 06 05 00 09 1f 00 6c 65 66 74 20 65 64 67   e.......left edg
|   3984: 65 0b 05 05 00 09 19 00 23 65 6e 74 65 72 17 04   e.......#enter..
|   4000: 05 00 09 31 00 75 70 70 65 72 2d 72 69 67 68 74   ...1.upper-right
|   4016: 20 63 6f 72 6e 65 72 17 03 05 00 09 31 00 6c 6f    corner.....1.lo
|   4032: 77 65 72 2d 72 69 67 68 74 20 63 6f 72 6e 65 72   wer-right corner
|   4048: 16 02 05 00 09 2f 00 75 70 70 65 72 2d 6c 65 66   ...../.upper-lef
|   4064: 74 20 63 6f 72 6e 65 72 16 01 05 00 09 2f 00 6c   t corner...../.l
|   4080: 6f 77 65 72 2d 6c 65 66 74 20 63 6f 72 6e 65 72   ower-left corner
| page 3 offset 8192
|      0: 0d 00 00 00 02 0b 2d 00 0b 2d 00 00 00 00 00 00   ......-..-......
|   2848: 00 00 00 00 00 00 00 00 00 00 00 00 00 89 50 01   ..............P.
|   2864: 04 00 93 24 00 00 00 00 00 00 00 00 08 00 00 00   ...$............
|   2880: 00 42 c8 00 00 00 00 00 00 40 a0 00 00 00 00 00   .B.......@......
|   2896: 00 00 00 00 42 c8 00 00 00 00 00 00 00 00 00 07   ....B...........
|   2912: 42 be 00 00 42 c8 00 00 00 00 00 00 42 c8 00 00   B...B.......B...
|   2928: 00 00 00 00 00 00 00 08 00 00 00 00 42 c8 00 00   ............B...
|   2944: 00 00 00 00 40 a0 00 00 00 00 00 00 00 00 00 09   ....@...........
|   2960: 00 00 00 00 42 c8 00 00 42 be 00 00 42 c8 00 00   ....B...B...B...
|   2976: 00 00 00 00 00 00 00 0a 00 00 00 00 42 c8 00 00   ............B...
|   2992: 00 00 00 00 42 c8 00 00 00 00 00 00 00 00 00 0b   ....B...........
|   3008: 00 00 00 00 42 48 00 00 00 00 00 04 2c 80 00 00   ....BH......,...
|   3024: 00 00 00 00 00 00 00 c4 00 00 00 00 00 42 c8 00   .............B..
|   3040: 00 00 00 00 00 00 00 00 07 42 be 00 00 42 c8 00   .........B...B..
|   3056: 00 00 00 00 00 42 c8 00 00 00 00 00 00 00 00 00   .....B..........
|   3072: 08 00 00 00 00 42 c8 00 00 00 00 00 00 40 a0 00   .....B.......@..
|   3088: 00 00 00 00 00 00 00 00 09 00 00 00 00 42 c8 00   .............B..
|   3104: 00 42 be 00 00 42 c8 00 00 00 00 00 00 00 00 00   .B...B..........
|   3120: 0a 00 00 00 00 42 c8 00 00 00 00 00 00 42 c8 00   .....B.......B..
|   3136: 00 00 00 00 00 00 00 00 0b 00 00 00 00 42 48 00   .............BH.
|   3152: 00 00 00 00 04 2c 80 00 00 00 00 00 00 00 00 00   .....,..........
|   3168: c4 24 c0 00 04 2c 80 00 00 00 00 00 04 2c 80 00   .$...,.......,..
|   3184: 00 00 00 00 00 00 00 00 d0 00 00 00 04 2c 80 00   .............,..
|   3200: 00 00 00 00 04 24 80 00 00 00 00 00 00 00 00 00   .....$..........
|   3216: e0 00 00 00 04 2c 80 00 04 24 c0 00 04 2c 00 00   .....,...$...,..
| page 4 offset 12288
|      0: 0d 00 00 00 00 10 00 00 00 00 00 00 0e 00 00 00   ................
|     16: 00 42 c8 00 00 42 4c 00 00 42 c8 00 00 00 00 00   .B...BL..B......
|     32: 00 00 00 0a 00 00 00 00 42 c8 00 00 00 00 00 00   ........B.......
|     48: 42 c8 00 00 00 00 00 00 00 00 00 0b 00 00 00 00   B...............
|     64: 42 48 00 00 00 00 00 04 2c 80 00 00 00 00 00 00   BH......,.......
|     80: 00 00 00 c4 24 c0 00 04 2c 80 00 00 00 00 00 04   ....$...,.......
|     96: 2c 80 00 00 00 00 00 00 00 00 00 d0 00 00 00 04   ,...............
|    112: 2c 80 00 00 00 00 00 04 24 80 00 00 00 00 00 00   ,.......$.......
|    128: 00 00 00 e0 00 00 00 04 2c 80 00 04 24 c0 00 04   ........,...$...
|    144: 2c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ,...............
| end c7.db
  }]
  catchsql {
    WITH RECURSIVE
      c1(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c1 WHERE x<8),
      c2(y) AS (VALUES(0) UNION ALL SELECT y+1 FROM c2 WHERE y<5)
    INSERT INTO t1(id, x0,x1,y0,y1,label)
      SELECT 1000+x+y*100, x, x+1, y, y+1, printf('box-%d,%d',x,y) FROM c1, c2;
  }
} {1 {database disk image is malformed}}

do_test rtreefuzz001-500 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 16384 pagesize 4096 filename crash-2e81f5dce5cbd4.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 05 0e 6d 00 0f c8 0f 7b   ..........m.....
|    112: 0f 20 0e cd 0e 6d 00 00 00 00 00 00 00 00 00 00   . ...m..........
|   3680: 00 00 00 00 00 00 00 00 00 00 00 00 00 5e 05 07   .............^..
|   3696: 17 1f 1f 01 81 0b 74 61 62 6c 65 74 31 5f 70 61   ......tablet1_pa
|   3712: 72 65 6e 74 74 31 5f 70 61 72 65 6e 74 05 43 52   rentt1_parent.CR
|   3728: 45 41 54 45 20 54 41 42 4c 45 20 22 74 31 5f 70   EATE TABLE .t1_p
|   3744: 61 72 65 6e 74 22 28 6e 6f 64 65 6e 6f 20 49 4e   arent.(nodeno IN
|   3760: 54 45 47 45 42 20 50 52 49 4d 41 52 59 20 4b 45   TEGEB PRIMARY KE
|   3776: 59 2c 70 61 72 65 6e 74 6e 6f 64 65 29 51 04 06   Y,parentnode)Q..
|   3792: 17 1b 1b 01 7b 74 61 62 6c 65 74 31 5f 6e 6f 64   .....tablet1_nod
|   3808: 65 74 31 5f 6e 6f 64 65 04 43 52 45 41 54 45 20   et1_node.CREATE 
|   3824: 54 41 42 4c 45 20 22 74 31 5f 6e 6f 64 65 22 28   TABLE .t1_node.(
|   3840: 6e 6f 64 65 6e 6f 20 49 4e 54 45 47 45 52 20 50   nodeno INTEGER P
|   3856: 52 49 4d 41 52 59 20 4b 45 59 2c 64 61 74 61 29   RIMARY KEY,data)
|   3872: 59 03 07 17 1d 1d 01 81 05 74 61 62 6c 65 84 31   Y........table.1
|   3888: 5f 72 6f 77 69 64 74 31 5f 72 6f 87 69 64 03 43   _rowidt1_ro.id.C
|   3904: 52 45 41 54 45 20 54 41 42 4c 45 20 22 74 31 5f   REATE TABLE .t1_
|   3920: 72 6f 77 69 64 22 28 72 6f 77 69 64 20 49 4e 54   rowid.(rowid INT
|   3936: 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59   EGER PRIMARY KEY
|   3952: 2c 6e f8 64 65 6e 6f 2c 61 30 29 4b 02 07 17 11   ,n.deno,a0)K....
|   3968: 11 08 81 03 74 22 62 6c 65 74 31 74 31 43 52 45   ....t.blet1t1CRE
|   3984: 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 4c   ATE VIRTUAL TABL
|   4000: 45 20 74 31 20 55 53 49 4e 47 20 72 74 72 65 65   E t1 USING rtree
|   4016: 5f 69 33 32 28 69 cc 2c 78 30 2c 78 31 2c 79 30   _i32(i.,x0,x1,y0
|   4032: 2c 79 31 2c 2b 65 78 29 36 01 06 17 17 17 01 4d   ,y1,+ex)6......M
|   4048: 74 61 62 6c 65 63 6f 6f 72 64 63 6f 6f 72 64 02   tablecoordcoord.
|   4064: 43 52 45 41 54 45 20 54 41 42 4c 45 20 63 6f 6f   CREATE TABLE coo
|   4080: 71 64 28 76 20 49 4e 54 2c 20 77 20 49 4e 54 29   qd(v INT, w INT)
| page 2 offset 4096
|   4016: 00 00 00 00 00 00 00 00 00 00 00 05 0a 03 01 01   ................
|   4032: 0a 02 05 09 03 01 01 09 02 05 08 03 01 01 08 02   ................
|   4048: 05 07 03 01 01 07 02 05 06 03 11 01 06 02 05 05   ................
|   4064: 03 01 01 05 02 05 04 03 01 01 04 02 05 03 03 01   ................
|   4080: 01 03 02 05 02 03 01 01 02 02 04 01 03 09 01 02   ................
| page 3 offset 8192
|      0: 0d 0e 4f 00 64 0b 5a 12 0d bb 0d 84 0f eb 0d c6   ..O.d.Z.........
|     16: 0f d7 0e cc 0f c1 0f b6 0f ab 0f 9f 0f 94 0d 8f   ................
|     32: 0f 86 0d d1 0f 62 0f 67 0f 5c 0f 51 1f 46 0f 3a   .....b.g...Q.F.:
|     48: 0f 30 0d 9a 0f 21 0d dc 0f 00 00 00 00 00 00 00   .0...!..........
|   2896: 00 00 00 00 00 00 00 00 00 00 0a ce 1a 04 00 01   ................
|   2912: 17 03 31 30 78 31 30 0a 4e 19 03 ff f1 15 03 31   ..10x10.N......1
|   2928: 30 78 39 09 ce 18 04 00 01 15 03 31 30 78 38 09   0x9........10x8.
|   2944: ce 17 04 00 01 15 03 31 30 78 37 09 ce 16 04 00   .......10x7.....
|   2960: 12 15 03 31 30 78 36 09 ce 15 04 00 01 15 03 31   ...10x6........1
|   2976: 30 78 35 09 ce 14 04 00 01 15 0d a1 30 78 34 09   0x5.........0x4.
|   2992: ce 13 04 00 01 15 03 31 30 78 33 09 ce 12 04 00   .......10x3.....
|   3008: 01 15 03 31 40 78 32 09 ce 11 04 00 01 15 03 31   ...1@x2........1
|   3024: 30 78 31 09 c6 32 04 00 01 15 03 39 78 31 30 08   0x1..2.....9x10.
|   3040: c6 31 04 00 01 13 03 39 78 39 08 c6 30 04 00 01   .1.....9x9..0...
|   3056: 13 03 39 78 38 08 c6 2f 04 00 01 14 03 39 78 37   ..9x8../.....9x7
|   3072: 08 c6 2e 04 00 01 13 03 39 78 36 08 c6 2d 04 00   ........9x6..-..
|   3088: 01 13 03 39 78 34 f8 c6 2c 04 00 01 13 03 39 78   ...9x4..,.....9x
|   3104: 34 08 c6 2b 04 00 60 13 03 39 79 13 08 c6 2a 04   4..+..`..9y...*.
|   3120: 00 11 13 03 39 78 32 08 c6 29 04 00 01 13 03 39   ....9x2..).....9
|   3136: 78 31 09 be 4a 04 00 01 15 03 38 78 31 30 08 be   x1..J.....8x10..
|   3152: 49 04 00 01 13 03 38 78 39 08 be 48 04 00 01 13   I.....8x9..H....
|   3168: 03 38 77 98 08 be 47 04 00 01 14 23 38 78 37 08   .8w...G....#8x7.
|   3184: be 46 04 00 01 13 03 38 78 36 08 be 45 04 00 01   .F.....8x6..E...
|   3200: 13 03 38 78 35 08 be 44 04 00 01 13 03 38 78 34   ..8x5..D.....8x4
|   3216: 08 be 43 04 00 01 13 03 38 78 33 08 be 42 04 00   ..C.....8x3..B..
|   3232: 01 13 03 38 78 32 08 be 41 04 00 01 13 03 38 78   ...8x2..A.....8x
|   3248: 31 09 b6 62 04 00 01 15 03 37 68 31 30 08 b6 61   1..b.....7h10..a
|   3264: 04 00 01 13 03 37 79 39 08 b6 60 04 00 01 12 f3   .....7y9..`.....
|   3280: 37 78 38 08 b6 5e 04 00 01 13 03 37 78 37 08 b6   7x8..^.....7x7..
|   3296: 5e 04 00 01 13 03 37 78 36 08 b6 5d 04 00 01 13   ^.....7x6..]....
|   3312: 03 37 78 35 08 b6 5c 04 00 00 13 03 37 78 34 08   .7x5........7x4.
|   3328: b6 5b 04 00 01 13 03 37 78 33 08 b6 5a 04 00 01   .[.....7x3..Z...
|   3344: 13 03 37 78 32 08 b6 59 04 00 01 13 03 37 78 31   ..7x2..Y.....7x1
|   3360: 09 ae 7a 04 00 01 15 03 36 78 31 30 08 ae 79 04   ..z.....6x10..y.
|   3376: 00 01 e2 03 36 78 39 08 ae 78 04 00 01 13 03 36   ....6x9..x.....6
|   3392: 78 38 08 ae 77 04 00 01 13 03 36 78 37 08 ae 76   x8..w.....6x7..v
|   3408: 04 00 01 13 03 36 78 36 08 ae 85 04 00 01 13 03   .....6x6........
|   3424: 36 78 35 08 ae 73 f4 00 01 13 03 36 78 34 08 ae   6x5..s.....6x4..
|   3440: 73 04 00 01 13 03 36 78 33 08 ae 72 04 00 01 13   s.....6x3..r....
|   3456: 03 36 78 32 08 87 6a 04 00 01 13 02 3d e8 32 08   .6x2..j.....=.2.
|   3472: 8f 52 04 00 01 13 02 32 78 32 08 97 3b 04 00 01   .R.....2x2..;...
|   3488: 13 02 33 78 32 08 9f 22 04 00 01 13 02 34 78 32   ..3x2........4x2
|   3504: 08 a7 0a 04 00 01 13 02 35 78 32 08 87 69 04 00   ........5x2..i..
|   3520: 01 13 02 31 78 31 08 87 6c 04 00 01 13 02 31 78   ...1x1..l.....1x
|   3536: 34 08 8f 54 04 00 01 13 02 32 78 34 08 97 3c 04   4..T.....2x4..<.
|   3552: 00 01 12 f2 33 78 34 08 9f 24 04 00 01 13 02 34   ....3x4..$.....4
|   3568: 78 34 08 a7 0c 04 00 01 13 02 35 78 34 0e 6c 00   x4........5x4.l.
|   3584: 08 ae 71 04 00 01 13 03 36 78 31 09 a7 12 04 00   ..q.....6x1.....
|   3600: 01 15 02 35 78 31 30 08 a7 11 04 00 01 13 02 35   ...5x10........5
|   3616: 78 39 08 a7 10 04 00 01 13 02 35 78 38 08 a7 0f   x9........5x8...
|   3632: 04 00 01 14 02 35 78 37 08 a7 0e 04 00 01 13 02   .....5x7........
|   3648: 35 78 36 08 a7 0d 04 00 01 13 02 35 78 35 0e 0e   5x6........5x5..
|   3664: b3 00 08 00 01 00 03 08 a7 0b 04 00 01 13 02 35   ...............5
|   3680: 78 33 0e d1 00 08 a7 09 04 00 01 13 02 35 78 31   x3...........5x1
|   3696: 09 9f 2a 04 00 01 15 02 34 78 31 30 03 cf 29 04   ..*.....4x10..).
|   3712: 00 01 13 02 34 78 39 08 9f 28 04 00 01 13 02 34   ....4x9..(.....4
|   3728: 78 38 09 9f 27 04 00 01 13 02 34 78 37 08 9f 26   x8..'.....4x7..&
|   3744: 04 00 01 13 0e a4 78 36 08 9f 25 04 00 01 13 02   ......x6..%.....
|   3760: 34 78 35 0f 18 00 09 00 09 13 34 78 08 9f 23 04   4x5.......4x..#.
|   3776: 00 01 13 02 34 78 33 0f 36 00 08 9f 21 04 00 01   ....4x3.6...!...
|   3792: 13 02 34 78 31 09 97 42 04 00 01 15 02 33 78 31   ..4x1..B.....3x1
|   3808: 30 08 97 41 04 00 01 13 02 33 78 39 08 97 40 04   0..A.....3x9..@.
|   3824: 00 01 13 02 33 78 38 18 97 3f 04 00 01 13 02 33   ....3x8..?.....3
|   3840: 78 37 08 97 3e 04 00 01 13 02 33 78 36 08 97 3d   x7..>.....3x6..=
|   3856: 04 00 01 13 02 33 78 35 1f 7d 00 09 00 09 13 33   .....3x5.......3
|   3872: 78 07 97 3b 04 00 01 13 02 33 78 33 0f 9b 00 08   x..;.....3x3....
|   3888: 97 39 04 00 01 13 02 33 78 31 09 8f 5a 04 00 01   .9.....3x1..Z...
|   3904: 15 02 32 79 31 30 08 8f 59 04 00 01 13 fa 32 78   ..2y10..Y.....2x
|   3920: 39 08 8f 58 04 00 01 13 02 32 78 38 08 8f 57 04   9..X.....2x8..W.
|   3936: 00 01 13 02 32 78 37 08 8f 56 04 00 01 13 02 32   ....2x7..V.....2
|   3952: 78 36 08 8f 55 04 00 01 13 02 32 78 35 0f e2 00   x6..U.....2x5...
|   3968: 09 00 09 13 32 78 08 8f 53 04 00 01 13 02 32 78   ....2x..S.....2x
|   3984: 33 00 00 00 08 8f 51 04 00 01 13 02 aa 78 31 09   3.....Q......x1.
|   4000: 87 72 04 00 01 15 02 31 78 31 30 08 87 71 04 00   .r.....1x10..q..
|   4016: 01 13 03 31 78 39 08 87 70 04 00 01 13 02 31 78   ...1x9..p.....1x
|   4032: 38 08 87 6f 04 00 01 13 02 31 78 37 08 87 6e 04   8..o.....1x7..n.
|   4048: 00 01 13 02 31 78 36 08 87 6d 04 00 01 13 02 31   ....1x6..m.....1
|   4064: 7d 25 0f f9 00 08 ff f9 13 31 78 08 87 6b 04 00   .%.......1x..k..
|   4080: 01 13 02 31 78 33 00 00 00 00 00 08 00 01 00 03   ...1x3..........
| page 4 offset 12288
|      0: 0d 00 00 00 03 01 87 00 0b 2d 06 5a 01 87 00 00   .........-.Z....
|    384: 00 00 00 00 00 00 00 89 50 01 54 00 93 24 00 00   ........P.T..$..
|    400: 00 32 00 00 00 00 00 00 23 2f 00 00 00 09 00 00   .2......#/......
|    416: 00 0b 00 00 00 07 00 00 00 09 00 00 00 00 00 00   ................
|    432: 23 2e 00 00 10 09 00 00 00 0b 00 00 00 06 00 00   #...............
|    448: 00 08 00 00 00 00 00 00 23 2d 00 00 00 09 00 00   ........#-......
|    464: 00 0b 00 00 00 05 00 00 00 07 00 00 00 00 00 00   ................
|    480: 23 2c 00 00 00 09 00 00 00 0b 00 00 00 04 00 00   #,..............
|    496: 00 06 00 00 00 00 00 00 23 2b 00 00 00 09 00 00   ........#+......
|    512: 00 0b 00 00 00 03 00 00 00 05 00 00 00 00 00 00   ................
|    528: 23 2a 00 00 00 09 00 00 00 0b 00 00 00 02 00 00   #*..............
|    544: 00 04 00 00 00 00 00 00 23 29 00 00 00 09 00 00   ........#)......
|    560: 00 0b 00 00 00 01 00 00 00 03 00 00 00 00 00 00   ................
|    576: 1f 4a 00 00 00 08 00 00 00 0a 00 00 00 0a 00 00   .J..............
|    592: 00 0c 00 00 00 00 00 00 0f 49 00 00 00 08 00 00   .........I......
|    608: 00 0a 00 00 00 09 00 00 00 0b 00 00 00 00 00 00   ................
|    624: 1f 48 00 00 00 08 00 00 00 0a 00 00 00 08 00 06   .H..............
|    640: 00 0a 00 00 00 00 00 00 1f 47 00 00 00 08 00 00   .........G......
|    656: 00 0a 00 00 00 07 00 00 00 09 00 00 00 00 00 00   ................
|    672: 15 d6 00 00 00 08 00 00 00 0a 00 00 00 06 00 00   ................
|    688: 00 08 00 00 00 00 00 00 1f 45 00 00 00 08 00 00   .........E......
|    704: 00 0a 00 00 00 05 00 00 00 07 00 00 00 00 00 00   ................
|    720: 1f 44 00 00 00 08 00 00 00 0a 00 00 00 04 00 00   .D..............
|    736: 00 06 00 00 00 00 00 00 1f 43 00 00 00 07 ff ff   .........C......
|    752: f0 0a 00 00 00 03 00 00 00 05 00 00 00 00 00 00   ................
|    768: 1f 42 00 00 00 08 00 00 00 0a 00 00 00 01 ff f0   .B..............
|    784: 00 03 ff ff ff ff ff ff 1f 41 00 00 00 08 00 00   .........A......
|    800: 00 0a 00 00 00 01 00 00 00 03 00 00 00 00 00 00   ................
|    816: 1b 62 00 00 00 07 00 00 00 09 00 00 00 0a 00 00   .b..............
|    832: 00 0c 05 00 00 00 00 00 1b 64 10 00 00 07 00 00   .........d......
|    848: 00 09 00 00 00 09 00 00 00 0b 00 00 00 00 00 00   ................
|    864: 1b 60 00 00 00 07 00 00 00 09 00 00 00 08 00 00   .`..............
|    880: 00 0a 00 00 00 00 00 00 1b 5f 00 00 00 07 00 00   ........._......
|    896: 00 09 00 00 00 07 00 00 00 09 00 00 00 00 00 00   ................
|    912: 1b 5e 00 00 00 07 00 00 00 09 00 00 00 06 00 00   .^..............
|    928: 00 08 00 00 00 00 00 00 1b 5d 00 00 00 08 00 00   .........]......
|    944: 00 09 00 00 00 05 00 00 00 07 00 00 00 00 00 00   ................
|    960: 1b 5c 00 00 00 07 00 00 00 09 00 00 00 04 00 00   ................
|    976: 06 46 00 00 00 00 00 00 1b 5b 00 00 00 07 00 00   .F.......[......
|    992: 00 09 00 00 00 03 00 00 00 04 ff f0 00 00 00 00   ................
|   1008: 1b 5a 00 00 00 07 00 00 00 19 00 00 00 02 00 00   .Z..............
|   1024: 00 04 00 00 00 00 00 00 1b 59 00 00 00 07 00 00   .........Y......
|   1040: 00 09 00 00 00 01 00 00 00 03 00 00 00 00 ff f0   ................
|   1056: 17 7a 00 00 00 06 00 00 00 08 00 00 00 0a 00 00   .z..............
|   1072: 00 0c 00 00 00 00 00 00 17 79 00 00 00 06 00 00   .........y......
|   1088: 00 08 00 00 00 09 00 00 00 0b 00 00 00 00 00 00   ................
|   1104: 17 78 00 00 00 06 00 00 00 08 00 00 00 08 00 00   .x..............
|   1120: 00 0a 00 00 00 00 00 00 17 77 00 00 00 06 10 00   .........w......
|   1136: 00 08 00 00 00 07 00 09 c0 09 00 00 00 00 00 00   ................
|   1152: 17 76 00 00 00 06 00 00 00 08 00 00 00 06 00 00   .v..............
|   1168: 00 08 00 00 00 00 00 00 17 75 00 00 00 06 00 00   .........u......
|   1184: 00 08 00 00 00 05 00 00 00 07 00 00 00 00 00 00   ................
|   1200: 17 74 00 00 00 06 00 00 00 08 00 00 00 03 ff ff   .t..............
|   1216: f0 06 00 00 00 83 00 00 17 73 00 00 00 06 00 00   .........s......
|   1232: 00 08 00 00 00 03 00 00 00 05 00 00 00 00 00 00   ................
|   1248: 17 71 ff 00 00 06 00 00 10 08 00 00 00 02 00 00   .q..............
|   1264: 00 04 00 00 c0 00 00 00 17 0d 00 00 00 06 00 00   ................
|   1280: 00 08 00 00 e7 01 00 00 00 03 00 00 09 e0 00 00   ................
|   1296: 23 30 00 00 00 09 00 00 00 0a 00 00 00 08 00 00   #0..............
|   1312: 00 0a 00 00 00 00 bb 00 23 31 00 00 00 09 00 00   ........#1......
|   1328: 00 0b 00 00 00 09 00 00 00 0b 00 00 00 00 00 00   ................
|   1344: 23 32 00 00 00 09 00 00 00 0b 00 00 00 0a 00 00   #2..............
|   1360: 00 0c 00 00 00 00 00 00 27 11 00 00 00 0a 00 00   ........'.......
|   1376: 00 0c 00 00 00 01 00 08 c0 03 00 00 00 00 00 00   ................
|   1392: 27 12 00 00 00 0a 00 00 00 0c 51 00 00 02 00 00   '.........Q.....
|   1408: 00 04 6f 00 00 00 00 00 27 13 00 00 00 09 ff ff   ..o.....'.......
|   1424: 00 0c 00 00 00 03 00 00 00 05 00 00 00 00 00 00   ................
|   1440: 27 14 00 00 00 0a 00 00 00 00 00 00 00 00 00 00   '...............
|   1616: 00 00 00 00 00 00 00 00 00 00 89 50 02 04 00 93   ...........P....
|   1632: 24 00 00 00 32 00 00 00 00 00 00 23 8c 00 00 00   $...2......#....
|   1648: 05 00 00 00 07 00 00 00 04 00 00 00 06 00 00 00   ................
|   1664: 00 00 00 0f a4 00 00 00 04 00 00 00 06 00 00 00   ................
|   1680: 04 00 00 00 06 00 00 00 00 00 00 0b bc 00 00 00   ................
|   1696: 03 00 00 00 05 00 00 00 04 00 00 00 06 00 00 00   ................
|   1712: 00 00 00 07 d4 00 00 00 02 00 00 00 04 00 00 00   ................
|   1728: 04 00 00 00 06 00 00 00 10 00 00 03 ec 00 00 00   ................
|   1744: 01 00 00 00 03 00 00 00 04 00 00 00 06 00 00 00   ................
|   1760: 00 00 00 13 8d 00 00 00 05 00 00 00 07 00 00 00   ................
|   1776: 05 00 00 00 07 00 00 00 00 00 00 0f a5 00 00 00   ................
|   1792: 04 00 00 00 06 00 00 00 05 00 00 00 07 00 00 00   ................
|   1808: 00 00 00 0b bd 00 00 00 03 00 00 00 05 00 00 00   ................
|   1824: 05 00 00 00 07 00 00 00 00 00 00 07 d5 00 00 00   ................
|   1840: 02 00 00 00 05 00 00 00 05 00 00 00 07 00 00 00   ................
|   1856: 00 00 00 03 ed 00 00 00 01 00 00 00 03 00 00 00   ................
|   1872: 05 00 00 00 07 00 00 00 00 00 00 13 8e 00 00 00   ................
|   1888: 05 00 00 00 07 00 00 00 06 00 00 00 08 00 00 00   ................
|   1904: 00 00 00 0f a6 00 00 00 04 00 00 00 06 00 00 00   ................
|   1920: 06 00 00 00 07 ff ff 00 00 00 00 0b be 00 00 00   ................
|   1936: 0b 40 00 00 05 00 00 00 06 00 00 00 08 00 00 00   .@..............
|   1952: 00 00 00 07 d6 00 00 00 02 00 00 00 04 00 00 00   ................
|   1968: 05 00 00 00 08 00 00 00 00 00 00 03 ee 00 00 00   ................
|   1984: 01 00 00 00 02 ff ff 00 06 00 00 00 08 00 00 00   ................
|   2000: 00 00 00 13 8f 00 00 00 05 00 00 00 07 00 00 00   ................
|   2016: 07 00 00 00 09 00 00 00 00 00 00 0f a7 00 00 00   ................
|   2032: 04 00 00 00 06 00 00 00 07 00 00 00 09 00 00 08   ................
|   2048: 30 00 00 0b bf 00 00 00 03 00 00 00 05 00 00 00   0...............
|   2064: 07 00 00 00 09 00 00 00 00 00 00 07 d7 00 00 00   ................
|   2080: 02 00 00 00 04 00 00 00 07 00 00 00 09 00 00 00   ................
|   2096: 00 00 00 03 ef 00 00 00 01 00 00 00 03 00 00 00   ................
|   2112: 07 00 00 00 09 00 00 00 00 00 00 13 90 00 00 00   ................
|   2128: 05 00 01 00 07 00 00 00 08 00 00 00 0a 00 00 00   ................
|   2144: 00 00 00 0f a8 00 00 00 04 00 00 00 06 00 00 00   ................
|   2160: 08 00 00 00 0a 00 00 00 00 00 00 0b f2 00 00 00   ................
|   2176: 03 00 00 00 05 00 00 00 08 00 00 00 0a 00 00 01   ................
|   2192: 00 00 00 07 d8 00 00 00 02 00 00 00 04 00 00 00   ................
|   2208: 08 00 00 00 0a 00 00 00 00 00 00 03 f0 00 00 00   ................
|   2224: 01 00 00 00 03 00 00 00 08 00 00 00 09 ff 00 00   ................
|   2240: 00 00 00 13 91 00 00 00 05 00 00 00 07 00 00 00   ................
|   2256: 09 00 00 00 0b 00 00 00 00 00 00 0f a9 00 00 00   ................
|   2272: 04 00 00 00 06 00 00 00 09 00 00 00 0b 00 00 00   ................
|   2288: 00 00 00 0b c1 00 00 00 03 00 00 00 05 00 00 00   ................
|   2304: 09 00 00 00 0b 00 00 00 00 00 00 07 d9 00 00 00   ................
|   2320: 02 00 00 00 04 00 00 00 09 00 00 00 0b 00 00 01   ................
|   2336: 00 00 00 03 f0 ff ff 00 01 00 00 00 03 00 00 00   ................
|   2352: 09 00 00 00 0b 00 00 00 00 00 00 13 92 00 00 00   ................
|   2368: 05 00 00 00 07 00 00 00 0a 00 00 00 0c 00 00 00   ................
|   2384: 00 00 00 0f aa 00 00 00 04 00 00 00 06 00 00 00   ................
|   2400: 0a 00 00 00 0c 00 00 00 00 00 00 0b c2 00 00 00   ................
|   2416: 03 00 00 00 05 00 00 00 0a 00 00 00 0c 00 00 00   ................
|   2432: 00 00 00 07 da 00 00 00 02 00 00 00 04 00 00 00   ................
|   2448: 0a 00 00 00 0c 00 00 00 00 00 00 03 f2 00 00 00   ................
|   2464: 01 00 00 10 03 00 00 00 0a 00 00 00 0c 00 00 00   ................
|   2480: 00 00 00 03 eb 00 00 00 01 00 00 00 03 00 00 00   ................
|   2496: 03 00 00 00 05 00 00 00 00 00 00 07 d3 00 00 00   ................
|   2512: 02 00 00 00 04 00 00 00 03 00 00 00 05 00 00 00   ................
|   2528: 00 00 00 0b bb 00 00 00 03 00 00 00 05 00 00 00   ................
|   2544: 03 00 00 00 05 00 00 00 00 00 00 0f a3 00 00 00   ................
|   2560: 04 00 00 00 06 00 00 00 03 00 00 00 05 00 00 00   ................
|   2576: 00 00 00 13 8b 00 00 00 05 00 00 00 07 00 00 00   ................
|   2592: 03 00 00 00 05 00 00 00 00 00 00 03 ea 00 00 00   ................
|   2608: 01 00 00 00 03 00 00 00 02 00 00 00 04 00 00 00   ................
|   2624: 00 00 00 07 d2 00 00 00 02 00 00 00 04 00 00 00   ................
|   2640: 02 00 00 00 04 00 00 00 00 00 00 0b ba 00 00 00   ................
|   2656: 03 00 00 00 05 00 00 00 02 00 00 00 04 00 00 00   ................
|   2672: 00 00 00 0f a1 ff ff ff 04 00 00 00 06 00 00 00   ................
|   2688: 02 00 00 00 04 00 00 00 00 00 00 13 8a 00 00 00   ................
|   2704: 05 00 00 00 06 ff ff ff f2 00 00 00 04 00 00 00   ................
|   2720: 00 00 00 03 e9 00 00 00 01 00 00 00 03 00 00 00   ................
|   2736: 01 00 00 00 03 00 00 00 00 00 00 07 d1 00 00 00   ................
|   2848: 00 00 00 00 00 00 00 00 00 00 00 00 00 89 50 01   ..............P.
|   2864: 04 00 93 24 00 01 00 02 00 00 00 00 00 00 00 02   ...$............
|   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/rtree/test_rtreedoc.c.





























































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2010 August 28
**
** 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.
**
*************************************************************************
** Code for testing all sorts of SQLite interfaces. This code
** is not included in the SQLite library. 
*/

#include "sqlite3.h"
#if defined(INCLUDE_SQLITE_TCL_H)
#  include "sqlite_tcl.h"
#else
#  include "tcl.h"
#endif

/* Solely for the UNUSED_PARAMETER() macro. */
#include "sqliteInt.h"

#ifdef SQLITE_ENABLE_RTREE

typedef struct BoxGeomCtx BoxGeomCtx;
struct BoxGeomCtx {
  Tcl_Interp *interp;
  Tcl_Obj *pScript;
};

typedef struct BoxQueryCtx BoxQueryCtx;
struct BoxQueryCtx {
  Tcl_Interp *interp;
  Tcl_Obj *pScript;
};

static void testDelUser(void *pCtx){
  BoxGeomCtx *p = (BoxGeomCtx*)pCtx;
  Tcl_EvalObjEx(p->interp, p->pScript, 0);
  Tcl_DecrRefCount(p->pScript);
  sqlite3_free(p);
}

static int invokeTclGeomCb(
  const char *zName, 
  sqlite3_rtree_geometry *p, 
  int nCoord,
  sqlite3_rtree_dbl *aCoord
){
  int rc = SQLITE_OK;
  if( p->pContext ){
    char aPtr[64];
    BoxGeomCtx *pCtx = (BoxGeomCtx*)p->pContext;
    Tcl_Interp *interp = pCtx->interp;
    Tcl_Obj *pScript = 0;
    Tcl_Obj *pParam = 0;
    Tcl_Obj *pCoord = 0;
    int ii;
    Tcl_Obj *pRes;


    pScript = Tcl_DuplicateObj(pCtx->pScript);
    Tcl_IncrRefCount(pScript);
    Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj(zName,-1));

    sqlite3_snprintf(sizeof(aPtr)-1, aPtr, "%p", (void*)p->pContext);
    Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj(aPtr,-1));

    pParam = Tcl_NewObj();
    for(ii=0; ii<p->nParam; ii++){
      Tcl_ListObjAppendElement(
          interp, pParam, Tcl_NewDoubleObj(p->aParam[ii])
      );
    }
    Tcl_ListObjAppendElement(interp, pScript, pParam);

    pCoord = Tcl_NewObj();
    for(ii=0; ii<nCoord; ii++){
      Tcl_ListObjAppendElement(interp, pCoord, Tcl_NewDoubleObj(aCoord[ii]));
    }
    Tcl_ListObjAppendElement(interp, pScript, pCoord);

    sqlite3_snprintf(sizeof(aPtr)-1, aPtr, "%p", (void*)p);
    Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj(aPtr,-1));

    rc = Tcl_EvalObjEx(interp, pScript, 0);
    if( rc!=TCL_OK ){
      rc = SQLITE_ERROR;
    }else{
      int nObj = 0;
      Tcl_Obj **aObj = 0;

      pRes = Tcl_GetObjResult(interp);
      if( Tcl_ListObjGetElements(interp, pRes, &nObj, &aObj) ) return TCL_ERROR;
      if( nObj>0 ){
        const char *zCmd = Tcl_GetString(aObj[0]);
        if( 0==sqlite3_stricmp(zCmd, "zero") ){
          p->aParam[0] = 0.0;
          p->nParam = 1;
        }
        else if( 0==sqlite3_stricmp(zCmd, "user") ){
          if( p->pUser || p->xDelUser ){
            rc = SQLITE_ERROR;
          }else{
            BoxGeomCtx *pBGCtx = sqlite3_malloc(sizeof(BoxGeomCtx));
            if( pBGCtx==0 ){
              rc = SQLITE_NOMEM;
            }else{
              pBGCtx->interp = interp;
              pBGCtx->pScript = Tcl_DuplicateObj(pRes);
              Tcl_IncrRefCount(pBGCtx->pScript);
              Tcl_ListObjReplace(interp, pBGCtx->pScript, 0, 1, 0, 0);
              p->pUser = (void*)pBGCtx;
              p->xDelUser = testDelUser;
            }
          }
        }
        else if( 0==sqlite3_stricmp(zCmd, "user_is_zero") ){
          if( p->pUser || p->xDelUser ) rc = SQLITE_ERROR;
        }
      }
    }
  }
  return rc;
}

/*
# EVIDENCE-OF: R-00693-36727 The legacy xGeom callback is invoked with
# four arguments.

# EVIDENCE-OF: R-50437-53270 The first argument is a pointer to an
# sqlite3_rtree_geometry structure which provides information about how
# the SQL function was invoked.

# EVIDENCE-OF: R-00090-24248 The third argument, aCoord[], is an array
# of nCoord coordinates that defines a bounding box to be tested.

# EVIDENCE-OF: R-28207-40885 The last argument is a pointer into which
# the callback result should be written.

*/
static int box_geom(
  sqlite3_rtree_geometry *p,      /* R-50437-53270 */
  int nCoord,                     /* R-02424-24769 */
  sqlite3_rtree_dbl *aCoord,      /* R-00090-24248 */
  int *pRes                       /* R-28207-40885 */
){
  int ii;

  if( p->nParam!=nCoord ){
    invokeTclGeomCb("box", p, nCoord, aCoord);
    return SQLITE_ERROR;
  }
  if( invokeTclGeomCb("box", p, nCoord, aCoord) ) return SQLITE_ERROR;

  for(ii=0; ii<nCoord; ii+=2){
    if( aCoord[ii]>p->aParam[ii+1] || aCoord[ii+1]<p->aParam[ii] ){
      /* R-28207-40885 */
      *pRes = 0;
      return SQLITE_OK;
    }
  }

  /* R-28207-40885 */
  *pRes = 1;

  return SQLITE_OK;
}

static int SQLITE_TCLAPI register_box_geom(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
  extern const char *sqlite3ErrName(int);
  sqlite3 *db;
  BoxGeomCtx *pCtx;
  char aPtr[64];

  if( objc!=3 ){
    Tcl_WrongNumArgs(interp, 1, objv, "DB SCRIPT");
    return TCL_ERROR;
  }
  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;

  pCtx = (BoxGeomCtx*)ckalloc(sizeof(BoxGeomCtx*));
  pCtx->interp = interp;
  pCtx->pScript = Tcl_DuplicateObj(objv[2]);
  Tcl_IncrRefCount(pCtx->pScript);

  sqlite3_rtree_geometry_callback(db, "box", box_geom, (void*)pCtx);

  sqlite3_snprintf(64, aPtr, "%p", (void*)pCtx);
  Tcl_SetObjResult(interp, Tcl_NewStringObj(aPtr, -1));
  return TCL_OK;
}

static int box_query(sqlite3_rtree_query_info *pInfo){
  const char *azParentWithin[] = {"not", "partly", "fully", 0};
  BoxQueryCtx *pCtx = (BoxQueryCtx*)pInfo->pContext;
  Tcl_Interp *interp = pCtx->interp;
  Tcl_Obj *pEval;
  Tcl_Obj *pArg;
  Tcl_Obj *pTmp = 0;
  int rc;
  int ii;

  pEval = Tcl_DuplicateObj(pCtx->pScript);
  Tcl_IncrRefCount(pEval);
  pArg = Tcl_NewObj();
  Tcl_IncrRefCount(pArg);

  /* aParam[] */
  pTmp = Tcl_NewObj();
  Tcl_IncrRefCount(pTmp);
  for(ii=0; ii<pInfo->nParam; ii++){
    Tcl_Obj *p = Tcl_NewDoubleObj(pInfo->aParam[ii]);
    Tcl_ListObjAppendElement(interp, pTmp, p);
  }
  Tcl_ListObjAppendElement(interp, pArg, Tcl_NewStringObj("aParam", -1));
  Tcl_ListObjAppendElement(interp, pArg, pTmp);
  Tcl_DecrRefCount(pTmp);

  /* aCoord[] */
  pTmp = Tcl_NewObj();
  Tcl_IncrRefCount(pTmp);
  for(ii=0; ii<pInfo->nCoord; ii++){
    Tcl_Obj *p = Tcl_NewDoubleObj(pInfo->aCoord[ii]);
    Tcl_ListObjAppendElement(interp, pTmp, p);
  }
  Tcl_ListObjAppendElement(interp, pArg, Tcl_NewStringObj("aCoord", -1));
  Tcl_ListObjAppendElement(interp, pArg, pTmp);
  Tcl_DecrRefCount(pTmp);

  /* anQueue[] */
  pTmp = Tcl_NewObj();
  Tcl_IncrRefCount(pTmp);
  for(ii=0; ii<=pInfo->mxLevel; ii++){
    Tcl_Obj *p = Tcl_NewIntObj((int)pInfo->anQueue[ii]);
    Tcl_ListObjAppendElement(interp, pTmp, p);
  }
  Tcl_ListObjAppendElement(interp, pArg, Tcl_NewStringObj("anQueue", -1));
  Tcl_ListObjAppendElement(interp, pArg, pTmp);
  Tcl_DecrRefCount(pTmp);
  
  /* iLevel */
  Tcl_ListObjAppendElement(interp, pArg, Tcl_NewStringObj("iLevel", -1));
  Tcl_ListObjAppendElement(interp, pArg, Tcl_NewIntObj(pInfo->iLevel));

  /* mxLevel */
  Tcl_ListObjAppendElement(interp, pArg, Tcl_NewStringObj("mxLevel", -1));
  Tcl_ListObjAppendElement(interp, pArg, Tcl_NewIntObj(pInfo->mxLevel));

  /* iRowid */
  Tcl_ListObjAppendElement(interp, pArg, Tcl_NewStringObj("iRowid", -1));
  Tcl_ListObjAppendElement(interp, pArg, Tcl_NewWideIntObj(pInfo->iRowid));

  /* rParentScore */
  Tcl_ListObjAppendElement(interp, pArg, Tcl_NewStringObj("rParentScore", -1));
  Tcl_ListObjAppendElement(interp, pArg, Tcl_NewDoubleObj(pInfo->rParentScore));

  /* eParentWithin */
  assert( pInfo->eParentWithin==0 
       || pInfo->eParentWithin==1 
       || pInfo->eParentWithin==2 
  );
  Tcl_ListObjAppendElement(interp, pArg, Tcl_NewStringObj("eParentWithin", -1));
  Tcl_ListObjAppendElement(interp, pArg, 
      Tcl_NewStringObj(azParentWithin[pInfo->eParentWithin], -1)
  );

  Tcl_ListObjAppendElement(interp, pEval, pArg);
  rc = Tcl_EvalObjEx(interp, pEval, 0) ? SQLITE_ERROR : SQLITE_OK;

  if( rc==SQLITE_OK ){
    double rScore = 0.0;
    int nObj = 0;
    int eP = 0;
    Tcl_Obj **aObj = 0;
    Tcl_Obj *pRes = Tcl_GetObjResult(interp);

    if( Tcl_ListObjGetElements(interp, pRes, &nObj, &aObj) 
     || nObj!=2 
     || Tcl_GetDoubleFromObj(interp, aObj[1], &rScore)
     || Tcl_GetIndexFromObj(interp, aObj[0], azParentWithin, "value", 0, &eP)
    ){
      rc = SQLITE_ERROR;
    }else{
      pInfo->rScore = rScore;
      pInfo->eParentWithin = eP;
    }
  }

  Tcl_DecrRefCount(pArg);
  Tcl_DecrRefCount(pEval);
  return rc;
}

static void box_query_destroy(void *p){
  BoxQueryCtx *pCtx = (BoxQueryCtx*)p;
  Tcl_DecrRefCount(pCtx->pScript);
  ckfree((char*)pCtx);
}

static int SQLITE_TCLAPI register_box_query(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
  extern const char *sqlite3ErrName(int);
  sqlite3 *db;
  BoxQueryCtx *pCtx;

  if( objc!=3 ){
    Tcl_WrongNumArgs(interp, 1, objv, "DB SCRIPT");
    return TCL_ERROR;
  }
  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;

  pCtx = (BoxQueryCtx*)ckalloc(sizeof(BoxQueryCtx));
  pCtx->interp = interp;
  pCtx->pScript = Tcl_DuplicateObj(objv[2]);
  Tcl_IncrRefCount(pCtx->pScript);

  sqlite3_rtree_query_callback(
      db, "qbox", box_query, (void*)pCtx, box_query_destroy
  );

  Tcl_ResetResult(interp);
  return TCL_OK;
}
#endif /* SQLITE_ENABLE_RTREE */


int Sqlitetestrtreedoc_Init(Tcl_Interp *interp){
#ifdef SQLITE_ENABLE_RTREE
  Tcl_CreateObjCommand(interp, "register_box_geom", register_box_geom, 0, 0);
  Tcl_CreateObjCommand(interp, "register_box_query", register_box_query, 0, 0);
#endif /* SQLITE_ENABLE_RTREE */
  return TCL_OK;
}

Changes to ext/session/changeset.c.

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







-
+







-
+

-
+


-
+



-
-
+
+
+




-
+







}

/*
** Read the content of a disk file into an in-memory buffer
*/
static void readFile(const char *zFilename, int *pSz, void **ppBuf){
  FILE *f;
  int sz;
  sqlite3_int64 sz;
  void *pBuf;
  f = fopen(zFilename, "rb");
  if( f==0 ){
    fprintf(stderr, "cannot open \"%s\" for reading\n", zFilename);
    exit(1);
  }
  fseek(f, 0, SEEK_END);
  sz = (int)ftell(f);
  sz = ftell(f);
  rewind(f);
  pBuf = sqlite3_malloc( sz ? sz : 1 );
  pBuf = sqlite3_malloc64( sz ? sz : 1 );
  if( pBuf==0 ){
    fprintf(stderr, "cannot allocate %d to hold content of \"%s\"\n",
            sz, zFilename);
            (int)sz, zFilename);
    exit(1);
  }
  if( sz>0 ){
    if( fread(pBuf, sz, 1, f)!=1 ){
      fprintf(stderr, "cannot read all %d bytes of \"%s\"\n", sz, zFilename);
    if( fread(pBuf, (size_t)sz, 1, f)!=1 ){
      fprintf(stderr, "cannot read all %d bytes of \"%s\"\n",
              (int)sz, zFilename);
      exit(1);
    }
    fclose(f);
  }
  *pSz = sz;
  *pSz = (int)sz;
  *ppBuf = pBuf;
}

/* Array for converting from half-bytes (nybbles) into ASCII hex
** digits. */
static const char hexdigits[] = {
  '0', '1', '2', '3', '4', '5', '6', '7',

Changes to ext/session/changesetfuzz.c.

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







-
+







-
+

-
+


-
+



-
-
+
+
+




-
+







}

/*
** Read the content of a disk file into an in-memory buffer
*/
static void fuzzReadFile(const char *zFilename, int *pSz, void **ppBuf){
  FILE *f;
  int sz;
  sqlite3_int64 sz;
  void *pBuf;
  f = fopen(zFilename, "rb");
  if( f==0 ){
    fprintf(stderr, "cannot open \"%s\" for reading\n", zFilename);
    exit(1);
  }
  fseek(f, 0, SEEK_END);
  sz = (int)ftell(f);
  sz = ftell(f);
  rewind(f);
  pBuf = sqlite3_malloc( sz ? sz : 1 );
  pBuf = sqlite3_malloc64( sz ? sz : 1 );
  if( pBuf==0 ){
    fprintf(stderr, "cannot allocate %d to hold content of \"%s\"\n",
            sz, zFilename);
            (int)sz, zFilename);
    exit(1);
  }
  if( sz>0 ){
    if( fread(pBuf, sz, 1, f)!=1 ){
      fprintf(stderr, "cannot read all %d bytes of \"%s\"\n", sz, zFilename);
    if( fread(pBuf, (size_t)sz, 1, f)!=1 ){
      fprintf(stderr, "cannot read all %d bytes of \"%s\"\n",
              (int)sz, zFilename);
      exit(1);
    }
    fclose(f);
  }
  *pSz = sz;
  *pSz = (int)sz;
  *ppBuf = pBuf;
}

/* 
** Write the contents of buffer pBuf, size nBuf bytes, into file zFilename
** on disk. zFilename, if it already exists, is clobbered.
*/
336
337
338
339
340
341
342
343
344


345
346

347
348
349
350
351
352
353
337
338
339
340
341
342
343


344
345
346

347
348
349
350
351
352
353
354







-
-
+
+

-
+







  u8 aSub[128];                   /* Buffer for substitute value */
  int iCurrent;                   /* Current change number */
};

/*
** Allocate and return nByte bytes of zeroed memory.
*/
static void *fuzzMalloc(int nByte){
  void *pRet = sqlite3_malloc(nByte);
static void *fuzzMalloc(sqlite3_int64 nByte){
  void *pRet = sqlite3_malloc64(nByte);
  if( pRet ){
    memset(pRet, 0, nByte);
    memset(pRet, 0, (size_t)nByte);
  }
  return pRet;
}

/*
** Free the buffer indicated by the first argument. This function is used
** to free buffers allocated by fuzzMalloc().
380
381
382
383
384
385
386
387

388
389
390
391
392
393
394
381
382
383
384
385
386
387

388
389
390
391
392
393
394
395







-
+







** Write value nVal into the buffer indicated by argument p as an SQLite
** varint. nVal is guaranteed to be between 0 and (2^21-1), inclusive.
** Return the number of bytes written to buffer p.
*/
static int fuzzPutVarint(u8 *p, int nVal){
  assert( nVal>0 && nVal<2097152 );
  if( nVal<128 ){
    p[0] = nVal;
    p[0] = (u8)nVal;
    return 1;
  }
  if( nVal<16384 ){
    p[0] = ((nVal >> 7) & 0x7F) | 0x80;
    p[1] = (nVal & 0x7F);
    return 2;
  }
455
456
457
458
459
460
461
462

463
464
465
466
467
468
469
456
457
458
459
460
461
462

463
464
465
466
467
468
469
470







-
+







      rc = fuzzCorrupt();
    }else{
      p++;
      p += fuzzGetVarint(p, &pGrp->nCol);
      pGrp->aPK = p;
      p += pGrp->nCol;
      pGrp->zTab = (const char*)p;
      p = &p[strlen(p)+1];
      p = &p[strlen((const char*)p)+1];

      if( p>=pEnd ){
        rc = fuzzCorrupt();
      }
    }
    *ppHdr = p;
  }
627
628
629
630
631
632
633
634

635
636
637
638
639
640
641
628
629
630
631
632
633
634

635
636
637
638
639
640
641
642







-
+







    /* Read a table-header from the changeset */
    rc = fuzzParseHeader(pParse, &p, pEnd, &pGrp);
    assert( (rc==SQLITE_OK)==(pGrp!=0) );

    /* If the table-header was successfully parsed, add the new change-group
    ** to the array and parse the associated changes. */
    if( rc==SQLITE_OK ){
      FuzzChangesetGroup **apNew = (FuzzChangesetGroup**)sqlite3_realloc(
      FuzzChangesetGroup **apNew = (FuzzChangesetGroup**)sqlite3_realloc64(
          pParse->apGroup, sizeof(FuzzChangesetGroup*)*(pParse->nGroup+1)
      );
      if( apNew==0 ){
        rc = SQLITE_NOMEM;
      }else{
        apNew[pParse->nGroup] = pGrp;
        pParse->apGroup = apNew;
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
692
693
694
695
696
697
698


699
700
701
702
703
704
705







-
-







          p += 8;
          break;
        }

        case 0x03:                    /* text */
        case 0x04: {                  /* blob */
          int nTxt;
          int sz;
          int i;
          p += fuzzGetVarint(p, &nTxt);
          printf("%s%s", zPre, eType==0x03 ? "'" : "X'");
          for(i=0; i<nTxt; i++){
            if( eType==0x03 ){
              printf("%c", p[i]);
            }else{
              char aHex[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
855
856
857
858
859
860
861
862

863
864
865
866
867
868
869
854
855
856
857
858
859
860

861
862
863
864
865
866
867
868







-
+







          fuzzPutU64(&pChange->aSub[1], iVal1);
          break;
        }

        case 0x03:                    /* text */
        case 0x04: {                  /* blob */
          int nByte = fuzzRandomInt(48);
          pChange->aSub[1] = nByte;
          pChange->aSub[1] = (u8)nByte;
          fuzzRandomBlob(nByte, &pChange->aSub[2]);
          if( pChange->aSub[0]==0x03 ){
            int i;
            for(i=0; i<nByte; i++){
              pChange->aSub[2+i] &= 0x7F;
            }
          }
1000
1001
1002
1003
1004
1005
1006
1007

1008
1009
1010
1011
1012
1013
1014
999
1000
1001
1002
1003
1004
1005

1006
1007
1008
1009
1010
1011
1012
1013







-
+







      }

      if( p==pFuzz->pSub1 ){
        pCopy = pFuzz->pSub2;
      }else if( p==pFuzz->pSub2 ){
        pCopy = pFuzz->pSub1;
      }else if( i==iUndef ){
        pCopy = "\0";
        pCopy = (u8*)"\0";
      }

      if( pCopy[0]==0x00 && eNew!=eType && eType==SQLITE_UPDATE && iRec==0 ){
        while( pCopy[0]==0x00 ){
          pCopy = pParse->apVal[fuzzRandomInt(pParse->nVal)];
        }
      }else if( p[0]==0x00 && pCopy[0]!=0x00 ){
1063
1064
1065
1066
1067
1068
1069
1070

1071
1072
1073
1074
1075
1076
1077
1062
1063
1064
1065
1066
1067
1068

1069
1070
1071
1072
1073
1074
1075
1076







-
+







    }
    if( eNew!=eType && eNew==SQLITE_UPDATE && !bPS ){
      int i;
      u8 *pCsr = (*ppOut) + 2;
      for(i=0; i<pGrp->nCol; i++){
        int sz;
        u8 *pCopy = pCsr;
        if( pGrp->aPK[i] ) pCopy = "\0";
        if( pGrp->aPK[i] ) pCopy = (u8*)"\0";
        fuzzChangeSize(pCopy, &sz);
        memcpy(pOut, pCopy, sz);
        pOut += sz;
        fuzzChangeSize(pCsr, &sz);
        pCsr += sz;
      }
    }
1210
1211
1212
1213
1214
1215
1216
1217

1218
1219
1220
1221
1222
1223
1224
1209
1210
1211
1212
1213
1214
1215

1216
1217
1218
1219
1220
1221
1222
1223







-
+








  if( rc==SQLITE_OK ){
    if( argc==2 ){
      for(i=0; i<changeset.nGroup; i++){
        fuzzPrintGroup(&changeset, changeset.apGroup[i]);
      }
    }else{
      pBuf = (u8*)fuzzMalloc(nChangeset*2 + 1024);
      pBuf = (u8*)fuzzMalloc((sqlite3_int64)nChangeset*2 + 1024);
      if( pBuf==0 ){
        rc = SQLITE_NOMEM;
      }else{
        iSeed = atoi(argv[2]);
        nRepeat = atoi(argv[3]);
        fuzzRandomSeed((unsigned int)iSeed);
        for(i=0; rc==SQLITE_OK && i<nRepeat; i++){
1233
1234
1235
1236
1237
1238
1239
1240
1232
1233
1234
1235
1236
1237
1238








-

  if( rc!=SQLITE_OK ){
    fprintf(stderr, "error while processing changeset: %d\n", rc);
  }

  return rc;
}

Changes to ext/session/session1.test.

148
149
150
151
152
153
154




















155
156
157
158
159
160
161
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







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







  execsql { INSERT INTO t1 VALUES(100, 'Bangkok') }
  execsql { DELETE FROM t1 WHERE x = 100 }
} {}
do_changeset_test $tn.2.4.2 S {}
do_changeset_invert_test $tn.2.4.3 S {}
do_test $tn.2.4.4 { S delete } {}

do_execsql_test $tn.2.5.0 {
  SELECT * FROM t1 ORDER BY x
} {
  2  Surin
  10 Sukhothai
  20 Thapae
}

do_test $tn.2.5.1 {
  sqlite3session S db main
  S attach t1
  execsql { DELETE FROM t1 }
} {}
do_changeset_test $tn.2.5.2 S {
  {DELETE t1 0 X. {i 10 t Sukhothai} {}} 
  {DELETE t1 0 X. {i 2 t Surin} {}}
  {DELETE t1 0 X. {i 20 t Thapae} {}}
}
do_test $tn.2.5.3 { S delete } {}

#-------------------------------------------------------------------------
# Test the application of simple changesets. These tests also test that
# the conflict callback is invoked correctly. For these tests, the 
# conflict callback always returns OMIT.
#
db close
forcedelete test.db test.db2

Changes to ext/session/session2.test.

31
32
33
34
35
36
37
38

39
40
41
42
43
44
45
31
32
33
34
35
36
37

38
39
40
41
42
43
44
45







-
+








##########################################################################
# End of proc definitions. Start of tests.
##########################################################################

test_reset
do_execsql_test 1.0 { 
  CREATE TABLE t1(a PRIMARY KEY, b);
  CREATE TABLE t1(a INT PRIMARY KEY, b);
  INSERT INTO t1 VALUES('i', 'one');
}
do_iterator_test 1.1 t1 {
  DELETE FROM t1 WHERE a = 'i';
  INSERT INTO t1 VALUES('ii', 'two');
} {
  {DELETE t1 0 X. {t i t one} {}} 
180
181
182
183
184
185
186
187

188
189
190
191
192
193
194
180
181
182
183
184
185
186

187
188
189
190
191
192
193
194







-
+







    DELETE FROM t1;
    INSERT INTO t1 VALUES('', NULL);
  }
}

test_reset
do_common_sql {
  CREATE TABLE t1(a PRIMARY KEY, b);
  CREATE TABLE t1(a int PRIMARY KEY, b);
  CREATE TABLE t2(a, b INTEGER PRIMARY KEY);
  CREATE TABLE t3(a, b, c, PRIMARY KEY(a, b));
  CREATE TABLE t4(a, b, PRIMARY KEY(b, a));
}

foreach {tn sql} [string map {%T1% t1 %T2% t2 %T3% t3 %T4% t4} $set_of_tests] {
  do_then_apply_sql $sql
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
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







-
+



-
+





-
+







#
test_reset
forcedelete test.db3
sqlite3 db3 test.db3
do_test 3.0 {
  execsql {
    ATTACH 'test.db3' AS 'aux';
    CREATE TABLE t1(a, b PRIMARY KEY);
    CREATE TABLE t1(a int, b PRIMARY KEY);
    CREATE TABLE t2(x, y, z);
    CREATE TABLE t3(a);

    CREATE TABLE aux.t1(a PRIMARY KEY, b);
    CREATE TABLE aux.t1(a int PRIMARY KEY, b);
    CREATE TABLE aux.t2(a, b INTEGER PRIMARY KEY);
    CREATE TABLE aux.t3(a, b, c, PRIMARY KEY(a, b));
    CREATE TABLE aux.t4(a, b, PRIMARY KEY(b, a));
  }
  execsql {
    CREATE TABLE t1(a PRIMARY KEY, b);
    CREATE TABLE t1(a int PRIMARY KEY, b);
    CREATE TABLE t2(a, b INTEGER PRIMARY KEY);
    CREATE TABLE t3(a, b, c, PRIMARY KEY(a, b));
    CREATE TABLE t4(a, b, PRIMARY KEY(b, a));
  } db2
} {}

proc xTrace {args} { puts $args }
583
584
585
586
587
588
589
590
















































591
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639








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

do_execsql_test 10.2 {
  SELECT enable(0);
  SELECT enable(-1);
  SELECT enable(1);
  SELECT enable(-1);
} {0 0 1 1}
S delete

#-------------------------------------------------------------------------
test_reset
do_common_sql {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d, e, f);
  WITH s(i) AS (
    SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<32
  )
  INSERT INTO t1 SELECT NULL, 0, 0, 0, 0, 0 FROM s
}

do_then_apply_sql {
  UPDATE t1 SET                             f=f+1 WHERE a=1;
  UPDATE t1 SET                      e=e+1        WHERE a=2;
  UPDATE t1 SET                      e=e+1, f=f+1 WHERE a=3;
  UPDATE t1 SET               d=d+1               WHERE a=4;
  UPDATE t1 SET               d=d+1,        f=f+1 WHERE a=5;
  UPDATE t1 SET               d=d+1, e=e+1        WHERE a=6;
  UPDATE t1 SET               d=d+1, e=e+1, f=f+1 WHERE a=7;
  UPDATE t1 SET        c=c+1                      WHERE a=8;
  UPDATE t1 SET        c=c+1,               f=f+1 WHERE a=9;
  UPDATE t1 SET        c=c+1,        e=e+1        WHERE a=10;
  UPDATE t1 SET        c=c+1,        e=e+1, f=f+1 WHERE a=11;
  UPDATE t1 SET        c=c+1, d=d+1               WHERE a=12;
  UPDATE t1 SET        c=c+1, d=d+1,        f=f+1 WHERE a=13;
  UPDATE t1 SET        c=c+1, d=d+1, e=e+1        WHERE a=14;
  UPDATE t1 SET        c=c+1, d=d+1, e=e+1, f=f+1 WHERE a=15;
  UPDATE t1 SET d=d+1                             WHERE a=16;
  UPDATE t1 SET d=d+1,                      f=f+1 WHERE a=17;
  UPDATE t1 SET d=d+1,               e=e+1        WHERE a=18;
  UPDATE t1 SET d=d+1,               e=e+1, f=f+1 WHERE a=19;
  UPDATE t1 SET d=d+1,        d=d+1               WHERE a=20;
  UPDATE t1 SET d=d+1,        d=d+1,        f=f+1 WHERE a=21;
  UPDATE t1 SET d=d+1,        d=d+1, e=e+1        WHERE a=22;
  UPDATE t1 SET d=d+1,        d=d+1, e=e+1, f=f+1 WHERE a=23;
  UPDATE t1 SET d=d+1, c=c+1                      WHERE a=24;
  UPDATE t1 SET d=d+1, c=c+1,               f=f+1 WHERE a=25;
  UPDATE t1 SET d=d+1, c=c+1,        e=e+1        WHERE a=26;
  UPDATE t1 SET d=d+1, c=c+1,        e=e+1, f=f+1 WHERE a=27;
  UPDATE t1 SET d=d+1, c=c+1, d=d+1               WHERE a=28;
  UPDATE t1 SET d=d+1, c=c+1, d=d+1,        f=f+1 WHERE a=29;
  UPDATE t1 SET d=d+1, c=c+1, d=d+1, e=e+1        WHERE a=30;
  UPDATE t1 SET d=d+1, c=c+1, d=d+1, e=e+1, f=f+1 WHERE a=31;
}

do_test 11.0 {
  compare_db db db2
} {}

finish_test

Changes to ext/session/session6.test.

15
16
17
18
19
20
21

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







+








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}
ifcapable !incrblob {finish_test; return}

set testprefix session6

proc do_then_apply_tcl {tcl {dbname main}} {
  proc xConflict args { return "OMIT" }
  set rc [catch {
    sqlite3session S db $dbname

Changes to ext/session/session8.test.

59
60
61
62
63
64
65
66

67
68
69
70
71
72
73
59
60
61
62
63
64
65

66
67
68
69
70
71
72
73







-
+







  uplevel [list do_test $tn.1 "set {} $a" 0]
  uplevel [list do_test $tn.2 "set {} $b" 1]
}

do_execsql_test 1.1 {
  CREATE TABLE t1(a PRIMARY KEY, b);
  INSERT INTO t1 VALUES(1, 2);
  INSERT INTO t1 VALUES("abc", "xyz");
  INSERT INTO t1 VALUES('abc', 'xyz');
}
do_then_undo 1.2 { INSERT INTO t1 VALUES(3, 4); }
do_then_undo 1.3 { DELETE FROM t1 WHERE b=2; }
do_then_undo 1.4 { UPDATE t1 SET b = 3 WHERE a = 1; }

do_execsql_test 2.1 {
  CREATE TABLE t2(a, b PRIMARY KEY);

Changes to ext/session/sessionB.test.

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







-
+
-







}

# INSERT + DELETE 
do_patchconcat_test 4.3.3 {
  INSERT INTO t2 VALUES('a', 'a', 'a', 'a');
} {
  DELETE FROM t2 WHERE c = 'a';
} {
} {}
}

# INSERT + UPDATE
do_patchconcat_test 4.3.4 {
  INSERT INTO t2 VALUES('a', 'a', 'a', 'a');
} {
  UPDATE t2 SET d = 'b' WHERE c='a';
} {

Changes to ext/session/sessionH.test.

25
26
27
28
29
30
31
32

33
34
35














































36
37
38
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







-
+



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



  do_common_sql {
    CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b));
  }
  do_then_apply_sql {
    WITH s(i) AS (
      VALUES(1) UNION ALL SELECT i+1 FROM s WHERe i<10000
    )
    INSERT INTO t1 SELECT 'abcde', randomblob(16), i FROM s;
    INSERT INTO t1 SELECT 'abcde', randomblob(18), i FROM s;
  }
  compare_db db db2
} {}

#------------------------------------------------------------------------
db2 close
reset_db

do_execsql_test 2.0 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
  INSERT INTO main.t1 VALUES(1, 2, 3), (4, 5, 6), (7, 8, 9);
}

do_test 2.1 {
  sqlite3session S db main
  S attach *
  db eval {
    BEGIN;
      INSERT INTO t1 VALUES(10, 11, 12);
      DELETE FROM t1 WHERE a=1;
      UPDATE t1 SET b='five', c='six' WHERE a=4;
  }

  set C [S changeset]
  db eval ROLLBACK
  S delete
  set {} {}
} {}

do_execsql_test 2.2 {
  CREATE TEMP TABLE t1(a INTEGER PRIMARY KEY, b, c);
  INSERT INTO temp.t1 VALUES(1, 2, 3), (4, 5, 6), (7, 8, 9);
}

set ::conflict [list]
proc xConflict {args} { lappend ::conflict $args ; return "" }
do_test 2.3 {
  sqlite3changeset_apply db $C xConflict
  set ::conflict
} {}
do_execsql_test 2.4 {
  SELECT * FROM main.t1;
  SELECT '****';
  SELECT * FROM temp.t1;
} {
  4 five six 7 8 9 10 11 12
  ****
  1 2 3 4 5 6 7 8 9
}


finish_test

Changes to ext/session/session_common.tcl.

168
169
170
171
172
173
174
175
176


177
178
179
180
181
182
183
168
169
170
171
172
173
174


175
176
177
178
179
180
181
182
183







-
-
+
+







    $db2 eval "PRAGMA table_info = $tbl" { lappend col2 $name }
    if {$col1 != $col2} { error "table $tbl schema mismatch" }

    set sql "SELECT * FROM $tbl ORDER BY [join $col1 ,]"
    set data1 [$db1 eval $sql]
    set data2 [$db2 eval $sql]
    if {$data1 != $data2} { 
      puts "$data1"
      puts "$data2"
      puts "$db1: $data1"
      puts "$db2: $data2"
      error "table $tbl data mismatch" 
    }
  }

  return ""
}

Changes to ext/session/session_speed_test.c.

352
353
354
355
356
357
358
359
360
352
353
354
355
356
357
358









-
-
      }
    }
  }


  return 0;
}


Changes to ext/session/sessionat.test.

16
17
18
19
20
21
22

23


24



25
26
27
28
29
30
31
16
17
18
19
20
21
22
23
24
25
26

27
28
29
30
31
32
33
34
35
36







+

+
+
-
+
+
+








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 sessionat

# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
ifcapable !altertable {
set testprefix sessionat
  finish_test
  return
}

db close
sqlite3_shutdown
test_sqlite3_log log
proc log {code msg} { lappend ::log $code $msg }

proc reset_test {} {
234
235
236
237
238
239
240






















































241
242
243
244
245
246
247
248
249
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







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









  }

  proc xConfict {args} { return "OMIT" }
  do_test $tn.6.3 {
    sqlite3changeset_apply db $cinv xConflict
    execsql { SELECT * FROM t7 }
  } {1 1 ccc 2 2 ccc 3 3 ccc}

  #-----------------------------------------------------------------------
  reset_test
  do_execsql_test $tn.7.0 {
    CREATE TABLE t8(a PRIMARY KEY, b, c);
  }
  do_execsql_test -db db2 $tn.7.1 {
    CREATE TABLE t8(a PRIMARY KEY, b, c, d DEFAULT 'D', e DEFAULT 'E');
  }

  do_then_apply_sql {
    INSERT INTO t8 VALUES(1, 2, 3);
    INSERT INTO t8 VALUES(4, 5, 6);
  }
  do_execsql_test $tn.7.2.1 {
    SELECT * FROM t8
  } {1 2 3    4 5 6}
  do_execsql_test -db db2 $tn.7.2.2 {
    SELECT * FROM t8
  } {1 2 3 D E   4 5 6 D E}

  do_then_apply_sql {
    UPDATE t8 SET c=45 WHERE a=4;
  }
  do_execsql_test $tn.7.3.1 {
    SELECT * FROM t8
  } {1 2 3    4 5 45}
  do_execsql_test -db db2 $tn.7.3.2 {
    SELECT * FROM t8
  } {1 2 3 D E   4 5 45 D E}

  #-----------------------------------------------------------------------
  reset_test
  do_execsql_test $tn.8.0 {
    CREATE TABLE t9(a PRIMARY KEY, b, c, d, e, f, g, h);
  }
  do_execsql_test -db db2 $tn.8.1 {
    CREATE TABLE t9(a PRIMARY KEY, b, c, d, e, f, g, h, i, j, k, l);
  }
  do_then_apply_sql {
    INSERT INTO t9 VALUES(1, 2, 3, 4, 5, 6, 7, 8);
  }
  do_then_apply_sql {
    UPDATE t9 SET h=450 WHERE a=1
  }
  do_execsql_test -db db2 $tn.8.2 {
    SELECT * FROM t9
  } {1 2 3 4 5 6 7 450 {} {} {} {}}
  do_then_apply_sql {
    UPDATE t9 SET h=NULL
  }
  do_execsql_test -db db2 $tn.8.2 {
    SELECT * FROM t9
  } {1 2 3 4 5 6 7 {} {} {} {} {}}
}]
}

catch { db close }
catch { db2 close }
sqlite3_shutdown
test_sqlite3_log

finish_test

Added ext/session/sessionbig.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2014 August 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 sessions SQLite extension.
# Specifically, this file contains tests for "patchset" changes.
#

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}

if {[permutation]=="session_strm" || [permutation]=="session_eec"} {
  finish_test
  return
}

if {$::tcl_platform(pointerSize)<8} {
  finish_test
  return
}

set testprefix sessionbig

forcedelete test.db2
sqlite3 db2 test.db2

do_execsql_test 1.0 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
}
do_execsql_test -db db2 1.1 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
}

do_test 1.2 {
  do_then_apply_sql {
    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );

    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );

    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
  }
} {}

do_test 1.3 {
  execsql { DELETE FROM t1 }
  execsql2 { DELETE FROM t1 }
} {}

do_test 1.4 {
  set rc [catch {
  do_then_apply_sql {
    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );

    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );

    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );

    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );

    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
    INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
  }
  } msg]
  list $rc $msg
} {1 SQLITE_NOMEM}


finish_test

Changes to ext/session/sessioninvert.test.

150
151
152
153
154
155
156
























157
158
159
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







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



  list [catch { sqlite3session_foreach -invert db2 $P {} } msg] $msg
} {1 SQLITE_CORRUPT}

do_test 3.2 {
  sqlite3changeset_apply_v2 db2 $P {} 
  compare_db db db2
} {}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 4.0 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b UNIQUE);
  INSERT INTO t1 VALUES(1, 'one');
  INSERT INTO t1 VALUES(2, 'two');
  INSERT INTO t1 VALUES(3, 'three');
  INSERT INTO t1 VALUES(4, 'four');
}

do_invert_test 4.1 {
  DELETE FROM t1;
  INSERT INTO t1 VALUES(1, 'two');
  INSERT INTO t1 VALUES(2, 'five');
  INSERT INTO t1 VALUES(3, 'one');
  INSERT INTO t1 VALUES(4, 'three');
} {
  {UPDATE t1 0 X. {i 1 t two} {{} {} t one}}
  {UPDATE t1 0 X. {i 2 t five} {{} {} t two}}
  {UPDATE t1 0 X. {i 3 t one} {{} {} t three}} 
  {UPDATE t1 0 X. {i 4 t three} {{} {} t four}}
}


finish_test

Added ext/session/sessionmem.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2020 December 23
#
# 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 the SQLite sessions module
# Specifically, for the sqlite3session_memory_used() API.
#

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 sessionmem

do_execsql_test 1.0 {
  CREATE TABLE t1(i INTEGER PRIMARY KEY, x, y);
  CREATE TABLE t2(i INTEGER, x, y, PRIMARY KEY(x, y));
}

do_test 1.1 {
  sqlite3session S db main
  S attach *
} {}

foreach {tn sql eRes} {
  1 { INSERT INTO t1 VALUES(1, 2, 3) } 1
  2 { UPDATE t1 SET x=5 }                    0
  3 { UPDATE t1 SET i=5 }                    1
  4 { DELETE FROM t1 }                       0
  5 { INSERT INTO t1 VALUES(1, 2, 3) }       0
  6 { INSERT INTO t1 VALUES(5, 2, 3) }       0
  7 { INSERT INTO t2 VALUES('a', 'b', 'c') } 1
  8 { INSERT INTO t2 VALUES('d', 'e', 'f') } 1
  9 { UPDATE t2 SET i='e' }                  0
} {
  set mem1 [S memory_used]
  do_test 1.2.$tn.(mu=$mem1) {
    execsql $sql
    set mem2 [S memory_used]
    expr {$mem2 > $mem1}
  } $eRes
}

do_test 1.3 {
  S delete
} {}

finish_test

Added ext/session/sessionnoop.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2021 Februar 20
#
# 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 sessionnoop

#-------------------------------------------------------------------------
# Test plan:
#
#   1.*: Test that concatenating changesets cannot produce a noop UPDATE.
#   2.*: Test that rebasing changesets cannot produce a noop UPDATE.
#   3.*: Test that sqlite3changeset_apply() ignores noop UPDATE changes.
#

do_execsql_test 1.0 {
  CREATE TABLE t1(a PRIMARY KEY, b, c, d);
  INSERT INTO t1 VALUES(1, 1, 1, 1);
  INSERT INTO t1 VALUES(2, 2, 2, 2);
  INSERT INTO t1 VALUES(3, 3, 3, 3);
}

proc do_concat_test {tn sql1 sql2 res} {
  uplevel [list do_test $tn [subst -nocommands {
    set C1 [changeset_from_sql {$sql1}]
    set C2 [changeset_from_sql {$sql2}]
    set C3 [sqlite3changeset_concat [set C1] [set C2]]
    set got [list]
    sqlite3session_foreach elem [set C3] { lappend got [set elem] }
    set got
  }] [list {*}$res]]
}

do_concat_test 1.1 {
  UPDATE t1 SET c=c+1;
} {
  UPDATE t1 SET c=c-1;
} {
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.0 {
  CREATE TABLE t1(a PRIMARY KEY, b, c);
  INSERT INTO t1 VALUES(1, 1, 1);
  INSERT INTO t1 VALUES(2, 2, 2);
  INSERT INTO t1 VALUES(3, 3, 3);
}

proc do_rebase_test {tn sql_local sql_remote conflict_res expected} {
  proc xConflict {args} [list return $conflict_res]

  uplevel [list \
    do_test $tn [subst -nocommands {
      execsql BEGIN
        set c_remote [changeset_from_sql {$sql_remote}]
      execsql ROLLBACK

      execsql BEGIN
        set c_local [changeset_from_sql {$sql_local}]
        set base [sqlite3changeset_apply_v2 db [set c_remote] xConflict]
      execsql ROLLBACK

      sqlite3rebaser_create R
      R config [set base]
      set res [list]
      sqlite3session_foreach elem [R rebase [set c_local]] { 
        lappend res [set elem] 
      }
      R delete
      set res
    }] [list {*}$expected]
  ]
}

do_rebase_test 2.1 {
  UPDATE t1 SET c=2 WHERE a=1;              -- local
} {
  UPDATE t1 SET c=3 WHERE a=1;              -- remote
} OMIT {
  {UPDATE t1 0 X.. {i 1 {} {} i 3} {{} {} {} {} i 2}}
}

do_rebase_test 2.2 {
  UPDATE t1 SET c=2 WHERE a=1;              -- local
} {
  UPDATE t1 SET c=3 WHERE a=1;              -- remote
} REPLACE {
}

do_rebase_test 2.3.1 {
  UPDATE t1 SET c=4 WHERE a=1;              -- local
} {
  UPDATE t1 SET c=4 WHERE a=1               -- remote
} OMIT {
  {UPDATE t1 0 X.. {i 1 {} {} i 4} {{} {} {} {} i 4}}
}

do_rebase_test 2.3.2 {
  UPDATE t1 SET c=5 WHERE a=1;              -- local
} {
  UPDATE t1 SET c=5 WHERE a=1               -- remote
} REPLACE {
}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 3.0 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
  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, 4, 4);
}

# Arg $pkstr contains one character for each column in the table. An
# "X" for PK column, or a "." for a non-PK.
#
proc mk_tbl_header {name pkstr} {
  set ret [binary format H2c 54 [string length $pkstr]]
  foreach i [split $pkstr {}] {
    if {$i=="X"} {
      append ret [binary format H2 01]
    } else {
      if {$i!="."} {error "bad pkstr: $pkstr ($i)"}
      append ret [binary format H2 00]
    }
  }
  append ret $name
  append ret [binary format H2 00]
  set ret
}

proc mk_update_change {args} {
  set ret [binary format H2H2 17 00]
  foreach a $args {
    if {$a==""} {
      append ret [binary format H2 00]
    } else {
      append ret [binary format H2W 01 $a]
    }
  }
  set ret
}

proc xConflict {args} { return "ABORT" }
do_test 3.1 {
  set    C [mk_tbl_header t1 X..]
  append C [mk_update_change    1 {} 1   {} {}  500]
  append C [mk_update_change    2 {} {}  {} {}  {}]
  append C [mk_update_change    3 3  {}  {} 600 {}]
  append C [mk_update_change    4 {} {}  {} {}  {}]

  sqlite3changeset_apply_v2 db $C xConflict
} {}
do_execsql_test 3.2 {
  SELECT * FROM t1
} {
  1 1 500
  2 2 2
  3 600 3
  4 4 4
}






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/sessionwor.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

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







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



+
  catch { db close }
  catch { db2 close }
  forcedelete test.db test.db2
  sqlite3 db test.db
  sqlite3 db2 test.db2
}


do_execsql_test 1.0 {
  CREATE TABLE t1(a PRIMARY KEY, b) WITHOUT ROWID;
}

do_iterator_test 1.1 t1 {
  INSERT INTO t1 VALUES('one', 'two');
} {
  {INSERT t1 0 X. {} {t one t two}}
}

do_iterator_test 1.2 t1 {
  UPDATE t1 SET b='three'
} {
  {UPDATE t1 0 X. {t one t two} {{} {} t three}}
}

do_iterator_test 1.3 t1 {
  DELETE FROM t1;
} {
  {DELETE t1 0 X. {t one t three} {}}
foreach {tn wo} {
  1 ""
  2 "WITHOUT ROWID"
} {
  reset_db

  do_execsql_test 1.$tn.0 "CREATE TABLE t1(a PRIMARY KEY, b) $wo ;"
  
  do_iterator_test 1.$tn.1 t1 {
    INSERT INTO t1 VALUES('one', 'two');
  } {
    {INSERT t1 0 X. {} {t one t two}}
  }
  
  do_iterator_test 1.$tn.2 t1 {
    UPDATE t1 SET b='three'
  } {
    {UPDATE t1 0 X. {t one t two} {{} {} t three}}
  }
  
  do_iterator_test 1.$tn.3 t1 {
    REPLACE INTO t1 VALUES('one', 'four');
  } {
    {UPDATE t1 0 X. {t one t three} {{} {} t four}}
  }
  
  do_iterator_test 1.$tn.4 t1 {
    DELETE FROM t1;
  } {
    {DELETE t1 0 X. {t one t four} {}}
  }
}

foreach {tn wo} {
  1 ""
  2 "WITHOUT ROWID"
} {
  reset_db

  do_execsql_test 2.$tn.0.1 "CREATE TABLE t1(a INTEGER PRIMARY KEY, b) $wo ;"
  do_execsql_test 2.$tn.0.2 "CREATE TABLE t2(a INTEGER PRIMARY KEY, b) $wo ;"
  do_execsql_test 2.$tn.0.3 "CREATE TABLE t3(a INTEGER PRIMARY KEY, b) $wo ;"
  
  do_iterator_test 1.1 t1 {
    INSERT INTO t1 VALUES(1, 'two');
  } {
    {INSERT t1 0 X. {} {i 1 t two}}
  }
  
  do_iterator_test 2.$tn.2 t1 {
    UPDATE t1 SET b='three'
  } {
    {UPDATE t1 0 X. {i 1 t two} {{} {} t three}}
  }
  
  do_iterator_test 2.$tn.3 t1 {
    REPLACE INTO t1 VALUES(1, 'four');
  } {
    {UPDATE t1 0 X. {i 1 t three} {{} {} t four}}
  }
  
  do_iterator_test 2.$tn.4 t1 {
    DELETE FROM t1;
  } {
    {DELETE t1 0 X. {i 1 t four} {}}
  }

  do_execsql_test 2.$tn.5 {
    INSERT INTO t1 VALUES(1, 'one');
    INSERT INTO t1 VALUES(2, 'two');
    INSERT INTO t1 VALUES(3, 'three');
  }

  do_iterator_test 2.$tn.6 t2 {
    INSERT INTO t2 SELECT a, b FROM t1
  } {
    {INSERT t2 0 X. {} {i 1 t one}} 
    {INSERT t2 0 X. {} {i 2 t two}}
    {INSERT t2 0 X. {} {i 3 t three}}
  }
  do_iterator_test 2.$tn.7 t3 {
    INSERT INTO t3 SELECT * FROM t1
  } {
    {INSERT t3 0 X. {} {i 1 t one}} 
    {INSERT t3 0 X. {} {i 2 t two}}
    {INSERT t3 0 X. {} {i 3 t three}}
  }
}

finish_test

Changes to ext/session/sqlite3session.c.

45
46
47
48
49
50
51

52
53
54
55
56
57


58
59
60
61
62
63
64
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67







+






+
+








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

/*
93
94
95
96
97
98
99

100
101
102
103
104
105
106
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110







+







** Structure for changeset iterators.
*/
struct sqlite3_changeset_iter {
  SessionInput in;                /* Input buffer or stream */
  SessionBuffer tblhdr;           /* Buffer to hold apValue/zTab/abPK/ */
  int bPatchset;                  /* True if this is a patchset */
  int bInvert;                    /* True to invert changeset */
  int bSkipEmpty;                 /* Skip noop UPDATE changes */
  int rc;                         /* Iterator error code */
  sqlite3_stmt *pConflict;        /* Points to conflicting row, if any */
  char *zTab;                     /* Current table */
  int nCol;                       /* Number of columns in zTab */
  int op;                         /* Current operation */
  int bIndirect;                  /* True if current change was indirect */
  u8 *abPK;                       /* Primary key array */
292
293
294
295
296
297
298
299
300



301
302
303
304
305
306
307
296
297
298
299
300
301
302


303
304
305
306
307
308
309
310
311
312







-
-
+
+
+







*/

/*
** 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 
366
367
368
369
370
371
372
373

374
375
376
377
378
379
380
371
372
373
374
375
376
377

378
379
380
381
382
383
384
385







-
+







** If no error occurs, SQLITE_OK is returned. Or, if an OOM error occurs
** within a call to sqlite3_value_text() (may fail if the db is utf-16)) 
** SQLITE_NOMEM is returned.
*/
static int sessionSerializeValue(
  u8 *aBuf,                       /* If non-NULL, write serialized value here */
  sqlite3_value *pValue,          /* Value to serialize */
  int *pnWrite                    /* IN/OUT: Increment by bytes written */
  sqlite3_int64 *pnWrite          /* IN/OUT: Increment by bytes written */
){
  int nByte;                      /* Size of serialized value in bytes */

  if( pValue ){
    int eType;                    /* Value type (SQLITE_NULL, TEXT etc.) */
  
    eType = sqlite3_value_type(pValue);
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
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







-
+















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







        }
        n = sqlite3_value_bytes(pValue);
        if( z==0 && (eType!=SQLITE_BLOB || n>0) ) return SQLITE_NOMEM;
        nVarint = sessionVarintLen(n);
  
        if( aBuf ){
          sessionVarintPut(&aBuf[1], n);
          if( n ) memcpy(&aBuf[nVarint + 1], z, n);
          if( n>0 ) memcpy(&aBuf[nVarint + 1], z, n);
        }
  
        nByte = 1 + nVarint + n;
        break;
      }
    }
  }else{
    nByte = 1;
    if( aBuf ) aBuf[0] = '\0';
  }

  if( pnWrite ) *pnWrite += nByte;
  return SQLITE_OK;
}

/*
** Allocate and return a pointer to a buffer nByte bytes in size. If
** pSession is not NULL, increase the sqlite3_session.nMalloc variable
** by the number of bytes allocated.
*/
static void *sessionMalloc64(sqlite3_session *pSession, i64 nByte){
  void *pRet = sqlite3_malloc64(nByte);
  if( pSession ) pSession->nMalloc += sqlite3_msize(pRet);
  return pRet;
}

/*
** Free buffer pFree, which must have been allocated by an earlier
** call to sessionMalloc64(). If pSession is not NULL, decrease the
** sqlite3_session.nMalloc counter by the number of bytes freed.
*/
static void sessionFree(sqlite3_session *pSession, void *pFree){
  if( pSession ) pSession->nMalloc -= sqlite3_msize(pFree);
  sqlite3_free(pFree);
}

/*
** This macro is used to calculate hash key values for data structures. In
** order to use this macro, the entire data structure must be represented
** as a series of unsigned integers. In order to calculate a hash-key value
** for a data structure represented as three such integers, the macro may
** then be used as follows:
901
902
903
904
905
906
907
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
935

936
937
938
939
940
941
942
926
927
928
929
930
931
932

933
934
935
936
937
938
939
940

941
942

943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965

966
967
968
969
970
971
972
973







-
+
+
+
+
+



-
+

-
+
+
+




















-
+







** SQLITE_OK.
**
** It is possible that a non-fatal OOM error occurs in this function. In
** that case the hash-table does not grow, but SQLITE_OK is returned anyway.
** Growing the hash table in this case is a performance optimization only,
** it is not required for correct operation.
*/
static int sessionGrowHash(int bPatchset, SessionTable *pTab){
static int sessionGrowHash(
  sqlite3_session *pSession,      /* For memory accounting. May be NULL */
  int bPatchset, 
  SessionTable *pTab
){
  if( pTab->nChange==0 || pTab->nEntry>=(pTab->nChange/2) ){
    int i;
    SessionChange **apNew;
    int nNew = (pTab->nChange ? pTab->nChange : 128) * 2;
    sqlite3_int64 nNew = 2*(sqlite3_int64)(pTab->nChange ? pTab->nChange : 128);

    apNew = (SessionChange **)sqlite3_malloc(sizeof(SessionChange *) * nNew);
    apNew = (SessionChange**)sessionMalloc64(
        pSession, sizeof(SessionChange*) * nNew
    );
    if( apNew==0 ){
      if( pTab->nChange==0 ){
        return SQLITE_ERROR;
      }
      return SQLITE_OK;
    }
    memset(apNew, 0, sizeof(SessionChange *) * nNew);

    for(i=0; i<pTab->nChange; i++){
      SessionChange *p;
      SessionChange *pNext;
      for(p=pTab->apChange[i]; p; p=pNext){
        int bPkOnly = (p->op==SQLITE_DELETE && bPatchset);
        int iHash = sessionChangeHash(pTab, bPkOnly, p->aRecord, nNew);
        pNext = p->pNext;
        p->pNext = apNew[iHash];
        apNew[iHash] = p;
      }
    }

    sqlite3_free(pTab->apChange);
    sessionFree(pSession, pTab->apChange);
    pTab->nChange = nNew;
    pTab->apChange = apNew;
  }

  return SQLITE_OK;
}

962
963
964
965
966
967
968

969
970
971
972
973
974
975
976
977
978
979
980

981
982
983
984
985
986
987
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







+











-
+







**     *pazCol = {"w", "x", "y", "z"}
**     *pabPK  = {1, 0, 0, 1}
**
** All returned buffers are part of the same single allocation, which must
** be freed using sqlite3_free() by the caller
*/
static int sessionTableInfo(
  sqlite3_session *pSession,      /* For memory accounting. May be NULL */
  sqlite3 *db,                    /* Database connection */
  const char *zDb,                /* Name of attached database (e.g. "main") */
  const char *zThis,              /* Table name */
  int *pnCol,                     /* OUT: number of columns */
  const char **pzTab,             /* OUT: Copy of zThis */
  const char ***pazCol,           /* OUT: Array of column names for table */
  u8 **pabPK                      /* OUT: Array of booleans - true for PK col */
){
  char *zPragma;
  sqlite3_stmt *pStmt;
  int rc;
  int nByte;
  sqlite3_int64 nByte;
  int nDbCol = 0;
  int nThis;
  int i;
  u8 *pAlloc = 0;
  char **azCol = 0;
  u8 *abPK = 0;

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







+
+
+
+





-
+
+
+
+
+
+
+



-
+
+
+
+
+
+
+










-
+







          "SELECT 0, 'tbl',  '', 0, '', 1     UNION ALL "
          "SELECT 1, 'idx',  '', 0, '', 2     UNION ALL "
          "SELECT 2, 'stat', '', 0, '', 0"
      );
    }else if( rc==SQLITE_ERROR ){
      zPragma = sqlite3_mprintf("");
    }else{
      *pazCol = 0;
      *pabPK = 0;
      *pnCol = 0;
      if( pzTab ) *pzTab = 0;
      return rc;
    }
  }else{
    zPragma = sqlite3_mprintf("PRAGMA '%q'.table_info('%q')", zDb, zThis);
  }
  if( !zPragma ) return SQLITE_NOMEM;
  if( !zPragma ){
    *pazCol = 0;
    *pabPK = 0;
    *pnCol = 0;
    if( pzTab ) *pzTab = 0;
    return SQLITE_NOMEM;
  }

  rc = sqlite3_prepare_v2(db, zPragma, -1, &pStmt, 0);
  sqlite3_free(zPragma);
  if( rc!=SQLITE_OK ) return rc;
  if( rc!=SQLITE_OK ){
    *pazCol = 0;
    *pabPK = 0;
    *pnCol = 0;
    if( pzTab ) *pzTab = 0;
    return rc;
  }

  nByte = nThis + 1;
  while( SQLITE_ROW==sqlite3_step(pStmt) ){
    nByte += sqlite3_column_bytes(pStmt, 1);
    nDbCol++;
  }
  rc = sqlite3_reset(pStmt);

  if( rc==SQLITE_OK ){
    nByte += nDbCol * (sizeof(const char *) + sizeof(u8) + 1);
    pAlloc = sqlite3_malloc(nByte);
    pAlloc = sessionMalloc64(pSession, nByte);
    if( pAlloc==0 ){
      rc = SQLITE_NOMEM;
    }
  }
  if( rc==SQLITE_OK ){
    azCol = (char **)pAlloc;
    pAlloc = (u8 *)&azCol[nDbCol];
1059
1060
1061
1062
1063
1064
1065
1066

1067
1068
1069
1070
1071
1072
1073
1107
1108
1109
1110
1111
1112
1113

1114
1115
1116
1117
1118
1119
1120
1121







-
+







    *pabPK = abPK;
    *pnCol = nDbCol;
  }else{
    *pazCol = 0;
    *pabPK = 0;
    *pnCol = 0;
    if( pzTab ) *pzTab = 0;
    sqlite3_free(azCol);
    sessionFree(pSession, azCol);
  }
  sqlite3_finalize(pStmt);
  return rc;
}

/*
** This function is only called from within a pre-update handler for a
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
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







-
+













+
+
+
+
+
+







** indicate that updates on this table should be ignored. SessionTable.abPK 
** is set to NULL in this case.
*/
static int sessionInitTable(sqlite3_session *pSession, SessionTable *pTab){
  if( pTab->nCol==0 ){
    u8 *abPK;
    assert( pTab->azCol==0 || pTab->abPK==0 );
    pSession->rc = sessionTableInfo(pSession->db, pSession->zDb, 
    pSession->rc = sessionTableInfo(pSession, pSession->db, pSession->zDb, 
        pTab->zName, &pTab->nCol, 0, &pTab->azCol, &abPK
    );
    if( pSession->rc==SQLITE_OK ){
      int i;
      for(i=0; i<pTab->nCol; i++){
        if( abPK[i] ){
          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
1140
1141
1142
1143
1144
1145
1146

































































































1147
1148
1149
1150
1151
1152
1153
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
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304







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







  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
1172
1173
1174
1175
1176
1177
1178
1179

1180
1181
1182
1183
1184
1185
1186
1323
1324
1325
1326
1327
1328
1329

1330
1331
1332
1333
1334
1335
1336
1337







-
+







  ** number of columns in the table.  */
  if( pTab->nCol!=pSession->hook.xCount(pSession->hook.pCtx) ){
    pSession->rc = SQLITE_SCHEMA;
    return;
  }

  /* Grow the hash table if required */
  if( sessionGrowHash(0, pTab) ){
  if( sessionGrowHash(pSession, 0, pTab) ){
    pSession->rc = SQLITE_NOMEM;
    return;
  }

  if( pTab->bStat1 ){
    stat1.hook = pSession->hook;
    stat1.pSession = pSession;
1213
1214
1215
1216
1217
1218
1219
1220
1221

1222
1223
1224
1225
1226
1227
1228
1364
1365
1366
1367
1368
1369
1370


1371
1372
1373
1374
1375
1376
1377
1378







-
-
+







      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 */
      int nByte;              /* Number of bytes to allocate */
      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 */
      nByte = sizeof(SessionChange);
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
1286
1287
1288







1289
1290
1291
1292
1293
1294
1295
1389
1390
1391
1392
1393
1394
1395


1396
1397
1398
1399
1400


1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416

1417
1418
1419
1420
1421

1422
1423




1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437

1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451







-
-
+
+



-
-
+
+














-
+




-
+

-
-
-
-
+
+
+
+










-
+
+
+
+
+
+
+







        /* 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 *)sqlite3_malloc(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 ){
1315
1316
1317
1318
1319
1320
1321
1322





1323
1324
1325
1326
1327
1328
1329
1471
1472
1473
1474
1475
1476
1477

1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489







-
+
+
+
+
+







    /* If there is a table-filter configured, invoke it. If it returns 0,
    ** do not automatically add the new table. */
    if( pSession->xTableFilter==0
     || pSession->xTableFilter(pSession->pFilterCtx, zName) 
    ){
      rc = sqlite3session_attach(pSession, zName);
      if( rc==SQLITE_OK ){
        for(pRet=pSession->pTable; pRet->pNext; pRet=pRet->pNext);
        pRet = pSession->pTable;
        while( ALWAYS(pRet) && pRet->pNext ){
          pRet = pRet->pNext;
        }
        assert( pRet!=0 );
        assert( 0==sqlite3_strnicmp(pRet->zName, zName, nName+1) );
      }
    }
  }

  assert( rc==SQLITE_OK || pRet==0 );
  *ppTab = pRet;
1342
1343
1344
1345
1346
1347
1348


1349
1350
1351
1352
1353
1354
1355
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517







+
+







  sqlite3_int64 iKey1,            /* Rowid of row about to be deleted/updated */
  sqlite3_int64 iKey2             /* New rowid value (for a rowid UPDATE) */
){
  sqlite3_session *pSession;
  int nDb = sqlite3Strlen30(zDb);

  assert( sqlite3_mutex_held(db->mutex) );
  (void)iKey1;
  (void)iKey2;

  for(pSession=(sqlite3_session *)pCtx; pSession; pSession=pSession->pNext){
    SessionTable *pTab;

    /* If this session is attached to a different database ("main", "temp" 
    ** etc.), or if it is not currently enabled, there is nothing to do. Skip 
    ** to the next session object attached to this database. */
1418
1419
1420
1421
1422
1423
1424

1425
1426
1427
1428
1429
1430
1431
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594







+







   return SQLITE_OK;
}
static int sessionDiffCount(void *pCtx){
  SessionDiffCtx *p = (SessionDiffCtx*)pCtx;
  return p->nOldOff ? p->nOldOff : sqlite3_column_count(p->pStmt);
}
static int sessionDiffDepth(void *pCtx){
  (void)pCtx;
  return 0;
}

/*
** Install the diff hooks on the session object passed as the only
** argument.
*/
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1654
1655
1656
1657
1658
1659
1660

1661
1662
1663
1664
1665
1666
1667







-







    zRet = sqlite3_mprintf("0");
  }

  return zRet;
}

static char *sessionSelectFindNew(
  int nCol,
  const char *zDb1,      /* Pick rows in this db only */
  const char *zDb2,      /* But not in this one */
  const char *zTbl,      /* Table name */
  const char *zExpr
){
  char *zRet = sqlite3_mprintf(
      "SELECT * FROM \"%w\".\"%w\" WHERE NOT EXISTS ("
1515
1516
1517
1518
1519
1520
1521
1522

1523
1524
1525
1526
1527
1528
1529
1677
1678
1679
1680
1681
1682
1683

1684
1685
1686
1687
1688
1689
1690
1691







-
+







  sqlite3_session *pSession,
  SessionTable *pTab,
  const char *zDb1,
  const char *zDb2,
  char *zExpr
){
  int rc = SQLITE_OK;
  char *zStmt = sessionSelectFindNew(pTab->nCol, zDb1, zDb2, pTab->zName,zExpr);
  char *zStmt = sessionSelectFindNew(zDb1, zDb2, pTab->zName,zExpr);

  if( zStmt==0 ){
    rc = SQLITE_NOMEM;
  }else{
    sqlite3_stmt *pStmt;
    rc = sqlite3_prepare(pSession->db, zStmt, -1, &pStmt, 0);
    if( rc==SQLITE_OK ){
1612
1613
1614
1615
1616
1617
1618
1619

1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633

1634


1635
1636
1637
1638
1639
1640
1641
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







-
+














+
-
+
+







    /* Check the table schemas match */
    if( rc==SQLITE_OK ){
      int bHasPk = 0;
      int bMismatch = 0;
      int nCol;                   /* Columns in zFrom.zTbl */
      u8 *abPK;
      const char **azCol = 0;
      rc = sessionTableInfo(db, zFrom, zTbl, &nCol, 0, &azCol, &abPK);
      rc = sessionTableInfo(0, db, zFrom, zTbl, &nCol, 0, &azCol, &abPK);
      if( rc==SQLITE_OK ){
        if( pTo->nCol!=nCol ){
          bMismatch = 1;
        }else{
          int i;
          for(i=0; i<nCol; i++){
            if( pTo->abPK[i]!=abPK[i] ) bMismatch = 1;
            if( sqlite3_stricmp(azCol[i], pTo->azCol[i]) ) bMismatch = 1;
            if( abPK[i] ) bHasPk = 1;
          }
        }
      }
      sqlite3_free((char*)azCol);
      if( bMismatch ){
        if( pzErrMsg ){
        *pzErrMsg = sqlite3_mprintf("table schemas do not match");
          *pzErrMsg = sqlite3_mprintf("table schemas do not match");
        }
        rc = SQLITE_SCHEMA;
      }
      if( bHasPk==0 ){
        /* Ignore tables with no primary keys */
        goto diff_out;
      }
    }
1683
1684
1685
1686
1687
1688
1689
1690

1691
1692
1693
1694
1695
1696
1697
1847
1848
1849
1850
1851
1852
1853

1854
1855
1856
1857
1858
1859
1860
1861







-
+







  sqlite3_session *pOld;          /* Session object already attached to db */
  int nDb = sqlite3Strlen30(zDb); /* Length of zDb in bytes */

  /* Zero the output value in case an error occurs. */
  *ppSession = 0;

  /* Allocate and populate the new session object. */
  pNew = (sqlite3_session *)sqlite3_malloc(sizeof(sqlite3_session) + nDb + 1);
  pNew = (sqlite3_session *)sqlite3_malloc64(sizeof(sqlite3_session) + nDb + 1);
  if( !pNew ) return SQLITE_NOMEM;
  memset(pNew, 0, sizeof(sqlite3_session));
  pNew->db = db;
  pNew->zDb = (char *)&pNew[1];
  pNew->bEnable = 1;
  memcpy(pNew->zDb, zDb, nDb+1);
  sessionPreupdateHooks(pNew);
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
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







-
+











-
+


-
-
-
+
+
+







  return SQLITE_OK;
}

/*
** Free the list of table objects passed as the first argument. The contents
** of the changed-rows hash tables are also deleted.
*/
static void sessionDeleteTable(SessionTable *pList){
static void sessionDeleteTable(sqlite3_session *pSession, SessionTable *pList){
  SessionTable *pNext;
  SessionTable *pTab;

  for(pTab=pList; pTab; pTab=pNext){
    int i;
    pNext = pTab->pNext;
    for(i=0; i<pTab->nChange; i++){
      SessionChange *p;
      SessionChange *pNextChange;
      for(p=pTab->apChange[i]; p; p=pNextChange){
        pNextChange = p->pNext;
        sqlite3_free(p);
        sessionFree(pSession, p);
      }
    }
    sqlite3_free((char*)pTab->azCol);  /* cast works around VC++ bug */
    sqlite3_free(pTab->apChange);
    sqlite3_free(pTab);
    sessionFree(pSession, (char*)pTab->azCol);  /* cast works around VC++ bug */
    sessionFree(pSession, pTab->apChange);
    sessionFree(pSession, pTab);
  }
}

/*
** Delete a session object previously allocated using sqlite3session_create().
*/
void sqlite3session_delete(sqlite3_session *pSession){
1753
1754
1755
1756
1757
1758
1759
1760

1761

1762


1763
1764
1765
1766
1767
1768
1769
1917
1918
1919
1920
1921
1922
1923

1924
1925
1926

1927
1928
1929
1930
1931
1932
1933
1934
1935







-
+

+
-
+
+







    }
  }
  sqlite3_mutex_leave(sqlite3_db_mutex(db));
  sqlite3ValueFree(pSession->pZeroBlob);

  /* Delete all attached table objects. And the contents of their 
  ** associated hash-tables. */
  sessionDeleteTable(pSession->pTable);
  sessionDeleteTable(pSession, pSession->pTable);

  /* Assert that all allocations have been freed and then free the 
  /* Free the session object itself. */
  ** session object itself. */
  assert( pSession->nMalloc==0 );
  sqlite3_free(pSession);
}

/*
** Set a table filter on a Session Object.
*/
void sqlite3session_table_filter(
1802
1803
1804
1805
1806
1807
1808
1809


1810
1811
1812
1813
1814
1815
1816
1968
1969
1970
1971
1972
1973
1974

1975
1976
1977
1978
1979
1980
1981
1982
1983







-
+
+







    nName = sqlite3Strlen30(zName);
    for(pTab=pSession->pTable; pTab; pTab=pTab->pNext){
      if( 0==sqlite3_strnicmp(pTab->zName, zName, nName+1) ) break;
    }

    if( !pTab ){
      /* Allocate new SessionTable object. */
      pTab = (SessionTable *)sqlite3_malloc(sizeof(SessionTable) + nName + 1);
      int nByte = sizeof(SessionTable) + nName + 1;
      pTab = (SessionTable*)sessionMalloc64(pSession, nByte);
      if( !pTab ){
        rc = SQLITE_NOMEM;
      }else{
        /* Populate the new SessionTable object and link it into the list.
        ** The new object must be linked onto the end of the list, not 
        ** simply added to the start of it in order to ensure that tables
        ** appear in the correct order when a changeset or patchset is
1832
1833
1834
1835
1836
1837
1838
1839
1840




1841
1842

1843
1844

1845













1846
1847
1848
1849
1850
1851
1852
1999
2000
2001
2002
2003
2004
2005


2006
2007
2008
2009
2010
2011
2012
2013
2014
2015

2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035







-
-
+
+
+
+


+


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







/*
** Ensure that there is room in the buffer to append nByte bytes of data.
** If not, use sqlite3_realloc() to grow the buffer so that there is.
**
** If successful, return zero. Otherwise, if an OOM condition is encountered,
** set *pRc to SQLITE_NOMEM and return non-zero.
*/
static int sessionBufferGrow(SessionBuffer *p, int nByte, int *pRc){
  if( *pRc==SQLITE_OK && p->nAlloc-p->nBuf<nByte ){
static int sessionBufferGrow(SessionBuffer *p, i64 nByte, int *pRc){
#define SESSION_MAX_BUFFER_SZ (0x7FFFFF00 - 1) 
  i64 nReq = p->nBuf + nByte;
  if( *pRc==SQLITE_OK && nReq>p->nAlloc ){
    u8 *aNew;
    i64 nNew = p->nAlloc ? p->nAlloc : 128;

    do {
      nNew = nNew*2;
    }while( nNew<nReq );
    }while( (nNew-p->nBuf)<nByte );

    /* The value of SESSION_MAX_BUFFER_SZ is copied from the implementation
    ** of sqlite3_realloc64(). Allocations greater than this size in bytes
    ** always fail. It is used here to ensure that this routine can always
    ** allocate up to this limit - instead of up to the largest power of
    ** two smaller than the limit.  */
    if( nNew>SESSION_MAX_BUFFER_SZ ){
      nNew = SESSION_MAX_BUFFER_SZ;
      if( nNew<nReq ){
        *pRc = SQLITE_NOMEM;
        return 1;
      }
    }

    aNew = (u8 *)sqlite3_realloc64(p->aBuf, nNew);
    if( 0==aNew ){
      *pRc = SQLITE_NOMEM;
    }else{
      p->aBuf = aNew;
      p->nAlloc = nNew;
1862
1863
1864
1865
1866
1867
1868
1869

1870
1871
1872
1873
1874
1875
1876
2045
2046
2047
2048
2049
2050
2051

2052
2053
2054
2055
2056
2057
2058
2059







-
+







** This function is a no-op if *pRc is non-zero when it is called.
** Otherwise, if an error occurs, *pRc is set to an SQLite error code
** before returning.
*/
static void sessionAppendValue(SessionBuffer *p, sqlite3_value *pVal, int *pRc){
  int rc = *pRc;
  if( rc==SQLITE_OK ){
    int nByte = 0;
    sqlite3_int64 nByte = 0;
    rc = sessionSerializeValue(0, pVal, &nByte);
    sessionBufferGrow(p, nByte, &rc);
    if( rc==SQLITE_OK ){
      rc = sessionSerializeValue(&p->aBuf[p->nBuf], pVal, 0);
      p->nBuf += nByte;
    }else{
      *pRc = rc;
2067
2068
2069
2070
2071
2072
2073

2074
2075
2076
2077
2078
2079
2080
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264







+







  int rc = SQLITE_OK;
  SessionBuffer buf2 = {0,0,0}; /* Buffer to accumulate new.* record in */
  int bNoop = 1;                /* Set to zero if any values are modified */
  int nRewind = pBuf->nBuf;     /* Set to zero if any values are modified */
  int i;                        /* Used to iterate through columns */
  u8 *pCsr = p->aRecord;        /* Used to iterate through old.* values */

  assert( abPK!=0 );
  sessionAppendByte(pBuf, SQLITE_UPDATE, &rc);
  sessionAppendByte(pBuf, p->bIndirect, &rc);
  for(i=0; i<sqlite3_column_count(pStmt); i++){
    int bChanged = 0;
    int nAdvance;
    int eType = *pCsr;
    switch( eType ){
2371
2372
2373
2374
2375
2376
2377
2378


2379
2380
2381
2382
2383

2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398


2399
2400
2401
2402
2403
2404
2405
2406

2407
2408
2409
2410
2411
2412
2413
2555
2556
2557
2558
2559
2560
2561

2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582


2583
2584
2585
2586
2587
2588
2589
2590
2591

2592
2593
2594
2595
2596
2597
2598
2599







-
+
+





+













-
-
+
+







-
+







  void **ppChangeset              /* OUT: Buffer containing changeset */
){
  sqlite3 *db = pSession->db;     /* Source database handle */
  SessionTable *pTab;             /* Used to iterate through attached tables */
  SessionBuffer buf = {0,0,0};    /* Buffer in which to accumlate changeset */
  int rc;                         /* Return code */

  assert( xOutput==0 || (pnChangeset==0 && ppChangeset==0 ) );
  assert( xOutput==0 || (pnChangeset==0 && ppChangeset==0) );
  assert( xOutput!=0 || (pnChangeset!=0 && ppChangeset!=0) );

  /* Zero the output variables in case an error occurs. If this session
  ** object is already in the error state (sqlite3_session.rc != SQLITE_OK),
  ** this call will be a no-op.  */
  if( xOutput==0 ){
    assert( pnChangeset!=0  && ppChangeset!=0 );
    *pnChangeset = 0;
    *ppChangeset = 0;
  }

  if( pSession->rc ) return pSession->rc;
  rc = sqlite3_exec(pSession->db, "SAVEPOINT changeset", 0, 0, 0);
  if( rc!=SQLITE_OK ) return rc;

  sqlite3_mutex_enter(sqlite3_db_mutex(db));

  for(pTab=pSession->pTable; rc==SQLITE_OK && pTab; pTab=pTab->pNext){
    if( pTab->nEntry ){
      const char *zName = pTab->zName;
      int nCol;                   /* Number of columns in table */
      u8 *abPK;                   /* Primary key array */
      int nCol = 0;               /* Number of columns in table */
      u8 *abPK = 0;               /* Primary key array */
      const char **azCol = 0;     /* Table columns */
      int i;                      /* Used to iterate through hash buckets */
      sqlite3_stmt *pSel = 0;     /* SELECT statement to query table pTab */
      int nRewind = buf.nBuf;     /* Initial size of write buffer */
      int nNoop;                  /* Size of buffer after writing tbl header */

      /* Check the table schema is still Ok. */
      rc = sessionTableInfo(db, pSession->zDb, zName, &nCol, 0, &azCol, &abPK);
      rc = sessionTableInfo(0, db, pSession->zDb, zName, &nCol, 0,&azCol,&abPK);
      if( !rc && (pTab->nCol!=nCol || memcmp(abPK, pTab->abPK, nCol)) ){
        rc = SQLITE_SCHEMA;
      }

      /* Write a table header */
      sessionAppendTableHdr(&buf, ePatchset, pTab, &rc);

2429
2430
2431
2432
2433
2434
2435

2436
2437
2438
2439
2440
2441
2442
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629







+







              int iCol;
              sessionAppendByte(&buf, SQLITE_INSERT, &rc);
              sessionAppendByte(&buf, p->bIndirect, &rc);
              for(iCol=0; iCol<nCol; iCol++){
                sessionAppendCol(&buf, pSel, iCol, &rc);
              }
            }else{
              assert( abPK!=0 );  /* Because sessionSelectStmt() returned ok */
              rc = sessionAppendUpdate(&buf, ePatchset, pSel, p, abPK);
            }
          }else if( p->op!=SQLITE_INSERT ){
            rc = sessionAppendDelete(&buf, ePatchset, p, nCol, abPK);
          }
          if( rc==SQLITE_OK ){
            rc = sqlite3_reset(pSel);
2489
2490
2491
2492
2493
2494
2495



2496

2497




2498
2499
2500
2501
2502
2503
2504
2505
2506
2507

2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519

2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535

2536
2537
2538
2539
2540
2541
2542
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
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739







+
+
+
-
+

+
+
+
+










+












+
















+







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

  if( pnChangeset==0 || ppChangeset==0 ) return SQLITE_MISUSE;
  return sessionGenerateChangeset(
  rc = sessionGenerateChangeset(
      pSession, SESSIONS_CHANGESET, 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,
  int (*xOutput)(void *pOut, const void *pData, int nData),
  void *pOut
){
  if( xOutput==0 ) return SQLITE_MISUSE;
  return sessionGenerateChangeset(
      pSession, SESSIONS_CHANGESET, xOutput, pOut, 0, 0);
}

/*
** Streaming version of sqlite3session_patchset().
*/
int sqlite3session_patchset_strm(
  sqlite3_session *pSession,
  int (*xOutput)(void *pOut, const void *pData, int nData),
  void *pOut
){
  if( xOutput==0 ) return SQLITE_MISUSE;
  return sessionGenerateChangeset(
      pSession, SESSIONS_PATCHSET, xOutput, pOut, 0, 0);
}

/*
** Obtain a patchset object containing all changes recorded by the 
** session object passed as the first argument.
**
** It is the responsibility of the caller to eventually free the buffer 
** using sqlite3_free().
*/
int sqlite3session_patchset(
  sqlite3_session *pSession,      /* Session object */
  int *pnPatchset,                /* OUT: Size of buffer at *ppChangeset */
  void **ppPatchset               /* OUT: Buffer containing changeset */
){
  if( pnPatchset==0 || ppPatchset==0 ) return SQLITE_MISUSE;
  return sessionGenerateChangeset(
      pSession, SESSIONS_PATCHSET, 0, 0, pnPatchset, ppPatchset);
}

int sqlite3session_fullchangeset(
  sqlite3_session *pSession,      /* Session object */
  int *pnChangeset,               /* OUT: Size of buffer at *ppChangeset */
2587
2588
2589
2590
2591
2592
2593








































2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604


2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624

2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639

2640
2641
2642
2643
2644
2645
2646
2647
2648

2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659

2660
2661
2662
2663
2664
2665
2666
2667
2668

2669
2670
2671
2672
2673
2674
2675
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
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840

2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877

2878
2879
2880
2881
2882
2883
2884
2885
2886

2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897

2898
2899
2900
2901
2902
2903
2904
2905
2906

2907
2908
2909
2910
2911
2912
2913
2914







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










-
+
+




















+














-
+








-
+










-
+








-
+







  for(pTab=pSession->pTable; pTab && ret==0; pTab=pTab->pNext){
    ret = (pTab->nEntry>0);
  }
  sqlite3_mutex_leave(sqlite3_db_mutex(pSession->db));

  return (ret==0);
}

/*
** 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),
  void *pIn,
  int nChangeset,                 /* Size of buffer pChangeset in bytes */
  void *pChangeset,               /* Pointer to buffer containing changeset */
  int bInvert                     /* True to invert changeset */
  int bInvert,                    /* True to invert changeset */
  int bSkipEmpty                  /* True to skip empty UPDATE changes */
){
  sqlite3_changeset_iter *pRet;   /* Iterator to return */
  int nByte;                      /* Number of bytes to allocate for iterator */

  assert( xInput==0 || (pChangeset==0 && nChangeset==0) );

  /* Zero the output variable in case an error occurs. */
  *pp = 0;

  /* Allocate and initialize the iterator structure. */
  nByte = sizeof(sqlite3_changeset_iter);
  pRet = (sqlite3_changeset_iter *)sqlite3_malloc(nByte);
  if( !pRet ) return SQLITE_NOMEM;
  memset(pRet, 0, sizeof(sqlite3_changeset_iter));
  pRet->in.aData = (u8 *)pChangeset;
  pRet->in.nData = nChangeset;
  pRet->in.xInput = xInput;
  pRet->in.pIn = pIn;
  pRet->in.bEof = (xInput ? 0 : 1);
  pRet->bInvert = bInvert;
  pRet->bSkipEmpty = bSkipEmpty;

  /* Populate the output variable and return success. */
  *pp = pRet;
  return SQLITE_OK;
}

/*
** Create an iterator used to iterate through the contents of a changeset.
*/
int sqlite3changeset_start(
  sqlite3_changeset_iter **pp,    /* OUT: Changeset iterator handle */
  int nChangeset,                 /* Size of buffer pChangeset in bytes */
  void *pChangeset                /* Pointer to buffer containing changeset */
){
  return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset, 0);
  return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset, 0, 0);
}
int sqlite3changeset_start_v2(
  sqlite3_changeset_iter **pp,    /* OUT: Changeset iterator handle */
  int nChangeset,                 /* Size of buffer pChangeset in bytes */
  void *pChangeset,               /* Pointer to buffer containing changeset */
  int flags
){
  int bInvert = !!(flags & SQLITE_CHANGESETSTART_INVERT);
  return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset, bInvert);
  return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset, bInvert, 0);
}

/*
** Streaming version of sqlite3changeset_start().
*/
int sqlite3changeset_start_strm(
  sqlite3_changeset_iter **pp,    /* OUT: Changeset iterator handle */
  int (*xInput)(void *pIn, void *pData, int *pnData),
  void *pIn
){
  return sessionChangesetStart(pp, xInput, pIn, 0, 0, 0);
  return sessionChangesetStart(pp, xInput, pIn, 0, 0, 0, 0);
}
int sqlite3changeset_start_v2_strm(
  sqlite3_changeset_iter **pp,    /* OUT: Changeset iterator handle */
  int (*xInput)(void *pIn, void *pData, int *pnData),
  void *pIn,
  int flags
){
  int bInvert = !!(flags & SQLITE_CHANGESETSTART_INVERT);
  return sessionChangesetStart(pp, xInput, pIn, 0, 0, bInvert);
  return sessionChangesetStart(pp, xInput, pIn, 0, 0, bInvert, 0);
}

/*
** If the SessionInput object passed as the only argument is a streaming
** object and the buffer is full, discard some data to free up space.
*/
static void sessionDiscardData(SessionInput *pIn){
2752
2753
2754
2755
2756
2757
2758
2759

2760
2761
2762
2763
2764
2765
2766
2991
2992
2993
2994
2995
2996
2997

2998
2999
3000
3001
3002
3003
3004
3005







-
+







  int nData,                      /* Size of buffer aData[] in bytes */
  u8 enc                          /* String encoding (0 for blobs) */
){
  /* In theory this code could just pass SQLITE_TRANSIENT as the final
  ** argument to sqlite3ValueSetStr() and have the copy created 
  ** automatically. But doing so makes it difficult to detect any OOM
  ** error. Hence the code to create the copy externally. */
  u8 *aCopy = sqlite3_malloc(nData+1);
  u8 *aCopy = sqlite3_malloc64((sqlite3_int64)nData+1);
  if( aCopy==0 ) return SQLITE_NOMEM;
  memcpy(aCopy, aData, nData);
  sqlite3ValueSetStr(pVal, nData, (char*)aCopy, enc, sqlite3_free);
  return SQLITE_OK;
}

/*
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
3026
3027
3028
3029
3030
3031
3032

3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059







-
+
+




+
+











+







** If an error occurs, an SQLite error code (e.g. SQLITE_NOMEM) is returned.
** The apOut[] array may have been partially populated in this case.
*/
static int sessionReadRecord(
  SessionInput *pIn,              /* Input data */
  int nCol,                       /* Number of values in record */
  u8 *abPK,                       /* Array of primary key flags, or NULL */
  sqlite3_value **apOut           /* Write values to this array */
  sqlite3_value **apOut,          /* Write values to this array */
  int *pbEmpty
){
  int i;                          /* Used to iterate through columns */
  int rc = SQLITE_OK;

  assert( pbEmpty==0 || *pbEmpty==0 );
  if( pbEmpty ) *pbEmpty = 1;
  for(i=0; i<nCol && rc==SQLITE_OK; i++){
    int eType = 0;                /* Type of value (SQLITE_NULL, TEXT etc.) */
    if( abPK && abPK[i]==0 ) continue;
    rc = sessionInputBuffer(pIn, 9);
    if( rc==SQLITE_OK ){
      if( pIn->iNext>=pIn->nData ){
        rc = SQLITE_CORRUPT_BKPT;
      }else{
        eType = pIn->aData[pIn->iNext++];
        assert( apOut[i]==0 );
        if( eType ){
          if( pbEmpty ) *pbEmpty = 0;
          apOut[i] = sqlite3ValueNew(0);
          if( !apOut[i] ) rc = SQLITE_NOMEM;
        }
      }
    }

    if( rc==SQLITE_OK ){
2964
2965
2966
2967
2968
2969
2970
2971

2972
2973
2974
2975
2976
2977




2978
2979



2980
2981
2982
2983
2984

2985
2986

2987
2988
2989
2990

2991
2992

2993
2994

2995
2996
2997

2998
2999

3000
3001
3002
3003


3004
3005
3006
3007
3008

3009
3010
3011
3012
3013
3014
3015
3207
3208
3209
3210
3211
3212
3213

3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224


3225
3226
3227
3228
3229
3230
3231

3232


3233


3234

3235


3236
3237

3238



3239
3240

3241
3242
3243
3244

3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259







-
+






+
+
+
+
-
-
+
+
+




-
+
-
-
+
-
-

-
+
-
-
+

-
+
-
-
-
+

-
+



-
+
+





+







      sessionBufferGrow(&p->tblhdr, nByte, &rc);
    }else{
      rc = SQLITE_CORRUPT_BKPT;
    }
  }

  if( rc==SQLITE_OK ){
    int iPK = sizeof(sqlite3_value*)*p->nCol*2;
    size_t iPK = sizeof(sqlite3_value*)*p->nCol*2;
    memset(p->tblhdr.aBuf, 0, iPK);
    memcpy(&p->tblhdr.aBuf[iPK], &p->in.aData[p->in.iNext], nCopy);
    p->in.iNext += nCopy;
  }

  p->apValue = (sqlite3_value**)p->tblhdr.aBuf;
  if( p->apValue==0 ){
    p->abPK = 0;
    p->zTab = 0;
  }else{
  p->abPK = (u8*)&p->apValue[p->nCol*2];
  p->zTab = (char*)&p->abPK[p->nCol];
    p->abPK = (u8*)&p->apValue[p->nCol*2];
    p->zTab = p->abPK ? (char*)&p->abPK[p->nCol] : 0;
  }
  return (p->rc = rc);
}

/*
** Advance the changeset iterator to the next change.
** Advance the changeset iterator to the next change. The differences between
**
** If both paRec and pnRec are NULL, then this function works like the public
** this function and sessionChangesetNext() are that
** API sqlite3changeset_next(). If SQLITE_ROW is returned, then the
** sqlite3changeset_new() and old() APIs may be used to query for values.
**
** Otherwise, if paRec and pnRec are not NULL, then a pointer to the change
**   * If pbEmpty is not NULL and the change is a no-op UPDATE (an UPDATE
** record is written to *paRec before returning and the number of bytes in
** the record to *pnRec.
**     that modifies no columns), this function sets (*pbEmpty) to 1.
**
** Either way, this function returns SQLITE_ROW if the iterator is 
**   * If the iterator is configured to skip no-op UPDATEs,
** successfully advanced to the next change in the changeset, an SQLite 
** error code if an error occurs, or SQLITE_DONE if there are no further 
** changes in the changeset.
**     sessionChangesetNext() does that. This function does not.
*/
static int sessionChangesetNext(
static int sessionChangesetNextOne(
  sqlite3_changeset_iter *p,      /* Changeset iterator */
  u8 **paRec,                     /* If non-NULL, store record pointer here */
  int *pnRec,                     /* If non-NULL, store size of record here */
  int *pbNew                      /* If non-NULL, true if new table */
  int *pbNew,                     /* If non-NULL, true if new table */
  int *pbEmpty
){
  int i;
  u8 op;

  assert( (paRec==0 && pnRec==0) || (paRec && pnRec) );
  assert( pbEmpty==0 || *pbEmpty==0 );

  /* If the iterator is in the error-state, return immediately. */
  if( p->rc!=SQLITE_OK ) return p->rc;

  /* Free the current contents of p->apValue[], if any. */
  if( p->apValue ){
    for(i=0; i<p->nCol*2; i++){
3074
3075
3076
3077
3078
3079
3080
3081

3082
3083
3084
3085
3086
3087

3088
3089
3090
3091
3092
3093
3094
3318
3319
3320
3321
3322
3323
3324

3325
3326
3327
3328
3329
3330

3331
3332
3333
3334
3335
3336
3337
3338







-
+





-
+







  }else{
    sqlite3_value **apOld = (p->bInvert ? &p->apValue[p->nCol] : p->apValue);
    sqlite3_value **apNew = (p->bInvert ? p->apValue : &p->apValue[p->nCol]);

    /* If this is an UPDATE or DELETE, read the old.* record. */
    if( p->op!=SQLITE_INSERT && (p->bPatchset==0 || p->op==SQLITE_DELETE) ){
      u8 *abPK = p->bPatchset ? p->abPK : 0;
      p->rc = sessionReadRecord(&p->in, p->nCol, abPK, apOld);
      p->rc = sessionReadRecord(&p->in, p->nCol, abPK, apOld, 0);
      if( p->rc!=SQLITE_OK ) return p->rc;
    }

    /* If this is an INSERT or UPDATE, read the new.* record. */
    if( p->op!=SQLITE_DELETE ){
      p->rc = sessionReadRecord(&p->in, p->nCol, 0, apNew);
      p->rc = sessionReadRecord(&p->in, p->nCol, 0, apNew, pbEmpty);
      if( p->rc!=SQLITE_OK ) return p->rc;
    }

    if( (p->bPatchset || p->bInvert) && p->op==SQLITE_UPDATE ){
      /* If this is an UPDATE that is part of a patchset, then all PK and
      ** modified fields are present in the new.* record. The old.* record
      ** is currently completely empty. This block shifts the PK fields from
3102
3103
3104
3105
3106
3107
3108
3109
3110


















3111
3112































3113
3114
3115
3116
3117
3118
3119
3346
3347
3348
3349
3350
3351
3352


3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410







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


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







          p->apValue[i+p->nCol] = 0;
        }
      }
    }else if( p->bInvert ){
      if( p->op==SQLITE_INSERT ) p->op = SQLITE_DELETE;
      else if( p->op==SQLITE_DELETE ) p->op = SQLITE_INSERT;
    }
  }


    /* If this is an UPDATE that is part of a changeset, then check that
    ** there are no fields in the old.* record that are not (a) PK fields,
    ** or (b) also present in the new.* record. 
    **
    ** Such records are technically corrupt, but the rebaser was at one
    ** point generating them. Under most circumstances this is benign, but
    ** can cause spurious SQLITE_RANGE errors when applying the changeset. */
    if( p->bPatchset==0 && p->op==SQLITE_UPDATE){
      for(i=0; i<p->nCol; i++){
        if( p->abPK[i]==0 && p->apValue[i+p->nCol]==0 ){
          sqlite3ValueFree(p->apValue[i]);
          p->apValue[i] = 0;
        }
      }
    }
  }

  return SQLITE_ROW;
}

/*
** Advance the changeset iterator to the next change.
**
** If both paRec and pnRec are NULL, then this function works like the public
** API sqlite3changeset_next(). If SQLITE_ROW is returned, then the
** sqlite3changeset_new() and old() APIs may be used to query for values.
**
** Otherwise, if paRec and pnRec are not NULL, then a pointer to the change
** record is written to *paRec before returning and the number of bytes in
** the record to *pnRec.
**
** Either way, this function returns SQLITE_ROW if the iterator is 
** successfully advanced to the next change in the changeset, an SQLite 
** error code if an error occurs, or SQLITE_DONE if there are no further 
** changes in the changeset.
*/
static int sessionChangesetNext(
  sqlite3_changeset_iter *p,      /* Changeset iterator */
  u8 **paRec,                     /* If non-NULL, store record pointer here */
  int *pnRec,                     /* If non-NULL, store size of record here */
  int *pbNew                      /* If non-NULL, true if new table */
){
  int bEmpty;
  int rc;
  do {
    bEmpty = 0;
    rc = sessionChangesetNextOne(p, paRec, pnRec, pbNew, &bEmpty);
  }while( rc==SQLITE_ROW && p->bSkipEmpty && bEmpty);
  return rc;
}

/*
** Advance an iterator created by sqlite3changeset_start() to the next
** change in the changeset. This function may return SQLITE_ROW, SQLITE_DONE
** or SQLITE_CORRUPT.
**
** This function may not be called on iterators passed to a conflict handler
3365
3366
3367
3368
3369
3370
3371
3372

3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386

3387
3388

3389
3390
3391
3392
3393
3394
3395
3656
3657
3658
3659
3660
3661
3662

3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676

3677
3678

3679
3680
3681
3682
3683
3684
3685
3686







-
+













-
+

-
+







        break;
      }

      case SQLITE_UPDATE: {
        int iCol;

        if( 0==apVal ){
          apVal = (sqlite3_value **)sqlite3_malloc(sizeof(apVal[0])*nCol*2);
          apVal = (sqlite3_value **)sqlite3_malloc64(sizeof(apVal[0])*nCol*2);
          if( 0==apVal ){
            rc = SQLITE_NOMEM;
            goto finished_invert;
          }
          memset(apVal, 0, sizeof(apVal[0])*nCol*2);
        }

        /* Write the header for the new UPDATE change. Same as the original. */
        sessionAppendByte(&sOut, eType, &rc);
        sessionAppendByte(&sOut, pInput->aData[pInput->iNext+1], &rc);

        /* Read the old.* and new.* records for the update change. */
        pInput->iNext += 2;
        rc = sessionReadRecord(pInput, nCol, 0, &apVal[0]);
        rc = sessionReadRecord(pInput, nCol, 0, &apVal[0], 0);
        if( rc==SQLITE_OK ){
          rc = sessionReadRecord(pInput, nCol, 0, &apVal[nCol]);
          rc = sessionReadRecord(pInput, nCol, 0, &apVal[nCol], 0);
        }

        /* Write the new old.* record. Consists of the PK columns from the
        ** original old.* record, and the other values from the original
        ** new.* record. */
        for(iCol=0; iCol<nCol; iCol++){
          sqlite3_value *pVal = apVal[iCol + (abPK[iCol] ? 0 : nCol)];
3425
3426
3427
3428
3429
3430
3431
3432

3433
3434
3435
3436

3437
3438
3439
3440
3441
3442
3443
3716
3717
3718
3719
3720
3721
3722

3723
3724
3725
3726

3727
3728
3729
3730
3731
3732
3733
3734







-
+



-
+







      rc = xOutput(pOut, sOut.aBuf, sOut.nBuf);
      sOut.nBuf = 0;
      if( rc!=SQLITE_OK ) goto finished_invert;
    }
  }

  assert( rc==SQLITE_OK );
  if( pnInverted ){
  if( pnInverted && ALWAYS(ppInverted) ){
    *pnInverted = sOut.nBuf;
    *ppInverted = sOut.aBuf;
    sOut.aBuf = 0;
  }else if( sOut.nBuf>0 ){
  }else if( sOut.nBuf>0 && ALWAYS(xOutput!=0) ){
    rc = xOutput(pOut, sOut.aBuf, sOut.nBuf);
  }

 finished_invert:
  sqlite3_free(sOut.aBuf);
  sqlite3_free(apVal);
  sqlite3_free(sPK.aBuf);
3482
3483
3484
3485
3486
3487
3488








3489
3490
3491
3492
3493
3494
3495
3496
3497
3498


3499
3500

3501
3502
3503
3504
3505

































































































































































3506
3507
3508
3509
3510
3511
3512
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791

3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
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
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
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
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
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974







+
+
+
+
+
+
+
+




-





+
+


+





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







  sInput.pIn = pIn;

  rc = sessionChangesetInvert(&sInput, xOutput, pOut, 0, 0);
  sqlite3_free(sInput.buf.aBuf);
  return rc;
}


typedef struct SessionUpdate SessionUpdate;
struct SessionUpdate {
  sqlite3_stmt *pStmt;
  u32 *aMask;
  SessionUpdate *pNext;
};

typedef struct SessionApplyCtx SessionApplyCtx;
struct SessionApplyCtx {
  sqlite3 *db;
  sqlite3_stmt *pDelete;          /* DELETE statement */
  sqlite3_stmt *pUpdate;          /* UPDATE statement */
  sqlite3_stmt *pInsert;          /* INSERT statement */
  sqlite3_stmt *pSelect;          /* SELECT statement */
  int nCol;                       /* Size of azCol[] and abPK[] arrays */
  const char **azCol;             /* Array of column names */
  u8 *abPK;                       /* Boolean array - true if column is in PK */
  u32 *aUpdateMask;               /* Used by sessionUpdateFind */
  SessionUpdate *pUp;
  int bStat1;                     /* True if table is sqlite_stat1 */
  int bDeferConstraints;          /* True to defer constraints */
  int bInvertConstraints;         /* Invert when iterating constraints buffer */
  SessionBuffer constraints;      /* Deferred constraints are stored here */
  SessionBuffer rebase;           /* Rebase information (if any) here */
  u8 bRebaseStarted;              /* If table header is already in rebase */
  u8 bRebase;                     /* True to collect rebase information */
};

/* Number of prepared UPDATE statements to cache. */
#define SESSION_UPDATE_CACHE_SZ 12

/*
** Find a prepared UPDATE statement suitable for the UPDATE step currently
** being visited by the iterator. The UPDATE is of the form:
**
**   UPDATE tbl SET col = ?, col2 = ? WHERE pk1 IS ? AND pk2 IS ?
*/
static int sessionUpdateFind(
  sqlite3_changeset_iter *pIter,
  SessionApplyCtx *p,
  int bPatchset,
  sqlite3_stmt **ppStmt
){
  int rc = SQLITE_OK;
  SessionUpdate *pUp = 0;
  int nCol = pIter->nCol;
  int nU32 = (pIter->nCol+33)/32;
  int ii;

  if( p->aUpdateMask==0 ){
    p->aUpdateMask = sqlite3_malloc(nU32*sizeof(u32));
    if( p->aUpdateMask==0 ){
      rc = SQLITE_NOMEM;
    }
  }

  if( rc==SQLITE_OK ){
    memset(p->aUpdateMask, 0, nU32*sizeof(u32));
    rc = SQLITE_CORRUPT;
    for(ii=0; ii<pIter->nCol; ii++){
      if( sessionChangesetNew(pIter, ii) ){
        p->aUpdateMask[ii/32] |= (1<<(ii%32));
        rc = SQLITE_OK;
      }
    }
  }

  if( rc==SQLITE_OK ){
    if( bPatchset ) p->aUpdateMask[nCol/32] |= (1<<(nCol%32));

    if( p->pUp ){
      int nUp = 0;
      SessionUpdate **pp = &p->pUp;
      while( 1 ){
        nUp++;
        if( 0==memcmp(p->aUpdateMask, (*pp)->aMask, nU32*sizeof(u32)) ){
          pUp = *pp;
          *pp = pUp->pNext;
          pUp->pNext = p->pUp;
          p->pUp = pUp;
          break;
        }

        if( (*pp)->pNext ){
          pp = &(*pp)->pNext;
        }else{
          if( nUp>=SESSION_UPDATE_CACHE_SZ ){
            sqlite3_finalize((*pp)->pStmt);
            sqlite3_free(*pp);
            *pp = 0;
          }
          break;
        }
      }
    }

    if( pUp==0 ){
      int nByte = sizeof(SessionUpdate) * nU32*sizeof(u32);
      int bStat1 = (sqlite3_stricmp(pIter->zTab, "sqlite_stat1")==0);
      pUp = (SessionUpdate*)sqlite3_malloc(nByte);
      if( pUp==0 ){
        rc = SQLITE_NOMEM;
      }else{
        const char *zSep = "";
        SessionBuffer buf;

        memset(&buf, 0, sizeof(buf));
        pUp->aMask = (u32*)&pUp[1];
        memcpy(pUp->aMask, p->aUpdateMask, nU32*sizeof(u32));

        sessionAppendStr(&buf, "UPDATE main.", &rc);
        sessionAppendIdent(&buf, pIter->zTab, &rc);
        sessionAppendStr(&buf, " SET ", &rc);

        /* Create the assignments part of the UPDATE */
        for(ii=0; ii<pIter->nCol; ii++){
          if( p->abPK[ii]==0 && sessionChangesetNew(pIter, ii) ){
            sessionAppendStr(&buf, zSep, &rc);
            sessionAppendIdent(&buf, p->azCol[ii], &rc);
            sessionAppendStr(&buf, " = ?", &rc);
            sessionAppendInteger(&buf, ii*2+1, &rc);
            zSep = ", ";
          }
        }

        /* Create the WHERE clause part of the UPDATE */
        zSep = "";
        sessionAppendStr(&buf, " WHERE ", &rc);
        for(ii=0; ii<pIter->nCol; ii++){
          if( p->abPK[ii] || (bPatchset==0 && sessionChangesetOld(pIter, ii)) ){
            sessionAppendStr(&buf, zSep, &rc);
            if( bStat1 && ii==1 ){
              assert( sqlite3_stricmp(p->azCol[ii], "idx")==0 );
              sessionAppendStr(&buf, 
                  "idx IS CASE "
                  "WHEN length(?4)=0 AND typeof(?4)='blob' THEN NULL "
                  "ELSE ?4 END ", &rc
              );
            }else{
              sessionAppendIdent(&buf, p->azCol[ii], &rc);
              sessionAppendStr(&buf, " IS ?", &rc);
              sessionAppendInteger(&buf, ii*2+2, &rc);
            }
            zSep = " AND ";
          }
        }

        if( rc==SQLITE_OK ){
          char *zSql = (char*)buf.aBuf;
          rc = sqlite3_prepare_v2(p->db, zSql, buf.nBuf, &pUp->pStmt, 0);
        }

        if( rc!=SQLITE_OK ){
          sqlite3_free(pUp);
          pUp = 0;
        }else{
          pUp->pNext = p->pUp;
          p->pUp = pUp;
        }
        sqlite3_free(buf.aBuf);
      }
    }
  }

  assert( (rc==SQLITE_OK)==(pUp!=0) );
  if( pUp ){
    *ppStmt = pUp->pStmt;
  }else{
    *ppStmt = 0;
  }
  return rc;
}

/*
** Free all cached UPDATE statements.
*/
static void sessionUpdateFree(SessionApplyCtx *p){
  SessionUpdate *pUp;
  SessionUpdate *pNext;
  for(pUp=p->pUp; pUp; pUp=pNext){
    pNext = pUp->pNext;
    sqlite3_finalize(pUp->pStmt);
    sqlite3_free(pUp);
  }
  p->pUp = 0;
  sqlite3_free(p->aUpdateMask);
  p->aUpdateMask = 0;
}

/*
** Formulate a statement to DELETE a row from database db. Assuming a table
** structure like this:
**
**     CREATE TABLE x(a, b, c, d, PRIMARY KEY(a, c));
**
3528
3529
3530
3531
3532
3533
3534
3535

3536
3537
3538
3539
3540
3541
3542
3990
3991
3992
3993
3994
3995
3996

3997
3998
3999
4000
4001
4002
4003
4004







-
+







){
  int i;
  const char *zSep = "";
  int rc = SQLITE_OK;
  SessionBuffer buf = {0, 0, 0};
  int nPk = 0;

  sessionAppendStr(&buf, "DELETE FROM ", &rc);
  sessionAppendStr(&buf, "DELETE FROM main.", &rc);
  sessionAppendIdent(&buf, zTab, &rc);
  sessionAppendStr(&buf, " WHERE ", &rc);

  for(i=0; i<p->nCol; i++){
    if( p->abPK[i] ){
      nPk++;
      sessionAppendStr(&buf, zSep, &rc);
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
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
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
4030
4031
4032
4033
4034
4035
4036

































































































4037
4038
4039
4040
4041
4042
4043







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







  if( rc==SQLITE_OK ){
    rc = sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, &p->pDelete, 0);
  }
  sqlite3_free(buf.aBuf);

  return rc;
}

/*
** Formulate and prepare a statement to UPDATE a row from database db. 
** Assuming a table structure like this:
**
**     CREATE TABLE x(a, b, c, d, PRIMARY KEY(a, c));
**
** The UPDATE statement looks like this:
**
**     UPDATE x SET
**     a = CASE WHEN ?2  THEN ?3  ELSE a END,
**     b = CASE WHEN ?5  THEN ?6  ELSE b END,
**     c = CASE WHEN ?8  THEN ?9  ELSE c END,
**     d = CASE WHEN ?11 THEN ?12 ELSE d END
**     WHERE a = ?1 AND c = ?7 AND (?13 OR 
**       (?5==0 OR b IS ?4) AND (?11==0 OR d IS ?10) AND
**     )
**
** For each column in the table, there are three variables to bind:
**
**     ?(i*3+1)    The old.* value of the column, if any.
**     ?(i*3+2)    A boolean flag indicating that the value is being modified.
**     ?(i*3+3)    The new.* value of the column, if any.
**
** Also, a boolean flag that, if set to true, causes the statement to update
** a row even if the non-PK values do not match. This is required if the
** conflict-handler is invoked with CHANGESET_DATA and returns
** CHANGESET_REPLACE. This is variable "?(nCol*3+1)".
**
** If successful, SQLITE_OK is returned and SessionApplyCtx.pUpdate is left
** pointing to the prepared version of the SQL statement.
*/
static int sessionUpdateRow(
  sqlite3 *db,                    /* Database handle */
  const char *zTab,               /* Table name */
  SessionApplyCtx *p              /* Session changeset-apply context */
){
  int rc = SQLITE_OK;
  int i;
  const char *zSep = "";
  SessionBuffer buf = {0, 0, 0};

  /* Append "UPDATE tbl SET " */
  sessionAppendStr(&buf, "UPDATE ", &rc);
  sessionAppendIdent(&buf, zTab, &rc);
  sessionAppendStr(&buf, " SET ", &rc);

  /* Append the assignments */
  for(i=0; i<p->nCol; i++){
    sessionAppendStr(&buf, zSep, &rc);
    sessionAppendIdent(&buf, p->azCol[i], &rc);
    sessionAppendStr(&buf, " = CASE WHEN ?", &rc);
    sessionAppendInteger(&buf, i*3+2, &rc);
    sessionAppendStr(&buf, " THEN ?", &rc);
    sessionAppendInteger(&buf, i*3+3, &rc);
    sessionAppendStr(&buf, " ELSE ", &rc);
    sessionAppendIdent(&buf, p->azCol[i], &rc);
    sessionAppendStr(&buf, " END", &rc);
    zSep = ", ";
  }

  /* Append the PK part of the WHERE clause */
  sessionAppendStr(&buf, " WHERE ", &rc);
  for(i=0; i<p->nCol; i++){
    if( p->abPK[i] ){
      sessionAppendIdent(&buf, p->azCol[i], &rc);
      sessionAppendStr(&buf, " = ?", &rc);
      sessionAppendInteger(&buf, i*3+1, &rc);
      sessionAppendStr(&buf, " AND ", &rc);
    }
  }

  /* Append the non-PK part of the WHERE clause */
  sessionAppendStr(&buf, " (?", &rc);
  sessionAppendInteger(&buf, p->nCol*3+1, &rc);
  sessionAppendStr(&buf, " OR 1", &rc);
  for(i=0; i<p->nCol; i++){
    if( !p->abPK[i] ){
      sessionAppendStr(&buf, " AND (?", &rc);
      sessionAppendInteger(&buf, i*3+2, &rc);
      sessionAppendStr(&buf, "=0 OR ", &rc);
      sessionAppendIdent(&buf, p->azCol[i], &rc);
      sessionAppendStr(&buf, " IS ?", &rc);
      sessionAppendInteger(&buf, i*3+1, &rc);
      sessionAppendStr(&buf, ")", &rc);
    }
  }
  sessionAppendStr(&buf, ")", &rc);

  if( rc==SQLITE_OK ){
    rc = sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, &p->pUpdate, 0);
  }
  sqlite3_free(buf.aBuf);

  return rc;
}


/*
** Formulate and prepare an SQL statement to query table zTab by primary
** key. Assuming the following table structure:
**
**     CREATE TABLE x(a, b, c, d, PRIMARY KEY(a, c));
**
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
4111
4112
4113
4114
4115
4116
4117











4118
4119
4120
4121
4122
4123
4124







-
-
-
-
-
-
-
-
-
-
-







  if( rc==SQLITE_OK ){
    rc = sessionPrepare(db, &p->pInsert,
        "INSERT INTO main.sqlite_stat1 VALUES(?1, "
        "CASE WHEN length(?2)=0 AND typeof(?2)='blob' THEN NULL ELSE ?2 END, "
        "?3)"
    );
  }
  if( rc==SQLITE_OK ){
    rc = sessionPrepare(db, &p->pUpdate,
        "UPDATE main.sqlite_stat1 SET "
        "tbl = CASE WHEN ?2 THEN ?3 ELSE tbl END, "
        "idx = CASE WHEN ?5 THEN ?6 ELSE idx END, "
        "stat = CASE WHEN ?8 THEN ?9 ELSE stat END  "
        "WHERE tbl=?1 AND idx IS "
        "CASE WHEN length(?4)=0 AND typeof(?4)='blob' THEN NULL ELSE ?4 END "
        "AND (?10 OR ?8=0 OR stat IS ?7)"
    );
  }
  if( rc==SQLITE_OK ){
    rc = sessionPrepare(db, &p->pDelete,
        "DELETE FROM main.sqlite_stat1 WHERE tbl=?1 AND idx IS "
        "CASE WHEN length(?2)=0 AND typeof(?2)='blob' THEN NULL ELSE ?2 END "
        "AND (?4 OR stat IS ?3)"
    );
  }
3822
3823
3824
3825
3826
3827
3828
3829

3830
3831
3832
3833
3834
3835
3836
4176
4177
4178
4179
4180
4181
4182

4183
4184
4185
4186
4187
4188
4189
4190







-
+







  ** argument iterator points to a suitable entry. Make sure that xValue 
  ** is one of these to guarantee that it is safe to ignore the return 
  ** in the code below. */
  assert( xValue==sqlite3changeset_old || xValue==sqlite3changeset_new );

  for(i=0; rc==SQLITE_OK && i<nCol; i++){
    if( !abPK || abPK[i] ){
      sqlite3_value *pVal;
      sqlite3_value *pVal = 0;
      (void)xValue(pIter, i, &pVal);
      if( pVal==0 ){
        /* The value in the changeset was "undefined". This indicates a
        ** corrupt changeset blob.  */
        rc = SQLITE_CORRUPT_BKPT;
      }else{
        rc = sessionBindValue(pStmt, i+1, pVal);
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
4208
4209
4210
4211
4212
4213
4214

4215
4216
4217
4218
4219
4220
4221







-







** not require a reset().
**
** If the iterator currently points to an INSERT record, bind values from the
** new.* record to the SELECT statement. Or, if it points to a DELETE or
** UPDATE, bind values from the old.* record. 
*/
static int sessionSeekToRow(
  sqlite3 *db,                    /* Database handle */
  sqlite3_changeset_iter *pIter,  /* Changeset iterator */
  u8 *abPK,                       /* Primary key flags array */
  sqlite3_stmt *pSelect           /* SELECT statement from sessionSelectRow() */
){
  int rc;                         /* Return code */
  int nCol;                       /* Number of columns in table */
  int op;                         /* Changset operation (SQLITE_UPDATE etc.) */
3879
3880
3881
3882
3883
3884
3885
3886

3887
3888
3889
3890
3891
3892
3893
4232
4233
4234
4235
4236
4237
4238

4239
4240
4241
4242
4243
4244
4245
4246







-
+







    if( rc!=SQLITE_ROW ) rc = sqlite3_reset(pSelect);
  }

  return rc;
}

/*
** This function is called from within sqlite3changset_apply_v2() when
** This function is called from within sqlite3changeset_apply_v2() when
** a conflict is encountered and resolved using conflict resolution
** mode eType (either SQLITE_CHANGESET_OMIT or SQLITE_CHANGESET_REPLACE)..
** It adds a conflict resolution record to the buffer in 
** SessionApplyCtx.rebase, which will eventually be returned to the caller
** of apply_v2() as the "rebase" buffer.
**
** Return SQLITE_OK if successful, or an SQLite error code otherwise.
3984
3985
3986
3987
3988
3989
3990
3991

3992
3993
3994
3995
3996
3997
3998
4337
4338
4339
4340
4341
4342
4343

4344
4345
4346
4347
4348
4349
4350
4351







-
+








  assert( eType==SQLITE_CHANGESET_CONFLICT || eType==SQLITE_CHANGESET_DATA );
  assert( SQLITE_CHANGESET_CONFLICT+1==SQLITE_CHANGESET_CONSTRAINT );
  assert( SQLITE_CHANGESET_DATA+1==SQLITE_CHANGESET_NOTFOUND );

  /* Bind the new.* PRIMARY KEY values to the SELECT statement. */
  if( pbReplace ){
    rc = sessionSeekToRow(p->db, pIter, p->abPK, p->pSelect);
    rc = sessionSeekToRow(pIter, p->abPK, p->pSelect);
  }else{
    rc = SQLITE_OK;
  }

  if( rc==SQLITE_ROW ){
    /* There exists another row with the new.* primary key. */
    pIter->pConflict = p->pSelect;
4073
4074
4075
4076
4077
4078
4079
4080

4081
4082
4083
4084
4085
4086
4087
4426
4427
4428
4429
4430
4431
4432

4433
4434
4435
4436
4437
4438
4439
4440







-
+







  int *pbRetry                    /* OUT: True to retry. */
){
  const char *zDummy;
  int op;
  int nCol;
  int rc = SQLITE_OK;

  assert( p->pDelete && p->pUpdate && p->pInsert && p->pSelect );
  assert( p->pDelete && p->pInsert && p->pSelect );
  assert( p->azCol && p->abPK );
  assert( !pbReplace || *pbReplace==0 );

  sqlite3changeset_op(pIter, &zDummy, &nCol, &op, 0);

  if( op==SQLITE_DELETE ){

4113
4114
4115
4116
4117
4118
4119




4120
4121
4122
4123
4124
4125

4126
4127
4128

4129
4130
4131

4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142


4143
4144
4145
4146
4147
4148
4149
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481

4482



4483
4484
4485

4486
4487
4488



4489
4490
4491
4492


4493
4494
4495
4496
4497
4498
4499
4500
4501







+
+
+
+





-
+
-
-
-
+


-
+


-
-
-




-
-
+
+







      rc = sessionConflictHandler(
          SQLITE_CHANGESET_CONFLICT, p, pIter, xConflict, pCtx, 0
      );
    }

  }else if( op==SQLITE_UPDATE ){
    int i;
    sqlite3_stmt *pUp = 0;
    int bPatchset = (pbRetry==0 || pIter->bPatchset);

    rc = sessionUpdateFind(pIter, p, bPatchset, &pUp);

    /* Bind values to the UPDATE statement. */
    for(i=0; rc==SQLITE_OK && i<nCol; i++){
      sqlite3_value *pOld = sessionChangesetOld(pIter, i);
      sqlite3_value *pNew = sessionChangesetNew(pIter, i);

      if( p->abPK[i] || (bPatchset==0 && pOld) ){
      sqlite3_bind_int(p->pUpdate, i*3+2, !!pNew);
      if( pOld ){
        rc = sessionBindValue(p->pUpdate, i*3+1, pOld);
        rc = sessionBindValue(pUp, i*2+2, pOld);
      }
      if( rc==SQLITE_OK && pNew ){
        rc = sessionBindValue(p->pUpdate, i*3+3, pNew);
        rc = sessionBindValue(pUp, i*2+1, pNew);
      }
    }
    if( rc==SQLITE_OK ){
      sqlite3_bind_int(p->pUpdate, nCol*3+1, pbRetry==0 || pIter->bPatchset);
    }
    if( rc!=SQLITE_OK ) return rc;

    /* Attempt the UPDATE. In the case of a NOTFOUND or DATA conflict,
    ** the result will be SQLITE_OK with 0 rows modified. */
    sqlite3_step(p->pUpdate);
    rc = sqlite3_reset(p->pUpdate);
    sqlite3_step(pUp);
    rc = sqlite3_reset(pUp);

    if( rc==SQLITE_OK && sqlite3_changes(p->db)==0 ){
      /* A NOTFOUND or DATA error. Search the table to see if it contains
      ** a row with a matching primary key. If so, this is a DATA conflict.
      ** Otherwise, if there is no primary key match, it is a NOTFOUND. */

      rc = sessionConflictHandler(
4159
4160
4161
4162
4163
4164
4165
4166

4167
4168
4169
4170
4171
4172
4173
4511
4512
4513
4514
4515
4516
4517

4518
4519
4520
4521
4522
4523
4524
4525







-
+








  }else{
    assert( op==SQLITE_INSERT );
    if( p->bStat1 ){
      /* Check if there is a conflicting row. For sqlite_stat1, this needs
      ** to be done using a SELECT, as there is no PRIMARY KEY in the 
      ** database schema to throw an exception if a duplicate is inserted.  */
      rc = sessionSeekToRow(p->db, pIter, p->abPK, p->pSelect);
      rc = sessionSeekToRow(pIter, p->abPK, p->pSelect);
      if( rc==SQLITE_ROW ){
        rc = SQLITE_CONSTRAINT;
        sqlite3_reset(p->pSelect);
      }
    }

    if( rc==SQLITE_OK ){
4266
4267
4268
4269
4270
4271
4272
4273



4274
4275

4276
4277
4278
4279
4280
4281
4282
4618
4619
4620
4621
4622
4623
4624

4625
4626
4627
4628

4629
4630
4631
4632
4633
4634
4635
4636







-
+
+
+

-
+







  int rc = SQLITE_OK;

  while( pApply->constraints.nBuf ){
    sqlite3_changeset_iter *pIter2 = 0;
    SessionBuffer cons = pApply->constraints;
    memset(&pApply->constraints, 0, sizeof(SessionBuffer));

    rc = sessionChangesetStart(&pIter2, 0, 0, cons.nBuf, cons.aBuf, 0);
    rc = sessionChangesetStart(
        &pIter2, 0, 0, cons.nBuf, cons.aBuf, pApply->bInvertConstraints, 1
    );
    if( rc==SQLITE_OK ){
      int nByte = 2*pApply->nCol*sizeof(sqlite3_value*);
      size_t nByte = 2*pApply->nCol*sizeof(sqlite3_value*);
      int rc2;
      pIter2->bPatchset = bPatchset;
      pIter2->zTab = (char*)zTab;
      pIter2->nCol = pApply->nCol;
      pIter2->abPK = pApply->abPK;
      sessionBufferGrow(&pIter2->tblhdr, nByte, &rc);
      pIter2->apValue = (sqlite3_value**)pIter2->tblhdr.aBuf;
4333
4334
4335
4336
4337
4338
4339

4340
4341
4342
4343
4344
4345
4346
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701







+







  int bPatchset;

  assert( xConflict!=0 );

  pIter->in.bNoDiscard = 1;
  memset(&sApply, 0, sizeof(sApply));
  sApply.bRebase = (ppRebase && pnRebase);
  sApply.bInvertConstraints = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
  sqlite3_mutex_enter(sqlite3_db_mutex(db));
  if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){
    rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0);
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3_exec(db, "PRAGMA defer_foreign_keys = 1", 0, 0, 0);
  }
4355
4356
4357
4358
4359
4360
4361

4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719

4720
4721
4722
4723

4724
4725
4726
4727
4728
4729
4730







+


-




-







      u8 *abPK;

      rc = sessionRetryConstraints(
          db, pIter->bPatchset, zTab, &sApply, xConflict, pCtx
      );
      if( rc!=SQLITE_OK ) break;

      sessionUpdateFree(&sApply);
      sqlite3_free((char*)sApply.azCol);  /* cast works around VC++ bug */
      sqlite3_finalize(sApply.pDelete);
      sqlite3_finalize(sApply.pUpdate); 
      sqlite3_finalize(sApply.pInsert);
      sqlite3_finalize(sApply.pSelect);
      sApply.db = db;
      sApply.pDelete = 0;
      sApply.pUpdate = 0;
      sApply.pInsert = 0;
      sApply.pSelect = 0;
      sApply.nCol = 0;
      sApply.azCol = 0;
      sApply.abPK = 0;
      sApply.bStat1 = 0;
      sApply.bDeferConstraints = 1;
4390
4391
4392
4393
4394
4395
4396
4397

4398
4399
4400
4401
4402
4403
4404
4744
4745
4746
4747
4748
4749
4750

4751
4752
4753
4754
4755
4756
4757
4758







-
+







        nTab = (int)strlen(zTab);
        sApply.azCol = (const char **)zTab;
      }else{
        int nMinCol = 0;
        int i;

        sqlite3changeset_pk(pIter, &abPK, 0);
        rc = sessionTableInfo(
        rc = sessionTableInfo(0, 
            db, "main", zNew, &sApply.nCol, &zTab, &sApply.azCol, &sApply.abPK
        );
        if( rc!=SQLITE_OK ) break;
        for(i=0; i<sApply.nCol; i++){
          if( sApply.abPK[i] ) nMinCol = i+1;
        }
  
4426
4427
4428
4429
4430
4431
4432
4433

4434
4435
4436
4437



4438
4439
4440
4441
4442
4443
4444
4780
4781
4782
4783
4784
4785
4786

4787




4788
4789
4790
4791
4792
4793
4794
4795
4796
4797







-
+
-
-
-
-
+
+
+







          sApply.nCol = nCol;
          if( 0==sqlite3_stricmp(zTab, "sqlite_stat1") ){
            if( (rc = sessionStat1Sql(db, &sApply) ) ){
              break;
            }
            sApply.bStat1 = 1;
          }else{
            if((rc = sessionSelectRow(db, zTab, &sApply))
            if( (rc = sessionSelectRow(db, zTab, &sApply))
                || (rc = sessionUpdateRow(db, zTab, &sApply))
                || (rc = sessionDeleteRow(db, zTab, &sApply))
                || (rc = sessionInsertRow(db, zTab, &sApply))
              ){
             || (rc = sessionDeleteRow(db, zTab, &sApply))
             || (rc = sessionInsertRow(db, zTab, &sApply))
            ){
              break;
            }
            sApply.bStat1 = 0;
          }
        }
        nTab = sqlite3Strlen30(zTab);
      }
4489
4490
4491
4492
4493
4494
4495

4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851

4852
4853
4854
4855
4856
4857
4858







+


-








  assert( sApply.bRebase || sApply.rebase.nBuf==0 );
  if( rc==SQLITE_OK && bPatchset==0 && sApply.bRebase ){
    *ppRebase = (void*)sApply.rebase.aBuf;
    *pnRebase = sApply.rebase.nBuf;
    sApply.rebase.aBuf = 0;
  }
  sessionUpdateFree(&sApply);
  sqlite3_finalize(sApply.pInsert);
  sqlite3_finalize(sApply.pDelete);
  sqlite3_finalize(sApply.pUpdate);
  sqlite3_finalize(sApply.pSelect);
  sqlite3_free((char*)sApply.azCol);  /* cast works around VC++ bug */
  sqlite3_free((char*)sApply.constraints.aBuf);
  sqlite3_free((char*)sApply.rebase.aBuf);
  sqlite3_mutex_leave(sqlite3_db_mutex(db));
  return rc;
}
4522
4523
4524
4525
4526
4527
4528
4529
4530


4531
4532
4533
4534
4535
4536
4537
4875
4876
4877
4878
4879
4880
4881


4882
4883
4884
4885
4886
4887
4888
4889
4890







-
-
+
+







    sqlite3_changeset_iter *p     /* Handle describing change and conflict */
  ),
  void *pCtx,                     /* First argument passed to xConflict */
  void **ppRebase, int *pnRebase,
  int flags
){
  sqlite3_changeset_iter *pIter;  /* Iterator to skip through changeset */  
  int bInverse = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
  int rc = sessionChangesetStart(&pIter, 0, 0, nChangeset, pChangeset,bInverse);
  int bInv = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
  int rc = sessionChangesetStart(&pIter, 0, 0, nChangeset, pChangeset, bInv, 1);
  if( rc==SQLITE_OK ){
    rc = sessionChangesetApply(
        db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags
    );
  }
  return rc;
}
4581
4582
4583
4584
4585
4586
4587
4588

4589
4590
4591
4592
4593
4594
4595
4934
4935
4936
4937
4938
4939
4940

4941
4942
4943
4944
4945
4946
4947
4948







-
+







  ),
  void *pCtx,                     /* First argument passed to xConflict */
  void **ppRebase, int *pnRebase,
  int flags
){
  sqlite3_changeset_iter *pIter;  /* Iterator to skip through changeset */  
  int bInverse = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
  int rc = sessionChangesetStart(&pIter, xInput, pIn, 0, 0, bInverse);
  int rc = sessionChangesetStart(&pIter, xInput, pIn, 0, 0, bInverse, 1);
  if( rc==SQLITE_OK ){
    rc = sessionChangesetApply(
        db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags
    );
  }
  return rc;
}
4638
4639
4640
4641
4642
4643
4644
4645

4646
4647
4648
4649
4650
4651
4652
4991
4992
4993
4994
4995
4996
4997

4998
4999
5000
5001
5002
5003
5004
5005







-
+







  int nRec,                       /* Number of bytes in aRec */
  SessionChange **ppNew           /* OUT: Merged change */
){
  SessionChange *pNew = 0;
  int rc = SQLITE_OK;

  if( !pExist ){
    pNew = (SessionChange *)sqlite3_malloc(sizeof(SessionChange) + nRec);
    pNew = (SessionChange *)sqlite3_malloc64(sizeof(SessionChange) + nRec);
    if( !pNew ){
      return SQLITE_NOMEM;
    }
    memset(pNew, 0, sizeof(SessionChange));
    pNew->op = op2;
    pNew->bIndirect = bIndirect;
    pNew->aRecord = (u8*)&pNew[1];
4671
4672
4673
4674
4675
4676
4677
4678
4679


4680
4681
4682
4683
4684
4685
4686
5024
5025
5026
5027
5028
5029
5030


5031
5032
5033
5034
5035
5036
5037
5038
5039







-
-
+
+







      }
      pNew->nRecord = pOut - pNew->aRecord;
    }
  }else if( bRebase ){
    if( pExist->op==SQLITE_DELETE && pExist->bIndirect ){
      *ppNew = pExist;
    }else{
      int nByte = nRec + pExist->nRecord + sizeof(SessionChange);
      pNew = (SessionChange*)sqlite3_malloc(nByte);
      sqlite3_int64 nByte = nRec + pExist->nRecord + sizeof(SessionChange);
      pNew = (SessionChange*)sqlite3_malloc64(nByte);
      if( pNew==0 ){
        rc = SQLITE_NOMEM;
      }else{
        int i;
        u8 *a1 = pExist->aRecord;
        u8 *a2 = aRec;
        u8 *pOut;
4732
4733
4734
4735
4736
4737
4738
4739

4740
4741
4742
4743
4744
4745
4746

4747
4748
4749
4750
4751
4752
4753
5085
5086
5087
5088
5089
5090
5091

5092
5093
5094
5095
5096
5097
5098

5099
5100
5101
5102
5103
5104
5105
5106







-
+






-
+







    ){
      pNew = pExist;
    }else if( op1==SQLITE_INSERT && op2==SQLITE_DELETE ){
      sqlite3_free(pExist);
      assert( pNew==0 );
    }else{
      u8 *aExist = pExist->aRecord;
      int nByte;
      sqlite3_int64 nByte;
      u8 *aCsr;

      /* Allocate a new SessionChange object. Ensure that the aRecord[]
      ** buffer of the new object is large enough to hold any record that
      ** may be generated by combining the input records.  */
      nByte = sizeof(SessionChange) + pExist->nRecord + nRec;
      pNew = (SessionChange *)sqlite3_malloc(nByte);
      pNew = (SessionChange *)sqlite3_malloc64(nByte);
      if( !pNew ){
        sqlite3_free(pExist);
        return SQLITE_NOMEM;
      }
      memset(pNew, 0, sizeof(SessionChange));
      pNew->bIndirect = (bIndirect && pExist->bIndirect);
      aCsr = pNew->aRecord = (u8 *)&pNew[1];
4845
4846
4847
4848
4849
4850
4851
4852

4853
4854
4855
4856
4857
4858
4859
5198
5199
5200
5201
5202
5203
5204

5205
5206
5207
5208
5209
5210
5211
5212







-
+







      sqlite3changeset_pk(pIter, &abPK, 0);
      for(pTab = pGrp->pList; pTab; pTab=pTab->pNext){
        if( 0==sqlite3_strnicmp(pTab->zName, zNew, nNew+1) ) break;
      }
      if( !pTab ){
        SessionTable **ppTab;

        pTab = sqlite3_malloc(sizeof(SessionTable) + nCol + nNew+1);
        pTab = sqlite3_malloc64(sizeof(SessionTable) + nCol + nNew+1);
        if( !pTab ){
          rc = SQLITE_NOMEM;
          break;
        }
        memset(pTab, 0, sizeof(SessionTable));
        pTab->nCol = nCol;
        pTab->abPK = (u8*)&pTab[1];
4869
4870
4871
4872
4873
4874
4875
4876

4877
4878
4879
4880
4881
4882
4883
5222
5223
5224
5225
5226
5227
5228

5229
5230
5231
5232
5233
5234
5235
5236







-
+







        *ppTab = pTab;
      }else if( pTab->nCol!=nCol || memcmp(pTab->abPK, abPK, nCol) ){
        rc = SQLITE_SCHEMA;
        break;
      }
    }

    if( sessionGrowHash(pIter->bPatchset, pTab) ){
    if( sessionGrowHash(0, pIter->bPatchset, pTab) ){
      rc = SQLITE_NOMEM;
      break;
    }
    iHash = sessionChangeHash(
        pTab, (pIter->bPatchset && op==SQLITE_DELETE), aRec, pTab->nChange
    );

4966
4967
4968
4969
4970
4971
4972
4973

4974
4975

4976
4977
4978
4979
4980
4981
4982
5319
5320
5321
5322
5323
5324
5325

5326
5327

5328
5329
5330
5331
5332
5333
5334
5335







-
+

-
+







      }
    }
  }

  if( rc==SQLITE_OK ){
    if( xOutput ){
      if( buf.nBuf>0 ) rc = xOutput(pOut, buf.aBuf, buf.nBuf);
    }else{
    }else if( ppOut ){
      *ppOut = buf.aBuf;
      *pnOut = buf.nBuf;
      if( pnOut ) *pnOut = buf.nBuf;
      buf.aBuf = 0;
    }
  }
  sqlite3_free(buf.aBuf);

  return rc;
}
5056
5057
5058
5059
5060
5061
5062
5063

5064
5065
5066
5067
5068
5069
5070
5409
5410
5411
5412
5413
5414
5415

5416
5417
5418
5419
5420
5421
5422
5423







-
+







}

/*
** Delete a changegroup object.
*/
void sqlite3changegroup_delete(sqlite3_changegroup *pGrp){
  if( pGrp ){
    sessionDeleteTable(pGrp->pList);
    sessionDeleteTable(0, pGrp->pList);
    sqlite3_free(pGrp);
  }
}

/* 
** Combine two changesets together.
*/
5202
5203
5204
5205
5206
5207
5208
5209

5210
5211
5212

5213
5214
5215
5216
5217
5218
5219
5555
5556
5557
5558
5559
5560
5561

5562
5563
5564

5565
5566
5567
5568
5569
5570
5571
5572







-
+


-
+








    *pOut++ = SQLITE_UPDATE;
    *pOut++ = pIter->bIndirect;
    for(i=0; i<pIter->nCol; i++){
      int n1 = sessionSerialLen(a1);
      int n2 = sessionSerialLen(a2);
      if( pIter->abPK[i] || a2[0]==0 ){
        if( !pIter->abPK[i] ) bData = 1;
        if( !pIter->abPK[i] && a1[0] ) bData = 1;
        memcpy(pOut, a1, n1);
        pOut += n1;
      }else if( a2[0]!=0xFF ){
      }else if( a2[0]!=0xFF && a1[0] ){
        bData = 1;
        memcpy(pOut, a2, n2);
        pOut += n2;
      }else{
        *pOut++ = '\0';
      }
      a1 += n1;
5368
5369
5370
5371
5372
5373
5374
5375

5376
5377
5378
5379
5380
5381
5382
5721
5722
5723
5724
5725
5726
5727

5728
5729
5730
5731
5732
5733
5734
5735







-
+







  }

  if( rc==SQLITE_OK ){
    if( xOutput ){
      if( sOut.nBuf>0 ){
        rc = xOutput(pOut, sOut.aBuf, sOut.nBuf);
      }
    }else{
    }else if( ppOut ){
      *ppOut = (void*)sOut.aBuf;
      *pnOut = sOut.nBuf;
      sOut.aBuf = 0;
    }
  }
  sqlite3_free(sOut.aBuf);
  return rc;
5457
5458
5459
5460
5461
5462
5463
5464

5465
5466
5467
5468
5469
5470
5471
5810
5811
5812
5813
5814
5815
5816

5817
5818
5819
5820
5821
5822
5823
5824







-
+







}

/* 
** Destroy a rebaser object 
*/
void sqlite3rebaser_delete(sqlite3_rebaser *p){
  if( p ){
    sessionDeleteTable(p->grp.pList);
    sessionDeleteTable(0, p->grp.pList);
    sqlite3_free(p);
  }
}

/* 
** Global configuration
*/

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
196
197
198
199
200
201
202
203

204
205
206
207
208
209
210
228
229
230
231
232
233
234

235
236
237
238
239
240
241
242







-
+







/*
** CAPI3REF: Set a table filter on a Session Object.
** METHOD: sqlite3_session
**
** The second argument (xFilter) is the "filter callback". For changes to rows 
** in tables that are not attached to the Session object, the filter is called
** to determine whether changes to the table's rows should be tracked or not. 
** If xFilter returns 0, changes is not tracked. Note that once a table is 
** If xFilter returns 0, changes are not tracked. Note that once a table is 
** attached, xFilter will not be called again.
*/
void sqlite3session_table_filter(
  sqlite3_session *pSession,      /* Session object */
  int(*xFilter)(
    void *pCtx,                   /* Copy of third arg to _filter_table() */
    const char *zTab              /* Table name */
332
333
334
335
336
337
338





























339
340
341
342
343
344
345
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







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







*/
int sqlite3session_fullchangeset(
  sqlite3_session *pSession,      /* Session object */
  int *pnChangeset,               /* OUT: Size of buffer at *ppChangeset */
  void **ppChangeset              /* OUT: Buffer containing changeset */
);

/*
** CAPI3REF: Generate A Full Changeset From A Session Object
**
** This function is similar to sqlite3session_changeset(), except that for
** each row affected by an UPDATE statement, all old.* values are recorded
** as part of the changeset, not just those modified.
*/
int sqlite3session_fullchangeset(
  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
383
384
385
386
387
388
389
390

391
392
393
394
395
396
397
444
445
446
447
448
449
450

451
452
453
454
455
456
457
458







-
+







** using [sqlite3session_changeset()], then after applying that changeset to 
** database zFrom the contents of the two compatible tables would be 
** identical.
**
** It an error if database zFrom does not exist or does not contain the
** required compatible table.
**
** If the operation successful, SQLITE_OK is returned. Otherwise, an SQLite
** If the operation is successful, SQLITE_OK is returned. Otherwise, an SQLite
** error code. In this case, if argument pzErrMsg is not NULL, *pzErrMsg
** may be set to point to a buffer containing an English language error 
** message. It is the responsibility of the caller to free this buffer using
** sqlite3_free().
*/
int sqlite3session_diff(
  sqlite3_session *pSession,
449
450
451
452
453
454
455








456
457
458
459
460
461
462
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531







+
+
+
+
+
+
+
+







** an attached table is modified and then later on the original values 
** are restored. However, if this function returns non-zero, then it is
** guaranteed that a call to sqlite3session_changeset() will return a 
** changeset containing zero changes.
*/
int sqlite3session_isempty(sqlite3_session *pSession);

/*
** CAPI3REF: Query for the amount of heap memory used by a session object.
**
** This API returns the total amount of heap memory in bytes currently 
** used by the session object passed as the only argument.
*/
sqlite3_int64 sqlite3session_memory_used(sqlite3_session *pSession);

/*
** CAPI3REF: Create An Iterator To Traverse A Changeset 
** CONSTRUCTOR: sqlite3_changeset_iter
**
** Create an iterator used to iterate through the contents of a changeset.
** If successful, *pp is set to point to the iterator handle and SQLITE_OK
** is returned. Otherwise, if an error occurs, *pp is set to zero and an
520
521
522
523
524
525
526
527

528
529
530
531
532
533
534
589
590
591
592
593
594
595

596
597
598
599
600
601
602
603







-
+







#define SQLITE_CHANGESETSTART_INVERT        0x0002


/*
** CAPI3REF: Advance A Changeset Iterator
** METHOD: sqlite3_changeset_iter
**
** This function may only be used with iterators created by function
** This function may only be used with iterators created by the function
** [sqlite3changeset_start()]. If it is called on an iterator passed to
** a conflict-handler callback by [sqlite3changeset_apply()], SQLITE_MISUSE
** is returned and the call has no effect.
**
** Immediately after an iterator is created by sqlite3changeset_start(), it
** does not point to any change in the changeset. Assuming the changeset
** is not empty, the first call to this function advances the iterator to
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
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







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


-
+
-
-







**
** The pIter argument passed to this function may either be an iterator
** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator
** created by [sqlite3changeset_start()]. In the latter case, the most recent
** call to [sqlite3changeset_next()] must have returned [SQLITE_ROW]. If this
** is not the case, this function returns [SQLITE_MISUSE].
**
** Arguments pOp, pnCol and pzTab may not be NULL. Upon return, three
** outputs are set through these pointers: 
**
** If argument pzTab is not NULL, then *pzTab is set to point to a
** nul-terminated utf-8 encoded string containing the name of the table
** affected by the current change. The buffer remains valid until either
** sqlite3changeset_next() is called on the iterator or until the 
** conflict-handler function returns. If pnCol is not NULL, then *pnCol is 
** *pOp is set to one of [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE],
** depending on the type of change that the iterator currently points to;
**
** *pnCol is set to the number of columns in the table affected by the change; and
**
** *pzTab is set to point to a nul-terminated utf-8 encoded string containing
** the name of the table affected by the current change. The buffer remains
** valid until either sqlite3changeset_next() is called on the iterator
** or until the conflict-handler function returns.
** set to the number of columns in the table affected by the change. If
** pbIncorrect is not NULL, then *pbIndirect is set to true (1) if the change
**
** If pbIndirect is not NULL, then *pbIndirect is set to true (1) if the change
** is an indirect change, or false (0) otherwise. See the documentation for
** [sqlite3session_indirect()] for a description of direct and indirect
** changes. Finally, if pOp is not NULL, then *pOp is set to one of 
** changes.
** [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE], depending on the 
** type of change that the iterator currently points to.
**
** If no error occurs, SQLITE_OK is returned. If an error does occur, an
** SQLite error code is returned. The values of the output variables may not
** be trusted in this case.
*/
int sqlite3changeset_op(
  sqlite3_changeset_iter *pIter,  /* Iterator object */
936
937
938
939
940
941
942
943
944


945
946
947
948
949
950
951
1010
1011
1012
1013
1014
1015
1016


1017
1018
1019
1020
1021
1022
1023
1024
1025







-
-
+
+







**
** If the new changeset contains changes to a table that is already present
** in the changegroup, then the number of columns and the position of the
** primary key columns for the table must be consistent. If this is not the
** case, this function fails with SQLITE_SCHEMA. If the input changeset
** appears to be corrupt and the corruption is detected, SQLITE_CORRUPT is
** returned. Or, if an out-of-memory condition occurs during processing, this
** function returns SQLITE_NOMEM. In all cases, if an error occurs the
** final contents of the changegroup is undefined.
** function returns SQLITE_NOMEM. In all cases, if an error occurs the state
** of the final contents of the changegroup is undefined.
**
** If no error occurs, SQLITE_OK is returned.
*/
int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData);

/*
** CAPI3REF: Obtain A Composite Changeset From A Changegroup
1112
1113
1114
1115
1116
1117
1118
1119

1120
1121
1122
1123
1124
1125
1126
1186
1187
1188
1189
1190
1191
1192

1193
1194
1195
1196
1197
1198
1199
1200







-
+







**   This includes the case where the UPDATE operation is attempted after 
**   an earlier call to the conflict handler function returned
**   [SQLITE_CHANGESET_REPLACE].  
** </dl>
**
** It is safe to execute SQL statements, including those that write to the
** table that the callback related to, from within the xConflict callback.
** This can be used to further customize the applications conflict
** This can be used to further customize the application's conflict
** resolution strategy.
**
** All changes made by these functions are enclosed in a savepoint transaction.
** If any other error (aside from a constraint failure when attempting to
** write to the target database) occurs, then the savepoint transaction is
** rolled back, restoring the target database to its original state, and an 
** SQLite error code returned.
1422
1423
1424
1425
1426
1427
1428
1429

1430
1431

1432
1433
1434
1435
1436
1437
1438
1496
1497
1498
1499
1500
1501
1502

1503
1504

1505
1506
1507
1508
1509
1510
1511
1512







-
+

-
+








/*
** CAPI3REF: Rebase a changeset
** EXPERIMENTAL
**
** Argument pIn must point to a buffer containing a changeset nIn bytes
** in size. This function allocates and populates a buffer with a copy
** of the changeset rebased rebased according to the configuration of the
** of the changeset rebased according to the configuration of the
** rebaser object passed as the first argument. If successful, (*ppOut)
** is set to point to the new buffer containing the rebased changset and 
** is set to point to the new buffer containing the rebased changeset and 
** (*pnOut) to its size in bytes and SQLITE_OK returned. It is the
** responsibility of the caller to eventually free the new buffer using
** sqlite3_free(). Otherwise, if an error occurs, (*ppOut) and (*pnOut)
** are set to zero and an SQLite error code returned.
*/
int sqlite3rebaser_rebase(
  sqlite3_rebaser*,

Changes to ext/session/test_session.c.

94
95
96
97
98
99
100













101
102
103
104
105
106
107
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







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







  /* Delete the session object */
  sqlite3session_delete(pSession);

  return rc;
}
/************************************************************************/


#ifdef SQLITE_DEBUG
static int sqlite3_test_changeset(int, void *, char **);
static void assert_changeset_is_ok(int n, void *p){
  int rc = 0;
  char *z = 0;
  rc = sqlite3_test_changeset(n, p, &z);
  assert( z==0 );
}
#else
# define assert_changeset_is_ok(n,p)
#endif

/*
** Tclcmd: sql_exec_changeset DB SQL
*/
static int SQLITE_TCLAPI test_sql_exec_changeset(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
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
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







+



















+
+
-
+
+







  rc = sql_exec_changeset(db, zSql, &nChangeset, &pChangeset);
  if( rc!=SQLITE_OK ){
    Tcl_ResetResult(interp);
    Tcl_AppendResult(interp, "error in sql_exec_changeset()", 0);
    return TCL_ERROR;
  }

  assert_changeset_is_ok(nChangeset, pChangeset);
  Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pChangeset, nChangeset));
  sqlite3_free(pChangeset);
  return TCL_OK;
}



#define SESSION_STREAM_TCL_VAR "sqlite3session_streams"

/*
** Attempt to find the global variable zVar within interpreter interp
** and extract an integer value from it. Return this value.
**
** If the named variable cannot be found, or if it cannot be interpreted
** as a integer, return 0.
*/
static int test_tcl_integer(Tcl_Interp *interp, const char *zVar){
  Tcl_Obj *pObj;
  int iVal = 0;
  Tcl_Obj *pName = Tcl_NewStringObj(zVar, -1);
  Tcl_IncrRefCount(pName);
  pObj = Tcl_ObjGetVar2(interp, Tcl_NewStringObj(zVar, -1), 0, TCL_GLOBAL_ONLY);
  pObj = Tcl_ObjGetVar2(interp, pName, 0, TCL_GLOBAL_ONLY);
  Tcl_DecrRefCount(pName);
  if( pObj ) Tcl_GetIntFromObj(0, pObj, &iVal);
  return iVal;
}

static int test_session_error(Tcl_Interp *interp, int rc, char *zErr){
  extern const char *sqlite3ErrName(int);
  Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
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
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







-
+














+
+
+







  void *clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  TestSession *p = (TestSession*)clientData;
  sqlite3_session *pSession = p->pSession;
  struct SessionSubcmd {
  static struct SessionSubcmd {
    const char *zSub;
    int nArg;
    const char *zMsg;
  } aSub[] = {
    { "attach",       1, "TABLE"       }, /* 0 */
    { "changeset",    0, ""            }, /* 1 */
    { "delete",       0, ""            }, /* 2 */
    { "enable",       1, "BOOL"        }, /* 3 */
    { "indirect",     1, "BOOL"        }, /* 4 */
    { "isempty",      0, ""            }, /* 5 */
    { "table_filter", 1, "SCRIPT"      }, /* 6 */
    { "patchset",     0, "",           }, /* 7 */
    { "diff",         2, "FROMDB TBL"  }, /* 8 */
    { "fullchangeset",0, ""            }, /* 9 */
    { "memory_used",  0, "",           }, /* 10 */
    { "changeset_size", 0, "",         }, /* 11 */
    { "object_config_size", 1, "INTEGER", }, /* 12 */
    { 0 }
  };
  int iSub;
  int rc;

  if( objc<2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
289
290
291
292
293
294
295

296
297
298
299
300
301
302
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323







+







        }else if( iSub==9 ){
          rc = sqlite3session_fullchangeset(pSession, &o.n, &o.p);
        }else{
          rc = sqlite3session_changeset(pSession, &o.n, &o.p);
        }
      }
      if( rc==SQLITE_OK ){
        assert_changeset_is_ok(o.n, o.p);
        Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(o.p, o.n)); 
      }
      sqlite3_free(o.p);
      if( rc!=SQLITE_OK ){
        return test_session_error(interp, rc, 0);
      }
      break;
348
349
350
351
352
353
354





























355
356
357
358
359
360
361
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







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







      );
      assert( rc!=SQLITE_OK || zErr==0 );
      if( rc ){
        return test_session_error(interp, rc, zErr);
      }
      break;
    }

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

    case 11: {
      sqlite3_int64 nSize = sqlite3session_changeset_size(pSession);
      Tcl_SetObjResult(interp, Tcl_NewWideIntObj(nSize));
      break;
    }
    case 12: {
      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;
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
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







+




















+
+
+
+
+
+
+







  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;
}
911
912
913
914
915
916
917

918
919
920
921
922
923
924
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983







+







    );
  }else{
    rc = sqlite3changeset_invert(sIn.nData, sIn.aData, &sOut.n, &sOut.p);
  }
  if( rc!=SQLITE_OK ){
    rc = test_session_error(interp, rc, 0);
  }else{
    assert_changeset_is_ok(sOut.n, sOut.p);
    Tcl_SetObjResult(interp,Tcl_NewByteArrayObj((unsigned char*)sOut.p,sOut.n));
  }
  sqlite3_free(sOut.p);
  return rc;
}

/*
959
960
961
962
963
964
965

966
967
968
969
970
971
972
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032







+







        sLeft.nData, sLeft.aData, sRight.nData, sRight.aData, &sOut.n, &sOut.p
    );
  }

  if( rc!=SQLITE_OK ){
    rc = test_session_error(interp, rc, 0);
  }else{
    assert_changeset_is_ok(sOut.n, sOut.p);
    Tcl_SetObjResult(interp,Tcl_NewByteArrayObj((unsigned char*)sOut.p,sOut.n));
  }
  sqlite3_free(sOut.p);
  return rc;
}

/*
1253
1254
1255
1256
1257
1258
1259
1260

1261
1262
1263
1264
1265
1266
1267
1313
1314
1315
1316
1317
1318
1319

1320
1321
1322
1323
1324
1325
1326
1327







-
+







*/
static int SQLITE_TCLAPI test_rebaser_cmd(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  struct RebaseSubcmd {
  static struct RebaseSubcmd {
    const char *zSub;
    int nArg;
    const char *zMsg;
    int iSub;
  } aSub[] = {
    { "configure",    1, "REBASE-BLOB" }, /* 0 */
    { "delete",       0, ""            }, /* 1 */
1315
1316
1317
1318
1319
1320
1321

1322
1323
1324
1325
1326
1327
1328
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389







+







            testStreamOutput, (void*)&sOut
        );
      }else{
        rc = sqlite3rebaser_rebase(p, sStr.nData, sStr.aData, &sOut.n, &sOut.p);
      }

      if( rc==SQLITE_OK ){
        assert_changeset_is_ok(sOut.n, sOut.p);
        Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(sOut.p, sOut.n));
      }
      sqlite3_free(sOut.p);
      break;
    }
  }

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
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
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
1546







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










-
+








  Tcl_CreateObjCommand(interp, Tcl_GetString(objv[1]), test_rebaser_cmd,
      (ClientData)pNew, test_rebaser_del
  );
  Tcl_SetObjResult(interp, objv[1]);
  return TCL_OK;
}

/*
** Run some sanity checks on the changeset in nChangeset byte buffer
** pChangeset. If any fail, return a non-zero value and, optionally,
** set output variable (*pzErr) to point to a buffer containing an
** English language error message describing the problem. In this
** case it is the responsibility of the caller to free the buffer
** using sqlite3_free().
**
** Or, if the changeset appears to be well-formed, this function
** returns SQLITE_OK and sets (*pzErr) to NULL.
*/
static int sqlite3_test_changeset(
  int nChangeset,
  void *pChangeset,
  char **pzErr
){
  sqlite3_changeset_iter *pIter = 0;
  char *zErr = 0;
  int rc = SQLITE_OK;
  int bPatch = (nChangeset>0 && ((char*)pChangeset)[0]=='P');

  rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset);
  if( rc==SQLITE_OK ){
    int rc2;
    while( rc==SQLITE_OK && SQLITE_ROW==sqlite3changeset_next(pIter) ){
      unsigned char *aPk = 0;
      int nCol = 0;
      int op = 0;
      const char *zTab = 0;

      sqlite3changeset_pk(pIter, &aPk, &nCol);
      sqlite3changeset_op(pIter, &zTab, &nCol, &op, 0);

      if( op==SQLITE_UPDATE ){
        int iCol;
        for(iCol=0; iCol<nCol; iCol++){
          sqlite3_value *pNew = 0;
          sqlite3_value *pOld = 0;
          sqlite3changeset_new(pIter, iCol, &pNew);
          sqlite3changeset_old(pIter, iCol, &pOld);

          if( aPk[iCol] ){
            if( pOld==0 ) rc = SQLITE_ERROR;
          }else if( bPatch ){
            if( pOld ) rc = SQLITE_ERROR;
          }else{
            if( (pOld==0)!=(pNew==0) ) rc = SQLITE_ERROR;
          }

          if( rc!=SQLITE_OK ){
            zErr = sqlite3_mprintf(
                "unexpected SQLITE_UPDATE (bPatch=%d pk=%d pOld=%d pNew=%d)",
                bPatch, (int)aPk[iCol], pOld!=0, pNew!=0
            );
            break;
          }
        }
      }
    }
    rc2 = sqlite3changeset_finalize(pIter);
    if( rc==SQLITE_OK ){
      rc = rc2;
    }
  }

  *pzErr = zErr;
  return rc;
}

/*
** test_changeset CHANGESET
*/
static int SQLITE_TCLAPI test_changeset(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  void *pChangeset = 0;           /* Buffer containing changeset */
  int nChangeset = 0;             /* Size of buffer aChangeset in bytes */
  int rc = SQLITE_OK;
  char *z = 0;

  if( objc!=2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "CHANGESET");
    return TCL_ERROR;
  }
  pChangeset = (void *)Tcl_GetByteArrayFromObj(objv[1], &nChangeset);

  Tcl_ResetResult(interp);
  rc = sqlite3_test_changeset(nChangeset, pChangeset, &z);
  if( rc!=SQLITE_OK ){
    char *zErr = sqlite3_mprintf("(%d) - \"%s\"", rc, z);
    Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1));
    sqlite3_free(zErr);
  }
  sqlite3_free(z);

  return rc ? TCL_ERROR : TCL_OK;
}

/*
** tclcmd: sqlite3rebaser_configure OP VALUE
*/
static int SQLITE_TCLAPI test_sqlite3session_config(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  struct ConfigOpt {
  static struct ConfigOpt {
    const char *zSub;
    int op;
  } aSub[] = {
    { "strm_size",    SQLITE_SESSION_CONFIG_STRMSIZE },
    { "invalid",      0 },
    { 0 }
  };
1416
1417
1418
1419
1420
1421
1422

1423
1424
1425
1426
1427
1428
1429
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592







+







    { "sqlite3changeset_apply", test_sqlite3changeset_apply },
    { "sqlite3changeset_apply_v2", test_sqlite3changeset_apply_v2 },
    { "sqlite3changeset_apply_replace_all", 
      test_sqlite3changeset_apply_replace_all },
    { "sql_exec_changeset", test_sql_exec_changeset },
    { "sqlite3rebaser_create", test_sqlite3rebaser_create },
    { "sqlite3session_config", test_sqlite3session_config },
    { "test_changeset", test_changeset },
  };
  int i;

  for(i=0; i<sizeof(aCmd)/sizeof(struct Cmd); i++){
    struct Cmd *p = &aCmd[i];
    Tcl_CreateObjCommand(interp, p->zCmd, p->xProc, 0, 0);
  }

Changes to ext/userauth/userauth.c.

36
37
38
39
40
41
42
43

44
45
46
47
48
49
50
36
37
38
39
40
41
42

43
44
45
46
47
48
49
50







-
+







  const char *zFormat,
  ...
){
  sqlite3_stmt *pStmt;
  char *zSql;
  int rc;
  va_list ap;
  int savedFlags = db->flags;
  u64 savedFlags = db->flags;

  va_start(ap, zFormat);
  zSql = sqlite3_vmprintf(zFormat, ap);
  va_end(ap);
  if( zSql==0 ) return 0;
  db->flags |= SQLITE_WriteSchema;
  rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);

Added ext/wasm/EXPORTED_FUNCTIONS.fiddle.








1
2
3
4
5
6
7
+
+
+
+
+
+
+
_fiddle_exec
_fiddle_interrupt
_fiddle_experiment
_fiddle_the_db
_fiddle_db_arg
_fiddle_db_filename
_fiddle_reset_db

Added ext/wasm/GNUmakefile.


















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
#######################################################################
# This GNU makefile drives the build of the sqlite3 WASM
# components. It is not part of the canonical build process.
#
# This build assumes a Linux platform and is not intended for
# general-purpose client-level use, except for creating builds with
# custom configurations. It is primarily intended for the sqlite
# project's own development of the JS/WASM components.
#
# Primary targets:
#
#  default, all = build in dev mode
#
#  o0, o1, o2, o3, os, oz = full clean/rebuild with the -Ox level indicated
#      by the target name. Rebuild is necessary for all components to get
#      the desired optimization level.
#
#  quick, q = do just a minimal build (sqlite3.js/wasm, tester1) for
#      faster development-mode turnaround.
#
#  qo2, qoz = a combination of quick+o2/oz.
#
#  dist = create end user deliverables. Add dist.build=oX to build
#      with a specific optimization level, where oX is one of the
#      above-listed o? or qo? target names.
#
#  snapshot = like dist, but uses a zip file name which clearly
#      marks it as a prerelease/snapshot build.
#
#  clean = clean up
#
# Required tools beyond those needed for the canonical builds:
#
# - Emscripten SDK: https://emscripten.org/docs/getting_started/downloads.html
# - The bash shell
# - GNU make, GNU sed, GNU awk, GNU grep (all in the $PATH)
# - wasm-strip for release builds: https://github.com/WebAssembly/wabt
# - InfoZip for 'dist' zip file
########################################################################
#
# Significant TODOs for this build include, but are not necessarily
# limited to:
#
# 1) Consolidate the code generation for sqlite3*.*js into a script
#    which generates the makefile code, rather than using $(call) and
#    $(eval), or at least centralize the setup of the numerous vars
#    related to each build variant (vanilla, esm, bundler-friendly).
#
SHELL := $(shell which bash 2>/dev/null)
MAKEFILE := $(lastword $(MAKEFILE_LIST))
CLEAN_FILES :=
DISTCLEAN_FILES := ./--dummy--
default: all
release: oz

# Emscripten SDK home dir and related binaries...
EMSDK_HOME ?= $(word 1,$(wildcard $(HOME)/emsdk $(HOME)/src/emsdk))
emcc.bin ?= $(word 1,$(wildcard $(EMSDK_HOME)/upstream/emscripten/emcc) $(shell which emcc))
ifeq (,$(emcc.bin))
  $(error Cannot find emcc.)
endif
emcc.version := $(shell "$(emcc.bin)" --version | sed -n 1p \
                  | sed -e 's/^.* \([3-9][^ ]*\) .*$$/\1/;')
ifeq (,$(emcc.version))
  $(warning Cannot determine emcc version. This might unduly impact build flags.)
else
  $(info using emcc version [$(emcc.version)])
endif
emcc.version := $(shell "$(emcc.bin)" --version | sed -n 1p \
                  | sed -e 's/^.* \([3-9][^ ]*\) .*$$/\1/;')
ifeq (,$(emcc.version))
  $(warning Cannot determine emcc version. This might unduly impact build flags.)
else
  $(info using emcc version [$(emcc.version)])
endif

wasm-strip ?= $(shell which wasm-strip 2>/dev/null)
ifeq (,$(filter clean,$(MAKECMDGOALS)))
ifeq (,$(wasm-strip))
  $(info WARNING: *******************************************************************)
  $(info WARNING: builds using -O2/-O3/-Os/-Oz will minify WASM-exported names,)
  $(info WARNING: breaking _All The Things_. The workaround for that is to build)
  $(info WARNING: with -g3 (which explodes the file size) and then strip the debug)
  $(info WARNING: info after compilation, using wasm-strip, to shrink the wasm file.)
  $(info WARNING: wasm-strip was not found in the PATH so we cannot strip those.)
  $(info WARNING: If this build uses any optimization level higher than -O1 then)
  $(info WARNING: the ***resulting JS code WILL NOT BE USABLE***.)
  $(info WARNING: wasm-strip is part of the wabt package:)
  $(info WARNING:    https://github.com/WebAssembly/wabt)
  $(info WARNING: on Ubuntu-like systems it can be installed with:)
  $(info WARNING:    sudo apt install wabt)
  $(info WARNING: *******************************************************************)
endif
endif # 'make clean' check

ifeq (,$(wasm-strip))
  maybe-wasm-strip = echo "not wasm-stripping"
else
  maybe-wasm-strip = $(wasm-strip)
endif

dir.top := ../..
# Reminder: some Emscripten flags require absolute paths but we want
# relative paths for most stuff simply to reduce noise. The
# $(abspath...) GNU make function can transform relative paths to
# absolute.
dir.wasm := $(patsubst %/,%,$(dir $(MAKEFILE)))
dir.api := api
dir.jacc := jaccwabyt
dir.common := common
dir.fiddle := fiddle
dir.tool := $(dir.top)/tool
CLEAN_FILES += *~ $(dir.jacc)/*~ $(dir.api)/*~ $(dir.common)/*~ $(dir.fiddle)/*~

########################################################################
# dir.dout = output dir for deliverables.
#
# MAINTENANCE REMINDER: the output .js and .wasm files of certain emcc
# buildables must be in _this_ dir, rather than a subdir, or else
# parts of the generated code get confused and cannot load
# property. Specifically, when X.js loads X.wasm, whether or not X.js
# uses the correct path for X.wasm depends on how it's loaded: an HTML
# script tag will resolve it intuitively, whereas a Worker's call to
# importScripts() will not.  That's a fundamental incompatibility with
# how URL resolution in JS happens between those two contexts. See:
#
# https://zzz.buzz/2017/03/14/relative-uris-in-web-development/
#
# We unfortunately have no way, from Worker-initiated code, to
# automatically resolve the path from X.js to X.wasm.
#
# We have an "only slightly unsightly" solution for our main builds
# but it does not work for the WASMFS builds, so those builds have to
# be built to _this_ directory and can only run when the client app is
# loaded from the same directory.
dir.dout := $(dir.wasm)/jswasm
# dir.tmp = output dir for intermediary build files, as opposed to
# end-user deliverables.
dir.tmp := $(dir.wasm)/bld
CLEAN_FILES += $(dir.tmp)/* $(dir.dout)/*
ifeq (,$(wildcard $(dir.dout)))
  dir._tmp := $(shell mkdir -p $(dir.dout))
endif
ifeq (,$(wildcard $(dir.tmp)))
  dir._tmp := $(shell mkdir -p $(dir.tmp))
endif

sqlite3.c := $(dir.top)/sqlite3.c
sqlite3.h := $(dir.top)/sqlite3.h
# Most SQLITE_OPT flags are set in sqlite3-wasm.c but we need them
# made explicit here for building speedtest1.c.
SQLITE_OPT = \
  -DSQLITE_ENABLE_FTS5 \
  -DSQLITE_ENABLE_RTREE \
  -DSQLITE_ENABLE_EXPLAIN_COMMENTS \
  -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION \
  -DSQLITE_ENABLE_STMTVTAB \
  -DSQLITE_ENABLE_DBPAGE_VTAB \
  -DSQLITE_ENABLE_DBSTAT_VTAB \
  -DSQLITE_ENABLE_BYTECODE_VTAB \
  -DSQLITE_ENABLE_OFFSET_SQL_FUNC \
  -DSQLITE_OMIT_LOAD_EXTENSION \
  -DSQLITE_OMIT_DEPRECATED \
  -DSQLITE_OMIT_UTF16 \
  -DSQLITE_OMIT_SHARED_CACHE \
  -DSQLITE_OMIT_WAL \
  -DSQLITE_THREADSAFE=0 \
  -DSQLITE_TEMP_STORE=3 \
  -DSQLITE_OS_KV_OPTIONAL=1 \
  '-DSQLITE_DEFAULT_UNIX_VFS="unix-none"' \
  -DSQLITE_USE_URI=1 \
  -DSQLITE_WASM_ENABLE_C_TESTS

$(sqlite3.c) $(sqlite3.h):
	$(MAKE) -C $(dir.top) sqlite3.c

.PHONY: clean distclean
clean:
	-rm -f $(CLEAN_FILES)
distclean: clean
	-rm -f $(DISTCLEAN_FILES)

ifeq (release,$(filter release,$(MAKECMDGOALS)))
  ifeq (,$(wasm-strip))
    $(error Cannot make release-quality binary because wasm-strip is not available. \
            See notes in the warning above)
  endif
else
  $(info Development build. Use '$(MAKE) release' for a smaller release build.)
endif

# bin.version-info = binary to output various sqlite3 version info for
# embedding in the JS files and in building the distribution zip file.
# It must NOT be in $(dir.tmp) because we need it to survive the
# cleanup process for the dist build to work properly.
bin.version-info := $(dir.wasm)/version-info
$(bin.version-info): $(dir.wasm)/version-info.c $(sqlite3.h) $(MAKEFILE)
	$(CC) -O0 -I$(dir.top) -o $@ $<
DISTCLEAN_FILES += $(bin.version-info)

# bin.stripcomments is used for stripping C/C++-style comments from JS
# files. The JS files contain large chunks of documentation which we
# don't need for all builds. That app's -k flag is of particular
# importance here, as it allows us to retain the opening comment
# blocks, which contain the license header and version info.
bin.stripccomments := $(dir.tool)/stripccomments
$(bin.stripccomments): $(bin.stripccomments).c $(MAKEFILE)
	$(CC) -o $@ $<
DISTCLEAN_FILES += $(bin.stripccomments)


########################################################################
# C-PP.FILTER: a $(call)able to transform $(1) to $(2) via ./c-pp -f
# $(1) ...
#
# Historical notes:
#
# - We first attempted to use gcc and/or clang to preprocess JS files
#   in the same way we would normally do C files, but C-specific quirks
#   of each makes that untennable.
#
# - We implemented c-pp.c (the C-Minus Pre-processor) as a custom
#   generic/file-format-agnostic preprocessor to enable us to pack
#   code for different target builds into the same JS files. Most
#   notably, some ES6 module (a.k.a. ESM) features cannot legally be
#   referenced at all in non-ESM code, e.g.  the "import" and "export"
#   keywords. This preprocessing step permits us to swap out sections
#   of code where necessary for ESM and non-ESM (a.k.a. vanilla JS)
#   require different implementations. The alternative to such
#   preprocessing, would be to have separate source files for ES6
#   builds, which would have a higher maintenance burden than c-pp.c
#   seems likely to.
#
# c-pp.c was written specifically for the sqlite project's JavaScript
# builds but is maintained as a standalone project:
# https://fossil.wanderinghorse.net/r/c-pp
bin.c-pp := ./c-pp
$(bin.c-pp): c-pp.c $(sqlite3.c) $(MAKEFILE)
	$(CC) -O0 -o $@ c-pp.c $(sqlite3.c) '-DCMPP_DEFAULT_DELIM="//#"' -I$(dir.top) \
		-DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_UTF16 \
		-DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_WAL -DSQLITE_THREADSAFE=0 \
		-DSQLITE_TEMP_STORE=3
define C-PP.FILTER
# Create $2 from $1 using $(bin.c-pp)
# $1 = Input file: c-pp -f $(1).js
# $2 = Output file: c-pp -o $(2).js
# $3 = optional c-pp -D... flags
$(2): $(1) $$(MAKEFILE) $$(bin.c-pp)
	$$(bin.c-pp) -f $(1) -o $$@ $(3)
CLEAN_FILES += $(2)
endef
# /end C-PP.FILTER
########################################################################

# cflags.common = C compiler flags for all builds
cflags.common :=  -I. -I.. -I$(dir.top)
# emcc.WASM_BIGINT = 1 for BigInt (C int64) support, else 0.  The API
# disables certain features if BigInt is not enabled and such builds
# _are not tested_ on any regular basis.
emcc.WASM_BIGINT ?= 1

# emcc_opt = optimization-related flags. These are primarily used by
# the various oX targets. build times for -O levels higher than 0 are
# painful at dev-time.
emcc_opt ?= -O0

# When passing emcc_opt from the CLI, += and re-assignment have no
# effect, so emcc_opt+=-g3 doesn't work. So...
emcc_opt_full := $(emcc_opt) -g3
# ^^^ ALWAYS use -g3. See below for why.
#
# ^^^ -flto improves runtime speed at -O0 considerably but doubles
# build time.
#
# ^^^^ -O3, -Oz, -Os minify symbol names and there appears to be no
# way around that except to use -g3, but -g3 causes the binary file
# size to absolutely explode (approx. 5x larger). This minification
# utterly breaks the resulting module, making it unsable except as
# self-contained/self-referential-only code, as ALL of the exported
# symbols get minified names.
#
# However, we have an option for using -Oz or -Os:
#
# Build with (-Os -g3) or (-Oz -g3) then use wasm-strip, from the wabt
# tools package (https://github.com/WebAssembly/wabt), to strip the
# debugging symbols. That results in a small build with unmangled
# symbol names. -Oz gives ever-so-slightly better compression than
# -Os: not quite 1% in some completely unscientific tests. Runtime
# speed for the unit tests is all over the place either way so it's
# difficult to say whether -Os gives any speed benefit over -Oz.
#
# Much practice has demonstrated that -O2 consistently gives the best
# runtime speeds, but not by a large enough factor to rule out use of
# -Oz when small deliverable size is a priority.
########################################################################

# EXPORTED_FUNCTIONS.* = files for use with Emscripten's
# -sEXPORTED_FUNCTION flag.
EXPORTED_FUNCTIONS.api.in := $(abspath $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-api)
EXPORTED_FUNCTIONS.api := $(dir.tmp)/EXPORTED_FUNCTIONS.api
$(EXPORTED_FUNCTIONS.api): $(EXPORTED_FUNCTIONS.api.in) $(MAKEFILE)
	cp $(EXPORTED_FUNCTIONS.api.in) $@

# sqlite3-license-version.js = generated JS file with the license
# header and version info.
sqlite3-license-version.js := $(dir.tmp)/sqlite3-license-version.js
# sqlite3-license-version-header.js = JS file containing only the
# license header.
sqlite3-license-version-header.js := $(dir.api)/sqlite3-license-version-header.js
# sqlite3-api-build-version.js = generated JS file which populates the
# sqlite3.version object using $(bin.version-info).
sqlite3-api-build-version.js := $(dir.tmp)/sqlite3-api-build-version.js
# sqlite3-api.jses = the list of JS files which make up
# $(sqlite3-api.js.in), in the order they need to be assembled.
sqlite3-api.jses := $(sqlite3-license-version.js)
sqlite3-api.jses += $(dir.api)/sqlite3-api-prologue.js
sqlite3-api.jses += $(dir.common)/whwasmutil.js
sqlite3-api.jses += $(dir.jacc)/jaccwabyt.js
sqlite3-api.jses += $(dir.api)/sqlite3-api-glue.js
sqlite3-api.jses += $(sqlite3-api-build-version.js)
sqlite3-api.jses += $(dir.api)/sqlite3-api-oo1.js
sqlite3-api.jses += $(dir.api)/sqlite3-api-worker1.js
sqlite3-api.jses += $(dir.api)/sqlite3-v-helper.js
sqlite3-api.jses += $(dir.api)/sqlite3-vfs-opfs.c-pp.js
sqlite3-api.jses += $(dir.api)/sqlite3-api-cleanup.js

# "External" API files which are part of our distribution
# but not part of the sqlite3-api.js amalgamation.
SOAP.js := $(dir.api)/sqlite3-opfs-async-proxy.js
# COPY_XAPI = a $(call)able function to copy $1 to $(dir.dout), where
# $1 must be one of the "external" JS API files.
define COPY_XAPI
sqlite3-api.ext.jses += $$(dir.dout)/$$(notdir $(1))
$$(dir.dout)/$$(notdir $(1)): $(1) $$(MAKEFILE)
	cp $$< $$@
endef
$(foreach X,$(SOAP.js),\
  $(eval $(call COPY_XAPI,$(X))))
all quick: $(sqlite3-api.ext.jses)
q: quick

########################################################################
# $(sqlite3-api*.*js) contain the core library code but not the
# Emscripten-related glue which deals with loading sqlite3.wasm. In
# theory they can be used by arbitrary build environments and WASM
# loaders, but in practice that breaks down because the WASM loader
# has to be able to provide all of the necessary "imports" to
# sqlite3.wasm, and that list of imports is unknown until sqlite3.wasm
# is compiled, at which point Emscripten sets up the imports
# appropriately. Abstractly speaking, it's impossible for other build
# environments to know exactly which imports are needed and provide
# them. Tools like wasm-objdump can be used to find the list of
# imports but it's questionable whether a non-Emscripten tool could
# realistically use that info to provide proper implementations.
# Sidebar: some of the imports are used soley by the Emscripten glue,
# which the sqlite3 JS code does not rely on.
#
# We build $(sqlite3-api*.*) "because we can" and because it might be
# a useful point of experimentation for some clients, but the
# above-described caveat may well make them unusable for real-life
# clients.
#
# sqlite3-api.js.in = the generated sqlite3-api.js before it gets
# preprocessed. It contains all of $(sqlite3-api.jses) but none of the
# Emscripten-specific headers and footers.
sqlite3-api.js.in := $(dir.tmp)/sqlite3-api.c-pp.js
$(sqlite3-api.js.in): $(sqlite3-api.jses) $(MAKEFILE)
	@echo "Making $@..."
	@for i in $(sqlite3-api.jses); do \
		echo "/* BEGIN FILE: $$i */"; \
		cat $$i; \
		echo "/* END FILE: $$i */"; \
	done > $@

########################################################################
# emcc flags for .c/.o/.wasm/.js.
emcc.flags :=
ifeq (1,$(emcc.verbose))
emcc.flags += -v
# -v is _very_ loud but also informative about what it's doing
endif

########################################################################
# emcc flags for .c/.o.
emcc.cflags :=
emcc.cflags += -std=c99 -fPIC
# -------------^^^^^^^^ we need c99 for $(sqlite3-wasm.c).
emcc.cflags += -I. -I$(dir.top)
########################################################################
# emcc flags specific to building .js/.wasm files...
emcc.jsflags := -fPIC
emcc.jsflags += --minify 0
emcc.jsflags += --no-entry
emcc.jsflags += -sWASM_BIGINT=$(emcc.WASM_BIGINT)
emcc.jsflags += -sMODULARIZE
emcc.jsflags += -sDYNAMIC_EXECUTION=0
emcc.jsflags += -sNO_POLYFILL
emcc.jsflags += -sEXPORTED_FUNCTIONS=@$(EXPORTED_FUNCTIONS.api)
emcc.exportedRuntimeMethods := \
    -sEXPORTED_RUNTIME_METHODS=wasmMemory
    # wasmMemory ==> required by our code for use with -sIMPORTED_MEMORY
emcc.jsflags += $(emcc.exportedRuntimeMethods)
emcc.jsflags += -sUSE_CLOSURE_COMPILER=0
emcc.jsflags += -sIMPORTED_MEMORY
ifeq (3.1.31,$(emcc.version))
  emcc.jsflags += -sSTRICT_JS=0
  $(warning Disabling -sSTRICT_JS for emcc $(emcc.version): \
     https://github.com/emscripten-core/emscripten/issues/18610)
else
  emcc.jsflags += -sSTRICT_JS=1
endif
emcc.environment := -sENVIRONMENT=web,worker
########################################################################
# -sINITIAL_MEMORY: How much memory we need to start with is governed
# at least in part by whether -sALLOW_MEMORY_GROWTH is enabled. If so,
# we can start with less. If not, we need as much as we'll ever
# possibly use (which, of course, we can't know for sure).  Note,
# however, that speedtest1 shows that performance for even moderate
# workloads MAY suffer considerably if we start small and have to grow
# at runtime. e.g. OPFS-backed (speedtest1 --size 75) take MAY take X
# time with 16mb+ memory and 3X time when starting with 8MB. However,
# such test results are inconsistent due to browser internals which
# are opaque to us.
emcc.jsflags += -sALLOW_MEMORY_GROWTH
emcc.INITIAL_MEMORY.128 := 13107200
emcc.INITIAL_MEMORY.96  := 100663296
emcc.INITIAL_MEMORY.64  := 64225280
emcc.INITIAL_MEMORY.32  := 33554432
emcc.INITIAL_MEMORY.16  := 16777216
emcc.INITIAL_MEMORY.8   := 8388608
emcc.INITIAL_MEMORY ?= 16
ifeq (,$(emcc.INITIAL_MEMORY.$(emcc.INITIAL_MEMORY)))
$(error emcc.INITIAL_MEMORY must be one of: 8, 16, 32, 64, 96, 128 (megabytes))
endif
emcc.jsflags += -sINITIAL_MEMORY=$(emcc.INITIAL_MEMORY.$(emcc.INITIAL_MEMORY))
# /INITIAL_MEMORY
########################################################################

emcc.jsflags += $(emcc.environment)
emcc.jsflags += -sSTACK_SIZE=512KB
# ^^^ ACHTUNG: emsdk 3.1.27 reduced the default stack size from 5MB to
# a mere 64KB, which leads to silent memory corruption via the kvvfs
# VFS, which requires twice that for its xRead() and xWrite() methods.
########################################################################
# $(sqlite3.js.init-func) is the name Emscripten assigns our exported
# module init/load function. This symbol name is hard-coded in
# $(extern-post-js.js) as well as in numerous docs.
#
# "sqlite3InitModule" is the symbol we document for client use, so
# that's the symbol name which must be exported, whether it comes from
# Emscripten or our own code in extern-post-js.js.
#
# That said... we can change $(sqlite3.js.init-func) as long as the
# name "sqlite3InitModule" is the one which gets exposed via the
# resulting JS files. That can be accomplished via
# extern-post-js.js. However...  using a temporary symbol name here
# and then adding sqlite3InitModule() ourselves results in 2 global
# symbols: we cannot "delete" the Emscripten-defined
# $(sqlite3.js.init-func) because it's declared with "var".
sqlite3.js.init-func := sqlite3InitModule
emcc.jsflags += -sEXPORT_NAME=$(sqlite3.js.init-func)
emcc.jsflags += -sGLOBAL_BASE=4096 # HYPOTHETICALLY keep func table indexes from overlapping w/ heap addr.
#emcc.jsflags += -sSTRICT # fails due to missing __syscall_...()
#emcc.jsflags += -sALLOW_UNIMPLEMENTED_SYSCALLS
#emcc.jsflags += -sFILESYSTEM=0 # only for experimentation. sqlite3 needs the FS API
#emcc.jsflags += -sABORTING_MALLOC # only for experimentation
emcc.jsflags += -sALLOW_TABLE_GROWTH
# ^^^^ -sALLOW_TABLE_GROWTH is required for installing new SQL UDFs
emcc.jsflags += -Wno-limited-postlink-optimizations
# ^^^^ emcc likes to warn when we have "limited optimizations" via the
# -g3 flag.
# emcc.jsflags += -sSTANDALONE_WASM # causes OOM errors, not sure why.

# Re. undefined symbol handling, see: https://lld.llvm.org/WebAssembly.html
emcc.jsflags += -sERROR_ON_UNDEFINED_SYMBOLS=1
emcc.jsflags += -sLLD_REPORT_UNDEFINED
#emcc.jsflags += --allow-undefined
#emcc.jsflags += --import-undefined
#emcc.jsflags += --unresolved-symbols=import-dynamic --experimental-pic
#emcc.jsflags += --experimental-pic --unresolved-symbols=ingore-all --import-undefined
#emcc.jsflags += --unresolved-symbols=ignore-all

########################################################################
# -sMEMORY64=1 fails to load, erroring with:
#  invalid memory limits flags 0x5
#    (enable via --experimental-wasm-memory64)
#
# ^^^^ MEMORY64=2 builds and loads but dies when we do things like:
#
#  new Uint8Array(wasm.heap8u().buffer, ptr, n)
#
# because ptr is now a BigInt, so is invalid for passing to arguments
# which have strict must-be-a-Number requirements. That aspect will
# make any eventual port to 64-bit address space extremely painful, as
# such constructs are found all over the place in the source code.
########################################################################

########################################################################
# -sSINGLE_FILE:
# https://github.com/emscripten-core/emscripten/blob/main/src/settings.js
#
# -sSINGLE_FILE=1 would be _really_ nice but we have to build with -g3
# for -O2 and higher to work (else minification breaks the code) and
# cannot wasm-strip the binary before it gets encoded into the JS
# file. The result is that the generated JS file is, because of the
# -g3 debugging info, _huge_.
########################################################################

$(sqlite3-api-build-version.js): $(bin.version-info) $(MAKEFILE)
	@echo "Making $@..."
	@{ \
  echo 'self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){'; \
	echo -n '  sqlite3.version = '; \
  $(bin.version-info) --json; \
  echo ';'; \
	echo '});'; \
  } > $@
$(sqlite3-license-version.js): $(sqlite3.h) $(sqlite3-license-version-header.js) \
  $(MAKEFILE)
	@echo "Making $@..."; { \
    cat $(sqlite3-license-version-header.js); \
    echo '/*'; \
    echo '** This code was built from sqlite3 version...'; \
    echo "**"; \
    awk -e '/define SQLITE_VERSION/{$$1=""; print "**" $$0}' \
        -e '/define SQLITE_SOURCE_ID/{$$1=""; print "**" $$0}' $(sqlite3.h); \
    echo "**"; \
    echo "** Using the Emscripten SDK version $(emcc.version)."; \
    echo '*/'; \
   } > $@

########################################################################
# --post-js and --pre-js are emcc flags we use to append/prepend JS to
# the generated emscripten module file. These rules set up the core
# pre/post files for use by the various builds.
pre-js.js.in := $(dir.api)/pre-js.c-pp.js
post-js.js.in := $(dir.tmp)/post-js.c-pp.js
post-jses.js := \
  $(dir.api)/post-js-header.js \
  $(sqlite3-api.js.in) \
  $(dir.api)/post-js-footer.js
$(post-js.js.in): $(post-jses.js) $(MAKEFILE)
	@echo "Making $@..."
	@for i in $(post-jses.js); do \
		echo "/* BEGIN FILE: $$i */"; \
		cat $$i; \
		echo "/* END FILE: $$i */"; \
	done > $@


########################################################################
# call-make-pre-post is a $(call)able which creates rules for
# pre-js-$(1).js. $1 = the base name of the JS file on whose behalf
# this pre-js is for (one of: sqlite3, sqlite3-wasmfs). $2 is the build
# mode: one of (vanilla, esm, bundler-friendly).  This sets up
# --[extern-][pre/post]-js flags in $(pre-post-$(1).flags.$(2)) and
# dependencies in $(pre-post-$(1).deps.$(2)).
define call-make-pre-post
pre-post-$(1).flags.$(2) ?=
$$(dir.tmp)/pre-js-$(1)-$(2).js: $$(pre-js.js.$(2)) $$(MAKEFILE)
	cp $$(pre-js.js.$(2)) $$@
	@if [ sqlite3-wasmfs = $(1) ]; then \
		echo "delete Module[xNameOfInstantiateWasm] /*for WASMFS build*/;"; \
	elif [ sqlite3 != $(1) ]; then \
		echo "Module[xNameOfInstantiateWasm].uri = '$(1).wasm';"; \
	fi >> $$@
pre-post-$(1).deps.$(2) := \
  $$(pre-post-jses.deps.$(2)) \
  $$(dir.tmp)/pre-js-$(1)-$(2).js
pre-post-$(1).flags.$(2) += \
  $$(pre-post-common.flags.$(2)) \
  --pre-js=$$(dir.tmp)/pre-js-$(1)-$(2).js
endef
# /post-js and pre-js
########################################################################

# Undocumented Emscripten feature: if the target file extension is
# "mjs", it defaults to ES6 module builds:
# https://github.com/emscripten-core/emscripten/issues/14383
sqlite3.wasm := $(dir.dout)/sqlite3.wasm
sqlite3-wasm.c := $(dir.api)/sqlite3-wasm.c
# sqlite3-wasm.o vs sqlite3-wasm.c: building against the latter
# (predictably) results in a slightly faster binary. We're close
# enough to the target speed requirements that the 500ms makes a
# difference, so we build all binaries against sqlite3-wasm.c instead
# of building a shared copy of sqlite3-wasm.o to link against.
########################################################################
# SQLITE3.xJS.EXPORT-DEFAULT is part of SQLITE3-WASMFS.xJS.RECIPE and
# SETUP_LIB_BUILD_MODE, factored into a separate piece to avoid code
# duplication. $1 is 1 if the build mode needs this workaround (esm,
# bundler-friendly) and 0 if not (vanilla).
#
# Reminder for ESM builds: even if we use -sEXPORT_ES6=0, emcc _still_
# adds:
#
#   export default $(sqlite3.js.init-func);
#
# when building *.mjs, which is bad because we need to export an
# overwritten version of that function and cannot "export default"
# twice. Because of this, we have to sed *.mjs to remove the _first_
# instance (only) of /^export default/.
#
# Upstream RFE:
# https://github.com/emscripten-core/emscripten/issues/18237
define SQLITE3.xJS.ESM-EXPORT-DEFAULT
if [ x1 = x$(1) ]; then \
		echo "Fragile workaround for an Emscripten annoyance. See SQLITE3.xJS.RECIPE."; \
		sed -i -e '0,/^export default/{/^export default/d;}' $@ || exit $$?; \
		if ! grep -q '^export default' $@; then \
			echo "Cannot find export default." 1>&2; \
			exit 1; \
		fi; \
fi
endef

# extern-post-js* and extern-pre-js* are files for use with
# Emscripten's --extern-pre-js and --extern-post-js flags.
extern-pre-js.js := $(dir.api)/extern-pre-js.js
extern-post-js.js.in := $(dir.api)/extern-post-js.c-pp.js
# Emscripten flags for --[extern-][pre|post]-js=... for the
# various builds.
pre-post-common.flags := \
  --extern-pre-js=$(sqlite3-license-version.js)
# pre-post-jses.deps.* = a list of dependencies for the
# --[extern-][pre/post]-js files.
pre-post-jses.deps.common := $(extern-pre-js.js) $(sqlite3-license-version.js)
########################################################################
# SETUP_LIB_BUILD_MODE is a $(call)'able which sets up numerous pieces
# for one of the build modes (vanilla, esm, bundler-friendly).
#
# $1 = build mode name
# $2 = 1 for ESM build mode, else 0
# $3 = resulting sqlite-api JS/MJS file
# $4 = resulting JS/MJS file
# $5 = -D... flags for $(bin.c-pp)
# $6 = emcc -sXYZ flags
define SETUP_LIB_BUILD_MODE
$(info Setting up build [$(1)]: $(4))
c-pp.D.$(1) := $(5)
pre-js.js.$(1) := $$(dir.api)/pre-js.$(1).js
$$(eval $$(call C-PP.FILTER,$$(pre-js.js.in),$$(pre-js.js.$(1)),$$(c-pp.D.$(1))))
post-js.js.$(1) := $$(dir.tmp)/post-js.$(1).js
$$(eval $$(call C-PP.FILTER,$$(post-js.js.in),$$(post-js.js.$(1)),$$(c-pp.D.$(1))))
extern-post-js.js.$(1) := $$(dir.tmp)/extern-post-js.$(1).js
$$(eval $$(call C-PP.FILTER,$$(extern-post-js.js.in),$$(extern-post-js.js.$(1)),$$(c-pp.D.$(1))))
pre-post-common.flags.$(1) := \
  $$(pre-post-common.flags) \
  --post-js=$$(post-js.js.$(1)) \
  --extern-post-js=$$(extern-post-js.js.$(1))
pre-post-jses.deps.$(1) := $$(pre-post-jses.deps.common) \
  $$(post-js.js.$(1)) $$(extern-post-js.js.$(1))
$$(eval $$(call call-make-pre-post,sqlite3,$(1)))
emcc.flags.sqlite3.$(1) := $(6)
$$(eval $$(call C-PP.FILTER, $$(sqlite3-api.js.in), $(3), $(5)))
$(4): $(3)
$(4): $(3) $$(MAKEFILE) $$(sqlite3-wasm.c) $$(EXPORTED_FUNCTIONS.api) $$(pre-post-sqlite3.deps.$(1))
	@echo "Building $$@ ..."
	$$(emcc.bin) -o $$@ $$(emcc_opt_full) $$(emcc.flags) \
    $$(emcc.jsflags) \
    $$(pre-post-sqlite3.flags.$(1)) $$(emcc.flags.sqlite3.$(1)) \
    $$(cflags.common) $$(SQLITE_OPT) $$(sqlite3-wasm.c)
	@$$(call SQLITE3.xJS.ESM-EXPORT-DEFAULT,$(2))
	@if [ bundler-friendly = $(1) ]; then \
		echo "Patching $(3) for sqlite3.wasm..."; \
		rm -f $$(dir.dout)/sqlite3-bundler-friendly.wasm; \
		sed -i -e 's/sqlite3-bundler-friendly.wasm/sqlite3.wasm/g' $$@ || exit $$$$?; \
	fi
	chmod -x $$(sqlite3.wasm)
	$$(maybe-wasm-strip) $$(sqlite3.wasm)
	@ls -la $@ $$(sqlite3.wasm)
all: $(4)
quick: $(4)
CLEAN_FILES += $(3) $(4)
endef
# ^^^ /SETUP_LIB_BUILD_MODE
########################################################################
sqlite3-api.js := $(dir.dout)/sqlite3-api.js
sqlite3.js := $(dir.dout)/sqlite3.js
sqlite3-api.mjs := $(dir.dout)/sqlite3-api.mjs
sqlite3.mjs := $(dir.dout)/sqlite3.mjs
sqlite3-api-bundler-friendly.mjs := $(dir.dout)/sqlite3-api-bundler-friendly.mjs
sqlite3-bundler-friendly.mjs := $(dir.dout)/sqlite3-bundler-friendly.mjs
# Maintenance reminder: careful not to introduce spaces around args $1, $2
#$(info $(call SETUP_LIB_BUILD_MODE,vanilla,0, $(sqlite3-api.js), $(sqlite3.js)))
$(eval $(call SETUP_LIB_BUILD_MODE,vanilla,0, $(sqlite3-api.js), $(sqlite3.js)))
$(eval $(call SETUP_LIB_BUILD_MODE,esm,1, $(sqlite3-api.mjs), $(sqlite3.mjs), \
       -Dtarget=es6-module, -sEXPORT_ES6 -sUSE_ES6_IMPORT_META))
$(eval $(call SETUP_LIB_BUILD_MODE,bundler-friendly,1,\
       $(sqlite3-api-bundler-friendly.mjs),$(sqlite3-bundler-friendly.mjs),\
       $(c-pp.D.esm) -Dtarget=es6-bundler-friendly, $(emcc.flags.sqlite3.esm)))
# The various -D... values used by *.c-pp.js include:
#
# -Dtarget=es6-module: for all ESM module builds
#
# -Dtarget=es6-module -Dtarget=es6-bundler-friendly: intended for
#    "bundler-friendly" ESM module build. These have some restrictions
#    on how URL() objects are constructed in some contexts: URLs which
#    refer to files which are part of this project must be references
#    as string literals so that bundlers' static-analysis tools can
#    find those files and include them in their bundles.
#
########################################################################
########################################################################
# We have to ensure that we do not build both $(sqlite3*.*js) in
# parallel because both result in the creation of $(sqlite3.wasm). We
# have no way to build just the .mjs file without also building the
# .wasm file because the generated .mjs file has to include info about
# the imports needed by the wasm file, so they have to be built
# together. i.e.  we're building $(sqlite3.wasm) multiple times, but
# that's unavoidable (and harmless, just a waste of build time).
$(sqlite3.wasm): $(sqlite3.js)
$(sqlite3.mjs): $(sqlite3.js)
$(sqlite3-bundler-friendly.mjs): $(sqlite3.mjs)
CLEAN_FILES += $(sqlite3.wasm)

########################################################################
# We need separate copies of certain supplementary JS files for the
# bundler-friendly build. Concretely, any supplemental JS files which
# themselves use importScripts() or Workers or URL() constructors
# which refer to other in-tree (m)JS files quire a bundler-friendly
# copy.
sqlite3-worker1.js.in := $(dir.api)/sqlite3-worker1.c-pp.js
sqlite3-worker1-promiser.js.in := $(dir.api)/sqlite3-worker1-promiser.c-pp.js
sqlite3-worker1.js := $(dir.dout)/sqlite3-worker1.js
sqlite3-worker1-promiser.js := $(dir.dout)/sqlite3-worker1-promiser.js
sqlite3-worker1-bundler-friendly.js := $(dir.dout)/sqlite3-worker1-bundler-friendly.js
sqlite3-worker1-promiser-bundler-friendly.js := $(dir.dout)/sqlite3-worker1-promiser-bundler-friendly.js
$(eval $(call C-PP.FILTER,$(sqlite3-worker1.js.in),$(sqlite3-worker1.js)))
$(eval $(call C-PP.FILTER,$(sqlite3-worker1.js.in),$(sqlite3-worker1-bundler-friendly.js),\
    $(c-pp.D.bundler-friendly)))
$(eval $(call C-PP.FILTER,$(sqlite3-worker1-promiser.js.in),$(sqlite3-worker1-promiser.js)))
$(eval $(call C-PP.FILTER,$(sqlite3-worker1-promiser.js.in),\
    $(sqlite3-worker1-promiser-bundler-friendly.js),\
    $(c-pp.D.bundler-friendly)))
$(sqlite3-bundler-friendly.mjs): $(sqlite3-worker1-bundler-friendly.js) \
    $(sqlite3-worker1-promiser-bundler-friendly.js)
$(sqlite3.js) $(sqlite3.mjs): $(sqlite3-worker1.js) $(sqlite3-worker1-promiser.js)

########################################################################
# batch-runner.js is part of one of the test apps which reads in SQL
# dumps generated by $(speedtest1) and executes them.
dir.sql := sql
speedtest1 := ../../speedtest1
speedtest1.c := ../../test/speedtest1.c
speedtest1.sql := $(dir.sql)/speedtest1.sql
speedtest1.cliflags := --size 25 --big-transactions
$(speedtest1):
	$(MAKE) -C ../.. speedtest1
$(speedtest1.sql): $(speedtest1) $(MAKEFILE)
	$(speedtest1) $(speedtest1.cliflags) --script $@
batch-runner.list: $(MAKEFILE) $(speedtest1.sql) $(dir.sql)/000-mandelbrot.sql
	bash split-speedtest1-script.sh $(dir.sql)/speedtest1.sql
	ls -1 $(dir.sql)/*.sql | grep -v speedtest1.sql | sort > $@
clean-batch:
	rm -f batch-runner.list $(dir.sql)/speedtest1*.sql
# ^^^ we don't do this along with 'clean' because we clean/rebuild on
# a regular basis with different -Ox flags and rebuilding the batch
# pieces each time is an unnecessary time sink.
batch: batch-runner.list
all: batch
# end batch-runner.js
########################################################################
# Wasmified speedtest1 is our primary benchmarking tool.
#
# emcc.speedtest1.common = emcc flags used by multiple builds of speedtest1
# emcc.speedtest1 = emcc flags used by main build of speedtest1
emcc.speedtest1.common := $(emcc_opt_full)
emcc.speedtest1 :=
emcc.speedtest1 += -sENVIRONMENT=web
emcc.speedtest1 += -sALLOW_MEMORY_GROWTH
emcc.speedtest1 += -sINITIAL_MEMORY=$(emcc.INITIAL_MEMORY.$(emcc.INITIAL_MEMORY))
emcc.speedtest1.common += -sINVOKE_RUN=0
emcc.speedtest1.common += --no-entry
emcc.speedtest1.common += -sABORTING_MALLOC
emcc.speedtest1.common += -sSTRICT_JS
emcc.speedtest1.common += -sMODULARIZE
emcc.speedtest1.common += -Wno-limited-postlink-optimizations
EXPORTED_FUNCTIONS.speedtest1 := $(abspath $(dir.tmp)/EXPORTED_FUNCTIONS.speedtest1)
emcc.speedtest1.common += -sSTACK_SIZE=512KB
emcc.speedtest1.common += -sEXPORTED_FUNCTIONS=@$(EXPORTED_FUNCTIONS.speedtest1)
emcc.speedtest1.common += $(emcc.exportedRuntimeMethods)
emcc.speedtest1.common += -sALLOW_TABLE_GROWTH
emcc.speedtest1.common += -sDYNAMIC_EXECUTION=0
emcc.speedtest1.common += --minify 0
emcc.speedtest1.common += -sEXPORT_NAME=$(sqlite3.js.init-func)
emcc.speedtest1.common += -sWASM_BIGINT=$(emcc.WASM_BIGINT)
speedtest1.exit-runtime0 := -sEXIT_RUNTIME=0
speedtest1.exit-runtime1 := -sEXIT_RUNTIME=1
# Re -sEXIT_RUNTIME=1 vs 0: if it's 1 and speedtest1 crashes, we get
# this error from emscripten:
#
# > native function `free` called after runtime exit (use
# NO_EXIT_RUNTIME to keep it alive after main() exits))
#
# If it's 0 and it crashes, we get:
#
# > stdio streams had content in them that was not flushed. you should
# set EXIT_RUNTIME to 1 (see the FAQ), or make sure to emit a newline
# when you printf etc.
#
# and pending output is not flushed because it didn't end with a
# newline (by design). The lesser of the two evils seems to be
# -sEXIT_RUNTIME=1 but we need EXIT_RUNTIME=0 for the worker-based app
# which runs speedtest1 multiple times.

$(EXPORTED_FUNCTIONS.speedtest1): $(EXPORTED_FUNCTIONS.api)
	@echo "Making $@ ..."
	@{ echo _wasm_main; cat $(EXPORTED_FUNCTIONS.api); } > $@
speedtest1.js := $(dir.dout)/speedtest1.js
speedtest1.wasm := $(dir.dout)/speedtest1.wasm
cflags.speedtest1 := $(cflags.common) -DSQLITE_SPEEDTEST1_WASM
speedtest1.cses := $(speedtest1.c) $(sqlite3-wasm.c)
$(eval $(call call-make-pre-post,speedtest1,vanilla))
$(speedtest1.js): $(MAKEFILE) $(speedtest1.cses) \
    $(pre-post-speedtest1.deps.vanilla) \
    $(EXPORTED_FUNCTIONS.speedtest1)
	@echo "Building $@ ..."
	$(emcc.bin) \
        $(emcc.speedtest1) $(emcc.speedtest1.common) \
        $(cflags.speedtest1) $(pre-post-speedtest1.flags.vanilla) \
        $(SQLITE_OPT) \
        $(speedtest1.exit-runtime0) \
        -o $@ $(speedtest1.cses) -lm
	$(maybe-wasm-strip) $(speedtest1.wasm)
	ls -la $@ $(speedtest1.wasm)

speedtest1: $(speedtest1.js)
all: speedtest1
CLEAN_FILES += $(speedtest1.js) $(speedtest1.wasm)
# end speedtest1.js
########################################################################

########################################################################
# tester1 is the main unit and regression test application and needs
# to be able to run in 4 separate modes to cover the primary
# client-side use cases:
#
# 1) Load sqlite3 in the main UI thread of a conventional script.
# 2) Load sqlite3 in a conventional Worker thread.
# 3) Load sqlite3 as an ES6 module (ESM) in the main thread.
# 4) Load sqlite3 as an ESM worker. (Not all browsers support this.)
#
# To that end, we require two separate builds of tester1.js:
#
#  tester1.js: cases 1 and 2
#  tester1.mjs: cases 3 and 4
#
# To create those, we filter tester1.c-pp.js with $(bin.c-pp)...
$(eval $(call C-PP.FILTER,tester1.c-pp.js,tester1.js))
$(eval $(call C-PP.FILTER,tester1.c-pp.js,tester1.mjs,$(c-pp.D.esm)))
$(eval $(call C-PP.FILTER,tester1.c-pp.html,tester1.html))
$(eval $(call C-PP.FILTER,tester1.c-pp.html,tester1-esm.html,$(c-pp.D.esm)))
tester1: tester1.js tester1.mjs tester1.html tester1-esm.html
# Note that we do not include $(sqlite3-bundler-friendly.mjs) in this
# because bundlers are client-specific.
all quick: tester1

########################################################################
# Convenience rules to rebuild with various -Ox levels. Much
# experimentation shows -O2 to be the clear winner in terms of speed.
# Note that build times with anything higher than -O0 are somewhat
# painful.

.PHONY: o0 o1 o2 o3 os oz
o-xtra :=
#o-xtra ?= -flto
# ^^^^ -flto can have a considerably performance boost at -O0 but
# doubles the build time and seems to have negligible, if any, effect
# on higher optimization levels.
o0: clean
	$(MAKE) -e "emcc_opt=-O0"
o1: clean
	$(MAKE) -e "emcc_opt=-O1 $(o-xtra)"
o2: clean
	$(MAKE) -j2 -e "emcc_opt=-O2 $(o-xtra)"
qo2: clean
	$(MAKE) -j2 -e "emcc_opt=-O2 $(o-xtra)" quick
o3: clean
	$(MAKE) -e "emcc_opt=-O3 $(o-xtra)"
os: clean
	@echo "WARNING: -Os can result in a build with mysteriously missing pieces!"
	$(MAKE) -e "emcc_opt=-Os $(o-xtra)"
oz: clean
	$(MAKE) -j2 -e "emcc_opt=-Oz $(o-xtra)"
qoz: clean
	$(MAKE) -j2 -e "emcc_opt=-Oz $(o-xtra)" quick

########################################################################
# Sub-makes...

# sqlite.org/fiddle application...
include fiddle.make

# Only add wasmfs if wasmfs.enable=1 or we're running (dist)clean
ifneq (,$(filter wasmfs,$(MAKECMDGOALS)))
wasmfs.enable ?= 1
else
wasmfs.enable ?= $(if $(filter %clean,$(MAKECMDGOALS)),1,0)
endif
ifeq (1,$(wasmfs.enable))
# wasmfs build disabled 2022-10-19 per /chat discussion.
# OPFS-over-wasmfs was initially a stopgap measure and a convenient
# point of comparison for the OPFS sqlite3_vfs's performance, but it
# currently doubles our deliverables and build maintenance burden for
# little benefit.
#
########################################################################
# Some platforms do not support the WASMFS build. Raspberry Pi OS is one
# of them. As such platforms are discovered, add their (uname -m) name
# to PLATFORMS_WITH_NO_WASMFS to exclude the wasmfs build parts.
PLATFORMS_WITH_NO_WASMFS := aarch64 # add any others here
THIS_ARCH := $(shell /usr/bin/uname -m)
ifneq (,$(filter $(THIS_ARCH),$(PLATFORMS_WITH_NO_WASMFS)))
$(info This platform does not support the WASMFS build.)
HAVE_WASMFS := 0
else
HAVE_WASMFS := 1
include wasmfs.make
endif
endif
# /wasmfs
########################################################################

########################################################################
# Push files to public wasm-testing.sqlite.org server
wasm-testing.include = *.js *.mjs *.html \
  ./tests \
  batch-runner.list \
  $(dir.dout) $(dir.sql) $(dir.common) $(dir.fiddle) $(dir.jacc)
wasm-testing.exclude = sql/speedtest1.sql
wasm-testing.dir     = /jail/sites/wasm-testing
wasm-testing.dest   ?= wasm-testing:$(wasm-testing.dir)
# ---------------------^^^^^^^^^^^^ ssh alias
.PHONY: push-testing
push-testing:
	rsync -z -e ssh --ignore-times --chown=stephan:www-data --group -r \
    $(patsubst %,--exclude=%,$(wasm-testing.exclude)) \
    $(wasm-testing.include) $(wasm-testing.dest)
	@echo "Updating gzipped copies..."; \
		ssh wasm-testing 'cd $(wasm-testing.dir) && bash .gzip' || \
    echo "SSH failed: it's likely that stale content will be served via old gzip files."

########################################################################
# If we find a copy of the sqlite.org/wasm docs checked out, copy
# certain files over to it, noting that some need automatable edits...
wasm.docs.home ?= ../../../wasm
wasm.docs.found = $(if $(wildcard $(wasm.docs.home)/api-index.md),\
  $(wildcard $(wasm.docs.home)),)
.PHONY: update-docs
ifeq (,$(wasm.docs.found))
update-docs:
	@echo "Cannot find wasm docs checkout."; \
	echo "Pass wasm.docs.home=/path/to/wasm/docs/checkout or edit this makefile to suit."; \
	exit 127
else
wasm.docs.jswasm := $(wasm.docs.home)/jswasm
update-docs: $(bin.stripccomments) $(sqlite3.js) $(sqlite3.wasm)
	@echo "Copying files to the /wasm docs. Be sure to use an -Oz build for this!"
	cp $(sqlite3.wasm) $(wasm.docs.jswasm)/.
	$(bin.stripccomments) -k -k < $(sqlite3.js) \
		| sed -e '/^[ \t]*$$/d' > $(wasm.docs.jswasm)/sqlite3.js
	cp demo-123.js demo-123.html demo-123-worker.html $(wasm.docs.home)
	sed -n -e '/EXTRACT_BEGIN/,/EXTRACT_END/p' \
		module-symbols.html > $(wasm.docs.home)/module-symbols.html
endif
# end /wasm docs
########################################################################

########################################################################
# Create main client downloadable zip file:
ifneq (,$(filter dist snapshot,$(MAKECMDGOALS)))
include dist.make
endif

# Run local web server for the test/demo pages.
httpd:
	althttpd -max-age 1 -enable-sab -page index.html

Added ext/wasm/README-dist.txt.















































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
This is the README for the sqlite3 WASM/JS distribution.

Main project page: https://sqlite.org

Documentation: https://sqlite.org/wasm

This archive contains the following deliverables for the WASM/JS
build:

- jswasm/sqlite3.js is the canonical "vanilla JS" version.

- jswasm/sqlite3.mjs is the same but in ES6 module form

- jswasm/*-bundler-friendly.js and .mjs are variants which are
  intended to be compatible with "bundler" tools commonly seen in
  node.js-based projects. Projects using such tools should use those
  variants, where available, instead of files without the
  "-bundler-friendly" suffix. Some files do not have separate
  variants.

- jswasm/sqlite3.wasm is the binary WASM file imported by all of the
  above-listed JS files.

- The jswasm directory additionally contains a number of supplemental
  JS files which cannot be bundled directly with the main JS files
  but are necessary for certain usages.

- The top-level directory contains various demonstration and test
  applications for sqlite3.js and sqlite3.mjs.
  sqlite3-bundler-friendly.mjs requires client-side build tools to make
  use of and is not demonstrated here.

Browsers will not serve WASM files from file:// URLs, so the test and
demonstration apps require a web server and that server must include
the following headers in its response when serving the files:

    Cross-Origin-Opener-Policy: same-origin
    Cross-Origin-Embedder-Policy: require-corp

The core library will function without those headers but certain
features, most notably OPFS storage, will not be available.

One simple way to get the demo apps up and running on Unix-style
systems is to install althttpd (https://sqlite.org/althttpd) and run:

    althttpd --enable-sab --page index.html

Added ext/wasm/README.md.










































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
This directory houses the [Web Assembly (WASM)](https://en.wikipedia.org/wiki/WebAssembly)
parts of the sqlite3 build.

It requires [emscripten][] and that the build environment be set up for
emscripten. A mini-HOWTO for setting that up follows...

First, install the Emscripten SDK, as documented
[here](https://emscripten.org/docs/getting_started/downloads.html) and summarized
below for Linux environments:

```
# Clone the emscripten repository:
$ sudo apt install git
$ git clone https://github.com/emscripten-core/emsdk.git
$ cd emsdk

# Download and install the latest SDK tools:
$ ./emsdk install latest

# Make the "latest" SDK "active" for the current user:
$ ./emsdk activate latest
```

Those parts only need to be run once, but the SDK can be updated using:

```
$ git pull
$ ./emsdk install latest
$ ./emsdk activate latest
```

The following needs to be run for each shell instance which needs the
`emcc` compiler:

```
# Activate PATH and other environment variables in the current terminal:
$ source ./emsdk_env.sh

$ which emcc
/path/to/emsdk/upstream/emscripten/emcc
```

Optionally, add that to your login shell's resource file (`~/.bashrc`
or equivalent).

That `env` script needs to be sourced for building this application
from the top of the sqlite3 build tree:

```
$ make fiddle
```

Or:

```
$ cd ext/wasm
$ make
```

That will generate the a number of files required for a handful of
test and demo applications which can be accessed via
`index.html`. WASM content cannot, due to XMLHttpRequest security
limitations, be loaded if the containing HTML file is opened directly
in the browser (i.e. if it is opened using a `file://` URL), so it
needs to be served via an HTTP server.  For example, using
[althttpd][]:

```
$ cd ext/wasm
$ althttpd --enable-sab --max-age 1 --page index.html
```

That will open the system's browser and run the index page, from which
all of the test and demo applications can be accessed.

Note that when serving this app via [althttpd][], it must be a version
from 2022-09-26 or newer so that it recognizes the `--enable-sab`
flag, which causes althttpd to emit two HTTP response headers which
are required to enable JavaScript's `SharedArrayBuffer` and `Atomics`
APIs. Those APIs are required in order to enable the OPFS-related
features in the apps which use them.

# Testing on a remote machine that is accessed via SSH

*NB: The following are developer notes, last validated on 2022-08-18*

  *  Remote: Install git, emsdk, and althttpd
     *  Use a [version of althttpd][althttpd] from
        September 26, 2022 or newer.
  *  Remote: Install the SQLite source tree.  CD to ext/wasm
  *  Remote: "`make`" to build WASM
  *  Remote: `althttpd --enable-sab --port 8080 --popup`
  *  Local:  `ssh -L 8180:localhost:8080 remote`
  *  Local:  Point your web-browser at http://localhost:8180/index.html

In order to enable [SharedArrayBuffers](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer),
the web-browser requires that the two extra Cross-Origin lines be present
in HTTP reply headers and that the request must come from "localhost".
Since the web-server is on a different machine from
the web-broser, the localhost requirement means that the connection must be tunneled
using SSH.


[emscripten]: https://emscripten.org
[althttpd]: https://sqlite.org/althttpd

Added ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api.









































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
_sqlite3_bind_blob
_sqlite3_bind_double
_sqlite3_bind_int
_sqlite3_bind_int64
_sqlite3_bind_null
_sqlite3_bind_parameter_count
_sqlite3_bind_parameter_index
_sqlite3_bind_text
_sqlite3_changes
_sqlite3_changes64
_sqlite3_clear_bindings
_sqlite3_close_v2
_sqlite3_column_blob
_sqlite3_column_bytes
_sqlite3_column_count
_sqlite3_column_count
_sqlite3_column_double
_sqlite3_column_int
_sqlite3_column_int64
_sqlite3_column_name
_sqlite3_column_text
_sqlite3_column_type
_sqlite3_compileoption_get
_sqlite3_compileoption_used
_sqlite3_create_function_v2
_sqlite3_data_count
_sqlite3_db_filename
_sqlite3_db_name
_sqlite3_errmsg
_sqlite3_error_offset
_sqlite3_errstr
_sqlite3_exec
_sqlite3_expanded_sql
_sqlite3_extended_errcode
_sqlite3_extended_result_codes
_sqlite3_finalize
_sqlite3_initialize
_sqlite3_interrupt
_sqlite3_libversion
_sqlite3_libversion_number
_sqlite3_open
_sqlite3_open_v2
_sqlite3_prepare_v2
_sqlite3_prepare_v3
_sqlite3_reset
_sqlite3_result_blob
_sqlite3_result_double
_sqlite3_result_error
_sqlite3_result_error_code
_sqlite3_result_error_nomem
_sqlite3_result_error_toobig
_sqlite3_result_int
_sqlite3_result_null
_sqlite3_result_text
_sqlite3_sourceid
_sqlite3_sql
_sqlite3_step
_sqlite3_strglob
_sqlite3_strlike
_sqlite3_total_changes
_sqlite3_total_changes64
_sqlite3_value_blob
_sqlite3_value_bytes
_sqlite3_value_double
_sqlite3_value_text
_sqlite3_value_type
_sqlite3_vfs_find
_sqlite3_vfs_register
_sqlite3_wasm_db_error
_sqlite3_wasm_enum_json
_malloc
_free

Added ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api.




1
2
3
+
+
+
FS
wasmMemory

Added ext/wasm/api/README.md.
































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# sqlite3-api.js And Friends

This is the README for the files `sqlite3-*.js` and
`sqlite3-wasm.c`. This collection of files is used to build a
single-file distribution of the sqlite3 WASM API. It is broken into
multiple JS files because:

1. To facilitate including or excluding certain components for
   specific use cases. e.g. by removing `sqlite3-api-oo1.js` if the
   OO#1 API is not needed.

2. To facilitate modularizing the pieces for use in different WASM
   build environments. e.g. the files `post-js-*.js` are for use with
   Emscripten's `--post-js` feature, and nowhere else.

3. Certain components must be in their own standalone files in order
   to be loaded as JS Workers.

Note that the structure described here is the current state of things,
as of this writing, but is not set in stone forever and may change
at any time.

The overall idea is that the following files get concatenated
together, in the listed order, the resulting file is loaded by a
browser client:

- **`sqlite3-api-prologue.js`**\  
  Contains the initial bootstrap setup of the sqlite3 API
  objects. This is exposed as a function, rather than objects, so that
  the next step can pass in a config object which abstracts away parts
  of the WASM environment, to facilitate plugging it in to arbitrary
  WASM toolchains.
- **`../common/whwasmutil.js`**\  
  A semi-third-party collection of JS/WASM utility code intended to
  replace much of the Emscripten glue. The sqlite3 APIs internally use
  these APIs instead of their Emscripten counterparts, in order to be
  more portable to arbitrary WASM toolchains. This API is
  configurable, in principle, for use with arbitrary WASM
  toolchains. It is "semi-third-party" in that it was created in order
  to support this tree but is standalone and maintained together
  with...
- **`../jaccwabyt/jaccwabyt.js`**\  
  Another semi-third-party API which creates bindings between JS
  and C structs, such that changes to the struct state from either JS
  or C are visible to the other end of the connection. This is also an
  independent spinoff project, conceived for the sqlite3 project but
  maintained separately.
- **`sqlite3-api-glue.js`**\  
  Invokes functionality exposed by the previous two files to flesh out
  low-level parts of `sqlite3-api-prologue.js`. Most of these pieces
  related to populating the `sqlite3.capi.wasm` object. This file
  also deletes most global-scope symbols the above files create,
  effectively moving them into the scope being used for initializing
  the API.
- **`<build>/sqlite3-api-build-version.js`**\  
  Gets created by the build process and populates the
  `sqlite3.version` object. This part is not critical, but records the
  version of the library against which this module was built.
- **`sqlite3-api-oo1.js`**\  
  Provides a high-level object-oriented wrapper to the lower-level C
  API, colloquially known as OO API #1. Its API is similar to other
  high-level sqlite3 JS wrappers and should feel relatively familiar
  to anyone familiar with such APIs. That said, it is not a "required
  component" and can be elided from builds which do not want it.
- **`sqlite3-api-worker1.js`**\  
  A Worker-thread-based API which uses OO API #1 to provide an
  interface to a database which can be driven from the main Window
  thread via the Worker message-passing interface. Like OO API #1,
  this is an optional component, offering one of any number of
  potential implementations for such an API.
    - **`sqlite3-worker1.js`**\  
      Is not part of the amalgamated sources and is intended to be
      loaded by a client Worker thread. It loads the sqlite3 module
      and runs the Worker #1 API which is implemented in
      `sqlite3-api-worker1.js`.
    - **`sqlite3-worker1-promiser.js`**\  
      Is likewise not part of the amalgamated sources and provides
      a Promise-based interface into the Worker #1 API. This is
      a far user-friendlier way to interface with databases running
      in a Worker thread.
- **`sqlite3-v-helper.js`**\  
  Installs `sqlite3.vfs` and `sqlite3.vtab`, namespaces which contain
  helpers for use by downstream code which creates `sqlite3_vfs`
  and `sqlite3_module` implementations.
- **`sqlite3-vfs-opfs.c-pp.js`**\  
  is an sqlite3 VFS implementation which supports Google Chrome's
  Origin-Private FileSystem (OPFS) as a storage layer to provide
  persistent storage for database files in a browser. It requires...
    - **`sqlite3-opfs-async-proxy.js`**\  
      is the asynchronous backend part of the OPFS proxy. It speaks
      directly to the (async) OPFS API and channels those results back
      to its synchronous counterpart. This file, because it must be
      started in its own Worker, is not part of the amalgamation.
- **`api/sqlite3-api-cleanup.js`**\  
  The previous files do not immediately extend the library. Instead
  they add callback functions to be called during its
  bootstrapping. Some also temporarily create global objects in order
  to communicate their state to the files which follow them. This file
  cleans up any dangling globals and runs the API bootstrapping
  process, which is what finally executes the initialization code
  installed by the previous files. As of this writing, this code
  ensures that the previous files leave no more than a single global
  symbol installed. When adapting the API for non-Emscripten
  toolchains, this "should" be the only file where changes are needed.


**Files with the extension `.c-pp.js`** are intended [to be processed
with `c-pp`](#c-pp), noting that such preprocessing may be applied
after all of the relevant files are concatenated. That extension is
used primarily to keep the code maintainers cognisant of the fact that
those files contain constructs which will not run as-is in JavaScript.

The build process glues those files together, resulting in
`sqlite3-api.js`, which is everything except for the `post-js-*.js`
files, and `sqlite3.js`, which is the Emscripten-generated amalgamated
output and includes the `post-js-*.js` parts, as well as the
Emscripten-provided module loading pieces.

The non-JS outlier file is `sqlite3-wasm.c`: it is a proxy for
`sqlite3.c` which `#include`'s that file and adds a couple more
WASM-specific helper functions, at least one of which requires access
to private/static `sqlite3.c` internals. `sqlite3.wasm` is compiled
from this file rather than `sqlite3.c`.

The following files are part of the build process but are injected
into the build-generated `sqlite3.js` along with `sqlite3-api.js`.

- `extern-pre-js.js`\  
  Emscripten-specific header for Emscripten's `--extern-pre-js`
  flag. As of this writing, that file is only used for experimentation
  purposes and holds no code relevant to the production deliverables.
- `pre-js.c-pp.js`\  
  Emscripten-specific header for Emscripten's `--pre-js` flag. This
  file is intended as a place to override certain Emscripten behavior
  before it starts up, but corner-case Emscripten bugs keep that from
  being a reality.
- `post-js-header.js`\  
  Emscripten-specific header for the `--post-js` input. It opens up
  a lexical scope by starting a post-run handler for Emscripten.
- `post-js-footer.js`\  
  Emscripten-specific footer for the `--post-js` input. This closes
  off the lexical scope opened by `post-js-header.js`.
- `extern-post-js.c-pp.js`\  
  Emscripten-specific header for Emscripten's `--extern-post-js`
  flag. This file overwrites the Emscripten-installed
  `sqlite3InitModule()` function with one which, after the module is
  loaded, also initializes the asynchronous parts of the sqlite3
  module. For example, the OPFS VFS support.

<a id='c-pp'></a>
Preprocessing of Source Files
------------------------------------------------------------------------

Certain files in the build require preprocessing to filter in/out
parts which differ between vanilla JS builds and ES6 Module
(a.k.a. esm) builds. The preprocessor application itself is in
[`c-pp.c`](/file/ext/wasm/c-pp.c) and the complete technical details
of such preprocessing are maintained in
[`GNUMakefile`](/file/ext/wasm/GNUmakefile).

Added ext/wasm/api/extern-post-js.c-pp.js.































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

/* ^^^^ ACHTUNG: blank line at the start is necessary because
   Emscripten will not add a newline in some cases and we need
   a blank line for a sed-based kludge for the ES6 build. */
/* extern-post-js.js must be appended to the resulting sqlite3.js
   file. It gets its name from being used as the value for the
   --extern-post-js=... Emscripten flag. Note that this code, unlike
   most of the associated JS code, runs outside of the
   Emscripten-generated module init scope, in the current
   global scope. */
//#if target=es6-module
const toExportForESM =
//#endif
(function(){
  /**
     In order to hide the sqlite3InitModule()'s resulting
     Emscripten module from downstream clients (and simplify our
     documentation by being able to elide those details), we hide that
     function and expose a hand-written sqlite3InitModule() to return
     the sqlite3 object (most of the time).

     Unfortunately, we cannot modify the module-loader/exporter-based
     impls which Emscripten installs at some point in the file above
     this.
  */
  const originalInit =
        /* Maintenance reminder: DO NOT use `self.` here. It's correct
           for non-ES6 Module cases but wrong for ES6 modules because those
           resolve this symbol differently. */ sqlite3InitModule;
  if(!originalInit){
    throw new Error("Expecting self.sqlite3InitModule to be defined by the Emscripten build.");
  }
  /**
     We need to add some state which our custom Module.locateFile()
     can see, but an Emscripten limitation currently prevents us from
     attaching it to the sqlite3InitModule function object:

     https://github.com/emscripten-core/emscripten/issues/18071

     The only(?) current workaround is to temporarily stash this state
     into the global scope and delete it when sqlite3InitModule()
     is called.
  */
  const initModuleState = self.sqlite3InitModuleState = Object.assign(Object.create(null),{
    moduleScript: self?.document?.currentScript,
    isWorker: ('undefined' !== typeof WorkerGlobalScope),
    location: self.location,
    urlParams:  new URL(self.location.href).searchParams
  });
  initModuleState.debugModule =
    initModuleState.urlParams.has('sqlite3.debugModule')
    ? (...args)=>console.warn('sqlite3.debugModule:',...args)
    : ()=>{};

  if(initModuleState.urlParams.has('sqlite3.dir')){
    initModuleState.sqlite3Dir = initModuleState.urlParams.get('sqlite3.dir') +'/';
  }else if(initModuleState.moduleScript){
    const li = initModuleState.moduleScript.src.split('/');
    li.pop();
    initModuleState.sqlite3Dir = li.join('/') + '/';
  }

  self.sqlite3InitModule = function ff(...args){
    //console.warn("Using replaced sqlite3InitModule()",self.location);
    return originalInit(...args).then((EmscriptenModule)=>{
      if(self.window!==self &&
         (EmscriptenModule['ENVIRONMENT_IS_PTHREAD']
          || EmscriptenModule['_pthread_self']
          || 'function'===typeof threadAlert
          || self.location.pathname.endsWith('.worker.js')
         )){
        /** Workaround for wasmfs-generated worker, which calls this
            routine from each individual thread and requires that its
            argument be returned. All of the criteria above are fragile,
            based solely on inspection of the offending code, not public
            Emscripten details. */
        return EmscriptenModule;
      }
      const s = EmscriptenModule.sqlite3;
      s.scriptInfo = initModuleState;
      //console.warn("sqlite3.scriptInfo =",s.scriptInfo);
      if(ff.__isUnderTest) s.__isUnderTest = true;
      const f = s.asyncPostInit;
      delete s.asyncPostInit;
      return f();
    }).catch((e)=>{
      console.error("Exception loading sqlite3 module:",e);
      throw e;
    });
  };
  self.sqlite3InitModule.ready = originalInit.ready;

  if(self.sqlite3InitModuleState.moduleScript){
    const sim = self.sqlite3InitModuleState;
    let src = sim.moduleScript.src.split('/');
    src.pop();
    sim.scriptDir = src.join('/') + '/';
  }
  initModuleState.debugModule('sqlite3InitModuleState =',initModuleState);
  if(0){
    console.warn("Replaced sqlite3InitModule()");
    console.warn("self.location.href =",self.location.href);
    if('undefined' !== typeof document){
      console.warn("document.currentScript.src =",
                   document?.currentScript?.src);
    }
  }
//#ifnot target=es6-module
// Emscripten does not inject these module-loader bits in ES6 module
// builds and including them here breaks JS bundlers, so elide them
// from ESM builds.
  /* Replace the various module exports performed by the Emscripten
     glue... */
  if (typeof exports === 'object' && typeof module === 'object'){
    module.exports = sqlite3InitModule;
  }else if (typeof exports === 'object'){
    exports["sqlite3InitModule"] = sqlite3InitModule;
  }
  /* AMD modules get injected in a way we cannot override,
     so we can't handle those here. */
//#endif // !target=es6-module
  return self.sqlite3InitModule /* required for ESM */;
})();
//#if target=es6-module
export default toExportForESM;
//#endif

Added ext/wasm/api/extern-pre-js.js.








1
2
3
4
5
6
7
+
+
+
+
+
+
+
/* extern-pre-js.js must be prepended to the resulting sqlite3.js
   file. This file is currently only used for holding snippets during
   test and development.

   It gets its name from being used as the value for the
   --extern-pre-js=... Emscripten flag.
*/

Added ext/wasm/api/post-js-footer.js.





1
2
3
4
+
+
+
+
/* The current function scope was opened via post-js-header.js, which
   gets prepended to this at build-time. This file closes that
   scope. */
})/*postRun.push(...)*/;

Added ext/wasm/api/post-js-header.js.



























1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/**
   post-js-header.js is to be prepended to other code to create
   post-js.js for use with Emscripten's --post-js flag. This code
   requires that it be running in that context. The Emscripten
   environment must have been set up already but it will not have
   loaded its WASM when the code in this file is run. The function it
   installs will be run after the WASM module is loaded, at which
   point the sqlite3 JS API bits will get set up.
*/
if(!Module.postRun) Module.postRun = [];
Module.postRun.push(function(Module/*the Emscripten-style module object*/){
  'use strict';
  /* This function will contain at least the following:

     - post-js-header.js (this file)
     - sqlite3-api-prologue.js  => Bootstrapping bits to attach the rest to
     - common/whwasmutil.js     => Replacements for much of Emscripten's glue
     - jaccwaby/jaccwabyt.js    => Jaccwabyt (C/JS struct binding)
     - sqlite3-api-glue.js      => glues previous parts together
     - sqlite3-api-oo.js        => SQLite3 OO API #1
     - sqlite3-api-worker1.js   => Worker-based API
     - sqlite3-vfs-helper.js    => Internal-use utilities for...
     - sqlite3-vfs-opfs.js      => OPFS VFS
     - sqlite3-api-cleanup.js   => final API cleanup
     - post-js-footer.js        => closes this postRun() function
  */

Added ext/wasm/api/pre-js.c-pp.js.















































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/**
   BEGIN FILE: api/pre-js.js

   This file is intended to be prepended to the sqlite3.js build using
   Emscripten's --pre-js=THIS_FILE flag (or equivalent).
*/

// See notes in extern-post-js.js
const sqlite3InitModuleState = self.sqlite3InitModuleState
      || Object.assign(Object.create(null),{
        debugModule: ()=>{}
      });
delete self.sqlite3InitModuleState;
sqlite3InitModuleState.debugModule('self.location =',self.location);

//#ifnot target=es6-bundler-friendly
/**
   This custom locateFile() tries to figure out where to load `path`
   from. The intent is to provide a way for foo/bar/X.js loaded from a
   Worker constructor or importScripts() to be able to resolve
   foo/bar/X.wasm (in the latter case, with some help):

   1) If URL param named the same as `path` is set, it is returned.

   2) If sqlite3InitModuleState.sqlite3Dir is set, then (thatName + path)
      is returned (note that it's assumed to end with '/').

   3) If this code is running in the main UI thread AND it was loaded
      from a SCRIPT tag, the directory part of that URL is used
      as the prefix. (This form of resolution unfortunately does not
      function for scripts loaded via importScripts().)

   4) If none of the above apply, (prefix+path) is returned.
*/
Module['locateFile'] = function(path, prefix) {
//#if target=es6-module
  return new URL(path, import.meta.url).href;
//#else
  'use strict';
  let theFile;
  const up = this.urlParams;
  if(up.has(path)){
    theFile = up.get(path);
  }else if(this.sqlite3Dir){
    theFile = this.sqlite3Dir + path;
  }else if(this.scriptDir){
    theFile = this.scriptDir + path;
  }else{
    theFile = prefix + path;
  }
  sqlite3InitModuleState.debugModule(
    "locateFile(",arguments[0], ',', arguments[1],")",
    'sqlite3InitModuleState.scriptDir =',this.scriptDir,
    'up.entries() =',Array.from(up.entries()),
    "result =", theFile
  );
  return theFile;
//#endif target=es6-module
}.bind(sqlite3InitModuleState);
//#endif ifnot target=es6-bundler-friendly

/**
   Bug warning: a custom Module.instantiateWasm() does not work
   in WASMFS builds:

   https://github.com/emscripten-core/emscripten/issues/17951

   In such builds we must disable this.
*/
const xNameOfInstantiateWasm = false
      ? 'instantiateWasm'
      : 'emscripten-bug-17951';
Module[xNameOfInstantiateWasm] = function callee(imports,onSuccess){
  imports.env.foo = function(){};
  const uri = Module.locateFile(
    callee.uri, (
      ('undefined'===typeof scriptDirectory/*var defined by Emscripten glue*/)
        ? "" : scriptDirectory)
  );
  sqlite3InitModuleState.debugModule(
    "instantiateWasm() uri =", uri
  );
  const wfetch = ()=>fetch(uri, {credentials: 'same-origin'});
  const loadWasm = WebAssembly.instantiateStreaming
        ? async ()=>{
          return WebAssembly.instantiateStreaming(wfetch(), imports)
            .then((arg)=>onSuccess(arg.instance, arg.module));
        }
        : async ()=>{ // Safari < v15
          return wfetch()
            .then(response => response.arrayBuffer())
            .then(bytes => WebAssembly.instantiate(bytes, imports))
            .then((arg)=>onSuccess(arg.instance, arg.module));
        };
  loadWasm();
  return {};
};
/*
  It is literally impossible to reliably get the name of _this_ script
  at runtime, so impossible to derive X.wasm from script name
  X.js. Thus we need, at build-time, to redefine
  Module[xNameOfInstantiateWasm].uri by appending it to a build-specific
  copy of this file with the name of the wasm file. This is apparently
  why Emscripten hard-codes the name of the wasm file into their glue
  scripts.
*/
Module[xNameOfInstantiateWasm].uri = 'sqlite3.wasm';
/* END FILE: api/pre-js.js, noting that the build process may add a
   line after this one to change the above .uri to a build-specific
   one. */

Added ext/wasm/api/sqlite3-api-cleanup.js.






























































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
  2022-07-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 is the tail end of the sqlite3-api.js constellation,
  intended to be appended after all other sqlite3-api-*.js files so
  that it can finalize any setup and clean up any global symbols
  temporarily used for setting up the API's various subsystems.
*/
'use strict';
if('undefined' !== typeof Module){ // presumably an Emscripten build
  /**
     Install a suitable default configuration for sqlite3ApiBootstrap().
  */
  const SABC = Object.assign(
    Object.create(null), {
      exports: Module['asm'],
      memory: Module.wasmMemory /* gets set if built with -sIMPORT_MEMORY */
    },
    self.sqlite3ApiConfig || {}
  );

  /**
     For current (2022-08-22) purposes, automatically call
     sqlite3ApiBootstrap().  That decision will be revisited at some
     point, as we really want client code to be able to call this to
     configure certain parts. Clients may modify
     self.sqlite3ApiBootstrap.defaultConfig to tweak the default
     configuration used by a no-args call to sqlite3ApiBootstrap(),
     but must have first loaded their WASM module in order to be
     able to provide the necessary configuration state.
  */
  //console.warn("self.sqlite3ApiConfig = ",self.sqlite3ApiConfig);
  self.sqlite3ApiConfig = SABC;
  let sqlite3;
  try{
    sqlite3 = self.sqlite3ApiBootstrap();
  }catch(e){
    console.error("sqlite3ApiBootstrap() error:",e);
    throw e;
  }finally{
    delete self.sqlite3ApiBootstrap;
    delete self.sqlite3ApiConfig;
  }

  Module.sqlite3 = sqlite3 /* Needed for customized sqlite3InitModule() to be able to
                              pass the sqlite3 object off to the client. */;
}else{
  console.warn("This is not running in an Emscripten module context, so",
               "self.sqlite3ApiBootstrap() is _not_ being called due to lack",
               "of config info for the WASM environment.",
               "It must be called manually.");
}

Added ext/wasm/api/sqlite3-api-glue.js.




















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
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
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
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
  2022-07-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 glues together disparate pieces of JS which are loaded in
  previous steps of the sqlite3-api.js bootstrapping process:
  sqlite3-api-prologue.js, whwasmutil.js, and jaccwabyt.js. It
  initializes the main API pieces so that the downstream components
  (e.g. sqlite3-api-oo1.js) have all that they need.
*/
self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
  'use strict';
  const toss = (...args)=>{throw new Error(args.join(' '))};
  const toss3 = sqlite3.SQLite3Error.toss;
  const capi = sqlite3.capi, wasm = sqlite3.wasm, util = sqlite3.util;
  self.WhWasmUtilInstaller(wasm);
  delete self.WhWasmUtilInstaller;

  if(0){
    /**
       Please keep this block around as a maintenance reminder
       that we cannot rely on this type of check.

       This block fails on Safari, per a report at
       https://sqlite.org/forum/forumpost/e5b20e1feb.

       It turns out that what Safari serves from the indirect function
       table (e.g. wasm.functionEntry(X)) is anonymous functions which
       wrap the WASM functions, rather than returning the WASM
       functions themselves. That means comparison of such functions
       is useless for determining whether or not we have a specific
       function from wasm.exports. i.e. if function X is indirection
       function table entry N then wasm.exports.X is not equal to
       wasm.functionEntry(N) in Safari, despite being so in the other
       browsers.
    */
    /**
       Find a mapping for SQLITE_WASM_DEALLOC, which the API
       guarantees is a WASM pointer to the same underlying function as
       wasm.dealloc() (noting that wasm.dealloc() is permitted to be a
       JS wrapper around the WASM function). There is unfortunately no
       O(1) algorithm for finding this pointer: we have to walk the
       WASM indirect function table to find it. However, experience
       indicates that that particular function is always very close to
       the front of the table (it's been entry #3 in all relevant
       tests).
    */
    const dealloc = wasm.exports[sqlite3.config.deallocExportName];
    const nFunc = wasm.functionTable().length;
    let i;
    for(i = 0; i < nFunc; ++i){
      const e = wasm.functionEntry(i);
      if(dealloc === e){
        capi.SQLITE_WASM_DEALLOC = i;
        break;
      }
    }
    if(dealloc !== wasm.functionEntry(capi.SQLITE_WASM_DEALLOC)){
      toss("Internal error: cannot find function pointer for SQLITE_WASM_DEALLOC.");
    }
  }

  /**
     Signatures for the WASM-exported C-side functions. Each entry
     is an array with 2+ elements:

     [ "c-side name",
       "result type" (wasm.xWrap() syntax),
       [arg types in xWrap() syntax]
       // ^^^ this needn't strictly be an array: it can be subsequent
       // elements instead: [x,y,z] is equivalent to x,y,z
     ]

     Note that support for the API-specific data types in the
     result/argument type strings gets plugged in at a later phase in
     the API initialization process.
  */
  wasm.bindingSignatures = [
    // Please keep these sorted by function name!
    ["sqlite3_aggregate_context","void*", "sqlite3_context*", "int"],
    /* sqlite3_auto_extension() has a hand-written binding. */
    /* sqlite3_bind_blob() and sqlite3_bind_text() have hand-written
       bindings to permit more flexible inputs. */
    ["sqlite3_bind_double","int", "sqlite3_stmt*", "int", "f64"],
    ["sqlite3_bind_int","int", "sqlite3_stmt*", "int", "int"],
    ["sqlite3_bind_null",undefined, "sqlite3_stmt*", "int"],
    ["sqlite3_bind_parameter_count", "int", "sqlite3_stmt*"],
    ["sqlite3_bind_parameter_index","int", "sqlite3_stmt*", "string"],
    ["sqlite3_bind_pointer", "int",
     "sqlite3_stmt*", "int", "*", "string:static", "*"],
    ["sqlite3_busy_handler","int", [
      "sqlite3*",
      new wasm.xWrap.FuncPtrAdapter({
        signature: 'i(pi)',
        contextKey: (argv,argIndex)=>argv[0/* sqlite3* */]
      }),
      "*"
    ]],
    ["sqlite3_busy_timeout","int", "sqlite3*", "int"],
    /* sqlite3_cancel_auto_extension() has a hand-written binding. */
    /* sqlite3_close_v2() is implemented by hand to perform some
       extra work. */
    ["sqlite3_changes", "int", "sqlite3*"],
    ["sqlite3_clear_bindings","int", "sqlite3_stmt*"],
    ["sqlite3_collation_needed", "int", "sqlite3*", "*", "*"/*=>v(ppis)*/],
    ["sqlite3_column_blob","*", "sqlite3_stmt*", "int"],
    ["sqlite3_column_bytes","int", "sqlite3_stmt*", "int"],
    ["sqlite3_column_count", "int", "sqlite3_stmt*"],
    ["sqlite3_column_double","f64", "sqlite3_stmt*", "int"],
    ["sqlite3_column_int","int", "sqlite3_stmt*", "int"],
    ["sqlite3_column_name","string", "sqlite3_stmt*", "int"],
    ["sqlite3_column_text","string", "sqlite3_stmt*", "int"],
    ["sqlite3_column_type","int", "sqlite3_stmt*", "int"],
    ["sqlite3_column_value","sqlite3_value*", "sqlite3_stmt*", "int"],
    ["sqlite3_commit_hook", "void*", [
      "sqlite3*",
      new wasm.xWrap.FuncPtrAdapter({
        name: 'sqlite3_commit_hook',
        signature: 'i(p)',
        contextKey: (argv)=>argv[0/* sqlite3* */]
      }),
      '*'
    ]],
    ["sqlite3_compileoption_get", "string", "int"],
    ["sqlite3_compileoption_used", "int", "string"],
    ["sqlite3_complete", "int", "string:flexible"],
    ["sqlite3_context_db_handle", "sqlite3*", "sqlite3_context*"],

    /* sqlite3_create_function(), sqlite3_create_function_v2(), and
       sqlite3_create_window_function() use hand-written bindings to
       simplify handling of their function-type arguments. */
    /* sqlite3_create_collation() and sqlite3_create_collation_v2()
       use hand-written bindings to simplify passing of the callback
       function.
      ["sqlite3_create_collation", "int",
     "sqlite3*", "string", "int",//SQLITE_UTF8 is the only legal value
     "*", "*"],
    ["sqlite3_create_collation_v2", "int",
     "sqlite3*", "string", "int",//SQLITE_UTF8 is the only legal value
     "*", "*", "*"],
    */
    ["sqlite3_data_count", "int", "sqlite3_stmt*"],
    ["sqlite3_db_filename", "string", "sqlite3*", "string"],
    ["sqlite3_db_handle", "sqlite3*", "sqlite3_stmt*"],
    ["sqlite3_db_name", "string", "sqlite3*", "int"],
    ["sqlite3_db_status", "int", "sqlite3*", "int", "*", "*", "int"],
    ["sqlite3_errcode", "int", "sqlite3*"],
    ["sqlite3_errmsg", "string", "sqlite3*"],
    ["sqlite3_error_offset", "int", "sqlite3*"],
    ["sqlite3_errstr", "string", "int"],
    ["sqlite3_exec", "int", [
      "sqlite3*", "string:flexible",
      new wasm.xWrap.FuncPtrAdapter({
        signature: 'i(pipp)',
        bindScope: 'transient',
        callProxy: (callback)=>{
          let aNames;
          return (pVoid, nCols, pColVals, pColNames)=>{
            try {
              const aVals = wasm.cArgvToJs(nCols, pColVals);
              if(!aNames) aNames = wasm.cArgvToJs(nCols, pColNames);
              return callback(aVals, aNames) | 0;
            }catch(e){
              /* If we set the db error state here, the higher-level
                 exec() call replaces it with its own, so we have no way
                 of reporting the exception message except the console. We
                 must not propagate exceptions through the C API. Though
                 we make an effort to report OOM here, sqlite3_exec()
                 translates that into SQLITE_ABORT as well. */
              return e.resultCode || capi.SQLITE_ERROR;
            }
          }
        }
      }),
      "*", "**"
    ]],
    ["sqlite3_expanded_sql", "string", "sqlite3_stmt*"],
    ["sqlite3_extended_errcode", "int", "sqlite3*"],
    ["sqlite3_extended_result_codes", "int", "sqlite3*", "int"],
    ["sqlite3_file_control", "int", "sqlite3*", "string", "int", "*"],
    ["sqlite3_finalize", "int", "sqlite3_stmt*"],
    ["sqlite3_free", undefined,"*"],
    ["sqlite3_get_auxdata", "*", "sqlite3_context*", "int"],
    ["sqlite3_initialize", undefined],
    /*["sqlite3_interrupt", undefined, "sqlite3*"
       ^^^ we cannot actually currently support this because JS is
        single-threaded and we don't have a portable way to access a DB
        from 2 SharedWorkers concurrently. ],*/
    ["sqlite3_keyword_count", "int"],
    ["sqlite3_keyword_name", "int", ["int", "**", "*"]],
    ["sqlite3_keyword_check", "int", ["string", "int"]],
    ["sqlite3_libversion", "string"],
    ["sqlite3_libversion_number", "int"],
    ["sqlite3_limit", "int", ["sqlite3*", "int", "int"]],
    ["sqlite3_malloc", "*","int"],
    ["sqlite3_open", "int", "string", "*"],
    ["sqlite3_open_v2", "int", "string", "*", "int", "string"],
    /* sqlite3_prepare_v2() and sqlite3_prepare_v3() are handled
       separately due to us requiring two different sets of semantics
       for those, depending on how their SQL argument is provided. */
    /* sqlite3_randomness() uses a hand-written wrapper to extend
       the range of supported argument types. */
    ["sqlite3_progress_handler", undefined, [
      "sqlite3*", "int", new wasm.xWrap.FuncPtrAdapter({
        name: 'xProgressHandler',
        signature: 'i(p)',
        bindScope: 'context',
        contextKey: (argv,argIndex)=>argv[0/* sqlite3* */]
      }), "*"
    ]],
    ["sqlite3_realloc", "*","*","int"],
    ["sqlite3_reset", "int", "sqlite3_stmt*"],
    /* sqlite3_reset_auto_extension() has a hand-written binding. */
    ["sqlite3_result_blob", undefined, "sqlite3_context*", "*", "int", "*"],
    ["sqlite3_result_double", undefined, "sqlite3_context*", "f64"],
    ["sqlite3_result_error", undefined, "sqlite3_context*", "string", "int"],
    ["sqlite3_result_error_code", undefined, "sqlite3_context*", "int"],
    ["sqlite3_result_error_nomem", undefined, "sqlite3_context*"],
    ["sqlite3_result_error_toobig", undefined, "sqlite3_context*"],
    ["sqlite3_result_int", undefined, "sqlite3_context*", "int"],
    ["sqlite3_result_null", undefined, "sqlite3_context*"],
    ["sqlite3_result_pointer", undefined,
     "sqlite3_context*", "*", "string:static", "*"],
    ["sqlite3_result_subtype", undefined, "sqlite3_value*", "int"],
    ["sqlite3_result_text", undefined, "sqlite3_context*", "string", "int", "*"],
    ["sqlite3_result_zeroblob", undefined, "sqlite3_context*", "int"],
    ["sqlite3_rollback_hook", "void*", [
      "sqlite3*",
      new wasm.xWrap.FuncPtrAdapter({
        name: 'sqlite3_rollback_hook',
        signature: 'v(p)',
        contextKey: (argv)=>argv[0/* sqlite3* */]
      }),
      '*'
    ]],
    ["sqlite3_set_authorizer", "int", [
      "sqlite3*",
      new wasm.xWrap.FuncPtrAdapter({
        name: "sqlite3_set_authorizer::xAuth",
        signature: "i(pi"+"ssss)",
        contextKey: (argv, argIndex)=>argv[0/*(sqlite3*)*/],
        callProxy: (callback)=>{
          return (pV, iCode, s0, s1, s2, s3)=>{
            try{
              s0 = s0 && wasm.cstrToJs(s0); s1 = s1 && wasm.cstrToJs(s1);
              s2 = s2 && wasm.cstrToJs(s2); s3 = s3 && wasm.cstrToJs(s3);
              return callback(pV, iCode, s0, s1, s2, s3) || 0;
            }catch(e){
              return e.resultCode || capi.SQLITE_ERROR;
            }
          }
        }
      }),
      "*"/*pUserData*/
    ]],
    ["sqlite3_set_auxdata", undefined, [
      "sqlite3_context*", "int", "*",
      new wasm.xWrap.FuncPtrAdapter({
        name: 'xDestroyAuxData',
        signature: 'v(*)',
        contextKey: (argv, argIndex)=>argv[0/* sqlite3_context* */]
      })
    ]],
    ["sqlite3_shutdown", undefined],
    ["sqlite3_sourceid", "string"],
    ["sqlite3_sql", "string", "sqlite3_stmt*"],
    ["sqlite3_status", "int", "int", "*", "*", "int"],
    ["sqlite3_step", "int", "sqlite3_stmt*"],
    ["sqlite3_stmt_isexplain", "int", ["sqlite3_stmt*"]],
    ["sqlite3_stmt_readonly", "int", ["sqlite3_stmt*"]],
    ["sqlite3_stmt_status", "int", "sqlite3_stmt*", "int", "int"],
    ["sqlite3_strglob", "int", "string","string"],
    ["sqlite3_stricmp", "int", "string", "string"],
    ["sqlite3_strlike", "int", "string", "string","int"],
    ["sqlite3_strnicmp", "int", "string", "string", "int"],
    ["sqlite3_table_column_metadata", "int",
     "sqlite3*", "string", "string", "string",
     "**", "**", "*", "*", "*"],
    ["sqlite3_total_changes", "int", "sqlite3*"],
    ["sqlite3_trace_v2", "int", [
      "sqlite3*", "int",
      new wasm.xWrap.FuncPtrAdapter({
        name: 'sqlite3_trace_v2::callback',
        signature: 'i(ippp)',
        contextKey: (argv,argIndex)=>argv[0/* sqlite3* */]
      }),
      "*"
    ]],
    ["sqlite3_txn_state", "int", ["sqlite3*","string"]],
    /* Note that sqlite3_uri_...() have very specific requirements for
       their first C-string arguments, so we cannot perform any value
       conversion on those. */
    ["sqlite3_uri_boolean", "int", "sqlite3_filename", "string", "int"],
    ["sqlite3_uri_key", "string", "sqlite3_filename", "int"],
    ["sqlite3_uri_parameter", "string", "sqlite3_filename", "string"],
    ["sqlite3_user_data","void*", "sqlite3_context*"],
    ["sqlite3_value_blob", "*", "sqlite3_value*"],
    ["sqlite3_value_bytes","int", "sqlite3_value*"],
    ["sqlite3_value_double","f64", "sqlite3_value*"],
    ["sqlite3_value_dup", "sqlite3_value*", "sqlite3_value*"],
    ["sqlite3_value_free", undefined, "sqlite3_value*"],
    ["sqlite3_value_frombind", "int", "sqlite3_value*"],
    ["sqlite3_value_int","int", "sqlite3_value*"],
    ["sqlite3_value_nochange", "int", "sqlite3_value*"],
    ["sqlite3_value_numeric_type", "int", "sqlite3_value*"],
    ["sqlite3_value_pointer", "*", "sqlite3_value*", "string:static"],
    ["sqlite3_value_subtype", "int", "sqlite3_value*"],
    ["sqlite3_value_text", "string", "sqlite3_value*"],
    ["sqlite3_value_type", "int", "sqlite3_value*"],
    ["sqlite3_vfs_find", "*", "string"],
    ["sqlite3_vfs_register", "int", "sqlite3_vfs*", "int"],
    ["sqlite3_vfs_unregister", "int", "sqlite3_vfs*"]
  ]/*wasm.bindingSignatures*/;

  if(false && wasm.compileOptionUsed('SQLITE_ENABLE_NORMALIZE')){
    /* ^^^ "the problem" is that this is an option feature and the
       build-time function-export list does not currently take
       optional features into account. */
    wasm.bindingSignatures.push(["sqlite3_normalized_sql", "string", "sqlite3_stmt*"]);
  }

  /**
     Functions which require BigInt (int64) support are separated from
     the others because we need to conditionally bind them or apply
     dummy impls, depending on the capabilities of the environment.

     Note that not all of these functions directly require int64
     but are only for use with APIs which require int64. For example,
     the vtab-related functions.
  */
  wasm.bindingSignatures.int64 = [
    ["sqlite3_bind_int64","int", ["sqlite3_stmt*", "int", "i64"]],
    ["sqlite3_changes64","i64", ["sqlite3*"]],
    ["sqlite3_column_int64","i64", ["sqlite3_stmt*", "int"]],
    ["sqlite3_create_module", "int",
     ["sqlite3*","string","sqlite3_module*","*"]],
    ["sqlite3_create_module_v2", "int",
     ["sqlite3*","string","sqlite3_module*","*","*"]],
    ["sqlite3_declare_vtab", "int", ["sqlite3*", "string:flexible"]],
    ["sqlite3_deserialize", "int", "sqlite3*", "string", "*", "i64", "i64", "int"]
    /* Careful! Short version: de/serialize() are problematic because they
       might use a different allocator than the user for managing the
       deserialized block. de/serialize() are ONLY safe to use with
       sqlite3_malloc(), sqlite3_free(), and its 64-bit variants. */,
    ["sqlite3_drop_modules", "int", ["sqlite3*", "**"]],
    ["sqlite3_last_insert_rowid", "i64", ["sqlite3*"]],
    ["sqlite3_malloc64", "*","i64"],
    ["sqlite3_msize", "i64", "*"],
    ["sqlite3_overload_function", "int", ["sqlite3*","string","int"]],
    ["sqlite3_preupdate_blobwrite", "int", "sqlite3*"],
    ["sqlite3_preupdate_count", "int", "sqlite3*"],
    ["sqlite3_preupdate_depth", "int", "sqlite3*"],
    ["sqlite3_preupdate_hook", "*", [
      "sqlite3*",
      new wasm.xWrap.FuncPtrAdapter({
        name: 'sqlite3_preupdate_hook',
        signature: "v(ppippjj)",
        contextKey: (argv)=>argv[0/* sqlite3* */],
        callProxy: (callback)=>{
          return (p,db,op,zDb,zTbl,iKey1,iKey2)=>{
            callback(p, db, op, wasm.cstrToJs(zDb), wasm.cstrToJs(zTbl),
                     iKey1, iKey2);
          };
        }
      }),
      "*"
    ]],
    ["sqlite3_preupdate_new", "int", ["sqlite3*", "int", "**"]],
    ["sqlite3_preupdate_old", "int", ["sqlite3*", "int", "**"]],
    ["sqlite3_realloc64", "*","*", "i64"],
    ["sqlite3_result_int64", undefined, "*", "i64"],
    ["sqlite3_result_zeroblob64", "int", "*", "i64"],
    ["sqlite3_serialize","*", "sqlite3*", "string", "*", "int"],
    ["sqlite3_set_last_insert_rowid", undefined, ["sqlite3*", "i64"]],
    ["sqlite3_status64", "int", "int", "*", "*", "int"],
    ["sqlite3_total_changes64", "i64", ["sqlite3*"]],
    ["sqlite3_update_hook", "*", [
      "sqlite3*",
      new wasm.xWrap.FuncPtrAdapter({
        name: 'sqlite3_update_hook',
        signature: "v(iippj)",
        contextKey: (argv)=>argv[0/* sqlite3* */],
        callProxy: (callback)=>{
          return (p,op,z0,z1,rowid)=>{
            callback(p, op, wasm.cstrToJs(z0), wasm.cstrToJs(z1), rowid);
          };
        }
      }),
      "*"
    ]],
    ["sqlite3_uri_int64", "i64", ["sqlite3_filename", "string", "i64"]],
    ["sqlite3_value_int64","i64", "sqlite3_value*"],
    ["sqlite3_vtab_collation","string","sqlite3_index_info*","int"],
    ["sqlite3_vtab_distinct","int", "sqlite3_index_info*"],
    ["sqlite3_vtab_in","int", "sqlite3_index_info*", "int", "int"],
    ["sqlite3_vtab_in_first", "int", "sqlite3_value*", "**"],
    ["sqlite3_vtab_in_next", "int", "sqlite3_value*", "**"],
    /*["sqlite3_vtab_config" is variadic and requires a hand-written
      proxy.] */
    ["sqlite3_vtab_nochange","int", "sqlite3_context*"],
    ["sqlite3_vtab_on_conflict","int", "sqlite3*"],
    ["sqlite3_vtab_rhs_value","int", "sqlite3_index_info*", "int", "**"]
  ];

  // Add session/changeset APIs...
  if(wasm.bigIntEnabled && !!wasm.exports.sqlite3changegroup_add){
    /* ACHTUNG: 2022-12-23: the session/changeset API bindings are
       COMPLETELY UNTESTED. */
    /**
       FuncPtrAdapter options for session-related callbacks with the
       native signature "i(ps)". This proxy converts the 2nd argument
       from a C string to a JS string before passing the arguments on
       to the client-provided JS callback.
    */
    const __ipsProxy = {
      signature: 'i(ps)',
      callProxy:(callback)=>{
        return (p,s)=>{
          try{return callback(p, wasm.cstrToJs(s)) | 0}
          catch(e){return e.resultCode || capi.SQLITE_ERROR}
        }
      }
    };

    wasm.bindingSignatures.int64.push(...[
      ['sqlite3changegroup_add', 'int', ['sqlite3_changegroup*', 'int', 'void*']],
      ['sqlite3changegroup_add_strm', 'int', [
        'sqlite3_changegroup*',
        new wasm.xWrap.FuncPtrAdapter({
          name: 'xInput', signature: 'i(ppp)', bindScope: 'transient'
        }),
        'void*'
      ]],
      ['sqlite3changegroup_delete', undefined, ['sqlite3_changegroup*']],
      ['sqlite3changegroup_new', 'int', ['**']],
      ['sqlite3changegroup_output', 'int', ['sqlite3_changegroup*', 'int*', '**']],
      ['sqlite3changegroup_output_strm', 'int', [
        'sqlite3_changegroup*',
        new wasm.xWrap.FuncPtrAdapter({
          name: 'xOutput', signature: 'i(ppi)', bindScope: 'transient'
        }),
        'void*'
      ]],
      ['sqlite3changeset_apply', 'int', [
        'sqlite3*', 'int', 'void*',
        new wasm.xWrap.FuncPtrAdapter({
          name: 'xFilter', bindScope: 'transient', ...__ipsProxy
        }),
        new wasm.xWrap.FuncPtrAdapter({
          name: 'xConflict', signature: 'i(pip)', bindScope: 'transient'
        }),
        'void*'
      ]],
      ['sqlite3changeset_apply_strm', 'int', [
        'sqlite3*',
        new wasm.xWrap.FuncPtrAdapter({
          name: 'xInput', signature: 'i(ppp)', bindScope: 'transient'
        }),
        'void*',
        new wasm.xWrap.FuncPtrAdapter({
          name: 'xFilter', bindScope: 'transient', ...__ipsProxy
        }),
        new wasm.xWrap.FuncPtrAdapter({
          name: 'xConflict', signature: 'i(pip)', bindScope: 'transient'
        }),
        'void*'
      ]],
      ['sqlite3changeset_apply_v2', 'int', [
        'sqlite3*', 'int', 'void*',
        new wasm.xWrap.FuncPtrAdapter({
          name: 'xFilter', bindScope: 'transient', ...__ipsProxy
        }),
        new wasm.xWrap.FuncPtrAdapter({
          name: 'xConflict', signature: 'i(pip)', bindScope: 'transient'
        }),
        'void*', '**', 'int*', 'int'

      ]],
      ['sqlite3changeset_apply_v2_strm', 'int', [
        'sqlite3*',
        new wasm.xWrap.FuncPtrAdapter({
          name: 'xInput', signature: 'i(ppp)', bindScope: 'transient'
        }),
        'void*',
        new wasm.xWrap.FuncPtrAdapter({
          name: 'xFilter', bindScope: 'transient', ...__ipsProxy
        }),
        new wasm.xWrap.FuncPtrAdapter({
          name: 'xConflict', signature: 'i(pip)', bindScope: 'transient'
        }),
        'void*', '**', 'int*', 'int'
      ]],
      ['sqlite3changeset_concat', 'int', ['int','void*', 'int', 'void*', 'int*', '**']],
      ['sqlite3changeset_concat_strm', 'int', [
        new wasm.xWrap.FuncPtrAdapter({
          name: 'xInputA', signature: 'i(ppp)', bindScope: 'transient'
        }),
        'void*',
        new wasm.xWrap.FuncPtrAdapter({
          name: 'xInputB', signature: 'i(ppp)', bindScope: 'transient'
        }),
        'void*',
        new wasm.xWrap.FuncPtrAdapter({
          name: 'xOutput', signature: 'i(ppi)', bindScope: 'transient'
        }),
        'void*'
      ]],
      ['sqlite3changeset_conflict', 'int', ['sqlite3_changeset_iter*', 'int', '**']],
      ['sqlite3changeset_finalize', 'int', ['sqlite3_changeset_iter*']],
      ['sqlite3changeset_fk_conflicts', 'int', ['sqlite3_changeset_iter*', 'int*']],
      ['sqlite3changeset_invert', 'int', ['int', 'void*', 'int*', '**']],
      ['sqlite3changeset_invert_strm', 'int', [
        new wasm.xWrap.FuncPtrAdapter({
          name: 'xInput', signature: 'i(ppp)', bindScope: 'transient'
        }),
        'void*',
        new wasm.xWrap.FuncPtrAdapter({
          name: 'xOutput', signature: 'i(ppi)', bindScope: 'transient'
        }),
        'void*'
      ]],
      ['sqlite3changeset_new', 'int', ['sqlite3_changeset_iter*', 'int', '**']],
      ['sqlite3changeset_next', 'int', ['sqlite3_changeset_iter*']],
      ['sqlite3changeset_old', 'int', ['sqlite3_changeset_iter*', 'int', '**']],
      ['sqlite3changeset_op', 'int', [
        'sqlite3_changeset_iter*', '**', 'int*', 'int*','int*'
      ]],
      ['sqlite3changeset_pk', 'int', ['sqlite3_changeset_iter*', '**', 'int*']],
      ['sqlite3changeset_start', 'int', ['**', 'int', '*']],
      ['sqlite3changeset_start_strm', 'int', [
        '**',
        new wasm.xWrap.FuncPtrAdapter({
          name: 'xInput', signature: 'i(ppp)', bindScope: 'transient'
        }),
        'void*'
      ]],
      ['sqlite3changeset_start_v2', 'int', ['**', 'int', '*', 'int']],
      ['sqlite3changeset_start_v2_strm', 'int', [
        '**',
        new wasm.xWrap.FuncPtrAdapter({
          name: 'xInput', signature: 'i(ppp)', bindScope: 'transient'
        }),
        'void*', 'int'
      ]],
      ['sqlite3session_attach', 'int', ['sqlite3_session*', 'string']],
      ['sqlite3session_changeset', 'int', ['sqlite3_session*', 'int*', '**']],
      ['sqlite3session_changeset_size', 'i64', ['sqlite3_session*']],
      ['sqlite3session_changeset_strm', 'int', [
        'sqlite3_session*',
        new wasm.xWrap.FuncPtrAdapter({
          name: 'xOutput', signature: 'i(ppp)', bindScope: 'transient'
        }),
        'void*'
      ]],
      ['sqlite3session_config', 'int', ['int', 'void*']],
      ['sqlite3session_create', 'int', ['sqlite3*', 'string', '**']],
      //sqlite3session_delete() is bound manually
      ['sqlite3session_diff', 'int', ['sqlite3_session*', 'string', 'string', '**']],
      ['sqlite3session_enable', 'int', ['sqlite3_session*', 'int']],
      ['sqlite3session_indirect', 'int', ['sqlite3_session*', 'int']],
      ['sqlite3session_isempty', 'int', ['sqlite3_session*']],
      ['sqlite3session_memory_used', 'i64', ['sqlite3_session*']],
      ['sqlite3session_object_config', 'int', ['sqlite3_session*', 'int', 'void*']],
      ['sqlite3session_patchset', 'int', ['sqlite3_session*', '*', '**']],
      ['sqlite3session_patchset_strm', 'int', [
        'sqlite3_session*',
        new wasm.xWrap.FuncPtrAdapter({
          name: 'xOutput', signature: 'i(ppp)', bindScope: 'transient'
        }),
        'void*'
      ]],
      ['sqlite3session_table_filter', undefined, [
        'sqlite3_session*',
        new wasm.xWrap.FuncPtrAdapter({
          name: 'xFilter', ...__ipsProxy,
          contextKey: (argv,argIndex)=>argv[0/* (sqlite3_session*) */]
        }),
        '*'
      ]]
    ]);
  }/*session/changeset APIs*/

  /**
     Functions which are intended solely for API-internal use by the
     WASM components, not client code. These get installed into
     sqlite3.wasm. Some of them get exposed to clients via variants
     named sqlite3_js_...().
  */
  wasm.bindingSignatures.wasm = [
    ["sqlite3_wasm_db_reset", "int", "sqlite3*"],
    ["sqlite3_wasm_db_vfs", "sqlite3_vfs*", "sqlite3*","string"],
    ["sqlite3_wasm_vfs_create_file", "int",
     "sqlite3_vfs*","string","*", "int"],
    ["sqlite3_wasm_vfs_unlink", "int", "sqlite3_vfs*","string"]
  ];

  /**
     Install JS<->C struct bindings for the non-opaque struct types we
     need... */
  sqlite3.StructBinder = self.Jaccwabyt({
    heap: 0 ? wasm.memory : wasm.heap8u,
    alloc: wasm.alloc,
    dealloc: wasm.dealloc,
    bigIntEnabled: wasm.bigIntEnabled,
    memberPrefix: /* Never change this: this prefix is baked into any
                     amount of code and client-facing docs. */ '$'
  });
  delete self.Jaccwabyt;

  {// wasm.xWrap() bindings...

    /* Convert Arrays and certain TypedArrays to strings for
       'string:flexible'-type arguments */
    const __xString = wasm.xWrap.argAdapter('string');
    wasm.xWrap.argAdapter(
      'string:flexible', (v)=>__xString(util.flexibleString(v))
    );

    /**
       The 'string:static' argument adapter treats its argument as
       either...

       - WASM pointer: assumed to be a long-lived C-string which gets
         returned as-is.

       - Anything else: gets coerced to a JS string for use as a map
         key. If a matching entry is found (as described next), it is
         returned, else wasm.allocCString() is used to create a a new
         string, map its pointer to (''+v) for the remainder of the
         application's life, and returns that pointer value for this
         call and all future calls which are passed a
         string-equivalent argument.

       Use case: sqlite3_bind_pointer() and sqlite3_result_pointer()
       call for "a static string and preferably a string
       literal". This converter is used to ensure that the string
       value seen by those functions is long-lived and behaves as they
       need it to.
    */
    wasm.xWrap.argAdapter(
      'string:static',
      function(v){
        if(wasm.isPtr(v)) return v;
        v = ''+v;
        let rc = this[v];
        return rc || (this[v] = wasm.allocCString(v));
      }.bind(Object.create(null))
    );

    /**
       Add some descriptive xWrap() aliases for '*' intended to (A)
       initially improve readability/correctness of
       wasm.bindingSignatures and (B) provide automatic conversion
       from higher-level representations, e.g. capi.sqlite3_vfs to
       `sqlite3_vfs*` via capi.sqlite3_vfs.pointer.
    */
    const __xArgPtr = wasm.xWrap.argAdapter('*');
    const nilType = function(){}/*a class no value can ever be an instance of*/;
    wasm.xWrap.argAdapter('sqlite3_filename', __xArgPtr)
    ('sqlite3_context*', __xArgPtr)
    ('sqlite3_value*', __xArgPtr)
    ('void*', __xArgPtr)
    ('sqlite3_changegroup*', __xArgPtr)
    ('sqlite3_changeset_iter*', __xArgPtr)
    //('sqlite3_rebaser*', __xArgPtr)
    ('sqlite3_session*', __xArgPtr)
    ('sqlite3_stmt*', (v)=>
      __xArgPtr((v instanceof (sqlite3?.oo1?.Stmt || nilType))
           ? v.pointer : v))
    ('sqlite3*', (v)=>
      __xArgPtr((v instanceof (sqlite3?.oo1?.DB || nilType))
           ? v.pointer : v))
    ('sqlite3_index_info*', (v)=>
      __xArgPtr((v instanceof (capi.sqlite3_index_info || nilType))
           ? v.pointer : v))
    ('sqlite3_module*', (v)=>
      __xArgPtr((v instanceof (capi.sqlite3_module || nilType))
           ? v.pointer : v))
    /**
       `sqlite3_vfs*`:

       - v is-a string: use the result of sqlite3_vfs_find(v) but
         throw if it returns 0.
       - v is-a capi.sqlite3_vfs: use v.pointer.
       - Else return the same as the `'*'` argument conversion.
    */
    ('sqlite3_vfs*', (v)=>{
      if('string'===typeof v){
        /* A NULL sqlite3_vfs pointer will be treated as the default
           VFS in many contexts. We specifically do not want that
           behavior here. */
        return capi.sqlite3_vfs_find(v)
          || sqlite3.SQLite3Error.toss(
            capi.SQLITE_NOTFOUND,
            "Unknown sqlite3_vfs name:", v
          );
      }
      return __xArgPtr((v instanceof (capi.sqlite3_vfs || nilType))
                       ? v.pointer : v);
    });

    const __xRcPtr = wasm.xWrap.resultAdapter('*');
    wasm.xWrap.resultAdapter('sqlite3*', __xRcPtr)
    ('sqlite3_context*', __xRcPtr)
    ('sqlite3_stmt*', __xRcPtr)
    ('sqlite3_value*', __xRcPtr)
    ('sqlite3_vfs*', __xRcPtr)
    ('void*', __xRcPtr);

    /**
       Populate api object with sqlite3_...() by binding the "raw" wasm
       exports into type-converting proxies using wasm.xWrap().
    */
    for(const e of wasm.bindingSignatures){
      capi[e[0]] = wasm.xWrap.apply(null, e);
    }
    for(const e of wasm.bindingSignatures.wasm){
      wasm[e[0]] = wasm.xWrap.apply(null, e);
    }

    /* For C API functions which cannot work properly unless
       wasm.bigIntEnabled is true, install a bogus impl which throws
       if called when bigIntEnabled is false. The alternative would be
       to elide these functions altogether, which seems likely to
       cause more confusion. */
    const fI64Disabled = function(fname){
      return ()=>toss(fname+"() is unavailable due to lack",
                      "of BigInt support in this build.");
    };
    for(const e of wasm.bindingSignatures.int64){
      capi[e[0]] = wasm.bigIntEnabled
        ? wasm.xWrap.apply(null, e)
        : fI64Disabled(e[0]);
    }

    /* There's no need to expose bindingSignatures to clients,
       implicitly making it part of the public interface. */
    delete wasm.bindingSignatures;

    if(wasm.exports.sqlite3_wasm_db_error){
      const __db_err = wasm.xWrap(
        'sqlite3_wasm_db_error', 'int', 'sqlite3*', 'int', 'string'
      );
      /**
         Sets the given db's error state. Accepts:

         - (sqlite3*, int code, string msg)
         - (sqlite3*, Error e [,string msg = ''+e])

         If passed a WasmAllocError, the message is ignored and the
         result code is SQLITE_NOMEM. If passed any other Error type,
         the result code defaults to SQLITE_ERROR unless the Error
         object has a resultCode property, in which case that is used
         (e.g. SQLite3Error has that). If passed a non-WasmAllocError
         exception, the message string defaults to theError.message.

         Returns the resulting code. Pass (pDb,0,0) to clear the error
         state.
       */
      util.sqlite3_wasm_db_error = function(pDb, resultCode, message){
        if(resultCode instanceof sqlite3.WasmAllocError){
          resultCode = capi.SQLITE_NOMEM;
          message = 0 /*avoid allocating message string*/;
        }else if(resultCode instanceof Error){
          message = message || ''+resultCode;
          resultCode = (resultCode.resultCode || capi.SQLITE_ERROR);
        }
        return pDb ? __db_err(pDb, resultCode, message) : resultCode;
      };
    }else{
      util.sqlite3_wasm_db_error = function(pDb,errCode,msg){
        console.warn("sqlite3_wasm_db_error() is not exported.",arguments);
        return errCode;
      };
    }
  }/*xWrap() bindings*/

  {/* Import C-level constants and structs... */
    const cJson = wasm.xCall('sqlite3_wasm_enum_json');
    if(!cJson){
      toss("Maintenance required: increase sqlite3_wasm_enum_json()'s",
           "static buffer size!");
    }
    //console.debug('wasm.ctype length =',wasm.cstrlen(cJson));
    wasm.ctype = JSON.parse(wasm.cstrToJs(cJson));
    // Groups of SQLITE_xyz macros...
    const defineGroups = ['access', 'authorizer',
                          'blobFinalizers', 'changeset',
                          'config', 'dataTypes',
                          'dbConfig', 'dbStatus',
                          'encodings', 'fcntl', 'flock', 'ioCap',
                          'limits', 'openFlags',
                          'prepareFlags', 'resultCodes',
                          'sqlite3Status',
                          'stmtStatus', 'syncFlags',
                          'trace', 'txnState', 'udfFlags',
                          'version' ];
    if(wasm.bigIntEnabled){
      defineGroups.push('serialize', 'session', 'vtab');
    }
    for(const t of defineGroups){
      for(const e of Object.entries(wasm.ctype[t])){
        // ^^^ [k,v] there triggers a buggy code transformation via
        // one of the Emscripten-driven optimizers.
        capi[e[0]] = e[1];
      }
    }
    if(!wasm.functionEntry(capi.SQLITE_WASM_DEALLOC)){
      toss("Internal error: cannot resolve exported function",
           "entry SQLITE_WASM_DEALLOC (=="+capi.SQLITE_WASM_DEALLOC+").");
    }
    const __rcMap = Object.create(null);
    for(const t of ['resultCodes']){
      for(const e of Object.entries(wasm.ctype[t])){
        __rcMap[e[1]] = e[0];
      }
    }
    /**
       For the given integer, returns the SQLITE_xxx result code as a
       string, or undefined if no such mapping is found.
    */
    capi.sqlite3_js_rc_str = (rc)=>__rcMap[rc];
    /* Bind all registered C-side structs... */
    const notThese = Object.assign(Object.create(null),{
      // For each struct to NOT register, map its name to true:
      WasmTestStruct: true,
      /* We unregister the kvvfs VFS from Worker threads below. */
      sqlite3_kvvfs_methods: !util.isUIThread(),
      /* sqlite3_index_info and friends require int64: */
      sqlite3_index_info: !wasm.bigIntEnabled,
      sqlite3_index_constraint: !wasm.bigIntEnabled,
      sqlite3_index_orderby: !wasm.bigIntEnabled,
      sqlite3_index_constraint_usage: !wasm.bigIntEnabled
    });
    for(const s of wasm.ctype.structs){
      if(!notThese[s.name]){
        capi[s.name] = sqlite3.StructBinder(s);
      }
    }
    if(capi.sqlite3_index_info){
      /* Move these inner structs into sqlite3_index_info.  Binding
      ** them to WASM requires that we create global-scope structs to
      ** model them with, but those are no longer needed after we've
      ** passed them to StructBinder. */
      for(const k of ['sqlite3_index_constraint',
                      'sqlite3_index_orderby',
                      'sqlite3_index_constraint_usage']){
        capi.sqlite3_index_info[k] = capi[k];
        delete capi[k];
      }
      capi.sqlite3_vtab_config = wasm.xWrap(
        'sqlite3_wasm_vtab_config','int',[
          'sqlite3*', 'int', 'int']
      );
    }/* end vtab-related setup */
  }/*end C constant and struct imports*/

  /**
     Internal helper to assist in validating call argument counts in
     the hand-written sqlite3_xyz() wrappers. We do this only for
     consistency with non-special-case wrappings.
  */
  const __dbArgcMismatch = (pDb,f,n)=>{
    return sqlite3.util.sqlite3_wasm_db_error(pDb, capi.SQLITE_MISUSE,
                                              f+"() requires "+n+" argument"+
                                              (1===n?"":'s')+".");
  };

  /** Code duplication reducer for functions which take an encoding
      argument and require SQLITE_UTF8.  Sets the db error code to
      SQLITE_FORMAT and returns that code. */
  const __errEncoding = (pDb)=>{
    return util.sqlite3_wasm_db_error(
      pDb, capi.SQLITE_FORMAT, "SQLITE_UTF8 is the only supported encoding."
    );
  };

  /**
     __dbCleanupMap is infrastructure for recording registration of
     UDFs and collations so that sqlite3_close_v2() can clean up any
     automated JS-to-WASM function conversions installed by those.
  */
  const __argPDb = (pDb)=>wasm.xWrap.argAdapter('sqlite3*')(pDb);
  const __argStr = (str)=>wasm.isPtr(str) ? wasm.cstrToJs(str) : str;
  const __dbCleanupMap = function(
    pDb, mode/*0=remove, >0=create if needed, <0=do not create if missing*/
  ){
    pDb = __argPDb(pDb);
    let m = this.dbMap.get(pDb);
    if(!mode){
      this.dbMap.delete(pDb);
      return m;
    }else if(!m && mode>0){
      this.dbMap.set(pDb, (m = Object.create(null)));
    }
    return m;
  }.bind(Object.assign(Object.create(null),{
    dbMap: new Map
  }));

  __dbCleanupMap.addCollation = function(pDb, name){
    const m = __dbCleanupMap(pDb, 1);
    if(!m.collation) m.collation = new Set;
    m.collation.add(__argStr(name).toLowerCase());
  };

  __dbCleanupMap._addUDF = function(pDb, name, arity, map){
    /* Map UDF name to a Set of arity values */
    name = __argStr(name).toLowerCase();
    let u = map.get(name);
    if(!u) map.set(name, (u = new Set));
    u.add((arity<0) ? -1 : arity);
  };

  __dbCleanupMap.addFunction = function(pDb, name, arity){
    const m = __dbCleanupMap(pDb, 1);
    if(!m.udf) m.udf = new Map;
    this._addUDF(pDb, name, arity, m.udf);
  };

  __dbCleanupMap.addWindowFunc = function(pDb, name, arity){
    const m = __dbCleanupMap(pDb, 1);
    if(!m.wudf) m.wudf = new Map;
    this._addUDF(pDb, name, arity, m.wudf);
  };

  /**
     Intended to be called _only_ from sqlite3_close_v2(),
     passed its non-0 db argument.

     This function frees up certain automatically-installed WASM
     function bindings which were installed on behalf of the given db,
     as those may otherwise leak.

     Notable caveat: this is only ever run via
     sqlite3.capi.sqlite3_close_v2(). If a client, for whatever
     reason, uses sqlite3.wasm.exports.sqlite3_close_v2() (the
     function directly exported from WASM), this cleanup will not
     happen.

     This is not a silver bullet for avoiding automation-related
     leaks but represents "an honest effort."

     The issue being addressed here is covered at:

     https://sqlite.org/wasm/doc/trunk/api-c-style.md#convert-func-ptr
  */
  __dbCleanupMap.cleanup = function(pDb){
    pDb = __argPDb(pDb);
    //wasm.xWrap.FuncPtrAdapter.debugFuncInstall = false;
    /**
       Installing NULL functions in the C API will remove those
       bindings. The FuncPtrAdapter which sits between us and the C
       API will also treat that as an opportunity to
       wasm.uninstallFunction() any WASM function bindings it has
       installed for pDb.
    */
    const closeArgs = [pDb];
    for(const name of [
      'sqlite3_busy_handler',
      'sqlite3_commit_hook',
      'sqlite3_preupdate_hook',
      'sqlite3_progress_handler',
      'sqlite3_rollback_hook',
      'sqlite3_set_authorizer',
      'sqlite3_trace_v2',
      'sqlite3_update_hook'
    ]) {
      const x = wasm.exports[name];
      closeArgs.length = x.length/*==argument count*/
      /* recall that undefined entries translate to 0 when passed to
         WASM. */;
      try{ capi[name](...closeArgs) }
      catch(e){
        console.warn("close-time call of",name+"(",closeArgs,") threw:",e);
      }
    }
    const m = __dbCleanupMap(pDb, 0);
    if(!m) return;
    if(m.collation){
      for(const name of m.collation){
        try{
          capi.sqlite3_create_collation_v2(
            pDb, name, capi.SQLITE_UTF8, 0, 0, 0
          );
        }catch(e){
          /*ignored*/
        }
      }
      delete m.collation;
    }
    let i;
    for(i = 0; i < 2; ++i){ /* Clean up UDFs... */
      const fmap = i ? m.wudf : m.udf;
      if(!fmap) continue;
      const func = i
            ? capi.sqlite3_create_window_function
            : capi.sqlite3_create_function_v2;
      for(const e of fmap){
        const name = e[0], arities = e[1];
        const fargs = [pDb, name, 0/*arity*/, capi.SQLITE_UTF8, 0, 0, 0, 0, 0];
        if(i) fargs.push(0);
        for(const arity of arities){
          try{ fargs[2] = arity; func.apply(null, fargs); }
          catch(e){/*ignored*/}
        }
        arities.clear();
      }
      fmap.clear();
    }
    delete m.udf;
    delete m.wudf;
  }/*__dbCleanupMap.cleanup()*/;

  {/* Binding of sqlite3_close_v2() */
    const __sqlite3CloseV2 = wasm.xWrap("sqlite3_close_v2", "int", "sqlite3*");
    capi.sqlite3_close_v2 = function(pDb){
      if(1!==arguments.length) return __dbArgcMismatch(pDb, 'sqlite3_close_v2', 1);
      if(pDb){
        try{__dbCleanupMap.cleanup(pDb)} catch(e){/*ignored*/}
      }
      return __sqlite3CloseV2(pDb);
    };
  }/*sqlite3_close_v2()*/

  if(capi.sqlite3session_table_filter){
    const __sqlite3SessionDelete = wasm.xWrap(
      'sqlite3session_delete', undefined, ['sqlite3_session*']
    );
    capi.sqlite3session_delete = function(pSession){
      if(1!==arguments.length){
        return __dbArgcMismatch(pDb, 'sqlite3session_delete', 1);
        /* Yes, we're returning a value from a void function. That seems
           like the lesser evil compared to not maintaining arg-count
           consistency as we do with other similar bindings. */
      }
      else if(pSession){
        //wasm.xWrap.FuncPtrAdapter.debugFuncInstall = true;
        capi.sqlite3session_table_filter(pSession, 0, 0);
      }
      __sqlite3SessionDelete(pSession);
    };
  }

  {/* Bindings for sqlite3_create_collation[_v2]() */
    // contextKey() impl for wasm.xWrap.FuncPtrAdapter
    const contextKey = (argv,argIndex)=>{
      return 'argv['+argIndex+']:'+argv[0/* sqlite3* */]+
        ':'+wasm.cstrToJs(argv[1/* collation name */]).toLowerCase()
    };
    const __sqlite3CreateCollationV2 = wasm.xWrap(
      'sqlite3_create_collation_v2', 'int', [
        'sqlite3*', 'string', 'int', '*',
        new wasm.xWrap.FuncPtrAdapter({
          /* int(*xCompare)(void*,int,const void*,int,const void*) */
          name: 'xCompare', signature: 'i(pipip)', contextKey
        }),
        new wasm.xWrap.FuncPtrAdapter({
          /* void(*xDestroy(void*) */
          name: 'xDestroy', signature: 'v(p)', contextKey
        })
      ]
    );

    /**
       Works exactly like C's sqlite3_create_collation_v2() except that:

       1) It returns capi.SQLITE_FORMAT if the 3rd argument contains
          any encoding-related value other than capi.SQLITE_UTF8.  No
          other encodings are supported. As a special case, if the
          bottom 4 bits of that argument are 0, SQLITE_UTF8 is
          assumed.

       2) It accepts JS functions for its function-pointer arguments,
          for which it will install WASM-bound proxies. The bindings
          are "permanent," in that they will stay in the WASM environment
          until it shuts down unless the client calls this again with the
          same collation name and a value of 0 or null for the
          the function pointer(s).

       For consistency with the C API, it requires the same number of
       arguments. It returns capi.SQLITE_MISUSE if passed any other
       argument count.

       Returns 0 on success, non-0 on error, in which case the error
       state of pDb (of type `sqlite3*` or argument-convertible to it)
       may contain more information.
    */
    capi.sqlite3_create_collation_v2 = function(pDb,zName,eTextRep,pArg,xCompare,xDestroy){
      if(6!==arguments.length) return __dbArgcMismatch(pDb, 'sqlite3_create_collation_v2', 6);
      else if( 0 === (eTextRep & 0xf) ){
        eTextRep |= capi.SQLITE_UTF8;
      }else if( capi.SQLITE_UTF8 !== (eTextRep & 0xf) ){
        return __errEncoding(pDb);
      }
      try{
        const rc = __sqlite3CreateCollationV2(pDb, zName, eTextRep, pArg, xCompare, xDestroy);
        if(0===rc && xCompare instanceof Function){
          __dbCleanupMap.addCollation(pDb, zName);
        }
        return rc;
      }catch(e){
        return util.sqlite3_wasm_db_error(pDb, e);
      }
    };

    capi.sqlite3_create_collation = (pDb,zName,eTextRep,pArg,xCompare)=>{
      return (5===arguments.length)
        ? capi.sqlite3_create_collation_v2(pDb,zName,eTextRep,pArg,xCompare,0)
        : __dbArgcMismatch(pDb, 'sqlite3_create_collation', 5);
    };

  }/*sqlite3_create_collation() and friends*/

  {/* Special-case handling of sqlite3_create_function_v2()
      and sqlite3_create_window_function(). */
    /** FuncPtrAdapter for contextKey() for sqlite3_create_function()
        and friends. */
    const contextKey = function(argv,argIndex){
      return (
        argv[0/* sqlite3* */]
          +':'+(argv[2/*number of UDF args*/] < 0 ? -1 : argv[2])
          +':'+argIndex/*distinct for each xAbc callback type*/
          +':'+wasm.cstrToJs(argv[1]).toLowerCase()
      )
    };

    /**
       JS proxies for the various sqlite3_create[_window]_function()
       callbacks, structured in a form usable by wasm.xWrap.FuncPtrAdapter.
    */
    const __cfProxy = Object.assign(Object.create(null), {
      xInverseAndStep: {
        signature:'v(pip)', contextKey,
        callProxy: (callback)=>{
          return (pCtx, argc, pArgv)=>{
            try{ callback(pCtx, ...capi.sqlite3_values_to_js(argc, pArgv)) }
            catch(e){ capi.sqlite3_result_error_js(pCtx, e) }
          };
        }
      },
      xFinalAndValue: {
        signature:'v(p)', contextKey,
        callProxy: (callback)=>{
          return (pCtx)=>{
            try{ capi.sqlite3_result_js(pCtx, callback(pCtx)) }
            catch(e){ capi.sqlite3_result_error_js(pCtx, e) }
          };
        }
      },
      xFunc: {
        signature:'v(pip)', contextKey,
        callProxy: (callback)=>{
          return (pCtx, argc, pArgv)=>{
            try{
              capi.sqlite3_result_js(
                pCtx,
                callback(pCtx, ...capi.sqlite3_values_to_js(argc, pArgv))
              );
            }catch(e){
              //console.error('xFunc() caught:',e);
              capi.sqlite3_result_error_js(pCtx, e);
            }
          };
        }
      },
      xDestroy: {
        signature:'v(p)', contextKey,
        //Arguable: a well-behaved destructor doesn't require a proxy.
        callProxy: (callback)=>{
          return (pVoid)=>{
            try{ callback(pVoid) }
            catch(e){ console.error("UDF xDestroy method threw:",e) }
          };
        }
      }
    })/*__cfProxy*/;

    const __sqlite3CreateFunction = wasm.xWrap(
      "sqlite3_create_function_v2", "int", [
        "sqlite3*", "string"/*funcName*/, "int"/*nArg*/,
        "int"/*eTextRep*/, "*"/*pApp*/,
        new wasm.xWrap.FuncPtrAdapter({name: 'xFunc', ...__cfProxy.xFunc}),
        new wasm.xWrap.FuncPtrAdapter({name: 'xStep', ...__cfProxy.xInverseAndStep}),
        new wasm.xWrap.FuncPtrAdapter({name: 'xFinal', ...__cfProxy.xFinalAndValue}),
        new wasm.xWrap.FuncPtrAdapter({name: 'xDestroy', ...__cfProxy.xDestroy})
      ]
    );

    const __sqlite3CreateWindowFunction = wasm.xWrap(
      "sqlite3_create_window_function", "int", [
        "sqlite3*", "string"/*funcName*/, "int"/*nArg*/,
        "int"/*eTextRep*/, "*"/*pApp*/,
        new wasm.xWrap.FuncPtrAdapter({name: 'xStep', ...__cfProxy.xInverseAndStep}),
        new wasm.xWrap.FuncPtrAdapter({name: 'xFinal', ...__cfProxy.xFinalAndValue}),
        new wasm.xWrap.FuncPtrAdapter({name: 'xValue', ...__cfProxy.xFinalAndValue}),
        new wasm.xWrap.FuncPtrAdapter({name: 'xInverse', ...__cfProxy.xInverseAndStep}),
        new wasm.xWrap.FuncPtrAdapter({name: 'xDestroy', ...__cfProxy.xDestroy})
      ]
    );

    /* Documented in the api object's initializer. */
    capi.sqlite3_create_function_v2 = function f(
      pDb, funcName, nArg, eTextRep, pApp,
      xFunc,   //void (*xFunc)(sqlite3_context*,int,sqlite3_value**)
      xStep,   //void (*xStep)(sqlite3_context*,int,sqlite3_value**)
      xFinal,  //void (*xFinal)(sqlite3_context*)
      xDestroy //void (*xDestroy)(void*)
    ){
      if( f.length!==arguments.length ){
        return __dbArgcMismatch(pDb,"sqlite3_create_function_v2",f.length);
      }else if( 0 === (eTextRep & 0xf) ){
        eTextRep |= capi.SQLITE_UTF8;
      }else if( capi.SQLITE_UTF8 !== (eTextRep & 0xf) ){
        return __errEncoding(pDb);
      }
      try{
        const rc = __sqlite3CreateFunction(pDb, funcName, nArg, eTextRep,
                                           pApp, xFunc, xStep, xFinal, xDestroy);
        if(0===rc && (xFunc instanceof Function
                      || xStep instanceof Function
                      || xFinal instanceof Function
                      || xDestroy instanceof Function)){
          __dbCleanupMap.addFunction(pDb, funcName, nArg);
        }
        return rc;
      }catch(e){
        console.error("sqlite3_create_function_v2() setup threw:",e);
        return util.sqlite3_wasm_db_error(pDb, e, "Creation of UDF threw: "+e);
      }
    };

    /* Documented in the api object's initializer. */
    capi.sqlite3_create_function = function f(
      pDb, funcName, nArg, eTextRep, pApp,
      xFunc, xStep, xFinal
    ){
      return (f.length===arguments.length)
        ? capi.sqlite3_create_function_v2(pDb, funcName, nArg, eTextRep,
                                          pApp, xFunc, xStep, xFinal, 0)
        : __dbArgcMismatch(pDb,"sqlite3_create_function",f.length);
    };

    /* Documented in the api object's initializer. */
    capi.sqlite3_create_window_function = function f(
      pDb, funcName, nArg, eTextRep, pApp,
      xStep,   //void (*xStep)(sqlite3_context*,int,sqlite3_value**)
      xFinal,  //void (*xFinal)(sqlite3_context*)
      xValue,  //void (*xValue)(sqlite3_context*)
      xInverse,//void (*xInverse)(sqlite3_context*,int,sqlite3_value**)
      xDestroy //void (*xDestroy)(void*)
    ){
      if( f.length!==arguments.length ){
        return __dbArgcMismatch(pDb,"sqlite3_create_window_function",f.length);
      }else if( 0 === (eTextRep & 0xf) ){
        eTextRep |= capi.SQLITE_UTF8;
      }else if( capi.SQLITE_UTF8 !== (eTextRep & 0xf) ){
        return __errEncoding(pDb);
      }
      try{
        const rc = __sqlite3CreateWindowFunction(pDb, funcName, nArg, eTextRep,
                                                 pApp, xStep, xFinal, xValue,
                                                 xInverse, xDestroy);
        if(0===rc && (xStep instanceof Function
                      || xFinal instanceof Function
                      || xValue instanceof Function
                      || xInverse instanceof Function
                      || xDestroy instanceof Function)){
          __dbCleanupMap.addWindowFunc(pDb, funcName, nArg);
        }
        return rc;
      }catch(e){
        console.error("sqlite3_create_window_function() setup threw:",e);
        return util.sqlite3_wasm_db_error(pDb, e, "Creation of UDF threw: "+e);
      }
    };
    /**
       A _deprecated_ alias for capi.sqlite3_result_js() which
       predates the addition of that function in the public API.
    */
    capi.sqlite3_create_function_v2.udfSetResult =
      capi.sqlite3_create_function.udfSetResult =
      capi.sqlite3_create_window_function.udfSetResult = capi.sqlite3_result_js;

    /**
       A _deprecated_ alias for capi.sqlite3_values_to_js() which
       predates the addition of that function in the public API.
    */
    capi.sqlite3_create_function_v2.udfConvertArgs =
      capi.sqlite3_create_function.udfConvertArgs =
      capi.sqlite3_create_window_function.udfConvertArgs = capi.sqlite3_values_to_js;

    /**
       A _deprecated_ alias for capi.sqlite3_result_error_js() which
       predates the addition of that function in the public API.
    */
    capi.sqlite3_create_function_v2.udfSetError =
      capi.sqlite3_create_function.udfSetError =
      capi.sqlite3_create_window_function.udfSetError = capi.sqlite3_result_error_js;

  }/*sqlite3_create_function_v2() and sqlite3_create_window_function() proxies*/;

  {/* Special-case handling of sqlite3_prepare_v2() and
      sqlite3_prepare_v3() */

    /**
       Helper for string:flexible conversions which require a
       byte-length counterpart argument. Passed a value and its
       ostensible length, this function returns [V,N], where V is
       either v or a transformed copy of v and N is either n, -1, or
       the byte length of v (if it's a byte array or ArrayBuffer).
    */
    const __flexiString = (v,n)=>{
      if('string'===typeof v){
        n = -1;
      }else if(util.isSQLableTypedArray(v)){
        n = v.byteLength;
        v = util.typedArrayToString(
          (v instanceof ArrayBuffer) ? new Uint8Array(v) : v
        );
      }else if(Array.isArray(v)){
        v = v.join("");
        n = -1;
      }
      return [v, n];
    };

    /**
       Scope-local holder of the two impls of sqlite3_prepare_v2/v3().
    */
    const __prepare = {
      /**
         This binding expects a JS string as its 2nd argument and
         null as its final argument. In order to compile multiple
         statements from a single string, the "full" impl (see
         below) must be used.
      */
      basic: wasm.xWrap('sqlite3_prepare_v3',
                        "int", ["sqlite3*", "string",
                                "int"/*ignored for this impl!*/,
                                "int", "**",
                                "**"/*MUST be 0 or null or undefined!*/]),
      /**
         Impl which requires that the 2nd argument be a pointer
         to the SQL string, instead of being converted to a
         string. This variant is necessary for cases where we
         require a non-NULL value for the final argument
         (exec()'ing multiple statements from one input
         string). For simpler cases, where only the first
         statement in the SQL string is required, the wrapper
         named sqlite3_prepare_v2() is sufficient and easier to
         use because it doesn't require dealing with pointers.
      */
      full: wasm.xWrap('sqlite3_prepare_v3',
                       "int", ["sqlite3*", "*", "int", "int",
                               "**", "**"])
    };

    /* Documented in the capi object's initializer. */
    capi.sqlite3_prepare_v3 = function f(pDb, sql, sqlLen, prepFlags, ppStmt, pzTail){
      if(f.length!==arguments.length){
        return __dbArgcMismatch(pDb,"sqlite3_prepare_v3",f.length);
      }
      const [xSql, xSqlLen] = __flexiString(sql, sqlLen);
      switch(typeof xSql){
          case 'string': return __prepare.basic(pDb, xSql, xSqlLen, prepFlags, ppStmt, null);
          case 'number': return __prepare.full(pDb, xSql, xSqlLen, prepFlags, ppStmt, pzTail);
          default:
            return util.sqlite3_wasm_db_error(
              pDb, capi.SQLITE_MISUSE,
              "Invalid SQL argument type for sqlite3_prepare_v2/v3()."
            );
      }
    };

    /* Documented in the capi object's initializer. */
    capi.sqlite3_prepare_v2 = function f(pDb, sql, sqlLen, ppStmt, pzTail){
      return (f.length===arguments.length)
        ? capi.sqlite3_prepare_v3(pDb, sql, sqlLen, 0, ppStmt, pzTail)
        : __dbArgcMismatch(pDb,"sqlite3_prepare_v2",f.length);
    };

  }/*sqlite3_prepare_v2/v3()*/

  {/*sqlite3_bind_text/blob()*/
    const __bindText = wasm.xWrap("sqlite3_bind_text", "int", [
      "sqlite3_stmt*", "int", "string", "int", "*"
    ]);
    const __bindBlob = wasm.xWrap("sqlite3_bind_blob", "int", [
      "sqlite3_stmt*", "int", "*", "int", "*"
    ]);

    /** Documented in the capi object's initializer. */
    capi.sqlite3_bind_text = function f(pStmt, iCol, text, nText, xDestroy){
      if(f.length!==arguments.length){
        return __dbArgcMismatch(capi.sqlite3_db_handle(pStmt),
                                "sqlite3_bind_text", f.length);
      }else if(wasm.isPtr(text) || null===text){
        return __bindText(pStmt, iCol, text, nText, xDestroy);
      }else if(text instanceof ArrayBuffer){
        text = new Uint8Array(text);
      }else if(Array.isArray(pMem)){
        text = pMem.join('');
      }
      let p, n;
      try{
        if(util.isSQLableTypedArray(text)){
          p = wasm.allocFromTypedArray(text);
          n = text.byteLength;
        }else if('string'===typeof text){
          [p, n] = wasm.allocCString(text);
        }else{
          return util.sqlite3_wasm_db_error(
            capi.sqlite3_db_handle(pStmt), capi.SQLITE_MISUSE,
            "Invalid 3rd argument type for sqlite3_bind_text()."
          );
        }
        return __bindText(pStmt, iCol, p, n, capi.SQLITE_WASM_DEALLOC);
      }catch(e){
        wasm.dealloc(p);
        return util.sqlite3_wasm_db_error(
          capi.sqlite3_db_handle(pStmt), e
        );
      }
    }/*sqlite3_bind_text()*/;

    /** Documented in the capi object's initializer. */
    capi.sqlite3_bind_blob = function f(pStmt, iCol, pMem, nMem, xDestroy){
      if(f.length!==arguments.length){
        return __dbArgcMismatch(capi.sqlite3_db_handle(pStmt),
                                "sqlite3_bind_blob", f.length);
      }else if(wasm.isPtr(pMem) || null===pMem){
        return __bindBlob(pStmt, iCol, pMem, nMem, xDestroy);
      }else if(pMem instanceof ArrayBuffer){
        pMem = new Uint8Array(pMem);
      }else if(Array.isArray(pMem)){
        pMem = pMem.join('');
      }
      let p, n;
      try{
        if(util.isBindableTypedArray(pMem)){
          p = wasm.allocFromTypedArray(pMem);
          n = nMem>=0 ? nMem : pMem.byteLength;
        }else if('string'===typeof pMem){
          [p, n] = wasm.allocCString(pMem);
        }else{
          return util.sqlite3_wasm_db_error(
            capi.sqlite3_db_handle(pStmt), capi.SQLITE_MISUSE,
            "Invalid 3rd argument type for sqlite3_bind_blob()."
          );
        }
        return __bindBlob(pStmt, iCol, p, n, capi.SQLITE_WASM_DEALLOC);
      }catch(e){
        wasm.dealloc(p);
        return util.sqlite3_wasm_db_error(
          capi.sqlite3_db_handle(pStmt), e
        );
      }
    }/*sqlite3_bind_blob()*/;

  }/*sqlite3_bind_text/blob()*/

  {/* sqlite3_config() */
    /**
       Wraps a small subset of the C API's sqlite3_config() options.
       Unsupported options trigger the return of capi.SQLITE_NOTFOUND.
       Passing fewer than 2 arguments triggers return of
       capi.SQLITE_MISUSE.
    */
    capi.sqlite3_config = function(op, ...args){
      if(arguments.length<2) return capi.SQLITE_MISUSE;
      switch(op){
          case capi.SQLITE_CONFIG_COVERING_INDEX_SCAN: // 20  /* int */
          case capi.SQLITE_CONFIG_MEMSTATUS:// 9  /* boolean */
          case capi.SQLITE_CONFIG_SMALL_MALLOC: // 27  /* boolean */
          case capi.SQLITE_CONFIG_SORTERREF_SIZE: // 28  /* int nByte */
          case capi.SQLITE_CONFIG_STMTJRNL_SPILL: // 26  /* int nByte */
          case capi.SQLITE_CONFIG_URI:// 17  /* int */
            return wasm.exports.sqlite3_wasm_config_i(op, args[0]);
          case capi.SQLITE_CONFIG_LOOKASIDE: // 13  /* int int */
            return wasm.exports.sqlite3_wasm_config_ii(op, args[0], args[1]);
          case capi.SQLITE_CONFIG_MEMDB_MAXSIZE: // 29  /* sqlite3_int64 */
            return wasm.exports.sqlite3_wasm_config_j(op, args[0]);
          case capi.SQLITE_CONFIG_GETMALLOC: // 5 /* sqlite3_mem_methods* */
          case capi.SQLITE_CONFIG_GETMUTEX: // 11  /* sqlite3_mutex_methods* */
          case capi.SQLITE_CONFIG_GETPCACHE2: // 19  /* sqlite3_pcache_methods2* */
          case capi.SQLITE_CONFIG_GETPCACHE: // 15  /* no-op */
          case capi.SQLITE_CONFIG_HEAP: // 8  /* void*, int nByte, int min */
          case capi.SQLITE_CONFIG_LOG: // 16  /* xFunc, void* */
          case capi.SQLITE_CONFIG_MALLOC:// 4  /* sqlite3_mem_methods* */
          case capi.SQLITE_CONFIG_MMAP_SIZE: // 22  /* sqlite3_int64, sqlite3_int64 */
          case capi.SQLITE_CONFIG_MULTITHREAD: // 2 /* nil */
          case capi.SQLITE_CONFIG_MUTEX: // 10  /* sqlite3_mutex_methods* */
          case capi.SQLITE_CONFIG_PAGECACHE: // 7  /* void*, int sz, int N */
          case capi.SQLITE_CONFIG_PCACHE2: // 18  /* sqlite3_pcache_methods2* */
          case capi.SQLITE_CONFIG_PCACHE: // 14  /* no-op */
          case capi.SQLITE_CONFIG_PCACHE_HDRSZ: // 24  /* int *psz */
          case capi.SQLITE_CONFIG_PMASZ: // 25  /* unsigned int szPma */
          case capi.SQLITE_CONFIG_SERIALIZED: // 3 /* nil */
          case capi.SQLITE_CONFIG_SINGLETHREAD: // 1 /* nil */:
          case capi.SQLITE_CONFIG_SQLLOG: // 21  /* xSqllog, void* */
          case capi.SQLITE_CONFIG_WIN32_HEAPSIZE: // 23  /* int nByte */
          default:
            return capi.SQLITE_NOTFOUND;
      }
    };
  }/* sqlite3_config() */

  {/*auto-extension bindings.*/
    const __autoExtFptr = new Set;

    capi.sqlite3_auto_extension = function(fPtr){
      if( fPtr instanceof Function ){
        fPtr = wasm.installFunction('i(ppp)', fPtr);
      }else if( 1!==arguments.length || !wasm.isPtr(fPtr) ){
        return capi.SQLITE_MISUSE;
      }
      const rc = wasm.exports.sqlite3_auto_extension(fPtr);
      if( fPtr!==arguments[0] ){
        if(0===rc) __autoExtFptr.add(fPtr);
        else wasm.uninstallFunction(fPtr);
      }
      return rc;
    };

    capi.sqlite3_cancel_auto_extension = function(fPtr){
     /* We do not do an automatic JS-to-WASM function conversion here
        because it would be senseless: the converted pointer would
        never possibly match an already-installed one. */;
      if(!fPtr || 1!==arguments.length || !wasm.isPtr(fPtr)) return 0;
      return wasm.exports.sqlite3_cancel_auto_extension(fPtr);
      /* Note that it "cannot happen" that a client passes a pointer which
         is in __autoExtFptr because __autoExtFptr only contains automatic
         conversions created inside sqlite3_auto_extension() and
         never exposed to the client. */
    };

    capi.sqlite3_reset_auto_extension = function(){
      wasm.exports.sqlite3_reset_auto_extension();
      for(const fp of __autoExtFptr) wasm.uninstallFunction(fp);
      __autoExtFptr.clear();
    };
  }/* auto-extension */

  const pKvvfs = capi.sqlite3_vfs_find("kvvfs");
  if( pKvvfs ){/* kvvfs-specific glue */
    if(util.isUIThread()){
      const kvvfsMethods = new capi.sqlite3_kvvfs_methods(
        wasm.exports.sqlite3_wasm_kvvfs_methods()
      );
      delete capi.sqlite3_kvvfs_methods;

      const kvvfsMakeKey = wasm.exports.sqlite3_wasm_kvvfsMakeKeyOnPstack,
            pstack = wasm.pstack;

      const kvvfsStorage = (zClass)=>
            ((115/*=='s'*/===wasm.peek(zClass))
             ? sessionStorage : localStorage);

      /**
         Implementations for members of the object referred to by
         sqlite3_wasm_kvvfs_methods(). We swap out the native
         implementations with these, which use localStorage or
         sessionStorage for their backing store.
      */
      const kvvfsImpls = {
        xRead: (zClass, zKey, zBuf, nBuf)=>{
          const stack = pstack.pointer,
                astack = wasm.scopedAllocPush();
          try {
            const zXKey = kvvfsMakeKey(zClass,zKey);
            if(!zXKey) return -3/*OOM*/;
            const jKey = wasm.cstrToJs(zXKey);
            const jV = kvvfsStorage(zClass).getItem(jKey);
            if(!jV) return -1;
            const nV = jV.length /* Note that we are relying 100% on v being
                                    ASCII so that jV.length is equal to the
                                    C-string's byte length. */;
            if(nBuf<=0) return nV;
            else if(1===nBuf){
              wasm.poke(zBuf, 0);
              return nV;
            }
            const zV = wasm.scopedAllocCString(jV);
            if(nBuf > nV + 1) nBuf = nV + 1;
            wasm.heap8u().copyWithin(zBuf, zV, zV + nBuf - 1);
            wasm.poke(zBuf + nBuf - 1, 0);
            return nBuf - 1;
          }catch(e){
            console.error("kvstorageRead()",e);
            return -2;
          }finally{
            pstack.restore(stack);
            wasm.scopedAllocPop(astack);
          }
        },
        xWrite: (zClass, zKey, zData)=>{
          const stack = pstack.pointer;
          try {
            const zXKey = kvvfsMakeKey(zClass,zKey);
            if(!zXKey) return 1/*OOM*/;
            const jKey = wasm.cstrToJs(zXKey);
            kvvfsStorage(zClass).setItem(jKey, wasm.cstrToJs(zData));
            return 0;
          }catch(e){
            console.error("kvstorageWrite()",e);
            return capi.SQLITE_IOERR;
          }finally{
            pstack.restore(stack);
          }
        },
        xDelete: (zClass, zKey)=>{
          const stack = pstack.pointer;
          try {
            const zXKey = kvvfsMakeKey(zClass,zKey);
            if(!zXKey) return 1/*OOM*/;
            kvvfsStorage(zClass).removeItem(wasm.cstrToJs(zXKey));
            return 0;
          }catch(e){
            console.error("kvstorageDelete()",e);
            return capi.SQLITE_IOERR;
          }finally{
            pstack.restore(stack);
          }
        }
      }/*kvvfsImpls*/;
      for(const k of Object.keys(kvvfsImpls)){
        kvvfsMethods[kvvfsMethods.memberKey(k)] =
          wasm.installFunction(
            kvvfsMethods.memberSignature(k),
            kvvfsImpls[k]
          );
      }
    }else{
      /* Worker thread: unregister kvvfs to avoid it being used
         for anything other than local/sessionStorage. It "can"
         be used that way but it's not really intended to be. */
      capi.sqlite3_vfs_unregister(pKvvfs);
    }
  }/*pKvvfs*/

  wasm.xWrap.FuncPtrAdapter.warnOnUse = true;
});

Added ext/wasm/api/sqlite3-api-oo1.js.





















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
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
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
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
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
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
  2022-07-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 contains the so-called OO #1 API wrapper for the sqlite3
  WASM build. It requires that sqlite3-api-glue.js has already run
  and it installs its deliverable as self.sqlite3.oo1.
*/
self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
  const toss = (...args)=>{throw new Error(args.join(' '))};
  const toss3 = (...args)=>{throw new sqlite3.SQLite3Error(...args)};

  const capi = sqlite3.capi, wasm = sqlite3.wasm, util = sqlite3.util;
  /* What follows is colloquially known as "OO API #1". It is a
     binding of the sqlite3 API which is designed to be run within
     the same thread (main or worker) as the one in which the
     sqlite3 WASM binding was initialized. This wrapper cannot use
     the sqlite3 binding if, e.g., the wrapper is in the main thread
     and the sqlite3 API is in a worker. */

  /**
     In order to keep clients from manipulating, perhaps
     inadvertently, the underlying pointer values of DB and Stmt
     instances, we'll gate access to them via the `pointer` property
     accessor and store their real values in this map. Keys = DB/Stmt
     objects, values = pointer values. This also unifies how those are
     accessed, for potential use downstream via custom
     wasm.xWrap() function signatures which know how to extract
     it.
  */
  const __ptrMap = new WeakMap();
  /**
     Map of DB instances to objects, each object being a map of Stmt
     wasm pointers to Stmt objects.
  */
  const __stmtMap = new WeakMap();

  /** If object opts has _its own_ property named p then that
      property's value is returned, else dflt is returned. */
  const getOwnOption = (opts, p, dflt)=>{
    const d = Object.getOwnPropertyDescriptor(opts,p);
    return d ? d.value : dflt;
  };

  // Documented in DB.checkRc()
  const checkSqlite3Rc = function(dbPtr, sqliteResultCode){
    if(sqliteResultCode){
      if(dbPtr instanceof DB) dbPtr = dbPtr.pointer;
      toss3(
        "sqlite3 result code",sqliteResultCode+":",
        (dbPtr
         ? capi.sqlite3_errmsg(dbPtr)
         : capi.sqlite3_errstr(sqliteResultCode))
      );
    }
    return arguments[0];
  };

  /**
     sqlite3_trace_v2() callback which gets installed by the DB ctor
     if its open-flags contain "t".
  */
  const __dbTraceToConsole =
        wasm.installFunction('i(ippp)', function(t,c,p,x){
          if(capi.SQLITE_TRACE_STMT===t){
            // x == SQL, p == sqlite3_stmt*
            console.log("SQL TRACE #"+(++this.counter)+' via sqlite3@'+c+':',
                        wasm.cstrToJs(x));
          }
        }.bind({counter: 0}));

  /**
     A map of sqlite3_vfs pointers to SQL code or a callback function
     to run when the DB constructor opens a database with the given
     VFS. In the latter case, the call signature is (theDbObject,sqlite3Namespace)
     and the callback is expected to throw on error.
  */
  const __vfsPostOpenSql = Object.create(null);

  /**
     A proxy for DB class constructors. It must be called with the
     being-construct DB object as its "this". See the DB constructor
     for the argument docs. This is split into a separate function
     in order to enable simple creation of special-case DB constructors,
     e.g. JsStorageDb and OpfsDb.

     Expects to be passed a configuration object with the following
     properties:

     - `.filename`: the db filename. It may be a special name like ":memory:"
       or "".

     - `.flags`: as documented in the DB constructor.

     - `.vfs`: as documented in the DB constructor.

     It also accepts those as the first 3 arguments.
  */
  const dbCtorHelper = function ctor(...args){
    if(!ctor._name2vfs){
      /**
         Map special filenames which we handle here (instead of in C)
         to some helpful metadata...

         As of 2022-09-20, the C API supports the names :localStorage:
         and :sessionStorage: for kvvfs. However, C code cannot
         determine (without embedded JS code, e.g. via Emscripten's
         EM_JS()) whether the kvvfs is legal in the current browser
         context (namely the main UI thread). In order to help client
         code fail early on, instead of it being delayed until they
         try to read or write a kvvfs-backed db, we'll check for those
         names here and throw if they're not legal in the current
         context.
      */
      ctor._name2vfs = Object.create(null);
      const isWorkerThread = ('function'===typeof importScripts/*===running in worker thread*/)
            ? (n)=>toss3("The VFS for",n,"is only available in the main window thread.")
            : false;
      ctor._name2vfs[':localStorage:'] = {
        vfs: 'kvvfs', filename: isWorkerThread || (()=>'local')
      };
      ctor._name2vfs[':sessionStorage:'] = {
        vfs: 'kvvfs', filename: isWorkerThread || (()=>'session')
      };
    }
    const opt = ctor.normalizeArgs(...args);
    let fn = opt.filename, vfsName = opt.vfs, flagsStr = opt.flags;
    if(('string'!==typeof fn && 'number'!==typeof fn)
       || 'string'!==typeof flagsStr
       || (vfsName && ('string'!==typeof vfsName && 'number'!==typeof vfsName))){
      console.error("Invalid DB ctor args",opt,arguments);
      toss3("Invalid arguments for DB constructor.");
    }
    let fnJs = ('number'===typeof fn) ? wasm.cstrToJs(fn) : fn;
    const vfsCheck = ctor._name2vfs[fnJs];
    if(vfsCheck){
      vfsName = vfsCheck.vfs;
      fn = fnJs = vfsCheck.filename(fnJs);
    }
    let pDb, oflags = 0;
    if( flagsStr.indexOf('c')>=0 ){
      oflags |= capi.SQLITE_OPEN_CREATE | capi.SQLITE_OPEN_READWRITE;
    }
    if( flagsStr.indexOf('w')>=0 ) oflags |= capi.SQLITE_OPEN_READWRITE;
    if( 0===oflags ) oflags |= capi.SQLITE_OPEN_READONLY;
    oflags |= capi.SQLITE_OPEN_EXRESCODE;
    const stack = wasm.pstack.pointer;
    try {
      const pPtr = wasm.pstack.allocPtr() /* output (sqlite3**) arg */;
      let rc = capi.sqlite3_open_v2(fn, pPtr, oflags, vfsName || 0);
      pDb = wasm.peekPtr(pPtr);
      checkSqlite3Rc(pDb, rc);
      capi.sqlite3_extended_result_codes(pDb, 1);
      if(flagsStr.indexOf('t')>=0){
        capi.sqlite3_trace_v2(pDb, capi.SQLITE_TRACE_STMT,
                              __dbTraceToConsole, pDb);
      }
    }catch( e ){
      if( pDb ) capi.sqlite3_close_v2(pDb);
      throw e;
    }finally{
      wasm.pstack.restore(stack);
    }
    this.filename = fnJs;
    __ptrMap.set(this, pDb);
    __stmtMap.set(this, Object.create(null));
    try{
      // Check for per-VFS post-open SQL/callback...
      const pVfs = capi.sqlite3_js_db_vfs(pDb);
      if(!pVfs) toss3("Internal error: cannot get VFS for new db handle.");
      const postInitSql = __vfsPostOpenSql[pVfs];
      if(postInitSql instanceof Function){
        postInitSql(this, sqlite3);
      }else if(postInitSql){
        checkSqlite3Rc(
          pDb, capi.sqlite3_exec(pDb, postInitSql, 0, 0, 0)
        );
      }
    }catch(e){
      this.close();
      throw e;
    }
  };

  /**
     Sets SQL which should be exec()'d on a DB instance after it is
     opened with the given VFS pointer. The SQL may be any type
     supported by the "string:flexible" function argument conversion.
     Alternately, the 2nd argument may be a function, in which case it
     is called with (theOo1DbObject,sqlite3Namespace) at the end of
     the DB() constructor. The function must throw on error, in which
     case the db is closed and the exception is propagated.  This
     function is intended only for use by DB subclasses or sqlite3_vfs
     implementations.
  */
  dbCtorHelper.setVfsPostOpenSql = function(pVfs, sql){
    __vfsPostOpenSql[pVfs] = sql;
  };

  /**
     A helper for DB constructors. It accepts either a single
     config-style object or up to 3 arguments (filename, dbOpenFlags,
     dbVfsName). It returns a new object containing:

     { filename: ..., flags: ..., vfs: ... }

     If passed an object, any additional properties it has are copied
     as-is into the new object.
  */
  dbCtorHelper.normalizeArgs = function(filename=':memory:',flags = 'c',vfs = null){
    const arg = {};
    if(1===arguments.length && arguments[0] && 'object'===typeof arguments[0]){
      Object.assign(arg, arguments[0]);
      if(undefined===arg.flags) arg.flags = 'c';
      if(undefined===arg.vfs) arg.vfs = null;
      if(undefined===arg.filename) arg.filename = ':memory:';
    }else{
      arg.filename = filename;
      arg.flags = flags;
      arg.vfs = vfs;
    }
    return arg;
  };
  /**
     The DB class provides a high-level OO wrapper around an sqlite3
     db handle.

     The given db filename must be resolvable using whatever
     filesystem layer (virtual or otherwise) is set up for the default
     sqlite3 VFS.

     Note that the special sqlite3 db names ":memory:" and ""
     (temporary db) have their normal special meanings here and need
     not resolve to real filenames, but "" uses an on-storage
     temporary database and requires that the VFS support that.

     The second argument specifies the open/create mode for the
     database. It must be string containing a sequence of letters (in
     any order, but case sensitive) specifying the mode:

     - "c": create if it does not exist, else fail if it does not
       exist. Implies the "w" flag.

     - "w": write. Implies "r": a db cannot be write-only.

     - "r": read-only if neither "w" nor "c" are provided, else it
       is ignored.

     - "t": enable tracing of SQL executed on this database handle,
       sending it to `console.log()`. To disable it later, call
       `sqlite3.capi.sqlite3_trace_v2(thisDb.pointer, 0, 0, 0)`.

     If "w" is not provided, the db is implicitly read-only, noting
     that "rc" is meaningless

     Any other letters are currently ignored. The default is
     "c". These modes are ignored for the special ":memory:" and ""
     names and _may_ be ignored altogether for certain VFSes.

     The final argument is analogous to the final argument of
     sqlite3_open_v2(): the name of an sqlite3 VFS. Pass a falsy value,
     or none at all, to use the default. If passed a value, it must
     be the string name of a VFS.

     The constructor optionally (and preferably) takes its arguments
     in the form of a single configuration object with the following
     properties:

     - `filename`: database file name
     - `flags`: open-mode flags
     - `vfs`: the VFS fname

     The `filename` and `vfs` arguments may be either JS strings or
     C-strings allocated via WASM. `flags` is required to be a JS
     string (because it's specific to this API, which is specific
     to JS).

     For purposes of passing a DB instance to C-style sqlite3
     functions, the DB object's read-only `pointer` property holds its
     `sqlite3*` pointer value. That property can also be used to check
     whether this DB instance is still open.

     In the main window thread, the filenames `":localStorage:"` and
     `":sessionStorage:"` are special: they cause the db to use either
     localStorage or sessionStorage for storing the database using
     the kvvfs. If one of these names are used, they trump
     any vfs name set in the arguments.
  */
  const DB = function(...args){
    dbCtorHelper.apply(this, args);
  };
  DB.dbCtorHelper = dbCtorHelper;

  /**
     Internal-use enum for mapping JS types to DB-bindable types.
     These do not (and need not) line up with the SQLITE_type
     values. All values in this enum must be truthy and distinct
     but they need not be numbers.
  */
  const BindTypes = {
    null: 1,
    number: 2,
    string: 3,
    boolean: 4,
    blob: 5
  };
  BindTypes['undefined'] == BindTypes.null;
  if(wasm.bigIntEnabled){
    BindTypes.bigint = BindTypes.number;
  }

  /**
     This class wraps sqlite3_stmt. Calling this constructor
     directly will trigger an exception. Use DB.prepare() to create
     new instances.

     For purposes of passing a Stmt instance to C-style sqlite3
     functions, its read-only `pointer` property holds its `sqlite3_stmt*`
     pointer value.

     Other non-function properties include:

     - `db`: the DB object which created the statement.

     - `columnCount`: the number of result columns in the query, or 0 for
     queries which cannot return results.

     - `parameterCount`: the number of bindable paramters in the query.
  */
  const Stmt = function(){
    if(BindTypes!==arguments[2]){
      toss3(capi.SQLITE_MISUSE, "Do not call the Stmt constructor directly. Use DB.prepare().");
    }
    this.db = arguments[0];
    __ptrMap.set(this, arguments[1]);
    this.columnCount = capi.sqlite3_column_count(this.pointer);
    this.parameterCount = capi.sqlite3_bind_parameter_count(this.pointer);
  };

  /** Throws if the given DB has been closed, else it is returned. */
  const affirmDbOpen = function(db){
    if(!db.pointer) toss3("DB has been closed.");
    return db;
  };

  /** Throws if ndx is not an integer or if it is out of range
      for stmt.columnCount, else returns stmt.

      Reminder: this will also fail after the statement is finalized
      but the resulting error will be about an out-of-bounds column
      index rather than a statement-is-finalized error.
  */
  const affirmColIndex = function(stmt,ndx){
    if((ndx !== (ndx|0)) || ndx<0 || ndx>=stmt.columnCount){
      toss3("Column index",ndx,"is out of range.");
    }
    return stmt;
  };

  /**
     Expects to be passed the `arguments` object from DB.exec(). Does
     the argument processing/validation, throws on error, and returns
     a new object on success:

     { sql: the SQL, opt: optionsObj, cbArg: function}

     The opt object is a normalized copy of any passed to this
     function. The sql will be converted to a string if it is provided
     in one of the supported non-string formats.

     cbArg is only set if the opt.callback or opt.resultRows are set,
     in which case it's a function which expects to be passed the
     current Stmt and returns the callback argument of the type
     indicated by the input arguments.
  */
  const parseExecArgs = function(db, args){
    const out = Object.create(null);
    out.opt = Object.create(null);
    switch(args.length){
        case 1:
          if('string'===typeof args[0] || util.isSQLableTypedArray(args[0])){
            out.sql = args[0];
          }else if(Array.isArray(args[0])){
            out.sql = args[0];
          }else if(args[0] && 'object'===typeof args[0]){
            out.opt = args[0];
            out.sql = out.opt.sql;
          }
          break;
        case 2:
          out.sql = args[0];
          out.opt = args[1];
          break;
        default: toss3("Invalid argument count for exec().");
    };
    out.sql = util.flexibleString(out.sql);
    if('string'!==typeof out.sql){
      toss3("Missing SQL argument or unsupported SQL value type.");
    }
    const opt = out.opt;
    switch(opt.returnValue){
        case 'resultRows':
          if(!opt.resultRows) opt.resultRows = [];
          out.returnVal = ()=>opt.resultRows;
          break;
        case 'saveSql':
          if(!opt.saveSql) opt.saveSql = [];
          out.returnVal = ()=>opt.saveSql;
          break;
        case undefined:
        case 'this':
          out.returnVal = ()=>db;
          break;
        default:
          toss3("Invalid returnValue value:",opt.returnValue);
    }
    if(!opt.callback && !opt.returnValue && undefined!==opt.rowMode){
      if(!opt.resultRows) opt.resultRows = [];
      out.returnVal = ()=>opt.resultRows;
    }
    if(opt.callback || opt.resultRows){
      switch((undefined===opt.rowMode)
             ? 'array' : opt.rowMode) {
          case 'object': out.cbArg = (stmt)=>stmt.get(Object.create(null)); break;
          case 'array': out.cbArg = (stmt)=>stmt.get([]); break;
          case 'stmt':
            if(Array.isArray(opt.resultRows)){
              toss3("exec(): invalid rowMode for a resultRows array: must",
                    "be one of 'array', 'object',",
                    "a result column number, or column name reference.");
            }
            out.cbArg = (stmt)=>stmt;
            break;
          default:
            if(util.isInt32(opt.rowMode)){
              out.cbArg = (stmt)=>stmt.get(opt.rowMode);
              break;
            }else if('string'===typeof opt.rowMode
                     && opt.rowMode.length>1
                     && '$'===opt.rowMode[0]){
              /* "$X": fetch column named "X" (case-sensitive!). Prior
                 to 2022-12-14 ":X" and "@X" were also permitted, but
                 having so many options is unnecessary and likely to
                 cause confusion. */
              const $colName = opt.rowMode.substr(1);
              out.cbArg = (stmt)=>{
                const rc = stmt.get(Object.create(null))[$colName];
                return (undefined===rc)
                  ? toss3(capi.SQLITE_NOTFOUND,
                          "exec(): unknown result column:",$colName)
                  : rc;
              };
              break;
            }
            toss3("Invalid rowMode:",opt.rowMode);
      }
    }
    return out;
  };

  /**
     Internal impl of the DB.selectValue(), selectArray(), and
     selectObject() methods.
  */
  const __selectFirstRow = (db, sql, bind, ...getArgs)=>{
    const stmt = db.prepare(sql);
    try {
      return stmt.bind(bind).step() ? stmt.get(...getArgs) : undefined;
    }finally{
      stmt.finalize();
    }
  };

  /**
     Internal impl of the DB.selectArrays() and selectObjects()
     methods.
  */
  const __selectAll =
        (db, sql, bind, rowMode)=>db.exec({
          sql, bind, rowMode, returnValue: 'resultRows'
        });

  /**
     Expects to be given a DB instance or an `sqlite3*` pointer (may
     be null) and an sqlite3 API result code. If the result code is
     not falsy, this function throws an SQLite3Error with an error
     message from sqlite3_errmsg(), using db (or, if db is-a DB,
     db.pointer) as the db handle, or sqlite3_errstr() if db is
     falsy. Note that if it's passed a non-error code like SQLITE_ROW
     or SQLITE_DONE, it will still throw but the error string might be
     "Not an error."  The various non-0 non-error codes need to be
     checked for in client code where they are expected.

     If it does not throw, it returns its first argument.
  */
  DB.checkRc = (db,resultCode)=>checkSqlite3Rc(db,resultCode);

  DB.prototype = {
    /** Returns true if this db handle is open, else false. */
    isOpen: function(){
      return !!this.pointer;
    },
    /** Throws if this given DB has been closed, else returns `this`. */
    affirmOpen: function(){
      return affirmDbOpen(this);
    },
    /**
       Finalizes all open statements and closes this database
       connection. This is a no-op if the db has already been
       closed. After calling close(), `this.pointer` will resolve to
       `undefined`, so that can be used to check whether the db
       instance is still opened.

       If this.onclose.before is a function then it is called before
       any close-related cleanup.

       If this.onclose.after is a function then it is called after the
       db is closed but before auxiliary state like this.filename is
       cleared.

       Both onclose handlers are passed this object, with the onclose
       object as their "this," noting that the db will have been
       closed when onclose.after is called. If this db is not opened
       when close() is called, neither of the handlers are called. Any
       exceptions the handlers throw are ignored because "destructors
       must not throw."

       Note that garbage collection of a db handle, if it happens at
       all, will never trigger close(), so onclose handlers are not a
       reliable way to implement close-time cleanup or maintenance of
       a db.
    */
    close: function(){
      if(this.pointer){
        if(this.onclose && (this.onclose.before instanceof Function)){
          try{this.onclose.before(this)}
          catch(e){/*ignore*/}
        }
        const pDb = this.pointer;
        Object.keys(__stmtMap.get(this)).forEach((k,s)=>{
          if(s && s.pointer) s.finalize();
        });
        __ptrMap.delete(this);
        __stmtMap.delete(this);
        capi.sqlite3_close_v2(pDb);
        if(this.onclose && (this.onclose.after instanceof Function)){
          try{this.onclose.after(this)}
          catch(e){/*ignore*/}
        }
        delete this.filename;
      }
    },
    /**
       Returns the number of changes, as per sqlite3_changes()
       (if the first argument is false) or sqlite3_total_changes()
       (if it's true). If the 2nd argument is true, it uses
       sqlite3_changes64() or sqlite3_total_changes64(), which
       will trigger an exception if this build does not have
       BigInt support enabled.
    */
    changes: function(total=false,sixtyFour=false){
      const p = affirmDbOpen(this).pointer;
      if(total){
        return sixtyFour
          ? capi.sqlite3_total_changes64(p)
          : capi.sqlite3_total_changes(p);
      }else{
        return sixtyFour
          ? capi.sqlite3_changes64(p)
          : capi.sqlite3_changes(p);
      }
    },
    /**
       Similar to the this.filename but returns the
       sqlite3_db_filename() value for the given database name,
       defaulting to "main".  The argument may be either a JS string
       or a pointer to a WASM-allocated C-string.
    */
    dbFilename: function(dbName='main'){
      return capi.sqlite3_db_filename(affirmDbOpen(this).pointer, dbName);
    },
    /**
       Returns the name of the given 0-based db number, as documented
       for sqlite3_db_name().
    */
    dbName: function(dbNumber=0){
      return capi.sqlite3_db_name(affirmDbOpen(this).pointer, dbNumber);
    },
    /**
       Returns the name of the sqlite3_vfs used by the given database
       of this connection (defaulting to 'main'). The argument may be
       either a JS string or a WASM C-string. Returns undefined if the
       given db name is invalid. Throws if this object has been
       close()d.
    */
    dbVfsName: function(dbName=0){
      let rc;
      const pVfs = capi.sqlite3_js_db_vfs(
        affirmDbOpen(this).pointer, dbName
      );
      if(pVfs){
        const v = new capi.sqlite3_vfs(pVfs);
        try{ rc = wasm.cstrToJs(v.$zName) }
        finally { v.dispose() }
      }
      return rc;
    },
    /**
       Compiles the given SQL and returns a prepared Stmt. This is
       the only way to create new Stmt objects. Throws on error.

       The given SQL must be a string, a Uint8Array holding SQL, a
       WASM pointer to memory holding the NUL-terminated SQL string,
       or an array of strings. In the latter case, the array is
       concatenated together, with no separators, to form the SQL
       string (arrays are often a convenient way to formulate long
       statements).  If the SQL contains no statements, an
       SQLite3Error is thrown.

       Design note: the C API permits empty SQL, reporting it as a 0
       result code and a NULL stmt pointer. Supporting that case here
       would cause extra work for all clients: any use of the Stmt API
       on such a statement will necessarily throw, so clients would be
       required to check `stmt.pointer` after calling `prepare()` in
       order to determine whether the Stmt instance is empty or not.
       Long-time practice (with other sqlite3 script bindings)
       suggests that the empty-prepare case is sufficiently rare that
       supporting it here would simply hurt overall usability.
    */
    prepare: function(sql){
      affirmDbOpen(this);
      const stack = wasm.pstack.pointer;
      let ppStmt, pStmt;
      try{
        ppStmt = wasm.pstack.alloc(8)/* output (sqlite3_stmt**) arg */;
        DB.checkRc(this, capi.sqlite3_prepare_v2(this.pointer, sql, -1, ppStmt, null));
        pStmt = wasm.peekPtr(ppStmt);
      }
      finally {
        wasm.pstack.restore(stack);
      }
      if(!pStmt) toss3("Cannot prepare empty SQL.");
      const stmt = new Stmt(this, pStmt, BindTypes);
      __stmtMap.get(this)[pStmt] = stmt;
      return stmt;
    },
    /**
       Executes one or more SQL statements in the form of a single
       string. Its arguments must be either (sql,optionsObject) or
       (optionsObject). In the latter case, optionsObject.sql must
       contain the SQL to execute. By default it returns this object
       but that can be changed via the `returnValue` option as
       described below. Throws on error.

       If no SQL is provided, or a non-string is provided, an
       exception is triggered. Empty SQL, on the other hand, is
       simply a no-op.

       The optional options object may contain any of the following
       properties:

       - `sql` = the SQL to run (unless it's provided as the first
       argument). This must be of type string, Uint8Array, or an array
       of strings. In the latter case they're concatenated together
       as-is, _with no separator_ between elements, before evaluation.
       The array form is often simpler for long hand-written queries.

       - `bind` = a single value valid as an argument for
       Stmt.bind(). This is _only_ applied to the _first_ non-empty
       statement in the SQL which has any bindable parameters. (Empty
       statements are skipped entirely.)

       - `saveSql` = an optional array. If set, the SQL of each
       executed statement is appended to this array before the
       statement is executed (but after it is prepared - we don't have
       the string until after that). Empty SQL statements are elided
       but can have odd effects in the output. e.g. SQL of: `"select
       1; -- empty\n; select 2"` will result in an array containing
       `["select 1;", "--empty \n; select 2"]`. That's simply how
       sqlite3 records the SQL for the 2nd statement.

       ==================================================================
       The following options apply _only_ to the _first_ statement
       which has a non-zero result column count, regardless of whether
       the statement actually produces any result rows.
       ==================================================================

       - `columnNames`: if this is an array, the column names of the
       result set are stored in this array before the callback (if
       any) is triggered (regardless of whether the query produces any
       result rows). If no statement has result columns, this value is
       unchanged. Achtung: an SQL result may have multiple columns
       with identical names.

       - `callback` = a function which gets called for each row of the
       result set, but only if that statement has any result
       _rows_. The callback's "this" is the options object, noting
       that this function synthesizes one if the caller does not pass
       one to exec(). The second argument passed to the callback is
       always the current Stmt object, as it's needed if the caller
       wants to fetch the column names or some such (noting that they
       could also be fetched via `this.columnNames`, if the client
       provides the `columnNames` option). If the callback returns a
       literal `false` (as opposed to any other falsy value, e.g.  an
       implicit `undefined` return), any ongoing statement-`step()`
       iteration stops without an error. The return value of the
       callback is otherwise ignored.

       ACHTUNG: The callback MUST NOT modify the Stmt object. Calling
       any of the Stmt.get() variants, Stmt.getColumnName(), or
       similar, is legal, but calling step() or finalize() is
       not. Member methods which are illegal in this context will
       trigger an exception, but clients must also refrain from using
       any lower-level (C-style) APIs which might modify the
       statement.

       The first argument passed to the callback defaults to an array of
       values from the current result row but may be changed with ...

       - `rowMode` = specifies the type of he callback's first argument.
       It may be any of...

       A) A string describing what type of argument should be passed
       as the first argument to the callback:

         A.1) `'array'` (the default) causes the results of
         `stmt.get([])` to be passed to the `callback` and/or appended
         to `resultRows`

         A.2) `'object'` causes the results of
         `stmt.get(Object.create(null))` to be passed to the
         `callback` and/or appended to `resultRows`.  Achtung: an SQL
         result may have multiple columns with identical names. In
         that case, the right-most column will be the one set in this
         object!

         A.3) `'stmt'` causes the current Stmt to be passed to the
         callback, but this mode will trigger an exception if
         `resultRows` is an array because appending the statement to
         the array would be downright unhelpful.

       B) An integer, indicating a zero-based column in the result
       row. Only that one single value will be passed on.

       C) A string with a minimum length of 2 and leading character of
       '$' will fetch the row as an object, extract that one field,
       and pass that field's value to the callback. Note that these
       keys are case-sensitive so must match the case used in the
       SQL. e.g. `"select a A from t"` with a `rowMode` of `'$A'`
       would work but `'$a'` would not. A reference to a column not in
       the result set will trigger an exception on the first row (as
       the check is not performed until rows are fetched).  Note also
       that `$` is a legal identifier character in JS so need not be
       quoted.

       Any other `rowMode` value triggers an exception.

       - `resultRows`: if this is an array, it functions similarly to
       the `callback` option: each row of the result set (if any),
       with the exception that the `rowMode` 'stmt' is not legal. It
       is legal to use both `resultRows` and `callback`, but
       `resultRows` is likely much simpler to use for small data sets
       and can be used over a WebWorker-style message interface.
       exec() throws if `resultRows` is set and `rowMode` is 'stmt'.

       - `returnValue`: is a string specifying what this function
       should return:

         A) The default value is (usually) `"this"`, meaning that the
            DB object itself should be returned. The exceptions is if
            the caller passes neither of `callback` nor `returnValue`
            but does pass an explicit `rowMode` then the default
            `returnValue` is `"resultRows"`, described below.

         B) `"resultRows"` means to return the value of the
            `resultRows` option. If `resultRows` is not set, this
            function behaves as if it were set to an empty array.

         C) `"saveSql"` means to return the value of the
            `saveSql` option. If `saveSql` is not set, this
            function behaves as if it were set to an empty array.

       Potential TODOs:

       - `bind`: permit an array of arrays/objects to bind. The first
       sub-array would act on the first statement which has bindable
       parameters (as it does now). The 2nd would act on the next such
       statement, etc.

       - `callback` and `resultRows`: permit an array entries with
       semantics similar to those described for `bind` above.

    */
    exec: function(/*(sql [,obj]) || (obj)*/){
      affirmDbOpen(this);
      const arg = parseExecArgs(this, arguments);
      if(!arg.sql){
        return toss3("exec() requires an SQL string.");
      }
      const opt = arg.opt;
      const callback = opt.callback;
      const resultRows =
            Array.isArray(opt.resultRows) ? opt.resultRows : undefined;
      let stmt;
      let bind = opt.bind;
      let evalFirstResult = !!(
        arg.cbArg || opt.columnNames || resultRows
      ) /* true to step through the first result-returning statement */;
      const stack = wasm.scopedAllocPush();
      const saveSql = Array.isArray(opt.saveSql) ? opt.saveSql : undefined;
      try{
        const isTA = util.isSQLableTypedArray(arg.sql)
        /* Optimization: if the SQL is a TypedArray we can save some string
           conversion costs. */;
        /* Allocate the two output pointers (ppStmt, pzTail) and heap
           space for the SQL (pSql). When prepare_v2() returns, pzTail
           will point to somewhere in pSql. */
        let sqlByteLen = isTA ? arg.sql.byteLength : wasm.jstrlen(arg.sql);
        const ppStmt  = wasm.scopedAlloc(
          /* output (sqlite3_stmt**) arg and pzTail */
          (2 * wasm.ptrSizeof) + (sqlByteLen + 1/* SQL + NUL */)
        );
        const pzTail = ppStmt + wasm.ptrSizeof /* final arg to sqlite3_prepare_v2() */;
        let pSql = pzTail + wasm.ptrSizeof;
        const pSqlEnd = pSql + sqlByteLen;
        if(isTA) wasm.heap8().set(arg.sql, pSql);
        else wasm.jstrcpy(arg.sql, wasm.heap8(), pSql, sqlByteLen, false);
        wasm.poke(pSql + sqlByteLen, 0/*NUL terminator*/);
        while(pSql && wasm.peek(pSql, 'i8')
              /* Maintenance reminder:^^^ _must_ be 'i8' or else we
                 will very likely cause an endless loop. What that's
                 doing is checking for a terminating NUL byte. If we
                 use i32 or similar then we read 4 bytes, read stuff
                 around the NUL terminator, and get stuck in and
                 endless loop at the end of the SQL, endlessly
                 re-preparing an empty statement. */ ){
          wasm.pokePtr([ppStmt, pzTail], 0);
          DB.checkRc(this, capi.sqlite3_prepare_v3(
            this.pointer, pSql, sqlByteLen, 0, ppStmt, pzTail
          ));
          const pStmt = wasm.peekPtr(ppStmt);
          pSql = wasm.peekPtr(pzTail);
          sqlByteLen = pSqlEnd - pSql;
          if(!pStmt) continue;
          if(saveSql) saveSql.push(capi.sqlite3_sql(pStmt).trim());
          stmt = new Stmt(this, pStmt, BindTypes);
          if(bind && stmt.parameterCount){
            stmt.bind(bind);
            bind = null;
          }
          if(evalFirstResult && stmt.columnCount){
            /* Only forward SELECT results for the FIRST query
               in the SQL which potentially has them. */
            evalFirstResult = false;
            if(Array.isArray(opt.columnNames)){
              stmt.getColumnNames(opt.columnNames);
            }
            if(arg.cbArg || resultRows){
              for(; stmt.step(); stmt._isLocked = false){
                stmt._isLocked = true;
                const row = arg.cbArg(stmt);
                if(resultRows) resultRows.push(row);
                if(callback && false === callback.call(opt, row, stmt)){
                  break;
                }
              }
              stmt._isLocked = false;
            }
          }else{
            stmt.step();
          }
          stmt.finalize();
          stmt = null;
        }
      }/*catch(e){
        console.warn("DB.exec() is propagating exception",opt,e);
        throw e;
      }*/finally{
        if(stmt){
          delete stmt._isLocked;
          stmt.finalize();
        }
        wasm.scopedAllocPop(stack);
      }
      return arg.returnVal();
    }/*exec()*/,

    /**
       Creates a new UDF (User-Defined Function) which is accessible
       via SQL code. This function may be called in any of the
       following forms:

       - (name, function)
       - (name, function, optionsObject)
       - (name, optionsObject)
       - (optionsObject)

       In the final two cases, the function must be defined as the
       `callback` property of the options object (optionally called
       `xFunc` to align with the C API documentation). In the final
       case, the function's name must be the 'name' property.

       The first two call forms can only be used for creating scalar
       functions. Creating an aggregate or window function requires
       the options-object form (see below for details).

       UDFs can be removed as documented for
       sqlite3_create_function_v2() and
       sqlite3_create_window_function(), but doing so will "leak" the
       JS-created WASM binding of those functions (meaning that their
       entries in the WASM indirect function table still
       exist). Eliminating that potential leak is a pending TODO.

       On success, returns this object. Throws on error.

       When called from SQL arguments to the UDF, and its result,
       will be converted between JS and SQL with as much fidelity as
       is feasible, triggering an exception if a type conversion
       cannot be determined. The docs for sqlite3_create_function_v2()
       describe the conversions in more detail.

       The values set in the options object differ for scalar and
       aggregate functions:

       - Scalar: set the `xFunc` function-type property to the UDF
         function.

       - Aggregate: set the `xStep` and `xFinal` function-type
         properties to the "step" and "final" callbacks for the
         aggregate. Do not set the `xFunc` property.

       - Window: set the `xStep`, `xFinal`, `xValue`, and `xInverse`
         function-type properties. Do not set the `xFunc` property.

       The options object may optionally have an `xDestroy`
       function-type property, as per sqlite3_create_function_v2().
       Its argument will be the WASM-pointer-type value of the `pApp`
       property, and this function will throw if `pApp` is defined but
       is not null, undefined, or a numeric (WASM pointer)
       value. i.e. `pApp`, if set, must be value suitable for use as a
       WASM pointer argument, noting that `null` or `undefined` will
       translate to 0 for that purpose.

       The options object may contain flags to modify how
       the function is defined:

       - `arity`: the number of arguments which SQL calls to this
       function expect or require. The default value is `xFunc.length`
       or `xStep.length` (i.e. the number of declared parameters it
       has) **MINUS 1** (see below for why). As a special case, if the
       `length` is 0, its arity is also 0 instead of -1. A negative
       arity value means that the function is variadic and may accept
       any number of arguments, up to sqlite3's compile-time
       limits. sqlite3 will enforce the argument count if is zero or
       greater. The callback always receives a pointer to an
       `sqlite3_context` object as its first argument. Any arguments
       after that are from SQL code. The leading context argument does
       _not_ count towards the function's arity. See the docs for
       sqlite3.capi.sqlite3_create_function_v2() for why that argument
       is needed in the interface.

       The following options-object properties correspond to flags
       documented at:

       https://sqlite.org/c3ref/create_function.html

       - `deterministic` = sqlite3.capi.SQLITE_DETERMINISTIC
       - `directOnly` = sqlite3.capi.SQLITE_DIRECTONLY
       - `innocuous` = sqlite3.capi.SQLITE_INNOCUOUS

       Sidebar: the ability to add new WASM-accessible functions to
       the runtime requires that the WASM build is compiled with the
       equivalent functionality as that provided by Emscripten's
       `-sALLOW_TABLE_GROWTH` flag.
    */
    createFunction: function f(name, xFunc, opt){
      const isFunc = (f)=>(f instanceof Function);
      switch(arguments.length){
          case 1: /* (optionsObject) */
            opt = name;
            name = opt.name;
            xFunc = opt.xFunc || 0;
            break;
          case 2: /* (name, callback|optionsObject) */
            if(!isFunc(xFunc)){
              opt = xFunc;
              xFunc = opt.xFunc || 0;
            }
            break;
          case 3: /* name, xFunc, opt */
            break;
          default: break;
      }
      if(!opt) opt = {};
      if('string' !== typeof name){
        toss3("Invalid arguments: missing function name.");
      }
      let xStep = opt.xStep || 0;
      let xFinal = opt.xFinal || 0;
      const xValue = opt.xValue || 0;
      const xInverse = opt.xInverse || 0;
      let isWindow = undefined;
      if(isFunc(xFunc)){
        isWindow = false;
        if(isFunc(xStep) || isFunc(xFinal)){
          toss3("Ambiguous arguments: scalar or aggregate?");
        }
        xStep = xFinal = null;
      }else if(isFunc(xStep)){
        if(!isFunc(xFinal)){
          toss3("Missing xFinal() callback for aggregate or window UDF.");
        }
        xFunc = null;
      }else if(isFunc(xFinal)){
        toss3("Missing xStep() callback for aggregate or window UDF.");
      }else{
        toss3("Missing function-type properties.");
      }
      if(false === isWindow){
        if(isFunc(xValue) || isFunc(xInverse)){
          toss3("xValue and xInverse are not permitted for non-window UDFs.");
        }
      }else if(isFunc(xValue)){
        if(!isFunc(xInverse)){
          toss3("xInverse must be provided if xValue is.");
        }
        isWindow = true;
      }else if(isFunc(xInverse)){
        toss3("xValue must be provided if xInverse is.");
      }
      const pApp = opt.pApp;
      if(undefined!==pApp &&
         null!==pApp &&
         (('number'!==typeof pApp) || !util.isInt32(pApp))){
        toss3("Invalid value for pApp property. Must be a legal WASM pointer value.");
      }
      const xDestroy = opt.xDestroy || 0;
      if(xDestroy && !isFunc(xDestroy)){
        toss3("xDestroy property must be a function.");
      }
      let fFlags = 0 /*flags for sqlite3_create_function_v2()*/;
      if(getOwnOption(opt, 'deterministic')) fFlags |= capi.SQLITE_DETERMINISTIC;
      if(getOwnOption(opt, 'directOnly')) fFlags |= capi.SQLITE_DIRECTONLY;
      if(getOwnOption(opt, 'innocuous')) fFlags |= capi.SQLITE_INNOCUOUS;
      name = name.toLowerCase();
      const xArity = xFunc || xStep;
      const arity = getOwnOption(opt, 'arity');
      const arityArg = ('number'===typeof arity
                        ? arity
                        : (xArity.length ? xArity.length-1/*for pCtx arg*/ : 0));
      let rc;
      if( isWindow ){
        rc = capi.sqlite3_create_window_function(
          this.pointer, name, arityArg,
          capi.SQLITE_UTF8 | fFlags, pApp || 0,
          xStep, xFinal, xValue, xInverse, xDestroy);
      }else{
        rc = capi.sqlite3_create_function_v2(
          this.pointer, name, arityArg,
          capi.SQLITE_UTF8 | fFlags, pApp || 0,
          xFunc, xStep, xFinal, xDestroy);
      }
      DB.checkRc(this, rc);
      return this;
    }/*createFunction()*/,
    /**
       Prepares the given SQL, step()s it one time, and returns
       the value of the first result column. If it has no results,
       undefined is returned.

       If passed a second argument, it is treated like an argument
       to Stmt.bind(), so may be any type supported by that
       function. Passing the undefined value is the same as passing
       no value, which is useful when...

       If passed a 3rd argument, it is expected to be one of the
       SQLITE_{typename} constants. Passing the undefined value is
       the same as not passing a value.

       Throws on error (e.g. malformed SQL).
    */
    selectValue: function(sql,bind,asType){
      return __selectFirstRow(this, sql, bind, 0, asType);
    },

    /**
       Runs the given query and returns an array of the values from
       the first result column of each row of the result set. The 2nd
       argument is an optional value for use in a single-argument call
       to Stmt.bind(). The 3rd argument may be any value suitable for
       use as the 2nd argument to Stmt.get(). If a 3rd argument is
       desired but no bind data are needed, pass `undefined` for the 2nd
       argument.

       If there are no result rows, an empty array is returned.
    */
    selectValues: function(sql,bind,asType){
      const stmt = this.prepare(sql), rc = [];
      try {
        stmt.bind(bind);
        while(stmt.step()) rc.push(stmt.get(0,asType));
      }finally{
        stmt.finalize();
      }
      return rc;
    },

    /**
       Prepares the given SQL, step()s it one time, and returns an
       array containing the values of the first result row. If it has
       no results, `undefined` is returned.

       If passed a second argument other than `undefined`, it is
       treated like an argument to Stmt.bind(), so may be any type
       supported by that function.

       Throws on error (e.g. malformed SQL).
    */
    selectArray: function(sql,bind){
      return __selectFirstRow(this, sql, bind, []);
    },

    /**
       Prepares the given SQL, step()s it one time, and returns an
       object containing the key/value pairs of the first result
       row. If it has no results, `undefined` is returned.

       Note that the order of returned object's keys is not guaranteed
       to be the same as the order of the fields in the query string.

       If passed a second argument other than `undefined`, it is
       treated like an argument to Stmt.bind(), so may be any type
       supported by that function.

       Throws on error (e.g. malformed SQL).
    */
    selectObject: function(sql,bind){
      return __selectFirstRow(this, sql, bind, {});
    },

    /**
       Runs the given SQL and returns an array of all results, with
       each row represented as an array, as per the 'array' `rowMode`
       option to `exec()`. An empty result set resolves
       to an empty array. The second argument, if any, is treated as
       the 'bind' option to a call to exec().
    */
    selectArrays: function(sql,bind){
      return __selectAll(this, sql, bind, 'array');
    },

    /**
       Works identically to selectArrays() except that each value
       in the returned array is an object, as per the 'object' `rowMode`
       option to `exec()`.
    */
    selectObjects: function(sql,bind){
      return __selectAll(this, sql, bind, 'object');
    },

    /**
       Returns the number of currently-opened Stmt handles for this db
       handle, or 0 if this DB instance is closed. Note that only
       handles prepared via this.prepare() are counted, and not
       handles prepared using capi.sqlite3_prepare_v3() (or
       equivalent).
    */
    openStatementCount: function(){
      return this.pointer ? Object.keys(__stmtMap.get(this)).length : 0;
    },

    /**
       Starts a transaction, calls the given callback, and then either
       rolls back or commits the savepoint, depending on whether the
       callback throws. The callback is passed this db object as its
       only argument. On success, returns the result of the
       callback. Throws on error.

       Note that transactions may not be nested, so this will throw if
       it is called recursively. For nested transactions, use the
       savepoint() method or manually manage SAVEPOINTs using exec().

       If called with 2 arguments, the first must be a keyword which
       is legal immediately after a BEGIN statement, e.g. one of
       "DEFERRED", "IMMEDIATE", or "EXCLUSIVE". Though the exact list
       of supported keywords is not hard-coded here, in order to be
       future-compatible, if the argument does not look like a single
       keyword then an exception is triggered with a description of
       the problem.
     */
    transaction: function(/* [beginQualifier,] */callback){
      let opener = 'BEGIN';
      if(arguments.length>1){
        if(/[^a-zA-Z]/.test(arguments[0])){
          toss3(capi.SQLITE_MISUSE, "Invalid argument for BEGIN qualifier.");
        }
        opener += ' '+arguments[0];
        callback = arguments[1];
      }
      affirmDbOpen(this).exec(opener);
      try {
        const rc = callback(this);
        this.exec("COMMIT");
        return rc;
      }catch(e){
        this.exec("ROLLBACK");
        throw e;
      }
    },

    /**
       This works similarly to transaction() but uses sqlite3's SAVEPOINT
       feature. This function starts a savepoint (with an unspecified name)
       and calls the given callback function, passing it this db object.
       If the callback returns, the savepoint is released (committed). If
       the callback throws, the savepoint is rolled back. If it does not
       throw, it returns the result of the callback.
    */
    savepoint: function(callback){
      affirmDbOpen(this).exec("SAVEPOINT oo1");
      try {
        const rc = callback(this);
        this.exec("RELEASE oo1");
        return rc;
      }catch(e){
        this.exec("ROLLBACK to SAVEPOINT oo1; RELEASE SAVEPOINT oo1");
        throw e;
      }
    },

    /**
       A convenience form of DB.checkRc(this,resultCode). If it does
       not throw, it returns this object.
    */
    checkRc: function(resultCode){
      return DB.checkRc(this, resultCode);
    }
  }/*DB.prototype*/;


  /** Throws if the given Stmt has been finalized, else stmt is
      returned. */
  const affirmStmtOpen = function(stmt){
    if(!stmt.pointer) toss3("Stmt has been closed.");
    return stmt;
  };

  /** Returns an opaque truthy value from the BindTypes
      enum if v's type is a valid bindable type, else
      returns a falsy value. As a special case, a value of
      undefined is treated as a bind type of null. */
  const isSupportedBindType = function(v){
    let t = BindTypes[(null===v||undefined===v) ? 'null' : typeof v];
    switch(t){
        case BindTypes.boolean:
        case BindTypes.null:
        case BindTypes.number:
        case BindTypes.string:
          return t;
        case BindTypes.bigint:
          if(wasm.bigIntEnabled) return t;
          /* else fall through */
        default:
          return util.isBindableTypedArray(v) ? BindTypes.blob : undefined;
    }
  };

  /**
     If isSupportedBindType(v) returns a truthy value, this
     function returns that value, else it throws.
  */
  const affirmSupportedBindType = function(v){
    //console.log('affirmSupportedBindType',v);
    return isSupportedBindType(v) || toss3("Unsupported bind() argument type:",typeof v);
  };

  /**
     If key is a number and within range of stmt's bound parameter
     count, key is returned.

     If key is not a number then it is checked against named
     parameters. If a match is found, its index is returned.

     Else it throws.
  */
  const affirmParamIndex = function(stmt,key){
    const n = ('number'===typeof key)
          ? key : capi.sqlite3_bind_parameter_index(stmt.pointer, key);
    if(0===n || !util.isInt32(n)){
      toss3("Invalid bind() parameter name: "+key);
    }
    else if(n<1 || n>stmt.parameterCount) toss3("Bind index",key,"is out of range.");
    return n;
  };

  /**
     If stmt._isLocked is truthy, this throws an exception
     complaining that the 2nd argument (an operation name,
     e.g. "bind()") is not legal while the statement is "locked".
     Locking happens before an exec()-like callback is passed a
     statement, to ensure that the callback does not mutate or
     finalize the statement. If it does not throw, it returns stmt.
  */
  const affirmUnlocked = function(stmt,currentOpName){
    if(stmt._isLocked){
      toss3("Operation is illegal when statement is locked:",currentOpName);
    }
    return stmt;
  };

  /**
     Binds a single bound parameter value on the given stmt at the
     given index (numeric or named) using the given bindType (see
     the BindTypes enum) and value. Throws on error. Returns stmt on
     success.
  */
  const bindOne = function f(stmt,ndx,bindType,val){
    affirmUnlocked(affirmStmtOpen(stmt), 'bind()');
    if(!f._){
      f._tooBigInt = (v)=>toss3(
        "BigInt value is too big to store without precision loss:", v
      );
      /* Reminder: when not in BigInt mode, it's impossible for
         JS to represent a number out of the range we can bind,
         so we have no range checking. */
      f._ = {
        string: function(stmt, ndx, val, asBlob){
          const [pStr, n] = wasm.allocCString(val, true);
          const f = asBlob ? capi.sqlite3_bind_blob : capi.sqlite3_bind_text;
          return f(stmt.pointer, ndx, pStr, n, capi.SQLITE_WASM_DEALLOC);
        }
      };
    }/* static init */
    affirmSupportedBindType(val);
    ndx = affirmParamIndex(stmt,ndx);
    let rc = 0;
    switch((null===val || undefined===val) ? BindTypes.null : bindType){
        case BindTypes.null:
          rc = capi.sqlite3_bind_null(stmt.pointer, ndx);
          break;
        case BindTypes.string:
          rc = f._.string(stmt, ndx, val, false);
          break;
        case BindTypes.number: {
          let m;
          if(util.isInt32(val)) m = capi.sqlite3_bind_int;
          else if('bigint'===typeof val){
            if(!util.bigIntFits64(val)){
              f._tooBigInt(val);
            }else if(wasm.bigIntEnabled){
              m = capi.sqlite3_bind_int64;
            }else if(util.bigIntFitsDouble(val)){
              val = Number(val);
              m = capi.sqlite3_bind_double;
            }else{
              f._tooBigInt(val);
            }
          }else{ // !int32, !bigint
            val = Number(val);
            if(wasm.bigIntEnabled && Number.isInteger(val)){
              m = capi.sqlite3_bind_int64;
            }else{
              m = capi.sqlite3_bind_double;
            }
          }
          rc = m(stmt.pointer, ndx, val);
          break;
        }
        case BindTypes.boolean:
          rc = capi.sqlite3_bind_int(stmt.pointer, ndx, val ? 1 : 0);
          break;
        case BindTypes.blob: {
          if('string'===typeof val){
            rc = f._.string(stmt, ndx, val, true);
            break;
          }else if(val instanceof ArrayBuffer){
            val = new Uint8Array(val);
          }else if(!util.isBindableTypedArray(val)){
            toss3("Binding a value as a blob requires",
                  "that it be a string, Uint8Array, Int8Array, or ArrayBuffer.");
          }
          const pBlob = wasm.alloc(val.byteLength || 1);
          wasm.heap8().set(val.byteLength ? val : [0], pBlob)
          rc = capi.sqlite3_bind_blob(stmt.pointer, ndx, pBlob, val.byteLength,
                                      capi.SQLITE_WASM_DEALLOC);
          break;
        }
        default:
          console.warn("Unsupported bind() argument type:",val);
          toss3("Unsupported bind() argument type: "+(typeof val));
    }
    if(rc) DB.checkRc(stmt.db.pointer, rc);
    stmt._mayGet = false;
    return stmt;
  };

  Stmt.prototype = {
    /**
       "Finalizes" this statement. This is a no-op if the
       statement has already been finalizes. Returns
       undefined. Most methods in this class will throw if called
       after this is.
    */
    finalize: function(){
      if(this.pointer){
        affirmUnlocked(this,'finalize()');
        delete __stmtMap.get(this.db)[this.pointer];
        capi.sqlite3_finalize(this.pointer);
        __ptrMap.delete(this);
        delete this._mayGet;
        delete this.columnCount;
        delete this.parameterCount;
        delete this.db;
        delete this._isLocked;
      }
    },
    /** Clears all bound values. Returns this object.
        Throws if this statement has been finalized. */
    clearBindings: function(){
      affirmUnlocked(affirmStmtOpen(this), 'clearBindings()')
      capi.sqlite3_clear_bindings(this.pointer);
      this._mayGet = false;
      return this;
    },
    /**
       Resets this statement so that it may be step()ed again
       from the beginning. Returns this object. Throws if this
       statement has been finalized.

       If passed a truthy argument then this.clearBindings() is
       also called, otherwise any existing bindings, along with
       any memory allocated for them, are retained.
    */
    reset: function(alsoClearBinds){
      affirmUnlocked(this,'reset()');
      if(alsoClearBinds) this.clearBindings();
      capi.sqlite3_reset(affirmStmtOpen(this).pointer);
      this._mayGet = false;
      return this;
    },
    /**
       Binds one or more values to its bindable parameters. It
       accepts 1 or 2 arguments:

       If passed a single argument, it must be either an array, an
       object, or a value of a bindable type (see below).

       If passed 2 arguments, the first one is the 1-based bind
       index or bindable parameter name and the second one must be
       a value of a bindable type.

       Bindable value types:

       - null is bound as NULL.

       - undefined as a standalone value is a no-op intended to
         simplify certain client-side use cases: passing undefined as
         a value to this function will not actually bind anything and
         this function will skip confirmation that binding is even
         legal. (Those semantics simplify certain client-side uses.)
         Conversely, a value of undefined as an array or object
         property when binding an array/object (see below) is treated
         the same as null.

       - Numbers are bound as either doubles or integers: doubles if
         they are larger than 32 bits, else double or int32, depending
         on whether they have a fractional part. Booleans are bound as
         integer 0 or 1. It is not expected the distinction of binding
         doubles which have no fractional parts is integers is
         significant for the majority of clients due to sqlite3's data
         typing model. If [BigInt] support is enabled then this
         routine will bind BigInt values as 64-bit integers if they'll
         fit in 64 bits. If that support disabled, it will store the
         BigInt as an int32 or a double if it can do so without loss
         of precision. If the BigInt is _too BigInt_ then it will
         throw.

       - Strings are bound as strings (use bindAsBlob() to force
         blob binding).

       - Uint8Array, Int8Array, and ArrayBuffer instances are bound as
         blobs.

       If passed an array, each element of the array is bound at
       the parameter index equal to the array index plus 1
       (because arrays are 0-based but binding is 1-based).

       If passed an object, each object key is treated as a
       bindable parameter name. The object keys _must_ match any
       bindable parameter names, including any `$`, `@`, or `:`
       prefix. Because `$` is a legal identifier chararacter in
       JavaScript, that is the suggested prefix for bindable
       parameters: `stmt.bind({$a: 1, $b: 2})`.

       It returns this object on success and throws on
       error. Errors include:

       - Any bind index is out of range, a named bind parameter
       does not match, or this statement has no bindable
       parameters.

       - Any value to bind is of an unsupported type.

       - Passed no arguments or more than two.

       - The statement has been finalized.
    */
    bind: function(/*[ndx,] arg*/){
      affirmStmtOpen(this);
      let ndx, arg;
      switch(arguments.length){
          case 1: ndx = 1; arg = arguments[0]; break;
          case 2: ndx = arguments[0]; arg = arguments[1]; break;
          default: toss3("Invalid bind() arguments.");
      }
      if(undefined===arg){
        /* It might seem intuitive to bind undefined as NULL
           but this approach simplifies certain client-side
           uses when passing on arguments between 2+ levels of
           functions. */
        return this;
      }else if(!this.parameterCount){
        toss3("This statement has no bindable parameters.");
      }
      this._mayGet = false;
      if(null===arg){
        /* bind NULL */
        return bindOne(this, ndx, BindTypes.null, arg);
      }
      else if(Array.isArray(arg)){
        /* bind each entry by index */
        if(1!==arguments.length){
          toss3("When binding an array, an index argument is not permitted.");
        }
        arg.forEach((v,i)=>bindOne(this, i+1, affirmSupportedBindType(v), v));
        return this;
      }else if(arg instanceof ArrayBuffer){
        arg = new Uint8Array(arg);
      }
      if('object'===typeof arg/*null was checked above*/
              && !util.isBindableTypedArray(arg)){
        /* Treat each property of arg as a named bound parameter. */
        if(1!==arguments.length){
          toss3("When binding an object, an index argument is not permitted.");
        }
        Object.keys(arg)
          .forEach(k=>bindOne(this, k,
                              affirmSupportedBindType(arg[k]),
                              arg[k]));
        return this;
      }else{
        return bindOne(this, ndx, affirmSupportedBindType(arg), arg);
      }
      toss3("Should not reach this point.");
    },
    /**
       Special case of bind() which binds the given value using the
       BLOB binding mechanism instead of the default selected one for
       the value. The ndx may be a numbered or named bind index. The
       value must be of type string, null/undefined (both get treated
       as null), or a TypedArray of a type supported by the bind()
       API. This API cannot bind numbers as blobs.

       If passed a single argument, a bind index of 1 is assumed and
       the first argument is the value.
    */
    bindAsBlob: function(ndx,arg){
      affirmStmtOpen(this);
      if(1===arguments.length){
        arg = ndx;
        ndx = 1;
      }
      const t = affirmSupportedBindType(arg);
      if(BindTypes.string !== t && BindTypes.blob !== t
         && BindTypes.null !== t){
        toss3("Invalid value type for bindAsBlob()");
      }
      return bindOne(this, ndx, BindTypes.blob, arg);
    },
    /**
       Steps the statement one time. If the result indicates that a
       row of data is available, a truthy value is returned.
       If no row of data is available, a falsy
       value is returned.  Throws on error.
    */
    step: function(){
      affirmUnlocked(this, 'step()');
      const rc = capi.sqlite3_step(affirmStmtOpen(this).pointer);
      switch(rc){
          case capi.SQLITE_DONE: return this._mayGet = false;
          case capi.SQLITE_ROW: return this._mayGet = true;
          default:
            this._mayGet = false;
            console.warn("sqlite3_step() rc=",rc,
                         capi.sqlite3_js_rc_str(rc),
                         "SQL =", capi.sqlite3_sql(this.pointer));
            DB.checkRc(this.db.pointer, rc);
      }
    },
    /**
       Functions exactly like step() except that...

       1) On success, it calls this.reset() and returns this object.
       2) On error, it throws and does not call reset().

       This is intended to simplify constructs like:

       ```
       for(...) {
         stmt.bind(...).stepReset();
       }
       ```

       Note that the reset() call makes it illegal to call this.get()
       after the step.
    */
    stepReset: function(){
      this.step();
      return this.reset();
    },
    /**
       Functions like step() except that it finalizes this statement
       immediately after stepping unless the step cannot be performed
       because the statement is locked. Throws on error, but any error
       other than the statement-is-locked case will also trigger
       finalization of this statement.

       On success, it returns true if the step indicated that a row of
       data was available, else it returns false.

       This is intended to simplify use cases such as:

       ```
       aDb.prepare("insert into foo(a) values(?)").bind(123).stepFinalize();
       ```
    */
    stepFinalize: function(){
      const rc = this.step();
      this.finalize();
      return rc;
    },
    /**
       Fetches the value from the given 0-based column index of
       the current data row, throwing if index is out of range.

       Requires that step() has just returned a truthy value, else
       an exception is thrown.

       By default it will determine the data type of the result
       automatically. If passed a second arugment, it must be one
       of the enumeration values for sqlite3 types, which are
       defined as members of the sqlite3 module: SQLITE_INTEGER,
       SQLITE_FLOAT, SQLITE_TEXT, SQLITE_BLOB. Any other value,
       except for undefined, will trigger an exception. Passing
       undefined is the same as not passing a value. It is legal
       to, e.g., fetch an integer value as a string, in which case
       sqlite3 will convert the value to a string.

       If ndx is an array, this function behaves a differently: it
       assigns the indexes of the array, from 0 to the number of
       result columns, to the values of the corresponding column,
       and returns that array.

       If ndx is a plain object, this function behaves even
       differentlier: it assigns the properties of the object to
       the values of their corresponding result columns.

       Blobs are returned as Uint8Array instances.

       Potential TODO: add type ID SQLITE_JSON, which fetches the
       result as a string and passes it (if it's not null) to
       JSON.parse(), returning the result of that. Until then,
       getJSON() can be used for that.
    */
    get: function(ndx,asType){
      if(!affirmStmtOpen(this)._mayGet){
        toss3("Stmt.step() has not (recently) returned true.");
      }
      if(Array.isArray(ndx)){
        let i = 0;
        while(i<this.columnCount){
          ndx[i] = this.get(i++);
        }
        return ndx;
      }else if(ndx && 'object'===typeof ndx){
        let i = 0;
        while(i<this.columnCount){
          ndx[capi.sqlite3_column_name(this.pointer,i)] = this.get(i++);
        }
        return ndx;
      }
      affirmColIndex(this, ndx);
      switch(undefined===asType
             ? capi.sqlite3_column_type(this.pointer, ndx)
             : asType){
          case capi.SQLITE_NULL: return null;
          case capi.SQLITE_INTEGER:{
            if(wasm.bigIntEnabled){
              const rc = capi.sqlite3_column_int64(this.pointer, ndx);
              if(rc>=Number.MIN_SAFE_INTEGER && rc<=Number.MAX_SAFE_INTEGER){
                /* Coerce "normal" number ranges to normal number values,
                   and only return BigInt-type values for numbers out of this
                   range. */
                return Number(rc).valueOf();
              }
              return rc;
            }else{
              const rc = capi.sqlite3_column_double(this.pointer, ndx);
              if(rc>Number.MAX_SAFE_INTEGER || rc<Number.MIN_SAFE_INTEGER){
                /* Throwing here is arguable but, since we're explicitly
                   extracting an SQLITE_INTEGER-type value, it seems fair to throw
                   if the extracted number is out of range for that type.
                   This policy may be laxened to simply pass on the number and
                   hope for the best, as the C API would do. */
                toss3("Integer is out of range for JS integer range: "+rc);
              }
              //console.log("get integer rc=",rc,isInt32(rc));
              return util.isInt32(rc) ? (rc | 0) : rc;
            }
          }
          case capi.SQLITE_FLOAT:
            return capi.sqlite3_column_double(this.pointer, ndx);
          case capi.SQLITE_TEXT:
            return capi.sqlite3_column_text(this.pointer, ndx);
          case capi.SQLITE_BLOB: {
            const n = capi.sqlite3_column_bytes(this.pointer, ndx),
                  ptr = capi.sqlite3_column_blob(this.pointer, ndx),
                  rc = new Uint8Array(n);
            //heap = n ? wasm.heap8() : false;
            if(n) rc.set(wasm.heap8u().slice(ptr, ptr+n), 0);
            //for(let i = 0; i < n; ++i) rc[i] = heap[ptr + i];
            if(n && this.db._blobXfer instanceof Array){
              /* This is an optimization soley for the
                 Worker-based API. These values will be
                 transfered to the main thread directly
                 instead of being copied. */
              this.db._blobXfer.push(rc.buffer);
            }
            return rc;
          }
          default: toss3("Don't know how to translate",
                         "type of result column #"+ndx+".");
      }
      toss3("Not reached.");
    },
    /** Equivalent to get(ndx) but coerces the result to an
        integer. */
    getInt: function(ndx){return this.get(ndx,capi.SQLITE_INTEGER)},
    /** Equivalent to get(ndx) but coerces the result to a
        float. */
    getFloat: function(ndx){return this.get(ndx,capi.SQLITE_FLOAT)},
    /** Equivalent to get(ndx) but coerces the result to a
        string. */
    getString: function(ndx){return this.get(ndx,capi.SQLITE_TEXT)},
    /** Equivalent to get(ndx) but coerces the result to a
        Uint8Array. */
    getBlob: function(ndx){return this.get(ndx,capi.SQLITE_BLOB)},
    /**
       A convenience wrapper around get() which fetches the value
       as a string and then, if it is not null, passes it to
       JSON.parse(), returning that result. Throws if parsing
       fails. If the result is null, null is returned. An empty
       string, on the other hand, will trigger an exception.
    */
    getJSON: function(ndx){
      const s = this.get(ndx, capi.SQLITE_STRING);
      return null===s ? s : JSON.parse(s);
    },
    // Design note: the only reason most of these getters have a 'get'
    // prefix is for consistency with getVALUE_TYPE().  The latter
    // arguably really need that prefix for API readability and the
    // rest arguably don't, but consistency is a powerful thing.
    /**
       Returns the result column name of the given index, or
       throws if index is out of bounds or this statement has been
       finalized. This can be used without having run step()
       first.
    */
    getColumnName: function(ndx){
      return capi.sqlite3_column_name(
        affirmColIndex(affirmStmtOpen(this),ndx).pointer, ndx
      );
    },
    /**
       If this statement potentially has result columns, this
       function returns an array of all such names. If passed an
       array, it is used as the target and all names are appended
       to it. Returns the target array. Throws if this statement
       cannot have result columns. This object's columnCount member
       holds the number of columns.
    */
    getColumnNames: function(tgt=[]){
      affirmColIndex(affirmStmtOpen(this),0);
      for(let i = 0; i < this.columnCount; ++i){
        tgt.push(capi.sqlite3_column_name(this.pointer, i));
      }
      return tgt;
    },
    /**
       If this statement has named bindable parameters and the
       given name matches one, its 1-based bind index is
       returned. If no match is found, 0 is returned. If it has no
       bindable parameters, the undefined value is returned.
    */
    getParamIndex: function(name){
      return (affirmStmtOpen(this).parameterCount
              ? capi.sqlite3_bind_parameter_index(this.pointer, name)
              : undefined);
    }
  }/*Stmt.prototype*/;

  {/* Add the `pointer` property to DB and Stmt. */
    const prop = {
      enumerable: true,
      get: function(){return __ptrMap.get(this)},
      set: ()=>toss3("The pointer property is read-only.")
    }
    Object.defineProperty(Stmt.prototype, 'pointer', prop);
    Object.defineProperty(DB.prototype, 'pointer', prop);
  }

  /** The OO API's public namespace. */
  sqlite3.oo1 = {
    DB,
    Stmt
  }/*oo1 object*/;

  if(util.isUIThread()){
    /**
       Functionally equivalent to DB(storageName,'c','kvvfs') except
       that it throws if the given storage name is not one of 'local'
       or 'session'.
    */
    sqlite3.oo1.JsStorageDb = function(storageName='session'){
      if('session'!==storageName && 'local'!==storageName){
        toss3("JsStorageDb db name must be one of 'session' or 'local'.");
      }
      dbCtorHelper.call(this, {
        filename: storageName,
        flags: 'c',
        vfs: "kvvfs"
      });
    };
    const jdb = sqlite3.oo1.JsStorageDb;
    jdb.prototype = Object.create(DB.prototype);
    /** Equivalent to sqlite3_js_kvvfs_clear(). */
    jdb.clearStorage = capi.sqlite3_js_kvvfs_clear;
    /**
       Clears this database instance's storage or throws if this
       instance has been closed. Returns the number of
       database blocks which were cleaned up.
    */
    jdb.prototype.clearStorage = function(){
      return jdb.clearStorage(affirmDbOpen(this).filename);
    };
    /** Equivalent to sqlite3_js_kvvfs_size(). */
    jdb.storageSize = capi.sqlite3_js_kvvfs_size;
    /**
       Returns the _approximate_ number of bytes this database takes
       up in its storage or throws if this instance has been closed.
    */
    jdb.prototype.storageSize = function(){
      return jdb.storageSize(affirmDbOpen(this).filename);
    };
  }/*main-window-only bits*/

});

Added ext/wasm/api/sqlite3-api-prologue.js.































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
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
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
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
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
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
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
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
  2022-05-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 is intended to be combined at build-time with other
  related code, most notably a header and footer which wraps this
  whole file into an Emscripten Module.postRun() handler. The sqlite3
  JS API has no hard requirements on Emscripten and does not expose
  any Emscripten APIs to clients. It is structured such that its build
  can be tweaked to include it in arbitrary WASM environments which
  can supply the necessary underlying features (e.g. a POSIX file I/O
  layer).

  Main project home page: https://sqlite.org

  Documentation home page: https://sqlite.org/wasm
*/

/**
   sqlite3ApiBootstrap() is the only global symbol persistently
   exposed by this API. It is intended to be called one time at the
   end of the API amalgamation process, passed configuration details
   for the current environment, and then optionally be removed from
   the global object using `delete self.sqlite3ApiBootstrap`.

   This function is not intended for client-level use. It is intended
   for use in creating bundles configured for specific WASM
   environments.

   This function expects a configuration object, intended to abstract
   away details specific to any given WASM environment, primarily so
   that it can be used without any _direct_ dependency on
   Emscripten. (Note the default values for the config object!) The
   config object is only honored the first time this is
   called. Subsequent calls ignore the argument and return the same
   (configured) object which gets initialized by the first call.  This
   function will throw if any of the required config options are
   missing.

   The config object properties include:

   - `exports`[^1]: the "exports" object for the current WASM
     environment. In an Emscripten-based build, this should be set to
     `Module['asm']`.

   - `memory`[^1]: optional WebAssembly.Memory object, defaulting to
     `exports.memory`. In Emscripten environments this should be set
     to `Module.wasmMemory` if the build uses `-sIMPORT_MEMORY`, or be
     left undefined/falsy to default to `exports.memory` when using
     WASM-exported memory.

   - `bigIntEnabled`: true if BigInt support is enabled. Defaults to
     true if `self.BigInt64Array` is available, else false. Some APIs
     will throw exceptions if called without BigInt support, as BigInt
     is required for marshalling C-side int64 into and out of JS.
     (Sidebar: it is technically possible to add int64 support via
     marshalling of int32 pairs, but doing so is unduly invasive.)

   - `allocExportName`: the name of the function, in `exports`, of the
     `malloc(3)`-compatible routine for the WASM environment. Defaults
     to `"sqlite3_malloc"`. Beware that using any allocator other than
     sqlite3_malloc() may require care in certain client-side code
     regarding which allocator is uses. Notably, sqlite3_deserialize()
     and sqlite3_serialize() can only safely use memory from different
     allocators under very specific conditions. The canonical builds
     of this API guaranty that `sqlite3_malloc()` is the JS-side
     allocator implementation.

   - `deallocExportName`: the name of the function, in `exports`, of
     the `free(3)`-compatible routine for the WASM
     environment. Defaults to `"sqlite3_free"`.

   - `reallocExportName`: the name of the function, in `exports`, of
     the `realloc(3)`-compatible routine for the WASM
     environment. Defaults to `"sqlite3_realloc"`.

   - `wasmfsOpfsDir`[^1]: As of 2022-12-17, this feature does not
     currently work due to incompatible Emscripten-side changes made
     in the WASMFS+OPFS combination. This option is currently ignored.

   [^1] = This property may optionally be a function, in which case this
          function re-assigns calls that function to fetch the value,
          enabling delayed evaluation.

   The returned object is the top-level sqlite3 namespace object.

*/
'use strict';
self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
  apiConfig = (self.sqlite3ApiConfig || sqlite3ApiBootstrap.defaultConfig)
){
  if(sqlite3ApiBootstrap.sqlite3){ /* already initalized */
    console.warn("sqlite3ApiBootstrap() called multiple times.",
                 "Config and external initializers are ignored on calls after the first.");
    return sqlite3ApiBootstrap.sqlite3;
  }
  const config = Object.assign(Object.create(null),{
    exports: undefined,
    memory: undefined,
    bigIntEnabled: (()=>{
      if('undefined'!==typeof Module){
        /* Emscripten module will contain HEAPU64 when built with
           -sWASM_BIGINT=1, else it will not. */
        return !!Module.HEAPU64;
      }
      return !!self.BigInt64Array;
    })(),
    wasmfsOpfsDir: '/opfs',
    /**
       useStdAlloc is just for testing an allocator discrepancy. The
       docs guarantee that this is false in the canonical builds. For
       99% of purposes it doesn't matter which allocators we use, but
       it becomes significant with, e.g., sqlite3_deserialize()
       and certain wasm.xWrap.resultAdapter()s.
    */
    useStdAlloc: false
  }, apiConfig || {});

  Object.assign(config, {
    allocExportName: config.useStdAlloc ? 'malloc' : 'sqlite3_malloc',
    deallocExportName: config.useStdAlloc ? 'free' : 'sqlite3_free',
    reallocExportName: config.useStdAlloc ? 'realloc' : 'sqlite3_realloc'
  }, config);

  [
    // If any of these config options are functions, replace them with
    // the result of calling that function...
    'exports', 'memory', 'wasmfsOpfsDir'
  ].forEach((k)=>{
    if('function' === typeof config[k]){
      config[k] = config[k]();
    }
  });
  config.wasmOpfsDir =
    /* 2022-12-17: WASMFS+OPFS can no longer be activated from the
       main thread (aborts via a failed assert() if it's attempted),
       which eliminates any(?) benefit to supporting it. */  false;

  /**
      The main sqlite3 binding API gets installed into this object,
      mimicking the C API as closely as we can. The numerous members
      names with prefixes 'sqlite3_' and 'SQLITE_' behave, insofar as
      possible, identically to the C-native counterparts, as documented at:

      https://www.sqlite.org/c3ref/intro.html

      A very few exceptions require an additional level of proxy
      function or may otherwise require special attention in the WASM
      environment, and all such cases are documented somewhere below
      in this file or in sqlite3-api-glue.js. capi members which are
      not documented are installed as 1-to-1 proxies for their
      C-side counterparts.
  */
  const capi = Object.create(null);
  /**
     Holds state which are specific to the WASM-related
     infrastructure and glue code.

     Note that a number of members of this object are injected
     dynamically after the api object is fully constructed, so
     not all are documented in this file.
  */
  const wasm = Object.create(null);

  /** Internal helper for SQLite3Error ctor. */
  const __rcStr = (rc)=>{
    return (capi.sqlite3_js_rc_str && capi.sqlite3_js_rc_str(rc))
           || ("Unknown result code #"+rc);
  };

  /** Internal helper for SQLite3Error ctor. */
  const __isInt = (n)=>'number'===typeof n && n===(n | 0);

  /**
     An Error subclass specifically for reporting DB-level errors and
     enabling clients to unambiguously identify such exceptions.
     The C-level APIs never throw, but some of the higher-level
     C-style APIs do and the object-oriented APIs use exceptions
     exclusively to report errors.
  */
  class SQLite3Error extends Error {
    /**
       Constructs this object with a message depending on its arguments:

       If its first argument is an integer, it is assumed to be
       an SQLITE_... result code and it is passed to
       sqlite3.capi.sqlite3_js_rc_str() to stringify it.

       If called with exactly 2 arguments and the 2nd is an object,
       that object is treated as the 2nd argument to the parent
       constructor.

       The exception's message is created by concatenating its
       arguments with a space between each, except for the
       two-args-with-an-objec form and that the first argument will
       get coerced to a string, as described above, if it's an
       integer.

       If passed an integer first argument, the error object's
       `resultCode` member will be set to the given integer value,
       else it will be set to capi.SQLITE_ERROR.
    */
    constructor(...args){
      let rc;
      if(args.length){
        if(__isInt(args[0])){
          rc = args[0];
          if(1===args.length){
            super(__rcStr(args[0]));
          }else{
            const rcStr = __rcStr(rc);
            if('object'===typeof args[1]){
              super(rcStr,args[1]);
            }else{
              args[0] = rcStr+':';
              super(args.join(' '));
            }
          }
        }else{
          if(2===args.length && 'object'===typeof args[1]){
            super(...args);
          }else{
            super(args.join(' '));
          }
        }
      }
      this.resultCode = rc || capi.SQLITE_ERROR;
      this.name = 'SQLite3Error';
    }
  };

  /**
     Functionally equivalent to the SQLite3Error constructor but may
     be used as part of an expression, e.g.:

     ```
     return someFunction(x) || SQLite3Error.toss(...);
     ```
  */
  SQLite3Error.toss = (...args)=>{
    throw new SQLite3Error(...args);
  };
  const toss3 = SQLite3Error.toss;

  if(config.wasmfsOpfsDir && !/^\/[^/]+$/.test(config.wasmfsOpfsDir)){
    toss3("config.wasmfsOpfsDir must be falsy or in the form '/dir-name'.");
  }

  /**
     Returns true if n is a 32-bit (signed) integer, else
     false. This is used for determining when we need to switch to
     double-type DB operations for integer values in order to keep
     more precision.
  */
  const isInt32 = (n)=>{
    return ('bigint'!==typeof n /*TypeError: can't convert BigInt to number*/)
      && !!(n===(n|0) && n<=2147483647 && n>=-2147483648);
  };
  /**
     Returns true if the given BigInt value is small enough to fit
     into an int64 value, else false.
  */
  const bigIntFits64 = function f(b){
    if(!f._max){
      f._max = BigInt("0x7fffffffffffffff");
      f._min = ~f._max;
    }
    return b >= f._min && b <= f._max;
  };

  /**
     Returns true if the given BigInt value is small enough to fit
     into an int32, else false.
  */
  const bigIntFits32 = (b)=>(b >= (-0x7fffffffn - 1n) && b <= 0x7fffffffn);

  /**
     Returns true if the given BigInt value is small enough to fit
     into a double value without loss of precision, else false.
  */
  const bigIntFitsDouble = function f(b){
    if(!f._min){
      f._min = Number.MIN_SAFE_INTEGER;
      f._max = Number.MAX_SAFE_INTEGER;
    }
    return b >= f._min && b <= f._max;
  };

  /** Returns v if v appears to be a TypedArray, else false. */
  const isTypedArray = (v)=>{
    return (v && v.constructor && isInt32(v.constructor.BYTES_PER_ELEMENT)) ? v : false;
  };


  /** Internal helper to use in operations which need to distinguish
      between TypedArrays which are backed by a SharedArrayBuffer
      from those which are not. */
  const __SAB = ('undefined'===typeof SharedArrayBuffer)
        ? function(){} : SharedArrayBuffer;
  /** Returns true if the given TypedArray object is backed by a
      SharedArrayBuffer, else false. */
  const isSharedTypedArray = (aTypedArray)=>(aTypedArray.buffer instanceof __SAB);

  /**
     Returns either aTypedArray.slice(begin,end) (if
     aTypedArray.buffer is a SharedArrayBuffer) or
     aTypedArray.subarray(begin,end) (if it's not).

     This distinction is important for APIs which don't like to
     work on SABs, e.g. TextDecoder, and possibly for our
     own APIs which work on memory ranges which "might" be
     modified by other threads while they're working.
  */
  const typedArrayPart = (aTypedArray, begin, end)=>{
    return isSharedTypedArray(aTypedArray)
      ? aTypedArray.slice(begin, end)
      : aTypedArray.subarray(begin, end);
  };

  /**
     Returns true if v appears to be one of our bind()-able TypedArray
     types: Uint8Array or Int8Array or ArrayBuffer. Support for
     TypedArrays with element sizes >1 is a potential TODO just
     waiting on a use case to justify them. Until then, their `buffer`
     property can be used to pass them as an ArrayBuffer. If it's not
     a bindable array type, a falsy value is returned.
  */
  const isBindableTypedArray = (v)=>{
    return v && (v instanceof Uint8Array
                 || v instanceof Int8Array
                 || v instanceof ArrayBuffer);
  };

  /**
     Returns true if v appears to be one of the TypedArray types
     which is legal for holding SQL code (as opposed to binary blobs).

     Currently this is the same as isBindableTypedArray() but it
     seems likely that we'll eventually want to add Uint32Array
     and friends to the isBindableTypedArray() list but not to the
     isSQLableTypedArray() list.
  */
  const isSQLableTypedArray = (v)=>{
    return v && (v instanceof Uint8Array
                 || v instanceof Int8Array
                 || v instanceof ArrayBuffer);
  };

  /** Returns true if isBindableTypedArray(v) does, else throws with a message
      that v is not a supported TypedArray value. */
  const affirmBindableTypedArray = (v)=>{
    return isBindableTypedArray(v)
      || toss3("Value is not of a supported TypedArray type.");
  };

  const utf8Decoder = new TextDecoder('utf-8');

  /**
     Uses TextDecoder to decode the given half-open range of the
     given TypedArray to a string. This differs from a simple
     call to TextDecoder in that it accounts for whether the
     first argument is backed by a SharedArrayBuffer or not,
     and can work more efficiently if it's not (TextDecoder
     refuses to act upon an SAB).
  */
  const typedArrayToString = function(typedArray, begin, end){
    return utf8Decoder.decode(typedArrayPart(typedArray, begin,end));
  };

  /**
     If v is-a Array, its join("") result is returned.  If
     isSQLableTypedArray(v) is true then typedArrayToString(v) is
     returned. If it looks like a WASM pointer, wasm.cstrToJs(v) is
     returned. Else v is returned as-is.
  */
  const flexibleString = function(v){
    if(isSQLableTypedArray(v)){
      return typedArrayToString(
        (v instanceof ArrayBuffer) ? new Uint8Array(v) : v
      );
    }
    else if(Array.isArray(v)) return v.join("");
    else if(wasm.isPtr(v)) v = wasm.cstrToJs(v);
    return v;
  };

  /**
     An Error subclass specifically for reporting Wasm-level malloc()
     failure and enabling clients to unambiguously identify such
     exceptions.
  */
  class WasmAllocError extends Error {
    /**
       If called with 2 arguments and the 2nd one is an object, it
       behaves like the Error constructor, else it concatenates all
       arguments together with a single space between each to
       construct an error message string. As a special case, if
       called with no arguments then it uses a default error
       message.
    */
    constructor(...args){
      if(2===args.length && 'object'===typeof args[1]){
        super(...args);
      }else if(args.length){
        super(args.join(' '));
      }else{
        super("Allocation failed.");
      }
      this.resultCode = capi.SQLITE_NOMEM;
      this.name = 'WasmAllocError';
    }
  };
  /**
     Functionally equivalent to the WasmAllocError constructor but may
     be used as part of an expression, e.g.:

     ```
     return someAllocatingFunction(x) || WasmAllocError.toss(...);
     ```
  */
  WasmAllocError.toss = (...args)=>{
    throw new WasmAllocError(...args);
  };

  Object.assign(capi, {
    /**
       sqlite3_bind_blob() works exactly like its C counterpart unless
       its 3rd argument is one of:

       - JS string: the 3rd argument is converted to a C string, the
         4th argument is ignored, and the C-string's length is used
         in its place.

       - Array: converted to a string as defined for "flexible
         strings" and then it's treated as a JS string.

       - Int8Array or Uint8Array: wasm.allocFromTypedArray() is used to
         conver the memory to the WASM heap. If the 4th argument is
         0 or greater, it is used as-is, otherwise the array's byteLength
         value is used. This is an exception to the C API's undefined
         behavior for a negative 4th argument, but results are undefined
         if the given 4th argument value is greater than the byteLength
         of the input array.

       - If it's an ArrayBuffer, it gets wrapped in a Uint8Array and
         treated as that type.

       In all of those cases, the final argument (destructor) is
       ignored and capi.SQLITE_WASM_DEALLOC is assumed.

       A 3rd argument of `null` is treated as if it were a WASM pointer
       of 0.

       If the 3rd argument is neither a WASM pointer nor one of the
       above-described types, capi.SQLITE_MISUSE is returned.

       The first argument may be either an `sqlite3_stmt*` WASM
       pointer or an sqlite3.oo1.Stmt instance.

       For consistency with the C API, it requires the same number of
       arguments. It returns capi.SQLITE_MISUSE if passed any other
       argument count.
    */
    sqlite3_bind_blob: undefined/*installed later*/,

    /**
       sqlite3_bind_text() works exactly like its C counterpart unless
       its 3rd argument is one of:

       - JS string: the 3rd argument is converted to a C string, the
         4th argument is ignored, and the C-string's length is used
         in its place.

       - Array: converted to a string as defined for "flexible
         strings". The 4th argument is ignored and a value of -1
         is assumed.

       - Int8Array or Uint8Array: is assumed to contain UTF-8 text, is
         converted to a string. The 4th argument is ignored, replaced
         by the array's byteLength value.

       - If it's an ArrayBuffer, it gets wrapped in a Uint8Array and
         treated as that type.

       In each of those cases, the final argument (text destructor) is
       ignored and capi.SQLITE_WASM_DEALLOC is assumed.

       A 3rd argument of `null` is treated as if it were a WASM pointer
       of 0.

       If the 3rd argument is neither a WASM pointer nor one of the
       above-described types, capi.SQLITE_MISUSE is returned.

       The first argument may be either an `sqlite3_stmt*` WASM
       pointer or an sqlite3.oo1.Stmt instance.

       For consistency with the C API, it requires the same number of
       arguments. It returns capi.SQLITE_MISUSE if passed any other
       argument count.

       If client code needs to bind partial strings, it needs to
       either parcel the string up before passing it in here or it
       must pass in a WASM pointer for the 3rd argument and a valid
       4th-argument value, taking care not to pass a value which
       truncates a multi-byte UTF-8 character. When passing
       WASM-format strings, it is important that the final argument be
       valid or unexpected content can result can result, or even a
       crash if the application reads past the WASM heap bounds.
    */
    sqlite3_bind_text: undefined/*installed later*/,

    /**
       sqlite3_create_function_v2() differs from its native
       counterpart only in the following ways:

       1) The fourth argument (`eTextRep`) argument must not specify
       any encoding other than sqlite3.SQLITE_UTF8. The JS API does not
       currently support any other encoding and likely never
       will. This function does not replace that argument on its own
       because it may contain other flags. As a special case, if
       the bottom 4 bits of that argument are 0, SQLITE_UTF8 is
       assumed.

       2) Any of the four final arguments may be either WASM pointers
       (assumed to be function pointers) or JS Functions. In the
       latter case, each gets bound to WASM using
       sqlite3.capi.wasm.installFunction() and that wrapper is passed
       on to the native implementation.

       For consistency with the C API, it requires the same number of
       arguments. It returns capi.SQLITE_MISUSE if passed any other
       argument count.

       The semantics of JS functions are:

       xFunc: is passed `(pCtx, ...values)`. Its return value becomes
       the new SQL function's result.

       xStep: is passed `(pCtx, ...values)`. Its return value is
       ignored.

       xFinal: is passed `(pCtx)`. Its return value becomes the new
       aggregate SQL function's result.

       xDestroy: is passed `(void*)`. Its return value is ignored. The
       pointer passed to it is the one from the 5th argument to
       sqlite3_create_function_v2().

       Note that:

       - `pCtx` in the above descriptions is a `sqlite3_context*`. At
         least 99 times out of a hundred, that initial argument will
         be irrelevant for JS UDF bindings, but it needs to be there
         so that the cases where it _is_ relevant, in particular with
         window and aggregate functions, have full access to the
         lower-level sqlite3 APIs.

       - When wrapping JS functions, the remaining arguments are passd
         to them as positional arguments, not as an array of
         arguments, because that allows callback definitions to be
         more JS-idiomatic than C-like. For example `(pCtx,a,b)=>a+b`
         is more intuitive and legible than
         `(pCtx,args)=>args[0]+args[1]`. For cases where an array of
         arguments would be more convenient, the callbacks simply need
         to be declared like `(pCtx,...args)=>{...}`, in which case
         `args` will be an array.

       - If a JS wrapper throws, it gets translated to
         sqlite3_result_error() or sqlite3_result_error_nomem(),
         depending on whether the exception is an
         sqlite3.WasmAllocError object or not.

       - When passing on WASM function pointers, arguments are _not_
         converted or reformulated. They are passed on as-is in raw
         pointer form using their native C signatures. Only JS
         functions passed in to this routine, and thus wrapped by this
         routine, get automatic conversions of arguments and result
         values. The routines which perform those conversions are
         exposed for client-side use as
         sqlite3_create_function_v2.convertUdfArgs() and
         sqlite3_create_function_v2.setUdfResult(). sqlite3_create_function()
         and sqlite3_create_window_function() have those same methods.

       For xFunc(), xStep(), and xFinal():

       - When called from SQL, arguments to the UDF, and its result,
         will be converted between JS and SQL with as much fidelity as
         is feasible, triggering an exception if a type conversion
         cannot be determined. Some freedom is afforded to numeric
         conversions due to friction between the JS and C worlds:
         integers which are larger than 32 bits may be treated as
         doubles or BigInts.

       If any JS-side bound functions throw, those exceptions are
       intercepted and converted to database-side errors with the
       exception of xDestroy(): any exception from it is ignored,
       possibly generating a console.error() message.  Destructors
       must not throw.

       Once installed, there is currently no way to uninstall the
       automatically-converted WASM-bound JS functions from WASM. They
       can be uninstalled from the database as documented in the C
       API, but this wrapper currently has no infrastructure in place
       to also free the WASM-bound JS wrappers, effectively resulting
       in a memory leak if the client uninstalls the UDF. Improving that
       is a potential TODO, but removing client-installed UDFs is rare
       in practice. If this factor is relevant for a given client,
       they can create WASM-bound JS functions themselves, hold on to their
       pointers, and pass the pointers in to here. Later on, they can
       free those pointers (using `wasm.uninstallFunction()` or
       equivalent).

       C reference: https://www.sqlite.org/c3ref/create_function.html

       Maintenance reminder: the ability to add new
       WASM-accessible functions to the runtime requires that the
       WASM build is compiled with emcc's `-sALLOW_TABLE_GROWTH`
       flag.
    */
    sqlite3_create_function_v2: (
      pDb, funcName, nArg, eTextRep, pApp,
      xFunc, xStep, xFinal, xDestroy
    )=>{/*installed later*/},
    /**
       Equivalent to passing the same arguments to
       sqlite3_create_function_v2(), with 0 as the final argument.
    */
    sqlite3_create_function: (
      pDb, funcName, nArg, eTextRep, pApp,
      xFunc, xStep, xFinal
    )=>{/*installed later*/},
    /**
       The sqlite3_create_window_function() JS wrapper differs from
       its native implementation in the exact same way that
       sqlite3_create_function_v2() does. The additional function,
       xInverse(), is treated identically to xStep() by the wrapping
       layer.
    */
    sqlite3_create_window_function: (
      pDb, funcName, nArg, eTextRep, pApp,
      xStep, xFinal, xValue, xInverse, xDestroy
    )=>{/*installed later*/},
    /**
       The sqlite3_prepare_v3() binding handles two different uses
       with differing JS/WASM semantics:

       1) sqlite3_prepare_v3(pDb, sqlString, -1, prepFlags, ppStmt , null)

       2) sqlite3_prepare_v3(pDb, sqlPointer, sqlByteLen, prepFlags, ppStmt, sqlPointerToPointer)

       Note that the SQL length argument (the 3rd argument) must, for
       usage (1), always be negative because it must be a byte length
       and that value is expensive to calculate from JS (where only
       the character length of strings is readily available). It is
       retained in this API's interface for code/documentation
       compatibility reasons but is currently _always_ ignored. With
       usage (2), the 3rd argument is used as-is but is is still
       critical that the C-style input string (2nd argument) be
       terminated with a 0 byte.

       In usage (1), the 2nd argument must be of type string,
       Uint8Array, Int8Array, or ArrayBuffer (all of which are assumed
       to hold SQL). If it is, this function assumes case (1) and
       calls the underyling C function with the equivalent of:

       (pDb, sqlAsString, -1, prepFlags, ppStmt, null)

       The `pzTail` argument is ignored in this case because its
       result is meaningless when a string-type value is passed
       through: the string goes through another level of internal
       conversion for WASM's sake and the result pointer would refer
       to that transient conversion's memory, not the passed-in
       string.

       If the sql argument is not a string, it must be a _pointer_ to
       a NUL-terminated string which was allocated in the WASM memory
       (e.g. using capi.wasm.alloc() or equivalent). In that case,
       the final argument may be 0/null/undefined or must be a pointer
       to which the "tail" of the compiled SQL is written, as
       documented for the C-side sqlite3_prepare_v3(). In case (2),
       the underlying C function is called with the equivalent of:

       (pDb, sqlAsPointer, sqlByteLen, prepFlags, ppStmt, pzTail)

       It returns its result and compiled statement as documented in
       the C API. Fetching the output pointers (5th and 6th
       parameters) requires using `capi.wasm.peek()` (or
       equivalent) and the `pzTail` will point to an address relative to
       the `sqlAsPointer` value.

       If passed an invalid 2nd argument type, this function will
       return SQLITE_MISUSE and sqlite3_errmsg() will contain a string
       describing the problem.

       Side-note: if given an empty string, or one which contains only
       comments or an empty SQL expression, 0 is returned but the result
       output pointer will be NULL.
    */
    sqlite3_prepare_v3: (dbPtr, sql, sqlByteLen, prepFlags,
                         stmtPtrPtr, strPtrPtr)=>{}/*installed later*/,

    /**
       Equivalent to calling sqlite3_prapare_v3() with 0 as its 4th argument.
    */
    sqlite3_prepare_v2: (dbPtr, sql, sqlByteLen,
                         stmtPtrPtr,strPtrPtr)=>{}/*installed later*/,

    /**
       This binding enables the callback argument to be a JavaScript.

       If the callback is a function, then for the duration of the
       sqlite3_exec() call, it installs a WASM-bound function which
       acts as a proxy for the given callback. That proxy will also
       perform a conversion of the callback's arguments from
       `(char**)` to JS arrays of strings. However, for API
       consistency's sake it will still honor the C-level callback
       parameter order and will call it like:

       `callback(pVoid, colCount, listOfValues, listOfColNames)`

       If the callback is not a JS function then this binding performs
       no translation of the callback, but the sql argument is still
       converted to a WASM string for the call using the
       "string:flexible" argument converter.
    */
    sqlite3_exec: (pDb, sql, callback, pVoid, pErrMsg)=>{}/*installed later*/,

    /**
       If passed a single argument which appears to be a byte-oriented
       TypedArray (Int8Array or Uint8Array), this function treats that
       TypedArray as an output target, fetches `theArray.byteLength`
       bytes of randomness, and populates the whole array with it. As
       a special case, if the array's length is 0, this function
       behaves as if it were passed (0,0). When called this way, it
       returns its argument, else it returns the `undefined` value.

       If called with any other arguments, they are passed on as-is
       to the C API. Results are undefined if passed any incompatible
       values.
     */
    sqlite3_randomness: (n, outPtr)=>{/*installed later*/},
  }/*capi*/);

  /**
     Various internal-use utilities are added here as needed. They
     are bound to an object only so that we have access to them in
     the differently-scoped steps of the API bootstrapping
     process. At the end of the API setup process, this object gets
     removed. These are NOT part of the public API.
  */
  const util = {
    affirmBindableTypedArray, flexibleString,
    bigIntFits32, bigIntFits64, bigIntFitsDouble,
    isBindableTypedArray,
    isInt32, isSQLableTypedArray, isTypedArray,
    typedArrayToString,
    isUIThread: ()=>(self.window===self && !!self.document),
    // is this true for ESM?: 'undefined'===typeof WorkerGlobalScope
    isSharedTypedArray,
    toss: function(...args){throw new Error(args.join(' '))},
    toss3,
    typedArrayPart
  };

  Object.assign(wasm, {
    /**
       Emscripten APIs have a deep-seated assumption that all pointers
       are 32 bits. We'll remain optimistic that that won't always be
       the case and will use this constant in places where we might
       otherwise use a hard-coded 4.
    */
    ptrSizeof: config.wasmPtrSizeof || 4,
    /**
       The WASM IR (Intermediate Representation) value for
       pointer-type values. It MUST refer to a value type of the
       size described by this.ptrSizeof.
    */
    ptrIR: config.wasmPtrIR || "i32",
    /**
       True if BigInt support was enabled via (e.g.) the
       Emscripten -sWASM_BIGINT flag, else false. When
       enabled, certain 64-bit sqlite3 APIs are enabled which
       are not otherwise enabled due to JS/WASM int64
       impedence mismatches.
    */
    bigIntEnabled: !!config.bigIntEnabled,
    /**
       The symbols exported by the WASM environment.
    */
    exports: config.exports
      || toss3("Missing API config.exports (WASM module exports)."),

    /**
       When Emscripten compiles with `-sIMPORT_MEMORY`, it
       initalizes the heap and imports it into wasm, as opposed to
       the other way around. In this case, the memory is not
       available via this.exports.memory.
    */
    memory: config.memory || config.exports['memory']
      || toss3("API config object requires a WebAssembly.Memory object",
              "in either config.exports.memory (exported)",
              "or config.memory (imported)."),

    /**
       The API's primary point of access to the WASM-side memory
       allocator.  Works like sqlite3_malloc() but throws a
       WasmAllocError if allocation fails. It is important that any
       code which might pass through the sqlite3 C API NOT throw and
       must instead return SQLITE_NOMEM (or equivalent, depending on
       the context).

       Very few cases in the sqlite3 JS APIs can result in
       client-defined functions propagating exceptions via the C-style
       API. Most notably, this applies to WASM-bound JS functions
       which are created directly by clients and passed on _as WASM
       function pointers_ to functions such as
       sqlite3_create_function_v2(). Such bindings created
       transparently by this API will automatically use wrappers which
       catch exceptions and convert them to appropriate error codes.

       For cases where non-throwing allocation is required, use
       this.alloc.impl(), which is direct binding of the
       underlying C-level allocator.

       Design note: this function is not named "malloc" primarily
       because Emscripten uses that name and we wanted to avoid any
       confusion early on in this code's development, when it still
       had close ties to Emscripten's glue code.
    */
    alloc: undefined/*installed later*/,

    /**
       Rarely necessary in JS code, this routine works like
       sqlite3_realloc(M,N), where M is either NULL or a pointer
       obtained from this function or this.alloc() and N is the number
       of bytes to reallocate the block to. Returns a pointer to the
       reallocated block or 0 if allocation fails.

       If M is NULL and N is positive, this behaves like
       this.alloc(N). If N is 0, it behaves like this.dealloc().
       Results are undefined if N is negative (sqlite3_realloc()
       treats that as 0, but if this code is built with a different
       allocator it may misbehave with negative values).

       Like this.alloc.impl(), this.realloc.impl() is a direct binding
       to the underlying realloc() implementation which does not throw
       exceptions, instead returning 0 on allocation error.
    */
    realloc: undefined/*installed later*/,

    /**
       The API's primary point of access to the WASM-side memory
       deallocator. Works like sqlite3_free().

       Design note: this function is not named "free" for the same
       reason that this.alloc() is not called this.malloc().
    */
    dealloc: undefined/*installed later*/

    /* Many more wasm-related APIs get installed later on. */
  }/*wasm*/);

  /**
     wasm.alloc()'s srcTypedArray.byteLength bytes,
     populates them with the values from the source
     TypedArray, and returns the pointer to that memory. The
     returned pointer must eventually be passed to
     wasm.dealloc() to clean it up.

     The argument may be a Uint8Array, Int8Array, or ArrayBuffer,
     and it throws if passed any other type.

     As a special case, to avoid further special cases where
     this is used, if srcTypedArray.byteLength is 0, it
     allocates a single byte and sets it to the value
     0. Even in such cases, calls must behave as if the
     allocated memory has exactly srcTypedArray.byteLength
     bytes.
  */
  wasm.allocFromTypedArray = function(srcTypedArray){
    if(srcTypedArray instanceof ArrayBuffer){
      srcTypedArray = new Uint8Array(srcTypedArray);
    }
    affirmBindableTypedArray(srcTypedArray);
    const pRet = wasm.alloc(srcTypedArray.byteLength || 1);
    wasm.heapForSize(srcTypedArray.constructor).set(
      srcTypedArray.byteLength ? srcTypedArray : [0], pRet
    );
    return pRet;
  };

  {
    // Set up allocators...
    const keyAlloc = config.allocExportName,
          keyDealloc = config.deallocExportName,
          keyRealloc = config.reallocExportName;
    for(const key of [keyAlloc, keyDealloc, keyRealloc]){
      const f = wasm.exports[key];
      if(!(f instanceof Function)) toss3("Missing required exports[",key,"] function.");
    }

    wasm.alloc = function f(n){
      return f.impl(n) || WasmAllocError.toss("Failed to allocate",n," bytes.");
    };
    wasm.alloc.impl = wasm.exports[keyAlloc];
    wasm.realloc = function f(m,n){
      const m2 = f.impl(m,n);
      return n ? (m2 || WasmAllocError.toss("Failed to reallocate",n," bytes.")) : 0;
    };
    wasm.realloc.impl = wasm.exports[keyRealloc];
    wasm.dealloc = wasm.exports[keyDealloc];
  }

  /**
     Reports info about compile-time options using
     sqlite3_compileoption_get() and sqlite3_compileoption_used(). It
     has several distinct uses:

     If optName is an array then it is expected to be a list of
     compilation options and this function returns an object
     which maps each such option to true or false, indicating
     whether or not the given option was included in this
     build. That object is returned.

     If optName is an object, its keys are expected to be compilation
     options and this function sets each entry to true or false,
     indicating whether the compilation option was used or not. That
     object is returned.

     If passed no arguments then it returns an object mapping
     all known compilation options to their compile-time values,
     or boolean true if they are defined with no value. This
     result, which is relatively expensive to compute, is cached
     and returned for future no-argument calls.

     In all other cases it returns true if the given option was
     active when when compiling the sqlite3 module, else false.

     Compile-time option names may optionally include their
     "SQLITE_" prefix. When it returns an object of all options,
     the prefix is elided.
  */
  wasm.compileOptionUsed = function f(optName){
    if(!arguments.length){
      if(f._result) return f._result;
      else if(!f._opt){
        f._rx = /^([^=]+)=(.+)/;
        f._rxInt = /^-?\d+$/;
        f._opt = function(opt, rv){
          const m = f._rx.exec(opt);
          rv[0] = (m ? m[1] : opt);
          rv[1] = m ? (f._rxInt.test(m[2]) ? +m[2] : m[2]) : true;
        };
      }
      const rc = {}, ov = [0,0];
      let i = 0, k;
      while((k = capi.sqlite3_compileoption_get(i++))){
        f._opt(k,ov);
        rc[ov[0]] = ov[1];
      }
      return f._result = rc;
    }else if(Array.isArray(optName)){
      const rc = {};
      optName.forEach((v)=>{
        rc[v] = capi.sqlite3_compileoption_used(v);
      });
      return rc;
    }else if('object' === typeof optName){
      Object.keys(optName).forEach((k)=> {
        optName[k] = capi.sqlite3_compileoption_used(k);
      });
      return optName;
    }
    return (
      'string'===typeof optName
    ) ? !!capi.sqlite3_compileoption_used(optName) : false;
  }/*compileOptionUsed()*/;

  /**
     sqlite3.wasm.pstack (pseudo-stack) holds a special-case
     stack-style allocator intended only for use with _small_ data of
     not more than (in total) a few kb in size, managed as if it were
     stack-based.

     It has only a single intended usage:

     ```
     const stackPos = pstack.pointer;
     try{
       const ptr = pstack.alloc(8);
       // ==> pstack.pointer === ptr
       const otherPtr = pstack.alloc(8);
       // ==> pstack.pointer === otherPtr
       ...
     }finally{
       pstack.restore(stackPos);
       // ==> pstack.pointer === stackPos
     }
     ```

     This allocator is much faster than a general-purpose one but is
     limited to usage patterns like the one shown above.

     It operates from a static range of memory which lives outside of
     space managed by Emscripten's stack-management, so does not
     collide with Emscripten-provided stack allocation APIs. The
     memory lives in the WASM heap and can be used with routines such
     as wasm.poke() and wasm.heap8u().slice().
  */
  wasm.pstack = Object.assign(Object.create(null),{
    /**
       Sets the current pstack position to the given pointer. Results
       are undefined if the passed-in value did not come from
       this.pointer.
    */
    restore: wasm.exports.sqlite3_wasm_pstack_restore,
    /**
       Attempts to allocate the given number of bytes from the
       pstack. On success, it zeroes out a block of memory of the
       given size, adjusts the pstack pointer, and returns a pointer
       to the memory. On error, throws a WasmAllocError. The
       memory must eventually be released using restore().

       If n is a string, it must be a WASM "IR" value in the set
       accepted by wasm.sizeofIR(), which is mapped to the size of
       that data type. If passed a string not in that set, it throws a
       WasmAllocError.

       This method always adjusts the given value to be a multiple
       of 8 bytes because failing to do so can lead to incorrect
       results when reading and writing 64-bit values from/to the WASM
       heap. Similarly, the returned address is always 8-byte aligned.
    */
    alloc: function(n){
      if('string'===typeof n && !(n = wasm.sizeofIR(n))){
        WasmAllocError.toss("Invalid value for pstack.alloc(",arguments[0],")");
      }
      return wasm.exports.sqlite3_wasm_pstack_alloc(n)
        || WasmAllocError.toss("Could not allocate",n,
                               "bytes from the pstack.");
    },
    /**
       alloc()'s n chunks, each sz bytes, as a single memory block and
       returns the addresses as an array of n element, each holding
       the address of one chunk.

       sz may optionally be an IR string accepted by wasm.sizeofIR().

       Throws a WasmAllocError if allocation fails.

       Example:

       ```
       const [p1, p2, p3] = wasm.pstack.allocChunks(3,4);
       ```
    */
    allocChunks: function(n,sz){
      if('string'===typeof sz && !(sz = wasm.sizeofIR(sz))){
        WasmAllocError.toss("Invalid size value for allocChunks(",arguments[1],")");
      }
      const mem = wasm.pstack.alloc(n * sz);
      const rc = [];
      let i = 0, offset = 0;
      for(; i < n; ++i, offset += sz) rc.push(mem + offset);
      return rc;
    },
    /**
       A convenience wrapper for allocChunks() which sizes each chunk
       as either 8 bytes (safePtrSize is truthy) or wasm.ptrSizeof (if
       safePtrSize is falsy).

       How it returns its result differs depending on its first
       argument: if it's 1, it returns a single pointer value. If it's
       more than 1, it returns the same as allocChunks().

       When a returned pointers will refer to a 64-bit value, e.g. a
       double or int64, and that value must be written or fetched,
       e.g. using wasm.poke() or wasm.peek(), it is
       important that the pointer in question be aligned to an 8-byte
       boundary or else it will not be fetched or written properly and
       will corrupt or read neighboring memory.

       However, when all pointers involved point to "small" data, it
       is safe to pass a falsy value to save a tiny bit of memory.
    */
    allocPtr: (n=1,safePtrSize=true)=>{
      return 1===n
        ? wasm.pstack.alloc(safePtrSize ? 8 : wasm.ptrSizeof)
        : wasm.pstack.allocChunks(n, safePtrSize ? 8 : wasm.ptrSizeof);
    }
  })/*wasm.pstack*/;
  Object.defineProperties(wasm.pstack, {
    /**
       sqlite3.wasm.pstack.pointer resolves to the current pstack
       position pointer. This value is intended _only_ to be saved
       for passing to restore(). Writing to this memory, without
       first reserving it via wasm.pstack.alloc() and friends, leads
       to undefined results.
    */
    pointer: {
      configurable: false, iterable: true, writeable: false,
      get: wasm.exports.sqlite3_wasm_pstack_ptr
      //Whether or not a setter as an alternative to restore() is
      //clearer or would just lead to confusion is unclear.
      //set: wasm.exports.sqlite3_wasm_pstack_restore
    },
    /**
       sqlite3.wasm.pstack.quota to the total number of bytes
       available in the pstack, including any space which is currently
       allocated. This value is a compile-time constant.
    */
    quota: {
      configurable: false, iterable: true, writeable: false,
      get: wasm.exports.sqlite3_wasm_pstack_quota
    },
    /**
       sqlite3.wasm.pstack.remaining resolves to the amount of space
       remaining in the pstack.
    */
    remaining: {
      configurable: false, iterable: true, writeable: false,
      get: wasm.exports.sqlite3_wasm_pstack_remaining
    }
  })/*wasm.pstack properties*/;

  capi.sqlite3_randomness = (...args)=>{
    if(1===args.length && util.isTypedArray(args[0])
      && 1===args[0].BYTES_PER_ELEMENT){
      const ta = args[0];
      if(0===ta.byteLength){
        wasm.exports.sqlite3_randomness(0,0);
        return ta;
      }
      const stack = wasm.pstack.pointer;
      try {
        let n = ta.byteLength, offset = 0;
        const r = wasm.exports.sqlite3_randomness;
        const heap = wasm.heap8u();
        const nAlloc = n < 512 ? n : 512;
        const ptr = wasm.pstack.alloc(nAlloc);
        do{
          const j = (n>nAlloc ? nAlloc : n);
          r(j, ptr);
          ta.set(typedArrayPart(heap, ptr, ptr+j), offset);
          n -= j;
          offset += j;
        } while(n > 0);
      }catch(e){
        console.error("Highly unexpected (and ignored!) "+
                      "exception in sqlite3_randomness():",e);
      }finally{
        wasm.pstack.restore(stack);
      }
      return ta;
    }
    wasm.exports.sqlite3_randomness(...args);
  };

  /** State for sqlite3_wasmfs_opfs_dir(). */
  let __wasmfsOpfsDir = undefined;
  /**
     2022-12-17: incompatible WASMFS changes have made WASMFS+OPFS
     unavailable from the main thread, which eliminates the most
     significant benefit of supporting WASMFS. This function is now a
     no-op which always returns a falsy value. Before that change,
     this function behaved as documented below (and how it will again
     if we can find a compelling reason to support it).

     If the wasm environment has a WASMFS/OPFS-backed persistent
     storage directory, its path is returned by this function. If it
     does not then it returns "" (noting that "" is a falsy value).

     The first time this is called, this function inspects the current
     environment to determine whether persistence support is available
     and, if it is, enables it (if needed).

     This function currently only recognizes the WASMFS/OPFS storage
     combination and its path refers to storage rooted in the
     Emscripten-managed virtual filesystem.
  */
  capi.sqlite3_wasmfs_opfs_dir = function(){
    if(undefined !== __wasmfsOpfsDir) return __wasmfsOpfsDir;
    // If we have no OPFS, there is no persistent dir
    const pdir = config.wasmfsOpfsDir;
    console.error("sqlite3_wasmfs_opfs_dir() can no longer work due "+
                  "to incompatible WASMFS changes. It will be removed.");
    if(!pdir
       || !self.FileSystemHandle
       || !self.FileSystemDirectoryHandle
       || !self.FileSystemFileHandle){
      return __wasmfsOpfsDir = "";
    }
    try{
      if(pdir && 0===wasm.xCallWrapped(
        'sqlite3_wasm_init_wasmfs', 'i32', ['string'], pdir
      )){
        return __wasmfsOpfsDir = pdir;
      }else{
        return __wasmfsOpfsDir = "";
      }
    }catch(e){
      // sqlite3_wasm_init_wasmfs() is not available
      return __wasmfsOpfsDir = "";
    }
  };

  /**
     Experimental and subject to change or removal.

     Returns true if sqlite3.capi.sqlite3_wasmfs_opfs_dir() is a
     non-empty string and the given name starts with (that string +
     '/'), else returns false.
  */
  capi.sqlite3_wasmfs_filename_is_persistent = function(name){
    const p = capi.sqlite3_wasmfs_opfs_dir();
    return (p && name) ? name.startsWith(p+'/') : false;
  };

  // This bit is highly arguable and is incompatible with the fiddle shell.
  if(false && 0===wasm.exports.sqlite3_vfs_find(0)){
    /* Assume that sqlite3_initialize() has not yet been called.
       This will be the case in an SQLITE_OS_KV build. */
    wasm.exports.sqlite3_initialize();
  }

  /**
     Given an `sqlite3*`, an sqlite3_vfs name, and an optional db name
     (defaulting to "main"), returns a truthy value (see below) if
     that db uses that VFS, else returns false. If pDb is falsy then
     the 3rd argument is ignored and this function returns a truthy
     value if the default VFS name matches that of the 2nd
     argument. Results are undefined if pDb is truthy but refers to an
     invalid pointer. The 3rd argument specifies the database name of
     the given database connection to check, defaulting to the main
     db.

     The 2nd and 3rd arguments may either be a JS string or a WASM
     C-string. If the 2nd argument is a NULL WASM pointer, the default
     VFS is assumed. If the 3rd is a NULL WASM pointer, "main" is
     assumed.

     The truthy value it returns is a pointer to the `sqlite3_vfs`
     object.

     To permit safe use of this function from APIs which may be called
     via the C stack (like SQL UDFs), this function does not throw: if
     bad arguments cause a conversion error when passing into
     wasm-space, false is returned.
  */
  capi.sqlite3_js_db_uses_vfs = function(pDb,vfsName,dbName=0){
    try{
      const pK = capi.sqlite3_vfs_find(vfsName);
      if(!pK) return false;
      else if(!pDb){
        return pK===capi.sqlite3_vfs_find(0) ? pK : false;
      }else{
        return pK===capi.sqlite3_js_db_vfs(pDb,dbName) ? pK : false;
      }
    }catch(e){
      /* Ignore - probably bad args to a wasm-bound function. */
      return false;
    }
  };

  /**
     Returns an array of the names of all currently-registered sqlite3
     VFSes.
  */
  capi.sqlite3_js_vfs_list = function(){
    const rc = [];
    let pVfs = capi.sqlite3_vfs_find(0);
    while(pVfs){
      const oVfs = new capi.sqlite3_vfs(pVfs);
      rc.push(wasm.cstrToJs(oVfs.$zName));
      pVfs = oVfs.$pNext;
      oVfs.dispose();
    }
    return rc;
  };

  /**
     A convenience wrapper around sqlite3_serialize() which serializes
     the given `sqlite3*` pointer to a Uint8Array. The first argument
     may be either an `sqlite3*` or an sqlite3.oo1.DB instance.

     On success it returns a Uint8Array. If the schema is empty, an
     empty array is returned.

     `schema` is the schema to serialize. It may be a WASM C-string
     pointer or a JS string. If it is falsy, it defaults to `"main"`.

     On error it throws with a description of the problem.
  */
  capi.sqlite3_js_db_export = function(pDb, schema=0){
    pDb = wasm.xWrap.testConvertArg('sqlite3*', pDb);
    if(!pDb) toss3('Invalid sqlite3* argument.');
    if(!wasm.bigIntEnabled) toss3('BigInt64 support is not enabled.');
    const scope = wasm.scopedAllocPush();
    let pOut;
    try{
      const pSize = wasm.scopedAlloc(8/*i64*/ + wasm.ptrSizeof);
      const ppOut = pSize + 8;
      /**
         Maintenance reminder, since this cost a full hour of grief
         and confusion: if the order of pSize/ppOut are reversed in
         that memory block, fetching the value of pSize after the
         export reads a garbage size because it's not on an 8-byte
         memory boundary!
      */
      const zSchema = schema
            ? (wasm.isPtr(schema) ? schema : wasm.scopedAllocCString(''+schema))
            : 0;
      let rc = wasm.exports.sqlite3_wasm_db_serialize(
        pDb, zSchema, ppOut, pSize, 0
      );
      if(rc){
        toss3("Database serialization failed with code",
             sqlite3.capi.sqlite3_js_rc_str(rc));
      }
      pOut = wasm.peekPtr(ppOut);
      const nOut = wasm.peek(pSize, 'i64');
      rc = nOut
        ? wasm.heap8u().slice(pOut, pOut + Number(nOut))
        : new Uint8Array();
      return rc;
    }finally{
      if(pOut) wasm.exports.sqlite3_free(pOut);
      wasm.scopedAllocPop(scope);
    }
  };

  /**
     Given a `sqlite3*` and a database name (JS string or WASM
     C-string pointer, which may be 0), returns a pointer to the
     sqlite3_vfs responsible for it. If the given db name is null/0,
     or not provided, then "main" is assumed.
  */
  capi.sqlite3_js_db_vfs =
    (dbPointer, dbName=0)=>wasm.sqlite3_wasm_db_vfs(dbPointer, dbName);

  /**
     A thin wrapper around capi.sqlite3_aggregate_context() which
     behaves the same except that it throws a WasmAllocError if that
     function returns 0. As a special case, if n is falsy it does
     _not_ throw if that function returns 0. That special case is
     intended for use with xFinal() implementations.
  */
  capi.sqlite3_js_aggregate_context = (pCtx, n)=>{
    return capi.sqlite3_aggregate_context(pCtx, n)
      || (n ? WasmAllocError.toss("Cannot allocate",n,
                                  "bytes for sqlite3_aggregate_context()")
          : 0);
  };

  /**
     Creates a file using the storage appropriate for the given
     sqlite3_vfs.  The first argument may be a VFS name (JS string
     only, NOT a WASM C-string), WASM-managed `sqlite3_vfs*`, or
     a capi.sqlite3_vfs instance. Pass 0 (a NULL pointer) to use the
     default VFS. If passed a string which does not resolve using
     sqlite3_vfs_find(), an exception is thrown. (Note that a WASM
     C-string is not accepted because it is impossible to
     distinguish from a C-level `sqlite3_vfs*`.)

     The second argument, the filename, must be a JS or WASM C-string.

     The 3rd may either be falsy, a valid WASM memory pointer, an
     ArrayBuffer, or a Uint8Array. The 4th must be the length, in
     bytes, of the data array to copy. If the 3rd argument is an
     ArrayBuffer or Uint8Array and the 4th is not a positive integer
     then the 4th defaults to the array's byteLength value.

     If data is falsy then a file is created with dataLen bytes filled
     with uninitialized data (whatever truncate() leaves there). If
     data is not falsy then a file is created or truncated and it is
     filled with the first dataLen bytes of the data source.

     Throws if any arguments are invalid or if creating or writing to
     the file fails.

     Note that most VFSes do _not_ automatically create directory
     parts of filenames, nor do all VFSes have a concept of
     directories.  If the given filename is not valid for the given
     VFS, an exception will be thrown. This function exists primarily
     to assist in implementing file-upload capability, with the caveat
     that clients must have some idea of the VFS into which they want
     to upload and that VFS must support the operation.

     VFS-specific notes:

     - "memdb": results are undefined.

     - "kvvfs": will fail with an I/O error due to strict internal
       requirments of that VFS's xTruncate().

     - "unix" and related: will use the WASM build's equivalent of the
       POSIX I/O APIs. This will work so long as neither a specific
       VFS nor the WASM environment imposes requirements which break it.

     - "opfs": uses OPFS storage and creates directory parts of the
       filename.
  */
  capi.sqlite3_js_vfs_create_file = function(vfs, filename, data, dataLen){
    let pData;
    if(data){
      if(wasm.isPtr(data)){
        pData = data;
      }else if(data instanceof ArrayBuffer){
        data = new Uint8Array(data);
      }
      if(data instanceof Uint8Array){
        pData = wasm.allocFromTypedArray(data);
        if(arguments.length<4 || !util.isInt32(dataLen) || dataLen<0){
          dataLen = data.byteLength;
        }
      }else{
        SQLite3Error.toss("Invalid 3rd argument type for sqlite3_js_vfs_create_file().");
      }
    }else{
       pData = 0;
    }
    if(!util.isInt32(dataLen) || dataLen<0){
      wasm.dealloc(pData);
      SQLite3Error.toss("Invalid 4th argument for sqlite3_js_vfs_create_file().");
    }
    try{
      const rc = wasm.sqlite3_wasm_vfs_create_file(vfs, filename, pData, dataLen);
      if(rc) SQLite3Error.toss("Creation of file failed with sqlite3 result code",
                               capi.sqlite3_js_rc_str(rc));
    }finally{
      wasm.dealloc(pData);
    }
  };

  if( util.isUIThread() ){
    /* Features specific to the main window thread... */

    /**
       Internal helper for sqlite3_js_kvvfs_clear() and friends.
       Its argument should be one of ('local','session',"").
    */
    const __kvvfsInfo = function(which){
      const rc = Object.create(null);
      rc.prefix = 'kvvfs-'+which;
      rc.stores = [];
      if('session'===which || ""===which) rc.stores.push(self.sessionStorage);
      if('local'===which || ""===which) rc.stores.push(self.localStorage);
      return rc;
    };

    /**
       Clears all storage used by the kvvfs DB backend, deleting any
       DB(s) stored there. Its argument must be either 'session',
       'local', or "". In the first two cases, only sessionStorage
       resp. localStorage is cleared. If it's an empty string (the
       default) then both are cleared. Only storage keys which match
       the pattern used by kvvfs are cleared: any other client-side
       data are retained.

       This function is only available in the main window thread.

       Returns the number of entries cleared.
    */
    capi.sqlite3_js_kvvfs_clear = function(which=""){
      let rc = 0;
      const kvinfo = __kvvfsInfo(which);
      kvinfo.stores.forEach((s)=>{
        const toRm = [] /* keys to remove */;
        let i;
        for( i = 0; i < s.length; ++i ){
          const k = s.key(i);
          if(k.startsWith(kvinfo.prefix)) toRm.push(k);
        }
        toRm.forEach((kk)=>s.removeItem(kk));
        rc += toRm.length;
      });
      return rc;
    };

    /**
       This routine guesses the approximate amount of
       window.localStorage and/or window.sessionStorage in use by the
       kvvfs database backend. Its argument must be one of
       ('session', 'local', ""). In the first two cases, only
       sessionStorage resp. localStorage is counted. If it's an empty
       string (the default) then both are counted. Only storage keys
       which match the pattern used by kvvfs are counted. The returned
       value is the "length" value of every matching key and value,
       noting that JavaScript stores each character in 2 bytes.

       Note that the returned size is not authoritative from the
       perspective of how much data can fit into localStorage and
       sessionStorage, as the precise algorithms for determining
       those limits are unspecified and may include per-entry
       overhead invisible to clients.
    */
    capi.sqlite3_js_kvvfs_size = function(which=""){
      let sz = 0;
      const kvinfo = __kvvfsInfo(which);
      kvinfo.stores.forEach((s)=>{
        let i;
        for(i = 0; i < s.length; ++i){
          const k = s.key(i);
          if(k.startsWith(kvinfo.prefix)){
            sz += k.length;
            sz += s.getItem(k).length;
          }
        }
      });
      return sz * 2 /* because JS uses 2-byte char encoding */;
    };

  }/* main-window-only bits */

  /**
     Wraps all known variants of the C-side variadic
     sqlite3_db_config().

     Full docs: https://sqlite.org/c3ref/db_config.html

     Returns capi.SQLITE_MISUSE if op is not a valid operation ID.
  */
  capi.sqlite3_db_config = function f(pDb, op, ...args){
    if(!this.s){
      this.s = wasm.xWrap('sqlite3_wasm_db_config_s','int',
                          ['sqlite3*', 'int', 'string:static']
                          /* MAINDBNAME requires a static string */);
      this.pii = wasm.xWrap('sqlite3_wasm_db_config_pii', 'int',
                            ['sqlite3*', 'int', '*','int', 'int']);
      this.ip = wasm.xWrap('sqlite3_wasm_db_config_ip','int',
                           ['sqlite3*', 'int', 'int','*']);
    }
    const c = capi;
    switch(op){
        case c.SQLITE_DBCONFIG_ENABLE_FKEY:
        case c.SQLITE_DBCONFIG_ENABLE_TRIGGER:
        case c.SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER:
        case c.SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION:
        case c.SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE:
        case c.SQLITE_DBCONFIG_ENABLE_QPSG:
        case c.SQLITE_DBCONFIG_TRIGGER_EQP:
        case c.SQLITE_DBCONFIG_RESET_DATABASE:
        case c.SQLITE_DBCONFIG_DEFENSIVE:
        case c.SQLITE_DBCONFIG_WRITABLE_SCHEMA:
        case c.SQLITE_DBCONFIG_LEGACY_ALTER_TABLE:
        case c.SQLITE_DBCONFIG_DQS_DML:
        case c.SQLITE_DBCONFIG_DQS_DDL:
        case c.SQLITE_DBCONFIG_ENABLE_VIEW:
        case c.SQLITE_DBCONFIG_LEGACY_FILE_FORMAT:
        case c.SQLITE_DBCONFIG_TRUSTED_SCHEMA:
          return this.ip(pDb, op, args[0], args[1] || 0);
        case c.SQLITE_DBCONFIG_LOOKASIDE:
          return this.pii(pDb, op, args[0], args[1], args[2]);
        case c.SQLITE_DBCONFIG_MAINDBNAME:
          return this.s(pDb, op, args[0]);
        default:
          return c.SQLITE_MISUSE;
    }
  }.bind(Object.create(null));

  /**
     Given a (sqlite3_value*), this function attempts to convert it
     to an equivalent JS value with as much fidelity as feasible and
     return it.

     By default it throws if it cannot determine any sensible
     conversion. If passed a falsy second argument, it instead returns
     `undefined` if no suitable conversion is found.  Note that there
     is no conversion from SQL to JS which results in the `undefined`
     value, so `undefined` has an unambiguous meaning here.  It will
     always throw a WasmAllocError if allocating memory for a
     conversion fails.

     Caveats:

     - It does not support sqlite3_value_to_pointer() conversions
       because those require a type name string which this function
       does not have and cannot sensibly be given at the level of the
       API where this is used (e.g. automatically converting UDF
       arguments). Clients using sqlite3_value_to_pointer(), and its
       related APIs, will need to manage those themselves.
  */
  capi.sqlite3_value_to_js = function(pVal,throwIfCannotConvert=true){
    let arg;
    const valType = capi.sqlite3_value_type(pVal);
    switch(valType){
        case capi.SQLITE_INTEGER:
          if(wasm.bigIntEnabled){
            arg = capi.sqlite3_value_int64(pVal);
            if(util.bigIntFitsDouble(arg)) arg = Number(arg);
          }
          else arg = capi.sqlite3_value_double(pVal)/*yes, double, for larger integers*/;
          break;
        case capi.SQLITE_FLOAT:
          arg = capi.sqlite3_value_double(pVal);
          break;
        case capi.SQLITE_TEXT:
          arg = capi.sqlite3_value_text(pVal);
          break;
        case capi.SQLITE_BLOB:{
          const n = capi.sqlite3_value_bytes(pVal);
          const pBlob = capi.sqlite3_value_blob(pVal);
          if(n && !pBlob) sqlite3.WasmAllocError.toss(
            "Cannot allocate memory for blob argument of",n,"byte(s)"
          );
          arg = n ? wasm.heap8u().slice(pBlob, pBlob + Number(n)) : null;
          break;
        }
        case capi.SQLITE_NULL:
          arg = null; break;
        default:
          if(throwIfCannotConvert){
            toss3(capi.SQLITE_MISMATCH,
                  "Unhandled sqlite3_value_type():",valType);
          }
          arg = undefined;
    }
    return arg;
  };

  /**
     Requires a C-style array of `sqlite3_value*` objects and the
     number of entries in that array. Returns a JS array containing
     the results of passing each C array entry to
     sqlite3_value_to_js(). The 3rd argument to this function is
     passed on as the 2nd argument to that one.
  */
  capi.sqlite3_values_to_js = function(argc,pArgv,throwIfCannotConvert=true){
    let i;
    const tgt = [];
    for(i = 0; i < argc; ++i){
      /**
         Curiously: despite ostensibly requiring 8-byte
         alignment, the pArgv array is parcelled into chunks of
         4 bytes (1 pointer each). The values those point to
         have 8-byte alignment but the individual argv entries
         do not.
      */
      tgt.push(capi.sqlite3_value_to_js(
        wasm.peekPtr(pArgv + (wasm.ptrSizeof * i))
      ));
    }
    return tgt;
  };

  /**
     Calls either sqlite3_result_error_nomem(), if e is-a
     WasmAllocError, or sqlite3_result_error(). In the latter case,
     the second arugment is coerced to a string to create the error
     message.

     The first argument is a (sqlite3_context*). Returns void.
     Does not throw.
  */
  capi.sqlite3_result_error_js = function(pCtx,e){
    if(e instanceof WasmAllocError){
      capi.sqlite3_result_error_nomem(pCtx);
    }else{
      /* Maintenance reminder: ''+e, rather than e.message,
         will prefix e.message with e.name, so it includes
         the exception's type name in the result. */;
      capi.sqlite3_result_error(pCtx, ''+e, -1);
    }
  };

  /**
     This function passes its 2nd argument to one of the
     sqlite3_result_xyz() routines, depending on the type of that
     argument:

     - If (val instanceof Error), this function passes it to
       sqlite3_result_error_js().
     - `null`: `sqlite3_result_null()`
     - `boolean`: `sqlite3_result_int()` with a value of 0 or 1.
     - `number`: `sqlite3_result_int()`, `sqlite3_result_int64()`, or
       `sqlite3_result_double()`, depending on the range of the number
       and whether or not int64 support is enabled.
     - `bigint`: similar to `number` but will trigger an error if the
       value is too big to store in an int64.
     - `string`: `sqlite3_result_text()`
     - Uint8Array or Int8Array or ArrayBuffer: `sqlite3_result_blob()`
     - `undefined`: is a no-op provided to simplify certain use cases.

     Anything else triggers `sqlite3_result_error()` with a
     description of the problem.

     The first argument to this function is a `(sqlite3_context*)`.
     Returns void. Does not throw.
  */
  capi.sqlite3_result_js = function(pCtx,val){
    if(val instanceof Error){
      capi.sqlite3_result_error_js(pCtx, val);
      return;
    }
    try{
      switch(typeof val) {
          case 'undefined':
            /* This is a no-op. This routine originated in the create_function()
               family of APIs and in that context, passing in undefined indicated
               that the caller was responsible for calling sqlite3_result_xxx()
               (if needed). */
            break;
          case 'boolean':
            capi.sqlite3_result_int(pCtx, val ? 1 : 0);
            break;
          case 'bigint':
            if(util.bigIntFits32(val)){
              capi.sqlite3_result_int(pCtx, Number(val));
            }else if(util.bigIntFitsDouble(val)){
              capi.sqlite3_result_double(pCtx, Number(val));
            }else if(wasm.bigIntEnabled){
              if(util.bigIntFits64(val)) capi.sqlite3_result_int64(pCtx, val);
              else toss3("BigInt value",val.toString(),"is too BigInt for int64.");
            }else{
              toss3("BigInt value",val.toString(),"is too BigInt.");
            }
            break;
          case 'number': {
            let f;
            if(util.isInt32(val)){
              f = capi.sqlite3_result_int;
            }else if(wasm.bigIntEnabled
                     && Number.isInteger(val)
                     && util.bigIntFits64(BigInt(val))){
              f = capi.sqlite3_result_int64;
            }else{
              f = capi.sqlite3_result_double;
            }
            f(pCtx, val);
            break;
          }
          case 'string': {
            const [p, n] = wasm.allocCString(val,true);
            capi.sqlite3_result_text(pCtx, p, n, capi.SQLITE_WASM_DEALLOC);
            break;
          }
          case 'object':
            if(null===val/*yes, typeof null === 'object'*/) {
              capi.sqlite3_result_null(pCtx);
              break;
            }else if(util.isBindableTypedArray(val)){
              const pBlob = wasm.allocFromTypedArray(val);
              capi.sqlite3_result_blob(
                pCtx, pBlob, val.byteLength,
                capi.SQLITE_WASM_DEALLOC
              );
              break;
            }
            // else fall through
          default:
            toss3("Don't not how to handle this UDF result value:",(typeof val), val);
      }
    }catch(e){
      capi.sqlite3_result_error_js(pCtx, e);
    }
  };

  /**
     Returns the result sqlite3_column_value(pStmt,iCol) passed to
     sqlite3_value_to_js(). The 3rd argument of this function is
     ignored by this function except to pass it on as the second
     argument of sqlite3_value_to_js(). If the sqlite3_column_value()
     returns NULL (e.g. because the column index is out of range),
     this function returns `undefined`, regardless of the 3rd
     argument. If the 3rd argument is falsy and conversion fails,
     `undefined` will be returned.

     Note that sqlite3_column_value() returns an "unprotected" value
     object, but in a single-threaded environment (like this one)
     there is no distinction between protected and unprotected values.
  */
  capi.sqlite3_column_js = function(pStmt, iCol, throwIfCannotConvert=true){
    const v = capi.sqlite3_column_value(pStmt, iCol);
    return (0===v) ? undefined : capi.sqlite3_value_to_js(v, throwIfCannotConvert);
  };

  /**
     Internal impl of sqlite3_preupdate_new/old_js() and
     sqlite3changeset_new/old_js().
  */
  const __newOldValue = function(pObj, iCol, impl){
    impl = capi[impl];
    if(!this.ptr) this.ptr = wasm.allocPtr();
    else wasm.pokePtr(this.ptr, 0);
    const rc = impl(pObj, iCol, this.ptr);
    if(rc) return SQLite3Error.toss(rc,arguments[2]+"() failed with code "+rc);
    const pv = wasm.peekPtr(this.ptr);
    return pv ? capi.sqlite3_value_to_js( pv, true ) : undefined;
  }.bind(Object.create(null));

  /**
     A wrapper around sqlite3_preupdate_new() which fetches the
     sqlite3_value at the given index and returns the result of
     passing it to sqlite3_value_to_js(). Throws on error.
  */
  capi.sqlite3_preupdate_new_js =
    (pDb, iCol)=>__newOldValue(pDb, iCol, 'sqlite3_preupdate_new');

  /**
     The sqlite3_preupdate_old() counterpart of
     sqlite3_preupdate_new_js(), with an identical interface.
  */
  capi.sqlite3_preupdate_old_js =
    (pDb, iCol)=>__newOldValue(pDb, iCol, 'sqlite3_preupdate_old');

  /**
     A wrapper around sqlite3changeset_new() which fetches the
     sqlite3_value at the given index and returns the result of
     passing it to sqlite3_value_to_js(). Throws on error.

     If sqlite3changeset_new() succeeds but has no value to report,
     this function returns the undefined value, noting that undefined
     is a valid conversion from an `sqlite3_value`, so is unambiguous.
  */
  capi.sqlite3changeset_new_js =
    (pChangesetIter, iCol) => __newOldValue(pChangesetIter, iCol,
                                            'sqlite3changeset_new');

  /**
     The sqlite3changeset_old() counterpart of
     sqlite3changeset_new_js(), with an identical interface.
  */
  capi.sqlite3changeset_old_js =
    (pChangesetIter, iCol)=>__newOldValue(pChangesetIter, iCol,
                                          'sqlite3changeset_old');

  /* The remainder of the API will be set up in later steps. */
  const sqlite3 = {
    WasmAllocError: WasmAllocError,
    SQLite3Error: SQLite3Error,
    capi,
    util,
    wasm,
    config,
    /**
       Holds the version info of the sqlite3 source tree from which
       the generated sqlite3-api.js gets built. Note that its version
       may well differ from that reported by sqlite3_libversion(), but
       that should be considered a source file mismatch, as the JS and
       WASM files are intended to be built and distributed together.

       This object is initially a placeholder which gets replaced by a
       build-generated object.
    */
    version: Object.create(null),

    /**
       The library reserves the 'client' property for client-side use
       and promises to never define a property with this name nor to
       ever rely on specific contents of it. It makes no such guarantees
       for other properties.
    */
    client: undefined,

    /**
       Performs any optional asynchronous library-level initialization
       which might be required. This function returns a Promise which
       resolves to the sqlite3 namespace object. Any error in the
       async init will be fatal to the init as a whole, but init
       routines are themselves welcome to install dummy catch()
       handlers which are not fatal if their failure should be
       considered non-fatal. If called more than once, the second and
       subsequent calls are no-ops which return a pre-resolved
       Promise.

       Ideally this function is called as part of the Promise chain
       which handles the loading and bootstrapping of the API.  If not
       then it must be called by client-level code, which must not use
       the library until the returned promise resolves.

       Bug: if called while a prior call is still resolving, the 2nd
       call will resolve prematurely, before the 1st call has finished
       resolving. The current build setup precludes that possibility,
       so it's only a hypothetical problem if/when this function
       ever needs to be invoked by clients.

       In Emscripten-based builds, this function is called
       automatically and deleted from this object.
    */
    asyncPostInit: async function(){
      let lip = sqlite3ApiBootstrap.initializersAsync;
      delete sqlite3ApiBootstrap.initializersAsync;
      if(!lip || !lip.length) return Promise.resolve(sqlite3);
      lip = lip.map((f)=>{
        const p = (f instanceof Promise) ? f : f(sqlite3);
        return p.catch((e)=>{
          console.error("an async sqlite3 initializer failed:",e);
          throw e;
        });
      });
      const postInit = ()=>{
        if(!sqlite3.__isUnderTest){
          /* Delete references to internal-only APIs which are used by
             some initializers. Retain them when running in test mode
             so that we can add tests for them. */
          delete sqlite3.util;
          /* It's conceivable that we might want to expose
             StructBinder to client-side code, but it's only useful if
             clients build their own sqlite3.wasm which contains their
             one C struct types. */
          delete sqlite3.StructBinder;
        }
        return sqlite3;
      };
      if(1){
        /* Run all initializers in sequence. The advantage is that it
           allows us to have post-init cleanup defined outside of this
           routine at the end of the list and have it run at a
           well-defined time. */
        let p = lip.shift();
        while(lip.length) p = p.then(lip.shift());
        return p.then(postInit);
      }else{
        /* Run them in an arbitrary order. */
        return Promise.all(lip).then(postInit);
      }
    },
    /**
       scriptInfo ideally gets injected into this object by the
       infrastructure which assembles the JS/WASM module. It contains
       state which must be collected before sqlite3ApiBootstrap() can
       be declared. It is not necessarily available to any
       sqlite3ApiBootstrap.initializers but "should" be in place (if
       it's added at all) by the time that
       sqlite3ApiBootstrap.initializersAsync is processed.

       This state is not part of the public API, only intended for use
       with the sqlite3 API bootstrapping and wasm-loading process.
    */
    scriptInfo: undefined
  };
  try{
    sqlite3ApiBootstrap.initializers.forEach((f)=>{
      f(sqlite3);
    });
  }catch(e){
    /* If we don't report this here, it can get completely swallowed
       up and disappear into the abyss of Promises and Workers. */
    console.error("sqlite3 bootstrap initializer threw:",e);
    throw e;
  }
  delete sqlite3ApiBootstrap.initializers;
  sqlite3ApiBootstrap.sqlite3 = sqlite3;
  return sqlite3;
}/*sqlite3ApiBootstrap()*/;
/**
  self.sqlite3ApiBootstrap.initializers is an internal detail used by
  the various pieces of the sqlite3 API's amalgamation process. It
  must not be modified by client code except when plugging such code
  into the amalgamation process.

  Each component of the amalgamation is expected to append a function
  to this array. When sqlite3ApiBootstrap() is called for the first
  time, each such function will be called (in their appended order)
  and passed the sqlite3 namespace object, into which they can install
  their features (noting that most will also require that certain
  features alread have been installed).  At the end of that process,
  this array is deleted.

  Note that the order of insertion into this array is significant for
  some pieces. e.g. sqlite3.capi and sqlite3.wasm cannot be fully
  utilized until the whwasmutil.js part is plugged in via
  sqlite3-api-glue.js.
*/
self.sqlite3ApiBootstrap.initializers = [];
/**
  self.sqlite3ApiBootstrap.initializersAsync is an internal detail
  used by the sqlite3 API's amalgamation process. It must not be
  modified by client code except when plugging such code into the
  amalgamation process.

  The counterpart of self.sqlite3ApiBootstrap.initializers,
  specifically for initializers which are asynchronous. All entries in
  this list must be either async functions, non-async functions which
  return a Promise, or a Promise. Each function in the list is called
  with the sqlite3 ojbect as its only argument.

  The resolved value of any Promise is ignored and rejection will kill
  the asyncPostInit() process (at an indeterminate point because all
  of them are run asynchronously in parallel).

  This list is not processed until the client calls
  sqlite3.asyncPostInit(). This means, for example, that intializers
  added to self.sqlite3ApiBootstrap.initializers may push entries to
  this list.
*/
self.sqlite3ApiBootstrap.initializersAsync = [];
/**
   Client code may assign sqlite3ApiBootstrap.defaultConfig an
   object-type value before calling sqlite3ApiBootstrap() (without
   arguments) in order to tell that call to use this object as its
   default config value. The intention of this is to provide
   downstream clients with a reasonably flexible approach for plugging in
   an environment-suitable configuration without having to define a new
   global-scope symbol.
*/
self.sqlite3ApiBootstrap.defaultConfig = Object.create(null);
/**
   Placeholder: gets installed by the first call to
   self.sqlite3ApiBootstrap(). However, it is recommended that the
   caller of sqlite3ApiBootstrap() capture its return value and delete
   self.sqlite3ApiBootstrap after calling it. It returns the same
   value which will be stored here.
*/
self.sqlite3ApiBootstrap.sqlite3 = undefined;

Added ext/wasm/api/sqlite3-api-worker1.js.



































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
638
639
640
641
642
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/**
  2022-07-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 the initializer for SQLite's "Worker API #1", a
  very basic DB access API intended to be scripted from a main window
  thread via Worker-style messages. Because of limitations in that
  type of communication, this API is minimalistic and only capable of
  serving relatively basic DB requests (e.g. it cannot process nested
  query loops concurrently).

  This file requires that the core C-style sqlite3 API and OO API #1
  have been loaded.
*/

/**
  sqlite3.initWorker1API() implements a Worker-based wrapper around
  SQLite3 OO API #1, colloquially known as "Worker API #1".

  In order to permit this API to be loaded in worker threads without
  automatically registering onmessage handlers, initializing the
  worker API requires calling initWorker1API(). If this function is
  called from a non-worker thread then it throws an exception.  It
  must only be called once per Worker.

  When initialized, it installs message listeners to receive Worker
  messages and then it posts a message in the form:

  ```
  {type:'sqlite3-api', result:'worker1-ready'}
  ```

  to let the client know that it has been initialized. Clients may
  optionally depend on this function not returning until
  initialization is complete, as the initialization is synchronous.
  In some contexts, however, listening for the above message is
  a better fit.

  Note that the worker-based interface can be slightly quirky because
  of its async nature. In particular, any number of messages may be posted
  to the worker before it starts handling any of them. If, e.g., an
  "open" operation fails, any subsequent messages will fail. The
  Promise-based wrapper for this API (`sqlite3-worker1-promiser.js`)
  is more comfortable to use in that regard.

  The documentation for the input and output worker messages for
  this API follows...

  ====================================================================
  Common message format...

  Each message posted to the worker has an operation-independent
  envelope and operation-dependent arguments:

  ```
  {
    type: string, // one of: 'open', 'close', 'exec', 'config-get'

    messageId: OPTIONAL arbitrary value. The worker will copy it as-is
    into response messages to assist in client-side dispatching.

    dbId: a db identifier string (returned by 'open') which tells the
    operation which database instance to work on. If not provided, the
    first-opened db is used. This is an "opaque" value, with no
    inherently useful syntax or information. Its value is subject to
    change with any given build of this API and cannot be used as a
    basis for anything useful beyond its one intended purpose.

    args: ...operation-dependent arguments...

    // the framework may add other properties for testing or debugging
    // purposes.

  }
  ```

  Response messages, posted back to the main thread, look like:

  ```
  {
    type: string. Same as above except for error responses, which have the type
    'error',

    messageId: same value, if any, provided by the inbound message

    dbId: the id of the db which was operated on, if any, as returned
    by the corresponding 'open' operation.

    result: ...operation-dependent result...

  }
  ```

  ====================================================================
  Error responses

  Errors are reported messages in an operation-independent format:

  ```
  {
    type: "error",

    messageId: ...as above...,

    dbId: ...as above...

    result: {

      operation: type of the triggering operation: 'open', 'close', ...

      message: ...error message text...

      errorClass: string. The ErrorClass.name property from the thrown exception.

      input: the message object which triggered the error.

      stack: _if available_, a stack trace array.

    }

  }
  ```


  ====================================================================
  "config-get"

  This operation fetches the serializable parts of the sqlite3 API
  configuration.

  Message format:

  ```
  {
    type: "config-get",
    messageId: ...as above...,
    args: currently ignored and may be elided.
  }
  ```

  Response:

  ```
  {
    type: "config-get",
    messageId: ...as above...,
    result: {

      version: sqlite3.version object

      bigIntEnabled: bool. True if BigInt support is enabled.

      vfsList: result of sqlite3.capi.sqlite3_js_vfs_list()
   }
  }
  ```


  ====================================================================
  "open" a database

  Message format:

  ```
  {
    type: "open",
    messageId: ...as above...,
    args:{

      filename [=":memory:" or "" (unspecified)]: the db filename.
      See the sqlite3.oo1.DB constructor for peculiarities and
      transformations,

      vfs: sqlite3_vfs name. Ignored if filename is ":memory:" or "".
           This may change how the given filename is resolved.
    }
  }
  ```

  Response:

  ```
  {
    type: "open",
    messageId: ...as above...,
    result: {
      filename: db filename, possibly differing from the input.

      dbId: an opaque ID value which must be passed in the message
      envelope to other calls in this API to tell them which db to
      use. If it is not provided to future calls, they will default to
      operating on the least-recently-opened db. This property is, for
      API consistency's sake, also part of the containing message
      envelope.  Only the `open` operation includes it in the `result`
      property.

      persistent: true if the given filename resides in the
      known-persistent storage, else false.

      vfs: name of the VFS the "main" db is using.
   }
  }
  ```

  ====================================================================
  "close" a database

  Message format:

  ```
  {
    type: "close",
    messageId: ...as above...
    dbId: ...as above...
    args: OPTIONAL {unlink: boolean}
  }
  ```

  If the `dbId` does not refer to an opened ID, this is a no-op. If
  the `args` object contains a truthy `unlink` value then the database
  will be unlinked (deleted) after closing it. The inability to close a
  db (because it's not opened) or delete its file does not trigger an
  error.

  Response:

  ```
  {
    type: "close",
    messageId: ...as above...,
    result: {

      filename: filename of closed db, or undefined if no db was closed

    }
  }
  ```

  ====================================================================
  "exec" SQL

  All SQL execution is processed through the exec operation. It offers
  most of the features of the oo1.DB.exec() method, with a few limitations
  imposed by the state having to cross thread boundaries.

  Message format:

  ```
  {
    type: "exec",
    messageId: ...as above...
    dbId: ...as above...
    args: string (SQL) or {... see below ...}
  }
  ```

  Response:

  ```
  {
    type: "exec",
    messageId: ...as above...,
    dbId: ...as above...
    result: {
      input arguments, possibly modified. See below.
    }
  }
  ```

  The arguments are in the same form accepted by oo1.DB.exec(), with
  the exceptions noted below.

  A function-type args.callback property cannot cross
  the window/Worker boundary, so is not useful here. If
  args.callback is a string then it is assumed to be a
  message type key, in which case a callback function will be
  applied which posts each row result via:

  postMessage({type: thatKeyType,
               rowNumber: 1-based-#,
               row: theRow,
               columnNames: anArray
               })

  And, at the end of the result set (whether or not any result rows
  were produced), it will post an identical message with
  (row=undefined, rowNumber=null) to alert the caller than the result
  set is completed. Note that a row value of `null` is a legal row
  result for certain arg.rowMode values.

    (Design note: we don't use (row=undefined, rowNumber=undefined) to
    indicate end-of-results because fetching those would be
    indistinguishable from fetching from an empty object unless the
    client used hasOwnProperty() (or similar) to distinguish "missing
    property" from "property with the undefined value".  Similarly,
    `null` is a legal value for `row` in some case , whereas the db
    layer won't emit a result value of `undefined`.)

  The callback proxy must not recurse into this interface. An exec()
  call will tie up the Worker thread, causing any recursion attempt
  to wait until the first exec() is completed.

  The response is the input options object (or a synthesized one if
  passed only a string), noting that options.resultRows and
  options.columnNames may be populated by the call to db.exec().

*/
self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
sqlite3.initWorker1API = function(){
  'use strict';
  const toss = (...args)=>{throw new Error(args.join(' '))};
  if('function' !== typeof importScripts){
    toss("initWorker1API() must be run from a Worker thread.");
  }
  const self = this.self;
  const sqlite3 = this.sqlite3 || toss("Missing this.sqlite3 object.");
  const DB = sqlite3.oo1.DB;

  /**
     Returns the app-wide unique ID for the given db, creating one if
     needed.
  */
  const getDbId = function(db){
    let id = wState.idMap.get(db);
    if(id) return id;
    id = 'db#'+(++wState.idSeq)+'@'+db.pointer;
    /** ^^^ can't simply use db.pointer b/c closing/opening may re-use
        the same address, which could map pending messages to a wrong
        instance. */
    wState.idMap.set(db, id);
    return id;
  };

  /**
     Internal helper for managing Worker-level state.
  */
  const wState = {
    /**
       Each opened DB is added to this.dbList, and the first entry in
       that list is the default db. As each db is closed, its entry is
       removed from the list.
    */
    dbList: [],
    /** Sequence number of dbId generation. */
    idSeq: 0,
    /** Map of DB instances to dbId. */
    idMap: new WeakMap,
    /** Temp holder for "transferable" postMessage() state. */
    xfer: [],
    open: function(opt){
      const db = new DB(opt);
      this.dbs[getDbId(db)] = db;
      if(this.dbList.indexOf(db)<0) this.dbList.push(db);
      return db;
    },
    close: function(db,alsoUnlink){
      if(db){
        delete this.dbs[getDbId(db)];
        const filename = db.filename;
        const pVfs = sqlite3.wasm.sqlite3_wasm_db_vfs(db.pointer, 0);
        db.close();
        const ddNdx = this.dbList.indexOf(db);
        if(ddNdx>=0) this.dbList.splice(ddNdx, 1);
        if(alsoUnlink && filename && pVfs){
          sqlite3.wasm.sqlite3_wasm_vfs_unlink(pVfs, filename);
        }
      }
    },
    /**
       Posts the given worker message value. If xferList is provided,
       it must be an array, in which case a copy of it passed as
       postMessage()'s second argument and xferList.length is set to
       0.
    */
    post: function(msg,xferList){
      if(xferList && xferList.length){
        self.postMessage( msg, Array.from(xferList) );
        xferList.length = 0;
      }else{
        self.postMessage(msg);
      }
    },
    /** Map of DB IDs to DBs. */
    dbs: Object.create(null),
    /** Fetch the DB for the given id. Throw if require=true and the
        id is not valid, else return the db or undefined. */
    getDb: function(id,require=true){
      return this.dbs[id]
        || (require ? toss("Unknown (or closed) DB ID:",id) : undefined);
    }
  };

  /** Throws if the given db is falsy or not opened, else returns its
      argument. */
  const affirmDbOpen = function(db = wState.dbList[0]){
    return (db && db.pointer) ? db : toss("DB is not opened.");
  };

  /** Extract dbId from the given message payload. */
  const getMsgDb = function(msgData,affirmExists=true){
    const db = wState.getDb(msgData.dbId,false) || wState.dbList[0];
    return affirmExists ? affirmDbOpen(db) : db;
  };

  const getDefaultDbId = function(){
    return wState.dbList[0] && getDbId(wState.dbList[0]);
  };

  const guessVfs = function(filename){
    const m = /^file:.+(vfs=(\w+))/.exec(filename);
    return sqlite3.capi.sqlite3_vfs_find(m ? m[2] : 0);
  };

  const isSpecialDbFilename = (n)=>{
    return ""===n || ':'===n[0];
  };

  /**
     A level of "organizational abstraction" for the Worker1
     API. Each method in this object must map directly to a Worker1
     message type key. The onmessage() dispatcher attempts to
     dispatch all inbound messages to a method of this object,
     passing it the event.data part of the inbound event object. All
     methods must return a plain Object containing any result
     state, which the dispatcher may amend. All methods must throw
     on error.
  */
  const wMsgHandler = {
    open: function(ev){
      const oargs = Object.create(null), args = (ev.args || Object.create(null));
      if(args.simulateError){ // undocumented internal testing option
        toss("Throwing because of simulateError flag.");
      }
      const rc = Object.create(null);
      let byteArray, pVfs;
      oargs.vfs = args.vfs;
      if(isSpecialDbFilename(args.filename)){
        oargs.filename = args.filename || "";
      }else{
        oargs.filename = args.filename;
        byteArray = args.byteArray;
        if(byteArray) pVfs = guessVfs(args.filename);
      }
      if(pVfs){
        /* 2022-11-02: this feature is as-yet untested except that
           sqlite3_wasm_vfs_create_file() has been tested from the
           browser dev console. */
        let pMem;
        try{
          pMem = sqlite3.wasm.allocFromTypedArray(byteArray);
          const rc = sqlite3.wasm.sqlite3_wasm_vfs_create_file(
            pVfs, oargs.filename, pMem, byteArray.byteLength
          );
          if(rc) sqlite3.SQLite3Error.toss(rc);
        }catch(e){
          throw new sqlite3.SQLite3Error(
            e.name+' creating '+args.filename+": "+e.message, {
              cause: e
            }
          );
        }finally{
          if(pMem) sqlite3.wasm.dealloc(pMem);
        }
      }
      const db = wState.open(oargs);
      rc.filename = db.filename;
      rc.persistent = !!sqlite3.capi.sqlite3_js_db_uses_vfs(db.pointer, "opfs");
      rc.dbId = getDbId(db);
      rc.vfs = db.dbVfsName();
      return rc;
    },

    close: function(ev){
      const db = getMsgDb(ev,false);
      const response = {
        filename: db && db.filename
      };
      if(db){
        const doUnlink = ((ev.args && 'object'===typeof ev.args)
                         ? !!ev.args.unlink : false);
        wState.close(db, doUnlink);
      }
      return response;
    },

    exec: function(ev){
      const rc = (
        'string'===typeof ev.args
      ) ? {sql: ev.args} : (ev.args || Object.create(null));
      if('stmt'===rc.rowMode){
        toss("Invalid rowMode for 'exec': stmt mode",
             "does not work in the Worker API.");
      }else if(!rc.sql){
        toss("'exec' requires input SQL.");
      }
      const db = getMsgDb(ev);
      if(rc.callback || Array.isArray(rc.resultRows)){
        // Part of a copy-avoidance optimization for blobs
        db._blobXfer = wState.xfer;
      }
      const theCallback = rc.callback;
      let rowNumber = 0;
      const hadColNames = !!rc.columnNames;
      if('string' === typeof theCallback){
        if(!hadColNames) rc.columnNames = [];
        /* Treat this as a worker message type and post each
           row as a message of that type. */
        rc.callback = function(row,stmt){
          wState.post({
            type: theCallback,
            columnNames: rc.columnNames,
            rowNumber: ++rowNumber,
            row: row
          }, wState.xfer);
        }
      }
      try {
        db.exec(rc);
        if(rc.callback instanceof Function){
          rc.callback = theCallback;
          /* Post a sentinel message to tell the client that the end
             of the result set has been reached (possibly with zero
             rows). */
          wState.post({
            type: theCallback,
            columnNames: rc.columnNames,
            rowNumber: null /*null to distinguish from "property not set"*/,
            row: undefined /*undefined because null is a legal row value
                             for some rowType values, but undefined is not*/
          });
        }
      }finally{
        delete db._blobXfer;
        if(rc.callback) rc.callback = theCallback;
      }
      return rc;
    }/*exec()*/,

    'config-get': function(){
      const rc = Object.create(null), src = sqlite3.config;
      [
        'bigIntEnabled'
      ].forEach(function(k){
        if(Object.getOwnPropertyDescriptor(src, k)) rc[k] = src[k];
      });
      rc.version = sqlite3.version;
      rc.vfsList = sqlite3.capi.sqlite3_js_vfs_list();
      rc.opfsEnabled = !!sqlite3.opfs;
      return rc;
    },

    /**
       Exports the database to a byte array, as per
       sqlite3_serialize(). Response is an object:

       {
         byteArray:  Uint8Array (db file contents),
         filename: the current db filename,
         mimetype: 'application/x-sqlite3'
       }
    */
    export: function(ev){
      const db = getMsgDb(ev);
      const response = {
        byteArray: sqlite3.capi.sqlite3_js_db_export(db.pointer),
        filename: db.filename,
        mimetype: 'application/x-sqlite3'
      };
      wState.xfer.push(response.byteArray.buffer);
      return response;
    }/*export()*/,

    toss: function(ev){
      toss("Testing worker exception");
    },

    'opfs-tree': async function(ev){
      if(!sqlite3.opfs) toss("OPFS support is unavailable.");
      const response = await sqlite3.opfs.treeList();
      return response;
    }
  }/*wMsgHandler*/;

  self.onmessage = async function(ev){
    ev = ev.data;
    let result, dbId = ev.dbId, evType = ev.type;
    const arrivalTime = performance.now();
    try {
      if(wMsgHandler.hasOwnProperty(evType) &&
         wMsgHandler[evType] instanceof Function){
        result = await wMsgHandler[evType](ev);
      }else{
        toss("Unknown db worker message type:",ev.type);
      }
    }catch(err){
      evType = 'error';
      result = {
        operation: ev.type,
        message: err.message,
        errorClass: err.name,
        input: ev
      };
      if(err.stack){
        result.stack = ('string'===typeof err.stack)
          ? err.stack.split(/\n\s*/) : err.stack;
      }
      if(0) console.warn("Worker is propagating an exception to main thread.",
                         "Reporting it _here_ for the stack trace:",err,result);
    }
    if(!dbId){
      dbId = result.dbId/*from 'open' cmd*/
        || getDefaultDbId();
    }
    // Timing info is primarily for use in testing this API. It's not part of
    // the public API. arrivalTime = when the worker got the message.
    wState.post({
      type: evType,
      dbId: dbId,
      messageId: ev.messageId,
      workerReceivedTime: arrivalTime,
      workerRespondTime: performance.now(),
      departureTime: ev.departureTime,
      // TODO: move the timing bits into...
      //timing:{
      //  departure: ev.departureTime,
      //  workerReceived: arrivalTime,
      //  workerResponse: performance.now();
      //},
      result: result
    }, wState.xfer);
  };
  self.postMessage({type:'sqlite3-api',result:'worker1-ready'});
}.bind({self, sqlite3});
});

Added ext/wasm/api/sqlite3-license-version-header.js.


























1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** LICENSE for the sqlite3 WebAssembly/JavaScript APIs.
**
** This bundle (typically released as sqlite3.js or sqlite3-wasmfs.js)
** is an amalgamation of JavaScript source code from two projects:
**
** 1) https://emscripten.org: the Emscripten "glue code" is covered by
**    the terms of the MIT license and University of Illinois/NCSA
**    Open Source License, as described at:
**
**    https://emscripten.org/docs/introducing_emscripten/emscripten_license.html
**
** 2) https://sqlite.org: all code and documentation labeled as being
**    from this source are released under the same terms as the sqlite3
**    C library:
**
** 2022-10-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.
*/

Added ext/wasm/api/sqlite3-opfs-async-proxy.js.


































































































































































































































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
  2022-09-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.

  ***********************************************************************

  A Worker which manages asynchronous OPFS handles on behalf of a
  synchronous API which controls it via a combination of Worker
  messages, SharedArrayBuffer, and Atomics. It is the asynchronous
  counterpart of the API defined in sqlite3-vfs-opfs.js.

  Highly indebted to:

  https://github.com/rhashimoto/wa-sqlite/blob/master/src/examples/OriginPrivateFileSystemVFS.js

  for demonstrating how to use the OPFS APIs.

  This file is to be loaded as a Worker. It does not have any direct
  access to the sqlite3 JS/WASM bits, so any bits which it needs (most
  notably SQLITE_xxx integer codes) have to be imported into it via an
  initialization process.

  This file represents an implementation detail of a larger piece of
  code, and not a public interface. Its details may change at any time
  and are not intended to be used by any client-level code.

  2022-11-27: Chrome v108 changes some async methods to synchronous, as
  documented at:

  https://developer.chrome.com/blog/sync-methods-for-accesshandles/

  We cannot change to the sync forms at this point without breaking
  clients who use Chrome v104-ish or higher. truncate(), getSize(),
  flush(), and close() are now (as of v108) synchronous. Calling them
  with an "await", as we have to for the async forms, is still legal
  with the sync forms but is superfluous. Calling the async forms with
  theFunc().then(...) is not compatible with the change to
  synchronous, but we do do not use those APIs that way. i.e. we don't
  _need_ to change anything for this, but at some point (after Chrome
  versions (approximately) 104-107 are extinct) should change our
  usage of those methods to remove the "await".
*/
"use strict";
const wPost = (type,...args)=>postMessage({type, payload:args});
const installAsyncProxy = function(self){
  const toss = function(...args){throw new Error(args.join(' '))};
  if(self.window === self){
    toss("This code cannot run from the main thread.",
         "Load it as a Worker from a separate Worker.");
  }else if(!navigator.storage.getDirectory){
    toss("This API requires navigator.storage.getDirectory.");
  }

  /**
     Will hold state copied to this object from the syncronous side of
     this API.
  */
  const state = Object.create(null);

  /**
     verbose:

     0 = no logging output
     1 = only errors
     2 = warnings and errors
     3 = debug, warnings, and errors
  */
  state.verbose = 1;

  const loggers = {
    0:console.error.bind(console),
    1:console.warn.bind(console),
    2:console.log.bind(console)
  };
  const logImpl = (level,...args)=>{
    if(state.verbose>level) loggers[level]("OPFS asyncer:",...args);
  };
  const log =    (...args)=>logImpl(2, ...args);
  const warn =   (...args)=>logImpl(1, ...args);
  const error =  (...args)=>logImpl(0, ...args);
  const metrics = Object.create(null);
  metrics.reset = ()=>{
    let k;
    const r = (m)=>(m.count = m.time = m.wait = 0);
    for(k in state.opIds){
      r(metrics[k] = Object.create(null));
    }
    let s = metrics.s11n = Object.create(null);
    s = s.serialize = Object.create(null);
    s.count = s.time = 0;
    s = metrics.s11n.deserialize = Object.create(null);
    s.count = s.time = 0;
  };
  metrics.dump = ()=>{
    let k, n = 0, t = 0, w = 0;
    for(k in state.opIds){
      const m = metrics[k];
      n += m.count;
      t += m.time;
      w += m.wait;
      m.avgTime = (m.count && m.time) ? (m.time / m.count) : 0;
    }
    console.log(self.location.href,
                "metrics for",self.location.href,":\n",
                metrics,
                "\nTotal of",n,"op(s) for",t,"ms",
                "approx",w,"ms spent waiting on OPFS APIs.");
    console.log("Serialization metrics:",metrics.s11n);
  };

  /**
     __openFiles is a map of sqlite3_file pointers (integers) to
     metadata related to a given OPFS file handles. The pointers are, in
     this side of the interface, opaque file handle IDs provided by the
     synchronous part of this constellation. Each value is an object
     with a structure demonstrated in the xOpen() impl.
  */
  const __openFiles = Object.create(null);
  /**
     __implicitLocks is a Set of sqlite3_file pointers (integers) which were
     "auto-locked".  i.e. those for which we obtained a sync access
     handle without an explicit xLock() call. Such locks will be
     released during db connection idle time, whereas a sync access
     handle obtained via xLock(), or subsequently xLock()'d after
     auto-acquisition, will not be released until xUnlock() is called.

     Maintenance reminder: if we relinquish auto-locks at the end of the
     operation which acquires them, we pay a massive performance
     penalty: speedtest1 benchmarks take up to 4x as long. By delaying
     the lock release until idle time, the hit is negligible.
  */
  const __implicitLocks = new Set();

  /**
     Expects an OPFS file path. It gets resolved, such that ".."
     components are properly expanded, and returned. If the 2nd arg is
     true, the result is returned as an array of path elements, else an
     absolute path string is returned.
  */
  const getResolvedPath = function(filename,splitIt){
    const p = new URL(
      filename, 'file://irrelevant'
    ).pathname;
    return splitIt ? p.split('/').filter((v)=>!!v) : p;
  };

  /**
     Takes the absolute path to a filesystem element. Returns an array
     of [handleOfContainingDir, filename]. If the 2nd argument is truthy
     then each directory element leading to the file is created along
     the way. Throws if any creation or resolution fails.
  */
  const getDirForFilename = async function f(absFilename, createDirs = false){
    const path = getResolvedPath(absFilename, true);
    const filename = path.pop();
    let dh = state.rootDir;
    for(const dirName of path){
      if(dirName){
        dh = await dh.getDirectoryHandle(dirName, {create: !!createDirs});
      }
    }
    return [dh, filename];
  };

  /**
     If the given file-holding object has a sync handle attached to it,
     that handle is remove and asynchronously closed. Though it may
     sound sensible to continue work as soon as the close() returns
     (noting that it's asynchronous), doing so can cause operations
     performed soon afterwards, e.g. a call to getSyncHandle() to fail
     because they may happen out of order from the close(). OPFS does
     not guaranty that the actual order of operations is retained in
     such cases. i.e.  always "await" on the result of this function.
  */
  const closeSyncHandle = async (fh)=>{
    if(fh.syncHandle){
      log("Closing sync handle for",fh.filenameAbs);
      const h = fh.syncHandle;
      delete fh.syncHandle;
      delete fh.xLock;
      __implicitLocks.delete(fh.fid);
      return h.close();
    }
  };

  /**
     A proxy for closeSyncHandle() which is guaranteed to not throw.

     This function is part of a lock/unlock step in functions which
     require a sync access handle but may be called without xLock()
     having been called first. Such calls need to release that
     handle to avoid locking the file for all of time. This is an
     _attempt_ at reducing cross-tab contention but it may prove
     to be more of a problem than a solution and may need to be
     removed.
  */
  const closeSyncHandleNoThrow = async (fh)=>{
    try{await closeSyncHandle(fh)}
    catch(e){
      warn("closeSyncHandleNoThrow() ignoring:",e,fh);
    }
  };

  /* Release all auto-locks. */
  const releaseImplicitLocks = async ()=>{
    if(__implicitLocks.size){
      /* Release all auto-locks. */
      for(const fid of __implicitLocks){
        const fh = __openFiles[fid];
        await closeSyncHandleNoThrow(fh);
        log("Auto-unlocked",fid,fh.filenameAbs);
      }
    }
  };

  /**
     An experiment in improving concurrency by freeing up implicit locks
     sooner. This is known to impact performance dramatically but it has
     also shown to improve concurrency considerably.

     If fh.releaseImplicitLocks is truthy and fh is in __implicitLocks,
     this routine returns closeSyncHandleNoThrow(), else it is a no-op.
  */
  const releaseImplicitLock = async (fh)=>{
    if(fh.releaseImplicitLocks && __implicitLocks.has(fh.fid)){
      return closeSyncHandleNoThrow(fh);
    }
  };

  /**
     An error class specifically for use with getSyncHandle(), the goal
     of which is to eventually be able to distinguish unambiguously
     between locking-related failures and other types, noting that we
     cannot currently do so because createSyncAccessHandle() does not
     define its exceptions in the required level of detail.

     2022-11-29: according to:

     https://github.com/whatwg/fs/pull/21

     NoModificationAllowedError will be the standard exception thrown
     when acquisition of a sync access handle fails due to a locking
     error. As of this writing, that error type is not visible in the
     dev console in Chrome v109, nor is it documented in MDN, but an
     error with that "name" property is being thrown from the OPFS
     layer.
  */
  class GetSyncHandleError extends Error {
    constructor(errorObject, ...msg){
      super([
        ...msg, ': '+errorObject.name+':',
        errorObject.message
      ].join(' '), {
        cause: errorObject
      });
      this.name = 'GetSyncHandleError';
    }
  };
  GetSyncHandleError.convertRc = (e,rc)=>{
    if(1){
      return (
        e instanceof GetSyncHandleError
          && ((e.cause.name==='NoModificationAllowedError')
              /* Inconsistent exception.name from Chrome/ium with the
                 same exception.message text: */
              || (e.cause.name==='DOMException'
                  && 0===e.cause.message.indexOf('Access Handles cannot')))
      ) ? (
        /*console.warn("SQLITE_BUSY",e),*/
        state.sq3Codes.SQLITE_BUSY
      ) : rc;
    }else{
      return rc;
    }
  }
  /**
     Returns the sync access handle associated with the given file
     handle object (which must be a valid handle object, as created by
     xOpen()), lazily opening it if needed.

     In order to help alleviate cross-tab contention for a dabase, if
     an exception is thrown while acquiring the handle, this routine
     will wait briefly and try again, up to some fixed number of
     times. If acquisition still fails at that point it will give up
     and propagate the exception. Client-level code will see that as
     an I/O error.
  */
  const getSyncHandle = async (fh,opName)=>{
    if(!fh.syncHandle){
      const t = performance.now();
      log("Acquiring sync handle for",fh.filenameAbs);
      const maxTries = 6,
            msBase = state.asyncIdleWaitTime * 2;
      let i = 1, ms = msBase;
      for(; true; ms = msBase * ++i){
        try {
          //if(i<3) toss("Just testing getSyncHandle() wait-and-retry.");
          //TODO? A config option which tells it to throw here
          //randomly every now and then, for testing purposes.
          fh.syncHandle = await fh.fileHandle.createSyncAccessHandle();
          break;
        }catch(e){
          if(i === maxTries){
            throw new GetSyncHandleError(
              e, "Error getting sync handle for",opName+"().",maxTries,
              "attempts failed.",fh.filenameAbs
            );
          }
          warn("Error getting sync handle for",opName+"(). Waiting",ms,
               "ms and trying again.",fh.filenameAbs,e);
          Atomics.wait(state.sabOPView, state.opIds.retry, 0, ms);
        }
      }
      log("Got",opName+"() sync handle for",fh.filenameAbs,
          'in',performance.now() - t,'ms');
      if(!fh.xLock){
        __implicitLocks.add(fh.fid);
        log("Acquired implicit lock for",opName+"()",fh.fid,fh.filenameAbs);
      }
    }
    return fh.syncHandle;
  };

  /**
     Stores the given value at state.sabOPView[state.opIds.rc] and then
     Atomics.notify()'s it.
  */
  const storeAndNotify = (opName, value)=>{
    log(opName+"() => notify(",value,")");
    Atomics.store(state.sabOPView, state.opIds.rc, value);
    Atomics.notify(state.sabOPView, state.opIds.rc);
  };

  /**
     Throws if fh is a file-holding object which is flagged as read-only.
  */
  const affirmNotRO = function(opName,fh){
    if(fh.readOnly) toss(opName+"(): File is read-only: "+fh.filenameAbs);
  };

  /**
     We track 2 different timers: the "metrics" timer records how much
     time we spend performing work. The "wait" timer records how much
     time we spend waiting on the underlying OPFS timer. See the calls
     to mTimeStart(), mTimeEnd(), wTimeStart(), and wTimeEnd()
     throughout this file to see how they're used.
  */
  const __mTimer = Object.create(null);
  __mTimer.op = undefined;
  __mTimer.start = undefined;
  const mTimeStart = (op)=>{
    __mTimer.start = performance.now();
    __mTimer.op = op;
    //metrics[op] || toss("Maintenance required: missing metrics for",op);
    ++metrics[op].count;
  };
  const mTimeEnd = ()=>(
    metrics[__mTimer.op].time += performance.now() - __mTimer.start
  );
  const __wTimer = Object.create(null);
  __wTimer.op = undefined;
  __wTimer.start = undefined;
  const wTimeStart = (op)=>{
    __wTimer.start = performance.now();
    __wTimer.op = op;
    //metrics[op] || toss("Maintenance required: missing metrics for",op);
  };
  const wTimeEnd = ()=>(
    metrics[__wTimer.op].wait += performance.now() - __wTimer.start
  );

  /**
     Gets set to true by the 'opfs-async-shutdown' command to quit the
     wait loop. This is only intended for debugging purposes: we cannot
     inspect this file's state while the tight waitLoop() is running and
     need a way to stop that loop for introspection purposes.
  */
  let flagAsyncShutdown = false;

  /**
     Asynchronous wrappers for sqlite3_vfs and sqlite3_io_methods
     methods, as well as helpers like mkdir(). Maintenance reminder:
     members are in alphabetical order to simplify finding them.
  */
  const vfsAsyncImpls = {
    'opfs-async-metrics': async ()=>{
      mTimeStart('opfs-async-metrics');
      metrics.dump();
      storeAndNotify('opfs-async-metrics', 0);
      mTimeEnd();
    },
    'opfs-async-shutdown': async ()=>{
      flagAsyncShutdown = true;
      storeAndNotify('opfs-async-shutdown', 0);
    },
    mkdir: async (dirname)=>{
      mTimeStart('mkdir');
      let rc = 0;
      wTimeStart('mkdir');
      try {
        await getDirForFilename(dirname+"/filepart", true);
      }catch(e){
        state.s11n.storeException(2,e);
        rc = state.sq3Codes.SQLITE_IOERR;
      }finally{
        wTimeEnd();
      }
      storeAndNotify('mkdir', rc);
      mTimeEnd();
    },
    xAccess: async (filename)=>{
      mTimeStart('xAccess');
      /* OPFS cannot support the full range of xAccess() queries
         sqlite3 calls for. We can essentially just tell if the file
         is accessible, but if it is then it's automatically writable
         (unless it's locked, which we cannot(?) know without trying
         to open it). OPFS does not have the notion of read-only.

         The return semantics of this function differ from sqlite3's
         xAccess semantics because we are limited in what we can
         communicate back to our synchronous communication partner: 0 =
         accessible, non-0 means not accessible.
      */
      let rc = 0;
      wTimeStart('xAccess');
      try{
        const [dh, fn] = await getDirForFilename(filename);
        await dh.getFileHandle(fn);
      }catch(e){
        state.s11n.storeException(2,e);
        rc = state.sq3Codes.SQLITE_IOERR;
      }finally{
        wTimeEnd();
      }
      storeAndNotify('xAccess', rc);
      mTimeEnd();
    },
    xClose: async function(fid/*sqlite3_file pointer*/){
      const opName = 'xClose';
      mTimeStart(opName);
      __implicitLocks.delete(fid);
      const fh = __openFiles[fid];
      let rc = 0;
      wTimeStart(opName);
      if(fh){
        delete __openFiles[fid];
        await closeSyncHandle(fh);
        if(fh.deleteOnClose){
          try{ await fh.dirHandle.removeEntry(fh.filenamePart) }
          catch(e){ warn("Ignoring dirHandle.removeEntry() failure of",fh,e) }
        }
      }else{
        state.s11n.serialize();
        rc = state.sq3Codes.SQLITE_NOTFOUND;
      }
      wTimeEnd();
      storeAndNotify(opName, rc);
      mTimeEnd();
    },
    xDelete: async function(...args){
      mTimeStart('xDelete');
      const rc = await vfsAsyncImpls.xDeleteNoWait(...args);
      storeAndNotify('xDelete', rc);
      mTimeEnd();
    },
    xDeleteNoWait: async function(filename, syncDir = 0, recursive = false){
      /* The syncDir flag is, for purposes of the VFS API's semantics,
         ignored here. However, if it has the value 0x1234 then: after
         deleting the given file, recursively try to delete any empty
         directories left behind in its wake (ignoring any errors and
         stopping at the first failure).

         That said: we don't know for sure that removeEntry() fails if
         the dir is not empty because the API is not documented. It has,
         however, a "recursive" flag which defaults to false, so
         presumably it will fail if the dir is not empty and that flag
         is false.
      */
      let rc = 0;
      wTimeStart('xDelete');
      try {
        while(filename){
          const [hDir, filenamePart] = await getDirForFilename(filename, false);
          if(!filenamePart) break;
          await hDir.removeEntry(filenamePart, {recursive});
          if(0x1234 !== syncDir) break;
          recursive = false;
          filename = getResolvedPath(filename, true);
          filename.pop();
          filename = filename.join('/');
        }
      }catch(e){
        state.s11n.storeException(2,e);
        rc = state.sq3Codes.SQLITE_IOERR_DELETE;
      }
      wTimeEnd();
      return rc;
    },
    xFileSize: async function(fid/*sqlite3_file pointer*/){
      mTimeStart('xFileSize');
      const fh = __openFiles[fid];
      let rc = 0;
      wTimeStart('xFileSize');
      try{
        const sz = await (await getSyncHandle(fh,'xFileSize')).getSize();
        state.s11n.serialize(Number(sz));
      }catch(e){
        state.s11n.storeException(1,e);
        rc = GetSyncHandleError.convertRc(e,state.sq3Codes.SQLITE_IOERR);
      }
      await releaseImplicitLock(fh);
      wTimeEnd();
      storeAndNotify('xFileSize', rc);
      mTimeEnd();
    },
    xLock: async function(fid/*sqlite3_file pointer*/,
                          lockType/*SQLITE_LOCK_...*/){
      mTimeStart('xLock');
      const fh = __openFiles[fid];
      let rc = 0;
      const oldLockType = fh.xLock;
      fh.xLock = lockType;
      if( !fh.syncHandle ){
        wTimeStart('xLock');
        try {
          await getSyncHandle(fh,'xLock');
          __implicitLocks.delete(fid);
        }catch(e){
          state.s11n.storeException(1,e);
          rc = GetSyncHandleError.convertRc(e,state.sq3Codes.SQLITE_IOERR_LOCK);
          fh.xLock = oldLockType;
        }
        wTimeEnd();
      }
      storeAndNotify('xLock',rc);
      mTimeEnd();
    },
    xOpen: async function(fid/*sqlite3_file pointer*/, filename,
                          flags/*SQLITE_OPEN_...*/,
                          opfsFlags/*OPFS_...*/){
      const opName = 'xOpen';
      mTimeStart(opName);
      const create = (state.sq3Codes.SQLITE_OPEN_CREATE & flags);
      wTimeStart('xOpen');
      try{
        let hDir, filenamePart;
        try {
          [hDir, filenamePart] = await getDirForFilename(filename, !!create);
        }catch(e){
          state.s11n.storeException(1,e);
          storeAndNotify(opName, state.sq3Codes.SQLITE_NOTFOUND);
          mTimeEnd();
          wTimeEnd();
          return;
        }
        const hFile = await hDir.getFileHandle(filenamePart, {create});
        wTimeEnd();
        const fh = Object.assign(Object.create(null),{
          fid: fid,
          filenameAbs: filename,
          filenamePart: filenamePart,
          dirHandle: hDir,
          fileHandle: hFile,
          sabView: state.sabFileBufView,
          readOnly: create
            ? false : (state.sq3Codes.SQLITE_OPEN_READONLY & flags),
          deleteOnClose: !!(state.sq3Codes.SQLITE_OPEN_DELETEONCLOSE & flags)
        });
        fh.releaseImplicitLocks =
          (opfsFlags & state.opfsFlags.OPFS_UNLOCK_ASAP)
          || state.opfsFlags.defaultUnlockAsap;
        if(0 /* this block is modelled after something wa-sqlite
                does but it leads to immediate contention on journal files.
                Update: this approach reportedly only works for DELETE journal
                mode. */
           && (0===(flags & state.sq3Codes.SQLITE_OPEN_MAIN_DB))){
          /* sqlite does not lock these files, so go ahead and grab an OPFS
             lock. */
          fh.xLock = "xOpen"/* Truthy value to keep entry from getting
                               flagged as auto-locked. String value so
                               that we can easily distinguish is later
                               if needed. */;
          await getSyncHandle(fh,'xOpen');
        }
        __openFiles[fid] = fh;
        storeAndNotify(opName, 0);
      }catch(e){
        wTimeEnd();
        error(opName,e);
        state.s11n.storeException(1,e);
        storeAndNotify(opName, state.sq3Codes.SQLITE_IOERR);
      }
      mTimeEnd();
    },
    xRead: async function(fid/*sqlite3_file pointer*/,n,offset64){
      mTimeStart('xRead');
      let rc = 0, nRead;
      const fh = __openFiles[fid];
      try{
        wTimeStart('xRead');
        nRead = (await getSyncHandle(fh,'xRead')).read(
          fh.sabView.subarray(0, n),
          {at: Number(offset64)}
        );
        wTimeEnd();
        if(nRead < n){/* Zero-fill remaining bytes */
          fh.sabView.fill(0, nRead, n);
          rc = state.sq3Codes.SQLITE_IOERR_SHORT_READ;
        }
      }catch(e){
        if(undefined===nRead) wTimeEnd();
        error("xRead() failed",e,fh);
        state.s11n.storeException(1,e);
        rc = GetSyncHandleError.convertRc(e,state.sq3Codes.SQLITE_IOERR_READ);
      }
      await releaseImplicitLock(fh);
      storeAndNotify('xRead',rc);
      mTimeEnd();
    },
    xSync: async function(fid/*sqlite3_file pointer*/,flags/*ignored*/){
      mTimeStart('xSync');
      const fh = __openFiles[fid];
      let rc = 0;
      if(!fh.readOnly && fh.syncHandle){
        try {
          wTimeStart('xSync');
          await fh.syncHandle.flush();
        }catch(e){
          state.s11n.storeException(2,e);
          rc = state.sq3Codes.SQLITE_IOERR_FSYNC;
        }
        wTimeEnd();
      }
      storeAndNotify('xSync',rc);
      mTimeEnd();
    },
    xTruncate: async function(fid/*sqlite3_file pointer*/,size){
      mTimeStart('xTruncate');
      let rc = 0;
      const fh = __openFiles[fid];
      wTimeStart('xTruncate');
      try{
        affirmNotRO('xTruncate', fh);
        await (await getSyncHandle(fh,'xTruncate')).truncate(size);
      }catch(e){
        error("xTruncate():",e,fh);
        state.s11n.storeException(2,e);
        rc = GetSyncHandleError.convertRc(e,state.sq3Codes.SQLITE_IOERR_TRUNCATE);
      }
      await releaseImplicitLock(fh);
      wTimeEnd();
      storeAndNotify('xTruncate',rc);
      mTimeEnd();
    },
    xUnlock: async function(fid/*sqlite3_file pointer*/,
                            lockType/*SQLITE_LOCK_...*/){
      mTimeStart('xUnlock');
      let rc = 0;
      const fh = __openFiles[fid];
      if( state.sq3Codes.SQLITE_LOCK_NONE===lockType
          && fh.syncHandle ){
        wTimeStart('xUnlock');
        try { await closeSyncHandle(fh) }
        catch(e){
          state.s11n.storeException(1,e);
          rc = state.sq3Codes.SQLITE_IOERR_UNLOCK;
        }
        wTimeEnd();
      }
      storeAndNotify('xUnlock',rc);
      mTimeEnd();
    },
    xWrite: async function(fid/*sqlite3_file pointer*/,n,offset64){
      mTimeStart('xWrite');
      let rc;
      const fh = __openFiles[fid];
      wTimeStart('xWrite');
      try{
        affirmNotRO('xWrite', fh);
        rc = (
          n === (await getSyncHandle(fh,'xWrite'))
            .write(fh.sabView.subarray(0, n),
                   {at: Number(offset64)})
        ) ? 0 : state.sq3Codes.SQLITE_IOERR_WRITE;
      }catch(e){
        error("xWrite():",e,fh);
        state.s11n.storeException(1,e);
        rc = GetSyncHandleError.convertRc(e,state.sq3Codes.SQLITE_IOERR_WRITE);
      }
      await releaseImplicitLock(fh);
      wTimeEnd();
      storeAndNotify('xWrite',rc);
      mTimeEnd();
    }
  }/*vfsAsyncImpls*/;

  const initS11n = ()=>{
    /**
       ACHTUNG: this code is 100% duplicated in the other half of this
       proxy! The documentation is maintained in the "synchronous half".
    */
    if(state.s11n) return state.s11n;
    const textDecoder = new TextDecoder(),
          textEncoder = new TextEncoder('utf-8'),
          viewU8 = new Uint8Array(state.sabIO, state.sabS11nOffset, state.sabS11nSize),
          viewDV = new DataView(state.sabIO, state.sabS11nOffset, state.sabS11nSize);
    state.s11n = Object.create(null);
    const TypeIds = Object.create(null);
    TypeIds.number  = { id: 1, size: 8, getter: 'getFloat64', setter: 'setFloat64' };
    TypeIds.bigint  = { id: 2, size: 8, getter: 'getBigInt64', setter: 'setBigInt64' };
    TypeIds.boolean = { id: 3, size: 4, getter: 'getInt32', setter: 'setInt32' };
    TypeIds.string =  { id: 4 };
    const getTypeId = (v)=>(
      TypeIds[typeof v]
        || toss("Maintenance required: this value type cannot be serialized.",v)
    );
    const getTypeIdById = (tid)=>{
      switch(tid){
          case TypeIds.number.id: return TypeIds.number;
          case TypeIds.bigint.id: return TypeIds.bigint;
          case TypeIds.boolean.id: return TypeIds.boolean;
          case TypeIds.string.id: return TypeIds.string;
          default: toss("Invalid type ID:",tid);
      }
    };
    state.s11n.deserialize = function(clear=false){
      ++metrics.s11n.deserialize.count;
      const t = performance.now();
      const argc = viewU8[0];
      const rc = argc ? [] : null;
      if(argc){
        const typeIds = [];
        let offset = 1, i, n, v;
        for(i = 0; i < argc; ++i, ++offset){
          typeIds.push(getTypeIdById(viewU8[offset]));
        }
        for(i = 0; i < argc; ++i){
          const t = typeIds[i];
          if(t.getter){
            v = viewDV[t.getter](offset, state.littleEndian);
            offset += t.size;
          }else{/*String*/
            n = viewDV.getInt32(offset, state.littleEndian);
            offset += 4;
            v = textDecoder.decode(viewU8.slice(offset, offset+n));
            offset += n;
          }
          rc.push(v);
        }
      }
      if(clear) viewU8[0] = 0;
      //log("deserialize:",argc, rc);
      metrics.s11n.deserialize.time += performance.now() - t;
      return rc;
    };
    state.s11n.serialize = function(...args){
      const t = performance.now();
      ++metrics.s11n.serialize.count;
      if(args.length){
        //log("serialize():",args);
        const typeIds = [];
        let i = 0, offset = 1;
        viewU8[0] = args.length & 0xff /* header = # of args */;
        for(; i < args.length; ++i, ++offset){
          /* Write the TypeIds.id value into the next args.length
             bytes. */
          typeIds.push(getTypeId(args[i]));
          viewU8[offset] = typeIds[i].id;
        }
        for(i = 0; i < args.length; ++i) {
          /* Deserialize the following bytes based on their
             corresponding TypeIds.id from the header. */
          const t = typeIds[i];
          if(t.setter){
            viewDV[t.setter](offset, args[i], state.littleEndian);
            offset += t.size;
          }else{/*String*/
            const s = textEncoder.encode(args[i]);
            viewDV.setInt32(offset, s.byteLength, state.littleEndian);
            offset += 4;
            viewU8.set(s, offset);
            offset += s.byteLength;
          }
        }
        //log("serialize() result:",viewU8.slice(0,offset));
      }else{
        viewU8[0] = 0;
      }
      metrics.s11n.serialize.time += performance.now() - t;
    };

    state.s11n.storeException = state.asyncS11nExceptions
      ? ((priority,e)=>{
        if(priority<=state.asyncS11nExceptions){
          state.s11n.serialize([e.name,': ',e.message].join(""));
        }
      })
      : ()=>{};

    return state.s11n;
  }/*initS11n()*/;

  const waitLoop = async function f(){
    const opHandlers = Object.create(null);
    for(let k of Object.keys(state.opIds)){
      const vi = vfsAsyncImpls[k];
      if(!vi) continue;
      const o = Object.create(null);
      opHandlers[state.opIds[k]] = o;
      o.key = k;
      o.f = vi;
    }
    while(!flagAsyncShutdown){
      try {
        if('timed-out'===Atomics.wait(
          state.sabOPView, state.opIds.whichOp, 0, state.asyncIdleWaitTime
        )){
          await releaseImplicitLocks();
          continue;
        }
        const opId = Atomics.load(state.sabOPView, state.opIds.whichOp);
        Atomics.store(state.sabOPView, state.opIds.whichOp, 0);
        const hnd = opHandlers[opId] ?? toss("No waitLoop handler for whichOp #",opId);
        const args = state.s11n.deserialize(
          true /* clear s11n to keep the caller from confusing this with
                  an exception string written by the upcoming
                  operation */
        ) || [];
        //warn("waitLoop() whichOp =",opId, hnd, args);
        if(hnd.f) await hnd.f(...args);
        else error("Missing callback for opId",opId);
      }catch(e){
        error('in waitLoop():',e);
      }
    }
  };

  navigator.storage.getDirectory().then(function(d){
    state.rootDir = d;
    self.onmessage = function({data}){
      switch(data.type){
          case 'opfs-async-init':{
            /* Receive shared state from synchronous partner */
            const opt = data.args;
            for(const k in opt) state[k] = opt[k];
            state.verbose = opt.verbose ?? 1;
            state.sabOPView = new Int32Array(state.sabOP);
            state.sabFileBufView = new Uint8Array(state.sabIO, 0, state.fileBufferSize);
            state.sabS11nView = new Uint8Array(state.sabIO, state.sabS11nOffset, state.sabS11nSize);
            Object.keys(vfsAsyncImpls).forEach((k)=>{
              if(!Number.isFinite(state.opIds[k])){
                toss("Maintenance required: missing state.opIds[",k,"]");
              }
            });
            initS11n();
            metrics.reset();
            log("init state",state);
            wPost('opfs-async-inited');
            waitLoop();
            break;
          }
          case 'opfs-async-restart':
            if(flagAsyncShutdown){
              warn("Restarting after opfs-async-shutdown. Might or might not work.");
              flagAsyncShutdown = false;
              waitLoop();
            }
            break;
          case 'opfs-async-metrics':
            metrics.dump();
            break;
      }
    };
    wPost('opfs-async-loaded');
  }).catch((e)=>error("error initializing OPFS asyncer:",e));
}/*installAsyncProxy()*/;
if(!self.SharedArrayBuffer){
  wPost('opfs-unavailable', "Missing SharedArrayBuffer API.",
        "The server must emit the COOP/COEP response headers to enable that.");
}else if(!self.Atomics){
  wPost('opfs-unavailable', "Missing Atomics API.",
        "The server must emit the COOP/COEP response headers to enable that.");
}else if(!self.FileSystemHandle ||
         !self.FileSystemDirectoryHandle ||
         !self.FileSystemFileHandle ||
         !self.FileSystemFileHandle.prototype.createSyncAccessHandle ||
         !navigator.storage.getDirectory){
  wPost('opfs-unavailable',"Missing required OPFS APIs.");
}else{
  installAsyncProxy(self);
}

Added ext/wasm/api/sqlite3-v-helper.js.











































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2022-11-30
**
** 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 installs sqlite3.vfs, and object which exists to assist
   in the creation of JavaScript implementations of sqlite3_vfs, along
   with its virtual table counterpart, sqlite3.vtab.
*/
'use strict';
self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
  const wasm = sqlite3.wasm, capi = sqlite3.capi, toss = sqlite3.util.toss3;
  const vfs = Object.create(null), vtab = Object.create(null);

  sqlite3.vfs = vfs;
  sqlite3.vtab = vtab;

  const sii = capi.sqlite3_index_info;
  /**
     If n is >=0 and less than this.$nConstraint, this function
     returns either a WASM pointer to the 0-based nth entry of
     this.$aConstraint (if passed a truthy 2nd argument) or an
     sqlite3_index_info.sqlite3_index_constraint object wrapping that
     address (if passed a falsy value or no 2nd argument). Returns a
     falsy value if n is out of range.
  */
  sii.prototype.nthConstraint = function(n, asPtr=false){
    if(n<0 || n>=this.$nConstraint) return false;
    const ptr = this.$aConstraint + (
      sii.sqlite3_index_constraint.structInfo.sizeof * n
    );
    return asPtr ? ptr : new sii.sqlite3_index_constraint(ptr);
  };

  /**
     Works identically to nthConstraint() but returns state from
     this.$aConstraintUsage, so returns an
     sqlite3_index_info.sqlite3_index_constraint_usage instance
     if passed no 2nd argument or a falsy 2nd argument.
  */
  sii.prototype.nthConstraintUsage = function(n, asPtr=false){
    if(n<0 || n>=this.$nConstraint) return false;
    const ptr = this.$aConstraintUsage + (
      sii.sqlite3_index_constraint_usage.structInfo.sizeof * n
    );
    return asPtr ? ptr : new sii.sqlite3_index_constraint_usage(ptr);
  };

  /**
     If n is >=0 and less than this.$nOrderBy, this function
     returns either a WASM pointer to the 0-based nth entry of
     this.$aOrderBy (if passed a truthy 2nd argument) or an
     sqlite3_index_info.sqlite3_index_orderby object wrapping that
     address (if passed a falsy value or no 2nd argument). Returns a
     falsy value if n is out of range.
  */
  sii.prototype.nthOrderBy = function(n, asPtr=false){
    if(n<0 || n>=this.$nOrderBy) return false;
    const ptr = this.$aOrderBy + (
      sii.sqlite3_index_orderby.structInfo.sizeof * n
    );
    return asPtr ? ptr : new sii.sqlite3_index_orderby(ptr);
  };

  /**
     Installs a StructBinder-bound function pointer member of the
     given name and function in the given StructType target object.

     It creates a WASM proxy for the given function and arranges for
     that proxy to be cleaned up when tgt.dispose() is called. Throws
     on the slightest hint of error, e.g. tgt is-not-a StructType,
     name does not map to a struct-bound member, etc.

     As a special case, if the given function is a pointer, then
     `wasm.functionEntry()` is used to validate that it is a known
     function. If so, it is used as-is with no extra level of proxying
     or cleanup, else an exception is thrown. It is legal to pass a
     value of 0, indicating a NULL pointer, with the caveat that 0
     _is_ a legal function pointer in WASM but it will not be accepted
     as such _here_. (Justification: the function at address zero must
     be one which initially came from the WASM module, not a method we
     want to bind to a virtual table or VFS.)

     This function returns a proxy for itself which is bound to tgt
     and takes 2 args (name,func). That function returns the same
     thing as this one, permitting calls to be chained.

     If called with only 1 arg, it has no side effects but returns a
     func with the same signature as described above.

     ACHTUNG: because we cannot generically know how to transform JS
     exceptions into result codes, the installed functions do no
     automatic catching of exceptions. It is critical, to avoid 
     undefined behavior in the C layer, that methods mapped via
     this function do not throw. The exception, as it were, to that
     rule is...

     If applyArgcCheck is true then each JS function (as opposed to
     function pointers) gets wrapped in a proxy which asserts that it
     is passed the expected number of arguments, throwing if the
     argument count does not match expectations. That is only intended
     for dev-time usage for sanity checking, and will leave the C
     environment in an undefined state.
  */
  const installMethod = function callee(
    tgt, name, func, applyArgcCheck = callee.installMethodArgcCheck
  ){
    if(!(tgt instanceof sqlite3.StructBinder.StructType)){
      toss("Usage error: target object is-not-a StructType.");
    }else if(!(func instanceof Function) && !wasm.isPtr(func)){
      toss("Usage errror: expecting a Function or WASM pointer to one.");
    }
    if(1===arguments.length){
      return (n,f)=>callee(tgt, n, f, applyArgcCheck);
    }
    if(!callee.argcProxy){
      callee.argcProxy = function(tgt, funcName, func,sig){
        return function(...args){
          if(func.length!==arguments.length){
            toss("Argument mismatch for",
                 tgt.structInfo.name+"::"+funcName
                 +": Native signature is:",sig);
          }
          return func.apply(this, args);
        }
      };
      /* An ondispose() callback for use with
         sqlite3.StructBinder-created types. */
      callee.removeFuncList = function(){
        if(this.ondispose.__removeFuncList){
          this.ondispose.__removeFuncList.forEach(
            (v,ndx)=>{
              if('number'===typeof v){
                try{wasm.uninstallFunction(v)}
                catch(e){/*ignore*/}
              }
              /* else it's a descriptive label for the next number in
                 the list. */
            }
          );
          delete this.ondispose.__removeFuncList;
        }
      };
    }/*static init*/
    const sigN = tgt.memberSignature(name);
    if(sigN.length<2){
      toss("Member",name,"does not have a function pointer signature:",sigN);
    }
    const memKey = tgt.memberKey(name);
    const fProxy = (applyArgcCheck && !wasm.isPtr(func))
    /** This middle-man proxy is only for use during development, to
        confirm that we always pass the proper number of
        arguments. We know that the C-level code will always use the
        correct argument count. */
          ? callee.argcProxy(tgt, memKey, func, sigN)
          : func;
    if(wasm.isPtr(fProxy)){
      if(fProxy && !wasm.functionEntry(fProxy)){
        toss("Pointer",fProxy,"is not a WASM function table entry.");
      }
      tgt[memKey] = fProxy;
    }else{
      const pFunc = wasm.installFunction(fProxy, tgt.memberSignature(name, true));
      tgt[memKey] = pFunc;
      if(!tgt.ondispose || !tgt.ondispose.__removeFuncList){
        tgt.addOnDispose('ondispose.__removeFuncList handler',
                         callee.removeFuncList);
        tgt.ondispose.__removeFuncList = [];
      }
      tgt.ondispose.__removeFuncList.push(memKey, pFunc);
    }
    return (n,f)=>callee(tgt, n, f, applyArgcCheck);
  }/*installMethod*/;
  installMethod.installMethodArgcCheck = false;

  /**
     Installs methods into the given StructType-type instance. Each
     entry in the given methods object must map to a known member of
     the given StructType, else an exception will be triggered.  See
     installMethod() for more details, including the semantics of the
     3rd argument.

     As an exception to the above, if any two or more methods in the
     2nd argument are the exact same function, installMethod() is
     _not_ called for the 2nd and subsequent instances, and instead
     those instances get assigned the same method pointer which is
     created for the first instance. This optimization is primarily to
     accommodate special handling of sqlite3_module::xConnect and
     xCreate methods.

     On success, returns its first argument. Throws on error.
  */
  const installMethods = function(
    structInstance, methods, applyArgcCheck = installMethod.installMethodArgcCheck
  ){
    const seen = new Map /* map of <Function, memberName> */;
    for(const k of Object.keys(methods)){
      const m = methods[k];
      const prior = seen.get(m);
      if(prior){
        const mkey = structInstance.memberKey(k);
        structInstance[mkey] = structInstance[structInstance.memberKey(prior)];
      }else{
        installMethod(structInstance, k, m, applyArgcCheck);
        seen.set(m, k);
      }
    }
    return structInstance;
  };

  /**
     Equivalent to calling installMethod(this,...arguments) with a
     first argument of this object. If called with 1 or 2 arguments
     and the first is an object, it's instead equivalent to calling
     installMethods(this,...arguments).
  */
  sqlite3.StructBinder.StructType.prototype.installMethod = function callee(
    name, func, applyArgcCheck = installMethod.installMethodArgcCheck
  ){
    return (arguments.length < 3 && name && 'object'===typeof name)
      ? installMethods(this, ...arguments)
      : installMethod(this, ...arguments);
  };

  /**
     Equivalent to calling installMethods() with a first argument
     of this object.
  */
  sqlite3.StructBinder.StructType.prototype.installMethods = function(
    methods, applyArgcCheck = installMethod.installMethodArgcCheck
  ){
    return installMethods(this, methods, applyArgcCheck);
  };

  /**
     Uses sqlite3_vfs_register() to register this
     sqlite3.capi.sqlite3_vfs. This object must have already been
     filled out properly. If the first argument is truthy, the VFS is
     registered as the default VFS, else it is not.

     On success, returns this object. Throws on error.
  */
  capi.sqlite3_vfs.prototype.registerVfs = function(asDefault=false){
    if(!(this instanceof sqlite3.capi.sqlite3_vfs)){
      toss("Expecting a sqlite3_vfs-type argument.");
    }
    const rc = capi.sqlite3_vfs_register(this, asDefault ? 1 : 0);
    if(rc){
      toss("sqlite3_vfs_register(",this,") failed with rc",rc);
    }
    if(this.pointer !== capi.sqlite3_vfs_find(this.$zName)){
      toss("BUG: sqlite3_vfs_find(vfs.$zName) failed for just-installed VFS",
           this);
    }
    return this;
  };

  /**
     A wrapper for installMethods() or registerVfs() to reduce
     installation of a VFS and/or its I/O methods to a single
     call.

     Accepts an object which contains the properties "io" and/or
     "vfs", each of which is itself an object with following properties:

     - `struct`: an sqlite3.StructType-type struct. This must be a
       populated (except for the methods) object of type
       sqlite3_io_methods (for the "io" entry) or sqlite3_vfs (for the
       "vfs" entry).

     - `methods`: an object mapping sqlite3_io_methods method names
       (e.g. 'xClose') to JS implementations of those methods. The JS
       implementations must be call-compatible with their native
       counterparts.

     For each of those object, this function passes its (`struct`,
     `methods`, (optional) `applyArgcCheck`) properties to
     installMethods().

     If the `vfs` entry is set then:

     - Its `struct` property's registerVfs() is called. The
       `vfs` entry may optionally have an `asDefault` property, which
       gets passed as the argument to registerVfs().

     - If `struct.$zName` is falsy and the entry has a string-type
       `name` property, `struct.$zName` is set to the C-string form of
       that `name` value before registerVfs() is called.

     On success returns this object. Throws on error.
  */
  vfs.installVfs = function(opt){
    let count = 0;
    const propList = ['io','vfs'];
    for(const key of propList){
      const o = opt[key];
      if(o){
        ++count;
        installMethods(o.struct, o.methods, !!o.applyArgcCheck);
        if('vfs'===key){
          if(!o.struct.$zName && 'string'===typeof o.name){
            o.struct.addOnDispose(
              o.struct.$zName = wasm.allocCString(o.name)
            );
          }
          o.struct.registerVfs(!!o.asDefault);
        }
      }
    }
    if(!count) toss("Misuse: installVfs() options object requires at least",
                    "one of:", propList);
    return this;
  };

  /**
     Internal factory function for xVtab and xCursor impls.
  */
  const __xWrapFactory = function(methodName,StructType){
    return function(ptr,removeMapping=false){
      if(0===arguments.length) ptr = new StructType;
      if(ptr instanceof StructType){
        //T.assert(!this.has(ptr.pointer));
        this.set(ptr.pointer, ptr);
        return ptr;
      }else if(!wasm.isPtr(ptr)){
        sqlite3.SQLite3Error.toss("Invalid argument to",methodName+"()");
      }
      let rc = this.get(ptr);
      if(removeMapping) this.delete(ptr);
      return rc;
    }.bind(new Map);
  };

  /**
     A factory function which implements a simple lifetime manager for
     mappings between C struct pointers and their JS-level wrappers.
     The first argument must be the logical name of the manager
     (e.g. 'xVtab' or 'xCursor'), which is only used for error
     reporting. The second must be the capi.XYZ struct-type value,
     e.g. capi.sqlite3_vtab or capi.sqlite3_vtab_cursor.

     Returns an object with 4 methods: create(), get(), unget(), and
     dispose(), plus a StructType member with the value of the 2nd
     argument. The methods are documented in the body of this
     function.
  */
  const StructPtrMapper = function(name, StructType){
    const __xWrap = __xWrapFactory(name,StructType);
    /**
       This object houses a small API for managing mappings of (`T*`)
       to StructType<T> objects, specifically within the lifetime
       requirements of sqlite3_module methods.
    */
    return Object.assign(Object.create(null),{
      /** The StructType object for this object's API. */
      StructType,
      /**
         Creates a new StructType object, writes its `pointer`
         value to the given output pointer, and returns that
         object. Its intended usage depends on StructType:

         sqlite3_vtab: to be called from sqlite3_module::xConnect()
         or xCreate() implementations.

         sqlite3_vtab_cursor: to be called from xOpen().

         This will throw if allocation of the StructType instance
         fails or if ppOut is not a pointer-type value.
      */
      create: (ppOut)=>{
        const rc = __xWrap();
        wasm.pokePtr(ppOut, rc.pointer);
        return rc;
      },
      /**
         Returns the StructType object previously mapped to the
         given pointer using create(). Its intended usage depends
         on StructType:

         sqlite3_vtab: to be called from sqlite3_module methods which
         take a (sqlite3_vtab*) pointer _except_ for
         xDestroy()/xDisconnect(), in which case unget() or dispose().

         sqlite3_vtab_cursor: to be called from any sqlite3_module methods
         which take a `sqlite3_vtab_cursor*` argument except xClose(),
         in which case use unget() or dispose().

         Rule to remember: _never_ call dispose() on an instance
         returned by this function.
      */
      get: (pCObj)=>__xWrap(pCObj),
      /**
         Identical to get() but also disconnects the mapping between the
         given pointer and the returned StructType object, such that
         future calls to this function or get() with the same pointer
         will return the undefined value. Its intended usage depends
         on StructType:

         sqlite3_vtab: to be called from sqlite3_module::xDisconnect() or
         xDestroy() implementations or in error handling of a failed
         xCreate() or xConnect().

         sqlite3_vtab_cursor: to be called from xClose() or during
         cleanup in a failed xOpen().

         Calling this method obligates the caller to call dispose() on
         the returned object when they're done with it.
      */
      unget: (pCObj)=>__xWrap(pCObj,true),
      /**
         Works like unget() plus it calls dispose() on the
         StructType object.
      */
      dispose: (pCObj)=>{
        const o = __xWrap(pCObj,true);
        if(o) o.dispose();
      }
    });
  };

  /**
     A lifetime-management object for mapping `sqlite3_vtab*`
     instances in sqlite3_module methods to capi.sqlite3_vtab
     objects.

     The API docs are in the API-internal StructPtrMapper().
  */
  vtab.xVtab = StructPtrMapper('xVtab', capi.sqlite3_vtab);

  /**
     A lifetime-management object for mapping `sqlite3_vtab_cursor*`
     instances in sqlite3_module methods to capi.sqlite3_vtab_cursor
     objects.

     The API docs are in the API-internal StructPtrMapper().
  */
  vtab.xCursor = StructPtrMapper('xCursor', capi.sqlite3_vtab_cursor);

  /**
     Convenience form of creating an sqlite3_index_info wrapper,
     intended for use in xBestIndex implementations. Note that the
     caller is expected to call dispose() on the returned object
     before returning. Though not _strictly_ required, as that object
     does not own the pIdxInfo memory, it is nonetheless good form.
  */
  vtab.xIndexInfo = (pIdxInfo)=>new capi.sqlite3_index_info(pIdxInfo);

  /**
     Given an error object, this function returns
     sqlite3.capi.SQLITE_NOMEM if (e instanceof
     sqlite3.WasmAllocError), else it returns its
     second argument. Its intended usage is in the methods
     of a sqlite3_vfs or sqlite3_module:

     ```
     try{
      let rc = ...
      return rc;
     }catch(e){
       return sqlite3.vtab.exceptionToRc(e, sqlite3.capi.SQLITE_XYZ);
       // where SQLITE_XYZ is some call-appropriate result code.
     }
     ```
  */
  /**vfs.exceptionToRc = vtab.exceptionToRc =
    (e, defaultRc=capi.SQLITE_ERROR)=>(
      (e instanceof sqlite3.WasmAllocError)
        ? capi.SQLITE_NOMEM
        : defaultRc
    );*/

  /**
     Given an sqlite3_module method name and error object, this
     function returns sqlite3.capi.SQLITE_NOMEM if (e instanceof
     sqlite3.WasmAllocError), else it returns its second argument. Its
     intended usage is in the methods of a sqlite3_vfs or
     sqlite3_module:

     ```
     try{
      let rc = ...
      return rc;
     }catch(e){
       return sqlite3.vtab.xError(
                'xColumn', e, sqlite3.capi.SQLITE_XYZ);
       // where SQLITE_XYZ is some call-appropriate result code.
     }
     ```

     If no 3rd argument is provided, its default depends on
     the error type:

     - An sqlite3.WasmAllocError always resolves to capi.SQLITE_NOMEM.

     - If err is an SQLite3Error then its `resultCode` property
       is used.

     - If all else fails, capi.SQLITE_ERROR is used.

     If xError.errorReporter is a function, it is called in
     order to report the error, else the error is not reported.
     If that function throws, that exception is ignored.
  */
  vtab.xError = function f(methodName, err, defaultRc){
    if(f.errorReporter instanceof Function){
      try{f.errorReporter("sqlite3_module::"+methodName+"(): "+err.message);}
      catch(e){/*ignored*/}
    }
    let rc;
    if(err instanceof sqlite3.WasmAllocError) rc = capi.SQLITE_NOMEM;
    else if(arguments.length>2) rc = defaultRc;
    else if(err instanceof sqlite3.SQLite3Error) rc = err.resultCode;
    return rc || capi.SQLITE_ERROR;
  };
  vtab.xError.errorReporter = 1 ? console.error.bind(console) : false;

  /**
     "The problem" with this is that it introduces an outer function with
     a different arity than the passed-in method callback. That means we
     cannot do argc validation on these. Additionally, some methods (namely
     xConnect) may have call-specific error handling. It would be a shame to
     hard-coded that per-method support in this function.
  */
  /** vtab.methodCatcher = function(methodName, method, defaultErrRc=capi.SQLITE_ERROR){
    return function(...args){
      try { method(...args); }
      }catch(e){ return vtab.xError(methodName, e, defaultRc) }
  };
  */

  /**
     A helper for sqlite3_vtab::xRowid() and xUpdate()
     implementations. It must be passed the final argument to one of
     those methods (an output pointer to an int64 row ID) and the
     value to store at the output pointer's address. Returns the same
     as wasm.poke() and will throw if the 1st or 2nd arguments
     are invalid for that function.

     Example xRowid impl:

     ```
     const xRowid = (pCursor, ppRowid64)=>{
       const c = vtab.xCursor(pCursor);
       vtab.xRowid(ppRowid64, c.myRowId);
       return 0;
     };
     ```
  */
  vtab.xRowid = (ppRowid64, value)=>wasm.poke(ppRowid64, value, 'i64');

  /**
     A helper to initialize and set up an sqlite3_module object for
     later installation into individual databases using
     sqlite3_create_module(). Requires an object with the following
     properties:

     - `methods`: an object containing a mapping of properties with
       the C-side names of the sqlite3_module methods, e.g. xCreate,
       xBestIndex, etc., to JS implementations for those functions.
       Certain special-case handling is performed, as described below.

     - `catchExceptions` (default=false): if truthy, the given methods
       are not mapped as-is, but are instead wrapped inside wrappers
       which translate exceptions into result codes of SQLITE_ERROR or
       SQLITE_NOMEM, depending on whether the exception is an
       sqlite3.WasmAllocError. In the case of the xConnect and xCreate
       methods, the exception handler also sets the output error
       string to the exception's error string.

     - OPTIONAL `struct`: a sqlite3.capi.sqlite3_module() instance. If
       not set, one will be created automatically. If the current
       "this" is-a sqlite3_module then it is unconditionally used in
       place of `struct`.

     - OPTIONAL `iVersion`: if set, it must be an integer value and it
       gets assigned to the `$iVersion` member of the struct object.
       If it's _not_ set, and the passed-in `struct` object's `$iVersion`
       is 0 (the default) then this function attempts to define a value
       for that property based on the list of methods it has.

     If `catchExceptions` is false, it is up to the client to ensure
     that no exceptions escape the methods, as doing so would move
     them through the C API, leading to undefined
     behavior. (vtab.xError() is intended to assist in reporting
     such exceptions.)

     Certain methods may refer to the same implementation. To simplify
     the definition of such methods:

     - If `methods.xConnect` is `true` then the value of
       `methods.xCreate` is used in its place, and vice versa. sqlite
       treats xConnect/xCreate functions specially if they are exactly
       the same function (same pointer value).

     - If `methods.xDisconnect` is true then the value of
       `methods.xDestroy` is used in its place, and vice versa.

     This is to facilitate creation of those methods inline in the
     passed-in object without requiring the client to explicitly get a
     reference to one of them in order to assign it to the other
     one. 

     The `catchExceptions`-installed handlers will account for
     identical references to the above functions and will install the
     same wrapper function for both.

     The given methods are expected to return integer values, as
     expected by the C API. If `catchExceptions` is truthy, the return
     value of the wrapped function will be used as-is and will be
     translated to 0 if the function returns a falsy value (e.g. if it
     does not have an explicit return). If `catchExceptions` is _not_
     active, the method implementations must explicitly return integer
     values.

     Throws on error. On success, returns the sqlite3_module object
     (`this` or `opt.struct` or a new sqlite3_module instance,
     depending on how it's called).
  */
  vtab.setupModule = function(opt){
    let createdMod = false;
    const mod = (this instanceof capi.sqlite3_module)
          ? this : (opt.struct || (createdMod = new capi.sqlite3_module()));
    try{
      const methods = opt.methods || toss("Missing 'methods' object.");
      for(const e of Object.entries({
        // -----^ ==> [k,v] triggers a broken code transformation in
        // some versions of the emsdk toolchain.
        xConnect: 'xCreate', xDisconnect: 'xDestroy'
      })){
        // Remap X=true to X=Y for certain X/Y combinations
        const k = e[0], v = e[1];
        if(true === methods[k]) methods[k] = methods[v];
        else if(true === methods[v]) methods[v] = methods[k];
      }
      if(opt.catchExceptions){
        const fwrap = function(methodName, func){
          if(['xConnect','xCreate'].indexOf(methodName) >= 0){
            return function(pDb, pAux, argc, argv, ppVtab, pzErr){
              try{return func(...arguments) || 0}
              catch(e){
                if(!(e instanceof sqlite3.WasmAllocError)){
                  wasm.dealloc(wasm.peekPtr(pzErr));
                  wasm.pokePtr(pzErr, wasm.allocCString(e.message));
                }
                return vtab.xError(methodName, e);
              }
            };
          }else{
            return function(...args){
              try{return func(...args) || 0}
              catch(e){
                return vtab.xError(methodName, e);
              }
            };
          }
        };
        const mnames = [
          'xCreate', 'xConnect', 'xBestIndex', 'xDisconnect',
          'xDestroy', 'xOpen', 'xClose', 'xFilter', 'xNext',
          'xEof', 'xColumn', 'xRowid', 'xUpdate',
          'xBegin', 'xSync', 'xCommit', 'xRollback',
          'xFindFunction', 'xRename', 'xSavepoint', 'xRelease',
          'xRollbackTo', 'xShadowName'
        ];
        const remethods = Object.create(null);
        for(const k of mnames){
          const m = methods[k];
          if(!(m instanceof Function)) continue;
          else if('xConnect'===k && methods.xCreate===m){
            remethods[k] = methods.xCreate;
          }else if('xCreate'===k && methods.xConnect===m){
            remethods[k] = methods.xConnect;
          }else{
            remethods[k] = fwrap(k, m);
          }
        }
        installMethods(mod, remethods, false);
      }else{
        // No automatic exception handling. Trust the client
        // to not throw.
        installMethods(
          mod, methods, !!opt.applyArgcCheck/*undocumented option*/
        );
      }
      if(0===mod.$iVersion){
        let v;
        if('number'===typeof opt.iVersion) v = opt.iVersion;
        else if(mod.$xShadowName) v = 3;
        else if(mod.$xSavePoint || mod.$xRelease || mod.$xRollbackTo) v = 2;
        else v = 1;
        mod.$iVersion = v;
      }
    }catch(e){
      if(createdMod) createdMod.dispose();
      throw e;
    }
    return mod;
  }/*setupModule()*/;

  /**
     Equivalent to calling vtab.setupModule() with this sqlite3_module
     object as the call's `this`.
  */
  capi.sqlite3_module.prototype.setupModule = function(opt){
    return vtab.setupModule.call(this, opt);
  };
}/*sqlite3ApiBootstrap.initializers.push()*/);

Added ext/wasm/api/sqlite3-vfs-opfs.c-pp.js.



















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
  2022-09-18

  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 holds the synchronous half of an sqlite3_vfs
  implementation which proxies, in a synchronous fashion, the
  asynchronous Origin-Private FileSystem (OPFS) APIs using a second
  Worker, implemented in sqlite3-opfs-async-proxy.js.  This file is
  intended to be appended to the main sqlite3 JS deliverable somewhere
  after sqlite3-api-oo1.js and before sqlite3-api-cleanup.js.
*/
'use strict';
self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
/**
   installOpfsVfs() returns a Promise which, on success, installs an
   sqlite3_vfs named "opfs", suitable for use with all sqlite3 APIs
   which accept a VFS. It is intended to be called via
   sqlite3ApiBootstrap.initializersAsync or an equivalent mechanism.

   The installed VFS uses the Origin-Private FileSystem API for
   all file storage. On error it is rejected with an exception
   explaining the problem. Reasons for rejection include, but are
   not limited to:

   - The counterpart Worker (see below) could not be loaded.

   - The environment does not support OPFS. That includes when
     this function is called from the main window thread.

  Significant notes and limitations:

  - As of this writing, OPFS is still very much in flux and only
    available in bleeding-edge versions of Chrome (v102+, noting that
    that number will increase as the OPFS API matures).

  - The OPFS features used here are only available in dedicated Worker
    threads. This file tries to detect that case, resulting in a
    rejected Promise if those features do not seem to be available.

  - It requires the SharedArrayBuffer and Atomics classes, and the
    former is only available if the HTTP server emits the so-called
    COOP and COEP response headers. These features are required for
    proxying OPFS's synchronous API via the synchronous interface
    required by the sqlite3_vfs API.

  - This function may only be called a single time. When called, this
    function removes itself from the sqlite3 object.

  All arguments to this function are for internal/development purposes
  only. They do not constitute a public API and may change at any
  time.

  The argument may optionally be a plain object with the following
  configuration options:

  - proxyUri: as described above

  - verbose (=2): an integer 0-3. 0 disables all logging, 1 enables
    logging of errors. 2 enables logging of warnings and errors. 3
    additionally enables debugging info.

  - sanityChecks (=false): if true, some basic sanity tests are
    run on the OPFS VFS API after it's initialized, before the
    returned Promise resolves.

  On success, the Promise resolves to the top-most sqlite3 namespace
  object and that object gets a new object installed in its
  `opfs` property, containing several OPFS-specific utilities.
*/
const installOpfsVfs = function callee(options){
  if(!self.SharedArrayBuffer
    || !self.Atomics){
    return Promise.reject(
      new Error("Cannot install OPFS: Missing SharedArrayBuffer and/or Atomics. "+
                "The server must emit the COOP/COEP response headers to enable those. "+
                "See https://sqlite.org/wasm/doc/trunk/persistence.md#coop-coep")
    );
  }else if(self.window===self && self.document){
    return Promise.reject(
      new Error("The OPFS sqlite3_vfs cannot run in the main thread "+
                "because it requires Atomics.wait().")
    );
  }else if(!self.FileSystemHandle ||
           !self.FileSystemDirectoryHandle ||
           !self.FileSystemFileHandle ||
           !self.FileSystemFileHandle.prototype.createSyncAccessHandle ||
           !navigator.storage.getDirectory){
    return Promise.reject(
      new Error("Missing required OPFS APIs.")
    );
  }
  if(!options || 'object'!==typeof options){
    options = Object.create(null);
  }
  const urlParams = new URL(self.location.href).searchParams;
  if(undefined===options.verbose){
    options.verbose = urlParams.has('opfs-verbose')
      ? (+urlParams.get('opfs-verbose') || 2) : 1;
  }
  if(undefined===options.sanityChecks){
    options.sanityChecks = urlParams.has('opfs-sanity-check');
  }
  if(undefined===options.proxyUri){
    options.proxyUri = callee.defaultProxyUri;
  }

  //console.warn("OPFS options =",options,self.location);

  if('function' === typeof options.proxyUri){
    options.proxyUri = options.proxyUri();
  }
  const thePromise = new Promise(function(promiseResolve, promiseReject_){
    const loggers = {
      0:console.error.bind(console),
      1:console.warn.bind(console),
      2:console.log.bind(console)
    };
    const logImpl = (level,...args)=>{
      if(options.verbose>level) loggers[level]("OPFS syncer:",...args);
    };
    const log =    (...args)=>logImpl(2, ...args);
    const warn =   (...args)=>logImpl(1, ...args);
    const error =  (...args)=>logImpl(0, ...args);
    const toss = sqlite3.util.toss;
    const capi = sqlite3.capi;
    const wasm = sqlite3.wasm;
    const sqlite3_vfs = capi.sqlite3_vfs;
    const sqlite3_file = capi.sqlite3_file;
    const sqlite3_io_methods = capi.sqlite3_io_methods;
    /**
       Generic utilities for working with OPFS. This will get filled out
       by the Promise setup and, on success, installed as sqlite3.opfs.

       ACHTUNG: do not rely on these APIs in client code. They are
       experimental and subject to change or removal as the
       OPFS-specific sqlite3_vfs evolves.
    */
    const opfsUtil = Object.create(null);

    /**
       Returns true if _this_ thread has access to the OPFS APIs.
    */
    const thisThreadHasOPFS = ()=>{
      return self.FileSystemHandle &&
        self.FileSystemDirectoryHandle &&
        self.FileSystemFileHandle &&
        self.FileSystemFileHandle.prototype.createSyncAccessHandle &&
        navigator.storage.getDirectory;
    };

    /**
       Not part of the public API. Solely for internal/development
       use.
    */
    opfsUtil.metrics = {
      dump: function(){
        let k, n = 0, t = 0, w = 0;
        for(k in state.opIds){
          const m = metrics[k];
          n += m.count;
          t += m.time;
          w += m.wait;
          m.avgTime = (m.count && m.time) ? (m.time / m.count) : 0;
          m.avgWait = (m.count && m.wait) ? (m.wait / m.count) : 0;
        }
        console.log(self.location.href,
                    "metrics for",self.location.href,":",metrics,
                    "\nTotal of",n,"op(s) for",t,
                    "ms (incl. "+w+" ms of waiting on the async side)");
        console.log("Serialization metrics:",metrics.s11n);
        W.postMessage({type:'opfs-async-metrics'});
      },
      reset: function(){
        let k;
        const r = (m)=>(m.count = m.time = m.wait = 0);
        for(k in state.opIds){
          r(metrics[k] = Object.create(null));
        }
        let s = metrics.s11n = Object.create(null);
        s = s.serialize = Object.create(null);
        s.count = s.time = 0;
        s = metrics.s11n.deserialize = Object.create(null);
        s.count = s.time = 0;
      }
    }/*metrics*/;
    const opfsVfs = new sqlite3_vfs();
    const opfsIoMethods = new sqlite3_io_methods();
    const promiseReject = function(err){
      opfsVfs.dispose();
      return promiseReject_(err);
    };
    const W =
//#if target=es6-bundler-friendly
    new Worker(new URL("sqlite3-opfs-async-proxy.js", import.meta.url));
//#elif target=es6-module
    new Worker(new URL(options.proxyUri, import.meta.url));
//#else
    new Worker(options.proxyUri);
//#endif
    W._originalOnError = W.onerror /* will be restored later */;
    W.onerror = function(err){
      // The error object doesn't contain any useful info when the
      // failure is, e.g., that the remote script is 404.
      error("Error initializing OPFS asyncer:",err);
      promiseReject(new Error("Loading OPFS async Worker failed for unknown reasons."));
    };
    const pDVfs = capi.sqlite3_vfs_find(null)/*pointer to default VFS*/;
    const dVfs = pDVfs
          ? new sqlite3_vfs(pDVfs)
          : null /* dVfs will be null when sqlite3 is built with
                    SQLITE_OS_OTHER. */;
    opfsVfs.$iVersion = 2/*yes, two*/;
    opfsVfs.$szOsFile = capi.sqlite3_file.structInfo.sizeof;
    opfsVfs.$mxPathname = 1024/*sure, why not?*/;
    opfsVfs.$zName = wasm.allocCString("opfs");
    // All C-side memory of opfsVfs is zeroed out, but just to be explicit:
    opfsVfs.$xDlOpen = opfsVfs.$xDlError = opfsVfs.$xDlSym = opfsVfs.$xDlClose = null;
    opfsVfs.ondispose = [
      '$zName', opfsVfs.$zName,
      'cleanup default VFS wrapper', ()=>(dVfs ? dVfs.dispose() : null),
      'cleanup opfsIoMethods', ()=>opfsIoMethods.dispose()
    ];
    /**
       Pedantic sidebar about opfsVfs.ondispose: the entries in that array
       are items to clean up when opfsVfs.dispose() is called, but in this
       environment it will never be called. The VFS instance simply
       hangs around until the WASM module instance is cleaned up. We
       "could" _hypothetically_ clean it up by "importing" an
       sqlite3_os_end() impl into the wasm build, but the shutdown order
       of the wasm engine and the JS one are undefined so there is no
       guaranty that the opfsVfs instance would be available in one
       environment or the other when sqlite3_os_end() is called (_if_ it
       gets called at all in a wasm build, which is undefined).
    */
    /**
       State which we send to the async-api Worker or share with it.
       This object must initially contain only cloneable or sharable
       objects. After the worker's "inited" message arrives, other types
       of data may be added to it.

       For purposes of Atomics.wait() and Atomics.notify(), we use a
       SharedArrayBuffer with one slot reserved for each of the API
       proxy's methods. The sync side of the API uses Atomics.wait()
       on the corresponding slot and the async side uses
       Atomics.notify() on that slot.

       The approach of using a single SAB to serialize comms for all
       instances might(?) lead to deadlock situations in multi-db
       cases. We should probably have one SAB here with a single slot
       for locking a per-file initialization step and then allocate a
       separate SAB like the above one for each file. That will
       require a bit of acrobatics but should be feasible. The most
       problematic part is that xOpen() would have to use
       postMessage() to communicate its SharedArrayBuffer, and mixing
       that approach with Atomics.wait/notify() gets a bit messy.
    */
    const state = Object.create(null);
    state.verbose = options.verbose;
    state.littleEndian = (()=>{
      const buffer = new ArrayBuffer(2);
      new DataView(buffer).setInt16(0, 256, true /* ==>littleEndian */);
      // Int16Array uses the platform's endianness.
      return new Int16Array(buffer)[0] === 256;
    })();
    /**
       asyncIdleWaitTime is how long (ms) to wait, in the async proxy,
       for each Atomics.wait() when waiting on inbound VFS API calls.
       We need to wake up periodically to give the thread a chance to
       do other things. If this is too high (e.g. 500ms) then even two
       workers/tabs can easily run into locking errors. Some multiple
       of this value is also used for determining how long to wait on
       lock contention to free up.
    */
    state.asyncIdleWaitTime = 150;
    /**
       Whether the async counterpart should log exceptions to
       the serialization channel. That produces a great deal of
       noise for seemingly innocuous things like xAccess() checks
       for missing files, so this option may have one of 3 values:

       0 = no exception logging.

       1 = only log exceptions for "significant" ops like xOpen(),
       xRead(), and xWrite().

       2 = log all exceptions.
    */
    state.asyncS11nExceptions = 1;
    /* Size of file I/O buffer block. 64k = max sqlite3 page size, and
       xRead/xWrite() will never deal in blocks larger than that. */
    state.fileBufferSize = 1024 * 64;
    state.sabS11nOffset = state.fileBufferSize;
    /**
       The size of the block in our SAB for serializing arguments and
       result values. Needs to be large enough to hold serialized
       values of any of the proxied APIs. Filenames are the largest
       part but are limited to opfsVfs.$mxPathname bytes. We also
       store exceptions there, so it needs to be long enough to hold
       a reasonably long exception string.
    */
    state.sabS11nSize = opfsVfs.$mxPathname * 2;
    /**
       The SAB used for all data I/O between the synchronous and
       async halves (file i/o and arg/result s11n).
    */
    state.sabIO = new SharedArrayBuffer(
      state.fileBufferSize/* file i/o block */
      + state.sabS11nSize/* argument/result serialization block */
    );
    state.opIds = Object.create(null);
    const metrics = Object.create(null);
    {
      /* Indexes for use in our SharedArrayBuffer... */
      let i = 0;
      /* SAB slot used to communicate which operation is desired
         between both workers. This worker writes to it and the other
         listens for changes. */
      state.opIds.whichOp = i++;
      /* Slot for storing return values. This worker listens to that
         slot and the other worker writes to it. */
      state.opIds.rc = i++;
      /* Each function gets an ID which this worker writes to
         the whichOp slot. The async-api worker uses Atomic.wait()
         on the whichOp slot to figure out which operation to run
         next. */
      state.opIds.xAccess = i++;
      state.opIds.xClose = i++;
      state.opIds.xDelete = i++;
      state.opIds.xDeleteNoWait = i++;
      state.opIds.xFileControl = i++;
      state.opIds.xFileSize = i++;
      state.opIds.xLock = i++;
      state.opIds.xOpen = i++;
      state.opIds.xRead = i++;
      state.opIds.xSleep = i++;
      state.opIds.xSync = i++;
      state.opIds.xTruncate = i++;
      state.opIds.xUnlock = i++;
      state.opIds.xWrite = i++;
      state.opIds.mkdir = i++;
      state.opIds['opfs-async-metrics'] = i++;
      state.opIds['opfs-async-shutdown'] = i++;
      /* The retry slot is used by the async part for wait-and-retry
         semantics. Though we could hypothetically use the xSleep slot
         for that, doing so might lead to undesired side effects. */
      state.opIds.retry = i++;
      state.sabOP = new SharedArrayBuffer(
        i * 4/* ==sizeof int32, noting that Atomics.wait() and friends
                can only function on Int32Array views of an SAB. */);
      opfsUtil.metrics.reset();
    }
    /**
       SQLITE_xxx constants to export to the async worker
       counterpart...
    */
    state.sq3Codes = Object.create(null);
    [
      'SQLITE_ACCESS_EXISTS',
      'SQLITE_ACCESS_READWRITE',
      'SQLITE_BUSY',
      'SQLITE_ERROR',
      'SQLITE_IOERR',
      'SQLITE_IOERR_ACCESS',
      'SQLITE_IOERR_CLOSE',
      'SQLITE_IOERR_DELETE',
      'SQLITE_IOERR_FSYNC',
      'SQLITE_IOERR_LOCK',
      'SQLITE_IOERR_READ',
      'SQLITE_IOERR_SHORT_READ',
      'SQLITE_IOERR_TRUNCATE',
      'SQLITE_IOERR_UNLOCK',
      'SQLITE_IOERR_WRITE',
      'SQLITE_LOCK_EXCLUSIVE',
      'SQLITE_LOCK_NONE',
      'SQLITE_LOCK_PENDING',
      'SQLITE_LOCK_RESERVED',
      'SQLITE_LOCK_SHARED',
      'SQLITE_LOCKED',
      'SQLITE_MISUSE',
      'SQLITE_NOTFOUND',
      'SQLITE_OPEN_CREATE',
      'SQLITE_OPEN_DELETEONCLOSE',
      'SQLITE_OPEN_MAIN_DB',
      'SQLITE_OPEN_READONLY'
    ].forEach((k)=>{
      if(undefined === (state.sq3Codes[k] = capi[k])){
        toss("Maintenance required: not found:",k);
      }
    });
    state.opfsFlags = Object.assign(Object.create(null),{
      /**
         Flag for use with xOpen(). "opfs-unlock-asap=1" enables
         this. See defaultUnlockAsap, below.
       */
      OPFS_UNLOCK_ASAP: 0x01,
      /**
         If true, any async routine which implicitly acquires a sync
         access handle (i.e. an OPFS lock) will release that locks at
         the end of the call which acquires it. If false, such
         "autolocks" are not released until the VFS is idle for some
         brief amount of time.

         The benefit of enabling this is much higher concurrency. The
         down-side is much-reduced performance (as much as a 4x decrease
         in speedtest1).
      */
      defaultUnlockAsap: false
    });

    /**
       Runs the given operation (by name) in the async worker
       counterpart, waits for its response, and returns the result
       which the async worker writes to SAB[state.opIds.rc]. The
       2nd and subsequent arguments must be the aruguments for the
       async op.
    */
    const opRun = (op,...args)=>{
      const opNdx = state.opIds[op] || toss("Invalid op ID:",op);
      state.s11n.serialize(...args);
      Atomics.store(state.sabOPView, state.opIds.rc, -1);
      Atomics.store(state.sabOPView, state.opIds.whichOp, opNdx);
      Atomics.notify(state.sabOPView, state.opIds.whichOp)
      /* async thread will take over here */;
      const t = performance.now();
      Atomics.wait(state.sabOPView, state.opIds.rc, -1)
      /* When this wait() call returns, the async half will have
         completed the operation and reported its results. */;
      const rc = Atomics.load(state.sabOPView, state.opIds.rc);
      metrics[op].wait += performance.now() - t;
      if(rc && state.asyncS11nExceptions){
        const err = state.s11n.deserialize();
        if(err) error(op+"() async error:",...err);
      }
      return rc;
    };

    /**
       Not part of the public API. Only for test/development use.
    */
    opfsUtil.debug = {
      asyncShutdown: ()=>{
        warn("Shutting down OPFS async listener. The OPFS VFS will no longer work.");
        opRun('opfs-async-shutdown');
      },
      asyncRestart: ()=>{
        warn("Attempting to restart OPFS VFS async listener. Might work, might not.");
        W.postMessage({type: 'opfs-async-restart'});
      }
    };

    const initS11n = ()=>{
      /**
         !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
         ACHTUNG: this code is 100% duplicated in the other half of
         this proxy! The documentation is maintained in the
         "synchronous half".
         !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

         This proxy de/serializes cross-thread function arguments and
         output-pointer values via the state.sabIO SharedArrayBuffer,
         using the region defined by (state.sabS11nOffset,
         state.sabS11nOffset]. Only one dataset is recorded at a time.

         This is not a general-purpose format. It only supports the
         range of operations, and data sizes, needed by the
         sqlite3_vfs and sqlite3_io_methods operations. Serialized
         data are transient and this serialization algorithm may
         change at any time.

         The data format can be succinctly summarized as:

         Nt...Td...D

         Where:

         - N = number of entries (1 byte)

         - t = type ID of first argument (1 byte)

         - ...T = type IDs of the 2nd and subsequent arguments (1 byte
         each).

         - d = raw bytes of first argument (per-type size).

         - ...D = raw bytes of the 2nd and subsequent arguments (per-type
         size).

         All types except strings have fixed sizes. Strings are stored
         using their TextEncoder/TextDecoder representations. It would
         arguably make more sense to store them as Int16Arrays of
         their JS character values, but how best/fastest to get that
         in and out of string form is an open point. Initial
         experimentation with that approach did not gain us any speed.

         Historical note: this impl was initially about 1% this size by
         using using JSON.stringify/parse(), but using fit-to-purpose
         serialization saves considerable runtime.
      */
      if(state.s11n) return state.s11n;
      const textDecoder = new TextDecoder(),
            textEncoder = new TextEncoder('utf-8'),
            viewU8 = new Uint8Array(state.sabIO, state.sabS11nOffset, state.sabS11nSize),
            viewDV = new DataView(state.sabIO, state.sabS11nOffset, state.sabS11nSize);
      state.s11n = Object.create(null);
      /* Only arguments and return values of these types may be
         serialized. This covers the whole range of types needed by the
         sqlite3_vfs API. */
      const TypeIds = Object.create(null);
      TypeIds.number  = { id: 1, size: 8, getter: 'getFloat64', setter: 'setFloat64' };
      TypeIds.bigint  = { id: 2, size: 8, getter: 'getBigInt64', setter: 'setBigInt64' };
      TypeIds.boolean = { id: 3, size: 4, getter: 'getInt32', setter: 'setInt32' };
      TypeIds.string =  { id: 4 };

      const getTypeId = (v)=>(
        TypeIds[typeof v]
          || toss("Maintenance required: this value type cannot be serialized.",v)
      );
      const getTypeIdById = (tid)=>{
        switch(tid){
            case TypeIds.number.id: return TypeIds.number;
            case TypeIds.bigint.id: return TypeIds.bigint;
            case TypeIds.boolean.id: return TypeIds.boolean;
            case TypeIds.string.id: return TypeIds.string;
            default: toss("Invalid type ID:",tid);
        }
      };

      /**
         Returns an array of the deserialized state stored by the most
         recent serialize() operation (from from this thread or the
         counterpart thread), or null if the serialization buffer is
         empty.  If passed a truthy argument, the serialization buffer
         is cleared after deserialization.
      */
      state.s11n.deserialize = function(clear=false){
        ++metrics.s11n.deserialize.count;
        const t = performance.now();
        const argc = viewU8[0];
        const rc = argc ? [] : null;
        if(argc){
          const typeIds = [];
          let offset = 1, i, n, v;
          for(i = 0; i < argc; ++i, ++offset){
            typeIds.push(getTypeIdById(viewU8[offset]));
          }
          for(i = 0; i < argc; ++i){
            const t = typeIds[i];
            if(t.getter){
              v = viewDV[t.getter](offset, state.littleEndian);
              offset += t.size;
            }else{/*String*/
              n = viewDV.getInt32(offset, state.littleEndian);
              offset += 4;
              v = textDecoder.decode(viewU8.slice(offset, offset+n));
              offset += n;
            }
            rc.push(v);
          }
        }
        if(clear) viewU8[0] = 0;
        //log("deserialize:",argc, rc);
        metrics.s11n.deserialize.time += performance.now() - t;
        return rc;
      };

      /**
         Serializes all arguments to the shared buffer for consumption
         by the counterpart thread.

         This routine is only intended for serializing OPFS VFS
         arguments and (in at least one special case) result values,
         and the buffer is sized to be able to comfortably handle
         those.

         If passed no arguments then it zeroes out the serialization
         state.
      */
      state.s11n.serialize = function(...args){
        const t = performance.now();
        ++metrics.s11n.serialize.count;
        if(args.length){
          //log("serialize():",args);
          const typeIds = [];
          let i = 0, offset = 1;
          viewU8[0] = args.length & 0xff /* header = # of args */;
          for(; i < args.length; ++i, ++offset){
            /* Write the TypeIds.id value into the next args.length
               bytes. */
            typeIds.push(getTypeId(args[i]));
            viewU8[offset] = typeIds[i].id;
          }
          for(i = 0; i < args.length; ++i) {
            /* Deserialize the following bytes based on their
               corresponding TypeIds.id from the header. */
            const t = typeIds[i];
            if(t.setter){
              viewDV[t.setter](offset, args[i], state.littleEndian);
              offset += t.size;
            }else{/*String*/
              const s = textEncoder.encode(args[i]);
              viewDV.setInt32(offset, s.byteLength, state.littleEndian);
              offset += 4;
              viewU8.set(s, offset);
              offset += s.byteLength;
            }
          }
          //log("serialize() result:",viewU8.slice(0,offset));
        }else{
          viewU8[0] = 0;
        }
        metrics.s11n.serialize.time += performance.now() - t;
      };
      return state.s11n;
    }/*initS11n()*/;

    /**
       Generates a random ASCII string len characters long, intended for
       use as a temporary file name.
    */
    const randomFilename = function f(len=16){
      if(!f._chars){
        f._chars = "abcdefghijklmnopqrstuvwxyz"+
          "ABCDEFGHIJKLMNOPQRSTUVWXYZ"+
          "012346789";
        f._n = f._chars.length;
      }
      const a = [];
      let i = 0;
      for( ; i < len; ++i){
        const ndx = Math.random() * (f._n * 64) % f._n | 0;
        a[i] = f._chars[ndx];
      }
      return a.join("");
      /*
        An alternative impl. with an unpredictable length
        but much simpler:

        Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(36)
      */
    };

    /**
       Map of sqlite3_file pointers to objects constructed by xOpen().
    */
    const __openFiles = Object.create(null);

    const opTimer = Object.create(null);
    opTimer.op = undefined;
    opTimer.start = undefined;
    const mTimeStart = (op)=>{
      opTimer.start = performance.now();
      opTimer.op = op;
      ++metrics[op].count;
    };
    const mTimeEnd = ()=>(
      metrics[opTimer.op].time += performance.now() - opTimer.start
    );

    /**
       Impls for the sqlite3_io_methods methods. Maintenance reminder:
       members are in alphabetical order to simplify finding them.
    */
    const ioSyncWrappers = {
      xCheckReservedLock: function(pFile,pOut){
        /**
           As of late 2022, only a single lock can be held on an OPFS
           file. We have no way of checking whether any _other_ db
           connection has a lock except by trying to obtain and (on
           success) release a sync-handle for it, but doing so would
           involve an inherent race condition. For the time being,
           pending a better solution, we simply report whether the
           given pFile is open.
        */
        const f = __openFiles[pFile];
        wasm.poke(pOut, f.lockType ? 1 : 0, 'i32');
        return 0;
      },
      xClose: function(pFile){
        mTimeStart('xClose');
        let rc = 0;
        const f = __openFiles[pFile];
        if(f){
          delete __openFiles[pFile];
          rc = opRun('xClose', pFile);
          if(f.sq3File) f.sq3File.dispose();
        }
        mTimeEnd();
        return rc;
      },
      xDeviceCharacteristics: function(pFile){
        //debug("xDeviceCharacteristics(",pFile,")");
        return capi.SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN;
      },
      xFileControl: function(pFile, opId, pArg){
        mTimeStart('xFileControl');
        const rc = (capi.SQLITE_FCNTL_SYNC===opId)
              ? opRun('xSync', pFile, 0)
              : capi.SQLITE_NOTFOUND;
        mTimeEnd();
        return rc;
      },
      xFileSize: function(pFile,pSz64){
        mTimeStart('xFileSize');
        let rc = opRun('xFileSize', pFile);
        if(0==rc){
          try {
            const sz = state.s11n.deserialize()[0];
            wasm.poke(pSz64, sz, 'i64');
          }catch(e){
            error("Unexpected error reading xFileSize() result:",e);
            rc = state.sq3Codes.SQLITE_IOERR;
          }
        }
        mTimeEnd();
        return rc;
      },
      xLock: function(pFile,lockType){
        mTimeStart('xLock');
        const f = __openFiles[pFile];
        let rc = 0;
        /* All OPFS locks are exclusive locks. If xLock() has
           previously succeeded, do nothing except record the lock
           type. If no lock is active, have the async counterpart
           lock the file. */
        if( !f.lockType ) {
          rc = opRun('xLock', pFile, lockType);
          if( 0===rc ) f.lockType = lockType;
        }else{
          f.lockType = lockType;
        }
        mTimeEnd();
        return rc;
      },
      xRead: function(pFile,pDest,n,offset64){
        mTimeStart('xRead');
        const f = __openFiles[pFile];
        let rc;
        try {
          rc = opRun('xRead',pFile, n, Number(offset64));
          if(0===rc || capi.SQLITE_IOERR_SHORT_READ===rc){
            /**
               Results get written to the SharedArrayBuffer f.sabView.
               Because the heap is _not_ a SharedArrayBuffer, we have
               to copy the results. TypedArray.set() seems to be the
               fastest way to copy this. */
            wasm.heap8u().set(f.sabView.subarray(0, n), pDest);
          }
        }catch(e){
          error("xRead(",arguments,") failed:",e,f);
          rc = capi.SQLITE_IOERR_READ;
        }
        mTimeEnd();
        return rc;
      },
      xSync: function(pFile,flags){
        ++metrics.xSync.count;
        return 0; // impl'd in xFileControl()
      },
      xTruncate: function(pFile,sz64){
        mTimeStart('xTruncate');
        const rc = opRun('xTruncate', pFile, Number(sz64));
        mTimeEnd();
        return rc;
      },
      xUnlock: function(pFile,lockType){
        mTimeStart('xUnlock');
        const f = __openFiles[pFile];
        let rc = 0;
        if( capi.SQLITE_LOCK_NONE === lockType
          && f.lockType ){
          rc = opRun('xUnlock', pFile, lockType);
        }
        if( 0===rc ) f.lockType = lockType;
        mTimeEnd();
        return rc;
      },
      xWrite: function(pFile,pSrc,n,offset64){
        mTimeStart('xWrite');
        const f = __openFiles[pFile];
        let rc;
        try {
          f.sabView.set(wasm.heap8u().subarray(pSrc, pSrc+n));
          rc = opRun('xWrite', pFile, n, Number(offset64));
        }catch(e){
          error("xWrite(",arguments,") failed:",e,f);
          rc = capi.SQLITE_IOERR_WRITE;
        }
        mTimeEnd();
        return rc;
      }
    }/*ioSyncWrappers*/;

    /**
       Impls for the sqlite3_vfs methods. Maintenance reminder: members
       are in alphabetical order to simplify finding them.
    */
    const vfsSyncWrappers = {
      xAccess: function(pVfs,zName,flags,pOut){
        mTimeStart('xAccess');
        const rc = opRun('xAccess', wasm.cstrToJs(zName));
        wasm.poke( pOut, (rc ? 0 : 1), 'i32' );
        mTimeEnd();
        return 0;
      },
      xCurrentTime: function(pVfs,pOut){
        /* If it turns out that we need to adjust for timezone, see:
           https://stackoverflow.com/a/11760121/1458521 */
        wasm.poke(pOut, 2440587.5 + (new Date().getTime()/86400000),
                         'double');
        return 0;
      },
      xCurrentTimeInt64: function(pVfs,pOut){
        // TODO: confirm that this calculation is correct
        wasm.poke(pOut, (2440587.5 * 86400000) + new Date().getTime(),
                         'i64');
        return 0;
      },
      xDelete: function(pVfs, zName, doSyncDir){
        mTimeStart('xDelete');
        opRun('xDelete', wasm.cstrToJs(zName), doSyncDir, false);
        /* We're ignoring errors because we cannot yet differentiate
           between harmless and non-harmless failures. */
        mTimeEnd();
        return 0;
      },
      xFullPathname: function(pVfs,zName,nOut,pOut){
        /* Until/unless we have some notion of "current dir"
           in OPFS, simply copy zName to pOut... */
        const i = wasm.cstrncpy(pOut, zName, nOut);
        return i<nOut ? 0 : capi.SQLITE_CANTOPEN
        /*CANTOPEN is required by the docs but SQLITE_RANGE would be a closer match*/;
      },
      xGetLastError: function(pVfs,nOut,pOut){
        /* TODO: store exception.message values from the async
           partner in a dedicated SharedArrayBuffer, noting that we'd have
           to encode them... TextEncoder can do that for us. */
        warn("OPFS xGetLastError() has nothing sensible to return.");
        return 0;
      },
      //xSleep is optionally defined below
      xOpen: function f(pVfs, zName, pFile, flags, pOutFlags){
        mTimeStart('xOpen');
        let opfsFlags = 0;
        if(0===zName){
          zName = randomFilename();
        }else if('number'===typeof zName){
          if(capi.sqlite3_uri_boolean(zName, "opfs-unlock-asap", 0)){
            /* -----------------------^^^^^ MUST pass the untranslated
               C-string here. */
            opfsFlags |= state.opfsFlags.OPFS_UNLOCK_ASAP;
          }
          zName = wasm.cstrToJs(zName);
        }
        const fh = Object.create(null);
        fh.fid = pFile;
        fh.filename = zName;
        fh.sab = new SharedArrayBuffer(state.fileBufferSize);
        fh.flags = flags;
        const rc = opRun('xOpen', pFile, zName, flags, opfsFlags);
        if(!rc){
          /* Recall that sqlite3_vfs::xClose() will be called, even on
             error, unless pFile->pMethods is NULL. */
          if(fh.readOnly){
            wasm.poke(pOutFlags, capi.SQLITE_OPEN_READONLY, 'i32');
          }
          __openFiles[pFile] = fh;
          fh.sabView = state.sabFileBufView;
          fh.sq3File = new sqlite3_file(pFile);
          fh.sq3File.$pMethods = opfsIoMethods.pointer;
          fh.lockType = capi.SQLITE_LOCK_NONE;
        }
        mTimeEnd();
        return rc;
      }/*xOpen()*/
    }/*vfsSyncWrappers*/;

    if(dVfs){
      opfsVfs.$xRandomness = dVfs.$xRandomness;
      opfsVfs.$xSleep = dVfs.$xSleep;
    }
    if(!opfsVfs.$xRandomness){
      /* If the default VFS has no xRandomness(), add a basic JS impl... */
      vfsSyncWrappers.xRandomness = function(pVfs, nOut, pOut){
        const heap = wasm.heap8u();
        let i = 0;
        for(; i < nOut; ++i) heap[pOut + i] = (Math.random()*255000) & 0xFF;
        return i;
      };
    }
    if(!opfsVfs.$xSleep){
      /* If we can inherit an xSleep() impl from the default VFS then
         assume it's sane and use it, otherwise install a JS-based
         one. */
      vfsSyncWrappers.xSleep = function(pVfs,ms){
        Atomics.wait(state.sabOPView, state.opIds.xSleep, 0, ms);
        return 0;
      };
    }

    /**
       Expects an OPFS file path. It gets resolved, such that ".."
       components are properly expanded, and returned. If the 2nd arg
       is true, the result is returned as an array of path elements,
       else an absolute path string is returned.
    */
    opfsUtil.getResolvedPath = function(filename,splitIt){
      const p = new URL(filename, "file://irrelevant").pathname;
      return splitIt ? p.split('/').filter((v)=>!!v) : p;
    };

    /**
       Takes the absolute path to a filesystem element. Returns an
       array of [handleOfContainingDir, filename]. If the 2nd argument
       is truthy then each directory element leading to the file is
       created along the way. Throws if any creation or resolution
       fails.
    */
    opfsUtil.getDirForFilename = async function f(absFilename, createDirs = false){
      const path = opfsUtil.getResolvedPath(absFilename, true);
      const filename = path.pop();
      let dh = opfsUtil.rootDirectory;
      for(const dirName of path){
        if(dirName){
          dh = await dh.getDirectoryHandle(dirName, {create: !!createDirs});
        }
      }
      return [dh, filename];
    };

    /**
       Creates the given directory name, recursively, in
       the OPFS filesystem. Returns true if it succeeds or the
       directory already exists, else false.
    */
    opfsUtil.mkdir = async function(absDirName){
      try {
        await opfsUtil.getDirForFilename(absDirName+"/filepart", true);
        return true;
      }catch(e){
        //console.warn("mkdir(",absDirName,") failed:",e);
        return false;
      }
    };
    /**
       Checks whether the given OPFS filesystem entry exists,
       returning true if it does, false if it doesn't.
    */
    opfsUtil.entryExists = async function(fsEntryName){
      try {
        const [dh, fn] = await opfsUtil.getDirForFilename(fsEntryName);
        await dh.getFileHandle(fn);
        return true;
      }catch(e){
        return false;
      }
    };

    /**
       Generates a random ASCII string, intended for use as a
       temporary file name. Its argument is the length of the string,
       defaulting to 16.
    */
    opfsUtil.randomFilename = randomFilename;

    /**
       Re-registers the OPFS VFS. This is intended only for odd use
       cases which have to call sqlite3_shutdown() as part of their
       initialization process, which will unregister the VFS
       registered by installOpfsVfs(). If passed a truthy value, the
       OPFS VFS is registered as the default VFS, else it is not made
       the default. Returns the result of the the
       sqlite3_vfs_register() call.

       Design note: the problem of having to re-register things after
       a shutdown/initialize pair is more general. How to best plug
       that in to the library is unclear. In particular, we cannot
       hook in to any C-side calls to sqlite3_initialize(), so we
       cannot add an after-initialize callback mechanism.
    */
    opfsUtil.registerVfs = (asDefault=false)=>{
      return wasm.exports.sqlite3_vfs_register(
        opfsVfs.pointer, asDefault ? 1 : 0
      );
    };

    /**
       Returns a promise which resolves to an object which represents
       all files and directories in the OPFS tree. The top-most object
       has two properties: `dirs` is an array of directory entries
       (described below) and `files` is a list of file names for all
       files in that directory.

       Traversal starts at sqlite3.opfs.rootDirectory.

       Each `dirs` entry is an object in this form:

       ```
       { name: directoryName,
         dirs: [...subdirs],
         files: [...file names]
       }
       ```

       The `files` and `subdirs` entries are always set but may be
       empty arrays.

       The returned object has the same structure but its `name` is
       an empty string. All returned objects are created with
       Object.create(null), so have no prototype.

       Design note: the entries do not contain more information,
       e.g. file sizes, because getting such info is not only
       expensive but is subject to locking-related errors.
    */
    opfsUtil.treeList = async function(){
      const doDir = async function callee(dirHandle,tgt){
        tgt.name = dirHandle.name;
        tgt.dirs = [];
        tgt.files = [];
        for await (const handle of dirHandle.values()){
          if('directory' === handle.kind){
            const subDir = Object.create(null);
            tgt.dirs.push(subDir);
            await callee(handle, subDir);
          }else{
            tgt.files.push(handle.name);
          }
        }
      };
      const root = Object.create(null);
      await doDir(opfsUtil.rootDirectory, root);
      return root;
    };

    /**
       Irrevocably deletes _all_ files in the current origin's OPFS.
       Obviously, this must be used with great caution. It may throw
       an exception if removal of anything fails (e.g. a file is
       locked), but the precise conditions under which the underlying
       APIs will throw are not documented (so we cannot tell you what
       they are).
    */
    opfsUtil.rmfr = async function(){
      const dir = opfsUtil.rootDirectory, opt = {recurse: true};
      for await (const handle of dir.values()){
        dir.removeEntry(handle.name, opt);
      }
    };

    /**
       Deletes the given OPFS filesystem entry.  As this environment
       has no notion of "current directory", the given name must be an
       absolute path. If the 2nd argument is truthy, deletion is
       recursive (use with caution!).

       The returned Promise resolves to true if the deletion was
       successful, else false (but...). The OPFS API reports the
       reason for the failure only in human-readable form, not
       exceptions which can be type-checked to determine the
       failure. Because of that...

       If the final argument is truthy then this function will
       propagate any exception on error, rather than returning false.
    */
    opfsUtil.unlink = async function(fsEntryName, recursive = false,
                                          throwOnError = false){
      try {
        const [hDir, filenamePart] =
              await opfsUtil.getDirForFilename(fsEntryName, false);
        await hDir.removeEntry(filenamePart, {recursive});
        return true;
      }catch(e){
        if(throwOnError){
          throw new Error("unlink(",arguments[0],") failed: "+e.message,{
            cause: e
          });
        }
        return false;
      }
    };

    /**
       Traverses the OPFS filesystem, calling a callback for each one.
       The argument may be either a callback function or an options object
       with any of the following properties:

       - `callback`: function which gets called for each filesystem
         entry.  It gets passed 3 arguments: 1) the
         FileSystemFileHandle or FileSystemDirectoryHandle of each
         entry (noting that both are instanceof FileSystemHandle). 2)
         the FileSystemDirectoryHandle of the parent directory. 3) the
         current depth level, with 0 being at the top of the tree
         relative to the starting directory. If the callback returns a
         literal false, as opposed to any other falsy value, traversal
         stops without an error. Any exceptions it throws are
         propagated. Results are undefined if the callback manipulate
         the filesystem (e.g. removing or adding entries) because the
         how OPFS iterators behave in the face of such changes is
         undocumented.

       - `recursive` [bool=true]: specifies whether to recurse into
         subdirectories or not. Whether recursion is depth-first or
         breadth-first is unspecified!

       - `directory` [FileSystemDirectoryEntry=sqlite3.opfs.rootDirectory]
         specifies the starting directory.

       If this function is passed a function, it is assumed to be the
       callback.

       Returns a promise because it has to (by virtue of being async)
       but that promise has no specific meaning: the traversal it
       performs is synchronous. The promise must be used to catch any
       exceptions propagated by the callback, however.

       TODO: add an option which specifies whether to traverse
       depth-first or breadth-first. We currently do depth-first but
       an incremental file browsing widget would benefit more from
       breadth-first.
    */
    opfsUtil.traverse = async function(opt){
      const defaultOpt = {
        recursive: true,
        directory: opfsUtil.rootDirectory
      };
      if('function'===typeof opt){
        opt = {callback:opt};
      }
      opt = Object.assign(defaultOpt, opt||{});
      const doDir = async function callee(dirHandle, depth){
        for await (const handle of dirHandle.values()){
          if(false === opt.callback(handle, dirHandle, depth)) return false;
          else if(opt.recursive && 'directory' === handle.kind){
            if(false === await callee(handle, depth + 1)) break;
          }
        }
      };
      doDir(opt.directory, 0);
    };

    //TODO to support fiddle and worker1 db upload:
    //opfsUtil.createFile = function(absName, content=undefined){...}
    //We have sqlite3.wasm.sqlite3_wasm_vfs_create_file() for this
    //purpose but its interface and name are still under
    //consideration.

    if(sqlite3.oo1){
      const OpfsDb = function(...args){
        const opt = sqlite3.oo1.DB.dbCtorHelper.normalizeArgs(...args);
        opt.vfs = opfsVfs.$zName;
        sqlite3.oo1.DB.dbCtorHelper.call(this, opt);
      };
      OpfsDb.prototype = Object.create(sqlite3.oo1.DB.prototype);
      sqlite3.oo1.OpfsDb = OpfsDb;
      sqlite3.oo1.DB.dbCtorHelper.setVfsPostOpenSql(
        opfsVfs.pointer,
        function(oo1Db, sqlite3){
          /* Set a relatively high default busy-timeout handler to
             help OPFS dbs deal with multi-tab/multi-worker
             contention. */
          sqlite3.capi.sqlite3_busy_timeout(oo1Db, 10000);
          sqlite3.capi.sqlite3_exec(oo1Db, [
            /* Truncate journal mode is faster than delete for
               this vfs, per speedtest1. That gap seems to have closed with
               Chrome version 108 or 109, but "persist" is very roughly 5-6%
               faster than truncate in initial tests. */
            "pragma journal_mode=persist;",
            /*
              This vfs benefits hugely from cache on moderate/large
              speedtest1 --size 50 and --size 100 workloads. We
              currently rely on setting a non-default cache size when
              building sqlite3.wasm. If that policy changes, the cache
              can be set here.
            */
            "pragma cache_size=-16384;"
          ], 0, 0, 0);
        }
      );
    }/*extend sqlite3.oo1*/

    const sanityCheck = function(){
      const scope = wasm.scopedAllocPush();
      const sq3File = new sqlite3_file();
      try{
        const fid = sq3File.pointer;
        const openFlags = capi.SQLITE_OPEN_CREATE
              | capi.SQLITE_OPEN_READWRITE
        //| capi.SQLITE_OPEN_DELETEONCLOSE
              | capi.SQLITE_OPEN_MAIN_DB;
        const pOut = wasm.scopedAlloc(8);
        const dbFile = "/sanity/check/file"+randomFilename(8);
        const zDbFile = wasm.scopedAllocCString(dbFile);
        let rc;
        state.s11n.serialize("This is ä string.");
        rc = state.s11n.deserialize();
        log("deserialize() says:",rc);
        if("This is ä string."!==rc[0]) toss("String d13n error.");
        vfsSyncWrappers.xAccess(opfsVfs.pointer, zDbFile, 0, pOut);
        rc = wasm.peek(pOut,'i32');
        log("xAccess(",dbFile,") exists ?=",rc);
        rc = vfsSyncWrappers.xOpen(opfsVfs.pointer, zDbFile,
                                   fid, openFlags, pOut);
        log("open rc =",rc,"state.sabOPView[xOpen] =",
            state.sabOPView[state.opIds.xOpen]);
        if(0!==rc){
          error("open failed with code",rc);
          return;
        }
        vfsSyncWrappers.xAccess(opfsVfs.pointer, zDbFile, 0, pOut);
        rc = wasm.peek(pOut,'i32');
        if(!rc) toss("xAccess() failed to detect file.");
        rc = ioSyncWrappers.xSync(sq3File.pointer, 0);
        if(rc) toss('sync failed w/ rc',rc);
        rc = ioSyncWrappers.xTruncate(sq3File.pointer, 1024);
        if(rc) toss('truncate failed w/ rc',rc);
        wasm.poke(pOut,0,'i64');
        rc = ioSyncWrappers.xFileSize(sq3File.pointer, pOut);
        if(rc) toss('xFileSize failed w/ rc',rc);
        log("xFileSize says:",wasm.peek(pOut, 'i64'));
        rc = ioSyncWrappers.xWrite(sq3File.pointer, zDbFile, 10, 1);
        if(rc) toss("xWrite() failed!");
        const readBuf = wasm.scopedAlloc(16);
        rc = ioSyncWrappers.xRead(sq3File.pointer, readBuf, 6, 2);
        wasm.poke(readBuf+6,0);
        let jRead = wasm.cstrToJs(readBuf);
        log("xRead() got:",jRead);
        if("sanity"!==jRead) toss("Unexpected xRead() value.");
        if(vfsSyncWrappers.xSleep){
          log("xSleep()ing before close()ing...");
          vfsSyncWrappers.xSleep(opfsVfs.pointer,2000);
          log("waking up from xSleep()");
        }
        rc = ioSyncWrappers.xClose(fid);
        log("xClose rc =",rc,"sabOPView =",state.sabOPView);
        log("Deleting file:",dbFile);
        vfsSyncWrappers.xDelete(opfsVfs.pointer, zDbFile, 0x1234);
        vfsSyncWrappers.xAccess(opfsVfs.pointer, zDbFile, 0, pOut);
        rc = wasm.peek(pOut,'i32');
        if(rc) toss("Expecting 0 from xAccess(",dbFile,") after xDelete().");
        warn("End of OPFS sanity checks.");
      }finally{
        sq3File.dispose();
        wasm.scopedAllocPop(scope);
      }
    }/*sanityCheck()*/;

    W.onmessage = function({data}){
      //log("Worker.onmessage:",data);
      switch(data.type){
          case 'opfs-unavailable':
            /* Async proxy has determined that OPFS is unavailable. There's
               nothing more for us to do here. */
            promiseReject(new Error(data.payload.join(' ')));
            break;
          case 'opfs-async-loaded':
            /*Arrives as soon as the asyc proxy finishes loading.
              Pass our config and shared state on to the async worker.*/
            W.postMessage({type: 'opfs-async-init',args: state});
            break;
          case 'opfs-async-inited':{
            /*Indicates that the async partner has received the 'init'
              and has finished initializing, so the real work can
              begin...*/
            try {
              sqlite3.vfs.installVfs({
                io: {struct: opfsIoMethods, methods: ioSyncWrappers},
                vfs: {struct: opfsVfs, methods: vfsSyncWrappers}
              });
              state.sabOPView = new Int32Array(state.sabOP);
              state.sabFileBufView = new Uint8Array(state.sabIO, 0, state.fileBufferSize);
              state.sabS11nView = new Uint8Array(state.sabIO, state.sabS11nOffset, state.sabS11nSize);
              initS11n();
              if(options.sanityChecks){
                warn("Running sanity checks because of opfs-sanity-check URL arg...");
                sanityCheck();
              }
              if(thisThreadHasOPFS()){
                navigator.storage.getDirectory().then((d)=>{
                  W.onerror = W._originalOnError;
                  delete W._originalOnError;
                  sqlite3.opfs = opfsUtil;
                  opfsUtil.rootDirectory = d;
                  log("End of OPFS sqlite3_vfs setup.", opfsVfs);
                  promiseResolve(sqlite3);
                }).catch(promiseReject);
              }else{
                promiseResolve(sqlite3);
              }
            }catch(e){
              error(e);
              promiseReject(e);
            }
            break;
          }
          default:
            promiseReject(e);
            error("Unexpected message from the async worker:",data);
            break;
      }/*switch(data.type)*/
    }/*W.onmessage()*/;
  })/*thePromise*/;
  return thePromise;
}/*installOpfsVfs()*/;
installOpfsVfs.defaultProxyUri =
  "sqlite3-opfs-async-proxy.js";
self.sqlite3ApiBootstrap.initializersAsync.push(async (sqlite3)=>{
  try{
    let proxyJs = installOpfsVfs.defaultProxyUri;
    if(sqlite3.scriptInfo.sqlite3Dir){
      installOpfsVfs.defaultProxyUri =
        sqlite3.scriptInfo.sqlite3Dir + proxyJs;
      //console.warn("installOpfsVfs.defaultProxyUri =",installOpfsVfs.defaultProxyUri);
    }
    return installOpfsVfs().catch((e)=>{
      console.warn("Ignoring inability to install OPFS sqlite3_vfs:",e.message);
    });
  }catch(e){
    console.error("installOpfsVfs() exception:",e);
    throw e;
  }
});
}/*sqlite3ApiBootstrap.initializers.push()*/);

Added ext/wasm/api/sqlite3-wasi.h.






































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/**
   Dummy function stubs to get sqlite3.c compiling with
   wasi-sdk. This requires, in addition:

   -D_WASI_EMULATED_MMAN -D_WASI_EMULATED_GETPID

   -lwasi-emulated-getpid
*/
typedef unsigned mode_t;
int fchmod(int fd, mode_t mode);
int fchmod(int fd, mode_t mode){
  return (fd && mode) ? 0 : 0;
}
typedef unsigned uid_t;
typedef uid_t gid_t;
int fchown(int fd, uid_t owner, gid_t group);
int fchown(int fd, uid_t owner, gid_t group){
  return (fd && owner && group) ? 0 : 0;
}
uid_t geteuid(void);
uid_t geteuid(void){return 0;}
#if !defined(F_WRLCK)
enum {
F_WRLCK,
F_RDLCK,
F_GETLK,
F_SETLK,
F_UNLCK
};
#endif

#undef HAVE_PREAD

#include <wasi/api.h>
#define WASM__KEEP __attribute__((used))

#if 0
/**
   wasi-sdk cannot build sqlite3's default VFS without at least the following
   functions. They are apparently syscalls which clients have to implement or
   otherwise obtain.

   https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md
*/
environ_get
environ_sizes_get
clock_time_get
fd_close
fd_fdstat_get
fd_fdstat_set_flags
fd_filestat_get
fd_filestat_set_size
fd_pread
fd_prestat_get
fd_prestat_dir_name
fd_read
fd_seek
fd_sync
fd_write
path_create_directory
path_filestat_get
path_filestat_set_times
path_open
path_readlink
path_remove_directory
path_unlink_file
poll_oneoff
proc_exit
#endif

Added ext/wasm/api/sqlite3-wasm.c.








































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
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
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
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** This file requires access to sqlite3.c static state in order to
** implement certain WASM-specific features, and thus directly
** includes that file. Unlike the rest of sqlite3.c, this file
** requires compiling with -std=c99 (or equivalent, or a later C
** version) because it makes use of features not available in C89.
**
** At its simplest, to build sqlite3.wasm either place this file
** in the same directory as sqlite3.c/h before compilation or use the
** -I/path flag to tell the compiler where to find both of those
** files, then compile this file. For example:
**
** emcc -o sqlite3.wasm ... -I/path/to/sqlite3-c-and-h sqlite3-wasm.c
*/
#define SQLITE_WASM
#ifdef SQLITE_WASM_ENABLE_C_TESTS
/*
** Code blocked off by SQLITE_WASM_TESTS is intended solely for use in
** unit/regression testing. They may be safely omitted from
** client-side builds. The main unit test script, tester1.js, will
** skip related tests if it doesn't find the corresponding functions
** in the WASM exports.
*/
#  define SQLITE_WASM_TESTS 1
#else
#  define SQLITE_WASM_TESTS 0
#endif

/*
** Threading and file locking: JS is single-threaded. Each Worker
** thread is a separate instance of the JS engine so can never access
** the same db handle as another thread, thus multi-threading support
** is unnecessary in the library. Because the filesystems are virtual
** and local to a given wasm runtime instance, two Workers can never
** access the same db file at once, with the exception of OPFS.
**
** Summary: except for the case of OPFS, which supports locking using
** its own API, threading and file locking support are unnecessary in
** the wasm build.
*/

/*
** Undefine any SQLITE_... config flags which we specifically do not
** want defined. Please keep these alphabetized.
*/
#undef SQLITE_OMIT_DESERIALIZE
#undef SQLITE_OMIT_MEMORYDB

/*
** Define any SQLITE_... config defaults we want if they aren't
** overridden by the builder. Please keep these alphabetized.
*/

/**********************************************************************/
/* SQLITE_D... */
#ifndef SQLITE_DEFAULT_CACHE_SIZE
/*
** The OPFS impls benefit tremendously from an increased cache size
** when working on large workloads, e.g. speedtest1 --size 50 or
** higher. On smaller workloads, e.g. speedtest1 --size 25, they
** clearly benefit from having 4mb of cache, but not as much as a
** larger cache benefits the larger workloads. Speed differences
** between 2x and nearly 3x have been measured with ample page cache.
*/
# define SQLITE_DEFAULT_CACHE_SIZE -16384
#endif
#if !defined(SQLITE_DEFAULT_PAGE_SIZE)
/*
** OPFS performance is improved by approx. 12% with a page size of 8kb
** instead of 4kb. Performance with 16kb is equivalent to 8kb.
**
** Performance difference of kvvfs with a page size of 8kb compared to
** 4kb, as measured by speedtest1 --size 4, is indeterminate:
** measurements are all over the place either way and not
** significantly different.
*/
# define SQLITE_DEFAULT_PAGE_SIZE 8192
#endif
#ifndef SQLITE_DEFAULT_UNIX_VFS
# define SQLITE_DEFAULT_UNIX_VFS "unix-none"
#endif
#undef SQLITE_DQS
#define SQLITE_DQS 0

/**********************************************************************/
/* SQLITE_ENABLE_... */
#ifndef SQLITE_ENABLE_BYTECODE_VTAB
#  define SQLITE_ENABLE_BYTECODE_VTAB 1
#endif
#ifndef SQLITE_ENABLE_DBPAGE_VTAB
#  define SQLITE_ENABLE_DBPAGE_VTAB 1
#endif
#ifndef SQLITE_ENABLE_DBSTAT_VTAB
#  define SQLITE_ENABLE_DBSTAT_VTAB 1
#endif
#ifndef SQLITE_ENABLE_EXPLAIN_COMMENTS
#  define SQLITE_ENABLE_EXPLAIN_COMMENTS 1
#endif
#ifndef SQLITE_ENABLE_FTS4
#  define SQLITE_ENABLE_FTS4 1
#endif
#ifndef SQLITE_ENABLE_MATH_FUNCTIONS
#  define SQLITE_ENABLE_MATH_FUNCTIONS 1
#endif
#ifndef SQLITE_ENABLE_OFFSET_SQL_FUNC
#  define SQLITE_ENABLE_OFFSET_SQL_FUNC 1
#endif
#ifndef SQLITE_ENABLE_PREUPDATE_HOOK
#  define SQLITE_ENABLE_PREUPDATE_HOOK 1 /*required by session extension*/
#endif
#ifndef SQLITE_ENABLE_RTREE
#  define SQLITE_ENABLE_RTREE 1
#endif
#ifndef SQLITE_ENABLE_SESSION
#  define SQLITE_ENABLE_SESSION 1
#endif
#ifndef SQLITE_ENABLE_STMTVTAB
#  define SQLITE_ENABLE_STMTVTAB 1
#endif
#ifndef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
#  define SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
#endif

/**********************************************************************/
/* SQLITE_M... */
#ifndef SQLITE_MAX_ALLOCATION_SIZE
# define SQLITE_MAX_ALLOCATION_SIZE 0x1fffffff
#endif

/**********************************************************************/
/* SQLITE_O... */
#ifndef SQLITE_OMIT_DEPRECATED
# define SQLITE_OMIT_DEPRECATED 1
#endif
#ifndef SQLITE_OMIT_LOAD_EXTENSION
# define SQLITE_OMIT_LOAD_EXTENSION 1
#endif
#ifndef SQLITE_OMIT_SHARED_CACHE
# define SQLITE_OMIT_SHARED_CACHE 1
#endif
#ifndef SQLITE_OMIT_UTF16
# define SQLITE_OMIT_UTF16 1
#endif
#ifndef SQLITE_OMIT_WAL
# define SQLITE_OMIT_WAL 1
#endif
#ifndef SQLITE_OS_KV_OPTIONAL
# define SQLITE_OS_KV_OPTIONAL 1
#endif

/**********************************************************************/
/* SQLITE_T... */
#ifndef SQLITE_TEMP_STORE
# define SQLITE_TEMP_STORE 3
#endif
#ifndef SQLITE_THREADSAFE
# define SQLITE_THREADSAFE 0
#endif

/**********************************************************************/
/* SQLITE_USE_... */
#ifndef SQLITE_USE_URI
#  define SQLITE_USE_URI 1
#endif

#include <assert.h>
#include "sqlite3.c" /* yes, .c instead of .h. */

#if defined(__EMSCRIPTEN__)
#  include <emscripten/console.h>
#endif

/*
** SQLITE_WASM_KEEP is functionally identical to EMSCRIPTEN_KEEPALIVE
** but is not Emscripten-specific. It explicitly marks functions for
** export into the target wasm file without requiring explicit listing
** of those functions in Emscripten's -sEXPORTED_FUNCTIONS=... list
** (or equivalent in other build platforms). Any function with neither
** this attribute nor which is listed as an explicit export will not
** be exported from the wasm file (but may still be used internally
** within the wasm file).
**
** The functions in this file (sqlite3-wasm.c) which require exporting
** are marked with this flag. They may also be added to any explicit
** build-time export list but need not be. All of these APIs are
** intended for use only within the project's own JS/WASM code, and
** not by client code, so an argument can be made for reducing their
** visibility by not including them in any build-time export lists.
**
** 2022-09-11: it's not yet _proven_ that this approach works in
** non-Emscripten builds. If not, such builds will need to export
** those using the --export=... wasm-ld flag (or equivalent). As of
** this writing we are tied to Emscripten for various reasons
** and cannot test the library with other build environments.
*/
#define SQLITE_WASM_KEEP __attribute__((used,visibility("default")))
// See also:
//__attribute__((export_name("theExportedName"), used, visibility("default")))


#if 0
/*
** An EXPERIMENT in implementing a stack-based allocator analog to
** Emscripten's stackSave(), stackAlloc(), stackRestore().
** Unfortunately, this cannot work together with Emscripten because
** Emscripten defines its own native one and we'd stomp on each
** other's memory. Other than that complication, basic tests show it
** to work just fine.
**
** Another option is to malloc() a chunk of our own and call that our
** "stack".
*/
SQLITE_WASM_KEEP void * sqlite3_wasm_stack_end(void){
  extern void __heap_base
    /* see https://stackoverflow.com/questions/10038964 */;
  return &__heap_base;
}
SQLITE_WASM_KEEP void * sqlite3_wasm_stack_begin(void){
  extern void __data_end;
  return &__data_end;
}
static void * pWasmStackPtr = 0;
SQLITE_WASM_KEEP void * sqlite3_wasm_stack_ptr(void){
  if(!pWasmStackPtr) pWasmStackPtr = sqlite3_wasm_stack_end();
  return pWasmStackPtr;
}
SQLITE_WASM_KEEP void sqlite3_wasm_stack_restore(void * p){
  pWasmStackPtr = p;
}
SQLITE_WASM_KEEP void * sqlite3_wasm_stack_alloc(int n){
  if(n<=0) return 0;
  n = (n + 7) & ~7 /* align to 8-byte boundary */;
  unsigned char * const p = (unsigned char *)sqlite3_wasm_stack_ptr();
  unsigned const char * const b = (unsigned const char *)sqlite3_wasm_stack_begin();
  if(b + n >= p || b + n < b/*overflow*/) return 0;
  return pWasmStackPtr = p - n;
}
#endif /* stack allocator experiment */

/*
** State for the "pseudo-stack" allocator implemented in
** sqlite3_wasm_pstack_xyz(). In order to avoid colliding with
** Emscripten-controled stack space, it carves out a bit of stack
** memory to use for that purpose. This memory ends up in the
** WASM-managed memory, such that routines which manipulate the wasm
** heap can also be used to manipulate this memory.
**
** This particular allocator is intended for small allocations such as
** storage for output pointers. We cannot reasonably size it large
** enough for general-purpose string conversions because some of our
** tests use input files (strings) of 16MB+.
*/
static unsigned char PStack_mem[512 * 8] = {0};
static struct {
  unsigned const char * const pBegin;/* Start (inclusive) of memory */
  unsigned const char * const pEnd;  /* One-after-the-end of memory */
  unsigned char * pPos;              /* Current stack pointer */
} PStack = {
  &PStack_mem[0],
  &PStack_mem[0] + sizeof(PStack_mem),
  &PStack_mem[0] + sizeof(PStack_mem)
};
/*
** Returns the current pstack position.
*/
SQLITE_WASM_KEEP void * sqlite3_wasm_pstack_ptr(void){
  return PStack.pPos;
}
/*
** Sets the pstack position poitner to p. Results are undefined if the
** given value did not come from sqlite3_wasm_pstack_ptr().
*/
SQLITE_WASM_KEEP void sqlite3_wasm_pstack_restore(unsigned char * p){
  assert(p>=PStack.pBegin && p<=PStack.pEnd && p>=PStack.pPos);
  assert(0==(p & 0x7));
  if(p>=PStack.pBegin && p<=PStack.pEnd /*&& p>=PStack.pPos*/){
    PStack.pPos = p;
  }
}
/*
** Allocate and zero out n bytes from the pstack. Returns a pointer to
** the memory on success, 0 on error (including a negative n value). n
** is always adjusted to be a multiple of 8 and returned memory is
** always zeroed out before returning (because this keeps the client
** JS code from having to do so, and most uses of the pstack will
** call for doing so).
*/
SQLITE_WASM_KEEP void * sqlite3_wasm_pstack_alloc(int n){
  if( n<=0 ) return 0;
  //if( n & 0x7 ) n += 8 - (n & 0x7) /* align to 8-byte boundary */;
  n = (n + 7) & ~7 /* align to 8-byte boundary */;
  if( PStack.pBegin + n > PStack.pPos /*not enough space left*/
      || PStack.pBegin + n <= PStack.pBegin /*overflow*/ ) return 0;
  memset((PStack.pPos = PStack.pPos - n), 0, (unsigned int)n);
  return PStack.pPos;
}
/*
** Return the number of bytes left which can be
** sqlite3_wasm_pstack_alloc()'d.
*/
SQLITE_WASM_KEEP int sqlite3_wasm_pstack_remaining(void){
  assert(PStack.pPos >= PStack.pBegin);
  assert(PStack.pPos <= PStack.pEnd);
  return (int)(PStack.pPos - PStack.pBegin);
}

/*
** Return the total number of bytes available in the pstack, including
** any space which is currently allocated. This value is a
** compile-time constant.
*/
SQLITE_WASM_KEEP int sqlite3_wasm_pstack_quota(void){
  return (int)(PStack.pEnd - PStack.pBegin);
}

/*
** This function is NOT part of the sqlite3 public API. It is strictly
** for use by the sqlite project's own JS/WASM bindings.
**
** For purposes of certain hand-crafted C/Wasm function bindings, we
** need a way of reporting errors which is consistent with the rest of
** the C API, as opposed to throwing JS exceptions. To that end, this
** internal-use-only function is a thin proxy around
** sqlite3ErrorWithMessage(). The intent is that it only be used from
** Wasm bindings such as sqlite3_prepare_v2/v3(), and definitely not
** from client code.
**
** Returns err_code.
*/
SQLITE_WASM_KEEP
int sqlite3_wasm_db_error(sqlite3*db, int err_code, const char *zMsg){
  if( db!=0 ){
    if( 0!=zMsg ){
      const int nMsg = sqlite3Strlen30(zMsg);
      sqlite3ErrorWithMsg(db, err_code, "%.*s", nMsg, zMsg);
    }else{
      sqlite3ErrorWithMsg(db, err_code, NULL);
    }
  }
  return err_code;
}

#if SQLITE_WASM_TESTS
struct WasmTestStruct {
  int v4;
  void * ppV;
  const char * cstr;
  int64_t v8;
  void (*xFunc)(void*);
};
typedef struct WasmTestStruct WasmTestStruct;
SQLITE_WASM_KEEP
void sqlite3_wasm_test_struct(WasmTestStruct * s){
  if(s){
    s->v4 *= 2;
    s->v8 = s->v4 * 2;
    s->ppV = s;
    s->cstr = __FILE__;
    if(s->xFunc) s->xFunc(s);
  }
  return;
}
#endif /* SQLITE_WASM_TESTS */

/*
** This function is NOT part of the sqlite3 public API. It is strictly
** for use by the sqlite project's own JS/WASM bindings. Unlike the
** rest of the sqlite3 API, this part requires C99 for snprintf() and
** variadic macros.
**
** Returns a string containing a JSON-format "enum" of C-level
** constants and struct-related metadata intended to be imported into
** the JS environment. The JSON is initialized the first time this
** function is called and that result is reused for all future calls.
**
** If this function returns NULL then it means that the internal
** buffer is not large enough for the generated JSON and needs to be
** increased. In debug builds that will trigger an assert().
*/
SQLITE_WASM_KEEP
const char * sqlite3_wasm_enum_json(void){
  static char aBuffer[1024 * 20] = {0} /* where the JSON goes */;
  int n = 0, nChildren = 0, nStruct = 0
    /* output counters for figuring out where commas go */;
  char * zPos = &aBuffer[1] /* skip first byte for now to help protect
                            ** against a small race condition */;
  char const * const zEnd = &aBuffer[0] + sizeof(aBuffer) /* one-past-the-end */;
  if(aBuffer[0]) return aBuffer;
  /* Leave aBuffer[0] at 0 until the end to help guard against a tiny
  ** race condition. If this is called twice concurrently, they might
  ** end up both writing to aBuffer, but they'll both write the same
  ** thing, so that's okay. If we set byte 0 up front then the 2nd
  ** instance might return and use the string before the 1st instance
  ** is done filling it. */

/* Core output macros... */
#define lenCheck assert(zPos < zEnd - 128 \
  && "sqlite3_wasm_enum_json() buffer is too small."); \
  if( zPos >= zEnd - 128 ) return 0
#define outf(format,...) \
  zPos += snprintf(zPos, ((size_t)(zEnd - zPos)), format, __VA_ARGS__); \
  lenCheck
#define out(TXT) outf("%s",TXT)
#define CloseBrace(LEVEL) \
  assert(LEVEL<5); memset(zPos, '}', LEVEL); zPos+=LEVEL; lenCheck

/* Macros for emitting maps of integer- and string-type macros to
** their values. */
#define DefGroup(KEY) n = 0; \
  outf("%s\"" #KEY "\": {",(nChildren++ ? "," : ""));
#define DefInt(KEY)                                     \
  outf("%s\"%s\": %d", (n++ ? ", " : ""), #KEY, (int)KEY)
#define DefStr(KEY)                                     \
  outf("%s\"%s\": \"%s\"", (n++ ? ", " : ""), #KEY, KEY)
#define _DefGroup CloseBrace(1)

  /* The following groups are sorted alphabetic by group name. */
  DefGroup(access){
    DefInt(SQLITE_ACCESS_EXISTS);
    DefInt(SQLITE_ACCESS_READWRITE);
    DefInt(SQLITE_ACCESS_READ)/*docs say this is unused*/;
  } _DefGroup;

  DefGroup(authorizer){
    DefInt(SQLITE_DENY);
    DefInt(SQLITE_IGNORE);
    DefInt(SQLITE_CREATE_INDEX);
    DefInt(SQLITE_CREATE_TABLE);
    DefInt(SQLITE_CREATE_TEMP_INDEX);
    DefInt(SQLITE_CREATE_TEMP_TABLE);
    DefInt(SQLITE_CREATE_TEMP_TRIGGER);
    DefInt(SQLITE_CREATE_TEMP_VIEW);
    DefInt(SQLITE_CREATE_TRIGGER);
    DefInt(SQLITE_CREATE_VIEW);
    DefInt(SQLITE_DELETE);
    DefInt(SQLITE_DROP_INDEX);
    DefInt(SQLITE_DROP_TABLE);
    DefInt(SQLITE_DROP_TEMP_INDEX);
    DefInt(SQLITE_DROP_TEMP_TABLE);
    DefInt(SQLITE_DROP_TEMP_TRIGGER);
    DefInt(SQLITE_DROP_TEMP_VIEW);
    DefInt(SQLITE_DROP_TRIGGER);
    DefInt(SQLITE_DROP_VIEW);
    DefInt(SQLITE_INSERT);
    DefInt(SQLITE_PRAGMA);
    DefInt(SQLITE_READ);
    DefInt(SQLITE_SELECT);
    DefInt(SQLITE_TRANSACTION);
    DefInt(SQLITE_UPDATE);
    DefInt(SQLITE_ATTACH);
    DefInt(SQLITE_DETACH);
    DefInt(SQLITE_ALTER_TABLE);
    DefInt(SQLITE_REINDEX);
    DefInt(SQLITE_ANALYZE);
    DefInt(SQLITE_CREATE_VTABLE);
    DefInt(SQLITE_DROP_VTABLE);
    DefInt(SQLITE_FUNCTION);
    DefInt(SQLITE_SAVEPOINT);
    //DefInt(SQLITE_COPY) /* No longer used */;
    DefInt(SQLITE_RECURSIVE);
  } _DefGroup;

  DefGroup(blobFinalizers) {
    /* SQLITE_STATIC/TRANSIENT need to be handled explicitly as
    ** integers to avoid casting-related warnings. */
    out("\"SQLITE_STATIC\":0, \"SQLITE_TRANSIENT\":-1");
    outf(",\"SQLITE_WASM_DEALLOC\": %lld",
         (sqlite3_int64)(sqlite3_free));
  } _DefGroup;

  DefGroup(changeset){
    DefInt(SQLITE_CHANGESETSTART_INVERT);
    DefInt(SQLITE_CHANGESETAPPLY_NOSAVEPOINT);
    DefInt(SQLITE_CHANGESETAPPLY_INVERT);

    DefInt(SQLITE_CHANGESET_DATA);
    DefInt(SQLITE_CHANGESET_NOTFOUND);
    DefInt(SQLITE_CHANGESET_CONFLICT);
    DefInt(SQLITE_CHANGESET_CONSTRAINT);
    DefInt(SQLITE_CHANGESET_FOREIGN_KEY);

    DefInt(SQLITE_CHANGESET_OMIT);
    DefInt(SQLITE_CHANGESET_REPLACE);
    DefInt(SQLITE_CHANGESET_ABORT);
  } _DefGroup;

  DefGroup(config){
    DefInt(SQLITE_CONFIG_SINGLETHREAD);
    DefInt(SQLITE_CONFIG_MULTITHREAD);
    DefInt(SQLITE_CONFIG_SERIALIZED);
    DefInt(SQLITE_CONFIG_MALLOC);
    DefInt(SQLITE_CONFIG_GETMALLOC);
    DefInt(SQLITE_CONFIG_SCRATCH);
    DefInt(SQLITE_CONFIG_PAGECACHE);
    DefInt(SQLITE_CONFIG_HEAP);
    DefInt(SQLITE_CONFIG_MEMSTATUS);
    DefInt(SQLITE_CONFIG_MUTEX);
    DefInt(SQLITE_CONFIG_GETMUTEX);
/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */
    DefInt(SQLITE_CONFIG_LOOKASIDE);
    DefInt(SQLITE_CONFIG_PCACHE);
    DefInt(SQLITE_CONFIG_GETPCACHE);
    DefInt(SQLITE_CONFIG_LOG);
    DefInt(SQLITE_CONFIG_URI);
    DefInt(SQLITE_CONFIG_PCACHE2);
    DefInt(SQLITE_CONFIG_GETPCACHE2);
    DefInt(SQLITE_CONFIG_COVERING_INDEX_SCAN);
    DefInt(SQLITE_CONFIG_SQLLOG);
    DefInt(SQLITE_CONFIG_MMAP_SIZE);
    DefInt(SQLITE_CONFIG_WIN32_HEAPSIZE);
    DefInt(SQLITE_CONFIG_PCACHE_HDRSZ);
    DefInt(SQLITE_CONFIG_PMASZ);
    DefInt(SQLITE_CONFIG_STMTJRNL_SPILL);
    DefInt(SQLITE_CONFIG_SMALL_MALLOC);
    DefInt(SQLITE_CONFIG_SORTERREF_SIZE);
    DefInt(SQLITE_CONFIG_MEMDB_MAXSIZE);
  } _DefGroup;

  DefGroup(dataTypes) {
    DefInt(SQLITE_INTEGER);
    DefInt(SQLITE_FLOAT);
    DefInt(SQLITE_TEXT);
    DefInt(SQLITE_BLOB);
    DefInt(SQLITE_NULL);
  } _DefGroup;

  DefGroup(dbConfig){
    DefInt(SQLITE_DBCONFIG_MAINDBNAME);
    DefInt(SQLITE_DBCONFIG_LOOKASIDE);
    DefInt(SQLITE_DBCONFIG_ENABLE_FKEY);
    DefInt(SQLITE_DBCONFIG_ENABLE_TRIGGER);
    DefInt(SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER);
    DefInt(SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION);
    DefInt(SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE);
    DefInt(SQLITE_DBCONFIG_ENABLE_QPSG);
    DefInt(SQLITE_DBCONFIG_TRIGGER_EQP);
    DefInt(SQLITE_DBCONFIG_RESET_DATABASE);
    DefInt(SQLITE_DBCONFIG_DEFENSIVE);
    DefInt(SQLITE_DBCONFIG_WRITABLE_SCHEMA);
    DefInt(SQLITE_DBCONFIG_LEGACY_ALTER_TABLE);
    DefInt(SQLITE_DBCONFIG_DQS_DML);
    DefInt(SQLITE_DBCONFIG_DQS_DDL);
    DefInt(SQLITE_DBCONFIG_ENABLE_VIEW);
    DefInt(SQLITE_DBCONFIG_LEGACY_FILE_FORMAT);
    DefInt(SQLITE_DBCONFIG_TRUSTED_SCHEMA);
    DefInt(SQLITE_DBCONFIG_MAX);
  } _DefGroup;

  DefGroup(dbStatus){
    DefInt(SQLITE_DBSTATUS_LOOKASIDE_USED);
    DefInt(SQLITE_DBSTATUS_CACHE_USED);
    DefInt(SQLITE_DBSTATUS_SCHEMA_USED);
    DefInt(SQLITE_DBSTATUS_STMT_USED);
    DefInt(SQLITE_DBSTATUS_LOOKASIDE_HIT);
    DefInt(SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE);
    DefInt(SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL);
    DefInt(SQLITE_DBSTATUS_CACHE_HIT);
    DefInt(SQLITE_DBSTATUS_CACHE_MISS);
    DefInt(SQLITE_DBSTATUS_CACHE_WRITE);
    DefInt(SQLITE_DBSTATUS_DEFERRED_FKS);
    DefInt(SQLITE_DBSTATUS_CACHE_USED_SHARED);
    DefInt(SQLITE_DBSTATUS_CACHE_SPILL);
    DefInt(SQLITE_DBSTATUS_MAX);
  } _DefGroup;

  DefGroup(encodings) {
    /* Noting that the wasm binding only aims to support UTF-8. */
    DefInt(SQLITE_UTF8);
    DefInt(SQLITE_UTF16LE);
    DefInt(SQLITE_UTF16BE);
    DefInt(SQLITE_UTF16);
    /*deprecated DefInt(SQLITE_ANY); */
    DefInt(SQLITE_UTF16_ALIGNED);
  } _DefGroup;

  DefGroup(fcntl) {
    DefInt(SQLITE_FCNTL_LOCKSTATE);
    DefInt(SQLITE_FCNTL_GET_LOCKPROXYFILE);
    DefInt(SQLITE_FCNTL_SET_LOCKPROXYFILE);
    DefInt(SQLITE_FCNTL_LAST_ERRNO);
    DefInt(SQLITE_FCNTL_SIZE_HINT);
    DefInt(SQLITE_FCNTL_CHUNK_SIZE);
    DefInt(SQLITE_FCNTL_FILE_POINTER);
    DefInt(SQLITE_FCNTL_SYNC_OMITTED);
    DefInt(SQLITE_FCNTL_WIN32_AV_RETRY);
    DefInt(SQLITE_FCNTL_PERSIST_WAL);
    DefInt(SQLITE_FCNTL_OVERWRITE);
    DefInt(SQLITE_FCNTL_VFSNAME);
    DefInt(SQLITE_FCNTL_POWERSAFE_OVERWRITE);
    DefInt(SQLITE_FCNTL_PRAGMA);
    DefInt(SQLITE_FCNTL_BUSYHANDLER);
    DefInt(SQLITE_FCNTL_TEMPFILENAME);
    DefInt(SQLITE_FCNTL_MMAP_SIZE);
    DefInt(SQLITE_FCNTL_TRACE);
    DefInt(SQLITE_FCNTL_HAS_MOVED);
    DefInt(SQLITE_FCNTL_SYNC);
    DefInt(SQLITE_FCNTL_COMMIT_PHASETWO);
    DefInt(SQLITE_FCNTL_WIN32_SET_HANDLE);
    DefInt(SQLITE_FCNTL_WAL_BLOCK);
    DefInt(SQLITE_FCNTL_ZIPVFS);
    DefInt(SQLITE_FCNTL_RBU);
    DefInt(SQLITE_FCNTL_VFS_POINTER);
    DefInt(SQLITE_FCNTL_JOURNAL_POINTER);
    DefInt(SQLITE_FCNTL_WIN32_GET_HANDLE);
    DefInt(SQLITE_FCNTL_PDB);
    DefInt(SQLITE_FCNTL_BEGIN_ATOMIC_WRITE);
    DefInt(SQLITE_FCNTL_COMMIT_ATOMIC_WRITE);
    DefInt(SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE);
    DefInt(SQLITE_FCNTL_LOCK_TIMEOUT);
    DefInt(SQLITE_FCNTL_DATA_VERSION);
    DefInt(SQLITE_FCNTL_SIZE_LIMIT);
    DefInt(SQLITE_FCNTL_CKPT_DONE);
    DefInt(SQLITE_FCNTL_RESERVE_BYTES);
    DefInt(SQLITE_FCNTL_CKPT_START);
    DefInt(SQLITE_FCNTL_EXTERNAL_READER);
    DefInt(SQLITE_FCNTL_CKSM_FILE);
  } _DefGroup;

  DefGroup(flock) {
    DefInt(SQLITE_LOCK_NONE);
    DefInt(SQLITE_LOCK_SHARED);
    DefInt(SQLITE_LOCK_RESERVED);
    DefInt(SQLITE_LOCK_PENDING);
    DefInt(SQLITE_LOCK_EXCLUSIVE);
  } _DefGroup;

  DefGroup(ioCap) {
    DefInt(SQLITE_IOCAP_ATOMIC);
    DefInt(SQLITE_IOCAP_ATOMIC512);
    DefInt(SQLITE_IOCAP_ATOMIC1K);
    DefInt(SQLITE_IOCAP_ATOMIC2K);
    DefInt(SQLITE_IOCAP_ATOMIC4K);
    DefInt(SQLITE_IOCAP_ATOMIC8K);
    DefInt(SQLITE_IOCAP_ATOMIC16K);
    DefInt(SQLITE_IOCAP_ATOMIC32K);
    DefInt(SQLITE_IOCAP_ATOMIC64K);
    DefInt(SQLITE_IOCAP_SAFE_APPEND);
    DefInt(SQLITE_IOCAP_SEQUENTIAL);
    DefInt(SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN);
    DefInt(SQLITE_IOCAP_POWERSAFE_OVERWRITE);
    DefInt(SQLITE_IOCAP_IMMUTABLE);
    DefInt(SQLITE_IOCAP_BATCH_ATOMIC);
  } _DefGroup;

  DefGroup(limits) {
    DefInt(SQLITE_MAX_ALLOCATION_SIZE);
    DefInt(SQLITE_LIMIT_LENGTH);
    DefInt(SQLITE_MAX_LENGTH);
    DefInt(SQLITE_LIMIT_SQL_LENGTH);
    DefInt(SQLITE_MAX_SQL_LENGTH);
    DefInt(SQLITE_LIMIT_COLUMN);
    DefInt(SQLITE_MAX_COLUMN);
    DefInt(SQLITE_LIMIT_EXPR_DEPTH);
    DefInt(SQLITE_MAX_EXPR_DEPTH);
    DefInt(SQLITE_LIMIT_COMPOUND_SELECT);
    DefInt(SQLITE_MAX_COMPOUND_SELECT);
    DefInt(SQLITE_LIMIT_VDBE_OP);
    DefInt(SQLITE_MAX_VDBE_OP);
    DefInt(SQLITE_LIMIT_FUNCTION_ARG);
    DefInt(SQLITE_MAX_FUNCTION_ARG);
    DefInt(SQLITE_LIMIT_ATTACHED);
    DefInt(SQLITE_MAX_ATTACHED);
    DefInt(SQLITE_LIMIT_LIKE_PATTERN_LENGTH);
    DefInt(SQLITE_MAX_LIKE_PATTERN_LENGTH);
    DefInt(SQLITE_LIMIT_VARIABLE_NUMBER);
    DefInt(SQLITE_MAX_VARIABLE_NUMBER);
    DefInt(SQLITE_LIMIT_TRIGGER_DEPTH);
    DefInt(SQLITE_MAX_TRIGGER_DEPTH);
    DefInt(SQLITE_LIMIT_WORKER_THREADS);
    DefInt(SQLITE_MAX_WORKER_THREADS);
  } _DefGroup;

  DefGroup(openFlags) {
    /* Noting that not all of these will have any effect in
    ** WASM-space. */
    DefInt(SQLITE_OPEN_READONLY);
    DefInt(SQLITE_OPEN_READWRITE);
    DefInt(SQLITE_OPEN_CREATE);
    DefInt(SQLITE_OPEN_URI);
    DefInt(SQLITE_OPEN_MEMORY);
    DefInt(SQLITE_OPEN_NOMUTEX);
    DefInt(SQLITE_OPEN_FULLMUTEX);
    DefInt(SQLITE_OPEN_SHAREDCACHE);
    DefInt(SQLITE_OPEN_PRIVATECACHE);
    DefInt(SQLITE_OPEN_EXRESCODE);
    DefInt(SQLITE_OPEN_NOFOLLOW);
    /* OPEN flags for use with VFSes... */
    DefInt(SQLITE_OPEN_MAIN_DB);
    DefInt(SQLITE_OPEN_MAIN_JOURNAL);
    DefInt(SQLITE_OPEN_TEMP_DB);
    DefInt(SQLITE_OPEN_TEMP_JOURNAL);
    DefInt(SQLITE_OPEN_TRANSIENT_DB);
    DefInt(SQLITE_OPEN_SUBJOURNAL);
    DefInt(SQLITE_OPEN_SUPER_JOURNAL);
    DefInt(SQLITE_OPEN_WAL);
    DefInt(SQLITE_OPEN_DELETEONCLOSE);
    DefInt(SQLITE_OPEN_EXCLUSIVE);
  } _DefGroup;

  DefGroup(prepareFlags) {
    DefInt(SQLITE_PREPARE_PERSISTENT);
    DefInt(SQLITE_PREPARE_NORMALIZE);
    DefInt(SQLITE_PREPARE_NO_VTAB);
  } _DefGroup;

  DefGroup(resultCodes) {
    DefInt(SQLITE_OK);
    DefInt(SQLITE_ERROR);
    DefInt(SQLITE_INTERNAL);
    DefInt(SQLITE_PERM);
    DefInt(SQLITE_ABORT);
    DefInt(SQLITE_BUSY);
    DefInt(SQLITE_LOCKED);
    DefInt(SQLITE_NOMEM);
    DefInt(SQLITE_READONLY);
    DefInt(SQLITE_INTERRUPT);
    DefInt(SQLITE_IOERR);
    DefInt(SQLITE_CORRUPT);
    DefInt(SQLITE_NOTFOUND);
    DefInt(SQLITE_FULL);
    DefInt(SQLITE_CANTOPEN);
    DefInt(SQLITE_PROTOCOL);
    DefInt(SQLITE_EMPTY);
    DefInt(SQLITE_SCHEMA);
    DefInt(SQLITE_TOOBIG);
    DefInt(SQLITE_CONSTRAINT);
    DefInt(SQLITE_MISMATCH);
    DefInt(SQLITE_MISUSE);
    DefInt(SQLITE_NOLFS);
    DefInt(SQLITE_AUTH);
    DefInt(SQLITE_FORMAT);
    DefInt(SQLITE_RANGE);
    DefInt(SQLITE_NOTADB);
    DefInt(SQLITE_NOTICE);
    DefInt(SQLITE_WARNING);
    DefInt(SQLITE_ROW);
    DefInt(SQLITE_DONE);
    // Extended Result Codes
    DefInt(SQLITE_ERROR_MISSING_COLLSEQ);
    DefInt(SQLITE_ERROR_RETRY);
    DefInt(SQLITE_ERROR_SNAPSHOT);
    DefInt(SQLITE_IOERR_READ);
    DefInt(SQLITE_IOERR_SHORT_READ);
    DefInt(SQLITE_IOERR_WRITE);
    DefInt(SQLITE_IOERR_FSYNC);
    DefInt(SQLITE_IOERR_DIR_FSYNC);
    DefInt(SQLITE_IOERR_TRUNCATE);
    DefInt(SQLITE_IOERR_FSTAT);
    DefInt(SQLITE_IOERR_UNLOCK);
    DefInt(SQLITE_IOERR_RDLOCK);
    DefInt(SQLITE_IOERR_DELETE);
    DefInt(SQLITE_IOERR_BLOCKED);
    DefInt(SQLITE_IOERR_NOMEM);
    DefInt(SQLITE_IOERR_ACCESS);
    DefInt(SQLITE_IOERR_CHECKRESERVEDLOCK);
    DefInt(SQLITE_IOERR_LOCK);
    DefInt(SQLITE_IOERR_CLOSE);
    DefInt(SQLITE_IOERR_DIR_CLOSE);
    DefInt(SQLITE_IOERR_SHMOPEN);
    DefInt(SQLITE_IOERR_SHMSIZE);
    DefInt(SQLITE_IOERR_SHMLOCK);
    DefInt(SQLITE_IOERR_SHMMAP);
    DefInt(SQLITE_IOERR_SEEK);
    DefInt(SQLITE_IOERR_DELETE_NOENT);
    DefInt(SQLITE_IOERR_MMAP);
    DefInt(SQLITE_IOERR_GETTEMPPATH);
    DefInt(SQLITE_IOERR_CONVPATH);
    DefInt(SQLITE_IOERR_VNODE);
    DefInt(SQLITE_IOERR_AUTH);
    DefInt(SQLITE_IOERR_BEGIN_ATOMIC);
    DefInt(SQLITE_IOERR_COMMIT_ATOMIC);
    DefInt(SQLITE_IOERR_ROLLBACK_ATOMIC);
    DefInt(SQLITE_IOERR_DATA);
    DefInt(SQLITE_IOERR_CORRUPTFS);
    DefInt(SQLITE_LOCKED_SHAREDCACHE);
    DefInt(SQLITE_LOCKED_VTAB);
    DefInt(SQLITE_BUSY_RECOVERY);
    DefInt(SQLITE_BUSY_SNAPSHOT);
    DefInt(SQLITE_BUSY_TIMEOUT);
    DefInt(SQLITE_CANTOPEN_NOTEMPDIR);
    DefInt(SQLITE_CANTOPEN_ISDIR);
    DefInt(SQLITE_CANTOPEN_FULLPATH);
    DefInt(SQLITE_CANTOPEN_CONVPATH);
    //DefInt(SQLITE_CANTOPEN_DIRTYWAL)/*docs say not used*/;
    DefInt(SQLITE_CANTOPEN_SYMLINK);
    DefInt(SQLITE_CORRUPT_VTAB);
    DefInt(SQLITE_CORRUPT_SEQUENCE);
    DefInt(SQLITE_CORRUPT_INDEX);
    DefInt(SQLITE_READONLY_RECOVERY);
    DefInt(SQLITE_READONLY_CANTLOCK);
    DefInt(SQLITE_READONLY_ROLLBACK);
    DefInt(SQLITE_READONLY_DBMOVED);
    DefInt(SQLITE_READONLY_CANTINIT);
    DefInt(SQLITE_READONLY_DIRECTORY);
    DefInt(SQLITE_ABORT_ROLLBACK);
    DefInt(SQLITE_CONSTRAINT_CHECK);
    DefInt(SQLITE_CONSTRAINT_COMMITHOOK);
    DefInt(SQLITE_CONSTRAINT_FOREIGNKEY);
    DefInt(SQLITE_CONSTRAINT_FUNCTION);
    DefInt(SQLITE_CONSTRAINT_NOTNULL);
    DefInt(SQLITE_CONSTRAINT_PRIMARYKEY);
    DefInt(SQLITE_CONSTRAINT_TRIGGER);
    DefInt(SQLITE_CONSTRAINT_UNIQUE);
    DefInt(SQLITE_CONSTRAINT_VTAB);
    DefInt(SQLITE_CONSTRAINT_ROWID);
    DefInt(SQLITE_CONSTRAINT_PINNED);
    DefInt(SQLITE_CONSTRAINT_DATATYPE);
    DefInt(SQLITE_NOTICE_RECOVER_WAL);
    DefInt(SQLITE_NOTICE_RECOVER_ROLLBACK);
    DefInt(SQLITE_WARNING_AUTOINDEX);
    DefInt(SQLITE_AUTH_USER);
    DefInt(SQLITE_OK_LOAD_PERMANENTLY);
    //DefInt(SQLITE_OK_SYMLINK) /* internal use only */;
  } _DefGroup;

  DefGroup(serialize){
    DefInt(SQLITE_SERIALIZE_NOCOPY);
    DefInt(SQLITE_DESERIALIZE_FREEONCLOSE);
    DefInt(SQLITE_DESERIALIZE_READONLY);
    DefInt(SQLITE_DESERIALIZE_RESIZEABLE);
  } _DefGroup;

  DefGroup(session){
    DefInt(SQLITE_SESSION_CONFIG_STRMSIZE);
    DefInt(SQLITE_SESSION_OBJCONFIG_SIZE);
  } _DefGroup;

  DefGroup(sqlite3Status){
    DefInt(SQLITE_STATUS_MEMORY_USED);
    DefInt(SQLITE_STATUS_PAGECACHE_USED);
    DefInt(SQLITE_STATUS_PAGECACHE_OVERFLOW);
    //DefInt(SQLITE_STATUS_SCRATCH_USED) /* NOT USED */;
    //DefInt(SQLITE_STATUS_SCRATCH_OVERFLOW) /* NOT USED */;
    DefInt(SQLITE_STATUS_MALLOC_SIZE);
    DefInt(SQLITE_STATUS_PARSER_STACK);
    DefInt(SQLITE_STATUS_PAGECACHE_SIZE);
    //DefInt(SQLITE_STATUS_SCRATCH_SIZE) /* NOT USED */;
    DefInt(SQLITE_STATUS_MALLOC_COUNT);
  } _DefGroup;

  DefGroup(stmtStatus){
    DefInt(SQLITE_STMTSTATUS_FULLSCAN_STEP);
    DefInt(SQLITE_STMTSTATUS_SORT);
    DefInt(SQLITE_STMTSTATUS_AUTOINDEX);
    DefInt(SQLITE_STMTSTATUS_VM_STEP);
    DefInt(SQLITE_STMTSTATUS_REPREPARE);
    DefInt(SQLITE_STMTSTATUS_RUN);
    DefInt(SQLITE_STMTSTATUS_FILTER_MISS);
    DefInt(SQLITE_STMTSTATUS_FILTER_HIT);
    DefInt(SQLITE_STMTSTATUS_MEMUSED);
  } _DefGroup;
  
  DefGroup(syncFlags) {
    DefInt(SQLITE_SYNC_NORMAL);
    DefInt(SQLITE_SYNC_FULL);
    DefInt(SQLITE_SYNC_DATAONLY);
  } _DefGroup;

  DefGroup(trace) {
    DefInt(SQLITE_TRACE_STMT);
    DefInt(SQLITE_TRACE_PROFILE);
    DefInt(SQLITE_TRACE_ROW);
    DefInt(SQLITE_TRACE_CLOSE);
  } _DefGroup;

  DefGroup(txnState){
    DefInt(SQLITE_TXN_NONE);
    DefInt(SQLITE_TXN_READ);
    DefInt(SQLITE_TXN_WRITE);
  } _DefGroup;

  DefGroup(udfFlags) {
    DefInt(SQLITE_DETERMINISTIC);
    DefInt(SQLITE_DIRECTONLY);
    DefInt(SQLITE_INNOCUOUS);
  } _DefGroup;

  DefGroup(version) {
    DefInt(SQLITE_VERSION_NUMBER);
    DefStr(SQLITE_VERSION);
    DefStr(SQLITE_SOURCE_ID);
  } _DefGroup;

  DefGroup(vtab) {
    DefInt(SQLITE_INDEX_SCAN_UNIQUE);
    DefInt(SQLITE_INDEX_CONSTRAINT_EQ);
    DefInt(SQLITE_INDEX_CONSTRAINT_GT);
    DefInt(SQLITE_INDEX_CONSTRAINT_LE);
    DefInt(SQLITE_INDEX_CONSTRAINT_LT);
    DefInt(SQLITE_INDEX_CONSTRAINT_GE);
    DefInt(SQLITE_INDEX_CONSTRAINT_MATCH);
    DefInt(SQLITE_INDEX_CONSTRAINT_LIKE);
    DefInt(SQLITE_INDEX_CONSTRAINT_GLOB);
    DefInt(SQLITE_INDEX_CONSTRAINT_REGEXP);
    DefInt(SQLITE_INDEX_CONSTRAINT_NE);
    DefInt(SQLITE_INDEX_CONSTRAINT_ISNOT);
    DefInt(SQLITE_INDEX_CONSTRAINT_ISNOTNULL);
    DefInt(SQLITE_INDEX_CONSTRAINT_ISNULL);
    DefInt(SQLITE_INDEX_CONSTRAINT_IS);
    DefInt(SQLITE_INDEX_CONSTRAINT_LIMIT);
    DefInt(SQLITE_INDEX_CONSTRAINT_OFFSET);
    DefInt(SQLITE_INDEX_CONSTRAINT_FUNCTION);
    DefInt(SQLITE_VTAB_CONSTRAINT_SUPPORT);
    DefInt(SQLITE_VTAB_INNOCUOUS);
    DefInt(SQLITE_VTAB_DIRECTONLY);
    DefInt(SQLITE_ROLLBACK);
    //DefInt(SQLITE_IGNORE); // Also used by sqlite3_authorizer() callback
    DefInt(SQLITE_FAIL);
    //DefInt(SQLITE_ABORT); // Also an error code
    DefInt(SQLITE_REPLACE);
  } _DefGroup;

#undef DefGroup
#undef DefStr
#undef DefInt
#undef _DefGroup

  /*
  ** Emit an array of "StructBinder" struct descripions, which look
  ** like:
  **
  ** {
  **   "name": "MyStruct",
  **   "sizeof": 16,
  **   "members": {
  **     "member1": {"offset": 0,"sizeof": 4,"signature": "i"},
  **     "member2": {"offset": 4,"sizeof": 4,"signature": "p"},
  **     "member3": {"offset": 8,"sizeof": 8,"signature": "j"}
  **   }
  ** }
  **
  ** Detailed documentation for those bits are in the docs for the
  ** Jaccwabyt JS-side component.
  */

  /** Macros for emitting StructBinder description. */
#define StructBinder__(TYPE)                 \
  n = 0;                                     \
  outf("%s{", (nStruct++ ? ", " : ""));      \
  out("\"name\": \"" # TYPE "\",");          \
  outf("\"sizeof\": %d", (int)sizeof(TYPE)); \
  out(",\"members\": {");
#define StructBinder_(T) StructBinder__(T)
  /** ^^^ indirection needed to expand CurrentStruct */
#define StructBinder StructBinder_(CurrentStruct)
#define _StructBinder CloseBrace(2)
#define M(MEMBER,SIG)                                         \
  outf("%s\"%s\": "                                           \
       "{\"offset\":%d,\"sizeof\": %d,\"signature\":\"%s\"}", \
       (n++ ? ", " : ""), #MEMBER,                            \
       (int)offsetof(CurrentStruct,MEMBER),                   \
       (int)sizeof(((CurrentStruct*)0)->MEMBER),              \
       SIG)

  nStruct = 0;
  out(", \"structs\": ["); {

#define CurrentStruct sqlite3_vfs
    StructBinder {
      M(iVersion,          "i");
      M(szOsFile,          "i");
      M(mxPathname,        "i");
      M(pNext,             "p");
      M(zName,             "s");
      M(pAppData,          "p");
      M(xOpen,             "i(pppip)");
      M(xDelete,           "i(ppi)");
      M(xAccess,           "i(ppip)");
      M(xFullPathname,     "i(ppip)");
      M(xDlOpen,           "p(pp)");
      M(xDlError,          "p(pip)");
      M(xDlSym,            "p()");
      M(xDlClose,          "v(pp)");
      M(xRandomness,       "i(pip)");
      M(xSleep,            "i(pi)");
      M(xCurrentTime,      "i(pp)");
      M(xGetLastError,     "i(pip)");
      M(xCurrentTimeInt64, "i(pp)");
      M(xSetSystemCall,    "i(ppp)");
      M(xGetSystemCall,    "p(pp)");
      M(xNextSystemCall,   "p(pp)");
    } _StructBinder;
#undef CurrentStruct

#define CurrentStruct sqlite3_io_methods
    StructBinder {
      M(iVersion,               "i");
      M(xClose,                 "i(p)");
      M(xRead,                  "i(ppij)");
      M(xWrite,                 "i(ppij)");
      M(xTruncate,              "i(pj)");
      M(xSync,                  "i(pi)");
      M(xFileSize,              "i(pp)");
      M(xLock,                  "i(pi)");
      M(xUnlock,                "i(pi)");
      M(xCheckReservedLock,     "i(pp)");
      M(xFileControl,           "i(pip)");
      M(xSectorSize,            "i(p)");
      M(xDeviceCharacteristics, "i(p)");
      M(xShmMap,                "i(piiip)");
      M(xShmLock,               "i(piii)");
      M(xShmBarrier,            "v(p)");
      M(xShmUnmap,              "i(pi)");
      M(xFetch,                 "i(pjip)");
      M(xUnfetch,               "i(pjp)");
    } _StructBinder;
#undef CurrentStruct

#define CurrentStruct sqlite3_file
    StructBinder {
      M(pMethods, "p");
    } _StructBinder;
#undef CurrentStruct

#define CurrentStruct sqlite3_kvvfs_methods
    StructBinder {
      M(xRead,    "i(sspi)");
      M(xWrite,   "i(sss)");
      M(xDelete,  "i(ss)");
      M(nKeySize, "i");
    } _StructBinder;
#undef CurrentStruct


#define CurrentStruct sqlite3_vtab
    StructBinder {
      M(pModule, "p");
      M(nRef,    "i");
      M(zErrMsg, "p");
    } _StructBinder;
#undef CurrentStruct

#define CurrentStruct sqlite3_vtab_cursor
    StructBinder {
      M(pVtab, "p");
    } _StructBinder;
#undef CurrentStruct

#define CurrentStruct sqlite3_module
    StructBinder {
      M(iVersion,       "i");
      M(xCreate,        "i(ppippp)");
      M(xConnect,       "i(ppippp)");
      M(xBestIndex,     "i(pp)");
      M(xDisconnect,    "i(p)");
      M(xDestroy,       "i(p)");
      M(xOpen,          "i(pp)");
      M(xClose,         "i(p)");
      M(xFilter,        "i(pisip)");
      M(xNext,          "i(p)");
      M(xEof,           "i(p)");
      M(xColumn,        "i(ppi)");
      M(xRowid,         "i(pp)");
      M(xUpdate,        "i(pipp)");
      M(xBegin,         "i(p)");
      M(xSync,          "i(p)");
      M(xCommit,        "i(p)");
      M(xRollback,      "i(p)");
      M(xFindFunction,  "i(pispp)");
      M(xRename,        "i(ps)");
      // ^^^ v1. v2+ follows...
      M(xSavepoint,     "i(pi)");
      M(xRelease,       "i(pi)");
      M(xRollbackTo,    "i(pi)");
      // ^^^ v2. v3+ follows...
      M(xShadowName,    "i(s)");
    } _StructBinder;
#undef CurrentStruct
    
    /**
     ** Workaround: in order to map the various inner structs from
     ** sqlite3_index_info, we have to uplift those into constructs we
     ** can access by type name. These structs _must_ match their
     ** in-sqlite3_index_info counterparts byte for byte.
    */
    typedef struct {
      int iColumn;
      unsigned char op;
      unsigned char usable;
      int iTermOffset;
    } sqlite3_index_constraint;
    typedef struct {
      int iColumn;
      unsigned char desc;
    } sqlite3_index_orderby;
    typedef struct {
      int argvIndex;
      unsigned char omit;
    } sqlite3_index_constraint_usage;
    { /* Validate that the above struct sizeof()s match
      ** expectations. We could improve upon this by
      ** checking the offsetof() for each member. */
      const sqlite3_index_info siiCheck;
#define IndexSzCheck(T,M)           \
      (sizeof(T) == sizeof(*siiCheck.M))
      if(!IndexSzCheck(sqlite3_index_constraint,aConstraint)
         || !IndexSzCheck(sqlite3_index_orderby,aOrderBy)
         || !IndexSzCheck(sqlite3_index_constraint_usage,aConstraintUsage)){
        assert(!"sizeof mismatch in sqlite3_index_... struct(s)");
        return 0;
      }
#undef IndexSzCheck
    }

#define CurrentStruct sqlite3_index_constraint
    StructBinder {
      M(iColumn,        "i");
      M(op,             "C");
      M(usable,         "C");
      M(iTermOffset,    "i");
    } _StructBinder;
#undef CurrentStruct

#define CurrentStruct sqlite3_index_orderby
    StructBinder {
      M(iColumn,   "i");
      M(desc,      "C");
    } _StructBinder;
#undef CurrentStruct

#define CurrentStruct sqlite3_index_constraint_usage
    StructBinder {
      M(argvIndex,  "i");
      M(omit,       "C");
    } _StructBinder;
#undef CurrentStruct

#define CurrentStruct sqlite3_index_info
    StructBinder {
      M(nConstraint,        "i");
      M(aConstraint,        "p");
      M(nOrderBy,           "i");
      M(aOrderBy,           "p");
      M(aConstraintUsage,   "p");
      M(idxNum,             "i");
      M(idxStr,             "p");
      M(needToFreeIdxStr,   "i");
      M(orderByConsumed,    "i");
      M(estimatedCost,      "d");
      M(estimatedRows,      "j");
      M(idxFlags,           "i");
      M(colUsed,            "j");
    } _StructBinder;
#undef CurrentStruct

#if SQLITE_WASM_TESTS
#define CurrentStruct WasmTestStruct
    StructBinder {
      M(v4,    "i");
      M(cstr,  "s");
      M(ppV,   "p");
      M(v8,    "j");
      M(xFunc, "v(p)");
    } _StructBinder;
#undef CurrentStruct
#endif

  } out( "]"/*structs*/);

  out("}"/*top-level object*/);
  *zPos = 0;
  aBuffer[0] = '{'/*end of the race-condition workaround*/;
  return aBuffer;
#undef StructBinder
#undef StructBinder_
#undef StructBinder__
#undef M
#undef _StructBinder
#undef CloseBrace
#undef out
#undef outf
#undef lenCheck
}

/*
** This function is NOT part of the sqlite3 public API. It is strictly
** for use by the sqlite project's own JS/WASM bindings.
**
** This function invokes the xDelete method of the given VFS (or the
** default VFS if pVfs is NULL), passing on the given filename. If
** zName is NULL, no default VFS is found, or it has no xDelete
** method, SQLITE_MISUSE is returned, else the result of the xDelete()
** call is returned.
*/
SQLITE_WASM_KEEP
int sqlite3_wasm_vfs_unlink(sqlite3_vfs *pVfs, const char *zName){
  int rc = SQLITE_MISUSE /* ??? */;
  if( 0==pVfs && 0!=zName ) pVfs = sqlite3_vfs_find(0);
  if( zName && pVfs && pVfs->xDelete ){
    rc = pVfs->xDelete(pVfs, zName, 1);
  }
  return rc;
}

/*
** This function is NOT part of the sqlite3 public API. It is strictly
** for use by the sqlite project's own JS/WASM bindings.
**
** Returns a pointer to the given DB's VFS for the given DB name,
** defaulting to "main" if zDbName is 0. Returns 0 if no db with the
** given name is open.
*/
SQLITE_WASM_KEEP
sqlite3_vfs * sqlite3_wasm_db_vfs(sqlite3 *pDb, const char *zDbName){
  sqlite3_vfs * pVfs = 0;
  sqlite3_file_control(pDb, zDbName ? zDbName : "main",
                       SQLITE_FCNTL_VFS_POINTER, &pVfs);
  return pVfs;
}

/*
** This function is NOT part of the sqlite3 public API. It is strictly
** for use by the sqlite project's own JS/WASM bindings.
**
** This function resets the given db pointer's database as described at
**
** https://sqlite.org/c3ref/c_dbconfig_defensive.html#sqlitedbconfigresetdatabase
**
** But beware: virtual tables destroyed that way do not have their
** xDestroy() called, so will leak if they require that function for
** proper cleanup.
**
** Returns 0 on success, an SQLITE_xxx code on error. Returns
** SQLITE_MISUSE if pDb is NULL.
*/
SQLITE_WASM_KEEP
int sqlite3_wasm_db_reset(sqlite3 *pDb){
  int rc = SQLITE_MISUSE;
  if( pDb ){
    sqlite3_table_column_metadata(pDb, "main", 0, 0, 0, 0, 0, 0, 0);
    rc = sqlite3_db_config(pDb, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0);
    if( 0==rc ){
      rc = sqlite3_exec(pDb, "VACUUM", 0, 0, 0);
      sqlite3_db_config(pDb, SQLITE_DBCONFIG_RESET_DATABASE, 0, 0);
    }
  }
  return rc;
}

/*
** This function is NOT part of the sqlite3 public API. It is strictly
** for use by the sqlite project's own JS/WASM bindings.
**
** Uses the given database's VFS xRead to stream the db file's
** contents out to the given callback. The callback gets a single
** chunk of size n (its 2nd argument) on each call and must return 0
** on success, non-0 on error. This function returns 0 on success,
** SQLITE_NOTFOUND if no db is open, or propagates any other non-0
** code from the callback. Note that this is not thread-friendly: it
** expects that it will be the only thread reading the db file and
** takes no measures to ensure that is the case.
**
** This implementation appears to work fine, but
** sqlite3_wasm_db_serialize() is arguably the better way to achieve
** this.
*/
SQLITE_WASM_KEEP
int sqlite3_wasm_db_export_chunked( sqlite3* pDb,
                                    int (*xCallback)(unsigned const char *zOut, int n) ){
  sqlite3_int64 nSize = 0;
  sqlite3_int64 nPos = 0;
  sqlite3_file * pFile = 0;
  unsigned char buf[1024 * 8];
  int nBuf = (int)sizeof(buf);
  int rc = pDb
    ? sqlite3_file_control(pDb, "main",
                           SQLITE_FCNTL_FILE_POINTER, &pFile)
    : SQLITE_NOTFOUND;
  if( rc ) return rc;
  rc = pFile->pMethods->xFileSize(pFile, &nSize);
  if( rc ) return rc;
  if(nSize % nBuf){
    /* DB size is not an even multiple of the buffer size. Reduce
    ** buffer size so that we do not unduly inflate the db size
    ** with zero-padding when exporting. */
    if(0 == nSize % 4096) nBuf = 4096;
    else if(0 == nSize % 2048) nBuf = 2048;
    else if(0 == nSize % 1024) nBuf = 1024;
    else nBuf = 512;
  }
  for( ; 0==rc && nPos<nSize; nPos += nBuf ){
    rc = pFile->pMethods->xRead(pFile, buf, nBuf, nPos);
    if( SQLITE_IOERR_SHORT_READ == rc ){
      rc = (nPos + nBuf) < nSize ? rc : 0/*assume EOF*/;
    }
    if( 0==rc ) rc = xCallback(buf, nBuf);
  }
  return rc;
}

/*
** This function is NOT part of the sqlite3 public API. It is strictly
** for use by the sqlite project's own JS/WASM bindings.
**
** A proxy for sqlite3_serialize() which serializes the schema zSchema
** of pDb, placing the serialized output in pOut and nOut. nOut may be
** NULL. If zSchema is NULL then "main" is assumed. If pDb or pOut are
** NULL then SQLITE_MISUSE is returned. If allocation of the
** serialized copy fails, SQLITE_NOMEM is returned.  On success, 0 is
** returned and `*pOut` will contain a pointer to the memory unless
** mFlags includes SQLITE_SERIALIZE_NOCOPY and the database has no
** contiguous memory representation, in which case `*pOut` will be
** NULL but 0 will be returned.
**
** If `*pOut` is not NULL, the caller is responsible for passing it to
** sqlite3_free() to free it.
*/
SQLITE_WASM_KEEP
int sqlite3_wasm_db_serialize( sqlite3 *pDb, const char *zSchema,
                               unsigned char **pOut,
                               sqlite3_int64 *nOut, unsigned int mFlags ){
  unsigned char * z;
  if( !pDb || !pOut ) return SQLITE_MISUSE;
  if( nOut ) *nOut = 0;
  z = sqlite3_serialize(pDb, zSchema ? zSchema : "main", nOut, mFlags);
  if( z || (SQLITE_SERIALIZE_NOCOPY & mFlags) ){
    *pOut = z;
    return 0;
  }else{
    return SQLITE_NOMEM;
  }
}

/*
** This function is NOT part of the sqlite3 public API. It is strictly
** for use by the sqlite project's own JS/WASM bindings.
**
** Creates a new file using the I/O API of the given VFS, containing
** the given number of bytes of the given data. If the file exists, it
** is truncated to the given length and populated with the given
** data.
**
** This function exists so that we can implement the equivalent of
** Emscripten's FS.createDataFile() in a VFS-agnostic way. This
** functionality is intended for use in uploading database files.
**
** Not all VFSes support this functionality, e.g. the "kvvfs" does
** not.
**
** If pVfs is NULL, sqlite3_vfs_find(0) is used.
**
** If zFile is NULL, pVfs is NULL (and sqlite3_vfs_find(0) returns
** NULL), or nData is negative, SQLITE_MISUSE are returned.
**
** On success, it creates a new file with the given name, populated
** with the fist nData bytes of pData. If pData is NULL, the file is
** created and/or truncated to nData bytes.
**
** Whether or not directory components of zFilename are created
** automatically or not is unspecified: that detail is left to the
** VFS. The "opfs" VFS, for example, creates them.
**
** If an error happens while populating or truncating the file, the
** target file will be deleted (if needed) if this function created
** it. If this function did not create it, it is not deleted but may
** be left in an undefined state.
**
** Returns 0 on success. On error, it returns a code described above
** or propagates a code from one of the I/O methods.
**
** Design note: nData is an integer, instead of int64, for WASM
** portability, so that the API can still work in builds where BigInt
** support is disabled or unavailable.
*/
SQLITE_WASM_KEEP
int sqlite3_wasm_vfs_create_file( sqlite3_vfs *pVfs,
                                  const char *zFilename,
                                  const unsigned char * pData,
                                  int nData ){
  int rc;
  sqlite3_file *pFile = 0;
  sqlite3_io_methods const *pIo;
  const int openFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
  int flagsOut = 0;
  int fileExisted = 0;
  int doUnlock = 0;
  const unsigned char *pPos = pData;
  const int blockSize = 512
    /* Because we are using pFile->pMethods->xWrite() for writing, and
    ** it may have a buffer limit related to sqlite3's pager size, we
    ** conservatively write in 512-byte blocks (smallest page
    ** size). */;
  //fprintf(stderr, "pVfs=%p, zFilename=%s, nData=%d\n", pVfs, zFilename, nData);
  if( !pVfs ) pVfs = sqlite3_vfs_find(0);
  if( !pVfs || !zFilename || nData<0 ) return SQLITE_MISUSE;
  pVfs->xAccess(pVfs, zFilename, SQLITE_ACCESS_EXISTS, &fileExisted);
  rc = sqlite3OsOpenMalloc(pVfs, zFilename, &pFile, openFlags, &flagsOut);
#if 0
# define RC fprintf(stderr,"create_file(%s,%s) @%d rc=%d\n", \
                    pVfs->zName, zFilename, __LINE__, rc);
#else
# define RC
#endif
  RC;
  if(rc) return rc;
  pIo = pFile->pMethods;
  if( pIo->xLock ) {
    /* We need xLock() in order to accommodate the OPFS VFS, as it
    ** obtains a writeable handle via the lock operation and releases
    ** it in xUnlock(). If we don't do those here, we have to add code
    ** to the VFS to account check whether it was locked before
    ** xFileSize(), xTruncate(), and the like, and release the lock
    ** only if it was unlocked when the op was started. */
    rc = pIo->xLock(pFile, SQLITE_LOCK_EXCLUSIVE);
    RC;
    doUnlock = 0==rc;
  }
  if( 0==rc ){
    rc = pIo->xTruncate(pFile, nData);
    RC;
  }
  if( 0==rc && 0!=pData && nData>0 ){
    while( 0==rc && nData>0 ){
      const int n = nData>=blockSize ? blockSize : nData;
      rc = pIo->xWrite(pFile, pPos, n, (sqlite3_int64)(pPos - pData));
      RC;
      nData -= n;
      pPos += n;
    }
    if( 0==rc && nData>0 ){
      assert( nData<blockSize );
      rc = pIo->xWrite(pFile, pPos, nData,
                       (sqlite3_int64)(pPos - pData));
      RC;
    }
  }
  if( pIo->xUnlock && doUnlock!=0 ){
    pIo->xUnlock(pFile, SQLITE_LOCK_NONE);
  }
  pIo->xClose(pFile);
  if( rc!=0 && 0==fileExisted ){
    pVfs->xDelete(pVfs, zFilename, 1);
  }
  RC;
#undef RC
  return rc;
}

/*
** This function is NOT part of the sqlite3 public API. It is strictly
** for use by the sqlite project's own JS/WASM bindings.
**
** Allocates sqlite3KvvfsMethods.nKeySize bytes from
** sqlite3_wasm_pstack_alloc() and returns 0 if that allocation fails,
** else it passes that string to kvstorageMakeKey() and returns a
** NUL-terminated pointer to that string. It is up to the caller to
** use sqlite3_wasm_pstack_restore() to free the returned pointer.
*/
SQLITE_WASM_KEEP
char * sqlite3_wasm_kvvfsMakeKeyOnPstack(const char *zClass,
                                         const char *zKeyIn){
  assert(sqlite3KvvfsMethods.nKeySize>24);
  char *zKeyOut =
    (char *)sqlite3_wasm_pstack_alloc(sqlite3KvvfsMethods.nKeySize);
  if(zKeyOut){
    kvstorageMakeKey(zClass, zKeyIn, zKeyOut);
  }
  return zKeyOut;
}

/*
** This function is NOT part of the sqlite3 public API. It is strictly
** for use by the sqlite project's own JS/WASM bindings.
**
** Returns the pointer to the singleton object which holds the kvvfs
** I/O methods and associated state.
*/
SQLITE_WASM_KEEP
sqlite3_kvvfs_methods * sqlite3_wasm_kvvfs_methods(void){
  return &sqlite3KvvfsMethods;
}

/*
** This function is NOT part of the sqlite3 public API. It is strictly
** for use by the sqlite project's own JS/WASM bindings.
**
** This is a proxy for the variadic sqlite3_vtab_config() which passes
** its argument on, or not, to sqlite3_vtab_config(), depending on the
** value of its 2nd argument. Returns the result of
** sqlite3_vtab_config(), or SQLITE_MISUSE if the 2nd arg is not a
** valid value.
*/
SQLITE_WASM_KEEP
int sqlite3_wasm_vtab_config(sqlite3 *pDb, int op, int arg){
  switch(op){
  case SQLITE_VTAB_DIRECTONLY:
  case SQLITE_VTAB_INNOCUOUS:
    return sqlite3_vtab_config(pDb, op);
  case SQLITE_VTAB_CONSTRAINT_SUPPORT:
    return sqlite3_vtab_config(pDb, op, arg);
  default:
    return SQLITE_MISUSE;
  }
}

/*
** This function is NOT part of the sqlite3 public API. It is strictly
** for use by the sqlite project's own JS/WASM bindings.
**
** Wrapper for the variants of sqlite3_db_config() which take
** (int,int*) variadic args.
*/
SQLITE_WASM_KEEP
int sqlite3_wasm_db_config_ip(sqlite3 *pDb, int op, int arg1, int* pArg2){
  switch(op){
    case SQLITE_DBCONFIG_ENABLE_FKEY:
    case SQLITE_DBCONFIG_ENABLE_TRIGGER:
    case SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER:
    case SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION:
    case SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE:
    case SQLITE_DBCONFIG_ENABLE_QPSG:
    case SQLITE_DBCONFIG_TRIGGER_EQP:
    case SQLITE_DBCONFIG_RESET_DATABASE:
    case SQLITE_DBCONFIG_DEFENSIVE:
    case SQLITE_DBCONFIG_WRITABLE_SCHEMA:
    case SQLITE_DBCONFIG_LEGACY_ALTER_TABLE:
    case SQLITE_DBCONFIG_DQS_DML:
    case SQLITE_DBCONFIG_DQS_DDL:
    case SQLITE_DBCONFIG_ENABLE_VIEW:
    case SQLITE_DBCONFIG_LEGACY_FILE_FORMAT:
    case SQLITE_DBCONFIG_TRUSTED_SCHEMA:
      return sqlite3_db_config(pDb, op, arg1, pArg2);
    default: return SQLITE_MISUSE;
  }
}

/*
** This function is NOT part of the sqlite3 public API. It is strictly
** for use by the sqlite project's own JS/WASM bindings.
**
** Wrapper for the variants of sqlite3_db_config() which take
** (void*,int,int) variadic args.
*/
SQLITE_WASM_KEEP
int sqlite3_wasm_db_config_pii(sqlite3 *pDb, int op, void * pArg1, int arg2, int arg3){
  switch(op){
    case SQLITE_DBCONFIG_LOOKASIDE:
      return sqlite3_db_config(pDb, op, pArg1, arg2, arg3);
    default: return SQLITE_MISUSE;
  }
}

/*
** This function is NOT part of the sqlite3 public API. It is strictly
** for use by the sqlite project's own JS/WASM bindings.
**
** Wrapper for the variants of sqlite3_db_config() which take
** (const char *) variadic args.
*/
SQLITE_WASM_KEEP
int sqlite3_wasm_db_config_s(sqlite3 *pDb, int op, const char *zArg){
  switch(op){
    case SQLITE_DBCONFIG_MAINDBNAME:
      return sqlite3_db_config(pDb, op, zArg);
    default: return SQLITE_MISUSE;
  }
}


/*
** This function is NOT part of the sqlite3 public API. It is strictly
** for use by the sqlite project's own JS/WASM bindings.
**
** Binding for combinations of sqlite3_config() arguments which take
** a single integer argument.
*/
SQLITE_WASM_KEEP
int sqlite3_wasm_config_i(int op, int arg){
  return sqlite3_config(op, arg);
}

/*
** This function is NOT part of the sqlite3 public API. It is strictly
** for use by the sqlite project's own JS/WASM bindings.
**
** Binding for combinations of sqlite3_config() arguments which take
** two int arguments.
*/
SQLITE_WASM_KEEP
int sqlite3_wasm_config_ii(int op, int arg1, int arg2){
  return sqlite3_config(op, arg1, arg2);
}

/*
** This function is NOT part of the sqlite3 public API. It is strictly
** for use by the sqlite project's own JS/WASM bindings.
**
** Binding for combinations of sqlite3_config() arguments which take
** a single i64 argument.
*/
SQLITE_WASM_KEEP
int sqlite3_wasm_config_j(int op, sqlite3_int64 arg){
  return sqlite3_config(op, arg);
}

#if 0
// Pending removal after verification of a workaround discussed in the
// forum post linked to below.
/*
** This function is NOT part of the sqlite3 public API. It is strictly
** for use by the sqlite project's own JS/WASM bindings.
**
** Returns a pointer to sqlite3_free(). In compliant browsers the
** return value, when passed to sqlite3.wasm.exports.functionEntry(),
** must resolve to the same function as
** sqlite3.wasm.exports.sqlite3_free. i.e. from a dev console where
** sqlite3 is exported globally, the following must be true:
**
** ```
** sqlite3.wasm.functionEntry(
**   sqlite3.wasm.exports.sqlite3_wasm_ptr_to_sqlite3_free()
** ) === sqlite3.wasm.exports.sqlite3_free
** ```
**
** Using a function to return this pointer, as opposed to exporting it
** via sqlite3_wasm_enum_json(), is an attempt to work around a
** Safari-specific quirk covered at
** https://sqlite.org/forum/info/e5b20e1feb37a19a.
**/
SQLITE_WASM_KEEP
void * sqlite3_wasm_ptr_to_sqlite3_free(void){
  return (void*)sqlite3_free;
}
#endif

#if defined(__EMSCRIPTEN__) && defined(SQLITE_ENABLE_WASMFS)
#include <emscripten/wasmfs.h>

/*
** This function is NOT part of the sqlite3 public API. It is strictly
** for use by the sqlite project's own JS/WASM bindings, specifically
** only when building with Emscripten's WASMFS support.
**
** This function should only be called if the JS side detects the
** existence of the Origin-Private FileSystem (OPFS) APIs in the
** client. The first time it is called, this function instantiates a
** WASMFS backend impl for OPFS. On success, subsequent calls are
** no-ops.
**
** This function may be passed a "mount point" name, which must have a
** leading "/" and is currently restricted to a single path component,
** e.g. "/foo" is legal but "/foo/" and "/foo/bar" are not. If it is
** NULL or empty, it defaults to "/opfs".
**
** Returns 0 on success, SQLITE_NOMEM if instantiation of the backend
** object fails, SQLITE_IOERR if mkdir() of the zMountPoint dir in
** the virtual FS fails. In builds compiled without SQLITE_ENABLE_WASMFS
** defined, SQLITE_NOTFOUND is returned without side effects.
*/
SQLITE_WASM_KEEP
int sqlite3_wasm_init_wasmfs(const char *zMountPoint){
  static backend_t pOpfs = 0;
  if( !zMountPoint || !*zMountPoint ) zMountPoint = "/opfs";
  if( !pOpfs ){
    pOpfs = wasmfs_create_opfs_backend();
  }
  /** It's not enough to instantiate the backend. We have to create a
      mountpoint in the VFS and attach the backend to it. */
  if( pOpfs && 0!=access(zMountPoint, F_OK) ){
    /* Note that this check and is not robust but it will
       hypothetically suffice for the transient wasm-based virtual
       filesystem we're currently running in. */
    const int rc = wasmfs_create_directory(zMountPoint, 0777, pOpfs);
    /*emscripten_console_logf("OPFS mkdir(%s) rc=%d", zMountPoint, rc);*/
    if(rc) return SQLITE_IOERR;
  }
  return pOpfs ? 0 : SQLITE_NOMEM;
}
#else
SQLITE_WASM_KEEP
int sqlite3_wasm_init_wasmfs(const char *zUnused){
  //emscripten_console_warn("WASMFS OPFS is not compiled in.");
  if(zUnused){/*unused*/}
  return SQLITE_NOTFOUND;
}
#endif /* __EMSCRIPTEN__ && SQLITE_ENABLE_WASMFS */

#if SQLITE_WASM_TESTS

SQLITE_WASM_KEEP
int sqlite3_wasm_test_intptr(int * p){
  return *p = *p * 2;
}

SQLITE_WASM_KEEP
void * sqlite3_wasm_test_voidptr(void * p){
  return p;
}

SQLITE_WASM_KEEP
int64_t sqlite3_wasm_test_int64_max(void){
  return (int64_t)0x7fffffffffffffff;
}

SQLITE_WASM_KEEP
int64_t sqlite3_wasm_test_int64_min(void){
  return ~sqlite3_wasm_test_int64_max();
}

SQLITE_WASM_KEEP
int64_t sqlite3_wasm_test_int64_times2(int64_t x){
  return x * 2;
}

SQLITE_WASM_KEEP
void sqlite3_wasm_test_int64_minmax(int64_t * min, int64_t *max){
  *max = sqlite3_wasm_test_int64_max();
  *min = sqlite3_wasm_test_int64_min();
  /*printf("minmax: min=%lld, max=%lld\n", *min, *max);*/
}

SQLITE_WASM_KEEP
int64_t sqlite3_wasm_test_int64ptr(int64_t * p){
  /*printf("sqlite3_wasm_test_int64ptr( @%lld = 0x%llx )\n", (int64_t)p, *p);*/
  return *p = *p * 2;
}

SQLITE_WASM_KEEP
void sqlite3_wasm_test_stack_overflow(int recurse){
  if(recurse) sqlite3_wasm_test_stack_overflow(recurse);
}

/* For testing the 'string:dealloc' whwasmutil.xWrap() conversion. */
SQLITE_WASM_KEEP
char * sqlite3_wasm_test_str_hello(int fail){
  char * s = fail ? 0 : (char *)sqlite3_malloc(6);
  if(s){
    memcpy(s, "hello", 5);
    s[5] = 0;
  }
  return s;
}
#endif /* SQLITE_WASM_TESTS */

#undef SQLITE_WASM_KEEP

Added ext/wasm/api/sqlite3-worker1-promiser.c-pp.js.








































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
  2022-08-24

  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 a Promise-based proxy for the sqlite3 Worker
  API #1. It is intended to be included either from the main thread or
  a Worker, but only if (A) the environment supports nested Workers
  and (B) it's _not_ a Worker which loads the sqlite3 WASM/JS
  module. This file's features will load that module and provide a
  slightly simpler client-side interface than the slightly-lower-level
  Worker API does.

  This script necessarily exposes one global symbol, but clients may
  freely `delete` that symbol after calling it.
*/
'use strict';
/**
   Configures an sqlite3 Worker API #1 Worker such that it can be
   manipulated via a Promise-based interface and returns a factory
   function which returns Promises for communicating with the worker.
   This proxy has an _almost_ identical interface to the normal
   worker API, with any exceptions documented below.

   It requires a configuration object with the following properties:

   - `worker` (required): a Worker instance which loads
   `sqlite3-worker1.js` or a functional equivalent. Note that the
   promiser factory replaces the worker.onmessage property. This
   config option may alternately be a function, in which case this
   function re-assigns this property with the result of calling that
   function, enabling delayed instantiation of a Worker.

   - `onready` (optional, but...): this callback is called with no
   arguments when the worker fires its initial
   'sqlite3-api'/'worker1-ready' message, which it does when
   sqlite3.initWorker1API() completes its initialization. This is
   the simplest way to tell the worker to kick off work at the
   earliest opportunity.

   - `onunhandled` (optional): a callback which gets passed the
   message event object for any worker.onmessage() events which
   are not handled by this proxy. Ideally that "should" never
   happen, as this proxy aims to handle all known message types.

   - `generateMessageId` (optional): a function which, when passed an
   about-to-be-posted message object, generates a _unique_ message ID
   for the message, which this API then assigns as the messageId
   property of the message. It _must_ generate unique IDs on each call
   so that dispatching can work. If not defined, a default generator
   is used (which should be sufficient for most or all cases).

   - `debug` (optional): a console.debug()-style function for logging
   information about messages.

   This function returns a stateful factory function with the
   following interfaces:

   - Promise function(messageType, messageArgs)
   - Promise function({message object})

   The first form expects the "type" and "args" values for a Worker
   message. The second expects an object in the form {type:...,
   args:...}  plus any other properties the client cares to set. This
   function will always set the `messageId` property on the object,
   even if it's already set, and will set the `dbId` property to the
   current database ID if it is _not_ set in the message object.

   The function throws on error.

   The function installs a temporary message listener, posts a
   message to the configured Worker, and handles the message's
   response via the temporary message listener. The then() callback
   of the returned Promise is passed the `message.data` property from
   the resulting message, i.e. the payload from the worker, stripped
   of the lower-level event state which the onmessage() handler
   receives.

   Example usage:

   ```
   const config = {...};
   const sq3Promiser = sqlite3Worker1Promiser(config);
   sq3Promiser('open', {filename:"/foo.db"}).then(function(msg){
     console.log("open response",msg); // => {type:'open', result: {filename:'/foo.db'}, ...}
   });
   sq3Promiser({type:'close'}).then((msg)=>{
     console.log("close response",msg); // => {type:'close', result: {filename:'/foo.db'}, ...}
   });
   ```

   Differences from Worker API #1:

   - exec's {callback: STRING} option does not work via this
   interface (it triggers an exception), but {callback: function}
   does and works exactly like the STRING form does in the Worker:
   the callback is called one time for each row of the result set,
   passed the same worker message format as the worker API emits:

     {type:typeString,
      row:VALUE,
      rowNumber:1-based-#,
      columnNames: array}

   Where `typeString` is an internally-synthesized message type string
   used temporarily for worker message dispatching. It can be ignored
   by all client code except that which tests this API. The `row`
   property contains the row result in the form implied by the
   `rowMode` option (defaulting to `'array'`). The `rowNumber` is a
   1-based integer value incremented by 1 on each call into th 
   callback.

   At the end of the result set, the same event is fired with
   (row=undefined, rowNumber=null) to indicate that
   the end of the result set has been reached. Note that the rows
   arrive via worker-posted messages, with all the implications
   of that.
*/
self.sqlite3Worker1Promiser = function callee(config = callee.defaultConfig){
  // Inspired by: https://stackoverflow.com/a/52439530
  if(1===arguments.length && 'function'===typeof arguments[0]){
    const f = config;
    config = Object.assign(Object.create(null), callee.defaultConfig);
    config.onready = f;
  }else{
    config = Object.assign(Object.create(null), callee.defaultConfig, config);
  }
  const handlerMap = Object.create(null);
  const noop = function(){};
  const err = config.onerror
        || noop /* config.onerror is intentionally undocumented
                   pending finding a less ambiguous name */;
  const debug = config.debug || noop;
  const idTypeMap = config.generateMessageId ? undefined : Object.create(null);
  const genMsgId = config.generateMessageId || function(msg){
    return msg.type+'#'+(idTypeMap[msg.type] = (idTypeMap[msg.type]||0) + 1);
  };
  const toss = (...args)=>{throw new Error(args.join(' '))};
  if(!config.worker) config.worker = callee.defaultConfig.worker;
  if('function'===typeof config.worker) config.worker = config.worker();
  let dbId;
  config.worker.onmessage = function(ev){
    ev = ev.data;
    debug('worker1.onmessage',ev);
    let msgHandler = handlerMap[ev.messageId];
    if(!msgHandler){
      if(ev && 'sqlite3-api'===ev.type && 'worker1-ready'===ev.result) {
        /*fired one time when the Worker1 API initializes*/
        if(config.onready) config.onready();
        return;
      }
      msgHandler = handlerMap[ev.type] /* check for exec per-row callback */;
      if(msgHandler && msgHandler.onrow){
        msgHandler.onrow(ev);
        return;
      }        
      if(config.onunhandled) config.onunhandled(arguments[0]);
      else err("sqlite3Worker1Promiser() unhandled worker message:",ev);
      return;
    }
    delete handlerMap[ev.messageId];
    switch(ev.type){
        case 'error':
          msgHandler.reject(ev);
          return;
        case 'open':
          if(!dbId) dbId = ev.dbId;
          break;
        case 'close':
          if(ev.dbId===dbId) dbId = undefined;
          break;
        default:
          break;
    }
    try {msgHandler.resolve(ev)}
    catch(e){msgHandler.reject(e)}
  }/*worker.onmessage()*/;
  return function(/*(msgType, msgArgs) || (msgEnvelope)*/){
    let msg;
    if(1===arguments.length){
      msg = arguments[0];
    }else if(2===arguments.length){
      msg = {
        type: arguments[0],
        args: arguments[1]
      };
    }else{
      toss("Invalid arugments for sqlite3Worker1Promiser()-created factory.");
    }
    if(!msg.dbId) msg.dbId = dbId;
    msg.messageId = genMsgId(msg);
    msg.departureTime = performance.now();
    const proxy = Object.create(null);
    proxy.message = msg;
    let rowCallbackId /* message handler ID for exec on-row callback proxy */;
    if('exec'===msg.type && msg.args){
      if('function'===typeof msg.args.callback){
        rowCallbackId = msg.messageId+':row';
        proxy.onrow = msg.args.callback;
        msg.args.callback = rowCallbackId;
        handlerMap[rowCallbackId] = proxy;
      }else if('string' === typeof msg.args.callback){
        toss("exec callback may not be a string when using the Promise interface.");
        /**
           Design note: the reason for this limitation is that this
           API takes over worker.onmessage() and the client has no way
           of adding their own message-type handlers to it. Per-row
           callbacks are implemented as short-lived message.type
           mappings for worker.onmessage().

           We "could" work around this by providing a new
           config.fallbackMessageHandler (or some such) which contains
           a map of event type names to callbacks. Seems like overkill
           for now, seeing as the client can pass callback functions
           to this interface (whereas the string-form "callback" is
           needed for the over-the-Worker interface).
        */
      }
    }
    //debug("requestWork", msg);
    let p = new Promise(function(resolve, reject){
      proxy.resolve = resolve;
      proxy.reject = reject;
      handlerMap[msg.messageId] = proxy;
      debug("Posting",msg.type,"message to Worker dbId="+(dbId||'default')+':',msg);
      config.worker.postMessage(msg);
    });
    if(rowCallbackId) p = p.finally(()=>delete handlerMap[rowCallbackId]);
    return p;
  };
}/*sqlite3Worker1Promiser()*/;
self.sqlite3Worker1Promiser.defaultConfig = {
  worker: function(){
//#if target=es6-bundler-friendly
    return new Worker("sqlite3-worker1.js");
//#else
    let theJs = "sqlite3-worker1.js";
    if(this.currentScript){
      const src = this.currentScript.src.split('/');
      src.pop();
      theJs = src.join('/')+'/' + theJs;
      //console.warn("promiser currentScript, theJs =",this.currentScript,theJs);
    }else{
      //console.warn("promiser self.location =",self.location);
      const urlParams = new URL(self.location.href).searchParams;
      if(urlParams.has('sqlite3.dir')){
        theJs = urlParams.get('sqlite3.dir') + '/' + theJs;
      }
    }
    return new Worker(theJs + self.location.search);
//#endif
  }.bind({
    currentScript: self?.document?.currentScript
  }),
  onerror: (...args)=>console.error('worker1 promiser error',...args)
};

Added ext/wasm/api/sqlite3-worker1.c-pp.js.



















































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
  2022-05-23

  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 is a JS Worker file for the main sqlite3 api. It loads
  sqlite3.js, initializes the module, and postMessage()'s a message
  after the module is initialized:

  {type: 'sqlite3-api', result: 'worker1-ready'}

  This seemingly superfluous level of indirection is necessary when
  loading sqlite3.js via a Worker. Instantiating a worker with new
  Worker("sqlite.js") will not (cannot) call sqlite3InitModule() to
  initialize the module due to a timing/order-of-operations conflict
  (and that symbol is not exported in a way that a Worker loading it
  that way can see it).  Thus JS code wanting to load the sqlite3
  Worker-specific API needs to pass _this_ file (or equivalent) to the
  Worker constructor and then listen for an event in the form shown
  above in order to know when the module has completed initialization.

  This file accepts a URL arguments to adjust how it loads sqlite3.js:

  - `sqlite3.dir`, if set, treats the given directory name as the
    directory from which `sqlite3.js` will be loaded.
*/
"use strict";
(()=>{
//#if target=es6-bundler-friendly
  importScripts('sqlite3.js');
//#else
  const urlParams = new URL(self.location.href).searchParams;
  let theJs = 'sqlite3.js';
  if(urlParams.has('sqlite3.dir')){
    theJs = urlParams.get('sqlite3.dir') + '/' + theJs;
  }
  //console.warn("worker1 theJs =",theJs);
  importScripts(theJs);
//#endif
  sqlite3InitModule().then((sqlite3)=>{
    sqlite3.initWorker1API();
  });
})();

Added ext/wasm/batch-runner.html.



























































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<!doctype html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
    <link rel="stylesheet" href="common/emscripten.css"/>
    <link rel="stylesheet" href="common/testing.css"/>
    <title>sqlite3-api batch SQL runner</title>
  </head>
  <body>
    <header id='titlebar'><span>sqlite3-api batch SQL runner</span></header>
    <!-- emscripten bits -->
    <figure id="module-spinner">
      <div class="spinner"></div>
      <div class='center'><strong>Initializing app...</strong></div>
      <div class='center'>
        On a slow internet connection this may take a moment.  If this
        message displays for "a long time", intialization may have
        failed and the JavaScript console may contain clues as to why.
      </div>
    </figure>
    <div class="emscripten" id="module-status">Downloading...</div>
    <div class="emscripten">
      <progress value="0" max="100" id="module-progress" hidden='1'></progress>  
    </div><!-- /emscripten bits -->
    <p>
      This page is for batch-running extracts from the output
      of <tt>speedtest1 --script</tt>, as well as other standalone SQL
      scripts.
    </p>
    <p id='warn-list' class='warning'>ACHTUNG: this file requires a generated input list
      file. Run "make batch" from this directory to generate it.
    </p>
    <p id='warn-opfs' class='warning hidden'>WARNING: if the WASMFS/OPFS layer crashes, this page may
      become completely unresponsive and need to be closed and reloaded to recover.
    </p>
    <p id='warn-websql' class='warning hidden'>WARNING: WebSQL's limited API requires that
      this app split up SQL batches into separate statements for execution. That will
      only work so long as semicolon characters are <em>only</em> used to terminate
      SQL statements, and not used within string literals or the like.
    </p>
    <hr>
    <fieldset id='toolbar'>
      <div>
        <select class='disable-during-eval' id='sql-select'>
          <option disabled selected>Populated via script code</option>
        </select>
        <button class='disable-during-eval' id='sql-run'>Run selected SQL</button>
        <button class='disable-during-eval' id='sql-run-next'>Run next...</button>
        <button class='disable-during-eval' id='sql-run-remaining'>Run all remaining...</button>
        <button class='disable-during-eval' id='export-metrics' disabled>Export metrics (WIP)<br>(broken by refactoring)</button>
        <button class='disable-during-eval' id='db-reset'>Reset db</button>
        <button id='output-clear'>Clear output</button>
        <span class='input-wrapper flex-col'>
          <label for='select-impl'>Storage impl:</label>
          <select id='select-impl'>
            <option value='virtualfs'>Virtual filesystem</option>
            <option value='memdb'>:memory:</option>
            <option value='wasmfs-opfs'>WASMFS OPFS</option>
            <option value='websql'>WebSQL</option>
          </select>
        </span>
      </fieldset>
    </div>
    <hr>
      <span class='input-wrapper'>
        <input type='checkbox' class='disable-during-eval' id='cb-reverse-log-order' checked></input>
        <label for='cb-reverse-log-order'>Reverse log order (newest first)</label>
      </span>
    <div id='test-output'></div>
    <script src="jswasm/sqlite3.js"></script>
    <script src="common/SqliteTestUtil.js"></script>
    <script src="batch-runner.js"></script>
    <style>
      .flex-col {
          display: flex;
          flex-direction: column;
      }
      #toolbar > div {
          display: flex;
          flex-direction: row;
          flex-wrap: wrap;
      }
      #toolbar > div > * {
          margin: 0.25em;
      }
    </style>
  </body>
</html>

Added ext/wasm/batch-runner.js.













































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
  2022-08-29

  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.

  ***********************************************************************

  A basic batch SQL runner for sqlite3-api.js. This file must be run in
  main JS thread and sqlite3.js must have been loaded before it.
*/
'use strict';
(function(){
  const toss = function(...args){throw new Error(args.join(' '))};
  const warn = console.warn.bind(console);
  let sqlite3;
  const urlParams = new URL(self.location.href).searchParams;
  const cacheSize = (()=>{
    if(urlParams.has('cachesize')) return +urlParams.get('cachesize');
    return 200;
  })();

  /** Throws if the given sqlite3 result code is not 0. */
  const checkSqliteRc = (dbh,rc)=>{
    if(rc) toss("Prepare failed:",sqlite3.capi.sqlite3_errmsg(dbh));
  };

  const sqlToDrop = [
    "SELECT type,name FROM sqlite_schema ",
    "WHERE name NOT LIKE 'sqlite\\_%' escape '\\' ",
    "AND name NOT LIKE '\\_%' escape '\\'"
  ].join('');
  
  const clearDbWebSQL = function(db){
    db.handle.transaction(function(tx){
      const onErr = (e)=>console.error(e);
      const callback = function(tx, result){
        const rows = result.rows;
        let i, n;
        i = n = rows.length;
        while(i--){
          const row = rows.item(i);
          const name = JSON.stringify(row.name);
          const type = row.type;
          switch(type){
              case 'index': case 'table':
              case 'trigger': case 'view': {
                const sql2 = 'DROP '+type+' '+name;
                tx.executeSql(sql2, [], ()=>{}, onErr);
                break;
              }
              default:
                warn("Unhandled db entry type:",type,'name =',name);
                break;
          }
        }
      };
      tx.executeSql(sqlToDrop, [], callback, onErr);
      db.handle.changeVersion(db.handle.version, "", ()=>{}, onErr, ()=>{});
    });
  };

  const clearDbSqlite = function(db){
    // This would be SO much easier with the oo1 API, but we specifically want to
    // inject metrics we can't get via that API, and we cannot reliably (OPFS)
    // open the same DB twice to clear it using that API, so...
    const rc = sqlite3.wasm.exports.sqlite3_wasm_db_reset(db.handle);
    App.logHtml("reset db rc =",rc,db.id, db.filename);
  };

  
  const E = (s)=>document.querySelector(s);
  const App = {
    e: {
      output: E('#test-output'),
      selSql: E('#sql-select'),
      btnRun: E('#sql-run'),
      btnRunNext: E('#sql-run-next'),
      btnRunRemaining: E('#sql-run-remaining'),
      btnExportMetrics: E('#export-metrics'),
      btnClear: E('#output-clear'),
      btnReset: E('#db-reset'),
      cbReverseLog: E('#cb-reverse-log-order'),
      selImpl: E('#select-impl'),
      fsToolbar: E('#toolbar')
    },
    db: Object.create(null),
    dbs: Object.create(null),
    cache:{},
    log: console.log.bind(console),
    warn: console.warn.bind(console),
    cls: function(){this.e.output.innerHTML = ''},
    logHtml2: function(cssClass,...args){
      const ln = document.createElement('div');
      if(cssClass) ln.classList.add(cssClass);
      ln.append(document.createTextNode(args.join(' ')));
      this.e.output.append(ln);
      //this.e.output.lastElementChild.scrollIntoViewIfNeeded();
    },
    logHtml: function(...args){
      console.log(...args);
      if(1) this.logHtml2('', ...args);
    },
    logErr: function(...args){
      console.error(...args);
      if(1) this.logHtml2('error', ...args);
    },

    execSql: async function(name,sql){
      const db = this.getSelectedDb();
      const banner = "========================================";
      this.logHtml(banner,
                   "Running",name,'('+sql.length,'bytes) using',db.id);
      const capi = this.sqlite3.capi, wasm = this.sqlite3.wasm;
      let pStmt = 0, pSqlBegin;
      const stack = wasm.scopedAllocPush();
      const metrics = db.metrics = Object.create(null);
      metrics.prepTotal = metrics.stepTotal = 0;
      metrics.stmtCount = 0;
      metrics.malloc = 0;
      metrics.strcpy = 0;
      this.blockControls(true);
      if(this.gotErr){
        this.logErr("Cannot run SQL: error cleanup is pending.");
        return;
      }
      // Run this async so that the UI can be updated for the above header...
      const endRun = ()=>{
        metrics.evalSqlEnd = performance.now();
        metrics.evalTimeTotal = (metrics.evalSqlEnd - metrics.evalSqlStart);
        this.logHtml(db.id,"metrics:",JSON.stringify(metrics, undefined, ' '));
        this.logHtml("prepare() count:",metrics.stmtCount);
        this.logHtml("Time in prepare_v2():",metrics.prepTotal,"ms",
                     "("+(metrics.prepTotal / metrics.stmtCount),"ms per prepare())");
        this.logHtml("Time in step():",metrics.stepTotal,"ms",
                     "("+(metrics.stepTotal / metrics.stmtCount),"ms per step())");
        this.logHtml("Total runtime:",metrics.evalTimeTotal,"ms");
        this.logHtml("Overhead (time - prep - step):",
                     (metrics.evalTimeTotal - metrics.prepTotal - metrics.stepTotal)+"ms");
        this.logHtml(banner,"End of",name);
      };

      let runner;
      if('websql'===db.id){
        const who = this;
        runner = function(resolve, reject){
          /* WebSQL cannot execute multiple statements, nor can it execute SQL without
             an explicit transaction. Thus we have to do some fragile surgery on the
             input SQL. Since we're only expecting carefully curated inputs, the hope is
             that this will suffice. PS: it also can't run most SQL functions, e.g. even
             instr() results in "not authorized". */
          if('string'!==typeof sql){ // assume TypedArray
            sql = new TextDecoder().decode(sql);
          }
          sql = sql.replace(/-- [^\n]+\n/g,''); // comment lines interfere with our split()
          const sqls = sql.split(/;+\n/);
          const rxBegin = /^BEGIN/i, rxCommit = /^COMMIT/i;
          try {
            const nextSql = ()=>{
              let x = sqls.shift();
              while(sqls.length && !x) x = sqls.shift();
              return x && x.trim();
            };
            const who = this;
            const transaction = function(tx){
              try {
                let s;
                /* Try to approximate the spirit of the input scripts
                   by running batches bound by BEGIN/COMMIT statements. */
                for(s = nextSql(); !!s; s = nextSql()){
                  if(rxBegin.test(s)) continue;
                  else if(rxCommit.test(s)) break;
                  //console.log("websql sql again",sqls.length, s);
                  ++metrics.stmtCount;
                  const t = performance.now();
                  tx.executeSql(s,[], ()=>{}, (t,e)=>{
                    console.error("WebSQL error",e,"SQL =",s);
                    who.logErr(e.message);
                    //throw e;
                    return false;
                  });
                  metrics.stepTotal += performance.now() - t;
                }
              }catch(e){
                who.logErr("transaction():",e.message);
                throw e;
              }
            };
            const n = sqls.length;
            const nextBatch = function(){
              if(sqls.length){
                console.log("websql sqls.length",sqls.length,'of',n);
                db.handle.transaction(transaction, (e)=>{
                  who.logErr("Ignoring and contiuing:",e.message)
                  //reject(e);
                  return false;
                }, nextBatch);
              }else{
                resolve(who);
              }
            };
            metrics.evalSqlStart = performance.now();
            nextBatch();
          }catch(e){
            //this.gotErr = e;
            console.error("websql error:",e);
            who.logErr(e.message);
            //reject(e);
          }
        }.bind(this);
      }else{/*sqlite3 db...*/
        runner = function(resolve, reject){
          metrics.evalSqlStart = performance.now();
          try {
            let t;
            let sqlByteLen = sql.byteLength;
            const [ppStmt, pzTail] = wasm.scopedAllocPtr(2);
            t = performance.now();
            pSqlBegin = wasm.scopedAlloc( sqlByteLen + 1/*SQL + NUL*/) || toss("alloc(",sqlByteLen,") failed");
            metrics.malloc = performance.now() - t;
            metrics.byteLength = sqlByteLen;
            let pSql = pSqlBegin;
            const pSqlEnd = pSqlBegin + sqlByteLen;
            t = performance.now();
            wasm.heap8().set(sql, pSql);
            wasm.poke(pSql + sqlByteLen, 0);
            metrics.strcpy = performance.now() - t;
            let breaker = 0;
            while(pSql && wasm.peek(pSql,'i8')){
              wasm.pokePtr(ppStmt, 0);
              wasm.pokePtr(pzTail, 0);
              t = performance.now();
              let rc = capi.sqlite3_prepare_v3(
                db.handle, pSql, sqlByteLen, 0, ppStmt, pzTail
              );
              metrics.prepTotal += performance.now() - t;
              checkSqliteRc(db.handle, rc);
              pStmt = wasm.peekPtr(ppStmt);
              pSql = wasm.peekPtr(pzTail);
              sqlByteLen = pSqlEnd - pSql;
              if(!pStmt) continue/*empty statement*/;
              ++metrics.stmtCount;
              t = performance.now();
              rc = capi.sqlite3_step(pStmt);
              capi.sqlite3_finalize(pStmt);
              pStmt = 0;
              metrics.stepTotal += performance.now() - t;
              switch(rc){
                  case capi.SQLITE_ROW:
                  case capi.SQLITE_DONE: break;
                  default: checkSqliteRc(db.handle, rc); toss("Not reached.");
              }
            }
            resolve(this);
          }catch(e){
            if(pStmt) capi.sqlite3_finalize(pStmt);
            //this.gotErr = e;
            reject(e);
          }finally{
            capi.sqlite3_exec(db.handle,"rollback;",0,0,0);
            wasm.scopedAllocPop(stack);
          }
        }.bind(this);
      }
      let p;
      if(1){
        p = new Promise(function(res,rej){
          setTimeout(()=>runner(res, rej), 50)/*give UI a chance to output the "running" banner*/;
        });
      }else{
        p = new Promise(runner);
      }
      return p.catch(
        (e)=>this.logErr("Error via execSql("+name+",...):",e.message)
      ).finally(()=>{
        endRun();
        this.blockControls(false);
      });
    },
    
    clearDb: function(){
      const db = this.getSelectedDb();
      if('websql'===db.id){
        this.logErr("TODO: clear websql db.");
        return;
      }
      if(!db.handle) return;
      const capi = this.sqlite3, wasm = this.sqlite3.wasm;
      //const scope = wasm.scopedAllocPush(
      this.logErr("TODO: clear db");
    },
    
    /**
       Loads batch-runner.list and populates the selection list from
       it. Returns a promise which resolves to nothing in particular
       when it completes. Only intended to be run once at the start
       of the app.
     */
    loadSqlList: async function(){
      const sel = this.e.selSql;
      sel.innerHTML = '';
      this.blockControls(true);
      const infile = 'batch-runner.list';
      this.logHtml("Loading list of SQL files:", infile);
      let txt;
      try{
        const r = await fetch(infile);
        if(404 === r.status){
          toss("Missing file '"+infile+"'.");
        }
        if(!r.ok) toss("Loading",infile,"failed:",r.statusText);
        txt = await r.text();
        const warning = E('#warn-list');
        if(warning) warning.remove();
      }catch(e){
        this.logErr(e.message);
        throw e;
      }finally{
        this.blockControls(false);
      }
      const list = txt.split(/\n+/);
      let opt;
      if(0){
        opt = document.createElement('option');
        opt.innerText = "Select file to evaluate...";
        opt.value = '';
        opt.disabled = true;
        opt.selected = true;
        sel.appendChild(opt);
      }
      list.forEach(function(fn){
        if(!fn) return;
        opt = document.createElement('option');
        opt.value = fn;
        opt.innerText = fn.split('/').pop();
        sel.appendChild(opt);
      });
      this.logHtml("Loaded",infile);
    },

    /** Fetch ./fn and return its contents as a Uint8Array. */
    fetchFile: async function(fn, cacheIt=false){
      if(cacheIt && this.cache[fn]) return this.cache[fn];
      this.logHtml("Fetching",fn,"...");
      let sql;
      try {
        const r = await fetch(fn);
        if(!r.ok) toss("Fetch failed:",r.statusText);
        sql = new Uint8Array(await r.arrayBuffer());
      }catch(e){
        this.logErr(e.message);
        throw e;
      }
      this.logHtml("Fetched",sql.length,"bytes from",fn);
      if(cacheIt) this.cache[fn] = sql;
      return sql;
    }/*fetchFile()*/,

    /** Disable or enable certain UI controls. */
    blockControls: function(disable){
      //document.querySelectorAll('.disable-during-eval').forEach((e)=>e.disabled = disable);
      this.e.fsToolbar.disabled = disable;
    },

    /**
       Converts this.metrics() to a form which is suitable for easy conversion to
       CSV. It returns an array of arrays. The first sub-array is the column names.
       The 2nd and subsequent are the values, one per test file (only the most recent
       metrics are kept for any given file).
    */
    metricsToArrays: function(){
      const rc = [];
      Object.keys(this.dbs).sort().forEach((k)=>{
        const d = this.dbs[k];
        const m = d.metrics;
        delete m.evalSqlStart;
        delete m.evalSqlEnd;
        const mk = Object.keys(m).sort();
        if(!rc.length){
          rc.push(['db', ...mk]);
        }
        const row = [k.split('/').pop()/*remove dir prefix from filename*/];
        rc.push(row);
        row.push(...mk.map((kk)=>m[kk]));
      });
      return rc;
    },

    metricsToBlob: function(colSeparator='\t'){
      const ar = [], ma = this.metricsToArrays();
      if(!ma.length){
        this.logErr("Metrics are empty. Run something.");
        return;
      }
      ma.forEach(function(row){
        ar.push(row.join(colSeparator),'\n');
      });
      return new Blob(ar);
    },
    
    downloadMetrics: function(){
      const b = this.metricsToBlob();
      if(!b) return;
      const url = URL.createObjectURL(b);
      const a = document.createElement('a');
      a.href = url;
      a.download = 'batch-runner-js-'+((new Date().getTime()/1000) | 0)+'.csv';
      this.logHtml("Triggering download of",a.download);
      document.body.appendChild(a);
      a.click();
      setTimeout(()=>{
        document.body.removeChild(a);
        URL.revokeObjectURL(url);
      }, 500);
    },

    /**
       Fetch file fn and eval it as an SQL blob. This is an async
       operation and returns a Promise which resolves to this
       object on success.
    */
    evalFile: async function(fn){
      const sql = await this.fetchFile(fn);
      return this.execSql(fn,sql);
    }/*evalFile()*/,

    /**
       Clears all DB tables in all _opened_ databases. Because of
       disparities between backends, we cannot simply "unlink" the
       databases to clean them up.
    */
    clearStorage: function(onlySelectedDb=false){
      const list = onlySelectedDb
            ? [('boolean'===typeof onlySelectedDb)
                ? this.dbs[this.e.selImpl.value]
                : onlySelectedDb]
            : Object.values(this.dbs);
      for(let db of list){
        if(db && db.handle){
          this.logHtml("Clearing db",db.id);
          db.clear();
        }
      }
    },

    /**
       Fetches the handle of the db associated with
       this.e.selImpl.value, opening it if needed.
    */
    getSelectedDb: function(){
      if(!this.dbs.memdb){
        for(let opt of this.e.selImpl.options){
          const d = this.dbs[opt.value] = Object.create(null);
          d.id = opt.value;
          switch(d.id){
              case 'virtualfs':
                d.filename = 'file:/virtualfs.sqlite3?vfs=unix-none';
                break;
              case 'memdb':
                d.filename = ':memory:';
                break;
              case 'wasmfs-opfs':
                d.filename = 'file:'+(
                  this.sqlite3.capi.sqlite3_wasmfs_opfs_dir()
                )+'/wasmfs-opfs.sqlite3b';
                break;
              case 'websql':
                d.filename = 'websql.db';
                break;
              default:
                this.logErr("Unhandled db selection option (see details in the console).",opt);
                toss("Unhandled db init option");
          }
        }
      }/*first-time init*/
      const dbId = this.e.selImpl.value;
      const d = this.dbs[dbId];
      if(d.handle) return d;
      if('websql' === dbId){
        d.handle = self.openDatabase('batch-runner', '0.1', 'foo', 1024 * 1024 * 50);
        d.clear = ()=>clearDbWebSQL(d);
        d.handle.transaction(function(tx){
          tx.executeSql("PRAGMA cache_size="+cacheSize);
          App.logHtml(dbId,"cache_size =",cacheSize);
        });
      }else{
        const capi = this.sqlite3.capi, wasm = this.sqlite3.wasm;
        const stack = wasm.scopedAllocPush();
        let pDb = 0;
        try{
          const oFlags = capi.SQLITE_OPEN_CREATE | capi.SQLITE_OPEN_READWRITE;
          const ppDb = wasm.scopedAllocPtr();
          const rc = capi.sqlite3_open_v2(d.filename, ppDb, oFlags, null);
          pDb = wasm.peekPtr(ppDb)
          if(rc) toss("sqlite3_open_v2() failed with code",rc);
          capi.sqlite3_exec(pDb, "PRAGMA cache_size="+cacheSize, 0, 0, 0);
          this.logHtml(dbId,"cache_size =",cacheSize);
        }catch(e){
          if(pDb) capi.sqlite3_close_v2(pDb);
        }finally{
          wasm.scopedAllocPop(stack);
        }
        d.handle = pDb;
        d.clear = ()=>clearDbSqlite(d);
      }
      d.clear();
      this.logHtml("Opened db:",dbId,d.filename);
      console.log("db =",d);
      return d;
    },

    run: function(sqlite3){
      delete this.run;
      this.sqlite3 = sqlite3;
      const capi = sqlite3.capi, wasm = sqlite3.wasm;
      this.logHtml("Loaded module:",capi.sqlite3_libversion(), capi.sqlite3_sourceid());
      this.logHtml("WASM heap size =",wasm.heap8().length);
      this.loadSqlList();
      if(capi.sqlite3_wasmfs_opfs_dir()){
        E('#warn-opfs').classList.remove('hidden');
      }else{
        E('#warn-opfs').remove();
        E('option[value=wasmfs-opfs]').disabled = true;
      }
      if('function' === typeof self.openDatabase){
        E('#warn-websql').classList.remove('hidden');
      }else{
        E('option[value=websql]').disabled = true;
        E('#warn-websql').remove();
      }
      const who = this;
      if(this.e.cbReverseLog.checked){
        this.e.output.classList.add('reverse');
      }
      this.e.cbReverseLog.addEventListener('change', function(){
        who.e.output.classList[this.checked ? 'add' : 'remove']('reverse');
      }, false);
      this.e.btnClear.addEventListener('click', ()=>this.cls(), false);
      this.e.btnRun.addEventListener('click', function(){
        if(!who.e.selSql.value) return;
        who.evalFile(who.e.selSql.value);
      }, false);
      this.e.btnRunNext.addEventListener('click', function(){
        ++who.e.selSql.selectedIndex;
        if(!who.e.selSql.value) return;
        who.evalFile(who.e.selSql.value);
      }, false);
      this.e.btnReset.addEventListener('click', function(){
        who.clearStorage(true);
      }, false);
      this.e.btnExportMetrics.addEventListener('click', function(){
        who.logHtml2('warning',"Triggering download of metrics CSV. Check your downloads folder.");
        who.downloadMetrics();
        //const m = who.metricsToArrays();
        //console.log("Metrics:",who.metrics, m);
      });
      this.e.selImpl.addEventListener('change', function(){
        who.getSelectedDb();
      });
      this.e.btnRunRemaining.addEventListener('click', async function(){
        let v = who.e.selSql.value;
        const timeStart = performance.now();
        while(v){
          await who.evalFile(v);
          if(who.gotError){
            who.logErr("Error handling script",v,":",who.gotError.message);
            break;
          }
          ++who.e.selSql.selectedIndex;
          v = who.e.selSql.value;
        }
        const timeTotal = performance.now() - timeStart;
        who.logHtml("Run-remaining time:",timeTotal,"ms ("+(timeTotal/1000/60)+" minute(s))");
        who.clearStorage();
      }, false);
    }/*run()*/
  }/*App*/;

  self.sqlite3TestModule.initSqlite3().then(function(sqlite3_){
    sqlite3 = sqlite3_;
    self.App = App /* only to facilitate dev console access */;
    App.run(sqlite3);
  });
})();

Added ext/wasm/c-pp.c.



























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2022-11-12:
**
** In place of a legal notice, here is a blessing:
**
**  * May you do good and not evil.
**  * May you find forgiveness for yourself and forgive others.
**  * May you share freely, never taking more than you give.
**
************************************************************************
**
** The C-minus Preprocessor: a truly minimal C-like preprocessor.
** Why? Because C preprocessors _can_ process non-C code but generally make
** quite a mess of it. The purpose of this application is an extremely
** minimal preprocessor with only the most basic functionality of a C
** preprocessor, namely:
**
** - Limited `#if`, where its one argument is a macro name which
**   resolves to true if it's defined, false if it's not. Likewise,
**   `#ifnot` is the inverse. Includes `#else` and `#elif` and
**   `#elifnot`. Such chains are terminated with `#endif`.
**
** - `#define` accepts one or more arguments, the names of
**   macros. Each one is implicitly true.
**
** - `#undef` undefine one or more macros.
**
** - `#error` treats the rest of the line as a fatal error message.
**
** - `#include` treats its argument as a filename token (NOT quoted,
**   though support for quoting may be added later). Some effort is
**   made to prevent recursive inclusion, but that support is both
**   somewhat fragile and possibly completely unnecessary.
**
** - `#pragma` is in place for adding "meta-commands", but it does not
**   yet have any concrete list of documented commands.
**
*  - `#stderr` outputs its file name, line number, and the remaininder
**   of that line to stderr.
**
** - `#//` acts as a single-line comment, noting that there must be as
**   space after the `//` part because `//` is (despite appearances)
**   parsed like a keyword.
**
** Note that "#" above is symbolic. The keyword delimiter is
** configurable and defaults to "##". Define CMPP_DEFAULT_DELIM to a
** string when compiling to define the default at build-time.
**
** This preprocessor does no expansion of content except within the
** bounds of its `#keywords`.
**
** Design note: this code makes use of sqlite3. Though not _strictly_
** needed in order to implement it, this tool was specifically created
** for use with the sqlite3 project's own JavaScript code, so there's
** no reason not to make use of it to do some of the heavy lifting. It
** does not require any cutting-edge sqlite3 features and should be
** usable with any version which supports `WITHOUT ROWID`.
**
** Author(s):
**
** - Stephan Beal <https://wanderinghorse.net/home/stephan/>
*/

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "sqlite3.h"

#if defined(_WIN32) || defined(WIN32)
#  include <io.h>
#  include <fcntl.h>
#  ifndef access
#    define access(f,m) _access((f),(m))
#  endif
#else
#  include <unistd.h>
#endif

#ifndef CMPP_DEFAULT_DELIM
#define CMPP_DEFAULT_DELIM "##"
#endif

#if 1
#  define CMPP_NORETURN __attribute__((noreturn))
#else
#  define CMPP_NORETURN
#endif

/* Fatally exits the app with the given printf-style message. */
static CMPP_NORETURN void fatalv(char const *zFmt, va_list);
static CMPP_NORETURN void fatal(char const *zFmt, ...);

/** Proxy for free(), for symmetry with cmpp_realloc(). */
static void cmpp_free(void *p);
/** A realloc() proxy which dies fatally on allocation error. */
static void * cmpp_realloc(void * p, unsigned n);
#if 0
/** A malloc() proxy which dies fatally on allocation error. */
static void * cmpp_malloc(unsigned n);
#endif

/*
** If p is stdin or stderr then this is a no-op, else it is a
** proxy for fclose(). This is a no-op if p is NULL.
*/
static void FILE_close(FILE *p);
/*
** Works like fopen() but accepts the special name "-" to mean either
** stdin (if zMode indicates a real-only mode) or stdout. Fails
** fatally on error.
*/
static FILE * FILE_open(char const *zName, const char * zMode);
/*
** Reads the entire contents of the given file, allocating it in a
** buffer which gets assigned to `*pOut`. `*nOut` gets assigned the
** length of the output buffer. Fails fatally on error.
*/
static void FILE_slurp(FILE *pFile, unsigned char **pOut,
                       unsigned * nOut);

/*
** Intended to be passed an sqlite3 result code. If it's non-0
** then it emits a fatal error message which contains both the
** given string and the sqlite3_errmsg() from the application's
** database instance.
*/
static void db_affirm_rc(int rc, const char * zMsg);

/*
** Proxy for sqlite3_str_finish() which fails fatally if that
** routine returns NULL.
*/
static char * db_str_finish(sqlite3_str *s, int * n);
/*
** Proxy for sqlite3_str_new() which fails fatally if that
** routine returns NULL.
*/
static sqlite3_str * db_str_new(void);

/* Proxy for sqlite3_finalize(). */
static void db_finalize(sqlite3_stmt *pStmt);
/*
** Proxy for sqlite3_step() which fails fatally if the result
** is anything other than SQLITE_ROW or SQLITE_DONE.
*/
static int db_step(sqlite3_stmt *pStmt);
/*
** Proxy for sqlite3_bind_int() which fails fatally on error.
*/
static void db_bind_int(sqlite3_stmt *pStmt, int col, int val);
#if 0
/*
** Proxy for sqlite3_bind_null() which fails fatally on error.
*/
static void db_bind_null(sqlite3_stmt *pStmt, int col);
#endif
/*
** Proxy for sqlite3_bind_text() which fails fatally on error.
*/
static void db_bind_text(sqlite3_stmt *pStmt, int col, const char * zStr);
/*
** Proxy for sqlite3_bind_text() which fails fatally on error.
*/
static void db_bind_textn(sqlite3_stmt *pStmt, int col, const char * zStr, int len);
#if 0
/*
** Proxy for sqlite3_bind_text() which fails fatally on error. It uses
** sqlite3_str_vappendf() so supports all of its formatting options.
*/
static void db_bind_textv(sqlite3_stmt *pStmt, int col, const char * zFmt, ...);
#endif
/*
** Proxy for sqlite3_free(), to be passed any memory which is allocated
** by sqlite3_malloc().
*/
static void db_free(void *m);
/*
** Adds the given `#define` macro name to the list of macros, ignoring
** any duplicates. Fails fatally on error.
*/
static void db_define_add(const char * zKey);
/*
** Returns true if the given key is already in the `#define` list,
** else false. Fails fatally on db error.
*/
static int db_define_has(const char * zName);
/*
** Removes the given `#define` macro name from the list of
** macros. Fails fatally on error.
*/
static void db_define_rm(const char * zKey);
/*
** Adds the given filename to the list of being-`#include`d files,
** using the given source file name and line number of error reporting
** purposes. If recursion is later detected.
*/
static void db_including_add(const char * zKey, const char * zSrc, int srcLine);
/*
** Adds the given dir to the list of includes. They are checked in the
** order they are added.
*/
static void db_include_dir_add(const char * zKey);
/*
** Returns a resolved path of PREFIX+'/'+zKey, where PREFIX is one of
** the `#include` dirs (db_include_dir_add()). If no file match is
** found, NULL is returned. Memory must eventually be passed to
** db_free() to free it.
*/
static char * db_include_search(const char * zKey);
/*
** Removes the given key from the `#include` list.
*/
static void db_include_rm(const char * zKey);
/*
** A proxy for sqlite3_prepare() which fails fatally on error.
*/
static void db_prepare(sqlite3_stmt **pStmt, const char * zSql, ...);

/*
** Opens the given file and processes its contents as c-pp, sending
** all output to the global c-pp output channel. Fails fatally on
** error.
*/
static void cmpp_process_file(const char * zName);

/*
** Returns the number newline characters between the given starting
** point and inclusive ending point. Results are undefined if zFrom is
** greater than zTo.
*/
static unsigned count_lines(unsigned char const * zFrom,
                            unsigned char const *zTo);

/*
** Wrapper around a FILE handle.
*/
struct FileWrapper {
  /* File's name. */
  char const *zName;
  /* FILE handle. */
  FILE * pFile;
  /* Where FileWrapper_slurp() stores the file's contents. */
  unsigned char * zContent;
  /* Size of this->zContent, as set by FileWrapper_slurp(). */
  unsigned nContent;
};
typedef struct FileWrapper FileWrapper;
#define FileWrapper_empty_m {0,0,0,0}
static const FileWrapper FileWrapper_empty = FileWrapper_empty_m;

/* Proxy for FILE_close(). */
static void FileWrapper_close(FileWrapper * p);
/* Proxy for FILE_open(). */
static void FileWrapper_open(FileWrapper * p, const char * zName, const char *zMode);
/* Proxy for FILE_slurp(). */
static void FileWrapper_slurp(FileWrapper * p);

/*
** Outputs a printf()-formatted message to stderr.
*/
static void g_stderr(char const *zFmt, ...);
/*
** Outputs a printf()-formatted message to stderr.
*/
static void g_stderrv(char const *zFmt, va_list);
#define g_debug(lvl,pfexpr)                                          \
  if(lvl<=g.doDebug) g_stderr("%s @ %s:%d: ",g.zArgv0,__FILE__,__LINE__); \
  if(lvl<=g.doDebug) g_stderr pfexpr

void fatalv(char const *zFmt, va_list va){
  if(zFmt && *zFmt){
    vfprintf(stderr, zFmt, va);
  }
  fputc('\n', stderr);
  exit(1);
}

void fatal(char const *zFmt, ...){
  va_list va;
  va_start(va, zFmt);
  fatalv(zFmt, va);
  va_end(va);
}

void cmpp_free(void *p){
  free(p);
}

void * cmpp_realloc(void * p, unsigned n){
  void * const rc = realloc(p, n);
  if(!rc) fatal("realloc(P,%u) failed", n);
  return rc;
}

#if 0
void * cmpp_malloc(unsigned n){
  void * const rc = malloc(n);
  if(!rc) fatal("malloc(%u) failed", n);
  return rc;
}
#endif

FILE * FILE_open(char const *zName, const char * zMode){
  FILE * p;
  if('-'==zName[0] && 0==zName[1]){
    p = strstr(zMode,"w") ? stdout : stdin;
  }else{
    p = fopen(zName, zMode);
    if(!p) fatal("Cannot open file [%s] with mode [%s]", zName, zMode);
  }
  return p;
}

void FILE_close(FILE *p){
  if(p && p!=stdout && p!=stderr){
    fclose(p);
  }
}

void FILE_slurp(FILE *pFile, unsigned char **pOut,
                unsigned * nOut){
  unsigned char zBuf[1024 * 8];
  unsigned char * pDest = 0;
  unsigned nAlloc = 0;
  unsigned nOff = 0;
  /* Note that this needs to be able to work on non-seekable streams,
  ** thus we read in chunks instead of doing a single alloc and
  ** filling it in one go. */
  while( !feof(pFile) ){
    size_t const n = fread(zBuf, 1, sizeof(zBuf), pFile);
    if(n>0){
      if(nAlloc < nOff + n + 1){
        nAlloc = nOff + n + 1;
        pDest = cmpp_realloc(pDest, nAlloc);
      }
      memcpy(pDest + nOff, zBuf, n);
      nOff += n;
    }
  }
  if(pDest) pDest[nOff] = 0;
  *pOut = pDest;
  *nOut = nOff;
}

void FileWrapper_close(FileWrapper * p){
  if(p->pFile) FILE_close(p->pFile);
  if(p->zContent) cmpp_free(p->zContent);
  *p = FileWrapper_empty;
}

void FileWrapper_open(FileWrapper * p, const char * zName,
                      const char * zMode){
  FileWrapper_close(p);
  p->pFile = FILE_open(zName, zMode);
  p->zName = zName;
}

void FileWrapper_slurp(FileWrapper * p){
  assert(!p->zContent);
  assert(p->pFile);
  FILE_slurp(p->pFile, &p->zContent, &p->nContent);
}

unsigned count_lines(unsigned char const * zFrom, unsigned char const *zTo){
  unsigned ln = 0;
  unsigned char const *zPos = zFrom;
  assert(zFrom && zTo);
  assert(zFrom <= zTo);
  for(; zPos < zTo; ++zPos){
    switch(*zPos){
      case (unsigned)'\n': ++ln; break;
      default: break;
    }
  }
  return ln;
}

enum CmppParseState {
TS_Start = 1,
TS_If,
TS_IfPassed,
TS_Else,
TS_Error
};
typedef enum CmppParseState CmppParseState;
enum CmppTokenType {
TT_Invalid = 0,
TT_Comment,
TT_Define,
TT_Elif,
TT_ElifNot,
TT_Else,
TT_EndIf,
TT_Error,
TT_If,
TT_IfNot,
TT_Include,
TT_Line,
TT_Pragma,
TT_Stderr,
TT_Undef
};
typedef enum CmppTokenType CmppTokenType;

struct CmppToken {
  CmppTokenType ttype;
  /* Line number of this token in the source file. */
  unsigned lineNo;
  /* Start of the token. */
  unsigned char const * zBegin;
  /* One-past-the-end byte of the token. */
  unsigned char const * zEnd;
};
typedef struct CmppToken CmppToken;
#define CmppToken_empty_m {TT_Invalid,0,0,0}
static const CmppToken CmppToken_empty = CmppToken_empty_m;

/*
** CmppLevel represents one "level" of tokenization, starting at the
** top of the main input, incrementing once for each level of `#if`,
** and decrementing for each `#endif`.
*/
typedef struct CmppLevel CmppLevel;
struct CmppLevel {
  unsigned short flags;
  /*
  ** Used for controlling which parts of an if/elif/...endif chain
  ** should get output.
  */
  unsigned short skipLevel;
  /* The token which started this level (an 'if' or 'ifnot'). */
  CmppToken token;
  CmppParseState pstate;
};
#define CmppLevel_empty_m {0U,0U,CmppToken_empty_m,TS_Start}
static const CmppLevel CmppLevel_empty = CmppLevel_empty_m;
enum CmppLevel_Flags {
/* Max depth of nested `#if` constructs in a single tokenizer. */
CmppLevel_Max = 10,
/* Max number of keyword arguments. */
CmppArgs_Max = 10,
/* Flag indicating that output for a CmpLevel should be elided. */
CmppLevel_F_ELIDE = 0x01,
/*
** Mask of CmppLevel::flags which are inherited when CmppLevel_push()
** is used.
*/
CmppLevel_F_INHERIT_MASK = 0x01
};

typedef struct CmppTokenizer CmppTokenizer;
typedef struct CmppKeyword CmppKeyword;
typedef void (*cmpp_keyword_f)(CmppKeyword const * pKw, CmppTokenizer * t);
struct CmppKeyword {
  const char *zName;
  unsigned nName;
  int bTokenize;
  CmppTokenType ttype;
  cmpp_keyword_f xCall;
};

static CmppKeyword const * CmppKeyword_search(const char *zName);
static void cmpp_process_keyword(CmppTokenizer * const t);

/*
** Tokenizer for c-pp input files.
*/
struct CmppTokenizer {
  const char * zName;            /* Input (file) name for error reporting */
  unsigned const char * zBegin;  /* start of input */
  unsigned const char * zEnd;    /* one-after-the-end of input */
  unsigned const char * zAnchor; /* start of input or end point of
                                    previous token */
  unsigned const char * zPos;    /* current position */
  unsigned int lineNo;           /* line # of current pos */
  CmppParseState pstate;
  CmppToken token;               /* current token result */
  struct {
    unsigned ndx;
    CmppLevel stack[CmppLevel_Max];
  } level;
  /* Args for use in cmpp_keyword_f() impls. */
  struct {
    CmppKeyword const * pKw;
    int argc;
    const unsigned char * argv[CmppArgs_Max];
    unsigned char lineBuf[1024];
  } args;
};
#define CT_level(t) (t)->level.stack[(t)->level.ndx]
#define CT_pstate(t) CT_level(t).pstate
#define CT_skipLevel(t) CT_level(t).skipLevel
#define CLvl_skip(lvl) ((lvl)->skipLevel || ((lvl)->flags & CmppLevel_F_ELIDE))
#define CT_skip(t) CLvl_skip(&CT_level(t))
#define CmppTokenizer_empty_m {                 \
    0,0,0,0,0,1U/*lineNo*/,                     \
    TS_Start,                                 \
    CmppToken_empty_m,                        \
    {/*level*/0U,{CmppLevel_empty_m}},       \
    {/*args*/0,0,{0},{0}}                \
  }
static const CmppTokenizer CmppTokenizer_empty = CmppTokenizer_empty_m;

static void cmpp_t_out(CmppTokenizer * t, void const *z, unsigned int n);
/*static void cmpp_t_outf(CmppTokenizer * t, char const *zFmt, ...);*/

/*
** Pushes a new level into the given tokenizer. Fails fatally if
** it's too deep.
*/
static void CmppLevel_push(CmppTokenizer * const t);
/*
** Pops a level from the tokenizer. Fails fatally if the top
** level is popped.
*/
static void CmppLevel_pop(CmppTokenizer * const t);
/*
** Returns the current level object.
*/
static CmppLevel * CmppLevel_get(CmppTokenizer * const t);

/*
** Global app state singleton. */
static struct Global {
  /* main()'s argv[0]. */
  const char * zArgv0;
  /*
  ** Bytes of the keyword delimiter/prefix. Owned
  ** elsewhere.
  */
  const char * zDelim;
  /* Byte length of this->zDelim. */
  unsigned short nDelim;
  /* If true, enables certain debugging output. */
  int doDebug;
  /* App's db instance. */
  sqlite3 * db;
  /* Output channel. */
  FileWrapper out;
  struct {
    sqlite3_stmt * defIns;
    sqlite3_stmt * defDel;
    sqlite3_stmt * defHas;
    sqlite3_stmt * inclIns;
    sqlite3_stmt * inclDel;
    sqlite3_stmt * inclHas;
    sqlite3_stmt * inclPathAdd;
    sqlite3_stmt * inclSearch;
  } stmt;
} g = {
"?",
CMPP_DEFAULT_DELIM/*zDelim*/,
(unsigned short) sizeof(CMPP_DEFAULT_DELIM)-1/*nDelim*/,
0/*doDebug*/,
0/*db*/,
FileWrapper_empty_m/*out*/,
{/*stmt*/
  0/*defIns*/, 0/*defDel*/, 0/*defHas*/,
  0/*inclIns*/, 0/*inclDel*/, 0/*inclHas*/,
  0/*inclPathAdd*/
}
};


#if 0
/*
** Outputs a printf()-formatted message to c-pp's global output
** channel.
*/
static void g_outf(char const *zFmt, ...);
void g_outf(char const *zFmt, ...){
  va_list va;
  va_start(va, zFmt);
  vfprintf(g.out.pFile, zFmt, va);
  va_end(va);
}
#endif

#if 0
/* Outputs n bytes from z to c-pp's global output channel. */
static void g_out(void const *z, unsigned int n);
void g_out(void const *z, unsigned int n){
  if(1!=fwrite(z, n, 1, g.out.pFile)){
    int const err = errno;
    fatal("fwrite() output failed with errno #%d", err);
  }
}
#endif

void g_stderrv(char const *zFmt, va_list va){
  vfprintf(stderr, zFmt, va);
}

void g_stderr(char const *zFmt, ...){
  va_list va;
  va_start(va, zFmt);
  g_stderrv(zFmt, va);
  va_end(va);
}

void cmpp_t_out(CmppTokenizer * t, void const *z, unsigned int n){
  g_debug(3,("CT_skipLevel() ?= %d\n",CT_skipLevel(t)));
  g_debug(3,("CT_skip() ?= %d\n",CT_skip(t)));
  if(!CT_skip(t)){
    if(1!=fwrite(z, n, 1, g.out.pFile)){
      int const err = errno;
      fatal("fwrite() output failed with errno #%d", err);
    }
  }
}

void CmppLevel_push(CmppTokenizer * const t){
  CmppLevel * pPrev;
  CmppLevel * p;
  if(t->level.ndx+1 == (unsigned)CmppLevel_Max){
    fatal("%sif nesting level is too deep. Max=%d\n",
          g.zDelim, CmppLevel_Max);
  }
  pPrev = &CT_level(t);
  g_debug(3,("push from tokenizer level=%u flags=%04x\n", t->level.ndx, pPrev->flags));
  p = &t->level.stack[++t->level.ndx];
  *p = CmppLevel_empty;
  p->token = t->token;
  p->flags = (CmppLevel_F_INHERIT_MASK & pPrev->flags);
  if(CLvl_skip(pPrev)) p->flags |= CmppLevel_F_ELIDE;
  g_debug(3,("push to tokenizer level=%u flags=%04x\n", t->level.ndx, p->flags));
}

void CmppLevel_pop(CmppTokenizer * const t){
  if(!t->level.ndx){
    fatal("Internal error: CmppLevel_pop() at the top of the stack");
  }
  g_debug(3,("pop from tokenizer level=%u, flags=%04x skipLevel?=%d\n", t->level.ndx,
             t->level.stack[t->level.ndx].flags, CT_skipLevel(t)));
  g_debug(3,("CT_skipLevel() ?= %d\n",CT_skipLevel(t)));
  g_debug(3,("CT_skip() ?= %d\n",CT_skip(t)));
  t->level.stack[t->level.ndx--] = CmppLevel_empty;
  g_debug(3,("pop to tokenizer level=%u, flags=%04x\n", t->level.ndx,
             t->level.stack[t->level.ndx].flags));
  g_debug(3,("CT_skipLevel() ?= %d\n",CT_skipLevel(t)));
  g_debug(3,("CT_skip() ?= %d\n",CT_skip(t)));
}

CmppLevel * CmppLevel_get(CmppTokenizer * const t){
  return &t->level.stack[t->level.ndx];
}


void db_affirm_rc(int rc, const char * zMsg){
  if(rc){
    fatal("Db error #%d %s: %s", rc, zMsg, sqlite3_errmsg(g.db));
  }
}

void db_finalize(sqlite3_stmt *pStmt){
  sqlite3_finalize(pStmt);
}

int db_step(sqlite3_stmt *pStmt){
  int const rc = sqlite3_step(pStmt);
  if(SQLITE_ROW!=rc && SQLITE_DONE!=rc){
    db_affirm_rc(rc, "from db_step()");
  }
  return rc;
}

static sqlite3_str * db_str_new(void){
  sqlite3_str * rc = sqlite3_str_new(g.db);
  if(!rc) fatal("Alloc failed for sqlite3_str_new()");
  return rc;
}

static char * db_str_finish(sqlite3_str *s, int * n){
  int const rc = sqlite3_str_errcode(s);
  if(rc) fatal("Error #%d from sqlite3_str_errcode()", rc);
  if(n) *n = sqlite3_str_length(s);
  char * z = sqlite3_str_finish(s);
  if(!z) fatal("Alloc failed for sqlite3_str_new()");
  return z;
}

void db_prepare(sqlite3_stmt **pStmt, const char * zSql, ...){
  int rc;
  sqlite3_str * str = db_str_new();
  char * z = 0;
  int n = 0;
  va_list va;
  if(!str) fatal("sqlite3_str_new() failed");
  va_start(va, zSql);
  sqlite3_str_vappendf(str, zSql, va);
  va_end(va);
  rc = sqlite3_str_errcode(str);
  if(rc) fatal("sqlite3_str_errcode() = %d", rc);
  z = db_str_finish(str, &n);
  rc = sqlite3_prepare_v2(g.db, z, n, pStmt, 0);
  if(rc) fatal("Error #%d (%s) preparing: %s",
               rc, sqlite3_errmsg(g.db), z);
  sqlite3_free(z);
}

void db_bind_int(sqlite3_stmt *pStmt, int col, int val){
  int const rc = sqlite3_bind_int(pStmt, col, val);
  db_affirm_rc(rc,"from db_bind_int()");
}

#if 0
void db_bind_null(sqlite3_stmt *pStmt, int col){
  int const rc = sqlite3_bind_null(pStmt, col);
  db_affirm_rc(rc,"from db_bind_null()");
}
#endif

void db_bind_textn(sqlite3_stmt *pStmt, int col,
                   const char * zStr, int n){
  int const rc = zStr
    ? sqlite3_bind_text(pStmt, col, zStr, n, SQLITE_TRANSIENT)
    : sqlite3_bind_null(pStmt, col);
  db_affirm_rc(rc,"from db_bind_textn()");
}

void db_bind_text(sqlite3_stmt *pStmt, int col,
                  const char * zStr){
  db_bind_textn(pStmt, col, zStr, -1);
}

#if 0
void db_bind_textv(sqlite3_stmt *pStmt, int col,
                   const char * zFmt, ...){
  int rc;
  sqlite3_str * str = db_str_new();
  int n = 0;
  char * z;
  va_list va;
  va_start(va,zFmt);
  sqlite3_str_vappendf(str, zFmt, va);
  va_end(va);
  z = db_str_finish(str, &n);
  rc = sqlite3_bind_text(pStmt, col, z, n, sqlite3_free);
  db_affirm_rc(rc,"from db_bind_textv()");
}
#endif

void db_free(void *m){
  sqlite3_free(m);
}

void db_define_add(const char * zKey){
  int rc;
  if(!g.stmt.defIns){
    db_prepare(&g.stmt.defIns,
               "INSERT OR REPLACE INTO def(k) VALUES(?)");
  }
  db_bind_text(g.stmt.defIns, 1, zKey);
  rc = db_step(g.stmt.defIns);
  if(SQLITE_DONE != rc){
    db_affirm_rc(rc, "Stepping INSERT on def");
  }
  g_debug(2,("define: %s\n",zKey));
  sqlite3_reset(g.stmt.defIns);
}

int db_define_has(const char * zName){
  int rc;
  if(!g.stmt.defHas){
    db_prepare(&g.stmt.defHas, "SELECT 1 FROM def WHERE k=?");
  }
  db_bind_text(g.stmt.defHas, 1, zName);
  rc = db_step(g.stmt.defHas);
  if(SQLITE_ROW == rc){
    rc = 1;
  }else{
    assert(SQLITE_DONE==rc);
    rc = 0;
  }
  g_debug(1,("defined [%s] ?= %d\n",zName, rc));
  sqlite3_clear_bindings(g.stmt.defHas);
  sqlite3_reset(g.stmt.defHas);
  return rc;
}


void db_define_rm(const char * zKey){
  int rc;
  int n = 0;
  const char *zPos = zKey;
  if(!g.stmt.defDel){
    db_prepare(&g.stmt.defDel, "DELETE FROM def WHERE k=?");
  }
  for( ; *zPos && '='!=*zPos; ++n, ++zPos) {}
  db_bind_text(g.stmt.defDel, 1, zKey);
  rc = db_step(g.stmt.defDel);
  if(SQLITE_DONE != rc){
    db_affirm_rc(rc, "Stepping DELETE on def");
  }
  g_debug(2,("undefine: %.*s\n",n, zKey));
  sqlite3_clear_bindings(g.stmt.defDel);
  sqlite3_reset(g.stmt.defDel);
}

void db_including_add(const char * zKey, const char * zSrc, int srcLine){
  int rc;
  if(!g.stmt.inclIns){
    db_prepare(&g.stmt.inclIns,
               "INSERT OR FAIL INTO incl(file,srcFile,srcLine) VALUES(?,?,?)");
  }
  db_bind_text(g.stmt.inclIns, 1, zKey);
  db_bind_text(g.stmt.inclIns, 2, zSrc);
  db_bind_int(g.stmt.inclIns, 3, srcLine);
  rc = db_step(g.stmt.inclIns);
  if(SQLITE_DONE != rc){
    db_affirm_rc(rc, "Stepping INSERT on incl");
  }
  g_debug(2,("inclpath add [%s] from [%s]:%d\n", zKey, zSrc, srcLine));
  sqlite3_clear_bindings(g.stmt.inclIns);
  sqlite3_reset(g.stmt.inclIns);
}

void db_include_rm(const char * zKey){
  int rc;
  if(!g.stmt.inclDel){
    db_prepare(&g.stmt.inclDel, "DELETE FROM incl WHERE file=?");
  }
  db_bind_text(g.stmt.inclDel, 1, zKey);
  rc = db_step(g.stmt.inclDel);
  if(SQLITE_DONE != rc){
    db_affirm_rc(rc, "Stepping DELETE on incl");
  }
  g_debug(2,("inclpath rm [%s]\n", zKey));
  sqlite3_clear_bindings(g.stmt.inclDel);
  sqlite3_reset(g.stmt.inclDel);
}

char * db_include_search(const char * zKey){
  char * zName = 0;
  if(!g.stmt.inclSearch){
    db_prepare(&g.stmt.inclSearch,
               "SELECT ?1 fn WHERE fileExists(fn) "
               "UNION ALL SELECT * FROM ("
               "SELECT replace(dir||'/'||?1, '//','/') AS fn "
               "FROM inclpath WHERE fileExists(fn) ORDER BY seq"
               ")");
  }
  db_bind_text(g.stmt.inclSearch, 1, zKey);
  if(SQLITE_ROW==db_step(g.stmt.inclSearch)){
    const unsigned char * z = sqlite3_column_text(g.stmt.inclSearch, 0);
    zName = z ? sqlite3_mprintf("%s", z) : 0;
    if(!zName) fatal("Alloc failed");
  }
  sqlite3_clear_bindings(g.stmt.inclSearch);
  sqlite3_reset(g.stmt.inclSearch);
  return zName;
}

static int db_including_has(const char * zName){
  int rc;
  if(!g.stmt.inclHas){
    db_prepare(&g.stmt.inclHas, "SELECT 1 FROM incl WHERE file=?");
  }
  db_bind_text(g.stmt.inclHas, 1, zName);
  rc = db_step(g.stmt.inclHas);
  if(SQLITE_ROW == rc){
    rc = 1;
  }else{
    assert(SQLITE_DONE==rc);
    rc = 0;
  }
  g_debug(2,("inclpath has [%s] = %d\n",zName, rc));
  sqlite3_clear_bindings(g.stmt.inclHas);
  sqlite3_reset(g.stmt.inclHas);
  return rc;
}

#if 0
/*
** Fails fatally if the `#include` list contains the given key.
*/
static void db_including_check(const char * zKey);
void db_including_check(const char * zName){
  if(db_including_has(zName)){
    fatal("Recursive include detected: %s\n", zName);
  }
}
#endif

void db_include_dir_add(const char * zDir){
  static int seq = 0;
  int rc;
  if(!g.stmt.inclPathAdd){
    db_prepare(&g.stmt.inclPathAdd,
               "INSERT OR FAIL INTO inclpath(seq,dir) VALUES(?,?)");
  }
  db_bind_int(g.stmt.inclPathAdd, 1, ++seq);
  db_bind_text(g.stmt.inclPathAdd, 2, zDir);
  rc = db_step(g.stmt.inclPathAdd);
  if(SQLITE_DONE != rc){
    db_affirm_rc(rc, "Stepping INSERT on inclpath");
  }
  g_debug(2,("inclpath add #%d: %s\n",seq, zDir));
  sqlite3_clear_bindings(g.stmt.inclPathAdd);
  sqlite3_reset(g.stmt.inclPathAdd);
}

static void cmpp_atexit(void){
#define FINI(M) if(g.stmt.M) sqlite3_finalize(g.stmt.M)
  FINI(defIns); FINI(defDel); FINI(defHas);
  FINI(inclIns); FINI(inclDel); FINI(inclHas);
  FINI(inclPathAdd); FINI(inclSearch);
#undef FINI
  FileWrapper_close(&g.out);
  if(g.db) sqlite3_close(g.db);
}

/*
** sqlite3 UDF which returns true if its argument refers to an
** accessible file, else false.
*/
static void udf_file_exists(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const char *zName;
  (void)(argc);  /* Unused parameter */
  zName = (const char*)sqlite3_value_text(argv[0]);
  if( zName==0 ) return;
  sqlite3_result_int(context, 0==access(zName, 0));
}

/* Initialize g.db, failing fatally on error. */
static void cmpp_initdb(void){
  int rc;
  char * zErr = 0;
  const char * zSchema =
    "CREATE TABLE def("
      "k TEXT PRIMARY KEY NOT NULL"
    /*"v INTEGER DEFAULT 1"*/
    ") WITHOUT ROWID;"
    /* ^^^ defines */
    "CREATE TABLE incl("
      "file TEXT PRIMARY KEY NOT NULL,"
      "srcFile TEXT DEFAULT NULL,"
      "srcLine INTEGER DEFAULT 0"
    ") WITHOUT ROWID;"
    /* ^^^ files currently being included */
    "CREATE TABLE inclpath("
      "seq INTEGER UNIQUE, "
      "dir TEXT PRIMARY KEY NOT NULL ON CONFLICT IGNORE"
    ")"
    /* ^^^ include path */
    ;
  assert(0==g.db);
  if(g.db) return;
  rc = sqlite3_open_v2(":memory:", &g.db, SQLITE_OPEN_READWRITE, 0);
  if(rc) fatal("Error opening :memory: db.");
  rc = sqlite3_exec(g.db, zSchema, 0, 0, &zErr);
  if(rc) fatal("Error initializing database: %s", zErr);
  rc = sqlite3_create_function(g.db, "fileExists", 1, 
                               SQLITE_UTF8|SQLITE_DIRECTONLY, 0,
                               udf_file_exists, 0, 0);
  db_affirm_rc(rc, "UDF registration failed.");
}

/*
** For position zPos, which must be in the half-open range
** [zBegin,zEnd), returns g.nDelim if it is at the start of a line and
** starts with g.zDelim, else returns 0.
*/
static unsigned short cmpp_is_delim(unsigned char const *zBegin,
                                    unsigned char const *zEnd,
                                    unsigned char const *zPos){
  assert(zEnd>zBegin);
  assert(zPos<zEnd);
  assert(zPos>=zBegin);
  if(zPos>zBegin &&
     ('\n'!=*(zPos - 1)
      || ((unsigned)(zEnd - zPos) <= g.nDelim))){
    return 0;
  }else if(0==memcmp(zPos, g.zDelim, g.nDelim)){
    return g.nDelim;
  }else{
    return 0;
  }
}

/*
** Scans t to the next keyword line, emitting all input before that
** which is _not_ a keyword line unless it's elided due to being
** inside a block which elides its content. Returns 0 if no keyword
** line was found, in which case the end of the input has been
** reached, else returns a truthy value and sets up t's state for use
** with cmpp_process_keyword(), which should then be called.
*/
static int cmpp_next_keyword_line(CmppTokenizer * const t){
  unsigned char const * zStart;
  unsigned char const * z;
  CmppToken * const tok = &t->token;
  unsigned short isDelim = 0;

  assert(t->zBegin);
  assert(t->zEnd > t->zBegin);
  if(!t->zPos) t->zPos = t->zBegin;
  t->zAnchor = t->zPos;
  zStart = z = t->zPos;
  *tok = CmppToken_empty;
  while(z<t->zEnd
        && 0==(isDelim = cmpp_is_delim(t->zBegin, t->zEnd, z))){
    ++z;
  }
  if(z>zStart){
    /* We passed up content */
    cmpp_t_out(t, zStart, (unsigned)(z - zStart));
  }
  assert(isDelim==0 || isDelim==g.nDelim);
  tok->lineNo = t->lineNo += count_lines(zStart, z);
  if(isDelim){
    /* Handle backslash-escaped newlines */
    int isEsc = 0, atEol = 0;
    tok->zBegin = z+isDelim;
    for( ++z ; z<t->zEnd && 0==atEol; ++z ){
      switch((int)*z){
        case (int)'\\':
          isEsc = 0==isEsc; break;
        case (int)'\n':
          atEol = 0==isEsc;
          isEsc = 0;
          ++t->lineNo;
          break;
        default:
          break;
      }
    }
    tok->zEnd = atEol ? z-1 : z;
    /* Strip leading spaces */
    while(tok->zBegin < tok->zEnd && isspace((char)(*tok->zBegin))){
      ++tok->zBegin;
    }
    tok->ttype = TT_Line;
    g_debug(2,("Keyword @ line %u: [[[%.*s]]]\n",
               tok->lineNo,
               (int)(tok->zEnd-tok->zBegin), tok->zBegin));
  }
  t->zPos = z;
  if(isDelim){
    /* Split t->token into arguments for the line's keyword */
    int i, argc = 0, prevChar = 0;
    const unsigned tokLen = (unsigned)(tok->zEnd - tok->zBegin);
    unsigned char * zKwd;
    unsigned char * zEsc;
    unsigned char * zz;

    assert(TT_Line==tok->ttype);
    if((unsigned)sizeof(t->args.lineBuf) < tokLen + 1){
      fatal("Keyword line is unreasonably long: %.*s",
            tokLen, tok->zBegin);
    }else if(!tokLen){
      fatal("Line #%u has no keyword after delimiter", tok->lineNo);
    }
    g_debug(2,("token @ line %u len=%u [[[%.*s]]]\n",
               tok->lineNo, tokLen, tokLen, tok->zBegin));
    zKwd = &t->args.lineBuf[0];
    memcpy(zKwd, tok->zBegin, tokLen);
    memset(zKwd + tokLen, 0, sizeof(t->args.lineBuf) - tokLen);
    for( zEsc = 0, zz = zKwd; *zz; ++zz ){
      /* Convert backslash-escaped newlines to whitespace */
      switch((int)*zz){
        case (int)'\\':
          if(zEsc) zEsc = 0;
          else zEsc = zz;
          break;
        case (int)'\n':
          assert(zEsc && "Should not have an unescaped newline?");
          if(zEsc==zz-1){
            *zEsc = (unsigned char)' ';
            /* FIXME?: memmove() lnBuf content one byte to the left here
            ** to collapse backslash and newline into a single
            ** byte. Also consider collapsing all leading space on the
            ** next line. */
          }
          zEsc = 0;
          *zz = (unsigned char)' ';
          break;
        default:
          zEsc = 0;
          break;
      }
    }
    t->args.argv[argc++] = zKwd;
    for( zz = zKwd; *zz; ++zz ){
      if(isspace(*zz)){
        *zz = 0;
        break;
      }
    }
    t->args.pKw = CmppKeyword_search((char const *)zKwd);
    if(!t->args.pKw){
      fatal("Unknown keyword '%s' at line %u\n", (char const *)zKwd,
            tok->lineNo);
    }
    for( ++zz ; *zz && isspace(*zz); ++zz ){}
    if(t->args.pKw->bTokenize){
      for( ; *zz; prevChar = *zz, ++zz ){
        /* Split string into word-shaped tokens. 
        ** TODO ?= quoted strings, for the sake of the
        ** #error keyword. */
        if(isspace(*zz)){
          assert(zz!=zKwd && "Leading space was stripped earlier.");
          *zz = 0;
        }else{
          if(argc == (int)CmppArgs_Max){
            fatal("Too many arguments @ line %u: %.*s",
                  tok->lineNo, tokLen, tok->zBegin);
          }else if(zz>zKwd && !prevChar){
            t->args.argv[argc++] = zz;
          }
        }
      }
    }else{
      /* Treat rest of line as one token */
      if(*zz) t->args.argv[argc++] = zz;
    }
    tok->ttype = t->args.pKw->ttype;
    if(g.doDebug>1){
      for(i = 0; i < argc; ++i){
        g_debug(0,("line %u arg #%d=%s\n",
                   tok->lineNo, i,
                   (char const *)t->args.argv[i]));
      }
    }
    t->args.argc = argc;
  }else{
    t->args.pKw = 0;
    t->args.argc = 0;
  }
  return isDelim;
}

static void cmpp_kwd__err_prefix(CmppKeyword const * pKw, CmppTokenizer *t,
                                 char const *zPrefix){
  g_stderr("%s%s%s @ %s line %u: ",
           zPrefix ? zPrefix : "",
           zPrefix ? ": " : "",
           pKw->zName, t->zName, t->token.lineNo);
}

/* Internal error reporting helper for cmpp_keyword_f() impls. */
static CMPP_NORETURN void cmpp_kwd__misuse(CmppKeyword const * pKw,
                                           CmppTokenizer *t,
                                           char const *zFmt, ...){
  va_list va;
  cmpp_kwd__err_prefix(pKw, t, "Fatal error");
  va_start(va, zFmt);
  fatalv(zFmt, va);
  va_end(va);
}

/* No-op cmpp_keyword_f() impl. */
static void cmpp_kwd_noop(CmppKeyword const * pKw, CmppTokenizer *t){
  if(t || pKw){/*unused*/}
}

/* #error impl. */
static void cmpp_kwd_error(CmppKeyword const * pKw, CmppTokenizer *t){
  if(CT_skip(t)) return;
  else{
    assert(t->args.argc < 3);
    const char *zBegin = t->args.argc>1
      ? (const char *)t->args.argv[1] : 0;
    cmpp_kwd__err_prefix(pKw, t, NULL);
    fatal("%s", zBegin ? zBegin : "(no additional info)");
  }
}

/* Impl. for #define, #undef */
static void cmpp_kwd_define(CmppKeyword const * pKw, CmppTokenizer *t){
  if(CT_skip(t)) return;
  if(t->args.argc<2){
    cmpp_kwd__misuse(pKw, t, "Expecting one or more arguments");
  }else{
    int i = 1;
    void (*func)(const char *) = TT_Define==pKw->ttype
      ? db_define_add : db_define_rm;
    for( ; i < t->args.argc; ++i){
      func( (char const *)t->args.argv[i] );
    }
  }
}

/* Impl. for #if, #ifnot, #elif, #elifnot. */
static void cmpp_kwd_if(CmppKeyword const * pKw, CmppTokenizer *t){
  int buul;
  CmppParseState tmpState = TS_Start;
  if(t->args.argc!=2){
    cmpp_kwd__misuse(pKw, t, "Expecting exactly 1 argument");
  }
  /*g_debug(0,("%s %s level %u pstate=%d\n", pKw->zName,
             (char const *)t->args.argv[1],
             t->level.ndx, (int)CT_pstate(t)));*/
  switch(pKw->ttype){
    case TT_Elif:
    case TT_ElifNot:
      switch(CT_pstate(t)){
        case TS_If: break;
        case TS_IfPassed: CT_level(t).flags |= CmppLevel_F_ELIDE; return;
        default: goto misuse;
      }
      break;
    case TT_If:
    case TT_IfNot:
      CmppLevel_push(t);
      break;
    default:
      cmpp_kwd__misuse(pKw, t, "Unpexected keyword token type");
      break;
  }
  buul = db_define_has((char const *)t->args.argv[1]);
  if(TT_IfNot==pKw->ttype || TT_ElifNot==pKw->ttype) buul = !buul;
  if(buul){
    CT_pstate(t) = tmpState = TS_IfPassed;
    CT_skipLevel(t) = 0;
  }else{
    CT_pstate(t) = TS_If /* also for TT_IfNot, TT_Elif, TT_ElifNot */;
    CT_skipLevel(t) = 1;
    g_debug(3,("setting CT_skipLevel = 1 @ level %d\n", t->level.ndx));
  }
  if(TT_If==pKw->ttype || TT_IfNot==pKw->ttype){
    unsigned const lvlIf = t->level.ndx;
    CmppToken const lvlToken = CT_level(t).token;
    while(cmpp_next_keyword_line(t)){
      cmpp_process_keyword(t);
      if(lvlIf > t->level.ndx){
        assert(TT_EndIf == t->token.ttype);
        break;
      }
#if 0
      if(TS_IfPassed==tmpState){
        tmpState = TS_Start;
        t->level.stack[lvlIf].flags |= CmppLevel_F_ELIDE;
        g_debug(1,("Setting ELIDE for TS_IfPassed @ lv %d (lvlIf=%d)\n", t->level.ndx, lvlIf));
      }
#endif
    }
    if(lvlIf <= t->level.ndx){
      cmpp_kwd__err_prefix(pKw, t, NULL);
      fatal("Input ended inside an unterminated %sif "
            "opened at [%s] line %u",
            g.zDelim, t->zName, lvlToken.lineNo);
    }
  }
  return;
  misuse:
  cmpp_kwd__misuse(pKw, t, "'%s' used out of context",
                   pKw->zName);
}

/* Impl. for #else. */
static void cmpp_kwd_else(CmppKeyword const * pKw, CmppTokenizer *t){
  if(t->args.argc>1){
    cmpp_kwd__misuse(pKw, t, "Expecting no arguments");
  }
  switch(CT_pstate(t)){
    case TS_IfPassed: CT_skipLevel(t) = 1; break;
    case TS_If: CT_skipLevel(t) = 0; break;
    default:
      cmpp_kwd__misuse(pKw, t, "'%s' with no matching 'if'",
                      pKw->zName);
  }
  /*g_debug(0,("else flags=0x%02x skipLevel=%u\n",
    CT_level(t).flags, CT_level(t).skipLevel));*/
  CT_pstate(t) = TS_Else;
}

/* Impl. for #endif. */
static void cmpp_kwd_endif(CmppKeyword const * pKw, CmppTokenizer *t){
  /* Maintenance reminder: we ignore all arguments after the endif
  ** to allow for constructs like:
  **
  ** #endif // foo
  **
  ** in a manner which does not require a specific comment style */
  switch(CT_pstate(t)){
    case TS_Else:
    case TS_If:
    case TS_IfPassed:
      break;
    default:
      cmpp_kwd__misuse(pKw, t, "'%s' with no matching 'if'",
                       pKw->zName);
  }
  CmppLevel_pop(t);
}

/* Impl. for #include. */
static void cmpp_kwd_include(CmppKeyword const * pKw, CmppTokenizer *t){
  char const * zFile;
  char * zResolved;
  if(CT_skip(t)) return;
  else if(t->args.argc!=2){
    cmpp_kwd__misuse(pKw, t, "Expecting exactly 1 filename argument");
  }
  zFile = (const char *)t->args.argv[1];
  if(db_including_has(zFile)){
    /* Note that different spellings of the same filename
    ** will elude this check, but that seems okay, as different
    ** spellings means that we're not re-running the exact same
    ** invocation. We might want some other form of multi-include
    ** protection, rather than this, however. There may well be
    ** sensible uses for recursion. */
    cmpp_kwd__err_prefix(pKw, t, NULL);
    fatal("Recursive include of file: %s", zFile);
  }
  zResolved = db_include_search(zFile);
  if(zResolved){
    db_including_add(zFile, t->zName, t->token.lineNo);
    cmpp_process_file(zResolved);
    db_include_rm(zFile);
    db_free(zResolved);
  }else{
    cmpp_kwd__err_prefix(pKw, t, NULL);
    fatal("file not found: %s", zFile);
  }
}

/* Impl. for #pragma. */
static void cmpp_kwd_pragma(CmppKeyword const * pKw, CmppTokenizer *t){
  const char * zArg;
  if(CT_skip(t)) return;
  else if(t->args.argc!=2){
    cmpp_kwd__misuse(pKw, t, "Expecting one argument");
  }
  zArg = (const char *)t->args.argv[1];
#define M(X) 0==strcmp(zArg,X)
  if(M("defines")){
    sqlite3_stmt * q = 0;
    db_prepare(&q, "SELECT k FROM def ORDER BY k");
    g_stderr("cmpp defines:\n");
    while(SQLITE_ROW==db_step(q)){
      int const n = sqlite3_column_bytes(q, 0);
      const char * z = (const char *)sqlite3_column_text(q, 0);
      g_stderr("\t%.*s\n", n, z);
    }
    db_finalize(q);
  }else{
    cmpp_kwd__misuse(pKw, t, "Unknown pragma");
  }
#undef M
}

/* #stder impl. */
static void cmpp_kwd_stderr(CmppKeyword const * pKw, CmppTokenizer *t){
  if(CT_skip(t)) return;
  else{
    const char *zBegin = t->args.argc>1
      ? (const char *)t->args.argv[1] : 0;
    if(zBegin){
      g_stderr("%s:%u: %s\n", t->zName, t->token.lineNo, zBegin);
    }else{
      g_stderr("%s:%u: (no %.*s%s argument)\n",
               t->zName, t->token.lineNo,
               g.nDelim, g.zDelim, pKw->zName);
    }
  }
}

#if 0
/* Impl. for dummy placeholder. */
static void cmpp_kwd_todo(CmppKeyword const * pKw, CmppTokenizer *t){
  if(t){/*unused*/}
  g_debug(0,("TODO: keyword handler for %s\n", pKw->zName));
}
#endif

CmppKeyword aKeywords[] = {
/* Keep these sorted by zName */
  {"//", 2, 0, TT_Comment, cmpp_kwd_noop},
  {"define", 6, 1, TT_Define, cmpp_kwd_define},
  {"elif", 4, 1, TT_Elif, cmpp_kwd_if},
  {"elifnot", 7, 1, TT_ElifNot, cmpp_kwd_if},
  {"else", 4, 1, TT_Else, cmpp_kwd_else},
  {"endif", 5, 0, TT_EndIf, cmpp_kwd_endif},
  {"error", 4, 0, TT_Error, cmpp_kwd_error},
  {"if", 2, 1, TT_If, cmpp_kwd_if},
  {"ifnot", 5, 1, TT_IfNot, cmpp_kwd_if},
  {"include", 7, 0, TT_Include, cmpp_kwd_include},
  {"pragma", 6, 1, TT_Pragma, cmpp_kwd_pragma},
  {"stderr", 6, 0, TT_Stderr, cmpp_kwd_stderr},
  {"undef", 5, 1, TT_Undef, cmpp_kwd_define},
  {0,0,TT_Invalid, 0}
};

static int cmp_CmppKeyword(const void *p1, const void *p2){
  char const * zName = (const char *)p1;
  CmppKeyword const * kw = (CmppKeyword const *)p2;
  return strcmp(zName, kw->zName);
}

CmppKeyword const * CmppKeyword_search(const char *zName){
  return (CmppKeyword const *)bsearch(zName, &aKeywords[0],
                                      sizeof(aKeywords)/sizeof(aKeywords[0]) - 1,
                                      sizeof(aKeywords[0]),
                                      cmp_CmppKeyword);
}

void cmpp_process_keyword(CmppTokenizer * const t){
  assert(t->args.pKw);
  assert(t->args.argc);
  t->args.pKw->xCall(t->args.pKw, t);
  t->args.pKw = 0;
  t->args.argc = 0;
}

void cmpp_process_file(const char * zName){
  FileWrapper fw = FileWrapper_empty;
  CmppTokenizer ct = CmppTokenizer_empty;

  FileWrapper_open(&fw, zName, "r");
  FileWrapper_slurp(&fw);
  g_debug(1,("Read %u byte(s) from [%s]\n", fw.nContent, fw.zName));
  ct.zName = zName;
  ct.zBegin = fw.zContent;
  ct.zEnd = fw.zContent + fw.nContent;
  while(cmpp_next_keyword_line(&ct)){
    cmpp_process_keyword(&ct);
  }
  FileWrapper_close(&fw);
  if(0!=ct.level.ndx){
    CmppLevel * const lv = CmppLevel_get(&ct);
    fatal("Input ended inside an unterminated nested construct"
          "opened at [%s] line %u", zName, lv->token.lineNo);
  }
}

static void usage(int isErr){
  FILE * const fOut = isErr ? stderr : stdout;
  fprintf(fOut,
          "Usage: %s [flags] [infile]\n"
          "Flags:\n",
          g.zArgv0);
#define arg(F,D) fprintf(fOut,"  %s\n      %s\n",F, D)
  arg("-f|--file FILE","Read input from FILE (default=- (stdin)).\n"
      "      Alternately, the first non-flag argument is assumed to "
      "be the input file.");
  arg("-o|--outfile FILE","Send output to FILE (default=- (stdout))");
  arg("-DXYZ","Define XYZ to true");
  arg("-UXYZ","Undefine XYZ (equivalent to false)");
  arg("-IXYZ","Add dir XYZ to include path");
  arg("-d|--delimiter VALUE", "Set keyword delimiter to VALUE "
      "(default=" CMPP_DEFAULT_DELIM ")");
#undef arg
  fputs("",fOut);
}

int main(int argc, char const * const * argv){
  int rc = 0;
  int i;
  int inclCount = 0;
  const char * zInfile = 0;
#define M(X) (0==strcmp(X,zArg))
#define ISFLAG(X) else if(M(X))
#define ISFLAG2(X,Y) else if(M(X) || M(Y))
#define ARGVAL \
  if(i+1>=argc) fatal("Missing value for flag '%s'", zArg);  \
  zArg = argv[++i]
  g.zArgv0 = argv[0];
  atexit(cmpp_atexit);
  cmpp_initdb();
  for(i = 1; i < argc; ++i){
    char const * zArg = argv[i];
    while('-'==*zArg) ++zArg;
    if(M("?") || M("help")) {
      usage(0);
      goto end;
    }else if('D'==*zArg){
      ++zArg;
      if(!*zArg) fatal("Missing key for -D");
      db_define_add(zArg);
    }else if('U'==*zArg){
      ++zArg;
      if(!*zArg) fatal("Missing key for -U");
      db_define_rm(zArg);
    }else if('I'==*zArg){
      ++zArg;
      if(!*zArg) fatal("Missing directory for -I");
      db_include_dir_add(zArg);
      ++inclCount;
    }
    ISFLAG2("o","outfile"){
      ARGVAL;
      if(g.out.zName) fatal("Cannot use -o more than once.");
      g.out.zName = zArg;
    }
    ISFLAG2("f","file"){
      ARGVAL;
      do_infile:
      if(zInfile) fatal("Cannot use -i more than once.");
      zInfile = zArg;
    }
    ISFLAG2("d","delimiter"){
      ARGVAL;
      g.zDelim = zArg;
      g.nDelim = (unsigned short)strlen(zArg);
      if(!g.nDelim) fatal("Keyword delimiter may not be empty.");
    }
    ISFLAG("debug"){
      ++g.doDebug;
    }else if(!zInfile){
      goto do_infile;
    }else{
      fatal("Unhandled flag: %s", argv[i]);
    }
  }
  if(!zInfile) zInfile = "-";
  if(!g.out.zName) g.out.zName = "-";
  if(!inclCount) db_include_dir_add(".");
  FileWrapper_open(&g.out, g.out.zName, "w");
  cmpp_process_file(zInfile);
  FileWrapper_close(&g.out);
  end:
  return rc ? EXIT_FAILURE : EXIT_SUCCESS;
}

#undef CT_level
#undef CT_pstate
#undef CT_skipLevel
#undef CT_skip
#undef CLvl_skip

Added ext/wasm/common/SqliteTestUtil.js.













































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
  2022-05-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 contains bootstrapping code used by various test scripts
  which live in this file's directory.
*/
'use strict';
(function(self){
  /* querySelectorAll() proxy */
  const EAll = function(/*[element=document,] cssSelector*/){
    return (arguments.length>1 ? arguments[0] : document)
      .querySelectorAll(arguments[arguments.length-1]);
  };
  /* querySelector() proxy */
  const E = function(/*[element=document,] cssSelector*/){
    return (arguments.length>1 ? arguments[0] : document)
      .querySelector(arguments[arguments.length-1]);
  };

  /**
     Helpers for writing sqlite3-specific tests.
  */
  self.SqliteTestUtil = {
    /** Running total of the number of tests run via
        this API. */
    counter: 0,
    /**
       If expr is a function, it is called and its result
       is returned, coerced to a bool, else expr, coerced to
       a bool, is returned.
    */
    toBool: function(expr){
      return (expr instanceof Function) ? !!expr() : !!expr;
    },
    /** abort() if expr is false. If expr is a function, it
        is called and its result is evaluated.
    */
    assert: function f(expr, msg){
      if(!f._){
        f._ = ('undefined'===typeof abort
               ? (msg)=>{throw new Error(msg)}
               : abort);
      }
      ++this.counter;
      if(!this.toBool(expr)){
        f._(msg || "Assertion failed.");
      }
      return this;
    },
    /** Identical to assert() but throws instead of calling
        abort(). */
    affirm: function(expr, msg){
      ++this.counter;
      if(!this.toBool(expr)) throw new Error(msg || "Affirmation failed.");
      return this;
    },
    /** Calls f() and squelches any exception it throws. If it
        does not throw, this function throws. */
    mustThrow: function(f, msg){
      ++this.counter;
      let err;
      try{ f(); } catch(e){err=e;}
      if(!err) throw new Error(msg || "Expected exception.");
      return this;
    },
    /**
       Works like mustThrow() but expects filter to be a regex,
       function, or string to match/filter the resulting exception
       against. If f() does not throw, this test fails and an Error is
       thrown. If filter is a regex, the test passes if
       filter.test(error.message) passes. If it's a function, the test
       passes if filter(error) returns truthy. If it's a string, the
       test passes if the filter matches the exception message
       precisely. In all other cases the test fails, throwing an
       Error.

       If it throws, msg is used as the error report unless it's falsy,
       in which case a default is used.
    */
    mustThrowMatching: function(f, filter, msg){
      ++this.counter;
      let err;
      try{ f(); } catch(e){err=e;}
      if(!err) throw new Error(msg || "Expected exception.");
      let pass = false;
      if(filter instanceof RegExp) pass = filter.test(err.message);
      else if(filter instanceof Function) pass = filter(err);
      else if('string' === typeof filter) pass = (err.message === filter);
      if(!pass){
        throw new Error(msg || ("Filter rejected this exception: "+err.message));
      }
      return this;
    },
    /** Throws if expr is truthy or expr is a function and expr()
        returns truthy. */
    throwIf: function(expr, msg){
      ++this.counter;
      if(this.toBool(expr)) throw new Error(msg || "throwIf() failed");
      return this;
    },
    /** Throws if expr is falsy or expr is a function and expr()
        returns falsy. */
    throwUnless: function(expr, msg){
      ++this.counter;
      if(!this.toBool(expr)) throw new Error(msg || "throwUnless() failed");
      return this;
    },

    /**
       Parses window.location.search-style string into an object
       containing key/value pairs of URL arguments (already
       urldecoded). The object is created using Object.create(null),
       so contains only parsed-out properties and has no prototype
       (and thus no inherited properties).

       If the str argument is not passed (arguments.length==0) then
       window.location.search.substring(1) is used by default. If
       neither str is passed in nor window exists then false is returned.

       On success it returns an Object containing the key/value pairs
       parsed from the string. Keys which have no value are treated
       has having the boolean true value.

       Pedantic licensing note: this code has appeared in other source
       trees, but was originally written by the same person who pasted
       it into those trees.
    */
    processUrlArgs: function(str) {
      if( 0 === arguments.length ) {
        if( ('undefined' === typeof window) ||
            !window.location ||
            !window.location.search )  return false;
        else str = (''+window.location.search).substring(1);
      }
      if( ! str ) return false;
      str = (''+str).split(/#/,2)[0]; // remove #... to avoid it being added as part of the last value.
      const args = Object.create(null);
      const sp = str.split(/&+/);
      const rx = /^([^=]+)(=(.+))?/;
      var i, m;
      for( i in sp ) {
        m = rx.exec( sp[i] );
        if( ! m ) continue;
        args[decodeURIComponent(m[1])] = (m[3] ? decodeURIComponent(m[3]) : true);
      }
      return args;
    }
  };

  
  /**
     This is a module object for use with the emscripten-installed
     sqlite3InitModule() factory function.
  */
  self.sqlite3TestModule = {
    /**
       Array of functions to call after Emscripten has initialized the
       wasm module. Each gets passed the Emscripten module object
       (which is _this_ object).
    */
    postRun: [
      /* function(theModule){...} */
    ],
    //onRuntimeInitialized: function(){},
    /* Proxy for C-side stdout output. */
    print: (...args)=>{console.log(...args)},
    /* Proxy for C-side stderr output. */
    printErr: (...args)=>{console.error(...args)},
    /**
       Called by the Emscripten module init bits to report loading
       progress. It gets passed an empty argument when loading is done
       (after onRuntimeInitialized() and any this.postRun callbacks
       have been run).
    */
    setStatus: function f(text){
      if(!f.last){
        f.last = { text: '', step: 0 };
        f.ui = {
          status: E('#module-status'),
          progress: E('#module-progress'),
          spinner: E('#module-spinner')
        };
      }
      if(text === f.last.text) return;
      f.last.text = text;
      if(f.ui.progress){
        f.ui.progress.value = f.last.step;
        f.ui.progress.max = f.last.step + 1;
      }
      ++f.last.step;
      if(text) {
        f.ui.status.classList.remove('hidden');
        f.ui.status.innerText = text;
      }else{
        if(f.ui.progress){
          f.ui.progress.remove();
          f.ui.spinner.remove();
          delete f.ui.progress;
          delete f.ui.spinner;
        }
        f.ui.status.classList.add('hidden');
      }
    },
    /**
       Config options used by the Emscripten-dependent initialization
       which happens via this.initSqlite3(). This object gets
       (indirectly) passed to sqlite3ApiBootstrap() to configure the
       sqlite3 API.
    */
    sqlite3ApiConfig: {
      wasmfsOpfsDir: "/opfs"
    },
    /**
       Intended to be called by apps which need to call the
       Emscripten-installed sqlite3InitModule() routine. This function
       temporarily installs this.sqlite3ApiConfig into the self
       object, calls it sqlite3InitModule(), and removes
       self.sqlite3ApiConfig after initialization is done. Returns the
       promise from sqlite3InitModule(), and the next then() handler
       will get the sqlite3 API object as its argument.
    */
    initSqlite3: function(){
      self.sqlite3ApiConfig = this.sqlite3ApiConfig;
      return self.sqlite3InitModule(this).finally(()=>delete self.sqlite3ApiConfig);
    }
  };
})(self/*window or worker*/);

Added ext/wasm/common/emscripten.css.

























1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/* emscripten-related styling, used during the module load/intialization processes... */
.emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
div.emscripten { text-align: center; }
div.emscripten_border { border: 1px solid black; }
#module-spinner { overflow: visible; }
#module-spinner > * {
    margin-top: 1em;
}
.spinner {
    height: 50px;
    width: 50px;
    margin: 0px auto;
    animation: rotation 0.8s linear infinite;
    border-left: 10px solid rgb(0,150,240);
    border-right: 10px solid rgb(0,150,240);
    border-bottom: 10px solid rgb(0,150,240);
    border-top: 10px solid rgb(100,0,200);
    border-radius: 100%;
    background-color: rgb(200,100,250);
}
@keyframes rotation {
    from {transform: rotate(0deg);}
    to {transform: rotate(360deg);}
}

Added ext/wasm/common/testing.css.






































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
body {
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
}
textarea {
    font-family: monospace;
}
header {
    font-size: 130%;
    font-weight: bold;
}
.hidden, .initially-hidden {
    position: absolute !important;
    opacity: 0 !important;
    pointer-events: none !important;
    display: none !important;
}
fieldset.options {
    font-size: 75%;
}
fieldset > legend {
    padding: 0 0.5em;
}
span.labeled-input {
    padding: 0.25em;
    margin: 0.25em 0.5em;
    border-radius: 0.25em;
    white-space: nowrap;
    background: #0002;
}
.center { text-align: center; }
.error {
    color: red;
    background-color: yellow;
}
.strong { font-weight: 700 }
.warning { color: firebrick; }
.green { color: darkgreen; }
.tests-pass { background-color: green; color: white }
.tests-fail { background-color: red; color: yellow }
.faded { opacity: 0.5; }
.group-start { color: blue; }
.group-end { color: blue; }
.input-wrapper {
  white-space: nowrap;
  display: flex;
  align-items: center;
}
#test-output {
  border: 1px inset;
  border-radius: 0.25em;
  padding: 0.25em;
  /*max-height: 30em;*/
  overflow: auto;
  white-space: break-spaces;
  display: flex; flex-direction: column;
  font-family: monospace;
}
#test-output.reverse {
  flex-direction: column-reverse;
}
label[for] { cursor: pointer }

h1 {
  border-radius: 0.25em;
  padding: 0.15em 0.25em;
}
h1:first-of-type {margin: 0 0 0.5em 0;}

Added ext/wasm/common/whwasmutil.js.




































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
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
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
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
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
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
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
1984
1985
1986
1987
1988
1989
1990
1991
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
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
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
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
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
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/**
  2022-07-08

  The author disclaims copyright to this source code.  In place of a
  legal notice, here is a blessing:

  *   May you do good and not evil.
  *   May you find forgiveness for yourself and forgive others.
  *   May you share freely, never taking more than you give.

  ***********************************************************************

  The whwasmutil is developed in conjunction with the Jaccwabyt
  project:

  https://fossil.wanderinghorse.net/r/jaccwabyt

  and sqlite3:

  https://sqlite.org

  This file is kept in sync between both of those trees.

  Maintenance reminder: If you're reading this in a tree other than
  one of those listed above, note that this copy may be replaced with
  upstream copies of that one from time to time. Thus the code
  installed by this function "should not" be edited outside of those
  projects, else it risks getting overwritten.
*/
/**
   This function is intended to simplify porting around various bits
   of WASM-related utility code from project to project.

   The primary goal of this code is to replace, where possible,
   Emscripten-generated glue code with equivalent utility code which
   can be used in arbitrary WASM environments built with toolchains
   other than Emscripten. As of this writing, this code is capable of
   acting as a replacement for Emscripten's generated glue code
   _except_ that the latter installs handlers for Emscripten-provided
   APIs such as its "FS" (virtual filesystem) API. Loading of such
   things still requires using Emscripten's glue, but the post-load
   utility APIs provided by this code are still usable as replacements
   for their sub-optimally-documented Emscripten counterparts.

   Intended usage:

   ```
   self.WhWasmUtilInstaller(appObject);
   delete self.WhWasmUtilInstaller;
   ```

   Its global-scope symbol is intended only to provide an easy way to
   make it available to 3rd-party scripts and "should" be deleted
   after calling it. That symbols is _not_ used within the library.

   Forewarning: this API explicitly targets only browser
   environments. If a given non-browser environment has the
   capabilities needed for a given feature (e.g. TextEncoder), great,
   but it does not go out of its way to account for them and does not
   provide compatibility crutches for them.

   It currently offers alternatives to the following
   Emscripten-generated APIs:

   - OPTIONALLY memory allocation, but how this gets imported is
     environment-specific.  Most of the following features only work
     if allocation is available.

   - WASM-exported "indirect function table" access and
     manipulation. e.g.  creating new WASM-side functions using JS
     functions, analog to Emscripten's addFunction() and
     uninstallFunction() but slightly different.

   - Get/set specific heap memory values, analog to Emscripten's
     getValue() and setValue().

   - String length counting in UTF-8 bytes (C-style and JS strings).

   - JS string to C-string conversion and vice versa, analog to
     Emscripten's stringToUTF8Array() and friends, but with slighter
     different interfaces.

   - JS string to Uint8Array conversion, noting that browsers actually
     already have this built in via TextEncoder.

   - "Scoped" allocation, such that allocations made inside of a given
     explicit scope will be automatically cleaned up when the scope is
     closed. This is fundamentally similar to Emscripten's
     stackAlloc() and friends but uses the heap instead of the stack
     because access to the stack requires C code.

   - Create JS wrappers for WASM functions, analog to Emscripten's
     ccall() and cwrap() functions, except that the automatic
     conversions for function arguments and return values can be
     easily customized by the client by assigning custom function
     signature type names to conversion functions. Essentially,
     it's ccall() and cwrap() on steroids.

   How to install...

   Passing an object to this function will install the functionality
   into that object. Afterwards, client code "should" delete the global
   symbol.

   This code requires that the target object have the following
   properties, noting that they needn't be available until the first
   time one of the installed APIs is used (as opposed to when this
   function is called) except where explicitly noted:

   - `exports` must be a property of the target object OR a property
     of `target.instance` (a WebAssembly.Module instance) and it must
     contain the symbols exported by the WASM module associated with
     this code. In an Enscripten environment it must be set to
     `Module['asm']`. The exports object must contain a minimum of the
     following symbols:

     - `memory`: a WebAssembly.Memory object representing the WASM
       memory. _Alternately_, the `memory` property can be set as
       `target.memory`, in particular if the WASM heap memory is
       initialized in JS an _imported_ into WASM, as opposed to being
       initialized in WASM and exported to JS.

     - `__indirect_function_table`: the WebAssembly.Table object which
       holds WASM-exported functions. This API does not strictly
       require that the table be able to grow but it will throw if its
       `installFunction()` is called and the table cannot grow.

   In order to simplify downstream usage, if `target.exports` is not
   set when this is called then a property access interceptor
   (read-only, configurable, enumerable) gets installed as `exports`
   which resolves to `target.instance.exports`, noting that the latter
   property need not exist until the first time `target.exports` is
   accessed.

   Some APIs _optionally_ make use of the `bigIntEnabled` property of
   the target object. It "should" be set to true if the WASM
   environment is compiled with BigInt support, else it must be
   false. If it is false, certain BigInt-related features will trigger
   an exception if invoked. This property, if not set when this is
   called, will get a default value of true only if the BigInt64Array
   constructor is available, else it will default to false. Note that
   having the BigInt type is not sufficient for full int64 integration
   with WASM: the target WASM file must also have been built with
   that support. In Emscripten that's done using the `-sWASM_BIGINT`
   flag.

   Some optional APIs require that the target have the following
   methods:

   - 'alloc()` must behave like C's `malloc()`, allocating N bytes of
     memory and returning its pointer. In Emscripten this is
     conventionally made available via `Module['_malloc']`. This API
     requires that the alloc routine throw on allocation error, as
     opposed to returning null or 0.

   - 'dealloc()` must behave like C's `free()`, accepting either a
     pointer returned from its allocation counterpart or the values
     null/0 (for which it must be a no-op). allocating N bytes of
     memory and returning its pointer. In Emscripten this is
     conventionally made available via `Module['_free']`.

   APIs which require allocation routines are explicitly documented as
   such and/or have "alloc" in their names.

   This code is developed and maintained in conjunction with the
   Jaccwabyt project:

   https://fossil.wanderinghorse.net/r/jaccwabbyt

   More specifically:

   https://fossil.wanderinghorse.net/r/jaccwabbyt/file/common/whwasmutil.js
*/
self.WhWasmUtilInstaller = function(target){
  'use strict';
  if(undefined===target.bigIntEnabled){
    target.bigIntEnabled = !!self['BigInt64Array'];
  }

  /** Throws a new Error, the message of which is the concatenation of
      all args with a space between each. */
  const toss = (...args)=>{throw new Error(args.join(' '))};

  if(!target.exports){
    Object.defineProperty(target, 'exports', {
      enumerable: true, configurable: true,
      get: ()=>(target.instance && target.instance.exports)
    });
  }

  /*********
    alloc()/dealloc() auto-install...

    This would be convenient but it can also cause us to pick up
    malloc() even when the client code is using a different exported
    allocator (who, me?), which is bad. malloc() may be exported even
    if we're not explicitly using it and overriding the malloc()
    function, linking ours first, is not always feasible when using a
    malloc() proxy, as it can lead to recursion and stack overflow
    (who, me?). So... we really need the downstream code to set up
    target.alloc/dealloc() itself.
  ******/
  /******
  if(target.exports){
    //Maybe auto-install alloc()/dealloc()...
    if(!target.alloc && target.exports.malloc){
      target.alloc = function(n){
        const m = this(n);
        return m || toss("Allocation of",n,"byte(s) failed.");
      }.bind(target.exports.malloc);
    }

    if(!target.dealloc && target.exports.free){
      target.dealloc = function(ptr){
        if(ptr) this(ptr);
      }.bind(target.exports.free);
    }
  }*******/

  /**
     Pointers in WASM are currently assumed to be 32-bit, but someday
     that will certainly change.
  */
  const ptrIR = target.pointerIR || 'i32';
  const ptrSizeof = target.ptrSizeof =
        ('i32'===ptrIR ? 4
         : ('i64'===ptrIR
            ? 8 : toss("Unhandled ptrSizeof:",ptrIR)));
  /** Stores various cached state. */
  const cache = Object.create(null);
  /** Previously-recorded size of cache.memory.buffer, noted so that
      we can recreate the view objects if the heap grows. */
  cache.heapSize = 0;
  /** WebAssembly.Memory object extracted from target.memory or
      target.exports.memory the first time heapWrappers() is
      called. */
  cache.memory = null;
  /** uninstallFunction() puts table indexes in here for reuse and
      installFunction() extracts them. */
  cache.freeFuncIndexes = [];
  /**
     Used by scopedAlloc() and friends.
  */
  cache.scopedAlloc = [];

  cache.utf8Decoder = new TextDecoder();
  cache.utf8Encoder = new TextEncoder('utf-8');

  /**
     For the given IR-like string in the set ('i8', 'i16', 'i32',
     'f32', 'float', 'i64', 'f64', 'double', '*'), or any string value
     ending in '*', returns the sizeof for that value
     (target.ptrSizeof in the latter case). For any other value, it
     returns the undefined value.
  */
  target.sizeofIR = (n)=>{
    switch(n){
        case 'i8': return 1;
        case 'i16': return 2;
        case 'i32': case 'f32': case 'float': return 4;
        case 'i64': case 'f64': case 'double': return 8;
        case '*': return ptrSizeof;
        default:
          return (''+n).endsWith('*') ? ptrSizeof : undefined;
    }
  };

  /**
     If (cache.heapSize !== cache.memory.buffer.byteLength), i.e. if
     the heap has grown since the last call, updates cache.HEAPxyz.
     Returns the cache object.
  */
  const heapWrappers = function(){
    if(!cache.memory){
      cache.memory = (target.memory instanceof WebAssembly.Memory)
        ? target.memory : target.exports.memory;
    }else if(cache.heapSize === cache.memory.buffer.byteLength){
      return cache;
    }
    // heap is newly-acquired or has been resized....
    const b = cache.memory.buffer;
    cache.HEAP8 = new Int8Array(b); cache.HEAP8U = new Uint8Array(b);
    cache.HEAP16 = new Int16Array(b); cache.HEAP16U = new Uint16Array(b);
    cache.HEAP32 = new Int32Array(b); cache.HEAP32U = new Uint32Array(b);
    if(target.bigIntEnabled){
      cache.HEAP64 = new BigInt64Array(b); cache.HEAP64U = new BigUint64Array(b);
    }
    cache.HEAP32F = new Float32Array(b); cache.HEAP64F = new Float64Array(b);
    cache.heapSize = b.byteLength;
    return cache;
  };

  /** Convenience equivalent of this.heapForSize(8,false). */
  target.heap8 = ()=>heapWrappers().HEAP8;

  /** Convenience equivalent of this.heapForSize(8,true). */
  target.heap8u = ()=>heapWrappers().HEAP8U;

  /** Convenience equivalent of this.heapForSize(16,false). */
  target.heap16 = ()=>heapWrappers().HEAP16;

  /** Convenience equivalent of this.heapForSize(16,true). */
  target.heap16u = ()=>heapWrappers().HEAP16U;

  /** Convenience equivalent of this.heapForSize(32,false). */
  target.heap32 = ()=>heapWrappers().HEAP32;

  /** Convenience equivalent of this.heapForSize(32,true). */
  target.heap32u = ()=>heapWrappers().HEAP32U;

  /**
     Requires n to be one of:

     - integer 8, 16, or 32.
     - A integer-type TypedArray constructor: Int8Array, Int16Array,
     Int32Array, or their Uint counterparts.

     If this.bigIntEnabled is true, it also accepts the value 64 or a
     BigInt64Array/BigUint64Array, else it throws if passed 64 or one
     of those constructors.

     Returns an integer-based TypedArray view of the WASM heap
     memory buffer associated with the given block size. If passed
     an integer as the first argument and unsigned is truthy then
     the "U" (unsigned) variant of that view is returned, else the
     signed variant is returned. If passed a TypedArray value, the
     2nd argument is ignored. Note that Float32Array and
     Float64Array views are not supported by this function.

     Note that growth of the heap will invalidate any references to
     this heap, so do not hold a reference longer than needed and do
     not use a reference after any operation which may
     allocate. Instead, re-fetch the reference by calling this
     function again.

     Throws if passed an invalid n.

     Pedantic side note: the name "heap" is a bit of a misnomer. In a
     WASM environment, the stack and heap memory are all accessed via
     the same view(s) of the memory.
  */
  target.heapForSize = function(n,unsigned = true){
    let ctor;
    const c = (cache.memory && cache.heapSize === cache.memory.buffer.byteLength)
          ? cache : heapWrappers();
    switch(n){
        case Int8Array: return c.HEAP8; case Uint8Array: return c.HEAP8U;
        case Int16Array: return c.HEAP16; case Uint16Array: return c.HEAP16U;
        case Int32Array: return c.HEAP32; case Uint32Array: return c.HEAP32U;
        case 8:  return unsigned ? c.HEAP8U : c.HEAP8;
        case 16: return unsigned ? c.HEAP16U : c.HEAP16;
        case 32: return unsigned ? c.HEAP32U : c.HEAP32;
        case 64:
          if(c.HEAP64) return unsigned ? c.HEAP64U : c.HEAP64;
          break;
        default:
          if(target.bigIntEnabled){
            if(n===self['BigUint64Array']) return c.HEAP64U;
            else if(n===self['BigInt64Array']) return c.HEAP64;
            break;
          }
    }
    toss("Invalid heapForSize() size: expecting 8, 16, 32,",
         "or (if BigInt is enabled) 64.");
  };

  /**
     Returns the WASM-exported "indirect function table."
  */
  target.functionTable = function(){
    return target.exports.__indirect_function_table;
    /** -----------------^^^^^ "seems" to be a standardized export name.
        From Emscripten release notes from 2020-09-10:
        - Use `__indirect_function_table` as the import name for the
        table, which is what LLVM does.
    */
  };

  /**
     Given a function pointer, returns the WASM function table entry
     if found, else returns a falsy value: undefined if fptr is out of
     range or null if it's in range but the table entry is empty.
  */
  target.functionEntry = function(fptr){
    const ft = target.functionTable();
    return fptr < ft.length ? ft.get(fptr) : undefined;
  };

  /**
     Creates a WASM function which wraps the given JS function and
     returns the JS binding of that WASM function. The signature
     string must be the Jaccwabyt-format or Emscripten
     addFunction()-format function signature string. In short: in may
     have one of the following formats:

     - Emscripten: `"x..."`, where the first x is a letter representing
       the result type and subsequent letters represent the argument
       types. Functions with no arguments have only a single
       letter. See below.

     - Jaccwabyt: `"x(...)"` where `x` is the letter representing the
       result type and letters in the parens (if any) represent the
       argument types. Functions with no arguments use `x()`. See
       below.

     Supported letters:

     - `i` = int32
     - `p` = int32 ("pointer")
     - `j` = int64
     - `f` = float32
     - `d` = float64
     - `v` = void, only legal for use as the result type

     It throws if an invalid signature letter is used.

     Jaccwabyt-format signatures support some additional letters which
     have no special meaning here but (in this context) act as aliases
     for other letters:

     - `s`, `P`: same as `p`

     Sidebar: this code is developed together with Jaccwabyt, thus the
     support for its signature format.

     The arguments may be supplied in either order: (func,sig) or
     (sig,func).
  */
  target.jsFuncToWasm = function f(func, sig){
    /** Attribution: adapted up from Emscripten-generated glue code,
        refactored primarily for efficiency's sake, eliminating
        call-local functions and superfluous temporary arrays. */
    if(!f._){/*static init...*/
      f._ = {
        // Map of signature letters to type IR values
        sigTypes: Object.assign(Object.create(null),{
          i: 'i32', p: 'i32', P: 'i32', s: 'i32',
          j: 'i64', f: 'f32', d: 'f64'
        }),
        // Map of type IR values to WASM type code values
        typeCodes: Object.assign(Object.create(null),{
          f64: 0x7c, f32: 0x7d, i64: 0x7e, i32: 0x7f
        }),
        /** Encodes n, which must be <2^14 (16384), into target array
            tgt, as a little-endian value, using the given method
            ('push' or 'unshift'). */
        uleb128Encode: function(tgt, method, n){
          if(n<128) tgt[method](n);
          else tgt[method]( (n % 128) | 128, n>>7);
        },
        /** Intentionally-lax pattern for Jaccwabyt-format function
            pointer signatures, the intent of which is simply to
            distinguish them from Emscripten-format signatures. The
            downstream checks are less lax. */
        rxJSig: /^(\w)\((\w*)\)$/,
        /** Returns the parameter-value part of the given signature
            string. */
        sigParams: function(sig){
          const m = f._.rxJSig.exec(sig);
          return m ? m[2] : sig.substr(1);
        },
        /** Returns the IR value for the given letter or throws
            if the letter is invalid. */
        letterType: (x)=>f._.sigTypes[x] || toss("Invalid signature letter:",x),
        /** Returns an object describing the result type and parameter
            type(s) of the given function signature, or throws if the
            signature is invalid. */
        /******** // only valid for use with the WebAssembly.Function ctor, which
                  // is not yet documented on MDN.
        sigToWasm: function(sig){
          const rc = {parameters:[], results: []};
          if('v'!==sig[0]) rc.results.push(f.sigTypes(sig[0]));
          for(const x of f._.sigParams(sig)){
            rc.parameters.push(f._.typeCodes(x));
          }
          return rc;
        },************/
        /** Pushes the WASM data type code for the given signature
            letter to the given target array. Throws if letter is
            invalid. */
        pushSigType: (dest, letter)=>dest.push(f._.typeCodes[f._.letterType(letter)])
      };
    }/*static init*/
    if('string'===typeof func){
      const x = sig;
      sig = func;
      func = x;
    }
    const sigParams = f._.sigParams(sig);
    const wasmCode = [0x01/*count: 1*/, 0x60/*function*/];
    f._.uleb128Encode(wasmCode, 'push', sigParams.length);
    for(const x of sigParams) f._.pushSigType(wasmCode, x);
    if('v'===sig[0]) wasmCode.push(0);
    else{
      wasmCode.push(1);
      f._.pushSigType(wasmCode, sig[0]);
    }
    f._.uleb128Encode(wasmCode, 'unshift', wasmCode.length)/* type section length */;
    wasmCode.unshift(
      0x00, 0x61, 0x73, 0x6d, /* magic: "\0asm" */
      0x01, 0x00, 0x00, 0x00, /* version: 1 */
      0x01 /* type section code */
    );
    wasmCode.push(
      /* import section: */ 0x02, 0x07,
      /* (import "e" "f" (func 0 (type 0))): */
      0x01, 0x01, 0x65, 0x01, 0x66, 0x00, 0x00,
      /* export section: */ 0x07, 0x05,
      /* (export "f" (func 0 (type 0))): */
      0x01, 0x01, 0x66, 0x00, 0x00
    );
    return (new WebAssembly.Instance(
      new WebAssembly.Module(new Uint8Array(wasmCode)), {
        e: { f: func }
      })).exports['f'];
  }/*jsFuncToWasm()*/;

  /**
     Documented as target.installFunction() except for the 3rd
     argument: if truthy, the newly-created function pointer
     is stashed in the current scoped-alloc scope and will be
     cleaned up at the matching scopedAllocPop(), else it
     is not stashed there.
   */
  const __installFunction = function f(func, sig, scoped){
    if(scoped && !cache.scopedAlloc.length){
      toss("No scopedAllocPush() scope is active.");
    }
    if('string'===typeof func){
      const x = sig;
      sig = func;
      func = x;
    }
    if('string'!==typeof sig || !(func instanceof Function)){
      toss("Invalid arguments: expecting (function,signature) "+
           "or (signature,function).");
    }
    const ft = target.functionTable();
    const oldLen = ft.length;
    let ptr;
    while(cache.freeFuncIndexes.length){
      ptr = cache.freeFuncIndexes.pop();
      if(ft.get(ptr)){ /* Table was modified via a different API */
        ptr = null;
        continue;
      }else{
        break;
      }
    }
    if(!ptr){
      ptr = oldLen;
      ft.grow(1);
    }
    try{
      /*this will only work if func is a WASM-exported function*/
      ft.set(ptr, func);
      if(scoped){
        cache.scopedAlloc[cache.scopedAlloc.length-1].push(ptr);
      }
      return ptr;
    }catch(e){
      if(!(e instanceof TypeError)){
        if(ptr===oldLen) cache.freeFuncIndexes.push(oldLen);
        throw e;
      }
    }
    // It's not a WASM-exported function, so compile one...
    try {
      const fptr = target.jsFuncToWasm(func, sig);
      ft.set(ptr, fptr);
      if(scoped){
        cache.scopedAlloc[cache.scopedAlloc.length-1].push(ptr);
      }
    }catch(e){
      if(ptr===oldLen) cache.freeFuncIndexes.push(oldLen);
      throw e;
    }
    return ptr;
  };

  /**
     Expects a JS function and signature, exactly as for
     this.jsFuncToWasm(). It uses that function to create a
     WASM-exported function, installs that function to the next
     available slot of this.functionTable(), and returns the
     function's index in that table (which acts as a pointer to that
     function). The returned pointer can be passed to
     uninstallFunction() to uninstall it and free up the table slot for
     reuse.

     If passed (string,function) arguments then it treats the first
     argument as the signature and second as the function.

     As a special case, if the passed-in function is a WASM-exported
     function then the signature argument is ignored and func is
     installed as-is, without requiring re-compilation/re-wrapping.

     This function will propagate an exception if
     WebAssembly.Table.grow() throws or this.jsFuncToWasm() throws.
     The former case can happen in an Emscripten-compiled
     environment when building without Emscripten's
     `-sALLOW_TABLE_GROWTH` flag.

     Sidebar: this function differs from Emscripten's addFunction()
     _primarily_ in that it does not share that function's
     undocumented behavior of reusing a function if it's passed to
     addFunction() more than once, which leads to uninstallFunction()
     breaking clients which do not take care to avoid that case:

     https://github.com/emscripten-core/emscripten/issues/17323
  */
  target.installFunction = (func, sig)=>__installFunction(func, sig, false);

  /**
     EXPERIMENTAL! DO NOT USE IN CLIENT CODE!

     Works exactly like installFunction() but requires that a
     scopedAllocPush() is active and uninstalls the given function
     when that alloc scope is popped via scopedAllocPop().
     This is used for implementing JS/WASM function bindings which
     should only persist for the life of a call into a single
     C-side function.
  */
  target.scopedInstallFunction = (func, sig)=>__installFunction(func, sig, true);

  /**
     Requires a pointer value previously returned from
     this.installFunction(). Removes that function from the WASM
     function table, marks its table slot as free for re-use, and
     returns that function. It is illegal to call this before
     installFunction() has been called and results are undefined if
     ptr was not returned by that function. The returned function
     may be passed back to installFunction() to reinstall it.

     To simplify certain use cases, if passed a falsy non-0 value
     (noting that 0 is a valid function table index), this function
     has no side effects and returns undefined.
  */
  target.uninstallFunction = function(ptr){
    if(!ptr && 0!==ptr) return undefined;
    const fi = cache.freeFuncIndexes;
    const ft = target.functionTable();
    fi.push(ptr);
    const rc = ft.get(ptr);
    ft.set(ptr, null);
    return rc;
  };

  /**
     Given a WASM heap memory address and a data type name in the form
     (i8, i16, i32, i64, float (or f32), double (or f64)), this
     fetches the numeric value from that address and returns it as a
     number or, for the case of type='i64', a BigInt (noting that that
     type triggers an exception if this.bigIntEnabled is
     falsy). Throws if given an invalid type.

     If the first argument is an array, it is treated as an array of
     addresses and the result is an array of the values from each of
     those address, using the same 2nd argument for determining the
     value type to fetch.

     As a special case, if type ends with a `*`, it is considered to
     be a pointer type and is treated as the WASM numeric type
     appropriate for the pointer size (`i32`).

     While likely not obvious, this routine and its poke()
     counterpart are how pointer-to-value _output_ parameters
     in WASM-compiled C code can be interacted with:

     ```
     const ptr = alloc(4);
     poke(ptr, 0, 'i32'); // clear the ptr's value
     aCFuncWithOutputPtrToInt32Arg( ptr ); // e.g. void foo(int *x);
     const result = peek(ptr, 'i32'); // fetch ptr's value
     dealloc(ptr);
     ```

     scopedAlloc() and friends can be used to make handling of
     `ptr` safe against leaks in the case of an exception:

     ```
     let result;
     const scope = scopedAllocPush();
     try{
       const ptr = scopedAlloc(4);
       poke(ptr, 0, 'i32');
       aCFuncWithOutputPtrArg( ptr );
       result = peek(ptr, 'i32');
     }finally{
       scopedAllocPop(scope);
     }
     ```

     As a rule poke() must be called to set (typically zero
     out) the pointer's value, else it will contain an essentially
     random value.

     ACHTUNG: calling this often, e.g. in a loop, can have a noticably
     painful impact on performance. Rather than doing so, use
     heapForSize() to fetch the heap object and read directly from it.

     See: poke()
  */
  target.peek = function f(ptr, type='i8'){
    if(type.endsWith('*')) type = ptrIR;
    const c = (cache.memory && cache.heapSize === cache.memory.buffer.byteLength)
          ? cache : heapWrappers();
    const list = Array.isArray(ptr) ? [] : undefined;
    let rc;
    do{
      if(list) ptr = arguments[0].shift();
      switch(type){
          case 'i1':
          case 'i8': rc = c.HEAP8[ptr>>0]; break;
          case 'i16': rc = c.HEAP16[ptr>>1]; break;
          case 'i32': rc = c.HEAP32[ptr>>2]; break;
          case 'float': case 'f32': rc = c.HEAP32F[ptr>>2]; break;
          case 'double': case 'f64': rc = Number(c.HEAP64F[ptr>>3]); break;
          case 'i64':
            if(target.bigIntEnabled){
              rc = BigInt(c.HEAP64[ptr>>3]);
              break;
            }
            /* fallthru */
          default:
            toss('Invalid type for peek():',type);
      }
      if(list) list.push(rc);
    }while(list && arguments[0].length);
    return list || rc;
  };

  /**
     The counterpart of peek(), this sets a numeric value at
     the given WASM heap address, using the type to define how many
     bytes are written. Throws if given an invalid type. See
     peek() for details about the type argument. If the 3rd
     argument ends with `*` then it is treated as a pointer type and
     this function behaves as if the 3rd argument were `i32`.

     If the first argument is an array, it is treated like a list
     of pointers and the given value is written to each one.

     Returns `this`. (Prior to 2022-12-09 it returns this function.)

     ACHTUNG: calling this often, e.g. in a loop, can have a noticably
     painful impact on performance. Rather than doing so, use
     heapForSize() to fetch the heap object and assign directly to it
     or use the heap's set() method.
  */
  target.poke = function(ptr, value, type='i8'){
    if (type.endsWith('*')) type = ptrIR;
    const c = (cache.memory && cache.heapSize === cache.memory.buffer.byteLength)
          ? cache : heapWrappers();
    for(const p of (Array.isArray(ptr) ? ptr : [ptr])){
      switch (type) {
          case 'i1':
          case 'i8': c.HEAP8[p>>0] = value; continue;
          case 'i16': c.HEAP16[p>>1] = value; continue;
          case 'i32': c.HEAP32[p>>2] = value; continue;
          case 'float': case 'f32': c.HEAP32F[p>>2] = value; continue;
          case 'double': case 'f64': c.HEAP64F[p>>3] = value; continue;
          case 'i64':
            if(c.HEAP64){
              c.HEAP64[p>>3] = BigInt(value);
              continue;
            }
            /* fallthru */
          default:
            toss('Invalid type for poke(): ' + type);
      }
    }
    return this;
  };

  /**
     Convenience form of peek() intended for fetching
     pointer-to-pointer values. If passed a single non-array argument
     it returns the value of that one pointer address. If passed
     multiple arguments, or a single array of arguments, it returns an
     array of their values.
  */
  target.peekPtr = (...ptr)=>target.peek( (1===ptr.length ? ptr[0] : ptr), ptrIR );

  /**
     A variant of poke() intended for setting pointer-to-pointer
     values. Its differences from poke() are that (1) it defaults to a
     value of 0 and (2) it always writes to the pointer-sized heap
     view.
  */
  target.pokePtr = (ptr, value=0)=>target.poke(ptr, value, ptrIR);

  /**
     Convenience form of peek() intended for fetching i8 values. If
     passed a single non-array argument it returns the value of that
     one pointer address. If passed multiple arguments, or a single
     array of arguments, it returns an array of their values.
  */
  target.peek8 = (...ptr)=>target.peek( (1===ptr.length ? ptr[0] : ptr), 'i8' );
  /**
     Convience form of poke() intended for setting individual bytes.
     Its difference from poke() is that it always writes to the
     i8-sized heap view.
  */
  target.poke8 = (ptr, value)=>target.poke(ptr, value, 'i8');
  /** i16 variant of peek8(). */
  target.peek16 = (...ptr)=>target.peek( (1===ptr.length ? ptr[0] : ptr), 'i16' );
  /** i16 variant of poke8(). */
  target.poke16 = (ptr, value)=>target.poke(ptr, value, 'i16');
  /** i32 variant of peek8(). */
  target.peek32 = (...ptr)=>target.peek( (1===ptr.length ? ptr[0] : ptr), 'i32' );
  /** i32 variant of poke8(). */
  target.poke32 = (ptr, value)=>target.poke(ptr, value, 'i32');
  /** i64 variant of peek8(). Will throw if this build is not
      configured for BigInt support. */
  target.peek64 = (...ptr)=>target.peek( (1===ptr.length ? ptr[0] : ptr), 'i64' );
  /** i64 variant of poke8(). Will throw if this build is not
      configured for BigInt support. Note that this returns
      a BigInt-type value, not a Number-type value. */
  target.poke64 = (ptr, value)=>target.poke(ptr, value, 'i64');
  /** f32 variant of peek8(). */
  target.peek32f = (...ptr)=>target.peek( (1===ptr.length ? ptr[0] : ptr), 'f32' );
  /** f32 variant of poke8(). */
  target.poke32f = (ptr, value)=>target.poke(ptr, value, 'f32');
  /** f64 variant of peek8(). */
  target.peek64f = (...ptr)=>target.peek( (1===ptr.length ? ptr[0] : ptr), 'f64' );
  /** f64 variant of poke8(). */
  target.poke64f = (ptr, value)=>target.poke(ptr, value, 'f64');

  /** Deprecated alias for getMemValue() */
  target.getMemValue = target.peek;
  /** Deprecated alias for peekPtr() */
  target.getPtrValue = target.peekPtr;
  /** Deprecated alias for poke() */
  target.setMemValue = target.poke;
  /** Deprecated alias for pokePtr() */
  target.setPtrValue = target.pokePtr;

  /**
     Returns true if the given value appears to be legal for use as
     a WASM pointer value. Its _range_ of values is not (cannot be)
     validated except to ensure that it is a 32-bit integer with a
     value of 0 or greater. Likewise, it cannot verify whether the
     value actually refers to allocated memory in the WASM heap.
  */
  target.isPtr32 = (ptr)=>('number'===typeof ptr && (ptr===(ptr|0)) && ptr>=0);

  /**
     isPtr() is an alias for isPtr32(). If/when 64-bit WASM pointer
     support becomes widespread, it will become an alias for either
     isPtr32() or the as-yet-hypothetical isPtr64(), depending on a
     configuration option.
  */
  target.isPtr = target.isPtr32;

  /**
     Expects ptr to be a pointer into the WASM heap memory which
     refers to a NUL-terminated C-style string encoded as UTF-8.
     Returns the length, in bytes, of the string, as for `strlen(3)`.
     As a special case, if !ptr or if it's not a pointer then it
     returns `null`. Throws if ptr is out of range for
     target.heap8u().
  */
  target.cstrlen = function(ptr){
    if(!ptr || !target.isPtr(ptr)) return null;
    const h = heapWrappers().HEAP8U;
    let pos = ptr;
    for( ; h[pos] !== 0; ++pos ){}
    return pos - ptr;
  };

  /** Internal helper to use in operations which need to distinguish
      between SharedArrayBuffer heap memory and non-shared heap. */
  const __SAB = ('undefined'===typeof SharedArrayBuffer)
        ? function(){} : SharedArrayBuffer;
  const __utf8Decode = function(arrayBuffer, begin, end){
    return cache.utf8Decoder.decode(
      (arrayBuffer.buffer instanceof __SAB)
        ? arrayBuffer.slice(begin, end)
        : arrayBuffer.subarray(begin, end)
    );
  };

  /**
     Expects ptr to be a pointer into the WASM heap memory which
     refers to a NUL-terminated C-style string encoded as UTF-8. This
     function counts its byte length using cstrlen() then returns a
     JS-format string representing its contents. As a special case, if
     ptr is falsy or not a pointer, `null` is returned.
  */
  target.cstrToJs = function(ptr){
    const n = target.cstrlen(ptr);
    return n ? __utf8Decode(heapWrappers().HEAP8U, ptr, ptr+n) : (null===n ? n : "");
  };

  /**
     Given a JS string, this function returns its UTF-8 length in
     bytes. Returns null if str is not a string.
  */
  target.jstrlen = function(str){
    /** Attribution: derived from Emscripten's lengthBytesUTF8() */
    if('string'!==typeof str) return null;
    const n = str.length;
    let len = 0;
    for(let i = 0; i < n; ++i){
      let u = str.charCodeAt(i);
      if(u>=0xd800 && u<=0xdfff){
        u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt(++i) & 0x3FF);
      }
      if(u<=0x7f) ++len;
      else if(u<=0x7ff) len += 2;
      else if(u<=0xffff) len += 3;
      else len += 4;
    }
    return len;
  };

  /**
     Encodes the given JS string as UTF8 into the given TypedArray
     tgt, starting at the given offset and writing, at most, maxBytes
     bytes (including the NUL terminator if addNul is true, else no
     NUL is added). If it writes any bytes at all and addNul is true,
     it always NUL-terminates the output, even if doing so means that
     the NUL byte is all that it writes.

     If maxBytes is negative (the default) then it is treated as the
     remaining length of tgt, starting at the given offset.

     If writing the last character would surpass the maxBytes count
     because the character is multi-byte, that character will not be
     written (as opposed to writing a truncated multi-byte character).
     This can lead to it writing as many as 3 fewer bytes than
     maxBytes specifies.

     Returns the number of bytes written to the target, _including_
     the NUL terminator (if any). If it returns 0, it wrote nothing at
     all, which can happen if:

     - str is empty and addNul is false.
     - offset < 0.
     - maxBytes == 0.
     - maxBytes is less than the byte length of a multi-byte str[0].

     Throws if tgt is not an Int8Array or Uint8Array.

     Design notes:

     - In C's strcpy(), the destination pointer is the first
       argument. That is not the case here primarily because the 3rd+
       arguments are all referring to the destination, so it seems to
       make sense to have them grouped with it.

     - Emscripten's counterpart of this function (stringToUTF8Array())
       returns the number of bytes written sans NUL terminator. That
       is, however, ambiguous: str.length===0 or maxBytes===(0 or 1)
       all cause 0 to be returned.
  */
  target.jstrcpy = function(jstr, tgt, offset = 0, maxBytes = -1, addNul = true){
    /** Attribution: the encoding bits are taken from Emscripten's
        stringToUTF8Array(). */
    if(!tgt || (!(tgt instanceof Int8Array) && !(tgt instanceof Uint8Array))){
      toss("jstrcpy() target must be an Int8Array or Uint8Array.");
    }
    if(maxBytes<0) maxBytes = tgt.length - offset;
    if(!(maxBytes>0) || !(offset>=0)) return 0;
    let i = 0, max = jstr.length;
    const begin = offset, end = offset + maxBytes - (addNul ? 1 : 0);
    for(; i < max && offset < end; ++i){
      let u = jstr.charCodeAt(i);
      if(u>=0xd800 && u<=0xdfff){
        u = 0x10000 + ((u & 0x3FF) << 10) | (jstr.charCodeAt(++i) & 0x3FF);
      }
      if(u<=0x7f){
        if(offset >= end) break;
        tgt[offset++] = u;
      }else if(u<=0x7ff){
        if(offset + 1 >= end) break;
        tgt[offset++] = 0xC0 | (u >> 6);
        tgt[offset++] = 0x80 | (u & 0x3f);
      }else if(u<=0xffff){
        if(offset + 2 >= end) break;
        tgt[offset++] = 0xe0 | (u >> 12);
        tgt[offset++] = 0x80 | ((u >> 6) & 0x3f);
        tgt[offset++] = 0x80 | (u & 0x3f);
      }else{
        if(offset + 3 >= end) break;
        tgt[offset++] = 0xf0 | (u >> 18);
        tgt[offset++] = 0x80 | ((u >> 12) & 0x3f);
        tgt[offset++] = 0x80 | ((u >> 6) & 0x3f);
        tgt[offset++] = 0x80 | (u & 0x3f);
      }
    }
    if(addNul) tgt[offset++] = 0;
    return offset - begin;
  };

  /**
     Works similarly to C's strncpy(), copying, at most, n bytes (not
     characters) from srcPtr to tgtPtr. It copies until n bytes have
     been copied or a 0 byte is reached in src. _Unlike_ strncpy(), it
     returns the number of bytes it assigns in tgtPtr, _including_ the
     NUL byte (if any). If n is reached before a NUL byte in srcPtr,
     tgtPtr will _not_ be NULL-terminated. If a NUL byte is reached
     before n bytes are copied, tgtPtr will be NUL-terminated.

     If n is negative, cstrlen(srcPtr)+1 is used to calculate it, the
     +1 being for the NUL byte.

     Throws if tgtPtr or srcPtr are falsy. Results are undefined if:

     - either is not a pointer into the WASM heap or

     - srcPtr is not NUL-terminated AND n is less than srcPtr's
       logical length.

     ACHTUNG: it is possible to copy partial multi-byte characters
     this way, and converting such strings back to JS strings will
     have undefined results.
  */
  target.cstrncpy = function(tgtPtr, srcPtr, n){
    if(!tgtPtr || !srcPtr) toss("cstrncpy() does not accept NULL strings.");
    if(n<0) n = target.cstrlen(strPtr)+1;
    else if(!(n>0)) return 0;
    const heap = target.heap8u();
    let i = 0, ch;
    for(; i < n && (ch = heap[srcPtr+i]); ++i){
      heap[tgtPtr+i] = ch;
    }
    if(i<n) heap[tgtPtr + i++] = 0;
    return i;
  };

  /**
     For the given JS string, returns a Uint8Array of its contents
     encoded as UTF-8. If addNul is true, the returned array will have
     a trailing 0 entry, else it will not.
  */
  target.jstrToUintArray = (str, addNul=false)=>{
    return cache.utf8Encoder.encode(addNul ? (str+"\0") : str);
    // Or the hard way...
    /** Attribution: derived from Emscripten's stringToUTF8Array() */
    //const a = [], max = str.length;
    //let i = 0, pos = 0;
    //for(; i < max; ++i){
    //  let u = str.charCodeAt(i);
    //  if(u>=0xd800 && u<=0xdfff){
    //    u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt(++i) & 0x3FF);
    //  }
    //  if(u<=0x7f) a[pos++] = u;
    //  else if(u<=0x7ff){
    //    a[pos++] = 0xC0 | (u >> 6);
    //    a[pos++] = 0x80 | (u & 63);
    //  }else if(u<=0xffff){
    //    a[pos++] = 0xe0 | (u >> 12);
    //    a[pos++] = 0x80 | ((u >> 6) & 63);
    //    a[pos++] = 0x80 | (u & 63);
    //  }else{
    //    a[pos++] = 0xf0 | (u >> 18);
    //    a[pos++] = 0x80 | ((u >> 12) & 63);
    //    a[pos++] = 0x80 | ((u >> 6) & 63);
    //    a[pos++] = 0x80 | (u & 63);
    //  }
    // }
    // return new Uint8Array(a);
  };

  const __affirmAlloc = (obj,funcName)=>{
    if(!(obj.alloc instanceof Function) ||
       !(obj.dealloc instanceof Function)){
      toss("Object is missing alloc() and/or dealloc() function(s)",
           "required by",funcName+"().");
    }
  };

  const __allocCStr = function(jstr, returnWithLength, allocator, funcName){
    __affirmAlloc(target, funcName);
    if('string'!==typeof jstr) return null;
    if(0){/* older impl, possibly more widely compatible? */
      const n = target.jstrlen(jstr),
            ptr = allocator(n+1);
      target.jstrcpy(jstr, target.heap8u(), ptr, n+1, true);
      return returnWithLength ? [ptr, n] : ptr;
    }else{/* newer, (probably) faster and (certainly) simpler impl */
      const u = cache.utf8Encoder.encode(jstr),
            ptr = allocator(u.length+1),
            heap = heapWrappers().HEAP8U;
      heap.set(u, ptr);
      heap[ptr + u.length] = 0;
      return returnWithLength ? [ptr, u.length] : ptr;
    }
  };

  /**
     Uses target.alloc() to allocate enough memory for jstrlen(jstr)+1
     bytes of memory, copies jstr to that memory using jstrcpy(),
     NUL-terminates it, and returns the pointer to that C-string.
     Ownership of the pointer is transfered to the caller, who must
     eventually pass the pointer to dealloc() to free it.

     If passed a truthy 2nd argument then its return semantics change:
     it returns [ptr,n], where ptr is the C-string's pointer and n is
     its cstrlen().

     Throws if `target.alloc` or `target.dealloc` are not functions.
  */
  target.allocCString =
    (jstr, returnWithLength=false)=>__allocCStr(jstr, returnWithLength,
                                                target.alloc, 'allocCString()');

  /**
     Starts an "allocation scope." All allocations made using
     scopedAlloc() are recorded in this scope and are freed when the
     value returned from this function is passed to
     scopedAllocPop().

     This family of functions requires that the API's object have both
     `alloc()` and `dealloc()` methods, else this function will throw.

     Intended usage:

     ```
     const scope = scopedAllocPush();
     try {
       const ptr1 = scopedAlloc(100);
       const ptr2 = scopedAlloc(200);
       const ptr3 = scopedAlloc(300);
       ...
       // Note that only allocations made via scopedAlloc()
       // are managed by this allocation scope.
     }finally{
       scopedAllocPop(scope);
     }
     ```

     The value returned by this function must be treated as opaque by
     the caller, suitable _only_ for passing to scopedAllocPop().
     Its type and value are not part of this function's API and may
     change in any given version of this code.

     `scopedAlloc.level` can be used to determine how many scoped
     alloc levels are currently active.
   */
  target.scopedAllocPush = function(){
    __affirmAlloc(target, 'scopedAllocPush');
    const a = [];
    cache.scopedAlloc.push(a);
    return a;
  };

  /**
     Cleans up all allocations made using scopedAlloc() in the context
     of the given opaque state object, which must be a value returned
     by scopedAllocPush(). See that function for an example of how to
     use this function.

     Though scoped allocations are managed like a stack, this API
     behaves properly if allocation scopes are popped in an order
     other than the order they were pushed.

     If called with no arguments, it pops the most recent
     scopedAllocPush() result:

     ```
     scopedAllocPush();
     try{ ... } finally { scopedAllocPop(); }
     ```

     It's generally recommended that it be passed an explicit argument
     to help ensure that push/push are used in matching pairs, but in
     trivial code that may be a non-issue.
  */
  target.scopedAllocPop = function(state){
    __affirmAlloc(target, 'scopedAllocPop');
    const n = arguments.length
          ? cache.scopedAlloc.indexOf(state)
          : cache.scopedAlloc.length-1;
    if(n<0) toss("Invalid state object for scopedAllocPop().");
    if(0===arguments.length) state = cache.scopedAlloc[n];
    cache.scopedAlloc.splice(n,1);
    for(let p; (p = state.pop()); ){
      if(target.functionEntry(p)){
        //console.warn("scopedAllocPop() uninstalling transient function",p);
        target.uninstallFunction(p);
      }
      else target.dealloc(p);
    }
  };

  /**
     Allocates n bytes of memory using this.alloc() and records that
     fact in the state for the most recent call of scopedAllocPush().
     Ownership of the memory is given to scopedAllocPop(), which
     will clean it up when it is called. The memory _must not_ be
     passed to this.dealloc(). Throws if this API object is missing
     the required `alloc()` or `dealloc()` functions or no scoped
     alloc is active.

     See scopedAllocPush() for an example of how to use this function.

     The `level` property of this function can be queried to query how
     many scoped allocation levels are currently active.

     See also: scopedAllocPtr(), scopedAllocCString()
  */
  target.scopedAlloc = function(n){
    if(!cache.scopedAlloc.length){
      toss("No scopedAllocPush() scope is active.");
    }
    const p = target.alloc(n);
    cache.scopedAlloc[cache.scopedAlloc.length-1].push(p);
    return p;
  };

  Object.defineProperty(target.scopedAlloc, 'level', {
    configurable: false, enumerable: false,
    get: ()=>cache.scopedAlloc.length,
    set: ()=>toss("The 'active' property is read-only.")
  });

  /**
     Works identically to allocCString() except that it allocates the
     memory using scopedAlloc().

     Will throw if no scopedAllocPush() call is active.
  */
  target.scopedAllocCString =
    (jstr, returnWithLength=false)=>__allocCStr(jstr, returnWithLength,
                                                target.scopedAlloc, 'scopedAllocCString()');

  // impl for allocMainArgv() and scopedAllocMainArgv().
  const __allocMainArgv = function(isScoped, list){
    const pList = target[
      isScoped ? 'scopedAlloc' : 'alloc'
    ]((list.length + 1) * target.ptrSizeof);
    let i = 0;
    list.forEach((e)=>{
      target.pokePtr(pList + (target.ptrSizeof * i++),
                         target[
                           isScoped ? 'scopedAllocCString' : 'allocCString'
                         ](""+e));
    });
    target.pokePtr(pList + (target.ptrSizeof * i), 0);
    return pList;
  };

  /**
     Creates an array, using scopedAlloc(), suitable for passing to a
     C-level main() routine. The input is a collection with a length
     property and a forEach() method. A block of memory
     (list.length+1) entries long is allocated and each pointer-sized
     block of that memory is populated with a scopedAllocCString()
     conversion of the (""+value) of each element, with the exception
     that the final entry is a NULL pointer. Returns a pointer to the
     start of the list, suitable for passing as the 2nd argument to a
     C-style main() function.

     Throws if scopedAllocPush() is not active.

     Design note: the returned array is allocated with an extra NULL
     pointer entry to accommodate certain APIs, but client code which
     does not need that functionality should treat the returned array
     as list.length entries long.
  */
  target.scopedAllocMainArgv = (list)=>__allocMainArgv(true, list);

  /**
     Identical to scopedAllocMainArgv() but uses alloc() instead of
     scopedAlloc().
  */
  target.allocMainArgv = (list)=>__allocMainArgv(false, list);

  /**
     Expects to be given a C-style string array and its length. It
     returns a JS array of strings and/or nulls: any entry in the
     pArgv array which is NULL results in a null entry in the result
     array. If argc is 0 then an empty array is returned.

     Results are undefined if any entry in the first argc entries of
     pArgv are neither 0 (NULL) nor legal UTF-format C strings.

     To be clear, the expected C-style arguments to be passed to this
     function are `(int, char **)` (optionally const-qualified).
  */
  target.cArgvToJs = (argc, pArgv)=>{
    const list = [];
    for(let i = 0; i < argc; ++i){
      const arg = target.peekPtr(pArgv + (target.ptrSizeof * i));
      list.push( arg ? target.cstrToJs(arg) : null );
    }
    return list;
  };

  /**
     Wraps function call func() in a scopedAllocPush() and
     scopedAllocPop() block, such that all calls to scopedAlloc() and
     friends from within that call will have their memory freed
     automatically when func() returns. If func throws or propagates
     an exception, the scope is still popped, otherwise it returns the
     result of calling func().
  */
  target.scopedAllocCall = function(func){
    target.scopedAllocPush();
    try{ return func() } finally{ target.scopedAllocPop() }
  };

  /** Internal impl for allocPtr() and scopedAllocPtr(). */
  const __allocPtr = function(howMany, safePtrSize, method){
    __affirmAlloc(target, method);
    const pIr = safePtrSize ? 'i64' : ptrIR;
    let m = target[method](howMany * (safePtrSize ? 8 : ptrSizeof));
    target.poke(m, 0, pIr)
    if(1===howMany){
      return m;
    }
    const a = [m];
    for(let i = 1; i < howMany; ++i){
      m += (safePtrSize ? 8 : ptrSizeof);
      a[i] = m;
      target.poke(m, 0, pIr);
    }
    return a;
  };

  /**
     Allocates one or more pointers as a single chunk of memory and
     zeroes them out.

     The first argument is the number of pointers to allocate. The
     second specifies whether they should use a "safe" pointer size (8
     bytes) or whether they may use the default pointer size
     (typically 4 but also possibly 8).

     How the result is returned depends on its first argument: if
     passed 1, it returns the allocated memory address. If passed more
     than one then an array of pointer addresses is returned, which
     can optionally be used with "destructuring assignment" like this:

     ```
     const [p1, p2, p3] = allocPtr(3);
     ```

     ACHTUNG: when freeing the memory, pass only the _first_ result
     value to dealloc(). The others are part of the same memory chunk
     and must not be freed separately.

     The reason for the 2nd argument is..

     When one of the returned pointers will refer to a 64-bit value,
     e.g. a double or int64, an that value must be written or fetched,
     e.g. using poke() or peek(), it is important that
     the pointer in question be aligned to an 8-byte boundary or else
     it will not be fetched or written properly and will corrupt or
     read neighboring memory. It is only safe to pass false when the
     client code is certain that it will only get/fetch 4-byte values
     (or smaller).
  */
  target.allocPtr =
    (howMany=1, safePtrSize=true)=>__allocPtr(howMany, safePtrSize, 'alloc');

  /**
     Identical to allocPtr() except that it allocates using scopedAlloc()
     instead of alloc().
  */
  target.scopedAllocPtr =
    (howMany=1, safePtrSize=true)=>__allocPtr(howMany, safePtrSize, 'scopedAlloc');

  /**
     If target.exports[name] exists, it is returned, else an
     exception is thrown.
  */
  target.xGet = function(name){
    return target.exports[name] || toss("Cannot find exported symbol:",name);
  };

  const __argcMismatch =
        (f,n)=>toss(f+"() requires",n,"argument(s).");

  /**
     Looks up a WASM-exported function named fname from
     target.exports. If found, it is called, passed all remaining
     arguments, and its return value is returned to xCall's caller. If
     not found, an exception is thrown. This function does no
     conversion of argument or return types, but see xWrap() and
     xCallWrapped() for variants which do.

     As a special case, if passed only 1 argument after the name and
     that argument in an Array, that array's entries become the
     function arguments. (This is not an ambiguous case because it's
     not legal to pass an Array object to a WASM function.)
  */
  target.xCall = function(fname, ...args){
    const f = target.xGet(fname);
    if(!(f instanceof Function)) toss("Exported symbol",fname,"is not a function.");
    if(f.length!==args.length) __argcMismatch(fname,f.length)
    /* This is arguably over-pedantic but we want to help clients keep
       from shooting themselves in the foot when calling C APIs. */;
    return (2===arguments.length && Array.isArray(arguments[1]))
      ? f.apply(null, arguments[1])
      : f.apply(null, args);
  };

  /**
     State for use with xWrap()
  */
  cache.xWrap = Object.create(null);
  cache.xWrap.convert = Object.create(null);
  /** Map of type names to argument conversion functions. */
  cache.xWrap.convert.arg = new Map;
  /** Map of type names to return result conversion functions. */
  cache.xWrap.convert.result = new Map;
  const xArg = cache.xWrap.convert.arg, xResult = cache.xWrap.convert.result;

  if(target.bigIntEnabled){
    xArg.set('i64', (i)=>BigInt(i));
  }
  const __xArgPtr = 'i32' === ptrIR
        ? ((i)=>(i | 0)) : ((i)=>(BigInt(i) | BigInt(0)));
  xArg.set('i32', __xArgPtr )
    .set('i16', (i)=>((i | 0) & 0xFFFF))
    .set('i8', (i)=>((i | 0) & 0xFF))
    .set('f32', (i)=>Number(i).valueOf())
    .set('float', xArg.get('f32'))
    .set('f64', xArg.get('f32'))
    .set('double', xArg.get('f64'))
    .set('int', xArg.get('i32'))
    .set('null', (i)=>i)
    .set(null, xArg.get('null'))
    .set('**', __xArgPtr)
    .set('*', __xArgPtr);
  xResult.set('*', __xArgPtr)
    .set('pointer', __xArgPtr)
    .set('number', (v)=>Number(v))
    .set('void', (v)=>undefined)
    .set('null', (v)=>v)
    .set(null, xResult.get('null'));

  { /* Copy certain xArg[...] handlers to xResult[...] and
       add pointer-style variants of them. */
    const copyToResult = ['i8', 'i16', 'i32', 'int',
                          'f32', 'float', 'f64', 'double'];
    if(target.bigIntEnabled) copyToResult.push('i64');
    const adaptPtr = xArg.get(ptrIR);
    for(const t of copyToResult){
      xArg.set(t+'*', adaptPtr);
      xResult.set(t+'*', adaptPtr);
      xResult.set(t, (xArg.get(t) || toss("Missing arg converter:",t)));
    }
  }

  /**
     In order for args of type string to work in various contexts in
     the sqlite3 API, we need to pass them on as, variably, a C-string
     or a pointer value. Thus for ARGs of type 'string' and
     '*'/'pointer' we behave differently depending on whether the
     argument is a string or not:

     - If v is a string, scopeAlloc() a new C-string from it and return
       that temp string's pointer.

     - Else return the value from the arg adapter defined for ptrIR.

     TODO? Permit an Int8Array/Uint8Array and convert it to a string?
     Would that be too much magic concentrated in one place, ready to
     backfire? We handle that at the client level in sqlite3 with a
     custom argument converter.
  */
  const __xArgString = function(v){
    if('string'===typeof v) return target.scopedAllocCString(v);
    return v ? __xArgPtr(v) : null;
  };
  xArg.set('string', __xArgString)
    .set('utf8', __xArgString)
    .set('pointer', __xArgString);
  //xArg.set('*', __xArgString);

  xResult.set('string', (i)=>target.cstrToJs(i))
    .set('utf8', xResult.get('string'))
    .set('string:dealloc', (i)=>{
      try { return i ? target.cstrToJs(i) : null }
      finally{ target.dealloc(i) }
    })
    .set('utf8:dealloc', xResult.get('string:dealloc'))
    .set('json', (i)=>JSON.parse(target.cstrToJs(i)))
    .set('json:dealloc', (i)=>{
      try{ return i ? JSON.parse(target.cstrToJs(i)) : null }
      finally{ target.dealloc(i) }
    });

  /**
     Internal-use-only base class for FuncPtrAdapter and potentially
     additional stateful argument adapter classes.

     Note that its main interface (convertArg()) is strictly
     internal, not to be exposed to client code, as it may still
     need re-shaping. Only the constructors of concrete subclasses
     should be exposed to clients, and those in such a way that
     does not hinder internal redesign of the convertArg()
     interface.
  */
  const AbstractArgAdapter = class {
    constructor(opt){
      this.name = opt.name || 'unnamed adapter';
    }
    /**
       Gets called via xWrap() to "convert" v to whatever type
       this specific class supports.

       argIndex is the argv index of _this_ argument in the
       being-xWrap()'d call. argv is the current argument list
       undergoing xWrap() argument conversion. argv entries to the
       left of argIndex will have already undergone transformation and
       those to the right will not have (they will have the values the
       client-level code passed in, awaiting conversion). The RHS
       indexes must never be relied upon for anything because their
       types are indeterminate, whereas the LHS values will be
       WASM-compatible values by the time this is called.
    */
    convertArg(v,argv,argIndex){
      toss("AbstractArgAdapter must be subclassed.");
    }
  };

  /**
     An attempt at adding function pointer conversion support to
     xWrap(). This type is recognized by xWrap() as a proxy for
     converting a JS function to a C-side function, either
     permanently, for the duration of a single call into the C layer,
     or semi-contextual, where it may keep track of a single binding
     for a given context and uninstall the binding if it's replaced.

     The constructor requires an options object with these properties:

     - name (optional): string describing the function binding. This
       is solely for debugging and error-reporting purposes. If not
       provided, an empty string is assumed.

     - signature: a function signature string compatible with
       jsFuncToWasm().

     - bindScope (string): one of ('transient', 'context',
       'singleton'). Bind scopes are:

       - 'transient': it will convert JS functions to WASM only for
         the duration of the xWrap()'d function call, using
         scopedInstallFunction(). Before that call returns, the
         WASM-side binding will be uninstalled.

       - 'singleton': holds one function-pointer binding for this
         instance. If it's called with a different function pointer,
         it uninstalls the previous one after converting the new
         value. This is only useful for use with "global" functions
         which do not rely on any state other than this function
         pointer. If the being-converted function pointer is intended
         to be mapped to some sort of state object (e.g. an
         `sqlite3*`) then "context" (see below) is the proper mode.

       - 'context': similar to singleton mode but for a given
         "context", where the context is a key provided by the user
         and possibly dependent on a small amount of call-time
         context. This mode is the default if bindScope is _not_ set
         but a property named contextKey (described below) is.

       - 'permanent': the function is installed and left there
         forever. There is no way to recover its pointer address
         later on.

     - callProxy (function): if set, this must be a function which
       will act as a proxy for any "converted" JS function. It is
       passed the being-converted function value and must return
       either that function or a function which acts on its
       behalf. The returned function will be the one which gets
       installed into the WASM function table. The proxy must perform
       any required argument conversion (noting that it will be called
       from C code, so will receive C-format arguments) before passing
       them on to the being-converted function. Whether or not the
       proxy itself must return a value depends on the context. If it
       does, it must be a WASM-friendly value, as it will be returning
       from a call made from native code.

     - contextKey (function): is only used if bindScope is 'context'
       or if bindScope is not set and this function is, in which case
       'context' is assumed. This function gets bound to this object,
       so its "this" is this object. It gets passed (argv,argIndex),
       where argIndex is the index of _this_ function pointer in its
       _wrapping_ function's arguments and argv is the _current_
       still-being-xWrap()-processed args array. All arguments to the
       left of argIndex will have been processed by xWrap() by the
       time this is called. argv[argIndex] will be the value the user
       passed in to the xWrap()'d function for the argument this
       FuncPtrAdapter is mapped to. Arguments to the right of
       argv[argIndex] will not yet have been converted before this is
       called. The function must return a key which uniquely
       identifies this function mapping context for _this_
       FuncPtrAdapter instance (other instances are not considered),
       taking into account that C functions often take some sort of
       state object as one or more of their arguments. As an example,
       if the xWrap()'d function takes `(int,T*,functionPtr,X*)` and
       this FuncPtrAdapter is the argv[2]nd arg, contextKey(argv,2)
       might return 'T@'+argv[1], or even just argv[1].  Note,
       however, that the (X*) argument will not yet have been
       processed by the time this is called and should not be used as
       part of that key because its pre-conversion data type might be
       unpredictable. Similarly, care must be taken with C-string-type
       arguments: those to the left in argv will, when this is called,
       be WASM pointers, whereas those to the right might (and likely
       do) have another data type. When using C-strings in keys, never
       use their pointers in the key because most C-strings in this
       constellation are transient.

     Yes, that ^^^ is quite awkward, but it's what we have.

     The constructor only saves the above state for later, and does
     not actually bind any functions. Its convertArg() method is
     called via xWrap() to perform any bindings.

     Shortcomings:

     - These "reverse" bindings, i.e. calling into a JS-defined
       function from a WASM-defined function (the generated proxy
       wrapper), lack all type conversion support. That means, for
       example, that...

     - Function pointers which include C-string arguments may still
       need a level of hand-written wrappers around them, depending on
       how they're used, in order to provide the client with JS
       strings. Alternately, clients will need to perform such conversions
       on their own, e.g. using cstrtojs(). Or maybe we can find a way
       to perform such conversions here, via addition of an xWrap()-style
       function signature to the options argument.
  */
  xArg.FuncPtrAdapter = class FuncPtrAdapter extends AbstractArgAdapter {
    constructor(opt) {
      super(opt);
      if(xArg.FuncPtrAdapter.warnOnUse){
        console.warn('xArg.FuncPtrAdapter is an internal-only API',
                     'and is not intended to be invoked from',
                     'client-level code. Invoked with:',opt);
      }
      this.signature = opt.signature;
      if(opt.contextKey instanceof Function){
        this.contextKey = opt.contextKey;
        if(!opt.bindScope) opt.bindScope = 'context';
      }
      this.bindScope = opt.bindScope
        || toss("FuncPtrAdapter options requires a bindScope (explicit or implied).");
      if(FuncPtrAdapter.bindScopes.indexOf(opt.bindScope)<0){
        toss("Invalid options.bindScope ("+opt.bindMod+") for FuncPtrAdapter. "+
             "Expecting one of: ("+FuncPtrAdapter.bindScopes.join(', ')+')');
      }
      this.isTransient = 'transient'===this.bindScope;
      this.isContext = 'context'===this.bindScope;
      this.isPermanent = 'permanent'===this.bindScope;
      this.singleton = ('singleton'===this.bindScope) ? [] : undefined;
      //console.warn("FuncPtrAdapter()",opt,this);
      this.callProxy = (opt.callProxy instanceof Function)
        ? opt.callProxy : undefined;
    }

    /** If true, the constructor emits a warning. The intent is that
        this be set to true after bootstrapping of the higher-level
        client library is complete, to warn downstream clients that
        they shouldn't be relying on this implemenation detail which
        does not have a stable interface. */
    static warnOnUse = false;

    /** If true, convertArg() will FuncPtrAdapter.debugOut() when it
        (un)installs a function binding to/from WASM. Note that
        deinstallation of bindScope=transient bindings happens
        via scopedAllocPop() so will not be output. */
    static debugFuncInstall = false;

    /** Function used for debug output. */
    static debugOut = console.debug.bind(console);

    static bindScopes = [
      'transient', 'context', 'singleton', 'permanent'
    ];

    /* Dummy impl. Overwritten per-instance as needed. */
    contextKey(argv,argIndex){
      return this;
    }

    /* Returns this objects mapping for the given context key, in the
       form of an an array, creating the mapping if needed. The key
       may be anything suitable for use in a Map. */
    contextMap(key){
      const cm = (this.__cmap || (this.__cmap = new Map));
      let rc = cm.get(key);
      if(undefined===rc) cm.set(key, (rc = []));
      return rc;
    }

    /**
       Gets called via xWrap() to "convert" v to a WASM-bound function
       pointer. If v is one of (a pointer, null, undefined) then
       (v||0) is returned and any earlier function installed by this
       mapping _might_, depending on how it's bound, be uninstalled.
       If v is not one of those types, it must be a Function, for
       which it creates (if needed) a WASM function binding and
       returns the WASM pointer to that binding. If this instance is
       not in 'transient' mode, it will remember the binding for at
       least the next call, to avoid recreating the function binding
       unnecessarily.

       If it's passed a pointer(ish) value for v, it does _not_
       perform any function binding, so this object's bindMode is
       irrelevant for such cases.

       See the parent class's convertArg() docs for details on what
       exactly the 2nd and 3rd arguments are.
    */
    convertArg(v,argv,argIndex){
      //FuncPtrAdapter.debugOut("FuncPtrAdapter.convertArg()",this.signature,this.transient,v);
      let pair = this.singleton;
      if(!pair && this.isContext){
        pair = this.contextMap(this.contextKey(argv,argIndex));
      }
      if(pair && pair[0]===v) return pair[1];
      if(v instanceof Function){
        /* Install a WASM binding and return its pointer. */
        if(this.callProxy) v = this.callProxy(v);
        const fp = __installFunction(v, this.signature, this.isTransient);
        if(FuncPtrAdapter.debugFuncInstall){
          FuncPtrAdapter.debugOut("FuncPtrAdapter installed", this,
                                  this.contextKey(argv,argIndex), '@'+fp, v);
        }
        if(pair){
          /* Replace existing stashed mapping */
          if(pair[1]){
            if(FuncPtrAdapter.debugFuncInstall){
              FuncPtrAdapter.debugOut("FuncPtrAdapter uninstalling", this,
                                      this.contextKey(argv,argIndex), '@'+pair[1], v);
            }
            try{target.uninstallFunction(pair[1])}
            catch(e){/*ignored*/}
          }
          pair[0] = v;
          pair[1] = fp;
        }
        return fp;
      }else if(target.isPtr(v) || null===v || undefined===v){
        if(pair && pair[1] && pair[1]!==v){
          /* uninstall stashed mapping and replace stashed mapping with v. */
          if(FuncPtrAdapter.debugFuncInstall){
            FuncPtrAdapter.debugOut("FuncPtrAdapter uninstalling", this,
                                    this.contextKey(argv,argIndex), '@'+pair[1], v);
          }
          try{target.uninstallFunction(pair[1])}
          catch(e){/*ignored*/}
          pair[0] = pair[1] = (v | 0);
        }
        return v || 0;
      }else{
        throw new TypeError("Invalid FuncPtrAdapter argument type. "+
                            "Expecting a function pointer or a "+
                            (this.name ? this.name+' ' : '')+
                            "function matching signature "+
                            this.signature+".");
      }
    }/*convertArg()*/
  }/*FuncPtrAdapter*/;

  const __xArgAdapterCheck =
        (t)=>xArg.get(t) || toss("Argument adapter not found:",t);

  const __xResultAdapterCheck =
        (t)=>xResult.get(t) || toss("Result adapter not found:",t);

  cache.xWrap.convertArg = (t,...args)=>__xArgAdapterCheck(t)(...args);
  cache.xWrap.convertArgNoCheck = (t,...args)=>xArg.get(t)(...args);

  cache.xWrap.convertResult =
    (t,v)=>(null===t ? v : (t ? __xResultAdapterCheck(t)(v) : undefined));
  cache.xWrap.convertResultNoCheck =
    (t,v)=>(null===t ? v : (t ? xResult.get(t)(v) : undefined));

  /**
     Creates a wrapper for another function which converts the arguments
     of the wrapper to argument types accepted by the wrapped function,
     then converts the wrapped function's result to another form
     for the wrapper.

     The first argument must be one of:

     - A JavaScript function.
     - The name of a WASM-exported function. In the latter case xGet()
       is used to fetch the exported function, which throws if it's not
       found.
     - A pointer into the indirect function table. e.g. a pointer
       returned from target.installFunction().

     It returns either the passed-in function or a wrapper for that
     function which converts the JS-side argument types into WASM-side
     types and converts the result type.

     The second argument, `resultType`, describes the conversion for
     the wrapped functions result. A literal `null` or the string
     `'null'` both mean to return the original function's value as-is
     (mnemonic: there is "null" conversion going on). Literal
     `undefined` or the string `"void"` both mean to ignore the
     function's result and return `undefined`. Aside from those two
     special cases, the `resultType` value may be one of the values
     described below or any mapping installed by the client using
     xWrap.resultAdapter().

     If passed 3 arguments and the final one is an array, that array
     must contain a list of type names (see below) for adapting the
     arguments from JS to WASM.  If passed 2 arguments, more than 3,
     or the 3rd is not an array, all arguments after the 2nd (if any)
     are treated as type names. i.e.:

     ```
     xWrap('funcname', 'i32', 'string', 'f64');
     // is equivalent to:
     xWrap('funcname', 'i32', ['string', 'f64']);
     ```

     This function enforces that the given list of arguments has the
     same arity as the being-wrapped function (as defined by its
     `length` property) and it will throw if that is not the case.
     Similarly, the created wrapper will throw if passed a differing
     argument count.

     Type names are symbolic names which map the arguments to an
     adapter function to convert, if needed, the value before passing
     it on to WASM or to convert a return result from WASM. The list
     of built-in names:

     - `i8`, `i16`, `i32` (args and results): all integer conversions
       which convert their argument to an integer and truncate it to
       the given bit length.

     - `N*` (args): a type name in the form `N*`, where N is a numeric
       type name, is treated the same as WASM pointer.

     - `*` and `pointer` (args): are assumed to be WASM pointer values
       and are returned coerced to an appropriately-sized pointer
       value (i32 or i64). Non-numeric values will coerce to 0 and
       out-of-range values will have undefined results (just as with
       any pointer misuse).

     - `*` and `pointer` (results): aliases for the current
       WASM pointer numeric type.

     - `**` (args): is simply a descriptive alias for the WASM pointer
       type. It's primarily intended to mark output-pointer arguments.

     - `i64` (args and results): passes the value to BigInt() to
       convert it to an int64. Only available if bigIntEnabled is
       true.

     - `f32` (`float`), `f64` (`double`) (args and results): pass
       their argument to Number(). i.e. the adapter does not currently
       distinguish between the two types of floating-point numbers.

     - `number` (results): converts the result to a JS Number using
       Number(theValue).valueOf(). Note that this is for result
       conversions only, as it's not possible to generically know
       which type of number to convert arguments to.

     Non-numeric conversions include:

     - `null` literal or `"null"` string (args and results): perform
       no translation and pass the arg on as-is. This is primarily
       useful for results but may have a use or two for arguments.

     - `string` or `utf8` (args): has two different semantics in order
       to accommodate various uses of certain C APIs
       (e.g. output-style strings)...

       - If the arg is a string, it creates a _temporary_
         UTF-8-encoded C-string to pass to the exported function,
         cleaning it up before the wrapper returns. If a long-lived
         C-string pointer is required, that requires client-side code
         to create the string, then pass its pointer to the function.

       - Else the arg is assumed to be a pointer to a string the
         client has already allocated and it's passed on as
         a WASM pointer.

     - `string` or `utf8` (results): treats the result value as a
       const C-string, encoded as UTF-8, copies it to a JS string,
       and returns that JS string.

     - `string:dealloc` or `utf8:dealloc) (results): treats the result value
       as a non-const UTF-8 C-string, ownership of which has just been
       transfered to the caller. It copies the C-string to a JS
       string, frees the C-string, and returns the JS string. If such
       a result value is NULL, the JS result is `null`. Achtung: when
       using an API which returns results from a specific allocator,
       e.g. `my_malloc()`, this conversion _is not legal_. Instead, an
       equivalent conversion which uses the appropriate deallocator is
       required. For example:

```js
   target.xWrap.resultAdapter('string:my_free',(i)=>{
      try { return i ? target.cstrToJs(i) : null }
      finally{ target.exports.my_free(i) }
   };
```

     - `json` (results): treats the result as a const C-string and
       returns the result of passing the converted-to-JS string to
       JSON.parse(). Returns `null` if the C-string is a NULL pointer.

     - `json:dealloc` (results): works exactly like `string:dealloc` but
       returns the same thing as the `json` adapter. Note the
       warning in `string:dealloc` regarding maching allocators and
       deallocators.

     The type names for results and arguments are validated when
     xWrap() is called and any unknown names will trigger an
     exception.

     Clients may map their own result and argument adapters using
     xWrap.resultAdapter() and xWrap.argAdapter(), noting that not all
     type conversions are valid for both arguments _and_ result types
     as they often have different memory ownership requirements.

     Design note: the ability to pass in a JS function as the first
     argument is of relatively limited use, primarily for testing
     argument and result converters. JS functions, by and large, will
     not want to deal with C-type arguments.

     TODOs:

     - Figure out how/whether we can (semi-)transparently handle
       pointer-type _output_ arguments. Those currently require
       explicit handling by allocating pointers, assigning them before
       the call using poke(), and fetching them with
       peek() after the call. We may be able to automate some
       or all of that.

     - Figure out whether it makes sense to extend the arg adapter
       interface such that each arg adapter gets an array containing
       the results of the previous arguments in the current call. That
       might allow some interesting type-conversion feature. Use case:
       handling of the final argument to sqlite3_prepare_v2() depends
       on the type (pointer vs JS string) of its 2nd
       argument. Currently that distinction requires hand-writing a
       wrapper for that function. That case is unusual enough that
       abstracting it into this API (and taking on the associated
       costs) may well not make good sense.
  */
  target.xWrap = function(fArg, resultType, ...argTypes){
    if(3===arguments.length && Array.isArray(arguments[2])){
      argTypes = arguments[2];
    }
    if(target.isPtr(fArg)){
      fArg = target.functionEntry(fArg)
        || toss("Function pointer not found in WASM function table.");
    }
    const fIsFunc = (fArg instanceof Function);
    const xf = fIsFunc ? fArg : target.xGet(fArg);
    if(fIsFunc) fArg = xf.name || 'unnamed function';
    if(argTypes.length!==xf.length) __argcMismatch(fArg, xf.length);
    if((null===resultType) && 0===xf.length){
      /* Func taking no args with an as-is return. We don't need a wrapper.
         We forego the argc check here, though. */
      return xf;
    }
    /*Verify the arg type conversions are valid...*/;
    if(undefined!==resultType && null!==resultType) __xResultAdapterCheck(resultType);
    for(const t of argTypes){
      if(t instanceof AbstractArgAdapter) xArg.set(t, (...args)=>t.convertArg(...args));
      else __xArgAdapterCheck(t);
    }
    const cxw = cache.xWrap;
    if(0===xf.length){
      // No args to convert, so we can create a simpler wrapper...
      return (...args)=>(args.length
                         ? __argcMismatch(fArg, xf.length)
                         : cxw.convertResult(resultType, xf.call(null)));
    }
    return function(...args){
      if(args.length!==xf.length) __argcMismatch(fArg, xf.length);
      const scope = target.scopedAllocPush();
      try{
        /*
          Maintenance reminder re. arguments passed to convertArg():
          The public interface of argument adapters is that they take
          ONE argument and return a (possibly) converted result for
          it. The passing-on of arguments after the first is an
          internal implementation detail for the sake of
          AbstractArgAdapter, and not to be relied on or documented
          for other cases. The fact that this is how
          AbstractArgAdapter.convertArgs() gets its 2nd+ arguments,
          and how FuncPtrAdapter.contextKey() gets its args, is also
          an implementation detail and subject to change. i.e. the
          public interface of 1 argument is stable.  The fact that any
          arguments may be passed in after that one, and what those
          arguments are, is _not_ part of the public interface and is
          _not_ stable.
        */
        for(const i in args) args[i] = cxw.convertArgNoCheck(
          argTypes[i], args[i], args, i
        );
        return cxw.convertResultNoCheck(resultType, xf.apply(null,args));
      }finally{
        target.scopedAllocPop(scope);
      }
    };
  }/*xWrap()*/;

  /** Internal impl for xWrap.resultAdapter() and argAdapter(). */
  const __xAdapter = function(func, argc, typeName, adapter, modeName, xcvPart){
    if('string'===typeof typeName){
      if(1===argc) return xcvPart.get(typeName);
      else if(2===argc){
        if(!adapter){
          delete xcvPart.get(typeName);
          return func;
        }else if(!(adapter instanceof Function)){
          toss(modeName,"requires a function argument.");
        }
        xcvPart.set(typeName, adapter);
        return func;
      }
    }
    toss("Invalid arguments to",modeName);
  };

  /**
     Gets, sets, or removes a result value adapter for use with
     xWrap(). If passed only 1 argument, the adapter function for the
     given type name is returned.  If the second argument is explicit
     falsy (as opposed to defaulted), the adapter named by the first
     argument is removed. If the 2nd argument is not falsy, it must be
     a function which takes one value and returns a value appropriate
     for the given type name. The adapter may throw if its argument is
     not of a type it can work with. This function throws for invalid
     arguments.

     Example:

     ```
     xWrap.resultAdapter('twice',(v)=>v+v);
     ```

     xWrap.resultAdapter() MUST NOT use the scopedAlloc() family of
     APIs to allocate a result value. xWrap()-generated wrappers run
     in the context of scopedAllocPush() so that argument adapters can
     easily convert, e.g., to C-strings, and have them cleaned up
     automatically before the wrapper returns to the caller. Likewise,
     if a _result_ adapter uses scoped allocation, the result will be
     freed before because they would be freed before the wrapper
     returns, leading to chaos and undefined behavior.

     Except when called as a getter, this function returns itself.
  */
  target.xWrap.resultAdapter = function f(typeName, adapter){
    return __xAdapter(f, arguments.length, typeName, adapter,
                      'resultAdapter()', xResult);
  };

  /**
     Functions identically to xWrap.resultAdapter() but applies to
     call argument conversions instead of result value conversions.

     xWrap()-generated wrappers perform argument conversion in the
     context of a scopedAllocPush(), so any memory allocation
     performed by argument adapters really, really, really should be
     made using the scopedAlloc() family of functions unless
     specifically necessary. For example:

     ```
     xWrap.argAdapter('my-string', function(v){
       return ('string'===typeof v)
         ? myWasmObj.scopedAllocCString(v) : null;
     };
     ```

     Contrariwise, xWrap.resultAdapter() must _not_ use scopedAlloc()
     to allocate its results because they would be freed before the
     xWrap()-created wrapper returns.

     Note that it is perfectly legitimate to use these adapters to
     perform argument validation, as opposed (or in addition) to
     conversion.
  */
  target.xWrap.argAdapter = function f(typeName, adapter){
    return __xAdapter(f, arguments.length, typeName, adapter,
                      'argAdapter()', xArg);
  };

  target.xWrap.FuncPtrAdapter = xArg.FuncPtrAdapter;

  /**
     Functions like xCall() but performs argument and result type
     conversions as for xWrap(). The first, second, and third
     arguments are as documented for xWrap(), except that the 3rd
     argument may be either a falsy value or empty array to represent
     nullary functions. The 4th+ arguments are arguments for the call,
     with the special case that if the 4th argument is an array, it is
     used as the arguments for the call. Returns the converted result
     of the call.

     This is just a thin wrapper around xWrap(). If the given function
     is to be called more than once, it's more efficient to use
     xWrap() to create a wrapper, then to call that wrapper as many
     times as needed. For one-shot calls, however, this variant is
     arguably more efficient because it will hypothetically free the
     wrapper function quickly.
  */
  target.xCallWrapped = function(fArg, resultType, argTypes, ...args){
    if(Array.isArray(arguments[3])) args = arguments[3];
    return target.xWrap(fArg, resultType, argTypes||[]).apply(null, args||[]);
  };

  /**
     This function is ONLY exposed in the public API to facilitate
     testing. It should not be used in application-level code, only
     in test code.

     Expects to be given (typeName, value) and returns a conversion
     of that value as has been registered using argAdapter().
     It throws if no adapter is found.

     ACHTUNG: the adapter may require that a scopedAllocPush() is
     active and it may allocate memory within that scope. It may also
     require additional arguments, depending on the type of
     conversion.
  */
  target.xWrap.testConvertArg = cache.xWrap.convertArg;

  /**
     This function is ONLY exposed in the public API to facilitate
     testing. It should not be used in application-level code, only
     in test code.

     Expects to be given (typeName, value) and returns a conversion
     of that value as has been registered using resultAdapter().
     It throws if no adapter is found.

     ACHTUNG: the adapter may allocate memory which the caller may need
     to know how to free.
  */
  target.xWrap.testConvertResult = cache.xWrap.convertResult;

  return target;
};

/**
   yawl (Yet Another Wasm Loader) provides very basic wasm loader.
   It requires a config object:

   - `uri`: required URI of the WASM file to load.

   - `onload(loadResult,config)`: optional callback. The first
     argument is the result object from
     WebAssembly.instantiate[Streaming](). The 2nd is the config
     object passed to this function. Described in more detail below.

   - `imports`: optional imports object for
     WebAssembly.instantiate[Streaming](). The default is an empty set
     of imports. If the module requires any imports, this object
     must include them.

   - `wasmUtilTarget`: optional object suitable for passing to
     WhWasmUtilInstaller(). If set, it gets passed to that function
     after the promise resolves. This function sets several properties
     on it before passing it on to that function (which sets many
     more):

     - `module`, `instance`: the properties from the
       instantiate[Streaming]() result.

     - If `instance.exports.memory` is _not_ set then it requires that
       `config.imports.env.memory` be set (else it throws), and
       assigns that to `target.memory`.

     - If `wasmUtilTarget.alloc` is not set and
       `instance.exports.malloc` is, it installs
       `wasmUtilTarget.alloc()` and `wasmUtilTarget.dealloc()`
       wrappers for the exports `malloc` and `free` functions.

   It returns a function which, when called, initiates loading of the
   module and returns a Promise. When that Promise resolves, it calls
   the `config.onload` callback (if set) and passes it
   `(loadResult,config)`, where `loadResult` is the result of
   WebAssembly.instantiate[Streaming](): an object in the form:

   ```
   {
     module: a WebAssembly.Module,
     instance: a WebAssembly.Instance
   }
   ```

   (Note that the initial `then()` attached to the promise gets only
   that object, and not the `config` one.)

   Error handling is up to the caller, who may attach a `catch()` call
   to the promise.
*/
self.WhWasmUtilInstaller.yawl = function(config){
  const wfetch = ()=>fetch(config.uri, {credentials: 'same-origin'});
  const wui = this;
  const finalThen = function(arg){
    //log("finalThen()",arg);
    if(config.wasmUtilTarget){
      const toss = (...args)=>{throw new Error(args.join(' '))};
      const tgt = config.wasmUtilTarget;
      tgt.module = arg.module;
      tgt.instance = arg.instance;
      //tgt.exports = tgt.instance.exports;
      if(!tgt.instance.exports.memory){
        /**
           WhWasmUtilInstaller requires either tgt.exports.memory
           (exported from WASM) or tgt.memory (JS-provided memory
           imported into WASM).
        */
        tgt.memory = (config.imports && config.imports.env
                      && config.imports.env.memory)
          || toss("Missing 'memory' object!");
      }
      if(!tgt.alloc && arg.instance.exports.malloc){
        const exports = arg.instance.exports;
        tgt.alloc = function(n){
          return exports.malloc(n) || toss("Allocation of",n,"bytes failed.");
        };
        tgt.dealloc = function(m){exports.free(m)};
      }
      wui(tgt);
    }
    if(config.onload) config.onload(arg,config);
    return arg /* for any then() handler attached to
                  yetAnotherWasmLoader()'s return value */;
  };
  const loadWasm = WebAssembly.instantiateStreaming
        ? function loadWasmStreaming(){
          return WebAssembly.instantiateStreaming(wfetch(), config.imports||{})
            .then(finalThen);
        }
        : function loadWasmOldSchool(){ // Safari < v15
          return wfetch()
            .then(response => response.arrayBuffer())
            .then(bytes => WebAssembly.instantiate(bytes, config.imports||{}))
            .then(finalThen);
        };
  return loadWasm;
}.bind(self.WhWasmUtilInstaller)/*yawl()*/;

Added ext/wasm/demo-123-worker.html.













































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<!doctype html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
    <title>Hello, sqlite3</title>
    <style>
      .warning, .error {color: red}
      .error {background-color: yellow}
      body {
          display: flex;
          flex-direction: column;
          font-family: monospace;
          white-space: break-spaces;
      }
    </style>
  </head>
  <body>
    <h1>1-2-sqlite3 worker demo</h1>
    <script>(function(){
      const logHtml = function(cssClass,...args){
        const ln = document.createElement('div');
        if(cssClass) ln.classList.add(cssClass);
        ln.append(document.createTextNode(args.join(' ')));
        document.body.append(ln);
      };
      const w = new Worker("demo-123.js?sqlite3.dir=jswasm"
                           /* Note the URL argument on that name. See
                              the notes in demo-123.js (search for
                              "importScripts") for why we need
                              that. */);
      w.onmessage = function({data}){
        switch(data.type){
            case 'log':
              logHtml(data.payload.cssClass, ...data.payload.args);
              break;
            default:
              logHtml('error',"Unhandled message:",data.type);
        };
      };
    })();</script>
  </body>
</html>

Added ext/wasm/demo-123.html.

























1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<!doctype html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
    <title>Hello, sqlite3</title>
    <style>
      .warning, .error {color: red}
      .error {background-color: yellow}
      body {
          display: flex;
          flex-direction: column;
          font-family: monospace;
          white-space: break-spaces;
      }
    </style>
  </head>
  <body>
    <h1>1-2-sqlite3 demo</h1>
    <script src="jswasm/sqlite3.js"></script>
    <script src="demo-123.js"></script>
  </body>
</html>

Added ext/wasm/demo-123.js.


































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
  2022-09-19

  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.

  ***********************************************************************

  A basic demonstration of the SQLite3 "OO#1" API.
*/
'use strict';
(function(){
  /**
     Set up our output channel differently depending
     on whether we are running in a worker thread or
     the main (UI) thread.
  */
  let logHtml;
  if(self.window === self /* UI thread */){
    console.log("Running demo from main UI thread.");
    logHtml = function(cssClass,...args){
      const ln = document.createElement('div');
      if(cssClass) ln.classList.add(cssClass);
      ln.append(document.createTextNode(args.join(' ')));
      document.body.append(ln);
    };
  }else{ /* Worker thread */
    console.log("Running demo from Worker thread.");
    logHtml = function(cssClass,...args){
      postMessage({
        type:'log',
        payload:{cssClass, args}
      });
    };
  }
  const log = (...args)=>logHtml('',...args);
  const warn = (...args)=>logHtml('warning',...args);
  const error = (...args)=>logHtml('error',...args);

  const demo1 = function(sqlite3){
    const capi = sqlite3.capi/*C-style API*/,
          oo = sqlite3.oo1/*high-level OO API*/;
    log("sqlite3 version",capi.sqlite3_libversion(), capi.sqlite3_sourceid());
    const db = new oo.DB("/mydb.sqlite3",'ct');
    log("transient db =",db.filename);
    /**
       Never(!) rely on garbage collection to clean up DBs and
       (especially) prepared statements. Always wrap their lifetimes
       in a try/finally construct, as demonstrated below. By and
       large, client code can entirely avoid lifetime-related
       complications of prepared statement objects by using the
       DB.exec() method for SQL execution.
    */
    try {
      log("Create a table...");
      db.exec("CREATE TABLE IF NOT EXISTS t(a,b)");
      //Equivalent:
      db.exec({
        sql:"CREATE TABLE IF NOT EXISTS t(a,b)"
        // ... numerous other options ... 
      });
      // SQL can be either a string or a byte array
      // or an array of strings which get concatenated
      // together as-is (so be sure to end each statement
      // with a semicolon).

      log("Insert some data using exec()...");
      let i;
      for( i = 20; i <= 25; ++i ){
        db.exec({
          sql: "insert into t(a,b) values (?,?)",
          // bind by parameter index...
          bind: [i, i*2]
        });
        db.exec({
          sql: "insert into t(a,b) values ($a,$b)",
          // bind by parameter name...
          bind: {$a: i * 10, $b: i * 20}
        });
      }    

      log("Insert using a prepared statement...");
      let q = db.prepare([
        // SQL may be a string or array of strings
        // (concatenated w/o separators).
        "insert into t(a,b) ",
        "values(?,?)"
      ]);
      try {
        for( i = 100; i < 103; ++i ){
          q.bind( [i, i*2] ).step();
          q.reset();
        }
        // Equivalent...
        for( i = 103; i <= 105; ++i ){
          q.bind(1, i).bind(2, i*2).stepReset();
        }
      }finally{
        q.finalize();
      }

      log("Query data with exec() using rowMode 'array'...");
      db.exec({
        sql: "select a from t order by a limit 3",
        rowMode: 'array', // 'array' (default), 'object', or 'stmt'
        callback: function(row){
          log("row ",++this.counter,"=",row);
        }.bind({counter: 0})
      });

      log("Query data with exec() using rowMode 'object'...");
      db.exec({
        sql: "select a as aa, b as bb from t order by aa limit 3",
        rowMode: 'object',
        callback: function(row){
          log("row ",++this.counter,"=",JSON.stringify(row));
        }.bind({counter: 0})
      });

      log("Query data with exec() using rowMode 'stmt'...");
      db.exec({
        sql: "select a from t order by a limit 3",
        rowMode: 'stmt',
        callback: function(row){
          log("row ",++this.counter,"get(0) =",row.get(0));
        }.bind({counter: 0})
      });

      log("Query data with exec() using rowMode INTEGER (result column index)...");
      db.exec({
        sql: "select a, b from t order by a limit 3",
        rowMode: 1, // === result column 1
        callback: function(row){
          log("row ",++this.counter,"b =",row);
        }.bind({counter: 0})
      });

      log("Query data with exec() using rowMode $COLNAME (result column name)...");
      db.exec({
        sql: "select a a, b from t order by a limit 3",
        rowMode: '$a',
        callback: function(value){
          log("row ",++this.counter,"a =",value);
        }.bind({counter: 0})
      });

      log("Query data with exec() without a callback...");
      let resultRows = [];
      db.exec({
        sql: "select a, b from t order by a limit 3",
        rowMode: 'object',
        resultRows: resultRows
      });
      log("Result rows:",JSON.stringify(resultRows,undefined,2));

      log("Create a scalar UDF...");
      db.createFunction({
        name: 'twice',
        xFunc: function(pCx, arg){ // note the call arg count
          return arg + arg;
        }
      });
      log("Run scalar UDF and collect result column names...");
      let columnNames = [];
      db.exec({
        sql: "select a, twice(a), twice(''||a) from t order by a desc limit 3",
        columnNames: columnNames,
        rowMode: 'stmt',
        callback: function(row){
          log("a =",row.get(0), "twice(a) =", row.get(1),
              "twice(''||a) =",row.get(2));
        }
      });
      log("Result column names:",columnNames);

      try{
        log("The following use of the twice() UDF will",
            "fail because of incorrect arg count...");
        db.exec("select twice(1,2,3)");
      }catch(e){
        warn("Got expected exception:",e.message);
      }

      try {
        db.transaction( function(D) {
          D.exec("delete from t");
          log("In transaction: count(*) from t =",db.selectValue("select count(*) from t"));
          throw new sqlite3.SQLite3Error("Demonstrating transaction() rollback");
        });
      }catch(e){
        if(e instanceof sqlite3.SQLite3Error){
          log("Got expected exception from db.transaction():",e.message);
          log("count(*) from t =",db.selectValue("select count(*) from t"));
        }else{
          throw e;
        }
      }

      try {
        db.savepoint( function(D) {
          D.exec("delete from t");
          log("In savepoint: count(*) from t =",db.selectValue("select count(*) from t"));
          D.savepoint(function(DD){
            const rows = [];
            DD.exec({
              sql: ["insert into t(a,b) values(99,100);",
                    "select count(*) from t"],
              rowMode: 0,
              resultRows: rows
            });
            log("In nested savepoint. Row count =",rows[0]);
            throw new sqlite3.SQLite3Error("Demonstrating nested savepoint() rollback");
          })
        });
      }catch(e){
        if(e instanceof sqlite3.SQLite3Error){
          log("Got expected exception from nested db.savepoint():",e.message);
          log("count(*) from t =",db.selectValue("select count(*) from t"));
        }else{
          throw e;
        }
      }
    }finally{
      db.close();
    }

    log("That's all, folks!");

    /**
       Some of the features of the OO API not demonstrated above...

       - get change count (total or statement-local, 32- or 64-bit)
       - get a DB's file name
    
       Misc. Stmt features:

       - Various forms of bind() 
       - clearBindings()
       - reset()
       - Various forms of step()
       - Variants of get() for explicit type treatment/conversion,
         e.g. getInt(), getFloat(), getBlob(), getJSON()
       - getColumnName(ndx), getColumnNames()
       - getParamIndex(name)
    */
  }/*demo1()*/;

  log("Loading and initializing sqlite3 module...");
  if(self.window!==self) /*worker thread*/{
    /*
      If sqlite3.js is in a directory other than this script, in order
      to get sqlite3.js to resolve sqlite3.wasm properly, we have to
      explicitly tell it where sqlite3.js is being loaded from. We do
      that by passing the `sqlite3.dir=theDirName` URL argument to
      _this_ script. That URL argument will be seen by the JS/WASM
      loader and it will adjust the sqlite3.wasm path accordingly. If
      sqlite3.js/.wasm are in the same directory as this script then
      that's not needed.

      URL arguments passed as part of the filename via importScripts()
      are simply lost, and such scripts see the self.location of
      _this_ script.
    */
    let sqlite3Js = 'sqlite3.js';
    const urlParams = new URL(self.location.href).searchParams;
    if(urlParams.has('sqlite3.dir')){
      sqlite3Js = urlParams.get('sqlite3.dir') + '/' + sqlite3Js;
    }
    importScripts(sqlite3Js);
  }
  self.sqlite3InitModule({
    // We can redirect any stdout/stderr from the module
    // like so...
    print: log,
    printErr: error
  }).then(function(sqlite3){
    //console.log('sqlite3 =',sqlite3);
    log("Done initializing. Running demo...");
    try {
      demo1(sqlite3);
    }catch(e){
      error("Exception:",e.message);
    }
  });
})();

Added ext/wasm/demo-jsstorage.html.


















































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<!doctype html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
    <link rel="stylesheet" href="common/emscripten.css"/>
    <link rel="stylesheet" href="common/testing.css"/>
    <title>sqlite3-kvvfs.js tests</title>
  </head>
  <body>
    <header id='titlebar'><span>sqlite3-kvvfs.js tests</span></header>
    <!-- emscripten bits -->
    <figure id="module-spinner">
      <div class="spinner"></div>
      <div class='center'><strong>Initializing app...</strong></div>
      <div class='center'>
        On a slow internet connection this may take a moment.  If this
        message displays for "a long time", intialization may have
        failed and the JavaScript console may contain clues as to why.
      </div>
    </figure>
    <div class="emscripten" id="module-status">Downloading...</div>
    <div class="emscripten">
      <progress value="0" max="100" id="module-progress" hidden='1'></progress>  
    </div><!-- /emscripten bits -->
    <fieldset>
      <legend>Options</legend>
      <div class='toolbar'>
        <button id='btn-clear-log'>Clear log</button>
        <button id='btn-clear-storage'>Clear storage</button>
        <button id='btn-init-db'>(Re)init db</button>
        <button id='btn-select1'>Select db rows</button>
        <button id='btn-storage-size'>Approx. storage size</button>
      </div>
    </fieldset>
    <div id='test-output'></div>
    <style>
      .toolbar {
          display: flex;
      }
      .toolbar > * { margin: 0.25em; }
      fieldset { border-radius: 0.5em; }
    </style>
    <script src="jswasm/sqlite3.js"></script>
    <script src="common/SqliteTestUtil.js"></script>
    <script src="demo-jsstorage.js"></script>
  </body>
</html>

Added ext/wasm/demo-jsstorage.js.



















































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
  2022-09-12

  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.

  ***********************************************************************

  A basic test script for sqlite3.wasm with kvvfs support. This file
  must be run in main JS thread and sqlite3.js must have been loaded
  before it.
*/
'use strict';
(function(){
  const T = self.SqliteTestUtil;
  const toss = function(...args){throw new Error(args.join(' '))};
  const debug = console.debug.bind(console);
  const eOutput = document.querySelector('#test-output');
  const logC = console.log.bind(console)
  const logE = function(domElement){
    eOutput.append(domElement);
  };
  const logHtml = function(cssClass,...args){
    const ln = document.createElement('div');
    if(cssClass) ln.classList.add(cssClass);
    ln.append(document.createTextNode(args.join(' ')));
    logE(ln);
  }
  const log = function(...args){
    logC(...args);
    logHtml('',...args);
  };
  const warn = function(...args){
    logHtml('warning',...args);
  };
  const error = function(...args){
    logHtml('error',...args);
  };
  
  const runTests = function(sqlite3){
    const capi = sqlite3.capi,
          oo = sqlite3.oo1,
          wasm = sqlite3.wasm;
    log("Loaded module:",capi.sqlite3_libversion(), capi.sqlite3_sourceid());
    T.assert( 0 !== capi.sqlite3_vfs_find(null) );
    if(!capi.sqlite3_vfs_find('kvvfs')){
      error("This build is not kvvfs-capable.");
      return;
    }
    
    const dbStorage = 0 ? 'session' : 'local';
    const theStore = 's'===dbStorage[0] ? sessionStorage : localStorage;
    const db = new oo.JsStorageDb( dbStorage );
    // Or: oo.DB(dbStorage, 'c', 'kvvfs')
    log("db.storageSize():",db.storageSize());
    document.querySelector('#btn-clear-storage').addEventListener('click',function(){
      const sz = db.clearStorage();
      log("kvvfs",db.filename+"Storage cleared:",sz,"entries.");
    });
    document.querySelector('#btn-clear-log').addEventListener('click',function(){
      eOutput.innerText = '';
    });
    document.querySelector('#btn-init-db').addEventListener('click',function(){
      try{
        const saveSql = [];
        db.exec({
          sql: ["drop table if exists t;",
                "create table if not exists t(a);",
                "insert into t(a) values(?),(?),(?)"],
          bind: [performance.now() >> 0,
                 (performance.now() * 2) >> 0,
                 (performance.now() / 2) >> 0],
          saveSql
        });
        console.log("saveSql =",saveSql,theStore);
        log("DB (re)initialized.");
      }catch(e){
        error(e.message);
      }
    });
    const btnSelect = document.querySelector('#btn-select1');
    btnSelect.addEventListener('click',function(){
      log("DB rows:");
      try{
        db.exec({
          sql: "select * from t order by a",
          rowMode: 0,
          callback: (v)=>log(v)
        });
      }catch(e){
        error(e.message);
      }
    });
    document.querySelector('#btn-storage-size').addEventListener('click',function(){
      log("size.storageSize(",dbStorage,") says", db.storageSize(),
          "bytes");
    });
    log("Storage backend:",db.filename);
    if(0===db.selectValue('select count(*) from sqlite_master')){
      log("DB is empty. Use the init button to populate it.");
    }else{
      log("DB contains data from a previous session. Use the Clear Ctorage button to delete it.");
      btnSelect.click();
    }
  };

  sqlite3InitModule(self.sqlite3TestModule).then((sqlite3)=>{
    runTests(sqlite3);
  });
})();

Added ext/wasm/demo-worker1-promiser.html.



































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<!doctype html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
    <link rel="stylesheet" href="common/emscripten.css"/>
    <link rel="stylesheet" href="common/testing.css"/>
    <title>worker-promise tests</title>
  </head>
  <body>
    <header id='titlebar'><span>worker-promise tests</span></header>
    <!-- emscripten bits -->
    <figure id="module-spinner">
      <div class="spinner"></div>
      <div class='center'><strong>Initializing app...</strong></div>
      <div class='center'>
        On a slow internet connection this may take a moment.  If this
        message displays for "a long time", intialization may have
        failed and the JavaScript console may contain clues as to why.
      </div>
    </figure>
    <div class="emscripten" id="module-status">Downloading...</div>
    <div class="emscripten">
      <progress value="0" max="100" id="module-progress" hidden='1'></progress>  
    </div><!-- /emscripten bits -->
    <div>Most stuff on this page happens in the dev console.</div>
    <hr>
    <div id='test-output'></div>
    <script src="common/SqliteTestUtil.js"></script>
    <script src="jswasm/sqlite3-worker1-promiser.js"></script>
    <script src="demo-worker1-promiser.js"></script>
  </body>
</html>

Added ext/wasm/demo-worker1-promiser.js.













































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
  2022-08-23

  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.

  ***********************************************************************
  
  Demonstration of the sqlite3 Worker API #1 Promiser: a Promise-based
  proxy for for the sqlite3 Worker #1 API.
*/
'use strict';
(function(){
  const T = self.SqliteTestUtil;
  const eOutput = document.querySelector('#test-output');
  const warn = console.warn.bind(console);
  const error = console.error.bind(console);
  const log = console.log.bind(console);
  const logHtml = async function(cssClass,...args){
    log.apply(this, args);
    const ln = document.createElement('div');
    if(cssClass) ln.classList.add(cssClass);
    ln.append(document.createTextNode(args.join(' ')));
    eOutput.append(ln);
  };

  let startTime;
  const testCount = async ()=>{
    logHtml("","Total test count:",T.counter+". Total time =",(performance.now() - startTime),"ms");
  };

  //why is this triggered even when we catch() a Promise?
  //window.addEventListener('unhandledrejection', function(event) {
  //  warn('unhandledrejection',event);
  //});

  const promiserConfig = {
    worker: ()=>{
      const w = new Worker("jswasm/sqlite3-worker1.js");
      w.onerror = (event)=>error("worker.onerror",event);
      return w;
    },
    debug: 1 ? undefined : (...args)=>console.debug('worker debug',...args),
    onunhandled: function(ev){
      error("Unhandled worker message:",ev.data);
    },
    onready: function(){
      self.sqlite3TestModule.setStatus(null)/*hide the HTML-side is-loading spinner*/;
      runTests();
    },
    onerror: function(ev){
      error("worker1 error:",ev);
    }
  };
  const workerPromise = self.sqlite3Worker1Promiser(promiserConfig);
  delete self.sqlite3Worker1Promiser;

  const wtest = async function(msgType, msgArgs, callback){
    if(2===arguments.length && 'function'===typeof msgArgs){
      callback = msgArgs;
      msgArgs = undefined;
    }
    const p = workerPromise({type: msgType, args:msgArgs});
    return callback ? p.then(callback).finally(testCount) : p;
  };

  const runTests = async function(){
    const dbFilename = '/testing2.sqlite3';
    startTime = performance.now();

    let sqConfig;
    await wtest('config-get', (ev)=>{
      const r = ev.result;
      log('sqlite3.config subset:', r);
      T.assert('boolean' === typeof r.bigIntEnabled);
      sqConfig = r;
    });
    logHtml('',
            "Sending 'open' message and waiting for its response before continuing...");
    
    await wtest('open', {
      filename: dbFilename,
      simulateError: 0 /* if true, fail the 'open' */,
    }, function(ev){
      const r = ev.result;
      log("then open result",r);
      T.assert(ev.dbId === r.dbId)
        .assert(ev.messageId)
        .assert('string' === typeof r.vfs);
      promiserConfig.dbId = ev.dbId;
    }).then(runTests2);
  };

  const runTests2 = async function(){
    const mustNotReach = ()=>toss("This is not supposed to be reached.");

    await wtest('exec',{
      sql: ["create table t(a,b)",
            "insert into t(a,b) values(1,2),(3,4),(5,6)"
           ].join(';'),
      multi: true,
      resultRows: [], columnNames: []
    }, function(ev){
      ev = ev.result;
      T.assert(0===ev.resultRows.length)
        .assert(0===ev.columnNames.length);
    });

    await wtest('exec',{
      sql: 'select a a, b b from t order by a',
      resultRows: [], columnNames: [],
    }, function(ev){
      ev = ev.result;
      T.assert(3===ev.resultRows.length)
        .assert(1===ev.resultRows[0][0])
        .assert(6===ev.resultRows[2][1])
        .assert(2===ev.columnNames.length)
        .assert('b'===ev.columnNames[1]);
    });

    await wtest('exec',{
      sql: 'select a a, b b from t order by a',
      resultRows: [], columnNames: [],
      rowMode: 'object'
    }, function(ev){
      ev = ev.result;
      T.assert(3===ev.resultRows.length)
        .assert(1===ev.resultRows[0].a)
        .assert(6===ev.resultRows[2].b)
    });

    await wtest(
      'exec',
      {sql:'intentional_error'},
      mustNotReach
    ).catch((e)=>{
      warn("Intentional error:",e);
    });

    await wtest('exec',{
      sql:'select 1 union all select 3',
      resultRows: [],
    }, function(ev){
      ev = ev.result;
      T.assert(2 === ev.resultRows.length)
        .assert(1 === ev.resultRows[0][0])
        .assert(3 === ev.resultRows[1][0]);
    });

    const resultRowTest1 = function f(ev){
      if(undefined === f.counter) f.counter = 0;
      if(null === ev.rowNumber){
        /* End of result set. */
        T.assert(undefined === ev.row)
          .assert(2===ev.columnNames.length)
          .assert('a'===ev.columnNames[0])
          .assert('B'===ev.columnNames[1]);
      }else{
        T.assert(ev.rowNumber > 0);
        ++f.counter;
      }
      log("exec() result row:",ev);
      T.assert(null === ev.rowNumber || 'number' === typeof ev.row.B);
    };
    await wtest('exec',{
      sql: 'select a a, b B from t order by a limit 3',
      callback: resultRowTest1,
      rowMode: 'object'
    }, function(ev){
      T.assert(3===resultRowTest1.counter);
      resultRowTest1.counter = 0;
    });

    const resultRowTest2 = function f(ev){
      if(null === ev.rowNumber){
        /* End of result set. */
        T.assert(undefined === ev.row)
          .assert(1===ev.columnNames.length)
          .assert('a'===ev.columnNames[0])
      }else{
        T.assert(ev.rowNumber > 0);
        f.counter = ev.rowNumber;
      }
      log("exec() result row:",ev);
      T.assert(null === ev.rowNumber || 'number' === typeof ev.row);
    };
    await wtest('exec',{
      sql: 'select a a from t limit 3',
      callback: resultRowTest2,
      rowMode: 0
    }, function(ev){
      T.assert(3===resultRowTest2.counter);
    });

    const resultRowTest3 = function f(ev){
      if(null === ev.rowNumber){
        T.assert(3===ev.columnNames.length)
          .assert('foo'===ev.columnNames[0])
          .assert('bar'===ev.columnNames[1])
          .assert('baz'===ev.columnNames[2]);
      }else{
        f.counter = ev.rowNumber;
        T.assert('number' === typeof ev.row);
      }
    };
    await wtest('exec',{
      sql: "select 'foo' foo, a bar, 'baz' baz  from t limit 2",
      callback: resultRowTest3,
      columnNames: [],
      rowMode: '$bar'
    }, function(ev){
      log("exec() result row:",ev);
      T.assert(2===resultRowTest3.counter);
    });

    await wtest('exec',{
      multi: true,
      sql:[
        'pragma foreign_keys=0;',
        // ^^^ arbitrary query with no result columns
        'select a, b from t order by a desc; select a from t;'
        // multi-exec only honors results from the first
        // statement with result columns (regardless of whether)
        // it has any rows).
      ],
      rowMode: 1,
      resultRows: []
    },function(ev){
      const rows = ev.result.resultRows;
      T.assert(3===rows.length).
        assert(6===rows[0]);
    });

    await wtest('exec',{sql: 'delete from t where a>3'});

    await wtest('exec',{
      sql: 'select count(a) from t',
      resultRows: []
    },function(ev){
      ev = ev.result;
      T.assert(1===ev.resultRows.length)
        .assert(2===ev.resultRows[0][0]);
    });

    await wtest('export', function(ev){
      ev = ev.result;
      T.assert('string' === typeof ev.filename)
        .assert(ev.byteArray instanceof Uint8Array)
        .assert(ev.byteArray.length > 1024)
        .assert('application/x-sqlite3' === ev.mimetype);
    });

    /***** close() tests must come last. *****/
    await wtest('close',{},function(ev){
      T.assert('string' === typeof ev.result.filename);
    });

    await wtest('close', (ev)=>{
      T.assert(undefined === ev.result.filename);
    }).finally(()=>logHtml('',"That's all, folks!"));
  }/*runTests2()*/;

  log("Init complete, but async init bits may still be running.");
})();

Added ext/wasm/demo-worker1.html.



































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

<!doctype html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
    <link rel="stylesheet" href="common/emscripten.css"/>
    <link rel="stylesheet" href="common/testing.css"/>
    <title>sqlite3-worker1.js tests</title>
  </head>
  <body>
    <header id='titlebar'><span>sqlite3-worker1.js tests</span></header>
    <!-- emscripten bits -->
    <figure id="module-spinner">
      <div class="spinner"></div>
      <div class='center'><strong>Initializing app...</strong></div>
      <div class='center'>
        On a slow internet connection this may take a moment.  If this
        message displays for "a long time", intialization may have
        failed and the JavaScript console may contain clues as to why.
      </div>
    </figure>
    <div class="emscripten" id="module-status">Downloading...</div>
    <div class="emscripten">
      <progress value="0" max="100" id="module-progress" hidden='1'></progress>  
    </div><!-- /emscripten bits -->
    <div>Most stuff on this page happens in the dev console.</div>
    <hr>
    <div id='test-output'></div>
    <script src="common/SqliteTestUtil.js"></script>
    <script src="demo-worker1.js"></script>
  </body>
</html>

Added ext/wasm/demo-worker1.js.


























































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
  2022-05-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.

  ***********************************************************************

  A basic test script for sqlite3-worker1.js.

  Note that the wrapper interface demonstrated in
  demo-worker1-promiser.js is much easier to use from client code, as it
  lacks the message-passing acrobatics demonstrated in this file.
*/
'use strict';
(function(){
  const T = self.SqliteTestUtil;
  const SW = new Worker("jswasm/sqlite3-worker1.js");
  const DbState = {
    id: undefined
  };
  const eOutput = document.querySelector('#test-output');
  const log = console.log.bind(console);
  const logHtml = function(cssClass,...args){
    log.apply(this, args);
    const ln = document.createElement('div');
    if(cssClass) ln.classList.add(cssClass);
    ln.append(document.createTextNode(args.join(' ')));
    eOutput.append(ln);
  };
  const warn = console.warn.bind(console);
  const error = console.error.bind(console);
  const toss = (...args)=>{throw new Error(args.join(' '))};

  SW.onerror = function(event){
    error("onerror",event);
  };

  let startTime;

  /**
     A queue for callbacks which are to be run in response to async
     DB commands. See the notes in runTests() for why we need
     this. The event-handling plumbing of this file requires that
     any DB command which includes a `messageId` property also have
     a queued callback entry, as the existence of that property in
     response payloads is how it knows whether or not to shift an
     entry off of the queue.
  */
  const MsgHandlerQueue = {
    queue: [],
    id: 0,
    push: function(type,callback){
      this.queue.push(callback);
      return type + '-' + (++this.id);
    },
    shift: function(){
      return this.queue.shift();
    }
  };
  
  const testCount = ()=>{
    logHtml("","Total test count:",T.counter+". Total time =",(performance.now() - startTime),"ms");
  };

  const logEventResult = function(ev){
    const evd = ev.result;
    logHtml(evd.errorClass ? 'error' : '',
            "runOneTest",ev.messageId,"Worker time =",
            (ev.workerRespondTime - ev.workerReceivedTime),"ms.",
            "Round-trip event time =",
            (performance.now() - ev.departureTime),"ms.",
            (evd.errorClass ? ev.message : "")//, JSON.stringify(evd)
           );
  };

  const runOneTest = function(eventType, eventArgs, callback){
    T.assert(eventArgs && 'object'===typeof eventArgs);
    /* ^^^ that is for the testing and messageId-related code, not
       a hard requirement of all of the Worker-exposed APIs. */
    const messageId = MsgHandlerQueue.push(eventType,function(ev){
      logEventResult(ev);
      if(callback instanceof Function){
        callback(ev);
        testCount();
      }
    });
    const msg = {
      type: eventType,
      args: eventArgs,
      dbId: DbState.id,
      messageId: messageId,
      departureTime: performance.now()
    };
    log("Posting",eventType,"message to worker dbId="+(DbState.id||'default')+':',msg);
    SW.postMessage(msg);
  };

  /** Methods which map directly to onmessage() event.type keys.
      They get passed the inbound event.data. */
  const dbMsgHandler = {
    open: function(ev){
      DbState.id = ev.dbId;
      log("open result",ev);
    },
    exec: function(ev){
      log("exec result",ev);
    },
    export: function(ev){
      log("export result",ev);
    },
    error: function(ev){
      error("ERROR from the worker:",ev);
      logEventResult(ev);
    },
    resultRowTest1: function f(ev){
      if(undefined === f.counter) f.counter = 0;
      if(null === ev.rowNumber){
        /* End of result set. */
        T.assert(undefined === ev.row)
          .assert(Array.isArray(ev.columnNames))
          .assert(ev.columnNames.length);
      }else{
        T.assert(ev.rowNumber > 0);
        ++f.counter;
      }
      //log("exec() result row:",ev);
      T.assert(null === ev.rowNumber || 'number' === typeof ev.row.b);
    }
  };

  /**
     "The problem" now is that the test results are async. We
     know, however, that the messages posted to the worker will
     be processed in the order they are passed to it, so we can
     create a queue of callbacks to handle them. The problem
     with that approach is that it's not error-handling
     friendly, in that an error can cause us to bypass a result
     handler queue entry. We have to perform some extra
     acrobatics to account for that.

     Problem #2 is that we cannot simply start posting events: we
     first have to post an 'open' event, wait for it to respond, and
     collect its db ID before continuing. If we don't wait, we may
     well fire off 10+ messages before the open actually responds.
  */
  const runTests2 = function(){
    const mustNotReach = ()=>{
      throw new Error("This is not supposed to be reached.");
    };
    runOneTest('exec',{
      sql: ["create table t(a,b);",
            "insert into t(a,b) values(1,2),(3,4),(5,6)"
           ],
      resultRows: [], columnNames: []
    }, function(ev){
      ev = ev.result;
      T.assert(0===ev.resultRows.length)
        .assert(0===ev.columnNames.length);
    });
    runOneTest('exec',{
      sql: 'select a a, b b from t order by a',
      resultRows: [], columnNames: [], saveSql:[]
    }, function(ev){
      ev = ev.result;
      T.assert(3===ev.resultRows.length)
        .assert(1===ev.resultRows[0][0])
        .assert(6===ev.resultRows[2][1])
        .assert(2===ev.columnNames.length)
        .assert('b'===ev.columnNames[1]);
    });
    //if(1){ error("Returning prematurely for testing."); return; }
    runOneTest('exec',{
      sql: 'select a a, b b from t order by a',
      resultRows: [], columnNames: [],
      rowMode: 'object'
    }, function(ev){
      ev = ev.result;
      T.assert(3===ev.resultRows.length)
        .assert(1===ev.resultRows[0].a)
        .assert(6===ev.resultRows[2].b)
    });
    runOneTest('exec',{sql:'intentional_error'}, mustNotReach);
    // Ensure that the message-handler queue survives ^^^ that error...
    runOneTest('exec',{
      sql:'select 1',
      resultRows: [],
      //rowMode: 'array', // array is the default in the Worker interface
    }, function(ev){
      ev = ev.result;
      T.assert(1 === ev.resultRows.length)
        .assert(1 === ev.resultRows[0][0]);
    });
    runOneTest('exec',{
      sql: 'select a a, b b from t order by a',
      callback: 'resultRowTest1',
      rowMode: 'object'
    }, function(ev){
      T.assert(3===dbMsgHandler.resultRowTest1.counter);
      dbMsgHandler.resultRowTest1.counter = 0;
    });
    runOneTest('exec',{
      sql:[
        "pragma foreign_keys=0;",
        // ^^^ arbitrary query with no result columns
        "select a, b from t order by a desc;",
        "select a from t;"
        // multi-statement exec only honors results from the first
        // statement with result columns (regardless of whether)
        // it has any rows).
      ],
      rowMode: 1,
      resultRows: []
    },function(ev){
      const rows = ev.result.resultRows;
      T.assert(3===rows.length).
        assert(6===rows[0]);
    });
    runOneTest('exec',{sql: 'delete from t where a>3'});
    runOneTest('exec',{
      sql: 'select count(a) from t',
      resultRows: []
    },function(ev){
      ev = ev.result;
      T.assert(1===ev.resultRows.length)
        .assert(2===ev.resultRows[0][0]);
    });
    runOneTest('export',{}, function(ev){
      ev = ev.result;
      log("export result:",ev);
      T.assert('string' === typeof ev.filename)
        .assert(ev.byteArray instanceof Uint8Array)
        .assert(ev.byteArray.length > 1024)
        .assert('application/x-sqlite3' === ev.mimetype);
    });
    /***** close() tests must come last. *****/
    runOneTest('close',{unlink:true},function(ev){
      ev = ev.result;
      T.assert('string' === typeof ev.filename);
    });
    runOneTest('close',{unlink:true},function(ev){
      ev = ev.result;
      T.assert(undefined === ev.filename);
      logHtml('warning',"This is the final test.");
    });
    logHtml('warning',"Finished posting tests. Waiting on async results.");
  };

  const runTests = function(){
    /**
       Design decision time: all remaining tests depend on the 'open'
       command having succeeded. In order to support multiple DBs, the
       upcoming commands ostensibly have to know the ID of the DB they
       want to talk to. We have two choices:

       1) We run 'open' and wait for its response, which contains the
       db id.

       2) We have the Worker automatically use the current "default
       db" (the one which was most recently opened) if no db id is
       provided in the message. When we do this, the main thread may
       well fire off _all_ of the test messages before the 'open'
       actually responds, but because the messages are handled on a
       FIFO basis, those after the initial 'open' will pick up the
       "default" db. However, if the open fails, then all pending
       messages (until next next 'open', at least) except for 'close'
       will fail and we have no way of cancelling them once they've
       been posted to the worker.

       Which approach we use below depends on the boolean value of
       waitForOpen.
    */
    const waitForOpen = 1,
          simulateOpenError = 0 /* if true, the remaining tests will
                                   all barf if waitForOpen is
                                   false. */;
    logHtml('',
            "Sending 'open' message and",(waitForOpen ? "" : "NOT ")+
            "waiting for its response before continuing.");
    startTime = performance.now();
    runOneTest('open', {
      filename:'testing2.sqlite3',
      simulateError: simulateOpenError
    }, function(ev){
      log("open result",ev);
      T.assert('testing2.sqlite3'===ev.result.filename)
        .assert(ev.dbId)
        .assert(ev.messageId)
        .assert('string' === typeof ev.result.vfs);
      DbState.id = ev.dbId;
      if(waitForOpen) setTimeout(runTests2, 0);
    });
    if(!waitForOpen) runTests2();
  };

  SW.onmessage = function(ev){
    if(!ev.data || 'object'!==typeof ev.data){
      warn("Unknown sqlite3-worker message type:",ev);
      return;
    }
    ev = ev.data/*expecting a nested object*/;
    //log("main window onmessage:",ev);
    if(ev.result && ev.messageId){
      /* We're expecting a queued-up callback handler. */
      const f = MsgHandlerQueue.shift();
      if('error'===ev.type){
        dbMsgHandler.error(ev);
        return;
      }
      T.assert(f instanceof Function);
      f(ev);
      return;
    }
    switch(ev.type){
        case 'sqlite3-api':
          switch(ev.result){
              case 'worker1-ready':
                log("Message:",ev);
                self.sqlite3TestModule.setStatus(null);
                runTests();
                return;
              default:
                warn("Unknown sqlite3-api message type:",ev);
                return;
          }
        default:
          if(dbMsgHandler.hasOwnProperty(ev.type)){
            try{dbMsgHandler[ev.type](ev);}
            catch(err){
              error("Exception while handling db result message",
                    ev,":",err);
            }
            return;
          }
          warn("Unknown sqlite3-api message type:",ev);
    }
  };
  log("Init complete, but async init bits may still be running.");
  log("Installing Worker into global scope SW for dev purposes.");
  self.SW = SW;
})();

Added ext/wasm/dist.make.



































































































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
#!/do/not/make
#^^^ help emacs select edit mode
#
# Intended to include'd by ./GNUmakefile.
#
# 'make dist' rules for creating a distribution archive of the WASM/JS
# pieces, noting that we only build a dist of the built files, not the
# numerous pieces required to build them.
#
# Use 'make snapshot' to create "snapshot" releases. They use a
# distinctly different zip file and top directory name to distinguish
# them from release builds.
#######################################################################
MAKEFILE.dist := $(lastword $(MAKEFILE_LIST))

########################################################################
# Chicken/egg situation: we need $(bin.version-info) to get the
# version info for the archive name, but that binary may not yet be
# built, and won't be built until we expand the dependencies. Thus we
# have to use a temporary name for the archive until we can get
# that binary built.
ifeq (,$(filter snapshot,$(MAKECMDGOALS)))
dist-name-prefix := sqlite-wasm
else
dist-name-prefix := sqlite-wasm-snapshot-$(shell /usr/bin/date +%Y%m%d)
endif
dist-name := $(dist-name-prefix)-TEMP

########################################################################
# dist.build must be the name of a target which triggers the build of
# the files to be packed into the dist archive.  The intention is that
# it be one of (o0, o1, o2, o3, os, oz), each of which uses like-named
# -Ox optimization level flags. The o2 target provides the best
# overall runtime speeds. The oz target provides slightly slower
# speeds (roughly 10%) with significantly smaller WASM file
# sizes. Note that -O2 (the o2 target) results in faster binaries than
# both -O3 and -Os (the o3 and os targets) in all tests run to
# date. Our general policy is that we want the smallest binaries for
# dist zip files, so use the oz build unless there is a compelling
# reason not to.
dist.build ?= qoz

dist-dir.top := $(dist-name)
dist-dir.jswasm := $(dist-dir.top)/$(notdir $(dir.dout))
dist-dir.common := $(dist-dir.top)/common
dist.top.extras := \
    demo-123.html demo-123-worker.html demo-123.js \
    tester1.html tester1-worker.html tester1-esm.html \
    tester1.js tester1.mjs \
    demo-jsstorage.html demo-jsstorage.js \
    demo-worker1.html demo-worker1.js \
    demo-worker1-promiser.html demo-worker1-promiser.js
dist.jswasm.extras := $(sqlite3-api.ext.jses) $(sqlite3.wasm)
dist.common.extras := \
    $(wildcard $(dir.common)/*.css) \
    $(dir.common)/SqliteTestUtil.js

.PHONY: dist snapshot
# DIST_STRIP_COMMENTS $(call)able to be used in stripping C-style
# from the dist copies of certain files.
#
#  $1 = source js file
#  $2 = flags for $(bin.stripcomments)
define DIST_STRIP_COMMENTS
$(bin.stripccomments) $(2) < $(1) > $(dist-dir.jswasm)/$(notdir $(1)) || exit;
endef
# STRIP_K1.js = list of JS files which need to be passed through
# $(bin.stripcomments) with a single -k flag.
STRIP_K1.js := $(sqlite3-worker1.js) $(sqlite3-worker1-promiser.js) \
  $(sqlite3-worker1-bundler-friendly.js) $(sqlite3-worker1-promiser-bundler-friendly.js)
# STRIP_K2.js = list of JS files which need to be passed through
# $(bin.stripcomments) with two -k flags.
STRIP_K2.js := $(sqlite3.js) $(sqlite3.mjs) $(sqlite3-bundler-friendly.mjs)
########################################################################
# dist: create the end-user deliverable archive.
#
# Maintenance reminder: because dist depends on $(dist.build), and
# $(dist.build) will depend on clean, having any deps on
# $(dist-archive) which themselves may be cleaned up by the clean
# target will lead to grief in parallel builds (-j #). Thus
# dist's deps must be trimmed to non-generated files or
# files which are _not_ cleaned up by the clean target.
#
# Note that we require $(bin.version-info) in order to figure out the
# dist file's name, so cannot (without a recursive make) have the
# target name equal to the archive name.
dist: \
    $(bin.stripccomments) $(bin.version-info) \
    $(dist.build) $(STRIP_K1.js) $(STRIP_K2.js) \
    $(MAKEFILE) $(MAKEFILE.dist)
	@echo "Making end-user deliverables..."
	@rm -fr $(dist-dir.top)
	@mkdir -p $(dist-dir.jswasm) $(dist-dir.common)
	@cp -p $(dist.top.extras) $(dist-dir.top)
	@cp -p README-dist.txt $(dist-dir.top)/README.txt
	@cp -p index-dist.html $(dist-dir.top)/index.html
	@cp -p $(dist.jswasm.extras) $(dist-dir.jswasm)
	@$(foreach JS,$(STRIP_K1.js),$(call DIST_STRIP_COMMENTS,$(JS),-k))
	@$(foreach JS,$(STRIP_K2.js),$(call DIST_STRIP_COMMENTS,$(JS),-k -k))
	@cp -p $(dist.common.extras) $(dist-dir.common)
	@set -e; \
		vnum=$$($(bin.version-info) --download-version); \
		vdir=$(dist-name-prefix)-$$vnum; \
		arczip=$$vdir.zip; \
		echo "Making $$arczip ..."; \
		rm -fr $$arczip $$vdir; \
		mv $(dist-dir.top) $$vdir; \
		zip -qr $$arczip $$vdir; \
		rm -fr $$vdir; \
		ls -la $$arczip; \
		set +e; \
		unzip -lv $$arczip || echo "Missing unzip app? Not fatal."
ifeq (,$(wasm.docs.found))
snapshot: dist
	@echo "To upload the snapshot build to the wasm docs server:"; \
	echo "1) move $(dist-name-prefix)*.zip to the top of a wasm docs checkout."; \
  echo "2) run 'make uv-sync'"
else
snapshot: dist
	@echo "Moving snapshot to [$(wasm.docs.found)]..."; \
	mv $(dist-name-prefix)*.zip $(wasm.docs.found)/.
	@echo "Run 'make uv-sync' from $(wasm.docs.found) to upload it."
endif
# We need a separate `clean` rule to account for weirdness in
# a sub-make, where we get a copy of the $(dist-name) dir
# copied into the new $(dist-name) dir.
.PHONY: dist-clean
clean: dist-clean
dist-clean:
	rm -fr $(dist-name) $(wildcard sqlite-wasm-*.zip)

Added ext/wasm/fiddle.make.




































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
#!/do/not/make
#^^^ help emacs select edit mode
#
# Intended to include'd by ./GNUmakefile.
#######################################################################
MAKEFILE.fiddle := $(lastword $(MAKEFILE_LIST))

########################################################################
# shell.c and its build flags...
make-np-0 := make -C  $(dir.top) -n -p
make-np-1 := sed -e 's/(TOP)/(dir.top)/g'
$(eval $(shell $(make-np-0) | grep -e '^SHELL_OPT ' | $(make-np-1)))
$(eval $(shell $(make-np-0) | grep -e '^SHELL_SRC ' | $(make-np-1)))
# ^^^ can't do that in 1 invocation b/c newlines get stripped
ifeq (,$(SHELL_OPT))
$(error Could not parse SHELL_OPT from $(dir.top)/Makefile.)
endif
ifeq (,$(SHELL_SRC))
$(error Could not parse SHELL_SRC from $(dir.top)/Makefile.)
endif
$(dir.top)/shell.c: $(SHELL_SRC) $(dir.top)/tool/mkshellc.tcl
	$(MAKE) -C $(dir.top) shell.c
# /shell.c
########################################################################

EXPORTED_FUNCTIONS.fiddle := $(dir.tmp)/EXPORTED_FUNCTIONS.fiddle
fiddle.emcc-flags = \
  $(emcc.cflags) $(emcc_opt_full) \
  --minify 0 \
  -sALLOW_TABLE_GROWTH \
  -sABORTING_MALLOC \
  -sSTRICT_JS \
  -sENVIRONMENT=web,worker \
  -sMODULARIZE \
  -sDYNAMIC_EXECUTION=0 \
  -sWASM_BIGINT=$(emcc.WASM_BIGINT) \
  -sEXPORT_NAME=$(sqlite3.js.init-func) \
  -Wno-limited-postlink-optimizations \
  $(sqlite3.js.flags.--post-js) \
  $(emcc.exportedRuntimeMethods) \
  -sEXPORTED_FUNCTIONS=@$(abspath $(EXPORTED_FUNCTIONS.fiddle)) \
  -sEXPORTED_RUNTIME_METHODS=FS,wasmMemory \
  $(SQLITE_OPT) $(SHELL_OPT) \
  -DSQLITE_SHELL_FIDDLE
# -D_POSIX_C_SOURCE is needed for strdup() with emcc

fiddle.EXPORTED_FUNCTIONS.in := \
    EXPORTED_FUNCTIONS.fiddle.in \
    $(EXPORTED_FUNCTIONS.api)

$(EXPORTED_FUNCTIONS.fiddle): $(fiddle.EXPORTED_FUNCTIONS.in) $(MAKEFILE.fiddle)
	sort -u $(fiddle.EXPORTED_FUNCTIONS.in) > $@

fiddle-module.js := $(dir.fiddle)/fiddle-module.js
fiddle-module.wasm := $(subst .js,.wasm,$(fiddle-module.js))
fiddle.cses := $(dir.top)/shell.c $(sqlite3-wasm.c)

fiddle.SOAP.js := $(dir.fiddle)/$(notdir $(SOAP.js))
$(fiddle.SOAP.js): $(SOAP.js)
	cp $< $@

$(eval $(call call-make-pre-js,fiddle-module,vanilla))
$(fiddle-module.js): $(MAKEFILE) $(MAKEFILE.fiddle) \
    $(EXPORTED_FUNCTIONS.fiddle) \
    $(fiddle.cses) $(pre-post-fiddle-module.deps.vanilla) $(fiddle.SOAP.js)
	$(emcc.bin) -o $@ $(fiddle.emcc-flags) \
    $(pre-post-fiddle-module.flags.vanilla) \
    $(fiddle.cses)
	$(maybe-wasm-strip) $(fiddle-module.wasm)
	gzip < $@ > $@.gz
	gzip < $(fiddle-module.wasm) > $(fiddle-module.wasm).gz

$(dir.fiddle)/fiddle.js.gz: $(dir.fiddle)/fiddle.js
	gzip < $< > $@

clean: clean-fiddle
clean-fiddle:
	rm -f $(fiddle-module.js) $(fiddle-module.js).gz \
        $(fiddle-module.wasm) $(fiddle-module.wasm).gz \
        $(dir.fiddle)/$(SOAP.js) \
        $(dir.fiddle)/fiddle-module.worker.js \
        EXPORTED_FUNCTIONS.fiddle
.PHONY: fiddle
fiddle: $(fiddle-module.js) $(dir.fiddle)/fiddle.js.gz
all: fiddle

########################################################################
# fiddle_remote is the remote destination for the fiddle app. It
# must be a [user@]HOST:/path for rsync.
# Note that the target "should probably" contain a symlink of
# index.html -> fiddle.html.
fiddle_remote ?=
ifeq (,$(fiddle_remote))
ifneq (,$(wildcard /home/stephan))
  fiddle_remote = wh:www/wh/sqlite3/.
else ifneq (,$(wildcard /home/drh))
  #fiddle_remote = if appropriate, add that user@host:/path here
endif
endif
push-fiddle: fiddle
	@if [ x = "x$(fiddle_remote)" ]; then \
		echo "fiddle_remote must be a [user@]HOST:/path for rsync"; \
		exit 1; \
	fi
	rsync -va fiddle/ $(fiddle_remote)
# end fiddle remote push
########################################################################


########################################################################
# Explanation of the emcc build flags follows. Full docs for these can
# be found at:
#
#  https://github.com/emscripten-core/emscripten/blob/main/src/settings.js
#
# -sENVIRONMENT=web: elides bootstrap code related to non-web JS
#  environments like node.js. Removing this makes the output a tiny
#  tick larger but hypothetically makes it more portable to
#  non-browser JS environments.
#
# -sMODULARIZE: changes how the generated code is structured to avoid
#  declaring a global Module object and instead installing a function
#  which loads and initializes the module. The function is named...
#
# -sEXPORT_NAME=jsFunctionName (see -sMODULARIZE)
#
# -sEXPORTED_RUNTIME_METHODS=@/absolute/path/to/file: a file
#  containing a list of emscripten-supplied APIs, one per line, which
#  must be exported into the generated JS. Must be an absolute path!
#
# -sEXPORTED_FUNCTIONS=@/absolute/path/to/file: a file containing a
#  list of C functions, one per line, which must be exported via wasm
#  so they're visible to JS. C symbols names in that file must all
#  start with an underscore for reasons known only to the emcc
#  developers. e.g., _sqlite3_open_v2 and _sqlite3_finalize. Must be
#  an absolute path!
#
# -sSTRICT_JS ensures that the emitted JS code includes the 'use
#  strict' option. Note that -sSTRICT is more broadly-scoped and
#  results in build errors.
#
# -sALLOW_TABLE_GROWTH is required for (at a minimum) the UDF-binding
#  feature. Without it, JS functions cannot be made to proxy C-side
#  callbacks.
#
# -sABORTING_MALLOC causes the JS-bound _malloc() to abort rather than
#  return 0 on OOM. If set to 0 then all code which uses _malloc()
#  must, just like in C, check the result before using it, else
#  they're likely to corrupt the JS/WASM heap by writing to its
#  address of 0. It is, as of this writing, enabled in Emscripten by
#  default but we enable it explicitly in case that default changes.
#
# -sDYNAMIC_EXECUTION=0 disables eval() and the Function constructor.
#  If the build runs without these, it's preferable to use this flag
#  because certain execution environments disallow those constructs.
#  This flag is not strictly necessary, however.
#
# -sWASM_BIGINT is UNTESTED but "should" allow the int64-using C APIs
#  to work with JS/wasm, insofar as the JS environment supports the
#  BigInt type. That support requires an extremely recent browser:
#  Safari didn't get that support until late 2020.
#
# --no-entry: for compiling library code with no main(). If this is
#  not supplied and the code has a main(), it is called as part of the
#  module init process. Note that main() is #if'd out of shell.c
#  (renamed) when building in wasm mode.
#
# --pre-js/--post-js=FILE relative or absolute paths to JS files to
#  prepend/append to the emcc-generated bootstrapping JS. It's
#  easier/faster to develop with separate JS files (reduces rebuilding
#  requirements) but certain configurations, namely -sMODULARIZE, may
#  require using at least a --pre-js file. They can be used
#  individually and need not be paired.
#
# -O0..-O3 and -Oz: optimization levels affect not only C-style
#  optimization but whether or not the resulting generated JS code
#  gets minified. -O0 compiles _much_ more quickly than -O3 or -Oz,
#  and doesn't minimize any JS code, so is recommended for
#  development. -O3 or -Oz are recommended for deployment, but
#  primarily because -Oz will shrink the wasm file notably. JS-side
#  minification makes little difference in terms of overall
#  distributable size.
#
# --minify 0: disables minification of the generated JS code,
#  regardless of optimization level. Minification of the JS has
#  minimal overall effect in the larger scheme of things and results
#  in JS files which can neither be edited nor viewed as text files in
#  Fossil (which flags them as binary because of their extreme line
#  lengths). Interestingly, whether or not the comments in the
#  generated JS file get stripped is unaffected by this setting and
#  depends entirely on the optimization level. Higher optimization
#  levels reduce the size of the JS considerably even without
#  minification.
#
########################################################################

Added ext/wasm/fiddle/emscripten.css.

























1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/* emcscript-related styling, used during the module load/intialization processes... */
.emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
div.emscripten { text-align: center; }
div.emscripten_border { border: 1px solid black; }
#module-spinner { overflow: visible; }
#module-spinner > * {
    margin-top: 1em;
}
.spinner {
    height: 50px;
    width: 50px;
    margin: 0px auto;
    animation: rotation 0.8s linear infinite;
    border-left: 10px solid rgb(0,150,240);
    border-right: 10px solid rgb(0,150,240);
    border-bottom: 10px solid rgb(0,150,240);
    border-top: 10px solid rgb(100,0,200);
    border-radius: 100%;
    background-color: rgb(200,100,250);
}
@keyframes rotation {
    from {transform: rotate(0deg);}
    to {transform: rotate(360deg);}
}

Added ext/wasm/fiddle/fiddle-worker.js.




























































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
  2022-05-20

  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 is the JS Worker file for the sqlite3 fiddle app. It loads the
  sqlite3 wasm module and offers access to the db via the Worker
  message-passing interface.

  Forewarning: this API is still very much Under Construction and
  subject to any number of changes as experience reveals what those
  need to be.

  Because we can have only a single message handler, as opposed to an
  arbitrary number of discrete event listeners like with DOM elements,
  we have to define a lower-level message API. Messages abstractly
  look like:

  { type: string, data: type-specific value }

  Where 'type' is used for dispatching and 'data' is a
  'type'-dependent value.

  The 'type' values expected by each side of the main/worker
  connection vary. The types are described below but subject to
  change at any time as this experiment evolves.

  Workers-to-Main types

  - stdout, stderr: indicate stdout/stderr output from the wasm
    layer. The data property is the string of the output, noting
    that the emscripten binding emits these one line at a time. Thus,
    if a C-side puts() emits multiple lines in a single call, the JS
    side will see that as multiple calls. Example:

    {type:'stdout', data: 'Hi, world.'}

  - module: Status text. This is intended to alert the main thread
    about module loading status so that, e.g., the main thread can
    update a progress widget and DTRT when the module is finished
    loading and available for work. Status messages come in the form
    
    {type:'module', data:{
        type:'status',
        data: {text:string|null, step:1-based-integer}
    }

    with an incrementing step value for each subsequent message. When
    the module loading is complete, a message with a text value of
    null is posted.

  - working: data='start'|'end'. Indicates that work is about to be
    sent to the module or has just completed. This can be used, e.g.,
    to disable UI elements which should not be activated while work
    is pending. Example:

    {type:'working', data:'start'}

  Main-to-Worker types:

  - shellExec: data=text to execute as if it had been entered in the
    sqlite3 CLI shell app (as opposed to sqlite3_exec()). This event
    causes the worker to emit a 'working' event (data='start') before
    it starts and a 'working' event (data='end') when it finished. If
    called while work is currently being executed it emits stderr
    message instead of doing actual work, as the underlying db cannot
    handle concurrent tasks. Example:

    {type:'shellExec', data: 'select * from sqlite_master'}

  - More TBD as the higher-level db layer develops.
*/

/*
  Apparent browser(s) bug: console messages emitted may be duplicated
  in the console, even though they're provably only run once. See:

  https://stackoverflow.com/questions/49659464

  Noting that it happens in Firefox as well as Chrome. Harmless but
  annoying.
*/
"use strict";
(function(){
  /**
     Posts a message in the form {type,data}. If passed more than 2
     args, the 3rd must be an array of "transferable" values to pass
     as the 2nd argument to postMessage(). */
  const wMsg =
        (type,data,transferables)=>{
          postMessage({type, data}, transferables || []);
        };
  const stdout = (...args)=>wMsg('stdout', args);
  const stderr = (...args)=>wMsg('stderr', args);
  const toss = (...args)=>{
    throw new Error(args.join(' '));
  };
  const fixmeOPFS = "(FIXME: won't work with OPFS-over-sqlite3_vfs.)";
  let sqlite3 /* gets assigned when the wasm module is loaded */;

  self.onerror = function(/*message, source, lineno, colno, error*/) {
    const err = arguments[4];
    if(err && 'ExitStatus'==err.name){
      /* This is relevant for the sqlite3 shell binding but not the
         lower-level binding. */
      fiddleModule.isDead = true;
      stderr("FATAL ERROR:", err.message);
      stderr("Restarting the app requires reloading the page.");
      wMsg('error', err);
    }
    console.error(err);
    fiddleModule.setStatus('Exception thrown, see JavaScript console: '+err);
  };

  const Sqlite3Shell = {
    /** Returns the name of the currently-opened db. */
    dbFilename: function f(){
      if(!f._) f._ = sqlite3.wasm.xWrap('fiddle_db_filename', "string", ['string']);
      return f._(0);
    },
    dbHandle: function f(){
      if(!f._) f._ = sqlite3.wasm.xWrap("fiddle_db_handle", "sqlite3*");
      return f._();
    },
    dbIsOpfs: function f(){
      return sqlite3.opfs && sqlite3.capi.sqlite3_js_db_uses_vfs(
        this.dbHandle(), "opfs"
      );
    },
    runMain: function f(){
      if(f.argv) return 0===f.argv.rc;
      const dbName = "/fiddle.sqlite3";
      f.argv = [
        'sqlite3-fiddle.wasm',
        '-bail', '-safe',
        dbName
        /* Reminder: because of how we run fiddle, we have to ensure
           that any argv strings passed to its main() are valid until
           the wasm environment shuts down. */
      ];
      const capi = sqlite3.capi, wasm = sqlite3.wasm;
      /* We need to call sqlite3_shutdown() in order to avoid numerous
         legitimate warnings from the shell about it being initialized
         after sqlite3_initialize() has been called. This means,
         however, that any initialization done by the JS code may need
         to be re-done (e.g.  re-registration of dynamically-loaded
         VFSes). We need a more generic approach to running such
         init-level code. */
      capi.sqlite3_shutdown();
      f.argv.pArgv = wasm.allocMainArgv(f.argv);
      f.argv.rc = wasm.exports.fiddle_main(
        f.argv.length, f.argv.pArgv
      );
      if(f.argv.rc){
        stderr("Fatal error initializing sqlite3 shell.");
        fiddleModule.isDead = true;
        return false;
      }
      stdout("SQLite version", capi.sqlite3_libversion(),
             capi.sqlite3_sourceid().substr(0,19));
      stdout('Welcome to the "fiddle" shell.');
      if(sqlite3.opfs){
        stdout("\nOPFS is available. To open a persistent db, use:\n\n",
               "  .open file:name?vfs=opfs\n\nbut note that some",
               "features (e.g. upload) do not yet work with OPFS.");
        sqlite3.opfs.registerVfs();
      }
      stdout('\nEnter ".help" for usage hints.');
      this.exec([ // initialization commands...
        '.nullvalue NULL',
        '.headers on'
      ].join('\n'));
      return true;
    },
    /**
       Runs the given text through the shell as if it had been typed
       in by a user. Fires a working/start event before it starts and
       working/end event when it finishes.
    */
    exec: function f(sql){
      if(!f._){
        if(!this.runMain()) return;
        f._ = sqlite3.wasm.xWrap('fiddle_exec', null, ['string']);
      }
      if(fiddleModule.isDead){
        stderr("shell module has exit()ed. Cannot run SQL.");
        return;
      }
      wMsg('working','start');
      try {
        if(f._running){
          stderr('Cannot run multiple commands concurrently.');
        }else if(sql){
          if(Array.isArray(sql)) sql = sql.join('');
          f._running = true;
          f._(sql);
        }
      }finally{
        delete f._running;
        wMsg('working','end');
      }
    },
    resetDb: function f(){
      if(!f._) f._ = sqlite3.wasm.xWrap('fiddle_reset_db', null);
      stdout("Resetting database.");
      f._();
      stdout("Reset",this.dbFilename());
    },
    /* Interrupt can't work: this Worker is tied up working, so won't get the
       interrupt event which would be needed to perform the interrupt. */
    interrupt: function f(){
      if(!f._) f._ = sqlite3.wasm.xWrap('fiddle_interrupt', null);
      stdout("Requesting interrupt.");
      f._();
    }
  };
  
  self.onmessage = function f(ev){
    ev = ev.data;
    if(!f.cache){
      f.cache = {
        prevFilename: null
      };
    }
    //console.debug("worker: onmessage.data",ev);
    switch(ev.type){
        case 'shellExec': Sqlite3Shell.exec(ev.data); return;
        case 'db-reset': Sqlite3Shell.resetDb(); return;
        case 'interrupt': Sqlite3Shell.interrupt(); return;
          /** Triggers the export of the current db. Fires an
              event in the form:

              {type:'db-export',
                data:{
                  filename: name of db,
                  buffer: contents of the db file (Uint8Array),
                  error: on error, a message string and no buffer property.
                }
              }
          */
        case 'db-export': {
          const fn = Sqlite3Shell.dbFilename();
          stdout("Exporting",fn+".");
          const fn2 = fn ? fn.split(/[/\\]/).pop() : null;
          try{
            if(!fn2) toss("DB appears to be closed.");
            const buffer = sqlite3.capi.sqlite3_js_db_export(
              Sqlite3Shell.dbHandle()
            );
            wMsg('db-export',{filename: fn2, buffer: buffer.buffer}, [buffer.buffer]);
          }catch(e){
            console.error("Export failed:",e);
            /* Post a failure message so that UI elements disabled
               during the export can be re-enabled. */
            wMsg('db-export',{
              filename: fn,
              error: e.message
            });
          }
          return;
        }
        case 'open': {
          /* Expects: {
               buffer: ArrayBuffer | Uint8Array,
               filename: the filename for the db. Any dir part is
                         stripped.
              }
          */
          const opt = ev.data;
          let buffer = opt.buffer;
          stderr('open():',fixmeOPFS);
          if(buffer instanceof ArrayBuffer){
            buffer = new Uint8Array(buffer);
          }else if(!(buffer instanceof Uint8Array)){
            stderr("'open' expects {buffer:Uint8Array} containing an uploaded db.");
            return;
          }
          const fn = (
            opt.filename
              ? opt.filename.split(/[/\\]/).pop().replace('"','_')
              : ("db-"+((Math.random() * 10000000) | 0)+
                 "-"+((Math.random() * 10000000) | 0)+".sqlite3")
          );
          try {
            /* We cannot delete the existing db file until the new one
               is installed, which means that we risk overflowing our
               quota (if any) by having both the previous and current
               db briefly installed in the virtual filesystem. */
            const fnAbs = '/'+fn;
            const oldName = Sqlite3Shell.dbFilename();
            if(oldName && oldName===fnAbs){
              /* We cannot create the replacement file while the current file
                 is opened, nor does the shell have a .close command, so we
                 must temporarily switch to another db... */
              Sqlite3Shell.exec('.open :memory:');
              fiddleModule.FS.unlink(fnAbs);
            }
            fiddleModule.FS.createDataFile("/", fn, buffer, true, true);
            Sqlite3Shell.exec('.open "'+fnAbs+'"');
            if(oldName && oldName!==fnAbs){
              try{fiddleModule.fsUnlink(oldName)}
              catch(e){/*ignored*/}
            }
            stdout("Replaced DB with",fn+".");
          }catch(e){
            stderr("Error installing db",fn+":",e.message);
          }
          return;
        }
    };
    console.warn("Unknown fiddle-worker message type:",ev);
  };
  
  /**
     emscripten module for use with build mode -sMODULARIZE.
  */
  const fiddleModule = {
    print: stdout,
    printErr: stderr,
    /**
       Intercepts status updates from the emscripting module init
       and fires worker events with a type of 'status' and a
       payload of:

       {
       text: string | null, // null at end of load process
       step: integer // starts at 1, increments 1 per call
       }

       We have no way of knowing in advance how many steps will
       be processed/posted, so creating a "percentage done" view is
       not really practical. One can be approximated by giving it a
       current value of message.step and max value of message.step+1,
       though.

       When work is finished, a message with a text value of null is
       submitted.

       After a message with text==null is posted, the module may later
       post messages about fatal problems, e.g. an exit() being
       triggered, so it is recommended that UI elements for posting
       status messages not be outright removed from the DOM when
       text==null, and that they instead be hidden until/unless
       text!=null.
    */
    setStatus: function f(text){
      if(!f.last) f.last = { step: 0, text: '' };
      else if(text === f.last.text) return;
      f.last.text = text;
      wMsg('module',{
        type:'status',
        data:{step: ++f.last.step, text: text||null}
      });
    }
  };

  importScripts('fiddle-module.js'+self.location.search);
  /**
     initFiddleModule() is installed via fiddle-module.js due to
     building with:

     emcc ... -sMODULARIZE=1 -sEXPORT_NAME=initFiddleModule
  */
  sqlite3InitModule(fiddleModule).then((_sqlite3)=>{
    sqlite3 = _sqlite3;
    const dbVfs = sqlite3.wasm.xWrap('fiddle_db_vfs', "*", ['string']);
    fiddleModule.fsUnlink = (fn)=>{
      return sqlite3.wasm.sqlite3_wasm_vfs_unlink(dbVfs(0), fn);
    };
    wMsg('fiddle-ready');
  })/*then()*/;
})();

Added ext/wasm/fiddle/fiddle.html.




























































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<!doctype html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>SQLite3 Fiddle</title>
    <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
    <!-- to add a togglable terminal-style view, uncomment the following
         two lines and ensure that these files are on the web server. -->
    <!--script src="jqterm/jqterm-bundle.min.js"></script>
    <link rel="stylesheet" href="jqterm/jquery.terminal.min.css"/-->
    <link rel="stylesheet" href="emscripten.css"/>
    <style>
      /* The following styles are for app-level use. */
      :root {
          --sqlite-blue: #044a64;
          --textarea-color1: #044a64;
          --textarea-color2: white;
      }
      textarea {
          font-family: monospace;
          flex: 1 1 auto;
          background-color: var(--textarea-color1);
          color: var(--textarea-color2);
      }
      textarea#input {
          color: var(--textarea-color1);
          background-color: var(--textarea-color2);
      }
      header {
          display: flex;
          justify-content: space-between;
          align-items: center;
          background-color: var(--sqlite-blue);
          color: white;
          font-size: 120%;
          font-weight: bold;
          border-radius: 0.25em;
          padding: 0.2em 0.5em;
      }
      header > .powered-by {
          font-size: 80%;
      }
      header a, header a:visited, header a:hover {
          color: inherit;
      }
      #main-wrapper {
          display: flex;
          flex-direction: column-reverse;
          flex: 1 1 auto;
          margin: 0.5em 0;
          overflow: hidden;
      }
      #main-wrapper.side-by-side {
          flex-direction: row;
      }
      #main-wrapper.side-by-side > fieldset {
          margin-left: 0.25em;
          margin-right: 0.25em;
      }
      #main-wrapper:not(.side-by-side) > fieldset {
          margin-bottom: 0.25em;
      }
      #main-wrapper.swapio {
          flex-direction: column;
      }
      #main-wrapper.side-by-side.swapio {
          flex-direction: row-reverse;
      }
      .zone-wrapper{
          display: flex;
          margin: 0;
          flex: 1 1 0%;
          border-radius: 0.5em;
          min-width: inherit/*important: resolves inability to scroll fieldset child element!*/;
          padding: 0.35em 0 0 0;
      }
      .zone-wrapper textarea {
          border-radius: 0.5em;
          flex: 1 1 auto;
          /*min/max width resolve an inexplicable margin on the RHS.  The -1em
            is for the padding, else we overlap the parent boundaries.*/
          /*min-width: calc(100% - 1em);
          max-width: calc(100% - 1em);
          padding: 0 0.5em;*/
      }

      .zone-wrapper.input { flex: 10 1 auto; }
      .zone-wrapper.output { flex: 20 1 auto; }
      .zone-wrapper > div {
          display:flex;
          flex: 1 1 0%;
      }
      .zone-wrapper.output {}
      .button-bar {
          display: flex;
          flex-wrap: wrap;
          align-items: center;
          align-content: space-between;
          justify-content: flex-start;
      }
      .button-bar > * {
          margin: 0.05em 0.5em 0.05em 0;
          flex: 0 1 auto;
          align-self: auto;
      }
      label[for] {
          cursor: pointer;
      }
      .error {
          color: red;
          background-color: yellow;
      }
      .hidden, .initially-hidden {
          position: absolute !important;
          opacity: 0 !important;
          pointer-events: none !important;
          display: none !important;
      }
      fieldset {
          border-radius: 0.5em;
          border: 1px inset;
          padding: 0.25em;
      }
      fieldset.options {
          font-size: 80%;
          margin-top: 0.5em;
      }
      fieldset:not(.options) > legend {
          font-size: 80%;
      }
      fieldset.options > div {
          display: flex;
          flex-wrap: wrap;
      }
      fieldset button {
          font-size: inherit;
      }
      fieldset.collapsible > legend > .fieldset-toggle::after {
          content: " [hide]";
          position: relative;
      }
      fieldset.collapsible.collapsed > legend > .fieldset-toggle::after {
          content: " [show]";
          position: relative;
      }
      span.labeled-input {
          padding: 0.25em;
          margin: 0.05em 0.25em;
          border-radius: 0.25em;
          white-space: nowrap;
          background: #0002;
          display: flex;
          align-items: center;
      }
      span.labeled-input > *:nth-child(2) {
          margin-left: 0.3em;
      }
      .center { text-align: center; }
      body.terminal-mode {
          max-height: calc(100% - 2em);
          display: flex;
          flex-direction: column;
          align-items: stretch;
      }
      #view-terminal {}
      .app-view {
          flex: 20 1 auto;
      }
      #view-split {
          display: flex;
          flex-direction: column-reverse;
      }
    </style>
  </head>
  <body>
    <header id='titlebar'>
      <span>SQLite3 Fiddle</span>
      <span class='powered-by'>Powered by
        <a href='https://sqlite.org'>SQLite3</a></span>
    </header>
    <!-- emscripten bits -->
    <figure id="module-spinner">
      <div class="spinner"></div>
      <div class='center'><strong>Initializing app...</strong></div>
      <div class='center'>
        On a slow internet connection this may take a moment.  If this
        message displays for "a long time", intialization may have
        failed and the JavaScript console may contain clues as to why.
      </div>
    </figure>
    <div class="emscripten" id="module-status">Downloading...</div>
    <div class="emscripten">
      <progress value="0" max="100" id="module-progress" hidden='1'></progress>  
    </div><!-- /emscripten bits -->

    <div id='view-terminal' class='app-view hidden initially-hidden'>
      This is a placeholder for a terminal-like view which is not in
      the default build.
    </div>

    <div id='view-split' class='app-view initially-hidden'>
      <fieldset class='options collapsible'>
        <legend><button class='fieldset-toggle'>Options</button></legend>
        <div class=''>
          <span class='labeled-input'>
            <input type='checkbox' id='opt-cb-sbs'
                   data-csstgt='#main-wrapper'
                   data-cssclass='side-by-side'
                   data-config='sideBySide'>
            <label for='opt-cb-sbs'>Side-by-side</label>
          </span>
          <span class='labeled-input'>
            <input type='checkbox' id='opt-cb-swapio'
                   data-csstgt='#main-wrapper'
                   data-cssclass='swapio'
                   data-config='swapInOut'>
            <label for='opt-cb-swapio'>Swap in/out</label>
          </span>
          <span class='labeled-input'>
            <input type='checkbox' id='opt-cb-autoscroll'
                   data-config='autoScrollOutput'>
            <label for='opt-cb-autoscroll'>Auto-scroll output</label>
          </span>
          <span class='labeled-input'>
            <input type='checkbox' id='opt-cb-autoclear'
                   data-config='autoClearOutput'>
            <label for='opt-cb-autoclear'>Auto-clear output</label>
          </span>
          <span class='labeled-input'>
            <input type='file' id='load-db' class='hidden'/>
            <button id='btn-load-db'>Load DB...</button>
          </span>
          <span class='labeled-input'>
            <button id='btn-export'>Download DB</button>
          </span>
          <span class='labeled-input'>
            <button id='btn-reset'>Reset DB</button>
          </span>
        </div>
      </fieldset><!-- .options -->
      <div id='main-wrapper' class=''>
        <fieldset class='zone-wrapper input'>
          <legend><div class='button-bar'>
            <button id='btn-shell-exec'>Run</button>
            <button id='btn-clear'>Clear Input</button>
            <!--button data-cmd='.help'>Help</button-->
            <select id='select-examples'></select>
          </div></legend>
          <div><textarea id="input"
                         placeholder="Shell input. Ctrl-enter/shift-enter runs it.">
-- ==================================================
-- Use ctrl-enter or shift-enter to execute sqlite3
-- shell commands and SQL.
-- If a subset of the text is currently selected,
-- only that part is executed.
-- ==================================================
.nullvalue NULL
.headers on
</textarea></div>
        </fieldset>
        <fieldset class='zone-wrapper output'>
          <legend><div class='button-bar'>
            <button id='btn-clear-output'>Clear Output</button>
            <button id='btn-interrupt' class='hidden' disabled>Interrupt</button>
            <!-- interruption cannot work in the current configuration
                 because we cannot send an interrupt message when work
                 is currently underway. At that point the Worker is
                 tied up and will not receive the message. -->
          </div></legend>
          <div><textarea id="output" readonly
                         placeholder="Shell output."></textarea></div>
        </fieldset>
      </div>
    </div> <!-- #view-split -->
    <!-- Maintenance notes:

        ... TODO... currently being refactored...

    -->
    <script src="fiddle.js"></script>
  </body>
</html>

Added ext/wasm/fiddle/fiddle.js.
















































































































































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
  2022-05-20

  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 is the main entry point for the sqlite3 fiddle app. It sets up the
  various UI bits, loads a Worker for the db connection, and manages the
  communication between the UI and worker.
*/
(function(){
  'use strict';
  /* Recall that the 'self' symbol, except where locally
     overwritten, refers to the global window or worker object. */

  const storage = (function(NS/*namespace object in which to store this module*/){
    /* Pedantic licensing note: this code originated in the Fossil SCM
       source tree, where it has a different license, but the person who
       ported it into sqlite is the same one who wrote it for fossil. */
    'use strict';
    NS = NS||{};

    /**
       This module provides a basic wrapper around localStorage
       or sessionStorage or a dummy proxy object if neither
       of those are available.
    */
    const tryStorage = function f(obj){
      if(!f.key) f.key = 'storage.access.check';
      try{
        obj.setItem(f.key, 'f');
        const x = obj.getItem(f.key);
        obj.removeItem(f.key);
        if(x!=='f') throw new Error(f.key+" failed")
        return obj;
      }catch(e){
        return undefined;
      }
    };

    /** Internal storage impl for this module. */
    const $storage =
          tryStorage(window.localStorage)
          || tryStorage(window.sessionStorage)
          || tryStorage({
            // A basic dummy xyzStorage stand-in
            $$$:{},
            setItem: function(k,v){this.$$$[k]=v},
            getItem: function(k){
              return this.$$$.hasOwnProperty(k) ? this.$$$[k] : undefined;
            },
            removeItem: function(k){delete this.$$$[k]},
            clear: function(){this.$$$={}}
          });

    /**
       For the dummy storage we need to differentiate between
       $storage and its real property storage for hasOwnProperty()
       to work properly...
    */
    const $storageHolder = $storage.hasOwnProperty('$$$') ? $storage.$$$ : $storage;

    /**
       A prefix which gets internally applied to all storage module
       property keys so that localStorage and sessionStorage across the
       same browser profile instance do not "leak" across multiple apps
       being hosted by the same origin server. Such cross-polination is
       still there but, with this key prefix applied, it won't be
       immediately visible via the storage API.

       With this in place we can justify using localStorage instead of
       sessionStorage.

       One implication of using localStorage and sessionStorage is that
       their scope (the same "origin" and client application/profile)
       allows multiple apps on the same origin to use the same
       storage. Thus /appA/foo could then see changes made via
       /appB/foo. The data do not cross user- or browser boundaries,
       though, so it "might" arguably be called a
       feature. storageKeyPrefix was added so that we can sandbox that
       state for each separate app which shares an origin.

       See: https://fossil-scm.org/forum/forumpost/4afc4d34de

       Sidebar: it might seem odd to provide a key prefix and stick all
       properties in the topmost level of the storage object. We do that
       because adding a layer of object to sandbox each app would mean
       (de)serializing that whole tree on every storage property change.
       e.g. instead of storageObject.projectName.foo we have
       storageObject[storageKeyPrefix+'foo']. That's soley for
       efficiency's sake (in terms of battery life and
       environment-internal storage-level effort).
    */
    const storageKeyPrefix = (
      $storageHolder===$storage/*localStorage or sessionStorage*/
        ? (
          (NS.config ?
           (NS.config.projectCode || NS.config.projectName
            || NS.config.shortProjectName)
           : false)
            || window.location.pathname
        )+'::' : (
          '' /* transient storage */
        )
    );

    /**
       A proxy for localStorage or sessionStorage or a
       page-instance-local proxy, if neither one is availble.

       Which exact storage implementation is uses is unspecified, and
       apps must not rely on it.
    */
    NS.storage = {
      storageKeyPrefix: storageKeyPrefix,
      /** Sets the storage key k to value v, implicitly converting
          it to a string. */
      set: (k,v)=>$storage.setItem(storageKeyPrefix+k,v),
      /** Sets storage key k to JSON.stringify(v). */
      setJSON: (k,v)=>$storage.setItem(storageKeyPrefix+k,JSON.stringify(v)),
      /** Returns the value for the given storage key, or
          dflt if the key is not found in the storage. */
      get: (k,dflt)=>$storageHolder.hasOwnProperty(
        storageKeyPrefix+k
      ) ? $storage.getItem(storageKeyPrefix+k) : dflt,
      /** Returns true if the given key has a value of "true".  If the
          key is not found, it returns true if the boolean value of dflt
          is "true". (Remember that JS persistent storage values are all
          strings.) */
      getBool: function(k,dflt){
        return 'true'===this.get(k,''+(!!dflt));
      },
      /** Returns the JSON.parse()'d value of the given
          storage key's value, or dflt is the key is not
          found or JSON.parse() fails. */
      getJSON: function f(k,dflt){
        try {
          const x = this.get(k,f);
          return x===f ? dflt : JSON.parse(x);
        }
        catch(e){return dflt}
      },
      /** Returns true if the storage contains the given key,
          else false. */
      contains: (k)=>$storageHolder.hasOwnProperty(storageKeyPrefix+k),
      /** Removes the given key from the storage. Returns this. */
      remove: function(k){
        $storage.removeItem(storageKeyPrefix+k);
        return this;
      },
      /** Clears ALL keys from the storage. Returns this. */
      clear: function(){
        this.keys().forEach((k)=>$storage.removeItem(/*w/o prefix*/k));
        return this;
      },
      /** Returns an array of all keys currently in the storage. */
      keys: ()=>Object.keys($storageHolder).filter((v)=>(v||'').startsWith(storageKeyPrefix)),
      /** Returns true if this storage is transient (only available
          until the page is reloaded), indicating that fileStorage
          and sessionStorage are unavailable. */
      isTransient: ()=>$storageHolder!==$storage,
      /** Returns a symbolic name for the current storage mechanism. */
      storageImplName: function(){
        if($storage===window.localStorage) return 'localStorage';
        else if($storage===window.sessionStorage) return 'sessionStorage';
        else return 'transient';
      },

      /**
         Returns a brief help text string for the currently-selected
         storage type.
      */
      storageHelpDescription: function(){
        return {
          localStorage: "Browser-local persistent storage with an "+
            "unspecified long-term lifetime (survives closing the browser, "+
            "but maybe not a browser upgrade).",
          sessionStorage: "Storage local to this browser tab, "+
            "lost if this tab is closed.",
          "transient": "Transient storage local to this invocation of this page."
        }[this.storageImplName()];
      }
    };
    return NS.storage;
  })({})/*storage API setup*/;


  /** Name of the stored copy of SqliteFiddle.config. */
  const configStorageKey = 'sqlite3-fiddle-config';

  /**
     The SqliteFiddle object is intended to be the primary
     app-level object for the main-thread side of the sqlite
     fiddle application. It uses a worker thread to load the
     sqlite WASM module and communicate with it.
  */
  const SF/*local convenience alias*/
        = window.SqliteFiddle/*canonical name*/ = {
          /* Config options. */
          config: {
            /* If true, SqliteFiddle.echo() will auto-scroll the
               output widget to the bottom when it receives output,
               else it won't. */
            autoScrollOutput: true,
            /* If true, the output area will be cleared before each
               command is run, else it will not. */
            autoClearOutput: false,
            /* If true, SqliteFiddle.echo() will echo its output to
               the console, in addition to its normal output widget.
               That slows it down but is useful for testing. */
            echoToConsole: false,
            /* If true, display input/output areas side-by-side. */
            sideBySide: true,
            /* If true, swap positions of the input/output areas. */
            swapInOut: false
          },
          /**
             Emits the given text, followed by a line break, to the
             output widget.  If given more than one argument, they are
             join()'d together with a space between each. As a special
             case, if passed a single array, that array is used in place
             of the arguments array (this is to facilitate receiving
             lists of arguments via worker events).
          */
          echo: function f(text) {
            /* Maintenance reminder: we currently require/expect a textarea
               output element. It might be nice to extend this to behave
               differently if the output element is a non-textarea element,
               in which case it would need to append the given text as a TEXT
               node and add a line break. */
            if(!f._){
              f._ = document.getElementById('output');
              f._.value = ''; // clear browser cache
            }
            if(arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
            else if(1===arguments.length && Array.isArray(text)) text = text.join(' ');
            // These replacements are necessary if you render to raw HTML
            //text = text.replace(/&/g, "&amp;");
            //text = text.replace(/</g, "&lt;");
            //text = text.replace(/>/g, "&gt;");
            //text = text.replace('\n', '<br>', 'g');
            if(null===text){/*special case: clear output*/
              f._.value = '';
              return;
            }else if(this.echo._clearPending){
              delete this.echo._clearPending;
              f._.value = '';
            }
            if(this.config.echoToConsole) console.log(text);
            if(this.jqTerm) this.jqTerm.echo(text);
            f._.value += text + "\n";
            if(this.config.autoScrollOutput){
              f._.scrollTop = f._.scrollHeight;
            }
          },
          _msgMap: {},
          /** Adds a worker message handler for messages of the given
              type. */
          addMsgHandler: function f(type,callback){
            if(Array.isArray(type)){
              type.forEach((t)=>this.addMsgHandler(t, callback));
              return this;
            }
            (this._msgMap.hasOwnProperty(type)
             ? this._msgMap[type]
             : (this._msgMap[type] = [])).push(callback);
            return this;
          },
          /** Given a worker message, runs all handlers for msg.type. */
          runMsgHandlers: function(msg){
            const list = (this._msgMap.hasOwnProperty(msg.type)
                          ? this._msgMap[msg.type] : false);
            if(!list){
              console.warn("No handlers found for message type:",msg);
              return false;
            }
            //console.debug("runMsgHandlers",msg);
            list.forEach((f)=>f(msg));
            return true;
          },
          /** Removes all message handlers for the given message type. */
          clearMsgHandlers: function(type){
            delete this._msgMap[type];
            return this;
          },
          /* Posts a message in the form {type, data} to the db worker. Returns this. */
          wMsg: function(type,data,transferables){
            this.worker.postMessage({type, data}, transferables || []);
            return this;
          },
          /**
             Prompts for confirmation and, if accepted, deletes
             all content and tables in the (transient) database.
          */
          resetDb: function(){
            if(window.confirm("Really destroy all content and tables "
                              +"in the (transient) db?")){
              this.wMsg('db-reset');
            }
            return this;
          },
          /** Stores this object's config in the browser's storage. */
          storeConfig: function(){
            storage.setJSON(configStorageKey,this.config);
          }
        };

  if(1){ /* Restore SF.config */
    const storedConfig = storage.getJSON(configStorageKey);
    if(storedConfig){
      /* Copy all properties to SF.config which are currently in
         storedConfig. We don't bother copying any other
         properties: those have been removed from the app in the
         meantime. */
      Object.keys(SF.config).forEach(function(k){
        if(storedConfig.hasOwnProperty(k)){
          SF.config[k] = storedConfig[k];
        }
      });
    }
  }

  SF.worker = new Worker('fiddle-worker.js'+self.location.search);
  SF.worker.onmessage = (ev)=>SF.runMsgHandlers(ev.data);
  SF.addMsgHandler(['stdout', 'stderr'], (ev)=>SF.echo(ev.data));

  /* querySelectorAll() proxy */
  const EAll = function(/*[element=document,] cssSelector*/){
    return (arguments.length>1 ? arguments[0] : document)
      .querySelectorAll(arguments[arguments.length-1]);
  };
  /* querySelector() proxy */
  const E = function(/*[element=document,] cssSelector*/){
    return (arguments.length>1 ? arguments[0] : document)
      .querySelector(arguments[arguments.length-1]);
  };

  /** Handles status updates from the Emscripten Module object. */
  SF.addMsgHandler('module', function f(ev){
    ev = ev.data;
    if('status'!==ev.type){
      console.warn("Unexpected module-type message:",ev);
      return;
    }
    if(!f.ui){
      f.ui = {
        status: E('#module-status'),
        progress: E('#module-progress'),
        spinner: E('#module-spinner')
      };
    }
    const msg = ev.data;
    if(f.ui.progres){
      progress.value = msg.step;
      progress.max = msg.step + 1/*we don't know how many steps to expect*/;
    }
    if(1==msg.step){
      f.ui.progress.classList.remove('hidden');
      f.ui.spinner.classList.remove('hidden');
    }
    if(msg.text){
      f.ui.status.classList.remove('hidden');
      f.ui.status.innerText = msg.text;
    }else{
      if(f.ui.progress){
        f.ui.progress.remove();
        f.ui.spinner.remove();
        delete f.ui.progress;
        delete f.ui.spinner;
      }
      f.ui.status.classList.add('hidden');
      /* The module can post messages about fatal problems,
         e.g. an exit() being triggered or assertion failure,
         after the last "load" message has arrived, so
         leave f.ui.status and message listener intact. */
    }
  });

  /**
     The 'fiddle-ready' event is fired (with no payload) when the
     wasm module has finished loading. Interestingly, that happens
     _before_ the final module:status event */
  SF.addMsgHandler('fiddle-ready', function(){
    SF.clearMsgHandlers('fiddle-ready');
    self.onSFLoaded();
  });

  /**
     Performs all app initialization which must wait until after the
     worker module is loaded. This function removes itself when it's
     called.
  */
  self.onSFLoaded = function(){
    delete this.onSFLoaded;
    // Unhide all elements which start out hidden
    EAll('.initially-hidden').forEach((e)=>e.classList.remove('initially-hidden'));
    E('#btn-reset').addEventListener('click',()=>SF.resetDb());
    const taInput = E('#input');
    const btnClearIn = E('#btn-clear');
    btnClearIn.addEventListener('click',function(){
      taInput.value = '';
    },false);
    // Ctrl-enter and shift-enter both run the current SQL.
    taInput.addEventListener('keydown',function(ev){
      if((ev.ctrlKey || ev.shiftKey) && 13 === ev.keyCode){
        ev.preventDefault();
        ev.stopPropagation();
        btnShellExec.click();
      }
    }, false);
    const taOutput = E('#output');
    const btnClearOut = E('#btn-clear-output');
    btnClearOut.addEventListener('click',function(){
      taOutput.value = '';
      if(SF.jqTerm) SF.jqTerm.clear();
    },false);
    const btnShellExec = E('#btn-shell-exec');
    btnShellExec.addEventListener('click',function(ev){
      let sql;
      ev.preventDefault();
      if(taInput.selectionStart<taInput.selectionEnd){
        sql = taInput.value.substring(taInput.selectionStart,taInput.selectionEnd).trim();
      }else{
        sql = taInput.value.trim();
      }
      if(sql) SF.dbExec(sql);
    },false);

    const btnInterrupt = E("#btn-interrupt");
    //btnInterrupt.classList.add('hidden');
    /** To be called immediately before work is sent to the
        worker. Updates some UI elements. The 'working'/'end'
        event will apply the inverse, undoing the bits this
        function does. This impl is not in the 'working'/'start'
        event handler because that event is given to us
        asynchronously _after_ we need to have performed this
        work.
    */
    const preStartWork = function f(){
      if(!f._){
        const title = E('title');
        f._ = {
          btnLabel: btnShellExec.innerText,
          pageTitle: title,
          pageTitleOrig: title.innerText
        };
      }
      f._.pageTitle.innerText = "[working...] "+f._.pageTitleOrig;
      btnShellExec.setAttribute('disabled','disabled');
      btnInterrupt.removeAttribute('disabled','disabled');
    };

    /* Sends the given text to the db module to evaluate as if it
       had been entered in the sqlite3 CLI shell. If it's null or
       empty, this is a no-op. */
    SF.dbExec = function f(sql){
      if(null!==sql && this.config.autoClearOutput){
        this.echo._clearPending = true;
      }
      preStartWork();
      this.wMsg('shellExec',sql);
    };

    SF.addMsgHandler('working',function f(ev){
      switch(ev.data){
          case 'start': /* See notes in preStartWork(). */; return;
          case 'end':
            preStartWork._.pageTitle.innerText = preStartWork._.pageTitleOrig;
            btnShellExec.innerText = preStartWork._.btnLabel;
            btnShellExec.removeAttribute('disabled');
            btnInterrupt.setAttribute('disabled','disabled');
            return;
      }
      console.warn("Unhandled 'working' event:",ev.data);
    });

    /* For each checkbox with data-csstgt, set up a handler which
       toggles the given CSS class on the element matching
       E(data-csstgt). */
    EAll('input[type=checkbox][data-csstgt]')
      .forEach(function(e){
        const tgt = E(e.dataset.csstgt);
        const cssClass = e.dataset.cssclass || 'error';
        e.checked = tgt.classList.contains(cssClass);
        e.addEventListener('change', function(){
          tgt.classList[
            this.checked ? 'add' : 'remove'
          ](cssClass)
        }, false);
      });
    /* For each checkbox with data-config=X, set up a binding to
       SF.config[X]. These must be set up AFTER data-csstgt
       checkboxes so that those two states can be synced properly. */
    EAll('input[type=checkbox][data-config]')
      .forEach(function(e){
        const confVal = !!SF.config[e.dataset.config];
        if(e.checked !== confVal){
          /* Ensure that data-csstgt mappings (if any) get
             synced properly. */
          e.checked = confVal;
          e.dispatchEvent(new Event('change'));
        }
        e.addEventListener('change', function(){
          SF.config[this.dataset.config] = this.checked;
          SF.storeConfig();
        }, false);
      });
    /* For each button with data-cmd=X, map a click handler which
       calls SF.dbExec(X). */
    const cmdClick = function(){SF.dbExec(this.dataset.cmd);};
    EAll('button[data-cmd]').forEach(
      e => e.addEventListener('click', cmdClick, false)
    );

    btnInterrupt.addEventListener('click',function(){
      SF.wMsg('interrupt');
    });

    /** Initiate a download of the db. */
    const btnExport = E('#btn-export');
    const eLoadDb = E('#load-db');
    const btnLoadDb = E('#btn-load-db');
    btnLoadDb.addEventListener('click', ()=>eLoadDb.click());
    /**
       Enables (if passed true) or disables all UI elements which
       "might," if timed "just right," interfere with an
       in-progress db import/export/exec operation.
    */
    const enableMutatingElements = function f(enable){
      if(!f._elems){
        f._elems = [
          /* UI elements to disable while import/export are
             running. Normally the export is fast enough
             that this won't matter, but we really don't
             want to be reading (from outside of sqlite) the
             db when the user taps btnShellExec. */
          btnShellExec, btnExport, eLoadDb
        ];
      }
      f._elems.forEach( enable
                        ? (e)=>e.removeAttribute('disabled')
                        : (e)=>e.setAttribute('disabled','disabled') );
    };
    btnExport.addEventListener('click',function(){
      enableMutatingElements(false);
      SF.wMsg('db-export');
    });
    SF.addMsgHandler('db-export', function(ev){
      enableMutatingElements(true);
      ev = ev.data;
      if(ev.error){
        SF.echo("Export failed:",ev.error);
        return;
      }
      const blob = new Blob([ev.buffer],
                            {type:"application/x-sqlite3"});
      const a = document.createElement('a');
      document.body.appendChild(a);
      a.href = window.URL.createObjectURL(blob);
      a.download = ev.filename;
      a.addEventListener('click',function(){
        setTimeout(function(){
          SF.echo("Exported (possibly auto-downloaded):",ev.filename);
          window.URL.revokeObjectURL(a.href);
          a.remove();
        },500);
      });
      a.click();
    });
    /**
       Handle load/import of an external db file.
    */
    eLoadDb.addEventListener('change',function(){
      const f = this.files[0];
      const r = new FileReader();
      const status = {loaded: 0, total: 0};
      enableMutatingElements(false);
      r.addEventListener('loadstart', function(){
        SF.echo("Loading",f.name,"...");
      });
      r.addEventListener('progress', function(ev){
        SF.echo("Loading progress:",ev.loaded,"of",ev.total,"bytes.");
      });
      const that = this;
      r.addEventListener('load', function(){
        enableMutatingElements(true);
        SF.echo("Loaded",f.name+". Opening db...");
        SF.wMsg('open',{
          filename: f.name,
          buffer: this.result
        }, [this.result]);
      });
      r.addEventListener('error',function(){
        enableMutatingElements(true);
        SF.echo("Loading",f.name,"failed for unknown reasons.");
      });
      r.addEventListener('abort',function(){
        enableMutatingElements(true);
        SF.echo("Cancelled loading of",f.name+".");
      });
      r.readAsArrayBuffer(f);
    });

    EAll('fieldset.collapsible').forEach(function(fs){
      const btnToggle = E(fs,'legend > .fieldset-toggle'),
            content = EAll(fs,':scope > div');
      btnToggle.addEventListener('click', function(){
        fs.classList.toggle('collapsed');
        content.forEach((d)=>d.classList.toggle('hidden'));
      }, false);
    });

    /**
       Given a DOM element, this routine measures its "effective
       height", which is the bounding top/bottom range of this element
       and all of its children, recursively. For some DOM structure
       cases, a parent may have a reported height of 0 even though
       children have non-0 sizes.

       Returns 0 if !e or if the element really has no height.
    */
    const effectiveHeight = function f(e){
      if(!e) return 0;
      if(!f.measure){
        f.measure = function callee(e, depth){
          if(!e) return;
          const m = e.getBoundingClientRect();
          if(0===depth){
            callee.top = m.top;
            callee.bottom = m.bottom;
          }else{
            callee.top = m.top ? Math.min(callee.top, m.top) : callee.top;
            callee.bottom = Math.max(callee.bottom, m.bottom);
          }
          Array.prototype.forEach.call(e.children,(e)=>callee(e,depth+1));
          if(0===depth){
            //console.debug("measure() height:",e.className, callee.top, callee.bottom, (callee.bottom - callee.top));
            f.extra += callee.bottom - callee.top;
          }
          return f.extra;
        };
      }
      f.extra = 0;
      f.measure(e,0);
      return f.extra;
    };

    /**
       Returns a function, that, as long as it continues to be invoked,
       will not be triggered. The function will be called after it stops
       being called for N milliseconds. If `immediate` is passed, call
       the callback immediately and hinder future invocations until at
       least the given time has passed.

       If passed only 1 argument, or passed a falsy 2nd argument,
       the default wait time set in this function's $defaultDelay
       property is used.

       Source: underscore.js, by way of https://davidwalsh.name/javascript-debounce-function
    */
    const debounce = function f(func, wait, immediate) {
      var timeout;
      if(!wait) wait = f.$defaultDelay;
      return function() {
        const context = this, args = Array.prototype.slice.call(arguments);
        const later = function() {
          timeout = undefined;
          if(!immediate) func.apply(context, args);
        };
        const callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if(callNow) func.apply(context, args);
      };
    };
    debounce.$defaultDelay = 500 /*arbitrary*/;

    const ForceResizeKludge = (function(){
      /* Workaround for Safari mayhem regarding use of vh CSS
         units....  We cannot use vh units to set the main view
         size because Safari chokes on that, so we calculate
         that height here. Larger than ~95% is too big for
         Firefox on Android, causing the input area to move
         off-screen. */
      const appViews = EAll('.app-view');
      const elemsToCount = [
        /* Elements which we need to always count in the
           visible body size. */
        E('body > header'),
        E('body > footer')
      ];
      const resized = function f(){
        if(f.$disabled) return;
        const wh = window.innerHeight;
        var ht;
        var extra = 0;
        elemsToCount.forEach((e)=>e ? extra += effectiveHeight(e) : false);
        ht = wh - extra;
        appViews.forEach(function(e){
          e.style.height =
            e.style.maxHeight = [
              "calc(", (ht>=100 ? ht : 100), "px",
              " - 2em"/*fudge value*/,")"
              /* ^^^^ hypothetically not needed, but both
                 Chrome/FF on Linux will force scrollbars on the
                 body if this value is too small. */
            ].join('');
        });
      };
      resized.$disabled = true/*gets deleted when setup is finished*/;
      window.addEventListener('resize', debounce(resized, 250), false);
      return resized;
    })();

    /** Set up a selection list of examples */
    (function(){
      const xElem = E('#select-examples');
      const examples = [
        {name: "Help", sql: [
          "-- ================================================\n",
          "-- Use ctrl-enter or shift-enter to execute sqlite3\n",
          "-- shell commands and SQL.\n",
          "-- If a subset of the text is currently selected,\n",
          "-- only that part is executed.\n",
          "-- ================================================\n",
          ".help\n"
        ]},
              //{name: "Timer on", sql: ".timer on"},
              // ^^^ re-enable if emscripten re-enables getrusage()
        {name: "Setup table T", sql:[
          ".nullvalue NULL\n",
          "CREATE TABLE t(a,b);\n",
          "INSERT INTO t(a,b) VALUES('abc',123),('def',456),(NULL,789),('ghi',012);\n",
          "SELECT * FROM t;\n"
        ]},
        {name: "Table list", sql: ".tables"},
        {name: "Box Mode", sql: ".mode box"},
        {name: "JSON Mode", sql: ".mode json"},
        {name: "Mandlebrot", sql:[
          "WITH RECURSIVE",
          "  xaxis(x) AS (VALUES(-2.0) UNION ALL SELECT x+0.05 FROM xaxis WHERE x<1.2),\n",
          "  yaxis(y) AS (VALUES(-1.0) UNION ALL SELECT y+0.1 FROM yaxis WHERE y<1.0),\n",
          "  m(iter, cx, cy, x, y) AS (\n",
          "    SELECT 0, x, y, 0.0, 0.0 FROM xaxis, yaxis\n",
          "    UNION ALL\n",
          "    SELECT iter+1, cx, cy, x*x-y*y + cx, 2.0*x*y + cy FROM m \n",
          "     WHERE (x*x + y*y) < 4.0 AND iter<28\n",
          "  ),\n",
          "  m2(iter, cx, cy) AS (\n",
          "    SELECT max(iter), cx, cy FROM m GROUP BY cx, cy\n",
          "  ),\n",
          "  a(t) AS (\n",
          "    SELECT group_concat( substr(' .+*#', 1+min(iter/7,4), 1), '') \n",
          "    FROM m2 GROUP BY cy\n",
          "  )\n",
          "SELECT group_concat(rtrim(t),x'0a') as Mandelbrot FROM a;\n",
        ]}
      ];
      const newOpt = function(lbl,val){
        const o = document.createElement('option');
        if(Array.isArray(val)) val = val.join('');
        o.value = val;
        if(!val) o.setAttribute('disabled',true);
        o.appendChild(document.createTextNode(lbl));
        xElem.appendChild(o);
      };
      newOpt("Examples (replaces input!)");
      examples.forEach((o)=>newOpt(o.name, o.sql));
      //xElem.setAttribute('disabled',true);
      xElem.selectedIndex = 0;
      xElem.addEventListener('change', function(){
        taInput.value = '-- ' +
          this.selectedOptions[0].innerText +
          '\n' + this.value;
        SF.dbExec(this.value);
      });
    })()/* example queries */;

    //SF.echo(null/*clear any output generated by the init process*/);
    if(window.jQuery && window.jQuery.terminal){
      /* Set up the terminal-style view... */
      const eTerm = window.jQuery('#view-terminal').empty();
      SF.jqTerm = eTerm.terminal(SF.dbExec.bind(SF),{
        prompt: 'sqlite> ',
        greetings: false /* note that the docs incorrectly call this 'greeting' */
      });
      /* Set up a button to toggle the views... */
      const head = E('header#titlebar');
      const btnToggleView = document.createElement('button');
      btnToggleView.appendChild(document.createTextNode("Toggle View"));
      head.appendChild(btnToggleView);
      btnToggleView.addEventListener('click',function f(){
        EAll('.app-view').forEach(e=>e.classList.toggle('hidden'));
        if(document.body.classList.toggle('terminal-mode')){
          ForceResizeKludge();
        }
      }, false);
      btnToggleView.click()/*default to terminal view*/;
    }
    SF.echo('This experimental app is provided in the hope that it',
            'may prove interesting or useful but is not an officially',
            'supported deliverable of the sqlite project. It is subject to',
            'any number of changes or outright removal at any time.\n');
    const urlParams = new URL(self.location.href).searchParams;
    SF.dbExec(urlParams.get('sql') || null);
    delete ForceResizeKludge.$disabled;
    ForceResizeKludge();
  }/*onSFLoaded()*/;
})();

Added ext/wasm/index-dist.html.









































































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<!doctype html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
    <title>sqlite3 WASM Demo Page Index</title>
  </head>
  <body>
    <style>
      body {
          display: flex;
          flex-direction: column;
          flex-wrap: wrap;
      }
      textarea {
          font-family: monospace;
      }
      header {
          font-size: 130%;
          font-weight: bold;
          background: #044a64;
          color: white;
          padding: 0.5em;
          border-radius: 0.25em;
      }
      .hidden, .initially-hidden {
          position: absolute !important;
          opacity: 0 !important;
          pointer-events: none !important;
          display: none !important;
      }
      .warning { color: firebrick; }
    </style>
    <header id='titlebar'><span>sqlite3 WASM demo pages</span></header>
    <hr>
    <div>Below is the list of demo pages for the sqlite3 WASM
      builds. The intent is that <em>this</em> page be run
      using the functional equivalent of:</div>
    <blockquote><pre><a href='https://sqlite.org/althttpd'>althttpd</a> -enable-sab -page index.html</pre></blockquote>
    <div>and the individual pages be started in their own tab.
      Warnings and Caveats:
      <ul class='warning'>
        <li>Some of these pages require that the web server emit the
          so-called
          <a href='https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy'>COOP</a>
          and
          <a href='https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy'>COEP</a>
          headers. <a href='https://sqlite.org/althttpd'>althttpd</a> requires the
          <code>-enable-sab</code> flag for that.
        </li>
      </ul>
    </div>
    <div>The tests and demos...
      <ul id='test-list'>
        <li>Core-most tests
          <ul>
            <li><a href='tester1.html'>tester1</a>: Core unit and
              regression tests for the various APIs and surrounding
              utility code.</li>
            <li><a href='tester1-worker.html'>tester1-worker</a>: same thing
              but running in a Worker.</li>
            <li><a href='tester1-esm.html'>tester1-esm</a>: same as
              <code>tester1</code> but loads sqlite3 in the main thread via
              an ES6 module.
            </li>
            <li><a href='tester1-worker.html?esm'>tester1-worker?esm</a>:
              same as <code>tester1-esm</code> but loads a Worker Module which
              then loads the sqlite3 API via an ES6 module. Note that
              not all browsers permit loading modules in Worker
              threads.
            </li>
          </ul>
        </li>
        <li>Higher-level apps and demos...
          <ul>
            <li><a href='demo-123.html'>demo-123</a> provides a
              no-nonsense example of adding sqlite3 support to a web
              page in the UI thread.</li>
            <li><a href='demo-123-worker.html'>demo-123-worker</a> is
              the same as <code>demo-123</code> but loads and runs
              sqlite3 from a Worker thread.</li>
            <li><a href='demo-jsstorage.html'>demo-jsstorage</a>: very basic
              demo of using the key-value VFS for storing a persistent db
              in JS <code>localStorage</code> or <code>sessionStorage</code>.</li>
            <li><a href='demo-worker1.html'>demo-worker1</a>:
              Worker-based wrapper of the OO API #1. Its Promise-based
              wrapper is significantly easier to use, however.</li>
            <li><a href='demo-worker1-promiser.html'>demo-worker1-promiser</a>:
              a demo of the Promise-based wrapper of the Worker1 API.</li>
          </ul>
        </li>
      </ul>
    </div>
    <style>
      #test-list { font-size: 120%; }
    </style>
    <script>//Assign a distinct target tab name for each test page...
      document.querySelectorAll('a').forEach(function(e){
          e.target = e.href;
      });
    </script>
  </body>
</html>

Added ext/wasm/index.html.











































































































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<!doctype html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
    <link rel="stylesheet" href="common/testing.css"/>
    <title>sqlite3 WASM Testing Page Index</title>
  </head>
  <body>
    <style>
      header {
          background: #044a64;
          color: white;
          padding: 0.5em;
          border-radius: 0.25em;
      }
    </style>
    <header id='titlebar'><span>sqlite3 WASM test pages</span></header>
    <hr>
    <div>Below is the list of test pages for the sqlite3 WASM
      builds. All of them require that this directory have been
      "make"d first. The intent is that <em>this</em> page be run
      using:</div>
    <blockquote><pre>althttpd -enable-sab -page index.html</pre></blockquote>
    <div>and the individual tests be started in their own tab.
      Warnings and Caveats:
      <ul class='warning'>
        <li>Some of these pages require that
          the web server emit the so-called
          <a href='https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy'>COOP</a>
          and
          <a href='https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy'>COEP</a>
          headers. <a href='https://sqlite.org/althttpd'>althttpd</a> requires the
          <code>-enable-sab</code> flag for that.
        </li>
        <li>Any OPFS-related pages require very recent version of
          Chrome or Chromium (v102 at least, possibly newer). OPFS
          support in the other major browsers is pending. Development
          and testing is currently done against a dev-channel release
          of Chrome (v110 as of 2022-12-02).
        </li>
      </ul>
    </div>
    <div>The tests and demos...
      <ul id='test-list'>
        <li>Core-most tests
          <ul>
            <li><a href='tester1.html'>tester1</a>: Core unit and
              regression tests for the various APIs and surrounding
              utility code.</li>
            <li><a href='tester1-worker.html'>tester1-worker</a>: same thing
              but running in a Worker.</li>
            <li><a href='tester1-esm.html'>tester1-esm</a>: same as
              <code>tester1</code> but loads sqlite3 in the main thread via
              an ES6 module.
            </li>
            <li><a href='tester1-worker.html?esm'>tester1-worker?esm</a>:
              same as <code>tester1-esm</code> but loads a Worker Module which
              then loads the sqlite3 API via an ES6 module. Note that
              not all browsers permit loading modules in Worker
              threads.
            </li>
          </ul>
        </li>
        <li>High-level apps and demos...
          <ul>
            <li><a href='fiddle/index.html'>fiddle</a> is an HTML front-end
              to a wasm build of the sqlite3 shell.</li>
            <li><a href='demo-123.html'>demo-123</a> provides a
              no-nonsense example of adding sqlite3 support to a web
              page in the UI thread.</li>
            <li><a href='demo-123-worker.html'>demo-123-worker</a> is
              the same as <code>demo-123</code> but loads and runs
              sqlite3 from a Worker thread.</li>
            <li><a href='demo-jsstorage.html'>demo-jsstorage</a>: very basic
              demo of using the key-value VFS for storing a persistent db
              in JS <code>localStorage</code> or <code>sessionStorage</code>.</li>
            <li><a href='demo-worker1.html'>demo-worker1</a>:
              Worker-based wrapper of the OO API #1. Its Promise-based
              wrapper is significantly easier to use, however.</li>
            <li><a href='demo-worker1-promiser.html'>demo-worker1-promiser</a>:
              a demo of the Promise-based wrapper of the Worker1 API.</li>
          </ul>
        </li>
        <li>speedtest1 ports (sqlite3's primary benchmarking tool)...
          <ul>
            <li><a href='speedtest1.html'>speedtest1</a>: a main-thread WASM build of speedtest1.</li>
            <li><a href='speedtest1.html?vfs=kvvfs'>speedtest1?vfs=kvvfs</a>: speedtest1 with the kvvfs.</li>
            <li><a href='speedtest1-worker.html?size=25'>speedtest1-worker</a>: an interactive Worker-thread variant of speedtest1.</li>
            <li><a href='speedtest1-worker.html?vfs=opfs&size=25'>speedtest1-worker?vfs=opfs</a>: speedtest1-worker with the
              OPFS VFS preselected and configured for a moderate workload.</li>
          </ul>
        </li>
        <li>The obligatory "misc." category...
          <ul>
            <li><a href='module-symbols.html'>module-symbols</a> gives
              a high-level overview of the symbols exposed by the JS
              module.</li>
            <li><a href='batch-runner.html'>batch-runner</a>: runs batches of SQL exported from speedtest1.</li>
            <li><a href='test-opfs-vfs.html'>test-opfs-vfs</a>
              (<a href='test-opfs-vfs.html?opfs-sanity-check&opfs-verbose'>same
              with verbose output and sanity-checking tests</a>) is an
              sqlite3_vfs OPFS proxy using SharedArrayBuffer and the
              Atomics APIs to regulate communication between the
              synchronous sqlite3_vfs interface and the async OPFS
              impl.
            </li>
            <li><a href='tests/opfs/concurrency/index.html'>OPFS concurrency</a>
              tests using multiple workers.
            </li>
          </ul>
        </li>
        <!--li>WASMFS-specific tests which currently do not work due to incompatible changes
          made to the WASMFS+OPFS combination.
          <ul>
            <li><a href='speedtest1-wasmfs.html?flags=--size,25'>speedtest1-wasmfs</a>:
              a variant of speedtest1 built solely for the wasmfs/opfs
              feature.</li>
            <li><a href='scratchpad-wasmfs-main.html'>scratchpad-wasmfs-main</a>:
              experimenting with WASMFS/OPFS-based persistence. Maintenance
              reminder: we cannot currently (2022-09-15) load WASMFS in a
              worker due to an Emscripten wasm loader limitation.</li>
          </ul>
        </li-->
        <!--li><a href='x.html'></a></li-->
      </ul>
    </div>
    <style>
      #test-list { font-size: 120%; }
    </style>
    <script>//Assign a distinct target tab name for each test page...
      document.querySelectorAll('a').forEach(function(e){
          e.target = e.href.replace(/^http*:\/\/[^/]+\//, '');
      });
    </script>
  </body>
</html>

Added ext/wasm/jaccwabyt/jaccwabyt.js.

























































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/**
  2022-06-30

  The author disclaims copyright to this source code.  In place of a
  legal notice, here is a blessing:

  *   May you do good and not evil.
  *   May you find forgiveness for yourself and forgive others.
  *   May you share freely, never taking more than you give.

  ***********************************************************************

  The Jaccwabyt API is documented in detail in an external file,
  _possibly_ called jaccwabyt.md in the same directory as this file.

  Project homes:
  - https://fossil.wanderinghorse.net/r/jaccwabyt
  - https://sqlite.org/src/dir/ext/wasm/jaccwabyt

*/
'use strict';
self.Jaccwabyt = function StructBinderFactory(config){
/* ^^^^ it is recommended that clients move that object into wherever
   they'd like to have it and delete the self-held copy ("self" being
   the global window or worker object).  This API does not require the
   global reference - it is simply installed as a convenience for
   connecting these bits to other co-developed code before it gets
   removed from the global namespace.
*/

  /** Throws a new Error, the message of which is the concatenation
      all args with a space between each. */
  const toss = (...args)=>{throw new Error(args.join(' '))};

  /**
     Implementing function bindings revealed significant
     shortcomings in Emscripten's addFunction()/removeFunction()
     interfaces:

     https://github.com/emscripten-core/emscripten/issues/17323

     Until those are resolved, or a suitable replacement can be
     implemented, our function-binding API will be more limited
     and/or clumsier to use than initially hoped.
  */
  if(!(config.heap instanceof WebAssembly.Memory)
     && !(config.heap instanceof Function)){
    toss("config.heap must be WebAssembly.Memory instance or a function.");
  }
  ['alloc','dealloc'].forEach(function(k){
    (config[k] instanceof Function) ||
      toss("Config option '"+k+"' must be a function.");
  });
  const SBF = StructBinderFactory;
  const heap = (config.heap instanceof Function)
        ? config.heap : (()=>new Uint8Array(config.heap.buffer)),
        alloc = config.alloc,
        dealloc = config.dealloc,
        log = config.log || console.log.bind(console),
        memberPrefix = (config.memberPrefix || ""),
        memberSuffix = (config.memberSuffix || ""),
        bigIntEnabled = (undefined===config.bigIntEnabled
                         ? !!self['BigInt64Array'] : !!config.bigIntEnabled),
        BigInt = self['BigInt'],
        BigInt64Array = self['BigInt64Array'],
        /* Undocumented (on purpose) config options: */
        ptrSizeof = config.ptrSizeof || 4,
        ptrIR = config.ptrIR || 'i32'
  ;

  if(!SBF.debugFlags){
    SBF.__makeDebugFlags = function(deriveFrom=null){
      /* This is disgustingly overengineered. :/ */
      if(deriveFrom && deriveFrom.__flags) deriveFrom = deriveFrom.__flags;
      const f = function f(flags){
        if(0===arguments.length){
          return f.__flags;
        }
        if(flags<0){
          delete f.__flags.getter; delete f.__flags.setter;
          delete f.__flags.alloc; delete f.__flags.dealloc;
        }else{
          f.__flags.getter  = 0!==(0x01 & flags);
          f.__flags.setter  = 0!==(0x02 & flags);
          f.__flags.alloc   = 0!==(0x04 & flags);
          f.__flags.dealloc = 0!==(0x08 & flags);
        }
        return f._flags;
      };
      Object.defineProperty(f,'__flags', {
        iterable: false, writable: false,
        value: Object.create(deriveFrom)
      });
      if(!deriveFrom) f(0);
      return f;
    };
    SBF.debugFlags = SBF.__makeDebugFlags();
  }/*static init*/

  const isLittleEndian = (function() {
    const buffer = new ArrayBuffer(2);
    new DataView(buffer).setInt16(0, 256, true /* littleEndian */);
    // Int16Array uses the platform's endianness.
    return new Int16Array(buffer)[0] === 256;
  })();
  /**
     Some terms used in the internal docs:

     StructType: a struct-wrapping class generated by this
     framework.
     DEF: struct description object.
     SIG: struct member signature string.
  */

  /** True if SIG s looks like a function signature, else
      false. */
  const isFuncSig = (s)=>'('===s[1];
  /** True if SIG s is-a pointer signature. */
  const isPtrSig = (s)=>'p'===s || 'P'===s;
  const isAutoPtrSig = (s)=>'P'===s /*EXPERIMENTAL*/;
  const sigLetter = (s)=>isFuncSig(s) ? 'p' : s[0];
  /** Returns the WASM IR form of the Emscripten-conventional letter
      at SIG s[0]. Throws for an unknown SIG. */
  const sigIR = function(s){
    switch(sigLetter(s)){
        case 'c': case 'C': return 'i8';
        case 'i': return 'i32';
        case 'p': case 'P': case 's': return ptrIR;
        case 'j': return 'i64';
        case 'f': return 'float';
        case 'd': return 'double';
    }
    toss("Unhandled signature IR:",s);
  };

  const affirmBigIntArray = BigInt64Array
        ? ()=>true : ()=>toss('BigInt64Array is not available.');
  /** Returns the name of a DataView getter method corresponding
      to the given SIG. */
  const sigDVGetter = function(s){
    switch(sigLetter(s)) {
        case 'p': case 'P': case 's': {
          switch(ptrSizeof){
              case 4: return 'getInt32';
              case 8: return affirmBigIntArray() && 'getBigInt64';
          }
          break;
        }
        case 'i': return 'getInt32';
        case 'c': return 'getInt8';
        case 'C': return 'getUint8';
        case 'j': return affirmBigIntArray() && 'getBigInt64';
        case 'f': return 'getFloat32';
        case 'd': return 'getFloat64';
    }
    toss("Unhandled DataView getter for signature:",s);
  };
  /** Returns the name of a DataView setter method corresponding
      to the given SIG. */
  const sigDVSetter = function(s){
    switch(sigLetter(s)){
        case 'p': case 'P': case 's': {
          switch(ptrSizeof){
              case 4: return 'setInt32';
              case 8: return affirmBigIntArray() && 'setBigInt64';
          }
          break;
        }
        case 'i': return 'setInt32';
        case 'c': return 'setInt8';
        case 'C': return 'setUint8';
        case 'j': return affirmBigIntArray() && 'setBigInt64';
        case 'f': return 'setFloat32';
        case 'd': return 'setFloat64';
    }
    toss("Unhandled DataView setter for signature:",s);
  };
  /**
     Returns either Number of BigInt, depending on the given
     SIG. This constructor is used in property setters to coerce
     the being-set value to the correct size.
  */
  const sigDVSetWrapper = function(s){
    switch(sigLetter(s)) {
        case 'i': case 'f': case 'c': case 'C': case 'd': return Number;
        case 'j': return affirmBigIntArray() && BigInt;
        case 'p': case 'P': case 's':
          switch(ptrSizeof){
              case 4: return Number;
              case 8: return affirmBigIntArray() && BigInt;
          }
          break;
    }
    toss("Unhandled DataView set wrapper for signature:",s);
  };

  /** Returns the given struct and member name in a form suitable for
      debugging and error output. */
  const sPropName = (s,k)=>s+'::'+k;

  const __propThrowOnSet = function(structName,propName){
    return ()=>toss(sPropName(structName,propName),"is read-only.");
  };

  /**
     In order to completely hide StructBinder-bound struct
     pointers from JS code, we store them in a scope-local
     WeakMap which maps the struct-bound objects to their WASM
     pointers. The pointers are accessible via
     boundObject.pointer, which is gated behind an accessor
     function, but are not exposed anywhere else in the
     object. The main intention of that is to make it impossible
     for stale copies to be made.
  */
  const __instancePointerMap = new WeakMap();

  /** Property name for the pointer-is-external marker. */
  const xPtrPropName = '(pointer-is-external)';

  /** Frees the obj.pointer memory and clears the pointer
      property. */
  const __freeStruct = function(ctor, obj, m){
    if(!m) m = __instancePointerMap.get(obj);
    if(m) {
      __instancePointerMap.delete(obj);
      if(Array.isArray(obj.ondispose)){
        let x;
        while((x = obj.ondispose.shift())){
          try{
            if(x instanceof Function) x.call(obj);
            else if(x instanceof StructType) x.dispose();
            else if('number' === typeof x) dealloc(x);
            // else ignore. Strings are permitted to annotate entries
            // to assist in debugging.
          }catch(e){
            console.warn("ondispose() for",ctor.structName,'@',
                         m,'threw. NOT propagating it.',e);
          }
        }
      }else if(obj.ondispose instanceof Function){
        try{obj.ondispose()}
        catch(e){
          /*do not rethrow: destructors must not throw*/
          console.warn("ondispose() for",ctor.structName,'@',
                       m,'threw. NOT propagating it.',e);
        }
      }
      delete obj.ondispose;
      if(ctor.debugFlags.__flags.dealloc){
        log("debug.dealloc:",(obj[xPtrPropName]?"EXTERNAL":""),
            ctor.structName,"instance:",
            ctor.structInfo.sizeof,"bytes @"+m);
      }
      if(!obj[xPtrPropName]) dealloc(m);
    }
  };

  /** Returns a skeleton for a read-only property accessor wrapping
      value v. */
  const rop = (v)=>{return {configurable: false, writable: false,
                            iterable: false, value: v}};

  /** Allocates obj's memory buffer based on the size defined in
      ctor.structInfo.sizeof. */
  const __allocStruct = function(ctor, obj, m){
    let fill = !m;
    if(m) Object.defineProperty(obj, xPtrPropName, rop(m));
    else{
      m = alloc(ctor.structInfo.sizeof);
      if(!m) toss("Allocation of",ctor.structName,"structure failed.");
    }
    try {
      if(ctor.debugFlags.__flags.alloc){
        log("debug.alloc:",(fill?"":"EXTERNAL"),
            ctor.structName,"instance:",
            ctor.structInfo.sizeof,"bytes @"+m);
      }
      if(fill) heap().fill(0, m, m + ctor.structInfo.sizeof);
      __instancePointerMap.set(obj, m);
    }catch(e){
      __freeStruct(ctor, obj, m);
      throw e;
    }
  };
  /** Gets installed as the memoryDump() method of all structs. */
  const __memoryDump = function(){
    const p = this.pointer;
    return p
      ? new Uint8Array(heap().slice(p, p+this.structInfo.sizeof))
      : null;
  };

  const __memberKey = (k)=>memberPrefix + k + memberSuffix;
  const __memberKeyProp = rop(__memberKey);

  /**
     Looks up a struct member in structInfo.members. Throws if found
     if tossIfNotFound is true, else returns undefined if not
     found. The given name may be either the name of the
     structInfo.members key (faster) or the key as modified by the
     memberPrefix and memberSuffix settings.
  */
  const __lookupMember = function(structInfo, memberName, tossIfNotFound=true){
    let m = structInfo.members[memberName];
    if(!m && (memberPrefix || memberSuffix)){
      // Check for a match on members[X].key
      for(const v of Object.values(structInfo.members)){
        if(v.key===memberName){ m = v; break; }
      }
      if(!m && tossIfNotFound){
        toss(sPropName(structInfo.name,memberName),'is not a mapped struct member.');
      }
    }
    return m;
  };

  /**
     Uses __lookupMember(obj.structInfo,memberName) to find a member,
     throwing if not found. Returns its signature, either in this
     framework's native format or in Emscripten format.
  */
  const __memberSignature = function f(obj,memberName,emscriptenFormat=false){
    if(!f._) f._ = (x)=>x.replace(/[^vipPsjrdcC]/g,"").replace(/[pPscC]/g,'i');
    const m = __lookupMember(obj.structInfo, memberName, true);
    return emscriptenFormat ? f._(m.signature) : m.signature;
  };

  const __ptrPropDescriptor = {
    configurable: false, enumerable: false,
    get: function(){return __instancePointerMap.get(this)},
    set: ()=>toss("Cannot assign the 'pointer' property of a struct.")
    // Reminder: leaving `set` undefined makes assignments
    // to the property _silently_ do nothing. Current unit tests
    // rely on it throwing, though.
  };

  /** Impl of X.memberKeys() for StructType and struct ctors. */
  const __structMemberKeys = rop(function(){
    const a = [];
    for(const k of Object.keys(this.structInfo.members)){
      a.push(this.memberKey(k));
    }
    return a;
  });

  const __utf8Decoder = new TextDecoder('utf-8');
  const __utf8Encoder = new TextEncoder();
  /** Internal helper to use in operations which need to distinguish
      between SharedArrayBuffer heap memory and non-shared heap. */
  const __SAB = ('undefined'===typeof SharedArrayBuffer)
        ? function(){} : SharedArrayBuffer;
  const __utf8Decode = function(arrayBuffer, begin, end){
    return __utf8Decoder.decode(
      (arrayBuffer.buffer instanceof __SAB)
        ? arrayBuffer.slice(begin, end)
        : arrayBuffer.subarray(begin, end)
    );
  };
  /**
     Uses __lookupMember() to find the given obj.structInfo key.
     Returns that member if it is a string, else returns false. If the
     member is not found, throws if tossIfNotFound is true, else
     returns false.
   */
  const __memberIsString = function(obj,memberName, tossIfNotFound=false){
    const m = __lookupMember(obj.structInfo, memberName, tossIfNotFound);
    return (m && 1===m.signature.length && 's'===m.signature[0]) ? m : false;
  };

  /**
     Given a member description object, throws if member.signature is
     not valid for assigning to or interpretation as a C-style string.
     It optimistically assumes that any signature of (i,p,s) is
     C-string compatible.
  */
  const __affirmCStringSignature = function(member){
    if('s'===member.signature) return;
    toss("Invalid member type signature for C-string value:",
         JSON.stringify(member));
  };

  /**
     Looks up the given member in obj.structInfo. If it has a
     signature of 's' then it is assumed to be a C-style UTF-8 string
     and a decoded copy of the string at its address is returned. If
     the signature is of any other type, it throws. If an s-type
     member's address is 0, `null` is returned.
  */
  const __memberToJsString = function f(obj,memberName){
    const m = __lookupMember(obj.structInfo, memberName, true);
    __affirmCStringSignature(m);
    const addr = obj[m.key];
    //log("addr =",addr,memberName,"m =",m);
    if(!addr) return null;
    let pos = addr;
    const mem = heap();
    for( ; mem[pos]!==0; ++pos ) {
      //log("mem[",pos,"]",mem[pos]);
    };
    //log("addr =",addr,"pos =",pos);
    return (addr===pos) ? "" : __utf8Decode(mem, addr, pos);
  };

  /**
     Adds value v to obj.ondispose, creating ondispose,
     or converting it to an array, if needed.
  */
  const __addOnDispose = function(obj, ...v){
    if(obj.ondispose){
      if(!Array.isArray(obj.ondispose)){
        obj.ondispose = [obj.ondispose];
      }
    }else{
      obj.ondispose = [];
    }
    obj.ondispose.push(...v);
  };

  /**
     Allocates a new UTF-8-encoded, NUL-terminated copy of the given
     JS string and returns its address relative to heap(). If
     allocation returns 0 this function throws. Ownership of the
     memory is transfered to the caller, who must eventually pass it
     to the configured dealloc() function.
  */
  const __allocCString = function(str){
    const u = __utf8Encoder.encode(str);
    const mem = alloc(u.length+1);
    if(!mem) toss("Allocation error while duplicating string:",str);
    const h = heap();
    //let i = 0;
    //for( ; i < u.length; ++i ) h[mem + i] = u[i];
    h.set(u, mem);
    h[mem + u.length] = 0;
    //log("allocCString @",mem," =",u);
    return mem;
  };

  /**
     Sets the given struct member of obj to a dynamically-allocated,
     UTF-8-encoded, NUL-terminated copy of str. It is up to the caller
     to free any prior memory, if appropriate. The newly-allocated
     string is added to obj.ondispose so will be freed when the object
     is disposed.

     The given name may be either the name of the structInfo.members
     key (faster) or the key as modified by the memberPrefix and
     memberSuffix settings.
  */
  const __setMemberCString = function(obj, memberName, str){
    const m = __lookupMember(obj.structInfo, memberName, true);
    __affirmCStringSignature(m);
    /* Potential TODO: if obj.ondispose contains obj[m.key] then
       dealloc that value and clear that ondispose entry */
    const mem = __allocCString(str);
    obj[m.key] = mem;
    __addOnDispose(obj, mem);
    return obj;
  };

  /**
     Prototype for all StructFactory instances (the constructors
     returned from StructBinder).
  */
  const StructType = function ctor(structName, structInfo){
    if(arguments[2]!==rop){
      toss("Do not call the StructType constructor",
           "from client-level code.");
    }
    Object.defineProperties(this,{
      //isA: rop((v)=>v instanceof ctor),
      structName: rop(structName),
      structInfo: rop(structInfo)
    });
  };

  /**
     Properties inherited by struct-type-specific StructType instances
     and (indirectly) concrete struct-type instances.
  */
  StructType.prototype = Object.create(null, {
    dispose: rop(function(){__freeStruct(this.constructor, this)}),
    lookupMember: rop(function(memberName, tossIfNotFound=true){
      return __lookupMember(this.structInfo, memberName, tossIfNotFound);
    }),
    memberToJsString: rop(function(memberName){
      return __memberToJsString(this, memberName);
    }),
    memberIsString: rop(function(memberName, tossIfNotFound=true){
      return __memberIsString(this, memberName, tossIfNotFound);
    }),
    memberKey: __memberKeyProp,
    memberKeys: __structMemberKeys,
    memberSignature: rop(function(memberName, emscriptenFormat=false){
      return __memberSignature(this, memberName, emscriptenFormat);
    }),
    memoryDump: rop(__memoryDump),
    pointer: __ptrPropDescriptor,
    setMemberCString: rop(function(memberName, str){
      return __setMemberCString(this, memberName, str);
    })
  });
  // Function-type non-Property inherited members 
  Object.assign(StructType.prototype,{
    addOnDispose: function(...v){
      __addOnDispose(this,...v);
      return this;
    }
  });

  /**
     "Static" properties for StructType.
  */
  Object.defineProperties(StructType, {
    allocCString: rop(__allocCString),
    isA: rop((v)=>v instanceof StructType),
    hasExternalPointer: rop((v)=>(v instanceof StructType) && !!v[xPtrPropName]),
    memberKey: __memberKeyProp
  });

  const isNumericValue = (v)=>Number.isFinite(v) || (v instanceof (BigInt || Number));

  /**
     Pass this a StructBinder-generated prototype, and the struct
     member description object. It will define property accessors for
     proto[memberKey] which read from/write to memory in
     this.pointer. It modifies descr to make certain downstream
     operations much simpler.
  */
  const makeMemberWrapper = function f(ctor,name, descr){
    if(!f._){
      /*cache all available getters/setters/set-wrappers for
        direct reuse in each accessor function. */
      f._ = {getters: {}, setters: {}, sw:{}};
      const a = ['i','c','C','p','P','s','f','d','v()'];
      if(bigIntEnabled) a.push('j');
      a.forEach(function(v){
        //const ir = sigIR(v);
        f._.getters[v] = sigDVGetter(v) /* DataView[MethodName] values for GETTERS */;
        f._.setters[v] = sigDVSetter(v) /* DataView[MethodName] values for SETTERS */;
        f._.sw[v] = sigDVSetWrapper(v)  /* BigInt or Number ctor to wrap around values
                                           for conversion */;
      });
      const rxSig1 = /^[ipPsjfdcC]$/,
            rxSig2 = /^[vipPsjfdcC]\([ipPsjfdcC]*\)$/;
      f.sigCheck = function(obj, name, key,sig){
        if(Object.prototype.hasOwnProperty.call(obj, key)){
          toss(obj.structName,'already has a property named',key+'.');
        }
        rxSig1.test(sig) || rxSig2.test(sig)
          || toss("Malformed signature for",
                  sPropName(obj.structName,name)+":",sig);
      };
    }
    const key = ctor.memberKey(name);
    f.sigCheck(ctor.prototype, name, key, descr.signature);
    descr.key = key;
    descr.name = name;
    const sigGlyph = sigLetter(descr.signature);
    const xPropName = sPropName(ctor.prototype.structName,key);
    const dbg = ctor.prototype.debugFlags.__flags;
    /*
      TODO?: set prototype of descr to an object which can set/fetch
      its prefered representation, e.g. conversion to string or mapped
      function. Advantage: we can avoid doing that via if/else if/else
      in the get/set methods.
    */
    const prop = Object.create(null);
    prop.configurable = false;
    prop.enumerable = false;
    prop.get = function(){
      if(dbg.getter){
        log("debug.getter:",f._.getters[sigGlyph],"for", sigIR(sigGlyph),
            xPropName,'@', this.pointer,'+',descr.offset,'sz',descr.sizeof);
      }
      let rc = (
        new DataView(heap().buffer, this.pointer + descr.offset, descr.sizeof)
      )[f._.getters[sigGlyph]](0, isLittleEndian);
      if(dbg.getter) log("debug.getter:",xPropName,"result =",rc);
      return rc;
    };
    if(descr.readOnly){
      prop.set = __propThrowOnSet(ctor.prototype.structName,key);
    }else{
      prop.set = function(v){
        if(dbg.setter){
          log("debug.setter:",f._.setters[sigGlyph],"for", sigIR(sigGlyph),
              xPropName,'@', this.pointer,'+',descr.offset,'sz',descr.sizeof, v);
        }
        if(!this.pointer){
          toss("Cannot set struct property on disposed instance.");
        }
        if(null===v) v = 0;
        else while(!isNumericValue(v)){
          if(isAutoPtrSig(descr.signature) && (v instanceof StructType)){
            // It's a struct instance: let's store its pointer value!
            v = v.pointer || 0;
            if(dbg.setter) log("debug.setter:",xPropName,"resolved to",v);
            break;
          }
          toss("Invalid value for pointer-type",xPropName+'.');
        }
        (
          new DataView(heap().buffer, this.pointer + descr.offset, descr.sizeof)
        )[f._.setters[sigGlyph]](0, f._.sw[sigGlyph](v), isLittleEndian);
      };
    }
    Object.defineProperty(ctor.prototype, key, prop);
  }/*makeMemberWrapper*/;
  
  /**
     The main factory function which will be returned to the
     caller.
  */
  const StructBinder = function StructBinder(structName, structInfo){
    if(1===arguments.length){
      structInfo = structName;
      structName = structInfo.name;
    }else if(!structInfo.name){
      structInfo.name = structName;
    }
    if(!structName) toss("Struct name is required.");
    let lastMember = false;
    Object.keys(structInfo.members).forEach((k)=>{
      // Sanity checks of sizeof/offset info...
      const m = structInfo.members[k];
      if(!m.sizeof) toss(structName,"member",k,"is missing sizeof.");
      else if(m.sizeof===1){
        (m.signature === 'c' || m.signature === 'C') ||
          toss("Unexpected sizeof==1 member",
               sPropName(structInfo.name,k),
               "with signature",m.signature);
      }else{
        // sizes and offsets of size-1 members may be odd values, but
        // others may not.
        if(0!==(m.sizeof%4)){
          console.warn("Invalid struct member description =",m,"from",structInfo);
          toss(structName,"member",k,"sizeof is not aligned. sizeof="+m.sizeof);
        }
        if(0!==(m.offset%4)){
          console.warn("Invalid struct member description =",m,"from",structInfo);
          toss(structName,"member",k,"offset is not aligned. offset="+m.offset);
        }
      }
      if(!lastMember || lastMember.offset < m.offset) lastMember = m;
    });
    if(!lastMember) toss("No member property descriptions found.");
    else if(structInfo.sizeof < lastMember.offset+lastMember.sizeof){
      toss("Invalid struct config:",structName,
           "max member offset ("+lastMember.offset+") ",
           "extends past end of struct (sizeof="+structInfo.sizeof+").");
    }
    const debugFlags = rop(SBF.__makeDebugFlags(StructBinder.debugFlags));
    /** Constructor for the StructCtor. */
    const StructCtor = function StructCtor(externalMemory){
      if(!(this instanceof StructCtor)){
        toss("The",structName,"constructor may only be called via 'new'.");
      }else if(arguments.length){
        if(externalMemory!==(externalMemory|0) || externalMemory<=0){
          toss("Invalid pointer value for",structName,"constructor.");
        }
        __allocStruct(StructCtor, this, externalMemory);
      }else{
        __allocStruct(StructCtor, this);
      }
    };
    Object.defineProperties(StructCtor,{
      debugFlags: debugFlags,
      isA: rop((v)=>v instanceof StructCtor),
      memberKey: __memberKeyProp,
      memberKeys: __structMemberKeys,
      methodInfoForKey: rop(function(mKey){
      }),
      structInfo: rop(structInfo),
      structName: rop(structName)
    });
    StructCtor.prototype = new StructType(structName, structInfo, rop);
    Object.defineProperties(StructCtor.prototype,{
      debugFlags: debugFlags,
      constructor: rop(StructCtor)
      /*if we assign StructCtor.prototype and don't do
        this then StructCtor!==instance.constructor!*/
    });
    Object.keys(structInfo.members).forEach(
      (name)=>makeMemberWrapper(StructCtor, name, structInfo.members[name])
    );
    return StructCtor;
  };
  StructBinder.StructType = StructType;
  StructBinder.config = config;
  StructBinder.allocCString = __allocCString;
  if(!StructBinder.debugFlags){
    StructBinder.debugFlags = SBF.__makeDebugFlags(SBF.debugFlags);
  }
  return StructBinder;
}/*StructBinderFactory*/;

Added ext/wasm/jaccwabyt/jaccwabyt.md.











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Jaccwabyt 🐇
============================================================

**Jaccwabyt**: _JavaScript ⇄ C Struct Communication via WASM Byte
Arrays_

Welcome to Jaccwabyt, a JavaScript API which creates bindings for
WASM-compiled C structs, defining them in such a way that changes to
their state in JS are visible in C/WASM, and vice versa, permitting
two-way interchange of struct state with very little user-side
friction.

(If that means nothing to you, neither will the rest of this page!)

**Browser compatibility**: this library requires a _recent_ browser
and makes no attempt whatsoever to accommodate "older" or
lesser-capable ones, where "recent," _very roughly_, means released in
mid-2018 or later, with late 2021 releases required for some optional
features in some browsers (e.g. [BigInt64Array][] in Safari). It also
relies on a couple non-standard, but widespread, features, namely
[TextEncoder][] and [TextDecoder][]. It is developed primarily on
Firefox and Chrome on Linux and all claims of Safari compatibility
are based solely on feature compatibility tables provided at
[MDN][].

**Formalities:**

- Author: [Stephan Beal][sgb]
- Project Homes:
  - <https://fossil.wanderinghorse.net/r/jaccwabyt>\  
    Is the primary home but...
  - <https://sqlite.org/src/dir/ext/wasm/jaccwabyt>\  
    ... most development happens here.

The license for both this documentation and the software it documents
is the same as [sqlite3][], the project from which this spinoff
project was spawned:

-----

> 2022-06-30:
>
> 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.

-----

<a name='overview'></a>
Table of Contents
============================================================

- [Overview](#overview)
  - [Architecture](#architecture)
- [Creating and Binding Structs](#creating-binding)
  - [Step 1: Configure Jaccwabyt](#step-1)
  - [Step 2: Struct Description](#step-2)
     - [`P` vs `p`](#step-2-pvsp)
  - [Step 3: Binding a Struct](#step-3)
  - [Step 4: Creating, Using, and Destroying Instances](#step-4)
- APIs
  - [Struct Binder Factory](#api-binderfactory)
  - [Struct Binder](#api-structbinder)
  - [Struct Type](#api-structtype)
  - [Struct Constructors](#api-structctor)
  - [Struct Protypes](#api-structprototype)
  - [Struct Instances](#api-structinstance)
- Appendices
  - [Appendix A: Limitations, TODOs, etc.](#appendix-a)
  - [Appendix D: Debug Info](#appendix-d)
  - [Appendix G: Generating Struct Descriptions](#appendix-g)

<a name='overview'></a>
Overview
============================================================

Management summary: this JavaScript-only framework provides limited
two-way bindings between C structs and JavaScript objects, such that
changes to the struct in one environment are visible in the other.

Details...

It works by creating JavaScript proxies for C structs. Reads and
writes of the JS-side members are marshaled through a flat byte array
allocated from the WASM heap. As that heap is shared with the C-side
code, and the memory block is written using the same approach C does,
that byte array can be used to access and manipulate a given struct
instance from both JS and C.

Motivating use case: this API was initially developed as an
experiment to determine whether it would be feasible to implement,
completely in JS, custom "VFS" and "virtual table" objects for the
WASM build of [sqlite3][]. Doing so was going to require some form of
two-way binding of several structs.  Once the proof of concept was
demonstrated, a rabbit hole appeared and _down we went_... It has
since grown beyond its humble proof-of-concept origins and is believed
to be a useful (or at least interesting) tool for mixed JS/C
applications.

Portability notes:

- These docs sometimes use [Emscripten][] as a point of reference
  because it is the most widespread WASM toolchain, but this code is
  specifically designed to be usable in arbitrary WASM environments.
  It abstracts away a few Emscripten-specific features into
  configurable options. Similarly, the build tree requires Emscripten
  but Jaccwabyt does not have any hard Emscripten dependencies.
- This code is encapsulated into a single JavaScript function. It
  should be trivial to copy/paste into arbitrary WASM/JS-using
  projects.
- The source tree includes C code, but only for testing and
  demonstration purposes. It is not part of the core distributable.

<a name='architecture'></a>
Architecture
------------------------------------------------------------

<!--
bug(?) (fossil): using "center" shrinks pikchr too much.
-->

```pikchr
BSBF: box rad 0.3*boxht "StructBinderFactory" fit fill lightblue
BSB: box same "StructBinder" fit at 0.75 e of 0.7 s of BSBF.c
BST: box same "StructType<T>" fit at 1.5 e of BSBF
BSC: box same "Struct<T>" "Ctor" fit at 1.5 s of BST
BSI: box same "Struct<T>" "Instances" fit at 1 right of BSB.e
BC: box same at 0.25 right of 1.6 e of BST "C Structs" fit fill lightgrey

arrow -> from BSBF.s to BSB.w "Generates" aligned above
arrow -> from BSB.n to BST.sw "Contains" aligned above
arrow -> from BSB.s to BSC.nw "Generates" aligned below
arrow -> from BSC.ne to BSI.s "Constructs" aligned below
arrow <- from BST.se to BSI.n "Inherits" aligned above
arrow <-> from BSI.e to BC.s dotted "Shared" aligned above "Memory" aligned below
arrow -> from BST.e to BC.w dotted "Mirrors Struct" aligned above "Model From" aligned below
arrow -> from BST.s to BSC.n "Prototype of" aligned above
```

Its major classes and functions are:

- **[StructBinderFactory][StructBinderFactory]** is a factory function which
  accepts a configuration object to customize it for a given WASM
  environment. A client will typically call this only one time, with
  an appropriate configuration, to generate a single...
- **[StructBinder][]** is a factory function which converts an
  arbitrary number struct descriptions into...
- **[StructTypes][StructCtors]** are constructors, one per struct
  description, which inherit from
  **[`StructBinder.StructType`][StructType]** and are used to instantiate...
- **[Struct instances][StructInstance]** are objects representing
  individual instances of generated struct types.

An app may have any number of StructBinders, but will typically
need only one. Each StructBinder is effectively a separate
namespace for struct creation.


<a name='creating-binding'></a>
Creating and Binding Structs
============================================================

From the amount of documentation provided, it may seem that
creating and using struct bindings is a daunting task, but it
essentially boils down to:

1. [Confire Jaccwabyt for your WASM environment](#step-1). This is a
   one-time task per project and results is a factory function which
   can create new struct bindings.
2. [Create a JSON-format description of your C structs](#step-2). This is
   required once for each struct and required updating if the C
   structs change.
3. [Feed (2) to the function generated by (1)](#step-3) to create JS
   constuctor functions for each struct. This is done at runtime, as
   opposed to during a build-process step, and can be set up in such a
   way that it does not require any maintenace after its initial
   setup.
4. [Create and use instances of those structs](#step-4).

Detailed instructions for each of those steps follows...

<a name='step-1'></a>
Step 1: Configure Jaccwabyt for the Environment
------------------------------------------------------------

Jaccwabyt's highest-level API is a single function. It creates a
factory for processing struct descriptions, but does not process any
descriptions itself. This level of abstraction exist primarily so that
the struct-specific factories can be configured for a given WASM
environment. Its usage looks like:

>  
```javascript
const MyBinder = StructBinderFactory({
  // These config options are all required:
  heap: WebAssembly.Memory instance or a function which returns
        a Uint8Array or Int8Array view of the WASM memory,
  alloc:   function(howMuchMemory){...},
  dealloc: function(pointerToFree){...}
});
```

It also offers a number of other settings, but all are optional except
for the ones shown above. Those three config options abstract away
details which are specific to a given WASM environment. They provide
the WASM "heap" memory (a byte array), the memory allocator, and the
deallocator. In a conventional Emscripten setup, that config might
simply look like:

>  
```javascript
{
    heap:    Module['asm']['memory'],
    //Or:
    // heap: ()=>Module['HEAP8'],
    alloc:   (n)=>Module['_malloc'](n),
    dealloc: (m)=>Module['_free'](m)
}
```

The StructBinder factory function returns a function which can then be
used to create bindings for our structs.

<a name='step-2'></a>
Step 2: Create a Struct Description
------------------------------------------------------------

The primary input for this framework is a JSON-compatible construct
which describes a struct we want to bind. For example, given this C
struct:

>  
```c
// C-side:
struct Foo {
  int member1;
  void * member2;
  int64_t member3;
};
```

Its JSON description looks like:

>  
```json
{
  "name": "Foo",
  "sizeof": 16,
  "members": {
    "member1": {"offset": 0,"sizeof": 4,"signature": "i"},
    "member2": {"offset": 4,"sizeof": 4,"signature": "p"},
    "member3": {"offset": 8,"sizeof": 8,"signature": "j"}
  }
}
```

These data _must_ match up with the C-side definition of the struct
(if any). See [Appendix G][appendix-g] for one way to easily generate
these from C code.

Each entry in the `members` object maps the member's name to
its low-level layout:

- `offset`: the byte offset from the start of the struct, as reported
  by C's `offsetof()` feature.
- `sizeof`: as reported by C's `sizeof()`.
- `signature`: described below.
- `readOnly`: optional. If set to true, the binding layer will
  throw if JS code tries to set that property.

The order of the `members` entries is not important: their memory
layout is determined by their `offset` and `sizeof` members. The
`name` property is technically optional, but one of the steps in the
binding process requires that either it be passed an explicit name or
there be one in the struct description. The names of the `members`
entries need not match their C counterparts. Project conventions may
call for giving them different names in the JS side and the
[StructBinderFactory][] can be configured to automatically add a
prefix and/or suffix to their names.

Nested structs are as-yet unsupported by this tool.

Struct member "signatures" describe the data types of the members and
are an extended variant of the format used by Emscripten's
`addFunction()`. A signature for a non-function-pointer member, or
function pointer member which is to be modelled as an opaque pointer,
is a single letter. A signature for a function pointer may also be
modelled as a series of letters describing the call signature. The
supported letters are:

- **`v`** = `void` (only used as return type for function pointer members)
- **`i`** = `int32` (4 bytes)
- **`j`** = `int64` (8 bytes) is only really usable if this code is built
  with BigInt support (e.g. using the Emscripten `-sWASM_BIGINT` build
  flag). Without that, this API may throw when encountering the `j`
  signature entry.
- **`f`** = `float` (4 bytes)
- **`d`** = `double` (8 bytes)
- **`c`** = `int8` (1 byte) char - see notes below!
- **`C`** = `uint8` (1 byte) unsigned char - see notes below!
- **`p`** = `int32` (see notes below!)
- **`P`** = Like `p` but with extra handling. Described below.
- **`s`** = like `int32` but is a _hint_ that it's a pointer to a
  string so that _some_ (very limited) contexts may treat it as such,
  noting that such algorithms must, for lack of information to the
  contrary, assume both that the encoding is UTF-8 and that the
  pointer's member is NUL-terminated. If that is _not_ the case for a
  given string member, do not use `s`: use `i` or `p` instead and do
  any string handling yourself.

Noting that:

- **All of these types are numeric**. Attempting to set any
  struct-bound property to a non-numeric value will trigger an
  exception except in cases explicitly noted otherwise.
- **"Char" types**: WASM does not define an `int8` type, nor does it
  distinguish between signed and unsigned. This API treats `c` as
  `int8` and `C` as `uint8` for purposes of getting and setting values
  when using the `DataView` class. It is _not_ recommended that client
  code use these types in new WASM-capable code, but they were added
  for the sake of binding some immutable legacy code to WASM.

> Sidebar: Emscripten's public docs do not mention `p`, but their
generated code includes `p` as an alias for `i`, presumably to mean
"pointer". Though `i` is legal for pointer types in the signature, `p`
is more descriptive, so this framework encourages the use of `p` for
pointer-type members. Using `p` for pointers also helps future-proof
the signatures against the eventuality that WASM eventually supports
64-bit pointers. Note that sometimes `p` really means
pointer-to-pointer, but the Emscripten JS/WASM glue does not offer
that level of expressiveness in these signatures. We simply have to be
aware of when we need to deal with pointers and pointers-to-pointers
in JS code.

> Trivia: this API treates `p` as distinctly different from `i` in
some contexts, so its use is encouraged for pointer types.

Signatures in the form `x(...)` denote function-pointer members and
`x` denotes non-function members. Functions with no arguments use the
form `x()`. For function-type signatures, the strings are formulated
such that they can be passed to Emscripten's `addFunction()` after
stripping out the `(` and `)` characters. For good measure, to match
the public Emscripten docs, `p`, `c`, and `C`, should also be replaced
with `i`. In JavaScript that might look like:

>  
```
signature.replace(/[^vipPsjfdcC]/g,'').replace(/[pPscC]/g,'i');
```

<a name='step-2-pvsp'></a>
### `P` vs `p` in Method Signatures

*This support is experimental and subject to change.*

The method signature letter `p` means "pointer," which, in WASM, means
"integer." `p` is treated as an integer for most contexts, while still
also being a separate type (analog to how pointers in C are just a
special use of unsigned numbers). A capital `P` changes the semantics
of plain member pointers (but not, as of this writing, function
pointer members) as follows:

- When a `P`-type member is **set** via `myStruct.x=y`, if
  [`(y instanceof StructType)`][StructType] then the value of `y.pointer` is
  stored in `myStruct.x`. If `y` is neither a number nor
  a [StructType][], an exception is triggered (regardless of whether
  `p` or `P` is used).


<a name='step-3'></a>
Step 3: Binding the Struct
------------------------------------------------------------

We can now use the results of steps 1 and 2:

>  
```javascript
const MyStruct = MyBinder(myStructDescription);
```

That creates a new constructor function, `MyStruct`, which can be used
to instantiate new instances. The binder will throw if it encounters
any problems.

That's all there is to it.

> Sidebar: that function may modify the struct description object
and/or its sub-objects, or may even replace sub-objects, in order to
simplify certain later operations. If that is not desired, then feed
it a copy of the original, e.g. by passing it
`JSON.parse(JSON.stringify(structDefinition))`.

<a name='step-4'></a>
Step 4: Creating, Using, and Destroying Struct Instances
------------------------------------------------------------

Now that we have our constructor...

>  
```javascript
const my = new MyStruct();
```

It is important to understand that creating a new instance allocates
memory on the WASM heap. We must not simply rely on garbage collection
to clean up the instances because doing so will not free up the WASM
heap memory. The correct way to free up that memory is to use the
object's `dispose()` method.

The following usage pattern offers one way to easily ensure proper
cleanup of struct instances:

>  
```javascript
const my = new MyStruct();
try {
  console.log(my.member1, my.member2, my.member3);
  my.member1 = 12;
  assert(12 === my.member1);
  /* ^^^ it may seem silly to test that, but recall that assigning that
     property encodes the value into a byte array in heap memory, not
     a normal JS property. Similarly, fetching the property decodes it
     from the byte array. */
  // Pass the struct to C code which takes a MyStruct pointer:
  aCFunction( my.pointer );
} finally {
  my.dispose();
}
```

> Sidebar: the `finally` block will be run no matter how the `try`
exits, whether it runs to completion, propagates an exception, or uses
flow-control keywords like `return` or `break`. It is perfectly legal
to use `try`/`finally` without a `catch`, and doing so is an ideal
match for the memory management requirements of Jaccwaby-bound struct
instances.

It is often useful to wrap an existing instance of a C-side struct
without taking over ownership of its memory. That can be achieved by
simply passing a pointer to the constructor. For example:

```js
const m = new MyStruct( functionReturningASharedPtr() );
// calling m.dispose() will _not_ free the wrapped C-side instance
// but will trigger any ondispose handler.
```

Now that we have struct instances, there are a number of things we
can do with them, as covered in the rest of this document.


<a name='api'></a>
API Reference
============================================================

<a name='api-binderfactory'></a>
API: Binder Factory
------------------------------------------------------------

This is the top-most function of the API, from which all other
functions and types are generated. The binder factory's signature is:

>  
```
Function StructBinderFactory(object configOptions);
```

It returns a function which these docs refer to as a [StructBinder][]
(covered in the next section). It throws on error.

The binder factory supports the following options in its
configuration object argument:


- `heap`  
  Must be either a `WebAssembly.Memory` instance representing the WASM
  heap memory OR a function which returns an Int8Array or Uint8Array
  view of the WASM heap. In the latter case the function should, if
  appropriate for the environment, account for the heap being able to
  grow. Jaccwabyt uses this property in such a way that it "should" be
  okay for the WASM heap to grow at runtime (that case is, however,
  untested).

- `alloc`  
  Must be a function semantically compatible with Emscripten's
  `Module._malloc()`. That is, it is passed the number of bytes to
  allocate and it returns a pointer. On allocation failure it may
  either return 0 or throw an exception. This API will throw an
  exception if allocation fails or will propagate whatever exception
  the allocator throws. The allocator _must_ use the same heap as the
  `heap` config option.

- `dealloc`  
  Must be a function semantically compatible with Emscripten's
  `Module._free()`. That is, it takes a pointer returned from
  `alloc()` and releases that memory. It must never throw and must
  accept a value of 0/null to mean "do nothing" (noting that 0 is
  _technically_ a legal memory address in WASM, but that seems like a
  design flaw).

- `bigIntEnabled` (bool=true if BigInt64Array is available, else false)  
  If true, the WASM bits this code is used with must have been
  compiled with int64 support (e.g. using Emscripten's `-sWASM_BIGINT`
  flag). If that's not the case, this flag should be set to false. If
  it's enabled, BigInt support is assumed to work and certain extra
  features are enabled. Trying to use features which requires BigInt
  when it is disabled (e.g. using 64-bit integer types) will trigger
  an exception.

- `memberPrefix` and `memberSuffix` (string="")  
  If set, struct-defined properties get bound to JS with this string
  as a prefix resp. suffix. This can be used to avoid symbol name
  collisions between the struct-side members and the JS-side ones
  and/or to make more explicit which object-level properties belong to
  the struct mapping and which to the JS side. This does not modify
  the values in the struct description objects, just the property
  names through which they are accessed via property access operations
  and the various a [StructInstance][] APIs (noting that the latter
  tend to permit both the original names and the names as modified by
  these settings).

- `log`  
  Optional function used for debugging output. By default
  `console.log` is used but by default no debug output is generated.
  This API assumes that the function will space-separate each argument
  (like `console.log` does). See [Appendix D](#appendix-d) for info
  about enabling debugging output.


<a name='api-structbinder'></a>
API: Struct Binder
------------------------------------------------------------

Struct Binders are factories which are created by the
[StructBinderFactory][].  A given Struct Binder can process any number
of distinct structs. In a typical setup, an app will have ony one
shared Binder Factory and one Struct Binder. Struct Binders which are
created via different [StructBinderFactory][] calls are unrelated to each
other, sharing no state except, perhaps, indirectly via
[StructBinderFactory][] configuration (e.g. the memory heap).

These factories have two call signatures:

>  
```javascript
Function StructBinder([string structName,] object structDescription)
```

If the struct description argument has a `name` property then the name
argument is optional, otherwise it is required.

The returned object is a constructor for instances of the struct
described by its argument(s), each of which derives from
a separate [StructType][] instance.

The Struct Binder has the following members:

- `allocCString(str)`  
  Allocates a new UTF-8-encoded, NUL-terminated copy of the given JS
  string and returns its address relative to `config.heap()`. If
  allocation returns 0 this function throws. Ownership of the memory
  is transfered to the caller, who must eventually pass it to the
  configured `config.dealloc()` function.

- `config`  
  The configuration object passed to the [StructBinderFactory][],
  primarily for accessing the memory (de)allocator and memory. Modifying
  any of its "significant" configuration values may have undefined
  results.

<a name='api-structtype'></a>
API: Struct Type
------------------------------------------------------------

The StructType class is a property of the [StructBinder][] function.

Each constructor created by a [StructBinder][] inherits from _its own
instance_ of the StructType class, which contains state specific to
that struct type (e.g. the struct name and description metadata).
StructTypes which are created via different [StructBinder][] instances
are unrelated to each other, sharing no state except [StructBinderFactory][]
config options.

The StructType constructor cannot be called from client code. It is
only called by the [StructBinder][]-generated
[constructors][StructCtors]. The `StructBinder.StructType` object
has the following "static" properties (^Which are accessible from
individual instances via `theInstance.constructor`.):

- `addOnDispose(...value)`\  
  If this object has no `ondispose` property, this function creates it
  as an array and pushes the given value(s) onto it. If the object has
  a function-typed `ondispose` property, this call replaces it with an
  array and moves that function into the array. In all other cases,
  `ondispose` is assumed to be an array and the argument(s) is/are
  appended to it. Returns `this`.

- `allocCString(str)`  
  Identical to the [StructBinder][] method of the same name.

- `hasExternalPointer(object)`  
  Returns true if the given object's `pointer` member refers to an
  "external" object. That is the case when a pointer is passed to a
  [struct's constructor][StructCtors]. If true, the memory is owned by
  someone other than the object and must outlive the object.

- `isA(value)`  
  Returns true if its argument is a StructType instance _from the same
  [StructBinder][]_ as this StructType.

- `memberKey(string)`  
  Returns the given string wrapped in the configured `memberPrefix`
  and `memberSuffix` values. e.g. if passed `"x"` and `memberPrefix`
  is `"$"` then it returns `"$x"`. This does not verify that the
  property is actually a struct a member, it simply transforms the
  given string.  TODO(?): add a 2nd parameter indicating whether it
  should validate that it's a known member name.

The base StructType prototype has the following members, all of which
are inherited by [struct instances](#api-structinstance) and may only
legally be called on concrete struct instances unless noted otherwise:

- `dispose()`  
  Frees, if appropriate, the WASM-allocated memory which is allocated
  by the constructor. If this is not called before the JS engine
  cleans up the object, a leak in the WASM heap memory pool will result.  
  When `dispose()` is called, if the object has a property named `ondispose`
  then it is treated as follows:  
  - If it is a function, it is called with the struct object as its `this`.
  That method must not throw - if it does, the exception will be
  ignored.
  - If it is an array, it may contain functions, pointers, other
    [StructType] instances, and/or JS strings. If an entry is a
    function, it is called as described above. If it's a number, it's
    assumed to be a pointer and is passed to the `dealloc()` function
    configured for the parent [StructBinder][]. If it's a
    [StructType][] instance then its `dispose()` method is called. If
    it's a JS string, it's assumed to be a helpful description of the
    next entry in the list and is simply ignored. Strings are
    supported primarily for use as debugging information.
  - Some struct APIs will manipulate the `ondispose` member, creating
    it as an array or converting it from a function to array as
    needed.

- `lookupMember(memberName,throwIfNotFound=true)`  
  Given the name of a mapped struct member, it returns the member
  description object. If not found, it either throws (if the 2nd
  argument is true) or returns `undefined` (if the second argument is
  false). The first argument may be either the member name as it is
  mapped in the struct description or that same name with the
  configured `memberPrefix` and `memberSuffix` applied, noting that
  the lookup in the former case is faster.\  
  This method may be called directly on the prototype, without a
  struct instance.

- `memberToJsString(memberName)`  
  Uses `this.lookupMember(memberName,true)` to look up the given
  member. If its signature is `s` then it is assumed to refer to a
  NUL-terminated, UTF-8-encoded string and its memory is decoded as
  such. If its signature is not one of those then an exception is
  thrown.  If its address is 0, `null` is returned. See also:
  `setMemberCString()`.

- `memberIsString(memberName [,throwIfNotFound=true])`  
  Uses `this.lookupMember(memberName,throwIfNotFound)` to look up the
  given member. Returns the member description object if the member
  has a signature of `s`, else returns false. If the given member is
  not found, it throws if the 2nd argument is true, else it returns
  false.

- `memberKey(string)`  
  Works identically to `StructBinder.StructType.memberKey()`.

- `memberKeys()`  
  Returns an array of the names of the properties of this object
  which refer to C-side struct counterparts.

- `memberSignature(memberName [,emscriptenFormat=false])`  
  Returns the signature for a given a member property, either in this
  framework's format or, if passed a truthy 2nd argument, in a format
  suitable for the 2nd argument to Emscripten's `addFunction()`.
  Throws if the first argument does not resolve to a struct-bound
  member name. The member name is resolved using `this.lookupMember()`
  and throws if the member is found mapped.

- `memoryDump()`  
  Returns a Uint8Array which contains the current state of this
  object's raw memory buffer. Potentially useful for debugging, but
  not much else. Note that the memory is necessarily, for
  compatibility with C, written in the host platform's endianness and
  is thus not useful as a persistent/portable serialization format.

- `setMemberCString(memberName,str)`  
  Uses `StructType.allocCString()` to allocate a new C-style string,
  assign it to the given member, and add the new string to this
  object's `ondispose` list for cleanup when `this.dispose()` is
  called. This function throws if `lookupMember()` fails for the given
  member name, if allocation of the string fails, or if the member has
  a signature value of anything other than `s`. Returns `this`.  
  *Achtung*: calling this repeatedly will not immediately free the
  previous values because this code cannot know whether they are in
  use in other places, namely C. Instead, each time this is called,
  the prior value is retained in the `ondispose` list for cleanup when
  the struct is disposed of. Because of the complexities and general
  uncertainties of memory ownership and lifetime in such
  constellations, it is recommended that the use of C-string members
  from JS be kept to a minimum or that the relationship be one-way:
  let C manage the strings and only fetch them from JS using, e.g.,
  `memberToJsString()`.
  

<a name='api-structctor'></a>
API: Struct Constructors
------------------------------------------------------------

Struct constructors (the functions returned from [StructBinder][])
are used for, intuitively enough, creating new instances of a given
struct type:

>  
```
const x = new MyStruct;
```

Normally they should be passed no arguments, but they optionally
accept a single argument: a WASM heap pointer address of memory
which the object will use for storage. It does _not_ take over
ownership of that memory and that memory must be valid at
for least as long as this struct instance. This is used, for example,
to proxy static/shared C-side instances:

>  
```
const x = new MyStruct( someCFuncWhichReturnsAMyStructPointer() );
...
x.dispose(); // does NOT free the memory
```

The JS-side construct does not own the memory in that case and has no
way of knowing when the C-side struct is destroyed. Results are
specifically undefined if the JS-side struct is used after the C-side
struct's member is freed.

> Potential TODO: add a way of passing ownership of the C-side struct
to the JS-side object. e.g. maybe simply pass `true` as the second
argument to tell the constructor to take over ownership. Currently the
pointer can be taken over using something like
`myStruct.ondispose=[myStruct.pointer]` immediately after creation.

These constructors have the following "static" members:

- `isA(value)`  
  Returns true if its argument was created by this constructor.

- `memberKey(string)`  
  Works exactly as documented for [StructType][].

- `memberKeys(string)`  
  Works exactly as documented for [StructType][].

- `structInfo`  
  The structure description passed to [StructBinder][] when this
  constructor was generated.

- `structName`  
  The structure name passed to [StructBinder][] when this constructor
  was generated.
  

<a name='api-structprototype'></a>
API: Struct Prototypes
------------------------------------------------------------

The prototypes of structs created via [the constructors described in
the previous section][StructCtors] are each a struct-type-specific
instance of [StructType][] and add the following struct-type-specific
properties to the mix:

- `structInfo`  
  The struct description metadata, as it was given to the
  [StructBinder][] which created this class.

- `structName`  
  The name of the struct, as it was given to the [StructBinder][] which
  created this class.

<a name='api-structinstance'></a>
API: Struct Instances
------------------------------------------------------------------------

Instances of structs created via [the constructors described
above][StructCtors] each have the following instance-specific state in
common:

- `pointer`  
  A read-only numeric property which is the "pointer" returned by the
  configured allocator when this object is constructed. After
  `dispose()` (inherited from [StructType][]) is called, this property
  has the `undefined` value. When calling C-side code which takes a
  pointer to a struct of this type, simply pass it `myStruct.pointer`.

<a name='appendices'></a>
Appendices
============================================================

<a name='appendix-a'></a>
Appendix A: Limitations, TODOs, and Non-TODOs
------------------------------------------------------------

- This library only supports the basic set of member types supported
  by WASM: numbers (which includes pointers). Nested structs are not
  handled except that a member may be a _pointer_ to such a
  struct. Whether or not it ever will depends entirely on whether its
  developer ever needs that support. Conversion of strings between
  JS and C requires infrastructure specific to each WASM environment
  and is not directly supported by this library.

- Binding functions to struct instances, such that C can see and call
  JS-defined functions, is not as transparent as it really could be,
  due to [shortcomings in the Emscripten
  `addFunction()`/`removeFunction()`
  interfaces](https://github.com/emscripten-core/emscripten/issues/17323). Until
  a replacement for that API can be written, this support will be
  quite limited. It _is_ possible to bind a JS-defined function to a
  C-side function pointer and call that function from C. What's
  missing is easier-to-use/more transparent support for doing so.
  - In the meantime, a [standalone
  subproject](/file/common/whwasmutil.js) of Jaccwabyt provides such a
  binding mechanism, but integrating it directly with Jaccwabyt would
  not only more than double its size but somehow feels inappropriate, so
  experimentation is in order for how to offer that capability via
  completely optional [StructBinderFactory][] config options.

- It "might be interesting" to move access of the C-bound members into
  a sub-object. e.g., from JS they might be accessed via
  `myStructInstance.s.structMember`. The main advantage is that it would
  eliminate any potential confusion about which members are part of
  the C struct and which exist purely in JS. "The problem" with that
  is that it requires internally mapping the `s` member back to the
  object which contains it, which makes the whole thing more costly
  and adds one more moving part which can break. Even so, it's
  something to try out one rainy day. Maybe even make it optional and
  make the `s` name configurable via the [StructBinderFactory][]
  options. (Over-engineering is an arguably bad habit of mine.)

- It "might be interesting" to offer (de)serialization support. It
  would be very limited, e.g. we can't serialize arbitrary pointers in
  any meaningful way, but "might" be useful for structs which contain
  only numeric or C-string state. As it is, it's easy enough for
  client code to write wrappers for that and handle the members in
  ways appropriate to their apps. Any impl provided in this library
  would have the shortcoming that it may inadvertently serialize
  pointers (since they're just integers), resulting in potential chaos
  after deserialization. Perhaps the struct description can be
  extended to tag specific members as serializable and how to
  serialize them.

<a name='appendix-d'></a>
Appendix D: Debug Info
------------------------------------------------------------

The [StructBinderFactory][], [StructBinder][], and [StructType][] classes
all have the following "unsupported" method intended primarily
to assist in their own development, as opposed to being for use in
client code:

- `debugFlags(flags)` (integer)  
  An "unsupported" debugging option which may change or be removed at
  any time. Its argument is a set of flags to enable/disable certain
  debug/tracing output for property accessors: 0x01 for getters, 0x02
  for setters, 0x04 for allocations, 0x08 for deallocations. Pass 0 to
  disable all flags and pass a negative value to _completely_ clear
  all flags. The latter has the side effect of telling the flags to be
  inherited from the next-higher-up class in the hierarchy, with
  [StructBinderFactory][] being top-most, followed by [StructBinder][], then
  [StructType][].


<a name='appendix-g'></a>
Appendix G: Generating Struct Descriptions From C
------------------------------------------------------------

Struct definitions are _ideally_ generated from WASM-compiled C, as
opposed to simply guessing the sizeofs and offsets, so that the sizeof
and offset information can be collected using C's `sizeof()` and
`offsetof()` features (noting that struct padding may impact offsets
in ways which might not be immediately obvious, so writing them by
hand is _most certainly not recommended_).

How exactly the desciption is generated is necessarily
project-dependent. It's tempting say, "oh, that's easy! We'll just
write it by hand!" but that would be folly. The struct sizes and byte
offsets into the struct _must_ be precisely how C-side code sees the
struct or the runtime results are completely undefined.

The approach used in developing and testing _this_ software is...

Below is a complete copy/pastable example of how we can use a small
set of macros to generate struct descriptions from C99 or later into
static string memory. Simply add such a file to your WASM build,
arrange for its function to be exported[^export-func], and call it
from JS (noting that it requires environment-specific JS glue to
convert the returned pointer to a JS-side string). Use `JSON.parse()`
to process it, then feed the included struct descriptions into the
binder factory at your leisure.

------------------------------------------------------------

```c
#include <string.h> /* memset() */
#include <stddef.h> /* offsetof() */
#include <stdio.h>  /* snprintf() */
#include <stdint.h> /* int64_t */
#include <assert.h>

struct ExampleStruct {
  int v4;
  void * ppV;
  int64_t v8;
  void (*xFunc)(void*);
};
typedef struct ExampleStruct ExampleStruct;

const char * wasm__ctype_json(void){
  static char strBuf[512 * 8] = {0}
    /* Static buffer which must be sized large enough for
       our JSON. The string-generation macros try very
       hard to assert() if this buffer is too small. */;
  int n = 0, structCount = 0 /* counters for the macros */;
  char * pos = &strBuf[1]
    /* Write-position cursor. Skip the first byte for now to help
       protect against a small race condition */;
  char const * const zEnd = pos + sizeof(strBuf)
    /* one-past-the-end cursor (virtual EOF) */;
  if(strBuf[0]) return strBuf; // Was set up in a previous call.

  ////////////////////////////////////////////////////////////////////
  // First we need to build up our macro framework...

  ////////////////////////////////////////////////////////////////////
  // Core output-generating macros...
#define lenCheck assert(pos < zEnd - 100)
#define outf(format,...) \
  pos += snprintf(pos, ((size_t)(zEnd - pos)), format, __VA_ARGS__); \
  lenCheck
#define out(TXT) outf("%s",TXT)
#define CloseBrace(LEVEL) \
  assert(LEVEL<5); memset(pos, '}', LEVEL); pos+=LEVEL; lenCheck

  ////////////////////////////////////////////////////////////////////
  // Macros for emiting StructBinders...
#define StructBinder__(TYPE)                 \
  n = 0;                                     \
  outf("%s{", (structCount++ ? ", " : ""));  \
  out("\"name\": \"" # TYPE "\",");          \
  outf("\"sizeof\": %d", (int)sizeof(TYPE)); \
  out(",\"members\": {");
#define StructBinder_(T) StructBinder__(T)
// ^^^ extra indirection needed to expand CurrentStruct
#define StructBinder StructBinder_(CurrentStruct)
#define _StructBinder CloseBrace(2)
#define M(MEMBER,SIG)                                         \
  outf("%s\"%s\": "                                           \
       "{\"offset\":%d,\"sizeof\": %d,\"signature\":\"%s\"}", \
       (n++ ? ", " : ""), #MEMBER,                            \
       (int)offsetof(CurrentStruct,MEMBER),                   \
       (int)sizeof(((CurrentStruct*)0)->MEMBER),              \
       SIG)
  // End of macros.
  ////////////////////////////////////////////////////////////////////

  ////////////////////////////////////////////////////////////////////
  // With that out of the way, we can do what we came here to do.
  out("\"structs\": ["); {

// For each struct description, do...
#define CurrentStruct ExampleStruct
    StructBinder {
      M(v4,"i");
      M(ppV,"p");
      M(v8,"j");
      M(xFunc,"v(p)");
    } _StructBinder;
#undef CurrentStruct

  } out( "]"/*structs*/);
  ////////////////////////////////////////////////////////////////////
  // Done! Finalize the output...
  out("}"/*top-level wrapper*/);
  *pos = 0;
  strBuf[0] = '{'/*end of the race-condition workaround*/;
  return strBuf;

// If this file will ever be concatenated or #included with others,
// it's good practice to clean up our macros:
#undef StructBinder
#undef StructBinder_
#undef StructBinder__
#undef M
#undef _StructBinder
#undef CloseBrace
#undef out
#undef outf
#undef lenCheck
}
```

------------------------------------------------------------

<style>
div.content {
  counter-reset: h1 -1;
}
div.content h1, div.content h2, div.content h3 {
  border-radius: 0.25em;
  border-bottom: 1px solid #70707070;
}
div.content h1 {
  counter-reset: h2;
}
div.content h1::before, div.content h2::before, div.content h3::before {
  background-color: #a5a5a570;
  margin-right: 0.5em;
  border-radius: 0.25em;
}
div.content h1::before {
  counter-increment: h1;
  content: counter(h1) ;
  padding: 0 0.5em;
  border-radius: 0.25em;
}
div.content h2::before {
  counter-increment: h2;
  content: counter(h1) "." counter(h2);
  padding: 0 0.5em 0 1.75em;
  border-radius: 0.25em;
}
div.content h2 {
  counter-reset: h3;
}
div.content h3::before {
  counter-increment: h3;
  content: counter(h1) "." counter(h2) "." counter(h3);
  padding: 0 0.5em 0 2.5em;
}
div.content h3 {border-left-width: 2.5em}
</style>

[sqlite3]: https://sqlite.org
[emscripten]: https://emscripten.org
[sgb]: https://wanderinghorse.net/home/stephan/
[appendix-g]: #appendix-g
[StructBinderFactory]: #api-binderfactory
[StructCtors]: #api-structctor
[StructType]: #api-structtype
[StructBinder]: #api-structbinder
[StructInstance]: #api-structinstance
[^export-func]: In Emscripten, add its name, prefixed with `_`, to the
  project's `EXPORT_FUNCTIONS` list.
[BigInt64Array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt64Array
[TextDecoder]: https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder
[TextEncoder]: https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder
[MDN]: https://developer.mozilla.org/docs/Web/API

Added ext/wasm/module-symbols.html.



















































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<!doctype html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
    <title>sqlite3 Module Symbols</title>
    <style>
      body {
          font-size: 12.5pt;
          padding-bottom: 1em;
      }
      </style>
  </head>
  <body>
<div class="fossil-doc" data-title="sqlite3 Module Symbols"><!-- EXTRACT_BEGIN -->
<!--
    The part of this doc wrapped in div.fossil-doc gets snipped out
    from the canonical copy in the main tree (ext/wasm/module-symbols.html)
    and added to the wasm docs repository, where it's served from
    fossil.
-->
  <style>
    .pseudolist {
        column-count: auto;
        column-width: 12rem;
        column-gap: 1.5em;
        width: 90%;
        margin: auto;
    }
    .pseudolist.wide {
        column-width: 21rem;
    }
    .pseudolist.wide2 {
        column-width: 25rem;
    }
    .pseudolist > span {
        font-family: monospace;
        margin: 0.25em 0;
        display: block;
    }
    .pseudolist.wrap-anywhere {
        overflow-wrap: anywhere;
    }
    .warning { color: firebrick }
    .error { color: firebrick; background-color: yellow}
    .hidden, .initially-hidden {
        position: absolute !important;
        opacity: 0 !important;
        pointer-events: none !important;
        display: none !important;
    }
    h1::before, h2::before, h3::before, h4::before {
        /* Remove automatic numbering */
        content: "" !important;
        background-color: transparent !important;
        margin: 0 !important;
        border: 0 !important;
        padding: 0 !important;
    }
    .func-wasm {
        
    }
    .func-wasm::after {
        content: "WASM";
        color: saddlebrown;
        /* ^^^^ the color must be legible in both "bright" and "dark"
           s    ite themes. */
        font-size: 0.65em;
    /* baseline-shift: super; */
        vertical-align: super;
    }
  </style>
  <p id='module-load-status'><strong>Loading WASM module...</strong>
    If this takes "a long time" it may have failed and the browser's
    dev console may contain hints as to why.
  </p>

  <p>
    This page lists the SQLite3 APIs exported
    by <code>sqlite3.wasm</code> and exposed to clients
    by <code>sqlite3.js</code>. These lists are generated dynamically
    by loading the JS/WASM module and introspecting it, with the following
    caveats:
  </p>

  <ul>
    <li>Some APIs are explicitly filtered out of these lists because
      they are strictly for internal use within the JS/WASM APIs and
      its own test code.
    </li>
    <li>This page runs in the main UI thread so cannot see features
      which are only available in a Worker thread. If this page were
      to function via a Worker, it would not be able to see
      functionality only available in the main thread. Either way, it
      would be missing certain APIs.
    </li>
  </ul>

  <div class='initially-hidden'>

    <p>This page exposes a global symbol named <code>sqlite3</code>
      which can be inspected using the browser's dev tools.
    </p>

    <p>Jump to...</p>
    <ul>
      <li><a href='#sqlite3-namespace'><code>sqlite3</code> namespace</a></li>
      <li><a href='#sqlite3-version'><code>sqlite3.version</code> object</a></li>
      <li><a href='#sqlite3-functions'><code>sqlite3_...()</code> functions</a></li>
      <li><a href='#sqlite3-constants'><code>SQLITE_...</code> constants</a></li>
      <li><a href='#sqlite3.oo1'><code>sqlite3.oo1</code> namespace</a>
        <!--ul>
          <li><a href='#sqlite3.oo1.DB'><code>sqlite3.oo1.DB</code></a></li>
          <li><a href='#sqlite3.oo1.Stmt'><code>sqlite3.oo1.Stmt</code></a></li>
        </ul-->
      </li>
      <li><a href='#sqlite3.wasm'><code>sqlite3.wasm</code> namespace</a></li>
      <li><a href='#sqlite3.wasm.pstack'><code>sqlite3.wasm.pstack</code> namespace</a></li>
      <li><a href='#compile-options'>Compilation options used in this module build</a></li>
    </ul>

    <a id="sqlite3-namespace"></a>
    <h1><code>sqlite3</code> Namespace</h1>
    <p>
      The <code>sqlite3</code> namespace object exposes the following...
    </p>
    <div id='list-namespace' class='pseudolist'></div>

    <a id="sqlite3-version"></a>
    <h1><code>sqlite3.version</code> Object</h1>
    <p>
      The <code>sqlite3.version</code> object exposes the following...
    </p>
    <div id='list-version' class='pseudolist wide wrap-anywhere'></div>

    <a id="sqlite3-functions"></a>
    <h1><code>sqlite3_...()</code> Function List</h1>

    <p>The <code>sqlite3.capi</code> namespace exposes the following
      <a href='https://sqlite.org/c3ref/funclist.html'><code>sqlite3_...()</code>
        functions</a>...
    </p>
    <div id='list-functions' class='pseudolist wide'></div>
    <p>
      <code class='func-wasm'></code> = function is specific to the JS/WASM
      bindings, not part of the C API.
    </p>

    <a id="sqlite3-constants"></a>
    <h1><code>SQLITE_...</code> Constants</h1>

    <p>The <code>sqlite3.capi</code> namespace exposes the following
      <a href='https://sqlite.org/c3ref/constlist.html'><code>SQLITE_...</code>
        constants</a>...
    </p>
    <div id='list-constants' class='pseudolist wide'></div>

    <a id="sqlite3.oo1"></a>
    <h1><code>sqlite3.oo1</code> Namespace</h1>
    <p>
      The <code>sqlite3.oo1</code> namespace exposes the following...
    </p>
    <div id='list-oo1' class='pseudolist'></div>

    <a id="sqlite3.wasm"></a>
    <h1><code>sqlite3.wasm</code> Namespace</h1>
    <p>
      The <code>sqlite3.wasm</code> namespace exposes the
      following...
    </p>
    <div id='list-wasm' class='pseudolist'></div>

    <a id="sqlite3.wasm.pstack"></a>
    <h1><code>sqlite3.wasm.pstack</code> Namespace</h1>
    <p>
      The <code>sqlite3.wasm.pstack</code> namespace exposes the
      following...
    </p>
    <div id='list-wasm-pstack' class='pseudolist'></div>

    <a id="compile-options"></a>
    <h1>Compilation Options</h1>
    <p>
      <code>SQLITE_...</code> compilation options used in this build
      of <code>sqlite3.wasm</code>...
    </p>
    <div id='list-compile-options' class='pseudolist wide2'></div>

  </div><!-- .initially-hidden -->
  <script src="jswasm/sqlite3.js">/* This tag MUST be inside the
  fossil-doc block so that this part can work without modification in
  the wasm docs repo.  */</script>
  <script>(async function(){
    const apiLinks = Object.assign(Object.create(null),{
        sqlite3_aggregate_context: 'www:/c3ref/aggregate_context.html',
        sqlite3_auto_extension: 'wasm:/api-c-style.md#auto-extension',
        sqlite3_bind_blob: 'www:/c3ref/bind_blob.html',
        sqlite3_bind_double: 'www:/c3ref/bind_blob.html',
        sqlite3_bind_int: 'www:/c3ref/bind_blob.html',
        sqlite3_bind_int64: 'www:/c3ref/bind_blob.html',
        sqlite3_bind_null: 'www:/c3ref/bind_blob.html',
        sqlite3_bind_parameter_count: 'www:/c3ref/bind_parameter_count.html',
        sqlite3_bind_parameter_index: 'www:/c3ref/bind_parameter_index.html',
        sqlite3_bind_pointer: 'www:/c3ref/bind_blob.html',
        sqlite3_bind_text: 'www:/c3ref/bind_blob.html',
        sqlite3_busy_handler: 'www:/c3ref/busy_handler.html',
        sqlite3_busy_timeout: 'www:/c3ref/busy_timeout.html',
        sqlite3_cancel_auto_extension: 'wasm:/api-c-style.md#auto-extension',
        sqlite3_changes: 'www:/c3ref/changes.html',
        sqlite3_changes64: 'www:/c3ref/changes.html',
        sqlite3_clear_bindings: 'www:/c3ref/clear_bindings.html',
        sqlite3_close_v2: 'www:/c3ref/close.html',
        sqlite3_collation_needed: 'www:/c3ref/collation_needed.html',
        sqlite3_column_blob: 'www:/c3ref/column_blob.html',
        sqlite3_column_bytes: 'www:/c3ref/column.html',
        sqlite3_column_count: 'www:/c3ref/column_count.html',
        sqlite3_column_double: 'www:/c3ref/column_blob.html',
        sqlite3_column_int: 'www:/c3ref/column_blob.html',
        sqlite3_column_int64: 'www:/c3ref/column_blob.html',
        sqlite3_column_name: 'www:/c3ref/column_name.html',
        sqlite3_column_text: 'www:/c3ref/column_blob.html',
        sqlite3_column_type: 'www:/c3ref/column_blob.html',
        sqlite3_column_value: 'www:/c3ref/column_blob.html',
        sqlite3_commit_hook: 'wasm:/api-c-style.md#hook-api',
        sqlite3_compileoption_get: 'www:/c3ref/compileoption_get.html',
        sqlite3_compileoption_used: 'www:/c3ref/compileoption_get.html',
        sqlite3_complete: 'www:/c3ref/complete.html',
        sqlite3_config: 'www:/c3ref/config.html',
        sqlite3_context_db_handle: 'www:/c3ref/context_db_handle.html',
        sqlite3_create_collation: 'www:/c3ref/create_collation.html',
        sqlite3_create_collation_v2: 'www:/c3ref/create_collation.html',
        sqlite3_create_function: 'wasm:/api-c-style.md#sqlite3_create_function',
        sqlite3_create_function_v2: 'wasm:/api-c-style.md#sqlite3_create_function',
        sqlite3_create_module: 'www:/c3ref/create_module.html',
        sqlite3_create_module_v2: 'www:/c3ref/create_module.html',
        sqlite3_create_window_function: 'wasm:/api-c-style.md#sqlite3_create_function',
        sqlite3_db_config: 'wasm:/api-c-style.md#sqlite3_db_config',
        sqlite3_data_count: 'www:/c3ref/data_count.html',
        sqlite3_db_filename: 'www:/c3ref/db_filename.html',
        sqlite3_db_handle: 'www:/c3ref/db_handle.html',
        sqlite3_db_name: 'www:/c3ref/db_name.html',
        sqlite3_db_status: 'www:/c3ref/db_status.html',
        sqlite3_declare_vtab: 'www:/c3ref/declare_vtab.html',
        sqlite3_deserialize: 'wasm:/api-c-style.md#sqlite3_deserialize',
        sqlite3_drop_modules: 'www:/c3ref/drop_modules.html',
        sqlite3_errcode: 'www:/c3ref/errcode.html',
        sqlite3_errmsg: 'www:/c3ref/errcode.html',
        sqlite3_error_offset: 'www:/c3ref/error_offset.html',
        sqlite3_errstr: 'www:/c3ref/errcode.html',
        sqlite3_exec: 'wasm:/api-c-style.md#sqlite3_exec',
        sqlite3_expanded_sql: 'www:/c3ref/expanded_sql.html',
        sqlite3_extended_errcode: 'www:/c3ref/errcode.html',
        sqlite3_extended_result_codes: 'www:/c3ref/extended_result_codes.html',
        sqlite3_file_control: 'www:/c3ref/file_control.html',
        sqlite3_finalize: 'www:/c3ref/finalize.html',
        sqlite3_free: 'www:/c3ref/free.html',
        sqlite3_get_auxdata: 'www:/c3ref/get_auxdata.html',
        sqlite3_initialize: 'www:/c3ref/initialize.html',
        sqlite3_keyword_check: 'www:/c3ref/keyword_check.html',
        sqlite3_keyword_count: 'www:/c3ref/keyword_check.html',
        sqlite3_keyword_name: 'www:/c3ref/keyword_check.html',
        sqlite3_last_insert_rowid: 'www:/c3ref/last_insert_rowid.html',
        sqlite3_libversion: 'www:/c3ref/libversion.html',
        sqlite3_libversion_number: 'www:/c3ref/libversion.html',
        sqlite3_limit: 'www:/c3ref/limit.html',
        sqlite3_malloc: 'www:/c3ref/free.html',
        sqlite3_malloc64: 'www:/c3ref/free.html',
        sqlite3_msize: 'www:/c3ref/free.html',
        sqlite3_open: 'www:/c3ref/open.html',
        sqlite3_open_v2: 'www:/c3ref/open.html',
        sqlite3_overload_function: 'www:/c3ref/overload_function.html',
        sqlite3_prepare_v2: 'wasm:/api-c-style.md#sqlite3_prepare_v2',
        sqlite3_prepare_v3: 'wasm:/api-c-style.md#sqlite3_prepare_v2',
        sqlite3_progress_handler: 'www:/c3ref/progress_handler.html',
        sqlite3_randomness: 'wasm:/api-c-style.md#sqlite3_randomness',
        sqlite3_realloc: 'www:/c3ref/free.html',
        sqlite3_realloc64: 'www:/c3ref/free.html',
        sqlite3_reset: 'www:/c3ref/reset.html',
        sqlite3_reset_auto_extension: 'wasm:/api-c-style.md#auto-extension',
        sqlite3_result_blob: 'www:/c3ref/result_blob.html',
        sqlite3_result_double: 'www:/c3ref/result_blob.html',
        sqlite3_result_error: 'www:/c3ref/result_blob.html',
        sqlite3_result_error_code: 'www:/c3ref/result_blob.html',
        sqlite3_result_error_nomem: 'www:/c3ref/result_blob.html',
        sqlite3_result_error_toobig: 'www:/c3ref/result_blob.html',
        sqlite3_result_int: 'www:/c3ref/result_blob.html',
        sqlite3_result_int64: 'www:/c3ref/result_blob.html',
        sqlite3_result_null: 'www:/c3ref/result_blob.html',
        sqlite3_result_pointer: 'www:/c3ref/result_blob.html',
        sqlite3_result_subtype: 'www:/c3ref/result_subtype.html',
        sqlite3_result_text: 'www:/c3ref/result_blob.html',
        sqlite3_result_zeroblob: 'www:/c3ref/result_blob.html',
        sqlite3_result_zeroblob64: 'www:/c3ref/result_blob.html',
        sqlite3_rollback_hook: 'wasm:/api-c-style.md#hook-api',
        sqlite3_serialize: 'www:/c3ref/serialize.html',
        sqlite3_set_authorizer: 'wasm:/api-c-style.md#sqlite3_set_authorizer',
        sqlite3_set_auxdata: 'www:/c3ref/get_auxdata.html',
        sqlite3_set_last_insert_rowid: 'www:/c3ref/set_last_insert_rowid',
        sqlite3_shutdown: 'www:/c3ref/initialize.html',
        sqlite3_sourceid: 'www:/c3ref/libversion.html',
        sqlite3_sql: 'www:/c3ref/expanded_sql.html',
        sqlite3_status: 'www:/c3ref/status.html',
        sqlite3_status64: 'www:/c3ref/status.html',
        sqlite3_step: 'www:/c3ref/step.html',
        sqlite3_stmt_isexplain: 'www:/c3ref/stmt_isexplain.html',
        sqlite3_stmt_readonly: 'www:/c3ref/stmt_readonly.html',
        sqlite3_stmt_status: 'www:/c3ref/stmt_status.html',
        sqlite3_strglob: 'www:/c3ref/strglob.html',
        sqlite3_stricmp: 'www:/c3ref/stricmp.html',
        sqlite3_strlike: 'www:/c3ref/strlike.html',
        sqlite3_strnicmp: 'www:/c3ref/strnicmp.html',
        sqlite3_table_column_metadata: 'www:/c3ref/table_column_metadata.html',
        sqlite3_total_changes: 'www:/c3ref/total_changes.html',
        sqlite3_total_changes64: 'www:/c3ref/total_changes.html',
        sqlite3_trace_v2: 'www:/c3ref/trace_v2.html',
        sqlite3_txn_state: 'www:/c3ref/txn_state.html',
        sqlite3_update_hook: 'wasm:/api-c-style.md#hook-api',
        sqlite3_uri_boolean: 'www:/c3ref/uri_boolean.html',
        sqlite3_uri_int64: 'www:/c3ref/uri_boolean.html',
        sqlite3_uri_key: 'www:/c3ref/uri_boolean.html',
        sqlite3_uri_parameter: 'www:/c3ref/uri_boolean.html',
        sqlite3_user_data: 'www:/c3ref/user_data.html',
        sqlite3_value_blob: 'www:/c3ref/value_blob.html',
        sqlite3_value_bytes: 'www:/c3ref/value_blob.html',
        sqlite3_value_double: 'www:/c3ref/value_blob.html',
        sqlite3_value_dup: 'www:/c3ref/value_dup.html',
        sqlite3_value_free: 'www:/c3ref/value_dup.html',
        sqlite3_value_frombind: 'www:/c3ref/value_blob.html',
        sqlite3_value_int: 'www:/c3ref/value_blob.html',
        sqlite3_value_int64: 'www:/c3ref/value_blob.html',
        sqlite3_value_nochange: 'www:/c3ref/value_blob.html',
        sqlite3_value_numeric_type: 'www:/c3ref/value_blob.html',
        sqlite3_value_pointer: 'www:/c3ref/value_blob.html',
        sqlite3_value_subtype: 'www:/c3ref/value_subtype.html',
        sqlite3_value_text: 'www:/c3ref/value_blob.html',
        sqlite3_value_type: 'www:/c3ref/value_blob.html',
        sqlite3_vfs_find: 'www:/c3ref/vfs_find.html',
        sqlite3_vfs_register: 'www:/c3ref/vfs_find.html',
        sqlite3_vfs_unregister: 'www:/c3ref/vfs_find.html',
        sqlite3_vtab_collation: 'www:/c3ref/vtab_collation.html',
        sqlite3_vtab_config: 'www:/c3ref/vtab_config.html',
        sqlite3_vtab_distinct: 'www:/c3ref/vtab_distinct.html',
        sqlite3_vtab_in: 'www:/c3ref/vtab_in.html',
        sqlite3_vtab_in_first: 'www:/c3ref/vtab_in_first.html',
        sqlite3_vtab_in_next: 'www:/c3ref/vtab_in_next.html',
        sqlite3_vtab_nochange: 'www:/c3ref/vtab_nochange.html',
        sqlite3_vtab_on_conflict: 'www:/c3ref/vtab_on_conflict.html',
        sqlite3_vtab_rhs_value: 'www:/c3ref/vtab_rhs_value.html',

        sqlite3_column_js: 'wasm:/api-c-style.md#sqlite3_column_js',
        sqlite3_js_aggregate_context: 'wasm:/api-c-style.md#sqlite3_js_aggregate_context',
        sqlite3_js_db_export: 'wasm:/api-c-style.md#sqlite3_js_db_export',
        sqlite3_js_db_uses_vfs: 'wasm:/api-c-style.md#sqlite3_js_db_uses_vfs',
        sqlite3_js_db_vfs: 'wasm:/api-c-style.md#sqlite3_js_db_vfs',
        sqlite3_js_kvvfs_clear: 'wasm:/api-c-style.md#sqlite3_js_kvvfs',
        sqlite3_js_kvvfs_size: 'wasm:/api-c-style.md#sqlite3_js_kvvfs',
        sqlite3_js_rc_str: 'wasm:/api-c-style.md#sqlite3_js_rc_str',
        sqlite3_js_vfs_create_file: 'wasm:/api-c-style.md#sqlite3_js_vfs_create_file',
        sqlite3_js_vfs_list: 'wasm:/api-c-style.md#sqlite3_js_vfs_list',
        sqlite3_result_error_js: 'wasm:/api-c-style.md#sqlite3_result_error_js',
        sqlite3_result_js: 'wasm:/api-c-style.md#sqlite3_result_js',
        sqlite3_value_to_js: 'wasm:/api-c-style.md#sqlite3_value_to_js',
        sqlite3_values_to_js: 'wasm:/api-c-style.md#sqlite3_values_to_js',
        
        xform: (v)=>{
            if(v){
                return v.replace('www:','https://sqlite.org')
                    .replace('wasm:','https://sqlite.org/wasm/doc/trunk');
            }else{
                return undefined;
            }
        }
    });
    const eNew = (tag,parent)=>{
        const e = document.createElement(tag);
        if(parent) parent.appendChild(e);
        return e;
    };
    const eLi = (label,parent)=>{
        const e = eNew('span',parent);
        e.innerText = label;
        return e;
    };
    const eLink = (label,url,parent)=>{
        const w = eNew('span',parent);
        const e = eNew('a',w);
        if(url){
            e.href = url;
            e.target = 'sqlite3-api-docs';
        }
        e.innerText = label;
        return w;
    };
    const E = (sel)=>document.querySelector(sel);
    const EAll = (sel)=>document.querySelectorAll(sel);
    const eFuncs = E('#list-functions'),
          eConst = E('#list-constants');
    const renderConst = function(name){
        eLi(name, eConst);
    };
    const renderFunc = function(name){
        let lbl = name+'()';
        const e = eLink(lbl, apiLinks.xform(apiLinks[name]), eFuncs);
        if(name.indexOf('_js')>0
           || name.indexOf('_wasm')>0){
            e.classList.add('func-wasm');
        }
    };
    const renderGeneric = function(name,value,eParent){
        let lbl;
        if(value instanceof Function) lbl = name+'()';
        else{
            switch(typeof value){
                case 'number': case 'boolean': case 'string':
                    lbl = name+' = '+JSON.stringify(value);
                    break;
                default:
                    lbl = name + ' ['+(typeof value)+']';
            }
        }
        const e = eLi(lbl, eParent);
        if(name.startsWith('sqlite3_wasm')){
            e.classList.add('func-wasm');
        }
    };
    const renderIt = async function(sqlite3){
        self.sqlite3 = sqlite3;
        console.warn("sqlite3 installed as global symbol self.sqlite3.");
        const capi = sqlite3.capi, wasm = sqlite3.wasm;
        const cmpIcase = (a,b)=>a.toLowerCase().localeCompare(b.toLowerCase());
        const renderX = function(tgtElem, container, keys){
            for(const k of keys.sort(cmpIcase)){
                renderGeneric(k, container[k], tgtElem);
            }
        };
        
        const excludeNamespace = ['scriptInfo','StructBinder'];
        renderX(
            E('#list-namespace'), sqlite3,
            Object.keys(sqlite3)
                .filter((v)=>excludeNamespace.indexOf(v)<0)
        );
        renderX(
            E('#list-version'), sqlite3.version,
            Object.keys(sqlite3.version)
        );

        /* sqlite3_...() and SQLITE_... */
        const lists = {c: [/*constants*/], f: [/*functions*/],
                       s: [/*structs*/]};
        /* Exclude these from the function list... */
        const excludeCapi = [
            // WASMFS stuff:
            'sqlite3_wasmfs_filename_is_persistent',
            'sqlite3_wasmfs_opfs_dir'
        ];
        for(const [k,v] of Object.entries(capi)){
            if(k.startsWith('SQLITE_')){
                lists.c.push(k);
            }else if(k.startsWith('sqlite3_')){
                if(excludeCapi.indexOf(k)>=0) continue;
                if(v.structInfo){
                    // assume this is a StructType-type.
                    continue;
                }
                lists.f.push(k);
            }
        }
        lists.c.sort().forEach(renderConst);
        lists.f.sort().forEach(renderFunc);
        lists.c = lists.f = null;

        renderX(E('#list-oo1'), sqlite3.oo1,
                Object.keys(sqlite3.oo1) );

        const excludeWasm = ['ctype'];
        renderX(E('#list-wasm'),
                wasm, Object.keys(wasm).filter((v)=>{
                    return !v.startsWith('sqlite3_wasm_')
                        && excludeWasm.indexOf(v)<0;
                }));
        const psKeys = Object.keys(wasm.pstack);
        psKeys.push('pointer','quota','remaining');
        renderX(E('#list-wasm-pstack'), wasm.pstack, psKeys);

        const cou = wasm.compileOptionUsed();
        //const cou2 = Object.create(null);
        //Object.entries(cou).forEach((e)=>cou2['SQLITE_'+e[0]] = e[1]);
        renderX(E('#list-compile-options'), cou, Object.keys(cou));
    };

    /**
       This is a module object for use with the emscripten-installed
       sqlite3InitModule() factory function.
    */
    const myModule = {
        print: (...args)=>{console.log(...args)},
        printErr: (...args)=>{console.error(...args)},
        /**
           Called by the Emscripten module init bits to report loading
           progress. It gets passed an empty argument when loading is done
           (after onRuntimeInitialized() and any this.postRun callbacks
           have been run).
        */
        setStatus: function f(text){
            if(!f.last){
                f.last = { text: '', step: 0 };
                f.ui = {
                    status: E('#module-load-status')
                };
            }
            if(text === f.last.text) return;
            f.last.text = text;
            ++f.last.step;
            if(text) {
                f.ui.status.classList.remove('hidden');
                f.ui.status.innerText = text;
            }else{
                f.ui.status.classList.add('hidden');
                EAll('.initially-hidden').forEach((e)=>{
                    e.classList.remove('initially-hidden');
                });
            }
        }
    }/*myModule*/;
    self.sqlite3InitModule(myModule).then(renderIt);
})();</script>
</div><!-- .fossil-doc EXTRACT_END -->
</body></html>

Added ext/wasm/scratchpad-wasmfs-main.html.









































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<!doctype html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
    <link rel="stylesheet" href="common/emscripten.css"/>
    <link rel="stylesheet" href="common/testing.css"/>
    <title>sqlite3 WASMFS/OPFS Main-thread Scratchpad</title>
  </head>
  <body>
    <header id='titlebar'><span>sqlite3 WASMFS/OPFS Main-thread Scratchpad</span></header>
    <!-- emscripten bits -->
    <figure id="module-spinner">
      <div class="spinner"></div>
      <div class='center'><strong>Initializing app...</strong></div>
      <div class='center'>
        On a slow internet connection this may take a moment.  If this
        message displays for "a long time", intialization may have
        failed and the JavaScript console may contain clues as to why.
      </div>
    </figure>
    <div class="emscripten" id="module-status">Downloading...</div>
    <div class="emscripten">
      <progress value="0" max="100" id="module-progress" hidden='1'></progress>  
    </div><!-- /emscripten bits -->
    <p>Scratchpad/test app for the WASMF/OPFS integration in the
      main window thread. This page requires that the sqlite3 API have
      been built with WASMFS support. If OPFS support is available then
      it "should" persist a database across reloads (watch the dev console
      output), otherwise it will not.
    </p>
    <p>All stuff on this page happens in the dev console.</p>
    <hr>
    <div id='test-output'></div>
    <script src="sqlite3-wasmfs.js"></script>
    <script src="common/SqliteTestUtil.js"></script>
    <script src="scratchpad-wasmfs-main.js"></script>
  </body>
</html>

Added ext/wasm/scratchpad-wasmfs-main.js.







































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
  2022-05-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.

  ***********************************************************************

  A basic test script for sqlite3-api.js. This file must be run in
  main JS thread and sqlite3.js must have been loaded before it.
*/
'use strict';
(function(){
  const toss = function(...args){throw new Error(args.join(' '))};
  const log = console.log.bind(console),
        warn = console.warn.bind(console),
        error = console.error.bind(console);

  const stdout = log;
  const stderr = error;

  const test1 = function(db){
    db.exec("create table if not exists t(a);")
      .transaction(function(db){
        db.prepare("insert into t(a) values(?)")
          .bind(new Date().getTime())
          .stepFinalize();
        stdout("Number of values in table t:",
            db.selectValue("select count(*) from t"));
      });
  };

  const runTests = function(sqlite3){
    const capi = sqlite3.capi,
          oo = sqlite3.oo1,
          wasm = sqlite3.wasm;
    stdout("Loaded sqlite3:",capi.sqlite3_libversion(), capi.sqlite3_sourceid());
    const persistentDir = capi.sqlite3_wasmfs_opfs_dir();
    if(persistentDir){
      stdout("Persistent storage dir:",persistentDir);
    }else{
      stderr("No persistent storage available.");
    }
    const startTime = performance.now();
    let db;
    try {
      db = new oo.DB(persistentDir+'/foo.db');
      stdout("DB filename:",db.filename);
      const banner1 = '>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>',
            banner2 = '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<';
      [
        test1
      ].forEach((f)=>{
        const n = performance.now();
        stdout(banner1,"Running",f.name+"()...");
        f(db, sqlite3);
        stdout(banner2,f.name+"() took ",(performance.now() - n),"ms");
      });
    }finally{
      if(db) db.close();
    }
    stdout("Total test time:",(performance.now() - startTime),"ms");
  };

  sqlite3InitModule(self.sqlite3TestModule).then(runTests);
})();

Added ext/wasm/speedtest1-wasmfs.html.























































































































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<!doctype html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
    <link rel="stylesheet" href="common/emscripten.css"/>
    <link rel="stylesheet" href="common/testing.css"/>
    <title>speedtest1-wasmfs.wasm</title>
  </head>
  <body>
    <header id='titlebar'><span>speedtest1-wasmfs.wasm</span></header>
    <div>See also: <a href='speedtest1-worker.html'>A Worker-thread variant of this page.</a></div>
    <!-- emscripten bits -->
    <figure id="module-spinner">
      <div class="spinner"></div>
      <div class='center'><strong>Initializing app...</strong></div>
      <div class='center'>
        On a slow internet connection this may take a moment.  If this
        message displays for "a long time", intialization may have
        failed and the JavaScript console may contain clues as to why.
      </div>
    </figure>
    <div class="emscripten" id="module-status">Downloading...</div>
    <div class="emscripten">
      <progress value="0" max="100" id="module-progress" hidden='1'></progress>  
    </div><!-- /emscripten bits -->
    <div class='warning'>This page starts running the main exe when it loads, which will
      block the UI until it finishes! Adding UI controls to manually configure and start it
      are TODO.</div>
    </div>
    <div class='warning'>Achtung: running it with the dev tools open may
      <em>drastically</em> slow it down. For faster results, keep the dev
      tools closed when running it!
    </div>
    <div>Output is delayed/buffered because we cannot update the UI while the
      speedtest is running. Output will appear below when ready...
    <div id='test-output'></div>
    <script src="common/SqliteTestUtil.js"></script>
    <script src="speedtest1-wasmfs.js"></script>
    <script>(function(){
    /**
       If this environment contains OPFS, this function initializes it and
       returns the name of the dir on which OPFS is mounted, else it returns
       an empty string.
    */
    const wasmfsDir = function f(wasmUtil,dirName="/opfs"){
        if(undefined !== f._) return f._;
        if( !self.FileSystemHandle
            || !self.FileSystemDirectoryHandle
            || !self.FileSystemFileHandle){
            return f._ = "";
        }
        try{
            if(0===wasmUtil.xCallWrapped(
                'sqlite3_wasm_init_wasmfs', 'i32', ['string'], dirName
            )){
                return f._ = dirName;
            }else{
                return f._ = "";
            }
        }catch(e){
            // sqlite3_wasm_init_wasmfs() is not available
            return f._ = "";
        }
    };
    wasmfsDir._ = undefined;

    const eOut = document.querySelector('#test-output');
    const log2 = function(cssClass,...args){
        const ln = document.createElement('div');
        if(cssClass) ln.classList.add(cssClass);
        ln.append(document.createTextNode(args.join(' ')));
        eOut.append(ln);
        //this.e.output.lastElementChild.scrollIntoViewIfNeeded();
    };
    const logList = [];
    const dumpLogList = function(){
        logList.forEach((v)=>log2('',v));
        logList.length = 0;
    };
    /* can't update DOM while speedtest is running unless we run
       speedtest in a worker thread. */;
    const log = (...args)=>{
        console.log(...args);
        logList.push(args.join(' '));
    };
    const logErr = function(...args){
        console.error(...args);
        logList.push('ERROR: '+args.join(' '));
    };

    const runTests = function(sqlite3){
        console.log("Module inited.");
        const wasm = sqlite3.wasm;
        const __unlink = wasm.xWrap("sqlite3_wasm_vfs_unlink", "int", ["*","string"]);
        const unlink = (fn)=>__unlink(0,fn);
        const pDir = wasmfsDir(wasm);
        if(pDir) log2('',"Persistent storage:",pDir);
        else{
            log2('error',"Expecting persistent storage in this build.");
            return;
        }
        const scope = wasm.scopedAllocPush();
        const dbFile = pDir+"/speedtest1.db";
        const urlParams = new URL(self.location.href).searchParams;
        const argv = ["speedtest1"];
        if(urlParams.has('flags')){
            argv.push(...(urlParams.get('flags').split(',')));
            let i = argv.indexOf('--vfs');
            if(i>=0) argv.splice(i,2);
        }else{
            argv.push(
                "--singlethread",
                "--nomutex",
                "--nosync",
                "--nomemstat"
            );
            //"--memdb", // note that memdb trumps the filename arg
        }

        if(argv.indexOf('--memdb')>=0){
            log2('error',"WARNING: --memdb flag trumps db filename.");
        }
        argv.push("--big-transactions"/*important for tests 410 and 510!*/,
                  dbFile);
        console.log("argv =",argv);
        // These log messages are not emitted to the UI until after main() returns. Fixing that
        // requires moving the main() call and related cleanup into a timeout handler.
        if(pDir) unlink(dbFile);
        log2('',"Starting native app:\n ",argv.join(' '));
        log2('',"This will take a while and the browser might warn about the runaway JS.",
             "Give it time...");
        logList.length = 0;
        setTimeout(function(){
            wasm.xCall('wasm_main', argv.length,
                       wasm.scopedAllocMainArgv(argv));
            wasm.scopedAllocPop(scope);
            if(pDir) unlink(dbFile);
            logList.unshift("Done running native main(). Output:");
            dumpLogList();
        }, 25);
    }/*runTests()*/;

    self.sqlite3TestModule.print = log;
    self.sqlite3TestModule.printErr = logErr;
    sqlite3InitModule(self.sqlite3TestModule).then(runTests);
})();</script>
  </body>
</html>

Added ext/wasm/speedtest1-worker.html.





















































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<!doctype html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
    <link rel="stylesheet" href="common/emscripten.css"/>
    <link rel="stylesheet" href="common/testing.css"/>
    <title>speedtest1.wasm Worker</title>
  </head>
  <body>
    <header id='titlebar'>speedtest1.wasm Worker</header>
    <div>See also: <a href='speedtest1.html'>A main-thread variant of this page.</a></div>
    <!-- emscripten bits -->
    <figure id="module-spinner">
      <div class="spinner"></div>
      <div class='center'><strong>Initializing app...</strong></div>
      <div class='center'>
        On a slow internet connection this may take a moment.  If this
        message displays for "a long time", intialization may have
        failed and the JavaScript console may contain clues as to why.
      </div>
    </figure>
    <div class="emscripten" id="module-status">Downloading...</div>
    <div class="emscripten">
      <progress value="0" max="100" id="module-progress" hidden='1'></progress>  
    </div><!-- /emscripten bits -->
    <fieldset id='ui-controls' class='hidden'>
      <legend>Options</legend>
      <div id='toolbar'>
        <div id='toolbar-select'>
          <select id='select-flags' size='10' multiple></select>
          <div>The following flags can be passed as URL parameters:
            vfs=NAME, size=N, journal=MODE, cachesize=SIZE
          </div>
        </div>
        <div class='toolbar-inner-vertical'>
          <div id='toolbar-selected-flags'></div>
          <div class='toolbar-inner-vertical'>
            <span>&rarr; <a id='link-main-thread' href='#' target='speedtest-main'
                            title='Start speedtest1.html with the selected flags'>speedtest1</a>
            </span>
            <span class='hidden'>&rarr; <a id='link-wasmfs' href='#' target='speedtest-wasmfs'
                            title='Start speedtest1-wasmfs.html with the selected flags'>speedtest1-wasmfs</a>
            </span>
            <span>&rarr; <a id='link-kvvfs' href='#' target='speedtest-kvvfs'
                            title='Start kvvfs speedtest1 with the selected flags'>speedtest1-kvvfs</a>
            </span>
          </div>
        </div>
        <div class='toolbar-inner-vertical' id='toolbar-runner-controls'>
          <button id='btn-reset-flags'>Reset Flags</button>
          <button id='btn-output-clear'>Clear output</button>
          <button id='btn-run'>Run</button>
        </div>
      </div>
    </fieldset>
    <div>
      <span class='input-wrapper'>
        <input type='checkbox' class='disable-during-eval' id='cb-reverse-log-order' checked></input>
        <label for='cb-reverse-log-order' id='lbl-reverse-log-order'>Reverse log order</label>
      </span>
    </div>
    <div id='test-output'>
    </div>
    <div id='tips'>
      <strong>Tips:</strong>
      <ul>
        <li>Control-click the flags to (de)select multiple flags.</li>
        <li>The <tt>--big-transactions</tt> flag is important for two
          of the bigger tests. Without it, those tests create a
          combined total of 140k implicit transactions, reducing their
          speed to an absolute crawl, especially when WASMFS is
          activated.
        </li>
        <li>The easiest way to try different optimization levels is,
          from this directory:
          <pre>$ rm -f jswasm/speedtest1.js; make -e emcc_opt='-O2' speedtest1</pre>
          Then reload this page. -O2 seems to consistently produce the fastest results.
        </li>
        </ul>
    </div>
    <style>
      #test-output {
          white-space: break-spaces;
          overflow: auto;
      }
      div#tips { margin-top: 1em; }
      #toolbar {
          display: flex;
          flex-direction: row;
          flex-wrap: wrap;
      }
      #toolbar > * {
          margin: 0 0.5em;
      }
      .toolbar-inner-vertical {
          display: flex;
          flex-direction: column;
          justify-content: space-between;
      }
      #toolbar-select {
          display: flex;
          flex-direction: column;
      }
      .toolbar-inner-vertical > *, #toolbar-select > * {
          margin: 0.2em 0;
      }
      #select-flags > option {
          white-space: pre;
          font-family: monospace;
      }
      fieldset {
          border-radius: 0.5em;
      }
      #toolbar-runner-controls { flex-grow: 1 }
      #toolbar-runner-controls > * { flex: 1 0 auto }
      #toolbar-selected-flags::before {
        font-family: initial;
        content:"Selected flags: ";
      }
      #toolbar-selected-flags {
        display: flex;
        flex-direction: column;
        font-family: monospace;
        justify-content: flex-start;
      }
    </style>
    <script>(function(){
    'use strict';
    const E = (sel)=>document.querySelector(sel);
    const eOut = E('#test-output');
    const log2 = function(cssClass,...args){
        let ln;
        if(1 || cssClass){
            ln = document.createElement('div');
            if(cssClass) ln.classList.add(cssClass);
            ln.append(document.createTextNode(args.join(' ')));
        }else{
            // This doesn't work with the "reverse order" option!
            ln = document.createTextNode(args.join(' ')+'\n');
        }
        eOut.append(ln);
    };
    const log = (...args)=>{
        //console.log(...args);
        log2('', ...args);
    };
    const logErr = function(...args){
        console.error(...args);
        log2('error', ...args);
    };
    const logWarn = function(...args){
        console.warn(...args);
        log2('warning', ...args);
    };

    const spacePad = function(str,len=21){
        if(str.length===len) return str;
        else if(str.length>len) return str.substr(0,len);
        const a = []; a.length = len - str.length;
        return str+a.join(' ');
    };
    // OPTION elements seem to ignore white-space:pre, so do this the hard way...
    const nbspPad = function(str,len=21){
        if(str.length===len) return str;
        else if(str.length>len) return str.substr(0,len);
        const a = []; a.length = len - str.length;
        return str+a.join('&nbsp;');
    };

    const urlParams = new URL(self.location.href).searchParams;
    const W = new Worker(
        "speedtest1-worker.js?sqlite3.dir=jswasm"+
            (urlParams.has('opfs-verbose') ? '&opfs-verbose' : '')
    );
    const mPost = function(msgType,payload){
        W.postMessage({type: msgType, data: payload});
    };

    const eFlags = E('#select-flags');
    const eSelectedFlags = E('#toolbar-selected-flags');
    const eLinkMainThread = E('#link-main-thread');
    const eLinkWasmfs = E('#link-wasmfs');
    const eLinkKvvfs = E('#link-kvvfs');
    const getSelectedFlags = ()=>{
        const f = Array.prototype.map.call(eFlags.selectedOptions, (v)=>v.value);
        [
            'size', 'vfs', 'journal', 'cachesize'
        ].forEach(function(k){
            if(urlParams.has(k)) f.push('--'+k, urlParams.get(k));
        });
        return f;
    };
    const updateSelectedFlags = function(){
        eSelectedFlags.innerText = '';
        const flags = getSelectedFlags();
        flags.forEach(function(f){
            const e = document.createElement('span');
            e.innerText = f;
            eSelectedFlags.appendChild(e);
        });
        const rxStripDash = /^(-+)?/;
        const comma = flags.join(',');
        eLinkMainThread.setAttribute('target', 'speedtest1-main-'+comma);
        eLinkMainThread.href = 'speedtest1.html?flags='+comma;
        eLinkWasmfs.setAttribute('target', 'speedtest1-wasmfs-'+comma);
        eLinkWasmfs.href = 'speedtest1-wasmfs.html?flags='+comma;
        eLinkKvvfs.setAttribute('target', 'speedtest1-kvvfs-'+comma);
        eLinkKvvfs.href = 'speedtest1.html?vfs=kvvfs&flags='+comma;
    };
    eFlags.addEventListener('change', updateSelectedFlags );
    {
        const flags = Object.create(null);
        /* TODO? Flags which require values need custom UI
           controls and some of them make little sense here
           (e.g. --script FILE). */
        flags["--autovacuum"] = "Enable AUTOVACUUM mode";
        flags["--big-transactions"] = "Important for tests 410 and 510!";
        //flags["--cachesize"] = "N       Set the cache size to N pages";
        flags["--checkpoint"] = "Run PRAGMA wal_checkpoint after each test case";
        flags["--exclusive"] = "Enable locking_mode=EXCLUSIVE";
        flags["--explain"] = "Like --sqlonly but with added EXPLAIN keywords";
        //flags["--heap"] = "SZ MIN       Memory allocator uses SZ bytes & min allocation MIN";
        flags["--incrvacuum"] = "Enable incremenatal vacuum mode";
        //flags["--journal"] = "M         Set the journal_mode to M";
        //flags["--key"] = "KEY           Set the encryption key to KEY";
        //flags["--lookaside"] = "N SZ    Configure lookaside for N slots of SZ bytes each";
        flags["--memdb"] = "Use an in-memory database";
        //flags["--mmap"] = "SZ           MMAP the first SZ bytes of the database file";
        flags["--multithread"] = "Set multithreaded mode";
        flags["--nomemstat"] = "Disable memory statistics";
        flags["--nomutex"] = "Open db with SQLITE_OPEN_NOMUTEX";
        flags["--nosync"] = "Set PRAGMA synchronous=OFF";
        flags["--notnull"] = "Add NOT NULL constraints to table columns";
        //flags["--output"] = "FILE       Store SQL output in FILE";
        //flags["--pagesize"] = "N        Set the page size to N";
        //flags["--pcache"] = "N SZ       Configure N pages of pagecache each of size SZ bytes";
        //flags["--primarykey"] = "Use PRIMARY KEY instead of UNIQUE where appropriate";
        //flags["--repeat"] = "N          Repeat each SELECT N times (default: 1)";
        flags["--reprepare"] = "Reprepare each statement upon every invocation";
        //flags["--reserve"] = "N         Reserve N bytes on each database page";
        //flags["--script"] = "FILE       Write an SQL script for the test into FILE";
        flags["--serialized"] = "Set serialized threading mode";
        flags["--singlethread"] = "Set single-threaded mode - disables all mutexing";
        flags["--sqlonly"] = "No-op.  Only show the SQL that would have been run.";
        flags["--shrink-memory"] = "Invoke sqlite3_db_release_memory() frequently.";
        //flags["--size"] = "N            Relative test size.  Default=100";
        flags["--strict"] = "Use STRICT table where appropriate";
        flags["--stats"] = "Show statistics at the end";
        //flags["--temp"] = "N            N from 0 to 9.  0: no temp table. 9: all temp tables";
        //flags["--testset"] = "T         Run test-set T (main, cte, rtree, orm, fp, debug)";
        flags["--trace"] = "Turn on SQL tracing";
        //flags["--threads"] = "N         Use up to N threads for sorting";
        /*
          The core API's WASM build does not support UTF16, but in
          this app it's not an issue because the data are not crossing
          JS/WASM boundaries.
        */
        flags["--utf16be"] = "Set text encoding to UTF-16BE";
        flags["--utf16le"] = "Set text encoding to UTF-16LE";
        flags["--verify"] = "Run additional verification steps.";
        flags["--without"] = "rowid     Use WITHOUT ROWID where appropriate";
        const preselectedFlags = [
            '--big-transactions',
            '--singlethread'
        ];
        if(urlParams.has('flags')){
            preselectedFlags.push(...urlParams.get('flags').split(','));
        }
        if('opfs'!==urlParams.get('vfs')){
            preselectedFlags.push('--memdb');
        }
        Object.keys(flags).sort().forEach(function(f){
            const opt = document.createElement('option');
            eFlags.appendChild(opt);
            const lbl = nbspPad(f)+flags[f];
            //opt.innerText = lbl;
            opt.innerHTML = lbl;
            opt.value = f;
            if(preselectedFlags.indexOf(f) >= 0) opt.selected = true;
        });    
        const cbReverseLog = E('#cb-reverse-log-order');
        const lblReverseLog = E('#lbl-reverse-log-order');
        if(cbReverseLog.checked){
            lblReverseLog.classList.add('warning');
            eOut.classList.add('reverse');
        }
        cbReverseLog.addEventListener('change', function(){
            if(this.checked){
                eOut.classList.add('reverse');
                lblReverseLog.classList.add('warning');
            }else{
                eOut.classList.remove('reverse');
                lblReverseLog.classList.remove('warning');
            }
        }, false);
        updateSelectedFlags();
    }
    E('#btn-output-clear').addEventListener('click', ()=>{
        eOut.innerText = '';
    });
    E('#btn-reset-flags').addEventListener('click',()=>{
        eFlags.value = '';
        updateSelectedFlags();
    });
    E('#btn-run').addEventListener('click',function(){
        log("Running speedtest1. UI controls will be disabled until it completes.");
        mPost('run', getSelectedFlags());
    });

    const eControls = E('#ui-controls');
    /** Update Emscripten-related UI elements while loading the module. */
    const updateLoadStatus = function f(text){
        if(!f.last){
            f.last = { text: '', step: 0 };
            const E = (cssSelector)=>document.querySelector(cssSelector);
            f.ui = {
                status: E('#module-status'),
                progress: E('#module-progress'),
                spinner: E('#module-spinner')
            };
        }
        if(text === f.last.text) return;
        f.last.text = text;
        if(f.ui.progress){
            f.ui.progress.value = f.last.step;
            f.ui.progress.max = f.last.step + 1;
        }
        ++f.last.step;
        if(text) {
            f.ui.status.classList.remove('hidden');
            f.ui.status.innerText = text;
        }else{
            if(f.ui.progress){
                f.ui.progress.remove();
                f.ui.spinner.remove();
                delete f.ui.progress;
                delete f.ui.spinner;
            }
            f.ui.status.classList.add('hidden');
        }
    };

    W.onmessage = function(msg){
        msg = msg.data;
        switch(msg.type){
            case 'ready':
                log("Worker is ready.");
                eControls.classList.remove('hidden');
                break;
            case 'stdout': log(msg.data); break;
            case 'stdout': logErr(msg.data); break;
            case 'run-start':
                eControls.disabled = true;
                log("Running speedtest1 with argv =",msg.data.join(' '));
                break;
            case 'run-end':
                log("speedtest1 finished.");
                eControls.disabled = false;
                // app output is in msg.data
                break;
            case 'error': logErr(msg.data); break;
            case 'load-status': updateLoadStatus(msg.data); break;
            default:
                logErr("Unhandled worker message type:",msg);
                break;
        }
    };
})();</script>
  </body>
</html>

Added ext/wasm/speedtest1-worker.js.




































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
'use strict';
(function(){
  let speedtestJs = 'speedtest1.js';
  const urlParams = new URL(self.location.href).searchParams;
  if(urlParams.has('sqlite3.dir')){
    speedtestJs = urlParams.get('sqlite3.dir') + '/' + speedtestJs;
  }
  importScripts('common/whwasmutil.js', speedtestJs);
  /**
     If this environment contains OPFS, this function initializes it and
     returns the name of the dir on which OPFS is mounted, else it returns
     an empty string.
  */
  const wasmfsDir = function f(wasmUtil){
    if(undefined !== f._) return f._;
    const pdir = '/opfs';
    if( !self.FileSystemHandle
        || !self.FileSystemDirectoryHandle
        || !self.FileSystemFileHandle){
      return f._ = "";
    }
    try{
      if(0===wasmUtil.xCallWrapped(
        'sqlite3_wasm_init_wasmfs', 'i32', ['string'], pdir
      )){
        return f._ = pdir;
      }else{
        return f._ = "";
      }
    }catch(e){
      // sqlite3_wasm_init_wasmfs() is not available
      return f._ = "";
    }
  };
  wasmfsDir._ = undefined;

  const mPost = function(msgType,payload){
    postMessage({type: msgType, data: payload});
  };

  const App = Object.create(null);
  App.logBuffer = [];
  const logMsg = (type,msgArgs)=>{
    const msg = msgArgs.join(' ');
    App.logBuffer.push(msg);
    mPost(type,msg);
  };
  const log = (...args)=>logMsg('stdout',args);
  const logErr = (...args)=>logMsg('stderr',args);

  const runSpeedtest = function(cliFlagsArray){
    const scope = App.wasm.scopedAllocPush();
    const dbFile = App.pDir+"/speedtest1.sqlite3";
    try{
      const argv = [
        "speedtest1.wasm", ...cliFlagsArray, dbFile
      ];
      App.logBuffer.length = 0;
      mPost('run-start', [...argv]);
      App.wasm.xCall('wasm_main', argv.length,
                     App.wasm.scopedAllocMainArgv(argv));
    }catch(e){
      mPost('error',e.message);
    }finally{
      App.wasm.scopedAllocPop(scope);
      mPost('run-end', App.logBuffer.join('\n'));
      App.logBuffer.length = 0;
    }
  };

  self.onmessage = function(msg){
    msg = msg.data;
    switch(msg.type){
        case 'run': runSpeedtest(msg.data || []); break;
        default:
          logErr("Unhandled worker message type:",msg.type);
          break;
    }
  };

  const EmscriptenModule = {
    print: log,
    printErr: logErr,
    setStatus: (text)=>mPost('load-status',text)
  };
  self.sqlite3InitModule(EmscriptenModule).then((sqlite3)=>{
    const S = sqlite3;
    App.vfsUnlink = function(pDb, fname){
      const pVfs = S.wasm.sqlite3_wasm_db_vfs(pDb, 0);
      if(pVfs) S.wasm.sqlite3_wasm_vfs_unlink(pVfs, fname||0);
    };
    App.pDir = wasmfsDir(S.wasm);
    App.wasm = S.wasm;
    //if(App.pDir) log("Persistent storage:",pDir);
    //else log("Using transient storage.");
    mPost('ready',true);
    log("Registered VFSes:", ...S.capi.sqlite3_js_vfs_list());
  });
})();

Added ext/wasm/speedtest1.html.















































































































































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<!doctype html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
    <link rel="stylesheet" href="common/emscripten.css"/>
    <link rel="stylesheet" href="common/testing.css"/>
    <title>speedtest1.wasm</title>
  </head>
  <body>
    <header id='titlebar'><span>speedtest1.wasm</span></header>
    <div>See also: <a href='speedtest1-worker.html'>A Worker-thread variant of this page.</a></div>
    <!-- emscripten bits -->
    <figure id="module-spinner">
      <div class="spinner"></div>
      <div class='center'><strong>Initializing app...</strong></div>
      <div class='center'>
        On a slow internet connection this may take a moment.  If this
        message displays for "a long time", intialization may have
        failed and the JavaScript console may contain clues as to why.
      </div>
    </figure>
    <div class="emscripten" id="module-status">Downloading...</div>
    <div class="emscripten">
      <progress value="0" max="100" id="module-progress" hidden='1'></progress>  
    </div><!-- /emscripten bits -->
    <div class='warning'>This page starts running the main exe when it loads, which will
      block the UI until it finishes! Adding UI controls to manually configure and start it
      are TODO.</div>
    </div>
    <div class='warning'>Achtung: running it with the dev tools open may
      <em>drastically</em> slow it down. For faster results, keep the dev
      tools closed when running it!
    </div>
    <div>Output is delayed/buffered because we cannot update the UI while the
      speedtest is running. Output will appear below when ready...
    <div id='test-output'></div>
    <script src="common/SqliteTestUtil.js"></script>
    <script src="jswasm/speedtest1.js"></script>
    <script>(function(){
    /**
       If this environment contains WASMFS with OPFS, this function
       initializes it and returns the name of the dir on which OPFS is
       mounted, else it returns an empty string.
    */
    const wasmfsDir = function f(wasmUtil){
        if(undefined !== f._) return f._;
        const pdir = '/persistent';
        if( !self.FileSystemHandle
            || !self.FileSystemDirectoryHandle
            || !self.FileSystemFileHandle){
            return f._ = "";
        }
        try{
            if(0===wasmUtil.xCallWrapped(
                'sqlite3_wasm_init_wasmfs', 'i32', ['string'], pdir
            )){
                return f._ = pdir;
            }else{
                return f._ = "";
            }
        }catch(e){
            // sqlite3_wasm_init_wasmfs() is not available
            return f._ = "";
        }
    };
    wasmfsDir._ = undefined;

    const eOut = document.querySelector('#test-output');
    const log2 = function(cssClass,...args){
        const ln = document.createElement('div');
        if(cssClass) ln.classList.add(cssClass);
        ln.append(document.createTextNode(args.join(' ')));
        eOut.append(ln);
        //this.e.output.lastElementChild.scrollIntoViewIfNeeded();
    };
    const logList = [];
    const dumpLogList = function(){
        logList.forEach((v)=>log2('',v));
        logList.length = 0;
    };
    /* can't update DOM while speedtest is running unless we run
       speedtest in a worker thread. */;
    const log = (...args)=>{
        console.log(...args);
        logList.push(args.join(' '));
    };
    const logErr = function(...args){
        console.error(...args);
        logList.push('ERROR: '+args.join(' '));
    };

    const runTests = function(sqlite3){
        const capi = sqlite3.capi, wasm = sqlite3.wasm;
        //console.debug('sqlite3 =',sqlite3);
        const pDir = wasmfsDir(wasm);
        if(pDir){
            console.warn("Persistent storage:",pDir);
        }
        const scope = wasm.scopedAllocPush();
        let dbFile = pDir+"/speedtest1.db";
        const urlParams = new URL(self.location.href).searchParams;
        const argv = ["speedtest1"];
        if(urlParams.has('flags')){
            argv.push(...(urlParams.get('flags').split(',')));
        }

        let forceSize = 0;
        let vfs, pVfs = 0;
        if(urlParams.has('vfs')){
            vfs = urlParams.get('vfs');
            pVfs = capi.sqlite3_vfs_find(vfs);
            if(!pVfs){
                log2('error',"Unknown VFS:",vfs);
                return;
            }
            argv.push("--vfs", vfs);
            log2('',"Using VFS:",vfs);
            if('kvvfs' === vfs){
                forceSize = 4 /* 5 uses approx. 4.96mb */;
                dbFile = 'session';
                log2('warning',"kvvfs VFS: forcing --size",forceSize,
                     "and filename '"+dbFile+"'.");
                capi.sqlite3_js_kvvfs_clear(dbFile);
            }
        }
        if(forceSize){
            argv.push('--size',forceSize);
        }else{
            [
                'size'
            ].forEach(function(k){
                const v = urlParams.get(k);
                if(v) argv.push('--'+k, urlParams[k]);
            });
        }
        argv.push(
            "--singlethread",
            //"--nomutex",
            //"--nosync",
            //"--memdb", // note that memdb trumps the filename arg
            "--nomemstat"
        );
        argv.push("--big-transactions"/*important for tests 410 and 510!*/,
                  dbFile);
        console.log("argv =",argv);
        // These log messages are not emitted to the UI until after main() returns. Fixing that
        // requires moving the main() call and related cleanup into a timeout handler.
        if(pDir) wasm.sqlite3_wasm_vfs_unlink(pVfs,dbFile);
        log2('',"Starting native app:\n ",argv.join(' '));
        log2('',"This will take a while and the browser might warn about the runaway JS.",
             "Give it time...");
        logList.length = 0;
        setTimeout(function(){
            wasm.xCall('wasm_main', argv.length,
                       wasm.scopedAllocMainArgv(argv));
            wasm.scopedAllocPop(scope);
            if('kvvfs'===vfs){
                logList.unshift("KVVFS "+dbFile+" size = "+
                                capi.sqlite3_js_kvvfs_size(dbFile));
            }
            if(pDir) wasm.sqlite3_wasm_vfs_unlink(pVfs,dbFile);
            logList.unshift("Done running native main(). Output:");
            dumpLogList();
        }, 50);
    }/*runTests()*/;

    self.sqlite3TestModule.print = log;
    self.sqlite3TestModule.printErr = logErr;
    sqlite3InitModule(self.sqlite3TestModule).then(runTests);
})();</script>
</body>
</html>

Added ext/wasm/split-speedtest1-script.sh.


















1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
#!/bin/bash
# Expects $1 to be a (speedtest1 --script) output file. Output is a
# series of SQL files extracted from that file.
infile=${1:?arg = speedtest1 --script output file}
testnums=$(grep -e '^-- begin test' "$infile" | cut -d' ' -f4)
if [ x = "x${testnums}" ]; then
  echo "Could not parse any begin/end blocks out of $infile" 1>&2
  exit 1
fi
odir=${infile%%/*}
if [ "$odir" = "$infile" ]; then odir="."; fi
#echo testnums=$testnums
for n in $testnums; do
  ofile=$odir/$(printf "speedtest1-%03d.sql" $n)
  sed -n -e "/^-- begin test $n /,/^-- end test $n\$/p" $infile > $ofile
  echo -e "$n\t$ofile"
done

Added ext/wasm/sql/000-mandelbrot.sql.


















1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
WITH RECURSIVE
  xaxis(x) AS (VALUES(-2.0) UNION ALL SELECT x+0.05 FROM xaxis WHERE x<1.2),
  yaxis(y) AS (VALUES(-1.0) UNION ALL SELECT y+0.1 FROM yaxis WHERE y<1.0),
  m(iter, cx, cy, x, y) AS (
    SELECT 0, x, y, 0.0, 0.0 FROM xaxis, yaxis
    UNION ALL
    SELECT iter+1, cx, cy, x*x-y*y + cx, 2.0*x*y + cy FROM m 
     WHERE (x*x + y*y) < 4.0 AND iter<28
  ),
  m2(iter, cx, cy) AS (
    SELECT max(iter), cx, cy FROM m GROUP BY cx, cy
  ),
  a(t) AS (
    SELECT group_concat( substr(' .+*#', 1+min(iter/7,4), 1), '') 
    FROM m2 GROUP BY cy
  )
SELECT group_concat(rtrim(t),x'0a') as Mandelbrot FROM a;

Added ext/wasm/sql/001-sudoku.sql.





























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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
WITH RECURSIVE
  input(sud) AS (
    VALUES('53..7....6..195....98....6.8...6...34..8.3..17...2...6.6....28....419..5....8..79')
  ),
  digits(z, lp) AS (
    VALUES('1', 1)
    UNION ALL SELECT
    CAST(lp+1 AS TEXT), lp+1 FROM digits WHERE lp<9
  ),
  x(s, ind) AS (
    SELECT sud, instr(sud, '.') FROM input
    UNION ALL
    SELECT
      substr(s, 1, ind-1) || z || substr(s, ind+1),
      instr( substr(s, 1, ind-1) || z || substr(s, ind+1), '.' )
     FROM x, digits AS z
    WHERE ind>0
      AND NOT EXISTS (
            SELECT 1
              FROM digits AS lp
             WHERE z.z = substr(s, ((ind-1)/9)*9 + lp, 1)
                OR z.z = substr(s, ((ind-1)%9) + (lp-1)*9 + 1, 1)
                OR z.z = substr(s, (((ind-1)/3) % 3) * 3
                        + ((ind-1)/27) * 27 + lp
                        + ((lp-1) / 3) * 6, 1)
         )
  )
SELECT s FROM x WHERE ind=0;

Added ext/wasm/test-opfs-vfs.html.



























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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<!doctype html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
    <link rel="stylesheet" href="common/emscripten.css"/>
    <link rel="stylesheet" href="common/testing.css"/>
    <title>Async-behind-Sync experiment</title>
  </head>
  <body>
    <header id='titlebar'><span>Async-behind-Sync sqlite3_vfs</span></header>
    <div>This performs a sanity test of the "opfs" sqlite3_vfs.
      <strong>See the dev console for all output.</strong>
    </div>
    <div>
      <a href='?delete'>Use this link</a> to delete the persistent OPFS-side db (if any).
    </div>
    <div id='test-output'></div>
    <script>
      new Worker(
          "test-opfs-vfs.js?sqlite3.dir=jswasm&"+self.location.search.substr(1)
      );
    </script>
  </body>
</html>

Added ext/wasm/test-opfs-vfs.js.






















































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
  2022-09-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.

  ***********************************************************************

  A testing ground for the OPFS VFS.
*/
'use strict';
const tryOpfsVfs = async function(sqlite3){
  const toss = function(...args){throw new Error(args.join(' '))};
  const logPrefix = "OPFS tester:";
  const log = (...args)=>console.log(logPrefix,...args);
  const warn =  (...args)=>console.warn(logPrefix,...args);
  const error =  (...args)=>console.error(logPrefix,...args);
  const opfs = sqlite3.opfs;
  log("tryOpfsVfs()");
  if(!sqlite3.opfs){
    const e = toss("OPFS is not available.");
    error(e);
    throw e;
  }
  const capi = sqlite3.capi;
  const pVfs = capi.sqlite3_vfs_find("opfs") || toss("Missing 'opfs' VFS.");
  const oVfs = new capi.sqlite3_vfs(pVfs);
  log("OPFS VFS:",pVfs, oVfs);

  const wait = async (ms)=>{
    return new Promise((resolve)=>setTimeout(resolve, ms));
  };

  const urlArgs = new URL(self.location.href).searchParams;
  const dbFile = "my-persistent.db";
  if(urlArgs.has('delete')) sqlite3.opfs.unlink(dbFile);

  const db = new sqlite3.oo1.OpfsDb(dbFile,'ct');
  log("db file:",db.filename);
  try{
    if(opfs.entryExists(dbFile)){
      let n = db.selectValue("select count(*) from sqlite_schema");
      log("Persistent data found. sqlite_schema entry count =",n);
    }
    db.transaction((db)=>{
      db.exec({
        sql:[
          "create table if not exists t(a);",
          "insert into t(a) values(?),(?),(?);",
        ],
        bind: [performance.now() | 0,
               (performance.now() |0) / 2,
               (performance.now() |0) / 4]
      });
    });
    log("count(*) from t =",db.selectValue("select count(*) from t"));

    // Some sanity checks of the opfs utility functions...
    const testDir = '/sqlite3-opfs-'+opfs.randomFilename(12);
    const aDir = testDir+'/test/dir';
    await opfs.mkdir(aDir) || toss("mkdir failed");
    await opfs.mkdir(aDir) || toss("mkdir must pass if the dir exists");
    await opfs.unlink(testDir+'/test') && toss("delete 1 should have failed (dir not empty)");
    //await opfs.entryExists(testDir)
    await opfs.unlink(testDir+'/test/dir') || toss("delete 2 failed");
    await opfs.unlink(testDir+'/test/dir') && toss("delete 2b should have failed (dir already deleted)");
    await opfs.unlink(testDir, true) || toss("delete 3 failed");
    await opfs.entryExists(testDir) && toss("entryExists(",testDir,") should have failed");
  }finally{
    db.close();
  }

  log("Done!");
}/*tryOpfsVfs()*/;

importScripts('jswasm/sqlite3.js');
self.sqlite3InitModule()
  .then((sqlite3)=>tryOpfsVfs(sqlite3))
  .catch((e)=>{
    console.error("Error initializing module:",e);
  });

Added ext/wasm/tester1-worker.html.


















































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<!doctype html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
    <link rel="stylesheet" href="../common/emscripten.css"/>
    <link rel="stylesheet" href="../common/testing.css"/>
    <title>sqlite3 tester #1: Worker thread</title>
    <style></style>
  </head>
  <body>
    <h1 id='color-target'>sqlite3 tester #1: Worker thread</h1>
    <div>Variants:
      <a href='tester1.html' target='tester1.html'>conventional UI thread</a>,
      <a href='tester1-worker.html' target='tester1-worker.html'>conventional worker</a>,
      <a href='tester1-esm.html' target='tester1-esm.html'>ESM in UI thread</a>,
      <a href='tester1-worker.html?esm' target='tester1-worker.html?esm'>ESM worker</a>
    </div>
    <div class='input-wrapper'>
      <input type='checkbox' id='cb-log-reverse'>
      <label for='cb-log-reverse'>Reverse log order?</label>
    </div>
    <div id='test-output'></div>
    <script>(function(){
      const logTarget = document.querySelector('#test-output');
      const logHtml = function(cssClass,...args){
        const ln = document.createElement('div');
        if(cssClass){
          for(const c of (Array.isArray(cssClass) ? cssClass : [cssClass])){
            ln.classList.add(c);
          }
        }
        ln.append(document.createTextNode(args.join(' ')));
        logTarget.append(ln);
      };
      const cbReverse = document.querySelector('#cb-log-reverse');
      const cbReverseIt = ()=>{
        logTarget.classList[cbReverse.checked ? 'add' : 'remove']('reverse');
      };
      cbReverse.addEventListener('change',cbReverseIt,true);
      cbReverseIt();
      const urlParams = new URL(self.location.href).searchParams;
      const workerArgs = [];
      if(urlParams.has('esm')){
          logHtml('warning',"Attempting to run an ES6 Worker Module, "+
                  "which is not supported by all browsers! "+
                  "e.g. Firefox (as of 2022-12) cannot do this.");
        workerArgs.push("tester1.mjs",{type:"module"});
        document.querySelectorAll('title,#color-target').forEach((e)=>{
          e.innerText = "sqlite3 tester #1: ES6 Worker Module";
        });
      }else{
        workerArgs.push("tester1.js?sqlite3.dir=jswasm");
      }
      const w = new Worker(...workerArgs);
      w.onmessage = function({data}){
        switch(data.type){
            case 'log':
              logHtml(data.payload.cssClass, ...data.payload.args);
              break;
            case 'error':
              logHtml('error', ...data.payload.args);
              break;
            case 'test-result':{
                document.querySelector('#color-target').classList.add(
                    data.payload.pass ? 'tests-pass' : 'tests-fail'
                );
                const e = document.querySelector('title');
                e.innerText = (
                    data.payload.pass ? 'PASS' : 'FAIL'
                ) + ': ' + e.innerText;
                break;
            }
            default:
              logHtml('error',"Unhandled message:",data.type);
        };
      };
    })();</script>
  </body>
</html>

Added ext/wasm/tester1.c-pp.html.










































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<!doctype html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
    <link rel="stylesheet" href="common/emscripten.css"/>
    <link rel="stylesheet" href="common/testing.css"/>
    <title>sqlite3 tester #1:
//#if target=es6-module
ES6 Module in UI thread
//#else
UI thread
//#endif
    </title>
    <style></style>
  </head>
  <body><h1 id='color-target'></h1>
    <div>Variants:
      <a href='tester1.html' target='tester1.html'>conventional UI thread</a>,
      <a href='tester1-worker.html' target='tester1-worker.html'>conventional worker</a>,
      <a href='tester1-esm.html' target='tester1-esm.html'>ESM in UI thread</a>,
      <a href='tester1-worker.html?esm' target='tester1-worker.html?esm'>ESM worker</a>
    </div>
    <div class='input-wrapper'>
      <input type='checkbox' id='cb-log-reverse'>
      <label for='cb-log-reverse'>Reverse log order?</label>
    </div>
    <div id='test-output'></div>
    <script>(function(){
      document.querySelector('h1').innerHTML =
        document.querySelector('title').innerHTML;
    })();</script>
//#if target=es6-module
    <script src="tester1.mjs" type="module"></script>
//#else
    <script src="jswasm/sqlite3.js"></script>
    <script src="tester1.js"></script>
//#endif
  </body>
</html>

Added ext/wasm/tester1.c-pp.js.



















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
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
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
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
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
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
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
1984
1985
1986
1987
1988
1989
1990
1991
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
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
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
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
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
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
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
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
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
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
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
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
  2022-10-12

  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.

  ***********************************************************************

  Main functional and regression tests for the sqlite3 WASM API.

  This mini-framework works like so:

  This script adds a series of test groups, each of which contains an
  arbitrary number of tests, into a queue. After loading of the
  sqlite3 WASM/JS module is complete, that queue is processed. If any
  given test fails, the whole thing fails. This script is built such
  that it can run from the main UI thread or worker thread. Test
  groups and individual tests can be assigned a predicate function
  which determines whether to run them or not, and this is
  specifically intended to be used to toggle certain tests on or off
  for the main/worker threads or the availability (or not) of
  optional features such as int64 support.

  Each test group defines a single state object which gets applied as
  the test functions' `this` for all tests in that group. Test
  functions can use that to, e.g., set up a db in an early test and
  close it in a later test. Each test gets passed the sqlite3
  namespace object as its only argument.
*/
/*
   This file is intended to be processed by c-pp to inject (or not)
   code specific to ES6 modules which is illegal in non-module code.

   Non-ES6 module build and ES6 module for the main-thread:

     ./c-pp -f tester1.c-pp.js -o tester1.js

   ES6 worker module build:

     ./c-pp -f tester1.c-pp.js -o tester1-esm.js -Dtarget=es6-module
*/
//#if target=es6-module
import {default as sqlite3InitModule} from './jswasm/sqlite3.mjs';
self.sqlite3InitModule = sqlite3InitModule;
//#else
'use strict';
//#endif
(function(self){
  /**
     Set up our output channel differently depending
     on whether we are running in a worker thread or
     the main (UI) thread.
  */
  let logClass;
  /* Predicate for tests/groups. */
  const isUIThread = ()=>(self.window===self && self.document);
  /* Predicate for tests/groups. */
  const isWorker = ()=>!isUIThread();
  /* Predicate for tests/groups. */
  const testIsTodo = ()=>false;
  const haveWasmCTests = ()=>{
    return !!wasm.exports.sqlite3_wasm_test_intptr;
  };
  {
    const mapToString = (v)=>{
      switch(typeof v){
          case 'number': case 'string': case 'boolean':
          case 'undefined': case 'bigint':
            return ''+v;
          default: break;
      }
      if(null===v) return 'null';
      if(v instanceof Error){
        v = {
          message: v.message,
          stack: v.stack,
          errorClass: v.name
        };
      }
      return JSON.stringify(v,undefined,2);
    };
    const normalizeArgs = (args)=>args.map(mapToString);
    if( isUIThread() ){
      console.log("Running in the UI thread.");
      const logTarget = document.querySelector('#test-output');
      logClass = function(cssClass,...args){
        const ln = document.createElement('div');
        if(cssClass){
          for(const c of (Array.isArray(cssClass) ? cssClass : [cssClass])){
            ln.classList.add(c);
          }
        }
        ln.append(document.createTextNode(normalizeArgs(args).join(' ')));
        logTarget.append(ln);
      };
      const cbReverse = document.querySelector('#cb-log-reverse');
      const cbReverseKey = 'tester1:cb-log-reverse';
      const cbReverseIt = ()=>{
        logTarget.classList[cbReverse.checked ? 'add' : 'remove']('reverse');
        //localStorage.setItem(cbReverseKey, cbReverse.checked ? 1 : 0);
      };
      cbReverse.addEventListener('change', cbReverseIt, true);
      /*if(localStorage.getItem(cbReverseKey)){
        cbReverse.checked = !!(+localStorage.getItem(cbReverseKey));
      }*/
      cbReverseIt();
    }else{ /* Worker thread */
      console.log("Running in a Worker thread.");
      logClass = function(cssClass,...args){
        postMessage({
          type:'log',
          payload:{cssClass, args: normalizeArgs(args)}
        });
      };
    }
  }
  const reportFinalTestStatus = function(pass){
    if(isUIThread()){
      let e = document.querySelector('#color-target');
      e.classList.add(pass ? 'tests-pass' : 'tests-fail');
      e = document.querySelector('title');
      e.innerText = (pass ? 'PASS' : 'FAIL') + ': ' + e.innerText;
    }else{
      postMessage({type:'test-result', payload:{pass}});
    }
  };
  const log = (...args)=>{
    //console.log(...args);
    logClass('',...args);
  }
  const warn = (...args)=>{
    console.warn(...args);
    logClass('warning',...args);
  }
  const error = (...args)=>{
    console.error(...args);
    logClass('error',...args);
  };

  const toss = (...args)=>{
    error(...args);
    throw new Error(args.join(' '));
  };
  const tossQuietly = (...args)=>{
    throw new Error(args.join(' '));
  };

  const roundMs = (ms)=>Math.round(ms*100)/100;

  /**
     Helpers for writing sqlite3-specific tests.
  */
  const TestUtil = {
    /** Running total of the number of tests run via
        this API. */
    counter: 0,
    /* Separator line for log messages. */
    separator: '------------------------------------------------------------',
    /**
       If expr is a function, it is called and its result
       is returned, coerced to a bool, else expr, coerced to
       a bool, is returned.
    */
    toBool: function(expr){
      return (expr instanceof Function) ? !!expr() : !!expr;
    },
    /** Throws if expr is false. If expr is a function, it is called
        and its result is evaluated. If passed multiple arguments,
        those after the first are a message string which get applied
        as an exception message if the assertion fails. The message
        arguments are concatenated together with a space between each.
    */
    assert: function f(expr, ...msg){
      ++this.counter;
      if(!this.toBool(expr)){
        throw new Error(msg.length ? msg.join(' ') : "Assertion failed.");
      }
      return this;
    },
    /** Calls f() and squelches any exception it throws. If it
        does not throw, this function throws. */
    mustThrow: function(f, msg){
      ++this.counter;
      let err;
      try{ f(); } catch(e){err=e;}
      if(!err) throw new Error(msg || "Expected exception.");
      return this;
    },
    /**
       Works like mustThrow() but expects filter to be a regex,
       function, or string to match/filter the resulting exception
       against. If f() does not throw, this test fails and an Error is
       thrown. If filter is a regex, the test passes if
       filter.test(error.message) passes. If it's a function, the test
       passes if filter(error) returns truthy. If it's a string, the
       test passes if the filter matches the exception message
       precisely. In all other cases the test fails, throwing an
       Error.

       If it throws, msg is used as the error report unless it's falsy,
       in which case a default is used.
    */
    mustThrowMatching: function(f, filter, msg){
      ++this.counter;
      let err;
      try{ f(); } catch(e){err=e;}
      if(!err) throw new Error(msg || "Expected exception.");
      let pass = false;
      if(filter instanceof RegExp) pass = filter.test(err.message);
      else if(filter instanceof Function) pass = filter(err);
      else if('string' === typeof filter) pass = (err.message === filter);
      if(!pass){
        throw new Error(msg || ("Filter rejected this exception: "+err.message));
      }
      return this;
    },
    /** Throws if expr is truthy or expr is a function and expr()
        returns truthy. */
    throwIf: function(expr, msg){
      ++this.counter;
      if(this.toBool(expr)) throw new Error(msg || "throwIf() failed");
      return this;
    },
    /** Throws if expr is falsy or expr is a function and expr()
        returns falsy. */
    throwUnless: function(expr, msg){
      ++this.counter;
      if(!this.toBool(expr)) throw new Error(msg || "throwUnless() failed");
      return this;
    },
    eqApprox: (v1,v2,factor=0.05)=>(v1>=(v2-factor) && v1<=(v2+factor)),
    TestGroup: (function(){
      let groupCounter = 0;
      const TestGroup = function(name, predicate){
        this.number = ++groupCounter;
        this.name = name;
        this.predicate = predicate;
        this.tests = [];
      };
      TestGroup.prototype = {
        addTest: function(testObj){
          this.tests.push(testObj);
          return this;
        },
        run: async function(sqlite3){
          log(TestUtil.separator);
          logClass('group-start',"Group #"+this.number+':',this.name);
          const indent = '    ';
          if(this.predicate){
            const p = this.predicate(sqlite3);
            if(!p || 'string'===typeof p){
              logClass('warning',indent,
                       "SKIPPING group:", p ? p : "predicate says to" );
              return;
            }
          }
          const assertCount = TestUtil.counter;
          const groupState = Object.create(null);
          const skipped = [];
          let runtime = 0, i = 0;
          for(const t of this.tests){
            ++i;
            const n = this.number+"."+i;
              log(indent, n+":", t.name);
            if(t.predicate){
              const p = t.predicate(sqlite3);
              if(!p || 'string'===typeof p){
                logClass('warning',indent,
                         "SKIPPING:", p ? p : "predicate says to" );
                skipped.push( n+': '+t.name );
                continue;
              }
            }
            const tc = TestUtil.counter, now = performance.now();
            await t.test.call(groupState, sqlite3);
            const then = performance.now();
            runtime += then - now;
            logClass('faded',indent, indent,
                     TestUtil.counter - tc, 'assertion(s) in',
                     roundMs(then-now),'ms');
          }
          logClass('green',
                   "Group #"+this.number+":",(TestUtil.counter - assertCount),
                   "assertion(s) in",roundMs(runtime),"ms");
          if(0 && skipped.length){
            logClass('warning',"SKIPPED test(s) in group",this.number+":",skipped);
          }
        }
      };
      return TestGroup;
    })()/*TestGroup*/,
    testGroups: [],
    currentTestGroup: undefined,
    addGroup: function(name, predicate){
      this.testGroups.push( this.currentTestGroup =
                            new this.TestGroup(name, predicate) );
      return this;
    },
    addTest: function(name, callback){
      let predicate;
      if(1===arguments.length){
        this.currentTestGroup.addTest(arguments[0]);
      }else{
        this.currentTestGroup.addTest({
          name, predicate, test: callback
        });
      }
      return this;
    },
    runTests: async function(sqlite3){
      return new Promise(async function(pok,pnok){
        try {
          let runtime = 0;
          for(let g of this.testGroups){
            const now = performance.now();
            await g.run(sqlite3);
            runtime += performance.now() - now;
          }
          log(TestUtil.separator);
          logClass(['strong','green'],
                   "Done running tests.",TestUtil.counter,"assertions in",
                   roundMs(runtime),'ms');
          pok();
          reportFinalTestStatus(true);
        }catch(e){
          error(e);
          pnok(e);
          reportFinalTestStatus(false);
        }
      }.bind(this));
    }
  }/*TestUtil*/;
  const T = TestUtil;
  T.g = T.addGroup;
  T.t = T.addTest;
  let capi, wasm/*assigned after module init*/;
  ////////////////////////////////////////////////////////////////////////
  // End of infrastructure setup. Now define the tests...
  ////////////////////////////////////////////////////////////////////////

  ////////////////////////////////////////////////////////////////////
  T.g('Basic sanity checks')
    .t({
      name:'sqlite3_config()',
      test:function(sqlite3){
        for(const k of [
          'SQLITE_CONFIG_GETMALLOC', 'SQLITE_CONFIG_URI'
        ]){
          T.assert(capi[k] > 0);
        }
        T.assert(capi.SQLITE_MISUSE===capi.sqlite3_config(
          capi.SQLITE_CONFIG_URI, 1
        ), "MISUSE because the library has already been initialized.");
        T.assert(capi.SQLITE_MISUSE === capi.sqlite3_config(
          // not enough args
          capi.SQLITE_CONFIG_GETMALLOC
        ));
        T.assert(capi.SQLITE_NOTFOUND === capi.sqlite3_config(
          // unhandled-in-JS config option
          capi.SQLITE_CONFIG_GETMALLOC, 1
        ));
        if(0){
          log("We cannot _fully_ test sqlite3_config() after the library",
              "has been initialized (which it necessarily has been to",
              "set up various bindings) and we cannot shut it down ",
              "without losing the VFS registrations.");
          T.assert(0 === capi.sqlite3_config(
            capi.SQLITE_CONFIG_URI, 1
          ));
        }
      }
    })/*sqlite3_config()*/

  ////////////////////////////////////////////////////////////////////
    .t({
      name: "JS wasm-side allocator",
      test: function(sqlite3){
        if(sqlite3.config.useStdAlloc){
          warn("Using system allocator. This violates the docs and",
               "may cause grief with certain APIs",
               "(e.g. sqlite3_deserialize()).");
          T.assert(wasm.alloc.impl === wasm.exports.malloc)
            .assert(wasm.dealloc === wasm.exports.free)
            .assert(wasm.realloc.impl === wasm.exports.realloc);
        }else{
          T.assert(wasm.alloc.impl === wasm.exports.sqlite3_malloc)
            .assert(wasm.dealloc === wasm.exports.sqlite3_free)
            .assert(wasm.realloc.impl === wasm.exports.sqlite3_realloc);
        }
      }
    })
    .t('Namespace object checks', function(sqlite3){
      const wasmCtypes = wasm.ctype;
      T.assert(wasmCtypes.structs[0].name==='sqlite3_vfs').
        assert(wasmCtypes.structs[0].members.szOsFile.sizeof>=4).
        assert(wasmCtypes.structs[1/*sqlite3_io_methods*/
                                 ].members.xFileSize.offset>0);
      [ /* Spot-check a handful of constants to make sure they got installed... */
        'SQLITE_SCHEMA','SQLITE_NULL','SQLITE_UTF8',
        'SQLITE_STATIC', 'SQLITE_DIRECTONLY',
        'SQLITE_OPEN_CREATE', 'SQLITE_OPEN_DELETEONCLOSE'
      ].forEach((k)=>T.assert('number' === typeof capi[k]));
      [/* Spot-check a few of the WASM API methods. */
        'alloc', 'dealloc', 'installFunction'
      ].forEach((k)=>T.assert(wasm[k] instanceof Function));

      T.assert(capi.sqlite3_errstr(capi.SQLITE_IOERR_ACCESS).indexOf("I/O")>=0).
        assert(capi.sqlite3_errstr(capi.SQLITE_CORRUPT).indexOf('malformed')>0).
        assert(capi.sqlite3_errstr(capi.SQLITE_OK) === 'not an error');

      try {
        throw new sqlite3.WasmAllocError;
      }catch(e){
        T.assert(e instanceof Error)
          .assert(e instanceof sqlite3.WasmAllocError)
          .assert("Allocation failed." === e.message);
      }
      try {
        throw new sqlite3.WasmAllocError("test",{
          cause: 3
        });
      }catch(e){
        T.assert(3 === e.cause)
          .assert("test" === e.message);
      }
      try {throw new sqlite3.WasmAllocError("test","ing",".")}
      catch(e){T.assert("test ing ." === e.message)}

      try{ throw new sqlite3.SQLite3Error(capi.SQLITE_SCHEMA) }
      catch(e){
        T.assert('SQLITE_SCHEMA' === e.message)
          .assert(capi.SQLITE_SCHEMA === e.resultCode);
      }
      try{ sqlite3.SQLite3Error.toss(capi.SQLITE_CORRUPT,{cause: true}) }
      catch(e){
        T.assert('SQLITE_CORRUPT' === e.message)
          .assert(capi.SQLITE_CORRUPT === e.resultCode)
          .assert(true===e.cause);
      }
      try{ sqlite3.SQLite3Error.toss("resultCode check") }
      catch(e){
        T.assert(capi.SQLITE_ERROR === e.resultCode)
          .assert('resultCode check' === e.message);        
      }
    })
  ////////////////////////////////////////////////////////////////////
    .t('strglob/strlike', function(sqlite3){
      T.assert(0===capi.sqlite3_strglob("*.txt", "foo.txt")).
        assert(0!==capi.sqlite3_strglob("*.txt", "foo.xtx")).
        assert(0===capi.sqlite3_strlike("%.txt", "foo.txt", 0)).
        assert(0!==capi.sqlite3_strlike("%.txt", "foo.xtx", 0));
    })

  ////////////////////////////////////////////////////////////////////
  ;/*end of basic sanity checks*/

  ////////////////////////////////////////////////////////////////////
  T.g('C/WASM Utilities')
    .t('sqlite3.wasm namespace', function(sqlite3){
      // TODO: break this into smaller individual test functions.
      const w = wasm;
      const chr = (x)=>x.charCodeAt(0);
      //log("heap getters...");
      {
        const li = [8, 16, 32];
        if(w.bigIntEnabled) li.push(64);
        for(const n of li){
          const bpe = n/8;
          const s = w.heapForSize(n,false);
          T.assert(bpe===s.BYTES_PER_ELEMENT).
            assert(w.heapForSize(s.constructor) === s);
          const u = w.heapForSize(n,true);
          T.assert(bpe===u.BYTES_PER_ELEMENT).
            assert(s!==u).
            assert(w.heapForSize(u.constructor) === u);
        }
      }

      // alloc(), realloc(), allocFromTypedArray()
      {
        let m = w.alloc(14);
        let m2 = w.realloc(m, 16);
        T.assert(m === m2/* because of alignment */);
        T.assert(0 === w.realloc(m, 0));
        m = m2 = 0;

        // Check allocation limits and allocator's responses...
        T.assert('number' === typeof sqlite3.capi.SQLITE_MAX_ALLOCATION_SIZE);
        if(!sqlite3.config.useStdAlloc){
          const tooMuch = sqlite3.capi.SQLITE_MAX_ALLOCATION_SIZE + 1,
                isAllocErr = (e)=>e instanceof sqlite3.WasmAllocError;
          T.mustThrowMatching(()=>w.alloc(tooMuch), isAllocErr)
            .assert(0 === w.alloc.impl(tooMuch))
            .mustThrowMatching(()=>w.realloc(0, tooMuch), isAllocErr)
            .assert(0 === w.realloc.impl(0, tooMuch));
        }

        // Check allocFromTypedArray()...
        const byteList = [11,22,33]
        const u = new Uint8Array(byteList);
        m = w.allocFromTypedArray(u);
        for(let i = 0; i < u.length; ++i){
          T.assert(u[i] === byteList[i])
            .assert(u[i] === w.peek8(m + i));
        }
        w.dealloc(m);
        m = w.allocFromTypedArray(u.buffer);
        for(let i = 0; i < u.length; ++i){
          T.assert(u[i] === byteList[i])
            .assert(u[i] === w.peek8(m + i));
        }

        w.dealloc(m);
        T.mustThrowMatching(
          ()=>w.allocFromTypedArray(1),
          'Value is not of a supported TypedArray type.'
        );
      }

      { // Test peekXYZ()/pokeXYZ()...
        const m = w.alloc(8);
        T.assert( 17 === w.poke8(m,17).peek8(m) )
          .assert( 31987 === w.poke16(m,31987).peek16(m) )
          .assert( 345678 === w.poke32(m,345678).peek32(m) )
          .assert(
            T.eqApprox( 345678.9, w.poke32f(m,345678.9).peek32f(m) )
          ).assert(
            T.eqApprox( 4567890123.4, w.poke64f(m, 4567890123.4).peek64f(m) )
          );
        if(w.bigIntEnabled){
          T.assert(
            BigInt(Number.MAX_SAFE_INTEGER) ===
              w.poke64(m, Number.MAX_SAFE_INTEGER).peek64(m)
          );
        }
        w.dealloc(m);
      }

      // isPtr32()
      {
        const ip = w.isPtr32;
        T.assert(ip(0))
          .assert(!ip(-1))
          .assert(!ip(1.1))
          .assert(!ip(0xffffffff))
          .assert(ip(0x7fffffff))
          .assert(!ip())
          .assert(!ip(null)/*might change: under consideration*/)
        ;
      }

      //log("jstrlen()...");
      {
        T.assert(3 === w.jstrlen("abc")).assert(4 === w.jstrlen("äbc"));
      }

      //log("jstrcpy()...");
      {
        const fillChar = 10;
        let ua = new Uint8Array(8), rc,
            refill = ()=>ua.fill(fillChar);
        refill();
        rc = w.jstrcpy("hello", ua);
        T.assert(6===rc).assert(0===ua[5]).assert(chr('o')===ua[4]);
        refill();
        ua[5] = chr('!');
        rc = w.jstrcpy("HELLO", ua, 0, -1, false);
        T.assert(5===rc).assert(chr('!')===ua[5]).assert(chr('O')===ua[4]);
        refill();
        rc = w.jstrcpy("the end", ua, 4);
        //log("rc,ua",rc,ua);
        T.assert(4===rc).assert(0===ua[7]).
          assert(chr('e')===ua[6]).assert(chr('t')===ua[4]);
        refill();
        rc = w.jstrcpy("the end", ua, 4, -1, false);
        T.assert(4===rc).assert(chr(' ')===ua[7]).
          assert(chr('e')===ua[6]).assert(chr('t')===ua[4]);
        refill();
        rc = w.jstrcpy("", ua, 0, 1, true);
        //log("rc,ua",rc,ua);
        T.assert(1===rc).assert(0===ua[0]);
        refill();
        rc = w.jstrcpy("x", ua, 0, 1, true);
        //log("rc,ua",rc,ua);
        T.assert(1===rc).assert(0===ua[0]);
        refill();
        rc = w.jstrcpy('äbä', ua, 0, 1, true);
        T.assert(1===rc, 'Must not write partial multi-byte char.')
          .assert(0===ua[0]);
        refill();
        rc = w.jstrcpy('äbä', ua, 0, 2, true);
        T.assert(1===rc, 'Must not write partial multi-byte char.')
          .assert(0===ua[0]);
        refill();
        rc = w.jstrcpy('äbä', ua, 0, 2, false);
        T.assert(2===rc).assert(fillChar!==ua[1]).assert(fillChar===ua[2]);
      }/*jstrcpy()*/

      //log("cstrncpy()...");
      {
        const scope = w.scopedAllocPush();
        try {
          let cStr = w.scopedAllocCString("hello");
          const n = w.cstrlen(cStr);
          let cpy = w.scopedAlloc(n+10);
          let rc = w.cstrncpy(cpy, cStr, n+10);
          T.assert(n+1 === rc).
            assert("hello" === w.cstrToJs(cpy)).
            assert(chr('o') === w.peek8(cpy+n-1)).
            assert(0 === w.peek8(cpy+n));
          let cStr2 = w.scopedAllocCString("HI!!!");
          rc = w.cstrncpy(cpy, cStr2, 3);
          T.assert(3===rc).
            assert("HI!lo" === w.cstrToJs(cpy)).
            assert(chr('!') === w.peek8(cpy+2)).
            assert(chr('l') === w.peek8(cpy+3));
        }finally{
          w.scopedAllocPop(scope);
        }
      }

      //log("jstrToUintArray()...");
      {
        let a = w.jstrToUintArray("hello", false);
        T.assert(5===a.byteLength).assert(chr('o')===a[4]);
        a = w.jstrToUintArray("hello", true);
        T.assert(6===a.byteLength).assert(chr('o')===a[4]).assert(0===a[5]);
        a = w.jstrToUintArray("äbä", false);
        T.assert(5===a.byteLength).assert(chr('b')===a[2]);
        a = w.jstrToUintArray("äbä", true);
        T.assert(6===a.byteLength).assert(chr('b')===a[2]).assert(0===a[5]);
      }

      //log("allocCString()...");
      {
        const jstr = "hällo, world!";
        const [cstr, n] = w.allocCString(jstr, true);
        T.assert(14 === n)
          .assert(0===w.peek8(cstr+n))
          .assert(chr('!')===w.peek8(cstr+n-1));
        w.dealloc(cstr);
      }

      //log("scopedAlloc() and friends...");
      {
        const alloc = w.alloc, dealloc = w.dealloc;
        w.alloc = w.dealloc = null;
        T.assert(!w.scopedAlloc.level)
          .mustThrowMatching(()=>w.scopedAlloc(1), /^No scopedAllocPush/)
          .mustThrowMatching(()=>w.scopedAllocPush(), /missing alloc/);
        w.alloc = alloc;
        T.mustThrowMatching(()=>w.scopedAllocPush(), /missing alloc/);
        w.dealloc = dealloc;
        T.mustThrowMatching(()=>w.scopedAllocPop(), /^Invalid state/)
          .mustThrowMatching(()=>w.scopedAlloc(1), /^No scopedAllocPush/)
          .mustThrowMatching(()=>w.scopedAlloc.level=0, /read-only/);
        const asc = w.scopedAllocPush();
        let asc2;
        try {
          const p1 = w.scopedAlloc(16),
                p2 = w.scopedAlloc(16);
          T.assert(1===w.scopedAlloc.level)
            .assert(Number.isFinite(p1))
            .assert(Number.isFinite(p2))
            .assert(asc[0] === p1)
            .assert(asc[1]===p2);
          asc2 = w.scopedAllocPush();
          const p3 = w.scopedAlloc(16);
          T.assert(2===w.scopedAlloc.level)
            .assert(Number.isFinite(p3))
            .assert(2===asc.length)
            .assert(p3===asc2[0]);

          const [z1, z2, z3] = w.scopedAllocPtr(3);
          T.assert('number'===typeof z1).assert(z2>z1).assert(z3>z2)
            .assert(0===w.peek32(z1), 'allocPtr() must zero the targets')
            .assert(0===w.peek32(z3));
        }finally{
          // Pop them in "incorrect" order to make sure they behave:
          w.scopedAllocPop(asc);
          T.assert(0===asc.length);
          T.mustThrowMatching(()=>w.scopedAllocPop(asc),
                              /^Invalid state object/);
          if(asc2){
            T.assert(2===asc2.length,'Should be p3 and z1');
            w.scopedAllocPop(asc2);
            T.assert(0===asc2.length);
            T.mustThrowMatching(()=>w.scopedAllocPop(asc2),
                                /^Invalid state object/);
          }
        }
        T.assert(0===w.scopedAlloc.level);
        w.scopedAllocCall(function(){
          T.assert(1===w.scopedAlloc.level);
          const [cstr, n] = w.scopedAllocCString("hello, world", true);
          T.assert(12 === n)
            .assert(0===w.peek8(cstr+n))
            .assert(chr('d')===w.peek8(cstr+n-1));
        });
      }/*scopedAlloc()*/

      //log("xCall()...");
      {
        const pJson = w.xCall('sqlite3_wasm_enum_json');
        T.assert(Number.isFinite(pJson)).assert(w.cstrlen(pJson)>300);
      }

      //log("xWrap()...");
      {
        T.mustThrowMatching(()=>w.xWrap('sqlite3_libversion',null,'i32'),
                            /requires 0 arg/).
          assert(w.xWrap.resultAdapter('i32') instanceof Function).
          assert(w.xWrap.argAdapter('i32') instanceof Function);
        let fw = w.xWrap('sqlite3_libversion','utf8');
        T.mustThrowMatching(()=>fw(1), /requires 0 arg/);
        let rc = fw();
        T.assert('string'===typeof rc).assert(rc.length>5);
        rc = w.xCallWrapped('sqlite3_wasm_enum_json','*');
        T.assert(rc>0 && Number.isFinite(rc));
        rc = w.xCallWrapped('sqlite3_wasm_enum_json','utf8');
        T.assert('string'===typeof rc).assert(rc.length>300);


        { // 'string:static' argAdapter() sanity checks...
          let argAd = w.xWrap.argAdapter('string:static');
          let p0 = argAd('foo'), p1 = argAd('bar');
          T.assert(w.isPtr(p0) && w.isPtr(p1))
            .assert(p0 !== p1)
            .assert(p0 === argAd('foo'))
            .assert(p1 === argAd('bar'));
        }

        // 'string:flexible' argAdapter() sanity checks...
        w.scopedAllocCall(()=>{
          const argAd = w.xWrap.argAdapter('string:flexible');
          const cj = (v)=>w.cstrToJs(argAd(v));
          T.assert('Hi' === cj('Hi'))
            .assert('hi' === cj(['h','i']))
            .assert('HI' === cj(new Uint8Array([72, 73])));
        });

        // jsFuncToWasm()
        {
          const fsum3 = (x,y,z)=>x+y+z;
          fw = w.jsFuncToWasm('i(iii)', fsum3);
          T.assert(fw instanceof Function)
            .assert( fsum3 !== fw )
            .assert( 3 === fw.length )
            .assert( 6 === fw(1,2,3) );
          T.mustThrowMatching( ()=>w.jsFuncToWasm('x()', function(){}),
                               'Invalid signature letter: x');
        }

        // xWrap(Function,...)
        {
          let fp;
          try {
            const fmy = function fmy(i,s,d){
              if(fmy.debug) log("fmy(",...arguments,")");
              T.assert( 3 === i )
                .assert( w.isPtr(s) )
                .assert( w.cstrToJs(s) === 'a string' )
                .assert( T.eqApprox(1.2, d) );
              return w.allocCString("hi");
            };
            fmy.debug = false;
            const xwArgs = ['string:dealloc', ['i32', 'string', 'f64']];
            fw = w.xWrap(fmy, ...xwArgs);
            const fmyArgs = [3, 'a string', 1.2];
            let rc = fw(...fmyArgs);
            T.assert( 'hi' === rc );
            if(0){
              /* Retain this as a "reminder to self"...

                 This extra level of indirection does not work: the
                 string argument is ending up as a null in fmy() but
                 the numeric arguments are making their ways through

                 What's happening is: installFunction() is creating a
                 WASM-compatible function instance. When we pass a JS string
                 into there it's getting coerced into `null` before being passed
                 on to the lower-level wrapper.
              */
              fmy.debug = true;
              fp = wasm.installFunction('i(isd)', fw);
              fw = w.functionEntry(fp);
              rc = fw(...fmyArgs);
              log("rc =",rc);
              T.assert( 'hi' === rc );
              // Similarly, this does not work:
              //let fpw = w.xWrap(fp, null, [null,null,null]);
              //rc = fpw(...fmyArgs);
              //log("rc =",rc);
              //T.assert( 'hi' === rc );
            }
          }finally{
            wasm.uninstallFunction(fp);
          }
        }

        if(haveWasmCTests()){
          if(!sqlite3.config.useStdAlloc){
            fw = w.xWrap('sqlite3_wasm_test_str_hello', 'utf8:dealloc',['i32']);
            rc = fw(0);
            T.assert('hello'===rc);
            rc = fw(1);
            T.assert(null===rc);
          }

          if(w.bigIntEnabled){
            w.xWrap.resultAdapter('thrice', (v)=>3n*BigInt(v));
            w.xWrap.argAdapter('twice', (v)=>2n*BigInt(v));
            fw = w.xWrap('sqlite3_wasm_test_int64_times2','thrice','twice');
            rc = fw(1);
            T.assert(12n===rc);

            w.scopedAllocCall(function(){
              const pI1 = w.scopedAlloc(8), pI2 = pI1+4;
              w.pokePtr([pI1, pI2], 0);
              const f = w.xWrap('sqlite3_wasm_test_int64_minmax',undefined,['i64*','i64*']);
              const [r1, r2] = w.peek64([pI1, pI2]);
              T.assert(!Number.isSafeInteger(r1)).assert(!Number.isSafeInteger(r2));
            });
          }
        }
      }/*xWrap()*/
    }/*WhWasmUtil*/)

  ////////////////////////////////////////////////////////////////////
    .t('sqlite3.StructBinder (jaccwabyt🐇)', function(sqlite3){
      const S = sqlite3, W = S.wasm;
      const MyStructDef = {
        sizeof: 16,
        members: {
          p4: {offset: 0, sizeof: 4, signature: "i"},
          pP: {offset: 4, sizeof: 4, signature: "P"},
          ro: {offset: 8, sizeof: 4, signature: "i", readOnly: true},
          cstr: {offset: 12, sizeof: 4, signature: "s"}
        }
      };
      if(W.bigIntEnabled){
        const m = MyStructDef;
        m.members.p8 = {offset: m.sizeof, sizeof: 8, signature: "j"};
        m.sizeof += m.members.p8.sizeof;
      }
      const StructType = S.StructBinder.StructType;
      const K = S.StructBinder('my_struct',MyStructDef);
      T.mustThrowMatching(()=>K(), /via 'new'/).
        mustThrowMatching(()=>new K('hi'), /^Invalid pointer/);
      const k1 = new K(), k2 = new K();
      try {
        T.assert(k1.constructor === K).
          assert(K.isA(k1)).
          assert(k1 instanceof K).
          assert(K.prototype.lookupMember('p4').key === '$p4').
          assert(K.prototype.lookupMember('$p4').name === 'p4').
          mustThrowMatching(()=>K.prototype.lookupMember('nope'), /not a mapped/).
          assert(undefined === K.prototype.lookupMember('nope',false)).
          assert(k1 instanceof StructType).
          assert(StructType.isA(k1)).
          mustThrowMatching(()=>k1.$ro = 1, /read-only/);
        Object.keys(MyStructDef.members).forEach(function(key){
          key = K.memberKey(key);
          T.assert(0 == k1[key],
                   "Expecting allocation to zero the memory "+
                   "for "+key+" but got: "+k1[key]+
                   " from "+k1.memoryDump());
        });
        T.assert('number' === typeof k1.pointer).
          mustThrowMatching(()=>k1.pointer = 1, /pointer/);
        k1.$p4 = 1; k1.$pP = 2;
        T.assert(1 === k1.$p4).assert(2 === k1.$pP);
        if(MyStructDef.members.$p8){
          k1.$p8 = 1/*must not throw despite not being a BigInt*/;
          k1.$p8 = BigInt(Number.MAX_SAFE_INTEGER * 2);
          T.assert(BigInt(2 * Number.MAX_SAFE_INTEGER) === k1.$p8);
        }
        T.assert(!k1.ondispose);
        k1.setMemberCString('cstr', "A C-string.");
        T.assert(Array.isArray(k1.ondispose)).
          assert(k1.ondispose[0] === k1.$cstr).
          assert('number' === typeof k1.$cstr).
          assert('A C-string.' === k1.memberToJsString('cstr'));
        k1.$pP = k2;
        T.assert(k1.$pP === k2.pointer);
        k1.$pP = null/*null is special-cased to 0.*/;
        T.assert(0===k1.$pP);
        let ptr = k1.pointer;
        k1.dispose();
        T.assert(undefined === k1.pointer).
          mustThrowMatching(()=>{k1.$pP=1}, /disposed instance/);
      }finally{
        k1.dispose();
        k2.dispose();
      }

      if(!W.bigIntEnabled){
        log("Skipping WasmTestStruct tests: BigInt not enabled.");
        return;
      }

      const WTStructDesc =
            W.ctype.structs.filter((e)=>'WasmTestStruct'===e.name)[0];
      const autoResolvePtr = true /* EXPERIMENTAL */;
      if(autoResolvePtr){
        WTStructDesc.members.ppV.signature = 'P';
      }
      const WTStruct = S.StructBinder(WTStructDesc);
      //log(WTStruct.structName, WTStruct.structInfo);
      const wts = new WTStruct();
      //log("WTStruct.prototype keys:",Object.keys(WTStruct.prototype));
      try{
        T.assert(wts.constructor === WTStruct).
          assert(WTStruct.memberKeys().indexOf('$ppV')>=0).
          assert(wts.memberKeys().indexOf('$v8')>=0).
          assert(!K.isA(wts)).
          assert(WTStruct.isA(wts)).
          assert(wts instanceof WTStruct).
          assert(wts instanceof StructType).
          assert(StructType.isA(wts)).
          assert(wts.pointer>0).assert(0===wts.$v4).assert(0n===wts.$v8).
          assert(0===wts.$ppV).assert(0===wts.$xFunc);
        const testFunc =
              W.xGet('sqlite3_wasm_test_struct'/*name gets mangled in -O3 builds!*/);
        let counter = 0;
        //log("wts.pointer =",wts.pointer);
        const wtsFunc = function(arg){
          /*log("This from a JS function called from C, "+
              "which itself was called from JS. arg =",arg);*/
          ++counter;
          if(3===counter){
            tossQuietly("Testing exception propagation.");
          }
        }
        wts.$v4 = 10; wts.$v8 = 20;
        wts.$xFunc = W.installFunction(wtsFunc, wts.memberSignature('xFunc'))
        T.assert(0===counter).assert(10 === wts.$v4).assert(20n === wts.$v8)
          .assert(0 === wts.$ppV).assert('number' === typeof wts.$xFunc)
          .assert(0 === wts.$cstr)
          .assert(wts.memberIsString('$cstr'))
          .assert(!wts.memberIsString('$v4'))
          .assert(null === wts.memberToJsString('$cstr'))
          .assert(W.functionEntry(wts.$xFunc) instanceof Function);
        /* It might seem silly to assert that the values match
           what we just set, but recall that all of those property
           reads and writes are, via property interceptors,
           actually marshaling their data to/from a raw memory
           buffer, so merely reading them back is actually part of
           testing the struct-wrapping API. */

        testFunc(wts.pointer);
        //log("wts.pointer, wts.$ppV",wts.pointer, wts.$ppV);
        T.assert(1===counter).assert(20 === wts.$v4).assert(40n === wts.$v8)
          .assert(wts.$ppV === wts.pointer)
          .assert('string' === typeof wts.memberToJsString('cstr'))
          .assert(wts.memberToJsString('cstr') === wts.memberToJsString('$cstr'))
          .mustThrowMatching(()=>wts.memberToJsString('xFunc'),
                             /Invalid member type signature for C-string/)
        ;
        testFunc(wts.pointer);
        T.assert(2===counter).assert(40 === wts.$v4).assert(80n === wts.$v8)
          .assert(wts.$ppV === wts.pointer);
        /** The 3rd call to wtsFunc throw from JS, which is called
            from C, which is called from JS. Let's ensure that
            that exception propagates back here... */
        T.mustThrowMatching(()=>testFunc(wts.pointer),/^Testing/);
        W.uninstallFunction(wts.$xFunc);
        wts.$xFunc = 0;
        wts.$ppV = 0;
        T.assert(!wts.$ppV);
        //WTStruct.debugFlags(0x03);
        wts.$ppV = wts;
        T.assert(wts.pointer === wts.$ppV)
        wts.setMemberCString('cstr', "A C-string.");
        T.assert(Array.isArray(wts.ondispose)).
          assert(wts.ondispose[0] === wts.$cstr).
          assert('A C-string.' === wts.memberToJsString('cstr'));
        const ptr = wts.pointer;
        wts.dispose();
        T.assert(ptr).assert(undefined === wts.pointer);
      }finally{
        wts.dispose();
      }

      if(1){ // ondispose of other struct instances
        const s1 = new WTStruct, s2 = new WTStruct, s3 = new WTStruct;
        T.assert(s1.lookupMember instanceof Function)
          .assert(s1.addOnDispose instanceof Function);
        s1.addOnDispose(s2,"testing variadic args");
        T.assert(2===s1.ondispose.length);
        s2.addOnDispose(s3);
        s1.dispose();
        T.assert(!s2.pointer,"Expecting s2 to be ondispose'd by s1.");
        T.assert(!s3.pointer,"Expecting s3 to be ondispose'd by s2.");
      }
    }/*StructBinder*/)

  ////////////////////////////////////////////////////////////////////
    .t('sqlite3.wasm.pstack', function(sqlite3){
      const P = wasm.pstack;
      const isAllocErr = (e)=>e instanceof sqlite3.WasmAllocError;
      const stack = P.pointer;
      T.assert(0===stack % 8 /* must be 8-byte aligned */);
      try{
        const remaining = P.remaining;
        T.assert(P.quota >= 4096)
          .assert(remaining === P.quota)
          .mustThrowMatching(()=>P.alloc(0), isAllocErr)
          .mustThrowMatching(()=>P.alloc(-1), isAllocErr)
          .mustThrowMatching(
            ()=>P.alloc('i33'),
            (e)=>e instanceof sqlite3.WasmAllocError
          );
        ;
        let p1 = P.alloc(12);
        T.assert(p1 === stack - 16/*8-byte aligned*/)
          .assert(P.pointer === p1);
        let p2 = P.alloc(7);
        T.assert(p2 === p1-8/*8-byte aligned, stack grows downwards*/)
          .mustThrowMatching(()=>P.alloc(remaining), isAllocErr)
          .assert(24 === stack - p2)
          .assert(P.pointer === p2);
        let n = remaining - (stack - p2);
        let p3 = P.alloc(n);
        T.assert(p3 === stack-remaining)
          .mustThrowMatching(()=>P.alloc(1), isAllocErr);
      }finally{
        P.restore(stack);
      }

      T.assert(P.pointer === stack);
      try {
        const [p1, p2, p3] = P.allocChunks(3,'i32');
        T.assert(P.pointer === stack-16/*always rounded to multiple of 8*/)
          .assert(p2 === p1 + 4)
          .assert(p3 === p2 + 4);
        T.mustThrowMatching(()=>P.allocChunks(1024, 1024 * 16),
                            (e)=>e instanceof sqlite3.WasmAllocError)
      }finally{
        P.restore(stack);
      }

      T.assert(P.pointer === stack);
      try {
        let [p1, p2, p3] = P.allocPtr(3,false);
        let sPos = stack-16/*always rounded to multiple of 8*/;
        T.assert(P.pointer === sPos)
          .assert(p2 === p1 + 4)
          .assert(p3 === p2 + 4);
        [p1, p2, p3] = P.allocPtr(3);
        T.assert(P.pointer === sPos-24/*3 x 8 bytes*/)
          .assert(p2 === p1 + 8)
          .assert(p3 === p2 + 8);
        p1 = P.allocPtr();
        T.assert('number'===typeof p1);
      }finally{
        P.restore(stack);
      }
    }/*pstack tests*/)
  ////////////////////////////////////////////////////////////////////
  ;/*end of C/WASM utils checks*/

  T.g('sqlite3_randomness()')
    .t('To memory buffer', function(sqlite3){
      const stack = wasm.pstack.pointer;
      try{
        const n = 520;
        const p = wasm.pstack.alloc(n);
        T.assert(0===wasm.peek8(p))
          .assert(0===wasm.peek8(p+n-1));
        T.assert(undefined === capi.sqlite3_randomness(n - 10, p));
        let j, check = 0;
        const heap = wasm.heap8u();
        for(j = 0; j < 10 && 0===check; ++j){
          check += heap[p + j];
        }
        T.assert(check > 0);
        check = 0;
        // Ensure that the trailing bytes were not modified...
        for(j = n - 10; j < n && 0===check; ++j){
          check += heap[p + j];
        }
        T.assert(0===check);
      }finally{
        wasm.pstack.restore(stack);
      }
    })
    .t('To byte array', function(sqlite3){
      const ta = new Uint8Array(117);
      let i, n = 0;
      for(i=0; i<ta.byteLength && 0===n; ++i){
        n += ta[i];
      }
      T.assert(0===n)
        .assert(ta === capi.sqlite3_randomness(ta));
      for(i=ta.byteLength-10; i<ta.byteLength && 0===n; ++i){
        n += ta[i];
      }
      T.assert(n>0);
      const t0 = new Uint8Array(0);
      T.assert(t0 === capi.sqlite3_randomness(t0),
               "0-length array is a special case");
    })
  ;/*end sqlite3_randomness() checks*/

  ////////////////////////////////////////////////////////////////////////
  T.g('sqlite3.oo1')
    .t('Create db', function(sqlite3){
      const dbFile = '/tester1.db';
      wasm.sqlite3_wasm_vfs_unlink(0, dbFile);
      const db = this.db = new sqlite3.oo1.DB(dbFile, 0 ? 'ct' : 'c');
      db.onclose = {
        disposeAfter: [],
        disposeBefore: [
          (db)=>{
            //console.debug("db.onclose.before dropping modules");
            //sqlite3.capi.sqlite3_drop_modules(db.pointer, 0);
          }
        ],
        before: function(db){
          while(this.disposeBefore.length){
            const v = this.disposeBefore.shift();
            console.debug("db.onclose.before cleaning up:",v);
            if(wasm.isPtr(v)) wasm.dealloc(v);
            else if(v instanceof sqlite3.StructBinder.StructType){
              v.dispose();
            }else if(v instanceof Function){
              try{ v(db) } catch(e){
                console.warn("beforeDispose() callback threw:",e);
              }
            }
          }
        },
        after: function(){
          while(this.disposeAfter.length){
            const v = this.disposeAfter.shift();
            console.debug("db.onclose.after cleaning up:",v);
            if(wasm.isPtr(v)) wasm.dealloc(v);
            else if(v instanceof sqlite3.StructBinder.StructType){
              v.dispose();
            }else if(v instanceof Function){
              try{v()} catch(e){/*ignored*/}
            }
          }
        }
      };

      T.assert(wasm.isPtr(db.pointer))
        .mustThrowMatching(()=>db.pointer=1, /read-only/)
        .assert(0===sqlite3.capi.sqlite3_extended_result_codes(db.pointer,1))
        .assert('main'===db.dbName(0))
        .assert('string' === typeof db.dbVfsName())
        .assert(db.pointer === wasm.xWrap.testConvertArg('sqlite3*',db));
      // Custom db error message handling via sqlite3_prepare_v2/v3()
      let rc = capi.sqlite3_prepare_v3(db.pointer, {/*invalid*/}, -1, 0, null, null);
      T.assert(capi.SQLITE_MISUSE === rc)
        .assert(0 === capi.sqlite3_errmsg(db.pointer).indexOf("Invalid SQL"))
        .assert(dbFile === db.dbFilename())
        .assert(!db.dbFilename('nope'));
      //Sanity check DB.checkRc()...
      let ex;
      try{db.checkRc(rc)}
      catch(e){ex = e}
      T.assert(ex instanceof sqlite3.SQLite3Error)
        .assert(0===ex.message.indexOf("sqlite3 result code"))
        .assert(ex.message.indexOf("Invalid SQL")>0);
      T.assert(db === db.checkRc(0))
        .assert(db === sqlite3.oo1.DB.checkRc(db,0))
        .assert(null === sqlite3.oo1.DB.checkRc(null,0));

      this.progressHandlerCount = 0;
      capi.sqlite3_progress_handler(db, 5, (p)=>{
        ++this.progressHandlerCount;
        return 0;
      }, 0);
    })
  ////////////////////////////////////////////////////////////////////
    .t('sqlite3_db_config() and sqlite3_db_status()', function(sqlite3){
      let rc = capi.sqlite3_db_config(this.db, capi.SQLITE_DBCONFIG_LEGACY_ALTER_TABLE, 0, 0);
      T.assert(0===rc);
      rc = capi.sqlite3_db_config(this.db, capi.SQLITE_DBCONFIG_MAX+1, 0);
      T.assert(capi.SQLITE_MISUSE === rc);
      rc = capi.sqlite3_db_config(this.db, capi.SQLITE_DBCONFIG_MAINDBNAME, "main");
      T.assert(0 === rc);
      const stack = wasm.pstack.pointer;
      try {
        const [pCur, pHi] = wasm.pstack.allocChunks(2,'i64');
        rc = capi.sqlite3_db_status(this.db, capi.SQLITE_DBSTATUS_LOOKASIDE_USED,
                                    pCur, pHi, 0);
        T.assert(0===rc);
        if(!wasm.peek32(pCur)){
          rc = capi.sqlite3_db_config(this.db, capi.SQLITE_DBCONFIG_LOOKASIDE,
                                      0, 4096, 12);
          T.assert(0 === rc);
        }else{
          console.debug("Cannot test db_config(SQLITE_DBCONFIG_LOOKASIDE)",
                        "while lookaside memory is in use.");
        }
        wasm.poke32([pCur, pHi], 0);
        let [vCur, vHi] = wasm.peek32(pCur, pHi);
        T.assert(0===vCur).assert(0===vHi);
        rc = capi.sqlite3_status(capi.SQLITE_STATUS_MEMORY_USED,
                                 pCur, pHi, 0);
        [vCur, vHi] = wasm.peek32(pCur, pHi);
        //console.warn("i32 vCur,vHi",vCur,vHi);
        T.assert(0 === rc).assert(vCur > 0).assert(vHi >= vCur);
        if(wasm.bigIntEnabled){
          // Again in 64-bit. Recall that pCur and pHi are allocated
          // large enough to account for this re-use.
          wasm.poke64([pCur, pHi], 0);
          rc = capi.sqlite3_status64(capi.SQLITE_STATUS_MEMORY_USED,
                                     pCur, pHi, 0);
          [vCur, vHi] = wasm.peek64([pCur, pHi]);
          //console.warn("i64 vCur,vHi",vCur,vHi);
          T.assert(0 === rc).assert(vCur > 0).assert(vHi >= vCur);
        }
      }finally{
        wasm.pstack.restore(stack);
      }
    })

  ////////////////////////////////////////////////////////////////////
    .t('DB.Stmt', function(sqlite3){
      let st = this.db.prepare(
        new TextEncoder('utf-8').encode("select 3 as a")
      );
      //debug("statement =",st);
      this.progressHandlerCount = 0;
      try {
        T.assert(wasm.isPtr(st.pointer))
          .mustThrowMatching(()=>st.pointer=1, /read-only/)
          .assert(1===this.db.openStatementCount())
          .assert(
            capi.sqlite3_stmt_status(
              st, capi.SQLITE_STMTSTATUS_RUN, 0
            ) === 0)
          .assert(!st._mayGet)
          .assert('a' === st.getColumnName(0))
          .assert(1===st.columnCount)
          .assert(0===st.parameterCount)
          .mustThrow(()=>st.bind(1,null))
          .assert(true===st.step())
          .assert(3 === st.get(0))
          .mustThrow(()=>st.get(1))
          .mustThrow(()=>st.get(0,~capi.SQLITE_INTEGER))
          .assert(3 === st.get(0,capi.SQLITE_INTEGER))
          .assert(3 === st.getInt(0))
          .assert('3' === st.get(0,capi.SQLITE_TEXT))
          .assert('3' === st.getString(0))
          .assert(3.0 === st.get(0,capi.SQLITE_FLOAT))
          .assert(3.0 === st.getFloat(0))
          .assert(3 === st.get({}).a)
          .assert(3 === st.get([])[0])
          .assert(3 === st.getJSON(0))
          .assert(st.get(0,capi.SQLITE_BLOB) instanceof Uint8Array)
          .assert(1===st.get(0,capi.SQLITE_BLOB).length)
          .assert(st.getBlob(0) instanceof Uint8Array)
          .assert('3'.charCodeAt(0) === st.getBlob(0)[0])
          .assert(st._mayGet)
          .assert(false===st.step())
          .assert(!st._mayGet)
          .assert(
            capi.sqlite3_stmt_status(
              st, capi.SQLITE_STMTSTATUS_RUN, 0
            ) > 0);

        T.assert(this.progressHandlerCount > 0,
                 "Expecting progress callback.").
          assert(0===capi.sqlite3_strglob("*.txt", "foo.txt")).
          assert(0!==capi.sqlite3_strglob("*.txt", "foo.xtx")).
          assert(0===capi.sqlite3_strlike("%.txt", "foo.txt", 0)).
          assert(0!==capi.sqlite3_strlike("%.txt", "foo.xtx", 0));
      }finally{
        st.finalize();
      }
      T.assert(!st.pointer)
        .assert(0===this.db.openStatementCount());

      T.mustThrowMatching(()=>new sqlite3.oo1.Stmt("hi"), function(err){
        return (err instanceof sqlite3.SQLite3Error)
          && capi.SQLITE_MISUSE === err.resultCode
          && 0 < err.message.indexOf("Do not call the Stmt constructor directly.")
      });
    })

  ////////////////////////////////////////////////////////////////////////
    .t('sqlite3_js_...()', function(){
      const db = this.db;
      if(1){
        const vfsList = capi.sqlite3_js_vfs_list();
        T.assert(vfsList.length>1);
        //log("vfsList =",vfsList);
        wasm.scopedAllocCall(()=>{
          const vfsArg = (v)=>wasm.xWrap.testConvertArg('sqlite3_vfs*',v);
          for(const v of vfsList){
            T.assert('string' === typeof v);
            const pVfs = capi.sqlite3_vfs_find(v);
            T.assert(wasm.isPtr(pVfs))
              .assert(pVfs===vfsArg(v));
            const vfs = new capi.sqlite3_vfs(pVfs);
            try { T.assert(vfsArg(vfs)===pVfs) }
            finally{ vfs.dispose() }
          }
        });
      }
      /**
         Trivia: the magic db name ":memory:" does not actually use the
         "memdb" VFS unless "memdb" is _explicitly_ provided as the VFS
         name. Instead, it uses the default VFS with an in-memory btree.
         Thus this.db's VFS may not be memdb even though it's an in-memory
         db.
      */
      const pVfsMem = capi.sqlite3_vfs_find('memdb'),
            pVfsDflt = capi.sqlite3_vfs_find(0),
            pVfsDb = capi.sqlite3_js_db_vfs(db.pointer);
      T.assert(pVfsMem > 0)
        .assert(pVfsDflt > 0)
        .assert(pVfsDb > 0)
        .assert(pVfsMem !== pVfsDflt
                /* memdb lives on top of the default vfs */)
        .assert(pVfsDb === pVfsDflt || pVfsdb === pVfsMem)
      ;
      /*const vMem = new capi.sqlite3_vfs(pVfsMem),
        vDflt = new capi.sqlite3_vfs(pVfsDflt),
        vDb = new capi.sqlite3_vfs(pVfsDb);*/
      const duv = capi.sqlite3_js_db_uses_vfs;
      T.assert(pVfsDflt === duv(db.pointer, 0)
               || pVfsMem === duv(db.pointer,0))
        .assert(!duv(db.pointer, "foo"))
      ;
    }/*sqlite3_js_...()*/)

  ////////////////////////////////////////////////////////////////////
    .t('Table t', function(sqlite3){
      const db = this.db;
      let list = [];
      this.progressHandlerCount = 0;
      let rc = db.exec({
        sql:['CREATE TABLE t(a,b);',
             // ^^^ using TEMP TABLE breaks the db export test
             "INSERT INTO t(a,b) VALUES(1,2),(3,4),",
             "(?,?),('blob',X'6869')"/*intentionally missing semicolon to test for
                                       off-by-one bug in string-to-WASM conversion*/],
        saveSql: list,
        bind: [5,6]
      });
      //debug("Exec'd SQL:", list);
      T.assert(rc === db)
        .assert(2 === list.length)
        .assert('string'===typeof list[1])
        .assert(4===db.changes())
        .assert(this.progressHandlerCount > 0,
                "Expecting progress callback.")
      if(wasm.bigIntEnabled){
        T.assert(4n===db.changes(false,true));
      }

      let vals = db.selectValues('select a from t order by a limit 2');
      T.assert( 2 === vals.length )
        .assert( 1===vals[0] && 3===vals[1] );
      vals = db.selectValues('select a from t order by a limit $L',
                             {$L:2}, capi.SQLITE_TEXT);
      T.assert( 2 === vals.length )
        .assert( '1'===vals[0] && '3'===vals[1] );
      vals = undefined;

      let blob = db.selectValue("select b from t where a='blob'");
      T.assert(blob instanceof Uint8Array).
        assert(0x68===blob[0] && 0x69===blob[1]);
      blob = null;
      let counter = 0, colNames = [];
      list.length = 0;
      db.exec(new TextEncoder('utf-8').encode("SELECT a a, b b FROM t"),{
        rowMode: 'object',
        resultRows: list,
        columnNames: colNames,
        _myState: 3 /* Accessible from the callback */,
        callback: function(row,stmt){
          ++counter;
          T.assert(
            3 === this._myState
            /* Recall that "this" is the options object. */
          ).assert(
            this.columnNames[0]==='a' && this.columnNames[1]==='b'
            /* options.columnNames is filled out before the first
               Stmt.step(). */
          ).assert(
            (row.a%2 && row.a<6) || 'blob'===row.a
          );
        }
      });
      T.assert(2 === colNames.length)
        .assert('a' === colNames[0])
        .assert(4 === counter)
        .assert(4 === list.length);
      list.length = 0;
      db.exec("SELECT a a, b b FROM t",{
        rowMode: 'array',
        callback: function(row,stmt){
          ++counter;
          T.assert(Array.isArray(row))
            .assert((0===row[1]%2 && row[1]<7)
                    || (row[1] instanceof Uint8Array));
        }
      });
      T.assert(8 === counter);
      T.assert(Number.MIN_SAFE_INTEGER ===
               db.selectValue("SELECT "+Number.MIN_SAFE_INTEGER)).
        assert(Number.MAX_SAFE_INTEGER ===
               db.selectValue("SELECT "+Number.MAX_SAFE_INTEGER));
      counter = 0;
      let rv = db.exec({
        sql: "SELECT a FROM t",
        callback: ()=>(1===++counter),
      });
      T.assert(db === rv)
        .assert(2===counter,
               "Expecting exec step() loop to stop if callback returns false.");
      /** If exec() is passed neither callback nor returnValue but
          is passed an explicit rowMode then the default returnValue
          is the whole result set, as if an empty resultRows option
          had been passed. */
      rv = db.exec({
        sql: "SELECT -1 UNION ALL SELECT -2 UNION ALL SELECT -3 ORDER BY 1 DESC",
        rowMode: 0
      });
      T.assert(Array.isArray(rv)).assert(3===rv.length)
        .assert(-1===rv[0]).assert(-3===rv[2]);
      rv = db.exec("SELECT 1 WHERE 0",{rowMode: 0});
      T.assert(Array.isArray(rv)).assert(0===rv.length);
      if(wasm.bigIntEnabled && haveWasmCTests()){
        const mI = wasm.xCall('sqlite3_wasm_test_int64_max');
        const b = BigInt(Number.MAX_SAFE_INTEGER * 2);
        T.assert(b === db.selectValue("SELECT "+b)).
          assert(b === db.selectValue("SELECT ?", b)).
          assert(mI == db.selectValue("SELECT $x", {$x:mI}));
      }else{
        /* Curiously, the JS spec seems to be off by one with the definitions
           of MIN/MAX_SAFE_INTEGER:

           https://github.com/emscripten-core/emscripten/issues/17391 */
        T.mustThrow(()=>db.selectValue("SELECT "+(Number.MAX_SAFE_INTEGER+1))).
          mustThrow(()=>db.selectValue("SELECT "+(Number.MIN_SAFE_INTEGER-1)));
      }

      let st = db.prepare("update t set b=:b where a='blob'");
      try {
        const ndx = st.getParamIndex(':b');
        T.assert(1===ndx);
        st.bindAsBlob(ndx, "ima blob").reset(true);
      } finally {
        st.finalize();
      }

      try {
        db.prepare("/*empty SQL*/");
        toss("Must not be reached.");
      }catch(e){
        T.assert(e instanceof sqlite3.SQLite3Error)
          .assert(0==e.message.indexOf('Cannot prepare empty'));
      }
    })/*setup table T*/

  ////////////////////////////////////////////////////////////////////
    .t({
      name: "sqlite3_set_authorizer()",
      test:function(sqlite3){
        T.assert(capi.SQLITE_IGNORE>0)
          .assert(capi.SQLITE_DENY>0);
        const db = this.db;
        const ssa = capi.sqlite3_set_authorizer;
        const n = db.selectValue('select count(*) from t');
        T.assert(n>0);
        let authCount = 0;
        let rc = ssa(db, function(pV, iCode, s0, s1, s2, s3){
          ++authCount;
          return capi.SQLITE_IGNORE;
        }, 0);
        T.assert(0===rc)
          .assert(
            undefined === db.selectValue('select count(*) from t')
            /* Note that the count() never runs, so we get undefined
               instead of 0. */
          )
          .assert(authCount>0);
        authCount = 0;
        db.exec("update t set a=-9999");
        T.assert(authCount>0);
        /* Reminder: we don't use DELETE because, from the C API docs:

          "If the action code is [SQLITE_DELETE] and the callback
          returns [SQLITE_IGNORE] then the [DELETE] operation proceeds
          but the [truncate optimization] is disabled and all rows are
          deleted individually."
        */
        rc = ssa(db, null, 0);
        authCount = 0;
        T.assert(-9999 != db.selectValue('select a from t'))
          .assert(0===authCount);
        rc = ssa(db, function(pV, iCode, s0, s1, s2, s3){
          ++authCount;
          return capi.SQLITE_DENY;
        }, 0);
        T.assert(0===rc);
        let err;
        try{ db.exec("select 1 from t") }
        catch(e){ err = e }
        T.assert(err instanceof sqlite3.SQLite3Error)
          .assert(err.message.indexOf('not authorized'>0))
          .assert(1===authCount);
        authCount = 0;
        rc = ssa(db, function(...args){
          ++authCount;
          return capi.SQLITE_OK;
        }, 0);
        T.assert(0===rc);
        T.assert(n === db.selectValue('select count(*) from t'))
          .assert(authCount>0);
        authCount = 0;
        rc = ssa(db, function(pV, iCode, s0, s1, s2, s3){
          ++authCount;
          throw new Error("Testing catching of authorizer.");
        }, 0);
        T.assert(0===rc);
        authCount = 0;
        err = undefined;
        try{ db.exec("select 1 from t") }
        catch(e){err = e}
        T.assert(err instanceof Error)
          .assert(err.message.indexOf('not authorized')>0)
        /* Note that the thrown message is trumped/overwritten
           by the authorizer process. */
          .assert(1===authCount);
        rc = ssa(db, 0, 0);
        authCount = 0;
        T.assert(0===rc);
        T.assert(n === db.selectValue('select count(*) from t'))
          .assert(0===authCount);
      }
    })/*sqlite3_set_authorizer()*/

  ////////////////////////////////////////////////////////////////////////
    .t("sqlite3_table_column_metadata()", function(sqlite3){
      const stack = wasm.pstack.pointer;
      try{
        const [pzDT, pzColl, pNotNull, pPK, pAuto] =
              wasm.pstack.allocPtr(5);
        const rc = capi.sqlite3_table_column_metadata(
          this.db, "main", "t", "rowid",
          pzDT, pzColl, pNotNull, pPK, pAuto
        );
        T.assert(0===rc)
          .assert("INTEGER"===wasm.cstrToJs(wasm.peekPtr(pzDT)))
          .assert("BINARY"===wasm.cstrToJs(wasm.peekPtr(pzColl)))
          .assert(0===wasm.peek32(pNotNull))
          .assert(1===wasm.peek32(pPK))
          .assert(0===wasm.peek32(pAuto))
      }finally{
        wasm.pstack.restore(stack);
      }
    })

  ////////////////////////////////////////////////////////////////////////
    .t('selectArray/Object()', function(sqlite3){
      const db = this.db;
      let rc = db.selectArray('select a, b from t where a=?', 5);
      T.assert(Array.isArray(rc))
        .assert(2===rc.length)
        .assert(5===rc[0] && 6===rc[1]);
      rc = db.selectArray('select a, b from t where b=-1');
      T.assert(undefined === rc);
      rc = db.selectObject('select a A, b b from t where b=?', 6);
      T.assert(rc && 'object'===typeof rc)
        .assert(5===rc.A)
        .assert(6===rc.b);
      rc = db.selectArray('select a, b from t where b=-1');
      T.assert(undefined === rc);
    })
  ////////////////////////////////////////////////////////////////////////
    .t('selectArrays/Objects()', function(sqlite3){
      const db = this.db;
      const sql = 'select a, b from t where a=? or b=? order by a';
      let rc = db.selectArrays(sql, [1, 4]);
      T.assert(Array.isArray(rc))
        .assert(2===rc.length)
        .assert(2===rc[0].length)
        .assert(1===rc[0][0])
        .assert(2===rc[0][1])
        .assert(3===rc[1][0])
        .assert(4===rc[1][1])
      rc = db.selectArrays(sql, [99,99]);
      T.assert(Array.isArray(rc)).assert(0===rc.length);
      rc = db.selectObjects(sql, [1,4]);
      T.assert(Array.isArray(rc))
        .assert(2===rc.length)
        .assert('object' === typeof rc[1])
        .assert(1===rc[0].a)
        .assert(2===rc[0].b)
        .assert(3===rc[1].a)
        .assert(4===rc[1].b);
    })

  ////////////////////////////////////////////////////////////////////////
    .t({
      name: 'sqlite3_js_db_export()',
      predicate: ()=>true,
      test: function(sqlite3){
        const db = this.db;
        const xp = capi.sqlite3_js_db_export(db.pointer);
        T.assert(xp instanceof Uint8Array)
          .assert(xp.byteLength>0)
          .assert(0 === xp.byteLength % 512);
        this.dbExport = xp;
      }
    }/*sqlite3_js_db_export()*/)
    .t({
      name: 'sqlite3_js_vfs_create_file() with db in default VFS',
      predicate: ()=>true,
      test: function(sqlite3){
        const db = this.db;
        const pVfs = capi.sqlite3_js_db_vfs(db);
        const filename = "sqlite3_js_vfs_create_file().db";
        capi.sqlite3_js_vfs_create_file(pVfs, filename, this.dbExport);
        delete this.dbExport;
        const db2 = new sqlite3.oo1.DB(filename,'r');
        try {
          const sql = "select count(*) from t";
          const n = db.selectValue(sql);
          T.assert(n>0 && db2.selectValue(sql) === n);
        }finally{
          db2.close();
          wasm.sqlite3_wasm_vfs_unlink(pVfs, filename);
        }
      }
    }/*sqlite3_js_vfs_create_file()*/)

  ////////////////////////////////////////////////////////////////////
    .t({
      name:'Scalar UDFs',
      test: function(sqlite3){
        const db = this.db;
        db.createFunction("foo",(pCx,a,b)=>a+b);
        T.assert(7===db.selectValue("select foo(3,4)")).
          assert(5===db.selectValue("select foo(3,?)",2)).
          assert(5===db.selectValue("select foo(?,?2)",[1,4])).
          assert(5===db.selectValue("select foo($a,$b)",{$a:0,$b:5}));
        db.createFunction("bar", {
          arity: -1,
          xFunc: (pCx,...args)=>{
            T.assert(db.pointer === capi.sqlite3_context_db_handle(pCx));
            let rc = 0;
            for(const v of args) rc += v;
            return rc;
          }
        }).createFunction({
          name: "asis",
          xFunc: (pCx,arg)=>arg
        });
        T.assert(0===db.selectValue("select bar()")).
          assert(1===db.selectValue("select bar(1)")).
          assert(3===db.selectValue("select bar(1,2)")).
          assert(-1===db.selectValue("select bar(1,2,-4)")).
          assert('hi' === db.selectValue("select asis('hi')")).
          assert('hi' === db.selectValue("select ?",'hi')).
          assert(null === db.selectValue("select null")).
          assert(null === db.selectValue("select asis(null)")).
          assert(1 === db.selectValue("select ?",1)).
          assert(2 === db.selectValue("select ?",[2])).
          assert(3 === db.selectValue("select $a",{$a:3})).
          assert(T.eqApprox(3.1,db.selectValue("select 3.0 + 0.1"))).
          assert(T.eqApprox(1.3,db.selectValue("select asis(1 + 0.3)")));

        let blobArg = new Uint8Array([0x68, 0x69]);
        let blobRc = db.selectValue(
          "select asis(?1)",
          blobArg.buffer/*confirm that ArrayBuffer is handled as a Uint8Array*/
        );
        T.assert(blobRc instanceof Uint8Array).
          assert(2 === blobRc.length).
          assert(0x68==blobRc[0] && 0x69==blobRc[1]);
        blobRc = db.selectValue("select asis(X'6869')");
        T.assert(blobRc instanceof Uint8Array).
          assert(2 === blobRc.length).
          assert(0x68==blobRc[0] && 0x69==blobRc[1]);

        blobArg = new Int8Array([0x68, 0x69]);
        //debug("blobArg=",blobArg);
        blobRc = db.selectValue("select asis(?1)", blobArg);
        T.assert(blobRc instanceof Uint8Array).
          assert(2 === blobRc.length);
        //debug("blobRc=",blobRc);
        T.assert(0x68==blobRc[0] && 0x69==blobRc[1]);

        let rc = sqlite3.capi.sqlite3_create_function_v2(
          this.db, "foo", 0, -1, 0, 0, 0, 0, 0
        );
        T.assert(
          sqlite3.capi.SQLITE_FORMAT === rc,
          "For invalid eTextRep argument."
        );
        rc = sqlite3.capi.sqlite3_create_function_v2(this.db, "foo", 0);
        T.assert(
          sqlite3.capi.SQLITE_MISUSE === rc,
          "For invalid arg count."
        );

        /* Confirm that we can map and unmap the same function with
           multiple arities... */
        const fCounts = [0,0];
        const fArityCheck = function(pCx){
          return ++fCounts[arguments.length-1];
        };
        //wasm.xWrap.FuncPtrAdapter.debugFuncInstall = true;
        rc = capi.sqlite3_create_function_v2(
          db, "nary", 0, capi.SQLITE_UTF8, 0, fArityCheck, 0, 0, 0
        );
        T.assert( 0===rc );
        rc = capi.sqlite3_create_function_v2(
          db, "nary", 1, capi.SQLITE_UTF8, 0, fArityCheck, 0, 0, 0
        );
        T.assert( 0===rc );
        const sqlFArity0 = "select nary()";
        const sqlFArity1 = "select nary(1)";
        T.assert( 1 === db.selectValue(sqlFArity0) )
          .assert( 1 === fCounts[0] ).assert( 0 === fCounts[1] );
        T.assert( 1 === db.selectValue(sqlFArity1) )
          .assert( 1 === fCounts[0] ).assert( 1 === fCounts[1] );
        capi.sqlite3_create_function_v2(
          db, "nary", 0, capi.SQLITE_UTF8, 0, 0, 0, 0, 0
        );
        T.mustThrowMatching((()=>db.selectValue(sqlFArity0)),
                            (e)=>((e instanceof sqlite3.SQLite3Error)
                                  && e.message.indexOf("wrong number of arguments")>0),
                            "0-arity variant was uninstalled.");
        T.assert( 2 === db.selectValue(sqlFArity1) )
          .assert( 1 === fCounts[0] ).assert( 2 === fCounts[1] );
        capi.sqlite3_create_function_v2(
          db, "nary", 1, capi.SQLITE_UTF8, 0, 0, 0, 0, 0
        );
        T.mustThrowMatching((()=>db.selectValue(sqlFArity1)),
                            (e)=>((e instanceof sqlite3.SQLite3Error)
                                  && e.message.indexOf("no such function")>0),
                            "1-arity variant was uninstalled.");
        //wasm.xWrap.FuncPtrAdapter.debugFuncInstall = false;
      }
    })

  ////////////////////////////////////////////////////////////////////
    .t({
      name: 'Aggregate UDFs',
      //predicate: ()=>false,
      test: function(sqlite3){
        const db = this.db;
        const sjac = capi.sqlite3_js_aggregate_context;
        db.createFunction({
          name: 'summer',
          xStep: (pCtx, n)=>{
            const ac = sjac(pCtx, 4);
            wasm.poke32(ac, wasm.peek32(ac) + Number(n));
          },
          xFinal: (pCtx)=>{
            const ac = sjac(pCtx, 0);
            return ac ? wasm.peek32(ac) : 0;
          }
        });
        let v = db.selectValue([
          "with cte(v) as (",
          "select 3 union all select 5 union all select 7",
          ") select summer(v), summer(v+1) from cte"
          /* ------------------^^^^^^^^^^^ ensures that we're handling
              sqlite3_aggregate_context() properly. */
        ]);
        T.assert(15===v);
        T.mustThrowMatching(()=>db.selectValue("select summer(1,2)"),
                            /wrong number of arguments/);

        db.createFunction({
          name: 'summerN',
          arity: -1,
          xStep: (pCtx, ...args)=>{
            const ac = sjac(pCtx, 4);
            let sum = wasm.peek32(ac);
            for(const v of args) sum += Number(v);
            wasm.poke32(ac, sum);
          },
          xFinal: (pCtx)=>{
            const ac = sjac(pCtx, 0);
            capi.sqlite3_result_int( pCtx, ac ? wasm.peek32(ac) : 0 );
            // xFinal() may either return its value directly or call
            // sqlite3_result_xyz() and return undefined. Both are
            // functionally equivalent.
          }
        });
        T.assert(18===db.selectValue('select summerN(1,8,9), summerN(2,3,4)'));
        T.mustThrowMatching(()=>{
          db.createFunction('nope',{
            xFunc: ()=>{}, xStep: ()=>{}
          });
        }, /scalar or aggregate\?/);
        T.mustThrowMatching(()=>{
          db.createFunction('nope',{xStep: ()=>{}});
        }, /Missing xFinal/);
        T.mustThrowMatching(()=>{
          db.createFunction('nope',{xFinal: ()=>{}});
        }, /Missing xStep/);
        T.mustThrowMatching(()=>{
          db.createFunction('nope',{});
        }, /Missing function-type properties/);
        T.mustThrowMatching(()=>{
          db.createFunction('nope',{xFunc:()=>{}, xDestroy:'nope'});
        }, /xDestroy property must be a function/);
        T.mustThrowMatching(()=>{
          db.createFunction('nope',{xFunc:()=>{}, pApp:'nope'});
        }, /Invalid value for pApp/);
     }
    }/*aggregate UDFs*/)

  ////////////////////////////////////////////////////////////////////////
    .t({
      name: 'Aggregate UDFs (64-bit)',
      predicate: ()=>wasm.bigIntEnabled,
      //predicate: ()=>false,
      test: function(sqlite3){
        const db = this.db;
        const sjac = capi.sqlite3_js_aggregate_context;
        db.createFunction({
          name: 'summer64',
          xStep: (pCtx, n)=>{
            const ac = sjac(pCtx, 8);
            wasm.poke64(ac, wasm.peek64(ac) + BigInt(n));
          },
          xFinal: (pCtx)=>{
            const ac = sjac(pCtx, 0);
            return ac ? wasm.peek64(ac) : 0n;
          }
        });
        let v = db.selectValue([
          "with cte(v) as (",
          "select 9007199254740991 union all select 1 union all select 2",
          ") select summer64(v), summer64(v+1) from cte"
        ]);
        T.assert(9007199254740994n===v);
     }
    }/*aggregate UDFs*/)

  ////////////////////////////////////////////////////////////////////
    .t({
      name: 'Window UDFs',
      //predicate: ()=>false,
      test: function(){
        /* Example window function, table, and results taken from:
           https://sqlite.org/windowfunctions.html#udfwinfunc */
        const db = this.db;
        const sjac = (cx,n=4)=>capi.sqlite3_js_aggregate_context(cx,n);
        const xValueFinal = (pCtx)=>{
          const ac = sjac(pCtx, 0);
          return ac ? wasm.peek32(ac) : 0;
        };
        const xStepInverse = (pCtx, n)=>{
          const ac = sjac(pCtx);
          wasm.poke32(ac, wasm.peek32(ac) + Number(n));
        };
        db.createFunction({
          name: 'winsumint',
          xStep: (pCtx, n)=>xStepInverse(pCtx, n),
          xInverse: (pCtx, n)=>xStepInverse(pCtx, -n),
          xFinal: xValueFinal,
          xValue: xValueFinal
        });
        db.exec([
          "CREATE TEMP TABLE twin(x, y); INSERT INTO twin VALUES",
          "('a', 4),('b', 5),('c', 3),('d', 8),('e', 1)"
        ]);
        let rc = db.exec({
          returnValue: 'resultRows',
          sql:[
            "SELECT x, winsumint(y) OVER (",
            "ORDER BY x ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING",
            ") AS sum_y ",
            "FROM twin ORDER BY x;"
          ]
        });
        T.assert(Array.isArray(rc))
          .assert(5 === rc.length);
        let count = 0;
        for(const row of rc){
          switch(++count){
              case 1: T.assert('a'===row[0] && 9===row[1]); break;
              case 2: T.assert('b'===row[0] && 12===row[1]); break;
              case 3: T.assert('c'===row[0] && 16===row[1]); break;
              case 4: T.assert('d'===row[0] && 12===row[1]); break;
              case 5: T.assert('e'===row[0] && 9===row[1]); break;
              default: toss("Too many rows to window function.");
          }
        }
        const resultRows = [];
        rc = db.exec({
          resultRows,
          returnValue: 'resultRows',
          sql:[
            "SELECT x, winsumint(y) OVER (",
            "ORDER BY x ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING",
            ") AS sum_y ",
            "FROM twin ORDER BY x;"
          ]
        });
        T.assert(rc === resultRows)
          .assert(5 === rc.length);

        rc = db.exec({
          returnValue: 'saveSql',
          sql: "select 1; select 2; -- empty\n; select 3"
        });
        T.assert(Array.isArray(rc))
          .assert(3===rc.length)
          .assert('select 1;' === rc[0])
          .assert('select 2;' === rc[1])
          .assert('-- empty\n; select 3' === rc[2]
                  /* Strange but true. */);
        T.mustThrowMatching(()=>{
          db.exec({sql:'', returnValue: 'nope'});
        }, /^Invalid returnValue/);

        db.exec("DROP TABLE twin");
      }
    }/*window UDFs*/)

  ////////////////////////////////////////////////////////////////////
    .t("ATTACH", function(){
      const db = this.db;
      const resultRows = [];
      db.exec({
        sql:new TextEncoder('utf-8').encode([
          // ^^^ testing string-vs-typedarray handling in exec()
          "attach 'session' as foo;",
          "create table foo.bar(a);",
          "insert into foo.bar(a) values(1),(2),(3);",
          "select a from foo.bar order by a;"
        ].join('')),
        rowMode: 0,
        resultRows
      });
      T.assert(3===resultRows.length)
        .assert(2===resultRows[1]);
      T.assert(2===db.selectValue('select a from foo.bar where a>1 order by a'));

      /** Demonstrate the JS-simplified form of the sqlite3_exec() callback... */
      let colCount = 0, rowCount = 0;
      let rc = capi.sqlite3_exec(
        db, "select a, a*2 from foo.bar", function(aVals, aNames){
          //console.warn("execCallback(",arguments,")");
          colCount = aVals.length;
          ++rowCount;
          T.assert(2===aVals.length)
            .assert(2===aNames.length)
            .assert(+(aVals[1]) === 2 * +(aVals[0]));
        }, 0, 0
      );
      T.assert(0===rc).assert(3===rowCount).assert(2===colCount);
      rc = capi.sqlite3_exec(
        db.pointer, "select a from foo.bar", ()=>{
          tossQuietly("Testing throwing from exec() callback.");
        }, 0, 0
      );
      T.assert(capi.SQLITE_ABORT === rc);

      /* Demonstrate how to get access to the "full" callback
         signature, as opposed to the simplified JS-specific one... */
      rowCount = colCount = 0;
      const pCb = wasm.installFunction('i(pipp)', function(pVoid,nCols,aVals,aCols){
        /* Tip: wasm.cArgvToJs() can be used to convert aVals and
           aCols to arrays: const vals = wasm.cArgvToJs(nCols,
           aVals); */
        ++rowCount;
        colCount = nCols;
        T.assert(2 === nCols)
          .assert(wasm.isPtr(pVoid))
          .assert(wasm.isPtr(aVals))
          .assert(wasm.isPtr(aCols))
          .assert(+wasm.cstrToJs(wasm.peekPtr(aVals + wasm.ptrSizeof))
                  === 2 * +wasm.cstrToJs(wasm.peekPtr(aVals)));
        return 0;
      });
      try {
        T.assert(wasm.isPtr(pCb));
        rc = capi.sqlite3_exec(
          db, new TextEncoder('utf-8').encode("select a, a*2 from foo.bar"),
          pCb, 0, 0
        );
        T.assert(0===rc)
          .assert(3===rowCount)
          .assert(2===colCount);
      }finally{
        wasm.uninstallFunction(pCb);
      }

      // Demonstrate that an OOM result does not propagate through sqlite3_exec()...
      rc = capi.sqlite3_exec(
        db, ["select a,"," a*2 from foo.bar"], (aVals, aNames)=>{
          sqlite3.WasmAllocError.toss("just testing");
        }, 0, 0
      );
      T.assert(capi.SQLITE_ABORT === rc);

      db.exec("detach foo");
      T.mustThrow(()=>db.exec("select * from foo.bar"),
                  "Because foo is no longer attached.");
    })

  ////////////////////////////////////////////////////////////////////
    .t({
      name: 'C-side WASM tests',
      predicate: ()=>(haveWasmCTests() || "Not compiled in."),
      test: function(){
        const w = wasm, db = this.db;
        const stack = w.scopedAllocPush();
        let ptrInt;
        const origValue = 512;
        try{
          ptrInt = w.scopedAlloc(4);
          w.poke32(ptrInt,origValue);
          const cf = w.xGet('sqlite3_wasm_test_intptr');
          const oldPtrInt = ptrInt;
          T.assert(origValue === w.peek32(ptrInt));
          const rc = cf(ptrInt);
          T.assert(2*origValue === rc).
            assert(rc === w.peek32(ptrInt)).
            assert(oldPtrInt === ptrInt);
          const pi64 = w.scopedAlloc(8)/*ptr to 64-bit integer*/;
          const o64 = 0x010203040506/*>32-bit integer*/;
          if(w.bigIntEnabled){
            w.poke64(pi64, o64);
            //log("pi64 =",pi64, "o64 = 0x",o64.toString(16), o64);
            const v64 = ()=>w.peek64(pi64)
            T.assert(v64() == o64);
            //T.assert(o64 === w.peek64(pi64));
            const cf64w = w.xGet('sqlite3_wasm_test_int64ptr');
            cf64w(pi64);
            T.assert(v64() == BigInt(2 * o64));
            cf64w(pi64);
            T.assert(v64() == BigInt(4 * o64));

            const biTimes2 = w.xGet('sqlite3_wasm_test_int64_times2');
            T.assert(BigInt(2 * o64) ===
                     biTimes2(BigInt(o64)/*explicit conv. required to avoid TypeError
                                           in the call :/ */));

            const pMin = w.scopedAlloc(16);
            const pMax = pMin + 8;
            const g64 = (p)=>w.peek64(p);
            w.poke64([pMin, pMax], 0);
            const minMaxI64 = [
              w.xCall('sqlite3_wasm_test_int64_min'),
              w.xCall('sqlite3_wasm_test_int64_max')
            ];
            T.assert(minMaxI64[0] < BigInt(Number.MIN_SAFE_INTEGER)).
              assert(minMaxI64[1] > BigInt(Number.MAX_SAFE_INTEGER));
            //log("int64_min/max() =",minMaxI64, typeof minMaxI64[0]);
            w.xCall('sqlite3_wasm_test_int64_minmax', pMin, pMax);
            T.assert(g64(pMin) === minMaxI64[0], "int64 mismatch").
              assert(g64(pMax) === minMaxI64[1], "int64 mismatch");
            //log("pMin",g64(pMin), "pMax",g64(pMax));
            w.poke64(pMin, minMaxI64[0]);
            T.assert(g64(pMin) === minMaxI64[0]).
              assert(minMaxI64[0] === db.selectValue("select ?",g64(pMin))).
              assert(minMaxI64[1] === db.selectValue("select ?",g64(pMax)));
            const rxRange = /too big/;
            T.mustThrowMatching(()=>{db.prepare("select ?").bind(minMaxI64[0] - BigInt(1))},
                                rxRange).
              mustThrowMatching(()=>{db.prepare("select ?").bind(minMaxI64[1] + BigInt(1))},
                                (e)=>rxRange.test(e.message));
          }else{
            log("No BigInt support. Skipping related tests.");
            log("\"The problem\" here is that we can manipulate, at the byte level,",
                "heap memory to set 64-bit values, but we can't get those values",
                "back into JS because of the lack of 64-bit integer support.");
          }
        }finally{
          const x = w.scopedAlloc(1), y = w.scopedAlloc(1), z = w.scopedAlloc(1);
          //log("x=",x,"y=",y,"z=",z); // just looking at the alignment
          w.scopedAllocPop(stack);
        }
      }
    }/* jaccwabyt-specific tests */)

  ////////////////////////////////////////////////////////////////////////
    .t({
      name: 'virtual table #1: eponymous w/ manual exception handling',
      predicate: ()=>!!capi.sqlite3_index_info,
      test: function(sqlite3){
        const VT = sqlite3.vtab;
        const tmplCols = Object.assign(Object.create(null),{
          A: 0, B: 1
        });
        /**
           The vtab demonstrated here is a JS-ification of
           ext/misc/templatevtab.c.
        */
        const tmplMod = new sqlite3.capi.sqlite3_module();
        T.assert(0===tmplMod.$xUpdate);
        tmplMod.setupModule({
          catchExceptions: false,
          methods: {
            xConnect: function(pDb, pAux, argc, argv, ppVtab, pzErr){
              try{
                const args = wasm.cArgvToJs(argc, argv);
                T.assert(args.length>=3)
                  .assert(args[0] === 'testvtab')
                  .assert(args[1] === 'main')
                  .assert(args[2] === 'testvtab');
                //console.debug("xConnect() args =",args);
                const rc = capi.sqlite3_declare_vtab(
                  pDb, "CREATE TABLE ignored(a,b)"
                );
                if(0===rc){
                  const t = VT.xVtab.create(ppVtab);
                  T.assert(t === VT.xVtab.get(wasm.peekPtr(ppVtab)));
                }
                return rc;
              }catch(e){
                if(!(e instanceof sqlite3.WasmAllocError)){
                  wasm.dealloc(wasm.peekPtr, pzErr);
                  wasm.pokePtr(pzErr, wasm.allocCString(e.message));
                }
                return VT.xError('xConnect',e);
              }
            },
            xCreate: true /* just for testing. Will be removed afterwards. */,
            xDisconnect: function(pVtab){
              try {
                VT.xVtab.unget(pVtab).dispose();
                return 0;
              }catch(e){
                return VT.xError('xDisconnect',e);
              }
            },
            xOpen: function(pVtab, ppCursor){
              try{
                const t = VT.xVtab.get(pVtab),
                      c = VT.xCursor.create(ppCursor);
                T.assert(t instanceof capi.sqlite3_vtab)
                  .assert(c instanceof capi.sqlite3_vtab_cursor);
                c._rowId = 0;
                return 0;
              }catch(e){
                return VT.xError('xOpen',e);
              }
            },
            xClose: function(pCursor){
              try{
                const c = VT.xCursor.unget(pCursor);
                T.assert(c instanceof capi.sqlite3_vtab_cursor)
                  .assert(!VT.xCursor.get(pCursor));
                c.dispose();
                return 0;
              }catch(e){
                return VT.xError('xClose',e);
              }
            },
            xNext: function(pCursor){
              try{
                const c = VT.xCursor.get(pCursor);
                ++c._rowId;
                return 0;
              }catch(e){
                return VT.xError('xNext',e);
              }
            },
            xColumn: function(pCursor, pCtx, iCol){
              try{
                const c = VT.xCursor.get(pCursor);
                switch(iCol){
                    case tmplCols.A:
                      capi.sqlite3_result_int(pCtx, 1000 + c._rowId);
                      break;
                    case tmplCols.B:
                      capi.sqlite3_result_int(pCtx, 2000 + c._rowId);
                      break;
                    default: sqlite3.SQLite3Error.toss("Invalid column id",iCol);
                }
                return 0;
              }catch(e){
                return VT.xError('xColumn',e);
              }
            },
            xRowid: function(pCursor, ppRowid64){
              try{
                const c = VT.xCursor.get(pCursor);
                VT.xRowid(ppRowid64, c._rowId);
                return 0;
              }catch(e){
                return VT.xError('xRowid',e);
              }
            },
            xEof: function(pCursor){
              const c = VT.xCursor.get(pCursor),
                    rc = c._rowId>=10;
              return rc;
            },
            xFilter: function(pCursor, idxNum, idxCStr,
                              argc, argv/* [sqlite3_value* ...] */){
              try{
                const c = VT.xCursor.get(pCursor);
                c._rowId = 0;
                const list = capi.sqlite3_values_to_js(argc, argv);
                T.assert(argc === list.length);
                //log(argc,"xFilter value(s):",list);
                return 0;
              }catch(e){
                return VT.xError('xFilter',e);
              }
            },
            xBestIndex: function(pVtab, pIdxInfo){
              try{
                //const t = VT.xVtab.get(pVtab);
                const sii = capi.sqlite3_index_info;
                const pii = new sii(pIdxInfo);
                pii.$estimatedRows = 10;
                pii.$estimatedCost = 10.0;
                //log("xBestIndex $nConstraint =",pii.$nConstraint);
                if(pii.$nConstraint>0){
                  // Validate nthConstraint() and nthConstraintUsage()
                  const max = pii.$nConstraint;
                  for(let i=0; i < max; ++i ){
                    let v = pii.nthConstraint(i,true);
                    T.assert(wasm.isPtr(v));
                    v = pii.nthConstraint(i);
                    T.assert(v instanceof sii.sqlite3_index_constraint)
                      .assert(v.pointer >= pii.$aConstraint);
                    v.dispose();
                    v = pii.nthConstraintUsage(i,true);
                    T.assert(wasm.isPtr(v));
                    v = pii.nthConstraintUsage(i);
                    T.assert(v instanceof sii.sqlite3_index_constraint_usage)
                      .assert(v.pointer >= pii.$aConstraintUsage);
                    v.$argvIndex = i;//just to get some values into xFilter
                    v.dispose();
                  }
                }
                //log("xBestIndex $nOrderBy =",pii.$nOrderBy);
                if(pii.$nOrderBy>0){
                  // Validate nthOrderBy()
                  const max = pii.$nOrderBy;
                  for(let i=0; i < max; ++i ){
                    let v = pii.nthOrderBy(i,true);
                    T.assert(wasm.isPtr(v));
                    v = pii.nthOrderBy(i);
                    T.assert(v instanceof sii.sqlite3_index_orderby)
                      .assert(v.pointer >= pii.$aOrderBy);
                    v.dispose();
                  }
                }
                pii.dispose();
                return 0;
              }catch(e){
                return VT.xError('xBestIndex',e);
              }
            }
          }
        });
        this.db.onclose.disposeAfter.push(tmplMod);
        T.assert(0===tmplMod.$xUpdate)
          .assert(tmplMod.$xCreate)
          .assert(tmplMod.$xCreate === tmplMod.$xConnect,
                  "setup() must make these equivalent and "+
                  "installMethods() must avoid re-compiling identical functions");
        tmplMod.$xCreate = 0 /* make tmplMod eponymous-only */;
        let rc = capi.sqlite3_create_module(
          this.db, "testvtab", tmplMod, 0
        );
        this.db.checkRc(rc);
        const list = this.db.selectArrays(
          "SELECT a,b FROM testvtab where a<9999 and b>1 order by a, b"
          /* Query is shaped so that it will ensure that some constraints
             end up in xBestIndex(). */
        );
        T.assert(10===list.length)
          .assert(1000===list[0][0])
          .assert(2009===list[list.length-1][1]);
      }
    })/*custom vtab #1*/

  ////////////////////////////////////////////////////////////////////////
    .t({
      name: 'virtual table #2: non-eponymous w/ automated exception wrapping',
      predicate: ()=>!!capi.sqlite3_index_info,
      test: function(sqlite3){
        const VT = sqlite3.vtab;
        const tmplCols = Object.assign(Object.create(null),{
          A: 0, B: 1
        });
        /**
           The vtab demonstrated here is a JS-ification of
           ext/misc/templatevtab.c.
        */
        let throwOnCreate = 1 ? 0 : capi.SQLITE_CANTOPEN
        /* ^^^ just for testing exception wrapping. Note that sqlite
           always translates errors from a vtable to a generic
           SQLITE_ERROR unless it's from xConnect()/xCreate() and that
           callback sets an error string. */;
        const vtabTrace = 1
              ? ()=>{}
              : (methodName,...args)=>console.debug('sqlite3_module::'+methodName+'():',...args);
        const modConfig = {
          /* catchExceptions changes how the methods are wrapped */
          catchExceptions: true,
          name: "vtab2test",
          methods:{
            xCreate: function(pDb, pAux, argc, argv, ppVtab, pzErr){
              vtabTrace("xCreate",...arguments);
              if(throwOnCreate){
                sqlite3.SQLite3Error.toss(
                  throwOnCreate,
                  "Throwing a test exception."
                );
              }
              const args = wasm.cArgvToJs(argc, argv);
              vtabTrace("xCreate","argv:",args);
              T.assert(args.length>=3);
              const rc = capi.sqlite3_declare_vtab(
                pDb, "CREATE TABLE ignored(a,b)"
              );
              if(0===rc){
                const t = VT.xVtab.create(ppVtab);
                T.assert(t === VT.xVtab.get(wasm.peekPtr(ppVtab)));
                vtabTrace("xCreate",...arguments," ppVtab =",t.pointer);
              }
              return rc;
            },
            xConnect: true,
            xDestroy: function(pVtab){
              vtabTrace("xDestroy/xDisconnect",pVtab);
              VT.xVtab.dispose(pVtab);
            },
            xDisconnect: true,
            xOpen: function(pVtab, ppCursor){
              const t = VT.xVtab.get(pVtab),
                    c = VT.xCursor.create(ppCursor);
              T.assert(t instanceof capi.sqlite3_vtab)
                .assert(c instanceof capi.sqlite3_vtab_cursor);
              vtabTrace("xOpen",...arguments," cursor =",c.pointer);
              c._rowId = 0;
            },
            xClose: function(pCursor){
              vtabTrace("xClose",...arguments);
              const c = VT.xCursor.unget(pCursor);
              T.assert(c instanceof capi.sqlite3_vtab_cursor)
                .assert(!VT.xCursor.get(pCursor));
              c.dispose();
            },
            xNext: function(pCursor){
              vtabTrace("xNext",...arguments);
              const c = VT.xCursor.get(pCursor);
              ++c._rowId;
            },
            xColumn: function(pCursor, pCtx, iCol){
              vtabTrace("xColumn",...arguments);
              const c = VT.xCursor.get(pCursor);
              switch(iCol){
                  case tmplCols.A:
                    capi.sqlite3_result_int(pCtx, 1000 + c._rowId);
                    break;
                  case tmplCols.B:
                    capi.sqlite3_result_int(pCtx, 2000 + c._rowId);
                    break;
                  default: sqlite3.SQLite3Error.toss("Invalid column id",iCol);
              }
            },
            xRowid: function(pCursor, ppRowid64){
              vtabTrace("xRowid",...arguments);
              const c = VT.xCursor.get(pCursor);
              VT.xRowid(ppRowid64, c._rowId);
            },
            xEof: function(pCursor){
              vtabTrace("xEof",...arguments);
              return VT.xCursor.get(pCursor)._rowId>=10;
            },
            xFilter: function(pCursor, idxNum, idxCStr,
                              argc, argv/* [sqlite3_value* ...] */){
              vtabTrace("xFilter",...arguments);
              const c = VT.xCursor.get(pCursor);
              c._rowId = 0;
              const list = capi.sqlite3_values_to_js(argc, argv);
              T.assert(argc === list.length);
            },
            xBestIndex: function(pVtab, pIdxInfo){
              vtabTrace("xBestIndex",...arguments);
              //const t = VT.xVtab.get(pVtab);
              const pii = VT.xIndexInfo(pIdxInfo);
              pii.$estimatedRows = 10;
              pii.$estimatedCost = 10.0;
              pii.dispose();
            }
          }/*methods*/
        };
        const tmplMod = VT.setupModule(modConfig);
        T.assert(1===tmplMod.$iVersion);
        this.db.onclose.disposeAfter.push(tmplMod);
        this.db.checkRc(capi.sqlite3_create_module(
          this.db.pointer, modConfig.name, tmplMod.pointer, 0
        ));
        this.db.exec([
          "create virtual table testvtab2 using ",
          modConfig.name,
          "(arg1 blah, arg2 bloop)"
        ]);
        if(0){
          /* If we DROP TABLE then xDestroy() is called. If the
             vtab is instead destroyed when the db is closed,
             xDisconnect() is called. */
          this.db.onclose.disposeBefore.push(function(db){
            console.debug("Explicitly dropping testvtab2 via disposeBefore handler...");
            db.exec(
              /** DROP TABLE is the only way to get xDestroy() to be called. */
              "DROP TABLE testvtab2"
            );
          });
        }
        let list = this.db.selectArrays(
          "SELECT a,b FROM testvtab2 where a<9999 and b>1 order by a, b"
          /* Query is shaped so that it will ensure that some
             constraints end up in xBestIndex(). */
        );
        T.assert(10===list.length)
          .assert(1000===list[0][0])
          .assert(2009===list[list.length-1][1]);

        list = this.db.selectArrays(
          "SELECT a,b FROM testvtab2 where a<9999 and b>1 order by b, a limit 5"
        );
        T.assert(5===list.length)
          .assert(1000===list[0][0])
          .assert(2004===list[list.length-1][1]);

        // Call it as a table-valued function...
        list = this.db.selectArrays([
          "SELECT a,b FROM ", modConfig.name,
          " where a<9999 and b>1 order by b, a limit 1"
        ]);
        T.assert(1===list.length)
          .assert(1000===list[0][0])
          .assert(2000===list[0][1]);
      }
    })/*custom vtab #2*/
  ////////////////////////////////////////////////////////////////////////
    .t('Custom collation', function(sqlite3){
      let collationCounter = 0;
      let myCmp = function(pArg,n1,p1,n2,p2){
        //int (*)(void*,int,const void*,int,const void*)
        ++collationCounter;
        const rc = wasm.exports.sqlite3_strnicmp(p1,p2,(n1<n2?n1:n2));
        return rc ? rc : (n1 - n2);
      };
      let rc = capi.sqlite3_create_collation_v2(this.db, "mycollation", capi.SQLITE_UTF8,
                                                0, myCmp, 0);
      this.db.checkRc(rc);
      rc = this.db.selectValue("select 'hi' = 'HI' collate mycollation");
      T.assert(1===rc).assert(1===collationCounter);
      rc = this.db.selectValue("select 'hii' = 'HI' collate mycollation");
      T.assert(0===rc).assert(2===collationCounter);
      rc = this.db.selectValue("select 'hi' = 'HIi' collate mycollation");
      T.assert(0===rc).assert(3===collationCounter);
      rc = capi.sqlite3_create_collation(this.db,"hi",capi.SQLITE_UTF8/*not enough args*/);
      T.assert(capi.SQLITE_MISUSE === rc);
      rc = capi.sqlite3_create_collation_v2(this.db,"hi",capi.SQLITE_UTF8+1/*invalid encoding*/,0,0,0);
      T.assert(capi.SQLITE_FORMAT === rc)
        .mustThrowMatching(()=>this.db.checkRc(rc),
                           /SQLITE_UTF8 is the only supported encoding./);
      /*
        We need to ensure that replacing that collation function does
        the right thing. We don't have a handle to the underlying WASM
        pointer from here, so cannot verify (without digging through
        internal state) that the old one gets uninstalled, but we can
        verify that a new one properly replaces it.  (That said,
        console.warn() output has shown that the uninstallation does
        happen.)
      */
      collationCounter = 0;
      myCmp = function(pArg,n1,p1,n2,p2){
        --collationCounter;
        return 0;
      };
      rc = capi.sqlite3_create_collation_v2(this.db, "MYCOLLATION", capi.SQLITE_UTF8,
                                            0, myCmp, 0);
      this.db.checkRc(rc);
      rc = this.db.selectValue("select 'hi' = 'HI' collate mycollation");
      T.assert(rc>0).assert(-1===collationCounter);
      rc = this.db.selectValue("select 'a' = 'b' collate mycollation");
      T.assert(rc>0).assert(-2===collationCounter);
      rc = capi.sqlite3_create_collation_v2(this.db, "MYCOLLATION", capi.SQLITE_UTF8,
                                            0, null, 0);
      this.db.checkRc(rc);
      rc = 0;
      try {
        this.db.selectValue("select 'a' = 'b' collate mycollation");
      }catch(e){
        /* Why is e.resultCode not automatically an extended result
           code? The DB() class enables those automatically. */
        rc = sqlite3.capi.sqlite3_extended_errcode(this.db);
      }
      T.assert(capi.SQLITE_ERROR_MISSING_COLLSEQ === rc);
    })/*custom collation*/

  ////////////////////////////////////////////////////////////////////////
    .t('Close db', function(){
      T.assert(this.db).assert(wasm.isPtr(this.db.pointer));
      //wasm.sqlite3_wasm_db_reset(this.db); // will leak virtual tables!
      this.db.close();
      T.assert(!this.db.pointer);
    })
  ;/* end of oo1 checks */

  ////////////////////////////////////////////////////////////////////////
  T.g('kvvfs')
    .t({
      name: 'kvvfs is disabled in worker',
      predicate: ()=>(isWorker() || "test is only valid in a Worker"),
      test: function(sqlite3){
        T.assert(
          !capi.sqlite3_vfs_find('kvvfs'),
          "Expecting kvvfs to be unregistered."
        );
      }
    })
    .t({
      name: 'kvvfs in main thread',
      predicate: ()=>(isUIThread()
                      || "local/sessionStorage are unavailable in a Worker"),
      test: function(sqlite3){
        const filename = this.kvvfsDbFile = 'session';
        const pVfs = capi.sqlite3_vfs_find('kvvfs');
        T.assert(pVfs);
        const JDb = this.JDb = sqlite3.oo1.JsStorageDb;
        const unlink = this.kvvfsUnlink = ()=>{JDb.clearStorage(filename)};
        unlink();
        let db = new JDb(filename);
        try {
          db.exec([
            'create table kvvfs(a);',
            'insert into kvvfs(a) values(1),(2),(3)'
          ]);
          T.assert(3 === db.selectValue('select count(*) from kvvfs'));
          db.close();
          db = new JDb(filename);
          db.exec('insert into kvvfs(a) values(4),(5),(6)');
          T.assert(6 === db.selectValue('select count(*) from kvvfs'));
        }finally{
          db.close();
        }
      }
    }/*kvvfs sanity checks*/)
    .t({
      name: 'kvvfs sqlite3_js_vfs_create_file()',
      predicate: ()=>"kvvfs does not currently support this",
      test: function(sqlite3){
        let db;
        try {
          db = new this.JDb(this.kvvfsDbFile);
          const exp = capi.sqlite3_js_db_export(db);
          db.close();
          this.kvvfsUnlink();
          capi.sqlite3_js_vfs_create_file("kvvfs", this.kvvfsDbFile, exp);
          db = new this.JDb(filename);
          T.assert(6 === db.selectValue('select count(*) from kvvfs'));
        }finally{
          db.close();
          this.kvvfsUnlink();
        }
        delete this.kvvfsDbFile;
        delete this.kvvfsUnlink;
        delete this.JDb;
      }
   }/*kvvfs sqlite3_js_vfs_create_file()*/)
  ;/* end kvvfs tests */

  ////////////////////////////////////////////////////////////////////////
  T.g('OPFS: Origin-Private File System',
      (sqlite3)=>(sqlite3.opfs
                  ? true : "requires Worker thread in a compatible browser"))
    .t({
      name: 'OPFS db sanity checks',
      test: async function(sqlite3){
        const filename = this.opfsDbFile = 'sqlite3-tester1.db';
        const pVfs = this.opfsVfs = capi.sqlite3_vfs_find('opfs');
        T.assert(pVfs);
        const unlink = this.opfsUnlink =
              (fn=filename)=>{wasm.sqlite3_wasm_vfs_unlink(pVfs,fn)};
        unlink();
        let db = new sqlite3.oo1.OpfsDb(filename);
        try {
          db.exec([
            'create table p(a);',
            'insert into p(a) values(1),(2),(3)'
          ]);
          T.assert(3 === db.selectValue('select count(*) from p'));
          db.close();
          db = new sqlite3.oo1.OpfsDb(filename);
          db.exec('insert into p(a) values(4),(5),(6)');
          T.assert(6 === db.selectValue('select count(*) from p'));
          this.opfsDbExport = capi.sqlite3_js_db_export(db);
          T.assert(this.opfsDbExport instanceof Uint8Array)
            .assert(this.opfsDbExport.byteLength>0
                    && 0===this.opfsDbExport.byteLength % 512);
        }finally{
          db.close();
          unlink();
        }
      }
    }/*OPFS db sanity checks*/)
    .t({
      name: 'OPFS export/import',
      test: async function(sqlite3){
        let db;
        try {
          const exp = this.opfsDbExport;
          delete this.opfsDbExport;
          capi.sqlite3_js_vfs_create_file("opfs", this.opfsDbFile, exp);
          const db = new sqlite3.oo1.OpfsDb(this.opfsDbFile);
          T.assert(6 === db.selectValue('select count(*) from p'));
        }finally{
          if(db) db.close();
        }
      }
    }/*OPFS export/import*/)
    .t({
      name: 'OPFS utility APIs and sqlite3_js_vfs_create_file()',
      test: async function(sqlite3){
        const filename = this.opfsDbFile;
        const pVfs = this.opfsVfs;
        const unlink = this.opfsUnlink;
        T.assert(filename && pVfs && !!unlink);
        delete this.opfsDbFile;
        delete this.opfsVfs;
        delete this.opfsUnlink;
        unlink();
        // Sanity-test sqlite3_js_vfs_create_file()...
        /**************************************************************
           ATTENTION CLIENT-SIDE USERS: sqlite3.opfs is NOT intended
           for client-side use. It is only for this project's own
           internal use. Its APIs are subject to change or removal at
           any time.
        ***************************************************************/
        const opfs = sqlite3.opfs;
        const fSize = 1379;
        let sh;
        try{
          T.assert(!(await opfs.entryExists(filename)));
          capi.sqlite3_js_vfs_create_file(
            pVfs, filename, null, fSize
          );
          T.assert(await opfs.entryExists(filename));
          let fh = await opfs.rootDirectory.getFileHandle(filename);
          sh = await fh.createSyncAccessHandle();
          T.assert(fSize === await sh.getSize());
          await sh.close();
          sh = undefined;
          unlink();
          T.assert(!(await opfs.entryExists(filename)));

          const ba = new Uint8Array([1,2,3,4,5]);
          capi.sqlite3_js_vfs_create_file(
            "opfs", filename, ba
          );
          T.assert(await opfs.entryExists(filename));
          fh = await opfs.rootDirectory.getFileHandle(filename);
          sh = await fh.createSyncAccessHandle();
          T.assert(ba.byteLength === await sh.getSize());
          await sh.close();
          sh = undefined;
          unlink();

          T.mustThrowMatching(()=>{
            capi.sqlite3_js_vfs_create_file(
              "no-such-vfs", filename, ba
            );
          }, "SQLITE_NOTFOUND: Unknown sqlite3_vfs name: no-such-vfs");
        }finally{
          if(sh) await sh.close();
          unlink();
        }

        // Some sanity checks of the opfs utility functions...
        const testDir = '/sqlite3-opfs-'+opfs.randomFilename(12);
        const aDir = testDir+'/test/dir';
        T.assert(await opfs.mkdir(aDir), "mkdir failed")
          .assert(await opfs.mkdir(aDir), "mkdir must pass if the dir exists")
          .assert(!(await opfs.unlink(testDir+'/test')), "delete 1 should have failed (dir not empty)")
          .assert((await opfs.unlink(testDir+'/test/dir')), "delete 2 failed")
          .assert(!(await opfs.unlink(testDir+'/test/dir')),
                  "delete 2b should have failed (dir already deleted)")
          .assert((await opfs.unlink(testDir, true)), "delete 3 failed")
          .assert(!(await opfs.entryExists(testDir)),
                  "entryExists(",testDir,") should have failed");
      }
    }/*OPFS util sanity checks*/)
  ;/* end OPFS tests */

  ////////////////////////////////////////////////////////////////////////
  T.g('Hook APIs')
    .t({
      name: "sqlite3_commit/rollback/update_hook()",
      predicate: ()=>wasm.bigIntEnabled || "Update hook requires int64",
      test: function(sqlite3){
        let countCommit = 0, countRollback = 0;;
        const db = new sqlite3.oo1.DB(':memory:',1 ? 'c' : 'ct');
        let rc = capi.sqlite3_commit_hook(db, (p)=>{
          ++countCommit;
          return (1 === p) ? 0 : capi.SQLITE_ERROR;
        }, 1);
        T.assert( 0 === rc /*void pointer*/ );

        // Commit hook...
        db.exec("BEGIN; SELECT 1; COMMIT");
        T.assert(0 === countCommit,
                 "No-op transactions (mostly) do not trigger commit hook.");
        db.exec("BEGIN EXCLUSIVE; SELECT 1; COMMIT");
        T.assert(1 === countCommit,
                 "But EXCLUSIVE transactions do.");
        db.transaction((d)=>{d.exec("create table t(a)");});
        T.assert(2 === countCommit);

        // Rollback hook:
        rc = capi.sqlite3_rollback_hook(db, (p)=>{
          ++countRollback;
          T.assert( 2 === p );
        }, 2);
        T.assert( 0 === rc /*void pointer*/ );
        T.mustThrowMatching(()=>{
          db.transaction('drop table t',()=>{})
        }, (e)=>{
          return (capi.SQLITE_MISUSE === e.resultCode)
            && ( e.message.indexOf('Invalid argument') > 0 );
        });
        T.assert(0 === countRollback, "Transaction was not started.");
        T.mustThrowMatching(()=>{
          db.transaction('immediate', ()=>{
            sqlite3.SQLite3Error.toss(capi.SQLITE_FULL,'testing rollback hook');
          });
        }, (e)=>{
          return capi.SQLITE_FULL === e.resultCode
        });
        T.assert(1 === countRollback);

        // Update hook...
        const countUpdate = Object.create(null);
        capi.sqlite3_update_hook(db, (p,op,dbName,tbl,rowid)=>{
          T.assert('main' === dbName.toLowerCase())
            .assert('t' === tbl.toLowerCase())
            .assert(3===p)
            .assert('bigint' === typeof rowid);
          switch(op){
              case capi.SQLITE_INSERT:
              case capi.SQLITE_UPDATE:
              case capi.SQLITE_DELETE:
                countUpdate[op] = (countUpdate[op]||0) + 1;
                break;
              default: toss("Unexpected hook operator:",op);
          }
        }, 3);
        db.transaction((d)=>{
          d.exec([
            "insert into t(a) values(1);",
            "update t set a=2;",
            "update t set a=3;",
            "delete from t where a=3"
            // update hook is not called for an unqualified DELETE
          ]);
        });
        T.assert(1 === countRollback)
          .assert(3 === countCommit)
          .assert(1 === countUpdate[capi.SQLITE_INSERT])
          .assert(2 === countUpdate[capi.SQLITE_UPDATE])
          .assert(1 === countUpdate[capi.SQLITE_DELETE]);
        //wasm.xWrap.FuncPtrAdapter.debugFuncInstall = true;
        T.assert(1 === capi.sqlite3_commit_hook(db, 0, 0));
        T.assert(2 === capi.sqlite3_rollback_hook(db, 0, 0));
        T.assert(3 === capi.sqlite3_update_hook(db, 0, 0));
        //wasm.xWrap.FuncPtrAdapter.debugFuncInstall = false;
        db.close();
      }
    })/* commit/rollback/update hooks */
    .t({
      name: "sqlite3_preupdate_hook()",
      predicate: ()=>wasm.bigIntEnabled || "Pre-update hook requires int64",
      test: function(sqlite3){
        const db = new sqlite3.oo1.DB(':memory:', 1 ? 'c' : 'ct');
        const countHook = Object.create(null);
        let rc = capi.sqlite3_preupdate_hook(
          db, function(p, pDb, op, zDb, zTbl, iKey1, iKey2){
            T.assert(9 === p)
              .assert(db.pointer === pDb)
              .assert(1 === capi.sqlite3_preupdate_count(pDb))
              .assert( 0 > capi.sqlite3_preupdate_blobwrite(pDb) );
            countHook[op] = (countHook[op]||0) + 1;
            switch(op){
                case capi.SQLITE_INSERT:
                case capi.SQLITE_UPDATE:
                 T.assert('number' === typeof capi.sqlite3_preupdate_new_js(pDb, 0));
                  break;
                case capi.SQLITE_DELETE:
                 T.assert('number' === typeof capi.sqlite3_preupdate_old_js(pDb, 0));
                  break;
                default: toss("Unexpected hook operator:",op);
            }
          },
          9
        );
        db.transaction((d)=>{
          d.exec([
            "create table t(a);",
            "insert into t(a) values(1);",
            "update t set a=2;",
            "update t set a=3;",
            "delete from t where a=3"
          ]);
        });
        T.assert(1 === countHook[capi.SQLITE_INSERT])
          .assert(2 === countHook[capi.SQLITE_UPDATE])
          .assert(1 === countHook[capi.SQLITE_DELETE]);
        //wasm.xWrap.FuncPtrAdapter.debugFuncInstall = true;
        db.close();
        //wasm.xWrap.FuncPtrAdapter.debugFuncInstall = false;
      }
    })/*pre-update hooks*/
  ;/*end hook API tests*/

  ////////////////////////////////////////////////////////////////////////
  T.g('Auto-extension API')
    .t({
      name: "Auto-extension sanity checks.",
      test: function(sqlite3){
        let counter = 0;
        const fp = wasm.installFunction('i(ppp)', function(pDb,pzErr,pApi){
          ++counter;
          return 0;
        });
        (new sqlite3.oo1.DB()).close();
        T.assert( 0===counter );
        capi.sqlite3_auto_extension(fp);
        (new sqlite3.oo1.DB()).close();
        T.assert( 1===counter );
        (new sqlite3.oo1.DB()).close();
        T.assert( 2===counter );
        capi.sqlite3_cancel_auto_extension(fp);
        wasm.uninstallFunction(fp);
        (new sqlite3.oo1.DB()).close();
        T.assert( 2===counter );
      }
    });

  ////////////////////////////////////////////////////////////////////////
  T.g('Session API')
    .t({
      name: 'Session API sanity checks',
      predicate: ()=>!!capi.sqlite3changegroup_add,
      test: function(sqlite3){
        warn("The session API tests could use some expansion.");
        const db1 = new sqlite3.oo1.DB(), db2 = new sqlite3.oo1.DB();
        const sqlInit = [
          "create table t(rowid INTEGER PRIMARY KEY,a,b); ",
          "insert into t(rowid,a,b) values",
          "(1,'a1','b1'),",
          "(2,'a2','b2'),",
          "(3,'a3','b3');"
        ].join('');
        db1.exec(sqlInit);
        db2.exec(sqlInit);
        T.assert(3 === db1.selectValue("select count(*) from t"))
          .assert('b3' === db1.selectValue('select b from t where rowid=3'));
        const stackPtr = wasm.pstack.pointer;
        try{
          let ppOut = wasm.pstack.allocPtr();
          let rc = capi.sqlite3session_create(db1, "main", ppOut);
          T.assert(0===rc);
          let pSession = wasm.peekPtr(ppOut);
          T.assert(pSession && wasm.isPtr(pSession));
          capi.sqlite3session_table_filter(pSession, (pCtx, tbl)=>{
            T.assert('t' === tbl).assert( 99 === pCtx );
            return 1;
          }, 99);
          db1.exec([
            "update t set b='bTwo' where rowid=2;",
            "update t set a='aThree' where rowid=3;",
            "delete from t where rowid=1;",
            "insert into t(rowid,a,b) values(4,'a4','b4')"
          ]);
          T.assert('bTwo' === db1.selectValue("select b from t where rowid=2"))
            .assert(undefined === db1.selectValue('select a from t where rowid=1'))
            .assert('b4' === db1.selectValue('select b from t where rowid=4'))
            .assert(3 === db1.selectValue('select count(*) from t'));

          const testSessionEnable = false;
          if(testSessionEnable){
            rc = capi.sqlite3session_enable(pSession, 0);
            T.assert( 0 === rc )
              .assert( 0 === capi.sqlite3session_enable(pSession, -1) );
            db1.exec("delete from t where rowid=2;");
            rc = capi.sqlite3session_enable(pSession, 1);
            T.assert( rc > 0 )
              .assert( capi.sqlite3session_enable(pSession, -1) > 0 )
              .assert(undefined === db1.selectValue('select a from t where rowid=2'));
          }else{
            warn("sqlite3session_enable() tests disabled due to unexpected results.",
                 "(Possibly a tester misunderstanding, as opposed to a bug.)");
          }
          let db1Count = db1.selectValue("select count(*) from t");
          T.assert( db1Count === (testSessionEnable ? 2 : 3) );

          /* Capture changeset and destroy session. */
          let pnChanges = wasm.pstack.alloc('i32'),
              ppChanges = wasm.pstack.allocPtr();
          rc = capi.sqlite3session_changeset(pSession, pnChanges, ppChanges);
          T.assert( 0 === rc );
          capi.sqlite3session_delete(pSession);
          pSession = 0;
          const pChanges = wasm.peekPtr(ppChanges),
                nChanges = wasm.peek32(pnChanges);
          T.assert( pChanges && wasm.isPtr( pChanges ) )
            .assert( nChanges > 0 );

          /* Revert db1 via an inverted changeset, but keep pChanges
             and nChanges for application to db2. */
          rc = capi.sqlite3changeset_invert( nChanges, pChanges, pnChanges, ppChanges );
          T.assert( 0 === rc );
          rc = capi.sqlite3changeset_apply(
            db1, wasm.peek32(pnChanges), wasm.peekPtr(ppChanges), 0, (pCtx, eConflict, pIter)=>{
              return 1;
            }, 0
          );
          T.assert( 0 === rc );
          wasm.dealloc( wasm.peekPtr(ppChanges) );
          pnChanges = ppChanges = 0;
          T.assert('b2' === db1.selectValue("select b from t where rowid=2"))
            .assert('a1' === db1.selectValue('select a from t where rowid=1'))
            .assert(undefined === db1.selectValue('select b from t where rowid=4'));
          db1Count = db1.selectValue("select count(*) from t");
          T.assert(3 === db1Count);

          /* Apply pre-reverted changeset (pChanges, nChanges) to
             db2... */
          rc = capi.sqlite3changeset_apply(
            db2, nChanges, pChanges, 0, (pCtx, eConflict, pIter)=>{
              return pCtx ? 1 : 0
            }, 1
          );
          wasm.dealloc( pChanges );
          T.assert( 0 === rc )
            .assert( 'b4' === db2.selectValue('select b from t where rowid=4') )
            .assert( 'aThree' === db2.selectValue('select a from t where rowid=3') )
            .assert( undefined === db2.selectValue('select b from t where rowid=1') );
          if(testSessionEnable){
            T.assert( (undefined === db2.selectValue('select b from t where rowid=2')),
                      "But... the session was disabled when rowid=2 was deleted?" );
            log("rowids from db2.t:",db2.selectValues('select rowid from t order by rowid'));
            T.assert( 3 === db2.selectValue('select count(*) from t') );
          }else{
            T.assert( 'bTwo' === db2.selectValue('select b from t where rowid=2') )
              .assert( 3 === db2.selectValue('select count(*) from t') );
          }
        }finally{
          wasm.pstack.restore(stackPtr);
          db1.close();
          db2.close();
        }
      }
    })/*session API sanity tests*/
  ;/*end of session API group*/;

  ////////////////////////////////////////////////////////////////////////
  log("Loading and initializing sqlite3 WASM module...");
  if(!self.sqlite3InitModule && !isUIThread()){
    /* Vanilla worker, as opposed to an ES6 module worker */
    /*
      If sqlite3.js is in a directory other than this script, in order
      to get sqlite3.js to resolve sqlite3.wasm properly, we have to
      explicitly tell it where sqlite3.js is being loaded from. We do
      that by passing the `sqlite3.dir=theDirName` URL argument to
      _this_ script. That URL argument will be seen by the JS/WASM
      loader and it will adjust the sqlite3.wasm path accordingly. If
      sqlite3.js/.wasm are in the same directory as this script then
      that's not needed.

      URL arguments passed as part of the filename via importScripts()
      are simply lost, and such scripts see the self.location of
      _this_ script.
    */
    let sqlite3Js = 'sqlite3.js';
    const urlParams = new URL(self.location.href).searchParams;
    if(urlParams.has('sqlite3.dir')){
      sqlite3Js = urlParams.get('sqlite3.dir') + '/' + sqlite3Js;
    }
    importScripts(sqlite3Js);
  }
  self.sqlite3InitModule.__isUnderTest =
    true /* disables certain API-internal cleanup so that we can
            test internal APIs from here */;
  self.sqlite3InitModule({
    print: log,
    printErr: error
  }).then(function(sqlite3){
    //console.log('sqlite3 =',sqlite3);
    log("Done initializing WASM/JS bits. Running tests...");
    console.warn("Installing sqlite3 bits as global S for local dev/test purposes.");
    self.S = sqlite3;
    capi = sqlite3.capi;
    wasm = sqlite3.wasm;
    log("sqlite3 version:",capi.sqlite3_libversion(),
        capi.sqlite3_sourceid());
    if(wasm.bigIntEnabled){
      log("BigInt/int64 support is enabled.");
    }else{
      logClass('warning',"BigInt/int64 support is disabled.");
    }
    if(haveWasmCTests()){
      log("sqlite3_wasm_test_...() APIs are available.");
    }else{
      logClass('warning',"sqlite3_wasm_test_...() APIs unavailable.");
    }
    TestUtil.runTests(sqlite3);
  });
})(self);

Added ext/wasm/tests/opfs/concurrency/index.html.


















































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<!doctype html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
    <link rel="stylesheet" href="../../../common/testing.css"/>
    <title>sqlite3 OPFS Worker concurrency tester</title>
    <style>
      body { display: revert; }
      body > * {}
      #test-output {
          font-family: monospace;
      }
    </style>
  </head>
  <body>
    <h1></h1>
    <p>
      OPFS concurrency tester using multiple independent Workers.
      Disclaimer: concurrency in OPFS is currently a pain point!
    </p>
    <p>
      URL flags: pass a number of workers using
      the <code>workers=N</code> URL flag. Set the time between each
      workload with <code>interval=N</code> (milliseconds). Set the
      number of worker iterations with <code>iterations=N</code>.
      Enable OPFS VFS verbosity with <code>verbose=1-3</code> (output
      goes to the dev console). Disable/enable "unlock ASAP" mode
      (higher concurrency, lower speed) with <code>unlock-asap=0-1</code>.
    </p>
    <p>Achtung: if it does not start to do anything within a couple of
      seconds, check the dev console: Chrome sometimes fails to load
      the wasm module due to "cannot allocate WasmMemory." Closing and
      re-opening the tab usually resolves it, but sometimes restarting
      the browser is required.
    </p>
    <div class='input-wrapper'>
      <input type='checkbox' id='cb-log-reverse'>
      <label for='cb-log-reverse'>Reverse log order?</label>
    </div>
    <div id='test-output'></div>
    <script>(function(){
      document.querySelector('h1').innerHTML =
        document.querySelector('title').innerHTML;
    })();</script>
    <script src="test.js?sqlite3.dir=../../../jswasm"></script>
  </body>
</html>

Added ext/wasm/tests/opfs/concurrency/test.js.









































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
(async function(self){

  const logCss = (function(){
    const mapToString = (v)=>{
      switch(typeof v){
          case 'number': case 'string': case 'boolean':
          case 'undefined': case 'bigint':
            return ''+v;
          default: break;
      }
      if(null===v) return 'null';
      if(v instanceof Error){
        v = {
          message: v.message,
          stack: v.stack,
          errorClass: v.name
        };
      }
      return JSON.stringify(v,undefined,2);
    };
    const normalizeArgs = (args)=>args.map(mapToString);
    const logTarget = document.querySelector('#test-output');
    const logCss = function(cssClass,...args){
      const ln = document.createElement('div');
      if(cssClass){
        for(const c of (Array.isArray(cssClass) ? cssClass : [cssClass])){
          ln.classList.add(c);
        }
      }
      ln.append(document.createTextNode(normalizeArgs(args).join(' ')));
      logTarget.append(ln);
    };
    const cbReverse = document.querySelector('#cb-log-reverse');
    const cbReverseKey = 'tester1:cb-log-reverse';
    const cbReverseIt = ()=>{
      logTarget.classList[cbReverse.checked ? 'add' : 'remove']('reverse');
      localStorage.setItem(cbReverseKey, cbReverse.checked ? 1 : 0);
    };
    cbReverse.addEventListener('change', cbReverseIt, true);
    if(localStorage.getItem(cbReverseKey)){
      cbReverse.checked = !!(+localStorage.getItem(cbReverseKey));
    }
    cbReverseIt();
    return logCss;
  })();
  const stdout = (...args)=>logCss('',...args);
  const stderr = (...args)=>logCss('error',...args);

  const wait = async (ms)=>{
    return new Promise((resolve)=>setTimeout(resolve,ms));
  };

  const urlArgsJs = new URL(document.currentScript.src).searchParams;
  const urlArgsHtml = new URL(self.location.href).searchParams;
  const options = Object.create(null);
  options.sqlite3Dir = urlArgsJs.get('sqlite3.dir');
  options.workerCount = (
    urlArgsHtml.has('workers') ? +urlArgsHtml.get('workers') : 3
  ) || 4;
  options.opfsVerbose = (
    urlArgsHtml.has('verbose') ? +urlArgsHtml.get('verbose') : 1
  ) || 1;
  options.interval = (
    urlArgsHtml.has('interval') ? +urlArgsHtml.get('interval') : 1000
  ) || 1000;
  options.iterations = (
    urlArgsHtml.has('iterations') ? +urlArgsHtml.get('iterations') : 10
  ) || 10;
  options.unlockAsap = (
    urlArgsHtml.has('unlock-asap') ? +urlArgsHtml.get('unlock-asap') : 0
  ) || 0;
  options.noUnlink = !!urlArgsHtml.has('no-unlink');
  const workers = [];
  workers.post = (type,...args)=>{
    for(const w of workers) w.postMessage({type, payload:args});
  };
  workers.counts = {loaded: 0, passed: 0, failed: 0};
  const checkFinished = function(){
    if(workers.counts.passed + workers.counts.failed !== workers.length){
      return;
    }
    if(workers.counts.failed>0){
      logCss('tests-fail',"Finished with",workers.counts.failed,"failure(s).");
    }else{
      logCss('tests-pass',"All",workers.length,"workers finished.");
    }
  };
  workers.onmessage = function(msg){
    msg = msg.data;
    const prefix = 'Worker #'+msg.worker+':';
    switch(msg.type){
        case 'loaded':
          stdout(prefix,"loaded");
          if(++workers.counts.loaded === workers.length){
            stdout("All",workers.length,"workers loaded. Telling them to run...");
            workers.post('run');
          }
          break;
        case 'stdout': stdout(prefix,...msg.payload); break;
        case 'stderr': stderr(prefix,...msg.payload); break;
        case 'error': stderr(prefix,"ERROR:",...msg.payload); break;
        case 'finished':
          ++workers.counts.passed;
          logCss('tests-pass',prefix,...msg.payload);
          checkFinished();
          break;
        case 'failed':
          ++workers.counts.failed;
          logCss('tests-fail',prefix,"FAILED:",...msg.payload);
          checkFinished();
          break;
        default: logCss('error',"Unhandled message type:",msg); break;
    }
  };

  stdout("Launching",options.workerCount,"workers. Options:",options);
  workers.uri = (
    'worker.js?'
      + 'sqlite3.dir='+options.sqlite3Dir
      + '&interval='+options.interval
      + '&iterations='+options.iterations
      + '&opfs-verbose='+options.opfsVerbose
      + '&opfs-unlock-asap='+options.unlockAsap
  );
  for(let i = 0; i < options.workerCount; ++i){
    stdout("Launching worker...");
    workers.push(new Worker(
      workers.uri+'&workerId='+(i+1)+(
        (i || options.noUnlink) ? '' : '&unlink-db'
      )
    ));
  }
  // Have to delay onmessage assignment until after the loop
  // to avoid that early workers get an undue head start.
  workers.forEach((w)=>w.onmessage = workers.onmessage);
})(self);

Added ext/wasm/tests/opfs/concurrency/worker.js.


















































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
importScripts(
  (new URL(self.location.href).searchParams).get('sqlite3.dir') + '/sqlite3.js'
);
self.sqlite3InitModule().then(async function(sqlite3){
  const urlArgs = new URL(self.location.href).searchParams;
  const options = {
    workerName: urlArgs.get('workerId') || Math.round(Math.random()*10000),
    unlockAsap: urlArgs.get('opfs-unlock-asap') || 0 /*EXPERIMENTAL*/
  };
  const wPost = (type,...payload)=>{
    postMessage({type, worker: options.workerName, payload});
  };
  const stdout = (...args)=>wPost('stdout',...args);
  const stderr = (...args)=>wPost('stderr',...args);
  if(!sqlite3.opfs){
    stderr("OPFS support not detected. Aborting.");
    return;
  }

  const wait = async (ms)=>{
    return new Promise((resolve)=>setTimeout(resolve,ms));
  };

  const dbName = 'concurrency-tester.db';
  if(urlArgs.has('unlink-db')){
    await sqlite3.opfs.unlink(dbName);
    stdout("Unlinked",dbName);
  }
  wPost('loaded');
  let db;
  const interval = Object.assign(Object.create(null),{
    delay: urlArgs.has('interval') ? (+urlArgs.get('interval') || 750) : 750,
    handle: undefined,
    count: 0
  });
  const finish = ()=>{
    if(db){
      if(!db.pointer) return;
      db.close();
    }
    if(interval.error){
      wPost('failed',"Ending work after interval #"+interval.count,
            "due to error:",interval.error);
    }else{
      wPost('finished',"Ending work after",interval.count,"intervals.");
    }
  };
  const run = async function(){
    db = new sqlite3.oo1.OpfsDb({
      filename: 'file:'+dbName+'?opfs-unlock-asap='+options.unlockAsap,
      flags: 'c'
    });
    sqlite3.capi.sqlite3_busy_timeout(db.pointer, 5000);
    db.transaction((db)=>{
      db.exec([
        "create table if not exists t1(w TEXT UNIQUE ON CONFLICT REPLACE,v);",
        "create table if not exists t2(w TEXT UNIQUE ON CONFLICT REPLACE,v);"
      ]);
    });

    const maxIterations =
          urlArgs.has('iterations') ? (+urlArgs.get('iterations') || 10) : 10;
    stdout("Starting interval-based db updates with delay of",interval.delay,"ms.");
    const doWork = async ()=>{
      const tm = new Date().getTime();
      ++interval.count;
      const prefix = "v(#"+interval.count+")";
      stdout("Setting",prefix,"=",tm);
      try{
        db.exec({
          sql:"INSERT OR REPLACE INTO t1(w,v) VALUES(?,?)",
          bind: [options.workerName, new Date().getTime()]
        });
        //stdout("Set",prefix);
      }catch(e){
        interval.error = e;
      }
    };
    if(1){/*use setInterval()*/
      setTimeout(async function timer(){
        await doWork();
        if(interval.error || maxIterations === interval.count){
          finish();
        }else{
          setTimeout(timer, interval.delay);
        }
      }, interval.delay);
    }else{
      /*This approach provides no concurrency whatsoever: each worker
        is run to completion before any others can work.*/
      let i;
      for(i = 0; i < maxIterations; ++i){
        await doWork();
        if(interval.error) break;
        await wait(interval.ms);
      }
      finish();
    }
  }/*run()*/;

  self.onmessage = function({data}){
    switch(data.type){
        case 'run': run().catch((e)=>{
          if(!interval.error) interval.error = e;
          finish();
        });
          break;
        default:
          stderr("Unhandled message type '"+data.type+"'.");
          break;
    }
  };
});

Added ext/wasm/version-info.c.











































































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2022-10-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 simply outputs sqlite3 version information in JSON form,
** intended for embedding in the sqlite3 JS API build.
*/
#ifdef TEST_VERSION
/*3029003 3039012*/
#define SQLITE_VERSION "X.Y.Z"
#define SQLITE_VERSION_NUMBER TEST_VERSION
#define SQLITE_SOURCE_ID "dummy"
#else
#include "sqlite3.h"
#endif
#include <stdio.h>
#include <string.h>
static void usage(const char *zAppName){
  puts("Emits version info about the sqlite3 it is built against.");
  printf("Usage: %s [--quote] --INFO-FLAG:\n\n", zAppName);
  puts("  --version          Emit SQLITE_VERSION (3.X.Y)");
  puts("  --version-number   Emit SQLITE_VERSION_NUMBER (30XXYYZZ)");
  puts("  --download-version Emit /download.html version number (3XXYYZZ)");
  puts("  --source-id        Emit SQLITE_SOURCE_ID");
  puts("  --json             Emit all info in JSON form");
  puts("\nThe non-JSON formats may be modified by:\n");
  puts("  --quote            Add double quotes around output.");
}

int main(int argc, char const * const * argv){
  int fJson = 0;
  int fVersion = 0;
  int fVersionNumber = 0;
  int fDlVersion = 0;
  int dlVersion = 0;
  int fSourceInfo = 0;
  int fQuote = 0;
  int nFlags = 0;
  int i;

  for( i = 1; i < argc; ++i ){
    const char * zArg = argv[i];
    while('-'==*zArg) ++zArg;
    if( 0==strcmp("version", zArg) ){
      fVersion = 1;
    }else if( 0==strcmp("version-number", zArg) ){
      fVersionNumber = 1;
    }else if( 0==strcmp("download-version", zArg) ){
      fDlVersion = 1;
    }else if( 0==strcmp("source-id", zArg) ){
      fSourceInfo = 1;
    }else if( 0==strcmp("json", zArg) ){
      fJson = 1;
    }else if( 0==strcmp("quote", zArg) ){
      fQuote = 1;
      --nFlags;
    }else{
      printf("Unhandled flag: %s\n", argv[i]);
      usage(argv[0]);
      return 1;
    }
    ++nFlags;
  }

  if( 0==nFlags ) fJson = 1;

  {
    const int v = SQLITE_VERSION_NUMBER;
    int ver[4] = {0,0,0,0};
    ver[0] = (v / 1000000) * 1000000;
    ver[1] = v % 1000000 / 100 * 1000;
    ver[2] = v % 100 * 100;
    dlVersion = ver[0] + ver[1] + ver[2] + ver[3];
  }
  if( fJson ){
    printf("{\"libVersion\": \"%s\", "
           "\"libVersionNumber\": %d, "
           "\"sourceId\": \"%s\","
           "\"downloadVersion\": %d}"/*missing newline is intentional*/,
           SQLITE_VERSION,
           SQLITE_VERSION_NUMBER,
           SQLITE_SOURCE_ID,
           dlVersion);
  }else{
    if(fQuote) printf("%c", '"');
    if( fVersion ){
      printf("%s", SQLITE_VERSION);
    }else if( fVersionNumber ){
      printf("%d", SQLITE_VERSION_NUMBER);
    }else if( fSourceInfo ){
      printf("%s", SQLITE_SOURCE_ID);
    }else if( fDlVersion ){
      printf("%d", dlVersion);
    }
    if(fQuote) printf("%c", '"');
    puts("");
  }
  return 0;
}

Added ext/wasm/wasmfs.make.





































































































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
#!/usr/bin/make
#^^^^ help emacs select makefile mode
#
# This is a sub-make for building a standalone wasmfs-based
# sqlite3.wasm.  It is intended to be "include"d from the main
# GNUMakefile.
########################################################################
MAKEFILE.wasmfs := $(lastword $(MAKEFILE_LIST))

# Maintenance reminder: these particular files cannot be built into a
# subdirectory because loading of the auxiliary
# sqlite3-wasmfs.worker.js file it creates fails if sqlite3-wasmfs.js
# is loaded from any directory other than the one in which the
# containing HTML lives. Similarly, they cannot be loaded from a
# Worker to an Emscripten quirk regarding loading nested Workers.
dir.wasmfs := $(dir.wasm)
sqlite3-wasmfs.js     := $(dir.wasmfs)/sqlite3-wasmfs.js
sqlite3-wasmfs.mjs    := $(dir.wasmfs)/sqlite3-wasmfs.mjs
sqlite3-wasmfs.wasm   := $(dir.wasmfs)/sqlite3-wasmfs.wasm

CLEAN_FILES += $(sqlite3-wasmfs.js) $(sqlite3-wasmfs.wasm) \
    $(subst .js,.worker.js,$(sqlite3-wasmfs.js)) \
    $(sqlite3-wasmfs.mjs) \
    $(subst .mjs,.worker.mjs,$(sqlite3-wasmfs.mjs))

########################################################################
# emcc flags for .c/.o.
cflags.sqlite3-wasmfs :=
cflags.sqlite3-wasmfs += -std=c99 -fPIC
cflags.sqlite3-wasmfs += -pthread
cflags.sqlite3-wasmfs += $(cflags.speedtest1)
cflags.sqlite3-wasmfs += $(SQLITE_OPT) -DSQLITE_ENABLE_WASMFS

########################################################################
# emcc flags specific to building the final .js/.wasm file...
emcc.flags.sqlite3-wasmfs := -fPIC
emcc.flags.sqlite3-wasmfs += --no-entry
emcc.flags.sqlite3-wasmfs += --minify 0
emcc.flags.sqlite3-wasmfs += -sMODULARIZE
emcc.flags.sqlite3-wasmfs += -sEXPORT_NAME=$(sqlite3.js.init-func)
emcc.flags.sqlite3-wasmfs += -sSTRICT_JS
emcc.flags.sqlite3-wasmfs += -sDYNAMIC_EXECUTION=0
emcc.flags.sqlite3-wasmfs += -sNO_POLYFILL
emcc.flags.sqlite3-wasmfs += -sWASM_BIGINT=$(emcc.WASM_BIGINT)
emcc.flags.sqlite3-wasmfs += -sEXPORTED_FUNCTIONS=@$(abspath $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-api)
emcc.flags.sqlite3-wasmfs += -sEXPORTED_RUNTIME_METHODS=FS,wasmMemory,allocateUTF8OnStack
                          # wasmMemory ==> for -sIMPORTED_MEMORY
                          # allocateUTF8OnStack ==> wasmfs internals
emcc.flags.sqlite3-wasmfs += -sUSE_CLOSURE_COMPILER=0
emcc.flags.sqlite3-wasmfs += -Wno-limited-postlink-optimizations
# ^^^^^ it likes to warn when we have "limited optimizations" via the -g3 flag.
emcc.flags.sqlite3-wasmfs += -sALLOW_TABLE_GROWTH
emcc.flags.sqlite3-wasmfs += -sSTACK_SIZE=512KB
emcc.flags.sqlite3-wasmfs += -sGLOBAL_BASE=4096 # HYPOTHETICALLY keep func table indexes from overlapping w/ heap addr.
emcc.flags.sqlite3-wasmfs += -sMEMORY64=0
emcc.flags.sqlite3-wasmfs += -sIMPORTED_MEMORY
emcc.flags.sqlite3-wasmfs += -sINITIAL_MEMORY=$(emcc.INITIAL_MEMORY.128)
# ^^^^ 64MB is not enough for WASMFS/OPFS test runs using batch-runner.js
sqlite3-wasmfs.fsflags := -pthread -sWASMFS \
    -sPTHREAD_POOL_SIZE=2 -sENVIRONMENT=web,worker \
    -sERROR_ON_UNDEFINED_SYMBOLS=0 -sLLD_REPORT_UNDEFINED 
# ^^^^^ why undefined symbols are necessary for the wasmfs build is anyone's guess.
emcc.flags.sqlite3-wasmfs += $(sqlite3-wasmfs.fsflags)
#emcc.flags.sqlite3-wasmfs += -sALLOW_MEMORY_GROWTH
#^^^ using ALLOW_MEMORY_GROWTH produces a warning from emcc:
#   USE_PTHREADS + ALLOW_MEMORY_GROWTH may run non-wasm code slowly,
#   see https://github.com/WebAssembly/design/issues/1271 [-Wpthreads-mem-growth]
# And, indeed, it runs slowly if memory is permitted to grow.
emcc.flags.sqlite3-wasmfs.vanilla :=
emcc.flags.sqlite3-wasmfs.esm := -sEXPORT_ES6 -sUSE_ES6_IMPORT_META
$(eval $(call call-make-pre-js,sqlite3-wasmfs,vanilla))
$(eval $(call call-make-pre-js,sqlite3-wasmfs,esm))
Xemcc.flags.sqlite3-wasmfs.vanilla += \
  $(pre-post-common.flags.vanilla) \
  $(pre-post-sqlite3-wasmfs.flags.vanilla)
Xemcc.flags.sqlite3-wasmfs.esm += \
  $(pre-post-common.flags.esm) \
  $(pre-post-sqlite3-wasmfs.flags.esm)
$(sqlite3-wasmfs.js) $(sqlite3-wasmfs.mjs): $(sqlite3-wasm.c) \
    $(EXPORTED_FUNCTIONS.api) $(MAKEFILE) $(MAKEFILE.wasmfs)
$(sqlite3-wasmfs.js): $(pre-post-sqlite3-wasmfs.deps.vanilla)
$(sqlite3-wasmfs.mjs): $(pre-post-sqlite3-wasmfs.deps.esm)
# SQLITE3-WASMFS.xJS.RECIPE is the wasmfs-specific counterpart
# of SQLITE3.xJS.RECIPE from the main makefile.
define SQLITE3-WASMFS.xJS.RECIPE
	@echo "Building $@ ..."
	$(emcc.bin) -o $@ $(emcc_opt_full) $(emcc.flags) \
      $(cflags.sqlite3-wasmfs) \
      $(emcc.flags.sqlite3-wasmfs) $(emcc.flags.sqlite3-wasmfs.$(1)) \
      $(pre-post-sqlite3-wasmfs.flags.$(1)) \
     $(sqlite3-wasm.c)
	@$(call SQLITE3.xJS.ESM-EXPORT-DEFAULT,$(1))
	chmod -x $(sqlite3-wasmfs.wasm)
	$(maybe-wasm-strip) $(sqlite3-wasmfs.wasm)
	@ls -la $(sqlite3-wasmfs.wasm) sqlite3-wasmfs*js
endef
$(sqlite3-wasmfs.js):
	$(call SQLITE3-WASMFS.xJS.RECIPE,vanilla)
$(sqlite3-wasmfs.mjs): $(sqlite3-wasmfs.js)
	$(call SQLITE3-WASMFS.xJS.RECIPE,esm)
$(sqlite3-wasmfs.wasm): $(sqlite3-wasmfs.js)
wasmfs: $(sqlite3-wasmfs.js) $(sqlite3-wasmfs.mjs)
#all: wasmfs

########################################################################
# speedtest1 for wasmfs.
speedtest1-wasmfs.js := $(dir.wasmfs)/speedtest1-wasmfs.js
speedtest1-wasmfs.wasm := $(subst .js,.wasm,$(speedtest1-wasmfs.js))
emcc.flags.speedtest1-wasmfs := $(sqlite3-wasmfs.fsflags)
emcc.flags.speedtest1-wasmfs += $(SQLITE_OPT) -DSQLITE_ENABLE_WASMFS
emcc.flags.speedtest1-wasmfs += -sALLOW_MEMORY_GROWTH=0
emcc.flags.speedtest1-wasmfs += -sINITIAL_MEMORY=$(emcc.INITIAL_MEMORY.128)
#$(eval $(call call-make-pre-js,speedtest1-wasmfs,vanilla))
$(speedtest1-wasmfs.js): $(speedtest1.cses) $(sqlite3-wasmfs.js) \
  $(MAKEFILE) $(MAKEFILE.wasmfs) \
  $(pre-post-sqlite3-wasmfs.deps) \
  $(EXPORTED_FUNCTIONS.speedtest1)
	@echo "Building $@ ..."
	$(emcc.bin) \
         $(emcc.speedtest1.common) $(emcc.flags.speedtest1-wasmfs) \
        $(pre-post-sqlite3-wasmfs.flags.vanilla) \
        $(cflags.sqlite3-wasmfs) \
        -o $@ $(speedtest1.cses) -lm
	$(maybe-wasm-strip) $(speedtest1-wasmfs.wasm)
	ls -la $@ $(speedtest1-wasmfs.wasm)

#speedtest1: $(speedtest1-wasmfs.js)
wasmfs: $(speedtest1-wasmfs.js)
CLEAN_FILES += $(speedtest1-wasmfs.js) $(speedtest1-wasmfs.wasm) \
     $(subst .js,.worker.js,$(speedtest1-wasmfs.js))
# end speedtest1.js
########################################################################

Changes to magic.txt.

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











-
+




-
+




-
-
+
+








+

# This file contains suggested magic(5) text for the unix file(1)
# utility for recognizing SQLite3 databases.
#
# When SQLite is used as an application file format, it is desirable to
# have file(1) recognize the database file as being with the specific
# application.  You can set the application_id for a database file
# using:
#
#     PRAGMA application_id = INTEGER;
#
# INTEGER can be any signed 32-bit integer.  That integer is written as
# a 4-byte big-endian integer into offset 68 of the database header. 
# a 4-byte big-endian integer into offset 68 of the database header.
#
# The Monotone application used "PRAGMA user_version=1598903374;" to set
# its identifier long before "PRAGMA application_id" became available.
# The user_version is very similar to application_id except that it is
# stored at offset 68 instead of offset 60.  The application_id pragma
# stored at offset 60 instead of offset 68.  The application_id pragma
# is preferred.  The rule using offset 60 for Monotone is for historical
# compatibility only.
#
0    string  =SQLite\ format\ 3
>68  belong  =0x0f055112  Fossil checkout - 
>68  belong  =0x0f055113  Fossil global configuration - 
>68  belong  =0x0f055112  Fossil checkout -
>68  belong  =0x0f055113  Fossil global configuration -
>68  belong  =0x0f055111  Fossil repository -
>68  belong  =0x42654462  Bentley Systems BeSQLite Database -
>68  belong  =0x42654c6e  Bentley Systems Localization File -
>60  belong  =0x5f4d544e  Monotone source repository -
>68  belong  =0x47504b47  OGC GeoPackage file -
>68  belong  =0x47503130  OGC GeoPackage version 1.0 file -
>68  belong  =0x45737269  Esri Spatially-Enabled Database -
>68  belong  =0x4d504258  MBTiles tileset -
>68  belong  =0x6a035744  TeXnicard card database
>0   string  =SQLite      SQLite3 database

Changes to main.mk.


1
2
3
4
5
6
7
1
2
3
4
5
6
7
8
+








###############################################################################
# The following macros should be defined before this script is
# invoked:
#
# TOP              The toplevel directory of the source tree.  This is the
#                  directory that contains this "Makefile.in" and the
#                  "configure.in" script.
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
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







-
+



-
+






+
-
+







         date.o dbpage.o dbstat.o delete.o expr.o \
	 fault.o fkey.o \
         fts3.o fts3_aux.o fts3_expr.o fts3_hash.o fts3_icu.o fts3_porter.o \
         fts3_snippet.o fts3_tokenizer.o fts3_tokenizer1.o \
         fts3_tokenize_vtab.o \
	 fts3_unicode.o fts3_unicode2.o \
         fts3_write.o fts5.o func.o global.o hash.o \
         icu.o insert.o json1.o legacy.o loadext.o \
         icu.o insert.o json.o legacy.o loadext.o \
         main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \
         memdb.o memjournal.o \
         mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \
         notify.o opcodes.o os.o os_unix.o os_win.o \
         notify.o opcodes.o os.o os_kv.o os_unix.o os_win.o \
         pager.o pcache.o pcache1.o pragma.o prepare.o printf.o \
         random.o resolve.o rowset.o rtree.o \
         select.o sqlite3rbu.o status.o stmt.o \
         table.o threads.o tokenize.o treeview.o trigger.o \
         update.o upsert.o userauth.o util.o vacuum.o \
         vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o vdbesort.o \
	 vdbetrace.o vdbevtab.o \
	 vdbetrace.o wal.o walker.o where.o wherecode.o whereexpr.o \
         wal.o walker.o where.o wherecode.o whereexpr.o \
         utf.o vtab.o window.o

LIBOBJ += sqlite3session.o

# All of the source code files.
#
SRC = \
105
106
107
108
109
110
111

112
113
114
115
116
117
118
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121







+







  $(TOP)/src/fkey.c \
  $(TOP)/src/func.c \
  $(TOP)/src/global.c \
  $(TOP)/src/hash.c \
  $(TOP)/src/hash.h \
  $(TOP)/src/hwtime.h \
  $(TOP)/src/insert.c \
  $(TOP)/src/json.c \
  $(TOP)/src/legacy.c \
  $(TOP)/src/loadext.c \
  $(TOP)/src/main.c \
  $(TOP)/src/malloc.c \
  $(TOP)/src/mem0.c \
  $(TOP)/src/mem1.c \
  $(TOP)/src/mem2.c \
127
128
129
130
131
132
133

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







+







  $(TOP)/src/mutex_unix.c \
  $(TOP)/src/mutex_w32.c \
  $(TOP)/src/notify.c \
  $(TOP)/src/os.c \
  $(TOP)/src/os.h \
  $(TOP)/src/os_common.h \
  $(TOP)/src/os_setup.h \
  $(TOP)/src/os_kv.c \
  $(TOP)/src/os_unix.c \
  $(TOP)/src/os_win.c \
  $(TOP)/src/os_win.h \
  $(TOP)/src/pager.c \
  $(TOP)/src/pager.h \
  $(TOP)/src/parse.y \
  $(TOP)/src/pcache.c \
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
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







+















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







  $(TOP)/src/vdbe.h \
  $(TOP)/src/vdbeapi.c \
  $(TOP)/src/vdbeaux.c \
  $(TOP)/src/vdbeblob.c \
  $(TOP)/src/vdbemem.c \
  $(TOP)/src/vdbesort.c \
  $(TOP)/src/vdbetrace.c \
  $(TOP)/src/vdbevtab.c \
  $(TOP)/src/vdbeInt.h \
  $(TOP)/src/vtab.c \
  $(TOP)/src/vxworks.h \
  $(TOP)/src/wal.c \
  $(TOP)/src/wal.h \
  $(TOP)/src/walker.c \
  $(TOP)/src/where.c \
  $(TOP)/src/wherecode.c \
  $(TOP)/src/whereexpr.c \
  $(TOP)/src/whereInt.h \
  $(TOP)/src/window.c

# Source code for extensions
#
SRC += \
  $(TOP)/ext/fts1/fts1.c \
  $(TOP)/ext/fts1/fts1.h \
  $(TOP)/ext/fts1/fts1_hash.c \
  $(TOP)/ext/fts1/fts1_hash.h \
  $(TOP)/ext/fts1/fts1_porter.c \
  $(TOP)/ext/fts1/fts1_tokenizer.h \
  $(TOP)/ext/fts1/fts1_tokenizer1.c
SRC += \
  $(TOP)/ext/fts2/fts2.c \
  $(TOP)/ext/fts2/fts2.h \
  $(TOP)/ext/fts2/fts2_hash.c \
  $(TOP)/ext/fts2/fts2_hash.h \
  $(TOP)/ext/fts2/fts2_icu.c \
  $(TOP)/ext/fts2/fts2_porter.c \
  $(TOP)/ext/fts2/fts2_tokenizer.h \
  $(TOP)/ext/fts2/fts2_tokenizer.c \
  $(TOP)/ext/fts2/fts2_tokenizer1.c
SRC += \
  $(TOP)/ext/fts3/fts3.c \
  $(TOP)/ext/fts3/fts3.h \
  $(TOP)/ext/fts3/fts3Int.h \
  $(TOP)/ext/fts3/fts3_aux.c \
  $(TOP)/ext/fts3/fts3_expr.c \
  $(TOP)/ext/fts3/fts3_hash.c \
  $(TOP)/ext/fts3/fts3_hash.h \
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
224
225
226
227
228
229
230

231
232
233
234
235
236
237







-







SRC += \
  $(TOP)/ext/userauth/userauth.c \
  $(TOP)/ext/userauth/sqlite3userauth.h
SRC += \
  $(TOP)/ext/rbu/sqlite3rbu.c \
  $(TOP)/ext/rbu/sqlite3rbu.h
SRC += \
  $(TOP)/ext/misc/json1.c \
  $(TOP)/ext/misc/stmt.c


# FTS5 things
#
FTS5_HDR = \
   $(TOP)/ext/fts5/fts5.h \
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
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







+









+
+
+

+


+









+
+







-



-
+
+
+
+
+


-


















+












+






+













-
+
+







  $(TOP)/src/test_server.c \
  $(TOP)/src/test_sqllog.c \
  $(TOP)/src/test_superlock.c \
  $(TOP)/src/test_syscall.c \
  $(TOP)/src/test_tclsh.c \
  $(TOP)/src/test_tclvar.c \
  $(TOP)/src/test_thread.c \
  $(TOP)/src/test_vdbecov.c \
  $(TOP)/src/test_vfs.c \
  $(TOP)/src/test_windirent.c \
  $(TOP)/src/test_window.c \
  $(TOP)/src/test_wsd.c

# Extensions to be statically loaded.
#
TESTSRC += \
  $(TOP)/ext/misc/amatch.c \
  $(TOP)/ext/misc/appendvfs.c \
  $(TOP)/ext/misc/basexx.c \
  $(TOP)/ext/misc/bgckpt.c \
  $(TOP)/ext/misc/carray.c \
  $(TOP)/ext/misc/cksumvfs.c \
  $(TOP)/ext/misc/closure.c \
  $(TOP)/ext/misc/csv.c \
  $(TOP)/ext/misc/decimal.c \
  $(TOP)/ext/misc/eval.c \
  $(TOP)/ext/misc/explain.c \
  $(TOP)/ext/misc/fileio.c \
  $(TOP)/ext/misc/fuzzer.c \
  $(TOP)/ext/misc/ieee754.c \
  $(TOP)/ext/misc/mmapwarm.c \
  $(TOP)/ext/misc/nextchar.c \
  $(TOP)/ext/misc/normalize.c \
  $(TOP)/ext/misc/percentile.c \
  $(TOP)/ext/misc/prefixes.c \
  $(TOP)/ext/misc/qpvtab.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/vfslog.c \
  $(TOP)/ext/misc/zipfile.c \
  $(TOP)/ext/fts5/fts5_tcl.c \
  $(TOP)/ext/fts5/fts5_test_mi.c \
  $(TOP)/ext/fts5/fts5_test_tok.c
  $(TOP)/ext/fts5/fts5_test_tok.c \
  $(TOP)/ext/rtree/test_rtreedoc.c \
  $(TOP)/ext/recover/sqlite3recover.c \
  $(TOP)/ext/recover/dbdata.c \
  $(TOP)/ext/recover/test_recover.c


#TESTSRC += $(TOP)/ext/fts2/fts2_tokenizer.c
#TESTSRC += $(TOP)/ext/fts3/fts3_tokenizer.c

TESTSRC2 = \
  $(TOP)/src/attach.c \
  $(TOP)/src/backup.c \
  $(TOP)/src/btree.c \
  $(TOP)/src/build.c \
  $(TOP)/src/date.c \
  $(TOP)/src/dbpage.c \
  $(TOP)/src/dbstat.c \
  $(TOP)/src/expr.c \
  $(TOP)/src/func.c \
  $(TOP)/src/global.c \
  $(TOP)/src/insert.c \
  $(TOP)/src/wal.c \
  $(TOP)/src/main.c \
  $(TOP)/src/mem5.c \
  $(TOP)/src/os.c \
  $(TOP)/src/os_kv.c \
  $(TOP)/src/os_unix.c \
  $(TOP)/src/os_win.c \
  $(TOP)/src/pager.c \
  $(TOP)/src/pragma.c \
  $(TOP)/src/prepare.c \
  $(TOP)/src/printf.c \
  $(TOP)/src/random.c \
  $(TOP)/src/pcache.c \
  $(TOP)/src/pcache1.c \
  $(TOP)/src/select.c \
  $(TOP)/src/threads.c \
  $(TOP)/src/tokenize.c \
  $(TOP)/src/treeview.c \
  $(TOP)/src/utf.c \
  $(TOP)/src/util.c \
  $(TOP)/src/vdbeapi.c \
  $(TOP)/src/vdbeaux.c \
  $(TOP)/src/vdbe.c \
  $(TOP)/src/vdbemem.c \
  $(TOP)/src/vdbevtab.c \
  $(TOP)/src/where.c \
  $(TOP)/src/wherecode.c \
  $(TOP)/src/whereexpr.c \
  parse.c \
  $(TOP)/ext/fts3/fts3.c \
  $(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/sqlite3changebatch.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 \
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
462
463
464
465
466
467
468








469
470
471
472
473
474
475







-
-
-
-
-
-
-
-







   $(TOP)/src/vdbeInt.h \
   $(TOP)/src/vxworks.h \
   $(TOP)/src/whereInt.h

# Header files used by extensions
#
EXTHDR += \
  $(TOP)/ext/fts1/fts1.h \
  $(TOP)/ext/fts1/fts1_hash.h \
  $(TOP)/ext/fts1/fts1_tokenizer.h
EXTHDR += \
  $(TOP)/ext/fts2/fts2.h \
  $(TOP)/ext/fts2/fts2_hash.h \
  $(TOP)/ext/fts2/fts2_tokenizer.h
EXTHDR += \
  $(TOP)/ext/fts3/fts3.h \
  $(TOP)/ext/fts3/fts3Int.h \
  $(TOP)/ext/fts3/fts3_hash.h \
  $(TOP)/ext/fts3/fts3_tokenizer.h
EXTHDR += \
  $(TOP)/ext/rtree/rtree.h \
  $(TOP)/ext/rtree/geopoly.c
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
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







-
+
+







-
+






-
-
-
-
+
+
+
+
+


+
+
+
+
+
+
+
+
+
+
+







-
+

-
+



-
+







FUZZDATA = \
  $(TOP)/test/fuzzdata1.db \
  $(TOP)/test/fuzzdata2.db \
  $(TOP)/test/fuzzdata3.db \
  $(TOP)/test/fuzzdata4.db \
  $(TOP)/test/fuzzdata5.db \
  $(TOP)/test/fuzzdata6.db \
  $(TOP)/test/fuzzdata7.db
  $(TOP)/test/fuzzdata7.db \
  $(TOP)/test/fuzzdata8.db

# Standard options to testfixture
#
TESTOPTS = --verbose=file --output=test-out.txt

# Extra compiler options for various shell tools
#
SHELL_OPT += -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5
SHELL_OPT += -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5
SHELL_OPT += -DSQLITE_ENABLE_RTREE
SHELL_OPT += -DSQLITE_ENABLE_EXPLAIN_COMMENTS
SHELL_OPT += -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
SHELL_OPT += -DSQLITE_ENABLE_STMTVTAB
SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB
SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC
SHELL_OPT += -DSQLITE_INTROSPECTION_PRAGMAS
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5
SHELL_OPT += -DSQLITE_ENABLE_BYTECODE_VTAB
SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC
FUZZCHECK_OPT += -I$(TOP)/test
FUZZCHECK_OPT += -I$(TOP)/ext/recover
FUZZCHECK_OPT += -DSQLITE_ENABLE_MEMSYS5
FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000
FUZZCHECK_OPT += -DSQLITE_PRINTF_PRECISION_LIMIT=1000
FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS4
FUZZCHECK_OPT += -DSQLITE_ENABLE_RTREE
FUZZCHECK_OPT += -DSQLITE_ENABLE_GEOPOLY
FUZZCHECK_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
FUZZCHECK_OPT += -DSQLITE_ENABLE_BYTECODE_VTAB
FUZZSRC += $(TOP)/test/fuzzcheck.c
FUZZSRC += $(TOP)/test/ossfuzz.c
FUZZSRC += $(TOP)/test/vt02.c
FUZZSRC += $(TOP)/test/fuzzinvariants.c
FUZZSRC += $(TOP)/ext/recover/dbdata.c
FUZZSRC += $(TOP)/ext/recover/sqlite3recover.c
DBFUZZ_OPT =
KV_OPT = -DSQLITE_THREADSAFE=0 -DSQLITE_DIRECT_OVERFLOW_READ
ST_OPT = -DSQLITE_THREADSAFE=0

# This is the default Makefile target.  The objects listed here
# are what get build when you type just "make" with no arguments.
#
all:	sqlite3.h libsqlite3.a sqlite3$(EXE)
all:	sqlite3.h sqlite3ext.h libsqlite3.a sqlite3$(EXE)

libsqlite3.a:	$(LIBOBJ)
libsqlite3.a: sqlite3.h	$(LIBOBJ)
	$(AR) libsqlite3.a $(LIBOBJ)
	$(RANLIB) libsqlite3.a

sqlite3$(EXE):	shell.c libsqlite3.a sqlite3.h
sqlite3$(EXE):	sqlite3.h libsqlite3.a shell.c
	$(TCCX) $(READLINE_FLAGS) -o sqlite3$(EXE) $(SHELL_OPT) \
		shell.c libsqlite3.a $(LIBREADLINE) $(TLIBS) $(THREADLIB)

sqldiff$(EXE):	$(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h
	$(TCCX) -o sqldiff$(EXE) -DSQLITE_THREADSAFE=0 \
		$(TOP)/tool/sqldiff.c sqlite3.c $(TLIBS) $(THREADLIB)

571
572
573
574
575
576
577









578






579
580
581

582
583
584
585
586
587
588
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







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


-
+







	  $(TLIBS) $(THREADLIB)

dbfuzz$(EXE):	$(TOP)/test/dbfuzz.c sqlite3.c sqlite3.h
	$(TCCX) -o dbfuzz$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
	  $(DBFUZZ_OPT) $(TOP)/test/dbfuzz.c sqlite3.c \
	  $(TLIBS) $(THREADLIB)

DBFUZZ2_OPTS = \
  -DSQLITE_THREADSAFE=0 \
  -DSQLITE_OMIT_LOAD_EXTENSION \
  -DSQLITE_DEBUG \
  -DSQLITE_ENABLE_DBSTAT_VTAB \
  -DSQLITE_ENABLE_BYTECODE_VTAB \
  -DSQLITE_ENABLE_RTREE \
  -DSQLITE_ENABLE_FTS4 \
  -DSQLITE_ENABLE_FTS5
fuzzcheck$(EXE):	$(TOP)/test/fuzzcheck.c sqlite3.c sqlite3.h $(TOP)/test/ossfuzz.c

dbfuzz2$(EXE):	$(TOP)/test/dbfuzz2.c sqlite3.c sqlite3.h
	$(TCCX) -I. -g -O0 -DSTANDALONE -o dbfuzz2$(EXE) \
	  $(DBFUZZ2_OPTS) $(TOP)/test/dbfuzz2.c sqlite3.c  $(TLIBS) $(THREADLIB)

fuzzcheck$(EXE):	$(FUZZSRC) sqlite3.c sqlite3.h $(FUZZDEP)
	$(TCCX) -o fuzzcheck$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
		-DSQLITE_ENABLE_MEMSYS5 $(FUZZCHECK_OPT) -DSQLITE_OSS_FUZZ \
		$(TOP)/test/fuzzcheck.c $(TOP)/test/ossfuzz.c sqlite3.c $(TLIBS) $(THREADLIB)
		$(FUZZSRC) sqlite3.c $(TLIBS) $(THREADLIB)

ossshell$(EXE):	$(TOP)/test/ossfuzz.c $(TOP)/test/ossshell.c sqlite3.c sqlite3.h
	$(TCCX) -o ossshell$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
		-DSQLITE_ENABLE_MEMSYS5 $(FUZZCHECK_OPT) \
		$(TOP)/test/ossfuzz.c $(TOP)/test/ossshell.c sqlite3.c $(TLIBS) $(THREADLIB)

sessionfuzz$(EXE):	$(TOP)/test/sessionfuzz.c sqlite3.c sqlite3.h
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
651
652
653
654
655
656
657

658
659
660
661
662
663
664
665
666
667






668
669
670
671
672
673
674







-
+









-
-
-
-
-
-







	echo '#endif /* USE_SYSTEM_SQLITE */' >>tclsqlite3.c
	cat $(TOP)/src/tclsqlite.c >>tclsqlite3.c

sqlite3ext.h:	target_source
	cp tsrc/sqlite3ext.h .

sqlite3.c-debug:	target_source $(TOP)/tool/mksqlite3c.tcl
	tclsh $(TOP)/tool/mksqlite3c.tcl --linemacros
	tclsh $(TOP)/tool/mksqlite3c.tcl --linemacros=1
	echo '#ifndef USE_SYSTEM_SQLITE' >tclsqlite3.c
	cat sqlite3.c >>tclsqlite3.c
	echo '#endif /* USE_SYSTEM_SQLITE */' >>tclsqlite3.c
	echo '#line 1 "tclsqlite.c"' >>tclsqlite3.c
	cat $(TOP)/src/tclsqlite.c >>tclsqlite3.c

sqlite3-all.c:	sqlite3.c $(TOP)/tool/split-sqlite3c.tcl
	tclsh $(TOP)/tool/split-sqlite3c.tcl

fts2amal.c:	target_source $(TOP)/ext/fts2/mkfts2amal.tcl
	tclsh $(TOP)/ext/fts2/mkfts2amal.tcl

fts3amal.c:	target_source $(TOP)/ext/fts3/mkfts3amal.tcl
	tclsh $(TOP)/ext/fts3/mkfts3amal.tcl

# Rules to build the LEMON compiler generator
#
lemon:	$(TOP)/tool/lemon.c $(TOP)/tool/lempar.c
	$(BCC) -o lemon $(TOP)/tool/lemon.c
	cp $(TOP)/tool/lempar.c .

# A tool to generate the source-id
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
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







-
+

-

-
-



+
+
+
+
+
+









+
-
+
+
+

-
+
+
+
+

+



+
+
+
+












-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







	cat parse.h $(TOP)/src/vdbe.c | \
		tclsh $(TOP)/tool/mkopcodeh.tcl >opcodes.h

# Rules to build parse.c and parse.h - the outputs of lemon.
#
parse.h:	parse.c

parse.c:	$(TOP)/src/parse.y lemon $(TOP)/tool/addopcodes.tcl
parse.c:	$(TOP)/src/parse.y lemon
	cp $(TOP)/src/parse.y .
	rm -f parse.h
	./lemon -s $(OPTS) parse.y
	mv parse.h parse.h.temp
	tclsh $(TOP)/tool/addopcodes.tcl parse.h.temp >parse.h

sqlite3.h:	$(TOP)/src/sqlite.h.in $(TOP)/manifest mksourceid $(TOP)/VERSION $(TOP)/ext/rtree/sqlite3rtree.h
	tclsh $(TOP)/tool/mksqlite3h.tcl $(TOP) >sqlite3.h

sqlite3rc.h:	$(TOP)/src/sqlite3.rc $(TOP)/VERSION
	echo '#ifndef SQLITE_RESOURCE_VERSION' >$@
	echo -n '#define SQLITE_RESOURCE_VERSION ' >>$@
	cat $(TOP)/VERSION | tclsh $(TOP)/tool/replace.tcl exact . , >>$@
	echo '#endif' >>sqlite3rc.h

keywordhash.h:	$(TOP)/tool/mkkeywordhash.c
	$(BCC) -o mkkeywordhash $(OPTS) $(TOP)/tool/mkkeywordhash.c
	./mkkeywordhash >keywordhash.h

# Source files that go into making shell.c
SHELL_SRC = \
	$(TOP)/src/shell.c.in \
        $(TOP)/ext/misc/appendvfs.c \
	$(TOP)/ext/misc/completion.c \
	$(TOP)/ext/misc/shathree.c \
        $(TOP)/ext/misc/base64.c \
        $(TOP)/ext/misc/base85.c \
        $(TOP)/ext/misc/decimal.c \
	$(TOP)/ext/misc/fileio.c \
	$(TOP)/ext/misc/completion.c \
        $(TOP)/ext/misc/ieee754.c \
        $(TOP)/ext/misc/regexp.c \
        $(TOP)/ext/misc/series.c \
	$(TOP)/ext/misc/shathree.c \
	$(TOP)/ext/misc/sqlar.c \
        $(TOP)/ext/misc/uint.c \
	$(TOP)/ext/expert/sqlite3expert.c \
	$(TOP)/ext/expert/sqlite3expert.h \
	$(TOP)/ext/misc/zipfile.c \
	$(TOP)/ext/misc/memtrace.c \
	$(TOP)/ext/recover/dbdata.c \
	$(TOP)/ext/recover/sqlite3recover.c \
	$(TOP)/ext/recover/sqlite3recover.h \
        $(TOP)/src/test_windirent.c

shell.c:	$(SHELL_SRC) $(TOP)/tool/mkshellc.tcl
	tclsh $(TOP)/tool/mkshellc.tcl >shell.c



# Rules to build the extension objects.
#
icu.o:	$(TOP)/ext/icu/icu.c $(HDR) $(EXTHDR)
	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/icu/icu.c

fts2.o:	$(TOP)/ext/fts2/fts2.c $(HDR) $(EXTHDR)
	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2.c

fts2_hash.o:	$(TOP)/ext/fts2/fts2_hash.c $(HDR) $(EXTHDR)
	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_hash.c

fts2_icu.o:	$(TOP)/ext/fts2/fts2_icu.c $(HDR) $(EXTHDR)
	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_icu.c

fts2_porter.o:	$(TOP)/ext/fts2/fts2_porter.c $(HDR) $(EXTHDR)
	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_porter.c

fts2_tokenizer.o:	$(TOP)/ext/fts2/fts2_tokenizer.c $(HDR) $(EXTHDR)
	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_tokenizer.c

fts2_tokenizer1.o:	$(TOP)/ext/fts2/fts2_tokenizer1.c $(HDR) $(EXTHDR)
	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_tokenizer1.c

fts3.o:	$(TOP)/ext/fts3/fts3.c $(HDR) $(EXTHDR)
	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3.c

fts3_aux.o:	$(TOP)/ext/fts3/fts3_aux.c $(HDR) $(EXTHDR)
	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_aux.c

fts3_expr.o:	$(TOP)/ext/fts3/fts3_expr.c $(HDR) $(EXTHDR)
785
786
787
788
789
790
791
792

793
794
795
796
797
798

799
800
801
802
803
804
805
794
795
796
797
798
799
800

801
802
803




804
805
806
807
808
809
810
811







-
+


-
-
-
-
+








fts3_unicode2.o:	$(TOP)/ext/fts3/fts3_unicode2.c $(HDR) $(EXTHDR)
	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_unicode2.c

fts3_write.o:	$(TOP)/ext/fts3/fts3_write.c $(HDR) $(EXTHDR)
	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_write.c

fts5.o:	fts5.c
fts5.o:	fts5.c  sqlite3ext.h sqlite3.h
	$(TCCX) -DSQLITE_CORE -c fts5.c

json1.o:	$(TOP)/ext/misc/json1.c
	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/misc/json1.c

stmt.o:	$(TOP)/ext/misc/stmt.c
stmt.o:	$(TOP)/ext/misc/stmt.c sqlite3ext.h sqlite3.h
	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/misc/stmt.c

rtree.o:	$(TOP)/ext/rtree/rtree.c $(HDR) $(EXTHDR)
	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/rtree/rtree.c



872
873
874
875
876
877
878

879

880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924

925
926
927
928
929
930






931
932
933
934
935
936
937
938
939
940


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



956
957
958
959
960
961
962
963
964

965
966
967
968
969
970
971
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900






901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920




921

922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943

944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980







+

+













-
-
-
-
-
-




















-
-
-
-

-
+






+
+
+
+
+
+









-
+
+















+
+
+









+







#
TESTFIXTURE_FLAGS  = -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1
TESTFIXTURE_FLAGS += -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE
TESTFIXTURE_FLAGS += -DSQLITE_SERIES_CONSTRAINT_VERIFY=1
TESTFIXTURE_FLAGS += -DSQLITE_DEFAULT_PAGE_SIZE=1024
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_STMTVTAB
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_DBPAGE_VTAB
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_BYTECODE_VTAB
TESTFIXTURE_FLAGS += -DTCLSH_INIT_PROC=sqlite3TestInit
TESTFIXTURE_FLAGS += -DSQLITE_CKSUMVFS_STATIC

testfixture$(EXE): $(TESTSRC2) libsqlite3.a $(TESTSRC) $(TOP)/src/tclsqlite.c
	$(TCCX) $(TCL_FLAGS) $(TESTFIXTURE_FLAGS)                            \
		$(TESTSRC) $(TESTSRC2) $(TOP)/src/tclsqlite.c                \
		-o testfixture$(EXE) $(LIBTCL) libsqlite3.a $(THREADLIB)

amalgamation-testfixture$(EXE): sqlite3.c $(TESTSRC) $(TOP)/src/tclsqlite.c  \
				$(TOP)/ext/session/test_session.c
	$(TCCX) $(TCL_FLAGS) $(TESTFIXTURE_FLAGS)                            \
		$(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c                  \
		$(TOP)/ext/session/test_session.c                            \
		-o testfixture$(EXE) $(LIBTCL) $(THREADLIB)

fts3-testfixture$(EXE): sqlite3.c fts3amal.c $(TESTSRC) $(TOP)/src/tclsqlite.c
	$(TCCX) $(TCL_FLAGS) $(TESTFIXTURE_FLAGS)                            \
	-DSQLITE_ENABLE_FTS3=1                                               \
		$(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c fts3amal.c       \
		-o testfixture$(EXE) $(LIBTCL) $(THREADLIB)

coretestprogs:	$(TESTPROGS)

testprogs:	coretestprogs srcck1$(EXE) fuzzcheck$(EXE) sessionfuzz$(EXE)

fulltest:	$(TESTPROGS) fuzztest
	./testfixture$(EXE) $(TOP)/test/all.test $(TESTOPTS)

soaktest:	$(TESTPROGS)
	./testfixture$(EXE) $(TOP)/test/all.test -soak=1 $(TESTOPTS)

fulltestonly:	$(TESTPROGS) fuzztest
	./testfixture$(EXE) $(TOP)/test/full.test $(TESTOPTS)

queryplantest:	testfixture$(EXE) sqlite3$(EXE)
	./testfixture$(EXE) $(TOP)/test/permutations.test queryplanner $(TESTOPTS)

fuzztest:	fuzzcheck$(EXE) $(FUZZDATA) sessionfuzz$(EXE) $(TOP)/test/sessionfuzz-data1.db
	./fuzzcheck$(EXE) $(FUZZDATA)
	./sessionfuzz run $(TOP)/test/sessionfuzz-data1.db

fastfuzztest:	fuzzcheck$(EXE) $(FUZZDATA) sessionfuzz$(EXE) $(TOP)/test/sessionfuzz-data1.db
	./fuzzcheck$(EXE) --limit-mem 100M $(FUZZDATA)
	./sessionfuzz run $(TOP)/test/sessionfuzz-data1.db

valgrindfuzz:	fuzzcheck$(EXE) $(FUZZDATA) sessionfuzz$(EXE) $(TOP)/test/sessionfuzz-data1.db
	valgrind ./fuzzcheck$(EXE) --cell-size-check --limit-mem 10M --timeout 600 $(FUZZDATA)
	valgrind ./fuzzcheck$(EXE) --cell-size-check --limit-mem 10M $(FUZZDATA)
	valgrind ./sessionfuzz run $(TOP)/test/sessionfuzz-data1.db

# The veryquick.test TCL tests.
#
tcltest:	./testfixture$(EXE)
	./testfixture$(EXE) $(TOP)/test/veryquick.test $(TESTOPTS)

# Runs all the same tests cases as the "tcltest" target but uses
# the testrunner.tcl script to run them in multiple cores
# concurrently.
testrunner:	testfixture$(EXE)
	./testfixture$(EXE) $(TOP)/test/testrunner.tcl

# A very quick test using only testfixture and omitting all the slower
# tests.  Designed to run in under 3 minutes on a workstation.
#
quicktest:	./testfixture$(EXE)
	./testfixture$(EXE) $(TOP)/test/extraquick.test $(TESTOPTS)

# The default test case.  Runs most of the faster standard TCL tests,
# and fuzz tests, and sqlite3_analyzer and sqldiff tests.
test:	fastfuzztest sourcetest $(TESTPROGS) tcltest
test:	fuzztest sourcetest $(TESTPROGS) tcltest


# Run a test using valgrind.  This can take a really long time
# because valgrind is so much slower than a native machine.
#
valgrindtest:	$(TESTPROGS) valgrindfuzz
	OMIT_MISUSE=1 valgrind -v \
	./testfixture$(EXE) $(TOP)/test/permutations.test valgrind $(TESTOPTS)

# A very fast test that checks basic sanity.  The name comes from
# the 60s-era electronics testing:  "Turn it on and see if smoke
# comes out."
#
smoketest:	$(TESTPROGS) fuzzcheck$(EXE)
	./testfixture$(EXE) $(TOP)/test/main.test $(TESTOPTS)

shelltest: $(TESTPROGS)
	./testfixture$(EXT) $(TOP)/test/permutations.test shell

# The next two rules are used to support the "threadtest" target. Building
# threadtest runs a few thread-safety tests that are implemented in C. This
# target is invoked by the releasetest.tcl script.
#
THREADTEST3_SRC = $(TOP)/test/threadtest3.c    \
                  $(TOP)/test/tt3_checkpoint.c \
                  $(TOP)/test/tt3_index.c      \
                  $(TOP)/test/tt3_vacuum.c      \
                  $(TOP)/test/tt3_stress.c      \
                  $(TOP)/test/tt3_bcwal2.c      \
                  $(TOP)/test/tt3_lookaside1.c

threadtest3$(EXE): sqlite3.o $(THREADTEST3_SRC) $(TOP)/src/test_multiplex.c
	$(TCCX) $(TOP)/test/threadtest3.c $(TOP)/src/test_multiplex.c sqlite3.o -o $@ $(THREADLIB)

bc_test1$(EXE): sqlite3.o $(TOP)/test/bc_test1.c $(TOP)/test/tt3_core.c
	$(TCCX) $(TOP)/test/bc_test1.c sqlite3.o -o $@ $(THREADLIB)
999
1000
1001
1002
1003
1004
1005
1006

1007
1008
1009
1010
1011
1012
1013
1008
1009
1010
1011
1012
1013
1014

1015
1016
1017
1018
1019
1020
1021
1022







-
+







	$(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o showwal$(EXE) \
		$(TOP)/tool/showwal.c sqlite3.o $(THREADLIB)

showshm$(EXE):	$(TOP)/tool/showshm.c
	$(TCC) -o showshm$(EXE) $(TOP)/tool/showshm.c

index_usage$(EXE): $(TOP)/tool/index_usage.c sqlite3.o
	$(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_DEPRECATED -o index_usage$(EXE) \
	$(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_DEPRECATED $(SHELL_OPTS) -o index_usage$(EXE) \
		$(TOP)/tool/index_usage.c sqlite3.o $(THREADLIB)

changeset$(EXE):	$(TOP)/ext/session/changeset.c sqlite3.o
	$(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o changeset$(EXE) \
		$(TOP)/ext/session/changeset.c sqlite3.o $(THREADLIB)

changesetfuzz$(EXE):	$(TOP)/ext/session/changesetfuzz.c sqlite3.o
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
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







+
+
+











-
+


-
+







rbu$(EXE): $(TOP)/ext/rbu/rbu.c $(TOP)/ext/rbu/sqlite3rbu.c sqlite3.o
	$(TCC) -I. -o rbu$(EXE) $(TOP)/ext/rbu/rbu.c sqlite3.o \
	  $(THREADLIB)

loadfts: $(TOP)/tool/loadfts.c libsqlite3.a
	$(TCC) $(TOP)/tool/loadfts.c libsqlite3.a -o loadfts $(THREADLIB)

threadtest5:	$(TOP)/test/threadtest5.c libsqlite3.a
	$(TCC) $(TOP)/test/threadtest5.c libsqlite3.a -o threadtest5 $(THREADLIB)

# This target will fail if the SQLite amalgamation contains any exported
# symbols that do not begin with "sqlite3_". It is run as part of the
# releasetest.tcl script.
#
checksymbols: sqlite3.o
	nm -g --defined-only sqlite3.o | grep -v " sqlite3_" ; test $$? -ne 0

# Build the amalgamation-autoconf package.  The amalamgation-tarball target builds
# a tarball named for the version number.  Ex:  sqlite-autoconf-3110000.tar.gz.
# The snapshot-tarball target builds a tarball named by the SHA1 hash
#
amalgamation-tarball: sqlite3.c
amalgamation-tarball: sqlite3.c sqlite3rc.h
	TOP=$(TOP) sh $(TOP)/tool/mkautoconfamal.sh --normal

snapshot-tarball: sqlite3.c
snapshot-tarball: sqlite3.c sqlite3rc.h
	TOP=$(TOP) sh $(TOP)/tool/mkautoconfamal.sh --snapshot


# Standard install and cleanup targets
#
install:	sqlite3 libsqlite3.a sqlite3.h
	mv sqlite3 /usr/bin
1104
1105
1106
1107
1108
1109
1110

1116
1117
1118
1119
1120
1121
1122
1123







+
	rm -f mptester mptester.exe
	rm -f fuzzershell fuzzershell.exe
	rm -f fuzzcheck fuzzcheck.exe
	rm -f sessionfuzz
	rm -f sqldiff sqldiff.exe
	rm -f fts5.* fts5parse.*
	rm -f lsm.h lsm1.c
	rm -f threadtest5

Added sqlite_cfg.h.in.















































































































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/* sqlite_cfg.h.in.  Generated from configure.ac by autoheader.  */

/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H

/* Define to 1 if you have the `fdatasync' function. */
#undef HAVE_FDATASYNC

/* Define to 1 if you have the `gmtime_r' function. */
#undef HAVE_GMTIME_R

/* Define to 1 if the system has the type `int16_t'. */
#undef HAVE_INT16_T

/* Define to 1 if the system has the type `int32_t'. */
#undef HAVE_INT32_T

/* Define to 1 if the system has the type `int64_t'. */
#undef HAVE_INT64_T

/* Define to 1 if the system has the type `int8_t'. */
#undef HAVE_INT8_T

/* Define to 1 if the system has the type `intptr_t'. */
#undef HAVE_INTPTR_T

/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H

/* Define to 1 if you have the `isnan' function. */
#undef HAVE_ISNAN

/* Define to 1 if you have the `localtime_r' function. */
#undef HAVE_LOCALTIME_R

/* Define to 1 if you have the `localtime_s' function. */
#undef HAVE_LOCALTIME_S

/* Define to 1 if you have the <malloc.h> header file. */
#undef HAVE_MALLOC_H

/* Define to 1 if you have the `malloc_usable_size' function. */
#undef HAVE_MALLOC_USABLE_SIZE

/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H

/* Define to 1 if you have the `pread' function. */
#undef HAVE_PREAD

/* Define to 1 if you have the `pread64' function. */
#undef HAVE_PREAD64

/* Define to 1 if you have the `pwrite' function. */
#undef HAVE_PWRITE

/* Define to 1 if you have the `pwrite64' function. */
#undef HAVE_PWRITE64

/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H

/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H

/* Define to 1 if you have the `strchrnul' function. */
#undef HAVE_STRCHRNUL

/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H

/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H

/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H

/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H

/* Define to 1 if the system has the type `uint16_t'. */
#undef HAVE_UINT16_T

/* Define to 1 if the system has the type `uint32_t'. */
#undef HAVE_UINT32_T

/* Define to 1 if the system has the type `uint64_t'. */
#undef HAVE_UINT64_T

/* Define to 1 if the system has the type `uint8_t'. */
#undef HAVE_UINT8_T

/* Define to 1 if the system has the type `uintptr_t'. */
#undef HAVE_UINTPTR_T

/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H

/* Define to 1 if you have the `usleep' function. */
#undef HAVE_USLEEP

/* Define to 1 if you have the `utime' function. */
#undef HAVE_UTIME

/* Define to 1 if you have the <zlib.h> header file. */
#undef HAVE_ZLIB_H

/* Define to the sub-directory in which libtool stores uninstalled libraries.
   */
#undef LT_OBJDIR

/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT

/* Define to the full name of this package. */
#undef PACKAGE_NAME

/* Define to the full name and version of this package. */
#undef PACKAGE_STRING

/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME

/* Define to the home page for this package. */
#undef PACKAGE_URL

/* Define to the version of this package. */
#undef PACKAGE_VERSION

/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS

/* Enable large inode numbers on Mac OS X 10.5.  */
#ifndef _DARWIN_USE_64_BIT_INODE
# define _DARWIN_USE_64_BIT_INODE 1
#endif

/* Number of bits in a file offset, on hosts where this is settable. */
#undef _FILE_OFFSET_BITS

/* Define for large files, on AIX-style hosts. */
#undef _LARGE_FILES

Changes to src/alter.c.

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







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












-
+
+
+
+
+
+
+
+


-
-
+
+

-
-
-
+
+
+





-
-
+
+

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








-
+



-
-
+
+







** Parameter zName is the name of a table that is about to be altered
** (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 isSystemTable(Parse *pParse, const char *zName){
  if( 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
    sqlite3ErrorMsg(pParse, "table %s may not be altered", zName);
static int isAlterableTable(Parse *pParse, Table *pTab){
  if( 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7)
#ifndef SQLITE_OMIT_VIRTUALTABLE
   || (pTab->tabFlags & TF_Eponymous)!=0
   || ( (pTab->tabFlags & TF_Shadow)!=0
        && sqlite3ReadOnlyShadowTables(pParse->db)
   )
#endif
  ){
    sqlite3ErrorMsg(pParse, "table %s may not be altered", pTab->zName);
    return 1;
  }
  return 0;
}

/*
** Generate code to verify that the schemas of database zDb and, if
** bTemp is not true, database "temp", can still be parsed. This is
** called at the end of the generation of an ALTER TABLE ... RENAME ...
** statement to ensure that the operation has not rendered any schema
** objects unusable.
*/
static void renameTestSchema(Parse *pParse, const char *zDb, int bTemp){
static void renameTestSchema(
  Parse *pParse,                  /* Parse context */
  const char *zDb,                /* Name of db to verify schema of */
  int bTemp,                      /* True if this is the temp db */
  const char *zWhen,              /* "when" part of error message */
  int bNoDQS                      /* Do not allow DQS in the schema */
){
  pParse->colNamesSet = 1;
  sqlite3NestedParse(pParse, 
      "SELECT 1 "
      "FROM \"%w\".%s "
      "WHERE name NOT LIKE 'sqlite_%%'"
      "FROM \"%w\"." LEGACY_SCHEMA_TABLE " "
      "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
      " AND sql NOT LIKE 'create virtual%%'"
      " AND sqlite_rename_test(%Q, sql, type, name, %d)=NULL ",
      zDb, MASTER_NAME, 
      zDb, bTemp
      " AND sqlite_rename_test(%Q, sql, type, name, %d, %Q, %d)=NULL ",
      zDb,
      zDb, bTemp, zWhen, bNoDQS
  );

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

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

/*
** Generate code to reload the schema for database iDb. And, if iDb!=1, for
** the temp database as well.
*/
static void renameReloadSchema(Parse *pParse, int iDb){
static void renameReloadSchema(Parse *pParse, int iDb, u16 p5){
  Vdbe *v = pParse->pVdbe;
  if( v ){
    sqlite3ChangeCookie(pParse, iDb);
    sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, iDb, 0);
    if( iDb!=1 ) sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, 1, 0);
    sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, iDb, 0, p5);
    if( iDb!=1 ) sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, 1, 0, p5);
  }
}

/*
** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy" 
** command. 
*/
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
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







-

-








-








-
+
+
+
+








-
+


-
-
+
+



-
+







  Table *pTab;              /* Table being renamed */
  char *zName = 0;          /* NULL-terminated version of pName */ 
  sqlite3 *db = pParse->db; /* Database connection */
  int nTabName;             /* Number of UTF-8 characters in zTabName */
  const char *zTabName;     /* Original name of the table */
  Vdbe *v;
  VTable *pVTab = 0;        /* Non-zero if this is a v-tab with an xRename() */
  u32 savedDbFlags;         /* Saved value of db->mDbFlags */

  savedDbFlags = db->mDbFlags;  
  if( NEVER(db->mallocFailed) ) goto exit_rename_table;
  assert( pSrc->nSrc==1 );
  assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );

  pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
  if( !pTab ) goto exit_rename_table;
  iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
  zDb = db->aDb[iDb].zDbSName;
  db->mDbFlags |= DBFLAG_PreferBuiltin;

  /* Get a NULL terminated version of the new table name. */
  zName = sqlite3NameFromToken(db, pName);
  if( !zName ) goto exit_rename_table;

  /* Check that a table or index named 'zName' does not already exist
  ** in database iDb. If so, this is an error.
  */
  if( sqlite3FindTable(db, zName, zDb) || sqlite3FindIndex(db, zName, zDb) ){
  if( sqlite3FindTable(db, zName, zDb)
   || sqlite3FindIndex(db, zName, zDb)
   || sqlite3IsShadowTableOf(db, pTab, zName)
  ){
    sqlite3ErrorMsg(pParse, 
        "there is already another table or index with this name: %s", zName);
    goto exit_rename_table;
  }

  /* Make sure it is not a system table being altered, or a reserved name
  ** that the table is being renamed to.
  */
  if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ){
  if( SQLITE_OK!=isAlterableTable(pParse, pTab) ){
    goto exit_rename_table;
  }
  if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ goto
    exit_rename_table;
  if( SQLITE_OK!=sqlite3CheckObjectName(pParse,zName,"table",zName) ){
    goto exit_rename_table;
  }

#ifndef SQLITE_OMIT_VIEW
  if( pTab->pSelect ){
  if( IsView(pTab) ){
    sqlite3ErrorMsg(pParse, "view %s may not be altered", pTab->zName);
    goto exit_rename_table;
  }
#endif

#ifndef SQLITE_OMIT_AUTHORIZATION
  /* Invoke the authorization callback. */
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
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







-
-
-
-
+
+
+
+
-




+








-
+


-
-
+
+


-
+


-
+



+
-
+




-
+




















-
+



-
+















-



-
-
+
+




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







    pVTab = sqlite3GetVTable(db, pTab);
    if( pVTab->pVtab->pModule->xRename==0 ){
      pVTab = 0;
    }
  }
#endif

  /* Begin a transaction for database iDb. 
  ** Then modify the schema cookie (since the ALTER TABLE modifies the
  ** schema). Open a statement transaction if the table is a virtual
  ** table.
  /* Begin a transaction for database iDb. Then modify the schema cookie
  ** (since the ALTER TABLE modifies the schema). Call sqlite3MayAbort(),
  ** as the scalar functions (e.g. sqlite_rename_table()) invoked by the 
  ** nested SQL may raise an exception.  */
  */
  v = sqlite3GetVdbe(pParse);
  if( v==0 ){
    goto exit_rename_table;
  }
  sqlite3MayAbort(pParse);

  /* figure out how many UTF-8 characters are in zName */
  zTabName = pTab->zName;
  nTabName = sqlite3Utf8CharLen(zTabName, -1);

  /* Rewrite all CREATE TABLE, INDEX, TRIGGER or VIEW statements in
  ** the schema to use the new table name.  */
  sqlite3NestedParse(pParse, 
      "UPDATE \"%w\".%s SET "
      "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET "
      "sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, %d) "
      "WHERE (type!='index' OR tbl_name=%Q COLLATE nocase)"
      "AND   name NOT LIKE 'sqlite_%%'"
      , zDb, MASTER_NAME, zDb, zTabName, zName, (iDb==1), zTabName
      "AND   name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
      , zDb, zDb, zTabName, zName, (iDb==1), zTabName
  );

  /* Update the tbl_name and name columns of the sqlite_master table
  /* Update the tbl_name and name columns of the sqlite_schema table
  ** as required.  */
  sqlite3NestedParse(pParse,
      "UPDATE %Q.%s SET "
      "UPDATE %Q." LEGACY_SCHEMA_TABLE " SET "
          "tbl_name = %Q, "
          "name = CASE "
            "WHEN type='table' THEN %Q "
            "WHEN name LIKE 'sqliteX_autoindex%%' ESCAPE 'X' "
            "WHEN name LIKE 'sqlite_autoindex%%' AND type='index' THEN "
            "     AND type='index' THEN "
             "'sqlite_autoindex_' || %Q || substr(name,%d+18) "
            "ELSE name END "
      "WHERE tbl_name=%Q COLLATE nocase AND "
          "(type='table' OR type='index' OR type='trigger');", 
      zDb, MASTER_NAME, 
      zDb,
      zName, zName, zName, 
      nTabName, zTabName
  );

#ifndef SQLITE_OMIT_AUTOINCREMENT
  /* If the sqlite_sequence table exists in this database, then update 
  ** it with the new table name.
  */
  if( sqlite3FindTable(db, "sqlite_sequence", zDb) ){
    sqlite3NestedParse(pParse,
        "UPDATE \"%w\".sqlite_sequence set name = %Q WHERE name = %Q",
        zDb, zName, pTab->zName);
  }
#endif

  /* If the table being renamed is not itself part of the temp database,
  ** edit view and trigger definitions within the temp database 
  ** as required.  */
  if( iDb!=1 ){
    sqlite3NestedParse(pParse, 
        "UPDATE sqlite_temp_master SET "
        "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) "
              "  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
  ** of any resources used by the v-table implementation (including other
  ** SQLite tables) that are identified by the name of the virtual table.
  */
#ifndef SQLITE_OMIT_VIRTUALTABLE
  if( pVTab ){
    int i = ++pParse->nMem;
    sqlite3VdbeLoadString(v, i, zName);
    sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB);
    sqlite3MayAbort(pParse);
  }
#endif

  renameReloadSchema(pParse, iDb);
  renameTestSchema(pParse, zDb, iDb==1);
  renameReloadSchema(pParse, iDb, INITFLAG_AlterRename);
  renameTestSchema(pParse, zDb, iDb==1, "after rename", 0);

exit_rename_table:
  sqlite3SrcListDelete(db, pSrc);
  sqlite3DbFree(db, zName);
}
  db->mDbFlags = savedDbFlags;

/*
** Write code that will raise an error if the table described by
** zDb and zTab is not empty.
*/
static void sqlite3ErrorIfNotEmpty(
  Parse *pParse,        /* Parsing context */
  const char *zDb,      /* Schema holding the table */
  const char *zTab,     /* Table to check for empty */
  const char *zErr      /* Error message text */
){
  sqlite3NestedParse(pParse,
     "SELECT raise(ABORT,%Q) FROM \"%w\".\"%w\"",
     zErr, zDb, zTab
  );
}

/*
** This function is called after an "ALTER TABLE ... ADD" statement
** has been parsed. Argument pColDef contains the text of the new
** column definition.
**
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
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







+
-
+
+








-
+










-
-
-
-
-
-
-
-










-
+
+


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

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





-



-
+
+
+
+

-
-
+
+
+

-
+



-


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








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







  Column *pCol;             /* The new column */
  Expr *pDflt;              /* Default value for the new column */
  sqlite3 *db;              /* The database connection; */
  Vdbe *v;                  /* The prepared statement under construction */
  int r1;                   /* Temporary registers */

  db = pParse->db;
  assert( db->pParse==pParse );
  if( pParse->nErr || db->mallocFailed ) return;
  if( pParse->nErr ) return;
  assert( db->mallocFailed==0 );
  pNew = pParse->pNewTable;
  assert( pNew );

  assert( sqlite3BtreeHoldsAllMutexes(db) );
  iDb = sqlite3SchemaToIndex(db, pNew->pSchema);
  zDb = db->aDb[iDb].zDbSName;
  zTab = &pNew->zName[16];  /* Skip the "sqlite_altertab_" prefix on the name */
  pCol = &pNew->aCol[pNew->nCol-1];
  pDflt = pCol->pDflt;
  pDflt = sqlite3ColumnExpr(pNew, pCol);
  pTab = sqlite3FindTable(db, zTab, zDb);
  assert( pTab );

#ifndef SQLITE_OMIT_AUTHORIZATION
  /* Invoke the authorization callback. */
  if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){
    return;
  }
#endif

  /* If the default value for the new column was specified with a 
  ** literal NULL, then set pDflt to 0. This simplifies checking
  ** for an SQL NULL default below.
  */
  assert( pDflt==0 || pDflt->op==TK_SPAN );
  if( pDflt && pDflt->pLeft->op==TK_NULL ){
    pDflt = 0;
  }

  /* Check that the new column is not specified as PRIMARY KEY or UNIQUE.
  ** If there is a NOT NULL constraint, then the default value for the
  ** column must not be NULL.
  */
  if( pCol->colFlags & COLFLAG_PRIMKEY ){
    sqlite3ErrorMsg(pParse, "Cannot add a PRIMARY KEY column");
    return;
  }
  if( pNew->pIndex ){
    sqlite3ErrorMsg(pParse, "Cannot add a UNIQUE column");
    sqlite3ErrorMsg(pParse,
         "Cannot add a UNIQUE column");
    return;
  }
  if( (pCol->colFlags & COLFLAG_GENERATED)==0 ){
    /* If the default value for the new column was specified with a 
    ** literal NULL, then set pDflt to 0. This simplifies checking
    ** for an SQL NULL default below.
    */
    assert( pDflt==0 || pDflt->op==TK_SPAN );
    if( pDflt && pDflt->pLeft->op==TK_NULL ){
      pDflt = 0;
    }
    assert( IsOrdinaryTable(pNew) );
  if( (db->flags&SQLITE_ForeignKeys) && pNew->pFKey && pDflt ){
    sqlite3ErrorMsg(pParse, 
        "Cannot add a REFERENCES column with non-NULL default value");
    if( (db->flags&SQLITE_ForeignKeys) && pNew->u.tab.pFKey && pDflt ){
      sqlite3ErrorIfNotEmpty(pParse, zDb, zTab,
          "Cannot add a REFERENCES column with non-NULL default value");
    return;
  }
  if( pCol->notNull && !pDflt ){
    sqlite3ErrorMsg(pParse, 
        "Cannot add a NOT NULL column with default value NULL");
    }
    if( pCol->notNull && !pDflt ){
      sqlite3ErrorIfNotEmpty(pParse, zDb, zTab,
          "Cannot add a NOT NULL column with default value NULL");
    return;
  }
    }


  /* Ensure the default expression is something that sqlite3ValueFromExpr()
  ** can handle (i.e. not CURRENT_TIME etc.)
  */
  if( pDflt ){
    sqlite3_value *pVal = 0;
    int rc;
    rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_BLOB, &pVal);
    assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
    if( rc!=SQLITE_OK ){
      assert( db->mallocFailed == 1 );
      return;
    }
    if( !pVal ){
      sqlite3ErrorMsg(pParse, "Cannot add a column with non-constant default");
    /* Ensure the default expression is something that sqlite3ValueFromExpr()
    ** can handle (i.e. not CURRENT_TIME etc.)
    */
    if( pDflt ){
      sqlite3_value *pVal = 0;
      int rc;
      rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_BLOB, &pVal);
      assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
      if( rc!=SQLITE_OK ){
        assert( db->mallocFailed == 1 );
        return;
      }
      if( !pVal ){
        sqlite3ErrorIfNotEmpty(pParse, zDb, zTab,
           "Cannot add a column with non-constant default");
      return;
    }
    sqlite3ValueFree(pVal);
  }
      }
      sqlite3ValueFree(pVal);
    }
  }else if( pCol->colFlags & COLFLAG_STORED ){
    sqlite3ErrorIfNotEmpty(pParse, zDb, zTab, "cannot add a STORED column");
  }


  /* Modify the CREATE TABLE statement. */
  zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n);
  if( zCol ){
    char *zEnd = &zCol[pColDef->n-1];
    u32 savedDbFlags = db->mDbFlags;
    while( zEnd>zCol && (*zEnd==';' || sqlite3Isspace(*zEnd)) ){
      *zEnd-- = '\0';
    }
    db->mDbFlags |= DBFLAG_PreferBuiltin;
    /* substr() operations on characters, but addColOffset is in bytes. So we
    ** have to use printf() to translate between these units: */
    assert( IsOrdinaryTable(pTab) );
    assert( IsOrdinaryTable(pNew) );
    sqlite3NestedParse(pParse, 
        "UPDATE \"%w\".%s SET "
          "sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d) "
        "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET "
          "sql = printf('%%.%ds, ',sql) || %Q"
          " || substr(sql,1+length(printf('%%.%ds',sql))) "
        "WHERE type = 'table' AND name = %Q", 
      zDb, MASTER_NAME, pNew->addColOffset, zCol, pNew->addColOffset+1,
      zDb, pNew->u.tab.addColOffset, zCol, pNew->u.tab.addColOffset,
      zTab
    );
    sqlite3DbFree(db, zCol);
    db->mDbFlags = savedDbFlags;
  }

  v = sqlite3GetVdbe(pParse);
  if( v ){
  /* Make sure the schema version is at least 3.  But do not upgrade
  ** from less than 3 to 4, as that will corrupt any preexisting DESC
  ** index.
  */
    /* Make sure the schema version is at least 3.  But do not upgrade
    ** from less than 3 to 4, as that will corrupt any preexisting DESC
    ** index.
    */
  v = sqlite3GetVdbe(pParse);
  if( v ){
    r1 = sqlite3GetTempReg(pParse);
    sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT);
    sqlite3VdbeUsesBtree(v, iDb);
    sqlite3VdbeAddOp2(v, OP_AddImm, r1, -2);
    sqlite3VdbeAddOp2(v, OP_IfPos, r1, sqlite3VdbeCurrentAddr(v)+2);
    VdbeCoverage(v);
    sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, 3);
    sqlite3ReleaseTempReg(pParse, r1);
  }


  /* Reload the table definition */
  renameReloadSchema(pParse, iDb);
    /* Reload the table definition */
    renameReloadSchema(pParse, iDb, INITFLAG_AlterAdd);

    /* Verify that constraints are still satisfied */
    if( pNew->pCheck!=0
     || (pCol->notNull && (pCol->colFlags & COLFLAG_GENERATED)!=0)
    ){
      sqlite3NestedParse(pParse,
        "SELECT CASE WHEN quick_check GLOB 'CHECK*'"
        " THEN raise(ABORT,'CHECK constraint failed')"
        " ELSE raise(ABORT,'NOT NULL constraint failed')"
        " END"
        "  FROM pragma_quick_check(%Q,%Q)"
        " WHERE quick_check GLOB 'CHECK*' OR quick_check GLOB 'NULL*'",
        zTab, zDb
      );
    }
  }
}

/*
** This function is called by the parser after the table-name in
** an "ALTER TABLE <table-name> ADD" statement is parsed. Argument 
** pSrc is the full-name of the table being altered.
**
416
417
418
419
420
421
422
423

424
425
426
427

428
429
430


431

432
433
434
435
436
437
438
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







-
+



-
+



+
+
-
+







  if( IsVirtual(pTab) ){
    sqlite3ErrorMsg(pParse, "virtual tables may not be altered");
    goto exit_begin_add_column;
  }
#endif

  /* Make sure this is not an attempt to ALTER a view. */
  if( pTab->pSelect ){
  if( IsView(pTab) ){
    sqlite3ErrorMsg(pParse, "Cannot add a column to a view");
    goto exit_begin_add_column;
  }
  if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ){
  if( SQLITE_OK!=isAlterableTable(pParse, pTab) ){
    goto exit_begin_add_column;
  }

  sqlite3MayAbort(pParse);
  assert( IsOrdinaryTable(pTab) );
  assert( pTab->addColOffset>0 );
  assert( pTab->u.tab.addColOffset>0 );
  iDb = sqlite3SchemaToIndex(db, pTab->pSchema);

  /* Put a copy of the Table struct in Parse.pNewTable for the
  ** sqlite3AddColumn() function and friends to modify.  But modify
  ** the name by adding an "sqlite_altertab_" prefix.  By adding this
  ** prefix, we insure that the name will not collide with an existing
  ** table because user table are not allowed to have the "sqlite_"
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
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







-
-
+
+
-

+
+

-
+
















-
+


-
+









-
-
+
+
+






-
+







  if( !pNew->aCol || !pNew->zName ){
    assert( db->mallocFailed );
    goto exit_begin_add_column;
  }
  memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol);
  for(i=0; i<pNew->nCol; i++){
    Column *pCol = &pNew->aCol[i];
    pCol->zName = sqlite3DbStrDup(db, pCol->zName);
    pCol->zColl = 0;
    pCol->zCnName = sqlite3DbStrDup(db, pCol->zCnName);
    pCol->hName = sqlite3StrIHash(pCol->zCnName);
    pCol->pDflt = 0;
  }
  assert( IsOrdinaryTable(pNew) );
  pNew->u.tab.pDfltList = sqlite3ExprListDup(db, pTab->u.tab.pDfltList, 0);
  pNew->pSchema = db->aDb[iDb].pSchema;
  pNew->addColOffset = pTab->addColOffset;
  pNew->u.tab.addColOffset = pTab->u.tab.addColOffset;
  pNew->nTabRef = 1;

exit_begin_add_column:
  sqlite3SrcListDelete(db, pSrc);
  return;
}

/*
** Parameter pTab is the subject of an ALTER TABLE ... RENAME COLUMN
** command. This function checks if the table is a view or virtual
** table (columns of views or virtual tables may not be renamed). If so,
** it loads an error message into pParse and returns non-zero.
**
** Or, if pTab is not a view or virtual table, zero is returned.
*/
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
static int isRealTable(Parse *pParse, Table *pTab){
static int isRealTable(Parse *pParse, Table *pTab, int bDrop){
  const char *zType = 0;
#ifndef SQLITE_OMIT_VIEW
  if( pTab->pSelect ){
  if( IsView(pTab) ){
    zType = "view";
  }
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
  if( IsVirtual(pTab) ){
    zType = "virtual table";
  }
#endif
  if( zType ){
    sqlite3ErrorMsg(
        pParse, "cannot rename columns of %s \"%s\"", zType, pTab->zName
    sqlite3ErrorMsg(pParse, "cannot %s %s \"%s\"", 
        (bDrop ? "drop column from" : "rename columns of"),
        zType, pTab->zName
    );
    return 1;
  }
  return 0;
}
#else /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */
# define isRealTable(x,y) (0)
# define isRealTable(x,y,z) (0)
#endif

/*
** Handles the following parser reduction:
**
**  cmd ::= ALTER TABLE pSrc RENAME COLUMN pOld TO pNew
*/
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
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







-
-
+
+


















-
+


-
+


+
+
+
+



-
+

+





-
+

-
-
-
+
+
+





-
+


-




-
-
+
+







  int bQuote;                     /* True to quote the new name */

  /* Locate the table to be altered */
  pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
  if( !pTab ) goto exit_rename_column;

  /* Cannot alter a system table */
  if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ) goto exit_rename_column;
  if( SQLITE_OK!=isRealTable(pParse, pTab) ) goto exit_rename_column;
  if( SQLITE_OK!=isAlterableTable(pParse, pTab) ) goto exit_rename_column;
  if( SQLITE_OK!=isRealTable(pParse, pTab, 0) ) goto exit_rename_column;

  /* Which schema holds the table to be altered */  
  iSchema = sqlite3SchemaToIndex(db, pTab->pSchema);
  assert( iSchema>=0 );
  zDb = db->aDb[iSchema].zDbSName;

#ifndef SQLITE_OMIT_AUTHORIZATION
  /* Invoke the authorization callback. */
  if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){
    goto exit_rename_column;
  }
#endif

  /* Make sure the old name really is a column name in the table to be
  ** altered.  Set iCol to be the index of the column being renamed */
  zOld = sqlite3NameFromToken(db, pOld);
  if( !zOld ) goto exit_rename_column;
  for(iCol=0; iCol<pTab->nCol; iCol++){
    if( 0==sqlite3StrICmp(pTab->aCol[iCol].zName, zOld) ) break;
    if( 0==sqlite3StrICmp(pTab->aCol[iCol].zCnName, zOld) ) break;
  }
  if( iCol==pTab->nCol ){
    sqlite3ErrorMsg(pParse, "no such column: \"%s\"", zOld);
    sqlite3ErrorMsg(pParse, "no such column: \"%T\"", pOld);
    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_master table.
  ** CREATE statement text for the sqlite_schema table.
  */
  sqlite3MayAbort(pParse);
  zNew = sqlite3NameFromToken(db, pNew);
  if( !zNew ) goto exit_rename_column;
  assert( pNew->n>0 );
  bQuote = sqlite3Isquote(pNew->z[0]);
  sqlite3NestedParse(pParse, 
      "UPDATE \"%w\".%s SET "
      "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET "
      "sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, %d) "
      "WHERE name NOT LIKE 'sqlite_%%' AND (type != 'index' OR tbl_name = %Q)"
      " AND sql NOT LIKE 'create virtual%%'",
      zDb, MASTER_NAME, 
      "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X' "
      " AND (type != 'index' OR tbl_name = %Q)",
      zDb,
      zDb, pTab->zName, iCol, zNew, bQuote, iSchema==1,
      pTab->zName
  );

  sqlite3NestedParse(pParse, 
      "UPDATE temp.%s SET "
      "UPDATE temp." LEGACY_SCHEMA_TABLE " SET "
      "sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, 1) "
      "WHERE type IN ('trigger', 'view')",
      MASTER_NAME, 
      zDb, pTab->zName, iCol, zNew, bQuote
  );

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

 exit_rename_column:
  sqlite3SrcListDelete(db, pSrc);
  sqlite3DbFree(db, zOld);
  sqlite3DbFree(db, zNew);
  return;
}
604
605
606
607
608
609
610
611

612
613
614
615
616
617
618
690
691
692
693
694
695
696

697
698
699
700
701
702
703
704







-
+







** routine is used to keep the mapping current.
**
** After the parse finishes, renameTokenFind() routine can be used
** to look up the actual token value that created some element in
** the parse tree.
*/
struct RenameToken {
  void *p;               /* Parse tree element created by token t */
  const void *p;         /* Parse tree element created by token t */
  Token t;               /* The token that created parse tree element p */
  RenameToken *pNext;    /* Next is a list of all RenameToken objects */
};

/*
** The context of an ALTER TABLE RENAME COLUMN operation that gets passed
** down into the Walker.
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
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
732
733
734
735
736
737
738




739
740
741
742
743
744
745
746
747

748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769

770
771
772
773
774
775
776
777
778






779
780
781
782
783
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953



954
955
956
957
958
959
960
961
962

963
964
965
966

967
968
969
970
971
972
973




974
975
976
977


978



979














980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002







-
-
-
-
+
+
+
+
+
+



-
+


+


















-
+
+
+
+
+



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










-
+















-
+
+
+
+




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



+




+
+

+















+
-
+
+


















-
-
-
+
+
+
+
+
+

+
+
-
+
+
+

-
+
+
+



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


+








+
+
+
+
+







**
**     sqlite3_free(x);
**     if( x==y ) ...
**
** Technically, as x no longer points into a valid object or to the byte
** following a valid object, it may not be used in comparison operations.
*/
static void renameTokenCheckAll(Parse *pParse, void *pPtr){
  if( pParse->nErr==0 && pParse->db->mallocFailed==0 ){
    RenameToken *p;
    u8 i = 0;
static void renameTokenCheckAll(Parse *pParse, const void *pPtr){
  assert( pParse==pParse->db->pParse );
  assert( pParse->db->mallocFailed==0 || pParse->nErr!=0 );
  if( pParse->nErr==0 ){
    const RenameToken *p;
    u32 i = 1;
    for(p=pParse->pRename; p; p=p->pNext){
      if( p->p ){
        assert( p->p!=pPtr );
        i += *(u8*)(p->p);
        i += *(u8*)(p->p) | 1;
      }
    }
    assert( i>0 );
  }
}
#else
# define renameTokenCheckAll(x,y)
#endif

/*
** Remember that the parser tree element pPtr was created using
** the token pToken.
**
** In other words, construct a new RenameToken object and add it
** to the list of RenameToken objects currently being built up
** in pParse->pRename.
**
** The pPtr argument is returned so that this routine can be used
** with tail recursion in tokenExpr() routine, for a small performance
** improvement.
*/
void *sqlite3RenameTokenMap(Parse *pParse, void *pPtr, Token *pToken){
const void *sqlite3RenameTokenMap(
  Parse *pParse,
  const void *pPtr,
  const Token *pToken
){
  RenameToken *pNew;
  assert( pPtr || pParse->db->mallocFailed );
  renameTokenCheckAll(pParse, pPtr);
  if( ALWAYS(pParse->eParseMode!=PARSE_MODE_UNMAP) ){
  pNew = sqlite3DbMallocZero(pParse->db, sizeof(RenameToken));
  if( pNew ){
    pNew->p = pPtr;
    pNew->t = *pToken;
    pNew->pNext = pParse->pRename;
    pParse->pRename = pNew;
    pNew = sqlite3DbMallocZero(pParse->db, sizeof(RenameToken));
    if( pNew ){
      pNew->p = pPtr;
      pNew->t = *pToken;
      pNew->pNext = pParse->pRename;
      pParse->pRename = pNew;
    }
  }

  return pPtr;
}

/*
** It is assumed that there is already a RenameToken object associated
** with parse tree element pFrom. This function remaps the associated token
** to parse tree element pTo.
*/
void sqlite3RenameTokenRemap(Parse *pParse, void *pTo, void *pFrom){
void sqlite3RenameTokenRemap(Parse *pParse, const void *pTo, const void *pFrom){
  RenameToken *p;
  renameTokenCheckAll(pParse, pTo);
  for(p=pParse->pRename; p; p=p->pNext){
    if( p->p==pFrom ){
      p->p = pTo;
      break;
    }
  }
}

/*
** Walker callback used by sqlite3RenameExprUnmap().
*/
static int renameUnmapExprCb(Walker *pWalker, Expr *pExpr){
  Parse *pParse = pWalker->pParse;
  sqlite3RenameTokenRemap(pParse, 0, (void*)pExpr);
  sqlite3RenameTokenRemap(pParse, 0, (const void*)pExpr);
  if( ExprUseYTab(pExpr) ){
    sqlite3RenameTokenRemap(pParse, 0, (const void*)&pExpr->y.pTab);
  }
  return WRC_Continue;
}

/*
** Iterate through the Select objects that are part of WITH clauses attached
** to select statement pSelect.
*/
static void renameWalkWith(Walker *pWalker, Select *pSelect){
  With *pWith = pSelect->pWith;
  if( pWith ){
    Parse *pParse = pWalker->pParse;
    int i;
    With *pCopy = 0;
    assert( pWith->nCte>0 );
    if( (pWith->a[0].pSelect->selFlags & SF_Expanded)==0 ){
      /* Push a copy of the With object onto the with-stack. We use a copy
      ** here as the original will be expanded and resolved (flags SF_Expanded
      ** and SF_Resolved) below. And the parser code that uses the with-stack
      ** fails if the Select objects on it have already been expanded and
      ** resolved.  */
      pCopy = sqlite3WithDup(pParse->db, pWith);
      pCopy = sqlite3WithPush(pParse, pCopy, 1);
    }
    for(i=0; i<pWith->nCte; i++){
      Select *p = pWith->a[i].pSelect;
      NameContext sNC;
      memset(&sNC, 0, sizeof(sNC));
      sNC.pParse = pParse;
      if( pCopy ) sqlite3SelectPrep(sNC.pParse, p, &sNC);
      if( sNC.pParse->db->mallocFailed ) return;
      sqlite3WalkSelect(pWalker, p);
      sqlite3RenameExprlistUnmap(pParse, pWith->a[i].pCols);
    }
    if( pCopy && pParse->pWith==pCopy ){
      pParse->pWith = pCopy->pOuter;
    }
  }
}

/*
** Unmap all tokens in the IdList object passed as the second argument.
*/
static void unmapColumnIdlistNames(
  Parse *pParse,
  const IdList *pIdList
){
  int ii;
  assert( pIdList!=0 );
  for(ii=0; ii<pIdList->nId; ii++){
    sqlite3RenameTokenRemap(pParse, 0, (const void*)pIdList->a[ii].zName);
  }
}

/*
** Walker callback used by sqlite3RenameExprUnmap().
*/
static int renameUnmapSelectCb(Walker *pWalker, Select *p){
  Parse *pParse = pWalker->pParse;
  int i;
  if( pParse->nErr ) return WRC_Abort;
  testcase( p->selFlags & SF_View );
  testcase( p->selFlags & SF_CopyCte );
  if( p->selFlags & (SF_View|SF_CopyCte) ){
    return WRC_Prune;
  }
  if( ALWAYS(p->pEList) ){
    ExprList *pList = p->pEList;
    for(i=0; i<pList->nExpr; i++){
      if( pList->a[i].zEName && pList->a[i].fg.eEName==ENAME_NAME ){
        sqlite3RenameTokenRemap(pParse, 0, (void*)pList->a[i].zEName);
      }
    }
  }
  if( ALWAYS(p->pSrc) ){  /* Every Select as a SrcList, even if it is empty */
    SrcList *pSrc = p->pSrc;
    for(i=0; i<pSrc->nSrc; i++){
      sqlite3RenameTokenRemap(pParse, 0, (void*)pSrc->a[i].zName);
      if( pSrc->a[i].fg.isUsing==0 ){
        sqlite3WalkExpr(pWalker, pSrc->a[i].u3.pOn);
      }else{
        unmapColumnIdlistNames(pParse, pSrc->a[i].u3.pUsing);
      }
    }
  }

  renameWalkWith(pWalker, p);
  return WRC_Continue;
}

/*
** Remove all nodes that are part of expression pExpr from the rename list.
*/
void sqlite3RenameExprUnmap(Parse *pParse, Expr *pExpr){
  u8 eMode = pParse->eParseMode;
  Walker sWalker;
  memset(&sWalker, 0, sizeof(Walker));
  sWalker.pParse = pParse;
  sWalker.xExprCallback = renameUnmapExprCb;
  sWalker.xSelectCallback = renameUnmapSelectCb;
  pParse->eParseMode = PARSE_MODE_UNMAP;
  sqlite3WalkExpr(&sWalker, pExpr);
  pParse->eParseMode = eMode;
}

/*
** Remove all nodes that are part of expression-list pEList from the 
** rename list.
*/
void sqlite3RenameExprlistUnmap(Parse *pParse, ExprList *pEList){
  if( pEList ){
    int i;
    Walker sWalker;
    memset(&sWalker, 0, sizeof(Walker));
    sWalker.pParse = pParse;
    sWalker.xExprCallback = renameUnmapExprCb;
    sqlite3WalkExprList(&sWalker, pEList);
    for(i=0; i<pEList->nExpr; i++){
      if( ALWAYS(pEList->a[i].fg.eEName==ENAME_NAME) ){
      sqlite3RenameTokenRemap(pParse, 0, (void*)pEList->a[i].zName);
        sqlite3RenameTokenRemap(pParse, 0, (void*)pEList->a[i].zEName);
      }
    }
  }
}

/*
** Free the list of RenameToken objects given in the second argument
*/
static void renameTokenFree(sqlite3 *db, RenameToken *pToken){
  RenameToken *pNext;
  RenameToken *p;
  for(p=pToken; p; p=pNext){
    pNext = p->pNext;
    sqlite3DbFree(db, p);
  }
}

/*
** Search the Parse object passed as the first argument for a RenameToken
** object associated with parse tree element pPtr. If found, remove it
** from the Parse object and add it to the list maintained by the
** RenameCtx object passed as the second argument.
** object associated with parse tree element pPtr. If found, return a pointer
** to it. Otherwise, return NULL.
**
** If the second argument passed to this function is not NULL and a matching
** RenameToken object is found, remove it from the Parse object and add it to
** the list maintained by the RenameCtx object.
*/
static RenameToken *renameTokenFind(
  Parse *pParse, 
static void renameTokenFind(Parse *pParse, struct RenameCtx *pCtx, void *pPtr){
  struct RenameCtx *pCtx, 
  const 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;
      pCtx->nList++;
        *pp = pToken->pNext;
        pToken->pNext = pCtx->pList;
        pCtx->pList = pToken;
        pCtx->nList++;
      break;
    }
      }
  }
}

      return pToken;
/*
** Iterate through the Select objects that are part of WITH clauses attached
** to select statement pSelect.
*/
static void renameWalkWith(Walker *pWalker, Select *pSelect){
  if( pSelect->pWith ){
    int i;
    for(i=0; i<pSelect->pWith->nCte; i++){
      Select *p = pSelect->pWith->a[i].pSelect;
      NameContext sNC;
      memset(&sNC, 0, sizeof(sNC));
      sNC.pParse = pWalker->pParse;
      sqlite3SelectPrep(sNC.pParse, p, &sNC);
      sqlite3WalkSelect(pWalker, p);
    }
  }
  return 0;
}

/*
** This is a Walker select callback. It does nothing. It is only required
** because without a dummy callback, sqlite3WalkExpr() and similar do not
** descend into sub-select statements.
*/
static int renameColumnSelectCb(Walker *pWalker, Select *p){
  if( p->selFlags & (SF_View|SF_CopyCte) ){
    testcase( p->selFlags & SF_View );
    testcase( p->selFlags & SF_CopyCte );
    return WRC_Prune;
  }
  renameWalkWith(pWalker, p);
  return WRC_Continue;
}

/*
** This is a Walker expression callback.
**
821
822
823
824
825
826
827
828


829
830
831
832
833
834
835
1010
1011
1012
1013
1014
1015
1016

1017
1018
1019
1020
1021
1022
1023
1024
1025







-
+
+







  RenameCtx *p = pWalker->u.pRename;
  if( pExpr->op==TK_TRIGGER 
   && pExpr->iColumn==p->iCol 
   && pWalker->pParse->pTriggerTab==p->pTab
  ){
    renameTokenFind(pWalker->pParse, p, (void*)pExpr);
  }else if( pExpr->op==TK_COLUMN 
   && pExpr->iColumn==p->iCol 
   && pExpr->iColumn==p->iCol
   && ALWAYS(ExprUseYTab(pExpr))
   && p->pTab==pExpr->y.pTab
  ){
    renameTokenFind(pWalker->pParse, p, (void*)pExpr);
  }
  return WRC_Continue;
}

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
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
935
936
937
938
939
940
941
942
943
944
945
946








947
948
949
950
951


952
953
954

955
956
957
958
959
960
961

962
963
964
965
966
967
968
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







-
+








-
-
+
+



-
+











-
+





-
-
-
+
+
+
+
+
+













-
+





-
+

-
+




+








-





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


-
+
-
-
-
-


-
+







** object (either pParse->pNewTable, pNewIndex or pNewTrigger) as part of an
** ALTER TABLE RENAME COLUMN program. The error message emitted by the
** sub-routine is currently stored in pParse->zErrMsg. This function
** adds context to the error message and then stores it in pCtx.
*/
static void renameColumnParseError(
  sqlite3_context *pCtx, 
  int bPost,
  const char *zWhen,
  sqlite3_value *pType,
  sqlite3_value *pObject,
  Parse *pParse
){
  const char *zT = (const char*)sqlite3_value_text(pType);
  const char *zN = (const char*)sqlite3_value_text(pObject);
  char *zErr;

  zErr = sqlite3_mprintf("error in %s %s%s: %s", 
      zT, zN, (bPost ? " after rename" : ""),
  zErr = sqlite3MPrintf(pParse->db, "error in %s %s%s%s: %s", 
      zT, zN, (zWhen[0] ? " " : ""), zWhen,
      pParse->zErrMsg
  );
  sqlite3_result_error(pCtx, zErr, -1);
  sqlite3_free(zErr);
  sqlite3DbFree(pParse->db, zErr);
}

/*
** For each name in the the expression-list pEList (i.e. each
** pEList->a[i].zName) that matches the string in zOld, extract the 
** corresponding rename-token from Parse object pParse and add it
** to the RenameCtx pCtx.
*/
static void renameColumnElistNames(
  Parse *pParse, 
  RenameCtx *pCtx, 
  ExprList *pEList, 
  const ExprList *pEList, 
  const char *zOld
){
  if( pEList ){
    int i;
    for(i=0; i<pEList->nExpr; i++){
      char *zName = pEList->a[i].zName;
      if( 0==sqlite3_stricmp(zName, zOld) ){
        renameTokenFind(pParse, pCtx, (void*)zName);
      const char *zName = pEList->a[i].zEName;
      if( ALWAYS(pEList->a[i].fg.eEName==ENAME_NAME)
       && ALWAYS(zName!=0)
       && 0==sqlite3_stricmp(zName, zOld)
      ){
        renameTokenFind(pParse, pCtx, (const void*)zName);
      }
    }
  }
}

/*
** For each name in the the id-list pIdList (i.e. each pIdList->a[i].zName) 
** that matches the string in zOld, extract the corresponding rename-token 
** from Parse object pParse and add it to the RenameCtx pCtx.
*/
static void renameColumnIdlistNames(
  Parse *pParse, 
  RenameCtx *pCtx, 
  IdList *pIdList, 
  const IdList *pIdList, 
  const char *zOld
){
  if( pIdList ){
    int i;
    for(i=0; i<pIdList->nId; i++){
      char *zName = pIdList->a[i].zName;
      const char *zName = pIdList->a[i].zName;
      if( 0==sqlite3_stricmp(zName, zOld) ){
        renameTokenFind(pParse, pCtx, (void*)zName);
        renameTokenFind(pParse, pCtx, (const void*)zName);
      }
    }
  }
}


/*
** Parse the SQL statement zSql using Parse object (*p). The Parse object
** 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 */
  int bTable,                     /* 1 -> RENAME TABLE, 0 -> RENAME COLUMN */
  sqlite3 *db,                    /* Database handle */
  const char *zSql,               /* SQL to parse */
  int bTemp                       /* True if SQL is from temp schema */
){
  int rc;
  char *zErr = 0;

  db->init.iDb = bTemp ? 1 : sqlite3FindDbName(db, zDb);


  sqlite3ParseObjectInit(p, db);
  if( zSql==0 ){
    return SQLITE_NOMEM;
  }
  if( sqlite3StrNICmp(zSql,"CREATE ",7)!=0 ){
    return SQLITE_CORRUPT_BKPT;
  }
  /* 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 = (bTable ? PARSE_MODE_RENAME_TABLE : PARSE_MODE_RENAME_COLUMN);
  db->init.iDb = bTemp ? 1 : sqlite3FindDbName(db, zDb);
  p->eParseMode = PARSE_MODE_RENAME;
  p->db = db;
  p->nQueryLoop = 1;
  rc = sqlite3RunParser(p, zSql, &zErr);
  rc = sqlite3RunParser(p, zSql);
  assert( p->zErrMsg==0 );
  assert( rc!=SQLITE_OK || zErr==0 );
  assert( (0!=p->pNewTable) + (0!=p->pNewIndex) + (0!=p->pNewTrigger)<2 );
  p->zErrMsg = zErr;
  if( db->mallocFailed ) rc = SQLITE_NOMEM;
  if( rc==SQLITE_OK 
   && p->pNewTable==0 && p->pNewIndex==0 && p->pNewTrigger==0 
   && NEVER(p->pNewTable==0 && p->pNewIndex==0 && p->pNewTrigger==0)
  ){
    rc = SQLITE_CORRUPT_BKPT;
  }

#ifdef SQLITE_DEBUG
  /* Ensure that all mappings in the Parse.pRename list really do map to
  ** a part of the input string.  */
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
1046
1047
1048
1049
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







-
-
+
+


-
+

-
+
+
+

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




-
-
+
+
-
-





-
-


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







static int renameEditSql(
  sqlite3_context *pCtx,          /* Return result here */
  RenameCtx *pRename,             /* Rename context */
  const char *zSql,               /* SQL statement to edit */
  const char *zNew,               /* New token text */
  int bQuote                      /* True to always quote token */
){
  int nNew = sqlite3Strlen30(zNew);
  int nSql = sqlite3Strlen30(zSql);
  i64 nNew = sqlite3Strlen30(zNew);
  i64 nSql = sqlite3Strlen30(zSql);
  sqlite3 *db = sqlite3_context_db_handle(pCtx);
  int rc = SQLITE_OK;
  char *zQuot;
  char *zQuot = 0;
  char *zOut;
  int nQuot;
  i64 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)
        );
1066
1067
1068
1069
1070
1071
1072
1073

1074
1075
1076
1077
1078
1079
1080
1281
1282
1283
1284
1285
1286
1287

1288
1289
1290
1291
1292
1293
1294
1295







-
+








/*
** Resolve all symbols in the trigger at pParse->pNewTrigger, assuming
** it was read from the schema of database zDb. Return SQLITE_OK if 
** successful. Otherwise, return an SQLite error code and leave an error
** message in the Parse object.
*/
static int renameResolveTrigger(Parse *pParse, const char *zDb){
static int renameResolveTrigger(Parse *pParse){
  sqlite3 *db = pParse->db;
  Trigger *pNew = pParse->pNewTrigger;
  TriggerStep *pStep;
  NameContext sNC;
  int rc = SQLITE_OK;

  memset(&sNC, 0, sizeof(sNC));
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
1312
1313
1314
1315
1316
1317
1318
1319
1320











1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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







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






-
+

-
-
+















+
+
+
+








  for(pStep=pNew->step_list; rc==SQLITE_OK && pStep; pStep=pStep->pNext){
    if( pStep->pSelect ){
      sqlite3SelectPrep(pParse, pStep->pSelect, &sNC);
      if( pParse->nErr ) rc = pParse->rc;
    }
    if( rc==SQLITE_OK && pStep->zTarget ){
      SrcList *pSrc = sqlite3TriggerStepSrc(pParse, pStep);
      if( pSrc ){
      Table *pTarget = sqlite3LocateTable(pParse, 0, pStep->zTarget, zDb);
      if( pTarget==0 ){
        rc = SQLITE_ERROR;
      }else if( SQLITE_OK==(rc = sqlite3ViewGetColumnNames(pParse, pTarget)) ){
        SrcList sSrc;
        memset(&sSrc, 0, sizeof(sSrc));
        sSrc.nSrc = 1;
        sSrc.a[0].zName = pStep->zTarget;
        sSrc.a[0].pTab = pTarget;
        sNC.pSrcList = &sSrc;
        if( pStep->pWhere ){
        Select *pSel = sqlite3SelectNew(
            pParse, pStep->pExprList, pSrc, 0, 0, 0, 0, 0, 0
        );
        if( pSel==0 ){
          pStep->pExprList = 0;
          pSrc = 0;
          rc = SQLITE_NOMEM;
        }else{
          sqlite3SelectPrep(pParse, pSel, 0);
          rc = pParse->nErr ? SQLITE_ERROR : SQLITE_OK;
          assert( pStep->pExprList==0 || pStep->pExprList==pSel->pEList );
          assert( pSrc==pSel->pSrc );
          if( pStep->pExprList ) pSel->pEList = 0;
          pSel->pSrc = 0;
          sqlite3SelectDelete(db, pSel);
        }
        if( pStep->pFrom ){
          int i;
          for(i=0; i<pStep->pFrom->nSrc && rc==SQLITE_OK; i++){
            SrcItem *p = &pStep->pFrom->a[i];
            if( p->pSelect ){
              sqlite3SelectPrep(pParse, p->pSelect, 0);
            }
          }
        }

        if(  db->mallocFailed ){
          rc = SQLITE_NOMEM;
        }
        sNC.pSrcList = pSrc;
        if( rc==SQLITE_OK && pStep->pWhere ){
          rc = sqlite3ResolveExprNames(&sNC, pStep->pWhere);
        }
        if( rc==SQLITE_OK ){
          rc = sqlite3ResolveExprListNames(&sNC, pStep->pExprList);
        }
        assert( !pStep->pUpsert || (!pStep->pWhere && !pStep->pExprList) );
        if( pStep->pUpsert ){
        if( pStep->pUpsert && rc==SQLITE_OK ){
          Upsert *pUpsert = pStep->pUpsert;
          assert( rc==SQLITE_OK );
          pUpsert->pUpsertSrc = &sSrc;
          pUpsert->pUpsertSrc = pSrc;
          sNC.uNC.pUpsert = pUpsert;
          sNC.ncFlags = NC_UUpsert;
          rc = sqlite3ResolveExprListNames(&sNC, pUpsert->pUpsertTarget);
          if( rc==SQLITE_OK ){
            ExprList *pUpsertSet = pUpsert->pUpsertSet;
            rc = sqlite3ResolveExprListNames(&sNC, pUpsertSet);
          }
          if( rc==SQLITE_OK ){
            rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertWhere);
          }
          if( rc==SQLITE_OK ){
            rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertTargetWhere);
          }
          sNC.ncFlags = 0;
        }
        sNC.pSrcList = 0;
        sqlite3SrcListDelete(db, pSrc);
      }else{
        rc = SQLITE_NOMEM;
      }
    }
  }
  return rc;
}

/*
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
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429

1430
1431
1432
1433
1434

1435
1436
1437
1438
1439
1440

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

1459
1460
1461
1462
1463
1464
1465
1466
1467







+
+
+
+
+
+









+




+
+
-
+
+



-
+





-
+

















-
+
+







    if( pStep->pUpsert ){
      Upsert *pUpsert = pStep->pUpsert;
      sqlite3WalkExprList(pWalker, pUpsert->pUpsertTarget);
      sqlite3WalkExprList(pWalker, pUpsert->pUpsertSet);
      sqlite3WalkExpr(pWalker, pUpsert->pUpsertWhere);
      sqlite3WalkExpr(pWalker, pUpsert->pUpsertTargetWhere);
    }
    if( pStep->pFrom ){
      int i;
      for(i=0; i<pStep->pFrom->nSrc; i++){
        sqlite3WalkSelect(pWalker, pStep->pFrom->a[i].pSelect);
      }
    }
  }
}

/*
** Free the contents of Parse object (*pParse). Do not free the memory
** occupied by the Parse object itself.
*/
static void renameParseCleanup(Parse *pParse){
  sqlite3 *db = pParse->db;
  Index *pIdx;
  if( pParse->pVdbe ){
    sqlite3VdbeFinalize(pParse->pVdbe);
  }
  sqlite3DeleteTable(db, pParse->pNewTable);
  while( (pIdx = pParse->pNewIndex)!=0 ){
    pParse->pNewIndex = pIdx->pNext;
  if( pParse->pNewIndex ) sqlite3FreeIndex(db, pParse->pNewIndex);
    sqlite3FreeIndex(db, pIdx);
  }
  sqlite3DeleteTrigger(db, pParse->pNewTrigger);
  sqlite3DbFree(db, pParse->zErrMsg);
  renameTokenFree(db, pParse->pRename);
  sqlite3ParserReset(pParse);
  sqlite3ParseObjectReset(pParse);
}

/*
** SQL function:
**
**     sqlite_rename_column(zSql, iCol, bQuote, zNew, zTable, zOld)
**     sqlite_rename_column(SQL,TYPE,OBJ,DB,TABLE,COL,NEWNAME,QUOTE,TEMP)
**
**   0. zSql:     SQL statement to rewrite
**   1. type:     Type of object ("table", "view" etc.)
**   2. object:   Name of object
**   3. Database: Database name (e.g. "main")
**   4. Table:    Table name
**   5. iCol:     Index of column to rename
**   6. zNew:     New column name
**   7. bQuote:   Non-zero if the new column name should be quoted.
**   8. bTemp:    True if zSql comes from temp schema
**
** Do a column rename operation on the CREATE statement given in zSql.
** The iCol-th column (left-most is 0) of table zTable is renamed from zCol
** into zNew.  The name should be quoted if bQuote is true.
**
** This function is used internally by the ALTER TABLE RENAME COLUMN command.
** It is only accessible to SQL created using sqlite3NestedParse().  It is
** not reachable from ordinary SQL passed into sqlite3_prepare().
** not reachable from ordinary SQL passed into sqlite3_prepare() unless the
** SQLITE_TESTCTRL_INTERNAL_FUNCTIONS test setting is enabled.
*/
static void renameColumnFunc(
  sqlite3_context *context,
  int NotUsed,
  sqlite3_value **argv
){
  sqlite3 *db = sqlite3_context_db_handle(context);
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
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
1318
1319
1320
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
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
1574
1575
1576

1577
1578
1579
1580
1581
1582
1583
1584







-
+






-
+











+
-
-
+
+

-
+





-
+



-


+
-
-
-
+
+
+
+







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


















-
+







  if( iCol<0 ) return;
  sqlite3BtreeEnterAll(db);
  pTab = sqlite3FindTable(db, zTable, zDb);
  if( pTab==0 || iCol>=pTab->nCol ){
    sqlite3BtreeLeaveAll(db);
    return;
  }
  zOld = pTab->aCol[iCol].zName;
  zOld = pTab->aCol[iCol].zCnName;
  memset(&sCtx, 0, sizeof(sCtx));
  sCtx.iCol = ((iCol==pTab->iPKey) ? -1 : iCol);

#ifndef SQLITE_OMIT_AUTHORIZATION
  db->xAuth = 0;
#endif
  rc = renameParseSql(&sParse, zDb, 0, db, zSql, bTemp);
  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;

  sCtx.pTab = pTab;
  if( rc!=SQLITE_OK ) goto renameColumnFunc_done;
  if( sParse.pNewTable ){
    if( IsView(sParse.pNewTable) ){
    Select *pSelect = sParse.pNewTable->pSelect;
    if( pSelect ){
      Select *pSelect = sParse.pNewTable->u.view.pSelect;
      pSelect->selFlags &= ~SF_View;
      sParse.rc = SQLITE_OK;
      sqlite3SelectPrep(&sParse, sParse.pNewTable->pSelect, 0);
      sqlite3SelectPrep(&sParse, pSelect, 0);
      rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc);
      if( rc==SQLITE_OK ){
        sqlite3WalkSelect(&sWalker, pSelect);
      }
      if( rc!=SQLITE_OK ) goto renameColumnFunc_done;
    }else{
    }else if( IsOrdinaryTable(sParse.pNewTable) ){
      /* A regular table */
      int bFKOnly = sqlite3_stricmp(zTable, sParse.pNewTable->zName);
      FKey *pFKey;
      assert( sParse.pNewTable->pSelect==0 );
      sCtx.pTab = sParse.pNewTable;
      if( bFKOnly==0 ){
        if( iCol<sParse.pNewTable->nCol ){
        renameTokenFind(
            &sParse, &sCtx, (void*)sParse.pNewTable->aCol[iCol].zName
        );
          renameTokenFind(
              &sParse, &sCtx, (void*)sParse.pNewTable->aCol[iCol].zCnName
          );
        }
        if( sCtx.iCol<0 ){
          renameTokenFind(&sParse, &sCtx, (void*)&sParse.pNewTable->iPKey);
        }
        sqlite3WalkExprList(&sWalker, sParse.pNewTable->pCheck);
        for(pIdx=sParse.pNewTable->pIndex; pIdx; pIdx=pIdx->pNext){
          sqlite3WalkExprList(&sWalker, pIdx->aColExpr);
        }
        for(pIdx=sParse.pNewIndex; pIdx; pIdx=pIdx->pNext){
          sqlite3WalkExprList(&sWalker, pIdx->aColExpr);
      }

      for(pFKey=sParse.pNewTable->pFKey; pFKey; pFKey=pFKey->pNextFrom){
        }
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
        for(i=0; i<sParse.pNewTable->nCol; i++){
          Expr *pExpr = sqlite3ColumnExpr(sParse.pNewTable,
                                                  &sParse.pNewTable->aCol[i]);
          sqlite3WalkExpr(&sWalker, pExpr);
        }
#endif
      }

      assert( IsOrdinaryTable(sParse.pNewTable) );
      for(pFKey=sParse.pNewTable->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){
        for(i=0; i<pFKey->nCol; i++){
          if( bFKOnly==0 && pFKey->aCol[i].iFrom==iCol ){
            renameTokenFind(&sParse, &sCtx, (void*)&pFKey->aCol[i]);
          }
          if( 0==sqlite3_stricmp(pFKey->zTo, zTable)
           && 0==sqlite3_stricmp(pFKey->aCol[i].zCol, zOld)
          ){
            renameTokenFind(&sParse, &sCtx, (void*)pFKey->aCol[i].zCol);
          }
        }
      }
    }
  }else if( sParse.pNewIndex ){
    sqlite3WalkExprList(&sWalker, sParse.pNewIndex->aColExpr);
    sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere);
  }else{
    /* A trigger */
    TriggerStep *pStep;
    rc = renameResolveTrigger(&sParse, (bTemp ? 0 : zDb));
    rc = renameResolveTrigger(&sParse);
    if( rc!=SQLITE_OK ) goto renameColumnFunc_done;

    for(pStep=sParse.pNewTrigger->step_list; pStep; pStep=pStep->pNext){
      if( pStep->zTarget ){ 
        Table *pTarget = sqlite3LocateTable(&sParse, 0, pStep->zTarget, zDb);
        if( pTarget==pTab ){
          if( pStep->pUpsert ){
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
1602
1603
1604
1605
1606
1607
1608
1609
1610


1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630

1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651

1652
1653
1654
1655
1656

1657
1658
1659
1660
1661
1662
1663
1664







+
+
-
-
+
+


















-
+
+
+
+












+
+
+
+
+
-
+




-
+







  }

  assert( rc==SQLITE_OK );
  rc = renameEditSql(context, &sCtx, zSql, zNew, bQuote);

renameColumnFunc_done:
  if( rc!=SQLITE_OK ){
    if( rc==SQLITE_ERROR && sqlite3WritableSchema(db) ){
      sqlite3_result_value(context, argv[0]);
    if( sParse.zErrMsg ){
      renameColumnParseError(context, 0, argv[1], argv[2], &sParse);
    }else if( sParse.zErrMsg ){
      renameColumnParseError(context, "", argv[1], argv[2], &sParse);
    }else{
      sqlite3_result_error_code(context, rc);
    }
  }

  renameParseCleanup(&sParse);
  renameTokenFree(db, sCtx.pList);
#ifndef SQLITE_OMIT_AUTHORIZATION
  db->xAuth = xAuth;
#endif
  sqlite3BtreeLeaveAll(db);
}

/*
** Walker expression callback used by "RENAME TABLE". 
*/
static int renameTableExprCb(Walker *pWalker, Expr *pExpr){
  RenameCtx *p = pWalker->u.pRename;
  if( pExpr->op==TK_COLUMN && p->pTab==pExpr->y.pTab ){
  if( pExpr->op==TK_COLUMN
   && ALWAYS(ExprUseYTab(pExpr))
   && p->pTab==pExpr->y.pTab
  ){
    renameTokenFind(pWalker->pParse, p, (void*)&pExpr->y.pTab);
  }
  return WRC_Continue;
}

/*
** Walker select callback used by "RENAME TABLE". 
*/
static int renameTableSelectCb(Walker *pWalker, Select *pSelect){
  int i;
  RenameCtx *p = pWalker->u.pRename;
  SrcList *pSrc = pSelect->pSrc;
  if( pSelect->selFlags & (SF_View|SF_CopyCte) ){
    testcase( pSelect->selFlags & SF_View );
    testcase( pSelect->selFlags & SF_CopyCte );
    return WRC_Prune;
  }
  if( pSrc==0 ){
  if( NEVER(pSrc==0) ){
    assert( pWalker->pParse->db->mallocFailed );
    return WRC_Abort;
  }
  for(i=0; i<pSrc->nSrc; i++){
    struct SrcList_item *pItem = &pSrc->a[i];
    SrcItem *pItem = &pSrc->a[i];
    if( pItem->pTab==p->pTab ){
      renameTokenFind(pWalker->pParse, p, pItem->zName);
    }
  }
  renameWalkWith(pWalker, pSelect);

  return WRC_Continue;
1441
1442
1443
1444
1445
1446
1447
1448

1449
1450
1451
1452
1453
1454
1455

1456

1457
1458
1459
1460


1461
1462
1463






1464
1465
1466
1467
1468



1469

1470

1471
1472
1473
1474
1475
1476
1477
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
1755
1756
1757
1758
1759
1760







-
+






-
+

+




+
+
-
-
-
+
+
+
+
+
+




-
+
+
+

+
-
+







    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, 1, db, zInput, bTemp);
    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 ){
        if( IsView(pTab) ){
          if( isLegacy==0 ){
            Select *pSelect = pTab->u.view.pSelect;
            NameContext sNC;
            memset(&sNC, 0, sizeof(sNC));
            sNC.pParse = &sParse;

            assert( pSelect->selFlags & SF_View );
            pSelect->selFlags &= ~SF_View;
            sqlite3SelectPrep(&sParse, pTab->pSelect, &sNC);
            if( sParse.nErr ) rc = sParse.rc;
            sqlite3WalkSelect(&sWalker, pTab->pSelect);
            sqlite3SelectPrep(&sParse, pTab->u.view.pSelect, &sNC);
            if( sParse.nErr ){
              rc = sParse.rc;
            }else{
              sqlite3WalkSelect(&sWalker, pTab->u.view.pSelect);
            }
          }
        }else{
          /* Modify any FK definitions to point to the new table. */
#ifndef SQLITE_OMIT_FOREIGN_KEY
          if( isLegacy==0 || (db->flags & SQLITE_ForeignKeys) ){
          if( (isLegacy==0 || (db->flags & SQLITE_ForeignKeys))
           && !IsVirtual(pTab)
          ){
            FKey *pFKey;
            assert( IsOrdinaryTable(pTab) );
            for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){
            for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){
              if( sqlite3_stricmp(pFKey->zTo, zOld)==0 ){
                renameTokenFind(&sParse, &sCtx, (void*)pFKey->zTo);
              }
            }
          }
#endif

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





















































































































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


1574
1575
1576
1577
1578
1579
1580

1581
1582
1583


1584


1585
1586

1587
1588
1589
1590

1591
1592
1593
1594
1595
1596

1597
1598
1599
1600


1601


1602
1603
1604
1605
1606
1607



1608
1609
1610
1611
1612
1613
1614
1615
























































































































































































































1616
1617
1618
1619
1620
1621
1622
1623
1624





1625
1626
1627
1628
1785
1786
1787
1788
1789
1790
1791

1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820


1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846

1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
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
1984
1985
1986
1987
1988
1989
1990
1991
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
2017

2018
2019
2020
2021
2022
2023

2024
2025
2026
2027
2028
2029
2030

2031
2032
2033
2034
2035
2036


2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
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
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
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
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269



2270
2271
2272
2273
2274
2275
2276
2277
2278







-
+





+
+
+
+
+
+
+
+
+












+
+
-
-
+
+
















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











+
+

-
-
+

+
+
-
-
+
+
+











+
+







+



+
+
-
+
+

-
+



-
+





-
+




+
+
-
+
+




-
-
+
+
+








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






-
-
-
+
+
+
+
+




        if( 0==sqlite3_stricmp(sParse.pNewTrigger->table, zOld) 
            && sCtx.pTab->pSchema==pTrigger->pTabSchema
          ){
          renameTokenFind(&sParse, &sCtx, sParse.pNewTrigger->table);
        }

        if( isLegacy==0 ){
          rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb);
          rc = renameResolveTrigger(&sParse);
          if( rc==SQLITE_OK ){
            renameWalkTrigger(&sWalker, pTrigger);
            for(pStep=pTrigger->step_list; pStep; pStep=pStep->pNext){
              if( pStep->zTarget && 0==sqlite3_stricmp(pStep->zTarget, zOld) ){
                renameTokenFind(&sParse, &sCtx, pStep->zTarget);
              }
              if( pStep->pFrom ){
                int i;
                for(i=0; i<pStep->pFrom->nSrc; i++){
                  SrcItem *pItem = &pStep->pFrom->a[i];
                  if( 0==sqlite3_stricmp(pItem->zName, zOld) ){
                    renameTokenFind(&sParse, &sCtx, pItem->zName);
                  }
                }
              }
            }
          }
        }
      }
#endif
    }

    if( rc==SQLITE_OK ){
      rc = renameEditSql(context, &sCtx, zInput, zNew, bQuote);
    }
    if( rc!=SQLITE_OK ){
      if( rc==SQLITE_ERROR && sqlite3WritableSchema(db) ){
        sqlite3_result_value(context, argv[3]);
      if( sParse.zErrMsg ){
        renameColumnParseError(context, 0, argv[1], argv[2], &sParse);
      }else if( sParse.zErrMsg ){
        renameColumnParseError(context, "", argv[1], argv[2], &sParse);
      }else{
        sqlite3_result_error_code(context, rc);
      }
    }

    renameParseCleanup(&sParse);
    renameTokenFree(db, sCtx.pList);
    sqlite3BtreeLeaveAll(db);
#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, (const void*)pExpr);
  }
  return WRC_Continue;
}

/* SQL function: sqlite_rename_quotefix(DB,SQL)
/*
**
** Rewrite the DDL statement "SQL" so that any string literals that use
** double-quotes use single quotes instead.
**
** 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
**
** If there is a error in the input SQL, then raise an error, except
** if PRAGMA writable_schema=ON, then just return the input string
** unmodified following an error.
*/
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 ){
        if( IsView(sParse.pNewTable) ){
          Select *pSelect = sParse.pNewTable->u.view.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, 
               sqlite3ColumnExpr(sParse.pNewTable, 
                                         &sParse.pNewTable->aCol[i]));
          }
#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 ){
      if( sqlite3WritableSchema(db) && rc==SQLITE_ERROR ){
        sqlite3_result_value(context, argv[1]);
      }else{
        sqlite3_result_error_code(context, rc);
      }
    }
    renameParseCleanup(&sParse);
  }

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

  sqlite3BtreeLeaveAll(db);
}

/* Function:  sqlite_rename_test(DB,SQL,TYPE,NAME,ISTEMP,WHEN,DQS)
**
** An SQL user function that checks that there are no parse or symbol
** resolution problems in a CREATE TRIGGER|TABLE|VIEW|INDEX statement.
** After an ALTER TABLE .. RENAME operation is performed and the schema
** reloaded, this function is called on each SQL statement in the schema
** to ensure that it is still usable.
**
**   0: Database name ("main", "temp" etc.).
**   1: SQL statement.
**   2: Object type ("view", "table", "trigger" or "index").
**   3: Object name.
**   4: True if object is from temp schema.
**   5: "when" part of error message.
**   6: True to disable the DQS quirk when parsing SQL.
**
** Unless it finds an error, this function normally returns NULL. However, it
** returns integer value 1 if:
** The return value is computed as follows:
**
**   A. If an error is seen and not in PRAGMA writable_schema=ON mode,
**      then raise the error.
**   * the SQL argument creates a trigger, and
**   * the table that the trigger is attached to is in database zDb.
**   B. Else if a trigger is created and the the table that the trigger is
**      attached to is in database zDb, then return 1.
**   C. Otherwise return NULL.
*/
static void renameTableTest(
  sqlite3_context *context,
  int NotUsed,
  sqlite3_value **argv
){
  sqlite3 *db = sqlite3_context_db_handle(context);
  char const *zDb = (const char*)sqlite3_value_text(argv[0]);
  char const *zInput = (const char*)sqlite3_value_text(argv[1]);
  int bTemp = sqlite3_value_int(argv[4]);
  int isLegacy = (db->flags & SQLITE_LegacyAlter);
  char const *zWhen = (const char*)sqlite3_value_text(argv[5]);
  int bNoDQS = sqlite3_value_int(argv[6]);

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

  UNUSED_PARAMETER(NotUsed);

  if( zDb && zInput ){
    int rc;
    Parse sParse;
    int flags = db->flags;
    if( bNoDQS ) db->flags &= ~(SQLITE_DqsDML|SQLITE_DqsDDL);
    rc = renameParseSql(&sParse, zDb, 1, db, zInput, bTemp);
    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 ){
      if( isLegacy==0 && sParse.pNewTable && IsView(sParse.pNewTable) ){
        NameContext sNC;
        memset(&sNC, 0, sizeof(sNC));
        sNC.pParse = &sParse;
        sqlite3SelectPrep(&sParse, sParse.pNewTable->pSelect, &sNC);
        sqlite3SelectPrep(&sParse, sParse.pNewTable->u.view.pSelect, &sNC);
        if( sParse.nErr ) rc = sParse.rc;
      }

      else if( sParse.pNewTrigger ){
        if( isLegacy==0 ){
          rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb);
          rc = renameResolveTrigger(&sParse);
        }
        if( rc==SQLITE_OK ){
          int i1 = sqlite3SchemaToIndex(db, sParse.pNewTrigger->pTabSchema);
          int i2 = sqlite3FindDbName(db, zDb);
          if( i1==i2 ){
            /* Handle output case B */
          if( i1==i2 ) sqlite3_result_int(context, 1);
            sqlite3_result_int(context, 1);
          }
        }
      }
    }

    if( rc!=SQLITE_OK ){
      renameColumnParseError(context, 1, argv[2], argv[3], &sParse);
    if( rc!=SQLITE_OK && zWhen && !sqlite3WritableSchema(db) ){
      /* Output case A */
      renameColumnParseError(context, zWhen, argv[2], argv[3],&sParse);
    }
    renameParseCleanup(&sParse);
  }

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

/*
** The implementation of internal UDF sqlite_drop_column().
** 
** Arguments:
**
**  argv[0]: An integer - the index of the schema containing the table
**  argv[1]: CREATE TABLE statement to modify.
**  argv[2]: An integer - the index of the column to remove.
**
** The value returned is a string containing the CREATE TABLE statement
** with column argv[2] removed.
*/
static void dropColumnFunc(
  sqlite3_context *context,
  int NotUsed,
  sqlite3_value **argv
){
  sqlite3 *db = sqlite3_context_db_handle(context);
  int iSchema = sqlite3_value_int(argv[0]);
  const char *zSql = (const char*)sqlite3_value_text(argv[1]);
  int iCol = sqlite3_value_int(argv[2]);
  const char *zDb = db->aDb[iSchema].zDbSName;
  int rc;
  Parse sParse;
  RenameToken *pCol;
  Table *pTab;
  const char *zEnd;
  char *zNew = 0;

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

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

  pCol = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol].zCnName);
  if( iCol<pTab->nCol-1 ){
    RenameToken *pEnd;
    pEnd = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol+1].zCnName);
    zEnd = (const char*)pEnd->t.z;
  }else{
    assert( IsOrdinaryTable(pTab) );
    zEnd = (const char*)&zSql[pTab->u.tab.addColOffset];
    while( ALWAYS(pCol->t.z[0]!=0) && pCol->t.z[0]!=',' ) pCol->t.z--;
  }

  zNew = sqlite3MPrintf(db, "%.*s%s", pCol->t.z-zSql, zSql, zEnd);
  sqlite3_result_text(context, zNew, -1, SQLITE_TRANSIENT);
  sqlite3_free(zNew);

drop_column_done:
  renameParseCleanup(&sParse);
#ifndef SQLITE_OMIT_AUTHORIZATION
  db->xAuth = xAuth;
#endif
  if( rc!=SQLITE_OK ){
    sqlite3_result_error_code(context, rc);
  }
}

/*
** This function is called by the parser upon parsing an 
**
**     ALTER TABLE pSrc DROP COLUMN pName
**
** statement. Argument pSrc contains the possibly qualified name of the
** table being edited, and token pName the name of the column to drop.
*/
void sqlite3AlterDropColumn(Parse *pParse, SrcList *pSrc, const Token *pName){
  sqlite3 *db = pParse->db;       /* Database handle */
  Table *pTab;                    /* Table to modify */
  int iDb;                        /* Index of db containing pTab in aDb[] */
  const char *zDb;                /* Database containing pTab ("main" etc.) */
  char *zCol = 0;                 /* Name of column to drop */
  int iCol;                       /* Index of column zCol in pTab->aCol[] */

  /* Look up the table being altered. */
  assert( pParse->pNewTable==0 );
  assert( sqlite3BtreeHoldsAllMutexes(db) );
  if( NEVER(db->mallocFailed) ) goto exit_drop_column;
  pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
  if( !pTab ) goto exit_drop_column;

  /* Make sure this is not an attempt to ALTER a view, virtual table or 
  ** system table. */
  if( SQLITE_OK!=isAlterableTable(pParse, pTab) ) goto exit_drop_column;
  if( SQLITE_OK!=isRealTable(pParse, pTab, 1) ) goto exit_drop_column;

  /* Find the index of the column being dropped. */
  zCol = sqlite3NameFromToken(db, pName);
  if( zCol==0 ){
    assert( db->mallocFailed );
    goto exit_drop_column;
  }
  iCol = sqlite3ColumnIndex(pTab, zCol);
  if( iCol<0 ){
    sqlite3ErrorMsg(pParse, "no such column: \"%T\"", pName);
    goto exit_drop_column;
  }

  /* Do not allow the user to drop a PRIMARY KEY column or a column 
  ** constrained by a UNIQUE constraint.  */
  if( pTab->aCol[iCol].colFlags & (COLFLAG_PRIMKEY|COLFLAG_UNIQUE) ){
    sqlite3ErrorMsg(pParse, "cannot drop %s column: \"%s\"", 
        (pTab->aCol[iCol].colFlags&COLFLAG_PRIMKEY) ? "PRIMARY KEY" : "UNIQUE",
        zCol
    );
    goto exit_drop_column;
  }

  /* Do not allow the number of columns to go to zero */
  if( pTab->nCol<=1 ){
    sqlite3ErrorMsg(pParse, "cannot drop column \"%s\": no other columns exist",zCol);
    goto exit_drop_column;
  }

  /* Edit the sqlite_schema table */
  iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
  assert( iDb>=0 );
  zDb = db->aDb[iDb].zDbSName;
#ifndef SQLITE_OMIT_AUTHORIZATION
  /* Invoke the authorization callback. */
  if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, zCol) ){
    goto exit_drop_column;
  }
#endif
  renameTestSchema(pParse, zDb, iDb==1, "", 0);
  renameFixQuotes(pParse, zDb, iDb==1);
  sqlite3NestedParse(pParse, 
      "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET "
      "sql = sqlite_drop_column(%d, sql, %d) "
      "WHERE (type=='table' AND tbl_name=%Q COLLATE nocase)"
      , zDb, iDb, iCol, pTab->zName
  );

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

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

23
24
25
26
27
28
29
30

31
32
33
34
35
36





37
38
39
40
41
42
43
23
24
25
26
27
28
29

30
31





32
33
34
35
36
37
38
39
40
41
42
43







-
+

-
-
-
-
-
+
+
+
+
+







**    CREATE TABLE sqlite_stat4(tbl, idx, nEq, nLt, nDLt, sample);
**
** Additional tables might be added in future releases of SQLite.
** The sqlite_stat2 table is not created or used unless the SQLite version
** is between 3.6.18 and 3.7.8, inclusive, and unless SQLite is compiled
** with SQLITE_ENABLE_STAT2.  The sqlite_stat2 table is deprecated.
** The sqlite_stat2 table is superseded by sqlite_stat3, which is only
** created and used by SQLite versions 3.7.9 and later and with
** created and used by SQLite versions 3.7.9 through 3.29.0 when
** SQLITE_ENABLE_STAT3 defined.  The functionality of sqlite_stat3
** is a superset of sqlite_stat2.  The sqlite_stat4 is an enhanced
** version of sqlite_stat3 and is only available when compiled with
** SQLITE_ENABLE_STAT4 and in SQLite versions 3.8.1 and later.  It is
** not possible to enable both STAT3 and STAT4 at the same time.  If they
** are both enabled, then STAT4 takes precedence.
** is a superset of sqlite_stat2 and is also now deprecated.  The
** sqlite_stat4 is an enhanced version of sqlite_stat3 and is only 
** available when compiled with SQLITE_ENABLE_STAT4 and in SQLite
** versions 3.8.1 and later.  STAT4 is the only variant that is still
** supported.
**
** For most applications, sqlite_stat1 provides all the statistics required
** for the query planner to make good choices.
**
** Format of sqlite_stat1:
**
** There is normally one row per index, with the index identified by the
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
140
141
142
143
144
145
146




147
148

149
150
151

152
153
154
155
156
157
158







-
-
-
-


-



-







** integer in the equivalent columns in sqlite_stat4.
*/
#ifndef SQLITE_OMIT_ANALYZE
#include "sqliteInt.h"

#if defined(SQLITE_ENABLE_STAT4)
# define IsStat4     1
# define IsStat3     0
#elif defined(SQLITE_ENABLE_STAT3)
# define IsStat4     0
# define IsStat3     1
#else
# define IsStat4     0
# define IsStat3     0
# undef SQLITE_STAT4_SAMPLES
# define SQLITE_STAT4_SAMPLES 1
#endif
#define IsStat34    (IsStat3+IsStat4)  /* 1 for STAT3 or STAT4. 0 otherwise */

/*
** This routine generates code that opens the sqlite_statN tables.
** The sqlite_stat1 table is always relevant.  sqlite_stat2 is now
** obsolete.  sqlite_stat3 and sqlite_stat4 are only opened when
** appropriate compile-time options are provided.
**
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
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







-
-
-
-

-


+





-
+

+
+
+
+
+












+

-
+







-
+







-












-
+





-
+

-
+

















-
-
-
+
+
+


-
+











-
-
-
+
+
+
+
+


+
+
+
+

-

-
+




-
-
+
+


-
+

-
-
+
+










-
-
+
+














-
-
+
+











-
-
+
+















-
+

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





-
+



-
+
+





-
-





-
-
-
+
+
+







-
+




-
-
-
+
+
+
+











-
+

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

-
-







+

+


+



-
+
-
+
+




-
-
+



-
-
+
+



















-
+


-
+







  static const struct {
    const char *zName;
    const char *zCols;
  } aTable[] = {
    { "sqlite_stat1", "tbl,idx,stat" },
#if defined(SQLITE_ENABLE_STAT4)
    { "sqlite_stat4", "tbl,idx,neq,nlt,ndlt,sample" },
    { "sqlite_stat3", 0 },
#elif defined(SQLITE_ENABLE_STAT3)
    { "sqlite_stat3", "tbl,idx,neq,nlt,ndlt,sample" },
    { "sqlite_stat4", 0 },
#else
    { "sqlite_stat3", 0 },
    { "sqlite_stat4", 0 },
#endif
    { "sqlite_stat3", 0 },
  };
  int i;
  sqlite3 *db = pParse->db;
  Db *pDb;
  Vdbe *v = sqlite3GetVdbe(pParse);
  int aRoot[ArraySize(aTable)];
  u32 aRoot[ArraySize(aTable)];
  u8 aCreateTbl[ArraySize(aTable)];
#ifdef SQLITE_ENABLE_STAT4
  const int nToOpen = OptimizationEnabled(db,SQLITE_Stat4) ? 2 : 1;
#else
  const int nToOpen = 1;
#endif

  if( v==0 ) return;
  assert( sqlite3BtreeHoldsAllMutexes(db) );
  assert( sqlite3VdbeDb(v)==db );
  pDb = &db->aDb[iDb];

  /* Create new statistic tables if they do not exist, or clear them
  ** if they do already exist.
  */
  for(i=0; i<ArraySize(aTable); i++){
    const char *zTab = aTable[i].zName;
    Table *pStat;
    aCreateTbl[i] = 0;
    if( (pStat = sqlite3FindTable(db, zTab, pDb->zDbSName))==0 ){
      if( aTable[i].zCols ){
      if( i<nToOpen ){
        /* The sqlite_statN table does not exist. Create it. Note that a 
        ** side-effect of the CREATE TABLE statement is to leave the rootpage 
        ** of the new table in register pParse->regRoot. This is important 
        ** because the OpenWrite opcode below will be needing it. */
        sqlite3NestedParse(pParse,
            "CREATE TABLE %Q.%s(%s)", pDb->zDbSName, zTab, aTable[i].zCols
        );
        aRoot[i] = pParse->regRoot;
        aRoot[i] = (u32)pParse->regRoot;
        aCreateTbl[i] = OPFLAG_P2ISREG;
      }
    }else{
      /* The table already exists. If zWhere is not NULL, delete all entries 
      ** associated with the table zWhere. If zWhere is NULL, delete the
      ** entire contents of the table. */
      aRoot[i] = pStat->tnum;
      aCreateTbl[i] = 0;
      sqlite3TableLock(pParse, iDb, aRoot[i], 1, zTab);
      if( zWhere ){
        sqlite3NestedParse(pParse,
           "DELETE FROM %Q.%s WHERE %s=%Q",
           pDb->zDbSName, zTab, zWhereType, zWhere
        );
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
      }else if( db->xPreUpdateCallback ){
        sqlite3NestedParse(pParse, "DELETE FROM %Q.%s", pDb->zDbSName, zTab);
#endif
      }else{
        /* The sqlite_stat[134] table already exists.  Delete all rows. */
        sqlite3VdbeAddOp2(v, OP_Clear, aRoot[i], iDb);
        sqlite3VdbeAddOp2(v, OP_Clear, (int)aRoot[i], iDb);
      }
    }
  }

  /* Open the sqlite_stat[134] tables for writing. */
  for(i=0; aTable[i].zCols; i++){
  for(i=0; i<nToOpen; i++){
    assert( i<ArraySize(aTable) );
    sqlite3VdbeAddOp4Int(v, OP_OpenWrite, iStatCur+i, aRoot[i], iDb, 3);
    sqlite3VdbeAddOp4Int(v, OP_OpenWrite, iStatCur+i, (int)aRoot[i], iDb, 3);
    sqlite3VdbeChangeP5(v, aCreateTbl[i]);
    VdbeComment((v, aTable[i].zName));
  }
}

/*
** Recommended number of samples for sqlite_stat4
*/
#ifndef SQLITE_STAT4_SAMPLES
# define SQLITE_STAT4_SAMPLES 24
#endif

/*
** Three SQL functions - stat_init(), stat_push(), and stat_get() -
** share an instance of the following structure to hold their state
** information.
*/
typedef struct Stat4Accum Stat4Accum;
typedef struct Stat4Sample Stat4Sample;
struct Stat4Sample {
typedef struct StatAccum StatAccum;
typedef struct StatSample StatSample;
struct StatSample {
  tRowcnt *anEq;                  /* sqlite_stat4.nEq */
  tRowcnt *anDLt;                 /* sqlite_stat4.nDLt */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
  tRowcnt *anLt;                  /* sqlite_stat4.nLt */
  union {
    i64 iRowid;                     /* Rowid in main table of the key */
    u8 *aRowid;                     /* Key for WITHOUT ROWID tables */
  } u;
  u32 nRowid;                     /* Sizeof aRowid[] */
  u8 isPSample;                   /* True if a periodic sample */
  int iCol;                       /* If !isPSample, the reason for inclusion */
  u32 iHash;                      /* Tiebreaker hash */
#endif
};                                                    
struct Stat4Accum {
  tRowcnt nRow;             /* Number of rows in the entire table */
  tRowcnt nPSample;         /* How often to do a periodic sample */
struct StatAccum {
  sqlite3 *db;              /* Database connection, for malloc() */
  tRowcnt nEst;             /* Estimated number of rows */
  tRowcnt nRow;             /* Number of rows visited so far */
  int nLimit;               /* Analysis row-scan limit */
  int nCol;                 /* Number of columns in index + pk/rowid */
  int nKeyCol;              /* Number of index columns w/o the pk/rowid */
  u8 nSkipAhead;            /* Number of times of skip-ahead */
  StatSample current;       /* Current row as a StatSample */
#ifdef SQLITE_ENABLE_STAT4
  tRowcnt nPSample;         /* How often to do a periodic sample */
  int mxSample;             /* Maximum number of samples to accumulate */
  Stat4Sample current;      /* Current row as a Stat4Sample */
  u32 iPrn;                 /* Pseudo-random number used for sampling */
  Stat4Sample *aBest;       /* Array of nCol best samples */
  StatSample *aBest;        /* Array of nCol best samples */
  int iMin;                 /* Index in a[] of entry with minimum score */
  int nSample;              /* Current number of samples */
  int nMaxEqZero;           /* Max leading 0 in anEq[] for any a[] entry */
  int iGet;                 /* Index of current sample accessed by stat_get() */
  Stat4Sample *a;           /* Array of mxSample Stat4Sample objects */
  sqlite3 *db;              /* Database connection, for malloc() */
  StatSample *a;            /* Array of mxSample StatSample objects */
#endif
};

/* Reclaim memory used by a Stat4Sample
/* Reclaim memory used by a StatSample
*/
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
static void sampleClear(sqlite3 *db, Stat4Sample *p){
#ifdef SQLITE_ENABLE_STAT4
static void sampleClear(sqlite3 *db, StatSample *p){
  assert( db!=0 );
  if( p->nRowid ){
    sqlite3DbFree(db, p->u.aRowid);
    p->nRowid = 0;
  }
}
#endif

/* Initialize the BLOB value of a ROWID
*/
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
static void sampleSetRowid(sqlite3 *db, Stat4Sample *p, int n, const u8 *pData){
#ifdef SQLITE_ENABLE_STAT4
static void sampleSetRowid(sqlite3 *db, StatSample *p, int n, const u8 *pData){
  assert( db!=0 );
  if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid);
  p->u.aRowid = sqlite3DbMallocRawNN(db, n);
  if( p->u.aRowid ){
    p->nRowid = n;
    memcpy(p->u.aRowid, pData, n);
  }else{
    p->nRowid = 0;
  }
}
#endif

/* Initialize the INTEGER value of a ROWID.
*/
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
static void sampleSetRowidInt64(sqlite3 *db, Stat4Sample *p, i64 iRowid){
#ifdef SQLITE_ENABLE_STAT4
static void sampleSetRowidInt64(sqlite3 *db, StatSample *p, i64 iRowid){
  assert( db!=0 );
  if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid);
  p->nRowid = 0;
  p->u.iRowid = iRowid;
}
#endif


/*
** Copy the contents of object (*pFrom) into (*pTo).
*/
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
static void sampleCopy(Stat4Accum *p, Stat4Sample *pTo, Stat4Sample *pFrom){
#ifdef SQLITE_ENABLE_STAT4
static void sampleCopy(StatAccum *p, StatSample *pTo, StatSample *pFrom){
  pTo->isPSample = pFrom->isPSample;
  pTo->iCol = pFrom->iCol;
  pTo->iHash = pFrom->iHash;
  memcpy(pTo->anEq, pFrom->anEq, sizeof(tRowcnt)*p->nCol);
  memcpy(pTo->anLt, pFrom->anLt, sizeof(tRowcnt)*p->nCol);
  memcpy(pTo->anDLt, pFrom->anDLt, sizeof(tRowcnt)*p->nCol);
  if( pFrom->nRowid ){
    sampleSetRowid(p->db, pTo, pFrom->nRowid, pFrom->u.aRowid);
  }else{
    sampleSetRowidInt64(p->db, pTo, pFrom->u.iRowid);
  }
}
#endif

/*
** Reclaim all memory of a Stat4Accum structure.
** Reclaim all memory of a StatAccum structure.
*/
static void stat4Destructor(void *pOld){
  Stat4Accum *p = (Stat4Accum*)pOld;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  int i;
  for(i=0; i<p->nCol; i++) sampleClear(p->db, p->aBest+i);
  for(i=0; i<p->mxSample; i++) sampleClear(p->db, p->a+i);
  sampleClear(p->db, &p->current);
static void statAccumDestructor(void *pOld){
  StatAccum *p = (StatAccum*)pOld;
#ifdef SQLITE_ENABLE_STAT4
  if( p->mxSample ){
    int i;
    for(i=0; i<p->nCol; i++) sampleClear(p->db, p->aBest+i);
    for(i=0; i<p->mxSample; i++) sampleClear(p->db, p->a+i);
    sampleClear(p->db, &p->current);
  }
#endif
  sqlite3DbFree(p->db, p);
}

/*
** Implementation of the stat_init(N,K,C) SQL function. The three parameters
** Implementation of the stat_init(N,K,C,L) SQL function. The four parameters
** are:
**     N:    The number of columns in the index including the rowid/pk (note 1)
**     K:    The number of columns in the index excluding the rowid/pk.
**     C:    The number of rows in the index (note 2)
**     C:    Estimated number of rows in the index
**     L:    A limit on the number of rows to scan, or 0 for no-limit 
**
** Note 1:  In the special case of the covering index that implements a
** WITHOUT ROWID table, N is the number of PRIMARY KEY columns, not the
** total number of columns in the table.
**
** Note 2:  C is only used for STAT3 and STAT4.
**
** For indexes on ordinary rowid tables, N==K+1.  But for indexes on
** WITHOUT ROWID tables, N=K+P where P is the number of columns in the
** PRIMARY KEY of the table.  The covering index that implements the
** original WITHOUT ROWID table as N==K as a special case.
**
** This routine allocates the Stat4Accum object in heap memory. The return 
** value is a pointer to the Stat4Accum object.  The datatype of the
** return value is BLOB, but it is really just a pointer to the Stat4Accum
** This routine allocates the StatAccum object in heap memory. The return 
** value is a pointer to the StatAccum object.  The datatype of the
** return value is BLOB, but it is really just a pointer to the StatAccum
** object.
*/
static void statInit(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  Stat4Accum *p;
  StatAccum *p;
  int nCol;                       /* Number of columns in index being sampled */
  int nKeyCol;                    /* Number of key columns */
  int nColUp;                     /* nCol rounded up for alignment */
  int n;                          /* Bytes of space to allocate */
  sqlite3 *db;                    /* Database connection */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  int mxSample = SQLITE_STAT4_SAMPLES;
  sqlite3 *db = sqlite3_context_db_handle(context);   /* Database connection */
#ifdef SQLITE_ENABLE_STAT4
  /* Maximum number of samples.  0 if STAT4 data is not collected */
  int mxSample = OptimizationEnabled(db,SQLITE_Stat4) ?SQLITE_STAT4_SAMPLES :0;
#endif

  /* Decode the three function arguments */
  UNUSED_PARAMETER(argc);
  nCol = sqlite3_value_int(argv[0]);
  assert( nCol>0 );
  nColUp = sizeof(tRowcnt)<8 ? (nCol+1)&~1 : nCol;
  nKeyCol = sqlite3_value_int(argv[1]);
  assert( nKeyCol<=nCol );
  assert( nKeyCol>0 );

  /* Allocate the space required for the Stat4Accum object */
  /* Allocate the space required for the StatAccum object */
  n = sizeof(*p) 
    + sizeof(tRowcnt)*nColUp                  /* Stat4Accum.anEq */
    + sizeof(tRowcnt)*nColUp                  /* Stat4Accum.anDLt */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
    + sizeof(tRowcnt)*nColUp                  /* Stat4Accum.anLt */
    + sizeof(Stat4Sample)*(nCol+mxSample)     /* Stat4Accum.aBest[], a[] */
    + sizeof(tRowcnt)*3*nColUp*(nCol+mxSample)
    + sizeof(tRowcnt)*nColUp                  /* StatAccum.anEq */
    + sizeof(tRowcnt)*nColUp;                 /* StatAccum.anDLt */
#ifdef SQLITE_ENABLE_STAT4
  if( mxSample ){
    n += sizeof(tRowcnt)*nColUp                  /* StatAccum.anLt */
      + sizeof(StatSample)*(nCol+mxSample)       /* StatAccum.aBest[], a[] */
      + sizeof(tRowcnt)*3*nColUp*(nCol+mxSample);
  }
#endif
  ;
  db = sqlite3_context_db_handle(context);
  p = sqlite3DbMallocZero(db, n);
  if( p==0 ){
    sqlite3_result_error_nomem(context);
    return;
  }

  p->db = db;
  p->nEst = sqlite3_value_int64(argv[2]);
  p->nRow = 0;
  p->nLimit = sqlite3_value_int64(argv[3]);
  p->nCol = nCol;
  p->nKeyCol = nKeyCol;
  p->nSkipAhead = 0;
  p->current.anDLt = (tRowcnt*)&p[1];
  p->current.anEq = &p->current.anDLt[nColUp];

#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
  {
  p->mxSample = p->nLimit==0 ? mxSample : 0;
  if( mxSample ){
    u8 *pSpace;                     /* Allocated space not yet assigned */
    int i;                          /* Used to iterate through p->aSample[] */

    p->iGet = -1;
    p->mxSample = mxSample;
    p->nPSample = (tRowcnt)(sqlite3_value_int64(argv[2])/(mxSample/3+1) + 1);
    p->nPSample = (tRowcnt)(p->nEst/(mxSample/3+1) + 1);
    p->current.anLt = &p->current.anEq[nColUp];
    p->iPrn = 0x689e962d*(u32)nCol ^ 0xd0944565*(u32)sqlite3_value_int(argv[2]);
  
    /* Set up the Stat4Accum.a[] and aBest[] arrays */
    p->a = (struct Stat4Sample*)&p->current.anLt[nColUp];
    /* Set up the StatAccum.a[] and aBest[] arrays */
    p->a = (struct StatSample*)&p->current.anLt[nColUp];
    p->aBest = &p->a[mxSample];
    pSpace = (u8*)(&p->a[mxSample+nCol]);
    for(i=0; i<(mxSample+nCol); i++){
      p->a[i].anEq = (tRowcnt *)pSpace; pSpace += (sizeof(tRowcnt) * nColUp);
      p->a[i].anLt = (tRowcnt *)pSpace; pSpace += (sizeof(tRowcnt) * nColUp);
      p->a[i].anDLt = (tRowcnt *)pSpace; pSpace += (sizeof(tRowcnt) * nColUp);
    }
    assert( (pSpace - (u8*)p)==n );
  
    for(i=0; i<nCol; i++){
      p->aBest[i].iCol = i;
    }
  }
#endif

  /* Return a pointer to the allocated object to the caller.  Note that
  ** only the pointer (the 2nd parameter) matters.  The size of the object
  ** (given by the 3rd parameter) is never used and can be any positive
  ** value. */
  sqlite3_result_blob(context, p, sizeof(*p), stat4Destructor);
  sqlite3_result_blob(context, p, sizeof(*p), statAccumDestructor);
}
static const FuncDef statInitFuncdef = {
  2+IsStat34,      /* nArg */
  4,               /* nArg */
  SQLITE_UTF8,     /* funcFlags */
  0,               /* pUserData */
  0,               /* pNext */
  statInit,        /* xSFunc */
  0,               /* xFinalize */
  0, 0,            /* xValue, xInverse */
  "stat_init",     /* zName */
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
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
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
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







-
-
-
+
+
+













-
+







-
-
-
+
+
+








-





-
-
-






-
-
+
+




-
-
-
+
+

-
+




-
+








-
+















-



-
+
















-


-









-
-
+
-












-
+

+






-
+
-





-
+







** In other words, if we assume that the cardinalities of the selected
** column for pNew and pOld are equal, is pNew to be preferred over pOld.
**
** This function assumes that for each argument sample, the contents of
** the anEq[] array from pSample->anEq[pSample->iCol+1] onwards are valid. 
*/
static int sampleIsBetterPost(
  Stat4Accum *pAccum, 
  Stat4Sample *pNew, 
  Stat4Sample *pOld
  StatAccum *pAccum, 
  StatSample *pNew, 
  StatSample *pOld
){
  int nCol = pAccum->nCol;
  int i;
  assert( pNew->iCol==pOld->iCol );
  for(i=pNew->iCol+1; i<nCol; i++){
    if( pNew->anEq[i]>pOld->anEq[i] ) return 1;
    if( pNew->anEq[i]<pOld->anEq[i] ) return 0;
  }
  if( pNew->iHash>pOld->iHash ) return 1;
  return 0;
}
#endif

#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
/*
** Return true if pNew is to be preferred over pOld.
**
** This function assumes that for each argument sample, the contents of
** the anEq[] array from pSample->anEq[pSample->iCol] onwards are valid. 
*/
static int sampleIsBetter(
  Stat4Accum *pAccum, 
  Stat4Sample *pNew, 
  Stat4Sample *pOld
  StatAccum *pAccum, 
  StatSample *pNew, 
  StatSample *pOld
){
  tRowcnt nEqNew = pNew->anEq[pNew->iCol];
  tRowcnt nEqOld = pOld->anEq[pOld->iCol];

  assert( pOld->isPSample==0 && pNew->isPSample==0 );
  assert( IsStat4 || (pNew->iCol==0 && pOld->iCol==0) );

  if( (nEqNew>nEqOld) ) return 1;
#ifdef SQLITE_ENABLE_STAT4
  if( nEqNew==nEqOld ){
    if( pNew->iCol<pOld->iCol ) return 1;
    return (pNew->iCol==pOld->iCol && sampleIsBetterPost(pAccum, pNew, pOld));
  }
  return 0;
#else
  return (nEqNew==nEqOld && pNew->iHash>pOld->iHash);
#endif
}

/*
** Copy the contents of sample *pNew into the p->a[] array. If necessary,
** remove the least desirable sample from p->a[] to make room.
*/
static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){
  Stat4Sample *pSample = 0;
static void sampleInsert(StatAccum *p, StatSample *pNew, int nEqZero){
  StatSample *pSample = 0;
  int i;

  assert( IsStat4 || nEqZero==0 );

#ifdef SQLITE_ENABLE_STAT4
  /* Stat4Accum.nMaxEqZero is set to the maximum number of leading 0
  ** values in the anEq[] array of any sample in Stat4Accum.a[]. In
  /* StatAccum.nMaxEqZero is set to the maximum number of leading 0
  ** values in the anEq[] array of any sample in StatAccum.a[]. In
  ** other words, if nMaxEqZero is n, then it is guaranteed that there
  ** are no samples with Stat4Sample.anEq[m]==0 for (m>=n). */
  ** are no samples with StatSample.anEq[m]==0 for (m>=n). */
  if( nEqZero>p->nMaxEqZero ){
    p->nMaxEqZero = nEqZero;
  }
  if( pNew->isPSample==0 ){
    Stat4Sample *pUpgrade = 0;
    StatSample *pUpgrade = 0;
    assert( pNew->anEq[pNew->iCol]>0 );

    /* This sample is being added because the prefix that ends in column 
    ** iCol occurs many times in the table. However, if we have already
    ** added a sample that shares this prefix, there is no need to add
    ** this one. Instead, upgrade the priority of the highest priority
    ** existing sample that shares this prefix.  */
    for(i=p->nSample-1; i>=0; i--){
      Stat4Sample *pOld = &p->a[i];
      StatSample *pOld = &p->a[i];
      if( pOld->anEq[pNew->iCol]==0 ){
        if( pOld->isPSample ) return;
        assert( pOld->iCol>pNew->iCol );
        assert( sampleIsBetter(p, pNew, pOld) );
        if( pUpgrade==0 || sampleIsBetter(p, pOld, pUpgrade) ){
          pUpgrade = pOld;
        }
      }
    }
    if( pUpgrade ){
      pUpgrade->iCol = pNew->iCol;
      pUpgrade->anEq[pUpgrade->iCol] = pNew->anEq[pUpgrade->iCol];
      goto find_new_min;
    }
  }
#endif

  /* If necessary, remove sample iMin to make room for the new sample. */
  if( p->nSample>=p->mxSample ){
    Stat4Sample *pMin = &p->a[p->iMin];
    StatSample *pMin = &p->a[p->iMin];
    tRowcnt *anEq = pMin->anEq;
    tRowcnt *anLt = pMin->anLt;
    tRowcnt *anDLt = pMin->anDLt;
    sampleClear(p->db, pMin);
    memmove(pMin, &pMin[1], sizeof(p->a[0])*(p->nSample-p->iMin-1));
    pSample = &p->a[p->nSample-1];
    pSample->nRowid = 0;
    pSample->anEq = anEq;
    pSample->anDLt = anDLt;
    pSample->anLt = anLt;
    p->nSample = p->mxSample-1;
  }

  /* The "rows less-than" for the rowid column must be greater than that
  ** for the last sample in the p->a[] array. Otherwise, the samples would
  ** be out of order. */
#ifdef SQLITE_ENABLE_STAT4
  assert( p->nSample==0 
       || pNew->anLt[p->nCol-1] > p->a[p->nSample-1].anLt[p->nCol-1] );
#endif

  /* Insert the new sample */
  pSample = &p->a[p->nSample];
  sampleCopy(p, pSample, pNew);
  p->nSample++;

  /* Zero the first nEqZero entries in the anEq[] array. */
  memset(pSample->anEq, 0, sizeof(tRowcnt)*nEqZero);

#ifdef SQLITE_ENABLE_STAT4
 find_new_min:
find_new_min:
#endif
  if( p->nSample>=p->mxSample ){
    int iMin = -1;
    for(i=0; i<p->mxSample; i++){
      if( p->a[i].isPSample ) continue;
      if( iMin<0 || sampleIsBetter(p, &p->a[iMin], &p->a[i]) ){
        iMin = i;
      }
    }
    assert( iMin>=0 );
    p->iMin = iMin;
  }
}
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
#endif /* SQLITE_ENABLE_STAT4 */

#ifdef SQLITE_ENABLE_STAT4
/*
** Field iChng of the index being scanned has changed. So at this point
** p->current contains a sample that reflects the previous row of the
** index. The value of anEq[iChng] and subsequent anEq[] elements are
** correct at this point.
*/
static void samplePushPrevious(Stat4Accum *p, int iChng){
static void samplePushPrevious(StatAccum *p, int iChng){
#ifdef SQLITE_ENABLE_STAT4
  int i;

  /* Check if any samples from the aBest[] array should be pushed
  ** into IndexSample.a[] at this point.  */
  for(i=(p->nCol-2); i>=iChng; i--){
    Stat4Sample *pBest = &p->aBest[i];
    StatSample *pBest = &p->aBest[i];
    pBest->anEq[i] = p->current.anEq[i];
    if( p->nSample<p->mxSample || sampleIsBetter(p, pBest, &p->a[p->iMin]) ){
      sampleInsert(p, pBest, i);
    }
  }

  /* Check that no sample contains an anEq[] entry with an index of
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
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
900
901
902
903
904

905
906
907
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
935
936


937
938

939
940
941
942



943
944
945

946
947
948
949
950
951

952
953
954
955
956
957
958
959
960
961
962

963
964
965


966
967
968
969
970

971
972
973
974




























975
976
977
978
979
980
981
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
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
900
901
902
903

904











905
906


907




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
935
936




937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971







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





-
+




-
-
-
-
+
+
+
+

+
+
+
-
+









-
+












+
-
+
+








-
-
+
+




+

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

-
-
-
+
-















-
+

+
+
+
-
+
+
+

-
+



















-
-
+
+






-
+


-
+









-
-
-
+
+
+






+












-
+









-
+


+
+
+
+
+

-
-
+
+

-
+
-
-
+
-
-
-
+
-
-



+
-
+
-


-
-
+
-

-
+






-
+









+
+











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





-
+










-
+
-
-
-
+
+





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







      int j;
      for(j=iChng; j<p->nCol; j++){
        if( p->a[i].anEq[j]==0 ) p->a[i].anEq[j] = p->current.anEq[j];
      }
    }
    p->nMaxEqZero = iChng;
  }
#endif

}
#if defined(SQLITE_ENABLE_STAT3) && !defined(SQLITE_ENABLE_STAT4)
  if( iChng==0 ){
    tRowcnt nLt = p->current.anLt[0];
    tRowcnt nEq = p->current.anEq[0];

    /* Check if this is to be a periodic sample. If so, add it. */
    if( (nLt/p->nPSample)!=(nLt+nEq)/p->nPSample ){
      p->current.isPSample = 1;
      sampleInsert(p, &p->current, 0);
      p->current.isPSample = 0;
    }else 

    /* Or if it is a non-periodic sample. Add it in this case too. */
    if( p->nSample<p->mxSample 
     || sampleIsBetter(p, &p->current, &p->a[p->iMin]) 
    ){
      sampleInsert(p, &p->current, 0);
    }
  }
#endif

#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
#endif /* SQLITE_ENABLE_STAT4 */
  UNUSED_PARAMETER( p );
  UNUSED_PARAMETER( iChng );
#endif
}

/*
** Implementation of the stat_push SQL function:  stat_push(P,C,R)
** Arguments:
**
**    P     Pointer to the Stat4Accum object created by stat_init()
**    P     Pointer to the StatAccum object created by stat_init()
**    C     Index of left-most column to differ from previous row
**    R     Rowid for the current row.  Might be a key record for
**          WITHOUT ROWID tables.
**
** This SQL function always returns NULL.  It's purpose it to accumulate
** statistical data and/or samples in the Stat4Accum object about the
** index being analyzed.  The stat_get() SQL function will later be used to
** extract relevant information for constructing the sqlite_statN tables.
** The purpose of this routine is to collect statistical data and/or
** samples from the index being analyzed into the StatAccum object.
** The stat_get() SQL function will be used afterwards to
** retrieve the information gathered.
**
** This SQL function usually returns NULL, but might return an integer
** if it wants the byte-code to do special processing.
**
** The R parameter is only used for STAT3 and STAT4
** The R parameter is only used for STAT4
*/
static void statPush(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  int i;

  /* The three function arguments */
  Stat4Accum *p = (Stat4Accum*)sqlite3_value_blob(argv[0]);
  StatAccum *p = (StatAccum*)sqlite3_value_blob(argv[0]);
  int iChng = sqlite3_value_int(argv[1]);

  UNUSED_PARAMETER( argc );
  UNUSED_PARAMETER( context );
  assert( p->nCol>0 );
  assert( iChng<p->nCol );

  if( p->nRow==0 ){
    /* This is the first call to this function. Do initialization. */
    for(i=0; i<p->nCol; i++) p->current.anEq[i] = 1;
  }else{
    /* Second and subsequent calls get processed here */
#ifdef SQLITE_ENABLE_STAT4
    samplePushPrevious(p, iChng);
    if( p->mxSample ) samplePushPrevious(p, iChng);
#endif

    /* Update anDLt[], anLt[] and anEq[] to reflect the values that apply
    ** to the current row of the index. */
    for(i=0; i<iChng; i++){
      p->current.anEq[i]++;
    }
    for(i=iChng; i<p->nCol; i++){
      p->current.anDLt[i]++;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
      p->current.anLt[i] += p->current.anEq[i];
#ifdef SQLITE_ENABLE_STAT4
      if( p->mxSample ) p->current.anLt[i] += p->current.anEq[i];
#endif
      p->current.anEq[i] = 1;
    }
  }

  p->nRow++;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  if( sqlite3_value_type(argv[2])==SQLITE_INTEGER ){
    sampleSetRowidInt64(p->db, &p->current, sqlite3_value_int64(argv[2]));
  }else{
    sampleSetRowid(p->db, &p->current, sqlite3_value_bytes(argv[2]),
                                       sqlite3_value_blob(argv[2]));
  }
  p->current.iHash = p->iPrn = p->iPrn*1103515245 + 12345;
#ifdef SQLITE_ENABLE_STAT4
  if( p->mxSample ){
    tRowcnt nLt;
    if( sqlite3_value_type(argv[2])==SQLITE_INTEGER ){
      sampleSetRowidInt64(p->db, &p->current, sqlite3_value_int64(argv[2]));
    }else{
      sampleSetRowid(p->db, &p->current, sqlite3_value_bytes(argv[2]),
                                         sqlite3_value_blob(argv[2]));
    }
    p->current.iHash = p->iPrn = p->iPrn*1103515245 + 12345;
#endif

#ifdef SQLITE_ENABLE_STAT4
  {
    tRowcnt nLt = p->current.anLt[p->nCol-1];
    nLt = p->current.anLt[p->nCol-1];

    /* Check if this is to be a periodic sample. If so, add it. */
    if( (nLt/p->nPSample)!=(nLt+1)/p->nPSample ){
      p->current.isPSample = 1;
      p->current.iCol = 0;
      sampleInsert(p, &p->current, p->nCol-1);
      p->current.isPSample = 0;
    }

    /* Update the aBest[] array. */
    for(i=0; i<(p->nCol-1); i++){
      p->current.iCol = i;
      if( i>=iChng || sampleIsBetterPost(p, &p->current, &p->aBest[i]) ){
        sampleCopy(p, &p->aBest[i], &p->current);
      }
    }
  }
  }else
#endif
  if( p->nLimit && p->nRow>(tRowcnt)p->nLimit*(p->nSkipAhead+1) ){
    p->nSkipAhead++;
    sqlite3_result_int(context, p->current.anDLt[0]>0);
}
  }
}

static const FuncDef statPushFuncdef = {
  2+IsStat34,      /* nArg */
  2+IsStat4,       /* nArg */
  SQLITE_UTF8,     /* funcFlags */
  0,               /* pUserData */
  0,               /* pNext */
  statPush,        /* xSFunc */
  0,               /* xFinalize */
  0, 0,            /* xValue, xInverse */
  "stat_push",     /* zName */
  {0}
};

#define STAT_GET_STAT1 0          /* "stat" column of stat1 table */
#define STAT_GET_ROWID 1          /* "rowid" column of stat[34] entry */
#define STAT_GET_NEQ   2          /* "neq" column of stat[34] entry */
#define STAT_GET_NLT   3          /* "nlt" column of stat[34] entry */
#define STAT_GET_NDLT  4          /* "ndlt" column of stat[34] entry */

/*
** Implementation of the stat_get(P,J) SQL function.  This routine is
** used to query statistical information that has been gathered into
** the Stat4Accum object by prior calls to stat_push().  The P parameter
** has type BLOB but it is really just a pointer to the Stat4Accum object.
** the StatAccum object by prior calls to stat_push().  The P parameter
** has type BLOB but it is really just a pointer to the StatAccum object.
** The content to returned is determined by the parameter J
** which is one of the STAT_GET_xxxx values defined above.
**
** The stat_get(P,J) function is not available to generic SQL.  It is
** inserted as part of a manually constructed bytecode program.  (See
** the callStatGet() routine below.)  It is guaranteed that the P
** parameter will always be a poiner to a Stat4Accum object, never a
** parameter will always be a pointer to a StatAccum object, never a
** NULL.
**
** If neither STAT3 nor STAT4 are enabled, then J is always
** If STAT4 is not enabled, then J is always
** STAT_GET_STAT1 and is hence omitted and this routine becomes
** a one-parameter function, stat_get(P), that always returns the
** stat1 table entry information.
*/
static void statGet(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  Stat4Accum *p = (Stat4Accum*)sqlite3_value_blob(argv[0]);
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  /* STAT3 and STAT4 have a parameter on this routine. */
  StatAccum *p = (StatAccum*)sqlite3_value_blob(argv[0]);
#ifdef SQLITE_ENABLE_STAT4
  /* STAT4 has a parameter on this routine. */
  int eCall = sqlite3_value_int(argv[1]);
  assert( argc==2 );
  assert( eCall==STAT_GET_STAT1 || eCall==STAT_GET_NEQ 
       || eCall==STAT_GET_ROWID || eCall==STAT_GET_NLT
       || eCall==STAT_GET_NDLT 
  );
  assert( eCall==STAT_GET_STAT1 || p->mxSample );
  if( eCall==STAT_GET_STAT1 )
#else
  assert( argc==1 );
#endif
  {
    /* Return the value to store in the "stat" column of the sqlite_stat1
    ** table for this index.
    **
    ** The value is a string composed of a list of integers describing 
    ** the index. The first integer in the list is the total number of 
    ** entries in the index. There is one additional integer in the list 
    ** for each indexed column. This additional integer is an estimate of
    ** the number of rows matched by a stabbing query on the index using
    ** the number of rows matched by a equality query on the index using
    ** a key with the corresponding number of fields. In other words,
    ** if the index is on columns (a,b) and the sqlite_stat1 value is 
    ** "100 10 2", then SQLite estimates that:
    **
    **   * the index contains 100 rows,
    **   * "WHERE a=?" matches 10 rows, and
    **   * "WHERE a=? AND b=?" matches 2 rows.
    **
    ** If D is the count of distinct values and K is the total number of 
    ** rows, then each estimate is computed as:
    ** rows, then each estimate is usually computed as:
    **
    **        I = (K+D-1)/D
    **
    ** In other words, I is K/D rounded up to the next whole integer.
    ** However, if I is between 1.0 and 1.1 (in other words if I is
    ** close to 1.0 but just a little larger) then do not round up but
    ** instead keep the I value at 1.0.
    */
    char *z;
    int i;
    sqlite3_str sStat;   /* Text of the constructed "stat" line */
    int i;               /* Loop counter */

    char *zRet = sqlite3MallocZero( (p->nKeyCol+1)*25 );
    sqlite3StrAccumInit(&sStat, 0, 0, 0, (p->nKeyCol+1)*100);
    if( zRet==0 ){
      sqlite3_result_error_nomem(context);
    sqlite3_str_appendf(&sStat, "%llu", 
      return;
    }

        p->nSkipAhead ? (u64)p->nEst : (u64)p->nRow);
    sqlite3_snprintf(24, zRet, "%llu", (u64)p->nRow);
    z = zRet + sqlite3Strlen30(zRet);
    for(i=0; i<p->nKeyCol; i++){
      u64 nDistinct = p->current.anDLt[i] + 1;
      u64 iVal = (p->nRow + nDistinct - 1) / nDistinct;
      if( iVal==2 && p->nRow*10 <= nDistinct*11 ) iVal = 1;
      sqlite3_snprintf(24, z, " %llu", iVal);
      sqlite3_str_appendf(&sStat, " %llu", iVal);
      z += sqlite3Strlen30(z);
      assert( p->current.anEq[i] );
    }
    assert( z[0]=='\0' && z>zRet );

    sqlite3ResultStrAccum(context, &sStat);
    sqlite3_result_text(context, zRet, -1, sqlite3_free);
  }
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
  else if( eCall==STAT_GET_ROWID ){
    if( p->iGet<0 ){
      samplePushPrevious(p, 0);
      p->iGet = 0;
    }
    if( p->iGet<p->nSample ){
      Stat4Sample *pS = p->a + p->iGet;
      StatSample *pS = p->a + p->iGet;
      if( pS->nRowid==0 ){
        sqlite3_result_int64(context, pS->u.iRowid);
      }else{
        sqlite3_result_blob(context, pS->u.aRowid, pS->nRowid,
                            SQLITE_TRANSIENT);
      }
    }
  }else{
    tRowcnt *aCnt = 0;
    sqlite3_str sStat;
    int i;

    assert( p->iGet<p->nSample );
    switch( eCall ){
      case STAT_GET_NEQ:  aCnt = p->a[p->iGet].anEq; break;
      case STAT_GET_NLT:  aCnt = p->a[p->iGet].anLt; break;
      default: {
        aCnt = p->a[p->iGet].anDLt; 
        p->iGet++;
        break;
      }
    }

    sqlite3StrAccumInit(&sStat, 0, 0, 0, p->nCol*100);
    if( IsStat3 ){
      sqlite3_result_int64(context, (i64)aCnt[0]);
    }else{
      char *zRet = sqlite3MallocZero(p->nCol * 25);
      if( zRet==0 ){
        sqlite3_result_error_nomem(context);
      }else{
        int i;
        char *z = zRet;
        for(i=0; i<p->nCol; i++){
          sqlite3_snprintf(24, z, "%llu ", (u64)aCnt[i]);
    for(i=0; i<p->nCol; i++){
      sqlite3_str_appendf(&sStat, "%llu ", (u64)aCnt[i]);
          z += sqlite3Strlen30(z);
        }
    }
        assert( z[0]=='\0' && z>zRet );
        z[-1] = '\0';
        sqlite3_result_text(context, zRet, -1, sqlite3_free);
      }
    if( sStat.nChar ) sStat.nChar--;
    sqlite3ResultStrAccum(context, &sStat);
  }
    }
  }
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
#endif /* SQLITE_ENABLE_STAT4 */
#ifndef SQLITE_DEBUG
  UNUSED_PARAMETER( argc );
#endif
}
static const FuncDef statGetFuncdef = {
  1+IsStat34,      /* nArg */
  1+IsStat4,       /* nArg */
  SQLITE_UTF8,     /* funcFlags */
  0,               /* pUserData */
  0,               /* pNext */
  statGet,         /* xSFunc */
  0,               /* xFinalize */
  0, 0,            /* xValue, xInverse */
  "stat_get",      /* zName */
  {0}
};

static void callStatGet(Vdbe *v, int regStat4, int iParam, int regOut){
static void callStatGet(Parse *pParse, int regStat, int iParam, int regOut){
  assert( regOut!=regStat4 && regOut!=regStat4+1 );
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  sqlite3VdbeAddOp2(v, OP_Integer, iParam, regStat4+1);
#ifdef SQLITE_ENABLE_STAT4
  sqlite3VdbeAddOp2(pParse->pVdbe, OP_Integer, iParam, regStat+1);
#elif SQLITE_DEBUG
  assert( iParam==STAT_GET_STAT1 );
#else
  UNUSED_PARAMETER( iParam );
#endif
  assert( regOut!=regStat && regOut!=regStat+1 );
  sqlite3VdbeAddOp4(v, OP_Function0, 0, regStat4, regOut,
                    (char*)&statGetFuncdef, P4_FUNCDEF);
  sqlite3VdbeChangeP5(v, 1 + IsStat34);
}
  sqlite3VdbeAddFunctionCall(pParse, 0, regStat, regOut, 1+IsStat4,
                             &statGetFuncdef, 0);
}

#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
/* Add a comment to the most recent VDBE opcode that is the name
** of the k-th column of the pIdx index.
*/
static void analyzeVdbeCommentIndexWithColumnName(
  Vdbe *v,         /* Prepared statement under construction */
  Index *pIdx,     /* Index whose column is being loaded */
  int k            /* Which column index */
){
  int i;           /* Index of column in the table */
  assert( k>=0 && k<pIdx->nColumn );
  i = pIdx->aiColumn[k];
  if( NEVER(i==XN_ROWID) ){
    VdbeComment((v,"%s.rowid",pIdx->zName));
  }else if( i==XN_EXPR ){
    assert( pIdx->bHasExpr );
    VdbeComment((v,"%s.expr(%d)",pIdx->zName, k));
  }else{
    VdbeComment((v,"%s.%s", pIdx->zName, pIdx->pTable->aCol[i].zCnName));
  }
}
#else
# define analyzeVdbeCommentIndexWithColumnName(a,b,c)
#endif /* SQLITE_DEBUG */

/*
** Generate code to do an analysis of all indices associated with
** a single table.
*/
static void analyzeOneTable(
  Parse *pParse,   /* Parser context */
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
981
982
983
984
985
986
987

988
989

990

991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005

1006
1007
1008
1009
1010
1011
1012
1013







-
+

-

-

+













-
+







  int iTabCur;                 /* Table cursor */
  Vdbe *v;                     /* The virtual machine being built up */
  int i;                       /* Loop counter */
  int jZeroRows = -1;          /* Jump from here if number of rows is zero */
  int iDb;                     /* Index of database containing pTab */
  u8 needTableCnt = 1;         /* True to count the table */
  int regNewRowid = iMem++;    /* Rowid for the inserted record */
  int regStat4 = iMem++;       /* Register to hold Stat4Accum object */
  int regStat = iMem++;        /* Register to hold StatAccum object */
  int regChng = iMem++;        /* Index of changed index field */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  int regRowid = iMem++;       /* Rowid argument passed to stat_push() */
#endif
  int regTemp = iMem++;        /* Temporary use register */
  int regTemp2 = iMem++;       /* Second temporary use register */
  int regTabname = iMem++;     /* Register containing table name */
  int regIdxname = iMem++;     /* Register containing index name */
  int regStat1 = iMem++;       /* Value for the stat column of sqlite_stat1 */
  int regPrev = iMem;          /* MUST BE LAST (see below) */
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
  Table *pStat1 = 0; 
#endif

  pParse->nMem = MAX(pParse->nMem, iMem);
  v = sqlite3GetVdbe(pParse);
  if( v==0 || NEVER(pTab==0) ){
    return;
  }
  if( pTab->tnum==0 ){
  if( !IsOrdinaryTable(pTab) ){
    /* Do not gather statistics on views or virtual tables */
    return;
  }
  if( sqlite3_strlike("sqlite\\_%", pTab->zName, '\\')==0 ){
    /* Do not gather statistics on system tables */
    return;
  }
1037
1038
1039
1040
1041
1042
1043
1044

1045
1046
1047
1048
1049
1050
1051
1026
1027
1028
1029
1030
1031
1032

1033
1034
1035
1036
1037
1038
1039
1040







-
+







  if( db->xPreUpdateCallback ){
    pStat1 = (Table*)sqlite3DbMallocZero(db, sizeof(Table) + 13);
    if( pStat1==0 ) return;
    pStat1->zName = (char*)&pStat1[1];
    memcpy(pStat1->zName, "sqlite_stat1", 13);
    pStat1->nCol = 3;
    pStat1->iPKey = -1;
    sqlite3VdbeAddOp4(pParse->pVdbe, OP_Noop, 0, 0, 0,(char*)pStat1,P4_DYNBLOB);
    sqlite3VdbeAddOp4(pParse->pVdbe, OP_Noop, 0, 0, 0,(char*)pStat1,P4_DYNAMIC);
  }
#endif

  /* Establish a read-lock on the table at the shared-cache level. 
  ** Open a read-only cursor on the table. Also allocate a cursor number
  ** to use for scanning indexes (iIdxCur). No index cursor is opened at
  ** this time though.  */
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
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







-
+
-
-
-

+
+
+
-
-
+
+
+
+
+
+

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









-
-




-
+







    VdbeComment((v, "%s", pIdx->zName));

    /* Invoke the stat_init() function. The arguments are:
    ** 
    **    (1) the number of columns in the index including the rowid
    **        (or for a WITHOUT ROWID table, the number of PK columns),
    **    (2) the number of columns in the key without the rowid/pk
    **    (3) the number of rows in the index,
    **    (3) estimated number of rows in the index,
    **
    **
    ** The third argument is only used for STAT3 and STAT4
    */
    sqlite3VdbeAddOp2(v, OP_Integer, nCol, regStat+1);
    assert( regRowid==regStat+2 );
    sqlite3VdbeAddOp2(v, OP_Integer, pIdx->nKeyCol, regRowid);
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
    sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regStat4+3);
#ifdef SQLITE_ENABLE_STAT4
    if( OptimizationEnabled(db, SQLITE_Stat4) ){
      sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regTemp);
      addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur);
      VdbeCoverage(v);
    }else
#endif
    {
    sqlite3VdbeAddOp2(v, OP_Integer, nCol, regStat4+1);
    sqlite3VdbeAddOp2(v, OP_Integer, pIdx->nKeyCol, regStat4+2);
    sqlite3VdbeAddOp4(v, OP_Function0, 0, regStat4+1, regStat4,
                     (char*)&statInitFuncdef, P4_FUNCDEF);
      addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur);
      VdbeCoverage(v);
      sqlite3VdbeAddOp3(v, OP_Count, iIdxCur, regTemp, 1);
    }
    assert( regTemp2==regStat+4 );
    sqlite3VdbeAddOp2(v, OP_Integer, db->nAnalysisLimit, regTemp2);
    sqlite3VdbeAddFunctionCall(pParse, 0, regStat+1, regStat, 4,
                               &statInitFuncdef, 0);
    sqlite3VdbeChangeP5(v, 2+IsStat34);

    /* Implementation of the following:
    **
    **   Rewind csr
    **   if eof(csr) goto end_of_scan;
    **   regChng = 0
    **   goto next_push_0;
    **
    */
    addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur);
    VdbeCoverage(v);
    sqlite3VdbeAddOp2(v, OP_Integer, 0, regChng);
    addrNextRow = sqlite3VdbeCurrentAddr(v);

    if( nColTest>0 ){
      int endDistinctTest = sqlite3VdbeMakeLabel(v);
      int endDistinctTest = sqlite3VdbeMakeLabel(pParse);
      int *aGotoChng;               /* Array of jump instruction addresses */
      aGotoChng = sqlite3DbMallocRawNN(db, sizeof(int)*nColTest);
      if( aGotoChng==0 ) continue;

      /*
      **  next_row:
      **   regChng = 0
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
1286
1287
1288
1289
1290
1291
1292

1293
1294
1295
1296
1297
1298
1299
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
1286
1287
1288
1289



1290
1291
1292
1293

1294
1295
1296
1297
1298
1299

1300
1301
1302
1303
1304
1305
1306
1307







+




















+







-
-
+
+



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

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


-
+









-
-
+
+
-
+













-
+


-
-
-
+
+
+


-
-
-




-






-
+







        sqlite3VdbeAddOp2(v, OP_NotNull, regPrev, endDistinctTest);
        VdbeCoverage(v);
      }
      for(i=0; i<nColTest; i++){
        char *pColl = (char*)sqlite3LocateCollSeq(pParse, pIdx->azColl[i]);
        sqlite3VdbeAddOp2(v, OP_Integer, i, regChng);
        sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regTemp);
        analyzeVdbeCommentIndexWithColumnName(v,pIdx,i);
        aGotoChng[i] = 
        sqlite3VdbeAddOp4(v, OP_Ne, regTemp, 0, regPrev+i, pColl, P4_COLLSEQ);
        sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
        VdbeCoverage(v);
      }
      sqlite3VdbeAddOp2(v, OP_Integer, nColTest, regChng);
      sqlite3VdbeGoto(v, endDistinctTest);
  
  
      /*
      **  chng_addr_0:
      **   regPrev(0) = idx(0)
      **  chng_addr_1:
      **   regPrev(1) = idx(1)
      **  ...
      */
      sqlite3VdbeJumpHere(v, addrNextRow-1);
      for(i=0; i<nColTest; i++){
        sqlite3VdbeJumpHere(v, aGotoChng[i]);
        sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regPrev+i);
        analyzeVdbeCommentIndexWithColumnName(v,pIdx,i);
      }
      sqlite3VdbeResolveLabel(v, endDistinctTest);
      sqlite3DbFree(db, aGotoChng);
    }
  
    /*
    **  chng_addr_N:
    **   regRowid = idx(rowid)            // STAT34 only
    **   stat_push(P, regChng, regRowid)  // 3rd parameter STAT34 only
    **   regRowid = idx(rowid)            // STAT4 only
    **   stat_push(P, regChng, regRowid)  // 3rd parameter STAT4 only
    **   Next csr
    **   if !eof(csr) goto next_row;
    */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
    assert( regRowid==(regStat4+2) );
    if( HasRowid(pTab) ){
      sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, regRowid);
    }else{
      Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);
      int j, k, regKey;
      regKey = sqlite3GetTempRange(pParse, pPk->nKeyCol);
      for(j=0; j<pPk->nKeyCol; j++){
        k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[j]);
        assert( k>=0 && k<pIdx->nColumn );
        sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, regKey+j);
        VdbeComment((v, "%s", pTab->aCol[pPk->aiColumn[j]].zName));
      }
      sqlite3VdbeAddOp3(v, OP_MakeRecord, regKey, pPk->nKeyCol, regRowid);
      sqlite3ReleaseTempRange(pParse, regKey, pPk->nKeyCol);
    }
#ifdef SQLITE_ENABLE_STAT4
    if( OptimizationEnabled(db, SQLITE_Stat4) ){
      assert( regRowid==(regStat+2) );
      if( HasRowid(pTab) ){
        sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, regRowid);
      }else{
        Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);
        int j, k, regKey;
        regKey = sqlite3GetTempRange(pParse, pPk->nKeyCol);
        for(j=0; j<pPk->nKeyCol; j++){
          k = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[j]);
          assert( k>=0 && k<pIdx->nColumn );
          sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, regKey+j);
          analyzeVdbeCommentIndexWithColumnName(v,pIdx,k);
        }
        sqlite3VdbeAddOp3(v, OP_MakeRecord, regKey, pPk->nKeyCol, regRowid);
        sqlite3ReleaseTempRange(pParse, regKey, pPk->nKeyCol);
      }
    }
#endif
    assert( regChng==(regStat4+1) );
    sqlite3VdbeAddOp4(v, OP_Function0, 1, regStat4, regTemp,
                     (char*)&statPushFuncdef, P4_FUNCDEF);
    sqlite3VdbeChangeP5(v, 2+IsStat34);
    sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v);
    assert( regChng==(regStat+1) );
    {
      sqlite3VdbeAddFunctionCall(pParse, 1, regStat, regTemp, 2+IsStat4,
                                 &statPushFuncdef, 0);
      if( db->nAnalysisLimit ){
        int j1, j2, j3;
        j1 = sqlite3VdbeAddOp1(v, OP_IsNull, regTemp); VdbeCoverage(v);
        j2 = sqlite3VdbeAddOp1(v, OP_If, regTemp); VdbeCoverage(v);
        j3 = sqlite3VdbeAddOp4Int(v, OP_SeekGT, iIdxCur, 0, regPrev, 1);
        VdbeCoverage(v);
        sqlite3VdbeJumpHere(v, j1);
        sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v);
        sqlite3VdbeJumpHere(v, j2);
        sqlite3VdbeJumpHere(v, j3);
      }else{
        sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v);
      }
    }

    /* Add the entry to the stat1 table. */
    callStatGet(v, regStat4, STAT_GET_STAT1, regStat1);
    callStatGet(pParse, regStat, STAT_GET_STAT1, regStat1);
    assert( "BBB"[0]==SQLITE_AFF_TEXT );
    sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "BBB", 0);
    sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
    sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regTemp, regNewRowid);
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
    sqlite3VdbeChangeP4(v, -1, (char*)pStat1, P4_TABLE);
#endif
    sqlite3VdbeChangeP5(v, OPFLAG_APPEND);

    /* Add the entries to the stat3 or stat4 table. */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
    /* Add the entries to the stat4 table. */
#ifdef SQLITE_ENABLE_STAT4
    {
    if( OptimizationEnabled(db, SQLITE_Stat4) && db->nAnalysisLimit==0 ){
      int regEq = regStat1;
      int regLt = regStat1+1;
      int regDLt = regStat1+2;
      int regSample = regStat1+3;
      int regCol = regStat1+4;
      int regSampleRowid = regCol + nCol;
      int addrNext;
      int addrIsNull;
      u8 seekOp = HasRowid(pTab) ? OP_NotExists : OP_NotFound;

      pParse->nMem = MAX(pParse->nMem, regCol+nCol);

      addrNext = sqlite3VdbeCurrentAddr(v);
      callStatGet(v, regStat4, STAT_GET_ROWID, regSampleRowid);
      callStatGet(pParse, regStat, STAT_GET_ROWID, regSampleRowid);
      addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regSampleRowid);
      VdbeCoverage(v);
      callStatGet(v, regStat4, STAT_GET_NEQ, regEq);
      callStatGet(v, regStat4, STAT_GET_NLT, regLt);
      callStatGet(v, regStat4, STAT_GET_NDLT, regDLt);
      callStatGet(pParse, regStat, STAT_GET_NEQ, regEq);
      callStatGet(pParse, regStat, STAT_GET_NLT, regLt);
      callStatGet(pParse, regStat, STAT_GET_NDLT, regDLt);
      sqlite3VdbeAddOp4Int(v, seekOp, iTabCur, addrNext, regSampleRowid, 0);
      VdbeCoverage(v);
#ifdef SQLITE_ENABLE_STAT3
      sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iTabCur, 0, regSample);
#else
      for(i=0; i<nCol; i++){
        sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iTabCur, i, regCol+i);
      }
      sqlite3VdbeAddOp3(v, OP_MakeRecord, regCol, nCol, regSample);
#endif
      sqlite3VdbeAddOp3(v, OP_MakeRecord, regTabname, 6, regTemp);
      sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur+1, regNewRowid);
      sqlite3VdbeAddOp3(v, OP_Insert, iStatCur+1, regTemp, regNewRowid);
      sqlite3VdbeAddOp2(v, OP_Goto, 1, addrNext); /* P1==1 for end-of-loop */
      sqlite3VdbeJumpHere(v, addrIsNull);
    }
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
#endif /* SQLITE_ENABLE_STAT4 */

    /* End of analysis */
    sqlite3VdbeJumpHere(v, addrRewind);
  }


  /* Create a single sqlite_stat1 entry containing NULL as the index
1460
1461
1462
1463
1464
1465
1466
1467

1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478

1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489

1490
1491
1492
1493
1494
1495
1496
1497
1498
1499


1500

1501
1502
1503
1504
1505
1506
1507
1468
1469
1470
1471
1472
1473
1474

1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485

1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496

1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509

1510
1511
1512
1513
1514
1515
1516
1517







-
+










-
+










-
+










+
+
-
+







  Index *pIndex          /* Handle extra flags for this index, if not NULL */
){
  char *z = zIntArray;
  int c;
  int i;
  tRowcnt v;

#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
  if( z==0 ) z = "";
#else
  assert( z!=0 );
#endif
  for(i=0; *z && i<nOut; i++){
    v = 0;
    while( (c=z[0])>='0' && c<='9' ){
      v = v*10 + c - '0';
      z++;
    }
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
    if( aOut ) aOut[i] = v;
    if( aLog ) aLog[i] = sqlite3LogEst(v);
#else
    assert( aOut==0 );
    UNUSED_PARAMETER(aOut);
    assert( aLog!=0 );
    aLog[i] = sqlite3LogEst(v);
#endif
    if( *z==' ' ) z++;
  }
#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
#ifndef SQLITE_ENABLE_STAT4
  assert( pIndex!=0 ); {
#else
  if( pIndex ){
#endif
    pIndex->bUnordered = 0;
    pIndex->noSkipScan = 0;
    while( z[0] ){
      if( sqlite3_strglob("unordered*", z)==0 ){
        pIndex->bUnordered = 1;
      }else if( sqlite3_strglob("sz=[0-9]*", z)==0 ){
        int sz = sqlite3Atoi(z+3);
        if( sz<2 ) sz = 2;
        pIndex->szIdxRow = sqlite3LogEst(sqlite3Atoi(z+3));
        pIndex->szIdxRow = sqlite3LogEst(sz);
      }else if( sqlite3_strglob("noskipscan*", z)==0 ){
        pIndex->noSkipScan = 1;
      }
#ifdef SQLITE_ENABLE_COSTMULT
      else if( sqlite3_strglob("costmult=[0-9]*",z)==0 ){
        pIndex->pTable->costMult = sqlite3LogEst(sqlite3Atoi(z+9));
      }
1547
1548
1549
1550
1551
1552
1553
1554

1555
1556
1557
1558
1559
1560
1561
1557
1558
1559
1560
1561
1562
1563

1564
1565
1566
1567
1568
1569
1570
1571







-
+







    pIndex = sqlite3FindIndex(pInfo->db, argv[1], pInfo->zDatabase);
  }
  z = argv[2];

  if( pIndex ){
    tRowcnt *aiRowEst = 0;
    int nCol = pIndex->nKeyCol+1;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
    /* Index.aiRowEst may already be set here if there are duplicate 
    ** sqlite_stat1 entries for this index. In that case just clobber
    ** the old data with the new instead of allocating a new array.  */
    if( pIndex->aiRowEst==0 ){
      pIndex->aiRowEst = (tRowcnt*)sqlite3MallocZero(sizeof(tRowcnt) * nCol);
      if( pIndex->aiRowEst==0 ) sqlite3OomFault(pInfo->db);
    }
1583
1584
1585
1586
1587
1588
1589


1590

1591
1592
1593
1594
1595
1596
1597
1598
1599

1600
1601
1602
1603
1604
1605
1606

1607
1608
1609

1610
1611
1612
1613
1614
1615
1616
1593
1594
1595
1596
1597
1598
1599
1600
1601

1602
1603
1604
1605
1606
1607
1608
1609
1610

1611
1612
1613
1614
1615
1616
1617

1618
1619
1620

1621
1622
1623
1624
1625
1626
1627
1628







+
+
-
+








-
+






-
+


-
+







}

/*
** If the Index.aSample variable is not NULL, delete the aSample[] array
** and its contents.
*/
void sqlite3DeleteIndexSamples(sqlite3 *db, Index *pIdx){
  assert( db!=0 );
  assert( pIdx!=0 );
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
  if( pIdx->aSample ){
    int j;
    for(j=0; j<pIdx->nSample; j++){
      IndexSample *p = &pIdx->aSample[j];
      sqlite3DbFree(db, p->p);
    }
    sqlite3DbFree(db, pIdx->aSample);
  }
  if( db && db->pnBytesFreed==0 ){
  if( db->pnBytesFreed==0 ){
    pIdx->nSample = 0;
    pIdx->aSample = 0;
  }
#else
  UNUSED_PARAMETER(db);
  UNUSED_PARAMETER(pIdx);
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
#endif /* SQLITE_ENABLE_STAT4 */
}

#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
/*
** Populate the pIdx->aAvgEq[] array based on the samples currently
** stored in pIdx->aSample[]. 
*/
static void initAvgEq(Index *pIdx){
  if( pIdx ){
    IndexSample *aSample = pIdx->aSample;
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
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







-
+



-
+
-








-







    Table *pTab = sqlite3FindTable(db, zName, zDb);
    if( pTab && !HasRowid(pTab) ) pIdx = sqlite3PrimaryKeyIndex(pTab);
  }
  return pIdx;
}

/*
** Load the content from either the sqlite_stat4 or sqlite_stat3 table 
** Load the content from either the sqlite_stat4
** into the relevant Index.aSample[] arrays.
**
** Arguments zSql1 and zSql2 must point to SQL statements that return
** data equivalent to the following (statements are different for stat3,
** data equivalent to the following:
** see the caller of this function for details):
**
**    zSql1: SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx
**    zSql2: SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat4
**
** where %Q is replaced with the database name before the SQL is executed.
*/
static int loadStatTbl(
  sqlite3 *db,                  /* Database handle */
  int bStat3,                   /* Assume single column records only */
  const char *zSql1,            /* SQL statement 1 (see above) */
  const char *zSql2,            /* SQL statement 2 (see above) */
  const char *zDb               /* Database name (e.g. "main") */
){
  int rc;                       /* Result codes from subroutines */
  sqlite3_stmt *pStmt = 0;      /* An SQL statement being run */
  char *zSql;                   /* Text of the SQL statement */
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
1755
1756
1757
1758

1759
1760
1761
1762
1763
1764
1765
1738
1739
1740
1741
1742
1743
1744

1745



1746






1747
1748
1749
1750
1751

1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772







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













+







    int i;          /* Bytes of space required */
    tRowcnt *pSpace;

    zIndex = (char *)sqlite3_column_text(pStmt, 0);
    if( zIndex==0 ) continue;
    nSample = sqlite3_column_int(pStmt, 1);
    pIdx = findIndexOrPrimaryKey(db, zIndex, zDb);
    assert( pIdx==0 || bStat3 || pIdx->nSample==0 );
    assert( pIdx==0 || pIdx->nSample==0 );
    /* Index.nSample is non-zero at this point if data has already been
    ** loaded from the stat4 table. In this case ignore stat3 data.  */
    if( pIdx==0 || pIdx->nSample ) continue;
    if( pIdx==0 ) continue;
    if( bStat3==0 ){
      assert( !HasRowid(pIdx->pTable) || pIdx->nColumn==pIdx->nKeyCol+1 );
      if( !HasRowid(pIdx->pTable) && IsPrimaryKeyIndex(pIdx) ){
        nIdxCol = pIdx->nKeyCol;
      }else{
        nIdxCol = pIdx->nColumn;
    assert( !HasRowid(pIdx->pTable) || pIdx->nColumn==pIdx->nKeyCol+1 );
    if( !HasRowid(pIdx->pTable) && IsPrimaryKeyIndex(pIdx) ){
      nIdxCol = pIdx->nKeyCol;
    }else{
      nIdxCol = pIdx->nColumn;
      }
    }
    pIdx->nSampleCol = nIdxCol;
    nByte = sizeof(IndexSample) * nSample;
    nByte += sizeof(tRowcnt) * nIdxCol * 3 * nSample;
    nByte += nIdxCol * sizeof(tRowcnt);     /* Space for Index.aAvgEq[] */

    pIdx->aSample = sqlite3DbMallocZero(db, nByte);
    if( pIdx->aSample==0 ){
      sqlite3_finalize(pStmt);
      return SQLITE_NOMEM_BKPT;
    }
    pSpace = (tRowcnt*)&pIdx->aSample[nSample];
    pIdx->aAvgEq = pSpace; pSpace += nIdxCol;
    pIdx->pTable->tabFlags |= TF_HasStat4;
    for(i=0; i<nSample; i++){
      pIdx->aSample[i].anEq = pSpace; pSpace += nIdxCol;
      pIdx->aSample[i].anLt = pSpace; pSpace += nIdxCol;
      pIdx->aSample[i].anDLt = pSpace; pSpace += nIdxCol;
    }
    assert( ((u8*)pSpace)-nByte==(u8*)(pIdx->aSample) );
  }
1780
1781
1782
1783
1784
1785
1786
1787

1788
1789
1790
1791
1792
1793
1794
1795
1796
1787
1788
1789
1790
1791
1792
1793

1794
1795

1796
1797
1798
1799
1800
1801
1802







-
+

-







    int nCol = 1;                 /* Number of columns in index */

    zIndex = (char *)sqlite3_column_text(pStmt, 0);
    if( zIndex==0 ) continue;
    pIdx = findIndexOrPrimaryKey(db, zIndex, zDb);
    if( pIdx==0 ) continue;
    /* This next condition is true if data has already been loaded from 
    ** the sqlite_stat4 table. In this case ignore stat3 data.  */
    ** the sqlite_stat4 table. */
    nCol = pIdx->nSampleCol;
    if( bStat3 && nCol>1 ) continue;
    if( pIdx!=pPrevIdx ){
      initAvgEq(pPrevIdx);
      pPrevIdx = pIdx;
    }
    pSample = &pIdx->aSample[pIdx->nSample];
    decodeIntArray((char*)sqlite3_column_text(pStmt,1),nCol,pSample->anEq,0,0);
    decodeIntArray((char*)sqlite3_column_text(pStmt,2),nCol,pSample->anLt,0,0);
1815
1816
1817
1818
1819
1820
1821
1822

1823
1824
1825
1826

1827
1828
1829
1830




1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847

1848
1849
1850

1851
1852

1853
1854
1855
1856
1857


1858
1859
1860

1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874

1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888

1889
1890
1891
1892
1893
1894
1895
1896
1897



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

1917
1918

1919
1920

1921
1922
1923
1924
1925
1926
1927
1821
1822
1823
1824
1825
1826
1827

1828
1829
1830
1831
1832
1833
1834
1835


1836
1837
1838
1839
1840
1841
1842
1843
1844









1845
1846

1847
1848
1849

1850
1851

1852
1853
1854
1855


1856
1857
1858
1859

1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888

1889
1890
1891
1892
1893
1894
1895
1896
1897

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

1919
1920

1921
1922

1923
1924
1925
1926
1927
1928
1929
1930







-
+




+


-
-
+
+
+
+





-
-
-
-
-
-
-
-
-


-
+


-
+

-
+



-
-
+
+


-
+














+













-
+








-
+
+
+


















-
+

-
+

-
+







  }
  rc = sqlite3_finalize(pStmt);
  if( rc==SQLITE_OK ) initAvgEq(pPrevIdx);
  return rc;
}

/*
** Load content from the sqlite_stat4 and sqlite_stat3 tables into 
** Load content from the sqlite_stat4 table into 
** the Index.aSample[] arrays of all indices.
*/
static int loadStat4(sqlite3 *db, const char *zDb){
  int rc = SQLITE_OK;             /* Result codes from subroutines */
  const Table *pStat4;

  assert( db->lookaside.bDisable );
  if( sqlite3FindTable(db, "sqlite_stat4", zDb) ){
    rc = loadStatTbl(db, 0,
  if( (pStat4 = sqlite3FindTable(db, "sqlite_stat4", zDb))!=0
   && IsOrdinaryTable(pStat4)
  ){
    rc = loadStatTbl(db,
      "SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx", 
      "SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat4",
      zDb
    );
  }

  if( rc==SQLITE_OK && sqlite3FindTable(db, "sqlite_stat3", zDb) ){
    rc = loadStatTbl(db, 1,
      "SELECT idx,count(*) FROM %Q.sqlite_stat3 GROUP BY idx", 
      "SELECT idx,neq,nlt,ndlt,sqlite_record(sample) FROM %Q.sqlite_stat3",
      zDb
    );
  }

  return rc;
}
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
#endif /* SQLITE_ENABLE_STAT4 */

/*
** Load the content of the sqlite_stat1 and sqlite_stat3/4 tables. The
** Load the content of the sqlite_stat1 and sqlite_stat4 tables. The
** contents of sqlite_stat1 are used to populate the Index.aiRowEst[]
** arrays. The contents of sqlite_stat3/4 are used to populate the
** arrays. The contents of sqlite_stat4 are used to populate the
** Index.aSample[] arrays.
**
** If the sqlite_stat1 table is not present in the database, SQLITE_ERROR
** is returned. In this case, even if SQLITE_ENABLE_STAT3/4 was defined 
** during compilation and the sqlite_stat3/4 table is present, no data is 
** is returned. In this case, even if SQLITE_ENABLE_STAT4 was defined 
** during compilation and the sqlite_stat4 table is present, no data is 
** read from it.
**
** If SQLITE_ENABLE_STAT3/4 was defined during compilation and the 
** If SQLITE_ENABLE_STAT4 was defined during compilation and the 
** sqlite_stat4 table is not present in the database, SQLITE_ERROR is
** returned. However, in this case, data is read from the sqlite_stat1
** table (if it is present) before returning.
**
** If an OOM error occurs, this function always sets db->mallocFailed.
** This means if the caller does not care about other errors, the return
** code may be ignored.
*/
int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
  analysisInfo sInfo;
  HashElem *i;
  char *zSql;
  int rc = SQLITE_OK;
  Schema *pSchema = db->aDb[iDb].pSchema;
  const Table *pStat1;

  assert( iDb>=0 && iDb<db->nDb );
  assert( db->aDb[iDb].pBt!=0 );

  /* Clear any prior statistics */
  assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
  for(i=sqliteHashFirst(&pSchema->tblHash); i; i=sqliteHashNext(i)){
    Table *pTab = sqliteHashData(i);
    pTab->tabFlags &= ~TF_HasStat1;
  }
  for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){
    Index *pIdx = sqliteHashData(i);
    pIdx->hasStat1 = 0;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
    sqlite3DeleteIndexSamples(db, pIdx);
    pIdx->aSample = 0;
#endif
  }

  /* Load new statistics out of the sqlite_stat1 table */
  sInfo.db = db;
  sInfo.zDatabase = db->aDb[iDb].zDbSName;
  if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)!=0 ){
  if( (pStat1 = sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase))
   && IsOrdinaryTable(pStat1)
  ){
    zSql = sqlite3MPrintf(db, 
        "SELECT tbl,idx,stat FROM %Q.sqlite_stat1", sInfo.zDatabase);
    if( zSql==0 ){
      rc = SQLITE_NOMEM_BKPT;
    }else{
      rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0);
      sqlite3DbFree(db, zSql);
    }
  }

  /* Set appropriate defaults on all indexes not in the sqlite_stat1 table */
  assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
  for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){
    Index *pIdx = sqliteHashData(i);
    if( !pIdx->hasStat1 ) sqlite3DefaultRowEst(pIdx);
  }

  /* Load the statistics from the sqlite_stat4 table. */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
  if( rc==SQLITE_OK ){
    db->lookaside.bDisable++;
    DisableLookaside;
    rc = loadStat4(db, sInfo.zDatabase);
    db->lookaside.bDisable--;
    EnableLookaside;
  }
  for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){
    Index *pIdx = sqliteHashData(i);
    sqlite3_free(pIdx->aiRowEst);
    pIdx->aiRowEst = 0;
  }
#endif

Changes to src/attach.c.

40
41
42
43
44
45
46











47
48
49
50
51
52
53
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







+
+
+
+
+
+
+
+
+
+
+







      rc = sqlite3ResolveExprNames(pName, pExpr);
    }else{
      pExpr->op = TK_STRING;
    }
  }
  return rc;
}

/*
** Return true if zName points to a name that may be used to refer to
** database iDb attached to handle db.
*/
int sqlite3DbIsNamed(sqlite3 *db, int iDb, const char *zName){
  return (
      sqlite3StrICmp(db->aDb[iDb].zDbSName, zName)==0
   || (iDb==0 && sqlite3StrICmp("main", zName)==0)
  );
}

/*
** An SQL user-function registered to do the work of an ATTACH statement. The
** three arguments to the function come directly from an attach statement:
**
**     ATTACH DATABASE x AS y KEY z
**
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
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







-
+









-
+









+


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
















-
-
-
+
+







  sqlite3 *db = sqlite3_context_db_handle(context);
  const char *zName;
  const char *zFile;
  char *zPath = 0;
  char *zErr = 0;
  unsigned int flags;
  Db *aNew;                 /* New array of Db pointers */
  Db *pNew;                 /* Db object for the newly attached database */
  Db *pNew = 0;             /* Db object for the newly attached database */
  char *zErrDyn = 0;
  sqlite3_vfs *pVfs;

  UNUSED_PARAMETER(NotUsed);
  zFile = (const char *)sqlite3_value_text(argv[0]);
  zName = (const char *)sqlite3_value_text(argv[1]);
  if( zFile==0 ) zFile = "";
  if( zName==0 ) zName = "";

#ifdef SQLITE_ENABLE_DESERIALIZE
#ifndef SQLITE_OMIT_DESERIALIZE
# define REOPEN_AS_MEMDB(db)  (db->init.reopenMemdb)
#else
# define REOPEN_AS_MEMDB(db)  (0)
#endif

  if( REOPEN_AS_MEMDB(db) ){
    /* This is not a real ATTACH.  Instead, this routine is being called
    ** from sqlite3_deserialize() to close database db->init.iDb and
    ** reopen it as a MemDB */
    Btree *pNewBt = 0;
    pVfs = sqlite3_vfs_find("memdb");
    if( pVfs==0 ) return;
    rc = sqlite3BtreeOpen(pVfs, "x\0", db, &pNewBt, 0, SQLITE_OPEN_MAIN_DB);
    if( rc==SQLITE_OK ){
      Schema *pNewSchema = sqlite3SchemaGet(db, pNewBt);
      if( pNewSchema ){
        /* Both the Btree and the new Schema were allocated successfully.
        ** Close the old db and update the aDb[] slot with the new memdb
        ** values.  */
    pNew = &db->aDb[db->init.iDb];
    if( pNew->pBt ) sqlite3BtreeClose(pNew->pBt);
    pNew->pBt = 0;
    pNew->pSchema = 0;
    rc = sqlite3BtreeOpen(pVfs, "x\0", db, &pNew->pBt, 0, SQLITE_OPEN_MAIN_DB);
        pNew = &db->aDb[db->init.iDb];
        if( ALWAYS(pNew->pBt) ) sqlite3BtreeClose(pNew->pBt);
        pNew->pBt = pNewBt;
        pNew->pSchema = pNewSchema;
      }else{
        sqlite3BtreeClose(pNewBt);
        rc = SQLITE_NOMEM;
      }
    }
    if( rc ) goto attach_error;
  }else{
    /* This is a real ATTACH
    **
    ** Check for the following errors:
    **
    **     * Too many attached databases,
    **     * Transaction currently open
    **     * Specified database name already being used.
    */
    if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){
      zErrDyn = sqlite3MPrintf(db, "too many attached databases - max %d", 
        db->aLimit[SQLITE_LIMIT_ATTACHED]
      );
      goto attach_error;
    }
    for(i=0; i<db->nDb; i++){
      char *z = db->aDb[i].zDbSName;
      assert( z && zName );
      if( sqlite3StrICmp(z, zName)==0 ){
      assert( zName );
      if( sqlite3DbIsNamed(db, i, zName) ){
        zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName);
        goto attach_error;
      }
    }
  
    /* Allocate the new entry in the db->aDb[] array and initialize the schema
    ** hash tables.
151
152
153
154
155
156
157
158
159

160
161
162
163
164
165
166
174
175
176
177
178
179
180

181
182
183
184
185
186
187
188
189







-

+







      sqlite3_result_error(context, zErr, -1);
      sqlite3_free(zErr);
      return;
    }
    assert( pVfs );
    flags |= SQLITE_OPEN_MAIN_DB;
    rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags);
    sqlite3_free( zPath );
    db->nDb++;
    pNew->zDbSName = sqlite3DbStrDup(db, zName);
  }
  db->noSharedCache = 0;
  if( rc==SQLITE_CONSTRAINT ){
    rc = SQLITE_ERROR;
    zErrDyn = sqlite3MPrintf(db, "database is already attached");
  }else if( rc==SQLITE_OK ){
    Pager *pPager;
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
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







-



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










+
-
+
+




-
+








-
+







#ifndef SQLITE_OMIT_PAGER_PRAGMAS
    sqlite3BtreeSetPagerFlags(pNew->pBt,
                      PAGER_SYNCHRONOUS_FULL | (db->flags & PAGER_FLAGS_MASK));
#endif
    sqlite3BtreeLeave(pNew->pBt);
  }
  pNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1;
  if( !REOPEN_AS_MEMDB(db) ) pNew->zDbSName = sqlite3DbStrDup(db, zName);
  if( rc==SQLITE_OK && pNew->zDbSName==0 ){
    rc = SQLITE_NOMEM_BKPT;
  }

  sqlite3_free_filename( zPath );

#ifdef SQLITE_HAS_CODEC
  if( rc==SQLITE_OK ){
    extern int sqlite3CodecAttach(sqlite3*, int, const void*, int);
    extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*);
    int nKey;
    char *zKey;
    int t = sqlite3_value_type(argv[2]);
    switch( t ){
      case SQLITE_INTEGER:
      case SQLITE_FLOAT:
        zErrDyn = sqlite3DbStrDup(db, "Invalid key value");
        rc = SQLITE_ERROR;
        break;
        
      case SQLITE_TEXT:
      case SQLITE_BLOB:
        nKey = sqlite3_value_bytes(argv[2]);
        zKey = (char *)sqlite3_value_blob(argv[2]);
        rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);
        break;

      case SQLITE_NULL:
        /* No key specified.  Use the key from the main database */
        sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey);
        if( nKey || sqlite3BtreeGetOptimalReserve(db->aDb[0].pBt)>0 ){
          rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);
        }
        break;
    }
  }
#endif

  /* If the file was opened successfully, read the schema for the new database.
  ** If this fails, or if opening the file failed, then close the file and 
  ** remove the entry from the db->aDb[] array. i.e. put everything back the
  ** way we found it.
  */
  if( rc==SQLITE_OK ){
    sqlite3BtreeEnterAll(db);
    db->init.iDb = 0;
    db->mDbFlags &= ~(DBFLAG_SchemaKnownOk);
    if( !REOPEN_AS_MEMDB(db) ){
    rc = sqlite3Init(db, &zErrDyn);
      rc = sqlite3Init(db, &zErrDyn);
    }
    sqlite3BtreeLeaveAll(db);
    assert( zErrDyn==0 || rc!=SQLITE_OK );
  }
#ifdef SQLITE_USER_AUTHENTICATION
  if( rc==SQLITE_OK ){
  if( rc==SQLITE_OK && !REOPEN_AS_MEMDB(db) ){
    u8 newAuth = 0;
    rc = sqlite3UserAuthCheckLogin(db, zName, &newAuth);
    if( newAuth<db->auth.authLevel ){
      rc = SQLITE_AUTH_USER;
    }
  }
#endif
  if( rc ){
    if( !REOPEN_AS_MEMDB(db) ){
    if( ALWAYS(!REOPEN_AS_MEMDB(db)) ){
      int iDb = db->nDb - 1;
      assert( iDb>=2 );
      if( db->aDb[iDb].pBt ){
        sqlite3BtreeClose(db->aDb[iDb].pBt);
        db->aDb[iDb].pBt = 0;
        db->aDb[iDb].pSchema = 0;
      }
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
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







+








-
+










+
-
+
+



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







  int NotUsed,
  sqlite3_value **argv
){
  const char *zName = (const char *)sqlite3_value_text(argv[0]);
  sqlite3 *db = sqlite3_context_db_handle(context);
  int i;
  Db *pDb = 0;
  HashElem *pEntry;
  char zErr[128];

  UNUSED_PARAMETER(NotUsed);

  if( zName==0 ) zName = "";
  for(i=0; i<db->nDb; i++){
    pDb = &db->aDb[i];
    if( pDb->pBt==0 ) continue;
    if( sqlite3StrICmp(pDb->zDbSName, zName)==0 ) break;
    if( sqlite3DbIsNamed(db, i, zName) ) break;
  }

  if( i>=db->nDb ){
    sqlite3_snprintf(sizeof(zErr),zErr, "no such database: %s", zName);
    goto detach_error;
  }
  if( i<2 ){
    sqlite3_snprintf(sizeof(zErr),zErr, "cannot detach database %s", zName);
    goto detach_error;
  }
  if( sqlite3BtreeTxnState(pDb->pBt)!=SQLITE_TXN_NONE
  if( sqlite3BtreeIsInReadTrans(pDb->pBt) || sqlite3BtreeIsInBackup(pDb->pBt) ){
   || sqlite3BtreeIsInBackup(pDb->pBt)
  ){
    sqlite3_snprintf(sizeof(zErr),zErr, "database %s is locked", zName);
    goto detach_error;
  }

  /* If any TEMP triggers reference the schema being detached, move those
  ** triggers to reference the TEMP schema itself. */
  assert( db->aDb[1].pSchema );
  pEntry = sqliteHashFirst(&db->aDb[1].pSchema->trigHash);
  while( pEntry ){
    Trigger *pTrig = (Trigger*)sqliteHashData(pEntry);
    if( pTrig->pTabSchema==pDb->pSchema ){
      pTrig->pTabSchema = pTrig->pSchema;
    }
    pEntry = sqliteHashNext(pEntry);
  }

  sqlite3BtreeClose(pDb->pBt);
  pDb->pBt = 0;
  pDb->pSchema = 0;
  sqlite3CollapseDatabaseArray(db);
  return;

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







+
+





-
-
-
+
+
+





-
+


+




















-
+
-
-
-
+
-







){
  int rc;
  NameContext sName;
  Vdbe *v;
  sqlite3* db = pParse->db;
  int regArgs;

  if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) goto attach_end;

  if( pParse->nErr ) goto attach_end;
  memset(&sName, 0, sizeof(NameContext));
  sName.pParse = pParse;

  if( 
      SQLITE_OK!=(rc = resolveAttachExpr(&sName, pFilename)) ||
      SQLITE_OK!=(rc = resolveAttachExpr(&sName, pDbname)) ||
      SQLITE_OK!=(rc = resolveAttachExpr(&sName, pKey))
      SQLITE_OK!=resolveAttachExpr(&sName, pFilename) ||
      SQLITE_OK!=resolveAttachExpr(&sName, pDbname) ||
      SQLITE_OK!=resolveAttachExpr(&sName, pKey)
  ){
    goto attach_end;
  }

#ifndef SQLITE_OMIT_AUTHORIZATION
  if( pAuthArg ){
  if( ALWAYS(pAuthArg) ){
    char *zAuthArg;
    if( pAuthArg->op==TK_STRING ){
      assert( !ExprHasProperty(pAuthArg, EP_IntValue) );
      zAuthArg = pAuthArg->u.zToken;
    }else{
      zAuthArg = 0;
    }
    rc = sqlite3AuthCheck(pParse, type, zAuthArg, 0, 0);
    if(rc!=SQLITE_OK ){
      goto attach_end;
    }
  }
#endif /* SQLITE_OMIT_AUTHORIZATION */


  v = sqlite3GetVdbe(pParse);
  regArgs = sqlite3GetTempRange(pParse, 4);
  sqlite3ExprCode(pParse, pFilename, regArgs);
  sqlite3ExprCode(pParse, pDbname, regArgs+1);
  sqlite3ExprCode(pParse, pKey, regArgs+2);

  assert( v || db->mallocFailed );
  if( v ){
    sqlite3VdbeAddOp4(v, OP_Function0, 0, regArgs+3-pFunc->nArg, regArgs+3,
    sqlite3VdbeAddFunctionCall(pParse, 0, regArgs+3-pFunc->nArg, regArgs+3,
                      (char *)pFunc, P4_FUNCDEF);
    assert( pFunc->nArg==-1 || (pFunc->nArg&0xff)==pFunc->nArg );
    sqlite3VdbeChangeP5(v, (u8)(pFunc->nArg));
                               pFunc->nArg, pFunc, 0);
 
    /* Code an OP_Expire. For an ATTACH statement, set P1 to true (expire this
    ** statement only). For DETACH, set it to false (expire all existing
    ** statements).
    */
    sqlite3VdbeAddOp1(v, OP_Expire, (type==SQLITE_ATTACH));
  }
  
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
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







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












-
+
-
-






-
+
+
+
+
+
+
+
+




















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





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





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









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



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





+



    0, 0,             /* xValue, xInverse */
    "sqlite_attach",  /* zName */
    {0}
  };
  codeAttach(pParse, SQLITE_ATTACH, &attach_func, p, p, pDbname, pKey);
}
#endif /* SQLITE_OMIT_ATTACH */

/*
** Expression callback used by sqlite3FixAAAA() routines.
*/
static int fixExprCb(Walker *p, Expr *pExpr){
  DbFixer *pFix = p->u.pFix;
  if( !pFix->bTemp ) ExprSetProperty(pExpr, EP_FromDDL);
  if( pExpr->op==TK_VARIABLE ){
    if( pFix->pParse->db->init.busy ){
      pExpr->op = TK_NULL;
    }else{
      sqlite3ErrorMsg(pFix->pParse, "%s cannot use variables", pFix->zType);
      return WRC_Abort;
    }
  }
  return WRC_Continue;
}

/*
** Select callback used by sqlite3FixAAAA() routines.
*/
static int fixSelectCb(Walker *p, Select *pSelect){
  DbFixer *pFix = p->u.pFix;
  int i;
  SrcItem *pItem;
  sqlite3 *db = pFix->pParse->db;
  int iDb = sqlite3FindDbName(db, pFix->zDb);
  SrcList *pList = pSelect->pSrc;

  if( NEVER(pList==0) ) return WRC_Continue;
  for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
    if( pFix->bTemp==0 ){
      if( pItem->zDatabase ){
        if( iDb!=sqlite3FindDbName(db, pItem->zDatabase) ){
          sqlite3ErrorMsg(pFix->pParse,
              "%s %T cannot reference objects in database %s",
              pFix->zType, pFix->pName, pItem->zDatabase);
          return WRC_Abort;
        }
        sqlite3DbFree(db, pItem->zDatabase);
        pItem->zDatabase = 0;
        pItem->fg.notCte = 1;
      }
      pItem->pSchema = pFix->pSchema;
      pItem->fg.fromDDL = 1;
    }
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
    if( pList->a[i].fg.isUsing==0
     && sqlite3WalkExpr(&pFix->w, pList->a[i].u3.pOn)
    ){
      return WRC_Abort;
    }
#endif
  }
  if( pSelect->pWith ){
    for(i=0; i<pSelect->pWith->nCte; i++){
      if( sqlite3WalkSelect(p, pSelect->pWith->a[i].pSelect) ){
        return WRC_Abort;
      }
    }
  }
  return WRC_Continue;
}

/*
** Initialize a DbFixer structure.  This routine must be called prior
** to passing the structure to one of the sqliteFixAAAA() routines below.
*/
void sqlite3FixInit(
  DbFixer *pFix,      /* The fixer to be initialized */
  Parse *pParse,      /* Error messages will be written here */
  int iDb,            /* This is the database that must be used */
  const char *zType,  /* "view", "trigger", or "index" */
  const Token *pName  /* Name of the view, trigger, or index */
){
  sqlite3 *db;
  sqlite3 *db = pParse->db;

  db = pParse->db;
  assert( db->nDb>iDb );
  pFix->pParse = pParse;
  pFix->zDb = db->aDb[iDb].zDbSName;
  pFix->pSchema = db->aDb[iDb].pSchema;
  pFix->zType = zType;
  pFix->pName = pName;
  pFix->bVarOnly = (iDb==1);
  pFix->bTemp = (iDb==1);
  pFix->w.pParse = pParse;
  pFix->w.xExprCallback = fixExprCb;
  pFix->w.xSelectCallback = fixSelectCb;
  pFix->w.xSelectCallback2 = sqlite3WalkWinDefnDummyCallback;
  pFix->w.walkerDepth = 0;
  pFix->w.eCode = 0;
  pFix->w.u.pFix = pFix;
}

/*
** The following set of routines walk through the parse tree and assign
** a specific database to all table references where the database name
** was left unspecified in the original SQL statement.  The pFix structure
** must have been initialized by a prior call to sqlite3FixInit().
**
** These routines are used to make sure that an index, trigger, or
** view in one database does not refer to objects in a different database.
** (Exception: indices, triggers, and views in the TEMP database are
** allowed to refer to anything.)  If a reference is explicitly made
** to an object in a different database, an error message is added to
** pParse->zErrMsg and these routines return non-zero.  If everything
** checks out, these routines return 0.
*/
int sqlite3FixSrcList(
  DbFixer *pFix,       /* Context of the fixation */
  SrcList *pList       /* The Source list to check and modify */
){
  int i;
  const char *zDb;
  struct SrcList_item *pItem;

  int res = 0;
  if( pList ){
    Select s; 
    memset(&s, 0, sizeof(s));
  if( NEVER(pList==0) ) return 0;
  zDb = pFix->zDb;
    s.pSrc = pList;
  for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
    if( pFix->bVarOnly==0 ){
      if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){
        sqlite3ErrorMsg(pFix->pParse,
    res = sqlite3WalkSelect(&pFix->w, &s);
            "%s %T cannot reference objects in database %s",
            pFix->zType, pFix->pName, pItem->zDatabase);
        return 1;
      }
  }
      sqlite3DbFree(pFix->pParse->db, pItem->zDatabase);
      pItem->zDatabase = 0;
      pItem->pSchema = pFix->pSchema;
    }
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
    if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1;
    if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1;
#endif
    if( pItem->fg.isTabFunc && sqlite3FixExprList(pFix, pItem->u1.pFuncArg) ){
      return 1;
    }
  return res;
}
  }
  return 0;
}
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
int sqlite3FixSelect(
  DbFixer *pFix,       /* Context of the fixation */
  Select *pSelect      /* The SELECT statement to be fixed to one database */
){
  while( pSelect ){
    if( sqlite3FixExprList(pFix, pSelect->pEList) ){
      return 1;
  return sqlite3WalkSelect(&pFix->w, pSelect);
    }
    if( sqlite3FixSrcList(pFix, pSelect->pSrc) ){
      return 1;
    }
    if( sqlite3FixExpr(pFix, pSelect->pWhere) ){
      return 1;
    }
    if( sqlite3FixExprList(pFix, pSelect->pGroupBy) ){
      return 1;
    }
    if( sqlite3FixExpr(pFix, pSelect->pHaving) ){
      return 1;
    }
    if( sqlite3FixExprList(pFix, pSelect->pOrderBy) ){
      return 1;
    }
    if( sqlite3FixExpr(pFix, pSelect->pLimit) ){
      return 1;
    }
    if( pSelect->pWith ){
      int i;
      for(i=0; i<pSelect->pWith->nCte; i++){
        if( sqlite3FixSelect(pFix, pSelect->pWith->a[i].pSelect) ){
          return 1;
        }
      }
    }
    pSelect = pSelect->pPrior;
  }
  return 0;
}
int sqlite3FixExpr(
  DbFixer *pFix,     /* Context of the fixation */
  Expr *pExpr        /* The expression to be fixed to one database */
){
  while( pExpr ){
    if( pExpr->op==TK_VARIABLE ){
      if( pFix->pParse->db->init.busy ){
        pExpr->op = TK_NULL;
      }else{
        sqlite3ErrorMsg(pFix->pParse, "%s cannot use variables", pFix->zType);
        return 1;
  return sqlite3WalkExpr(&pFix->w, pExpr);
      }
    }
    if( ExprHasProperty(pExpr, EP_TokenOnly|EP_Leaf) ) break;
    if( ExprHasProperty(pExpr, EP_xIsSelect) ){
      if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1;
    }else{
      if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1;
    }
    if( sqlite3FixExpr(pFix, pExpr->pRight) ){
      return 1;
    }
    pExpr = pExpr->pLeft;
  }
  return 0;
}
int sqlite3FixExprList(
  DbFixer *pFix,     /* Context of the fixation */
  ExprList *pList    /* The expression to be fixed to one database */
){
  int i;
  struct ExprList_item *pItem;
  if( pList==0 ) return 0;
  for(i=0, pItem=pList->a; i<pList->nExpr; i++, pItem++){
    if( sqlite3FixExpr(pFix, pItem->pExpr) ){
      return 1;
    }
  }
  return 0;
}
#endif

#ifndef SQLITE_OMIT_TRIGGER
int sqlite3FixTriggerStep(
  DbFixer *pFix,     /* Context of the fixation */
  TriggerStep *pStep /* The trigger step be fixed to one database */
){
  while( pStep ){
    if( sqlite3FixSelect(pFix, pStep->pSelect) ){
    if( sqlite3WalkSelect(&pFix->w, pStep->pSelect)
      return 1;
    }
    if( sqlite3FixExpr(pFix, pStep->pWhere) ){
     || sqlite3WalkExpr(&pFix->w, pStep->pWhere) 
      return 1;
    }
    if( sqlite3FixExprList(pFix, pStep->pExprList) ){
     || sqlite3WalkExprList(&pFix->w, pStep->pExprList)
     || sqlite3FixSrcList(pFix, pStep->pFrom)
    ){
      return 1;
    }
#ifndef SQLITE_OMIT_UPSERT
    if( pStep->pUpsert ){
      Upsert *pUp = pStep->pUpsert;
      if( sqlite3FixExprList(pFix, pUp->pUpsertTarget)
       || sqlite3FixExpr(pFix, pUp->pUpsertTargetWhere)
       || sqlite3FixExprList(pFix, pUp->pUpsertSet)
       || sqlite3FixExpr(pFix, 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/auth.c.

74
75
76
77
78
79
80
81

82
83
84
85
86
87
88
74
75
76
77
78
79
80

81
82
83
84
85
86
87
88







-
+







){
#ifdef SQLITE_ENABLE_API_ARMOR
  if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
#endif
  sqlite3_mutex_enter(db->mutex);
  db->xAuth = (sqlite3_xauth)xAuth;
  db->pAuthArg = pArg;
  sqlite3ExpirePreparedStatements(db, 0);
  if( db->xAuth ) sqlite3ExpirePreparedStatements(db, 1);
  sqlite3_mutex_leave(db->mutex);
  return SQLITE_OK;
}

/*
** Write an error message into pParse->zErrMsg that explains that the
** user-supplied authorization function returned an illegal value.
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
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







-







-
-
+
+











-
+







-
+



-
+


-
+



-
+







*/
void sqlite3AuthRead(
  Parse *pParse,        /* The parser context */
  Expr *pExpr,          /* The expression to check authorization on */
  Schema *pSchema,      /* The schema of the expression */
  SrcList *pTabList     /* All table that pExpr might refer to */
){
  sqlite3 *db = pParse->db;
  Table *pTab = 0;      /* The table being read */
  const char *zCol;     /* Name of the column of the table */
  int iSrc;             /* Index in pTabList->a[] of table being read */
  int iDb;              /* The index of the database the expression refers to */
  int iCol;             /* Index of column in table */

  assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER );
  assert( !IN_RENAME_OBJECT || db->xAuth==0 );
  if( db->xAuth==0 ) return;
  assert( !IN_RENAME_OBJECT );
  assert( pParse->db->xAuth!=0 );
  iDb = sqlite3SchemaToIndex(pParse->db, pSchema);
  if( iDb<0 ){
    /* An attempt to read a column out of a subquery or other
    ** temporary table. */
    return;
  }

  if( pExpr->op==TK_TRIGGER ){
    pTab = pParse->pTriggerTab;
  }else{
    assert( pTabList );
    for(iSrc=0; ALWAYS(iSrc<pTabList->nSrc); iSrc++){
    for(iSrc=0; iSrc<pTabList->nSrc; iSrc++){
      if( pExpr->iTable==pTabList->a[iSrc].iCursor ){
        pTab = pTabList->a[iSrc].pTab;
        break;
      }
    }
  }
  iCol = pExpr->iColumn;
  if( NEVER(pTab==0) ) return;
  if( pTab==0 ) return;

  if( iCol>=0 ){
    assert( iCol<pTab->nCol );
    zCol = pTab->aCol[iCol].zName;
    zCol = pTab->aCol[iCol].zCnName;
  }else if( pTab->iPKey>=0 ){
    assert( pTab->iPKey<pTab->nCol );
    zCol = pTab->aCol[pTab->iPKey].zName;
    zCol = pTab->aCol[pTab->iPKey].zCnName;
  }else{
    zCol = "ROWID";
  }
  assert( iDb>=0 && iDb<db->nDb );
  assert( iDb>=0 && iDb<pParse->db->nDb );
  if( SQLITE_IGNORE==sqlite3AuthReadCol(pParse, pTab->zName, zCol, iDb) ){
    pExpr->op = TK_NULL;
  }
}

/*
** Do an authorization check using the code and arguments given.  Return
205
206
207
208
209
210
211
212
213
214
215
216

217
218
219
220
221
222
223
204
205
206
207
208
209
210





211
212
213
214
215
216
217
218







-
-
-
-
-
+







  sqlite3 *db = pParse->db;
  int rc;

  /* Don't do any authorization checks if the database is initialising
  ** or if the parser is being invoked from within sqlite3_declare_vtab.
  */
  assert( !IN_RENAME_OBJECT || db->xAuth==0 );
  if( db->init.busy || IN_SPECIAL_PARSE ){
    return SQLITE_OK;
  }

  if( db->xAuth==0 ){
  if( db->xAuth==0 || db->init.busy || IN_SPECIAL_PARSE ){
    return SQLITE_OK;
  }

  /* EVIDENCE-OF: R-43249-19882 The third through sixth parameters to the
  ** callback are either NULL pointers or zero-terminated strings that
  ** contain additional details about the action to be authorized.
  **

Changes to src/backup.c.

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







-
+
-





-
+



















-
+










-
+







*/
static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
  int i = sqlite3FindDbName(pDb, zDb);

  if( i==1 ){
    Parse sParse;
    int rc = 0;
    memset(&sParse, 0, sizeof(sParse));
    sqlite3ParseObjectInit(&sParse,pDb);
    sParse.db = pDb;
    if( sqlite3OpenTempDatabase(&sParse) ){
      sqlite3ErrorWithMsg(pErrorDb, sParse.rc, "%s", sParse.zErrMsg);
      rc = SQLITE_ERROR;
    }
    sqlite3DbFree(pErrorDb, sParse.zErrMsg);
    sqlite3ParserReset(&sParse);
    sqlite3ParseObjectReset(&sParse);
    if( rc ){
      return 0;
    }
  }

  if( i<0 ){
    sqlite3ErrorWithMsg(pErrorDb, SQLITE_ERROR, "unknown database %s", zDb);
    return 0;
  }

  return pDb->aDb[i].pBt;
}

/*
** Attempt to set the page size of the destination to match the page size
** of the source.
*/
static int setDestPgsz(sqlite3_backup *p){
  int rc;
  rc = sqlite3BtreeSetPageSize(p->pDest,sqlite3BtreeGetPageSize(p->pSrc),-1,0);
  rc = sqlite3BtreeSetPageSize(p->pDest,sqlite3BtreeGetPageSize(p->pSrc),0,0);
  return rc;
}

/*
** Check that there is no open read-transaction on the b-tree passed as the
** second argument. If there is not, return SQLITE_OK. Otherwise, if there
** is an open read-transaction, return SQLITE_ERROR and leave an error 
** message in database handle db.
*/
static int checkReadTransaction(sqlite3 *db, Btree *p){
  if( sqlite3BtreeIsInReadTrans(p) ){
  if( sqlite3BtreeTxnState(p)!=SQLITE_TXN_NONE ){
    sqlite3ErrorWithMsg(db, SQLITE_ERROR, "destination database is in use");
    return SQLITE_ERROR;
  }
  return SQLITE_OK;
}

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







-
-
-
-
-
-
-
















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







  int bUpdate                     /* True for an update, false otherwise */
){
  Pager * const pDestPager = sqlite3BtreePager(p->pDest);
  const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc);
  int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest);
  const int nCopy = MIN(nSrcPgsz, nDestPgsz);
  const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz;
#ifdef SQLITE_HAS_CODEC
  /* Use BtreeGetReserveNoMutex() for the source b-tree, as although it is
  ** guaranteed that the shared-mutex is held by this thread, handle
  ** p->pSrc may not actually be the owner.  */
  int nSrcReserve = sqlite3BtreeGetReserveNoMutex(p->pSrc);
  int nDestReserve = sqlite3BtreeGetOptimalReserve(p->pDest);
#endif
  int rc = SQLITE_OK;
  i64 iOff;

  assert( sqlite3BtreeGetReserveNoMutex(p->pSrc)>=0 );
  assert( p->bDestLocked );
  assert( !isFatalError(p->rc) );
  assert( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) );
  assert( zSrcData );

  /* Catch the case where the destination is an in-memory database and the
  ** page sizes of the source and destination differ. 
  */
  if( nSrcPgsz!=nDestPgsz && sqlite3PagerIsMemdb(pDestPager) ){
    rc = SQLITE_READONLY;
  }

#ifdef SQLITE_HAS_CODEC
  /* Backup is not possible if the page size of the destination is changing
  ** and a codec is in use.
  */
  if( nSrcPgsz!=nDestPgsz && sqlite3PagerGetCodec(pDestPager)!=0 ){
    rc = SQLITE_READONLY;
  }

  /* Backup is not possible if the number of bytes of reserve space differ
  ** between source and destination.  If there is a difference, try to
  ** fix the destination to agree with the source.  If that is not possible,
  ** then the backup cannot proceed.
  */
  if( nSrcReserve!=nDestReserve ){
    u32 newPgsz = nSrcPgsz;
    rc = sqlite3PagerSetPagesize(pDestPager, &newPgsz, nSrcReserve);
    if( rc==SQLITE_OK && newPgsz!=nSrcPgsz ) rc = SQLITE_READONLY;
  }
#endif

  /* This loop runs once for each destination page spanned by the source 
  ** page. For each iteration, variable iOff is set to the byte offset
  ** of the destination page.
  */
  for(iOff=iEnd-(i64)nSrcPgsz; rc==SQLITE_OK && iOff<iEnd; iOff+=nDestPgsz){
    DbPage *pDestPg = 0;
    Pgno iDest = (Pgno)(iOff/nDestPgsz)+1;
377
378
379
380
381
382
383
384

385
386
387
388
389
390
391
349
350
351
352
353
354
355

356
357
358
359
360
361
362
363







-
+







      rc = SQLITE_OK;
    }

    /* If there is no open read-transaction on the source database, open
    ** one now. If a transaction is opened here, then it will be closed
    ** before this function exits.
    */
    if( rc==SQLITE_OK && 0==sqlite3BtreeIsInReadTrans(p->pSrc) ){
    if( rc==SQLITE_OK && SQLITE_TXN_NONE==sqlite3BtreeTxnState(p->pSrc) ){
      rc = sqlite3BtreeBeginTrans(p->pSrc, 0, 0);
      bCloseTrans = 1;
    }

    /* If the destination database has not yet been locked (i.e. if this
    ** is the first call to backup_step() for the current backup operation),
    ** try to set its page size to the same as the source database. This
615
616
617
618
619
620
621

622
623

624
625
626
627
628
629
630
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604







+


+








  /* Detach this backup from the source pager. */
  if( p->pDestDb ){
    p->pSrc->nBackup--;
  }
  if( p->isAttached ){
    pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc));
    assert( pp!=0 );
    while( *pp!=p ){
      pp = &(*pp)->pNext;
      assert( pp!=0 );
    }
    *pp = p->pNext;
  }

  /* If a transaction is still open on the Btree, roll it back. */
  sqlite3BtreeRollback(p->pDest, SQLITE_OK, 0);

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







-
+



















-
-
-
-
















-
+






int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
  int rc;
  sqlite3_file *pFd;              /* File descriptor for database pTo */
  sqlite3_backup b;
  sqlite3BtreeEnter(pTo);
  sqlite3BtreeEnter(pFrom);

  assert( sqlite3BtreeIsInTrans(pTo) );
  assert( sqlite3BtreeTxnState(pTo)==SQLITE_TXN_WRITE );
  pFd = sqlite3PagerFile(sqlite3BtreePager(pTo));
  if( pFd->pMethods ){
    i64 nByte = sqlite3BtreeGetPageSize(pFrom)*(i64)sqlite3BtreeLastPage(pFrom);
    rc = sqlite3OsFileControl(pFd, SQLITE_FCNTL_OVERWRITE, &nByte);
    if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
    if( rc ) goto copy_finished;
  }

  /* Set up an sqlite3_backup object. sqlite3_backup.pDestDb must be set
  ** to 0. This is used by the implementations of sqlite3_backup_step()
  ** and sqlite3_backup_finish() to detect that they are being called
  ** from this function, not directly by the user.
  */
  memset(&b, 0, sizeof(b));
  b.pSrcDb = pFrom->db;
  b.pSrc = pFrom;
  b.pDest = pTo;
  b.iNext = 1;

#ifdef SQLITE_HAS_CODEC
  sqlite3PagerAlignReserve(sqlite3BtreePager(pTo), sqlite3BtreePager(pFrom));
#endif

  /* 0x7FFFFFFF is the hard limit for the number of pages in a database
  ** file. By passing this as the number of pages to copy to
  ** sqlite3_backup_step(), we can guarantee that the copy finishes 
  ** within a single call (unless an error occurs). The assert() statement
  ** checks this assumption - (p->rc) should be set to either SQLITE_DONE 
  ** or an error code.  */
  sqlite3_backup_step(&b, 0x7FFFFFFF);
  assert( b.rc!=SQLITE_OK );

  rc = sqlite3_backup_finish(&b);
  if( rc==SQLITE_OK ){
    pTo->pBt->btsFlags &= ~BTS_PAGESIZE_FIXED;
  }else{
    sqlite3PagerClearCache(sqlite3BtreePager(b.pDest));
  }

  assert( sqlite3BtreeIsInTrans(pTo)==0 );
  assert( sqlite3BtreeTxnState(pTo)!=SQLITE_TXN_WRITE );
copy_finished:
  sqlite3BtreeLeave(pFrom);
  sqlite3BtreeLeave(pTo);
  return rc;
}
#endif /* SQLITE_OMIT_VACUUM */

Changes to src/bitvec.c.

355
356
357
358
359
360
361
362

363
364
365
366
367
368
369
355
356
357
358
359
360
361

362
363
364
365
366
367
368
369







-
+







  if( pBitvec==0 || pV==0 || pTmpSpace==0  ) goto bitvec_end;

  /* NULL pBitvec tests */
  sqlite3BitvecSet(0, 1);
  sqlite3BitvecClear(0, 1, pTmpSpace);

  /* Run the program */
  pc = 0;
  pc = i = 0;
  while( (op = aOp[pc])!=0 ){
    switch( op ){
      case 1:
      case 2:
      case 5: {
        nx = 4;
        i = aOp[pc+2] - 1;

Changes to src/btmutex.c.

248
249
250
251
252
253
254

255
256
257
258
259
260
261
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262







+







**
** If pSchema is not NULL, then iDb is computed from pSchema and
** db using sqlite3SchemaToIndex().
*/
int sqlite3SchemaMutexHeld(sqlite3 *db, int iDb, Schema *pSchema){
  Btree *p;
  assert( db!=0 );
  if( db->pVfs==0 && db->nDb==0 ) return 1;
  if( pSchema ) iDb = sqlite3SchemaToIndex(db, pSchema);
  assert( iDb>=0 && iDb<db->nDb );
  if( !sqlite3_mutex_held(db->mutex) ) return 0;
  if( iDb==1 ) return 1;
  p = db->aDb[iDb].pBt;
  assert( p!=0 );
  return p->sharable==0 || p->locked==1;

Changes to src/btree.c.

65
66
67
68
69
70
71
72

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

72
73
74
75
76
77
78
79







-
+







#ifndef SQLITE_OMIT_SHARED_CACHE
/*
** A list of BtShared objects that are eligible for participation
** in shared cache.  This variable has file scope during normal builds,
** but the test harness needs to access it so we make it global for 
** test builds.
**
** Access to this variable is protected by SQLITE_MUTEX_STATIC_MASTER.
** Access to this variable is protected by SQLITE_MUTEX_STATIC_MAIN.
*/
#ifdef SQLITE_TEST
BtShared *SQLITE_WSD sqlite3SharedCacheList = 0;
#else
static BtShared *SQLITE_WSD sqlite3SharedCacheList = 0;
#endif
#endif /* SQLITE_OMIT_SHARED_CACHE */
107
108
109
110
111
112
113











114
115
116
117
118
119
120
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







+
+
+
+
+
+
+
+
+
+
+







  #define querySharedCacheTableLock(a,b,c) SQLITE_OK
  #define setSharedCacheTableLock(a,b,c) SQLITE_OK
  #define clearAllSharedCacheTableLocks(a)
  #define downgradeAllSharedCacheTableLocks(a)
  #define hasSharedCacheTableLock(a,b,c,d) 1
  #define hasReadConflicts(a, b) 0
#endif

#ifdef SQLITE_DEBUG
/*
** Return and reset the seek counter for a Btree object.
*/
sqlite3_uint64 sqlite3BtreeSeekCount(Btree *pBt){
  u64 n =  pBt->nSeek;
  pBt->nSeek = 0;
  return n;
}
#endif

/*
** Implementation of the SQLITE_CORRUPT_PAGE() macro. Takes a single
** (MemPage*) as an argument. The (MemPage*) must not be NULL.
**
** If SQLITE_DEBUG is not defined, then this macro is equivalent to
** SQLITE_CORRUPT_BKPT. Or, if SQLITE_DEBUG is set, then the log message
196
197
198
199
200
201
202

203
204
205
206


207
208
209
210
211
212

213
214
215
216
217
218
219
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







+


-
-
+
+






+








  /* Figure out the root-page that the lock should be held on. For table
  ** b-trees, this is just the root page of the b-tree being read or
  ** written. For index b-trees, it is the root page of the associated
  ** table.  */
  if( isIndex ){
    HashElem *p;
    int bSeen = 0;
    for(p=sqliteHashFirst(&pSchema->idxHash); p; p=sqliteHashNext(p)){
      Index *pIdx = (Index *)sqliteHashData(p);
      if( pIdx->tnum==(int)iRoot ){
        if( iTab ){
      if( pIdx->tnum==iRoot ){
        if( bSeen ){
          /* Two or more indexes share the same root page.  There must
          ** be imposter tables.  So just return true.  The assert is not
          ** useful in that case. */
          return 1;
        }
        iTab = pIdx->pTable->tnum;
        bSeen = 1;
      }
    }
  }else{
    iTab = iRoot;
  }

  /* Search for the required lock. Either a write-lock on root-page iTab, a 
351
352
353
354
355
356
357
358

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

371
372
373
374
375
376
377
378







-
+








  assert( sqlite3BtreeHoldsMutex(p) );
  assert( eLock==READ_LOCK || eLock==WRITE_LOCK );
  assert( p->db!=0 );

  /* A connection with the read-uncommitted flag set will never try to
  ** obtain a read-lock using this function. The only read-lock obtained
  ** by a connection in read-uncommitted mode is on the sqlite_master 
  ** by a connection in read-uncommitted mode is on the sqlite_schema 
  ** table, and that lock is obtained in BtreeBeginTrans().  */
  assert( 0==(p->db->flags&SQLITE_ReadUncommit) || eLock==WRITE_LOCK );

  /* This function should only be called on a sharable b-tree after it 
  ** has been determined that no other b-tree holds a conflicting lock.  */
  assert( p->sharable );
  assert( SQLITE_OK==querySharedCacheTableLock(p, iTable, eLock) );
763
764
765
766
767
768
769
770

771
772
773
774
775
776
777
776
777
778
779
780
781
782

783
784
785
786
787
788
789
790







-
+







static void invalidateIncrblobCursors(
  Btree *pBtree,          /* The database file to check */
  Pgno pgnoRoot,          /* The table that might be changing */
  i64 iRow,               /* The rowid that might be changing */
  int isClearTable        /* True if all rows are being deleted */
){
  BtCursor *p;
  if( pBtree->hasIncrblobCur==0 ) return;
  assert( pBtree->hasIncrblobCur );
  assert( sqlite3BtreeHoldsMutex(pBtree) );
  pBtree->hasIncrblobCur = 0;
  for(p=pBtree->pBt->pCursor; p; p=p->pNext){
    if( (p->curFlags & BTCF_Incrblob)!=0 ){
      pBtree->hasIncrblobCur = 1;
      if( p->pgnoRoot==pgnoRoot && (isClearTable || p->info.nKey==iRow) ){
        p->eState = CURSOR_INVALID;
840
841
842
843
844
845
846
847

848
849
850
851
852
853
854
853
854
855
856
857
858
859

860
861
862
863
864
865
866
867







-
+







**
** This function is called when a free-list leaf page is removed from the
** free-list for reuse. It returns false if it is safe to retrieve the
** page from the pager layer with the 'no-content' flag set. True otherwise.
*/
static int btreeGetHasContent(BtShared *pBt, Pgno pgno){
  Bitvec *p = pBt->pHasContent;
  return (p && (pgno>sqlite3BitvecSize(p) || sqlite3BitvecTest(p, pgno)));
  return p && (pgno>sqlite3BitvecSize(p) || sqlite3BitvecTestNotNull(p, pgno));
}

/*
** Clear (destroy) the BtShared.pHasContent bitvec. This should be
** invoked at the conclusion of each write-transaction.
*/
static void btreeClearHasContent(BtShared *pBt){
901
902
903
904
905
906
907

908
909
910
911
912
913
914
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928







+







    ** below. */
    void *pKey;
    pCur->nKey = sqlite3BtreePayloadSize(pCur);
    pKey = sqlite3Malloc( pCur->nKey + 9 + 8 );
    if( pKey ){
      rc = sqlite3BtreePayload(pCur, 0, (int)pCur->nKey, pKey);
      if( rc==SQLITE_OK ){
        memset(((u8*)pKey)+pCur->nKey, 0, 9+8);
        pCur->pKey = pKey;
      }else{
        sqlite3_free(pKey);
      }
    }else{
      rc = SQLITE_NOMEM_BKPT;
    }
927
928
929
930
931
932
933



934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957







+
+
+







static int saveCursorPosition(BtCursor *pCur){
  int rc;

  assert( CURSOR_VALID==pCur->eState || CURSOR_SKIPNEXT==pCur->eState );
  assert( 0==pCur->pKey );
  assert( cursorHoldsMutex(pCur) );

  if( pCur->curFlags & BTCF_Pinned ){
    return SQLITE_CONSTRAINT_PINNED;
  }
  if( pCur->eState==CURSOR_SKIPNEXT ){
    pCur->eState = CURSOR_VALID;
  }else{
    pCur->skipNext = 0;
  }

  rc = saveCursorKey(pCur);
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
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







-
+












+

-
+

-
-
+
+

+
-
+

+


-
-
+
-
-
-













-
+






+
+
+
-
+
+




-
+







  pCur->pKey = 0;
  pCur->eState = CURSOR_INVALID;
}

/*
** In this version of BtreeMoveto, pKey is a packed index record
** such as is generated by the OP_MakeRecord opcode.  Unpack the
** record and then call BtreeMovetoUnpacked() to do the work.
** record and then call sqlite3BtreeIndexMoveto() to do the work.
*/
static int btreeMoveto(
  BtCursor *pCur,     /* Cursor open on the btree to be searched */
  const void *pKey,   /* Packed key if the btree is an index */
  i64 nKey,           /* Integer key for tables.  Size of pKey for indices */
  int bias,           /* Bias search to the high end */
  int *pRes           /* Write search results here */
){
  int rc;                    /* Status code */
  UnpackedRecord *pIdxKey;   /* Unpacked index key */

  if( pKey ){
    KeyInfo *pKeyInfo = pCur->pKeyInfo;
    assert( nKey==(i64)(int)nKey );
    pIdxKey = sqlite3VdbeAllocUnpackedRecord(pCur->pKeyInfo);
    pIdxKey = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
    if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT;
    sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey);
    if( pIdxKey->nField==0 ){
    sqlite3VdbeRecordUnpack(pKeyInfo, (int)nKey, pKey, pIdxKey);
    if( pIdxKey->nField==0 || pIdxKey->nField>pKeyInfo->nAllField ){
      rc = SQLITE_CORRUPT_BKPT;
    }else{
      goto moveto_done;
      rc = sqlite3BtreeIndexMoveto(pCur, pIdxKey, pRes);
    }
    sqlite3DbFree(pCur->pKeyInfo->db, pIdxKey);
  }else{
    pIdxKey = 0;
  }
  rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes);
    rc = sqlite3BtreeTableMoveto(pCur, nKey, bias, pRes);
moveto_done:
  if( pIdxKey ){
    sqlite3DbFree(pCur->pKeyInfo->db, pIdxKey);
  }
  return rc;
}

/*
** Restore the cursor to the position it was in (or as close to as possible)
** when saveCursorPosition() was called. Note that this call deletes the 
** saved position info stored by saveCursorPosition(), so there can be
** at most one effective restoreCursorPosition() call after each 
** saveCursorPosition().
*/
static int btreeRestoreCursorPosition(BtCursor *pCur){
  int rc;
  int skipNext;
  int skipNext = 0;
  assert( cursorOwnsBtShared(pCur) );
  assert( pCur->eState>=CURSOR_REQUIRESEEK );
  if( pCur->eState==CURSOR_FAULT ){
    return pCur->skipNext;
  }
  pCur->eState = CURSOR_INVALID;
  if( sqlite3FaultSim(410) ){
    rc = SQLITE_IOERR;
  }else{
  rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &skipNext);
    rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &skipNext);
  }
  if( rc==SQLITE_OK ){
    sqlite3_free(pCur->pKey);
    pCur->pKey = 0;
    assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID );
    pCur->skipNext |= skipNext;
    if( skipNext ) pCur->skipNext = skipNext;
    if( pCur->skipNext && pCur->eState==CURSOR_VALID ){
      pCur->eState = CURSOR_SKIPNEXT;
    }
  }
  return rc;
}

1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1162
1163
1164
1165
1166
1167
1168

1169
1170
1171
1172
1173
1174
1175







-







  if( rc ){
    *pDifferentRow = 1;
    return rc;
  }
  if( pCur->eState!=CURSOR_VALID ){
    *pDifferentRow = 1;
  }else{
    assert( pCur->skipNext==0 );
    *pDifferentRow = 0;
  }
  return SQLITE_OK;
}

#ifdef SQLITE_ENABLE_CURSOR_HINTS
/*
1212
1213
1214
1215
1216
1217
1218
1219

1220
1221
1222
1223
1224
1225
1226
1231
1232
1233
1234
1235
1236
1237

1238
1239
1240
1241
1242
1243
1244
1245







-
+







  Pgno iPtrmap;     /* The pointer map page number */
  int offset;       /* Offset in pointer map page */
  int rc;           /* Return code from subfunctions */

  if( *pRC ) return;

  assert( sqlite3_mutex_held(pBt->mutex) );
  /* The master-journal page number is never added to a pointer-map page */
  /* The super-journal page number must never be used as a pointer map page */
  assert( 0==PTRMAP_ISPAGE(pBt, PENDING_BYTE_PAGE(pBt)) );

#ifndef SQLITE_OMIT_CONCURRENT
  if( pBt->pMap ){
    *pRC = btreePtrmapStore(pBt, key, eType, parent);
    return;
  }
1302
1303
1304
1305
1306
1307
1308
1309

1310
1311
1312
1313
1314
1315
1316
1321
1322
1323
1324
1325
1326
1327

1328
1329
1330
1331
1332
1333
1334
1335







-
+







  if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT_PGNO(iPtrmap);
  return SQLITE_OK;
}

#else /* if defined SQLITE_OMIT_AUTOVACUUM */
  #define ptrmapPut(w,x,y,z,rc)
  #define ptrmapGet(w,x,y,z) SQLITE_OK
  #define ptrmapPutOvflPtr(x, y, rc)
  #define ptrmapPutOvflPtr(x, y, z, rc)
#endif

/*
** Given a btree page and a cell index (0 means the first cell on
** the page, 1 means the second cell, and so forth) return a pointer
** to the cell content.
**
1357
1358
1359
1360
1361
1362
1363


















1364
1365
1366
1367
1368
1369
1370
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







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







  if( surplus <= maxLocal ){
    pInfo->nLocal = (u16)surplus;
  }else{
    pInfo->nLocal = (u16)minLocal;
  }
  pInfo->nSize = (u16)(&pInfo->pPayload[pInfo->nLocal] - pCell) + 4;
}

/*
** Given a record with nPayload bytes of payload stored within btree
** page pPage, return the number of bytes of payload stored locally.
*/
static int btreePayloadToLocal(MemPage *pPage, i64 nPayload){
  int maxLocal;  /* Maximum amount of payload held locally */
  maxLocal = pPage->maxLocal;
  if( nPayload<=maxLocal ){
    return nPayload;
  }else{
    int minLocal;  /* Minimum amount of payload held locally */
    int surplus;   /* Overflow payload available for local storage */
    minLocal = pPage->minLocal;
    surplus = minLocal + (nPayload - minLocal)%(pPage->pBt->usableSize-4);
    return ( surplus <= maxLocal ) ? surplus : minLocal;
  }
}

/*
** The following routines are implementations of the MemPage.xParseCell()
** method.
**
** Parse a cell content block and fill in the CellInfo structure.
**
1424
1425
1426
1427
1428
1429
1430
1431


1432
1433
1434
1435
1436


1437
1438
1439
1440
1441














1442





1443
1444
1445
1446
1447
1448
1449
1450
1451
1452

1453
1454
1455
1456
1457
1458
1459
1461
1462
1463
1464
1465
1466
1467

1468
1469
1470
1471
1472


1473
1474





1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488

1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502

1503
1504
1505
1506
1507
1508
1509
1510







-
+
+



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









-
+







  }
  pIter++;

  /* The next block of code is equivalent to:
  **
  **     pIter += getVarint(pIter, (u64*)&pInfo->nKey);
  **
  ** The code is inlined to avoid a function call.
  ** The code is inlined and the loop is unrolled for performance.
  ** This routine is a high-runner.
  */
  iKey = *pIter;
  if( iKey>=0x80 ){
    u8 *pEnd = &pIter[7];
    iKey &= 0x7f;
    u8 x;
    iKey = ((iKey&0x7f)<<7) | ((x = *++pIter) & 0x7f);
    while(1){
      iKey = (iKey<<7) | (*++pIter & 0x7f);
      if( (*pIter)<0x80 ) break;
      if( pIter>=pEnd ){
        iKey = (iKey<<8) | *++pIter;
    if( x>=0x80 ){
      iKey = (iKey<<7) | ((x =*++pIter) & 0x7f);
      if( x>=0x80 ){
        iKey = (iKey<<7) | ((x = *++pIter) & 0x7f);
        if( x>=0x80 ){
          iKey = (iKey<<7) | ((x = *++pIter) & 0x7f);
          if( x>=0x80 ){
            iKey = (iKey<<7) | ((x = *++pIter) & 0x7f);
            if( x>=0x80 ){
              iKey = (iKey<<7) | ((x = *++pIter) & 0x7f);
              if( x>=0x80 ){
                iKey = (iKey<<7) | ((x = *++pIter) & 0x7f);
                if( x>=0x80 ){
                  iKey = (iKey<<8) | (*++pIter);
        break;
                }
              }
            }
          }
        }
      }
    }
  }
  pIter++;

  pInfo->nKey = *(i64*)&iKey;
  pInfo->nPayload = nPayload;
  pInfo->pPayload = pIter;
  testcase( nPayload==pPage->maxLocal );
  testcase( nPayload==pPage->maxLocal+1 );
  testcase( nPayload==(u32)pPage->maxLocal+1 );
  if( nPayload<=pPage->maxLocal ){
    /* This is the (easy) common case where the entire payload fits
    ** on the local page.  No overflow is required.
    */
    pInfo->nSize = nPayload + (u16)(pIter - pCell);
    if( pInfo->nSize<4 ) pInfo->nSize = 4;
    pInfo->nLocal = (u16)nPayload;
1482
1483
1484
1485
1486
1487
1488
1489

1490
1491
1492
1493
1494
1495
1496
1533
1534
1535
1536
1537
1538
1539

1540
1541
1542
1543
1544
1545
1546
1547







-
+







    }while( *(pIter)>=0x80 && pIter<pEnd );
  }
  pIter++;
  pInfo->nKey = nPayload;
  pInfo->nPayload = nPayload;
  pInfo->pPayload = pIter;
  testcase( nPayload==pPage->maxLocal );
  testcase( nPayload==pPage->maxLocal+1 );
  testcase( nPayload==(u32)pPage->maxLocal+1 );
  if( nPayload<=pPage->maxLocal ){
    /* This is the (easy) common case where the entire payload fits
    ** on the local page.  No overflow is required.
    */
    pInfo->nSize = nPayload + (u16)(pIter - pCell);
    if( pInfo->nSize<4 ) pInfo->nSize = 4;
    pInfo->nLocal = (u16)nPayload;
1512
1513
1514
1515
1516
1517
1518

1519
1520
1521
1522
1523
1524
1525
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577







+







**
** Compute the total number of bytes that a Cell needs in the cell
** data area of the btree-page.  The return number includes the cell
** data header and the local payload, but not any overflow page or
** the space used by the cell pointer.
**
** cellSizePtrNoPayload()    =>   table internal nodes
** cellSizePtrTableLeaf()    =>   table leaf nodes
** cellSizePtr()             =>   all index nodes & table leaf nodes
*/
static u16 cellSizePtr(MemPage *pPage, u8 *pCell){
  u8 *pIter = pCell + pPage->childPtrSize; /* For looping over bytes of pCell */
  u8 *pEnd;                                /* End mark for a varint */
  u32 nSize;                               /* Size value to return */

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
1589
1590
1591
1592
1593
1594
1595







1596

1597
1598
1599
1600
1601
1602
1603
1604

1605
1606
1607
1608
1609
1610
1611
1612







-
-
-
-
-
-
-

-
+







-
+







    pEnd = &pIter[8];
    nSize &= 0x7f;
    do{
      nSize = (nSize<<7) | (*++pIter & 0x7f);
    }while( *(pIter)>=0x80 && pIter<pEnd );
  }
  pIter++;
  if( pPage->intKey ){
    /* pIter now points at the 64-bit integer key value, a variable length 
    ** integer. The following block moves pIter to point at the first byte
    ** past the end of the key value. */
    pEnd = &pIter[9];
    while( (*pIter++)&0x80 && pIter<pEnd );
  }
  testcase( nSize==pPage->maxLocal );
  testcase( nSize==pPage->maxLocal+1 );
  testcase( nSize==(u32)pPage->maxLocal+1 );
  if( nSize<=pPage->maxLocal ){
    nSize += (u32)(pIter - pCell);
    if( nSize<4 ) nSize = 4;
  }else{
    int minLocal = pPage->minLocal;
    nSize = minLocal + (nSize - minLocal) % (pPage->pBt->usableSize - 4);
    testcase( nSize==pPage->maxLocal );
    testcase( nSize==pPage->maxLocal+1 );
    testcase( nSize==(u32)pPage->maxLocal+1 );
    if( nSize>pPage->maxLocal ){
      nSize = minLocal;
    }
    nSize += 4 + (u16)(pIter - pCell);
  }
  assert( nSize==debuginfo.nSize || CORRUPT_DB );
  return (u16)nSize;
1583
1584
1585
1586
1587
1588
1589




















































1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604




1605
1606

1607
1608
1609
1610
1611
1612
1613


1614
1615
1616
1617
1618
1619
1620
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698



1699
1700
1701
1702
1703

1704
1705
1706
1707
1708
1709
1710

1711
1712
1713
1714
1715
1716
1717
1718
1719







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












-
-
-
+
+
+
+

-
+






-
+
+








  assert( pPage->childPtrSize==4 );
  pEnd = pIter + 9;
  while( (*pIter++)&0x80 && pIter<pEnd );
  assert( debuginfo.nSize==(u16)(pIter - pCell) || CORRUPT_DB );
  return (u16)(pIter - pCell);
}
static u16 cellSizePtrTableLeaf(MemPage *pPage, u8 *pCell){
  u8 *pIter = pCell;   /* For looping over bytes of pCell */
  u8 *pEnd;            /* End mark for a varint */
  u32 nSize;           /* Size value to return */

#ifdef SQLITE_DEBUG
  /* The value returned by this function should always be the same as
  ** the (CellInfo.nSize) value found by doing a full parse of the
  ** cell. If SQLITE_DEBUG is defined, an assert() at the bottom of
  ** this function verifies that this invariant is not violated. */
  CellInfo debuginfo;
  pPage->xParseCell(pPage, pCell, &debuginfo);
#endif

  nSize = *pIter;
  if( nSize>=0x80 ){
    pEnd = &pIter[8];
    nSize &= 0x7f;
    do{
      nSize = (nSize<<7) | (*++pIter & 0x7f);
    }while( *(pIter)>=0x80 && pIter<pEnd );
  }
  pIter++;
  /* pIter now points at the 64-bit integer key value, a variable length 
  ** integer. The following block moves pIter to point at the first byte
  ** past the end of the key value. */
  if( (*pIter++)&0x80
   && (*pIter++)&0x80
   && (*pIter++)&0x80
   && (*pIter++)&0x80
   && (*pIter++)&0x80
   && (*pIter++)&0x80
   && (*pIter++)&0x80
   && (*pIter++)&0x80 ){ pIter++; }
  testcase( nSize==pPage->maxLocal );
  testcase( nSize==(u32)pPage->maxLocal+1 );
  if( nSize<=pPage->maxLocal ){
    nSize += (u32)(pIter - pCell);
    if( nSize<4 ) nSize = 4;
  }else{
    int minLocal = pPage->minLocal;
    nSize = minLocal + (nSize - minLocal) % (pPage->pBt->usableSize - 4);
    testcase( nSize==pPage->maxLocal );
    testcase( nSize==(u32)pPage->maxLocal+1 );
    if( nSize>pPage->maxLocal ){
      nSize = minLocal;
    }
    nSize += 4 + (u16)(pIter - pCell);
  }
  assert( nSize==debuginfo.nSize || CORRUPT_DB );
  return (u16)nSize;
}


#ifdef SQLITE_DEBUG
/* This variation on cellSizePtr() is used inside of assert() statements
** only. */
static u16 cellSize(MemPage *pPage, int iCell){
  return pPage->xCellSize(pPage, findCell(pPage, iCell));
}
#endif

#ifndef SQLITE_OMIT_AUTOVACUUM
/*
** If the cell pCell, part of page pPage contains a pointer
** to an overflow page, insert an entry into the pointer-map
** for the overflow page.
** The cell pCell is currently part of page pSrc but will ultimately be part
** of pPage.  (pSrc and pPage are often the same.)  If pCell contains a
** pointer to an overflow page, insert an entry into the pointer-map for
** the overflow page that will be valid after pCell has been moved to pPage.
*/
static void ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell, int *pRC){
static void ptrmapPutOvflPtr(MemPage *pPage, MemPage *pSrc, u8 *pCell,int *pRC){
  CellInfo info;
  if( *pRC ) return;
  assert( pCell!=0 );
  pPage->xParseCell(pPage, pCell, &info);
  if( info.nLocal<info.nPayload ){
    Pgno ovfl;
    if( SQLITE_WITHIN(pPage->aDataEnd, pCell, pCell+info.nLocal) ){
    if( SQLITE_WITHIN(pSrc->aDataEnd, pCell, pCell+info.nLocal) ){
      testcase( pSrc!=pPage );
      *pRC = SQLITE_CORRUPT_BKPT;
      return;
    }
    ovfl = get4byte(&pCell[info.nSize-4]);
    ptrmapPut(pPage->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno, pRC);
  }
}
1643
1644
1645
1646
1647
1648
1649

1650
1651
1652
1653
1654
1655
1656
1657

1658
1659
1660
1661

1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672

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


1695

1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710





1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732






















1733
1734
1735
1736
1737

1738
1739
1740
1741
1742
1743
1744
1745


1746
1747
1748
1749
1750
1751
1752
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755


1756
1757
1758
1759

1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770

1771




1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813






















1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835





1836


1837

1838
1839
1840

1841
1842
1843
1844
1845
1846
1847
1848
1849







+






-
-
+



-
+










-
+
-
-
-
-


















+
+

+















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

-



-
+
+







  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;
  src = data = pPage->aData;
  data = pPage->aData;
  hdr = pPage->hdrOffset;
  cellOffset = pPage->cellOffset;
  nCell = pPage->nCell;
  assert( nCell==get2byte(&data[hdr+3]) );
  assert( nCell==get2byte(&data[hdr+3]) || CORRUPT_DB );
  iCellFirst = cellOffset + 2*nCell;
  usableSize = pPage->pBt->usableSize;

  /* This block handles pages with two or fewer free blocks and nMaxFrag
  ** or fewer fragmented bytes. In this case it is faster to move the
  ** two (or one) blocks of cells using memmove() and add the required
  ** offsets to each pointer in the cell-pointer array than it is to 
  ** reconstruct the entire page.  */
  if( (int)data[hdr+7]<=nMaxFrag ){
    int iFree = get2byte(&data[hdr+1]);

    if( iFree>usableSize-4 ) return SQLITE_CORRUPT_PAGE(pPage);
    /* If the initial freeblock offset were out of bounds, that would
    ** have been detected by btreeInitPage() when it was computing the
    ** number of free bytes on the page. */
    assert( iFree<=usableSize-4 );
    if( iFree ){
      int iFree2 = get2byte(&data[iFree]);
      if( iFree2>usableSize-4 ) return SQLITE_CORRUPT_PAGE(pPage);
      if( 0==iFree2 || (data[iFree2]==0 && data[iFree2+1]==0) ){
        u8 *pEnd = &data[cellOffset + nCell*2];
        u8 *pAddr;
        int sz2 = 0;
        int sz = get2byte(&data[iFree+2]);
        int top = get2byte(&data[hdr+5]);
        if( top>=iFree ){
          return SQLITE_CORRUPT_PAGE(pPage);
        }
        if( iFree2 ){
          if( iFree+sz>iFree2 ) return SQLITE_CORRUPT_PAGE(pPage);
          sz2 = get2byte(&data[iFree2+2]);
          if( iFree2+sz2 > usableSize ) return SQLITE_CORRUPT_PAGE(pPage);
          memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz));
          sz += sz2;
        }else if( iFree+sz>usableSize ){
          return SQLITE_CORRUPT_PAGE(pPage);
        }

        cbrk = top+sz;
        assert( cbrk+(iFree-top) <= usableSize );
        memmove(&data[cbrk], &data[top], iFree-top);
        for(pAddr=&data[cellOffset]; pAddr<pEnd; pAddr+=2){
          pc = get2byte(pAddr);
          if( pc<iFree ){ put2byte(pAddr, pc+sz); }
          else if( pc<iFree2 ){ put2byte(pAddr, pc+sz2); }
        }
        goto defragment_out;
      }
    }
  }

  cbrk = usableSize;
  iCellLast = usableSize - 4;
  iCellStart = get2byte(&data[hdr+5]);
  if( nCell>0 ){
    temp = sqlite3PagerTempSpace(pPage->pBt->pPager);
    memcpy(&temp[iCellStart], &data[iCellStart], usableSize - iCellStart);
    src = temp;
  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 ){
      return SQLITE_CORRUPT_PAGE(pPage);
    }
    assert( pc>=iCellFirst && pc<=iCellLast );
    size = pPage->xCellSize(pPage, &src[pc]);
    cbrk -= size;
    if( cbrk<iCellFirst || pc+size>usableSize ){
      return SQLITE_CORRUPT_PAGE(pPage);
    }
    assert( cbrk+size<=usableSize && cbrk>=iCellFirst );
    testcase( cbrk+size==usableSize );
    testcase( pc+size==usableSize );
    put2byte(pAddr, cbrk);
    for(i=0; i<nCell; i++){
      u8 *pAddr;     /* The i-th cell pointer */
      pAddr = &data[cellOffset + i*2];
      pc = get2byte(pAddr);
      testcase( pc==iCellFirst );
      testcase( pc==iCellLast );
      /* These conditions have already been verified in btreeInitPage()
      ** if PRAGMA cell_size_check=ON.
      */
      if( pc<iCellStart || pc>iCellLast ){
        return SQLITE_CORRUPT_PAGE(pPage);
      }
      assert( pc>=iCellStart && pc<=iCellLast );
      size = pPage->xCellSize(pPage, &src[pc]);
      cbrk -= size;
      if( cbrk<iCellStart || pc+size>usableSize ){
        return SQLITE_CORRUPT_PAGE(pPage);
      }
      assert( cbrk+size<=usableSize && cbrk>=iCellStart );
      testcase( cbrk+size==usableSize );
      testcase( pc+size==usableSize );
      put2byte(pAddr, cbrk);
    if( temp==0 ){
      int x;
      if( cbrk==pc ) continue;
      temp = sqlite3PagerTempSpace(pPage->pBt->pPager);
      x = get2byte(&data[hdr+5]);
      memcpy(&data[cbrk], &src[pc], size);
      memcpy(&temp[x], &data[x], (cbrk+size) - x);
      src = temp;
    }
    memcpy(&data[cbrk], &src[pc], size);
  }
  data[hdr+7] = 0;

 defragment_out:
defragment_out:
  assert( pPage->nFree>=0 );
  if( data[hdr+7]+cbrk-iCellFirst!=pPage->nFree ){
    return SQLITE_CORRUPT_PAGE(pPage);
  }
  assert( cbrk>=iCellFirst );
  put2byte(&data[hdr+5], cbrk);
  data[hdr+1] = 0;
  data[hdr+2] = 0;
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
1863
1864
1865
1866
1867
1868
1869







1870
1871
1872
1873
1874
1875
1876
1877
1878
1879

1880
1881
1882
1883
1884

1885
1886
1887
1888




1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904

1905
1906
1907
1908
1909
1910
1911


1912
1913





1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931







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


-
+



+
-
+



-
-
-
-
+








+
+
+
+
+


-
+





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







** detected then *pRc is set to SQLITE_CORRUPT and NULL is returned.
**
** Slots on the free list that are between 1 and 3 bytes larger than nByte
** will be ignored if adding the extra space to the fragmentation count
** causes the fragmentation count to exceed 60.
*/
static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
  const int hdr = pPg->hdrOffset;
  u8 * const aData = pPg->aData;
  int iAddr = hdr + 1;
  int pc = get2byte(&aData[iAddr]);
  int x;
  int usableSize = pPg->pBt->usableSize;
  int size;            /* Size of the free slot */
  const int hdr = pPg->hdrOffset;            /* Offset to page header */
  u8 * const aData = pPg->aData;             /* Page data */
  int iAddr = hdr + 1;                       /* Address of ptr to pc */
  u8 *pTmp = &aData[iAddr];                  /* Temporary ptr into aData[] */
  int pc = get2byte(pTmp);                   /* Address of a free slot */
  int x;                                     /* Excess size of the slot */
  int maxPC = pPg->pBt->usableSize - nByte;  /* Max address for a usable slot */
  int size;                                  /* Size of the free slot */

  assert( pc>0 );
  while( pc<=usableSize-4 ){
  while( pc<=maxPC ){
    /* EVIDENCE-OF: R-22710-53328 The third and fourth bytes of each
    ** freeblock form a big-endian integer which is the size of the freeblock
    ** in bytes, including the 4-byte header. */
    pTmp = &aData[pc+2];
    size = get2byte(&aData[pc+2]);
    size = get2byte(pTmp);
    if( (x = size - nByte)>=0 ){
      testcase( x==4 );
      testcase( x==3 );
      if( size+pc > usableSize ){
        *pRc = SQLITE_CORRUPT_PAGE(pPg);
        return 0;
      }else if( x<4 ){
      if( x<4 ){
        /* EVIDENCE-OF: R-11498-58022 In a well-formed b-tree page, the total
        ** number of bytes in fragments may not exceed 60. */
        if( aData[hdr+7]>57 ) return 0;

        /* Remove the slot from the free-list. Update the number of
        ** fragmented bytes within the page. */
        memcpy(&aData[iAddr], &aData[pc], 2);
        aData[hdr+7] += (u8)x;
        return &aData[pc];
      }else if( x+pc > maxPC ){
        /* This slot extends off the end of the usable part of the page */
        *pRc = SQLITE_CORRUPT_PAGE(pPg);
        return 0;
      }else{
        /* The slot remains on the free-list. Reduce its size to account
         ** for the portion used by the new allocation. */
        ** for the portion used by the new allocation. */
        put2byte(&aData[pc+2], x);
      }
      return &aData[pc + x];
    }
    iAddr = pc;
    pTmp = &aData[pc];
    pc = get2byte(&aData[pc]);
    if( pc<iAddr+size ) break;
    pc = get2byte(pTmp);
    if( pc<=iAddr ){
  }
  if( pc ){
    *pRc = SQLITE_CORRUPT_PAGE(pPg);
  }

      if( pc ){
        /* The next slot in the chain comes before the current slot */
        *pRc = SQLITE_CORRUPT_PAGE(pPg);
      }
      return 0;
    }
  }
  if( pc>maxPC+nByte-4 ){
    /* The free slot chain extends off the end of the page */
    *pRc = SQLITE_CORRUPT_PAGE(pPg);
  }
  return 0;
}

/*
** Allocate nByte bytes of space from within the B-Tree page passed
** as the first argument. Write into *pIdx the index into pPage->aData[]
** of the first byte of allocated space. Return either SQLITE_OK or
1831
1832
1833
1834
1835
1836
1837

1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855

1856
1857


1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868



1869
1870
1871
1872
1873
1874
1875

1876
1877
1878







1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889

1890
1891
1892
1893
1894
1895
1896
1897
1898

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

1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931

1932
1933
1934
1935
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
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
1984
1985
1986



1987
1988
1989
1990
1991
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
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032

2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066


2067
2068
2069
2070
2071
2072

2073
2074
2075

2076
2077
2078
2079
2080
2081
2082
2083







+


















+
-
-
+
+








-
-
-
+
+
+







+
-
-
-
+
+
+
+
+
+
+











+








-
+


















-
+














+


















-
-
+
+




-
+


-
+







** also end up needing a new cell pointer.
*/
static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
  const int hdr = pPage->hdrOffset;    /* Local cache of pPage->hdrOffset */
  u8 * const data = pPage->aData;      /* Local cache of pPage->aData */
  int top;                             /* First byte of cell content area */
  int rc = SQLITE_OK;                  /* Integer return code */
  u8 *pTmp;                            /* Temp ptr into data[] */
  int gap;        /* First byte of gap between cell pointers and cell content */
  
  assert( sqlite3PagerIswriteable(pPage->pDbPage) );
  assert( pPage->pBt );
  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  assert( nByte>=0 );  /* Minimum cell size is 4 */
  assert( pPage->nFree>=nByte );
  assert( pPage->nOverflow==0 );
  assert( nByte < (int)(pPage->pBt->usableSize-8) );

  assert( pPage->cellOffset == hdr + 12 - 4*pPage->leaf );
  gap = pPage->cellOffset + 2*pPage->nCell;
  assert( gap<=65536 );
  /* EVIDENCE-OF: R-29356-02391 If the database uses a 65536-byte page size
  ** and the reserved space is zero (the usual value for reserved space)
  ** then the cell content offset of an empty page wants to be 65536.
  ** However, that integer is too large to be stored in a 2-byte unsigned
  ** integer, so a value of 0 is used in its place. */
  pTmp = &data[hdr+5];
  top = get2byte(&data[hdr+5]);
  assert( top<=(int)pPage->pBt->usableSize ); /* Prevent by getAndInitPage() */
  top = get2byte(pTmp);
  assert( top<=(int)pPage->pBt->usableSize ); /* by btreeComputeFreeSpace() */
  if( gap>top ){
    if( top==0 && pPage->pBt->usableSize==65536 ){
      top = 65536;
    }else{
      return SQLITE_CORRUPT_PAGE(pPage);
    }
  }

  /* If there is enough space between gap and top for one more cell pointer
  ** array entry offset, and if the freelist is not empty, then search the
  ** freelist looking for a free slot big enough to satisfy the request.
  /* If there is enough space between gap and top for one more cell pointer,
  ** and if the freelist is not empty, then search the
  ** freelist looking for a slot big enough to satisfy the request.
  */
  testcase( gap+2==top );
  testcase( gap+1==top );
  testcase( gap==top );
  if( (data[hdr+2] || data[hdr+1]) && gap+2<=top ){
    u8 *pSpace = pageFindSlot(pPage, nByte, &rc);
    if( pSpace ){
      int g2;
      assert( pSpace>=data && (pSpace - data)<65536 );
      *pIdx = (int)(pSpace - data);
      return SQLITE_OK;
      assert( pSpace+nByte<=data+pPage->pBt->usableSize );
      *pIdx = g2 = (int)(pSpace-data);
      if( g2<=gap ){
        return SQLITE_CORRUPT_PAGE(pPage);
      }else{
        return SQLITE_OK;
      }
    }else if( rc ){
      return rc;
    }
  }

  /* The request could not be fulfilled using a freelist slot.  Check
  ** to see if defragmentation is necessary.
  */
  testcase( gap+2+nByte==top );
  if( gap+2+nByte>top ){
    assert( pPage->nCell>0 || CORRUPT_DB );
    assert( pPage->nFree>=0 );
    rc = defragmentPage(pPage, MIN(4, pPage->nFree - (2+nByte)));
    if( rc ) return rc;
    top = get2byteNotZero(&data[hdr+5]);
    assert( gap+2+nByte<=top );
  }


  /* Allocate memory from the gap in between the cell pointer array
  ** and the cell content area.  The btreeInitPage() call has already
  ** and the cell content area.  The btreeComputeFreeSpace() call has already
  ** validated the freelist.  Given that the freelist is valid, there
  ** is no way that the allocation can extend off the end of the page.
  ** The assert() below verifies the previous sentence.
  */
  top -= nByte;
  put2byte(&data[hdr+5], top);
  assert( top+nByte <= (int)pPage->pBt->usableSize );
  *pIdx = top;
  return SQLITE_OK;
}

/*
** Return a section of the pPage->aData to the freelist.
** The first byte of the new free block is pPage->aData[iStart]
** and the size of the block is iSize bytes.
**
** Adjacent freeblocks are coalesced.
**
** Note that even though the freeblock list was checked by btreeInitPage(),
** Even though the freeblock list was checked by btreeComputeFreeSpace(),
** that routine will not detect overlap between cells or freeblocks.  Nor
** does it detect cells or freeblocks that encrouch into the reserved bytes
** at the end of the page.  So do additional corruption checks inside this
** routine and return SQLITE_CORRUPT if any problems are found.
*/
static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
  u16 iPtr;                             /* Address of ptr to next freeblock */
  u16 iFreeBlk;                         /* Address of the next freeblock */
  u8 hdr;                               /* Page header size.  0 or 100 */
  u8 nFrag = 0;                         /* Reduction in fragmentation */
  u16 iOrigSize = iSize;                /* Original value of iSize */
  u16 x;                                /* Offset to cell content area */
  u32 iEnd = iStart + iSize;            /* First byte past the iStart buffer */
  unsigned char *data = pPage->aData;   /* Page content */
  u8 *pTmp;                             /* Temporary ptr into data[] */

  assert( pPage->pBt!=0 );
  assert( sqlite3PagerIswriteable(pPage->pDbPage) );
  assert( CORRUPT_DB || iStart>=pPage->hdrOffset+6+pPage->childPtrSize );
  assert( CORRUPT_DB || iEnd <= pPage->pBt->usableSize );
  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  assert( iSize>=4 );   /* Minimum cell size is 4 */
  assert( iStart<=pPage->pBt->usableSize-4 );

  /* The list of freeblocks must be in ascending order.  Find the 
  ** spot on the list where iStart should be inserted.
  */
  hdr = pPage->hdrOffset;
  iPtr = hdr + 1;
  if( data[iPtr+1]==0 && data[iPtr]==0 ){
    iFreeBlk = 0;  /* Shortcut for the case when the freelist is empty */
  }else{
    while( (iFreeBlk = get2byte(&data[iPtr]))<iStart ){
      if( iFreeBlk<iPtr+4 ){
        if( iFreeBlk==0 ) break;
      if( iFreeBlk<=iPtr ){
        if( iFreeBlk==0 ) break; /* TH3: corrupt082.100 */
        return SQLITE_CORRUPT_PAGE(pPage);
      }
      iPtr = iFreeBlk;
    }
    if( iFreeBlk>pPage->pBt->usableSize-4 ){
    if( iFreeBlk>pPage->pBt->usableSize-4 ){ /* TH3: corrupt081.100 */
      return SQLITE_CORRUPT_PAGE(pPage);
    }
    assert( iFreeBlk>iPtr || iFreeBlk==0 );
    assert( iFreeBlk>iPtr || iFreeBlk==0 || CORRUPT_DB );
  
    /* At this point:
    **    iFreeBlk:   First freeblock after iStart, or zero if none
    **    iPtr:       The address of a pointer to iFreeBlk
    **
    ** Check to see if iFreeBlk should be coalesced onto the end of iStart.
    */
1987
1988
1989
1990
1991
1992
1993

1994

1995
1996
1997
1998

1999

2000
2001
2002
2003
2004
2005
2006
2104
2105
2106
2107
2108
2109
2110
2111

2112
2113
2114
2115
2116
2117

2118
2119
2120
2121
2122
2123
2124
2125







+
-
+




+
-
+







        iSize = iEnd - iPtr;
        iStart = iPtr;
      }
    }
    if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_PAGE(pPage);
    data[hdr+7] -= nFrag;
  }
  pTmp = &data[hdr+5];
  x = get2byte(&data[hdr+5]);
  x = get2byte(pTmp);
  if( iStart<=x ){
    /* The new freeblock is at the beginning of the cell content area,
    ** so just extend the cell content area rather than create another
    ** freelist entry */
    if( iStart<x ) return SQLITE_CORRUPT_PAGE(pPage);
    if( iStart<x || iPtr!=hdr+1 ) return SQLITE_CORRUPT_PAGE(pPage);
    if( iPtr!=hdr+1 ) return SQLITE_CORRUPT_PAGE(pPage);
    put2byte(&data[hdr+1], iFreeBlk);
    put2byte(&data[hdr+5], iEnd);
  }else{
    /* Insert the new freeblock into the freelist */
    put2byte(&data[iPtr], iStart);
  }
  if( pPage->pBt->btsFlags & BTS_FAST_SECURE ){
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026




2027
2028
2029
2030
2031
2032
2033
2034
2035
2036




2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050

































2051
2052
2053
2054
2055
2056
2057




2058
2059
2060
2061
2062
2063
2064
2065
2066




2067
2068
2069
2070
2071
2072
2073


2074

2075
2076
2077
2078
2079
2080


2081
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
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179

2180
2181
2182
2183
2184
2185
2186
2136
2137
2138
2139
2140
2141
2142



2143
2144
2145
2146

2147
2148
2149
2150
2151
2152



2153
2154
2155
2156














2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192




2193
2194
2195
2196









2197
2198
2199
2200







2201
2202

2203
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
2234
2235
2236














2237








2238




















2239
2240
2241
2242
2243
2244
2245
2246
2247

2248
2249
2250
2251
2252
2253
2254
2255







-
-
-
+
+
+
+
-






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



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




-
-
+
+
-
-
-
-
-

-
+



-

-











-
+
+

-
+


-
-
-
-
-
-
-
-
-
-
-
-
-




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

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-









-
+







/*
** Decode the flags byte (the first byte of the header) for a page
** and initialize fields of the MemPage structure accordingly.
**
** Only the following combinations are supported.  Anything different
** indicates a corrupt database files:
**
**         PTF_ZERODATA
**         PTF_ZERODATA | PTF_LEAF
**         PTF_LEAFDATA | PTF_INTKEY
**         PTF_ZERODATA                             (0x02,  2)
**         PTF_LEAFDATA | PTF_INTKEY                (0x05,  5)
**         PTF_ZERODATA | PTF_LEAF                  (0x0a, 10)
**         PTF_LEAFDATA | PTF_INTKEY | PTF_LEAF     (0x0d, 13)
**         PTF_LEAFDATA | PTF_INTKEY | PTF_LEAF
*/
static int decodeFlags(MemPage *pPage, int flagByte){
  BtShared *pBt;     /* A copy of pPage->pBt */

  assert( pPage->hdrOffset==(pPage->pgno==1 ? 100 : 0) );
  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  pPage->leaf = (u8)(flagByte>>3);  assert( PTF_LEAF == 1<<3 );
  flagByte &= ~PTF_LEAF;
  pPage->childPtrSize = 4-4*pPage->leaf;
  pBt = pPage->pBt;
  pPage->max1bytePayload = pBt->max1bytePayload;
  if( flagByte>=(PTF_ZERODATA | PTF_LEAF) ){
    pPage->childPtrSize = 0;
  pPage->xCellSize = cellSizePtr;
  pBt = pPage->pBt;
  if( flagByte==(PTF_LEAFDATA | PTF_INTKEY) ){
    /* EVIDENCE-OF: R-07291-35328 A value of 5 (0x05) means the page is an
    ** interior table b-tree page. */
    assert( (PTF_LEAFDATA|PTF_INTKEY)==5 );
    /* EVIDENCE-OF: R-26900-09176 A value of 13 (0x0d) means the page is a
    ** leaf table b-tree page. */
    assert( (PTF_LEAFDATA|PTF_INTKEY|PTF_LEAF)==13 );
    pPage->intKey = 1;
    if( pPage->leaf ){
      pPage->intKeyLeaf = 1;
      pPage->xParseCell = btreeParseCellPtr;
    }else{
    pPage->leaf = 1;
    if( flagByte==(PTF_LEAFDATA | PTF_INTKEY | PTF_LEAF) ){
      pPage->intKeyLeaf = 1;
      pPage->xCellSize = cellSizePtrTableLeaf;
      pPage->xParseCell = btreeParseCellPtr;
      pPage->intKey = 1;
      pPage->maxLocal = pBt->maxLeaf;
      pPage->minLocal = pBt->minLeaf;
    }else if( flagByte==(PTF_ZERODATA | PTF_LEAF) ){
      pPage->intKey = 0;
      pPage->intKeyLeaf = 0;
      pPage->xCellSize = cellSizePtr;
      pPage->xParseCell = btreeParseCellPtrIndex;
      pPage->maxLocal = pBt->maxLocal;
      pPage->minLocal = pBt->minLocal;
    }else{
      pPage->intKey = 0;
      pPage->intKeyLeaf = 0;
      pPage->xCellSize = cellSizePtr;
      pPage->xParseCell = btreeParseCellPtrIndex;
      return SQLITE_CORRUPT_PAGE(pPage);
    }
  }else{
    pPage->childPtrSize = 4;
    pPage->leaf = 0;
    if( flagByte==(PTF_ZERODATA) ){
      pPage->intKey = 0;
      pPage->intKeyLeaf = 0;
      pPage->xCellSize = cellSizePtr;
      pPage->xParseCell = btreeParseCellPtrIndex;
      pPage->maxLocal = pBt->maxLocal;
      pPage->minLocal = pBt->minLocal;
    }else if( flagByte==(PTF_LEAFDATA | PTF_INTKEY) ){
      pPage->intKeyLeaf = 0;
      pPage->xCellSize = cellSizePtrNoPayload;
      pPage->xParseCell = btreeParseCellPtrNoPayload;
    }
    pPage->maxLocal = pBt->maxLeaf;
    pPage->minLocal = pBt->minLeaf;
  }else if( flagByte==PTF_ZERODATA ){
      pPage->intKey = 1;
      pPage->maxLocal = pBt->maxLeaf;
      pPage->minLocal = pBt->minLeaf;
    }else{
    /* EVIDENCE-OF: R-43316-37308 A value of 2 (0x02) means the page is an
    ** interior index b-tree page. */
    assert( (PTF_ZERODATA)==2 );
    /* EVIDENCE-OF: R-59615-42828 A value of 10 (0x0a) means the page is a
    ** leaf index b-tree page. */
    assert( (PTF_ZERODATA|PTF_LEAF)==10 );
    pPage->intKey = 0;
    pPage->intKeyLeaf = 0;
    pPage->xParseCell = btreeParseCellPtrIndex;
      pPage->intKey = 0;
      pPage->intKeyLeaf = 0;
      pPage->xCellSize = cellSizePtr;
      pPage->xParseCell = btreeParseCellPtrIndex;
    pPage->maxLocal = pBt->maxLocal;
    pPage->minLocal = pBt->minLocal;
  }else{
    /* EVIDENCE-OF: R-47608-56469 Any other value for the b-tree page type is
    ** an error. */
    return SQLITE_CORRUPT_PAGE(pPage);
  }
      return SQLITE_CORRUPT_PAGE(pPage);
    }
  pPage->max1bytePayload = pBt->max1bytePayload;
  }
  return SQLITE_OK;
}

/*
** Initialize the auxiliary information for a disk block.
**
** Compute the amount of freespace on the page.  In other words, fill
** in the pPage->nFree field.
** Return SQLITE_OK on success.  If we see that the page does
** not contain a well-formed database page, then return 
** SQLITE_CORRUPT.  Note that a return of SQLITE_OK does not
** guarantee that the page is well-formed.  It only shows that
** we failed to detect any corruption.
*/
static int btreeInitPage(MemPage *pPage){
static int btreeComputeFreeSpace(MemPage *pPage){
  int pc;            /* Address of a freeblock within pPage->aData[] */
  u8 hdr;            /* Offset to beginning of page header */
  u8 *data;          /* Equal to pPage->aData */
  BtShared *pBt;        /* The main btree structure */
  int usableSize;    /* Amount of usable space on each page */
  u16 cellOffset;    /* Offset from start of page to first cell pointer */
  int nFree;         /* Number of unused bytes on the page */
  int top;           /* First byte of the cell content area */
  int iCellFirst;    /* First allowable cell or freeblock offset */
  int iCellLast;     /* Last possible cell or freeblock offset */

  assert( pPage->pBt!=0 );
  assert( pPage->pBt->db!=0 );
  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) );
  assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) );
  assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) );
  assert( pPage->isInit==0 );
  assert( pPage->isInit==1 );
  assert( pPage->nFree<0 );

  pBt = pPage->pBt;
  usableSize = pPage->pBt->usableSize;
  hdr = pPage->hdrOffset;
  data = pPage->aData;
  /* EVIDENCE-OF: R-28594-02890 The one-byte flag at offset 0 indicating
  ** the b-tree page type. */
  if( decodeFlags(pPage, data[hdr]) ){
    return SQLITE_CORRUPT_PAGE(pPage);
  }
  assert( pBt->pageSize>=512 && pBt->pageSize<=65536 );
  pPage->maskPage = (u16)(pBt->pageSize - 1);
  pPage->nOverflow = 0;
  usableSize = pBt->usableSize;
  pPage->cellOffset = cellOffset = hdr + 8 + pPage->childPtrSize;
  pPage->aDataEnd = &data[usableSize];
  pPage->aCellIdx = &data[cellOffset];
  pPage->aDataOfst = &data[pPage->childPtrSize];
  /* EVIDENCE-OF: R-58015-48175 The two-byte integer at offset 5 designates
  ** the start of the cell content area. A zero value for this integer is
  ** interpreted as 65536. */
  top = get2byteNotZero(&data[hdr+5]);
  /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
  ** number of cells on the page. */
  pPage->nCell = get2byte(&data[hdr+3]);
  if( pPage->nCell>MX_CELL(pBt) ){
    /* To many cells for a single page.  The page must be corrupt */
    return SQLITE_CORRUPT_PAGE(pPage);
  }
  testcase( pPage->nCell==MX_CELL(pBt) );
  /* EVIDENCE-OF: R-24089-57979 If a page contains no cells (which is only
  ** possible for a root page of a table that contains no rows) then the
  ** offset to the cell content area will equal the page size minus the
  ** bytes of reserved space. */
  assert( pPage->nCell>0 || top==usableSize || CORRUPT_DB );

  iCellFirst = hdr + 8 + pPage->childPtrSize + 2*pPage->nCell;
  /* A malformed database page might cause us to read past the end
  ** of page when parsing a cell.  
  **
  ** The following block of code checks early to see if a cell extends
  ** past the end of a page boundary and causes SQLITE_CORRUPT to be 
  ** returned if it does.
  */
  iCellFirst = cellOffset + 2*pPage->nCell;
  iCellLast = usableSize - 4;
  if( pBt->db->flags & SQLITE_CellSizeCk ){
    int i;            /* Index into the cell pointer array */
    int sz;           /* Size of a cell */

    if( !pPage->leaf ) iCellLast--;
    for(i=0; i<pPage->nCell; i++){
      pc = get2byteAligned(&data[cellOffset+i*2]);
      testcase( pc==iCellFirst );
      testcase( pc==iCellLast );
      if( pc<iCellFirst || pc>iCellLast ){
        return SQLITE_CORRUPT_PAGE(pPage);
      }
      sz = pPage->xCellSize(pPage, &data[pc]);
      testcase( pc+sz==usableSize );
      if( pc+sz>usableSize ){
        return SQLITE_CORRUPT_PAGE(pPage);
      }
    }
    if( !pPage->leaf ) iCellLast++;
  }  

  /* Compute the total free space on the page
  ** EVIDENCE-OF: R-23588-34450 The two-byte integer at offset 1 gives the
  ** start of the first freeblock on the page, or is zero if there are no
  ** freeblocks. */
  pc = get2byte(&data[hdr+1]);
  nFree = data[hdr+7] + top;  /* Init nFree to non-freeblock free space */
  if( pc>0 ){
    u32 next, size;
    if( pc<iCellFirst ){
    if( pc<top ){
      /* EVIDENCE-OF: R-55530-52930 In a well-formed b-tree page, there will
      ** always be at least one cell before the first freeblock.
      */
      return SQLITE_CORRUPT_PAGE(pPage); 
    }
    while( 1 ){
      if( pc>iCellLast ){
2206
2207
2208
2209
2210
2211
2212
2213

2214
2215
2216


























































































2217



2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231

2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247

2248
2249
2250
2251
2252
2253
2254
2275
2276
2277
2278
2279
2280
2281

2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392

2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408

2409
2410
2411
2412
2413
2414
2415
2416







-
+



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

+
+
+













-
+















-
+







  /* At this point, nFree contains the sum of the offset to the start
  ** of the cell-content area plus the number of free bytes within
  ** the cell-content area. If this is greater than the usable-size
  ** of the page, then the page must be corrupted. This check also
  ** serves to verify that the offset to the start of the cell-content
  ** area, according to the page header, lies within the page.
  */
  if( nFree>usableSize ){
  if( nFree>usableSize || nFree<iCellFirst ){
    return SQLITE_CORRUPT_PAGE(pPage);
  }
  pPage->nFree = (u16)(nFree - iCellFirst);
  return SQLITE_OK;
}

/*
** Do additional sanity check after btreeInitPage() if
** PRAGMA cell_size_check=ON 
*/
static SQLITE_NOINLINE int btreeCellSizeCheck(MemPage *pPage){
  int iCellFirst;    /* First allowable cell or freeblock offset */
  int iCellLast;     /* Last possible cell or freeblock offset */
  int i;             /* Index into the cell pointer array */
  int sz;            /* Size of a cell */
  int pc;            /* Address of a freeblock within pPage->aData[] */
  u8 *data;          /* Equal to pPage->aData */
  int usableSize;    /* Maximum usable space on the page */
  int cellOffset;    /* Start of cell content area */

  iCellFirst = pPage->cellOffset + 2*pPage->nCell;
  usableSize = pPage->pBt->usableSize;
  iCellLast = usableSize - 4;
  data = pPage->aData;
  cellOffset = pPage->cellOffset;
  if( !pPage->leaf ) iCellLast--;
  for(i=0; i<pPage->nCell; i++){
    pc = get2byteAligned(&data[cellOffset+i*2]);
    testcase( pc==iCellFirst );
    testcase( pc==iCellLast );
    if( pc<iCellFirst || pc>iCellLast ){
      return SQLITE_CORRUPT_PAGE(pPage);
    }
    sz = pPage->xCellSize(pPage, &data[pc]);
    testcase( pc+sz==usableSize );
    if( pc+sz>usableSize ){
      return SQLITE_CORRUPT_PAGE(pPage);
    }
  }
  return SQLITE_OK;
}

/*
** Initialize the auxiliary information for a disk block.
**
** Return SQLITE_OK on success.  If we see that the page does
** not contain a well-formed database page, then return 
** SQLITE_CORRUPT.  Note that a return of SQLITE_OK does not
** guarantee that the page is well-formed.  It only shows that
** we failed to detect any corruption.
*/
static int btreeInitPage(MemPage *pPage){
  u8 *data;          /* Equal to pPage->aData */
  BtShared *pBt;        /* The main btree structure */

  assert( pPage->pBt!=0 );
  assert( pPage->pBt->db!=0 );
  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) );
  assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) );
  assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) );
  assert( pPage->isInit==0 );

  pBt = pPage->pBt;
  data = pPage->aData + pPage->hdrOffset;
  /* EVIDENCE-OF: R-28594-02890 The one-byte flag at offset 0 indicating
  ** the b-tree page type. */
  if( decodeFlags(pPage, data[0]) ){
    return SQLITE_CORRUPT_PAGE(pPage);
  }
  assert( pBt->pageSize>=512 && pBt->pageSize<=65536 );
  pPage->maskPage = (u16)(pBt->pageSize - 1);
  pPage->nOverflow = 0;
  pPage->cellOffset = pPage->hdrOffset + 8 + pPage->childPtrSize;
  pPage->aCellIdx = data + pPage->childPtrSize + 8;
  pPage->aDataEnd = pPage->aData + pBt->pageSize;
  pPage->aDataOfst = pPage->aData + pPage->childPtrSize;
  /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
  ** number of cells on the page. */
  pPage->nCell = get2byte(&data[3]);
  if( pPage->nCell>MX_CELL(pBt) ){
    /* To many cells for a single page.  The page must be corrupt */
    return SQLITE_CORRUPT_PAGE(pPage);
  }
  testcase( pPage->nCell==MX_CELL(pBt) );
  /* EVIDENCE-OF: R-24089-57979 If a page contains no cells (which is only
  ** possible for a root page of a table that contains no rows) then the
  ** offset to the cell content area will equal the page size minus the
  ** bytes of reserved space. */
  assert( pPage->nCell>0
       || get2byteNotZero(&data[5])==(int)pBt->usableSize
       || CORRUPT_DB );
  pPage->nFree = -1;  /* Indicate that this value is yet uncomputed */
  pPage->isInit = 1;
  if( pBt->db->flags & SQLITE_CellSizeCk ){
    return btreeCellSizeCheck(pPage);
  }
  return SQLITE_OK;
}

/*
** Set up a raw page so that it looks like a database page holding
** no entries.
*/
static void zeroPage(MemPage *pPage, int flags){
  unsigned char *data = pPage->aData;
  BtShared *pBt = pPage->pBt;
  u8 hdr = pPage->hdrOffset;
  u16 first;

  assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno );
  assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno || CORRUPT_DB );
  assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage );
  assert( sqlite3PagerGetData(pPage->pDbPage) == data );
  assert( sqlite3PagerIswriteable(pPage->pDbPage) );
  assert( sqlite3_mutex_held(pBt->mutex) );
  if( pBt->btsFlags & BTS_FAST_SECURE ){
    memset(&data[hdr], 0, pBt->usableSize - hdr);
  }
  data[hdr] = (char)flags;
  first = hdr + ((flags&PTF_LEAF)==0 ? 12 : 8);
  memset(&data[hdr+1], 0, 4);
  data[hdr+7] = 0;
  put2byte(&data[hdr+5], pBt->usableSize);
  pPage->nFree = (u16)(pBt->usableSize - first);
  decodeFlags(pPage, flags);
  pPage->cellOffset = first;
  pPage->aDataEnd = &data[pBt->usableSize];
  pPage->aDataEnd = &data[pBt->pageSize];
  pPage->aCellIdx = &data[first];
  pPage->aDataOfst = &data[pPage->childPtrSize];
  pPage->nOverflow = 0;
  assert( pBt->pageSize>=512 && pBt->pageSize<=65536 );
  pPage->maskPage = (u16)(pBt->pageSize - 1);
  pPage->nCell = 0;
  pPage->isInit = 1;
2318
2319
2320
2321
2322
2323
2324
2325

2326
2327
2328
2329
2330
2331
2332
2333
2334
2480
2481
2482
2483
2484
2485
2486

2487
2488

2489
2490
2491
2492
2493
2494
2495







-
+

-







/*
** Return the size of the database file in pages. If there is any kind of
** error, return ((unsigned int)-1).
*/
static Pgno btreePagecount(BtShared *pBt){
  return pBt->nPage;
}
u32 sqlite3BtreeLastPage(Btree *p){
Pgno sqlite3BtreeLastPage(Btree *p){
  assert( sqlite3BtreeHoldsMutex(p) );
  assert( ((p->pBt->nPage)&0x80000000)==0 );
  return btreePagecount(p->pBt);
}

/*
** Get a page from the pager and initialize it.
**
** If pCur!=0 then the page is being fetched as part of a moveToChild()
2353
2354
2355
2356
2357
2358
2359
2360

2361
2362
2363
2364

2365
2366
2367
2368
2369
2370
2371
2372

2373
2374
2375

2376
2377
2378
2379
2380
2381
2382
2383

2384
2385
2386
2387



2388
2389
2390
2391
2392
2393

2394
2395
2396
2397
2398
2399
2400
2514
2515
2516
2517
2518
2519
2520

2521
2522
2523
2524

2525
2526
2527
2528
2529
2530
2531


2532
2533
2534

2535
2536
2537
2538
2539
2540
2541


2542
2543
2544
2545

2546
2547
2548
2549
2550
2551
2552
2553

2554
2555
2556
2557
2558
2559
2560
2561







-
+



-
+






-
-
+


-
+






-
-
+



-
+
+
+





-
+







  assert( sqlite3_mutex_held(pBt->mutex) );
  assert( pCur==0 || ppPage==&pCur->pPage );
  assert( pCur==0 || bReadOnly==pCur->curPagerFlags );
  assert( pCur==0 || pCur->iPage>0 );

  if( pgno>btreePagecount(pBt) ){
    rc = SQLITE_CORRUPT_BKPT;
    goto getAndInitPage_error;
    goto getAndInitPage_error1;
  }
  rc = sqlite3PagerGet(pBt->pPager, pgno, (DbPage**)&pDbPage, bReadOnly);
  if( rc ){
    goto getAndInitPage_error;
    goto getAndInitPage_error1;
  }
  *ppPage = (MemPage*)sqlite3PagerGetExtra(pDbPage);
  if( (*ppPage)->isInit==0 ){
    btreePageFromDbPage(pDbPage, pgno, pBt);
    rc = btreeInitPage(*ppPage);
    if( rc!=SQLITE_OK ){
      releasePage(*ppPage);
      goto getAndInitPage_error;
      goto getAndInitPage_error2;
    }
  }
  assert( (*ppPage)->pgno==pgno );
  assert( (*ppPage)->pgno==pgno || CORRUPT_DB );
  assert( (*ppPage)->aData==sqlite3PagerGetData(pDbPage) );

  /* If obtaining a child page for a cursor, we must verify that the page is
  ** compatible with the root page. */
  if( pCur && ((*ppPage)->nCell<1 || (*ppPage)->intKey!=pCur->curIntKey) ){
    rc = SQLITE_CORRUPT_PGNO(pgno);
    releasePage(*ppPage);
    goto getAndInitPage_error;
    goto getAndInitPage_error2;
  }
  return SQLITE_OK;

getAndInitPage_error:
getAndInitPage_error2:
  releasePage(*ppPage);
getAndInitPage_error1:
  if( pCur ){
    pCur->iPage--;
    pCur->pPage = pCur->apPage[pCur->iPage];
  }
  testcase( pgno==0 );
  assert( pgno!=0 || rc==SQLITE_CORRUPT );
  assert( pgno!=0 || rc!=SQLITE_OK );
  return rc;
}

#ifndef SQLITE_OMIT_CONCURRENT
/* 
** Set the value of the MemPage.pgnoRoot variable, if it exists.
*/
2494
2495
2496
2497
2498
2499
2500
2501

2502
2503
2504
2505
2506
2507
2508
2509
2655
2656
2657
2658
2659
2660
2661

2662

2663
2664
2665
2666
2667
2668
2669







-
+
-







/*
** Invoke the busy handler for a btree.
*/
static int btreeInvokeBusyHandler(void *pArg){
  BtShared *pBt = (BtShared*)pArg;
  assert( pBt->db );
  assert( sqlite3_mutex_held(pBt->db->mutex) );
  return sqlite3InvokeBusyHandler(&pBt->db->busyHandler,
  return sqlite3InvokeBusyHandler(&pBt->db->busyHandler);
                                  sqlite3PagerFile(pBt->pPager));
}

/*
** Open a database file.
** 
** zFilename is the name of the database file.  If zFilename is NULL
** then an ephemeral database is created.  The ephemeral database might
2599
2600
2601
2602
2603
2604
2605



2606
2607
2608




2609
2610
2611
2612
2613
2614

2615
2616
2617
2618
2619
2620
2621
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768



2769
2770
2771
2772
2773
2774
2775
2776
2777

2778
2779
2780
2781
2782
2783
2784
2785







+
+
+
-
-
-
+
+
+
+





-
+







      }
      if( isMemdb ){
        memcpy(zFullPathname, zFilename, nFilename);
      }else{
        rc = sqlite3OsFullPathname(pVfs, zFilename,
                                   nFullPathname, zFullPathname);
        if( rc ){
          if( rc==SQLITE_OK_SYMLINK ){
            rc = SQLITE_OK;
          }else{
          sqlite3_free(zFullPathname);
          sqlite3_free(p);
          return rc;
            sqlite3_free(zFullPathname);
            sqlite3_free(p);
            return rc;
          }
        }
      }
#if SQLITE_THREADSAFE
      mutexOpen = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_OPEN);
      sqlite3_mutex_enter(mutexOpen);
      mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
      mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN);
      sqlite3_mutex_enter(mutexShared);
#endif
      for(pBt=GLOBAL(BtShared*,sqlite3SharedCacheList); pBt; pBt=pBt->pNext){
        assert( pBt->nRef>0 );
        if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager, 0))
                 && sqlite3PagerVfs(pBt->pPager)==pVfs ){
          int iDb;
2726
2727
2728
2729
2730
2731
2732
2733

2734
2735
2736
2737
2738
2739
2740
2890
2891
2892
2893
2894
2895
2896

2897
2898
2899
2900
2901
2902
2903
2904







-
+







   
#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO)
    /* Add the new BtShared object to the linked list sharable BtShareds.
    */
    pBt->nRef = 1;
    if( p->sharable ){
      MUTEX_LOGIC( sqlite3_mutex *mutexShared; )
      MUTEX_LOGIC( mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);)
      MUTEX_LOGIC( mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN);)
      if( SQLITE_THREADSAFE && sqlite3GlobalConfig.bCoreMutex ){
        pBt->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_FAST);
        if( pBt->mutex==0 ){
          rc = SQLITE_NOMEM_BKPT;
          goto btree_open_out;
        }
      }
2791
2792
2793
2794
2795
2796
2797
2798

2799
2800
2801
2802
2803
2804
2805
2955
2956
2957
2958
2959
2960
2961

2962
2963
2964
2965
2966
2967
2968
2969







-
+







    sqlite3_file *pFile;

    /* If the B-Tree was successfully opened, set the pager-cache size to the
    ** default value. Except, when opening on an existing shared pager-cache,
    ** do not change the pager-cache size.
    */
    if( sqlite3BtreeSchema(p, 0, 0)==0 ){
      sqlite3PagerSetCachesize(p->pBt->pPager, SQLITE_DEFAULT_CACHE_SIZE);
      sqlite3BtreeSetCacheSize(p, SQLITE_DEFAULT_CACHE_SIZE);
    }

    pFile = sqlite3PagerFile(pBt->pPager);
    if( pFile->pMethods ){
      sqlite3OsFileControlHint(pFile, SQLITE_FCNTL_PDB, (void*)&pBt->db);
    }
  }
2815
2816
2817
2818
2819
2820
2821
2822

2823
2824
2825
2826
2827
2828


2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847

2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877





























2878
2879
2880


2881
2882

2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905




2906
2907
2908
2909
2910
2911






2912
2913

2914
2915
2916
2917
2918
2919
2920
2979
2980
2981
2982
2983
2984
2985

2986
2987
2988
2989
2990


2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010

3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022



















3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051



3052
3053


3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072

3073
3074
3075
3076
3077
3078
3079
3080






3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096







-
+




-
-
+
+


















-
+











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


















-




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


+







** Decrement the BtShared.nRef counter.  When it reaches zero,
** remove the BtShared structure from the sharing list.  Return
** true if the BtShared.nRef counter reaches zero and return
** false if it is still positive.
*/
static int removeFromSharingList(BtShared *pBt){
#ifndef SQLITE_OMIT_SHARED_CACHE
  MUTEX_LOGIC( sqlite3_mutex *pMaster; )
  MUTEX_LOGIC( sqlite3_mutex *pMainMtx; )
  BtShared *pList;
  int removed = 0;

  assert( sqlite3_mutex_notheld(pBt->mutex) );
  MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
  sqlite3_mutex_enter(pMaster);
  MUTEX_LOGIC( pMainMtx = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); )
  sqlite3_mutex_enter(pMainMtx);
  pBt->nRef--;
  if( pBt->nRef<=0 ){
    if( GLOBAL(BtShared*,sqlite3SharedCacheList)==pBt ){
      GLOBAL(BtShared*,sqlite3SharedCacheList) = pBt->pNext;
    }else{
      pList = GLOBAL(BtShared*,sqlite3SharedCacheList);
      while( ALWAYS(pList) && pList->pNext!=pBt ){
        pList=pList->pNext;
      }
      if( ALWAYS(pList) ){
        pList->pNext = pBt->pNext;
      }
    }
    if( SQLITE_THREADSAFE ){
      sqlite3_mutex_free(pBt->mutex);
    }
    removed = 1;
  }
  sqlite3_mutex_leave(pMaster);
  sqlite3_mutex_leave(pMainMtx);
  return removed;
#else
  return 1;
#endif
}

/*
** Make sure pBt->pTmpSpace points to an allocation of 
** MX_CELL_SIZE(pBt) bytes with a 4-byte prefix for a left-child
** pointer.
*/
static void allocateTempSpace(BtShared *pBt){
  if( !pBt->pTmpSpace ){
    pBt->pTmpSpace = sqlite3PageMalloc( pBt->pageSize );

    /* One of the uses of pBt->pTmpSpace is to format cells before
    ** inserting them into a leaf page (function fillInCell()). If
    ** a cell is less than 4 bytes in size, it is rounded up to 4 bytes
    ** by the various routines that manipulate binary cells. Which
    ** can mean that fillInCell() only initializes the first 2 or 3
    ** bytes of pTmpSpace, but that the first 4 bytes are copied from
    ** it into a database page. This is not actually a problem, but it
    ** does cause a valgrind error when the 1 or 2 bytes of unitialized 
    ** data is passed to system call write(). So to avoid this error,
    ** zero the first 4 bytes of temp space here.
    **
    ** Also:  Provide four bytes of initialized space before the
    ** beginning of pTmpSpace as an area available to prepend the
    ** left-child pointer to the beginning of a cell.
    */
static SQLITE_NOINLINE int allocateTempSpace(BtShared *pBt){
  assert( pBt!=0 );
  assert( pBt->pTmpSpace==0 );
  /* This routine is called only by btreeCursor() when allocating the
  ** first write cursor for the BtShared object */
  assert( pBt->pCursor!=0 && (pBt->pCursor->curFlags & BTCF_WriteFlag)!=0 );
  pBt->pTmpSpace = sqlite3PageMalloc( pBt->pageSize );
  if( pBt->pTmpSpace==0 ){
    BtCursor *pCur = pBt->pCursor;
    pBt->pCursor = pCur->pNext;  /* Unlink the cursor */
    memset(pCur, 0, sizeof(*pCur));
    return SQLITE_NOMEM_BKPT;
  }

  /* One of the uses of pBt->pTmpSpace is to format cells before
  ** inserting them into a leaf page (function fillInCell()). If
  ** a cell is less than 4 bytes in size, it is rounded up to 4 bytes
  ** by the various routines that manipulate binary cells. Which
  ** can mean that fillInCell() only initializes the first 2 or 3
  ** bytes of pTmpSpace, but that the first 4 bytes are copied from
  ** it into a database page. This is not actually a problem, but it
  ** does cause a valgrind error when the 1 or 2 bytes of unitialized 
  ** data is passed to system call write(). So to avoid this error,
  ** zero the first 4 bytes of temp space here.
  **
  ** Also:  Provide four bytes of initialized space before the
  ** beginning of pTmpSpace as an area available to prepend the
  ** left-child pointer to the beginning of a cell.
  */
    if( pBt->pTmpSpace ){
      memset(pBt->pTmpSpace, 0, 8);
      pBt->pTmpSpace += 4;
  memset(pBt->pTmpSpace, 0, 8);
  pBt->pTmpSpace += 4;
    }
  }
  return SQLITE_OK;
}

/*
** Free the pBt->pTmpSpace allocation
*/
static void freeTempSpace(BtShared *pBt){
  if( pBt->pTmpSpace ){
    pBt->pTmpSpace -= 4;
    sqlite3PageFree(pBt->pTmpSpace);
    pBt->pTmpSpace = 0;
  }
}

/*
** Close an open database and invalidate all cursors.
*/
int sqlite3BtreeClose(Btree *p){
  BtShared *pBt = p->pBt;
  BtCursor *pCur;

  /* Close all cursors opened via this handle.  */
  assert( sqlite3_mutex_held(p->db->mutex) );
  sqlite3BtreeEnter(p);

  /* Verify that no other cursors have this Btree open */
#ifdef SQLITE_DEBUG
  {
  pCur = pBt->pCursor;
  while( pCur ){
    BtCursor *pTmp = pCur;
    pCur = pCur->pNext;
    if( pTmp->pBtree==p ){
      sqlite3BtreeCloseCursor(pTmp);
    BtCursor *pCur = pBt->pCursor;
    while( pCur ){
      BtCursor *pTmp = pCur;
      pCur = pCur->pNext;
      assert( pTmp->pBtree!=p );

    }
  }
#endif

  /* Rollback any active transaction and free the handle structure.
  ** The call to sqlite3BtreeRollback() drops any table-locks held by
  ** this handle.
  */
  sqlite3BtreeRollback(p, SQLITE_OK, 0);
  sqlite3BtreeLeave(p);
3042
3043
3044
3045
3046
3047
3048

3049
3050

3051
3052
3053
3054



3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066

3067
3068
3069
3070
3071
3072
3073
3218
3219
3220
3221
3222
3223
3224
3225
3226

3227
3228



3229
3230
3231
3232
3233
3234
3235



3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248







+

-
+

-
-
-
+
+
+




-
-
-





+







** bytes per page is left unchanged.
**
** If the iFix!=0 then the BTS_PAGESIZE_FIXED flag is set so that the page size
** and autovacuum mode can no longer be changed.
*/
int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, int iFix){
  int rc = SQLITE_OK;
  int x;
  BtShared *pBt = p->pBt;
  assert( nReserve>=-1 && nReserve<=255 );
  assert( nReserve>=0 && nReserve<=255 );
  sqlite3BtreeEnter(p);
#if SQLITE_HAS_CODEC
  if( nReserve>pBt->optimalReserve ) pBt->optimalReserve = (u8)nReserve;
#endif
  pBt->nReserveWanted = nReserve;
  x = pBt->pageSize - pBt->usableSize;
  if( nReserve<x ) nReserve = x;
  if( pBt->btsFlags & BTS_PAGESIZE_FIXED ){
    sqlite3BtreeLeave(p);
    return SQLITE_READONLY;
  }
  if( nReserve<0 ){
    nReserve = pBt->pageSize - pBt->usableSize;
  }
  assert( nReserve>=0 && nReserve<=255 );
  if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE &&
        ((pageSize-1)&pageSize)==0 ){
    assert( (pageSize & 7)==0 );
    assert( !pBt->pCursor );
    if( nReserve>32 && pageSize==512 ) pageSize = 1024;
    pBt->pageSize = (u32)pageSize;
    freeTempSpace(pBt);
  }
  rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, nReserve);
  pBt->usableSize = pBt->pageSize - (u16)nReserve;
  if( iFix ) pBt->btsFlags |= BTS_PAGESIZE_FIXED;
  sqlite3BtreeLeave(p);
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109



3110
3111
3112


3113

3114

3115
3116
3117
3118
3119

3120
3121
3122
3123
3124
3125
3126
3127
3128
3129


3130
3131
3132
3133
3134
3135
3136
3275
3276
3277
3278
3279
3280
3281



3282
3283
3284
3285


3286
3287
3288
3289

3290



3291

3292
3293
3294
3295
3296
3297
3298
3299
3300


3301
3302
3303
3304
3305
3306
3307
3308
3309







-
-
-
+
+
+

-
-
+
+

+
-
+
-
-
-

-
+








-
-
+
+







}

/*
** Return the number of bytes of space at the end of every page that
** are intentually left unused.  This is the "reserved" space that is
** sometimes used by extensions.
**
** If SQLITE_HAS_MUTEX is defined then the number returned is the
** greater of the current reserved space and the maximum requested
** reserve space.
** The value returned is the larger of the current reserve size and
** the latest reserve size requested by SQLITE_FILECTRL_RESERVE_BYTES.
** The amount of reserve can only grow - never shrink.
*/
int sqlite3BtreeGetOptimalReserve(Btree *p){
  int n;
int sqlite3BtreeGetRequestedReserve(Btree *p){
  int n1, n2;
  sqlite3BtreeEnter(p);
  n1 = (int)p->pBt->nReserveWanted;
  n = sqlite3BtreeGetReserveNoMutex(p);
  n2 = sqlite3BtreeGetReserveNoMutex(p);
#ifdef SQLITE_HAS_CODEC
  if( n<p->pBt->optimalReserve ) n = p->pBt->optimalReserve;
#endif
  sqlite3BtreeLeave(p);
  return n;
  return n1>n2 ? n1 : n2;
}


/*
** Set the maximum page count for a database if mxPage is positive.
** No changes are made if mxPage is 0 or negative.
** Regardless of the value of mxPage, return the maximum page count.
*/
int sqlite3BtreeMaxPageCount(Btree *p, int mxPage){
  int n;
Pgno sqlite3BtreeMaxPageCount(Btree *p, Pgno mxPage){
  Pgno n;
  sqlite3BtreeEnter(p);
  n = sqlite3PagerMaxPageCount(p->pBt->pPager, mxPage);
  sqlite3BtreeLeave(p);
  return n;
}

/*
3251
3252
3253
3254
3255
3256
3257
3258
3259


3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273


3274
3275
3276
3277
3278
3279
3280
3424
3425
3426
3427
3428
3429
3430


3431
3432

3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443


3444
3445
3446
3447
3448
3449
3450
3451
3452







-
-
+
+
-











-
-
+
+







** well-formed database file, then SQLITE_CORRUPT is returned.
** SQLITE_BUSY is returned if the database is locked.  SQLITE_NOMEM
** is returned if we run out of memory. 
*/
static int lockBtree(BtShared *pBt){
  int rc;              /* Result code from subfunctions */
  MemPage *pPage1;     /* Page 1 of the database file */
  int nPage;           /* Number of pages in the database */
  int nPageFile = 0;   /* Number of pages in the database file */
  u32 nPage;           /* Number of pages in the database */
  u32 nPageFile = 0;   /* Number of pages in the database file */
  int nPageHeader;     /* Number of pages in the database according to hdr */

  assert( sqlite3_mutex_held(pBt->mutex) );
  assert( pBt->pPage1==0 );
  rc = sqlite3PagerSharedLock(pBt->pPager);
  if( rc!=SQLITE_OK ) return rc;
  rc = btreeGetPage(pBt, 1, &pPage1, 0);
  if( rc!=SQLITE_OK ) return rc;

  /* Do some checking to help insure the file we opened really is
  ** a valid database file. 
  */
  nPage = nPageHeader = get4byte(28+(u8*)pPage1->aData);
  sqlite3PagerPagecount(pBt->pPager, &nPageFile);
  nPage = get4byte(28+(u8*)pPage1->aData);
  sqlite3PagerPagecount(pBt->pPager, (int*)&nPageFile);
  if( nPage==0 || memcmp(24+(u8*)pPage1->aData, 92+(u8*)pPage1->aData,4)!=0 ){
    nPage = nPageFile;
  }
  if( (pBt->db->flags & SQLITE_ResetDatabase)!=0 ){
    nPage = 0;
  }
  if( nPage>0 ){
3293
3294
3295
3296
3297
3298
3299
3300

3301
3302
3303

3304
3305
3306
3307

3308
3309
3310
3311
3312
3313
3314
3315

3316
3317

3318
3319
3320
3321
3322
3323
3324
3465
3466
3467
3468
3469
3470
3471

3472
3473
3474

3475
3476
3477
3478

3479
3480
3481
3482
3483
3484
3485
3486

3487
3488

3489
3490
3491
3492
3493
3494
3495
3496







-
+


-
+



-
+







-
+

-
+







    if( page1[18]>1 ){
      pBt->btsFlags |= BTS_READ_ONLY;
    }
    if( page1[19]>1 ){
      goto page1_init_failed;
    }
#else
    if( page1[18]>2 ){
    if( page1[18]>3 ){
      pBt->btsFlags |= BTS_READ_ONLY;
    }
    if( page1[19]>2 ){
    if( page1[19]>3 ){
      goto page1_init_failed;
    }

    /* If the write version is set to 2, this database should be accessed
    /* If the read version is set to 2, this database should be accessed
    ** in WAL mode. If the log is not already open, open it now. Then 
    ** return SQLITE_OK and return without populating BtShared.pPage1.
    ** The caller detects this and calls this function again. This is
    ** required as the version of page 1 currently in the page1 buffer
    ** may not be the latest version - there may be a newer one in the log
    ** file.
    */
    if( page1[19]==2 && (pBt->btsFlags & BTS_NO_WAL)==0 ){
    if( page1[19]>=2 && (pBt->btsFlags & BTS_NO_WAL)==0 ){
      int isOpen = 0;
      rc = sqlite3PagerOpenWal(pBt->pPager, &isOpen);
      rc = sqlite3PagerOpenWal(pBt->pPager, (page1[19]==3), &isOpen);
      if( rc!=SQLITE_OK ){
        goto page1_init_failed;
      }else{
        setDefaultSyncFlag(pBt, SQLITE_DEFAULT_WAL_SYNCHRONOUS+1);
        if( isOpen==0 ){
          releasePageOne(pPage1);
          return SQLITE_OK;
3347
3348
3349
3350
3351
3352
3353

3354
3355
3356
3357
3358
3359
3360
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533







+







    ** between 512 and 65536 inclusive. */
    if( ((pageSize-1)&pageSize)!=0
     || pageSize>SQLITE_MAX_PAGE_SIZE 
     || pageSize<=256 
    ){
      goto page1_init_failed;
    }
    pBt->btsFlags |= BTS_PAGESIZE_FIXED;
    assert( (pageSize & 7)==0 );
    /* EVIDENCE-OF: R-59310-51205 The "reserved space" size in the 1-byte
    ** integer at offset 20 is the number of bytes of space at the end of
    ** each page to reserve for extensions. 
    **
    ** EVIDENCE-OF: R-37497-42412 The size of the reserved region is
    ** determined by the one-byte unsigned integer found at an offset of 20
3371
3372
3373
3374
3375
3376
3377

3378
3379
3380






3381
3382
3383
3384
3385
3386
3387
3544
3545
3546
3547
3548
3549
3550
3551



3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564







+
-
-
-
+
+
+
+
+
+







      pBt->usableSize = usableSize;
      pBt->pageSize = pageSize;
      freeTempSpace(pBt);
      rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize,
                                   pageSize-usableSize);
      return rc;
    }
    if( nPage>nPageFile ){
    if( sqlite3WritableSchema(pBt->db)==0 && nPage>nPageFile ){
      rc = SQLITE_CORRUPT_BKPT;
      goto page1_init_failed;
      if( sqlite3WritableSchema(pBt->db)==0 ){
        rc = SQLITE_CORRUPT_BKPT;
        goto page1_init_failed;
      }else{
        nPage = nPageFile;
      }
    }
    /* EVIDENCE-OF: R-28312-64704 However, the usable size is not allowed to
    ** be less than 480. In other words, if the page size is 512, then the
    ** reserved space size cannot exceed 32. */
    if( usableSize<480 ){
      goto page1_init_failed;
    }
3561
3562
3563
3564
3565
3566
3567

3568
3569

3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584

3585
3586
3587
3588
3589
3590
3591
3738
3739
3740
3741
3742
3743
3744
3745
3746

3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761

3762
3763
3764
3765
3766
3767
3768
3769







+

-
+














-
+







** One or the other of the two processes must give way or there can be
** no progress.  By returning SQLITE_BUSY and not invoking the busy callback
** when A already has a read lock, we encourage A to give up and let B
** proceed.
*/
int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){
  BtShared *pBt = p->pBt;
  Pager *pPager = pBt->pPager;
  int rc = SQLITE_OK;
  int bConcurrent = (p->db->bConcurrent && !ISAUTOVACUUM);
  int bConcurrent = (p->db->eConcurrent && !ISAUTOVACUUM(pBt));

  sqlite3BtreeEnter(p);
  btreeIntegrity(p);

  /* If the btree is already in a write-transaction, or it
  ** is already in a read-transaction and a read-transaction
  ** is requested, this is a no-op.
  */
  if( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){
    goto trans_begun;
  }
  assert( pBt->inTransaction==TRANS_WRITE || IfNotOmitAV(pBt->bDoTruncate)==0 );

  if( (p->db->flags & SQLITE_ResetDatabase) 
   && sqlite3PagerIsreadonly(pBt->pPager)==0 
   && sqlite3PagerIsreadonly(pPager)==0 
  ){
    pBt->btsFlags &= ~BTS_READ_ONLY;
  }

  /* Write transactions are not possible on a read-only database */
  if( (pBt->btsFlags & BTS_READ_ONLY)!=0 && wrflag ){
    rc = SQLITE_READONLY;
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

3659
3660
3661
3662
3663




3664
3665
3666
3667
3668
3669
3670
3797
3798
3799
3800
3801
3802
3803

3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
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







-
+





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














-
+












+




-
+
+
+
+







    }
  }
#endif

  /* Any read-only or read-write transaction implies a read-lock on 
  ** page 1. So if some other shared-cache client already has a write-lock 
  ** on page 1, the transaction cannot be opened. */
  rc = querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK);
  rc = querySharedCacheTableLock(p, SCHEMA_ROOT, READ_LOCK);
  if( SQLITE_OK!=rc ) goto trans_begun;

  pBt->btsFlags &= ~BTS_INITIALLY_EMPTY;
  if( pBt->nPage==0 ) pBt->btsFlags |= BTS_INITIALLY_EMPTY;
  do {
    sqlite3PagerWalDb(pPager, p->db);

#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
    /* If transitioning from no transaction directly to a write transaction,
    ** block for the WRITER lock first if possible. */
    if( pBt->pPage1==0 && wrflag ){
      assert( pBt->inTransaction==TRANS_NONE );
      rc = sqlite3PagerWalWriteLock(pPager, 1);
      if( rc!=SQLITE_BUSY && rc!=SQLITE_OK ) break;
    }
#endif

    /* Call lockBtree() until either pBt->pPage1 is populated or
    ** lockBtree() returns something other than SQLITE_OK. lockBtree()
    ** may return SQLITE_OK but leave pBt->pPage1 set to 0 if after
    ** reading page 1 it discovers that the page-size of the database 
    ** file is not pBt->pageSize. In this case lockBtree() will update
    ** pBt->pageSize to the page-size of the file on disk.
    */
    while( pBt->pPage1==0 && SQLITE_OK==(rc = lockBtree(pBt)) );

    if( rc==SQLITE_OK && wrflag ){
      if( (pBt->btsFlags & BTS_READ_ONLY)!=0 ){
        rc = SQLITE_READONLY;
      }else{
        int exFlag = bConcurrent ? -1 : (wrflag>1);
        rc = sqlite3PagerBegin(pBt->pPager, exFlag, sqlite3TempInMemory(p->db));
        rc = sqlite3PagerBegin(pPager, exFlag, sqlite3TempInMemory(p->db));
        if( rc==SQLITE_OK ){
          rc = newDatabase(pBt);
        }else if( rc==SQLITE_BUSY_SNAPSHOT && pBt->inTransaction==TRANS_NONE ){
          /* if there was no transaction opened when this function was
          ** called and SQLITE_BUSY_SNAPSHOT is returned, change the error
          ** code to SQLITE_BUSY. */
          rc = SQLITE_BUSY;
        }
      }
    }
  
    if( rc!=SQLITE_OK ){
      (void)sqlite3PagerWalWriteLock(pPager, 0);
      unlockBtreeIfUnused(pBt);
    }
  }while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE &&
          btreeInvokeBusyHandler(pBt) );
  sqlite3PagerResetLockTimeout(pBt->pPager);
  sqlite3PagerWalDb(pPager, 0);
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
  if( rc==SQLITE_BUSY_TIMEOUT ) rc = SQLITE_BUSY;
#endif

  if( rc==SQLITE_OK ){
    if( p->inTrans==TRANS_NONE ){
      pBt->nTransaction++;
#ifndef SQLITE_OMIT_SHARED_CACHE
      if( p->sharable ){
        assert( p->lock.pBtree==p && p->lock.iTable==1 );
3718
3719
3720
3721
3722
3723
3724
3725

3726
3727
3728
3729
3730
3731
3732
3912
3913
3914
3915
3916
3917
3918

3919
3920
3921
3922
3923
3924
3925
3926







-
+







    }
    if( wrflag ){
      /* This call makes sure that the pager has the correct number of
      ** open savepoints. If the second parameter is greater than 0 and
      ** the sub-journal is not already open, then it will be opened here.
      */
      int nSavepoint = p->db->nSavepoint;
      rc = sqlite3PagerOpenSavepoint(pBt->pPager, nSavepoint);
      rc = sqlite3PagerOpenSavepoint(pPager, nSavepoint);
      if( rc==SQLITE_OK && nSavepoint ){
        rc = btreePtrmapBegin(pBt, nSavepoint);
      }
    }
  }

  btreeIntegrity(p);
3752
3753
3754
3755
3756
3757
3758
3759

3760
3761
3762
3763
3764
3765
3766
3946
3947
3948
3949
3950
3951
3952

3953
3954
3955
3956
3957
3958
3959
3960







-
+







  rc = pPage->isInit ? SQLITE_OK : btreeInitPage(pPage);
  if( rc!=SQLITE_OK ) return rc;
  nCell = pPage->nCell;

  for(i=0; i<nCell; i++){
    u8 *pCell = findCell(pPage, i);

    ptrmapPutOvflPtr(pPage, pCell, &rc);
    ptrmapPutOvflPtr(pPage, pPage, pCell, &rc);

    if( !pPage->leaf ){
      Pgno childPgno = get4byte(pCell);
      ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno, &rc);
    }
  }

3815
3816
3817
3818
3819
3820
3821



3822
3823
3824
3825
3826
3827
3828
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025







+
+
+







          }
          if( iFrom==get4byte(pCell+info.nSize-4) ){
            put4byte(pCell+info.nSize-4, iTo);
            break;
          }
        }
      }else{
        if( pCell+4 > pPage->aData+pPage->pBt->usableSize ){
          return SQLITE_CORRUPT_PAGE(pPage);
        }
        if( get4byte(pCell)==iFrom ){
          put4byte(pCell, iTo);
          break;
        }
      }
    }
  
4001
4002
4003
4004
4005
4006
4007

4008
4009
4010
4011
4012
4013




4014
4015
4016
4017
4018
4019
4020
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222







+






+
+
+
+







      */
      if( bCommit==0 ){
        eMode = BTALLOC_LE;
        iNear = nFin;
      }
      do {
        MemPage *pFreePg;
        Pgno dbSize = btreePagecount(pBt);
        rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iNear, eMode);
        if( rc!=SQLITE_OK ){
          releasePage(pLastPg);
          return rc;
        }
        releasePage(pFreePg);
        if( iFreePg>dbSize ){
          releasePage(pLastPg);
          return SQLITE_CORRUPT_BKPT;
        }
      }while( bCommit && iFreePg>nFin );
      assert( iFreePg<iLastPg );
      
      rc = relocatePage(pBt, pLastPg, eType, iPtrPage, iFreePg, bCommit);
      releasePage(pLastPg);
      if( rc!=SQLITE_OK ){
        return rc;
4072
4073
4074
4075
4076
4077
4078
4079

4080
4081
4082
4083
4084
4085
4086
4274
4275
4276
4277
4278
4279
4280

4281
4282
4283
4284
4285
4286
4287
4288







-
+







  if( !pBt->autoVacuum ){
    rc = SQLITE_DONE;
  }else{
    Pgno nOrig = btreePagecount(pBt);
    Pgno nFree = get4byte(&pBt->pPage1->aData[36]);
    Pgno nFin = finalDbSize(pBt, nOrig, nFree);

    if( nOrig<nFin ){
    if( nOrig<nFin || nFree>=nOrig ){
      rc = SQLITE_CORRUPT_BKPT;
    }else if( nFree>0 ){
      rc = saveAllCursors(pBt, 0, 0);
      if( rc==SQLITE_OK ){
        invalidateAllOverflowCache(pBt);
        rc = incrVacuumStep(pBt, nFin, nOrig, 0);
      }
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108

4109
4110
4111









4112
4113
4114
4115
4116
4117
4118

4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131






















4132

4133
4134
4135
4136
4137
4138

4139
4140
4141

4142
4143



4144
4145
4146
4147
4148
4149
4150
4297
4298
4299
4300
4301
4302
4303





4304

4305
4306


4307
4308
4309
4310
4311
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
4360
4361
4362
4363
4364

4365
4366
4367
4368
4369


4370
4371
4372
4373
4374
4375
4376
4377
4378
4379







-
-
-
-
-

-
+

-
-
+
+
+
+
+
+
+
+
+







+













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





-
+



+
-
-
+
+
+







  sqlite3BtreeLeave(p);
  return rc;
}

/*
** This routine is called prior to sqlite3PagerCommit when a transaction
** is committed for an auto-vacuum database.
**
** If SQLITE_OK is returned, then *pnTrunc is set to the number of pages
** the database file should be truncated to during the commit process. 
** i.e. the database has been reorganized so that only the first *pnTrunc
** pages are in use.
*/
static int autoVacuumCommit(BtShared *pBt){
static int autoVacuumCommit(Btree *p){
  int rc = SQLITE_OK;
  Pager *pPager = pBt->pPager;
  VVA_ONLY( int nRef = sqlite3PagerRefcount(pPager); )
  Pager *pPager;
  BtShared *pBt;
  sqlite3 *db;
  VVA_ONLY( int nRef );

  assert( p!=0 );
  pBt = p->pBt;  
  pPager = pBt->pPager;
  VVA_ONLY( nRef = sqlite3PagerRefcount(pPager); )

  assert( sqlite3_mutex_held(pBt->mutex) );
  invalidateAllOverflowCache(pBt);
  assert(pBt->autoVacuum);
  if( !pBt->incrVacuum ){
    Pgno nFin;         /* Number of pages in database after autovacuuming */
    Pgno nFree;        /* Number of pages on the freelist initially */
    Pgno nVac;         /* Number of pages to vacuum */
    Pgno iFree;        /* The next page to be freed */
    Pgno nOrig;        /* Database size before freeing */

    nOrig = btreePagecount(pBt);
    if( PTRMAP_ISPAGE(pBt, nOrig) || nOrig==PENDING_BYTE_PAGE(pBt) ){
      /* It is not possible to create a database for which the final page
      ** is either a pointer-map page or the pending-byte page. If one
      ** is encountered, this indicates corruption.
      */
      return SQLITE_CORRUPT_BKPT;
    }

    nFree = get4byte(&pBt->pPage1->aData[36]);
    db = p->db;
    if( db->xAutovacPages ){
      int iDb;
      for(iDb=0; ALWAYS(iDb<db->nDb); iDb++){
        if( db->aDb[iDb].pBt==p ) break;
      }
      nVac = db->xAutovacPages(
        db->pAutovacPagesArg,
        db->aDb[iDb].zDbSName,
        nOrig,
        nFree,
        pBt->pageSize
      );
      if( nVac>nFree ){
        nVac = nFree;
      }
      if( nVac==0 ){
        return SQLITE_OK;
      }
    }else{
      nVac = nFree;
    }
    nFin = finalDbSize(pBt, nOrig, nFree);
    nFin = finalDbSize(pBt, nOrig, nVac);
    if( nFin>nOrig ) return SQLITE_CORRUPT_BKPT;
    if( nFin<nOrig ){
      rc = saveAllCursors(pBt, 0, 0);
    }
    for(iFree=nOrig; iFree>nFin && rc==SQLITE_OK; iFree--){
      rc = incrVacuumStep(pBt, nFin, iFree, 1);
      rc = incrVacuumStep(pBt, nFin, iFree, nVac==nFree);
    }
    if( (rc==SQLITE_DONE || rc==SQLITE_OK) && nFree>0 ){
      rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
      if( nVac==nFree ){
      put4byte(&pBt->pPage1->aData[32], 0);
      put4byte(&pBt->pPage1->aData[36], 0);
        put4byte(&pBt->pPage1->aData[32], 0);
        put4byte(&pBt->pPage1->aData[36], 0);
      }
      put4byte(&pBt->pPage1->aData[28], nFin);
      pBt->bDoTruncate = 1;
      pBt->nPage = nFin;
    }
    if( rc!=SQLITE_OK ){
      sqlite3PagerRollback(pPager);
    }
4338
4339
4340
4341
4342
4343
4344
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
4371
4372
4373
4374
4375

4376
4377
4378
4379

4380
4381
4382
4383
4384
4385
4386
4567
4568
4569
4570
4571
4572
4573



4574
4575
4576
4577
4578

4579
4580
4581
4582
4583
4584

4585
4586
4587
4588
4589
4590
4591
4592
4593

4594
4595
4596
4597
4598
4599
4600
4601
4602
4603

4604
4605
4606
4607

4608
4609
4610
4611
4612
4613
4614
4615







-
-
-
+
+
+


-
+





-
+








-
+









-
+



-
+







** At the end of this call, the rollback journal still exists on the
** disk and we are still holding all locks, so the transaction has not
** committed.  See sqlite3BtreeCommitPhaseTwo() for the second phase of the
** commit process.
**
** This call is a no-op if no write-transaction is currently active on pBt.
**
** Otherwise, sync the database file for the btree pBt. zMaster points to
** the name of a master journal file that should be written into the
** individual journal file, or is NULL, indicating no master journal file 
** Otherwise, sync the database file for the btree pBt. zSuperJrnl points to
** the name of a super-journal file that should be written into the
** individual journal file, or is NULL, indicating no super-journal file 
** (single database transaction).
**
** When this is called, the master journal should already have been
** When this is called, the super-journal should already have been
** created, populated with this journal pointer and synced to disk.
**
** Once this is routine has returned, the only thing required to commit
** the write-transaction for this database file is to delete the journal.
*/
int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zMaster){
int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zSuperJrnl){
  int rc = SQLITE_OK;
  if( p->inTrans==TRANS_WRITE ){
    BtShared *pBt = p->pBt;
    sqlite3BtreeEnter(p);

#ifndef SQLITE_OMIT_AUTOVACUUM
    if( pBt->autoVacuum ){
      assert( ISCONCURRENT==0 );
      rc = autoVacuumCommit(pBt);
      rc = autoVacuumCommit(p);
      if( rc!=SQLITE_OK ){
        sqlite3BtreeLeave(p);
        return rc;
      }
    }
    if( pBt->bDoTruncate ){
      sqlite3PagerTruncateImage(pBt->pPager, pBt->nPage);
    }
#endif
    if( rc==SQLITE_OK && ISCONCURRENT ){
    if( rc==SQLITE_OK && ISCONCURRENT && p->db->eConcurrent==CONCURRENT_OPEN ){
      rc = btreeFixUnlocked(p);
    }
    if( rc==SQLITE_OK ){
      rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zMaster, 0);
      rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zSuperJrnl, 0);
    }
    sqlite3BtreeLeave(p);
  }
  return rc;
}

/*
4441
4442
4443
4444
4445
4446
4447
4448

4449
4450
4451
4452
4453
4454
4455
4670
4671
4672
4673
4674
4675
4676

4677
4678
4679
4680
4681
4682
4683
4684







-
+







** drop locks.
**
** Normally, if an error occurs while the pager layer is attempting to 
** finalize the underlying journal file, this function returns an error and
** the upper layer will attempt a rollback. However, if the second argument
** is non-zero then this b-tree transaction is part of a multi-file 
** transaction. In this case, the transaction has already been committed 
** (by deleting a master journal file) and the caller will ignore this 
** (by deleting a super-journal file) and the caller will ignore this 
** functions return code. So, even if an error occurs in the pager layer,
** reset the b-tree objects internal state to indicate that the write
** transaction has been closed. This is quite safe, as the pager will have
** transitioned to the error state.
**
** This will release the write lock on the database file.  If there
** are no active cursors, it also releases the read lock.
4469
4470
4471
4472
4473
4474
4475
4476

4477
4478
4479
4480
4481
4482
4483
4698
4699
4700
4701
4702
4703
4704

4705
4706
4707
4708
4709
4710
4711
4712







-
+







    assert( pBt->inTransaction==TRANS_WRITE );
    assert( pBt->nTransaction>0 );
    rc = sqlite3PagerCommitPhaseTwo(pBt->pPager);
    if( rc!=SQLITE_OK && bCleanup==0 ){
      sqlite3BtreeLeave(p);
      return rc;
    }
    p->iDataVersion--;  /* Compensate for pPager->iDataVersion++; */
    p->iBDataVersion--;  /* Compensate for pPager->iDataVersion++; */
    pBt->inTransaction = TRANS_READ;
    btreeClearHasContent(pBt);
  }

  btreeEndTransaction(p);
  sqlite3BtreeLeave(p);
  return SQLITE_OK;
4546
4547
4548
4549
4550
4551
4552












4553
4554
4555
4556
4557
4558
4559
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800







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







      }
      btreeReleaseAllCursorPages(p);
    }
    sqlite3BtreeLeave(pBtree);
  }
  return rc;
}

/*
** Set the pBt->nPage field correctly, according to the current
** state of the database.  Assume pBt->pPage1 is valid.
*/
static void btreeSetNPage(BtShared *pBt, MemPage *pPage1){
  int nPage = get4byte(&pPage1->aData[28]);
  testcase( nPage==0 );
  if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage);
  testcase( pBt->nPage!=(u32)nPage );
  pBt->nPage = nPage;
}

/*
** Rollback the transaction in progress.
**
** If tripCode is not SQLITE_OK then cursors will be invalidated (tripped).
** Only write cursors are tripped if writeOnly is true but all cursors are
** tripped if writeOnly is false.  Any attempt to use
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603

4604
4605
4606
4607
4608
4609
4610
4833
4834
4835
4836
4837
4838
4839





4840
4841
4842
4843
4844
4845
4846
4847







-
-
-
-
-
+







      rc = rc2;
    }

    /* The rollback may have destroyed the pPage1->aData value.  So
    ** call btreeGetPage() on page 1 again to make
    ** sure pPage1->aData is set correctly. */
    if( btreeGetPage(pBt, 1, &pPage1, 0)==SQLITE_OK ){
      int nPage = get4byte(28+(u8*)pPage1->aData);
      testcase( nPage==0 );
      if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage);
      testcase( pBt->nPage!=nPage );
      pBt->nPage = nPage;
      btreeSetNPage(pBt, pPage1);
      releasePageOne(pPage1);
    }
    assert( countValidCursors(pBt, 1)==0 );
    pBt->inTransaction = TRANS_READ;
    btreeClearHasContent(pBt);
  }

4680
4681
4682
4683
4684
4685
4686
4687

4688
4689
4690


4691
4692

4693
4694
4695
4696
4697
4698
4699
4917
4918
4919
4920
4921
4922
4923

4924
4925


4926
4927


4928
4929
4930
4931
4932
4933
4934
4935







-
+

-
-
+
+
-
-
+







      rc = sqlite3PagerSavepoint(pBt->pPager, op, iSavepoint);
    }
    if( rc==SQLITE_OK ){
      if( iSavepoint<0 && (pBt->btsFlags & BTS_INITIALLY_EMPTY)!=0 ){
        pBt->nPage = 0;
      }
      rc = newDatabase(pBt);
      pBt->nPage = get4byte(28 + pBt->pPage1->aData);
      btreeSetNPage(pBt, pBt->pPage1);

      /* The database size was written into the offset 28 of the header
      ** when the transaction started, so we know that the value at offset
      /* pBt->nPage might be zero if the database was corrupt when 
      ** the transaction was started. Otherwise, it must be at least 1.  */
      ** 28 is nonzero. */
      assert( pBt->nPage>0 );
      assert( CORRUPT_DB || pBt->nPage>0 );
    }
    sqlite3BtreeLeave(p);
  }
  return rc;
}

/*
4736
4737
4738
4739
4740
4741
4742
4743

4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761



4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772



4773
4774
4775
4776




4777
4778
4779
4780
4781

4782
4783
4784
4785
4786

4787
4788
4789
4790
4791

4792
4793

4794
4795

4796
4797


4798





4799













4800
4801
4802
4803

4804
4805
4806
4807
4808
4809


4810
4811
4812
4813

4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4972
4973
4974
4975
4976
4977
4978

4979
4980
4981
4982
4983
4984
4985
4986
4987
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

5024
5025
5026

5027
5028

5029
5030
5031
5032
5033
5034
5035
5036

5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058

5059
5060
5061
5062
5063


5064
5065

5066


5067

5068

5069
5070
5071
5072
5073
5074
5075







-
+
















-
-
+
+
+








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




-
+




-
+
-



-
+

-
+


+


+
+
-
+
+
+
+
+

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



-
+




-
-
+
+
-

-
-
+
-

-







** will not work correctly.
**
** It is assumed that the sqlite3BtreeCursorZero() has been called
** on pCur to initialize the memory space prior to invoking this routine.
*/
static int btreeCursor(
  Btree *p,                              /* The btree */
  int iTable,                            /* Root page of table to open */
  Pgno iTable,                           /* Root page of table to open */
  int wrFlag,                            /* 1 to write. 0 read-only */
  struct KeyInfo *pKeyInfo,              /* First arg to comparison function */
  BtCursor *pCur                         /* Space for new cursor */
){
  BtShared *pBt = p->pBt;                /* Shared b-tree handle */
  BtCursor *pX;                          /* Looping over other all cursors */

  assert( sqlite3BtreeHoldsMutex(p) );
  assert( wrFlag==0 
       || wrFlag==BTREE_WRCSR 
       || wrFlag==(BTREE_WRCSR|BTREE_FORDELETE) 
  );

  /* The following assert statements verify that if this is a sharable 
  ** b-tree database, the connection is holding the required table locks, 
  ** and that no other connection has any open cursor that conflicts with 
  ** this lock.  */
  assert( hasSharedCacheTableLock(p, iTable, pKeyInfo!=0, (wrFlag?2:1)) );
  ** this lock.  The iTable<1 term disables the check for corrupt schemas. */
  assert( hasSharedCacheTableLock(p, iTable, pKeyInfo!=0, (wrFlag?2:1))
          || iTable<1 );
  assert( wrFlag==0 || !hasReadConflicts(p, iTable) );

  /* Assert that the caller has opened the required transaction. */
  assert( p->inTrans>TRANS_NONE );
  assert( wrFlag==0 || p->inTrans==TRANS_WRITE );
  assert( pBt->pPage1 && pBt->pPage1->aData );
  assert( wrFlag==0 || (pBt->btsFlags & BTS_READ_ONLY)==0 );

  if( wrFlag ){
    allocateTempSpace(pBt);
    if( pBt->pTmpSpace==0 ) return SQLITE_NOMEM_BKPT;
  if( iTable<=1 ){
    if( iTable<1 ){
      return SQLITE_CORRUPT_BKPT;
  }
  if( iTable==1 && btreePagecount(pBt)==0 ){
    assert( wrFlag==0 );
    iTable = 0;
    }else if( btreePagecount(pBt)==0 ){
      assert( wrFlag==0 );
      iTable = 0;
    }
  }

  /* Now that no other errors can occur, finish filling in the BtCursor
  ** variables and link the cursor into the BtShared list.  */
  pCur->pgnoRoot = (Pgno)iTable;
  pCur->pgnoRoot = iTable;
  pCur->iPage = -1;
  pCur->pKeyInfo = pKeyInfo;
  pCur->pBtree = p;
  pCur->pBt = pBt;
  pCur->curFlags = wrFlag ? BTCF_WriteFlag : 0;
  pCur->curFlags = 0;
  pCur->curPagerFlags = wrFlag ? 0 : PAGER_GET_READONLY;
  /* If there are two or more cursors on the same btree, then all such
  ** cursors *must* have the BTCF_Multiple flag set. */
  for(pX=pBt->pCursor; pX; pX=pX->pNext){
    if( pX->pgnoRoot==(Pgno)iTable ){
    if( pX->pgnoRoot==iTable ){
      pX->curFlags |= BTCF_Multiple;
      pCur->curFlags |= BTCF_Multiple;
      pCur->curFlags = BTCF_Multiple;
    }
  }
  pCur->eState = CURSOR_INVALID;
  pCur->pNext = pBt->pCursor;
  pBt->pCursor = pCur;
  if( wrFlag ){
    pCur->curFlags |= BTCF_WriteFlag;
  pCur->eState = CURSOR_INVALID;
    pCur->curPagerFlags = 0;
    if( pBt->pTmpSpace==0 ) return allocateTempSpace(pBt);
  }else{
    pCur->curPagerFlags = PAGER_GET_READONLY;
  }
  return SQLITE_OK;
}
static int btreeCursorWithLock(
  Btree *p,                              /* The btree */
  Pgno iTable,                           /* Root page of table to open */
  int wrFlag,                            /* 1 to write. 0 read-only */
  struct KeyInfo *pKeyInfo,              /* First arg to comparison function */
  BtCursor *pCur                         /* Space for new cursor */
){
  int rc;
  sqlite3BtreeEnter(p);
  rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur);
  sqlite3BtreeLeave(p);
  return rc;
}
int sqlite3BtreeCursor(
  Btree *p,                                   /* The btree */
  int iTable,                                 /* Root page of table to open */
  Pgno iTable,                                /* Root page of table to open */
  int wrFlag,                                 /* 1 to write. 0 read-only */
  struct KeyInfo *pKeyInfo,                   /* First arg to xCompare() */
  BtCursor *pCur                              /* Write new cursor here */
){
  int rc;
  if( iTable<1 ){
  if( p->sharable ){
    return btreeCursorWithLock(p, iTable, wrFlag, pKeyInfo, pCur);
    rc = SQLITE_CORRUPT_BKPT;
  }else{
    sqlite3BtreeEnter(p);
    rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur);
    return btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur);
    sqlite3BtreeLeave(p);
  }
  return rc;
}

/*
** Return the size of a BtCursor object in bytes.
**
** This interfaces is needed so that users of cursors can preallocate
** sufficient storage to hold a cursor.  The BtCursor object is opaque
4862
4863
4864
4865
4866
4867
4868






4869



4870
4871
4872
4873
4874
4875
4876
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126

5127
5128
5129
5130
5131
5132
5133
5134
5135
5136







+
+
+
+
+
+
-
+
+
+







        pPrev = pPrev->pNext;
      }while( ALWAYS(pPrev) );
    }
    btreeReleaseAllCursorPages(pCur);
    unlockBtreeIfUnused(pBt);
    sqlite3_free(pCur->aOverflow);
    sqlite3_free(pCur->pKey);
    if( (pBt->openFlags & BTREE_SINGLE) && pBt->pCursor==0 ){
      /* Since the BtShared is not sharable, there is no need to
      ** worry about the missing sqlite3BtreeLeave() call here.  */
      assert( pBtree->sharable==0 );
      sqlite3BtreeClose(pBtree);
    }else{
    sqlite3BtreeLeave(pBtree);
      sqlite3BtreeLeave(pBtree);
    }
    pCur->pBtree = 0;
  }
  return SQLITE_OK;
}

/*
** Make sure the BtCursor* given in the argument has a valid
** BtCursor.info structure.  If it is not already valid, call
4930
4931
4932
4933
4934
4935
4936












4937
4938
4939
4940
4941
4942
4943
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215







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







i64 sqlite3BtreeIntegerKey(BtCursor *pCur){
  assert( cursorHoldsMutex(pCur) );
  assert( pCur->eState==CURSOR_VALID );
  assert( pCur->curIntKey );
  getCellInfo(pCur);
  return pCur->info.nKey;
}

/*
** Pin or unpin a cursor.
*/
void sqlite3BtreeCursorPin(BtCursor *pCur){
  assert( (pCur->curFlags & BTCF_Pinned)==0 );
  pCur->curFlags |= BTCF_Pinned;
}
void sqlite3BtreeCursorUnpin(BtCursor *pCur){
  assert( (pCur->curFlags & BTCF_Pinned)!=0 );
  pCur->curFlags &= ~BTCF_Pinned;
}

#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
/*
** Return the offset into the database file for the start of the
** payload to which the cursor is pointing.
*/
i64 sqlite3BtreeOffset(BtCursor *pCur){
4960
4961
4962
4963
4964
4965
4966



















4967
4968
4969
4970
4971
4972
4973
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264







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







*/
u32 sqlite3BtreePayloadSize(BtCursor *pCur){
  assert( cursorHoldsMutex(pCur) );
  assert( pCur->eState==CURSOR_VALID );
  getCellInfo(pCur);
  return pCur->info.nPayload;
}

/*
** Return an upper bound on the size of any record for the table
** that the cursor is pointing into.
**
** This is an optimization.  Everything will still work if this
** routine always returns 2147483647 (which is the largest record
** that SQLite can handle) or more.  But returning a smaller value might
** prevent large memory allocations when trying to interpret a
** corrupt datrabase.
**
** The current implementation merely returns the size of the underlying
** database file.
*/
sqlite3_int64 sqlite3BtreeMaxRecordSize(BtCursor *pCur){
  assert( cursorHoldsMutex(pCur) );
  assert( pCur->eState==CURSOR_VALID );
  return pCur->pBt->pageSize * (sqlite3_int64)pCur->pBt->nPage;
}

/*
** Given the page number of an overflow page in the database (parameter
** ovfl), this function finds the page number of the next page in the 
** linked list of overflow pages. If possible, it uses the auto-vacuum
** pointer-map data instead of reading the content of page ovfl to do so. 
**
5117
5118
5119
5120
5121
5122
5123
5124



5125
5126
5127
5128
5129
5130
5131
5408
5409
5410
5411
5412
5413
5414

5415
5416
5417
5418
5419
5420
5421
5422
5423
5424







-
+
+
+







#ifdef SQLITE_DIRECT_OVERFLOW_READ
  unsigned char * const pBufStart = pBuf;     /* Start of original out buffer */
#endif

  assert( pPage );
  assert( eOp==0 || eOp==1 );
  assert( pCur->eState==CURSOR_VALID );
  assert( pCur->ix<pPage->nCell );
  if( pCur->ix>=pPage->nCell ){
    return SQLITE_CORRUPT_PAGE(pPage);
  }
  assert( cursorHoldsMutex(pCur) );

  getCellInfo(pCur);
  aPayload = pCur->info.pPayload;
  assert( offset+amt <= pCur->info.nPayload );

  assert( aPayload > pPage->aData );
5154
5155
5156
5157
5158
5159
5160
5161

5162
5163
5164
5165
5166
5167
5168
5447
5448
5449
5450
5451
5452
5453

5454
5455
5456
5457
5458
5459
5460
5461







-
+









  if( rc==SQLITE_OK && amt>0 ){
    const u32 ovflSize = pBt->usableSize - 4;  /* Bytes content per ovfl page */
    Pgno nextPage;

    nextPage = get4byte(&aPayload[pCur->info.nLocal]);

 
    /* If the BtCursor.aOverflow[] has not been allocated, allocate it now.
    **
    ** The aOverflow[] array is sized at one entry for each overflow page
    ** in the overflow chain. The page number of the first overflow page is
    ** stored in aOverflow[0], etc. A value of 0 in the aOverflow[] array
    ** means "not yet known" (the cache is lazily populated).
    */
5193
5194
5195
5196
5197
5198
5199

5200
5201
5202
5203
5204
5205
5206
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500







+







        offset = (offset%ovflSize);
      }
    }

    assert( rc==SQLITE_OK && amt>0 );
    while( nextPage ){
      /* If required, populate the overflow page-list cache. */
      if( nextPage > pBt->nPage ) return SQLITE_CORRUPT_BKPT;
      assert( pCur->aOverflow[iIdx]==0
              || pCur->aOverflow[iIdx]==nextPage
              || CORRUPT_DB );
      pCur->aOverflow[iIdx] = nextPage;

      if( offset>=ovflSize ){
        /* The only reason to read this page is to obtain the page
5247
5248
5249
5250
5251
5252
5253

5254
5255
5256
5257
5258
5259
5260
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555







+







        ){
          sqlite3_file *fd = sqlite3PagerFile(pBt->pPager);
          u8 aSave[4];
          u8 *aWrite = &pBuf[-4];
          assert( aWrite>=pBufStart );                         /* due to (6) */
          memcpy(aSave, aWrite, 4);
          rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1));
          if( rc && nextPage>pBt->nPage ) rc = SQLITE_CORRUPT_BKPT;
          nextPage = get4byte(aWrite);
          memcpy(aWrite, aSave, 4);
        }else
#endif

        {
          DbPage *pDbPage;
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5597
5598
5599
5600
5601
5602
5603

5604
5605
5606
5607
5608
5609
5610







-







** wrong.  An error is returned if "offset+amt" is larger than
** the available payload.
*/
int sqlite3BtreePayload(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
  assert( cursorHoldsMutex(pCur) );
  assert( pCur->eState==CURSOR_VALID );
  assert( pCur->iPage>=0 && pCur->pPage );
  assert( pCur->ix<pCur->pPage->nCell );
  return accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0);
}

/*
** This variant of sqlite3BtreePayload() works even if the cursor has not
** in the CURSOR_VALID state.  It is only used by the sqlite3_blob_read()
** interface.
5364
5365
5366
5367
5368
5369
5370
5371

5372
5373
5374
5375
5376
5377
5378
5658
5659
5660
5661
5662
5663
5664

5665
5666
5667
5668
5669
5670
5671
5672







-
+







  u32 *pAmt            /* Write the number of available bytes here */
){
  int amt;
  assert( pCur!=0 && pCur->iPage>=0 && pCur->pPage);
  assert( pCur->eState==CURSOR_VALID );
  assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
  assert( cursorOwnsBtShared(pCur) );
  assert( pCur->ix<pCur->pPage->nCell );
  assert( pCur->ix<pCur->pPage->nCell || CORRUPT_DB );
  assert( pCur->info.nSize>0 );
  assert( pCur->info.pPayload>pCur->pPage->aData || CORRUPT_DB );
  assert( pCur->info.pPayload<pCur->pPage->aDataEnd ||CORRUPT_DB);
  amt = pCur->info.nLocal;
  if( amt>(int)(pCur->pPage->aDataEnd - pCur->info.pPayload) ){
    /* There is too little space on the page for the expected amount
    ** of local content. Database must be corrupt. */
5521
5522
5523
5524
5525
5526
5527
5528

5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543

5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554

5555
5556
5557
5558
5559
5560
5561
5815
5816
5817
5818
5819
5820
5821

5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836

5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847

5848
5849
5850
5851
5852
5853
5854
5855







-
+














-
+










-
+








  if( pCur->iPage>=0 ){
    if( pCur->iPage ){
      releasePageNotNull(pCur->pPage);
      while( --pCur->iPage ){
        releasePageNotNull(pCur->apPage[pCur->iPage]);
      }
      pCur->pPage = pCur->apPage[0];
      pRoot = pCur->pPage = pCur->apPage[0];
      goto skip_init;
    }
  }else if( pCur->pgnoRoot==0 ){
    pCur->eState = CURSOR_INVALID;
    return SQLITE_EMPTY;
  }else{
    assert( pCur->iPage==(-1) );
    if( pCur->eState>=CURSOR_REQUIRESEEK ){
      if( pCur->eState==CURSOR_FAULT ){
        assert( pCur->skipNext!=SQLITE_OK );
        return pCur->skipNext;
      }
      sqlite3BtreeClearCursor(pCur);
    }
    rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->pPage,
    rc = getAndInitPage(pCur->pBt, pCur->pgnoRoot, &pCur->pPage,
                        0, pCur->curPagerFlags);
    if( rc!=SQLITE_OK ){
      pCur->eState = CURSOR_INVALID;
      return rc;
    }
    setMempageRoot(pCur->pPage, pCur->pgnoRoot);
    pCur->iPage = 0;
    pCur->curIntKey = pCur->pPage->intKey;
  }
  pRoot = pCur->pPage;
  assert( pRoot->pgno==pCur->pgnoRoot );
  assert( pRoot->pgno==pCur->pgnoRoot || CORRUPT_DB );

  /* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor
  ** expected to open it on an index b-tree. Otherwise, if pKeyInfo is
  ** NULL, the caller expects a table b-tree. If this is not the case,
  ** return an SQLITE_CORRUPT error. 
  **
  ** Earlier versions of SQLite assumed that this test could not fail
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5863
5864
5865
5866
5867
5868
5869

5870
5871
5872
5873
5874
5875
5876







-







  }

skip_init:  
  pCur->ix = 0;
  pCur->info.nSize = 0;
  pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl);

  pRoot = pCur->pPage;
  if( pRoot->nCell>0 ){
    pCur->eState = CURSOR_VALID;
  }else if( !pRoot->leaf ){
    Pgno subpage;
    if( pRoot->pgno!=1 ) return SQLITE_CORRUPT_BKPT;
    subpage = get4byte(&pRoot->aData[pRoot->hdrOffset+8]);
    pCur->eState = CURSOR_VALID;
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686

5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707

5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723



5724




















5725
5726


5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743

5744
5745
5746
5747

5748
5749
5750

5751
5752
5753
5754
5755

5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769


5770
5771
5772
5773
5774

5775
5776
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
5803
5804
5805
5806
5807


5808
5809
5810
5811
5812
5813

5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830




















































































































































































































































5831


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

5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884

5885
5886
5887
5888
5889



5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
















































































5969
5970
5971
5972
5973
5974

5975
5976
5977
5978

5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990

5991
5992
5993
5994
5995
5996
5997
5951
5952
5953
5954
5955
5956
5957

















5958
5959
5960
5961

5962





















5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003


6004
6005




6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017

6018
6019
6020
6021

6022
6023
6024

6025



6026

6027
6028

6029
6030
6031
6032
6033

6034
6035
6036
6037


6038
6039
6040
6041
6042


6043

6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056

6057
6058
6059
6060
6061
6062
6063
6064

6065


6066
6067
6068
6069
6070
6071


6072
6073






6074


6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333

6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348

6349
6350
6351





































6352





6353
6354
6355
6356














































































6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436

6437
6438
6439
6440

6441
6442
6443
6444

6445
6446

6447
6448
6449
6450
6451
6452
6453
6454
6455

6456
6457
6458
6459
6460
6461
6462
6463







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-




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
















+
+
+

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












-
+



-
+


-
+
-
-
-

-
+

-





-




-
-
+
+



-
-
+
-













-
+







-
+
-
-






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















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













-
+


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

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




-
+



-
+

-









-
+







    assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 );
    *pRes = 1;
    rc = SQLITE_OK;
  }
  return rc;
}

/*
** This function is a no-op if cursor pCur does not point to a valid row.
** Otherwise, if pCur is valid, configure it so that the next call to
** sqlite3BtreeNext() is a no-op.
*/
#ifndef SQLITE_OMIT_WINDOWFUNC
void sqlite3BtreeSkipNext(BtCursor *pCur){
  /* We believe that the cursor must always be in the valid state when
  ** this routine is called, but the proof is difficult, so we add an
  ** ALWaYS() test just in case we are wrong. */
  if( ALWAYS(pCur->eState==CURSOR_VALID) ){
    pCur->eState = CURSOR_SKIPNEXT;
    pCur->skipNext = 1;
  }
}
#endif /* SQLITE_OMIT_WINDOWFUNC */

/* Move the cursor to the last entry in the table.  Return SQLITE_OK
** on success.  Set *pRes to 0 if the cursor actually points to something
** or set *pRes to 1 if the table is empty.
*/
int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
static SQLITE_NOINLINE int btreeLast(BtCursor *pCur, int *pRes){
  int rc;
 
  assert( cursorOwnsBtShared(pCur) );
  assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );

  /* If the cursor already points to the last entry, this is a no-op. */
  if( CURSOR_VALID==pCur->eState && (pCur->curFlags & BTCF_AtLast)!=0 ){
#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->pPage->leaf );
#endif
    return SQLITE_OK;
  }

  rc = moveToRoot(pCur);
  int rc = moveToRoot(pCur);
  if( rc==SQLITE_OK ){
    assert( pCur->eState==CURSOR_VALID );
    *pRes = 0;
    rc = moveToRightmost(pCur);
    if( rc==SQLITE_OK ){
      pCur->curFlags |= BTCF_AtLast;
    }else{
      pCur->curFlags &= ~BTCF_AtLast;
    }
  }else if( rc==SQLITE_EMPTY ){
    assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 );
    *pRes = 1;
    rc = SQLITE_OK;
  }
  return rc;
}
int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
  assert( cursorOwnsBtShared(pCur) );
  assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );

  /* If the cursor already points to the last entry, this is a no-op. */
  if( CURSOR_VALID==pCur->eState && (pCur->curFlags & BTCF_AtLast)!=0 ){
#ifdef SQLITE_DEBUG
    /* This block serves to assert() that the cursor really does point 
    ** to the last entry in the b-tree. */
    int ii;
    for(ii=0; ii<pCur->iPage; ii++){
      assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell );
    }
    assert( pCur->ix==pCur->pPage->nCell-1 || CORRUPT_DB );
    testcase( pCur->ix!=pCur->pPage->nCell-1 );
    /* ^-- dbsqlfuzz b92b72e4de80b5140c30ab71372ca719b8feb618 */
    assert( pCur->pPage->leaf );
#endif
    *pRes = 0;
    return SQLITE_OK;
  }
  return btreeLast(pCur, pRes);
}

/* Move the cursor so that it points to an entry near the key 
** specified by pIdxKey or intKey.   Return a success code.
/* Move the cursor so that it points to an entry in a table (a.k.a INTKEY)
** table near the key intKey.   Return a success code.
**
** For INTKEY tables, the intKey parameter is used.  pIdxKey 
** must be NULL.  For index tables, pIdxKey is used and intKey
** is ignored.
**
** If an exact match is not found, then the cursor is always
** left pointing at a leaf page which would hold the entry if it
** were present.  The cursor might point to an entry that comes
** before or after the key.
**
** An integer is written into *pRes which is the result of
** comparing the key with the entry to which the cursor is 
** pointing.  The meaning of the integer written into
** *pRes is as follows:
**
**     *pRes<0      The cursor is left pointing at an entry that
**                  is smaller than intKey/pIdxKey or if the table is empty
**                  is smaller than intKey or if the table is empty
**                  and the cursor is therefore left point to nothing.
**
**     *pRes==0     The cursor is left pointing at an entry that
**                  exactly matches intKey/pIdxKey.
**                  exactly matches intKey.
**
**     *pRes>0      The cursor is left pointing at an entry that
**                  is larger than intKey/pIdxKey.
**                  is larger than intKey.
**
** For index tables, the pIdxKey->eqSeen field is set to 1 if there
** exists an entry in the table that exactly matches pIdxKey.  
*/
int sqlite3BtreeMovetoUnpacked(
int sqlite3BtreeTableMoveto(
  BtCursor *pCur,          /* The cursor to be moved */
  UnpackedRecord *pIdxKey, /* Unpacked index key */
  i64 intKey,              /* The table key */
  int biasRight,           /* If true, bias the search to the high end */
  int *pRes                /* Write search results here */
){
  int rc;
  RecordCompare xRecordCompare;

  assert( cursorOwnsBtShared(pCur) );
  assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
  assert( pRes );
  assert( (pIdxKey==0)==(pCur->pKeyInfo==0) );
  assert( pCur->eState!=CURSOR_VALID || (pIdxKey==0)==(pCur->curIntKey!=0) );
  assert( pCur->pKeyInfo==0 );
  assert( pCur->eState!=CURSOR_VALID || pCur->curIntKey!=0 );

  /* If the cursor is already positioned at the point we are trying
  ** to move to, then just return without doing any work */
  if( pIdxKey==0
   && pCur->eState==CURSOR_VALID && (pCur->curFlags & BTCF_ValidNKey)!=0
  if( pCur->eState==CURSOR_VALID && (pCur->curFlags & BTCF_ValidNKey)!=0 ){
  ){
    if( pCur->info.nKey==intKey ){
      *pRes = 0;
      return SQLITE_OK;
    }
    if( pCur->info.nKey<intKey ){
      if( (pCur->curFlags & BTCF_AtLast)!=0 ){
        *pRes = -1;
        return SQLITE_OK;
      }
      /* If the requested key is one more than the previous key, then
      ** try to get there using sqlite3BtreeNext() rather than a full
      ** binary search.  This is an optimization only.  The correct answer
      ** is still obtained without this case, only a little more slowely */
      if( pCur->info.nKey+1==intKey && !pCur->skipNext ){
      if( pCur->info.nKey+1==intKey ){
        *pRes = 0;
        rc = sqlite3BtreeNext(pCur, 0);
        if( rc==SQLITE_OK ){
          getCellInfo(pCur);
          if( pCur->info.nKey==intKey ){
            return SQLITE_OK;
          }
        }else if( rc==SQLITE_DONE ){
        }else if( rc!=SQLITE_DONE ){
          rc = SQLITE_OK;
        }else{
          return rc;
        }
      }
    }
  }

  if( pIdxKey ){
    xRecordCompare = sqlite3VdbeFindCompare(pIdxKey);
#ifdef SQLITE_DEBUG
  pCur->pBtree->nSeek++;   /* Performance measurement during testing */
    pIdxKey->errCode = 0;
    assert( pIdxKey->default_rc==1 
         || pIdxKey->default_rc==0 
         || pIdxKey->default_rc==-1
    );
  }else{
#endif
    xRecordCompare = 0; /* All keys are integers */
  }

  rc = moveToRoot(pCur);
  if( rc ){
    if( rc==SQLITE_EMPTY ){
      assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 );
      *pRes = -1;
      return SQLITE_OK;
    }
    return rc;
  }
  assert( pCur->pPage );
  assert( pCur->pPage->isInit );
  assert( pCur->eState==CURSOR_VALID );
  assert( pCur->pPage->nCell > 0 );
  assert( pCur->iPage==0 || pCur->apPage[0]->intKey==pCur->curIntKey );
  assert( pCur->curIntKey );

  for(;;){
    int lwr, upr, idx, c;
    Pgno chldPg;
    MemPage *pPage = pCur->pPage;
    u8 *pCell;                          /* Pointer to current cell in pPage */

    /* pPage->nCell must be greater than zero. If this is the root-page
    ** the cursor would have been INVALID above and this for(;;) loop
    ** not run. If this is not the root-page, then the moveToChild() routine
    ** would have already detected db corruption. Similarly, pPage must
    ** be the right kind (index or table) of b-tree page. Otherwise
    ** a moveToChild() or moveToRoot() call would have detected corruption.  */
    assert( pPage->nCell>0 );
    assert( pPage->intKey );
    lwr = 0;
    upr = pPage->nCell-1;
    assert( biasRight==0 || biasRight==1 );
    idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */
    for(;;){
      i64 nCellKey;
      pCell = findCellPastPtr(pPage, idx);
      if( pPage->intKeyLeaf ){
        while( 0x80 <= *(pCell++) ){
          if( pCell>=pPage->aDataEnd ){
            return SQLITE_CORRUPT_PAGE(pPage);
          }
        }
      }
      getVarint(pCell, (u64*)&nCellKey);
      if( nCellKey<intKey ){
        lwr = idx+1;
        if( lwr>upr ){ c = -1; break; }
      }else if( nCellKey>intKey ){
        upr = idx-1;
        if( lwr>upr ){ c = +1; break; }
      }else{
        assert( nCellKey==intKey );
        pCur->ix = (u16)idx;
        if( !pPage->leaf ){
          lwr = idx;
          goto moveto_table_next_layer;
        }else{
          pCur->curFlags |= BTCF_ValidNKey;
          pCur->info.nKey = nCellKey;
          pCur->info.nSize = 0;
          *pRes = 0;
          return SQLITE_OK;
        }
      }
      assert( lwr+upr>=0 );
      idx = (lwr+upr)>>1;  /* idx = (lwr+upr)/2; */
    }
    assert( lwr==upr+1 || !pPage->leaf );
    assert( pPage->isInit );
    if( pPage->leaf ){
      assert( pCur->ix<pCur->pPage->nCell );
      pCur->ix = (u16)idx;
      *pRes = c;
      rc = SQLITE_OK;
      goto moveto_table_finish;
    }
moveto_table_next_layer:
    if( lwr>=pPage->nCell ){
      chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]);
    }else{
      chldPg = get4byte(findCell(pPage, lwr));
    }
    pCur->ix = (u16)lwr;
    rc = moveToChild(pCur, chldPg);
    if( rc ) break;
  }
moveto_table_finish:
  pCur->info.nSize = 0;
  assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
  return rc;
}

/*
** Compare the "idx"-th cell on the page the cursor pCur is currently
** pointing to to pIdxKey using xRecordCompare.  Return negative or
** zero if the cell is less than or equal pIdxKey.  Return positive
** if unknown.
**
**    Return value negative:     Cell at pCur[idx] less than pIdxKey
**
**    Return value is zero:      Cell at pCur[idx] equals pIdxKey
**
**    Return value positive:     Nothing is known about the relationship
**                               of the cell at pCur[idx] and pIdxKey.
**
** This routine is part of an optimization.  It is always safe to return
** a positive value as that will cause the optimization to be skipped.
*/
static int indexCellCompare(
  BtCursor *pCur,
  int idx,
  UnpackedRecord *pIdxKey,
  RecordCompare xRecordCompare
){
  MemPage *pPage = pCur->pPage;
  int c;
  int nCell;  /* Size of the pCell cell in bytes */
  u8 *pCell = findCellPastPtr(pPage, idx);

  nCell = pCell[0];
  if( nCell<=pPage->max1bytePayload ){
    /* This branch runs if the record-size field of the cell is a
    ** single byte varint and the record fits entirely on the main
    ** b-tree page.  */
    testcase( pCell+nCell+1==pPage->aDataEnd );
    c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
  }else if( !(pCell[1] & 0x80) 
    && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
  ){
    /* The record-size field is a 2 byte varint and the record 
    ** fits entirely on the main b-tree page.  */
    testcase( pCell+nCell+2==pPage->aDataEnd );
    c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
  }else{
    /* If the record extends into overflow pages, do not attempt
    ** the optimization. */
    c = 99;
  }
  return c;
}

/*
** Return true (non-zero) if pCur is current pointing to the last
** page of a table.
*/
static int cursorOnLastPage(BtCursor *pCur){
  int i;
  assert( pCur->eState==CURSOR_VALID );
  for(i=0; i<pCur->iPage; i++){
    MemPage *pPage = pCur->apPage[i];
    if( pCur->aiIdx[i]<pPage->nCell ) return 0;
  }
  return 1;
}

/* Move the cursor so that it points to an entry in an index table
** near the key pIdxKey.   Return a success code.
**
** If an exact match is not found, then the cursor is always
** left pointing at a leaf page which would hold the entry if it
** were present.  The cursor might point to an entry that comes
** before or after the key.
**
** An integer is written into *pRes which is the result of
** comparing the key with the entry to which the cursor is 
** pointing.  The meaning of the integer written into
** *pRes is as follows:
**
**     *pRes<0      The cursor is left pointing at an entry that
**                  is smaller than pIdxKey or if the table is empty
**                  and the cursor is therefore left point to nothing.
**
**     *pRes==0     The cursor is left pointing at an entry that
**                  exactly matches pIdxKey.
**
**     *pRes>0      The cursor is left pointing at an entry that
**                  is larger than pIdxKey.
**
** The pIdxKey->eqSeen field is set to 1 if there
** exists an entry in the table that exactly matches pIdxKey.  
*/
int sqlite3BtreeIndexMoveto(
  BtCursor *pCur,          /* The cursor to be moved */
  UnpackedRecord *pIdxKey, /* Unpacked index key */
  int *pRes                /* Write search results here */
){
  int rc;
  RecordCompare xRecordCompare;

  assert( cursorOwnsBtShared(pCur) );
  assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
  assert( pRes );
  assert( pCur->pKeyInfo!=0 );

#ifdef SQLITE_DEBUG
  pCur->pBtree->nSeek++;   /* Performance measurement during testing */
#endif

  xRecordCompare = sqlite3VdbeFindCompare(pIdxKey);
  pIdxKey->errCode = 0;
  assert( pIdxKey->default_rc==1 
       || pIdxKey->default_rc==0 
       || pIdxKey->default_rc==-1
  );


  /* Check to see if we can skip a lot of work.  Two cases:
  **
  **    (1) If the cursor is already pointing to the very last cell
  **        in the table and the pIdxKey search key is greater than or
  **        equal to that last cell, then no movement is required.
  **
  **    (2) If the cursor is on the last page of the table and the first
  **        cell on that last page is less than or equal to the pIdxKey
  **        search key, then we can start the search on the current page
  **        without needing to go back to root.
  */
  if( pCur->eState==CURSOR_VALID
   && pCur->pPage->leaf
   && cursorOnLastPage(pCur)
  ){
    int c;
    if( pCur->ix==pCur->pPage->nCell-1
     && (c = indexCellCompare(pCur, pCur->ix, pIdxKey, xRecordCompare))<=0
     && pIdxKey->errCode==SQLITE_OK
    ){
      *pRes = c;
      return SQLITE_OK;  /* Cursor already pointing at the correct spot */
    }
    if( pCur->iPage>0 
     && indexCellCompare(pCur, 0, pIdxKey, xRecordCompare)<=0
     && pIdxKey->errCode==SQLITE_OK
    ){
      pCur->curFlags &= ~BTCF_ValidOvfl;
      if( !pCur->pPage->isInit ){
        return SQLITE_CORRUPT_BKPT;
      }
      goto bypass_moveto_root;  /* Start search on the current page */
    }
    pIdxKey->errCode = SQLITE_OK;
  }

  rc = moveToRoot(pCur);
  if( rc ){
    if( rc==SQLITE_EMPTY ){
      assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 );
      *pRes = -1;
      return SQLITE_OK;
    }
    return rc;
  }

bypass_moveto_root:
  assert( pCur->pPage );
  assert( pCur->pPage->isInit );
  assert( pCur->eState==CURSOR_VALID );
  assert( pCur->pPage->nCell > 0 );
  assert( pCur->curIntKey || pIdxKey );
  assert( pCur->curIntKey==0 );
  assert( pIdxKey!=0 );
  for(;;){
    int lwr, upr, idx, c;
    Pgno chldPg;
    MemPage *pPage = pCur->pPage;
    u8 *pCell;                          /* Pointer to current cell in pPage */

    /* pPage->nCell must be greater than zero. If this is the root-page
    ** the cursor would have been INVALID above and this for(;;) loop
    ** not run. If this is not the root-page, then the moveToChild() routine
    ** would have already detected db corruption. Similarly, pPage must
    ** be the right kind (index or table) of b-tree page. Otherwise
    ** a moveToChild() or moveToRoot() call would have detected corruption.  */
    assert( pPage->nCell>0 );
    assert( pPage->intKey==(pIdxKey==0) );
    assert( pPage->intKey==0 );
    lwr = 0;
    upr = pPage->nCell-1;
    assert( biasRight==0 || biasRight==1 );
    idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */
    pCur->ix = (u16)idx;
    if( xRecordCompare==0 ){
      for(;;){
        i64 nCellKey;
        pCell = findCellPastPtr(pPage, idx);
        if( pPage->intKeyLeaf ){
          while( 0x80 <= *(pCell++) ){
            if( pCell>=pPage->aDataEnd ){
              return SQLITE_CORRUPT_PAGE(pPage);
            }
          }
        }
        getVarint(pCell, (u64*)&nCellKey);
        if( nCellKey<intKey ){
          lwr = idx+1;
          if( lwr>upr ){ c = -1; break; }
        }else if( nCellKey>intKey ){
          upr = idx-1;
          if( lwr>upr ){ c = +1; break; }
        }else{
          assert( nCellKey==intKey );
          pCur->ix = (u16)idx;
          if( !pPage->leaf ){
            lwr = idx;
            goto moveto_next_layer;
          }else{
            pCur->curFlags |= BTCF_ValidNKey;
            pCur->info.nKey = nCellKey;
            pCur->info.nSize = 0;
            *pRes = 0;
            return SQLITE_OK;
          }
        }
        assert( lwr+upr>=0 );
        idx = (lwr+upr)>>1;  /* idx = (lwr+upr)/2; */
    idx = upr>>1; /* idx = (lwr+upr)/2; */
      }
    }else{
      for(;;){
        int nCell;  /* Size of the pCell cell in bytes */
        pCell = findCellPastPtr(pPage, idx);
    for(;;){
      int nCell;  /* Size of the pCell cell in bytes */
      pCell = findCellPastPtr(pPage, idx);

        /* The maximum supported page-size is 65536 bytes. This means that
        ** the maximum number of record bytes stored on an index B-Tree
        ** page is less than 16384 bytes and may be stored as a 2-byte
        ** varint. This information is used to attempt to avoid parsing 
        ** the entire cell by checking for the cases where the record is 
        ** stored entirely within the b-tree page by inspecting the first 
        ** 2 bytes of the cell.
        */
        nCell = pCell[0];
        if( nCell<=pPage->max1bytePayload ){
          /* This branch runs if the record-size field of the cell is a
          ** single byte varint and the record fits entirely on the main
          ** b-tree page.  */
          testcase( pCell+nCell+1==pPage->aDataEnd );
          c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
        }else if( !(pCell[1] & 0x80) 
          && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
        ){
          /* The record-size field is a 2 byte varint and the record 
          ** fits entirely on the main b-tree page.  */
          testcase( pCell+nCell+2==pPage->aDataEnd );
          c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
        }else{
          /* The record flows over onto one or more overflow pages. In
          ** this case the whole cell needs to be parsed, a buffer allocated
          ** and accessPayload() used to retrieve the record into the
          ** buffer before VdbeRecordCompare() can be called. 
          **
          ** If the record is corrupt, the xRecordCompare routine may read
          ** up to two varints past the end of the buffer. An extra 18 
          ** bytes of padding is allocated at the end of the buffer in
          ** case this happens.  */
          void *pCellKey;
          u8 * const pCellBody = pCell - pPage->childPtrSize;
          pPage->xParseCell(pPage, pCellBody, &pCur->info);
          nCell = (int)pCur->info.nKey;
          testcase( nCell<0 );   /* True if key size is 2^32 or more */
          testcase( nCell==0 );  /* Invalid key size:  0x80 0x80 0x00 */
          testcase( nCell==1 );  /* Invalid key size:  0x80 0x80 0x01 */
          testcase( nCell==2 );  /* Minimum legal index key size */
          if( nCell<2 ){
            rc = SQLITE_CORRUPT_PAGE(pPage);
            goto moveto_finish;
          }
          pCellKey = sqlite3Malloc( nCell+18 );
          if( pCellKey==0 ){
            rc = SQLITE_NOMEM_BKPT;
            goto moveto_finish;
          }
          pCur->ix = (u16)idx;
          rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
          pCur->curFlags &= ~BTCF_ValidOvfl;
          if( rc ){
            sqlite3_free(pCellKey);
            goto moveto_finish;
          }
          c = xRecordCompare(nCell, pCellKey, pIdxKey);
          sqlite3_free(pCellKey);
        }
        assert( 
            (pIdxKey->errCode!=SQLITE_CORRUPT || c==0)
         && (pIdxKey->errCode!=SQLITE_NOMEM || pCur->pBtree->db->mallocFailed)
        );
        if( c<0 ){
          lwr = idx+1;
        }else if( c>0 ){
          upr = idx-1;
        }else{
          assert( c==0 );
          *pRes = 0;
          rc = SQLITE_OK;
          pCur->ix = (u16)idx;
          if( pIdxKey->errCode ) rc = SQLITE_CORRUPT_BKPT;
          goto moveto_finish;
        }
        if( lwr>upr ) break;
        assert( lwr+upr>=0 );
        idx = (lwr+upr)>>1;  /* idx = (lwr+upr)/2 */
      /* The maximum supported page-size is 65536 bytes. This means that
      ** the maximum number of record bytes stored on an index B-Tree
      ** page is less than 16384 bytes and may be stored as a 2-byte
      ** varint. This information is used to attempt to avoid parsing 
      ** the entire cell by checking for the cases where the record is 
      ** stored entirely within the b-tree page by inspecting the first 
      ** 2 bytes of the cell.
      */
      nCell = pCell[0];
      if( nCell<=pPage->max1bytePayload ){
        /* This branch runs if the record-size field of the cell is a
        ** single byte varint and the record fits entirely on the main
        ** b-tree page.  */
        testcase( pCell+nCell+1==pPage->aDataEnd );
        c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
      }else if( !(pCell[1] & 0x80) 
        && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
      ){
        /* The record-size field is a 2 byte varint and the record 
        ** fits entirely on the main b-tree page.  */
        testcase( pCell+nCell+2==pPage->aDataEnd );
        c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
      }else{
        /* The record flows over onto one or more overflow pages. In
        ** this case the whole cell needs to be parsed, a buffer allocated
        ** and accessPayload() used to retrieve the record into the
        ** buffer before VdbeRecordCompare() can be called. 
        **
        ** If the record is corrupt, the xRecordCompare routine may read
        ** up to two varints past the end of the buffer. An extra 18 
        ** bytes of padding is allocated at the end of the buffer in
        ** case this happens.  */
        void *pCellKey;
        u8 * const pCellBody = pCell - pPage->childPtrSize;
        const int nOverrun = 18;  /* Size of the overrun padding */
        pPage->xParseCell(pPage, pCellBody, &pCur->info);
        nCell = (int)pCur->info.nKey;
        testcase( nCell<0 );   /* True if key size is 2^32 or more */
        testcase( nCell==0 );  /* Invalid key size:  0x80 0x80 0x00 */
        testcase( nCell==1 );  /* Invalid key size:  0x80 0x80 0x01 */
        testcase( nCell==2 );  /* Minimum legal index key size */
        if( nCell<2 || nCell/pCur->pBt->usableSize>pCur->pBt->nPage ){
          rc = SQLITE_CORRUPT_PAGE(pPage);
          goto moveto_index_finish;
        }
        pCellKey = sqlite3Malloc( nCell+nOverrun );
        if( pCellKey==0 ){
          rc = SQLITE_NOMEM_BKPT;
          goto moveto_index_finish;
        }
        pCur->ix = (u16)idx;
        rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
        memset(((u8*)pCellKey)+nCell,0,nOverrun); /* Fix uninit warnings */
        pCur->curFlags &= ~BTCF_ValidOvfl;
        if( rc ){
          sqlite3_free(pCellKey);
          goto moveto_index_finish;
        }
        c = sqlite3VdbeRecordCompare(nCell, pCellKey, pIdxKey);
        sqlite3_free(pCellKey);
      }
      assert( 
          (pIdxKey->errCode!=SQLITE_CORRUPT || c==0)
       && (pIdxKey->errCode!=SQLITE_NOMEM || pCur->pBtree->db->mallocFailed)
      );
      if( c<0 ){
        lwr = idx+1;
      }else if( c>0 ){
        upr = idx-1;
      }else{
        assert( c==0 );
        *pRes = 0;
        rc = SQLITE_OK;
        pCur->ix = (u16)idx;
        if( pIdxKey->errCode ) rc = SQLITE_CORRUPT_BKPT;
        goto moveto_index_finish;
      }
      if( lwr>upr ) break;
      assert( lwr+upr>=0 );
      idx = (lwr+upr)>>1;  /* idx = (lwr+upr)/2 */
      }
    }
    assert( lwr==upr+1 || (pPage->intKey && !pPage->leaf) );
    assert( pPage->isInit );
    if( pPage->leaf ){
      assert( pCur->ix<pCur->pPage->nCell );
      assert( pCur->ix<pCur->pPage->nCell || CORRUPT_DB );
      pCur->ix = (u16)idx;
      *pRes = c;
      rc = SQLITE_OK;
      goto moveto_finish;
      goto moveto_index_finish;
    }
moveto_next_layer:
    if( lwr>=pPage->nCell ){
      chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]);
    }else{
      chldPg = get4byte(findCell(pPage, lwr));
    }
    pCur->ix = (u16)lwr;
    rc = moveToChild(pCur, chldPg);
    if( rc ) break;
  }
moveto_finish:
moveto_index_finish:
  pCur->info.nSize = 0;
  assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
  return rc;
}


/*
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074

6075
6076

6077
6078
6079
6080
6081
6082
6083
6084
6085
6086

6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
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







-









-
-
+

-
+
-
-
-
-





-
+
-
-
-
-
-
-
-



-
-
-
-
-
-
-







*/
static SQLITE_NOINLINE int btreeNext(BtCursor *pCur){
  int rc;
  int idx;
  MemPage *pPage;

  assert( cursorOwnsBtShared(pCur) );
  assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
  if( pCur->eState!=CURSOR_VALID ){
    assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
    rc = restoreCursorPosition(pCur);
    if( rc!=SQLITE_OK ){
      return rc;
    }
    if( CURSOR_INVALID==pCur->eState ){
      return SQLITE_DONE;
    }
    if( pCur->skipNext ){
      assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT );
    if( pCur->eState==CURSOR_SKIPNEXT ){
      pCur->eState = CURSOR_VALID;
      if( pCur->skipNext>0 ){
      if( pCur->skipNext>0 ) return SQLITE_OK;
        pCur->skipNext = 0;
        return SQLITE_OK;
      }
      pCur->skipNext = 0;
    }
  }

  pPage = pCur->pPage;
  idx = ++pCur->ix;
  if( !pPage->isInit ){
  if( NEVER(!pPage->isInit) || sqlite3FaultSim(412) ){
    /* The only known way for this to happen is for there to be a
    ** recursive SQL function that does a DELETE operation as part of a
    ** SELECT which deletes content out from under an active cursor
    ** in a corrupt database file where the table being DELETE-ed from
    ** has pages in common with the table being queried.  See TH3
    ** module cov1/btree78.test testcase 220 (2018-06-08) for an
    ** example. */
    return SQLITE_CORRUPT_BKPT;
  }

  /* If the database file is corrupt, it is possible for the value of idx 
  ** to be invalid here. This can only occur if a second cursor modifies
  ** the page while cursor pCur is holding a reference to it. Which can
  ** only happen if the database is corrupt in such a way as to link the
  ** page into more than one b-tree structure. */
  testcase( idx>pPage->nCell );

  if( idx>=pPage->nCell ){
    if( !pPage->leaf ){
      rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8]));
      if( rc ) return rc;
      return moveToLeftmost(pCur);
    }
    do{
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6574
6575
6576
6577
6578
6579
6580

6581
6582
6583
6584
6585
6586
6587







-







  }
}
int sqlite3BtreeNext(BtCursor *pCur, int flags){
  MemPage *pPage;
  UNUSED_PARAMETER( flags );  /* Used in COMDB2 but not native SQLite */
  assert( cursorOwnsBtShared(pCur) );
  assert( flags==0 || flags==1 );
  assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
  pCur->info.nSize = 0;
  pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
  if( pCur->eState!=CURSOR_VALID ) return btreeNext(pCur);
  pPage = pCur->pPage;
  if( (++pCur->ix)>=pPage->nCell ){
    pCur->ix--;
    return btreeNext(pCur);
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188

6189
6190

6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6614
6615
6616
6617
6618
6619
6620

6621
6622
6623
6624
6625
6626
6627
6628
6629
6630


6631
6632

6633




6634
6635
6636
6637
6638
6639
6640







-










-
-
+

-
+
-
-
-
-







** use this hint, but COMDB2 does.
*/
static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur){
  int rc;
  MemPage *pPage;

  assert( cursorOwnsBtShared(pCur) );
  assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
  assert( (pCur->curFlags & (BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey))==0 );
  assert( pCur->info.nSize==0 );
  if( pCur->eState!=CURSOR_VALID ){
    rc = restoreCursorPosition(pCur);
    if( rc!=SQLITE_OK ){
      return rc;
    }
    if( CURSOR_INVALID==pCur->eState ){
      return SQLITE_DONE;
    }
    if( pCur->skipNext ){
      assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT );
    if( CURSOR_SKIPNEXT==pCur->eState ){
      pCur->eState = CURSOR_VALID;
      if( pCur->skipNext<0 ){
      if( pCur->skipNext<0 ) return SQLITE_OK;
        pCur->skipNext = 0;
        return SQLITE_OK;
      }
      pCur->skipNext = 0;
    }
  }

  pPage = pCur->pPage;
  assert( pPage->isInit );
  if( !pPage->leaf ){
    int idx = pCur->ix;
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6661
6662
6663
6664
6665
6666
6667

6668
6669
6670
6671
6672
6673
6674







-







    }
  }
  return rc;
}
int sqlite3BtreePrevious(BtCursor *pCur, int flags){
  assert( cursorOwnsBtShared(pCur) );
  assert( flags==0 || flags==1 );
  assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
  UNUSED_PARAMETER( flags );  /* Used in COMDB2 but not native SQLite */
  pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey);
  pCur->info.nSize = 0;
  if( pCur->eState!=CURSOR_VALID
   || pCur->ix==0
   || pCur->pPage->leaf==0
  ){
6277
6278
6279
6280
6281
6282
6283
6284
6285


6286
6287
6288
6289
6290
6291
6292
6715
6716
6717
6718
6719
6720
6721


6722
6723
6724
6725
6726
6727
6728
6729
6730







-
-
+
+







  MemPage *pPrevTrunk = 0;
  Pgno mxPage;     /* Total size of the database file */

  assert( sqlite3_mutex_held(pBt->mutex) );
  assert( eMode==BTALLOC_ANY || (nearby>0 && REQUIRE_PTRMAP ) );
  pPage1 = pBt->pPage1;
  mxPage = btreePagecount(pBt);
  /* EVIDENCE-OF: R-05119-02637 The 4-byte big-endian integer at offset 36
  ** stores stores the total number of pages on the freelist. */
  /* EVIDENCE-OF: R-21003-45125 The 4-byte big-endian integer at offset 36
  ** stores the total number of pages on the freelist. */
  n = get4byte(&pPage1->aData[36]);
  testcase( n==mxPage-1 );
  if( n>=mxPage ){
    return SQLITE_CORRUPT_BKPT;
  }

  /* Ensure page 1 is writable. This function will either change the number
6304
6305
6306
6307
6308
6309
6310
6311
6312


6313
6314
6315
6316
6317
6318
6319
6742
6743
6744
6745
6746
6747
6748


6749
6750
6751
6752
6753
6754
6755
6756
6757







-
-
+
+







    u32 nSearch = 0;   /* Count of the number of search attempts */
    
    /* If eMode==BTALLOC_EXACT and a query of the pointer-map
    ** shows that the page 'nearby' is somewhere on the free-list, then
    ** the entire-list will be searched for that page.
    */
    if( eMode==BTALLOC_EXACT ){
      assert( ISAUTOVACUUM!=ISCONCURRENT );
      if( ISAUTOVACUUM ){
      assert( ISAUTOVACUUM(pBt)!=ISCONCURRENT );
      if( ISAUTOVACUUM(pBt) ){
        if( nearby<=mxPage ){
          u8 eType;
          assert( nearby>0 );
          assert( pBt->autoVacuum );
          rc = ptrmapGet(pBt, nearby, &eType, 0);
          if( rc ) return rc;
          if( eType==PTRMAP_FREEPAGE ){
6475
6476
6477
6478
6479
6480
6481
6482

6483
6484
6485
6486
6487
6488
6489
6913
6914
6915
6916
6917
6918
6919

6920
6921
6922
6923
6924
6925
6926
6927







-
+







          }
        }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)) 
        ){
6568
6569
6570
6571
6572
6573
6574
6575

6576
6577
6578
6579
6580
6581
6582
7006
7007
7008
7009
7010
7011
7012

7013
7014
7015
7016
7017
7018
7019
7020







-
+







    if( rc!=SQLITE_OK ){
      releasePage(*ppPage);
      *ppPage = 0;
    }
    TRACE(("ALLOCATE: %d from end of file\n", *pPgno));
  }

  assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
  assert( CORRUPT_DB || *pPgno!=PENDING_BYTE_PAGE(pBt) );

end_allocate_page:
  releasePage(pTrunk);
  releasePage(pPrevTrunk);
  assert( rc!=SQLITE_OK || sqlite3PagerPageRefcount((*ppPage)->pDbPage)<=1 );
  assert( rc!=SQLITE_OK || (*ppPage)->isInit==0 );
  return rc;
6596
6597
6598
6599
6600
6601
6602
6603

6604
6605
6606
6607
6608

6609


6610
6611
6612
6613
6614
6615
6616
7034
7035
7036
7037
7038
7039
7040

7041
7042
7043
7044
7045
7046
7047

7048
7049
7050
7051
7052
7053
7054
7055
7056







-
+





+
-
+
+







*/
static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
  MemPage *pTrunk = 0;                /* Free-list trunk page */
  Pgno iTrunk = 0;                    /* Page number of free-list trunk page */ 
  MemPage *pPage1 = pBt->pPage1;      /* Local reference to page 1 */
  MemPage *pPage;                     /* Page being freed. May be NULL. */
  int rc;                             /* Return Code */
  int nFree;                          /* Initial number of pages on free-list */
  u32 nFree;                          /* Initial number of pages on free-list */

  assert( sqlite3_mutex_held(pBt->mutex) );
  assert( CORRUPT_DB || iPage>1 );
  assert( !pMemPage || pMemPage->pgno==iPage );

  if( iPage<2 || iPage>pBt->nPage ){
  if( iPage<2 ) return SQLITE_CORRUPT_BKPT;
    return SQLITE_CORRUPT_BKPT;
  }
  if( pMemPage ){
    pPage = pMemPage;
    sqlite3PagerRef(pPage->pDbPage);
  }else{
    pPage = btreePageLookup(pBt, iPage);
  }

6647
6648
6649
6650
6651
6652
6653




6654
6655
6656
6657
6658
6659
6660
7087
7088
7089
7090
7091
7092
7093
7094
7095
7096
7097
7098
7099
7100
7101
7102
7103
7104







+
+
+
+







  ** first trunk page in the current free-list. This block tests if it
  ** is possible to add the page as a new free-list leaf.
  */
  if( nFree!=0 ){
    u32 nLeaf;                /* Initial number of leaf cells on trunk page */

    iTrunk = get4byte(&pPage1->aData[32]);
    if( iTrunk>btreePagecount(pBt) ){
      rc = SQLITE_CORRUPT_BKPT;
      goto freepage_out;
    }
    rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0);
    if( rc!=SQLITE_OK ){
      goto freepage_out;
    }

    nLeaf = get4byte(&pTrunk->aData[4]);
    assert( pBt->usableSize>32 );
6725
6726
6727
6728
6729
6730
6731
6732

6733
6734
6735

6736
6737
6738
6739
6740
6741
6742
6743
6744
6745
6746
6747
6748

6749
6750
6751
6752
6753
6754
6755
6756
6757
7169
7170
7171
7172
7173
7174
7175

7176

7177

7178
7179
7180
7181
7182
7183
7184
7185
7186
7187
7188
7189


7190


7191
7192
7193
7194
7195
7196
7197







-
+
-

-
+











-
-
+
-
-







static void freePage(MemPage *pPage, int *pRC){
  if( (*pRC)==SQLITE_OK ){
    *pRC = freePage2(pPage->pBt, pPage, pPage->pgno);
  }
}

/*
** Free any overflow pages associated with the given Cell.  Store
** Free the overflow pages associated with the given Cell.
** size information about the cell in pInfo.
*/
static int clearCell(
static SQLITE_NOINLINE int clearCellOverflow(
  MemPage *pPage,          /* The page that contains the Cell */
  unsigned char *pCell,    /* First byte of the Cell */
  CellInfo *pInfo          /* Size information about the cell */
){
  BtShared *pBt;
  Pgno ovflPgno;
  int rc;
  int nOvfl;
  u32 ovflPageSize;

  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  pPage->xParseCell(pPage, pCell, pInfo);
  if( pInfo->nLocal==pInfo->nPayload ){
  assert( pInfo->nLocal!=pInfo->nPayload );
    return SQLITE_OK;  /* No overflow pages. Return without doing anything */
  }
  testcase( pCell + pInfo->nSize == pPage->aDataEnd );
  testcase( pCell + (pInfo->nSize-1) == pPage->aDataEnd );
  if( pCell + pInfo->nSize > pPage->aDataEnd ){
    /* Cell extends past end of page */
    return SQLITE_CORRUPT_PAGE(pPage);
  }
  ovflPgno = get4byte(pCell + pInfo->nSize - 4);
6798
6799
6800
6801
6802
6803
6804















6805
6806
6807
6808
6809
6810
6811
7238
7239
7240
7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261
7262
7263
7264
7265
7266







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







      sqlite3PagerUnref(pOvfl->pDbPage);
    }
    if( rc ) return rc;
    ovflPgno = iNext;
  }
  return SQLITE_OK;
}

/* Call xParseCell to compute the size of a cell.  If the cell contains
** overflow, then invoke cellClearOverflow to clear out that overflow.
** STore the result code (SQLITE_OK or some error code) in rc.
**
** Implemented as macro to force inlining for performance.
*/
#define BTREE_CLEAR_CELL(rc, pPage, pCell, sInfo)   \
  pPage->xParseCell(pPage, pCell, &sInfo);          \
  if( sInfo.nLocal!=sInfo.nPayload ){               \
    rc = clearCellOverflow(pPage, pCell, &sInfo);   \
  }else{                                            \
    rc = SQLITE_OK;                                 \
  }


/*
** Create the byte sequence used to represent a cell on page pPage
** and write that byte sequence into pCell[].  Overflow pages are
** allocated and filled in as necessary.  The calling procedure
** is responsible for making sure sufficient space has been allocated
** for pCell[].
7008
7009
7010
7011
7012
7013
7014
7015


7016
7017
7018

7019
7020

7021
7022
7023

7024
7025
7026
7027
7028
7029
7030
7463
7464
7465
7466
7467
7468
7469

7470
7471
7472
7473
7474
7475
7476
7477
7478
7479
7480

7481
7482
7483
7484
7485
7486
7487
7488







-
+
+



+


+


-
+







  u32 pc;         /* Offset to cell content of cell being deleted */
  u8 *data;       /* pPage->aData */
  u8 *ptr;        /* Used to move bytes around within data[] */
  int rc;         /* The return code */
  int hdr;        /* Beginning of the header.  0 most pages.  100 page 1 */

  if( *pRC ) return;
  assert( idx>=0 && idx<pPage->nCell );
  assert( idx>=0 );
  assert( idx<pPage->nCell );
  assert( CORRUPT_DB || sz==cellSize(pPage, idx) );
  assert( sqlite3PagerIswriteable(pPage->pDbPage) );
  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  assert( pPage->nFree>=0 );
  data = pPage->aData;
  ptr = &pPage->aCellIdx[2*idx];
  assert( pPage->pBt->usableSize > (u32)(ptr-data) );
  pc = get2byte(ptr);
  hdr = pPage->hdrOffset;
  testcase( pc==get2byte(&data[hdr+5]) );
  testcase( pc==(u32)get2byte(&data[hdr+5]) );
  testcase( pc+sz==pPage->pBt->usableSize );
  if( pc+sz > pPage->pBt->usableSize ){
    *pRC = SQLITE_CORRUPT_BKPT;
    return;
  }
  rc = freeSpace(pPage, pc, sz);
  if( rc ){
7052
7053
7054
7055
7056
7057
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
7510
7511
7512
7513
7514
7515
7516


7517

7518
7519
7520
7521
7522
7523

7524

7525
7526
7527
7528
7529
7530

7531
7532
7533
7534
7535
7536






7537
7538
7539
7540
7541
7542
7543
7544
7545







-
-

-
+





-
+
-






-






-
-
-
-
-
-
+
+







** If the cell content will fit on the page, then put it there.  If it
** will not fit, then make a copy of the cell content into pTemp if
** pTemp is not null.  Regardless of pTemp, allocate a new entry
** in pPage->apOvfl[] and make it point to the cell content (either
** in pTemp or the original pCell) and also record its index. 
** Allocating a new entry in pPage->aCell[] implies that 
** pPage->nOverflow is incremented.
**
** *pRC must be SQLITE_OK when this routine is called.
*/
static void insertCell(
static int insertCell(
  MemPage *pPage,   /* Page into which we are copying */
  int i,            /* New cell becomes the i-th cell of the page */
  u8 *pCell,        /* Content of the new cell */
  int sz,           /* Bytes of content in pCell */
  u8 *pTemp,        /* Temp storage space for pCell, if needed */
  Pgno iChild,      /* If non-zero, replace first 4 bytes with this value */
  Pgno iChild       /* If non-zero, replace first 4 bytes with this value */
  int *pRC          /* Read and write return code from here */
){
  int idx = 0;      /* Where to write new cell content in data[] */
  int j;            /* Loop counter */
  u8 *data;         /* The content of the whole page */
  u8 *pIns;         /* The point in pPage->aCellIdx[] where no cell inserted */

  assert( *pRC==SQLITE_OK );
  assert( i>=0 && i<=pPage->nCell+pPage->nOverflow );
  assert( MX_CELL(pPage->pBt)<=10921 );
  assert( pPage->nCell<=MX_CELL(pPage->pBt) || CORRUPT_DB );
  assert( pPage->nOverflow<=ArraySize(pPage->apOvfl) );
  assert( ArraySize(pPage->apOvfl)==ArraySize(pPage->aiOvfl) );
  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  /* The cell should normally be sized correctly.  However, when moving a
  ** malformed cell from a leaf page to an interior page, if the cell size
  ** wanted to be less than 4 but got rounded up to 4 on the leaf, then size
  ** might be less than 8 (leaf-size + pointer) on the interior node.  Hence
  ** the term after the || in the following assert(). */
  assert( sz==pPage->xCellSize(pPage, pCell) || (sz==8 && iChild>0) );
  assert( sz==pPage->xCellSize(pPage, pCell) || CORRUPT_DB );
  assert( pPage->nFree>=0 );
  if( pPage->nOverflow || sz+2>pPage->nFree ){
    if( pTemp ){
      memcpy(pTemp, pCell, sz);
      pCell = pTemp;
    }
    if( iChild ){
      put4byte(pCell, iChild);
7109
7110
7111
7112
7113
7114
7115
7116
7117

7118
7119
7120
7121
7122
7123

7124
7125
7126
7127
7128
7129
7130
7131






7132


7133
7134
7135
7136
7137
7138
7139
7140

7141

7142
7143
7144
7145


7146
7147

7148
7149
7150




















7151
7152



























































7153
7154
7155
7156
7157
7158
7159


7160
7161
7162
7163
7164
7165
7166


7167
7168
7169
7170
7171


7172
7173
7174

7175
7176
7177
7178
7179
7180
7181
7559
7560
7561
7562
7563
7564
7565


7566
7567
7568
7569
7570
7571

7572
7573
7574
7575
7576
7577
7578

7579
7580
7581
7582
7583
7584
7585
7586
7587
7588
7589
7590
7591
7592
7593
7594
7595

7596
7597
7598
7599
7600
7601

7602
7603
7604
7605
7606
7607
7608
7609
7610
7611
7612
7613
7614
7615
7616
7617
7618
7619
7620
7621
7622
7623
7624
7625
7626
7627
7628
7629
7630
7631
7632
7633
7634
7635
7636
7637
7638
7639
7640
7641
7642
7643
7644
7645
7646
7647
7648
7649
7650
7651
7652
7653
7654
7655
7656
7657
7658
7659
7660
7661
7662
7663
7664
7665
7666
7667
7668
7669
7670
7671
7672
7673
7674
7675
7676
7677
7678
7679
7680
7681
7682
7683
7684
7685
7686
7687
7688
7689
7690
7691
7692
7693
7694
7695
7696
7697
7698
7699
7700
7701
7702
7703
7704
7705
7706
7707
7708
7709
7710
7711


7712
7713
7714
7715

7716
7717
7718
7719
7720
7721
7722
7723







-
-
+





-
+






-

+
+
+
+
+
+

+
+







-
+

+



-
+
+


+



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


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







+
+







+
+



-
-
+
+


-
+







    */
    assert( j==0 || pPage->aiOvfl[j-1]<(u16)i ); /* Overflows in sorted order */
    assert( j==0 || i==pPage->aiOvfl[j-1]+1 );   /* Overflows are sequential */
  }else{
    BtShared *pBt = pPage->pBt;
    int rc = sqlite3PagerWrite(pPage->pDbPage);
    if( rc!=SQLITE_OK ){
      *pRC = rc;
      return;
      return rc;
    }
    assert( sqlite3PagerIswriteable(pPage->pDbPage) );
    data = pPage->aData;
    assert( &data[pPage->cellOffset]==pPage->aCellIdx );
    rc = allocateSpace(pPage, sz, &idx);
    if( rc ){ *pRC = rc; return; }
    if( rc ){ return rc; }
    /* The allocateSpace() routine guarantees the following properties
    ** if it returns successfully */
    assert( idx >= 0 );
    assert( idx >= pPage->cellOffset+2*pPage->nCell+2 || CORRUPT_DB );
    assert( idx+sz <= (int)pBt->usableSize );
    pPage->nFree -= (u16)(2 + sz);
    memcpy(&data[idx], pCell, sz);
    if( iChild ){
      /* In a corrupt database where an entry in the cell index section of
      ** a btree page has a value of 3 or less, the pCell value might point
      ** as many as 4 bytes in front of the start of the aData buffer for
      ** the source page.  Make sure this does not cause problems by not
      ** reading the first 4 bytes */
      memcpy(&data[idx+4], pCell+4, sz-4);
      put4byte(&data[idx], iChild);
    }else{
      memcpy(&data[idx], pCell, sz);
    }
    pIns = pPage->aCellIdx + i*2;
    memmove(pIns+2, pIns, 2*(pPage->nCell - i));
    put2byte(pIns, idx);
    pPage->nCell++;
    /* increment the cell count */
    if( (++data[pPage->hdrOffset+4])==0 ) data[pPage->hdrOffset+3]++;
    assert( get2byte(&data[pPage->hdrOffset+3])==pPage->nCell );
    assert( get2byte(&data[pPage->hdrOffset+3])==pPage->nCell || CORRUPT_DB );
    if( REQUIRE_PTRMAP ){
      int rc2 = SQLITE_OK;
      /* The cell may contain a pointer to an overflow page. If so, write
      ** the entry for the overflow page into the pointer map.
      */
      ptrmapPutOvflPtr(pPage, pCell, pRC);
      ptrmapPutOvflPtr(pPage, pPage, pCell, &rc2);
      if( rc2 ) return rc2;
    }
  }
  return SQLITE_OK;
}

/*
** The following parameters determine how many adjacent pages get involved
** in a balancing operation.  NN is the number of neighbors on either side
** of the page that participate in the balancing operation.  NB is the
** total number of pages that participate, including the target page and
** NN neighbors on either side.
**
** The minimum value of NN is 1 (of course).  Increasing NN above 1
** (to 2 or 3) gives a modest improvement in SELECT and DELETE performance
** in exchange for a larger degradation in INSERT and UPDATE performance.
** The value of NN appears to give the best results overall.
**
** (Later:) The description above makes it seem as if these values are
** tunable - as if you could change them and recompile and it would all work.
** But that is unlikely.  NB has been 3 since the inception of SQLite and
** we have never tested any other value.
*/
#define NN 1             /* Number of neighbors on either side of pPage */
#define NB 3             /* (NN*2+1): Total pages involved in the balance */

/*
** A CellArray object contains a cache of pointers and sizes for a
** consecutive sequence of cells that might be held on multiple pages.
**
** The cells in this array are the divider cell or cells from the pParent
** page plus up to three child pages.  There are a total of nCell cells.
**
** pRef is a pointer to one of the pages that contributes cells.  This is
** used to access information such as MemPage.intKey and MemPage.pBt->pageSize
** which should be common to all pages that contribute cells to this array.
**
** apCell[] and szCell[] hold, respectively, pointers to the start of each
** cell and the size of each cell.  Some of the apCell[] pointers might refer
** to overflow cells.  In other words, some apCel[] pointers might not point
** to content area of the pages.
**
** A szCell[] of zero means the size of that cell has not yet been computed.
**
** The cells come from as many as four different pages:
**
**             -----------
**             | Parent  |
**             -----------
**            /     |     \
**           /      |      \
**  ---------   ---------   ---------
**  |Child-1|   |Child-2|   |Child-3|
**  ---------   ---------   ---------
**
** The order of cells is in the array is for an index btree is:
**
**       1.  All cells from Child-1 in order
**       2.  The first divider cell from Parent
**       3.  All cells from Child-2 in order
**       4.  The second divider cell from Parent
**       5.  All cells from Child-3 in order
**
** For a table-btree (with rowids) the items 2 and 4 are empty because
** content exists only in leaves and there are no divider cells.
**
** For an index btree, the apEnd[] array holds pointer to the end of page
** for Child-1, the Parent, Child-2, the Parent (again), and Child-3,
** respectively. The ixNx[] array holds the number of cells contained in
** each of these 5 stages, and all stages to the left.  Hence:
**
**    ixNx[0] = Number of cells in Child-1.
**    ixNx[1] = Number of cells in Child-1 plus 1 for first divider.
**    ixNx[2] = Number of cells in Child-1 and Child-2 + 1 for 1st divider.
**    ixNx[3] = Number of cells in Child-1 and Child-2 + both divider cells
**    ixNx[4] = Total number of cells.
**
** For a table-btree, the concept is similar, except only apEnd[0]..apEnd[2]
** are used and they point to the leaf pages only, and the ixNx value are:
**
**    ixNx[0] = Number of cells in Child-1.
**    ixNx[1] = Number of cells in Child-1 and Child-2.
**    ixNx[2] = Total number of cells.
**
** Sometimes when deleting, a child page can have zero cells.  In those
** cases, ixNx[] entries with higher indexes, and the corresponding apEnd[]
** entries, shift down.  The end result is that each ixNx[] entry should
** be larger than the previous
*/
typedef struct CellArray CellArray;
struct CellArray {
  int nCell;              /* Number of cells in apCell[] */
  MemPage *pRef;          /* Reference page */
  u8 **apCell;            /* All cells begin balanced */
  u16 *szCell;            /* Local size of all cells in apCell[] */
  u8 *apEnd[NB*2];        /* MemPage.aDataEnd values */
  int ixNx[NB*2];         /* Index of at which we move to the next apEnd[] */
};

/*
** Make sure the cell sizes at idx, idx+1, ..., idx+N-1 have been
** computed.
*/
static void populateCellCache(CellArray *p, int idx, int N){
  MemPage *pRef = p->pRef;
  u16 *szCell = p->szCell;
  assert( idx>=0 && idx+N<=p->nCell );
  while( N>0 ){
    assert( p->apCell[idx]!=0 );
    if( p->szCell[idx]==0 ){
      p->szCell[idx] = p->pRef->xCellSize(p->pRef, p->apCell[idx]);
    if( szCell[idx]==0 ){
      szCell[idx] = pRef->xCellSize(pRef, p->apCell[idx]);
    }else{
      assert( CORRUPT_DB ||
              p->szCell[idx]==p->pRef->xCellSize(p->pRef, p->apCell[idx]) );
              szCell[idx]==pRef->xCellSize(pRef, p->apCell[idx]) );
    }
    idx++;
    N--;
  }
}

/*
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
7236
7237
7238
7239
7240








7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255

7256
7257
7258
7259
7260




7261
7262
7263
7264
7265
7266
7267
7745
7746
7747
7748
7749
7750
7751
7752

7753
7754


7755
7756
7757
7758
7759
7760
7761
7762

7763
7764
7765
7766
7767
7768
7769
7770


7771
7772
7773
7774
7775
7776
7777
7778




7779
7780
7781
7782
7783
7784
7785
7786
7787
7788
7789
7790
7791

7792
7793
7794
7795



7796
7797
7798
7799
7800
7801
7802
7803
7804
7805
7806
7807
7808
7809
7810
7811
7812
7813
7814
7815
7816
7817

7818





7819
7820
7821
7822
7823
7824
7825
7826
7827
7828
7829







+
-
+

-
-
+





+
+
-
+



+
+

+
-
-
+
+
+
+
+
+


-
-
-
-
+
+
+
+
+
+

+
+
+
+

+
-
+



-
-
-
+
+
+
+
+
+
+
+














-
+
-
-
-
-
-
+
+
+
+







** function works around problems caused by this by making a copy of any 
** such cells before overwriting the page data.
**
** The MemPage.nFree field is invalidated by this function. It is the 
** responsibility of the caller to set it correctly.
*/
static int rebuildPage(
  CellArray *pCArray,             /* Content to be added to page pPg */
  MemPage *pPg,                   /* Edit this page */
  int iFirst,                     /* First cell in pCArray to use */
  int nCell,                      /* Final number of cells on page */
  u8 **apCell,                    /* Array of cells */
  u16 *szCell                     /* Array of cell sizes */
  MemPage *pPg                    /* The page to be reconstructed */
){
  const int hdr = pPg->hdrOffset;          /* Offset of header on pPg */
  u8 * const aData = pPg->aData;           /* Pointer to data for pPg */
  const int usableSize = pPg->pBt->usableSize;
  u8 * const pEnd = &aData[usableSize];
  int i = iFirst;                 /* Which cell to copy from pCArray*/
  u32 j;                          /* Start of cell content area */
  int i;
  int iEnd = i+nCell;             /* Loop terminator */
  u8 *pCellptr = pPg->aCellIdx;
  u8 *pTmp = sqlite3PagerTempSpace(pPg->pBt->pPager);
  u8 *pData;
  int k;                          /* Current slot in pCArray->apEnd[] */
  u8 *pSrcEnd;                    /* Current pCArray->apEnd[k] value */

  assert( i<iEnd );
  i = get2byte(&aData[hdr+5]);
  memcpy(&pTmp[i], &aData[i], usableSize - i);
  j = get2byte(&aData[hdr+5]);
  if( j>(u32)usableSize ){ j = 0; }
  memcpy(&pTmp[j], &aData[j], usableSize - j);

  for(k=0; pCArray->ixNx[k]<=i && ALWAYS(k<NB*2); k++){}
  pSrcEnd = pCArray->apEnd[k];

  pData = pEnd;
  for(i=0; i<nCell; i++){
    u8 *pCell = apCell[i];
    if( SQLITE_WITHIN(pCell,aData,pEnd) ){
      if( ((uptr)(pCell+szCell[i]))>(uptr)pEnd ) return SQLITE_CORRUPT_BKPT;
  while( 1/*exit by break*/ ){
    u8 *pCell = pCArray->apCell[i];
    u16 sz = pCArray->szCell[i];
    assert( sz>0 );
    if( SQLITE_WITHIN(pCell,aData+j,pEnd) ){
      if( ((uptr)(pCell+sz))>(uptr)pEnd ) return SQLITE_CORRUPT_BKPT;
      pCell = &pTmp[pCell - aData];
    }else if( (uptr)(pCell+sz)>(uptr)pSrcEnd
           && (uptr)(pCell)<(uptr)pSrcEnd
    ){
      return SQLITE_CORRUPT_BKPT;
    }

    pData -= szCell[i];
    pData -= sz;
    put2byte(pCellptr, (pData - aData));
    pCellptr += 2;
    if( pData < pCellptr ) return SQLITE_CORRUPT_BKPT;
    memcpy(pData, pCell, szCell[i]);
    assert( szCell[i]==pPg->xCellSize(pPg, pCell) || CORRUPT_DB );
    testcase( szCell[i]!=pPg->xCellSize(pPg,pCell) );
    memmove(pData, pCell, sz);
    assert( sz==pPg->xCellSize(pPg, pCell) || CORRUPT_DB );
    i++;
    if( i>=iEnd ) break;
    if( pCArray->ixNx[k]<=i ){
      k++;
      pSrcEnd = pCArray->apEnd[k];
    }
  }

  /* The pPg->nFree field is now set incorrectly. The caller will fix it. */
  pPg->nCell = nCell;
  pPg->nOverflow = 0;

  put2byte(&aData[hdr+1], 0);
  put2byte(&aData[hdr+3], pPg->nCell);
  put2byte(&aData[hdr+5], pData - aData);
  aData[hdr+7] = 0x00;
  return SQLITE_OK;
}

/*
** Array apCell[] contains nCell pointers to b-tree cells. Array szCell
** The pCArray objects contains pointers to b-tree cells and the cell sizes.
** contains the size in bytes of each such cell. This function attempts to 
** add the cells stored in the array to page pPg. If it cannot (because 
** the page needs to be defragmented before the cells will fit), non-zero
** is returned. Otherwise, if the cells are added successfully, zero is
** returned.
** This function attempts to add the cells stored in the array to page pPg.
** If it cannot (because the page needs to be defragmented before the cells
** will fit), non-zero is returned. Otherwise, if the cells are added
** successfully, zero is returned.
**
** Argument pCellptr points to the first entry in the cell-pointer array
** (part of page pPg) to populate. After cell apCell[0] is written to the
** page body, a 16-bit offset is written to pCellptr. And so on, for each
** cell in the array. It is the responsibility of the caller to ensure
** that it is safe to overwrite this part of the cell-pointer array.
**
7275
7276
7277
7278
7279
7280
7281
7282

7283
7284
7285
7286
7287
7288
7289
7290
7291






7292
7293




7294
7295

7296

7297
7298
7299
7300
7301
7302
7303
7304
7305
7306
7307







7308
7309
7310






7311
7312
7313
7314
7315
7316
7317
7318
7319
7320
7321





7322
7323
7324
7325
7326
7327
7328
7329
7330
7331
7332
7333
7334
7335
7336
7337
7338


7339
7340
7341
7342
7343
7344
7345
7346
7347
7348
7349
7350
7351
7352
7353
7354
7355



7356



7357
7358
7359
7360
7361
7362
7363
7364
7365
7366
7367
7368
7369
7370
7371
7372
7373



7374
7375
7376
7377
7378
7379
7380
7837
7838
7839
7840
7841
7842
7843

7844
7845
7846
7847
7848
7849




7850
7851
7852
7853
7854
7855
7856

7857
7858
7859
7860
7861
7862
7863

7864
7865
7866
7867
7868
7869
7870
7871
7872
7873
7874
7875
7876
7877
7878
7879
7880
7881
7882
7883
7884
7885
7886
7887
7888
7889
7890
7891
7892
7893
7894
7895
7896
7897





7898
7899
7900
7901
7902
7903
7904
7905
7906
7907
7908
7909
7910
7911
7912
7913
7914
7915
7916
7917


7918
7919
7920
7921
7922
7923
7924
7925
7926
7927
7928
7929
7930
7931
7932
7933
7934
7935

7936
7937
7938
7939
7940
7941
7942
7943
7944
7945
7946
7947
7948
7949
7950
7951
7952
7953
7954
7955
7956



7957
7958
7959
7960
7961
7962
7963
7964
7965
7966







-
+





-
-
-
-
+
+
+
+
+
+

-
+
+
+
+


+
-
+











+
+
+
+
+
+
+



+
+
+
+
+
+






-
-
-
-
-
+
+
+
+
+















-
-
+
+
















-
+
+
+

+
+
+














-
-
-
+
+
+







** all cells - not just those inserted by the current call). If the content
** area must be extended to before this point in order to accomodate all
** cells in apCell[], then the cells do not fit and non-zero is returned.
*/
static int pageInsertArray(
  MemPage *pPg,                   /* Page to add cells to */
  u8 *pBegin,                     /* End of cell-pointer array */
  u8 **ppData,                    /* IN/OUT: Page content -area pointer */
  u8 **ppData,                    /* IN/OUT: Page content-area pointer */
  u8 *pCellptr,                   /* Pointer to cell-pointer area */
  int iFirst,                     /* Index of first cell to add */
  int nCell,                      /* Number of cells to add to pPg */
  CellArray *pCArray              /* Array of cells */
){
  int i;
  u8 *aData = pPg->aData;
  u8 *pData = *ppData;
  int iEnd = iFirst + nCell;
  int i = iFirst;                 /* Loop counter - cell index to insert */
  u8 *aData = pPg->aData;         /* Complete page */
  u8 *pData = *ppData;            /* Content area.  A subset of aData[] */
  int iEnd = iFirst + nCell;      /* End of loop. One past last cell to ins */
  int k;                          /* Current slot in pCArray->apEnd[] */
  u8 *pEnd;                       /* Maximum extent of cell data */
  assert( CORRUPT_DB || pPg->hdrOffset==0 );    /* Never called on page 1 */
  for(i=iFirst; i<iEnd; i++){
  if( iEnd<=iFirst ) return 0;
  for(k=0; pCArray->ixNx[k]<=i && ALWAYS(k<NB*2); k++){}
  pEnd = pCArray->apEnd[k];
  while( 1 /*Exit by break*/ ){
    int sz, rc;
    u8 *pSlot;
    assert( pCArray->szCell[i]!=0 );
    sz = cachedCellSize(pCArray, i);
    sz = pCArray->szCell[i];
    if( (aData[1]==0 && aData[2]==0) || (pSlot = pageFindSlot(pPg,sz,&rc))==0 ){
      if( (pData - pBegin)<sz ) return 1;
      pData -= sz;
      pSlot = pData;
    }
    /* pSlot and pCArray->apCell[i] will never overlap on a well-formed
    ** database.  But they might for a corrupt database.  Hence use memmove()
    ** since memcpy() sends SIGABORT with overlapping buffers on OpenBSD */
    assert( (pSlot+sz)<=pCArray->apCell[i]
         || pSlot>=(pCArray->apCell[i]+sz)
         || CORRUPT_DB );
    if( (uptr)(pCArray->apCell[i]+sz)>(uptr)pEnd
     && (uptr)(pCArray->apCell[i])<(uptr)pEnd
    ){
      assert( CORRUPT_DB );
      (void)SQLITE_CORRUPT_BKPT;
      return 1;
    }
    memmove(pSlot, pCArray->apCell[i], sz);
    put2byte(pCellptr, (pSlot - aData));
    pCellptr += 2;
    i++;
    if( i>=iEnd ) break;
    if( pCArray->ixNx[k]<=i ){
      k++;
      pEnd = pCArray->apEnd[k];
    }
  }
  *ppData = pData;
  return 0;
}

/*
** Array apCell[] contains nCell pointers to b-tree cells. Array szCell 
** contains the size in bytes of each such cell. This function adds the
** space associated with each cell in the array that is currently stored 
** within the body of pPg to the pPg free-list. The cell-pointers and other
** fields of the page are not updated.
** The pCArray object contains pointers to b-tree cells and their sizes.
**
** This function adds the space associated with each cell in the array
** that is currently stored within the body of pPg to the pPg free-list.
** The cell-pointers and other fields of the page are not updated.
**
** This function returns the total number of cells added to the free-list.
*/
static int pageFreeArray(
  MemPage *pPg,                   /* Page to edit */
  int iFirst,                     /* First cell to delete */
  int nCell,                      /* Cells to delete */
  CellArray *pCArray              /* Array of cells */
){
  u8 * const aData = pPg->aData;
  u8 * const pEnd = &aData[pPg->pBt->usableSize];
  u8 * const pStart = &aData[pPg->hdrOffset + 8 + pPg->childPtrSize];
  int nRet = 0;
  int i;
  int iEnd = iFirst + nCell;
  u8 *pFree = 0;
  int szFree = 0;
  u8 *pFree = 0;                  /* \__ Parameters for pending call to */
  int szFree = 0;                 /* /   freeSpace()                    */

  for(i=iFirst; i<iEnd; i++){
    u8 *pCell = pCArray->apCell[i];
    if( SQLITE_WITHIN(pCell, pStart, pEnd) ){
      int sz;
      /* No need to use cachedCellSize() here.  The sizes of all cells that
      ** are to be freed have already been computing while deciding which
      ** cells need freeing */
      sz = pCArray->szCell[i];  assert( sz>0 );
      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( pFree+sz>pEnd ){
          return 0;
        }
      }else{
        /* The current cell is adjacent to and before the pFree cell.
        ** Combine the two regions into one to reduce the number of calls
        ** to freeSpace(). */
        pFree = pCell;
        szFree += sz;
      }
      nRet++;
    }
  }
  if( pFree ){
    assert( pFree>aData && (pFree - aData)<65536 );
    freeSpace(pPg, (u16)(pFree - aData), szFree);
  }
  return nRet;
}

/*
** apCell[] and szCell[] contains pointers to and sizes of all cells in the
** pages being balanced.  The current page, pPg, has pPg->nCell cells starting
** with apCell[iOld].  After balancing, this page should hold nNew cells
** pCArray contains pointers to and sizes of all cells in the page being
** balanced.  The current page, pPg, has pPg->nCell cells starting with
** pCArray->apCell[iOld].  After balancing, this page should hold nNew cells
** starting at apCell[iNew].
**
** This routine makes the necessary adjustments to pPg so that it contains
** the correct cells after being balanced.
**
** The pPg->nFree field is invalid when this function returns. It is the
** responsibility of the caller to set it correctly.
7398
7399
7400
7401
7402
7403
7404

7405
7406

7407
7408
7409
7410
7411



7412
7413
7414
7415

7416
7417
7418
7419
7420

7421
7422
7423
7424
7425
7426
7427
7428
7429
7430
7431
7432
7433
7434

7435


7436

7437
7438
7439
7440
7441
7442
7443
7444

7445
7446
7447
7448
7449
7450
7451
7984
7985
7986
7987
7988
7989
7990
7991
7992
7993
7994
7995
7996
7997
7998

7999
8000
8001
8002
8003
8004
8005
8006
8007
8008
8009
8010
8011
8012
8013
8014
8015
8016
8017
8018
8019
8020
8021
8022
8023
8024
8025
8026
8027

8028
8029
8030
8031
8032
8033
8034
8035
8036
8037
8038
8039
8040
8041
8042
8043
8044
8045
8046
8047







+


+




-
+
+
+




+





+














+
-
+
+

+








+








#ifdef SQLITE_DEBUG
  u8 *pTmp = sqlite3PagerTempSpace(pPg->pBt->pPager);
  memcpy(pTmp, aData, pPg->pBt->usableSize);
#endif

  /* Remove cells from the start and end of the page */
  assert( nCell>=0 );
  if( iOld<iNew ){
    int nShift = pageFreeArray(pPg, iOld, iNew-iOld, pCArray);
    if( NEVER(nShift>nCell) ) return SQLITE_CORRUPT_BKPT;
    memmove(pPg->aCellIdx, &pPg->aCellIdx[nShift*2], nCell*2);
    nCell -= nShift;
  }
  if( iNewEnd < iOldEnd ){
    nCell -= pageFreeArray(pPg, iNewEnd, iOldEnd - iNewEnd, pCArray);
    int nTail = pageFreeArray(pPg, iNewEnd, iOldEnd - iNewEnd, pCArray);
    assert( nCell>=nTail );
    nCell -= nTail;
  }

  pData = &aData[get2byteNotZero(&aData[hdr+5])];
  if( pData<pBegin ) goto editpage_fail;
  if( pData>pPg->aDataEnd ) goto editpage_fail;

  /* Add cells to the start of the page */
  if( iNew<iOld ){
    int nAdd = MIN(nNew,iOld-iNew);
    assert( (iOld-iNew)<nNew || nCell==0 || CORRUPT_DB );
    assert( nAdd>=0 );
    pCellptr = pPg->aCellIdx;
    memmove(&pCellptr[nAdd*2], pCellptr, nCell*2);
    if( pageInsertArray(
          pPg, pBegin, &pData, pCellptr,
          iNew, nAdd, pCArray
    ) ) goto editpage_fail;
    nCell += nAdd;
  }

  /* Add any overflow cells */
  for(i=0; i<pPg->nOverflow; i++){
    int iCell = (iOld + pPg->aiOvfl[i]) - iNew;
    if( iCell>=0 && iCell<nNew ){
      pCellptr = &pPg->aCellIdx[iCell * 2];
      if( nCell>iCell ){
      memmove(&pCellptr[2], pCellptr, (nCell - iCell) * 2);
        memmove(&pCellptr[2], pCellptr, (nCell - iCell) * 2);
      }
      nCell++;
      cachedCellSize(pCArray, iCell+iNew);
      if( pageInsertArray(
            pPg, pBegin, &pData, pCellptr,
            iCell+iNew, 1, pCArray
      ) ) goto editpage_fail;
    }
  }

  /* Append cells to the end of the page */
  assert( nCell>=0 );
  pCellptr = &pPg->aCellIdx[nCell*2];
  if( pageInsertArray(
        pPg, pBegin, &pData, pCellptr,
        iNew+nCell, nNew-nCell, pCArray
  ) ) goto editpage_fail;

  pPg->nCell = nNew;
7466
7467
7468
7469
7470
7471
7472
7473

7474
7475
7476
7477
7478
7479
7480
7481
7482
7483
7484
7485
7486
7487
7488
7489
7490
7491
7492
7493
7494
7495
7496
8062
8063
8064
8065
8066
8067
8068

8069
8070















8071
8072
8073
8074
8075
8076
8077







-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







  }
#endif

  return SQLITE_OK;
 editpage_fail:
  /* Unable to edit this page. Rebuild it from scratch instead. */
  populateCellCache(pCArray, iNew, nNew);
  return rebuildPage(pPg, nNew, &pCArray->apCell[iNew], &pCArray->szCell[iNew]);
  return rebuildPage(pCArray, iNew, nNew, pPg);
}

/*
** The following parameters determine how many adjacent pages get involved
** in a balancing operation.  NN is the number of neighbors on either side
** of the page that participate in the balancing operation.  NB is the
** total number of pages that participate, including the target page and
** NN neighbors on either side.
**
** The minimum value of NN is 1 (of course).  Increasing NN above 1
** (to 2 or 3) gives a modest improvement in SELECT and DELETE performance
** in exchange for a larger degradation in INSERT and UPDATE performance.
** The value of NN appears to give the best results overall.
*/
#define NN 1             /* Number of neighbors on either side of pPage */
#define NB (NN*2+1)      /* Total pages involved in the balance */


#ifndef SQLITE_OMIT_QUICKBALANCE
/*
** This version of balance() handles the common special case where
** a new entry is being inserted on the extreme right-end of the
** tree, in other words, when the new entry will become the largest
7518
7519
7520
7521
7522
7523
7524
7525

7526


7527
7528
7529
7530
7531
7532
7533
7534
7535
7536
7537
7538
7539

7540
7541
7542

7543






7544
7545





7546
7547
7548
7549
7550
7551
7552
7553
7554
7555
7556
7557
7558
7559
7560

7561
7562
7563
7564
7565
7566
7567
8099
8100
8101
8102
8103
8104
8105

8106
8107
8108
8109
8110
8111
8112
8113
8114
8115
8116
8117
8118
8119
8120
8121
8122
8123
8124
8125

8126
8127
8128
8129
8130
8131
8132
8133


8134
8135
8136
8137
8138
8139
8140
8141
8142
8143
8144
8145
8146
8147
8148
8149
8150
8151
8152

8153
8154
8155
8156
8157
8158
8159
8160







-
+

+
+













+


-
+

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














-
+







  MemPage *pNew;                       /* Newly allocated page */
  int rc;                              /* Return Code */
  Pgno pgnoNew;                        /* Page number of pNew */

  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  assert( sqlite3PagerIswriteable(pParent->pDbPage) );
  assert( pPage->nOverflow==1 );

  
  if( pPage->nCell==0 ) return SQLITE_CORRUPT_BKPT;  /* dbfuzz001.test */
  assert( pPage->nFree>=0 );
  assert( pParent->nFree>=0 );

  /* Allocate a new page. This page will become the right-sibling of 
  ** pPage. Make the parent page writable, so that the new divider cell
  ** may be inserted. If both these operations are successful, proceed.
  */
  rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0);

  if( rc==SQLITE_OK ){

    u8 *pOut = &pSpace[4];
    u8 *pCell = pPage->apOvfl[0];
    u16 szCell = pPage->xCellSize(pPage, pCell);
    u8 *pStop;
    CellArray b;

    assert( sqlite3PagerIswriteable(pNew->pDbPage) );
    assert( pPage->aData[0]==(PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF) );
    assert( CORRUPT_DB || pPage->aData[0]==(PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF) );
    zeroPage(pNew, PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF);
    b.nCell = 1;
    b.pRef = pPage;
    b.apCell = &pCell;
    b.szCell = &szCell;
    b.apEnd[0] = pPage->aDataEnd;
    b.ixNx[0] = 2;
    rc = rebuildPage(pNew, 1, &pCell, &szCell);
    if( NEVER(rc) ) return rc;
    rc = rebuildPage(&b, 0, 1, pNew);
    if( NEVER(rc) ){
      releasePage(pNew);
      return rc;
    }
    pNew->nFree = pBt->usableSize - pNew->cellOffset - 2 - szCell;

    /* If this is an auto-vacuum database, update the pointer map
    ** with entries for the new page, and any pointer from the 
    ** cell on the page to an overflow page. If either of these
    ** operations fails, the return code is set, but the contents
    ** of the parent page are still manipulated by thh code below.
    ** That is Ok, at this point the parent page is guaranteed to
    ** be marked as dirty. Returning an error code will cause a
    ** rollback, undoing any changes made to the parent page.
    */
    if( REQUIRE_PTRMAP ){
      ptrmapPut(pBt, pgnoNew, PTRMAP_BTREE, pParent->pgno, &rc);
      if( szCell>pNew->minLocal ){
        ptrmapPutOvflPtr(pNew, pCell, &rc);
        ptrmapPutOvflPtr(pNew, pNew, pCell, &rc);
      }
    }
  
    /* Create a divider cell to insert into pParent. The divider cell
    ** consists of a 4-byte page number (the page number of pPage) and
    ** a variable length key value (which must be the same value as the
    ** largest key on pPage).
7578
7579
7580
7581
7582
7583
7584
7585
7586


7587
7588
7589
7590
7591
7592
7593
8171
8172
8173
8174
8175
8176
8177


8178
8179
8180
8181
8182
8183
8184
8185
8186







-
-
+
+







    pStop = &pCell[9];
    while( (*(pCell++)&0x80) && pCell<pStop );
    pStop = &pCell[9];
    while( ((*(pOut++) = *(pCell++))&0x80) && pCell<pStop );

    /* Insert the new divider cell into pParent. */
    if( rc==SQLITE_OK ){
      insertCell(pParent, pParent->nCell, pSpace, (int)(pOut-pSpace),
                   0, pPage->pgno, &rc);
      rc = insertCell(pParent, pParent->nCell, pSpace, (int)(pOut-pSpace),
                      0, pPage->pgno);
    }

    /* Set the right-child pointer of pParent to point to the new page. */
    put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew);
  
    /* Release the reference to the new page. */
    releasePage(pNew);
7679
7680
7681
7682
7683
7684
7685

7686
7687
7688
7689
7690
7691
7692
8272
8273
8274
8275
8276
8277
8278
8279
8280
8281
8282
8283
8284
8285
8286







+







    /* Reinitialize page pTo so that the contents of the MemPage structure
    ** match the new data. The initialization of pTo can actually fail under
    ** fairly obscure circumstances, even though it is a copy of initialized 
    ** page pFrom.
    */
    pTo->isInit = 0;
    rc = btreeInitPage(pTo);
    if( rc==SQLITE_OK ) rc = btreeComputeFreeSpace(pTo);
    if( rc!=SQLITE_OK ){
      *pRC = rc;
      return;
    }
  
    /* If this is an auto-vacuum database, update the pointer-map entries
    ** for any b-tree or overflow pages that pTo now contains the pointers to.
7766
7767
7768
7769
7770
7771
7772
7773
7774
7775

7776
7777
7778

7779
7780
7781
7782
7783
7784
7785
7786
7787
7788
7789
7790
7791
7792
7793
7794
7795
7796
7797
7798

7799
7800
7801
7802
7803
7804
7805
8360
8361
8362
8363
8364
8365
8366



8367
8368
8369

8370

8371
8372
8373
8374




8375
8376
8377
8378
8379
8380
8381
8382
8383
8384
8385
8386
8387
8388
8389
8390
8391
8392
8393







-
-
-
+


-
+
-




-
-
-
-











+







  int cntNew[NB+2];            /* Index in b.paCell[] of cell after i-th page */
  int cntOld[NB+2];            /* Old index in b.apCell[] */
  int szNew[NB+2];             /* Combined size of cells placed on i-th page */
  u8 *aSpace1;                 /* Space for copies of dividers cells */
  Pgno pgno;                   /* Temp var to store a page number in */
  u8 abDone[NB+2];             /* True after i'th new page is populated */
  Pgno aPgno[NB+2];            /* Page numbers of new pages before shuffling */
  Pgno aPgOrder[NB+2];         /* Copy of aPgno[] used for sorting pages */
  u16 aPgFlags[NB+2];          /* flags field of new pages before shuffling */
  CellArray b;                  /* Parsed information on cells being balanced */
  CellArray b;                 /* Parsed information on cells being balanced */

  memset(abDone, 0, sizeof(abDone));
  b.nCell = 0;
  memset(&b, 0, sizeof(b));
  b.apCell = 0;
  pBt = pParent->pBt;
  assert( sqlite3_mutex_held(pBt->mutex) );
  assert( sqlite3PagerIswriteable(pParent->pDbPage) );

#if 0
  TRACE(("BALANCE: begin page %d child of %d\n", pPage->pgno, pParent->pgno));
#endif

  /* At this point pParent may have at most one overflow cell. And if
  ** this overflow cell is present, it must be the cell with 
  ** index iParentIdx. This scenario comes about when this function
  ** is called (indirectly) from sqlite3BtreeDelete().
  */
  assert( pParent->nOverflow==0 || pParent->nOverflow==1 );
  assert( pParent->nOverflow==0 || pParent->aiOvfl[0]==iParentIdx );

  if( !aOvflSpace ){
    return SQLITE_NOMEM_BKPT;
  }
  assert( pParent->nFree>=0 );

  /* Find the sibling pages to balance. Also locate the cells in pParent 
  ** that divide the siblings. An attempt is made to find NN siblings on 
  ** either side of pPage. More siblings are taken from one side, however, 
  ** if there are fewer than NN siblings on the other side. If pParent
  ** has NB or fewer children then all children of pParent are taken.  
  **
7826
7827
7828
7829
7830
7831
7832

7833


7834
7835
7836
7837
7838
7839
7840









7841
7842
7843
7844
7845
7846
7847
8414
8415
8416
8417
8418
8419
8420
8421

8422
8423
8424
8425
8426
8427



8428
8429
8430
8431
8432
8433
8434
8435
8436
8437
8438
8439
8440
8441
8442
8443







+
-
+
+




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







  if( (i+nxDiv-pParent->nOverflow)==pParent->nCell ){
    pRight = &pParent->aData[pParent->hdrOffset+8];
  }else{
    pRight = findCell(pParent, i+nxDiv-pParent->nOverflow);
  }
  pgno = get4byte(pRight);
  while( 1 ){
    if( rc==SQLITE_OK ){
    rc = getAndInitPage(pBt, pgno, &apOld[i], 0, 0);
      rc = getAndInitPage(pBt, pgno, &apOld[i], 0, 0);
    }
    if( rc ){
      memset(apOld, 0, (i+1)*sizeof(MemPage*));
      goto balance_cleanup;
    }
    setMempageRoot(apOld[i], pgnoRoot);

    nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow;
    if( apOld[i]->nFree<0 ){
      rc = btreeComputeFreeSpace(apOld[i]);
      if( rc ){
        memset(apOld, 0, (i)*sizeof(MemPage*));
        goto balance_cleanup;
      }
    }
    setMempageRoot(apOld[i], pgnoRoot);
    nMaxCells += apOld[i]->nCell + ArraySize(pParent->apOvfl);
    if( (i--)==0 ) break;

    if( pParent->nOverflow && i+nxDiv==pParent->aiOvfl[0] ){
      apDiv[i] = pParent->apOvfl[0];
      pgno = get4byte(apDiv[i]);
      szNew[i] = pParent->xCellSize(pParent, apDiv[i]);
      pParent->nOverflow = 0;
7861
7862
7863
7864
7865
7866
7867


7868
7869

7870
7871
7872
7873
7874
7875
7876
7877
7878
7879
7880
7881
7882
7883
7884
7885
7886
7887
7888
7889
7890
7891
7892
7893
7894

7895
7896
7897
7898
7899
7900
7901
8457
8458
8459
8460
8461
8462
8463
8464
8465
8466

8467




8468
8469
8470
8471
8472
8473
8474
8475
8476
8477
8478
8479
8480
8481
8482
8483
8484
8485
8486
8487

8488
8489
8490
8491
8492
8493
8494
8495







+
+

-
+
-
-
-
-




















-
+







      ** the dropCell() routine will overwrite the entire cell with zeroes.
      ** In this case, temporarily copy the cell into the aOvflSpace[]
      ** buffer. It will be copied out again as soon as the aSpace[] buffer
      ** is allocated.  */
      if( pBt->btsFlags & BTS_FAST_SECURE ){
        int iOff;

        /* If the following if() condition is not true, the db is corrupted.
        ** The call to dropCell() below will detect this.  */
        iOff = SQLITE_PTR_TO_INT(apDiv[i]) - SQLITE_PTR_TO_INT(pParent->aData);
        if( (iOff+szNew[i])>(int)pBt->usableSize ){
        if( (iOff+szNew[i])<=(int)pBt->usableSize ){
          rc = SQLITE_CORRUPT_BKPT;
          memset(apOld, 0, (i+1)*sizeof(MemPage*));
          goto balance_cleanup;
        }else{
          memcpy(&aOvflSpace[iOff], apDiv[i], szNew[i]);
          apDiv[i] = &aOvflSpace[apDiv[i]-pParent->aData];
        }
      }
      dropCell(pParent, i+nxDiv-pParent->nOverflow, szNew[i], &rc);
    }
  }

  /* Make nMaxCells a multiple of 4 in order to preserve 8-byte
  ** alignment */
  nMaxCells = (nMaxCells + 3)&~3;

  /*
  ** Allocate space for memory structures
  */
  szScratch =
       nMaxCells*sizeof(u8*)                       /* b.apCell */
     + nMaxCells*sizeof(u16)                       /* b.szCell */
     + pBt->pageSize;                              /* aSpace1 */

  assert( szScratch<=6*(int)pBt->pageSize );
  assert( szScratch<=7*(int)pBt->pageSize );
  b.apCell = sqlite3StackAllocRaw(0, szScratch );
  if( b.apCell==0 ){
    rc = SQLITE_NOMEM_BKPT;
    goto balance_cleanup;
  }
  b.szCell = (u16*)&b.apCell[nMaxCells];
  aSpace1 = (u8*)&b.szCell[nMaxCells];
7923
7924
7925
7926
7927
7928
7929

7930
7931
7932
7933
7934
7935
7936
8517
8518
8519
8520
8521
8522
8523
8524
8525
8526
8527
8528
8529
8530
8531







+







  for(i=0; i<nOld; i++){
    MemPage *pOld = apOld[i];
    int limit = pOld->nCell;
    u8 *aData = pOld->aData;
    u16 maskPage = pOld->maskPage;
    u8 *piCell = aData + pOld->cellOffset;
    u8 *piEnd;
    VVA_ONLY( int nCellAtStart = b.nCell; )

    /* Verify that all sibling pages are of the same "type" (table-leaf,
    ** table-interior, index-leaf, or index-interior).
    */
    if( pOld->aData[0]!=apOld[0]->aData[0] ){
      rc = SQLITE_CORRUPT_BKPT;
      goto balance_cleanup;
7951
7952
7953
7954
7955
7956
7957




7958
7959
7960
7961
7962
7963
7964
7965
7966
7967
7968
7969
7970
7971
7972
7973
7974
7975
7976

7977
7978
7979
7980
7981
7982
7983
7984
7985
7986
7987
7988
7989
7990
7991
7992
7993
7994

7995
7996
7997
7998
7999
8000
8001
8546
8547
8548
8549
8550
8551
8552
8553
8554
8555
8556
8557
8558
8559
8560
8561
8562
8563
8564
8565
8566
8567
8568
8569
8570
8571
8572
8573
8574
8575
8576
8577
8578
8579
8580
8581
8582
8583
8584
8585
8586
8587
8588
8589
8590
8591
8592
8593

8594
8595
8596
8597
8598
8599
8600
8601







+
+
+
+



















+

















-
+







    ** This must be done in advance.  Once the balance starts, the cell
    ** offset section of the btree page will be overwritten and we will no
    ** long be able to find the cells if a pointer to each cell is not saved
    ** first.
    */
    memset(&b.szCell[b.nCell], 0, sizeof(b.szCell[0])*(limit+pOld->nOverflow));
    if( pOld->nOverflow>0 ){
      if( NEVER(limit<pOld->aiOvfl[0]) ){
        rc = SQLITE_CORRUPT_BKPT;
        goto balance_cleanup;
      }
      limit = pOld->aiOvfl[0];
      for(j=0; j<limit; j++){
        b.apCell[b.nCell] = aData + (maskPage & get2byteAligned(piCell));
        piCell += 2;
        b.nCell++;
      }
      for(k=0; k<pOld->nOverflow; k++){
        assert( k==0 || pOld->aiOvfl[k-1]+1==pOld->aiOvfl[k] );/* NOTE 1 */
        b.apCell[b.nCell] = pOld->apOvfl[k];
        b.nCell++;
      }
    }
    piEnd = aData + pOld->cellOffset + 2*pOld->nCell;
    while( piCell<piEnd ){
      assert( b.nCell<nMaxCells );
      b.apCell[b.nCell] = aData + (maskPage & get2byteAligned(piCell));
      piCell += 2;
      b.nCell++;
    }
    assert( (b.nCell-nCellAtStart)==(pOld->nCell+pOld->nOverflow) );

    cntOld[i] = b.nCell;
    if( i<nOld-1 && !leafData){
      u16 sz = (u16)szNew[i];
      u8 *pTemp;
      assert( b.nCell<nMaxCells );
      b.szCell[b.nCell] = sz;
      pTemp = &aSpace1[iSpace1];
      iSpace1 += sz;
      assert( sz<=pBt->maxLocal+23 );
      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
8023
8024
8025
8026
8027
8028
8029
8030

8031











8032
8033
8034
8035
8036
8037
8038
8623
8624
8625
8626
8627
8628
8629

8630
8631
8632
8633
8634
8635
8636
8637
8638
8639
8640
8641
8642
8643
8644
8645
8646
8647
8648
8649







-
+

+
+
+
+
+
+
+
+
+
+
+







  **    szNew[i]: Spaced used on the i-th sibling page.
  **   cntNew[i]: Index in b.apCell[] and b.szCell[] for the first cell to
  **              the right of the i-th sibling page.
  ** usableSpace: Number of bytes of space available on each sibling.
  ** 
  */
  usableSpace = pBt->usableSize - 12 + leafCorrection;
  for(i=0; i<nOld; i++){
  for(i=k=0; i<nOld; i++, k++){
    MemPage *p = apOld[i];
    b.apEnd[k] = p->aDataEnd;
    b.ixNx[k] = cntOld[i];
    if( k && b.ixNx[k]==b.ixNx[k-1] ){
      k--;  /* Omit b.ixNx[] entry for child pages with no cells */
    }
    if( !leafData ){
      k++;
      b.apEnd[k] = pParent->aDataEnd;
      b.ixNx[k] = cntOld[i]+1;
    }
    assert( p->nFree>=0 );
    szNew[i] = usableSpace - p->nFree;
    for(j=0; j<p->nOverflow; j++){
      szNew[i] += 2 + p->xCellSize(p, p->apOvfl[j]);
    }
    cntNew[i] = cntOld[i];
  }
  k = nOld;
8096
8097
8098
8099
8100
8101
8102

8103
8104
8105


8106
8107

8108
8109
8110
8111


8112
8113
8114
8115
8116
8117
8118
8707
8708
8709
8710
8711
8712
8713
8714
8715
8716

8717
8718
8719

8720
8721
8722


8723
8724
8725
8726
8727
8728
8729
8730
8731







+


-
+
+

-
+


-
-
+
+







    int r;              /* Index of right-most cell in left sibling */
    int d;              /* Index of first cell to the left of right sibling */

    r = cntNew[i-1] - 1;
    d = r + 1 - leafData;
    (void)cachedCellSize(&b, d);
    do{
      int szR, szD;
      assert( d<nMaxCells );
      assert( r<nMaxCells );
      (void)cachedCellSize(&b, r);
      szR = cachedCellSize(&b, r);
      szD = b.szCell[d];
      if( szRight!=0
       && (bBulk || szRight+b.szCell[d]+2 > szLeft-(b.szCell[r]+(i==k-1?0:2)))){
       && (bBulk || szRight+szD+2 > szLeft-(szR+(i==k-1?0:2)))){
        break;
      }
      szRight += b.szCell[d] + 2;
      szLeft -= b.szCell[r] + 2;
      szRight += szD + 2;
      szLeft -= szR + 2;
      cntNew[i-1] = r;
      r--;
      d--;
    }while( r>=0 );
    szNew[i] = szRight;
    szNew[i-1] = szLeft;
    if( cntNew[i-1] <= (i>1 ? cntNew[i-2] : 0) ){
8142
8143
8144
8145
8146
8147
8148





8149
8150
8151
8152
8153
8154
8155
8755
8756
8757
8758
8759
8760
8761
8762
8763
8764
8765
8766
8767
8768
8769
8770
8771
8772
8773







+
+
+
+
+







  for(i=0; i<k; i++){
    MemPage *pNew;
    if( i<nOld ){
      pNew = apNew[i] = apOld[i];
      apOld[i] = 0;
      rc = sqlite3PagerWrite(pNew->pDbPage);
      nNew++;
      if( sqlite3PagerPageRefcount(pNew->pDbPage)!=1+(i==(iParentIdx-nxDiv))
       && rc==SQLITE_OK
      ){
        rc = SQLITE_CORRUPT_BKPT;
      }
      if( rc ) goto balance_cleanup;
    }else{
      assert( i>0 );
      rc = allocateBtreePage(pBt, &pNew, &pgno, (bBulk ? 1 : pgno), 0);
      if( rc ) goto balance_cleanup;
      zeroPage(pNew, pageFlags);
      apNew[i] = pNew;
8168
8169
8170
8171
8172
8173
8174
8175
8176


8177
8178
8179
8180
8181
8182
8183


8184
8185
8186
8187
8188
8189
8190
8191
8192

8193
8194
8195

8196
8197
8198
8199
8200
8201




8202
8203
8204
8205
8206
8207














8208
8209
8210



8211
8212
8213
8214
8215
8216
8217
8218
8219
8220
8221
8222
8223
8224
8225
8226
8227


8228
8229
8230
8231
8232
8233
8234
8786
8787
8788
8789
8790
8791
8792


8793
8794
8795
8796
8797
8798
8799


8800
8801









8802



8803






8804
8805
8806
8807
8808





8809
8810
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
8836
8837
8838
8839
8840
8841
8842
8843
8844
8845
8846
8847
8848
8849
8850
8851







-
-
+
+





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

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

















+
+








  /*
  ** Reassign page numbers so that the new pages are in ascending order. 
  ** This helps to keep entries in the disk file in order so that a scan
  ** of the table is closer to a linear scan through the file. That in turn 
  ** helps the operating system to deliver pages from the disk more rapidly.
  **
  ** An O(n^2) insertion sort algorithm is used, but since n is never more 
  ** than (NB+2) (a small constant), that should not be a problem.
  ** An O(N*N) sort algorithm is used, but since N is never more than NB+2
  ** (5), that is not a performance concern.
  **
  ** When NB==3, this one optimization makes the database about 25% faster 
  ** for large insertions and deletions.
  */
  for(i=0; i<nNew; i++){
    aPgOrder[i] = aPgno[i] = apNew[i]->pgno;
    aPgFlags[i] = apNew[i]->pDbPage->flags;
    aPgno[i] = apNew[i]->pgno;
    assert( apNew[i]->pDbPage->flags & PGHDR_WRITEABLE );
    for(j=0; j<i; j++){
      if( aPgno[j]==aPgno[i] ){
        /* This branch is taken if the set of sibling pages somehow contains
        ** duplicate entries. This can happen if the database is corrupt. 
        ** It would be simpler to detect this as part of the loop below, but
        ** we do the detection here in order to avoid populating the pager
        ** cache with two separate objects associated with the same
        ** page number.  */
        assert( CORRUPT_DB );
    assert( apNew[i]->pDbPage->flags & PGHDR_DIRTY );
        rc = SQLITE_CORRUPT_BKPT;
        goto balance_cleanup;
      }
  }
    }
  }
  for(i=0; i<nNew; i++){
    int iBest = 0;                /* aPgno[] index of page number to use */
    for(j=1; j<nNew; j++){
      if( aPgOrder[j]<aPgOrder[iBest] ) iBest = j;
  for(i=0; i<nNew-1; i++){
    int iB = i;
    for(j=i+1; j<nNew; j++){
      if( apNew[j]->pgno < apNew[iB]->pgno ) iB = j;
    }
    pgno = aPgOrder[iBest];
    aPgOrder[iBest] = 0xffffffff;
    if( iBest!=i ){
      if( iBest>i ){
        sqlite3PagerRekey(apNew[iBest]->pDbPage, pBt->nPage+iBest+1, 0);

    /* If apNew[i] has a page number that is bigger than any of the
    ** subsequence apNew[i] entries, then swap apNew[i] with the subsequent
    ** entry that has the smallest page number (which we know to be
    ** entry apNew[iB]).
    */
    if( iB!=i ){
      Pgno pgnoA = apNew[i]->pgno;
      Pgno pgnoB = apNew[iB]->pgno;
      Pgno pgnoTemp = (PENDING_BYTE/pBt->pageSize)+1;
      u16 fgA = apNew[i]->pDbPage->flags;
      u16 fgB = apNew[iB]->pDbPage->flags;
      sqlite3PagerRekey(apNew[i]->pDbPage, pgnoTemp, fgB);
      sqlite3PagerRekey(apNew[iB]->pDbPage, pgnoA, fgA);
      }
      sqlite3PagerRekey(apNew[i]->pDbPage, pgno, aPgFlags[iBest]);
      apNew[i]->pgno = pgno;
      sqlite3PagerRekey(apNew[i]->pDbPage, pgnoB, fgB);
      apNew[i]->pgno = pgnoB;
      apNew[iB]->pgno = pgnoA;
    }
  }

  TRACE(("BALANCE: new: %d(%d nc=%d) %d(%d nc=%d) %d(%d nc=%d) "
         "%d(%d nc=%d) %d(%d nc=%d)\n",
    apNew[0]->pgno, szNew[0], cntNew[0],
    nNew>=2 ? apNew[1]->pgno : 0, nNew>=2 ? szNew[1] : 0,
    nNew>=2 ? cntNew[1] - cntNew[0] - !leafData : 0,
    nNew>=3 ? apNew[2]->pgno : 0, nNew>=3 ? szNew[2] : 0,
    nNew>=3 ? cntNew[2] - cntNew[1] - !leafData : 0,
    nNew>=4 ? apNew[3]->pgno : 0, nNew>=4 ? szNew[3] : 0,
    nNew>=4 ? cntNew[3] - cntNew[2] - !leafData : 0,
    nNew>=5 ? apNew[4]->pgno : 0, nNew>=5 ? szNew[4] : 0,
    nNew>=5 ? cntNew[4] - cntNew[3] - !leafData : 0
  ));

  assert( sqlite3PagerIswriteable(pParent->pDbPage) );
  assert( nNew>=1 && nNew<=ArraySize(apNew) );
  assert( apNew[nNew-1]!=0 );
  put4byte(pRight, apNew[nNew-1]->pgno);

  /* If the sibling pages are not leaves, ensure that the right-child pointer
  ** of the right-most new sibling page is set to the value that was 
  ** originally in the same field of the right-most old sibling page. */
  if( (pageFlags & PTF_LEAF)==0 && nOld!=nNew ){
    MemPage *pOld = (nNew>nOld ? apNew : apOld)[nOld-1];
8248
8249
8250
8251
8252
8253
8254
8255
8256


8257
8258
8259
8260
8261
8262
8263
8264
8265





8266
8267
8268
8269
8270
8271
8272
8273
8274
8275
8276
8277
8278
8279
8280
8281
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
8865
8866
8867
8868
8869
8870
8871


8872
8873
8874

8875
8876
8877
8878
8879


8880
8881
8882
8883
8884
8885

8886
8887
8888
8889
8890
8891
8892
8893
8894
8895
8896
8897
8898
8899

8900
8901
8902
8903
8904
8905

8906
8907
8908
8909
8910
8911
8912
8913
8914
8915
8916
8917
8918
8919
8920
8921
8922
8923
8924
8925







-
-
+
+

-





-
-
+
+
+
+
+

-














-
+





-
+











+







  **
  ** If the sibling pages are not leaves, then the pointer map entry 
  ** associated with the right-child of each sibling may also need to be 
  ** updated. This happens below, after the sibling pages have been 
  ** populated, not here.
  */
  if( REQUIRE_PTRMAP ){
    MemPage *pNew = apNew[0];
    u8 *aOld = pNew->aData;
    MemPage *pOld;
    MemPage *pNew = pOld = apNew[0];
    int cntOldNext = pNew->nCell + pNew->nOverflow;
    int usableSize = pBt->usableSize;
    int iNew = 0;
    int iOld = 0;

    for(i=0; i<b.nCell; i++){
      u8 *pCell = b.apCell[i];
      if( i==cntOldNext ){
        MemPage *pOld = (++iOld)<nNew ? apNew[iOld] : apOld[iOld];
      while( i==cntOldNext ){
        iOld++;
        assert( iOld<nNew || iOld<nOld );
        assert( iOld>=0 && iOld<NB );
        pOld = iOld<nNew ? apNew[iOld] : apOld[iOld];
        cntOldNext += pOld->nCell + pOld->nOverflow + !leafData;
        aOld = pOld->aData;
      }
      if( i==cntNew[iNew] ){
        pNew = apNew[++iNew];
        if( !leafData ) continue;
      }

      /* Cell pCell is destined for new sibling page pNew. Originally, it
      ** was either part of sibling page iOld (possibly an overflow cell), 
      ** or else the divider cell to the left of sibling page iOld. So,
      ** if sibling page iOld had the same page number as pNew, and if
      ** pCell really was a part of sibling page iOld (not a divider or
      ** overflow cell), we can skip updating the pointer map entries.  */
      if( iOld>=nNew
       || pNew->pgno!=aPgno[iOld]
       || !SQLITE_WITHIN(pCell,aOld,&aOld[usableSize])
       || !SQLITE_WITHIN(pCell,pOld->aData,pOld->aDataEnd)
      ){
        if( !leafCorrection ){
          ptrmapPut(pBt, get4byte(pCell), PTRMAP_BTREE, pNew->pgno, &rc);
        }
        if( cachedCellSize(&b,i)>pNew->minLocal ){
          ptrmapPutOvflPtr(pNew, pCell, &rc);
          ptrmapPutOvflPtr(pNew, pOld, pCell, &rc);
        }
        if( rc ) goto balance_cleanup;
      }
    }
  }

  /* 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;
8336
8337
8338
8339
8340
8341
8342






8343

8344
8345
8346
8347
8348
8349
8350
8955
8956
8957
8958
8959
8960
8961
8962
8963
8964
8965
8966
8967

8968
8969
8970
8971
8972
8973
8974
8975







+
+
+
+
+
+
-
+







        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]<=j && 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);
    rc = insertCell(pParent, nxDiv+i, pCell, sz, pTemp, pNew->pgno);
    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
  ** cells may still to be read. In practice, this means:
8426
8427
8428
8429
8430
8431
8432

8433

8434
8435
8436
8437
8438
8439
8440
9051
9052
9053
9054
9055
9056
9057
9058

9059
9060
9061
9062
9063
9064
9065
9066







+
-
+







    ** by smaller than the child due to the database header, and so all the
    ** free space needs to be up front.
    */
    assert( nNew==1 || CORRUPT_DB );
    rc = defragmentPage(apNew[0], -1);
    testcase( rc!=SQLITE_OK );
    assert( apNew[0]->nFree == 
        (get2byteNotZero(&apNew[0]->aData[5]) - apNew[0]->cellOffset
        (get2byte(&apNew[0]->aData[5])-apNew[0]->cellOffset-apNew[0]->nCell*2)
          - apNew[0]->nCell*2)
      || rc!=SQLITE_OK
    );
    copyNodeContent(apNew[0], pParent, &rc);
    freePage(apNew[0], &rc);
  }else if( REQUIRE_PTRMAP && !leafCorrection ){
    /* Fix the pointer map entries associated with the right-child of each
    ** sibling page. All other pointer map entries have already been taken
8452
8453
8454
8455
8456
8457
8458
8459

8460
8461
8462
8463
8464
8465
8466
9078
9079
9080
9081
9082
9083
9084

9085
9086
9087
9088
9089
9090
9091
9092







-
+







  /* Free any old pages that were not reused as new pages.
  */
  for(i=nNew; i<nOld; i++){
    freePage(apOld[i], &rc);
  }

#if 0
  if( ISAUTOVACUUM && rc==SQLITE_OK && apNew[0]->isInit ){
  if( ISAUTOVACUUM(pBt) && rc==SQLITE_OK && apNew[0]->isInit ){
    /* The ptrmapCheckPages() contains assert() statements that verify that
    ** all pointer map pages are set correctly. This is helpful while 
    ** debugging. This is usually disabled because a corrupt database may
    ** cause an assert() statement to fail.  */
    ptrmapCheckPages(apNew, nNew);
    ptrmapCheckPages(&pParent, 1);
  }
8525
8526
8527
8528
8529
8530
8531
8532

8533
8534
8535
8536
8537
8538
8539
8540
8541
8542
8543
8544
8545
8546
8547
8548
8549
























8550
8551
8552
8553
8554
8555
8556
8557
8558
8559
8560
8561
8562
8563
8564
8565
8566
8567
8568
8569
8570
8571

8572
8573







8574
8575


8576
8577
8578
8579
8580
8581
8582
8583
8584
8585
8586
8587
8588
8589
8590
8591
8592
8593
8594
8595
8596





8597
8598
8599
8600
8601



8602
8603
8604
8605
8606
8607
8608
9151
9152
9153
9154
9155
9156
9157

9158
9159
9160
9161
9162
9163
9164
9165
9166
9167
9168
9169
9170
9171
9172
9173
9174
9175
9176
9177
9178
9179
9180
9181
9182
9183
9184
9185
9186
9187
9188
9189
9190
9191
9192
9193
9194
9195
9196
9197
9198
9199
9200
9201
9202
9203
9204
9205
9206
9207
9208
9209
9210
9211
9212

9213
9214
9215
9216
9217
9218
9219

9220
9221
9222
9223
9224
9225
9226
9227
9228
9229


9230
9231
9232
9233
9234
9235
9236
9237
9238
9239
9240
9241
9242
9243
9244
9245
9246
9247
9248
9249
9250


9251
9252
9253
9254
9255
9256
9257
9258
9259
9260
9261
9262
9263
9264
9265
9266
9267
9268
9269
9270







-
+

















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













-







-
+


+
+
+
+
+
+
+
-
-
+
+



















-
-
+
+
+
+
+





+
+
+







  if( rc ){
    *ppChild = 0;
    releasePage(pChild);
    return rc;
  }
  assert( sqlite3PagerIswriteable(pChild->pDbPage) );
  assert( sqlite3PagerIswriteable(pRoot->pDbPage) );
  assert( pChild->nCell==pRoot->nCell );
  assert( pChild->nCell==pRoot->nCell || CORRUPT_DB );

  TRACE(("BALANCE: copy root %d into %d\n", pRoot->pgno, pChild->pgno));

  /* Copy the overflow cells from pRoot to pChild */
  memcpy(pChild->aiOvfl, pRoot->aiOvfl,
         pRoot->nOverflow*sizeof(pRoot->aiOvfl[0]));
  memcpy(pChild->apOvfl, pRoot->apOvfl,
         pRoot->nOverflow*sizeof(pRoot->apOvfl[0]));
  pChild->nOverflow = pRoot->nOverflow;

  /* Zero the contents of pRoot. Then install pChild as the right-child. */
  zeroPage(pRoot, pChild->aData[0] & ~PTF_LEAF);
  put4byte(&pRoot->aData[pRoot->hdrOffset+8], pgnoChild);

  *ppChild = pChild;
  return SQLITE_OK;
}

/*
** Return SQLITE_CORRUPT if any cursor other than pCur is currently valid
** on the same B-tree as pCur.
**
** This can occur if a database is corrupt with two or more SQL tables
** pointing to the same b-tree.  If an insert occurs on one SQL table
** and causes a BEFORE TRIGGER to do a secondary insert on the other SQL
** table linked to the same b-tree.  If the secondary insert causes a
** rebalance, that can change content out from under the cursor on the
** first SQL table, violating invariants on the first insert.
*/
static int anotherValidCursor(BtCursor *pCur){
  BtCursor *pOther;
  for(pOther=pCur->pBt->pCursor; pOther; pOther=pOther->pNext){
    if( pOther!=pCur
     && pOther->eState==CURSOR_VALID
     && pOther->pPage==pCur->pPage
    ){
      return SQLITE_CORRUPT_BKPT;
    }
  }
  return SQLITE_OK;
}

/*
** The page that pCur currently points to has just been modified in
** some way. This function figures out if this modification means the
** tree needs to be balanced, and if so calls the appropriate balancing 
** routine. Balancing routines are:
**
**   balance_quick()
**   balance_deeper()
**   balance_nonroot()
*/
static int balance(BtCursor *pCur){
  int rc = SQLITE_OK;
  const int nMin = pCur->pBt->usableSize * 2 / 3;
  u8 aBalanceQuickSpace[13];
  u8 *pFree = 0;

  VVA_ONLY( int balance_quick_called = 0 );
  VVA_ONLY( int balance_deeper_called = 0 );

  do {
    int iPage = pCur->iPage;
    int iPage;
    MemPage *pPage = pCur->pPage;

    if( NEVER(pPage->nFree<0) && btreeComputeFreeSpace(pPage) ) break;
    if( pPage->nOverflow==0 && pPage->nFree*3<=(int)pCur->pBt->usableSize*2 ){
      /* No rebalance required as long as:
      **   (1) There are no overflow cells
      **   (2) The amount of free space on the page is less than 2/3rds of
      **       the total usable space on the page. */
      break;
    if( iPage==0 ){
      if( pPage->nOverflow ){
    }else if( (iPage = pCur->iPage)==0 ){
      if( pPage->nOverflow && (rc = anotherValidCursor(pCur))==SQLITE_OK ){
        /* The root page of the b-tree is overfull. In this case call the
        ** balance_deeper() function to create a new child for the root-page
        ** and copy the current contents of the root-page to it. The
        ** next iteration of the do-loop will balance the child page.
        */ 
        assert( balance_deeper_called==0 );
        VVA_ONLY( balance_deeper_called++ );
        rc = balance_deeper(pPage, &pCur->apPage[1]);
        if( rc==SQLITE_OK ){
          pCur->iPage = 1;
          pCur->ix = 0;
          pCur->aiIdx[0] = 0;
          pCur->apPage[0] = pPage;
          pCur->pPage = pCur->apPage[1];
          assert( pCur->pPage->nOverflow );
        }
      }else{
        break;
      }
    }else if( pPage->nOverflow==0 && pPage->nFree<=nMin ){
      break;
    }else if( sqlite3PagerPageRefcount(pPage->pDbPage)>1 ){
      /* The page being written is not a root page, and there is currently
      ** more than one reference to it. This only happens if the page is one 
      ** of its own ancestor pages. Corruption. */
      rc = SQLITE_CORRUPT_BKPT;
    }else{
      MemPage * const pParent = pCur->apPage[iPage-1];
      int const iIdx = pCur->aiIdx[iPage-1];

      rc = sqlite3PagerWrite(pParent->pDbPage);
      if( rc==SQLITE_OK && pParent->nFree<0 ){
        rc = btreeComputeFreeSpace(pParent);
      }
      if( rc==SQLITE_OK ){
#ifndef SQLITE_OMIT_QUICKBALANCE
        if( pPage->intKeyLeaf
         && pPage->nOverflow==1
         && pPage->aiOvfl[0]==pPage->nCell
         && pParent->pgno!=1
         && pParent->nCell==iIdx
8705
8706
8707
8708
8709
8710
8711




8712

8713
8714
8715
8716
8717
8718
8719
8720


8721


8722


8723
8724
8725
8726
8727
8728
8729
8730
8731

8732
8733

8734
8735
8736
8737
8738
8739
8740
8741
8742
8743
8744
8745
8746
8747
8748
8749
8750

8751
8752
8753
8754
8755
8756
8757
8758
8759
8760
8761
8762
8763
8764
8765
8766























8767
8768
8769
8770
8771
8772
8773
8774
8775
8776
8777
8778
8779
8780
8781
8782
8783
8784
8785

8786
8787
8788
8789
8790
8791
8792
8793
8794
8795
8796
8797
8798
8799
8800
8801
8802
8803

8804
8805
8806
8807
8808
8809
8810
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
8836
8837
8838
8839
8840
8841
8842
8843
8844
8845
8846
8847

8848







8849
8850


























8851
8852
8853
8854

8855


8856
8857
8858
8859
8860
8861
8862
8863
8864
8865
8866
8867
8868
8869
8870
8871
9367
9368
9369
9370
9371
9372
9373
9374
9375
9376
9377

9378
9379
9380
9381
9382
9383
9384
9385

9386
9387
9388
9389
9390

9391
9392
9393
9394
9395
9396
9397
9398
9399
9400

9401


9402
9403
9404
9405
9406

9407
9408
9409
9410
9411
9412
9413
9414
9415
9416
9417

9418
9419
9420
9421
9422
9423
9424
9425
9426
9427
9428
9429
9430
9431
9432
9433
9434
9435
9436
9437
9438
9439
9440
9441
9442
9443
9444
9445
9446
9447
9448
9449
9450
9451
9452
9453
9454
9455
9456
9457
9458
9459
9460
9461
9462
9463
9464
9465
9466
9467
9468
9469
9470
9471
9472
9473
9474
9475

9476
9477
9478
9479
9480
9481
9482
9483
9484
9485
9486
9487
9488
9489
9490
9491
9492
9493

9494
9495
9496
9497
9498
9499
9500
9501

9502
9503
9504


9505
9506

















9507
9508
9509
9510
9511
9512
9513
9514
9515
9516
9517
9518
9519

9520
9521
9522
9523
9524
9525
9526
9527
9528


9529
9530
9531
9532
9533
9534
9535
9536
9537
9538
9539
9540
9541
9542
9543
9544
9545
9546
9547
9548
9549
9550
9551
9552
9553
9554
9555
9556
9557
9558
9559

9560
9561
9562
9563
9564
9565
9566
9567
9568
9569

9570
9571
9572
9573
9574
9575
9576







+
+
+
+
-
+







-
+
+

+
+
-
+
+








-
+
-
-
+




-











-
+
















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


















-
+

















-
+







-



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













-
+

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




+
-
+
+








-







                                 iAmt-nData);
      if( rc ) return rc;
      iAmt = nData;
    }
    if( memcmp(pDest, ((u8*)pX->pData) + iOffset, iAmt)!=0 ){
      int rc = sqlite3PagerWrite(pPage->pDbPage);
      if( rc ) return rc;
      /* In a corrupt database, it is possible for the source and destination
      ** buffers to overlap.  This is harmless since the database is already
      ** corrupt but it does cause valgrind and ASAN warnings.  So use
      ** memmove(). */
      memcpy(pDest, ((u8*)pX->pData) + iOffset, iAmt);
      memmove(pDest, ((u8*)pX->pData) + iOffset, iAmt);
    }
  }
  return SQLITE_OK;
}

/*
** Overwrite the cell that cursor pCur is pointing to with fresh content
** contained in pX.
** contained in pX.  In this variant, pCur is pointing to an overflow
** cell.
*/
static SQLITE_NOINLINE int btreeOverwriteOverflowCell(
  BtCursor *pCur,                     /* Cursor pointing to cell to ovewrite */
static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){
  const BtreePayload *pX              /* Content to write into the cell */
){
  int iOffset;                        /* Next byte of pX->pData to write */
  int nTotal = pX->nData + pX->nZero; /* Total bytes of to write */
  int rc;                             /* Return code */
  MemPage *pPage = pCur->pPage;       /* Page being written */
  BtShared *pBt;                      /* Btree */
  Pgno ovflPgno;                      /* Next overflow page to write */
  u32 ovflPageSize;                   /* Size to write on overflow page */

  if( pCur->info.pPayload + pCur->info.nLocal > pPage->aDataEnd ){
  assert( pCur->info.nLocal<nTotal );  /* pCur is an overflow cell */
    return SQLITE_CORRUPT_BKPT;
  }

  /* Overwrite the local portion first */
  rc = btreeOverwriteContent(pPage, pCur->info.pPayload, pX,
                             0, pCur->info.nLocal);
  if( rc ) return rc;
  if( pCur->info.nLocal==nTotal ) return SQLITE_OK;

  /* Now overwrite the overflow pages */
  iOffset = pCur->info.nLocal;
  assert( nTotal>=0 );
  assert( iOffset>=0 );
  ovflPgno = get4byte(pCur->info.pPayload + iOffset);
  pBt = pPage->pBt;
  ovflPageSize = pBt->usableSize - 4;
  do{
    rc = btreeGetPage(pBt, ovflPgno, &pPage, 0);
    if( rc ) return rc;
    if( sqlite3PagerPageRefcount(pPage->pDbPage)!=1 ){
    if( sqlite3PagerPageRefcount(pPage->pDbPage)!=1 || pPage->isInit ){
      rc = SQLITE_CORRUPT_BKPT;
    }else{
      if( iOffset+ovflPageSize<(u32)nTotal ){
        ovflPgno = get4byte(pPage->aData);
      }else{
        ovflPageSize = nTotal - iOffset;
      }
      rc = btreeOverwriteContent(pPage, pPage->aData+4, pX,
                                 iOffset, ovflPageSize);
    }
    sqlite3PagerUnref(pPage->pDbPage);
    if( rc ) return rc;
    iOffset += ovflPageSize;
  }while( iOffset<nTotal );
  return SQLITE_OK;    
}

/*
** Overwrite the cell that cursor pCur is pointing to with fresh content
** contained in pX.
*/
static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){
  int nTotal = pX->nData + pX->nZero; /* Total bytes of to write */
  MemPage *pPage = pCur->pPage;       /* Page being written */

  if( pCur->info.pPayload + pCur->info.nLocal > pPage->aDataEnd
   || pCur->info.pPayload < pPage->aData + pPage->cellOffset
  ){
    return SQLITE_CORRUPT_BKPT;
  }
  if( pCur->info.nLocal==nTotal ){
    /* The entire cell is local */
    return btreeOverwriteContent(pPage, pCur->info.pPayload, pX,
                                 0, pCur->info.nLocal);
  }else{
    /* The cell contains overflow content */
    return btreeOverwriteOverflowCell(pCur, pX);
  }
}


/*
** Insert a new record into the BTree.  The content of the new record
** is described by the pX object.  The pCur cursor is used only to
** define what table the record should be inserted into, and is left
** pointing at a random location.
**
** For a table btree (used for rowid tables), only the pX.nKey value of
** the key is used. The pX.pKey value must be NULL.  The pX.nKey is the
** rowid or INTEGER PRIMARY KEY of the row.  The pX.nData,pData,nZero fields
** hold the content of the row.
**
** For an index btree (used for indexes and WITHOUT ROWID tables), the
** key is an arbitrary byte sequence stored in pX.pKey,nKey.  The 
** pX.pData,nData,nZero fields must be zero.
**
** If the seekResult parameter is non-zero, then a successful call to
** MovetoUnpacked() to seek cursor pCur to (pKey,nKey) has already
** sqlite3BtreeIndexMoveto() to seek cursor pCur to (pKey,nKey) has already
** been performed.  In other words, if seekResult!=0 then the cursor
** is currently pointing to a cell that will be adjacent to the cell
** to be inserted.  If seekResult<0 then pCur points to a cell that is
** smaller then (pKey,nKey).  If seekResult>0 then pCur points to a cell
** that is larger than (pKey,nKey).
**
** If seekResult==0, that means pCur is pointing at some unknown location.
** In that case, this routine must seek the cursor to the correct insertion
** point for (pKey,nKey) before doing the insertion.  For index btrees,
** if pX->nMem is non-zero, then pX->aMem contains pointers to the unpacked
** key values and pX->aMem can be used instead of pX->pKey to avoid having
** to decode the key.
*/
int sqlite3BtreeInsert(
  BtCursor *pCur,                /* Insert data into the table of this cursor */
  const BtreePayload *pX,        /* Content of the row to be inserted */
  int flags,                     /* True if this is likely an append */
  int seekResult                 /* Result of prior MovetoUnpacked() call */
  int seekResult                 /* Result of prior IndexMoveto() call */
){
  int rc;
  int loc = seekResult;          /* -1: before desired location  +1: after */
  int szNew = 0;
  int idx;
  MemPage *pPage;
  Btree *p = pCur->pBtree;
  BtShared *pBt = p->pBt;
  unsigned char *oldCell;
  unsigned char *newCell = 0;

  assert( (flags & (BTREE_SAVEPOSITION|BTREE_APPEND))==flags );

  assert( (flags & (BTREE_SAVEPOSITION|BTREE_APPEND|BTREE_PREFORMAT))==flags );
  assert( (flags & BTREE_PREFORMAT)==0 || seekResult || pCur->pKeyInfo==0 );
  if( pCur->eState==CURSOR_FAULT ){
    assert( pCur->skipNext!=SQLITE_OK );
    return pCur->skipNext;
  }

  assert( cursorOwnsBtShared(pCur) );
  assert( (pCur->curFlags & BTCF_WriteFlag)!=0
              && pBt->inTransaction==TRANS_WRITE
              && (pBt->btsFlags & BTS_READ_ONLY)==0 );
  assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );

  /* Assert that the caller has been consistent. If this cursor was opened
  ** expecting an index b-tree, then the caller should be inserting blob
  ** keys with no associated data. If the cursor was opened expecting an
  ** intkey table, the caller should be inserting integer keys with a
  ** blob of associated data.  */
  assert( (pX->pKey==0)==(pCur->pKeyInfo==0) );

  /* Save the positions of any other cursors open on this table.
  **
  ** In some cases, the call to btreeMoveto() below is a no-op. For
  ** example, when inserting data into a table with auto-generated integer
  ** keys, the VDBE layer invokes sqlite3BtreeLast() to figure out the 
  ** integer key to use. It then calls this function to actually insert the 
  ** data into the intkey B-Tree. In this case btreeMoveto() recognizes
  ** 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);
    rc = saveAllCursors(p->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;
  }

    }
  }

  /* Ensure that the cursor is not in the CURSOR_FAULT state and that it
  ** points to a valid cell.
  */
  if( pCur->eState>=CURSOR_REQUIRESEEK ){
    testcase( pCur->eState==CURSOR_REQUIRESEEK );
    testcase( pCur->eState==CURSOR_FAULT );
    rc = moveToRoot(pCur);
    if( rc && rc!=SQLITE_EMPTY ) return rc;
  }

  assert( cursorOwnsBtShared(pCur) );
  assert( (pCur->curFlags & BTCF_WriteFlag)!=0
              && p->pBt->inTransaction==TRANS_WRITE
              && (p->pBt->btsFlags & BTS_READ_ONLY)==0 );
  assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );

  /* Assert that the caller has been consistent. If this cursor was opened
  ** expecting an index b-tree, then the caller should be inserting blob
  ** keys with no associated data. If the cursor was opened expecting an
  ** intkey table, the caller should be inserting integer keys with a
  ** blob of associated data.  */
  assert( (flags & BTREE_PREFORMAT) || (pX->pKey==0)==(pCur->pKeyInfo==0) );

  if( pCur->pKeyInfo==0 ){
    assert( pX->pKey==0 );
    /* If this is an insert into a table b-tree, invalidate any incrblob 
    ** cursors open on the row being replaced */
    if( p->hasIncrblobCur ){
    invalidateIncrblobCursors(p, pCur->pgnoRoot, pX->nKey, 0);
      invalidateIncrblobCursors(p, pCur->pgnoRoot, pX->nKey, 0);
    }

    /* If BTREE_SAVEPOSITION is set, the cursor must already be pointing 
    ** to a row with the same key as the new entry being inserted.
    */
#ifdef SQLITE_DEBUG
    if( flags & BTREE_SAVEPOSITION ){
      assert( pCur->curFlags & BTCF_ValidNKey );
      assert( pX->nKey==pCur->info.nKey );
      assert( pCur->info.nSize!=0 );
      assert( loc==0 );
    }
#endif

    /* On the other hand, BTREE_SAVEPOSITION==0 does not imply
    ** that the cursor is not pointing to a row to be overwritten.
    ** So do a complete check.
8882
8883
8884
8885
8886
8887
8888
8889


8890
8891
8892
8893
8894
8895
8896
9587
9588
9589
9590
9591
9592
9593

9594
9595
9596
9597
9598
9599
9600
9601
9602







-
+
+







      }
      assert( loc==0 );
    }else if( loc==0 ){
      /* The cursor is *not* pointing to the cell to be overwritten, nor
      ** to an adjacent cell.  Move the cursor so that it is pointing either
      ** to the cell to be overwritten or an adjacent cell.
      */
      rc = sqlite3BtreeMovetoUnpacked(pCur, 0, pX->nKey, flags!=0, &loc);
      rc = sqlite3BtreeTableMoveto(pCur, pX->nKey, 
               (flags & BTREE_APPEND)!=0, &loc);
      if( rc ) return rc;
    }
  }else{
    /* This is an index or a WITHOUT ROWID table */

    /* If BTREE_SAVEPOSITION is set, the cursor must already be pointing 
    ** to a row with the same key as the new entry being inserted.
8905
8906
8907
8908
8909
8910
8911
8912
8913
8914
8915
8916

8917
8918


8919
8920
8921
8922
8923
8924
8925
8926
8927
8928
8929
8930
8931
8932
8933
8934
8935
8936
8937

8938
8939


8940
8941
8942

8943









8944
8945
8946
8947
8948
8949


8950















8951
8952



8953
8954

8955
8956
8957

8958




8959
8960
8961
8962
8963
8964
8965
8966
8967



8968
8969
8970
8971
8972
8973
8974
8975
8976
8977
8978
8979
8980



8981



8982
8983
8984
8985
8986
8987
8988
8989
8990
8991
8992
8993
8994

8995
8996
8997
8998
8999
9000
9001
9611
9612
9613
9614
9615
9616
9617



9618

9619
9620

9621
9622
9623
9624
9625
9626
9627
9628
9629
9630
9631
9632
9633
9634
9635
9636
9637
9638
9639
9640

9641


9642
9643
9644
9645

9646
9647
9648
9649
9650
9651
9652
9653
9654
9655
9656
9657
9658
9659
9660


9661
9662
9663
9664
9665
9666
9667
9668
9669
9670
9671
9672
9673
9674
9675
9676
9677
9678


9679
9680
9681
9682

9683
9684
9685
9686
9687

9688
9689
9690
9691
9692
9693
9694
9695
9696
9697
9698
9699

9700
9701
9702
9703
9704
9705
9706
9707
9708
9709
9710
9711
9712
9713
9714
9715
9716
9717
9718

9719
9720
9721
9722
9723
9724
9725
9726
9727
9728
9729
9730
9731
9732
9733

9734
9735
9736
9737
9738
9739
9740
9741







-
-
-

-
+

-
+
+


















-
+
-
-
+
+


-
+

+
+
+
+
+
+
+
+
+




-
-
+
+

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

-
+



+
-
+
+
+
+








-
+
+
+













+
+
+
-
+
+
+












-
+







    if( loc==0 && (flags & BTREE_SAVEPOSITION)==0 ){
      if( pX->nMem ){
        UnpackedRecord r;
        r.pKeyInfo = pCur->pKeyInfo;
        r.aMem = pX->aMem;
        r.nField = pX->nMem;
        r.default_rc = 0;
        r.errCode = 0;
        r.r1 = 0;
        r.r2 = 0;
        r.eqSeen = 0;
        rc = sqlite3BtreeMovetoUnpacked(pCur, &r, 0, flags!=0, &loc);
        rc = sqlite3BtreeIndexMoveto(pCur, &r, &loc);
      }else{
        rc = btreeMoveto(pCur, pX->pKey, pX->nKey, flags!=0, &loc);
        rc = btreeMoveto(pCur, pX->pKey, pX->nKey, 
                    (flags & BTREE_APPEND)!=0, &loc);
      }
      if( rc ) return rc;
    }

    /* If the cursor is currently pointing to an entry to be overwritten
    ** and the new content is the same as as the old, then use the
    ** overwrite optimization.
    */
    if( loc==0 ){
      getCellInfo(pCur);
      if( pCur->info.nKey==pX->nKey ){
        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) );
  assert( pCur->eState==CURSOR_VALID 
       || (pCur->eState==CURSOR_INVALID && loc) );

  pPage = pCur->pPage;
  assert( pPage->intKey || pX->nKey>=0 );
  assert( pPage->intKey || pX->nKey>=0 || (flags & BTREE_PREFORMAT) );
  assert( pPage->leaf || !pPage->intKey );
  if( pPage->nFree<0 ){
    if( NEVER(pCur->eState>CURSOR_INVALID) ){
     /* ^^^^^--- due to the moveToRoot() call above */
      rc = SQLITE_CORRUPT_BKPT;
    }else{
      rc = btreeComputeFreeSpace(pPage);
    }
    if( rc ) return rc;
  }

  TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n",
          pCur->pgnoRoot, pX->nKey, pX->nData, pPage->pgno,
          loc==0 ? "overwrite" : "new entry"));
  assert( pPage->isInit );
  newCell = pBt->pTmpSpace;
  assert( pPage->isInit || CORRUPT_DB );
  newCell = p->pBt->pTmpSpace;
  assert( newCell!=0 );
  assert( BTREE_PREFORMAT==OPFLAG_PREFORMAT );
  if( flags & BTREE_PREFORMAT ){
    rc = SQLITE_OK;
    szNew = p->pBt->nPreformatSize;
    if( szNew<4 ) szNew = 4;
    if( ISAUTOVACUUM(p->pBt) && szNew>pPage->maxLocal ){
      CellInfo info;
      pPage->xParseCell(pPage, newCell, &info);
      if( info.nPayload!=info.nLocal ){
        Pgno ovfl = get4byte(&newCell[szNew-4]);
        ptrmapPut(p->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno, &rc);
        if( NEVER(rc) ) goto end_insert;
      }
    }
  }else{
  rc = fillInCell(pPage, newCell, pX, &szNew);
  if( rc ) goto end_insert;
    rc = fillInCell(pPage, newCell, pX, &szNew);
    if( rc ) goto end_insert;
  }
  assert( szNew==pPage->xCellSize(pPage, newCell) );
  assert( szNew <= MX_CELL_SIZE(pBt) );
  assert( szNew <= MX_CELL_SIZE(p->pBt) );
  idx = pCur->ix;
  if( loc==0 ){
    CellInfo info;
    BtShared *pBt = p->pBt;
    assert( idx<pPage->nCell );
    assert( idx>=0 );
    if( idx>=pPage->nCell ){
      return SQLITE_CORRUPT_BKPT;
    }
    rc = sqlite3PagerWrite(pPage->pDbPage);
    if( rc ){
      goto end_insert;
    }
    oldCell = findCell(pPage, idx);
    if( !pPage->leaf ){
      memcpy(newCell, oldCell, 4);
    }
    rc = clearCell(pPage, oldCell, &info);
    BTREE_CLEAR_CELL(rc, pPage, oldCell, info);
    testcase( pCur->curFlags & BTCF_ValidOvfl );
    invalidateOverflowCache(pCur);
    if( info.nSize==szNew && info.nLocal==info.nPayload 
     && (!REQUIRE_PTRMAP || szNew<pPage->minLocal)
    ){
      /* Overwrite the old cell with the new if they are the same size.
      ** We could also try to do this if the old cell is smaller, then add
      ** the leftover space to the free list.  But experiments show that
      ** doing that is no faster then skipping this optimization and just
      ** calling dropCell() and insertCell(). 
      **
      ** This optimization cannot be used on an autovacuum database if the
      ** new entry uses overflow pages, as the insertCell() call below is
      ** necessary to add the PTRMAP_OVERFLOW1 pointer-map entry.  */
      assert( rc==SQLITE_OK ); /* clearCell never fails when nLocal==nPayload */
      if( oldCell < pPage->aData+pPage->hdrOffset+10 ){
        return SQLITE_CORRUPT_BKPT;
      }
      if( oldCell+szNew > pPage->aDataEnd ) return SQLITE_CORRUPT_BKPT;
      if( oldCell+szNew > pPage->aDataEnd ){
        return SQLITE_CORRUPT_BKPT;
      }
      memcpy(oldCell, newCell, szNew);
      return SQLITE_OK;
    }
    dropCell(pPage, idx, info.nSize, &rc);
    if( rc ) goto end_insert;
  }else if( loc<0 && pPage->nCell>0 ){
    assert( pPage->leaf );
    idx = ++pCur->ix;
    pCur->curFlags &= ~BTCF_ValidNKey;
  }else{
    assert( pPage->leaf );
  }
  insertCell(pPage, idx, newCell, szNew, 0, 0, &rc);
  rc = insertCell(pPage, idx, newCell, szNew, 0, 0);
  assert( pPage->nOverflow==0 || rc==SQLITE_OK );
  assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 );

  /* If no error has occurred and pPage has an overflow cell, call balance() 
  ** to redistribute the cells within the tree. Since balance() may move
  ** the cursor, zero the BtCursor.info.nSize and BTCF_ValidNKey
  ** variables.
9043
9044
9045
9046
9047
9048
9049
















































































































9050
9051
9052
9053
9054
9055
9056
9783
9784
9785
9786
9787
9788
9789
9790
9791
9792
9793
9794
9795
9796
9797
9798
9799
9800
9801
9802
9803
9804
9805
9806
9807
9808
9809
9810
9811
9812
9813
9814
9815
9816
9817
9818
9819
9820
9821
9822
9823
9824
9825
9826
9827
9828
9829
9830
9831
9832
9833
9834
9835
9836
9837
9838
9839
9840
9841
9842
9843
9844
9845
9846
9847
9848
9849
9850
9851
9852
9853
9854
9855
9856
9857
9858
9859
9860
9861
9862
9863
9864
9865
9866
9867
9868
9869
9870
9871
9872
9873
9874
9875
9876
9877
9878
9879
9880
9881
9882
9883
9884
9885
9886
9887
9888
9889
9890
9891
9892
9893
9894
9895
9896
9897
9898
9899
9900
9901
9902
9903
9904
9905
9906
9907
9908







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







    }
  }
  assert( pCur->iPage<0 || pCur->pPage->nOverflow==0 );

end_insert:
  return rc;
}

/*
** This function is used as part of copying the current row from cursor
** pSrc into cursor pDest. If the cursors are open on intkey tables, then
** parameter iKey is used as the rowid value when the record is copied
** into pDest. Otherwise, the record is copied verbatim.
**
** This function does not actually write the new value to cursor pDest.
** Instead, it creates and populates any required overflow pages and
** writes the data for the new cell into the BtShared.pTmpSpace buffer
** for the destination database. The size of the cell, in bytes, is left
** in BtShared.nPreformatSize. The caller completes the insertion by
** calling sqlite3BtreeInsert() with the BTREE_PREFORMAT flag specified.
**
** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
*/
int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64 iKey){
  BtShared *pBt = pDest->pBt;
  u8 *aOut = pBt->pTmpSpace;    /* Pointer to next output buffer */
  const u8 *aIn;                /* Pointer to next input buffer */
  u32 nIn;                      /* Size of input buffer aIn[] */
  u32 nRem;                     /* Bytes of data still to copy */

  getCellInfo(pSrc);
  if( pSrc->info.nPayload<0x80 ){
    *(aOut++) = pSrc->info.nPayload;
  }else{
    aOut += sqlite3PutVarint(aOut, pSrc->info.nPayload);
  }
  if( pDest->pKeyInfo==0 ) aOut += putVarint(aOut, iKey);
  nIn = pSrc->info.nLocal;
  aIn = pSrc->info.pPayload;
  if( aIn+nIn>pSrc->pPage->aDataEnd ){
    return SQLITE_CORRUPT_BKPT;
  }
  nRem = pSrc->info.nPayload;
  if( nIn==nRem && nIn<pDest->pPage->maxLocal ){
    memcpy(aOut, aIn, nIn);
    pBt->nPreformatSize = nIn + (aOut - pBt->pTmpSpace);
    return SQLITE_OK;
  }else{
    int rc = SQLITE_OK;
    Pager *pSrcPager = pSrc->pBt->pPager;
    u8 *pPgnoOut = 0;
    Pgno ovflIn = 0;
    DbPage *pPageIn = 0;
    MemPage *pPageOut = 0;
    u32 nOut;                     /* Size of output buffer aOut[] */

    nOut = btreePayloadToLocal(pDest->pPage, pSrc->info.nPayload);
    pBt->nPreformatSize = nOut + (aOut - pBt->pTmpSpace);
    if( nOut<pSrc->info.nPayload ){
      pPgnoOut = &aOut[nOut];
      pBt->nPreformatSize += 4;
    }
  
    if( nRem>nIn ){
      if( aIn+nIn+4>pSrc->pPage->aDataEnd ){
        return SQLITE_CORRUPT_BKPT;
      }
      ovflIn = get4byte(&pSrc->info.pPayload[nIn]);
    }
  
    do {
      nRem -= nOut;
      do{
        assert( nOut>0 );
        if( nIn>0 ){
          int nCopy = MIN(nOut, nIn);
          memcpy(aOut, aIn, nCopy);
          nOut -= nCopy;
          nIn -= nCopy;
          aOut += nCopy;
          aIn += nCopy;
        }
        if( nOut>0 ){
          sqlite3PagerUnref(pPageIn);
          pPageIn = 0;
          rc = sqlite3PagerGet(pSrcPager, ovflIn, &pPageIn, PAGER_GET_READONLY);
          if( rc==SQLITE_OK ){
            aIn = (const u8*)sqlite3PagerGetData(pPageIn);
            ovflIn = get4byte(aIn);
            aIn += 4;
            nIn = pSrc->pBt->usableSize - 4;
          }
        }
      }while( rc==SQLITE_OK && nOut>0 );
  
      if( rc==SQLITE_OK && nRem>0 && ALWAYS(pPgnoOut) ){
        Pgno pgnoNew;
        MemPage *pNew = 0;
        rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0);
        put4byte(pPgnoOut, pgnoNew);
        if( ISAUTOVACUUM(pBt) && pPageOut ){
          ptrmapPut(pBt, pgnoNew, PTRMAP_OVERFLOW2, pPageOut->pgno, &rc);
        }
        releasePage(pPageOut);
        pPageOut = pNew;
        if( pPageOut ){
          pPgnoOut = pPageOut->aData;
          put4byte(pPgnoOut, 0);
          aOut = &pPgnoOut[4];
          nOut = MIN(pBt->usableSize - 4, nRem);
        }
      }
    }while( nRem>0 && rc==SQLITE_OK );
  
    releasePage(pPageOut);
    sqlite3PagerUnref(pPageIn);
    return rc;
  }
}

/*
** Delete the entry that the cursor is pointing to. 
**
** If the BTREE_SAVEPOSITION bit of the flags parameter is zero, then
** the cursor is left pointing at an arbitrary location after the delete.
** But if that bit is set, then the cursor is left in a state such that
9064
9065
9066
9067
9068
9069
9070
9071
9072
9073
9074
9075
9076






9077
9078

9079
9080
9081
9082
9083
9084
9085

9086









9087
9088
9089
9090
9091
9092



9093


9094
9095



9096
9097
9098
9099
9100
9101

9102
9103









9104
9105

9106

9107
9108
9109
9110
9111
9112
9113
9114

9115
9116
9117
9118
9119
9120
9121
9916
9917
9918
9919
9920
9921
9922






9923
9924
9925
9926
9927
9928


9929
9930
9931
9932
9933
9934
9935
9936
9937

9938
9939
9940
9941
9942
9943
9944
9945
9946
9947

9948
9949
9950
9951
9952
9953
9954
9955
9956
9957


9958
9959
9960
9961
9962
9963
9964
9965

9966
9967

9968
9969
9970
9971
9972
9973
9974
9975
9976
9977
9978
9979

9980
9981
9982
9983
9984
9985
9986
9987

9988
9989
9990
9991
9992
9993
9994
9995







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







+
-
+
+
+
+
+
+
+
+
+

-




+
+
+

+
+
-
-
+
+
+





-
+

-
+
+
+
+
+
+
+
+
+


+
-
+







-
+







** operation on non-FORDELETE cursors is tagged with the AUXDELETE flag.
** The BTREE_AUXDELETE bit is a hint that is not used by this implementation,
** but which might be used by alternative storage engines.
*/
int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
  Btree *p = pCur->pBtree;
  BtShared *pBt = p->pBt;              
  int rc;                              /* Return code */
  MemPage *pPage;                      /* Page to delete cell from */
  unsigned char *pCell;                /* Pointer to cell to delete */
  int iCellIdx;                        /* Index of cell to delete */
  int iCellDepth;                      /* Depth of node containing pCell */ 
  CellInfo info;                       /* Size of the cell being deleted */
  int rc;                    /* Return code */
  MemPage *pPage;            /* Page to delete cell from */
  unsigned char *pCell;      /* Pointer to cell to delete */
  int iCellIdx;              /* Index of cell to delete */
  int iCellDepth;            /* Depth of node containing pCell */ 
  CellInfo info;             /* Size of the cell being deleted */
  int bSkipnext = 0;                   /* Leaf cursor in SKIPNEXT state */
  u8 bPreserve = flags & BTREE_SAVEPOSITION;  /* Keep cursor valid */
  u8 bPreserve;              /* Keep cursor valid.  2 for CURSOR_SKIPNEXT */

  assert( cursorOwnsBtShared(pCur) );
  assert( pBt->inTransaction==TRANS_WRITE );
  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 );
  assert( pCur->ix<pCur->pPage->nCell );
  if( pCur->eState!=CURSOR_VALID ){
    if( pCur->eState>=CURSOR_REQUIRESEEK ){
      rc = btreeRestoreCursorPosition(pCur);
      assert( rc!=SQLITE_OK || CORRUPT_DB || pCur->eState==CURSOR_VALID );
      if( rc || pCur->eState!=CURSOR_VALID ) return rc;
    }else{
      return SQLITE_CORRUPT_BKPT;
    }
  }
  assert( pCur->eState==CURSOR_VALID );
  assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 );

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

  /* If the bPreserve flag is set to true, then the cursor position must
  }

  /* If the BTREE_SAVEPOSITION bit is on, then the cursor position must
  ** be preserved following this delete operation. If the current delete
  ** will cause a b-tree rebalance, then this is done by saving the cursor
  ** key and leaving the cursor in CURSOR_REQUIRESEEK state before 
  ** returning. 
  **
  ** Or, if the current delete will not cause a rebalance, then the cursor
  ** If the current delete will not cause a rebalance, then the cursor
  ** will be left in CURSOR_SKIPNEXT state pointing to the entry immediately
  ** before or after the deleted entry. In this case set bSkipnext to true.  */
  ** before or after the deleted entry.
  **
  ** The bPreserve value records which path is required:
  **
  **    bPreserve==0         Not necessary to save the cursor position
  **    bPreserve==1         Use CURSOR_REQUIRESEEK to save the cursor position
  **    bPreserve==2         Cursor won't move.  Set CURSOR_SKIPNEXT.
  */
  bPreserve = (flags & BTREE_SAVEPOSITION)!=0;
  if( bPreserve ){
    if( !pPage->leaf 
     || (pPage->nFree+pPage->xCellSize(pPage,pCell)+2) >
     || (pPage->nFree+cellSizePtr(pPage,pCell)+2)>(int)(pBt->usableSize*2/3)
                                                   (int)(pBt->usableSize*2/3)
     || pPage->nCell==1  /* See dbfuzz001.test for a test case */
    ){
      /* A b-tree rebalance will be required after deleting this entry.
      ** Save the cursor key.  */
      rc = saveCursorKey(pCur);
      if( rc ) return rc;
    }else{
      bSkipnext = 1;
      bPreserve = 2;
    }
  }

  /* If the page containing the entry to delete is not a leaf page, move
  ** the cursor to the largest entry in the tree that is smaller than
  ** the entry being deleted. This cell will replace the cell being deleted
  ** from the internal node. The 'previous' entry is used for this instead
9133
9134
9135
9136
9137
9138
9139
9140

9141
9142
9143
9144
9145
9146
9147
9148
9149

9150
9151
9152
9153
9154
9155
9156
9157
9158
9159
9160
9161
9162
9163




9164
9165
9166
9167
9168
9169
9170
9171
9172
9173
9174
9175
9176
9177

9178
9179
9180
9181
9182
9183
9184
9185
9186
9187
9188
9189
9190
9191
9192
9193
9194
9195
9196
9197







9198


9199
9200
9201
9202
9203
9204
9205
9206
9207
9208
9209
9210
9211


9212
9213
9214
9215
9216
9217
9218
10007
10008
10009
10010
10011
10012
10013

10014
10015
10016
10017
10018
10019
10020
10021
10022

10023
10024
10025
10026
10027
10028
10029
10030
10031
10032
10033
10034
10035
10036
10037
10038
10039
10040
10041
10042
10043
10044
10045
10046
10047
10048
10049
10050
10051
10052
10053
10054

10055
10056
10057
10058
10059
10060
10061
10062
10063
10064
10065
10066
10067
10068
10069
10070
10071
10072
10073
10074
10075
10076
10077
10078
10079
10080
10081
10082

10083
10084
10085
10086
10087
10088
10089
10090
10091
10092
10093
10094
10095


10096
10097
10098
10099
10100
10101
10102
10103
10104







-
+








-
+














+
+
+
+













-
+




















+
+
+
+
+
+
+
-
+
+











-
-
+
+







  if( pCur->curFlags & BTCF_Multiple ){
    rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
    if( rc ) return rc;
  }

  /* If this is a delete operation to remove a row from a table b-tree,
  ** invalidate any incrblob cursors open on the row being deleted.  */
  if( pCur->pKeyInfo==0 ){
  if( pCur->pKeyInfo==0 && p->hasIncrblobCur ){
    invalidateIncrblobCursors(p, pCur->pgnoRoot, pCur->info.nKey, 0);
  }

  /* Make the page containing the entry to be deleted writable. Then free any
  ** overflow pages associated with the entry and finally remove the cell
  ** itself from within the page.  */
  rc = sqlite3PagerWrite(pPage->pDbPage);
  if( rc ) return rc;
  rc = clearCell(pPage, pCell, &info);
  BTREE_CLEAR_CELL(rc, pPage, pCell, info);
  dropCell(pPage, iCellIdx, info.nSize, &rc);
  if( rc ) return rc;

  /* If the cell deleted was not located on a leaf page, then the cursor
  ** is currently pointing to the largest entry in the sub-tree headed
  ** by the child-page of the cell that was just deleted from an internal
  ** node. The cell from the leaf node needs to be moved to the internal
  ** node to replace the deleted cell.  */
  if( !pPage->leaf ){
    MemPage *pLeaf = pCur->pPage;
    int nCell;
    Pgno n;
    unsigned char *pTmp;

    if( pLeaf->nFree<0 ){
      rc = btreeComputeFreeSpace(pLeaf);
      if( rc ) return rc;
    }
    if( iCellDepth<pCur->iPage-1 ){
      n = pCur->apPage[iCellDepth+1]->pgno;
    }else{
      n = pCur->pPage->pgno;
    }
    pCell = findCell(pLeaf, pLeaf->nCell-1);
    if( pCell<&pLeaf->aData[4] ) return SQLITE_CORRUPT_BKPT;
    nCell = pLeaf->xCellSize(pLeaf, pCell);
    assert( MX_CELL_SIZE(pBt) >= nCell );
    pTmp = pBt->pTmpSpace;
    assert( pTmp!=0 );
    rc = sqlite3PagerWrite(pLeaf->pDbPage);
    if( rc==SQLITE_OK ){
      insertCell(pPage, iCellIdx, pCell-4, nCell+4, pTmp, n, &rc);
      rc = insertCell(pPage, iCellIdx, pCell-4, nCell+4, pTmp, n);
    }
    dropCell(pLeaf, pLeaf->nCell-1, nCell, &rc);
    if( rc ) return rc;
  }

  /* Balance the tree. If the entry deleted was located on a leaf page,
  ** then the cursor still points to that page. In this case the first
  ** call to balance() repairs the tree, and the if(...) condition is
  ** never true.
  **
  ** Otherwise, if the entry deleted was on an internal node page, then
  ** pCur is pointing to the leaf page from which a cell was removed to
  ** replace the cell deleted from the internal node. This is slightly
  ** tricky as the leaf node may be underfull, and the internal node may
  ** be either under or overfull. In this case run the balancing algorithm
  ** on the leaf node first. If the balance proceeds far enough up the
  ** tree that we can be sure that any problem in the internal node has
  ** been corrected, so be it. Otherwise, after balancing the leaf node,
  ** walk the cursor up the tree to the internal node and balance it as 
  ** well.  */
  assert( pCur->pPage->nOverflow==0 );
  assert( pCur->pPage->nFree>=0 );
  if( pCur->pPage->nFree*3<=(int)pCur->pBt->usableSize*2 ){
    /* Optimization: If the free space is less than 2/3rds of the page,
    ** then balance() will always be a no-op.  No need to invoke it. */
    rc = SQLITE_OK;
  }else{
  rc = balance(pCur);
    rc = balance(pCur);
  }
  if( rc==SQLITE_OK && pCur->iPage>iCellDepth ){
    releasePageNotNull(pCur->pPage);
    pCur->iPage--;
    while( pCur->iPage>iCellDepth ){
      releasePage(pCur->apPage[pCur->iPage--]);
    }
    pCur->pPage = pCur->apPage[pCur->iPage];
    rc = balance(pCur);
  }

  if( rc==SQLITE_OK ){
    if( bSkipnext ){
      assert( bPreserve && (pCur->iPage==iCellDepth || CORRUPT_DB) );
    if( bPreserve>1 ){
      assert( (pCur->iPage==iCellDepth || CORRUPT_DB) );
      assert( pPage==pCur->pPage || CORRUPT_DB );
      assert( (pPage->nCell>0 || CORRUPT_DB) && iCellIdx<=pPage->nCell );
      pCur->eState = CURSOR_SKIPNEXT;
      if( iCellIdx>=pPage->nCell ){
        pCur->skipNext = -1;
        pCur->ix = pPage->nCell-1;
      }else{
9237
9238
9239
9240
9241
9242
9243
9244

9245
9246
9247
9248
9249
9250
9251
10123
10124
10125
10126
10127
10128
10129

10130
10131
10132
10133
10134
10135
10136
10137







-
+







** The type of type is determined by the flags parameter.  Only the
** following values of flags are currently in use.  Other values for
** flags might not work:
**
**     BTREE_INTKEY|BTREE_LEAFDATA     Used for SQL tables with rowid keys
**     BTREE_ZERODATA                  Used for SQL indices
*/
static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
static int btreeCreateTable(Btree *p, Pgno *piTable, int createTabFlags){
  BtShared *pBt = p->pBt;
  MemPage *pRoot;
  Pgno pgnoRoot;
  int rc;
  int ptfFlags;          /* Page-type flage for the root page of new table */

  assert( sqlite3BtreeHoldsMutex(p) );
9270
9271
9272
9273
9274
9275
9276



9277
9278
9279
9280
9281
9282
9283
9284
9285
9286

9287
9288
9289
9290
9291
9292
9293
9294
10156
10157
10158
10159
10160
10161
10162
10163
10164
10165
10166
10167
10168
10169
10170
10171
10172
10173
10174

10175

10176
10177
10178
10179
10180
10181
10182







+
+
+









-
+
-







    invalidateAllOverflowCache(pBt);

    /* Read the value of meta[3] from the database to determine where the
    ** root page of the new table should go. meta[3] is the largest root-page
    ** created so far, so the new root-page is (meta[3]+1).
    */
    sqlite3BtreeGetMeta(p, BTREE_LARGEST_ROOT_PAGE, &pgnoRoot);
    if( pgnoRoot>btreePagecount(pBt) ){
      return SQLITE_CORRUPT_BKPT;
    }
    pgnoRoot++;

    /* The new root-page may not be allocated on a pointer-map page, or the
    ** PENDING_BYTE page.
    */
    while( pgnoRoot==PTRMAP_PAGENO(pBt, pgnoRoot) ||
        pgnoRoot==PENDING_BYTE_PAGE(pBt) ){
      pgnoRoot++;
    }
    assert( pgnoRoot>=3 || CORRUPT_DB );
    assert( pgnoRoot>=3 );
    testcase( pgnoRoot<3 );

    /* Allocate a page. The page that currently resides at pgnoRoot will
    ** be moved to the allocated page (unless the allocated page happens
    ** to reside at pgnoRoot).
    */
    rc = allocateBtreePage(pBt, &pPageMove, &pgnoMove, pgnoRoot, BTALLOC_EXACT);
    if( rc!=SQLITE_OK ){
9377
9378
9379
9380
9381
9382
9383
9384

9385
9386
9387

9388
9389
9390
9391
9392
9393
9394
9395
9396
9397
9398
9399
9400
9401
9402
9403

9404
9405
9406
9407
9408
9409
9410
9411
9412
9413
9414
9415
9416
9417
9418
9419


9420

9421
9422
9423
9424
9425
9426
9427
9428
9429
9430
9431
9432

9433
9434
9435
9436
9437
9438
9439


9440

9441
9442
9443
9444
9445
9446
9447
9448
9449
9450
9451
9452
9453
9454
9455
9456
9457
9458
9459
9460
9461
9462
9463
9464
9465
9466
9467


9468
9469
9470

9471
9472
9473
9474
9475
9476
9477
9478
9479
9480
9481

9482


9483
9484
9485
9486
9487
9488
9489
10265
10266
10267
10268
10269
10270
10271

10272
10273
10274

10275
10276
10277
10278
10279
10280
10281
10282
10283
10284
10285
10286
10287
10288
10289
10290

10291
10292
10293
10294
10295
10296
10297
10298
10299
10300
10301
10302
10303
10304
10305
10306
10307
10308
10309

10310
10311
10312
10313

10314
10315
10316
10317
10318
10319
10320

10321
10322
10323
10324
10325
10326
10327
10328
10329
10330

10331

10332
10333
10334
10335
10336
10337
10338
10339
10340
10341

10342
10343
10344
10345
10346
10347
10348
10349
10350
10351
10352
10353
10354


10355
10356

10357

10358
10359
10360
10361
10362
10363
10364
10365
10366
10367
10368
10369
10370

10371
10372
10373
10374
10375
10376
10377
10378
10379







-
+


-
+















-
+
















+
+
-
+



-







-
+







+
+
-
+
-










-













-
-
+
+
-

-
+











+
-
+
+







    ptfFlags = PTF_INTKEY | PTF_LEAFDATA | PTF_LEAF;
  }else{
    ptfFlags = PTF_ZERODATA | PTF_LEAF;
  }
  zeroPage(pRoot, ptfFlags);
  sqlite3PagerUnref(pRoot->pDbPage);
  assert( (pBt->openFlags & BTREE_SINGLE)==0 || pgnoRoot==2 );
  *piTable = (int)pgnoRoot;
  *piTable = pgnoRoot;
  return SQLITE_OK;
}
int sqlite3BtreeCreateTable(Btree *p, int *piTable, int flags){
int sqlite3BtreeCreateTable(Btree *p, Pgno *piTable, int flags){
  int rc;
  sqlite3BtreeEnter(p);
  rc = btreeCreateTable(p, piTable, flags);
  sqlite3BtreeLeave(p);
  return rc;
}

/*
** Erase the given database page and all its children.  Return
** the page to the freelist.
*/
static int clearDatabasePage(
  BtShared *pBt,           /* The BTree that contains the table */
  Pgno pgno,               /* Page number to clear */
  int freePageFlag,        /* Deallocate page if true */
  int *pnChange,           /* Add number of Cells freed to this counter */
  i64 *pnChange,           /* Add number of Cells freed to this counter */
  Pgno pgnoRoot
){
  MemPage *pPage;
  int rc;
  unsigned char *pCell;
  int i;
  int hdr;
  CellInfo info;

  assert( sqlite3_mutex_held(pBt->mutex) );
  if( pgno>btreePagecount(pBt) ){
    return SQLITE_CORRUPT_BKPT;
  }
  rc = getAndInitPage(pBt, pgno, &pPage, 0, 0);
  if( rc ) return rc;
  setMempageRoot(pPage, pgnoRoot);
  if( (pBt->openFlags & BTREE_SINGLE)==0 
   && sqlite3PagerPageRefcount(pPage->pDbPage) != (1 + (pgno==1))
  if( pPage->bBusy ){
  ){
    rc = SQLITE_CORRUPT_BKPT;
    goto cleardatabasepage_out;
  }
  pPage->bBusy = 1;
  hdr = pPage->hdrOffset;
  for(i=0; i<pPage->nCell; i++){
    pCell = findCell(pPage, i);
    if( !pPage->leaf ){
      rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange, pgnoRoot);
      if( rc ) goto cleardatabasepage_out;
    }
    rc = clearCell(pPage, pCell, &info);
    BTREE_CLEAR_CELL(rc, pPage, pCell, info);
    if( rc ) goto cleardatabasepage_out;
  }
  if( !pPage->leaf ){
    rc = clearDatabasePage(
        pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange, pgnoRoot
    );
    if( rc ) goto cleardatabasepage_out;
    if( pPage->intKey ) pnChange = 0;
  }
  }else if( pnChange ){
  if( pnChange ){
    assert( pPage->intKey || CORRUPT_DB );
    testcase( !pPage->intKey );
    *pnChange += pPage->nCell;
  }
  if( freePageFlag ){
    freePage(pPage, &rc);
  }else if( (rc = sqlite3PagerWrite(pPage->pDbPage))==0 ){
    zeroPage(pPage, pPage->aData[hdr] | PTF_LEAF);
  }

cleardatabasepage_out:
  pPage->bBusy = 0;
  releasePage(pPage);
  return rc;
}

/*
** Delete all information from a single table in the database.  iTable is
** the page number of the root of the table.  After this routine returns,
** the root page is empty, but still exists.
**
** This routine will fail with SQLITE_LOCKED if there are any open
** read cursors on the table.  Open write cursors are moved to the
** root of the table.
**
** If pnChange is not NULL, then table iTable must be an intkey table. The
** integer value pointed to by pnChange is incremented by the number of
** If pnChange is not NULL, then the integer value pointed to by pnChange
** is incremented by the number of entries in the table.
** entries in the table.
*/
int sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){
int sqlite3BtreeClearTable(Btree *p, int iTable, i64 *pnChange){
  int rc;
  BtShared *pBt = p->pBt;
  sqlite3BtreeEnter(p);
  assert( p->inTrans==TRANS_WRITE );

  rc = saveAllCursors(pBt, (Pgno)iTable, 0);

  if( SQLITE_OK==rc ){
    /* Invalidate all incrblob cursors open on table iTable (assuming iTable
    ** is the root of a table b-tree - if it is not, the following call is
    ** a no-op).  */
    if( p->hasIncrblobCur ){
    invalidateIncrblobCursors(p, (Pgno)iTable, 0, 1);
      invalidateIncrblobCursors(p, (Pgno)iTable, 0, 1);
    }
    rc = clearDatabasePage(pBt, (Pgno)iTable, 0, pnChange, (Pgno)iTable);
  }
  sqlite3BtreeLeave(p);
  return rc;
}

/*
9519
9520
9521
9522
9523
9524
9525


9526
9527


9528
9529
9530



9531
9532
9533
9534
9535
9536
9537
10409
10410
10411
10412
10413
10414
10415
10416
10417


10418
10419

10420

10421
10422
10423
10424
10425
10426
10427
10428
10429
10430







+
+
-
-
+
+
-

-
+
+
+







  int rc;
  MemPage *pPage = 0;
  BtShared *pBt = p->pBt;

  assert( sqlite3BtreeHoldsMutex(p) );
  assert( p->inTrans==TRANS_WRITE );
  assert( iTable>=2 );
  if( iTable>btreePagecount(pBt) ){
    return SQLITE_CORRUPT_BKPT;

  rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0);
  }

  if( rc ) return rc;
  rc = sqlite3BtreeClearTable(p, iTable, 0);
  if( rc ){
  if( rc ) return rc;
  rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0);
  if( NEVER(rc) ){
    releasePage(pPage);
    return rc;
  }

  *piMoved = 0;

#ifdef SQLITE_OMIT_AUTOVACUUM
9627
9628
9629
9630
9631
9632
9633
9634

9635
9636
9637
9638
9639

9640
9641
9642
9643
9644
9645
9646
10520
10521
10522
10523
10524
10525
10526

10527
10528
10529
10530
10531

10532
10533
10534
10535
10536
10537
10538
10539







-
+




-
+







** read it from this routine.
*/
void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){
  BtShared *pBt = p->pBt;

  sqlite3BtreeEnter(p);
  assert( p->inTrans>TRANS_NONE );
  assert( SQLITE_OK==querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK) );
  assert( SQLITE_OK==querySharedCacheTableLock(p, SCHEMA_ROOT, READ_LOCK) );
  assert( pBt->pPage1 );
  assert( idx>=0 && idx<=15 );

  if( idx==BTREE_DATA_VERSION ){
    *pMeta = sqlite3PagerDataVersion(pBt->pPager) + p->iDataVersion;
    *pMeta = sqlite3PagerDataVersion(pBt->pPager) + p->iBDataVersion;
  }else{
    *pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]);
  }

  /* If auto-vacuum is disabled in this build and this is an auto-vacuum
  ** database, mark the database as read-only.  */
#ifdef SQLITE_OMIT_AUTOVACUUM
9676
9677
9678
9679
9680
9681
9682
9683
9684
9685
9686
9687
9688
9689
9690
9691
9692

9693
9694
9695
9696
9697
9698
9699
9700
9701
9702
9703
9704
9705

9706
9707
9708
9709
9710
9711
9712
10569
10570
10571
10572
10573
10574
10575

10576
10577
10578
10579
10580
10581
10582
10583

10584
10585
10586
10587
10588
10589
10590
10591
10592
10593
10594
10595
10596

10597
10598
10599
10600
10601
10602
10603
10604







-








-
+












-
+







    }
#endif
  }
  sqlite3BtreeLeave(p);
  return rc;
}

#ifndef SQLITE_OMIT_BTREECOUNT
/*
** The first argument, pCur, is a cursor opened on some b-tree. Count the
** number of entries in the b-tree and write the result to *pnEntry.
**
** SQLITE_OK is returned if the operation is successfully executed. 
** Otherwise, if an error is encountered (i.e. an IO error or database
** corruption) an SQLite error code is returned.
*/
int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
int sqlite3BtreeCount(sqlite3 *db, BtCursor *pCur, i64 *pnEntry){
  i64 nEntry = 0;                      /* Value to return in *pnEntry */
  int rc;                              /* Return code */

  rc = moveToRoot(pCur);
  if( rc==SQLITE_EMPTY ){
    *pnEntry = 0;
    return SQLITE_OK;
  }

  /* Unless an error occurs, the following loop runs one iteration for each
  ** page in the B-Tree structure (not including overflow pages). 
  */
  while( rc==SQLITE_OK ){
  while( rc==SQLITE_OK && !AtomicLoad(&db->u1.isInterrupted) ){
    int iIdx;                          /* Index of child node in parent */
    MemPage *pPage;                    /* Current page of the b-tree */

    /* If this is a leaf page or the tree is not an int-key tree, then 
    ** this page contains countable entries. Increment the entry counter
    ** accordingly.
    */
9749
9750
9751
9752
9753
9754
9755
9756
9757
9758
9759
9760
9761
9762
9763
9764
9765
9766



































9767
9768
9769
9770
9771
9772
9773
9774
9775

9776
9777
9778
9779
9780
9781
9782
9783
9784
9785
9786
9787
9788
9789

9790
9791
9792
9793
9794
9795
9796
10641
10642
10643
10644
10645
10646
10647

10648
10649
10650
10651
10652
10653
10654
10655
10656
10657
10658
10659
10660
10661
10662
10663
10664
10665
10666
10667
10668
10669
10670
10671
10672
10673
10674
10675
10676
10677
10678
10679
10680
10681
10682
10683
10684
10685
10686
10687
10688
10689
10690
10691
10692
10693
10694
10695
10696
10697
10698
10699
10700
10701
10702
10703
10704
10705
10706
10707
10708
10709
10710
10711
10712
10713
10714
10715

10716
10717
10718
10719
10720
10721
10722
10723







-










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









+













-
+







      rc = moveToChild(pCur, get4byte(findCell(pPage, iIdx)));
    }
  }

  /* An error has occurred. Return an error code. */
  return rc;
}
#endif

/*
** Return the pager associated with a BTree.  This routine is used for
** testing and debugging only.
*/
Pager *sqlite3BtreePager(Btree *p){
  return p->pBt->pPager;
}

#ifndef SQLITE_OMIT_INTEGRITY_CHECK
/*
** Record an OOM error during integrity_check
*/
static void checkOom(IntegrityCk *pCheck){
  pCheck->rc = SQLITE_NOMEM;
  pCheck->mxErr = 0;  /* Causes integrity_check processing to stop */
  if( pCheck->nErr==0 ) pCheck->nErr++;
}

/*
** Invoke the progress handler, if appropriate.  Also check for an
** interrupt.
*/
static void checkProgress(IntegrityCk *pCheck){
  sqlite3 *db = pCheck->db;
  if( AtomicLoad(&db->u1.isInterrupted) ){
    pCheck->rc = SQLITE_INTERRUPT;
    pCheck->nErr++;
    pCheck->mxErr = 0;
  }
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  if( db->xProgress ){
    assert( db->nProgressOps>0 );
    pCheck->nStep++;
    if( (pCheck->nStep % db->nProgressOps)==0
     && db->xProgress(db->pProgressArg)
    ){
      pCheck->rc = SQLITE_INTERRUPT;
      pCheck->nErr++;
      pCheck->mxErr = 0;
    }
  }
#endif
}

/*
** Append a message to the error message string.
*/
static void checkAppendMsg(
  IntegrityCk *pCheck,
  const char *zFormat,
  ...
){
  va_list ap;
  checkProgress(pCheck);
  if( !pCheck->mxErr ) return;
  pCheck->mxErr--;
  pCheck->nErr++;
  va_start(ap, zFormat);
  if( pCheck->errMsg.nChar ){
    sqlite3_str_append(&pCheck->errMsg, "\n", 1);
  }
  if( pCheck->zPfx ){
    sqlite3_str_appendf(&pCheck->errMsg, pCheck->zPfx, pCheck->v1, pCheck->v2);
  }
  sqlite3_str_vappendf(&pCheck->errMsg, zFormat, ap);
  va_end(ap);
  if( pCheck->errMsg.accError==SQLITE_NOMEM ){
    pCheck->mallocFailed = 1;
    checkOom(pCheck);
  }
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */

#ifndef SQLITE_OMIT_INTEGRITY_CHECK

/*
9846
9847
9848
9849
9850
9851
9852
9853

9854
9855
9856
9857
9858
9859
9860
9861
9862
9863
9864
9865
9866
9867
9868
9869
9870
9871
9872
9873
9874


9875
9876
9877

9878
9879
9880
9881
9882
9883
9884
10773
10774
10775
10776
10777
10778
10779

10780
10781
10782
10783
10784
10785
10786
10787
10788
10789
10790
10791
10792
10793
10794
10795
10796
10797
10798
10799


10800
10801
10802
10803

10804
10805
10806
10807
10808
10809
10810
10811







-
+



















-
-
+
+


-
+







){
  int rc;
  u8 ePtrmapType;
  Pgno iPtrmapParent;

  rc = ptrmapGet(pCheck->pBt, iChild, &ePtrmapType, &iPtrmapParent);
  if( rc!=SQLITE_OK ){
    if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ) pCheck->mallocFailed = 1;
    if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ) checkOom(pCheck);
    checkAppendMsg(pCheck, "Failed to read ptrmap key=%d", iChild);
    return;
  }

  if( ePtrmapType!=eType || iPtrmapParent!=iParent ){
    checkAppendMsg(pCheck,
      "Bad ptr map entry key=%d expected=(%d,%d) got=(%d,%d)", 
      iChild, eType, iParent, ePtrmapType, iPtrmapParent);
  }
}
#endif

/*
** Check the integrity of the freelist or of an overflow page list.
** Verify that the number of pages on the list is N.
*/
static void checkList(
  IntegrityCk *pCheck,  /* Integrity checking context */
  int isFreeList,       /* True for a freelist.  False for overflow page list */
  int iPage,            /* Page number for first page in the list */
  int N                 /* Expected number of pages in the list */
  Pgno iPage,           /* Page number for first page in the list */
  u32 N                 /* Expected number of pages in the list */
){
  int i;
  int expected = N;
  u32 expected = N;
  int nErrAtStart = pCheck->nErr;
  while( iPage!=0 && pCheck->mxErr ){
    DbPage *pOvflPage;
    unsigned char *pOvflData;
    if( checkRef(pCheck, iPage) ) break;
    N--;
    if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage, 0) ){
9953
9954
9955
9956
9957
9958
9959


9960

9961
9962
9963
9964
9965
9966
9967
10880
10881
10882
10883
10884
10885
10886
10887
10888

10889
10890
10891
10892
10893
10894
10895
10896







+
+
-
+







**
** This heap is used for cell overlap and coverage testing.  Each u32
** entry represents the span of a cell or freeblock on a btree page.  
** The upper 16 bits are the index of the first byte of a range and the
** lower 16 bits are the index of the last byte of that range.
*/
static void btreeHeapInsert(u32 *aHeap, u32 x){
  u32 j, i;
  assert( aHeap!=0 );
  u32 j, i = ++aHeap[0];
  i = ++aHeap[0];
  aHeap[i] = x;
  while( (j = i/2)>0 && aHeap[j]>aHeap[i] ){
    x = aHeap[j];
    aHeap[j] = aHeap[i];
    aHeap[i] = x;
    i = j;
  }
9998
9999
10000
10001
10002
10003
10004
10005

10006
10007
10008
10009
10010
10011
10012
10927
10928
10929
10930
10931
10932
10933

10934
10935
10936
10937
10938
10939
10940
10941







-
+







**      2.  Make sure integer cell keys are in order.
**      3.  Check the integrity of overflow pages.
**      4.  Recursively call checkTreePage on all children.
**      5.  Verify that the depth of all children is the same.
*/
static int checkTreePage(
  IntegrityCk *pCheck,  /* Context for the sanity check */
  int iPage,            /* Page number of the page to check */
  Pgno iPage,           /* Page number of the page to check */
  i64 *piMinKey,        /* Write minimum integer primary key here */
  i64 maxKey            /* Error if integer primary key greater than this */
){
  MemPage *pPage = 0;      /* The page being analyzed */
  int i;                   /* Loop counter */
  int rc;                  /* Result code from subroutine call */
  int depth = -1, d2;      /* Depth of a subtree */
10030
10031
10032
10033
10034
10035
10036


10037
10038
10039
10040
10041

10042
10043

10044
10045
10046
10047
10048
10049
10050
10051
10052
10053
10054
10055
10056
10057
10058





10059
10060
10061
10062
10063

10064
10065
10066
10067
10068
10069
10070
10071
10072
10073
10074
10075
10076
10077
10078
10079
10080
10081
10082
10083

10084
10085
10086
10087
10088
10089
10090
10959
10960
10961
10962
10963
10964
10965
10966
10967
10968
10969
10970
10971

10972
10973

10974
10975
10976
10977
10978
10979
10980
10981
10982
10983
10984
10985
10986
10987
10988
10989
10990
10991
10992
10993
10994
10995
10996
10997
10998

10999
11000
11001
11002
11003
11004
11005
11006
11007
11008
11009
11010
11011
11012
11013
11014
11015
11016
11017
11018

11019
11020
11021
11022
11023
11024
11025
11026







+
+




-
+

-
+















+
+
+
+
+




-
+



















-
+







  const char *saved_zPfx = pCheck->zPfx;
  int saved_v1 = pCheck->v1;
  int saved_v2 = pCheck->v2;
  u8 savedIsInit = 0;

  /* Check that the page exists
  */
  checkProgress(pCheck);
  if( pCheck->mxErr==0 ) goto end_of_check;
  pBt = pCheck->pBt;
  usableSize = pBt->usableSize;
  if( iPage==0 ) return 0;
  if( checkRef(pCheck, iPage) ) return 0;
  pCheck->zPfx = "Page %d: ";
  pCheck->zPfx = "Page %u: ";
  pCheck->v1 = iPage;
  if( (rc = btreeGetPage(pBt, (Pgno)iPage, &pPage, 0))!=0 ){
  if( (rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0 ){
    checkAppendMsg(pCheck,
       "unable to get the page. error code=%d", rc);
    goto end_of_check;
  }

  /* Clear MemPage.isInit to make sure the corruption detection code in
  ** btreeInitPage() is executed.  */
  savedIsInit = pPage->isInit;
  pPage->isInit = 0;
  if( (rc = btreeInitPage(pPage))!=0 ){
    assert( rc==SQLITE_CORRUPT );  /* The only possible error from InitPage */
    checkAppendMsg(pCheck,
                   "btreeInitPage() returns error code %d", rc);
    goto end_of_check;
  }
  if( (rc = btreeComputeFreeSpace(pPage))!=0 ){
    assert( rc==SQLITE_CORRUPT );
    checkAppendMsg(pCheck, "free space corruption", rc);
    goto end_of_check;
  }
  data = pPage->aData;
  hdr = pPage->hdrOffset;

  /* Set up for cell analysis */
  pCheck->zPfx = "On tree page %d cell %d: ";
  pCheck->zPfx = "On tree page %u cell %d: ";
  contentOffset = get2byteNotZero(&data[hdr+5]);
  assert( contentOffset<=usableSize );  /* Enforced by btreeInitPage() */

  /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
  ** number of cells on the page. */
  nCell = get2byte(&data[hdr+3]);
  assert( pPage->nCell==nCell );

  /* EVIDENCE-OF: R-23882-45353 The cell pointer array of a b-tree page
  ** immediately follows the b-tree page header. */
  cellStart = hdr + 12 - 4*pPage->leaf;
  assert( pPage->aCellIdx==&data[cellStart] );
  pCellIdx = &data[cellStart + 2*(nCell-1)];

  if( !pPage->leaf ){
    /* Analyze the right-child page of internal pages */
    pgno = get4byte(&data[hdr+8]);
#ifndef SQLITE_OMIT_AUTOVACUUM
    if( pBt->autoVacuum ){
      pCheck->zPfx = "On page %d at right child: ";
      pCheck->zPfx = "On page %u at right child: ";
      checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage);
    }
#endif
    depth = checkTreePage(pCheck, pgno, &maxKey, maxKey);
    keyCanBeEqual = 0;
  }else{
    /* For leaf pages, the coverage check will occur in the same loop
10124
10125
10126
10127
10128
10129
10130
10131

10132
10133
10134
10135
10136
10137
10138
11060
11061
11062
11063
11064
11065
11066

11067
11068
11069
11070
11071
11072
11073
11074







-
+







      }
      maxKey = info.nKey;
      keyCanBeEqual = 0;     /* Only the first key on the page may ==maxKey */
    }

    /* Check the content overflow list */
    if( info.nPayload>info.nLocal ){
      int nPage;       /* Number of pages on the overflow chain */
      u32 nPage;       /* Number of pages on the overflow chain */
      Pgno pgnoOvfl;   /* First page of the overflow chain */
      assert( pc + info.nSize - 4 <= usableSize );
      nPage = (info.nPayload - info.nLocal + usableSize - 5)/(usableSize - 4);
      pgnoOvfl = get4byte(&pCell[info.nSize - 4]);
#ifndef SQLITE_OMIT_AUTOVACUUM
      if( pBt->autoVacuum ){
        checkPtrmap(pCheck, pgnoOvfl, PTRMAP_OVERFLOW1, iPage);
10184
10185
10186
10187
10188
10189
10190
10191

10192
10193

10194
10195
10196
10197
10198
10199
10200
10201
10202
10203


10204
10205
10206
10207
10208
10209
10210
10211
10212
10213
10214
10215
10216
10217
10218
10219
10220
10221
10222
10223
10224

10225
10226
10227
10228
10229
10230
10231
10232
10233
10234
10235
10236
10237
10238
10239

10240
10241
10242
10243
10244
10245
10246
11120
11121
11122
11123
11124
11125
11126

11127
11128

11129
11130
11131
11132
11133
11134
11135
11136
11137


11138
11139
11140
11141
11142
11143
11144
11145
11146
11147
11148
11149
11150
11151
11152
11153
11154
11155
11156
11157
11158
11159

11160
11161
11162
11163
11164
11165
11166
11167
11168
11169
11170
11171
11172
11173
11174

11175
11176
11177
11178
11179
11180
11181
11182







-
+

-
+








-
-
+
+




















-
+














-
+







    ** EVIDENCE-OF: R-20690-50594 The second field of the b-tree page header
    ** is the offset of the first freeblock, or zero if there are no
    ** freeblocks on the page. 
    */
    i = get2byte(&data[hdr+1]);
    while( i>0 ){
      int size, j;
      assert( (u32)i<=usableSize-4 );     /* Enforced by btreeInitPage() */
      assert( (u32)i<=usableSize-4 ); /* Enforced by btreeComputeFreeSpace() */
      size = get2byte(&data[i+2]);
      assert( (u32)(i+size)<=usableSize );  /* Enforced by btreeInitPage() */
      assert( (u32)(i+size)<=usableSize ); /* due to btreeComputeFreeSpace() */
      btreeHeapInsert(heap, (((u32)i)<<16)|(i+size-1));
      /* EVIDENCE-OF: R-58208-19414 The first 2 bytes of a freeblock are a
      ** big-endian integer which is the offset in the b-tree page of the next
      ** freeblock in the chain, or zero if the freeblock is the last on the
      ** chain. */
      j = get2byte(&data[i]);
      /* EVIDENCE-OF: R-06866-39125 Freeblocks are always connected in order of
      ** increasing offset. */
      assert( j==0 || j>i+size );  /* Enforced by btreeInitPage() */
      assert( (u32)j<=usableSize-4 );   /* Enforced by btreeInitPage() */
      assert( j==0 || j>i+size );     /* Enforced by btreeComputeFreeSpace() */
      assert( (u32)j<=usableSize-4 ); /* Enforced by btreeComputeFreeSpace() */
      i = j;
    }
    /* Analyze the min-heap looking for overlap between cells and/or 
    ** freeblocks, and counting the number of untracked bytes in nFrag.
    ** 
    ** Each min-heap entry is of the form:    (start_address<<16)|end_address.
    ** There is an implied first entry the covers the page header, the cell
    ** pointer index, and the gap between the cell pointer index and the start
    ** of cell content.  
    **
    ** The loop below pulls entries from the min-heap in order and compares
    ** the start_address against the previous end_address.  If there is an
    ** overlap, that means bytes are used multiple times.  If there is a gap,
    ** that gap is added to the fragmentation count.
    */
    nFrag = 0;
    prev = contentOffset - 1;   /* Implied first min-heap entry */
    while( btreeHeapPull(heap,&x) ){
      if( (prev&0xffff)>=(x>>16) ){
        checkAppendMsg(pCheck,
          "Multiple uses for byte %u of page %d", x>>16, iPage);
          "Multiple uses for byte %u of page %u", x>>16, iPage);
        break;
      }else{
        nFrag += (x>>16) - (prev&0xffff) - 1;
        prev = x;
      }
    }
    nFrag += usableSize - (prev&0xffff) - 1;
    /* EVIDENCE-OF: R-43263-13491 The total number of bytes in all fragments
    ** is stored in the fifth field of the b-tree page header.
    ** EVIDENCE-OF: R-07161-27322 The one-byte integer at offset 7 gives the
    ** number of fragmented free bytes within the cell content area.
    */
    if( heap[0]==0 && nFrag!=data[hdr+7] ){
      checkAppendMsg(pCheck,
          "Fragmentation of %d bytes reported as %d on page %d",
          "Fragmentation of %d bytes reported as %d on page %u",
          nFrag, data[hdr+7], iPage);
    }
  }

end_of_check:
  if( !doCoverageCheck ) pPage->isInit = savedIsInit;
  releasePage(pPage);
10260
10261
10262
10263
10264
10265
10266









10267
10268


10269
10270

10271
10272
10273


10274
10275
10276
10277
10278

10279


10280








10281
10282
10283
10284
10285


10286
10287
10288
10289
10290
10291
10292
10293
10294
10295
10296
10297
10298
10299
10300
10301
10302
10303
10304
10305

10306
10307
10308
10309
10310

10311
10312
10313
10314
10315
10316
10317
10318

10319
10320
10321
10322
10323






10324
10325
10326

10327
10328
10329
10330
10331
10332
10333
10334
10335
10336
10337
10338
10339
10340
10341
















10342
10343
10344
10345
10346
10347
10348
10349
10350

10351
10352
10353
10354
10355
10356
10357
10358
10359
10360
10361

10362

10363
10364
10365
10366



10367
10368
10369
10370
10371
10372
10373
10374
10375
10376
10377
10378











10379

10380
10381
10382
10383
10384
10385
10386

10387

10388


10389

10390
10391
10392
10393
10394
10395
10396

10397
10398
10399
10400
10401
10402
10403
11196
11197
11198
11199
11200
11201
11202
11203
11204
11205
11206
11207
11208
11209
11210
11211
11212

11213
11214
11215

11216
11217
11218

11219
11220
11221
11222
11223
11224

11225
11226
11227
11228
11229
11230
11231
11232
11233
11234
11235
11236
11237
11238
11239
11240
11241
11242
11243
11244
11245
11246
11247
11248







11249
11250
11251
11252
11253
11254
11255
11256

11257
11258
11259
11260
11261

11262
11263
11264
11265
11266
11267
11268
11269
11270
11271





11272
11273
11274
11275
11276
11277
11278
11279
11280
11281















11282
11283
11284
11285
11286
11287
11288
11289
11290
11291
11292
11293
11294
11295
11296
11297
11298
11299
11300
11301
11302
11303
11304
11305

11306
11307
11308
11309
11310
11311
11312
11313
11314
11315
11316
11317
11318

11319
11320



11321
11322
11323
11324











11325
11326
11327
11328
11329
11330
11331
11332
11333
11334
11335
11336
11337
11338
11339
11340
11341
11342
11343
11344
11345

11346
11347
11348
11349

11350
11351


11352
11353
11354

11355
11356
11357
11358
11359
11360
11361
11362







+
+
+
+
+
+
+
+
+

-
+
+

-
+


-
+
+




-
+

+
+

+
+
+
+
+
+
+
+





+
+




-
-
-
-
-
-
-








-
+




-
+








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



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








-
+











+
-
+

-
-
-
+
+
+

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

+







+
-
+

+
+
-
+

-
-



-
+







** A read-only or read-write transaction must be opened before calling
** this function.
**
** Write the number of error seen in *pnErr.  Except for some memory
** allocation errors,  an error message held in memory obtained from
** malloc is returned if *pnErr is non-zero.  If *pnErr==0 then NULL is
** returned.  If a memory allocation error occurs, NULL is returned.
**
** If the first entry in aRoot[] is 0, that indicates that the list of
** root pages is incomplete.  This is a "partial integrity-check".  This
** happens when performing an integrity check on a single table.  The
** zero is skipped, of course.  But in addition, the freelist checks
** and the checks to make sure every page is referenced are also skipped,
** since obviously it is not possible to know which pages are covered by
** the unverified btrees.  Except, if aRoot[1] is 1, then the freelist
** checks are still performed.
*/
char *sqlite3BtreeIntegrityCheck(
int sqlite3BtreeIntegrityCheck(
  sqlite3 *db,  /* Database connection that is running the check */
  Btree *p,     /* The btree to be checked */
  int *aRoot,   /* An array of root pages numbers for individual trees */
  Pgno *aRoot,  /* An array of root pages numbers for individual trees */
  int nRoot,    /* Number of entries in aRoot[] */
  int mxErr,    /* Stop reporting errors after this many */
  int *pnErr    /* Write number of errors seen to this variable */
  int *pnErr,   /* OUT: Write number of errors seen to this variable */
  char **pzOut  /* OUT: Write the error message string here */
){
  Pgno i;
  IntegrityCk sCheck;
  BtShared *pBt = p->pBt;
  int savedDbFlags = pBt->db->flags;
  u64 savedDbFlags = pBt->db->flags;
  char zErr[100];
  int bPartial = 0;            /* True if not checking all btrees */
  int bCkFreelist = 1;         /* True to scan the freelist */
  VVA_ONLY( int nRef );
  assert( nRoot>0 );

  /* aRoot[0]==0 means this is a partial check */
  if( aRoot[0]==0 ){
    assert( nRoot>1 );
    bPartial = 1;
    if( aRoot[1]!=1 ) bCkFreelist = 0;
  }

  sqlite3BtreeEnter(p);
  assert( p->inTrans>TRANS_NONE && pBt->inTransaction>TRANS_NONE );
  VVA_ONLY( nRef = sqlite3PagerRefcount(pBt->pPager) );
  assert( nRef>=0 );
  memset(&sCheck, 0, sizeof(sCheck));
  sCheck.db = db;
  sCheck.pBt = pBt;
  sCheck.pPager = pBt->pPager;
  sCheck.nPage = btreePagecount(sCheck.pBt);
  sCheck.mxErr = mxErr;
  sCheck.nErr = 0;
  sCheck.mallocFailed = 0;
  sCheck.zPfx = 0;
  sCheck.v1 = 0;
  sCheck.v2 = 0;
  sCheck.aPgRef = 0;
  sCheck.heap = 0;
  sqlite3StrAccumInit(&sCheck.errMsg, 0, zErr, sizeof(zErr), SQLITE_MAX_LENGTH);
  sCheck.errMsg.printfFlags = SQLITE_PRINTF_INTERNAL;
  if( sCheck.nPage==0 ){
    goto integrity_ck_cleanup;
  }

  sCheck.aPgRef = sqlite3MallocZero((sCheck.nPage / 8)+ 1);
  if( !sCheck.aPgRef ){
    sCheck.mallocFailed = 1;
    checkOom(&sCheck);
    goto integrity_ck_cleanup;
  }
  sCheck.heap = (u32*)sqlite3PageMalloc( pBt->pageSize );
  if( sCheck.heap==0 ){
    sCheck.mallocFailed = 1;
    checkOom(&sCheck);
    goto integrity_ck_cleanup;
  }

  i = PENDING_BYTE_PAGE(pBt);
  if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i);

  /* Check the integrity of the freelist
  */
  if( bCkFreelist ){
  sCheck.zPfx = "Main freelist: ";
  checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]),
            get4byte(&pBt->pPage1->aData[36]));
  sCheck.zPfx = 0;

    sCheck.zPfx = "Main freelist: ";
    checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]),
              get4byte(&pBt->pPage1->aData[36]));
    sCheck.zPfx = 0;
  }

  /* Check all the tables.
  */
#ifndef SQLITE_OMIT_AUTOVACUUM
  if( !bPartial ){
  if( pBt->autoVacuum ){
    int mx = 0;
    int mxInHdr;
    for(i=0; (int)i<nRoot; i++) if( mx<aRoot[i] ) mx = aRoot[i];
    mxInHdr = get4byte(&pBt->pPage1->aData[52]);
    if( mx!=mxInHdr ){
      checkAppendMsg(&sCheck,
        "max rootpage (%d) disagrees with header (%d)",
        mx, mxInHdr
      );
    }
  }else if( get4byte(&pBt->pPage1->aData[64])!=0 ){
    checkAppendMsg(&sCheck,
      "incremental_vacuum enabled with a max rootpage of zero"
    );
    if( pBt->autoVacuum ){
      Pgno mx = 0;
      Pgno mxInHdr;
      for(i=0; (int)i<nRoot; i++) if( mx<aRoot[i] ) mx = aRoot[i];
      mxInHdr = get4byte(&pBt->pPage1->aData[52]);
      if( mx!=mxInHdr ){
        checkAppendMsg(&sCheck,
          "max rootpage (%d) disagrees with header (%d)",
          mx, mxInHdr
        );
      }
    }else if( get4byte(&pBt->pPage1->aData[64])!=0 ){
      checkAppendMsg(&sCheck,
        "incremental_vacuum enabled with a max rootpage of zero"
      );
    }
  }
#endif
  testcase( pBt->db->flags & SQLITE_CellSizeCk );
  pBt->db->flags &= ~(u64)SQLITE_CellSizeCk;
  for(i=0; (int)i<nRoot && sCheck.mxErr; i++){
    i64 notUsed;
    if( aRoot[i]==0 ) continue;
#ifndef SQLITE_OMIT_AUTOVACUUM
    if( pBt->autoVacuum && aRoot[i]>1 ){
    if( pBt->autoVacuum && aRoot[i]>1 && !bPartial ){
      checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0);
    }
#endif
    checkTreePage(&sCheck, aRoot[i], &notUsed, LARGEST_INT64);
  }
  pBt->db->flags = savedDbFlags;

  /* Make sure every page in the file is referenced. Skip this if the
  ** database is currently being written by a CONCURRENT transaction (it 
  ** may fail as pages that were part of the free-list when the transaction
  ** was opened cannot be counted).  */
  if( !bPartial ){
  for(i=1; ISCONCURRENT==0 && i<=sCheck.nPage && sCheck.mxErr; i++){
    for(i=1; ISCONCURRENT==0 && i<=sCheck.nPage && sCheck.mxErr; i++){
#ifdef SQLITE_OMIT_AUTOVACUUM
    if( getPageReferenced(&sCheck, i)==0 ){
      checkAppendMsg(&sCheck, "Page %d is never used", i);
    }
      if( getPageReferenced(&sCheck, i)==0 ){
        checkAppendMsg(&sCheck, "Page %d is never used", i);
      }
#else
    /* If the database supports auto-vacuum, make sure no tables contain
    ** references to pointer-map pages.
    */
    if( getPageReferenced(&sCheck, i)==0 && 
       (PTRMAP_PAGENO(pBt, i)!=i || !pBt->autoVacuum) ){
      checkAppendMsg(&sCheck, "Page %d is never used", i);
    }
    if( getPageReferenced(&sCheck, i)!=0 && 
       (PTRMAP_PAGENO(pBt, i)==i && pBt->autoVacuum) ){
      checkAppendMsg(&sCheck, "Pointer map page %d is referenced", i);
    }
      /* If the database supports auto-vacuum, make sure no tables contain
      ** references to pointer-map pages.
      */
      if( getPageReferenced(&sCheck, i)==0 && 
         (PTRMAP_PAGENO(pBt, i)!=i || !pBt->autoVacuum) ){
        checkAppendMsg(&sCheck, "Page %d is never used", i);
      }
      if( getPageReferenced(&sCheck, i)!=0 && 
         (PTRMAP_PAGENO(pBt, i)==i && pBt->autoVacuum) ){
        checkAppendMsg(&sCheck, "Pointer map page %d is referenced", i);
      }
#endif
    }
  }

  /* Clean  up and report errors.
  */
integrity_ck_cleanup:
  sqlite3PageFree(sCheck.heap);
  sqlite3_free(sCheck.aPgRef);
  *pnErr = sCheck.nErr;
  if( sCheck.mallocFailed ){
  if( sCheck.nErr==0 ){
    sqlite3_str_reset(&sCheck.errMsg);
    *pzOut = 0;
  }else{
    sCheck.nErr++;
    *pzOut = sqlite3StrAccumFinish(&sCheck.errMsg);
  }
  *pnErr = sCheck.nErr;
  if( sCheck.nErr==0 ) sqlite3_str_reset(&sCheck.errMsg);
  /* Make sure this analysis did not leave any unref() pages. */
  assert( nRef==sqlite3PagerRefcount(pBt->pPager) );
  sqlite3BtreeLeave(p);
  return sqlite3StrAccumFinish(&sCheck.errMsg);
  return sCheck.rc;
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */

/*
** Return the full pathname of the underlying database file.  Return
** an empty string if the database is in-memory or a TEMP database.
**
10419
10420
10421
10422
10423
10424
10425

10426

10427
10428

10429
10430

10431
10432
10433
10434
10435
10436
10437
11378
11379
11380
11381
11382
11383
11384
11385

11386
11387

11388
11389

11390
11391
11392
11393
11394
11395
11396
11397







+
-
+

-
+

-
+







*/
const char *sqlite3BtreeGetJournalname(Btree *p){
  assert( p->pBt->pPager!=0 );
  return sqlite3PagerJournalname(p->pBt->pPager);
}

/*
** Return one of SQLITE_TXN_NONE, SQLITE_TXN_READ, or SQLITE_TXN_WRITE
** Return non-zero if a transaction is active.
** to describe the current transaction state of Btree p.
*/
int sqlite3BtreeIsInTrans(Btree *p){
int sqlite3BtreeTxnState(Btree *p){
  assert( p==0 || sqlite3_mutex_held(p->db->mutex) );
  return (p && (p->inTrans==TRANS_WRITE));
  return p ? p->inTrans : 0;
}

#ifndef SQLITE_OMIT_WAL
/*
** Run a checkpoint on the Btree passed as the first argument.
**
** Return SQLITE_LOCKED if this or any other connection has an open 
10452
10453
10454
10455
10456
10457
10458
10459

10460
10461
10462
10463
10464
10465
10466
10467
10468
10469
10470
10471
10472
10473
11412
11413
11414
11415
11416
11417
11418

11419
11420






11421
11422
11423
11424
11425
11426
11427







-
+

-
-
-
-
-
-







    sqlite3BtreeLeave(p);
  }
  return rc;
}
#endif

/*
** Return non-zero if a read (or write) transaction is active.
** Return true if there is currently a backup running on Btree p.
*/
int sqlite3BtreeIsInReadTrans(Btree *p){
  assert( p );
  assert( sqlite3_mutex_held(p->db->mutex) );
  return p->inTrans!=TRANS_NONE;
}

int sqlite3BtreeIsInBackup(Btree *p){
  assert( p );
  assert( sqlite3_mutex_held(p->db->mutex) );
  return p->nBackup!=0;
}

/*
10500
10501
10502
10503
10504
10505
10506
10507

10508
10509
10510
10511
10512
10513

10514
10515
10516
10517
10518
10519
10520
11454
11455
11456
11457
11458
11459
11460

11461
11462
11463
11464
11465
11466

11467
11468
11469
11470
11471
11472
11473
11474







-
+





-
+







  sqlite3BtreeLeave(p);
  return pBt->pSchema;
}

/*
** Return SQLITE_LOCKED_SHAREDCACHE if another user of the same shared 
** btree as the argument handle holds an exclusive lock on the 
** sqlite_master table. Otherwise SQLITE_OK.
** sqlite_schema table. Otherwise SQLITE_OK.
*/
int sqlite3BtreeSchemaLocked(Btree *p){
  int rc;
  assert( sqlite3_mutex_held(p->db->mutex) );
  sqlite3BtreeEnter(p);
  rc = querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK);
  rc = querySharedCacheTableLock(p, SCHEMA_ROOT, READ_LOCK);
  assert( rc==SQLITE_OK || rc==SQLITE_LOCKED_SHAREDCACHE );
  sqlite3BtreeLeave(p);
  return rc;
}


#ifndef SQLITE_OMIT_SHARED_CACHE
10612
10613
10614
10615
10616
10617
10618
10619

10620
10621
10622
10623
10624
10625
10626
11566
11567
11568
11569
11570
11571
11572

11573
11574
11575
11576
11577
11578
11579
11580







-
+







** "write version" (single byte at byte offset 19) fields in the database
** header to iVersion.
*/
int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
  BtShared *pBt = pBtree->pBt;
  int rc;                         /* Return code */
 
  assert( iVersion==1 || iVersion==2 );
  assert( iVersion==1 || iVersion==2 || iVersion==3 );

  /* If setting the version fields to 1, do not automatically open the
  ** WAL connection, even if the version fields are currently set to 2.
  */
  pBt->btsFlags &= ~BTS_NO_WAL;
  if( iVersion==1 ) pBt->btsFlags |= BTS_NO_WAL;

10682
10683
10684
10685
10686
10687
10688
10689




10690
10691
10692
10693
10694
10695
10696
11636
11637
11638
11639
11640
11641
11642

11643
11644
11645
11646
11647
11648
11649
11650
11651
11652
11653







-
+
+
+
+







*/
int sqlite3BtreeExclusiveLock(Btree *p){
  int rc;
  Pgno pgno = 0;
  BtShared *pBt = p->pBt;
  assert( p->inTrans==TRANS_WRITE && pBt->pPage1 );
  sqlite3BtreeEnter(p);
  rc = sqlite3PagerExclusiveLock(pBt->pPager, pBt->pPage1->pDbPage, &pgno);
  rc = sqlite3PagerExclusiveLock(pBt->pPager, 
    (p->db->eConcurrent==CONCURRENT_SCHEMA) ? 0 : pBt->pPage1->pDbPage,
    &pgno
  );
#ifdef SQLITE_OMIT_CONCURRENT
  assert( pgno==0 );
#else
  if( rc==SQLITE_BUSY_SNAPSHOT && pgno ){
    PgHdr *pPg = 0;
    int rc2 = sqlite3PagerGet(pBt->pPager, pgno, &pPg, 0);
    if( rc2==SQLITE_OK ){
10751
10752
10753
10754
10755
10756
10757











10758
10759
10760
10761
10762
10763
10764
11708
11709
11710
11711
11712
11713
11714
11715
11716
11717
11718
11719
11720
11721
11722
11723
11724
11725
11726
11727
11728
11729
11730
11731
11732







+
+
+
+
+
+
+
+
+
+
+







      );
    }
  }
#endif
  sqlite3BtreeLeave(p);
  return rc;
}

/*
** If no transaction is active and the database is not a temp-db, clear
** the in-memory pager cache.
*/
void sqlite3BtreeClearCache(Btree *p){
  BtShared *pBt = p->pBt;
  if( pBt->inTransaction==TRANS_NONE ){
    sqlite3PagerClearCache(pBt->pPager);
  }
}

#if !defined(SQLITE_OMIT_SHARED_CACHE)
/*
** Return true if the Btree passed as the only argument is sharable.
*/
int sqlite3BtreeSharable(Btree *p){
  return p->sharable;

Changes to src/btree.h.

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







-
-
+
+

-
+




-
+




-
-
-
-
+
+
+
+





+
+
+

+
+
+
+
+







int sqlite3BtreeSetSpillSize(Btree*,int);
#if SQLITE_MAX_MMAP_SIZE>0
  int sqlite3BtreeSetMmapLimit(Btree*,sqlite3_int64);
#endif
int sqlite3BtreeSetPagerFlags(Btree*,unsigned);
int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix);
int sqlite3BtreeGetPageSize(Btree*);
int sqlite3BtreeMaxPageCount(Btree*,int);
u32 sqlite3BtreeLastPage(Btree*);
Pgno sqlite3BtreeMaxPageCount(Btree*,Pgno);
Pgno sqlite3BtreeLastPage(Btree*);
int sqlite3BtreeSecureDelete(Btree*,int);
int sqlite3BtreeGetOptimalReserve(Btree*);
int sqlite3BtreeGetRequestedReserve(Btree*);
int sqlite3BtreeGetReserveNoMutex(Btree *p);
int sqlite3BtreeSetAutoVacuum(Btree *, int);
int sqlite3BtreeGetAutoVacuum(Btree *);
int sqlite3BtreeBeginTrans(Btree*,int,int*);
int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster);
int sqlite3BtreeCommitPhaseOne(Btree*, const char*);
int sqlite3BtreeCommitPhaseTwo(Btree*, int);
int sqlite3BtreeCommit(Btree*);
int sqlite3BtreeRollback(Btree*,int,int);
int sqlite3BtreeBeginStmt(Btree*,int);
int sqlite3BtreeCreateTable(Btree*, int*, int flags);
int sqlite3BtreeIsInTrans(Btree*);
int sqlite3BtreeIsInReadTrans(Btree*);
int sqlite3BtreeIsInBackup(Btree*);
int sqlite3BtreeCreateTable(Btree*, Pgno*, int flags);
int sqlite3BtreeTxnState(Btree*);
int sqlite3BtreeIsInBackup(Btree*);

void *sqlite3BtreeSchema(Btree *, int, void(*)(void *));
int sqlite3BtreeSchemaLocked(Btree *pBtree);
#ifndef SQLITE_OMIT_SHARED_CACHE
int sqlite3BtreeLockTable(Btree *pBtree, int iTab, u8 isWriteLock);
#endif

/* Savepoints are named, nestable SQL transactions mostly implemented */ 
/* in vdbe.c and pager.c See https://sqlite.org/lang_savepoint.html */
int sqlite3BtreeSavepoint(Btree *, int, int);

/* "Checkpoint" only refers to WAL. See https://sqlite.org/wal.html#ckpt */
#ifndef SQLITE_OMIT_WAL
  int sqlite3BtreeCheckpoint(Btree*, int, int *, int *);  
#endif

const char *sqlite3BtreeGetFilename(Btree *);
const char *sqlite3BtreeGetJournalname(Btree *);
int sqlite3BtreeCopyFile(Btree *, Btree *);

int sqlite3BtreeIncrVacuum(Btree *);

111
112
113
114
115
116
117
118

119
120
121
122
123
124
125
119
120
121
122
123
124
125

126
127
128
129
130
131
132
133







-
+







** anywhere - the key is the content.  (BTREE_BLOBKEY is used for SQL
** indices.)
*/
#define BTREE_INTKEY     1    /* Table has only 64-bit signed integer keys */
#define BTREE_BLOBKEY    2    /* Table has keys only - no data */

int sqlite3BtreeDropTable(Btree*, int, int*);
int sqlite3BtreeClearTable(Btree*, int, int*);
int sqlite3BtreeClearTable(Btree*, int, i64*);
int sqlite3BtreeClearTableOfCursor(BtCursor*);
int sqlite3BtreeTripAllCursors(Btree*, int, int);

void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue);
int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);

int sqlite3BtreeNewDb(Btree *p);
171
172
173
174
175
176
177
178

179
180
181
182
183
184
185
179
180
181
182
183
184
185

186
187
188
189
190
191
192
193







-
+







**
**     The design of the _RANGE hint is aid b-tree implementations that try
**     to prefetch content from remote machines - to provide those
**     implementations with limits on what needs to be prefetched and thereby
**     reduce network bandwidth.
**
** Note that BTREE_HINT_FLAGS with BTREE_BULKLOAD is the only hint used by
** standard SQLite.  The other hints are provided for extentions that use
** standard SQLite.  The other hints are provided for extensions that use
** the SQLite parser and code generator but substitute their own storage
** engine.
*/
#define BTREE_HINT_RANGE 0       /* Range constraints on queries */

/*
** Values that may be OR'd together to form the argument to the
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
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







-
+













-
+

-



+
+
+
+
+









+







** FORDELETE cursor may return a null row: 0x01 0x00.
*/
#define BTREE_WRCSR     0x00000004     /* read-write cursor */
#define BTREE_FORDELETE 0x00000008     /* Cursor is for seek/delete only */

int sqlite3BtreeCursor(
  Btree*,                              /* BTree containing table to open */
  int iTable,                          /* Index of root page */
  Pgno iTable,                         /* Index of root page */
  int wrFlag,                          /* 1 for writing.  0 for read-only */
  struct KeyInfo*,                     /* First argument to compare function */
  BtCursor *pCursor                    /* Space to write cursor structure */
);
BtCursor *sqlite3BtreeFakeValidCursor(void);
int sqlite3BtreeCursorSize(void);
void sqlite3BtreeCursorZero(BtCursor*);
void sqlite3BtreeCursorHintFlags(BtCursor*, unsigned);
#ifdef SQLITE_ENABLE_CURSOR_HINTS
void sqlite3BtreeCursorHint(BtCursor*, int, ...);
#endif

int sqlite3BtreeCloseCursor(BtCursor*);
int sqlite3BtreeMovetoUnpacked(
int sqlite3BtreeTableMoveto(
  BtCursor*,
  UnpackedRecord *pUnKey,
  i64 intKey,
  int bias,
  int *pRes
);
int sqlite3BtreeIndexMoveto(
  BtCursor*,
  UnpackedRecord *pUnKey,
  int *pRes
);
int sqlite3BtreeCursorHasMoved(BtCursor*);
int sqlite3BtreeCursorRestore(BtCursor*, int*);
int sqlite3BtreeDelete(BtCursor*, u8 flags);

/* Allowed flags for sqlite3BtreeDelete() and sqlite3BtreeInsert() */
#define BTREE_SAVEPOSITION 0x02  /* Leave cursor pointing at NEXT or PREV */
#define BTREE_AUXDELETE    0x04  /* not the primary delete operation */
#define BTREE_APPEND       0x08  /* Insert is likely an append */
#define BTREE_PREFORMAT    0x80  /* Inserted data is a preformated cell */

/* An instance of the BtreePayload object describes the content of a single
** entry in either an index or table btree.
**
** Index btrees (used for indexes and also WITHOUT ROWID tables) contain
** an arbitrary key and no data.  These btrees have pKey,nKey set to the
** key and the pData,nData,nZero fields are uninitialized.  The aMem,nMem
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
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







-
-
-





+
+






+

-
+
+
+
+
+
+
+
+
+













+
+
+
+
+
+








-
-
+
-









+
+
+
+







  int nData;              /* Size of pData.  0 if none. */
  int nZero;              /* Extra zero data appended after pData,nData */
};

int sqlite3BtreeInsert(BtCursor*, const BtreePayload *pPayload,
                       int flags, int seekResult);
int sqlite3BtreeFirst(BtCursor*, int *pRes);
#ifndef SQLITE_OMIT_WINDOWFUNC
void sqlite3BtreeSkipNext(BtCursor*);
#endif
int sqlite3BtreeLast(BtCursor*, int *pRes);
int sqlite3BtreeNext(BtCursor*, int flags);
int sqlite3BtreeEof(BtCursor*);
int sqlite3BtreePrevious(BtCursor*, int flags);
i64 sqlite3BtreeIntegerKey(BtCursor*);
void sqlite3BtreeCursorPin(BtCursor*);
void sqlite3BtreeCursorUnpin(BtCursor*);
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
i64 sqlite3BtreeOffset(BtCursor*);
#endif
int sqlite3BtreePayload(BtCursor*, u32 offset, u32 amt, void*);
const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt);
u32 sqlite3BtreePayloadSize(BtCursor*);
sqlite3_int64 sqlite3BtreeMaxRecordSize(BtCursor*);

char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*);
int sqlite3BtreeIntegrityCheck(
  sqlite3 *db,  /* Database connection that is running the check */
  Btree *p,     /* The btree to be checked */
  Pgno *aRoot,  /* An array of root pages numbers for individual trees */
  int nRoot,    /* Number of entries in aRoot[] */
  int mxErr,    /* Stop reporting errors after this many */
  int *pnErr,   /* OUT: Write number of errors seen to this variable */
  char **pzOut  /* OUT: Write the error message string here */
);
struct Pager *sqlite3BtreePager(Btree*);
i64 sqlite3BtreeRowCountEst(BtCursor*);

#ifndef SQLITE_OMIT_INCRBLOB
int sqlite3BtreePayloadChecked(BtCursor*, u32 offset, u32 amt, void*);
int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*);
void sqlite3BtreeIncrblobCursor(BtCursor *);
#endif
void sqlite3BtreeClearCursor(BtCursor *);
int sqlite3BtreeSetVersion(Btree *pBt, int iVersion);
int sqlite3BtreeCursorHasHint(BtCursor*, unsigned int mask);
int sqlite3BtreeIsReadonly(Btree *pBt);
int sqlite3HeaderSizeBtree(void);

#ifdef SQLITE_DEBUG
sqlite3_uint64 sqlite3BtreeSeekCount(Btree*);
#else
# define sqlite3BtreeSeekCount(X) 0
#endif

int sqlite3BtreeExclusiveLock(Btree *pBt);

#ifndef NDEBUG
int sqlite3BtreeCursorIsValid(BtCursor*);
#endif
int sqlite3BtreeCursorIsValidNN(BtCursor*);

#ifndef SQLITE_OMIT_BTREECOUNT
int sqlite3BtreeCount(BtCursor *, i64 *);
int sqlite3BtreeCount(sqlite3*, BtCursor*, i64*);
#endif

#ifdef SQLITE_TEST
int sqlite3BtreeCursorInfo(BtCursor*, int*, int);
void sqlite3BtreeCursorList(Btree*);
#endif

#ifndef SQLITE_OMIT_WAL
  int sqlite3BtreeCheckpoint(Btree*, int, int *, int *);
#endif

int sqlite3BtreeTransferRow(BtCursor*, BtCursor*, i64);

void sqlite3BtreeClearCache(Btree*);

/*
** If we are not using shared cache, then there is no need to
** use mutexes to access the BtShared structures.  So make the
** Enter and Leave procedures no-ops.
*/
#ifndef SQLITE_OMIT_SHARED_CACHE

Changes to src/btreeInt.h.

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







-
















-
+







-
+
+
+







** "extra" information associated with each page of the pager.)
**
** Access to all fields of this structure is controlled by the mutex
** stored in MemPage.pBt->mutex.
*/
struct MemPage {
  u8 isInit;           /* True if previously initialized. MUST BE FIRST! */
  u8 bBusy;            /* Prevent endless loops on corrupt database files */
  u8 intKey;           /* True if table b-trees.  False for index b-trees */
  u8 intKeyLeaf;       /* True if the leaf of an intKey table */
  Pgno pgno;           /* Page number for this page */
#ifndef SQLITE_OMIT_CONCURRENT
  Pgno pgnoRoot;       /* Root page of b-tree that this page belongs to */
#endif
  /* Only the first 8 bytes (above) are zeroed by pager.c when a new page
  ** is allocated. All fields that follow must be initialized before use */
  u8 leaf;             /* True if a leaf page */
  u8 hdrOffset;        /* 100 for page 1.  0 otherwise */
  u8 childPtrSize;     /* 0 if leaf==1.  4 if leaf==0 */
  u8 max1bytePayload;  /* min(maxLocal,127) */
  u8 nOverflow;        /* Number of overflow cell bodies in aCell[] */
  u16 maxLocal;        /* Copy of BtShared.maxLocal or BtShared.maxLeaf */
  u16 minLocal;        /* Copy of BtShared.minLocal or BtShared.minLeaf */
  u16 cellOffset;      /* Index in aData of first cell pointer */
  u16 nFree;           /* Number of free bytes on the page */
  int nFree;           /* Number of free bytes on the page. -1 for unknown */
  u16 nCell;           /* Number of cells on this page, local and ovfl */
  u16 maskPage;        /* Mask for page offset */
  u16 aiOvfl[4];       /* Insert the i-th overflow cell before the aiOvfl-th
                       ** non-overflow cell */
  u8 *apOvfl[4];       /* Pointers to the body of overflow cells */
  BtShared *pBt;       /* Pointer to BtShared that this page is part of */
  u8 *aData;           /* Pointer to disk image of the page data */
  u8 *aDataEnd;        /* One byte past the end of usable data */
  u8 *aDataEnd;        /* One byte past the end of the entire page - not just
                       ** the usable space, the entire page.  Used to prevent
                       ** corruption-induced buffer overflow. */
  u8 *aCellIdx;        /* The cell index area */
  u8 *aDataOfst;       /* Same as aData for leaves.  aData+4 for interior */
  DbPage *pDbPage;     /* Pager page handle */
  u16 (*xCellSize)(MemPage*,u8*);             /* cellSizePtr method */
  void (*xParseCell)(MemPage*,u8*,CellInfo*); /* btreeParseCell method */
};

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







-
+


+
+
+











+
+
+




+
+
+
+
+
+
+
+
+
+
+













-
+







  BtShared *pBt;     /* Sharable content of this btree */
  u8 inTrans;        /* TRANS_NONE, TRANS_READ or TRANS_WRITE */
  u8 sharable;       /* True if we can share pBt with another db */
  u8 locked;         /* True if db currently has pBt locked */
  u8 hasIncrblobCur; /* True if there are one or more Incrblob cursors */
  int wantToLock;    /* Number of nested calls to sqlite3BtreeEnter() */
  int nBackup;       /* Number of backup operations reading this btree */
  u32 iDataVersion;  /* Combines with pBt->pPager->iDataVersion */
  u32 iBDataVersion; /* Combines with pBt->pPager->iDataVersion */
  Btree *pNext;      /* List of other sharable Btrees from the same db */
  Btree *pPrev;      /* Back pointer of the same list */
#ifdef SQLITE_DEBUG
  u64 nSeek;         /* Calls to sqlite3BtreeMovetoUnpacked() */
#endif
#ifndef SQLITE_OMIT_SHARED_CACHE
  BtLock lock;       /* Object used to lock page 1 */
#endif
};

/*
** Btree.inTrans may take one of the following values.
**
** If the shared-data extension is enabled, there may be multiple users
** of the Btree structure. At most one of these may open a write transaction,
** but any number may have active read transactions.
**
** These values must match SQLITE_TXN_NONE, SQLITE_TXN_READ, and
** SQLITE_TXN_WRITE
*/
#define TRANS_NONE  0
#define TRANS_READ  1
#define TRANS_WRITE 2

#if TRANS_NONE!=SQLITE_TXN_NONE
# error wrong numeric code for no-transaction
#endif
#if TRANS_READ!=SQLITE_TXN_READ
# error wrong numeric code for read-transaction
#endif
#if TRANS_WRITE!=SQLITE_TXN_WRITE
# error wrong numeric code for write-transaction
#endif


/*
** An instance of this object represents a single database file.
** 
** A single database file can be in use at the same time by two
** or more database connections.  When two or more connections are
** sharing the same database file, each connection has it own
** private Btree object for the file and each of those Btrees points
** to this one BtShared object.  BtShared.nRef is the number of
** connections currently sharing this database file.
**
** Fields in this structure are accessed under the BtShared.mutex
** mutex, except for nRef and pNext which are accessed under the
** global SQLITE_MUTEX_STATIC_MASTER mutex.  The pPager field
** global SQLITE_MUTEX_STATIC_MAIN mutex.  The pPager field
** may not be modified once it is initially set as long as nRef>0.
** The pSchema field may be set once under BtShared.mutex and
** thereafter is unchanged as long as nRef>0.
**
** isPending:
**
**   If a BtShared client fails to obtain a write-lock on a database
417
418
419
420
421
422
423
424
425

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


442

443
444
445
446
447
448
449







-
-
+
-







#ifndef SQLITE_OMIT_AUTOVACUUM
  u8 autoVacuum;        /* True if auto-vacuum is enabled */
  u8 incrVacuum;        /* True if incr-vacuum is enabled */
  u8 bDoTruncate;       /* True to truncate db on commit */
#endif
  u8 inTransaction;     /* Transaction state */
  u8 max1bytePayload;   /* Maximum first byte of cell for a 1-byte payload */
#ifdef SQLITE_HAS_CODEC
  u8 optimalReserve;    /* Desired amount of reserved space per page */
  u8 nReserveWanted;    /* Desired number of extra bytes per page */
#endif
  u16 btsFlags;         /* Boolean parameters.  See BTS_* macros below */
  u16 maxLocal;         /* Maximum local payload in non-LEAFDATA tables */
  u16 minLocal;         /* Minimum local payload in non-LEAFDATA tables */
  u16 maxLeaf;          /* Maximum local payload in a LEAFDATA table */
  u16 minLeaf;          /* Minimum local payload in a LEAFDATA table */
  u32 pageSize;         /* Total number of bytes on a page */
  u32 usableSize;       /* Number of usable bytes on each page */
443
444
445
446
447
448
449

450
451
452
453
454
455
456
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473







+







  BtLock *pLock;        /* List of locks held on this shared-btree struct */
  Btree *pWriter;       /* Btree with currently open write transaction */
#endif
  u8 *pTmpSpace;        /* Temp space sufficient to hold a single cell */
#ifndef SQLITE_OMIT_CONCURRENT
  BtreePtrmap *pMap;
#endif
  int nPreformatSize;   /* Size of last cell written by TransferRow() */
};

/*
** Allowed values for BtShared.btsFlags
*/
#define BTS_READ_ONLY        0x0001   /* Underlying file is readonly */
#define BTS_PAGESIZE_FIXED   0x0002   /* Page size can no longer be changed */
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







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







** but cursors cannot be shared.  Each cursor is associated with a
** particular database connection identified BtCursor.pBtree.db.
**
** Fields in this structure are accessed under the BtShared.mutex
** found at self->pBt->mutex. 
**
** skipNext meaning:
** The meaning of skipNext depends on the value of eState:
**
**   eState            Meaning of skipNext
**   VALID             skipNext is meaningless and is ignored
**   INVALID           skipNext is meaningless and is ignored
**    eState==SKIPNEXT && skipNext>0:  Next sqlite3BtreeNext() is no-op.
**    eState==SKIPNEXT && skipNext<0:  Next sqlite3BtreePrevious() is no-op.
**    eState==FAULT:                   Cursor fault with skipNext as error code.
**   SKIPNEXT          sqlite3BtreeNext() is a no-op if skipNext>0 and
**                     sqlite3BtreePrevious() is no-op if skipNext<0.
**   REQUIRESEEK       restoreCursorPosition() restores the cursor to
**                     eState=SKIPNEXT if skipNext!=0
**   FAULT             skipNext holds the cursor fault error code.
*/
struct BtCursor {
  u8 eState;                /* One of the CURSOR_XXX constants (see below) */
  u8 curFlags;              /* zero or more BTCF_* flags defined below */
  u8 curPagerFlags;         /* Flags to send to sqlite3PagerGet() */
  u8 hints;                 /* As configured by CursorSetHints() */
  int skipNext;    /* Prev() is noop if negative. Next() is noop if positive.
538
539
540
541
542
543
544

545
546
547
548
549
550
551
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576







+







*/
#define BTCF_WriteFlag    0x01   /* True if a write cursor */
#define BTCF_ValidNKey    0x02   /* True if info.nKey is valid */
#define BTCF_ValidOvfl    0x04   /* True if aOverflow is valid */
#define BTCF_AtLast       0x08   /* Cursor is pointing ot the last entry */
#define BTCF_Incrblob     0x10   /* True if an incremental I/O handle */
#define BTCF_Multiple     0x20   /* Maybe another cursor on the same btree */
#define BTCF_Pinned       0x40   /* Cursor is busy and cannot be moved */

/*
** Potential values for BtCursor.eState.
**
** CURSOR_INVALID:
**   Cursor does not point to a valid entry. This can happen (for example) 
**   because the table is empty or because BtreeCursorFirst() has not been
578
579
580
581
582
583
584
585

586
587
588
589
590
591
592
603
604
605
606
607
608
609

610
611
612
613
614
615
616
617







-
+







#define CURSOR_SKIPNEXT          2
#define CURSOR_REQUIRESEEK       3
#define CURSOR_FAULT             4

/* 
** The database page the PENDING_BYTE occupies. This page is never used.
*/
# define PENDING_BYTE_PAGE(pBt) PAGER_MJ_PGNO(pBt)
#define PENDING_BYTE_PAGE(pBt)  ((Pgno)((PENDING_BYTE/((pBt)->pageSize))+1))

/*
** These macros define the location of the pointer-map entry for a 
** database page. The first argument to each is the number of usable
** bytes on each page of the database (often 1024). The second is the
** page number to look up in the pointer map.
**
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
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







-
+

-
+








-
+


-
-
+
+















-
+
+

+
-
+


+







** The ISAUTOVACUUM macro is used within balance_nonroot() to determine
** if the database supports auto-vacuum or not. Because it is used
** within an expression that is an argument to another macro 
** (sqliteMallocRaw), it is not possible to use conditional compilation.
** So, this macro is defined instead.
*/
#ifdef SQLITE_OMIT_AUTOVACUUM
#define ISAUTOVACUUM 0
#define ISAUTOVACUUM(pBt) 0
#else
#define ISAUTOVACUUM (pBt->autoVacuum)
#define ISAUTOVACUUM(pBt) (pBt->autoVacuum)
#endif

#ifdef SQLITE_OMIT_CONCURRENT
# define ISCONCURRENT 0
#else
# define ISCONCURRENT (pBt->pMap!=0)
#endif

#define REQUIRE_PTRMAP (ISAUTOVACUUM || ISCONCURRENT)
#define REQUIRE_PTRMAP (ISAUTOVACUUM(pBt) || ISCONCURRENT)

/*
** This structure is passed around through all the sanity checking routines
** in order to keep track of some global state information.
** This structure is passed around through all the PRAGMA integrity_check
** checking routines in order to keep track of some global state information.
**
** The aRef[] array is allocated so that there is 1 bit for each page in
** the database. As the integrity-check proceeds, for each page used in
** the database the corresponding bit is set. This allows integrity-check to 
** detect pages that are used twice and orphaned pages (both of which 
** indicate corruption).
*/
typedef struct IntegrityCk IntegrityCk;
struct IntegrityCk {
  BtShared *pBt;    /* The tree being checked out */
  Pager *pPager;    /* The associated pager.  Also accessible by pBt->pPager */
  u8 *aPgRef;       /* 1 bit per page in the db (see above) */
  Pgno nPage;       /* Number of pages in the database */
  int mxErr;        /* Stop accumulating errors when this reaches zero */
  int nErr;         /* Number of messages written to zErrMsg so far */
  int mallocFailed; /* A memory allocation error has occurred */
  int rc;           /* SQLITE_OK, SQLITE_NOMEM, or SQLITE_INTERRUPT */
  u32 nStep;        /* Number of steps into the integrity_check process */
  const char *zPfx; /* Error message prefix */
  Pgno v1;          /* Value for first %u substitution in zPfx */
  int v1, v2;       /* Values for up to two %d fields in zPfx */
  int v2;           /* Value for second %d substitution in zPfx */
  StrAccum errMsg;  /* Accumulate the error message text here */
  u32 *heap;        /* Min-heap used for analyzing cell coverage */
  sqlite3 *db;      /* Database connection running the check */
};

/*
** Routines to read or write a two- and four-byte big-endian integer values.
*/
#define get2byte(x)   ((x)[0]<<8 | (x)[1])
#define put2byte(p,v) ((p)[0] = (u8)((v)>>8), (p)[1] = (u8)(v))

Changes to src/build.c.

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







-
+














-
+


-
+



-
+





-
-
-
+
-







#ifndef SQLITE_OMIT_SHARED_CACHE
/*
** The TableLock structure is only used by the sqlite3TableLock() and
** codeTableLocks() functions.
*/
struct TableLock {
  int iDb;               /* The database containing the table to be locked */
  int iTab;              /* The root page of the table to be locked */
  Pgno iTab;             /* The root page of the table to be locked */
  u8 isWriteLock;        /* True for write lock.  False for a read lock */
  const char *zLockName; /* Name of the table */
};

/*
** Record the fact that we want to lock a table at run-time.  
**
** The table to be locked has root page iTab and is found in database iDb.
** A read or a write lock can be taken depending on isWritelock.
**
** This routine just records the fact that the lock is desired.  The
** code to make the lock occur is generated by a later call to
** codeTableLocks() which occurs during sqlite3FinishCoding().
*/
void sqlite3TableLock(
static SQLITE_NOINLINE void lockTable(
  Parse *pParse,     /* Parsing context */
  int iDb,           /* Index of the database containing the table to lock */
  int iTab,          /* Root page number of the table to be locked */
  Pgno iTab,         /* Root page number of the table to be locked */
  u8 isWriteLock,    /* True for a write lock */
  const char *zName  /* Name of the table to be locked */
){
  Parse *pToplevel = sqlite3ParseToplevel(pParse);
  Parse *pToplevel;
  int i;
  int nBytes;
  TableLock *p;
  assert( iDb>=0 );

#ifdef SQLITE_OMIT_CONCURRENT
  if( iDb==1 ) return;
  if( !sqlite3BtreeSharable(pParse->db->aDb[iDb].pBt) ) return;
  pToplevel = sqlite3ParseToplevel(pParse);
#endif
  for(i=0; i<pToplevel->nTableLock; i++){
    p = &pToplevel->aTableLock[i];
    if( p->iDb==iDb && p->iTab==iTab ){
      p->isWriteLock = (p->isWriteLock || isWriteLock);
      return;
    }
  }
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
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







+
+
+
+
+
+
+
+
+
+
+







-
+
-
-
-
+







    p->isWriteLock = isWriteLock;
    p->zLockName = zName;
  }else{
    pToplevel->nTableLock = 0;
    sqlite3OomFault(pToplevel->db);
  }
}
void sqlite3TableLock(
  Parse *pParse,     /* Parsing context */
  int iDb,           /* Index of the database containing the table to lock */
  Pgno iTab,         /* Root page number of the table to be locked */
  u8 isWriteLock,    /* True for a write lock */
  const char *zName  /* Name of the table to be locked */
){
  if( iDb==1 ) return;
  if( !sqlite3BtreeSharable(pParse->db->aDb[iDb].pBt) ) return;
  lockTable(pParse, iDb, iTab, isWriteLock, zName);
}

/*
** Code an OP_TableLock instruction for each table locked by the
** statement (configured by calls to sqlite3TableLock()).
*/
static void codeTableLocks(Parse *pParse){
  int i;
  Vdbe *pVdbe; 
  Vdbe *pVdbe = pParse->pVdbe; 

  pVdbe = sqlite3GetVdbe(pParse);
  assert( pVdbe!=0 ); /* sqlite3GetVdbe cannot fail: VDBE already allocated */
  assert( pVdbe!=0 );

  for(i=0; i<pParse->nTableLock; i++){
    TableLock *p = &pParse->aTableLock[i];
    int p1 = p->iDb;
    sqlite3VdbeAddOp4(pVdbe, OP_TableLock, p1, p->iTab, p->isWriteLock,
                      p->zLockName, P4_STATIC);
  }
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
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







+



+

-
-
+
+


+




+
+
+
+
+
+
-
+
+
+



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



















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

-
-
-
-
-
+
+
+
+
+


-
-
-
-
-
+
+
+
+
+

-
-
-
+
+
+

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

-
-
-
-
+
+
+
+
+
+

+
+
-
+
+


+
+
-
+













-
-
-
-
+
+
+
+
+

-
-
-
+
+
+




-

+



+





+
+
+
+
+
-
+




+
-
-
+
+







**
** Note that if an error occurred, it might be the case that
** no VDBE code was generated.
*/
void sqlite3FinishCoding(Parse *pParse){
  sqlite3 *db;
  Vdbe *v;
  int iDb, i;

  assert( pParse->pToplevel==0 );
  db = pParse->db;
  assert( db->pParse==pParse );
  if( pParse->nested ) return;
  if( db->mallocFailed || pParse->nErr ){
    if( pParse->rc==SQLITE_OK ) pParse->rc = SQLITE_ERROR;
  if( pParse->nErr ){
    if( db->mallocFailed ) pParse->rc = SQLITE_NOMEM;
    return;
  }
  assert( db->mallocFailed==0 );

  /* Begin by generating some termination code at the end of the
  ** vdbe program
  */
  v = pParse->pVdbe;
  if( v==0 ){
    if( db->init.busy ){
      pParse->rc = SQLITE_DONE;
      return;
    }
  v = sqlite3GetVdbe(pParse);
    v = sqlite3GetVdbe(pParse);
    if( v==0 ) pParse->rc = SQLITE_ERROR;
  }
  assert( !pParse->isMultiWrite 
       || sqlite3VdbeAssertMayAbort(v, pParse->mayAbort));
  if( v ){
    if( pParse->bReturning ){
      Returning *pReturning = pParse->u1.pReturning;
      int addrRewind;
      int reg;

      if( pReturning->nRetCol ){
        sqlite3VdbeAddOp0(v, OP_FkCheck);
        addrRewind =
           sqlite3VdbeAddOp1(v, OP_Rewind, pReturning->iRetCur);
        VdbeCoverage(v);
        reg = pReturning->iRetReg;
        for(i=0; i<pReturning->nRetCol; i++){
          sqlite3VdbeAddOp3(v, OP_Column, pReturning->iRetCur, i, reg+i);
        }
        sqlite3VdbeAddOp2(v, OP_ResultRow, reg, i);
        sqlite3VdbeAddOp2(v, OP_Next, pReturning->iRetCur, addrRewind+1);
        VdbeCoverage(v);
        sqlite3VdbeJumpHere(v, addrRewind);
      }
    }
    sqlite3VdbeAddOp0(v, OP_Halt);

#if SQLITE_USER_AUTHENTICATION
    if( pParse->nTableLock>0 && db->init.busy==0 ){
      sqlite3UserAuthInit(db);
      if( db->auth.authLevel<UAUTH_User ){
        sqlite3ErrorMsg(pParse, "user not authenticated");
        pParse->rc = SQLITE_AUTH_USER;
        return;
      }
    }
#endif

    /* The cookie mask contains one bit for each database file open.
    ** (Bit 0 is for main, bit 1 is for temp, and so forth.)  Bits are
    ** set for each database that is used.  Generate code to start a
    ** transaction on each used database and to verify the schema cookie
    ** on each used database.
    */
    if( db->mallocFailed==0 
     && (DbMaskNonZero(pParse->cookieMask) || pParse->pConstExpr)
    ){
      int iDb, i;
      assert( sqlite3VdbeGetOp(v, 0)->opcode==OP_Init );
      sqlite3VdbeJumpHere(v, 0);
      for(iDb=0; iDb<db->nDb; iDb++){
        Schema *pSchema;
        if( DbMaskTest(pParse->cookieMask, iDb)==0 ) continue;
        sqlite3VdbeUsesBtree(v, iDb);
        pSchema = db->aDb[iDb].pSchema;
        sqlite3VdbeAddOp4Int(v,
          OP_Transaction,                    /* Opcode */
          iDb,                               /* P1 */
          DbMaskTest(pParse->writeMask,iDb), /* P2 */
          pSchema->schema_cookie,            /* P3 */
          pSchema->iGeneration               /* P4 */
        );
        if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1);
        VdbeComment((v,
              "usesStmtJournal=%d", pParse->mayAbort && pParse->isMultiWrite));
    assert( pParse->nErr>0 || sqlite3VdbeGetOp(v, 0)->opcode==OP_Init );
    sqlite3VdbeJumpHere(v, 0);
    assert( db->nDb>0 );
    iDb = 0;
    do{
      Schema *pSchema;
      if( DbMaskTest(pParse->cookieMask, iDb)==0 ) continue;
      sqlite3VdbeUsesBtree(v, iDb);
      pSchema = db->aDb[iDb].pSchema;
      sqlite3VdbeAddOp4Int(v,
        OP_Transaction,                    /* Opcode */
        iDb,                               /* P1 */
        DbMaskTest(pParse->writeMask,iDb), /* P2 */
        pSchema->schema_cookie,            /* P3 */
        pSchema->iGeneration               /* P4 */
      );
      if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1);
      VdbeComment((v,
            "usesStmtJournal=%d", pParse->mayAbort && pParse->isMultiWrite));
      }
    }while( ++iDb<db->nDb );
#ifndef SQLITE_OMIT_VIRTUALTABLE
      for(i=0; i<pParse->nVtabLock; i++){
        char *vtab = (char *)sqlite3GetVTable(db, pParse->apVtabLock[i]);
        sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB);
      }
      pParse->nVtabLock = 0;
    for(i=0; i<pParse->nVtabLock; i++){
      char *vtab = (char *)sqlite3GetVTable(db, pParse->apVtabLock[i]);
      sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB);
    }
    pParse->nVtabLock = 0;
#endif

      /* Once all the cookies have been verified and transactions opened, 
      ** obtain the required table-locks. This is a no-op unless the 
      ** shared-cache feature is enabled.
      */
      codeTableLocks(pParse);
    /* Once all the cookies have been verified and transactions opened, 
    ** obtain the required table-locks. This is a no-op unless the 
    ** shared-cache feature is enabled.
    */
    codeTableLocks(pParse);

      /* Initialize any AUTOINCREMENT data structures required.
      */
      sqlite3AutoincrementBegin(pParse);
    /* Initialize any AUTOINCREMENT data structures required.
    */
    sqlite3AutoincrementBegin(pParse);

      /* Code constant expressions that where factored out of inner loops */
      if( pParse->pConstExpr ){
        ExprList *pEL = pParse->pConstExpr;
        pParse->okConstFactor = 0;
        for(i=0; i<pEL->nExpr; i++){
          sqlite3ExprCode(pParse, pEL->a[i].pExpr, pEL->a[i].u.iConstExprReg);
        }
      }
    /* Code constant expressions that where factored out of inner loops.
    **
    ** The pConstExpr list might also contain expressions that we simply
    ** want to keep around until the Parse object is deleted.  Such
    ** expressions have iConstExprReg==0.  Do not generate code for
    ** those expressions, of course.
    */
    if( pParse->pConstExpr ){
      ExprList *pEL = pParse->pConstExpr;
      pParse->okConstFactor = 0;
      for(i=0; i<pEL->nExpr; i++){
        int iReg = pEL->a[i].u.iConstExprReg;
        sqlite3ExprCode(pParse, pEL->a[i].pExpr, iReg);
      }
    }

      /* Finally, jump back to the beginning of the executable code. */
      sqlite3VdbeGoto(v, 1);
    }
  }
    if( pParse->bReturning ){
      Returning *pRet = pParse->u1.pReturning;
      if( pRet->nRetCol ){
        sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRet->iRetCur, pRet->nRetCol);
      }
    }

    /* Finally, jump back to the beginning of the executable code. */
    sqlite3VdbeGoto(v, 1);

  }

  /* Get the VDBE program ready for execution
  */
  assert( v!=0 || pParse->nErr );
  assert( db->mallocFailed==0 || pParse->nErr );
  if( v && pParse->nErr==0 && !db->mallocFailed ){
  if( pParse->nErr==0 ){
    /* A minimum of one cursor is required if autoincrement is used
    *  See ticket [a696379c1f08866] */
    assert( pParse->pAinc==0 || pParse->nTab>0 );
    sqlite3VdbeMakeReady(v, pParse);
    pParse->rc = SQLITE_DONE;
  }else{
    pParse->rc = SQLITE_ERROR;
  }
}

/*
** Run the parser and code generator recursively in order to generate
** code for the SQL statement given onto the end of the pParse context
** currently under construction.  When the parser is run recursively
** this way, the final OP_Halt is not appended and other initialization
** and finalization steps are omitted because those are handling by the
** outermost parser.
** currently under construction.  Notes:
**
**   *  The final OP_Halt is not appended and other initialization
**      and finalization steps are omitted because those are handling by the
**      outermost parser.
**
** Not everything is nestable.  This facility is designed to permit
** INSERT, UPDATE, and DELETE operations against SQLITE_MASTER.  Use
** care if you decide to try to use this routine for some other purposes.
**   *  Built-in SQL functions always take precedence over application-defined
**      SQL functions.  In other words, it is not possible to override a
**      built-in function.
*/
void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
  va_list ap;
  char *zSql;
  char *zErrMsg = 0;
  sqlite3 *db = pParse->db;
  u32 savedDbFlags = db->mDbFlags;
  char saveBuf[PARSE_TAIL_SZ];

  if( pParse->nErr ) return;
  if( pParse->eParseMode ) return;
  assert( pParse->nested<10 );  /* Nesting should only be of limited depth */
  va_start(ap, zFormat);
  zSql = sqlite3VMPrintf(db, zFormat, ap);
  va_end(ap);
  if( zSql==0 ){
    /* This can result either from an OOM or because the formatted string
    ** exceeds SQLITE_LIMIT_LENGTH.  In the latter case, we need to set
    ** an error */
    if( !db->mallocFailed ) pParse->rc = SQLITE_TOOBIG;
    pParse->nErr++;
    return;   /* A malloc must have failed */
    return;
  }
  pParse->nested++;
  memcpy(saveBuf, PARSE_TAIL(pParse), PARSE_TAIL_SZ);
  memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ);
  db->mDbFlags |= DBFLAG_PreferBuiltin;
  sqlite3RunParser(pParse, zSql, &zErrMsg);
  sqlite3DbFree(db, zErrMsg);
  sqlite3RunParser(pParse, zSql);
  db->mDbFlags = savedDbFlags;
  sqlite3DbFree(db, zSql);
  memcpy(PARSE_TAIL(pParse), saveBuf, PARSE_TAIL_SZ);
  pParse->nested--;
}

#if SQLITE_USER_AUTHENTICATION
/*
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
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







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







#if SQLITE_USER_AUTHENTICATION
  /* Only the admin user is allowed to know that the sqlite_user table
  ** exists */
  if( db->auth.authLevel<UAUTH_Admin && sqlite3UserAuthTable(zName)!=0 ){
    return 0;
  }
#endif
  while(1){
    for(i=OMIT_TEMPDB; i<db->nDb; i++){
  if( zDatabase ){
    for(i=0; i<db->nDb; i++){
      int j = (i<2) ? i^1 : i;   /* Search TEMP before MAIN */
      if( zDatabase==0 || sqlite3StrICmp(zDatabase, db->aDb[j].zDbSName)==0 ){
        assert( sqlite3SchemaMutexHeld(db, j, 0) );
        p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName);
        if( p ) return p;
      }
    }
      if( sqlite3StrICmp(zDatabase, db->aDb[i].zDbSName)==0 ) break;
    }
    if( i>=db->nDb ){
      /* No match against the official names.  But always match "main"
      ** to schema 0 as a legacy fallback. */
      if( sqlite3StrICmp(zDatabase,"main")==0 ){
        i = 0;
      }else{
        return 0;
      }
    }
    p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash, zName);
    if( p==0 && sqlite3StrNICmp(zName, "sqlite_", 7)==0 ){
      if( i==1 ){
        if( sqlite3StrICmp(zName+7, &PREFERRED_TEMP_SCHEMA_TABLE[7])==0
         || sqlite3StrICmp(zName+7, &PREFERRED_SCHEMA_TABLE[7])==0
         || sqlite3StrICmp(zName+7, &LEGACY_SCHEMA_TABLE[7])==0
        ){
          p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash, 
                              LEGACY_TEMP_SCHEMA_TABLE);
        }
      }else{
        if( sqlite3StrICmp(zName+7, &PREFERRED_SCHEMA_TABLE[7])==0 ){
          p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash,
                              LEGACY_SCHEMA_TABLE);
        }
      }
    }
  }else{
    /* Match against TEMP first */
    p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash, zName);
    if( p ) return p;
    /* The main database is second */
    p = sqlite3HashFind(&db->aDb[0].pSchema->tblHash, zName);
    if( p ) return p;
    /* Attached databases are in order of attachment */
    for(i=2; i<db->nDb; i++){
      assert( sqlite3SchemaMutexHeld(db, i, 0) );
      p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash, zName);
      if( p ) break;
    }
    if( p==0 && sqlite3StrNICmp(zName, "sqlite_", 7)==0 ){
      if( sqlite3StrICmp(zName+7, &PREFERRED_SCHEMA_TABLE[7])==0 ){
        p = sqlite3HashFind(&db->aDb[0].pSchema->tblHash, LEGACY_SCHEMA_TABLE);
      }else if( sqlite3StrICmp(zName+7, &PREFERRED_TEMP_SCHEMA_TABLE[7])==0 ){
        p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash, 
                            LEGACY_TEMP_SCHEMA_TABLE);
      }
    /* Not found.  If the name we were looking for was temp.sqlite_master
    ** then change the name to sqlite_temp_master and try again. */
    if( sqlite3StrICmp(zName, MASTER_NAME)!=0 ) break;
    if( sqlite3_stricmp(zDatabase, db->aDb[1].zDbSName)!=0 ) break;
    zName = TEMP_MASTER_NAME;
  }
  return 0;
    }
  }
  return p;
}

/*
** Locate the in-memory structure that describes a particular database
** table given the name of that table and (optionally) the name of the
** database containing the table.  Return NULL if not found.  Also leave an
** error message in pParse->zErrMsg.
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
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







-




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

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

















-
+











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







   && SQLITE_OK!=sqlite3ReadSchema(pParse)
  ){
    return 0;
  }

  p = sqlite3FindTable(db, zName, zDbase);
  if( p==0 ){
    const char *zMsg = flags & LOCATE_VIEW ? "no such view" : "no such table";
#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->prepFlags & SQLITE_PREPARE_NO_VTAB)==0 && db->init.busy==0 ){
    Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName);
    if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
      pMod = sqlite3PragmaVtabRegister(db, zName);
    }
    if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){
      return pMod->pEpoTab;
    }
      Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName);
      if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
        pMod = sqlite3PragmaVtabRegister(db, zName);
      }
      if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){
        testcase( pMod->pEpoTab==0 );
        return pMod->pEpoTab;
      }
    }
#endif
    if( (flags & LOCATE_NOERR)==0 ){
      if( zDbase ){
        sqlite3ErrorMsg(pParse, "%s: %s.%s", zMsg, zDbase, zName);
      }else{
        sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName);
      }
    if( flags & LOCATE_NOERR ) return 0;
    pParse->checkSchema = 1;
  }else if( IsVirtual(p) && (pParse->prepFlags & SQLITE_PREPARE_NO_VTAB)!=0 ){
    p = 0;
  }

  if( p==0 ){
    const char *zMsg = flags & LOCATE_VIEW ? "no such view" : "no such table";
    if( zDbase ){
      sqlite3ErrorMsg(pParse, "%s: %s.%s", zMsg, zDbase, zName);
    }else{
      sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName);
    }
      pParse->checkSchema = 1;
    }
  }else{
    assert( HasRowid(p) || p->iPKey<0 );
  }

  return p;
}

/*
** Locate the table identified by *p.
**
** This is a wrapper around sqlite3LocateTable(). The difference between
** sqlite3LocateTable() and this function is that this function restricts
** the search to schema (p->pSchema) if it is not NULL. p->pSchema may be
** non-NULL if it is part of a view or trigger program definition. See
** sqlite3FixSrcList() for details.
*/
Table *sqlite3LocateTableItem(
  Parse *pParse, 
  u32 flags,
  struct SrcList_item *p
  SrcItem *p
){
  const char *zDb;
  assert( p->pSchema==0 || p->zDatabase==0 );
  if( p->pSchema ){
    int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema);
    zDb = pParse->db->aDb[iDb].zDbSName;
  }else{
    zDb = p->zDatabase;
  }
  return sqlite3LocateTable(pParse, flags, p->zName, zDb);
}

/*
** Return the preferred table name for system tables.  Translate legacy
** names into the new preferred names, as appropriate.
*/
const char *sqlite3PreferredTableName(const char *zName){
  if( sqlite3StrNICmp(zName, "sqlite_", 7)==0 ){
    if( sqlite3StrICmp(zName+7, &LEGACY_SCHEMA_TABLE[7])==0 ){
      return PREFERRED_SCHEMA_TABLE;
    }
    if( sqlite3StrICmp(zName+7, &LEGACY_TEMP_SCHEMA_TABLE[7])==0 ){
      return PREFERRED_TEMP_SCHEMA_TABLE;
    }
  }
  return zName;
}

/*
** Locate the in-memory structure that describes 
** a particular index given the name of that index
** and the name of the database that contains the index.
** Return NULL if not found.
**
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
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







-
+


















-
+







  int i;
  /* All mutexes are required for schema access.  Make sure we hold them. */
  assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) );
  for(i=OMIT_TEMPDB; i<db->nDb; i++){
    int j = (i<2) ? i^1 : i;  /* Search TEMP before MAIN */
    Schema *pSchema = db->aDb[j].pSchema;
    assert( pSchema );
    if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zDbSName) ) continue;
    if( zDb && sqlite3DbIsNamed(db, j, zDb)==0 ) continue;
    assert( sqlite3SchemaMutexHeld(db, j, 0) );
    p = sqlite3HashFind(&pSchema->idxHash, zName);
    if( p ) break;
  }
  return p;
}

/*
** Reclaim the memory used by an index
*/
void sqlite3FreeIndex(sqlite3 *db, Index *p){
#ifndef SQLITE_OMIT_ANALYZE
  sqlite3DeleteIndexSamples(db, p);
#endif
  sqlite3ExprDelete(db, p->pPartIdxWhere);
  sqlite3ExprListDelete(db, p->aColExpr);
  sqlite3DbFree(db, p->zColAff);
  if( p->isResized ) sqlite3DbFree(db, (void *)p->azColl);
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
  sqlite3_free(p->aiRowEst);
#endif
  sqlite3DbFree(db, p);
}

/*
** For the index called zIdxName which is found in the database iDb,
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
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
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









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







+


+
-
-
-
+
+
+
+
+

+
-
+
+
+
+
+
+








/*
** This routine is called when a commit occurs.
*/
void sqlite3CommitInternalChanges(sqlite3 *db){
  db->mDbFlags &= ~DBFLAG_SchemaChange;
}

/*
** Set the expression associated with a column.  This is usually
** the DEFAULT value, but might also be the expression that computes
** the value for a generated column.
*/
void sqlite3ColumnSetExpr(
  Parse *pParse,    /* Parsing context */
  Table *pTab,      /* The table containing the column */
  Column *pCol,     /* The column to receive the new DEFAULT expression */
  Expr *pExpr       /* The new default expression */
){
  ExprList *pList;
  assert( IsOrdinaryTable(pTab) );
  pList = pTab->u.tab.pDfltList;
  if( pCol->iDflt==0
   || NEVER(pList==0)
   || NEVER(pList->nExpr<pCol->iDflt)
  ){
    pCol->iDflt = pList==0 ? 1 : pList->nExpr+1;
    pTab->u.tab.pDfltList = sqlite3ExprListAppend(pParse, pList, pExpr);
  }else{
    sqlite3ExprDelete(pParse->db, pList->a[pCol->iDflt-1].pExpr);
    pList->a[pCol->iDflt-1].pExpr = pExpr;
  }
}

/*
** Return the expression associated with a column.  The expression might be
** the DEFAULT clause or the AS clause of a generated column.
** Return NULL if the column has no associated expression.
*/
Expr *sqlite3ColumnExpr(Table *pTab, Column *pCol){
  if( pCol->iDflt==0 ) return 0;
  if( NEVER(!IsOrdinaryTable(pTab)) ) return 0;
  if( NEVER(pTab->u.tab.pDfltList==0) ) return 0;
  if( NEVER(pTab->u.tab.pDfltList->nExpr<pCol->iDflt) ) return 0;
  return pTab->u.tab.pDfltList->a[pCol->iDflt-1].pExpr;
}

/*
** Set the collating sequence name for a column.
*/
void sqlite3ColumnSetColl(
  sqlite3 *db,
  Column *pCol,
  const char *zColl
){
  i64 nColl;
  i64 n;
  char *zNew;
  assert( zColl!=0 );
  n = sqlite3Strlen30(pCol->zCnName) + 1;
  if( pCol->colFlags & COLFLAG_HASTYPE ){
    n += sqlite3Strlen30(pCol->zCnName+n) + 1;
  }
  nColl = sqlite3Strlen30(zColl) + 1;
  zNew = sqlite3DbRealloc(db, pCol->zCnName, nColl+n);
  if( zNew ){
    pCol->zCnName = zNew;
    memcpy(pCol->zCnName + n, zColl, nColl);
    pCol->colFlags |= COLFLAG_HASCOLL;
  }
}

/*
** Return the collating squence name for a column
*/
const char *sqlite3ColumnColl(Column *pCol){
  const char *z;
  if( (pCol->colFlags & COLFLAG_HASCOLL)==0 ) return 0;
  z = pCol->zCnName;
  while( *z ){ z++; }
  if( pCol->colFlags & COLFLAG_HASTYPE ){
    do{ z++; }while( *z );
  }
  return z+1;
}

/*
** Delete memory allocated for the column names of a table or view (the
** Table.aCol[] array).
*/
void sqlite3DeleteColumnNames(sqlite3 *db, Table *pTable){
  int i;
  Column *pCol;
  assert( pTable!=0 );
  assert( db!=0 );
  if( (pCol = pTable->aCol)!=0 ){
    for(i=0; i<pTable->nCol; i++, pCol++){
      assert( pCol->zCnName==0 || pCol->hName==sqlite3StrIHash(pCol->zCnName) );
      sqlite3DbFree(db, pCol->zName);
      sqlite3ExprDelete(db, pCol->pDflt);
      sqlite3DbFree(db, pCol->zColl);
      sqlite3DbFree(db, pCol->zCnName);
    }
    sqlite3DbNNFreeNN(db, pTable->aCol);
    if( IsOrdinaryTable(pTable) ){
      sqlite3ExprListDelete(db, pTable->u.tab.pDfltList);
    }
    if( db->pnBytesFreed==0 ){
    sqlite3DbFree(db, pTable->aCol);
      pTable->aCol = 0;
      pTable->nCol = 0;
      if( IsOrdinaryTable(pTable) ){
        pTable->u.tab.pDfltList = 0;
      }
    }
  }
}

/*
** Remove the memory data structures associated with the given
** Table.  No changes are made to disk by this routine.
**
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
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







-
-
+
+
+
+
+
+

+
-
+









-
+










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






-

-
-
-







+

-
+







** used by the Table object.
*/
static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){
  Index *pIndex, *pNext;

#ifdef SQLITE_DEBUG
  /* Record the number of outstanding lookaside allocations in schema Tables
  ** prior to doing any free() operations.  Since schema Tables do not use
  ** lookaside, this number should not change. */
  ** prior to doing any free() operations. Since schema Tables do not use
  ** lookaside, this number should not change. 
  **
  ** If malloc has already failed, it may be that it failed while allocating
  ** a Table object that was going to be marked ephemeral. So do not check
  ** that no lookaside memory is used in this case either. */
  int nLookaside = 0;
  assert( db!=0 );
  if( db && (pTable->tabFlags & TF_Ephemeral)==0 ){
  if( !db->mallocFailed && (pTable->tabFlags & TF_Ephemeral)==0 ){
    nLookaside = sqlite3LookasideUsed(db, 0);
  }
#endif

  /* Delete all indices associated with this table. */
  for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){
    pNext = pIndex->pNext;
    assert( pIndex->pSchema==pTable->pSchema
         || (IsVirtual(pTable) && pIndex->idxType!=SQLITE_IDXTYPE_APPDEF) );
    if( (db==0 || db->pnBytesFreed==0) && !IsVirtual(pTable) ){
    if( db->pnBytesFreed==0 && !IsVirtual(pTable) ){
      char *zName = pIndex->zName; 
      TESTONLY ( Index *pOld = ) sqlite3HashInsert(
         &pIndex->pSchema->idxHash, zName, 0
      );
      assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) );
      assert( pOld==pIndex || pOld==0 );
    }
    sqlite3FreeIndex(db, pIndex);
  }

  /* Delete any foreign keys attached to this table. */
  sqlite3FkDelete(db, pTable);
  if( IsOrdinaryTable(pTable) ){
    sqlite3FkDelete(db, pTable);
  }
#ifndef SQLITE_OMIT_VIRTUAL_TABLE
  else if( IsVirtual(pTable) ){
    sqlite3VtabClear(db, pTable);
  }
#endif
  else{
    assert( IsView(pTable) );
    sqlite3SelectDelete(db, pTable->u.view.pSelect);
  }

  /* Delete the Table structure itself.
  */
  sqlite3DeleteColumnNames(db, pTable);
  sqlite3DbFree(db, pTable->zName);
  sqlite3DbFree(db, pTable->zColAff);
  sqlite3SelectDelete(db, pTable->pSelect);
  sqlite3ExprListDelete(db, pTable->pCheck);
#ifndef SQLITE_OMIT_VIRTUALTABLE
  sqlite3VtabClear(db, pTable);
#endif
  sqlite3DbFree(db, pTable);

  /* Verify that no lookaside memory was used by schema tables */
  assert( nLookaside==0 || nLookaside==sqlite3LookasideUsed(db,0) );
}
void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
  /* Do not delete the table until the reference count reaches zero. */
  assert( db!=0 );
  if( !pTable ) return;
  if( ((!db || db->pnBytesFreed==0) && (--pTable->nTabRef)>0) ) return;
  if( db->pnBytesFreed==0 && (--pTable->nTabRef)>0 ) return;
  deleteTable(db, pTable);
}


/*
** Unlink the given table from the hash tables and the delete the
** table structure with all its indices and foreign keys.
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
906
907
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
935
936
937
938







-
+


-
+








-
+


-
+

-
-
+
+







** Any quotation marks (ex:  "name", 'name', [name], or `name`) that
** surround the body of the token are removed.
**
** Tokens are often just pointers into the original SQL text and so
** are not \000 terminated and are not persistent.  The returned string
** is \000 terminated and is persistent.
*/
char *sqlite3NameFromToken(sqlite3 *db, Token *pName){
char *sqlite3NameFromToken(sqlite3 *db, const Token *pName){
  char *zName;
  if( pName ){
    zName = sqlite3DbStrNDup(db, (char*)pName->z, pName->n);
    zName = sqlite3DbStrNDup(db, (const char*)pName->z, pName->n);
    sqlite3Dequote(zName);
  }else{
    zName = 0;
  }
  return zName;
}

/*
** Open the sqlite_master table stored in database number iDb for
** Open the sqlite_schema table stored in database number iDb for
** writing. The table is opened using cursor 0.
*/
void sqlite3OpenMasterTable(Parse *p, int iDb){
void sqlite3OpenSchemaTable(Parse *p, int iDb){
  Vdbe *v = sqlite3GetVdbe(p);
  sqlite3TableLock(p, iDb, MASTER_ROOT, 1, MASTER_NAME);
  sqlite3VdbeAddOp4Int(v, OP_OpenWrite, 0, MASTER_ROOT, iDb, 5);
  sqlite3TableLock(p, iDb, SCHEMA_ROOT, 1, LEGACY_SCHEMA_TABLE);
  sqlite3VdbeAddOp4Int(v, OP_OpenWrite, 0, SCHEMA_ROOT, iDb, 5);
  if( p->nTab==0 ){
    p->nTab = 1;
  }
}

/*
** Parameter zName points to a nul-terminated buffer containing the name
784
785
786
787
788
789
790
791

792
793
794
795
796
797
798
1003
1004
1005
1006
1007
1008
1009

1010
1011
1012
1013
1014
1015
1016
1017







-
+







    *pUnqual = pName2;
    iDb = sqlite3FindDb(db, pName1);
    if( iDb<0 ){
      sqlite3ErrorMsg(pParse, "unknown database %T", pName1);
      return -1;
    }
  }else{
    assert( db->init.iDb==0 || db->init.busy || IN_RENAME_OBJECT
    assert( db->init.iDb==0 || db->init.busy || IN_SPECIAL_PARSE
             || (db->mDbFlags & DBFLAG_Vacuum)!=0);
    iDb = db->init.iDb;
    *pUnqual = pName1;
  }
  return iDb;
}

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







+
+
+
+

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














+
-
-
+
+
+

-
+






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








/*
** This routine is used to check if the UTF-8 string zName is a legal
** unqualified name for a new schema object (table, index, view or
** trigger). All names are legal except those that begin with the string
** "sqlite_" (in upper, lower or mixed case). This portion of the namespace
** is reserved for internal use.
**
** When parsing the sqlite_schema table, this routine also checks to
** make sure the "type", "name", and "tbl_name" columns are consistent
** with the SQL.
*/
int sqlite3CheckObjectName(Parse *pParse, const char *zName){
  if( !pParse->db->init.busy && pParse->nested==0 
          && sqlite3WritableSchema(pParse->db)==0
          && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
    sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName);
    return SQLITE_ERROR;
int sqlite3CheckObjectName(
  Parse *pParse,            /* Parsing context */
  const char *zName,        /* Name of the object to check */
  const char *zType,        /* Type of this object */
  const char *zTblName      /* Parent table name for triggers and indexes */
){
  sqlite3 *db = pParse->db;
  if( sqlite3WritableSchema(db)
   || db->init.imposterTable
   || !sqlite3Config.bExtraSchemaChecks
  ){
    /* Skip these error checks for writable_schema=ON */
    return SQLITE_OK;
  }
  if( db->init.busy ){
    if( sqlite3_stricmp(zType, db->init.azInit[0])
     || sqlite3_stricmp(zName, db->init.azInit[1])
     || sqlite3_stricmp(zTblName, db->init.azInit[2])
    ){
      sqlite3ErrorMsg(pParse, ""); /* corruptSchema() will supply the error */
      return SQLITE_ERROR;
    }
  }else{
    if( (pParse->nested==0 && 0==sqlite3StrNICmp(zName, "sqlite_", 7))
     || (sqlite3ReadOnlyShadowTables(db) && sqlite3ShadowTableName(db, zName))
    ){
      sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s",
                      zName);
      return SQLITE_ERROR;
    }

  }
  return SQLITE_OK;
}

/*
** Return the PRIMARY KEY index of a table
*/
Index *sqlite3PrimaryKeyIndex(Table *pTab){
  Index *p;
  for(p=pTab->pIndex; p && !IsPrimaryKeyIndex(p); p=p->pNext){}
  return p;
}

/*
** Convert an table column number into a index column number.  That is,
** Return the column of index pIdx that corresponds to table
** column iCol.  Return -1 if not found.
** for the column iCol in the table (as defined by the CREATE TABLE statement)
** find the (first) offset of that column in index pIdx.  Or return -1
** if column iCol is not used in index pIdx.
*/
i16 sqlite3ColumnOfIndex(Index *pIdx, i16 iCol){
i16 sqlite3TableColumnToIndex(Index *pIdx, i16 iCol){
  int i;
  for(i=0; i<pIdx->nColumn; i++){
    if( iCol==pIdx->aiColumn[i] ) return i;
  }
  return -1;
}

#ifndef SQLITE_OMIT_GENERATED_COLUMNS
/* Convert a storage column number into a table column number.
**
** The storage column number (0,1,2,....) is the index of the value
** as it appears in the record on disk.  The true column number
** is the index (0,1,2,...) of the column in the CREATE TABLE statement.
**
** The storage column number is less than the table column number if
** and only there are VIRTUAL columns to the left.
**
** If SQLITE_OMIT_GENERATED_COLUMNS, this routine is a no-op macro.
*/
i16 sqlite3StorageColumnToTable(Table *pTab, i16 iCol){
  if( pTab->tabFlags & TF_HasVirtual ){
    int i;
    for(i=0; i<=iCol; i++){
      if( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ) iCol++;
    }
  }
  return iCol;
}
#endif

#ifndef SQLITE_OMIT_GENERATED_COLUMNS
/* Convert a table column number into a storage column number.
**
** The storage column number (0,1,2,....) is the index of the value
** as it appears in the record on disk.  Or, if the input column is
** the N-th virtual column (zero-based) then the storage number is
** the number of non-virtual columns in the table plus N.  
**
** The true column number is the index (0,1,2,...) of the column in
** the CREATE TABLE statement.
**
** If the input column is a VIRTUAL column, then it should not appear
** in storage.  But the value sometimes is cached in registers that
** follow the range of registers used to construct storage.  This
** avoids computing the same VIRTUAL column multiple times, and provides
** values for use by OP_Param opcodes in triggers.  Hence, if the
** input column is a VIRTUAL table, put it after all the other columns.
**
** In the following, N means "normal column", S means STORED, and
** V means VIRTUAL.  Suppose the CREATE TABLE has columns like this:
**
**        CREATE TABLE ex(N,S,V,N,S,V,N,S,V);
**                     -- 0 1 2 3 4 5 6 7 8
**
** Then the mapping from this function is as follows:
**
**    INPUTS:     0 1 2 3 4 5 6 7 8
**    OUTPUTS:    0 1 6 2 3 7 4 5 8
**
** So, in other words, this routine shifts all the virtual columns to
** the end.
**
** If SQLITE_OMIT_GENERATED_COLUMNS then there are no virtual columns and
** this routine is a no-op macro.  If the pTab does not have any virtual
** columns, then this routine is no-op that always return iCol.  If iCol
** is negative (indicating the ROWID column) then this routine return iCol.
*/
i16 sqlite3TableColumnToStorage(Table *pTab, i16 iCol){
  int i;
  i16 n;
  assert( iCol<pTab->nCol );
  if( (pTab->tabFlags & TF_HasVirtual)==0 || iCol<0 ) return iCol;
  for(i=0, n=0; i<iCol; i++){
    if( (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ) n++;
  }
  if( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ){
    /* iCol is a virtual column itself */
    return pTab->nNVCol + i - n;
  }else{
    /* iCol is a normal or stored column */
    return n;
  }
}
#endif

/*
** Insert a single OP_JournalMode query opcode in order to force the
** prepared statement to return false for sqlite3_stmt_readonly().  This
** is used by CREATE TABLE IF NOT EXISTS and similar if the table already
** exists, so that the prepared statement for CREATE TABLE IF NOT EXISTS
** will return false for sqlite3_stmt_readonly() even if that statement
** is a read-only no-op.
*/
static void sqlite3ForceNotReadOnly(Parse *pParse){
  int iReg = ++pParse->nMem;
  Vdbe *v = sqlite3GetVdbe(pParse);
  if( v ){
    sqlite3VdbeAddOp3(v, OP_JournalMode, 0, iReg, PAGER_JOURNALMODE_QUERY);
    sqlite3VdbeUsesBtree(v, 0);
  }
}

/*
** Begin constructing a new table representation in memory.  This is
** the first of several action routines that get called in response
** to a CREATE TABLE statement.  In particular, this routine is called
** after seeing tokens "CREATE" and "TABLE" and the table name. The isTemp
** flag is true if the table should be stored in the auxiliary database
877
878
879
880
881
882
883
884

885
886
887
888
889
890
891
1222
1223
1224
1225
1226
1227
1228

1229
1230
1231
1232
1233
1234
1235
1236







-
+







  char *zName = 0; /* The name of the new table */
  sqlite3 *db = pParse->db;
  Vdbe *v;
  int iDb;         /* Database number to create the table in */
  Token *pName;    /* Unqualified name of the table to create */

  if( db->init.busy && db->init.newTnum==1 ){
    /* Special case:  Parsing the sqlite_master or sqlite_temp_master schema */
    /* Special case:  Parsing the sqlite_schema or sqlite_temp_schema schema */
    iDb = db->init.iDb;
    zName = sqlite3DbStrDup(db, SCHEMA_TABLE(iDb));
    pName = pName1;
  }else{
    /* The common case */
    iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
    if( iDb<0 ) return;
899
900
901
902
903
904
905
906

907
908
909
910
911
912
913
1244
1245
1246
1247
1248
1249
1250

1251
1252
1253
1254
1255
1256
1257
1258







-
+







    zName = sqlite3NameFromToken(db, pName);
    if( IN_RENAME_OBJECT ){
      sqlite3RenameTokenMap(pParse, (void*)zName, pName);
    }
  }
  pParse->sNameToken = *pName;
  if( zName==0 ) return;
  if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
  if( sqlite3CheckObjectName(pParse, zName, isView?"view":"table", zName) ){
    goto begin_table_error;
  }
  if( db->init.iDb==1 ) isTemp = 1;
#ifndef SQLITE_OMIT_AUTHORIZATION
  assert( isTemp==0 || isTemp==1 );
  assert( isView==0 || isView==1 );
  {
939
940
941
942
943
944
945
946


947
948
949

950
951
952
953
954
955
956
1284
1285
1286
1287
1288
1289
1290

1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303







-
+
+



+







    char *zDb = db->aDb[iDb].zDbSName;
    if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
      goto begin_table_error;
    }
    pTable = sqlite3FindTable(db, zName, zDb);
    if( pTable ){
      if( !noErr ){
        sqlite3ErrorMsg(pParse, "table %T already exists", pName);
        sqlite3ErrorMsg(pParse, "%s %T already exists",
                        (IsView(pTable)? "view" : "table"), pName);
      }else{
        assert( !db->init.busy || CORRUPT_DB );
        sqlite3CodeVerifySchema(pParse, iDb);
        sqlite3ForceNotReadOnly(pParse);
      }
      goto begin_table_error;
    }
    if( sqlite3FindIndex(db, zName, zDb)!=0 ){
      sqlite3ErrorMsg(pParse, "there is already an index named %s", zName);
      goto begin_table_error;
    }
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990

991
992
993
994
995
996
997
1318
1319
1320
1321
1322
1323
1324











1325

1326
1327
1328
1329
1330
1331
1332
1333







-
-
-
-
-
-
-
-
-
-
-

-
+







  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 SQLITE_MASTER table.  Note in particular that we must go ahead
  ** 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.
  */
  if( !db->init.busy && (v = sqlite3GetVdbe(pParse))!=0 ){
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
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
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494

1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
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
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
1574
1575

1576
1577
1578


1579
1580
1581
1582
1583


1584
1585
1586
1587
1588
1589
1590


1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605







-
+














+
-
+


-
+












+









-
+

+






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









-
+






+
+
+
+
+
+





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

-
-
-
+
+
+

+

-
+





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


-
+
+


-
+


-
-
+
+
+

+
-
-
+
+
+




-
-
+
+





+







    addr1 = sqlite3VdbeAddOp1(v, OP_If, reg3); VdbeCoverage(v);
    fileFormat = (db->flags & SQLITE_LegacyFileFmt)!=0 ?
                  1 : SQLITE_MAX_FILE_FORMAT;
    sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, fileFormat);
    sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_TEXT_ENCODING, ENC(db));
    sqlite3VdbeJumpHere(v, addr1);

    /* This just creates a place-holder record in the sqlite_master table.
    /* This just creates a place-holder record in the sqlite_schema table.
    ** The record created does not contain anything yet.  It will be replaced
    ** by the real entry in code generated at sqlite3EndTable().
    **
    ** The rowid for the new entry is left in register pParse->regRowid.
    ** The root page number of the new table is left in reg pParse->regRoot.
    ** The rowid and root page number values are needed by the code that
    ** sqlite3EndTable will generate.
    */
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
    if( isView || isVirtual ){
      sqlite3VdbeAddOp2(v, OP_Integer, 0, reg2);
    }else
#endif
    {
      assert( !pParse->bReturning );
      pParse->addrCrTab =
      pParse->u1.addrCrTab =
         sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, reg2, BTREE_INTKEY);
    }
    sqlite3OpenMasterTable(pParse, iDb);
    sqlite3OpenSchemaTable(pParse, iDb);
    sqlite3VdbeAddOp2(v, OP_NewRowid, 0, reg1);
    sqlite3VdbeAddOp4(v, OP_Blob, 6, reg3, 0, nullRow, P4_STATIC);
    sqlite3VdbeAddOp3(v, OP_Insert, 0, reg3, reg1);
    sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
    sqlite3VdbeAddOp0(v, OP_Close);
  }

  /* Normal (non-error) return. */
  return;

  /* If an error occurs, we jump here */
begin_table_error:
  pParse->checkSchema = 1;
  sqlite3DbFree(db, zName);
  return;
}

/* Set properties of a table column based on the (magical)
** name of the column.
*/
#if SQLITE_ENABLE_HIDDEN_COLUMNS
void sqlite3ColumnPropertiesFromName(Table *pTab, Column *pCol){
  if( sqlite3_strnicmp(pCol->zName, "__hidden__", 10)==0 ){
  if( sqlite3_strnicmp(pCol->zCnName, "__hidden__", 10)==0 ){
    pCol->colFlags |= COLFLAG_HIDDEN;
    if( pTab ) pTab->tabFlags |= TF_HasHidden;
  }else if( pTab && pCol!=pTab->aCol && (pCol[-1].colFlags & COLFLAG_HIDDEN) ){
    pTab->tabFlags |= TF_OOOHidden;
  }
}
#endif

/*
** Name of the special TEMP trigger used to implement RETURNING.  The
** name begins with "sqlite_" so that it is guaranteed not to collide
** with any application-generated triggers.
*/
#define RETURNING_TRIGGER_NAME  "sqlite_returning"

/*
** Clean up the data structures associated with the RETURNING clause.
*/
static void sqlite3DeleteReturning(sqlite3 *db, Returning *pRet){
  Hash *pHash;
  pHash = &(db->aDb[1].pSchema->trigHash);
  sqlite3HashInsert(pHash, RETURNING_TRIGGER_NAME, 0);
  sqlite3ExprListDelete(db, pRet->pReturnEL);
  sqlite3DbFree(db, pRet);
}

/*
** Add the RETURNING clause to the parse currently underway.
**
** This routine creates a special TEMP trigger that will fire for each row
** of the DML statement.  That TEMP trigger contains a single SELECT
** statement with a result set that is the argument of the RETURNING clause.
** The trigger has the Trigger.bReturning flag and an opcode of
** TK_RETURNING instead of TK_SELECT, so that the trigger code generator
** knows to handle it specially.  The TEMP trigger is automatically
** removed at the end of the parse.
**
** When this routine is called, we do not yet know if the RETURNING clause
** is attached to a DELETE, INSERT, or UPDATE, so construct it as a
** RETURNING trigger instead.  It will then be converted into the appropriate
** type on the first call to sqlite3TriggersExist().
*/
void sqlite3AddReturning(Parse *pParse, ExprList *pList){
  Returning *pRet;
  Hash *pHash;
  sqlite3 *db = pParse->db;
  if( pParse->pNewTrigger ){
    sqlite3ErrorMsg(pParse, "cannot use RETURNING in a trigger");
  }else{
    assert( pParse->bReturning==0 );
  }
  pParse->bReturning = 1;
  pRet = sqlite3DbMallocZero(db, sizeof(*pRet));
  if( pRet==0 ){
    sqlite3ExprListDelete(db, pList);
    return;
  }
  pParse->u1.pReturning = pRet;
  pRet->pParse = pParse;
  pRet->pReturnEL = pList;
  sqlite3ParserAddCleanup(pParse,
     (void(*)(sqlite3*,void*))sqlite3DeleteReturning, pRet);
  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)
          ==&pRet->retTrig ){
    sqlite3OomFault(db);
  }
}

/*
** Add a new column to the table currently being constructed.
**
** The parser calls this routine once for each column declaration
** in a CREATE TABLE statement.  sqlite3StartTable() gets called
** first to get things going.  Then this routine is called for each
** column.
*/
void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){
void sqlite3AddColumn(Parse *pParse, Token sName, Token sType){
  Table *p;
  int i;
  char *z;
  char *zType;
  Column *pCol;
  sqlite3 *db = pParse->db;
  u8 hName;
  Column *aNew;
  u8 eType = COLTYPE_CUSTOM;
  u8 szEst = 1;
  char affinity = SQLITE_AFF_BLOB;

  if( (p = pParse->pNewTable)==0 ) return;
  if( p->nCol+1>db->aLimit[SQLITE_LIMIT_COLUMN] ){
    sqlite3ErrorMsg(pParse, "too many columns on %s", p->zName);
    return;
  }
  if( !IN_RENAME_OBJECT ) sqlite3DequoteToken(&sName);

  /* Because keywords GENERATE ALWAYS can be converted into indentifiers
  ** by the parser, we can sometimes end up with a typename that ends
  ** with "generated always".  Check for this case and omit the surplus
  ** text. */
  if( sType.n>=16
   && sqlite3_strnicmp(sType.z+(sType.n-6),"always",6)==0
  ){
    sType.n -= 6;
    while( ALWAYS(sType.n>0) && sqlite3Isspace(sType.z[sType.n-1]) ) sType.n--;
    if( sType.n>=9
     && sqlite3_strnicmp(sType.z+(sType.n-9),"generated",9)==0
    ){
      sType.n -= 9;
      while( sType.n>0 && sqlite3Isspace(sType.z[sType.n-1]) ) sType.n--;
    }
  }

  /* Check for standard typenames.  For standard typenames we will
  ** set the Column.eType field rather than storing the typename after
  ** the column name, in order to save space. */
  if( sType.n>=3 ){
    sqlite3DequoteToken(&sType);
    for(i=0; i<SQLITE_N_STDTYPE; i++){
       if( sType.n==sqlite3StdTypeLen[i]
        && sqlite3_strnicmp(sType.z, sqlite3StdType[i], sType.n)==0
       ){
         sType.n = 0;
         eType = i+1;
         affinity = sqlite3StdTypeAffinity[i];
         if( affinity<=SQLITE_AFF_TEXT ) szEst = 5;
         break;
       }
    }
  }

  z = sqlite3DbMallocRaw(db, pName->n + pType->n + 2);
  z = sqlite3DbMallocRaw(db, (i64)sName.n + 1 + (i64)sType.n + (sType.n>0) );
  if( z==0 ) return;
  if( IN_RENAME_OBJECT ) sqlite3RenameTokenMap(pParse, (void*)z, pName);
  memcpy(z, pName->z, pName->n);
  z[pName->n] = 0;
  if( IN_RENAME_OBJECT ) sqlite3RenameTokenMap(pParse, (void*)z, &sName);
  memcpy(z, sName.z, sName.n);
  z[sName.n] = 0;
  sqlite3Dequote(z);
  hName = sqlite3StrIHash(z);
  for(i=0; i<p->nCol; i++){
    if( sqlite3_stricmp(z, p->aCol[i].zName)==0 ){
    if( p->aCol[i].hName==hName && sqlite3StrICmp(z, p->aCol[i].zCnName)==0 ){
      sqlite3ErrorMsg(pParse, "duplicate column name: %s", z);
      sqlite3DbFree(db, z);
      return;
    }
  }
  if( (p->nCol & 0x7)==0 ){
    Column *aNew;
    aNew = sqlite3DbRealloc(db,p->aCol,(p->nCol+8)*sizeof(p->aCol[0]));
    if( aNew==0 ){
      sqlite3DbFree(db, z);
      return;
    }
    p->aCol = aNew;
  aNew = sqlite3DbRealloc(db,p->aCol,((i64)p->nCol+1)*sizeof(p->aCol[0]));
  if( aNew==0 ){
    sqlite3DbFree(db, z);
    return;
  }
  p->aCol = aNew;
  }
  pCol = &p->aCol[p->nCol];
  memset(pCol, 0, sizeof(p->aCol[0]));
  pCol->zName = z;
  pCol->zCnName = z;
  pCol->hName = hName;
  sqlite3ColumnPropertiesFromName(p, pCol);
 
  if( pType->n==0 ){
  if( sType.n==0 ){
    /* If there is no type specified, columns have the default affinity
    ** 'BLOB' with a default size of 4 bytes. */
    pCol->affinity = SQLITE_AFF_BLOB;
    pCol->szEst = 1;
    pCol->affinity = affinity;
    pCol->eCType = eType;
    pCol->szEst = szEst;
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
    if( affinity==SQLITE_AFF_BLOB ){
    if( 4>=sqlite3GlobalConfig.szSorterRef ){
      pCol->colFlags |= COLFLAG_SORTERREF;
      if( 4>=sqlite3GlobalConfig.szSorterRef ){
        pCol->colFlags |= COLFLAG_SORTERREF;
      }
    }
#endif
  }else{
    zType = z + sqlite3Strlen30(z) + 1;
    memcpy(zType, pType->z, pType->n);
    zType[pType->n] = 0;
    memcpy(zType, sType.z, sType.n);
    zType[sType.n] = 0;
    sqlite3Dequote(zType);
    pCol->affinity = sqlite3AffinityType(zType, pCol);
    pCol->colFlags |= COLFLAG_HASTYPE;
  }
  p->nCol++;
  p->nNVCol++;
  pParse->constraintName.n = 0;
}

/*
** This routine is called by the parser while in the middle of
** parsing a CREATE TABLE statement.  A "NOT NULL" constraint has
** been seen on a column.  This routine sets the notNull flag on
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
1736
1737
1738
1739
1740
1741
1742
1743
1744

1745
1746

1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757

1758

1759
1760
1761
1762
1763

1764
1765
1766
1767
1768
1769
1770
1771
1772
1773







+

-
+

-
+
+
+
+
+
+
+




-
+
-





-
+

+







  const char *zEnd         /* First character past end of defaut value text */
){
  Table *p;
  Column *pCol;
  sqlite3 *db = pParse->db;
  p = pParse->pNewTable;
  if( p!=0 ){
    int isInit = db->init.busy && db->init.iDb!=1;
    pCol = &(p->aCol[p->nCol-1]);
    if( !sqlite3ExprIsConstantOrFunction(pExpr, db->init.busy) ){
    if( !sqlite3ExprIsConstantOrFunction(pExpr, isInit) ){
      sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant",
          pCol->zName);
          pCol->zCnName);
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
    }else if( pCol->colFlags & COLFLAG_GENERATED ){
      testcase( pCol->colFlags & COLFLAG_VIRTUAL );
      testcase( pCol->colFlags & COLFLAG_STORED );
      sqlite3ErrorMsg(pParse, "cannot use DEFAULT on a generated column");
#endif
    }else{
      /* A copy of pExpr is used instead of the original, as pExpr contains
      ** tokens that point to volatile memory.
      */
      Expr x;
      Expr x, *pDfltExpr;
      sqlite3ExprDelete(db, pCol->pDflt);
      memset(&x, 0, sizeof(x));
      x.op = TK_SPAN;
      x.u.zToken = sqlite3DbSpanDup(db, zStart, zEnd);
      x.pLeft = pExpr;
      x.flags = EP_Skip;
      pCol->pDflt = sqlite3ExprDup(db, &x, EXPRDUP_REDUCE);
      pDfltExpr = sqlite3ExprDup(db, &x, EXPRDUP_REDUCE);
      sqlite3DbFree(db, x.u.zToken);
      sqlite3ColumnSetExpr(pParse, p, pCol, pDfltExpr);
    }
  }
  if( IN_RENAME_OBJECT ){
    sqlite3RenameExprUnmap(pParse, pExpr);
  }
  sqlite3ExprDelete(db, pExpr);
}
1316
1317
1318
1319
1320
1321
1322
1323

1324
1325
1326
1327
1328
1329
1330
1331
1332















1333
1334
1335
1336
1337
1338
1339
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







-
+









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







**     CREATE TABLE xyz(a,b,c,d,e,PRIMARY KEY('a'),UNIQUE('b','c' COLLATE trim)
**     CREATE INDEX abc ON xyz('c','d' DESC,'e' COLLATE nocase DESC);
**
** This is goofy.  But to preserve backwards compatibility we continue to
** accept it.  This routine does the necessary conversion.  It converts
** the expression given in its argument from a TK_STRING into a TK_ID
** if the expression is just a TK_STRING with an optional COLLATE clause.
** If the epxression is anything other than TK_STRING, the expression is
** If the expression is anything other than TK_STRING, the expression is
** unchanged.
*/
static void sqlite3StringToId(Expr *p){
  if( p->op==TK_STRING ){
    p->op = TK_ID;
  }else if( p->op==TK_COLLATE && p->pLeft->op==TK_STRING ){
    p->pLeft->op = TK_ID;
  }
}

/*
** Tag the given column as being part of the PRIMARY KEY
*/
static void makeColumnPartOfPrimaryKey(Parse *pParse, Column *pCol){
  pCol->colFlags |= COLFLAG_PRIMKEY;
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
  if( pCol->colFlags & COLFLAG_GENERATED ){
    testcase( pCol->colFlags & COLFLAG_VIRTUAL );
    testcase( pCol->colFlags & COLFLAG_STORED );
    sqlite3ErrorMsg(pParse,
      "generated columns cannot be part of the PRIMARY KEY");
  }
#endif          
}

/*
** Designate the PRIMARY KEY for the table.  pList is a list of names 
** of columns that form the primary key.  If pList is NULL, then the
** most recently added column of the table is the primary key.
**
** A table can have at most one primary key.  If the table already has
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
1430
1431
1432
1433
1434
1435
1436
1437







1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456

1457
1458
1459
1460
1461
1462
1463
1464
1465

1466
1467
1468
1469
1470
1471
1472
1473
1474

1475
1476
1477
1478
1479
1480
1481





1482
1483
1484
1485

1486
1487
1488
1489
1490
1491

1492
1493
1494
1495
1496












1497
1498

1499
1500
1501





1502
1503
1504


1505
1506
1507
1508
1509
1510











1511






1512
1513
1514
1515

















1516
1517
1518
1519
1520
1521
1522
1846
1847
1848
1849
1850
1851
1852

1853
1854
1855
1856
1857
1858
1859
1860
1861

1862
1863
1864
1865

1866
1867

1868
1869
1870
1871
1872
1873
1874
1875
1876

1877
1878
1879
1880
1881

1882
1883
1884
1885
1886
1887

1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909


1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
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
1984
1985
1986
1987


1988



1989
1990
1991
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
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037







-
+








-
+
+
+

-
+

-
+








-
+



+
-
+





-
+
+




















-
-
+
+
+
+










+
+
+
+
+
+
+


















-
+







-
-
+








-
+


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

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







      "table \"%s\" has more than one primary key", pTab->zName);
    goto primary_key_exit;
  }
  pTab->tabFlags |= TF_HasPrimaryKey;
  if( pList==0 ){
    iCol = pTab->nCol - 1;
    pCol = &pTab->aCol[iCol];
    pCol->colFlags |= COLFLAG_PRIMKEY;
    makeColumnPartOfPrimaryKey(pParse, pCol);
    nTerm = 1;
  }else{
    nTerm = pList->nExpr;
    for(i=0; i<nTerm; i++){
      Expr *pCExpr = sqlite3ExprSkipCollate(pList->a[i].pExpr);
      assert( pCExpr!=0 );
      sqlite3StringToId(pCExpr);
      if( pCExpr->op==TK_ID ){
        const char *zCName = pCExpr->u.zToken;
        const char *zCName;
        assert( !ExprHasProperty(pCExpr, EP_IntValue) );
        zCName = pCExpr->u.zToken;
        for(iCol=0; iCol<pTab->nCol; iCol++){
          if( sqlite3StrICmp(zCName, pTab->aCol[iCol].zName)==0 ){
          if( sqlite3StrICmp(zCName, pTab->aCol[iCol].zCnName)==0 ){
            pCol = &pTab->aCol[iCol];
            pCol->colFlags |= COLFLAG_PRIMKEY;
            makeColumnPartOfPrimaryKey(pParse, pCol);
            break;
          }
        }
      }
    }
  }
  if( nTerm==1
   && pCol
   && sqlite3StrICmp(sqlite3ColumnType(pCol,""), "INTEGER")==0
   && pCol->eCType==COLTYPE_INTEGER
   && sortOrder!=SQLITE_SO_DESC
  ){
    if( IN_RENAME_OBJECT && pList ){
      Expr *pCExpr = sqlite3ExprSkipCollate(pList->a[0].pExpr);
      sqlite3RenameTokenRemap(pParse, &pTab->iPKey, pList->a[0].pExpr);
      sqlite3RenameTokenRemap(pParse, &pTab->iPKey, pCExpr);
    }
    pTab->iPKey = iCol;
    pTab->keyConf = (u8)onError;
    assert( autoInc==0 || autoInc==1 );
    pTab->tabFlags |= autoInc*TF_Autoincrement;
    if( pList ) pParse->iPkSortOrder = pList->a[0].sortOrder;
    if( pList ) pParse->iPkSortOrder = pList->a[0].fg.sortFlags;
    (void)sqlite3HasExplicitNulls(pParse, pList);
  }else if( autoInc ){
#ifndef SQLITE_OMIT_AUTOINCREMENT
    sqlite3ErrorMsg(pParse, "AUTOINCREMENT is only allowed on an "
       "INTEGER PRIMARY KEY");
#endif
  }else{
    sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0,
                           0, sortOrder, 0, SQLITE_IDXTYPE_PRIMARYKEY);
    pList = 0;
  }

primary_key_exit:
  sqlite3ExprListDelete(pParse->db, pList);
  return;
}

/*
** Add a new CHECK constraint to the table currently under construction.
*/
void sqlite3AddCheckConstraint(
  Parse *pParse,    /* Parsing context */
  Expr *pCheckExpr  /* The check expression */
  Parse *pParse,      /* Parsing context */
  Expr *pCheckExpr,   /* The check expression */
  const char *zStart, /* Opening "(" */
  const char *zEnd    /* Closing ")" */
){
#ifndef SQLITE_OMIT_CHECK
  Table *pTab = pParse->pNewTable;
  sqlite3 *db = pParse->db;
  if( pTab && !IN_DECLARE_VTAB
   && !sqlite3BtreeIsReadonly(db->aDb[db->init.iDb].pBt)
  ){
    pTab->pCheck = sqlite3ExprListAppend(pParse, pTab->pCheck, pCheckExpr);
    if( pParse->constraintName.n ){
      sqlite3ExprListSetName(pParse, pTab->pCheck, &pParse->constraintName, 1);
    }else{
      Token t;
      for(zStart++; sqlite3Isspace(zStart[0]); zStart++){}
      while( sqlite3Isspace(zEnd[-1]) ){ zEnd--; }
      t.z = zStart;
      t.n = (int)(zEnd - t.z);
      sqlite3ExprListSetName(pParse, pTab->pCheck, &t, 1);    
    }
  }else
#endif
  {
    sqlite3ExprDelete(pParse->db, pCheckExpr);
  }
}

/*
** Set the collation function of the most recently parsed table column
** to the CollSeq given.
*/
void sqlite3AddCollateType(Parse *pParse, Token *pToken){
  Table *p;
  int i;
  char *zColl;              /* Dequoted name of collation sequence */
  sqlite3 *db;

  if( (p = pParse->pNewTable)==0 ) return;
  if( (p = pParse->pNewTable)==0 || IN_RENAME_OBJECT ) return;
  i = p->nCol-1;
  db = pParse->db;
  zColl = sqlite3NameFromToken(db, pToken);
  if( !zColl ) return;

  if( sqlite3LocateCollSeq(pParse, zColl) ){
    Index *pIdx;
    sqlite3DbFree(db, p->aCol[i].zColl);
    p->aCol[i].zColl = zColl;
    sqlite3ColumnSetColl(db, &p->aCol[i], zColl);
  
    /* If the column is declared as "<name> PRIMARY KEY COLLATE <type>",
    ** then an index may have been created on this column before the
    ** collation type was added. Correct this if it is the case.
    */
    for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){
      assert( pIdx->nKeyCol==1 );
      if( pIdx->aiColumn[0]==i ){
        pIdx->azColl[0] = p->aCol[i].zColl;
        pIdx->azColl[0] = sqlite3ColumnColl(&p->aCol[i]);
      }
    }
  }else{
    sqlite3DbFree(db, zColl);
  }
}

  }
  sqlite3DbFree(db, zColl);
}

/* Change the most recently parsed column to be a GENERATED ALWAYS AS
/*
** This function returns the collation sequence for database native text
** encoding identified by the string zName, length nName.
**
** column.
** If the requested collation sequence is not available, or not available
** in the database native encoding, the collation factory is invoked to
** request it. If the collation factory does not supply such a sequence,
** and the sequence is available in another text encoding, then that is
** returned instead.
**
*/
** If no versions of the requested collations sequence are available, or
** another error occurs, NULL is returned and an error message written into
** pParse.
**
** This routine is a wrapper around sqlite3FindCollSeq().  This routine
void sqlite3AddGenerated(Parse *pParse, Expr *pExpr, Token *pType){
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
  u8 eType = COLFLAG_VIRTUAL;
  Table *pTab = pParse->pNewTable;
  Column *pCol;
  if( pTab==0 ){
    /* generated column in an CREATE TABLE IF NOT EXISTS that already exists */
    goto generated_done;
  }
  pCol = &(pTab->aCol[pTab->nCol-1]);
  if( IN_DECLARE_VTAB ){
    sqlite3ErrorMsg(pParse, "virtual tables cannot use computed columns");
** invokes the collation factory if the named collation cannot be found
** and generates an error message.
    goto generated_done;
**
** See also: sqlite3FindCollSeq(), sqlite3GetCollSeq()
*/
  }
  if( pCol->iDflt>0 ) goto generated_error;
  if( pType ){
    if( pType->n==7 && sqlite3StrNICmp("virtual",pType->z,7)==0 ){
      /* no-op */
CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName){
  sqlite3 *db = pParse->db;
  u8 enc = ENC(db);
    }else if( pType->n==6 && sqlite3StrNICmp("stored",pType->z,6)==0 ){
      eType = COLFLAG_STORED;
  u8 initbusy = db->init.busy;
  CollSeq *pColl;

  pColl = sqlite3FindCollSeq(db, enc, zName, initbusy);
  if( !initbusy && (!pColl || !pColl->xCmp) ){
    pColl = sqlite3GetCollSeq(pParse, enc, pColl, zName);
    }else{
      goto generated_error;
    }
  }
  if( eType==COLFLAG_VIRTUAL ) pTab->nNVCol--;
  pCol->colFlags |= eType;
  assert( TF_HasVirtual==COLFLAG_VIRTUAL );
  assert( TF_HasStored==COLFLAG_STORED );
  pTab->tabFlags |= eType;
  if( pCol->colFlags & COLFLAG_PRIMKEY ){
    makeColumnPartOfPrimaryKey(pParse, pCol); /* For the error message */
  }
  if( ALWAYS(pExpr) && pExpr->op==TK_ID ){
    /* The value of a generated column needs to be a real expression, not
    ** just a reference to another column, in order for covering index
    ** optimizations to work correctly.  So if the value is not an expression,
    ** turn it into one by adding a unary "+" operator. */
    pExpr = sqlite3PExpr(pParse, TK_UPLUS, pExpr, 0);

  return pColl;
}

  }
  sqlite3ColumnSetExpr(pParse, pTab, pCol, pExpr);
  pExpr = 0;
  goto generated_done;

generated_error:
  sqlite3ErrorMsg(pParse, "error in generated column \"%s\"",
                  pCol->zCnName);
generated_done:
  sqlite3ExprDelete(pParse->db, pExpr);
#else
  /* Throw and error for the GENERATED ALWAYS AS clause if the
  ** SQLITE_OMIT_GENERATED_COLUMNS compile-time option is used. */
  sqlite3ErrorMsg(pParse, "generated columns not supported");
  sqlite3ExprDelete(pParse->db, pExpr);
#endif
}

/*
** Generate code that will increment the schema cookie.
**
** The schema cookie is used to determine when the schema for the
** database changes.  After each schema change, the cookie value
** changes.  When a process first reads the schema it records the
1601
1602
1603
1604
1605
1606
1607
1608

1609
1610
1611
1612
1613
1614
1615
2116
2117
2118
2119
2120
2121
2122

2123
2124
2125
2126
2127
2128
2129
2130







-
+







static char *createTableStmt(sqlite3 *db, Table *p){
  int i, k, n;
  char *zStmt;
  char *zSep, *zSep2, *zEnd;
  Column *pCol;
  n = 0;
  for(pCol = p->aCol, i=0; i<p->nCol; i++, pCol++){
    n += identLength(pCol->zName) + 5;
    n += identLength(pCol->zCnName) + 5;
  }
  n += identLength(p->zName);
  if( n<50 ){ 
    zSep = "";
    zSep2 = ",";
    zEnd = ")";
  }else{
1629
1630
1631
1632
1633
1634
1635
1636


1637
1638
1639
1640
1641
1642
1643
1644

1645
1646
1647
1648
1649
1650
1651

1652
1653
1654
1655


1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674

1675
1676
1677
1678
1679



1680
1681
1682
1683
1684
1685
1686
2144
2145
2146
2147
2148
2149
2150

2151
2152
2153
2154
2155
2156
2157
2158
2159

2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171

2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191

2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207







-
+
+







-
+







+



-
+
+


















-
+





+
+
+







  zStmt[k++] = '(';
  for(pCol=p->aCol, i=0; i<p->nCol; i++, pCol++){
    static const char * const azType[] = {
        /* SQLITE_AFF_BLOB    */ "",
        /* SQLITE_AFF_TEXT    */ " TEXT",
        /* SQLITE_AFF_NUMERIC */ " NUM",
        /* SQLITE_AFF_INTEGER */ " INT",
        /* SQLITE_AFF_REAL    */ " REAL"
        /* SQLITE_AFF_REAL    */ " REAL",
        /* SQLITE_AFF_FLEXNUM */ " NUM",
    };
    int len;
    const char *zType;

    sqlite3_snprintf(n-k, &zStmt[k], zSep);
    k += sqlite3Strlen30(&zStmt[k]);
    zSep = zSep2;
    identPut(zStmt, &k, pCol->zName);
    identPut(zStmt, &k, pCol->zCnName);
    assert( pCol->affinity-SQLITE_AFF_BLOB >= 0 );
    assert( pCol->affinity-SQLITE_AFF_BLOB < ArraySize(azType) );
    testcase( pCol->affinity==SQLITE_AFF_BLOB );
    testcase( pCol->affinity==SQLITE_AFF_TEXT );
    testcase( pCol->affinity==SQLITE_AFF_NUMERIC );
    testcase( pCol->affinity==SQLITE_AFF_INTEGER );
    testcase( pCol->affinity==SQLITE_AFF_REAL );
    testcase( pCol->affinity==SQLITE_AFF_FLEXNUM );
    
    zType = azType[pCol->affinity - SQLITE_AFF_BLOB];
    len = sqlite3Strlen30(zType);
    assert( pCol->affinity==SQLITE_AFF_BLOB 
    assert( pCol->affinity==SQLITE_AFF_BLOB
            || pCol->affinity==SQLITE_AFF_FLEXNUM
            || pCol->affinity==sqlite3AffinityType(zType, 0) );
    memcpy(&zStmt[k], zType, len);
    k += len;
    assert( k<=n );
  }
  sqlite3_snprintf(n-k, &zStmt[k], "%s", zEnd);
  return zStmt;
}

/*
** Resize an Index object to hold N columns total.  Return SQLITE_OK
** on success and SQLITE_NOMEM on an OOM error.
*/
static int resizeIndexObject(sqlite3 *db, Index *pIdx, int N){
  char *zExtra;
  int nByte;
  if( pIdx->nColumn>=N ) return SQLITE_OK;
  assert( pIdx->isResized==0 );
  nByte = (sizeof(char*) + sizeof(i16) + 1)*N;
  nByte = (sizeof(char*) + sizeof(LogEst) + sizeof(i16) + 1)*N;
  zExtra = sqlite3DbMallocZero(db, nByte);
  if( zExtra==0 ) return SQLITE_NOMEM_BKPT;
  memcpy(zExtra, pIdx->azColl, sizeof(char*)*pIdx->nColumn);
  pIdx->azColl = (const char**)zExtra;
  zExtra += sizeof(char*)*N;
  memcpy(zExtra, pIdx->aiRowLogEst, sizeof(LogEst)*(pIdx->nKeyCol+1));
  pIdx->aiRowLogEst = (LogEst*)zExtra;
  zExtra += sizeof(LogEst)*N;
  memcpy(zExtra, pIdx->aiColumn, sizeof(i16)*pIdx->nColumn);
  pIdx->aiColumn = (i16*)zExtra;
  zExtra += sizeof(i16)*N;
  memcpy(zExtra, pIdx->aSortOrder, pIdx->nColumn);
  pIdx->aSortOrder = (u8*)zExtra;
  pIdx->nColumn = N;
  pIdx->isResized = 1;
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
1755
1756
1757
1758
1759
1760
1761

1762
1763

1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778

1779
1780
1781
1782
1783
1784
1785
1786
1787



1788
1789
1790

1791
1792
1793
1794
1795

1796

1797
1798

1799
1800
1801
1802
1803
1804
1805
1806
1807

1808
1809
1810
1811








1812

1813
1814
1815





1816
1817

1818
1819

1820
1821
1822
1823
1824
1825
1826
1827

1828
1829



1830
1831
1832
1833
1834
1835
1836
1837
1838

1839
1840

1841
1842
1843
1844
1845
1846

1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858

1859



1860
1861
1862
1863
1864
1865
1866
1867

1868

1869
1870




1871
1872
1873
1874
1875
1876
1877
1878
1879

1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891

















1892
1893
1894
1895
1896
1897

























































1898
1899
1900
1901
1902
1903
1904
1905
1906

1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
















1923










1924
1925
1926



1927
1928
1929
1930
1931
1932
1933
1934
1935
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
1984
1985
1986
1987











































1988
1989
1990
1991
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
2017
2018
2019
2020
2021

2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041

2042
2043
2044
2045
2046
2047
2048
2233
2234
2235
2236
2237
2238
2239

2240
2241
2242
2243
2244

2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289

2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311

2312
2313
2314
2315
2316
2317
2318

2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331

2332
2333

2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358

2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371

2372
2373

2374
2375
2376
2377
2378
2379
2380
2381
2382

2383
2384
2385


2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397

2398
2399
2400
2401
2402
2403

2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414

2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428

2429
2430

2431
2432
2433
2434
2435
2436

2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450

2451
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
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496



2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564

2565
2566
2567


2568
2569
2570
2571
2572
2573
2574





2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602


2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614

2615
2616


2617
2618
2619

2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630

2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641

2642
2643
2644

2645
2646
2647
2648
2649

2650
2651
2652
2653
2654

2655
2656
2657
2658

2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
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
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718




2719
2720
2721
2722
2723


2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737

2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
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







-
+
+
+


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






-
+
+


+
+
+
+
+
+
+
+







+


-
+






-
+












-
+

-
+















+








-
+
+
+



+





+
-
+

-
+








-
+


-
-
+
+
+
+
+
+
+
+

+


-
+
+
+
+
+

-
+


+







-
+


+
+
+








-
+

-
+





-
+












+
-
+
+
+








+
-
+


+
+
+
+









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



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








-
+


-
-







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

+
+
+
+
+
+
+
+
+
+

-
-
+
+
+









-
+

-
-
+
+

-
+










-
+










-



-
+




-
+




-
+



-
+






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










-
-
-
-
+
+
+
+
+
-
-







+
+
+
+
+
+
+
-
+
+

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








-
+



















-
+







    i16 x = pIdx->aiColumn[i];
    assert( x<pIdx->pTable->nCol );
    wIndex += x<0 ? 1 : aCol[pIdx->aiColumn[i]].szEst;
  }
  pIdx->szIdxRow = sqlite3LogEst(wIndex*4);
}

/* Return true if value x is found any of the first nCol entries of aiCol[]
/* Return true if column number x is any of the first nCol entries of aiCol[].
** This is used to determine if the column number x appears in any of the
** first nCol entries of an index.
*/
static int hasColumn(const i16 *aiCol, int nCol, int x){
  while( nCol-- > 0 ) if( x==*(aiCol++) ) return 1;
  while( nCol-- > 0 ){
    if( x==*(aiCol++) ){
      return 1;
    }
  }
  return 0;
}

/*
** Return true if any of the first nKey entries of index pIdx exactly
** match the iCol-th entry of pPk.  pPk is always a WITHOUT ROWID
** PRIMARY KEY index.  pIdx is an index on the same table.  pIdx may
** or may not be the same index as pPk.
**
** The first nKey entries of pIdx are guaranteed to be ordinary columns,
** not a rowid or expression.
**
** This routine differs from hasColumn() in that both the column and the
** collating sequence must match for this routine, but for hasColumn() only
** the column name must match.
*/
static int isDupColumn(Index *pIdx, int nKey, Index *pPk, int iCol){
  int i, j;
  assert( nKey<=pIdx->nColumn );
  assert( iCol<MAX(pPk->nColumn,pPk->nKeyCol) );
  assert( pPk->idxType==SQLITE_IDXTYPE_PRIMARYKEY );
  assert( pPk->pTable->tabFlags & TF_WithoutRowid );
  assert( pPk->pTable==pIdx->pTable );
  testcase( pPk==pIdx );
  j = pPk->aiColumn[iCol];
  assert( j!=XN_ROWID && j!=XN_EXPR );
  for(i=0; i<nKey; i++){
    assert( pIdx->aiColumn[i]>=0 || j>=0 );
    if( pIdx->aiColumn[i]==j 
     && sqlite3StrICmp(pIdx->azColl[i], pPk->azColl[iCol])==0
    ){
      return 1;
    }
  }
  return 0;
}

/* Recompute the colNotIdxed field of the Index.
**
** colNotIdxed is a bitmask that has a 0 bit representing each indexed
** columns that are within the first 63 columns of the table.  The
** columns that are within the first 63 columns of the table and a 1 for
** all other bits (all columns that are not in the index).  The
** high-order bit of colNotIdxed is always 1.  All unindexed columns
** of the table have a 1.
**
** 2019-10-24:  For the purpose of this computation, virtual columns are
** not considered to be covered by the index, even if they are in the
** index, because we do not trust the logic in whereIndexExprTrans() to be
** able to find all instances of a reference to the indexed table column
** and convert them into references to the index.  Hence we always want
** the actual table at hand in order to recompute the virtual column, if
** necessary.
**
** The colNotIdxed mask is AND-ed with the SrcList.a[].colUsed mask
** to determine if the index is covering index.
*/
static void recomputeColumnsNotIndexed(Index *pIdx){
  Bitmask m = 0;
  int j;
  Table *pTab = pIdx->pTable;
  for(j=pIdx->nColumn-1; j>=0; j--){
    int x = pIdx->aiColumn[j];
    if( x>=0 ){
    if( x>=0 && (pTab->aCol[x].colFlags & COLFLAG_VIRTUAL)==0 ){
      testcase( x==BMS-1 );
      testcase( x==BMS-2 );
      if( x<BMS-1 ) m |= MASKBIT(x);
    }
  }
  pIdx->colNotIdxed = ~m;
  assert( (pIdx->colNotIdxed>>63)==1 );
  assert( (pIdx->colNotIdxed>>63)==1 );  /* See note-20221022-a */
}

/*
** This routine runs at the end of parsing a CREATE TABLE statement that
** has a WITHOUT ROWID clause.  The job of this routine is to convert both
** internal schema data structures and the generated VDBE code so that they
** are appropriate for a WITHOUT ROWID table instead of a rowid table.
** Changes include:
**
**     (1)  Set all columns of the PRIMARY KEY schema object to be NOT NULL.
**     (2)  Convert P3 parameter of the OP_CreateBtree from BTREE_INTKEY 
**          into BTREE_BLOBKEY.
**     (3)  Bypass the creation of the sqlite_master table entry
**     (3)  Bypass the creation of the sqlite_schema table entry
**          for the PRIMARY KEY as the primary key index is now
**          identified by the sqlite_master table entry of the table itself.
**          identified by the sqlite_schema table entry of the table itself.
**     (4)  Set the Index.tnum of the PRIMARY KEY Index object in the
**          schema to the rootpage from the main table.
**     (5)  Add all table columns to the PRIMARY KEY Index object
**          so that the PRIMARY KEY is a covering index.  The surplus
**          columns are part of KeyInfo.nAllField and are not used for
**          sorting or lookup or uniqueness checks.
**     (6)  Replace the rowid tail on all automatically generated UNIQUE
**          indices with the PRIMARY KEY columns.
**
** For virtual tables, only (1) is performed.
*/
static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
  Index *pIdx;
  Index *pPk;
  int nPk;
  int nExtra;
  int i, j;
  sqlite3 *db = pParse->db;
  Vdbe *v = pParse->pVdbe;

  /* Mark every PRIMARY KEY column as NOT NULL (except for imposter tables)
  */
  if( !db->init.imposterTable ){
    for(i=0; i<pTab->nCol; i++){
      if( (pTab->aCol[i].colFlags & COLFLAG_PRIMKEY)!=0 ){
      if( (pTab->aCol[i].colFlags & COLFLAG_PRIMKEY)!=0
       && (pTab->aCol[i].notNull==OE_None)
      ){
        pTab->aCol[i].notNull = OE_Abort;
      }
    }
    pTab->tabFlags |= TF_HasNotNull;
  }

  /* Convert the P3 operand of the OP_CreateBtree opcode from BTREE_INTKEY
  ** into BTREE_BLOBKEY.
  */
  assert( !pParse->bReturning );
  if( pParse->addrCrTab ){
  if( pParse->u1.addrCrTab ){
    assert( v );
    sqlite3VdbeChangeP3(v, pParse->addrCrTab, BTREE_BLOBKEY);
    sqlite3VdbeChangeP3(v, pParse->u1.addrCrTab, BTREE_BLOBKEY);
  }

  /* Locate the PRIMARY KEY index.  Or, if this table was originally
  ** an INTEGER PRIMARY KEY table, create a new PRIMARY KEY index. 
  */
  if( pTab->iPKey>=0 ){
    ExprList *pList;
    Token ipkToken;
    sqlite3TokenInit(&ipkToken, pTab->aCol[pTab->iPKey].zName);
    sqlite3TokenInit(&ipkToken, pTab->aCol[pTab->iPKey].zCnName);
    pList = sqlite3ExprListAppend(pParse, 0, 
                  sqlite3ExprAlloc(db, TK_ID, &ipkToken, 0));
    if( pList==0 ) return;
    pList->a[0].sortOrder = pParse->iPkSortOrder;
    if( pList==0 ){
      pTab->tabFlags &= ~TF_WithoutRowid;
      return;
    }
    if( IN_RENAME_OBJECT ){
      sqlite3RenameTokenRemap(pParse, pList->a[0].pExpr, &pTab->iPKey);
    }
    pList->a[0].fg.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( pParse->nErr ){
      pTab->tabFlags &= ~TF_WithoutRowid;
      return;
    }
    assert( db->mallocFailed==0 );
    pPk = sqlite3PrimaryKeyIndex(pTab);
    pTab->iPKey = -1;
    assert( pPk->nKeyCol==1 );
  }else{
    pPk = sqlite3PrimaryKeyIndex(pTab);
    assert( pPk!=0 );

    /*
    ** Remove all redundant columns from the PRIMARY KEY.  For example, change
    ** "PRIMARY KEY(a,b,a,b,c,b,c,d)" into just "PRIMARY KEY(a,b,c,d)".  Later
    ** code assumes the PRIMARY KEY contains no repeated columns.
    */
    for(i=j=1; i<pPk->nKeyCol; i++){
      if( hasColumn(pPk->aiColumn, j, pPk->aiColumn[i]) ){
      if( isDupColumn(pPk, j, pPk, i) ){
        pPk->nColumn--;
      }else{
        testcase( hasColumn(pPk->aiColumn, j, pPk->aiColumn[i]) );
        pPk->azColl[j] = pPk->azColl[i];
        pPk->aSortOrder[j] = pPk->aSortOrder[i];
        pPk->aiColumn[j++] = pPk->aiColumn[i];
      }
    }
    pPk->nKeyCol = j;
  }
  assert( pPk!=0 );
  pPk->isCovering = 1;
  if( !db->init.imposterTable ) pPk->uniqNotNull = 1;
  nPk = pPk->nKeyCol;
  nPk = pPk->nColumn = pPk->nKeyCol;

  /* Bypass the creation of the PRIMARY KEY btree and the sqlite_master
  /* Bypass the creation of the PRIMARY KEY btree and the sqlite_schema
  ** table entry. This is only required if currently generating VDBE
  ** code for a CREATE TABLE (not when parsing one as part of reading
  ** a database schema).  */
  if( v && pPk->tnum>0 ){
    assert( db->init.busy==0 );
    sqlite3VdbeChangeOpcode(v, pPk->tnum, OP_Goto);
    sqlite3VdbeChangeOpcode(v, (int)pPk->tnum, OP_Goto);
  }

  /* The root page of the PRIMARY KEY is the table root page */
  pPk->tnum = pTab->tnum;

  /* Update the in-memory representation of all UNIQUE indices by converting
  ** the final rowid column into one or more columns of the PRIMARY KEY.
  */
  for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
    int n;
    if( IsPrimaryKeyIndex(pIdx) ) continue;
    for(i=n=0; i<nPk; i++){
      if( !isDupColumn(pIdx, pIdx->nKeyCol, pPk, i) ){
      if( !hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) ) n++;
        testcase( hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) );
        n++;
      }
    }
    if( n==0 ){
      /* This index is a superset of the primary key */
      pIdx->nColumn = pIdx->nKeyCol;
      continue;
    }
    if( resizeIndexObject(db, pIdx, pIdx->nKeyCol+n) ) return;
    for(i=0, j=pIdx->nKeyCol; i<nPk; i++){
      if( !isDupColumn(pIdx, pIdx->nKeyCol, pPk, i) ){
      if( !hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) ){
        testcase( hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) );
        pIdx->aiColumn[j] = pPk->aiColumn[i];
        pIdx->azColl[j] = pPk->azColl[i];
        if( pPk->aSortOrder[i] ){
          /* See ticket https://www.sqlite.org/src/info/bba7b69f9849b5bf */
          pIdx->bAscKeyBug = 1;
        }
        j++;
      }
    }
    assert( pIdx->nColumn>=pIdx->nKeyCol+n );
    assert( pIdx->nColumn>=j );
  }

  /* Add all table columns to the PRIMARY KEY index
  */
  nExtra = 0;
  if( nPk<pTab->nCol ){
    if( resizeIndexObject(db, pPk, pTab->nCol) ) return;
    for(i=0, j=nPk; i<pTab->nCol; i++){
      if( !hasColumn(pPk->aiColumn, j, i) ){
        assert( j<pPk->nColumn );
        pPk->aiColumn[j] = i;
        pPk->azColl[j] = sqlite3StrBINARY;
        j++;
      }
    }
    assert( pPk->nColumn==j );
    assert( pTab->nCol==j );
  for(i=0; i<pTab->nCol; i++){
    if( !hasColumn(pPk->aiColumn, nPk, i)
     && (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ) nExtra++;
  }
  if( resizeIndexObject(db, pPk, nPk+nExtra) ) return;
  for(i=0, j=nPk; i<pTab->nCol; i++){
    if( !hasColumn(pPk->aiColumn, j, i)
     && (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0
    ){
      assert( j<pPk->nColumn );
      pPk->aiColumn[j] = i;
      pPk->azColl[j] = sqlite3StrBINARY;
      j++;
    }
  }
  assert( pPk->nColumn==j );
  assert( pTab->nNVCol<=j );
  }else{
    pPk->nColumn = pTab->nCol;
  }
  recomputeColumnsNotIndexed(pPk);
}


#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Return true if pTab is a virtual table and zName is a shadow table name
** for that virtual table.
*/
int sqlite3IsShadowTableOf(sqlite3 *db, Table *pTab, const char *zName){
  int nName;                    /* Length of zName */
  Module *pMod;                 /* Module for the virtual table */

  if( !IsVirtual(pTab) ) return 0;
  nName = sqlite3Strlen30(pTab->zName);
  if( sqlite3_strnicmp(zName, pTab->zName, nName)!=0 ) return 0;
  if( zName[nName]!='_' ) return 0;
  pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->u.vtab.azArg[0]);
  if( pMod==0 ) return 0;
  if( pMod->pModule->iVersion<3 ) return 0;
  if( pMod->pModule->xShadowName==0 ) return 0;
  return pMod->pModule->xShadowName(zName+nName+1);
}
#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */

#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Table pTab is a virtual table.  If it the virtual table implementation
** exists and has an xShadowName method, then loop over all other ordinary
** tables within the same schema looking for shadow tables of pTab, and mark
** any shadow tables seen using the TF_Shadow flag.
*/
void sqlite3MarkAllShadowTablesOf(sqlite3 *db, Table *pTab){
  int nName;                    /* Length of pTab->zName */
  Module *pMod;                 /* Module for the virtual table */
  HashElem *k;                  /* For looping through the symbol table */

  assert( IsVirtual(pTab) );
  pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->u.vtab.azArg[0]);
  if( pMod==0 ) return;
  if( NEVER(pMod->pModule==0) ) return;
  if( pMod->pModule->iVersion<3 ) return;
  if( pMod->pModule->xShadowName==0 ) return;
  assert( pTab->zName!=0 );
  nName = sqlite3Strlen30(pTab->zName);
  for(k=sqliteHashFirst(&pTab->pSchema->tblHash); k; k=sqliteHashNext(k)){
    Table *pOther = sqliteHashData(k);
    assert( pOther->zName!=0 );
    if( !IsOrdinaryTable(pOther) ) continue;
    if( pOther->tabFlags & TF_Shadow ) continue;
    if( sqlite3StrNICmp(pOther->zName, pTab->zName, nName)==0
     && pOther->zName[nName]=='_'
     && pMod->pModule->xShadowName(pOther->zName+nName+1)
    ){
      pOther->tabFlags |= TF_Shadow;
    }
  }
}
#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */

#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Return true if zName is a shadow table name in the current database
** connection.
**
** zName is temporarily modified while this routine is running, but is
** restored to its original value prior to this routine returning.
*/
static int isShadowTableName(sqlite3 *db, char *zName){
int sqlite3ShadowTableName(sqlite3 *db, const char *zName){
  char *zTail;                  /* Pointer to the last "_" in zName */
  Table *pTab;                  /* Table that zName is a shadow of */
  Module *pMod;                 /* Module for the virtual table */

  zTail = strrchr(zName, '_');
  if( zTail==0 ) return 0;
  *zTail = 0;
  pTab = sqlite3FindTable(db, zName, 0);
  *zTail = '_';
  if( pTab==0 ) return 0;
  if( !IsVirtual(pTab) ) return 0;
  pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->azModuleArg[0]);
  if( pMod==0 ) return 0;
  if( pMod->pModule->iVersion<3 ) return 0;
  if( pMod->pModule->xShadowName==0 ) return 0;
  return pMod->pModule->xShadowName(zTail+1);
  return sqlite3IsShadowTableOf(db, pTab, zName);
}
#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */


#ifdef SQLITE_DEBUG
/*
** Mark all nodes of an expression as EP_Immutable, indicating that
** they should not be changed.  Expressions attached to a table or
** index definition are tagged this way to help ensure that we do
** not pass them into code generator routines by mistake.
*/
static int markImmutableExprStep(Walker *pWalker, Expr *pExpr){
  (void)pWalker;
  ExprSetVVAProperty(pExpr, EP_Immutable);
  return WRC_Continue;
}
static void markExprListImmutable(ExprList *pList){
  if( pList ){
    Walker w;
    memset(&w, 0, sizeof(w));
    w.xExprCallback = markImmutableExprStep;
    w.xSelectCallback = sqlite3SelectWalkNoop;
    w.xSelectCallback2 = 0;
    sqlite3WalkExprList(&w, pList);
  }
}
#else
# define isShadowTableName(x,y) 0
#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
#define markExprListImmutable(X)  /* no-op */
#endif /* SQLITE_DEBUG */


/*
** This routine is called to report the final ")" that terminates
** a CREATE TABLE statement.
**
** The table structure that other action routines have been building
** is added to the internal hash tables, assuming no errors have
** occurred.
**
** An entry for the table is made in the master table on disk, unless
** An entry for the table is made in the schema table on disk, unless
** this is a temporary table or db->init.busy==1.  When db->init.busy==1
** it means we are reading the sqlite_master table because we just
** connected to the database or because the sqlite_master table has
** it means we are reading the sqlite_schema table because we just
** connected to the database or because the sqlite_schema table has
** recently changed, so the entry for this table already exists in
** the sqlite_master table.  We do not want to create it again.
** the sqlite_schema table.  We do not want to create it again.
**
** If the pSelect argument is not NULL, it means that this routine
** was called to create a table generated from a 
** "CREATE TABLE ... AS SELECT ..." statement.  The column names of
** the new table will match the result set of the SELECT.
*/
void sqlite3EndTable(
  Parse *pParse,          /* Parse context */
  Token *pCons,           /* The ',' token after the last column defn. */
  Token *pEnd,            /* The ')' before options in the CREATE TABLE */
  u8 tabOpts,             /* Extra table options. Usually 0. */
  u32 tabOpts,            /* Extra table options. Usually 0. */
  Select *pSelect         /* Select from a "CREATE ... AS SELECT" */
){
  Table *p;                 /* The new table */
  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 && isShadowTableName(db, p->zName) ){
  if( pSelect==0 && sqlite3ShadowTableName(db, p->zName) ){
    p->tabFlags |= TF_Shadow;
  }

  /* If the db->init.busy is 1 it means we are reading the SQL off the
  ** "sqlite_master" or "sqlite_temp_master" table on the disk.
  ** "sqlite_schema" or "sqlite_temp_schema" table on the disk.
  ** So do not write to the disk again.  Extract the root page number
  ** for the table from the db->init.newTnum field.  (The page number
  ** should have been put there by the sqliteOpenCb routine.)
  **
  ** If the root page number is 1, that means this is the sqlite_master
  ** If the root page number is 1, that means this is the sqlite_schema
  ** table itself.  So mark it read-only.
  */
  if( db->init.busy ){
    if( pSelect ){
    if( pSelect || (!IsOrdinaryTable(p) && db->init.newTnum) ){
      sqlite3ErrorMsg(pParse, "");
      return;
    }
    p->tnum = db->init.newTnum;
    if( p->tnum==1 ) p->tabFlags |= TF_Readonly;
  }

  /* Special processing for tables that include the STRICT keyword:
  **
  **   *  Do not allow custom column datatypes.  Every column must have
  **      a datatype that is one of INT, INTEGER, REAL, TEXT, or BLOB.
  **
  **   *  If a PRIMARY KEY is defined, other than the INTEGER PRIMARY KEY,
  **      then all columns of the PRIMARY KEY must have a NOT NULL
  **      constraint.
  */
  if( tabOpts & TF_Strict ){
    int ii;
    p->tabFlags |= TF_Strict;
    for(ii=0; ii<p->nCol; ii++){
      Column *pCol = &p->aCol[ii];
      if( pCol->eCType==COLTYPE_CUSTOM ){
        if( pCol->colFlags & COLFLAG_HASTYPE ){
          sqlite3ErrorMsg(pParse,
            "unknown datatype for %s.%s: \"%s\"",
            p->zName, pCol->zCnName, sqlite3ColumnType(pCol, "")
          );
        }else{
          sqlite3ErrorMsg(pParse, "missing datatype for %s.%s",
                          p->zName, pCol->zCnName);
        }
        return;
      }else if( pCol->eCType==COLTYPE_ANY ){
        pCol->affinity = SQLITE_AFF_BLOB;
      }
      if( (pCol->colFlags & COLFLAG_PRIMKEY)!=0
       && p->iPKey!=ii
       && pCol->notNull == OE_None
      ){
        pCol->notNull = OE_Abort;
        p->tabFlags |= TF_HasNotNull;
      }
    }    
  }

  assert( (p->tabFlags & TF_HasPrimaryKey)==0
       || p->iPKey>=0 || sqlite3PrimaryKeyIndex(p)!=0 );
  assert( (p->tabFlags & TF_HasPrimaryKey)!=0
       || (p->iPKey<0 && sqlite3PrimaryKeyIndex(p)==0) );

  /* Special processing for WITHOUT ROWID Tables */
  if( tabOpts & TF_WithoutRowid ){
    if( (p->tabFlags & TF_Autoincrement) ){
      sqlite3ErrorMsg(pParse,
          "AUTOINCREMENT not allowed on WITHOUT ROWID tables");
      return;
    }
    if( (p->tabFlags & TF_HasPrimaryKey)==0 ){
      sqlite3ErrorMsg(pParse, "PRIMARY KEY missing on table %s", p->zName);
    }else{
      p->tabFlags |= TF_WithoutRowid | TF_NoVisibleRowid;
      convertToWithoutRowidTable(pParse, p);
    }
      return;
    }
    p->tabFlags |= TF_WithoutRowid | TF_NoVisibleRowid;
    convertToWithoutRowidTable(pParse, p);
  }
  }

  iDb = sqlite3SchemaToIndex(db, p->pSchema);

#ifndef SQLITE_OMIT_CHECK
  /* Resolve names in all CHECK constraint expressions.
  */
  if( p->pCheck ){
    sqlite3ResolveSelfReference(pParse, p, NC_IsCheck, 0, p->pCheck);
    if( pParse->nErr ){
      /* If errors are seen, delete the CHECK constraints now, else they might
      ** actually be used if PRAGMA writable_schema=ON is set. */
      sqlite3ExprListDelete(db, p->pCheck);
      p->pCheck = 0;
    }else{
      markExprListImmutable(p->pCheck);
  }
    }
  }
#endif /* !defined(SQLITE_OMIT_CHECK) */
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
  if( p->tabFlags & TF_HasGenerated ){
    int ii, nNG = 0;
    testcase( p->tabFlags & TF_HasVirtual );
    testcase( p->tabFlags & TF_HasStored );
    for(ii=0; ii<p->nCol; ii++){
      u32 colFlags = p->aCol[ii].colFlags;
      if( (colFlags & COLFLAG_GENERATED)!=0 ){
        Expr *pX = sqlite3ColumnExpr(p, &p->aCol[ii]);
        testcase( colFlags & COLFLAG_VIRTUAL );
        testcase( colFlags & COLFLAG_STORED );
        if( sqlite3ResolveSelfReference(pParse, p, NC_GenCol, pX, 0) ){
          /* If there are errors in resolving the expression, change the
          ** expression to a NULL.  This prevents code generators that operate
          ** on the expression from inserting extra parts into the expression
          ** tree that have been allocated from lookaside memory, which is
          ** illegal in a schema and will lead to errors or heap corruption
          ** when the database connection closes. */
          sqlite3ColumnSetExpr(pParse, p, &p->aCol[ii], 
               sqlite3ExprAlloc(db, TK_NULL, 0, 0));
        }
      }else{
        nNG++;
      }
    }
    if( nNG==0 ){
      sqlite3ErrorMsg(pParse, "must have at least one non-generated column");
      return;
    }
  }
#endif

  /* Estimate the average row size for the table and for all implied indices */
  estimateTableWidth(p);
  for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){
    estimateIndexWidth(pIdx);
  }

  /* If not initializing, then create a record for the new table
  ** in the SQLITE_MASTER table of the database.
  ** in the schema table of the database.
  **
  ** If this is a TEMPORARY table, write the entry into the auxiliary
  ** file instead of into the main database file.
  */
  if( !db->init.busy ){
    int n;
    Vdbe *v;
    char *zType;    /* "view" or "table" */
    char *zType2;   /* "VIEW" or "TABLE" */
    char *zStmt;    /* Text of the CREATE TABLE or CREATE VIEW statement */

    v = sqlite3GetVdbe(pParse);
    if( NEVER(v==0) ) return;

    sqlite3VdbeAddOp1(v, OP_Close, 0);

    /* 
    ** Initialize zType for the new view or table.
    */
    if( p->pSelect==0 ){
    if( IsOrdinaryTable(p) ){
      /* A regular table */
      zType = "table";
      zType2 = "TABLE";
#ifndef SQLITE_OMIT_VIEW
    }else{
      /* A view */
      zType = "view";
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
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849

2850
2851
2852

2853
2854
2855
2856
2857
2858
2859
2860







+
+
+
+
+











-
+


-
+







      int regYield;       /* Register holding co-routine entry-point */
      int addrTop;        /* Top of the co-routine */
      int regRec;         /* A record to be insert into the new table */
      int regRowid;       /* Rowid of the next row to insert */
      int addrInsLoop;    /* Top of the loop for inserting rows */
      Table *pSelTab;     /* A table that describes the SELECT results */

      if( IN_SPECIAL_PARSE ){
        pParse->rc = SQLITE_ERROR;
        pParse->nErr++;
        return;
      }
      regYield = ++pParse->nMem;
      regRec = ++pParse->nMem;
      regRowid = ++pParse->nMem;
      assert(pParse->nTab==1);
      sqlite3MayAbort(pParse);
      sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, pParse->regRoot, iDb);
      sqlite3VdbeChangeP5(v, OPFLAG_P2ISREG);
      pParse->nTab = 2;
      addrTop = sqlite3VdbeCurrentAddr(v) + 1;
      sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop);
      if( pParse->nErr ) return;
      pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect);
      pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect, SQLITE_AFF_BLOB);
      if( pSelTab==0 ) return;
      assert( p->aCol==0 );
      p->nCol = pSelTab->nCol;
      p->nCol = p->nNVCol = pSelTab->nCol;
      p->aCol = pSelTab->aCol;
      pSelTab->nCol = 0;
      pSelTab->aCol = 0;
      sqlite3DeleteTable(db, pSelTab);
      sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield);
      sqlite3Select(pParse, pSelect, &dest);
      if( pParse->nErr ) return;
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
2880
2881
2882
2883
2884
2885
2886

2887
2888
2889
2890




2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908

2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922

2923
2924

2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945



2946
2947
2948
2949
2950
2951
2952
2953





2954
2955
2956
2957
2958
2959



2960
2961
2962

2963
2964
2965
2966
2967
2968
2969







-
+



-
-
-
-
+
+
+
+














-
+













-
+

-







+









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

-







      if( pEnd2->z[0]!=';' ) n += pEnd2->n;
      zStmt = sqlite3MPrintf(db, 
          "CREATE %s %.*s", zType2, n, pParse->sNameToken.z
      );
    }

    /* A slot for the record has already been allocated in the 
    ** SQLITE_MASTER table.  We just need to update that slot with all
    ** schema table.  We just need to update that slot with all
    ** the information we've collected.
    */
    sqlite3NestedParse(pParse,
      "UPDATE %Q.%s "
         "SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q "
       "WHERE rowid=#%d",
      db->aDb[iDb].zDbSName, MASTER_NAME,
      "UPDATE %Q." LEGACY_SCHEMA_TABLE
      " SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q"
      " WHERE rowid=#%d",
      db->aDb[iDb].zDbSName,
      zType,
      p->zName,
      p->zName,
      pParse->regRoot,
      zStmt,
      pParse->regRowid
    );
    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
        );
      }
    }
#endif

    /* Reparse everything to update our internal data structures */
    sqlite3VdbeAddParseSchemaOp(v, iDb,
           sqlite3MPrintf(db, "tbl_name='%q' AND type!='trigger'", p->zName));
           sqlite3MPrintf(db, "tbl_name='%q' AND type!='trigger'", p->zName),0);
  }


  /* 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_ALTERTABLE
    if( !p->pSelect ){
      const char *zName = (const char *)pParse->sNameToken.z;
#ifndef SQLITE_OMIT_AUTOINCREMENT
    if( strcmp(p->zName, "sqlite_sequence")==0 ){
      assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
      p->pSchema->pSeqTab = p;
    }
#endif
  }

      int nName;
      assert( !pSelect && pCons && pEnd );
      if( pCons->z==0 ){
        pCons = pEnd;
      }
#ifndef SQLITE_OMIT_ALTERTABLE
  if( !pSelect && IsOrdinaryTable(p) ){
    assert( pCons && pEnd );
    if( pCons->z==0 ){
      pCons = pEnd;
    }
      nName = (int)((const char *)pCons->z - zName);
      p->addColOffset = 13 + sqlite3Utf8CharLen(zName, nName);
    }
    p->u.tab.addColOffset = 13 + (int)(pCons->z - pParse->sNameToken.z);
  }
#endif
  }
}

#ifndef SQLITE_OMIT_VIEW
/*
** The parser calls this routine in order to create a new VIEW
*/
void sqlite3CreateView(
2216
2217
2218
2219
2220
2221
2222










2223
2224
2225
2226
2227
2228
2229
2230
2231
2232

2233
2234

2235
2236
2237

2238
2239

2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258

2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277

2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292

2293
2294
2295



2296
2297

2298
2299
2300
2301
2302
2303
2304


2305
2306

2307
2308
2309
2310
2311
2312
2313
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016

3017
3018
3019

3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041

3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060

3061
3062
3063
3064

3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076



3077
3078
3079


3080
3081

3082
3083
3084
3085

3086
3087
3088

3089
3090
3091
3092
3093
3094
3095
3096







+
+
+
+
+
+
+
+
+
+










+

-
+


-
+


+


















-
+


















-
+



-











+
-
-
-
+
+
+
-
-
+

-




-
+
+

-
+







  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
  ** allocated rather than point to the input string - which means that
  ** they will persist after the current sqlite3_exec() call returns.
  */
  pSelect->selFlags |= SF_View;
  if( IN_RENAME_OBJECT ){
    p->pSelect = pSelect;
    p->u.view.pSelect = pSelect;
    pSelect = 0;
  }else{
    p->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
    p->u.view.pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
  }
  p->pCheck = sqlite3ExprListDup(db, pCNames, EXPRDUP_REDUCE);
  p->eTabType = TABTYP_VIEW;
  if( db->mallocFailed ) goto create_view_fail;

  /* Locate the end of the CREATE VIEW statement.  Make sEnd point to
  ** the end.
  */
  sEnd = pParse->sLastToken;
  assert( sEnd.z[0]!=0 || sEnd.n==0 );
  if( sEnd.z[0]!=';' ){
    sEnd.z += sEnd.n;
  }
  sEnd.n = 0;
  n = (int)(sEnd.z - pBegin->z);
  assert( n>0 );
  z = pBegin->z;
  while( sqlite3Isspace(z[n-1]) ){ n--; }
  sEnd.z = &z[n-1];
  sEnd.n = 1;

  /* Use sqlite3EndTable() to add the view to the SQLITE_MASTER table */
  /* Use sqlite3EndTable() to add the view to the schema table */
  sqlite3EndTable(pParse, 0, &sEnd, 0, 0);

create_view_fail:
  sqlite3SelectDelete(db, pSelect);
  if( IN_RENAME_OBJECT ){
    sqlite3RenameExprlistUnmap(pParse, pCNames);
  }
  sqlite3ExprListDelete(db, pCNames);
  return;
}
#endif /* SQLITE_OMIT_VIEW */

#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
/*
** The Table structure pTable is really a VIEW.  Fill in the names of
** the columns of the view in the pTable structure.  Return the number
** of errors.  If an error is seen leave an error message in pParse->zErrMsg.
*/
int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
static SQLITE_NOINLINE int viewGetColumnNames(Parse *pParse, Table *pTable){
  Table *pSelTab;   /* A fake table from which we get the result set */
  Select *pSel;     /* Copy of the SELECT that implements the view */
  int nErr = 0;     /* Number of errors encountered */
  int n;            /* Temporarily holds the number of cursors assigned */
  sqlite3 *db = pParse->db;  /* Database connection for malloc errors */
#ifndef SQLITE_OMIT_VIRTUALTABLE
  int rc;
#endif
#ifndef SQLITE_OMIT_AUTHORIZATION
  sqlite3_xauth xAuth;       /* Saved xAuth pointer */
#endif

  assert( pTable );

#ifndef SQLITE_OMIT_VIRTUALTABLE
  if( IsVirtual(pTable) ){
  db->nSchemaLock++;
  rc = sqlite3VtabCallConnect(pParse, pTable);
  db->nSchemaLock--;
    db->nSchemaLock++;
    rc = sqlite3VtabCallConnect(pParse, pTable);
    db->nSchemaLock--;
  if( rc ){
    return 1;
    return rc;
  }
  if( IsVirtual(pTable) ) return 0;
#endif

#ifndef SQLITE_OMIT_VIEW
  /* A positive nCol means the columns names for this view are
  ** already known.
  ** already known.  This routine is not called unless either the
  ** table is virtual or nCol is zero.
  */
  if( pTable->nCol>0 ) return 0;
  assert( pTable->nCol<=0 );

  /* A negative nCol is a special marker meaning that we are currently
  ** trying to compute the column names.  If we enter this routine with
  ** a negative nCol, it means two or more views form a loop, like this:
  **
  **     CREATE VIEW one AS SELECT * FROM two;
  **     CREATE VIEW two AS SELECT * FROM one;
2329
2330
2331
2332
2333
2334
2335
2336
2337


2338
2339
2340


2341
2342
2343
2344
2345
2346

2347
2348
2349
2350

2351
2352
2353

2354
2355
2356






2357
2358
2359
2360
2361
2362
2363
2364
2365
2366

2367
2368

2369

2370
2371

2372
2373
2374
2375
2376
2377

2378
2379
2380
2381
2382
2383
2384

2385
2386
2387

2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401





2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415

2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
3112
3113
3114
3115
3116
3117
3118


3119
3120
3121

3122
3123
3124
3125


3126
3127

3128
3129
3130
3131

3132
3133
3134

3135
3136


3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150


3151
3152
3153
3154

3155
3156

3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167



3168
3169
3170
3171

3172

3173

3174
3175
3176
3177
3178
3179


3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200

3201
3202


3203
3204
3205
3206
3207
3208
3209







-
-
+
+

-

+
+

-
-


-
+



-
+


-
+

-
-
+
+
+
+
+
+








-
-
+


+
-
+

-
+






+



-
-
-

+


-
+
-

-






-
-



+
+
+
+
+













-
+

-
-







  /* If we get this far, it means we need to compute the table names.
  ** Note that the call to sqlite3ResultSetOfSelect() will expand any
  ** "*" elements in the results set of the view and will assign cursors
  ** to the elements of the FROM clause.  But we do not want these changes
  ** to be permanent.  So the computation is done on a copy of the SELECT
  ** statement that defines the view.
  */
  assert( pTable->pSelect );
  pSel = sqlite3SelectDup(db, pTable->pSelect, 0);
  assert( IsView(pTable) );
  pSel = sqlite3SelectDup(db, pTable->u.view.pSelect, 0);
  if( pSel ){
#ifndef SQLITE_OMIT_ALTERTABLE
    u8 eParseMode = pParse->eParseMode;
    int nTab = pParse->nTab;
    int nSelect = pParse->nSelect;
    pParse->eParseMode = PARSE_MODE_NORMAL;
#endif
    n = pParse->nTab;
    sqlite3SrcListAssignCursors(pParse, pSel->pSrc);
    pTable->nCol = -1;
    db->lookaside.bDisable++;
    DisableLookaside;
#ifndef SQLITE_OMIT_AUTHORIZATION
    xAuth = db->xAuth;
    db->xAuth = 0;
    pSelTab = sqlite3ResultSetOfSelect(pParse, pSel);
    pSelTab = sqlite3ResultSetOfSelect(pParse, pSel, SQLITE_AFF_NONE);
    db->xAuth = xAuth;
#else
    pSelTab = sqlite3ResultSetOfSelect(pParse, pSel);
    pSelTab = sqlite3ResultSetOfSelect(pParse, pSel, SQLITE_AFF_NONE);
#endif
    pParse->nTab = n;
    if( pTable->pCheck ){
    pParse->nTab = nTab;
    pParse->nSelect = nSelect;
    if( pSelTab==0 ){
      pTable->nCol = 0;
      nErr++;
    }else if( pTable->pCheck ){
      /* CREATE VIEW name(arglist) AS ...
      ** The names of the columns in the table are taken from
      ** arglist which is stored in pTable->pCheck.  The pCheck field
      ** normally holds CHECK constraints on an ordinary table, but for
      ** a VIEW it holds the list of column names.
      */
      sqlite3ColumnsFromExprList(pParse, pTable->pCheck, 
                                 &pTable->nCol, &pTable->aCol);
      if( db->mallocFailed==0 
       && pParse->nErr==0
      if( pParse->nErr==0
       && pTable->nCol==pSel->pEList->nExpr
      ){
        assert( db->mallocFailed==0 );
        sqlite3SelectAddColumnTypeAndCollation(pParse, pTable, pSel);
        sqlite3SubqueryColumnTypes(pParse, pTable, pSel, SQLITE_AFF_NONE);
      }
    }else if( pSelTab ){
    }else{
      /* CREATE VIEW name AS...  without an argument list.  Construct
      ** the column names from the SELECT statement that defines the view.
      */
      assert( pTable->aCol==0 );
      pTable->nCol = pSelTab->nCol;
      pTable->aCol = pSelTab->aCol;
      pTable->tabFlags |= (pSelTab->tabFlags & COLFLAG_NOINSERT);
      pSelTab->nCol = 0;
      pSelTab->aCol = 0;
      assert( sqlite3SchemaMutexHeld(db, 0, pTable->pSchema) );
    }else{
      pTable->nCol = 0;
      nErr++;
    }
    pTable->nNVCol = pTable->nCol;
    sqlite3DeleteTable(db, pSelTab);
    sqlite3SelectDelete(db, pSel);
    db->lookaside.bDisable--;
    EnableLookaside;
#ifndef SQLITE_OMIT_ALTERTABLE
    pParse->eParseMode = eParseMode;
#endif
  } else {
    nErr++;
  }
  pTable->pSchema->schemaFlags |= DB_UnresetViews;
  if( db->mallocFailed ){
    sqlite3DeleteColumnNames(db, pTable);
    pTable->aCol = 0;
    pTable->nCol = 0;
  }
#endif /* SQLITE_OMIT_VIEW */
  return nErr;  
}
int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
  assert( pTable!=0 );
  if( !IsVirtual(pTable) && pTable->nCol>0 ) return 0;
  return viewGetColumnNames(pParse, pTable);
}
#endif /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */

#ifndef SQLITE_OMIT_VIEW
/*
** Clear the column names from every VIEW in database idx.
*/
static void sqliteViewResetAll(sqlite3 *db, int idx){
  HashElem *i;
  assert( sqlite3SchemaMutexHeld(db, idx, 0) );
  if( !DbHasProperty(db, idx, DB_UnresetViews) ) return;
  for(i=sqliteHashFirst(&db->aDb[idx].pSchema->tblHash); i;i=sqliteHashNext(i)){
    Table *pTab = sqliteHashData(i);
    if( pTab->pSelect ){
    if( IsView(pTab) ){
      sqlite3DeleteColumnNames(db, pTab);
      pTab->aCol = 0;
      pTab->nCol = 0;
    }
  }
  DbClearProperty(db, idx, DB_UnresetViews);
}
#else
# define sqliteViewResetAll(A,B)
#endif /* SQLITE_OMIT_VIEW */
2438
2439
2440
2441
2442
2443
2444
2445

2446
2447
2448
2449
2450
2451
2452
3222
3223
3224
3225
3226
3227
3228

3229
3230
3231
3232
3233
3234
3235
3236







-
+







** because the first match might be for one of the deleted indices
** or tables and not the table/index that is actually being moved.
** We must continue looping until all tables and indices with
** rootpage==iFrom have been converted to have a rootpage of iTo
** in order to be certain that we got the right one.
*/
#ifndef SQLITE_OMIT_AUTOVACUUM
void sqlite3RootPageMoved(sqlite3 *db, int iDb, int iFrom, int iTo){
void sqlite3RootPageMoved(sqlite3 *db, int iDb, Pgno iFrom, Pgno iTo){
  HashElem *pElem;
  Hash *pHash;
  Db *pDb;

  assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
  pDb = &db->aDb[iDb];
  pHash = &pDb->pSchema->tblHash;
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
2493


2494
2495
2496
2497
2498
2499
2500

2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522


2523
2524
2525
2526

2527
2528
2529
2530
2531
2532

2533
2534
2535
2536
2537
2538
2539
3248
3249
3250
3251
3252
3253
3254

3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267

3268
3269
3270
3271
3272
3273
3274
3275
3276


3277
3278
3279
3280
3281
3282
3283
3284

3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305


3306
3307
3308
3309
3310

3311
3312
3313
3314
3315
3316

3317
3318
3319
3320
3321
3322
3323
3324







-
+












-
+







+
-
-
+
+






-
+




















-
-
+
+



-
+





-
+







    }
  }
}
#endif

/*
** Write code to erase the table with root-page iTable from database iDb.
** Also write code to modify the sqlite_master table and internal schema
** Also write code to modify the sqlite_schema table and internal schema
** if a root-page of another table is moved by the btree-layer whilst
** erasing iTable (this can happen with an auto-vacuum database).
*/ 
static void destroyRootPage(Parse *pParse, int iTable, int iDb){
  Vdbe *v = sqlite3GetVdbe(pParse);
  int r1 = sqlite3GetTempReg(pParse);
  if( iTable<2 ) sqlite3ErrorMsg(pParse, "corrupt schema");
  sqlite3VdbeAddOp3(v, OP_Destroy, iTable, r1, iDb);
  sqlite3MayAbort(pParse);
#ifndef SQLITE_OMIT_AUTOVACUUM
  /* OP_Destroy stores an in integer r1. If this integer
  ** is non-zero, then it is the root page number of a table moved to
  ** location iTable. The following code modifies the sqlite_master table to
  ** location iTable. The following code modifies the sqlite_schema table to
  ** reflect this.
  **
  ** The "#NNN" in the SQL is a special constant that means whatever value
  ** is in register NNN.  See grammar rules associated with the TK_REGISTER
  ** token for additional information.
  */
  sqlite3NestedParse(pParse, 
     "UPDATE %Q." LEGACY_SCHEMA_TABLE
     "UPDATE %Q.%s SET rootpage=%d WHERE #%d AND rootpage=#%d",
     pParse->db->aDb[iDb].zDbSName, MASTER_NAME, iTable, r1, r1);
     " SET rootpage=%d WHERE #%d AND rootpage=#%d",
     pParse->db->aDb[iDb].zDbSName, iTable, r1, r1);
#endif
  sqlite3ReleaseTempReg(pParse, r1);
}

/*
** Write VDBE code to erase table pTab and all associated indices on disk.
** Code to update the sqlite_master tables and internal schema definitions
** Code to update the sqlite_schema tables and internal schema definitions
** in case a root-page belonging to another table is moved by the btree layer
** is also added (this can happen with an auto-vacuum database).
*/
static void destroyTable(Parse *pParse, Table *pTab){
  /* If the database may be auto-vacuum capable (if SQLITE_OMIT_AUTOVACUUM
  ** is not defined), then it is important to call OP_Destroy on the
  ** table and index root-pages in order, starting with the numerically 
  ** largest root-page number. This guarantees that none of the root-pages
  ** to be destroyed is relocated by an earlier OP_Destroy. i.e. if the
  ** following were coded:
  **
  ** OP_Destroy 4 0
  ** ...
  ** OP_Destroy 5 0
  **
  ** and root page 5 happened to be the largest root-page number in the
  ** database, then root page 5 would be moved to page 4 by the 
  ** "OP_Destroy 4 0" opcode. The subsequent "OP_Destroy 5 0" would hit
  ** a free-list page.
  */
  int iTab = pTab->tnum;
  int iDestroyed = 0;
  Pgno iTab = pTab->tnum;
  Pgno iDestroyed = 0;

  while( 1 ){
    Index *pIdx;
    int iLargest = 0;
    Pgno iLargest = 0;

    if( iDestroyed==0 || iTab<iDestroyed ){
      iLargest = iTab;
    }
    for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
      int iIdx = pIdx->tnum;
      Pgno iIdx = pIdx->tnum;
      assert( pIdx->pSchema==pTab->pSchema );
      if( (iDestroyed==0 || (iIdx<iDestroyed)) && iIdx>iLargest ){
        iLargest = iIdx;
      }
    }
    if( iLargest==0 ){
      return;
2586
2587
2588
2589
2590
2591
2592
2593
2594


2595
2596
2597
2598
2599
2600
2601
3371
3372
3373
3374
3375
3376
3377


3378
3379
3380
3381
3382
3383
3384
3385
3386







-
-
+
+







#ifndef SQLITE_OMIT_VIRTUALTABLE
  if( IsVirtual(pTab) ){
    sqlite3VdbeAddOp0(v, OP_VBegin);
  }
#endif

  /* Drop all triggers associated with the table being dropped. Code
  ** is generated to remove entries from sqlite_master and/or
  ** sqlite_temp_master if required.
  ** is generated to remove entries from sqlite_schema and/or
  ** sqlite_temp_schema if required.
  */
  pTrigger = sqlite3TriggerList(pParse, pTab);
  while( pTrigger ){
    assert( pTrigger->pSchema==pTab->pSchema || 
        pTrigger->pSchema==db->aDb[1].pSchema );
    sqlite3DropTriggerPtr(pParse, pTrigger);
    pTrigger = pTrigger->pNext;
2611
2612
2613
2614
2615
2616
2617
2618
2619


2620
2621
2622
2623
2624
2625

2626
2627


2628
2629
2630
2631
2632
2633
2634
2635
2636

2637
2638
2639
2640
2641



































2642
2643
2644
2645
2646
2647
2648
3396
3397
3398
3399
3400
3401
3402


3403
3404
3405
3406
3407
3408
3409
3410
3411


3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470







-
-
+
+






+
-
-
+
+









+





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







    sqlite3NestedParse(pParse,
      "DELETE FROM %Q.sqlite_sequence WHERE name=%Q",
      pDb->zDbSName, pTab->zName
    );
  }
#endif

  /* Drop all SQLITE_MASTER table and index entries that refer to the
  ** table. The program name loops through the master table and deletes
  /* Drop all entries in the schema table that refer to the
  ** table. The program name loops through the schema table and deletes
  ** every row that refers to a table of the same name as the one being
  ** dropped. Triggers are handled separately because a trigger can be
  ** created in the temp database that refers to a table in another
  ** database.
  */
  sqlite3NestedParse(pParse, 
      "DELETE FROM %Q." LEGACY_SCHEMA_TABLE
      "DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'",
      pDb->zDbSName, MASTER_NAME, pTab->zName);
      " WHERE tbl_name=%Q and type!='trigger'",
      pDb->zDbSName, pTab->zName);
  if( !isView && !IsVirtual(pTab) ){
    destroyTable(pParse, pTab);
  }

  /* Remove the table entry from SQLite's internal schema and modify
  ** the schema cookie.
  */
  if( IsVirtual(pTab) ){
    sqlite3VdbeAddOp4(v, OP_VDestroy, iDb, 0, 0, pTab->zName, 0);
    sqlite3MayAbort(pParse);
  }
  sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0);
  sqlite3ChangeCookie(pParse, iDb);
  sqliteViewResetAll(db, iDb);
}

/*
** Return TRUE if shadow tables should be read-only in the current
** context.
*/
int sqlite3ReadOnlyShadowTables(sqlite3 *db){
#ifndef SQLITE_OMIT_VIRTUALTABLE
  if( (db->flags & SQLITE_Defensive)!=0
   && db->pVtabCtx==0
   && db->nVdbeExec==0
   && !sqlite3VtabInSync(db)
  ){
    return 1;
  }
#endif
  return 0;
}

/*
** Return true if it is not allowed to drop the given table
*/
static int tableMayNotBeDropped(sqlite3 *db, Table *pTab){
  if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){
    if( sqlite3StrNICmp(pTab->zName+7, "stat", 4)==0 ) return 0;
    if( sqlite3StrNICmp(pTab->zName+7, "parameters", 10)==0 ) return 0;
    return 1;
  }
  if( (pTab->tabFlags & TF_Shadow)!=0 && sqlite3ReadOnlyShadowTables(db) ){
    return 1;
  }
  if( pTab->tabFlags & TF_Eponymous ){
    return 1;
  }
  return 0;
}

/*
** This routine is called to do the work of a DROP TABLE statement.
** pName is the name of the table to be dropped.
*/
void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
  Table *pTab;
2658
2659
2660
2661
2662
2663
2664

2665



2666
2667
2668
2669
2670
2671
2672
3480
3481
3482
3483
3484
3485
3486
3487

3488
3489
3490
3491
3492
3493
3494
3495
3496
3497







+
-
+
+
+







  if( sqlite3ReadSchema(pParse) ) goto exit_drop_table;
  if( noErr ) db->suppressErr++;
  assert( isView==0 || isView==LOCATE_VIEW );
  pTab = sqlite3LocateTableItem(pParse, isView, &pName->a[0]);
  if( noErr ) db->suppressErr--;

  if( pTab==0 ){
    if( noErr ){
    if( noErr ) sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
      sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
      sqlite3ForceNotReadOnly(pParse);
    }
    goto exit_drop_table;
  }
  iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
  assert( iDb>=0 && iDb<db->nDb );

  /* If pTab is a virtual table, call ViewGetColumnNames() to ensure
  ** it is initialized.
2705
2706
2707
2708
2709
2710
2711
2712

2713
2714
2715
2716
2717
2718
2719
2720
2721
2722

2723
2724
2725
2726

2727
2728
2729
2730
2731
2732

2733
2734
2735
2736
2737
2738
2739
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







-
+
-








-
+



-
+





-
+







      goto exit_drop_table;
    }
    if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){
      goto exit_drop_table;
    }
  }
#endif
  if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 
  if( tableMayNotBeDropped(db, pTab) ){
    && sqlite3StrNICmp(pTab->zName, "sqlite_stat", 11)!=0 ){
    sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName);
    goto exit_drop_table;
  }

#ifndef SQLITE_OMIT_VIEW
  /* Ensure DROP TABLE is not used on a view, and DROP VIEW is not used
  ** on a table.
  */
  if( isView && pTab->pSelect==0 ){
  if( isView && !IsView(pTab) ){
    sqlite3ErrorMsg(pParse, "use DROP TABLE to delete table %s", pTab->zName);
    goto exit_drop_table;
  }
  if( !isView && pTab->pSelect ){
  if( !isView && IsView(pTab) ){
    sqlite3ErrorMsg(pParse, "use DROP VIEW to delete view %s", pTab->zName);
    goto exit_drop_table;
  }
#endif

  /* Generate code to remove the table from the master table
  /* Generate code to remove the table from the schema table
  ** on disk.
  */
  v = sqlite3GetVdbe(pParse);
  if( v ){
    sqlite3BeginWriteOperation(pParse, 1, iDb);
    if( !isView ){
      sqlite3ClearStatTables(pParse, iDb, "tbl", pTab->zName);
2770
2771
2772
2773
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
2811
2812

2813

2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830

2831
2832
2833
2834
2835
2836
2837
2838

2839
2840
2841
2842

2843
2844
2845
2846
2847
2848

2849
2850
2851

2852
2853

2854
2855
2856
2857
2858
2859
2860
3594
3595
3596
3597
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
3659
3660
3661
3662

3663
3664
3665
3666

3667
3668
3669
3670
3671
3672

3673
3674
3675

3676
3677

3678
3679
3680
3681
3682
3683
3684
3685







-
+












-
+














-
+







+
-
+
















-
+







-
+



-
+





-
+


-
+

-
+







  int flags            /* Conflict resolution algorithms. */
){
  sqlite3 *db = pParse->db;
#ifndef SQLITE_OMIT_FOREIGN_KEY
  FKey *pFKey = 0;
  FKey *pNextTo;
  Table *p = pParse->pNewTable;
  int nByte;
  i64 nByte;
  int i;
  int nCol;
  char *z;

  assert( pTo!=0 );
  if( p==0 || IN_DECLARE_VTAB ) goto fk_end;
  if( pFromCol==0 ){
    int iCol = p->nCol-1;
    if( NEVER(iCol<0) ) goto fk_end;
    if( pToCol && pToCol->nExpr!=1 ){
      sqlite3ErrorMsg(pParse, "foreign key on %s"
         " should reference only one column of table %T",
         p->aCol[iCol].zName, pTo);
         p->aCol[iCol].zCnName, pTo);
      goto fk_end;
    }
    nCol = 1;
  }else if( pToCol && pToCol->nExpr!=pFromCol->nExpr ){
    sqlite3ErrorMsg(pParse,
        "number of columns in foreign key does not match the number of "
        "columns in the referenced table");
    goto fk_end;
  }else{
    nCol = pFromCol->nExpr;
  }
  nByte = sizeof(*pFKey) + (nCol-1)*sizeof(pFKey->aCol[0]) + pTo->n + 1;
  if( pToCol ){
    for(i=0; i<pToCol->nExpr; i++){
      nByte += sqlite3Strlen30(pToCol->a[i].zName) + 1;
      nByte += sqlite3Strlen30(pToCol->a[i].zEName) + 1;
    }
  }
  pFKey = sqlite3DbMallocZero(db, nByte );
  if( pFKey==0 ){
    goto fk_end;
  }
  pFKey->pFrom = p;
  assert( IsOrdinaryTable(p) );
  pFKey->pNextFrom = p->pFKey;
  pFKey->pNextFrom = p->u.tab.pFKey;
  z = (char*)&pFKey->aCol[nCol];
  pFKey->zTo = z;
  if( IN_RENAME_OBJECT ){
    sqlite3RenameTokenMap(pParse, (void*)z, pTo);
  }
  memcpy(z, pTo->z, pTo->n);
  z[pTo->n] = 0;
  sqlite3Dequote(z);
  z += pTo->n+1;
  pFKey->nCol = nCol;
  if( pFromCol==0 ){
    pFKey->aCol[0].iFrom = p->nCol-1;
  }else{
    for(i=0; i<nCol; i++){
      int j;
      for(j=0; j<p->nCol; j++){
        if( sqlite3StrICmp(p->aCol[j].zName, pFromCol->a[i].zName)==0 ){
        if( sqlite3StrICmp(p->aCol[j].zCnName, pFromCol->a[i].zEName)==0 ){
          pFKey->aCol[i].iFrom = j;
          break;
        }
      }
      if( j>=p->nCol ){
        sqlite3ErrorMsg(pParse, 
          "unknown column \"%s\" in foreign key definition", 
          pFromCol->a[i].zName);
          pFromCol->a[i].zEName);
        goto fk_end;
      }
      if( IN_RENAME_OBJECT ){
        sqlite3RenameTokenRemap(pParse, &pFKey->aCol[i], pFromCol->a[i].zName);
        sqlite3RenameTokenRemap(pParse, &pFKey->aCol[i], pFromCol->a[i].zEName);
      }
    }
  }
  if( pToCol ){
    for(i=0; i<nCol; i++){
      int n = sqlite3Strlen30(pToCol->a[i].zName);
      int n = sqlite3Strlen30(pToCol->a[i].zEName);
      pFKey->aCol[i].zCol = z;
      if( IN_RENAME_OBJECT ){
        sqlite3RenameTokenRemap(pParse, z, pToCol->a[i].zName);
        sqlite3RenameTokenRemap(pParse, z, pToCol->a[i].zEName);
      }
      memcpy(z, pToCol->a[i].zName, n);
      memcpy(z, pToCol->a[i].zEName, n);
      z[n] = 0;
      z += n+1;
    }
  }
  pFKey->isDeferred = 0;
  pFKey->aAction[0] = (u8)(flags & 0xff);            /* ON DELETE action */
  pFKey->aAction[1] = (u8)((flags >> 8 ) & 0xff);    /* ON UPDATE action */
2871
2872
2873
2874
2875
2876
2877

2878

2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899



2900
2901
2902
2903
2904
2905
2906
3696
3697
3698
3699
3700
3701
3702
3703

3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724

3725
3726
3727
3728
3729
3730
3731
3732
3733
3734







+
-
+




















-
+
+
+







    assert( pNextTo->pPrevTo==0 );
    pFKey->pNextTo = pNextTo;
    pNextTo->pPrevTo = pFKey;
  }

  /* Link the foreign key to the table as the last step.
  */
  assert( IsOrdinaryTable(p) );
  p->pFKey = pFKey;
  p->u.tab.pFKey = pFKey;
  pFKey = 0;

fk_end:
  sqlite3DbFree(db, pFKey);
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
  sqlite3ExprListDelete(db, pFromCol);
  sqlite3ExprListDelete(db, pToCol);
}

/*
** This routine is called when an INITIALLY IMMEDIATE or INITIALLY DEFERRED
** clause is seen as part of a foreign key definition.  The isDeferred
** parameter is 1 for INITIALLY DEFERRED and 0 for INITIALLY IMMEDIATE.
** The behavior of the most recently created foreign key is adjusted
** accordingly.
*/
void sqlite3DeferForeignKey(Parse *pParse, int isDeferred){
#ifndef SQLITE_OMIT_FOREIGN_KEY
  Table *pTab;
  FKey *pFKey;
  if( (pTab = pParse->pNewTable)==0 || (pFKey = pTab->pFKey)==0 ) return;
  if( (pTab = pParse->pNewTable)==0 ) return;
  if( NEVER(!IsOrdinaryTable(pTab)) ) return;
  if( (pFKey = pTab->u.tab.pFKey)==0 ) return;
  assert( isDeferred==0 || isDeferred==1 ); /* EV: R-30323-21917 */
  pFKey->isDeferred = (u8)isDeferred;
#endif
}

/*
** Generate code that will erase and refill index *pIdx.  This is
2916
2917
2918
2919
2920
2921
2922
2923

2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944

2945
2946
2947
2948
2949

2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969

2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982








2983
2984
2985








2986


2987
2988
2989
2990
2991
2992
2993
3744
3745
3746
3747
3748
3749
3750

3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771

3772
3773
3774
3775
3776

3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796

3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829

3830
3831
3832
3833
3834
3835
3836
3837
3838







-
+




















-
+




-
+



















-
+













+
+
+
+
+
+
+
+



+
+
+
+
+
+
+
+
-
+
+







static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
  Table *pTab = pIndex->pTable;  /* The table that is indexed */
  int iTab = pParse->nTab++;     /* Btree cursor used for pTab */
  int iIdx = pParse->nTab++;     /* Btree cursor used for pIndex */
  int iSorter;                   /* Cursor opened by OpenSorter (if in use) */
  int addr1;                     /* Address of top of loop */
  int addr2;                     /* Address to jump to for next iteration */
  int tnum;                      /* Root page of index */
  Pgno tnum;                     /* Root page of index */
  int iPartIdxLabel;             /* Jump to this label to skip a row */
  Vdbe *v;                       /* Generate code into this virtual machine */
  KeyInfo *pKey;                 /* KeyInfo for index */
  int regRecord;                 /* Register holding assembled index record */
  sqlite3 *db = pParse->db;      /* The database connection */
  int iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);

#ifndef SQLITE_OMIT_AUTHORIZATION
  if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0,
      db->aDb[iDb].zDbSName ) ){
    return;
  }
#endif

  /* Require a write-lock on the table to perform this operation */
  sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName);

  v = sqlite3GetVdbe(pParse);
  if( v==0 ) return;
  if( memRootPage>=0 ){
    tnum = memRootPage;
    tnum = (Pgno)memRootPage;
  }else{
    tnum = pIndex->tnum;
  }
  pKey = sqlite3KeyInfoOfIndex(pParse, pIndex);
  assert( pKey!=0 || db->mallocFailed || pParse->nErr );
  assert( pKey!=0 || pParse->nErr );

  /* Open the sorter cursor if we are to use one. */
  iSorter = pParse->nTab++;
  sqlite3VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, pIndex->nKeyCol, (char*)
                    sqlite3KeyInfoRef(pKey), P4_KEYINFO);

  /* Open the table. Loop through all rows of the table, inserting index
  ** records into the sorter. */
  sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
  addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); VdbeCoverage(v);
  regRecord = sqlite3GetTempReg(pParse);
  sqlite3MultiWrite(pParse);

  sqlite3GenerateIndexKey(pParse,pIndex,iTab,regRecord,0,&iPartIdxLabel,0,0);
  sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord);
  sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel);
  sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1); VdbeCoverage(v);
  sqlite3VdbeJumpHere(v, addr1);
  if( memRootPage<0 ) sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb);
  sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb, 
  sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, (int)tnum, iDb, 
                    (char *)pKey, P4_KEYINFO);
  sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0));

  addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0); VdbeCoverage(v);
  if( IsUniqueIndex(pIndex) ){
    int j2 = sqlite3VdbeGoto(v, 1);
    addr2 = sqlite3VdbeCurrentAddr(v);
    sqlite3VdbeVerifyAbortable(v, OE_Abort);
    sqlite3VdbeAddOp4Int(v, OP_SorterCompare, iSorter, j2, regRecord,
                         pIndex->nKeyCol); VdbeCoverage(v);
    sqlite3UniqueConstraint(pParse, OE_Abort, pIndex);
    sqlite3VdbeJumpHere(v, j2);
  }else{
    /* Most CREATE INDEX and REINDEX statements that are not UNIQUE can not
    ** abort. The exception is if one of the indexed expressions contains a
    ** user function that throws an exception when it is evaluated. But the
    ** overhead of adding a statement journal to a CREATE INDEX statement is
    ** very small (since most of the pages written do not contain content that
    ** needs to be restored if the statement aborts), so we call 
    ** sqlite3MayAbort() for all CREATE INDEX statements.  */
    sqlite3MayAbort(pParse);
    addr2 = sqlite3VdbeCurrentAddr(v);
  }
  sqlite3VdbeAddOp3(v, OP_SorterData, iSorter, regRecord, iIdx);
  if( !pIndex->bAscKeyBug ){
    /* This OP_SeekEnd opcode makes index insert for a REINDEX go much
    ** faster by avoiding unnecessary seeks.  But the optimization does
    ** not work for UNIQUE constraint indexes on WITHOUT ROWID tables
    ** with DESC primary keys, since those indexes have there keys in
    ** a different order from the main table.
    ** See ticket: https://www.sqlite.org/src/info/bba7b69f9849b5bf
    */
  sqlite3VdbeAddOp1(v, OP_SeekEnd, iIdx);
    sqlite3VdbeAddOp1(v, OP_SeekEnd, iIdx);
  }
  sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdx, regRecord);
  sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
  sqlite3ReleaseTempReg(pParse, regRecord);
  sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2); VdbeCoverage(v);
  sqlite3VdbeJumpHere(v, addr1);

  sqlite3VdbeAddOp1(v, OP_Close, iTab);
3025
3026
3027
3028
3029
3030
3031





















3032
3033
3034
3035
3036
3037
3038
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
3899
3900
3901
3902
3903
3904







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







    p->aSortOrder = (u8*)pExtra;
    p->nColumn = nCol;
    p->nKeyCol = nCol - 1;
    *ppExtra = ((char*)p) + nByte;
  }
  return p;
}

/*
** If expression list pList contains an expression that was parsed with
** an explicit "NULLS FIRST" or "NULLS LAST" clause, leave an error in
** pParse and return non-zero. Otherwise, return zero.
*/
int sqlite3HasExplicitNulls(Parse *pParse, ExprList *pList){
  if( pList ){
    int i;
    for(i=0; i<pList->nExpr; i++){
      if( pList->a[i].fg.bNulls ){
        u8 sf = pList->a[i].fg.sortFlags;
        sqlite3ErrorMsg(pParse, "unsupported use of NULLS %s", 
            (sf==0 || sf==3) ? "FIRST" : "LAST"
        );
        return 1;
      }
    }
  }
  return 0;
}

/*
** Create a new index for an SQL table.  pName1.pName2 is the name of the index 
** and pTblList is the name of the table that is to be indexed.  Both will 
** be NULL for a primary key or an index that is created to satisfy a
** UNIQUE constraint.  If pTable and pIndex are NULL, use pParse->pNewTable
** as the table to be indexed.  pParse->pNewTable is a table that is
3068
3069
3070
3071
3072
3073
3074

3075

3076
3077

3078
3079
3080
3081
3082



3083
3084
3085
3086
3087
3088
3089
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







+
-
+


+





+
+
+







  Token *pName = 0;    /* Unqualified name of the index to create */
  struct ExprList_item *pListItem; /* For looping over pList */
  int nExtra = 0;                  /* Space allocated for zExtra[] */
  int nExtraCol;                   /* Number of extra columns needed */
  char *zExtra = 0;                /* Extra space after the Index object */
  Index *pPk = 0;      /* PRIMARY KEY index for WITHOUT ROWID tables */

  assert( db->pParse==pParse );
  if( db->mallocFailed || pParse->nErr>0 ){
  if( pParse->nErr ){
    goto exit_create_index;
  }
  assert( db->mallocFailed==0 );
  if( IN_DECLARE_VTAB && idxType!=SQLITE_IDXTYPE_PRIMARYKEY ){
    goto exit_create_index;
  }
  if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
    goto exit_create_index;
  }
  if( sqlite3HasExplicitNulls(pParse, pList) ){
    goto exit_create_index;
  }

  /*
  ** Find the table that is to be indexed.  Return early if not found.
  */
  if( pTblName!=0 ){

3131
3132
3133
3134
3135
3136
3137
3138
3139
3140

3141
3142
3143
3144
3145
3146
3147
3148

3149
3150
3151
3152
3153

3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170

3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182

3183
3184
3185
3186
3187

3188
3189
3190
3191
3192
3193
3194
3195
3196
3197

3198
3199
3200
3201
3202
3203
3204
4002
4003
4004
4005
4006
4007
4008

4009
4010
4011
4012
4013
4014





4015
4016
4017
4018
4019

4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036

4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048

4049
4050
4051
4052
4053

4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072







-


+



-
-
-
-
-
+




-
+
















-
+











-
+




-
+










+







    pTab = pParse->pNewTable;
    if( !pTab ) goto exit_create_index;
    iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
  }
  pDb = &db->aDb[iDb];

  assert( pTab!=0 );
  assert( pParse->nErr==0 );
  if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 
       && db->init.busy==0
       && pTblName!=0
#if SQLITE_USER_AUTHENTICATION
       && sqlite3UserAuthTable(pTab->zName)==0
#endif
#ifdef SQLITE_ALLOW_SQLITE_MASTER_INDEX
       && sqlite3StrICmp(&pTab->zName[7],"master")!=0
#endif
       && sqlite3StrNICmp(&pTab->zName[7],"altertab_",9)!=0
 ){
  ){
    sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
    goto exit_create_index;
  }
#ifndef SQLITE_OMIT_VIEW
  if( pTab->pSelect ){
  if( IsView(pTab) ){
    sqlite3ErrorMsg(pParse, "views may not be indexed");
    goto exit_create_index;
  }
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
  if( IsVirtual(pTab) ){
    sqlite3ErrorMsg(pParse, "virtual tables may not be indexed");
    goto exit_create_index;
  }
#endif

  /*
  ** Find the name of the index.  Make sure there is not already another
  ** index or table with the same name.  
  **
  ** Exception:  If we are reading the names of permanent indices from the
  ** sqlite_master table (because some other process changed the schema) and
  ** sqlite_schema table (because some other process changed the schema) and
  ** one of the index names collides with the name of a temporary table or
  ** index, then we will continue to process this index.
  **
  ** If pName==0 it means that we are
  ** dealing with a primary key or UNIQUE constraint.  We have to invent our
  ** own name.
  */
  if( pName ){
    zName = sqlite3NameFromToken(db, pName);
    if( zName==0 ) goto exit_create_index;
    assert( pName->z!=0 );
    if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
    if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName,"index",pTab->zName) ){
      goto exit_create_index;
    }
    if( !IN_RENAME_OBJECT ){
      if( !db->init.busy ){
        if( sqlite3FindTable(db, zName, 0)!=0 ){
        if( sqlite3FindTable(db, zName, pDb->zDbSName)!=0 ){
          sqlite3ErrorMsg(pParse, "there is already a table named %s", zName);
          goto exit_create_index;
        }
      }
      if( sqlite3FindIndex(db, zName, pDb->zDbSName)!=0 ){
        if( !ifNotExist ){
          sqlite3ErrorMsg(pParse, "index %s already exists", zName);
        }else{
          assert( !db->init.busy );
          sqlite3CodeVerifySchema(pParse, iDb);
          sqlite3ForceNotReadOnly(pParse);
        }
        goto exit_create_index;
      }
    }
  }else{
    int n;
    Index *pLoop;
3236
3237
3238
3239
3240
3241
3242
3243

3244
3245
3246
3247
3248

3249
3250

3251
3252
3253
3254
3255
3256
3257
3258
3259

3260
3261
3262
3263
3264
3265
3266
3267
3268

3269
3270
3271
3272
3273
3274
3275
4104
4105
4106
4107
4108
4109
4110

4111
4112
4113
4114
4115

4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146







-
+




-
+


+









+









+







  ** key out of the last column added to the table under construction.
  ** So create a fake list to simulate this.
  */
  if( pList==0 ){
    Token prevCol;
    Column *pCol = &pTab->aCol[pTab->nCol-1];
    pCol->colFlags |= COLFLAG_UNIQUE;
    sqlite3TokenInit(&prevCol, pCol->zName);
    sqlite3TokenInit(&prevCol, pCol->zCnName);
    pList = sqlite3ExprListAppend(pParse, 0,
              sqlite3ExprAlloc(db, TK_ID, &prevCol, 0));
    if( pList==0 ) goto exit_create_index;
    assert( pList->nExpr==1 );
    sqlite3ExprListSetSortOrder(pList, sortOrder);
    sqlite3ExprListSetSortOrder(pList, sortOrder, SQLITE_SO_UNDEFINED);
  }else{
    sqlite3ExprListCheckLength(pParse, pList, "index");
    if( pParse->nErr ) goto exit_create_index;
  }

  /* Figure out how many bytes of space are required to store explicitly
  ** specified collation sequence names.
  */
  for(i=0; i<pList->nExpr; i++){
    Expr *pExpr = pList->a[i].pExpr;
    assert( pExpr!=0 );
    if( pExpr->op==TK_COLLATE ){
      assert( !ExprHasProperty(pExpr, EP_IntValue) );
      nExtra += (1 + sqlite3Strlen30(pExpr->u.zToken));
    }
  }

  /* 
  ** Allocate the index structure. 
  */
  nName = sqlite3Strlen30(zName);
  nExtraCol = pPk ? pPk->nKeyCol : 1;
  assert( pList->nExpr + nExtraCol <= 32767 /* Fits in i16 */ );
  pIndex = sqlite3AllocateIndexObject(db, pList->nExpr + nExtraCol,
                                      nName + nExtra + 1, &zExtra);
  if( db->mallocFailed ){
    goto exit_create_index;
  }
  assert( EIGHT_BYTE_ALIGNMENT(pIndex->aiRowLogEst) );
  assert( EIGHT_BYTE_ALIGNMENT(pIndex->azColl) );
3329
3330
3331
3332
3333
3334
3335

3336
3337
3338
3339
3340

3341
3342







3343
3344
3345
3346
3347
3348

3349
3350
3351
3352
3353
3354
3355
3356
3357

3358
3359
3360
3361
3362
3363
3364

3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376

3377
3378

3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396

3397
3398
3399
3400
3401
3402

3403
3404
3405
3406
3407
3408
3409
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213


4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235

4236
4237
4238
4239
4240
4241
4242

4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254

4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275

4276
4277
4278
4279
4280
4281

4282
4283
4284
4285
4286
4287
4288
4289







+





+
-
-
+
+
+
+
+
+
+






+








-
+






-
+











-
+


+

















-
+





-
+







      if( pIndex->aColExpr==0 ){
        pIndex->aColExpr = pList;
        pList = 0;
      }
      j = XN_EXPR;
      pIndex->aiColumn[i] = XN_EXPR;
      pIndex->uniqNotNull = 0;
      pIndex->bHasExpr = 1;
    }else{
      j = pCExpr->iColumn;
      assert( j<=0x7fff );
      if( j<0 ){
        j = pTab->iPKey;
      }else{
      }else if( pTab->aCol[j].notNull==0 ){
        pIndex->uniqNotNull = 0;
        if( pTab->aCol[j].notNull==0 ){
          pIndex->uniqNotNull = 0;
        }
        if( pTab->aCol[j].colFlags & COLFLAG_VIRTUAL ){
          pIndex->bHasVCol = 1;
          pIndex->bHasExpr = 1;
        }
      }
      pIndex->aiColumn[i] = (i16)j;
    }
    zColl = 0;
    if( pListItem->pExpr->op==TK_COLLATE ){
      int nColl;
      assert( !ExprHasProperty(pListItem->pExpr, EP_IntValue) );
      zColl = pListItem->pExpr->u.zToken;
      nColl = sqlite3Strlen30(zColl) + 1;
      assert( nExtra>=nColl );
      memcpy(zExtra, zColl, nColl);
      zColl = zExtra;
      zExtra += nColl;
      nExtra -= nColl;
    }else if( j>=0 ){
      zColl = pTab->aCol[j].zColl;
      zColl = sqlite3ColumnColl(&pTab->aCol[j]);
    }
    if( !zColl ) zColl = sqlite3StrBINARY;
    if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl) ){
      goto exit_create_index;
    }
    pIndex->azColl[i] = zColl;
    requestedSortOrder = pListItem->sortOrder & sortOrderMask;
    requestedSortOrder = pListItem->fg.sortFlags & sortOrderMask;
    pIndex->aSortOrder[i] = (u8)requestedSortOrder;
  }

  /* Append the table key to the end of the index.  For WITHOUT ROWID
  ** tables (when pPk!=0) this will be the declared PRIMARY KEY.  For
  ** normal tables (when pPk==0) this will be the rowid.
  */
  if( pPk ){
    for(j=0; j<pPk->nKeyCol; j++){
      int x = pPk->aiColumn[j];
      assert( x>=0 );
      if( hasColumn(pIndex->aiColumn, pIndex->nKeyCol, x) ){
      if( isDupColumn(pIndex, pIndex->nKeyCol, pPk, j) ){
        pIndex->nColumn--; 
      }else{
        testcase( hasColumn(pIndex->aiColumn,pIndex->nKeyCol,x) );
        pIndex->aiColumn[i] = x;
        pIndex->azColl[i] = pPk->azColl[j];
        pIndex->aSortOrder[i] = pPk->aSortOrder[j];
        i++;
      }
    }
    assert( i==pIndex->nColumn );
  }else{
    pIndex->aiColumn[i] = XN_ROWID;
    pIndex->azColl[i] = sqlite3StrBINARY;
  }
  sqlite3DefaultRowEst(pIndex);
  if( pParse->pNewTable==0 ) estimateIndexWidth(pIndex);

  /* If this index contains every column of its table, then mark
  ** it as a covering index */
  assert( HasRowid(pTab) 
      || pTab->iPKey<0 || sqlite3ColumnOfIndex(pIndex, pTab->iPKey)>=0 );
      || pTab->iPKey<0 || sqlite3TableColumnToIndex(pIndex, pTab->iPKey)>=0 );
  recomputeColumnsNotIndexed(pIndex);
  if( pTblName!=0 && pIndex->nColumn>=pTab->nCol ){
    pIndex->isCovering = 1;
    for(j=0; j<pTab->nCol; j++){
      if( j==pTab->iPKey ) continue;
      if( sqlite3ColumnOfIndex(pIndex,j)>=0 ) continue;
      if( sqlite3TableColumnToIndex(pIndex,j)>=0 ) continue;
      pIndex->isCovering = 0;
      break;
    }
  }

  if( pTab==pParse->pNewTable ){
    /* This routine has been called to create an automatic index as a
3458
3459
3460
3461
3462
3463
3464





3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479








3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497


3498
3499
3500
3501
3502
3503
3504
4338
4339
4340
4341
4342
4343
4344
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
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380



4381
4382
4383
4384
4385


4386
4387
4388
4389
4390
4391
4392
4393
4394







+
+
+
+
+















+
+
+
+
+
+
+
+








-
-
-





-
-
+
+







                "conflicting ON CONFLICT clauses specified", 0);
          }
          if( pIdx->onError==OE_Default ){
            pIdx->onError = pIndex->onError;
          }
        }
        if( idxType==SQLITE_IDXTYPE_PRIMARYKEY ) pIdx->idxType = idxType;
        if( IN_RENAME_OBJECT ){
          pIndex->pNext = pParse->pNewIndex;
          pParse->pNewIndex = pIndex;
          pIndex = 0;
        }
        goto exit_create_index;
      }
    }
  }

  if( !IN_RENAME_OBJECT ){

    /* Link the new Index structure to its table and to the other
    ** in-memory database structures. 
    */
    assert( pParse->nErr==0 );
    if( db->init.busy ){
      Index *p;
      assert( !IN_SPECIAL_PARSE );
      assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) );
      if( pTblName!=0 ){
        pIndex->tnum = db->init.newTnum;
        if( sqlite3IndexHasDuplicateRootPage(pIndex) ){
          sqlite3ErrorMsg(pParse, "invalid rootpage");
          pParse->rc = SQLITE_CORRUPT_BKPT;
          goto exit_create_index;
        }
      }
      p = sqlite3HashInsert(&pIndex->pSchema->idxHash, 
          pIndex->zName, pIndex);
      if( p ){
        assert( p==pIndex );  /* Malloc must have failed */
        sqlite3OomFault(db);
        goto exit_create_index;
      }
      db->mDbFlags |= DBFLAG_SchemaChange;
      if( pTblName!=0 ){
        pIndex->tnum = db->init.newTnum;
      }
    }

    /* If this is the initial CREATE INDEX statement (or CREATE TABLE if the
    ** index is an implied index for a UNIQUE or PRIMARY KEY constraint) then
    ** emit code to allocate the index rootpage on disk and make an entry for
    ** the index in the sqlite_master table and populate the index with
    ** content.  But, do not do this if we are simply reading the sqlite_master
    ** the index in the sqlite_schema table and populate the index with
    ** content.  But, do not do this if we are simply reading the sqlite_schema
    ** table to parse the schema, or if this index is the PRIMARY KEY index
    ** of a WITHOUT ROWID table.
    **
    ** If pTblName==0 it means this index is generated as an implied PRIMARY KEY
    ** or UNIQUE index in a CREATE TABLE statement.  Since the table
    ** has just been created, it contains no data and the index initialization
    ** step can be skipped.
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
3569
3570
3571
3572
3573
3574
3575
3576
3577


3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596





























3597
3598
3599
3600
3601
3602
3603
4405
4406
4407
4408
4409
4410
4411

4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430

4431
4432
4433







4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449

4450
4451
4452
4453

4454
4455
4456







4457




4458
4459








4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506







-
+





+












-
+


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









-
+



-
+


-
-
-
-
-
-
-

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











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








      /* Create the rootpage for the index using CreateIndex. But before
      ** doing so, code a Noop instruction and store its address in 
      ** Index.tnum. This is required in case this index is actually a 
      ** PRIMARY KEY and the table is actually a WITHOUT ROWID table. In 
      ** that case the convertToWithoutRowidTable() routine will replace
      ** the Noop with a Goto to jump over the VDBE code generated below. */
      pIndex->tnum = sqlite3VdbeAddOp0(v, OP_Noop);
      pIndex->tnum = (Pgno)sqlite3VdbeAddOp0(v, OP_Noop);
      sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, iMem, BTREE_BLOBKEY);

      /* Gather the complete text of the CREATE INDEX statement into
      ** the zStmt variable
      */
      assert( pName!=0 || pStart==0 );
      if( pStart ){
        int n = (int)(pParse->sLastToken.z - pName->z) + pParse->sLastToken.n;
        if( pName->z[n-1]==';' ) n--;
        /* A named index with an explicit CREATE INDEX statement */
        zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s",
            onError==OE_None ? "" : " UNIQUE", n, pName->z);
      }else{
        /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */
        /* zStmt = sqlite3MPrintf(""); */
        zStmt = 0;
      }

      /* Add an entry in sqlite_master for this index
      /* Add an entry in sqlite_schema for this index
      */
      sqlite3NestedParse(pParse, 
          "INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);",
          db->aDb[iDb].zDbSName, MASTER_NAME,
          pIndex->zName,
          pTab->zName,
          iMem,
          zStmt
          );
         "INSERT INTO %Q." LEGACY_SCHEMA_TABLE " VALUES('index',%Q,%Q,#%d,%Q);",
         db->aDb[iDb].zDbSName,
         pIndex->zName,
         pTab->zName,
         iMem,
         zStmt
      );
      sqlite3DbFree(db, zStmt);

      /* Fill the index with data and reparse the schema. Code an OP_Expire
      ** to invalidate all pre-compiled statements.
      */
      if( pTblName ){
        sqlite3RefillIndex(pParse, pIndex, iMem);
        sqlite3ChangeCookie(pParse, iDb);
        sqlite3VdbeAddParseSchemaOp(v, iDb,
            sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName));
            sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName), 0);
        sqlite3VdbeAddOp2(v, OP_Expire, 0, 1);
      }

      sqlite3VdbeJumpHere(v, pIndex->tnum);
      sqlite3VdbeJumpHere(v, (int)pIndex->tnum);
    }
  }

  /* When adding an index to the list of indices for a table, make
  ** sure all indices labeled OE_Replace come after all those labeled
  ** OE_Ignore.  This is necessary for the correct constraint check
  ** processing (in sqlite3GenerateConstraintChecks()) as part of
  ** UPDATE and INSERT statements.  
  */
  if( db->init.busy || pTblName==0 ){
    if( onError!=OE_Replace || pTab->pIndex==0
         || pTab->pIndex->onError==OE_Replace){
      pIndex->pNext = pTab->pIndex;
      pTab->pIndex = pIndex;
    pIndex->pNext = pTab->pIndex;
    pTab->pIndex = pIndex;
    }else{
      Index *pOther = pTab->pIndex;
      while( pOther->pNext && pOther->pNext->onError!=OE_Replace ){
        pOther = pOther->pNext;
      }
      pIndex->pNext = pOther->pNext;
      pOther->pNext = pIndex;
    }
    pIndex = 0;
  }
  else if( IN_RENAME_OBJECT ){
    assert( pParse->pNewIndex==0 );
    pParse->pNewIndex = pIndex;
    pIndex = 0;
  }

  /* Clean up before exiting */
exit_create_index:
  if( pIndex ) sqlite3FreeIndex(db, pIndex);
  if( pTab ){
    /* Ensure all REPLACE indexes on pTab are at the end of the pIndex list.
    ** The list was already ordered when this routine was entered, so at this
    ** point at most a single index (the newly added index) will be out of
    ** order.  So we have to reorder at most one index. */
    Index **ppFrom;
    Index *pThis;
    for(ppFrom=&pTab->pIndex; (pThis = *ppFrom)!=0; ppFrom=&pThis->pNext){
      Index *pNext;
      if( pThis->onError!=OE_Replace ) continue;
      while( (pNext = pThis->pNext)!=0 && pNext->onError!=OE_Replace ){
        *ppFrom = pNext;
        pThis->pNext = pNext->pNext;
        pNext->pNext = pThis;
        ppFrom = &pNext->pNext;
      }
      break;
    }
#ifdef SQLITE_DEBUG
    /* Verify that all REPLACE indexes really are now at the end
    ** of the index list.  In other words, no other index type ever
    ** comes after a REPLACE index on the list. */
    for(pThis = pTab->pIndex; pThis; pThis=pThis->pNext){
      assert( pThis->onError!=OE_Replace
           || pThis->pNext==0
           || pThis->pNext->onError==OE_Replace );
    }
#endif
  }
  sqlite3ExprDelete(db, pPIWhere);
  sqlite3ExprListDelete(db, pList);
  sqlite3SrcListDelete(db, pTblName);
  sqlite3DbFree(db, zName);
}

/*
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
4518
4519
4520
4521
4522
4523
4524


4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536




4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558







-
-
+
+

+








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







**           aiRowEst[N]>=1
**
** Apart from that, we have little to go on besides intuition as to
** how aiRowEst[] should be initialized.  The numbers generated here
** are based on typical values found in actual indices.
*/
void sqlite3DefaultRowEst(Index *pIdx){
  /*                10,  9,  8,  7,  6 */
  LogEst aVal[] = { 33, 32, 30, 28, 26 };
               /*                10,  9,  8,  7,  6 */
  static const LogEst aVal[] = { 33, 32, 30, 28, 26 };
  LogEst *a = pIdx->aiRowLogEst;
  LogEst x;
  int nCopy = MIN(ArraySize(aVal), pIdx->nKeyCol);
  int i;

  /* Indexes with default row estimates should not have stat1 data */
  assert( !pIdx->hasStat1 );

  /* Set the first entry (number of rows in the index) to the estimated 
  ** number of rows in the table, or half the number of rows in the table
  ** for a partial index.   But do not let the estimate drop below 10. */
  a[0] = pIdx->pTable->nRowLogEst;
  if( pIdx->pPartIdxWhere!=0 ) a[0] -= 10;  assert( 10==sqlite3LogEst(2) );
  if( a[0]<33 ) a[0] = 33;                  assert( 33==sqlite3LogEst(10) );
  ** for a partial index.
  **
  ** 2020-05-27:  If some of the stat data is coming from the sqlite_stat1
  ** table but other parts we are having to guess at, then do not let the
  ** estimated number of rows in the table be less than 1000 (LogEst 99).
  ** Failure to do this can cause the indexes for which we do not have
  ** stat1 data to be ignored by the query planner.
  */
  x = pIdx->pTable->nRowLogEst;
  assert( 99==sqlite3LogEst(1000) );
  if( x<99 ){
    pIdx->pTable->nRowLogEst = x = 99;
  }
  if( pIdx->pPartIdxWhere!=0 ){ x -= 10;  assert( 10==sqlite3LogEst(2) ); }
  a[0] = x;

  /* Estimate that a[1] is 10, a[2] is 9, a[3] is 8, a[4] is 7, a[5] is
  ** 6 and each subsequent value (if any) is 5.  */
  memcpy(&a[1], aVal, nCopy*sizeof(LogEst));
  for(i=nCopy+1; i<=pIdx->nKeyCol; i++){
    a[i] = 23;                    assert( 23==sqlite3LogEst(5) );
  }
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662

3663
3664
3665
3666
3667
3668
3669
3670

3671
3672

3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692

3693
3694
3695
3696
3697
3698
3699

3700
3701
3702
3703
3704
3705


3706
3707
3708
3709
3710
3711
3712
4567
4568
4569
4570
4571
4572
4573

4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584

4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607

4608
4609
4610
4611
4612
4613
4614

4615
4616
4617
4618
4619


4620
4621
4622
4623
4624
4625
4626
4627
4628







-



+







-
+


+



















-
+






-
+




-
-
+
+







*/
void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){
  Index *pIndex;
  Vdbe *v;
  sqlite3 *db = pParse->db;
  int iDb;

  assert( pParse->nErr==0 );   /* Never called with prior errors */
  if( db->mallocFailed ){
    goto exit_drop_index;
  }
  assert( pParse->nErr==0 );   /* Never called with prior non-OOM errors */
  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);
      sqlite3ForceNotReadOnly(pParse);
    }
    pParse->checkSchema = 1;
    goto exit_drop_index;
  }
  if( pIndex->idxType!=SQLITE_IDXTYPE_APPDEF ){
    sqlite3ErrorMsg(pParse, "index associated with UNIQUE "
      "or PRIMARY KEY constraint cannot be dropped", 0);
    goto exit_drop_index;
  }
  iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
#ifndef SQLITE_OMIT_AUTHORIZATION
  {
    int code = SQLITE_DROP_INDEX;
    Table *pTab = pIndex->pTable;
    const char *zDb = db->aDb[iDb].zDbSName;
    const char *zTab = SCHEMA_TABLE(iDb);
    if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){
      goto exit_drop_index;
    }
    if( !OMIT_TEMPDB && iDb ) code = SQLITE_DROP_TEMP_INDEX;
    if( !OMIT_TEMPDB && iDb==1 ) code = SQLITE_DROP_TEMP_INDEX;
    if( sqlite3AuthCheck(pParse, code, pIndex->zName, pTab->zName, zDb) ){
      goto exit_drop_index;
    }
  }
#endif

  /* Generate code to remove the index and from the master table */
  /* Generate code to remove the index and from the schema table */
  v = sqlite3GetVdbe(pParse);
  if( v ){
    sqlite3BeginWriteOperation(pParse, 1, iDb);
    sqlite3NestedParse(pParse,
       "DELETE FROM %Q.%s WHERE name=%Q AND type='index'",
       db->aDb[iDb].zDbSName, MASTER_NAME, pIndex->zName
       "DELETE FROM %Q." LEGACY_SCHEMA_TABLE " WHERE name=%Q AND type='index'",
       db->aDb[iDb].zDbSName, pIndex->zName
    );
    sqlite3ClearStatTables(pParse, iDb, "idx", pIndex->zName);
    sqlite3ChangeCookie(pParse, iDb);
    destroyRootPage(pParse, pIndex->tnum, iDb);
    sqlite3VdbeAddOp4(v, OP_DropIndex, iDb, 0, 0, pIndex->zName, 0);
  }

3735
3736
3737
3738
3739
3740
3741
3742

3743
3744

3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771

3772
3773
3774
3775
3776



3777
3778
3779
3780
3781
3782







3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794

3795

3796
3797
3798
3799
3800

3801
3802
3803
3804
3805
3806
3807
3808
3809

3810
3811
3812
3813
3814
3815












3816
3817
3818
3819
3820
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
3866
3867
3868
3869
4651
4652
4653
4654
4655
4656
4657

4658
4659

4660
4661
4662
4663
4664
4665
4666
4667
4668
4669

4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685

4686





4687
4688
4689






4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714


4715
4716
4717
4718
4719
4720
4721
4722
4723

4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758


4759
4760
4761
4762
4763

4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779


4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792

4793
4794
4795


4796
4797
4798
4799
4800
4801
4802
4803







-
+

-
+









-
















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












+

+



-
-
+








-
+






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
















-
-
+
+
+


-
+















-
-
+
+
+
+
+
+
+
+
+




-
+


-
-
+







  sqlite3 *db,      /* Connection to notify of malloc failures */
  void *pArray,     /* Array of objects.  Might be reallocated */
  int szEntry,      /* Size of each object in the array */
  int *pnEntry,     /* Number of objects currently in use */
  int *pIdx         /* Write the index of a new slot here */
){
  char *z;
  int n = *pnEntry;
  sqlite3_int64 n = *pIdx = *pnEntry;
  if( (n & (n-1))==0 ){
    int sz = (n==0) ? 1 : 2*n;
    sqlite3_int64 sz = (n==0) ? 1 : 2*n;
    void *pNew = sqlite3DbRealloc(db, pArray, sz*szEntry);
    if( pNew==0 ){
      *pIdx = -1;
      return pArray;
    }
    pArray = pNew;
  }
  z = (char*)pArray;
  memset(&z[n * szEntry], 0, szEntry);
  *pIdx = n;
  ++*pnEntry;
  return pArray;
}

/*
** Append a new element to the given IdList.  Create a new IdList if
** need be.
**
** A new IdList is returned, or NULL if malloc() fails.
*/
IdList *sqlite3IdListAppend(Parse *pParse, IdList *pList, Token *pToken){
  sqlite3 *db = pParse->db;
  int i;
  if( pList==0 ){
    pList = sqlite3DbMallocZero(db, sizeof(IdList) );
    if( pList==0 ) return 0;
  }
  }else{
  pList->a = sqlite3ArrayAllocate(
      db,
      pList->a,
      sizeof(pList->a[0]),
      &pList->nId,
    IdList *pNew;
    pNew = sqlite3DbRealloc(db, pList,
                 sizeof(IdList) + pList->nId*sizeof(pList->a));
      &i
  );
  if( i<0 ){
    sqlite3IdListDelete(db, pList);
    return 0;
  }
    if( pNew==0 ){
      sqlite3IdListDelete(db, pList);
      return 0;
    }
    pList = pNew;
  }
  i = pList->nId++;
  pList->a[i].zName = sqlite3NameFromToken(db, pToken);
  if( IN_RENAME_OBJECT && pList->a[i].zName ){
    sqlite3RenameTokenMap(pParse, (void*)pList->a[i].zName, pToken);
  }
  return pList;
}

/*
** Delete an IdList.
*/
void sqlite3IdListDelete(sqlite3 *db, IdList *pList){
  int i;
  assert( db!=0 );
  if( pList==0 ) return;
  assert( pList->eU4!=EU4_EXPR ); /* EU4_EXPR mode is not currently used */
  for(i=0; i<pList->nId; i++){
    sqlite3DbFree(db, pList->a[i].zName);
  }
  sqlite3DbFree(db, pList->a);
  sqlite3DbFreeNN(db, pList);
  sqlite3DbNNFreeNN(db, pList);
}

/*
** Return the index in pList of the identifier named zId.  Return -1
** if not found.
*/
int sqlite3IdListIndex(IdList *pList, const char *zName){
  int i;
  if( pList==0 ) return -1;
  assert( pList!=0 );
  for(i=0; i<pList->nId; i++){
    if( sqlite3StrICmp(pList->a[i].zName, zName)==0 ) return i;
  }
  return -1;
}

/*
** Maximum size of a SrcList object.
** The SrcList object is used to represent the FROM clause of a
** SELECT statement, and the query planner cannot deal with more
** than 64 tables in a join.  So any value larger than 64 here
** is sufficient for most uses.  Smaller values, like say 10, are
** appropriate for small and memory-limited applications.
*/
#ifndef SQLITE_MAX_SRCLIST
# define SQLITE_MAX_SRCLIST 200
#endif

/*
** Expand the space allocated for the given SrcList object by
** creating nExtra new slots beginning at iStart.  iStart is zero based.
** New slots are zeroed.
**
** For example, suppose a SrcList initially contains two entries: A,B.
** To append 3 new entries onto the end, do this:
**
**    sqlite3SrcListEnlarge(db, pSrclist, 3, 2);
**
** After the call above it would contain:  A, B, nil, nil, nil.
** If the iStart argument had been 1 instead of 2, then the result
** would have been:  A, nil, nil, nil, B.  To prepend the new slots,
** the iStart value would be 0.  The result then would
** be: nil, nil, nil, A, B.
**
** If a memory allocation fails the SrcList is unchanged.  The
** db->mallocFailed flag will be set to true.
** If a memory allocation fails or the SrcList becomes too large, leave
** the original SrcList unchanged, return NULL, and leave an error message
** in pParse.
*/
SrcList *sqlite3SrcListEnlarge(
  sqlite3 *db,       /* Database connection to notify of OOM errors */
  Parse *pParse,     /* Parsing context into which errors are reported */
  SrcList *pSrc,     /* The SrcList to be enlarged */
  int nExtra,        /* Number of new slots to add to pSrc->a[] */
  int iStart         /* Index in pSrc->a[] of first new slot */
){
  int i;

  /* Sanity checking on calling parameters */
  assert( iStart>=0 );
  assert( nExtra>=1 );
  assert( pSrc!=0 );
  assert( iStart<=pSrc->nSrc );

  /* Allocate additional space if needed */
  if( (u32)pSrc->nSrc+nExtra>pSrc->nAlloc ){
    SrcList *pNew;
    int nAlloc = pSrc->nSrc*2+nExtra;
    int nGot;
    sqlite3_int64 nAlloc = 2*(sqlite3_int64)pSrc->nSrc+nExtra;
    sqlite3 *db = pParse->db;

    if( pSrc->nSrc+nExtra>=SQLITE_MAX_SRCLIST ){
      sqlite3ErrorMsg(pParse, "too many FROM clause terms, max: %d",
                      SQLITE_MAX_SRCLIST);
      return 0;
    }
    if( nAlloc>SQLITE_MAX_SRCLIST ) nAlloc = SQLITE_MAX_SRCLIST;
    pNew = sqlite3DbRealloc(db, pSrc,
               sizeof(*pSrc) + (nAlloc-1)*sizeof(pSrc->a[0]) );
    if( pNew==0 ){
      assert( db->mallocFailed );
      return pSrc;
      return 0;
    }
    pSrc = pNew;
    nGot = (sqlite3DbMallocSize(db, pNew) - sizeof(*pSrc))/sizeof(pSrc->a[0])+1;
    pSrc->nAlloc = nGot;
    pSrc->nAlloc = nAlloc;
  }

  /* Move existing slots that come after the newly inserted slots
  ** out of the way */
  for(i=pSrc->nSrc-1; i>=iStart; i--){
    pSrc->a[i+nExtra] = pSrc->a[i];
  }
3880
3881
3882
3883
3884
3885
3886
3887


3888
3889
3890
3891
3892
3893
3894
4814
4815
4816
4817
4818
4819
4820

4821
4822
4823
4824
4825
4826
4827
4828
4829







-
+
+







}


/*
** Append a new table name to the given SrcList.  Create a new SrcList if
** need be.  A new entry is created in the SrcList even if pTable is NULL.
**
** A SrcList is returned, or NULL if there is an OOM error.  The returned
** A SrcList is returned, or NULL if there is an OOM error or if the
** SrcList grows to large.  The returned
** SrcList might be the same as the SrcList that was input or it might be
** a new one.  If an OOM error does occurs, then the prior value of pList
** that is input to this routine is automatically freed.
**
** If pDatabase is not null, it means that the table has an optional
** database name prefix.  Like this:  "database.table".  The pDatabase
** points to the table name and the pTable points to the database name.
3911
3912
3913
3914
3915
3916
3917
3918

3919
3920
3921
3922
3923


3924
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



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
4846
4847
4848
4849
4850
4851
4852

4853
4854
4855
4856
4857

4858
4859
4860

4861
4862
4863
4864

4865
4866
4867
4868
4869
4870
4871

4872




4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898



4899
4900
4901
4902

4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916

4917
4918
4919
4920



4921
4922
4923
4924
4925
4926





4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941







-
+




-
+
+

-
+
+
+

-
+






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




















-
-
-
+
+
+

-
+













-
+
+


-
-
-
+
+
+



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







**
**         sqlite3SrcListAppend(D,A,0,C);
**
** Both pTable and pDatabase are assumed to be quoted.  They are dequoted
** before being added to the SrcList.
*/
SrcList *sqlite3SrcListAppend(
  sqlite3 *db,        /* Connection to notify of malloc failures */
  Parse *pParse,      /* Parsing context, in which errors are reported */
  SrcList *pList,     /* Append to this SrcList. NULL creates a new SrcList */
  Token *pTable,      /* Table to append */
  Token *pDatabase    /* Database of the table */
){
  struct SrcList_item *pItem;
  SrcItem *pItem;
  sqlite3 *db;
  assert( pDatabase==0 || pTable!=0 );  /* Cannot have C without B */
  assert( db!=0 );
  assert( pParse!=0 );
  assert( pParse->db!=0 );
  db = pParse->db;
  if( pList==0 ){
    pList = sqlite3DbMallocRawNN(db, sizeof(SrcList) );
    pList = sqlite3DbMallocRawNN(pParse->db, sizeof(SrcList) );
    if( pList==0 ) return 0;
    pList->nAlloc = 1;
    pList->nSrc = 1;
    memset(&pList->a[0], 0, sizeof(pList->a[0]));
    pList->a[0].iCursor = -1;
  }else{
    pList = sqlite3SrcListEnlarge(db, pList, 1, pList->nSrc);
    SrcList *pNew = sqlite3SrcListEnlarge(pParse, pList, 1, pList->nSrc);
  }
  if( db->mallocFailed ){
    sqlite3SrcListDelete(db, pList);
    return 0;
    if( pNew==0 ){
      sqlite3SrcListDelete(db, pList);
      return 0;
    }else{
      pList = pNew;
    }
  }
  pItem = &pList->a[pList->nSrc-1];
  if( pDatabase && pDatabase->z==0 ){
    pDatabase = 0;
  }
  if( pDatabase ){
    pItem->zName = sqlite3NameFromToken(db, pDatabase);
    pItem->zDatabase = sqlite3NameFromToken(db, pTable);
  }else{
    pItem->zName = sqlite3NameFromToken(db, pTable);
    pItem->zDatabase = 0;
  }
  return pList;
}

/*
** Assign VdbeCursor index numbers to all tables in a SrcList
*/
void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){
  int i;
  struct SrcList_item *pItem;
  assert(pList || pParse->db->mallocFailed );
  if( pList ){
  SrcItem *pItem;
  assert( pList || pParse->db->mallocFailed );
  if( ALWAYS(pList) ){
    for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
      if( pItem->iCursor>=0 ) break;
      if( pItem->iCursor>=0 ) continue;
      pItem->iCursor = pParse->nTab++;
      if( pItem->pSelect ){
        sqlite3SrcListAssignCursors(pParse, pItem->pSelect->pSrc);
      }
    }
  }
}

/*
** Delete an entire SrcList including all its substructure.
*/
void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
  int i;
  struct SrcList_item *pItem;
  SrcItem *pItem;
  assert( db!=0 );
  if( pList==0 ) return;
  for(pItem=pList->a, i=0; i<pList->nSrc; i++, pItem++){
    sqlite3DbFree(db, pItem->zDatabase);
    sqlite3DbFree(db, pItem->zName);
    sqlite3DbFree(db, pItem->zAlias);
    if( pItem->zDatabase ) sqlite3DbNNFreeNN(db, pItem->zDatabase);
    if( pItem->zName ) sqlite3DbNNFreeNN(db, pItem->zName);
    if( pItem->zAlias ) sqlite3DbNNFreeNN(db, pItem->zAlias);
    if( pItem->fg.isIndexedBy ) sqlite3DbFree(db, pItem->u1.zIndexedBy);
    if( pItem->fg.isTabFunc ) sqlite3ExprListDelete(db, pItem->u1.pFuncArg);
    sqlite3DeleteTable(db, pItem->pTab);
    sqlite3SelectDelete(db, pItem->pSelect);
    sqlite3ExprDelete(db, pItem->pOn);
    sqlite3IdListDelete(db, pItem->pUsing);
  }
  sqlite3DbFreeNN(db, pList);
    if( pItem->pSelect ) sqlite3SelectDelete(db, pItem->pSelect);
    if( pItem->fg.isUsing ){
      sqlite3IdListDelete(db, pItem->u3.pUsing);
    }else if( pItem->u3.pOn ){
      sqlite3ExprDelete(db, pItem->u3.pOn);
    }
  }
  sqlite3DbNNFreeNN(db, pList);
}

/*
** This routine is called by the parser to add a new term to the
** end of a growing FROM clause.  The "p" parameter is the part of
** the FROM clause that has already been constructed.  "p" is NULL
** if this is the first term of the FROM clause.  pTable and pDatabase
4009
4010
4011
4012
4013
4014
4015
4016
4017

4018
4019

4020
4021

4022
4023

4024
4025
4026
4027

4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042

4043
4044
4045















4046
4047
4048

4049
4050

4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063

4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075

4076
4077





















4078
4079
4080
4081
4082
4083
4084
4085
4086

4087
4088
4089
4090
4091
4092
4093
4953
4954
4955
4956
4957
4958
4959


4960
4961

4962
4963

4964
4965

4966
4967
4968
4969

4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986



4987
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
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062

5063
5064
5065
5066
5067
5068
5069
5070







-
-
+

-
+

-
+

-
+



-
+















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


-
+

-
+
-











-
+












+


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








-
+







SrcList *sqlite3SrcListAppendFromTerm(
  Parse *pParse,          /* Parsing context */
  SrcList *p,             /* The left part of the FROM clause already seen */
  Token *pTable,          /* Name of the table to add to the FROM clause */
  Token *pDatabase,       /* Name of the database containing pTable */
  Token *pAlias,          /* The right-hand side of the AS subexpression */
  Select *pSubquery,      /* A subquery used in place of a table name */
  Expr *pOn,              /* The ON clause of a join */
  IdList *pUsing          /* The USING clause of a join */
  OnOrUsing *pOnUsing     /* Either the ON clause or the USING clause */
){
  struct SrcList_item *pItem;
  SrcItem *pItem;
  sqlite3 *db = pParse->db;
  if( !p && (pOn || pUsing) ){
  if( !p && pOnUsing!=0 && (pOnUsing->pOn || pOnUsing->pUsing) ){
    sqlite3ErrorMsg(pParse, "a JOIN clause is required before %s", 
      (pOn ? "ON" : "USING")
      (pOnUsing->pOn ? "ON" : "USING")
    );
    goto append_from_error;
  }
  p = sqlite3SrcListAppend(db, p, pTable, pDatabase);
  p = sqlite3SrcListAppend(pParse, p, pTable, pDatabase);
  if( p==0 ){
    goto append_from_error;
  }
  assert( p->nSrc>0 );
  pItem = &p->a[p->nSrc-1];
  assert( (pTable==0)==(pDatabase==0) );
  assert( pItem->zName==0 || pDatabase!=0 );
  if( IN_RENAME_OBJECT && pItem->zName ){
    Token *pToken = (ALWAYS(pDatabase) && pDatabase->z) ? pDatabase : pTable;
    sqlite3RenameTokenMap(pParse, pItem->zName, pToken);
  }
  assert( pAlias!=0 );
  if( pAlias->n ){
    pItem->zAlias = sqlite3NameFromToken(db, pAlias);
  }
  if( pSubquery ){
  pItem->pSelect = pSubquery;
  pItem->pOn = pOn;
  pItem->pUsing = pUsing;
    pItem->pSelect = pSubquery;
    if( pSubquery->selFlags & SF_NestedFrom ){
      pItem->fg.isNestedFrom = 1;
    }
  }
  assert( pOnUsing==0 || pOnUsing->pOn==0 || pOnUsing->pUsing==0 );
  assert( pItem->fg.isUsing==0 );
  if( pOnUsing==0 ){
    pItem->u3.pOn = 0;
  }else if( pOnUsing->pUsing ){
    pItem->fg.isUsing = 1;
    pItem->u3.pUsing = pOnUsing->pUsing;
  }else{
    pItem->u3.pOn = pOnUsing->pOn;
  }
  return p;

 append_from_error:
append_from_error:
  assert( p==0 );
  sqlite3ExprDelete(db, pOn);
  sqlite3ClearOnOrUsing(db, pOnUsing);
  sqlite3IdListDelete(db, pUsing);
  sqlite3SelectDelete(db, pSubquery);
  return 0;
}

/*
** Add an INDEXED BY or NOT INDEXED clause to the most recently added 
** element of the source-list passed as the second argument.
*/
void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){
  assert( pIndexedBy!=0 );
  if( p && pIndexedBy->n>0 ){
    struct SrcList_item *pItem;
    SrcItem *pItem;
    assert( p->nSrc>0 );
    pItem = &p->a[p->nSrc-1];
    assert( pItem->fg.notIndexed==0 );
    assert( pItem->fg.isIndexedBy==0 );
    assert( pItem->fg.isTabFunc==0 );
    if( pIndexedBy->n==1 && !pIndexedBy->z ){
      /* A "NOT INDEXED" clause was supplied. See parse.y 
      ** construct "indexed_opt" for details. */
      pItem->fg.notIndexed = 1;
    }else{
      pItem->u1.zIndexedBy = sqlite3NameFromToken(pParse->db, pIndexedBy);
      pItem->fg.isIndexedBy = 1;
      assert( pItem->fg.isCte==0 );  /* No collision on union u2 */
    }
  }
}

/*
** Append the contents of SrcList p2 to SrcList p1 and return the resulting
** SrcList. Or, if an error occurs, return NULL. In all cases, p1 and p2
** are deleted by this function.
*/ 
SrcList *sqlite3SrcListAppendList(Parse *pParse, SrcList *p1, SrcList *p2){
  assert( p1 && p1->nSrc==1 );
  if( p2 ){
    SrcList *pNew = sqlite3SrcListEnlarge(pParse, p1, p2->nSrc, 1);
    if( pNew==0 ){
      sqlite3SrcListDelete(pParse->db, p2);
    }else{
      p1 = pNew;
      memcpy(&p1->a[1], p2->a, p2->nSrc*sizeof(SrcItem));
      sqlite3DbFree(pParse->db, p2);
      p1->a[0].fg.jointype |= (JT_LTORJ & p1->a[1].fg.jointype);
    }
  }
  return p1;
}

/*
** Add the list of function arguments to the SrcList entry for a
** table-valued-function.
*/
void sqlite3SrcListFuncArgs(Parse *pParse, SrcList *p, ExprList *pList){
  if( p ){
    struct SrcList_item *pItem = &p->a[p->nSrc-1];
    SrcItem *pItem = &p->a[p->nSrc-1];
    assert( pItem->fg.notIndexed==0 );
    assert( pItem->fg.isIndexedBy==0 );
    assert( pItem->fg.isTabFunc==0 );
    pItem->u1.pFuncArg = pList;
    pItem->fg.isTabFunc = 1;
  }else{
    sqlite3ExprListDelete(pParse->db, pList);
4104
4105
4106
4107
4108
4109
4110







4111
4112
4113



4114
4115
4116
4117
4118

















4119
4120
4121
4122
4123
4124
4125
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095


5096
5097
5098





5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122







+
+
+
+
+
+
+

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







** Example: Suppose the join is like this:
**
**           A natural cross join B
**
** The operator is "natural cross join".  The A and B operands are stored
** in p->a[0] and p->a[1], respectively.  The parser initially stores the
** operator with A.  This routine shifts that operator over to B.
**
** Additional changes:
**
**   *   All tables to the left of the right-most RIGHT JOIN are tagged with
**       JT_LTORJ (mnemonic: Left Table Of Right Join) so that the
**       code generator can easily tell that the table is part of
**       the left operand of at least one RIGHT JOIN.
*/
void sqlite3SrcListShiftJoinType(SrcList *p){
  if( p ){
void sqlite3SrcListShiftJoinType(Parse *pParse, SrcList *p){
  (void)pParse;
  if( p && p->nSrc>1 ){
    int i;
    for(i=p->nSrc-1; i>0; i--){
      p->a[i].fg.jointype = p->a[i-1].fg.jointype;
    }
    p->a[0].fg.jointype = 0;
    int i = p->nSrc-1;
    u8 allFlags = 0;
    do{
      allFlags |= p->a[i].fg.jointype = p->a[i-1].fg.jointype;
    }while( (--i)>0 );
    p->a[0].fg.jointype = 0;

    /* All terms to the left of a RIGHT JOIN should be tagged with the
    ** JT_LTORJ flags */
    if( allFlags & JT_RIGHT ){
      for(i=p->nSrc-1; ALWAYS(i>0) && (p->a[i].fg.jointype&JT_RIGHT)==0; i--){}
      i--;
      assert( i>=0 );
      do{
        p->a[i].fg.jointype |= JT_LTORJ;
      }while( (--i)>=0 );
    }
  }
}

/*
** Generate VDBE code for a BEGIN statement.
*/
void sqlite3BeginTransaction(Parse *pParse, int type){
4133
4134
4135
4136
4137
4138
4139









4140

4141
4142
4143
4144
4145
4146
4147
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145

5146
5147
5148
5149
5150
5151
5152
5153







+
+
+
+
+
+
+
+
+
-
+







  if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ){
    return;
  }
  v = sqlite3GetVdbe(pParse);
  if( !v ) return;
  if( type==TK_IMMEDIATE || type==TK_EXCLUSIVE ){
    for(i=0; i<db->nDb; i++){
      int eTxnType;
      Btree *pBt = db->aDb[i].pBt;
      if( pBt && sqlite3BtreeIsReadonly(pBt) ){
        eTxnType = 0;  /* Read txn */
      }else if( type==TK_EXCLUSIVE ){
        eTxnType = 2;  /* Exclusive txn */
      }else{
        eTxnType = 1;  /* Write txn */
      }
      sqlite3VdbeAddOp2(v, OP_Transaction, i, (type==TK_EXCLUSIVE)+1);
      sqlite3VdbeAddOp2(v, OP_Transaction, i, eTxnType);
      sqlite3VdbeUsesBtree(v, i);
    }
  }
  sqlite3VdbeAddOp3(v, OP_AutoCommit, 0, 0, (type==TK_CONCURRENT));
}

/*
4208
4209
4210
4211
4212
4213
4214
4215

4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229

4230
4231
4232
4233
4234
4235




4236
4237
4238
4239
4240
4241
4242




4243
4244
4245
4246
4247
4248
4249
5214
5215
5216
5217
5218
5219
5220

5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234

5235






5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257







-
+













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







+
+
+
+







      sqlite3ErrorMsg(pParse, "unable to open a temporary database "
        "file for storing temporary tables");
      pParse->rc = rc;
      return 1;
    }
    db->aDb[1].pBt = pBt;
    assert( db->aDb[1].pSchema );
    if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1, 0) ){
    if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, 0, 0) ){
      sqlite3OomFault(db);
      return 1;
    }
  }
  return 0;
}

/*
** Record the fact that the schema cookie will need to be verified
** for database iDb.  The code to actually verify the schema cookie
** will occur at the end of the top-level VDBE and will be generated
** later, by sqlite3FinishCoding().
*/
void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
static void sqlite3CodeVerifySchemaAtToplevel(Parse *pToplevel, int iDb){
  Parse *pToplevel = sqlite3ParseToplevel(pParse);

  assert( iDb>=0 && iDb<pParse->db->nDb );
  assert( pParse->db->aDb[iDb].pBt!=0 || iDb==1 );
  assert( iDb<SQLITE_MAX_ATTACHED+2 );
  assert( sqlite3SchemaMutexHeld(pParse->db, iDb, 0) );
  assert( iDb>=0 && iDb<pToplevel->db->nDb );
  assert( pToplevel->db->aDb[iDb].pBt!=0 || iDb==1 );
  assert( iDb<SQLITE_MAX_DB );
  assert( sqlite3SchemaMutexHeld(pToplevel->db, iDb, 0) );
  if( DbMaskTest(pToplevel->cookieMask, iDb)==0 ){
    DbMaskSet(pToplevel->cookieMask, iDb);
    if( !OMIT_TEMPDB && iDb==1 ){
      sqlite3OpenTempDatabase(pToplevel);
    }
  }
}
void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
  sqlite3CodeVerifySchemaAtToplevel(sqlite3ParseToplevel(pParse), iDb);
}


/*
** If argument zDb is NULL, then call sqlite3CodeVerifySchema() for each 
** attached database. Otherwise, invoke it for the database named zDb only.
*/
void sqlite3CodeVerifyNamedSchema(Parse *pParse, const char *zDb){
  sqlite3 *db = pParse->db;
4267
4268
4269
4270
4271
4272
4273
4274

4275
4276
4277
4278
4279
4280
4281
5275
5276
5277
5278
5279
5280
5281

5282
5283
5284
5285
5286
5287
5288
5289







-
+







** the way through and which will need to undo some writes without having to
** rollback the whole transaction.  For operations where all constraints
** can be checked before any changes are made to the database, it is never
** necessary to undo a write and the checkpoint should not be set.
*/
void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){
  Parse *pToplevel = sqlite3ParseToplevel(pParse);
  sqlite3CodeVerifySchema(pParse, iDb);
  sqlite3CodeVerifySchemaAtToplevel(pToplevel, iDb);
  DbMaskSet(pToplevel->writeMask, iDb);
  pToplevel->isMultiWrite |= setStatement;
}

/*
** Indicate that the statement currently under construction might write
** more than one entry (example: deleting one row then inserting another,
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
4360
4361
5326
5327
5328
5329
5330
5331
5332
5333
5334


5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356

5357
5358
5359
5360
5361
5362
5363
5364

5365
5366
5367
5368
5369
5370
5371
5372







+
+
-
-
+
+




















-
+
+






-
+







  Parse *pParse,    /* Parsing context */
  int errCode,      /* extended error code */
  int onError,      /* Constraint type */
  char *p4,         /* Error message */
  i8 p4type,        /* P4_STATIC or P4_TRANSIENT */
  u8 p5Errmsg       /* P5_ErrMsg type */
){
  Vdbe *v;
  assert( pParse->pVdbe!=0 );
  Vdbe *v = sqlite3GetVdbe(pParse);
  assert( (errCode&0xff)==SQLITE_CONSTRAINT );
  v = sqlite3GetVdbe(pParse);
  assert( (errCode&0xff)==SQLITE_CONSTRAINT || pParse->nested );
  if( onError==OE_Abort ){
    sqlite3MayAbort(pParse);
  }
  sqlite3VdbeAddOp4(v, OP_Halt, errCode, onError, 0, p4, p4type);
  sqlite3VdbeChangeP5(v, p5Errmsg);
}

/*
** Code an OP_Halt due to UNIQUE or PRIMARY KEY constraint violation.
*/
void sqlite3UniqueConstraint(
  Parse *pParse,    /* Parsing context */
  int onError,      /* Constraint type */
  Index *pIdx       /* The index that triggers the constraint */
){
  char *zErr;
  int j;
  StrAccum errMsg;
  Table *pTab = pIdx->pTable;

  sqlite3StrAccumInit(&errMsg, pParse->db, 0, 0, 200);
  sqlite3StrAccumInit(&errMsg, pParse->db, 0, 0, 
                      pParse->db->aLimit[SQLITE_LIMIT_LENGTH]);
  if( pIdx->aColExpr ){
    sqlite3_str_appendf(&errMsg, "index '%q'", pIdx->zName);
  }else{
    for(j=0; j<pIdx->nKeyCol; j++){
      char *zCol;
      assert( pIdx->aiColumn[j]>=0 );
      zCol = pTab->aCol[pIdx->aiColumn[j]].zName;
      zCol = pTab->aCol[pIdx->aiColumn[j]].zCnName;
      if( j ) sqlite3_str_append(&errMsg, ", ", 2);
      sqlite3_str_appendall(&errMsg, pTab->zName);
      sqlite3_str_append(&errMsg, ".", 1);
      sqlite3_str_appendall(&errMsg, zCol);
    }
  }
  zErr = sqlite3StrAccumFinish(&errMsg);
4374
4375
4376
4377
4378
4379
4380
4381

4382
4383
4384
4385
4386
4387
4388
5385
5386
5387
5388
5389
5390
5391

5392
5393
5394
5395
5396
5397
5398
5399







-
+







  int onError,      /* Conflict resolution algorithm */
  Table *pTab       /* The table with the non-unique rowid */ 
){
  char *zMsg;
  int rc;
  if( pTab->iPKey>=0 ){
    zMsg = sqlite3MPrintf(pParse->db, "%s.%s", pTab->zName,
                          pTab->aCol[pTab->iPKey].zName);
                          pTab->aCol[pTab->iPKey].zCnName);
    rc = SQLITE_CONSTRAINT_PRIMARYKEY;
  }else{
    zMsg = sqlite3MPrintf(pParse->db, "%s.rowid", pTab->zName);
    rc = SQLITE_CONSTRAINT_ROWID;
  }
  sqlite3HaltConstraint(pParse, rc, onError, zMsg, P4_DYNAMIC,
                        P5_ConstraintUnique);
4409
4410
4411
4412
4413
4414
4415

4416

4417
4418
4419
4420
4421
4422






4423
4424
4425
4426
4427
4428
4429
5420
5421
5422
5423
5424
5425
5426
5427

5428
5429





5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442







+
-
+

-
-
-
-
-
+
+
+
+
+
+








/*
** Recompute all indices of pTab that use the collating sequence pColl.
** If pColl==0 then recompute all indices of pTab.
*/
#ifndef SQLITE_OMIT_REINDEX
static void reindexTable(Parse *pParse, Table *pTab, char const *zColl){
  if( !IsVirtual(pTab) ){
  Index *pIndex;              /* An index associated with pTab */
    Index *pIndex;              /* An index associated with pTab */

  for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){
    if( zColl==0 || collationMatch(zColl, pIndex) ){
      int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
      sqlite3BeginWriteOperation(pParse, 0, iDb);
      sqlite3RefillIndex(pParse, pIndex, -1);
    for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){
      if( zColl==0 || collationMatch(zColl, pIndex) ){
        int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
        sqlite3BeginWriteOperation(pParse, 0, iDb);
        sqlite3RefillIndex(pParse, pIndex, -1);
      }
    }
  }
}
#endif

/*
** Recompute all indices of all tables in all databases where the
4536
4537
4538
4539
4540
4541
4542
4543


4544
4545
4546
4547
4548
4549
4550
5549
5550
5551
5552
5553
5554
5555

5556
5557
5558
5559
5560
5561
5562
5563
5564







-
+
+







  }
  if( pKey ){
    assert( sqlite3KeyInfoIsWriteable(pKey) );
    for(i=0; i<nCol; i++){
      const char *zColl = pIdx->azColl[i];
      pKey->aColl[i] = zColl==sqlite3StrBINARY ? 0 :
                        sqlite3LocateCollSeq(pParse, zColl);
      pKey->aSortOrder[i] = pIdx->aSortOrder[i];
      pKey->aSortFlags[i] = pIdx->aSortOrder[i];
      assert( 0==(pKey->aSortFlags[i] & KEYINFO_ORDER_BIGNULL) );
    }
    if( pParse->nErr ){
      assert( pParse->rc==SQLITE_ERROR_MISSING_COLLSEQ );
      if( pIdx->bNoQuery==0 ){
        /* Deactivate the index because it contains an unknown collating
        ** sequence.  The only way to reactive the index is to reload the
        ** schema.  Adding the missing collating sequence later does not
4559
4560
4561
4562
4563
4564
4565
4566

















































4567
4568



4569
4570
4571
4572
4573

4574
4575
4576
4577
4578
4579




4580
4581
4582
4583

4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594

4595
4596
4597
4598
4599
4600
4601
4602
4603

4604
4605
4606
4607
4608
4609
4610
4611


4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624

4625
4626
4627
4628
4629
4630
4631
4632
5573
5574
5575
5576
5577
5578
5579

5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629

5630
5631
5632
5633
5634
5635
5636

5637


5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648

5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659

5660
5661
5662
5663
5664
5665
5666
5667


5668

5669
5670





5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684

5685



5686
5687
5688
5689
5690







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

-
+
+
+




-
+
-
-




+
+
+
+



-
+










-
+







-
-
+
-


-
-
-
-
-
+
+












-
+
-
-
-





      pKey = 0;
    }
  }
  return pKey;
}

#ifndef SQLITE_OMIT_CTE
/* 
/*
** Create a new CTE object
*/
Cte *sqlite3CteNew(
  Parse *pParse,          /* Parsing context */
  Token *pName,           /* Name of the common-table */
  ExprList *pArglist,     /* Optional column name list for the table */
  Select *pQuery,         /* Query used to initialize the table */
  u8 eM10d                /* The MATERIALIZED flag */
){
  Cte *pNew;
  sqlite3 *db = pParse->db;

  pNew = sqlite3DbMallocZero(db, sizeof(*pNew));
  assert( pNew!=0 || db->mallocFailed );

  if( db->mallocFailed ){
    sqlite3ExprListDelete(db, pArglist);
    sqlite3SelectDelete(db, pQuery);
  }else{
    pNew->pSelect = pQuery;
    pNew->pCols = pArglist;
    pNew->zName = sqlite3NameFromToken(pParse->db, pName);
    pNew->eM10d = eM10d;
  }
  return pNew;
}

/*
** Clear information from a Cte object, but do not deallocate storage
** for the object itself.
*/
static void cteClear(sqlite3 *db, Cte *pCte){
  assert( pCte!=0 );
  sqlite3ExprListDelete(db, pCte->pCols);
  sqlite3SelectDelete(db, pCte->pSelect);
  sqlite3DbFree(db, pCte->zName);
}

/*
** Free the contents of the CTE object passed as the second argument.
*/
void sqlite3CteDelete(sqlite3 *db, Cte *pCte){
  assert( pCte!=0 );
  cteClear(db, pCte);
  sqlite3DbFree(db, pCte);
}

/* 
** This routine is invoked once per CTE by the parser while parsing a 
** WITH clause. 
** WITH clause.  The CTE described by teh third argument is added to
** the WITH clause of the second argument.  If the second argument is
** NULL, then a new WITH argument is created.
*/
With *sqlite3WithAdd(
  Parse *pParse,          /* Parsing context */
  With *pWith,            /* Existing WITH clause, or NULL */
  Token *pName,           /* Name of the common-table */
  Cte *pCte               /* CTE to add to the WITH clause */
  ExprList *pArglist,     /* Optional column name list for the table */
  Select *pQuery          /* Query used to initialize the table */
){
  sqlite3 *db = pParse->db;
  With *pNew;
  char *zName;

  if( pCte==0 ){
    return pWith;
  }

  /* Check that the CTE name is unique within this WITH clause. If
  ** not, store an error in the Parse structure. */
  zName = sqlite3NameFromToken(pParse->db, pName);
  zName = pCte->zName;
  if( zName && pWith ){
    int i;
    for(i=0; i<pWith->nCte; i++){
      if( sqlite3StrICmp(zName, pWith->a[i].zName)==0 ){
        sqlite3ErrorMsg(pParse, "duplicate WITH table name: %s", zName);
      }
    }
  }

  if( pWith ){
    int nByte = sizeof(*pWith) + (sizeof(pWith->a[1]) * pWith->nCte);
    sqlite3_int64 nByte = sizeof(*pWith) + (sizeof(pWith->a[1]) * pWith->nCte);
    pNew = sqlite3DbRealloc(db, pWith, nByte);
  }else{
    pNew = sqlite3DbMallocZero(db, sizeof(*pWith));
  }
  assert( (pNew!=0 && zName!=0) || db->mallocFailed );

  if( db->mallocFailed ){
    sqlite3ExprListDelete(db, pArglist);
    sqlite3SelectDelete(db, pQuery);
    sqlite3CteDelete(db, pCte);
    sqlite3DbFree(db, zName);
    pNew = pWith;
  }else{
    pNew->a[pNew->nCte].pSelect = pQuery;
    pNew->a[pNew->nCte].pCols = pArglist;
    pNew->a[pNew->nCte].zName = zName;
    pNew->a[pNew->nCte].zCteErr = 0;
    pNew->nCte++;
    pNew->a[pNew->nCte++] = *pCte;
    sqlite3DbFree(db, pCte);
  }

  return pNew;
}

/*
** Free the contents of the With object passed as the second argument.
*/
void sqlite3WithDelete(sqlite3 *db, With *pWith){
  if( pWith ){
    int i;
    for(i=0; i<pWith->nCte; i++){
      struct Cte *pCte = &pWith->a[i];
      cteClear(db, &pWith->a[i]);
      sqlite3ExprListDelete(db, pCte->pCols);
      sqlite3SelectDelete(db, pCte->pSelect);
      sqlite3DbFree(db, pCte->zName);
    }
    sqlite3DbFree(db, pWith);
  }
}
#endif /* !defined(SQLITE_OMIT_CTE) */

Changes to src/callback.c.

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
61
62
63
64
65
66
67













































68
69
70
71
72
73
74







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







      pColl->xDel = 0;         /* Do not copy the destructor */
      return SQLITE_OK;
    }
  }
  return SQLITE_ERROR;
}

/*
** This function is responsible for invoking the collation factory callback
** or substituting a collation sequence of a different encoding when the
** requested collation sequence is not available in the desired encoding.
** 
** If it is not NULL, then pColl must point to the database native encoding 
** collation sequence with name zName, length nName.
**
** The return value is either the collation sequence to be used in database
** db for collation type name zName, length nName, or NULL, if no collation
** sequence can be found.  If no collation is found, leave an error message.
**
** See also: sqlite3LocateCollSeq(), sqlite3FindCollSeq()
*/
CollSeq *sqlite3GetCollSeq(
  Parse *pParse,        /* Parsing context */
  u8 enc,               /* The desired encoding for the collating sequence */
  CollSeq *pColl,       /* Collating sequence with native encoding, or NULL */
  const char *zName     /* Collating sequence name */
){
  CollSeq *p;
  sqlite3 *db = pParse->db;

  p = pColl;
  if( !p ){
    p = sqlite3FindCollSeq(db, enc, zName, 0);
  }
  if( !p || !p->xCmp ){
    /* No collation sequence of this type for this encoding is registered.
    ** Call the collation factory to see if it can supply us with one.
    */
    callCollNeeded(db, enc, zName);
    p = sqlite3FindCollSeq(db, enc, zName, 0);
  }
  if( p && !p->xCmp && synthCollSeq(db, p) ){
    p = 0;
  }
  assert( !p || p->xCmp );
  if( p==0 ){
    sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
    pParse->rc = SQLITE_ERROR_MISSING_COLLSEQ;
  }
  return p;
}

/*
** This routine is called on a collation sequence before it is used to
** check that it is defined. An undefined collation sequence exists when
** a database is loaded that contains references to collation sequences
** that have not been defined by sqlite3_create_collation() etc.
**
** If required, this routine calls the 'collation needed' callback to
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
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







-
-
-
-
+
+
+
+


+
+


+



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







** this routine.  sqlite3LocateCollSeq() invokes the collation factory
** if necessary and generates an error message if the collating sequence
** cannot be found.
**
** See also: sqlite3LocateCollSeq(), sqlite3GetCollSeq()
*/
CollSeq *sqlite3FindCollSeq(
  sqlite3 *db,
  u8 enc,
  const char *zName,
  int create
  sqlite3 *db,          /* Database connection to search */
  u8 enc,               /* Desired text encoding */
  const char *zName,    /* Name of the collating sequence.  Might be NULL */
  int create            /* True to create CollSeq if doesn't already exist */
){
  CollSeq *pColl;
  assert( SQLITE_UTF8==1 && SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
  assert( enc>=SQLITE_UTF8 && enc<=SQLITE_UTF16BE );
  if( zName ){
    pColl = findCollSeqEntry(db, zName, create);
    if( pColl ) pColl += enc-1;
  }else{
    pColl = db->pDfltColl;
  }
  return pColl;
}
  assert( SQLITE_UTF8==1 && SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
  assert( enc>=SQLITE_UTF8 && enc<=SQLITE_UTF16BE );
  if( pColl ) pColl += enc-1;

/*
** Change the text encoding for a database connection. This means that
** the pDfltColl must change as well.
*/
void sqlite3SetTextEncoding(sqlite3 *db, u8 enc){
  assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
  db->enc = enc;
  /* EVIDENCE-OF: R-08308-17224 The default collating function for all
  ** strings is BINARY. 
  */
  db->pDfltColl = sqlite3FindCollSeq(db, enc, sqlite3StrBINARY, 0);
}

/*
** This function is responsible for invoking the collation factory callback
** or substituting a collation sequence of a different encoding when the
** requested collation sequence is not available in the desired encoding.
** 
** If it is not NULL, then pColl must point to the database native encoding 
** collation sequence with name zName, length nName.
**
** The return value is either the collation sequence to be used in database
** db for collation type name zName, length nName, or NULL, if no collation
** sequence can be found.  If no collation is found, leave an error message.
**
** See also: sqlite3LocateCollSeq(), sqlite3FindCollSeq()
*/
CollSeq *sqlite3GetCollSeq(
  Parse *pParse,        /* Parsing context */
  u8 enc,               /* The desired encoding for the collating sequence */
  CollSeq *pColl,       /* Collating sequence with native encoding, or NULL */
  const char *zName     /* Collating sequence name */
){
  CollSeq *p;
  sqlite3 *db = pParse->db;

  p = pColl;
  if( !p ){
    p = sqlite3FindCollSeq(db, enc, zName, 0);
  }
  if( !p || !p->xCmp ){
    /* No collation sequence of this type for this encoding is registered.
    ** Call the collation factory to see if it can supply us with one.
    */
    callCollNeeded(db, enc, zName);
    p = sqlite3FindCollSeq(db, enc, zName, 0);
  }
  if( p && !p->xCmp && synthCollSeq(db, p) ){
    p = 0;
  }
  assert( !p || p->xCmp );
  if( p==0 ){
    sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
    pParse->rc = SQLITE_ERROR_MISSING_COLLSEQ;
  }
  return p;
}

/*
** This function returns the collation sequence for database native text
** encoding identified by the string zName.
**
** If the requested collation sequence is not available, or not available
** in the database native encoding, the collation factory is invoked to
** request it. If the collation factory does not supply such a sequence,
** and the sequence is available in another text encoding, then that is
** returned instead.
**
** If no versions of the requested collations sequence are available, or
** another error occurs, NULL is returned and an error message written into
** pParse.
**
** This routine is a wrapper around sqlite3FindCollSeq().  This routine
** invokes the collation factory if the named collation cannot be found
** and generates an error message.
**
** See also: sqlite3FindCollSeq(), sqlite3GetCollSeq()
*/
CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName){
  sqlite3 *db = pParse->db;
  u8 enc = ENC(db);
  u8 initbusy = db->init.busy;
  CollSeq *pColl;

  pColl = sqlite3FindCollSeq(db, enc, zName, initbusy);
  if( !initbusy && (!pColl || !pColl->xCmp) ){
    pColl = sqlite3GetCollSeq(pParse, enc, pColl, zName);
  }

  return pColl;
}

/* During the search for the best function definition, this procedure
** is called to test how well the function passed as the first argument
** matches the request for a function with nArg arguments in a system
** that uses encoding enc. The value returned indicates how well the
250
251
252
253
254
255
256

257

258
259
260




261
262
263
264
265
266
267
268
269
297
298
299
300
301
302
303
304
305
306



307
308
309
310


311
312
313
314
315
316
317







+

+
-
-
-
+
+
+
+
-
-







#define FUNC_PERFECT_MATCH 6  /* The score for a perfect match */
static int matchQuality(
  FuncDef *p,     /* The function we are evaluating for match quality */
  int nArg,       /* Desired number of arguments.  (-1)==any */
  u8 enc          /* Desired text encoding */
){
  int match;
  assert( p->nArg>=-1 );

  /* Wrong number of arguments means "no match" */
  /* nArg of -2 is a special case */
  if( nArg==(-2) ) return (p->xSFunc==0) ? 0 : FUNC_PERFECT_MATCH;

  if( p->nArg!=nArg ){
    if( nArg==(-2) ) return (p->xSFunc==0) ? 0 : FUNC_PERFECT_MATCH;
    if( p->nArg>=0 ) return 0;
  }
  /* Wrong number of arguments means "no match" */
  if( p->nArg!=nArg && p->nArg>=0 ) return 0;

  /* Give a better score to a function with a specific number of arguments
  ** than to function that accepts any number of arguments. */
  if( p->nArg==nArg ){
    match = 4;
  }else{
    match = 1;
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
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







+




















-
+







*/
FuncDef *sqlite3FunctionSearch(
  int h,               /* Hash of the name */
  const char *zFunc    /* Name of function */
){
  FuncDef *p;
  for(p=sqlite3BuiltinFunctions.a[h]; p; p=p->u.pHash){
    assert( p->funcFlags & SQLITE_FUNC_BUILTIN );
    if( sqlite3StrICmp(p->zName, zFunc)==0 ){
      return p;
    }
  }
  return 0;
}

/*
** Insert a new FuncDef into a FuncDefHash hash table.
*/
void sqlite3InsertBuiltinFuncs(
  FuncDef *aDef,      /* List of global functions to be inserted */
  int nDef            /* Length of the apDef[] list */
){
  int i;
  for(i=0; i<nDef; i++){
    FuncDef *pOther;
    const char *zName = aDef[i].zName;
    int nName = sqlite3Strlen30(zName);
    int h = SQLITE_FUNC_HASH(zName[0], nName);
    assert( zName[0]>='a' && zName[0]<='z' );
    assert( aDef[i].funcFlags & SQLITE_FUNC_BUILTIN );
    pOther = sqlite3FunctionSearch(h, zName);
    if( pOther ){
      assert( pOther!=&aDef[i] && pOther->pNext!=&aDef[i] );
      aDef[i].pNext = pOther->pNext;
      pOther->pNext = &aDef[i];
    }else{
      aDef[i].pNext = 0;
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
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







+

+





-
+





-
+







** The Schema.cache_size variable is not cleared.
*/
void sqlite3SchemaClear(void *p){
  Hash temp1;
  Hash temp2;
  HashElem *pElem;
  Schema *pSchema = (Schema *)p;
  sqlite3 xdb;

  memset(&xdb, 0, sizeof(xdb));
  temp1 = pSchema->tblHash;
  temp2 = pSchema->trigHash;
  sqlite3HashInit(&pSchema->trigHash);
  sqlite3HashClear(&pSchema->idxHash);
  for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
    sqlite3DeleteTrigger(0, (Trigger*)sqliteHashData(pElem));
    sqlite3DeleteTrigger(&xdb, (Trigger*)sqliteHashData(pElem));
  }
  sqlite3HashClear(&temp2);
  sqlite3HashInit(&pSchema->tblHash);
  for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){
    Table *pTab = sqliteHashData(pElem);
    sqlite3DeleteTable(0, pTab);
    sqlite3DeleteTable(&xdb, pTab);
  }
  sqlite3HashClear(&temp1);
  sqlite3HashClear(&pSchema->fkeyHash);
  pSchema->pSeqTab = 0;
  if( pSchema->schemaFlags & DB_SchemaLoaded ){
    pSchema->iGeneration++;
  }

Changes to src/ctime.c.









1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

18
19
20
21
22
23
24

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

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

53
54
55

56
57
58

59
60

61
62



63
64

65
66



67
68
69
70

71
72
73

74
75
76

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

89
90
91

92
93
94

95
96
97

98
99
100
101
102
103

104
105
106
107
108
109
110
111
112

113
114
115
116
117
118
119
120
121
122
123

124
125



126
127
128
129
130
131
132
133
134
135
136
137
138
139

140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160

161
162
163

164
165
166

167
168
169

170
171
172

173
174
175

176
177
178

179
180
181

182
183



184
185
186
187

188
189
190

191
192
193

194
195



196

197
198
199

200
201
202

203
204
205

206
207
208

209
210



211

212
213
214

215
216
217
218


219
220
221
222
223

224
225
226

227
228
229

230
231
232

233
234
235

236
237
238

239
240
241

242
243
244

245
246
247

248
249
250
251
252
253

254
255
256
257
258



259

260
261
262

263
264
265

266
267
268

269
270
271

272
273
274

275
276



277

278
279
280

281
282
283

284
285
286

287
288
289

290
291
292
293
294
295

296
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23


24
25
26
27
28
29
30

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56




57
58
59

60
61
62

63
64
65
66


67
68
69
70

71
72
73
74
75
76
77
78
79

80
81
82

83
84
85

86
87
88
89
90
91
92
93
94
95
96
97

98
99
100

101
102
103

104
105
106

107
108
109
110
111
112

113
114
115
116
117
118
119
120
121

122
123
124
125
126
127
128
129
130
131
132
133
134


135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150

151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171

172
173
174

175
176
177

178
179
180

181
182
183

184
185
186

187
188
189

190
191
192

193
194
195
196
197
198
199
200
201

202
203
204

205
206
207

208
209
210
211
212
213

214
215
216

217
218
219

220
221
222

223
224
225

226
227
228
229
230
231

232
233
234

235
236
237


238
239
240




241
242
243

244
245
246

247
248
249

250
251
252

253
254
255

256
257
258

259
260
261

262
263
264

265
266
267




268
269
270
271
272
273
274
275
276

277
278
279

280
281
282

283
284
285

286
287
288

289
290
291

292
293
294
295
296
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
+
+
+
+
+
+
+
+















-
-
+






-
+













+











-
-
-
-
+


-
+


-
+


+
-
-
+
+
+

-
+


+
+
+



-
+


-
+


-
+











-
+


-
+


-
+


-
+





-
+








-
+











+
-
-
+
+
+













-
+




















-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


+
+
+



-
+


-
+


-
+


+
+
+
-
+


-
+


-
+


-
+


-
+


+
+
+
-
+


-
+


-
-
+
+

-
-
-
-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
-
-
-
+





+
+
+
-
+


-
+


-
+


-
+


-
+


-
+


+
+
+
-
+


-
+


-
+


-
+


-
+


-
-
-
-
+


-
+


-
+


-
+


-
+

-
-

-
+


-
+


+
+
+
-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+











-
+


-
+


-
-
-



+
-
-
+
+
+

-
+


-
+


-
+


-
+





-
+


-
+


-
+







/* DO NOT EDIT!
** This file is automatically generated by the script in the canonical
** SQLite source tree at tool/mkctimec.tcl.
**
** To modify this header, edit any of the various lists in that script
** which specify categories of generated conditionals in this file.
*/

/*
** 2010 February 23
**
** 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 routines used to report what compile-time options
** SQLite was built with.
*/

#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS /* IMP: R-16824-07538 */

/*
** Include the configuration header output by 'configure' if we're using the
** autoconf-based build
*/
#if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H)
#include "config.h"
#include "sqlite_cfg.h"
#define SQLITECONFIG_H 1
#endif

/* These macros are provided to "stringify" the value of the define
** for those options in which the value is meaningful. */
#define CTIMEOPT_VAL_(opt) #opt
#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)

/* Like CTIMEOPT_VAL, but especially for SQLITE_DEFAULT_LOOKASIDE. This
** option requires a separate macro because legal values contain a single
** comma. e.g. (-DSQLITE_DEFAULT_LOOKASIDE="100,100") */
#define CTIMEOPT_VAL2_(opt1,opt2) #opt1 "," #opt2
#define CTIMEOPT_VAL2(opt) CTIMEOPT_VAL2_(opt)
#include "sqliteInt.h"

/*
** An array of names of all compile-time options.  This array should 
** be sorted A-Z.
**
** This array looks large, but in a typical installation actually uses
** only a handful of compile-time options, so most times this array is usually
** rather short and uses little memory space.
*/
static const char * const sqlite3azCompileOpt[] = {

/* 
** BEGIN CODE GENERATED BY tool/mkctime.tcl 
*/
#if SQLITE_32BIT_ROWID
#ifdef SQLITE_32BIT_ROWID
  "32BIT_ROWID",
#endif
#if SQLITE_4_BYTE_ALIGNED_MALLOC
#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
  "4_BYTE_ALIGNED_MALLOC",
#endif
#if SQLITE_64BIT_STATS
#ifdef SQLITE_64BIT_STATS
  "64BIT_STATS",
#endif
#ifdef SQLITE_ALLOW_COVERING_INDEX_SCAN
#if SQLITE_ALLOW_COVERING_INDEX_SCAN
  "ALLOW_COVERING_INDEX_SCAN",
# if SQLITE_ALLOW_COVERING_INDEX_SCAN != 1
  "ALLOW_COVERING_INDEX_SCAN=" CTIMEOPT_VAL(SQLITE_ALLOW_COVERING_INDEX_SCAN),
# endif
#endif
#if SQLITE_ALLOW_URI_AUTHORITY
#ifdef SQLITE_ALLOW_URI_AUTHORITY
  "ALLOW_URI_AUTHORITY",
#endif
#ifdef SQLITE_ATOMIC_INTRINSICS
  "ATOMIC_INTRINSICS=" CTIMEOPT_VAL(SQLITE_ATOMIC_INTRINSICS),
#endif
#ifdef SQLITE_BITMASK_TYPE
  "BITMASK_TYPE=" CTIMEOPT_VAL(SQLITE_BITMASK_TYPE),
#endif
#if SQLITE_BUG_COMPATIBLE_20160819
#ifdef SQLITE_BUG_COMPATIBLE_20160819
  "BUG_COMPATIBLE_20160819",
#endif
#if SQLITE_CASE_SENSITIVE_LIKE
#ifdef SQLITE_CASE_SENSITIVE_LIKE
  "CASE_SENSITIVE_LIKE",
#endif
#if SQLITE_CHECK_PAGES
#ifdef SQLITE_CHECK_PAGES
  "CHECK_PAGES",
#endif
#if defined(__clang__) && defined(__clang_major__)
  "COMPILER=clang-" CTIMEOPT_VAL(__clang_major__) "."
                    CTIMEOPT_VAL(__clang_minor__) "."
                    CTIMEOPT_VAL(__clang_patchlevel__),
#elif defined(_MSC_VER)
  "COMPILER=msvc-" CTIMEOPT_VAL(_MSC_VER),
#elif defined(__GNUC__) && defined(__VERSION__)
  "COMPILER=gcc-" __VERSION__,
#endif
#if SQLITE_COVERAGE_TEST
#ifdef SQLITE_COVERAGE_TEST
  "COVERAGE_TEST",
#endif
#if SQLITE_DEBUG
#ifdef SQLITE_DEBUG
  "DEBUG",
#endif
#if SQLITE_DEFAULT_AUTOMATIC_INDEX
#ifdef SQLITE_DEFAULT_AUTOMATIC_INDEX
  "DEFAULT_AUTOMATIC_INDEX",
#endif
#if SQLITE_DEFAULT_AUTOVACUUM
#ifdef SQLITE_DEFAULT_AUTOVACUUM
  "DEFAULT_AUTOVACUUM",
#endif
#ifdef SQLITE_DEFAULT_CACHE_SIZE
  "DEFAULT_CACHE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_CACHE_SIZE),
#endif
#if SQLITE_DEFAULT_CKPTFULLFSYNC
#ifdef SQLITE_DEFAULT_CKPTFULLFSYNC
  "DEFAULT_CKPTFULLFSYNC",
#endif
#ifdef SQLITE_DEFAULT_FILE_FORMAT
  "DEFAULT_FILE_FORMAT=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_FORMAT),
#endif
#ifdef SQLITE_DEFAULT_FILE_PERMISSIONS
  "DEFAULT_FILE_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_PERMISSIONS),
#endif
#if SQLITE_DEFAULT_FOREIGN_KEYS
#ifdef SQLITE_DEFAULT_FOREIGN_KEYS
  "DEFAULT_FOREIGN_KEYS",
#endif
#ifdef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT
  "DEFAULT_JOURNAL_SIZE_LIMIT=" CTIMEOPT_VAL(SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT),
#endif
#ifdef SQLITE_DEFAULT_LOCKING_MODE
  "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
#endif
#ifdef SQLITE_DEFAULT_LOOKASIDE
  "DEFAULT_LOOKASIDE=" CTIMEOPT_VAL2(SQLITE_DEFAULT_LOOKASIDE),
#endif
#ifdef SQLITE_DEFAULT_MEMSTATUS
#if SQLITE_DEFAULT_MEMSTATUS
  "DEFAULT_MEMSTATUS",
# if SQLITE_DEFAULT_MEMSTATUS != 1
  "DEFAULT_MEMSTATUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_MEMSTATUS),
# endif
#endif
#ifdef SQLITE_DEFAULT_MMAP_SIZE
  "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE),
#endif
#ifdef SQLITE_DEFAULT_PAGE_SIZE
  "DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_PAGE_SIZE),
#endif
#ifdef SQLITE_DEFAULT_PCACHE_INITSZ
  "DEFAULT_PCACHE_INITSZ=" CTIMEOPT_VAL(SQLITE_DEFAULT_PCACHE_INITSZ),
#endif
#ifdef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
  "DEFAULT_PROXYDIR_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_PROXYDIR_PERMISSIONS),
#endif
#if SQLITE_DEFAULT_RECURSIVE_TRIGGERS
#ifdef SQLITE_DEFAULT_RECURSIVE_TRIGGERS
  "DEFAULT_RECURSIVE_TRIGGERS",
#endif
#ifdef SQLITE_DEFAULT_ROWEST
  "DEFAULT_ROWEST=" CTIMEOPT_VAL(SQLITE_DEFAULT_ROWEST),
#endif
#ifdef SQLITE_DEFAULT_SECTOR_SIZE
  "DEFAULT_SECTOR_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_SECTOR_SIZE),
#endif
#ifdef SQLITE_DEFAULT_SYNCHRONOUS
  "DEFAULT_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_SYNCHRONOUS),
#endif
#ifdef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT
  "DEFAULT_WAL_AUTOCHECKPOINT=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_AUTOCHECKPOINT),
#endif
#ifdef SQLITE_DEFAULT_WAL_SYNCHRONOUS
  "DEFAULT_WAL_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_SYNCHRONOUS),
#endif
#ifdef SQLITE_DEFAULT_WORKER_THREADS
  "DEFAULT_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WORKER_THREADS),
#endif
#if SQLITE_DIRECT_OVERFLOW_READ
#ifdef SQLITE_DIRECT_OVERFLOW_READ
  "DIRECT_OVERFLOW_READ",
#endif
#if SQLITE_DISABLE_DIRSYNC
#ifdef SQLITE_DISABLE_DIRSYNC
  "DISABLE_DIRSYNC",
#endif
#if SQLITE_DISABLE_FTS3_UNICODE
#ifdef SQLITE_DISABLE_FTS3_UNICODE
  "DISABLE_FTS3_UNICODE",
#endif
#if SQLITE_DISABLE_FTS4_DEFERRED
#ifdef SQLITE_DISABLE_FTS4_DEFERRED
  "DISABLE_FTS4_DEFERRED",
#endif
#if SQLITE_DISABLE_INTRINSIC
#ifdef SQLITE_DISABLE_INTRINSIC
  "DISABLE_INTRINSIC",
#endif
#if SQLITE_DISABLE_LFS
#ifdef SQLITE_DISABLE_LFS
  "DISABLE_LFS",
#endif
#if SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
#ifdef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
  "DISABLE_PAGECACHE_OVERFLOW_STATS",
#endif
#if SQLITE_DISABLE_SKIPAHEAD_DISTINCT
#ifdef SQLITE_DISABLE_SKIPAHEAD_DISTINCT
  "DISABLE_SKIPAHEAD_DISTINCT",
#endif
#ifdef SQLITE_DQS
  "DQS=" CTIMEOPT_VAL(SQLITE_DQS),
#endif
#ifdef SQLITE_ENABLE_8_3_NAMES
  "ENABLE_8_3_NAMES=" CTIMEOPT_VAL(SQLITE_ENABLE_8_3_NAMES),
#endif
#if SQLITE_ENABLE_API_ARMOR
#ifdef SQLITE_ENABLE_API_ARMOR
  "ENABLE_API_ARMOR",
#endif
#if SQLITE_ENABLE_ATOMIC_WRITE
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
  "ENABLE_ATOMIC_WRITE",
#endif
#if SQLITE_ENABLE_BATCH_ATOMIC_WRITE
#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
  "ENABLE_BATCH_ATOMIC_WRITE",
#endif
#ifdef SQLITE_ENABLE_BYTECODE_VTAB
  "ENABLE_BYTECODE_VTAB",
#endif
#if SQLITE_ENABLE_CEROD
#ifdef SQLITE_ENABLE_CEROD
  "ENABLE_CEROD=" CTIMEOPT_VAL(SQLITE_ENABLE_CEROD),
#endif
#if SQLITE_ENABLE_COLUMN_METADATA
#ifdef SQLITE_ENABLE_COLUMN_METADATA
  "ENABLE_COLUMN_METADATA",
#endif
#if SQLITE_ENABLE_COLUMN_USED_MASK
#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
  "ENABLE_COLUMN_USED_MASK",
#endif
#if SQLITE_ENABLE_COSTMULT
#ifdef SQLITE_ENABLE_COSTMULT
  "ENABLE_COSTMULT",
#endif
#if SQLITE_ENABLE_CURSOR_HINTS
#ifdef SQLITE_ENABLE_CURSOR_HINTS
  "ENABLE_CURSOR_HINTS",
#endif
#ifdef SQLITE_ENABLE_DBPAGE_VTAB
  "ENABLE_DBPAGE_VTAB",
#endif
#if SQLITE_ENABLE_DBSTAT_VTAB
#ifdef SQLITE_ENABLE_DBSTAT_VTAB
  "ENABLE_DBSTAT_VTAB",
#endif
#if SQLITE_ENABLE_EXPENSIVE_ASSERT
#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
  "ENABLE_EXPENSIVE_ASSERT",
#endif
#if SQLITE_ENABLE_FTS1
  "ENABLE_FTS1",
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
  "ENABLE_EXPLAIN_COMMENTS",
#endif
#if SQLITE_ENABLE_FTS2
  "ENABLE_FTS2",
#endif
#if SQLITE_ENABLE_FTS3
#ifdef SQLITE_ENABLE_FTS3
  "ENABLE_FTS3",
#endif
#if SQLITE_ENABLE_FTS3_PARENTHESIS
#ifdef SQLITE_ENABLE_FTS3_PARENTHESIS
  "ENABLE_FTS3_PARENTHESIS",
#endif
#if SQLITE_ENABLE_FTS3_TOKENIZER
#ifdef SQLITE_ENABLE_FTS3_TOKENIZER
  "ENABLE_FTS3_TOKENIZER",
#endif
#if SQLITE_ENABLE_FTS4
#ifdef SQLITE_ENABLE_FTS4
  "ENABLE_FTS4",
#endif
#if SQLITE_ENABLE_FTS5
#ifdef SQLITE_ENABLE_FTS5
  "ENABLE_FTS5",
#endif
#if SQLITE_ENABLE_GEOPOLY
#ifdef SQLITE_ENABLE_GEOPOLY
  "ENABLE_GEOPOLY",
#endif
#if SQLITE_ENABLE_HIDDEN_COLUMNS
#ifdef SQLITE_ENABLE_HIDDEN_COLUMNS
  "ENABLE_HIDDEN_COLUMNS",
#endif
#if SQLITE_ENABLE_ICU
#ifdef SQLITE_ENABLE_ICU
  "ENABLE_ICU",
#endif
#if SQLITE_ENABLE_IOTRACE
#ifdef SQLITE_ENABLE_IOTRACE
  "ENABLE_IOTRACE",
#endif
#if SQLITE_ENABLE_JSON1
  "ENABLE_JSON1",
#endif
#if SQLITE_ENABLE_LOAD_EXTENSION
#ifdef SQLITE_ENABLE_LOAD_EXTENSION
  "ENABLE_LOAD_EXTENSION",
#endif
#ifdef SQLITE_ENABLE_LOCKING_STYLE
  "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE),
#endif
#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
  "ENABLE_MATH_FUNCTIONS",
#endif
#if SQLITE_ENABLE_MEMORY_MANAGEMENT
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
  "ENABLE_MEMORY_MANAGEMENT",
#endif
#if SQLITE_ENABLE_MEMSYS3
#ifdef SQLITE_ENABLE_MEMSYS3
  "ENABLE_MEMSYS3",
#endif
#if SQLITE_ENABLE_MEMSYS5
#ifdef SQLITE_ENABLE_MEMSYS5
  "ENABLE_MEMSYS5",
#endif
#if SQLITE_ENABLE_MULTIPLEX
#ifdef SQLITE_ENABLE_MULTIPLEX
  "ENABLE_MULTIPLEX",
#endif
#if SQLITE_ENABLE_NORMALIZE
#ifdef SQLITE_ENABLE_NORMALIZE
  "ENABLE_NORMALIZE",
#endif
#if SQLITE_ENABLE_NULL_TRIM
#ifdef SQLITE_ENABLE_NULL_TRIM
  "ENABLE_NULL_TRIM",
#endif
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
  "ENABLE_OFFSET_SQL_FUNC",
#endif
#if SQLITE_ENABLE_OVERSIZE_CELL_CHECK
#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
  "ENABLE_OVERSIZE_CELL_CHECK",
#endif
#if SQLITE_ENABLE_PREUPDATE_HOOK
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
  "ENABLE_PREUPDATE_HOOK",
#endif
#if SQLITE_ENABLE_QPSG
#ifdef SQLITE_ENABLE_QPSG
  "ENABLE_QPSG",
#endif
#if SQLITE_ENABLE_RBU
#ifdef SQLITE_ENABLE_RBU
  "ENABLE_RBU",
#endif
#if SQLITE_ENABLE_RTREE
#ifdef SQLITE_ENABLE_RTREE
  "ENABLE_RTREE",
#endif
#if SQLITE_ENABLE_SELECTTRACE
  "ENABLE_SELECTTRACE",
#endif
#if SQLITE_ENABLE_SESSION
#ifdef SQLITE_ENABLE_SESSION
  "ENABLE_SESSION",
#endif
#if SQLITE_ENABLE_SNAPSHOT
#ifdef SQLITE_ENABLE_SNAPSHOT
  "ENABLE_SNAPSHOT",
#endif
#if SQLITE_ENABLE_SORTER_REFERENCES
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
  "ENABLE_SORTER_REFERENCES",
#endif
#if SQLITE_ENABLE_SQLLOG
#ifdef SQLITE_ENABLE_SQLLOG
  "ENABLE_SQLLOG",
#endif
#if defined(SQLITE_ENABLE_STAT4)
#ifdef SQLITE_ENABLE_STAT4
  "ENABLE_STAT4",
#elif defined(SQLITE_ENABLE_STAT3)
  "ENABLE_STAT3",
#endif
#if SQLITE_ENABLE_STMTVTAB
#ifdef SQLITE_ENABLE_STMTVTAB
  "ENABLE_STMTVTAB",
#endif
#if SQLITE_ENABLE_STMT_SCANSTATUS
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
  "ENABLE_STMT_SCANSTATUS",
#endif
#ifdef SQLITE_ENABLE_TREETRACE
  "ENABLE_TREETRACE",
#endif
#if SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
  "ENABLE_UNKNOWN_SQL_FUNCTION",
#endif
#if SQLITE_ENABLE_UNLOCK_NOTIFY
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
  "ENABLE_UNLOCK_NOTIFY",
#endif
#if SQLITE_ENABLE_UPDATE_DELETE_LIMIT
#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
  "ENABLE_UPDATE_DELETE_LIMIT",
#endif
#if SQLITE_ENABLE_URI_00_ERROR
#ifdef SQLITE_ENABLE_URI_00_ERROR
  "ENABLE_URI_00_ERROR",
#endif
#if SQLITE_ENABLE_VFSTRACE
#ifdef SQLITE_ENABLE_VFSTRACE
  "ENABLE_VFSTRACE",
#endif
#if SQLITE_ENABLE_WHERETRACE
#ifdef SQLITE_ENABLE_WHERETRACE
  "ENABLE_WHERETRACE",
#endif
#if SQLITE_ENABLE_ZIPVFS
#ifdef SQLITE_ENABLE_ZIPVFS
  "ENABLE_ZIPVFS",
#endif
#if SQLITE_EXPLAIN_ESTIMATED_ROWS
#ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS
  "EXPLAIN_ESTIMATED_ROWS",
#endif
#if SQLITE_EXTRA_IFNULLROW
#ifdef SQLITE_EXTRA_IFNULLROW
  "EXTRA_IFNULLROW",
#endif
#ifdef SQLITE_EXTRA_INIT
  "EXTRA_INIT=" CTIMEOPT_VAL(SQLITE_EXTRA_INIT),
#endif
#ifdef SQLITE_EXTRA_SHUTDOWN
  "EXTRA_SHUTDOWN=" CTIMEOPT_VAL(SQLITE_EXTRA_SHUTDOWN),
#endif
#ifdef SQLITE_FTS3_MAX_EXPR_DEPTH
  "FTS3_MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_FTS3_MAX_EXPR_DEPTH),
#endif
#if SQLITE_FTS5_ENABLE_TEST_MI
#ifdef SQLITE_FTS5_ENABLE_TEST_MI
  "FTS5_ENABLE_TEST_MI",
#endif
#if SQLITE_FTS5_NO_WITHOUT_ROWID
#ifdef SQLITE_FTS5_NO_WITHOUT_ROWID
  "FTS5_NO_WITHOUT_ROWID",
#endif
#if SQLITE_HAS_CODEC
  "HAS_CODEC",
#endif
#if HAVE_ISNAN || SQLITE_HAVE_ISNAN
  "HAVE_ISNAN",
#endif
#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
#if SQLITE_HOMEGROWN_RECURSIVE_MUTEX
  "HOMEGROWN_RECURSIVE_MUTEX",
# if SQLITE_HOMEGROWN_RECURSIVE_MUTEX != 1
  "HOMEGROWN_RECURSIVE_MUTEX=" CTIMEOPT_VAL(SQLITE_HOMEGROWN_RECURSIVE_MUTEX),
# endif
#endif
#if SQLITE_IGNORE_AFP_LOCK_ERRORS
#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS
  "IGNORE_AFP_LOCK_ERRORS",
#endif
#if SQLITE_IGNORE_FLOCK_LOCK_ERRORS
#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
  "IGNORE_FLOCK_LOCK_ERRORS",
#endif
#if SQLITE_INLINE_MEMCPY
#ifdef SQLITE_INLINE_MEMCPY
  "INLINE_MEMCPY",
#endif
#if SQLITE_INT64_TYPE
#ifdef SQLITE_INT64_TYPE
  "INT64_TYPE",
#endif
#ifdef SQLITE_INTEGRITY_CHECK_ERROR_MAX
  "INTEGRITY_CHECK_ERROR_MAX=" CTIMEOPT_VAL(SQLITE_INTEGRITY_CHECK_ERROR_MAX),
#endif
#if SQLITE_LIKE_DOESNT_MATCH_BLOBS
#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
  "LIKE_DOESNT_MATCH_BLOBS",
#endif
#if SQLITE_LOCK_TRACE
#ifdef SQLITE_LOCK_TRACE
  "LOCK_TRACE",
#endif
#if SQLITE_LOG_CACHE_SPILL
#ifdef SQLITE_LOG_CACHE_SPILL
  "LOG_CACHE_SPILL",
#endif
#ifdef SQLITE_MALLOC_SOFT_LIMIT
  "MALLOC_SOFT_LIMIT=" CTIMEOPT_VAL(SQLITE_MALLOC_SOFT_LIMIT),
#endif
#ifdef SQLITE_MAX_ATTACHED
  "MAX_ATTACHED=" CTIMEOPT_VAL(SQLITE_MAX_ATTACHED),
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
638

639
640



641
642

643
644
645

646
647
648

649
650
651

652
653
654

655
656
657

658
659
660

661
662
663

664
665
666

667
668
669
670
671
672

673
674

675
676



677
678

679
680
681

682
683
684

685
686
687

688
689
690

691
692
693

694
695
696
697
698
699

700
701
702
703
704
705
706
707
708

709
710



711

712
713
714

715
716
717
718
719
720

721
722
723
724
725
726
727
728
729
730

731
732
733

734
735
736

737
738
739

740
741
742

743
744
745

746
747
748

749
750
751

752
753
754

755
756
757

758
759
760

761
762
763
764
765
766
767
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
638

639
640
641

642
643
644

645
646
647

648
649
650

651
652
653

654
655
656
657


658
659
660
661

662
663
664

665
666
667

668
669
670

671
672
673

674
675
676

677
678
679

680
681
682

683
684
685

686
687
688




689
690
691
692


693
694
695
696

697
698
699

700
701
702

703
704
705

706
707
708

709
710
711

712
713
714
715
716
717

718
719
720
721
722
723
724
725
726

727
728
729
730
731
732

733
734
735

736
737
738
739
740
741

742
743
744
745
746
747
748
749
750
751

752
753
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







-
+


-
+


-
+


-
+


-
-
-
-
+


-
+


-
+


-
+


-
-
-
-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
-
-
-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


+
+
+
-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


+
+
+
+
+
+
-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


+
-
-
+
+
+

-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
-
-
-
+


+
-
-
+
+
+

-
+


-
+


-
+


-
+


-
+


-
+





-
+








-
+


+
+
+
-
+


-
+





-
+









-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+
-
-
-
+







#endif
#ifdef SQLITE_MAX_VDBE_OP
  "MAX_VDBE_OP=" CTIMEOPT_VAL(SQLITE_MAX_VDBE_OP),
#endif
#ifdef SQLITE_MAX_WORKER_THREADS
  "MAX_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_MAX_WORKER_THREADS),
#endif
#if SQLITE_MEMDEBUG
#ifdef SQLITE_MEMDEBUG
  "MEMDEBUG",
#endif
#if SQLITE_MIXED_ENDIAN_64BIT_FLOAT
#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
  "MIXED_ENDIAN_64BIT_FLOAT",
#endif
#if SQLITE_MMAP_READWRITE
#ifdef SQLITE_MMAP_READWRITE
  "MMAP_READWRITE",
#endif
#if SQLITE_MUTEX_NOOP
#ifdef SQLITE_MUTEX_NOOP
  "MUTEX_NOOP",
#endif
#if SQLITE_MUTEX_NREF
  "MUTEX_NREF",
#endif
#if SQLITE_MUTEX_OMIT
#ifdef SQLITE_MUTEX_OMIT
  "MUTEX_OMIT",
#endif
#if SQLITE_MUTEX_PTHREADS
#ifdef SQLITE_MUTEX_PTHREADS
  "MUTEX_PTHREADS",
#endif
#if SQLITE_MUTEX_W32
#ifdef SQLITE_MUTEX_W32
  "MUTEX_W32",
#endif
#if SQLITE_NEED_ERR_NAME
#ifdef SQLITE_NEED_ERR_NAME
  "NEED_ERR_NAME",
#endif
#if SQLITE_NOINLINE
  "NOINLINE",
#endif
#if SQLITE_NO_SYNC
#ifdef SQLITE_NO_SYNC
  "NO_SYNC",
#endif
#if SQLITE_OMIT_ALTERTABLE
#ifdef SQLITE_OMIT_ALTERTABLE
  "OMIT_ALTERTABLE",
#endif
#if SQLITE_OMIT_ANALYZE
#ifdef SQLITE_OMIT_ANALYZE
  "OMIT_ANALYZE",
#endif
#if SQLITE_OMIT_ATTACH
#ifdef SQLITE_OMIT_ATTACH
  "OMIT_ATTACH",
#endif
#if SQLITE_OMIT_AUTHORIZATION
#ifdef SQLITE_OMIT_AUTHORIZATION
  "OMIT_AUTHORIZATION",
#endif
#if SQLITE_OMIT_AUTOINCREMENT
#ifdef SQLITE_OMIT_AUTOINCREMENT
  "OMIT_AUTOINCREMENT",
#endif
#if SQLITE_OMIT_AUTOINIT
#ifdef SQLITE_OMIT_AUTOINIT
  "OMIT_AUTOINIT",
#endif
#if SQLITE_OMIT_AUTOMATIC_INDEX
#ifdef SQLITE_OMIT_AUTOMATIC_INDEX
  "OMIT_AUTOMATIC_INDEX",
#endif
#if SQLITE_OMIT_AUTORESET
#ifdef SQLITE_OMIT_AUTORESET
  "OMIT_AUTORESET",
#endif
#if SQLITE_OMIT_AUTOVACUUM
#ifdef SQLITE_OMIT_AUTOVACUUM
  "OMIT_AUTOVACUUM",
#endif
#if SQLITE_OMIT_BETWEEN_OPTIMIZATION
#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION
  "OMIT_BETWEEN_OPTIMIZATION",
#endif
#if SQLITE_OMIT_BLOB_LITERAL
#ifdef SQLITE_OMIT_BLOB_LITERAL
  "OMIT_BLOB_LITERAL",
#endif
#if SQLITE_OMIT_BTREECOUNT
  "OMIT_BTREECOUNT",
#endif
#if SQLITE_OMIT_CAST
#ifdef SQLITE_OMIT_CAST
  "OMIT_CAST",
#endif
#if SQLITE_OMIT_CHECK
#ifdef SQLITE_OMIT_CHECK
  "OMIT_CHECK",
#endif
#if SQLITE_OMIT_COMPLETE
#ifdef SQLITE_OMIT_COMPLETE
  "OMIT_COMPLETE",
#endif
#if SQLITE_OMIT_COMPOUND_SELECT
#ifdef SQLITE_OMIT_COMPOUND_SELECT
  "OMIT_COMPOUND_SELECT",
#endif
#if SQLITE_OMIT_CONFLICT_CLAUSE
#ifdef SQLITE_OMIT_CONFLICT_CLAUSE
  "OMIT_CONFLICT_CLAUSE",
#endif
#if SQLITE_OMIT_CTE
#ifdef SQLITE_OMIT_CTE
  "OMIT_CTE",
#endif
#if SQLITE_OMIT_DATETIME_FUNCS
#if defined(SQLITE_OMIT_DATETIME_FUNCS) || defined(SQLITE_OMIT_FLOATING_POINT)
  "OMIT_DATETIME_FUNCS",
#endif
#if SQLITE_OMIT_DECLTYPE
#ifdef SQLITE_OMIT_DECLTYPE
  "OMIT_DECLTYPE",
#endif
#if SQLITE_OMIT_DEPRECATED
#ifdef SQLITE_OMIT_DEPRECATED
  "OMIT_DEPRECATED",
#endif
#ifdef SQLITE_OMIT_DESERIALIZE
  "OMIT_DESERIALIZE",
#endif
#if SQLITE_OMIT_DISKIO
#ifdef SQLITE_OMIT_DISKIO
  "OMIT_DISKIO",
#endif
#if SQLITE_OMIT_EXPLAIN
#ifdef SQLITE_OMIT_EXPLAIN
  "OMIT_EXPLAIN",
#endif
#if SQLITE_OMIT_FLAG_PRAGMAS
#ifdef SQLITE_OMIT_FLAG_PRAGMAS
  "OMIT_FLAG_PRAGMAS",
#endif
#if SQLITE_OMIT_FLOATING_POINT
#ifdef SQLITE_OMIT_FLOATING_POINT
  "OMIT_FLOATING_POINT",
#endif
#if SQLITE_OMIT_FOREIGN_KEY
#ifdef SQLITE_OMIT_FOREIGN_KEY
  "OMIT_FOREIGN_KEY",
#endif
#if SQLITE_OMIT_GET_TABLE
#ifdef SQLITE_OMIT_GET_TABLE
  "OMIT_GET_TABLE",
#endif
#if SQLITE_OMIT_HEX_INTEGER
#ifdef SQLITE_OMIT_HEX_INTEGER
  "OMIT_HEX_INTEGER",
#endif
#if SQLITE_OMIT_INCRBLOB
#ifdef SQLITE_OMIT_INCRBLOB
  "OMIT_INCRBLOB",
#endif
#if SQLITE_OMIT_INTEGRITY_CHECK
#ifdef SQLITE_OMIT_INTEGRITY_CHECK
  "OMIT_INTEGRITY_CHECK",
#endif
#ifdef SQLITE_OMIT_INTROSPECTION_PRAGMAS
  "OMIT_INTROSPECTION_PRAGMAS",
#endif
#ifdef SQLITE_OMIT_JSON
  "OMIT_JSON",
#endif
#if SQLITE_OMIT_LIKE_OPTIMIZATION
#ifdef SQLITE_OMIT_LIKE_OPTIMIZATION
  "OMIT_LIKE_OPTIMIZATION",
#endif
#if SQLITE_OMIT_LOAD_EXTENSION
#ifdef SQLITE_OMIT_LOAD_EXTENSION
  "OMIT_LOAD_EXTENSION",
#endif
#if SQLITE_OMIT_LOCALTIME
#ifdef SQLITE_OMIT_LOCALTIME
  "OMIT_LOCALTIME",
#endif
#if SQLITE_OMIT_LOOKASIDE
#ifdef SQLITE_OMIT_LOOKASIDE
  "OMIT_LOOKASIDE",
#endif
#if SQLITE_OMIT_MEMORYDB
#ifdef SQLITE_OMIT_MEMORYDB
  "OMIT_MEMORYDB",
#endif
#if SQLITE_OMIT_OR_OPTIMIZATION
#ifdef SQLITE_OMIT_OR_OPTIMIZATION
  "OMIT_OR_OPTIMIZATION",
#endif
#if SQLITE_OMIT_PAGER_PRAGMAS
#ifdef SQLITE_OMIT_PAGER_PRAGMAS
  "OMIT_PAGER_PRAGMAS",
#endif
#if SQLITE_OMIT_PARSER_TRACE
#ifdef SQLITE_OMIT_PARSER_TRACE
  "OMIT_PARSER_TRACE",
#endif
#if SQLITE_OMIT_POPEN
#ifdef SQLITE_OMIT_POPEN
  "OMIT_POPEN",
#endif
#if SQLITE_OMIT_PRAGMA
#ifdef SQLITE_OMIT_PRAGMA
  "OMIT_PRAGMA",
#endif
#if SQLITE_OMIT_PROGRESS_CALLBACK
#ifdef SQLITE_OMIT_PROGRESS_CALLBACK
  "OMIT_PROGRESS_CALLBACK",
#endif
#if SQLITE_OMIT_QUICKBALANCE
#ifdef SQLITE_OMIT_QUICKBALANCE
  "OMIT_QUICKBALANCE",
#endif
#if SQLITE_OMIT_REINDEX
#ifdef SQLITE_OMIT_REINDEX
  "OMIT_REINDEX",
#endif
#if SQLITE_OMIT_SCHEMA_PRAGMAS
#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS
  "OMIT_SCHEMA_PRAGMAS",
#endif
#if SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
  "OMIT_SCHEMA_VERSION_PRAGMAS",
#endif
#if SQLITE_OMIT_SHARED_CACHE
#ifdef SQLITE_OMIT_SHARED_CACHE
  "OMIT_SHARED_CACHE",
#endif
#if SQLITE_OMIT_SHUTDOWN_DIRECTORIES
#ifdef SQLITE_OMIT_SHUTDOWN_DIRECTORIES
  "OMIT_SHUTDOWN_DIRECTORIES",
#endif
#if SQLITE_OMIT_SUBQUERY
#ifdef SQLITE_OMIT_SUBQUERY
  "OMIT_SUBQUERY",
#endif
#if SQLITE_OMIT_TCL_VARIABLE
#ifdef SQLITE_OMIT_TCL_VARIABLE
  "OMIT_TCL_VARIABLE",
#endif
#if SQLITE_OMIT_TEMPDB
#ifdef SQLITE_OMIT_TEMPDB
  "OMIT_TEMPDB",
#endif
#if SQLITE_OMIT_TEST_CONTROL
#ifdef SQLITE_OMIT_TEST_CONTROL
  "OMIT_TEST_CONTROL",
#endif
#ifdef SQLITE_OMIT_TRACE
#if SQLITE_OMIT_TRACE
  "OMIT_TRACE",
# if SQLITE_OMIT_TRACE != 1
  "OMIT_TRACE=" CTIMEOPT_VAL(SQLITE_OMIT_TRACE),
# endif
#endif
#if SQLITE_OMIT_TRIGGER
#ifdef SQLITE_OMIT_TRIGGER
  "OMIT_TRIGGER",
#endif
#if SQLITE_OMIT_TRUNCATE_OPTIMIZATION
#ifdef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
  "OMIT_TRUNCATE_OPTIMIZATION",
#endif
#if SQLITE_OMIT_UTF16
#ifdef SQLITE_OMIT_UTF16
  "OMIT_UTF16",
#endif
#if SQLITE_OMIT_VACUUM
#ifdef SQLITE_OMIT_VACUUM
  "OMIT_VACUUM",
#endif
#if SQLITE_OMIT_VIEW
#ifdef SQLITE_OMIT_VIEW
  "OMIT_VIEW",
#endif
#if SQLITE_OMIT_VIRTUALTABLE
#ifdef SQLITE_OMIT_VIRTUALTABLE
  "OMIT_VIRTUALTABLE",
#endif
#if SQLITE_OMIT_WAL
#ifdef SQLITE_OMIT_WAL
  "OMIT_WAL",
#endif
#if SQLITE_OMIT_WSD
#ifdef SQLITE_OMIT_WSD
  "OMIT_WSD",
#endif
#if SQLITE_OMIT_XFER_OPT
#ifdef SQLITE_OMIT_XFER_OPT
  "OMIT_XFER_OPT",
#endif
#if SQLITE_PCACHE_SEPARATE_HEADER
  "PCACHE_SEPARATE_HEADER",
#endif
#if SQLITE_PERFORMANCE_TRACE
#ifdef SQLITE_PERFORMANCE_TRACE
  "PERFORMANCE_TRACE",
#endif
#ifdef SQLITE_POWERSAFE_OVERWRITE
#if SQLITE_POWERSAFE_OVERWRITE
  "POWERSAFE_OVERWRITE",
# if SQLITE_POWERSAFE_OVERWRITE != 1
  "POWERSAFE_OVERWRITE=" CTIMEOPT_VAL(SQLITE_POWERSAFE_OVERWRITE),
# endif
#endif
#if SQLITE_PREFER_PROXY_LOCKING
#ifdef SQLITE_PREFER_PROXY_LOCKING
  "PREFER_PROXY_LOCKING",
#endif
#if SQLITE_PROXY_DEBUG
#ifdef SQLITE_PROXY_DEBUG
  "PROXY_DEBUG",
#endif
#if SQLITE_REVERSE_UNORDERED_SELECTS
#ifdef SQLITE_REVERSE_UNORDERED_SELECTS
  "REVERSE_UNORDERED_SELECTS",
#endif
#if SQLITE_RTREE_INT_ONLY
#ifdef SQLITE_RTREE_INT_ONLY
  "RTREE_INT_ONLY",
#endif
#if SQLITE_SECURE_DELETE
#ifdef SQLITE_SECURE_DELETE
  "SECURE_DELETE",
#endif
#if SQLITE_SMALL_STACK
#ifdef SQLITE_SMALL_STACK
  "SMALL_STACK",
#endif
#ifdef SQLITE_SORTER_PMASZ
  "SORTER_PMASZ=" CTIMEOPT_VAL(SQLITE_SORTER_PMASZ),
#endif
#if SQLITE_SOUNDEX
#ifdef SQLITE_SOUNDEX
  "SOUNDEX",
#endif
#ifdef SQLITE_STAT4_SAMPLES
  "STAT4_SAMPLES=" CTIMEOPT_VAL(SQLITE_STAT4_SAMPLES),
#endif
#ifdef SQLITE_STMTJRNL_SPILL
  "STMTJRNL_SPILL=" CTIMEOPT_VAL(SQLITE_STMTJRNL_SPILL),
#endif
#if SQLITE_SUBSTR_COMPATIBILITY
#ifdef SQLITE_SUBSTR_COMPATIBILITY
  "SUBSTR_COMPATIBILITY",
#endif
#if (!defined(SQLITE_WIN32_MALLOC) \
     && !defined(SQLITE_ZERO_MALLOC) \
     && !defined(SQLITE_MEMDEBUG) \
#if SQLITE_SYSTEM_MALLOC
    ) || defined(SQLITE_SYSTEM_MALLOC)
  "SYSTEM_MALLOC",
#endif
#if SQLITE_TCL
#ifdef SQLITE_TCL
  "TCL",
#endif
#ifdef SQLITE_TEMP_STORE
  "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
#endif
#if SQLITE_TEST
#ifdef SQLITE_TEST
  "TEST",
#endif
#if defined(SQLITE_THREADSAFE)
  "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
#elif defined(THREADSAFE)
  "THREADSAFE=" CTIMEOPT_VAL(THREADSAFE),
#else
  "THREADSAFE=1",
#endif
#if SQLITE_UNLINK_AFTER_CLOSE
#ifdef SQLITE_UNLINK_AFTER_CLOSE
  "UNLINK_AFTER_CLOSE",
#endif
#if SQLITE_UNTESTABLE
#ifdef SQLITE_UNTESTABLE
  "UNTESTABLE",
#endif
#if SQLITE_USER_AUTHENTICATION
#ifdef SQLITE_USER_AUTHENTICATION
  "USER_AUTHENTICATION",
#endif
#if SQLITE_USE_ALLOCA
#ifdef SQLITE_USE_ALLOCA
  "USE_ALLOCA",
#endif
#if SQLITE_USE_FCNTL_TRACE
#ifdef SQLITE_USE_FCNTL_TRACE
  "USE_FCNTL_TRACE",
#endif
#if SQLITE_USE_URI
#ifdef SQLITE_USE_URI
  "USE_URI",
#endif
#if SQLITE_VDBE_COVERAGE
#ifdef SQLITE_VDBE_COVERAGE
  "VDBE_COVERAGE",
#endif
#if SQLITE_WIN32_MALLOC
#ifdef SQLITE_WIN32_MALLOC
  "WIN32_MALLOC",
#endif
#if SQLITE_ZERO_MALLOC
#ifdef SQLITE_ZERO_MALLOC
  "ZERO_MALLOC",
#endif
/* 

** END CODE GENERATED BY tool/mkctime.tcl 
*/
};
} ;

const char **sqlite3CompileOptions(int *pnOpt){
  *pnOpt = sizeof(sqlite3azCompileOpt) / sizeof(sqlite3azCompileOpt[0]);
  return (const char**)sqlite3azCompileOpt;
}

#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */

Changes to src/date.c.

272
273
274
275
276
277
278
279

280
281
282
283
284
285
286
272
273
274
275
276
277
278

279
280
281
282
283
284
285
286







-
+







  A = Y/100;
  B = 2 - A + (A/4);
  X1 = 36525*(Y+4716)/100;
  X2 = 306001*(M+1)/10000;
  p->iJD = (sqlite3_int64)((X1 + X2 + D + B - 1524.5 ) * 86400000);
  p->validJD = 1;
  if( p->validHMS ){
    p->iJD += p->h*3600000 + p->m*60000 + (sqlite3_int64)(p->s*1000);
    p->iJD += p->h*3600000 + p->m*60000 + (sqlite3_int64)(p->s*1000 + 0.5);
    if( p->validTZ ){
      p->iJD -= p->tz*60000;
      p->validYMD = 0;
      p->validHMS = 0;
      p->validTZ = 0;
    }
  }
384
385
386
387
388
389
390
391

392
393
394
395
396
397
398
384
385
386
387
388
389
390

391
392
393
394
395
396
397
398







-
+







  double r;
  if( parseYyyyMmDd(zDate,p)==0 ){
    return 0;
  }else if( parseHhMmSs(zDate, p)==0 ){
    return 0;
  }else if( sqlite3StrICmp(zDate,"now")==0 && sqlite3NotPureFunc(context) ){
    return setDateTimeToCurrent(context, p);
  }else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8) ){
  }else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8)>0 ){
    setRawDateNumber(p, r);
    return 0;
  }
  return 1;
}

/* The julian day number for 9999-12-31 23:59:59.999 is 5373484.4999999.
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
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
638
639
640
641
642







-
-
+
+
+
+










-
+




-
+
+
+
+
+
+
+
+
+


+

+



-
+
+
+
+
+
+
+














-
+
-
-
-
-
-

-
-
-
+
+
+
-

-


+




-
-
-
+
+
+
+





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


-
-
+

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












-
-
-
-
-
+
+
+
+

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








/*
** The following routine implements the rough equivalent of localtime_r()
** using whatever operating-system specific localtime facility that
** is available.  This routine returns 0 on success and
** non-zero on any kind of error.
**
** If the sqlite3GlobalConfig.bLocaltimeFault variable is true then this
** routine will always fail.
** If the sqlite3GlobalConfig.bLocaltimeFault variable is non-zero then this
** routine will always fail.  If bLocaltimeFault is nonzero and
** sqlite3GlobalConfig.xAltLocaltime is not NULL, then xAltLocaltime() is
** invoked in place of the OS-defined localtime() function.
**
** EVIDENCE-OF: R-62172-00036 In this implementation, the standard C
** library function localtime_r() is used to assist in the calculation of
** local time.
*/
static int osLocaltime(time_t *t, struct tm *pTm){
  int rc;
#if !HAVE_LOCALTIME_R && !HAVE_LOCALTIME_S
  struct tm *pX;
#if SQLITE_THREADSAFE>0
  sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
  sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN);
#endif
  sqlite3_mutex_enter(mutex);
  pX = localtime(t);
#ifndef SQLITE_UNTESTABLE
  if( sqlite3GlobalConfig.bLocaltimeFault ) pX = 0;
  if( sqlite3GlobalConfig.bLocaltimeFault ){
    if( sqlite3GlobalConfig.xAltLocaltime!=0
     && 0==sqlite3GlobalConfig.xAltLocaltime((const void*)t,(void*)pTm)
    ){
      pX = pTm;
    }else{
      pX = 0;
    }
  }
#endif
  if( pX ) *pTm = *pX;
#if SQLITE_THREADSAFE>0
  sqlite3_mutex_leave(mutex);
#endif
  rc = pX==0;
#else
#ifndef SQLITE_UNTESTABLE
  if( sqlite3GlobalConfig.bLocaltimeFault ) return 1;
  if( sqlite3GlobalConfig.bLocaltimeFault ){
    if( sqlite3GlobalConfig.xAltLocaltime!=0 ){
      return sqlite3GlobalConfig.xAltLocaltime((const void*)t,(void*)pTm);
    }else{
      return 1;
    }
  }
#endif
#if HAVE_LOCALTIME_R
  rc = localtime_r(t, pTm)==0;
#else
  rc = localtime_s(pTm, t);
#endif /* HAVE_LOCALTIME_R */
#endif /* HAVE_LOCALTIME_R || HAVE_LOCALTIME_S */
  return rc;
}
#endif /* SQLITE_OMIT_LOCALTIME */


#ifndef SQLITE_OMIT_LOCALTIME
/*
** Compute the difference (in milliseconds) between localtime and UTC
** Assuming the input DateTime is UTC, move it to its localtime equivalent.
** (a.k.a. GMT) for the time value p where p is in UTC. If no error occurs,
** return this value and set *pRc to SQLITE_OK. 
**
** Or, if an error does occur, set *pRc to SQLITE_ERROR. The returned value
** is undefined in this case.
*/
static sqlite3_int64 localtimeOffset(
  DateTime *p,                    /* Date at which to calculate offset */
  sqlite3_context *pCtx,          /* Write error here if one occurs */
static int toLocaltime(
  DateTime *p,                   /* Date at which to calculate offset */
  sqlite3_context *pCtx          /* Write error here if one occurs */
  int *pRc                        /* OUT: Error code. SQLITE_OK or ERROR */
){
  DateTime x, y;
  time_t t;
  struct tm sLocal;
  int iYearDiff;

  /* Initialize the contents of sLocal to avoid a compiler warning. */
  memset(&sLocal, 0, sizeof(sLocal));

  x = *p;
  computeYMD_HMS(&x);
  if( x.Y<1971 || x.Y>=2038 ){
  computeJD(p);
  if( p->iJD<2108667600*(i64)100000 /* 1970-01-01 */
   || p->iJD>2130141456*(i64)100000 /* 2038-01-18 */
  ){
    /* EVIDENCE-OF: R-55269-29598 The localtime_r() C function normally only
    ** works for years between 1970 and 2037. For dates outside this range,
    ** SQLite attempts to map the year into an equivalent year within this
    ** range, do the calculation, then map the year back.
    */
    x.Y = 2000;
    x.M = 1;
    x.D = 1;
    x.h = 0;
    DateTime x = *p;
    computeYMD_HMS(&x);
    iYearDiff = (2000 + x.Y%4) - x.Y;
    x.Y += iYearDiff;
    x.m = 0;
    x.s = 0.0;
  } else {
    int s = (int)(x.s + 0.5);
    x.s = s;
  }
  x.tz = 0;
  x.validJD = 0;
  computeJD(&x);
  t = (time_t)(x.iJD/1000 - 21086676*(i64)10000);
    x.validJD = 0;
    computeJD(&x);
    t = (time_t)(x.iJD/1000 -  21086676*(i64)10000);
  }else{
    iYearDiff = 0;
    t = (time_t)(p->iJD/1000 -  21086676*(i64)10000);
  }
  if( osLocaltime(&t, &sLocal) ){
    sqlite3_result_error(pCtx, "local time unavailable", -1);
    *pRc = SQLITE_ERROR;
    return 0;
    return SQLITE_ERROR;
  }
  y.Y = sLocal.tm_year + 1900;
  y.M = sLocal.tm_mon + 1;
  y.D = sLocal.tm_mday;
  y.h = sLocal.tm_hour;
  y.m = sLocal.tm_min;
  y.s = sLocal.tm_sec;
  y.validYMD = 1;
  y.validHMS = 1;
  y.validJD = 0;
  y.rawS = 0;
  y.validTZ = 0;
  y.isError = 0;
  p->Y = sLocal.tm_year + 1900 - iYearDiff;
  p->M = sLocal.tm_mon + 1;
  p->D = sLocal.tm_mday;
  p->h = sLocal.tm_hour;
  p->m = sLocal.tm_min;
  p->s = sLocal.tm_sec + (p->iJD%1000)*0.001;
  p->validYMD = 1;
  p->validHMS = 1;
  p->validJD = 0;
  p->rawS = 0;
  p->validTZ = 0;
  p->isError = 0;
  computeJD(&y);
  *pRc = SQLITE_OK;
  return SQLITE_OK;
  return y.iJD - x.iJD;
}
#endif /* SQLITE_OMIT_LOCALTIME */

/*
** The following table defines various date transformations of the form
**
**            'NNN days'
**
** Where NNN is an arbitrary floating-point number and "days" can be one
** of several units of time.
*/
static const struct {
  u8 eType;           /* Transformation type code */
  u8 nName;           /* Length of th name */
  char *zName;        /* Name of the transformation */
  double rLimit;      /* Maximum NNN value for this transform */
  double rXform;      /* Constant used for this transform */
  u8 nName;           /* Length of the name */
  char zName[7];      /* Name of the transformation */
  float rLimit;       /* Maximum NNN value for this transform */
  float rXform;       /* Constant used for this transform */
} aXformType[] = {
  { 0, 6, "second", 464269060800.0, 86400000.0/(24.0*60.0*60.0) },
  { 0, 6, "minute", 7737817680.0,   86400000.0/(24.0*60.0)      },
  { 0, 4, "hour",   128963628.0,    86400000.0/24.0             },
  { 0, 3, "day",    5373485.0,      86400000.0                  },
  { 1, 5, "month",  176546.0,       30.0*86400000.0             },
  { 2, 4, "year",   14713.0,        365.0*86400000.0            },
  { 6, "second", 4.6427e+14,       1.0  },
  { 6, "minute", 7.7379e+12,      60.0  },
  { 4, "hour",   1.2897e+11,    3600.0  },
  { 3, "day",    5373485.0,    86400.0  },
  { 5, "month",  176546.0,   2592000.0  },
  { 4, "year",   14713.0,   31536000.0  },
};

/*
** Process a modifier to a date-time stamp.  The modifiers are
** as follows:
**
**     NNN days
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
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
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







-
+
+




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








-
-
+
-












+



-
+








+
+
+
+
-
+

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

-
-

+













-
-
+
+







** to context pCtx. If the error is an unrecognized modifier, no error is
** written to pCtx.
*/
static int parseModifier(
  sqlite3_context *pCtx,      /* Function context */
  const char *z,              /* The text of the modifier */
  int n,                      /* Length of zMod in bytes */
  DateTime *p                 /* The date/time value to be modified */
  DateTime *p,                /* The date/time value to be modified */
  int idx                     /* Parameter index of the modifier */
){
  int rc = 1;
  double r;
  switch(sqlite3UpperToLower[(u8)z[0]] ){
    case 'a': {
      /*
      **    auto
      **
      ** If rawS is available, then interpret as a julian day number, or
      ** a unix timestamp, depending on its magnitude.
      */
      if( sqlite3_stricmp(z, "auto")==0 ){
        if( idx>1 ) return 1; /* IMP: R-33611-57934 */
        if( !p->rawS || p->validJD ){
          rc = 0;
          p->rawS = 0;
        }else if( p->s>=-21086676*(i64)10000        /* -4713-11-24 12:00:00 */
               && p->s<=(25340230*(i64)10000)+799   /*  9999-12-31 23:59:59 */
        ){
          r = p->s*1000.0 + 210866760000000.0;
          clearYMD_HMS_TZ(p);
          p->iJD = (sqlite3_int64)(r + 0.5);
          p->validJD = 1;
          p->rawS = 0;
          rc = 0;
        }
      }
      break;
    }
    case 'j': {
      /*
      **    julianday
      **
      ** Always interpret the prior number as a julian-day value.  If this
      ** is not the first modifier, or if the prior argument is not a numeric
      ** value in the allowed range of julian day numbers understood by
      ** SQLite (0..5373484.5) then the result will be NULL.
      */
      if( sqlite3_stricmp(z, "julianday")==0 ){
        if( idx>1 ) return 1;  /* IMP: R-31176-64601 */
        if( p->validJD && p->rawS ){
          rc = 0;
          p->rawS = 0;
        }
      }
      break;
    }
#ifndef SQLITE_OMIT_LOCALTIME
    case 'l': {
      /*    localtime
      **
      ** Assuming the current time value is UTC (a.k.a. GMT), shift it to
      ** show local time.
      */
      if( sqlite3_stricmp(z, "localtime")==0 && sqlite3NotPureFunc(pCtx) ){
        computeJD(p);
        p->iJD += localtimeOffset(p, pCtx, &rc);
        rc = toLocaltime(p, pCtx);
        clearYMD_HMS_TZ(p);
      }
      break;
    }
#endif
    case 'u': {
      /*
      **    unixepoch
      **
      ** Treat the current value of p->s as the number of
      ** seconds since 1970.  Convert to a real julian day number.
      */
      if( sqlite3_stricmp(z, "unixepoch")==0 && p->rawS ){
        if( idx>1 ) return 1;  /* IMP: R-49255-55373 */
        r = p->s*1000.0 + 210866760000000.0;
        if( r>=0.0 && r<464269060800000.0 ){
          clearYMD_HMS_TZ(p);
          p->iJD = (sqlite3_int64)r;
          p->iJD = (sqlite3_int64)(r + 0.5);
          p->validJD = 1;
          p->rawS = 0;
          rc = 0;
        }
      }
#ifndef SQLITE_OMIT_LOCALTIME
      else if( sqlite3_stricmp(z, "utc")==0 && sqlite3NotPureFunc(pCtx) ){
        if( p->tzSet==0 ){
          i64 iOrigJD;              /* Original localtime */
          i64 iGuess;               /* Guess at the corresponding utc time */
          int cnt = 0;              /* Safety to prevent infinite loop */
          int iErr;                 /* Guess is off by this much */
          sqlite3_int64 c1;

          computeJD(p);
          iGuess = iOrigJD = p->iJD;
          iErr = 0;
          do{
            DateTime new;
            memset(&new, 0, sizeof(new));
            iGuess -= iErr;
            new.iJD = iGuess;
            new.validJD = 1;
          c1 = localtimeOffset(p, pCtx, &rc);
          if( rc==SQLITE_OK ){
            p->iJD -= c1;
            rc = toLocaltime(&new, pCtx);
            if( rc ) return rc;
            computeJD(&new);
            iErr = new.iJD - iOrigJD;
          }while( iErr && cnt++<3 );
          memset(p, 0, sizeof(*p));
          p->iJD = iGuess;
            clearYMD_HMS_TZ(p);
            p->iJD += c1 - localtimeOffset(p, pCtx, &rc);
          p->validJD = 1;
          }
          p->tzSet = 1;
        }else{
          rc = SQLITE_OK;
        }
        rc = SQLITE_OK;
      }
#endif
      break;
    }
    case 'w': {
      /*
      **    weekday N
      **
      ** Move the date to the same time on the next occurrence of
      ** weekday N where 0==Sunday, 1==Monday, and so forth.  If the
      ** date is already on the appropriate weekday, this is a no-op.
      */
      if( sqlite3_strnicmp(z, "weekday ", 8)==0
               && sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8)
               && (n=(int)r)==r && n>=0 && r<7 ){
               && sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8)>0
               && r>=0.0 && r<7.0 && (n=(int)r)==r ){
        sqlite3_int64 Z;
        computeYMD_HMS(p);
        p->validTZ = 0;
        p->validJD = 0;
        computeJD(p);
        Z = ((p->iJD + 129600000)/86400000) % 7;
        if( Z>n ) Z -= 7;
777
778
779
780
781
782
783
784

785
786
787
788
789
790
791
839
840
841
842
843
844
845

846
847
848
849
850
851
852
853







-
+







    case '6':
    case '7':
    case '8':
    case '9': {
      double rRounder;
      int i;
      for(n=1; z[n] && z[n]!=':' && !sqlite3Isspace(z[n]); n++){}
      if( !sqlite3AtoF(z, &r, n, SQLITE_UTF8) ){
      if( sqlite3AtoF(z, &r, n, SQLITE_UTF8)<=0 ){
        rc = 1;
        break;
      }
      if( z[n]==':' ){
        /* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the
        ** specified number of hours, minutes, seconds, and fractional seconds
        ** to the time.  The ".FFF" may be omitted.  The ":SS.FFF" may be
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
882
883
884
885
886
887
888


889
890
891
892
893
894
895
896
897
898
899
900
901

902
903
904
905
906
907
908
909
910
911
912

913
914
915
916
917
918
919
920







-
-
+
+

+









-
+

+








-
+







      rc = 1;
      rRounder = r<0 ? -0.5 : +0.5;
      for(i=0; i<ArraySize(aXformType); i++){
        if( aXformType[i].nName==n
         && sqlite3_strnicmp(aXformType[i].zName, z, n)==0
         && r>-aXformType[i].rLimit && r<aXformType[i].rLimit
        ){
          switch( aXformType[i].eType ){
            case 1: { /* Special processing to add months */
          switch( i ){
            case 4: { /* Special processing to add months */
              int x;
              assert( strcmp(aXformType[i].zName,"month")==0 );
              computeYMD_HMS(p);
              p->M += (int)r;
              x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
              p->Y += x;
              p->M -= x*12;
              p->validJD = 0;
              r -= (int)r;
              break;
            }
            case 2: { /* Special processing to add years */
            case 5: { /* Special processing to add years */
              int y = (int)r;
              assert( strcmp(aXformType[i].zName,"year")==0 );
              computeYMD_HMS(p);
              p->Y += y;
              p->validJD = 0;
              r -= (int)r;
              break;
            }
          }
          computeJD(p);
          p->iJD += (sqlite3_int64)(r*aXformType[i].rXform + rRounder);
          p->iJD += (sqlite3_int64)(r*1000.0*aXformType[i].rXform + rRounder);
          rc = 0;
          break;
        }
      }
      clearYMD_HMS_TZ(p);
      break;
    }
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
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962

963
964
965
966
967
968
969
970







+














-
+







  DateTime *p
){
  int i, n;
  const unsigned char *z;
  int eType;
  memset(p, 0, sizeof(*p));
  if( argc==0 ){
    if( !sqlite3NotPureFunc(context) ) return 1;
    return setDateTimeToCurrent(context, p);
  }
  if( (eType = sqlite3_value_type(argv[0]))==SQLITE_FLOAT
                   || eType==SQLITE_INTEGER ){
    setRawDateNumber(p, sqlite3_value_double(argv[0]));
  }else{
    z = sqlite3_value_text(argv[0]);
    if( !z || parseDateOrTime(context, (char*)z, p) ){
      return 1;
    }
  }
  for(i=1; i<argc; i++){
    z = sqlite3_value_text(argv[i]);
    n = sqlite3_value_bytes(argv[i]);
    if( z==0 || parseModifier(context, (char*)z, n, p) ) return 1;
    if( z==0 || parseModifier(context, (char*)z, n, p, i) ) return 1;
  }
  computeJD(p);
  if( p->isError || !validJulianDay(p->iJD) ) return 1;
  return 0;
}


920
921
922
923
924
925
926


















927
928
929
930
931
932
933
934
935
936
937
938
939

940

941






942
943
944























945
946
947
948
949
950
951
952
953
954
955
956
957
958
959

960

961






962
963





964
965
966
967
968
969
970
971
972
973
974
975
976
977
978

979

980
981
982



















983
984
985
986
987
988
989
985
986
987
988
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
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







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













+
-
+

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















+
-
+

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















+
-
+

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







){
  DateTime x;
  if( isDate(context, argc, argv, &x)==0 ){
    computeJD(&x);
    sqlite3_result_double(context, x.iJD/86400000.0);
  }
}

/*
**    unixepoch( TIMESTRING, MOD, MOD, ...)
**
** Return the number of seconds (including fractional seconds) since
** the unix epoch of 1970-01-01 00:00:00 GMT.
*/
static void unixepochFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  DateTime x;
  if( isDate(context, argc, argv, &x)==0 ){
    computeJD(&x);
    sqlite3_result_int64(context, x.iJD/1000 - 21086676*(i64)10000);
  }
}

/*
**    datetime( TIMESTRING, MOD, MOD, ...)
**
** Return YYYY-MM-DD HH:MM:SS
*/
static void datetimeFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  DateTime x;
  if( isDate(context, argc, argv, &x)==0 ){
    int Y, s;
    char zBuf[100];
    char zBuf[24];
    computeYMD_HMS(&x);
    Y = x.Y;
    if( Y<0 ) Y = -Y;
    zBuf[1] = '0' + (Y/1000)%10;
    zBuf[2] = '0' + (Y/100)%10;
    zBuf[3] = '0' + (Y/10)%10;
    zBuf[4] = '0' + (Y)%10;
    sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d %02d:%02d:%02d",
                     x.Y, x.M, x.D, x.h, x.m, (int)(x.s));
    sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
    zBuf[5] = '-';
    zBuf[6] = '0' + (x.M/10)%10;
    zBuf[7] = '0' + (x.M)%10;
    zBuf[8] = '-';
    zBuf[9] = '0' + (x.D/10)%10;
    zBuf[10] = '0' + (x.D)%10;
    zBuf[11] = ' ';
    zBuf[12] = '0' + (x.h/10)%10;
    zBuf[13] = '0' + (x.h)%10;
    zBuf[14] = ':';
    zBuf[15] = '0' + (x.m/10)%10;
    zBuf[16] = '0' + (x.m)%10;
    zBuf[17] = ':';
    s = (int)x.s;
    zBuf[18] = '0' + (s/10)%10;
    zBuf[19] = '0' + (s)%10;
    zBuf[20] = 0;
    if( x.Y<0 ){
      zBuf[0] = '-';
      sqlite3_result_text(context, zBuf, 20, SQLITE_TRANSIENT);
    }else{
      sqlite3_result_text(context, &zBuf[1], 19, SQLITE_TRANSIENT);
    }
  }
}

/*
**    time( TIMESTRING, MOD, MOD, ...)
**
** Return HH:MM:SS
*/
static void timeFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  DateTime x;
  if( isDate(context, argc, argv, &x)==0 ){
    int s;
    char zBuf[100];
    char zBuf[16];
    computeHMS(&x);
    zBuf[0] = '0' + (x.h/10)%10;
    zBuf[1] = '0' + (x.h)%10;
    zBuf[2] = ':';
    zBuf[3] = '0' + (x.m/10)%10;
    zBuf[4] = '0' + (x.m)%10;
    zBuf[5] = ':';
    sqlite3_snprintf(sizeof(zBuf), zBuf, "%02d:%02d:%02d", x.h, x.m, (int)x.s);
    sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
    s = (int)x.s;
    zBuf[6] = '0' + (s/10)%10;
    zBuf[7] = '0' + (s)%10;
    zBuf[8] = 0;
    sqlite3_result_text(context, zBuf, 8, SQLITE_TRANSIENT);
  }
}

/*
**    date( TIMESTRING, MOD, MOD, ...)
**
** Return YYYY-MM-DD
*/
static void dateFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  DateTime x;
  if( isDate(context, argc, argv, &x)==0 ){
    int Y;
    char zBuf[100];
    char zBuf[16];
    computeYMD(&x);
    sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d", x.Y, x.M, x.D);
    sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
    Y = x.Y;
    if( Y<0 ) Y = -Y;
    zBuf[1] = '0' + (Y/1000)%10;
    zBuf[2] = '0' + (Y/100)%10;
    zBuf[3] = '0' + (Y/10)%10;
    zBuf[4] = '0' + (Y)%10;
    zBuf[5] = '-';
    zBuf[6] = '0' + (x.M/10)%10;
    zBuf[7] = '0' + (x.M)%10;
    zBuf[8] = '-';
    zBuf[9] = '0' + (x.D/10)%10;
    zBuf[10] = '0' + (x.D)%10;
    zBuf[11] = 0;
    if( x.Y<0 ){
      zBuf[0] = '-';
      sqlite3_result_text(context, zBuf, 11, SQLITE_TRANSIENT);
    }else{
      sqlite3_result_text(context, &zBuf[1], 10, SQLITE_TRANSIENT);
    }
  }
}

/*
**    strftime( FORMAT, TIMESTRING, MOD, MOD, ...)
**
** Return a string described by FORMAT.  Conversions as follows:
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
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







-

-


+
-
+
+




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



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



-
-
+
+
-







*/
static void strftimeFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  DateTime x;
  u64 n;
  size_t i,j;
  char *z;
  sqlite3 *db;
  const char *zFmt;
  sqlite3_str sRes;
  char zBuf[100];


  if( argc==0 ) return;
  zFmt = (const char*)sqlite3_value_text(argv[0]);
  if( zFmt==0 || isDate(context, argc-1, argv+1, &x) ) return;
  db = sqlite3_context_db_handle(context);
  for(i=0, n=1; zFmt[i]; i++, n++){
    if( zFmt[i]=='%' ){
      switch( zFmt[i+1] ){
        case 'd':
        case 'H':
        case 'm':
        case 'M':
        case 'S':
        case 'W':
          n++;
          /* fall thru */
        case 'w':
        case '%':
          break;
        case 'f':
          n += 8;
          break;
        case 'j':
          n += 3;
          break;
        case 'Y':
          n += 8;
          break;
        case 's':
        case 'J':
          n += 50;
          break;
        default:
          return;  /* ERROR.  return a NULL */
      }
      i++;
    }
  }
  testcase( n==sizeof(zBuf)-1 );
  testcase( n==sizeof(zBuf) );
  testcase( n==(u64)db->aLimit[SQLITE_LIMIT_LENGTH]+1 );
  testcase( n==(u64)db->aLimit[SQLITE_LIMIT_LENGTH] );
  sqlite3StrAccumInit(&sRes, 0, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
  if( n<sizeof(zBuf) ){
    z = zBuf;
  }else if( n>(u64)db->aLimit[SQLITE_LIMIT_LENGTH] ){
    sqlite3_result_error_toobig(context);
    return;
  }else{
    z = sqlite3DbMallocRawNN(db, (int)n);
    if( z==0 ){
      sqlite3_result_error_nomem(context);
      return;
    }

  }
  computeJD(&x);
  computeYMD_HMS(&x);
  for(i=j=0; zFmt[i]; i++){
    if( zFmt[i]!='%' ){
      z[j++] = zFmt[i];
    if( zFmt[i]!='%' ) continue;
    if( j<i ) sqlite3_str_append(&sRes, zFmt+j, (int)(i-j));
    }else{
      i++;
      switch( zFmt[i] ){
        case 'd':  sqlite3_snprintf(3, &z[j],"%02d",x.D); j+=2; break;
        case 'f': {
          double s = x.s;
          if( s>59.999 ) s = 59.999;
          sqlite3_snprintf(7, &z[j],"%06.3f", s);
    i++;
    j = i + 1;
    switch( zFmt[i] ){
      case 'd': {
        sqlite3_str_appendf(&sRes, "%02d", x.D);
        break;
      }
      case 'f': {
        double s = x.s;
        if( s>59.999 ) s = 59.999;
        sqlite3_str_appendf(&sRes, "%06.3f", s);
          j += sqlite3Strlen30(&z[j]);
          break;
        }
        case 'H':  sqlite3_snprintf(3, &z[j],"%02d",x.h); j+=2; break;
        case 'W': /* Fall thru */
        case 'j': {
          int nDay;             /* Number of days since 1st day of year */
          DateTime y = x;
          y.validJD = 0;
          y.M = 1;
          y.D = 1;
          computeJD(&y);
          nDay = (int)((x.iJD-y.iJD+43200000)/86400000);
          if( zFmt[i]=='W' ){
            int wd;   /* 0=Monday, 1=Tuesday, ... 6=Sunday */
            wd = (int)(((x.iJD+43200000)/86400000)%7);
            sqlite3_snprintf(3, &z[j],"%02d",(nDay+7-wd)/7);
        break;
      }
      case 'H': {
        sqlite3_str_appendf(&sRes, "%02d", x.h);
        break;
      }
      case 'W': /* Fall thru */
      case 'j': {
        int nDay;             /* Number of days since 1st day of year */
        DateTime y = x;
        y.validJD = 0;
        y.M = 1;
        y.D = 1;
        computeJD(&y);
        nDay = (int)((x.iJD-y.iJD+43200000)/86400000);
        if( zFmt[i]=='W' ){
          int wd;   /* 0=Monday, 1=Tuesday, ... 6=Sunday */
          wd = (int)(((x.iJD+43200000)/86400000)%7);
          sqlite3_str_appendf(&sRes,"%02d",(nDay+7-wd)/7);
            j += 2;
          }else{
            sqlite3_snprintf(4, &z[j],"%03d",nDay+1);
        }else{
          sqlite3_str_appendf(&sRes,"%03d",nDay+1);
            j += 3;
          }
          break;
        }
        case 'J': {
          sqlite3_snprintf(20, &z[j],"%.16g",x.iJD/86400000.0);
        }
        break;
      }
      case 'J': {
        sqlite3_str_appendf(&sRes,"%.16g",x.iJD/86400000.0);
          j+=sqlite3Strlen30(&z[j]);
          break;
        }
        case 'm':  sqlite3_snprintf(3, &z[j],"%02d",x.M); j+=2; break;
        case 'M':  sqlite3_snprintf(3, &z[j],"%02d",x.m); j+=2; break;
        case 's': {
        break;
      }
      case 'm': {
        sqlite3_str_appendf(&sRes,"%02d",x.M);
        break;
      }
      case 'M': {
        sqlite3_str_appendf(&sRes,"%02d",x.m);
        break;
      }
      case 's': {
          sqlite3_snprintf(30,&z[j],"%lld",
                           (i64)(x.iJD/1000 - 21086676*(i64)10000));
          j += sqlite3Strlen30(&z[j]);
          break;
        }
        case 'S':  sqlite3_snprintf(3,&z[j],"%02d",(int)x.s); j+=2; break;
        case 'w': {
          z[j++] = (char)(((x.iJD+129600000)/86400000) % 7) + '0';
          break;
        }
        case 'Y': {
          sqlite3_snprintf(5,&z[j],"%04d",x.Y); j+=sqlite3Strlen30(&z[j]);
          break;
        }
        default:   z[j++] = '%'; break;
        i64 iS = (i64)(x.iJD/1000 - 21086676*(i64)10000);
        sqlite3_str_appendf(&sRes,"%lld",iS);
        break;
      }
      case 'S': {
        sqlite3_str_appendf(&sRes,"%02d",(int)x.s);
        break;
      }
      case 'w': {
        sqlite3_str_appendchar(&sRes, 1,
                       (char)(((x.iJD+129600000)/86400000) % 7) + '0');
        break;
      }
      case 'Y': {
        sqlite3_str_appendf(&sRes,"%04d",x.Y);
        break;
      }
      case '%': {
        sqlite3_str_appendchar(&sRes, 1, '%');
        break;
      }
      default: {
        sqlite3_str_reset(&sRes);
        return;
      }
    }
  }
  z[j] = 0;
  sqlite3_result_text(context, z, -1,
  if( j<i ) sqlite3_str_append(&sRes, zFmt+j, (int)(i-j));
  sqlite3ResultStrAccum(context, &sRes);
                      z==zBuf ? SQLITE_TRANSIENT : SQLITE_DYNAMIC);
}

/*
** current_time()
**
** This function returns the same value as time('now').
*/
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
1314
1315
1316
1317
1318
1319
1320

1321
1322
1323

1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349







-
+


-
+

















+








  iT = sqlite3StmtCurrentTime(context);
  if( iT<=0 ) return;
  t = iT/1000 - 10000*(sqlite3_int64)21086676;
#if HAVE_GMTIME_R
  pTm = gmtime_r(&t, &sNow);
#else
  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN));
  pTm = gmtime(&t);
  if( pTm ) memcpy(&sNow, pTm, sizeof(sNow));
  sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
  sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN));
#endif
  if( pTm ){
    strftime(zBuf, 20, zFormat, &sNow);
    sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
  }
}
#endif

/*
** This function registered all of the above C functions as SQL
** functions.  This should be the only routine in this file with
** external linkage.
*/
void sqlite3RegisterDateTimeFunctions(void){
  static FuncDef aDateTimeFuncs[] = {
#ifndef SQLITE_OMIT_DATETIME_FUNCS
    PURE_DATE(julianday,        -1, 0, 0, juliandayFunc ),
    PURE_DATE(unixepoch,        -1, 0, 0, unixepochFunc ),
    PURE_DATE(date,             -1, 0, 0, dateFunc      ),
    PURE_DATE(time,             -1, 0, 0, timeFunc      ),
    PURE_DATE(datetime,         -1, 0, 0, datetimeFunc  ),
    PURE_DATE(strftime,         -1, 0, 0, strftimeFunc  ),
    DFUNCTION(current_time,      0, 0, 0, ctimeFunc     ),
    DFUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc),
    DFUNCTION(current_date,      0, 0, 0, cdateFunc     ),

Changes to src/dbpage.c.

68
69
70
71
72
73
74




75

76
77
78
79
80
81
82
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87







+
+
+
+

+







  void *pAux,
  int argc, const char *const*argv,
  sqlite3_vtab **ppVtab,
  char **pzErr
){
  DbpageTable *pTab = 0;
  int rc = SQLITE_OK;
  (void)pAux;
  (void)argc;
  (void)argv;
  (void)pzErr;

  sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY);
  rc = sqlite3_declare_vtab(db, 
          "CREATE TABLE x(pgno INTEGER PRIMARY KEY, data BLOB, schema HIDDEN)");
  if( rc==SQLITE_OK ){
    pTab = (DbpageTable *)sqlite3_malloc64(sizeof(DbpageTable));
    if( pTab==0 ) rc = SQLITE_NOMEM_BKPT;
  }

105
106
107
108
109
110
111

112
113
114
115
116
117
118
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124







+







**     1     schema=main, pgno=?1
**     2     schema=?1, full table scan
**     3     schema=?1, pgno=?2
*/
static int dbpageBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
  int i;
  int iPlan = 0;
  (void)tab;

  /* If there is a schema= constraint, it must be honored.  Report a
  ** ridiculously large estimated cost if the schema= constraint is
  ** unavailable
  */
  for(i=0; i<pIdxInfo->nConstraint; i++){
    struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i];
151
152
153
154
155
156
157

158
159
160
161
162
163
164
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171







+








  if( pIdxInfo->nOrderBy>=1
   && pIdxInfo->aOrderBy[0].iColumn<=0
   && pIdxInfo->aOrderBy[0].desc==0
  ){
    pIdxInfo->orderByConsumed = 1;
  }
  sqlite3VtabUsesAllSchemas(pIdxInfo);
  return SQLITE_OK;
}

/*
** Open a new dbpagevfs cursor.
*/
static int dbpageOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
219
220
221
222
223
224
225


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







+
+







){
  DbpageCursor *pCsr = (DbpageCursor *)pCursor;
  DbpageTable *pTab = (DbpageTable *)pCursor->pVtab;
  int rc;
  sqlite3 *db = pTab->db;
  Btree *pBt;

  (void)idxStr;
  
  /* Default setting is no rows of result */
  pCsr->pgno = 1; 
  pCsr->mxPgno = 0;

  if( idxNum & 2 ){
    const char *zSchema;
    assert( argc>=1 );
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
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







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








-
+







  switch( i ){
    case 0: {           /* pgno */
      sqlite3_result_int(ctx, pCsr->pgno);
      break;
    }
    case 1: {           /* data */
      DbPage *pDbPage = 0;
      if( pCsr->pgno==((PENDING_BYTE/pCsr->szPage)+1) ){
        /* The pending byte page. Assume it is zeroed out. Attempting to
        ** request this page from the page is an SQLITE_CORRUPT error. */
        sqlite3_result_zeroblob(ctx, pCsr->szPage);
      }else{
      rc = sqlite3PagerGet(pCsr->pPager, pCsr->pgno, (DbPage**)&pDbPage, 0);
      if( rc==SQLITE_OK ){
        sqlite3_result_blob(ctx, sqlite3PagerGetData(pDbPage), pCsr->szPage,
                            SQLITE_TRANSIENT);
      }
      sqlite3PagerUnref(pDbPage);
        rc = sqlite3PagerGet(pCsr->pPager, pCsr->pgno, (DbPage**)&pDbPage, 0);
        if( rc==SQLITE_OK ){
          sqlite3_result_blob(ctx, sqlite3PagerGetData(pDbPage), pCsr->szPage,
              SQLITE_TRANSIENT);
        }
        sqlite3PagerUnref(pDbPage);
      }
      break;
    }
    default: {          /* schema */
      sqlite3 *db = sqlite3_context_db_handle(ctx);
      sqlite3_result_text(ctx, db->aDb[pCsr->iDb].zDbSName, -1, SQLITE_STATIC);
      break;
    }
  }
  return SQLITE_OK;
  return rc;
}

static int dbpageRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
  DbpageCursor *pCsr = (DbpageCursor *)pCursor;
  *pRowid = pCsr->pgno;
  return SQLITE_OK;
}
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
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







+




















-
+













+
+
+
-
-
-
+
+
+
-
-



















+
-
+

-
+

-
+







  char *zErr = 0;
  const char *zSchema;
  int iDb;
  Btree *pBt;
  Pager *pPager;
  int szPage;

  (void)pRowid;
  if( pTab->db->flags & SQLITE_Defensive ){
    zErr = "read-only";
    goto update_fail;
  }
  if( argc==1 ){
    zErr = "cannot delete";
    goto update_fail;
  }
  pgno = sqlite3_value_int(argv[0]);
  if( (Pgno)sqlite3_value_int(argv[1])!=pgno ){
    zErr = "cannot insert";
    goto update_fail;
  }
  zSchema = (const char*)sqlite3_value_text(argv[4]);
  iDb = zSchema ? sqlite3FindDbName(pTab->db, zSchema) : -1;
  if( iDb<0 ){
    zErr = "no such schema";
    goto update_fail;
  }
  pBt = pTab->db->aDb[iDb].pBt;
  if( pgno<1 || pBt==0 || pgno>(int)sqlite3BtreeLastPage(pBt) ){
  if( pgno<1 || pBt==0 || pgno>sqlite3BtreeLastPage(pBt) ){
    zErr = "bad page number";
    goto update_fail;
  }
  szPage = sqlite3BtreeGetPageSize(pBt);
  if( sqlite3_value_type(argv[3])!=SQLITE_BLOB 
   || sqlite3_value_bytes(argv[3])!=szPage
  ){
    zErr = "bad page value";
    goto update_fail;
  }
  pPager = sqlite3BtreePager(pBt);
  rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pDbPage, 0);
  if( rc==SQLITE_OK ){
    const void *pData = sqlite3_value_blob(argv[3]);
    assert( pData!=0 || pTab->db->mallocFailed );
    if( pData
    rc = sqlite3PagerWrite(pDbPage);
    if( rc==SQLITE_OK ){
      memcpy(sqlite3PagerGetData(pDbPage),
     && (rc = sqlite3PagerWrite(pDbPage))==SQLITE_OK
    ){
      memcpy(sqlite3PagerGetData(pDbPage), pData, szPage);
             sqlite3_value_blob(argv[3]),
             szPage);
    }
  }
  sqlite3PagerUnref(pDbPage);
  return rc;

update_fail:
  sqlite3_free(pVtab->zErrMsg);
  pVtab->zErrMsg = sqlite3_mprintf("%s", zErr);
  return SQLITE_ERROR;
}

/* Since we do not know in advance which database files will be
** written by the sqlite_dbpage virtual table, start a write transaction
** on them all.
*/
static int dbpageBegin(sqlite3_vtab *pVtab){
  DbpageTable *pTab = (DbpageTable *)pVtab;
  sqlite3 *db = pTab->db;
  int i;
  int rc = SQLITE_OK;
  for(i=0; i<db->nDb; i++){
  for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
    Btree *pBt = db->aDb[i].pBt;
    if( pBt ) sqlite3BtreeBeginTrans(pBt, 1, 0);
    if( pBt ) rc = sqlite3BtreeBeginTrans(pBt, 1, 0);
  }
  return SQLITE_OK;
  return rc;
}


/*
** Invoke this routine to register the "dbpage" virtual table module
*/
int sqlite3DbpageRegister(sqlite3 *db){

Changes to src/dbstat.c.

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







-
+












+
+
+
+
+
+
+
+
+







**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file contains an implementation of the "dbstat" virtual table.
**
** The dbstat virtual table is used to extract low-level formatting
** The dbstat virtual table is used to extract low-level storage
** information from an SQLite database in order to implement the
** "sqlite3_analyzer" utility.  See the ../tool/spaceanal.tcl script
** for an example implementation.
**
** Additional information is available on the "dbstat.html" page of the
** official SQLite documentation.
*/

#include "sqliteInt.h"   /* Requires access to internal data structures */
#if (defined(SQLITE_ENABLE_DBSTAT_VTAB) || defined(SQLITE_TEST)) \
    && !defined(SQLITE_OMIT_VIRTUALTABLE)

/*
** The pager and btree modules arrange objects in memory so that there are
** always approximately 200 bytes of addressable memory following each page
** buffer. This way small buffer overreads caused by corrupt database pages
** do not cause undefined behaviour. This module pads each page buffer
** by the following number of bytes for the same purpose.
*/
#define DBSTAT_PAGE_PADDING_BYTES 256

/*
** Page paths:
** 
**   The value of the 'path' column describes the path taken from the 
**   root-node of the b-tree structure to each page. The value of the 
**   root-node path is '/'.
**
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
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







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

+





+









+

-
-
-
+
+
+
-








-
+


+

-
+

-
+
+


-
+



+


-

+

-
-
-
+
+
+

-
+


+

-
-
+
+








-
+











+












+
-
+

















-
+







-
+
-
-

+
+
-
+
+
+
+



+
+
+
+







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

+
+
+
-
+
+

















+






-
+







**
**   If the paths are sorted using the BINARY collation sequence, then
**   the overflow pages associated with a cell will appear earlier in the
**   sort-order than its child page:
**
**      '/1c2/000/'               // Left-most child of 451st child of root
*/
#define VTAB_SCHEMA                                                         \
  "CREATE TABLE xx( "                                                       \
  "  name       TEXT,             /* Name of table or index */"             \
  "  path       TEXT,             /* Path to page from root */"             \
  "  pageno     INTEGER,          /* Page number */"                        \
  "  pagetype   TEXT,             /* 'internal', 'leaf' or 'overflow' */"   \
  "  ncell      INTEGER,          /* Cells on page (0 for overflow) */"     \
  "  payload    INTEGER,          /* Bytes of payload on this page */"      \
  "  unused     INTEGER,          /* Bytes of unused space on this page */" \
  "  mx_payload INTEGER,          /* Largest payload size of all cells */"  \
  "  pgoffset   INTEGER,          /* Offset of page in file */"             \
  "  pgsize     INTEGER,          /* Size of the page */"                   \
  "  schema     TEXT HIDDEN       /* Database schema being analyzed */"     \
  ");"

static const char zDbstatSchema[] = 
  "CREATE TABLE x("
  " name       TEXT,"          /*  0 Name of table or index */
  " path       TEXT,"          /*  1 Path to page from root (NULL for agg) */
  " pageno     INTEGER,"       /*  2 Page number (page count for aggregates) */
  " pagetype   TEXT,"          /*  3 'internal', 'leaf', 'overflow', or NULL */
  " ncell      INTEGER,"       /*  4 Cells on page (0 for overflow) */
  " payload    INTEGER,"       /*  5 Bytes of payload on this page */
  " unused     INTEGER,"       /*  6 Bytes of unused space on this page */
  " mx_payload INTEGER,"       /*  7 Largest payload size of all cells */
  " pgoffset   INTEGER,"       /*  8 Offset of page in file (NULL for agg) */
  " pgsize     INTEGER,"       /*  9 Size of the page (sum for aggregate) */
  " schema     TEXT HIDDEN,"   /* 10 Database schema being analyzed */
  " aggregate  BOOLEAN HIDDEN" /* 11 aggregate info for each table */
  ")"
;

/* Forward reference to data structured used in this module */
typedef struct StatTable StatTable;
typedef struct StatCursor StatCursor;
typedef struct StatPage StatPage;
typedef struct StatCell StatCell;

/* Size information for a single cell within a btree page */
struct StatCell {
  int nLocal;                     /* Bytes of local payload */
  u32 iChildPg;                   /* Child node (or 0 if this is a leaf) */
  int nOvfl;                      /* Entries in aOvfl[] */
  u32 *aOvfl;                     /* Array of overflow page numbers */
  int nLastOvfl;                  /* Bytes of payload on final overflow page */
  int iOvfl;                      /* Iterates through aOvfl[] */
};

/* Size information for a single btree page */
struct StatPage {
  u32 iPgno;
  DbPage *pPg;
  int iCell;
  u32 iPgno;                      /* Page number */
  u8 *aPg;                        /* Page buffer from sqlite3_malloc() */
  int iCell;                      /* Current cell */

  char *zPath;                    /* Path to this page */

  /* Variables populated by statDecodePage(): */
  u8 flags;                       /* Copy of flags byte */
  int nCell;                      /* Number of cells on page */
  int nUnused;                    /* Number of unused bytes on page */
  StatCell *aCell;                /* Array of parsed cells */
  u32 iRightChildPg;              /* Right-child page number (or 0) */
  int nMxPayload;                 /* Largest payload of any cell on this page */
  int nMxPayload;                 /* Largest payload of any cell on the page */
};

/* The cursor for scanning the dbstat virtual table */
struct StatCursor {
  sqlite3_vtab_cursor base;
  sqlite3_vtab_cursor base;       /* base class.  MUST BE FIRST! */
  sqlite3_stmt *pStmt;            /* Iterates through set of root pages */
  int isEof;                      /* After pStmt has returned SQLITE_DONE */
  u8 isEof;                       /* After pStmt has returned SQLITE_DONE */
  u8 isAgg;                       /* Aggregate results for each table */
  int iDb;                        /* Schema used for this query */

  StatPage aPage[32];
  StatPage aPage[32];             /* Pages in path to current page */
  int iPage;                      /* Current entry in aPage[] */

  /* Values to return. */
  u32 iPageno;                    /* Value of 'pageno' column */
  char *zName;                    /* Value of 'name' column */
  char *zPath;                    /* Value of 'path' column */
  u32 iPageno;                    /* Value of 'pageno' column */
  char *zPagetype;                /* Value of 'pagetype' column */
  int nPage;                      /* Number of pages in current btree */
  int nCell;                      /* Value of 'ncell' column */
  int nPayload;                   /* Value of 'payload' column */
  int nUnused;                    /* Value of 'unused' column */
  int nMxPayload;                 /* Value of 'mx_payload' column */
  int nMxPayload;                 /* Value of 'mx_payload' column */
  i64 nUnused;                    /* Value of 'unused' column */
  i64 nPayload;                   /* Value of 'payload' column */
  i64 iOffset;                    /* Value of 'pgOffset' column */
  int szPage;                     /* Value of 'pgSize' column */
  i64 szPage;                     /* Value of 'pgSize' column */
};

/* An instance of the DBSTAT virtual table */
struct StatTable {
  sqlite3_vtab base;
  sqlite3 *db;
  sqlite3_vtab base;              /* base class.  MUST BE FIRST! */
  sqlite3 *db;                    /* Database connection that owns this vtab */
  int iDb;                        /* Index of database to analyze */
};

#ifndef get2byte
# define get2byte(x)   ((x)[0]<<8 | (x)[1])
#endif

/*
** Connect to or create a statvfs virtual table.
** Connect to or create a new DBSTAT virtual table.
*/
static int statConnect(
  sqlite3 *db,
  void *pAux,
  int argc, const char *const*argv,
  sqlite3_vtab **ppVtab,
  char **pzErr
){
  StatTable *pTab = 0;
  int rc = SQLITE_OK;
  int iDb;
  (void)pAux;

  if( argc>=4 ){
    Token nm;
    sqlite3TokenInit(&nm, (char*)argv[3]);
    iDb = sqlite3FindDb(db, &nm);
    if( iDb<0 ){
      *pzErr = sqlite3_mprintf("no such database: %s", argv[3]);
      return SQLITE_ERROR;
    }
  }else{
    iDb = 0;
  }
  sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY);
  rc = sqlite3_declare_vtab(db, VTAB_SCHEMA);
  rc = sqlite3_declare_vtab(db, zDbstatSchema);
  if( rc==SQLITE_OK ){
    pTab = (StatTable *)sqlite3_malloc64(sizeof(StatTable));
    if( pTab==0 ) rc = SQLITE_NOMEM_BKPT;
  }

  assert( rc==SQLITE_OK || pTab==0 );
  if( rc==SQLITE_OK ){
    memset(pTab, 0, sizeof(StatTable));
    pTab->db = db;
    pTab->iDb = iDb;
  }

  *ppVtab = (sqlite3_vtab*)pTab;
  return rc;
}

/*
** Disconnect from or destroy a statvfs virtual table.
** Disconnect from or destroy the DBSTAT virtual table.
*/
static int statDisconnect(sqlite3_vtab *pVtab){
  sqlite3_free(pVtab);
  return SQLITE_OK;
}

/*
** There is no "best-index". This virtual table always does a linear
** Compute the best query strategy and return the result in idxNum.
** scan.  However, a schema=? constraint should cause this table to
** operate on a different database schema, so check for it.
**
**   idxNum-Bit        Meaning
**   ----------        ----------------------------------------------
** idxNum is normally 0, but will be 1 if a schema=? constraint exists.
**      0x01           There is a schema=? term in the WHERE clause
**      0x02           There is a name=? term in the WHERE clause
**      0x04           There is an aggregate=? term in the WHERE clause
**      0x08           Output should be ordered by name and path
*/
static int statBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
  int i;
  int iSchema = -1;
  int iName = -1;
  int iAgg = -1;
  (void)tab;

  /* Look for a valid schema=? constraint.  If found, change the idxNum to
  ** 1 and request the value of that constraint be sent to xFilter.  And
  ** lower the cost estimate to encourage the constrained version to be
  ** used.
  */
  for(i=0; i<pIdxInfo->nConstraint; i++){
    if( pIdxInfo->aConstraint[i].iColumn!=10 ) continue;
    if( pIdxInfo->aConstraint[i].usable==0 ) return SQLITE_CONSTRAINT;
    if( pIdxInfo->aConstraint[i].op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
    pIdxInfo->idxNum = 1;
    pIdxInfo->estimatedCost = 1.0;
    pIdxInfo->aConstraintUsage[i].argvIndex = 1;
    pIdxInfo->aConstraintUsage[i].omit = 1;
    if( pIdxInfo->aConstraint[i].op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
    if( pIdxInfo->aConstraint[i].usable==0 ){
      /* Force DBSTAT table should always be the right-most table in a join */
      return SQLITE_CONSTRAINT;
    }
    switch( pIdxInfo->aConstraint[i].iColumn ){
      case 0: {    /* name */
        iName = i;
        break;
      }
      case 10: {   /* schema */
        iSchema = i;
        break;
      }
      case 11: {   /* aggregate */
        iAgg = i;
        break;
      }
    }
  }
  i = 0;
  if( iSchema>=0 ){
    pIdxInfo->aConstraintUsage[iSchema].argvIndex = ++i;
    pIdxInfo->aConstraintUsage[iSchema].omit = 1;
    pIdxInfo->idxNum |= 0x01;
  }
  if( iName>=0 ){
    pIdxInfo->aConstraintUsage[iName].argvIndex = ++i;
    break;
    pIdxInfo->idxNum |= 0x02;
  }
  if( iAgg>=0 ){
    pIdxInfo->aConstraintUsage[iAgg].argvIndex = ++i;
    pIdxInfo->idxNum |= 0x04;

  }
  pIdxInfo->estimatedCost = 1.0;

  /* Records are always returned in ascending order of (name, path). 
  ** If this will satisfy the client, set the orderByConsumed flag so that 
  ** SQLite does not do an external sort.
  */
  if( ( pIdxInfo->nOrderBy==1
     && pIdxInfo->aOrderBy[0].iColumn==0
     && pIdxInfo->aOrderBy[0].desc==0
     ) ||
      ( pIdxInfo->nOrderBy==2
     && pIdxInfo->aOrderBy[0].iColumn==0
     && pIdxInfo->aOrderBy[0].desc==0
     && pIdxInfo->aOrderBy[1].iColumn==1
     && pIdxInfo->aOrderBy[1].desc==0
     )
  ){
    pIdxInfo->orderByConsumed = 1;
    pIdxInfo->idxNum |= 0x08;
  }

  return SQLITE_OK;
}

/*
** Open a new statvfs cursor.
** Open a new DBSTAT cursor.
*/
static int statOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
  StatTable *pTab = (StatTable *)pVTab;
  StatCursor *pCsr;

  pCsr = (StatCursor *)sqlite3_malloc64(sizeof(StatCursor));
  if( pCsr==0 ){
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
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







+

-


+




+
-
+
+
+


+
+

+






+
+
+
+
+
+
+
+
+
+

-
+









+
+
+
+
+
-
+


-
+
-















-
+


+
+
+







-
+







    sqlite3_free(p->aCell);
  }
  p->nCell = 0;
  p->aCell = 0;
}

static void statClearPage(StatPage *p){
  u8 *aPg = p->aPg;
  statClearCells(p);
  sqlite3PagerUnref(p->pPg);
  sqlite3_free(p->zPath);
  memset(p, 0, sizeof(StatPage));
  p->aPg = aPg;
}

static void statResetCsr(StatCursor *pCsr){
  int i;
  /* In some circumstances, specifically if an OOM has occurred, the call
  sqlite3_reset(pCsr->pStmt);
  ** to sqlite3_reset() may cause the pager to be reset (emptied). It is
  ** important that statClearPage() is called to free any page refs before
  ** this happens. dbsqlfuzz 9ed3e4e3816219d3509d711636c38542bf3f40b1. */
  for(i=0; i<ArraySize(pCsr->aPage); i++){
    statClearPage(&pCsr->aPage[i]);
    sqlite3_free(pCsr->aPage[i].aPg);
    pCsr->aPage[i].aPg = 0;
  }
  sqlite3_reset(pCsr->pStmt);
  pCsr->iPage = 0;
  sqlite3_free(pCsr->zPath);
  pCsr->zPath = 0;
  pCsr->isEof = 0;
}

/* Resize the space-used counters inside of the cursor */
static void statResetCounts(StatCursor *pCsr){
  pCsr->nCell = 0;
  pCsr->nMxPayload = 0;
  pCsr->nUnused = 0;
  pCsr->nPayload = 0;
  pCsr->szPage = 0;
  pCsr->nPage = 0;
}

/*
** Close a statvfs cursor.
** Close a DBSTAT cursor.
*/
static int statClose(sqlite3_vtab_cursor *pCursor){
  StatCursor *pCsr = (StatCursor *)pCursor;
  statResetCsr(pCsr);
  sqlite3_finalize(pCsr->pStmt);
  sqlite3_free(pCsr);
  return SQLITE_OK;
}

/*
** For a single cell on a btree page, compute the number of bytes of
** content (payload) stored on that page.  That is to say, compute the
** number of bytes of content not found on overflow pages.
*/
static void getLocalPayload(
static int getLocalPayload(
  int nUsable,                    /* Usable bytes per page */
  u8 flags,                       /* Page flags */
  int nTotal,                     /* Total record (payload) size */
  int nTotal                      /* Total record (payload) size */
  int *pnLocal                    /* OUT: Bytes stored locally */
){
  int nLocal;
  int nMinLocal;
  int nMaxLocal;
 
  if( flags==0x0D ){              /* Table leaf node */
    nMinLocal = (nUsable - 12) * 32 / 255 - 23;
    nMaxLocal = nUsable - 35;
  }else{                          /* Index interior and leaf nodes */
    nMinLocal = (nUsable - 12) * 32 / 255 - 23;
    nMaxLocal = (nUsable - 12) * 64 / 255 - 23;
  }

  nLocal = nMinLocal + (nTotal - nMinLocal) % (nUsable - 4);
  if( nLocal>nMaxLocal ) nLocal = nMinLocal;
  *pnLocal = nLocal;
  return nLocal;
}

/* Populate the StatPage object with information about the all
** cells found on the page currently under analysis.
*/
static int statDecodePage(Btree *pBt, StatPage *p){
  int nUnused;
  int iOff;
  int nHdr;
  int isLeaf;
  int szPage;

  u8 *aData = sqlite3PagerGetData(p->pPg);
  u8 *aData = p->aPg;
  u8 *aHdr = &aData[p->iPgno==1 ? 100 : 0];

  p->flags = aHdr[0];
  if( p->flags==0x0A || p->flags==0x0D ){
    isLeaf = 1;
    nHdr = 8;
  }else if( p->flags==0x05 || p->flags==0x02 ){
383
384
385
386
387
388
389
390

391
392
393
394
395
396
397

398


399
400
401
402
403
404
405
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







-
+







+
-
+
+







        int nLocal;               /* Bytes of payload stored locally */
        iOff += getVarint32(&aData[iOff], nPayload);
        if( p->flags==0x0D ){
          u64 dummy;
          iOff += sqlite3GetVarint(&aData[iOff], &dummy);
        }
        if( nPayload>(u32)p->nMxPayload ) p->nMxPayload = nPayload;
        getLocalPayload(nUsable, p->flags, nPayload, &nLocal);
        nLocal = getLocalPayload(nUsable, p->flags, nPayload);
        if( nLocal<0 ) goto statPageIsCorrupt;
        pCell->nLocal = nLocal;
        assert( nPayload>=(u32)nLocal );
        assert( nLocal<=(nUsable-35) );
        if( nPayload>(u32)nLocal ){
          int j;
          int nOvfl = ((nPayload - nLocal) + nUsable-4 - 1) / (nUsable - 4);
          if( iOff+nLocal+4>nUsable || nPayload>0x7fffffff ){
          if( iOff+nLocal>nUsable ) goto statPageIsCorrupt;
            goto statPageIsCorrupt;
          }
          pCell->nLastOvfl = (nPayload-nLocal) - (nOvfl-1) * (nUsable-4);
          pCell->nOvfl = nOvfl;
          pCell->aOvfl = sqlite3_malloc64(sizeof(u32)*nOvfl);
          if( pCell->aOvfl==0 ) return SQLITE_NOMEM_BKPT;
          pCell->aOvfl[0] = sqlite3Get4byte(&aData[iOff+nLocal]);
          for(j=1; j<nOvfl; j++){
            int rc;
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
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
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







-
-
-
-
-
-
+
+





-
+
+
+
+
+

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



-
+
+
+














-
+
+
+









-
+


+
-
+
+
+

-
+





-
+
-

-
+


-
-
+
+




-
-
-
-
-
+
+
-
-
-

-
-
+

-
-
+
+

+

-
-
+
+
+
+
+
+
+
+
+







-

+
+
+
+
+



+
+
+
+







-
+
+

+
-
+
-
-
+
+
+







static void statSizeAndOffset(StatCursor *pCsr){
  StatTable *pTab = (StatTable *)((sqlite3_vtab_cursor *)pCsr)->pVtab;
  Btree *pBt = pTab->db->aDb[pTab->iDb].pBt;
  Pager *pPager = sqlite3BtreePager(pBt);
  sqlite3_file *fd;
  sqlite3_int64 x[2];

  /* The default page size and offset */
  pCsr->szPage = sqlite3BtreeGetPageSize(pBt);
  pCsr->iOffset = (i64)pCsr->szPage * (pCsr->iPageno - 1);

  /* If connected to a ZIPVFS backend, override the page size and
  ** offset with actual values obtained from ZIPVFS.
  /* If connected to a ZIPVFS backend, find the page size and
  ** offset from ZIPVFS.
  */
  fd = sqlite3PagerFile(pPager);
  x[0] = pCsr->iPageno;
  if( sqlite3OsFileControl(fd, 230440, &x)==SQLITE_OK ){
    pCsr->iOffset = x[0];
    pCsr->szPage = (int)x[1];
    pCsr->szPage += x[1];
  }else{
    /* Not ZIPVFS: The default page size and offset */
    pCsr->szPage += sqlite3BtreeGetPageSize(pBt);
    pCsr->iOffset = (i64)pCsr->szPage * (pCsr->iPageno - 1);
  }
}

/*
** Load a copy of the page data for page iPg into the buffer belonging
** to page object pPg. Allocate the buffer if necessary. Return SQLITE_OK
** if successful, or an SQLite error code otherwise.
*/
static int statGetPage(
  Btree *pBt,                     /* Load page from this b-tree */
  u32 iPg,                        /* Page number to load */
  StatPage *pPg                   /* Load page into this object */
){
  int pgsz = sqlite3BtreeGetPageSize(pBt);
  DbPage *pDbPage = 0;
  int rc;

  if( pPg->aPg==0 ){
    pPg->aPg = (u8*)sqlite3_malloc(pgsz + DBSTAT_PAGE_PADDING_BYTES);
    if( pPg->aPg==0 ){
      return SQLITE_NOMEM_BKPT;
    }
    memset(&pPg->aPg[pgsz], 0, DBSTAT_PAGE_PADDING_BYTES);
  }

  rc = sqlite3PagerGet(sqlite3BtreePager(pBt), iPg, &pDbPage, 0);
  if( rc==SQLITE_OK ){
    const u8 *a = sqlite3PagerGetData(pDbPage);
    memcpy(pPg->aPg, a, pgsz);
    sqlite3PagerUnref(pDbPage);
  }

  return rc;
}

/*
** Move a statvfs cursor to the next entry in the file.
** Move a DBSTAT cursor to the next entry.  Normally, the next
** entry will be the next page, but in aggregated mode (pCsr->isAgg!=0),
** the next entry is the next btree.
*/
static int statNext(sqlite3_vtab_cursor *pCursor){
  int rc;
  int nPayload;
  char *z;
  StatCursor *pCsr = (StatCursor *)pCursor;
  StatTable *pTab = (StatTable *)pCursor->pVtab;
  Btree *pBt = pTab->db->aDb[pCsr->iDb].pBt;
  Pager *pPager = sqlite3BtreePager(pBt);

  sqlite3_free(pCsr->zPath);
  pCsr->zPath = 0;

statNextRestart:
  if( pCsr->aPage[0].pPg==0 ){
  if( pCsr->iPage<0 ){
    /* Start measuring space on the next btree */
    statResetCounts(pCsr);
    rc = sqlite3_step(pCsr->pStmt);
    if( rc==SQLITE_ROW ){
      int nPage;
      u32 iRoot = (u32)sqlite3_column_int64(pCsr->pStmt, 1);
      sqlite3PagerPagecount(pPager, &nPage);
      if( nPage==0 ){
        pCsr->isEof = 1;
        return sqlite3_reset(pCsr->pStmt);
      }
      rc = sqlite3PagerGet(pPager, iRoot, &pCsr->aPage[0].pPg, 0);
      rc = statGetPage(pBt, iRoot, &pCsr->aPage[0]);
      pCsr->aPage[0].iPgno = iRoot;
      pCsr->aPage[0].iCell = 0;
      if( !pCsr->isAgg ){
      pCsr->aPage[0].zPath = z = sqlite3_mprintf("/");
        pCsr->aPage[0].zPath = z = sqlite3_mprintf("/");
        if( z==0 ) rc = SQLITE_NOMEM_BKPT;
      }
      pCsr->iPage = 0;
      if( z==0 ) rc = SQLITE_NOMEM_BKPT;
      pCsr->nPage = 1;
    }else{
      pCsr->isEof = 1;
      return sqlite3_reset(pCsr->pStmt);
    }
  }else{

    /* Continue analyzing the btree previously started */
    /* Page p itself has already been visited. */
    StatPage *p = &pCsr->aPage[pCsr->iPage];

    if( !pCsr->isAgg ) statResetCounts(pCsr);
    while( p->iCell<p->nCell ){
      StatCell *pCell = &p->aCell[p->iCell];
      if( pCell->iOvfl<pCell->nOvfl ){
        int nUsable;
      while( pCell->iOvfl<pCell->nOvfl ){
        int nUsable, iOvfl;
        sqlite3BtreeEnter(pBt);
        nUsable = sqlite3BtreeGetPageSize(pBt) - 
                        sqlite3BtreeGetReserveNoMutex(pBt);
        sqlite3BtreeLeave(pBt);
        pCsr->zName = (char *)sqlite3_column_text(pCsr->pStmt, 0);
        pCsr->iPageno = pCell->aOvfl[pCell->iOvfl];
        pCsr->zPagetype = "overflow";
        pCsr->nCell = 0;
        pCsr->nMxPayload = 0;
        pCsr->nPage++;
        statSizeAndOffset(pCsr);
        pCsr->zPath = z = sqlite3_mprintf(
            "%s%.3x+%.6x", p->zPath, p->iCell, pCell->iOvfl
        );
        if( pCell->iOvfl<pCell->nOvfl-1 ){
          pCsr->nUnused = 0;
          pCsr->nPayload = nUsable - 4;
          pCsr->nPayload += nUsable - 4;
        }else{
          pCsr->nPayload = pCell->nLastOvfl;
          pCsr->nUnused = nUsable - 4 - pCsr->nPayload;
          pCsr->nPayload += pCell->nLastOvfl;
          pCsr->nUnused += nUsable - 4 - pCell->nLastOvfl;
        }
        iOvfl = pCell->iOvfl;
        pCell->iOvfl++;
        statSizeAndOffset(pCsr);
        return z==0 ? SQLITE_NOMEM_BKPT : SQLITE_OK;
        if( !pCsr->isAgg ){
          pCsr->zName = (char *)sqlite3_column_text(pCsr->pStmt, 0);
          pCsr->iPageno = pCell->aOvfl[iOvfl];
          pCsr->zPagetype = "overflow";
          pCsr->zPath = z = sqlite3_mprintf(
              "%s%.3x+%.6x", p->zPath, p->iCell, iOvfl
          );
          return z==0 ? SQLITE_NOMEM_BKPT : SQLITE_OK;
        }
      }
      if( p->iRightChildPg ) break;
      p->iCell++;
    }

    if( !p->iRightChildPg || p->iCell>p->nCell ){
      statClearPage(p);
      if( pCsr->iPage==0 ) return statNext(pCursor);
      pCsr->iPage--;
      if( pCsr->isAgg && pCsr->iPage<0 ){
        /* label-statNext-done:  When computing aggregate space usage over
        ** an entire btree, this is the exit point from this function */
        return SQLITE_OK;
      }
      goto statNextRestart; /* Tail recursion */
    }
    pCsr->iPage++;
    if( pCsr->iPage>=ArraySize(pCsr->aPage) ){
      statResetCsr(pCsr);
      return SQLITE_CORRUPT_BKPT;
    }
    assert( p==&pCsr->aPage[pCsr->iPage-1] );

    if( p->iCell==p->nCell ){
      p[1].iPgno = p->iRightChildPg;
    }else{
      p[1].iPgno = p->aCell[p->iCell].iChildPg;
    }
    rc = sqlite3PagerGet(pPager, p[1].iPgno, &p[1].pPg, 0);
    rc = statGetPage(pBt, p[1].iPgno, &p[1]);
    pCsr->nPage++;
    p[1].iCell = 0;
    if( !pCsr->isAgg ){
    p[1].zPath = z = sqlite3_mprintf("%s%.3x/", p->zPath, p->iCell);
      p[1].zPath = z = sqlite3_mprintf("%s%.3x/", p->zPath, p->iCell);
    p->iCell++;
    if( z==0 ) rc = SQLITE_NOMEM_BKPT;
      if( z==0 ) rc = SQLITE_NOMEM_BKPT;
    }
    p->iCell++;
  }


  /* Populate the StatCursor fields with the values to be returned
  ** by the xColumn() and xRowid() methods.
  */
  if( rc==SQLITE_OK ){
568
569
570
571
572
573
574
575
576
577
578
579







580
581
582
583
584






585
586
587
588
589
590
591
592
593
594
595




596
597
598
599
600
601
602

603
604
605






606



607
608



609
610
611

612
613


614
615
616
617
618
619
620









621
622
623
624
625
626
627
















628
629
630
631
632
633
634
635

636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651

652


653
654



655


656
657

658


659
660
661

662
663
664

665
666
667

668
669
670

671
672

673


674
675
676

677
678

679
680
681
682




683
684
685
686
687
688
689
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
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







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




-
+
+
+
+
+
+











+
+
+
+







+
-
-
-
+
+
+
+
+
+

+
+
+
-
-
+
+
+


-
+
-
-
+
+




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








+
















+
-
+
+


+
+
+
-
+
+


+
-
+
+


-
+


-
+


-
+


-
+


+
-
+
+


-
+

-
+




+
+
+
+







        case 0x0A:             /* index leaf */
          pCsr->zPagetype = "leaf";
          break;
        default:
          pCsr->zPagetype = "corrupted";
          break;
      }
      pCsr->nCell = p->nCell;
      pCsr->nUnused = p->nUnused;
      pCsr->nMxPayload = p->nMxPayload;
      pCsr->zPath = z = sqlite3_mprintf("%s", p->zPath);
      if( z==0 ) rc = SQLITE_NOMEM_BKPT;
      pCsr->nCell += p->nCell;
      pCsr->nUnused += p->nUnused;
      if( p->nMxPayload>pCsr->nMxPayload ) pCsr->nMxPayload = p->nMxPayload;
      if( !pCsr->isAgg ){
        pCsr->zPath = z = sqlite3_mprintf("%s", p->zPath);
        if( z==0 ) rc = SQLITE_NOMEM_BKPT;
      }
      nPayload = 0;
      for(i=0; i<p->nCell; i++){
        nPayload += p->aCell[i].nLocal;
      }
      pCsr->nPayload = nPayload;
      pCsr->nPayload += nPayload;

      /* If computing aggregate space usage by btree, continue with the
      ** next page.  The loop will exit via the return at label-statNext-done
      */
      if( pCsr->isAgg ) goto statNextRestart;
    }
  }

  return rc;
}

static int statEof(sqlite3_vtab_cursor *pCursor){
  StatCursor *pCsr = (StatCursor *)pCursor;
  return pCsr->isEof;
}

/* Initialize a cursor according to the query plan idxNum using the
** arguments in argv[0].  See statBestIndex() for a description of the
** meaning of the bits in idxNum.
*/
static int statFilter(
  sqlite3_vtab_cursor *pCursor, 
  int idxNum, const char *idxStr,
  int argc, sqlite3_value **argv
){
  StatCursor *pCsr = (StatCursor *)pCursor;
  StatTable *pTab = (StatTable*)(pCursor->pVtab);
  sqlite3_str *pSql;      /* Query of btrees to analyze */
  char *zSql;
  int rc = SQLITE_OK;
  char *zMaster;
  char *zSql;             /* String value of pSql */
  int iArg = 0;           /* Count of argv[] parameters used so far */
  int rc = SQLITE_OK;     /* Result of this operation */
  const char *zName = 0;  /* Only provide analysis of this table */
  (void)argc;
  (void)idxStr;

  statResetCsr(pCsr);
  sqlite3_finalize(pCsr->pStmt);
  pCsr->pStmt = 0;
  if( idxNum==1 ){
    const char *zDbase = (const char*)sqlite3_value_text(argv[0]);
  if( idxNum & 0x01 ){
    /* schema=? constraint is present.  Get its value */
    const char *zDbase = (const char*)sqlite3_value_text(argv[iArg++]);
    pCsr->iDb = sqlite3FindDbName(pTab->db, zDbase);
    if( pCsr->iDb<0 ){
      sqlite3_free(pCursor->pVtab->zErrMsg);
      pCsr->iDb = 0;
      pCursor->pVtab->zErrMsg = sqlite3_mprintf("no such schema: %s", zDbase);
      return pCursor->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM_BKPT;
      pCsr->isEof = 1;
      return SQLITE_OK;
    }
  }else{
    pCsr->iDb = pTab->iDb;
  }
  statResetCsr(pCsr);
  sqlite3_finalize(pCsr->pStmt);
  pCsr->pStmt = 0;
  if( idxNum & 0x02 ){
    /* name=? constraint is present */
    zName = (const char*)sqlite3_value_text(argv[iArg++]);
  }
  if( idxNum & 0x04 ){
    /* aggregate=? constraint is present */
    pCsr->isAgg = sqlite3_value_double(argv[iArg++])!=0.0;
  }else{
    pCsr->isAgg = 0;
  zMaster = pCsr->iDb==1 ? "sqlite_temp_master" : "sqlite_master";
  zSql = sqlite3_mprintf(
      "SELECT 'sqlite_master' AS name, 1 AS rootpage, 'table' AS type"
      "  UNION ALL  "
      "SELECT name, rootpage, type"
      "  FROM \"%w\".%s WHERE rootpage!=0"
      "  ORDER BY name", pTab->db->aDb[pCsr->iDb].zDbSName, zMaster);
  }
  pSql = sqlite3_str_new(pTab->db);
  sqlite3_str_appendf(pSql,
      "SELECT * FROM ("
        "SELECT 'sqlite_schema' AS name,1 AS rootpage,'table' AS type"
        " UNION ALL "
        "SELECT name,rootpage,type"
        " FROM \"%w\".sqlite_schema WHERE rootpage!=0)",
      pTab->db->aDb[pCsr->iDb].zDbSName);
  if( zName ){
    sqlite3_str_appendf(pSql, "WHERE name=%Q", zName);
  }
  if( idxNum & 0x08 ){
    sqlite3_str_appendf(pSql, " ORDER BY name");
  }
  zSql = sqlite3_str_finish(pSql);
  if( zSql==0 ){
    return SQLITE_NOMEM_BKPT;
  }else{
    rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pStmt, 0);
    sqlite3_free(zSql);
  }

  if( rc==SQLITE_OK ){
    pCsr->iPage = -1;
    rc = statNext(pCursor);
  }
  return rc;
}

static int statColumn(
  sqlite3_vtab_cursor *pCursor, 
  sqlite3_context *ctx, 
  int i
){
  StatCursor *pCsr = (StatCursor *)pCursor;
  switch( i ){
    case 0:            /* name */
      sqlite3_result_text(ctx, pCsr->zName, -1, SQLITE_TRANSIENT);
      break;
    case 1:            /* path */
      if( !pCsr->isAgg ){
      sqlite3_result_text(ctx, pCsr->zPath, -1, SQLITE_TRANSIENT);
        sqlite3_result_text(ctx, pCsr->zPath, -1, SQLITE_TRANSIENT);
      }
      break;
    case 2:            /* pageno */
      if( pCsr->isAgg ){
        sqlite3_result_int64(ctx, pCsr->nPage);
      }else{
      sqlite3_result_int64(ctx, pCsr->iPageno);
        sqlite3_result_int64(ctx, pCsr->iPageno);
      }
      break;
    case 3:            /* pagetype */
      if( !pCsr->isAgg ){
      sqlite3_result_text(ctx, pCsr->zPagetype, -1, SQLITE_STATIC);
        sqlite3_result_text(ctx, pCsr->zPagetype, -1, SQLITE_STATIC);
      }
      break;
    case 4:            /* ncell */
      sqlite3_result_int(ctx, pCsr->nCell);
      sqlite3_result_int64(ctx, pCsr->nCell);
      break;
    case 5:            /* payload */
      sqlite3_result_int(ctx, pCsr->nPayload);
      sqlite3_result_int64(ctx, pCsr->nPayload);
      break;
    case 6:            /* unused */
      sqlite3_result_int(ctx, pCsr->nUnused);
      sqlite3_result_int64(ctx, pCsr->nUnused);
      break;
    case 7:            /* mx_payload */
      sqlite3_result_int(ctx, pCsr->nMxPayload);
      sqlite3_result_int64(ctx, pCsr->nMxPayload);
      break;
    case 8:            /* pgoffset */
      if( !pCsr->isAgg ){
      sqlite3_result_int64(ctx, pCsr->iOffset);
        sqlite3_result_int64(ctx, pCsr->iOffset);
      }
      break;
    case 9:            /* pgsize */
      sqlite3_result_int(ctx, pCsr->szPage);
      sqlite3_result_int64(ctx, pCsr->szPage);
      break;
    default: {          /* schema */
    case 10: {         /* schema */
      sqlite3 *db = sqlite3_context_db_handle(ctx);
      int iDb = pCsr->iDb;
      sqlite3_result_text(ctx, db->aDb[iDb].zDbSName, -1, SQLITE_STATIC);
      break;
    }
    default: {         /* aggregate */
      sqlite3_result_int(ctx, pCsr->isAgg);
      break;
    }
  }
  return SQLITE_OK;
}

static int statRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
  StatCursor *pCsr = (StatCursor *)pCursor;

Changes to src/delete.c.

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







-
+

-
+





-
-
-
+
+
+



+
+
+
+
+
+
+
+
+
+








+
+
+
+
-
+



-
+



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



-
+







-
+
-
-
-
-



-
-
-
+
+
+
+
+







-
+







** The following fields are initialized appropriate in pSrc:
**
**    pSrc->a[0].pTab       Pointer to the Table object
**    pSrc->a[0].pIndex     Pointer to the INDEXED BY index, if there is one
**
*/
Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
  struct SrcList_item *pItem = pSrc->a;
  SrcItem *pItem = pSrc->a;
  Table *pTab;
  assert( pItem && pSrc->nSrc==1 );
  assert( pItem && pSrc->nSrc>=1 );
  pTab = sqlite3LocateTableItem(pParse, 0, pItem);
  sqlite3DeleteTable(pParse->db, pItem->pTab);
  pItem->pTab = pTab;
  if( pTab ){
    pTab->nTabRef++;
  }
  if( sqlite3IndexedByLookup(pParse, pItem) ){
    pTab = 0;
    if( pItem->fg.isIndexedBy && sqlite3IndexedByLookup(pParse, pItem) ){
      pTab = 0;
    }
  }
  return pTab;
}

/* Generate byte-code that will report the number of rows modified 
** by a DELETE, INSERT, or UPDATE statement.
*/
void sqlite3CodeChangeCount(Vdbe *v, int regCounter, const char *zColName){
  sqlite3VdbeAddOp0(v, OP_FkCheck);
  sqlite3VdbeAddOp2(v, OP_ResultRow, regCounter, 1);
  sqlite3VdbeSetNumCols(v, 1);
  sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zColName, SQLITE_STATIC);
}

/* Return true if table pTab is read-only.
**
** A table is read-only if any of the following are true:
**
**   1) It is a virtual table and no implementation of the xUpdate method
**      has been provided
**
**   2) A trigger is currently being coded and the table is a virtual table
**      that is SQLITE_VTAB_DIRECTONLY or if PRAGMA trusted_schema=OFF and
**      the table is not SQLITE_VTAB_INNOCUOUS.
**
**   2) It is a system table (i.e. sqlite_master), this call is not
**   3) It is a system table (i.e. sqlite_schema), this call is not
**      part of a nested parse and writable_schema pragma has not 
**      been specified
**
**   3) The table is a shadow table, the database connection is in
**   4) The table is a shadow table, the database connection is in
**      defensive mode, and the current sqlite3_prepare()
**      is for a top-level SQL statement.
*/
static int vtabIsReadOnly(Parse *pParse, Table *pTab){
  if( sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0 ){
    return 1;
  }

  /* Within triggers:
  **   *  Do not allow DELETE, INSERT, or UPDATE of SQLITE_VTAB_DIRECTONLY
  **      virtual tables
  **   *  Only allow DELETE, INSERT, or UPDATE of non-SQLITE_VTAB_INNOCUOUS
  **      virtual tables if PRAGMA trusted_schema=ON.
  */
  if( pParse->pToplevel!=0
   && pTab->u.vtab.p->eVtabRisk > 
           ((pParse->db->flags & SQLITE_TrustedSchema)!=0)
  ){
    sqlite3ErrorMsg(pParse, "unsafe use of virtual table \"%s\"",
      pTab->zName);
  }
  return 0;
}
static int tabIsReadOnly(Parse *pParse, Table *pTab){
  sqlite3 *db;
  if( IsVirtual(pTab) ){
    return sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0;
    return vtabIsReadOnly(pParse, pTab);
  }
  if( (pTab->tabFlags & (TF_Readonly|TF_Shadow))==0 ) return 0;
  db = pParse->db;
  if( (pTab->tabFlags & TF_Readonly)!=0 ){
    return sqlite3WritableSchema(db)==0 && pParse->nested==0;
  }
  assert( pTab->tabFlags & TF_Shadow );
  return (db->flags & SQLITE_Defensive)!=0 
  return sqlite3ReadOnlyShadowTables(db);
#ifndef SQLITE_OMIT_VIRTUALTABLE
          && db->pVtabCtx==0
#endif
          && db->nVdbeExec==0;
}

/*
** Check to make sure the given table is writable.  If it is not
** writable, generate an error message and return 1.  If it is
** writable return 0;
** Check to make sure the given table is writable. 
**
** If pTab is not writable  ->  generate an error message and return 1.
** If pTab is writable but other errors have occurred -> return 1.
** If pTab is writable and no prior errors -> return 0;
*/
int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
  if( tabIsReadOnly(pParse, pTab) ){
    sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName);
    return 1;
  }
#ifndef SQLITE_OMIT_VIEW
  if( !viewOk && pTab->pSelect ){
  if( !viewOk && IsView(pTab) ){
    sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName);
    return 1;
  }
#endif
  return 0;
}

113
114
115
116
117
118
119
120

121
122
123
124
125
126


127
128
129
130
131
132
133
145
146
147
148
149
150
151

152
153
154
155
156


157
158
159
160
161
162
163
164
165







-
+




-
-
+
+







){
  SelectDest dest;
  Select *pSel;
  SrcList *pFrom;
  sqlite3 *db = pParse->db;
  int iDb = sqlite3SchemaToIndex(db, pView->pSchema);
  pWhere = sqlite3ExprDup(db, pWhere, 0);
  pFrom = sqlite3SrcListAppend(db, 0, 0, 0);
  pFrom = sqlite3SrcListAppend(pParse, 0, 0, 0);
  if( pFrom ){
    assert( pFrom->nSrc==1 );
    pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName);
    pFrom->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName);
    assert( pFrom->a[0].pOn==0 );
    assert( pFrom->a[0].pUsing==0 );
    assert( pFrom->a[0].fg.isUsing==0 );
    assert( pFrom->a[0].u3.pOn==0 );
  }
  pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, pOrderBy, 
                          SF_IncludeHidden, pLimit);
  sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
  sqlite3Select(pParse, pSel, &dest);
  sqlite3SelectDelete(db, pSel);
}
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
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







-
+





-
+












-
+

+
+
-
+
+
+
+
+
+







    pLhs = sqlite3PExpr(pParse, TK_ROW, 0, 0);
    pEList = sqlite3ExprListAppend(
        pParse, 0, sqlite3PExpr(pParse, TK_ROW, 0, 0)
    );
  }else{
    Index *pPk = sqlite3PrimaryKeyIndex(pTab);
    if( pPk->nKeyCol==1 ){
      const char *zName = pTab->aCol[pPk->aiColumn[0]].zName;
      const char *zName = pTab->aCol[pPk->aiColumn[0]].zCnName;
      pLhs = sqlite3Expr(db, TK_ID, zName);
      pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ID, zName));
    }else{
      int i;
      for(i=0; i<pPk->nKeyCol; i++){
        Expr *p = sqlite3Expr(db, TK_ID, pTab->aCol[pPk->aiColumn[i]].zName);
        Expr *p = sqlite3Expr(db, TK_ID, pTab->aCol[pPk->aiColumn[i]].zCnName);
        pEList = sqlite3ExprListAppend(pParse, pEList, p);
      }
      pLhs = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
      if( pLhs ){
        pLhs->x.pList = sqlite3ExprListDup(db, pEList, 0);
      }
    }
  }

  /* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree
  ** and the SELECT subtree. */
  pSrc->a[0].pTab = 0;
  pSelectSrc = sqlite3SrcListDup(pParse->db, pSrc, 0);
  pSelectSrc = sqlite3SrcListDup(db, pSrc, 0);
  pSrc->a[0].pTab = pTab;
  if( pSrc->a[0].fg.isIndexedBy ){
    assert( pSrc->a[0].fg.isCte==0 );
  pSrc->a[0].pIBIndex = 0;
    pSrc->a[0].u2.pIBIndex = 0;
    pSrc->a[0].fg.isIndexedBy = 0;
    sqlite3DbFree(db, pSrc->a[0].u1.zIndexedBy);
  }else if( pSrc->a[0].fg.isCte ){
    pSrc->a[0].u2.pCteUse->nUse++;
  }

  /* generate the SELECT expression tree. */
  pSelect = sqlite3SelectNew(pParse, pEList, pSelectSrc, pWhere, 0 ,0, 
      pOrderBy,0,pLimit
  );

  /* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */
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
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







+
-
+


+

-














-
+









+
+
+
+
+
+
+
+







#ifndef SQLITE_OMIT_TRIGGER
  int isView;                  /* True if attempting to delete from a view */
  Trigger *pTrigger;           /* List of table triggers, if required */
#endif

  memset(&sContext, 0, sizeof(sContext));
  db = pParse->db;
  assert( db->pParse==pParse );
  if( pParse->nErr || db->mallocFailed ){
  if( pParse->nErr ){
    goto delete_from_cleanup;
  }
  assert( db->mallocFailed==0 );
  assert( pTabList->nSrc==1 );


  /* Locate the table which we want to delete.  This table has to be
  ** put in an SrcList structure because some of the subroutines we
  ** will be calling are designed to work with multiple tables and expect
  ** an SrcList* parameter instead of just a Table* parameter.
  */
  pTab = sqlite3SrcListLookup(pParse, pTabList);
  if( pTab==0 )  goto delete_from_cleanup;

  /* Figure out if we have any triggers and if the table being
  ** deleted from is a view
  */
#ifndef SQLITE_OMIT_TRIGGER
  pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
  isView = pTab->pSelect!=0;
  isView = IsView(pTab);
#else
# define pTrigger 0
# define isView 0
#endif
  bComplex = pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0);
#ifdef SQLITE_OMIT_VIEW
# undef isView
# define isView 0
#endif

#if TREETRACE_ENABLED
  if( sqlite3TreeTrace & 0x10000 ){
    sqlite3TreeViewLine(0, "In sqlite3Delete() at %s:%d", __FILE__, __LINE__);
    sqlite3TreeViewDelete(pParse->pWith, pTabList, pWhere,
                          pOrderBy, pLimit, pTrigger);
  }
#endif

#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
  if( !isView ){
    pWhere = sqlite3LimitWhere(
        pParse, pTabList, pWhere, pOrderBy, pLimit, "DELETE"
    );
    pOrderBy = 0;
387
388
389
390
391
392
393

394
395
396
397
398
399
400
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449







+








  /* Initialize the counter of the number of rows deleted, if
  ** we are counting rows.
  */
  if( (db->flags & SQLITE_CountRows)!=0
   && !pParse->nested
   && !pParse->pTriggerTab
   && !pParse->bReturning
  ){
    memCnt = ++pParse->nMem;
    sqlite3VdbeAddOp2(v, OP_Integer, 0, memCnt);
  }

#ifndef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
  /* Special case: A DELETE without a WHERE clause deletes everything.
420
421
422
423
424
425
426



427


428
429
430
431
432

433
434
435
436
437
438
439
469
470
471
472
473
474
475
476
477
478

479
480
481
482
483
484

485
486
487
488
489
490
491
492







+
+
+
-
+
+




-
+







    sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName);
    if( HasRowid(pTab) ){
      sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt ? memCnt : -1,
                        pTab->zName, P4_STATIC);
    }
    for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
      assert( pIdx->pSchema==pTab->pSchema );
      if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
        sqlite3VdbeAddOp3(v, OP_Clear, pIdx->tnum, iDb, memCnt ? memCnt : -1);
      }else{
      sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
        sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
      }
    }
  }else
#endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */
  {
    u16 wcf = WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK|WHERE_SEEK_TABLE;
    u16 wcf = WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK;
    if( sNC.ncFlags & NC_VarSelect ) bComplex = 1;
    wcf |= (bComplex ? 0 : WHERE_ONEPASS_MULTIROW);
    if( HasRowid(pTab) ){
      /* For a rowid table, initialize the RowSet to an empty set */
      pPk = 0;
      nPk = 1;
      iRowSet = ++pParse->nMem;
455
456
457
458
459
460
461
462

463
464
465
466
467



468
469
470
471
472
473
474
508
509
510
511
512
513
514

515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530







-
+





+
+
+







    ** to be deleted, based on the WHERE clause. Set variable eOnePass
    ** to indicate the strategy used to implement this delete:
    **
    **  ONEPASS_OFF:    Two-pass approach - use a FIFO for rowids/PK values.
    **  ONEPASS_SINGLE: One-pass approach - at most one row deleted.
    **  ONEPASS_MULTI:  One-pass approach - any number of rows may be deleted.
    */
    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, wcf, iTabCur+1);
    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0,0,wcf,iTabCur+1);
    if( pWInfo==0 ) goto delete_from_cleanup;
    eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
    assert( IsVirtual(pTab)==0 || eOnePass!=ONEPASS_MULTI );
    assert( IsVirtual(pTab) || bComplex || eOnePass!=ONEPASS_OFF );
    if( eOnePass!=ONEPASS_SINGLE ) sqlite3MultiWrite(pParse);
    if( sqlite3WhereUsesDeferredSeek(pWInfo) ){
      sqlite3VdbeAddOp1(v, OP_FinishSeek, iTabCur);
    }
  
    /* Keep track of the number of rows to be deleted */
    if( memCnt ){
      sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
    }
  
    /* Extract the rowid or primary key for the current row */
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
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







+













-
-
-
-
-
-
-


















-
+
+
+








-
+







        goto delete_from_cleanup;
      }
      memset(aToOpen, 1, nIdx+1);
      aToOpen[nIdx+1] = 0;
      if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iTabCur] = 0;
      if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iTabCur] = 0;
      if( addrEphOpen ) sqlite3VdbeChangeToNoop(v, addrEphOpen);
      addrBypass = sqlite3VdbeMakeLabel(pParse);
    }else{
      if( pPk ){
        /* Add the PK key for this row to the temporary table */
        iKey = ++pParse->nMem;
        nKey = 0;   /* Zero tells OP_Found to use a composite key */
        sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, iKey,
            sqlite3IndexAffinityStr(pParse->db, pPk), nPk);
        sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iEphCur, iKey, iPk, nPk);
      }else{
        /* Add the rowid of the row to be deleted to the RowSet */
        nKey = 1;  /* OP_DeferredSeek always uses a single rowid */
        sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, iKey);
      }
    }
  
    /* If this DELETE cannot use the ONEPASS strategy, this is the 
    ** end of the WHERE loop */
    if( eOnePass!=ONEPASS_OFF ){
      addrBypass = sqlite3VdbeMakeLabel(v);
    }else{
      sqlite3WhereEnd(pWInfo);
    }
  
    /* Unless this is a view, open cursors for the table we are 
    ** deleting from and all its indices. If this is a view, then the
    ** only effect this statement has is to fire the INSTEAD OF 
    ** triggers.
    */
    if( !isView ){
      int iAddrOnce = 0;
      if( eOnePass==ONEPASS_MULTI ){
        iAddrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
      }
      testcase( IsVirtual(pTab) );
      sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, OPFLAG_FORDELETE,
                                 iTabCur, aToOpen, &iDataCur, &iIdxCur);
      assert( pPk || IsVirtual(pTab) || iDataCur==iTabCur );
      assert( pPk || IsVirtual(pTab) || iIdxCur==iDataCur+1 );
      if( eOnePass==ONEPASS_MULTI ) sqlite3VdbeJumpHere(v, iAddrOnce);
      if( eOnePass==ONEPASS_MULTI ){
        sqlite3VdbeJumpHereOrPopInst(v, iAddrOnce);
      }
    }
  
    /* Set up a loop over the rowids/primary-keys that were found in the
    ** where-clause loop above.
    */
    if( eOnePass!=ONEPASS_OFF ){
      assert( nKey==nPk );  /* OP_Found will use an unpacked key */
      if( !IsVirtual(pTab) && aToOpen[iDataCur-iTabCur] ){
        assert( pPk!=0 || pTab->pSelect!=0 );
        assert( pPk!=0 || IsView(pTab) );
        sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey);
        VdbeCoverage(v);
      }
    }else if( pPk ){
      addrLoop = sqlite3VdbeAddOp1(v, OP_Rewind, iEphCur); VdbeCoverage(v);
      if( IsVirtual(pTab) ){
        sqlite3VdbeAddOp3(v, OP_Column, iEphCur, 0, iKey);
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
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







-
-
-
+










-
+







  }

  /* Return the number of rows that were deleted. If this routine is 
  ** generating code because of a call to sqlite3NestedParse(), do not
  ** invoke the callback function.
  */
  if( memCnt ){
    sqlite3VdbeAddOp2(v, OP_ResultRow, memCnt, 1);
    sqlite3VdbeSetNumCols(v, 1);
    sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", SQLITE_STATIC);
    sqlite3CodeChangeCount(v, memCnt, "rows deleted");
  }

delete_from_cleanup:
  sqlite3AuthContextPop(&sContext);
  sqlite3SrcListDelete(db, pTabList);
  sqlite3ExprDelete(db, pWhere);
#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) 
  sqlite3ExprListDelete(db, pOrderBy);
  sqlite3ExprDelete(db, pLimit);
#endif
  sqlite3DbFree(db, aToOpen);
  if( aToOpen ) sqlite3DbNNFreeNN(db, aToOpen);
  return;
}
/* Make sure "isView" and other macros defined above are undefined. Otherwise
** they may interfere with compilation of other functions in this file
** (or in another file, if this file becomes part of the amalgamation).  */
#ifdef isView
 #undef isView
702
703
704
705
706
707
708
709

710
711
712
713
714
715
716
752
753
754
755
756
757
758

759
760
761
762
763
764
765
766







-
+







  assert( v );
  VdbeModuleComment((v, "BEGIN: GenRowDel(%d,%d,%d,%d)",
                         iDataCur, iIdxCur, iPk, (int)nPk));

  /* Seek cursor iCur to the row to delete. If this row no longer exists 
  ** (this can happen if a trigger program has already deleted it), do
  ** not attempt to delete it or fire any DELETE triggers.  */
  iLabel = sqlite3VdbeMakeLabel(v);
  iLabel = sqlite3VdbeMakeLabel(pParse);
  opSeek = HasRowid(pTab) ? OP_NotExists : OP_NotFound;
  if( eMode==ONEPASS_OFF ){
    sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk);
    VdbeCoverageIf(v, opSeek==OP_NotExists);
    VdbeCoverageIf(v, opSeek==OP_NotFound);
  }
 
733
734
735
736
737
738
739

740

741
742
743
744
745
746
747
783
784
785
786
787
788
789
790

791
792
793
794
795
796
797
798







+
-
+







    /* Populate the OLD.* pseudo-table register array. These values will be 
    ** used by any BEFORE and AFTER triggers that exist.  */
    sqlite3VdbeAddOp2(v, OP_Copy, iPk, iOld);
    for(iCol=0; iCol<pTab->nCol; iCol++){
      testcase( mask!=0xffffffff && iCol==31 );
      testcase( mask!=0xffffffff && iCol==32 );
      if( mask==0xffffffff || (iCol<=31 && (mask & MASKBIT32(iCol))!=0) ){
        int kk = sqlite3TableColumnToStorage(pTab, iCol);
        sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, iCol, iOld+iCol+1);
        sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, iCol, iOld+kk+1);
      }
    }

    /* Invoke BEFORE DELETE trigger programs. */
    addrStart = sqlite3VdbeCurrentAddr(v);
    sqlite3CodeRowTrigger(pParse, pTrigger, 
        TK_DELETE, 0, TRIGGER_BEFORE, pTab, iOld, onconf, iLabel
775
776
777
778
779
780
781
782

783
784
785
786
787
788
789
826
827
828
829
830
831
832

833
834
835
836
837
838
839
840







-
+







  **
  ** If variable 'count' is non-zero, then this OP_Delete instruction should
  ** invoke the update-hook. The pre-update-hook, on the other hand should
  ** be invoked unless table pTab is a system table. The difference is that
  ** the update-hook is not invoked for rows removed by REPLACE, but the 
  ** pre-update-hook is.
  */ 
  if( pTab->pSelect==0 ){
  if( !IsView(pTab) ){
    u8 p5 = 0;
    sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek);
    sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0));
    if( pParse->nested==0 || 0==sqlite3_stricmp(pTab->zName, "sqlite_stat1") ){
      sqlite3VdbeAppendP4(v, (char*)pTab, P4_TABLE);
    }
    if( eMode!=ONEPASS_OFF ){
855
856
857
858
859
860
861

862
863
864
865
866
867
868
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920







+







    if( pIdx==pPk ) continue;
    if( iIdxCur+i==iIdxNoSeek ) continue;
    VdbeModuleComment((v, "GenRowIdxDel for %s", pIdx->zName));
    r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 1,
        &iPartIdxLabel, pPrior, r1);
    sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1,
        pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn);
    sqlite3VdbeChangeP5(v, 1);  /* Cause IdxDelete to error if no entry found */
    sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel);
    pPrior = pIdx;
  }
}

/*
** Generate code that will assemble an index key and stores it in register
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
935

936
937
938
939
940
941
942








943
944
945
946
947
948
949
950
951
952
953
954
955
956
960
961
962
963
964
965
966

967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990







991
992
993
994
995
996
997
998
999
1000
1001




1002
1003
1004
1005
1006
1007
1008







-
+




+
+
















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



-
-
-
-







  Vdbe *v = pParse->pVdbe;
  int j;
  int regBase;
  int nCol;

  if( piPartIdxLabel ){
    if( pIdx->pPartIdxWhere ){
      *piPartIdxLabel = sqlite3VdbeMakeLabel(v);
      *piPartIdxLabel = sqlite3VdbeMakeLabel(pParse);
      pParse->iSelfTab = iDataCur + 1;
      sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel, 
                            SQLITE_JUMPIFNULL);
      pParse->iSelfTab = 0;
      pPrior = 0; /* Ticket a9efb42811fa41ee 2019-11-02;
                  ** pPartIdxWhere may have corrupted regPrior registers */
    }else{
      *piPartIdxLabel = 0;
    }
  }
  nCol = (prefixOnly && pIdx->uniqNotNull) ? pIdx->nKeyCol : pIdx->nColumn;
  regBase = sqlite3GetTempRange(pParse, nCol);
  if( pPrior && (regBase!=regPrior || pPrior->pPartIdxWhere) ) pPrior = 0;
  for(j=0; j<nCol; j++){
    if( pPrior
     && pPrior->aiColumn[j]==pIdx->aiColumn[j]
     && pPrior->aiColumn[j]!=XN_EXPR
    ){
      /* This column was already computed by the previous index */
      continue;
    }
    sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iDataCur, j, regBase+j);
    if( pIdx->aiColumn[j]>=0 ){
    /* If the column affinity is REAL but the number is an integer, then it
    ** might be stored in the table as an integer (using a compact
    ** representation) then converted to REAL by an OP_RealAffinity opcode.
    ** But we are getting ready to store this value back into an index, where
    ** it should be converted by to INTEGER again.  So omit the OP_RealAffinity
    ** opcode if it is present */
    sqlite3VdbeDeletePriorOpcode(v, OP_RealAffinity);
      /* If the column affinity is REAL but the number is an integer, then it
      ** might be stored in the table as an integer (using a compact
      ** representation) then converted to REAL by an OP_RealAffinity opcode.
      ** But we are getting ready to store this value back into an index, where
      ** it should be converted by to INTEGER again.  So omit the
      ** OP_RealAffinity opcode if it is present */
      sqlite3VdbeDeletePriorOpcode(v, OP_RealAffinity);
    }
  }
  if( regOut ){
    sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regOut);
    if( pIdx->pTable->pSelect ){
      const char *zAff = sqlite3IndexAffinityStr(pParse->db, pIdx);
      sqlite3VdbeChangeP4(v, -1, zAff, P4_TRANSIENT);
    }
  }
  sqlite3ReleaseTempRange(pParse, regBase, nCol);
  return regBase;
}

/*
** If a prior call to sqlite3GenerateIndexKey() generated a jump-over label

Changes to src/expr.c.

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
17
18
19
20
21
22
23



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

45
46


47
48
49
50
51
52
53




54
55
56
57
58
59
60

61




62
63
64
65
66










67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170

171
172
173
174
175
176
177
178
179
180
181
182
183
184
185

186
187
188
189
190
191
192
193
194
195
196
197

198

199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215

216
217
218
219
220
221
222
223







-
-
-
+
+
+


















-
+

-
-

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

-
-
-
-
+
+
+
+

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











-
+














-
+
+
+
+
+







-
+
-



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

-
+







/* Forward declarations */
static void exprCodeBetween(Parse*,Expr*,int,void(*)(Parse*,Expr*,int,int),int);
static int exprCodeVector(Parse *pParse, Expr *p, int *piToFree);

/*
** Return the affinity character for a single column of a table.
*/
char sqlite3TableColumnAffinity(Table *pTab, int iCol){
  assert( iCol<pTab->nCol );
  return iCol>=0 ? pTab->aCol[iCol].affinity : SQLITE_AFF_INTEGER;
char sqlite3TableColumnAffinity(const Table *pTab, int iCol){
  if( iCol<0 || NEVER(iCol>=pTab->nCol) ) return SQLITE_AFF_INTEGER;
  return pTab->aCol[iCol].affinity;
}

/*
** Return the 'affinity' of the expression pExpr if any.
**
** If pExpr is a column, a reference to a column via an 'AS' alias,
** or a sub-select with a column as the return value, then the 
** affinity of that column is returned. Otherwise, 0x00 is returned,
** indicating no affinity for the expression.
**
** i.e. the WHERE clause expressions in the following statements all
** have an affinity:
**
** CREATE TABLE t1(a);
** SELECT * FROM t1 WHERE a;
** SELECT a AS b FROM t1 WHERE b;
** SELECT * FROM t1 WHERE (select a from t1);
*/
char sqlite3ExprAffinity(Expr *pExpr){
char sqlite3ExprAffinity(const Expr *pExpr){
  int op;
  pExpr = sqlite3ExprSkipCollate(pExpr);
  if( pExpr->flags & EP_Generic ) return 0;
  op = pExpr->op;
  while( 1 /* exit-by-break */ ){
    if( op==TK_COLUMN || (op==TK_AGG_COLUMN && pExpr->y.pTab!=0) ){
      assert( ExprUseYTab(pExpr) );
      assert( pExpr->y.pTab!=0 );
      return sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
    }
  if( op==TK_SELECT ){
    assert( pExpr->flags&EP_xIsSelect );
    return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
  }
    if( op==TK_SELECT ){
      assert( ExprUseXSelect(pExpr) );
      assert( pExpr->x.pSelect!=0 );
      assert( pExpr->x.pSelect->pEList!=0 );
      assert( pExpr->x.pSelect->pEList->a[0].pExpr!=0 );
      return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
    }
  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);
  }
    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
    );
  }
  return pExpr->affinity;
    if( op==TK_SELECT_COLUMN ){
      assert( pExpr->pLeft!=0 && ExprUseXSelect(pExpr->pLeft) );
      assert( pExpr->iColumn < pExpr->iTable );
      assert( pExpr->iTable==pExpr->pLeft->x.pSelect->pEList->nExpr );
      return sqlite3ExprAffinity(
          pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr
      );
    }
    if( op==TK_VECTOR ){
      assert( ExprUseXList(pExpr) );
      return sqlite3ExprAffinity(pExpr->x.pList->a[0].pExpr);
    }
    if( ExprHasProperty(pExpr, EP_Skip|EP_IfNullRow) ){
      assert( pExpr->op==TK_COLLATE
           || pExpr->op==TK_IF_NULL_ROW
           || (pExpr->op==TK_REGISTER && pExpr->op2==TK_IF_NULL_ROW) );
      pExpr = pExpr->pLeft;
      op = pExpr->op;
      continue;
    }
    if( op!=TK_REGISTER || (op = pExpr->op2)==TK_REGISTER ) break;
  }
  return pExpr->affExpr;
}

/*
** Make a guess at all the possible datatypes of the result that could
** be returned by an expression.  Return a bitmask indicating the answer:
**
**     0x01         Numeric
**     0x02         Text
**     0x04         Blob
**
** If the expression must return NULL, then 0x00 is returned.
*/
int sqlite3ExprDataType(const Expr *pExpr){
  while( pExpr ){
    switch( pExpr->op ){
      case TK_COLLATE:
      case TK_IF_NULL_ROW:
      case TK_UPLUS:  {
        pExpr = pExpr->pLeft;
        break;
      }
      case TK_NULL: {
        pExpr = 0;
        break;
      }
      case TK_STRING: {
        return 0x02;
      }
      case TK_BLOB: {
        return 0x04;
      }
      case TK_CONCAT: {
        return 0x06;
      }
      case TK_VARIABLE:
      case TK_AGG_FUNCTION:
      case TK_FUNCTION: {
        return 0x07;
      }
      case TK_COLUMN:
      case TK_AGG_COLUMN:
      case TK_SELECT:
      case TK_CAST:
      case TK_SELECT_COLUMN:
      case TK_VECTOR:  {
        int aff = sqlite3ExprAffinity(pExpr);
        if( aff>=SQLITE_AFF_NUMERIC ) return 0x05;
        if( aff==SQLITE_AFF_TEXT )    return 0x06;
        return 0x07;
      }
      case TK_CASE: {
        int res = 0;
        int ii;
        ExprList *pList = pExpr->x.pList;
        assert( ExprUseXList(pExpr) && pList!=0 );
        assert( pList->nExpr > 0);
        for(ii=1; ii<pList->nExpr; ii+=2){
          res |= sqlite3ExprDataType(pList->a[ii].pExpr);
        }
        if( pList->nExpr % 2 ){
          res |= sqlite3ExprDataType(pList->a[pList->nExpr-1].pExpr);
        }
        return res;
      }
      default: {
        return 0x01;
      }
    } /* End of switch(op) */
  } /* End of while(pExpr) */
  return 0x00;
}

/*
** Set the collating sequence for expression pExpr to be the collating
** sequence named by pToken.   Return a pointer to a new Expr node that
** implements the COLLATE operator.
**
** If a memory allocation error occurs, that fact is recorded in pParse->db
** and the pExpr parameter is returned unchanged.
*/
Expr *sqlite3ExprAddCollateToken(
  Parse *pParse,           /* Parsing context */
  const Parse *pParse,     /* Parsing context */
  Expr *pExpr,             /* Add the "COLLATE" clause to this expression */
  const Token *pCollName,  /* Name of collating sequence */
  int dequote              /* True to dequote pCollName */
){
  if( pCollName->n>0 ){
    Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, dequote);
    if( pNew ){
      pNew->pLeft = pExpr;
      pNew->flags |= EP_Collate|EP_Skip;
      pExpr = pNew;
    }
  }
  return pExpr;
}
Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){
Expr *sqlite3ExprAddCollateString(
  const Parse *pParse,  /* Parsing context */
  Expr *pExpr,          /* Add the "COLLATE" clause to this expression */
  const char *zC        /* The collating sequence name */
){
  Token s;
  assert( zC!=0 );
  sqlite3TokenInit(&s, (char*)zC);
  return sqlite3ExprAddCollateToken(pParse, pExpr, &s, 0);
}

/*
** Skip over any TK_COLLATE operators and any unlikely()
** Skip over any TK_COLLATE operators.
** or likelihood() function at the root of an expression.
*/
Expr *sqlite3ExprSkipCollate(Expr *pExpr){
  while( pExpr && ExprHasProperty(pExpr, EP_Skip) ){
    assert( pExpr->op==TK_COLLATE );
    pExpr = pExpr->pLeft;
  }   
  return pExpr;
}

/*
** Skip over any TK_COLLATE operators and/or any unlikely()
** or likelihood() or likely() functions at the root of an
** expression.
*/
Expr *sqlite3ExprSkipCollateAndLikely(Expr *pExpr){
  while( pExpr && ExprHasProperty(pExpr, EP_Skip|EP_Unlikely) ){
    if( ExprHasProperty(pExpr, EP_Unlikely) ){
      assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
      assert( ExprUseXList(pExpr) );
      assert( pExpr->x.pList->nExpr>0 );
      assert( pExpr->op==TK_FUNCTION );
      pExpr = pExpr->x.pList->a[0].pExpr;
    }else{
      assert( pExpr->op==TK_COLLATE );
      pExpr = pExpr->pLeft;
    }
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
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







-
+


-
+


-

+
-
+
-

+
+
-
+
-
-
+
-
-
+








+
+
+
+
+

+









+

-
-
-
-
+







** default collation if pExpr has no defined collation.
**
** The collating sequence might be determined by a COLLATE operator
** or by the presence of a column with a defined collating sequence.
** COLLATE operators take first precedence.  Left operands take
** precedence over right operands.
*/
CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr){
  sqlite3 *db = pParse->db;
  CollSeq *pColl = 0;
  Expr *p = pExpr;
  const Expr *p = pExpr;
  while( p ){
    int op = p->op;
    if( p->flags & EP_Generic ) break;
    if( op==TK_REGISTER ) op = p->op2;
    if( (op==TK_AGG_COLUMN && p->y.pTab!=0) 
    if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_TRIGGER)
     || op==TK_COLUMN || op==TK_TRIGGER
     && p->y.pTab!=0
    ){
      int j;
      assert( ExprUseYTab(p) );
      /* op==TK_REGISTER && p->y.pTab!=0 happens when pExpr was originally
      assert( p->y.pTab!=0 );
      ** a TK_COLUMN but was previously evaluated and cached in a register */
      int j = p->iColumn;
      if( (j = p->iColumn)>=0 ){
      if( j>=0 ){
        const char *zColl = p->y.pTab->aCol[j].zColl;
        const char *zColl = sqlite3ColumnColl(&p->y.pTab->aCol[j]);
        pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
      }
      break;
    }
    if( op==TK_CAST || op==TK_UPLUS ){
      p = p->pLeft;
      continue;
    }
    if( op==TK_VECTOR ){
      assert( ExprUseXList(p) );
      p = p->x.pList->a[0].pExpr;
      continue;
    }
    if( op==TK_COLLATE ){
      assert( !ExprHasProperty(p, EP_IntValue) );
      pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
      break;
    }
    if( p->flags & EP_Collate ){
      if( p->pLeft && (p->pLeft->flags & EP_Collate)!=0 ){
        p = p->pLeft;
      }else{
        Expr *pNext  = p->pRight;
        /* The Expr.x union is never used at the same time as Expr.pRight */
        assert( ExprUseXList(p) );
        assert( p->x.pList==0 || p->pRight==0 );
        /* p->flags holds EP_Collate and p->pLeft->flags does not.  And
        ** p->x.pSelect cannot.  So if p->x.pLeft exists, it must hold at
        ** least one EP_Collate. Thus the following two ALWAYS. */
        if( p->x.pList!=0 && ALWAYS(!ExprHasProperty(p, EP_xIsSelect)) ){
        if( p->x.pList!=0 && !db->mallocFailed ){
          int i;
          for(i=0; ALWAYS(i<p->x.pList->nExpr); i++){
            if( ExprHasProperty(p->x.pList->a[i].pExpr, EP_Collate) ){
              pNext = p->x.pList->a[i].pExpr;
              break;
            }
          }
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
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







-
+









-
+










-
+

-
+








-
-
-
-
-


-
-
+
+







-
+








-
+













-
+

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

+






-
+
+
+
+
+



















-
-
+
+















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











-
+
+





+
+
+
+
-
+
+
















-
+









-
+



+


+







** defautl collation sequence.
**
** See also: sqlite3ExprCollSeq()
**
** The sqlite3ExprCollSeq() routine works the same except that it
** returns NULL if there is no defined collation.
*/
CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr){
CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, const Expr *pExpr){
  CollSeq *p = sqlite3ExprCollSeq(pParse, pExpr);
  if( p==0 ) p = pParse->db->pDfltColl;
  assert( p!=0 );
  return p;
}

/*
** Return TRUE if the two expressions have equivalent collating sequences.
*/
int sqlite3ExprCollSeqMatch(Parse *pParse, Expr *pE1, Expr *pE2){
int sqlite3ExprCollSeqMatch(Parse *pParse, const Expr *pE1, const Expr *pE2){
  CollSeq *pColl1 = sqlite3ExprNNCollSeq(pParse, pE1);
  CollSeq *pColl2 = sqlite3ExprNNCollSeq(pParse, pE2);
  return sqlite3StrICmp(pColl1->zName, pColl2->zName)==0;
}

/*
** pExpr is an operand of a comparison operator.  aff2 is the
** type affinity of the other operand.  This routine returns the
** type affinity that should be used for the comparison operator.
*/
char sqlite3CompareAffinity(Expr *pExpr, char aff2){
char sqlite3CompareAffinity(const Expr *pExpr, char aff2){
  char aff1 = sqlite3ExprAffinity(pExpr);
  if( aff1 && aff2 ){
  if( aff1>SQLITE_AFF_NONE && aff2>SQLITE_AFF_NONE ){
    /* Both sides of the comparison are columns. If one has numeric
    ** affinity, use that. Otherwise use no affinity.
    */
    if( sqlite3IsNumericAffinity(aff1) || sqlite3IsNumericAffinity(aff2) ){
      return SQLITE_AFF_NUMERIC;
    }else{
      return SQLITE_AFF_BLOB;
    }
  }else if( !aff1 && !aff2 ){
    /* Neither side of the comparison is a column.  Compare the
    ** results directly.
    */
    return SQLITE_AFF_BLOB;
  }else{
    /* One side is a column, the other is not. Use the columns affinity. */
    assert( aff1==0 || aff2==0 );
    return (aff1 + aff2);
    assert( aff1<=SQLITE_AFF_NONE || aff2<=SQLITE_AFF_NONE );
    return (aff1<=SQLITE_AFF_NONE ? aff2 : aff1) | SQLITE_AFF_NONE;
  }
}

/*
** pExpr is a comparison operator.  Return the type affinity that should
** be applied to both operands prior to doing the comparison.
*/
static char comparisonAffinity(Expr *pExpr){
static char comparisonAffinity(const Expr *pExpr){
  char aff;
  assert( pExpr->op==TK_EQ || pExpr->op==TK_IN || pExpr->op==TK_LT ||
          pExpr->op==TK_GT || pExpr->op==TK_GE || pExpr->op==TK_LE ||
          pExpr->op==TK_NE || pExpr->op==TK_IS || pExpr->op==TK_ISNOT );
  assert( pExpr->pLeft );
  aff = sqlite3ExprAffinity(pExpr->pLeft);
  if( pExpr->pRight ){
    aff = sqlite3CompareAffinity(pExpr->pRight, aff);
  }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
  }else if( ExprUseXSelect(pExpr) ){
    aff = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff);
  }else if( aff==0 ){
    aff = SQLITE_AFF_BLOB;
  }
  return aff;
}

/*
** pExpr is a comparison expression, eg. '=', '<', IN(...) etc.
** idx_affinity is the affinity of an indexed column. Return true
** if the index with affinity idx_affinity may be used to implement
** the comparison in pExpr.
*/
int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){
int sqlite3IndexAffinityOk(const Expr *pExpr, char idx_affinity){
  char aff = comparisonAffinity(pExpr);
  switch( aff ){
    case SQLITE_AFF_BLOB:
      return 1;
    case SQLITE_AFF_TEXT:
      return idx_affinity==SQLITE_AFF_TEXT;
  if( aff<SQLITE_AFF_TEXT ){
    return 1;
  }
  if( aff==SQLITE_AFF_TEXT ){
    return idx_affinity==SQLITE_AFF_TEXT;
    default:
      return sqlite3IsNumericAffinity(idx_affinity);
  }
  return sqlite3IsNumericAffinity(idx_affinity);
}

/*
** Return the P5 value that should be used for a binary comparison
** opcode (OP_Eq, OP_Ge etc.) used to compare pExpr1 and pExpr2.
*/
static u8 binaryCompareP5(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){
static u8 binaryCompareP5(
  const Expr *pExpr1,   /* Left operand */
  const Expr *pExpr2,   /* Right operand */
  int jumpIfNull        /* Extra flags added to P5 */
){
  u8 aff = (char)sqlite3ExprAffinity(pExpr2);
  aff = (u8)sqlite3CompareAffinity(pExpr1, aff) | (u8)jumpIfNull;
  return aff;
}

/*
** Return a pointer to the collation sequence that should be used by
** a binary comparison operator comparing pLeft and pRight.
**
** If the left hand expression has a collating sequence type, then it is
** used. Otherwise the collation sequence for the right hand expression
** is used, or the default (BINARY) if neither expression has a collating
** type.
**
** Argument pRight (but not pLeft) may be a null pointer. In this case,
** it is not considered.
*/
CollSeq *sqlite3BinaryCompareCollSeq(
  Parse *pParse, 
  Expr *pLeft, 
  Expr *pRight
  const Expr *pLeft, 
  const Expr *pRight
){
  CollSeq *pColl;
  assert( pLeft );
  if( pLeft->flags & EP_Collate ){
    pColl = sqlite3ExprCollSeq(pParse, pLeft);
  }else if( pRight && (pRight->flags & EP_Collate)!=0 ){
    pColl = sqlite3ExprCollSeq(pParse, pRight);
  }else{
    pColl = sqlite3ExprCollSeq(pParse, pLeft);
    if( !pColl ){
      pColl = sqlite3ExprCollSeq(pParse, pRight);
    }
  }
  return pColl;
}

/* Expresssion p is a comparison operator.  Return a collation sequence
** appropriate for the comparison operator.
**
** This is normally just a wrapper around sqlite3BinaryCompareCollSeq().
** However, if the OP_Commuted flag is set, then the order of the operands
** is reversed in the sqlite3BinaryCompareCollSeq() call so that the
** correct collating sequence is found.
*/
CollSeq *sqlite3ExprCompareCollSeq(Parse *pParse, const Expr *p){
  if( ExprHasProperty(p, EP_Commuted) ){
    return sqlite3BinaryCompareCollSeq(pParse, p->pRight, p->pLeft);
  }else{
    return sqlite3BinaryCompareCollSeq(pParse, p->pLeft, p->pRight);
  }
}

/*
** Generate code for a comparison operator.
*/
static int codeCompare(
  Parse *pParse,    /* The parsing (and code generating) context */
  Expr *pLeft,      /* The left operand */
  Expr *pRight,     /* The right operand */
  int opcode,       /* The comparison opcode */
  int in1, int in2, /* Register holding operands */
  int dest,         /* Jump here if true.  */
  int jumpIfNull    /* If true, jump if either operand is NULL */
  int jumpIfNull,   /* If true, jump if either operand is NULL */
  int isCommuted    /* The comparison has been commuted */
){
  int p5;
  int addr;
  CollSeq *p4;

  if( pParse->nErr ) return 0;
  if( isCommuted ){
    p4 = sqlite3BinaryCompareCollSeq(pParse, pRight, pLeft);
  }else{
  p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight);
    p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight);
  }
  p5 = binaryCompareP5(pLeft, pRight, jumpIfNull);
  addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1,
                           (void*)p4, P4_COLLSEQ);
  sqlite3VdbeChangeP5(pParse->pVdbe, (u8)p5);
  return addr;
}

/*
** Return true if expression pExpr is a vector, or false otherwise.
**
** A vector is defined as any expression that results in two or more
** columns of result.  Every TK_VECTOR node is an vector because the
** parser will not generate a TK_VECTOR with fewer than two entries.
** But a TK_SELECT might be either a vector or a scalar. It is only
** considered a vector if it has two or more result columns.
*/
int sqlite3ExprIsVector(Expr *pExpr){
int sqlite3ExprIsVector(const Expr *pExpr){
  return sqlite3ExprVectorSize(pExpr)>1;
}

/*
** If the expression passed as the only argument is of type TK_VECTOR 
** return the number of expressions in the vector. Or, if the expression
** is a sub-select, return the number of columns in the sub-select. For
** any other type of expression, return 1.
*/
int sqlite3ExprVectorSize(Expr *pExpr){
int sqlite3ExprVectorSize(const Expr *pExpr){
  u8 op = pExpr->op;
  if( op==TK_REGISTER ) op = pExpr->op2;
  if( op==TK_VECTOR ){
    assert( ExprUseXList(pExpr) );
    return pExpr->x.pList->nExpr;
  }else if( op==TK_SELECT ){
    assert( ExprUseXSelect(pExpr) );
    return pExpr->x.pSelect->pEList->nExpr;
  }else{
    return 1;
  }
}

/*
395
396
397
398
399
400
401
402

403
404
405

406
407

408
409
410
411
412
413
414
525
526
527
528
529
530
531

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







-
+



+


+







**
** If the vector is a (SELECT ...) then the expression returned is
** just the expression for the i-th term of the result set, and may
** not be ready for evaluation because the table cursor has not yet
** been positioned.
*/
Expr *sqlite3VectorFieldSubexpr(Expr *pVector, int i){
  assert( i<sqlite3ExprVectorSize(pVector) );
  assert( i<sqlite3ExprVectorSize(pVector) || pVector->op==TK_ERROR );
  if( sqlite3ExprIsVector(pVector) ){
    assert( pVector->op2==0 || pVector->op==TK_REGISTER );
    if( pVector->op==TK_SELECT || pVector->op2==TK_SELECT ){
      assert( ExprUseXSelect(pVector) );
      return pVector->x.pSelect->pEList->a[i].pExpr;
    }else{
      assert( ExprUseXList(pVector) );
      return pVector->x.pList->a[i].pExpr;
    }
  }
  return pVector;
}

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







-
+
+



-
+


















+



-

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

















-
+







** A trick to cause a TK_SELECT pVector to be deleted together with
** the returned Expr object is to attach the pVector to the pRight field
** of the returned TK_SELECT_COLUMN Expr object.
*/
Expr *sqlite3ExprForVectorField(
  Parse *pParse,       /* Parsing context */
  Expr *pVector,       /* The vector.  List of expressions or a sub-SELECT */
  int iField           /* Which column of the vector to return */
  int iField,          /* Which column of the vector to return */
  int nField           /* Total number of columns in the vector */
){
  Expr *pRet;
  if( pVector->op==TK_SELECT ){
    assert( pVector->flags & EP_xIsSelect );
    assert( ExprUseXSelect(pVector) );
    /* The TK_SELECT_COLUMN Expr node:
    **
    ** pLeft:           pVector containing TK_SELECT.  Not deleted.
    ** pRight:          not used.  But recursively deleted.
    ** iColumn:         Index of a column in pVector
    ** iTable:          0 or the number of columns on the LHS of an assignment
    ** pLeft->iTable:   First in an array of register holding result, or 0
    **                  if the result is not yet computed.
    **
    ** sqlite3ExprDelete() specifically skips the recursive delete of
    ** pLeft on TK_SELECT_COLUMN nodes.  But pRight is followed, so pVector
    ** can be attached to pRight to cause this node to take ownership of
    ** pVector.  Typically there will be multiple TK_SELECT_COLUMN nodes
    ** with the same pLeft pointer to the pVector, but only one of them
    ** will own the pVector.
    */
    pRet = sqlite3PExpr(pParse, TK_SELECT_COLUMN, 0, 0);
    if( pRet ){
      pRet->iTable = nField;
      pRet->iColumn = iField;
      pRet->pLeft = pVector;
    }
    assert( pRet==0 || pRet->iTable==0 );
  }else{
    if( pVector->op==TK_VECTOR ) pVector = pVector->x.pList->a[iField].pExpr;
    if( pVector->op==TK_VECTOR ){
      Expr **ppVector;
      assert( ExprUseXList(pVector) );
      ppVector = &pVector->x.pList->a[iField].pExpr;
      pVector = *ppVector;
      if( IN_RENAME_OBJECT ){
        /* This must be a vector UPDATE inside a trigger */
        *ppVector = 0;
        return pVector;
      }
    }
    pRet = sqlite3ExprDup(pParse->db, pVector, 0);
  }
  return pRet;
}

/*
** If expression pExpr is of type TK_SELECT, generate code to evaluate
** it. Return the register in which the result is stored (or, if the 
** sub-select returns more than one column, the first in an array
** of registers in which the result is stored).
**
** If pExpr is not a TK_SELECT expression, return 0.
*/
static int exprCodeSubselect(Parse *pParse, Expr *pExpr){
  int reg = 0;
#ifndef SQLITE_OMIT_SUBQUERY
  if( pExpr->op==TK_SELECT ){
    reg = sqlite3CodeSubselect(pParse, pExpr, 0, 0);
    reg = sqlite3CodeSubselect(pParse, pExpr);
  }
#endif
  return reg;
}

/*
** Argument pVector points to a vector expression - either a TK_VECTOR
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
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







-
+





+



+
+
-
-
+
+
+
+







  Expr *pVector,                  /* Vector to extract element from */
  int iField,                     /* Field to extract from pVector */
  int regSelect,                  /* First in array of registers */
  Expr **ppExpr,                  /* OUT: Expression element */
  int *pRegFree                   /* OUT: Temp register to free */
){
  u8 op = pVector->op;
  assert( op==TK_VECTOR || op==TK_REGISTER || op==TK_SELECT );
  assert( op==TK_VECTOR || op==TK_REGISTER || op==TK_SELECT || op==TK_ERROR );
  if( op==TK_REGISTER ){
    *ppExpr = sqlite3VectorFieldSubexpr(pVector, iField);
    return pVector->iTable+iField;
  }
  if( op==TK_SELECT ){
    assert( ExprUseXSelect(pVector) );
    *ppExpr = pVector->x.pSelect->pEList->a[iField].pExpr;
     return regSelect+iField;
  }
  if( op==TK_VECTOR ){
    assert( ExprUseXList(pVector) );
  *ppExpr = pVector->x.pList->a[iField].pExpr;
  return sqlite3ExprCodeTemp(pParse, *ppExpr, pRegFree);
    *ppExpr = pVector->x.pList->a[iField].pExpr;
    return sqlite3ExprCodeTemp(pParse, *ppExpr, pRegFree);
  }
  return 0;
}

/*
** Expression pExpr is a comparison between two vector values. Compute
** the result of the comparison (1, 0, or NULL) and write that
** result into register dest.
**
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
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
775
776
777
778
779
780
781
782







+
-
+
+

+
+














-
-
-
+
+
+




+


-
+


+


+
-
+








+
+
+
+
+
+
+
+
+
+




-
-
-
-
+
-


-
+
-
-
-
-



+

+
+
+







  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(v);
  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; 
    Expr *pL = 0, *pR = 0; 
    int r1, r2;
    assert( i>=0 && i<nLeft );
    if( addrCmp ) sqlite3VdbeJumpHere(v, addrCmp);
    r1 = exprVectorRegister(pParse, pLeft, i, regLeft, &pL, &regFree1);
    r2 = exprVectorRegister(pParse, pRight, i, regRight, &pR, &regFree2);
    addrCmp = sqlite3VdbeCurrentAddr(v);
    codeCompare(pParse, pL, pR, opx, r1, r2, dest, p5);
    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.
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
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







-
+






-
+







-
-
+
+







** of any expression tree referenced by the structure passed as the
** first argument.
**
** If this maximum height is greater than the current value pointed
** to by pnHeight, the second parameter, then set *pnHeight to that
** value.
*/
static void heightOfExpr(Expr *p, int *pnHeight){
static void heightOfExpr(const Expr *p, int *pnHeight){
  if( p ){
    if( p->nHeight>*pnHeight ){
      *pnHeight = p->nHeight;
    }
  }
}
static void heightOfExprList(ExprList *p, int *pnHeight){
static void heightOfExprList(const ExprList *p, int *pnHeight){
  if( p ){
    int i;
    for(i=0; i<p->nExpr; i++){
      heightOfExpr(p->a[i].pExpr, pnHeight);
    }
  }
}
static void heightOfSelect(Select *pSelect, int *pnHeight){
  Select *p;
static void heightOfSelect(const Select *pSelect, int *pnHeight){
  const Select *p;
  for(p=pSelect; p; p=p->pPrior){
    heightOfExpr(p->pWhere, pnHeight);
    heightOfExpr(p->pHaving, pnHeight);
    heightOfExpr(p->pLimit, pnHeight);
    heightOfExprList(p->pEList, pnHeight);
    heightOfExprList(p->pGroupBy, pnHeight);
    heightOfExprList(p->pOrderBy, pnHeight);
675
676
677
678
679
680
681
682
683
684
685





686
687
688
689
690
691
692
836
837
838
839
840
841
842




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







-
-
-
-
+
+
+
+
+







** has a height equal to the maximum height of any other 
** referenced Expr plus one.
**
** Also propagate EP_Propagate flags up from Expr.x.pList to Expr.flags,
** if appropriate.
*/
static void exprSetHeight(Expr *p){
  int nHeight = 0;
  heightOfExpr(p->pLeft, &nHeight);
  heightOfExpr(p->pRight, &nHeight);
  if( ExprHasProperty(p, EP_xIsSelect) ){
  int nHeight = p->pLeft ? p->pLeft->nHeight : 0;
  if( NEVER(p->pRight) && p->pRight->nHeight>nHeight ){
    nHeight = p->pRight->nHeight;
  }
  if( ExprUseXSelect(p) ){
    heightOfSelect(p->x.pSelect, &nHeight);
  }else if( p->x.pList ){
    heightOfExprList(p->x.pList, &nHeight);
    p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList);
  }
  p->nHeight = nHeight + 1;
}
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
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







-
+










+
-
+







  sqlite3ExprCheckHeight(pParse, p->nHeight);
}

/*
** Return the maximum height of any expression tree referenced
** by the select statement passed as an argument.
*/
int sqlite3SelectExprHeight(Select *p){
int sqlite3SelectExprHeight(const Select *p){
  int nHeight = 0;
  heightOfSelect(p, &nHeight);
  return nHeight;
}
#else /* ABOVE:  Height enforcement enabled.  BELOW: Height enforcement off */
/*
** Propagate all EP_Propagate flags from the Expr.x.pList into
** Expr.flags. 
*/
void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){
  if( pParse->nErr ) return;
  if( p && p->x.pList && !ExprHasProperty(p, EP_xIsSelect) ){
  if( p && ExprUseXList(p) && p->x.pList ){
    p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList);
  }
}
#define exprSetHeight(y)
#endif /* SQLITE_MAX_EXPR_DEPTH>0 */

/*
768
769
770
771
772
773
774
775

776
777
778
779
780
781
782
783
784

785
786
787
788
789
790
791
931
932
933
934
935
936
937

938
939
940
941
942
943
944
945


946
947
948
949
950
951
952
953







-
+







-
-
+







  pNew = sqlite3DbMallocRawNN(db, sizeof(Expr)+nExtra);
  if( pNew ){
    memset(pNew, 0, sizeof(Expr));
    pNew->op = (u8)op;
    pNew->iAgg = -1;
    if( pToken ){
      if( nExtra==0 ){
        pNew->flags |= EP_IntValue|EP_Leaf;
        pNew->flags |= EP_IntValue|EP_Leaf|(iValue?EP_IsTrue:EP_IsFalse);
        pNew->u.iValue = iValue;
      }else{
        pNew->u.zToken = (char*)&pNew[1];
        assert( pToken->z!=0 || pToken->n==0 );
        if( pToken->n ) memcpy(pNew->u.zToken, pToken->z, pToken->n);
        pNew->u.zToken[pToken->n] = 0;
        if( dequote && sqlite3Isquote(pNew->u.zToken[0]) ){
          if( pNew->u.zToken[0]=='"' ) pNew->flags |= EP_DblQuoted;
          sqlite3Dequote(pNew->u.zToken);
          sqlite3DequoteExpr(pNew);
        }
      }
    }
#if SQLITE_MAX_EXPR_DEPTH>0
    pNew->nHeight = 1;
#endif  
  }
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

900









901
902
903
904
905
906
907
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

935
936
937
938
939
940
941
942
943
944
945

946
947
948
949
950
951
952
953
954
955



956



957
958
959
960
961

962
963
964
965


































966
967
968
969
970
971
972
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005

1006

1007
1008
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







+
+



+
+
+
+
+




+
+
+
-
+
-
+
+

















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

-
-

+
+
+



















-

-
-
-
+
+
+
+

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

-
+
-
-
+

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










-
-
+
+
+



-
-
-
-
+
+
+
+
+
+

-
-
-
+










-
+










+
+
+
-
+
+
+




-
+




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







  Expr *pRight
){
  if( pRoot==0 ){
    assert( db->mallocFailed );
    sqlite3ExprDelete(db, pLeft);
    sqlite3ExprDelete(db, pRight);
  }else{
    assert( ExprUseXList(pRoot) );
    assert( pRoot->x.pSelect==0 );
    if( pRight ){
      pRoot->pRight = pRight;
      pRoot->flags |= EP_Propagate & pRight->flags;
#if SQLITE_MAX_EXPR_DEPTH>0
      pRoot->nHeight = pRight->nHeight+1;
    }else{
      pRoot->nHeight = 1;
#endif
    }
    if( pLeft ){
      pRoot->pLeft = pLeft;
      pRoot->flags |= EP_Propagate & pLeft->flags;
#if SQLITE_MAX_EXPR_DEPTH>0
      if( pLeft->nHeight>=pRoot->nHeight ){
        pRoot->nHeight = pLeft->nHeight+1;
    }
      }
    exprSetHeight(pRoot);
#endif
    }
  }
}

/*
** Allocate an Expr node which joins as many as two subtrees.
**
** One or both of the subtrees can be NULL.  Return a pointer to the new
** Expr node.  Or, if an OOM error occurs, set pParse->db->mallocFailed,
** free the subtrees and return NULL.
*/
Expr *sqlite3PExpr(
  Parse *pParse,          /* Parsing context */
  int op,                 /* Expression opcode */
  Expr *pLeft,            /* Left operand */
  Expr *pRight            /* Right operand */
){
  Expr *p;
  if( op==TK_AND && pParse->nErr==0 ){
    /* Take advantage of short-circuit false optimization for AND */
    p = sqlite3ExprAnd(pParse->db, pLeft, pRight);
  }else{
    p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr));
    if( p ){
      memset(p, 0, sizeof(Expr));
      p->op = op & TKFLG_MASK;
      p->iAgg = -1;
  p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr));
  if( p ){
    memset(p, 0, sizeof(Expr));
    p->op = op & 0xff;
    p->iAgg = -1;
    }
    sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight);
  }
  if( p ) {
    sqlite3ExprCheckHeight(pParse, p->nHeight);
  }else{
    sqlite3ExprDelete(pParse->db, pLeft);
    sqlite3ExprDelete(pParse->db, pRight);
  }
  return p;
}

/*
** Add pSelect to the Expr.x.pSelect field.  Or, if pExpr is NULL (due
** do a memory allocation failure) then delete the pSelect object.
*/
void sqlite3PExprAddSelect(Parse *pParse, Expr *pExpr, Select *pSelect){
  if( pExpr ){
    pExpr->x.pSelect = pSelect;
    ExprSetProperty(pExpr, EP_xIsSelect|EP_Subquery);
    sqlite3ExprSetHeightAndFlags(pParse, pExpr);
  }else{
    assert( pParse->db->mallocFailed );
    sqlite3SelectDelete(pParse->db, pSelect);
  }
}


/*
** If the expression is always either TRUE or FALSE (respectively),
** then return 1.  If one cannot determine the truth value of the
** expression at compile-time return 0.
** Expression list pEList is a list of vector values. This function
** converts the contents of pEList to a VALUES(...) Select statement
** returning 1 row for each element of the list. For example, the 
** expression list:
**
** This is an optimization.  If is OK to return 0 here even if
** the expression really is always false or false (a false negative).
** But it is a bug to return 1 if the expression might have different
** boolean values in different circumstances (a false positive.)
**   ( (1,2), (3,4) (5,6) )
**
** is translated to the equivalent of:
**
**   VALUES(1,2), (3,4), (5,6)
**
** Each of the vector values in pEList must contain exactly nElem terms.
** If a list element that is not a vector or does not contain nElem terms,
** an error message is left in pParse.
**
** Note that if the expression is part of conditional for a
** This is used as part of processing IN(...) expressions with a list
** LEFT JOIN, then we cannot determine at compile-time whether or not
** is it true or false, so always return 0.
** of vectors on the RHS. e.g. "... IN ((1,2), (3,4), (5,6))".
*/
Select *sqlite3ExprListToValues(Parse *pParse, int nElem, ExprList *pEList){
  int ii;
  Select *pRet = 0;
  assert( nElem>1 );
  for(ii=0; ii<pEList->nExpr; ii++){
    Select *pSel;
    Expr *pExpr = pEList->a[ii].pExpr;
    int nExprElem;
    if( pExpr->op==TK_VECTOR ){
static int exprAlwaysTrue(Expr *p){
  int v = 0;
  if( ExprHasProperty(p, EP_FromJoin) ) return 0;
  if( !sqlite3ExprIsInteger(p, &v) ) return 0;
  return v!=0;
}
static int exprAlwaysFalse(Expr *p){
  int v = 0;
  if( ExprHasProperty(p, EP_FromJoin) ) return 0;
  if( !sqlite3ExprIsInteger(p, &v) ) return 0;
  return v==0;
      assert( ExprUseXList(pExpr) );
      nExprElem = pExpr->x.pList->nExpr;
    }else{
      nExprElem = 1;
    }
    if( nExprElem!=nElem ){
      sqlite3ErrorMsg(pParse, "IN(...) element has %d term%s - expected %d", 
          nExprElem, nExprElem>1?"s":"", nElem
      );
      break;
    }
    assert( ExprUseXList(pExpr) );
    pSel = sqlite3SelectNew(pParse, pExpr->x.pList, 0, 0, 0, 0, 0, SF_Values,0);
    pExpr->x.pList = 0;
    if( pSel ){
      if( pRet ){
        pSel->op = TK_ALL;
        pSel->pPrior = pRet;
      }
      pRet = pSel;
    }
  }

  if( pRet && pRet->pPrior ){
    pRet->selFlags |= SF_MultiValue;
  }
  sqlite3ExprListDelete(pParse->db, pEList);
  return pRet;
}

/*
** Join two expressions using an AND operator.  If either expression is
** NULL, then just return the other expression.
**
** If one side or the other of the AND is known to be false, then instead
** of returning an AND expression, just return a constant expression with
** a value of false.
*/
Expr *sqlite3ExprAnd(sqlite3 *db, Expr *pLeft, Expr *pRight){
  if( pLeft==0 ){
Expr *sqlite3ExprAnd(Parse *pParse, Expr *pLeft, Expr *pRight){
  sqlite3 *db = pParse->db;
  if( pLeft==0  ){
    return pRight;
  }else if( pRight==0 ){
    return pLeft;
  }else if( exprAlwaysFalse(pLeft) || exprAlwaysFalse(pRight) ){
    sqlite3ExprDelete(db, pLeft);
    sqlite3ExprDelete(db, pRight);
    return sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[0], 0);
  }else if( (ExprAlwaysFalse(pLeft) || ExprAlwaysFalse(pRight)) 
         && !IN_RENAME_OBJECT
  ){
    sqlite3ExprDeferredDelete(pParse, pLeft);
    sqlite3ExprDeferredDelete(pParse, pRight);
    return sqlite3Expr(db, TK_INTEGER, "0");
  }else{
    Expr *pNew = sqlite3ExprAlloc(db, TK_AND, 0, 0);
    sqlite3ExprAttachSubtrees(db, pNew, pLeft, pRight);
    return pNew;
    return sqlite3PExpr(pParse, TK_AND, pLeft, pRight);
  }
}

/*
** Construct a new expression node for a function with multiple
** arguments.
*/
Expr *sqlite3ExprFunction(
  Parse *pParse,        /* Parsing context */
  ExprList *pList,      /* Argument list */
  Token *pToken,        /* Name of the function */
  const Token *pToken,  /* Name of the function */
  int eDistinct         /* SF_Distinct or SF_ALL or 0 */
){
  Expr *pNew;
  sqlite3 *db = pParse->db;
  assert( pToken );
  pNew = sqlite3ExprAlloc(db, TK_FUNCTION, pToken, 1);
  if( pNew==0 ){
    sqlite3ExprListDelete(db, pList); /* Avoid memory leak when malloc fails */
    return 0;
  }
  assert( !ExprHasProperty(pNew, EP_InnerON|EP_OuterON) );
  pNew->w.iOfst = (int)(pToken->z - pParse->zTail);
  if( pList 
  if( pList && pList->nExpr > pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
   && pList->nExpr > pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG]
   && !pParse->nested
  ){
    sqlite3ErrorMsg(pParse, "too many arguments on function %T", pToken);
  }
  pNew->x.pList = pList;
  ExprSetProperty(pNew, EP_HasFunc);
  assert( !ExprHasProperty(pNew, EP_xIsSelect) );
  assert( ExprUseXList(pNew) );
  sqlite3ExprSetHeightAndFlags(pParse, pNew);
  if( eDistinct==SF_Distinct ) ExprSetProperty(pNew, EP_Distinct);
  return pNew;
}

/*
** Check to see if a function is usable according to current access
** rules:
**
**    SQLITE_FUNC_DIRECT    -     Only usable from top-level SQL
**
**    SQLITE_FUNC_UNSAFE    -     Usable if TRUSTED_SCHEMA or from
**                                top-level SQL
**
** If the function is not usable, create an error.
*/
void sqlite3ExprFunctionUsable(
  Parse *pParse,         /* Parsing and code generating context */
  const Expr *pExpr,     /* The function invocation */
  const FuncDef *pDef    /* The function being invoked */
){
  assert( !IN_RENAME_OBJECT );
  assert( (pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE))!=0 );
  if( ExprHasProperty(pExpr, EP_FromDDL) ){
    if( (pDef->funcFlags & SQLITE_FUNC_DIRECT)!=0
     || (pParse->db->flags & SQLITE_TrustedSchema)==0
    ){
      /* Functions prohibited in triggers and views if:
      **     (1) tagged with SQLITE_DIRECTONLY
      **     (2) not tagged with SQLITE_INNOCUOUS (which means it
      **         is tagged with SQLITE_FUNC_UNSAFE) and 
      **         SQLITE_DBCONFIG_TRUSTED_SCHEMA is off (meaning
      **         that the schema is possibly tainted).
      */
      sqlite3ErrorMsg(pParse, "unsafe use of %#T()", pExpr);
    }
  }
}

/*
** Assign a variable number to an expression that encodes a wildcard
** in the original SQL statement.  
**
** Wildcards consisting of a single "?" are assigned the next sequential
** variable number.
1011
1012
1013
1014
1015
1016
1017

1018
1019
1020
1021
1022
1023
1024
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264







+







      testcase( i==0 );
      testcase( i==1 );
      testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 );
      testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] );
      if( bOk==0 || i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
        sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d",
            db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]);
        sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr);
        return;
      }
      x = (ynVar)i;
      if( x>pParse->nVar ){
        pParse->nVar = (int)x;
        doAdd = 1;
      }else if( sqlite3VListNumToName(pParse->pVList, x)==0 ){
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
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
1318


1319
1320




1321
1322
1323
1324

1325
1326

1327
1328
1329
1330
1331
1332
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







+








-
-
-
-
-
+
+
+
+
+
-




-
+
+




-
+


+

+
-
+



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

-
+





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






-
+







    if( doAdd ){
      pParse->pVList = sqlite3VListAdd(db, pParse->pVList, z, n, x);
    }
  }
  pExpr->iColumn = x;
  if( x>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
    sqlite3ErrorMsg(pParse, "too many SQL variables");
    sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr);
  }
}

/*
** Recursively delete an expression tree.
*/
static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
  assert( p!=0 );
  /* Sanity check: Assert that the IntValue is non-negative if it exists */
  assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 );

  assert( !ExprHasProperty(p, EP_WinFunc) || p->y.pWin!=0 || db->mallocFailed );
  assert( p->op!=TK_FUNCTION || ExprHasProperty(p, EP_TokenOnly|EP_Reduced)
  assert( db!=0 );
  assert( !ExprUseUValue(p) || p->u.iValue>=0 );
  assert( !ExprUseYWin(p) || !ExprUseYSub(p) );
  assert( !ExprUseYWin(p) || p->y.pWin!=0 || db->mallocFailed );
  assert( p->op!=TK_FUNCTION || !ExprUseYSub(p) );
          || p->y.pWin==0 || ExprHasProperty(p, EP_WinFunc) );
#ifdef SQLITE_DEBUG
  if( ExprHasProperty(p, EP_Leaf) && !ExprHasProperty(p, EP_TokenOnly) ){
    assert( p->pLeft==0 );
    assert( p->pRight==0 );
    assert( p->x.pSelect==0 );
    assert( !ExprUseXSelect(p) || p->x.pSelect==0 );
    assert( !ExprUseXList(p) || p->x.pList==0 );
  }
#endif
  if( !ExprHasProperty(p, (EP_TokenOnly|EP_Leaf)) ){
    /* The Expr.x union is never used at the same time as Expr.pRight */
    assert( p->x.pList==0 || p->pRight==0 );
    assert( (ExprUseXList(p) && p->x.pList==0) || p->pRight==0 );
    if( p->pLeft && p->op!=TK_SELECT_COLUMN ) sqlite3ExprDeleteNN(db, p->pLeft);
    if( p->pRight ){
      assert( !ExprHasProperty(p, EP_WinFunc) );
      sqlite3ExprDeleteNN(db, p->pRight);
    }else if( ExprUseXSelect(p) ){
    }else if( ExprHasProperty(p, EP_xIsSelect) ){
      assert( !ExprHasProperty(p, EP_WinFunc) );
      sqlite3SelectDelete(db, p->x.pSelect);
    }else{
      sqlite3ExprListDelete(db, p->x.pList);
    }
    if( ExprHasProperty(p, EP_WinFunc) ){
#ifndef SQLITE_OMIT_WINDOWFUNC
      if( ExprHasProperty(p, EP_WinFunc) ){
      assert( p->op==TK_FUNCTION );
      sqlite3WindowDelete(db, p->y.pWin);
    }
  }
        sqlite3WindowDelete(db, p->y.pWin);
      }
#endif
    }
  if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken);
  }
  if( !ExprHasProperty(p, EP_Static) ){
    sqlite3DbFreeNN(db, p);
    sqlite3DbNNFreeNN(db, p);
  }
}
void sqlite3ExprDelete(sqlite3 *db, Expr *p){
  if( p ) sqlite3ExprDeleteNN(db, p);
}

/*
** Clear both elements of an OnOrUsing object
*/
void sqlite3ClearOnOrUsing(sqlite3 *db, OnOrUsing *p){
  if( p==0 ){
    /* Nothing to clear */
  }else if( p->pOn ){
    sqlite3ExprDeleteNN(db, p->pOn);
  }else if( p->pUsing ){
    sqlite3IdListDelete(db, p->pUsing);
  }
}

/*
** 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){
  sqlite3ParserAddCleanup(pParse,
    (void(*)(sqlite3*,void*))sqlite3ExprDelete,
    pExpr);
}

/* Invoke sqlite3RenameExprUnmap() and sqlite3ExprDelete() on the
** expression.
*/
void sqlite3ExprUnmapAndDelete(Parse *pParse, Expr *p){
  if( p ){
    if( IN_RENAME_OBJECT ){
      sqlite3RenameExprUnmap(pParse, p);
    }
    sqlite3ExprDeleteNN(pParse->db, p);
  }
}

/*
** Return the number of bytes allocated for the expression structure 
** passed as the first argument. This is always one of EXPR_FULLSIZE,
** EXPR_REDUCEDSIZE or EXPR_TOKENONLYSIZE.
*/
static int exprStructSize(Expr *p){
static int exprStructSize(const Expr *p){
  if( ExprHasProperty(p, EP_TokenOnly) ) return EXPR_TOKENONLYSIZE;
  if( ExprHasProperty(p, EP_Reduced) ) return EXPR_REDUCEDSIZE;
  return EXPR_FULLSIZE;
}

/*
** The dupedExpr*Size() routines each return the number of bytes required
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
1413
1414
1415
1416
1417
1418
1419

1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432

1433


1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449

1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470

1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489

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







-
+












-
+
-
-
+















-
+




















-
+


















-
+













+







** later parts of the Expr object and that extra information might get chopped
** off if the expression is reduced.  Note also that it does not work to
** make an EXPRDUP_REDUCE copy of a reduced expression.  It is only legal
** to reduce a pristine expression tree from the parser.  The implementation
** of dupedExprStructSize() contain multiple assert() statements that attempt
** to enforce this constraint.
*/
static int dupedExprStructSize(Expr *p, int flags){
static int dupedExprStructSize(const Expr *p, int flags){
  int nSize;
  assert( flags==EXPRDUP_REDUCE || flags==0 ); /* Only one flag value allowed */
  assert( EXPR_FULLSIZE<=0xfff );
  assert( (0xfff & (EP_Reduced|EP_TokenOnly))==0 );
  if( 0==flags || p->op==TK_SELECT_COLUMN 
#ifndef SQLITE_OMIT_WINDOWFUNC
   || ExprHasProperty(p, EP_WinFunc)
#endif
  ){
    nSize = EXPR_FULLSIZE;
  }else{
    assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
    assert( !ExprHasProperty(p, EP_FromJoin) ); 
    assert( !ExprHasProperty(p, EP_OuterON) ); 
    assert( !ExprHasProperty(p, EP_MemToken) );
    assert( !ExprHasProperty(p, EP_NoReduce) );
    assert( !ExprHasVVAProperty(p, EP_NoReduce) );
    if( p->pLeft || p->x.pList ){
      nSize = EXPR_REDUCEDSIZE | EP_Reduced;
    }else{
      assert( p->pRight==0 );
      nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly;
    }
  }
  return nSize;
}

/*
** This function returns the space in bytes required to store the copy 
** of the Expr structure and a copy of the Expr.u.zToken string (if that
** string is defined.)
*/
static int dupedExprNodeSize(Expr *p, int flags){
static int dupedExprNodeSize(const Expr *p, int flags){
  int nByte = dupedExprStructSize(p, flags) & 0xfff;
  if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){
    nByte += sqlite3Strlen30NN(p->u.zToken)+1;
  }
  return ROUND8(nByte);
}

/*
** Return the number of bytes required to create a duplicate of the 
** expression passed as the first argument. The second argument is a
** mask containing EXPRDUP_XXX flags.
**
** The value returned includes space to create a copy of the Expr struct
** itself and the buffer referred to by Expr.u.zToken, if any.
**
** If the EXPRDUP_REDUCE flag is set, then the return value includes 
** space to duplicate all Expr nodes in the tree formed by Expr.pLeft 
** and Expr.pRight variables (but not for any structures pointed to or 
** descended from the Expr.x.pList or Expr.x.pSelect variables).
*/
static int dupedExprSize(Expr *p, int flags){
static int dupedExprSize(const Expr *p, int flags){
  int nByte = 0;
  if( p ){
    nByte = dupedExprNodeSize(p, flags);
    if( flags&EXPRDUP_REDUCE ){
      nByte += dupedExprSize(p->pLeft, flags) + dupedExprSize(p->pRight, flags);
    }
  }
  return nByte;
}

/*
** This function is similar to sqlite3ExprDup(), except that if pzBuffer 
** is not NULL then *pzBuffer is assumed to point to a buffer large enough 
** to store the copy of expression p, the copies of p->u.zToken
** (if applicable), and the copies of the p->pLeft and p->pRight expressions,
** if any. Before returning, *pzBuffer is set to the first byte past the
** portion of the buffer copied into by this function.
*/
static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
static Expr *exprDup(sqlite3 *db, const Expr *p, int dupFlags, u8 **pzBuffer){
  Expr *pNew;           /* Value to return */
  u8 *zAlloc;           /* Memory space from which to build Expr object */
  u32 staticFlag;       /* EP_Static if space not obtained from malloc */

  assert( db!=0 );
  assert( p );
  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 ){
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
1530
1531
1532
1533
1534
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







-
+


+
+
+
+









-
+







      memcpy(zAlloc, p, nSize);
      if( nSize<EXPR_FULLSIZE ){ 
        memset(&zAlloc[nSize], 0, EXPR_FULLSIZE-nSize);
      }
    }

    /* Set the EP_Reduced, EP_TokenOnly, and EP_Static flags appropriately. */
    pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static|EP_MemToken);
    pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static);
    pNew->flags |= nStructSize & (EP_Reduced|EP_TokenOnly);
    pNew->flags |= staticFlag;
    ExprClearVVAProperties(pNew);
    if( dupFlags ){
      ExprSetVVAProperty(pNew, EP_Immutable);
    }

    /* Copy the p->u.zToken string, if any. */
    if( nToken ){
      char *zToken = pNew->u.zToken = (char*)&zAlloc[nNewSize];
      memcpy(zToken, p->u.zToken, nToken);
    }

    if( 0==((p->flags|pNew->flags) & (EP_TokenOnly|EP_Leaf)) ){
      /* Fill in the pNew->x.pSelect or pNew->x.pList member. */
      if( ExprHasProperty(p, EP_xIsSelect) ){
      if( ExprUseXSelect(p) ){
        pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, dupFlags);
      }else{
        pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, dupFlags);
      }
    }

    /* Fill in pNew->pLeft and pNew->pRight. */
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
1318
1319
1320
1321
1322
1323

1324
1325
1326
1327
1328
1329
1330

1331
1332
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
1575
1576
1577
1578
1579
1580
1581


1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599

1600
1601
1602

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

1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629

1630



1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655







-
-
+
+
















-
+


-
+








+






-
+










-
+
-
-
-
+
+
+
+
+
+











+







      if( pzBuffer ){
        *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);
      }
    }
  }
  return pNew;
}

/*
** Create and return a deep copy of the object passed as the second 
** argument. If an OOM condition is encountered, NULL is returned
** and the db->mallocFailed flag set.
*/
#ifndef SQLITE_OMIT_CTE
static With *withDup(sqlite3 *db, With *p){
With *sqlite3WithDup(sqlite3 *db, With *p){
  With *pRet = 0;
  if( p ){
    int nByte = sizeof(*p) + sizeof(p->a[0]) * (p->nCte-1);
    sqlite3_int64 nByte = sizeof(*p) + sizeof(p->a[0]) * (p->nCte-1);
    pRet = sqlite3DbMallocZero(db, nByte);
    if( pRet ){
      int i;
      pRet->nCte = p->nCte;
      for(i=0; i<p->nCte; i++){
        pRet->a[i].pSelect = sqlite3SelectDup(db, p->a[i].pSelect, 0);
        pRet->a[i].pCols = sqlite3ExprListDup(db, p->a[i].pCols, 0);
        pRet->a[i].zName = sqlite3DbStrDup(db, p->a[i].zName);
        pRet->a[i].eM10d = p->a[i].eM10d;
      }
    }
  }
  return pRet;
}
#else
# define withDup(x,y) 0
# define sqlite3WithDup(x,y) 0
#endif

#ifndef SQLITE_OMIT_WINDOWFUNC
/*
** The gatherSelectWindows() procedure and its helper routine
** gatherSelectWindowsCallback() are used to scan all the expressions
** an a newly duplicated SELECT statement and gather all of the Window
** objects found there, assembling them onto the linked list at Select->pWin.
*/
static int gatherSelectWindowsCallback(Walker *pWalker, Expr *pExpr){
  if( pExpr->op==TK_FUNCTION && pExpr->y.pWin!=0 ){
  if( pExpr->op==TK_FUNCTION && ExprHasProperty(pExpr, EP_WinFunc) ){
    assert( ExprHasProperty(pExpr, EP_WinFunc) );
    pExpr->y.pWin->pNextWin = pWalker->u.pSelect->pWin;
    pWalker->u.pSelect->pWin = pExpr->y.pWin;
    Select *pSelect = pWalker->u.pSelect;
    Window *pWin = pExpr->y.pWin;
    assert( pWin );
    assert( IsWindowFunc(pExpr) );
    assert( pWin->ppThis==0 );
    sqlite3WindowLink(pSelect, pWin);
  }
  return WRC_Continue;
}
static int gatherSelectWindowsSelectCallback(Walker *pWalker, Select *p){
  return p==pWalker->u.pSelect ? WRC_Continue : WRC_Prune;
}
static void gatherSelectWindows(Select *p){
  Walker w;
  w.xExprCallback = gatherSelectWindowsCallback;
  w.xSelectCallback = gatherSelectWindowsSelectCallback;
  w.xSelectCallback2 = 0;
  w.pParse = 0;
  w.u.pSelect = p;
  sqlite3WalkSelect(&w, p);
}
#endif


/*
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
1430
1431
1432
1433
1434

1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446


1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459




1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470






1471
1472
1473
1474
1475

1476
1477
1478
1479

1480

1481
1482
1483
1484

1485
1486
1487
1488
1489
1490
1491
1492
1493

1494
1495

1496
1497
1498
1499

1500
1501
1502
1503

1504
1505
1506
1507
1508
1509
1510
1665
1666
1667
1668
1669
1670
1671

1672
1673
1674
1675

1676
1677

1678
1679
1680

1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698




1699
1700
1701
1702
1703





1704
1705
1706
1707
1708
1709
1710
1711

1712



1713
1714


1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727

1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738


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

1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765


1766
1767
1768
1769
1770
1771
1772
1773
1774
1775

1776
1777
1778
1779
1780
1781

1782
1783
1784


1785






1786
1787

1788
1789

1790
1791
1792
1793

1794
1795
1796
1797

1798
1799
1800
1801
1802
1803
1804
1805







-
+



-
+

-
+
+

-
+
+





+










-
-
-
-
+
+
+
+

-
-
-
-
-
+
+
+
+
+
+


-
+
-
-
-
+
+
-
-













-
+










-
-
+
+












-
+
+
+
+









-
-
+
+
+
+
+
+




-
+




+
-
+


-
-
+
-
-
-
-
-
-


-
+

-
+



-
+



-
+







** Any tables that the SrcList might point to are not duplicated.
**
** The flags parameter contains a combination of the EXPRDUP_XXX flags.
** If the EXPRDUP_REDUCE flag is set, then the structure returned is a
** truncated version of the usual Expr structure that will be stored as
** part of the in-memory representation of the database schema.
*/
Expr *sqlite3ExprDup(sqlite3 *db, Expr *p, int flags){
Expr *sqlite3ExprDup(sqlite3 *db, const Expr *p, int flags){
  assert( flags==0 || flags==EXPRDUP_REDUCE );
  return p ? exprDup(db, p, flags, 0) : 0;
}
ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
ExprList *sqlite3ExprListDup(sqlite3 *db, const ExprList *p, int flags){
  ExprList *pNew;
  struct ExprList_item *pItem, *pOldItem;
  struct ExprList_item *pItem;
  const struct ExprList_item *pOldItem;
  int i;
  Expr *pPriorSelectCol = 0;
  Expr *pPriorSelectColOld = 0;
  Expr *pPriorSelectColNew = 0;
  assert( db!=0 );
  if( p==0 ) return 0;
  pNew = sqlite3DbMallocRawNN(db, sqlite3DbMallocSize(db, p));
  if( pNew==0 ) return 0;
  pNew->nExpr = p->nExpr;
  pNew->nAlloc = p->nAlloc;
  pItem = pNew->a;
  pOldItem = p->a;
  for(i=0; i<p->nExpr; i++, pItem++, pOldItem++){
    Expr *pOldExpr = pOldItem->pExpr;
    Expr *pNewExpr;
    pItem->pExpr = sqlite3ExprDup(db, pOldExpr, flags);
    if( pOldExpr 
     && pOldExpr->op==TK_SELECT_COLUMN
     && (pNewExpr = pItem->pExpr)!=0 
    ){
      assert( pNewExpr->iColumn==0 || i>0 );
      if( pNewExpr->iColumn==0 ){
        assert( pOldExpr->pLeft==pOldExpr->pRight );
        pPriorSelectCol = pNewExpr->pLeft = pNewExpr->pRight;
      if( pNewExpr->pRight ){
        pPriorSelectColOld = pOldExpr->pRight;
        pPriorSelectColNew = pNewExpr->pRight;
        pNewExpr->pLeft = pNewExpr->pRight;
      }else{
        assert( i>0 );
        assert( pItem[-1].pExpr!=0 );
        assert( pNewExpr->iColumn==pItem[-1].pExpr->iColumn+1 );
        assert( pPriorSelectCol==pItem[-1].pExpr->pLeft );
        pNewExpr->pLeft = pPriorSelectCol;
        if( pOldExpr->pLeft!=pPriorSelectColOld ){
          pPriorSelectColOld = pOldExpr->pLeft;
          pPriorSelectColNew = sqlite3ExprDup(db, pPriorSelectColOld, flags);
          pNewExpr->pRight = pPriorSelectColNew;
        }
        pNewExpr->pLeft = pPriorSelectColNew;
      }
    }
    pItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
    pItem->zEName = sqlite3DbStrDup(db, pOldItem->zEName);
    pItem->zSpan = sqlite3DbStrDup(db, pOldItem->zSpan);
    pItem->sortOrder = pOldItem->sortOrder;
    pItem->done = 0;
    pItem->fg = pOldItem->fg;
    pItem->fg.done = 0;
    pItem->bSpanIsTab = pOldItem->bSpanIsTab;
    pItem->bSorterRef = pOldItem->bSorterRef;
    pItem->u = pOldItem->u;
  }
  return pNew;
}

/*
** If cursors, triggers, views and subqueries are all omitted from
** the build, then none of the following routines, except for 
** sqlite3SelectDup(), can be called. sqlite3SelectDup() is sometimes
** called with a NULL argument.
*/
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) \
 || !defined(SQLITE_OMIT_SUBQUERY)
SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){
SrcList *sqlite3SrcListDup(sqlite3 *db, const SrcList *p, int flags){
  SrcList *pNew;
  int i;
  int nByte;
  assert( db!=0 );
  if( p==0 ) return 0;
  nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0);
  pNew = sqlite3DbMallocRawNN(db, nByte );
  if( pNew==0 ) return 0;
  pNew->nSrc = pNew->nAlloc = p->nSrc;
  for(i=0; i<p->nSrc; i++){
    struct SrcList_item *pNewItem = &pNew->a[i];
    struct SrcList_item *pOldItem = &p->a[i];
    SrcItem *pNewItem = &pNew->a[i];
    const SrcItem *pOldItem = &p->a[i];
    Table *pTab;
    pNewItem->pSchema = pOldItem->pSchema;
    pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase);
    pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
    pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
    pNewItem->fg = pOldItem->fg;
    pNewItem->iCursor = pOldItem->iCursor;
    pNewItem->addrFillSub = pOldItem->addrFillSub;
    pNewItem->regReturn = pOldItem->regReturn;
    if( pNewItem->fg.isIndexedBy ){
      pNewItem->u1.zIndexedBy = sqlite3DbStrDup(db, pOldItem->u1.zIndexedBy);
    }
    pNewItem->pIBIndex = pOldItem->pIBIndex;
    pNewItem->u2 = pOldItem->u2;
    if( pNewItem->fg.isCte ){
      pNewItem->u2.pCteUse->nUse++;
    }
    if( pNewItem->fg.isTabFunc ){
      pNewItem->u1.pFuncArg = 
          sqlite3ExprListDup(db, pOldItem->u1.pFuncArg, flags);
    }
    pTab = pNewItem->pTab = pOldItem->pTab;
    if( pTab ){
      pTab->nTabRef++;
    }
    pNewItem->pSelect = sqlite3SelectDup(db, pOldItem->pSelect, flags);
    pNewItem->pOn = sqlite3ExprDup(db, pOldItem->pOn, flags);
    pNewItem->pUsing = sqlite3IdListDup(db, pOldItem->pUsing);
    if( pOldItem->fg.isUsing ){
      assert( pNewItem->fg.isUsing );
      pNewItem->u3.pUsing = sqlite3IdListDup(db, pOldItem->u3.pUsing);
    }else{
      pNewItem->u3.pOn = sqlite3ExprDup(db, pOldItem->u3.pOn, flags);
    }
    pNewItem->colUsed = pOldItem->colUsed;
  }
  return pNew;
}
IdList *sqlite3IdListDup(sqlite3 *db, IdList *p){
IdList *sqlite3IdListDup(sqlite3 *db, const IdList *p){
  IdList *pNew;
  int i;
  assert( db!=0 );
  if( p==0 ) return 0;
  assert( p->eU4!=EU4_EXPR );
  pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew) );
  pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew)+(p->nId-1)*sizeof(p->a[0]) );
  if( pNew==0 ) return 0;
  pNew->nId = p->nId;
  pNew->a = sqlite3DbMallocRawNN(db, p->nId*sizeof(p->a[0]) );
  if( pNew->a==0 ){
  pNew->eU4 = p->eU4;
    sqlite3DbFreeNN(db, pNew);
    return 0;
  }
  /* Note that because the size of the allocation for p->a[] is not
  ** necessarily a power of two, sqlite3IdListAppend() may not be called
  ** on the duplicate created by this function. */
  for(i=0; i<p->nId; i++){
    struct IdList_item *pNewItem = &pNew->a[i];
    struct IdList_item *pOldItem = &p->a[i];
    const struct IdList_item *pOldItem = &p->a[i];
    pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
    pNewItem->idx = pOldItem->idx;
    pNewItem->u4 = pOldItem->u4;
  }
  return pNew;
}
Select *sqlite3SelectDup(sqlite3 *db, Select *pDup, int flags){
Select *sqlite3SelectDup(sqlite3 *db, const Select *pDup, int flags){
  Select *pRet = 0;
  Select *pNext = 0;
  Select **pp = &pRet;
  Select *p;
  const Select *p;

  assert( db!=0 );
  for(p=pDup; p; p=p->pPrior){
    Select *pNew = sqlite3DbMallocRawNN(db, sizeof(*p) );
    if( pNew==0 ) break;
    pNew->pEList = sqlite3ExprListDup(db, p->pEList, flags);
    pNew->pSrc = sqlite3SrcListDup(db, p->pSrc, flags);
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
1546
1547
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







-
+



-
+


+
+
+
+
+
+
+
+








-
+







    pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags);
    pNew->iLimit = 0;
    pNew->iOffset = 0;
    pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
    pNew->addrOpenEphm[0] = -1;
    pNew->addrOpenEphm[1] = -1;
    pNew->nSelectRow = p->nSelectRow;
    pNew->pWith = withDup(db, p->pWith);
    pNew->pWith = sqlite3WithDup(db, p->pWith);
#ifndef SQLITE_OMIT_WINDOWFUNC
    pNew->pWin = 0;
    pNew->pWinDefn = sqlite3WindowListDup(db, p->pWinDefn);
    if( p->pWin ) gatherSelectWindows(pNew);
    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;
}
#else
Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
Select *sqlite3SelectDup(sqlite3 *db, const Select *p, int flags){
  assert( p==0 );
  return 0;
}
#endif


/*
1555
1556
1557
1558
1559
1560
1561

1562
1563


1564
1565
1566
1567
1568
1569


1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583













































1584
1585
1586
1587
1588

1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1858
1859
1860
1861
1862
1863
1864
1865


1866
1867

1868
1869
1870


1871
1872














1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919



1920
1921
1922






1923
1924
1925
1926
1927
1928
1929







+
-
-
+
+
-



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


-
-
-
+


-
-
-
-
-
-







** 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*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,zName)==sizeof(pItem->pExpr) );
  assert( offsetof(struct ExprList_item,pExpr)==0 );
  memset(&pItem->zName,0,sizeof(*pItem)-offsetof(struct ExprList_item,zName));
  *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)
1630
1631
1632
1633
1634
1635
1636
1637



1638
1639
1640
1641

1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662

1663
1664
1665
1666
1667
1668
1669
1670


1671


1672
1673
1674
1675
1676














1677
1678








1679
1680
1681
1682

1683
1684
1685
1686
1687
1688
1689
1690
1691
1692

1693
1694
1695

1696
1697
1698
1699
1700
1701
1702
1703
1704











1705
1706
1707
1708
1709
1710
1711
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
1986
1987
1988
1989

1990
1991
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
2017

2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028

2029
2030
2031
2032
2033
2034
2035
2036
2037
2038

2039
2040
2041
2042
2043
2044
2045
2046
2047





2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065







-
+
+
+



-
+




















-
+







-
+
+

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

-
+
+
+
+
+
+
+
+



-
+









-
+



+




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







  if( pExpr->op!=TK_SELECT && pColumns->nId!=(n=sqlite3ExprVectorSize(pExpr)) ){
    sqlite3ErrorMsg(pParse, "%d columns assigned %d values",
                    pColumns->nId, n);
    goto vector_append_error;
  }

  for(i=0; i<pColumns->nId; i++){
    Expr *pSubExpr = sqlite3ExprForVectorField(pParse, pExpr, i);
    Expr *pSubExpr = sqlite3ExprForVectorField(pParse, pExpr, i, pColumns->nId);
    assert( pSubExpr!=0 || db->mallocFailed );
    if( pSubExpr==0 ) continue;
    pList = sqlite3ExprListAppend(pParse, pList, pSubExpr);
    if( pList ){
      assert( pList->nExpr==iFirst+i+1 );
      pList->a[pList->nExpr-1].zName = pColumns->a[i].zName;
      pList->a[pList->nExpr-1].zEName = pColumns->a[i].zName;
      pColumns->a[i].zName = 0;
    }
  }

  if( !db->mallocFailed && pExpr->op==TK_SELECT && ALWAYS(pList!=0) ){
    Expr *pFirst = pList->a[iFirst].pExpr;
    assert( pFirst!=0 );
    assert( pFirst->op==TK_SELECT_COLUMN );
     
    /* Store the SELECT statement in pRight so it will be deleted when
    ** sqlite3ExprListDelete() is called */
    pFirst->pRight = pExpr;
    pExpr = 0;

    /* Remember the size of the LHS in iTable so that we can check that
    ** the RHS and LHS sizes match during code generation. */
    pFirst->iTable = pColumns->nId;
  }

vector_append_error:
  sqlite3ExprDelete(db, pExpr);
  sqlite3ExprUnmapAndDelete(pParse, pExpr);
  sqlite3IdListDelete(db, pColumns);
  return pList;
}

/*
** Set the sort order for the last element on the given ExprList.
*/
void sqlite3ExprListSetSortOrder(ExprList *p, int iSortOrder){
void sqlite3ExprListSetSortOrder(ExprList *p, int iSortOrder, int eNulls){
  struct ExprList_item *pItem;
  if( p==0 ) return;
  assert( p->nExpr>0 );

  assert( SQLITE_SO_UNDEFINED<0 && SQLITE_SO_ASC>=0 && SQLITE_SO_DESC>0 );
  assert( p->nExpr>0 );
  if( iSortOrder<0 ){
    assert( p->a[p->nExpr-1].sortOrder==SQLITE_SO_ASC );
    return;
  assert( SQLITE_SO_UNDEFINED<0 && SQLITE_SO_ASC==0 && SQLITE_SO_DESC>0 );
  assert( iSortOrder==SQLITE_SO_UNDEFINED 
       || iSortOrder==SQLITE_SO_ASC 
       || iSortOrder==SQLITE_SO_DESC 
  );
  assert( eNulls==SQLITE_SO_UNDEFINED 
       || eNulls==SQLITE_SO_ASC 
       || eNulls==SQLITE_SO_DESC 
  );

  pItem = &p->a[p->nExpr-1];
  assert( pItem->fg.bNulls==0 );
  if( iSortOrder==SQLITE_SO_UNDEFINED ){
    iSortOrder = SQLITE_SO_ASC;
  }
  p->a[p->nExpr-1].sortOrder = (u8)iSortOrder;
  pItem->fg.sortFlags = (u8)iSortOrder;

  if( eNulls!=SQLITE_SO_UNDEFINED ){
    pItem->fg.bNulls = 1;
    if( iSortOrder!=eNulls ){
      pItem->fg.sortFlags |= KEYINFO_ORDER_BIGNULL;
    }
  }
}

/*
** Set the ExprList.a[].zName element of the most recently added item
** Set the ExprList.a[].zEName element of the most recently added item
** on the expression list.
**
** pList might be NULL following an OOM error.  But pName should never be
** NULL.  If a memory allocation fails, the pParse->db->mallocFailed flag
** is set.
*/
void sqlite3ExprListSetName(
  Parse *pParse,          /* Parsing context */
  ExprList *pList,        /* List to which to add the span. */
  Token *pName,           /* Name to be added */
  const Token *pName,     /* Name to be added */
  int dequote             /* True to cause the name to be dequoted */
){
  assert( pList!=0 || pParse->db->mallocFailed!=0 );
  assert( pParse->eParseMode!=PARSE_MODE_UNMAP || dequote==0 );
  if( pList ){
    struct ExprList_item *pItem;
    assert( pList->nExpr>0 );
    pItem = &pList->a[pList->nExpr-1];
    assert( pItem->zName==0 );
    pItem->zName = sqlite3DbStrNDup(pParse->db, pName->z, pName->n);
    if( dequote ) sqlite3Dequote(pItem->zName);
    if( IN_RENAME_OBJECT ){
      sqlite3RenameTokenMap(pParse, (void*)pItem->zName, pName);
    assert( pItem->zEName==0 );
    assert( pItem->fg.eEName==ENAME_NAME );
    pItem->zEName = sqlite3DbStrNDup(pParse->db, pName->z, pName->n);
    if( dequote ){
      /* If dequote==0, then pName->z does not point to part of a DDL
      ** statement handled by the parser. And so no token need be added
      ** to the token-map.  */
      sqlite3Dequote(pItem->zEName);
      if( IN_RENAME_OBJECT ){
        sqlite3RenameTokenMap(pParse, (const void*)pItem->zEName, pName);
      }
    }
  }
}

/*
** Set the ExprList.a[].zSpan element of the most recently added item
** on the expression list.
1721
1722
1723
1724
1725
1726
1727
1728
1729




1730
1731
1732
1733
1734
1735
1736
2075
2076
2077
2078
2079
2080
2081


2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092







-
-
+
+
+
+







  const char *zEnd        /* End of the span */
){
  sqlite3 *db = pParse->db;
  assert( pList!=0 || db->mallocFailed!=0 );
  if( pList ){
    struct ExprList_item *pItem = &pList->a[pList->nExpr-1];
    assert( pList->nExpr>0 );
    sqlite3DbFree(db, pItem->zSpan);
    pItem->zSpan = sqlite3DbSpanDup(db, zStart, zEnd);
    if( pItem->zEName==0 ){
      pItem->zEName = sqlite3DbSpanDup(db, zStart, zEnd);
      pItem->fg.eEName = ENAME_SPAN;
    }
  }
}

/*
** If the expression list pEList contains more than iLimit elements,
** leave an error message in pParse.
*/
1750
1751
1752
1753
1754
1755
1756

1757
1758
1759

1760
1761
1762
1763

1764
1765
1766
1767
1768
1769
1770
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115

2116

2117
2118

2119
2120
2121
2122
2123
2124
2125
2126







+


-
+
-


-
+







/*
** Delete an entire expression list.
*/
static SQLITE_NOINLINE void exprListDeleteNN(sqlite3 *db, ExprList *pList){
  int i = pList->nExpr;
  struct ExprList_item *pItem =  pList->a;
  assert( pList->nExpr>0 );
  assert( db!=0 );
  do{
    sqlite3ExprDelete(db, pItem->pExpr);
    sqlite3DbFree(db, pItem->zName);
    if( pItem->zEName ) sqlite3DbNNFreeNN(db, pItem->zEName);
    sqlite3DbFree(db, pItem->zSpan);
    pItem++;
  }while( --i>0 );
  sqlite3DbFreeNN(db, pList);
  sqlite3DbNNFreeNN(db, pList);
}
void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
  if( pList ) exprListDeleteNN(db, pList);
}

/*
** Return the bitwise-OR of all Expr.flags fields in the given
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
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177

2178

2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
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
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243





2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256

2257
2258

2259
2260
2261
2262
2263
2264
2265
2266
2267
2268

2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283

2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297

2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310

2311
2312
2313
2314
2315
2316
2317
2318

2319
2320
2321
2322
2323
2324
2325
2326







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







+

+
-
+
-


+










+

+




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


















-
-
-
-
-
+
+
+
+
+
+







-
+

-
+









-
+
+
+
+











-
+













-
+


+


+






-
+







-
+







** This callback is used by multiple expression walkers.
*/
int sqlite3SelectWalkFail(Walker *pWalker, Select *NotUsed){
  UNUSED_PARAMETER(NotUsed);
  pWalker->eCode = 0;
  return WRC_Abort;
}

/*
** Check the input string to see if it is "true" or "false" (in any case).
**
**       If the string is....           Return
**         "true"                         EP_IsTrue
**         "false"                        EP_IsFalse
**         anything else                  0
*/
u32 sqlite3IsTrueOrFalse(const char *zIn){
  if( sqlite3StrICmp(zIn, "true")==0  ) return EP_IsTrue;
  if( sqlite3StrICmp(zIn, "false")==0 ) return EP_IsFalse;
  return 0;
}


/*
** If the input expression is an ID with the name "true" or "false"
** then convert it into an TK_TRUEFALSE term.  Return non-zero if
** the conversion happened, and zero if the expression is unaltered.
*/
int sqlite3ExprIdToTrueFalse(Expr *pExpr){
  u32 v;
  assert( pExpr->op==TK_ID || pExpr->op==TK_STRING );
  if( !ExprHasProperty(pExpr, EP_Quoted|EP_IntValue)
  if( sqlite3StrICmp(pExpr->u.zToken, "true")==0
   && (v = sqlite3IsTrueOrFalse(pExpr->u.zToken))!=0
   || sqlite3StrICmp(pExpr->u.zToken, "false")==0
  ){
    pExpr->op = TK_TRUEFALSE;
    ExprSetProperty(pExpr, v);
    return 1;
  }
  return 0;
}

/*
** The argument must be a TK_TRUEFALSE Expr node.  Return 1 if it is TRUE
** and 0 if it is FALSE.
*/
int sqlite3ExprTruthValue(const Expr *pExpr){
  pExpr = sqlite3ExprSkipCollate((Expr*)pExpr);
  assert( pExpr->op==TK_TRUEFALSE );
  assert( !ExprHasProperty(pExpr, EP_IntValue) );
  assert( sqlite3StrICmp(pExpr->u.zToken,"true")==0
       || sqlite3StrICmp(pExpr->u.zToken,"false")==0 );
  return pExpr->u.zToken[4]==0;
}

/*
** If pExpr is an AND or OR expression, try to simplify it by eliminating
** terms that are always true or false.  Return the simplified expression.
** Or return the original expression if no simplification is possible.
**
** Examples:
**
**     (x<10) AND true                =>   (x<10)
**     (x<10) AND false               =>   false
**     (x<10) AND (y=22 OR false)     =>   (x<10) AND (y=22)
**     (x<10) AND (y=22 OR true)      =>   (x<10)
**     (y=22) OR true                 =>   true
*/
Expr *sqlite3ExprSimplifiedAndOr(Expr *pExpr){
  assert( pExpr!=0 );
  if( pExpr->op==TK_AND || pExpr->op==TK_OR ){
    Expr *pRight = sqlite3ExprSimplifiedAndOr(pExpr->pRight);
    Expr *pLeft = sqlite3ExprSimplifiedAndOr(pExpr->pLeft);
    if( ExprAlwaysTrue(pLeft) || ExprAlwaysFalse(pRight) ){
      pExpr = pExpr->op==TK_AND ? pRight : pLeft;
    }else if( ExprAlwaysTrue(pRight) || ExprAlwaysFalse(pLeft) ){
      pExpr = pExpr->op==TK_AND ? pLeft : pRight;
    }
  }
  return pExpr;
}


/*
** These routines are Walker callbacks used to check expressions to
** see if they are "constant" for some definition of constant.  The
** Walker.eCode value determines the type of "constant" we are looking
** for.
**
** These callback routines are used to implement the following:
**
**     sqlite3ExprIsConstant()                  pWalker->eCode==1
**     sqlite3ExprIsConstantNotJoin()           pWalker->eCode==2
**     sqlite3ExprIsTableConstant()             pWalker->eCode==3
**     sqlite3ExprIsConstantOrFunction()        pWalker->eCode==4 or 5
**
** In all cases, the callbacks set Walker.eCode=0 and abort if the expression
** is found to not be a constant.
**
** The sqlite3ExprIsConstantOrFunction() is used for evaluating expressions
** in a CREATE TABLE statement.  The Walker.eCode value is 5 when parsing
** an existing schema and 4 when processing a new statement.  A bound
** parameter raises an error for new statements, but is silently converted
** to NULL for existing schemas.  This allows sqlite_master tables that 
** The sqlite3ExprIsConstantOrFunction() is used for evaluating DEFAULT
** expressions in a CREATE TABLE statement.  The Walker.eCode value is 5
** when parsing an existing schema out of the sqlite_schema table and 4
** when processing a new CREATE TABLE statement.  A bound parameter raises
** an error for new statements, but is silently converted
** to NULL for existing schemas.  This allows sqlite_schema tables that 
** contain a bound parameter because they were generated by older versions
** of SQLite to be parsed by newer versions of SQLite without raising a
** malformed schema error.
*/
static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){

  /* If pWalker->eCode is 2 then any term of the expression that comes from
  ** the ON or USING clauses of a left join disqualifies the expression
  ** the ON or USING clauses of an outer join disqualifies the expression
  ** from being considered constant. */
  if( pWalker->eCode==2 && ExprHasProperty(pExpr, EP_FromJoin) ){
  if( pWalker->eCode==2 && ExprHasProperty(pExpr, EP_OuterON) ){
    pWalker->eCode = 0;
    return WRC_Abort;
  }

  switch( pExpr->op ){
    /* Consider functions to be constant if all their arguments are constant
    ** and either pWalker->eCode==4 or 5 or the function has the
    ** SQLITE_FUNC_CONST flag. */
    case TK_FUNCTION:
      if( pWalker->eCode>=4 || ExprHasProperty(pExpr,EP_ConstFunc) ){
      if( (pWalker->eCode>=4 || ExprHasProperty(pExpr,EP_ConstFunc))
       && !ExprHasProperty(pExpr, EP_WinFunc)
      ){
        if( pWalker->eCode==5 ) ExprSetProperty(pExpr, EP_FromDDL);
        return WRC_Continue;
      }else{
        pWalker->eCode = 0;
        return WRC_Abort;
      }
    case TK_ID:
      /* Convert "true" or "false" in a DEFAULT clause into the
      ** appropriate TK_TRUEFALSE operator */
      if( sqlite3ExprIdToTrueFalse(pExpr) ){
        return WRC_Prune;
      }
      /* Fall thru */
      /* no break */ deliberate_fall_through
    case TK_COLUMN:
    case TK_AGG_FUNCTION:
    case TK_AGG_COLUMN:
      testcase( pExpr->op==TK_ID );
      testcase( pExpr->op==TK_COLUMN );
      testcase( pExpr->op==TK_AGG_FUNCTION );
      testcase( pExpr->op==TK_AGG_COLUMN );
      if( ExprHasProperty(pExpr, EP_FixedCol) && pWalker->eCode!=2 ){
        return WRC_Continue;
      }
      if( pWalker->eCode==3 && pExpr->iTable==pWalker->u.iCur ){
        return WRC_Continue;
      }
      /* Fall through */
      /* no break */ deliberate_fall_through
    case TK_IF_NULL_ROW:
    case TK_REGISTER:
    case TK_DOT:
      testcase( pExpr->op==TK_REGISTER );
      testcase( pExpr->op==TK_IF_NULL_ROW );
      testcase( pExpr->op==TK_DOT );
      pWalker->eCode = 0;
      return WRC_Abort;
    case TK_VARIABLE:
      if( pWalker->eCode==5 ){
        /* Silently convert bound parameters that appear inside of CREATE
        ** statements into a NULL when parsing the CREATE statement text out
        ** of the sqlite_master table */
        ** of the sqlite_schema table */
        pExpr->op = TK_NULL;
      }else if( pWalker->eCode==4 ){
        /* A bound parameter in a CREATE statement that originates from
        ** sqlite3_prepare() causes an error */
        pWalker->eCode = 0;
        return WRC_Abort;
      }
      /* Fall through */
      /* no break */ deliberate_fall_through
    default:
      testcase( pExpr->op==TK_SELECT ); /* sqlite3SelectWalkFail() disallows */
      testcase( pExpr->op==TK_EXISTS ); /* sqlite3SelectWalkFail() disallows */
      return WRC_Continue;
  }
}
static int exprIsConst(Expr *p, int initFlag, int iCur){
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
2355
2356
2357
2358
2359
2360
2361

2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419







-
+














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







**   (2) the expression does originate in the ON or USING clause
**       of a LEFT JOIN, and
**   (3) the expression does not contain any EP_FixedCol TK_COLUMN
**       operands created by the constant propagation optimization.
**
** When this routine returns true, it indicates that the expression
** can be added to the pParse->pConstExpr list and evaluated once when
** the prepared statement starts up.  See sqlite3ExprCodeAtInit().
** the prepared statement starts up.  See sqlite3ExprCodeRunJustOnce().
*/
int sqlite3ExprIsConstantNotJoin(Expr *p){
  return exprIsConst(p, 2, 0);
}

/*
** Walk an expression tree.  Return non-zero if the expression is constant
** for any single row of the table with cursor iCur.  In other words, the
** expression must not refer to any non-deterministic function nor any
** table other than iCur.
*/
int sqlite3ExprIsTableConstant(Expr *p, int iCur){
  return exprIsConst(p, 3, iCur);
}

/*
** Check pExpr to see if it is an invariant constraint on data source pSrc.
** This is an optimization.  False negatives will perhaps cause slower
** queries, but false positives will yield incorrect answers.  So when in
** doubt, return 0.
**
** To be an invariant constraint, the following must be true:
**
**   (1)  pExpr cannot refer to any table other than pSrc->iCursor.
**
**   (2)  pExpr cannot use subqueries or non-deterministic functions.
**
**   (3)  pSrc cannot be part of the left operand for a RIGHT JOIN.
**        (Is there some way to relax this constraint?)
**
**   (4)  If pSrc is the right operand of a LEFT JOIN, then...
**         (4a)  pExpr must come from an ON clause..
           (4b)  and specifically the ON clause associated with the LEFT JOIN.
**
**   (5)  If pSrc is not the right operand of a LEFT JOIN or the left
**        operand of a RIGHT JOIN, then pExpr must be from the WHERE
**        clause, not an ON clause.
*/
int sqlite3ExprIsTableConstraint(Expr *pExpr, const SrcItem *pSrc){
  if( pSrc->fg.jointype & JT_LTORJ ){
    return 0;  /* rule (3) */
  }
  if( pSrc->fg.jointype & JT_LEFT ){
    if( !ExprHasProperty(pExpr, EP_OuterON) ) return 0;   /* rule (4a) */
    if( pExpr->w.iJoin!=pSrc->iCursor ) return 0;         /* rule (4b) */
  }else{
    if( ExprHasProperty(pExpr, EP_OuterON) ) return 0;    /* rule (5) */
  }
  return sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor); /* rules (1), (2) */
}


/*
** sqlite3WalkExpr() callback used by sqlite3ExprIsConstantOrGroupBy().
*/
static int exprNodeIsConstantOrGroupBy(Walker *pWalker, Expr *pExpr){
  ExprList *pGroupBy = pWalker->u.pGroupBy;
1984
1985
1986
1987
1988
1989
1990
1991

1992
1993
1994
1995
1996
1997
1998
2428
2429
2430
2431
2432
2433
2434

2435
2436
2437
2438
2439
2440
2441
2442







-
+







      if( sqlite3IsBinary(pColl) ){
        return WRC_Prune;
      }
    }
  }

  /* Check if pExpr is a sub-select. If so, consider it variable. */
  if( ExprHasProperty(pExpr, EP_xIsSelect) ){
  if( ExprUseXSelect(pExpr) ){
    pWalker->eCode = 0;
    return WRC_Abort;
  }

  return exprNodeIsConstant(pWalker, pExpr);
}

2023
2024
2025
2026
2027
2028
2029

2030
2031
2032














2033
2034
2035
2036
2037
2038
2039
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
2493
2494
2495







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







  w.u.pGroupBy = pGroupBy;
  w.pParse = pParse;
  sqlite3WalkExpr(&w, p);
  return w.eCode;
}

/*
** Walk an expression tree for the DEFAULT field of a column definition
** Walk an expression tree.  Return non-zero if the expression is constant
** or a function call with constant arguments.  Return and 0 if there
** are any variables.
** in a CREATE TABLE statement.  Return non-zero if the expression is 
** acceptable for use as a DEFAULT.  That is to say, return non-zero if
** the expression is constant or a function call with constant arguments.
** Return and 0 if there are any variables.
**
** isInit is true when parsing from sqlite_schema.  isInit is false when
** processing a new CREATE TABLE statement.  When isInit is true, parameters
** (such as ? or $abc) in the expression are converted into NULL.  When
** isInit is false, parameters raise an error.  Parameters should not be
** allowed in a CREATE TABLE statement, but some legacy versions of SQLite
** allowed it, so we need to support it when reading sqlite_schema for
** backwards compatibility.
**
** If isInit is true, set EP_FromDDL on every TK_FUNCTION node.
**
** For the purposes of this function, a double-quoted string (ex: "abc")
** is considered a variable but a single-quoted string (ex: 'abc') is
** a constant.
*/
int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){
  assert( isInit==0 || isInit==1 );
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
2516
2517
2518
2519
2520
2521
2522

2523
2524

2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541

2542
2543

2544
2545
2546
2547
2548
2549
2550
2551







-
+

-
+
















-
+

-
+








/*
** If the expression p codes a constant integer that is small enough
** to fit in a 32-bit integer, return 1 and put the value of the integer
** in *pValue.  If the expression is not an integer or if it is too big
** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged.
*/
int sqlite3ExprIsInteger(Expr *p, int *pValue){
int sqlite3ExprIsInteger(const Expr *p, int *pValue){
  int rc = 0;
  if( p==0 ) return 0;  /* Can only happen following on OOM */
  if( NEVER(p==0) ) return 0;  /* Used to only happen following on OOM */

  /* If an expression is an integer literal that fits in a signed 32-bit
  ** integer, then the EP_IntValue flag will have already been set */
  assert( p->op!=TK_INTEGER || (p->flags & EP_IntValue)!=0
           || sqlite3GetInt32(p->u.zToken, &rc)==0 );

  if( p->flags & EP_IntValue ){
    *pValue = p->u.iValue;
    return 1;
  }
  switch( p->op ){
    case TK_UPLUS: {
      rc = sqlite3ExprIsInteger(p->pLeft, pValue);
      break;
    }
    case TK_UMINUS: {
      int v;
      int v = 0;
      if( sqlite3ExprIsInteger(p->pLeft, &v) ){
        assert( v!=(-2147483647-1) );
        assert( ((unsigned int)v)!=0x80000000 );
        *pValue = -v;
        rc = 1;
      }
      break;
    }
    default: break;
  }
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
2564
2565
2566
2567
2568
2569
2570
2571

2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589

2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609

2610
2611
2612
2613
2614
2615
2616
2617

2618
2619
2620

2621
2622
2623

2624
2625
2626

2627
2628
2629
2630


2631
2632
2633
2634
2635
2636
2637
2638







+
-
+
+
+
+









+


+
+
-
+

















+

-
+
+
+
+




-
+


-
+


-
+


-
+



-
-
+







** 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; }
  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:
    case TK_BLOB:
      return 0;
    case TK_COLUMN:
      assert( ExprUseYTab(p) );
      return ExprHasProperty(p, EP_CanBeNull) ||
             p->y.pTab==0 ||  /* Reference to column of index on expression */
             (p->iColumn>=0
              && p->y.pTab->aCol!=0 /* Possible due to prior error */
             (p->iColumn>=0 && p->y.pTab->aCol[p->iColumn].notNull==0);
              && p->y.pTab->aCol[p->iColumn].notNull==0);
    default:
      return 1;
  }
}

/*
** Return TRUE if the given expression is a constant which would be
** unchanged by OP_Affinity with the affinity given in the second
** argument.
**
** This routine is used to determine if the OP_Affinity operation
** can be omitted.  When in doubt return FALSE.  A false negative
** is harmless.  A false positive, however, can result in the wrong
** answer.
*/
int sqlite3ExprNeedsNoAffinityChange(const Expr *p, char aff){
  u8 op;
  int unaryMinus = 0;
  if( aff==SQLITE_AFF_BLOB ) return 1;
  while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ p = p->pLeft; }
  while( p->op==TK_UPLUS || p->op==TK_UMINUS ){
    if( p->op==TK_UMINUS ) unaryMinus = 1;
    p = p->pLeft;
  }
  op = p->op;
  if( op==TK_REGISTER ) op = p->op2;
  switch( op ){
    case TK_INTEGER: {
      return aff==SQLITE_AFF_INTEGER || aff==SQLITE_AFF_NUMERIC;
      return aff>=SQLITE_AFF_NUMERIC;
    }
    case TK_FLOAT: {
      return aff==SQLITE_AFF_REAL || aff==SQLITE_AFF_NUMERIC;
      return aff>=SQLITE_AFF_NUMERIC;
    }
    case TK_STRING: {
      return aff==SQLITE_AFF_TEXT;
      return !unaryMinus && aff==SQLITE_AFF_TEXT;
    }
    case TK_BLOB: {
      return 1;
      return !unaryMinus;
    }
    case TK_COLUMN: {
      assert( p->iTable>=0 );  /* p cannot be part of a CHECK constraint */
      return p->iColumn<0
          && (aff==SQLITE_AFF_INTEGER || aff==SQLITE_AFF_NUMERIC);
      return aff>=SQLITE_AFF_NUMERIC && p->iColumn<0;
    }
    default: {
      return 0;
    }
  }
}

2184
2185
2186
2187
2188
2189
2190
2191

2192
2193
2194
2195
2196
2197

2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215

2216
2217
2218
2219
2220
2221
2222
2650
2651
2652
2653
2654
2655
2656

2657
2658
2659
2660
2661
2662

2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680

2681
2682
2683
2684
2685
2686
2687
2688







-
+





-
+

















-
+







** pX is the RHS of an IN operator.  If pX is a SELECT statement 
** that can be simplified to a direct table access, then return
** a pointer to the SELECT statement.  If pX is not a SELECT statement,
** or if the SELECT statement needs to be manifested into a transient
** table, then return NULL.
*/
#ifndef SQLITE_OMIT_SUBQUERY
static Select *isCandidateForInOpt(Expr *pX){
static Select *isCandidateForInOpt(const Expr *pX){
  Select *p;
  SrcList *pSrc;
  ExprList *pEList;
  Table *pTab;
  int i;
  if( !ExprHasProperty(pX, EP_xIsSelect) ) return 0;  /* Not a subquery */
  if( !ExprUseXSelect(pX) ) return 0;                 /* Not a subquery */
  if( ExprHasProperty(pX, EP_VarSelect)  ) return 0;  /* Correlated subq */
  p = pX->x.pSelect;
  if( p->pPrior ) return 0;              /* Not a compound SELECT */
  if( p->selFlags & (SF_Distinct|SF_Aggregate) ){
    testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct );
    testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate );
    return 0; /* No DISTINCT keyword and no aggregate functions */
  }
  assert( p->pGroupBy==0 );              /* Has no GROUP BY clause */
  if( p->pLimit ) return 0;              /* Has no LIMIT clause */
  if( p->pWhere ) return 0;              /* Has no WHERE clause */
  pSrc = p->pSrc;
  assert( pSrc!=0 );
  if( pSrc->nSrc!=1 ) return 0;          /* Single term in FROM clause */
  if( pSrc->a[0].pSelect ) return 0;     /* FROM is not a subquery or view */
  pTab = pSrc->a[0].pTab;
  assert( pTab!=0 );
  assert( pTab->pSelect==0 );            /* FROM clause is not a view */
  assert( !IsView(pTab)  );              /* FROM clause is not a view */
  if( IsVirtual(pTab) ) return 0;        /* FROM clause not a virtual table */
  pEList = p->pEList;
  assert( pEList!=0 );
  /* All SELECT results must be columns. */
  for(i=0; i<pEList->nExpr; i++){
    Expr *pRes = pEList->a[i].pExpr;
    if( pRes->op!=TK_COLUMN ) return 0;
2268
2269
2270
2271
2272
2273
2274
2275

2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295




2296
2297
2298
2299
2300
2301
2302
2734
2735
2736
2737
2738
2739
2740

2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760

2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771







-
+



















-
+
+
+
+







** might be either a list of expressions or a subquery.
**
** The job of this routine is to find or create a b-tree object that can
** be used either to test for membership in the RHS set or to iterate through
** all members of the RHS set, skipping duplicates.
**
** A cursor is opened on the b-tree object that is the RHS of the IN operator
** and pX->iTable is set to the index of that cursor.
** and the *piTab parameter is set to the index of that cursor.
**
** The returned value of this function indicates the b-tree type, as follows:
**
**   IN_INDEX_ROWID      - The cursor was opened on a database table.
**   IN_INDEX_INDEX_ASC  - The cursor was opened on an ascending index.
**   IN_INDEX_INDEX_DESC - The cursor was opened on a descending index.
**   IN_INDEX_EPH        - The cursor was opened on a specially created and
**                         populated epheremal table.
**   IN_INDEX_NOOP       - No cursor was allocated.  The IN operator must be
**                         implemented as a sequence of comparisons.
**
** An existing b-tree might be used if the RHS expression pX is a simple
** subquery such as:
**
**     SELECT <column1>, <column2>... FROM <table>
**
** If the RHS of the IN operator is a list or a more complex subquery, then
** an ephemeral table might need to be generated from the RHS and then
** pX->iTable made to point to the ephemeral table instead of an
** existing table.
** existing table.  In this case, the creation and initialization of the
** ephmeral table might be put inside of a subroutine, the EP_Subrtn flag
** will be set on pX and the pX->y.sub fields will be set to show where
** the subroutine is coded.
**
** The inFlags parameter must contain, at a minimum, one of the bits
** IN_INDEX_MEMBERSHIP or IN_INDEX_LOOP but not both.  If inFlags contains
** IN_INDEX_MEMBERSHIP, then the generated table will be used for a fast
** membership test.  When the IN_INDEX_LOOP bit is set, the IN index will
** be used to loop over all values of the RHS of the IN operator.
**
2341
2342
2343
2344
2345
2346
2347
2348

2349
2350
2351


2352
2353
2354
2355

2356
2357
2358
2359
2360

2361
2362
2363
2364
2365
2366
2367

2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384

2385
2386
2387
2388
2389
2390
2391
2392
2393
2394

2395
2396
2397
2398
2399
2400
2401
2810
2811
2812
2813
2814
2815
2816

2817
2818
2819

2820
2821
2822
2823
2824

2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837

2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854

2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873







-
+


-
+
+



-
+





+






-
+
















-
+










+







**   CREATE INDEX i1 ON t1(b, c, a);
**
** then aiMap[] is populated with {2, 0, 1}.
*/
#ifndef SQLITE_OMIT_SUBQUERY
int sqlite3FindInIndex(
  Parse *pParse,             /* Parsing context */
  Expr *pX,                  /* The right-hand side (RHS) of the IN operator */
  Expr *pX,                  /* The IN expression */
  u32 inFlags,               /* IN_INDEX_LOOP, _MEMBERSHIP, and/or _NOOP_OK */
  int *prRhsHasNull,         /* Register holding NULL status.  See notes */
  int *aiMap                 /* Mapping from Index fields to RHS fields */
  int *aiMap,                /* Mapping from Index fields to RHS fields */
  int *piTab                 /* OUT: index to use */
){
  Select *p;                            /* SELECT to the right of IN operator */
  int eType = 0;                        /* Type of RHS table. IN_INDEX_* */
  int iTab = pParse->nTab++;            /* Cursor of the RHS table */
  int iTab;                             /* Cursor of the RHS table */
  int mustBeUnique;                     /* True if RHS must be unique */
  Vdbe *v = sqlite3GetVdbe(pParse);     /* Virtual machine being coded */

  assert( pX->op==TK_IN );
  mustBeUnique = (inFlags & IN_INDEX_LOOP)!=0;
  iTab = pParse->nTab++;

  /* If the RHS of this IN(...) operator is a SELECT, and if it matters 
  ** whether or not the SELECT result contains NULL values, check whether
  ** or not NULL is actually possible (it may not be, for example, due 
  ** to NOT NULL constraints in the schema). If no NULL values are possible,
  ** set prRhsHasNull to 0 before continuing.  */
  if( prRhsHasNull && (pX->flags & EP_xIsSelect) ){
  if( prRhsHasNull && ExprUseXSelect(pX) ){
    int i;
    ExprList *pEList = pX->x.pSelect->pEList;
    for(i=0; i<pEList->nExpr; i++){
      if( sqlite3ExprCanBeNull(pEList->a[i].pExpr) ) break;
    }
    if( i==pEList->nExpr ){
      prRhsHasNull = 0;
    }
  }

  /* Check to see if an existing table or index can be used to
  ** satisfy the query.  This is preferable to generating a new 
  ** ephemeral table.  */
  if( pParse->nErr==0 && (p = isCandidateForInOpt(pX))!=0 ){
    sqlite3 *db = pParse->db;              /* Database connection */
    Table *pTab;                           /* Table <table>. */
    i16 iDb;                               /* Database idx for pTab */
    int iDb;                               /* Database idx for pTab */
    ExprList *pEList = p->pEList;
    int nExpr = pEList->nExpr;

    assert( p->pEList!=0 );             /* Because of isCandidateForInOpt(p) */
    assert( p->pEList->a[0].pExpr!=0 ); /* Because of isCandidateForInOpt(p) */
    assert( p->pSrc!=0 );               /* Because of isCandidateForInOpt(p) */
    pTab = p->pSrc->a[0].pTab;

    /* Code an OP_Transaction and OP_TableLock for <table>. */
    iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
    assert( iDb>=0 && iDb<SQLITE_MAX_DB );
    sqlite3CodeVerifySchema(pParse, iDb);
    sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);

    assert(v);  /* sqlite3GetVdbe() has always been previously called */
    if( nExpr==1 && pEList->a[0].pExpr->iColumn<0 ){
      /* The "x IN (SELECT rowid FROM table)" case */
      int iAddr = sqlite3VdbeAddOp0(v, OP_Once);
2515
2516
2517
2518
2519
2520
2521
2522

2523
2524


2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542


2543



2544
2545
2546
2547
2548
2549
2550
2551
2552
2553

2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567

2568
2569
2570

2571
2572
2573
2574
2575
2576
2577
2987
2988
2989
2990
2991
2992
2993

2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010



3011
3012
3013
3014
3015

3016
3017
3018
3019


3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040

3041
3042
3043

3044
3045
3046
3047
3048
3049
3050
3051







-
+


+
+












-
-
-



+
+
-
+
+
+

-
-







+













-
+


-
+







  ** and the RHS of the IN operator is a list, not a subquery
  ** and the RHS is not constant or has two or fewer terms,
  ** then it is not worth creating an ephemeral table to evaluate
  ** the IN operator so return IN_INDEX_NOOP.
  */
  if( eType==0
   && (inFlags & IN_INDEX_NOOP_OK)
   && !ExprHasProperty(pX, EP_xIsSelect)
   && ExprUseXList(pX)
   && (!sqlite3InRhsIsConstant(pX) || pX->x.pList->nExpr<=2)
  ){
    pParse->nTab--;  /* Back out the allocation of the unused cursor */
    iTab = -1;       /* Cursor is not allocated */
    eType = IN_INDEX_NOOP;
  }

  if( eType==0 ){
    /* Could not find an existing table or index to use as the RHS b-tree.
    ** We will have to generate an ephemeral table to do the job.
    */
    u32 savedNQueryLoop = pParse->nQueryLoop;
    int rMayHaveNull = 0;
    eType = IN_INDEX_EPH;
    if( inFlags & IN_INDEX_LOOP ){
      pParse->nQueryLoop = 0;
      if( pX->pLeft->iColumn<0 && !ExprHasProperty(pX, EP_xIsSelect) ){
        eType = IN_INDEX_ROWID;
      }
    }else if( prRhsHasNull ){
      *prRhsHasNull = rMayHaveNull = ++pParse->nMem;
    }
    assert( pX->op==TK_IN );
    sqlite3CodeRhsOfIN(pParse, pX, iTab);
    sqlite3CodeSubselect(pParse, pX, rMayHaveNull, eType==IN_INDEX_ROWID);
    if( rMayHaveNull ){
      sqlite3SetHasNullFlag(v, iTab, rMayHaveNull);
    }
    pParse->nQueryLoop = savedNQueryLoop;
  }else{
    pX->iTable = iTab;
  }

  if( aiMap && eType!=IN_INDEX_INDEX_ASC && eType!=IN_INDEX_INDEX_DESC ){
    int i, n;
    n = sqlite3ExprVectorSize(pX->pLeft);
    for(i=0; i<n; i++) aiMap[i] = i;
  }
  *piTab = iTab;
  return eType;
}
#endif

#ifndef SQLITE_OMIT_SUBQUERY
/*
** Argument pExpr is an (?, ?...) IN(...) expression. This 
** function allocates and returns a nul-terminated string containing 
** the affinities to be used for each column of the comparison.
**
** It is the responsibility of the caller to ensure that the returned
** string is eventually freed using sqlite3DbFree().
*/
static char *exprINAffinity(Parse *pParse, Expr *pExpr){
static char *exprINAffinity(Parse *pParse, const Expr *pExpr){
  Expr *pLeft = pExpr->pLeft;
  int nVal = sqlite3ExprVectorSize(pLeft);
  Select *pSelect = (pExpr->flags & EP_xIsSelect) ? pExpr->x.pSelect : 0;
  Select *pSelect = ExprUseXSelect(pExpr) ? pExpr->x.pSelect : 0;
  char *zRet;

  assert( pExpr->op==TK_IN );
  zRet = sqlite3DbMallocRaw(pParse->db, nVal+1);
  if( zRet ){
    int i;
    for(i=0; i<nVal; i++){
2593
2594
2595
2596
2597
2598
2599

2600
2601



2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618

2619
2620
2621
2622
2623
2624
2625
2626

2627
2628
2629



2630
2631
2632
2633
2634
2635
2636
2637





2638
2639

2640
2641

2642
2643
2644
2645
2646
2647




2648
2649
2650

2651
2652
2653
2654
2655
2656
2657

2658
2659

2660
2661

2662

2663
2664
2665





2666
2667


































































































































































































































2668

2669
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
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
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
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830










2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857

















2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874































2875
2876

2877
2878
2879
2880



2881
2882



2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896

2897
2898
2899
2900
2901
2902
2903
3067
3068
3069
3070
3071
3072
3073
3074


3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093

3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104


3105
3106
3107
3108


3109
3110
3111


3112
3113
3114
3115
3116
3117

3118


3119






3120
3121
3122
3123



3124




3125


3126
3127

3128


3129
3130
3131



3132
3133
3134
3135
3136

3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363

3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374

3375
3376

3377





















































































































































3378
3379
3380
3381
3382
3383
3384
3385
3386
3387



























3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404

















3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435


3436




3437
3438
3439


3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455

3456
3457
3458
3459
3460
3461
3462
3463







+
-
-
+
+
+
















-
+








+

-
-
+
+
+

-
-



-
-
+
+
+
+
+

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

-
-
+

-
+
-
-
+

+
-
-
-
+
+
+
+
+
-

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










-
+

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













-
+







/*
** Load the Parse object passed as the first argument with an error 
** message of the form:
**
**   "sub-select returns N columns - expected M"
*/   
void sqlite3SubselectError(Parse *pParse, int nActual, int nExpect){
  if( pParse->nErr==0 ){
  const char *zFmt = "sub-select returns %d columns - expected %d";
  sqlite3ErrorMsg(pParse, zFmt, nActual, nExpect);
    const char *zFmt = "sub-select returns %d columns - expected %d";
    sqlite3ErrorMsg(pParse, zFmt, nActual, nExpect);
  }
}
#endif

/*
** Expression pExpr is a vector that has been used in a context where
** it is not permitted. If pExpr is a sub-select vector, this routine 
** loads the Parse object with a message of the form:
**
**   "sub-select returns N columns - expected 1"
**
** Or, if it is a regular scalar vector:
**
**   "row value misused"
*/   
void sqlite3VectorErrorMsg(Parse *pParse, Expr *pExpr){
#ifndef SQLITE_OMIT_SUBQUERY
  if( pExpr->flags & EP_xIsSelect ){
  if( ExprUseXSelect(pExpr) ){
    sqlite3SubselectError(pParse, pExpr->x.pSelect->pEList->nExpr, 1);
  }else
#endif
  {
    sqlite3ErrorMsg(pParse, "row value misused");
  }
}

#ifndef SQLITE_OMIT_SUBQUERY
/*
** Generate code for scalar subqueries used as a subquery expression, EXISTS,
** or IN operators.  Examples:
** Generate code that will construct an ephemeral table containing all terms
** in the RHS of an IN operator.  The IN operator can be in either of two
** forms:
**
**     (SELECT a FROM b)          -- subquery
**     EXISTS (SELECT a FROM b)   -- EXISTS subquery
**     x IN (4,5,11)              -- IN operator with list on right-hand side
**     x IN (SELECT a FROM b)     -- IN operator with subquery on the right
**
** The pExpr parameter describes the expression that contains the IN
** operator or subquery.
** The pExpr parameter is the IN operator.  The cursor number for the
** constructed ephermeral table is returned.  The first time the ephemeral
** table is computed, the cursor number is also stored in pExpr->iTable,
** however the cursor number returned might not be the same, as it might
** have been duplicated using OP_OpenDup.
**
** If parameter isRowid is non-zero, then expression pExpr is guaranteed
** If the LHS expression ("x" in the examples) is a column value, or
** to be of the form "<rowid> IN (?, ?, ?)", where <rowid> is a reference
** to some integer key column of a table B-Tree. In this case, use an
** the SELECT statement returns a column value, then the affinity of that
** intkey B-Tree to store the set of IN(...) values instead of the usual
** (slower) variable length keys B-Tree.
**
** If rMayHaveNull is non-zero, that means that the operation is an IN
** (not a SELECT or EXISTS) and that the RHS might contains NULLs.
** All this routine does is initialize the register given by rMayHaveNull
** column is used to build the index keys. If both 'x' and the
** SELECT... statement are columns, then numeric affinity is used
** if either column has NUMERIC or INTEGER affinity. If neither
** 'x' nor the SELECT... statement are columns, then numeric affinity
** to NULL.  Calling routines will take care of changing this register
** value to non-NULL if the RHS is NULL-free.
**
** is used.
** For a SELECT or EXISTS operator, return the register that holds the
** result.  For a multi-column SELECT, the result is stored in a contiguous
** array of registers and the return value is the register of the left-most
** result column.  Return 0 for IN operators or if an error occurs.
*/
#ifndef SQLITE_OMIT_SUBQUERY
int sqlite3CodeSubselect(
void sqlite3CodeRhsOfIN(
  Parse *pParse,          /* Parsing context */
  Expr *pExpr,            /* The IN, SELECT, or EXISTS operator */
  Expr *pExpr,            /* The IN operator */
  int rHasNullFlag,       /* Register that records whether NULLs exist in RHS */
  int isRowid             /* If true, LHS of IN operator is a rowid */
  int iTab                /* Use this cursor number */
){
  int addrOnce = 0;           /* Address of the OP_Once instruction at top */
  int jmpIfDynamic = -1;                      /* One-time test address */
  int rReg = 0;                           /* Register storing resulting */
  Vdbe *v = sqlite3GetVdbe(pParse);
  int addr;                   /* Address of OP_OpenEphemeral instruction */
  Expr *pLeft;                /* the LHS of the IN operator */
  KeyInfo *pKeyInfo = 0;      /* Key information */
  int nVal;                   /* Size of vector pLeft */
  Vdbe *v;                    /* The prepared statement under construction */
  if( NEVER(v==0) ) return 0;

  v = pParse->pVdbe;
  assert( v!=0 );

  /* The evaluation of the IN must be repeated every time it
  ** is encountered if any of the following is true:
  **
  **    *  The right-hand side is a correlated subquery
  **    *  The right-hand side is an expression list containing variables
  **    *  We are inside a trigger
  **
  ** If all of the above are false, then we can compute the RHS just once
  ** and reuse it many names.
  */
  if( !ExprHasProperty(pExpr, EP_VarSelect) && pParse->iSelfTab==0 ){
    /* Reuse of the RHS is allowed */
    /* If this routine has already been coded, but the previous code
    ** might not have been invoked yet, so invoke it now as a subroutine. 
    */
    if( ExprHasProperty(pExpr, EP_Subrtn) ){
      addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
      if( ExprUseXSelect(pExpr) ){
        ExplainQueryPlan((pParse, 0, "REUSE LIST SUBQUERY %d",
              pExpr->x.pSelect->selId));
      }
      assert( ExprUseYSub(pExpr) );
      sqlite3VdbeAddOp2(v, OP_Gosub, pExpr->y.sub.regReturn,
                        pExpr->y.sub.iAddr);
      assert( iTab!=pExpr->iTable );
      sqlite3VdbeAddOp2(v, OP_OpenDup, iTab, pExpr->iTable);
      sqlite3VdbeJumpHere(v, addrOnce);
      return;
    }

    /* Begin coding the subroutine */
    assert( !ExprUseYWin(pExpr) );
    ExprSetProperty(pExpr, EP_Subrtn);
    assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
    pExpr->y.sub.regReturn = ++pParse->nMem;
    pExpr->y.sub.iAddr =
      sqlite3VdbeAddOp2(v, OP_BeginSubrtn, 0, pExpr->y.sub.regReturn) + 1;

    addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
  }

  /* Check to see if this is a vector IN operator */
  pLeft = pExpr->pLeft;
  nVal = sqlite3ExprVectorSize(pLeft);

  /* Construct the ephemeral table that will contain the content of
  ** RHS of the IN operator.
  */
  pExpr->iTable = iTab;
  addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, nVal);
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
  if( ExprUseXSelect(pExpr) ){
    VdbeComment((v, "Result of SELECT %u", pExpr->x.pSelect->selId));
  }else{
    VdbeComment((v, "RHS of IN operator"));
  }
#endif
  pKeyInfo = sqlite3KeyInfoAlloc(pParse->db, nVal, 1);

  if( ExprUseXSelect(pExpr) ){
    /* Case 1:     expr IN (SELECT ...)
    **
    ** Generate code to write the results of the select into the temporary
    ** table allocated and opened above.
    */
    Select *pSelect = pExpr->x.pSelect;
    ExprList *pEList = pSelect->pEList;

    ExplainQueryPlan((pParse, 1, "%sLIST SUBQUERY %d",
        addrOnce?"":"CORRELATED ", pSelect->selId
    ));
    /* If the LHS and RHS of the IN operator do not match, that
    ** error will have been caught long before we reach this point. */
    if( ALWAYS(pEList->nExpr==nVal) ){
      Select *pCopy;
      SelectDest dest;
      int i;
      int rc;
      sqlite3SelectDestInit(&dest, SRT_Set, iTab);
      dest.zAffSdst = exprINAffinity(pParse, pExpr);
      pSelect->iLimit = 0;
      testcase( pSelect->selFlags & SF_Distinct );
      testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
      pCopy = sqlite3SelectDup(pParse->db, pSelect, 0);
      rc = pParse->db->mallocFailed ? 1 :sqlite3Select(pParse, pCopy, &dest);
      sqlite3SelectDelete(pParse->db, pCopy);
      sqlite3DbFree(pParse->db, dest.zAffSdst);
      if( rc ){
        sqlite3KeyInfoUnref(pKeyInfo);
        return;
      }      
      assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */
      assert( pEList!=0 );
      assert( pEList->nExpr>0 );
      assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
      for(i=0; i<nVal; i++){
        Expr *p = sqlite3VectorFieldSubexpr(pLeft, i);
        pKeyInfo->aColl[i] = sqlite3BinaryCompareCollSeq(
            pParse, p, pEList->a[i].pExpr
        );
      }
    }
  }else if( ALWAYS(pExpr->x.pList!=0) ){
    /* Case 2:     expr IN (exprlist)
    **
    ** For each expression, build an index key from the evaluation and
    ** store it in the temporary table. If <expr> is a column, then use
    ** that columns affinity when building index keys. If <expr> is not
    ** a column, use numeric affinity.
    */
    char affinity;            /* Affinity of the LHS of the IN */
    int i;
    ExprList *pList = pExpr->x.pList;
    struct ExprList_item *pItem;
    int r1, r2;
    affinity = sqlite3ExprAffinity(pLeft);
    if( affinity<=SQLITE_AFF_NONE ){
      affinity = SQLITE_AFF_BLOB;
    }else if( affinity==SQLITE_AFF_REAL ){
      affinity = SQLITE_AFF_NUMERIC;
    }
    if( pKeyInfo ){
      assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
      pKeyInfo->aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
    }

    /* Loop through each expression in <exprlist>. */
    r1 = sqlite3GetTempReg(pParse);
    r2 = sqlite3GetTempReg(pParse);
    for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){
      Expr *pE2 = pItem->pExpr;

      /* If the expression is not constant then we will need to
      ** disable the test that was generated above that makes sure
      ** this code only executes once.  Because for a non-constant
      ** expression we need to rerun this code each time.
      */
      if( addrOnce && !sqlite3ExprIsConstant(pE2) ){
        sqlite3VdbeChangeToNoop(v, addrOnce-1);
        sqlite3VdbeChangeToNoop(v, addrOnce);
        ExprClearProperty(pExpr, EP_Subrtn);
        addrOnce = 0;
      }

      /* Evaluate the expression and insert it into the temp table */
      sqlite3ExprCode(pParse, pE2, r1);
      sqlite3VdbeAddOp4(v, OP_MakeRecord, r1, 1, r2, &affinity, 1);
      sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r2, r1, 1);
    }
    sqlite3ReleaseTempReg(pParse, r1);
    sqlite3ReleaseTempReg(pParse, r2);
  }
  if( pKeyInfo ){
    sqlite3VdbeChangeP4(v, addr, (void *)pKeyInfo, P4_KEYINFO);
  }
  if( addrOnce ){
    sqlite3VdbeAddOp1(v, OP_NullRow, iTab);
    sqlite3VdbeJumpHere(v, addrOnce);
    /* Subroutine return */
    assert( ExprUseYSub(pExpr) );
    assert( sqlite3VdbeGetOp(v,pExpr->y.sub.iAddr-1)->opcode==OP_BeginSubrtn
            || pParse->nErr );
    sqlite3VdbeAddOp3(v, OP_Return, pExpr->y.sub.regReturn,
                      pExpr->y.sub.iAddr, 1);
    VdbeCoverage(v);
    sqlite3ClearTempRegCache(pParse);
  }
}
#endif /* SQLITE_OMIT_SUBQUERY */

/*
** Generate code for scalar subqueries used as a subquery expression
** or EXISTS operator:
**
**     (SELECT a FROM b)          -- subquery
**     EXISTS (SELECT a FROM b)   -- EXISTS subquery
**
** The pExpr parameter is the SELECT or EXISTS operator to be coded.
**
** Return the register that holds the result.  For a multi-column SELECT, 
** the result is stored in a contiguous array of registers and the
** return value is the register of the left-most result column.
** Return 0 if an error occurs.
*/
#ifndef SQLITE_OMIT_SUBQUERY
int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
  int addrOnce = 0;           /* Address of OP_Once at top of subroutine */
  int rReg = 0;               /* Register storing resulting */
  Select *pSel;               /* SELECT statement to encode */
  SelectDest dest;            /* How to deal with SELECT result */
  int nReg;                   /* Registers to allocate */
  Expr *pLimit;               /* New limit expression */
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
  int addrExplain;            /* Address of OP_Explain instruction */
#endif

  Vdbe *v = pParse->pVdbe;
  assert( v!=0 );
  if( pParse->nErr ) return 0;
  testcase( pExpr->op==TK_EXISTS );
  testcase( pExpr->op==TK_SELECT );
  assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT );
  assert( ExprUseXSelect(pExpr) );
  pSel = pExpr->x.pSelect;

  /* If this routine has already been coded, then invoke it as a
  ** subroutine. */
  if( ExprHasProperty(pExpr, EP_Subrtn) ){
    ExplainQueryPlan((pParse, 0, "REUSE SUBQUERY %d", pSel->selId));
    assert( ExprUseYSub(pExpr) );
    sqlite3VdbeAddOp2(v, OP_Gosub, pExpr->y.sub.regReturn,
                      pExpr->y.sub.iAddr);
    return pExpr->iTable;
  }

  /* Begin coding the subroutine */
  assert( !ExprUseYWin(pExpr) );
  assert( !ExprHasProperty(pExpr, EP_Reduced|EP_TokenOnly) );
  ExprSetProperty(pExpr, EP_Subrtn);
  pExpr->y.sub.regReturn = ++pParse->nMem;
  pExpr->y.sub.iAddr =
    sqlite3VdbeAddOp2(v, OP_BeginSubrtn, 0, pExpr->y.sub.regReturn) + 1;

  /* The evaluation of the IN/EXISTS/SELECT must be repeated every time it
  /* The evaluation of the EXISTS/SELECT must be repeated every time it
  ** is encountered if any of the following is true:
  **
  **    *  The right-hand side is a correlated subquery
  **    *  The right-hand side is an expression list containing variables
  **    *  We are inside a trigger
  **
  ** If all of the above are false, then we can run this code just once
  ** save the results, and reuse the same result on subsequent invocations.
  */
  if( !ExprHasProperty(pExpr, EP_VarSelect) ){
    jmpIfDynamic = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
    addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
  }

  
  switch( pExpr->op ){
    case TK_IN: {
      int addr;                   /* Address of OP_OpenEphemeral instruction */
      Expr *pLeft = pExpr->pLeft; /* the LHS of the IN operator */
      KeyInfo *pKeyInfo = 0;      /* Key information */
      int nVal;                   /* Size of vector pLeft */
      
      nVal = sqlite3ExprVectorSize(pLeft);
      assert( !isRowid || nVal==1 );

      /* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)'
      ** expression it is handled the same way.  An ephemeral table is 
      ** filled with index keys representing the results from the 
      ** SELECT or the <exprlist>.
      **
      ** If the 'x' expression is a column value, or the SELECT...
      ** statement returns a column value, then the affinity of that
      ** column is used to build the index keys. If both 'x' and the
      ** SELECT... statement are columns, then numeric affinity is used
      ** if either column has NUMERIC or INTEGER affinity. If neither
      ** 'x' nor the SELECT... statement are columns, then numeric affinity
      ** is used.
      */
      pExpr->iTable = pParse->nTab++;
      addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, 
          pExpr->iTable, (isRowid?0:nVal));
      pKeyInfo = isRowid ? 0 : sqlite3KeyInfoAlloc(pParse->db, nVal, 1);

      if( ExprHasProperty(pExpr, EP_xIsSelect) ){
        /* Case 1:     expr IN (SELECT ...)
        **
        ** Generate code to write the results of the select into the temporary
        ** table allocated and opened above.
        */
        Select *pSelect = pExpr->x.pSelect;
        ExprList *pEList = pSelect->pEList;

        ExplainQueryPlan((pParse, 1, "%sLIST SUBQUERY",
            jmpIfDynamic>=0?"":"CORRELATED "
        ));
        assert( !isRowid );
        /* If the LHS and RHS of the IN operator do not match, that
        ** error will have been caught long before we reach this point. */
        if( ALWAYS(pEList->nExpr==nVal) ){
          SelectDest dest;
          int i;
          sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable);
          dest.zAffSdst = exprINAffinity(pParse, pExpr);
          pSelect->iLimit = 0;
          testcase( pSelect->selFlags & SF_Distinct );
          testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
          if( sqlite3Select(pParse, pSelect, &dest) ){
            sqlite3DbFree(pParse->db, dest.zAffSdst);
            sqlite3KeyInfoUnref(pKeyInfo);
            return 0;
          }
          sqlite3DbFree(pParse->db, dest.zAffSdst);
          assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */
          assert( pEList!=0 );
          assert( pEList->nExpr>0 );
          assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
          for(i=0; i<nVal; i++){
            Expr *p = sqlite3VectorFieldSubexpr(pLeft, i);
            pKeyInfo->aColl[i] = sqlite3BinaryCompareCollSeq(
                pParse, p, pEList->a[i].pExpr
            );
          }
        }
      }else if( ALWAYS(pExpr->x.pList!=0) ){
        /* Case 2:     expr IN (exprlist)
        **
        ** For each expression, build an index key from the evaluation and
        ** store it in the temporary table. If <expr> is a column, then use
        ** that columns affinity when building index keys. If <expr> is not
        ** a column, use numeric affinity.
        */
        char affinity;            /* Affinity of the LHS of the IN */
        int i;
        ExprList *pList = pExpr->x.pList;
        struct ExprList_item *pItem;
        int r1, r2, r3;
        affinity = sqlite3ExprAffinity(pLeft);
        if( !affinity ){
          affinity = SQLITE_AFF_BLOB;
        }
        if( pKeyInfo ){
          assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
          pKeyInfo->aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
        }

        /* Loop through each expression in <exprlist>. */
        r1 = sqlite3GetTempReg(pParse);
        r2 = sqlite3GetTempReg(pParse);
        if( isRowid ) sqlite3VdbeAddOp4(v, OP_Blob, 0, r2, 0, "", P4_STATIC);
        for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){
          Expr *pE2 = pItem->pExpr;
          int iValToIns;

          /* If the expression is not constant then we will need to
          ** disable the test that was generated above that makes sure
          ** this code only executes once.  Because for a non-constant
          ** expression we need to rerun this code each time.
          */
          if( jmpIfDynamic>=0 && !sqlite3ExprIsConstant(pE2) ){
            sqlite3VdbeChangeToNoop(v, jmpIfDynamic);
            jmpIfDynamic = -1;
          }

          /* Evaluate the expression and insert it into the temp table */
          if( isRowid && sqlite3ExprIsInteger(pE2, &iValToIns) ){
            sqlite3VdbeAddOp3(v, OP_InsertInt, pExpr->iTable, r2, iValToIns);
          }else{
            r3 = sqlite3ExprCodeTarget(pParse, pE2, r1);
            if( isRowid ){
              sqlite3VdbeAddOp2(v, OP_MustBeInt, r3,
                                sqlite3VdbeCurrentAddr(v)+2);
              VdbeCoverage(v);
              sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3);
            }else{
              sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1);
              sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pExpr->iTable, r2, r3, 1);
            }
          }
        }
        sqlite3ReleaseTempReg(pParse, r1);
        sqlite3ReleaseTempReg(pParse, r2);
      }
      if( pKeyInfo ){
        sqlite3VdbeChangeP4(v, addr, (void *)pKeyInfo, P4_KEYINFO);
      }
      break;
    }

    case TK_EXISTS:
    case TK_SELECT:
    default: {
      /* Case 3:    (SELECT ... FROM ...)
      **     or:    EXISTS(SELECT ... FROM ...)
      **
      ** For a SELECT, generate code to put the values for all columns of
      ** the first row into an array of registers and return the index of
      ** the first register.
      **
      ** If this is an EXISTS, write an integer 0 (not exists) or 1 (exists)
      ** into a register and return that register number.
      **
      ** In both cases, the query is augmented with "LIMIT 1".  Any 
      ** preexisting limit is discarded in place of the new LIMIT 1.
      */
  /* For a SELECT, generate code to put the values for all columns of
  ** the first row into an array of registers and return the index of
  ** the first register.
  **
  ** If this is an EXISTS, write an integer 0 (not exists) or 1 (exists)
  ** into a register and return that register number.
  **
  ** In both cases, the query is augmented with "LIMIT 1".  Any 
  ** preexisting limit is discarded in place of the new LIMIT 1.
  */
      Select *pSel;                         /* SELECT statement to encode */
      SelectDest dest;                      /* How to deal with SELECT result */
      int nReg;                             /* Registers to allocate */
      Expr *pLimit;                         /* New limit expression */

      testcase( pExpr->op==TK_EXISTS );
      testcase( pExpr->op==TK_SELECT );
      assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT );
      assert( ExprHasProperty(pExpr, EP_xIsSelect) );

      pSel = pExpr->x.pSelect;
      ExplainQueryPlan((pParse, 1, "%sSCALAR SUBQUERY",
            jmpIfDynamic>=0?"":"CORRELATED "));
      nReg = pExpr->op==TK_SELECT ? pSel->pEList->nExpr : 1;
      sqlite3SelectDestInit(&dest, 0, pParse->nMem+1);
      pParse->nMem += nReg;
      if( pExpr->op==TK_SELECT ){
        dest.eDest = SRT_Mem;
        dest.iSdst = dest.iSDParm;
        dest.nSdst = nReg;
        sqlite3VdbeAddOp3(v, OP_Null, 0, dest.iSDParm, dest.iSDParm+nReg-1);
        VdbeComment((v, "Init subquery result"));
      }else{
        dest.eDest = SRT_Exists;
        sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iSDParm);
        VdbeComment((v, "Init EXISTS result"));
      }
  ExplainQueryPlan2(addrExplain, (pParse, 1, "%sSCALAR SUBQUERY %d",
        addrOnce?"":"CORRELATED ", pSel->selId));
  sqlite3VdbeScanStatusCounters(v, addrExplain, addrExplain, -1);
  nReg = pExpr->op==TK_SELECT ? pSel->pEList->nExpr : 1;
  sqlite3SelectDestInit(&dest, 0, pParse->nMem+1);
  pParse->nMem += nReg;
  if( pExpr->op==TK_SELECT ){
    dest.eDest = SRT_Mem;
    dest.iSdst = dest.iSDParm;
    dest.nSdst = nReg;
    sqlite3VdbeAddOp3(v, OP_Null, 0, dest.iSDParm, dest.iSDParm+nReg-1);
    VdbeComment((v, "Init subquery result"));
  }else{
    dest.eDest = SRT_Exists;
    sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iSDParm);
    VdbeComment((v, "Init EXISTS result"));
  }
      pLimit = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[1], 0);
      if( pSel->pLimit ){
        sqlite3ExprDelete(pParse->db, pSel->pLimit->pLeft);
        pSel->pLimit->pLeft = pLimit;
      }else{
        pSel->pLimit = sqlite3PExpr(pParse, TK_LIMIT, pLimit, 0);
      }
      pSel->iLimit = 0;
      if( sqlite3Select(pParse, pSel, &dest) ){
        return 0;
      }
      rReg = dest.iSDParm;
      ExprSetVVAProperty(pExpr, EP_NoReduce);
      break;
    }
  }

  if( pSel->pLimit ){
    /* The subquery already has a limit.  If the pre-existing limit is X
    ** then make the new limit X<>0 so that the new limit is either 1 or 0 */
    sqlite3 *db = pParse->db;
    pLimit = sqlite3Expr(db, TK_INTEGER, "0");
    if( pLimit ){
      pLimit->affExpr = SQLITE_AFF_NUMERIC;
      pLimit = sqlite3PExpr(pParse, TK_NE,
                            sqlite3ExprDup(db, pSel->pLimit->pLeft, 0), pLimit);
    }
    sqlite3ExprDeferredDelete(pParse, pSel->pLimit->pLeft);
    pSel->pLimit->pLeft = pLimit;
  }else{
    /* If there is no pre-existing limit add a limit of 1 */
    pLimit = sqlite3Expr(pParse->db, TK_INTEGER, "1");
    pSel->pLimit = sqlite3PExpr(pParse, TK_LIMIT, pLimit, 0);
  }
  pSel->iLimit = 0;
  if( sqlite3Select(pParse, pSel, &dest) ){
    pExpr->op2 = pExpr->op;
    pExpr->op = TK_ERROR;
    return 0;
  }
  pExpr->iTable = rReg = dest.iSDParm;
  ExprSetVVAProperty(pExpr, EP_NoReduce);
  if( addrOnce ){
    sqlite3VdbeJumpHere(v, addrOnce);
  }
  sqlite3VdbeScanStatusRange(v, addrExplain, addrExplain, -1);

  /* Subroutine return */
  if( rHasNullFlag ){
    sqlite3SetHasNullFlag(v, pExpr->iTable, rHasNullFlag);
  assert( ExprUseYSub(pExpr) );
  }

  if( jmpIfDynamic>=0 ){
    sqlite3VdbeJumpHere(v, jmpIfDynamic);
  assert( sqlite3VdbeGetOp(v,pExpr->y.sub.iAddr-1)->opcode==OP_BeginSubrtn
          || pParse->nErr );
  sqlite3VdbeAddOp3(v, OP_Return, pExpr->y.sub.regReturn,
  }

                    pExpr->y.sub.iAddr, 1);
  VdbeCoverage(v);
  sqlite3ClearTempRegCache(pParse);
  return rReg;
}
#endif /* SQLITE_OMIT_SUBQUERY */

#ifndef SQLITE_OMIT_SUBQUERY
/*
** Expr pIn is an IN(...) expression. This function checks that the 
** sub-select on the RHS of the IN() operator has the same number of 
** columns as the vector on the LHS. Or, if the RHS of the IN() is not 
** a sub-query, that the LHS is a vector of size 1.
*/
int sqlite3ExprCheckIN(Parse *pParse, Expr *pIn){
  int nVector = sqlite3ExprVectorSize(pIn->pLeft);
  if( (pIn->flags & EP_xIsSelect) ){
  if( ExprUseXSelect(pIn) && !pParse->db->mallocFailed ){
    if( nVector!=pIn->x.pSelect->pEList->nExpr ){
      sqlite3SubselectError(pParse, pIn->x.pSelect->pEList->nExpr, nVector);
      return 1;
    }
  }else if( nVector!=1 ){
    sqlite3VectorErrorMsg(pParse, pIn->pLeft);
    return 1;
2950
2951
2952
2953
2954
2955
2956


2957

2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968

2969
2970
2971
2972
2973
2974
2975
2976


2977
2978
2979
2980
2981
2982
2983
3510
3511
3512
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







+
+

+










-
+







-
+
+







  Expr *pLeft;          /* The LHS of the IN operator */
  int i;                /* loop counter */
  int destStep2;        /* Where to jump when NULLs seen in step 2 */
  int destStep6 = 0;    /* Start of code for Step 6 */
  int addrTruthOp;      /* Address of opcode that determines the IN is true */
  int destNotNull;      /* Jump here if a comparison is not true in step 6 */
  int addrTop;          /* Top of the step-6 loop */ 
  int iTab = 0;         /* Index to use */
  u8 okConstFactor = pParse->okConstFactor;

  assert( !ExprHasVVAProperty(pExpr,EP_Immutable) );
  pLeft = pExpr->pLeft;
  if( sqlite3ExprCheckIN(pParse, pExpr) ) return;
  zAff = exprINAffinity(pParse, pExpr);
  nVector = sqlite3ExprVectorSize(pExpr->pLeft);
  aiMap = (int*)sqlite3DbMallocZero(
      pParse->db, nVector*(sizeof(int) + sizeof(char)) + 1
  );
  if( pParse->db->mallocFailed ) goto sqlite3ExprCodeIN_oom_error;

  /* Attempt to compute the RHS. After this step, if anything other than
  ** IN_INDEX_NOOP is returned, the table opened ith cursor pExpr->iTable 
  ** IN_INDEX_NOOP is returned, the table opened with cursor iTab
  ** contains the values that make up the RHS. If IN_INDEX_NOOP is returned,
  ** the RHS has not yet been coded.  */
  v = pParse->pVdbe;
  assert( v!=0 );       /* OOM detected prior to this routine */
  VdbeNoopComment((v, "begin IN expr"));
  eType = sqlite3FindInIndex(pParse, pExpr,
                             IN_INDEX_MEMBERSHIP | IN_INDEX_NOOP_OK,
                             destIfFalse==destIfNull ? 0 : &rRhsHasNull, aiMap);
                             destIfFalse==destIfNull ? 0 : &rRhsHasNull,
                             aiMap, &iTab);

  assert( pParse->nErr || nVector==1 || eType==IN_INDEX_EPH
       || eType==IN_INDEX_INDEX_ASC || eType==IN_INDEX_INDEX_DESC 
  );
#ifdef SQLITE_DEBUG
  /* Confirm that aiMap[] contains nVector integer values between 0 and
  ** nVector-1. */
2992
2993
2994
2995
2996
2997
2998
2999






3000

3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022



3023
3024
3025
3026



3027
3028
3029
3030
3031
3032
3033
3034
3035

3036

3037

3038
3039
3040




3041
3042

3043
3044
3045




3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066

3067
3068
3069

3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084

3085
3086
3087
3088
3089
3090
3091

3092
3093
3094
3095
3096

3097
3098
3099
3100
3101
3102
3103
3556
3557
3558
3559
3560
3561
3562

3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589



3590
3591
3592
3593
3594
3595

3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
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
3659
3660
3661
3662

3663
3664
3665
3666
3667
3668
3669

3670
3671
3672
3673
3674

3675
3676
3677
3678
3679
3680
3681
3682







-
+
+
+
+
+
+

+



















-
-
-
+
+
+



-
+
+
+









+

+
-
+

-
-
+
+
+
+


+

-
-
+
+
+
+


-

















-
+



+














-
+






-
+




-
+







  ** vector, then it is stored in an array of nVector registers starting 
  ** at r1.
  **
  ** sqlite3FindInIndex() might have reordered the fields of the LHS vector
  ** so that the fields are in the same order as an existing index.   The
  ** aiMap[] array contains a mapping from the original LHS field order to
  ** the field order that matches the RHS index.
  */
  **
  ** Avoid factoring the LHS of the IN(...) expression out of the loop,
  ** even if it is constant, as OP_Affinity may be used on the register
  ** by code generated below.  */
  assert( pParse->okConstFactor==okConstFactor );
  pParse->okConstFactor = 0;
  rLhsOrig = exprCodeVector(pParse, pLeft, &iDummy);
  pParse->okConstFactor = okConstFactor;
  for(i=0; i<nVector && aiMap[i]==i; i++){} /* Are LHS fields reordered? */
  if( i==nVector ){
    /* LHS fields are not reordered */
    rLhs = rLhsOrig;
  }else{
    /* Need to reorder the LHS fields according to aiMap */
    rLhs = sqlite3GetTempRange(pParse, nVector);
    for(i=0; i<nVector; i++){
      sqlite3VdbeAddOp3(v, OP_Copy, rLhsOrig+i, rLhs+aiMap[i], 0);
    }
  }

  /* If sqlite3FindInIndex() did not find or create an index that is
  ** suitable for evaluating the IN operator, then evaluate using a
  ** sequence of comparisons.
  **
  ** This is step (1) in the in-operator.md optimized algorithm.
  */
  if( eType==IN_INDEX_NOOP ){
    ExprList *pList = pExpr->x.pList;
    CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
    int labelOk = sqlite3VdbeMakeLabel(v);
    ExprList *pList;
    CollSeq *pColl;
    int labelOk = sqlite3VdbeMakeLabel(pParse);
    int r2, regToFree;
    int regCkNull = 0;
    int ii;
    assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
    assert( ExprUseXList(pExpr) );
    pList = pExpr->x.pList;
    pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
    if( destIfNull!=destIfFalse ){
      regCkNull = sqlite3GetTempReg(pParse);
      sqlite3VdbeAddOp3(v, OP_BitAnd, rLhs, rLhs, regCkNull);
    }
    for(ii=0; ii<pList->nExpr; ii++){
      r2 = sqlite3ExprCodeTemp(pParse, pList->a[ii].pExpr, &regToFree);
      if( regCkNull && sqlite3ExprCanBeNull(pList->a[ii].pExpr) ){
        sqlite3VdbeAddOp3(v, OP_BitAnd, regCkNull, r2, regCkNull);
      }
      sqlite3ReleaseTempReg(pParse, regToFree);
      if( ii<pList->nExpr-1 || destIfNull!=destIfFalse ){
        int op = rLhs!=r2 ? OP_Eq : OP_NotNull;
        sqlite3VdbeAddOp4(v, OP_Eq, rLhs, labelOk, r2,
        sqlite3VdbeAddOp4(v, op, rLhs, labelOk, r2,
                          (void*)pColl, P4_COLLSEQ);
        VdbeCoverageIf(v, ii<pList->nExpr-1);
        VdbeCoverageIf(v, ii==pList->nExpr-1);
        VdbeCoverageIf(v, ii<pList->nExpr-1 && op==OP_Eq);
        VdbeCoverageIf(v, ii==pList->nExpr-1 && op==OP_Eq);
        VdbeCoverageIf(v, ii<pList->nExpr-1 && op==OP_NotNull);
        VdbeCoverageIf(v, ii==pList->nExpr-1 && op==OP_NotNull);
        sqlite3VdbeChangeP5(v, zAff[0]);
      }else{
        int op = rLhs!=r2 ? OP_Ne : OP_IsNull;
        assert( destIfNull==destIfFalse );
        sqlite3VdbeAddOp4(v, OP_Ne, rLhs, destIfFalse, r2,
                          (void*)pColl, P4_COLLSEQ); VdbeCoverage(v);
        sqlite3VdbeAddOp4(v, op, rLhs, destIfFalse, r2,
                          (void*)pColl, P4_COLLSEQ);
        VdbeCoverageIf(v, op==OP_Ne);
        VdbeCoverageIf(v, op==OP_IsNull);
        sqlite3VdbeChangeP5(v, zAff[0] | SQLITE_JUMPIFNULL);
      }
      sqlite3ReleaseTempReg(pParse, regToFree);
    }
    if( regCkNull ){
      sqlite3VdbeAddOp2(v, OP_IsNull, regCkNull, destIfNull); VdbeCoverage(v);
      sqlite3VdbeGoto(v, destIfFalse);
    }
    sqlite3VdbeResolveLabel(v, labelOk);
    sqlite3ReleaseTempReg(pParse, regCkNull);
    goto sqlite3ExprCodeIN_finished;
  }

  /* Step 2: Check to see if the LHS contains any NULL columns.  If the
  ** LHS does contain NULLs then the result must be either FALSE or NULL.
  ** We will then skip the binary search of the RHS.
  */
  if( destIfNull==destIfFalse ){
    destStep2 = destIfFalse;
  }else{
    destStep2 = destStep6 = sqlite3VdbeMakeLabel(v);
    destStep2 = destStep6 = sqlite3VdbeMakeLabel(pParse);
  }
  for(i=0; i<nVector; i++){
    Expr *p = sqlite3VectorFieldSubexpr(pExpr->pLeft, i);
    if( pParse->nErr ) 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
  ** of the RHS using the LHS as a probe.  If found, the result is
  ** true.
  */
  if( eType==IN_INDEX_ROWID ){
    /* In this case, the RHS is the ROWID of table b-tree and so we also
    ** know that the RHS is non-NULL.  Hence, we combine steps 3 and 4
    ** into a single opcode. */
    sqlite3VdbeAddOp3(v, OP_SeekRowid, pExpr->iTable, destIfFalse, rLhs);
    sqlite3VdbeAddOp3(v, OP_SeekRowid, iTab, destIfFalse, rLhs);
    VdbeCoverage(v);
    addrTruthOp = sqlite3VdbeAddOp0(v, OP_Goto);  /* Return True */
  }else{
    sqlite3VdbeAddOp4(v, OP_Affinity, rLhs, nVector, 0, zAff, nVector);
    if( destIfFalse==destIfNull ){
      /* Combine Step 3 and Step 5 into a single opcode */
      sqlite3VdbeAddOp4Int(v, OP_NotFound, pExpr->iTable, destIfFalse,
      sqlite3VdbeAddOp4Int(v, OP_NotFound, iTab, destIfFalse,
                           rLhs, nVector); VdbeCoverage(v);
      goto sqlite3ExprCodeIN_finished;
    }
    /* Ordinary Step 3, for the case where FALSE and NULL are distinct */
    addrTruthOp = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0,
    addrTruthOp = sqlite3VdbeAddOp4Int(v, OP_Found, iTab, 0,
                                      rLhs, nVector); VdbeCoverage(v);
  }

  /* Step 4.  If the RHS is known to be non-NULL and we did not find
  ** an match on the search above, then the result must be FALSE.
  */
  if( rRhsHasNull && nVector==1 ){
3114
3115
3116
3117
3118
3119
3120
3121

3122
3123
3124

3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136

3137
3138
3139
3140
3141
3142
3143
3144
3145

3146
3147
3148
3149
3150
3151
3152
3693
3694
3695
3696
3697
3698
3699

3700
3701
3702

3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714

3715
3716
3717
3718
3719
3720
3721
3722
3723

3724
3725
3726
3727
3728
3729
3730
3731







-
+


-
+











-
+








-
+







  ** If any comparison is NULL, then the result is NULL.  If all
  ** comparisons are FALSE then the final result is FALSE.
  **
  ** For a scalar LHS, it is sufficient to check just the first row
  ** of the RHS.
  */
  if( destStep6 ) sqlite3VdbeResolveLabel(v, destStep6);
  addrTop = sqlite3VdbeAddOp2(v, OP_Rewind, pExpr->iTable, destIfFalse);
  addrTop = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, destIfFalse);
  VdbeCoverage(v);
  if( nVector>1 ){
    destNotNull = sqlite3VdbeMakeLabel(v);
    destNotNull = sqlite3VdbeMakeLabel(pParse);
  }else{
    /* For nVector==1, combine steps 6 and 7 by immediately returning
    ** FALSE if the first comparison is not NULL */
    destNotNull = destIfFalse;
  }
  for(i=0; i<nVector; i++){
    Expr *p;
    CollSeq *pColl;
    int r3 = sqlite3GetTempReg(pParse);
    p = sqlite3VectorFieldSubexpr(pLeft, i);
    pColl = sqlite3ExprCollSeq(pParse, p);
    sqlite3VdbeAddOp3(v, OP_Column, pExpr->iTable, i, r3);
    sqlite3VdbeAddOp3(v, OP_Column, iTab, i, r3);
    sqlite3VdbeAddOp4(v, OP_Ne, rLhs+i, destNotNull, r3,
                      (void*)pColl, P4_COLLSEQ);
    VdbeCoverage(v);
    sqlite3ReleaseTempReg(pParse, r3);
  }
  sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull);
  if( nVector>1 ){
    sqlite3VdbeResolveLabel(v, destNotNull);
    sqlite3VdbeAddOp2(v, OP_Next, pExpr->iTable, addrTop+1);
    sqlite3VdbeAddOp2(v, OP_Next, iTab, addrTop+1);
    VdbeCoverage(v);

    /* Step 7:  If we reach this point, we know that the result must
    ** be false. */
    sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse);
  }

3200
3201
3202
3203
3204
3205
3206
3207

3208
3209
3210
3211


3212
3213
3214
3215
3216
3217
3218
3779
3780
3781
3782
3783
3784
3785

3786
3787
3788
3789

3790
3791
3792
3793
3794
3795
3796
3797
3798







-
+



-
+
+







    int c;
    i64 value;
    const char *z = pExpr->u.zToken;
    assert( z!=0 );
    c = sqlite3DecOrHexToI64(z, &value);
    if( (c==3 && !negFlag) || (c==2) || (negFlag && value==SMALLEST_INT64)){
#ifdef SQLITE_OMIT_FLOATING_POINT
      sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z);
      sqlite3ErrorMsg(pParse, "oversized integer: %s%#T", negFlag?"-":"",pExpr);
#else
#ifndef SQLITE_OMIT_HEX_INTEGER
      if( sqlite3_strnicmp(z,"0x",2)==0 ){
        sqlite3ErrorMsg(pParse, "hex literal too big: %s%s", negFlag?"-":"",z);
        sqlite3ErrorMsg(pParse, "hex literal too big: %s%#T",
                        negFlag?"-":"",pExpr);
      }else
#endif
      {
        codeReal(v, z, negFlag, iMem);
      }
#endif
    }else{
3242
3243
3244
3245
3246
3247
3248




























3249
3250
3251
3252
3253

3254
3255
3256
3257
3258


3259

3260
3261
3262
3263
3264

3265


3266
3267
3268
3269



























3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295


3296
3297


3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316



3317
3318
3319
3320
3321
3322
3323
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
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
3899
3900
3901
3902
3903
3904


3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923



3924
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







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




-
+





+
+
-
+
-
-
-


+

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


-
-



















-
-
-
+
+

-
+
+









-








-
+
+
+







    pParse->iSelfTab = 0;
  }else{
    sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pIdx->pTable, iTabCur,
                                    iTabCol, regOut);
  }
}

#ifndef SQLITE_OMIT_GENERATED_COLUMNS
/*
** Generate code that will compute the value of generated column pCol
** and store the result in register regOut
*/
void sqlite3ExprCodeGeneratedColumn(
  Parse *pParse,     /* Parsing context */
  Table *pTab,       /* Table containing the generated column */
  Column *pCol,      /* The generated column */
  int regOut         /* Put the result in this register */
){
  int iAddr;
  Vdbe *v = pParse->pVdbe;
  assert( v!=0 );
  assert( pParse->iSelfTab!=0 );
  if( pParse->iSelfTab>0 ){
    iAddr = sqlite3VdbeAddOp3(v, OP_IfNullRow, pParse->iSelfTab-1, 0, regOut);
  }else{
    iAddr = 0;
  }
  sqlite3ExprCodeCopy(pParse, sqlite3ColumnExpr(pTab,pCol), regOut);
  if( pCol->affinity>=SQLITE_AFF_TEXT ){
    sqlite3VdbeAddOp4(v, OP_Affinity, regOut, 1, 0, &pCol->affinity, 1);
  }
  if( iAddr ) sqlite3VdbeJumpHere(v, iAddr);
}
#endif /* SQLITE_OMIT_GENERATED_COLUMNS */

/*
** Generate code to extract the value of the iCol-th column of a table.
*/
void sqlite3ExprCodeGetColumnOfTable(
  Vdbe *v,        /* The VDBE under construction */
  Vdbe *v,        /* Parsing context */
  Table *pTab,    /* The table containing the value */
  int iTabCur,    /* The table cursor.  Or the PK cursor for WITHOUT ROWID */
  int iCol,       /* Index of the column to extract */
  int regOut      /* Extract the value into this register */
){
  Column *pCol;
  assert( v!=0 );
  if( pTab==0 ){
  assert( pTab!=0 );
    sqlite3VdbeAddOp3(v, OP_Column, iTabCur, iCol, regOut);
    return;
  }
  if( iCol<0 || iCol==pTab->iPKey ){
    sqlite3VdbeAddOp2(v, OP_Rowid, iTabCur, regOut);
    VdbeComment((v, "%s.rowid", pTab->zName));
  }else{
    int op;
    int x;
    int op = IsVirtual(pTab) ? OP_VColumn : OP_Column;
    int x = iCol;
    if( !HasRowid(pTab) && !IsVirtual(pTab) ){
      x = sqlite3ColumnOfIndex(sqlite3PrimaryKeyIndex(pTab), iCol);
    if( IsVirtual(pTab) ){
      op = OP_VColumn;
      x = iCol;
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
    }else if( (pCol = &pTab->aCol[iCol])->colFlags & COLFLAG_VIRTUAL ){
      Parse *pParse = sqlite3VdbeParser(v);
      if( pCol->colFlags & COLFLAG_BUSY ){
        sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"",
                        pCol->zCnName);
      }else{
        int savedSelfTab = pParse->iSelfTab;
        pCol->colFlags |= COLFLAG_BUSY;
        pParse->iSelfTab = iTabCur+1;
        sqlite3ExprCodeGeneratedColumn(pParse, pTab, pCol, regOut);
        pParse->iSelfTab = savedSelfTab;
        pCol->colFlags &= ~COLFLAG_BUSY;
      }
      return;
#endif
    }else if( !HasRowid(pTab) ){
      testcase( iCol!=sqlite3TableColumnToStorage(pTab, iCol) );
      x = sqlite3TableColumnToIndex(sqlite3PrimaryKeyIndex(pTab), iCol);
      op = OP_Column;
    }else{
      x = sqlite3TableColumnToStorage(pTab,iCol);
      testcase( x!=iCol );
      op = OP_Column;
    }
    sqlite3VdbeAddOp3(v, op, iTabCur, x, regOut);
  }
  if( iCol>=0 ){
    sqlite3ColumnDefault(v, pTab, iCol, regOut);
  }
}

/*
** Generate code that will extract the iColumn-th column from
** table pTab and store the column value in register iReg. 
**
** There must be an open cursor to pTab in iTable when this routine
** is called.  If iColumn<0 then code is generated that extracts the rowid.
*/
int sqlite3ExprCodeGetColumn(
  Parse *pParse,   /* Parsing and code generating context */
  Table *pTab,     /* Description of the table we are reading from */
  int iColumn,     /* Index of the table column */
  int iTable,      /* The cursor pointing to the table */
  int iReg,        /* Store results here */
  u8 p5            /* P5 value for OP_Column + FLAGS */
){
  Vdbe *v = pParse->pVdbe;
  assert( v!=0 );
  sqlite3ExprCodeGetColumnOfTable(v, pTab, iTable, iColumn, iReg);
  assert( pParse->pVdbe!=0 );
  sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pTab, iTable, iColumn, iReg);
  if( p5 ){
    sqlite3VdbeChangeP5(v, p5);
    VdbeOp *pOp = sqlite3VdbeGetLastOp(pParse->pVdbe);
    if( pOp->opcode==OP_Column ) pOp->p5 = p5;
  }
  return iReg;
}

/*
** Generate code to move content from registers iFrom...iFrom+nReg-1
** over to iTo..iTo+nReg-1.
*/
void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){
  assert( iFrom>=iTo+nReg || iFrom+nReg<=iTo );
  sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg);
}

/*
** Convert a scalar expression node to a TK_REGISTER referencing
** register iReg.  The caller must ensure that iReg already contains
** the correct value for the expression.
*/
static void exprToRegister(Expr *p, int iReg){
static void exprToRegister(Expr *pExpr, int iReg){
  Expr *p = sqlite3ExprSkipCollateAndLikely(pExpr);
  if( NEVER(p==0) ) return;
  p->op2 = p->op;
  p->op = TK_REGISTER;
  p->iTable = iReg;
  ExprClearProperty(p, EP_Skip);
}

/*
3337
3338
3339
3340
3341
3342
3343
3344

3345
3346
3347
3348
3349

3350
3351
3352
3353
3354
3355
3356















































































































































































3357
3358
3359
3360
3361
3362
3363
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
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
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
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171







-
+





+







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







    iResult = sqlite3ExprCodeTemp(pParse, p, piFreeable);
  }else{
    *piFreeable = 0;
    if( p->op==TK_SELECT ){
#if SQLITE_OMIT_SUBQUERY
      iResult = 0;
#else
      iResult = sqlite3CodeSubselect(pParse, p, 0, 0);
      iResult = sqlite3CodeSubselect(pParse, p);
#endif
    }else{
      int i;
      iResult = pParse->nMem+1;
      pParse->nMem += nResult;
      assert( ExprUseXList(p) );
      for(i=0; i<nResult; i++){
        sqlite3ExprCodeFactorable(pParse, p->x.pList->a[i].pExpr, i+iResult);
      }
    }
  }
  return iResult;
}

/*
** If the last opcode is a OP_Copy, then set the do-not-merge flag (p5)
** so that a subsequent copy will not be merged into this one.
*/
static void setDoNotMergeFlagOnCopy(Vdbe *v){
  if( sqlite3VdbeGetLastOp(v)->opcode==OP_Copy ){
    sqlite3VdbeChangeP5(v, 1);  /* Tag trailing OP_Copy as not mergable */
  }
}

/*
** Generate code to implement special SQL functions that are implemented
** in-line rather than by using the usual callbacks.
*/
static int exprCodeInlineFunction(
  Parse *pParse,        /* Parsing context */
  ExprList *pFarg,      /* List of function arguments */
  int iFuncId,          /* Function ID.  One of the INTFUNC_... values */
  int target            /* Store function result in this register */
){
  int nFarg;
  Vdbe *v = pParse->pVdbe;
  assert( v!=0 );
  assert( pFarg!=0 );
  nFarg = pFarg->nExpr;
  assert( nFarg>0 );  /* All in-line functions have at least one argument */
  switch( iFuncId ){
    case INLINEFUNC_coalesce: {
      /* Attempt a direct implementation of the built-in COALESCE() and
      ** IFNULL() functions.  This avoids unnecessary evaluation of
      ** arguments past the first non-NULL argument.
      */
      int endCoalesce = sqlite3VdbeMakeLabel(pParse);
      int i;
      assert( nFarg>=2 );
      sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target);
      for(i=1; i<nFarg; i++){
        sqlite3VdbeAddOp2(v, OP_NotNull, target, endCoalesce);
        VdbeCoverage(v);
        sqlite3ExprCode(pParse, pFarg->a[i].pExpr, target);
      }
      setDoNotMergeFlagOnCopy(v);
      sqlite3VdbeResolveLabel(v, endCoalesce);
      break;
    }
    case INLINEFUNC_iif: {
      Expr caseExpr;
      memset(&caseExpr, 0, sizeof(caseExpr));
      caseExpr.op = TK_CASE;
      caseExpr.x.pList = pFarg;
      return sqlite3ExprCodeTarget(pParse, &caseExpr, target);
    }
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
    case INLINEFUNC_sqlite_offset: {
      Expr *pArg = pFarg->a[0].pExpr;
      if( pArg->op==TK_COLUMN && pArg->iTable>=0 ){
        sqlite3VdbeAddOp3(v, OP_Offset, pArg->iTable, pArg->iColumn, target);
      }else{
        sqlite3VdbeAddOp2(v, OP_Null, 0, target);
      }
      break;
    }
#endif
    default: {   
      /* The UNLIKELY() function is a no-op.  The result is the value
      ** of the first argument.
      */
      assert( nFarg==1 || nFarg==2 );
      target = sqlite3ExprCodeTarget(pParse, pFarg->a[0].pExpr, target);
      break;
    }

  /***********************************************************************
  ** Test-only SQL functions that are only usable if enabled
  ** via SQLITE_TESTCTRL_INTERNAL_FUNCTIONS
  */
#if !defined(SQLITE_UNTESTABLE)
    case INLINEFUNC_expr_compare: {
      /* Compare two expressions using sqlite3ExprCompare() */
      assert( nFarg==2 );
      sqlite3VdbeAddOp2(v, OP_Integer, 
         sqlite3ExprCompare(0,pFarg->a[0].pExpr, pFarg->a[1].pExpr,-1),
         target);
      break;
    }

    case INLINEFUNC_expr_implies_expr: {
      /* Compare two expressions using sqlite3ExprImpliesExpr() */
      assert( nFarg==2 );
      sqlite3VdbeAddOp2(v, OP_Integer, 
         sqlite3ExprImpliesExpr(pParse,pFarg->a[0].pExpr, pFarg->a[1].pExpr,-1),
         target);
      break;
    }

    case INLINEFUNC_implies_nonnull_row: {
      /* REsult of sqlite3ExprImpliesNonNullRow() */
      Expr *pA1;
      assert( nFarg==2 );
      pA1 = pFarg->a[1].pExpr;
      if( pA1->op==TK_COLUMN ){
        sqlite3VdbeAddOp2(v, OP_Integer, 
           sqlite3ExprImpliesNonNullRow(pFarg->a[0].pExpr,pA1->iTable),
           target);
      }else{
        sqlite3VdbeAddOp2(v, OP_Null, 0, target);
      }
      break;
    }

    case INLINEFUNC_affinity: {
      /* The AFFINITY() function evaluates to a string that describes
      ** the type affinity of the argument.  This is used for testing of
      ** the SQLite type logic.
      */
      const char *azAff[] = { "blob", "text", "numeric", "integer", "real" };
      char aff;
      assert( nFarg==1 );
      aff = sqlite3ExprAffinity(pFarg->a[0].pExpr);
      sqlite3VdbeLoadString(v, target, 
              (aff<=SQLITE_AFF_NONE) ? "none" : azAff[aff-SQLITE_AFF_BLOB]);
      break;
    }
#endif /* !defined(SQLITE_UNTESTABLE) */
  }
  return target;
}

/*
** Check to see if pExpr is one of the indexed expressions on pParse->pIdxEpr.
** If it is, then resolve the expression by reading from the index and
** return the register into which the value has been read.  If pExpr is
** not an indexed expression, then return negative.
*/
static SQLITE_NOINLINE int sqlite3IndexedExprLookup(
  Parse *pParse,   /* The parsing context */
  Expr *pExpr,     /* The expression to potentially bypass */
  int target       /* Where to store the result of the expression */
){
  IndexedExpr *p;
  Vdbe *v;
  for(p=pParse->pIdxEpr; p; p=p->pIENext){
    int iDataCur = p->iDataCur;
    if( iDataCur<0 ) continue;
    if( pParse->iSelfTab ){
      if( p->iDataCur!=pParse->iSelfTab-1 ) continue;
      iDataCur = -1;
    }
    if( sqlite3ExprCompare(0, pExpr, p->pExpr, iDataCur)!=0 ) continue;
    v = pParse->pVdbe;
    assert( v!=0 );
    if( p->bMaybeNullRow ){
      /* If the index is on a NULL row due to an outer join, then we
      ** cannot extract the value from the index.  The value must be
      ** computed using the original expression. */
      int addr = sqlite3VdbeCurrentAddr(v);
      sqlite3VdbeAddOp3(v, OP_IfNullRow, p->iIdxCur, addr+3, target);
      VdbeCoverage(v);
      sqlite3VdbeAddOp3(v, OP_Column, p->iIdxCur, p->iIdxCol, target);
      VdbeComment((v, "%s expr-column %d", p->zIdxName, p->iIdxCol));
      sqlite3VdbeGoto(v, 0);
      p = pParse->pIdxEpr;
      pParse->pIdxEpr = 0;
      sqlite3ExprCode(pParse, pExpr, target);
      pParse->pIdxEpr = p;
      sqlite3VdbeJumpHere(v, addr+2);
    }else{
      sqlite3VdbeAddOp3(v, OP_Column, p->iIdxCur, p->iIdxCol, target);
      VdbeComment((v, "%s expr-column %d", p->zIdxName, p->iIdxCol));
    }
    return target;
  }
  return -1;  /* Not found */
}


/*
** Generate code into the current Vdbe to evaluate the given
** expression.  Attempt to store the results in register "target".
** Return the register where results are stored.
**
3374
3375
3376
3377
3378
3379
3380
3381
3382

3383
3384
3385
3386
3387
3388





3389

3390
3391
3392
3393
3394
3395




3396
3397
3398

3399

3400
3401
















3402
3403
3404

3405
3406
3407

3408
3409
3410
3411
3412
3413
3414

3415
3416
3417
3418






3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431

3432
3433
3434











































3435
3436
3437
3438
3439


3440

3441
3442

3443
3444
3445
3446
3447
3448
3449
4182
4183
4184
4185
4186
4187
4188


4189


4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205

4206
4207
4208
4209
4210


4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247




4248
4249
4250
4251
4252
4253
4254
4255




4256
4257
4258
4259
4260
4261
4262
4263



4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313

4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324







-
-
+
-
-




+
+
+
+
+

+





-
+
+
+
+

-
-
+

+


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



+



+







+
-
-
-
-
+
+
+
+
+
+


-
-
-
-







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





+
+
-
+


+







  int regFree1 = 0;         /* If non-zero free this temporary register */
  int regFree2 = 0;         /* If non-zero free this temporary register */
  int r1, r2;               /* Various register numbers */
  Expr tempX;               /* Temporary expression node */
  int p5 = 0;

  assert( target>0 && target<=pParse->nMem );
  if( v==0 ){
    assert( pParse->db->mallocFailed );
  assert( v!=0 );
    return 0;
  }

expr_code_doover:
  if( pExpr==0 ){
    op = TK_NULL;
  }else if( pParse->pIdxEpr!=0 
   && !ExprHasProperty(pExpr, EP_Leaf)
   && (r1 = sqlite3IndexedExprLookup(pParse, pExpr, target))>=0
  ){
    return r1;
  }else{
    assert( !ExprHasVVAProperty(pExpr,EP_Immutable) );
    op = pExpr->op;
  }
  switch( op ){
    case TK_AGG_COLUMN: {
      AggInfo *pAggInfo = pExpr->pAggInfo;
      struct AggInfo_col *pCol = &pAggInfo->aCol[pExpr->iAgg];
      struct AggInfo_col *pCol;
      assert( pAggInfo!=0 );
      assert( pExpr->iAgg>=0 && pExpr->iAgg<pAggInfo->nColumn );
      pCol = &pAggInfo->aCol[pExpr->iAgg];
      if( !pAggInfo->directMode ){
        assert( pCol->iMem>0 );
        return pCol->iMem;
        return AggInfoColumnReg(pAggInfo, pExpr->iAgg);
      }else if( pAggInfo->useSortingIdx ){
        Table *pTab = pCol->pTab;
        sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdxPTab,
                              pCol->iSorterColumn, target);
        if( pTab==0 ){
          /* No comment added */
        }else if( pCol->iColumn<0 ){
          VdbeComment((v,"%s.rowid",pTab->zName));
        }else{
          VdbeComment((v,"%s.%s", 
              pTab->zName, pTab->aCol[pCol->iColumn].zCnName));
          if( pTab->aCol[pCol->iColumn].affinity==SQLITE_AFF_REAL ){
            sqlite3VdbeAddOp1(v, OP_RealAffinity, target);
          }
        }
        return target;
      }else if( pExpr->y.pTab==0 ){
        /* This case happens when the argument to an aggregate function
        ** is rewritten by aggregateConvertIndexedExprRefToColumn() */
        sqlite3VdbeAddOp3(v, OP_Column, pExpr->iTable, pExpr->iColumn, target);
        return target;
      }
      /* Otherwise, fall thru into the TK_COLUMN case */
      /* no break */ deliberate_fall_through
    }
    case TK_COLUMN: {
      int iTab = pExpr->iTable;
      int iReg;
      if( ExprHasProperty(pExpr, EP_FixedCol) ){
        /* This COLUMN expression is really a constant due to WHERE clause
        ** constraints, and that constant is coded by the pExpr->pLeft
        ** expresssion.  However, make sure the constant has the correct
        ** datatype by applying the Affinity of the table column to the
        ** constant.
        */
        int aff;
        int iReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft,target);
        int aff = sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
        if( aff!=SQLITE_AFF_BLOB ){
          static const char zAff[] = "B\000C\000D\000E";
        iReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft,target);
        assert( ExprUseYTab(pExpr) );
        assert( pExpr->y.pTab!=0 );
        aff = sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
        if( aff>SQLITE_AFF_BLOB ){
          static const char zAff[] = "B\000C\000D\000E\000F";
          assert( SQLITE_AFF_BLOB=='A' );
          assert( SQLITE_AFF_TEXT=='B' );
          if( iReg!=target ){
            sqlite3VdbeAddOp2(v, OP_SCopy, iReg, target);
            iReg = target;
          }
          sqlite3VdbeAddOp4(v, OP_Affinity, iReg, 1, 0,
                            &zAff[(aff-'B')*2], P4_STATIC);
        }
        return iReg;
      }
      if( iTab<0 ){
        if( pParse->iSelfTab<0 ){
          /* Other columns in the same row for CHECK constraints or
          /* Generating CHECK constraints or inserting into partial index */
          return pExpr->iColumn - pParse->iSelfTab;
        }else{
          ** generated columns or for inserting into partial index.
          ** The row is unpacked into registers beginning at
          ** 0-(pParse->iSelfTab).  The rowid (if any) is in a register
          ** immediately prior to the first column.
          */
          Column *pCol;
          Table *pTab;
          int iSrc;
          int iCol = pExpr->iColumn;
          assert( ExprUseYTab(pExpr) );
          pTab = pExpr->y.pTab;
          assert( pTab!=0 );
          assert( iCol>=XN_ROWID );
          assert( iCol<pTab->nCol );
          if( iCol<0 ){
            return -1-pParse->iSelfTab;
          }
          pCol = pTab->aCol + iCol;
          testcase( iCol!=sqlite3TableColumnToStorage(pTab,iCol) );
          iSrc = sqlite3TableColumnToStorage(pTab, iCol) - pParse->iSelfTab;
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
          if( pCol->colFlags & COLFLAG_GENERATED ){
            if( pCol->colFlags & COLFLAG_BUSY ){
              sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"",
                              pCol->zCnName);
              return 0;
            }
            pCol->colFlags |= COLFLAG_BUSY;
            if( pCol->colFlags & COLFLAG_NOTAVAIL ){
              sqlite3ExprCodeGeneratedColumn(pParse, pTab, pCol, iSrc);
            }
            pCol->colFlags &= ~(COLFLAG_BUSY|COLFLAG_NOTAVAIL);
            return iSrc;
          }else
#endif /* SQLITE_OMIT_GENERATED_COLUMNS */
          if( pCol->affinity==SQLITE_AFF_REAL ){
            sqlite3VdbeAddOp2(v, OP_SCopy, iSrc, target);
            sqlite3VdbeAddOp1(v, OP_RealAffinity, target);
            return target;
          }else{
            return iSrc;
          }
        }else{
          /* Coding an expression that is part of an index where column names
          ** in the index refer to the table to which the index belongs */
          iTab = pParse->iSelfTab - 1;
        }
      }
      assert( ExprUseYTab(pExpr) );
      assert( pExpr->y.pTab!=0 );
      return sqlite3ExprCodeGetColumn(pParse, pExpr->y.pTab,
      iReg = sqlite3ExprCodeGetColumn(pParse, pExpr->y.pTab,
                               pExpr->iColumn, iTab, target,
                               pExpr->op2);
      return iReg;
    }
    case TK_INTEGER: {
      codeInteger(pParse, pExpr, 0, target);
      return target;
    }
    case TK_TRUEFALSE: {
      sqlite3VdbeAddOp2(v, OP_Integer, sqlite3ExprTruthValue(pExpr), target);
3457
3458
3459
3460
3461
3462
3463
3464






3465
3466
3467
3468
3469
3470
3471
4332
4333
4334
4335
4336
4337
4338

4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351







-
+
+
+
+
+
+







    }
#endif
    case TK_STRING: {
      assert( !ExprHasProperty(pExpr, EP_IntValue) );
      sqlite3VdbeLoadString(v, target, pExpr->u.zToken);
      return target;
    }
    case TK_NULL: {
    default: {
      /* Make NULL the default case so that if a bug causes an illegal
      ** Expr node to be passed into this function, it will be handled
      ** sanely and not crash.  But keep the assert() to bring the problem
      ** to the attention of the developers. */
      assert( op==TK_NULL || op==TK_ERROR || pParse->db->mallocFailed );
      sqlite3VdbeAddOp2(v, OP_Null, 0, target);
      return target;
    }
#ifndef SQLITE_OMIT_BLOB_LITERAL
    case TK_BLOB: {
      int n;
      const char *z;
3484
3485
3486
3487
3488
3489
3490
3491

3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507

3508
3509
3510
3511
3512
3513
3514
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
4394
4395







-
+
















+







    case TK_VARIABLE: {
      assert( !ExprHasProperty(pExpr, EP_IntValue) );
      assert( pExpr->u.zToken!=0 );
      assert( pExpr->u.zToken[0]!=0 );
      sqlite3VdbeAddOp2(v, OP_Variable, pExpr->iColumn, target);
      if( pExpr->u.zToken[1]!=0 ){
        const char *z = sqlite3VListNumToName(pParse->pVList, pExpr->iColumn);
        assert( pExpr->u.zToken[0]=='?' || strcmp(pExpr->u.zToken, z)==0 );
        assert( pExpr->u.zToken[0]=='?' || (z && !strcmp(pExpr->u.zToken, z)) );
        pParse->pVList[0] = 0; /* Indicate VList may no longer be enlarged */
        sqlite3VdbeAppendP4(v, (char*)z, P4_STATIC);
      }
      return target;
    }
    case TK_REGISTER: {
      return pExpr->iTable;
    }
#ifndef SQLITE_OMIT_CAST
    case TK_CAST: {
      /* Expressions of the form:   CAST(pLeft AS token) */
      inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
      if( inReg!=target ){
        sqlite3VdbeAddOp2(v, OP_SCopy, inReg, target);
        inReg = target;
      }
      assert( !ExprHasProperty(pExpr, EP_IntValue) );
      sqlite3VdbeAddOp2(v, OP_Cast, target,
                        sqlite3AffinityType(pExpr->u.zToken, 0));
      return inReg;
    }
#endif /* SQLITE_OMIT_CAST */
    case TK_IS:
    case TK_ISNOT:
3523
3524
3525
3526
3527
3528
3529

3530

3531


3532
3533
3534
3535
3536
3537





3538
3539
3540
3541
3542
3543
3544
4404
4405
4406
4407
4408
4409
4410
4411

4412

4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432







+
-
+
-
+
+






+
+
+
+
+







    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:
3582
3583
3584
3585
3586
3587
3588

3589
3590
3591
3592
3593
3594
3595
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484







+







        codeReal(v, pLeft->u.zToken, 1, target);
        return target;
#endif
      }else{
        tempX.op = TK_INTEGER;
        tempX.flags = EP_IntValue|EP_TokenOnly;
        tempX.u.iValue = 0;
        ExprClearVVAProperties(&tempX);
        r1 = sqlite3ExprCodeTemp(pParse, &tempX, &regFree1);
        r2 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree2);
        sqlite3VdbeAddOp3(v, OP_Subtract, r2, r1, target);
        testcase( regFree2==0 );
      }
      break;
    }
3627
3628
3629
3630
3631
3632
3633
3634




3635
3636

3637
3638

3639
3640
3641
3642
3643
3644
3645
4516
4517
4518
4519
4520
4521
4522

4523
4524
4525
4526
4527

4528
4529

4530
4531
4532
4533
4534
4535
4536
4537







-
+
+
+
+

-
+

-
+







      VdbeCoverageIf(v, op==TK_NOTNULL);
      sqlite3VdbeAddOp2(v, OP_Integer, 0, target);
      sqlite3VdbeJumpHere(v, addr);
      break;
    }
    case TK_AGG_FUNCTION: {
      AggInfo *pInfo = pExpr->pAggInfo;
      if( pInfo==0 ){
      if( pInfo==0
       || NEVER(pExpr->iAgg<0)
       || NEVER(pExpr->iAgg>=pInfo->nFunc)
      ){
        assert( !ExprHasProperty(pExpr, EP_IntValue) );
        sqlite3ErrorMsg(pParse, "misuse of aggregate: %s()", pExpr->u.zToken);
        sqlite3ErrorMsg(pParse, "misuse of aggregate: %#T()", pExpr);
      }else{
        return pInfo->aFunc[pExpr->iAgg].iMem;
        return AggInfoFuncReg(pInfo, pExpr->iAgg);
      }
      break;
    }
    case TK_FUNCTION: {
      ExprList *pFarg;       /* List of function arguments */
      int nFarg;             /* Number of function arguments */
      FuncDef *pDef;         /* The function definition object */
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662



3663
3664
3665


3666
3667
3668

3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680

3681
3682
3683
3684
3685
3686
3687
3688

3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700

3701
3702
3703
3704

3705
3706

3707
3708

3709
3710
3711
3712
3713
3714

3715
3716
3717
3718

3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
4545
4546
4547
4548
4549
4550
4551



4552
4553
4554
4555


4556
4557



4558

4559
4560
4561
4562
4563
4564
4565
4566
4567
4568

4569
4570
4571






4572












4573




4574


4575


4576






4577




4578



4579

4580
4581
4582
4583
4584
4585
4586







-
-
-
+
+
+

-
-
+
+
-
-
-
+
-










-
+


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

-







#ifndef SQLITE_OMIT_WINDOWFUNC
      if( ExprHasProperty(pExpr, EP_WinFunc) ){
        return pExpr->y.pWin->regResult;
      }
#endif

      if( ConstFactorOk(pParse) && sqlite3ExprIsConstantNotJoin(pExpr) ){
        /* SQL functions can be expensive. So try to move constant functions
        ** out of the inner loop, even if that means an extra OP_Copy. */
        return sqlite3ExprCodeAtInit(pParse, pExpr, -1);
        /* SQL functions can be expensive. So try to avoid running them
        ** multiple times if we know they always give the same result */
        return sqlite3ExprCodeRunJustOnce(pParse, pExpr, -1);
      }
      assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
      if( ExprHasProperty(pExpr, EP_TokenOnly) ){
      assert( !ExprHasProperty(pExpr, EP_TokenOnly) );
      assert( ExprUseXList(pExpr) );
        pFarg = 0;
      }else{
        pFarg = pExpr->x.pList;
      pFarg = pExpr->x.pList;
      }
      nFarg = pFarg ? pFarg->nExpr : 0;
      assert( !ExprHasProperty(pExpr, EP_IntValue) );
      zId = pExpr->u.zToken;
      pDef = sqlite3FindFunction(db, zId, nFarg, enc, 0);
#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
      if( pDef==0 && pParse->explain ){
        pDef = sqlite3FindFunction(db, "unknown", nFarg, enc, 0);
      }
#endif
      if( pDef==0 || pDef->xFinalize!=0 ){
        sqlite3ErrorMsg(pParse, "unknown function: %s()", zId);
        sqlite3ErrorMsg(pParse, "unknown function: %#T()", pExpr);
        break;
      }

      /* Attempt a direct implementation of the built-in COALESCE() and
      ** IFNULL() functions.  This avoids unnecessary evaluation of
      ** arguments past the first non-NULL argument.
      */
      if( pDef->funcFlags & SQLITE_FUNC_COALESCE ){
      if( pDef->funcFlags & SQLITE_FUNC_INLINE ){
        int endCoalesce = sqlite3VdbeMakeLabel(v);
        assert( nFarg>=2 );
        sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target);
        for(i=1; i<nFarg; i++){
          sqlite3VdbeAddOp2(v, OP_NotNull, target, endCoalesce);
          VdbeCoverage(v);
          sqlite3ExprCode(pParse, pFarg->a[i].pExpr, target);
        }
        sqlite3VdbeResolveLabel(v, endCoalesce);
        break;
      }

        assert( (pDef->funcFlags & SQLITE_FUNC_UNSAFE)==0 );
      /* The UNLIKELY() function is a no-op.  The result is the value
      ** of the first argument.
      */
      if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){
        assert( (pDef->funcFlags & SQLITE_FUNC_DIRECT)==0 );
        assert( nFarg>=1 );
        return sqlite3ExprCodeTarget(pParse, pFarg->a[0].pExpr, target);
        return exprCodeInlineFunction(pParse, pFarg,
      }

             SQLITE_PTR_TO_INT(pDef->pUserData), target);
#ifdef SQLITE_DEBUG
      /* The AFFINITY() function evaluates to a string that describes
      ** the type affinity of the argument.  This is used for testing of
      ** the SQLite type logic.
      */
      if( pDef->funcFlags & SQLITE_FUNC_AFFINITY ){
      }else if( pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE) ){
        const char *azAff[] = { "blob", "text", "numeric", "integer", "real" };
        char aff;
        assert( nFarg==1 );
        aff = sqlite3ExprAffinity(pFarg->a[0].pExpr);
        sqlite3ExprFunctionUsable(pParse, pExpr, pDef);
        sqlite3VdbeLoadString(v, target, 
                              aff ? azAff[aff-SQLITE_AFF_BLOB] : "none");
        return target;
      }
#endif

      for(i=0; i<nFarg; i++){
        if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){
          testcase( i==31 );
          constMask |= MASKBIT32(i);
        }
        if( (pDef->funcFlags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793





3794
3795
3796
3797
3798
3799
3800
3801
3802
3803


3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814




3815


3816
3817
3818

3819
3820
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
4638
4639
4640
4641
4642
4643
4644





4645
4646
4647
4648
4649
4650









4651
4652


4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665

4666
4667
4668
4669

4670
4671
4672
4673
4674
4675


4676
4677
4678
4679
4680


4681
4682
4683


4684
4685
4686

4687
4688
4689


4690
4691
4692
4693
4694
4695
4696
4697
4698







-
-
-
-
-
+
+
+
+
+

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









+
+
+
+
-
+
+


-
+





-
-
+
+
+
+

-
-
+
+
+
-
-



-
+


-
-
+
+







        pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[0].pExpr);
      }
#endif
      if( pDef->funcFlags & SQLITE_FUNC_NEEDCOLL ){
        if( !pColl ) pColl = db->pDfltColl; 
        sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ);
      }
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
      if( pDef->funcFlags & SQLITE_FUNC_OFFSET ){
        Expr *pArg = pFarg->a[0].pExpr;
        if( pArg->op==TK_COLUMN ){
          sqlite3VdbeAddOp3(v, OP_Offset, pArg->iTable, pArg->iColumn, target);
      sqlite3VdbeAddFunctionCall(pParse, constMask, r1, target, nFarg,
                                 pDef, pExpr->op2);
      if( nFarg ){
        if( constMask==0 ){
          sqlite3ReleaseTempRange(pParse, r1, nFarg);
        }else{
          sqlite3VdbeAddOp2(v, OP_Null, 0, target);
        }
      }else
#endif
      {
        sqlite3VdbeAddOp4(v, pParse->iSelfTab ? OP_PureFunc0 : OP_Function0,
                          constMask, r1, target, (char*)pDef, P4_FUNCDEF);
        sqlite3VdbeChangeP5(v, (u8)nFarg);
      }
          sqlite3VdbeReleaseRegisters(pParse, r1, nFarg, constMask, 1);
        }
      if( nFarg && constMask==0 ){
        sqlite3ReleaseTempRange(pParse, r1, nFarg);
      }
      return target;
    }
#ifndef SQLITE_OMIT_SUBQUERY
    case TK_EXISTS:
    case TK_SELECT: {
      int nCol;
      testcase( op==TK_EXISTS );
      testcase( op==TK_SELECT );
      if( pParse->db->mallocFailed ){
        return 0;
      }else if( op==TK_SELECT
             && ALWAYS( ExprUseXSelect(pExpr) )
      if( op==TK_SELECT && (nCol = pExpr->x.pSelect->pEList->nExpr)!=1 ){
             && (nCol = pExpr->x.pSelect->pEList->nExpr)!=1
      ){
        sqlite3SubselectError(pParse, nCol, 1);
      }else{
        return sqlite3CodeSubselect(pParse, pExpr, 0, 0);
        return sqlite3CodeSubselect(pParse, pExpr);
      }
      break;
    }
    case TK_SELECT_COLUMN: {
      int n;
      if( pExpr->pLeft->iTable==0 ){
        pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft, 0, 0);
      Expr *pLeft = pExpr->pLeft;
      if( pLeft->iTable==0 || pParse->withinRJSubrtn > pLeft->op2 ){
        pLeft->iTable = sqlite3CodeSubselect(pParse, pLeft);
        pLeft->op2 = pParse->withinRJSubrtn;
      }
      assert( pExpr->iTable==0 || pExpr->pLeft->op==TK_SELECT );
      if( pExpr->iTable
      assert( pLeft->op==TK_SELECT || pLeft->op==TK_ERROR );
      n = sqlite3ExprVectorSize(pLeft);
      if( pExpr->iTable!=n ){
       && pExpr->iTable!=(n = sqlite3ExprVectorSize(pExpr->pLeft)) 
      ){
        sqlite3ErrorMsg(pParse, "%d columns assigned %d values",
                                pExpr->iTable, n);
      }
      return pExpr->pLeft->iTable + pExpr->iColumn;
      return pLeft->iTable + pExpr->iColumn;
    }
    case TK_IN: {
      int destIfFalse = sqlite3VdbeMakeLabel(v);
      int destIfNull = sqlite3VdbeMakeLabel(v);
      int destIfFalse = sqlite3VdbeMakeLabel(pParse);
      int destIfNull = sqlite3VdbeMakeLabel(pParse);
      sqlite3VdbeAddOp2(v, OP_Null, 0, target);
      sqlite3ExprCodeIN(pParse, pExpr, destIfFalse, destIfNull);
      sqlite3VdbeAddOp2(v, OP_Integer, 1, target);
      sqlite3VdbeResolveLabel(v, destIfFalse);
      sqlite3VdbeAddOp2(v, OP_AddImm, target, 0);
      sqlite3VdbeResolveLabel(v, destIfNull);
      return target;
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866


















3867
3868
3869
3870
3871
3872
3873
4710
4711
4712
4713
4714
4715
4716
4717


4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742








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







    ** X is stored in pExpr->pLeft.
    ** Y is stored in pExpr->pList->a[0].pExpr.
    ** Z is stored in pExpr->pList->a[1].pExpr.
    */
    case TK_BETWEEN: {
      exprCodeBetween(pParse, pExpr, target, 0, 0);
      return target;
    }
    case TK_SPAN:
    case TK_COLLATE: 
    case TK_COLLATE: {
      if( !ExprHasProperty(pExpr, EP_Collate)
       && ALWAYS(pExpr->pLeft)
       && pExpr->pLeft->op==TK_FUNCTION
      ){
        inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
        if( inReg!=target ){
          sqlite3VdbeAddOp2(v, OP_SCopy, inReg, target);
          inReg = target;
        }
        sqlite3VdbeAddOp1(v, OP_ClrSubtype, inReg);
        return inReg;
      }else{
        pExpr = pExpr->pLeft;
        goto expr_code_doover; /* 2018-04-28: Prevent deep recursion. */
      }
    }
    case TK_SPAN:
    case TK_UPLUS: {
      pExpr = pExpr->pLeft;
      goto expr_code_doover; /* 2018-04-28: Prevent deep recursion. OSSFuzz. */
    }

    case TK_TRIGGER: {
      /* If the opcode is TK_TRIGGER, then the expression is a reference
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
3923
3924
3925
3926
3927
3928
3929
3930
3931






3932
3933
















3934





3935

3936
3937
3938
3939
3940
3941
3942
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771


4772
4773
4774
4775
4776
4777


4778
4779
4780
4781
4782
4783
4784

4785
4786
4787
4788
4789
4790
4791
4792
4793


4794

4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844







+
+
+
+
+
-
-
+
+
+
+


-
-
+
+





-
+








-
-
+
-











+
+
+
+
+
+


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

+
+
+
+
+

+







      **
      ** Then p1 is interpreted as follows:
      **
      **   p1==0   ->    old.rowid     p1==3   ->    new.rowid
      **   p1==1   ->    old.a         p1==4   ->    new.a
      **   p1==2   ->    old.b         p1==5   ->    new.b       
      */
      Table *pTab;
      int iCol;
      int p1;

      assert( ExprUseYTab(pExpr) );
      Table *pTab = pExpr->y.pTab;
      int p1 = pExpr->iTable * (pTab->nCol+1) + 1 + pExpr->iColumn;
      pTab = pExpr->y.pTab;
      iCol = pExpr->iColumn;
      p1 = pExpr->iTable * (pTab->nCol+1) + 1 
                     + sqlite3TableColumnToStorage(pTab, iCol);

      assert( pExpr->iTable==0 || pExpr->iTable==1 );
      assert( pExpr->iColumn>=-1 && pExpr->iColumn<pTab->nCol );
      assert( pTab->iPKey<0 || pExpr->iColumn!=pTab->iPKey );
      assert( iCol>=-1 && iCol<pTab->nCol );
      assert( pTab->iPKey<0 || iCol!=pTab->iPKey );
      assert( p1>=0 && p1<(pTab->nCol*2+2) );

      sqlite3VdbeAddOp2(v, OP_Param, p1, target);
      VdbeComment((v, "r[%d]=%s.%s", target,
        (pExpr->iTable ? "new" : "old"),
        (pExpr->iColumn<0 ? "rowid" : pExpr->y.pTab->aCol[pExpr->iColumn].zName)
        (pExpr->iColumn<0 ? "rowid" : pExpr->y.pTab->aCol[iCol].zCnName)
      ));

#ifndef SQLITE_OMIT_FLOATING_POINT
      /* If the column has REAL affinity, it may currently be stored as an
      ** integer. Use OP_RealAffinity to make sure it is really real.
      **
      ** EVIDENCE-OF: R-60985-57662 SQLite will convert the value back to
      ** floating point when extracting it from the record.  */
      if( pExpr->iColumn>=0 
       && pTab->aCol[pExpr->iColumn].affinity==SQLITE_AFF_REAL
      if( iCol>=0 && pTab->aCol[iCol].affinity==SQLITE_AFF_REAL ){
      ){
        sqlite3VdbeAddOp1(v, OP_RealAffinity, target);
      }
#endif
      break;
    }

    case TK_VECTOR: {
      sqlite3ErrorMsg(pParse, "row value misused");
      break;
    }

    /* TK_IF_NULL_ROW Expr nodes are inserted ahead of expressions
    ** that derive from the right-hand table of a LEFT JOIN.  The
    ** Expr.iTable value is the table number for the right-hand table.
    ** The expression is only evaluated if that table is not currently
    ** on a LEFT JOIN NULL row.
    */
    case TK_IF_NULL_ROW: {
      int addrINR;
      u8 okConstFactor = pParse->okConstFactor;
      AggInfo *pAggInfo = pExpr->pAggInfo;
      if( pAggInfo ){
        assert( pExpr->iAgg>=0 && pExpr->iAgg<pAggInfo->nColumn );
        if( !pAggInfo->directMode ){
          inReg = AggInfoColumnReg(pAggInfo, pExpr->iAgg);
          break;
        }
        if( pExpr->pAggInfo->useSortingIdx ){
          sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdxPTab,
                            pAggInfo->aCol[pExpr->iAgg].iSorterColumn,
                            target);
          inReg = target;
          break;
        }
      }
      addrINR = sqlite3VdbeAddOp1(v, OP_IfNullRow, pExpr->iTable);
      /* Temporarily disable factoring of constant expressions, since
      ** even though expressions may appear to be constant, they are not
      ** really constant because they originate from the right-hand side
      ** of a LEFT JOIN. */
      pParse->okConstFactor = 0;
      inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
      pParse->okConstFactor = okConstFactor;
      sqlite3VdbeJumpHere(v, addrINR);
      sqlite3VdbeChangeP3(v, addrINR, inReg);
      break;
    }

    /*
    ** Form A:
3955
3956
3957
3958
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
4000
4001

4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013


4014
4015
4016
4017
4018
4019
4020
4021
4022




4023
4024

4025
4026
4027
4028
4029

4030
4031
4032
4033

4034
4035
4036
4037
4038
4039



4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052







4053
4054
4055
4056
4057
4058




4059
4060

4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071

4072


4073
4074
4075
4076
4077














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
4107
4108
4109
4110

4111
4112
4113
4114
4115
4116
4117
4857
4858
4859
4860
4861
4862
4863

4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876

4877
4878
4879
4880
4881

4882
4883

4884
4885
4886
4887
4888
4889

4890
4891
4892
4893

4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908

4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928




4929
4930
4931
4932
4933

4934
4935
4936
4937
4938

4939
4940
4941
4942

4943
4944
4945
4946
4947


4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962

4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973


4974
4975
4976
4977
4978

4979
4980
4981
4982
4983
4984
4985
4986
4987
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
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039

5040
5041
5042
5043
5044
5045
5046

5047
5048
5049
5050
5051
5052
5053
5054







-
+









+
+

-
+




-
+

-
+
+
+
+
+

-
+



-
+














-
+












+
+





-
-
-
-
+
+
+
+

-
+




-
+



-
+




-
-
+
+
+












-
+
+
+
+
+
+
+




-
-
+
+
+
+

-
+











+
-
+
+





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


















-
+

+




-
+







    ** is even, then Y is omitted and the "otherwise" result is NULL.
    ** Ei is in pExpr->pList->a[i*2] and Ri is pExpr->pList->a[i*2+1].
    **
    ** The result of the expression is the Ri for the first matching Ei,
    ** or if there is no matching Ei, the ELSE term Y, or if there is
    ** no ELSE term, NULL.
    */
    default: assert( op==TK_CASE ); {
    case TK_CASE: {
      int endLabel;                     /* GOTO label for end of CASE stmt */
      int nextCase;                     /* GOTO label for next WHEN clause */
      int nExpr;                        /* 2x number of WHEN terms */
      int i;                            /* Loop counter */
      ExprList *pEList;                 /* List of WHEN terms */
      struct ExprList_item *aListelem;  /* Array of WHEN terms */
      Expr opCompare;                   /* The X==Ei expression */
      Expr *pX;                         /* The X expression */
      Expr *pTest = 0;                  /* X==Ei (form A) or just Ei (form B) */
      Expr *pDel = 0;
      sqlite3 *db = pParse->db;

      assert( !ExprHasProperty(pExpr, EP_xIsSelect) && pExpr->x.pList );
      assert( ExprUseXList(pExpr) && pExpr->x.pList!=0 );
      assert(pExpr->x.pList->nExpr > 0);
      pEList = pExpr->x.pList;
      aListelem = pEList->a;
      nExpr = pEList->nExpr;
      endLabel = sqlite3VdbeMakeLabel(v);
      endLabel = sqlite3VdbeMakeLabel(pParse);
      if( (pX = pExpr->pLeft)!=0 ){
        tempX = *pX;
        pDel = sqlite3ExprDup(db, pX, 0);
        if( db->mallocFailed ){
          sqlite3ExprDelete(db, pDel);
          break;
        }
        testcase( pX->op==TK_COLUMN );
        exprToRegister(&tempX, exprCodeVector(pParse, &tempX, &regFree1));
        exprToRegister(pDel, exprCodeVector(pParse, pDel, &regFree1));
        testcase( regFree1==0 );
        memset(&opCompare, 0, sizeof(opCompare));
        opCompare.op = TK_EQ;
        opCompare.pLeft = &tempX;
        opCompare.pLeft = pDel;
        pTest = &opCompare;
        /* Ticket b351d95f9cd5ef17e9d9dbae18f5ca8611190001:
        ** The value in regFree1 might get SCopy-ed into the file result.
        ** So make sure that the regFree1 register is not reused for other
        ** purposes and possibly overwritten.  */
        regFree1 = 0;
      }
      for(i=0; i<nExpr-1; i=i+2){
        if( pX ){
          assert( pTest!=0 );
          opCompare.pRight = aListelem[i].pExpr;
        }else{
          pTest = aListelem[i].pExpr;
        }
        nextCase = sqlite3VdbeMakeLabel(v);
        nextCase = sqlite3VdbeMakeLabel(pParse);
        testcase( pTest->op==TK_COLUMN );
        sqlite3ExprIfFalse(pParse, pTest, nextCase, SQLITE_JUMPIFNULL);
        testcase( aListelem[i+1].pExpr->op==TK_COLUMN );
        sqlite3ExprCode(pParse, aListelem[i+1].pExpr, target);
        sqlite3VdbeGoto(v, endLabel);
        sqlite3VdbeResolveLabel(v, nextCase);
      }
      if( (nExpr&1)!=0 ){
        sqlite3ExprCode(pParse, pEList->a[nExpr-1].pExpr, target);
      }else{
        sqlite3VdbeAddOp2(v, OP_Null, 0, target);
      }
      sqlite3ExprDelete(db, pDel);
      setDoNotMergeFlagOnCopy(v);
      sqlite3VdbeResolveLabel(v, endLabel);
      break;
    }
#ifndef SQLITE_OMIT_TRIGGER
    case TK_RAISE: {
      assert( pExpr->affinity==OE_Rollback 
           || pExpr->affinity==OE_Abort
           || pExpr->affinity==OE_Fail
           || pExpr->affinity==OE_Ignore
      assert( pExpr->affExpr==OE_Rollback 
           || pExpr->affExpr==OE_Abort
           || pExpr->affExpr==OE_Fail
           || pExpr->affExpr==OE_Ignore
      );
      if( !pParse->pTriggerTab ){
      if( !pParse->pTriggerTab && !pParse->nested ){
        sqlite3ErrorMsg(pParse,
                       "RAISE() may only be used within a trigger-program");
        return 0;
      }
      if( pExpr->affinity==OE_Abort ){
      if( pExpr->affExpr==OE_Abort ){
        sqlite3MayAbort(pParse);
      }
      assert( !ExprHasProperty(pExpr, EP_IntValue) );
      if( pExpr->affinity==OE_Ignore ){
      if( pExpr->affExpr==OE_Ignore ){
        sqlite3VdbeAddOp4(
            v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0);
        VdbeCoverage(v);
      }else{
        sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_TRIGGER,
                              pExpr->affinity, pExpr->u.zToken, 0, 0);
        sqlite3HaltConstraint(pParse,
             pParse->pTriggerTab ? SQLITE_CONSTRAINT_TRIGGER : SQLITE_ERROR,
             pExpr->affExpr, pExpr->u.zToken, 0, 0);
      }

      break;
    }
#endif
  }
  sqlite3ReleaseTempReg(pParse, regFree1);
  sqlite3ReleaseTempReg(pParse, regFree2);
  return inReg;
}

/*
** Factor out the code of the given expression to initialization time.
** Generate code that will evaluate expression pExpr just one time
** per prepared statement execution.
**
** If the expression uses functions (that might throw an exception) then
** guard them with an OP_Once opcode to ensure that the code is only executed
** once. If no functions are involved, then factor the code out and put it at
** the end of the prepared statement in the initialization section.
**
** If regDest>=0 then the result is always stored in that register and the
** result is not reusable.  If regDest<0 then this routine is free to 
** store the value whereever it wants.  The register where the expression 
** is stored is returned.  When regDest<0, two identical expressions will
** code to the same register.
** is stored is returned.  When regDest<0, two identical expressions might
** code to the same register, if they do not contain function calls and hence
** are factored out into the initialization section at the end of the
** prepared statement.
*/
int sqlite3ExprCodeAtInit(
int sqlite3ExprCodeRunJustOnce(
  Parse *pParse,    /* Parsing context */
  Expr *pExpr,      /* The expression to code when the VDBE initializes */
  int regDest       /* Store the value in this register */
){
  ExprList *p;
  assert( ConstFactorOk(pParse) );
  p = pParse->pConstExpr;
  if( regDest<0 && p ){
    struct ExprList_item *pItem;
    int i;
    for(pItem=p->a, i=p->nExpr; i>0; pItem++, i--){
      if( pItem->fg.reusable
      if( pItem->reusable && sqlite3ExprCompare(0,pItem->pExpr,pExpr,-1)==0 ){
       && sqlite3ExprCompare(0,pItem->pExpr,pExpr,-1)==0
      ){
        return pItem->u.iConstExprReg;
      }
    }
  }
  pExpr = sqlite3ExprDup(pParse->db, pExpr, 0);
  if( pExpr!=0 && ExprHasProperty(pExpr, EP_HasFunc) ){
    Vdbe *v = pParse->pVdbe;
    int addr;
    assert( v );
    addr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
    pParse->okConstFactor = 0;
    if( !pParse->db->mallocFailed ){
      if( regDest<0 ) regDest = ++pParse->nMem;
      sqlite3ExprCode(pParse, pExpr, regDest);
    }
    pParse->okConstFactor = 1;
    sqlite3ExprDelete(pParse->db, pExpr);
    sqlite3VdbeJumpHere(v, addr);
  }else{
  p = sqlite3ExprListAppend(pParse, p, pExpr);
  if( p ){
     struct ExprList_item *pItem = &p->a[p->nExpr-1];
     pItem->reusable = regDest<0;
     if( regDest<0 ) regDest = ++pParse->nMem;
     pItem->u.iConstExprReg = regDest;
  }
  pParse->pConstExpr = p;
    p = sqlite3ExprListAppend(pParse, p, pExpr);
    if( p ){
       struct ExprList_item *pItem = &p->a[p->nExpr-1];
       pItem->fg.reusable = regDest<0;
       if( regDest<0 ) regDest = ++pParse->nMem;
       pItem->u.iConstExprReg = regDest;
    }
    pParse->pConstExpr = p;
  }
  return regDest;
}

/*
** Generate code to evaluate an expression and store the results
** into a register.  Return the register number where the results
** are stored.
**
** If the register is a temporary register that can be deallocated,
** then write its number into *pReg.  If the result register is not
** a temporary, then set *pReg to zero.
**
** If pExpr is a constant, then this routine might generate this
** code to fill the register in the initialization section of the
** VDBE program, in order to factor it out of the evaluation loop.
*/
int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){
  int r2;
  pExpr = sqlite3ExprSkipCollate(pExpr);
  pExpr = sqlite3ExprSkipCollateAndLikely(pExpr);
  if( ConstFactorOk(pParse)
   && ALWAYS(pExpr!=0)
   && pExpr->op!=TK_REGISTER
   && sqlite3ExprIsConstantNotJoin(pExpr)
  ){
    *pReg  = 0;
    r2 = sqlite3ExprCodeAtInit(pParse, pExpr, -1);
    r2 = sqlite3ExprCodeRunJustOnce(pParse, pExpr, -1);
  }else{
    int r1 = sqlite3GetTempReg(pParse);
    r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
    if( r2==r1 ){
      *pReg = r1;
    }else{
      sqlite3ReleaseTempReg(pParse, r1);
4125
4126
4127
4128
4129
4130
4131

4132
4133
4134
4135
4136



4137
4138
4139






4140

4141
4142
4143
4144
4145
4146
4147
5062
5063
5064
5065
5066
5067
5068
5069
5070




5071
5072
5073



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







+

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

+







** Generate code that will evaluate expression pExpr and store the
** results in register target.  The results are guaranteed to appear
** in register target.
*/
void sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
  int inReg;

  assert( pExpr==0 || !ExprHasVVAProperty(pExpr,EP_Immutable) );
  assert( target>0 && target<=pParse->nMem );
  if( pExpr && pExpr->op==TK_REGISTER ){
    sqlite3VdbeAddOp2(pParse->pVdbe, OP_Copy, pExpr->iTable, target);
  }else{
    inReg = sqlite3ExprCodeTarget(pParse, pExpr, target);
  assert( pParse->pVdbe!=0 || pParse->db->mallocFailed );
  if( pParse->pVdbe==0 ) return;
  inReg = sqlite3ExprCodeTarget(pParse, pExpr, target);
    assert( pParse->pVdbe!=0 || pParse->db->mallocFailed );
    if( inReg!=target && pParse->pVdbe ){
      sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, inReg, target);
  if( inReg!=target ){
    u8 op;
    if( ALWAYS(pExpr) && ExprHasProperty(pExpr,EP_Subquery) ){
      op = OP_Copy;
    }else{
      op = OP_SCopy;
    }
    sqlite3VdbeAddOp2(pParse->pVdbe, op, inReg, target);
  }
}

/*
** Make a transient copy of expression pExpr and then code it using
** sqlite3ExprCode().  This routine works just like sqlite3ExprCode()
** except that the input expression is guaranteed to be unchanged.
4157
4158
4159
4160
4161
4162
4163
4164

4165
4166

4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
5098
5099
5100
5101
5102
5103
5104

5105
5106

5107
5108
























5109
5110
5111
5112
5113
5114
5115







-
+

-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







** Generate code that will evaluate expression pExpr and store the
** results in register target.  The results are guaranteed to appear
** in register target.  If the expression is constant, then this routine
** might choose to code the expression at initialization time.
*/
void sqlite3ExprCodeFactorable(Parse *pParse, Expr *pExpr, int target){
  if( pParse->okConstFactor && sqlite3ExprIsConstantNotJoin(pExpr) ){
    sqlite3ExprCodeAtInit(pParse, pExpr, target);
    sqlite3ExprCodeRunJustOnce(pParse, pExpr, target);
  }else{
    sqlite3ExprCode(pParse, pExpr, target);
    sqlite3ExprCodeCopy(pParse, pExpr, target);
  }
}

/*
** Generate code that evaluates the given expression and puts the result
** in register target.
**
** Also make a copy of the expression results into another "cache" register
** and modify the expression so that the next time it is evaluated,
** the result is a copy of the cache register.
**
** This routine is used for expressions that are used multiple 
** times.  They are evaluated once and the results of the expression
** are reused.
*/
void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){
  Vdbe *v = pParse->pVdbe;
  int iMem;

  assert( target>0 );
  assert( pExpr->op!=TK_REGISTER );
  sqlite3ExprCode(pParse, pExpr, target);
  iMem = ++pParse->nMem;
  sqlite3VdbeAddOp2(v, OP_Copy, target, iMem);
  exprToRegister(pExpr, iMem);
}

/*
** Generate code that pushes the value of every element of the given
** expression list into a sequence of registers beginning at target.
**
** Return the number of elements evaluated.  The number returned will
4226
4227
4228
4229
4230
4231
4232
4233

4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248

4249
4250
4251
4252
4253
4254

4255
4256

4257
4258
4259
4260
4261
4262
4263
5143
5144
5145
5146
5147
5148
5149

5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164

5165
5166
5167
5168
5169
5170

5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181







-
+














-
+





-
+


+







  assert( target>0 );
  assert( pParse->pVdbe!=0 );  /* Never gets this far otherwise */
  n = pList->nExpr;
  if( !ConstFactorOk(pParse) ) flags &= ~SQLITE_ECEL_FACTOR;
  for(pItem=pList->a, i=0; i<n; i++, pItem++){
    Expr *pExpr = pItem->pExpr;
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
    if( pItem->bSorterRef ){
    if( pItem->fg.bSorterRef ){
      i--;
      n--;
    }else
#endif
    if( (flags & SQLITE_ECEL_REF)!=0 && (j = pItem->u.x.iOrderByCol)>0 ){
      if( flags & SQLITE_ECEL_OMITREF ){
        i--;
        n--;
      }else{
        sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i);
      }
    }else if( (flags & SQLITE_ECEL_FACTOR)!=0
           && sqlite3ExprIsConstantNotJoin(pExpr)
    ){
      sqlite3ExprCodeAtInit(pParse, pExpr, target+i);
      sqlite3ExprCodeRunJustOnce(pParse, pExpr, target+i);
    }else{
      int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i);
      if( inReg!=target+i ){
        VdbeOp *pOp;
        if( copyOp==OP_Copy
         && (pOp=sqlite3VdbeGetOp(v, -1))->opcode==OP_Copy
         && (pOp=sqlite3VdbeGetLastOp(v))->opcode==OP_Copy
         && pOp->p1+pOp->p3+1==inReg
         && pOp->p2+pOp->p3+1==target+i
         && pOp->p5==0  /* The do-not-merge flag must be clear */
        ){
          pOp->p3++;
        }else{
          sqlite3VdbeAddOp2(v, copyOp, inReg, target+i);
        }
      }
    }
4288
4289
4290
4291
4292
4293
4294
4295

4296
4297
4298
4299
4300


4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
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
5206
5207
5208
5209
5210
5211
5212

5213
5214
5215

5216

5217
5218
5219
5220
5221
5222
5223
























5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257







-
+


-

-
+
+





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







static void exprCodeBetween(
  Parse *pParse,    /* Parsing and code generating context */
  Expr *pExpr,      /* The BETWEEN expression */
  int dest,         /* Jump destination or storage location */
  void (*xJump)(Parse*,Expr*,int,int), /* Action to take */
  int jumpIfNull    /* Take the jump if the BETWEEN is NULL */
){
 Expr exprAnd;     /* The AND operator in  x>=y AND x<=z  */
  Expr exprAnd;     /* The AND operator in  x>=y AND x<=z  */
  Expr compLeft;    /* The  x>=y  term */
  Expr compRight;   /* The  x<=z  term */
  Expr exprX;       /* The  x  subexpression */
  int regFree1 = 0; /* Temporary use register */

  Expr *pDel = 0;
  sqlite3 *db = pParse->db;

  memset(&compLeft, 0, sizeof(Expr));
  memset(&compRight, 0, sizeof(Expr));
  memset(&exprAnd, 0, sizeof(Expr));

  assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
  exprX = *pExpr->pLeft;
  exprAnd.op = TK_AND;
  exprAnd.pLeft = &compLeft;
  exprAnd.pRight = &compRight;
  compLeft.op = TK_GE;
  compLeft.pLeft = &exprX;
  compLeft.pRight = pExpr->x.pList->a[0].pExpr;
  compRight.op = TK_LE;
  compRight.pLeft = &exprX;
  compRight.pRight = pExpr->x.pList->a[1].pExpr;
  exprToRegister(&exprX, exprCodeVector(pParse, &exprX, &regFree1));
  if( xJump ){
    xJump(pParse, &exprAnd, dest, jumpIfNull);
  }else{
    /* Mark the expression is being from the ON or USING clause of a join
    ** so that the sqlite3ExprCodeTarget() routine will not attempt to move
    ** it into the Parse.pConstExpr list.  We should use a new bit for this,
    ** for clarity, but we are out of bits in the Expr.flags field so we
    ** have to reuse the EP_FromJoin bit.  Bummer. */
    exprX.flags |= EP_FromJoin;
    sqlite3ExprCodeTarget(pParse, &exprAnd, dest);
  }
  sqlite3ReleaseTempReg(pParse, regFree1);
  assert( ExprUseXList(pExpr) );
  pDel = sqlite3ExprDup(db, pExpr->pLeft, 0);
  if( db->mallocFailed==0 ){
    exprAnd.op = TK_AND;
    exprAnd.pLeft = &compLeft;
    exprAnd.pRight = &compRight;
    compLeft.op = TK_GE;
    compLeft.pLeft = pDel;
    compLeft.pRight = pExpr->x.pList->a[0].pExpr;
    compRight.op = TK_LE;
    compRight.pLeft = pDel;
    compRight.pRight = pExpr->x.pList->a[1].pExpr;
    exprToRegister(pDel, exprCodeVector(pParse, pDel, &regFree1));
    if( xJump ){
      xJump(pParse, &exprAnd, dest, jumpIfNull);
    }else{
      /* Mark the expression is being from the ON or USING clause of a join
      ** so that the sqlite3ExprCodeTarget() routine will not attempt to move
      ** it into the Parse.pConstExpr list.  We should use a new bit for this,
      ** for clarity, but we are out of bits in the Expr.flags field so we
      ** have to reuse the EP_OuterON bit.  Bummer. */
      pDel->flags |= EP_OuterON;
      sqlite3ExprCodeTarget(pParse, &exprAnd, dest);
    }
    sqlite3ReleaseTempReg(pParse, regFree1);
  }
  sqlite3ExprDelete(db, pDel);

  /* Ensure adequate test coverage */
  testcase( xJump==sqlite3ExprIfTrue  && jumpIfNull==0 && regFree1==0 );
  testcase( xJump==sqlite3ExprIfTrue  && jumpIfNull==0 && regFree1!=0 );
  testcase( xJump==sqlite3ExprIfTrue  && jumpIfNull!=0 && regFree1==0 );
  testcase( xJump==sqlite3ExprIfTrue  && jumpIfNull!=0 && regFree1!=0 );
  testcase( xJump==sqlite3ExprIfFalse && jumpIfNull==0 && regFree1==0 );
4360
4361
4362
4363
4364
4365
4366

4367
4368
4369
4370
4371
4372
4373
4374












4375
4376

4377
4378
4379
4380




4381
4382
4383
4384
4385
4386
4387
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290






5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302


5303




5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314







+


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







  int regFree1 = 0;
  int regFree2 = 0;
  int r1, r2;

  assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 );
  if( NEVER(v==0) )     return;  /* Existence of VDBE checked by caller */
  if( NEVER(pExpr==0) ) return;  /* No way this can happen */
  assert( !ExprHasVVAProperty(pExpr, EP_Immutable) );
  op = pExpr->op;
  switch( op ){
    case TK_AND: {
      int d2 = sqlite3VdbeMakeLabel(v);
      testcase( jumpIfNull==0 );
      sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL);
      sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
      sqlite3VdbeResolveLabel(v, d2);
    case TK_AND:
    case TK_OR: {
      Expr *pAlt = sqlite3ExprSimplifiedAndOr(pExpr);
      if( pAlt!=pExpr ){
        sqlite3ExprIfTrue(pParse, pAlt, dest, jumpIfNull);
      }else if( op==TK_AND ){
        int d2 = sqlite3VdbeMakeLabel(pParse);
        testcase( jumpIfNull==0 );
        sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,
                           jumpIfNull^SQLITE_JUMPIFNULL);
        sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
        sqlite3VdbeResolveLabel(v, d2);
      break;
    }
      }else{
    case TK_OR: {
      testcase( jumpIfNull==0 );
      sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
      sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
        testcase( jumpIfNull==0 );
        sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
        sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
      }
      break;
    }
    case TK_NOT: {
      testcase( jumpIfNull==0 );
      sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
      break;
    }
4404
4405
4406
4407
4408
4409
4410
4411

4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423

4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442

4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456

4457
4458
4459
4460
4461
4462
4463
4464
4465
4466

4467
4468

4469
4470
4471
4472
4473
4474
4475
5331
5332
5333
5334
5335
5336
5337

5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349

5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383

5384
5385
5386
5387
5388
5389
5390
5391
5392
5393

5394
5395

5396
5397
5398
5399
5400
5401
5402
5403







-
+











-
+



















+













-
+









-
+

-
+







    }
    case TK_IS:
    case TK_ISNOT:
      testcase( op==TK_IS );
      testcase( op==TK_ISNOT );
      op = (op==TK_IS) ? TK_EQ : TK_NE;
      jumpIfNull = SQLITE_NULLEQ;
      /* Fall thru */
      /* no break */ deliberate_fall_through
    case TK_LT:
    case TK_LE:
    case TK_GT:
    case TK_GE:
    case TK_NE:
    case TK_EQ: {
      if( sqlite3ExprIsVector(pExpr->pLeft) ) goto default_expr;
      testcase( jumpIfNull==0 );
      r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
      r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
      codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
                  r1, r2, dest, jumpIfNull);
                  r1, r2, dest, jumpIfNull, 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 && jumpIfNull==SQLITE_NULLEQ);
      VdbeCoverageIf(v, op==OP_Eq && jumpIfNull!=SQLITE_NULLEQ);
      assert(TK_NE==OP_Ne); testcase(op==OP_Ne);
      VdbeCoverageIf(v, op==OP_Ne && jumpIfNull==SQLITE_NULLEQ);
      VdbeCoverageIf(v, op==OP_Ne && jumpIfNull!=SQLITE_NULLEQ);
      testcase( regFree1==0 );
      testcase( regFree2==0 );
      break;
    }
    case TK_ISNULL:
    case TK_NOTNULL: {
      assert( TK_ISNULL==OP_IsNull );   testcase( op==TK_ISNULL );
      assert( TK_NOTNULL==OP_NotNull ); testcase( op==TK_NOTNULL );
      r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
      sqlite3VdbeTypeofColumn(v, r1);
      sqlite3VdbeAddOp2(v, op, r1, dest);
      VdbeCoverageIf(v, op==TK_ISNULL);
      VdbeCoverageIf(v, op==TK_NOTNULL);
      testcase( regFree1==0 );
      break;
    }
    case TK_BETWEEN: {
      testcase( jumpIfNull==0 );
      exprCodeBetween(pParse, pExpr, dest, sqlite3ExprIfTrue, jumpIfNull);
      break;
    }
#ifndef SQLITE_OMIT_SUBQUERY
    case TK_IN: {
      int destIfFalse = sqlite3VdbeMakeLabel(v);
      int destIfFalse = sqlite3VdbeMakeLabel(pParse);
      int destIfNull = jumpIfNull ? dest : destIfFalse;
      sqlite3ExprCodeIN(pParse, pExpr, destIfFalse, destIfNull);
      sqlite3VdbeGoto(v, dest);
      sqlite3VdbeResolveLabel(v, destIfFalse);
      break;
    }
#endif
    default: {
    default_expr:
      if( exprAlwaysTrue(pExpr) ){
      if( ExprAlwaysTrue(pExpr) ){
        sqlite3VdbeGoto(v, dest);
      }else if( exprAlwaysFalse(pExpr) ){
      }else if( ExprAlwaysFalse(pExpr) ){
        /* No-op */
      }else{
        r1 = sqlite3ExprCodeTemp(pParse, pExpr, &regFree1);
        sqlite3VdbeAddOp3(v, OP_If, r1, dest, jumpIfNull!=0);
        VdbeCoverage(v);
        testcase( regFree1==0 );
        testcase( jumpIfNull==0 );
4496
4497
4498
4499
4500
4501
4502

4503
4504
4505
4506
4507
4508
4509
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438







+







  int regFree1 = 0;
  int regFree2 = 0;
  int r1, r2;

  assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 );
  if( NEVER(v==0) ) return; /* Existence of VDBE checked by caller */
  if( pExpr==0 )    return;
  assert( !ExprHasVVAProperty(pExpr,EP_Immutable) );

  /* The value of pExpr->op and op are related as follows:
  **
  **       pExpr->op            op
  **       ---------          ----------
  **       TK_ISNULL          OP_NotNull
  **       TK_NOTNULL         OP_IsNull
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539









4540
4541

4542
4543
4544
4545
4546
4547







4548
4549
4550
4551
4552
4553
4554
5458
5459
5460
5461
5462
5463
5464




5465
5466
5467
5468
5469
5470
5471
5472
5473


5474






5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488







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







  assert( pExpr->op!=TK_EQ || op==OP_Ne );
  assert( pExpr->op!=TK_LT || op==OP_Ge );
  assert( pExpr->op!=TK_LE || op==OP_Gt );
  assert( pExpr->op!=TK_GT || op==OP_Le );
  assert( pExpr->op!=TK_GE || op==OP_Lt );

  switch( pExpr->op ){
    case TK_AND: {
      testcase( jumpIfNull==0 );
      sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
      sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
    case TK_AND:
    case TK_OR: {
      Expr *pAlt = sqlite3ExprSimplifiedAndOr(pExpr);
      if( pAlt!=pExpr ){
        sqlite3ExprIfFalse(pParse, pAlt, dest, jumpIfNull);
      }else if( pExpr->op==TK_AND ){
        testcase( jumpIfNull==0 );
        sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
        sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
      break;
    }
      }else{
    case TK_OR: {
      int d2 = sqlite3VdbeMakeLabel(v);
      testcase( jumpIfNull==0 );
      sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL);
      sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
      sqlite3VdbeResolveLabel(v, d2);
        int d2 = sqlite3VdbeMakeLabel(pParse);
        testcase( jumpIfNull==0 );
        sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2,
                          jumpIfNull^SQLITE_JUMPIFNULL);
        sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
        sqlite3VdbeResolveLabel(v, d2);
      }
      break;
    }
    case TK_NOT: {
      testcase( jumpIfNull==0 );
      sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
      break;
    }
4574
4575
4576
4577
4578
4579
4580
4581

4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593

4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610

4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627

4628
4629
4630
4631
4632
4633
4634
4635
4636

4637
4638

4639
4640
4641
4642
4643
4644
4645
5508
5509
5510
5511
5512
5513
5514

5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526

5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561

5562
5563
5564
5565
5566
5567
5568
5569
5570

5571
5572

5573
5574
5575
5576
5577
5578
5579
5580







-
+











-
+

















+
















-
+








-
+

-
+







    }
    case TK_IS:
    case TK_ISNOT:
      testcase( pExpr->op==TK_IS );
      testcase( pExpr->op==TK_ISNOT );
      op = (pExpr->op==TK_IS) ? TK_NE : TK_EQ;
      jumpIfNull = SQLITE_NULLEQ;
      /* Fall thru */
      /* no break */ deliberate_fall_through
    case TK_LT:
    case TK_LE:
    case TK_GT:
    case TK_GE:
    case TK_NE:
    case TK_EQ: {
      if( sqlite3ExprIsVector(pExpr->pLeft) ) goto default_expr;
      testcase( jumpIfNull==0 );
      r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
      r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
      codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
                  r1, r2, dest, jumpIfNull);
                  r1, r2, dest, jumpIfNull,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 && jumpIfNull!=SQLITE_NULLEQ);
      VdbeCoverageIf(v, op==OP_Eq && jumpIfNull==SQLITE_NULLEQ);
      assert(TK_NE==OP_Ne); testcase(op==OP_Ne);
      VdbeCoverageIf(v, op==OP_Ne && jumpIfNull!=SQLITE_NULLEQ);
      VdbeCoverageIf(v, op==OP_Ne && jumpIfNull==SQLITE_NULLEQ);
      testcase( regFree1==0 );
      testcase( regFree2==0 );
      break;
    }
    case TK_ISNULL:
    case TK_NOTNULL: {
      r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
      sqlite3VdbeTypeofColumn(v, r1);
      sqlite3VdbeAddOp2(v, op, r1, dest);
      testcase( op==TK_ISNULL );   VdbeCoverageIf(v, op==TK_ISNULL);
      testcase( op==TK_NOTNULL );  VdbeCoverageIf(v, op==TK_NOTNULL);
      testcase( regFree1==0 );
      break;
    }
    case TK_BETWEEN: {
      testcase( jumpIfNull==0 );
      exprCodeBetween(pParse, pExpr, dest, sqlite3ExprIfFalse, jumpIfNull);
      break;
    }
#ifndef SQLITE_OMIT_SUBQUERY
    case TK_IN: {
      if( jumpIfNull ){
        sqlite3ExprCodeIN(pParse, pExpr, dest, dest);
      }else{
        int destIfNull = sqlite3VdbeMakeLabel(v);
        int destIfNull = sqlite3VdbeMakeLabel(pParse);
        sqlite3ExprCodeIN(pParse, pExpr, dest, destIfNull);
        sqlite3VdbeResolveLabel(v, destIfNull);
      }
      break;
    }
#endif
    default: {
    default_expr: 
      if( exprAlwaysFalse(pExpr) ){
      if( ExprAlwaysFalse(pExpr) ){
        sqlite3VdbeGoto(v, dest);
      }else if( exprAlwaysTrue(pExpr) ){
      }else if( ExprAlwaysTrue(pExpr) ){
        /* no-op */
      }else{
        r1 = sqlite3ExprCodeTemp(pParse, pExpr, &regFree1);
        sqlite3VdbeAddOp3(v, OP_IfNot, r1, dest, jumpIfNull!=0);
        VdbeCoverage(v);
        testcase( regFree1==0 );
        testcase( jumpIfNull==0 );
4674
4675
4676
4677
4678
4679
4680
4681





4682
4683
4684
4685
4686
4687
4688
5609
5610
5611
5612
5613
5614
5615

5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627







-
+
+
+
+
+







** to re-prepare each time a new value is bound to variable pVar.
**
** Additionally, if pExpr is a simple SQL value and the value is the
** same as that currently bound to variable pVar, non-zero is returned.
** Otherwise, if the values are not the same or if pExpr is not a simple
** SQL value, zero is returned.
*/
static int exprCompareVariable(Parse *pParse, Expr *pVar, Expr *pExpr){
static int exprCompareVariable(
  const Parse *pParse,
  const Expr *pVar,
  const Expr *pExpr
){
  int res = 0;
  int iVar;
  sqlite3_value *pL, *pR = 0;
  
  sqlite3ValueFromExpr(pParse->db, pExpr, SQLITE_UTF8, SQLITE_AFF_BLOB, &pR);
  if( pR ){
    iVar = pVar->iColumn;
4726
4727
4728
4729
4730
4731
4732
4733






4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748

4749
4750
4751
4752
4753
4754





4755
4756
4757
4758







4759
4760
4761

4762
4763
4764
4765
4766
4767
4768
4769



4770
4771
4772




4773


4774
4775




4776


4777
4778
4779
4780
4781



4782
4783
4784
4785
4786
4787
4788
4789

4790
4791

4792
4793



4794
4795
4796
4797
4798
4799
4800
4801



4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814

4815
4816
4817
4818
4819

4820
4821
4822
4823


4824
4825
4826
4827
4828
4829
4830
4831
4832

4833
4834
4835


4836
4837














































































4838
4839
4840
4841
4842
4843
4844
5665
5666
5667
5668
5669
5670
5671

5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691

5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703




5704
5705
5706
5707
5708
5709
5710
5711
5712

5713








5714
5715
5716
5717


5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730

5731
5732
5733
5734
5735


5736
5737
5738
5739
5740
5741
5742
5743
5744
5745

5746
5747
5748
5749


5750
5751
5752
5753
5754
5755
5756
5757
5758


5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773

5774
5775
5776
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
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883







-
+
+
+
+
+
+














-
+






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


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

-
-
+
+
+
+

+
+


+
+
+
+
-
+
+



-
-
+
+
+







-
+


+
-
-
+
+
+






-
-
+
+
+












-
+





+


-
-
+
+








-
+

-
-
+
+


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







** If pParse is not NULL then TK_VARIABLE terms in pA with bindings in
** pParse->pReprepare can be matched against literals in pB.  The 
** pParse->pVdbe->expmask bitmask is updated for each variable referenced.
** If pParse is NULL (the normal case) then any TK_VARIABLE term in 
** Argument pParse should normally be NULL. If it is not NULL and pA or
** pB causes a return value of 2.
*/
int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
int sqlite3ExprCompare(
  const Parse *pParse,
  const Expr *pA,
  const Expr *pB,
  int iTab
){
  u32 combinedFlags;
  if( pA==0 || pB==0 ){
    return pB==pA ? 0 : 2;
  }
  if( pParse && pA->op==TK_VARIABLE && exprCompareVariable(pParse, pA, pB) ){
    return 0;
  }
  combinedFlags = pA->flags | pB->flags;
  if( combinedFlags & EP_IntValue ){
    if( (pA->flags&pB->flags&EP_IntValue)!=0 && pA->u.iValue==pB->u.iValue ){
      return 0;
    }
    return 2;
  }
  if( pA->op!=pB->op ){
  if( pA->op!=pB->op || pA->op==TK_RAISE ){
    if( pA->op==TK_COLLATE && sqlite3ExprCompare(pParse, pA->pLeft,pB,iTab)<2 ){
      return 1;
    }
    if( pB->op==TK_COLLATE && sqlite3ExprCompare(pParse, pA,pB->pLeft,iTab)<2 ){
      return 1;
    }
    if( pA->op==TK_AGG_COLUMN && pB->op==TK_COLUMN 
     && pB->iTable<0 && pA->iTable==iTab
    ){
      /* fall through */
    }else{
    return 2;
  }
  if( pA->op!=TK_COLUMN && pA->op!=TK_AGG_COLUMN && pA->u.zToken ){
    if( pA->op==TK_FUNCTION ){
      return 2;
    }
  }
  assert( !ExprHasProperty(pA, EP_IntValue) );
  assert( !ExprHasProperty(pB, EP_IntValue) );
  if( pA->u.zToken ){
    if( pA->op==TK_FUNCTION || pA->op==TK_AGG_FUNCTION ){
      if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2;
#ifndef SQLITE_OMIT_WINDOWFUNC
      /* Justification for the assert():
      assert( pA->op==pB->op );
      ** window functions have p->op==TK_FUNCTION but aggregate functions
      ** have p->op==TK_AGG_FUNCTION.  So any comparison between an aggregate
      ** function and a window function should have failed before reaching
      ** this point.  And, it is not possible to have a window function and
      ** a scalar function with the same name and number of arguments.  So
      ** if we reach this point, either A and B both window functions or
      ** neither are a window functions. */
      assert( ExprHasProperty(pA,EP_WinFunc)==ExprHasProperty(pB,EP_WinFunc) );
      if( ExprHasProperty(pA,EP_WinFunc)!=ExprHasProperty(pB,EP_WinFunc) ){
        return 2;
      }
      if( ExprHasProperty(pA,EP_WinFunc) ){
        if( sqlite3WindowCompare(pParse,pA->y.pWin,pB->y.pWin)!=0 ) return 2;
      }
        if( sqlite3WindowCompare(pParse, pA->y.pWin, pB->y.pWin, 1)!=0 ){
          return 2;
        }
      }
#endif
    }else if( pA->op==TK_NULL ){
      return 0;
    }else if( pA->op==TK_COLLATE ){
      if( sqlite3_stricmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2;
    }else 
    if( pB->u.zToken!=0
     && pA->op!=TK_COLUMN
     && pA->op!=TK_AGG_COLUMN
    }else if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){
     && strcmp(pA->u.zToken,pB->u.zToken)!=0
    ){
      return 2;
    }
  }
  if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
  if( (combinedFlags & EP_TokenOnly)==0 ){
  if( (pA->flags & (EP_Distinct|EP_Commuted))
     != (pB->flags & (EP_Distinct|EP_Commuted)) ) return 2;
  if( ALWAYS((combinedFlags & EP_TokenOnly)==0) ){
    if( combinedFlags & EP_xIsSelect ) return 2;
    if( (combinedFlags & EP_FixedCol)==0
     && sqlite3ExprCompare(pParse, pA->pLeft, pB->pLeft, iTab) ) return 2;
    if( sqlite3ExprCompare(pParse, pA->pRight, pB->pRight, iTab) ) return 2;
    if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
    if( pA->op!=TK_STRING
     && pA->op!=TK_TRUEFALSE
     && (combinedFlags & EP_Reduced)==0
     && ALWAYS((combinedFlags & EP_Reduced)==0)
    ){
      if( pA->iColumn!=pB->iColumn ) return 2;
      if( pA->op2!=pB->op2 && pA->op==TK_TRUTH ) return 2;
      if( pA->iTable!=pB->iTable 
       && (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2;
      if( pA->op!=TK_IN && pA->iTable!=pB->iTable && pA->iTable!=iTab ){
        return 2;
      }
    }
  }
  return 0;
}

/*
** Compare two ExprList objects.  Return 0 if they are identical and 
** non-zero if they differ in any way.
** Compare two ExprList objects.  Return 0 if they are identical, 1
** if they are certainly different, or 2 if it is not possible to 
** determine if they are identical or not.
**
** If any subelement of pB has Expr.iTable==(-1) then it is allowed
** to compare equal to an equivalent element in pA with Expr.iTable==iTab.
**
** This routine might return non-zero for equivalent ExprLists.  The
** only consequence will be disabled optimizations.  But this routine
** must never return 0 if the two ExprList objects are different, or
** a malfunction will result.
**
** Two NULL pointers are considered to be the same.  But a NULL pointer
** always differs from a non-NULL pointer.
*/
int sqlite3ExprListCompare(ExprList *pA, ExprList *pB, int iTab){
int sqlite3ExprListCompare(const ExprList *pA, const ExprList *pB, int iTab){
  int i;
  if( pA==0 && pB==0 ) return 0;
  if( pA==0 || pB==0 ) return 1;
  if( pA->nExpr!=pB->nExpr ) return 1;
  for(i=0; i<pA->nExpr; i++){
    int res;
    Expr *pExprA = pA->a[i].pExpr;
    Expr *pExprB = pB->a[i].pExpr;
    if( pA->a[i].sortOrder!=pB->a[i].sortOrder ) return 1;
    if( sqlite3ExprCompare(0, pExprA, pExprB, iTab) ) return 1;
    if( pA->a[i].fg.sortFlags!=pB->a[i].fg.sortFlags ) return 1;
    if( (res = sqlite3ExprCompare(0, pExprA, pExprB, iTab)) ) return res;
  }
  return 0;
}

/*
** Like sqlite3ExprCompare() except COLLATE operators at the top-level
** are ignored.
*/
int sqlite3ExprCompareSkip(Expr *pA, Expr *pB, int iTab){
int sqlite3ExprCompareSkip(Expr *pA,Expr *pB, int iTab){
  return sqlite3ExprCompare(0,
             sqlite3ExprSkipCollate(pA),
             sqlite3ExprSkipCollate(pB),
             sqlite3ExprSkipCollateAndLikely(pA),
             sqlite3ExprSkipCollateAndLikely(pB),
             iTab);
}

/*
** Return non-zero if Expr p can only be true if pNN is not NULL.
**
** Or if seenNot is true, return non-zero if Expr p can only be
** non-NULL if pNN is not NULL
*/
static int exprImpliesNotNull(
  const Parse *pParse,/* Parsing context */
  const Expr *p,      /* The expression to be checked */
  const Expr *pNN,    /* The expression that is NOT NULL */
  int iTab,           /* Table being evaluated */
  int seenNot         /* Return true only if p can be any non-NULL value */
){
  assert( p );
  assert( pNN );
  if( sqlite3ExprCompare(pParse, p, pNN, iTab)==0 ){
    return pNN->op!=TK_NULL;
  }
  switch( p->op ){
    case TK_IN: {
      if( seenNot && ExprHasProperty(p, EP_xIsSelect) ) return 0;
      assert( ExprUseXSelect(p) || (p->x.pList!=0 && p->x.pList->nExpr>0) );
      return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1);
    }
    case TK_BETWEEN: {
      ExprList *pList;
      assert( ExprUseXList(p) );
      pList = p->x.pList;
      assert( pList!=0 );
      assert( pList->nExpr==2 );
      if( seenNot ) return 0;
      if( exprImpliesNotNull(pParse, pList->a[0].pExpr, pNN, iTab, 1)
       || exprImpliesNotNull(pParse, pList->a[1].pExpr, pNN, iTab, 1)
      ){
        return 1;
      }
      return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1);
    }
    case TK_EQ:
    case TK_NE:
    case TK_LT:
    case TK_LE:
    case TK_GT:
    case TK_GE:
    case TK_PLUS:
    case TK_MINUS:
    case TK_BITOR:
    case TK_LSHIFT:
    case TK_RSHIFT: 
    case TK_CONCAT: 
      seenNot = 1;
      /* no break */ deliberate_fall_through
    case TK_STAR:
    case TK_REM:
    case TK_BITAND:
    case TK_SLASH: {
      if( exprImpliesNotNull(pParse, p->pRight, pNN, iTab, seenNot) ) return 1;
      /* no break */ deliberate_fall_through
    }
    case TK_SPAN:
    case TK_COLLATE:
    case TK_UPLUS:
    case TK_UMINUS: {
      return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, seenNot);
    }
    case TK_TRUTH: {
      if( seenNot ) return 0;
      if( p->op2!=TK_IS ) return 0;
      return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1);
    }
    case TK_BITNOT:
    case TK_NOT: {
      return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1);
    }
  }
  return 0;
}

/*
** Return true if we can prove the pE2 will always be true if pE1 is
** true.  Return false if we cannot complete the proof or if pE2 might
** be false.  Examples:
**
**     pE1: x==5       pE2: x==5             Result: true
4857
4858
4859
4860
4861
4862
4863
4864






4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877




4878
4879
4880
4881
4882
4883

4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894

4895
4896
4897
4898


4899
4900

4901
4902
4903

4904
4905
4906


4907
4908

4909
4910
4911

4912
4913
4914
4915
4916
4917
4918
4919

















4920
4921
4922
4923
4924
4925
4926
4927
4928



4929
4930
4931
4932
4933
4934




4935
4936






4937
4938

4939


4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959


4960
4961
4962
4963
4964
4965
4966
4967
4968










4969
4970
4971
4972
4973
4974
4975
5896
5897
5898
5899
5900
5901
5902

5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917




5918
5919
5920
5921
5922
5923
5924
5925
5926

5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937

5938
5939
5940


5941
5942
5943
5944
5945
5946
5947
5948
5949
5950


5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992

5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005


6006
6007
6008
6009
6010
6011
6012

6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034


6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062







-
+
+
+
+
+
+









-
-
-
-
+
+
+
+





-
+










-
+


-
-
+
+


+



+

-
-
+
+


+



+








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








-
+
+
+






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

-
+

+
+


















-
-
+
+









+
+
+
+
+
+
+
+
+
+







** modified to record which bound variables are referenced.  If pParse 
** is NULL, then false will be returned if pE1 contains any bound variables.
**
** When in doubt, return false.  Returning true might give a performance
** improvement.  Returning false might cause a performance reduction, but
** it will always give the correct answer and is hence always safe.
*/
int sqlite3ExprImpliesExpr(Parse *pParse, Expr *pE1, Expr *pE2, int iTab){
int sqlite3ExprImpliesExpr(
  const Parse *pParse,
  const Expr *pE1,
  const Expr *pE2,
  int iTab
){
  if( sqlite3ExprCompare(pParse, pE1, pE2, iTab)==0 ){
    return 1;
  }
  if( pE2->op==TK_OR
   && (sqlite3ExprImpliesExpr(pParse, pE1, pE2->pLeft, iTab)
             || sqlite3ExprImpliesExpr(pParse, pE1, pE2->pRight, iTab) )
  ){
    return 1;
  }
  if( pE2->op==TK_NOTNULL && pE1->op!=TK_ISNULL && pE1->op!=TK_IS ){
    Expr *pX = sqlite3ExprSkipCollate(pE1->pLeft);
    testcase( pX!=pE1->pLeft );
    if( sqlite3ExprCompare(pParse, pX, pE2->pLeft, iTab)==0 ) return 1;
  if( pE2->op==TK_NOTNULL
   && exprImpliesNotNull(pParse, pE1, pE2->pLeft, iTab, 0)
  ){
    return 1;
  }
  return 0;
}

/*
** This is the Expr node callback for sqlite3ExprImpliesNotNullRow().
** This is the Expr node callback for sqlite3ExprImpliesNonNullRow().
** If the expression node requires that the table at pWalker->iCur
** have one or more non-NULL column, then set pWalker->eCode to 1 and abort.
**
** This routine controls an optimization.  False positives (setting
** pWalker->eCode to 1 when it should not be) are deadly, but false-negatives
** (never setting pWalker->eCode) is a harmless missed optimization.
*/
static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
  testcase( pExpr->op==TK_AGG_COLUMN );
  testcase( pExpr->op==TK_AGG_FUNCTION );
  if( ExprHasProperty(pExpr, EP_FromJoin) ) return WRC_Prune;
  if( ExprHasProperty(pExpr, EP_OuterON) ) return WRC_Prune;
  switch( pExpr->op ){
    case TK_ISNOT:
    case TK_NOT:
    case TK_ISNULL:
    case TK_ISNULL:
    case TK_NOTNULL:
    case TK_IS:
    case TK_OR:
    case TK_VECTOR:
    case TK_CASE:
    case TK_IN:
    case TK_FUNCTION:
    case TK_TRUTH:
      testcase( pExpr->op==TK_ISNOT );
      testcase( pExpr->op==TK_NOT );
      testcase( pExpr->op==TK_ISNULL );
      testcase( pExpr->op==TK_ISNULL );
      testcase( pExpr->op==TK_NOTNULL );
      testcase( pExpr->op==TK_IS );
      testcase( pExpr->op==TK_OR );
      testcase( pExpr->op==TK_VECTOR );
      testcase( pExpr->op==TK_CASE );
      testcase( pExpr->op==TK_IN );
      testcase( pExpr->op==TK_FUNCTION );
      testcase( pExpr->op==TK_TRUTH );
      return WRC_Prune;
    case TK_COLUMN:
      if( pWalker->u.iCur==pExpr->iTable ){
        pWalker->eCode = 1;
        return WRC_Abort;
      }
      return WRC_Prune;

    case TK_AND:
      if( pWalker->eCode==0 ){
        sqlite3WalkExpr(pWalker, pExpr->pLeft);
        if( pWalker->eCode ){
          pWalker->eCode = 0;
          sqlite3WalkExpr(pWalker, pExpr->pRight);
        }
      }
      return WRC_Prune;

    case TK_BETWEEN:
      if( sqlite3WalkExpr(pWalker, pExpr->pLeft)==WRC_Abort ){
        assert( pWalker->eCode );
        return WRC_Abort;
      }
      return WRC_Prune;

    /* Virtual tables are allowed to use constraints like x=NULL.  So
    ** a term of the form x=y does not prove that y is not null if x
    ** is the column of a virtual table */
    case TK_EQ:
    case TK_NE:
    case TK_LT:
    case TK_LE:
    case TK_GT:
    case TK_GE:
    case TK_GE: {
      Expr *pLeft = pExpr->pLeft;
      Expr *pRight = pExpr->pRight;
      testcase( pExpr->op==TK_EQ );
      testcase( pExpr->op==TK_NE );
      testcase( pExpr->op==TK_LT );
      testcase( pExpr->op==TK_LE );
      testcase( pExpr->op==TK_GT );
      testcase( pExpr->op==TK_GE );
      /* The y.pTab=0 assignment in wherecode.c always happens after the
      ** impliesNotNullRow() test */
      assert( pLeft->op!=TK_COLUMN || ExprUseYTab(pLeft) );
      assert( pRight->op!=TK_COLUMN || ExprUseYTab(pRight) );
      if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->y.pTab))
       || (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->y.pTab))
      if( (pLeft->op==TK_COLUMN
           && ALWAYS(pLeft->y.pTab!=0)
           && IsVirtual(pLeft->y.pTab))
       || (pRight->op==TK_COLUMN
           && ALWAYS(pRight->y.pTab!=0)
           && IsVirtual(pRight->y.pTab))
      ){
       return WRC_Prune;
        return WRC_Prune;
      }
      /* no break */ deliberate_fall_through
    }
    default:
      return WRC_Continue;
  }
}

/*
** Return true (non-zero) if expression p can only be true if at least
** one column of table iTab is non-null.  In other words, return true
** if expression p will always be NULL or false if every column of iTab
** is NULL.
**
** False negatives are acceptable.  In other words, it is ok to return
** zero even if expression p will never be true of every column of iTab
** is NULL.  A false negative is merely a missed optimization opportunity.
**
** False positives are not allowed, however.  A false positive may result
** in an incorrect answer.
**
** Terms of p that are marked with EP_FromJoin (and hence that come from
** the ON or USING clauses of LEFT JOINS) are excluded from the analysis.
** Terms of p that are marked with EP_OuterON (and hence that come from
** the ON or USING clauses of OUTER JOINS) are excluded from the analysis.
**
** This routine is used to check if a LEFT JOIN can be converted into
** an ordinary JOIN.  The p argument is the WHERE clause.  If the WHERE
** clause requires that some column of the right table of the LEFT JOIN
** be non-NULL, then the LEFT JOIN can be safely converted into an
** ordinary join.
*/
int sqlite3ExprImpliesNonNullRow(Expr *p, int iTab){
  Walker w;
  p = sqlite3ExprSkipCollateAndLikely(p);
  if( p==0 ) return 0;
  if( p->op==TK_NOTNULL ){
    p = p->pLeft;
  }else{
    while( p->op==TK_AND ){
      if( sqlite3ExprImpliesNonNullRow(p->pLeft, iTab) ) return 1;
      p = p->pRight;
    }
  }
  w.xExprCallback = impliesNotNullRow;
  w.xSelectCallback = 0;
  w.xSelectCallback2 = 0;
  w.eCode = 0;
  w.u.iCur = iTab;
  sqlite3WalkExpr(&w, p);
  return w.eCode;
4991
4992
4993
4994
4995
4996
4997
4998

4999
5000
5001
5002
5003
5004
5005
6078
6079
6080
6081
6082
6083
6084

6085
6086
6087
6088
6089
6090
6091
6092







-
+







** Check to see if there are references to columns in table 
** pWalker->u.pIdxCover->iCur can be satisfied using the index
** pWalker->u.pIdxCover->pIdx.
*/
static int exprIdxCover(Walker *pWalker, Expr *pExpr){
  if( pExpr->op==TK_COLUMN
   && pExpr->iTable==pWalker->u.pIdxCover->iCur
   && sqlite3ColumnOfIndex(pWalker->u.pIdxCover->pIdx, pExpr->iColumn)<0
   && sqlite3TableColumnToIndex(pWalker->u.pIdxCover->pIdx, pExpr->iColumn)<0
  ){
    pWalker->eCode = 1;
    return WRC_Abort;
  }
  return WRC_Continue;
}

5026
5027
5028
5029
5030
5031
5032
5033
5034

5035
5036

5037
5038
5039
5040
5041
5042





5043
5044
5045



































5046








5047
5048

5049
5050
5051
5052
5053
5054



5055
5056
5057


5058
5059
5060








5061



5062
5063
5064
5065




















































































5066
5067
5068
5069
5070
5071
5072
5073


5074
5075
5076
5077
5078


5079
5080
5081
5082



5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
6113
6114
6115
6116
6117
6118
6119


6120


6121

6122




6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165

6166
6167
6168
6169
6170
6171
6172
6173
6174

6175






6176
6177
6178
6179


6180
6181
6182
6183

6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195




6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285


6286
6287


6288


6289
6290




6291
6292
6293






6294
6295
6296
6297
6298
6299
6300







-
-
+
-
-
+
-

-
-
-
-
+
+
+
+
+



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

-
+
-
-
-
-
-
-
+
+
+

-
-
+
+


-
+
+
+
+
+
+
+
+

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






-
-
+
+
-
-

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







  w.xExprCallback = exprIdxCover;
  w.u.pIdxCover = &xcov;
  sqlite3WalkExpr(&w, pExpr);
  return !w.eCode;
}


/*
** An instance of the following structure is used by the tree walker
/* Structure used to pass information throught the Walker in order to
** to count references to table columns in the arguments of an 
** aggregate function, in order to implement the
** implement sqlite3ReferencesSrcList().
** sqlite3FunctionThisSrc() routine.
*/
struct SrcCount {
  SrcList *pSrc;   /* One particular FROM clause in a nested query */
  int nThis;       /* Number of references to columns in pSrcList */
  int nOther;      /* Number of references to columns in other FROM clauses */
struct RefSrcList {
  sqlite3 *db;         /* Database connection used for sqlite3DbRealloc() */
  SrcList *pRef;       /* Looking for references to these tables */
  i64 nExclude;        /* Number of tables to exclude from the search */
  int *aiExclude;      /* Cursor IDs for tables to exclude from the search */
};

/*
** Walker SELECT callbacks for sqlite3ReferencesSrcList().
**
** When entering a new subquery on the pExpr argument, add all FROM clause
** entries for that subquery to the exclude list.
**
** When leaving the subquery, remove those entries from the exclude list.
*/
static int selectRefEnter(Walker *pWalker, Select *pSelect){
  struct RefSrcList *p = pWalker->u.pRefSrcList;
  SrcList *pSrc = pSelect->pSrc;
  i64 i, j;
  int *piNew;
  if( pSrc->nSrc==0 ) return WRC_Continue;
  j = p->nExclude;
  p->nExclude += pSrc->nSrc;
  piNew = sqlite3DbRealloc(p->db, p->aiExclude, p->nExclude*sizeof(int));
  if( piNew==0 ){
    p->nExclude = 0;
    return WRC_Abort;
  }else{
    p->aiExclude = piNew;
  }
  for(i=0; i<pSrc->nSrc; i++, j++){
     p->aiExclude[j] = pSrc->a[i].iCursor;
  }
  return WRC_Continue;
}
static void selectRefLeave(Walker *pWalker, Select *pSelect){
  struct RefSrcList *p = pWalker->u.pRefSrcList;
  SrcList *pSrc = pSelect->pSrc;
  if( p->nExclude ){
    assert( p->nExclude>=pSrc->nSrc );
    p->nExclude -= pSrc->nSrc;
  }
}
** Count the number of references to columns.

/* This is the Walker EXPR callback for sqlite3ReferencesSrcList().
** 
** Set the 0x01 bit of pWalker->eCode if there is a reference to any
** of the tables shown in RefSrcList.pRef.
**
** Set the 0x02 bit of pWalker->eCode if there is a reference to a
** table is in neither RefSrcList.pRef nor RefSrcList.aiExclude.
*/
static int exprSrcCount(Walker *pWalker, Expr *pExpr){
static int exprRefToSrcList(Walker *pWalker, Expr *pExpr){
  /* The NEVER() on the second term is because sqlite3FunctionUsesThisSrc()
  ** is always called before sqlite3ExprAnalyzeAggregates() and so the
  ** TK_COLUMNs have not yet been converted into TK_AGG_COLUMN.  If
  ** sqlite3FunctionUsesThisSrc() is used differently in the future, the
  ** NEVER() will need to be removed. */
  if( pExpr->op==TK_COLUMN || NEVER(pExpr->op==TK_AGG_COLUMN) ){
  if( pExpr->op==TK_COLUMN
   || pExpr->op==TK_AGG_COLUMN
  ){
    int i;
    struct SrcCount *p = pWalker->u.pSrcCount;
    SrcList *pSrc = p->pSrc;
    struct RefSrcList *p = pWalker->u.pRefSrcList;
    SrcList *pSrc = p->pRef;
    int nSrc = pSrc ? pSrc->nSrc : 0;
    for(i=0; i<nSrc; i++){
      if( pExpr->iTable==pSrc->a[i].iCursor ) break;
      if( pExpr->iTable==pSrc->a[i].iCursor ){
        pWalker->eCode |= 1;
        return WRC_Continue;
      }
    }
    for(i=0; i<p->nExclude && p->aiExclude[i]!=pExpr->iTable; i++){}
    if( i>=p->nExclude ){
      pWalker->eCode |= 2;
    }
  }
  return WRC_Continue;
}
    if( i<nSrc ){
      p->nThis++;
    }else{
      p->nOther++;

/*
** Check to see if pExpr references any tables in pSrcList.
** Possible return values:
**
**    1         pExpr does references a table in pSrcList.
**
**    0         pExpr references some table that is not defined in either
**              pSrcList or in subqueries of pExpr itself.
**
**   -1         pExpr only references no tables at all, or it only
**              references tables defined in subqueries of pExpr itself.
**
** As currently used, pExpr is always an aggregate function call.  That
** fact is exploited for efficiency.
*/
int sqlite3ReferencesSrcList(Parse *pParse, Expr *pExpr, SrcList *pSrcList){
  Walker w;
  struct RefSrcList x;
  assert( pParse->db!=0 );
  memset(&w, 0, sizeof(w));
  memset(&x, 0, sizeof(x));
  w.xExprCallback = exprRefToSrcList;
  w.xSelectCallback = selectRefEnter;
  w.xSelectCallback2 = selectRefLeave;
  w.u.pRefSrcList = &x;
  x.db = pParse->db;
  x.pRef = pSrcList;
  assert( pExpr->op==TK_AGG_FUNCTION );
  assert( ExprUseXList(pExpr) );
  sqlite3WalkExprList(&w, pExpr->x.pList);
#ifndef SQLITE_OMIT_WINDOWFUNC
  if( ExprHasProperty(pExpr, EP_WinFunc) ){
    sqlite3WalkExpr(&w, pExpr->y.pWin->pFilter);
  }
#endif
  if( x.aiExclude ) sqlite3DbNNFreeNN(pParse->db, x.aiExclude);
  if( w.eCode & 0x01 ){
    return 1;
  }else if( w.eCode ){
    return 0;
  }else{
    return -1;
  }
}

/*
** This is a Walker expression node callback.
**
** For Expr nodes that contain pAggInfo pointers, make sure the AggInfo
** object that is referenced does not refer directly to the Expr.  If
** it does, make a copy.  This is done because the pExpr argument is
** subject to change.
**
** The copy is scheduled for deletion using the sqlite3ExprDeferredDelete()
** which builds on the sqlite3ParserAddCleanup() mechanism.
*/
static int agginfoPersistExprCb(Walker *pWalker, Expr *pExpr){
  if( ALWAYS(!ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced))
   && pExpr->pAggInfo!=0
  ){
    AggInfo *pAggInfo = pExpr->pAggInfo;
    int iAgg = pExpr->iAgg;
    Parse *pParse = pWalker->pParse;
    sqlite3 *db = pParse->db;
    if( pExpr->op!=TK_AGG_FUNCTION ){
      assert( iAgg>=0 && iAgg<pAggInfo->nColumn );
      if( pAggInfo->aCol[iAgg].pCExpr==pExpr ){
        pExpr = sqlite3ExprDup(db, pExpr, 0);
        if( pExpr ){
          pAggInfo->aCol[iAgg].pCExpr = pExpr;
          sqlite3ExprDeferredDelete(pParse, pExpr);
        }
      }
    }else{
      assert( pExpr->op==TK_AGG_FUNCTION );
      assert( iAgg>=0 && iAgg<pAggInfo->nFunc );
      if( pAggInfo->aFunc[iAgg].pFExpr==pExpr ){
        pExpr = sqlite3ExprDup(db, pExpr, 0);
        if( pExpr ){
          pAggInfo->aFunc[iAgg].pFExpr = pExpr;
          sqlite3ExprDeferredDelete(pParse, pExpr);
        }
      }
    }
  }
  return WRC_Continue;
}

/*
** Determine if any of the arguments to the pExpr Function reference
** pSrcList.  Return true if they do.  Also return true if the function
** Initialize a Walker object so that will persist AggInfo entries referenced
** by the tree that is walked.
** has no arguments or has only constant arguments.  Return false if pExpr
** references columns but not columns of tables found in pSrcList.
*/
int sqlite3FunctionUsesThisSrc(Expr *pExpr, SrcList *pSrcList){
  Walker w;
void sqlite3AggInfoPersistWalkerInit(Walker *pWalker, Parse *pParse){
  memset(pWalker, 0, sizeof(*pWalker));
  struct SrcCount cnt;
  assert( pExpr->op==TK_AGG_FUNCTION );
  w.xExprCallback = exprSrcCount;
  w.xSelectCallback = 0;
  pWalker->pParse = pParse;
  pWalker->xExprCallback = agginfoPersistExprCb;
  pWalker->xSelectCallback = sqlite3SelectWalkNoop;
  w.u.pSrcCount = &cnt;
  cnt.pSrc = pSrcList;
  cnt.nThis = 0;
  cnt.nOther = 0;
  sqlite3WalkExprList(&w, pExpr->x.pList);
  return cnt.nThis>0 || cnt.nOther==0;
}

/*
** Add a new element to the pAggInfo->aCol[] array.  Return the index of
** the new element.  Return a negative number if malloc fails.
*/
static int addAggInfoColumn(sqlite3 *db, AggInfo *pInfo){
5114
5115
5116
5117
5118
5119
5120
5121




































































5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135

5136






























5137
5138
5139
5140

5141
5142
5143
5144

5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164

5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214

5215

5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227

5228
5229

5230
5231
5232
5233
5234
5235
5236
6319
6320
6321
6322
6323
6324
6325

6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447

6448
6449

6450
6451
















6452



































6453
6454
6455
6456
6457
6458
6459
6460
6461
6462
6463
6464
6465
6466
6467
6468

6469
6470
6471
6472
6473
6474
6475
6476
6477
6478
6479
6480

6481


6482
6483
6484
6485
6486
6487
6488
6489







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














+

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




+



-
+

-


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















+
-
+











-
+
-
-
+







       db, 
       pInfo->aFunc,
       sizeof(pInfo->aFunc[0]),
       &pInfo->nFunc,
       &i
  );
  return i;
}    
}

/*
** Search the AggInfo object for an aCol[] entry that has iTable and iColumn.
** Return the index in aCol[] of the entry that describes that column. 
**
** If no prior entry is found, create a new one and return -1.  The
** new column will have an idex of pAggInfo->nColumn-1.
*/
static void findOrCreateAggInfoColumn(
  Parse *pParse,       /* Parsing context */
  AggInfo *pAggInfo,   /* The AggInfo object to search and/or modify */
  Expr *pExpr          /* Expr describing the column to find or insert */
){
  struct AggInfo_col *pCol;
  int k;

  assert( pAggInfo->iFirstReg==0 );
  pCol = pAggInfo->aCol;
  for(k=0; k<pAggInfo->nColumn; k++, pCol++){
    if( pCol->iTable==pExpr->iTable
     && pCol->iColumn==pExpr->iColumn
     && pExpr->op!=TK_IF_NULL_ROW
    ){
      goto fix_up_expr;
    }
  }
  k = addAggInfoColumn(pParse->db, pAggInfo);
  if( k<0 ){
    /* OOM on resize */
    assert( pParse->db->mallocFailed );
    return;
  }
  pCol = &pAggInfo->aCol[k];
  assert( ExprUseYTab(pExpr) );
  pCol->pTab = pExpr->y.pTab;
  pCol->iTable = pExpr->iTable;
  pCol->iColumn = pExpr->iColumn;
  pCol->iSorterColumn = -1;
  pCol->pCExpr = pExpr;
  if( pAggInfo->pGroupBy && pExpr->op!=TK_IF_NULL_ROW ){
    int j, n;
    ExprList *pGB = pAggInfo->pGroupBy;
    struct ExprList_item *pTerm = pGB->a;
    n = pGB->nExpr;
    for(j=0; j<n; j++, pTerm++){
      Expr *pE = pTerm->pExpr;
      if( pE->op==TK_COLUMN
       && pE->iTable==pExpr->iTable
       && pE->iColumn==pExpr->iColumn
      ){
        pCol->iSorterColumn = j;
        break;
      }
    }
  }
  if( pCol->iSorterColumn<0 ){
    pCol->iSorterColumn = pAggInfo->nSortingColumn++;
  }
fix_up_expr:
  ExprSetVVAProperty(pExpr, EP_NoReduce);
  assert( pExpr->pAggInfo==0 || pExpr->pAggInfo==pAggInfo );
  pExpr->pAggInfo = pAggInfo;
  if( pExpr->op==TK_COLUMN ){
    pExpr->op = TK_AGG_COLUMN;
  }
  pExpr->iAgg = (i16)k;
}

/*
** This is the xExprCallback for a tree walker.  It is used to
** implement sqlite3ExprAnalyzeAggregates().  See sqlite3ExprAnalyzeAggregates
** for additional information.
*/
static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
  int i;
  NameContext *pNC = pWalker->u.pNC;
  Parse *pParse = pNC->pParse;
  SrcList *pSrcList = pNC->pSrcList;
  AggInfo *pAggInfo = pNC->uNC.pAggInfo;

  assert( pNC->ncFlags & NC_UAggInfo );
  assert( pAggInfo->iFirstReg==0 );
  switch( pExpr->op ){
    default: {
      IndexedExpr *pIEpr;
      Expr tmp;
      assert( pParse->iSelfTab==0 );
      if( (pNC->ncFlags & NC_InAggFunc)==0 ) break;
      if( pParse->pIdxEpr==0 ) break;
      for(pIEpr=pParse->pIdxEpr; pIEpr; pIEpr=pIEpr->pIENext){
        int iDataCur = pIEpr->iDataCur;
        if( iDataCur<0 ) continue;
        if( sqlite3ExprCompare(0, pExpr, pIEpr->pExpr, iDataCur)==0 ) break;
      }
      if( pIEpr==0 ) break;
      if( NEVER(!ExprUseYTab(pExpr)) ) break;
      if( pExpr->pAggInfo!=0 ) break; /* Already resolved by outer context */

      /* If we reach this point, it means that expression pExpr can be
      ** translated into a reference to an index column as described by
      ** pIEpr.
      */
      memset(&tmp, 0, sizeof(tmp));
      tmp.op = TK_AGG_COLUMN;
      tmp.iTable = pIEpr->iIdxCur;
      tmp.iColumn = pIEpr->iIdxCol;
      findOrCreateAggInfoColumn(pParse, pAggInfo, &tmp);
      pAggInfo->aCol[tmp.iAgg].pCExpr = pExpr;
      pExpr->pAggInfo = pAggInfo;
      pExpr->iAgg = tmp.iAgg;
      return WRC_Prune;
    }
    case TK_IF_NULL_ROW:
    case TK_AGG_COLUMN:
    case TK_COLUMN: {
      testcase( pExpr->op==TK_AGG_COLUMN );
      testcase( pExpr->op==TK_COLUMN );
      testcase( pExpr->op==TK_IF_NULL_ROW );
      /* Check to see if the column is in one of the tables in the FROM
      ** clause of the aggregate query */
      if( ALWAYS(pSrcList!=0) ){
        struct SrcList_item *pItem = pSrcList->a;
        SrcItem *pItem = pSrcList->a;
        for(i=0; i<pSrcList->nSrc; i++, pItem++){
          struct AggInfo_col *pCol;
          assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
          if( pExpr->iTable==pItem->iCursor ){
            /* If we reach this point, it means that pExpr refers to a table
            ** that is in the FROM clause of the aggregate query.  
            **
            ** Make an entry for the column in pAggInfo->aCol[] if there
            ** is not an entry there already.
            */
            int k;
            pCol = pAggInfo->aCol;
            for(k=0; k<pAggInfo->nColumn; k++, pCol++){
              if( pCol->iTable==pExpr->iTable &&
                  pCol->iColumn==pExpr->iColumn ){
                break;
              }
            }
            if( (k>=pAggInfo->nColumn)
             && (k = addAggInfoColumn(pParse->db, pAggInfo))>=0 
            findOrCreateAggInfoColumn(pParse, pAggInfo, pExpr);
            ){
              pCol = &pAggInfo->aCol[k];
              pCol->pTab = pExpr->y.pTab;
              pCol->iTable = pExpr->iTable;
              pCol->iColumn = pExpr->iColumn;
              pCol->iMem = ++pParse->nMem;
              pCol->iSorterColumn = -1;
              pCol->pExpr = pExpr;
              if( pAggInfo->pGroupBy ){
                int j, n;
                ExprList *pGB = pAggInfo->pGroupBy;
                struct ExprList_item *pTerm = pGB->a;
                n = pGB->nExpr;
                for(j=0; j<n; j++, pTerm++){
                  Expr *pE = pTerm->pExpr;
                  if( pE->op==TK_COLUMN && pE->iTable==pExpr->iTable &&
                      pE->iColumn==pExpr->iColumn ){
                    pCol->iSorterColumn = j;
                    break;
                  }
                }
              }
              if( pCol->iSorterColumn<0 ){
                pCol->iSorterColumn = pAggInfo->nSortingColumn++;
              }
            }
            /* There is now an entry for pExpr in pAggInfo->aCol[] (either
            ** because it was there before or because we just created it).
            ** Convert the pExpr to be a TK_AGG_COLUMN referring to that
            ** pAggInfo->aCol[] entry.
            */
            ExprSetVVAProperty(pExpr, EP_NoReduce);
            pExpr->pAggInfo = pAggInfo;
            pExpr->op = TK_AGG_COLUMN;
            pExpr->iAgg = (i16)k;
            break;
          } /* endif pExpr->iTable==pItem->iCursor */
        } /* end loop over pSrcList */
      }
      return WRC_Prune;
    }
    case TK_AGG_FUNCTION: {
      if( (pNC->ncFlags & NC_InAggFunc)==0
       && pWalker->walkerDepth==pExpr->op2
      ){
        /* Check to see if pExpr is a duplicate of another aggregate 
        ** function that is already in the pAggInfo structure
        */
        struct AggInfo_func *pItem = pAggInfo->aFunc;
        for(i=0; i<pAggInfo->nFunc; i++, pItem++){
          if( pItem->pFExpr==pExpr ) break;
          if( sqlite3ExprCompare(0, pItem->pExpr, pExpr, -1)==0 ){
          if( sqlite3ExprCompare(0, pItem->pFExpr, pExpr, -1)==0 ){
            break;
          }
        }
        if( i>=pAggInfo->nFunc ){
          /* pExpr is original.  Make a new entry in pAggInfo->aFunc[]
          */
          u8 enc = ENC(pParse->db);
          i = addAggInfoFunc(pParse->db, pAggInfo);
          if( i>=0 ){
            assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
            pItem = &pAggInfo->aFunc[i];
            pItem->pExpr = pExpr;
            pItem->pFExpr = pExpr;
            pItem->iMem = ++pParse->nMem;
            assert( !ExprHasProperty(pExpr, EP_IntValue) );
            assert( ExprUseUToken(pExpr) );
            pItem->pFunc = sqlite3FindFunction(pParse->db,
                   pExpr->u.zToken, 
                   pExpr->x.pList ? pExpr->x.pList->nExpr : 0, enc, 0);
            if( pExpr->flags & EP_Distinct ){
              pItem->iDistinct = pParse->nTab++;
            }else{
              pItem->iDistinct = -1;
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277


5278
5279

5280
5281
5282
5283
5284
5285
5286
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







-
-
-
-
-
-
-
-
-













-
-
+
+


+







      }else{
        return WRC_Continue;
      }
    }
  }
  return WRC_Continue;
}
static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){
  UNUSED_PARAMETER(pSelect);
  pWalker->walkerDepth++;
  return WRC_Continue;
}
static void analyzeAggregatesInSelectEnd(Walker *pWalker, Select *pSelect){
  UNUSED_PARAMETER(pSelect);
  pWalker->walkerDepth--;
}

/*
** Analyze the pExpr expression looking for aggregate functions and
** for variables that need to be added to AggInfo object that pNC->pAggInfo
** points to.  Additional entries are made on the AggInfo object as
** necessary.
**
** This routine should only be called after the expression has been
** analyzed by sqlite3ResolveExprNames().
*/
void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
  Walker w;
  w.xExprCallback = analyzeAggregate;
  w.xSelectCallback = analyzeAggregatesInSelect;
  w.xSelectCallback2 = analyzeAggregatesInSelectEnd;
  w.xSelectCallback = sqlite3WalkerDepthIncrease;
  w.xSelectCallback2 = sqlite3WalkerDepthDecrease;
  w.walkerDepth = 0;
  w.u.pNC = pNC;
  w.pParse = 0;
  assert( pNC->pSrcList!=0 );
  sqlite3WalkExpr(&w, pExpr);
}

/*
** Call sqlite3ExprAnalyzeAggregates() for every expression in an
** expression list.  Return the number of errors.
5308
5309
5310
5311
5312
5313
5314


5315
5316



5317
5318
5319
5320
5321
5322
5323
6553
6554
6555
6556
6557
6558
6559
6560
6561


6562
6563
6564
6565
6566
6567
6568
6569
6570
6571







+
+
-
-
+
+
+







}

/*
** Deallocate a register, making available for reuse for some other
** purpose.
*/
void sqlite3ReleaseTempReg(Parse *pParse, int iReg){
  if( iReg ){
    sqlite3VdbeReleaseRegisters(pParse, iReg, 1, 0, 0);
  if( iReg && pParse->nTempReg<ArraySize(pParse->aTempReg) ){
    pParse->aTempReg[pParse->nTempReg++] = iReg;
    if( pParse->nTempReg<ArraySize(pParse->aTempReg) ){
      pParse->aTempReg[pParse->nTempReg++] = iReg;
    }
  }
}

/*
** Allocate or deallocate a block of nReg consecutive registers.
*/
int sqlite3GetTempRange(Parse *pParse, int nReg){
5335
5336
5337
5338
5339
5340
5341

5342
5343
5344
5345
5346
5347
5348
5349





5350
5351
5352
5353
5354
5355
5356
6583
6584
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610







+








+
+
+
+
+







  return i;
}
void sqlite3ReleaseTempRange(Parse *pParse, int iReg, int nReg){
  if( nReg==1 ){
    sqlite3ReleaseTempReg(pParse, iReg);
    return;
  }
  sqlite3VdbeReleaseRegisters(pParse, iReg, nReg, 0, 0);
  if( nReg>pParse->nRangeReg ){
    pParse->nRangeReg = nReg;
    pParse->iRangeReg = iReg;
  }
}

/*
** Mark all temporary registers as being unavailable for reuse.
**
** Always invoke this procedure after coding a subroutine or co-routine
** that might be invoked from other parts of the code, to ensure that
** the sub/co-routine does not use registers in common with the code that
** invokes the sub/co-routine.
*/
void sqlite3ClearTempRegCache(Parse *pParse){
  pParse->nTempReg = 0;
  pParse->nRangeReg = 0;
}

/*

Changes to src/fkey.c.

211
212
213
214
215
216
217
218



219
220
221
222
223
224
225
211
212
213
214
215
216
217

218
219
220
221
222
223
224
225
226
227







-
+
+
+







    **   1) There is an INTEGER PRIMARY KEY column and the FK is implicitly 
    **      mapped to the primary key of table pParent, or
    **   2) The FK is explicitly mapped to a column declared as INTEGER
    **      PRIMARY KEY.
    */
    if( pParent->iPKey>=0 ){
      if( !zKey ) return 0;
      if( !sqlite3StrICmp(pParent->aCol[pParent->iPKey].zName, zKey) ) return 0;
      if( !sqlite3StrICmp(pParent->aCol[pParent->iPKey].zCnName, zKey) ){
        return 0;
      }
    }
  }else if( paiCol ){
    assert( nCol>1 );
    aiCol = (int *)sqlite3DbMallocRawNN(pParse->db, nCol*sizeof(int));
    if( !aiCol ) return 1;
    *paiCol = aiCol;
  }
253
254
255
256
257
258
259
260

261
262
263
264

265
266
267
268
269
270
271
255
256
257
258
259
260
261

262
263
264
265

266
267
268
269
270
271
272
273







-
+



-
+







          char *zIdxCol;                    /* Name of indexed column */

          if( iCol<0 ) break; /* No foreign keys against expression indexes */

          /* If the index uses a collation sequence that is different from
          ** the default collation sequence for the column, this index is
          ** unusable. Bail out early in this case.  */
          zDfltColl = pParent->aCol[iCol].zColl;
          zDfltColl = sqlite3ColumnColl(&pParent->aCol[iCol]);
          if( !zDfltColl ) zDfltColl = sqlite3StrBINARY;
          if( sqlite3StrICmp(pIdx->azColl[i], zDfltColl) ) break;

          zIdxCol = pParent->aCol[iCol].zName;
          zIdxCol = pParent->aCol[iCol].zCnName;
          for(j=0; j<nCol; j++){
            if( sqlite3StrICmp(pFKey->aCol[j].zCol, zIdxCol)==0 ){
              if( aiCol ) aiCol[i] = pFKey->aCol[j].iFrom;
              break;
            }
          }
          if( j==nCol ) break;
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
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







-
+



















-
+















-
+
+







  int regData,          /* Address of array containing child table row */
  int nIncr,            /* Increment constraint counter by this */
  int isIgnore          /* If true, pretend pTab contains all NULL values */
){
  int i;                                    /* Iterator variable */
  Vdbe *v = sqlite3GetVdbe(pParse);         /* Vdbe to add code to */
  int iCur = pParse->nTab - 1;              /* Cursor number to use */
  int iOk = sqlite3VdbeMakeLabel(v);        /* jump here if parent key found */
  int iOk = sqlite3VdbeMakeLabel(pParse);   /* jump here if parent key found */

  sqlite3VdbeVerifyAbortable(v,
    (!pFKey->isDeferred
      && !(pParse->db->flags & SQLITE_DeferFKs)
      && !pParse->pToplevel 
      && !pParse->isMultiWrite) ? OE_Abort : OE_Ignore);

  /* If nIncr is less than zero, then check at runtime if there are any
  ** outstanding constraints to resolve. If there are not, there is no need
  ** to check if deleting this row resolves any outstanding violations.
  **
  ** Check if any of the key columns in the child table row are NULL. If 
  ** any are, then the constraint is considered satisfied. No need to 
  ** search for a matching row in the parent table.  */
  if( nIncr<0 ){
    sqlite3VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, iOk);
    VdbeCoverage(v);
  }
  for(i=0; i<pFKey->nCol; i++){
    int iReg = aiCol[i] + regData + 1;
    int iReg = sqlite3TableColumnToStorage(pFKey->pFrom,aiCol[i]) + regData + 1;
    sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iOk); VdbeCoverage(v);
  }

  if( isIgnore==0 ){
    if( pIdx==0 ){
      /* If pIdx is NULL, then the parent key is the INTEGER PRIMARY KEY
      ** column of the parent table (table pTab).  */
      int iMustBeInt;               /* Address of MustBeInt instruction */
      int regTemp = sqlite3GetTempReg(pParse);
  
      /* Invoke MustBeInt to coerce the child key value to an integer (i.e. 
      ** apply the affinity of the parent key). If this fails, then there
      ** is no matching parent key. Before using MustBeInt, make a copy of
      ** the value. Otherwise, the value inserted into the child key column
      ** will have INTEGER affinity applied to it, which may not be correct.  */
      sqlite3VdbeAddOp2(v, OP_SCopy, aiCol[0]+1+regData, regTemp);
      sqlite3VdbeAddOp2(v, OP_SCopy, 
        sqlite3TableColumnToStorage(pFKey->pFrom,aiCol[0])+1+regData, regTemp);
      iMustBeInt = sqlite3VdbeAddOp2(v, OP_MustBeInt, regTemp, 0);
      VdbeCoverage(v);
  
      /* If the parent table is the same as the child table, and we are about
      ** to increment the constraint-counter (i.e. this is an INSERT operation),
      ** then check if the row being inserted matches itself. If so, do not
      ** increment the constraint-counter.  */
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
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







-




-
+
+
+















+
-
-
+
+
+
+











-
-
+
+

-
-
+
+
-







      sqlite3VdbeGoto(v, iOk);
      sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
      sqlite3VdbeJumpHere(v, iMustBeInt);
      sqlite3ReleaseTempReg(pParse, regTemp);
    }else{
      int nCol = pFKey->nCol;
      int regTemp = sqlite3GetTempRange(pParse, nCol);
      int regRec = sqlite3GetTempReg(pParse);
  
      sqlite3VdbeAddOp3(v, OP_OpenRead, iCur, pIdx->tnum, iDb);
      sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
      for(i=0; i<nCol; i++){
        sqlite3VdbeAddOp2(v, OP_Copy, aiCol[i]+1+regData, regTemp+i);
        sqlite3VdbeAddOp2(v, OP_Copy, 
               sqlite3TableColumnToStorage(pFKey->pFrom, aiCol[i])+1+regData,
               regTemp+i);
      }
  
      /* If the parent table is the same as the child table, and we are about
      ** to increment the constraint-counter (i.e. this is an INSERT operation),
      ** then check if the row being inserted matches itself. If so, do not
      ** increment the constraint-counter. 
      **
      ** If any of the parent-key values are NULL, then the row cannot match 
      ** itself. So set JUMPIFNULL to make sure we do the OP_Found if any
      ** of the parent-key values are NULL (at this point it is known that
      ** none of the child key values are).
      */
      if( pTab==pFKey->pFrom && nIncr==1 ){
        int iJump = sqlite3VdbeCurrentAddr(v) + nCol + 1;
        for(i=0; i<nCol; i++){
          int iChild = sqlite3TableColumnToStorage(pFKey->pFrom,aiCol[i])
          int iChild = aiCol[i]+1+regData;
          int iParent = pIdx->aiColumn[i]+1+regData;
                              +1+regData;
          int iParent = 1+regData;
          iParent += sqlite3TableColumnToStorage(pIdx->pTable,
                                                 pIdx->aiColumn[i]);
          assert( pIdx->aiColumn[i]>=0 );
          assert( aiCol[i]!=pTab->iPKey );
          if( pIdx->aiColumn[i]==pTab->iPKey ){
            /* The parent key is a composite key that includes the IPK column */
            iParent = regData;
          }
          sqlite3VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent); VdbeCoverage(v);
          sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL);
        }
        sqlite3VdbeGoto(v, iOk);
      }
  
      sqlite3VdbeAddOp4(v, OP_MakeRecord, regTemp, nCol, regRec,

      sqlite3VdbeAddOp4(v, OP_Affinity, regTemp, nCol, 0,
                        sqlite3IndexAffinityStr(pParse->db,pIdx), nCol);
      sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0); VdbeCoverage(v);
  
      sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regTemp, nCol);
      VdbeCoverage(v);
      sqlite3ReleaseTempReg(pParse, regRec);
      sqlite3ReleaseTempRange(pParse, regTemp, nCol);
    }
  }

  if( !pFKey->isDeferred && !(pParse->db->flags & SQLITE_DeferFKs)
   && !pParse->pToplevel 
   && !pParse->isMultiWrite 
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
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







-
-
-
+
+
+




-
+

















+







  const char *zColl;
  sqlite3 *db = pParse->db;

  pExpr = sqlite3Expr(db, TK_REGISTER, 0);
  if( pExpr ){
    if( iCol>=0 && iCol!=pTab->iPKey ){
      pCol = &pTab->aCol[iCol];
      pExpr->iTable = regBase + iCol + 1;
      pExpr->affinity = pCol->affinity;
      zColl = pCol->zColl;
      pExpr->iTable = regBase + sqlite3TableColumnToStorage(pTab,iCol) + 1;
      pExpr->affExpr = pCol->affinity;
      zColl = sqlite3ColumnColl(pCol);
      if( zColl==0 ) zColl = db->pDfltColl->zName;
      pExpr = sqlite3ExprAddCollateString(pParse, pExpr, zColl);
    }else{
      pExpr->iTable = regBase;
      pExpr->affinity = SQLITE_AFF_INTEGER;
      pExpr->affExpr = SQLITE_AFF_INTEGER;
    }
  }
  return pExpr;
}

/*
** Return an Expr object that refers to column iCol of table pTab which
** has cursor iCur.
*/
static Expr *exprTableColumn(
  sqlite3 *db,      /* The database connection */
  Table *pTab,      /* The table whose column is desired */
  int iCursor,      /* The open cursor on the table */
  i16 iCol          /* The column that is wanted */
){
  Expr *pExpr = sqlite3Expr(db, TK_COLUMN, 0);
  if( pExpr ){
    assert( ExprUseYTab(pExpr) );
    pExpr->y.pTab = pTab;
    pExpr->iTable = iCursor;
    pExpr->iColumn = iCol;
  }
  return pExpr;
}

523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
530
531
532
533
534
535
536


537
538
539
540


541
542
543
544
545
546
547







-
-




-
-







** The code generated by this function scans through the rows in the child
** table that correspond to the parent table row being deleted or inserted.
** For each child row found, one of the following actions is taken:
**
**   Operation | FK type   | Action taken
**   --------------------------------------------------------------------------
**   DELETE      immediate   Increment the "immediate constraint counter".
**                           Or, if the ON (UPDATE|DELETE) action is RESTRICT,
**                           throw a "FOREIGN KEY constraint failed" exception.
**
**   INSERT      immediate   Decrement the "immediate constraint counter".
**
**   DELETE      deferred    Increment the "deferred constraint counter".
**                           Or, if the ON (UPDATE|DELETE) action is RESTRICT,
**                           throw a "FOREIGN KEY constraint failed" exception.
**
**   INSERT      deferred    Decrement the "deferred constraint counter".
**
** These operations are identified in the comment at the top of this file 
** (fkey.c) as "I.2" and "D.2".
*/
static void fkScanChildren(
584
585
586
587
588
589
590
591

592
593
594

595
596
597
598
599
600
601
602
603
604
605
606





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

621
622
623
624
625
626



627
628
629
630

631
632
633
634
635
636
637
638
639
640
641
642
643

644
645
646
647
648
649
650
651
652
653

654
655
656
657
658
659
660
587
588
589
590
591
592
593

594
595
596

597
598
599
600
601
602
603
604
605
606
607


608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623

624

625
626
627
628



629
630
631
632
633
634

635
636
637
638
639
640
641
642
643
644
645
646
647

648
649
650
651
652
653
654
655
656
657

658
659
660
661
662
663
664
665







-
+


-
+










-
-
+
+
+
+
+











-

-
+



-
-
-
+
+
+



-
+












-
+









-
+







    i16 iCol;                     /* Index of column in child table */ 
    const char *zCol;             /* Name of column in child table */

    iCol = pIdx ? pIdx->aiColumn[i] : -1;
    pLeft = exprTableRegister(pParse, pTab, regData, iCol);
    iCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom;
    assert( iCol>=0 );
    zCol = pFKey->pFrom->aCol[iCol].zName;
    zCol = pFKey->pFrom->aCol[iCol].zCnName;
    pRight = sqlite3Expr(db, TK_ID, zCol);
    pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight);
    pWhere = sqlite3ExprAnd(db, pWhere, pEq);
    pWhere = sqlite3ExprAnd(pParse, pWhere, pEq);
  }

  /* If the child table is the same as the parent table, then add terms
  ** to the WHERE clause that prevent this entry from being scanned.
  ** The added WHERE clause terms are like this:
  **
  **     $current_rowid!=rowid
  **     NOT( $current_a==a AND $current_b==b AND ... )
  **
  ** The first form is used for rowid tables.  The second form is used
  ** for WITHOUT ROWID tables.  In the second form, the primary key is
  ** (a,b,...)
  ** for WITHOUT ROWID tables. In the second form, the *parent* key is
  ** (a,b,...). Either the parent or primary key could be used to 
  ** uniquely identify the current row, but the parent key is more convenient
  ** as the required values have already been loaded into registers
  ** by the caller.
  */
  if( pTab==pFKey->pFrom && nIncr>0 ){
    Expr *pNe;                    /* Expression (pLeft != pRight) */
    Expr *pLeft;                  /* Value from parent table row */
    Expr *pRight;                 /* Column ref to child table */
    if( HasRowid(pTab) ){
      pLeft = exprTableRegister(pParse, pTab, regData, -1);
      pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, -1);
      pNe = sqlite3PExpr(pParse, TK_NE, pLeft, pRight);
    }else{
      Expr *pEq, *pAll = 0;
      Index *pPk = sqlite3PrimaryKeyIndex(pTab);
      assert( pIdx!=0 );
      for(i=0; i<pPk->nKeyCol; i++){
      for(i=0; i<pIdx->nKeyCol; i++){
        i16 iCol = pIdx->aiColumn[i];
        assert( iCol>=0 );
        pLeft = exprTableRegister(pParse, pTab, regData, iCol);
        pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, iCol);
        pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight);
        pAll = sqlite3ExprAnd(db, pAll, pEq);
        pRight = sqlite3Expr(db, TK_ID, pTab->aCol[iCol].zCnName);
        pEq = sqlite3PExpr(pParse, TK_IS, pLeft, pRight);
        pAll = sqlite3ExprAnd(pParse, pAll, pEq);
      }
      pNe = sqlite3PExpr(pParse, TK_NOT, pAll, 0);
    }
    pWhere = sqlite3ExprAnd(db, pWhere, pNe);
    pWhere = sqlite3ExprAnd(pParse, pWhere, pNe);
  }

  /* Resolve the references in the WHERE clause. */
  memset(&sNameContext, 0, sizeof(NameContext));
  sNameContext.pSrcList = pSrc;
  sNameContext.pParse = pParse;
  sqlite3ResolveExprNames(&sNameContext, pWhere);

  /* Create VDBE to loop through the entries in pSrc that match the WHERE
  ** clause. For each row found, increment either the deferred or immediate
  ** foreign key constraint counter. */
  if( pParse->nErr==0 ){
    pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0);
    pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0, 0);
    sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
    if( pWInfo ){
      sqlite3WhereEnd(pWInfo);
    }
  }

  /* Clean up the WHERE clause constructed above. */
  sqlite3ExprDelete(db, pWhere);
  if( iFkIfZero ){
    sqlite3VdbeJumpHere(v, iFkIfZero);
    sqlite3VdbeJumpHereOrPopInst(v, iFkIfZero);
  }
}

/*
** This function returns a linked list of FKey objects (connected by
** FKey.pNextTo) holding all children of table pTab.  For example,
** given the following schema:
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
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







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




















-
+




-
+







-
+



-
+







    sqlite3ExprDelete(dbMem, pStep->pWhere);
    sqlite3ExprListDelete(dbMem, pStep->pExprList);
    sqlite3SelectDelete(dbMem, pStep->pSelect);
    sqlite3ExprDelete(dbMem, p->pWhen);
    sqlite3DbFree(dbMem, p);
  }
}

/*
** Clear the apTrigger[] cache of CASCADE triggers for all foreign keys
** in a particular database.  This needs to happen when the schema
** changes.
*/
void sqlite3FkClearTriggerCache(sqlite3 *db, int iDb){
  HashElem *k;
  Hash *pHash = &db->aDb[iDb].pSchema->tblHash;
  for(k=sqliteHashFirst(pHash); k; k=sqliteHashNext(k)){
    Table *pTab = sqliteHashData(k);
    FKey *pFKey;
    if( !IsOrdinaryTable(pTab) ) continue;
    for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){
      fkTriggerDelete(db, pFKey->apTrigger[0]); pFKey->apTrigger[0] = 0;
      fkTriggerDelete(db, pFKey->apTrigger[1]); pFKey->apTrigger[1] = 0;
    }
  }
}

/*
** This function is called to generate code that runs when table pTab is
** being dropped from the database. The SrcList passed as the second argument
** to this function contains a single entry guaranteed to resolve to
** table pTab.
**
** Normally, no code is required. However, if either
**
**   (a) The table is the parent table of a FK constraint, or
**   (b) The table is the child table of a deferred FK constraint and it is
**       determined at runtime that there are outstanding deferred FK 
**       constraint violations in the database,
**
** then the equivalent of "DELETE FROM <tbl>" is executed before dropping
** the table from the database. Triggers are disabled while running this
** DELETE, but foreign key actions are not.
*/
void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){
  sqlite3 *db = pParse->db;
  if( (db->flags&SQLITE_ForeignKeys) && !IsVirtual(pTab) ){
  if( (db->flags&SQLITE_ForeignKeys) && IsOrdinaryTable(pTab) ){
    int iSkip = 0;
    Vdbe *v = sqlite3GetVdbe(pParse);

    assert( v );                  /* VDBE has already been allocated */
    assert( pTab->pSelect==0 );   /* Not a view */
    assert( IsOrdinaryTable(pTab) );
    if( sqlite3FkReferences(pTab)==0 ){
      /* Search for a deferred foreign key constraint for which this table
      ** is the child table. If one cannot be found, return without 
      ** generating any VDBE code. If one can be found, then jump over
      ** the entire DELETE if there are no outstanding deferred constraints
      ** when this statement is run.  */
      FKey *p;
      for(p=pTab->pFKey; p; p=p->pNextFrom){
      for(p=pTab->u.tab.pFKey; p; p=p->pNextFrom){
        if( p->isDeferred || (db->flags & SQLITE_DeferFKs) ) break;
      }
      if( !p ) return;
      iSkip = sqlite3VdbeMakeLabel(v);
      iSkip = sqlite3VdbeMakeLabel(pParse);
      sqlite3VdbeAddOp2(v, OP_FkIfZero, 1, iSkip); VdbeCoverage(v);
    }

    pParse->disableTriggers = 1;
    sqlite3DeleteFrom(pParse, sqlite3SrcListDup(db, pName, 0), 0, 0, 0);
    pParse->disableTriggers = 0;

808
809
810
811
812
813
814
815

816
817
818
819
820
821
822
832
833
834
835
836
837
838

839
840
841
842
843
844
845
846







-
+







  for(i=0; i<p->nCol; i++){
    char *zKey = p->aCol[i].zCol;
    int iKey;
    for(iKey=0; iKey<pTab->nCol; iKey++){
      if( aChange[iKey]>=0 || (iKey==pTab->iPKey && bChngRowid) ){
        Column *pCol = &pTab->aCol[iKey];
        if( zKey ){
          if( 0==sqlite3StrICmp(pCol->zName, zKey) ) return 1;
          if( 0==sqlite3StrICmp(pCol->zCnName, zKey) ) return 1;
        }else if( pCol->colFlags & COLFLAG_PRIMKEY ){
          return 1;
        }
      }
    }
  }
  return 0;
875
876
877
878
879
880
881

882
883
884
885
886
887
888

889
890
891
892
893
894
895
899
900
901
902
903
904
905
906
907
908
909
910
911
912

913
914
915
916
917
918
919
920







+






-
+







  int isIgnoreErrors = pParse->disableTriggers;

  /* Exactly one of regOld and regNew should be non-zero. */
  assert( (regOld==0)!=(regNew==0) );

  /* If foreign-keys are disabled, this function is a no-op. */
  if( (db->flags&SQLITE_ForeignKeys)==0 ) return;
  if( !IsOrdinaryTable(pTab) ) return;

  iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
  zDb = db->aDb[iDb].zDbSName;

  /* Loop through all the foreign key constraints for which pTab is the
  ** child table (the table that the foreign key definition is part of).  */
  for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){
  for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){
    Table *pTo;                   /* Parent table of foreign key pFKey */
    Index *pIdx = 0;              /* Index on key columns in pTo */
    int *aiFree = 0;
    int *aiCol;
    int iCol;
    int i;
    int bIgnore = 0;
920
921
922
923
924
925
926

927


928
929
930
931
932
933
934
945
946
947
948
949
950
951
952

953
954
955
956
957
958
959
960
961







+
-
+
+







        ** If the parent table of an FK constraint on the current table is
        ** missing, behave as if it is empty. i.e. decrement the relevant
        ** FK counter for each row of the current table with non-NULL keys.
        */
        Vdbe *v = sqlite3GetVdbe(pParse);
        int iJump = sqlite3VdbeCurrentAddr(v) + pFKey->nCol + 1;
        for(i=0; i<pFKey->nCol; i++){
          int iFromCol, iReg;
          int iReg = pFKey->aCol[i].iFrom + regOld + 1;
          iFromCol = pFKey->aCol[i].iFrom;
          iReg = sqlite3TableColumnToStorage(pFKey->pFrom,iFromCol) + regOld+1;
          sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iJump); VdbeCoverage(v);
        }
        sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, -1);
      }
      continue;
    }
    assert( pFKey->nCol==1 || (aiFree && pIdx) );
946
947
948
949
950
951
952
953

954
955
956
957
958
959
960
973
974
975
976
977
978
979

980
981
982
983
984
985
986
987







-
+







      assert( pIdx==0 || pIdx->aiColumn[i]>=0 );
#ifndef SQLITE_OMIT_AUTHORIZATION
      /* Request permission to read the parent key columns. If the 
      ** authorization callback returns SQLITE_IGNORE, behave as if any
      ** values read from the parent table are NULL. */
      if( db->xAuth ){
        int rcauth;
        char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zName;
        char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zCnName;
        rcauth = sqlite3AuthReadCol(pParse, pTo->zName, zCol, iDb);
        bIgnore = (rcauth==SQLITE_IGNORE);
      }
#endif
    }

    /* Take a shared-cache advisory read-lock on the parent table. Allocate 
1008
1009
1010
1011
1012
1013
1014
1015

1016
1017

1018
1019
1020
1021
1022
1023
1024
1035
1036
1037
1038
1039
1040
1041

1042
1043

1044
1045
1046
1047
1048
1049
1050
1051







-
+

-
+







      if( !isIgnoreErrors || db->mallocFailed ) return;
      continue;
    }
    assert( aiCol || pFKey->nCol==1 );

    /* Create a SrcList structure containing the child table.  We need the
    ** child table as a SrcList for sqlite3WhereBegin() */
    pSrc = sqlite3SrcListAppend(db, 0, 0, 0);
    pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
    if( pSrc ){
      struct SrcList_item *pItem = pSrc->a;
      SrcItem *pItem = pSrc->a;
      pItem->pTab = pFKey->pFrom;
      pItem->zName = pFKey->pFrom->zName;
      pItem->pTab->nTabRef++;
      pItem->iCursor = pParse->nTab++;
  
      if( regNew!=0 ){
        fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regNew, -1);
1061
1062
1063
1064
1065
1066
1067
1068

1069
1070
1071

1072
1073
1074
1075
1076
1077
1078
1088
1089
1090
1091
1092
1093
1094

1095
1096
1097

1098
1099
1100
1101
1102
1103
1104
1105







-
+


-
+







** row contained in table pTab.
*/
u32 sqlite3FkOldmask(
  Parse *pParse,                  /* Parse context */
  Table *pTab                     /* Table being modified */
){
  u32 mask = 0;
  if( pParse->db->flags&SQLITE_ForeignKeys ){
  if( pParse->db->flags&SQLITE_ForeignKeys && IsOrdinaryTable(pTab) ){
    FKey *p;
    int i;
    for(p=pTab->pFKey; p; p=p->pNextFrom){
    for(p=pTab->u.tab.pFKey; p; p=p->pNextFrom){
      for(i=0; i<p->nCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom);
    }
    for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
      Index *pIdx = 0;
      sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0);
      if( pIdx ){
        for(i=0; i<pIdx->nKeyCol; i++){
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
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







-
+
+
+











-
-
+
+
+




-
+






-
+
-

+
-
+







-
+




-
+











-
-
-
+
+
+







**
** If any foreign key processing will be required, this function returns
** non-zero. If there is no foreign key related processing, this function 
** returns zero.
**
** For an UPDATE, this function returns 2 if:
**
**   * There are any FKs for which pTab is the child and the parent table, or
**   * There are any FKs for which pTab is the child and the parent table
**     and any FK processing at all is required (even of a different FK), or
**
**   * the UPDATE modifies one or more parent keys for which the action is
**     not "NO ACTION" (i.e. is CASCADE, SET DEFAULT or SET NULL).
**
** Or, assuming some other foreign key processing is required, 1.
*/
int sqlite3FkRequired(
  Parse *pParse,                  /* Parse context */
  Table *pTab,                    /* Table being modified */
  int *aChange,                   /* Non-NULL for UPDATE operations */
  int chngRowid                   /* True for UPDATE that affects rowid */
){
  int eRet = 0;
  if( pParse->db->flags&SQLITE_ForeignKeys ){
  int eRet = 1;                   /* Value to return if bHaveFK is true */
  int bHaveFK = 0;                /* If FK processing is required */
  if( pParse->db->flags&SQLITE_ForeignKeys && IsOrdinaryTable(pTab) ){
    if( !aChange ){
      /* A DELETE operation. Foreign key processing is required if the 
      ** table in question is either the child or parent table for any 
      ** foreign key constraint.  */
      eRet = (sqlite3FkReferences(pTab) || pTab->pFKey);
      bHaveFK = (sqlite3FkReferences(pTab) || pTab->u.tab.pFKey);
    }else{
      /* This is an UPDATE. Foreign key processing is only required if the
      ** operation modifies one or more child or parent key columns. */
      FKey *p;

      /* Check if any child key columns are being modified. */
      for(p=pTab->pFKey; p; p=p->pNextFrom){
      for(p=pTab->u.tab.pFKey; p; p=p->pNextFrom){
        if( 0==sqlite3_stricmp(pTab->zName, p->zTo) ) return 2;
        if( fkChildIsModified(pTab, p, aChange, chngRowid) ){
          if( 0==sqlite3_stricmp(pTab->zName, p->zTo) ) eRet = 2;
          eRet = 1;
          bHaveFK = 1;
        }
      }

      /* Check if any parent key columns are being modified. */
      for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
        if( fkParentIsModified(pTab, p, aChange, chngRowid) ){
          if( p->aAction[1]!=OE_None ) return 2;
          eRet = 1;
          bHaveFK = 1;
        }
      }
    }
  }
  return eRet;
  return bHaveFK ? eRet : 0;
}

/*
** This function is called when an UPDATE or DELETE operation is being 
** compiled on table pTab, which is the parent table of foreign-key pFKey.
** If the current operation is an UPDATE, then the pChanges parameter is
** passed a pointer to the list of columns being modified. If it is a
** DELETE, pChanges is passed a NULL pointer.
**
** It returns a pointer to a Trigger structure containing a trigger
** equivalent to the ON UPDATE or ON DELETE action specified by pFKey.
** If the action is "NO ACTION" or "RESTRICT", then a NULL pointer is
** returned (these actions require no special handling by the triggers
** sub-system, code for them is created by fkScanChildren()).
** If the action is "NO ACTION" then a NULL pointer is returned (these actions
** require no special handling by the triggers sub-system, code for them is
** created by fkScanChildren()).
**
** For example, if pFKey is the foreign key and pTab is table "p" in 
** the following schema:
**
**   CREATE TABLE p(pk PRIMARY KEY);
**   CREATE TABLE c(ck REFERENCES p ON DELETE CASCADE);
**
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



1286
1287
1288

1289
1290
1291
1292

1293
1294
1295
1296
1297
1298
1299
1300

1301
1302
1303
1304
1305
1306
1307
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
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330

1331
1332
1333
1334

1335
1336
1337
1338
1339
1340
1341
1342

1343
1344
1345
1346
1347
1348
1349
1350







-
-
+
+











-
+















-
+









+
-
+
+
+
+
+
+
+
+


















+

+




+
+
+


-
+



-
+







-
+







      Expr *pEq;                  /* tFromCol = OLD.tToCol */

      iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom;
      assert( iFromCol>=0 );
      assert( pIdx!=0 || (pTab->iPKey>=0 && pTab->iPKey<pTab->nCol) );
      assert( pIdx==0 || pIdx->aiColumn[i]>=0 );
      sqlite3TokenInit(&tToCol,
                   pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zName);
      sqlite3TokenInit(&tFromCol, pFKey->pFrom->aCol[iFromCol].zName);
                   pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zCnName);
      sqlite3TokenInit(&tFromCol, pFKey->pFrom->aCol[iFromCol].zCnName);

      /* Create the expression "OLD.zToCol = zFromCol". It is important
      ** that the "OLD.zToCol" term is on the LHS of the = operator, so
      ** that the affinity and collation sequence associated with the
      ** parent table are used for the comparison. */
      pEq = sqlite3PExpr(pParse, TK_EQ,
          sqlite3PExpr(pParse, TK_DOT, 
            sqlite3ExprAlloc(db, TK_ID, &tOld, 0),
            sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)),
          sqlite3ExprAlloc(db, TK_ID, &tFromCol, 0)
      );
      pWhere = sqlite3ExprAnd(db, pWhere, pEq);
      pWhere = sqlite3ExprAnd(pParse, pWhere, pEq);

      /* For ON UPDATE, construct the next term of the WHEN clause.
      ** The final WHEN clause will be like this:
      **
      **    WHEN NOT(old.col1 IS new.col1 AND ... AND old.colN IS new.colN)
      */
      if( pChanges ){
        pEq = sqlite3PExpr(pParse, TK_IS,
            sqlite3PExpr(pParse, TK_DOT, 
              sqlite3ExprAlloc(db, TK_ID, &tOld, 0),
              sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)),
            sqlite3PExpr(pParse, TK_DOT, 
              sqlite3ExprAlloc(db, TK_ID, &tNew, 0),
              sqlite3ExprAlloc(db, TK_ID, &tToCol, 0))
            );
        pWhen = sqlite3ExprAnd(db, pWhen, pEq);
        pWhen = sqlite3ExprAnd(pParse, pWhen, pEq);
      }
  
      if( action!=OE_Restrict && (action!=OE_Cascade || pChanges) ){
        Expr *pNew;
        if( action==OE_Cascade ){
          pNew = sqlite3PExpr(pParse, TK_DOT, 
            sqlite3ExprAlloc(db, TK_ID, &tNew, 0),
            sqlite3ExprAlloc(db, TK_ID, &tToCol, 0));
        }else if( action==OE_SetDflt ){
          Column *pCol = pFKey->pFrom->aCol + iFromCol;
          Expr *pDflt = pFKey->pFrom->aCol[iFromCol].pDflt;
          Expr *pDflt;
          if( pCol->colFlags & COLFLAG_GENERATED ){
            testcase( pCol->colFlags & COLFLAG_VIRTUAL );
            testcase( pCol->colFlags & COLFLAG_STORED );
            pDflt = 0;
          }else{
            pDflt = sqlite3ColumnExpr(pFKey->pFrom, pCol);
          }
          if( pDflt ){
            pNew = sqlite3ExprDup(db, pDflt, 0);
          }else{
            pNew = sqlite3ExprAlloc(db, TK_NULL, 0, 0);
          }
        }else{
          pNew = sqlite3ExprAlloc(db, TK_NULL, 0, 0);
        }
        pList = sqlite3ExprListAppend(pParse, pList, pNew);
        sqlite3ExprListSetName(pParse, pList, &tFromCol, 0);
      }
    }
    sqlite3DbFree(db, aiCol);

    zFrom = pFKey->pFrom->zName;
    nFrom = sqlite3Strlen30(zFrom);

    if( action==OE_Restrict ){
      int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
      Token tFrom;
      Token tDb;
      Expr *pRaise; 

      tFrom.z = zFrom;
      tFrom.n = nFrom;
      tDb.z = db->aDb[iDb].zDbSName;
      tDb.n = sqlite3Strlen30(tDb.z);

      pRaise = sqlite3Expr(db, TK_RAISE, "FOREIGN KEY constraint failed");
      if( pRaise ){
        pRaise->affinity = OE_Abort;
        pRaise->affExpr = OE_Abort;
      }
      pSelect = sqlite3SelectNew(pParse, 
          sqlite3ExprListAppend(pParse, 0, pRaise),
          sqlite3SrcListAppend(db, 0, &tFrom, 0),
          sqlite3SrcListAppend(pParse, 0, &tDb, &tFrom),
          pWhere,
          0, 0, 0, 0, 0
      );
      pWhere = 0;
    }

    /* Disable lookaside memory allocation */
    db->lookaside.bDisable++;
    DisableLookaside;

    pTrigger = (Trigger *)sqlite3DbMallocZero(db, 
        sizeof(Trigger) +         /* struct Trigger */
        sizeof(TriggerStep) +     /* Single step in trigger program */
        nFrom + 1                 /* Space for pStep->zTarget */
    );
    if( pTrigger ){
1315
1316
1317
1318
1319
1320
1321
1322

1323
1324
1325
1326
1327
1328
1329
1330
1331
1332

1333
1334
1335
1336

1337
1338
1339
1340
1341
1342

1343
1344
1345
1346
1347
1348
1349
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







-
+










+



-
+






+







      if( pWhen ){
        pWhen = sqlite3PExpr(pParse, TK_NOT, pWhen, 0);
        pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE);
      }
    }

    /* Re-enable the lookaside buffer, if it was disabled earlier. */
    db->lookaside.bDisable--;
    EnableLookaside;

    sqlite3ExprDelete(db, pWhere);
    sqlite3ExprDelete(db, pWhen);
    sqlite3ExprListDelete(db, pList);
    sqlite3SelectDelete(db, pSelect);
    if( db->mallocFailed==1 ){
      fkTriggerDelete(db, pTrigger);
      return 0;
    }
    assert( pStep!=0 );
    assert( pTrigger!=0 );

    switch( action ){
      case OE_Restrict:
        pStep->op = TK_SELECT; 
        pStep->op = TK_SELECT;
        break;
      case OE_Cascade: 
        if( !pChanges ){ 
          pStep->op = TK_DELETE; 
          break; 
        }
        /* no break */ deliberate_fall_through
      default:
        pStep->op = TK_UPDATE;
    }
    pStep->pTrig = pTrigger;
    pTrigger->pSchema = pTab->pSchema;
    pTrigger->pTabSchema = pTab->pSchema;
    pFKey->apTrigger[iAction] = pTrigger;
1389
1390
1391
1392
1393
1394
1395

1396
1397



1398
1399
1400
1401

1402
1403
1404
1405
1406
1407
1408
1434
1435
1436
1437
1438
1439
1440
1441


1442
1443
1444

1445
1446

1447
1448
1449
1450
1451
1452
1453
1454







+
-
-
+
+
+
-


-
+







** table pTab. Remove the deleted foreign keys from the Schema.fkeyHash
** hash table.
*/
void sqlite3FkDelete(sqlite3 *db, Table *pTab){
  FKey *pFKey;                    /* Iterator variable */
  FKey *pNext;                    /* Copy of pFKey->pNextFrom */

  assert( IsOrdinaryTable(pTab) );
  assert( db==0 || IsVirtual(pTab)
         || sqlite3SchemaMutexHeld(db, 0, pTab->pSchema) );
  assert( db!=0 );
  for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pNext){
    assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pTab->pSchema) );
  for(pFKey=pTab->pFKey; pFKey; pFKey=pNext){

    /* Remove the FK from the fkeyHash hash table. */
    if( !db || db->pnBytesFreed==0 ){
    if( db->pnBytesFreed==0 ){
      if( pFKey->pPrevTo ){
        pFKey->pPrevTo->pNextTo = pFKey->pNextTo;
      }else{
        void *p = (void *)pFKey->pNextTo;
        const char *z = (p ? pFKey->pNextTo->zTo : pFKey->zTo);
        sqlite3HashInsert(&pTab->pSchema->fkeyHash, z, p);
      }

Changes to src/func.c.

12
13
14
15
16
17
18



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







+
+
+







** This file contains the C-language implementations for many of the SQL
** functions of SQLite.  (Some function, and in particular the date and
** time functions, are implemented separately.)
*/
#include "sqliteInt.h"
#include <stdlib.h>
#include <assert.h>
#ifndef SQLITE_OMIT_FLOATING_POINT
#include <math.h>
#endif
#include "vdbeInt.h"

/*
** Return the collating function associated with a function.
*/
static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){
  VdbeOp *pOp;
90
91
92
93
94
95
96












97
98
99
100
101
102
103
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







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







  /* EVIDENCE-OF: R-01470-60482 The sqlite3_value_type(V) interface returns
  ** the datatype code for the initial datatype of the sqlite3_value object
  ** V. The returned value is one of SQLITE_INTEGER, SQLITE_FLOAT,
  ** SQLITE_TEXT, SQLITE_BLOB, or SQLITE_NULL. */
  sqlite3_result_text(context, azType[i], -1, SQLITE_STATIC);
}

/* subtype(X)
**
** Return the subtype of X
*/
static void subtypeFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  UNUSED_PARAMETER(argc);
  sqlite3_result_int(context, sqlite3_value_subtype(argv[0]));
}

/*
** Implementation of the length() function
*/
static void lengthFunc(
  sqlite3_context *context,
  int argc,
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
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







+
+
+












-
+



+
+
+
+
+
+
+
+
+
+

-
-
+
+
+
+
+









+
+
+
+
+
+
+



-
+







  const unsigned char *zHaystack;
  const unsigned char *zNeedle;
  int nHaystack;
  int nNeedle;
  int typeHaystack, typeNeedle;
  int N = 1;
  int isText;
  unsigned char firstChar;
  sqlite3_value *pC1 = 0;
  sqlite3_value *pC2 = 0;

  UNUSED_PARAMETER(argc);
  typeHaystack = sqlite3_value_type(argv[0]);
  typeNeedle = sqlite3_value_type(argv[1]);
  if( typeHaystack==SQLITE_NULL || typeNeedle==SQLITE_NULL ) return;
  nHaystack = sqlite3_value_bytes(argv[0]);
  nNeedle = sqlite3_value_bytes(argv[1]);
  if( nNeedle>0 ){
    if( typeHaystack==SQLITE_BLOB && typeNeedle==SQLITE_BLOB ){
      zHaystack = sqlite3_value_blob(argv[0]);
      zNeedle = sqlite3_value_blob(argv[1]);
      isText = 0;
    }else{
    }else if( typeHaystack!=SQLITE_BLOB && typeNeedle!=SQLITE_BLOB ){
      zHaystack = sqlite3_value_text(argv[0]);
      zNeedle = sqlite3_value_text(argv[1]);
      isText = 1;
    }else{
      pC1 = sqlite3_value_dup(argv[0]);
      zHaystack = sqlite3_value_text(pC1);
      if( zHaystack==0 ) goto endInstrOOM;
      nHaystack = sqlite3_value_bytes(pC1);
      pC2 = sqlite3_value_dup(argv[1]);
      zNeedle = sqlite3_value_text(pC2);
      if( zNeedle==0 ) goto endInstrOOM;
      nNeedle = sqlite3_value_bytes(pC2);
      isText = 1;
    }
    if( zNeedle==0 || (nHaystack && zHaystack==0) ) return;
    while( nNeedle<=nHaystack && memcmp(zHaystack, zNeedle, nNeedle)!=0 ){
    if( zNeedle==0 || (nHaystack && zHaystack==0) ) goto endInstrOOM;
    firstChar = zNeedle[0];
    while( nNeedle<=nHaystack
       && (zHaystack[0]!=firstChar || memcmp(zHaystack, zNeedle, nNeedle)!=0)
    ){
      N++;
      do{
        nHaystack--;
        zHaystack++;
      }while( isText && (zHaystack[0]&0xc0)==0x80 );
    }
    if( nNeedle>nHaystack ) N = 0;
  }
  sqlite3_result_int(context, N);
endInstr:
  sqlite3_value_free(pC1);
  sqlite3_value_free(pC2);
  return;
endInstrOOM:
  sqlite3_result_error_nomem(context);
  goto endInstr;
}

/*
** Implementation of the printf() function.
** Implementation of the printf() (a.k.a. format()) SQL function.
*/
static void printfFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  PrintfArguments x;
378
379
380
381
382
383
384
385
386
387
388




389
390
391
392
393
394
395
416
417
418
419
420
421
422




423
424
425
426
427
428
429
430
431
432
433







-
-
-
-
+
+
+
+







  }
  if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
  r = sqlite3_value_double(argv[0]);
  /* If Y==0 and X will fit in a 64-bit int,
  ** handle the rounding directly,
  ** otherwise use printf.
  */
  if( n==0 && r>=0 && r<LARGEST_INT64-1 ){
    r = (double)((sqlite_int64)(r+0.5));
  }else if( n==0 && r<0 && (-r)<LARGEST_INT64-1 ){
    r = -(double)((sqlite_int64)((-r)+0.5));
  if( r<-4503599627370496.0 || r>+4503599627370496.0 ){
    /* The value has no fractional part so there is nothing to round */
  }else if( n==0 ){  
    r = (double)((sqlite_int64)(r+(r<0?-0.5:+0.5)));
  }else{
    zBuf = sqlite3_mprintf("%.*f",n,r);
    if( zBuf==0 ){
      sqlite3_result_error_nomem(context);
      return;
    }
    sqlite3AtoF(zBuf, &r, sqlite3Strlen30(zBuf), SQLITE_UTF8);
507
508
509
510
511
512
513
514

515
516
517
518
519

520
521
522
523
524
525
526
545
546
547
548
549
550
551

552
553
554
555
556

557
558
559
560
561
562
563
564







-
+




-
+







** that is N bytes long.
*/
static void randomBlob(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  int n;
  sqlite3_int64 n;
  unsigned char *p;
  sqlite3 *db = sqlite3_context_db_handle(context);
  assert( argc==1 );
  UNUSED_PARAMETER(argc);
  n = sqlite3_value_int(argv[0]);
  n = sqlite3_value_int64(argv[0]);
  if( n<1 ){
    n = 1;
  }
  p = contextMalloc(context, n);
  if( p ){
    sqlite3FastRandomness(&db->sPrng, n, p);
    sqlite3_result_blob(context, (char*)p, n, sqlite3_free);
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
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







-
-
-
+
+
+








-
+




-
+








-
-
-
+
+
+







  ** function. */
  sqlite3_result_int64(context, sqlite3_last_insert_rowid(db));
}

/*
** Implementation of the changes() SQL function.
**
** IMP: R-62073-11209 The changes() SQL function is a wrapper
** around the sqlite3_changes() C/C++ function and hence follows the same
** rules for counting changes.
** IMP: R-32760-32347 The changes() SQL function is a wrapper
** around the sqlite3_changes64() C/C++ function and hence follows the
** same rules for counting changes.
*/
static void changes(
  sqlite3_context *context,
  int NotUsed,
  sqlite3_value **NotUsed2
){
  sqlite3 *db = sqlite3_context_db_handle(context);
  UNUSED_PARAMETER2(NotUsed, NotUsed2);
  sqlite3_result_int(context, sqlite3_changes(db));
  sqlite3_result_int64(context, sqlite3_changes64(db));
}

/*
** Implementation of the total_changes() SQL function.  The return value is
** the same as the sqlite3_total_changes() API function.
** the same as the sqlite3_total_changes64() API function.
*/
static void total_changes(
  sqlite3_context *context,
  int NotUsed,
  sqlite3_value **NotUsed2
){
  sqlite3 *db = sqlite3_context_db_handle(context);
  UNUSED_PARAMETER2(NotUsed, NotUsed2);
  /* IMP: R-52756-41993 This function is a wrapper around the
  ** sqlite3_total_changes() C/C++ interface. */
  sqlite3_result_int(context, sqlite3_total_changes(db));
  /* IMP: R-11217-42568 This function is a wrapper around the
  ** sqlite3_total_changes64() C/C++ interface. */
  sqlite3_result_int64(context, sqlite3_total_changes64(db));
}

/*
** A structure defining how to do GLOB-style comparisons.
*/
struct compareInfo {
  u8 matchAll;          /* "*" or "%" */
666
667
668
669
670
671
672
673


674
675
676
677
678
679
680
704
705
706
707
708
709
710

711
712
713
714
715
716
717
718
719







-
+
+







  const u8 *zEscaped = 0;          /* One past the last escaped input char */
  
  while( (c = Utf8Read(zPattern))!=0 ){
    if( c==matchAll ){  /* Match "*" */
      /* Skip over multiple "*" characters in the pattern.  If there
      ** are also "?" characters, skip those as well, but consume a
      ** single character of the input string for each "?" skipped */
      while( (c=Utf8Read(zPattern)) == matchAll || c == matchOne ){
      while( (c=Utf8Read(zPattern)) == matchAll 
             || (c == matchOne && matchOne!=0) ){
        if( c==matchOne && sqlite3Utf8Read(&zString)==0 ){
          return SQLITE_NOWILDCARDMATCH;
        }
      }
      if( c==0 ){
        return SQLITE_MATCH;   /* "*" at the end of the pattern matches */
      }else if( c==matchOther ){
699
700
701
702
703
704
705
706

707
708
709
710
711
712
713
738
739
740
741
742
743
744

745
746
747
748
749
750
751
752







-
+







      ** first matching character and recursively continue the match from
      ** that point.
      **
      ** For a case-insensitive search, set variable cx to be the same as
      ** c but in the other case and search the input string for either
      ** c or cx.
      */
      if( c<=0x80 ){
      if( c<0x80 ){
        char zStop[3];
        int bMatch;
        if( noCase ){
          zStop[0] = sqlite3Toupper(c);
          zStop[1] = sqlite3Tolower(c);
          zStop[2] = 0;
        }else{
782
783
784
785
786
787
788





789


790
791
792
793
794
795
796





797


798
799
800
801
802
803
804
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







+
+
+
+
+
-
+
+







+
+
+
+
+
-
+
+







}

/*
** The sqlite3_strglob() interface.  Return 0 on a match (like strcmp()) and
** non-zero if there is no match.
*/
int sqlite3_strglob(const char *zGlobPattern, const char *zString){
  if( zString==0 ){
    return zGlobPattern!=0;
  }else if( zGlobPattern==0 ){
    return 1;
  }else {
  return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, '[');
    return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, '[');
  }
}

/*
** The sqlite3_strlike() interface.  Return 0 on a match and non-zero for
** a miss - like strcmp().
*/
int sqlite3_strlike(const char *zPattern, const char *zStr, unsigned int esc){
  if( zStr==0 ){
    return zPattern!=0;
  }else if( zPattern==0 ){
    return 1;
  }else{
  return patternCompare((u8*)zPattern, (u8*)zStr, &likeInfoNorm, esc);
    return patternCompare((u8*)zPattern, (u8*)zStr, &likeInfoNorm, esc);
  }
}

/*
** Count the number of times that the LIKE operator (or GLOB which is
** just a variation of LIKE) gets called.  This is used for testing
** only.
*/
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
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895


896
897
898
899
900
901
902
903
904
905
906


907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936







+












-
-











-
-












+
+
+
+
+
+



+
+







  sqlite3_value **argv
){
  const unsigned char *zA, *zB;
  u32 escape;
  int nPat;
  sqlite3 *db = sqlite3_context_db_handle(context);
  struct compareInfo *pInfo = sqlite3_user_data(context);
  struct compareInfo backupInfo;

#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
  if( sqlite3_value_type(argv[0])==SQLITE_BLOB
   || sqlite3_value_type(argv[1])==SQLITE_BLOB
  ){
#ifdef SQLITE_TEST
    sqlite3_like_count++;
#endif
    sqlite3_result_int(context, 0);
    return;
  }
#endif
  zB = sqlite3_value_text(argv[0]);
  zA = sqlite3_value_text(argv[1]);

  /* Limit the length of the LIKE or GLOB pattern to avoid problems
  ** of deep recursion and N*N behavior in patternCompare().
  */
  nPat = sqlite3_value_bytes(argv[0]);
  testcase( nPat==db->aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH] );
  testcase( nPat==db->aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]+1 );
  if( nPat > db->aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH] ){
    sqlite3_result_error(context, "LIKE or GLOB pattern too complex", -1);
    return;
  }
  assert( zB==sqlite3_value_text(argv[0]) );  /* Encoding did not change */

  if( argc==3 ){
    /* The escape character string must consist of a single UTF-8 character.
    ** Otherwise, return an error.
    */
    const unsigned char *zEsc = sqlite3_value_text(argv[2]);
    if( zEsc==0 ) return;
    if( sqlite3Utf8CharLen((char*)zEsc, -1)!=1 ){
      sqlite3_result_error(context, 
          "ESCAPE expression must be a single character", -1);
      return;
    }
    escape = sqlite3Utf8Read(&zEsc);
    if( escape==pInfo->matchAll || escape==pInfo->matchOne ){
      memcpy(&backupInfo, pInfo, sizeof(backupInfo));
      pInfo = &backupInfo;
      if( escape==pInfo->matchAll ) pInfo->matchAll = 0;
      if( escape==pInfo->matchOne ) pInfo->matchOne = 0;
    }
  }else{
    escape = pInfo->matchSet;
  }
  zB = sqlite3_value_text(argv[0]);
  zA = sqlite3_value_text(argv[1]);
  if( zA && zB ){
#ifdef SQLITE_TEST
    sqlite3_like_count++;
#endif
    sqlite3_result_int(context,
                      patternCompare(zB, zA, pInfo, escape)==SQLITE_MATCH);
  }
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
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
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







-
-
-
+
+
-
-

-
-
-
-
+
+
+
+
+
+
+


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



-
+



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









-
+
-




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



-
-
+
+




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







** digits. */
static const char hexdigits[] = {
  '0', '1', '2', '3', '4', '5', '6', '7',
  '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' 
};

/*
** Implementation of the QUOTE() function.  This function takes a single
** argument.  If the argument is numeric, the return value is the same as
** the argument.  If the argument is NULL, the return value is the string
** Append to pStr text that is the SQL literal representation of the
** value contained in pValue.
** "NULL".  Otherwise, the argument is enclosed in single quotes with
** single-quote escapes.
*/
static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
  assert( argc==1 );
  UNUSED_PARAMETER(argc);
  switch( sqlite3_value_type(argv[0]) ){
void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue){
  /* As currently implemented, the string must be initially empty.
  ** we might relax this requirement in the future, but that will
  ** require enhancements to the implementation. */
  assert( pStr!=0 && pStr->nChar==0 );

  switch( sqlite3_value_type(pValue) ){
    case SQLITE_FLOAT: {
      double r1, r2;
      char zBuf[50];
      r1 = sqlite3_value_double(argv[0]);
      sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.15g", r1);
      sqlite3AtoF(zBuf, &r2, 20, SQLITE_UTF8);
      if( r1!=r2 ){
        sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.20e", r1);
      }
      const char *zVal;
      r1 = sqlite3_value_double(pValue);
      sqlite3_str_appendf(pStr, "%!.15g", r1);
      zVal = sqlite3_str_value(pStr);
      if( zVal ){
        sqlite3AtoF(zVal, &r2, pStr->nChar, SQLITE_UTF8);
        if( r1!=r2 ){
          sqlite3_str_reset(pStr);
          sqlite3_str_appendf(pStr, "%!.20e", r1);
        }
      sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
      }
      break;
    }
    case SQLITE_INTEGER: {
      sqlite3_result_value(context, argv[0]);
      sqlite3_str_appendf(pStr, "%lld", sqlite3_value_int64(pValue));
      break;
    }
    case SQLITE_BLOB: {
      char *zText = 0;
      char const *zBlob = sqlite3_value_blob(argv[0]);
      int nBlob = sqlite3_value_bytes(argv[0]);
      assert( zBlob==sqlite3_value_blob(argv[0]) ); /* No encoding change */
      zText = (char *)contextMalloc(context, (2*(i64)nBlob)+4); 
      if( zText ){
      char const *zBlob = sqlite3_value_blob(pValue);
      i64 nBlob = sqlite3_value_bytes(pValue);
      assert( zBlob==sqlite3_value_blob(pValue) ); /* No encoding change */
      sqlite3StrAccumEnlarge(pStr, nBlob*2 + 4);
      if( pStr->accError==0 ){
        char *zText = pStr->zText;
        int i;
        for(i=0; i<nBlob; i++){
          zText[(i*2)+2] = hexdigits[(zBlob[i]>>4)&0x0F];
          zText[(i*2)+3] = hexdigits[(zBlob[i])&0x0F];
        }
        zText[(nBlob*2)+2] = '\'';
        zText[(nBlob*2)+3] = '\0';
        zText[0] = 'X';
        zText[1] = '\'';
        sqlite3_result_text(context, zText, -1, SQLITE_TRANSIENT);
        pStr->nChar = nBlob*2 + 3;
        sqlite3_free(zText);
      }
      break;
    }
    case SQLITE_TEXT: {
      int i,j;
      u64 n;
      const unsigned char *zArg = sqlite3_value_text(argv[0]);
      const unsigned char *zArg = sqlite3_value_text(pValue);
      char *z;

      sqlite3_str_appendf(pStr, "%Q", zArg);
      if( zArg==0 ) return;
      for(i=0, n=0; zArg[i]; i++){ if( zArg[i]=='\'' ) n++; }
      z = contextMalloc(context, ((i64)i)+((i64)n)+3);
      if( z ){
        z[0] = '\'';
        for(i=0, j=1; zArg[i]; i++){
          z[j++] = zArg[i];
          if( zArg[i]=='\'' ){
            z[j++] = '\'';
          }
        }
        z[j++] = '\'';
        z[j] = 0;
        sqlite3_result_text(context, z, j, sqlite3_free);
      }
      break;
    }
    default: {
      assert( sqlite3_value_type(argv[0])==SQLITE_NULL );
      sqlite3_result_text(context, "NULL", 4, SQLITE_STATIC);
      assert( sqlite3_value_type(pValue)==SQLITE_NULL );
      sqlite3_str_append(pStr, "NULL", 4);
      break;
    }
  }
}

/*
** Implementation of the QUOTE() function.  
**
** The quote(X) function returns the text of an SQL literal which is the
** value of its argument suitable for inclusion into an SQL statement.
** Strings are surrounded by single-quotes with escapes on interior quotes
** as needed. BLOBs are encoded as hexadecimal literals. Strings with
** embedded NUL characters cannot be represented as string literals in SQL
** and hence the returned string literal is truncated prior to the first NUL.
*/
static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
  sqlite3_str str;
  sqlite3 *db = sqlite3_context_db_handle(context);
  assert( argc==1 );
  UNUSED_PARAMETER(argc);
  sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
  sqlite3QuoteValue(&str,argv[0]);
  sqlite3_result_text(context, sqlite3StrAccumFinish(&str), str.nChar,
                      SQLITE_DYNAMIC);
  if( str.accError!=SQLITE_OK ){
    sqlite3_result_null(context);
    sqlite3_result_error_code(context, str.accError);
  }
}

/*
** The unicode() function.  Return the integer unicode code-point value
** for the first character of the input string. 
*/
static void unicodeFunc(
  sqlite3_context *context,
1155
1156
1157
1158
1159
1160
1161


























































































1162
1163
1164
1165
1166
1167
1168
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
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
1318
1319
1320
1321
1322
1323







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







      *(z++) = hexdigits[(c>>4)&0xf];
      *(z++) = hexdigits[c&0xf];
    }
    *z = 0;
    sqlite3_result_text(context, zHex, n*2, sqlite3_free);
  }
}

/*
** Buffer zStr contains nStr bytes of utf-8 encoded text. Return 1 if zStr
** contains character ch, or 0 if it does not.
*/
static int strContainsChar(const u8 *zStr, int nStr, u32 ch){
  const u8 *zEnd = &zStr[nStr];
  const u8 *z = zStr;
  while( z<zEnd ){
    u32 tst = Utf8Read(z);
    if( tst==ch ) return 1;
  }
  return 0;
}

/*
** The unhex() function. This function may be invoked with either one or
** two arguments. In both cases the first argument is interpreted as text
** a text value containing a set of pairs of hexadecimal digits which are
** decoded and returned as a blob.
**
** If there is only a single argument, then it must consist only of an
** even number of hexadeximal digits. Otherwise, return NULL.
**
** Or, if there is a second argument, then any character that appears in
** the second argument is also allowed to appear between pairs of hexadecimal
** digits in the first argument. If any other character appears in the
** first argument, or if one of the allowed characters appears between 
** two hexadecimal digits that make up a single byte, NULL is returned.
**
** The following expressions are all true:
**
**     unhex('ABCD')       IS x'ABCD'
**     unhex('AB CD')      IS NULL
**     unhex('AB CD', ' ') IS x'ABCD'
**     unhex('A BCD', ' ') IS NULL
*/
static void unhexFunc(
  sqlite3_context *pCtx,
  int argc,
  sqlite3_value **argv
){
  const u8 *zPass = (const u8*)"";
  int nPass = 0;
  const u8 *zHex = sqlite3_value_text(argv[0]);
  int nHex = sqlite3_value_bytes(argv[0]);
#ifdef SQLITE_DEBUG
  const u8 *zEnd = &zHex[nHex];
#endif
  u8 *pBlob = 0;
  u8 *p = 0;

  assert( argc==1 || argc==2 );
  if( argc==2 ){
    zPass = sqlite3_value_text(argv[1]);
    nPass = sqlite3_value_bytes(argv[1]);
  }
  if( !zHex || !zPass ) return;

  p = pBlob = contextMalloc(pCtx, (nHex/2)+1);
  if( pBlob ){
    u8 c;                         /* Most significant digit of next byte */
    u8 d;                         /* Least significant digit of next byte */

    while( (c = *zHex)!=0x00 ){
      while( !sqlite3Isxdigit(c) ){
        u32 ch = Utf8Read(zHex);
        assert( zHex<=zEnd );
        if( !strContainsChar(zPass, nPass, ch) ) goto unhex_null;
        c = *zHex;
        if( c==0x00 ) goto unhex_done;
      }
      zHex++;
      assert( *zEnd==0x00 );
      assert( zHex<=zEnd );
      d = *(zHex++);
      if( !sqlite3Isxdigit(d) ) goto unhex_null;
      *(p++) = (sqlite3HexToInt(c)<<4) | sqlite3HexToInt(d);
    }
  }

 unhex_done:
  sqlite3_result_blob(pCtx, pBlob, (p - pBlob), sqlite3_free);
  return;

 unhex_null:
  sqlite3_free(pBlob);
  return;
}


/*
** The zeroblob(N) function returns a zero-filled blob of size N bytes.
*/
static void zeroblobFunc(
  sqlite3_context *context,
  int argc,
1250
1251
1252
1253
1254
1255
1256
1257

1258
1259
1260
1261
1262
1263
1264
1405
1406
1407
1408
1409
1410
1411

1412
1413
1414
1415
1416
1417
1418
1419







-
+







        }
        cntExpand++;
        if( (cntExpand&(cntExpand-1))==0 ){
          /* Grow the size of the output buffer only on substitutions
          ** whose index is a power of two: 1, 2, 4, 8, 16, 32, ... */
          u8 *zOld;
          zOld = zOut;
          zOut = sqlite3_realloc64(zOut, (int)nOut + (nOut - nStr - 1));
          zOut = sqlite3Realloc(zOut, (int)nOut + (nOut - nStr - 1));
          if( zOut==0 ){
            sqlite3_result_error_nomem(context);
            sqlite3_free(zOld);
            return;
          }
        }
      }
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
1318


1319
1320
1321
1322

1323
1324
1325
1326

1327
1328
1329
1330
1331
1332
1333
1334

1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346

1347
1348
1349
1350
1351
1352
1353
1437
1438
1439
1440
1441
1442
1443

1444
1445
1446

1447
1448
1449
1450
1451
1452
1453
1454
1455

1456
1457
1458

1459
1460
1461

1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472

1473
1474
1475
1476
1477

1478
1479
1480
1481

1482
1483
1484
1485
1486
1487
1488
1489

1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501

1502
1503
1504
1505
1506
1507
1508
1509







-
+


-
+








-
+


-
+


-
+










-
+
+



-
+



-
+







-
+











-
+







static void trimFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const unsigned char *zIn;         /* Input string */
  const unsigned char *zCharSet;    /* Set of characters to trim */
  int nIn;                          /* Number of bytes in input */
  unsigned int nIn;                 /* Number of bytes in input */
  int flags;                        /* 1: trimleft  2: trimright  3: trim */
  int i;                            /* Loop counter */
  unsigned char *aLen = 0;          /* Length of each character in zCharSet */
  unsigned int *aLen = 0;           /* Length of each character in zCharSet */
  unsigned char **azChar = 0;       /* Individual characters in zCharSet */
  int nChar;                        /* Number of characters in zCharSet */

  if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
    return;
  }
  zIn = sqlite3_value_text(argv[0]);
  if( zIn==0 ) return;
  nIn = sqlite3_value_bytes(argv[0]);
  nIn = (unsigned)sqlite3_value_bytes(argv[0]);
  assert( zIn==sqlite3_value_text(argv[0]) );
  if( argc==1 ){
    static const unsigned char lenOne[] = { 1 };
    static const unsigned lenOne[] = { 1 };
    static unsigned char * const azOne[] = { (u8*)" " };
    nChar = 1;
    aLen = (u8*)lenOne;
    aLen = (unsigned*)lenOne;
    azChar = (unsigned char **)azOne;
    zCharSet = 0;
  }else if( (zCharSet = sqlite3_value_text(argv[1]))==0 ){
    return;
  }else{
    const unsigned char *z;
    for(z=zCharSet, nChar=0; *z; nChar++){
      SQLITE_SKIP_UTF8(z);
    }
    if( nChar>0 ){
      azChar = contextMalloc(context, ((i64)nChar)*(sizeof(char*)+1));
      azChar = contextMalloc(context, 
                     ((i64)nChar)*(sizeof(char*)+sizeof(unsigned)));
      if( azChar==0 ){
        return;
      }
      aLen = (unsigned char*)&azChar[nChar];
      aLen = (unsigned*)&azChar[nChar];
      for(z=zCharSet, nChar=0; *z; nChar++){
        azChar[nChar] = (unsigned char *)z;
        SQLITE_SKIP_UTF8(z);
        aLen[nChar] = (u8)(z - azChar[nChar]);
        aLen[nChar] = (unsigned)(z - azChar[nChar]);
      }
    }
  }
  if( nChar>0 ){
    flags = SQLITE_PTR_TO_INT(sqlite3_user_data(context));
    if( flags & 1 ){
      while( nIn>0 ){
        int len = 0;
        unsigned int len = 0;
        for(i=0; i<nChar; i++){
          len = aLen[i];
          if( len<=nIn && memcmp(zIn, azChar[i], len)==0 ) break;
        }
        if( i>=nChar ) break;
        zIn += len;
        nIn -= len;
      }
    }
    if( flags & 2 ){
      while( nIn>0 ){
        int len = 0;
        unsigned int len = 0;
        for(i=0; i<nChar; i++){
          len = aLen[i];
          if( len<=nIn && memcmp(&zIn[nIn-len],azChar[i],len)==0 ) break;
        }
        if( i>=nChar ) break;
        nIn -= len;
      }
1372
1373
1374
1375
1376
1377
1378



1379
1380
1381
1382
1383
1384
1385
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544







+
+
+







*/
static void unknownFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  /* no-op */
  (void)context;
  (void)argc;
  (void)argv;
}
#endif /*SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION*/


/* IMP: R-25361-16150 This function is omitted from SQLite by default. It
** is only available if the SQLITE_SOUNDEX compile-time option is used
** when SQLite is built.
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
1744


1745

1746




1747
1748
1749
1750
1751
1752
1753
1754
1755



1756
1757
1758


1759
1760
1761
1762

1763

1764
1765
1766
1767
1768
1769
1770




1771
1772
1773
1774
1775
1776
1777

1778
1779
1780
1781
1782
1783
1784
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872

1873
1874
1875
1876
1877

1878


1879
1880











1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932

1933
1934
1935
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
1984



1985
1986
1987



1988
1989




1990

1991
1992
1993
1994
1995



1996
1997
1998
1999
2000
2001
2002
2003
2004
2005

2006
2007
2008
2009
2010
2011
2012
2013







+
+
+
+
+
+

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






-
+




-
+
-
-
+

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

+
+


-
+


+






-
-
+

+

-
-
+
+

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

-
+
+

-
-
+
+

-
-
+
+

+
-
+
+
+
+






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




-
-
-
+
+
+
+






-
+







#endif /* SQLITE_OMIT_WINDOWFUNC */
static void minMaxFinalize(sqlite3_context *context){
  minMaxValueFinalize(context, 0);
}

/*
** group_concat(EXPR, ?SEPARATOR?)
**
** The SEPARATOR goes before the EXPR string.  This is tragic.  The
** groupConcatInverse() implementation would have been easier if the
** SEPARATOR were appended after EXPR.  And the order is undocumented,
** so we could change it, in theory.  But the old behavior has been
** around for so long that we dare not, for fear of breaking something.
*/
typedef struct {
  StrAccum str;          /* The accumulated concatenation */
#ifndef SQLITE_OMIT_WINDOWFUNC
  int nAccum;            /* Number of strings presently concatenated */
  int nFirstSepLength;   /* Used to detect separator length change */
  /* If pnSepLengths!=0, refs an array of inter-string separator lengths,
  ** stored as actually incorporated into presently accumulated result.
  ** (Hence, its slots in use number nAccum-1 between method calls.)
  ** If pnSepLengths==0, nFirstSepLength is the length used throughout.
  */
  int *pnSepLengths;
#endif
} GroupConcatCtx;

static void groupConcatStep(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const char *zVal;
  StrAccum *pAccum;
  GroupConcatCtx *pGCC;
  const char *zSep;
  int nVal, nSep;
  assert( argc==1 || argc==2 );
  if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
  pAccum = (StrAccum*)sqlite3_aggregate_context(context, sizeof(*pAccum));
  pGCC = (GroupConcatCtx*)sqlite3_aggregate_context(context, sizeof(*pGCC));

  if( pAccum ){
  if( pGCC ){
    sqlite3 *db = sqlite3_context_db_handle(context);
    int firstTerm = pAccum->mxAlloc==0;
    pAccum->mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH];
    if( !firstTerm ){
      if( argc==2 ){
        zSep = (char*)sqlite3_value_text(argv[1]);
        nSep = sqlite3_value_bytes(argv[1]);
      }else{
        zSep = ",";
        nSep = 1;
      }
      if( zSep ) sqlite3_str_append(pAccum, zSep, nSep);
    int firstTerm = pGCC->str.mxAlloc==0;
    pGCC->str.mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH];
    if( argc==1 ){
      if( !firstTerm ){
        sqlite3_str_appendchar(&pGCC->str, 1, ',');
      }
#ifndef SQLITE_OMIT_WINDOWFUNC
      else{
        pGCC->nFirstSepLength = 1;
      }
#endif
    }else if( !firstTerm ){
      zSep = (char*)sqlite3_value_text(argv[1]);
      nSep = sqlite3_value_bytes(argv[1]);
      if( zSep ){
        sqlite3_str_append(&pGCC->str, zSep, nSep);
      }
#ifndef SQLITE_OMIT_WINDOWFUNC
      else{
        nSep = 0;
      }
      if( nSep != pGCC->nFirstSepLength || pGCC->pnSepLengths != 0 ){
        int *pnsl = pGCC->pnSepLengths;
        if( pnsl == 0 ){
          /* First separator length variation seen, start tracking them. */
          pnsl = (int*)sqlite3_malloc64((pGCC->nAccum+1) * sizeof(int));
          if( pnsl!=0 ){
            int i = 0, nA = pGCC->nAccum-1;
            while( i<nA ) pnsl[i++] = pGCC->nFirstSepLength;
          }
        }else{
          pnsl = (int*)sqlite3_realloc64(pnsl, pGCC->nAccum * sizeof(int));
        }
        if( pnsl!=0 ){
          if( ALWAYS(pGCC->nAccum>0) ){
            pnsl[pGCC->nAccum-1] = nSep;
          }
          pGCC->pnSepLengths = pnsl;
        }else{
          sqlite3StrAccumSetError(&pGCC->str, SQLITE_NOMEM);
        }
      }
#endif
    }
#ifndef SQLITE_OMIT_WINDOWFUNC
    else{
      pGCC->nFirstSepLength = sqlite3_value_bytes(argv[1]);
    }
    pGCC->nAccum += 1;
#endif
    zVal = (char*)sqlite3_value_text(argv[0]);
    nVal = sqlite3_value_bytes(argv[0]);
    if( zVal ) sqlite3_str_append(pAccum, zVal, nVal);
    if( zVal ) sqlite3_str_append(&pGCC->str, zVal, nVal);
  }
}

#ifndef SQLITE_OMIT_WINDOWFUNC
static void groupConcatInverse(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  int n;
  StrAccum *pAccum;
  GroupConcatCtx *pGCC;
  assert( argc==1 || argc==2 );
  (void)argc;  /* Suppress unused parameter warning */
  if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
  pAccum = (StrAccum*)sqlite3_aggregate_context(context, sizeof(*pAccum));
  /* pAccum is always non-NULL since groupConcatStep() will have always
  pGCC = (GroupConcatCtx*)sqlite3_aggregate_context(context, sizeof(*pGCC));
  /* pGCC is always non-NULL since groupConcatStep() will have always
  ** run frist to initialize it */
  if( ALWAYS(pAccum) ){
    n = sqlite3_value_bytes(argv[0]);
    if( argc==2 ){
      n += sqlite3_value_bytes(argv[1]);
  if( ALWAYS(pGCC) ){
    int nVS;
    /* Must call sqlite3_value_text() to convert the argument into text prior
    ** to invoking sqlite3_value_bytes(), in case the text encoding is UTF16 */
    (void)sqlite3_value_text(argv[0]);
    nVS = sqlite3_value_bytes(argv[0]);
    pGCC->nAccum -= 1;
    if( pGCC->pnSepLengths!=0 ){
      assert(pGCC->nAccum >= 0);
      if( pGCC->nAccum>0 ){
        nVS += *pGCC->pnSepLengths;
        memmove(pGCC->pnSepLengths, pGCC->pnSepLengths+1,
               (pGCC->nAccum-1)*sizeof(int));
      }
    }else{
      n++;
      /* If removing single accumulated string, harmlessly over-do. */
      nVS += pGCC->nFirstSepLength;
    }
    if( n>=(int)pAccum->nChar ){
      pAccum->nChar = 0;
    if( nVS>=(int)pGCC->str.nChar ){
      pGCC->str.nChar = 0;
    }else{
      pAccum->nChar -= n;
      memmove(pAccum->zText, &pAccum->zText[n], pAccum->nChar);
      pGCC->str.nChar -= nVS;
      memmove(pGCC->str.zText, &pGCC->str.zText[nVS], pGCC->str.nChar);
    }
    if( pGCC->str.nChar==0 ){
    if( pAccum->nChar==0 ) pAccum->mxAlloc = 0;
      pGCC->str.mxAlloc = 0;
      sqlite3_free(pGCC->pnSepLengths);
      pGCC->pnSepLengths = 0;
    }
  }
}
#else
# define groupConcatInverse 0
#endif /* SQLITE_OMIT_WINDOWFUNC */
static void groupConcatFinalize(sqlite3_context *context){
  StrAccum *pAccum;
  pAccum = sqlite3_aggregate_context(context, 0);
  if( pAccum ){
  GroupConcatCtx *pGCC
    = (GroupConcatCtx*)sqlite3_aggregate_context(context, 0);
  if( pGCC ){
    if( pAccum->accError==SQLITE_TOOBIG ){
      sqlite3_result_error_toobig(context);
    }else if( pAccum->accError==SQLITE_NOMEM ){
    sqlite3ResultStrAccum(context, &pGCC->str);
#ifndef SQLITE_OMIT_WINDOWFUNC
      sqlite3_result_error_nomem(context);
    }else{    
      sqlite3_result_text(context, sqlite3StrAccumFinish(pAccum), -1, 
                          sqlite3_free);
    sqlite3_free(pGCC->pnSepLengths);
    }
#endif
  }
}
#ifndef SQLITE_OMIT_WINDOWFUNC
static void groupConcatValue(sqlite3_context *context){
  sqlite3_str *pAccum;
  pAccum = (sqlite3_str*)sqlite3_aggregate_context(context, 0);
  if( pAccum ){
  GroupConcatCtx *pGCC
    = (GroupConcatCtx*)sqlite3_aggregate_context(context, 0);
  if( pGCC ){
    StrAccum *pAccum = &pGCC->str;
    if( pAccum->accError==SQLITE_TOOBIG ){
      sqlite3_result_error_toobig(context);
    }else if( pAccum->accError==SQLITE_NOMEM ){
      sqlite3_result_error_nomem(context);
    }else{    
      const char *zText = sqlite3_str_value(pAccum);
      sqlite3_result_text(context, zText, -1, SQLITE_TRANSIENT);
      sqlite3_result_text(context, zText, pAccum->nChar, SQLITE_TRANSIENT);
    }
  }
}
#else
# define groupConcatValue 0
#endif /* SQLITE_OMIT_WINDOWFUNC */

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
2021
2022
2023
2024
2025
2026
2027












2028
2029

2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043

2044



2045

2046
2047
2048
2049
2050
2051
2052







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

-
+



+


+


+



-
+
-
-
-
+
-







  assert( rc==SQLITE_NOMEM || rc==SQLITE_OK );
  if( rc==SQLITE_NOMEM ){
    sqlite3OomFault(db);
  }
}

/*
** Set the LIKEOPT flag on the 2-argument function with the given name.
*/
static void setLikeOptFlag(sqlite3 *db, const char *zName, u8 flagVal){
  FuncDef *pDef;
  pDef = sqlite3FindFunction(db, zName, 2, SQLITE_UTF8, 0);
  if( ALWAYS(pDef) ){
    pDef->funcFlags |= flagVal;
  }
}

/*
** Register the built-in LIKE and GLOB functions.  The caseSensitive
** Re-register the built-in LIKE functions.  The caseSensitive
** parameter determines whether or not the LIKE operator is case
** sensitive.  GLOB is always case sensitive.
** sensitive.
*/
void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){
  struct compareInfo *pInfo;
  int flags;
  if( caseSensitive ){
    pInfo = (struct compareInfo*)&likeInfoAlt;
    flags = SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE;
  }else{
    pInfo = (struct compareInfo*)&likeInfoNorm;
    flags = SQLITE_FUNC_LIKE;
  }
  sqlite3CreateFunc(db, "like", 2, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0, 0, 0);
  sqlite3CreateFunc(db, "like", 3, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0, 0, 0);
  sqlite3CreateFunc(db, "glob", 2, SQLITE_UTF8, 
  sqlite3FindFunction(db, "like", 2, SQLITE_UTF8, 0)->funcFlags |= flags;
      (struct compareInfo*)&globInfo, likeFunc, 0, 0, 0, 0, 0);
  setLikeOptFlag(db, "glob", SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE);
  setLikeOptFlag(db, "like", 
  sqlite3FindFunction(db, "like", 3, SQLITE_UTF8, 0)->funcFlags |= flags;
      caseSensitive ? (SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE) : SQLITE_FUNC_LIKE);
}

/*
** pExpr points to an expression which implements a function.  If
** it is appropriate to apply the LIKE optimization to that function
** then set aWc[0] through aWc[2] to the wildcard characters and the
** escape character and then return TRUE.  If the function is not a 
1843
1844
1845
1846
1847
1848
1849



1850

1851
1852
1853
1854

1855



1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877















1878
1879
1880


































































































































































































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








1901
1902
1903
1904
1905
1906


1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917



1918
1919
1920
1921
1922

1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934

1935
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
1984
1985
1986
1987
1988
1989
1990
1991
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
2017
2018
2019
2020
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
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
2199
2200
2201
2202
2203
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
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335


2336
2337
2338
2339
2340
2341
2342
2343
2344
2345



2346
2347
2348



2349

2350

2351
2352
2353
2354
2355
2356
2357
2358
2359
2360

2361
2362
2363
2364

2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383

2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404

2405
2406
2407

2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
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
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491







+
+
+
-
+


-

+

+
+
+


-
-
-
-
-
-
-
-
-
-










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



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




















+
+
+
+
+
+
+
+




-
-
+
+








-
-
-
+
+
+
-
-
-

-
+
-










-
+



-
+

+



+










+
+
-
+














+
+




-
+
+

-
+


















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





-
-
-

+











+







** the function (default for LIKE).  If the function makes the distinction
** between uppercase and lowercase (as does GLOB) then *pIsNocase is set to
** false.
*/
int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
  FuncDef *pDef;
  int nExpr;
  assert( pExpr!=0 );
  assert( pExpr->op==TK_FUNCTION );
  assert( ExprUseXList(pExpr) );
  if( pExpr->op!=TK_FUNCTION || !pExpr->x.pList ){
  if( !pExpr->x.pList ){
    return 0;
  }
  assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
  nExpr = pExpr->x.pList->nExpr;
  assert( !ExprHasProperty(pExpr, EP_IntValue) );
  pDef = sqlite3FindFunction(db, pExpr->u.zToken, nExpr, SQLITE_UTF8, 0);
#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
  if( pDef==0 ) return 0;
#endif
  if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_FUNC_LIKE)==0 ){
    return 0;
  }
  if( nExpr<3 ){
    aWc[3] = 0;
  }else{
    Expr *pEscape = pExpr->x.pList->a[2].pExpr;
    char *zEscape;
    if( pEscape->op!=TK_STRING ) return 0;
    zEscape = pEscape->u.zToken;
    if( zEscape[0]==0 || zEscape[1]!=0 ) return 0;
    aWc[3] = zEscape[0];
  }

  /* The memcpy() statement assumes that the wildcard characters are
  ** the first three statements in the compareInfo structure.  The
  ** asserts() that follow verify that assumption
  */
  memcpy(aWc, pDef->pUserData, 3);
  assert( (char*)&likeInfoAlt == (char*)&likeInfoAlt.matchAll );
  assert( &((char*)&likeInfoAlt)[1] == (char*)&likeInfoAlt.matchOne );
  assert( &((char*)&likeInfoAlt)[2] == (char*)&likeInfoAlt.matchSet );

  if( nExpr<3 ){
    aWc[3] = 0;
  }else{
    Expr *pEscape = pExpr->x.pList->a[2].pExpr;
    char *zEscape;
    if( pEscape->op!=TK_STRING ) return 0;
    assert( !ExprHasProperty(pEscape, EP_IntValue) );
    zEscape = pEscape->u.zToken;
    if( zEscape[0]==0 || zEscape[1]!=0 ) return 0;
    if( zEscape[0]==aWc[0] ) return 0;
    if( zEscape[0]==aWc[1] ) return 0;
    aWc[3] = zEscape[0];
  }

  *pIsNocase = (pDef->funcFlags & SQLITE_FUNC_CASE)==0;
  return 1;
}

/* Mathematical Constants */
#ifndef M_PI
# define M_PI   3.141592653589793238462643383279502884
#endif
#ifndef M_LN10
# define M_LN10 2.302585092994045684017991454684364208
#endif
#ifndef M_LN2
# define M_LN2  0.693147180559945309417232121458176568
#endif


/* Extra math functions that require linking with -lm
*/
#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
/*
** Implementation SQL functions:
**
**   ceil(X)
**   ceiling(X)
**   floor(X)
**
** The sqlite3_user_data() pointer is a pointer to the libm implementation
** of the underlying C function.
*/
static void ceilingFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  assert( argc==1 );
  switch( sqlite3_value_numeric_type(argv[0]) ){
    case SQLITE_INTEGER: {
       sqlite3_result_int64(context, sqlite3_value_int64(argv[0]));
       break;
    }
    case SQLITE_FLOAT: {
       double (*x)(double) = (double(*)(double))sqlite3_user_data(context);
       sqlite3_result_double(context, x(sqlite3_value_double(argv[0])));
       break;
    }
    default: {
       break;
    }
  }
}

/*
** On some systems, ceil() and floor() are intrinsic function.  You are
** unable to take a pointer to these functions.  Hence, we here wrap them
** in our own actual functions.
*/
static double xCeil(double x){ return ceil(x); }
static double xFloor(double x){ return floor(x); }

/*
** Implementation of SQL functions:
**
**   ln(X)       - natural logarithm
**   log(X)      - log X base 10
**   log10(X)    - log X base 10
**   log(B,X)    - log X base B
*/
static void logFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  double x, b, ans;
  assert( argc==1 || argc==2 );
  switch( sqlite3_value_numeric_type(argv[0]) ){
    case SQLITE_INTEGER:
    case SQLITE_FLOAT:
      x = sqlite3_value_double(argv[0]);
      if( x<=0.0 ) return;
      break;
    default:
      return;
  }
  if( argc==2 ){
    switch( sqlite3_value_numeric_type(argv[0]) ){
      case SQLITE_INTEGER:
      case SQLITE_FLOAT:
        b = log(x);
        if( b<=0.0 ) return;
        x = sqlite3_value_double(argv[1]);
        if( x<=0.0 ) return;
        break;
     default:
        return;
    }
    ans = log(x)/b;
  }else{
    switch( SQLITE_PTR_TO_INT(sqlite3_user_data(context)) ){
      case 1:
        ans = log10(x);
        break;
      case 2:
        ans = log2(x);
        break;
      default:
        ans = log(x);
        break;
    }
  }
  sqlite3_result_double(context, ans);
}

/*
** Functions to converts degrees to radians and radians to degrees.
*/
static double degToRad(double x){ return x*(M_PI/180.0); }
static double radToDeg(double x){ return x*(180.0/M_PI); }

/*
** Implementation of 1-argument SQL math functions:
**
**   exp(X)  - Compute e to the X-th power
*/
static void math1Func(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  int type0;
  double v0, ans;
  double (*x)(double);
  assert( argc==1 );
  type0 = sqlite3_value_numeric_type(argv[0]);
  if( type0!=SQLITE_INTEGER && type0!=SQLITE_FLOAT ) return;
  v0 = sqlite3_value_double(argv[0]);
  x = (double(*)(double))sqlite3_user_data(context);
  ans = x(v0);
  sqlite3_result_double(context, ans);
}

/*
** Implementation of 2-argument SQL math functions:
**
**   power(X,Y)  - Compute X to the Y-th power
*/
static void math2Func(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  int type0, type1;
  double v0, v1, ans;
  double (*x)(double,double);
  assert( argc==2 );
  type0 = sqlite3_value_numeric_type(argv[0]);
  if( type0!=SQLITE_INTEGER && type0!=SQLITE_FLOAT ) return;
  type1 = sqlite3_value_numeric_type(argv[1]);
  if( type1!=SQLITE_INTEGER && type1!=SQLITE_FLOAT ) return;
  v0 = sqlite3_value_double(argv[0]);
  v1 = sqlite3_value_double(argv[1]);
  x = (double(*)(double,double))sqlite3_user_data(context);
  ans = x(v0, v1);
  sqlite3_result_double(context, ans);
}

/*
** Implementation of 0-argument pi() function.
*/
static void piFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  assert( argc==0 );
  (void)argv;
  sqlite3_result_double(context, M_PI);
}

#endif /* SQLITE_ENABLE_MATH_FUNCTIONS */

/*
** Implementation of sign(X) function.
*/
static void signFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  int type0;
  double x;
  UNUSED_PARAMETER(argc);
  assert( argc==1 );
  type0 = sqlite3_value_numeric_type(argv[0]);
  if( type0!=SQLITE_INTEGER && type0!=SQLITE_FLOAT ) return;
  x = sqlite3_value_double(argv[0]);
  sqlite3_result_int(context, x<0.0 ? -1 : x>0.0 ? +1 : 0);
}

/*
** All of the FuncDef structures in the aBuiltinFunc[] array above
** to the global function hash table.  This occurs at start-time (as
** a consequence of calling sqlite3_initialize()).
**
** After this routine runs
*/
void sqlite3RegisterBuiltinFunctions(void){
  /*
  ** The following array holds FuncDef structures for all of the functions
  ** defined in this file.
  **
  ** The array cannot be constant since changes are made to the
  ** FuncDef.pHash elements at start-time.  The elements of this array
  ** are read-only after initialization is complete.
  **
  ** For peak efficiency, put the most frequently used function last.
  */
  static FuncDef aBuiltinFunc[] = {
/***** Functions only available with SQLITE_TESTCTRL_INTERNAL_FUNCTIONS *****/
#if !defined(SQLITE_UNTESTABLE)
    TEST_FUNC(implies_nonnull_row, 2, INLINEFUNC_implies_nonnull_row, 0),
    TEST_FUNC(expr_compare,        2, INLINEFUNC_expr_compare,        0),
    TEST_FUNC(expr_implies_expr,   2, INLINEFUNC_expr_implies_expr,   0),
    TEST_FUNC(affinity,            1, INLINEFUNC_affinity,            0),
#endif /* !defined(SQLITE_UNTESTABLE) */
/***** Regular functions *****/
#ifdef SQLITE_SOUNDEX
    FUNCTION(soundex,            1, 0, 0, soundexFunc      ),
#endif
#ifndef SQLITE_OMIT_LOAD_EXTENSION
    VFUNCTION(load_extension,    1, 0, 0, loadExt          ),
    VFUNCTION(load_extension,    2, 0, 0, loadExt          ),
    SFUNCTION(load_extension,    1, 0, 0, loadExt          ),
    SFUNCTION(load_extension,    2, 0, 0, loadExt          ),
#endif
#if SQLITE_USER_AUTHENTICATION
    FUNCTION(sqlite_crypt,       2, 0, 0, sqlite3CryptFunc ),
#endif
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
    DFUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc  ),
    DFUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc  ),
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
    FUNCTION2(unlikely,          1, 0, 0, noopFunc,  SQLITE_FUNC_UNLIKELY),
    FUNCTION2(likelihood,        2, 0, 0, noopFunc,  SQLITE_FUNC_UNLIKELY),
    FUNCTION2(likely,            1, 0, 0, noopFunc,  SQLITE_FUNC_UNLIKELY),
    INLINE_FUNC(unlikely,        1, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY),
    INLINE_FUNC(likelihood,      2, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY),
    INLINE_FUNC(likely,          1, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY),
#ifdef SQLITE_DEBUG
    FUNCTION2(affinity,          1, 0, 0, noopFunc,  SQLITE_FUNC_AFFINITY),
#endif
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
    FUNCTION2(sqlite_offset,     1, 0, 0, noopFunc,  SQLITE_FUNC_OFFSET|
    INLINE_FUNC(sqlite_offset,   1, INLINEFUNC_sqlite_offset, 0 ),
                                                     SQLITE_FUNC_TYPEOF),
#endif
    FUNCTION(ltrim,              1, 1, 0, trimFunc         ),
    FUNCTION(ltrim,              2, 1, 0, trimFunc         ),
    FUNCTION(rtrim,              1, 2, 0, trimFunc         ),
    FUNCTION(rtrim,              2, 2, 0, trimFunc         ),
    FUNCTION(trim,               1, 3, 0, trimFunc         ),
    FUNCTION(trim,               2, 3, 0, trimFunc         ),
    FUNCTION(min,               -1, 0, 1, minmaxFunc       ),
    FUNCTION(min,                0, 0, 1, 0                ),
    WAGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize, minMaxValue, 0,
                                          SQLITE_FUNC_MINMAX ),
                                 SQLITE_FUNC_MINMAX|SQLITE_FUNC_ANYORDER ),
    FUNCTION(max,               -1, 1, 1, minmaxFunc       ),
    FUNCTION(max,                0, 1, 1, 0                ),
    WAGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize, minMaxValue, 0,
                                          SQLITE_FUNC_MINMAX ),
                                 SQLITE_FUNC_MINMAX|SQLITE_FUNC_ANYORDER ),
    FUNCTION2(typeof,            1, 0, 0, typeofFunc,  SQLITE_FUNC_TYPEOF),
    FUNCTION2(subtype,           1, 0, 0, subtypeFunc, SQLITE_FUNC_TYPEOF),
    FUNCTION2(length,            1, 0, 0, lengthFunc,  SQLITE_FUNC_LENGTH),
    FUNCTION(instr,              2, 0, 0, instrFunc        ),
    FUNCTION(printf,            -1, 0, 0, printfFunc       ),
    FUNCTION(format,            -1, 0, 0, printfFunc       ),
    FUNCTION(unicode,            1, 0, 0, unicodeFunc      ),
    FUNCTION(char,              -1, 0, 0, charFunc         ),
    FUNCTION(abs,                1, 0, 0, absFunc          ),
#ifndef SQLITE_OMIT_FLOATING_POINT
    FUNCTION(round,              1, 0, 0, roundFunc        ),
    FUNCTION(round,              2, 0, 0, roundFunc        ),
#endif
    FUNCTION(upper,              1, 0, 0, upperFunc        ),
    FUNCTION(lower,              1, 0, 0, lowerFunc        ),
    FUNCTION(hex,                1, 0, 0, hexFunc          ),
    FUNCTION(unhex,              1, 0, 0, unhexFunc        ),
    FUNCTION(unhex,              2, 0, 0, unhexFunc        ),
    FUNCTION2(ifnull,            2, 0, 0, noopFunc,  SQLITE_FUNC_COALESCE),
    INLINE_FUNC(ifnull,          2, INLINEFUNC_coalesce, 0 ),
    VFUNCTION(random,            0, 0, 0, randomFunc       ),
    VFUNCTION(randomblob,        1, 0, 0, randomBlob       ),
    FUNCTION(nullif,             2, 0, 1, nullifFunc       ),
    DFUNCTION(sqlite_version,    0, 0, 0, versionFunc      ),
    DFUNCTION(sqlite_source_id,  0, 0, 0, sourceidFunc     ),
    FUNCTION(sqlite_log,         2, 0, 0, errlogFunc       ),
    FUNCTION(quote,              1, 0, 0, quoteFunc        ),
    VFUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid),
    VFUNCTION(changes,           0, 0, 0, changes          ),
    VFUNCTION(total_changes,     0, 0, 0, total_changes    ),
    FUNCTION(replace,            3, 0, 0, replaceFunc      ),
    FUNCTION(zeroblob,           1, 0, 0, zeroblobFunc     ),
    FUNCTION(substr,             2, 0, 0, substrFunc       ),
    FUNCTION(substr,             3, 0, 0, substrFunc       ),
    FUNCTION(substring,          2, 0, 0, substrFunc       ),
    FUNCTION(substring,          3, 0, 0, substrFunc       ),
    WAGGREGATE(sum,   1,0,0, sumStep, sumFinalize, sumFinalize, sumInverse, 0),
    WAGGREGATE(total, 1,0,0, sumStep,totalFinalize,totalFinalize,sumInverse, 0),
    WAGGREGATE(avg,   1,0,0, sumStep, avgFinalize, avgFinalize, sumInverse, 0),
    WAGGREGATE(count, 0,0,0, countStep, 
        countFinalize, countFinalize, countInverse, SQLITE_FUNC_COUNT  ),
        countFinalize, countFinalize, countInverse,
        SQLITE_FUNC_COUNT|SQLITE_FUNC_ANYORDER  ),
    WAGGREGATE(count, 1,0,0, countStep, 
        countFinalize, countFinalize, countInverse, 0  ),
        countFinalize, countFinalize, countInverse, SQLITE_FUNC_ANYORDER ),
    WAGGREGATE(group_concat, 1, 0, 0, groupConcatStep, 
        groupConcatFinalize, groupConcatValue, groupConcatInverse, 0),
    WAGGREGATE(group_concat, 2, 0, 0, groupConcatStep, 
        groupConcatFinalize, groupConcatValue, groupConcatInverse, 0),
  
    LIKEFUNC(glob, 2, &globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
#ifdef SQLITE_CASE_SENSITIVE_LIKE
    LIKEFUNC(like, 2, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
    LIKEFUNC(like, 3, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
#else
    LIKEFUNC(like, 2, &likeInfoNorm, SQLITE_FUNC_LIKE),
    LIKEFUNC(like, 3, &likeInfoNorm, SQLITE_FUNC_LIKE),
#endif
#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
    FUNCTION(unknown,           -1, 0, 0, unknownFunc      ),
#endif
    FUNCTION(coalesce,           1, 0, 0, 0                ),
    FUNCTION(coalesce,           0, 0, 0, 0                ),
#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
    MFUNCTION(ceil,              1, xCeil,     ceilingFunc ),
    MFUNCTION(ceiling,           1, xCeil,     ceilingFunc ),
    MFUNCTION(floor,             1, xFloor,    ceilingFunc ),
#if SQLITE_HAVE_C99_MATH_FUNCS
    MFUNCTION(trunc,             1, trunc,     ceilingFunc ),
#endif
    FUNCTION(ln,                 1, 0, 0,      logFunc     ),
    FUNCTION(log,                1, 1, 0,      logFunc     ),
    FUNCTION(log10,              1, 1, 0,      logFunc     ),
    FUNCTION(log2,               1, 2, 0,      logFunc     ),
    FUNCTION(log,                2, 0, 0,      logFunc     ),
    MFUNCTION(exp,               1, exp,       math1Func   ),
    MFUNCTION(pow,               2, pow,       math2Func   ),
    MFUNCTION(power,             2, pow,       math2Func   ),
    MFUNCTION(mod,               2, fmod,      math2Func   ),
    MFUNCTION(acos,              1, acos,      math1Func   ),
    MFUNCTION(asin,              1, asin,      math1Func   ),
    MFUNCTION(atan,              1, atan,      math1Func   ),
    MFUNCTION(atan2,             2, atan2,     math2Func   ),
    MFUNCTION(cos,               1, cos,       math1Func   ),
    MFUNCTION(sin,               1, sin,       math1Func   ),
    MFUNCTION(tan,               1, tan,       math1Func   ),
    MFUNCTION(cosh,              1, cosh,      math1Func   ),
    MFUNCTION(sinh,              1, sinh,      math1Func   ),
    MFUNCTION(tanh,              1, tanh,      math1Func   ),
#if SQLITE_HAVE_C99_MATH_FUNCS
    MFUNCTION(acosh,             1, acosh,     math1Func   ),
    MFUNCTION(asinh,             1, asinh,     math1Func   ),
    MFUNCTION(atanh,             1, atanh,     math1Func   ),
#endif
    MFUNCTION(sqrt,              1, sqrt,      math1Func   ),
    MFUNCTION(radians,           1, degToRad,  math1Func   ),
    MFUNCTION(degrees,           1, radToDeg,  math1Func   ),
    FUNCTION(pi,                 0, 0, 0,      piFunc      ),
#endif /* SQLITE_ENABLE_MATH_FUNCTIONS */
    FUNCTION(sign,               1, 0, 0,      signFunc    ),
    FUNCTION2(coalesce,         -1, 0, 0, noopFunc,  SQLITE_FUNC_COALESCE),
    INLINE_FUNC(coalesce,       -1, INLINEFUNC_coalesce, 0 ),
    INLINE_FUNC(iif,             3, INLINEFUNC_iif,      0 ),
  };
#ifndef SQLITE_OMIT_ALTERTABLE
  sqlite3AlterFunctions();
#endif
  sqlite3WindowFunctions();
#if defined(SQLITE_ENABLE_STAT3) || defined(SQLITE_ENABLE_STAT4)
  sqlite3AnalyzeFunctions();
#endif
  sqlite3RegisterDateTimeFunctions();
  sqlite3RegisterJsonFunctions();
  sqlite3InsertBuiltinFuncs(aBuiltinFunc, ArraySize(aBuiltinFunc));

#if 0  /* Enable to print out how the built-in functions are hashed */
  {
    int i;
    FuncDef *p;
    for(i=0; i<SQLITE_FUNC_HASH_SZ; i++){
      printf("FUNC-HASH %02d:", i);
      for(p=sqlite3BuiltinFunctions.a[i]; p; p=p->u.pHash){
        int n = sqlite3Strlen30(p->zName);
        int h = p->zName[0] + n;
        assert( p->funcFlags & SQLITE_FUNC_BUILTIN );
        printf(" %s(%d)", p->zName, h);
      }
      printf("\n");
    }
  }
#endif
}

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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
111
112
113
114
115
116
117

118
119
120
121
122
123
124







-







** array. tolower() is used more often than toupper() by SQLite.
**
** Bit 0x40 is set if the character is non-alphanumeric and can be used in an 
** SQLite identifier.  Identifiers are alphanumerics, "_", "$", and any
** non-ASCII UTF character. Hence the test for whether or not a character is
** part of an identifier is 0x46.
*/
#ifdef SQLITE_ASCII
const unsigned char sqlite3CtypeMap[256] = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  /* 00..07    ........ */
  0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,  /* 08..0f    ........ */
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  /* 10..17    ........ */
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  /* 18..1f    ........ */
  0x01, 0x00, 0x80, 0x00, 0x40, 0x00, 0x00, 0x80,  /* 20..27     !"#$%&' */
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  /* 28..2f    ()*+,-./ */
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
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







-











-
-
-


-
-
-
-
+
-






-
+

+
+
+
+
+
+
+







  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* d0..d7    ........ */
  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* d8..df    ........ */
  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* e0..e7    ........ */
  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* e8..ef    ........ */
  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* f0..f7    ........ */
  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40   /* f8..ff    ........ */
};
#endif

/* EVIDENCE-OF: R-02982-34736 In order to maintain full backwards
** compatibility for legacy applications, the URI filename capability is
** disabled by default.
**
** EVIDENCE-OF: R-38799-08373 URI filenames can be enabled or disabled
** using the SQLITE_USE_URI=1 or SQLITE_USE_URI=0 compile-time options.
**
** EVIDENCE-OF: R-43642-56306 By default, URI handling is globally
** disabled. The default value may be changed by compiling with the
** SQLITE_USE_URI symbol defined.
**
** URI filenames are enabled by default if SQLITE_HAS_CODEC is
** enabled.
*/
#ifndef SQLITE_USE_URI
# ifdef SQLITE_HAS_CODEC
#  define SQLITE_USE_URI 1
# else
#  define SQLITE_USE_URI 0
# define SQLITE_USE_URI 0
# endif
#endif

/* EVIDENCE-OF: R-38720-18127 The default setting is determined by the
** SQLITE_ALLOW_COVERING_INDEX_SCAN compile-time option, or is "on" if
** that compile-time option is omitted.
*/
#ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN
#if !defined(SQLITE_ALLOW_COVERING_INDEX_SCAN)
# define SQLITE_ALLOW_COVERING_INDEX_SCAN 1
#else
# if !SQLITE_ALLOW_COVERING_INDEX_SCAN 
#   error "Compile-time disabling of covering index scan using the\
 -DSQLITE_ALLOW_COVERING_INDEX_SCAN=0 option is deprecated.\
 Contact SQLite developers if this is a problem for you, and\
 delete this #error macro to continue with your build."
# endif
#endif

/* The minimum PMA size is set to this value multiplied by the database
** page size in bytes.
*/
#ifndef SQLITE_SORTER_PMASZ
# define SQLITE_SORTER_PMASZ 250
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
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







+
+
+
+
+


+
-
+
+
+
+


+
+
+
+
+
+
+












+







/*
** The default lookaside-configuration, the format "SZ,N".  SZ is the
** number of bytes in each lookaside slot (should be a multiple of 8)
** and N is the number of slots.  The lookaside-configuration can be
** changed as start-time using sqlite3_config(SQLITE_CONFIG_LOOKASIDE)
** or at run-time for an individual database connection using
** sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE);
**
** With the two-size-lookaside enhancement, less lookaside is required.
** The default configuration of 1200,40 actually provides 30 1200-byte slots
** and 93 128-byte slots, which is more lookaside than is available
** using the older 1200,100 configuration without two-size-lookaside.
*/
#ifndef SQLITE_DEFAULT_LOOKASIDE
# ifdef SQLITE_OMIT_TWOSIZE_LOOKASIDE
# define SQLITE_DEFAULT_LOOKASIDE 1200,100
#   define SQLITE_DEFAULT_LOOKASIDE 1200,100  /* 120KB of memory */
# else
#   define SQLITE_DEFAULT_LOOKASIDE 1200,40   /* 48KB of memory */
# endif
#endif


/* The default maximum size of an in-memory database created using
** sqlite3_deserialize()
*/
#ifndef SQLITE_MEMDB_DEFAULT_MAXSIZE
# define SQLITE_MEMDB_DEFAULT_MAXSIZE 1073741824
#endif

/*
** The following singleton contains the global configuration for
** the SQLite library.
*/
SQLITE_WSD struct Sqlite3Config sqlite3Config = {
   SQLITE_DEFAULT_MEMSTATUS,  /* bMemstat */
   1,                         /* bCoreMutex */
   SQLITE_THREADSAFE==1,      /* bFullMutex */
   SQLITE_USE_URI,            /* bOpenUri */
   SQLITE_ALLOW_COVERING_INDEX_SCAN,   /* bUseCis */
   0,                         /* bSmallMalloc */
   1,                         /* bExtraSchemaChecks */
   0x7ffffffe,                /* mxStrlen */
   0,                         /* neverCorrupt */
   SQLITE_DEFAULT_LOOKASIDE,  /* szLookaside, nLookaside */
   SQLITE_STMTJRNL_SPILL,     /* nStmtSpill */
   {0,0,0,0,0,0,0,0},         /* m */
   {0,0,0,0,0,0,0,0,0},       /* mutex */
   {0,0,0,0,0,0,0,0,0,0,0,0,0},/* pcache2 */
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
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







+
+
+




-
+

-
+
+
+
+
+









+

+
-
+
+
+
+
+

-
+
-
-
-
+







   0,                         /* xSqllog */
   0,                         /* pSqllogArg */
#endif
#ifdef SQLITE_VDBE_COVERAGE
   0,                         /* xVdbeBranch */
   0,                         /* pVbeBranchArg */
#endif
#ifndef SQLITE_OMIT_DESERIALIZE
   SQLITE_MEMDB_DEFAULT_MAXSIZE,   /* mxMemdbSize */
#endif
#ifndef SQLITE_UNTESTABLE
   0,                         /* xTestCallback */
#endif
   0,                         /* bLocaltimeFault */
   0,                         /* bInternalFunctions */
   0,                         /* xAltLocaltime */
   0x7ffffffe,                /* iOnceResetThreshold */
   SQLITE_DEFAULT_SORTERREF_SIZE   /* szSorterRef */
   SQLITE_DEFAULT_SORTERREF_SIZE,   /* szSorterRef */
   0,                         /* iPrngSeed */
#ifdef SQLITE_DEBUG
   {0,0,0,0,0,0}              /* aTune */
#endif
};

/*
** Hash table for global functions - functions common to all
** database connections.  After initialization, this table is
** read-only.
*/
FuncDefHash sqlite3BuiltinFunctions;

#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG)
/*
** Counter used for coverage testing.  Does not come into play for
** Constant tokens for values 0 and 1.
** release builds.
**
** Access to this global variable is not mutex protected.  This might
** result in TSAN warnings.  But as the variable does not exist in
** release builds, that should not be a concern.
*/
const Token sqlite3IntTokens[] = {
unsigned int sqlite3CoverageCounter;
   { "0", 1 },
   { "1", 1 }
};
#endif /* SQLITE_COVERAGE_TEST || SQLITE_DEBUG */

#ifdef VDBE_PROFILE
/*
** The following performance counter can be used in place of
** sqlite3Hwtime() for profiling.  This is a no-op on standard builds.
*/
sqlite3_uint64 sqlite3NProfileCnt = 0;
286
287
288
289
290
291
292






293
294
295
296
297
298
299
300
301
302
303
304
305






























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







+
+
+
+
+
+













+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
** Changing the pending byte during operation will result in undefined
** and incorrect behavior.
*/
#ifndef SQLITE_OMIT_WSD
int sqlite3PendingByte = 0x40000000;
#endif

/*
** Tracing flags set by SQLITE_TESTCTRL_TRACEFLAGS.
*/
u32 sqlite3TreeTrace = 0;
u32 sqlite3WhereTrace = 0;

#include "opcodes.h"
/*
** Properties of opcodes.  The OPFLG_INITIALIZER macro is
** created by mkopcodeh.awk during compilation.  Data is obtained
** from the comments following the "case OP_xxxx:" statements in
** the vdbe.c file.  
*/
const unsigned char sqlite3OpcodeProperty[] = OPFLG_INITIALIZER;

/*
** Name of the default collating sequence
*/
const char sqlite3StrBINARY[] = "BINARY";

/*
** Standard typenames.  These names must match the COLTYPE_* definitions.
** Adjust the SQLITE_N_STDTYPE value if adding or removing entries.
**
**    sqlite3StdType[]            The actual names of the datatypes.
**
**    sqlite3StdTypeLen[]         The length (in bytes) of each entry
**                                in sqlite3StdType[].
**
**    sqlite3StdTypeAffinity[]    The affinity associated with each entry
**                                in sqlite3StdType[].
*/
const unsigned char sqlite3StdTypeLen[] = { 3, 4, 3, 7, 4, 4 };
const char sqlite3StdTypeAffinity[] = {
  SQLITE_AFF_NUMERIC,
  SQLITE_AFF_BLOB,
  SQLITE_AFF_INTEGER,
  SQLITE_AFF_INTEGER,
  SQLITE_AFF_REAL,
  SQLITE_AFF_TEXT
};
const char *sqlite3StdType[] = {
  "ANY",
  "BLOB",
  "INT",
  "INTEGER",
  "REAL",
  "TEXT"
};

Changes to src/hash.c.

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







-
+















-
+





+







*/
static HashElem *findElementWithHash(
  const Hash *pH,     /* The pH to be searched */
  const char *pKey,   /* The key we are searching for */
  unsigned int *pHash /* Write the hash value here */
){
  HashElem *elem;                /* Used to loop thru the element list */
  int count;                     /* Number of elements left to test */
  unsigned int count;            /* Number of elements left to test */
  unsigned int h;                /* The computed hash */
  static HashElem nullElement = { 0, 0, 0, 0 };

  if( pH->ht ){   /*OPTIMIZATION-IF-TRUE*/
    struct _ht *pEntry;
    h = strHash(pKey) % pH->htsize;
    pEntry = &pH->ht[h];
    elem = pEntry->chain;
    count = pEntry->count;
  }else{
    h = 0;
    elem = pH->first;
    count = pH->count;
  }
  if( pHash ) *pHash = h;
  while( count-- ){
  while( count ){
    assert( elem!=0 );
    if( sqlite3StrICmp(elem->pKey,pKey)==0 ){ 
      return elem;
    }
    elem = elem->next;
    count--;
  }
  return &nullElement;
}

/* Remove a single entry from the hash table given a pointer to that
** element and a hash on the element's key.
*/
194
195
196
197
198
199
200
201
202


203
204
205
206
207
208
209
195
196
197
198
199
200
201


202
203
204
205
206
207
208
209
210







-
-
+
+







    elem->next->prev = elem->prev;
  }
  if( pH->ht ){
    pEntry = &pH->ht[h];
    if( pEntry->chain==elem ){
      pEntry->chain = elem->next;
    }
    pEntry->count--;
    assert( pEntry->count>=0 );
    assert( pEntry->count>0 );
    pEntry->count--;
  }
  sqlite3_free( elem );
  pH->count--;
  if( pH->count==0 ){
    assert( pH->first==0 );
    assert( pH->count==0 );
    sqlite3HashClear(pH);

Changes to src/hash.h.

41
42
43
44
45
46
47
48

49
50
51
52
53
54
55
41
42
43
44
45
46
47

48
49
50
51
52
53
54
55







-
+







** the hash table.
*/
struct Hash {
  unsigned int htsize;      /* Number of buckets in the hash table */
  unsigned int count;       /* Number of entries in this table */
  HashElem *first;          /* The first element of the array */
  struct _ht {              /* the hash table */
    int count;                 /* Number of entries with this hash */
    unsigned int count;        /* Number of entries with this hash */
    HashElem *chain;           /* Pointer to first entry with this hash */
  } *ht;
};

/* Each element in the hash table is an instance of the following 
** structure.  All elements are stored on a single doubly-linked list.
**
87
88
89
90
91
92
93
94

95
96
87
88
89
90
91
92
93

94
95
96







-
+


#define sqliteHashData(E)   ((E)->data)
/* #define sqliteHashKey(E)    ((E)->pKey) // NOT USED */
/* #define sqliteHashKeysize(E) ((E)->nKey)  // NOT USED */

/*
** Number of entries in a hash table
*/
/* #define sqliteHashCount(H)  ((H)->count) // NOT USED */
#define sqliteHashCount(H)  ((H)->count)

#endif /* SQLITE_HASH_H */

Changes to src/hwtime.h.

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













-
+










+
-
-
+
+




















-
+


-
-
-
+
+
+


-
+
















-
-

+
-
-
-
-
+
+
+
+
+
-






/*
** 2008 May 27
**
** 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 contains inline asm code for retrieving "high-performance"
** counters for x86 class CPUs.
** counters for x86 and x86_64 class CPUs.
*/
#ifndef SQLITE_HWTIME_H
#define SQLITE_HWTIME_H

/*
** The following routine only works on pentium-class (or newer) processors.
** It uses the RDTSC opcode to read the cycle count value out of the
** processor and returns that value.  This can be used for high-res
** profiling.
*/
#if !defined(__STRICT_ANSI__) && \
#if (defined(__GNUC__) || defined(_MSC_VER)) && \
      (defined(i386) || defined(__i386__) || defined(_M_IX86))
    (defined(__GNUC__) || defined(_MSC_VER)) && \
    (defined(i386) || defined(__i386__) || defined(_M_IX86))

  #if defined(__GNUC__)

  __inline__ sqlite_uint64 sqlite3Hwtime(void){
     unsigned int lo, hi;
     __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
     return (sqlite_uint64)hi << 32 | lo;
  }

  #elif defined(_MSC_VER)

  __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
     __asm {
        rdtsc
        ret       ; return value at EDX:EAX
     }
  }

  #endif

#elif (defined(__GNUC__) && defined(__x86_64__))
#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))

  __inline__ sqlite_uint64 sqlite3Hwtime(void){
      unsigned long val;
      __asm__ __volatile__ ("rdtsc" : "=A" (val));
      return val;
     unsigned int lo, hi;
     __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
     return (sqlite_uint64)hi << 32 | lo;
  }
 
#elif (defined(__GNUC__) && defined(__ppc__))
#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))

  __inline__ sqlite_uint64 sqlite3Hwtime(void){
      unsigned long long retval;
      unsigned long junk;
      __asm__ __volatile__ ("\n\
          1:      mftbu   %1\n\
                  mftb    %L0\n\
                  mftbu   %0\n\
                  cmpw    %0,%1\n\
                  bne     1b"
                  : "=r" (retval), "=r" (junk));
      return retval;
  }

#else

  #error Need implementation of sqlite3Hwtime() for your platform.

  /*
  ** asm() is needed for hardware timing support.  Without asm(),
  ** To compile without implementing sqlite3Hwtime() for your platform,
  ** you can remove the above #error and use the following
  ** stub function.  You will lose timing support for many
  ** of the debugging and testing utilities, but it should at
  ** disable the sqlite3Hwtime() routine.
  **
  ** sqlite3Hwtime() is only used for some obscure debugging
  ** and analysis configurations, not in any deliverable, so this
  ** should not be a great loss.
  ** least compile and run.
  */
  sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }

#endif

#endif /* !defined(SQLITE_HWTIME_H) */

Changes to src/insert.c.

28
29
30
31
32
33
34

35

36
37
38
39
40

41
42
43
44
45

46
47
48
49
50
51
52
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







+
-
+




-
+




-
+







  int iCur,       /* The cursor number of the table */
  int iDb,        /* The database index in sqlite3.aDb[] */
  Table *pTab,    /* The table to be opened */
  int opcode      /* OP_OpenRead or OP_OpenWrite */
){
  Vdbe *v;
  assert( !IsVirtual(pTab) );
  assert( pParse->pVdbe!=0 );
  v = sqlite3GetVdbe(pParse);
  v = pParse->pVdbe;
  assert( opcode==OP_OpenWrite || opcode==OP_OpenRead );
  sqlite3TableLock(pParse, iDb, pTab->tnum, 
                   (opcode==OP_OpenWrite)?1:0, pTab->zName);
  if( HasRowid(pTab) ){
    sqlite3VdbeAddOp4Int(v, opcode, iCur, pTab->tnum, iDb, pTab->nCol);
    sqlite3VdbeAddOp4Int(v, opcode, iCur, pTab->tnum, iDb, pTab->nNVCol);
    VdbeComment((v, "%s", pTab->zName));
  }else{
    Index *pPk = sqlite3PrimaryKeyIndex(pTab);
    assert( pPk!=0 );
    assert( pPk->tnum==pTab->tnum );
    assert( pPk->tnum==pTab->tnum || CORRUPT_DB );
    sqlite3VdbeAddOp3(v, opcode, iCur, pPk->tnum, iDb);
    sqlite3VdbeSetP4KeyInfo(pParse, pPk);
    VdbeComment((v, "%s", pTab->zName));
  }
}

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







+

-
+

-
+

-

+


+
-
-
+
+
+
-








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



-
-
-
+
+
+
+
+





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



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

-
+
-

-
+


-
-
-
-
-
-
-








+
+







    pIdx->zColAff = (char *)sqlite3DbMallocRaw(0, pIdx->nColumn+1);
    if( !pIdx->zColAff ){
      sqlite3OomFault(db);
      return 0;
    }
    for(n=0; n<pIdx->nColumn; n++){
      i16 x = pIdx->aiColumn[n];
      char aff;
      if( x>=0 ){
        pIdx->zColAff[n] = pTab->aCol[x].affinity;
        aff = pTab->aCol[x].affinity;
      }else if( x==XN_ROWID ){
        pIdx->zColAff[n] = SQLITE_AFF_INTEGER;
        aff = SQLITE_AFF_INTEGER;
      }else{
        char aff;
        assert( x==XN_EXPR );
        assert( pIdx->bHasExpr );
        assert( pIdx->aColExpr!=0 );
        aff = sqlite3ExprAffinity(pIdx->aColExpr->a[n].pExpr);
      }
        if( aff==0 ) aff = SQLITE_AFF_BLOB;
        pIdx->zColAff[n] = aff;
      if( aff<SQLITE_AFF_BLOB ) aff = SQLITE_AFF_BLOB;
      if( aff>SQLITE_AFF_NUMERIC) aff = SQLITE_AFF_NUMERIC;
      pIdx->zColAff[n] = aff;
      }
    }
    pIdx->zColAff[n] = 0;
  }
 
  return pIdx->zColAff;
}

/*
** Compute an affinity string for a table.   Space is obtained
** from sqlite3DbMalloc().  The caller is responsible for freeing
** the space when done.
*/
char *sqlite3TableAffinityStr(sqlite3 *db, const Table *pTab){
  char *zColAff;
  zColAff = (char *)sqlite3DbMallocRaw(db, pTab->nCol+1);
  if( zColAff ){
    int i, j;
    for(i=j=0; i<pTab->nCol; i++){
      if( (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ){
        zColAff[j++] = pTab->aCol[i].affinity;
      }
    }
    do{
      zColAff[j--] = 0;
    }while( j>=0 && zColAff[j]<=SQLITE_AFF_BLOB );
  }
  return zColAff;  
}

/*
** Make changes to the evolving bytecode to do affinity transformations
** of values that are about to be gathered into a row for table pTab.
**
** For ordinary (legacy, non-strict) tables:
** -----------------------------------------
**
** Compute the affinity string for table pTab, if it has not already been
** computed.  As an optimization, omit trailing SQLITE_AFF_BLOB affinities.
**
** If the affinity exists (if it is no entirely SQLITE_AFF_BLOB values) and
** if iReg>0 then code an OP_Affinity opcode that will set the affinities
** for register iReg and following.  Or if affinities exists and iReg==0,
** If the affinity string is empty (because it was all SQLITE_AFF_BLOB entries
** which were then optimized out) then this routine becomes a no-op.
**
** Otherwise if iReg>0 then code an OP_Affinity opcode that will set the
** affinities for register iReg and following.  Or if iReg==0,
** then just set the P4 operand of the previous opcode (which should  be
** an OP_MakeRecord) to the affinity string.
**
** A column affinity string has one character per column:
**
**  Character      Column affinity
**  ------------------------------
**  'A'            BLOB
**  'B'            TEXT
**  'C'            NUMERIC
**  'D'            INTEGER
**  'E'            REAL
**    Character      Column affinity
**    ---------      ---------------
**    'A'            BLOB
**    'B'            TEXT
**    'C'            NUMERIC
**    'D'            INTEGER
**    'E'            REAL
**
** For STRICT tables:
** ------------------
**
** Generate an appropropriate OP_TypeCheck opcode that will verify the
** datatypes against the column definitions in pTab.  If iReg==0, that
** means an OP_MakeRecord opcode has already been generated and should be
** the last opcode generated.  The new OP_TypeCheck needs to be inserted
** before the OP_MakeRecord.  The new OP_TypeCheck should use the same
** register set as the OP_MakeRecord.  If iReg>0 then register iReg is
** the first of a series of registers that will form the new record.
** Apply the type checking to that array of registers.
*/
void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
  int i;
  char *zColAff;
  if( pTab->tabFlags & TF_Strict ){
    if( iReg==0 ){
      /* Move the previous opcode (which should be OP_MakeRecord) forward
      ** by one slot and insert a new OP_TypeCheck where the current
      ** OP_MakeRecord is found */
      VdbeOp *pPrev;
      sqlite3VdbeAppendP4(v, pTab, P4_TABLE);
      pPrev = sqlite3VdbeGetLastOp(v);
      assert( pPrev!=0 );
      assert( pPrev->opcode==OP_MakeRecord || sqlite3VdbeDb(v)->mallocFailed );
      pPrev->opcode = OP_TypeCheck;
      sqlite3VdbeAddOp3(v, OP_MakeRecord, pPrev->p1, pPrev->p2, pPrev->p3);
    }else{
      /* Insert an isolated OP_Typecheck */
      sqlite3VdbeAddOp2(v, OP_TypeCheck, iReg, pTab->nNVCol);
      sqlite3VdbeAppendP4(v, pTab, P4_TABLE);
    }
    return;
  }
  char *zColAff = pTab->zColAff;
  zColAff = pTab->zColAff;
  if( zColAff==0 ){
    sqlite3 *db = sqlite3VdbeDb(v);
    zColAff = sqlite3TableAffinityStr(0, pTab);
    zColAff = (char *)sqlite3DbMallocRaw(0, pTab->nCol+1);
    if( !zColAff ){
      sqlite3OomFault(db);
      sqlite3OomFault(sqlite3VdbeDb(v));
      return;
    }

    for(i=0; i<pTab->nCol; i++){
      zColAff[i] = pTab->aCol[i].affinity;
    }
    do{
      zColAff[i--] = 0;
    }while( i>=0 && zColAff[i]==SQLITE_AFF_BLOB );
    pTab->zColAff = zColAff;
  }
  assert( zColAff!=0 );
  i = sqlite3Strlen30NN(zColAff);
  if( i ){
    if( iReg ){
      sqlite3VdbeAddOp4(v, OP_Affinity, iReg, i, 0, zColAff, i);
    }else{
      assert( sqlite3VdbeGetLastOp(v)->opcode==OP_MakeRecord
              || sqlite3VdbeDb(v)->mallocFailed );
      sqlite3VdbeChangeP4(v, -1, zColAff, i);
    }
  }
}

/*
** Return non-zero if the table pTab in database iDb or any of its indices
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
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







-
+



















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







#endif

  for(i=1; i<iEnd; i++){
    VdbeOp *pOp = sqlite3VdbeGetOp(v, i);
    assert( pOp!=0 );
    if( pOp->opcode==OP_OpenRead && pOp->p3==iDb ){
      Index *pIndex;
      int tnum = pOp->p2;
      Pgno tnum = pOp->p2;
      if( tnum==pTab->tnum ){
        return 1;
      }
      for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){
        if( tnum==pIndex->tnum ){
          return 1;
        }
      }
    }
#ifndef SQLITE_OMIT_VIRTUALTABLE
    if( pOp->opcode==OP_VOpen && pOp->p4.pVtab==pVTab ){
      assert( pOp->p4.pVtab!=0 );
      assert( pOp->p4type==P4_VTAB );
      return 1;
    }
#endif
  }
  return 0;
}

/* This walker callback will compute the union of colFlags flags for all
** referenced columns in a CHECK constraint or generated column expression.
*/
static int exprColumnFlagUnion(Walker *pWalker, Expr *pExpr){
  if( pExpr->op==TK_COLUMN && pExpr->iColumn>=0 ){
    assert( pExpr->iColumn < pWalker->u.pTab->nCol );
    pWalker->eCode |= pWalker->u.pTab->aCol[pExpr->iColumn].colFlags;
  }
  return WRC_Continue;
}

#ifndef SQLITE_OMIT_GENERATED_COLUMNS
/*
** All regular columns for table pTab have been puts into registers
** starting with iRegStore.  The registers that correspond to STORED
** or VIRTUAL columns have not yet been initialized.  This routine goes
** back and computes the values for those columns based on the previously
** computed normal columns.
*/
void sqlite3ComputeGeneratedColumns(
  Parse *pParse,    /* Parsing context */
  int iRegStore,    /* Register holding the first column */
  Table *pTab       /* The table */
){
  int i;
  Walker w;
  Column *pRedo;
  int eProgress;
  VdbeOp *pOp;

  assert( pTab->tabFlags & TF_HasGenerated );
  testcase( pTab->tabFlags & TF_HasVirtual );
  testcase( pTab->tabFlags & TF_HasStored );

  /* Before computing generated columns, first go through and make sure
  ** that appropriate affinity has been applied to the regular columns
  */
  sqlite3TableAffinity(pParse->pVdbe, pTab, iRegStore);
  if( (pTab->tabFlags & TF_HasStored)!=0 ){
    pOp = sqlite3VdbeGetLastOp(pParse->pVdbe);
    if( pOp->opcode==OP_Affinity ){
      /* Change the OP_Affinity argument to '@' (NONE) for all stored
      ** columns.  '@' is the no-op affinity and those columns have not
      ** yet been computed. */
      int ii, jj;
      char *zP4 = pOp->p4.z;
      assert( zP4!=0 );
      assert( pOp->p4type==P4_DYNAMIC );
      for(ii=jj=0; zP4[jj]; ii++){
        if( pTab->aCol[ii].colFlags & COLFLAG_VIRTUAL ){
          continue;
        }
        if( pTab->aCol[ii].colFlags & COLFLAG_STORED ){
          zP4[jj] = SQLITE_AFF_NONE;
        }
        jj++;
      }
    }else if( pOp->opcode==OP_TypeCheck ){
      /* If an OP_TypeCheck was generated because the table is STRICT,
      ** then set the P3 operand to indicate that generated columns should
      ** not be checked */
      pOp->p3 = 1;
    }
  }

  /* Because there can be multiple generated columns that refer to one another,
  ** this is a two-pass algorithm.  On the first pass, mark all generated
  ** columns as "not available".
  */
  for(i=0; i<pTab->nCol; i++){
    if( pTab->aCol[i].colFlags & COLFLAG_GENERATED ){
      testcase( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL );
      testcase( pTab->aCol[i].colFlags & COLFLAG_STORED );
      pTab->aCol[i].colFlags |= COLFLAG_NOTAVAIL;
    }
  }

  w.u.pTab = pTab;
  w.xExprCallback = exprColumnFlagUnion;
  w.xSelectCallback = 0;
  w.xSelectCallback2 = 0;

  /* On the second pass, compute the value of each NOT-AVAILABLE column.
  ** Companion code in the TK_COLUMN case of sqlite3ExprCodeTarget() will
  ** compute dependencies and mark remove the COLSPAN_NOTAVAIL mark, as
  ** they are needed.
  */
  pParse->iSelfTab = -iRegStore;
  do{
    eProgress = 0;
    pRedo = 0;
    for(i=0; i<pTab->nCol; i++){
      Column *pCol = pTab->aCol + i;
      if( (pCol->colFlags & COLFLAG_NOTAVAIL)!=0 ){
        int x;
        pCol->colFlags |= COLFLAG_BUSY;
        w.eCode = 0;
        sqlite3WalkExpr(&w, sqlite3ColumnExpr(pTab, pCol));
        pCol->colFlags &= ~COLFLAG_BUSY;
        if( w.eCode & COLFLAG_NOTAVAIL ){
          pRedo = pCol;
          continue;
        }
        eProgress = 1;
        assert( pCol->colFlags & COLFLAG_GENERATED );
        x = sqlite3TableColumnToStorage(pTab, i) + iRegStore;
        sqlite3ExprCodeGeneratedColumn(pParse, pTab, pCol, x);
        pCol->colFlags &= ~COLFLAG_NOTAVAIL;
      }
    }
  }while( pRedo && eProgress );
  if( pRedo ){
    sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"", pRedo->zCnName);
  }
  pParse->iSelfTab = 0;
}
#endif /* SQLITE_OMIT_GENERATED_COLUMNS */


#ifndef SQLITE_OMIT_AUTOINCREMENT
/*
** Locate or create an AutoincInfo structure associated with table pTab
** which is in database iDb.  Return the register number for the register
** that holds the maximum rowid.  Return zero if pTab is not an AUTOINCREMENT
** table.  (Also return zero when doing a VACUUM since we do not want to
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
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







-
+











+
+
-
+







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

    pInfo = pToplevel->pAinc;
    while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; }
    if( pInfo==0 ){
      pInfo = sqlite3DbMallocRawNN(pParse->db, sizeof(*pInfo));
      sqlite3ParserAddCleanup(pToplevel, sqlite3DbFree, pInfo);
      testcase( pParse->earlyCleanup );
      if( pInfo==0 ) return 0;
      if( pParse->db->mallocFailed ) return 0;
      pInfo->pNext = pToplevel->pAinc;
      pToplevel->pAinc = pInfo;
      pInfo->pTab = pTab;
      pInfo->iDb = iDb;
      pToplevel->nMem++;                  /* Register to hold name of table */
      pInfo->regCtr = ++pToplevel->nMem;  /* Max rowid register */
      pToplevel->nMem +=2;       /* Rowid in sqlite_sequence + orig max val */
500
501
502
503
504
505
506
507

508
509
510
511
512
513
514
680
681
682
683
684
685
686

687
688
689
690
691
692
693
694







-
+







**         end loop
**      D: cleanup
*/
void sqlite3Insert(
  Parse *pParse,        /* Parser context */
  SrcList *pTabList,    /* Name of table into which we are inserting */
  Select *pSelect,      /* A SELECT statement to use as the data source */
  IdList *pColumn,      /* Column names corresponding to IDLIST. */
  IdList *pColumn,      /* Column names corresponding to IDLIST, or NULL. */
  int onError,          /* How to handle constraint errors */
  Upsert *pUpsert       /* ON CONFLICT clauses for upsert, or NULL */
){
  sqlite3 *db;          /* The main database structure */
  Table *pTab;          /* The table to insert into.  aka TABLE */
  int i, j;             /* Loop counters */
  Vdbe *v;              /* Generate code into this virtual machine */
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
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







+

















+
-
+


+







  SelectDest dest;      /* Destination for SELECT on rhs of INSERT */
  int iDb;              /* Index of database holding TABLE */
  u8 useTempTable = 0;  /* Store SELECT results in intermediate table */
  u8 appendFlag = 0;    /* True if the insert is likely to be an append */
  u8 withoutRowid;      /* 0 for normal table.  1 for WITHOUT ROWID table */
  u8 bIdListInOrder;    /* True if IDLIST is in table order */
  ExprList *pList = 0;  /* List of VALUES() to be inserted  */
  int iRegStore;        /* Register in which to store next column */

  /* Register allocations */
  int regFromSelect = 0;/* Base register for data coming from SELECT */
  int regAutoinc = 0;   /* Register holding the AUTOINCREMENT counter */
  int regRowCount = 0;  /* Memory cell used for the row counter */
  int regIns;           /* Block of regs holding rowid+data being inserted */
  int regRowid;         /* registers holding insert rowid */
  int regData;          /* register holding first column to insert */
  int *aRegIdx = 0;     /* One register allocated to each index */

#ifndef SQLITE_OMIT_TRIGGER
  int isView;                 /* True if attempting to insert into a view */
  Trigger *pTrigger;          /* List of triggers on pTab, if required */
  int tmask;                  /* Mask of trigger times */
#endif

  db = pParse->db;
  assert( db->pParse==pParse );
  if( pParse->nErr || db->mallocFailed ){
  if( pParse->nErr ){
    goto insert_cleanup;
  }
  assert( db->mallocFailed==0 );
  dest.iSDParm = 0;  /* Suppress a harmless compiler warning */

  /* If the Select object is really just a simple VALUES() list with a
  ** single row (the common case) then keep that one row of values
  ** and discard the other (unused) parts of the pSelect object
  */
  if( pSelect && (pSelect->selFlags & SF_Values)!=0 && pSelect->pPrior==0 ){
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
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







-
+










+
+
+
+
+
+
+
+







  withoutRowid = !HasRowid(pTab);

  /* Figure out if we have any triggers and if the table being
  ** inserted into is a view
  */
#ifndef SQLITE_OMIT_TRIGGER
  pTrigger = sqlite3TriggersExist(pParse, pTab, TK_INSERT, 0, &tmask);
  isView = pTab->pSelect!=0;
  isView = IsView(pTab);
#else
# define pTrigger 0
# define tmask 0
# define isView 0
#endif
#ifdef SQLITE_OMIT_VIEW
# undef isView
# define isView 0
#endif
  assert( (pTrigger && tmask) || (pTrigger==0 && tmask==0) );

#if TREETRACE_ENABLED
  if( sqlite3TreeTrace & 0x10000 ){
    sqlite3TreeViewLine(0, "In sqlite3Insert() at %s:%d", __FILE__, __LINE__);
    sqlite3TreeViewInsert(pParse->pWith, pTabList, pColumn, pSelect, pList,
                          onError, pUpsert, pTrigger);
  }
#endif

  /* If pTab is really a view, make sure it has been initialized.
  ** ViewGetColumnNames() is a no-op if pTab is not a view.
  */
  if( sqlite3ViewGetColumnNames(pParse, pTab) ){
    goto insert_cleanup;
  }
620
621
622
623
624
625
626



627


628
629
630
631
632
633
634
635
636
637
638
639
640


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









660
661

662


663
664

665
666
667
668
669


670
671
672
673








674
675
676
677
678
679
680
681
682
683

684
685
686
687
688
689
690
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
900
901
902
903







+
+
+
-
+
+











-
-
+
+


















-
+
+
+
+
+
+
+
+
+

-
+

+
+

-
+



-
-
+
+




+
+
+
+
+
+
+
+









-
+







  **       INSERT INTO <table1> SELECT * FROM <table2>;
  **
  ** Then special optimizations can be applied that make the transfer
  ** very fast and which reduce fragmentation of indices.
  **
  ** This is the 2nd template.
  */
  if( pColumn==0 
   && pSelect!=0
   && pTrigger==0
  if( pColumn==0 && xferOptimization(pParse, pTab, pSelect, onError, iDb) ){
   && xferOptimization(pParse, pTab, pSelect, onError, iDb)
  ){
    assert( !pTrigger );
    assert( pList==0 );
    goto insert_end;
  }
#endif /* SQLITE_OMIT_XFER_OPT */

  /* If this is an AUTOINCREMENT table, look up the sequence number in the
  ** sqlite_sequence table and store it in memory cell regAutoinc.
  */
  regAutoinc = autoIncBegin(pParse, iDb, pTab);

  /* Allocate registers for holding the rowid of the new row,
  ** the content of the new row, and the assembled row record.
  /* Allocate a block registers to hold the rowid and the values
  ** for all columns of the new row.
  */
  regRowid = regIns = pParse->nMem+1;
  pParse->nMem += pTab->nCol + 1;
  if( IsVirtual(pTab) ){
    regRowid++;
    pParse->nMem++;
  }
  regData = regRowid+1;

  /* If the INSERT statement included an IDLIST term, then make sure
  ** all elements of the IDLIST really are columns of the table and 
  ** remember the column indices.
  **
  ** If the table has an INTEGER PRIMARY KEY column and that column
  ** is named in the IDLIST, then record in the ipkColumn variable
  ** the index into IDLIST of the primary key column.  ipkColumn is
  ** the index of the primary key as it appears in IDLIST, not as
  ** is appears in the original table.  (The index of the INTEGER
  ** PRIMARY KEY in the original table is pTab->iPKey.)
  ** PRIMARY KEY in the original table is pTab->iPKey.)  After this
  ** loop, if ipkColumn==(-1), that means that integer primary key
  ** is unspecified, and hence the table is either WITHOUT ROWID or
  ** it will automatically generated an integer primary key.
  **
  ** bIdListInOrder is true if the columns in IDLIST are in storage
  ** order.  This enables an optimization that avoids shuffling the
  ** columns into storage order.  False negatives are harmless,
  ** but false positives will cause database corruption.
  */
  bIdListInOrder = (pTab->tabFlags & TF_OOOHidden)==0;
  bIdListInOrder = (pTab->tabFlags & (TF_OOOHidden|TF_HasStored))==0;
  if( pColumn ){
    assert( pColumn->eU4!=EU4_EXPR );
    pColumn->eU4 = EU4_IDX;
    for(i=0; i<pColumn->nId; i++){
      pColumn->a[i].idx = -1;
      pColumn->a[i].u4.idx = -1;
    }
    for(i=0; i<pColumn->nId; i++){
      for(j=0; j<pTab->nCol; j++){
        if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zName)==0 ){
          pColumn->a[i].idx = j;
        if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zCnName)==0 ){
          pColumn->a[i].u4.idx = j;
          if( i!=j ) bIdListInOrder = 0;
          if( j==pTab->iPKey ){
            ipkColumn = i;  assert( !withoutRowid );
          }
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
          if( pTab->aCol[j].colFlags & (COLFLAG_STORED|COLFLAG_VIRTUAL) ){
            sqlite3ErrorMsg(pParse, 
               "cannot INSERT into generated column \"%s\"",
               pTab->aCol[j].zCnName);
            goto insert_cleanup;
          }
#endif
          break;
        }
      }
      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;
        }
      }
    }
  }

704
705
706
707
708
709
710

711


712
713
714
715
716
717
718
917
918
919
920
921
922
923
924

925
926
927
928
929
930
931
932
933







+
-
+
+







    addrTop = sqlite3VdbeCurrentAddr(v) + 1;
    sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop);
    sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield);
    dest.iSdst = bIdListInOrder ? regData : 0;
    dest.nSdst = pTab->nCol;
    rc = sqlite3Select(pParse, pSelect, &dest);
    regFromSelect = dest.iSdst;
    assert( db->pParse==pParse );
    if( rc || db->mallocFailed || pParse->nErr ) goto insert_cleanup;
    if( rc || pParse->nErr ) goto insert_cleanup;
    assert( db->mallocFailed==0 );
    sqlite3VdbeEndCoroutine(v, regYield);
    sqlite3VdbeJumpHere(v, addrTop - 1);                       /* label B: */
    assert( pSelect->pEList );
    nColumn = pSelect->pEList->nExpr;

    /* Set useTempTable to TRUE if the result of the SELECT statement
    ** should be written into a temporary table (template 4).  Set to
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
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
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







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











+










-
+








+



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

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








  /* If there is no IDLIST term but the table has an integer primary
  ** key, the set the ipkColumn variable to the integer primary key 
  ** column index in the original table definition.
  */
  if( pColumn==0 && nColumn>0 ){
    ipkColumn = pTab->iPKey;
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
    if( ipkColumn>=0 && (pTab->tabFlags & TF_HasGenerated)!=0 ){
      testcase( pTab->tabFlags & TF_HasVirtual );
      testcase( pTab->tabFlags & TF_HasStored );
      for(i=ipkColumn-1; i>=0; i--){
        if( pTab->aCol[i].colFlags & COLFLAG_GENERATED ){
          testcase( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL );
          testcase( pTab->aCol[i].colFlags & COLFLAG_STORED );
          ipkColumn--;
  }

  /* Make sure the number of columns in the source data matches the number
  ** of columns to be inserted into the table.
  */
  for(i=0; i<pTab->nCol; i++){
    nHidden += (IsHiddenColumn(&pTab->aCol[i]) ? 1 : 0);
  }
  if( pColumn==0 && nColumn && nColumn!=(pTab->nCol-nHidden) ){
    sqlite3ErrorMsg(pParse, 
       "table %S has %d columns but %d values were supplied",
       pTabList, 0, pTab->nCol-nHidden, nColumn);
    goto insert_cleanup;
        }
      }
    }
#endif

    /* Make sure the number of columns in the source data matches the number
    ** of columns to be inserted into the table.
    */
    assert( TF_HasHidden==COLFLAG_HIDDEN );
    assert( TF_HasGenerated==COLFLAG_GENERATED );
    assert( COLFLAG_NOINSERT==(COLFLAG_GENERATED|COLFLAG_HIDDEN) );
    if( (pTab->tabFlags & (TF_HasGenerated|TF_HasHidden))!=0 ){
      for(i=0; i<pTab->nCol; i++){
        if( pTab->aCol[i].colFlags & COLFLAG_NOINSERT ) nHidden++;
      }
    }
    if( nColumn!=(pTab->nCol-nHidden) ){
      sqlite3ErrorMsg(pParse, 
         "table %S has %d columns but %d values were supplied",
         pTabList->a, pTab->nCol-nHidden, nColumn);
     goto insert_cleanup;
    }
  }
  if( pColumn!=0 && nColumn!=pColumn->nId ){
    sqlite3ErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId);
    goto insert_cleanup;
  }
    
  /* Initialize the count of rows to be inserted
  */
  if( (db->flags & SQLITE_CountRows)!=0
   && !pParse->nested
   && !pParse->pTriggerTab
   && !pParse->bReturning
  ){
    regRowCount = ++pParse->nMem;
    sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount);
  }

  /* If this is not a view, open the table and and all indices */
  if( !isView ){
    int nIdx;
    nIdx = sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, -1, 0,
                                      &iDataCur, &iIdxCur);
    aRegIdx = sqlite3DbMallocRawNN(db, sizeof(int)*(nIdx+1));
    aRegIdx = sqlite3DbMallocRawNN(db, sizeof(int)*(nIdx+2));
    if( aRegIdx==0 ){
      goto insert_cleanup;
    }
    for(i=0, pIdx=pTab->pIndex; i<nIdx; pIdx=pIdx->pNext, i++){
      assert( pIdx );
      aRegIdx[i] = ++pParse->nMem;
      pParse->nMem += pIdx->nColumn;
    }
    aRegIdx[i] = ++pParse->nMem;  /* Register to store the table record */
  }
#ifndef SQLITE_OMIT_UPSERT
  if( pUpsert ){
    Upsert *pNx;
    if( IsVirtual(pTab) ){
      sqlite3ErrorMsg(pParse, "UPSERT not implemented for virtual table \"%s\"",
              pTab->zName);
      goto insert_cleanup;
    }
    if( IsView(pTab) ){
      sqlite3ErrorMsg(pParse, "cannot UPSERT a view");
      goto insert_cleanup;
    }
    if( sqlite3HasExplicitNulls(pParse, pUpsert->pUpsertTarget) ){
      goto insert_cleanup;
    }
    pTabList->a[0].iCursor = iDataCur;
    pNx = pUpsert;
    do{
    pUpsert->pUpsertSrc = pTabList;
    pUpsert->regData = regData;
    pUpsert->iDataCur = iDataCur;
    pUpsert->iIdxCur = iIdxCur;
    if( pUpsert->pUpsertTarget ){
      sqlite3UpsertAnalyzeTarget(pParse, pTabList, pUpsert);
    }
      pNx->pUpsertSrc = pTabList;
      pNx->regData = regData;
      pNx->iDataCur = iDataCur;
      pNx->iIdxCur = iIdxCur;
      if( pNx->pUpsertTarget ){
        if( sqlite3UpsertAnalyzeTarget(pParse, pTabList, pNx) ){
          goto insert_cleanup;
        }
      }
      pNx = pNx->pNextUpsert;
    }while( pNx!=0 );
  }
#endif


  /* This is the top of the main insertion loop */
  if( useTempTable ){
    /* This block codes the top of loop only.  The complete loop is the
856
857
858
859
860
861
862

863
864





865
























































































866
867
868
869

870
871
872
873
874
875
876
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







+


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



-
+







    ** following pseudocode (template 3):
    **
    **      C: yield X, at EOF goto D
    **         insert the select result into <table> from R..R+n
    **         goto C
    **      D: ...
    */
    sqlite3VdbeReleaseRegisters(pParse, regData, pTab->nCol, 0, 0);
    addrInsTop = addrCont = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm);
    VdbeCoverage(v);
    if( ipkColumn>=0 ){
      /* tag-20191021-001: If the INTEGER PRIMARY KEY is being generated by the
      ** SELECT, go ahead and copy the value into the rowid slot now, so that
      ** the value does not get overwritten by a NULL at tag-20191021-002. */
      sqlite3VdbeAddOp2(v, OP_Copy, regFromSelect+ipkColumn, regRowid);
  }
    }
  }

  /* Compute data for ordinary columns of the new entry.  Values
  ** are written in storage order into registers starting with regData.
  ** Only ordinary columns are computed in this loop. The rowid
  ** (if there is one) is computed later and generated columns are
  ** computed after the rowid since they might depend on the value
  ** of the rowid.
  */
  nHidden = 0;
  iRegStore = regData;  assert( regData==regRowid+1 );
  for(i=0; i<pTab->nCol; i++, iRegStore++){
    int k;
    u32 colFlags;
    assert( i>=nHidden );
    if( i==pTab->iPKey ){
      /* tag-20191021-002: References to the INTEGER PRIMARY KEY are filled
      ** using the rowid. So put a NULL in the IPK slot of the record to avoid
      ** using excess space.  The file format definition requires this extra
      ** NULL - we cannot optimize further by skipping the column completely */
      sqlite3VdbeAddOp1(v, OP_SoftNull, iRegStore);
      continue;
    }
    if( ((colFlags = pTab->aCol[i].colFlags) & COLFLAG_NOINSERT)!=0 ){
      nHidden++;
      if( (colFlags & COLFLAG_VIRTUAL)!=0 ){
        /* Virtual columns do not participate in OP_MakeRecord.  So back up
        ** iRegStore by one slot to compensate for the iRegStore++ in the
        ** outer for() loop */
        iRegStore--;
        continue;
      }else if( (colFlags & COLFLAG_STORED)!=0 ){
        /* Stored columns are computed later.  But if there are BEFORE
        ** triggers, the slots used for stored columns will be OP_Copy-ed
        ** to a second block of registers, so the register needs to be
        ** initialized to NULL to avoid an uninitialized register read */
        if( tmask & TRIGGER_BEFORE ){
          sqlite3VdbeAddOp1(v, OP_SoftNull, iRegStore);
        }
        continue;
      }else if( pColumn==0 ){
        /* Hidden columns that are not explicitly named in the INSERT
        ** get there default value */
        sqlite3ExprCodeFactorable(pParse, 
            sqlite3ColumnExpr(pTab, &pTab->aCol[i]),
            iRegStore);
        continue;
      }
    }
    if( pColumn ){
      assert( pColumn->eU4==EU4_IDX );
      for(j=0; j<pColumn->nId && pColumn->a[j].u4.idx!=i; j++){}
      if( j>=pColumn->nId ){
        /* A column not named in the insert column list gets its
        ** default value */
        sqlite3ExprCodeFactorable(pParse, 
            sqlite3ColumnExpr(pTab, &pTab->aCol[i]),
            iRegStore);
        continue;
      }
      k = j;
    }else if( nColumn==0 ){
      /* This is INSERT INTO ... DEFAULT VALUES.  Load the default value. */
      sqlite3ExprCodeFactorable(pParse, 
          sqlite3ColumnExpr(pTab, &pTab->aCol[i]),
          iRegStore);
      continue;
    }else{
      k = i - nHidden;
    }

    if( useTempTable ){
      sqlite3VdbeAddOp3(v, OP_Column, srcTab, k, iRegStore); 
    }else if( pSelect ){
      if( regFromSelect!=regData ){
        sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+k, iRegStore);
      }
    }else{
      Expr *pX = pList->a[k].pExpr;
      int y = sqlite3ExprCodeTarget(pParse, pX, iRegStore);
      if( y!=iRegStore ){
        sqlite3VdbeAddOp2(v,
          ExprHasProperty(pX, EP_Subquery) ? OP_Copy : OP_SCopy, y, iRegStore);
      }
    }
  }


  /* Run the BEFORE and INSTEAD OF triggers, if there are any
  */
  endOfLoop = sqlite3VdbeMakeLabel(v);
  endOfLoop = sqlite3VdbeMakeLabel(pParse);
  if( tmask & TRIGGER_BEFORE ){
    int regCols = sqlite3GetTempRange(pParse, pTab->nCol+1);

    /* build the NEW.* reference row.  Note that if there is an INTEGER
    ** PRIMARY KEY into which a NULL is being inserted, that NULL will be
    ** translated into a unique ID for the row.  But on a BEFORE trigger,
    ** we do not know what the unique ID will be (because the insert has
889
890
891
892
893
894
895
896

897
898
899


900

901

902
903
904
905
906




907
908
909
910
911


912
913

914
915
916
917

918
919

920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945

946
947
948
949

950
951
952

953
954
955


956
957
958
959


960
961
962
963
964
965
966
967
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
1286


1287



1288
1289
1290



1291
1292

1293
1294
1295
1296
1297
1298
1299







-
+
-
-
-
+
+

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

















-
-
-






+



-
+

-
-
+
-
-
-
+
+

-
-
-
+
+
-







      }
      addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, regCols); VdbeCoverage(v);
      sqlite3VdbeAddOp2(v, OP_Integer, -1, regCols);
      sqlite3VdbeJumpHere(v, addr1);
      sqlite3VdbeAddOp1(v, OP_MustBeInt, regCols); VdbeCoverage(v);
    }

    /* Cannot have triggers on a virtual table. If it were possible,
    /* Copy the new data already generated. */
    ** this block would have to account for hidden column.
    */
    assert( !IsVirtual(pTab) );
    assert( pTab->nNVCol>0 );
    sqlite3VdbeAddOp3(v, OP_Copy, regRowid+1, regCols+1, pTab->nNVCol-1);

#ifndef SQLITE_OMIT_GENERATED_COLUMNS
    /* Create the new column data
    /* Compute the new value for generated columns after all other
    */
    for(i=j=0; i<pTab->nCol; i++){
      if( pColumn ){
        for(j=0; j<pColumn->nId; j++){
          if( pColumn->a[j].idx==i ) break;
    ** columns have already been computed.  This must be done after
    ** computing the ROWID in case one of the generated columns
    ** refers to the ROWID. */
    if( pTab->tabFlags & TF_HasGenerated ){
        }
      }
      if( (!useTempTable && !pList) || (pColumn && j>=pColumn->nId)
            || (pColumn==0 && IsOrdinaryHiddenColumn(&pTab->aCol[i])) ){
        sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regCols+i+1);
      testcase( pTab->tabFlags & TF_HasVirtual );
      testcase( pTab->tabFlags & TF_HasStored );
      }else if( useTempTable ){
        sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, regCols+i+1); 
      sqlite3ComputeGeneratedColumns(pParse, regCols+1, pTab);
      }else{
        assert( pSelect==0 ); /* Otherwise useTempTable is true */
        sqlite3ExprCodeAndCache(pParse, pList->a[j].pExpr, regCols+i+1);
      }
    }
      if( pColumn==0 && !IsOrdinaryHiddenColumn(&pTab->aCol[i]) ) j++;
    }
#endif

    /* If this is an INSERT on a view with an INSTEAD OF INSERT trigger,
    ** do not attempt any conversions before assembling the record.
    ** If this is a real table, attempt conversions as required by the
    ** table column affinities.
    */
    if( !isView ){
      sqlite3TableAffinity(v, pTab, regCols+1);
    }

    /* Fire BEFORE or INSTEAD OF triggers */
    sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_BEFORE, 
        pTab, regCols-pTab->nCol-1, onError, endOfLoop);

    sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol+1);
  }

  /* Compute the content of the next row to insert into a range of
  ** registers beginning at regIns.
  */
  if( !isView ){
    if( IsVirtual(pTab) ){
      /* The row that the VUpdate opcode will delete: none */
      sqlite3VdbeAddOp2(v, OP_Null, 0, regIns);
    }
    if( ipkColumn>=0 ){
      /* Compute the new rowid */
      if( useTempTable ){
        sqlite3VdbeAddOp3(v, OP_Column, srcTab, ipkColumn, regRowid);
      }else if( pSelect ){
        sqlite3VdbeAddOp2(v, OP_Copy, regFromSelect+ipkColumn, regRowid);
        /* Rowid already initialized at tag-20191021-001 */
      }else{
        VdbeOp *pOp;
        sqlite3ExprCode(pParse, pList->a[ipkColumn].pExpr, regRowid);
        Expr *pIpk = pList->a[ipkColumn].pExpr;
        pOp = sqlite3VdbeGetOp(v, -1);
        assert( pOp!=0 );
        if( pOp->opcode==OP_Null && !IsVirtual(pTab) ){
        if( pIpk->op==TK_NULL && !IsVirtual(pTab) ){
          sqlite3VdbeAddOp3(v, OP_NewRowid, iDataCur, regRowid, regAutoinc);
          appendFlag = 1;
          pOp->opcode = OP_NewRowid;
          pOp->p1 = iDataCur;
          pOp->p2 = regRowid;
        }else{
          sqlite3ExprCode(pParse, pList->a[ipkColumn].pExpr, regRowid);
          pOp->p3 = regAutoinc;
        }
      }
      /* If the PRIMARY KEY expression is NULL, then use OP_NewRowid
      ** to generate a unique primary key value.
      */
      if( !appendFlag ){
        int addr1;
979
980
981
982
983
984
985

986
987


988
989

990
991
992
993

994
995
996
997
998
999
1000
1001

1002
1003
1004
1005
1006
1007
1008
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
1311
1312
1313
1314
1315
1316
1317
1318


1319
1320


1321




1322








1323













1324







1325
1326



1327
1328
1329
1330
1331
1332
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







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














-
+




+
-
+
+









-
+
-
-




+
+
+
+
+
+
+







      sqlite3VdbeAddOp2(v, OP_Null, 0, regRowid);
    }else{
      sqlite3VdbeAddOp3(v, OP_NewRowid, iDataCur, regRowid, regAutoinc);
      appendFlag = 1;
    }
    autoIncStep(pParse, regAutoinc, regRowid);

#ifndef SQLITE_OMIT_GENERATED_COLUMNS
    /* Compute data for all columns of the new entry, beginning
    ** with the first column.
    /* Compute the new value for generated columns after all other
    ** columns have already been computed.  This must be done after
    */
    nHidden = 0;
    ** computing the ROWID in case one of the generated columns
    for(i=0; i<pTab->nCol; i++){
      int iRegStore = regRowid+1+i;
      if( i==pTab->iPKey ){
        /* The value of the INTEGER PRIMARY KEY column is always a NULL.
    ** is derived from the INTEGER PRIMARY KEY. */
        ** Whenever this column is read, the rowid will be substituted
        ** in its place.  Hence, fill this column with a NULL to avoid
        ** taking up data space with information that will never be used.
        ** As there may be shallow copies of this value, make it a soft-NULL */
        sqlite3VdbeAddOp1(v, OP_SoftNull, iRegStore);
        continue;
      }
      if( pColumn==0 ){
    if( pTab->tabFlags & TF_HasGenerated ){
        if( IsHiddenColumn(&pTab->aCol[i]) ){
          j = -1;
          nHidden++;
        }else{
          j = i - nHidden;
        }
      }else{
        for(j=0; j<pColumn->nId; j++){
          if( pColumn->a[j].idx==i ) break;
        }
      }
      if( j<0 || nColumn==0 || (pColumn && j>=pColumn->nId) ){
        sqlite3ExprCodeFactorable(pParse, pTab->aCol[i].pDflt, iRegStore);
      sqlite3ComputeGeneratedColumns(pParse, regRowid+1, pTab);
      }else if( useTempTable ){
        sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, iRegStore); 
      }else if( pSelect ){
        if( regFromSelect!=regData ){
          sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+j, iRegStore);
        }
      }else{
    }
#endif
        sqlite3ExprCode(pParse, pList->a[j].pExpr, iRegStore);
      }
    }

    /* Generate code to check constraints and generate index keys and
    ** do the insertion.
    */
#ifndef SQLITE_OMIT_VIRTUALTABLE
    if( IsVirtual(pTab) ){
      const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
      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
      );
      if( db->flags & SQLITE_ForeignKeys ){
      sqlite3FkCheck(pParse, pTab, 0, regIns, 0, 0);
        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 || (pTrigger==0 &&
      bUseSeek = (isReplace==0 || !sqlite3VdbeHasSubProgram(v));
          ((db->flags & SQLITE_ForeignKeys)==0 || sqlite3FkReferences(pTab)==0)
      ));
      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);
  }
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422

1423


1424
1425
1426
1427
1428
1429
1430
1431

1432
1433
1434
1435
1436
1437
1438
1439







+
+
+
+
+
+
+
+
+



+

+














-
+
-
-








-
+







  sqlite3VdbeResolveLabel(v, endOfLoop);
  if( useTempTable ){
    sqlite3VdbeAddOp2(v, OP_Next, srcTab, addrCont); VdbeCoverage(v);
    sqlite3VdbeJumpHere(v, addrInsTop);
    sqlite3VdbeAddOp1(v, OP_Close, srcTab);
  }else if( pSelect ){
    sqlite3VdbeGoto(v, addrCont);
#ifdef SQLITE_DEBUG
    /* If we are jumping back to an OP_Yield that is preceded by an
    ** OP_ReleaseReg, set the p5 flag on the OP_Goto so that the
    ** OP_ReleaseReg will be included in the loop. */
    if( sqlite3VdbeGetOp(v, addrCont-1)->opcode==OP_ReleaseReg ){
      assert( sqlite3VdbeGetOp(v, addrCont)->opcode==OP_Yield );
      sqlite3VdbeChangeP5(v, 1);
    }
#endif
    sqlite3VdbeJumpHere(v, addrInsTop);
  }

#ifndef SQLITE_OMIT_XFER_OPT
insert_end:
#endif /* SQLITE_OMIT_XFER_OPT */
  /* Update the sqlite_sequence table by storing the content of the
  ** maximum rowid counter values recorded while inserting into
  ** autoincrement tables.
  */
  if( pParse->nested==0 && pParse->pTriggerTab==0 ){
    sqlite3AutoincrementEnd(pParse);
  }

  /*
  ** Return the number of rows inserted. If this routine is 
  ** generating code because of a call to sqlite3NestedParse(), do not
  ** invoke the callback function.
  */
  if( regRowCount ){
    sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1);
    sqlite3CodeChangeCount(v, regRowCount, "rows inserted");
    sqlite3VdbeSetNumCols(v, 1);
    sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", SQLITE_STATIC);
  }

insert_cleanup:
  sqlite3SrcListDelete(db, pTabList);
  sqlite3ExprListDelete(db, pList);
  sqlite3UpsertDelete(db, pUpsert);
  sqlite3SelectDelete(db, pSelect);
  sqlite3IdListDelete(db, pColumn);
  sqlite3DbFree(db, aRegIdx);
  if( aRegIdx ) sqlite3DbNNFreeNN(db, aRegIdx);
}

/* Make sure "isView" and other macros defined above are undefined. Otherwise
** they may interfere with compilation of other functions in this file
** (or in another file, if this file becomes part of the amalgamation).  */
#ifdef isView
 #undef isView
1186
1187
1188
1189
1190
1191
1192
































































1193
1194
1195
1196
1197
1198
1199
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
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
1574
1575
1576
1577
1578
1579
1580
1581







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







  testcase( w.eCode==0 );
  testcase( w.eCode==CKCNSTRNT_COLUMN );
  testcase( w.eCode==CKCNSTRNT_ROWID );
  testcase( w.eCode==(CKCNSTRNT_ROWID|CKCNSTRNT_COLUMN) );
  return w.eCode!=0;
}

/*
** The sqlite3GenerateConstraintChecks() routine usually wants to visit
** the indexes of a table in the order provided in the Table->pIndex list.
** However, sometimes (rarely - when there is an upsert) it wants to visit
** the indexes in a different order.  The following data structures accomplish
** this.
**
** The IndexIterator object is used to walk through all of the indexes
** of a table in either Index.pNext order, or in some other order established
** by an array of IndexListTerm objects.
*/
typedef struct IndexListTerm IndexListTerm;
typedef struct IndexIterator IndexIterator;
struct IndexIterator {
  int eType;    /* 0 for Index.pNext list.  1 for an array of IndexListTerm */
  int i;        /* Index of the current item from the list */
  union {
    struct {    /* Use this object for eType==0: A Index.pNext list */
      Index *pIdx;   /* The current Index */
    } lx;      
    struct {    /* Use this object for eType==1; Array of IndexListTerm */
      int nIdx;               /* Size of the array */
      IndexListTerm *aIdx;    /* Array of IndexListTerms */
    } ax;
  } u;
};

/* When IndexIterator.eType==1, then each index is an array of instances
** of the following object
*/
struct IndexListTerm {
  Index *p;  /* The index */
  int ix;    /* Which entry in the original Table.pIndex list is this index*/
};

/* Return the first index on the list */
static Index *indexIteratorFirst(IndexIterator *pIter, int *pIx){
  assert( pIter->i==0 );
  if( pIter->eType ){
    *pIx = pIter->u.ax.aIdx[0].ix;
    return pIter->u.ax.aIdx[0].p;
  }else{
    *pIx = 0;
    return pIter->u.lx.pIdx;
  }
}

/* Return the next index from the list.  Return NULL when out of indexes */
static Index *indexIteratorNext(IndexIterator *pIter, int *pIx){
  if( pIter->eType ){
    int i = ++pIter->i;
    if( i>=pIter->u.ax.nIdx ){
      *pIx = i;
      return 0;
    }
    *pIx = pIter->u.ax.aIdx[i].ix;
    return pIter->u.ax.aIdx[i].p;
  }else{
    ++(*pIx);
    pIter->u.lx.pIdx = pIter->u.lx.pIdx->pNext;
    return pIter->u.lx.pIdx;
  }
}
  
/*
** Generate code to do constraint checks prior to an INSERT or an UPDATE
** on table pTab.
**
** The regNewData parameter is the first register in a range that contains
** the data to be inserted or the data after the update.  There will be
** pTab->nCol+1 registers in this range.  The first register (the one
1220
1221
1222
1223
1224
1225
1226








1227
1228
1229
1230
1231
1232
1233
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623







+
+
+
+
+
+
+
+







** value for either the rowid column or its INTEGER PRIMARY KEY alias.
**
** The code generated by this routine will store new index entries into
** registers identified by aRegIdx[].  No index entry is created for
** indices where aRegIdx[i]==0.  The order of indices in aRegIdx[] is
** the same as the order of indices on the linked list of indices
** at pTab->pIndex.
**
** (2019-05-07) The generated code also creates a new record for the
** main table, if pTab is a rowid table, and stores that record in the
** register identified by aRegIdx[nIdx] - in other words in the first
** entry of aRegIdx[] past the last index.  It is important that the
** record be generated during constraint checks to avoid affinity changes
** to the register content that occur after constraint checks but before
** the new record is inserted.
**
** The caller must have already opened writeable cursors on the main
** table and all applicable indices (that is to say, all indices for which
** aRegIdx[] is not zero).  iDataCur is the cursor for the main table when
** inserting or updating a rowid table, or the cursor for the PRIMARY KEY
** index when operating on a WITHOUT ROWID table.  iIdxCur is the cursor
** for the first index in the pTab->pIndex list.  Cursors for other indices
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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
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
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
































1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809


1810




1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826

1827

1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853

1854
1855
1856
1857

1858
1859
1860
1861
1862
1863



1864
1865
1866
1867
1868
1869
1870
1871
1872
1873







-
+





-


-
-
+
+

-
-
+
+


+
+
+
+
+
+
+
+



-
+

-
+




















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


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










+








+
+
+
+
-
+

+
+
-
+
+
+



-
-
-
+
+
+







  int ignoreDest,      /* Jump to this label on an OE_Ignore resolution */
  int *pbMayReplace,   /* OUT: Set to true if constraint may cause a replace */
  int *aiChng,         /* column i is unchanged if aiChng[i]<0 */
  Upsert *pUpsert      /* ON CONFLICT clauses, if any.  NULL otherwise */
){
  Vdbe *v;             /* VDBE under constrution */
  Index *pIdx;         /* Pointer to one of the indices */
  Index *pPk = 0;      /* The PRIMARY KEY index */
  Index *pPk = 0;      /* The PRIMARY KEY index for WITHOUT ROWID tables */
  sqlite3 *db;         /* Database connection */
  int i;               /* loop counter */
  int ix;              /* Index loop counter */
  int nCol;            /* Number of columns */
  int onError;         /* Conflict resolution strategy */
  int addr1;           /* Address of jump instruction */
  int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */
  int nPkField;        /* Number of fields in PRIMARY KEY. 1 for ROWID tables */
  Index *pUpIdx = 0;   /* Index to which to apply the upsert */
  u8 isUpdate;         /* True if this is an UPDATE operation */
  Upsert *pUpsertClause = 0;  /* The specific ON CONFLICT clause for pIdx */
  u8 isUpdate;           /* True if this is an UPDATE operation */
  u8 bAffinityDone = 0;  /* True if the OP_Affinity operation has been run */
  int upsertBypass = 0;  /* Address of Goto to bypass upsert subroutine */
  int upsertJump = 0;    /* Address of Goto that jumps into upsert subroutine */
  int upsertIpkReturn = 0; /* Address of Goto at end of IPK uniqueness check */
  int upsertIpkDelay = 0;  /* Address of Goto to bypass initial IPK check */
  int ipkTop = 0;        /* Top of the IPK uniqueness check */
  int ipkBottom = 0;     /* OP_Goto at the end of the IPK uniqueness check */
  /* Variables associated with retesting uniqueness constraints after
  ** replace triggers fire have run */
  int regTrigCnt;       /* Register used to count replace trigger invocations */
  int addrRecheck = 0;  /* Jump here to recheck all uniqueness constraints */
  int lblRecheckOk = 0; /* Each recheck jumps to this label if it passes */
  Trigger *pTrigger;    /* List of DELETE triggers on the table pTab */
  int nReplaceTrig = 0; /* Number of replace triggers coded */
  IndexIterator sIdxIter;  /* Index iterator */

  isUpdate = regOldData!=0;
  db = pParse->db;
  v = sqlite3GetVdbe(pParse);
  v = pParse->pVdbe;
  assert( v!=0 );
  assert( pTab->pSelect==0 );  /* This table is not a VIEW */
  assert( !IsView(pTab) );  /* This table is not a VIEW */
  nCol = pTab->nCol;
  
  /* pPk is the PRIMARY KEY index for WITHOUT ROWID tables and NULL for
  ** normal rowid tables.  nPkField is the number of key fields in the 
  ** pPk index or 1 for a rowid table.  In other words, nPkField is the
  ** number of fields in the true primary key of the table. */
  if( HasRowid(pTab) ){
    pPk = 0;
    nPkField = 1;
  }else{
    pPk = sqlite3PrimaryKeyIndex(pTab);
    nPkField = pPk->nKeyCol;
  }

  /* Record that this module has started */
  VdbeModuleComment((v, "BEGIN: GenCnstCks(%d,%d,%d,%d,%d)",
                     iDataCur, iIdxCur, regNewData, regOldData, pkChng));

  /* Test all NOT NULL constraints.
  */
  if( pTab->tabFlags & TF_HasNotNull ){
    int b2ndPass = 0;         /* True if currently running 2nd pass */
    int nSeenReplace = 0;     /* Number of ON CONFLICT REPLACE operations */
    int nGenerated = 0;       /* Number of generated columns with NOT NULL */
    while(1){  /* Make 2 passes over columns. Exit loop via "break" */
  for(i=0; i<nCol; i++){
    if( i==pTab->iPKey ){
      continue;        /* ROWID is never NULL */
    }
    if( aiChng && aiChng[i]<0 ){
      /* Don't bother checking for NOT NULL on columns that do not change */
      continue;
    }
      for(i=0; i<nCol; i++){
        int iReg;                        /* Register holding column value */
        Column *pCol = &pTab->aCol[i];   /* The column to check for NOT NULL */
        int isGenerated;                 /* non-zero if column is generated */
        onError = pCol->notNull;
        if( onError==OE_None ) continue; /* No NOT NULL on this column */
        if( i==pTab->iPKey ){
          continue;        /* ROWID is never NULL */
        }
        isGenerated = pCol->colFlags & COLFLAG_GENERATED;
        if( isGenerated && !b2ndPass ){
          nGenerated++;
          continue;        /* Generated columns processed on 2nd pass */
        }
        if( aiChng && aiChng[i]<0 && !isGenerated ){
          /* Do not check NOT NULL on columns that do not change */
          continue;
        }
    onError = pTab->aCol[i].notNull;
    if( onError==OE_None ) continue;  /* This column is allowed to be NULL */
    if( overrideError!=OE_Default ){
      onError = overrideError;
    }else if( onError==OE_Default ){
      onError = OE_Abort;
    }
    if( onError==OE_Replace && pTab->aCol[i].pDflt==0 ){
      onError = OE_Abort;
    }
    assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
        || onError==OE_Ignore || onError==OE_Replace );
    switch( onError ){
      case OE_Abort:
        sqlite3MayAbort(pParse);
        /* Fall through */
      case OE_Rollback:
      case OE_Fail: {
        char *zMsg = sqlite3MPrintf(db, "%s.%s", pTab->zName,
                                    pTab->aCol[i].zName);
        sqlite3VdbeAddOp3(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL, onError,
                          regNewData+1+i);
        sqlite3VdbeAppendP4(v, zMsg, P4_DYNAMIC);
        sqlite3VdbeChangeP5(v, P5_ConstraintNotNull);
        VdbeCoverage(v);
        break;
      }
      case OE_Ignore: {
        sqlite3VdbeAddOp2(v, OP_IsNull, regNewData+1+i, ignoreDest);
        VdbeCoverage(v);
        break;
      }
        if( overrideError!=OE_Default ){
          onError = overrideError;
        }else if( onError==OE_Default ){
          onError = OE_Abort;
        }
        if( onError==OE_Replace ){
          if( b2ndPass        /* REPLACE becomes ABORT on the 2nd pass */
           || pCol->iDflt==0  /* REPLACE is ABORT if no DEFAULT value */
          ){
            testcase( pCol->colFlags & COLFLAG_VIRTUAL );
            testcase( pCol->colFlags & COLFLAG_STORED );
            testcase( pCol->colFlags & COLFLAG_GENERATED );
            onError = OE_Abort;
          }else{
            assert( !isGenerated );
          }
        }else if( b2ndPass && !isGenerated ){
          continue;
        }
        assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
            || onError==OE_Ignore || onError==OE_Replace );
        testcase( i!=sqlite3TableColumnToStorage(pTab, i) );
        iReg = sqlite3TableColumnToStorage(pTab, i) + regNewData + 1;
        switch( onError ){
          case OE_Replace: {
            int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, iReg);
            VdbeCoverage(v);
            assert( (pCol->colFlags & COLFLAG_GENERATED)==0 );
            nSeenReplace++;
            sqlite3ExprCodeCopy(pParse,
               sqlite3ColumnExpr(pTab, pCol), iReg);
            sqlite3VdbeJumpHere(v, addr1);
            break;
          }
          case OE_Abort:
            sqlite3MayAbort(pParse);
            /* no break */ deliberate_fall_through
          case OE_Rollback:
          case OE_Fail: {
            char *zMsg = sqlite3MPrintf(db, "%s.%s", pTab->zName,
                                        pCol->zCnName);
            testcase( zMsg==0 && db->mallocFailed==0 );
            sqlite3VdbeAddOp3(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL,
                              onError, iReg);
            sqlite3VdbeAppendP4(v, zMsg, P4_DYNAMIC);
            sqlite3VdbeChangeP5(v, P5_ConstraintNotNull);
            VdbeCoverage(v);
            break;
          }
          default: {
            assert( onError==OE_Ignore );
            sqlite3VdbeAddOp2(v, OP_IsNull, iReg, ignoreDest);
            VdbeCoverage(v);
            break;
          }
      default: {
        assert( onError==OE_Replace );
        } /* end switch(onError) */
        addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, regNewData+1+i);
           VdbeCoverage(v);
        sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regNewData+1+i);
        sqlite3VdbeJumpHere(v, addr1);
      } /* end loop i over columns */
      if( nGenerated==0 && nSeenReplace==0 ){
        /* If there are no generated columns with NOT NULL constraints
        ** and no NOT NULL ON CONFLICT REPLACE constraints, then a single
        ** pass is sufficient */
        break;
      }
      if( b2ndPass ) break;  /* Never need more than 2 passes */
      b2ndPass = 1;
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
      if( nSeenReplace>0 && (pTab->tabFlags & TF_HasGenerated)!=0 ){
        /* If any NOT NULL ON CONFLICT REPLACE constraints fired on the
        ** first pass, recomputed values for all generated columns, as
        ** those values might depend on columns affected by the REPLACE.
        */
        sqlite3ComputeGeneratedColumns(pParse, regNewData+1, pTab);
    }
      }
  }
#endif
    } /* end of 2-pass loop */
  } /* end if( has-not-null-constraints ) */

  /* Test all CHECK constraints
  */
#ifndef SQLITE_OMIT_CHECK
  if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
    ExprList *pCheck = pTab->pCheck;
    pParse->iSelfTab = -(regNewData+1);
    onError = overrideError!=OE_Default ? overrideError : OE_Abort;
    for(i=0; i<pCheck->nExpr; i++){
      int allOk;
      Expr *pCopy;
      Expr *pExpr = pCheck->a[i].pExpr;
      if( aiChng
       && !sqlite3ExprReferencesUpdatedColumn(pExpr, aiChng, pkChng)
      ){
        /* The check constraints do not reference any of the columns being
        ** updated so there is no point it verifying the check constraint */
        continue;
      }
      if( bAffinityDone==0 ){
        sqlite3TableAffinity(v, pTab, regNewData+1);
        bAffinityDone = 1;
      }
      allOk = sqlite3VdbeMakeLabel(v);
      allOk = sqlite3VdbeMakeLabel(pParse);
      sqlite3VdbeVerifyAbortable(v, onError);
      pCopy = sqlite3ExprDup(db, pExpr, 0);
      if( !db->mallocFailed ){
      sqlite3ExprIfTrue(pParse, pExpr, allOk, SQLITE_JUMPIFNULL);
        sqlite3ExprIfTrue(pParse, pCopy, allOk, SQLITE_JUMPIFNULL);
      }
      sqlite3ExprDelete(db, pCopy);
      if( onError==OE_Ignore ){
        sqlite3VdbeGoto(v, ignoreDest);
      }else{
        char *zName = pCheck->a[i].zName;
        if( zName==0 ) zName = pTab->zName;
        if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */
        char *zName = pCheck->a[i].zEName;
        assert( zName!=0 || pParse->db->mallocFailed );
        if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-26383-51744 */
        sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_CHECK,
                              onError, zName, P4_TRANSIENT,
                              P5_ConstraintCheck);
      }
      sqlite3VdbeResolveLabel(v, allOk);
    }
    pParse->iSelfTab = 0;
1443
1444
1445
1446
1447
1448
1449
1450




1451
1452



1453
1454


1455
1456
1457
1458
1459
1460
1461
1462


























































































1463
1464
1465
1466
1467
1468
1469
1470

1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485














1486
1487
1488
1489
1490
1491
1492
1493
1494
1495

1496

1497
1498
1499
1500
1501
1502
1503
1898
1899
1900
1901
1902
1903
1904

1905
1906
1907
1908
1909
1910
1911
1912
1913


1914
1915








1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
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
1984
1985
1986
1987
1988
1989
1990
1991
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
2017
2018
2019
2020
2021
2022
2023





2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046

2047
2048
2049
2050
2051
2052
2053
2054
2055
2056







-
+
+
+
+


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







-
+










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









-
+

+







  **        default conflict resolution strategy
  **   (C)  Unique index that do use OE_Replace by default.
  **
  ** The ordering of (2) and (3) is accomplished by making sure the linked
  ** list of indexes attached to a table puts all OE_Replace indexes last
  ** in the list.  See sqlite3CreateIndex() for where that happens.
  */

  sIdxIter.eType = 0;
  sIdxIter.i = 0;
  sIdxIter.u.ax.aIdx = 0;  /* Silence harmless compiler warning */
  sIdxIter.u.lx.pIdx = pTab->pIndex;
  if( pUpsert ){
    if( pUpsert->pUpsertTarget==0 ){
      /* There is just on ON CONFLICT clause and it has no constraint-target */
      assert( pUpsert->pNextUpsert==0 );
      if( pUpsert->isDoUpdate==0 ){
      /* An ON CONFLICT DO NOTHING clause, without a constraint-target.
      ** Make all unique constraint resolution be OE_Ignore */
        /* A single ON CONFLICT DO NOTHING clause, without a constraint-target.
        ** Make all unique constraint resolution be OE_Ignore */
      assert( pUpsert->pUpsertSet==0 );
      overrideError = OE_Ignore;
      pUpsert = 0;
    }else if( (pUpIdx = pUpsert->pUpsertIdx)!=0 ){
      /* If the constraint-target uniqueness check must be run first.
      ** Jump to that uniqueness check now */
      upsertJump = sqlite3VdbeAddOp0(v, OP_Goto);
      VdbeComment((v, "UPSERT constraint goes first"));
        overrideError = OE_Ignore;
        pUpsert = 0;
      }else{
        /* A single ON CONFLICT DO UPDATE.  Make all resolutions OE_Update */
        overrideError = OE_Update;
      }
    }else if( pTab->pIndex!=0 ){
      /* Otherwise, we'll need to run the IndexListTerm array version of the
      ** iterator to ensure that all of the ON CONFLICT conditions are
      ** checked first and in order. */
      int nIdx, jj;
      u64 nByte;
      Upsert *pTerm;
      u8 *bUsed;
      for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){
         assert( aRegIdx[nIdx]>0 );
      }
      sIdxIter.eType = 1;
      sIdxIter.u.ax.nIdx = nIdx;
      nByte = (sizeof(IndexListTerm)+1)*nIdx + nIdx;
      sIdxIter.u.ax.aIdx = sqlite3DbMallocZero(db, nByte);
      if( sIdxIter.u.ax.aIdx==0 ) return; /* OOM */
      bUsed = (u8*)&sIdxIter.u.ax.aIdx[nIdx];
      pUpsert->pToFree = sIdxIter.u.ax.aIdx;
      for(i=0, pTerm=pUpsert; pTerm; pTerm=pTerm->pNextUpsert){
        if( pTerm->pUpsertTarget==0 ) break;
        if( pTerm->pUpsertIdx==0 ) continue;  /* Skip ON CONFLICT for the IPK */
        jj = 0;
        pIdx = pTab->pIndex;
        while( ALWAYS(pIdx!=0) && pIdx!=pTerm->pUpsertIdx ){
           pIdx = pIdx->pNext;
           jj++;
        }
        if( bUsed[jj] ) continue; /* Duplicate ON CONFLICT clause ignored */
        bUsed[jj] = 1;
        sIdxIter.u.ax.aIdx[i].p = pIdx;
        sIdxIter.u.ax.aIdx[i].ix = jj;
        i++;
      }
      for(jj=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, jj++){
        if( bUsed[jj] ) continue;
        sIdxIter.u.ax.aIdx[i].p = pIdx;
        sIdxIter.u.ax.aIdx[i].ix = jj;
        i++;
      }
      assert( i==nIdx );
    }
  }

  /* Determine if it is possible that triggers (either explicitly coded
  ** triggers or FK resolution actions) might run as a result of deletes
  ** that happen when OE_Replace conflict resolution occurs. (Call these
  ** "replace triggers".)  If any replace triggers run, we will need to
  ** recheck all of the uniqueness constraints after they have all run.
  ** But on the recheck, the resolution is OE_Abort instead of OE_Replace.
  **
  ** If replace triggers are a possibility, then
  **
  **   (1) Allocate register regTrigCnt and initialize it to zero.
  **       That register will count the number of replace triggers that
  **       fire.  Constraint recheck only occurs if the number is positive.
  **   (2) Initialize pTrigger to the list of all DELETE triggers on pTab.
  **   (3) Initialize addrRecheck and lblRecheckOk
  **
  ** The uniqueness rechecking code will create a series of tests to run
  ** in a second pass.  The addrRecheck and lblRecheckOk variables are
  ** used to link together these tests which are separated from each other
  ** in the generate bytecode.
  */
  if( (db->flags & (SQLITE_RecTriggers|SQLITE_ForeignKeys))==0 ){
    /* There are not DELETE triggers nor FK constraints.  No constraint
    ** rechecks are needed. */
    pTrigger = 0;
    regTrigCnt = 0;
  }else{
    if( db->flags&SQLITE_RecTriggers ){
      pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
      regTrigCnt = pTrigger!=0 || sqlite3FkRequired(pParse, pTab, 0, 0);
    }else{
      pTrigger = 0;
      regTrigCnt = sqlite3FkRequired(pParse, pTab, 0, 0);
    }
    if( regTrigCnt ){
      /* Replace triggers might exist.  Allocate the counter and
      ** initialize it to zero. */
      regTrigCnt = ++pParse->nMem;
      sqlite3VdbeAddOp2(v, OP_Integer, 0, regTrigCnt);
      VdbeComment((v, "trigger count"));
      lblRecheckOk = sqlite3VdbeMakeLabel(pParse);
      addrRecheck = lblRecheckOk;
    }
  }

  /* If rowid is changing, make sure the new rowid does not previously
  ** exist in the table.
  */
  if( pkChng && pPk==0 ){
    int addrRowidOk = sqlite3VdbeMakeLabel(v);
    int addrRowidOk = sqlite3VdbeMakeLabel(pParse);

    /* Figure out what action to take in case of a rowid collision */
    onError = pTab->keyConf;
    if( overrideError!=OE_Default ){
      onError = overrideError;
    }else if( onError==OE_Default ){
      onError = OE_Abort;
    }

    /* figure out whether or not upsert applies in this case */
    if( pUpsert && pUpsert->pUpsertIdx==0 ){
      if( pUpsert->pUpsertSet==0 ){
        onError = OE_Ignore;  /* DO NOTHING is the same as INSERT OR IGNORE */
      }else{
        onError = OE_Update;  /* DO UPDATE */
    if( pUpsert ){
      pUpsertClause = sqlite3UpsertOfIndex(pUpsert,0);
      if( pUpsertClause!=0 ){
        if( pUpsertClause->isDoUpdate==0 ){
          onError = OE_Ignore;  /* DO NOTHING is the same as INSERT OR IGNORE */
        }else{
          onError = OE_Update;  /* DO UPDATE */
        }
      }
      if( pUpsertClause!=pUpsert ){
        /* The first ON CONFLICT clause has a conflict target other than
        ** the IPK.  We have to jump ahead to that first ON CONFLICT clause
        ** and then come back here and deal with the IPK afterwards */
        upsertIpkDelay = sqlite3VdbeAddOp0(v, OP_Goto);
      }
    }

    /* If the response to a rowid conflict is REPLACE but the response
    ** to some other UNIQUE constraint is FAIL or IGNORE, then we need
    ** to defer the running of the rowid conflict checking until after
    ** the UNIQUE constraints have run.
    */
    if( onError==OE_Replace      /* IPK rule is REPLACE */
     && onError!=overrideError   /* Rules for other contraints are different */
     && onError!=overrideError   /* Rules for other constraints are different */
     && pTab->pIndex             /* There exist other constraints */
     && !upsertIpkDelay          /* IPK check already deferred by UPSERT */
    ){
      ipkTop = sqlite3VdbeAddOp0(v, OP_Goto)+1;
      VdbeComment((v, "defer IPK REPLACE until last"));
    }

    if( isUpdate ){
      /* pkChng!=0 does not mean that the rowid has changed, only that
1514
1515
1516
1517
1518
1519
1520
1521

1522
1523
1524
1525
1526
1527
1528
2067
2068
2069
2070
2071
2072
2073

2074
2075
2076
2077
2078
2079
2080
2081







-
+







    sqlite3VdbeVerifyAbortable(v, onError);
    sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRowidOk, regNewData);
    VdbeCoverage(v);

    switch( onError ){
      default: {
        onError = OE_Abort;
        /* Fall thru into the next case */
        /* no break */ deliberate_fall_through
      }
      case OE_Rollback:
      case OE_Abort:
      case OE_Fail: {
        testcase( onError==OE_Rollback );
        testcase( onError==OE_Abort );
        testcase( onError==OE_Fail );
1548
1549
1550
1551
1552
1553
1554
1555

1556
1557
1558
1559
1560
1561
1562


1563
1564
1565
1566
1567
1568
1569
2101
2102
2103
2104
2105
2106
2107

2108




2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120







-
+
-
-
-
-



+
+







        ** but being more selective here allows statements like:
        **
        **   REPLACE INTO t(rowid) VALUES($newrowid)
        **
        ** to run without a statement journal if there are no indexes on the
        ** table.
        */
        Trigger *pTrigger = 0;
        if( regTrigCnt ){
        if( db->flags&SQLITE_RecTriggers ){
          pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
        }
        if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
          sqlite3MultiWrite(pParse);
          sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
                                   regNewData, 1, 0, OE_Replace, 1, -1);
          sqlite3VdbeAddOp2(v, OP_AddImm, regTrigCnt, 1); /* incr trigger cnt */
          nReplaceTrig++;
        }else{
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
          assert( HasRowid(pTab) );
          /* This OP_Delete opcode fires the pre-update-hook only. It does
          ** not modify the b-tree. It is more efficient to let the coming
          ** OP_Insert replace the existing entry than it is to delete the
          ** existing entry and then insert a new one. */
1577
1578
1579
1580
1581
1582
1583
1584

1585
1586
1587
1588
1589
1590
1591
1592
1593


1594

1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606

1607



1608
1609
1610
1611

1612
1613
1614

1615
1616
1617
1618



1619
1620
1621
1622




1623
1624
1625
1626

1627
1628
1629
1630
1631
1632
1633
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







-
+









+
+
-
+












+
-
+
+
+




+


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



-
+







        }
        seenReplace = 1;
        break;
      }
#ifndef SQLITE_OMIT_UPSERT
      case OE_Update: {
        sqlite3UpsertDoUpdate(pParse, pUpsert, pTab, 0, iDataCur);
        /* Fall through */
        /* no break */ deliberate_fall_through
      }
#endif
      case OE_Ignore: {
        testcase( onError==OE_Ignore );
        sqlite3VdbeGoto(v, ignoreDest);
        break;
      }
    }
    sqlite3VdbeResolveLabel(v, addrRowidOk);
    if( pUpsert && pUpsertClause!=pUpsert ){
      upsertIpkReturn = sqlite3VdbeAddOp0(v, OP_Goto);
    if( ipkTop ){
    }else if( ipkTop ){
      ipkBottom = sqlite3VdbeAddOp0(v, OP_Goto);
      sqlite3VdbeJumpHere(v, ipkTop-1);
    }
  }

  /* Test all UNIQUE constraints by creating entries for each UNIQUE
  ** index and making sure that duplicate entries do not already exist.
  ** Compute the revised record entries for indices as we go.
  **
  ** This loop also handles the case of the PRIMARY KEY index for a
  ** WITHOUT ROWID table.
  */
  for(pIdx = indexIteratorFirst(&sIdxIter, &ix);
  for(ix=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, ix++){
      pIdx;
      pIdx = indexIteratorNext(&sIdxIter, &ix)
  ){
    int regIdx;          /* Range of registers hold conent for pIdx */
    int regR;            /* Range of registers holding conflicting PK */
    int iThisCur;        /* Cursor for this UNIQUE index */
    int addrUniqueOk;    /* Jump here if the UNIQUE constraint is satisfied */
    int addrConflictCk;  /* First opcode in the conflict check logic */

    if( aRegIdx[ix]==0 ) continue;  /* Skip indices that do not change */
    if( pUpIdx==pIdx ){
    if( pUpsert ){
      addrUniqueOk = upsertJump+1;
      upsertBypass = sqlite3VdbeGoto(v, 0);
      VdbeComment((v, "Skip upsert subroutine"));
      sqlite3VdbeJumpHere(v, upsertJump);
      pUpsertClause = sqlite3UpsertOfIndex(pUpsert, pIdx);
      if( upsertIpkDelay && pUpsertClause==pUpsert ){
        sqlite3VdbeJumpHere(v, upsertIpkDelay);
    }else{
      addrUniqueOk = sqlite3VdbeMakeLabel(v);
    }
    if( bAffinityDone==0 && (pUpIdx==0 || pUpIdx==pIdx) ){
      }
    }
    addrUniqueOk = sqlite3VdbeMakeLabel(pParse);
    if( bAffinityDone==0 ){
      sqlite3TableAffinity(v, pTab, regNewData+1);
      bAffinityDone = 1;
    }
    VdbeNoopComment((v, "uniqueness check for %s", pIdx->zName));
    VdbeNoopComment((v, "prep index %s", pIdx->zName));
    iThisCur = iIdxCur+ix;


    /* Skip partial indices for which the WHERE clause is not true */
    if( pIdx->pPartIdxWhere ){
      sqlite3VdbeAddOp2(v, OP_Null, 0, aRegIdx[ix]);
      pParse->iSelfTab = -(regNewData+1);
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655







1656
1657
1658


1659
1660
1661
1662
1663

1664


1665

1666
1667
1668
1669
1670
1671
1672
2200
2201
2202
2203
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







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





+
-
+
+

+







      int iField = pIdx->aiColumn[i];
      int x;
      if( iField==XN_EXPR ){
        pParse->iSelfTab = -(regNewData+1);
        sqlite3ExprCodeCopy(pParse, pIdx->aColExpr->a[i].pExpr, regIdx+i);
        pParse->iSelfTab = 0;
        VdbeComment((v, "%s column %d", pIdx->zName, i));
      }else{
        if( iField==XN_ROWID || iField==pTab->iPKey ){
          x = regNewData;
        }else{
          x = iField + regNewData + 1;
      }else if( iField==XN_ROWID || iField==pTab->iPKey ){
        x = regNewData;
        sqlite3VdbeAddOp2(v, OP_IntCopy, x, regIdx+i);
        VdbeComment((v, "rowid"));
      }else{
        testcase( sqlite3TableColumnToStorage(pTab, iField)!=iField );
        x = sqlite3TableColumnToStorage(pTab, iField) + regNewData + 1;
        }
        sqlite3VdbeAddOp2(v, iField<0 ? OP_IntCopy : OP_SCopy, x, regIdx+i);
        VdbeComment((v, "%s", iField<0 ? "rowid" : pTab->aCol[iField].zName));
        sqlite3VdbeAddOp2(v, OP_SCopy, x, regIdx+i);
        VdbeComment((v, "%s", pTab->aCol[iField].zCnName));
      }
    }
    sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[ix]);
    VdbeComment((v, "for %s", pIdx->zName));
#ifdef SQLITE_ENABLE_NULL_TRIM
    if( pIdx->idxType==SQLITE_IDXTYPE_PRIMARYKEY ){
    if( pIdx->idxType==2 ) sqlite3SetMakeRecordP5(v, pIdx->pTable);
      sqlite3SetMakeRecordP5(v, pIdx->pTable);
    }
#endif
    sqlite3VdbeReleaseRegisters(pParse, regIdx, pIdx->nColumn, 0, 0);

    /* In an UPDATE operation, if this index is the PRIMARY KEY index 
    ** of a WITHOUT ROWID table and there has been no change the
    ** primary key, then no collision is possible.  The collision detection
    ** logic below can all be skipped. */
    if( isUpdate && pPk==pIdx && pkChng==0 ){
      sqlite3VdbeResolveLabel(v, addrUniqueOk);
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

1744
1745
1746
1747
1748
1749

1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765

1766
1767
1768
1769
1770
1771
1772
2242
2243
2244
2245
2246
2247
2248


2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262

2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274

2275
2276
2277
2278
2279
2280
2281
2282
2283
2284


2285
2286
2287
2288

2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306

2307
2308
2309

2310
2311
2312
2313
2314
2315

2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340







-
-
+
+












-
+
+
+
+
+
+






-
+




+



+
-
-
+
+


-
+

















-
+


-
+





-
+
















+







    if( overrideError!=OE_Default ){
      onError = overrideError;
    }else if( onError==OE_Default ){
      onError = OE_Abort;
    }

    /* Figure out if the upsert clause applies to this index */
    if( pUpIdx==pIdx ){
      if( pUpsert->pUpsertSet==0 ){
    if( pUpsertClause ){
      if( pUpsertClause->isDoUpdate==0 ){
        onError = OE_Ignore;  /* DO NOTHING is the same as INSERT OR IGNORE */
      }else{
        onError = OE_Update;  /* DO UPDATE */
      }
    }

    /* Collision detection may be omitted if all of the following are true:
    **   (1) The conflict resolution algorithm is REPLACE
    **   (2) The table is a WITHOUT ROWID table
    **   (3) There are no secondary indexes on the table
    **   (4) No delete triggers need to be fired if there is a conflict
    **   (5) No FK constraint counters need to be updated if a conflict occurs.
    */ 
    **
    ** This is not possible for ENABLE_PREUPDATE_HOOK builds, as the row
    ** must be explicitly deleted in order to ensure any pre-update hook
    ** is invoked.  */
    assert( IsOrdinaryTable(pTab) );
#ifndef SQLITE_ENABLE_PREUPDATE_HOOK
    if( (ix==0 && pIdx->pNext==0)                   /* Condition 3 */
     && pPk==pIdx                                   /* Condition 2 */
     && onError==OE_Replace                         /* Condition 1 */
     && ( 0==(db->flags&SQLITE_RecTriggers) ||      /* Condition 4 */
          0==sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0))
     && ( 0==(db->flags&SQLITE_ForeignKeys) ||      /* Condition 5 */
         (0==pTab->pFKey && 0==sqlite3FkReferences(pTab)))
         (0==pTab->u.tab.pFKey && 0==sqlite3FkReferences(pTab)))
    ){
      sqlite3VdbeResolveLabel(v, addrUniqueOk);
      continue;
    }
#endif /* ifndef SQLITE_ENABLE_PREUPDATE_HOOK */

    /* Check to see if the new index entry will be unique */
    sqlite3VdbeVerifyAbortable(v, onError);
    addrConflictCk = 
    sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk,
                         regIdx, pIdx->nKeyCol); VdbeCoverage(v);
      sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk,
                           regIdx, pIdx->nKeyCol); VdbeCoverage(v);

    /* Generate code to handle collisions */
    regR = (pIdx==pPk) ? regIdx : sqlite3GetTempRange(pParse, nPkField);
    regR = pIdx==pPk ? regIdx : sqlite3GetTempRange(pParse, nPkField);
    if( isUpdate || onError==OE_Replace ){
      if( HasRowid(pTab) ){
        sqlite3VdbeAddOp2(v, OP_IdxRowid, iThisCur, regR);
        /* Conflict only if the rowid of the existing index entry
        ** is different from old-rowid */
        if( isUpdate ){
          sqlite3VdbeAddOp3(v, OP_Eq, regR, addrUniqueOk, regOldData);
          sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
          VdbeCoverage(v);
        }
      }else{
        int x;
        /* Extract the PRIMARY KEY from the end of the index entry and
        ** store it in registers regR..regR+nPk-1 */
        if( pIdx!=pPk ){
          for(i=0; i<pPk->nKeyCol; i++){
            assert( pPk->aiColumn[i]>=0 );
            x = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[i]);
            x = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[i]);
            sqlite3VdbeAddOp3(v, OP_Column, iThisCur, x, regR+i);
            VdbeComment((v, "%s.%s", pTab->zName,
                         pTab->aCol[pPk->aiColumn[i]].zName));
                         pTab->aCol[pPk->aiColumn[i]].zCnName));
          }
        }
        if( isUpdate ){
          /* If currently processing the PRIMARY KEY of a WITHOUT ROWID 
          ** table, only conflict if the new PRIMARY KEY values are actually
          ** different from the old.
          ** different from the old.  See TH3 withoutrowid04.test.
          **
          ** For a UNIQUE index, only conflict if the PRIMARY KEY values
          ** of the matched index row are different from the original PRIMARY
          ** KEY values of this row before the update.  */
          int addrJump = sqlite3VdbeCurrentAddr(v)+pPk->nKeyCol;
          int op = OP_Ne;
          int regCmp = (IsPrimaryKeyIndex(pIdx) ? regIdx : regR);
  
          for(i=0; i<pPk->nKeyCol; i++){
            char *p4 = (char*)sqlite3LocateCollSeq(pParse, pPk->azColl[i]);
            x = pPk->aiColumn[i];
            assert( x>=0 );
            if( i==(pPk->nKeyCol-1) ){
              addrJump = addrUniqueOk;
              op = OP_Eq;
            }
            x = sqlite3TableColumnToStorage(pTab, x);
            sqlite3VdbeAddOp4(v, op, 
                regOldData+1+x, addrJump, regCmp+i, p4, P4_COLLSEQ
            );
            sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
            VdbeCoverageIf(v, op==OP_Eq);
            VdbeCoverageIf(v, op==OP_Ne);
          }
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
2354
2355
2356
2357
2358
2359
2360

2361
2362
2363
2364
2365
2366
2367
2368
2369
2370

2371
2372
2373
2374
2375
2376


2377
2378
2379
2380


2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443




2444
2445
2446
2447
2448
2449
2450

2451

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
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510

2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550







-
+








+
-
+

+
+
+
+
-
-
+
+
+

-
-
+
+




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




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

-




-
+

+


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




















-
+






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







        testcase( onError==OE_Fail );
        sqlite3UniqueConstraint(pParse, onError, pIdx);
        break;
      }
#ifndef SQLITE_OMIT_UPSERT
      case OE_Update: {
        sqlite3UpsertDoUpdate(pParse, pUpsert, pTab, pIdx, iIdxCur+ix);
        /* Fall through */
        /* no break */ deliberate_fall_through
      }
#endif
      case OE_Ignore: {
        testcase( onError==OE_Ignore );
        sqlite3VdbeGoto(v, ignoreDest);
        break;
      }
      default: {
        int nConflictCk;   /* Number of opcodes in conflict check logic */
        Trigger *pTrigger = 0;

        assert( onError==OE_Replace );
        nConflictCk = sqlite3VdbeCurrentAddr(v) - addrConflictCk;
        assert( nConflictCk>0 || db->mallocFailed );
        testcase( nConflictCk<=0 );
        testcase( nConflictCk>1 );
        if( db->flags&SQLITE_RecTriggers ){
          pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
        if( regTrigCnt ){
          sqlite3MultiWrite(pParse);
          nReplaceTrig++;
        }
        if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
          sqlite3MultiWrite(pParse);
        if( pTrigger && isUpdate ){
          sqlite3VdbeAddOp1(v, OP_CursorLock, iDataCur);
        }
        sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
            regR, nPkField, 0, OE_Replace,
            (pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), iThisCur);
        if( pTrigger && isUpdate ){
          sqlite3VdbeAddOp1(v, OP_CursorUnlock, iDataCur);
        }
        if( regTrigCnt ){
          int addrBypass;  /* Jump destination to bypass recheck logic */

          sqlite3VdbeAddOp2(v, OP_AddImm, regTrigCnt, 1); /* incr trigger cnt */
          addrBypass = sqlite3VdbeAddOp0(v, OP_Goto);  /* Bypass recheck */
          VdbeComment((v, "bypass recheck"));

          /* Here we insert code that will be invoked after all constraint
          ** checks have run, if and only if one or more replace triggers
          ** fired. */
          sqlite3VdbeResolveLabel(v, lblRecheckOk);
          lblRecheckOk = sqlite3VdbeMakeLabel(pParse);
          if( pIdx->pPartIdxWhere ){
            /* Bypass the recheck if this partial index is not defined
            ** for the current row */
            sqlite3VdbeAddOp2(v, OP_IsNull, regIdx-1, lblRecheckOk);
            VdbeCoverage(v);
          }
          /* Copy the constraint check code from above, except change
          ** the constraint-ok jump destination to be the address of
          ** the next retest block */
          while( nConflictCk>0 ){
            VdbeOp x;    /* Conflict check opcode to copy */
            /* The sqlite3VdbeAddOp4() call might reallocate the opcode array.
            ** Hence, make a complete copy of the opcode, rather than using
            ** a pointer to the opcode. */
            x = *sqlite3VdbeGetOp(v, addrConflictCk);
            if( x.opcode!=OP_IdxRowid ){
              int p2;      /* New P2 value for copied conflict check opcode */
              const char *zP4;
              if( sqlite3OpcodeProperty[x.opcode]&OPFLG_JUMP ){
                p2 = lblRecheckOk;
              }else{
                p2 = x.p2;
              }
              zP4 = x.p4type==P4_INT32 ? SQLITE_INT_TO_PTR(x.p4.i) : x.p4.z;
              sqlite3VdbeAddOp4(v, x.opcode, x.p1, p2, x.p3, zP4, x.p4type);
              sqlite3VdbeChangeP5(v, x.p5);
              VdbeCoverageIf(v, p2!=x.p2);
            }
            nConflictCk--;
            addrConflictCk++;
          }
          /* If the retest fails, issue an abort */
          sqlite3UniqueConstraint(pParse, OE_Abort, pIdx);

          sqlite3VdbeJumpHere(v, addrBypass); /* Terminate the recheck bypass */
        }
        seenReplace = 1;
        break;
      }
    }
    sqlite3VdbeResolveLabel(v, addrUniqueOk);
    if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField);
    if( pUpIdx==pIdx ){
      sqlite3VdbeGoto(v, upsertJump+1);
      sqlite3VdbeJumpHere(v, upsertBypass);
    }else{
    if( pUpsertClause 
     && upsertIpkReturn
     && sqlite3UpsertNextIsIPK(pUpsertClause)
    ){
      sqlite3VdbeGoto(v, upsertIpkDelay+1);
      sqlite3VdbeJumpHere(v, upsertIpkReturn);
      upsertIpkReturn = 0;
      sqlite3VdbeResolveLabel(v, addrUniqueOk);
    }
    if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField);
  }

  /* If the IPK constraint is a REPLACE, run it last */
  if( ipkTop ){
    sqlite3VdbeGoto(v, ipkTop+1);
    sqlite3VdbeGoto(v, ipkTop);
    VdbeComment((v, "Do IPK REPLACE"));
    assert( ipkBottom>0 );
    sqlite3VdbeJumpHere(v, ipkBottom);
  }

  /* Recheck all uniqueness constraints after replace triggers have run */
  testcase( regTrigCnt!=0 && nReplaceTrig==0 );
  assert( regTrigCnt!=0 || nReplaceTrig==0 );
  if( nReplaceTrig ){
    sqlite3VdbeAddOp2(v, OP_IfNot, regTrigCnt, lblRecheckOk);VdbeCoverage(v);
    if( !pPk ){
      if( isUpdate ){
        sqlite3VdbeAddOp3(v, OP_Eq, regNewData, addrRecheck, regOldData);
        sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
        VdbeCoverage(v);
      }
      sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRecheck, regNewData);
      VdbeCoverage(v);
      sqlite3RowidConstraint(pParse, OE_Abort, pTab);
    }else{
      sqlite3VdbeGoto(v, addrRecheck);
    }
    sqlite3VdbeResolveLabel(v, lblRecheckOk);
  }

  /* Generate the table record */
  if( HasRowid(pTab) ){
    int regRec = aRegIdx[ix];
    sqlite3VdbeAddOp3(v, OP_MakeRecord, regNewData+1, pTab->nNVCol, regRec);
    sqlite3SetMakeRecordP5(v, pTab);
    if( !bAffinityDone ){
      sqlite3TableAffinity(v, pTab, 0);
    }
  }

  *pbMayReplace = seenReplace;
  VdbeModuleComment((v, "END: GenCnstCks(%d)", seenReplace));
}

#ifdef SQLITE_ENABLE_NULL_TRIM
/*
** Change the P5 operand on the last opcode (which should be an OP_MakeRecord)
** to be the number of columns in table pTab that must not be NULL-trimmed.
**
** Or if no columns of pTab may be NULL-trimmed, leave P5 at zero.
*/
void sqlite3SetMakeRecordP5(Vdbe *v, Table *pTab){
  u16 i;

  /* Records with omitted columns are only allowed for schema format
  ** version 2 and later (SQLite version 3.1.4, 2005-02-20). */
  if( pTab->pSchema->file_format<2 ) return;

  for(i=pTab->nCol-1; i>0; i--){
    if( pTab->aCol[i].pDflt!=0 ) break;
    if( pTab->aCol[i].iDflt!=0 ) break;
    if( pTab->aCol[i].colFlags & COLFLAG_PRIMKEY ) break;
  }
  sqlite3VdbeChangeP5(v, i+1);
}
#endif

/*
** Table pTab is a WITHOUT ROWID table that is being written to. The cursor
** number is iCur, and register regData contains the new record for the
** PK index. This function adds code to invoke the pre-update hook,
** if one is registered.
*/
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
static void codeWithoutRowidPreupdate(
  Parse *pParse,                  /* Parse context */
  Table *pTab,                    /* Table being updated */
  int iCur,                       /* Cursor number for table */
  int regData                     /* Data containing new record */
){
  Vdbe *v = pParse->pVdbe;
  int r = sqlite3GetTempReg(pParse);
  assert( !HasRowid(pTab) );
  assert( 0==(pParse->db->mDbFlags & DBFLAG_Vacuum) || CORRUPT_DB );
  sqlite3VdbeAddOp2(v, OP_Integer, 0, r);
  sqlite3VdbeAddOp4(v, OP_Insert, iCur, regData, r, (char*)pTab, P4_TABLE);
  sqlite3VdbeChangeP5(v, OPFLAG_ISNOOP);
  sqlite3ReleaseTempReg(pParse, r);
}
#else
# define codeWithoutRowidPreupdate(a,b,c,d)
#endif

/*
** This routine generates code to finish the INSERT or UPDATE operation
** that was started by a prior call to sqlite3GenerateConstraintChecks.
** A consecutive range of registers starting at regNewData contains the
** rowid and the content to be inserted.
**
** The arguments to this routine should be the same as the first six
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892

1893
1894

1895




1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910

1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941

1942
1943
1944
1945
1946
1947
1948
2560
2561
2562
2563
2564
2565
2566


2567

2568
2569
2570
2571
2572
2573

2574
2575

2576
2577
2578
2579
2580
2581
2582

2583
2584
2585
2586
2587
2588

2589
2590

2591


2592


2593

2594
2595
2596
2597
2598
2599
2600







2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612

2613
2614
2615
2616
2617
2618
2619
2620







-
-

-






-
+

-
+

+
+
+
+

-






-


-

-
-
+
-
-

-







-
-
-
-
-
-
-












-
+







  int update_flags,   /* True for UPDATE, False for INSERT */
  int appendBias,     /* True if this is likely to be an append */
  int useSeekResult   /* True to set the USESEEKRESULT flag on OP_[Idx]Insert */
){
  Vdbe *v;            /* Prepared statements under construction */
  Index *pIdx;        /* An index being inserted or updated */
  u8 pik_flags;       /* flag values passed to the btree insert */
  int regData;        /* Content registers (after the rowid) */
  int regRec;         /* Register holding assembled record for the table */
  int i;              /* Loop counter */
  u8 bAffinityDone = 0; /* True if OP_Affinity has been run already */

  assert( update_flags==0
       || update_flags==OPFLAG_ISUPDATE
       || update_flags==(OPFLAG_ISUPDATE|OPFLAG_SAVEPOSITION)
  );

  v = sqlite3GetVdbe(pParse);
  v = pParse->pVdbe;
  assert( v!=0 );
  assert( pTab->pSelect==0 );  /* This table is not a VIEW */
  assert( !IsView(pTab) );  /* This table is not a VIEW */
  for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
    /* All REPLACE indexes are at the end of the list */
    assert( pIdx->onError!=OE_Replace
         || pIdx->pNext==0
         || pIdx->pNext->onError==OE_Replace );
    if( aRegIdx[i]==0 ) continue;
    bAffinityDone = 1;
    if( pIdx->pPartIdxWhere ){
      sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2);
      VdbeCoverage(v);
    }
    pik_flags = (useSeekResult ? OPFLAG_USESEEKRESULT : 0);
    if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
      assert( pParse->nested==0 );
      pik_flags |= OPFLAG_NCHANGE;
      pik_flags |= (update_flags & OPFLAG_SAVEPOSITION);
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
      if( update_flags==0 ){
        sqlite3VdbeAddOp4(v, OP_InsertInt, 
            iIdxCur+i, aRegIdx[i], 0, (char*)pTab, P4_TABLE
        codeWithoutRowidPreupdate(pParse, pTab, iIdxCur+i, aRegIdx[i]);
        );
        sqlite3VdbeChangeP5(v, OPFLAG_ISNOOP);
      }
#endif
    }
    sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i],
                         aRegIdx[i]+1,
                         pIdx->uniqNotNull ? pIdx->nKeyCol: pIdx->nColumn);
    sqlite3VdbeChangeP5(v, pik_flags);
  }
  if( !HasRowid(pTab) ) return;
  regData = regNewData + 1;
  regRec = sqlite3GetTempReg(pParse);
  sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec);
  sqlite3SetMakeRecordP5(v, pTab);
  if( !bAffinityDone ){
    sqlite3TableAffinity(v, pTab, 0);
  }
  if( pParse->nested ){
    pik_flags = 0;
  }else{
    pik_flags = OPFLAG_NCHANGE;
    pik_flags |= (update_flags?update_flags:OPFLAG_LASTROWID);
  }
  if( appendBias ){
    pik_flags |= OPFLAG_APPEND;
  }
  if( useSeekResult ){
    pik_flags |= OPFLAG_USESEEKRESULT;
  }
  sqlite3VdbeAddOp3(v, OP_Insert, iDataCur, regRec, regNewData);
  sqlite3VdbeAddOp3(v, OP_Insert, iDataCur, aRegIdx[i], regNewData);
  if( !pParse->nested ){
    sqlite3VdbeAppendP4(v, pTab, P4_TABLE);
  }
  sqlite3VdbeChangeP5(v, pik_flags);
}

/*
1982
1983
1984
1985
1986
1987
1988
1989
1990



1991
1992
1993
1994

1995
1996
1997
1998
1999
2000
2001
2654
2655
2656
2657
2658
2659
2660


2661
2662
2663
2664
2665
2666

2667
2668
2669
2670
2671
2672
2673
2674







-
-
+
+
+



-
+







  Index *pIdx;
  Vdbe *v;

  assert( op==OP_OpenRead || op==OP_OpenWrite );
  assert( op==OP_OpenWrite || p5==0 );
  if( IsVirtual(pTab) ){
    /* This routine is a no-op for virtual tables. Leave the output
    ** variables *piDataCur and *piIdxCur uninitialized so that valgrind
    ** can detect if they are used by mistake in the caller. */
    ** variables *piDataCur and *piIdxCur set to illegal cursor numbers
    ** for improved error detection. */
    *piDataCur = *piIdxCur = -999;
    return 0;
  }
  iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
  v = sqlite3GetVdbe(pParse);
  v = pParse->pVdbe;
  assert( v!=0 );
  if( iBase<0 ) iBase = pParse->nTab;
  iDataCur = iBase++;
  if( piDataCur ) *piDataCur = iDataCur;
  if( HasRowid(pTab) && (aToOpen==0 || aToOpen[0]) ){
    sqlite3OpenTable(pParse, iDataCur, iDb, pTab, op);
  }else{
2044
2045
2046
2047
2048
2049
2050
2051

2052
2053
2054
2055
2056
2057
2058
2717
2718
2719
2720
2721
2722
2723

2724
2725
2726
2727
2728
2729
2730
2731







-
+







**    *   The same collating sequence on each column
**    *   The index has the exact same WHERE clause
*/
static int xferCompatibleIndex(Index *pDest, Index *pSrc){
  int i;
  assert( pDest && pSrc );
  assert( pDest->pTable!=pSrc->pTable );
  if( pDest->nKeyCol!=pSrc->nKeyCol ){
  if( pDest->nKeyCol!=pSrc->nKeyCol || pDest->nColumn!=pSrc->nColumn ){
    return 0;   /* Different number of columns */
  }
  if( pDest->onError!=pSrc->onError ){
    return 0;   /* Different conflict resolution strategies */
  }
  for(i=0; i<pSrc->nKeyCol; i++){
    if( pSrc->aiColumn[i]!=pDest->aiColumn[i] ){
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
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 onError,          /* How to handle constraint errors */
  int iDbDest           /* The database of pDest */
){
  sqlite3 *db = pParse->db;
  ExprList *pEList;                /* The result set of the SELECT */
  Table *pSrc;                     /* The table in the FROM clause of SELECT */
  Index *pSrcIdx, *pDestIdx;       /* Source and destination indices */
  struct SrcList_item *pItem;      /* An element of pSelect->pSrc */
  SrcItem *pItem;                  /* An element of pSelect->pSrc */
  int i;                           /* Loop counter */
  int iDbSrc;                      /* The database of pSrc */
  int iSrc, iDest;                 /* Cursors from source and destination */
  int addr1, addr2;                /* Loop addresses */
  int emptyDestTest = 0;           /* Address of test for empty pDest */
  int emptySrcTest = 0;            /* Address of test for empty pSrc */
  Vdbe *v;                         /* The VDBE we are building */
  int regAutoinc;                  /* Memory register used by AUTOINC */
  int destHasUniqueIdx = 0;        /* True if pDest has a UNIQUE index */
  int regData, regRowid;           /* Registers holding data and rowid */

  if( pSelect==0 ){
  assert( pSelect!=0 );
    return 0;   /* Must be of the form  INSERT INTO ... SELECT ... */
  }
  if( pParse->pWith || pSelect->pWith ){
    /* Do not attempt to process this query if there are an WITH clauses
    ** attached to it. Proceeding may generate a false "no such table: xxx"
    ** error if pSelect reads from a CTE named "xxx".  */
    return 0;
  }
  if( sqlite3TriggerList(pParse, pDest) ){
    return 0;   /* tab1 must not have triggers */
  }
#ifndef SQLITE_OMIT_VIRTUALTABLE
  if( IsVirtual(pDest) ){
    return 0;   /* tab1 must not be a virtual table */
  }
#endif
  if( onError==OE_Default ){
    if( pDest->iPKey>=0 ) onError = pDest->keyConf;
2191
2192
2193
2194
2195
2196
2197
2198


2199
2200
2201
2202
2203
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
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243










2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258







2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272

2273

2274
2275
2276
2277
2278
2279
2280
2859
2860
2861
2862
2863
2864
2865

2866
2867
2868
2869
2870
2871
2872


2873





2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932

2933
2934
2935
2936
2937
2938
2939
2940






2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987

2988
2989
2990
2991
2992
2993
2994
2995







-
+
+





-
-
+
-
-
-
-
-
+






+
+
+











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



-
+
+






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















+
+
+
+
+
+
+














+
-
+







  ** we have to check the semantics.
  */
  pItem = pSelect->pSrc->a;
  pSrc = sqlite3LocateTableItem(pParse, 0, pItem);
  if( pSrc==0 ){
    return 0;   /* FROM clause does not contain a real table */
  }
  if( pSrc==pDest ){
  if( pSrc->tnum==pDest->tnum && pSrc->pSchema==pDest->pSchema ){
    testcase( pSrc!=pDest ); /* Possible due to bad sqlite_schema.rootpage */
    return 0;   /* tab1 and tab2 may not be the same table */
  }
  if( HasRowid(pDest)!=HasRowid(pSrc) ){
    return 0;   /* source and destination must both be WITHOUT ROWID or not */
  }
#ifndef SQLITE_OMIT_VIRTUALTABLE
  if( IsVirtual(pSrc) ){
  if( !IsOrdinaryTable(pSrc) ){
    return 0;   /* tab2 must not be a virtual table */
  }
#endif
  if( pSrc->pSelect ){
    return 0;   /* tab2 may not be a view */
    return 0;   /* tab2 may not be a view or virtual table */
  }
  if( pDest->nCol!=pSrc->nCol ){
    return 0;   /* Number of columns must be the same in tab1 and tab2 */
  }
  if( pDest->iPKey!=pSrc->iPKey ){
    return 0;   /* Both tables must have the same INTEGER PRIMARY KEY */
  }
  if( (pDest->tabFlags & TF_Strict)!=0 && (pSrc->tabFlags & TF_Strict)==0 ){
    return 0;   /* Cannot feed from a non-strict into a strict table */
  }
  for(i=0; i<pDest->nCol; i++){
    Column *pDestCol = &pDest->aCol[i];
    Column *pSrcCol = &pSrc->aCol[i];
#ifdef SQLITE_ENABLE_HIDDEN_COLUMNS
    if( (db->mDbFlags & DBFLAG_Vacuum)==0 
     && (pDestCol->colFlags | pSrcCol->colFlags) & COLFLAG_HIDDEN 
    ){
      return 0;    /* Neither table may have __hidden__ columns */
    }
#endif
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
    /* Even if tables t1 and t2 have identical schemas, if they contain
    ** generated columns, then this statement is semantically incorrect:
    **
    **     INSERT INTO t2 SELECT * FROM t1;
    **
    ** The reason is that generated column values are returned by the
    ** the SELECT statement on the right but the INSERT statement on the
    ** left wants them to be omitted.
    **
    ** Nevertheless, this is a useful notational shorthand to tell SQLite
    ** to do a bulk transfer all of the content from t1 over to t2.
    ** 
    ** We could, in theory, disable this (except for internal use by the
    ** VACUUM command where it is actually needed).  But why do that?  It
    ** seems harmless enough, and provides a useful service.
    */
    if( (pDestCol->colFlags & COLFLAG_GENERATED) !=
        (pSrcCol->colFlags & COLFLAG_GENERATED) ){
      return 0;    /* Both columns have the same generated-column type */
    }
    /* But the transfer is only allowed if both the source and destination
    ** tables have the exact same expressions for generated columns.
    ** This requirement could be relaxed for VIRTUAL columns, I suppose.
    */
    if( (pDestCol->colFlags & COLFLAG_GENERATED)!=0 ){
      if( sqlite3ExprCompare(0,
             sqlite3ColumnExpr(pSrc, pSrcCol),
             sqlite3ColumnExpr(pDest, pDestCol), -1)!=0 ){
        testcase( pDestCol->colFlags & COLFLAG_VIRTUAL );
        testcase( pDestCol->colFlags & COLFLAG_STORED );
        return 0;  /* Different generator expressions */
      }
    }
#endif
    if( pDestCol->affinity!=pSrcCol->affinity ){
      return 0;    /* Affinity must be the same on all columns */
    }
    if( sqlite3_stricmp(pDestCol->zColl, pSrcCol->zColl)!=0 ){
    if( sqlite3_stricmp(sqlite3ColumnColl(pDestCol), 
                        sqlite3ColumnColl(pSrcCol))!=0 ){
      return 0;    /* Collating sequence must be the same on all columns */
    }
    if( pDestCol->notNull && !pSrcCol->notNull ){
      return 0;    /* tab2 must be NOT NULL if tab1 is */
    }
    /* Default values for second and subsequent columns need to match. */
    if( i>0 ){
      assert( pDestCol->pDflt==0 || pDestCol->pDflt->op==TK_SPAN );
      assert( pSrcCol->pDflt==0 || pSrcCol->pDflt->op==TK_SPAN );
      if( (pDestCol->pDflt==0)!=(pSrcCol->pDflt==0) 
       || (pDestCol->pDflt && strcmp(pDestCol->pDflt->u.zToken,
                                       pSrcCol->pDflt->u.zToken)!=0)
    if( (pDestCol->colFlags & COLFLAG_GENERATED)==0 && i>0 ){
      Expr *pDestExpr = sqlite3ColumnExpr(pDest, pDestCol);
      Expr *pSrcExpr = sqlite3ColumnExpr(pSrc, pSrcCol);
      assert( pDestExpr==0 || pDestExpr->op==TK_SPAN );
      assert( pDestExpr==0 || !ExprHasProperty(pDestExpr, EP_IntValue) );
      assert( pSrcExpr==0 || pSrcExpr->op==TK_SPAN );
      assert( pSrcExpr==0 || !ExprHasProperty(pSrcExpr, EP_IntValue) );
      if( (pDestExpr==0)!=(pSrcExpr==0) 
       || (pDestExpr!=0 && strcmp(pDestExpr->u.zToken,
                                       pSrcExpr->u.zToken)!=0)
      ){
        return 0;    /* Default values must be the same for all columns */
      }
    }
  }
  for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){
    if( IsUniqueIndex(pDestIdx) ){
      destHasUniqueIdx = 1;
    }
    for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){
      if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break;
    }
    if( pSrcIdx==0 ){
      return 0;    /* pDestIdx has no corresponding index in pSrc */
    }
    if( pSrcIdx->tnum==pDestIdx->tnum && pSrc->pSchema==pDest->pSchema
         && sqlite3FaultSim(411)==SQLITE_OK ){
      /* The sqlite3FaultSim() call allows this corruption test to be
      ** bypassed during testing, in order to exercise other corruption tests
      ** further downstream. */
      return 0;   /* Corrupt schema - two indexes on the same btree */
    }
  }
#ifndef SQLITE_OMIT_CHECK
  if( pDest->pCheck && sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1) ){
    return 0;   /* Tables have different CHECK constraints.  Ticket #2252 */
  }
#endif
#ifndef SQLITE_OMIT_FOREIGN_KEY
  /* Disallow the transfer optimization if the destination table constains
  ** any foreign key constraints.  This is more restrictive than necessary.
  ** But the main beneficiary of the transfer optimization is the VACUUM 
  ** command, and the VACUUM command disables foreign key constraints.  So
  ** the extra complication to make this rule less restrictive is probably
  ** not worth the effort.  Ticket [6284df89debdfa61db8073e062908af0c9b6118e]
  */
  assert( IsOrdinaryTable(pDest) );
  if( (db->flags & SQLITE_ForeignKeys)!=0 && pDest->pFKey!=0 ){
  if( (db->flags & SQLITE_ForeignKeys)!=0 && pDest->u.tab.pFKey!=0 ){
    return 0;
  }
#endif
  if( (db->flags & SQLITE_CountRows)!=0 ){
    return 0;  /* xfer opt does not play well with PRAGMA count_changes */
  }

2288
2289
2290
2291
2292
2293
2294

2295
2296
2297
2298
2299
2300
2301
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017







+







  iDbSrc = sqlite3SchemaToIndex(db, pSrc->pSchema);
  v = sqlite3GetVdbe(pParse);
  sqlite3CodeVerifySchema(pParse, iDbSrc);
  iSrc = pParse->nTab++;
  iDest = pParse->nTab++;
  regAutoinc = autoIncBegin(pParse, iDbDest, pDest);
  regData = sqlite3GetTempReg(pParse);
  sqlite3VdbeAddOp2(v, OP_Null, 0, regData);
  regRowid = sqlite3GetTempReg(pParse);
  sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite);
  assert( HasRowid(pDest) || destHasUniqueIdx );
  if( (db->mDbFlags & DBFLAG_Vacuum)==0 && (
      (pDest->iPKey<0 && pDest->pIndex!=0)          /* (1) */
   || destHasUniqueIdx                              /* (2) */
   || (onError!=OE_Abort && onError!=OE_Rollback)   /* (3) */
2323
2324
2325
2326
2327
2328
2329

2330
2331
2332
2333
2334






2335
2336

2337
2338
2339
2340
2341
2342

2343
2344
2345
2346

2347
2348

2349









2350
2351




2352

2353
2354
2355
2356
2357
2358
2359
3039
3040
3041
3042
3043
3044
3045
3046





3047
3048
3049
3050
3051
3052
3053

3054
3055
3056
3057
3058
3059

3060
3061
3062


3063
3064

3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075


3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088







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

-
+





-
+


-
-
+

-
+

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

+







  }
  if( HasRowid(pSrc) ){
    u8 insFlags;
    sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead);
    emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v);
    if( pDest->iPKey>=0 ){
      addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
      if( (db->mDbFlags & DBFLAG_Vacuum)==0 ){
      sqlite3VdbeVerifyAbortable(v, onError);
      addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid);
      VdbeCoverage(v);
      sqlite3RowidConstraint(pParse, onError, pDest);
      sqlite3VdbeJumpHere(v, addr2);
        sqlite3VdbeVerifyAbortable(v, onError);
        addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid);
        VdbeCoverage(v);
        sqlite3RowidConstraint(pParse, onError, pDest);
        sqlite3VdbeJumpHere(v, addr2);
      }
      autoIncStep(pParse, regAutoinc, regRowid);
    }else if( pDest->pIndex==0 ){
    }else if( pDest->pIndex==0 && !(db->mDbFlags & DBFLAG_VacuumInto) ){
      addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid);
    }else{
      addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
      assert( (pDest->tabFlags & TF_Autoincrement)==0 );
    }
    sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);

    if( db->mDbFlags & DBFLAG_Vacuum ){
      sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest);
      insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|
                           OPFLAG_APPEND|OPFLAG_USESEEKRESULT;
      insFlags = OPFLAG_APPEND|OPFLAG_USESEEKRESULT|OPFLAG_PREFORMAT;
    }else{
      insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND;
      insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND|OPFLAG_PREFORMAT;
    }
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
    if( (db->mDbFlags & DBFLAG_Vacuum)==0 ){
      sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
      insFlags &= ~OPFLAG_PREFORMAT;
    }else
#endif
    {
      sqlite3VdbeAddOp3(v, OP_RowCell, iDest, iSrc, regRowid);
    }
    sqlite3VdbeAddOp4(v, OP_Insert, iDest, regData, regRowid,
                      (char*)pDest, P4_TABLE);
    sqlite3VdbeAddOp3(v, OP_Insert, iDest, regData, regRowid);
    if( (db->mDbFlags & DBFLAG_Vacuum)==0 ){
      sqlite3VdbeChangeP4(v, -1, (char*)pDest, P4_TABLE);
    }
    sqlite3VdbeChangeP5(v, insFlags);

    sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); VdbeCoverage(v);
    sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
    sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);
  }else{
    sqlite3TableLock(pParse, iDbDest, pDest->tnum, 1, pDest->zName);
    sqlite3TableLock(pParse, iDbSrc, pSrc->tnum, 0, pSrc->zName);
  }
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395

2396

2397
2398
2399

2400









2401
2402
2403
2404
2405
2406
2407
3096
3097
3098
3099
3100
3101
3102

3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122

3123
3124
3125
3126


3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144







-




















-
+

+

-
-
+

+
+
+
+
+
+
+
+
+







    sqlite3VdbeSetP4KeyInfo(pParse, pSrcIdx);
    VdbeComment((v, "%s", pSrcIdx->zName));
    sqlite3VdbeAddOp3(v, OP_OpenWrite, iDest, pDestIdx->tnum, iDbDest);
    sqlite3VdbeSetP4KeyInfo(pParse, pDestIdx);
    sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR);
    VdbeComment((v, "%s", pDestIdx->zName));
    addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v);
    sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
    if( db->mDbFlags & DBFLAG_Vacuum ){
      /* This INSERT command is part of a VACUUM operation, which guarantees
      ** that the destination table is empty. If all indexed columns use
      ** collation sequence BINARY, then it can also be assumed that the
      ** index will be populated by inserting keys in strictly sorted 
      ** order. In this case, instead of seeking within the b-tree as part
      ** of every OP_IdxInsert opcode, an OP_SeekEnd is added before the
      ** OP_IdxInsert to seek to the point within the b-tree where each key 
      ** should be inserted. This is faster.
      **
      ** If any of the indexed columns use a collation sequence other than
      ** BINARY, this optimization is disabled. This is because the user 
      ** might change the definition of a collation sequence and then run
      ** a VACUUM command. In that case keys may not be written in strictly
      ** sorted order.  */
      for(i=0; i<pSrcIdx->nColumn; i++){
        const char *zColl = pSrcIdx->azColl[i];
        if( sqlite3_stricmp(sqlite3StrBINARY, zColl) ) break;
      }
      if( i==pSrcIdx->nColumn ){
        idxInsFlags = OPFLAG_USESEEKRESULT;
        idxInsFlags = OPFLAG_USESEEKRESULT|OPFLAG_PREFORMAT;
        sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest);
        sqlite3VdbeAddOp2(v, OP_RowCell, iDest, iSrc);
      }
    }
    if( !HasRowid(pSrc) && pDestIdx->idxType==2 ){
    }else if( !HasRowid(pSrc) && pDestIdx->idxType==SQLITE_IDXTYPE_PRIMARYKEY ){
      idxInsFlags |= OPFLAG_NCHANGE;
    }
    if( idxInsFlags!=(OPFLAG_USESEEKRESULT|OPFLAG_PREFORMAT) ){
      sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
      if( (db->mDbFlags & DBFLAG_Vacuum)==0 
       && !HasRowid(pDest) 
       && IsPrimaryKeyIndex(pDestIdx) 
      ){
        codeWithoutRowidPreupdate(pParse, pDest, iDest, regData);
      }
    }
    sqlite3VdbeAddOp2(v, OP_IdxInsert, iDest, regData);
    sqlite3VdbeChangeP5(v, idxInsFlags|OPFLAG_APPEND);
    sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v);
    sqlite3VdbeJumpHere(v, addr1);
    sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
    sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);

Added src/json.c.



















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
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
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
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
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
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
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
1984
1985
1986
1987
1988
1989
1990
1991
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
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
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
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
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
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
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
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
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
2704
2705
2706
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2015-08-12
**
** 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 SQLite JSON functions.
**
** This file began as an extension in ext/misc/json1.c in 2015.  That
** extension proved so useful that it has now been moved into the core.
**
** For the time being, all JSON is stored as pure text.  (We might add
** a JSONB type in the future which stores a binary encoding of JSON in
** a BLOB, but there is no support for JSONB in the current implementation.
** This implementation parses JSON text at 250 MB/s, so it is hard to see
** how JSONB might improve on that.)
*/
#ifndef SQLITE_OMIT_JSON
#include "sqliteInt.h"

/*
** Growing our own isspace() routine this way is twice as fast as
** the library isspace() function, resulting in a 7% overall performance
** increase for the parser.  (Ubuntu14.10 gcc 4.8.4 x64 with -Os).
*/
static const char jsonIsSpace[] = {
  0, 0, 0, 0, 0, 0, 0, 0,     0, 1, 1, 0, 0, 1, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
  1, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
};
#define fast_isspace(x) (jsonIsSpace[(unsigned char)x])

#if !defined(SQLITE_DEBUG) && !defined(SQLITE_COVERAGE_TEST)
#  define VVA(X)
#else
#  define VVA(X) X
#endif

/* Objects */
typedef struct JsonString JsonString;
typedef struct JsonNode JsonNode;
typedef struct JsonParse JsonParse;

/* An instance of this object represents a JSON string
** under construction.  Really, this is a generic string accumulator
** that can be and is used to create strings other than JSON.
*/
struct JsonString {
  sqlite3_context *pCtx;   /* Function context - put error messages here */
  char *zBuf;              /* Append JSON content here */
  u64 nAlloc;              /* Bytes of storage available in zBuf[] */
  u64 nUsed;               /* Bytes of zBuf[] currently used */
  u8 bStatic;              /* True if zBuf is static space */
  u8 bErr;                 /* True if an error has been encountered */
  char zSpace[100];        /* Initial static space */
};

/* JSON type values
*/
#define JSON_NULL     0
#define JSON_TRUE     1
#define JSON_FALSE    2
#define JSON_INT      3
#define JSON_REAL     4
#define JSON_STRING   5
#define JSON_ARRAY    6
#define JSON_OBJECT   7

/* The "subtype" set for JSON values */
#define JSON_SUBTYPE  74    /* Ascii for "J" */

/*
** Names of the various JSON types:
*/
static const char * const jsonType[] = {
  "null", "true", "false", "integer", "real", "text", "array", "object"
};

/* Bit values for the JsonNode.jnFlag field
*/
#define JNODE_RAW     0x01         /* Content is raw, not JSON encoded */
#define JNODE_ESCAPE  0x02         /* Content is text with \ escapes */
#define JNODE_REMOVE  0x04         /* Do not output */
#define JNODE_REPLACE 0x08         /* Replace with JsonNode.u.iReplace */
#define JNODE_PATCH   0x10         /* Patch with JsonNode.u.pPatch */
#define JNODE_APPEND  0x20         /* More ARRAY/OBJECT entries at u.iAppend */
#define JNODE_LABEL   0x40         /* Is a label of an object */


/* A single node of parsed JSON
*/
struct JsonNode {
  u8 eType;              /* One of the JSON_ type values */
  u8 jnFlags;            /* JNODE flags */
  u8 eU;                 /* Which union element to use */
  u32 n;                 /* Bytes of content, or number of sub-nodes */
  union {
    const char *zJContent; /* 1: Content for INT, REAL, and STRING */
    u32 iAppend;           /* 2: More terms for ARRAY and OBJECT */
    u32 iKey;              /* 3: Key for ARRAY objects in json_tree() */
    u32 iReplace;          /* 4: Replacement content for JNODE_REPLACE */
    JsonNode *pPatch;      /* 5: Node chain of patch for JNODE_PATCH */
  } u;
};

/* A completely parsed JSON string
*/
struct JsonParse {
  u32 nNode;         /* Number of slots of aNode[] used */
  u32 nAlloc;        /* Number of slots of aNode[] allocated */
  JsonNode *aNode;   /* Array of nodes containing the parse */
  const char *zJson; /* Original JSON string */
  u32 *aUp;          /* Index of parent of each node */
  u8 oom;            /* Set to true if out of memory */
  u8 nErr;           /* Number of errors seen */
  u16 iDepth;        /* Nesting depth */
  int nJson;         /* Length of the zJson string in bytes */
  u32 iHold;         /* Replace cache line with the lowest iHold value */
};

/*
** Maximum nesting depth of JSON for this implementation.
**
** This limit is needed to avoid a stack overflow in the recursive
** descent parser.  A depth of 2000 is far deeper than any sane JSON
** should go.
*/
#define JSON_MAX_DEPTH  2000

/**************************************************************************
** Utility routines for dealing with JsonString objects
**************************************************************************/

/* Set the JsonString object to an empty string
*/
static void jsonZero(JsonString *p){
  p->zBuf = p->zSpace;
  p->nAlloc = sizeof(p->zSpace);
  p->nUsed = 0;
  p->bStatic = 1;
}

/* Initialize the JsonString object
*/
static void jsonInit(JsonString *p, sqlite3_context *pCtx){
  p->pCtx = pCtx;
  p->bErr = 0;
  jsonZero(p);
}


/* Free all allocated memory and reset the JsonString object back to its
** initial state.
*/
static void jsonReset(JsonString *p){
  if( !p->bStatic ) sqlite3_free(p->zBuf);
  jsonZero(p);
}


/* Report an out-of-memory (OOM) condition 
*/
static void jsonOom(JsonString *p){
  p->bErr = 1;
  sqlite3_result_error_nomem(p->pCtx);
  jsonReset(p);
}

/* Enlarge pJson->zBuf so that it can hold at least N more bytes.
** Return zero on success.  Return non-zero on an OOM error
*/
static int jsonGrow(JsonString *p, u32 N){
  u64 nTotal = N<p->nAlloc ? p->nAlloc*2 : p->nAlloc+N+10;
  char *zNew;
  if( p->bStatic ){
    if( p->bErr ) return 1;
    zNew = sqlite3_malloc64(nTotal);
    if( zNew==0 ){
      jsonOom(p);
      return SQLITE_NOMEM;
    }
    memcpy(zNew, p->zBuf, (size_t)p->nUsed);
    p->zBuf = zNew;
    p->bStatic = 0;
  }else{
    zNew = sqlite3_realloc64(p->zBuf, nTotal);
    if( zNew==0 ){
      jsonOom(p);
      return SQLITE_NOMEM;
    }
    p->zBuf = zNew;
  }
  p->nAlloc = nTotal;
  return SQLITE_OK;
}

/* Append N bytes from zIn onto the end of the JsonString string.
*/
static void jsonAppendRaw(JsonString *p, const char *zIn, u32 N){
  if( N==0 ) return;
  if( (N+p->nUsed >= p->nAlloc) && jsonGrow(p,N)!=0 ) return;
  memcpy(p->zBuf+p->nUsed, zIn, N);
  p->nUsed += N;
}

/* Append formatted text (not to exceed N bytes) to the JsonString.
*/
static void jsonPrintf(int N, JsonString *p, const char *zFormat, ...){
  va_list ap;
  if( (p->nUsed + N >= p->nAlloc) && jsonGrow(p, N) ) return;
  va_start(ap, zFormat);
  sqlite3_vsnprintf(N, p->zBuf+p->nUsed, zFormat, ap);
  va_end(ap);
  p->nUsed += (int)strlen(p->zBuf+p->nUsed);
}

/* Append a single character
*/
static void jsonAppendChar(JsonString *p, char c){
  if( p->nUsed>=p->nAlloc && jsonGrow(p,1)!=0 ) return;
  p->zBuf[p->nUsed++] = c;
}

/* Append a comma separator to the output buffer, if the previous
** character is not '[' or '{'.
*/
static void jsonAppendSeparator(JsonString *p){
  char c;
  if( p->nUsed==0 ) return;
  c = p->zBuf[p->nUsed-1];
  if( c!='[' && c!='{' ) jsonAppendChar(p, ',');
}

/* Append the N-byte string in zIn to the end of the JsonString string
** under construction.  Enclose the string in "..." and escape
** any double-quotes or backslash characters contained within the
** string.
*/
static void jsonAppendString(JsonString *p, const char *zIn, u32 N){
  u32 i;
  if( zIn==0 || ((N+p->nUsed+2 >= p->nAlloc) && jsonGrow(p,N+2)!=0) ) return;
  p->zBuf[p->nUsed++] = '"';
  for(i=0; i<N; i++){
    unsigned char c = ((unsigned const char*)zIn)[i];
    if( c=='"' || c=='\\' ){
      json_simple_escape:
      if( (p->nUsed+N+3-i > p->nAlloc) && jsonGrow(p,N+3-i)!=0 ) return;
      p->zBuf[p->nUsed++] = '\\';
    }else if( c<=0x1f ){
      static const char aSpecial[] = {
         0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0,   0,   0, 0, 0
      };
      assert( sizeof(aSpecial)==32 );
      assert( aSpecial['\b']=='b' );
      assert( aSpecial['\f']=='f' );
      assert( aSpecial['\n']=='n' );
      assert( aSpecial['\r']=='r' );
      assert( aSpecial['\t']=='t' );
      if( aSpecial[c] ){
        c = aSpecial[c];
        goto json_simple_escape;
      }
      if( (p->nUsed+N+7+i > p->nAlloc) && jsonGrow(p,N+7-i)!=0 ) return;
      p->zBuf[p->nUsed++] = '\\';
      p->zBuf[p->nUsed++] = 'u';
      p->zBuf[p->nUsed++] = '0';
      p->zBuf[p->nUsed++] = '0';
      p->zBuf[p->nUsed++] = '0' + (c>>4);
      c = "0123456789abcdef"[c&0xf];
    }
    p->zBuf[p->nUsed++] = c;
  }
  p->zBuf[p->nUsed++] = '"';
  assert( p->nUsed<p->nAlloc );
}

/*
** Append a function parameter value to the JSON string under 
** construction.
*/
static void jsonAppendValue(
  JsonString *p,                 /* Append to this JSON string */
  sqlite3_value *pValue          /* Value to append */
){
  switch( sqlite3_value_type(pValue) ){
    case SQLITE_NULL: {
      jsonAppendRaw(p, "null", 4);
      break;
    }
    case SQLITE_INTEGER:
    case SQLITE_FLOAT: {
      const char *z = (const char*)sqlite3_value_text(pValue);
      u32 n = (u32)sqlite3_value_bytes(pValue);
      jsonAppendRaw(p, z, n);
      break;
    }
    case SQLITE_TEXT: {
      const char *z = (const char*)sqlite3_value_text(pValue);
      u32 n = (u32)sqlite3_value_bytes(pValue);
      if( sqlite3_value_subtype(pValue)==JSON_SUBTYPE ){
        jsonAppendRaw(p, z, n);
      }else{
        jsonAppendString(p, z, n);
      }
      break;
    }
    default: {
      if( p->bErr==0 ){
        sqlite3_result_error(p->pCtx, "JSON cannot hold BLOB values", -1);
        p->bErr = 2;
        jsonReset(p);
      }
      break;
    }
  }
}


/* Make the JSON in p the result of the SQL function.
*/
static void jsonResult(JsonString *p){
  if( p->bErr==0 ){
    sqlite3_result_text64(p->pCtx, p->zBuf, p->nUsed, 
                          p->bStatic ? SQLITE_TRANSIENT : sqlite3_free,
                          SQLITE_UTF8);
    jsonZero(p);
  }
  assert( p->bStatic );
}

/**************************************************************************
** Utility routines for dealing with JsonNode and JsonParse objects
**************************************************************************/

/*
** Return the number of consecutive JsonNode slots need to represent
** the parsed JSON at pNode.  The minimum answer is 1.  For ARRAY and
** OBJECT types, the number might be larger.
**
** Appended elements are not counted.  The value returned is the number
** by which the JsonNode counter should increment in order to go to the
** next peer value.
*/
static u32 jsonNodeSize(JsonNode *pNode){
  return pNode->eType>=JSON_ARRAY ? pNode->n+1 : 1;
}

/*
** Reclaim all memory allocated by a JsonParse object.  But do not
** delete the JsonParse object itself.
*/
static void jsonParseReset(JsonParse *pParse){
  sqlite3_free(pParse->aNode);
  pParse->aNode = 0;
  pParse->nNode = 0;
  pParse->nAlloc = 0;
  sqlite3_free(pParse->aUp);
  pParse->aUp = 0;
}

/*
** Free a JsonParse object that was obtained from sqlite3_malloc().
*/
static void jsonParseFree(JsonParse *pParse){
  jsonParseReset(pParse);
  sqlite3_free(pParse);
}

/*
** Convert the JsonNode pNode into a pure JSON string and
** append to pOut.  Subsubstructure is also included.  Return
** the number of JsonNode objects that are encoded.
*/
static void jsonRenderNode(
  JsonNode *pNode,               /* The node to render */
  JsonString *pOut,              /* Write JSON here */
  sqlite3_value **aReplace       /* Replacement values */
){
  assert( pNode!=0 );
  if( pNode->jnFlags & (JNODE_REPLACE|JNODE_PATCH) ){
    if( (pNode->jnFlags & JNODE_REPLACE)!=0 && ALWAYS(aReplace!=0) ){
      assert( pNode->eU==4 );
      jsonAppendValue(pOut, aReplace[pNode->u.iReplace]);
      return;
    }
    assert( pNode->eU==5 );
    pNode = pNode->u.pPatch;
  }
  switch( pNode->eType ){
    default: {
      assert( pNode->eType==JSON_NULL );
      jsonAppendRaw(pOut, "null", 4);
      break;
    }
    case JSON_TRUE: {
      jsonAppendRaw(pOut, "true", 4);
      break;
    }
    case JSON_FALSE: {
      jsonAppendRaw(pOut, "false", 5);
      break;
    }
    case JSON_STRING: {
      if( pNode->jnFlags & JNODE_RAW ){
        assert( pNode->eU==1 );
        jsonAppendString(pOut, pNode->u.zJContent, pNode->n);
        break;
      }
      /* no break */ deliberate_fall_through
    }
    case JSON_REAL:
    case JSON_INT: {
      assert( pNode->eU==1 );
      jsonAppendRaw(pOut, pNode->u.zJContent, pNode->n);
      break;
    }
    case JSON_ARRAY: {
      u32 j = 1;
      jsonAppendChar(pOut, '[');
      for(;;){
        while( j<=pNode->n ){
          if( (pNode[j].jnFlags & JNODE_REMOVE)==0 ){
            jsonAppendSeparator(pOut);
            jsonRenderNode(&pNode[j], pOut, aReplace);
          }
          j += jsonNodeSize(&pNode[j]);
        }
        if( (pNode->jnFlags & JNODE_APPEND)==0 ) break;
        assert( pNode->eU==2 );
        pNode = &pNode[pNode->u.iAppend];
        j = 1;
      }
      jsonAppendChar(pOut, ']');
      break;
    }
    case JSON_OBJECT: {
      u32 j = 1;
      jsonAppendChar(pOut, '{');
      for(;;){
        while( j<=pNode->n ){
          if( (pNode[j+1].jnFlags & JNODE_REMOVE)==0 ){
            jsonAppendSeparator(pOut);
            jsonRenderNode(&pNode[j], pOut, aReplace);
            jsonAppendChar(pOut, ':');
            jsonRenderNode(&pNode[j+1], pOut, aReplace);
          }
          j += 1 + jsonNodeSize(&pNode[j+1]);
        }
        if( (pNode->jnFlags & JNODE_APPEND)==0 ) break;
        assert( pNode->eU==2 );
        pNode = &pNode[pNode->u.iAppend];
        j = 1;
      }
      jsonAppendChar(pOut, '}');
      break;
    }
  }
}

/*
** Return a JsonNode and all its descendents as a JSON string.
*/
static void jsonReturnJson(
  JsonNode *pNode,            /* Node to return */
  sqlite3_context *pCtx,      /* Return value for this function */
  sqlite3_value **aReplace    /* Array of replacement values */
){
  JsonString s;
  jsonInit(&s, pCtx);
  jsonRenderNode(pNode, &s, aReplace);
  jsonResult(&s);
  sqlite3_result_subtype(pCtx, JSON_SUBTYPE);
}

/*
** Translate a single byte of Hex into an integer.
** This routine only works if h really is a valid hexadecimal
** character:  0..9a..fA..F
*/
static u8 jsonHexToInt(int h){
  assert( (h>='0' && h<='9') ||  (h>='a' && h<='f') ||  (h>='A' && h<='F') );
#ifdef SQLITE_EBCDIC
  h += 9*(1&~(h>>4));
#else
  h += 9*(1&(h>>6));
#endif
  return (u8)(h & 0xf);
}

/*
** Convert a 4-byte hex string into an integer
*/
static u32 jsonHexToInt4(const char *z){
  u32 v;
  assert( sqlite3Isxdigit(z[0]) );
  assert( sqlite3Isxdigit(z[1]) );
  assert( sqlite3Isxdigit(z[2]) );
  assert( sqlite3Isxdigit(z[3]) );
  v = (jsonHexToInt(z[0])<<12)
    + (jsonHexToInt(z[1])<<8)
    + (jsonHexToInt(z[2])<<4)
    + jsonHexToInt(z[3]);
  return v;
}

/*
** Make the JsonNode the return value of the function.
*/
static void jsonReturn(
  JsonNode *pNode,            /* Node to return */
  sqlite3_context *pCtx,      /* Return value for this function */
  sqlite3_value **aReplace    /* Array of replacement values */
){
  switch( pNode->eType ){
    default: {
      assert( pNode->eType==JSON_NULL );
      sqlite3_result_null(pCtx);
      break;
    }
    case JSON_TRUE: {
      sqlite3_result_int(pCtx, 1);
      break;
    }
    case JSON_FALSE: {
      sqlite3_result_int(pCtx, 0);
      break;
    }
    case JSON_INT: {
      sqlite3_int64 i = 0;
      const char *z;
      assert( pNode->eU==1 );
      z = pNode->u.zJContent;
      if( z[0]=='-' ){ z++; }
      while( z[0]>='0' && z[0]<='9' ){
        unsigned v = *(z++) - '0';
        if( i>=LARGEST_INT64/10 ){
          if( i>LARGEST_INT64/10 ) goto int_as_real;
          if( z[0]>='0' && z[0]<='9' ) goto int_as_real;
          if( v==9 ) goto int_as_real;
          if( v==8 ){
            if( pNode->u.zJContent[0]=='-' ){
              sqlite3_result_int64(pCtx, SMALLEST_INT64);
              goto int_done;
            }else{
              goto int_as_real;
            }
          }
        }
        i = i*10 + v;
      }
      if( pNode->u.zJContent[0]=='-' ){ i = -i; }
      sqlite3_result_int64(pCtx, i);
      int_done:
      break;
      int_as_real: ; /* no break */ deliberate_fall_through
    }
    case JSON_REAL: {
      double r;
#ifdef SQLITE_AMALGAMATION
      const char *z;
      assert( pNode->eU==1 );
      z = pNode->u.zJContent;
      sqlite3AtoF(z, &r, sqlite3Strlen30(z), SQLITE_UTF8);
#else
      assert( pNode->eU==1 );
      r = strtod(pNode->u.zJContent, 0);
#endif
      sqlite3_result_double(pCtx, r);
      break;
    }
    case JSON_STRING: {
#if 0 /* Never happens because JNODE_RAW is only set by json_set(),
      ** json_insert() and json_replace() and those routines do not
      ** call jsonReturn() */
      if( pNode->jnFlags & JNODE_RAW ){
        assert( pNode->eU==1 );
        sqlite3_result_text(pCtx, pNode->u.zJContent, pNode->n,
                            SQLITE_TRANSIENT);
      }else 
#endif
      assert( (pNode->jnFlags & JNODE_RAW)==0 );
      if( (pNode->jnFlags & JNODE_ESCAPE)==0 ){
        /* JSON formatted without any backslash-escapes */
        assert( pNode->eU==1 );
        sqlite3_result_text(pCtx, pNode->u.zJContent+1, pNode->n-2,
                            SQLITE_TRANSIENT);
      }else{
        /* Translate JSON formatted string into raw text */
        u32 i;
        u32 n = pNode->n;
        const char *z;
        char *zOut;
        u32 j;
        assert( pNode->eU==1 );
        z = pNode->u.zJContent;
        zOut = sqlite3_malloc( n+1 );
        if( zOut==0 ){
          sqlite3_result_error_nomem(pCtx);
          break;
        }
        for(i=1, j=0; i<n-1; i++){
          char c = z[i];
          if( c!='\\' ){
            zOut[j++] = c;
          }else{
            c = z[++i];
            if( c=='u' ){
              u32 v = jsonHexToInt4(z+i+1);
              i += 4;
              if( v==0 ) break;
              if( v<=0x7f ){
                zOut[j++] = (char)v;
              }else if( v<=0x7ff ){
                zOut[j++] = (char)(0xc0 | (v>>6));
                zOut[j++] = 0x80 | (v&0x3f);
              }else{
                u32 vlo;
                if( (v&0xfc00)==0xd800
                  && i<n-6
                  && z[i+1]=='\\'
                  && z[i+2]=='u'
                  && ((vlo = jsonHexToInt4(z+i+3))&0xfc00)==0xdc00
                ){
                  /* We have a surrogate pair */
                  v = ((v&0x3ff)<<10) + (vlo&0x3ff) + 0x10000;
                  i += 6;
                  zOut[j++] = 0xf0 | (v>>18);
                  zOut[j++] = 0x80 | ((v>>12)&0x3f);
                  zOut[j++] = 0x80 | ((v>>6)&0x3f);
                  zOut[j++] = 0x80 | (v&0x3f);
                }else{
                  zOut[j++] = 0xe0 | (v>>12);
                  zOut[j++] = 0x80 | ((v>>6)&0x3f);
                  zOut[j++] = 0x80 | (v&0x3f);
                }
              }
            }else{
              if( c=='b' ){
                c = '\b';
              }else if( c=='f' ){
                c = '\f';
              }else if( c=='n' ){
                c = '\n';
              }else if( c=='r' ){
                c = '\r';
              }else if( c=='t' ){
                c = '\t';
              }
              zOut[j++] = c;
            }
          }
        }
        zOut[j] = 0;
        sqlite3_result_text(pCtx, zOut, j, sqlite3_free);
      }
      break;
    }
    case JSON_ARRAY:
    case JSON_OBJECT: {
      jsonReturnJson(pNode, pCtx, aReplace);
      break;
    }
  }
}

/* Forward reference */
static int jsonParseAddNode(JsonParse*,u32,u32,const char*);

/*
** A macro to hint to the compiler that a function should not be
** inlined.
*/
#if defined(__GNUC__)
#  define JSON_NOINLINE  __attribute__((noinline))
#elif defined(_MSC_VER) && _MSC_VER>=1310
#  define JSON_NOINLINE  __declspec(noinline)
#else
#  define JSON_NOINLINE
#endif


static JSON_NOINLINE int jsonParseAddNodeExpand(
  JsonParse *pParse,        /* Append the node to this object */
  u32 eType,                /* Node type */
  u32 n,                    /* Content size or sub-node count */
  const char *zContent      /* Content */
){
  u32 nNew;
  JsonNode *pNew;
  assert( pParse->nNode>=pParse->nAlloc );
  if( pParse->oom ) return -1;
  nNew = pParse->nAlloc*2 + 10;
  pNew = sqlite3_realloc64(pParse->aNode, sizeof(JsonNode)*nNew);
  if( pNew==0 ){
    pParse->oom = 1;
    return -1;
  }
  pParse->nAlloc = nNew;
  pParse->aNode = pNew;
  assert( pParse->nNode<pParse->nAlloc );
  return jsonParseAddNode(pParse, eType, n, zContent);
}

/*
** Create a new JsonNode instance based on the arguments and append that
** instance to the JsonParse.  Return the index in pParse->aNode[] of the
** new node, or -1 if a memory allocation fails.
*/
static int jsonParseAddNode(
  JsonParse *pParse,        /* Append the node to this object */
  u32 eType,                /* Node type */
  u32 n,                    /* Content size or sub-node count */
  const char *zContent      /* Content */
){
  JsonNode *p;
  if( pParse->aNode==0 || pParse->nNode>=pParse->nAlloc ){
    return jsonParseAddNodeExpand(pParse, eType, n, zContent);
  }
  p = &pParse->aNode[pParse->nNode];
  p->eType = (u8)eType;
  p->jnFlags = 0;
  VVA( p->eU = zContent ? 1 : 0 );
  p->n = n;
  p->u.zJContent = zContent;
  return pParse->nNode++;
}

/*
** Return true if z[] begins with 4 (or more) hexadecimal digits
*/
static int jsonIs4Hex(const char *z){
  int i;
  for(i=0; i<4; i++) if( !sqlite3Isxdigit(z[i]) ) return 0;
  return 1;
}

/*
** Parse a single JSON value which begins at pParse->zJson[i].  Return the
** index of the first character past the end of the value parsed.
**
** Return negative for a syntax error.  Special cases:  return -2 if the
** first non-whitespace character is '}' and return -3 if the first
** non-whitespace character is ']'.
*/
static int jsonParseValue(JsonParse *pParse, u32 i){
  char c;
  u32 j;
  int iThis;
  int x;
  JsonNode *pNode;
  const char *z = pParse->zJson;
  while( fast_isspace(z[i]) ){ i++; }
  if( (c = z[i])=='{' ){
    /* Parse object */
    iThis = jsonParseAddNode(pParse, JSON_OBJECT, 0, 0);
    if( iThis<0 ) return -1;
    for(j=i+1;;j++){
      while( fast_isspace(z[j]) ){ j++; }
      if( ++pParse->iDepth > JSON_MAX_DEPTH ) return -1;
      x = jsonParseValue(pParse, j);
      if( x<0 ){
        pParse->iDepth--;
        if( x==(-2) && pParse->nNode==(u32)iThis+1 ) return j+1;
        return -1;
      }
      if( pParse->oom ) return -1;
      pNode = &pParse->aNode[pParse->nNode-1];
      if( pNode->eType!=JSON_STRING ) return -1;
      pNode->jnFlags |= JNODE_LABEL;
      j = x;
      while( fast_isspace(z[j]) ){ j++; }
      if( z[j]!=':' ) return -1;
      j++;
      x = jsonParseValue(pParse, j);
      pParse->iDepth--;
      if( x<0 ) return -1;
      j = x;
      while( fast_isspace(z[j]) ){ j++; }
      c = z[j];
      if( c==',' ) continue;
      if( c!='}' ) return -1;
      break;
    }
    pParse->aNode[iThis].n = pParse->nNode - (u32)iThis - 1;
    return j+1;
  }else if( c=='[' ){
    /* Parse array */
    iThis = jsonParseAddNode(pParse, JSON_ARRAY, 0, 0);
    if( iThis<0 ) return -1;
    memset(&pParse->aNode[iThis].u, 0, sizeof(pParse->aNode[iThis].u));
    for(j=i+1;;j++){
      while( fast_isspace(z[j]) ){ j++; }
      if( ++pParse->iDepth > JSON_MAX_DEPTH ) return -1;
      x = jsonParseValue(pParse, j);
      pParse->iDepth--;
      if( x<0 ){
        if( x==(-3) && pParse->nNode==(u32)iThis+1 ) return j+1;
        return -1;
      }
      j = x;
      while( fast_isspace(z[j]) ){ j++; }
      c = z[j];
      if( c==',' ) continue;
      if( c!=']' ) return -1;
      break;
    }
    pParse->aNode[iThis].n = pParse->nNode - (u32)iThis - 1;
    return j+1;
  }else if( c=='"' ){
    /* Parse string */
    u8 jnFlags = 0;
    j = i+1;
    for(;;){
      c = z[j];
      if( (c & ~0x1f)==0 ){
        /* Control characters are not allowed in strings */
        return -1;
      }
      if( c=='\\' ){
        c = z[++j];
        if( c=='"' || c=='\\' || c=='/' || c=='b' || c=='f'
           || c=='n' || c=='r' || c=='t'
           || (c=='u' && jsonIs4Hex(z+j+1)) ){
          jnFlags = JNODE_ESCAPE;
        }else{
          return -1;
        }
      }else if( c=='"' ){
        break;
      }
      j++;
    }
    jsonParseAddNode(pParse, JSON_STRING, j+1-i, &z[i]);
    if( !pParse->oom ) pParse->aNode[pParse->nNode-1].jnFlags = jnFlags;
    return j+1;
  }else if( c=='n'
         && strncmp(z+i,"null",4)==0
         && !sqlite3Isalnum(z[i+4]) ){
    jsonParseAddNode(pParse, JSON_NULL, 0, 0);
    return i+4;
  }else if( c=='t'
         && strncmp(z+i,"true",4)==0
         && !sqlite3Isalnum(z[i+4]) ){
    jsonParseAddNode(pParse, JSON_TRUE, 0, 0);
    return i+4;
  }else if( c=='f'
         && strncmp(z+i,"false",5)==0
         && !sqlite3Isalnum(z[i+5]) ){
    jsonParseAddNode(pParse, JSON_FALSE, 0, 0);
    return i+5;
  }else if( c=='-' || (c>='0' && c<='9') ){
    /* Parse number */
    u8 seenDP = 0;
    u8 seenE = 0;
    assert( '-' < '0' );
    if( c<='0' ){
      j = c=='-' ? i+1 : i;
      if( z[j]=='0' && z[j+1]>='0' && z[j+1]<='9' ) return -1;
    }
    j = i+1;
    for(;; j++){
      c = z[j];
      if( c>='0' && c<='9' ) continue;
      if( c=='.' ){
        if( z[j-1]=='-' ) return -1;
        if( seenDP ) return -1;
        seenDP = 1;
        continue;
      }
      if( c=='e' || c=='E' ){
        if( z[j-1]<'0' ) return -1;
        if( seenE ) return -1;
        seenDP = seenE = 1;
        c = z[j+1];
        if( c=='+' || c=='-' ){
          j++;
          c = z[j+1];
        }
        if( c<'0' || c>'9' ) return -1;
        continue;
      }
      break;
    }
    if( z[j-1]<'0' ) return -1;
    jsonParseAddNode(pParse, seenDP ? JSON_REAL : JSON_INT,
                        j - i, &z[i]);
    return j;
  }else if( c=='}' ){
    return -2;  /* End of {...} */
  }else if( c==']' ){
    return -3;  /* End of [...] */
  }else if( c==0 ){
    return 0;   /* End of file */
  }else{
    return -1;  /* Syntax error */
  }
}

/*
** Parse a complete JSON string.  Return 0 on success or non-zero if there
** are any errors.  If an error occurs, free all memory associated with
** pParse.
**
** pParse is uninitialized when this routine is called.
*/
static int jsonParse(
  JsonParse *pParse,           /* Initialize and fill this JsonParse object */
  sqlite3_context *pCtx,       /* Report errors here */
  const char *zJson            /* Input JSON text to be parsed */
){
  int i;
  memset(pParse, 0, sizeof(*pParse));
  if( zJson==0 ) return 1;
  pParse->zJson = zJson;
  i = jsonParseValue(pParse, 0);
  if( pParse->oom ) i = -1;
  if( i>0 ){
    assert( pParse->iDepth==0 );
    while( fast_isspace(zJson[i]) ) i++;
    if( zJson[i] ) i = -1;
  }
  if( i<=0 ){
    if( pCtx!=0 ){
      if( pParse->oom ){
        sqlite3_result_error_nomem(pCtx);
      }else{
        sqlite3_result_error(pCtx, "malformed JSON", -1);
      }
    }
    jsonParseReset(pParse);
    return 1;
  }
  return 0;
}

/* Mark node i of pParse as being a child of iParent.  Call recursively
** to fill in all the descendants of node i.
*/
static void jsonParseFillInParentage(JsonParse *pParse, u32 i, u32 iParent){
  JsonNode *pNode = &pParse->aNode[i];
  u32 j;
  pParse->aUp[i] = iParent;
  switch( pNode->eType ){
    case JSON_ARRAY: {
      for(j=1; j<=pNode->n; j += jsonNodeSize(pNode+j)){
        jsonParseFillInParentage(pParse, i+j, i);
      }
      break;
    }
    case JSON_OBJECT: {
      for(j=1; j<=pNode->n; j += jsonNodeSize(pNode+j+1)+1){
        pParse->aUp[i+j] = i;
        jsonParseFillInParentage(pParse, i+j+1, i);
      }
      break;
    }
    default: {
      break;
    }
  }
}

/*
** Compute the parentage of all nodes in a completed parse.
*/
static int jsonParseFindParents(JsonParse *pParse){
  u32 *aUp;
  assert( pParse->aUp==0 );
  aUp = pParse->aUp = sqlite3_malloc64( sizeof(u32)*pParse->nNode );
  if( aUp==0 ){
    pParse->oom = 1;
    return SQLITE_NOMEM;
  }
  jsonParseFillInParentage(pParse, 0, 0);
  return SQLITE_OK;
}

/*
** Magic number used for the JSON parse cache in sqlite3_get_auxdata()
*/
#define JSON_CACHE_ID  (-429938)  /* First cache entry */
#define JSON_CACHE_SZ  4          /* Max number of cache entries */

/*
** Obtain a complete parse of the JSON found in the first argument
** of the argv array.  Use the sqlite3_get_auxdata() cache for this
** parse if it is available.  If the cache is not available or if it
** is no longer valid, parse the JSON again and return the new parse,
** and also register the new parse so that it will be available for
** future sqlite3_get_auxdata() calls.
*/
static JsonParse *jsonParseCached(
  sqlite3_context *pCtx,
  sqlite3_value **argv,
  sqlite3_context *pErrCtx
){
  const char *zJson = (const char*)sqlite3_value_text(argv[0]);
  int nJson = sqlite3_value_bytes(argv[0]);
  JsonParse *p;
  JsonParse *pMatch = 0;
  int iKey;
  int iMinKey = 0;
  u32 iMinHold = 0xffffffff;
  u32 iMaxHold = 0;
  if( zJson==0 ) return 0;
  for(iKey=0; iKey<JSON_CACHE_SZ; iKey++){
    p = (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID+iKey);
    if( p==0 ){
      iMinKey = iKey;
      break;
    }
    if( pMatch==0
     && p->nJson==nJson
     && memcmp(p->zJson,zJson,nJson)==0
    ){
      p->nErr = 0;
      pMatch = p;
    }else if( p->iHold<iMinHold ){
      iMinHold = p->iHold;
      iMinKey = iKey;
    }
    if( p->iHold>iMaxHold ){
      iMaxHold = p->iHold;
    }
  }
  if( pMatch ){
    pMatch->nErr = 0;
    pMatch->iHold = iMaxHold+1;
    return pMatch;
  }
  p = sqlite3_malloc64( sizeof(*p) + nJson + 1 );
  if( p==0 ){
    sqlite3_result_error_nomem(pCtx);
    return 0;
  }
  memset(p, 0, sizeof(*p));
  p->zJson = (char*)&p[1];
  memcpy((char*)p->zJson, zJson, nJson+1);
  if( jsonParse(p, pErrCtx, p->zJson) ){
    sqlite3_free(p);
    return 0;
  }
  p->nJson = nJson;
  p->iHold = iMaxHold+1;
  sqlite3_set_auxdata(pCtx, JSON_CACHE_ID+iMinKey, p,
                      (void(*)(void*))jsonParseFree);
  return (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID+iMinKey);
}

/*
** Compare the OBJECT label at pNode against zKey,nKey.  Return true on
** a match.
*/
static int jsonLabelCompare(JsonNode *pNode, const char *zKey, u32 nKey){
  assert( pNode->eU==1 );
  if( pNode->jnFlags & JNODE_RAW ){
    if( pNode->n!=nKey ) return 0;
    return strncmp(pNode->u.zJContent, zKey, nKey)==0;
  }else{
    if( pNode->n!=nKey+2 ) return 0;
    return strncmp(pNode->u.zJContent+1, zKey, nKey)==0;
  }
}

/* forward declaration */
static JsonNode *jsonLookupAppend(JsonParse*,const char*,int*,const char**);

/*
** Search along zPath to find the node specified.  Return a pointer
** to that node, or NULL if zPath is malformed or if there is no such
** node.
**
** If pApnd!=0, then try to append new nodes to complete zPath if it is
** possible to do so and if no existing node corresponds to zPath.  If
** new nodes are appended *pApnd is set to 1.
*/
static JsonNode *jsonLookupStep(
  JsonParse *pParse,      /* The JSON to search */
  u32 iRoot,              /* Begin the search at this node */
  const char *zPath,      /* The path to search */
  int *pApnd,             /* Append nodes to complete path if not NULL */
  const char **pzErr      /* Make *pzErr point to any syntax error in zPath */
){
  u32 i, j, nKey;
  const char *zKey;
  JsonNode *pRoot = &pParse->aNode[iRoot];
  if( zPath[0]==0 ) return pRoot;
  if( pRoot->jnFlags & JNODE_REPLACE ) return 0;
  if( zPath[0]=='.' ){
    if( pRoot->eType!=JSON_OBJECT ) return 0;
    zPath++;
    if( zPath[0]=='"' ){
      zKey = zPath + 1;
      for(i=1; zPath[i] && zPath[i]!='"'; i++){}
      nKey = i-1;
      if( zPath[i] ){
        i++;
      }else{
        *pzErr = zPath;
        return 0;
      }
      testcase( nKey==0 );
    }else{
      zKey = zPath;
      for(i=0; zPath[i] && zPath[i]!='.' && zPath[i]!='['; i++){}
      nKey = i;
      if( nKey==0 ){
        *pzErr = zPath;
        return 0;
      }
    }
    j = 1;
    for(;;){
      while( j<=pRoot->n ){
        if( jsonLabelCompare(pRoot+j, zKey, nKey) ){
          return jsonLookupStep(pParse, iRoot+j+1, &zPath[i], pApnd, pzErr);
        }
        j++;
        j += jsonNodeSize(&pRoot[j]);
      }
      if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break;
      assert( pRoot->eU==2 );
      iRoot += pRoot->u.iAppend;
      pRoot = &pParse->aNode[iRoot];
      j = 1;
    }
    if( pApnd ){
      u32 iStart, iLabel;
      JsonNode *pNode;
      iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0);
      iLabel = jsonParseAddNode(pParse, JSON_STRING, nKey, zKey);
      zPath += i;
      pNode = jsonLookupAppend(pParse, zPath, pApnd, pzErr);
      if( pParse->oom ) return 0;
      if( pNode ){
        pRoot = &pParse->aNode[iRoot];
        assert( pRoot->eU==0 );
        pRoot->u.iAppend = iStart - iRoot;
        pRoot->jnFlags |= JNODE_APPEND;
        VVA( pRoot->eU = 2 );
        pParse->aNode[iLabel].jnFlags |= JNODE_RAW;
      }
      return pNode;
    }
  }else if( zPath[0]=='[' ){
    i = 0;
    j = 1;
    while( sqlite3Isdigit(zPath[j]) ){
      i = i*10 + zPath[j] - '0';
      j++;
    }
    if( j<2 || zPath[j]!=']' ){
      if( zPath[1]=='#' ){
        JsonNode *pBase = pRoot;
        int iBase = iRoot;
        if( pRoot->eType!=JSON_ARRAY ) return 0;
        for(;;){
          while( j<=pBase->n ){
            if( (pBase[j].jnFlags & JNODE_REMOVE)==0 ) i++;
            j += jsonNodeSize(&pBase[j]);
          }
          if( (pBase->jnFlags & JNODE_APPEND)==0 ) break;
          assert( pBase->eU==2 );
          iBase += pBase->u.iAppend;
          pBase = &pParse->aNode[iBase];
          j = 1;
        }
        j = 2;
        if( zPath[2]=='-' && sqlite3Isdigit(zPath[3]) ){
          unsigned int x = 0;
          j = 3;
          do{
            x = x*10 + zPath[j] - '0';
            j++;
          }while( sqlite3Isdigit(zPath[j]) );
          if( x>i ) return 0;
          i -= x;
        }
        if( zPath[j]!=']' ){
          *pzErr = zPath;
          return 0;
        }
      }else{
        *pzErr = zPath;
        return 0;
      }
    }
    if( pRoot->eType!=JSON_ARRAY ) return 0;
    zPath += j + 1;
    j = 1;
    for(;;){
      while( j<=pRoot->n && (i>0 || (pRoot[j].jnFlags & JNODE_REMOVE)!=0) ){
        if( (pRoot[j].jnFlags & JNODE_REMOVE)==0 ) i--;
        j += jsonNodeSize(&pRoot[j]);
      }
      if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break;
      assert( pRoot->eU==2 );
      iRoot += pRoot->u.iAppend;
      pRoot = &pParse->aNode[iRoot];
      j = 1;
    }
    if( j<=pRoot->n ){
      return jsonLookupStep(pParse, iRoot+j, zPath, pApnd, pzErr);
    }
    if( i==0 && pApnd ){
      u32 iStart;
      JsonNode *pNode;
      iStart = jsonParseAddNode(pParse, JSON_ARRAY, 1, 0);
      pNode = jsonLookupAppend(pParse, zPath, pApnd, pzErr);
      if( pParse->oom ) return 0;
      if( pNode ){
        pRoot = &pParse->aNode[iRoot];
        assert( pRoot->eU==0 );
        pRoot->u.iAppend = iStart - iRoot;
        pRoot->jnFlags |= JNODE_APPEND;
        VVA( pRoot->eU = 2 );
      }
      return pNode;
    }
  }else{
    *pzErr = zPath;
  }
  return 0;
}

/*
** Append content to pParse that will complete zPath.  Return a pointer
** to the inserted node, or return NULL if the append fails.
*/
static JsonNode *jsonLookupAppend(
  JsonParse *pParse,     /* Append content to the JSON parse */
  const char *zPath,     /* Description of content to append */
  int *pApnd,            /* Set this flag to 1 */
  const char **pzErr     /* Make this point to any syntax error */
){
  *pApnd = 1;
  if( zPath[0]==0 ){
    jsonParseAddNode(pParse, JSON_NULL, 0, 0);
    return pParse->oom ? 0 : &pParse->aNode[pParse->nNode-1];
  }
  if( zPath[0]=='.' ){
    jsonParseAddNode(pParse, JSON_OBJECT, 0, 0);
  }else if( strncmp(zPath,"[0]",3)==0 ){
    jsonParseAddNode(pParse, JSON_ARRAY, 0, 0);
  }else{
    return 0;
  }
  if( pParse->oom ) return 0;
  return jsonLookupStep(pParse, pParse->nNode-1, zPath, pApnd, pzErr);
}

/*
** Return the text of a syntax error message on a JSON path.  Space is
** obtained from sqlite3_malloc().
*/
static char *jsonPathSyntaxError(const char *zErr){
  return sqlite3_mprintf("JSON path error near '%q'", zErr);
}

/*
** Do a node lookup using zPath.  Return a pointer to the node on success.
** Return NULL if not found or if there is an error.
**
** On an error, write an error message into pCtx and increment the
** pParse->nErr counter.
**
** If pApnd!=NULL then try to append missing nodes and set *pApnd = 1 if
** nodes are appended.
*/
static JsonNode *jsonLookup(
  JsonParse *pParse,      /* The JSON to search */
  const char *zPath,      /* The path to search */
  int *pApnd,             /* Append nodes to complete path if not NULL */
  sqlite3_context *pCtx   /* Report errors here, if not NULL */
){
  const char *zErr = 0;
  JsonNode *pNode = 0;
  char *zMsg;

  if( zPath==0 ) return 0;
  if( zPath[0]!='$' ){
    zErr = zPath;
    goto lookup_err;
  }
  zPath++;
  pNode = jsonLookupStep(pParse, 0, zPath, pApnd, &zErr);
  if( zErr==0 ) return pNode;

lookup_err:
  pParse->nErr++;
  assert( zErr!=0 && pCtx!=0 );
  zMsg = jsonPathSyntaxError(zErr);
  if( zMsg ){
    sqlite3_result_error(pCtx, zMsg, -1);
    sqlite3_free(zMsg);
  }else{
    sqlite3_result_error_nomem(pCtx);
  }
  return 0;
}


/*
** Report the wrong number of arguments for json_insert(), json_replace()
** or json_set().
*/
static void jsonWrongNumArgs(
  sqlite3_context *pCtx,
  const char *zFuncName
){
  char *zMsg = sqlite3_mprintf("json_%s() needs an odd number of arguments",
                               zFuncName);
  sqlite3_result_error(pCtx, zMsg, -1);
  sqlite3_free(zMsg);     
}

/*
** Mark all NULL entries in the Object passed in as JNODE_REMOVE.
*/
static void jsonRemoveAllNulls(JsonNode *pNode){
  int i, n;
  assert( pNode->eType==JSON_OBJECT );
  n = pNode->n;
  for(i=2; i<=n; i += jsonNodeSize(&pNode[i])+1){
    switch( pNode[i].eType ){
      case JSON_NULL:
        pNode[i].jnFlags |= JNODE_REMOVE;
        break;
      case JSON_OBJECT:
        jsonRemoveAllNulls(&pNode[i]);
        break;
    }
  }
}


/****************************************************************************
** SQL functions used for testing and debugging
****************************************************************************/

#ifdef SQLITE_DEBUG
/*
** The json_parse(JSON) function returns a string which describes
** a parse of the JSON provided.  Or it returns NULL if JSON is not
** well-formed.
*/
static void jsonParseFunc(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  JsonString s;       /* Output string - not real JSON */
  JsonParse x;        /* The parse */
  u32 i;

  assert( argc==1 );
  if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
  jsonParseFindParents(&x);
  jsonInit(&s, ctx);
  for(i=0; i<x.nNode; i++){
    const char *zType;
    if( x.aNode[i].jnFlags & JNODE_LABEL ){
      assert( x.aNode[i].eType==JSON_STRING );
      zType = "label";
    }else{
      zType = jsonType[x.aNode[i].eType];
    }
    jsonPrintf(100, &s,"node %3u: %7s n=%-4d up=%-4d",
               i, zType, x.aNode[i].n, x.aUp[i]);
    assert( x.aNode[i].eU==0 || x.aNode[i].eU==1 );
    if( x.aNode[i].u.zJContent!=0 ){
      assert( x.aNode[i].eU==1 );
      jsonAppendRaw(&s, " ", 1);
      jsonAppendRaw(&s, x.aNode[i].u.zJContent, x.aNode[i].n);
    }else{
      assert( x.aNode[i].eU==0 );
    }
    jsonAppendRaw(&s, "\n", 1);
  }
  jsonParseReset(&x);
  jsonResult(&s);
}

/*
** The json_test1(JSON) function return true (1) if the input is JSON
** text generated by another json function.  It returns (0) if the input
** is not known to be JSON.
*/
static void jsonTest1Func(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  UNUSED_PARAMETER(argc);
  sqlite3_result_int(ctx, sqlite3_value_subtype(argv[0])==JSON_SUBTYPE);
}
#endif /* SQLITE_DEBUG */

/****************************************************************************
** Scalar SQL function implementations
****************************************************************************/

/*
** Implementation of the json_QUOTE(VALUE) function.  Return a JSON value
** corresponding to the SQL value input.  Mostly this means putting 
** double-quotes around strings and returning the unquoted string "null"
** when given a NULL input.
*/
static void jsonQuoteFunc(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  JsonString jx;
  UNUSED_PARAMETER(argc);

  jsonInit(&jx, ctx);
  jsonAppendValue(&jx, argv[0]);
  jsonResult(&jx);
  sqlite3_result_subtype(ctx, JSON_SUBTYPE);
}

/*
** Implementation of the json_array(VALUE,...) function.  Return a JSON
** array that contains all values given in arguments.  Or if any argument
** is a BLOB, throw an error.
*/
static void jsonArrayFunc(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  int i;
  JsonString jx;

  jsonInit(&jx, ctx);
  jsonAppendChar(&jx, '[');
  for(i=0; i<argc; i++){
    jsonAppendSeparator(&jx);
    jsonAppendValue(&jx, argv[i]);
  }
  jsonAppendChar(&jx, ']');
  jsonResult(&jx);
  sqlite3_result_subtype(ctx, JSON_SUBTYPE);
}


/*
** json_array_length(JSON)
** json_array_length(JSON, PATH)
**
** Return the number of elements in the top-level JSON array.  
** Return 0 if the input is not a well-formed JSON array.
*/
static void jsonArrayLengthFunc(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  JsonParse *p;          /* The parse */
  sqlite3_int64 n = 0;
  u32 i;
  JsonNode *pNode;

  p = jsonParseCached(ctx, argv, ctx);
  if( p==0 ) return;
  assert( p->nNode );
  if( argc==2 ){
    const char *zPath = (const char*)sqlite3_value_text(argv[1]);
    pNode = jsonLookup(p, zPath, 0, ctx);
  }else{
    pNode = p->aNode;
  }
  if( pNode==0 ){
    return;
  }
  if( pNode->eType==JSON_ARRAY ){
    assert( (pNode->jnFlags & JNODE_APPEND)==0 );
    for(i=1; i<=pNode->n; n++){
      i += jsonNodeSize(&pNode[i]);
    }
  }
  sqlite3_result_int64(ctx, n);
}

/*
** Bit values for the flags passed into jsonExtractFunc() or
** jsonSetFunc() via the user-data value.
*/
#define JSON_JSON      0x01        /* Result is always JSON */
#define JSON_SQL       0x02        /* Result is always SQL */
#define JSON_ABPATH    0x03        /* Allow abbreviated JSON path specs */
#define JSON_ISSET     0x04        /* json_set(), not json_insert() */

/*
** json_extract(JSON, PATH, ...)
** "->"(JSON,PATH)
** "->>"(JSON,PATH)
**
** Return the element described by PATH.  Return NULL if that PATH element
** is not found.
**
** If JSON_JSON is set or if more that one PATH argument is supplied then
** always return a JSON representation of the result.  If JSON_SQL is set,
** then always return an SQL representation of the result.  If neither flag
** is present and argc==2, then return JSON for objects and arrays and SQL
** for all other values.
**
** When multiple PATH arguments are supplied, the result is a JSON array
** containing the result of each PATH.
**
** Abbreviated JSON path expressions are allows if JSON_ABPATH, for
** compatibility with PG.
*/
static void jsonExtractFunc(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  JsonParse *p;          /* The parse */
  JsonNode *pNode;
  const char *zPath;
  int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx));
  JsonString jx;

  if( argc<2 ) return;
  p = jsonParseCached(ctx, argv, ctx);
  if( p==0 ) return;
  if( argc==2 ){
    /* With a single PATH argument */
    zPath = (const char*)sqlite3_value_text(argv[1]);
    if( zPath==0 ) return;
    if( flags & JSON_ABPATH ){
      if( zPath[0]!='$' ){
        /* The -> and ->> operators accept abbreviated PATH arguments.  This
        ** is mostly for compatibility with PostgreSQL, but also for
        ** convenience.
        **
        **     NUMBER   ==>  $[NUMBER]     // PG compatible
        **     LABEL    ==>  $.LABEL       // PG compatible
        **     [NUMBER] ==>  $[NUMBER]     // Not PG.  Purely for convenience
        */
        jsonInit(&jx, ctx);
        if( sqlite3Isdigit(zPath[0]) ){
          jsonAppendRaw(&jx, "$[", 2);
          jsonAppendRaw(&jx, zPath, (int)strlen(zPath));
          jsonAppendRaw(&jx, "]", 2);
        }else{
          jsonAppendRaw(&jx, "$.", 1 + (zPath[0]!='['));
          jsonAppendRaw(&jx, zPath, (int)strlen(zPath));
          jsonAppendChar(&jx, 0);
        }
        pNode = jx.bErr ? 0 : jsonLookup(p, jx.zBuf, 0, ctx);
        jsonReset(&jx);
      }else{
        pNode = jsonLookup(p, zPath, 0, ctx);
      }
      if( pNode ){
        if( flags & JSON_JSON ){
          jsonReturnJson(pNode, ctx, 0);
        }else{
          jsonReturn(pNode, ctx, 0);
          sqlite3_result_subtype(ctx, 0);
        }
      }
    }else{
      pNode = jsonLookup(p, zPath, 0, ctx);
      if( p->nErr==0 && pNode ) jsonReturn(pNode, ctx, 0);
    }
  }else{
    /* Two or more PATH arguments results in a JSON array with each
    ** element of the array being the value selected by one of the PATHs */
    int i;
    jsonInit(&jx, ctx);
    jsonAppendChar(&jx, '[');
    for(i=1; i<argc; i++){
      zPath = (const char*)sqlite3_value_text(argv[i]);
      pNode = jsonLookup(p, zPath, 0, ctx);
      if( p->nErr ) break;
      jsonAppendSeparator(&jx);
      if( pNode ){
        jsonRenderNode(pNode, &jx, 0);
      }else{
        jsonAppendRaw(&jx, "null", 4);
      }
    }
    if( i==argc ){
      jsonAppendChar(&jx, ']');
      jsonResult(&jx);
      sqlite3_result_subtype(ctx, JSON_SUBTYPE);
    }
    jsonReset(&jx);
  }
}

/* This is the RFC 7396 MergePatch algorithm.
*/
static JsonNode *jsonMergePatch(
  JsonParse *pParse,   /* The JSON parser that contains the TARGET */
  u32 iTarget,         /* Node of the TARGET in pParse */
  JsonNode *pPatch     /* The PATCH */
){
  u32 i, j;
  u32 iRoot;
  JsonNode *pTarget;
  if( pPatch->eType!=JSON_OBJECT ){
    return pPatch;
  }
  assert( iTarget<pParse->nNode );
  pTarget = &pParse->aNode[iTarget];
  assert( (pPatch->jnFlags & JNODE_APPEND)==0 );
  if( pTarget->eType!=JSON_OBJECT ){
    jsonRemoveAllNulls(pPatch);
    return pPatch;
  }
  iRoot = iTarget;
  for(i=1; i<pPatch->n; i += jsonNodeSize(&pPatch[i+1])+1){
    u32 nKey;
    const char *zKey;
    assert( pPatch[i].eType==JSON_STRING );
    assert( pPatch[i].jnFlags & JNODE_LABEL );
    assert( pPatch[i].eU==1 );
    nKey = pPatch[i].n;
    zKey = pPatch[i].u.zJContent;
    assert( (pPatch[i].jnFlags & JNODE_RAW)==0 );
    for(j=1; j<pTarget->n; j += jsonNodeSize(&pTarget[j+1])+1 ){
      assert( pTarget[j].eType==JSON_STRING );
      assert( pTarget[j].jnFlags & JNODE_LABEL );
      assert( (pPatch[i].jnFlags & JNODE_RAW)==0 );
      if( pTarget[j].n==nKey && strncmp(pTarget[j].u.zJContent,zKey,nKey)==0 ){
        if( pTarget[j+1].jnFlags & (JNODE_REMOVE|JNODE_PATCH) ) break;
        if( pPatch[i+1].eType==JSON_NULL ){
          pTarget[j+1].jnFlags |= JNODE_REMOVE;
        }else{
          JsonNode *pNew = jsonMergePatch(pParse, iTarget+j+1, &pPatch[i+1]);
          if( pNew==0 ) return 0;
          pTarget = &pParse->aNode[iTarget];
          if( pNew!=&pTarget[j+1] ){
            assert( pTarget[j+1].eU==0
                 || pTarget[j+1].eU==1
                 || pTarget[j+1].eU==2 );
            testcase( pTarget[j+1].eU==1 );
            testcase( pTarget[j+1].eU==2 );
            VVA( pTarget[j+1].eU = 5 );
            pTarget[j+1].u.pPatch = pNew;
            pTarget[j+1].jnFlags |= JNODE_PATCH;
          }
        }
        break;
      }
    }
    if( j>=pTarget->n && pPatch[i+1].eType!=JSON_NULL ){
      int iStart, iPatch;
      iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0);
      jsonParseAddNode(pParse, JSON_STRING, nKey, zKey);
      iPatch = jsonParseAddNode(pParse, JSON_TRUE, 0, 0);
      if( pParse->oom ) return 0;
      jsonRemoveAllNulls(pPatch);
      pTarget = &pParse->aNode[iTarget];
      assert( pParse->aNode[iRoot].eU==0 || pParse->aNode[iRoot].eU==2 );
      testcase( pParse->aNode[iRoot].eU==2 );
      pParse->aNode[iRoot].jnFlags |= JNODE_APPEND;
      VVA( pParse->aNode[iRoot].eU = 2 );
      pParse->aNode[iRoot].u.iAppend = iStart - iRoot;
      iRoot = iStart;
      assert( pParse->aNode[iPatch].eU==0 );
      VVA( pParse->aNode[iPatch].eU = 5 );
      pParse->aNode[iPatch].jnFlags |= JNODE_PATCH;
      pParse->aNode[iPatch].u.pPatch = &pPatch[i+1];
    }
  }
  return pTarget;
}

/*
** Implementation of the json_mergepatch(JSON1,JSON2) function.  Return a JSON
** object that is the result of running the RFC 7396 MergePatch() algorithm
** on the two arguments.
*/
static void jsonPatchFunc(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  JsonParse x;     /* The JSON that is being patched */
  JsonParse y;     /* The patch */
  JsonNode *pResult;   /* The result of the merge */

  UNUSED_PARAMETER(argc);
  if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
  if( jsonParse(&y, ctx, (const char*)sqlite3_value_text(argv[1])) ){
    jsonParseReset(&x);
    return;
  }
  pResult = jsonMergePatch(&x, 0, y.aNode);
  assert( pResult!=0 || x.oom );
  if( pResult ){
    jsonReturnJson(pResult, ctx, 0);
  }else{
    sqlite3_result_error_nomem(ctx);
  }
  jsonParseReset(&x);
  jsonParseReset(&y);
}


/*
** Implementation of the json_object(NAME,VALUE,...) function.  Return a JSON
** object that contains all name/value given in arguments.  Or if any name
** is not a string or if any value is a BLOB, throw an error.
*/
static void jsonObjectFunc(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  int i;
  JsonString jx;
  const char *z;
  u32 n;

  if( argc&1 ){
    sqlite3_result_error(ctx, "json_object() requires an even number "
                                  "of arguments", -1);
    return;
  }
  jsonInit(&jx, ctx);
  jsonAppendChar(&jx, '{');
  for(i=0; i<argc; i+=2){
    if( sqlite3_value_type(argv[i])!=SQLITE_TEXT ){
      sqlite3_result_error(ctx, "json_object() labels must be TEXT", -1);
      jsonReset(&jx);
      return;
    }
    jsonAppendSeparator(&jx);
    z = (const char*)sqlite3_value_text(argv[i]);
    n = (u32)sqlite3_value_bytes(argv[i]);
    jsonAppendString(&jx, z, n);
    jsonAppendChar(&jx, ':');
    jsonAppendValue(&jx, argv[i+1]);
  }
  jsonAppendChar(&jx, '}');
  jsonResult(&jx);
  sqlite3_result_subtype(ctx, JSON_SUBTYPE);
}


/*
** json_remove(JSON, PATH, ...)
**
** Remove the named elements from JSON and return the result.  malformed
** JSON or PATH arguments result in an error.
*/
static void jsonRemoveFunc(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  JsonParse x;          /* The parse */
  JsonNode *pNode;
  const char *zPath;
  u32 i;

  if( argc<1 ) return;
  if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
  assert( x.nNode );
  for(i=1; i<(u32)argc; i++){
    zPath = (const char*)sqlite3_value_text(argv[i]);
    if( zPath==0 ) goto remove_done;
    pNode = jsonLookup(&x, zPath, 0, ctx);
    if( x.nErr ) goto remove_done;
    if( pNode ) pNode->jnFlags |= JNODE_REMOVE;
  }
  if( (x.aNode[0].jnFlags & JNODE_REMOVE)==0 ){
    jsonReturnJson(x.aNode, ctx, 0);
  }
remove_done:
  jsonParseReset(&x);
}

/*
** json_replace(JSON, PATH, VALUE, ...)
**
** Replace the value at PATH with VALUE.  If PATH does not already exist,
** this routine is a no-op.  If JSON or PATH is malformed, throw an error.
*/
static void jsonReplaceFunc(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  JsonParse x;          /* The parse */
  JsonNode *pNode;
  const char *zPath;
  u32 i;

  if( argc<1 ) return;
  if( (argc&1)==0 ) {
    jsonWrongNumArgs(ctx, "replace");
    return;
  }
  if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
  assert( x.nNode );
  for(i=1; i<(u32)argc; i+=2){
    zPath = (const char*)sqlite3_value_text(argv[i]);
    pNode = jsonLookup(&x, zPath, 0, ctx);
    if( x.nErr ) goto replace_err;
    if( pNode ){
      assert( pNode->eU==0 || pNode->eU==1 || pNode->eU==4 );
      testcase( pNode->eU!=0 && pNode->eU!=1 );
      pNode->jnFlags |= (u8)JNODE_REPLACE;
      VVA( pNode->eU =  4 );
      pNode->u.iReplace = i + 1;
    }
  }
  if( x.aNode[0].jnFlags & JNODE_REPLACE ){
    assert( x.aNode[0].eU==4 );
    sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]);
  }else{
    jsonReturnJson(x.aNode, ctx, argv);
  }
replace_err:
  jsonParseReset(&x);
}


/*
** json_set(JSON, PATH, VALUE, ...)
**
** Set the value at PATH to VALUE.  Create the PATH if it does not already
** exist.  Overwrite existing values that do exist.
** If JSON or PATH is malformed, throw an error.
**
** json_insert(JSON, PATH, VALUE, ...)
**
** Create PATH and initialize it to VALUE.  If PATH already exists, this
** routine is a no-op.  If JSON or PATH is malformed, throw an error.
*/
static void jsonSetFunc(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  JsonParse x;          /* The parse */
  JsonNode *pNode;
  const char *zPath;
  u32 i;
  int bApnd;
  int bIsSet = sqlite3_user_data(ctx)!=0;

  if( argc<1 ) return;
  if( (argc&1)==0 ) {
    jsonWrongNumArgs(ctx, bIsSet ? "set" : "insert");
    return;
  }
  if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
  assert( x.nNode );
  for(i=1; i<(u32)argc; i+=2){
    zPath = (const char*)sqlite3_value_text(argv[i]);
    bApnd = 0;
    pNode = jsonLookup(&x, zPath, &bApnd, ctx);
    if( x.oom ){
      sqlite3_result_error_nomem(ctx);
      goto jsonSetDone;
    }else if( x.nErr ){
      goto jsonSetDone;
    }else if( pNode && (bApnd || bIsSet) ){
      testcase( pNode->eU!=0 && pNode->eU!=1 );
      assert( pNode->eU!=3 && pNode->eU!=5 );
      VVA( pNode->eU = 4 );
      pNode->jnFlags |= (u8)JNODE_REPLACE;
      pNode->u.iReplace = i + 1;
    }
  }
  if( x.aNode[0].jnFlags & JNODE_REPLACE ){
    assert( x.aNode[0].eU==4 );
    sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]);
  }else{
    jsonReturnJson(x.aNode, ctx, argv);
  }
jsonSetDone:
  jsonParseReset(&x);
}

/*
** json_type(JSON)
** json_type(JSON, PATH)
**
** Return the top-level "type" of a JSON string.  json_type() raises an
** error if either the JSON or PATH inputs are not well-formed.
*/
static void jsonTypeFunc(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  JsonParse *p;          /* The parse */
  const char *zPath;
  JsonNode *pNode;

  p = jsonParseCached(ctx, argv, ctx);
  if( p==0 ) return;
  if( argc==2 ){
    zPath = (const char*)sqlite3_value_text(argv[1]);
    pNode = jsonLookup(p, zPath, 0, ctx);
  }else{
    pNode = p->aNode;
  }
  if( pNode ){
    sqlite3_result_text(ctx, jsonType[pNode->eType], -1, SQLITE_STATIC);
  }
}

/*
** json_valid(JSON)
**
** Return 1 if JSON is a well-formed JSON string according to RFC-7159.
** Return 0 otherwise.
*/
static void jsonValidFunc(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  JsonParse *p;          /* The parse */
  UNUSED_PARAMETER(argc);
  p = jsonParseCached(ctx, argv, 0);
  sqlite3_result_int(ctx, p!=0);
}


/****************************************************************************
** Aggregate SQL function implementations
****************************************************************************/
/*
** json_group_array(VALUE)
**
** Return a JSON array composed of all values in the aggregate.
*/
static void jsonArrayStep(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  JsonString *pStr;
  UNUSED_PARAMETER(argc);
  pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
  if( pStr ){
    if( pStr->zBuf==0 ){
      jsonInit(pStr, ctx);
      jsonAppendChar(pStr, '[');
    }else if( pStr->nUsed>1 ){
      jsonAppendChar(pStr, ',');
    }
    pStr->pCtx = ctx;
    jsonAppendValue(pStr, argv[0]);
  }
}
static void jsonArrayCompute(sqlite3_context *ctx, int isFinal){
  JsonString *pStr;
  pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
  if( pStr ){
    pStr->pCtx = ctx;
    jsonAppendChar(pStr, ']');
    if( pStr->bErr ){
      if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx);
      assert( pStr->bStatic );
    }else if( isFinal ){
      sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed,
                          pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free);
      pStr->bStatic = 1;
    }else{
      sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT);
      pStr->nUsed--;
    }
  }else{
    sqlite3_result_text(ctx, "[]", 2, SQLITE_STATIC);
  }
  sqlite3_result_subtype(ctx, JSON_SUBTYPE);
}
static void jsonArrayValue(sqlite3_context *ctx){
  jsonArrayCompute(ctx, 0);
}
static void jsonArrayFinal(sqlite3_context *ctx){
  jsonArrayCompute(ctx, 1);
}

#ifndef SQLITE_OMIT_WINDOWFUNC
/*
** This method works for both json_group_array() and json_group_object().
** It works by removing the first element of the group by searching forward
** to the first comma (",") that is not within a string and deleting all
** text through that comma.
*/
static void jsonGroupInverse(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  unsigned int i;
  int inStr = 0;
  int nNest = 0;
  char *z;
  char c;
  JsonString *pStr;
  UNUSED_PARAMETER(argc);
  UNUSED_PARAMETER(argv);
  pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
#ifdef NEVER
  /* pStr is always non-NULL since jsonArrayStep() or jsonObjectStep() will
  ** always have been called to initalize it */
  if( NEVER(!pStr) ) return;
#endif
  z = pStr->zBuf;
  for(i=1; i<pStr->nUsed && ((c = z[i])!=',' || inStr || nNest); i++){
    if( c=='"' ){
      inStr = !inStr;
    }else if( c=='\\' ){
      i++;
    }else if( !inStr ){
      if( c=='{' || c=='[' ) nNest++;
      if( c=='}' || c==']' ) nNest--;
    }
  }
  if( i<pStr->nUsed ){
    pStr->nUsed -= i;
    memmove(&z[1], &z[i+1], (size_t)pStr->nUsed-1);
    z[pStr->nUsed] = 0;
  }else{
    pStr->nUsed = 1;
  }
}
#else
# define jsonGroupInverse 0
#endif


/*
** json_group_obj(NAME,VALUE)
**
** Return a JSON object composed of all names and values in the aggregate.
*/
static void jsonObjectStep(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
  JsonString *pStr;
  const char *z;
  u32 n;
  UNUSED_PARAMETER(argc);
  pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
  if( pStr ){
    if( pStr->zBuf==0 ){
      jsonInit(pStr, ctx);
      jsonAppendChar(pStr, '{');
    }else if( pStr->nUsed>1 ){
      jsonAppendChar(pStr, ',');
    }
    pStr->pCtx = ctx;
    z = (const char*)sqlite3_value_text(argv[0]);
    n = (u32)sqlite3_value_bytes(argv[0]);
    jsonAppendString(pStr, z, n);
    jsonAppendChar(pStr, ':');
    jsonAppendValue(pStr, argv[1]);
  }
}
static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){
  JsonString *pStr;
  pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
  if( pStr ){
    jsonAppendChar(pStr, '}');
    if( pStr->bErr ){
      if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx);
      assert( pStr->bStatic );
    }else if( isFinal ){
      sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed,
                          pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free);
      pStr->bStatic = 1;
    }else{
      sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT);
      pStr->nUsed--;
    }
  }else{
    sqlite3_result_text(ctx, "{}", 2, SQLITE_STATIC);
  }
  sqlite3_result_subtype(ctx, JSON_SUBTYPE);
}
static void jsonObjectValue(sqlite3_context *ctx){
  jsonObjectCompute(ctx, 0);
}
static void jsonObjectFinal(sqlite3_context *ctx){
  jsonObjectCompute(ctx, 1);
}



#ifndef SQLITE_OMIT_VIRTUALTABLE
/****************************************************************************
** The json_each virtual table
****************************************************************************/
typedef struct JsonEachCursor JsonEachCursor;
struct JsonEachCursor {
  sqlite3_vtab_cursor base;  /* Base class - must be first */
  u32 iRowid;                /* The rowid */
  u32 iBegin;                /* The first node of the scan */
  u32 i;                     /* Index in sParse.aNode[] of current row */
  u32 iEnd;                  /* EOF when i equals or exceeds this value */
  u8 eType;                  /* Type of top-level element */
  u8 bRecursive;             /* True for json_tree().  False for json_each() */
  char *zJson;               /* Input JSON */
  char *zRoot;               /* Path by which to filter zJson */
  JsonParse sParse;          /* Parse of the input JSON */
};

/* Constructor for the json_each virtual table */
static int jsonEachConnect(
  sqlite3 *db,
  void *pAux,
  int argc, const char *const*argv,
  sqlite3_vtab **ppVtab,
  char **pzErr
){
  sqlite3_vtab *pNew;
  int rc;

/* Column numbers */
#define JEACH_KEY     0
#define JEACH_VALUE   1
#define JEACH_TYPE    2
#define JEACH_ATOM    3
#define JEACH_ID      4
#define JEACH_PARENT  5
#define JEACH_FULLKEY 6
#define JEACH_PATH    7
/* The xBestIndex method assumes that the JSON and ROOT columns are
** the last two columns in the table.  Should this ever changes, be
** sure to update the xBestIndex method. */
#define JEACH_JSON    8
#define JEACH_ROOT    9

  UNUSED_PARAMETER(pzErr);
  UNUSED_PARAMETER(argv);
  UNUSED_PARAMETER(argc);
  UNUSED_PARAMETER(pAux);
  rc = sqlite3_declare_vtab(db, 
     "CREATE TABLE x(key,value,type,atom,id,parent,fullkey,path,"
                    "json HIDDEN,root HIDDEN)");
  if( rc==SQLITE_OK ){
    pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) );
    if( pNew==0 ) return SQLITE_NOMEM;
    memset(pNew, 0, sizeof(*pNew));
    sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
  }
  return rc;
}

/* destructor for json_each virtual table */
static int jsonEachDisconnect(sqlite3_vtab *pVtab){
  sqlite3_free(pVtab);
  return SQLITE_OK;
}

/* constructor for a JsonEachCursor object for json_each(). */
static int jsonEachOpenEach(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
  JsonEachCursor *pCur;

  UNUSED_PARAMETER(p);
  pCur = sqlite3_malloc( sizeof(*pCur) );
  if( pCur==0 ) return SQLITE_NOMEM;
  memset(pCur, 0, sizeof(*pCur));
  *ppCursor = &pCur->base;
  return SQLITE_OK;
}

/* constructor for a JsonEachCursor object for json_tree(). */
static int jsonEachOpenTree(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
  int rc = jsonEachOpenEach(p, ppCursor);
  if( rc==SQLITE_OK ){
    JsonEachCursor *pCur = (JsonEachCursor*)*ppCursor;
    pCur->bRecursive = 1;
  }
  return rc;
}

/* Reset a JsonEachCursor back to its original state.  Free any memory
** held. */
static void jsonEachCursorReset(JsonEachCursor *p){
  sqlite3_free(p->zJson);
  sqlite3_free(p->zRoot);
  jsonParseReset(&p->sParse);
  p->iRowid = 0;
  p->i = 0;
  p->iEnd = 0;
  p->eType = 0;
  p->zJson = 0;
  p->zRoot = 0;
}

/* Destructor for a jsonEachCursor object */
static int jsonEachClose(sqlite3_vtab_cursor *cur){
  JsonEachCursor *p = (JsonEachCursor*)cur;
  jsonEachCursorReset(p);
  sqlite3_free(cur);
  return SQLITE_OK;
}

/* Return TRUE if the jsonEachCursor object has been advanced off the end
** of the JSON object */
static int jsonEachEof(sqlite3_vtab_cursor *cur){
  JsonEachCursor *p = (JsonEachCursor*)cur;
  return p->i >= p->iEnd;
}

/* Advance the cursor to the next element for json_tree() */
static int jsonEachNext(sqlite3_vtab_cursor *cur){
  JsonEachCursor *p = (JsonEachCursor*)cur;
  if( p->bRecursive ){
    if( p->sParse.aNode[p->i].jnFlags & JNODE_LABEL ) p->i++;
    p->i++;
    p->iRowid++;
    if( p->i<p->iEnd ){
      u32 iUp = p->sParse.aUp[p->i];
      JsonNode *pUp = &p->sParse.aNode[iUp];
      p->eType = pUp->eType;
      if( pUp->eType==JSON_ARRAY ){
        assert( pUp->eU==0 || pUp->eU==3 );
        testcase( pUp->eU==3 );
        VVA( pUp->eU = 3 );
        if( iUp==p->i-1 ){
          pUp->u.iKey = 0;
        }else{
          pUp->u.iKey++;
        }
      }
    }
  }else{
    switch( p->eType ){
      case JSON_ARRAY: {
        p->i += jsonNodeSize(&p->sParse.aNode[p->i]);
        p->iRowid++;
        break;
      }
      case JSON_OBJECT: {
        p->i += 1 + jsonNodeSize(&p->sParse.aNode[p->i+1]);
        p->iRowid++;
        break;
      }
      default: {
        p->i = p->iEnd;
        break;
      }
    }
  }
  return SQLITE_OK;
}

/* Append an object label to the JSON Path being constructed
** in pStr.
*/
static void jsonAppendObjectPathElement(
  JsonString *pStr,
  JsonNode *pNode
){
  int jj, nn;
  const char *z;
  assert( pNode->eType==JSON_STRING );
  assert( pNode->jnFlags & JNODE_LABEL );
  assert( pNode->eU==1 );
  z = pNode->u.zJContent;
  nn = pNode->n;
  assert( nn>=2 );
  assert( z[0]=='"' );
  assert( z[nn-1]=='"' );
  if( nn>2 && sqlite3Isalpha(z[1]) ){
    for(jj=2; jj<nn-1 && sqlite3Isalnum(z[jj]); jj++){}
    if( jj==nn-1 ){
      z++;
      nn -= 2;
    }
  }
  jsonPrintf(nn+2, pStr, ".%.*s", nn, z);
}

/* Append the name of the path for element i to pStr
*/
static void jsonEachComputePath(
  JsonEachCursor *p,       /* The cursor */
  JsonString *pStr,        /* Write the path here */
  u32 i                    /* Path to this element */
){
  JsonNode *pNode, *pUp;
  u32 iUp;
  if( i==0 ){
    jsonAppendChar(pStr, '$');
    return;
  }
  iUp = p->sParse.aUp[i];
  jsonEachComputePath(p, pStr, iUp);
  pNode = &p->sParse.aNode[i];
  pUp = &p->sParse.aNode[iUp];
  if( pUp->eType==JSON_ARRAY ){
    assert( pUp->eU==3 || (pUp->eU==0 && pUp->u.iKey==0) );
    testcase( pUp->eU==0 );
    jsonPrintf(30, pStr, "[%d]", pUp->u.iKey);
  }else{
    assert( pUp->eType==JSON_OBJECT );
    if( (pNode->jnFlags & JNODE_LABEL)==0 ) pNode--;
    jsonAppendObjectPathElement(pStr, pNode);
  }
}

/* Return the value of a column */
static int jsonEachColumn(
  sqlite3_vtab_cursor *cur,   /* The cursor */
  sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
  int i                       /* Which column to return */
){
  JsonEachCursor *p = (JsonEachCursor*)cur;
  JsonNode *pThis = &p->sParse.aNode[p->i];
  switch( i ){
    case JEACH_KEY: {
      if( p->i==0 ) break;
      if( p->eType==JSON_OBJECT ){
        jsonReturn(pThis, ctx, 0);
      }else if( p->eType==JSON_ARRAY ){
        u32 iKey;
        if( p->bRecursive ){
          if( p->iRowid==0 ) break;
          assert( p->sParse.aNode[p->sParse.aUp[p->i]].eU==3 );
          iKey = p->sParse.aNode[p->sParse.aUp[p->i]].u.iKey;
        }else{
          iKey = p->iRowid;
        }
        sqlite3_result_int64(ctx, (sqlite3_int64)iKey);
      }
      break;
    }
    case JEACH_VALUE: {
      if( pThis->jnFlags & JNODE_LABEL ) pThis++;
      jsonReturn(pThis, ctx, 0);
      break;
    }
    case JEACH_TYPE: {
      if( pThis->jnFlags & JNODE_LABEL ) pThis++;
      sqlite3_result_text(ctx, jsonType[pThis->eType], -1, SQLITE_STATIC);
      break;
    }
    case JEACH_ATOM: {
      if( pThis->jnFlags & JNODE_LABEL ) pThis++;
      if( pThis->eType>=JSON_ARRAY ) break;
      jsonReturn(pThis, ctx, 0);
      break;
    }
    case JEACH_ID: {
      sqlite3_result_int64(ctx, 
         (sqlite3_int64)p->i + ((pThis->jnFlags & JNODE_LABEL)!=0));
      break;
    }
    case JEACH_PARENT: {
      if( p->i>p->iBegin && p->bRecursive ){
        sqlite3_result_int64(ctx, (sqlite3_int64)p->sParse.aUp[p->i]);
      }
      break;
    }
    case JEACH_FULLKEY: {
      JsonString x;
      jsonInit(&x, ctx);
      if( p->bRecursive ){
        jsonEachComputePath(p, &x, p->i);
      }else{
        if( p->zRoot ){
          jsonAppendRaw(&x, p->zRoot, (int)strlen(p->zRoot));
        }else{
          jsonAppendChar(&x, '$');
        }
        if( p->eType==JSON_ARRAY ){
          jsonPrintf(30, &x, "[%d]", p->iRowid);
        }else if( p->eType==JSON_OBJECT ){
          jsonAppendObjectPathElement(&x, pThis);
        }
      }
      jsonResult(&x);
      break;
    }
    case JEACH_PATH: {
      if( p->bRecursive ){
        JsonString x;
        jsonInit(&x, ctx);
        jsonEachComputePath(p, &x, p->sParse.aUp[p->i]);
        jsonResult(&x);
        break;
      }
      /* For json_each() path and root are the same so fall through
      ** into the root case */
      /* no break */ deliberate_fall_through
    }
    default: {
      const char *zRoot = p->zRoot;
      if( zRoot==0 ) zRoot = "$";
      sqlite3_result_text(ctx, zRoot, -1, SQLITE_STATIC);
      break;
    }
    case JEACH_JSON: {
      assert( i==JEACH_JSON );
      sqlite3_result_text(ctx, p->sParse.zJson, -1, SQLITE_STATIC);
      break;
    }
  }
  return SQLITE_OK;
}

/* Return the current rowid value */
static int jsonEachRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
  JsonEachCursor *p = (JsonEachCursor*)cur;
  *pRowid = p->iRowid;
  return SQLITE_OK;
}

/* The query strategy is to look for an equality constraint on the json
** column.  Without such a constraint, the table cannot operate.  idxNum is
** 1 if the constraint is found, 3 if the constraint and zRoot are found,
** and 0 otherwise.
*/
static int jsonEachBestIndex(
  sqlite3_vtab *tab,
  sqlite3_index_info *pIdxInfo
){
  int i;                     /* Loop counter or computed array index */
  int aIdx[2];               /* Index of constraints for JSON and ROOT */
  int unusableMask = 0;      /* Mask of unusable JSON and ROOT constraints */
  int idxMask = 0;           /* Mask of usable == constraints JSON and ROOT */
  const struct sqlite3_index_constraint *pConstraint;

  /* This implementation assumes that JSON and ROOT are the last two
  ** columns in the table */
  assert( JEACH_ROOT == JEACH_JSON+1 );
  UNUSED_PARAMETER(tab);
  aIdx[0] = aIdx[1] = -1;
  pConstraint = pIdxInfo->aConstraint;
  for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
    int iCol;
    int iMask;
    if( pConstraint->iColumn < JEACH_JSON ) continue;
    iCol = pConstraint->iColumn - JEACH_JSON;
    assert( iCol==0 || iCol==1 );
    testcase( iCol==0 );
    iMask = 1 << iCol;
    if( pConstraint->usable==0 ){
      unusableMask |= iMask;
    }else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
      aIdx[iCol] = i;
      idxMask |= iMask;
    }
  }
  if( pIdxInfo->nOrderBy>0 
   && pIdxInfo->aOrderBy[0].iColumn<0 
   && pIdxInfo->aOrderBy[0].desc==0
  ){
    pIdxInfo->orderByConsumed = 1;
  }

  if( (unusableMask & ~idxMask)!=0 ){
    /* If there are any unusable constraints on JSON or ROOT, then reject
    ** this entire plan */
    return SQLITE_CONSTRAINT;
  }
  if( aIdx[0]<0 ){
    /* No JSON input.  Leave estimatedCost at the huge value that it was
    ** initialized to to discourage the query planner from selecting this
    ** plan. */
    pIdxInfo->idxNum = 0;
  }else{
    pIdxInfo->estimatedCost = 1.0;
    i = aIdx[0];
    pIdxInfo->aConstraintUsage[i].argvIndex = 1;
    pIdxInfo->aConstraintUsage[i].omit = 1;
    if( aIdx[1]<0 ){
      pIdxInfo->idxNum = 1;  /* Only JSON supplied.  Plan 1 */
    }else{
      i = aIdx[1];
      pIdxInfo->aConstraintUsage[i].argvIndex = 2;
      pIdxInfo->aConstraintUsage[i].omit = 1;
      pIdxInfo->idxNum = 3;  /* Both JSON and ROOT are supplied.  Plan 3 */
    }
  }
  return SQLITE_OK;
}

/* Start a search on a new JSON string */
static int jsonEachFilter(
  sqlite3_vtab_cursor *cur,
  int idxNum, const char *idxStr,
  int argc, sqlite3_value **argv
){
  JsonEachCursor *p = (JsonEachCursor*)cur;
  const char *z;
  const char *zRoot = 0;
  sqlite3_int64 n;

  UNUSED_PARAMETER(idxStr);
  UNUSED_PARAMETER(argc);
  jsonEachCursorReset(p);
  if( idxNum==0 ) return SQLITE_OK;
  z = (const char*)sqlite3_value_text(argv[0]);
  if( z==0 ) return SQLITE_OK;
  n = sqlite3_value_bytes(argv[0]);
  p->zJson = sqlite3_malloc64( n+1 );
  if( p->zJson==0 ) return SQLITE_NOMEM;
  memcpy(p->zJson, z, (size_t)n+1);
  if( jsonParse(&p->sParse, 0, p->zJson) ){
    int rc = SQLITE_NOMEM;
    if( p->sParse.oom==0 ){
      sqlite3_free(cur->pVtab->zErrMsg);
      cur->pVtab->zErrMsg = sqlite3_mprintf("malformed JSON");
      if( cur->pVtab->zErrMsg ) rc = SQLITE_ERROR;
    }
    jsonEachCursorReset(p);
    return rc;
  }else if( p->bRecursive && jsonParseFindParents(&p->sParse) ){
    jsonEachCursorReset(p);
    return SQLITE_NOMEM;
  }else{
    JsonNode *pNode = 0;
    if( idxNum==3 ){
      const char *zErr = 0;
      zRoot = (const char*)sqlite3_value_text(argv[1]);
      if( zRoot==0 ) return SQLITE_OK;
      n = sqlite3_value_bytes(argv[1]);
      p->zRoot = sqlite3_malloc64( n+1 );
      if( p->zRoot==0 ) return SQLITE_NOMEM;
      memcpy(p->zRoot, zRoot, (size_t)n+1);
      if( zRoot[0]!='$' ){
        zErr = zRoot;
      }else{
        pNode = jsonLookupStep(&p->sParse, 0, p->zRoot+1, 0, &zErr);
      }
      if( zErr ){
        sqlite3_free(cur->pVtab->zErrMsg);
        cur->pVtab->zErrMsg = jsonPathSyntaxError(zErr);
        jsonEachCursorReset(p);
        return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM;
      }else if( pNode==0 ){
        return SQLITE_OK;
      }
    }else{
      pNode = p->sParse.aNode;
    }
    p->iBegin = p->i = (int)(pNode - p->sParse.aNode);
    p->eType = pNode->eType;
    if( p->eType>=JSON_ARRAY ){
      assert( pNode->eU==0 );
      VVA( pNode->eU = 3 );
      pNode->u.iKey = 0;
      p->iEnd = p->i + pNode->n + 1;
      if( p->bRecursive ){
        p->eType = p->sParse.aNode[p->sParse.aUp[p->i]].eType;
        if( p->i>0 && (p->sParse.aNode[p->i-1].jnFlags & JNODE_LABEL)!=0 ){
          p->i--;
        }
      }else{
        p->i++;
      }
    }else{
      p->iEnd = p->i+1;
    }
  }
  return SQLITE_OK;
}

/* The methods of the json_each virtual table */
static sqlite3_module jsonEachModule = {
  0,                         /* iVersion */
  0,                         /* xCreate */
  jsonEachConnect,           /* xConnect */
  jsonEachBestIndex,         /* xBestIndex */
  jsonEachDisconnect,        /* xDisconnect */
  0,                         /* xDestroy */
  jsonEachOpenEach,          /* xOpen - open a cursor */
  jsonEachClose,             /* xClose - close a cursor */
  jsonEachFilter,            /* xFilter - configure scan constraints */
  jsonEachNext,              /* xNext - advance a cursor */
  jsonEachEof,               /* xEof - check for end of scan */
  jsonEachColumn,            /* xColumn - read data */
  jsonEachRowid,             /* xRowid - read data */
  0,                         /* xUpdate */
  0,                         /* xBegin */
  0,                         /* xSync */
  0,                         /* xCommit */
  0,                         /* xRollback */
  0,                         /* xFindMethod */
  0,                         /* xRename */
  0,                         /* xSavepoint */
  0,                         /* xRelease */
  0,                         /* xRollbackTo */
  0                          /* xShadowName */
};

/* The methods of the json_tree virtual table. */
static sqlite3_module jsonTreeModule = {
  0,                         /* iVersion */
  0,                         /* xCreate */
  jsonEachConnect,           /* xConnect */
  jsonEachBestIndex,         /* xBestIndex */
  jsonEachDisconnect,        /* xDisconnect */
  0,                         /* xDestroy */
  jsonEachOpenTree,          /* xOpen - open a cursor */
  jsonEachClose,             /* xClose - close a cursor */
  jsonEachFilter,            /* xFilter - configure scan constraints */
  jsonEachNext,              /* xNext - advance a cursor */
  jsonEachEof,               /* xEof - check for end of scan */
  jsonEachColumn,            /* xColumn - read data */
  jsonEachRowid,             /* xRowid - read data */
  0,                         /* xUpdate */
  0,                         /* xBegin */
  0,                         /* xSync */
  0,                         /* xCommit */
  0,                         /* xRollback */
  0,                         /* xFindMethod */
  0,                         /* xRename */
  0,                         /* xSavepoint */
  0,                         /* xRelease */
  0,                         /* xRollbackTo */
  0                          /* xShadowName */
};
#endif /* SQLITE_OMIT_VIRTUALTABLE */
#endif /* !defined(SQLITE_OMIT_JSON) */

/*
** Register JSON functions.
*/
void sqlite3RegisterJsonFunctions(void){
#ifndef SQLITE_OMIT_JSON
  static FuncDef aJsonFunc[] = {
    JFUNCTION(json,               1, 0,  jsonRemoveFunc),
    JFUNCTION(json_array,        -1, 0,  jsonArrayFunc),
    JFUNCTION(json_array_length,  1, 0,  jsonArrayLengthFunc),
    JFUNCTION(json_array_length,  2, 0,  jsonArrayLengthFunc),
    JFUNCTION(json_extract,      -1, 0,  jsonExtractFunc),
    JFUNCTION(->,                 2, JSON_JSON, jsonExtractFunc),
    JFUNCTION(->>,                2, JSON_SQL, jsonExtractFunc),
    JFUNCTION(json_insert,       -1, 0,  jsonSetFunc),
    JFUNCTION(json_object,       -1, 0,  jsonObjectFunc),
    JFUNCTION(json_patch,         2, 0,  jsonPatchFunc),
    JFUNCTION(json_quote,         1, 0,  jsonQuoteFunc),
    JFUNCTION(json_remove,       -1, 0,  jsonRemoveFunc),
    JFUNCTION(json_replace,      -1, 0,  jsonReplaceFunc),
    JFUNCTION(json_set,          -1, JSON_ISSET,  jsonSetFunc),
    JFUNCTION(json_type,          1, 0,  jsonTypeFunc),
    JFUNCTION(json_type,          2, 0,  jsonTypeFunc),
    JFUNCTION(json_valid,         1, 0,  jsonValidFunc),
#if SQLITE_DEBUG
    JFUNCTION(json_parse,         1, 0,  jsonParseFunc),
    JFUNCTION(json_test1,         1, 0,  jsonTest1Func),
#endif
    WAGGREGATE(json_group_array,  1, 0, 0, 
       jsonArrayStep, jsonArrayFinal, jsonArrayValue, jsonGroupInverse,
       SQLITE_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC),
    WAGGREGATE(json_group_object, 2, 0, 0, 
       jsonObjectStep, jsonObjectFinal, jsonObjectValue, jsonGroupInverse,
       SQLITE_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC)
  };
  sqlite3InsertBuiltinFuncs(aJsonFunc, ArraySize(aJsonFunc));
#endif
}

#if  !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON)
/*
** Register the JSON table-valued functions
*/
int sqlite3JsonTableFunctions(sqlite3 *db){
  int rc = SQLITE_OK;
  static const struct {
    const char *zName;
    sqlite3_module *pModule;
  } aMod[] = {
    { "json_each",            &jsonEachModule               },
    { "json_tree",            &jsonTreeModule               },
  };
  unsigned int i;
  for(i=0; i<sizeof(aMod)/sizeof(aMod[0]) && rc==SQLITE_OK; i++){
    rc = sqlite3_create_module(db, aMod[i].zName, aMod[i].pModule, 0);
  }
  return rc;
}
#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON) */

Changes to src/legacy.c.

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







-
+













-

-










+








  if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
  if( zSql==0 ) zSql = "";

  sqlite3_mutex_enter(db->mutex);
  sqlite3Error(db, SQLITE_OK);
  while( rc==SQLITE_OK && zSql[0] ){
    int nCol;
    int nCol = 0;
    char **azVals = 0;

    pStmt = 0;
    rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
    assert( rc==SQLITE_OK || pStmt==0 );
    if( rc!=SQLITE_OK ){
      continue;
    }
    if( !pStmt ){
      /* this happens for a comment or white-space */
      zSql = zLeftover;
      continue;
    }

    callbackIsInit = 0;
    nCol = sqlite3_column_count(pStmt);

    while( 1 ){
      int i;
      rc = sqlite3_step(pStmt);

      /* Invoke the callback function if required */
      if( xCallback && (SQLITE_ROW==rc || 
          (SQLITE_DONE==rc && !callbackIsInit
                           && db->flags&SQLITE_NullCallback)) ){
        if( !callbackIsInit ){
          nCol = sqlite3_column_count(pStmt);
          azCols = sqlite3DbMallocRaw(db, (2*nCol+1)*sizeof(const char*));
          if( azCols==0 ){
            goto exec_out;
          }
          for(i=0; i<nCol; i++){
            azCols[i] = (char *)sqlite3_column_name(pStmt, i);
            /* sqlite3VdbeSetColName() installs column names as UTF8

Changes to src/loadext.c.

451
452
453
454
455
456
457
458

459
460

461






















































462








463
464
465
466
467
468
469
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







-
+

-
+

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

+
+
+
+
+
+
+
+







  sqlite3_str_errcode,
  sqlite3_str_length,
  sqlite3_str_value,
  /* Version 3.25.0 and later */
  sqlite3_create_window_function,
  /* Version 3.26.0 and later */
#ifdef SQLITE_ENABLE_NORMALIZE
  sqlite3_normalized_sql
  sqlite3_normalized_sql,
#else
  0
  0,
#endif
  /* Version 3.28.0 and later */
  sqlite3_stmt_isexplain,
  sqlite3_value_frombind,
  /* Version 3.30.0 and later */
#ifndef SQLITE_OMIT_VIRTUALTABLE
  sqlite3_drop_modules,
#else
  0,
#endif
  /* Version 3.31.0 and later */
  sqlite3_hard_heap_limit64,
  sqlite3_uri_key,
  sqlite3_filename_database,
  sqlite3_filename_journal,
  sqlite3_filename_wal,
  /* Version 3.32.0 and later */
  sqlite3_create_filename,
  sqlite3_free_filename,
  sqlite3_database_file_object,
  /* Version 3.34.0 and later */
  sqlite3_txn_state,
  /* Version 3.36.1 and later */
  sqlite3_changes64,
  sqlite3_total_changes64,
  /* Version 3.37.0 and later */
  sqlite3_autovacuum_pages,
  /* Version 3.38.0 and later */
  sqlite3_error_offset,
#ifndef SQLITE_OMIT_VIRTUALTABLE
  sqlite3_vtab_rhs_value,
  sqlite3_vtab_distinct,
  sqlite3_vtab_in,
  sqlite3_vtab_in_first,
  sqlite3_vtab_in_next,
#else
  0,
  0,
  0,
  0,
  0,
#endif
  /* Version 3.39.0 and later */
#ifndef SQLITE_OMIT_DESERIALIZE
  sqlite3_deserialize,
  sqlite3_serialize,
#else
  0,
  0,
#endif
  sqlite3_db_name,
  /* Version 3.40.0 and later */
  sqlite3_value_encoding,
  /* Version 3.41.0 and later */
  sqlite3_is_interrupted
};

/* True if x is the directory separator character
*/
#if SQLITE_OS_WIN
# define DirSep(X)  ((X)=='/'||(X)=='\\')
#else
# define DirSep(X)  ((X)=='/')
#endif

/*
** Attempt to load an SQLite extension library contained in the file
** zFile.  The entry point is zProc.  zProc may be 0 in which case a
** default entry point name (sqlite3_extension_init) is used.  Use
** of the default name is recommended.
**
482
483
484
485
486
487
488
489

490
491
492
493
494
495
496
544
545
546
547
548
549
550

551
552
553
554
555
556
557
558







-
+







  sqlite3_vfs *pVfs = db->pVfs;
  void *handle;
  sqlite3_loadext_entry xInit;
  char *zErrmsg = 0;
  const char *zEntry;
  char *zAltEntry = 0;
  void **aHandle;
  u64 nMsg = 300 + sqlite3Strlen30(zFile);
  u64 nMsg = strlen(zFile);
  int ii;
  int rc;

  /* Shared library endings to try if zFile cannot be loaded as written */
  static const char *azEndings[] = {
#if SQLITE_OS_WIN
     "dll"   
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
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







+
+
+
+
+
+









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







      *pzErrMsg = sqlite3_mprintf("not authorized");
    }
    return SQLITE_ERROR;
  }

  zEntry = zProc ? zProc : "sqlite3_extension_init";

  /* tag-20210611-1.  Some dlopen() implementations will segfault if given
  ** an oversize filename.  Most filesystems have a pathname limit of 4K,
  ** so limit the extension filename length to about twice that.
  ** https://sqlite.org/forum/forumpost/08a0d6d9bf */
  if( nMsg>SQLITE_MAX_PATHLEN ) goto extension_not_found;
    
  handle = sqlite3OsDlOpen(pVfs, zFile);
#if SQLITE_OS_UNIX || SQLITE_OS_WIN
  for(ii=0; ii<ArraySize(azEndings) && handle==0; ii++){
    char *zAltFile = sqlite3_mprintf("%s.%s", zFile, azEndings[ii]);
    if( zAltFile==0 ) return SQLITE_NOMEM_BKPT;
    handle = sqlite3OsDlOpen(pVfs, zAltFile);
    sqlite3_free(zAltFile);
  }
#endif
  if( handle==0 ){
  if( handle==0 ) goto extension_not_found;
    if( pzErrMsg ){
      *pzErrMsg = zErrmsg = sqlite3_malloc64(nMsg);
      if( zErrmsg ){
        sqlite3_snprintf(nMsg, zErrmsg, 
            "unable to open shared library [%s]", zFile);
        sqlite3OsDlError(pVfs, nMsg-1, zErrmsg);
      }
    }
    return SQLITE_ERROR;
  }
  xInit = (sqlite3_loadext_entry)sqlite3OsDlSym(pVfs, handle, zEntry);

  /* If no entry point was specified and the default legacy
  ** entry point name "sqlite3_extension_init" was not found, then
  ** construct an entry point name "sqlite3_X_init" where the X is
  ** replaced by the lowercase value of every ASCII alphabetic 
  ** character in the filename after the last "/" upto the first ".",
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
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







-
+













-
+


+
-
+







    int ncFile = sqlite3Strlen30(zFile);
    zAltEntry = sqlite3_malloc64(ncFile+30);
    if( zAltEntry==0 ){
      sqlite3OsDlClose(pVfs, handle);
      return SQLITE_NOMEM_BKPT;
    }
    memcpy(zAltEntry, "sqlite3_", 8);
    for(iFile=ncFile-1; iFile>=0 && zFile[iFile]!='/'; iFile--){}
    for(iFile=ncFile-1; iFile>=0 && !DirSep(zFile[iFile]); iFile--){}
    iFile++;
    if( sqlite3_strnicmp(zFile+iFile, "lib", 3)==0 ) iFile += 3;
    for(iEntry=8; (c = zFile[iFile])!=0 && c!='.'; iFile++){
      if( sqlite3Isalpha(c) ){
        zAltEntry[iEntry++] = (char)sqlite3UpperToLower[(unsigned)c];
      }
    }
    memcpy(zAltEntry+iEntry, "_init", 6);
    zEntry = zAltEntry;
    xInit = (sqlite3_loadext_entry)sqlite3OsDlSym(pVfs, handle, zEntry);
  }
  if( xInit==0 ){
    if( pzErrMsg ){
      nMsg += sqlite3Strlen30(zEntry);
      nMsg += strlen(zEntry) + 300;
      *pzErrMsg = zErrmsg = sqlite3_malloc64(nMsg);
      if( zErrmsg ){
        assert( nMsg<0x7fffffff );  /* zErrmsg would be NULL if not so */
        sqlite3_snprintf(nMsg, zErrmsg,
        sqlite3_snprintf((int)nMsg, zErrmsg,
            "no entry point [%s] in shared library [%s]", zEntry, zFile);
        sqlite3OsDlError(pVfs, nMsg-1, zErrmsg);
      }
    }
    sqlite3OsDlClose(pVfs, handle);
    sqlite3_free(zAltEntry);
    return SQLITE_ERROR;
609
610
611
612
613
614
615













616
617
618
619
620
621
622
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







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







    memcpy(aHandle, db->aExtension, sizeof(handle)*db->nExtension);
  }
  sqlite3DbFree(db, db->aExtension);
  db->aExtension = aHandle;

  db->aExtension[db->nExtension++] = handle;
  return SQLITE_OK;

extension_not_found:
  if( pzErrMsg ){
    nMsg += 300;
    *pzErrMsg = zErrmsg = sqlite3_malloc64(nMsg);
    if( zErrmsg ){
      assert( nMsg<0x7fffffff );  /* zErrmsg would be NULL if not so */
      sqlite3_snprintf((int)nMsg, zErrmsg,
          "unable to open shared library [%.*s]", SQLITE_MAX_PATHLEN, zFile);
      sqlite3OsDlError(pVfs, nMsg-1, zErrmsg);
    }
  }
  return SQLITE_ERROR;
}
int sqlite3_load_extension(
  sqlite3 *db,          /* Load the extension into this database connection */
  const char *zFile,    /* Name of the shared library containing extension */
  const char *zProc,    /* Entry point.  Use "sqlite3_extension_init" if 0 */
  char **pzErrMsg       /* Put error message here if not 0 */
){
658
659
660
661
662
663
664
665

666
667
668
669
670
671
672
730
731
732
733
734
735
736

737
738
739
740
741
742
743
744







-
+








#endif /* !defined(SQLITE_OMIT_LOAD_EXTENSION) */

/*
** The following object holds the list of automatically loaded
** extensions.
**
** This list is shared across threads.  The SQLITE_MUTEX_STATIC_MASTER
** This list is shared across threads.  The SQLITE_MUTEX_STATIC_MAIN
** mutex must be held while accessing this list.
*/
typedef struct sqlite3AutoExtList sqlite3AutoExtList;
static SQLITE_WSD struct sqlite3AutoExtList {
  u32 nExt;              /* Number of entries in aExt[] */          
  void (**aExt)(void);   /* Pointers to the extension init functions */
} sqlite3Autoext = { 0, 0 };
700
701
702
703
704
705
706
707

708
709
710
711
712
713
714
772
773
774
775
776
777
778

779
780
781
782
783
784
785
786







-
+







  if( rc ){
    return rc;
  }else
#endif
  {
    u32 i;
#if SQLITE_THREADSAFE
    sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
    sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN);
#endif
    wsdAutoextInit;
    sqlite3_mutex_enter(mutex);
    for(i=0; i<wsdAutoext.nExt; i++){
      if( wsdAutoext.aExt[i]==xInit ) break;
    }
    if( i==wsdAutoext.nExt ){
738
739
740
741
742
743
744
745

746
747
748
749
750
751
752
810
811
812
813
814
815
816

817
818
819
820
821
822
823
824







-
+







** Return 1 if xInit was found on the list and removed.  Return 0 if xInit
** was not on the list.
*/
int sqlite3_cancel_auto_extension(
  void (*xInit)(void)
){
#if SQLITE_THREADSAFE
  sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
  sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN);
#endif
  int i;
  int n = 0;
  wsdAutoextInit;
  sqlite3_mutex_enter(mutex);
  for(i=(int)wsdAutoext.nExt-1; i>=0; i--){
    if( wsdAutoext.aExt[i]==xInit ){
765
766
767
768
769
770
771
772

773
774
775
776
777
778
779
837
838
839
840
841
842
843

844
845
846
847
848
849
850
851







-
+







*/
void sqlite3_reset_auto_extension(void){
#ifndef SQLITE_OMIT_AUTOINIT
  if( sqlite3_initialize()==SQLITE_OK )
#endif
  {
#if SQLITE_THREADSAFE
    sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
    sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN);
#endif
    wsdAutoextInit;
    sqlite3_mutex_enter(mutex);
    sqlite3_free(wsdAutoext.aExt);
    wsdAutoext.aExt = 0;
    wsdAutoext.nExt = 0;
    sqlite3_mutex_leave(mutex);
795
796
797
798
799
800
801
802

803
804
805
806
807
808
809
867
868
869
870
871
872
873

874
875
876
877
878
879
880
881







-
+







  if( wsdAutoext.nExt==0 ){
    /* Common case: early out without every having to acquire a mutex */
    return;
  }
  for(i=0; go; i++){
    char *zErrmsg;
#if SQLITE_THREADSAFE
    sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
    sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN);
#endif
#ifdef SQLITE_OMIT_LOAD_EXTENSION
    const sqlite3_api_routines *pThunk = 0;
#else
    const sqlite3_api_routines *pThunk = &sqlite3Apis;
#endif
    sqlite3_mutex_enter(mutex);

Changes to src/main.c.

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







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

+
+
+
+
+
+



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

-
+

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



-
+







#endif
#ifdef SQLITE_ENABLE_RTREE
# include "rtree.h"
#endif
#if defined(SQLITE_ENABLE_ICU) || defined(SQLITE_ENABLE_ICU_COLLATIONS)
# include "sqliteicu.h"
#endif

/*
** This is an extension initializer that is a no-op and always
** succeeds, except that it fails if the fault-simulation is set
** to 500.
*/
static int sqlite3TestExtInit(sqlite3 *db){
  (void)db;
  return sqlite3FaultSim(500);
}


/*
** Forward declarations of external module initializer functions
** for modules that need them.
*/
#ifdef SQLITE_ENABLE_JSON1
int sqlite3Json1Init(sqlite3*);
#ifdef SQLITE_ENABLE_FTS1
int sqlite3Fts1Init(sqlite3*);
#endif
#ifdef SQLITE_ENABLE_FTS2
int sqlite3Fts2Init(sqlite3*);
#endif
#ifdef SQLITE_ENABLE_FTS5
int sqlite3Fts5Init(sqlite3*);
#endif
#ifdef SQLITE_ENABLE_STMTVTAB
int sqlite3StmtVtabInit(sqlite3*);
#endif

/*
** An array of pointers to extension initializer functions for
** built-in extensions.
*/
static int (*const sqlite3BuiltinExtensions[])(sqlite3*) = {
#ifdef SQLITE_ENABLE_FTS1
  sqlite3Fts1Init,
#endif
#ifdef SQLITE_ENABLE_FTS2
  sqlite3Fts2Init,
#endif
#ifdef SQLITE_ENABLE_FTS3
  sqlite3Fts3Init,
#endif
#ifdef SQLITE_ENABLE_FTS5
int sqlite3Fts5Init(sqlite3*);
  sqlite3Fts5Init,
#endif
#if defined(SQLITE_ENABLE_ICU) || defined(SQLITE_ENABLE_ICU_COLLATIONS)
  sqlite3IcuInit,
#endif
#ifdef SQLITE_ENABLE_RTREE
  sqlite3RtreeInit,
#endif
#ifdef SQLITE_ENABLE_DBPAGE_VTAB
  sqlite3DbpageRegister,
#endif
#ifdef SQLITE_ENABLE_DBSTAT_VTAB
  sqlite3DbstatRegister,
#endif
  sqlite3TestExtInit,
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON)
  sqlite3JsonTableFunctions,
#endif
#ifdef SQLITE_ENABLE_STMTVTAB
  sqlite3StmtVtabInit,
#endif
#ifdef SQLITE_ENABLE_BYTECODE_VTAB
  sqlite3VdbeBytecodeVtabInit,
#endif
};

#ifndef SQLITE_AMALGAMATION
/* IMPLEMENTATION-OF: R-46656-45156 The sqlite3_version[] string constant
** contains the text of SQLITE_VERSION macro. 
** contains the text of SQLITE_VERSION macro.
*/
const char sqlite3_version[] = SQLITE_VERSION;
#endif

/* IMPLEMENTATION-OF: R-53536-42575 The sqlite3_libversion() function returns
** a pointer to the to the sqlite3_version[] string constant. 
*/
134
135
136
137
138
139
140
141

142
143
144
145
146
147
148
194
195
196
197
198
199
200

201
202
203
204
205
206
207
208







-
+







**    *  Calls to this routine from Y must block until the outer-most
**       call by X completes.
**
**    *  Recursive calls to this routine from thread X return immediately
**       without blocking.
*/
int sqlite3_initialize(void){
  MUTEX_LOGIC( sqlite3_mutex *pMaster; )       /* The main static mutex */
  MUTEX_LOGIC( sqlite3_mutex *pMainMtx; )      /* The main static mutex */
  int rc;                                      /* Result code */
#ifdef SQLITE_EXTRA_INIT
  int bRunExtraInit = 0;                       /* Extra initialization needed */
#endif

#ifdef SQLITE_OMIT_WSD
  rc = sqlite3_wsd_init(4096, 24);
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
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







-
+
+
+
+













-
+




-
-
+
+

















-
+







  assert( SQLITE_PTRSIZE==sizeof(char*) );

  /* If SQLite is already completely initialized, then this call
  ** to sqlite3_initialize() should be a no-op.  But the initialization
  ** must be complete.  So isInit must not be set until the very end
  ** of this routine.
  */
  if( sqlite3GlobalConfig.isInit ) return SQLITE_OK;
  if( sqlite3GlobalConfig.isInit ){
    sqlite3MemoryBarrier();
    return SQLITE_OK;
  }

  /* Make sure the mutex subsystem is initialized.  If unable to 
  ** initialize the mutex subsystem, return early with the error.
  ** If the system is so sick that we are unable to allocate a mutex,
  ** there is not much SQLite is going to be able to do.
  **
  ** The mutex subsystem must take care of serializing its own
  ** initialization.
  */
  rc = sqlite3MutexInit();
  if( rc ) return rc;

  /* Initialize the malloc() system and the recursive pInitMutex mutex.
  ** This operation is protected by the STATIC_MASTER mutex.  Note that
  ** This operation is protected by the STATIC_MAIN mutex.  Note that
  ** MutexAlloc() is called for a static mutex prior to initializing the
  ** malloc subsystem - this implies that the allocation of a static
  ** mutex must not require support from the malloc subsystem.
  */
  MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
  sqlite3_mutex_enter(pMaster);
  MUTEX_LOGIC( pMainMtx = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); )
  sqlite3_mutex_enter(pMainMtx);
  sqlite3GlobalConfig.isMutexInit = 1;
  if( !sqlite3GlobalConfig.isMallocInit ){
    rc = sqlite3MallocInit();
  }
  if( rc==SQLITE_OK ){
    sqlite3GlobalConfig.isMallocInit = 1;
    if( !sqlite3GlobalConfig.pInitMutex ){
      sqlite3GlobalConfig.pInitMutex =
           sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
      if( sqlite3GlobalConfig.bCoreMutex && !sqlite3GlobalConfig.pInitMutex ){
        rc = SQLITE_NOMEM_BKPT;
      }
    }
  }
  if( rc==SQLITE_OK ){
    sqlite3GlobalConfig.nRefInitMutex++;
  }
  sqlite3_mutex_leave(pMaster);
  sqlite3_mutex_leave(pMainMtx);

  /* If rc is not SQLITE_OK at this point, then either the malloc
  ** subsystem could not be initialized or the system failed to allocate
  ** the pInitMutex mutex. Return an error in either case.  */
  if( rc!=SQLITE_OK ){
    return rc;
  }
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
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







-
+







+












-
+






-
+







    if( sqlite3GlobalConfig.isPCacheInit==0 ){
      rc = sqlite3PcacheInitialize();
    }
    if( rc==SQLITE_OK ){
      sqlite3GlobalConfig.isPCacheInit = 1;
      rc = sqlite3OsInit();
    }
#ifdef SQLITE_ENABLE_DESERIALIZE
#ifndef SQLITE_OMIT_DESERIALIZE
    if( rc==SQLITE_OK ){
      rc = sqlite3MemdbInit();
    }
#endif
    if( rc==SQLITE_OK ){
      sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage, 
          sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);
      sqlite3MemoryBarrier();
      sqlite3GlobalConfig.isInit = 1;
#ifdef SQLITE_EXTRA_INIT
      bRunExtraInit = 1;
#endif
    }
    sqlite3GlobalConfig.inProgress = 0;
  }
  sqlite3_mutex_leave(sqlite3GlobalConfig.pInitMutex);

  /* Go back under the static mutex and clean up the recursive
  ** mutex to prevent a resource leak.
  */
  sqlite3_mutex_enter(pMaster);
  sqlite3_mutex_enter(pMainMtx);
  sqlite3GlobalConfig.nRefInitMutex--;
  if( sqlite3GlobalConfig.nRefInitMutex<=0 ){
    assert( sqlite3GlobalConfig.nRefInitMutex==0 );
    sqlite3_mutex_free(sqlite3GlobalConfig.pInitMutex);
    sqlite3GlobalConfig.pInitMutex = 0;
  }
  sqlite3_mutex_leave(pMaster);
  sqlite3_mutex_leave(pMainMtx);

  /* The following is just a sanity check to make sure SQLite has
  ** been compiled correctly.  It is important to run this code, but
  ** we don't want to run it too often and soak up CPU cycles for no
  ** reason.  So we run it once during initialization.
  */
#ifndef NDEBUG
649
650
651
652
653
654
655







656
657
658
659
660
661
662
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733







+
+
+
+
+
+
+







        iVal = SQLITE_DEFAULT_SORTERREF_SIZE;
      }
      sqlite3GlobalConfig.szSorterRef = (u32)iVal;
      break;
    }
#endif /* SQLITE_ENABLE_SORTER_REFERENCES */

#ifndef SQLITE_OMIT_DESERIALIZE
    case SQLITE_CONFIG_MEMDB_MAXSIZE: {
      sqlite3GlobalConfig.mxMemdbSize = va_arg(ap, sqlite3_int64);
      break;
    }
#endif /* SQLITE_OMIT_DESERIALIZE */

    default: {
      rc = SQLITE_ERROR;
      break;
    }
  }
  va_end(ap);
  return rc;
672
673
674
675
676
677
678



679
680
681
682
683
684
685
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759







+
+
+







** space for the lookaside memory is obtained from sqlite3_malloc().
** If pStart is not NULL then it is sz*cnt bytes of memory to use for
** the lookaside memory.
*/
static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
#ifndef SQLITE_OMIT_LOOKASIDE
  void *pStart;
  sqlite3_int64 szAlloc = sz*(sqlite3_int64)cnt;
  int nBig;   /* Number of full-size slots */
  int nSm;    /* Number smaller LOOKASIDE_SMALL-byte slots */
  
  if( sqlite3LookasideUsed(db,0)>0 ){
    return SQLITE_BUSY;
  }
  /* Free any existing lookaside buffer for this handle before
  ** allocating a new one so we don't have to have space for 
  ** both at the same time.
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
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







-
+

-
+


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





+




-

-
+




+
+
+
+
+
+
+
+
+
+
+



+

-
-
+
+
+
+
+
+
+

+



+
+







  if( sz<=(int)sizeof(LookasideSlot*) ) sz = 0;
  if( cnt<0 ) cnt = 0;
  if( sz==0 || cnt==0 ){
    sz = 0;
    pStart = 0;
  }else if( pBuf==0 ){
    sqlite3BeginBenignMalloc();
    pStart = sqlite3Malloc( sz*cnt );  /* IMP: R-61949-35727 */
    pStart = sqlite3Malloc( szAlloc );  /* IMP: R-61949-35727 */
    sqlite3EndBenignMalloc();
    if( pStart ) cnt = sqlite3MallocSize(pStart)/sz;
    if( pStart ) szAlloc = sqlite3MallocSize(pStart);
  }else{
    pStart = pBuf;
  }
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
  if( sz>=LOOKASIDE_SMALL*3 ){
    nBig = szAlloc/(3*LOOKASIDE_SMALL+sz);
    nSm = (szAlloc - sz*nBig)/LOOKASIDE_SMALL;
  }else if( sz>=LOOKASIDE_SMALL*2 ){
    nBig = szAlloc/(LOOKASIDE_SMALL+sz);
    nSm = (szAlloc - sz*nBig)/LOOKASIDE_SMALL;
  }else
#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
  if( sz>0 ){
    nBig = szAlloc/sz;
    nSm = 0;
  }else{
    nBig = nSm = 0;
  }
  db->lookaside.pStart = pStart;
  db->lookaside.pInit = 0;
  db->lookaside.pFree = 0;
  db->lookaside.sz = (u16)sz;
  db->lookaside.szTrue = (u16)sz;
  if( pStart ){
    int i;
    LookasideSlot *p;
    assert( sz > (int)sizeof(LookasideSlot*) );
    db->lookaside.nSlot = cnt;
    p = (LookasideSlot*)pStart;
    for(i=cnt-1; i>=0; i--){
    for(i=0; i<nBig; i++){
      p->pNext = db->lookaside.pInit;
      db->lookaside.pInit = p;
      p = (LookasideSlot*)&((u8*)p)[sz];
    }
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
    db->lookaside.pSmallInit = 0;
    db->lookaside.pSmallFree = 0;
    db->lookaside.pMiddle = p;
    for(i=0; i<nSm; i++){
      p->pNext = db->lookaside.pSmallInit;
      db->lookaside.pSmallInit = p;
      p = (LookasideSlot*)&((u8*)p)[LOOKASIDE_SMALL];
    }
#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
    assert( ((uptr)p)<=szAlloc + (uptr)pStart );
    db->lookaside.pEnd = p;
    db->lookaside.bDisable = 0;
    db->lookaside.bMalloced = pBuf==0 ?1:0;
    db->lookaside.nSlot = nBig+nSm;
  }else{
    db->lookaside.pStart = db;
    db->lookaside.pEnd = db;
    db->lookaside.pStart = 0;
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
    db->lookaside.pSmallInit = 0;
    db->lookaside.pSmallFree = 0;
    db->lookaside.pMiddle = 0;
#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
    db->lookaside.pEnd = 0;
    db->lookaside.bDisable = 1;
    db->lookaside.sz = 0;
    db->lookaside.bMalloced = 0;
    db->lookaside.nSlot = 0;
  }
  db->lookaside.pTrueEnd = db->lookaside.pEnd;
  assert( sqlite3LookasideUsed(db,0)==0 );
#endif /* SQLITE_OMIT_LOOKASIDE */
  return SQLITE_OK;
}

/*
** Return the mutex associated with a database connection.
*/
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
891
892
893
894
895
896
897

898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925







-
+



















+







#ifdef SQLITE_ENABLE_API_ARMOR
  if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
#endif
  sqlite3_mutex_enter(db->mutex);
  sqlite3BtreeEnterAll(db);
  for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
    Btree *pBt = db->aDb[i].pBt;
    if( pBt && sqlite3BtreeIsInTrans(pBt) ){
    if( pBt && sqlite3BtreeTxnState(pBt)==SQLITE_TXN_WRITE ){
      Pager *pPager = sqlite3BtreePager(pBt);
      rc = sqlite3PagerFlush(pPager);
      if( rc==SQLITE_BUSY ){
        bSeenBusy = 1;
        rc = SQLITE_OK;
      }
    }
  }
  sqlite3BtreeLeaveAll(db);
  sqlite3_mutex_leave(db->mutex);
  return ((rc==SQLITE_OK && bSeenBusy) ? SQLITE_BUSY : rc);
}

/*
** Configuration settings for an individual database connection
*/
int sqlite3_db_config(sqlite3 *db, int op, ...){
  va_list ap;
  int rc;
  sqlite3_mutex_enter(db->mutex);
  va_start(ap, op);
  switch( op ){
    case SQLITE_DBCONFIG_MAINDBNAME: {
      /* IMP: R-06824-28531 */
      /* IMP: R-36257-52125 */
      db->aDb[0].zDbSName = va_arg(ap,char*);
      rc = SQLITE_OK;
825
826
827
828
829
830
831

832
833
834
835
836
837
838







839
840
841
842
843
844
845
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963







+







+
+
+
+
+
+
+







    default: {
      static const struct {
        int op;      /* The opcode */
        u32 mask;    /* Mask of the bit in sqlite3.flags to set/clear */
      } aFlagOp[] = {
        { SQLITE_DBCONFIG_ENABLE_FKEY,           SQLITE_ForeignKeys    },
        { SQLITE_DBCONFIG_ENABLE_TRIGGER,        SQLITE_EnableTrigger  },
        { SQLITE_DBCONFIG_ENABLE_VIEW,           SQLITE_EnableView     },
        { SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer  },
        { SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension  },
        { SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE,      SQLITE_NoCkptOnClose  },
        { SQLITE_DBCONFIG_ENABLE_QPSG,           SQLITE_EnableQPSG     },
        { SQLITE_DBCONFIG_TRIGGER_EQP,           SQLITE_TriggerEQP     },
        { SQLITE_DBCONFIG_RESET_DATABASE,        SQLITE_ResetDatabase  },
        { SQLITE_DBCONFIG_DEFENSIVE,             SQLITE_Defensive      },
        { SQLITE_DBCONFIG_WRITABLE_SCHEMA,       SQLITE_WriteSchema|
                                                 SQLITE_NoSchemaError  },
        { SQLITE_DBCONFIG_LEGACY_ALTER_TABLE,    SQLITE_LegacyAlter    },
        { SQLITE_DBCONFIG_DQS_DDL,               SQLITE_DqsDDL         },
        { SQLITE_DBCONFIG_DQS_DML,               SQLITE_DqsDML         },
        { SQLITE_DBCONFIG_LEGACY_FILE_FORMAT,    SQLITE_LegacyFileFmt  },
        { SQLITE_DBCONFIG_TRUSTED_SCHEMA,        SQLITE_TrustedSchema  },
      };
      unsigned int i;
      rc = SQLITE_ERROR; /* IMP: R-42790-23372 */
      for(i=0; i<ArraySize(aFlagOp); i++){
        if( aFlagOp[i].op==op ){
          int onoff = va_arg(ap, int);
          int *pRes = va_arg(ap, int*);
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
908
909
910
911



















912
913
914
915
916
917
918

919
920

921
922
923
924
925
926
927
977
978
979
980
981
982
983
984
985
986
987









988
989
990



991
992

993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005














1006
1007
1008
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







+



-
-
-
-
-
-
-
-
-



-
-
-


-
+




+







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






-
+
-
-
+







          break;
        }
      }
      break;
    }
  }
  va_end(ap);
  sqlite3_mutex_leave(db->mutex);
  return rc;
}


/*
** Return true if the buffer z[0..n-1] contains all spaces.
*/
static int allSpaces(const char *z, int n){
  while( n>0 && z[n-1]==' ' ){ n--; }
  return n==0;
}

/*
** This is the default collating function named "BINARY" which is always
** available.
**
** If the padFlag argument is not NULL then space padding at the end
** of strings is ignored.  This implements the RTRIM collation.
*/
static int binCollFunc(
  void *padFlag,
  void *NotUsed,
  int nKey1, const void *pKey1,
  int nKey2, const void *pKey2
){
  int rc, n;
  UNUSED_PARAMETER(NotUsed);
  n = nKey1<nKey2 ? nKey1 : nKey2;
  /* EVIDENCE-OF: R-65033-28449 The built-in BINARY collation compares
  ** strings byte by byte using the memcmp() function from the standard C
  ** library. */
  assert( pKey1 && pKey2 );
  rc = memcmp(pKey1, pKey2, n);
  if( rc==0 ){
    if( padFlag
     && allSpaces(((char*)pKey1)+n, nKey1-n)
     && allSpaces(((char*)pKey2)+n, nKey2-n)
    ){
      /* EVIDENCE-OF: R-31624-24737 RTRIM is like BINARY except that extra
      ** spaces at the end of either string do not change the result. In other
      ** words, strings will compare equal to one another as long as they
      ** differ only in the number of spaces at the end.
      */
    }else{
      rc = nKey1 - nKey2;
    }
  }
  return rc;
    rc = nKey1 - nKey2;
  }
  return rc;
}

/*
** This is the collating function named "RTRIM" which is always
** available.  Ignore trailing spaces.
*/
static int rtrimCollFunc(
  void *pUser,
  int nKey1, const void *pKey1,
  int nKey2, const void *pKey2
){
  const u8 *pK1 = (const u8*)pKey1;
  const u8 *pK2 = (const u8*)pKey2;
  while( nKey1 && pK1[nKey1-1]==' ' ) nKey1--;
  while( nKey2 && pK2[nKey2-1]==' ' ) nKey2--;
  return binCollFunc(pUser, nKey1, pKey1, nKey2, pKey2);
}

/*
** Return true if CollSeq is the default built-in BINARY.
*/
int sqlite3IsBinary(const CollSeq *p){
  assert( p==0 || p->xCmp!=binCollFunc || p->pUser!=0
  assert( p==0 || p->xCmp!=binCollFunc || strcmp(p->zName,"BINARY")==0 );
            || strcmp(p->zName,"BINARY")==0 );
  return p==0 || (p->xCmp==binCollFunc && p->pUser==0);
  return p==0 || p->xCmp==binCollFunc;
}

/*
** Another built-in collating sequence: NOCASE. 
**
** This collating sequence is intended to be used for "case independent
** comparison". SQLite's knowledge of upper and lower case equivalents
970
971
972
973
974
975
976
977

978
979
980
981
982
983
984
985



986
987
988
989
990

991
992
993
994
995
996
997
998



999
1000
1001
1002
1003
1004
1005
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







-
+








+
+
+




-
+








+
+
+







  db->lastRowid = iRowid;
  sqlite3_mutex_leave(db->mutex);
}

/*
** Return the number of changes in the most recent call to sqlite3_exec().
*/
int sqlite3_changes(sqlite3 *db){
sqlite3_int64 sqlite3_changes64(sqlite3 *db){
#ifdef SQLITE_ENABLE_API_ARMOR
  if( !sqlite3SafetyCheckOk(db) ){
    (void)SQLITE_MISUSE_BKPT;
    return 0;
  }
#endif
  return db->nChange;
}
int sqlite3_changes(sqlite3 *db){
  return (int)sqlite3_changes64(db);
}

/*
** Return the number of changes since the database handle was opened.
*/
int sqlite3_total_changes(sqlite3 *db){
sqlite3_int64 sqlite3_total_changes64(sqlite3 *db){
#ifdef SQLITE_ENABLE_API_ARMOR
  if( !sqlite3SafetyCheckOk(db) ){
    (void)SQLITE_MISUSE_BKPT;
    return 0;
  }
#endif
  return db->nTotalChange;
}
int sqlite3_total_changes(sqlite3 *db){
  return (int)sqlite3_total_changes64(db);
}

/*
** Close all open savepoints. This function only manipulates fields of the
** database handle object, it does not close any savepoints that may be open
** at the b-tree/pager level.
*/
void sqlite3CloseSavepoints(sqlite3 *db){
1016
1017
1018
1019
1020
1021
1022
1023



1024
1025
1026
1027
1028
1029
1030
1134
1135
1136
1137
1138
1139
1140

1141
1142
1143
1144
1145
1146
1147
1148
1149
1150







-
+
+
+







/*
** Invoke the destructor function associated with FuncDef p, if any. Except,
** if this is not the last copy of the function, do not invoke it. Multiple
** copies of a single function are created when create_function() is called
** with SQLITE_ANY as the encoding.
*/
static void functionDestroy(sqlite3 *db, FuncDef *p){
  FuncDestructor *pDestructor = p->u.pDestructor;
  FuncDestructor *pDestructor;
  assert( (p->funcFlags & SQLITE_FUNC_BUILTIN)==0 );
  pDestructor = p->u.pDestructor;
  if( pDestructor ){
    pDestructor->nRef--;
    if( pDestructor->nRef==0 ){
      pDestructor->xDestroy(pDestructor->pUserData);
      sqlite3DbFree(db, pDestructor);
    }
  }
1086
1087
1088
1089
1090
1091
1092
1093

1094
1095
1096
1097
1098
1099
1100
1206
1207
1208
1209
1210
1211
1212

1213
1214
1215
1216
1217
1218
1219
1220







-
+







    return SQLITE_OK;
  }
  if( !sqlite3SafetyCheckSickOrOk(db) ){
    return SQLITE_MISUSE_BKPT;
  }
  sqlite3_mutex_enter(db->mutex);
  if( db->mTrace & SQLITE_TRACE_CLOSE ){
    db->xTrace(SQLITE_TRACE_CLOSE, db->pTraceArg, db, 0);
    db->trace.xV2(SQLITE_TRACE_CLOSE, db->pTraceArg, db, 0);
  }

  /* Force xDisconnect calls on all virtual tables */
  disconnectAllVtab(db);

  /* If a transaction is open, the disconnectAllVtab() call above
  ** will not have called the xDisconnect() method on any virtual
1120
1121
1122
1123
1124
1125
1126
1127

1128
1129
1130
1131
1132






























1133
1134
1135

1136
1137
1138
1139
1140
1141
1142
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
1286
1287
1288
1289
1290
1291
1292







-
+





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


-
+







    /* Closing the handle. Fourth parameter is passed the value 2. */
    sqlite3GlobalConfig.xSqllog(sqlite3GlobalConfig.pSqllogArg, db, 0, 2);
  }
#endif

  /* Convert the connection into a zombie and then close it.
  */
  db->magic = SQLITE_MAGIC_ZOMBIE;
  db->eOpenState = SQLITE_STATE_ZOMBIE;
  sqlite3LeaveMutexAndCloseZombie(db);
  return SQLITE_OK;
}

/*
** Return the transaction state for a single databse, or the maximum
** transaction state over all attached databases if zSchema is null.
*/
int sqlite3_txn_state(sqlite3 *db, const char *zSchema){
  int iDb, nDb;
  int iTxn = -1;
#ifdef SQLITE_ENABLE_API_ARMOR
  if( !sqlite3SafetyCheckOk(db) ){
    (void)SQLITE_MISUSE_BKPT;
    return -1;
  }
#endif
  sqlite3_mutex_enter(db->mutex);
  if( zSchema ){
    nDb = iDb = sqlite3FindDbName(db, zSchema);
    if( iDb<0 ) nDb--;
  }else{
    iDb = 0;
    nDb = db->nDb-1;
  }
  for(; iDb<=nDb; iDb++){
    Btree *pBt = db->aDb[iDb].pBt;
    int x = pBt!=0 ? sqlite3BtreeTxnState(pBt) : SQLITE_TXN_NONE;
    if( x>iTxn ) iTxn = x;
  }
  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); }
1154
1155
1156
1157
1158
1159
1160
1161

1162
1163
1164
1165
1166
1167
1168
1304
1305
1306
1307
1308
1309
1310

1311
1312
1313
1314
1315
1316
1317
1318







-
+







  HashElem *i;                    /* Hash table iterator */
  int j;

  /* If there are outstanding sqlite3_stmt or sqlite3_backup objects
  ** or if the connection has not yet been closed by sqlite3_close_v2(),
  ** then just leave the mutex and return.
  */
  if( db->magic!=SQLITE_MAGIC_ZOMBIE || connectionIsBusy(db) ){
  if( db->eOpenState!=SQLITE_STATE_ZOMBIE || connectionIsBusy(db) ){
    sqlite3_mutex_leave(db->mutex);
    return;
  }

  /* If we reach this point, it means that the database connection has
  ** closed all sqlite3_stmt and sqlite3_backup objects and has been
  ** passed to sqlite3_close (meaning that it is a zombie).  Therefore,
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
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







-
-
-

-
+












-
+








+
+
+

-
+







    }
    sqlite3DbFree(db, pColl);
  }
  sqlite3HashClear(&db->aCollSeq);
#ifndef SQLITE_OMIT_VIRTUALTABLE
  for(i=sqliteHashFirst(&db->aModule); i; i=sqliteHashNext(i)){
    Module *pMod = (Module *)sqliteHashData(i);
    if( pMod->xDestroy ){
      pMod->xDestroy(pMod->pAux);
    }
    sqlite3VtabEponymousTableClear(db, pMod);
    sqlite3DbFree(db, pMod);
    sqlite3VtabModuleUnref(db, pMod);
  }
  sqlite3HashClear(&db->aModule);
#endif

  sqlite3Error(db, SQLITE_OK); /* Deallocates any cached error strings. */
  sqlite3ValueFree(db->pErr);
  sqlite3CloseExtensions(db);
#if SQLITE_USER_AUTHENTICATION
  sqlite3_free(db->auth.zAuthUser);
  sqlite3_free(db->auth.zAuthPW);
#endif

  db->magic = SQLITE_MAGIC_ERROR;
  db->eOpenState = SQLITE_STATE_ERROR;

  /* The temp-database schema is allocated differently from the other schema
  ** objects (using sqliteMalloc() directly, instead of sqlite3BtreeSchema()).
  ** So it needs to be freed here. Todo: Why not roll the temp schema into
  ** the same sqliteMalloc() as the one that allocates the database 
  ** structure?
  */
  sqlite3DbFree(db, db->aDb[1].pSchema);
  if( db->xAutovacDestr ){
    db->xAutovacDestr(db->pAutovacPagesArg);
  }
  sqlite3_mutex_leave(db->mutex);
  db->magic = SQLITE_MAGIC_CLOSED;
  db->eOpenState = SQLITE_STATE_CLOSED;
  sqlite3_mutex_free(db->mutex);
  assert( sqlite3LookasideUsed(db,0)==0 );
  if( db->lookaside.bMalloced ){
    sqlite3_free(db->lookaside.pStart);
  }
  sqlite3_free(db);
}
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
1318
1319
1320
1438
1439
1440
1441
1442
1443
1444

1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462

1463
1464
1465
1466
1467
1468
1469
1470







-
+

















-
+







  ** corruption reports in some cases.  */
  sqlite3BtreeEnterAll(db);
  schemaChange = (db->mDbFlags & DBFLAG_SchemaChange)!=0 && db->init.busy==0;

  for(i=0; i<db->nDb; i++){
    Btree *p = db->aDb[i].pBt;
    if( p ){
      if( sqlite3BtreeIsInTrans(p) ){
      if( sqlite3BtreeTxnState(p)==SQLITE_TXN_WRITE ){
        inTrans = 1;
      }
      sqlite3BtreeRollback(p, tripCode, !schemaChange);
    }
  }
  sqlite3VtabRollback(db);
  sqlite3EndBenignMalloc();

  if( schemaChange ){
    sqlite3ExpirePreparedStatements(db, 0);
    sqlite3ResetAllSchemasOfConnection(db);
  }
  sqlite3BtreeLeaveAll(db);

  /* Any deferred constraint violations have now been resolved. */
  db->nDeferredCons = 0;
  db->nDeferredImmCons = 0;
  db->flags &= ~(u64)SQLITE_DeferFKs;
  db->flags &= ~(u64)(SQLITE_DeferFKs|SQLITE_CorruptRdOnly);

  /* If one has been configured, invoke the rollback-hook callback */
  if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){
    db->xRollbackCallback(db->pRollbackArg);
  }
}

1380
1381
1382
1383
1384
1385
1386

1387
1388
1389
1390
1391
1392
1393
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544







+







      case SQLITE_NOTFOUND:           zName = "SQLITE_NOTFOUND";          break;
      case SQLITE_FULL:               zName = "SQLITE_FULL";              break;
      case SQLITE_CANTOPEN:           zName = "SQLITE_CANTOPEN";          break;
      case SQLITE_CANTOPEN_NOTEMPDIR: zName = "SQLITE_CANTOPEN_NOTEMPDIR";break;
      case SQLITE_CANTOPEN_ISDIR:     zName = "SQLITE_CANTOPEN_ISDIR";    break;
      case SQLITE_CANTOPEN_FULLPATH:  zName = "SQLITE_CANTOPEN_FULLPATH"; break;
      case SQLITE_CANTOPEN_CONVPATH:  zName = "SQLITE_CANTOPEN_CONVPATH"; break;
      case SQLITE_CANTOPEN_SYMLINK:   zName = "SQLITE_CANTOPEN_SYMLINK";  break;
      case SQLITE_PROTOCOL:           zName = "SQLITE_PROTOCOL";          break;
      case SQLITE_EMPTY:              zName = "SQLITE_EMPTY";             break;
      case SQLITE_SCHEMA:             zName = "SQLITE_SCHEMA";            break;
      case SQLITE_TOOBIG:             zName = "SQLITE_TOOBIG";            break;
      case SQLITE_CONSTRAINT:         zName = "SQLITE_CONSTRAINT";        break;
      case SQLITE_CONSTRAINT_UNIQUE:  zName = "SQLITE_CONSTRAINT_UNIQUE"; break;
      case SQLITE_CONSTRAINT_TRIGGER: zName = "SQLITE_CONSTRAINT_TRIGGER";break;
1411
1412
1413
1414
1415
1416
1417

1418
1419
1420
1421
1422
1423
1424
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576







+







      case SQLITE_RANGE:              zName = "SQLITE_RANGE";             break;
      case SQLITE_NOTADB:             zName = "SQLITE_NOTADB";            break;
      case SQLITE_ROW:                zName = "SQLITE_ROW";               break;
      case SQLITE_NOTICE:             zName = "SQLITE_NOTICE";            break;
      case SQLITE_NOTICE_RECOVER_WAL: zName = "SQLITE_NOTICE_RECOVER_WAL";break;
      case SQLITE_NOTICE_RECOVER_ROLLBACK:
                                zName = "SQLITE_NOTICE_RECOVER_ROLLBACK"; break;
      case SQLITE_NOTICE_RBU:         zName = "SQLITE_NOTICE_RBU"; break;
      case SQLITE_WARNING:            zName = "SQLITE_WARNING";           break;
      case SQLITE_WARNING_AUTOINDEX:  zName = "SQLITE_WARNING_AUTOINDEX"; break;
      case SQLITE_DONE:               zName = "SQLITE_DONE";              break;
    }
  }
  if( zName==0 ){
    static char zBuf[50];
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
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

1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584

1585
1586
1587
1588
1589
1590
1591
1592
1653
1654
1655
1656
1657
1658
1659

1660

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













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

1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709

1710
1711
1712









1713

1714
1715
1716
1717
1718
1719
1720







-
+
-













-
-
-
-
-
-
-
-
-
-
-
-
-



















-

















-
+


-
-
-
-
-
-
-
-
-
+
-







** argument.
**
** Return non-zero to retry the lock.  Return zero to stop trying
** and cause SQLite to return SQLITE_BUSY.
*/
static int sqliteDefaultBusyCallback(
  void *ptr,               /* Database connection */
  int count,               /* Number of times table has been busy */
  int count                /* Number of times table has been busy */
  sqlite3_file *pFile      /* The file on which the lock occurred */
){
#if SQLITE_OS_WIN || HAVE_USLEEP
  /* This case is for systems that have support for sleeping for fractions of
  ** a second.  Examples:  All windows systems, unix systems with usleep() */
  static const u8 delays[] =
     { 1, 2, 5, 10, 15, 20, 25, 25,  25,  50,  50, 100 };
  static const u8 totals[] =
     { 0, 1, 3,  8, 18, 33, 53, 78, 103, 128, 178, 228 };
# define NDELAY ArraySize(delays)
  sqlite3 *db = (sqlite3 *)ptr;
  int tmout = db->busyTimeout;
  int delay, prior;

#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
  if( sqlite3OsFileControl(pFile,SQLITE_FCNTL_LOCK_TIMEOUT,&tmout)==SQLITE_OK ){
    if( count ){
      tmout = 0;
      sqlite3OsFileControl(pFile, SQLITE_FCNTL_LOCK_TIMEOUT, &tmout);
      return 0;
    }else{
      return 1;
    }
  }
#else
  UNUSED_PARAMETER(pFile);
#endif
  assert( count>=0 );
  if( count < NDELAY ){
    delay = delays[count];
    prior = totals[count];
  }else{
    delay = delays[NDELAY-1];
    prior = totals[NDELAY-1] + delay*(count-(NDELAY-1));
  }
  if( prior + delay > tmout ){
    delay = tmout - prior;
    if( delay<=0 ) return 0;
  }
  sqlite3OsSleep(db->pVfs, delay*1000);
  return 1;
#else
  /* This case for unix systems that lack usleep() support.  Sleeping
  ** must be done in increments of whole seconds */
  sqlite3 *db = (sqlite3 *)ptr;
  int tmout = ((sqlite3 *)ptr)->busyTimeout;
  UNUSED_PARAMETER(pFile);
  if( (count+1)*1000 > tmout ){
    return 0;
  }
  sqlite3OsSleep(db->pVfs, 1000000);
  return 1;
#endif
}

/*
** Invoke the given busy handler.
**
** This routine is called when an operation failed to acquire a
** lock on VFS file pFile.
**
** If this routine returns non-zero, the lock is retried.  If it
** returns 0, the operation aborts with an SQLITE_BUSY error.
*/
int sqlite3InvokeBusyHandler(BusyHandler *p, sqlite3_file *pFile){
int sqlite3InvokeBusyHandler(BusyHandler *p){
  int rc;
  if( p->xBusyHandler==0 || p->nBusy<0 ) return 0;
  if( p->bExtraFileArg ){
    /* Add an extra parameter with the pFile pointer to the end of the
    ** callback argument list */
    int (*xTra)(void*,int,sqlite3_file*);
    xTra = (int(*)(void*,int,sqlite3_file*))p->xBusyHandler;
    rc = xTra(p->pBusyArg, p->nBusy, pFile);
  }else{
    /* Legacy style busy handler callback */
    rc = p->xBusyHandler(p->pBusyArg, p->nBusy);
  rc = p->xBusyHandler(p->pBusyArg, p->nBusy);
  }
  if( rc==0 ){
    p->nBusy = -1;
  }else{
    p->nBusy++;
  }
  return rc; 
}
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1731
1732
1733
1734
1735
1736
1737

1738
1739
1740
1741
1742
1743
1744







-







#ifdef SQLITE_ENABLE_API_ARMOR
  if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
#endif
  sqlite3_mutex_enter(db->mutex);
  db->busyHandler.xBusyHandler = xBusy;
  db->busyHandler.pBusyArg = pArg;
  db->busyHandler.nBusy = 0;
  db->busyHandler.bExtraFileArg = 0;
  db->busyTimeout = 0;
  sqlite3_mutex_leave(db->mutex);
  return SQLITE_OK;
}

#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
/*
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
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







-











-
+
+
+




-
+


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







#ifdef SQLITE_ENABLE_API_ARMOR
  if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
#endif
  if( ms>0 ){
    sqlite3_busy_handler(db, (int(*)(void*,int))sqliteDefaultBusyCallback,
                             (void*)db);
    db->busyTimeout = ms;
    db->busyHandler.bExtraFileArg = 1;
  }else{
    sqlite3_busy_handler(db, 0, 0);
  }
  return SQLITE_OK;
}

/*
** Cause any pending operation to stop at its earliest opportunity.
*/
void sqlite3_interrupt(sqlite3 *db){
#ifdef SQLITE_ENABLE_API_ARMOR
  if( !sqlite3SafetyCheckOk(db) && (db==0 || db->magic!=SQLITE_MAGIC_ZOMBIE) ){
  if( !sqlite3SafetyCheckOk(db)
   && (db==0 || db->eOpenState!=SQLITE_STATE_ZOMBIE)
  ){
    (void)SQLITE_MISUSE_BKPT;
    return;
  }
#endif
  db->u1.isInterrupted = 1;
  AtomicStore(&db->u1.isInterrupted, 1);
}

/*
** Return true or false depending on whether or not an interrupt is
** pending on connection db.
*/
int sqlite3_is_interrupted(sqlite3 *db){
#ifdef SQLITE_ENABLE_API_ARMOR
  if( !sqlite3SafetyCheckOk(db)
   && (db==0 || db->eOpenState!=SQLITE_STATE_ZOMBIE)
  ){
    (void)SQLITE_MISUSE_BKPT;
    return 0;
  }
#endif
  return AtomicLoad(&db->u1.isInterrupted)!=0;
}

/*
** This function is exactly the same as sqlite3_create_function(), except
** that it is designed to be called by internal code. The difference is
** that if a malloc() fails in sqlite3_create_function(), an error code
** is returned and the mallocFailed flag cleared. 
*/
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
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762




1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780

1781
1782
1783
1784
1785
1786
1787
1838
1839
1840
1841
1842
1843
1844

1845
1846
1847
1848
1849
1850
1851
1852
1853

1854
1855
1856
1857
1858
1859
1860

1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879














1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955







-









-
+





+
-
+
+

+
+
+
+
+
+









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




















+
+
+
+


















+







  void (*xStep)(sqlite3_context*,int,sqlite3_value **),
  void (*xFinal)(sqlite3_context*),
  void (*xValue)(sqlite3_context*),
  void (*xInverse)(sqlite3_context*,int,sqlite3_value **),
  FuncDestructor *pDestructor
){
  FuncDef *p;
  int nName;
  int extraFlags;

  assert( sqlite3_mutex_held(db->mutex) );
  assert( xValue==0 || xSFunc==0 );
  if( zFunctionName==0                /* Must have a valid name */
   || (xSFunc!=0 && xFinal!=0)        /* Not both xSFunc and xFinal */
   || ((xFinal==0)!=(xStep==0))       /* Both or neither of xFinal and xStep */
   || ((xValue==0)!=(xInverse==0))    /* Both or neither of xValue, xInverse */
   || (nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG)
   || (255<(nName = sqlite3Strlen30( zFunctionName)))
   || (255<sqlite3Strlen30(zFunctionName))
  ){
    return SQLITE_MISUSE_BKPT;
  }

  assert( SQLITE_FUNC_CONSTANT==SQLITE_DETERMINISTIC );
  assert( SQLITE_FUNC_DIRECT==SQLITE_DIRECTONLY );
  extraFlags = enc &  SQLITE_DETERMINISTIC;
  extraFlags = enc &  (SQLITE_DETERMINISTIC|SQLITE_DIRECTONLY|
                       SQLITE_SUBTYPE|SQLITE_INNOCUOUS);
  enc &= (SQLITE_FUNC_ENCMASK|SQLITE_ANY);

  /* The SQLITE_INNOCUOUS flag is the same bit as SQLITE_FUNC_UNSAFE.  But
  ** the meaning is inverted.  So flip the bit. */
  assert( SQLITE_FUNC_UNSAFE==SQLITE_INNOCUOUS );
  extraFlags ^= SQLITE_FUNC_UNSAFE;  /* tag-20230109-1 */

  
#ifndef SQLITE_OMIT_UTF16
  /* If SQLITE_UTF16 is specified as the encoding type, transform this
  ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the
  ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally.
  **
  ** If SQLITE_ANY is specified, add three versions of the function
  ** to the hash table.
  */
  switch( enc ){
  if( enc==SQLITE_UTF16 ){
    enc = SQLITE_UTF16NATIVE;
  }else if( enc==SQLITE_ANY ){
    int rc;
    rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF8|extraFlags,
         pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor);
    if( rc==SQLITE_OK ){
      rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE|extraFlags,
          pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor);
    }
    if( rc!=SQLITE_OK ){
      return rc;
    }
    enc = SQLITE_UTF16BE;
    case SQLITE_UTF16:
      enc = SQLITE_UTF16NATIVE;
      break;
    case SQLITE_ANY: {
      int rc;
      rc = sqlite3CreateFunc(db, zFunctionName, nArg,
           (SQLITE_UTF8|extraFlags)^SQLITE_FUNC_UNSAFE, /* tag-20230109-1 */
           pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor);
      if( rc==SQLITE_OK ){
        rc = sqlite3CreateFunc(db, zFunctionName, nArg,
             (SQLITE_UTF16LE|extraFlags)^SQLITE_FUNC_UNSAFE, /* tag-20230109-1*/
             pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor);
      }
      if( rc!=SQLITE_OK ){
        return rc;
      }
      enc = SQLITE_UTF16BE;
      break;
    }
    case SQLITE_UTF8:
    case SQLITE_UTF16LE:
    case SQLITE_UTF16BE:
      break;
    default:
      enc = SQLITE_UTF8;
      break;
  }
#else
  enc = SQLITE_UTF8;
#endif
  
  /* Check if an existing function is being overridden or deleted. If so,
  ** and there are active VMs, then return SQLITE_BUSY. If a function
  ** is being overridden/deleted but there are no active VMs, allow the
  ** operation to continue but invalidate all precompiled statements.
  */
  p = sqlite3FindFunction(db, zFunctionName, nArg, (u8)enc, 0);
  if( p && (p->funcFlags & SQLITE_FUNC_ENCMASK)==(u32)enc && p->nArg==nArg ){
    if( db->nVdbeActive ){
      sqlite3ErrorWithMsg(db, SQLITE_BUSY, 
        "unable to delete/modify user-function due to active statements");
      assert( !db->mallocFailed );
      return SQLITE_BUSY;
    }else{
      sqlite3ExpirePreparedStatements(db, 0);
    }
  }else if( xSFunc==0 && xFinal==0 ){
    /* Trying to delete a function that does not exist.  This is a no-op.
    ** https://sqlite.org/forum/forumpost/726219164b */
    return SQLITE_OK;
  }

  p = sqlite3FindFunction(db, zFunctionName, nArg, (u8)enc, 1);
  assert(p || db->mallocFailed);
  if( !p ){
    return SQLITE_NOMEM_BKPT;
  }

  /* If an older version of the function with a configured destructor is
  ** being replaced invoke the destructor function here. */
  functionDestroy(db, p);

  if( pDestructor ){
    pDestructor->nRef++;
  }
  p->u.pDestructor = pDestructor;
  p->funcFlags = (p->funcFlags & SQLITE_FUNC_ENCMASK) | extraFlags;
  testcase( p->funcFlags & SQLITE_DETERMINISTIC );
  testcase( p->funcFlags & SQLITE_DIRECTONLY );
  p->xSFunc = xSFunc ? xSFunc : xStep;
  p->xFinalize = xFinal;
  p->xValue = xValue;
  p->xInverse = xInverse;
  p->pUserData = pUserData;
  p->nArg = (u16)nArg;
  return SQLITE_OK;
1827
1828
1829
1830
1831
1832
1833
1834

1835
1836
1837
1838
1839
1840
1841
1995
1996
1997
1998
1999
2000
2001

2002
2003
2004
2005
2006
2007
2008
2009







-
+







    pArg->xDestroy = xDestroy;
    pArg->pUserData = p;
  }
  rc = sqlite3CreateFunc(db, zFunc, nArg, enc, p, 
      xSFunc, xStep, xFinal, xValue, xInverse, pArg
  );
  if( pArg && pArg->nRef==0 ){
    assert( rc!=SQLITE_OK );
    assert( rc!=SQLITE_OK || (xStep==0 && xFinal==0) );
    xDestroy(p);
    sqlite3_free(pArg);
  }

 out:
  rc = sqlite3ApiExit(db, rc);
  sqlite3_mutex_leave(db->mutex);
1964
1965
1966
1967
1968
1969
1970
1971

1972
1973
1974
1975
1976
1977
1978
2132
2133
2134
2135
2136
2137
2138

2139
2140
2141
2142
2143
2144
2145
2146







-
+







    return SQLITE_MISUSE_BKPT;
  }
#endif
  sqlite3_mutex_enter(db->mutex);
  rc = sqlite3FindFunction(db, zName, nArg, SQLITE_UTF8, 0)!=0;
  sqlite3_mutex_leave(db->mutex);
  if( rc ) return SQLITE_OK;
  zCopy = sqlite3_mprintf(zName);
  zCopy = sqlite3_mprintf("%s", zName);
  if( zCopy==0 ) return SQLITE_NOMEM;
  return sqlite3_create_function_v2(db, zName, nArg, SQLITE_UTF8,
                           zCopy, sqlite3InvalidFunction, 0, 0, sqlite3_free);
}

#ifndef SQLITE_OMIT_TRACE
/*
1992
1993
1994
1995
1996
1997
1998
1999

2000
2001
2002
2003
2004
2005
2006
2160
2161
2162
2163
2164
2165
2166

2167
2168
2169
2170
2171
2172
2173
2174







-
+







    (void)SQLITE_MISUSE_BKPT;
    return 0;
  }
#endif
  sqlite3_mutex_enter(db->mutex);
  pOld = db->pTraceArg;
  db->mTrace = xTrace ? SQLITE_TRACE_LEGACY : 0;
  db->xTrace = (int(*)(u32,void*,void*,void*))xTrace;
  db->trace.xLegacy = xTrace;
  db->pTraceArg = pArg;
  sqlite3_mutex_leave(db->mutex);
  return pOld;
}
#endif /* SQLITE_OMIT_DEPRECATED */

/* Register a trace callback using the version-2 interface.
2016
2017
2018
2019
2020
2021
2022
2023

2024
2025
2026
2027
2028
2029
2030
2184
2185
2186
2187
2188
2189
2190

2191
2192
2193
2194
2195
2196
2197
2198







-
+







    return SQLITE_MISUSE_BKPT;
  }
#endif
  sqlite3_mutex_enter(db->mutex);
  if( mTrace==0 ) xTrace = 0;
  if( xTrace==0 ) mTrace = 0;
  db->mTrace = mTrace;
  db->xTrace = xTrace;
  db->trace.xV2 = xTrace;
  db->pTraceArg = pArg;
  sqlite3_mutex_leave(db->mutex);
  return SQLITE_OK;
}

#ifndef SQLITE_OMIT_DEPRECATED
/*
2152
2153
2154
2155
2156
2157
2158




























2159
2160
2161
2162
2163
2164
2165
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361







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







  pRet = db->pPreUpdateArg;
  db->xPreUpdateCallback = xCallback;
  db->pPreUpdateArg = pArg;
  sqlite3_mutex_leave(db->mutex);
  return pRet;
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */

/*
** Register a function to be invoked prior to each autovacuum that
** determines the number of pages to vacuum.
*/
int sqlite3_autovacuum_pages(
  sqlite3 *db,                 /* Attach the hook to this database */
  unsigned int (*xCallback)(void*,const char*,u32,u32,u32), 
  void *pArg,                  /* Argument to the function */
  void (*xDestructor)(void*)   /* Destructor for pArg */
){
#ifdef SQLITE_ENABLE_API_ARMOR
  if( !sqlite3SafetyCheckOk(db) ){
    if( xDestructor ) xDestructor(pArg);
    return SQLITE_MISUSE_BKPT;
  }
#endif
  sqlite3_mutex_enter(db->mutex);
  if( db->xAutovacDestr ){
    db->xAutovacDestr(db->pAutovacPagesArg);
  }
  db->xAutovacPages = xCallback;
  db->pAutovacPagesArg = pArg;
  db->xAutovacDestr = xDestructor;
  sqlite3_mutex_leave(db->mutex);
  return SQLITE_OK;
}


#ifndef SQLITE_OMIT_WAL
/*
** The sqlite3_wal_hook() callback registered by sqlite3_wal_autocheckpoint().
** Invoke sqlite3_wal_checkpoint if the number of frames in the log file
** is greater than sqlite3.pWalArg cast to an integer (the value configured by
** wal_autocheckpoint()).
2245
2246
2247
2248
2249
2250
2251
2252

2253
2254
2255
2256
2257
2258
2259
2441
2442
2443
2444
2445
2446
2447

2448
2449
2450
2451
2452
2453
2454
2455







-
+







  int *pnLog,                     /* OUT: Size of WAL log in frames */
  int *pnCkpt                     /* OUT: Total number of frames checkpointed */
){
#ifdef SQLITE_OMIT_WAL
  return SQLITE_OK;
#else
  int rc;                         /* Return code */
  int iDb = SQLITE_MAX_ATTACHED;  /* sqlite3.aDb[] index of db to checkpoint */
  int iDb;                        /* Schema to checkpoint */

#ifdef SQLITE_ENABLE_API_ARMOR
  if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
#endif

  /* Initialize the output variables to -1 in case an error occurs. */
  if( pnLog ) *pnLog = -1;
2268
2269
2270
2271
2272
2273
2274


2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289

2290
2291
2292
2293
2294
2295
2296
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
2493
2494







+
+














-
+







    ** mode: */
    return SQLITE_MISUSE;
  }

  sqlite3_mutex_enter(db->mutex);
  if( zDb && zDb[0] ){
    iDb = sqlite3FindDbName(db, zDb);
  }else{
    iDb = SQLITE_MAX_DB;   /* This means process all schemas */
  }
  if( iDb<0 ){
    rc = SQLITE_ERROR;
    sqlite3ErrorWithMsg(db, SQLITE_ERROR, "unknown database: %s", zDb);
  }else{
    db->busyHandler.nBusy = 0;
    rc = sqlite3Checkpoint(db, iDb, eMode, pnLog, pnCkpt);
    sqlite3Error(db, rc);
  }
  rc = sqlite3ApiExit(db, rc);

  /* If there are no active statements, clear the interrupt flag at this
  ** point.  */
  if( db->nVdbeActive==0 ){
    db->u1.isInterrupted = 0;
    AtomicStore(&db->u1.isInterrupted, 0);
  }

  sqlite3_mutex_leave(db->mutex);
  return rc;
#endif
}

2316
2317
2318
2319
2320
2321
2322
2323

2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337


2338
2339
2340

2341
2342
2343
2344
2345
2346
2347
2514
2515
2516
2517
2518
2519
2520

2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539

2540
2541
2542
2543
2544
2545
2546
2547







-
+














+
+


-
+







** an error occurs while running the checkpoint, an SQLite error code is 
** returned (i.e. SQLITE_IOERR). Otherwise, SQLITE_OK.
**
** The mutex on database handle db should be held by the caller. The mutex
** associated with the specific b-tree being checkpointed is taken by
** this function while the checkpoint is running.
**
** If iDb is passed SQLITE_MAX_ATTACHED, then all attached databases are
** If iDb is passed SQLITE_MAX_DB then all attached databases are
** checkpointed. If an error is encountered it is returned immediately -
** no attempt is made to checkpoint any remaining databases.
**
** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL, RESTART
** or TRUNCATE.
*/
int sqlite3Checkpoint(sqlite3 *db, int iDb, int eMode, int *pnLog, int *pnCkpt){
  int rc = SQLITE_OK;             /* Return code */
  int i;                          /* Used to iterate through attached dbs */
  int bBusy = 0;                  /* True if SQLITE_BUSY has been encountered */

  assert( sqlite3_mutex_held(db->mutex) );
  assert( !pnLog || *pnLog==-1 );
  assert( !pnCkpt || *pnCkpt==-1 );
  testcase( iDb==SQLITE_MAX_ATTACHED ); /* See forum post a006d86f72 */
  testcase( iDb==SQLITE_MAX_DB );

  for(i=0; i<db->nDb && rc==SQLITE_OK; i++){
    if( i==iDb || iDb==SQLITE_MAX_ATTACHED ){
    if( i==iDb || iDb==SQLITE_MAX_DB ){
      rc = sqlite3BtreeCheckpoint(db->aDb[i].pBt, eMode, pnLog, pnCkpt);
      pnLog = 0;
      pnCkpt = 0;
      if( rc==SQLITE_BUSY ){
        bBusy = 1;
        rc = SQLITE_OK;
      }
2410
2411
2412
2413
2414
2415
2416













2417
2418
2419
2420
2421
2422
2423
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636







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







    if( z==0 ){
      z = sqlite3ErrStr(db->errCode);
    }
  }
  sqlite3_mutex_leave(db->mutex);
  return z;
}

/*
** Return the byte offset of the most recent error
*/
int sqlite3_error_offset(sqlite3 *db){
  int iOffset = -1;
  if( db && sqlite3SafetyCheckSickOrOk(db) && db->errCode ){
    sqlite3_mutex_enter(db->mutex);
    iOffset = db->errByteOffset;
    sqlite3_mutex_leave(db->mutex);
  }
  return iOffset;
}

#ifndef SQLITE_OMIT_UTF16
/*
** Return UTF-16 encoded English language explanation of the most recent
** error.
*/
const void *sqlite3_errmsg16(sqlite3 *db){
2671
2672
2673
2674
2675
2676
2677


2678
2679
2680
2681
2682
2683
2684
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899







+
+







  if( limitId<0 || limitId>=SQLITE_N_LIMIT ){
    return -1;
  }
  oldLimit = db->aLimit[limitId];
  if( newLimit>=0 ){                   /* IMP: R-52476-28732 */
    if( newLimit>aHardLimit[limitId] ){
      newLimit = aHardLimit[limitId];  /* IMP: R-51463-25634 */
    }else if( newLimit<1 && limitId==SQLITE_LIMIT_LENGTH ){
      newLimit = 1;
    }
    db->aLimit[limitId] = newLimit;
  }
  return oldLimit;                     /* IMP: R-53341-35419 */
}

/*
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701





2702
2703
2704
2705
2706
2707
2708
2907
2908
2909
2910
2911
2912
2913



2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925







-
-
-
+
+
+
+
+







** itself. When this function is called the *pFlags variable should contain
** the default flags to open the database handle with. The value stored in
** *pFlags may be updated before returning if the URI filename contains 
** "cache=xxx" or "mode=xxx" query parameters.
**
** If successful, SQLITE_OK is returned. In this case *ppVfs is set to point to
** the VFS that should be used to open the database file. *pzFile is set to
** point to a buffer containing the name of the file to open. It is the 
** responsibility of the caller to eventually call sqlite3_free() to release
** this buffer.
** point to a buffer containing the name of the file to open.  The value
** stored in *pzFile is a database name acceptable to sqlite3_uri_parameter()
** and is in the same format as names created using sqlite3_create_filename().
** The caller must invoke sqlite3_free_filename() (not sqlite3_free()!) on
** the value returned in *pzFile to avoid a memory leak.
**
** If an error occurs, then an SQLite error code is returned and *pzErrMsg
** may be set to point to a buffer containing an English language error 
** message. It is the responsibility of the caller to eventually release
** this buffer by calling sqlite3_free().
*/
int sqlite3ParseUri(
2726
2727
2728
2729
2730
2731
2732
2733

2734
2735
2736
2737
2738
2739
2740
2741



2742
2743
2744
2745
2746
2747
2748
2943
2944
2945
2946
2947
2948
2949

2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968







-
+








+
+
+







            || sqlite3GlobalConfig.bOpenUri) /* IMP: R-51689-46548 */
   && nUri>=5 && memcmp(zUri, "file:", 5)==0 /* IMP: R-57884-37496 */
  ){
    char *zOpt;
    int eState;                   /* Parser state when parsing URI */
    int iIn;                      /* Input character index */
    int iOut = 0;                 /* Output character index */
    u64 nByte = nUri+2;           /* Bytes of space to allocate */
    u64 nByte = nUri+8;           /* Bytes of space to allocate */

    /* Make sure the SQLITE_OPEN_URI flag is set to indicate to the VFS xOpen 
    ** method that there may be extra parameters following the file-name.  */
    flags |= SQLITE_OPEN_URI;

    for(iIn=0; iIn<nUri; iIn++) nByte += (zUri[iIn]=='&');
    zFile = sqlite3_malloc64(nByte);
    if( !zFile ) return SQLITE_NOMEM_BKPT;

    memset(zFile, 0, 4);  /* 4-byte of 0x00 is the start of DB name marker */
    zFile += 4;

    iIn = 5;
#ifdef SQLITE_ALLOW_URI_AUTHORITY
    if( strncmp(zUri+5, "///", 3)==0 ){
      iIn = 7;
      /* The following condition causes URIs with five leading / characters
      ** like file://///host/path to be converted into UNCs like //host/path.
2825
2826
2827
2828
2829
2830
2831
2832

2833
2834
2835
2836
2837
2838
2839
2840
3045
3046
3047
3048
3049
3050
3051

3052

3053
3054
3055
3056
3057
3058
3059







-
+
-







      }else if( (eState==0 && c=='?') || (eState==2 && c=='&') ){
        c = 0;
        eState = 1;
      }
      zFile[iOut++] = c;
    }
    if( eState==1 ) zFile[iOut++] = '\0';
    zFile[iOut++] = '\0';
    memset(zFile+iOut, 0, 4); /* end-of-options + empty journal filenames */
    zFile[iOut++] = '\0';

    /* Check if there were any options specified that should be interpreted 
    ** here. Options that are interpreted here include "vfs" and those that
    ** correspond to flags that may be passed to the sqlite3_open_v2()
    ** method. */
    zOpt = &zFile[sqlite3Strlen30(zFile)+1];
    while( zOpt[0] ){
2906
2907
2908
2909
2910
2911
2912
2913

2914


2915
2916
2917
2918

2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930

2931
2932
2933
2934
2935
2936
















2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954

2955
2956
2957
2958
2959
2960
2961
3125
3126
3127
3128
3129
3130
3131

3132
3133
3134
3135
3136
3137
3138

3139

3140
3141
3142
3143
3144
3145
3146
3147
3148
3149

3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198







-
+

+
+



-
+
-










-
+






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


















+







        }
      }

      zOpt = &zVal[nVal+1];
    }

  }else{
    zFile = sqlite3_malloc64(nUri+2);
    zFile = sqlite3_malloc64(nUri+8);
    if( !zFile ) return SQLITE_NOMEM_BKPT;
    memset(zFile, 0, 4);
    zFile += 4;
    if( nUri ){
      memcpy(zFile, zUri, nUri);
    }
    zFile[nUri] = '\0';
    memset(zFile+nUri, 0, 4);
    zFile[nUri+1] = '\0';
    flags &= ~SQLITE_OPEN_URI;
  }

  *ppVfs = sqlite3_vfs_find(zVfs);
  if( *ppVfs==0 ){
    *pzErrMsg = sqlite3_mprintf("no such vfs: %s", zVfs);
    rc = SQLITE_ERROR;
  }
 parse_uri_out:
  if( rc!=SQLITE_OK ){
    sqlite3_free(zFile);
    sqlite3_free_filename(zFile);
    zFile = 0;
  }
  *pFlags = flags;
  *pzFile = zFile;
  return rc;
}

/*
** This routine does the core work of extracting URI parameters from a
** database filename for the sqlite3_uri_parameter() interface.
*/
static const char *uriParameter(const char *zFilename, const char *zParam){
  zFilename += sqlite3Strlen30(zFilename) + 1;
  while( ALWAYS(zFilename!=0) && zFilename[0] ){
    int x = strcmp(zFilename, zParam);
    zFilename += sqlite3Strlen30(zFilename) + 1;
    if( x==0 ) return zFilename;
    zFilename += sqlite3Strlen30(zFilename) + 1;
  }
  return 0;
}



/*
** This routine does the work of opening a database on behalf of
** sqlite3_open() and sqlite3_open16(). The database filename "zFilename"  
** is UTF-8 encoded.
*/
static int openDatabase(
  const char *zFilename, /* Database filename UTF-8 encoded */
  sqlite3 **ppDb,        /* OUT: Returned database handle */
  unsigned int flags,    /* Operational flags */
  const char *zVfs       /* Name of the VFS to use */
){
  sqlite3 *db;                    /* Store allocated handle here */
  int rc;                         /* Return code */
  int isThreadsafe;               /* True for threadsafe connections */
  char *zOpen = 0;                /* Filename argument to pass to BtreeOpen() */
  char *zErrMsg = 0;              /* Error message from sqlite3ParseUri() */
  int i;                          /* Loop counter */

#ifdef SQLITE_ENABLE_API_ARMOR
  if( ppDb==0 ) return SQLITE_MISUSE_BKPT;
#endif
  *ppDb = 0;
#ifndef SQLITE_OMIT_AUTOINIT
  rc = sqlite3_initialize();
2980
2981
2982
2983
2984
2985
2986
2987
2988


2989
2990
2991
2992
2993
2994
2995
2996
2997
2998

2999
3000
3001
3002
3003
3004
3005
3217
3218
3219
3220
3221
3222
3223


3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234

3235
3236
3237
3238
3239
3240
3241
3242







-
-
+
+









-
+








  /* Remove harmful bits from the flags parameter
  **
  ** The SQLITE_OPEN_NOMUTEX and SQLITE_OPEN_FULLMUTEX flags were
  ** dealt with in the previous code block.  Besides these, the only
  ** valid input flags for sqlite3_open_v2() are SQLITE_OPEN_READONLY,
  ** SQLITE_OPEN_READWRITE, SQLITE_OPEN_CREATE, SQLITE_OPEN_SHAREDCACHE,
  ** SQLITE_OPEN_PRIVATECACHE, and some reserved bits.  Silently mask
  ** off all other flags.
  ** SQLITE_OPEN_PRIVATECACHE, SQLITE_OPEN_EXRESCODE, and some reserved
  ** bits.  Silently mask off all other flags.
  */
  flags &=  ~( SQLITE_OPEN_DELETEONCLOSE |
               SQLITE_OPEN_EXCLUSIVE |
               SQLITE_OPEN_MAIN_DB |
               SQLITE_OPEN_TEMP_DB | 
               SQLITE_OPEN_TRANSIENT_DB | 
               SQLITE_OPEN_MAIN_JOURNAL | 
               SQLITE_OPEN_TEMP_JOURNAL | 
               SQLITE_OPEN_SUBJOURNAL | 
               SQLITE_OPEN_MASTER_JOURNAL |
               SQLITE_OPEN_SUPER_JOURNAL |
               SQLITE_OPEN_NOMUTEX |
               SQLITE_OPEN_FULLMUTEX |
               SQLITE_OPEN_WAL
             );

  /* Allocate the sqlite data structure */
  db = sqlite3MallocZero( sizeof(sqlite3) );
3016
3017
3018
3019
3020
3021
3022
3023

3024
3025

3026
3027

3028
3029
3030
3031
3032
3033
3034
3035







3036

3037
































3038
3039
3040
3041
3042
3043
3044
3253
3254
3255
3256
3257
3258
3259

3260
3261

3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282

3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321







-
+

-
+


+








+
+
+
+
+
+
+

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







      goto opendb_out;
    }
    if( isThreadsafe==0 ){
      sqlite3MutexWarnOnContention(db->mutex);
    }
  }
  sqlite3_mutex_enter(db->mutex);
  db->errMask = 0xff;
  db->errMask = (flags & SQLITE_OPEN_EXRESCODE)!=0 ? 0xffffffff : 0xff;
  db->nDb = 2;
  db->magic = SQLITE_MAGIC_BUSY;
  db->eOpenState = SQLITE_STATE_BUSY;
  db->aDb = db->aDbStatic;
  db->lookaside.bDisable = 1;
  db->lookaside.sz = 0;
  sqlite3FastPrngInit(&db->sPrng);
  assert( sizeof(db->aLimit)==sizeof(aHardLimit) );
  memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit));
  db->aLimit[SQLITE_LIMIT_WORKER_THREADS] = SQLITE_DEFAULT_WORKER_THREADS;
  db->autoCommit = 1;
  db->nextAutovac = -1;
  db->szMmap = sqlite3GlobalConfig.szMmap;
  db->nextPagesize = 0;
  db->init.azInit = sqlite3StdType; /* Any array of string ptrs will do */
#ifdef SQLITE_ENABLE_SORTER_MMAP
  /* Beginning with version 3.37.0, using the VFS xFetch() API to memory-map 
  ** the temporary files used to do external sorts (see code in vdbesort.c)
  ** is disabled. It can still be used either by defining
  ** SQLITE_ENABLE_SORTER_MMAP at compile time or by using the
  ** SQLITE_TESTCTRL_SORTER_MMAP test-control at runtime. */
  db->nMaxSorterMmap = 0x7FFFFFFF;
#endif
  db->flags |= SQLITE_ShortColNames | SQLITE_EnableTrigger | SQLITE_CacheSpill
  db->flags |= SQLITE_ShortColNames
                 | SQLITE_EnableTrigger
                 | SQLITE_EnableView
                 | SQLITE_CacheSpill
#if !defined(SQLITE_TRUSTED_SCHEMA) || SQLITE_TRUSTED_SCHEMA+0!=0
                 | SQLITE_TrustedSchema
#endif
/* The SQLITE_DQS compile-time option determines the default settings
** for SQLITE_DBCONFIG_DQS_DDL and SQLITE_DBCONFIG_DQS_DML.
**
**    SQLITE_DQS     SQLITE_DBCONFIG_DQS_DDL    SQLITE_DBCONFIG_DQS_DML
**    ----------     -----------------------    -----------------------
**     undefined               on                          on   
**         3                   on                          on
**         2                   on                         off
**         1                  off                          on
**         0                  off                         off
**
** Legacy behavior is 3 (double-quoted string literals are allowed anywhere)
** and so that is the default.  But developers are encouranged to use
** -DSQLITE_DQS=0 (best) or -DSQLITE_DQS=1 (second choice) if possible.
*/
#if !defined(SQLITE_DQS)
# define SQLITE_DQS 3
#endif
#if (SQLITE_DQS&1)==1
                 | SQLITE_DqsDML
#endif
#if (SQLITE_DQS&2)==2
                 | SQLITE_DqsDDL
#endif

#if !defined(SQLITE_DEFAULT_AUTOMATIC_INDEX) || SQLITE_DEFAULT_AUTOMATIC_INDEX
                 | SQLITE_AutoIndex
#endif
#if SQLITE_DEFAULT_CKPTFULLFSYNC
                 | SQLITE_CkptFullFSync
#endif
#if SQLITE_DEFAULT_FILE_FORMAT<4
3064
3065
3066
3067
3068
3069
3070



3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088

3089
3090
3091
3092
3093







3094
3095



3096



3097
3098
3099
3100
3101
3102
3103
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367

3368
3369
3370
3371


3372
3373
3374
3375
3376
3377
3378


3379
3380
3381

3382
3383
3384
3385
3386
3387
3388
3389
3390
3391







+
+
+

















-
+



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







#endif
#if defined(SQLITE_ENABLE_QPSG)
                 | SQLITE_EnableQPSG
#endif
#if defined(SQLITE_DEFAULT_DEFENSIVE)
                 | SQLITE_Defensive
#endif
#if defined(SQLITE_DEFAULT_LEGACY_ALTER_TABLE)
                 | SQLITE_LegacyAlter
#endif
      ;
  sqlite3HashInit(&db->aCollSeq);
#ifndef SQLITE_OMIT_VIRTUALTABLE
  sqlite3HashInit(&db->aModule);
#endif

  /* Add the default collation sequence BINARY. BINARY works for both UTF-8
  ** and UTF-16, so add a version for each to avoid any unnecessary
  ** conversions. The only error that can occur here is a malloc() failure.
  **
  ** EVIDENCE-OF: R-52786-44878 SQLite defines three built-in collating
  ** functions:
  */
  createCollation(db, sqlite3StrBINARY, SQLITE_UTF8, 0, binCollFunc, 0);
  createCollation(db, sqlite3StrBINARY, SQLITE_UTF16BE, 0, binCollFunc, 0);
  createCollation(db, sqlite3StrBINARY, SQLITE_UTF16LE, 0, binCollFunc, 0);
  createCollation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc, 0);
  createCollation(db, "RTRIM", SQLITE_UTF8, (void*)1, binCollFunc, 0);
  createCollation(db, "RTRIM", SQLITE_UTF8, 0, rtrimCollFunc, 0);
  if( db->mallocFailed ){
    goto opendb_out;
  }
  /* EVIDENCE-OF: R-08308-17224 The default collating function for all
  ** strings is BINARY. 

#if SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL)
  /* Process magic filenames ":localStorage:" and ":sessionStorage:" */
  if( zFilename && zFilename[0]==':' ){
    if( strcmp(zFilename, ":localStorage:")==0 ){
      zFilename = "file:local?vfs=kvvfs";
      flags |= SQLITE_OPEN_URI;
  */
  db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, sqlite3StrBINARY, 0);
    }else if( strcmp(zFilename, ":sessionStorage:")==0 ){
      zFilename = "file:session?vfs=kvvfs";
      flags |= SQLITE_OPEN_URI;
  assert( db->pDfltColl!=0 );
    }
  }
#endif /* SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL) */

  /* Parse the filename/URI argument
  **
  ** Only allow sensible combinations of bits in the flags argument.  
  ** Throw an error if any non-sense combination is used.  If we
  ** do not block illegal combinations here, it could trigger
  ** assert() statements in deeper layers.  Sensible combinations
3111
3112
3113
3114
3115
3116
3117
3118

3119
3120
3121
3122
3123
3124
3125
3126
3127






3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141



3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153

3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166

3167
3168

3169
3170
3171


3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186

3187
3188
3189
3190
3191
3192

3193
3194
3195
3196
3197
3198
3199

3200
3201
3202
3203
3204
3205

3206
3207
3208
3209
3210
3211

3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3399
3400
3401
3402
3403
3404
3405

3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434

3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448

3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461

3462


3463



3464
3465
3466

3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478

3479






3480







3481






3482






3483




























3484
3485
3486
3487
3488
3489
3490







-
+









+
+
+
+
+
+













-
+
+
+











-
+












-
+
-
-
+
-
-
-
+
+

-












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







  assert( SQLITE_OPEN_READONLY  == 0x01 );
  assert( SQLITE_OPEN_READWRITE == 0x02 );
  assert( SQLITE_OPEN_CREATE    == 0x04 );
  testcase( (1<<(flags&7))==0x02 ); /* READONLY */
  testcase( (1<<(flags&7))==0x04 ); /* READWRITE */
  testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */
  if( ((1<<(flags&7)) & 0x46)==0 ){
    rc = SQLITE_MISUSE_BKPT;  /* IMP: R-65497-44594 */
    rc = SQLITE_MISUSE_BKPT;  /* IMP: R-18321-05872 */
  }else{
    rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg);
  }
  if( rc!=SQLITE_OK ){
    if( rc==SQLITE_NOMEM ) sqlite3OomFault(db);
    sqlite3ErrorWithMsg(db, rc, zErrMsg ? "%s" : 0, zErrMsg);
    sqlite3_free(zErrMsg);
    goto opendb_out;
  }
  assert( db->pVfs!=0 );
#if SQLITE_OS_KV || defined(SQLITE_OS_KV_OPTIONAL)
  if( sqlite3_stricmp(db->pVfs->zName, "kvvfs")==0 ){
    db->temp_store = 2;
  }
#endif

  /* Open the backend database driver */
  rc = sqlite3BtreeOpen(db->pVfs, zOpen, db, &db->aDb[0].pBt, 0,
                        flags | SQLITE_OPEN_MAIN_DB);
  if( rc!=SQLITE_OK ){
    if( rc==SQLITE_IOERR_NOMEM ){
      rc = SQLITE_NOMEM_BKPT;
    }
    sqlite3Error(db, rc);
    goto opendb_out;
  }
  sqlite3BtreeEnter(db->aDb[0].pBt);
  db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt);
  if( !db->mallocFailed ) ENC(db) = SCHEMA_ENC(db);
  if( !db->mallocFailed ){
    sqlite3SetTextEncoding(db, SCHEMA_ENC(db));
  }
  sqlite3BtreeLeave(db->aDb[0].pBt);
  db->aDb[1].pSchema = sqlite3SchemaGet(db, 0);

  /* The default safety_level for the main database is FULL; for the temp
  ** database it is OFF. This matches the pager layer defaults.  
  */
  db->aDb[0].zDbSName = "main";
  db->aDb[0].safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1;
  db->aDb[1].zDbSName = "temp";
  db->aDb[1].safety_level = PAGER_SYNCHRONOUS_OFF;

  db->magic = SQLITE_MAGIC_OPEN;
  db->eOpenState = SQLITE_STATE_OPEN;
  if( db->mallocFailed ){
    goto opendb_out;
  }

  /* Register all built-in functions, but do not attempt to read the
  ** database schema yet. This is delayed until the first time the database
  ** is accessed.
  */
  sqlite3Error(db, SQLITE_OK);
  sqlite3RegisterPerConnectionBuiltinFunctions(db);
  rc = sqlite3_errcode(db);

#ifdef SQLITE_ENABLE_FTS5

  /* Register any built-in FTS5 module before loading the automatic
  ** extensions. This allows automatic extensions to register FTS5 
  /* Load compiled-in extensions */
  ** tokenizers and auxiliary functions.  */
  if( !db->mallocFailed && rc==SQLITE_OK ){
    rc = sqlite3Fts5Init(db);
  for(i=0; rc==SQLITE_OK && i<ArraySize(sqlite3BuiltinExtensions); i++){
    rc = sqlite3BuiltinExtensions[i](db);
  }
#endif

  /* Load automatic extensions - extensions that have been registered
  ** using the sqlite3_automatic_extension() API.
  */
  if( rc==SQLITE_OK ){
    sqlite3AutoLoadExtensions(db);
    rc = sqlite3_errcode(db);
    if( rc!=SQLITE_OK ){
      goto opendb_out;
    }
  }

#ifdef SQLITE_ENABLE_FTS1
#ifdef SQLITE_ENABLE_INTERNAL_FUNCTIONS
  if( !db->mallocFailed ){
    extern int sqlite3Fts1Init(sqlite3*);
    rc = sqlite3Fts1Init(db);
  }
#endif

  /* Testing use only!!! The -DSQLITE_ENABLE_INTERNAL_FUNCTIONS=1 compile-time
#ifdef SQLITE_ENABLE_FTS2
  if( !db->mallocFailed && rc==SQLITE_OK ){
    extern int sqlite3Fts2Init(sqlite3*);
    rc = sqlite3Fts2Init(db);
  }
#endif

  ** option gives access to internal functions by default.  
#ifdef SQLITE_ENABLE_FTS3 /* automatically defined by SQLITE_ENABLE_FTS4 */
  if( !db->mallocFailed && rc==SQLITE_OK ){
    rc = sqlite3Fts3Init(db);
  }
#endif

  ** Testing use only!!! */
#if defined(SQLITE_ENABLE_ICU) || defined(SQLITE_ENABLE_ICU_COLLATIONS)
  if( !db->mallocFailed && rc==SQLITE_OK ){
    rc = sqlite3IcuInit(db);
  }
#endif

  db->mDbFlags |= DBFLAG_InternalFunc;
#ifdef SQLITE_ENABLE_RTREE
  if( !db->mallocFailed && rc==SQLITE_OK){
    rc = sqlite3RtreeInit(db);
  }
#endif

#ifdef SQLITE_ENABLE_DBPAGE_VTAB
  if( !db->mallocFailed && rc==SQLITE_OK){
    rc = sqlite3DbpageRegister(db);
  }
#endif

#ifdef SQLITE_ENABLE_DBSTAT_VTAB
  if( !db->mallocFailed && rc==SQLITE_OK){
    rc = sqlite3DbstatRegister(db);
  }
#endif

#ifdef SQLITE_ENABLE_JSON1
  if( !db->mallocFailed && rc==SQLITE_OK){
    rc = sqlite3Json1Init(db);
  }
#endif

#ifdef SQLITE_ENABLE_STMTVTAB
  if( !db->mallocFailed && rc==SQLITE_OK){
    rc = sqlite3StmtVtabInit(db);
  }
#endif

  /* -DSQLITE_DEFAULT_LOCKING_MODE=1 makes EXCLUSIVE the default locking
  ** mode.  -DSQLITE_DEFAULT_LOCKING_MODE=0 make NORMAL the default locking
  ** mode.  Doing nothing at all also makes NORMAL the default.
  */
#ifdef SQLITE_DEFAULT_LOCKING_MODE
3260
3261
3262
3263
3264
3265
3266
3267
3268


3269
3270
3271
3272

3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300


3301

3302
3303
3304
3305
3306
3307
3308
3504
3505
3506
3507
3508
3509
3510


3511
3512
3513
3514
3515

3516
3517
3518
3519
3520
3521
3522
3523
3524
3525



















3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536







-
-
+
+



-
+









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

+







opendb_out:
  if( db ){
    assert( db->mutex!=0 || isThreadsafe==0
           || sqlite3GlobalConfig.bFullMutex==0 );
    sqlite3_mutex_leave(db->mutex);
  }
  rc = sqlite3_errcode(db);
  assert( db!=0 || rc==SQLITE_NOMEM );
  if( rc==SQLITE_NOMEM ){
  assert( db!=0 || (rc&0xff)==SQLITE_NOMEM );
  if( (rc&0xff)==SQLITE_NOMEM ){
    sqlite3_close(db);
    db = 0;
  }else if( rc!=SQLITE_OK ){
    db->magic = SQLITE_MAGIC_SICK;
    db->eOpenState = SQLITE_STATE_SICK;
  }
  *ppDb = db;
#ifdef SQLITE_ENABLE_SQLLOG
  if( sqlite3GlobalConfig.xSqllog ){
    /* Opening a db handle. Fourth parameter is passed 0. */
    void *pArg = sqlite3GlobalConfig.pSqllogArg;
    sqlite3GlobalConfig.xSqllog(pArg, db, zFilename, 0);
  }
#endif
#if defined(SQLITE_HAS_CODEC)
  if( rc==SQLITE_OK ){
    const char *zKey;
    if( (zKey = sqlite3_uri_parameter(zOpen, "hexkey"))!=0 && zKey[0] ){
      u8 iByte;
      int i;
      char zDecoded[40];
      for(i=0, iByte=0; i<sizeof(zDecoded)*2 && sqlite3Isxdigit(zKey[i]); i++){
        iByte = (iByte<<4) + sqlite3HexToInt(zKey[i]);
        if( (i&1)!=0 ) zDecoded[i/2] = iByte;
      }
      sqlite3_key_v2(db, 0, zDecoded, i/2);
    }else if( (zKey = sqlite3_uri_parameter(zOpen, "key"))!=0 ){
      sqlite3_key_v2(db, 0, zKey, sqlite3Strlen30(zKey));
    }
  }
#endif
  sqlite3_free(zOpen);
  return rc & 0xff;
  sqlite3_free_filename(zOpen);
  return rc;
}


/*
** Open a new database handle.
*/
int sqlite3_open(
  const char *zFilename, 
  sqlite3 **ppDb 
3518
3519
3520
3521
3522
3523
3524
3525

3526
3527
3528
3529
3530
3531


3532
3533
3534
3535
3536
3537
3538
3746
3747
3748
3749
3750
3751
3752

3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768







-
+






+
+







  testcase( sqlite3GlobalConfig.xLog!=0 );
  return sqlite3ReportError(SQLITE_MISUSE, lineno, "misuse");
}
int sqlite3CantopenError(int lineno){
  testcase( sqlite3GlobalConfig.xLog!=0 );
  return sqlite3ReportError(SQLITE_CANTOPEN, lineno, "cannot open file");
}
#ifdef SQLITE_DEBUG
#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_CORRUPT_PGNO)
int sqlite3CorruptPgnoError(int lineno, Pgno pgno){
  char zMsg[100];
  sqlite3_snprintf(sizeof(zMsg), zMsg, "database corruption page %d", pgno);
  testcase( sqlite3GlobalConfig.xLog!=0 );
  return sqlite3ReportError(SQLITE_CORRUPT, lineno, zMsg);
}
#endif
#ifdef SQLITE_DEBUG
int sqlite3NomemError(int lineno){
  testcase( sqlite3GlobalConfig.xLog!=0 );
  return sqlite3ReportError(SQLITE_NOMEM, lineno, "OOM");
}
int sqlite3IoerrnomemError(int lineno){
  testcase( sqlite3GlobalConfig.xLog!=0 );
  return sqlite3ReportError(SQLITE_IOERR_NOMEM, lineno, "I/O OOM error");
3590
3591
3592
3593
3594
3595
3596
3597

3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608

3609
3610
3611
3612
3613
3614
3615
3820
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







-
+










-
+







  rc = sqlite3Init(db, &zErrMsg);
  if( SQLITE_OK!=rc ){
    goto error_out;
  }

  /* Locate the table in question */
  pTab = sqlite3FindTable(db, zTableName, zDbName);
  if( !pTab || pTab->pSelect ){
  if( !pTab || IsView(pTab) ){
    pTab = 0;
    goto error_out;
  }

  /* Find the column for which info is requested */
  if( zColumnName==0 ){
    /* Query for existance of table only */
  }else{
    for(iCol=0; iCol<pTab->nCol; iCol++){
      pCol = &pTab->aCol[iCol];
      if( 0==sqlite3StrICmp(pCol->zName, zColumnName) ){
      if( 0==sqlite3StrICmp(pCol->zCnName, zColumnName) ){
        break;
      }
    }
    if( iCol==pTab->nCol ){
      if( HasRowid(pTab) && sqlite3IsRowid(zColumnName) ){
        iCol = pTab->iPKey;
        pCol = iCol>=0 ? &pTab->aCol[iCol] : 0;
3628
3629
3630
3631
3632
3633
3634
3635

3636
3637
3638
3639
3640
3641
3642
3858
3859
3860
3861
3862
3863
3864

3865
3866
3867
3868
3869
3870
3871
3872







-
+







  **        and there is no explicitly declared IPK column. 
  **
  **     2. The table is not a view and the column name identified an 
  **        explicitly declared column. Copy meta information from *pCol.
  */ 
  if( pCol ){
    zDataType = sqlite3ColumnType(pCol,0);
    zCollSeq = pCol->zColl;
    zCollSeq = sqlite3ColumnColl(pCol);
    notnull = pCol->notNull!=0;
    primarykey  = (pCol->colFlags & COLFLAG_PRIMKEY)!=0;
    autoinc = pTab->iPKey==iCol && (pTab->tabFlags & TF_Autoincrement)!=0;
  }else{
    zDataType = "INTEGER";
    primarykey = 1;
  }
3727
3728
3729
3730
3731
3732
3733










3734

3735

3736
3737
3738
3739
3740
3741
3742
3957
3958
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







+
+
+
+
+
+
+
+
+
+

+

+







      rc = SQLITE_OK;
    }else if( op==SQLITE_FCNTL_JOURNAL_POINTER ){
      *(sqlite3_file**)pArg = sqlite3PagerJrnlFile(pPager);
      rc = SQLITE_OK;
    }else if( op==SQLITE_FCNTL_DATA_VERSION ){
      *(unsigned int*)pArg = sqlite3PagerDataVersion(pPager);
      rc = SQLITE_OK;
    }else if( op==SQLITE_FCNTL_RESERVE_BYTES ){
      int iNew = *(int*)pArg;
      *(int*)pArg = sqlite3BtreeGetRequestedReserve(pBtree);
      if( iNew>=0 && iNew<=255 ){
        sqlite3BtreeSetPageSize(pBtree, 0, iNew, 0);
      }
      rc = SQLITE_OK;
    }else if( op==SQLITE_FCNTL_RESET_CACHE ){
      sqlite3BtreeClearCache(pBtree);
      rc = SQLITE_OK;
    }else{
      int nSave = db->busyHandler.nBusy;
      rc = sqlite3OsFileControl(fd, op, pArg);
      db->busyHandler.nBusy = nSave;
    }
    sqlite3BtreeLeave(pBtree);
  }
  sqlite3_mutex_leave(db->mutex);
  return rc;
}

3766
3767
3768
3769
3770
3771
3772

3773
3774
3775
3776


















3777

3778







3779
3780
3781

3782
3783
3784
3785
3786
3787
3788
4008
4009
4010
4011
4012
4013
4014
4015




4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035

4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053







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

+
-
+
+
+
+
+
+
+



+







    ** this verb acts like PRNG_RESET.
    */
    case SQLITE_TESTCTRL_PRNG_RESTORE: {
      sqlite3PrngRestoreState();
      break;
    }

    /*  sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SEED, int x, sqlite3 *db);
    /*
    ** Reset the PRNG back to its uninitialized state.  The next call
    ** to sqlite3_randomness() will reseed the PRNG using a single call
    ** to the xRandomness method of the default VFS.
    **
    ** Control the seed for the pseudo-random number generator (PRNG) that
    ** is built into SQLite.  Cases:
    **
    **    x!=0 && db!=0       Seed the PRNG to the current value of the
    **                        schema cookie in the main database for db, or
    **                        x if the schema cookie is zero.  This case
    **                        is convenient to use with database fuzzers
    **                        as it allows the fuzzer some control over the
    **                        the PRNG seed.
    **
    **    x!=0 && db==0       Seed the PRNG to the value of x.
    **
    **    x==0 && db==0       Revert to default behavior of using the
    **                        xRandomness method on the primary VFS.
    **
    ** This test-control also resets the PRNG so that the new seed will
    ** be used for the next call to sqlite3_randomness().
    */
#ifndef SQLITE_OMIT_WSD
    case SQLITE_TESTCTRL_PRNG_RESET: {
    case SQLITE_TESTCTRL_PRNG_SEED: {
      int x = va_arg(ap, int);
      int y;
      sqlite3 *db = va_arg(ap, sqlite3*);
      assert( db==0 || db->aDb[0].pSchema!=0 );
      if( db && (y = db->aDb[0].pSchema->schema_cookie)!=0 ){ x = y; }
      sqlite3Config.iPrngSeed = x;
      sqlite3_randomness(0,0);
      break;
    }
#endif

    /*
    **  sqlite3_test_control(BITVEC_TEST, size, program)
    **
    ** Run a test against a Bitvec object of size.  The program argument
    ** is an array of integers that defines the test.  Return -1 on a
    ** memory allocation error, 0 on success, or non-zero for an error.
3803
3804
3805
3806
3807
3808
3809


3810
3811




3812
3813
3814
3815


3816
3817
3818
3819
3820
3821
3822
4068
4069
4070
4071
4072
4073
4074
4075
4076


4077
4078
4079
4080
4081
4082


4083
4084
4085
4086
4087
4088
4089
4090
4091







+
+
-
-
+
+
+
+


-
-
+
+







    **
    ** As a test of the fault simulator mechanism itself, sqlite3FaultSim(0)
    ** is called immediately after installing the new callback and the return
    ** value from sqlite3FaultSim(0) becomes the return from
    ** sqlite3_test_control().
    */
    case SQLITE_TESTCTRL_FAULT_INSTALL: {
      /* A bug in MSVC prevents it from understanding pointers to functions
      ** types in the second argument to va_arg().  Work around the problem
      /* MSVC is picky about pulling func ptrs from va lists.
      ** http://support.microsoft.com/kb/47961
      ** using a typedef.
      ** http://support.microsoft.com/kb/47961  <-- dead hyperlink
      ** Search at http://web.archive.org/ to find the 2015-03-16 archive
      ** of the link above to see the original text.
      ** sqlite3GlobalConfig.xTestCallback = va_arg(ap, int(*)(int));
      */
      typedef int(*TESTCALLBACKFUNC_t)(int);
      sqlite3GlobalConfig.xTestCallback = va_arg(ap, TESTCALLBACKFUNC_t);
      typedef int(*sqlite3FaultFuncType)(int);
      sqlite3GlobalConfig.xTestCallback = va_arg(ap, sqlite3FaultFuncType);
      rc = sqlite3FaultSim(0);
      break;
    }

    /*
    **  sqlite3_test_control(BENIGN_MALLOC_HOOKS, xBegin, xEnd)
    **
3867
3868
3869
3870
3871
3872
3873






















3874
3875
3876
3877
3878
3879
3880
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171







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







    ** process aborts.  If X is false and assert() is disabled, then the
    ** return value is zero.
    */
    case SQLITE_TESTCTRL_ASSERT: {
      volatile int x = 0;
      assert( /*side-effects-ok*/ (x = va_arg(ap,int))!=0 );
      rc = x;
#if defined(SQLITE_DEBUG)
      /* Invoke these debugging routines so that the compiler does not
      ** issue "defined but not used" warnings. */
      if( x==9999 ){
        sqlite3ShowExpr(0);
        sqlite3ShowExpr(0);
        sqlite3ShowExprList(0);
        sqlite3ShowIdList(0);
        sqlite3ShowSrcList(0);
        sqlite3ShowWith(0);
        sqlite3ShowUpsert(0);
        sqlite3ShowTriggerStep(0);
        sqlite3ShowTriggerStepList(0);
        sqlite3ShowTrigger(0);
        sqlite3ShowTriggerList(0);
#ifndef SQLITE_OMIT_WINDOWFUNC
        sqlite3ShowWindow(0);
        sqlite3ShowWinFunc(0);
#endif
        sqlite3ShowSelect(0);
      }
#endif
      break;
    }


    /*
    **  sqlite3_test_control(SQLITE_TESTCTRL_ALWAYS, int X)
    **
3920
3921
3922
3923
3924
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
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
4211
4212
4213
4214
4215
4216
4217














4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228

4229
4230
4231
4232

4233
4234


4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256

4257
4258


4259
4260


4261
4262

4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303







-
-
-
-
-
-
-
-
-
-
-
-
-
-











-
+



-
+

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



+
+
+
+
+
+



-
+

-
-
+
+
-
-


-
+
+















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







    **  123410     little-endian, determined at compile-time
    */ 
    case SQLITE_TESTCTRL_BYTEORDER: {
      rc = SQLITE_BYTEORDER*100 + SQLITE_LITTLEENDIAN*10 + SQLITE_BIGENDIAN;
      break;
    }

    /*   sqlite3_test_control(SQLITE_TESTCTRL_RESERVE, sqlite3 *db, int N)
    **
    ** Set the nReserve size to N for the main database on the database
    ** connection db.
    */
    case SQLITE_TESTCTRL_RESERVE: {
      sqlite3 *db = va_arg(ap, sqlite3*);
      int x = va_arg(ap,int);
      sqlite3_mutex_enter(db->mutex);
      sqlite3BtreeSetPageSize(db->aDb[0].pBt, 0, x, 0);
      sqlite3_mutex_leave(db->mutex);
      break;
    }

    /*  sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, sqlite3 *db, int N)
    **
    ** Enable or disable various optimizations for testing purposes.  The 
    ** argument N is a bitmask of optimizations to be disabled.  For normal
    ** operation N should be 0.  The idea is that a test program (like the
    ** SQL Logic Test or SLT test module) can run the same SQL multiple times
    ** with various optimizations disabled to verify that the same answer
    ** is obtained in every case.
    */
    case SQLITE_TESTCTRL_OPTIMIZATIONS: {
      sqlite3 *db = va_arg(ap, sqlite3*);
      db->dbOptFlags = (u16)(va_arg(ap, int) & 0xffff);
      db->dbOptFlags = va_arg(ap, u32);
      break;
    }

    /*   sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff);
    /*   sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, onoff, xAlt);
    **
    ** If parameter onoff is non-zero, subsequent calls to localtime()
    ** and its variants fail. If onoff is zero, undo this setting.
    ** If parameter onoff is 1, subsequent calls to localtime() fail.
    ** If 2, then invoke xAlt() instead of localtime().  If 0, normal
    ** processing.
    **
    ** xAlt arguments are void pointers, but they really want to be:
    **
    **    int xAlt(const time_t*, struct tm*);
    **
    ** xAlt should write results in to struct tm object of its 2nd argument
    ** and return zero on success, or return non-zero on failure.
    */
    case SQLITE_TESTCTRL_LOCALTIME_FAULT: {
      sqlite3GlobalConfig.bLocaltimeFault = va_arg(ap, int);
      if( sqlite3GlobalConfig.bLocaltimeFault==2 ){
        typedef int(*sqlite3LocaltimeType)(const void*,void*);
        sqlite3GlobalConfig.xAltLocaltime = va_arg(ap, sqlite3LocaltimeType);
      }else{
        sqlite3GlobalConfig.xAltLocaltime = 0;
      }
      break;
    }

    /*   sqlite3_test_control(SQLITE_TESTCTRL_INTERNAL_FUNCS, int onoff);
    /*   sqlite3_test_control(SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, sqlite3*);
    **
    ** If parameter onoff is non-zero, internal-use-only SQL functions
    ** are visible to ordinary SQL.  This is useful for testing but is
    ** Toggle the ability to use internal functions on or off for
    ** the database connection given in the argument.
    ** unsafe because invalid parameters to those internal-use-only functions
    ** can result in crashes or segfaults.
    */
    case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS: {
      sqlite3GlobalConfig.bInternalFunctions = va_arg(ap, int);
      sqlite3 *db = va_arg(ap, sqlite3*);
      db->mDbFlags ^= DBFLAG_InternalFunc;
      break;
    }

    /*   sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, int);
    **
    ** Set or clear a flag that indicates that the database file is always well-
    ** formed and never corrupt.  This flag is clear by default, indicating that
    ** database files might have arbitrary corruption.  Setting the flag during
    ** testing causes certain assert() statements in the code to be activated
    ** that demonstrat invariants on well-formed database files.
    */
    case SQLITE_TESTCTRL_NEVER_CORRUPT: {
      sqlite3GlobalConfig.neverCorrupt = va_arg(ap, int);
      break;
    }

    /*   sqlite3_test_control(SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS, int);
    **
    ** Set or clear a flag that causes SQLite to verify that type, name,
    ** and tbl_name fields of the sqlite_schema table.  This is normally
    ** on, but it is sometimes useful to turn it off for testing.
    **
    ** 2020-07-22:  Disabling EXTRA_SCHEMA_CHECKS also disables the
    ** verification of rootpage numbers when parsing the schema.  This
    ** is useful to make it easier to reach strange internal error states
    ** during testing.  The EXTRA_SCHEMA_CHECKS setting is always enabled
    ** in production.
    */
    case SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS: {
      sqlite3GlobalConfig.bExtraSchemaChecks = va_arg(ap, int);
      break;
    }

    /* Set the threshold at which OP_Once counters reset back to zero.
    ** By default this is 0x7ffffffe (over 2 billion), but that value is
    ** too big to test in a reasonable amount of time, so this control is
    ** provided to set a small and easily reachable reset value.
    */
    case SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD: {
4044
4045
4046
4047
4048
4049
4050

4051
4052
4053
4054
4055
4056








4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077











































































































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
4107
4108
4109
4110
4351
4352
4353
4354
4355
4356
4357
4358
4359





4360
4361
4362
4363
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
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
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
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600

4601

4602

4603
4604

4605
4606
4607
4608
4609
4610
4611
4612







+

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




















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




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














+
+
+
+
+
+
+
+
+
+

-
+
-

-


-
+







    **
    ** If onOff==0 and tnum>0 then reset the schema for all databases, causing
    ** the schema to be reparsed the next time it is needed.  This has the
    ** effect of erasing all imposter tables.
    */
    case SQLITE_TESTCTRL_IMPOSTER: {
      sqlite3 *db = va_arg(ap, sqlite3*);
      int iDb;
      sqlite3_mutex_enter(db->mutex);
      db->init.iDb = sqlite3FindDbName(db, va_arg(ap,const char*));
      db->init.busy = db->init.imposterTable = va_arg(ap,int);
      db->init.newTnum = va_arg(ap,int);
      if( db->init.busy==0 && db->init.newTnum>0 ){
        sqlite3ResetAllSchemasOfConnection(db);
      iDb = sqlite3FindDbName(db, va_arg(ap,const char*));
      if( iDb>=0 ){
        db->init.iDb = iDb;
        db->init.busy = db->init.imposterTable = va_arg(ap,int);
        db->init.newTnum = va_arg(ap,int);
        if( db->init.busy==0 && db->init.newTnum>0 ){
          sqlite3ResetAllSchemasOfConnection(db);
        }
      }
      sqlite3_mutex_leave(db->mutex);
      break;
    }

#if defined(YYCOVERAGE)
    /*  sqlite3_test_control(SQLITE_TESTCTRL_PARSER_COVERAGE, FILE *out)
    **
    ** This test control (only available when SQLite is compiled with
    ** -DYYCOVERAGE) writes a report onto "out" that shows all
    ** state/lookahead combinations in the parser state machine
    ** which are never exercised.  If any state is missed, make the
    ** return code SQLITE_ERROR.
    */
    case SQLITE_TESTCTRL_PARSER_COVERAGE: {
      FILE *out = va_arg(ap, FILE*);
      if( sqlite3ParserCoverage(out) ) rc = SQLITE_ERROR;
      break;
    }
#endif /* defined(YYCOVERAGE) */
  }

    /*  sqlite3_test_control(SQLITE_TESTCTRL_RESULT_INTREAL, sqlite3_context*);
    **
    ** This test-control causes the most recent sqlite3_result_int64() value
    ** to be interpreted as a MEM_IntReal instead of as an MEM_Int.  Normally,
    ** MEM_IntReal values only arise during an INSERT operation of integer
    ** values into a REAL column, so they can be challenging to test.  This
    ** test-control enables us to write an intreal() SQL function that can
    ** inject an intreal() value at arbitrary places in an SQL statement,
    ** for testing purposes.
    */
    case SQLITE_TESTCTRL_RESULT_INTREAL: {
      sqlite3_context *pCtx = va_arg(ap, sqlite3_context*);
      sqlite3ResultIntReal(pCtx);
      break;
    }

    /*  sqlite3_test_control(SQLITE_TESTCTRL_SEEK_COUNT,
    **    sqlite3 *db,    // Database connection
    **    u64 *pnSeek     // Write seek count here
    **  );
    **
    ** This test-control queries the seek-counter on the "main" database
    ** file.  The seek-counter is written into *pnSeek and is then reset.
    ** The seek-count is only available if compiled with SQLITE_DEBUG.
    */
    case SQLITE_TESTCTRL_SEEK_COUNT: {
      sqlite3 *db = va_arg(ap, sqlite3*);
      u64 *pn = va_arg(ap, sqlite3_uint64*);
      *pn = sqlite3BtreeSeekCount(db->aDb->pBt);
      (void)db;  /* Silence harmless unused variable warning */
      break;
    }

    /*  sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, op, ptr)
    **
    **  "ptr" is a pointer to a u32.  
    **
    **   op==0       Store the current sqlite3TreeTrace in *ptr
    **   op==1       Set sqlite3TreeTrace to the value *ptr
    **   op==3       Store the current sqlite3WhereTrace in *ptr
    **   op==3       Set sqlite3WhereTrace to the value *ptr
    */
    case SQLITE_TESTCTRL_TRACEFLAGS: {
       int opTrace = va_arg(ap, int);
       u32 *ptr = va_arg(ap, u32*);
       switch( opTrace ){
         case 0:   *ptr = sqlite3TreeTrace;      break;
         case 1:   sqlite3TreeTrace = *ptr;      break;
         case 2:   *ptr = sqlite3WhereTrace;     break;
         case 3:   sqlite3WhereTrace = *ptr;     break;
       }
       break;
    }

    /* sqlite3_test_control(SQLITE_TESTCTRL_LOGEST,
    **      double fIn,     // Input value
    **      int *pLogEst,   // sqlite3LogEstFromDouble(fIn)
    **      u64 *pInt,      // sqlite3LogEstToInt(*pLogEst)
    **      int *pLogEst2   // sqlite3LogEst(*pInt)
    ** );
    **
    ** Test access for the LogEst conversion routines.
    */
    case SQLITE_TESTCTRL_LOGEST: {
      double rIn = va_arg(ap, double);
      LogEst rLogEst = sqlite3LogEstFromDouble(rIn);
      int *pI1 = va_arg(ap,int*);
      u64 *pU64 = va_arg(ap,u64*);
      int *pI2 = va_arg(ap,int*);
      *pI1 = rLogEst;
      *pU64 = sqlite3LogEstToInt(rLogEst);
      *pI2 = sqlite3LogEst(*pU64);
      break;
    }
 

#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_WSD)
    /* sqlite3_test_control(SQLITE_TESTCTRL_TUNE, id, *piValue)
    **
    ** If "id" is an integer between 1 and SQLITE_NTUNE then set the value
    ** of the id-th tuning parameter to *piValue.  If "id" is between -1
    ** and -SQLITE_NTUNE, then write the current value of the (-id)-th
    ** tuning parameter into *piValue.
    **
    ** Tuning parameters are for use during transient development builds,
    ** to help find the best values for constants in the query planner.
    ** Access tuning parameters using the Tuning(ID) macro.  Set the
    ** parameters in the CLI using ".testctrl tune ID VALUE".
    **
    ** Transient use only.  Tuning parameters should not be used in
    ** checked-in code.
    */
    case SQLITE_TESTCTRL_TUNE: {
      int id = va_arg(ap, int);
      int *piValue = va_arg(ap, int*);
      if( id>0 && id<=SQLITE_NTUNE ){
        Tuning(id) = *piValue;
      }else if( id<0 && id>=-SQLITE_NTUNE ){
        *piValue = Tuning(-id);
      }else{
        rc = SQLITE_NOTFOUND;
      }
      break;
    }
#endif
  }
  va_end(ap);
#endif /* SQLITE_UNTESTABLE */
  return rc;
}

/*
** The Pager stores the Database filename, Journal filename, and WAL filename
** consecutively in memory, in that order.  The database filename is prefixed
** by four zero bytes.  Locate the start of the database filename by searching
** backwards for the first byte following four consecutive zero bytes.
**
** This only works if the filename passed in was obtained from the Pager.
*/
static const char *databaseName(const char *zName){
  while( zName[-1]!=0 || zName[-2]!=0 || zName[-3]!=0 || zName[-4]!=0 ){
    zName--;
  }
  return zName;
}

/*
** Append text z[] to the end of p[].  Return a pointer to the first
** character after then zero terminator on the new text in p[].
*/
static char *appendText(char *p, const char *z){
  size_t n = strlen(z);
  memcpy(p, z, n+1);
  return p+n+1;
}

/*
** Allocate memory to hold names for a database, journal file, WAL file,
** and query parameters.  The pointer returned is valid for use by
** sqlite3_filename_database() and sqlite3_uri_parameter() and related
** functions.
**
** Memory layout must be compatible with that generated by the pager
** and expected by sqlite3_uri_parameter() and databaseName().
*/
const char *sqlite3_create_filename(
  const char *zDatabase,
  const char *zJournal,
  const char *zWal,
  int nParam,
  const char **azParam
){
  sqlite3_int64 nByte;
  int i;
  char *pResult, *p;
  nByte = strlen(zDatabase) + strlen(zJournal) + strlen(zWal) + 10;
  for(i=0; i<nParam*2; i++){
    nByte += strlen(azParam[i])+1;
  }
  pResult = p = sqlite3_malloc64( nByte );
  if( p==0 ) return 0;
  memset(p, 0, 4);
  p += 4;
  p = appendText(p, zDatabase);
  for(i=0; i<nParam*2; i++){
    p = appendText(p, azParam[i]);
  }
  *(p++) = 0;
  p = appendText(p, zJournal);
  p = appendText(p, zWal);
  *(p++) = 0;
  *(p++) = 0;
  assert( (sqlite3_int64)(p - pResult)==nByte );
  return pResult + 4;
}

/*
** Free memory obtained from sqlite3_create_filename().  It is a severe
** error to call this routine with any parameter other than a pointer
** previously obtained from sqlite3_create_filename() or a NULL pointer.
*/
void sqlite3_free_filename(const char *p){
  if( p==0 ) return;
  p = databaseName(p);
  sqlite3_free((char*)p - 4);
}


/*
** This is a utility routine, useful to VFS implementations, that checks
** to see if a database file was a URI that contained a specific query 
** parameter, and if so obtains the value of the query parameter.
**
** The zFilename argument is the filename pointer passed into the xOpen()
** method of a VFS implementation.  The zParam argument is the name of the
** query parameter we seek.  This routine returns the value of the zParam
** parameter if it exists.  If the parameter does not exist, this routine
** returns a NULL pointer.
*/
const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam){
  if( zFilename==0 || zParam==0 ) return 0;
  zFilename = databaseName(zFilename);
  return uriParameter(zFilename, zParam);
}

/*
** Return a pointer to the name of Nth query parameter of the filename.
*/
const char *sqlite3_uri_key(const char *zFilename, int N){
  if( zFilename==0 || N<0 ) return 0;
  zFilename = databaseName(zFilename);
  zFilename += sqlite3Strlen30(zFilename) + 1;
  while( zFilename[0] ){
  while( ALWAYS(zFilename) && zFilename[0] && (N--)>0 ){
    int x = strcmp(zFilename, zParam);
    zFilename += sqlite3Strlen30(zFilename) + 1;
    if( x==0 ) return zFilename;
    zFilename += sqlite3Strlen30(zFilename) + 1;
  }
  return 0;
  return zFilename[0] ? zFilename : 0;
}

/*
** Return a boolean value for a query parameter.
*/
int sqlite3_uri_boolean(const char *zFilename, const char *zParam, int bDflt){
  const char *z = sqlite3_uri_parameter(zFilename, zParam);
4123
4124
4125
4126
4127
4128
4129


































4130
4131
4132
4133
4134
4135
4136
4137


















4138
4139
4140
4141
4142
4143
4144
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698







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








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







  const char *z = sqlite3_uri_parameter(zFilename, zParam);
  sqlite3_int64 v;
  if( z && sqlite3DecOrHexToI64(z, &v)==0 ){
    bDflt = v;
  }
  return bDflt;
}

/*
** Translate a filename that was handed to a VFS routine into the corresponding
** database, journal, or WAL file.
**
** It is an error to pass this routine a filename string that was not
** passed into the VFS from the SQLite core.  Doing so is similar to
** passing free() a pointer that was not obtained from malloc() - it is
** an error that we cannot easily detect but that will likely cause memory
** corruption.
*/
const char *sqlite3_filename_database(const char *zFilename){
  if( zFilename==0 ) return 0;
  return databaseName(zFilename);
}
const char *sqlite3_filename_journal(const char *zFilename){
  if( zFilename==0 ) return 0;
  zFilename = databaseName(zFilename);
  zFilename += sqlite3Strlen30(zFilename) + 1;
  while( ALWAYS(zFilename) && zFilename[0] ){
    zFilename += sqlite3Strlen30(zFilename) + 1;
    zFilename += sqlite3Strlen30(zFilename) + 1;
  }
  return zFilename + 1;
}
const char *sqlite3_filename_wal(const char *zFilename){
#ifdef SQLITE_OMIT_WAL
  return 0;
#else
  zFilename = sqlite3_filename_journal(zFilename);
  if( zFilename ) zFilename += sqlite3Strlen30(zFilename) + 1;
  return zFilename;
#endif
}

/*
** Return the Btree pointer identified by zDbName.  Return NULL if not found.
*/
Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){
  int iDb = zDbName ? sqlite3FindDbName(db, zDbName) : 0;
  return iDb<0 ? 0 : db->aDb[iDb].pBt;
}

/*
** Return the name of the N-th database schema.  Return NULL if N is out
** of range.
*/
const char *sqlite3_db_name(sqlite3 *db, int N){
#ifdef SQLITE_ENABLE_API_ARMOR
  if( !sqlite3SafetyCheckOk(db) ){
    (void)SQLITE_MISUSE_BKPT;
    return 0;
  }
#endif
  if( N<0 || N>=db->nDb ){
    return 0;
  }else{
    return db->aDb[N].zDbSName;
  }
}

/*
** Return the filename of the database associated with a database
** connection.
*/
const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){
  Btree *pBt;
4188
4189
4190
4191
4192
4193
4194
4195

4196
4197
4198
4199
4200
4201
4202
4742
4743
4744
4745
4746
4747
4748

4749
4750
4751
4752
4753
4754
4755
4756







-
+







#endif
  sqlite3_mutex_enter(db->mutex);

  if( db->autoCommit==0 ){
    int iDb = sqlite3FindDbName(db, zDb);
    if( iDb==0 || iDb>1 ){
      Btree *pBt = db->aDb[iDb].pBt;
      if( 0==sqlite3BtreeIsInTrans(pBt) ){
      if( SQLITE_TXN_WRITE!=sqlite3BtreeTxnState(pBt) ){
        rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
        if( rc==SQLITE_OK ){
          rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot);
        }
      }
    }
  }
4224
4225
4226
4227
4228
4229
4230
4231

4232
4233
4234

4235
4236
4237
4238
4239
4240
4241
4778
4779
4780
4781
4782
4783
4784

4785
4786
4787

4788
4789
4790
4791
4792
4793
4794
4795







-
+


-
+







#endif
  sqlite3_mutex_enter(db->mutex);
  if( db->autoCommit==0 ){
    int iDb;
    iDb = sqlite3FindDbName(db, zDb);
    if( iDb==0 || iDb>1 ){
      Btree *pBt = db->aDb[iDb].pBt;
      if( sqlite3BtreeIsInTrans(pBt)==0 ){
      if( sqlite3BtreeTxnState(pBt)!=SQLITE_TXN_WRITE ){
        Pager *pPager = sqlite3BtreePager(pBt);
        int bUnlock = 0;
        if( sqlite3BtreeIsInReadTrans(pBt) ){
        if( sqlite3BtreeTxnState(pBt)!=SQLITE_TXN_NONE ){
          if( db->nVdbeActive==0 ){
            rc = sqlite3PagerSnapshotCheck(pPager, pSnapshot);
            if( rc==SQLITE_OK ){
              bUnlock = 1;
              rc = sqlite3BtreeCommit(pBt);
            }
          }
4263
4264
4265
4266
4267
4268
4269
4270
4271

4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283

4284
4285
4286
4287
4288
4289
4290
4817
4818
4819
4820
4821
4822
4823

4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836

4837
4838
4839
4840
4841
4842
4843
4844







-

+











-
+








/*
** Recover as many snapshots as possible from the wal file associated with
** schema zDb of database db.
*/
int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb){
  int rc = SQLITE_ERROR;
  int iDb;
#ifndef SQLITE_OMIT_WAL
  int iDb;

#ifdef SQLITE_ENABLE_API_ARMOR
  if( !sqlite3SafetyCheckOk(db) ){
    return SQLITE_MISUSE_BKPT;
  }
#endif

  sqlite3_mutex_enter(db->mutex);
  iDb = sqlite3FindDbName(db, zDb);
  if( iDb==0 || iDb>1 ){
    Btree *pBt = db->aDb[iDb].pBt;
    if( 0==sqlite3BtreeIsInReadTrans(pBt) ){
    if( SQLITE_TXN_NONE==sqlite3BtreeTxnState(pBt) ){
      rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
      if( rc==SQLITE_OK ){
        rc = sqlite3PagerSnapshotRecover(sqlite3BtreePager(pBt));
        sqlite3BtreeCommit(pBt);
      }
    }
  }

Changes to src/malloc.c.

28
29
30
31
32
33
34







35
36
37
38
39
40

41
42
43
44
45
46
47

48
49
50
51
52
53
54
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







+
+
+
+
+
+
+






+






-
+







  ** is a no-op returning zero if SQLite is not compiled with
  ** SQLITE_ENABLE_MEMORY_MANAGEMENT. */
  UNUSED_PARAMETER(n);
  return 0;
#endif
}

/*
** Default value of the hard heap limit.  0 means "no limit".
*/
#ifndef SQLITE_MAX_MEMORY
# define SQLITE_MAX_MEMORY 0
#endif

/*
** State information local to the memory allocation subsystem.
*/
static SQLITE_WSD struct Mem0Global {
  sqlite3_mutex *mutex;         /* Mutex to serialize access */
  sqlite3_int64 alarmThreshold; /* The soft heap limit */
  sqlite3_int64 hardLimit;      /* The hard upper bound on memory */

  /*
  ** True if heap is nearly "full" where "full" is defined by the
  ** sqlite3_soft_heap_limit() setting.
  */
  int nearlyFull;
} mem0 = { 0, 0, 0 };
} mem0 = { 0, SQLITE_MAX_MEMORY, SQLITE_MAX_MEMORY, 0 };

#define mem0 GLOBAL(struct Mem0Global, mem0)

/*
** Return the memory allocator mutex. sqlite3_status() needs it.
*/
sqlite3_mutex *sqlite3MallocMutex(void){
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
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







-
-
+
+
+
+
+
+
+
+
+














+
+
+



-
+









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









-

















-
+







  (void)pArg;
  (void)iThreshold;
  return SQLITE_OK;
}
#endif

/*
** Set the soft heap-size limit for the library. Passing a zero or 
** negative value indicates no limit.
** Set the soft heap-size limit for the library.  An argument of
** zero disables the limit.  A negative argument is a no-op used to
** obtain the return value.
**
** The return value is the value of the heap limit just before this
** interface was called.
**
** If the hard heap limit is enabled, then the soft heap limit cannot
** be disabled nor raised above the hard heap limit.
*/
sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 n){
  sqlite3_int64 priorLimit;
  sqlite3_int64 excess;
  sqlite3_int64 nUsed;
#ifndef SQLITE_OMIT_AUTOINIT
  int rc = sqlite3_initialize();
  if( rc ) return -1;
#endif
  sqlite3_mutex_enter(mem0.mutex);
  priorLimit = mem0.alarmThreshold;
  if( n<0 ){
    sqlite3_mutex_leave(mem0.mutex);
    return priorLimit;
  }
  if( mem0.hardLimit>0 && (n>mem0.hardLimit || n==0) ){
    n = mem0.hardLimit;
  }
  mem0.alarmThreshold = n;
  nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
  mem0.nearlyFull = (n>0 && n<=nUsed);
  AtomicStore(&mem0.nearlyFull, n>0 && n<=nUsed);
  sqlite3_mutex_leave(mem0.mutex);
  excess = sqlite3_memory_used() - n;
  if( excess>0 ) sqlite3_release_memory((int)(excess & 0x7fffffff));
  return priorLimit;
}
void sqlite3_soft_heap_limit(int n){
  if( n<0 ) n = 0;
  sqlite3_soft_heap_limit64(n);
}

/*
** Set the hard heap-size limit for the library. An argument of zero
** disables the hard heap limit.  A negative argument is a no-op used
** to obtain the return value without affecting the hard heap limit.
**
** The return value is the value of the hard heap limit just prior to
** calling this interface.
**
** Setting the hard heap limit will also activate the soft heap limit
** and constrain the soft heap limit to be no more than the hard heap
** limit.
*/
sqlite3_int64 sqlite3_hard_heap_limit64(sqlite3_int64 n){
  sqlite3_int64 priorLimit;
#ifndef SQLITE_OMIT_AUTOINIT
  int rc = sqlite3_initialize();
  if( rc ) return -1;
#endif
  sqlite3_mutex_enter(mem0.mutex);
  priorLimit = mem0.hardLimit;
  if( n>=0 ){
    mem0.hardLimit = n;
    if( n<mem0.alarmThreshold || mem0.alarmThreshold==0 ){
      mem0.alarmThreshold = n;
    }
  }
  sqlite3_mutex_leave(mem0.mutex);
  return priorLimit;
}


/*
** Initialize the memory allocation subsystem.
*/
int sqlite3MallocInit(void){
  int rc;
  if( sqlite3GlobalConfig.m.xMalloc==0 ){
    sqlite3MemSetDefault();
  }
  memset(&mem0, 0, sizeof(mem0));
  mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
  if( sqlite3GlobalConfig.pPage==0 || sqlite3GlobalConfig.szPage<512
      || sqlite3GlobalConfig.nPage<=0 ){
    sqlite3GlobalConfig.pPage = 0;
    sqlite3GlobalConfig.szPage = 0;
  }
  rc = sqlite3GlobalConfig.m.xInit(sqlite3GlobalConfig.m.pAppData);
  if( rc!=SQLITE_OK ) memset(&mem0, 0, sizeof(mem0));
  return rc;
}

/*
** Return true if the heap is currently under memory pressure - in other
** words if the amount of heap used is close to the limit set by
** sqlite3_soft_heap_limit().
*/
int sqlite3HeapNearlyFull(void){
  return mem0.nearlyFull;
  return AtomicLoad(&mem0.nearlyFull);
}

/*
** Deinitialize the memory allocation subsystem.
*/
void sqlite3MallocEnd(void){
  if( sqlite3GlobalConfig.m.xShutdown ){
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
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







-
-
-
-
-
-
-




-
+

+
+
+
+
+
+
+

-
+

















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






-
+
-
-
-
-
-







  /* In Firefox (circa 2017-02-08), xRoundup() is remapped to an internal
  ** implementation of malloc_good_size(), which must be called in debug
  ** mode and specifically when the DMD "Dark Matter Detector" is enabled
  ** or else a crash results.  Hence, do not attempt to optimize out the
  ** following xRoundup() call. */
  nFull = sqlite3GlobalConfig.m.xRoundup(n);

#ifdef SQLITE_MAX_MEMORY
  if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)+nFull>SQLITE_MAX_MEMORY ){
    *pp = 0;
    return;
  }
#endif

  sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, n);
  if( mem0.alarmThreshold>0 ){
    sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
    if( nUsed >= mem0.alarmThreshold - nFull ){
      mem0.nearlyFull = 1;
      AtomicStore(&mem0.nearlyFull, 1);
      sqlite3MallocAlarm(nFull);
      if( mem0.hardLimit ){
        nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
        if( nUsed >= mem0.hardLimit - nFull ){
          *pp = 0;
          return;
        }
      }
    }else{
      mem0.nearlyFull = 0;
      AtomicStore(&mem0.nearlyFull, 0);
    }
  }
  p = sqlite3GlobalConfig.m.xMalloc(nFull);
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
  if( p==0 && mem0.alarmThreshold>0 ){
    sqlite3MallocAlarm(nFull);
    p = sqlite3GlobalConfig.m.xMalloc(nFull);
  }
#endif
  if( p ){
    nFull = sqlite3MallocSize(p);
    sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nFull);
    sqlite3StatusUp(SQLITE_STATUS_MALLOC_COUNT, 1);
  }
  *pp = p;
}

/*
** Maximum size of any single memory allocation.
**
** This is not a limit on the total amount of memory used.  This is
** a limit on the size parameter to sqlite3_malloc() and sqlite3_realloc().
**
** The upper bound is slightly less than 2GiB:  0x7ffffeff == 2,147,483,391
** This provides a 256-byte safety margin for defense against 32-bit 
** signed integer overflow bugs when computing memory allocation sizes.
** Paranoid applications might want to reduce the maximum allocation size
** further for an even larger safety margin.  0x3fffffff or 0x0fffffff
** or even smaller would be reasonable upper bounds on the size of a memory
** allocations for most applications.
*/
#ifndef SQLITE_MAX_ALLOCATION_SIZE
# define SQLITE_MAX_ALLOCATION_SIZE  2147483391
#endif
#if SQLITE_MAX_ALLOCATION_SIZE>2147483391
# error Maximum size for SQLITE_MAX_ALLOCATION_SIZE is 2147483391
#endif

/*
** Allocate memory.  This routine is like sqlite3_malloc() except that it
** assumes the memory subsystem has already been initialized.
*/
void *sqlite3Malloc(u64 n){
  void *p;
  if( n==0 || n>=0x7fffff00 ){
  if( n==0 || n>SQLITE_MAX_ALLOCATION_SIZE ){
    /* A memory allocation of a number of bytes which is near the maximum
    ** signed integer value might cause an integer overflow inside of the
    ** xMalloc().  Hence we limit the maximum size to 0x7fffff00, giving
    ** 255 bytes of overhead.  SQLite itself will never use anything near
    ** this amount.  The only way to reach the limit is with sqlite3_malloc() */
    p = 0;
  }else if( sqlite3GlobalConfig.bMemstat ){
    sqlite3_mutex_enter(mem0.mutex);
    mallocWithAlarm((int)n, &p);
    sqlite3_mutex_leave(mem0.mutex);
  }else{
    p = sqlite3GlobalConfig.m.xMalloc((int)n);
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
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







-
-
+
+









-
+

-
+

+
+
+
+
+
+
+
-
+

-

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

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







  return sqlite3Malloc(n);
}

/*
** TRUE if p is a lookaside memory allocation from db
*/
#ifndef SQLITE_OMIT_LOOKASIDE
static int isLookaside(sqlite3 *db, void *p){
  return SQLITE_WITHIN(p, db->lookaside.pStart, db->lookaside.pEnd);
static int isLookaside(sqlite3 *db, const void *p){
  return SQLITE_WITHIN(p, db->lookaside.pStart, db->lookaside.pTrueEnd);
}
#else
#define isLookaside(A,B) 0
#endif

/*
** Return the size of a memory allocation previously obtained from
** sqlite3Malloc() or sqlite3_malloc().
*/
int sqlite3MallocSize(void *p){
int sqlite3MallocSize(const void *p){
  assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
  return sqlite3GlobalConfig.m.xSize(p);
  return sqlite3GlobalConfig.m.xSize((void*)p);
}
static int lookasideMallocSize(sqlite3 *db, const void *p){
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE    
  return p<db->lookaside.pMiddle ? db->lookaside.szTrue : LOOKASIDE_SMALL;
#else
  return db->lookaside.szTrue;
#endif  
}
int sqlite3DbMallocSize(sqlite3 *db, void *p){
int sqlite3DbMallocSize(sqlite3 *db, const void *p){
  assert( p!=0 );
  if( db==0 || !isLookaside(db,p) ){
#ifdef SQLITE_DEBUG
    if( db==0 ){
      assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
      assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
    }else{
      assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
      assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
    }
  if( db==0 ){
    assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
    assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
  }else if( !isLookaside(db,p) ){
    assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
    assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
  }
#endif
  if( db ){
    if( ((uptr)p)<(uptr)(db->lookaside.pTrueEnd) ){
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
      if( ((uptr)p)>=(uptr)(db->lookaside.pMiddle) ){
        assert( sqlite3_mutex_held(db->mutex) );
    return sqlite3GlobalConfig.m.xSize(p);
  }else{
    assert( sqlite3_mutex_held(db->mutex) );
    return db->lookaside.sz;
  }
        return LOOKASIDE_SMALL;
      }
#endif
      if( ((uptr)p)>=(uptr)(db->lookaside.pStart) ){
        assert( sqlite3_mutex_held(db->mutex) );
        return db->lookaside.szTrue;
      }
    }
  }
  return sqlite3GlobalConfig.m.xSize((void*)p);
}
sqlite3_uint64 sqlite3_msize(void *p){
  assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
  assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
  return p ? sqlite3GlobalConfig.m.xSize(p) : 0;
}

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







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

-
-
+

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






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







** connection.  Calling sqlite3DbFree(D,X) for X==0 is a harmless no-op.
** The sqlite3DbFreeNN(D,X) version requires that X be non-NULL.
*/
void sqlite3DbFreeNN(sqlite3 *db, void *p){
  assert( db==0 || sqlite3_mutex_held(db->mutex) );
  assert( p!=0 );
  if( db ){
    if( ((uptr)p)<(uptr)(db->lookaside.pEnd) ){
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
      if( ((uptr)p)>=(uptr)(db->lookaside.pMiddle) ){
        LookasideSlot *pBuf = (LookasideSlot*)p;
    if( db->pnBytesFreed ){
        assert( db->pnBytesFreed==0 );
      measureAllocationSize(db, p);
      return;
    }
    if( isLookaside(db, p) ){
      LookasideSlot *pBuf = (LookasideSlot*)p;
#ifdef SQLITE_DEBUG
        memset(p, 0xaa, LOOKASIDE_SMALL);  /* Trash freed content */
#endif
        pBuf->pNext = db->lookaside.pSmallFree;
        db->lookaside.pSmallFree = pBuf;
        return;
      }
#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
      if( ((uptr)p)>=(uptr)(db->lookaside.pStart) ){
        LookasideSlot *pBuf = (LookasideSlot*)p;
        assert( db->pnBytesFreed==0 );
#ifdef SQLITE_DEBUG
      /* Trash all content in the buffer being freed */
      memset(p, 0xaa, db->lookaside.sz);
        memset(p, 0xaa, db->lookaside.szTrue);  /* Trash freed content */
#endif
      pBuf->pNext = db->lookaside.pFree;
      db->lookaside.pFree = pBuf;
      return;
    }
        pBuf->pNext = db->lookaside.pFree;
        db->lookaside.pFree = pBuf;
        return;
      }
    }
    if( db->pnBytesFreed ){
      measureAllocationSize(db, p);
      return;
    }
  }
  assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
  assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
  assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
  sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
  sqlite3_free(p);
}
void sqlite3DbNNFreeNN(sqlite3 *db, void *p){
  assert( db!=0 );
  assert( sqlite3_mutex_held(db->mutex) );
  assert( p!=0 );
  if( ((uptr)p)<(uptr)(db->lookaside.pEnd) ){
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
    if( ((uptr)p)>=(uptr)(db->lookaside.pMiddle) ){
      LookasideSlot *pBuf = (LookasideSlot*)p;
      assert( db->pnBytesFreed==0 );
#ifdef SQLITE_DEBUG
      memset(p, 0xaa, LOOKASIDE_SMALL);  /* Trash freed content */
#endif
      pBuf->pNext = db->lookaside.pSmallFree;
      db->lookaside.pSmallFree = pBuf;
      return;
    }
#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
    if( ((uptr)p)>=(uptr)(db->lookaside.pStart) ){
      LookasideSlot *pBuf = (LookasideSlot*)p;
      assert( db->pnBytesFreed==0 );
#ifdef SQLITE_DEBUG
      memset(p, 0xaa, db->lookaside.szTrue);  /* Trash freed content */
#endif
      pBuf->pNext = db->lookaside.pFree;
      db->lookaside.pFree = pBuf;
      return;
    }
  }
  if( db->pnBytesFreed ){
    measureAllocationSize(db, p);
    return;
  }
  assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
  assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
  sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
  sqlite3_free(p);
}
void sqlite3DbFree(sqlite3 *db, void *p){
  assert( db==0 || sqlite3_mutex_held(db->mutex) );
  if( p ) sqlite3DbFreeNN(db, p);
}

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







+



-
+


+
+
+
-
+
+

+




+







  /* IMPLEMENTATION-OF: R-46199-30249 SQLite guarantees that the second
  ** argument to xRealloc is always a value returned by a prior call to
  ** xRoundup. */
  nNew = sqlite3GlobalConfig.m.xRoundup((int)nBytes);
  if( nOld==nNew ){
    pNew = pOld;
  }else if( sqlite3GlobalConfig.bMemstat ){
    sqlite3_int64 nUsed;
    sqlite3_mutex_enter(mem0.mutex);
    sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, (int)nBytes);
    nDiff = nNew - nOld;
    if( nDiff>0 && sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >= 
    if( nDiff>0 && (nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)) >= 
          mem0.alarmThreshold-nDiff ){
      sqlite3MallocAlarm(nDiff);
      if( mem0.hardLimit>0 && nUsed >= mem0.hardLimit - nDiff ){
        sqlite3_mutex_leave(mem0.mutex);
        return 0;
    }
      }
    }
    pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
    if( pNew==0 && mem0.alarmThreshold>0 ){
      sqlite3MallocAlarm((int)nBytes);
      pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
    }
#endif
    if( pNew ){
      nNew = sqlite3MallocSize(pNew);
      sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nNew-nOld);
    }
    sqlite3_mutex_leave(mem0.mutex);
  }else{
    pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
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
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







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







}
void *sqlite3DbMallocRawNN(sqlite3 *db, u64 n){
#ifndef SQLITE_OMIT_LOOKASIDE
  LookasideSlot *pBuf;
  assert( db!=0 );
  assert( sqlite3_mutex_held(db->mutex) );
  assert( db->pnBytesFreed==0 );
  if( n>db->lookaside.sz ){
  if( db->lookaside.bDisable==0 ){
    assert( db->mallocFailed==0 );
    if( n>db->lookaside.sz ){
      db->lookaside.anStat[1]++;
    }else if( (pBuf = db->lookaside.pFree)!=0 ){
      db->lookaside.pFree = pBuf->pNext;
      db->lookaside.anStat[0]++;
      return (void*)pBuf;
    }else if( (pBuf = db->lookaside.pInit)!=0 ){
      db->lookaside.pInit = pBuf->pNext;
      db->lookaside.anStat[0]++;
      return (void*)pBuf;
    }else{
      db->lookaside.anStat[2]++;
    if( !db->lookaside.bDisable ){
      db->lookaside.anStat[1]++;      
    }else if( db->mallocFailed ){
      return 0;
    }
    return dbMallocRawFinish(db, n);
  }
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
  if( n<=LOOKASIDE_SMALL ){
    if( (pBuf = db->lookaside.pSmallFree)!=0 ){
      db->lookaside.pSmallFree = pBuf->pNext;
      db->lookaside.anStat[0]++;
      return (void*)pBuf;
    }else if( (pBuf = db->lookaside.pSmallInit)!=0 ){
      db->lookaside.pSmallInit = pBuf->pNext;
      db->lookaside.anStat[0]++;
      return (void*)pBuf;
    }
  }
#endif
  if( (pBuf = db->lookaside.pFree)!=0 ){
    db->lookaside.pFree = pBuf->pNext;
    db->lookaside.anStat[0]++;
    return (void*)pBuf;
  }else if( (pBuf = db->lookaside.pInit)!=0 ){
    db->lookaside.pInit = pBuf->pNext;
    db->lookaside.anStat[0]++;
    return (void*)pBuf;
  }else{
    db->lookaside.anStat[2]++;
    }
  }else if( db->mallocFailed ){
    return 0;
  }
#else
  assert( db!=0 );
  assert( sqlite3_mutex_held(db->mutex) );
  assert( db->pnBytesFreed==0 );
  if( db->mallocFailed ){
    return 0;
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
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







+
+
+
+
+
+
+
-
+
+
+










-
+






-
+







** Resize the block of memory pointed to by p to n bytes. If the
** resize fails, set the mallocFailed flag in the connection object.
*/
void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){
  assert( db!=0 );
  if( p==0 ) return sqlite3DbMallocRawNN(db, n);
  assert( sqlite3_mutex_held(db->mutex) );
  if( ((uptr)p)<(uptr)db->lookaside.pEnd ){
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
    if( ((uptr)p)>=(uptr)db->lookaside.pMiddle ){
      if( n<=LOOKASIDE_SMALL ) return p;
    }else
#endif
    if( ((uptr)p)>=(uptr)db->lookaside.pStart ){
  if( isLookaside(db,p) && n<=db->lookaside.sz ) return p;
      if( n<=db->lookaside.szTrue ) return p;
    }
  }
  return dbReallocFinish(db, p, n);
}
static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n){
  void *pNew = 0;
  assert( db!=0 );
  assert( p!=0 );
  if( db->mallocFailed==0 ){
    if( isLookaside(db, p) ){
      pNew = sqlite3DbMallocRawNN(db, n);
      if( pNew ){
        memcpy(pNew, p, db->lookaside.sz);
        memcpy(pNew, p, lookasideMallocSize(db, p));
        sqlite3DbFree(db, p);
      }
    }else{
      assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
      assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
      sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
      pNew = sqlite3_realloc64(p, n);
      pNew = sqlite3Realloc(p, n);
      if( !pNew ){
        sqlite3OomFault(db);
      }
      sqlite3MemdebugSetType(pNew,
            (db->lookaside.bDisable==0 ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
    }
  }
611
612
613
614
615
616
617
618

619
620
621
622

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





637
638
639

640
641
642
643
644
645
646

647
648

649
650
651
652
653
654
655







656
657

658
659
660
661

662
663
664












665
666
667
668
669
670
671
672
673
674
675
676
677

678
679

680
681
682
683
684

685
686
687
688
689







690
691
692
693
694
695
696
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







-
+
-
-

-
+














+
+
+
+
+


-
+







+

-
+







+
+
+
+
+
+
+

-
+



-
+

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












-
+

-
+




-
+

-
-
-
-
+
+
+
+
+
+
+







    memcpy(zNew, z, n);
  }
  return zNew;
}
char *sqlite3DbStrNDup(sqlite3 *db, const char *z, u64 n){
  char *zNew;
  assert( db!=0 );
  if( z==0 ){
  assert( z!=0 || n==0 );
    return 0;
  }
  assert( (n&0x7fffffff)==n );
  zNew = sqlite3DbMallocRawNN(db, n+1);
  zNew = z ? sqlite3DbMallocRawNN(db, n+1) : 0;
  if( zNew ){
    memcpy(zNew, z, (size_t)n);
    zNew[n] = 0;
  }
  return zNew;
}

/*
** The text between zStart and zEnd represents a phrase within a larger
** SQL statement.  Make a copy of this phrase in space obtained form
** sqlite3DbMalloc().  Omit leading and trailing whitespace.
*/
char *sqlite3DbSpanDup(sqlite3 *db, const char *zStart, const char *zEnd){
  int n;
#ifdef SQLITE_DEBUG
  /* Because of the way the parser works, the span is guaranteed to contain
  ** at least one non-space character */
  for(n=0; sqlite3Isspace(zStart[n]); n++){ assert( &zStart[n]<zEnd ); }
#endif
  while( sqlite3Isspace(zStart[0]) ) zStart++;
  n = (int)(zEnd - zStart);
  while( ALWAYS(n>0) && sqlite3Isspace(zStart[n-1]) ) n--;
  while( sqlite3Isspace(zStart[n-1]) ) n--;
  return sqlite3DbStrNDup(db, zStart, n);
}

/*
** Free any prior content in *pz and replace it with a copy of zNew.
*/
void sqlite3SetString(char **pz, sqlite3 *db, const char *zNew){
  char *z = sqlite3DbStrDup(db, zNew);
  sqlite3DbFree(db, *pz);
  *pz = sqlite3DbStrDup(db, zNew);
  *pz = z;
}

/*
** Call this routine to record the fact that an OOM (out-of-memory) error
** has happened.  This routine will set db->mallocFailed, and also
** temporarily disable the lookaside memory allocator and interrupt
** any running VDBEs.
**
** Always return a NULL pointer so that this routine can be invoked using
**
**      return sqlite3OomFault(db);
**
** and thereby avoid unnecessary stack frame allocations for the overwhelmingly
** common case where no OOM occurs.
*/
void sqlite3OomFault(sqlite3 *db){
void *sqlite3OomFault(sqlite3 *db){
  if( db->mallocFailed==0 && db->bBenignMalloc==0 ){
    db->mallocFailed = 1;
    if( db->nVdbeExec>0 ){
      db->u1.isInterrupted = 1;
      AtomicStore(&db->u1.isInterrupted, 1);
    }
    db->lookaside.bDisable++;
  }
    DisableLookaside;
    if( db->pParse ){
      Parse *pParse;
      sqlite3ErrorMsg(db->pParse, "out of memory");
      db->pParse->rc = SQLITE_NOMEM_BKPT;
      for(pParse=db->pParse->pOuterParse; pParse; pParse = pParse->pOuterParse){
        pParse->nErr++;
        pParse->rc = SQLITE_NOMEM;
      } 
    }
  }
  return 0;
}

/*
** This routine reactivates the memory allocator and clears the
** db->mallocFailed flag as necessary.
**
** The memory allocator is not restarted if there are running
** VDBEs.
*/
void sqlite3OomClear(sqlite3 *db){
  if( db->mallocFailed && db->nVdbeExec==0 ){
    db->mallocFailed = 0;
    db->u1.isInterrupted = 0;
    AtomicStore(&db->u1.isInterrupted, 0);
    assert( db->lookaside.bDisable>0 );
    db->lookaside.bDisable--;
    EnableLookaside;
  }
}

/*
** Take actions at the end of an API call to indicate an OOM error
** Take actions at the end of an API call to deal with error codes.
*/
static SQLITE_NOINLINE int apiOomError(sqlite3 *db){
  sqlite3OomClear(db);
  sqlite3Error(db, SQLITE_NOMEM);
  return SQLITE_NOMEM_BKPT;
static SQLITE_NOINLINE int apiHandleError(sqlite3 *db, int rc){
  if( db->mallocFailed || rc==SQLITE_IOERR_NOMEM ){
    sqlite3OomClear(db);
    sqlite3Error(db, SQLITE_NOMEM);
    return SQLITE_NOMEM_BKPT;
  }
  return rc & db->errMask;
}

/*
** This function must be called before exiting any API function (i.e. 
** returning control to the user) that has called sqlite3_malloc or
** sqlite3_realloc.
**
704
705
706
707
708
709
710
711
712


713
714
715
889
890
891
892
893
894
895


896
897
898
899
900







-
-
+
+



int sqlite3ApiExit(sqlite3* db, int rc){
  /* If the db handle must hold the connection handle mutex here.
  ** Otherwise the read (and possible write) of db->mallocFailed 
  ** is unsafe, as is the call to sqlite3Error().
  */
  assert( db!=0 );
  assert( sqlite3_mutex_held(db->mutex) );
  if( db->mallocFailed || rc==SQLITE_IOERR_NOMEM ){
    return apiOomError(db);
  if( db->mallocFailed || rc ){
    return apiHandleError(db, rc);
  }
  return rc & db->errMask;
}

Changes to src/mem2.c.

145
146
147
148
149
150
151
152

153
154
155
156
157
158
159
145
146
147
148
149
150
151

152
153
154
155
156
157
158
159







-
+








/*
** Given an allocation, find the MemBlockHdr for that allocation.
**
** This routine checks the guards at either end of the allocation and
** if they are incorrect it asserts.
*/
static struct MemBlockHdr *sqlite3MemsysGetHeader(void *pAllocation){
static struct MemBlockHdr *sqlite3MemsysGetHeader(const void *pAllocation){
  struct MemBlockHdr *p;
  int *pInt;
  u8 *pU8;
  int nReserve;

  p = (struct MemBlockHdr*)pAllocation;
  p--;
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
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







-
+
















-
+

-
+



















-
+

-
+







  sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
}

/*
** Set the "type" of an allocation.
*/
void sqlite3MemdebugSetType(void *p, u8 eType){
  if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){
  if( p && sqlite3GlobalConfig.m.xFree==sqlite3MemFree ){
    struct MemBlockHdr *pHdr;
    pHdr = sqlite3MemsysGetHeader(p);
    assert( pHdr->iForeGuard==FOREGUARD );
    pHdr->eType = eType;
  }
}

/*
** Return TRUE if the mask of type in eType matches the type of the
** allocation p.  Also return true if p==NULL.
**
** This routine is designed for use within an assert() statement, to
** verify the type of an allocation.  For example:
**
**     assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
*/
int sqlite3MemdebugHasType(void *p, u8 eType){
int sqlite3MemdebugHasType(const void *p, u8 eType){
  int rc = 1;
  if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){
  if( p && sqlite3GlobalConfig.m.xFree==sqlite3MemFree ){
    struct MemBlockHdr *pHdr;
    pHdr = sqlite3MemsysGetHeader(p);
    assert( pHdr->iForeGuard==FOREGUARD );         /* Allocation is valid */
    if( (pHdr->eType&eType)==0 ){
      rc = 0;
    }
  }
  return rc;
}

/*
** Return TRUE if the mask of type in eType matches no bits of the type of the
** allocation p.  Also return true if p==NULL.
**
** This routine is designed for use within an assert() statement, to
** verify the type of an allocation.  For example:
**
**     assert( sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
*/
int sqlite3MemdebugNoType(void *p, u8 eType){
int sqlite3MemdebugNoType(const void *p, u8 eType){
  int rc = 1;
  if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){
  if( p && sqlite3GlobalConfig.m.xFree==sqlite3MemFree ){
    struct MemBlockHdr *pHdr;
    pHdr = sqlite3MemsysGetHeader(p);
    assert( pHdr->iForeGuard==FOREGUARD );         /* Allocation is valid */
    if( (pHdr->eType&eType)!=0 ){
      rc = 0;
    }
  }

Changes to src/mem3.c.

114
115
116
117
118
119
120
121

122
123
124
125
126
127




128
129
130


131
132
133
134
135
136
137
114
115
116
117
118
119
120

121
122
123




124
125
126
127
128


129
130
131
132
133
134
135
136
137







-
+


-
-
-
-
+
+
+
+

-
-
+
+







  ** Mutex to control access to the memory allocation subsystem.
  */
  sqlite3_mutex *mutex;
  
  /*
  ** The minimum amount of free space that we have seen.
  */
  u32 mnMaster;
  u32 mnKeyBlk;

  /*
  ** iMaster is the index of the master chunk.  Most new allocations
  ** occur off of this chunk.  szMaster is the size (in Mem3Blocks)
  ** of the current master.  iMaster is 0 if there is not master chunk.
  ** The master chunk is not in either the aiHash[] or aiSmall[].
  ** iKeyBlk is the index of the key chunk.  Most new allocations
  ** occur off of this chunk.  szKeyBlk is the size (in Mem3Blocks)
  ** of the current key chunk.  iKeyBlk is 0 if there is no key chunk.
  ** The key chunk is not in either the aiHash[] or aiSmall[].
  */
  u32 iMaster;
  u32 szMaster;
  u32 iKeyBlk;
  u32 szKeyBlk;

  /*
  ** Array of lists of free blocks according to the block size 
  ** for smaller chunks, or a hash on the block size for larger
  ** chunks.
  */
  u32 aiSmall[MX_SMALL-1];   /* For sizes 2 through MX_SMALL, inclusive */
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
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







-
-
+
+


-
+

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


-
+

-
-
-
-
+
+
+
+

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













-
-
-
+
+
+

-
+

-
+







  mem3.aPool[i-1].u.hdr.size4x = nBlock*4 | 1 | (x&2);
  mem3.aPool[i+nBlock-1].u.hdr.prevSize = nBlock;
  mem3.aPool[i+nBlock-1].u.hdr.size4x |= 2;
  return &mem3.aPool[i];
}

/*
** Carve a piece off of the end of the mem3.iMaster free chunk.
** Return a pointer to the new allocation.  Or, if the master chunk
** Carve a piece off of the end of the mem3.iKeyBlk free chunk.
** Return a pointer to the new allocation.  Or, if the key chunk
** is not large enough, return 0.
*/
static void *memsys3FromMaster(u32 nBlock){
static void *memsys3FromKeyBlk(u32 nBlock){
  assert( sqlite3_mutex_held(mem3.mutex) );
  assert( mem3.szMaster>=nBlock );
  if( nBlock>=mem3.szMaster-1 ){
    /* Use the entire master */
    void *p = memsys3Checkout(mem3.iMaster, mem3.szMaster);
    mem3.iMaster = 0;
    mem3.szMaster = 0;
    mem3.mnMaster = 0;
  assert( mem3.szKeyBlk>=nBlock );
  if( nBlock>=mem3.szKeyBlk-1 ){
    /* Use the entire key chunk */
    void *p = memsys3Checkout(mem3.iKeyBlk, mem3.szKeyBlk);
    mem3.iKeyBlk = 0;
    mem3.szKeyBlk = 0;
    mem3.mnKeyBlk = 0;
    return p;
  }else{
    /* Split the master block.  Return the tail. */
    /* Split the key block.  Return the tail. */
    u32 newi, x;
    newi = mem3.iMaster + mem3.szMaster - nBlock;
    assert( newi > mem3.iMaster+1 );
    mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = nBlock;
    mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x |= 2;
    newi = mem3.iKeyBlk + mem3.szKeyBlk - nBlock;
    assert( newi > mem3.iKeyBlk+1 );
    mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.prevSize = nBlock;
    mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.size4x |= 2;
    mem3.aPool[newi-1].u.hdr.size4x = nBlock*4 + 1;
    mem3.szMaster -= nBlock;
    mem3.aPool[newi-1].u.hdr.prevSize = mem3.szMaster;
    x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
    mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
    if( mem3.szMaster < mem3.mnMaster ){
      mem3.mnMaster = mem3.szMaster;
    mem3.szKeyBlk -= nBlock;
    mem3.aPool[newi-1].u.hdr.prevSize = mem3.szKeyBlk;
    x = mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x & 2;
    mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x = mem3.szKeyBlk*4 | x;
    if( mem3.szKeyBlk < mem3.mnKeyBlk ){
      mem3.mnKeyBlk = mem3.szKeyBlk;
    }
    return (void*)&mem3.aPool[newi];
  }
}

/*
** *pRoot is the head of a list of free chunks of the same size
** or same size hash.  In other words, *pRoot is an entry in either
** mem3.aiSmall[] or mem3.aiHash[].  
**
** This routine examines all entries on the given list and tries
** to coalesce each entries with adjacent free chunks.  
**
** If it sees a chunk that is larger than mem3.iMaster, it replaces 
** the current mem3.iMaster with the new larger chunk.  In order for
** this mem3.iMaster replacement to work, the master chunk must be
** If it sees a chunk that is larger than mem3.iKeyBlk, it replaces 
** the current mem3.iKeyBlk with the new larger chunk.  In order for
** this mem3.iKeyBlk replacement to work, the key chunk must be
** linked into the hash tables.  That is not the normal state of
** affairs, of course.  The calling routine must link the master
** affairs, of course.  The calling routine must link the key
** chunk before invoking this routine, then must unlink the (possibly
** changed) master chunk once this routine has finished.
** changed) key chunk once this routine has finished.
*/
static void memsys3Merge(u32 *pRoot){
  u32 iNext, prev, size, i, x;

  assert( sqlite3_mutex_held(mem3.mutex) );
  for(i=*pRoot; i>0; i=iNext){
    iNext = mem3.aPool[i].u.list.next;
333
334
335
336
337
338
339
340
341
342



343
344
345
346
347
348
349
333
334
335
336
337
338
339



340
341
342
343
344
345
346
347
348
349







-
-
-
+
+
+







      mem3.aPool[prev-1].u.hdr.size4x = size*4 | x;
      mem3.aPool[prev+size-1].u.hdr.prevSize = size;
      memsys3Link(prev);
      i = prev;
    }else{
      size /= 4;
    }
    if( size>mem3.szMaster ){
      mem3.iMaster = i;
      mem3.szMaster = size;
    if( size>mem3.szKeyBlk ){
      mem3.iKeyBlk = i;
      mem3.szKeyBlk = size;
    }
  }
}

/*
** Return a block of memory of at least nBytes in size.
** Return NULL if unable.
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
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







-
+

-
-
+
+





-
+

-
+




-
-
-
-
+
+
+
+







-
-
-
-
+
+
+
+







        return memsys3Checkout(i, nBlock);
      }
    }
  }

  /* STEP 2:
  ** Try to satisfy the allocation by carving a piece off of the end
  ** of the master chunk.  This step usually works if step 1 fails.
  ** of the key chunk.  This step usually works if step 1 fails.
  */
  if( mem3.szMaster>=nBlock ){
    return memsys3FromMaster(nBlock);
  if( mem3.szKeyBlk>=nBlock ){
    return memsys3FromKeyBlk(nBlock);
  }


  /* STEP 3:  
  ** Loop through the entire memory pool.  Coalesce adjacent free
  ** chunks.  Recompute the master chunk as the largest free chunk.
  ** chunks.  Recompute the key chunk as the largest free chunk.
  ** Then try again to satisfy the allocation by carving a piece off
  ** of the end of the master chunk.  This step happens very
  ** of the end of the key chunk.  This step happens very
  ** rarely (we hope!)
  */
  for(toFree=nBlock*16; toFree<(mem3.nPool*16); toFree *= 2){
    memsys3OutOfMemory(toFree);
    if( mem3.iMaster ){
      memsys3Link(mem3.iMaster);
      mem3.iMaster = 0;
      mem3.szMaster = 0;
    if( mem3.iKeyBlk ){
      memsys3Link(mem3.iKeyBlk);
      mem3.iKeyBlk = 0;
      mem3.szKeyBlk = 0;
    }
    for(i=0; i<N_HASH; i++){
      memsys3Merge(&mem3.aiHash[i]);
    }
    for(i=0; i<MX_SMALL-1; i++){
      memsys3Merge(&mem3.aiSmall[i]);
    }
    if( mem3.szMaster ){
      memsys3Unlink(mem3.iMaster);
      if( mem3.szMaster>=nBlock ){
        return memsys3FromMaster(nBlock);
    if( mem3.szKeyBlk ){
      memsys3Unlink(mem3.iKeyBlk);
      if( mem3.szKeyBlk>=nBlock ){
        return memsys3FromKeyBlk(nBlock);
      }
    }
  }

  /* If none of the above worked, then we fail. */
  return 0;
}
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
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







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

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







  size = mem3.aPool[i-1].u.hdr.size4x/4;
  assert( i+size<=mem3.nPool+1 );
  mem3.aPool[i-1].u.hdr.size4x &= ~1;
  mem3.aPool[i+size-1].u.hdr.prevSize = size;
  mem3.aPool[i+size-1].u.hdr.size4x &= ~2;
  memsys3Link(i);

  /* Try to expand the master using the newly freed chunk */
  if( mem3.iMaster ){
    while( (mem3.aPool[mem3.iMaster-1].u.hdr.size4x&2)==0 ){
      size = mem3.aPool[mem3.iMaster-1].u.hdr.prevSize;
      mem3.iMaster -= size;
      mem3.szMaster += size;
      memsys3Unlink(mem3.iMaster);
      x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
      mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
      mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = mem3.szMaster;
  /* Try to expand the key using the newly freed chunk */
  if( mem3.iKeyBlk ){
    while( (mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x&2)==0 ){
      size = mem3.aPool[mem3.iKeyBlk-1].u.hdr.prevSize;
      mem3.iKeyBlk -= size;
      mem3.szKeyBlk += size;
      memsys3Unlink(mem3.iKeyBlk);
      x = mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x & 2;
      mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x = mem3.szKeyBlk*4 | x;
      mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.prevSize = mem3.szKeyBlk;
    }
    x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
    while( (mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x&1)==0 ){
      memsys3Unlink(mem3.iMaster+mem3.szMaster);
      mem3.szMaster += mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x/4;
      mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
      mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = mem3.szMaster;
    x = mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x & 2;
    while( (mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.size4x&1)==0 ){
      memsys3Unlink(mem3.iKeyBlk+mem3.szKeyBlk);
      mem3.szKeyBlk += mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.size4x/4;
      mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x = mem3.szKeyBlk*4 | x;
      mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.prevSize = mem3.szKeyBlk;
    }
  }
}

/*
** Return the size of an outstanding allocation, in bytes.  The
** size returned omits the 8-byte header overhead.  This only
556
557
558
559
560
561
562
563
564
565
566
567





568
569
570
571
572
573
574
556
557
558
559
560
561
562





563
564
565
566
567
568
569
570
571
572
573
574







-
-
-
-
-
+
+
+
+
+







  }

  /* Store a pointer to the memory block in global structure mem3. */
  assert( sizeof(Mem3Block)==8 );
  mem3.aPool = (Mem3Block *)sqlite3GlobalConfig.pHeap;
  mem3.nPool = (sqlite3GlobalConfig.nHeap / sizeof(Mem3Block)) - 2;

  /* Initialize the master block. */
  mem3.szMaster = mem3.nPool;
  mem3.mnMaster = mem3.szMaster;
  mem3.iMaster = 1;
  mem3.aPool[0].u.hdr.size4x = (mem3.szMaster<<2) + 2;
  /* Initialize the key block. */
  mem3.szKeyBlk = mem3.nPool;
  mem3.mnKeyBlk = mem3.szKeyBlk;
  mem3.iKeyBlk = 1;
  mem3.aPool[0].u.hdr.size4x = (mem3.szKeyBlk<<2) + 2;
  mem3.aPool[mem3.nPool].u.hdr.prevSize = mem3.nPool;
  mem3.aPool[mem3.nPool].u.hdr.size4x = 1;

  return SQLITE_OK;
}

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







-
+




















-
-
-
+
+
+







      assert( 0 );
      break;
    }
    if( size&1 ){
      fprintf(out, "%p %6d bytes checked out\n", &mem3.aPool[i], (size/4)*8-8);
    }else{
      fprintf(out, "%p %6d bytes free%s\n", &mem3.aPool[i], (size/4)*8-8,
                  i==mem3.iMaster ? " **master**" : "");
                  i==mem3.iKeyBlk ? " **key**" : "");
    }
  }
  for(i=0; i<MX_SMALL-1; i++){
    if( mem3.aiSmall[i]==0 ) continue;
    fprintf(out, "small(%2d):", i);
    for(j = mem3.aiSmall[i]; j>0; j=mem3.aPool[j].u.list.next){
      fprintf(out, " %p(%d)", &mem3.aPool[j],
              (mem3.aPool[j-1].u.hdr.size4x/4)*8-8);
    }
    fprintf(out, "\n"); 
  }
  for(i=0; i<N_HASH; i++){
    if( mem3.aiHash[i]==0 ) continue;
    fprintf(out, "hash(%2d):", i);
    for(j = mem3.aiHash[i]; j>0; j=mem3.aPool[j].u.list.next){
      fprintf(out, " %p(%d)", &mem3.aPool[j],
              (mem3.aPool[j-1].u.hdr.size4x/4)*8-8);
    }
    fprintf(out, "\n"); 
  }
  fprintf(out, "master=%d\n", mem3.iMaster);
  fprintf(out, "nowUsed=%d\n", mem3.nPool*8 - mem3.szMaster*8);
  fprintf(out, "mxUsed=%d\n", mem3.nPool*8 - mem3.mnMaster*8);
  fprintf(out, "key=%d\n", mem3.iKeyBlk);
  fprintf(out, "nowUsed=%d\n", mem3.nPool*8 - mem3.szKeyBlk*8);
  fprintf(out, "mxUsed=%d\n", mem3.nPool*8 - mem3.mnKeyBlk*8);
  sqlite3_mutex_leave(mem3.mutex);
  if( out==stdout ){
    fflush(stdout);
  }else{
    fclose(out);
  }
#else

Changes to src/mem5.c.

416
417
418
419
420
421
422





423
424






425
426
427
428
429
430
431
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







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







**
** All allocations must be a power of two and must be expressed by a
** 32-bit signed integer.  Hence the largest allocation is 0x40000000
** or 1073741824 bytes.
*/
static int memsys5Roundup(int n){
  int iFullSz;
  if( n<=mem5.szAtom*2 ){
    if( n<=mem5.szAtom ) return mem5.szAtom;
    return mem5.szAtom*2;
  }
  if( n>0x10000000 ){
  if( n > 0x40000000 ) return 0;
  for(iFullSz=mem5.szAtom; iFullSz<n; iFullSz *= 2);
    if( n>0x40000000 ) return 0;
    if( n>0x20000000 ) return 0x40000000;
    return 0x20000000;
  }
  for(iFullSz=mem5.szAtom*8; iFullSz<n; iFullSz *= 4);
  if( (iFullSz/2)>=(i64)n ) return iFullSz/2;
  return iFullSz;
}

/*
** Return the ceiling of the logarithm base 2 of iValue.
**
** Examples:   memsys5Log(1) -> 0

Changes to src/memdb.c.

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







-
+






+






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

+
-
+

+


+
+
+
+
+
+
+
+
+
+



+
+
+
+
+
+
+
+
+
+
+










+







** This file implements an in-memory VFS. A database is held as a contiguous
** block of memory.
**
** This file also implements interface sqlite3_serialize() and
** sqlite3_deserialize().
*/
#include "sqliteInt.h"
#ifdef SQLITE_ENABLE_DESERIALIZE
#ifndef SQLITE_OMIT_DESERIALIZE

/*
** Forward declaration of objects used by this utility
*/
typedef struct sqlite3_vfs MemVfs;
typedef struct MemFile MemFile;
typedef struct MemStore MemStore;

/* Access to a lower-level VFS that (might) implement dynamic loading,
** access to randomness, etc.
*/
#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData))

/* Storage for a memdb file.
**
** An memdb object can be shared or separate.  Shared memdb objects can be
** used by more than one database connection.  Mutexes are used by shared
** memdb objects to coordinate access.  Separate memdb objects are only
** connected to a single database connection and do not require additional
/* An open file */
struct MemFile {
** mutexes.
**
** Shared memdb objects have .zFName!=0 and .pMutex!=0.  They are created
** using "file:/name?vfs=memdb".  The first character of the name must be
** "/" or else the object will be a separate memdb object.  All shared
** memdb objects are stored in memdb_g.apMemStore[] in an arbitrary order.
**
** Separate memdb objects are created using a name that does not begin
** with "/" or using sqlite3_deserialize().
**
** Access rules for shared MemStore objects:
**
**   *  .zFName is initialized when the object is created and afterwards
**      is unchanged until the object is destroyed.  So it can be accessed
**      at any time as long as we know the object is not being destroyed,
**      which means while either the SQLITE_MUTEX_STATIC_VFS1 or
**      .pMutex is held or the object is not part of memdb_g.apMemStore[].
**
**   *  Can .pMutex can only be changed while holding the 
**      SQLITE_MUTEX_STATIC_VFS1 mutex or while the object is not part
**      of memdb_g.apMemStore[].
**
**   *  Other fields can only be changed while holding the .pMutex mutex
**      or when the .nRef is less than zero and the object is not part of
**      memdb_g.apMemStore[].
**
**   *  The .aData pointer has the added requirement that it can can only
**      be changed (for resizing) when nMmap is zero.
**      
*/
struct MemStore {
  sqlite3_file base;              /* IO methods */
  sqlite3_int64 sz;               /* Size of the file */
  sqlite3_int64 szAlloc;          /* Space allocated to aData */
  sqlite3_int64 szMax;            /* Space allocated to aData */
  sqlite3_int64 szMax;            /* Maximum allowed size of the file */
  unsigned char *aData;           /* content of the file */
  sqlite3_mutex *pMutex;          /* Used by shared stores only */
  int nMmap;                      /* Number of memory mapped pages */
  unsigned mFlags;                /* Flags */
  int nRdLock;                    /* Number of readers */
  int nWrLock;                    /* Number of writers.  (Always 0 or 1) */
  int nRef;                       /* Number of users of this MemStore */
  char *zFName;                   /* The filename for shared stores */
};

/* An open file */
struct MemFile {
  sqlite3_file base;              /* IO methods */
  MemStore *pStore;               /* The storage */
  int eLock;                      /* Most recent lock against this file */
};

/*
** File-scope variables for holding the memdb files that are accessible
** to multiple database connections in separate threads.
**
** Must hold SQLITE_MUTEX_STATIC_VFS1 to access any part of this object.
*/
static struct MemFS {
  int nMemStore;                  /* Number of shared MemStore objects */
  MemStore **apMemStore;          /* Array of all shared MemStore objects */
} memdb_g;

/*
** Methods for MemFile
*/
static int memdbClose(sqlite3_file*);
static int memdbRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
static int memdbWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
static int memdbTruncate(sqlite3_file*, sqlite3_int64 size);
static int memdbSync(sqlite3_file*, int flags);
static int memdbFileSize(sqlite3_file*, sqlite3_int64 *pSize);
static int memdbLock(sqlite3_file*, int);
static int memdbUnlock(sqlite3_file*, int);
/* static int memdbCheckReservedLock(sqlite3_file*, int *pResOut);// not used */
static int memdbFileControl(sqlite3_file*, int op, void *pArg);
/* static int memdbSectorSize(sqlite3_file*); // not used */
static int memdbDeviceCharacteristics(sqlite3_file*);
static int memdbFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
static int memdbUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p);

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







-
+
+
+
+











-
+












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




+
-
+
-
-


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












-
+
+



+



+






-
+

-
+


+
+
+
+
+
-
-
+
+

-
+












-
+
+
+
+
+
+
+
+


-
-
+
+

+






+











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






+
+







-
+
+

+







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



-
+

+
-
+






+





-
+

+




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
















+













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





-
+
+
+
+

+









-
+



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



-
+







  memdbDlError,                /* xDlError */
  memdbDlSym,                  /* xDlSym */
  memdbDlClose,                /* xDlClose */
  memdbRandomness,             /* xRandomness */
  memdbSleep,                  /* xSleep */
  0, /* memdbCurrentTime, */   /* xCurrentTime */
  memdbGetLastError,           /* xGetLastError */
  memdbCurrentTimeInt64        /* xCurrentTimeInt64 */
  memdbCurrentTimeInt64,       /* xCurrentTimeInt64 */
  0,                           /* xSetSystemCall */
  0,                           /* xGetSystemCall */
  0,                           /* xNextSystemCall */
};

static const sqlite3_io_methods memdb_io_methods = {
  3,                              /* iVersion */
  memdbClose,                      /* xClose */
  memdbRead,                       /* xRead */
  memdbWrite,                      /* xWrite */
  memdbTruncate,                   /* xTruncate */
  memdbSync,                       /* xSync */
  memdbFileSize,                   /* xFileSize */
  memdbLock,                       /* xLock */
  memdbLock,                       /* xUnlock - same as xLock in this case */ 
  memdbUnlock,                     /* xUnlock */
  0, /* memdbCheckReservedLock, */ /* xCheckReservedLock */
  memdbFileControl,                /* xFileControl */
  0, /* memdbSectorSize,*/         /* xSectorSize */
  memdbDeviceCharacteristics,      /* xDeviceCharacteristics */
  0,                               /* xShmMap */
  0,                               /* xShmLock */
  0,                               /* xShmBarrier */
  0,                               /* xShmUnmap */
  memdbFetch,                      /* xFetch */
  memdbUnfetch                     /* xUnfetch */
};

/*
** Enter/leave the mutex on a MemStore
*/
#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE==0
static void memdbEnter(MemStore *p){
  UNUSED_PARAMETER(p);
}
static void memdbLeave(MemStore *p){
  UNUSED_PARAMETER(p);
}
#else
static void memdbEnter(MemStore *p){
  sqlite3_mutex_enter(p->pMutex);
}
static void memdbLeave(MemStore *p){
  sqlite3_mutex_leave(p->pMutex);
}
#endif



/*
** Close an memdb-file.
** Free the underlying MemStore object when its refcount drops to zero
**
** or less.
** The pData pointer is owned by the application, so there is nothing
** to free.
*/
static int memdbClose(sqlite3_file *pFile){
  MemFile *p = (MemFile *)pFile;
  if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ) sqlite3_free(p->aData);
  MemStore *p = ((MemFile*)pFile)->pStore;
  if( p->zFName ){
    int i;
#ifndef SQLITE_MUTEX_OMIT
    sqlite3_mutex *pVfsMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
#endif
    sqlite3_mutex_enter(pVfsMutex);
    for(i=0; ALWAYS(i<memdb_g.nMemStore); i++){
      if( memdb_g.apMemStore[i]==p ){
        memdbEnter(p);
        if( p->nRef==1 ){
          memdb_g.apMemStore[i] = memdb_g.apMemStore[--memdb_g.nMemStore];
          if( memdb_g.nMemStore==0 ){
            sqlite3_free(memdb_g.apMemStore);
            memdb_g.apMemStore = 0;
          }
        }
        break;
      }
    }
    sqlite3_mutex_leave(pVfsMutex);
  }else{
    memdbEnter(p);
  }
  p->nRef--;
  if( p->nRef<=0 ){
    if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ){
      sqlite3_free(p->aData);
    }
    memdbLeave(p);
    sqlite3_mutex_free(p->pMutex);
    sqlite3_free(p);
  }else{
    memdbLeave(p);
  }
  return SQLITE_OK;
}

/*
** Read data from an memdb-file.
*/
static int memdbRead(
  sqlite3_file *pFile, 
  void *zBuf, 
  int iAmt, 
  sqlite_int64 iOfst
){
  MemFile *p = (MemFile *)pFile;
  MemStore *p = ((MemFile*)pFile)->pStore;
  memdbEnter(p);
  if( iOfst+iAmt>p->sz ){
    memset(zBuf, 0, iAmt);
    if( iOfst<p->sz ) memcpy(zBuf, p->aData+iOfst, p->sz - iOfst);
    memdbLeave(p);
    return SQLITE_IOERR_SHORT_READ;
  }
  memcpy(zBuf, p->aData+iOfst, iAmt);
  memdbLeave(p);
  return SQLITE_OK;
}

/*
** Try to enlarge the memory allocation to hold at least sz bytes
*/
static int memdbEnlarge(MemFile *p, sqlite3_int64 newSz){
static int memdbEnlarge(MemStore *p, sqlite3_int64 newSz){
  unsigned char *pNew;
  if( (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)==0 || p->nMmap>0 ){
  if( (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)==0 || NEVER(p->nMmap>0) ){
    return SQLITE_FULL;
  }
  if( newSz>p->szMax ){
    return SQLITE_FULL;
  }
  newSz *= 2;
  if( newSz>p->szMax ) newSz = p->szMax;
  pNew = sqlite3_realloc64(p->aData, newSz);
  if( pNew==0 ) return SQLITE_NOMEM;
  pNew = sqlite3Realloc(p->aData, newSz);
  if( pNew==0 ) return SQLITE_IOERR_NOMEM;
  p->aData = pNew;
  p->szMax = newSz;
  p->szAlloc = newSz;
  return SQLITE_OK;
}

/*
** Write data to an memdb-file.
*/
static int memdbWrite(
  sqlite3_file *pFile,
  const void *z,
  int iAmt,
  sqlite_int64 iOfst
){
  MemFile *p = (MemFile *)pFile;
  MemStore *p = ((MemFile*)pFile)->pStore;
  memdbEnter(p);
  if( NEVER(p->mFlags & SQLITE_DESERIALIZE_READONLY) ){
    /* Can't happen: memdbLock() will return SQLITE_READONLY before
    ** reaching this point */
    memdbLeave(p);
    return SQLITE_IOERR_WRITE;
  }
  if( iOfst+iAmt>p->sz ){
    int rc;
    if( iOfst+iAmt>p->szMax
     && (rc = memdbEnlarge(p, (iOfst+iAmt)*2))!=SQLITE_OK
    if( iOfst+iAmt>p->szAlloc
     && (rc = memdbEnlarge(p, iOfst+iAmt))!=SQLITE_OK
    ){
      memdbLeave(p);
      return rc;
    }
    if( iOfst>p->sz ) memset(p->aData+p->sz, 0, iOfst-p->sz);
    p->sz = iOfst+iAmt;
  }
  memcpy(p->aData+iOfst, z, iAmt);
  memdbLeave(p);
  return SQLITE_OK;
}

/*
** Truncate an memdb-file.
**
** In rollback mode (which is always the case for memdb, as it does not
** support WAL mode) the truncate() method is only used to reduce
** the size of a file, never to increase the size.
*/
static int memdbTruncate(sqlite3_file *pFile, sqlite_int64 size){
  MemFile *p = (MemFile *)pFile;
  if( NEVER(size>p->sz) ) return SQLITE_FULL;
  p->sz = size; 
  return SQLITE_OK;
  MemStore *p = ((MemFile*)pFile)->pStore;
  int rc = SQLITE_OK;
  memdbEnter(p);
  if( size>p->sz ){
    /* This can only happen with a corrupt wal mode db */
    rc = SQLITE_CORRUPT;
  }else{
    p->sz = size; 
  }
  memdbLeave(p);
  return rc;
}

/*
** Sync an memdb-file.
*/
static int memdbSync(sqlite3_file *pFile, int flags){
  UNUSED_PARAMETER(pFile);
  UNUSED_PARAMETER(flags);
  return SQLITE_OK;
}

/*
** Return the current file-size of an memdb-file.
*/
static int memdbFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
  MemFile *p = (MemFile *)pFile;
  MemStore *p = ((MemFile*)pFile)->pStore;
  memdbEnter(p);
  *pSize = p->sz;
  memdbLeave(p);
  return SQLITE_OK;
}

/*
** Lock an memdb-file.
*/
static int memdbLock(sqlite3_file *pFile, int eLock){
  MemFile *pThis = (MemFile*)pFile;
  MemStore *p = pThis->pStore;
  int rc = SQLITE_OK;
  if( eLock<=pThis->eLock ) return SQLITE_OK;
  memdbEnter(p);
  MemFile *p = (MemFile *)pFile;
  p->eLock = eLock;

  assert( p->nWrLock==0 || p->nWrLock==1 );
  assert( pThis->eLock<=SQLITE_LOCK_SHARED || p->nWrLock==1 );
  assert( pThis->eLock==SQLITE_LOCK_NONE || p->nRdLock>=1 );

  if( eLock>SQLITE_LOCK_SHARED && (p->mFlags & SQLITE_DESERIALIZE_READONLY) ){
    rc = SQLITE_READONLY;
  }else{
    switch( eLock ){
      case SQLITE_LOCK_SHARED: {
        assert( pThis->eLock==SQLITE_LOCK_NONE );
        if( p->nWrLock>0 ){
          rc = SQLITE_BUSY;
        }else{
          p->nRdLock++;
        }
        break;
      };
  
      case SQLITE_LOCK_RESERVED:
      case SQLITE_LOCK_PENDING: {
        assert( pThis->eLock>=SQLITE_LOCK_SHARED );
        if( ALWAYS(pThis->eLock==SQLITE_LOCK_SHARED) ){
          if( p->nWrLock>0 ){
            rc = SQLITE_BUSY;
          }else{
            p->nWrLock = 1;
          }
        }
        break;
      }
  
      default: {
        assert(  eLock==SQLITE_LOCK_EXCLUSIVE );
        assert( pThis->eLock>=SQLITE_LOCK_SHARED );
        if( p->nRdLock>1 ){
          rc = SQLITE_BUSY;
        }else if( pThis->eLock==SQLITE_LOCK_SHARED ){
          p->nWrLock = 1;
        }
        break;
      }
    }
  }
  if( rc==SQLITE_OK ) pThis->eLock = eLock;
  memdbLeave(p);
  return rc;
}

/*
** Unlock an memdb-file.
*/
static int memdbUnlock(sqlite3_file *pFile, int eLock){
  MemFile *pThis = (MemFile*)pFile;
  MemStore *p = pThis->pStore;
  if( eLock>=pThis->eLock ) return SQLITE_OK;
  memdbEnter(p);

  assert( eLock==SQLITE_LOCK_SHARED || eLock==SQLITE_LOCK_NONE );
  if( eLock==SQLITE_LOCK_SHARED ){
    if( ALWAYS(pThis->eLock>SQLITE_LOCK_SHARED) ){
      p->nWrLock--;
    }
  }else{
    if( pThis->eLock>SQLITE_LOCK_SHARED ){
      p->nWrLock--;
    }
    p->nRdLock--;
  }

  pThis->eLock = eLock;
  memdbLeave(p);
  return SQLITE_OK;
}

#if 0 /* Never used because memdbAccess() always returns false */
#if 0
/*
** This interface is only used for crash recovery, which does not
** Check if another file-handle holds a RESERVED lock on an memdb-file.
** occur on an in-memory database.
*/
static int memdbCheckReservedLock(sqlite3_file *pFile, int *pResOut){
  *pResOut = 0;
  return SQLITE_OK;
}
#endif


/*
** File control method. For custom operations on an memdb-file.
*/
static int memdbFileControl(sqlite3_file *pFile, int op, void *pArg){
  MemFile *p = (MemFile *)pFile;
  MemStore *p = ((MemFile*)pFile)->pStore;
  int rc = SQLITE_NOTFOUND;
  memdbEnter(p);
  if( op==SQLITE_FCNTL_VFSNAME ){
    *(char**)pArg = sqlite3_mprintf("memdb(%p,%lld)", p->aData, p->sz);
    rc = SQLITE_OK;
  }
  if( op==SQLITE_FCNTL_SIZE_LIMIT ){
    sqlite3_int64 iLimit = *(sqlite3_int64*)pArg;
    if( iLimit<p->sz ){
      if( iLimit<0 ){
        iLimit = p->szMax;
      }else{
        iLimit = p->sz;
      }
    }
    p->szMax = iLimit;
    *(sqlite3_int64*)pArg = iLimit;
    rc = SQLITE_OK;
  }
  memdbLeave(p);
  return rc;
}

#if 0  /* Not used because of SQLITE_IOCAP_POWERSAFE_OVERWRITE */
/*
** Return the sector-size in bytes for an memdb-file.
*/
static int memdbSectorSize(sqlite3_file *pFile){
  return 1024;
}
#endif

/*
** Return the device characteristic flags supported by an memdb-file.
*/
static int memdbDeviceCharacteristics(sqlite3_file *pFile){
  UNUSED_PARAMETER(pFile);
  return SQLITE_IOCAP_ATOMIC | 
         SQLITE_IOCAP_POWERSAFE_OVERWRITE |
         SQLITE_IOCAP_SAFE_APPEND |
         SQLITE_IOCAP_SEQUENTIAL;
}

/* Fetch a page of a memory-mapped file */
static int memdbFetch(
  sqlite3_file *pFile,
  sqlite3_int64 iOfst,
  int iAmt,
  void **pp
){
  MemFile *p = (MemFile *)pFile;
  p->nMmap++;
  *pp = (void*)(p->aData + iOfst);
  MemStore *p = ((MemFile*)pFile)->pStore;
  memdbEnter(p);
  if( iOfst+iAmt>p->sz || (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)!=0 ){
    *pp = 0;
  }else{
    p->nMmap++;
    *pp = (void*)(p->aData + iOfst);
  }
  memdbLeave(p);
  return SQLITE_OK;
}

/* Release a memory-mapped page */
static int memdbUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
  MemFile *p = (MemFile *)pFile;
  MemStore *p = ((MemFile*)pFile)->pStore;
  UNUSED_PARAMETER(iOfst);
  UNUSED_PARAMETER(pPage);
  memdbEnter(p);
  p->nMmap--;
  memdbLeave(p);
  return SQLITE_OK;
}

/*
** Open an mem file handle.
*/
static int memdbOpen(
  sqlite3_vfs *pVfs,
  const char *zName,
  sqlite3_file *pFile,
  sqlite3_file *pFd,
  int flags,
  int *pOutFlags
){
  MemFile *p = (MemFile*)pFile;
  if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){
    return ORIGVFS(pVfs)->xOpen(ORIGVFS(pVfs), zName, pFile, flags, pOutFlags);
  }
  memset(p, 0, sizeof(*p));
  p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE;
  assert( pOutFlags!=0 );  /* True because flags==SQLITE_OPEN_MAIN_DB */
  *pOutFlags = flags | SQLITE_OPEN_MEMORY;
  p->base.pMethods = &memdb_io_methods;
  MemFile *pFile = (MemFile*)pFd;
  MemStore *p = 0;
  int szName;
  UNUSED_PARAMETER(pVfs);

  memset(pFile, 0, sizeof(*pFile));
  szName = sqlite3Strlen30(zName);
  if( szName>1 && (zName[0]=='/' || zName[0]=='\\') ){
    int i;
#ifndef SQLITE_MUTEX_OMIT
    sqlite3_mutex *pVfsMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
#endif
    sqlite3_mutex_enter(pVfsMutex);
    for(i=0; i<memdb_g.nMemStore; i++){
      if( strcmp(memdb_g.apMemStore[i]->zFName,zName)==0 ){
        p = memdb_g.apMemStore[i];
        break;
      }
    }
    if( p==0 ){
      MemStore **apNew;
      p = sqlite3Malloc( sizeof(*p) + szName + 3 );
      if( p==0 ){
        sqlite3_mutex_leave(pVfsMutex);
        return SQLITE_NOMEM;
      }
      apNew = sqlite3Realloc(memdb_g.apMemStore,
                             sizeof(apNew[0])*(memdb_g.nMemStore+1) );
      if( apNew==0 ){
        sqlite3_free(p);
        sqlite3_mutex_leave(pVfsMutex);
        return SQLITE_NOMEM;
      }
      apNew[memdb_g.nMemStore++] = p;
      memdb_g.apMemStore = apNew;
      memset(p, 0, sizeof(*p));
      p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE|SQLITE_DESERIALIZE_FREEONCLOSE;
      p->szMax = sqlite3GlobalConfig.mxMemdbSize;
      p->zFName = (char*)&p[1];
      memcpy(p->zFName, zName, szName+1);
      p->pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
      if( p->pMutex==0 ){
        memdb_g.nMemStore--;
        sqlite3_free(p);
        sqlite3_mutex_leave(pVfsMutex);
        return SQLITE_NOMEM;
      }
      p->nRef = 1;
      memdbEnter(p);
    }else{
      memdbEnter(p);
      p->nRef++;
    }
    sqlite3_mutex_leave(pVfsMutex);
  }else{
    p = sqlite3Malloc( sizeof(*p) );
    if( p==0 ){
      return SQLITE_NOMEM;
    }
    memset(p, 0, sizeof(*p));
    p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE;
    p->szMax = sqlite3GlobalConfig.mxMemdbSize;
  }
  pFile->pStore = p;
  if( pOutFlags!=0 ){
    *pOutFlags = flags | SQLITE_OPEN_MEMORY;
  }
  pFd->pMethods = &memdb_io_methods;
  memdbLeave(p);
  return SQLITE_OK;
}

#if 0 /* Only used to delete rollback journals, master journals, and WAL
#if 0 /* Only used to delete rollback journals, super-journals, and WAL
      ** files, none of which exist in memdb.  So this routine is never used */
/*
** Delete the file located at zPath. If the dirSync argument is true,
** ensure the file-system modifications are synced to disk before
** returning.
*/
static int memdbDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
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
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







+
+
+















+







*/
static int memdbAccess(
  sqlite3_vfs *pVfs, 
  const char *zPath, 
  int flags, 
  int *pResOut
){
  UNUSED_PARAMETER(pVfs);
  UNUSED_PARAMETER(zPath);
  UNUSED_PARAMETER(flags);
  *pResOut = 0;
  return SQLITE_OK;
}

/*
** Populate buffer zOut with the full canonical pathname corresponding
** to the pathname in zPath. zOut is guaranteed to point to a buffer
** of at least (INST_MAX_PATHNAME+1) bytes.
*/
static int memdbFullPathname(
  sqlite3_vfs *pVfs, 
  const char *zPath, 
  int nOut, 
  char *zOut
){
  UNUSED_PARAMETER(pVfs);
  sqlite3_snprintf(nOut, zOut, "%s", zPath);
  return SQLITE_OK;
}

/*
** Open the dynamic library located at zPath and return a handle.
*/
421
422
423
424
425
426
427

428
429
430




431
432
433
434
435
436
437
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750







+



+
+
+
+








/*
** Translate a database connection pointer and schema name into a
** MemFile pointer.
*/
static MemFile *memdbFromDbSchema(sqlite3 *db, const char *zSchema){
  MemFile *p = 0;
  MemStore *pStore;
  int rc = sqlite3_file_control(db, zSchema, SQLITE_FCNTL_FILE_POINTER, &p);
  if( rc ) return 0;
  if( p->base.pMethods!=&memdb_io_methods ) return 0;
  pStore = p->pStore;
  memdbEnter(pStore);
  if( pStore->zFName!=0 ) p = 0;
  memdbLeave(pStore);
  return p;
}

/*
** Return the serialization of a database
*/
unsigned char *sqlite3_serialize(
459
460
461
462
463
464
465


466

467
468

469
470
471


472
473
474
475
476
477
478
772
773
774
775
776
777
778
779
780

781
782

783
784


785
786
787
788
789
790
791
792
793







+
+
-
+

-
+

-
-
+
+








  if( zSchema==0 ) zSchema = db->aDb[0].zDbSName;
  p = memdbFromDbSchema(db, zSchema);
  iDb = sqlite3FindDbName(db, zSchema);
  if( piSize ) *piSize = -1;
  if( iDb<0 ) return 0;
  if( p ){
    MemStore *pStore = p->pStore;
    assert( pStore->pMutex==0 );
    if( piSize ) *piSize = p->sz;
    if( piSize ) *piSize = pStore->sz;
    if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
      pOut = p->aData;
      pOut = pStore->aData;
    }else{
      pOut = sqlite3_malloc64( p->sz );
      if( pOut ) memcpy(pOut, p->aData, p->sz);
      pOut = sqlite3_malloc64( pStore->sz );
      if( pOut ) memcpy(pOut, pStore->aData, pStore->sz);
    }
    return pOut;
  }
  pBt = db->aDb[iDb].pBt;
  if( pBt==0 ) return 0;
  szPage = sqlite3BtreeGetPageSize(pBt);
  zSql = sqlite3_mprintf("PRAGMA \"%w\".page_count", zSchema);
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

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
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917

918
919




920
921
922
923
924
925
926
927

928







+
-
+


-
+

+
+
+
-
-
+
+
+













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





+
+
+



+
+
+
+
+
+
+







+
+
-
+

-
-
-
-
+
+
+
+
+



-
+
  if( szDb<0 ) return SQLITE_MISUSE_BKPT;
  if( szBuf<0 ) return SQLITE_MISUSE_BKPT;
#endif

  sqlite3_mutex_enter(db->mutex);
  if( zSchema==0 ) zSchema = db->aDb[0].zDbSName;
  iDb = sqlite3FindDbName(db, zSchema);
  testcase( iDb==1 );
  if( iDb<0 ){
  if( iDb<2 && iDb!=0 ){
    rc = SQLITE_ERROR;
    goto end_deserialize;
  }    
  }
  zSql = sqlite3_mprintf("ATTACH x AS %Q", zSchema);
  if( zSql==0 ){
    rc = SQLITE_NOMEM;
  }else{
  rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
  sqlite3_free(zSql);
    rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
    sqlite3_free(zSql);
  }
  if( rc ) goto end_deserialize;
  db->init.iDb = (u8)iDb;
  db->init.reopenMemdb = 1;
  rc = sqlite3_step(pStmt);
  db->init.reopenMemdb = 0;
  if( rc!=SQLITE_DONE ){
    rc = SQLITE_ERROR;
    goto end_deserialize;
  }
  p = memdbFromDbSchema(db, zSchema);
  if( p==0 ){
    rc = SQLITE_ERROR;
  }else{
    MemStore *pStore = p->pStore;
    p->aData = pData;
    p->sz = szDb;
    p->szMax = szBuf;
    p->mFlags = mFlags;
    pStore->aData = pData;
    pData = 0;
    pStore->sz = szDb;
    pStore->szAlloc = szBuf;
    pStore->szMax = szBuf;
    if( pStore->szMax<sqlite3GlobalConfig.mxMemdbSize ){
      pStore->szMax = sqlite3GlobalConfig.mxMemdbSize;
    }
    pStore->mFlags = mFlags;
    rc = SQLITE_OK;
  }

end_deserialize:
  sqlite3_finalize(pStmt);
  if( pData && (mFlags & SQLITE_DESERIALIZE_FREEONCLOSE)!=0 ){
    sqlite3_free(pData);
  }
  sqlite3_mutex_leave(db->mutex);
  return rc;
}

/*
** Return true if the VFS is the memvfs.
*/
int sqlite3IsMemdb(const sqlite3_vfs *pVfs){
  return pVfs==&memdb_vfs;
}

/* 
** This routine is called when the extension is loaded.
** Register the new VFS.
*/
int sqlite3MemdbInit(void){
  sqlite3_vfs *pLower = sqlite3_vfs_find(0);
  unsigned int sz;
  if( NEVER(pLower==0) ) return SQLITE_ERROR;
  int sz = pLower->szOsFile;
  sz = pLower->szOsFile;
  memdb_vfs.pAppData = pLower;
  /* In all known configurations of SQLite, the size of a default
  ** sqlite3_file is greater than the size of a memdb sqlite3_file.
  ** Should that ever change, remove the following NEVER() */
  if( NEVER(sz<sizeof(MemFile)) ) sz = sizeof(MemFile);
  /* The following conditional can only be true when compiled for
  ** Windows x86 and SQLITE_MAX_MMAP_SIZE=0.  We always leave
  ** it in, to be safe, but it is marked as NO_TEST since there
  ** is no way to reach it under most builds. */
  if( sz<sizeof(MemFile) ) sz = sizeof(MemFile); /*NO_TEST*/
  memdb_vfs.szOsFile = sz;
  return sqlite3_vfs_register(&memdb_vfs, 0);
}
#endif /* SQLITE_ENABLE_DESERIALIZE */
#endif /* SQLITE_OMIT_DESERIALIZE */

Changes to src/memjournal.c.

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

73
74
75
76
77
78
79







-







** is an instance of this class.
*/
struct MemJournal {
  const sqlite3_io_methods *pMethod; /* Parent class. MUST BE FIRST */
  int nChunkSize;                 /* In-memory chunk-size */

  int nSpill;                     /* Bytes of data before flushing */
  int nSize;                      /* Bytes of data currently in memory */
  FileChunk *pFirst;              /* Head of in-memory chunk-list */
  FilePoint endpoint;             /* Pointer to the end of the file */
  FilePoint readpoint;            /* Pointer to the end of the last xRead() */

  int flags;                      /* xOpen flags */
  sqlite3_vfs *pVfs;              /* The "real" underlying VFS */
  const char *zJournal;           /* Name of the journal file */
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
91
92
93
94
95
96
97


98
99
100



101
102
103
104
105
106
107







-
-



-
-
-







){
  MemJournal *p = (MemJournal *)pJfd;
  u8 *zOut = zBuf;
  int nRead = iAmt;
  int iChunkOffset;
  FileChunk *pChunk;

#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \
 || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
  if( (iAmt+iOfst)>p->endpoint.iOffset ){
    return SQLITE_IOERR_SHORT_READ;
  }
#endif

  assert( (iAmt+iOfst)<=p->endpoint.iOffset );
  assert( p->readpoint.iOffset==0 || p->readpoint.pChunk!=0 );
  if( p->readpoint.iOffset!=iOfst || iOfst==0 ){
    sqlite3_int64 iOff = 0;
    for(pChunk=p->pFirst; 
        ALWAYS(pChunk) && (iOff+p->nChunkSize)<=iOfst;
        pChunk=pChunk->pNext
    ){
132
133
134
135
136
137
138
139

140
141
142

143
144
145
146
147
148
149
150
151
152
153
126
127
128
129
130
131
132

133
134
135

136
137
138
139

140
141
142
143
144
145
146







-
+


-
+



-








  return SQLITE_OK;
}

/*
** Free the list of FileChunk structures headed at MemJournal.pFirst.
*/
static void memjrnlFreeChunks(MemJournal *p){
static void memjrnlFreeChunks(FileChunk *pFirst){
  FileChunk *pIter;
  FileChunk *pNext;
  for(pIter=p->pFirst; pIter; pIter=pNext){
  for(pIter=pFirst; pIter; pIter=pNext){
    pNext = pIter->pNext;
    sqlite3_free(pIter);
  } 
  p->pFirst = 0;
}

/*
** Flush the contents of memory to a real file on disk.
*/
static int memjrnlCreateFile(MemJournal *p){
  int rc;
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
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







-
+














+
+
+







      }
      rc = sqlite3OsWrite(pReal, (u8*)pIter->zChunk, nChunk, iOff);
      if( rc ) break;
      iOff += nChunk;
    }
    if( rc==SQLITE_OK ){
      /* No error has occurred. Free the in-memory buffers. */
      memjrnlFreeChunks(&copy);
      memjrnlFreeChunks(copy.pFirst);
    }
  }
  if( rc!=SQLITE_OK ){
    /* If an error occurred while creating or writing to the file, restore
    ** the original before returning. This way, SQLite uses the in-memory
    ** journal data to roll back changes made to the internal page-cache
    ** before this function was called.  */
    sqlite3OsClose(pReal);
    *p = copy;
  }
  return rc;
}


/* Forward reference */
static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size);

/*
** Write data to the file.
*/
static int memjrnlWrite(
  sqlite3_file *pJfd,    /* The journal file into which to write */
  const void *zBuf,      /* Take data to be written from here */
  int iAmt,              /* Number of bytes to write */
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
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







-
-
-
-
+
+
+
+
+



-
+
-
-
-
-





+














-
+


+
-
+




-







-
+
-
-
-
-



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











-
+








  /* If the contents of this write should be stored in memory */
  else{
    /* An in-memory journal file should only ever be appended to. Random
    ** access writes are not required. The only exception to this is when
    ** the in-memory journal is being used by a connection using the
    ** atomic-write optimization. In this case the first 28 bytes of the
    ** journal file may be written as part of committing the transaction. */ 
    assert( iOfst==p->endpoint.iOffset || iOfst==0 );
#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \
 || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
    ** journal file may be written as part of committing the transaction. */
    assert( iOfst<=p->endpoint.iOffset );
    if( iOfst>0 && iOfst!=p->endpoint.iOffset ){
      memjrnlTruncate(pJfd, iOfst);
    }
    if( iOfst==0 && p->pFirst ){
      assert( p->nChunkSize>iAmt );
      memcpy((u8*)p->pFirst->zChunk, zBuf, iAmt);
    }else
    }else{
#else
    assert( iOfst>0 || p->pFirst==0 );
#endif
    {
      while( nWrite>0 ){
        FileChunk *pChunk = p->endpoint.pChunk;
        int iChunkOffset = (int)(p->endpoint.iOffset%p->nChunkSize);
        int iSpace = MIN(nWrite, p->nChunkSize - iChunkOffset);

        assert( pChunk!=0 || iChunkOffset==0 );
        if( iChunkOffset==0 ){
          /* New chunk is required to extend the file. */
          FileChunk *pNew = sqlite3_malloc(fileChunkSize(p->nChunkSize));
          if( !pNew ){
            return SQLITE_IOERR_NOMEM_BKPT;
          }
          pNew->pNext = 0;
          if( pChunk ){
            assert( p->pFirst );
            pChunk->pNext = pNew;
          }else{
            assert( !p->pFirst );
            p->pFirst = pNew;
          }
          p->endpoint.pChunk = pNew;
          pChunk = p->endpoint.pChunk = pNew;
        }

        assert( pChunk!=0 );
        memcpy((u8*)p->endpoint.pChunk->zChunk + iChunkOffset, zWrite, iSpace);
        memcpy((u8*)pChunk->zChunk + iChunkOffset, zWrite, iSpace);
        zWrite += iSpace;
        nWrite -= iSpace;
        p->endpoint.iOffset += iSpace;
      }
      p->nSize = iAmt + iOfst;
    }
  }

  return SQLITE_OK;
}

/*
** Truncate the file.
** Truncate the in-memory file.
**
** If the journal file is already on disk, truncate it there. Or, if it
** is still in main memory but is being truncated to zero bytes in size,
** ignore 
*/
static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){
  MemJournal *p = (MemJournal *)pJfd;
  assert( p->endpoint.pChunk==0 || p->endpoint.pChunk->pNext==0 );
  if( size<p->endpoint.iOffset ){
    FileChunk *pIter = 0;
    if( size==0 ){
      memjrnlFreeChunks(p->pFirst);
      p->pFirst = 0;
    }else{
      i64 iOff = p->nChunkSize;
      for(pIter=p->pFirst; ALWAYS(pIter) && iOff<size; pIter=pIter->pNext){
        iOff += p->nChunkSize;
      }
  if( ALWAYS(size==0) ){
    memjrnlFreeChunks(p);
    p->nSize = 0;
    p->endpoint.pChunk = 0;
    p->endpoint.iOffset = 0;
      if( ALWAYS(pIter) ){
        memjrnlFreeChunks(pIter->pNext);
        pIter->pNext = 0;
      }
    }

    p->endpoint.pChunk = pIter;
    p->endpoint.iOffset = size;
    p->readpoint.pChunk = 0;
    p->readpoint.iOffset = 0;
  }
  return SQLITE_OK;
}

/*
** Close the file.
*/
static int memjrnlClose(sqlite3_file *pJfd){
  MemJournal *p = (MemJournal *)pJfd;
  memjrnlFreeChunks(p);
  memjrnlFreeChunks(p->pFirst);
  return SQLITE_OK;
}

/*
** Sync the file.
**
** If the real file has been created, call its xSync method. Otherwise, 
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
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







+
+

















-
+







  sqlite3_vfs *pVfs,         /* The VFS to use for actual file I/O */
  const char *zName,         /* Name of the journal file */
  sqlite3_file *pJfd,        /* Preallocated, blank file handle */
  int flags,                 /* Opening flags */
  int nSpill                 /* Bytes buffered before opening the file */
){
  MemJournal *p = (MemJournal*)pJfd;

  assert( zName || nSpill<0 || (flags & SQLITE_OPEN_EXCLUSIVE) );

  /* Zero the file-handle object. If nSpill was passed zero, initialize
  ** it using the sqlite3OsOpen() function of the underlying VFS. In this
  ** case none of the code in this module is executed as a result of calls
  ** made on the journal file-handle.  */
  memset(p, 0, sizeof(MemJournal));
  if( nSpill==0 ){
    return sqlite3OsOpen(pVfs, zName, pJfd, flags, 0);
  }

  if( nSpill>0 ){
    p->nChunkSize = nSpill;
  }else{
    p->nChunkSize = 8 + MEMJOURNAL_DFLT_FILECHUNKSIZE - sizeof(FileChunk);
    assert( MEMJOURNAL_DFLT_FILECHUNKSIZE==fileChunkSize(p->nChunkSize) );
  }

  p->pMethod = (const sqlite3_io_methods*)&MemJournalMethods;
  pJfd->pMethods = (const sqlite3_io_methods*)&MemJournalMethods;
  p->nSpill = nSpill;
  p->flags = flags;
  p->zJournal = zName;
  p->pVfs = pVfs;
  return SQLITE_OK;
}

393
394
395
396
397
398
399
400

401
402
403
404
405
406
407
399
400
401
402
403
404
405

406
407
408
409
410
411
412
413







-
+







** in-memory-only journal file (i.e. is one that was opened with a +ve
** nSpill parameter or as SQLITE_OPEN_MAIN_JOURNAL), and the underlying 
** file has not yet been created, create it now.
*/
int sqlite3JournalCreate(sqlite3_file *pJfd){
  int rc = SQLITE_OK;
  MemJournal *p = (MemJournal*)pJfd;
  if( p->pMethod==&MemJournalMethods && (
  if( pJfd->pMethods==&MemJournalMethods && (
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
     p->nSpill>0
#else
     /* While this appears to not be possible without ATOMIC_WRITE, the
     ** paths are complex, so it seems prudent to leave the test in as
     ** a NEVER(), in case our analysis is subtly flawed. */
     NEVER(p->nSpill>0)

Changes to src/msvc.h.

29
30
31
32
33
34
35





36
29
30
31
32
33
34
35
36
37
38
39
40
41







+
+
+
+
+

#pragma warning(disable : 4244)
#pragma warning(disable : 4305)
#pragma warning(disable : 4306)
#pragma warning(disable : 4702)
#pragma warning(disable : 4706)
#endif /* defined(_MSC_VER) */

#if defined(_MSC_VER) && !defined(_WIN64)
#undef SQLITE_4_BYTE_ALIGNED_MALLOC
#define SQLITE_4_BYTE_ALIGNED_MALLOC
#endif /* defined(_MSC_VER) && !defined(_WIN64) */

#endif /* SQLITE_MSVC_H */

Changes to src/mutex.c.

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







+







  assert( sqlite3GlobalConfig.mutex.xMutexInit );
  rc = sqlite3GlobalConfig.mutex.xMutexInit();

#ifdef SQLITE_DEBUG
  GLOBAL(int, mutexIsInit) = 1;
#endif

  sqlite3MemoryBarrier();
  return rc;
}

/*
** Shutdown the mutex system. This call frees resources allocated by
** sqlite3MutexInit().
*/

Changes to src/mutex.h.

63
64
65
66
67
68
69

70
63
64
65
66
67
68
69
70
71







+

#define sqlite3_mutex_notheld(X)  ((void)(X),1)
#define sqlite3MutexAlloc(X)      ((sqlite3_mutex*)8)
#define sqlite3MutexInit()        SQLITE_OK
#define sqlite3MutexEnd()
#define MUTEX_LOGIC(X)
#else
#define MUTEX_LOGIC(X)            X
int sqlite3_mutex_held(sqlite3_mutex*);
#endif /* defined(SQLITE_MUTEX_OMIT) */

Changes to src/mutex_unix.c.

108
109
110
111
112
113
114
115

116
117
118
119
120
121
122
108
109
110
111
112
113
114

115
116
117
118
119
120
121
122







-
+







** that means that a mutex could not be allocated.  SQLite
** will unwind its stack and return an error.  The argument
** to sqlite3_mutex_alloc() is one of these integer constants:
**
** <ul>
** <li>  SQLITE_MUTEX_FAST
** <li>  SQLITE_MUTEX_RECURSIVE
** <li>  SQLITE_MUTEX_STATIC_MASTER
** <li>  SQLITE_MUTEX_STATIC_MAIN
** <li>  SQLITE_MUTEX_STATIC_MEM
** <li>  SQLITE_MUTEX_STATIC_OPEN
** <li>  SQLITE_MUTEX_STATIC_PRNG
** <li>  SQLITE_MUTEX_STATIC_LRU
** <li>  SQLITE_MUTEX_STATIC_PMEM
** <li>  SQLITE_MUTEX_STATIC_APP1
** <li>  SQLITE_MUTEX_STATIC_APP2

Changes to src/mutex_w32.c.

167
168
169
170
171
172
173
174

175
176
177
178
179
180
181
167
168
169
170
171
172
173

174
175
176
177
178
179
180
181







-
+







** that means that a mutex could not be allocated.  SQLite
** will unwind its stack and return an error.  The argument
** to sqlite3_mutex_alloc() is one of these integer constants:
**
** <ul>
** <li>  SQLITE_MUTEX_FAST
** <li>  SQLITE_MUTEX_RECURSIVE
** <li>  SQLITE_MUTEX_STATIC_MASTER
** <li>  SQLITE_MUTEX_STATIC_MAIN
** <li>  SQLITE_MUTEX_STATIC_MEM
** <li>  SQLITE_MUTEX_STATIC_OPEN
** <li>  SQLITE_MUTEX_STATIC_PRNG
** <li>  SQLITE_MUTEX_STATIC_LRU
** <li>  SQLITE_MUTEX_STATIC_PMEM
** <li>  SQLITE_MUTEX_STATIC_APP1
** <li>  SQLITE_MUTEX_STATIC_APP2

Changes to src/notify.c.

25
26
27
28
29
30
31
32

33
34
35
36
37

38
39
40
41
42
43
44
25
26
27
28
29
30
31

32
33
34
35
36

37
38
39
40
41
42
43
44







-
+




-
+







**   sqlite3ConnectionBlocked()
**   sqlite3ConnectionUnlocked()
**   sqlite3ConnectionClosed()
**   sqlite3_unlock_notify()
*/

#define assertMutexHeld() \
  assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)) )
  assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN)) )

/*
** Head of a linked list of all sqlite3 objects created by this process
** for which either sqlite3.pBlockingConnection or sqlite3.pUnlockConnection
** is not NULL. This variable may only accessed while the STATIC_MASTER
** is not NULL. This variable may only accessed while the STATIC_MAIN
** mutex is held.
*/
static sqlite3 *SQLITE_WSD sqlite3BlockedList = 0;

#ifndef NDEBUG
/*
** This function is a complex assert() that verifies the following 
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
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







-
+


-
+




-
+




-
+







    pp=&(*pp)->pNextBlocked
  );
  db->pNextBlocked = *pp;
  *pp = db;
}

/*
** Obtain the STATIC_MASTER mutex.
** Obtain the STATIC_MAIN mutex.
*/
static void enterMutex(void){
  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN));
  checkListProperties(0);
}

/*
** Release the STATIC_MASTER mutex.
** Release the STATIC_MAIN mutex.
*/
static void leaveMutex(void){
  assertMutexHeld();
  checkListProperties(0);
  sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
  sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN));
}

/*
** Register an unlock-notify callback.
**
** This is called after connection "db" has attempted some operation
** but has received an SQLITE_LOCKED error because another connection
228
229
230
231
232
233
234
235

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

235
236
237
238
239
240
241
242







-
+







  int nArg = 0;                            /* Number of entries in aArg[] */
  sqlite3 **pp;                            /* Iterator variable */
  void **aArg;               /* Arguments to the unlock callback */
  void **aDyn = 0;           /* Dynamically allocated space for aArg[] */
  void *aStatic[16];         /* Starter space for aArg[].  No malloc required */

  aArg = aStatic;
  enterMutex();         /* Enter STATIC_MASTER mutex */
  enterMutex();         /* Enter STATIC_MAIN mutex */

  /* This loop runs once for each entry in the blocked-connections list. */
  for(pp=&sqlite3BlockedList; *pp; /* no-op */ ){
    sqlite3 *p = *pp;

    /* Step 1. */
    if( p->pBlockingConnection==db ){
311
312
313
314
315
316
317
318

319
320
321
322
323
324
325
311
312
313
314
315
316
317

318
319
320
321
322
323
324
325







-
+







    }
  }

  if( nArg!=0 ){
    xUnlockNotify(aArg, nArg);
  }
  sqlite3_free(aDyn);
  leaveMutex();         /* Leave STATIC_MASTER mutex */
  leaveMutex();         /* Leave STATIC_MAIN mutex */
}

/*
** This is called when the database connection passed as an argument is 
** being closed. The connection is removed from the blocked list.
*/
void sqlite3ConnectionClosed(sqlite3 *db){

Changes to src/os.c.

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







+



+




















+
+










-
+
+
+
+
+
+














+







}
int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){
  DO_OS_MALLOC_TEST(id);
  return id->pMethods->xFileSize(id, pSize);
}
int sqlite3OsLock(sqlite3_file *id, int lockType){
  DO_OS_MALLOC_TEST(id);
  assert( lockType>=SQLITE_LOCK_SHARED && lockType<=SQLITE_LOCK_EXCLUSIVE );
  return id->pMethods->xLock(id, lockType);
}
int sqlite3OsUnlock(sqlite3_file *id, int lockType){
  assert( lockType==SQLITE_LOCK_NONE || lockType==SQLITE_LOCK_SHARED );
  return id->pMethods->xUnlock(id, lockType);
}
int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut){
  DO_OS_MALLOC_TEST(id);
  return id->pMethods->xCheckReservedLock(id, pResOut);
}

/*
** Use sqlite3OsFileControl() when we are doing something that might fail
** and we need to know about the failures.  Use sqlite3OsFileControlHint()
** when simply tossing information over the wall to the VFS and we do not
** really care if the VFS receives and understands the information since it
** is only a hint and can be safely ignored.  The sqlite3OsFileControlHint()
** routine has no return value since the return value would be meaningless.
*/
int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){
  if( id->pMethods==0 ) return SQLITE_NOTFOUND;
#ifdef SQLITE_TEST
  if( op!=SQLITE_FCNTL_COMMIT_PHASETWO
   && op!=SQLITE_FCNTL_LOCK_TIMEOUT
   && op!=SQLITE_FCNTL_CKPT_DONE
   && op!=SQLITE_FCNTL_CKPT_START
  ){
    /* Faults are not injected into COMMIT_PHASETWO because, assuming SQLite
    ** is using a regular VFS, it is called after the corresponding
    ** transaction has been committed. Injecting a fault at this point
    ** confuses the test scripts - the COMMIT comand returns SQLITE_NOMEM
    ** but the transaction is committed anyway.
    **
    ** The core must call OsFileControl() though, not OsFileControlHint(),
    ** as if a custom VFS (e.g. zipvfs) returns an error here, it probably
    ** means the commit really has failed and an error should be returned
    ** to the user.  */
    ** to the user.
    **
    ** The CKPT_DONE and CKPT_START file-controls are write-only signals
    ** to the cksumvfs.  Their return code is meaningless and is ignored
    ** by the SQLite core, so there is no point in simulating OOMs for them.
    */
    DO_OS_MALLOC_TEST(id);
  }
#endif
  return id->pMethods->xFileControl(id, op, pArg);
}
void sqlite3OsFileControlHint(sqlite3_file *id, int op, void *pArg){
  if( id->pMethods ) (void)id->pMethods->xFileControl(id, op, pArg);
}

int sqlite3OsSectorSize(sqlite3_file *id){
  int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize;
  return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE);
}
int sqlite3OsDeviceCharacteristics(sqlite3_file *id){
  if( NEVER(id->pMethods==0) ) return 0;
  return id->pMethods->xDeviceCharacteristics(id);
}
#ifndef SQLITE_OMIT_WAL
int sqlite3OsShmLock(sqlite3_file *id, int offset, int n, int flags){
  return id->pMethods->xShmLock(id, offset, n, flags);
}
void sqlite3OsShmBarrier(sqlite3_file *id){
211
212
213
214
215
216
217

218

219
220
221
222
223
224
225

226
227
228
229
230
231
232
221
222
223
224
225
226
227
228

229
230
231
232
233
234
235

236
237
238
239
240
241
242
243







+
-
+






-
+







){
  int rc;
  DO_OS_MALLOC_TEST(0);
  /* 0x87f7f is a mask of SQLITE_OPEN_ flags that are valid to be passed
  ** down into the VFS layer.  Some SQLITE_OPEN_ flags (for example,
  ** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before
  ** reaching the VFS. */
  assert( zPath || (flags & SQLITE_OPEN_EXCLUSIVE) );
  rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x87f7f, pFlagsOut);
  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
){
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
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







+
+













+
+
+
+
+
+
-
+
+
+







){
  DO_OS_MALLOC_TEST(0);
  zPathOut[0] = 0;
  return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut);
}
#ifndef SQLITE_OMIT_LOAD_EXTENSION
void *sqlite3OsDlOpen(sqlite3_vfs *pVfs, const char *zPath){
  assert( zPath!=0 );
  assert( strlen(zPath)<=SQLITE_MAX_PATHLEN );  /* tag-20210611-1 */
  return pVfs->xDlOpen(pVfs, zPath);
}
void sqlite3OsDlError(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
  pVfs->xDlError(pVfs, nByte, zBufOut);
}
void (*sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHdle, const char *zSym))(void){
  return pVfs->xDlSym(pVfs, pHdle, zSym);
}
void sqlite3OsDlClose(sqlite3_vfs *pVfs, void *pHandle){
  pVfs->xDlClose(pVfs, pHandle);
}
#endif /* SQLITE_OMIT_LOAD_EXTENSION */
int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
  if( sqlite3Config.iPrngSeed ){
    memset(zBufOut, 0, nByte);
    if( ALWAYS(nByte>(signed)sizeof(unsigned)) ) nByte = sizeof(unsigned int);
    memcpy(zBufOut, &sqlite3Config.iPrngSeed, nByte);
    return SQLITE_OK;
  }else{
  return pVfs->xRandomness(pVfs, nByte, zBufOut);
    return pVfs->xRandomness(pVfs, nByte, zBufOut);
  }
  
}
int sqlite3OsSleep(sqlite3_vfs *pVfs, int nMicro){
  return pVfs->xSleep(pVfs, nMicro);
}
int sqlite3OsGetLastError(sqlite3_vfs *pVfs){
  return pVfs->xGetLastError ? pVfs->xGetLastError(pVfs, 0, 0) : 0;
}
294
295
296
297
298
299
300

301
302
303
304

305
306

307
308
309
310
311
312
313
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337







+




+


+







  int rc;
  sqlite3_file *pFile;
  pFile = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile);
  if( pFile ){
    rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags);
    if( rc!=SQLITE_OK ){
      sqlite3_free(pFile);
      *ppFile = 0;
    }else{
      *ppFile = pFile;
    }
  }else{
    *ppFile = 0;
    rc = SQLITE_NOMEM_BKPT;
  }
  assert( *ppFile!=0 || rc!=SQLITE_OK );
  return rc;
}
void sqlite3OsCloseFree(sqlite3_file *pFile){
  assert( pFile );
  sqlite3OsClose(pFile);
  sqlite3_free(pFile);
}
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
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







-
+














-
+







  sqlite3_mutex *mutex;
#endif
#ifndef SQLITE_OMIT_AUTOINIT
  int rc = sqlite3_initialize();
  if( rc ) return 0;
#endif
#if SQLITE_THREADSAFE
  mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
  mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN);
#endif
  sqlite3_mutex_enter(mutex);
  for(pVfs = vfsList; pVfs; pVfs=pVfs->pNext){
    if( zVfs==0 ) break;
    if( strcmp(zVfs, pVfs->zName)==0 ) break;
  }
  sqlite3_mutex_leave(mutex);
  return pVfs;
}

/*
** Unlink a VFS from the linked list
*/
static void vfsUnlink(sqlite3_vfs *pVfs){
  assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)) );
  assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN)) );
  if( pVfs==0 ){
    /* No-op */
  }else if( vfsList==pVfs ){
    vfsList = pVfs->pNext;
  }else if( vfsList ){
    sqlite3_vfs *p = vfsList;
    while( p->pNext && p->pNext!=pVfs ){
387
388
389
390
391
392
393
394

395
396
397
398
399
400
401
411
412
413
414
415
416
417

418
419
420
421
422
423
424
425







-
+







  int rc = sqlite3_initialize();
  if( rc ) return rc;
#endif
#ifdef SQLITE_ENABLE_API_ARMOR
  if( pVfs==0 ) return SQLITE_MISUSE_BKPT;
#endif

  MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
  MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); )
  sqlite3_mutex_enter(mutex);
  vfsUnlink(pVfs);
  if( makeDflt || vfsList==0 ){
    pVfs->pNext = vfsList;
    vfsList = pVfs;
  }else{
    pVfs->pNext = vfsList->pNext;
411
412
413
414
415
416
417
418

419
420
421
422
423
435
436
437
438
439
440
441

442
443
444
445
446
447







-
+





*/
int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){
  MUTEX_LOGIC(sqlite3_mutex *mutex;)
#ifndef SQLITE_OMIT_AUTOINIT
  int rc = sqlite3_initialize();
  if( rc ) return rc;
#endif
  MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
  MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); )
  sqlite3_mutex_enter(mutex);
  vfsUnlink(pVfs);
  sqlite3_mutex_leave(mutex);
  return SQLITE_OK;
}

Changes to src/os.h.

28
29
30
31
32
33
34













35
36
37
38
39
40
41
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







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








/* If the SET_FULLSYNC macro is not defined above, then make it
** a no-op
*/
#ifndef SET_FULLSYNC
# define SET_FULLSYNC(x,y)
#endif

/* Maximum pathname length.  Note: FILENAME_MAX defined by stdio.h
*/
#ifndef SQLITE_MAX_PATHLEN
# define SQLITE_MAX_PATHLEN FILENAME_MAX
#endif

/* Maximum number of symlinks that will be resolved while trying to
** expand a filename in xFullPathname() in the VFS.
*/
#ifndef SQLITE_MAX_SYMLINK
# define SQLITE_MAX_SYMLINK 200
#endif

/*
** The default size of a disk sector
*/
#ifndef SQLITE_DEFAULT_SECTOR_SIZE
# define SQLITE_DEFAULT_SECTOR_SIZE 4096
#endif

Changes to src/os_common.h.

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







-
-
-
-
-
-








/*
** Macros for performance tracing.  Normally turned off.  Only works
** on i486 hardware.
*/
#ifdef SQLITE_PERFORMANCE_TRACE

/*
** hwtime.h contains inline assembler code for implementing
** high-performance timing routines.
*/
#include "hwtime.h"

static sqlite_uint64 g_start;
static sqlite_uint64 g_elapsed;
#define TIMER_START       g_start=sqlite3Hwtime()
#define TIMER_END         g_elapsed=sqlite3Hwtime()-g_start
#define TIMER_ELAPSED     g_elapsed
#else
#define TIMER_START

Added src/os_kv.c.




















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2022-09-06
**
** 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 contains an experimental VFS layer that operates on a
** Key/Value storage engine where both keys and values must be pure
** text.
*/
#include <sqliteInt.h>
#if SQLITE_OS_KV || (SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL))

/*****************************************************************************
** Debugging logic
*/

/* SQLITE_KV_TRACE() is used for tracing calls to kvstorage routines. */
#if 0
#define SQLITE_KV_TRACE(X)  printf X
#else
#define SQLITE_KV_TRACE(X)
#endif

/* SQLITE_KV_LOG() is used for tracing calls to the VFS interface */
#if 0
#define SQLITE_KV_LOG(X)  printf X
#else
#define SQLITE_KV_LOG(X)
#endif


/*
** Forward declaration of objects used by this VFS implementation
*/
typedef struct KVVfsFile KVVfsFile;

/* A single open file.  There are only two files represented by this
** VFS - the database and the rollback journal.
*/
struct KVVfsFile {
  sqlite3_file base;              /* IO methods */
  const char *zClass;             /* Storage class */
  int isJournal;                  /* True if this is a journal file */
  unsigned int nJrnl;             /* Space allocated for aJrnl[] */
  char *aJrnl;                    /* Journal content */
  int szPage;                     /* Last known page size */
  sqlite3_int64 szDb;             /* Database file size.  -1 means unknown */
  char *aData;                    /* Buffer to hold page data */
};
#define SQLITE_KVOS_SZ 133073

/*
** Methods for KVVfsFile
*/
static int kvvfsClose(sqlite3_file*);
static int kvvfsReadDb(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
static int kvvfsReadJrnl(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
static int kvvfsWriteDb(sqlite3_file*,const void*,int iAmt, sqlite3_int64);
static int kvvfsWriteJrnl(sqlite3_file*,const void*,int iAmt, sqlite3_int64);
static int kvvfsTruncateDb(sqlite3_file*, sqlite3_int64 size);
static int kvvfsTruncateJrnl(sqlite3_file*, sqlite3_int64 size);
static int kvvfsSyncDb(sqlite3_file*, int flags);
static int kvvfsSyncJrnl(sqlite3_file*, int flags);
static int kvvfsFileSizeDb(sqlite3_file*, sqlite3_int64 *pSize);
static int kvvfsFileSizeJrnl(sqlite3_file*, sqlite3_int64 *pSize);
static int kvvfsLock(sqlite3_file*, int);
static int kvvfsUnlock(sqlite3_file*, int);
static int kvvfsCheckReservedLock(sqlite3_file*, int *pResOut);
static int kvvfsFileControlDb(sqlite3_file*, int op, void *pArg);
static int kvvfsFileControlJrnl(sqlite3_file*, int op, void *pArg);
static int kvvfsSectorSize(sqlite3_file*);
static int kvvfsDeviceCharacteristics(sqlite3_file*);

/*
** Methods for sqlite3_vfs
*/
static int kvvfsOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
static int kvvfsDelete(sqlite3_vfs*, const char *zName, int syncDir);
static int kvvfsAccess(sqlite3_vfs*, const char *zName, int flags, int *);
static int kvvfsFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
static void *kvvfsDlOpen(sqlite3_vfs*, const char *zFilename);
static int kvvfsRandomness(sqlite3_vfs*, int nByte, char *zOut);
static int kvvfsSleep(sqlite3_vfs*, int microseconds);
static int kvvfsCurrentTime(sqlite3_vfs*, double*);
static int kvvfsCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);

static sqlite3_vfs sqlite3OsKvvfsObject = {
  1,                              /* iVersion */
  sizeof(KVVfsFile),              /* szOsFile */
  1024,                           /* mxPathname */
  0,                              /* pNext */
  "kvvfs",                        /* zName */
  0,                              /* pAppData */
  kvvfsOpen,                      /* xOpen */
  kvvfsDelete,                    /* xDelete */
  kvvfsAccess,                    /* xAccess */
  kvvfsFullPathname,              /* xFullPathname */
  kvvfsDlOpen,                    /* xDlOpen */
  0,                              /* xDlError */
  0,                              /* xDlSym */
  0,                              /* xDlClose */
  kvvfsRandomness,                /* xRandomness */
  kvvfsSleep,                     /* xSleep */
  kvvfsCurrentTime,               /* xCurrentTime */
  0,                              /* xGetLastError */
  kvvfsCurrentTimeInt64           /* xCurrentTimeInt64 */
};

/* Methods for sqlite3_file objects referencing a database file
*/
static sqlite3_io_methods kvvfs_db_io_methods = {
  1,                              /* iVersion */
  kvvfsClose,                     /* xClose */
  kvvfsReadDb,                    /* xRead */
  kvvfsWriteDb,                   /* xWrite */
  kvvfsTruncateDb,                /* xTruncate */
  kvvfsSyncDb,                    /* xSync */
  kvvfsFileSizeDb,                /* xFileSize */
  kvvfsLock,                      /* xLock */
  kvvfsUnlock,                    /* xUnlock */
  kvvfsCheckReservedLock,         /* xCheckReservedLock */
  kvvfsFileControlDb,             /* xFileControl */
  kvvfsSectorSize,                /* xSectorSize */
  kvvfsDeviceCharacteristics,     /* xDeviceCharacteristics */
  0,                              /* xShmMap */
  0,                              /* xShmLock */
  0,                              /* xShmBarrier */
  0,                              /* xShmUnmap */
  0,                              /* xFetch */
  0                               /* xUnfetch */
};

/* Methods for sqlite3_file objects referencing a rollback journal
*/
static sqlite3_io_methods kvvfs_jrnl_io_methods = {
  1,                              /* iVersion */
  kvvfsClose,                     /* xClose */
  kvvfsReadJrnl,                  /* xRead */
  kvvfsWriteJrnl,                 /* xWrite */
  kvvfsTruncateJrnl,              /* xTruncate */
  kvvfsSyncJrnl,                  /* xSync */
  kvvfsFileSizeJrnl,              /* xFileSize */
  kvvfsLock,                      /* xLock */
  kvvfsUnlock,                    /* xUnlock */
  kvvfsCheckReservedLock,         /* xCheckReservedLock */
  kvvfsFileControlJrnl,           /* xFileControl */
  kvvfsSectorSize,                /* xSectorSize */
  kvvfsDeviceCharacteristics,     /* xDeviceCharacteristics */
  0,                              /* xShmMap */
  0,                              /* xShmLock */
  0,                              /* xShmBarrier */
  0,                              /* xShmUnmap */
  0,                              /* xFetch */
  0                               /* xUnfetch */
};

/****** Storage subsystem **************************************************/
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

/* Forward declarations for the low-level storage engine
*/
static int kvstorageWrite(const char*, const char *zKey, const char *zData);
static int kvstorageDelete(const char*, const char *zKey);
static int kvstorageRead(const char*, const char *zKey, char *zBuf, int nBuf);
#define KVSTORAGE_KEY_SZ  32

/* Expand the key name with an appropriate prefix and put the result
** zKeyOut[].  The zKeyOut[] buffer is assumed to hold at least
** KVSTORAGE_KEY_SZ bytes.
*/
static void kvstorageMakeKey(
  const char *zClass,
  const char *zKeyIn,
  char *zKeyOut
){
  sqlite3_snprintf(KVSTORAGE_KEY_SZ, zKeyOut, "kvvfs-%s-%s", zClass, zKeyIn);
}

/* Write content into a key.  zClass is the particular namespace of the
** underlying key/value store to use - either "local" or "session".
**
** Both zKey and zData are zero-terminated pure text strings.
**
** Return the number of errors.
*/
static int kvstorageWrite(
  const char *zClass,
  const char *zKey,
  const char *zData
){
  FILE *fd;
  char zXKey[KVSTORAGE_KEY_SZ];
  kvstorageMakeKey(zClass, zKey, zXKey);
  fd = fopen(zXKey, "wb");
  if( fd ){
    SQLITE_KV_TRACE(("KVVFS-WRITE  %-15s (%d) %.50s%s\n", zXKey,
                 (int)strlen(zData), zData,
                 strlen(zData)>50 ? "..." : ""));
    fputs(zData, fd);
    fclose(fd);
    return 0;
  }else{
    return 1;
  }
}

/* Delete a key (with its corresponding data) from the key/value
** namespace given by zClass.  If the key does not previously exist,
** this routine is a no-op.
*/
static int kvstorageDelete(const char *zClass, const char *zKey){
  char zXKey[KVSTORAGE_KEY_SZ];
  kvstorageMakeKey(zClass, zKey, zXKey);
  unlink(zXKey);
  SQLITE_KV_TRACE(("KVVFS-DELETE %-15s\n", zXKey));
  return 0;
}

/* Read the value associated with a zKey from the key/value namespace given
** by zClass and put the text data associated with that key in the first
** nBuf bytes of zBuf[].  The value might be truncated if zBuf is not large
** enough to hold it all.  The value put into zBuf must always be zero
** terminated, even if it gets truncated because nBuf is not large enough.
**
** Return the total number of bytes in the data, without truncation, and
** not counting the final zero terminator.   Return -1 if the key does
** not exist.
**
** If nBuf<=0 then this routine simply returns the size of the data without
** actually reading it.
*/
static int kvstorageRead(
  const char *zClass,
  const char *zKey,
  char *zBuf,
  int nBuf
){
  FILE *fd;
  struct stat buf;
  char zXKey[KVSTORAGE_KEY_SZ];
  kvstorageMakeKey(zClass, zKey, zXKey);
  if( access(zXKey, R_OK)!=0
   || stat(zXKey, &buf)!=0
   || !S_ISREG(buf.st_mode)
  ){
    SQLITE_KV_TRACE(("KVVFS-READ   %-15s (-1)\n", zXKey));
    return -1;
  }
  if( nBuf<=0 ){
    return (int)buf.st_size;
  }else if( nBuf==1 ){
    zBuf[0] = 0;
    SQLITE_KV_TRACE(("KVVFS-READ   %-15s (%d)\n", zXKey,
                 (int)buf.st_size));
    return (int)buf.st_size;
  }
  if( nBuf > buf.st_size + 1 ){
    nBuf = buf.st_size + 1;
  }
  fd = fopen(zXKey, "rb");
  if( fd==0 ){
    SQLITE_KV_TRACE(("KVVFS-READ   %-15s (-1)\n", zXKey));
    return -1;
  }else{
    sqlite3_int64 n = fread(zBuf, 1, nBuf-1, fd);
    fclose(fd);
    zBuf[n] = 0;
    SQLITE_KV_TRACE(("KVVFS-READ   %-15s (%lld) %.50s%s\n", zXKey,
                 n, zBuf, n>50 ? "..." : ""));
    return (int)n;
  }
}

/*
** An internal level of indirection which enables us to replace the
** kvvfs i/o methods with JavaScript implementations in WASM builds.
** Maintenance reminder: if this struct changes in any way, the JSON
** rendering of its structure must be updated in
** sqlite3_wasm_enum_json(). There are no binary compatibility
** concerns, so it does not need an iVersion member. This file is
** necessarily always compiled together with sqlite3_wasm_enum_json(),
** and JS code dynamically creates the mapping of members based on
** that JSON description.
*/
typedef struct sqlite3_kvvfs_methods sqlite3_kvvfs_methods;
struct sqlite3_kvvfs_methods {
  int (*xRead)(const char *zClass, const char *zKey, char *zBuf, int nBuf);
  int (*xWrite)(const char *zClass, const char *zKey, const char *zData);
  int (*xDelete)(const char *zClass, const char *zKey);
  const int nKeySize;
};

/*
** This object holds the kvvfs I/O methods which may be swapped out
** for JavaScript-side implementations in WASM builds. In such builds
** it cannot be const, but in native builds it should be so that
** the compiler can hopefully optimize this level of indirection out.
** That said, kvvfs is intended primarily for use in WASM builds.
**
** Note that this is not explicitly flagged as static because the
** amalgamation build will tag it with SQLITE_PRIVATE.
*/
#ifndef SQLITE_WASM
const
#endif
sqlite3_kvvfs_methods sqlite3KvvfsMethods = {
kvstorageRead,
kvstorageWrite,
kvstorageDelete,
KVSTORAGE_KEY_SZ
};

/****** Utility subroutines ************************************************/

/*
** Encode binary into the text encoded used to persist on disk.
** The output text is stored in aOut[], which must be at least
** nData+1 bytes in length.
**
** Return the actual length of the encoded text, not counting the
** zero terminator at the end.
**
** Encoding format
** ---------------
**
**   *  Non-zero bytes are encoded as upper-case hexadecimal
**
**   *  A sequence of one or more zero-bytes that are not at the
**      beginning of the buffer are encoded as a little-endian
**      base-26 number using a..z.  "a" means 0.  "b" means 1,
**      "z" means 25.  "ab" means 26.  "ac" means 52.  And so forth.
**
**   *  Because there is no overlap between the encoding characters
**      of hexadecimal and base-26 numbers, it is always clear where
**      one stops and the next begins.
*/
static int kvvfsEncode(const char *aData, int nData, char *aOut){
  int i, j;
  const unsigned char *a = (const unsigned char*)aData;
  for(i=j=0; i<nData; i++){
    unsigned char c = a[i];
    if( c!=0 ){
      aOut[j++] = "0123456789ABCDEF"[c>>4];
      aOut[j++] = "0123456789ABCDEF"[c&0xf];
    }else{
      /* A sequence of 1 or more zeros is stored as a little-endian
      ** base-26 number using a..z as the digits. So one zero is "b".
      ** Two zeros is "c". 25 zeros is "z", 26 zeros is "ab", 27 is "bb",
      ** and so forth.
      */
      int k;
      for(k=1; i+k<nData && a[i+k]==0; k++){}
      i += k-1;
      while( k>0 ){
        aOut[j++] = 'a'+(k%26);
        k /= 26;
      }
    }
  }
  aOut[j] = 0;
  return j;
}

static const signed char kvvfsHexValue[256] = {
  -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1,
  -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1,
  -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1,
   0,  1,  2,  3,  4,  5,  6,  7,    8,  9, -1, -1, -1, -1, -1, -1,
  -1, 10, 11, 12, 13, 14, 15, -1,   -1, -1, -1, -1, -1, -1, -1, -1,
  -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1,
  -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1,
  -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1,

  -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1,
  -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1,
  -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1,
  -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1,
  -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1,
  -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1,
  -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1,
  -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1
};

/*
** Decode the text encoding back to binary.  The binary content is
** written into pOut, which must be at least nOut bytes in length.
**
** The return value is the number of bytes actually written into aOut[].
*/
static int kvvfsDecode(const char *a, char *aOut, int nOut){
  int i, j;
  int c;
  const unsigned char *aIn = (const unsigned char*)a;
  i = 0;
  j = 0;
  while( 1 ){
    c = kvvfsHexValue[aIn[i]];
    if( c<0 ){
      int n = 0;
      int mult = 1;
      c = aIn[i];
      if( c==0 ) break;
      while( c>='a' && c<='z' ){
        n += (c - 'a')*mult;
        mult *= 26;
        c = aIn[++i];
      }
      if( j+n>nOut ) return -1;
      memset(&aOut[j], 0, n);
      j += n;
      if( c==0 || mult==1 ) break; /* progress stalled if mult==1 */
    }else{
      aOut[j] = c<<4;
      c = kvvfsHexValue[aIn[++i]];
      if( c<0 ) break;
      aOut[j++] += c;
      i++;
    }
  }
  return j;
}

/*
** Decode a complete journal file.  Allocate space in pFile->aJrnl
** and store the decoding there.  Or leave pFile->aJrnl set to NULL
** if an error is encountered.
**
** The first few characters of the text encoding will be a little-endian
** base-26 number (digits a..z) that is the total number of bytes
** in the decoded journal file image.  This base-26 number is followed
** by a single space, then the encoding of the journal.  The space
** separator is required to act as a terminator for the base-26 number.
*/
static void kvvfsDecodeJournal(
  KVVfsFile *pFile,      /* Store decoding in pFile->aJrnl */
  const char *zTxt,      /* Text encoding.  Zero-terminated */
  int nTxt               /* Bytes in zTxt, excluding zero terminator */
){
  unsigned int n = 0;
  int c, i, mult;
  i = 0;
  mult = 1;
  while( (c = zTxt[i++])>='a' && c<='z' ){
    n += (zTxt[i] - 'a')*mult;
    mult *= 26;
  }
  sqlite3_free(pFile->aJrnl);
  pFile->aJrnl = sqlite3_malloc64( n );
  if( pFile->aJrnl==0 ){
    pFile->nJrnl = 0;
    return;
  }
  pFile->nJrnl = n;
  n = kvvfsDecode(zTxt+i, pFile->aJrnl, pFile->nJrnl);
  if( n<pFile->nJrnl ){
    sqlite3_free(pFile->aJrnl);
    pFile->aJrnl = 0;
    pFile->nJrnl = 0;
  }
}

/*
** Read or write the "sz" element, containing the database file size.
*/
static sqlite3_int64 kvvfsReadFileSize(KVVfsFile *pFile){
  char zData[50];
  zData[0] = 0;
  sqlite3KvvfsMethods.xRead(pFile->zClass, "sz", zData, sizeof(zData)-1);
  return strtoll(zData, 0, 0);
}
static int kvvfsWriteFileSize(KVVfsFile *pFile, sqlite3_int64 sz){
  char zData[50];
  sqlite3_snprintf(sizeof(zData), zData, "%lld", sz);
  return sqlite3KvvfsMethods.xWrite(pFile->zClass, "sz", zData);
}

/****** sqlite3_io_methods methods ******************************************/

/*
** Close an kvvfs-file.
*/
static int kvvfsClose(sqlite3_file *pProtoFile){
  KVVfsFile *pFile = (KVVfsFile *)pProtoFile;

  SQLITE_KV_LOG(("xClose %s %s\n", pFile->zClass, 
             pFile->isJournal ? "journal" : "db"));
  sqlite3_free(pFile->aJrnl);
  sqlite3_free(pFile->aData);
  return SQLITE_OK;
}

/*
** Read from the -journal file.
*/
static int kvvfsReadJrnl(
  sqlite3_file *pProtoFile,
  void *zBuf, 
  int iAmt, 
  sqlite_int64 iOfst
){
  KVVfsFile *pFile = (KVVfsFile*)pProtoFile;
  assert( pFile->isJournal );
  SQLITE_KV_LOG(("xRead('%s-journal',%d,%lld)\n", pFile->zClass, iAmt, iOfst));
  if( pFile->aJrnl==0 ){
    int szTxt = kvstorageRead(pFile->zClass, "jrnl", 0, 0);
    char *aTxt;
    if( szTxt<=4 ){
      return SQLITE_IOERR;
    }
    aTxt = sqlite3_malloc64( szTxt+1 );
    if( aTxt==0 ) return SQLITE_NOMEM;
    kvstorageRead(pFile->zClass, "jrnl", aTxt, szTxt+1);
    kvvfsDecodeJournal(pFile, aTxt, szTxt);
    sqlite3_free(aTxt);
    if( pFile->aJrnl==0 ) return SQLITE_IOERR;
  }
  if( iOfst+iAmt>pFile->nJrnl ){
    return SQLITE_IOERR_SHORT_READ;
  }
  memcpy(zBuf, pFile->aJrnl+iOfst, iAmt);
  return SQLITE_OK;
}

/*
** Read from the database file.
*/
static int kvvfsReadDb(
  sqlite3_file *pProtoFile,
  void *zBuf, 
  int iAmt, 
  sqlite_int64 iOfst
){
  KVVfsFile *pFile = (KVVfsFile*)pProtoFile;
  unsigned int pgno;
  int got, n;
  char zKey[30];
  char *aData = pFile->aData;
  assert( iOfst>=0 );
  assert( iAmt>=0 );
  SQLITE_KV_LOG(("xRead('%s-db',%d,%lld)\n", pFile->zClass, iAmt, iOfst));
  if( iOfst+iAmt>=512 ){
    if( (iOfst % iAmt)!=0 ){
      return SQLITE_IOERR_READ;
    }
    if( (iAmt & (iAmt-1))!=0 || iAmt<512 || iAmt>65536 ){
      return SQLITE_IOERR_READ;
    }
    pFile->szPage = iAmt;
    pgno = 1 + iOfst/iAmt;
  }else{
    pgno = 1;
  }
  sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno);
  got = sqlite3KvvfsMethods.xRead(pFile->zClass, zKey,
                                  aData, SQLITE_KVOS_SZ-1);
  if( got<0 ){
    n = 0;
  }else{
    aData[got] = 0;
    if( iOfst+iAmt<512 ){
      int k = iOfst+iAmt;
      aData[k*2] = 0;
      n = kvvfsDecode(aData, &aData[2000], SQLITE_KVOS_SZ-2000);
      if( n>=iOfst+iAmt ){
        memcpy(zBuf, &aData[2000+iOfst], iAmt);
        n = iAmt;
      }else{
        n = 0;
      }
    }else{
      n = kvvfsDecode(aData, zBuf, iAmt);
    }
  }
  if( n<iAmt ){
    memset(zBuf+n, 0, iAmt-n);
    return SQLITE_IOERR_SHORT_READ;
  }
  return SQLITE_OK;
}


/*
** Write into the -journal file.
*/
static int kvvfsWriteJrnl(
  sqlite3_file *pProtoFile,
  const void *zBuf, 
  int iAmt, 
  sqlite_int64 iOfst
){
  KVVfsFile *pFile = (KVVfsFile*)pProtoFile;
  sqlite3_int64 iEnd = iOfst+iAmt;
  SQLITE_KV_LOG(("xWrite('%s-journal',%d,%lld)\n", pFile->zClass, iAmt, iOfst));
  if( iEnd>=0x10000000 ) return SQLITE_FULL;
  if( pFile->aJrnl==0 || pFile->nJrnl<iEnd ){
    char *aNew = sqlite3_realloc(pFile->aJrnl, iEnd);
    if( aNew==0 ){
      return SQLITE_IOERR_NOMEM;
    }
    pFile->aJrnl = aNew;
    if( pFile->nJrnl<iOfst ){
      memset(pFile->aJrnl+pFile->nJrnl, 0, iOfst-pFile->nJrnl);
    }
    pFile->nJrnl = iEnd;
  }
  memcpy(pFile->aJrnl+iOfst, zBuf, iAmt);
  return SQLITE_OK;
}

/*
** Write into the database file.
*/
static int kvvfsWriteDb(
  sqlite3_file *pProtoFile,
  const void *zBuf, 
  int iAmt, 
  sqlite_int64 iOfst
){
  KVVfsFile *pFile = (KVVfsFile*)pProtoFile;
  unsigned int pgno;
  char zKey[30];
  char *aData = pFile->aData;
  SQLITE_KV_LOG(("xWrite('%s-db',%d,%lld)\n", pFile->zClass, iAmt, iOfst));
  assert( iAmt>=512 && iAmt<=65536 );
  assert( (iAmt & (iAmt-1))==0 );
  assert( pFile->szPage<0 || pFile->szPage==iAmt );
  pFile->szPage = iAmt;
  pgno = 1 + iOfst/iAmt;
  sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno);
  kvvfsEncode(zBuf, iAmt, aData);
  if( sqlite3KvvfsMethods.xWrite(pFile->zClass, zKey, aData) ){
    return SQLITE_IOERR;
  }
  if( iOfst+iAmt > pFile->szDb ){
    pFile->szDb = iOfst + iAmt;
  }
  return SQLITE_OK;
}

/*
** Truncate an kvvfs-file.
*/
static int kvvfsTruncateJrnl(sqlite3_file *pProtoFile, sqlite_int64 size){
  KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
  SQLITE_KV_LOG(("xTruncate('%s-journal',%lld)\n", pFile->zClass, size));
  assert( size==0 );
  sqlite3KvvfsMethods.xDelete(pFile->zClass, "jrnl");
  sqlite3_free(pFile->aJrnl);
  pFile->aJrnl = 0;
  pFile->nJrnl = 0;
  return SQLITE_OK;
}
static int kvvfsTruncateDb(sqlite3_file *pProtoFile, sqlite_int64 size){
  KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
  if( pFile->szDb>size
   && pFile->szPage>0 
   && (size % pFile->szPage)==0
  ){
    char zKey[50];
    unsigned int pgno, pgnoMax;
    SQLITE_KV_LOG(("xTruncate('%s-db',%lld)\n", pFile->zClass, size));
    pgno = 1 + size/pFile->szPage;
    pgnoMax = 2 + pFile->szDb/pFile->szPage;
    while( pgno<=pgnoMax ){
      sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno);
      sqlite3KvvfsMethods.xDelete(pFile->zClass, zKey);
      pgno++;
    }
    pFile->szDb = size;
    return kvvfsWriteFileSize(pFile, size) ? SQLITE_IOERR : SQLITE_OK;
  }
  return SQLITE_IOERR;
}

/*
** Sync an kvvfs-file.
*/
static int kvvfsSyncJrnl(sqlite3_file *pProtoFile, int flags){
  int i, n;
  KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
  char *zOut;
  SQLITE_KV_LOG(("xSync('%s-journal')\n", pFile->zClass));
  if( pFile->nJrnl<=0 ){
    return kvvfsTruncateJrnl(pProtoFile, 0);
  }
  zOut = sqlite3_malloc64( pFile->nJrnl*2 + 50 );
  if( zOut==0 ){
    return SQLITE_IOERR_NOMEM;
  }
  n = pFile->nJrnl;
  i = 0;
  do{
    zOut[i++] = 'a' + (n%26);
    n /= 26;
  }while( n>0 );
  zOut[i++] = ' ';
  kvvfsEncode(pFile->aJrnl, pFile->nJrnl, &zOut[i]);
  i = sqlite3KvvfsMethods.xWrite(pFile->zClass, "jrnl", zOut);
  sqlite3_free(zOut);
  return i ? SQLITE_IOERR : SQLITE_OK;
}
static int kvvfsSyncDb(sqlite3_file *pProtoFile, int flags){
  return SQLITE_OK;
}

/*
** Return the current file-size of an kvvfs-file.
*/
static int kvvfsFileSizeJrnl(sqlite3_file *pProtoFile, sqlite_int64 *pSize){
  KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
  SQLITE_KV_LOG(("xFileSize('%s-journal')\n", pFile->zClass));
  *pSize = pFile->nJrnl;
  return SQLITE_OK;
}
static int kvvfsFileSizeDb(sqlite3_file *pProtoFile, sqlite_int64 *pSize){
  KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
  SQLITE_KV_LOG(("xFileSize('%s-db')\n", pFile->zClass));
  if( pFile->szDb>=0 ){
    *pSize = pFile->szDb;
  }else{
    *pSize = kvvfsReadFileSize(pFile);
  }
  return SQLITE_OK;
}

/*
** Lock an kvvfs-file.
*/
static int kvvfsLock(sqlite3_file *pProtoFile, int eLock){
  KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
  assert( !pFile->isJournal );
  SQLITE_KV_LOG(("xLock(%s,%d)\n", pFile->zClass, eLock));

  if( eLock!=SQLITE_LOCK_NONE ){
    pFile->szDb = kvvfsReadFileSize(pFile);
  }
  return SQLITE_OK;
}

/*
** Unlock an kvvfs-file.
*/
static int kvvfsUnlock(sqlite3_file *pProtoFile, int eLock){
  KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
  assert( !pFile->isJournal );
  SQLITE_KV_LOG(("xUnlock(%s,%d)\n", pFile->zClass, eLock));
  if( eLock==SQLITE_LOCK_NONE ){
    pFile->szDb = -1;
  }
  return SQLITE_OK;
}

/*
** Check if another file-handle holds a RESERVED lock on an kvvfs-file.
*/
static int kvvfsCheckReservedLock(sqlite3_file *pProtoFile, int *pResOut){
  SQLITE_KV_LOG(("xCheckReservedLock\n"));
  *pResOut = 0;
  return SQLITE_OK;
}

/*
** File control method. For custom operations on an kvvfs-file.
*/
static int kvvfsFileControlJrnl(sqlite3_file *pProtoFile, int op, void *pArg){
  SQLITE_KV_LOG(("xFileControl(%d) on journal\n", op));
  return SQLITE_NOTFOUND;
}
static int kvvfsFileControlDb(sqlite3_file *pProtoFile, int op, void *pArg){
  SQLITE_KV_LOG(("xFileControl(%d) on database\n", op));
  if( op==SQLITE_FCNTL_SYNC ){
    KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
    int rc = SQLITE_OK;
    SQLITE_KV_LOG(("xSync('%s-db')\n", pFile->zClass));
    if( pFile->szDb>0 && 0!=kvvfsWriteFileSize(pFile, pFile->szDb) ){
      rc = SQLITE_IOERR;
    }
    return rc;
  }
  return SQLITE_NOTFOUND;
}

/*
** Return the sector-size in bytes for an kvvfs-file.
*/
static int kvvfsSectorSize(sqlite3_file *pFile){
  return 512;
}

/*
** Return the device characteristic flags supported by an kvvfs-file.
*/
static int kvvfsDeviceCharacteristics(sqlite3_file *pProtoFile){
  return 0;
}

/****** sqlite3_vfs methods *************************************************/

/*
** Open an kvvfs file handle.
*/
static int kvvfsOpen(
  sqlite3_vfs *pProtoVfs,
  const char *zName,
  sqlite3_file *pProtoFile,
  int flags,
  int *pOutFlags
){
  KVVfsFile *pFile = (KVVfsFile*)pProtoFile;
  if( zName==0 ) zName = "";
  SQLITE_KV_LOG(("xOpen(\"%s\")\n", zName));
  if( strcmp(zName, "local")==0
   || strcmp(zName, "session")==0
  ){
    pFile->isJournal = 0;
    pFile->base.pMethods = &kvvfs_db_io_methods;
  }else
  if( strcmp(zName, "local-journal")==0 
   || strcmp(zName, "session-journal")==0
  ){
    pFile->isJournal = 1;
    pFile->base.pMethods = &kvvfs_jrnl_io_methods;
  }else{
    return SQLITE_CANTOPEN;
  }
  if( zName[0]=='s' ){
    pFile->zClass = "session";
  }else{
    pFile->zClass = "local";
  }
  pFile->aData = sqlite3_malloc64(SQLITE_KVOS_SZ);
  if( pFile->aData==0 ){
    return SQLITE_NOMEM;
  }
  pFile->aJrnl = 0;
  pFile->nJrnl = 0;
  pFile->szPage = -1;
  pFile->szDb = -1;
  return SQLITE_OK;
}

/*
** Delete the file located at zPath. If the dirSync argument is true,
** ensure the file-system modifications are synced to disk before
** returning.
*/
static int kvvfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
  if( strcmp(zPath, "local-journal")==0 ){
    sqlite3KvvfsMethods.xDelete("local", "jrnl");
  }else
  if( strcmp(zPath, "session-journal")==0 ){
    sqlite3KvvfsMethods.xDelete("session", "jrnl");
  }
  return SQLITE_OK;
}

/*
** Test for access permissions. Return true if the requested permission
** is available, or false otherwise.
*/
static int kvvfsAccess(
  sqlite3_vfs *pProtoVfs, 
  const char *zPath, 
  int flags, 
  int *pResOut
){
  SQLITE_KV_LOG(("xAccess(\"%s\")\n", zPath));
  if( strcmp(zPath, "local-journal")==0 ){
    *pResOut = sqlite3KvvfsMethods.xRead("local", "jrnl", 0, 0)>0;
  }else
  if( strcmp(zPath, "session-journal")==0 ){
    *pResOut = sqlite3KvvfsMethods.xRead("session", "jrnl", 0, 0)>0;
  }else
  if( strcmp(zPath, "local")==0 ){
    *pResOut = sqlite3KvvfsMethods.xRead("local", "sz", 0, 0)>0;
  }else
  if( strcmp(zPath, "session")==0 ){
    *pResOut = sqlite3KvvfsMethods.xRead("session", "sz", 0, 0)>0;
  }else
  {
    *pResOut = 0;
  }
  SQLITE_KV_LOG(("xAccess returns %d\n",*pResOut));
  return SQLITE_OK;
}

/*
** Populate buffer zOut with the full canonical pathname corresponding
** to the pathname in zPath. zOut is guaranteed to point to a buffer
** of at least (INST_MAX_PATHNAME+1) bytes.
*/
static int kvvfsFullPathname(
  sqlite3_vfs *pVfs, 
  const char *zPath, 
  int nOut, 
  char *zOut
){
  size_t nPath;
#ifdef SQLITE_OS_KV_ALWAYS_LOCAL
  zPath = "local";
#endif
  nPath = strlen(zPath);
  SQLITE_KV_LOG(("xFullPathname(\"%s\")\n", zPath));
  if( nOut<nPath+1 ) nPath = nOut - 1;
  memcpy(zOut, zPath, nPath);
  zOut[nPath] = 0;
  return SQLITE_OK;
}

/*
** Open the dynamic library located at zPath and return a handle.
*/
static void *kvvfsDlOpen(sqlite3_vfs *pVfs, const char *zPath){
  return 0;
}

/*
** Populate the buffer pointed to by zBufOut with nByte bytes of 
** random data.
*/
static int kvvfsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
  memset(zBufOut, 0, nByte);
  return nByte;
}

/*
** Sleep for nMicro microseconds. Return the number of microseconds 
** actually slept.
*/
static int kvvfsSleep(sqlite3_vfs *pVfs, int nMicro){
  return SQLITE_OK;
}

/*
** Return the current time as a Julian Day number in *pTimeOut.
*/
static int kvvfsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
  sqlite3_int64 i = 0;
  int rc;
  rc = kvvfsCurrentTimeInt64(0, &i);
  *pTimeOut = i/86400000.0;
  return rc;
}
#include <sys/time.h>
static int kvvfsCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){
  static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
  struct timeval sNow;
  (void)gettimeofday(&sNow, 0);  /* Cannot fail given valid arguments */
  *pTimeOut = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_usec/1000;
  return SQLITE_OK;
}
#endif /* SQLITE_OS_KV || SQLITE_OS_UNIX */

#if SQLITE_OS_KV
/* 
** This routine is called initialize the KV-vfs as the default VFS.
*/
int sqlite3_os_init(void){
  return sqlite3_vfs_register(&sqlite3OsKvvfsObject, 1);
}
int sqlite3_os_end(void){
  return SQLITE_OK;
}
#endif /* SQLITE_OS_KV */

#if SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL)
int sqlite3KvvfsInit(void){
  return sqlite3_vfs_register(&sqlite3OsKvvfsObject, 0);
}
#endif

Changes to src/os_setup.h.

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







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

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

+
-
+

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

+


#ifndef SQLITE_OS_SETUP_H
#define SQLITE_OS_SETUP_H

/*
** Figure out if we are dealing with Unix, Windows, or some other operating
** system.
**
** After the following block of preprocess macros, all of SQLITE_OS_UNIX,
** SQLITE_OS_WIN, and SQLITE_OS_OTHER will defined to either 1 or 0.  One of
** the three will be 1.  The other two will be 0.
** After the following block of preprocess macros, all of 
**
**    SQLITE_OS_KV
**    SQLITE_OS_OTHER
**    SQLITE_OS_UNIX
**    SQLITE_OS_WIN
**
** will defined to either 1 or 0. One of them will be 1. The others will be 0.
** If none of the macros are initially defined, then select either
** SQLITE_OS_UNIX or SQLITE_OS_WIN depending on the target platform.
**
** If SQLITE_OS_OTHER=1 is specified at compile-time, then the application
** must provide its own VFS implementation together with sqlite3_os_init()
** and sqlite3_os_end() routines.
*/
#if !defined(SQLITE_OS_KV) && !defined(SQLITE_OS_OTHER) && \
#if defined(SQLITE_OS_OTHER)
#  if SQLITE_OS_OTHER==1
#    undef SQLITE_OS_UNIX
#    define SQLITE_OS_UNIX 0
#    undef SQLITE_OS_WIN
#    define SQLITE_OS_WIN 0
       !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_WIN)
#  if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \
          defined(__MINGW32__) || defined(__BORLANDC__)
#    define SQLITE_OS_WIN 1
#    define SQLITE_OS_UNIX 0
#  else
#    define SQLITE_OS_WIN 0
#    define SQLITE_OS_UNIX 1
#  endif
#endif
#if SQLITE_OS_OTHER+1>1
#  undef SQLITE_OS_KV
#  define SQLITE_OS_KV 0
#  undef SQLITE_OS_UNIX
#  define SQLITE_OS_UNIX 0
#  else
#    undef SQLITE_OS_OTHER
#  endif
#  undef SQLITE_OS_WIN
#  define SQLITE_OS_WIN 0
#endif
#if SQLITE_OS_KV+1>1
#if !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_OTHER)
#  undef SQLITE_OS_OTHER
#  define SQLITE_OS_OTHER 0
#  ifndef SQLITE_OS_WIN
#  undef SQLITE_OS_UNIX
#    if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \
        defined(__MINGW32__) || defined(__BORLANDC__)
#      define SQLITE_OS_WIN 1
#      define SQLITE_OS_UNIX 0
#    else
#      define SQLITE_OS_WIN 0
#      define SQLITE_OS_UNIX 1
#    endif
#  else
#    define SQLITE_OS_UNIX 0
#  endif
#  define SQLITE_OS_UNIX 0
#  undef SQLITE_OS_WIN
#  define SQLITE_OS_WIN 0
#  define SQLITE_OMIT_LOAD_EXTENSION 1
#  define SQLITE_OMIT_WAL 1
#  define SQLITE_OMIT_DEPRECATED 1
#  undef SQLITE_TEMP_STORE
#  define SQLITE_TEMP_STORE 3  /* Always use memory for temporary storage */
#  define SQLITE_DQS 0
#  define SQLITE_OMIT_SHARED_CACHE 1
#  define SQLITE_OMIT_AUTOINIT 1
#endif
#if SQLITE_OS_UNIX+1>1
#  undef SQLITE_OS_KV
#  define SQLITE_OS_KV 0
#  undef SQLITE_OS_OTHER
#else
#  ifndef SQLITE_OS_WIN
#    define SQLITE_OS_WIN 0
#  endif
#  define SQLITE_OS_OTHER 0
#  undef SQLITE_OS_WIN
#  define SQLITE_OS_WIN 0
#endif
#if SQLITE_OS_WIN+1>1
#  undef SQLITE_OS_KV
#  define SQLITE_OS_KV 0
#  undef SQLITE_OS_OTHER
#  define SQLITE_OS_OTHER 0
#  undef SQLITE_OS_UNIX
#  define SQLITE_OS_UNIX 0
#endif


#endif /* SQLITE_OS_SETUP_H */

Changes to src/os_unix.c.

42
43
44
45
46
47
48










49
50
51
52
53
54
55
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65







+
+
+
+
+
+
+
+
+
+







**   *  Locking primitives for the proxy uber-locking-method. (MacOSX only)
**   *  Definitions of sqlite3_vfs objects for all locking methods
**      plus implementations of sqlite3_os_init() and sqlite3_os_end().
*/
#include "sqliteInt.h"
#if SQLITE_OS_UNIX              /* This file is used on unix only */

/* Turn this feature on in all builds for now */
#define SQLITE_MUTEXFREE_SHMLOCK 1
#define SQLITE_MFS_EXCLUSIVE     255
#ifndef SQLITE_MFS_NSHARD
# define SQLITE_MFS_NSHARD       8
#endif
#if SQLITE_MFS_NSHARD<1
# error "SQLITE_MFS_NSHARD must be greater than 0"
#endif

/*
** There are various methods for file locking used for concurrency
** control:
**
**   1. POSIX locking (the default),
**   2. No locking,
**   3. Dot-file locking,
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
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







-
-
+
+


-
+

-
+











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







# undef USE_PREAD64
# define USE_PREAD 1
#endif

/*
** standard include files.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>   /* amalgamator: keep */
#include <sys/stat.h>    /* amalgamator: keep */
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <unistd.h>      /* amalgamator: keep */
#include <time.h>
#include <sys/time.h>
#include <sys/time.h>    /* amalgamator: keep */
#include <errno.h>
#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
# include <sys/mman.h>
#endif

#if SQLITE_ENABLE_LOCKING_STYLE
# include <sys/ioctl.h>
# include <sys/file.h>
# include <sys/param.h>
#endif /* SQLITE_ENABLE_LOCKING_STYLE */

/*
** Try to determine if gethostuuid() is available based on standard
** macros.  This might sometimes compute the wrong value for some
** obscure platforms.  For those cases, simply compile with one of
** the following:
**
**    -DHAVE_GETHOSTUUID=0
**    -DHAVE_GETHOSTUUID=1
**
** None if this matters except when building on Apple products with
** -DSQLITE_ENABLE_LOCKING_STYLE.
*/
#ifndef HAVE_GETHOSTUUID
# define HAVE_GETHOSTUUID 0
#if defined(__APPLE__) && ((__MAC_OS_X_VERSION_MIN_REQUIRED > 1050) || \
                           (__IPHONE_OS_VERSION_MIN_REQUIRED > 2000))
#  if (!defined(TARGET_OS_EMBEDDED) || (TARGET_OS_EMBEDDED==0)) \
       && (!defined(TARGET_IPHONE_SIMULATOR) || (TARGET_IPHONE_SIMULATOR==0))
#    define HAVE_GETHOSTUUID 1
#  else
#    warning "gethostuuid() is disabled."
# if defined(__APPLE__) && ((__MAC_OS_X_VERSION_MIN_REQUIRED > 1050) || \
                            (__IPHONE_OS_VERSION_MIN_REQUIRED > 2000))
#    if (!defined(TARGET_OS_EMBEDDED) || (TARGET_OS_EMBEDDED==0)) \
        && (!defined(TARGET_IPHONE_SIMULATOR) || (TARGET_IPHONE_SIMULATOR==0))\
        && (!defined(TARGET_OS_MACCATALYST) || (TARGET_OS_MACCATALYST==0))
#      undef HAVE_GETHOSTUUID
#      define HAVE_GETHOSTUUID 1
#    else
#      warning "gethostuuid() is disabled."
#    endif
#  endif
#endif


#if OS_VXWORKS
# include <sys/ioctl.h>
# include <semaphore.h>
517
518
519
520
521
522
523

524
525

526
527
528
529
530
531
532
533
534
535
536
537
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558

559
560
561
562
563
564
565







+


+




-







  { "lstat",         (sqlite3_syscall_ptr)0,              0 },
#endif
#define osLstat      ((int(*)(const char*,struct stat*))aSyscall[27].pCurrent)

#if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
# ifdef __ANDROID__
  { "ioctl", (sqlite3_syscall_ptr)(int(*)(int, int, ...))ioctl, 0 },
#define osIoctl ((int(*)(int,int,...))aSyscall[28].pCurrent)
# else
  { "ioctl",         (sqlite3_syscall_ptr)ioctl,          0 },
#define osIoctl ((int(*)(int,unsigned long,...))aSyscall[28].pCurrent)
# endif
#else
  { "ioctl",         (sqlite3_syscall_ptr)0,              0 },
#endif
#define osIoctl ((int(*)(int,int,...))aSyscall[28].pCurrent)

}; /* End of the overrideable system calls */


/*
** On some systems, calls to fchown() will trigger a message in a security
** log if they come from non-root processes.  So avoid calling fchown() if
664
665
666
667
668
669
670



671
672
673
674
675

676
677
678
679
680
681
682
692
693
694
695
696
697
698
699
700
701
702
703
704
705

706
707
708
709
710
711
712
713







+
+
+




-
+







    fd = osOpen(z,f,m2);
#endif
    if( fd<0 ){
      if( errno==EINTR ) continue;
      break;
    }
    if( fd>=SQLITE_MINIMUM_FILE_DESCRIPTOR ) break;
    if( (f & (O_EXCL|O_CREAT))==(O_EXCL|O_CREAT) ){
      (void)osUnlink(z);
    }
    osClose(fd);
    sqlite3_log(SQLITE_WARNING, 
                "attempt to open \"%s\" as file descriptor %d", z, fd);
    fd = -1;
    if( osOpen("/dev/null", f, m)<0 ) break;
    if( osOpen("/dev/null", O_RDONLY, m)<0 ) break;
  }
  if( fd>=0 ){
    if( m!=0 ){
      struct stat statbuf;
      if( osFstat(fd, &statbuf)==0 
       && statbuf.st_size==0
       && (statbuf.st_mode&0777)!=m 
1534
1535
1536
1537
1538
1539
1540



1541
1542
1543
1544
1545
1546
1547
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581







+
+
+







  sqlite3_mutex_leave(pFile->pInode->pLockMutex);
  OSTRACE(("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved));

  *pResOut = reserved;
  return rc;
}

/* Forward declaration*/
static int unixSleep(sqlite3_vfs*,int);

/*
** Set a posix-advisory-lock.
**
** There are two versions of this routine.  If compiled with
** SQLITE_ENABLE_SETLK_TIMEOUT then the routine has an extra parameter
** which is a pointer to a unixFile.  If the unixFile->iBusyTimeout
** value is set, then it is the number of milliseconds to wait before
1555
1556
1557
1558
1559
1560
1561

1562
1563

1564
1565
1566
1567
1568
1569

1570
1571

1572
1573
1574
1575
1576
1577
1578
1589
1590
1591
1592
1593
1594
1595
1596
1597

1598
1599
1600
1601
1602
1603

1604
1605

1606
1607
1608
1609
1610
1611
1612
1613







+

-
+





-
+

-
+







# define osSetPosixAdvisoryLock(h,x,t) osFcntl(h,F_SETLK,x)
#else
static int osSetPosixAdvisoryLock(
  int h,                /* The file descriptor on which to take the lock */
  struct flock *pLock,  /* The description of the lock */
  unixFile *pFile       /* Structure holding timeout value */
){
  int tm = pFile->iBusyTimeout;
  int rc = osFcntl(h,F_SETLK,pLock);
  while( rc<0 && pFile->iBusyTimeout>0 ){
  while( rc<0 && tm>0 ){
    /* On systems that support some kind of blocking file lock with a timeout,
    ** make appropriate changes here to invoke that blocking file lock.  On
    ** generic posix, however, there is no such API.  So we simply try the
    ** lock once every millisecond until either the timeout expires, or until
    ** the lock is obtained. */
    usleep(1000);
    unixSleep(0,1000);
    rc = osFcntl(h,F_SETLK,pLock);
    pFile->iBusyTimeout--;
    tm--;
  }
  return rc;
}
#endif /* SQLITE_ENABLE_SETLK_TIMEOUT */


/*
1633
1634
1635
1636
1637
1638
1639
1640

1641
1642
1643
1644
1645
1646
1647
1668
1669
1670
1671
1672
1673
1674

1675
1676
1677
1678
1679
1680
1681
1682







-
+







** are inserted in between.  The locking might fail on one of the later
** transitions leaving the lock state different from what it started but
** still short of its goal.  The following chart shows the allowed
** transitions and the inserted intermediate states:
**
**    UNLOCKED -> SHARED
**    SHARED -> RESERVED
**    SHARED -> (PENDING) -> EXCLUSIVE
**    SHARED -> EXCLUSIVE
**    RESERVED -> (PENDING) -> EXCLUSIVE
**    PENDING -> EXCLUSIVE
**
** This routine will only increase a lock.  Use the sqlite3OsUnlock()
** routine to lower a locking level.
*/
static int unixLock(sqlite3_file *id, int eFileLock){
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
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







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

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







  ** lack of shared-locks on Windows95 lives on, for backwards
  ** compatibility.)
  **
  ** A process may only obtain a RESERVED lock after it has a SHARED lock.
  ** A RESERVED lock is implemented by grabbing a write-lock on the
  ** 'reserved byte'. 
  **
  ** A process may only obtain a PENDING lock after it has obtained a
  ** SHARED lock. A PENDING lock is implemented by obtaining a write-lock
  ** on the 'pending byte'. This ensures that no new SHARED locks can be
  ** obtained, but existing SHARED locks are allowed to persist. A process
  ** An EXCLUSIVE lock may only be requested after either a SHARED or
  ** RESERVED lock is held. An EXCLUSIVE lock is implemented by obtaining 
  ** a write-lock on the entire 'shared byte range'. Since all other locks 
  ** require a read-lock on one of the bytes within this range, this ensures 
  ** that no other locks are held on the database. 
  ** does not have to obtain a RESERVED lock on the way to a PENDING lock.
  ** This property is used by the algorithm for rolling back a journal file
  ** after a crash.
  **
  ** If a process that holds a RESERVED lock requests an EXCLUSIVE, then
  ** An EXCLUSIVE lock, obtained after a PENDING lock is held, is
  ** implemented by obtaining a write-lock on the entire 'shared byte
  ** range'. Since all other locks require a read-lock on one of the bytes
  ** within this range, this ensures that no other locks are held on the
  ** database. 
  ** a PENDING lock is obtained first. A PENDING lock is implemented by 
  ** obtaining a write-lock on the 'pending byte'. This ensures that no new 
  ** SHARED locks can be obtained, but existing SHARED locks are allowed to 
  ** persist. If the call to this function fails to obtain the EXCLUSIVE
  ** lock in this case, it holds the PENDING lock intead. The client may
  ** then re-attempt the EXCLUSIVE lock later on, after existing SHARED
  ** locks have cleared.
  */
  int rc = SQLITE_OK;
  unixFile *pFile = (unixFile*)id;
  unixInodeInfo *pInode;
  struct flock lock;
  int tErrno = 0;

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







-
+










+
+
+







  /* A PENDING lock is needed before acquiring a SHARED lock and before
  ** acquiring an EXCLUSIVE lock.  For the SHARED lock, the PENDING will
  ** be released.
  */
  lock.l_len = 1L;
  lock.l_whence = SEEK_SET;
  if( eFileLock==SHARED_LOCK 
      || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock<PENDING_LOCK)
   || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock==RESERVED_LOCK)
  ){
    lock.l_type = (eFileLock==SHARED_LOCK?F_RDLCK:F_WRLCK);
    lock.l_start = PENDING_BYTE;
    if( unixFileLock(pFile, &lock) ){
      tErrno = errno;
      rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
      if( rc!=SQLITE_BUSY ){
        storeLastErrno(pFile, tErrno);
      }
      goto end_lock;
    }else if( eFileLock==EXCLUSIVE_LOCK ){
      pFile->eFileLock = PENDING_LOCK;
      pInode->eFileLock = PENDING_LOCK;
    }
  }


  /* If control gets to this point, then actually go ahead and make
  ** operating system calls for the specified lock.
  */
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1886
1887
1888
1889
1890
1891
1892

1893
1894
1895



1896
1897
1898
1899
1900
1901
1902







-



-
-
-







  ){
    pFile->transCntrChng = 0;
    pFile->dbUpdate = 0;
    pFile->inNormalWrite = 1;
  }
#endif


  if( rc==SQLITE_OK ){
    pFile->eFileLock = eFileLock;
    pInode->eFileLock = eFileLock;
  }else if( eFileLock==EXCLUSIVE_LOCK ){
    pFile->eFileLock = PENDING_LOCK;
    pInode->eFileLock = PENDING_LOCK;
  }

end_lock:
  sqlite3_mutex_leave(pInode->pLockMutex);
  OSTRACE(("LOCK    %d %s %s (unix)\n", pFile->h, azFileLock(eFileLock), 
      rc==SQLITE_OK ? "ok" : "failed"));
  return rc;
2133
2134
2135
2136
2137
2138
2139

2140
2141
2142
2143
2144
2145
2146
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182







+







    ** descriptor to pInode->pUnused list.  It will be automatically closed 
    ** when the last lock is cleared.
    */
    setPendingFd(pFile);
  }
  sqlite3_mutex_leave(pInode->pLockMutex);
  releaseInodeInfo(pFile);
  assert( pFile->pShm==0 );
  rc = closeUnixFile(id);
  unixLeaveMutex();
  return rc;
}

/************** End of the posix advisory lock implementation *****************
******************************************************************************/
3337
3338
3339
3340
3341
3342
3343
3344

3345
3346
3347
3348
3349
3350
3351
3373
3374
3375
3376
3377
3378
3379

3380
3381
3382
3383
3384
3385
3386
3387







-
+







){
  unixFile *pFile = (unixFile *)id;
  int got;
  assert( id );
  assert( offset>=0 );
  assert( amt>0 );

  /* If this is a database file (not a journal, master-journal or temp
  /* If this is a database file (not a journal, super-journal or temp
  ** file), the bytes in the locking range should never be read or written. */
#if 0
  assert( pFile->pPreallocatedUnused==0
       || offset>=PENDING_BYTE+512
       || offset+amt<=PENDING_BYTE 
  );
#endif
3367
3368
3369
3370
3371
3372
3373







3374











3375
3376
3377
3378
3379
3380
3381
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416

3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434







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







  }
#endif

  got = seekAndRead(pFile, offset, pBuf, amt);
  if( got==amt ){
    return SQLITE_OK;
  }else if( got<0 ){
    /* pFile->lastErrno has been set by seekAndRead().
    ** Usually we return SQLITE_IOERR_READ here, though for some
    ** kinds of errors we return SQLITE_IOERR_CORRUPTFS.  The
    ** SQLITE_IOERR_CORRUPTFS will be converted into SQLITE_CORRUPT
    ** prior to returning to the application by the sqlite3ApiExit()
    ** routine.
    */
    /* lastErrno set by seekAndRead */
    switch( pFile->lastErrno ){
      case ERANGE:
      case EIO:
#ifdef ENXIO
      case ENXIO:
#endif
#ifdef EDEVERR
      case EDEVERR:
#endif
        return SQLITE_IOERR_CORRUPTFS;
    }
    return SQLITE_IOERR_READ;
  }else{
    storeLastErrno(pFile, 0);   /* not a system error */
    /* Unread parts of the buffer must be zero-filled */
    memset(&((char*)pBuf)[got], 0, amt-got);
    return SQLITE_IOERR_SHORT_READ;
  }
3450
3451
3452
3453
3454
3455
3456
3457

3458
3459
3460
3461
3462
3463
3464
3503
3504
3505
3506
3507
3508
3509

3510
3511
3512
3513
3514
3515
3516
3517







-
+







  sqlite3_int64 offset 
){
  unixFile *pFile = (unixFile*)id;
  int wrote = 0;
  assert( id );
  assert( amt>0 );

  /* If this is a database file (not a journal, master-journal or temp
  /* If this is a database file (not a journal, super-journal or temp
  ** file), the bytes in the locking range should never be read or written. */
#if 0
  assert( pFile->pPreallocatedUnused==0
       || offset>=PENDING_BYTE+512
       || offset+amt<=PENDING_BYTE 
  );
#endif
3926
3927
3928
3929
3930
3931
3932



3933
3934
3935
3936
3937
3938
3939
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995







+
+
+







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

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

/*
** Information and control of an open file handle.
*/
static int unixFileControl(sqlite3_file *id, int op, void *pArg){
  unixFile *pFile = (unixFile*)id;
  switch( op ){
3993
3994
3995
3996
3997
3998
3999

4000

4001
4002
4003
4004
4005
4006
4007
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065







+

+







    }
    case SQLITE_FCNTL_HAS_MOVED: {
      *(int*)pArg = fileHasMoved(pFile);
      return SQLITE_OK;
    }
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
    case SQLITE_FCNTL_LOCK_TIMEOUT: {
      int iOld = pFile->iBusyTimeout;
      pFile->iBusyTimeout = *(int*)pArg;
      *(int*)pArg = iOld;
      return SQLITE_OK;
    }
#endif
#if SQLITE_MAX_MMAP_SIZE>0
    case SQLITE_FCNTL_MMAP_SIZE: {
      i64 newLimit = *(i64*)pArg;
      int rc = SQLITE_OK;
4043
4044
4045
4046
4047
4048
4049









4050
4051
4052
4053
4054
4055
4056
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123







+
+
+
+
+
+
+
+
+







#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: {
#ifndef SQLITE_OMIT_WAL
      return unixFcntlExternalReader((unixFile*)id, (int*)pArg);
#else
      *(int*)pArg = 0;
      return SQLITE_OK;
#endif
    }
  }
  return SQLITE_NOTFOUND;
}

/*
** If pFd->sectorSize is non-zero when this function is called, it is a
** no-op. Otherwise, the values of pFd->sectorSize and 
4252
4253
4254
4255
4256
4257
4258

4259
4260
4261
4262
4263


















4264















4265
4266
4267
4268
4269
4270
4271
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
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372







+





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

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







  int szRegion;              /* Size of shared-memory regions */
  u16 nRegion;               /* Size of array apRegion */
  u8 isReadonly;             /* True if read-only */
  u8 isUnlocked;             /* True if no DMS lock held */
  char **apRegion;           /* Array of mapped shared-memory regions */
  int nRef;                  /* Number of unixShm objects pointing to this */
  unixShm *pFirst;           /* All unixShm objects pointing to this */
  int aLock[SQLITE_SHM_NLOCK];  /* # shared locks on slot, -1==excl lock */
#ifdef SQLITE_DEBUG
  u8 exclMask;               /* Mask of exclusive locks held */
  u8 sharedMask;             /* Mask of shared locks held */
  u8 nextShmId;              /* Next available unixShm.id value */
#endif

#ifdef SQLITE_MUTEXFREE_SHMLOCK
  /* In unix-excl mode, if SQLITE_MUTEXFREE_SHMLOCK is defined, all locks
  ** are stored in the following 64-bit value. There are in total 8 
  ** shm-locking slots, each of which are assigned 8-bits from the 64-bit
  ** value. The least-significant 8 bits correspond to shm-locking slot
  ** 0, and so on.
  **
  ** If the 8-bits corresponding to a shm-locking locking slot are set to
  ** 0xFF, then a write-lock is held on the slot. Or, if they are set to
  ** a non-zero value smaller than 0xFF, then they represent the total 
  ** number of read-locks held on the slot. There is no way to distinguish
  ** between a write-lock and 255 read-locks.  */
  struct LockingSlot {
    u32 nLock;
    u64 aPadding[7];
  } aMFSlot[3 + SQLITE_MFS_NSHARD*5];
#endif
};

/*
** Atomic CAS primitive used in multi-process mode. Equivalent to:
** 
**   int unixCompareAndSwap(u32 *ptr, u32 oldval, u32 newval){
**     if( *ptr==oldval ){
**       *ptr = newval;
**       return 1;
**     }
**     return 0;
**   }
*/
#define unixCompareAndSwap(ptr,oldval,newval) \
    __sync_bool_compare_and_swap(ptr,oldval,newval)


/*
** Structure used internally by this VFS to record the state of an
** open shared memory connection.
**
** The following fields are initialized when this object is created and
** are read-only thereafter:
4279
4280
4281
4282
4283
4284
4285



4286
4287
4288
4289
4290
4291
4292


































4293
4294
4295
4296
4297
4298
4299
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437







+
+
+







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







struct unixShm {
  unixShmNode *pShmNode;     /* The underlying unixShmNode object */
  unixShm *pNext;            /* Next unixShm with the same unixShmNode */
  u8 hasMutex;               /* True if holding the unixShmNode->pShmMutex */
  u8 id;                     /* Id of this connection within its unixShmNode */
  u16 sharedMask;            /* Mask of shared locks held */
  u16 exclMask;              /* Mask of exclusive locks held */
#ifdef SQLITE_MUTEXFREE_SHMLOCK
  u8 aMFCurrent[8];          /* Current slot used for each shared lock */
#endif
};

/*
** 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.
*/
4315
4316
4317
4318
4319
4320
4321

4322
4323
4324
4325
4326
4327
4328








4329
4330
4331
4332
4333
4334
4335
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465


4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480







+





-
-
+
+
+
+
+
+
+
+







  /* Shared locks never span more than one byte */
  assert( n==1 || lockType!=F_RDLCK );

  /* Locks are within range */
  assert( n>=1 && n<=SQLITE_SHM_NLOCK );

  if( pShmNode->hShm>=0 ){
    int res;
    /* Initialize the locking parameters */
    f.l_type = lockType;
    f.l_whence = SEEK_SET;
    f.l_start = ofst;
    f.l_len = n;
    rc = osSetPosixAdvisoryLock(pShmNode->hShm, &f, pFile);
    rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
    res = osSetPosixAdvisoryLock(pShmNode->hShm, &f, pFile);
    if( res==-1 ){
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
      rc = (pFile->iBusyTimeout ? SQLITE_BUSY_TIMEOUT : SQLITE_BUSY);
#else
      rc = SQLITE_BUSY;
#endif
    }
  }

  /* Update the global lock state and do debug tracing */
#ifdef SQLITE_DEBUG
  { u16 mask;
  OSTRACE(("SHM-LOCK "));
  mask = ofst>31 ? 0xffff : (1<<(ofst+n)) - (1<<ofst);
4577
4578
4579
4580
4581
4582
4583
4584


4585
4586
4587


4588
4589
4590
4591
4592
4593
4594
4722
4723
4724
4725
4726
4727
4728

4729
4730
4731
4732

4733
4734
4735
4736
4737
4738
4739
4740
4741







-
+
+


-
+
+







        rc = SQLITE_NOMEM_BKPT;
        goto shm_open_err;
      }
    }

    if( pInode->bProcessLock==0 ){
      if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){
        pShmNode->hShm = robust_open(zShm, O_RDWR|O_CREAT,(sStat.st_mode&0777));
        pShmNode->hShm = robust_open(zShm, O_RDWR|O_CREAT|O_NOFOLLOW,
                                     (sStat.st_mode&0777));
      }
      if( pShmNode->hShm<0 ){
        pShmNode->hShm = robust_open(zShm, O_RDONLY, (sStat.st_mode&0777));
        pShmNode->hShm = robust_open(zShm, O_RDONLY|O_NOFOLLOW,
                                     (sStat.st_mode&0777));
        if( pShmNode->hShm<0 ){
          rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShm);
          goto shm_open_err;
        }
        pShmNode->isReadonly = 1;
      }

4783
4784
4785
4786
4787
4788
4789

















































































































4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805

4806
4807

4808
4809







4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822



























4823
4824
4825

4826


4827

4828
4829
4830

4831
4832
4833
4834
4835
4836
4837
4838







4839
4840
4841







4842
4843
4844
4845
4846
4847






4848
4849
4850
4851


4852
4853
4854
4855
4856


4857
4858
4859
4860
4861
4862

4863
4864
4865
4866
4867
4868
4869
4870

4871
4872
4873
4874
4875






4876
4877
4878

4879
4880
4881




4882
4883
4884
4885
4886
4887
4888



4889
4890
4891
4892
4893
4894



4895
4896
4897

4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913



4914
4915
4916
4917
4918
4919

4920
4921
4922
4923
4924
4925
4926
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
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
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064

5065


5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122

5123
5124


5125








5126
5127
5128
5129
5130
5131
5132



5133
5134
5135
5136
5137
5138
5139
5140





5141
5142
5143
5144
5145
5146
5147



5148
5149





5150
5151
5152





5153



5154




5155
5156




5157
5158
5159
5160
5161
5162
5163
5164

5165



5166
5167
5168
5169
5170
5171
5172
5173



5174
5175
5176

5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221







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















-
+
-
-
+


+
+
+
+
+
+
+













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



+

+
+
-
+

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

-
-
-
-
-
+
+
+
+
+
+

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

-
-
-
-
-
+
-
-
-

-
-
-
-
+

-
-
-
-
+
+
+
+
+
+


-
+
-
-
-
+
+
+
+




-
-
-
+
+
+
-





+
+
+



+
















+
+
+






+







    *pp = 0;
  }
  if( pShmNode->isReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY;
  sqlite3_mutex_leave(pShmNode->pShmMutex);
  return rc;
}

#ifdef SQLITE_MUTEXFREE_SHMLOCK
static int unixMutexFreeShmlock(
  unixFile *pFd,             /* Database file holding the shared memory */
  int ofst,                  /* First lock to acquire or release */
  int n,                     /* Number of locks to acquire or release */
  int flags                  /* What to do with the lock */
){
  struct LockMapEntry {
    int iFirst;
    int nSlot;
  } aMap[9] = {
    { 0, 1 },
    { 1, 1 },
    { 2, 1 },
    { 3+0*SQLITE_MFS_NSHARD, SQLITE_MFS_NSHARD },
    { 3+1*SQLITE_MFS_NSHARD, SQLITE_MFS_NSHARD },
    { 3+2*SQLITE_MFS_NSHARD, SQLITE_MFS_NSHARD },
    { 3+3*SQLITE_MFS_NSHARD, SQLITE_MFS_NSHARD },
    { 3+4*SQLITE_MFS_NSHARD, SQLITE_MFS_NSHARD },
    { 3+5*SQLITE_MFS_NSHARD, 0 },
  };

  unixShm *p = pFd->pShm;               /* The shared memory being locked */
  unixShmNode *pShmNode = p->pShmNode;  /* The underlying file iNode */

  if( flags & SQLITE_SHM_SHARED ){
    /* SHARED locks */
    u32 iOld, iNew, *ptr;
    int iIncr = -1;
    if( (flags & SQLITE_SHM_UNLOCK)==0 ){
      p->aMFCurrent[ofst] = (p->aMFCurrent[ofst] + 1) % aMap[ofst].nSlot;
      iIncr = 1;
    }
    ptr = &pShmNode->aMFSlot[aMap[ofst].iFirst + p->aMFCurrent[ofst]].nLock;
    do {
      iOld = *ptr;
      iNew = iOld + iIncr;
      if( iNew>SQLITE_MFS_EXCLUSIVE ){
        return SQLITE_BUSY;
      }
    }while( 0==unixCompareAndSwap(ptr, iOld, iNew) );
  }else{
    /* EXCLUSIVE locks */
    u16 mask = (1<<(ofst+n)) - (1<<ofst);
    if( (flags & SQLITE_SHM_LOCK) || (mask & p->exclMask) ){
      int iFirst = aMap[ofst].iFirst;
      int iLast = aMap[ofst+n].iFirst;
      int i;
      for(i=iFirst; i<iLast; i++){
        u32 *ptr = &pShmNode->aMFSlot[i].nLock;
        if( flags & SQLITE_SHM_UNLOCK ){
          assert( (*ptr)==SQLITE_MFS_EXCLUSIVE );
          *ptr = 0;
        }else{
          u32 iOld;
          do {
            iOld = *ptr;
            if( iOld>0 ){
              while( i>iFirst ){
                i--;
                pShmNode->aMFSlot[i].nLock = 0;
              }
              return SQLITE_BUSY;
            }
          }while( 0==unixCompareAndSwap(ptr, iOld, SQLITE_MFS_EXCLUSIVE) );
        }
      }
      if( flags & SQLITE_SHM_UNLOCK ){
        p->exclMask &= ~mask;
      }else{
        p->exclMask |= mask;
      }
    }
  }

  return SQLITE_OK;
}
#else
# define unixMutexFreeShmlock(a,b,c,d) SQLITE_OK
#endif

/*
** Check that the pShmNode->aLock[] array comports with the locking bitmasks
** held by each client. Return true if it does, or false otherwise. This
** is to be used in an assert(). e.g.
**
**     assert( assertLockingArrayOk(pShmNode) );
*/
#ifdef SQLITE_DEBUG
static int assertLockingArrayOk(unixShmNode *pShmNode){
  unixShm *pX;
  int aLock[SQLITE_SHM_NLOCK];
  assert( sqlite3_mutex_held(pShmNode->pShmMutex) );

  memset(aLock, 0, sizeof(aLock));
  for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
    int i;
    for(i=0; i<SQLITE_SHM_NLOCK; i++){
      if( pX->exclMask & (1<<i) ){
        assert( aLock[i]==0 );
        aLock[i] = -1;
      }else if( pX->sharedMask & (1<<i) ){
        assert( aLock[i]>=0 );
        aLock[i]++;
      }
    }
  }

  assert( 0==memcmp(pShmNode->aLock, aLock, sizeof(aLock)) );
  return (memcmp(pShmNode->aLock, aLock, sizeof(aLock))==0);
}
#endif

/*
** Change the lock state for a shared-memory segment.
**
** Note that the relationship between SHAREd and EXCLUSIVE locks is a little
** different here than in posix.  In xShmLock(), one can go from unlocked
** to shared and back or from unlocked to exclusive and back.  But one may
** not go from shared to exclusive or from exclusive to shared.
*/
static int unixShmLock(
  sqlite3_file *fd,          /* Database file holding the shared memory */
  int ofst,                  /* First lock to acquire or release */
  int n,                     /* Number of locks to acquire or release */
  int flags                  /* What to do with the lock */
){
  unixFile *pDbFd = (unixFile*)fd;      /* Connection holding shared memory */
  unixShm *p = pDbFd->pShm;             /* The shared memory being locked */
  unixShm *p;                           /* The shared memory being locked */
  unixShm *pX;                          /* For looping over all siblings */
  unixShmNode *pShmNode = p->pShmNode;  /* The underlying file iNode */
  unixShmNode *pShmNode;                /* The underlying file iNode */
  int rc = SQLITE_OK;                   /* Result code */
  u16 mask;                             /* Mask of locks to take or release */
  int *aLock;

  p = pDbFd->pShm;
  if( p==0 ) return SQLITE_IOERR_SHMLOCK;
  pShmNode = p->pShmNode;
  if( NEVER(pShmNode==0) ) return SQLITE_IOERR_SHMLOCK;
  aLock = pShmNode->aLock;

  assert( pShmNode==pDbFd->pInode->pShmNode );
  assert( pShmNode->pInode==pDbFd->pInode );
  assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK );
  assert( n>=1 );
  assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED)
       || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE)
       || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
       || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
  assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
  assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 );
  assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 );

  if( pDbFd->pInode->bProcessLock ){
    return unixMutexFreeShmlock(pDbFd, ofst, n, flags);
  }


  /* Check that, if this to be a blocking lock, no locks that occur later
  ** in the following list than the lock being obtained are already held:
  **
  **   1. Checkpointer lock (ofst==1).
  **   2. Write lock (ofst==0).
  **   3. Read locks (ofst>=3 && ofst<SQLITE_SHM_NLOCK).
  **
  ** In other words, if this is a blocking lock, none of the locks that
  ** occur later in the above list than the lock being obtained may be
  ** held.  
  **
  ** It is not permitted to block on the RECOVER lock.
  */
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
  assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || (
         (ofst!=2)                                   /* not RECOVER */
      && (ofst!=1 || (p->exclMask|p->sharedMask)==0)
      && (ofst!=0 || (p->exclMask|p->sharedMask)<3)
      && (ofst<3  || (p->exclMask|p->sharedMask)<(1<<ofst))
  ));
#endif

  mask = (1<<(ofst+n)) - (1<<ofst);
  assert( n>1 || mask==(1<<ofst) );
  sqlite3_mutex_enter(pShmNode->pShmMutex);
  assert( assertLockingArrayOk(pShmNode) );
  if( flags & SQLITE_SHM_UNLOCK ){
    if( (p->exclMask|p->sharedMask) & mask ){
      int ii;
    u16 allMask = 0; /* Mask of locks held by siblings */
      int bUnlock = 1;

    /* See if any siblings hold this same lock */
    for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
      for(ii=ofst; ii<ofst+n; ii++){
      if( pX==p ) continue;
      assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
      allMask |= pX->sharedMask;
    }

    /* Unlock the system-level locks */
    if( (mask & allMask)==0 ){
      rc = unixShmSystemLock(pDbFd, F_UNLCK, ofst+UNIX_SHM_BASE, n);
        if( aLock[ii]>((p->sharedMask & (1<<ii)) ? 1 : 0) ){
          bUnlock = 0;
        }
      }

      if( bUnlock ){
        rc = unixShmSystemLock(pDbFd, F_UNLCK, ofst+UNIX_SHM_BASE, n);
    }else{
      rc = SQLITE_OK;
    }
        if( rc==SQLITE_OK ){
          memset(&aLock[ofst], 0, sizeof(int)*n);
        }
      }else if( ALWAYS(p->sharedMask & (1<<ofst)) ){
        assert( n==1 && aLock[ofst]>1 );
        aLock[ofst]--;
      }

    /* Undo the local locks */
    if( rc==SQLITE_OK ){
      p->exclMask &= ~mask;
      p->sharedMask &= ~mask;
    } 
      /* Undo the local locks */
      if( rc==SQLITE_OK ){
        p->exclMask &= ~mask;
        p->sharedMask &= ~mask;
      } 
    }
  }else if( flags & SQLITE_SHM_SHARED ){
    u16 allShared = 0;  /* Union of locks held by connections other than "p" */

    /* Find out which shared locks are already held by sibling connections.
    assert( n==1 );
    assert( (p->exclMask & (1<<ofst))==0 );
    ** If any sibling already holds an exclusive lock, go ahead and return
    ** SQLITE_BUSY.
    */
    for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
      if( (pX->exclMask & mask)!=0 ){
    if( (p->sharedMask & mask)==0 ){
      if( aLock[ofst]<0 ){
        rc = SQLITE_BUSY;
        break;
      }
      allShared |= pX->sharedMask;
    }

      }else if( aLock[ofst]==0 ){
    /* Get shared locks at the system level, if necessary */
    if( rc==SQLITE_OK ){
      if( (allShared & mask)==0 ){
        rc = unixShmSystemLock(pDbFd, F_RDLCK, ofst+UNIX_SHM_BASE, n);
      }else{
        rc = SQLITE_OK;
      }
    }
      }

    /* Get the local shared locks */
    if( rc==SQLITE_OK ){
      p->sharedMask |= mask;
    }
      /* Get the local shared locks */
      if( rc==SQLITE_OK ){
        p->sharedMask |= mask;
        aLock[ofst]++;
      }
    }
  }else{
    /* Make sure no sibling connections hold locks that will block this
    ** lock.  If any do, return SQLITE_BUSY right away.
    ** lock.  If any do, return SQLITE_BUSY right away.  */
    */
    for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
      if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
    int ii;
    for(ii=ofst; ii<ofst+n; ii++){
      assert( (p->sharedMask & mask)==0 );
      if( ALWAYS((p->exclMask & (1<<ii))==0) && aLock[ii] ){
        rc = SQLITE_BUSY;
        break;
      }
    }
  
    /* Get the exclusive locks at the system level.  Then if successful
    ** also mark the local connection as being locked.

    /* Get the exclusive locks at the system level. Then if successful
    ** also update the in-memory values. */
    */
    if( rc==SQLITE_OK ){
      rc = unixShmSystemLock(pDbFd, F_WRLCK, ofst+UNIX_SHM_BASE, n);
      if( rc==SQLITE_OK ){
        assert( (p->sharedMask & mask)==0 );
        p->exclMask |= mask;
        for(ii=ofst; ii<ofst+n; ii++){
          aLock[ii] = -1;
        }
      }
    }
  }
  assert( assertLockingArrayOk(pShmNode) );
  sqlite3_mutex_leave(pShmNode->pShmMutex);
  OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n",
           p->id, osGetpid(0), p->sharedMask, p->exclMask));
  return rc;
}

/*
** Implement a memory barrier or memory fence on shared memory.  
**
** All loads and stores begun before the barrier must complete before
** any load or store begun after the barrier.
*/
static void unixShmBarrier(
  sqlite3_file *fd                /* Database file holding the shared memory */
){
  UNUSED_PARAMETER(fd);
#ifdef SQLITE_MUTEXFREE_SHMLOCK
  __sync_synchronize();
#else
  sqlite3MemoryBarrier();         /* compiler-defined memory barrier */
  assert( fd->pMethods->xLock==nolockLock 
       || unixFileMutexNotheld((unixFile*)fd) 
  );
  unixEnterMutex();               /* Also mutex, for redundancy */
  unixLeaveMutex();
#endif
}

/*
** Close a connection to shared-memory.  Delete the underlying 
** storage if deleteFlag is true.
**
** If there is no shared memory associated with the connection then this
5687
5688
5689
5690
5691
5692
5693
5694

5695
5696
5697
5698
5699




















5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729


5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741

5742
5743
5744
5745
5746
5747
5748
5749

5750

5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761

















5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775

5776
5777
5778
5779
5780
5781
5782
5982
5983
5984
5985
5986
5987
5988

5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020








6021
6022
6023
6024


6025
6026
6027
6028
6029
6030
6031
6032


6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058











6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088

6089
6090
6091
6092
6093
6094
6095
6096







-
+





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






-
-
-
-
-
-
-
-




-
-








-
-
+
+












+








+

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













-
+







    osUnlink(zFilename);
    pNew->ctrlFlags |= UNIXFILE_DELETE;
  }
#endif
  if( rc!=SQLITE_OK ){
    if( h>=0 ) robust_close(pNew, h, __LINE__);
  }else{
    pNew->pMethod = pLockingStyle;
    pId->pMethods = pLockingStyle;
    OpenCounter(+1);
    verifyDbFile(pNew);
  }
  return rc;
}

/*
** Directories to consider for temp files.
*/
static const char *azTempDirs[] = {
  0,
  0,
  "/var/tmp",
  "/usr/tmp",
  "/tmp",
  "."
};

/*
** Initialize first two members of azTempDirs[] array.
*/
static void unixTempFileInit(void){
  azTempDirs[0] = getenv("SQLITE_TMPDIR");
  azTempDirs[1] = getenv("TMPDIR");
}

/*
** Return the name of a directory in which to put temporary files.
** If no suitable temporary file directory can be found, return NULL.
*/
static const char *unixTempFileDir(void){
  static const char *azDirs[] = {
     0,
     0,
     "/var/tmp",
     "/usr/tmp",
     "/tmp",
     "."
  };
  unsigned int i = 0;
  struct stat buf;
  const char *zDir = sqlite3_temp_directory;

  if( !azDirs[0] ) azDirs[0] = getenv("SQLITE_TMPDIR");
  if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR");
  while(1){
    if( zDir!=0
     && osStat(zDir, &buf)==0
     && S_ISDIR(buf.st_mode)
     && osAccess(zDir, 03)==0
    ){
      return zDir;
    }
    if( i>=sizeof(azDirs)/sizeof(azDirs[0]) ) break;
    zDir = azDirs[i++];
    if( i>=sizeof(azTempDirs)/sizeof(azTempDirs[0]) ) break;
    zDir = azTempDirs[i++];
  }
  return 0;
}

/*
** Create a temporary file name in zBuf.  zBuf must be allocated
** by the calling process and must be big enough to hold at least
** pVfs->mxPathname bytes.
*/
static int unixGetTempname(int nBuf, char *zBuf){
  const char *zDir;
  int iLimit = 0;
  int rc = SQLITE_OK;

  /* It's odd to simulate an io-error here, but really this is just
  ** using the io-error infrastructure to test that SQLite handles this
  ** function failing. 
  */
  zBuf[0] = 0;
  SimulateIOError( return SQLITE_IOERR );

  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
  zDir = unixTempFileDir();
  if( zDir==0 ){
  if( zDir==0 ) return SQLITE_IOERR_GETTEMPPATH;
  do{
    u64 r;
    sqlite3_randomness(sizeof(r), &r);
    assert( nBuf>2 );
    zBuf[nBuf-2] = 0;
    sqlite3_snprintf(nBuf, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX"%llx%c",
                     zDir, r, 0);
    if( zBuf[nBuf-2]!=0 || (iLimit++)>10 ) return SQLITE_ERROR;
  }while( osAccess(zBuf,0)==0 );
  return SQLITE_OK;
    rc = SQLITE_IOERR_GETTEMPPATH;
  }else{
    do{
      u64 r;
      sqlite3_randomness(sizeof(r), &r);
      assert( nBuf>2 );
      zBuf[nBuf-2] = 0;
      sqlite3_snprintf(nBuf, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX"%llx%c",
                       zDir, r, 0);
      if( zBuf[nBuf-2]!=0 || (iLimit++)>10 ){
        rc = SQLITE_ERROR;
        break;
      }
    }while( osAccess(zBuf,0)==0 );
  }
  sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
  return rc;
}

#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
/*
** Routine to transform a unixFile into a proxy-locking unixFile.
** Implementation in the proxy-lock division, but used by unixOpen()
** if SQLITE_PREFER_PROXY_LOCKING is defined.
*/
static int proxyTransformUnixFile(unixFile*, const char*);
#endif

/*
** Search for an unused file descriptor that was opened on the database 
** file (not a journal or master-journal file) identified by pathname
** file (not a journal or super-journal file) identified by pathname
** zPath with SQLITE_OPEN_XXX flags matching those passed as the second
** argument to this function.
**
** Such a file descriptor may exist if a database connection was closed
** but the associated file descriptor could not be closed because some
** other file descriptor open on the same file is holding a file-lock.
** Refer to comments in the unixClose() function and the lengthy comment
5815
5816
5817
5818
5819
5820
5821

5822
5823
5824
5825
5826
5827
5828
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143







+







                     || pInode->fileId.ino!=(u64)sStat.st_ino) ){
       pInode = pInode->pNext;
    }
    if( pInode ){
      UnixUnusedFd **pp;
      assert( sqlite3_mutex_notheld(pInode->pLockMutex) );
      sqlite3_mutex_enter(pInode->pLockMutex);
      flags &= (SQLITE_OPEN_READONLY|SQLITE_OPEN_READWRITE);
      for(pp=&pInode->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext));
      pUnused = *pp;
      if( pUnused ){
        *pp = pUnused->pNext;
      }
      sqlite3_mutex_leave(pInode->pLockMutex);
    }
5868
5869
5870
5871
5872
5873
5874
5875

5876
5877
5878
5879
5880
5881
5882
6183
6184
6185
6186
6187
6188
6189

6190
6191
6192
6193
6194
6195
6196
6197







-
+







** corresponding database file and sets *pMode to this value. Whenever 
** possible, WAL and journal files are created using the same permissions 
** as the associated database file.
**
** If the SQLITE_ENABLE_8_3_NAMES option is enabled, then the
** original filename is unavailable.  But 8_3_NAMES is only used for
** FAT filesystems and permissions do not matter there, so just use
** the default permissions.
** the default permissions.  In 8_3_NAMES mode, leave *pMode set to zero.
*/
static int findCreateFileMode(
  const char *zPath,              /* Path of file (possibly) being created */
  int flags,                      /* Flags passed as 4th argument to xOpen() */
  mode_t *pMode,                  /* OUT: Permissions to open file with */
  uid_t *pUid,                    /* OUT: uid to set on the file */
  gid_t *pGid                     /* OUT: gid to set on the file */
5896
5897
5898
5899
5900
5901
5902
5903

5904
5905
5906
5907
5908
5909
5910
5911









5912
5913
5914


5915
5916





5917
5918
5919
5920
5921
5922
5923
6211
6212
6213
6214
6215
6216
6217

6218








6219
6220
6221
6222
6223
6224
6225
6226
6227



6228
6229


6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241







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







    **   "<path to db>-journal"
    **   "<path to db>-wal"
    **   "<path to db>-journalNN"
    **   "<path to db>-walNN"
    **
    ** where NN is a decimal number. The NN naming schemes are 
    ** used by the test_multiplex.c module.
    */
    **
    nDb = sqlite3Strlen30(zPath) - 1; 
    while( zPath[nDb]!='-' ){
      /* In normal operation, the journal file name will always contain
      ** a '-' character.  However in 8+3 filename mode, or if a corrupt
      ** rollback journal specifies a master journal with a goofy name, then
      ** the '-' might be missing. */
      if( nDb==0 || zPath[nDb]=='.' ) return SQLITE_OK;
      nDb--;
    ** In normal operation, the journal file name will always contain
    ** a '-' character.  However in 8+3 filename mode, or if a corrupt
    ** rollback journal specifies a super-journal with a goofy name, then
    ** the '-' might be missing or the '-' might be the first character in
    ** the filename.  In that case, just return SQLITE_OK with *pMode==0.
    */
    nDb = sqlite3Strlen30(zPath) - 1;
    while( nDb>0 && zPath[nDb]!='.' ){
      if( zPath[nDb]=='-' ){
    }
    memcpy(zDb, zPath, nDb);
    zDb[nDb] = '\0';
        memcpy(zDb, zPath, nDb);
        zDb[nDb] = '\0';

    rc = getFileMode(zDb, pMode, pUid, pGid);
        rc = getFileMode(zDb, pMode, pUid, pGid);
        break;
      }
      nDb--;
    }
  }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){
    *pMode = 0600;
  }else if( flags & SQLITE_OPEN_URI ){
    /* If this is a main database file and the file was opened using a URI
    ** filename, check for the "modeof" parameter. If present, interpret
    ** its value as a filename and try to copy the mode, uid and gid from
    ** that file.  */
5957
5958
5959
5960
5961
5962
5963
5964

5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981

5982
5983
5984
5985
5986

5987
5988
5989
5990
5991
5992
5993
6275
6276
6277
6278
6279
6280
6281

6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298

6299
6300
6301
6302
6303

6304
6305
6306
6307
6308
6309
6310
6311







-
+
















-
+




-
+







  sqlite3_file *pFile,         /* The file descriptor to be filled in */
  int flags,                   /* Input flags to control the opening */
  int *pOutFlags               /* Output flags returned to SQLite core */
){
  unixFile *p = (unixFile *)pFile;
  int fd = -1;                   /* File descriptor returned by open() */
  int openFlags = 0;             /* Flags to pass to open() */
  int eType = flags&0xFFFFFF00;  /* Type of file to open */
  int eType = flags&0x0FFF00;  /* Type of file to open */
  int noLock;                    /* True to omit locking primitives */
  int rc = SQLITE_OK;            /* Function Return Code */
  int ctrlFlags = 0;             /* UNIXFILE_* flags */

  int isExclusive  = (flags & SQLITE_OPEN_EXCLUSIVE);
  int isDelete     = (flags & SQLITE_OPEN_DELETEONCLOSE);
  int isCreate     = (flags & SQLITE_OPEN_CREATE);
  int isReadonly   = (flags & SQLITE_OPEN_READONLY);
  int isReadWrite  = (flags & SQLITE_OPEN_READWRITE);
#if SQLITE_ENABLE_LOCKING_STYLE
  int isAutoProxy  = (flags & SQLITE_OPEN_AUTOPROXY);
#endif
#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
  struct statfs fsInfo;
#endif

  /* If creating a master or main-file journal, this function will open
  /* If creating a super- or main-file journal, this function will open
  ** a file-descriptor on the directory too. The first time unixSync()
  ** is called the directory file descriptor will be fsync()ed and close()d.
  */
  int isNewJrnl = (isCreate && (
        eType==SQLITE_OPEN_MASTER_JOURNAL 
        eType==SQLITE_OPEN_SUPER_JOURNAL 
     || eType==SQLITE_OPEN_MAIN_JOURNAL 
     || eType==SQLITE_OPEN_WAL
  ));

  /* If argument zPath is a NULL pointer, this function is required to open
  ** a temporary file. Use this buffer to store the file name in.
  */
6002
6003
6004
6005
6006
6007
6008
6009

6010
6011
6012
6013

6014
6015
6016
6017
6018
6019

6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032





6033
6034
6035
6036
6037
6038
6039
6320
6321
6322
6323
6324
6325
6326

6327
6328
6329
6330

6331
6332
6333
6334
6335
6336

6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362







-
+



-
+





-
+













+
+
+
+
+







  **   (d) if DELETEONCLOSE is set, then CREATE must also be set.
  */
  assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly));
  assert(isCreate==0 || isReadWrite);
  assert(isExclusive==0 || isCreate);
  assert(isDelete==0 || isCreate);

  /* The main DB, main journal, WAL file and master journal are never 
  /* The main DB, main journal, WAL file and super-journal are never 
  ** automatically deleted. Nor are they ever temporary files.  */
  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_SUPER_JOURNAL );
  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );

  /* Assert that the upper layer has set one of the "file-type" flags. */
  assert( eType==SQLITE_OPEN_MAIN_DB      || eType==SQLITE_OPEN_TEMP_DB 
       || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL 
       || eType==SQLITE_OPEN_SUBJOURNAL   || eType==SQLITE_OPEN_MASTER_JOURNAL 
       || eType==SQLITE_OPEN_SUBJOURNAL   || eType==SQLITE_OPEN_SUPER_JOURNAL 
       || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
  );

  /* Detect a pid change and reset the PRNG.  There is a race condition
  ** here such that two or more threads all trying to open databases at
  ** the same instant might all reset the PRNG.  But multiple resets
  ** are harmless.
  */
  if( randomnessPid!=osGetpid(0) ){
    randomnessPid = osGetpid(0);
    sqlite3_randomness(0,0);
  }
  memset(p, 0, sizeof(unixFile));

#ifdef SQLITE_ASSERT_NO_FILES
  /* Applications that never read or write a persistent disk files */
  assert( zName==0 );
#endif

  if( eType==SQLITE_OPEN_MAIN_DB ){
    UnixUnusedFd *pUnused;
    pUnused = findReusableFd(zName, flags);
    if( pUnused ){
      fd = pUnused->fd;
    }else{
6067
6068
6069
6070
6071
6072
6073
6074

6075
6076
6077
6078
6079
6080
6081
6390
6391
6392
6393
6394
6395
6396

6397
6398
6399
6400
6401
6402
6403
6404







-
+







  ** open(). These must be calculated even if open() is not called, as
  ** they may be stored as part of the file handle and used by the 
  ** 'conch file' locking functions later on.  */
  if( isReadonly )  openFlags |= O_RDONLY;
  if( isReadWrite ) openFlags |= O_RDWR;
  if( isCreate )    openFlags |= O_CREAT;
  if( isExclusive ) openFlags |= (O_EXCL|O_NOFOLLOW);
  openFlags |= (O_LARGEFILE|O_BINARY);
  openFlags |= (O_LARGEFILE|O_BINARY|O_NOFOLLOW);

  if( fd<0 ){
    mode_t openMode;              /* Permissions to create file with */
    uid_t uid;                    /* Userid for the file */
    gid_t gid;                    /* Groupid for the file */
    rc = findCreateFileMode(zName, flags, &openMode, &uid, &gid);
    if( rc!=SQLITE_OK ){
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112











6113
6114

6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125


6126
6127
6128
6129
6130
6131
6132
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







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

-
+










-
+
+







    }
    if( fd<0 ){
      int rc2 = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName);
      if( rc==SQLITE_OK ) rc = rc2;
      goto open_finished;
    }

    /* If this process is running as root and if creating a new rollback
    ** journal or WAL file, set the ownership of the journal or WAL to be
    ** the same as the original database.
    /* The owner of the rollback journal or WAL file should always be the
    ** same as the owner of the database file.  Try to ensure that this is
    ** the case.  The chown() system call will be a no-op if the current
    ** process lacks root privileges, be we should at least try.  Without
    ** this step, if a root process opens a database file, it can leave
    ** behinds a journal/WAL that is owned by root and hence make the
    ** database inaccessible to unprivileged processes.
    **
    ** If openMode==0, then that means uid and gid are not set correctly
    ** (probably because SQLite is configured to use 8+3 filename mode) and
    ** in that case we do not want to attempt the chown().
    */
    if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
    if( openMode && (flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL))!=0 ){
      robustFchown(fd, uid, gid);
    }
  }
  assert( fd>=0 );
  if( pOutFlags ){
    *pOutFlags = flags;
  }

  if( p->pPreallocatedUnused ){
    p->pPreallocatedUnused->fd = fd;
    p->pPreallocatedUnused->flags = flags;
    p->pPreallocatedUnused->flags = 
                          flags & (SQLITE_OPEN_READONLY|SQLITE_OPEN_READWRITE);
  }

  if( isDelete ){
#if OS_VXWORKS
    zPath = zName;
#elif defined(SQLITE_UNLINK_AFTER_CLOSE)
    zPath = sqlite3_mprintf("%s", zName);
6196
6197
6198
6199
6200
6201
6202
6203

6204
6205
6206
6207
6208
6209
6210
6528
6529
6530
6531
6532
6533
6534

6535
6536
6537
6538
6539
6540
6541
6542







-
+







      }
      goto open_finished;
    }
  }
#endif
  
  assert( zPath==0 || zPath[0]=='/' 
      || eType==SQLITE_OPEN_MASTER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL 
      || eType==SQLITE_OPEN_SUPER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL 
  );
  rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);

open_finished:
  if( rc!=SQLITE_OK ){
    sqlite3_free(p->pPreallocatedUnused);
  }
6276
6277
6278
6279
6280
6281
6282
6283


6284
6285
6286
6287
6288
6289
6290

6291












































































6292
6293
6294



6295
6296
6297
6298
6299
6300
6301
6302






6303
6304
6305

6306
6307

6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340

6341
6342
6343

6344
6345
6346
6347
6348
6349
6350

6351
6352
6353
6354
6355

6356
6357
6358
6359
6360
6361
6362

6363
6364

6365
6366

6367
6368
6369

6370
6371
6372

6373
6374
6375
6376

6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387

6388
6389
6390
6391
6392

6393
6394
6395


6396
6397
6398
6399
6400
6401
6402
6403



6404
6405

6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6608
6609
6610
6611
6612
6613
6614

6615
6616
6617
6618
6619
6620
6621
6622
6623
6624

6625
6626
6627
6628
6629
6630
6631
6632
6633
6634
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
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
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







6735





6736







6737


6738


6739



6740



6741




6742











6743





6744



6745
6746








6747
6748
6749


6750

6751

6752
6753
6754
6755
6756
6757
6758







-
+
+







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

-
-
+
+
+
-
-

-
-
-
-
-
+
+
+
+
+
+

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

















-
-
-
-
-
-
-
-
-
+
-

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

-








  /* The spec says there are three possible values for flags.  But only
  ** two of them are actually used */
  assert( flags==SQLITE_ACCESS_EXISTS || flags==SQLITE_ACCESS_READWRITE );

  if( flags==SQLITE_ACCESS_EXISTS ){
    struct stat buf;
    *pResOut = (0==osStat(zPath, &buf) && buf.st_size>0);
    *pResOut = 0==osStat(zPath, &buf) &&
                (!S_ISREG(buf.st_mode) || buf.st_size>0);
  }else{
    *pResOut = osAccess(zPath, W_OK|R_OK)==0;
  }
  return SQLITE_OK;
}

/*
** A pathname under construction
**
*/
typedef struct DbPath DbPath;
struct DbPath {
  int rc;           /* Non-zero following any error */
  int nSymlink;     /* Number of symlinks resolved */
  char *zOut;       /* Write the pathname here */
  int nOut;         /* Bytes of space available to zOut[] */
  int nUsed;        /* Bytes of zOut[] currently being used */
};

/* Forward reference */
static void appendAllPathElements(DbPath*,const char*);

/*
** Append a single path element to the DbPath under construction
*/
static void appendOnePathElement(
  DbPath *pPath,       /* Path under construction, to which to append zName */
  const char *zName,   /* Name to append to pPath.  Not zero-terminated */
  int nName            /* Number of significant bytes in zName */
){
  assert( nName>0 );
  assert( zName!=0 );
  if( zName[0]=='.' ){
    if( nName==1 ) return;
    if( zName[1]=='.' && nName==2 ){
      if( pPath->nUsed>1 ){
        assert( pPath->zOut[0]=='/' );
        while( pPath->zOut[--pPath->nUsed]!='/' ){}
      }
      return;
    }
  }
  if( pPath->nUsed + nName + 2 >= pPath->nOut ){
    pPath->rc = SQLITE_ERROR;
    return;
  }
  pPath->zOut[pPath->nUsed++] = '/';
  memcpy(&pPath->zOut[pPath->nUsed], zName, nName);
  pPath->nUsed += nName;
#if defined(HAVE_READLINK) && defined(HAVE_LSTAT)
  if( pPath->rc==SQLITE_OK ){
    const char *zIn;
    struct stat buf;
    pPath->zOut[pPath->nUsed] = 0;
    zIn = pPath->zOut;
    if( osLstat(zIn, &buf)!=0 ){
      if( errno!=ENOENT ){
        pPath->rc = unixLogError(SQLITE_CANTOPEN_BKPT, "lstat", zIn);
      }
    }else if( S_ISLNK(buf.st_mode) ){
      ssize_t got;
      char zLnk[SQLITE_MAX_PATHLEN+2];
      if( pPath->nSymlink++ > SQLITE_MAX_SYMLINK ){
        pPath->rc = SQLITE_CANTOPEN_BKPT;
        return;
      }
      got = osReadlink(zIn, zLnk, sizeof(zLnk)-2);
      if( got<=0 || got>=(ssize_t)sizeof(zLnk)-2 ){
        pPath->rc = unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zIn);
        return;
      }
      zLnk[got] = 0;
      if( zLnk[0]=='/' ){
        pPath->nUsed = 0;
      }else{
        pPath->nUsed -= nName + 1;
      }
      appendAllPathElements(pPath, zLnk);
    }
  }
#endif
}

/*
** Append all path elements in zPath to the DbPath under construction.
*/
static int mkFullPathname(
  const char *zPath,              /* Input path */
static void appendAllPathElements(
  DbPath *pPath,       /* Path under construction, to which to append zName */
  const char *zPath    /* Path to append to pPath.  Is zero-terminated */
  char *zOut,                     /* Output buffer */
  int nOut                        /* Allocated size of buffer zOut */
){
  int nPath = sqlite3Strlen30(zPath);
  int iOff = 0;
  if( zPath[0]!='/' ){
    if( osGetcwd(zOut, nOut-2)==0 ){
      return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath);
  int i = 0;
  int j = 0;
  do{
    while( zPath[i] && zPath[i]!='/' ){ i++; }
    if( i>j ){
      appendOnePathElement(pPath, &zPath[j], i-j);
    }
    iOff = sqlite3Strlen30(zOut);
    zOut[iOff++] = '/';
    j = i+1;
  }
  if( (iOff+nPath+1)>nOut ){
  }while( zPath[i++] );
    /* SQLite assumes that xFullPathname() nul-terminates the output buffer
    ** even if it returns an error.  */
    zOut[iOff] = '\0';
    return SQLITE_CANTOPEN_BKPT;
  }
  sqlite3_snprintf(nOut-iOff, &zOut[iOff], "%s", zPath);
  return SQLITE_OK;
}

/*
** Turn a relative pathname into a full pathname. The relative path
** is stored as a nul-terminated string in the buffer pointed to by
** zPath. 
**
** zOut points to a buffer of at least sqlite3_vfs.mxPathname bytes 
** (in this case, MAX_PATHNAME bytes). The full-path is written to
** this buffer before returning.
*/
static int unixFullPathname(
  sqlite3_vfs *pVfs,            /* Pointer to vfs object */
  const char *zPath,            /* Possibly relative input path */
  int nOut,                     /* Size of output buffer in bytes */
  char *zOut                    /* Output buffer */
){
#if !defined(HAVE_READLINK) || !defined(HAVE_LSTAT)
  return mkFullPathname(zPath, zOut, nOut);
#else
  int rc = SQLITE_OK;
  int nByte;
  int nLink = 1;                /* Number of symbolic links followed so far */
  const char *zIn = zPath;      /* Input path for each iteration of loop */
  char *zDel = 0;

  DbPath path;
  assert( pVfs->mxPathname==MAX_PATHNAME );
  UNUSED_PARAMETER(pVfs);

  path.rc = 0;
  /* It's odd to simulate an io-error here, but really this is just
  ** using the io-error infrastructure to test that SQLite handles this
  ** function failing. This function could fail if, for example, the
  ** current working directory has been unlinked.
  */
  SimulateIOError( return SQLITE_ERROR );

  path.nUsed = 0;
  do {

    /* Call stat() on path zIn. Set bLink to true if the path is a symbolic
    ** link, or false otherwise.  */
    int bLink = 0;
  path.nSymlink = 0;
    struct stat buf;
    if( osLstat(zIn, &buf)!=0 ){
      if( errno!=ENOENT ){
        rc = unixLogError(SQLITE_CANTOPEN_BKPT, "lstat", zIn);
      }
    }else{
      bLink = S_ISLNK(buf.st_mode);
  path.nOut = nOut;
    }

  path.zOut = zOut;
    if( bLink ){
      if( zDel==0 ){
  if( zPath[0]!='/' ){
        zDel = sqlite3_malloc(nOut);
        if( zDel==0 ) rc = SQLITE_NOMEM_BKPT;
      }else if( ++nLink>SQLITE_MAX_SYMLINKS ){
    char zPwd[SQLITE_MAX_PATHLEN+2];
        rc = SQLITE_CANTOPEN_BKPT;
      }

    if( osGetcwd(zPwd, sizeof(zPwd)-2)==0 ){
      if( rc==SQLITE_OK ){
        nByte = osReadlink(zIn, zDel, nOut-1);
        if( nByte<0 ){
          rc = unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zIn);
      return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath);
        }else{
          if( zDel[0]!='/' ){
            int n;
            for(n = sqlite3Strlen30(zIn); n>0 && zIn[n-1]!='/'; n--);
            if( nByte+n+1>nOut ){
              rc = SQLITE_CANTOPEN_BKPT;
            }else{
              memmove(&zDel[n], zDel, nByte+1);
              memcpy(zDel, zIn, n);
              nByte += n;
            }
    }
          }
          zDel[nByte] = '\0';
        }
      }

    appendAllPathElements(&path, zPwd);
      zIn = zDel;
    }

  }
  appendAllPathElements(&path, zPath);
    assert( rc!=SQLITE_OK || zIn!=zOut || zIn[0]=='/' );
    if( rc==SQLITE_OK && zIn!=zOut ){
      rc = mkFullPathname(zIn, zOut, nOut);
    }
    if( bLink==0 ) break;
    zIn = zOut;
  }while( rc==SQLITE_OK );

  zOut[path.nUsed] = 0;
  if( path.rc || path.nUsed<2 ) return SQLITE_CANTOPEN_BKPT;
  if( path.nSymlink ) return SQLITE_OK_SYMLINK;
  sqlite3_free(zDel);
  return rc;
  return SQLITE_OK;
#endif   /* HAVE_READLINK && HAVE_LSTAT */
}


#ifndef SQLITE_OMIT_LOAD_EXTENSION
/*
** Interfaces for opening a shared library, finding entry points
** within the shared library, and closing the shared library.
*/
#include <dlfcn.h>
6516
6517
6518
6519
6520
6521
6522
6523

6524
6525
6526
6527
6528
6529
6530
6531

6532

6533
6534
6535
6536
6537
6538
6539
6859
6860
6861
6862
6863
6864
6865

6866
6867
6868
6869
6870
6871
6872
6873
6874
6875

6876
6877
6878
6879
6880
6881
6882
6883







-
+








+
-
+







** The argument is the number of microseconds we want to sleep.
** The return value is the number of microseconds of sleep actually
** requested from the underlying operating system, a number which
** might be greater than or equal to the argument, but not less
** than the argument.
*/
static int unixSleep(sqlite3_vfs *NotUsed, int microseconds){
#if OS_VXWORKS
#if OS_VXWORKS || _POSIX_C_SOURCE >= 199309L
  struct timespec sp;

  sp.tv_sec = microseconds / 1000000;
  sp.tv_nsec = (microseconds % 1000000) * 1000;
  nanosleep(&sp, NULL);
  UNUSED_PARAMETER(NotUsed);
  return microseconds;
#elif defined(HAVE_USLEEP) && HAVE_USLEEP
  if( microseconds>=1000000 ) sleep(microseconds/1000000);
  usleep(microseconds);
  if( microseconds%1000000 ) usleep(microseconds%1000000);
  UNUSED_PARAMETER(NotUsed);
  return microseconds;
#else
  int seconds = (microseconds+999999)/1000000;
  sleep(seconds);
  UNUSED_PARAMETER(NotUsed);
  return seconds*1000000;
6883
6884
6885
6886
6887
6888
6889
6890

6891
6892
6893
6894
6895
6896
6897
7227
7228
7229
7230
7231
7232
7233

7234
7235
7236
7237
7238
7239
7240
7241







-
+







    const char *path,        /* path for the new unixFile */
    unixFile **ppFile,       /* unixFile created and returned by ref */
    int islockfile           /* if non zero missing dirs will be created */
) {
  int fd = -1;
  unixFile *pNew;
  int rc = SQLITE_OK;
  int openFlags = O_RDWR | O_CREAT;
  int openFlags = O_RDWR | O_CREAT | O_NOFOLLOW;
  sqlite3_vfs dummyVfs;
  int terrno = 0;
  UnixUnusedFd *pUnused = NULL;

  /* 1. first try to open/create the file
  ** 2. if that fails, and this is a lock file (not-conch), try creating
  ** the parent directories and then try again.
6913
6914
6915
6916
6917
6918
6919
6920

6921
6922
6923
6924
6925
6926
6927
7257
7258
7259
7260
7261
7262
7263

7264
7265
7266
7267
7268
7269
7270
7271







-
+







    if( fd<0 && errno==ENOENT && islockfile ){
      if( proxyCreateLockPath(path) == SQLITE_OK ){
        fd = robust_open(path, openFlags, 0);
      }
    }
  }
  if( fd<0 ){
    openFlags = O_RDONLY;
    openFlags = O_RDONLY | O_NOFOLLOW;
    fd = robust_open(path, openFlags, 0);
    terrno = errno;
  }
  if( fd<0 ){
    if( islockfile ){
      return SQLITE_BUSY;
    }
6964
6965
6966
6967
6968
6969
6970
6971

6972
6973
6974
6975
6976
6977
6978
6979
6980
6981
6982

6983
6984
6985
6986
6987
6988
6989
7308
7309
7310
7311
7312
7313
7314

7315
7316
7317
7318
7319
7320
7321
7322
7323
7324
7325

7326
7327
7328
7329
7330
7331
7332
7333







-
+










-
+







#ifdef SQLITE_TEST
/* simulate multiple hosts by creating unique hostid file paths */
int sqlite3_hostid_num = 0;
#endif

#define PROXY_HOSTIDLEN    16  /* conch file host id length */

#ifdef HAVE_GETHOSTUUID
#if HAVE_GETHOSTUUID
/* Not always defined in the headers as it ought to be */
extern int gethostuuid(uuid_t id, const struct timespec *wait);
#endif

/* get the host ID via gethostuuid(), pHostID must point to PROXY_HOSTIDLEN 
** bytes of writable memory.
*/
static int proxyGetHostID(unsigned char *pHostID, int *pError){
  assert(PROXY_HOSTIDLEN == sizeof(uuid_t));
  memset(pHostID, 0, PROXY_HOSTIDLEN);
#ifdef HAVE_GETHOSTUUID
#if HAVE_GETHOSTUUID
  {
    struct timespec timeout = {1, 0}; /* 1 sec timeout */
    if( gethostuuid(pHostID, &timeout) ){
      int err = errno;
      if( pError ){
        *pError = err;
      }
7039
7040
7041
7042
7043
7044
7045
7046

7047
7048
7049
7050
7051
7052
7053
7383
7384
7385
7386
7387
7388
7389

7390
7391
7392
7393
7394
7395
7396
7397







-
+







  /* read the conch content */
  readLen = osPread(conchFile->h, buf, PROXY_MAXCONCHLEN, 0);
  if( readLen<PROXY_PATHINDEX ){
    sqlite3_snprintf(sizeof(errmsg),errmsg,"read error (len %d)",(int)readLen);
    goto end_breaklock;
  }
  /* write it out to the temporary break file */
  fd = robust_open(tPath, (O_RDWR|O_CREAT|O_EXCL), 0);
  fd = robust_open(tPath, (O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW), 0);
  if( fd<0 ){
    sqlite3_snprintf(sizeof(errmsg), errmsg, "create failed (%d)", errno);
    goto end_breaklock;
  }
  if( osPwrite(fd, buf, readLen, 0) != (ssize_t)readLen ){
    sqlite3_snprintf(sizeof(errmsg), errmsg, "write failed (%d)", errno);
    goto end_breaklock;
7098
7099
7100
7101
7102
7103
7104
7105

7106
7107
7108
7109
7110
7111
7112
7442
7443
7444
7445
7446
7447
7448

7449
7450
7451
7452
7453
7454
7455
7456







-
+







      if( osFstat(conchFile->h, &buf) ){
        storeLastErrno(pFile, errno);
        return SQLITE_IOERR_LOCK;
      }
      
      if( nTries==1 ){
        conchModTime = buf.st_mtimespec;
        usleep(500000); /* wait 0.5 sec and try the lock again*/
        unixSleep(0,500000); /* wait 0.5 sec and try the lock again*/
        continue;  
      }

      assert( nTries>1 );
      if( conchModTime.tv_sec != buf.st_mtimespec.tv_sec || 
         conchModTime.tv_nsec != buf.st_mtimespec.tv_nsec ){
        return SQLITE_BUSY;
7124
7125
7126
7127
7128
7129
7130
7131

7132
7133
7134
7135
7136
7137
7138
7468
7469
7470
7471
7472
7473
7474

7475
7476
7477
7478
7479
7480
7481
7482







-
+







          if( 0!=memcmp(&tBuf[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN) ){
            return SQLITE_BUSY;
          }
        }else{
          /* don't break the lock on short read or a version mismatch */
          return SQLITE_BUSY;
        }
        usleep(10000000); /* wait 10 sec and try the lock again */
        unixSleep(0,10000000); /* wait 10 sec and try the lock again */
        continue; 
      }
      
      assert( nTries==3 );
      if( 0==proxyBreakConchLock(pFile, myHostID) ){
        rc = SQLITE_OK;
        if( lockType==EXCLUSIVE_LOCK ){
7649
7650
7651
7652
7653
7654
7655
7656

7657
7658
7659
7660
7661
7662
7663
7993
7994
7995
7996
7997
7998
7999

8000
8001
8002
8003
8004
8005
8006
8007







-
+







      }
      return rc;
    }
    default: {
      assert( 0 );  /* The call assures that only valid opcodes are sent */
    }
  }
  /*NOTREACHED*/
  /*NOTREACHED*/ assert(0);
  return SQLITE_ERROR;
}

/*
** Within this division (the proxying locking implementation) the procedures
** above this point are all utilities.  The lock-related methods of the
** proxy-locking sqlite3_io_method object follow.
7897
7898
7899
7900
7901
7902
7903




7904

7905



7906






















7907
7908
7909
7910
7911
7912
7913
8241
8242
8243
8244
8245
8246
8247
8248
8249
8250
8251
8252
8253
8254
8255
8256
8257
8258
8259
8260
8261
8262
8263
8264
8265
8266
8267
8268
8269
8270
8271
8272
8273
8274
8275
8276
8277
8278
8279
8280
8281
8282
8283
8284
8285
8286
8287







+
+
+
+

+

+
+
+

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








  /* Double-check that the aSyscall[] array has been constructed
  ** correctly.  See ticket [bb3a86e890c8e96ab] */
  assert( ArraySize(aSyscall)==29 );

  /* Register all VFSes defined in the aVfs[] array */
  for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
#ifdef SQLITE_DEFAULT_UNIX_VFS
    sqlite3_vfs_register(&aVfs[i],
           0==strcmp(aVfs[i].zName,SQLITE_DEFAULT_UNIX_VFS));
#else
    sqlite3_vfs_register(&aVfs[i], i==0);
#endif
  }
#ifdef SQLITE_OS_KV_OPTIONAL
  sqlite3KvvfsInit();
#endif
  unixBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);

#ifndef SQLITE_OMIT_WAL
  /* Validate lock assumptions */
  assert( SQLITE_SHM_NLOCK==8 );  /* Number of available locks */
  assert( UNIX_SHM_BASE==120  );  /* Start of locking area */
  /* Locks:
  **    WRITE       UNIX_SHM_BASE      120
  **    CKPT        UNIX_SHM_BASE+1    121
  **    RECOVER     UNIX_SHM_BASE+2    122
  **    READ-0      UNIX_SHM_BASE+3    123
  **    READ-1      UNIX_SHM_BASE+4    124
  **    READ-2      UNIX_SHM_BASE+5    125
  **    READ-3      UNIX_SHM_BASE+6    126
  **    READ-4      UNIX_SHM_BASE+7    127
  **    DMS         UNIX_SHM_BASE+8    128
  */
  assert( UNIX_SHM_DMS==128   );  /* Byte offset of the deadman-switch */
#endif

  /* Initialize temp file dir array. */
  unixTempFileInit();

  return SQLITE_OK; 
}

/*
** Shutdown the operating system interface.
**
** Some operating systems might need to do some cleanup in this routine,

Changes to src/os_win.c.

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







-
+

-
+

-
+





-
+







** If a Win32 native heap has been configured, this function will attempt to
** destroy and recreate it.  If the Win32 native heap is not isolated and/or
** the sqlite3_memory_used() function does not return zero, SQLITE_BUSY will
** be returned and no changes will be made to the Win32 native heap.
*/
int sqlite3_win32_reset_heap(){
  int rc;
  MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */
  MUTEX_LOGIC( sqlite3_mutex *pMainMtx; ) /* The main static mutex */
  MUTEX_LOGIC( sqlite3_mutex *pMem; )    /* The memsys static mutex */
  MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
  MUTEX_LOGIC( pMainMtx = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); )
  MUTEX_LOGIC( pMem = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); )
  sqlite3_mutex_enter(pMaster);
  sqlite3_mutex_enter(pMainMtx);
  sqlite3_mutex_enter(pMem);
  winMemAssertMagic();
  if( winMemGetHeap()!=NULL && winMemGetOwned() && sqlite3_memory_used()==0 ){
    /*
    ** At this point, there should be no outstanding memory allocations on
    ** the heap.  Also, since both the master and memsys locks are currently
    ** the heap.  Also, since both the main and memsys locks are currently
    ** being held by us, no other function (i.e. from another thread) should
    ** be able to even access the heap.  Attempt to destroy and recreate our
    ** isolated Win32 native heap now.
    */
    assert( winMemGetHeap()!=NULL );
    assert( winMemGetOwned() );
    assert( sqlite3_memory_used()==0 );
1319
1320
1321
1322
1323
1324
1325
1326

1327
1328
1329
1330
1331
1332
1333
1319
1320
1321
1322
1323
1324
1325

1326
1327
1328
1329
1330
1331
1332
1333







-
+







  }else{
    /*
    ** The Win32 native heap cannot be modified because it may be in use.
    */
    rc = SQLITE_BUSY;
  }
  sqlite3_mutex_leave(pMem);
  sqlite3_mutex_leave(pMaster);
  sqlite3_mutex_leave(pMainMtx);
  return rc;
}
#endif /* SQLITE_WIN32_MALLOC */

/*
** This function outputs the specified (ANSI) string to the Win32 debugger
** (if available).
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
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







+

-
+


+














-
+
+




-
+
+
+

+
+
-
+







** it accepts a UTF-8 string.
*/
int sqlite3_win32_set_directory8(
  unsigned long type, /* Identifier for directory being set or reset */
  const char *zValue  /* New value for directory being set or reset */
){
  char **ppDirectory = 0;
  int rc;
#ifndef SQLITE_OMIT_AUTOINIT
  int rc = sqlite3_initialize();
  rc = sqlite3_initialize();
  if( rc ) return rc;
#endif
  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
  if( type==SQLITE_WIN32_DATA_DIRECTORY_TYPE ){
    ppDirectory = &sqlite3_data_directory;
  }else if( type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE ){
    ppDirectory = &sqlite3_temp_directory;
  }
  assert( !ppDirectory || type==SQLITE_WIN32_DATA_DIRECTORY_TYPE
          || type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE
  );
  assert( !ppDirectory || sqlite3MemdebugHasType(*ppDirectory, MEMTYPE_HEAP) );
  if( ppDirectory ){
    char *zCopy = 0;
    if( zValue && zValue[0] ){
      zCopy = sqlite3_mprintf("%s", zValue);
      if ( zCopy==0 ){
        return SQLITE_NOMEM_BKPT;
        rc = SQLITE_NOMEM_BKPT;
        goto set_directory8_done;
      }
    }
    sqlite3_free(*ppDirectory);
    *ppDirectory = zCopy;
    return SQLITE_OK;
    rc = SQLITE_OK;
  }else{
    rc = SQLITE_ERROR;
  }
set_directory8_done:
  sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
  return SQLITE_ERROR;
  return rc;
}

/*
** This function is the same as sqlite3_win32_set_directory (below); however,
** it accepts a UTF-16 string.
*/
int sqlite3_win32_set_directory16(
3498
3499
3500
3501
3502
3503
3504

3505
3506
3507
3508
3509
3510
3511
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519







+







    pFile->ctrlFlags |= mask;
  }
}

/* Forward references to VFS helper methods used for temporary files */
static int winGetTempname(sqlite3_vfs *, char **);
static int winIsDir(const void *);
static BOOL winIsLongPathPrefix(const char *);
static BOOL winIsDriveLetterAndColon(const char *);

/*
** Control and query of the open file handle.
*/
static int winFileControl(sqlite3_file *id, int op, void *pArg){
  winFile *pFile = (winFile*)id;
4065
4066
4067
4068
4069
4070
4071
4072

4073
4074
4075




4076
4077
4078
4079
4080
4081
4082
4073
4074
4075
4076
4077
4078
4079

4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094







-
+



+
+
+
+







  int ofst,                  /* First lock to acquire or release */
  int n,                     /* Number of locks to acquire or release */
  int flags                  /* What to do with the lock */
){
  winFile *pDbFd = (winFile*)fd;        /* Connection holding shared memory */
  winShm *p = pDbFd->pShm;              /* The shared memory being locked */
  winShm *pX;                           /* For looping over all siblings */
  winShmNode *pShmNode = p->pShmNode;
  winShmNode *pShmNode;
  int rc = SQLITE_OK;                   /* Result code */
  u16 mask;                             /* Mask of locks to take or release */

  if( p==0 ) return SQLITE_IOERR_SHMLOCK;
  pShmNode = p->pShmNode;
  if( NEVER(pShmNode==0) ) return SQLITE_IOERR_SHMLOCK;

  assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK );
  assert( n>=1 );
  assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED)
       || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE)
       || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
       || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
  assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
4211
4212
4213
4214
4215
4216
4217

4218
4219
4220
4221
4222
4223
4224
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237







+







  DWORD flags = FILE_MAP_WRITE | FILE_MAP_READ;
  int rc = SQLITE_OK;

  if( !pShm ){
    rc = winOpenSharedMemory(pDbFd);
    if( rc!=SQLITE_OK ) return rc;
    pShm = pDbFd->pShm;
    assert( pShm!=0 );
  }
  pShmNode = pShm->pShmNode;

  sqlite3_mutex_enter(pShmNode->mutex);
  if( pShmNode->isUnlocked ){
    rc = winLockSharedMemory(pShmNode);
    if( rc!=SQLITE_OK ) goto shmpage_out;
4513
4514
4515
4516
4517
4518
4519

4520
4521
4522
4523
4524
4525
4526
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540







+







      if( rc!=SQLITE_OK ){
        OSTRACE(("FETCH pid=%lu, pFile=%p, rc=%s\n",
                 osGetCurrentProcessId(), pFd, sqlite3ErrName(rc)));
        return rc;
      }
    }
    if( pFd->mmapSize >= iOff+nAmt ){
      assert( pFd->pMapRegion!=0 );
      *pp = &((u8 *)pFd->pMapRegion)[iOff];
      pFd->nFetchOut++;
    }
  }
#endif

  OSTRACE(("FETCH pid=%lu, pFile=%p, pp=%p, *pp=%p, rc=SQLITE_OK\n",
4705
4706
4707
4708
4709
4710
4711













4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745







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







        zBuf[nLen+1] = '\0';
        return 1;
      }
    }
  }
  return 0;
}

/*
** If sqlite3_temp_directory is defined, take the mutex and return true.
**
** If sqlite3_temp_directory is NULL (undefined), omit the mutex and
** return false.
*/
static int winTempDirDefined(void){
  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
  if( sqlite3_temp_directory!=0 ) return 1;
  sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
  return 0;
}

/*
** Create a temporary file name and store the resulting pointer into pzBuf.
** The pointer returned in pzBuf must be freed via sqlite3_free().
*/
static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
  static char zChars[] =
4742
4743
4744
4745
4746
4747
4748
4749

4750
4751
4752
4753
4754
4755

4756
4757
4758
4759
4760
4761

4762

4763
4764
4765
4766
4767
4768
4769
4769
4770
4771
4772
4773
4774
4775

4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799







-
+






+






+

+








  /* Figure out the effective temporary directory.  First, check if one
  ** has been explicitly set by the application; otherwise, use the one
  ** configured by the operating system.
  */
  nDir = nMax - (nPre + 15);
  assert( nDir>0 );
  if( sqlite3_temp_directory ){
  if( winTempDirDefined() ){
    int nDirLen = sqlite3Strlen30(sqlite3_temp_directory);
    if( nDirLen>0 ){
      if( !winIsDirSep(sqlite3_temp_directory[nDirLen-1]) ){
        nDirLen++;
      }
      if( nDirLen>nDir ){
        sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
        sqlite3_free(zBuf);
        OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n"));
        return winLogError(SQLITE_ERROR, 0, "winGetTempname1", 0);
      }
      sqlite3_snprintf(nMax, zBuf, "%s", sqlite3_temp_directory);
    }
    sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
  }

#if defined(__CYGWIN__)
  else{
    static const char *azDirs[] = {
       0, /* getenv("SQLITE_TMPDIR") */
       0, /* getenv("TMPDIR") */
       0, /* getenv("TMP") */
       0, /* getenv("TEMP") */
5016
5017
5018
5019
5020
5021
5022
5023

5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044

5045
5046
5047
5048

5049
5050
5051
5052
5053
5054

5055
5056
5057
5058
5059
5060
5061
5046
5047
5048
5049
5050
5051
5052

5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073

5074
5075
5076
5077

5078
5079
5080
5081
5082
5083

5084
5085
5086
5087
5088
5089
5090
5091







-
+




















-
+



-
+





-
+







  int isDelete     = (flags & SQLITE_OPEN_DELETEONCLOSE);
  int isCreate     = (flags & SQLITE_OPEN_CREATE);
  int isReadonly   = (flags & SQLITE_OPEN_READONLY);
  int isReadWrite  = (flags & SQLITE_OPEN_READWRITE);

#ifndef NDEBUG
  int isOpenJournal = (isCreate && (
        eType==SQLITE_OPEN_MASTER_JOURNAL
        eType==SQLITE_OPEN_SUPER_JOURNAL
     || eType==SQLITE_OPEN_MAIN_JOURNAL
     || eType==SQLITE_OPEN_WAL
  ));
#endif

  OSTRACE(("OPEN name=%s, pFile=%p, flags=%x, pOutFlags=%p\n",
           zUtf8Name, id, flags, pOutFlags));

  /* Check the following statements are true:
  **
  **   (a) Exactly one of the READWRITE and READONLY flags must be set, and
  **   (b) if CREATE is set, then READWRITE must also be set, and
  **   (c) if EXCLUSIVE is set, then CREATE must also be set.
  **   (d) if DELETEONCLOSE is set, then CREATE must also be set.
  */
  assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly));
  assert(isCreate==0 || isReadWrite);
  assert(isExclusive==0 || isCreate);
  assert(isDelete==0 || isCreate);

  /* The main DB, main journal, WAL file and master journal are never
  /* The main DB, main journal, WAL file and super-journal are never
  ** automatically deleted. Nor are they ever temporary files.  */
  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_SUPER_JOURNAL );
  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );

  /* Assert that the upper layer has set one of the "file-type" flags. */
  assert( eType==SQLITE_OPEN_MAIN_DB      || eType==SQLITE_OPEN_TEMP_DB
       || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
       || eType==SQLITE_OPEN_SUBJOURNAL   || eType==SQLITE_OPEN_MASTER_JOURNAL
       || eType==SQLITE_OPEN_SUBJOURNAL   || eType==SQLITE_OPEN_SUPER_JOURNAL
       || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
  );

  assert( pFile!=0 );
  memset(pFile, 0, sizeof(winFile));
  pFile->h = INVALID_HANDLE_VALUE;

5119
5120
5121
5122
5123
5124
5125

5126




5127
5128
5129
5130
5131
5132
5133
5149
5150
5151
5152
5153
5154
5155
5156

5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167







+
-
+
+
+
+







    /* Open existing file, or create if it doesn't exist */
    dwCreationDisposition = OPEN_ALWAYS;
  }else{
    /* Opens a file, only if it exists. */
    dwCreationDisposition = OPEN_EXISTING;
  }

  if( 0==sqlite3_uri_boolean(zName, "exclusive", 0) ){
  dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
    dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
  }else{
    dwShareMode = 0;
  }

  if( isDelete ){
#if SQLITE_OS_WINCE
    dwFlagsAndAttributes = FILE_ATTRIBUTE_HIDDEN;
    isTemp = 1;
#else
    dwFlagsAndAttributes = FILE_ATTRIBUTE_TEMPORARY
5259
5260
5261
5262
5263
5264
5265
5266

5267
5268
5269
5270
5271

5272


5273
5274
5275
5276
5277
5278
5279
5293
5294
5295
5296
5297
5298
5299

5300
5301
5302
5303
5304
5305
5306

5307
5308
5309
5310
5311
5312
5313
5314
5315







-
+





+
-
+
+







  }else
#endif
  {
    sqlite3_free(zConverted);
  }

  sqlite3_free(zTmpname);
  pFile->pMethod = pAppData ? pAppData->pMethod : &winIoMethod;
  id->pMethods = pAppData ? pAppData->pMethod : &winIoMethod;
  pFile->pVfs = pVfs;
  pFile->h = h;
  if( isReadonly ){
    pFile->ctrlFlags |= WINFILE_RDONLY;
  }
  if( (flags & SQLITE_OPEN_MAIN_DB)
  if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){
   && sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) 
  ){
    pFile->ctrlFlags |= WINFILE_PSOW;
  }
  pFile->lastErrno = NO_ERROR;
  pFile->zPath = zName;
#if SQLITE_MAX_MMAP_SIZE>0
  pFile->hMap = NULL;
  pFile->pMapRegion = 0;
5474
5475
5476
5477
5478
5479
5480











5481
5482
5483
5484
5485
5486
5487
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534







+
+
+
+
+
+
+
+
+
+
+







      assert(!"Invalid flags argument");
  }
  *pResOut = rc;
  OSTRACE(("ACCESS name=%s, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n",
           zFilename, pResOut, *pResOut));
  return SQLITE_OK;
}

/*
** Returns non-zero if the specified path name starts with the "long path"
** prefix.
*/
static BOOL winIsLongPathPrefix(
  const char *zPathname
){
  return ( zPathname[0]=='\\' && zPathname[1]=='\\'
        && zPathname[2]=='?'  && zPathname[3]=='\\' );
}

/*
** Returns non-zero if the specified path name starts with a drive letter
** followed by a colon character.
*/
static BOOL winIsDriveLetterAndColon(
  const char *zPathname
5527
5528
5529
5530
5531
5532
5533
5534

5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547


5548
5549


5550
5551
5552
5553
5554
5555
5556
5574
5575
5576
5577
5578
5579
5580

5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592


5593
5594
5595

5596
5597
5598
5599
5600
5601
5602
5603
5604







-
+











-
-
+
+

-
+
+







}

/*
** Turn a relative pathname into a full pathname.  Write the full
** pathname into zOut[].  zOut[] will be at least pVfs->mxPathname
** bytes in size.
*/
static int winFullPathname(
static int winFullPathnameNoMutex(
  sqlite3_vfs *pVfs,            /* Pointer to vfs object */
  const char *zRelative,        /* Possibly relative input path */
  int nFull,                    /* Size of output buffer in bytes */
  char *zFull                   /* Output buffer */
){
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(__CYGWIN__)
  DWORD nByte;
  void *zConverted;
  char *zOut;
#endif

  /* If this path name begins with "/X:", where "X" is any alphabetic
  ** character, discard the initial "/" from the pathname.
  /* If this path name begins with "/X:" or "\\?\", where "X" is any
  ** alphabetic character, discard the initial "/" from the pathname.
  */
  if( zRelative[0]=='/' && winIsDriveLetterAndColon(zRelative+1) ){
  if( zRelative[0]=='/' && (winIsDriveLetterAndColon(zRelative+1)
       || winIsLongPathPrefix(zRelative+1)) ){
    zRelative++;
  }

#if defined(__CYGWIN__)
  SimulateIOError( return SQLITE_ERROR );
  UNUSED_PARAMETER(nFull);
  assert( nFull>=pVfs->mxPathname );
5704
5705
5706
5707
5708
5709
5710














5711
5712
5713
5714
5715
5716
5717
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779







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







    sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut);
    sqlite3_free(zOut);
    return SQLITE_OK;
  }else{
    return SQLITE_IOERR_NOMEM_BKPT;
  }
#endif
}
static int winFullPathname(
  sqlite3_vfs *pVfs,            /* Pointer to vfs object */
  const char *zRelative,        /* Possibly relative input path */
  int nFull,                    /* Size of output buffer in bytes */
  char *zFull                   /* Output buffer */
){
  int rc;
  MUTEX_LOGIC( sqlite3_mutex *pMutex; )
  MUTEX_LOGIC( pMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR); )
  sqlite3_mutex_enter(pMutex);
  rc = winFullPathnameNoMutex(pVfs, zRelative, nFull, zFull);
  sqlite3_mutex_leave(pMutex);
  return rc;
}

#ifndef SQLITE_OMIT_LOAD_EXTENSION
/*
** Interfaces for opening a shared library, finding entry points
** within the shared library, and closing the shared library.
*/

Changes to src/pager.c.

66
67
68
69
70
71
72
73
74


75
76
77
78
79
80
81
66
67
68
69
70
71
72


73
74
75
76
77
78
79
80
81







-
-
+
+







** (4) Reads from the database file are either aligned on a page boundary and
**     an integer multiple of the page size in length or are taken from the
**     first 100 bytes of the database file.
** 
** (5) All writes to the database file are synced prior to the rollback journal
**     being deleted, truncated, or zeroed.
** 
** (6) If a master journal file is used, then all writes to the database file
**     are synced prior to the master journal being deleted.
** (6) If a super-journal file is used, then all writes to the database file
**     are synced prior to the super-journal being deleted.
** 
** Definition: Two databases (or the same database at two points it time)
** are said to be "logically equivalent" if they give the same answer to
** all queries.  Note in particular the content of freelist leaf
** pages can be changed arbitrarily without affecting the logical equivalence
** of the database.
** 
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
402
403
404
405
406
407
408














409
410
411
412
413
414
415







-
-
-
-
-
-
-
-
-
-
-
-
-
-







** PagerSharedLock() for more detail.
**
** Pager.eLock may only be set to UNKNOWN_LOCK when the pager is in 
** PAGER_OPEN state.
*/
#define UNKNOWN_LOCK                (EXCLUSIVE_LOCK+1)

/*
** A macro used for invoking the codec if there is one
*/
#ifdef SQLITE_HAS_CODEC
# define CODEC1(P,D,N,X,E) \
    if( P->xCodec && P->xCodec(P->pCodec,D,N,X)==0 ){ E; }
# define CODEC2(P,D,N,X,E,O) \
    if( P->xCodec==0 ){ O=(char*)D; }else \
    if( (O=(char*)(P->xCodec(P->pCodec,D,N,X)))==0 ){ E; }
#else
# define CODEC1(P,D,N,X,E)   /* NO-OP */
# define CODEC2(P,D,N,X,E,O) O=(char*)D
#endif

/*
** The maximum allowed sector size. 64KiB. If the xSectorsize() method 
** returns a value larger than this, then MAX_SECTOR_SIZE is used instead.
** This could conceivably cause corruption following a power failure on
** such a system. This is currently an undocumented limit.
*/
#define MAX_SECTOR_SIZE 0x10000
445
446
447
448
449
450
451

452
453
454
455
456
457
458
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445







+







typedef struct PagerSavepoint PagerSavepoint;
struct PagerSavepoint {
  i64 iOffset;                 /* Starting offset in main journal */
  i64 iHdrOffset;              /* See above */
  Bitvec *pInSavepoint;        /* Set of pages in this savepoint */
  Pgno nOrig;                  /* Original number of pages in file */
  Pgno iSubRec;                /* Index of first record in sub-journal */
  int bTruncateOnRelease;      /* If stmt journal may be truncated on RELEASE */
#ifndef SQLITE_OMIT_WAL
  u32 aWalData[WAL_SAVEPOINT_NDATA];        /* WAL savepoint context */
#endif
};

/*
** Bits of the Pager.doNotSpill flag.  See further description below.
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
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







-
+


-
+


-
+


-
+

-
+



-
+

-
+




-
+







**   The changeCountDone flag is inspected. If it is true, the work of
**   updating the change-counter is omitted for the current transaction.
**
**   This mechanism means that when running in exclusive mode, a connection 
**   need only update the change-counter once, for the first transaction
**   committed.
**
** setMaster
** setSuper
**
**   When PagerCommitPhaseOne() is called to commit a transaction, it may
**   (or may not) specify a master-journal name to be written into the 
**   (or may not) specify a super-journal name to be written into the 
**   journal file before it is synced to disk.
**
**   Whether or not a journal file contains a master-journal pointer affects 
**   Whether or not a journal file contains a super-journal pointer affects 
**   the way in which the journal file is finalized after the transaction is 
**   committed or rolled back when running in "journal_mode=PERSIST" mode.
**   If a journal file does not contain a master-journal pointer, it is
**   If a journal file does not contain a super-journal pointer, it is
**   finalized by overwriting the first journal header with zeroes. If
**   it does contain a master-journal pointer the journal file is finalized 
**   it does contain a super-journal pointer the journal file is finalized 
**   by truncating it to zero bytes, just as if the connection were 
**   running in "journal_mode=truncate" mode.
**
**   Journal files that contain master journal pointers cannot be finalized
**   Journal files that contain super-journal pointers cannot be finalized
**   simply by overwriting the first journal-header with zeroes, as the
**   master journal pointer could interfere with hot-journal rollback of any
**   super-journal pointer could interfere with hot-journal rollback of any
**   subsequently interrupted transaction that reuses the journal file.
**
**   The flag is cleared as soon as the journal file is finalized (either
**   by PagerCommitPhaseTwo or PagerRollback). If an IO error prevents the
**   journal file from being successfully finalized, the setMaster flag
**   journal file from being successfully finalized, the setSuper flag
**   is cleared anyway (and the pager will move to ERROR state).
**
** doNotSpill
**
**   This variables control the behavior of cache-spills  (calls made by
**   the pcache module to the pagerStress() routine to write cached data
**   to the file-system in order to free up memory).
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
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







+













-
+







  u8 extraSync;               /* sync directory after journal delete */
  u8 syncFlags;               /* SYNC_NORMAL or SYNC_FULL otherwise */
  u8 walSyncFlags;            /* See description above */
  u8 tempFile;                /* zFilename is a temporary or immutable file */
  u8 noLock;                  /* Do not lock (except in WAL mode) */
  u8 readOnly;                /* True for a read-only database */
  u8 memDb;                   /* True to inhibit all file I/O */
  u8 memVfs;                  /* VFS-implemented memory database */

  /**************************************************************************
  ** The following block contains those class members that change during
  ** routine operation.  Class members not in this block are either fixed
  ** when the pager is first created or else only change when there is a
  ** significant mode change (such as changing the page_size, locking_mode,
  ** or the journal_mode).  From another view, these class members describe
  ** the "state" of the pager, while other class members describe the
  ** "configuration" of the pager.
  */
  u8 eState;                  /* Pager state (OPEN, READER, WRITER_LOCKED..) */
  u8 eLock;                   /* Current lock held on database file */
  u8 changeCountDone;         /* Set after incrementing the change-counter */
  u8 setMaster;               /* True if a m-j name has been written to jrnl */
  u8 setSuper;                /* Super-jrnl name is written into jrnl */
  u8 doNotSpill;              /* Do not spill the cache when non-zero */
  u8 subjInMemory;            /* True to use in-memory sub-journals */
  u8 bUseFetch;               /* True to use xFetch() */
  u8 hasHeldSharedLock;       /* True if a shared lock has ever been held */
  Pgno dbSize;                /* Number of pages in the database */
  Pgno dbOrigSize;            /* dbSize before the current transaction */
  Pgno dbFileSize;            /* Number of pages in the database file */
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
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







-

+
+











-
-
-
-
-
-







  ** End of the routinely-changing class members
  ***************************************************************************/

  u16 nExtra;                 /* Add this many bytes to each in-memory page */
  i16 nReserve;               /* Number of unused bytes at end of each page */
  u32 vfsFlags;               /* Flags for sqlite3_vfs.xOpen() */
  u32 sectorSize;             /* Assumed sector size during rollback */
  int pageSize;               /* Number of bytes in a page */
  Pgno mxPgno;                /* Maximum allowed size of the database */
  Pgno lckPgno;               /* Page number for the locking page */
  i64 pageSize;               /* Number of bytes in a page */
  i64 journalSizeLimit;       /* Size limit for persistent journal files */
  char *zFilename;            /* Name of the database file */
  char *zJournal;             /* Name of the journal file */
  int (*xBusyHandler)(void*); /* Function to call when busy */
  void *pBusyHandlerArg;      /* Context argument for xBusyHandler */
  int aStat[4];               /* Total cache hits, misses, writes, spills */
#ifdef SQLITE_TEST
  int nRead;                  /* Database pages read */
#endif
  void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */
  int (*xGet)(Pager*,Pgno,DbPage**,int); /* Routine to fetch a patch */
#ifdef SQLITE_HAS_CODEC
  void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
  void (*xCodecSizeChng)(void*,int,int); /* Notify of page size changes */
  void (*xCodecFree)(void*);             /* Destructor for the codec */
  void *pCodec;               /* First argument to xCodec... methods */
#endif
  char *pTmpSpace;            /* Pager.pageSize bytes of space for tmp use */
  PCache *pPCache;            /* Pointer to page cache object */
#ifndef SQLITE_OMIT_WAL
  Wal *pWal;                  /* Write-ahead log used by "journal_mode=wal" */
  char *zWal;                 /* File name for write-ahead log */
#endif
};
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
788
789
790
791
792
793
794



















795
796
797
798
799
800
801







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







*/
#if SQLITE_MAX_MMAP_SIZE>0
# define USEFETCH(x) ((x)->bUseFetch)
#else
# define USEFETCH(x) 0
#endif

/*
** The maximum legal page number is (2^31 - 1).
*/
#define PAGER_MAX_PGNO 2147483647

/*
** The argument to this macro is a file descriptor (type sqlite3_file*).
** Return 0 if it is not open, or non-zero (but not 1) if it is.
**
** This is so that expressions can be written as:
**
**   if( isOpen(pPager->jfd) ){ ...
**
** instead of
**
**   if( pPager->jfd->pMethods ){ ...
*/
#define isOpen(pFd) ((pFd)->pMethods!=0)

#ifdef SQLITE_DIRECT_OVERFLOW_READ
/*
** Return true if page pgno can be read directly from the database file
** by the b-tree layer. This is the case if:
**
**   * the database file is open,
**   * there are no dirty pages in the cache, and
941
942
943
944
945
946
947
948

949
950
951
952
953
954
955
956
957
958
959
960
961
962
963

964
965
966
967
968
969
970
971
972
973
974
975
976
977

978
979
980
981
982
983
984
985
986
987
988
989

990
991
992
993
994
995
996
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963







-
+















+














+












+







        assert( p->eLock>=RESERVED_LOCK );
      }
#ifndef SQLITE_OMIT_CONCURRENT
      assert( pPager->dbSize==pPager->dbOrigSize || pPager->pAllRead );
#endif
      assert( pPager->dbOrigSize==pPager->dbFileSize );
      assert( pPager->dbOrigSize==pPager->dbHintSize );
      assert( pPager->setMaster==0 );
      assert( pPager->setSuper==0 );
      break;

    case PAGER_WRITER_CACHEMOD:
      assert( p->eLock!=UNKNOWN_LOCK );
      assert( pPager->errCode==SQLITE_OK );
      if( !pagerUseWal(pPager) ){
        /* It is possible that if journal_mode=wal here that neither the
        ** journal file nor the WAL file are open. This happens during
        ** a rollback transaction that switches from journal_mode=off
        ** to journal_mode=wal.
        */
        assert( p->eLock>=RESERVED_LOCK );
        assert( isOpen(p->jfd) 
             || p->journalMode==PAGER_JOURNALMODE_OFF 
             || p->journalMode==PAGER_JOURNALMODE_WAL 
             || p->journalMode==PAGER_JOURNALMODE_WAL2
        );
      }
      assert( pPager->dbOrigSize==pPager->dbFileSize );
      assert( pPager->dbOrigSize==pPager->dbHintSize );
      break;

    case PAGER_WRITER_DBMOD:
      assert( p->eLock==EXCLUSIVE_LOCK );
      assert( pPager->errCode==SQLITE_OK );
      assert( !pagerUseWal(pPager) );
      assert( p->eLock>=EXCLUSIVE_LOCK );
      assert( isOpen(p->jfd) 
           || p->journalMode==PAGER_JOURNALMODE_OFF 
           || p->journalMode==PAGER_JOURNALMODE_WAL 
           || p->journalMode==PAGER_JOURNALMODE_WAL2
           || (sqlite3OsDeviceCharacteristics(p->fd)&SQLITE_IOCAP_BATCH_ATOMIC)
      );
      assert( pPager->dbOrigSize<=pPager->dbHintSize );
      break;

    case PAGER_WRITER_FINISHED:
      assert( p->eLock==EXCLUSIVE_LOCK );
      assert( pPager->errCode==SQLITE_OK );
      assert( !pagerUseWal(pPager) );
      assert( isOpen(p->jfd) 
           || p->journalMode==PAGER_JOURNALMODE_OFF 
           || p->journalMode==PAGER_JOURNALMODE_WAL 
           || p->journalMode==PAGER_JOURNALMODE_WAL2
           || (sqlite3OsDeviceCharacteristics(p->fd)&SQLITE_IOCAP_BATCH_ATOMIC)
      );
      break;

    case PAGER_ERROR:
      /* There must be at least one outstanding reference to the pager if
      ** in ERROR state. Otherwise the pager should have already dropped
1071
1072
1073
1074
1075
1076
1077
1078

1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1038
1039
1040
1041
1042
1043
1044

1045




1046
1047
1048
1049
1050
1051
1052







-
+
-
-
-
-







** Set the Pager.xGet method for the appropriate routine used to fetch
** content from the pager.
*/
static void setGetterMethod(Pager *pPager){
  if( pPager->errCode ){
    pPager->xGet = getPageError;
#if SQLITE_MAX_MMAP_SIZE>0
  }else if( USEFETCH(pPager)
  }else if( USEFETCH(pPager) ){
#ifdef SQLITE_HAS_CODEC
   && pPager->xCodec==0
#endif
  ){
    pPager->xGet = getPageMMap;
#endif /* SQLITE_MAX_MMAP_SIZE>0 */
  }else{
    pPager->xGet = getPageNormal;
  }
}

1100
1101
1102
1103
1104
1105
1106



1107
1108
1109
1110
1111
1112
1113
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079







+
+
+







  Pager *pPager = pPg->pPager;
  PagerSavepoint *p;
  Pgno pgno = pPg->pgno;
  int i;
  for(i=0; i<pPager->nSavepoint; i++){
    p = &pPager->aSavepoint[i];
    if( p->nOrig>=pgno && 0==sqlite3BitvecTestNotNull(p->pInSavepoint, pgno) ){
      for(i=i+1; i<pPager->nSavepoint; i++){
        pPager->aSavepoint[i].bTruncateOnRelease = 0;
      }
      return 1;
    }
  }
  return 0;
}

#ifdef SQLITE_DEBUG
1170
1171
1172
1173
1174
1175
1176

1177
1178
1179
1180
1181
1182
1183
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150







+







    assert( pPager->eLock>=eLock );
    rc = pPager->noLock ? SQLITE_OK : sqlite3OsUnlock(pPager->fd, eLock);
    if( pPager->eLock!=UNKNOWN_LOCK ){
      pPager->eLock = (u8)eLock;
    }
    IOTRACE(("UNLOCK %p %d\n", pPager, eLock))
  }
  pPager->changeCountDone = pPager->tempFile; /* ticket fb3b3024ea238d5c */
  return rc;
}

/*
** Lock the database file to level eLock, which must be either SHARED_LOCK,
** RESERVED_LOCK or EXCLUSIVE_LOCK. If the caller is successful, set the
** Pager.eLock variable to the new locking state. 
1298
1299
1300
1301
1302
1303
1304
1305

1306
1307
1308


1309
1310

1311
1312
1313
1314



1315
1316
1317
1318
1319
1320




1321
1322
1323


1324
1325
1326
1327
1328

1329
1330

1331
1332
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
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

1318
1319

1320
1321
1322
1323

1324
1325

1326
1327
1328
1329

1330
1331
1332
1333
1334
1335
1336
1337
1338







-
+

-
-
+
+

-
+

-
-
-
+
+
+


-
-
-
-
+
+
+
+

-
-
+
+




-
+

-
+




-
+




-
+





-
+




-
+

-
+



-
+

-
+



-
+
+







#define pager_pagehash(X)  0
#define pager_set_pagehash(X)
#define CHECK_PAGE(x)
#endif  /* SQLITE_CHECK_PAGES */

/*
** When this is called the journal file for pager pPager must be open.
** This function attempts to read a master journal file name from the 
** This function attempts to read a super-journal file name from the 
** end of the file and, if successful, copies it into memory supplied 
** by the caller. See comments above writeMasterJournal() for the format
** used to store a master journal file name at the end of a journal file.
** by the caller. See comments above writeSuperJournal() for the format
** used to store a super-journal file name at the end of a journal file.
**
** zMaster must point to a buffer of at least nMaster bytes allocated by
** zSuper must point to a buffer of at least nSuper bytes allocated by
** the caller. This should be sqlite3_vfs.mxPathname+1 (to ensure there is
** enough space to write the master journal name). If the master journal
** name in the journal is longer than nMaster bytes (including a
** nul-terminator), then this is handled as if no master journal name
** enough space to write the super-journal name). If the super-journal
** name in the journal is longer than nSuper bytes (including a
** nul-terminator), then this is handled as if no super-journal name
** were present in the journal.
**
** If a master journal file name is present at the end of the journal
** file, then it is copied into the buffer pointed to by zMaster. A
** nul-terminator byte is appended to the buffer following the master
** journal file name.
** If a super-journal file name is present at the end of the journal
** file, then it is copied into the buffer pointed to by zSuper. A
** nul-terminator byte is appended to the buffer following the
** super-journal file name.
**
** If it is determined that no master journal file name is present 
** zMaster[0] is set to 0 and SQLITE_OK returned.
** If it is determined that no super-journal file name is present 
** zSuper[0] is set to 0 and SQLITE_OK returned.
**
** If an error occurs while reading from the journal file, an SQLite
** error code is returned.
*/
static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, u32 nMaster){
static int readSuperJournal(sqlite3_file *pJrnl, char *zSuper, u32 nSuper){
  int rc;                    /* Return code */
  u32 len;                   /* Length in bytes of master journal name */
  u32 len;                   /* Length in bytes of super-journal name */
  i64 szJ;                   /* Total size in bytes of journal file pJrnl */
  u32 cksum;                 /* MJ checksum value read from journal */
  u32 u;                     /* Unsigned loop counter */
  unsigned char aMagic[8];   /* A buffer to hold the magic header */
  zMaster[0] = '\0';
  zSuper[0] = '\0';

  if( SQLITE_OK!=(rc = sqlite3OsFileSize(pJrnl, &szJ))
   || szJ<16
   || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len))
   || len>=nMaster 
   || len>=nSuper 
   || len>szJ-16
   || len==0 
   || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum))
   || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8))
   || memcmp(aMagic, aJournalMagic, 8)
   || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, zMaster, len, szJ-16-len))
   || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, zSuper, len, szJ-16-len))
  ){
    return rc;
  }

  /* See if the checksum matches the master journal name */
  /* See if the checksum matches the super-journal name */
  for(u=0; u<len; u++){
    cksum -= zMaster[u];
    cksum -= zSuper[u];
  }
  if( cksum ){
    /* If the checksum doesn't add up, then one or more of the disk sectors
    ** containing the master journal filename is corrupted. This means
    ** containing the super-journal filename is corrupted. This means
    ** definitely roll back, so just return SQLITE_OK and report a (nul)
    ** master-journal filename.
    ** super-journal filename.
    */
    len = 0;
  }
  zMaster[len] = '\0';
  zSuper[len] = '\0';
  zSuper[len+1] = '\0';
   
  return SQLITE_OK;
}

/*
** Return the offset of the sector boundary at or immediately 
** following the value in pPager->journalOff, assuming a sector 
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
1744
1745
1746
1747
1748




1749
1750

1751
1752
1753
1754

1755
1756
1757

1758
1759
1760

1761
1762
1763
1764
1765
1766
1767
1652
1653
1654
1655
1656
1657
1658


1659
1660
1661
1662
1663
1664




1665
1666
1667
1668
1669
1670


1671
1672
1673

1674
1675
1676

1677
1678

1679
1680
1681

1682
1683

1684
1685
1686

1687
1688
1689
1690
1691
1692

1693
1694
1695



1696
1697
1698
1699
1700
1701

1702
1703
1704
1705
1706
1707
1708
1709

1710
1711
1712




1713
1714
1715
1716
1717

1718
1719
1720
1721

1722
1723
1724

1725
1726
1727

1728
1729
1730
1731
1732
1733
1734
1735







-
-
+
+




-
-
-
-
+
+
+
+


-
-
+
+

-
+


-
+

-
+


-
+

-
+


-
+





-
+


-
-
-
+
+
+



-
+







-
+


-
-
-
-
+
+
+
+

-
+



-
+


-
+


-
+








  pPager->journalOff += JOURNAL_HDR_SZ(pPager);
  return rc;
}


/*
** Write the supplied master journal name into the journal file for pager
** pPager at the current location. The master journal name must be the last
** Write the supplied super-journal name into the journal file for pager
** pPager at the current location. The super-journal name must be the last
** thing written to a journal file. If the pager is in full-sync mode, the
** journal file descriptor is advanced to the next sector boundary before
** anything is written. The format is:
**
**   + 4 bytes: PAGER_MJ_PGNO.
**   + N bytes: Master journal filename in utf-8.
**   + 4 bytes: N (length of master journal name in bytes, no nul-terminator).
**   + 4 bytes: Master journal name checksum.
**   + 4 bytes: PAGER_SJ_PGNO.
**   + N bytes: super-journal filename in utf-8.
**   + 4 bytes: N (length of super-journal name in bytes, no nul-terminator).
**   + 4 bytes: super-journal name checksum.
**   + 8 bytes: aJournalMagic[].
**
** The master journal page checksum is the sum of the bytes in the master
** journal name, where each byte is interpreted as a signed 8-bit integer.
** The super-journal page checksum is the sum of the bytes in thesuper-journal
** name, where each byte is interpreted as a signed 8-bit integer.
**
** If zMaster is a NULL pointer (occurs for a single database transaction), 
** If zSuper is a NULL pointer (occurs for a single database transaction), 
** this call is a no-op.
*/
static int writeMasterJournal(Pager *pPager, const char *zMaster){
static int writeSuperJournal(Pager *pPager, const char *zSuper){
  int rc;                          /* Return code */
  int nMaster;                     /* Length of string zMaster */
  int nSuper;                      /* Length of string zSuper */
  i64 iHdrOff;                     /* Offset of header in journal file */
  i64 jrnlSize;                    /* Size of journal file on disk */
  u32 cksum = 0;                   /* Checksum of string zMaster */
  u32 cksum = 0;                   /* Checksum of string zSuper */

  assert( pPager->setMaster==0 );
  assert( pPager->setSuper==0 );
  assert( !pagerUseWal(pPager) );

  if( !zMaster 
  if( !zSuper 
   || pPager->journalMode==PAGER_JOURNALMODE_MEMORY 
   || !isOpen(pPager->jfd)
  ){
    return SQLITE_OK;
  }
  pPager->setMaster = 1;
  pPager->setSuper = 1;
  assert( pPager->journalHdr <= pPager->journalOff );

  /* Calculate the length in bytes and the checksum of zMaster */
  for(nMaster=0; zMaster[nMaster]; nMaster++){
    cksum += zMaster[nMaster];
  /* Calculate the length in bytes and the checksum of zSuper */
  for(nSuper=0; zSuper[nSuper]; nSuper++){
    cksum += zSuper[nSuper];
  }

  /* If in full-sync mode, advance to the next disk sector before writing
  ** the master journal name. This is in case the previous page written to
  ** the super-journal name. This is in case the previous page written to
  ** the journal has already been synced.
  */
  if( pPager->fullSync ){
    pPager->journalOff = journalHdrOffset(pPager);
  }
  iHdrOff = pPager->journalOff;

  /* Write the master journal data to the end of the journal file. If
  /* Write the super-journal data to the end of the journal file. If
  ** an error occurs, return the error code to the caller.
  */
  if( (0 != (rc = write32bits(pPager->jfd, iHdrOff, PAGER_MJ_PGNO(pPager))))
   || (0 != (rc = sqlite3OsWrite(pPager->jfd, zMaster, nMaster, iHdrOff+4)))
   || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nMaster, nMaster)))
   || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nMaster+4, cksum)))
  if( (0 != (rc = write32bits(pPager->jfd, iHdrOff, PAGER_SJ_PGNO(pPager))))
   || (0 != (rc = sqlite3OsWrite(pPager->jfd, zSuper, nSuper, iHdrOff+4)))
   || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nSuper, nSuper)))
   || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nSuper+4, cksum)))
   || (0 != (rc = sqlite3OsWrite(pPager->jfd, aJournalMagic, 8,
                                 iHdrOff+4+nMaster+8)))
                                 iHdrOff+4+nSuper+8)))
  ){
    return rc;
  }
  pPager->journalOff += (nMaster+20);
  pPager->journalOff += (nSuper+20);

  /* If the pager is in peristent-journal mode, then the physical 
  ** journal-file may extend past the end of the master-journal name
  ** journal-file may extend past the end of the super-journal name
  ** and 8 bytes of magic data just written to the file. This is 
  ** dangerous because the code to rollback a hot-journal file
  ** will not be able to find the master-journal name to determine 
  ** will not be able to find the super-journal name to determine 
  ** whether or not the journal is hot. 
  **
  ** Easiest thing to do in this scenario is to truncate the journal 
  ** file to the required size.
  */ 
  if( SQLITE_OK==(rc = sqlite3OsFileSize(pPager->jfd, &jrnlSize))
   && jrnlSize>pPager->journalOff
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1904
1905
1906
1907
1908
1909
1910

1911
1912
1913
1914
1915
1916
1917







-







    }

    /* The pager state may be changed from PAGER_ERROR to PAGER_OPEN here
    ** without clearing the error code. This is intentional - the error
    ** code is cleared and the cache reset in the block below.
    */
    assert( pPager->errCode || pPager->eState!=PAGER_ERROR );
    pPager->changeCountDone = 0;
    pPager->eState = PAGER_OPEN;
  }

  /* If Pager.errCode is set, the contents of the pager cache cannot be
  ** trusted. Now that there are no outstanding references to the pager,
  ** it can safely move back to PAGER_OPEN state. This happens in both
  ** normal and exclusive-locking mode.
1961
1962
1963
1964
1965
1966
1967
1968

1969
1970
1971
1972
1973
1974
1975
1928
1929
1930
1931
1932
1933
1934

1935
1936
1937
1938
1939
1940
1941
1942







-
+







    if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0);
    pPager->errCode = SQLITE_OK;
    setGetterMethod(pPager);
  }

  pPager->journalOff = 0;
  pPager->journalHdr = 0;
  pPager->setMaster = 0;
  pPager->setSuper = 0;
}

/*
** This function is called whenever an IOERR or FULL error that requires
** the pager to transition into the ERROR state may ahve occurred.
** The first argument is a pointer to the pager structure, the second 
** the error-code about to be returned by a pager API function. The 
2077
2078
2079
2080
2081
2082
2083
2084

2085
2086
2087
2088
2089
2090
2091
2044
2045
2046
2047
2048
2049
2050

2051
2052
2053
2054
2055
2056
2057
2058







-
+







** database then the IO error code is returned to the user. If the 
** operation to finalize the journal file fails, then the code still
** tries to unlock the database file if not in exclusive mode. If the
** unlock operation fails as well, then the first error code related
** to the first error encountered (the journal finalization one) is
** returned.
*/
static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
static int pager_end_transaction(Pager *pPager, int hasSuper, int bCommit){
  int rc = SQLITE_OK;      /* Error code from journal finalization operation */
  int rc2 = SQLITE_OK;     /* Error code from db file unlock operation */

  /* Do nothing if the pager does not have an open write transaction
  ** or at least a RESERVED lock. This function may be called when there
  ** is no write-transaction active but a RESERVED or greater lock is
  ** held under two circumstances:
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
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







-
+

-
+











-
+
+







          ** https://bugzilla.mozilla.org/show_bug.cgi?id=1072773
          */
          rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags);
        }
      }
      pPager->journalOff = 0;
    }else if( pPager->journalMode==PAGER_JOURNALMODE_PERSIST
      || (pPager->exclusiveMode && pPager->journalMode!=PAGER_JOURNALMODE_WAL)
      || (pPager->exclusiveMode && pPager->journalMode<PAGER_JOURNALMODE_WAL)
    ){
      rc = zeroJournalHdr(pPager, hasMaster||pPager->tempFile);
      rc = zeroJournalHdr(pPager, hasSuper||pPager->tempFile);
      pPager->journalOff = 0;
    }else{
      /* This branch may be executed with Pager.journalMode==MEMORY if
      ** a hot-journal was just rolled back. In this case the journal
      ** file should be closed and deleted. If this connection writes to
      ** the database file, it will do so using an in-memory journal.
      */
      int bDelete = !pPager->tempFile;
      assert( sqlite3JournalIsInMemory(pPager->jfd)==0 );
      assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE 
           || pPager->journalMode==PAGER_JOURNALMODE_MEMORY 
           || pPager->journalMode==PAGER_JOURNALMODE_WAL 
           || pPager->journalMode==PAGER_JOURNALMODE_WAL
           || pPager->journalMode==PAGER_JOURNALMODE_WAL2
      );
      sqlite3OsClose(pPager->jfd);
      if( bDelete ){
        rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, pPager->extraSync);
      }
    }
  }
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209

2210
2211
2212
2213
2214
2215
2216
2167
2168
2169
2170
2171
2172
2173

2174
2175

2176
2177
2178
2179
2180
2181
2182
2183







-


-
+







    if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
  }

  if( !pPager->exclusiveMode 
   && (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0))
  ){
    rc2 = pagerUnlockDb(pPager, SHARED_LOCK);
    pPager->changeCountDone = 0;
  }
  pPager->eState = PAGER_READER;
  pPager->setMaster = 0;
  pPager->setSuper = 0;

  return (rc==SQLITE_OK?rc2:rc);
}

/*
** Execute a rollback if a transaction is active and unlock the 
** database file. 
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2235
2236
2237
2238
2239
2240
2241





























2242
2243
2244
2245
2246
2247
2248







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







  while( i>0 ){
    cksum += aData[i];
    i -= 200;
  }
  return cksum;
}

/*
** Report the current page size and number of reserved bytes back
** to the codec.
*/
#ifdef SQLITE_HAS_CODEC
static void pagerReportSize(Pager *pPager){
  if( pPager->xCodecSizeChng ){
    pPager->xCodecSizeChng(pPager->pCodec, pPager->pageSize,
                           (int)pPager->nReserve);
  }
}
#else
# define pagerReportSize(X)     /* No-op if we do not support a codec */
#endif

#ifdef SQLITE_HAS_CODEC
/*
** Make sure the number of reserved bits is the same in the destination
** pager as it is in the source.  This comes up when a VACUUM changes the
** number of reserved bits to the "optimal" amount.
*/
void sqlite3PagerAlignReserve(Pager *pDest, Pager *pSrc){
  if( pDest->nReserve!=pSrc->nReserve ){
    pDest->nReserve = pSrc->nReserve;
    pagerReportSize(pDest);
  }
}
#endif

/*
** Read a single page from either the journal file (if isMainJrnl==1) or
** from the sub-journal (if isMainJrnl==0) and playback that page.
** The page begins at offset *pOffset into the file. The *pOffset
** value is increased to the start of the next page in the journal.
**
** The main rollback journal uses checksums - the statement journal does 
2324
2325
2326
2327
2328
2329
2330
2331

2332
2333
2334
2335
2336
2337
2338
2262
2263
2264
2265
2266
2267
2268

2269
2270
2271
2272
2273
2274
2275
2276







-
+







** and played back, then SQLITE_OK is returned. If an IO error occurs
** while reading the record from the (sub-)journal file or while writing
** to the database file, then the IO error code is returned. If data
** is successfully read from the (sub-)journal file but appears to be
** corrupted, SQLITE_DONE is returned. Data is considered corrupted in
** two circumstances:
** 
**   * If the record page-number is illegal (0 or PAGER_MJ_PGNO), or
**   * If the record page-number is illegal (0 or PAGER_SJ_PGNO), or
**   * If the record is being rolled back from the main journal file
**     and the checksum field does not match the record content.
**
** Neither of these two scenarios are possible during a savepoint rollback.
**
** If this is a savepoint rollback, then memory may have to be dynamically
** allocated by this function. If this is the case and an allocation fails,
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2286
2287
2288
2289
2290
2291
2292





2293
2294
2295
2296
2297
2298
2299







-
-
-
-
-







  int rc;
  PgHdr *pPg;                   /* An existing page in the cache */
  Pgno pgno;                    /* The page number of a page in journal */
  u32 cksum;                    /* Checksum used for sanity checking */
  char *aData;                  /* Temporary storage for the page */
  sqlite3_file *jfd;            /* The file descriptor for the journal file */
  int isSynced;                 /* True if journal page is synced */
#ifdef SQLITE_HAS_CODEC
  /* The jrnlEnc flag is true if Journal pages should be passed through
  ** the codec.  It is false for pure in-memory journals. */
  const int jrnlEnc = (isMainJrnl || pPager->subjInMemory==0);
#endif

  assert( (isMainJrnl&~1)==0 );      /* isMainJrnl is 0 or 1 */
  assert( (isSavepnt&~1)==0 );       /* isSavepnt is 0 or 1 */
  assert( isMainJrnl || pDone );     /* pDone always used on sub-journals */
  assert( isSavepnt || pDone==0 );   /* pDone never used on non-savepoint */

  aData = pPager->pTmpSpace;
2389
2390
2391
2392
2393
2394
2395
2396

2397
2398
2399
2400
2401
2402
2403
2322
2323
2324
2325
2326
2327
2328

2329
2330
2331
2332
2333
2334
2335
2336







-
+







  *pOffset += pPager->pageSize + 4 + isMainJrnl*4;

  /* Sanity checking on the page.  This is more important that I originally
  ** thought.  If a power failure occurs while the journal is being written,
  ** it could cause invalid data to be written into the journal.  We need to
  ** detect this invalid data (with high probability) and ignore it.
  */
  if( pgno==0 || pgno==PAGER_MJ_PGNO(pPager) ){
  if( pgno==0 || pgno==PAGER_SJ_PGNO(pPager) ){
    assert( !isSavepnt );
    return SQLITE_DONE;
  }
  if( pgno>(Pgno)pPager->dbSize || sqlite3BitvecTest(pDone, pgno) ){
    return SQLITE_OK;
  }
  if( isMainJrnl ){
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2348
2349
2350
2351
2352
2353
2354

2355
2356
2357
2358
2359
2360
2361







-







    return rc;
  }

  /* When playing back page 1, restore the nReserve setting
  */
  if( pgno==1 && pPager->nReserve!=((u8*)aData)[20] ){
    pPager->nReserve = ((u8*)aData)[20];
    pagerReportSize(pPager);
  }

  /* If the pager is in CACHEMOD state, then there must be a copy of this
  ** page in the pager cache. In this case just update the pager cache,
  ** not the database file. The page is left marked dirty in this case.
  **
  ** An exception to the above rule: If the database is in no-sync mode
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2415
2416
2417
2418
2419
2420
2421







2422
2423
2424
2425
2426
2427







2428
2429
2430
2431
2432
2433
2434







-
-
-
-
-
-
-






-
-
-
-
-
-
-








    /* Write the data read from the journal back into the database file.
    ** This is usually safe even for an encrypted database - as the data
    ** was encrypted before it was written to the journal file. The exception
    ** is if the data was just read from an in-memory sub-journal. In that
    ** case it must be encrypted here before it is copied into the database
    ** file.  */
#ifdef SQLITE_HAS_CODEC
    if( !jrnlEnc ){
      CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM_BKPT, aData);
      rc = sqlite3OsWrite(pPager->fd, (u8 *)aData, pPager->pageSize, ofst);
      CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM_BKPT);
    }else
#endif
    rc = sqlite3OsWrite(pPager->fd, (u8 *)aData, pPager->pageSize, ofst);

    if( pgno>pPager->dbFileSize ){
      pPager->dbFileSize = pgno;
    }
    if( pPager->pBackup ){
#ifdef SQLITE_HAS_CODEC
      if( jrnlEnc ){
        CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM_BKPT);
        sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData);
        CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM_BKPT,aData);
      }else
#endif
      sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData);
    }
  }else if( !isMainJrnl && pPg==0 ){
    /* If this is a rollback of a savepoint and data was not written to
    ** the database and the page is not in-memory, there is a potential
    ** problem. When the page is next fetched by the b-tree layer, it 
    ** will be read from the database file, which may or may not be 
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573



2574
2575
2576

2577
2578
2579

2580
2581
2582

2583
2584
2585
2586
2587

2588
2589
2590

2591
2592
2593
2594
2595
2596


2597
2598
2599
2600

2601
2602
2603
2604
2605
2606
2607
2608
2609

2610
2611
2612
2613

2614
2615
2616

2617
2618
2619


2620
2621
2622



2623
2624
2625


2626
2627

2628
2629

2630

2631
2632
2633



2634
2635

2636
2637
2638
2639
2640




2641
2642
2643
2644
2645
2646





2647
2648

2649

2650
2651
2652
2653






2654
2655
2656


2657
2658
2659
2660

2661
2662
2663
2664
2665






2666
2667
2668

2669
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
2704
2471
2472
2473
2474
2475
2476
2477





2478
2479
2480
2481
2482
2483



2484
2485
2486
2487
2488

2489
2490
2491

2492
2493
2494

2495
2496
2497
2498
2499

2500
2501
2502

2503
2504
2505
2506
2507


2508
2509
2510
2511
2512

2513
2514
2515
2516
2517
2518
2519
2520
2521

2522
2523
2524
2525

2526
2527
2528

2529
2530


2531
2532
2533


2534
2535
2536
2537


2538
2539
2540

2541


2542
2543
2544
2545


2546
2547
2548
2549

2550
2551




2552
2553
2554
2555
2556





2557
2558
2559
2560
2561
2562

2563
2564
2565




2566
2567
2568
2569
2570
2571
2572


2573
2574
2575
2576
2577

2578
2579
2580



2581
2582
2583
2584
2585
2586
2587
2588

2589
2590
2591

2592
2593
2594

2595
2596
2597

2598
2599
2600

2601
2602


2603
2604
2605
2606
2607
2608
2609


2610
2611
2612




2613
2614
2615
2616
2617

2618
2619
2620
2621
2622
2623
2624
2625







-
-
-
-
-






-
-
-
+
+
+


-
+


-
+


-
+




-
+


-
+




-
-
+
+



-
+








-
+



-
+


-
+

-
-
+
+

-
-
+
+
+

-
-
+
+

-
+
-
-
+

+

-
-
+
+
+

-
+

-
-
-
-
+
+
+
+

-
-
-
-
-
+
+
+
+
+

-
+

+
-
-
-
-
+
+
+
+
+
+

-
-
+
+



-
+


-
-
-
+
+
+
+
+
+


-
+


-
+


-
+


-
+


-
+

-
-
+
+





-
-
+
+

-
-
-
-
+
+
+
+

-
+







    pager_set_pagehash(pPg);

    /* If this was page 1, then restore the value of Pager.dbFileVers.
    ** Do this before any decoding. */
    if( pgno==1 ){
      memcpy(&pPager->dbFileVers, &((u8*)pData)[24],sizeof(pPager->dbFileVers));
    }

    /* Decode the page just read from disk */
#if SQLITE_HAS_CODEC
    if( jrnlEnc ){ CODEC1(pPager, pData, pPg->pgno, 3, rc=SQLITE_NOMEM_BKPT); }
#endif
    sqlite3PcacheRelease(pPg);
  }
  return rc;
}

/*
** Parameter zMaster is the name of a master journal file. A single journal
** file that referred to the master journal file has just been rolled back.
** This routine checks if it is possible to delete the master journal file,
** Parameter zSuper is the name of a super-journal file. A single journal
** file that referred to the super-journal file has just been rolled back.
** This routine checks if it is possible to delete the super-journal file,
** and does so if it is.
**
** Argument zMaster may point to Pager.pTmpSpace. So that buffer is not 
** Argument zSuper may point to Pager.pTmpSpace. So that buffer is not 
** available for use within this function.
**
** When a master journal file is created, it is populated with the names 
** When a super-journal file is created, it is populated with the names 
** of all of its child journals, one after another, formatted as utf-8 
** encoded text. The end of each child journal file is marked with a 
** nul-terminator byte (0x00). i.e. the entire contents of a master journal
** nul-terminator byte (0x00). i.e. the entire contents of a super-journal
** file for a transaction involving two databases might be:
**
**   "/home/bill/a.db-journal\x00/home/bill/b.db-journal\x00"
**
** A master journal file may only be deleted once all of its child 
** A super-journal file may only be deleted once all of its child 
** journals have been rolled back.
**
** This function reads the contents of the master-journal file into 
** This function reads the contents of the super-journal file into 
** memory and loops through each of the child journal names. For
** each child journal, it checks if:
**
**   * if the child journal exists, and if so
**   * if the child journal contains a reference to master journal 
**     file zMaster
**   * if the child journal contains a reference to super-journal 
**     file zSuper
**
** If a child journal can be found that matches both of the criteria
** above, this function returns without doing anything. Otherwise, if
** no such child journal can be found, file zMaster is deleted from
** no such child journal can be found, file zSuper is deleted from
** the file-system using sqlite3OsDelete().
**
** If an IO error within this function, an error code is returned. This
** function allocates memory by calling sqlite3Malloc(). If an allocation
** fails, SQLITE_NOMEM is returned. Otherwise, if no IO or malloc errors 
** occur, SQLITE_OK is returned.
**
** TODO: This function allocates a single block of memory to load
** the entire contents of the master journal file. This could be
** the entire contents of the super-journal file. This could be
** a couple of kilobytes or so - potentially larger than the page 
** size.
*/
static int pager_delmaster(Pager *pPager, const char *zMaster){
static int pager_delsuper(Pager *pPager, const char *zSuper){
  sqlite3_vfs *pVfs = pPager->pVfs;
  int rc;                   /* Return code */
  sqlite3_file *pMaster;    /* Malloc'd master-journal file descriptor */
  sqlite3_file *pSuper;     /* Malloc'd super-journal file descriptor */
  sqlite3_file *pJournal;   /* Malloc'd child-journal file descriptor */
  char *zMasterJournal = 0; /* Contents of master journal file */
  i64 nMasterJournal;       /* Size of master journal file */
  char *zSuperJournal = 0;  /* Contents of super-journal file */
  i64 nSuperJournal;        /* Size of super-journal file */
  char *zJournal;           /* Pointer to one journal within MJ file */
  char *zMasterPtr;         /* Space to hold MJ filename from a journal file */
  int nMasterPtr;           /* Amount of space allocated to zMasterPtr[] */
  char *zSuperPtr;          /* Space to hold super-journal filename */
  char *zFree = 0;          /* Free this buffer */
  int nSuperPtr;            /* Amount of space allocated to zSuperPtr[] */

  /* Allocate space for both the pJournal and pMaster file descriptors.
  ** If successful, open the master journal file for reading.
  /* Allocate space for both the pJournal and pSuper file descriptors.
  ** If successful, open the super-journal file for reading.
  */
  pMaster = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile * 2);
  pSuper = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile * 2);
  pJournal = (sqlite3_file *)(((u8 *)pMaster) + pVfs->szOsFile);
  if( !pMaster ){
  if( !pSuper ){
    rc = SQLITE_NOMEM_BKPT;
    pJournal = 0;
  }else{
    const int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MASTER_JOURNAL);
    rc = sqlite3OsOpen(pVfs, zMaster, pMaster, flags, 0);
    const int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_SUPER_JOURNAL);
    rc = sqlite3OsOpen(pVfs, zSuper, pSuper, flags, 0);
    pJournal = (sqlite3_file *)(((u8 *)pSuper) + pVfs->szOsFile);
  }
  if( rc!=SQLITE_OK ) goto delmaster_out;
  if( rc!=SQLITE_OK ) goto delsuper_out;

  /* Load the entire master journal file into space obtained from
  ** sqlite3_malloc() and pointed to by zMasterJournal.   Also obtain
  ** sufficient space (in zMasterPtr) to hold the names of master
  ** journal files extracted from regular rollback-journals.
  /* Load the entire super-journal file into space obtained from
  ** sqlite3_malloc() and pointed to by zSuperJournal.   Also obtain
  ** sufficient space (in zSuperPtr) to hold the names of super-journal
  ** files extracted from regular rollback-journals.
  */
  rc = sqlite3OsFileSize(pMaster, &nMasterJournal);
  if( rc!=SQLITE_OK ) goto delmaster_out;
  nMasterPtr = pVfs->mxPathname+1;
  zMasterJournal = sqlite3Malloc(nMasterJournal + nMasterPtr + 1);
  if( !zMasterJournal ){
  rc = sqlite3OsFileSize(pSuper, &nSuperJournal);
  if( rc!=SQLITE_OK ) goto delsuper_out;
  nSuperPtr = pVfs->mxPathname+1;
  zFree = sqlite3Malloc(4 + nSuperJournal + nSuperPtr + 2);
  if( !zFree ){
    rc = SQLITE_NOMEM_BKPT;
    goto delmaster_out;
    goto delsuper_out;
  }
  zFree[0] = zFree[1] = zFree[2] = zFree[3] = 0;
  zMasterPtr = &zMasterJournal[nMasterJournal+1];
  rc = sqlite3OsRead(pMaster, zMasterJournal, (int)nMasterJournal, 0);
  if( rc!=SQLITE_OK ) goto delmaster_out;
  zMasterJournal[nMasterJournal] = 0;
  zSuperJournal = &zFree[4];
  zSuperPtr = &zSuperJournal[nSuperJournal+2];
  rc = sqlite3OsRead(pSuper, zSuperJournal, (int)nSuperJournal, 0);
  if( rc!=SQLITE_OK ) goto delsuper_out;
  zSuperJournal[nSuperJournal] = 0;
  zSuperJournal[nSuperJournal+1] = 0;

  zJournal = zMasterJournal;
  while( (zJournal-zMasterJournal)<nMasterJournal ){
  zJournal = zSuperJournal;
  while( (zJournal-zSuperJournal)<nSuperJournal ){
    int exists;
    rc = sqlite3OsAccess(pVfs, zJournal, SQLITE_ACCESS_EXISTS, &exists);
    if( rc!=SQLITE_OK ){
      goto delmaster_out;
      goto delsuper_out;
    }
    if( exists ){
      /* One of the journals pointed to by the master journal exists.
      ** Open it and check if it points at the master journal. If
      ** so, return without deleting the master journal file.
      /* One of the journals pointed to by the super-journal exists.
      ** Open it and check if it points at the super-journal. If
      ** so, return without deleting the super-journal file.
      ** NB:  zJournal is really a MAIN_JOURNAL.  But call it a 
      ** SUPER_JOURNAL here so that the VFS will not send the zJournal
      ** name into sqlite3_database_file_object().
      */
      int c;
      int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL);
      int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_SUPER_JOURNAL);
      rc = sqlite3OsOpen(pVfs, zJournal, pJournal, flags, 0);
      if( rc!=SQLITE_OK ){
        goto delmaster_out;
        goto delsuper_out;
      }

      rc = readMasterJournal(pJournal, zMasterPtr, nMasterPtr);
      rc = readSuperJournal(pJournal, zSuperPtr, nSuperPtr);
      sqlite3OsClose(pJournal);
      if( rc!=SQLITE_OK ){
        goto delmaster_out;
        goto delsuper_out;
      }

      c = zMasterPtr[0]!=0 && strcmp(zMasterPtr, zMaster)==0;
      c = zSuperPtr[0]!=0 && strcmp(zSuperPtr, zSuper)==0;
      if( c ){
        /* We have a match. Do not delete the master journal file. */
        goto delmaster_out;
        /* We have a match. Do not delete the super-journal file. */
        goto delsuper_out;
      }
    }
    zJournal += (sqlite3Strlen30(zJournal)+1);
  }
 
  sqlite3OsClose(pMaster);
  rc = sqlite3OsDelete(pVfs, zMaster, 0);
  sqlite3OsClose(pSuper);
  rc = sqlite3OsDelete(pVfs, zSuper, 0);

delmaster_out:
  sqlite3_free(zMasterJournal);
  if( pMaster ){
    sqlite3OsClose(pMaster);
delsuper_out:
  sqlite3_free(zFree);
  if( pSuper ){
    sqlite3OsClose(pSuper);
    assert( !isOpen(pJournal) );
    sqlite3_free(pMaster);
    sqlite3_free(pSuper);
  }
  return rc;
}


/*
** This function is used to change the actual size of the database 
2738
2739
2740
2741
2742
2743
2744

2745
2746
2747
2748
2749
2750
2751
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673







+







      if( currentSize>newSize ){
        rc = sqlite3OsTruncate(pPager->fd, newSize);
      }else if( (currentSize+szPage)<=newSize ){
        char *pTmp = pPager->pTmpSpace;
        memset(pTmp, 0, szPage);
        testcase( (newSize-szPage) == currentSize );
        testcase( (newSize-szPage) >  currentSize );
        sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_SIZE_HINT, &newSize);
        rc = sqlite3OsWrite(pPager->fd, pTmp, szPage, newSize-szPage);
      }
      if( rc==SQLITE_OK ){
        pPager->dbFileSize = nPage;
      }
    }
  }
2768
2769
2770
2771
2772
2773
2774
2775

2776
2777
2778
2779
2780
2781
2782
2690
2691
2692
2693
2694
2695
2696

2697
2698
2699
2700
2701
2702
2703
2704







-
+







}

/*
** Set the value of the Pager.sectorSize variable for the given
** pager based on the value returned by the xSectorSize method
** of the open database file. The sector size will be used 
** to determine the size and alignment of journal header and 
** master journal pointers within created journal files.
** super-journal pointers within created journal files.
**
** For temporary files the effective sector size is always 512 bytes.
**
** Otherwise, for non-temporary files, the effective sector size is
** the value returned by the xSectorSize() method rounded up to 32 if
** it is less than 32, or rounded down to MAX_SECTOR_SIZE if it
** is greater than MAX_SECTOR_SIZE.
2867
2868
2869
2870
2871
2872
2873
2874

2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889


2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902




2903
2904

2905
2906
2907
2908
2909
2910
2911
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
2818
2819
2820




2821
2822
2823
2824
2825

2826
2827
2828
2829
2830
2831
2832
2833







-
+













-
-
+
+









-
-
-
-
+
+
+
+

-
+







  sqlite3_vfs *pVfs = pPager->pVfs;
  i64 szJ;                 /* Size of the journal file in bytes */
  u32 nRec;                /* Number of Records in the journal */
  u32 u;                   /* Unsigned loop counter */
  Pgno mxPg = 0;           /* Size of the original file in pages */
  int rc;                  /* Result code of a subroutine */
  int res = 1;             /* Value returned by sqlite3OsAccess() */
  char *zMaster = 0;       /* Name of master journal file if any */
  char *zSuper = 0;        /* Name of super-journal file if any */
  int needPagerReset;      /* True to reset page prior to first page rollback */
  int nPlayback = 0;       /* Total number of pages restored from journal */
  u32 savedPageSize = pPager->pageSize;

  /* Figure out how many records are in the journal.  Abort early if
  ** the journal is empty.
  */
  assert( isOpen(pPager->jfd) );
  rc = sqlite3OsFileSize(pPager->jfd, &szJ);
  if( rc!=SQLITE_OK ){
    goto end_playback;
  }

  /* Read the master journal name from the journal, if it is present.
  ** If a master journal file name is specified, but the file is not
  /* Read the super-journal name from the journal, if it is present.
  ** If a super-journal file name is specified, but the file is not
  ** present on disk, then the journal is not hot and does not need to be
  ** played back.
  **
  ** TODO: Technically the following is an error because it assumes that
  ** buffer Pager.pTmpSpace is (mxPathname+1) bytes or larger. i.e. that
  ** (pPager->pageSize >= pPager->pVfs->mxPathname+1). Using os_unix.c,
  ** mxPathname is 512, which is the same as the minimum allowable value
  ** for pageSize.
  */
  zMaster = pPager->pTmpSpace;
  rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
  if( rc==SQLITE_OK && zMaster[0] ){
    rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res);
  zSuper = pPager->pTmpSpace;
  rc = readSuperJournal(pPager->jfd, zSuper, pPager->pVfs->mxPathname+1);
  if( rc==SQLITE_OK && zSuper[0] ){
    rc = sqlite3OsAccess(pVfs, zSuper, SQLITE_ACCESS_EXISTS, &res);
  }
  zMaster = 0;
  zSuper = 0;
  if( rc!=SQLITE_OK || !res ){
    goto end_playback;
  }
  pPager->journalOff = 0;
  needPagerReset = isHot;

  /* This loop terminates either when a readJournalHdr() or 
2960
2961
2962
2963
2964
2965
2966



2967
2968
2969
2970
2971
2972
2973
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898







+
+
+







    */
    if( pPager->journalOff==JOURNAL_HDR_SZ(pPager) ){
      rc = pager_truncate(pPager, mxPg);
      if( rc!=SQLITE_OK ){
        goto end_playback;
      }
      pPager->dbSize = mxPg;
      if( pPager->mxPgno<mxPg ){
        pPager->mxPgno = mxPg;
      }
    }

    /* Copy original pages out of the journal and back into the 
    ** database file and/or page cache.
    */
    for(u=0; u<nRec; u++){
      if( needPagerReset ){
3024
3025
3026
3027
3028
3029
3030




3031
3032


3033
3034
3035
3036
3037
3038
3039
3040
3041

3042
3043
3044
3045
3046



3047


3048

3049
3050
3051
3052
3053
3054
3055
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959


2960
2961
2962
2963
2964
2965
2966
2967
2968
2969

2970
2971
2972



2973
2974
2975
2976
2977
2978

2979
2980
2981
2982
2983
2984
2985
2986







+
+
+
+
-
-
+
+








-
+


-
-
-
+
+
+

+
+
-
+







  ** update the change-counter at all. This may lead to cache inconsistency
  ** problems for other processes at some point in the future. So, just
  ** in case this has happened, clear the changeCountDone flag now.
  */
  pPager->changeCountDone = pPager->tempFile;

  if( rc==SQLITE_OK ){
    /* Leave 4 bytes of space before the super-journal filename in memory.
    ** This is because it may end up being passed to sqlite3OsOpen(), in
    ** which case it requires 4 0x00 bytes in memory immediately before
    ** the filename. */
    zMaster = pPager->pTmpSpace;
    rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
    zSuper = &pPager->pTmpSpace[4];
    rc = readSuperJournal(pPager->jfd, zSuper, pPager->pVfs->mxPathname+1);
    testcase( rc!=SQLITE_OK );
  }
  if( rc==SQLITE_OK
   && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
  ){
    rc = sqlite3PagerSync(pPager, 0);
  }
  if( rc==SQLITE_OK ){
    rc = pager_end_transaction(pPager, zMaster[0]!='\0', 0);
    rc = pager_end_transaction(pPager, zSuper[0]!='\0', 0);
    testcase( rc!=SQLITE_OK );
  }
  if( rc==SQLITE_OK && zMaster[0] && res ){
    /* If there was a master journal and this routine will return success,
    ** see if it is possible to delete the master journal.
  if( rc==SQLITE_OK && zSuper[0] && res ){
    /* If there was a super-journal and this routine will return success,
    ** see if it is possible to delete the super-journal.
    */
    assert( zSuper==&pPager->pTmpSpace[4] );
    memset(pPager->pTmpSpace, 0, 4);
    rc = pager_delmaster(pPager, zMaster);
    rc = pager_delsuper(pPager, zSuper);
    testcase( rc!=SQLITE_OK );
  }
  if( isHot && nPlayback ){
    sqlite3_log(SQLITE_NOTICE_RECOVER_ROLLBACK, "recovered %d pages from %s",
                nPlayback, pPager->zJournal);
  }

3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143

3144
3145
3146
3147
3148
3149
3150
3047
3048
3049
3050
3051
3052
3053


3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080







-
-



















+







      */
      memset(pPager->dbFileVers, 0xff, sizeof(pPager->dbFileVers));
    }else{
      u8 *dbFileVers = &((u8*)pPg->pData)[24];
      memcpy(&pPager->dbFileVers, dbFileVers, sizeof(pPager->dbFileVers));
    }
  }
  CODEC1(pPager, pPg->pData, pPg->pgno, 3, rc = SQLITE_NOMEM_BKPT);

  PAGER_INCR(sqlite3_pager_readdb_count);
  PAGER_INCR(pPager->nRead);
  IOTRACE(("PGIN %p %d\n", pPager, pPg->pgno));
  PAGERTRACE(("FETCH %d page %d hash(%08x)\n",
               PAGERID(pPager), pPg->pgno, pager_pagehash(pPg)));

  return rc;
}

/*
** Update the value of the change-counter at offsets 24 and 92 in
** the header and the sqlite version number at offset 96.
**
** This is an unconditional update.  See also the pager_incr_changecounter()
** routine which only updates the change-counter if the update is actually
** needed, as determined by the pPager->changeCountDone state variable.
*/
static void pager_write_changecounter(PgHdr *pPg){
  u32 change_counter;
  if( NEVER(pPg==0) ) return;

  /* Increment the value just read and write it back to byte 24. */
  change_counter = sqlite3Get4byte((u8*)pPg->pPager->dbFileVers)+1;
  put32bits(((char*)pPg->pData)+24, change_counter);

  /* Also store the SQLite version number in bytes 96..99 and in
  ** bytes 92..95 store the change counter for which the version number
3209
3210
3211
3212
3213
3214
3215
3216







3217
3218
3219
3220
3221
3222
3223
3139
3140
3141
3142
3143
3144
3145

3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159







-
+
+
+
+
+
+
+







  ** been written (but not committed) to the log file, do one of the 
  ** following:
  **
  **   + Discard the cached page (if refcount==0), or
  **   + Reload page content from the database (if refcount>0).
  */
  pPager->dbSize = pPager->dbOrigSize;
  rc = sqlite3WalUndo(pPager->pWal, pagerUndoCallback, (void *)pPager);
  rc = sqlite3WalUndo(pPager->pWal, pagerUndoCallback, (void *)pPager, 
#ifdef SQLITE_OMIT_CONCURRENT
      0
#else
      pPager->pAllRead!=0
#endif
  );
  pList = sqlite3PcacheDirtyList(pPager->pPCache);

#ifndef SQLITE_OMIT_CONCURRENT
  /* If this is an CONCURRENT transaction, then page 1 must be reread from 
  ** the db file, even if it is not dirty. This is because the b-tree layer 
  ** may have already zeroed the nFree and iTrunk header fields.  */
  if( rc==SQLITE_OK && (pList==0 || pList->pgno!=1) && pPager->pAllRead ){
3326
3327
3328
3329
3330
3331
3332




3333
3334
3335
3336
3337
3338
3339
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279







+
+
+
+







  */
  sqlite3WalEndReadTransaction(pPager->pWal);

  rc = sqlite3WalBeginReadTransaction(pPager->pWal, &changed);
  if( rc!=SQLITE_OK || changed ){
    pager_reset(pPager);
    if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0);
    assert( pPager->journalMode==PAGER_JOURNALMODE_WAL
         || pPager->journalMode==PAGER_JOURNALMODE_WAL2
    );
    pPager->journalMode = sqlite3WalJournalMode(pPager->pWal);
  }

  return rc;
}
#endif

/*
3421
3422
3423
3424
3425
3426
3427
3428

3429
3430

3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441

3442
3443
3444
3445
3446
3447
3448
3361
3362
3363
3364
3365
3366
3367

3368
3369

3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380

3381
3382
3383
3384
3385
3386
3387
3388







-
+

-
+










-
+








        rc = pagerPagecount(pPager, &nPage);
        if( rc ) return rc;
        if( nPage==0 ){
          rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0);
        }else{
          testcase( sqlite3PcachePagecount(pPager->pPCache)==0 );
          rc = sqlite3PagerOpenWal(pPager, 0);
          rc = sqlite3PagerOpenWal(pPager, 0, 0);
        }
      }else if( pPager->journalMode==PAGER_JOURNALMODE_WAL ){
      }else if( pPager->journalMode>=PAGER_JOURNALMODE_WAL ){
        pPager->journalMode = PAGER_JOURNALMODE_DELETE;
      }
    }
  }
  return rc;
}
#endif

/*
** Playback savepoint pSavepoint. Or, if pSavepoint==NULL, then playback
** the entire master journal file. The case pSavepoint==NULL occurs when 
** the entire super-journal file. The case pSavepoint==NULL occurs when 
** a ROLLBACK TO command is invoked on a SAVEPOINT that is a transaction 
** savepoint.
**
** When pSavepoint is not NULL (meaning a non-transaction savepoint is 
** being rolled back), then the rollback consists of up to three stages,
** performed in the order specified:
**
3844
3845
3846
3847
3848
3849
3850


3851
3852






3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863

3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3784
3785
3786
3787
3788
3789
3790
3791
3792


3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820

3821
3822
3823
3824
3825
3826
3827







+
+
-
-
+
+
+
+
+
+











+










-







    char *pNew = NULL;             /* New temp space */
    i64 nByte = 0;

    if( pPager->eState>PAGER_OPEN && isOpen(pPager->fd) ){
      rc = sqlite3OsFileSize(pPager->fd, &nByte);
    }
    if( rc==SQLITE_OK ){
      /* 8 bytes of zeroed overrun space is sufficient so that the b-tree
      * cell header parser will never run off the end of the allocation */
      pNew = (char *)sqlite3PageMalloc(pageSize);
      if( !pNew ) rc = SQLITE_NOMEM_BKPT;
      pNew = (char *)sqlite3PageMalloc(pageSize+8);
      if( !pNew ){
        rc = SQLITE_NOMEM_BKPT;
      }else{
        memset(pNew+pageSize, 0, 8);
      }
    }

    if( rc==SQLITE_OK ){
      pager_reset(pPager);
      rc = sqlite3PcacheSetPageSize(pPager->pPCache, pageSize);
    }
    if( rc==SQLITE_OK ){
      sqlite3PageFree(pPager->pTmpSpace);
      pPager->pTmpSpace = pNew;
      pPager->dbSize = (Pgno)((nByte+pageSize-1)/pageSize);
      pPager->pageSize = pageSize;
      pPager->lckPgno = (Pgno)(PENDING_BYTE/pageSize) + 1;
    }else{
      sqlite3PageFree(pNew);
    }
  }

  *pPageSize = pPager->pageSize;
  if( rc==SQLITE_OK ){
    if( nReserve<0 ) nReserve = pPager->nReserve;
    assert( nReserve>=0 && nReserve<1000 );
    pPager->nReserve = (i16)nReserve;
    pagerReportSize(pPager);
    pagerFixMaplimit(pPager);
  }
  return rc;
}

/*
** Return a pointer to the "temporary page" buffer held internally
3892
3893
3894
3895
3896
3897
3898
3899

3900
3901
3902
3903
3904




3905
3906
3907
3908
3909
3910
3911
3838
3839
3840
3841
3842
3843
3844

3845
3846
3847
3848
3849

3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860







-
+




-
+
+
+
+







/*
** Attempt to set the maximum database page count if mxPage is positive. 
** Make no changes if mxPage is zero or negative.  And never reduce the
** maximum page count below the current size of the database.
**
** Regardless of mxPage, return the current maximum page count.
*/
int sqlite3PagerMaxPageCount(Pager *pPager, int mxPage){
Pgno sqlite3PagerMaxPageCount(Pager *pPager, Pgno mxPage){
  if( mxPage>0 ){
    pPager->mxPgno = mxPage;
  }
  assert( pPager->eState!=PAGER_OPEN );      /* Called only by OP_MaxPgcnt */
  assert( pPager->mxPgno>=pPager->dbSize );  /* OP_MaxPgcnt enforces this */
  /* assert( pPager->mxPgno>=pPager->dbSize ); */
  /* OP_MaxPgcnt ensures that the parameter passed to this function is not
  ** less than the total number of valid pages in the database. But this
  ** may be less than Pager.dbSize, and so the assert() above is not valid */
  return pPager->mxPgno;
}

/*
** The following set of routines are used to disable the simulated
** I/O error mechanism.  These routines are used to avoid simulated
** errors in places where we do not care about errors.
4015
4016
4017
4018
4019
4020
4021
4022

4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037

4038



4039





4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060

4061
4062
4063
4064
4065
4066
4067
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
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015

4016
4017
4018
4019
4020
4021
4022
4023







-
+
-














+

+
+
+
-
+
+
+
+
+




















-
+







** Function assertTruncateConstraint(pPager) checks that one of the 
** following is true for all dirty pages currently in the page-cache:
**
**   a) The page number is less than or equal to the size of the 
**      current database image, in pages, OR
**
**   b) if the page content were written at this time, it would not
**      be necessary to write the current content out to the sub-journal
**      be necessary to write the current content out to the sub-journal.
**      (as determined by function subjRequiresPage()).
**
** If the condition asserted by this function were not true, and the
** dirty page were to be discarded from the cache via the pagerStress()
** routine, pagerStress() would not write the current page content to
** the database file. If a savepoint transaction were rolled back after
** this happened, the correct behavior would be to restore the current
** content of the page. However, since this content is not present in either
** the database file or the portion of the rollback journal and 
** sub-journal rolled back the content could not be restored and the
** database image would become corrupt. It is therefore fortunate that 
** this circumstance cannot arise.
*/
#if defined(SQLITE_DEBUG)
static void assertTruncateConstraintCb(PgHdr *pPg){
  Pager *pPager = pPg->pPager;
  assert( pPg->flags&PGHDR_DIRTY );
  if( pPg->pgno>pPager->dbSize ){      /* if (a) is false */
    Pgno pgno = pPg->pgno;
    int i;
  assert( !subjRequiresPage(pPg) || pPg->pgno<=pPg->pPager->dbSize );
    for(i=0; i<pPg->pPager->nSavepoint; i++){
      PagerSavepoint *p = &pPager->aSavepoint[i];
      assert( p->nOrig<pgno || sqlite3BitvecTestNotNull(p->pInSavepoint,pgno) );
    }
  }
}
static void assertTruncateConstraint(Pager *pPager){
  sqlite3PcacheIterateDirty(pPager->pPCache, assertTruncateConstraintCb);
}
#else
# define assertTruncateConstraint(pPager)
#endif

/*
** Truncate the in-memory database file image to nPage pages. This 
** function does not actually modify the database file on disk. It 
** just sets the internal state of the pager object so that the 
** truncation will be done when the current transaction is committed.
**
** 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 );
  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
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4216
4217
4218
4219
4220
4221
4222





4223
4224
4225
4226
4227
4228
4229







-
-
-
-
-







  enable_simulated_io_errors();
  PAGERTRACE(("CLOSE %d\n", PAGERID(pPager)));
  IOTRACE(("CLOSE %p\n", pPager))
  sqlite3OsClose(pPager->jfd);
  sqlite3OsClose(pPager->fd);
  sqlite3PageFree(pTmp);
  sqlite3PcacheClose(pPager->pPCache);

#ifdef SQLITE_HAS_CODEC
  if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec);
#endif

  assert( !pPager->aSavepoint && !pPager->pInJournal );
  assert( !isOpen(pPager->jfd) && !isOpen(pPager->sjfd) );

  sqlite3_free(pPager);
  return SQLITE_OK;
}

4515
4516
4517
4518
4519
4520
4521
4522
4523

4524
4525
4526
4527
4528
4529
4530
4466
4467
4468
4469
4470
4471
4472


4473
4474
4475
4476
4477
4478
4479
4480







-
-
+







    if( pgno<=pPager->dbSize && 0==(pList->flags&PGHDR_DONT_WRITE) ){
      i64 offset = (pgno-1)*(i64)pPager->pageSize;   /* Offset to write */
      char *pData;                                   /* Data to write */    

      assert( (pList->flags&PGHDR_NEED_SYNC)==0 );
      if( pList->pgno==1 ) pager_write_changecounter(pList);

      /* Encode the database */
      CODEC2(pPager, pList->pData, pgno, 6, return SQLITE_NOMEM_BKPT, pData);
      pData = pList->pData;

      /* Write out the page data. */
      rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize, offset);

      /* If page 1 was just written, update Pager.dbFileVers to match
      ** the value now stored in the database file. If writing this 
      ** page caused the database file to grow, update dbFileSize. 
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4555
4556
4557
4558
4559
4560
4561






4562
4563
4564
4565
4566
4567
4568







-
-
-
-
-
-








    /* If the sub-journal was opened successfully (or was already open),
    ** write the journal record into the file.  */
    if( rc==SQLITE_OK ){
      void *pData = pPg->pData;
      i64 offset = (i64)pPager->nSubRec*(4+pPager->pageSize);
      char *pData2;

#if SQLITE_HAS_CODEC   
      if( !pPager->subjInMemory ){
        CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM_BKPT, pData2);
      }else
#endif
      pData2 = pData;
      PAGERTRACE(("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno));
      rc = write32bits(pPager->sjfd, offset, pPg->pgno);
      if( rc==SQLITE_OK ){
        rc = sqlite3OsWrite(pPager->sjfd, pData2, pPager->pageSize, offset+4);
      }
    }
4799
4800
4801
4802
4803
4804
4805
4806

4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818

4819

4820
4821
4822
4823
4824
4825
4826
4743
4744
4745
4746
4747
4748
4749

4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763

4764
4765
4766
4767
4768
4769
4770
4771







-
+












+
-
+







  void (*xReinit)(DbPage*) /* Function to reinitialize pages */
){
  u8 *pPtr;
  Pager *pPager = 0;       /* Pager object to allocate and return */
  int rc = SQLITE_OK;      /* Return code */
  int tempFile = 0;        /* True for temp files (incl. in-memory files) */
  int memDb = 0;           /* True if this is an in-memory file */
#ifdef SQLITE_ENABLE_DESERIALIZE
#ifndef SQLITE_OMIT_DESERIALIZE
  int memJM = 0;           /* Memory journal mode */
#else
# define memJM 0
#endif
  int readOnly = 0;        /* True if this is a read-only file */
  int journalFileSize;     /* Bytes to allocate for each journal fd */
  char *zPathname = 0;     /* Full path to database file */
  int nPathname = 0;       /* Number of bytes in zPathname */
  int useJournal = (flags & PAGER_OMIT_JOURNAL)==0; /* False to omit journal */
  int pcacheSize = sqlite3PcacheSize();       /* Bytes to allocate for PCache */
  u32 szPageDflt = SQLITE_DEFAULT_PAGE_SIZE;  /* Default page size */
  const char *zUri = 0;    /* URI args to copy */
  int nUriByte = 1;        /* Number of bytes of URI args at *zUri */
  int nUri = 0;            /* Number of bytes of URI args at *zUri */
  int nUri = 0;            /* Number of URI parameters */

  /* Figure out how much space is required for each journal file-handle
  ** (there are two of them, the main journal and the sub-journal).  */
  journalFileSize = ROUND8(sqlite3JournalSize(pVfs));

  /* Set the output variable to NULL in case an error occurs. */
  *ppPager = 0;
4846
4847
4848
4849
4850
4851
4852









4853
4854
4855
4856
4857



4858
4859
4860


4861
4862
4863
4864
4865
4866
4867
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809


4810
4811
4812
4813


4814
4815
4816
4817
4818
4819
4820
4821
4822







+
+
+
+
+
+
+
+
+



-
-
+
+
+

-
-
+
+







    nPathname = pVfs->mxPathname+1;
    zPathname = sqlite3DbMallocRaw(0, nPathname*2);
    if( zPathname==0 ){
      return SQLITE_NOMEM_BKPT;
    }
    zPathname[0] = 0; /* Make sure initialized even if FullPathname() fails */
    rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname);
    if( rc!=SQLITE_OK ){
      if( rc==SQLITE_OK_SYMLINK ){
        if( vfsFlags & SQLITE_OPEN_NOFOLLOW ){
          rc = SQLITE_CANTOPEN_SYMLINK;
        }else{
          rc = SQLITE_OK;
        }
      }
    }
    nPathname = sqlite3Strlen30(zPathname);
    z = zUri = &zFilename[sqlite3Strlen30(zFilename)+1];
    while( *z ){
      z += sqlite3Strlen30(z)+1;
      z += sqlite3Strlen30(z)+1;
      z += strlen(z)+1;
      z += strlen(z)+1;
      nUri++;
    }
    nUri = (int)(&z[1] - zUri);
    assert( nUri>=0 );
    nUriByte = (int)(&z[1] - zUri);
    assert( nUriByte>=1 );
    if( rc==SQLITE_OK && nPathname+8>pVfs->mxPathname ){
      /* This branch is taken when the journal path required by
      ** the database being opened will be more than pVfs->mxPathname
      ** bytes in length. This means the database cannot be opened,
      ** as it will not be possible to open the journal file or even
      ** check for a hot-journal before reading.
      */
4878
4879
4880
4881
4882
4883
4884


4885

4886






























4887
4888
4889
4890
4891
4892
4893
4894









4895
4896


4897

4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908





4909
4910

4911
4912
4913
4914
4915
4916
4917
4918
4919
4920


























4921


4922
4923
4924
4925












4926
4927
4928



4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939


4940
4941
4942
4943
4944
4945
4946
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843

4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875






4876
4877
4878
4879
4880
4881
4882
4883
4884
4885

4886
4887
4888
4889
4890
4891
4892
4893
4894
4895





4896
4897
4898
4899
4900

4901
4902
4903









4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932




4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945


4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957


4958
4959
4960
4961
4962
4963
4964
4965
4966







+
+

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


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

-
+
+

+






-
-
-
-
-
+
+
+
+
+
-

+

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

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

-
-
+
+
+









-
-
+
+







  ** file name. The layout in memory is as follows:
  **
  **     Pager object                    (sizeof(Pager) bytes)
  **     PCache object                   (sqlite3PcacheSize() bytes)
  **     Database file handle            (pVfs->szOsFile bytes)
  **     Sub-journal file handle         (journalFileSize bytes)
  **     Main journal file handle        (journalFileSize bytes)
  **     Ptr back to the Pager           (sizeof(Pager*) bytes)
  **     \0\0\0\0 database prefix        (4 bytes)
  **     Database file name              (nPathname+1 bytes)
  **     URI query parameters            (nUriByte bytes)
  **     Journal file name               (nPathname+8+1 bytes)
  **     Journal filename                (nPathname+8+1 bytes)
  **     WAL filename                    (nPathname+4+1 bytes)
  **     \0\0\0 terminator               (3 bytes)
  **
  ** Some 3rd-party software, over which we have no control, depends on
  ** the specific order of the filenames and the \0 separators between them
  ** so that it can (for example) find the database filename given the WAL
  ** filename without using the sqlite3_filename_database() API.  This is a
  ** misuse of SQLite and a bug in the 3rd-party software, but the 3rd-party
  ** software is in widespread use, so we try to avoid changing the filename
  ** order and formatting if possible.  In particular, the details of the
  ** filename format expected by 3rd-party software should be as follows:
  **
  **   - Main Database Path
  **   - \0
  **   - Multiple URI components consisting of:
  **     - Key
  **     - \0
  **     - Value
  **     - \0
  **   - \0
  **   - Journal Path
  **   - \0
  **   - WAL Path (zWALName)
  **   - \0
  **
  ** The sqlite3_create_filename() interface and the databaseFilename() utility
  ** that is used by sqlite3_filename_database() and kin also depend on the
  ** specific formatting and order of the various filenames, so if the format
  ** changes here, be sure to change it there as well.
  */
  pPtr = (u8 *)sqlite3MallocZero(
    ROUND8(sizeof(*pPager)) +      /* Pager structure */
    ROUND8(pcacheSize) +           /* PCache object */
    ROUND8(pVfs->szOsFile) +       /* The main db file */
    journalFileSize * 2 +          /* The two journal files */ 
    nPathname + 1 + nUri +         /* zFilename */
    nPathname + 8 + 2              /* zJournal */
    ROUND8(sizeof(*pPager)) +            /* Pager structure */
    ROUND8(pcacheSize) +                 /* PCache object */
    ROUND8(pVfs->szOsFile) +             /* The main db file */
    journalFileSize * 2 +                /* The two journal files */
    sizeof(pPager) +                     /* Space to hold a pointer */
    4 +                                  /* Database prefix */
    nPathname + 1 +                      /* database filename */
    nUriByte +                           /* query parameters */
    nPathname + 8 + 1 +                  /* Journal filename */
#ifndef SQLITE_OMIT_WAL
    + nPathname + 4 + 2            /* zWal */
    nPathname + 4 + 1 +                  /* WAL filename */
    nPathname + 5 + 1 +                  /* Second WAL filename */
#endif
    3                                    /* Terminator */
  );
  assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) );
  if( !pPtr ){
    sqlite3DbFree(0, zPathname);
    return SQLITE_NOMEM_BKPT;
  }
  pPager =              (Pager*)(pPtr);
  pPager->pPCache =    (PCache*)(pPtr += ROUND8(sizeof(*pPager)));
  pPager->fd =   (sqlite3_file*)(pPtr += ROUND8(pcacheSize));
  pPager->sjfd = (sqlite3_file*)(pPtr += ROUND8(pVfs->szOsFile));
  pPager->jfd =  (sqlite3_file*)(pPtr += journalFileSize);
  pPager = (Pager*)pPtr;                  pPtr += ROUND8(sizeof(*pPager));
  pPager->pPCache = (PCache*)pPtr;        pPtr += ROUND8(pcacheSize);
  pPager->fd = (sqlite3_file*)pPtr;       pPtr += ROUND8(pVfs->szOsFile);
  pPager->sjfd = (sqlite3_file*)pPtr;     pPtr += journalFileSize;
  pPager->jfd =  (sqlite3_file*)pPtr;     pPtr += journalFileSize;
  pPager->zFilename =    (char*)(pPtr += journalFileSize);
  assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) );
  memcpy(pPtr, &pPager, sizeof(pPager));  pPtr += sizeof(pPager);

  /* Fill in the Pager.zFilename and Pager.zJournal buffers, if required. */
  if( zPathname ){
    assert( nPathname>0 );
    pPager->zJournal =   (char*)(pPtr += nPathname + 1 + nUri);
    memcpy(pPager->zFilename, zPathname, nPathname);
    if( nUri ) memcpy(&pPager->zFilename[nPathname+1], zUri, nUri);
    memcpy(pPager->zJournal, zPathname, nPathname);
    memcpy(&pPager->zJournal[nPathname], "-journal\000", 8+2);
    sqlite3FileSuffix3(pPager->zFilename, pPager->zJournal);
  /* Fill in the Pager.zFilename and pPager.zQueryParam fields */
                                          pPtr += 4;  /* Skip zero prefix */
  pPager->zFilename = (char*)pPtr;
  if( nPathname>0 ){
    memcpy(pPtr, zPathname, nPathname);   pPtr += nPathname + 1;
    if( zUri ){
      memcpy(pPtr, zUri, nUriByte);       pPtr += nUriByte;
    }else{
                                          pPtr++;
    }
  }


  /* Fill in Pager.zJournal */
  if( nPathname>0 ){
    pPager->zJournal = (char*)pPtr;
    memcpy(pPtr, zPathname, nPathname);   pPtr += nPathname;
    memcpy(pPtr, "-journal",8);           pPtr += 8 + 1;
#ifdef SQLITE_ENABLE_8_3_NAMES
    sqlite3FileSuffix3(zFilename,pPager->zJournal);
    pPtr = (u8*)(pPager->zJournal + sqlite3Strlen30(pPager->zJournal)+1);
#endif
  }else{
    pPager->zJournal = 0;
  }

#ifndef SQLITE_OMIT_WAL
  /* Fill in Pager.zWal */
  if( nPathname>0 ){
    pPager->zWal = &pPager->zJournal[nPathname+8+1];
    memcpy(pPager->zWal, zPathname, nPathname);
    memcpy(&pPager->zWal[nPathname], "-wal\000", 4+1);
    sqlite3FileSuffix3(pPager->zFilename, pPager->zWal);
    pPager->zWal = (char*)pPtr;
    memcpy(pPtr, zPathname, nPathname);   pPtr += nPathname;
    memcpy(pPtr, "-wal", 4);              pPtr += 4 + 1;
#ifdef SQLITE_ENABLE_8_3_NAMES
    sqlite3FileSuffix3(zFilename, pPager->zWal);
    pPtr = (u8*)(pPager->zWal + sqlite3Strlen30(pPager->zWal)+1);
#endif
    memcpy(pPtr, zPathname, nPathname);   pPtr += nPathname;
    memcpy(pPtr, "-wal2", 5);             pPtr += 5 + 1;
  }else{
    pPager->zWal = 0;
  }
#endif
    sqlite3DbFree(0, zPathname);
  }
  (void)pPtr;  /* Suppress warning about unused pPtr value */

  if( nPathname ) sqlite3DbFree(0, zPathname);
  pPager->pVfs = pVfs;
  pPager->vfsFlags = vfsFlags;

  /* Open the pager file.
  */
  if( zFilename && zFilename[0] ){
    int fout = 0;                    /* VFS flags returned by xOpen() */
    rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout);
    assert( !memDb );
#ifdef SQLITE_ENABLE_DESERIALIZE
    memJM = (fout&SQLITE_OPEN_MEMORY)!=0;
#ifndef SQLITE_OMIT_DESERIALIZE
    pPager->memVfs = memJM = (fout&SQLITE_OPEN_MEMORY)!=0;
#endif
    readOnly = (fout&SQLITE_OPEN_READONLY)!=0;

    /* If the file was successfully opened for read/write access,
    ** choose a default page size in case we have to create the
    ** database file. The default page size is the maximum of:
    **
4970
4971
4972
4973
4974
4975
4976
4977

4978
4979

4980
4981
4982
4983
4984
4985
4986
4990
4991
4992
4993
4994
4995
4996

4997
4998

4999
5000
5001
5002
5003
5004
5005
5006







-
+

-
+







            if( iDc&(SQLITE_IOCAP_ATOMIC|(ii>>8)) ){
              szPageDflt = ii;
            }
          }
        }
#endif
      }
      pPager->noLock = sqlite3_uri_boolean(zFilename, "nolock", 0);
      pPager->noLock = sqlite3_uri_boolean(pPager->zFilename, "nolock", 0);
      if( (iDc & SQLITE_IOCAP_IMMUTABLE)!=0
       || sqlite3_uri_boolean(zFilename, "immutable", 0) ){
       || sqlite3_uri_boolean(pPager->zFilename, "immutable", 0) ){
          vfsFlags |= SQLITE_OPEN_READONLY;
          goto act_like_temp_file;
      }
    }
  }else{
    /* If a temporary file is requested, it is not opened immediately.
    ** In this case we accept the default page size and delay actually
5079
5080
5081
5082
5083
5084
5085













5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107


5108
5109
5110
5111
5112
5113
5114
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138


5139
5140
5141
5142
5143
5144
5145
5146
5147







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




















-
-
+
+







  /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
  /* pPager->szMmap = SQLITE_DEFAULT_MMAP_SIZE // will be set by btree.c */

  *ppPager = pPager;
  return SQLITE_OK;
}

/*
** Return the sqlite3_file for the main database given the name
** of the corresonding WAL or Journal name as passed into
** xOpen.
*/
sqlite3_file *sqlite3_database_file_object(const char *zName){
  Pager *pPager;
  while( zName[-1]!=0 || zName[-2]!=0 || zName[-3]!=0 || zName[-4]!=0 ){
    zName--;
  }
  pPager = *(Pager**)(zName - 4 - sizeof(Pager*));
  return pPager->fd;
}


/*
** This function is called after transitioning from PAGER_UNLOCK to
** PAGER_SHARED state. It tests if there is a hot journal present in
** the file-system for the given pager. A hot journal is one that 
** needs to be played back. According to this function, a hot-journal
** file exists if the following criteria are met:
**
**   * The journal file exists in the file system, and
**   * No process holds a RESERVED or greater lock on the database file, and
**   * The database file itself is greater than 0 bytes in size, and
**   * The first byte of the journal file exists and is not 0x00.
**
** If the current size of the database file is 0 but a journal file
** exists, that is probably an old journal left over from a prior
** database with the same name. In this case the journal file is
** just deleted using OsDelete, *pExists is set to 0 and SQLITE_OK
** is returned.
**
** This routine does not check if there is a master journal filename
** at the end of the file. If there is, and that master journal file
** This routine does not check if there is a super-journal filename
** at the end of the file. If there is, and that super-journal file
** does not exist, then the journal file is not really hot. In this
** case this routine will return a false-positive. The pager_playback()
** routine will discover that the journal file is not really hot and 
** will not roll it back. 
**
** If a hot-journal file is found to exist, *pExists is set to 1 and 
** SQLITE_OK returned. If no hot-journal file is present, *pExists is
5304
5305
5306
5307
5308
5309
5310
5311

5312
5313
5314
5315
5316
5317
5318
5337
5338
5339
5340
5341
5342
5343

5344
5345
5346
5347
5348
5349
5350
5351







-
+







      **
      ** If the journal does not exist, it usually means that some 
      ** other connection managed to get in and roll it back before 
      ** this connection obtained the exclusive lock above. Or, it 
      ** may mean that the pager was in the error-state when this
      ** function was called and the journal file does not exist.
      */
      if( !isOpen(pPager->jfd) ){
      if( !isOpen(pPager->jfd) && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){
        sqlite3_vfs * const pVfs = pPager->pVfs;
        int bExists;              /* True if journal file exists */
        rc = sqlite3OsAccess(
            pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &bExists);
        if( rc==SQLITE_OK && bExists ){
          int fout = 0;
          int f = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_JOURNAL;
5561
5562
5563
5564
5565
5566
5567
5568

5569
5570
5571
5572
5573
5574
5575
5576

5577
5578
5579

5580
5581
5582
5583
5584
5585
5586
5594
5595
5596
5597
5598
5599
5600

5601
5602
5603
5604
5605
5606
5607
5608

5609
5610
5611

5612
5613
5614
5615
5616
5617
5618
5619







-
+







-
+


-
+







  assert( pPg->pgno==pgno );
  assert( pPg->pPager==pPager || pPg->pPager==0 );

  noContent = (flags & PAGER_GET_NOCONTENT)!=0;
  if( pPg->pPager && !noContent ){
    /* In this case the pcache already contains an initialized copy of
    ** the page. Return without further ado.  */
    assert( pgno<=PAGER_MAX_PGNO && pgno!=PAGER_MJ_PGNO(pPager) );
    assert( pgno!=PAGER_SJ_PGNO(pPager) );
    pPager->aStat[PAGER_STAT_HIT]++;
    return SQLITE_OK;

  }else{
    /* The pager cache has created a new page. Its content needs to 
    ** be initialized. But first some error checks:
    **
    ** (1) The maximum page number is 2^31
    ** (*) obsolete.  Was: maximum page number is 2^31
    ** (2) Never try to fetch the locking page
    */
    if( pgno>PAGER_MAX_PGNO || pgno==PAGER_MJ_PGNO(pPager) ){
    if( pgno==PAGER_SJ_PGNO(pPager) ){
      rc = SQLITE_CORRUPT_BKPT;
      goto pager_acquire_err;
    }

    pPg->pPager = pPager;

    assert( !isOpen(pPager->fd) || !MEMDB );
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5679
5680
5681
5682
5683
5684
5685



5686
5687
5688
5689
5690
5691
5692







-
-
-







  ** flag was specified by the caller. And so long as the db is not a 
  ** temporary or in-memory database.  */
  const int bMmapOk = (pgno>1
   && (pPager->eState==PAGER_READER || (flags & PAGER_GET_READONLY))
  );

  assert( USEFETCH(pPager) );
#ifdef SQLITE_HAS_CODEC
  assert( pPager->xCodec==0 );
#endif

  /* Optimization note:  Adding the "pgno<=1" term before "pgno==0" here
  ** allows the compiler optimizer to reuse the results of the "pgno>1"
  ** test in the previous statement, and avoid testing pgno==0 in the
  ** common case where pgno is large. */
  if( pgno<=1 && pgno==0 ){
    return SQLITE_CORRUPT_BKPT;
5721
5722
5723
5724
5725
5726
5727

5728
5729
5730
5731
5732
5733
5734
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765







+







*/
int sqlite3PagerGet(
  Pager *pPager,      /* The pager open on the database file */
  Pgno pgno,          /* Page number to fetch */
  DbPage **ppPage,    /* Write a pointer to the page here */
  int flags           /* PAGER_GET_XXX flags */
){
  /* printf("PAGE %u\n", pgno); fflush(stdout); */
  return pPager->xGet(pPager, pgno, ppPage, flags);
}

/*
** Acquire a page if it is already in the in-memory cache.  Do
** not read the page from disk.  Return a pointer to the page,
** or 0 if the page is not in cache. 
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5810
5811
5812
5813
5814
5815
5816

5817
5818
5819
5820
5821
5822
5823







-







}
void sqlite3PagerUnrefPageOne(DbPage *pPg){
  Pager *pPager;
  assert( pPg!=0 );
  assert( pPg->pgno==1 );
  assert( (pPg->flags & PGHDR_MMAP)==0 ); /* Page1 is never memory mapped */
  pPager = pPg->pPager;
  sqlite3PagerResetLockTimeout(pPager);
  sqlite3PcacheRelease(pPg);
  pagerUnlockIfUnused(pPager);
}

/*
** This function is called at the start of every write transaction.
** There must already be a RESERVED or EXCLUSIVE lock on the database 
5835
5836
5837
5838
5839
5840
5841

5842
5843
5844
5845
5846
5847
5848
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879







+







        sqlite3MemJournalOpen(pPager->jfd);
      }else{
        int flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
        int nSpill;

        if( pPager->tempFile ){
          flags |= (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL);
          flags |= SQLITE_OPEN_EXCLUSIVE;
          nSpill = sqlite3Config.nStmtSpill;
        }else{
          flags |= SQLITE_OPEN_MAIN_JOURNAL;
          nSpill = jrnlBufferSize(pPager);
        }
          
        /* Verify that the database still has the same name as it did when
5861
5862
5863
5864
5865
5866
5867
5868

5869
5870
5871
5872
5873
5874
5875
5876

5877
5878
5879
5880
5881
5882
5883
5892
5893
5894
5895
5896
5897
5898

5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915







-
+








+







    /* Write the first journal header to the journal file and open 
    ** the sub-journal if necessary.
    */
    if( rc==SQLITE_OK ){
      /* TODO: Check if all of these are really required. */
      pPager->nRec = 0;
      pPager->journalOff = 0;
      pPager->setMaster = 0;
      pPager->setSuper = 0;
      pPager->journalHdr = 0;
      rc = writeJournalHdr(pPager);
    }
  }

  if( rc!=SQLITE_OK ){
    sqlite3BitvecDestroy(pPager->pInJournal);
    pPager->pInJournal = 0;
    pPager->journalOff = 0;
  }else{
    assert( pPager->eState==PAGER_WRITER_LOCKED );
    pPager->eState = PAGER_WRITER_CACHEMOD;
  }

  return rc;
}
5905
5906
5907
5908
5909
5910
5911
5912

5913
5914
5915
5916
5917
5918
5919
5937
5938
5939
5940
5941
5942
5943

5944
5945
5946
5947
5948
5949
5950
5951







-
+







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) ){
        rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
5977
5978
5979
5980
5981
5982
5983
5984

5985
5986
5987

5988
5989
5990
5991
5992
5993
5994
6009
6010
6011
6012
6013
6014
6015

6016
6017
6018

6019
6020
6021
6022
6023
6024
6025
6026







-
+


-
+







  u32 cksum;
  char *pData2;
  i64 iOff = pPager->journalOff;

  /* We should never write to the journal file the page that
  ** contains the database locks.  The following assert verifies
  ** that we do not. */
  assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) );
  assert( pPg->pgno!=PAGER_SJ_PGNO(pPager) );

  assert( pPager->journalHdr<=pPager->journalOff );
  CODEC2(pPager, pPg->pData, pPg->pgno, 7, return SQLITE_NOMEM_BKPT, pData2);
  pData2 = pPg->pData;
  cksum = pager_cksum(pPager, (u8*)pData2);

  /* Even if an IO or diskfull error occurs while journalling the
  ** page in the block above, set the need-sync flag for the page.
  ** Otherwise, when the transaction is rolled back, the logic in
  ** playback_one_page() will think that the page needs to be restored
  ** in the database file. And if an IO error occurs while doing so,
6156
6157
6158
6159
6160
6161
6162
6163

6164
6165
6166
6167
6168
6169
6170
6188
6189
6190
6191
6192
6193
6194

6195
6196
6197
6198
6199
6200
6201
6202







-
+







  assert(pg1<=pPg->pgno);
  assert((pg1+nPage)>pPg->pgno);

  for(ii=0; ii<nPage && rc==SQLITE_OK; ii++){
    Pgno pg = pg1+ii;
    PgHdr *pPage;
    if( pg==pPg->pgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){
      if( pg!=PAGER_MJ_PGNO(pPager) ){
      if( pg!=PAGER_SJ_PGNO(pPager) ){
        rc = sqlite3PagerGet(pPager, pg, &pPage, 0);
        if( rc==SQLITE_OK ){
          rc = pager_write(pPage);
          if( pPage->flags&PGHDR_NEED_SYNC ){
            needSync = 1;
          }
          sqlite3PagerUnrefNotNull(pPage);
6345
6346
6347
6348
6349
6350
6351
6352

6353
6354
6355
6356
6357
6358
6359
6377
6378
6379
6380
6381
6382
6383

6384
6385
6386
6387
6388
6389
6390
6391







-
+







      /* Actually do the update of the change counter */
      pager_write_changecounter(pPgHdr);

      /* If running in direct mode, write the contents of page 1 to the file. */
      if( DIRECT_MODE ){
        const void *zBuf;
        assert( pPager->dbFileSize>0 );
        CODEC2(pPager, pPgHdr->pData, 1, 6, rc=SQLITE_NOMEM_BKPT, zBuf);
        zBuf = pPgHdr->pData;
        if( rc==SQLITE_OK ){
          rc = sqlite3OsWrite(pPager->fd, zBuf, pPager->pageSize, 0);
          pPager->aStat[PAGER_STAT_WRITE]++;
        }
        if( rc==SQLITE_OK ){
          /* Update the pager's copy of the change-counter. Otherwise, the
          ** next time a read transaction is opened the cache will be
6376
6377
6378
6379
6380
6381
6382
6383

6384
6385

6386
6387
6388
6389
6390
6391
6392
6408
6409
6410
6411
6412
6413
6414

6415
6416

6417
6418
6419
6420
6421
6422
6423
6424







-
+

-
+







/*
** Sync the database file to disk. This is a no-op for in-memory databases
** or pages with the Pager.noSync flag set.
**
** If successful, or if called on a pager for which it is a no-op, this
** function returns SQLITE_OK. Otherwise, an IO error code is returned.
*/
int sqlite3PagerSync(Pager *pPager, const char *zMaster){
int sqlite3PagerSync(Pager *pPager, const char *zSuper){
  int rc = SQLITE_OK;
  void *pArg = (void*)zMaster;
  void *pArg = (void*)zSuper;
  rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC, pArg);
  if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
  if( rc==SQLITE_OK && !pPager->noSync ){
    assert( !MEMDB );
    rc = sqlite3OsSync(pPager->fd, pPager->syncFlags);
  }
  return rc;
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
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







-
-
-
-
+
+
+
+











-
+

-
+









-
+

















-
-
+
+







    sqlite3WalEndWriteTransaction(pPager->pWal);
  }
}
#endif  /* SQLITE_OMIT_CONCURRENT */


/*
** Sync the database file for the pager pPager. zMaster points to the name
** of a master journal file that should be written into the individual
** journal file. zMaster may be NULL, which is interpreted as no master
** journal (a single database transaction).
** Sync the database file for the pager pPager. zSuper points to the name
** of a super-journal file that should be written into the individual
** journal file. zSuper may be NULL, which is interpreted as no 
** super-journal (a single database transaction).
**
** This routine ensures that:
**
**   * The database file change-counter is updated,
**   * the journal is synced (unless the atomic-write optimization is used),
**   * all dirty pages are written to the database file, 
**   * the database file is truncated (if required), and
**   * the database file synced. 
**
** The only thing that remains to commit the transaction is to finalize 
** (delete, truncate or zero the first part of) the journal file (or 
** delete the master journal file if specified).
** delete the super-journal file if specified).
**
** Note that if zMaster==NULL, this does not overwrite a previous value
** Note that if zSuper==NULL, this does not overwrite a previous value
** passed to an sqlite3PagerCommitPhaseOne() call.
**
** If the final parameter - noSync - is true, then the database file itself
** is not synced. The caller must call sqlite3PagerSync() directly to
** sync the database file before calling CommitPhaseTwo() to delete the
** journal file in this case.
*/
int sqlite3PagerCommitPhaseOne(
  Pager *pPager,                  /* Pager object */
  const char *zMaster,            /* If not NULL, the master journal name */
  const char *zSuper,            /* If not NULL, the super-journal name */
  int noSync                      /* True to omit the xSync on the db file */
){
  int rc = SQLITE_OK;             /* Return code */

  assert( pPager->eState==PAGER_WRITER_LOCKED
       || pPager->eState==PAGER_WRITER_CACHEMOD
       || pPager->eState==PAGER_WRITER_DBMOD
       || pPager->eState==PAGER_ERROR
  );
  assert( assert_pager_state(pPager) );

  /* If a prior error occurred, report that error again. */
  if( NEVER(pPager->errCode) ) return pPager->errCode;

  /* Provide the ability to easily simulate an I/O error during testing */
  if( sqlite3FaultSim(400) ) return SQLITE_IOERR;

  PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n", 
      pPager->zFilename, zMaster, pPager->dbSize));
  PAGERTRACE(("DATABASE SYNC: File=%s zSuper=%s nSize=%d\n", 
      pPager->zFilename, zSuper, pPager->dbSize));

  /* If no database changes have been made, return early. */
  if( pPager->eState<PAGER_WRITER_CACHEMOD ) return SQLITE_OK;

  assert( MEMDB==0 || pPager->tempFile );
  assert( isOpen(pPager->fd) || pPager->tempFile );
  if( 0==pagerFlushOnCommit(pPager, 1) ){
6573
6574
6575
6576
6577
6578
6579
6580

6581
6582
6583
6584
6585
6586
6587
6605
6606
6607
6608
6609
6610
6611

6612
6613
6614
6615
6616
6617
6618
6619







-
+







    }else{
      /* The bBatch boolean is true if the batch-atomic-write commit method
      ** should be used.  No rollback journal is created if batch-atomic-write
      ** is enabled.
      */
#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
      sqlite3_file *fd = pPager->fd;
      int bBatch = zMaster==0    /* An SQLITE_IOCAP_BATCH_ATOMIC commit */
      int bBatch = zSuper==0    /* An SQLITE_IOCAP_BATCH_ATOMIC commit */
        && (sqlite3OsDeviceCharacteristics(fd) & SQLITE_IOCAP_BATCH_ATOMIC)
        && !pPager->noSync
        && sqlite3JournalIsInMemory(pPager->jfd);
#else
#     define bBatch 0
#endif

6611
6612
6613
6614
6615
6616
6617
6618

6619
6620
6621
6622
6623
6624
6625
6626
6627
6628
6629
6630
6631
6632
6633
6634
6635
6636
6637
6638
6639

6640
6641
6642
6643
6644
6645
6646
6647
6648
6649
6650
6651



6652
6653

6654
6655
6656
6657
6658
6659
6660
6643
6644
6645
6646
6647
6648
6649

6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
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







-
+




















-
+









-
-
-
+
+
+

-
+







      */
      if( bBatch==0 ){
        PgHdr *pPg;
        assert( isOpen(pPager->jfd) 
            || pPager->journalMode==PAGER_JOURNALMODE_OFF 
            || pPager->journalMode==PAGER_JOURNALMODE_WAL 
            );
        if( !zMaster && isOpen(pPager->jfd) 
        if( !zSuper && isOpen(pPager->jfd) 
         && pPager->journalOff==jrnlBufferSize(pPager) 
         && pPager->dbSize>=pPager->dbOrigSize
         && (!(pPg = sqlite3PcacheDirtyList(pPager->pPCache)) || 0==pPg->pDirty)
        ){
          /* Update the db file change counter via the direct-write method. The 
          ** following call will modify the in-memory representation of page 1 
          ** to include the updated change counter and then write page 1 
          ** directly to the database file. Because of the atomic-write 
          ** property of the host file-system, this is safe.
          */
          rc = pager_incr_changecounter(pPager, 1);
        }else{
          rc = sqlite3JournalCreate(pPager->jfd);
          if( rc==SQLITE_OK ){
            rc = pager_incr_changecounter(pPager, 0);
          }
        }
      }
#else  /* SQLITE_ENABLE_ATOMIC_WRITE */
#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
      if( zMaster ){
      if( zSuper ){
        rc = sqlite3JournalCreate(pPager->jfd);
        if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
        assert( bBatch==0 );
      }
#endif
      rc = pager_incr_changecounter(pPager, 0);
#endif /* !SQLITE_ENABLE_ATOMIC_WRITE */
      if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
  
      /* Write the master journal name into the journal file. If a master 
      ** journal file name has already been written to the journal file, 
      ** or if zMaster is NULL (no master journal), then this call is a no-op.
      /* Write the super-journal name into the journal file. If a
      ** super-journal file name has already been written to the journal file, 
      ** or if zSuper is NULL (no super-journal), then this call is a no-op.
      */
      rc = writeMasterJournal(pPager, zMaster);
      rc = writeSuperJournal(pPager, zSuper);
      if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
  
      /* Sync the journal file and write all dirty pages to the database.
      ** If the atomic-update optimization is being used, this sync will not 
      ** create the journal file or perform any real IO.
      **
      ** Because the change-counter page was just modified, unless the
6706
6707
6708
6709
6710
6711
6712
6713

6714
6715
6716
6717
6718
6719
6720
6721

6722
6723
6724
6725
6726
6727
6728
6738
6739
6740
6741
6742
6743
6744

6745
6746
6747
6748
6749
6750
6751
6752

6753
6754
6755
6756
6757
6758
6759
6760







-
+







-
+







      /* If the file on disk is smaller than the database image, use 
      ** pager_truncate to grow the file here. This can happen if the database
      ** image was extended as part of the current transaction and then the
      ** last page in the db image moved to the free-list. In this case the
      ** last page is never written out to disk, leaving the database file
      ** undersized. Fix this now if it is the case.  */
      if( pPager->dbSize>pPager->dbFileSize ){
        Pgno nNew = pPager->dbSize - (pPager->dbSize==PAGER_MJ_PGNO(pPager));
        Pgno nNew = pPager->dbSize - (pPager->dbSize==PAGER_SJ_PGNO(pPager));
        assert( pPager->eState==PAGER_WRITER_DBMOD );
        rc = pager_truncate(pPager, nNew);
        if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
      }
  
      /* Finally, sync the database file. */
      if( !noSync ){
        rc = sqlite3PagerSync(pPager, zMaster);
        rc = sqlite3PagerSync(pPager, zSuper);
      }
      IOTRACE(("DBSYNC %p\n", pPager))
    }
  }

commit_phase_one_exit:
  if( rc==SQLITE_OK && !pagerUseWal(pPager) ){
6750
6751
6752
6753
6754
6755
6756

6757
6758
6759
6760
6761
6762
6763
6782
6783
6784
6785
6786
6787
6788
6789
6790
6791
6792
6793
6794
6795
6796







+







int sqlite3PagerCommitPhaseTwo(Pager *pPager){
  int rc = SQLITE_OK;                  /* Return code */

  /* This routine should not be called if a prior error has occurred.
  ** But if (due to a coding error elsewhere in the system) it does get
  ** called, just return the same error code without doing anything. */
  if( NEVER(pPager->errCode) ) return pPager->errCode;
  pPager->iDataVersion++;

  assert( pPager->eState==PAGER_WRITER_LOCKED
       || pPager->eState==PAGER_WRITER_FINISHED
       || (pagerUseWal(pPager) && pPager->eState==PAGER_WRITER_CACHEMOD)
  );
  assert( assert_pager_state(pPager) );

6778
6779
6780
6781
6782
6783
6784
6785
6786

6787
6788
6789
6790
6791
6792
6793
6811
6812
6813
6814
6815
6816
6817


6818
6819
6820
6821
6822
6823
6824
6825







-
-
+







  ){
    assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) || !pPager->journalOff );
    pPager->eState = PAGER_READER;
    return SQLITE_OK;
  }

  PAGERTRACE(("COMMIT %d\n", PAGERID(pPager)));
  pPager->iDataVersion++;
  rc = pager_end_transaction(pPager, pPager->setMaster, 1);
  rc = pager_end_transaction(pPager, pPager->setSuper, 1);
  return pager_error(pPager, rc);
}

/*
** If a write transaction is open, then all changes made within the 
** transaction are reverted and the current write-transaction is closed.
** The pager falls back to PAGER_READER state if successful, or PAGER_ERROR
6824
6825
6826
6827
6828
6829
6830
6831

6832
6833
6834
6835
6836
6837
6838
6856
6857
6858
6859
6860
6861
6862

6863
6864
6865
6866
6867
6868
6869
6870







-
+







  assert( assert_pager_state(pPager) );
  if( pPager->eState==PAGER_ERROR ) return pPager->errCode;
  if( pPager->eState<=PAGER_READER ) return SQLITE_OK;

  if( pagerUseWal(pPager) ){
    int rc2;
    rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, -1);
    rc2 = pager_end_transaction(pPager, pPager->setMaster, 0);
    rc2 = pager_end_transaction(pPager, pPager->setSuper, 0);
    if( rc==SQLITE_OK ) rc = rc2;
  }else if( !isOpen(pPager->jfd) || pPager->eState==PAGER_WRITER_LOCKED ){
    int eState = pPager->eState;
    rc = pager_end_transaction(pPager, 0, 0);
    if( !MEMDB && eState>PAGER_WRITER_LOCKED ){
      /* This can happen using journal_mode=off. Move the pager to the error 
      ** state to indicate that the contents of the cache may not be trusted.
6877
6878
6879
6880
6881
6882
6883
6884
6885


6886
6887
6888
6889
6890
6891
6892
6909
6910
6911
6912
6913
6914
6915


6916
6917
6918
6919
6920
6921
6922
6923
6924







-
-
+
+







#endif

/*
** Return the approximate number of bytes of memory currently
** used by the pager and its associated cache.
*/
int sqlite3PagerMemUsed(Pager *pPager){
  int perPageSize = pPager->pageSize + pPager->nExtra + sizeof(PgHdr)
                                     + 5*sizeof(void*);
  int perPageSize = pPager->pageSize + pPager->nExtra
    + (int)(sizeof(PgHdr) + 5*sizeof(void*));
  return perPageSize*sqlite3PcachePagecount(pPager->pPCache)
           + sqlite3MallocSize(pPager)
           + pPager->pageSize;
}

/*
** Return the number of references to the specified page.
6947
6948
6949
6950
6951
6952
6953
6954

6955
6956
6957
6958
6959
6960
6961
6979
6980
6981
6982
6983
6984
6985

6986
6987
6988
6989
6990
6991
6992
6993







-
+







  }
}

/*
** Return true if this is an in-memory or temp-file backed pager.
*/
int sqlite3PagerIsMemdb(Pager *pPager){
  return pPager->tempFile;
  return pPager->tempFile || pPager->memVfs;
}

/*
** Check that there are at least nSavepoint savepoints open. If there are
** currently less than nSavepoints open, then open one or more savepoints
** to make up the difference. If the number of savepoints is already
** equal to nSavepoint, then this function is a no-op.
6993
6994
6995
6996
6997
6998
6999

7000
7001
7002
7003
7004
7005
7006
7025
7026
7027
7028
7029
7030
7031
7032
7033
7034
7035
7036
7037
7038
7039







+







    if( isOpen(pPager->jfd) && pPager->journalOff>0 ){
      aNew[ii].iOffset = pPager->journalOff;
    }else{
      aNew[ii].iOffset = JOURNAL_HDR_SZ(pPager);
    }
    aNew[ii].iSubRec = pPager->nSubRec;
    aNew[ii].pInSavepoint = sqlite3BitvecCreate(pPager->dbSize);
    aNew[ii].bTruncateOnRelease = 1;
    if( !aNew[ii].pInSavepoint ){
      return SQLITE_NOMEM_BKPT;
    }
    if( pagerUseWal(pPager) ){
      sqlite3WalSavepoint(pPager->pWal, aNew[ii].aWalData);
    }
    pPager->nSavepoint = ii+1;
7071
7072
7073
7074
7075
7076
7077
7078
7079


7080

7081

7082
7083

7084

7085
7086
7087

7088
7089
7090
7091
7092
7093
7094
7104
7105
7106
7107
7108
7109
7110


7111
7112
7113
7114

7115
7116
7117
7118

7119
7120
7121

7122
7123
7124
7125
7126
7127
7128
7129







-
-
+
+

+
-
+


+
-
+


-
+







    */
    nNew = iSavepoint + (( op==SAVEPOINT_RELEASE ) ? 0 : 1);
    for(ii=nNew; ii<pPager->nSavepoint; ii++){
      sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint);
    }
    pPager->nSavepoint = nNew;

    /* If this is a release of the outermost savepoint, truncate 
    ** the sub-journal to zero bytes in size. */
    /* Truncate the sub-journal so that it only includes the parts
    ** that are still in use. */
    if( op==SAVEPOINT_RELEASE ){
      PagerSavepoint *pRel = &pPager->aSavepoint[nNew];
      if( nNew==0 && isOpen(pPager->sjfd) ){
      if( pRel->bTruncateOnRelease && isOpen(pPager->sjfd) ){
        /* Only truncate if it is an in-memory sub-journal. */
        if( sqlite3JournalIsInMemory(pPager->sjfd) ){
          i64 sz = (pPager->pageSize+4)*(i64)pRel->iSubRec;
          rc = sqlite3OsTruncate(pPager->sjfd, 0);
          rc = sqlite3OsTruncate(pPager->sjfd, sz);
          assert( rc==SQLITE_OK );
        }
        pPager->nSubRec = 0;
        pPager->nSubRec = pRel->iSubRec;
      }
    }
    /* Else this is a rollback operation, playback the specified savepoint.
    ** If this is a temp-file, it is possible that the journal file has
    ** not yet been opened. In this case there have been no changes to
    ** the database file, so the playback operation can be skipped.
    */
7122
7123
7124
7125
7126
7127
7128



7129
7130
7131







7132
7133
7134
7135
7136
7137
7138
7139
7140
7141
7142
7143
7144
7145
7146
7147
7148
7149
7150
7151
7152
7153
7154
7155
7156
7157
7158
7159
7160
7161
7162
7163
7164
7165
7166
7167
7168
7169
7170
7171
7172
7173
7174
7175
7176
7177
7178
7179
7180
7181
7182
7183
7184
7185
7186
7187
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
7157
7158
7159
7160
7161
7162
7163
7164
7165
7166
7167


7168
7169
7170
7171
7172
7173
7174
7175
7176
7177
7178
7179
7180
7181
7182
7183
7184
7185
7186
7187
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







+
+
+

-
-
+
+
+
+
+
+
+


















-
-
-
-
-
-
-
-
-
-



















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







**
** Except, if the pager is in-memory only, then return an empty string if
** nullIfMemDb is true.  This routine is called with nullIfMemDb==1 when
** used to report the filename to the user, for compatibility with legacy
** behavior.  But when the Btree needs to know the filename for matching to
** shared cache, it uses nullIfMemDb==0 so that in-memory databases can
** participate in shared-cache.
**
** The return value to this routine is always safe to use with
** sqlite3_uri_parameter() and sqlite3_filename_database() and friends.
*/
const char *sqlite3PagerFilename(Pager *pPager, int nullIfMemDb){
  return (nullIfMemDb && pPager->memDb) ? "" : pPager->zFilename;
const char *sqlite3PagerFilename(const Pager *pPager, int nullIfMemDb){
  static const char zFake[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
  if( nullIfMemDb && (pPager->memDb || sqlite3IsMemdb(pPager->pVfs)) ){
    return &zFake[4];
  }else{
    return pPager->zFilename;
  }
}

/*
** Return the VFS structure for the pager.
*/
sqlite3_vfs *sqlite3PagerVfs(Pager *pPager){
  return pPager->pVfs;
}

/*
** Return the file handle for the database file associated
** with the pager.  This might return NULL if the file has
** not yet been opened.
*/
sqlite3_file *sqlite3PagerFile(Pager *pPager){
  return pPager->fd;
}

#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
/*
** Reset the lock timeout for pager.
*/
void sqlite3PagerResetLockTimeout(Pager *pPager){
  int x = 0;
  sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_LOCK_TIMEOUT, &x);
}
#endif

/*
** Return the file handle for the journal file (if it exists).
** This will be either the rollback journal or the WAL file.
*/
sqlite3_file *sqlite3PagerJrnlFile(Pager *pPager){
#if SQLITE_OMIT_WAL
  return pPager->jfd;
#else
  return pPager->pWal ? sqlite3WalFile(pPager->pWal) : pPager->jfd;
#endif
}

/*
** Return the full pathname of the journal file.
*/
const char *sqlite3PagerJournalname(Pager *pPager){
  return pPager->zJournal;
}

#ifdef SQLITE_HAS_CODEC
/*
** Set or retrieve the codec for this pager
*/
void sqlite3PagerSetCodec(
  Pager *pPager,
  void *(*xCodec)(void*,void*,Pgno,int),
  void (*xCodecSizeChng)(void*,int,int),
  void (*xCodecFree)(void*),
  void *pCodec
){
  if( pPager->xCodecFree ){
    pPager->xCodecFree(pPager->pCodec);
  }else{
    pager_reset(pPager);
  }
  pPager->xCodec = pPager->memDb ? 0 : xCodec;
  pPager->xCodecSizeChng = xCodecSizeChng;
  pPager->xCodecFree = xCodecFree;
  pPager->pCodec = pCodec;
  setGetterMethod(pPager);
  pagerReportSize(pPager);
}
void *sqlite3PagerGetCodec(Pager *pPager){
  return pPager->pCodec;
}

/*
** This function is called by the wal module when writing page content
** into the log file.
**
** This function returns a pointer to a buffer containing the encrypted
** page content. If a malloc fails, this function may return NULL.
*/
void *sqlite3PagerCodec(PgHdr *pPg){
  void *aData = 0;
  CODEC2(pPg->pPager, pPg->pData, pPg->pgno, 6, return 0, aData);
  return aData;
}

/*
** Return the current pager state
*/
int sqlite3PagerState(Pager *pPager){
  return pPager->eState;
}
#endif /* SQLITE_HAS_CODEC */

#ifndef SQLITE_OMIT_AUTOVACUUM
/*
** Move the page pPg to location pgno in the file.
**
** There must be no references to the page previously located at
** pgno (which we call pPgOld) though that page is allowed to be
** in cache.  If the page previously located at pgno is not already
7316
7317
7318
7319
7320
7321
7322
7323

7324




7325
7326
7327
7328
7329
7330
7331
7301
7302
7303
7304
7305
7306
7307

7308
7309
7310
7311
7312
7313
7314
7315
7316
7317
7318
7319
7320







-
+

+
+
+
+







  /* If the cache contains a page with page-number pgno, remove it
  ** from its hash chain. Also, if the PGHDR_NEED_SYNC flag was set for 
  ** page pgno before the 'move' operation, it needs to be retained 
  ** for the page moved there.
  */
  pPg->flags &= ~PGHDR_NEED_SYNC;
  pPgOld = sqlite3PagerLookup(pPager, pgno);
  assert( !pPgOld || pPgOld->nRef==1 );
  assert( !pPgOld || pPgOld->nRef==1 || CORRUPT_DB );
  if( pPgOld ){
    if( NEVER(pPgOld->nRef>1) ){
      sqlite3PagerUnrefNotNull(pPgOld);
      return SQLITE_CORRUPT_BKPT;
    }
    pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);
    if( pPager->tempFile ){
      /* Do not discard pages from an in-memory database since we might
      ** need to rollback later.  Just move the page out of the way. */
      sqlite3PcacheMove(pPgOld, pPager->dbSize+1);
    }else{
      sqlite3PcacheDrop(pPgOld);
7449
7450
7451
7452
7453
7454
7455
7456
7457
7458
7459
7460
7461







7462
7463
7464
7465
7466
7467
7468
7438
7439
7440
7441
7442
7443
7444






7445
7446
7447
7448
7449
7450
7451
7452
7453
7454
7455
7456
7457
7458







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







**
** The returned indicate the current (possibly updated) journal-mode.
*/
int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){
  u8 eOld = pPager->journalMode;    /* Prior journalmode */

  /* The eMode parameter is always valid */
  assert(      eMode==PAGER_JOURNALMODE_DELETE
            || eMode==PAGER_JOURNALMODE_TRUNCATE
            || eMode==PAGER_JOURNALMODE_PERSIST
            || eMode==PAGER_JOURNALMODE_OFF 
            || eMode==PAGER_JOURNALMODE_WAL 
            || eMode==PAGER_JOURNALMODE_MEMORY );
  assert(      eMode==PAGER_JOURNALMODE_DELETE    /* 0 */
            || eMode==PAGER_JOURNALMODE_PERSIST   /* 1 */
            || eMode==PAGER_JOURNALMODE_OFF       /* 2 */
            || eMode==PAGER_JOURNALMODE_TRUNCATE  /* 3 */
            || eMode==PAGER_JOURNALMODE_MEMORY    /* 4 */
            || eMode==PAGER_JOURNALMODE_WAL       /* 5 */
            || eMode==PAGER_JOURNALMODE_WAL2      /* 6 */ );

  /* This routine is only called from the OP_JournalMode opcode, and
  ** the logic there will never allow a temporary file to be changed
  ** to WAL mode.
  */
  assert( pPager->tempFile==0 || eMode!=PAGER_JOURNALMODE_WAL );

7488
7489
7490
7491
7492
7493
7494

7495
7496
7497
7498



7499
7500
7501
7502
7503
7504
7505
7478
7479
7480
7481
7482
7483
7484
7485
7486
7487


7488
7489
7490
7491
7492
7493
7494
7495
7496
7497







+


-
-
+
+
+







    */
    assert( (PAGER_JOURNALMODE_TRUNCATE & 5)==1 );
    assert( (PAGER_JOURNALMODE_PERSIST & 5)==1 );
    assert( (PAGER_JOURNALMODE_DELETE & 5)==0 );
    assert( (PAGER_JOURNALMODE_MEMORY & 5)==4 );
    assert( (PAGER_JOURNALMODE_OFF & 5)==0 );
    assert( (PAGER_JOURNALMODE_WAL & 5)==5 );
    assert( (PAGER_JOURNALMODE_WAL2 & 5)==4 );

    assert( isOpen(pPager->fd) || pPager->exclusiveMode );
    if( !pPager->exclusiveMode && (eOld & 5)==1 && (eMode & 1)==0 ){

    if( !pPager->exclusiveMode && (eOld & 5)==1 && (eMode & 1)==0 
     && eMode!=PAGER_JOURNALMODE_WAL2       /* TODO: fix this if possible */
    ){
      /* In this case we would like to delete the journal file. If it is
      ** not possible, then that is not a problem. Deleting the journal file
      ** here is an optimization only.
      **
      ** Before deleting the journal file, obtain a RESERVED lock on the
      ** database file. This ensures that the journal file is not deleted
      ** while it is in use by some other client.
7603
7604
7605
7606
7607
7608
7609












7610
7611
7612
7613
7614
7615
7616
7617
7618
7619
7620
7621
7622
7623
7624
7595
7596
7597
7598
7599
7600
7601
7602
7603
7604
7605
7606
7607
7608
7609
7610
7611
7612
7613
7614
7615
7616
7617
7618
7619
7620

7621
7622
7623
7624
7625
7626
7627







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







-







  Pager *pPager,                  /* Checkpoint on this pager */
  sqlite3 *db,                    /* Db handle used to check for interrupts */
  int eMode,                      /* Type of checkpoint */
  int *pnLog,                     /* OUT: Final number of frames in log */
  int *pnCkpt                     /* OUT: Final number of checkpointed frames */
){
  int rc = SQLITE_OK;
  if( pPager->pWal==0 && pPager->journalMode==PAGER_JOURNALMODE_WAL ){
    /* This only happens when a database file is zero bytes in size opened and
    ** then "PRAGMA journal_mode=WAL" is run and then sqlite3_wal_checkpoint()
    ** is invoked without any intervening transactions.  We need to start
    ** a transaction to initialize pWal.  The PRAGMA table_list statement is
    ** used for this since it starts transactions on every database file,
    ** including all ATTACHed databases.  This seems expensive for a single
    ** sqlite3_wal_checkpoint() call, but it happens very rarely.
    ** https://sqlite.org/forum/forumpost/fd0f19d229156939
    */
    sqlite3_exec(db, "PRAGMA table_list",0,0,0);
  }
  if( pPager->pWal ){
    rc = sqlite3WalCheckpoint(pPager->pWal, db, eMode,
        (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler),
        pPager->pBusyHandlerArg,
        pPager->walSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
        pnLog, pnCkpt
    );
    sqlite3PagerResetLockTimeout(pPager);
  }
  return rc;
}

int sqlite3PagerWalCallback(Pager *pPager){
  return sqlite3WalCallback(pPager->pWal);
}
7653
7654
7655
7656
7657
7658
7659
7660

7661
7662
7663
7664
7665
7666
7667
7668
7669
7670
7671
7672
7673
7674
7675
7676
7677
7678
7679
7680
7681

7682
7683
7684
7685
7686
7687
7688
7656
7657
7658
7659
7660
7661
7662

7663
7664
7665
7666
7667
7668
7669
7670
7671
7672
7673
7674
7675
7676
7677
7678
7679
7680
7681
7682
7683

7684
7685
7686
7687
7688
7689
7690
7691







-
+




















-
+








/*
** Call sqlite3WalOpen() to open the WAL handle. If the pager is in 
** exclusive-locking mode when this function is called, take an EXCLUSIVE
** lock on the database file and use heap-memory to store the wal-index
** in. Otherwise, use the normal shared-memory.
*/
static int pagerOpenWal(Pager *pPager){
static int pagerOpenWal(Pager *pPager, int bWal2){
  int rc = SQLITE_OK;

  assert( pPager->pWal==0 && pPager->tempFile==0 );
  assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK );

  /* If the pager is already in exclusive-mode, the WAL module will use 
  ** heap-memory for the wal-index instead of the VFS shared-memory 
  ** implementation. Take the exclusive lock now, before opening the WAL
  ** file, to make sure this is safe.
  */
  if( pPager->exclusiveMode ){
    rc = pagerExclusiveLock(pPager);
  }

  /* Open the connection to the log file. If this operation fails, 
  ** (e.g. due to malloc() failure), return an error code.
  */
  if( rc==SQLITE_OK ){
    rc = sqlite3WalOpen(pPager->pVfs,
        pPager->fd, pPager->zWal, pPager->exclusiveMode,
        pPager->journalSizeLimit, &pPager->pWal
        pPager->journalSizeLimit, bWal2, &pPager->pWal
    );
  }
  pagerFixMaplimit(pPager);

  return rc;
}

7700
7701
7702
7703
7704
7705
7706

7707
7708
7709
7710
7711
7712
7713
7714
7715
7716
7717
7718
7719
7720
7721
7722
7723

7724
7725

7726
7727
7728
7729
7730
7731
7732
7703
7704
7705
7706
7707
7708
7709
7710
7711
7712
7713
7714
7715
7716
7717
7718
7719
7720
7721
7722
7723
7724
7725
7726

7727
7728

7729
7730
7731
7732
7733
7734
7735
7736







+
















-
+

-
+







**
** If the pager is open on a temp-file (or in-memory database), or if
** the WAL file is already open, set *pbOpen to 1 and return SQLITE_OK
** without doing anything.
*/
int sqlite3PagerOpenWal(
  Pager *pPager,                  /* Pager object */
  int bWal2,                      /* Open in wal2 mode if not already open */
  int *pbOpen                     /* OUT: Set to true if call is a no-op */
){
  int rc = SQLITE_OK;             /* Return code */

  assert( assert_pager_state(pPager) );
  assert( pPager->eState==PAGER_OPEN   || pbOpen );
  assert( pPager->eState==PAGER_READER || !pbOpen );
  assert( pbOpen==0 || *pbOpen==0 );
  assert( pbOpen!=0 || (!pPager->tempFile && !pPager->pWal) );

  if( !pPager->tempFile && !pPager->pWal ){
    if( !sqlite3PagerWalSupported(pPager) ) return SQLITE_CANTOPEN;

    /* Close any rollback journal previously open */
    sqlite3OsClose(pPager->jfd);

    rc = pagerOpenWal(pPager);
    rc = pagerOpenWal(pPager, bWal2);
    if( rc==SQLITE_OK ){
      pPager->journalMode = PAGER_JOURNALMODE_WAL;
      pPager->journalMode = bWal2?PAGER_JOURNALMODE_WAL2:PAGER_JOURNALMODE_WAL;
      pPager->eState = PAGER_OPEN;
    }
  }else{
    *pbOpen = 1;
  }

  return rc;
7740
7741
7742
7743
7744
7745
7746
7747



7748
7749
7750
7751
7752
7753
7754
7755
7756
7757
7758
7759
7760
7761
7762

7763
7764
7765
7766
7767
7768
7769
7770
7771
7772
7773
7774
7775
7776
7777
7778
7779
7780


























7781
7782
7783
7784
7785
7786
7787
7788
7789
7790
7791
7792
7793
7794
7795
7796
7797
7798
7799
7800




7801
7802
7803
7804
7805
7806
7807
7744
7745
7746
7747
7748
7749
7750

7751
7752
7753
7754
7755
7756
7757
7758
7759
7760
7761
7762
7763
7764
7765
7766
7767

7768
7769
7770
7771
7772
7773
7774
7775
7776
7777
7778
7779
7780
7781
7782
7783
7784
7785
7786
7787
7788
7789
7790
7791
7792
7793
7794
7795
7796
7797
7798
7799
7800
7801
7802
7803
7804
7805
7806
7807
7808
7809
7810
7811
7812
7813
7814
7815
7816
7817
7818
7819
7820
7821
7822
7823
7824
7825
7826
7827
7828
7829
7830
7831

7832
7833
7834
7835
7836
7837
7838
7839
7840
7841
7842







-
+
+
+














-
+


















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



















-
+
+
+
+







** EXCLUSIVE lock on the database file. If this cannot be obtained, an
** error (SQLITE_BUSY) is returned and the log connection is not closed.
** If successful, the EXCLUSIVE lock is not released before returning.
*/
int sqlite3PagerCloseWal(Pager *pPager, sqlite3 *db){
  int rc = SQLITE_OK;

  assert( pPager->journalMode==PAGER_JOURNALMODE_WAL );
  assert( pPager->journalMode==PAGER_JOURNALMODE_WAL 
       || pPager->journalMode==PAGER_JOURNALMODE_WAL2
  );

  /* If the log file is not already open, but does exist in the file-system,
  ** it may need to be checkpointed before the connection can switch to
  ** rollback mode. Open it now so this can happen.
  */
  if( !pPager->pWal ){
    int logexists = 0;
    rc = pagerLockDb(pPager, SHARED_LOCK);
    if( rc==SQLITE_OK ){
      rc = sqlite3OsAccess(
          pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &logexists
      );
    }
    if( rc==SQLITE_OK && logexists ){
      rc = pagerOpenWal(pPager);
      rc = pagerOpenWal(pPager, 0);
    }
  }
    
  /* Checkpoint and close the log. Because an EXCLUSIVE lock is held on
  ** the database file, the log and log-summary files will be deleted.
  */
  if( rc==SQLITE_OK && pPager->pWal ){
    rc = pagerExclusiveLock(pPager);
    if( rc==SQLITE_OK ){
      rc = sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags,
                           pPager->pageSize, (u8*)pPager->pTmpSpace);
      pPager->pWal = 0;
      pagerFixMaplimit(pPager);
      if( rc && !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK);
    }
  }
  return rc;
}

#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
/*
** If pager pPager is a wal-mode database not in exclusive locking mode,
** invoke the sqlite3WalWriteLock() function on the associated Wal object 
** with the same db and bLock parameters as were passed to this function.
** Return an SQLite error code if an error occurs, or SQLITE_OK otherwise.
*/
int sqlite3PagerWalWriteLock(Pager *pPager, int bLock){
  int rc = SQLITE_OK;
  if( pagerUseWal(pPager) && pPager->exclusiveMode==0 ){
    rc = sqlite3WalWriteLock(pPager->pWal, bLock);
  }
  return rc;
}

/*
** Set the database handle used by the wal layer to determine if 
** blocking locks are required.
*/
void sqlite3PagerWalDb(Pager *pPager, sqlite3 *db){
  if( pagerUseWal(pPager) ){
    sqlite3WalDb(pPager->pWal, db);
  }
}
#endif

#ifdef SQLITE_ENABLE_SNAPSHOT
/*
** If this is a WAL database, obtain a snapshot handle for the snapshot
** currently open. Otherwise, return an error.
*/
int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot){
  int rc = SQLITE_ERROR;
  if( pPager->pWal ){
    rc = sqlite3WalSnapshotGet(pPager->pWal, ppSnapshot);
  }
  return rc;
}

/*
** If this is a WAL database, store a pointer to pSnapshot. Next time a
** read transaction is opened, attempt to read from the snapshot it 
** identifies. If this is not a WAL database, return an error.
*/
int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot){
int sqlite3PagerSnapshotOpen(
  Pager *pPager, 
  sqlite3_snapshot *pSnapshot
){
  int rc = SQLITE_OK;
  if( pPager->pWal ){
    sqlite3WalSnapshotOpen(pPager->pWal, pSnapshot);
  }else{
    rc = SQLITE_ERROR;
  }
  return rc;
7845
7846
7847
7848
7849
7850
7851
7852

7853
7854
7855
7856
7857
7858
7859
7880
7881
7882
7883
7884
7885
7886

7887
7888
7889
7890
7891
7892
7893
7894







-
+








/*
** Release a lock obtained by an earlier successful call to
** sqlite3PagerSnapshotCheck().
*/
void sqlite3PagerSnapshotUnlock(Pager *pPager){
  assert( pPager->pWal );
  return sqlite3WalSnapshotUnlock(pPager->pWal);
  sqlite3WalSnapshotUnlock(pPager->pWal);
}

#endif /* SQLITE_ENABLE_SNAPSHOT */

int sqlite3PagerWalInfo(Pager *pPager, u32 *pnPrior, u32 *pnFrame){
  return sqlite3WalInfo(pPager->pWal, pnPrior, pnFrame);
}

Changes to src/pager.h.

39
40
41
42
43
44
45
46

47
48
49
50


51
52
53


54
55
56
57
58
59
60
39
40
41
42
43
44
45

46
47
48


49
50
51
52

53
54
55
56
57
58
59
60
61







-
+


-
-
+
+


-
+
+








/*
** Handle type for pages.
*/
typedef struct PgHdr DbPage;

/*
** Page number PAGER_MJ_PGNO is never used in an SQLite database (it is
** Page number PAGER_SJ_PGNO is never used in an SQLite database (it is
** reserved for working around a windows/posix incompatibility). It is
** used in the journal to signify that the remainder of the journal file 
** is devoted to storing a master journal name - there are no more pages to
** roll back. See comments for function writeMasterJournal() in pager.c 
** is devoted to storing a super-journal name - there are no more pages to
** roll back. See comments for function writeSuperJournal() in pager.c 
** for details.
*/
#define PAGER_MJ_PGNO(x) ((Pgno)((PENDING_BYTE/((x)->pageSize))+1))
#define PAGER_SJ_PGNO_COMPUTED(x) ((Pgno)((PENDING_BYTE/((x)->pageSize))+1))
#define PAGER_SJ_PGNO(x)          ((x)->lckPgno)

/*
** Allowed values for the flags parameter to sqlite3PagerOpen().
**
** NOTE: These values must match the corresponding BTREE_ values in btree.h.
*/
#define PAGER_OMIT_JOURNAL  0x0001    /* Do not use a rollback journal */
77
78
79
80
81
82
83

















84
85
86
87
88
89
90
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







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







#define PAGER_JOURNALMODE_QUERY     (-1)  /* Query the value of journalmode */
#define PAGER_JOURNALMODE_DELETE      0   /* Commit by deleting journal file */
#define PAGER_JOURNALMODE_PERSIST     1   /* Commit by zeroing journal header */
#define PAGER_JOURNALMODE_OFF         2   /* Journal omitted.  */
#define PAGER_JOURNALMODE_TRUNCATE    3   /* Commit by truncating journal */
#define PAGER_JOURNALMODE_MEMORY      4   /* In-memory journal file */
#define PAGER_JOURNALMODE_WAL         5   /* Use write-ahead logging */
#define PAGER_JOURNALMODE_WAL2        6   /* Use write-ahead logging mode 2 */

#define isWalMode(x) ((x)==PAGER_JOURNALMODE_WAL || (x)==PAGER_JOURNALMODE_WAL2)

/*
** The argument to this macro is a file descriptor (type sqlite3_file*).
** Return 0 if it is not open, or non-zero (but not 1) if it is.
**
** This is so that expressions can be written as:
**
**   if( isOpen(pPager->jfd) ){ ...
**
** instead of
**
**   if( pPager->jfd->pMethods ){ ...
*/
#define isOpen(pFd) ((pFd)->pMethods!=0)

/*
** Flags that make up the mask passed to sqlite3PagerGet().
*/
#define PAGER_GET_NOCONTENT     0x01  /* Do not load data from disk */
#define PAGER_GET_READONLY      0x02  /* Read-only page is acceptable */

124
125
126
127
128
129
130
131
132
133
134

135
136
137
138
139
140
141
142
143
144
145
146
147
148




149
150
151
152
153
154
155
156







-
-
-
-
+







);
int sqlite3PagerClose(Pager *pPager, sqlite3*);
int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);

/* Functions used to configure a Pager object. */
void sqlite3PagerSetBusyHandler(Pager*, int(*)(void *), void *);
int sqlite3PagerSetPagesize(Pager*, u32*, int);
#ifdef SQLITE_HAS_CODEC
void sqlite3PagerAlignReserve(Pager*,Pager*);
#endif
int sqlite3PagerMaxPageCount(Pager*, int);
Pgno sqlite3PagerMaxPageCount(Pager*, Pgno);
void sqlite3PagerSetCachesize(Pager*, int);
int sqlite3PagerSetSpillsize(Pager*, int);
void sqlite3PagerSetMmapLimit(Pager *, sqlite3_int64);
void sqlite3PagerShrink(Pager*);
void sqlite3PagerSetFlags(Pager*,unsigned);
int sqlite3PagerLockingMode(Pager *, int);
int sqlite3PagerSetJournalMode(Pager *, int);
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
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







-
+

-
+











-
+


-
-
+
+





+
+
+
+
+
+
+
+
















-
+









-
-
-
-
-







int sqlite3PagerPageRefcount(DbPage*);
void *sqlite3PagerGetData(DbPage *); 
void *sqlite3PagerGetExtra(DbPage *); 

/* Functions used to manage pager transactions and savepoints. */
void sqlite3PagerPagecount(Pager*, int*);
int sqlite3PagerBegin(Pager*, int exFlag, int);
int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, int);
int sqlite3PagerCommitPhaseOne(Pager*,const char *zSuper, int);
int sqlite3PagerExclusiveLock(Pager*, DbPage *pPage1, Pgno*);
int sqlite3PagerSync(Pager *pPager, const char *zMaster);
int sqlite3PagerSync(Pager *pPager, const char *zSuper);
int sqlite3PagerCommitPhaseTwo(Pager*);
int sqlite3PagerRollback(Pager*);
int sqlite3PagerOpenSavepoint(Pager *pPager, int n);
int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint);
int sqlite3PagerSharedLock(Pager *pPager);


#ifndef SQLITE_OMIT_WAL
  int sqlite3PagerCheckpoint(Pager *pPager, sqlite3*, int, int*, int*);
  int sqlite3PagerWalSupported(Pager *pPager);
  int sqlite3PagerWalCallback(Pager *pPager);
  int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
  int sqlite3PagerOpenWal(Pager *pPager, int, int *pisOpen);
  int sqlite3PagerCloseWal(Pager *pPager, sqlite3*);
# ifdef SQLITE_ENABLE_SNAPSHOT
  int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot);
  int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot);
  int sqlite3PagerSnapshotGet(Pager*, sqlite3_snapshot **ppSnapshot);
  int sqlite3PagerSnapshotOpen(Pager*, sqlite3_snapshot *pSnapshot);
  int sqlite3PagerSnapshotRecover(Pager *pPager);
  int sqlite3PagerSnapshotCheck(Pager *pPager, sqlite3_snapshot *pSnapshot);
  void sqlite3PagerSnapshotUnlock(Pager *pPager);
# endif
#endif

#if !defined(SQLITE_OMIT_WAL) && defined(SQLITE_ENABLE_SETLK_TIMEOUT)
  int sqlite3PagerWalWriteLock(Pager*, int);
  void sqlite3PagerWalDb(Pager*, sqlite3*);
#else
# define sqlite3PagerWalWriteLock(y,z) SQLITE_OK
# define sqlite3PagerWalDb(x,y)
#endif

#ifdef SQLITE_DIRECT_OVERFLOW_READ
  int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno);
#endif

#ifdef SQLITE_ENABLE_ZIPVFS
  int sqlite3PagerWalFramesize(Pager *pPager);
#endif

/* Functions used to query pager state and configuration. */
u8 sqlite3PagerIsreadonly(Pager*);
u32 sqlite3PagerDataVersion(Pager*);
#ifdef SQLITE_DEBUG
  int sqlite3PagerRefcount(Pager*);
#endif
int sqlite3PagerMemUsed(Pager*);
const char *sqlite3PagerFilename(Pager*, int);
const char *sqlite3PagerFilename(const Pager*, int);
sqlite3_vfs *sqlite3PagerVfs(Pager*);
sqlite3_file *sqlite3PagerFile(Pager*);
sqlite3_file *sqlite3PagerJrnlFile(Pager*);
const char *sqlite3PagerJournalname(Pager*);
void *sqlite3PagerTempSpace(Pager*);
int sqlite3PagerIsMemdb(Pager*);
void sqlite3PagerCacheStat(Pager *, int, int, int *);
void sqlite3PagerClearCache(Pager*);
int sqlite3SectorSize(sqlite3_file *);
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
void sqlite3PagerResetLockTimeout(Pager *pPager);
#else
# define sqlite3PagerResetLockTimeout(X)
#endif

/* Functions used to truncate the database file. */
void sqlite3PagerTruncateImage(Pager*,Pgno);

void sqlite3PagerRekey(DbPage*, Pgno, u16);

#ifndef SQLITE_OMIT_CONCURRENT
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







-
-
-
-








#if defined(SQLITE_DEBUG) || !defined(SQLITE_OMIT_CONCURRENT)
int sqlite3PagerIswriteable(DbPage*);
#endif

int sqlite3PagerWalInfo(Pager*, u32 *pnPrior, u32 *pnFrame);

#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_WAL)
void *sqlite3PagerCodec(DbPage *);
#endif

/* Functions to support testing and debugging. */
#if !defined(NDEBUG) || defined(SQLITE_TEST)
  Pgno sqlite3PagerPagenumber(DbPage*);
#endif
#ifdef SQLITE_TEST
  int *sqlite3PagerStats(Pager*);
  void sqlite3PagerRefdump(Pager*);

Changes to src/parse.y.


1
2

3
4
5
6
7
8
9
10
11
12
13
14
15








16

17
18
19
20
21
22
23
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
+

-
+









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

+







%include {
/*
** 2001 September 15
** 2001-09-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 contains SQLite's grammar for SQL.  Process this file
** using the lemon parser generator to generate C code that runs
** the parser.  Lemon will also generate a header file containing
** numeric codes for all of the tokens.
** This file contains SQLite's SQL parser.
**
** The canonical source code to this file ("parse.y") is a Lemon grammar 
** file that specifies the input grammar and actions to take while parsing.
** That input file is processed by Lemon to generate a C-language 
** implementation of a parser for the given grammer.  You might be reading
** this comment as part of the translated C-code.  Edits should be made
** to the original parse.y sources.
*/
}

// All token codes are small integers with #defines that begin with "TK_"
%token_prefix TK_

// The type of the data attached to each token is Token.  This is also the
// default type for non-terminals.
//
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
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







+

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










-
+







struct FrameBound     { int eType; Expr *pExpr; };

/*
** Disable lookaside memory allocation for objects that might be
** shared across database connections.
*/
static void disableLookaside(Parse *pParse){
  sqlite3 *db = pParse->db;
  pParse->disableLookaside++;
  DisableLookaside;
}
  pParse->db->lookaside.bDisable++;
}

#if !defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) \
 && defined(SQLITE_UDL_CAPABLE_PARSER)
/*
** Issue an error message if an ORDER BY or LIMIT clause occurs on an
** UPDATE or DELETE statement.
*/
static void updateDeleteLimitError(
  Parse *pParse,
  ExprList *pOrderBy,
  Expr *pLimit
){
  if( pOrderBy ){
    sqlite3ErrorMsg(pParse, "syntax error near \"ORDER BY\"");
  }else{
    sqlite3ErrorMsg(pParse, "syntax error near \"LIMIT\"");
  }
  sqlite3ExprListDelete(pParse->db, pOrderBy);
  sqlite3ExprDelete(pParse->db, pLimit);
}
#endif /* SQLITE_ENABLE_UPDATE_DELETE_LIMIT */

} // end %include

// Input is a single SQL command
input ::= cmdlist.
cmdlist ::= cmdlist ecmd.
cmdlist ::= ecmd.
ecmd ::= SEMI.
ecmd ::= cmdx SEMI.
%ifndef SQLITE_OMIT_EXPLAIN
ecmd ::= explain cmdx.
ecmd ::= explain cmdx SEMI.       {NEVER-REDUCE}
explain ::= EXPLAIN.              { pParse->explain = 1; }
explain ::= EXPLAIN QUERY PLAN.   { pParse->explain = 2; }
%endif  SQLITE_OMIT_EXPLAIN
cmdx ::= cmd.           { sqlite3FinishCoding(pParse); }

///////////////////// Begin and end transactions. ////////////////////////////
//
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
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







-
+


-
+






-
-
-
+
+
+
+
+
+






+
+
+
+
+
+
+
+



-
+





-
+
-
-

















+





+

+
+
+
+







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). {
create_table_args ::= LP columnlist conslist_opt(X) RP(E) table_option_set(F). {
  sqlite3EndTable(pParse,&X,&E,F,0);
}
create_table_args ::= AS select(S). {
  sqlite3EndTable(pParse,0,0,0,S);
  sqlite3SelectDelete(pParse->db, S);
}
%type table_options {int}
table_options(A) ::= .    {A = 0;}
table_options(A) ::= WITHOUT nm(X). {
%type table_option_set {u32}
%type table_option {u32}
table_option_set(A) ::= .    {A = 0;}
table_option_set(A) ::= table_option(A).
table_option_set(A) ::= table_option_set(X) COMMA table_option(Y). {A = X|Y;}
table_option(A) ::= WITHOUT nm(X). {
  if( X.n==5 && sqlite3_strnicmp(X.z,"rowid",5)==0 ){
    A = TF_WithoutRowid | TF_NoVisibleRowid;
  }else{
    A = 0;
    sqlite3ErrorMsg(pParse, "unknown table option: %.*s", X.n, X.z);
  }
}
table_option(A) ::= nm(X). {
  if( X.n==6 && sqlite3_strnicmp(X.z,"strict",6)==0 ){
    A = TF_Strict;
  }else{
    A = 0;
    sqlite3ErrorMsg(pParse, "unknown table option: %.*s", X.n, X.z);
  }
}
columnlist ::= columnlist COMMA columnname carglist.
columnlist ::= columnname carglist.
columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,&A,&Y);}
columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,A,Y);}

// Declare some tokens early in order to influence their values, to 
// improve performance and reduce the executable size.  The goal here is
// to get the "jump" operations in ISNULL through ESCAPE to have numeric
// values that are early enough so that all jump operations are clustered
// at the beginning, but also so that the comparison tokens NE through GE
// at the beginning.
// are as large as possible so that they are near to FUNCTION, which is a
// token synthesized by addopcodes.tcl.
//
%token ABORT ACTION AFTER ANALYZE ASC ATTACH BEFORE BEGIN BY CASCADE CAST.
%token CONFLICT DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL.
%token OR AND NOT IS MATCH LIKE_KW BETWEEN IN ISNULL NOTNULL NE EQ.
%token GT LE LT GE ESCAPE.

// The following directive causes tokens ABORT, AFTER, ASC, etc. to
// fallback to ID if they will not parse as their original value.
// This obviates the need for the "id" nonterminal.
//
%fallback ID
  ABORT ACTION AFTER ANALYZE ASC ATTACH BEFORE BEGIN BY CASCADE CAST COLUMNKW
  CONFLICT DATABASE DEFERRED DESC DETACH DO
  EACH END EXCLUSIVE EXPLAIN FAIL FOR
  IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH NO PLAN
  QUERY KEY OF OFFSET PRAGMA RAISE RECURSIVE RELEASE REPLACE RESTRICT ROW ROWS
  ROLLBACK SAVEPOINT TEMP TRIGGER VACUUM VIEW VIRTUAL WITH WITHOUT
  NULLS FIRST LAST
%ifdef SQLITE_OMIT_COMPOUND_SELECT
  EXCEPT INTERSECT UNION
%endif SQLITE_OMIT_COMPOUND_SELECT
%ifndef SQLITE_OMIT_WINDOWFUNC
  CURRENT FOLLOWING PARTITION PRECEDING RANGE UNBOUNDED
  EXCLUDE GROUPS OTHERS TIES
%endif SQLITE_OMIT_WINDOWFUNC
%ifndef SQLITE_OMIT_GENERATED_COLUMNS
  GENERATED ALWAYS
%endif
  MATERIALIZED
  REINDEX RENAME CTIME_KW IF
  .
%wildcard ANY.

// Define operator precedence early so that this is the first occurrence
// of the operator tokens in the grammer.  Keeping the operators together
// causes them to be assigned integer values that are close together,
255
256
257
258
259
260
261
262

263
264
265
266
267
268
269
298
299
300
301
302
303
304

305
306
307
308
309
310
311
312







-
+







%right NOT.
%left IS MATCH LIKE_KW BETWEEN IN ISNULL NOTNULL NE EQ.
%left GT LE LT GE.
%right ESCAPE.
%left BITAND BITOR LSHIFT RSHIFT.
%left PLUS MINUS.
%left STAR SLASH REM.
%left CONCAT.
%left CONCAT PTR.
%left COLLATE.
%right BITNOT.
%nonassoc ON.

// An IDENTIFIER can be a generic identifier, or one of several
// keywords.  Any non-standard keyword can also be an identifier.
//
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
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







+
+
+
+







-
-
+
+


-
-
-
+
+
+

-
+

-
+

















-
+




+
+
+
+







// post-processing, if needed.
//
%type scanpt {const char*}
scanpt(A) ::= . {
  assert( yyLookahead!=YYNOCODE );
  A = yyLookaheadToken.z;
}
scantok(A) ::= . {
  assert( yyLookahead!=YYNOCODE );
  A = yyLookaheadToken;
}

// "carglist" is a list of additional constraints that come after the
// column name and column type in a CREATE TABLE statement.
//
carglist ::= carglist ccons.
carglist ::= .
ccons ::= CONSTRAINT nm(X).           {pParse->constraintName = X;}
ccons ::= DEFAULT scanpt(A) term(X) scanpt(Z).
                            {sqlite3AddDefaultValue(pParse,X,A,Z);}
ccons ::= DEFAULT scantok(A) term(X).
                            {sqlite3AddDefaultValue(pParse,X,A.z,&A.z[A.n]);}
ccons ::= DEFAULT LP(A) expr(X) RP(Z).
                            {sqlite3AddDefaultValue(pParse,X,A.z+1,Z.z);}
ccons ::= DEFAULT PLUS(A) term(X) scanpt(Z).
                            {sqlite3AddDefaultValue(pParse,X,A.z,Z);}
ccons ::= DEFAULT MINUS(A) term(X) scanpt(Z).      {
ccons ::= DEFAULT PLUS(A) scantok(Z) term(X).
                            {sqlite3AddDefaultValue(pParse,X,A.z,&Z.z[Z.n]);}
ccons ::= DEFAULT MINUS(A) scantok(Z) term(X). {
  Expr *p = sqlite3PExpr(pParse, TK_UMINUS, X, 0);
  sqlite3AddDefaultValue(pParse,p,A.z,Z);
  sqlite3AddDefaultValue(pParse,p,A.z,&Z.z[Z.n]);
}
ccons ::= DEFAULT scanpt id(X).       {
ccons ::= DEFAULT scantok id(X).       {
  Expr *p = tokenExpr(pParse, TK_STRING, X);
  if( p ){
    sqlite3ExprIdToTrueFalse(p);
    testcase( p->op==TK_TRUEFALSE && sqlite3ExprTruthValue(p) );
  }
    sqlite3AddDefaultValue(pParse,p,X.z,X.z+X.n);
}

// In addition to the type name, we also care about the primary key and
// UNIQUE constraints.
//
ccons ::= NULL onconf.
ccons ::= NOT NULL onconf(R).    {sqlite3AddNotNull(pParse, R);}
ccons ::= PRIMARY KEY sortorder(Z) onconf(R) autoinc(I).
                                 {sqlite3AddPrimaryKey(pParse,0,R,I,Z);}
ccons ::= UNIQUE onconf(R).      {sqlite3CreateIndex(pParse,0,0,0,0,R,0,0,0,0,
                                   SQLITE_IDXTYPE_UNIQUE);}
ccons ::= CHECK LP expr(X) RP.   {sqlite3AddCheckConstraint(pParse,X);}
ccons ::= CHECK LP(A) expr(X) RP(B).  {sqlite3AddCheckConstraint(pParse,X,A.z,B.z);}
ccons ::= REFERENCES nm(T) eidlist_opt(TA) refargs(R).
                                 {sqlite3CreateForeignKey(pParse,0,&T,TA,R);}
ccons ::= defer_subclause(D).    {sqlite3DeferForeignKey(pParse,D);}
ccons ::= COLLATE ids(C).        {sqlite3AddCollateType(pParse, &C);}
ccons ::= GENERATED ALWAYS AS generated.
ccons ::= AS generated.
generated ::= LP expr(E) RP.          {sqlite3AddGenerated(pParse,E,0);}
generated ::= LP expr(E) RP ID(TYPE). {sqlite3AddGenerated(pParse,E,&TYPE);}

// The optional AUTOINCREMENT keyword
%type autoinc {int}
autoinc(X) ::= .          {X = 0;}
autoinc(X) ::= AUTOINCR.  {X = 1;}

// The next group of rules parses the arguments to a REFERENCES clause
398
399
400
401
402
403
404
405
406


407
408
409
410
411
412
413
449
450
451
452
453
454
455


456
457
458
459
460
461
462
463
464







-
-
+
+







tconscomma ::= .
tcons ::= CONSTRAINT nm(X).      {pParse->constraintName = X;}
tcons ::= PRIMARY KEY LP sortlist(X) autoinc(I) RP onconf(R).
                                 {sqlite3AddPrimaryKey(pParse,X,R,I,0);}
tcons ::= UNIQUE LP sortlist(X) RP onconf(R).
                                 {sqlite3CreateIndex(pParse,0,0,0,X,R,0,0,0,0,
                                       SQLITE_IDXTYPE_UNIQUE);}
tcons ::= CHECK LP expr(E) RP onconf.
                                 {sqlite3AddCheckConstraint(pParse,E);}
tcons ::= CHECK LP(A) expr(E) RP(B) onconf.
                                 {sqlite3AddCheckConstraint(pParse,E,A.z,B.z);}
tcons ::= FOREIGN KEY LP eidlist(FA) RP
          REFERENCES nm(T) eidlist_opt(TA) refargs(R) defer_subclause_opt(D). {
    sqlite3CreateForeignKey(pParse, FA, &T, TA, R);
    sqlite3DeferForeignKey(pParse, D);
}
%type defer_subclause_opt {int}
defer_subclause_opt(A) ::= .                    {A = 0;}
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
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







-
+


















+

-
-
+
+
-
+


+
+
+
+
+
+
+
+
+
+









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



















-
+







  sqlite3DropTable(pParse, X, 1, E);
}
%endif  SQLITE_OMIT_VIEW

//////////////////////// The SELECT statement /////////////////////////////////
//
cmd ::= select(X).  {
  SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0};
  SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0, 0};
  sqlite3Select(pParse, X, &dest);
  sqlite3SelectDelete(pParse->db, X);
}

%type select {Select*}
%destructor select {sqlite3SelectDelete(pParse->db, $$);}
%type selectnowith {Select*}
%destructor selectnowith {sqlite3SelectDelete(pParse->db, $$);}
%type oneselect {Select*}
%destructor oneselect {sqlite3SelectDelete(pParse->db, $$);}

%include {
  /*
  ** For a compound SELECT statement, make sure p->pPrior->pNext==p for
  ** all elements in the list.  And make sure list length does not exceed
  ** SQLITE_LIMIT_COMPOUND_SELECT.
  */
  static void parserDoubleLinkSelect(Parse *pParse, Select *p){
    assert( p!=0 );
    if( p->pPrior ){
      Select *pNext = 0, *pLoop;
      int mxSelect, cnt = 0;
      Select *pNext = 0, *pLoop = p;
      int mxSelect, cnt = 1;
      for(pLoop=p; pLoop; pNext=pLoop, pLoop=pLoop->pPrior, cnt++){
      while(1){
        pLoop->pNext = pNext;
        pLoop->selFlags |= SF_Compound;
        pNext = pLoop;
        pLoop = pLoop->pPrior;
        if( pLoop==0 ) break;
        cnt++;        
        if( pLoop->pOrderBy || pLoop->pLimit ){
          sqlite3ErrorMsg(pParse,"%s clause should come after %s not before",
             pLoop->pOrderBy!=0 ? "ORDER BY" : "LIMIT",
             sqlite3SelectOpName(pNext->op));
          break;
        }
      }
      if( (p->selFlags & SF_MultiValue)==0 && 
        (mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT])>0 &&
        cnt>mxSelect
      ){
        sqlite3ErrorMsg(pParse, "too many terms in compound SELECT");
      }
    }
  }
}

%ifndef SQLITE_OMIT_CTE

  /* Attach a With object describing the WITH clause to a Select
  ** object describing the query for which the WITH clause is a prefix.
select(A) ::= WITH wqlist(W) selectnowith(X). {
  Select *p = X;
  if( p ){
    p->pWith = W;
    parserDoubleLinkSelect(pParse, p);
  }else{
    sqlite3WithDelete(pParse->db, W);
  }
  A = p;
}
  */
  static Select *attachWithToSelect(Parse *pParse, Select *pSelect, With *pWith){
    if( pSelect ){
      pSelect->pWith = pWith;
      parserDoubleLinkSelect(pParse, pSelect);
    }else{
      sqlite3WithDelete(pParse->db, pWith);
    }
    return pSelect;
  }
select(A) ::= WITH RECURSIVE wqlist(W) selectnowith(X). {
  Select *p = X;
  if( p ){
    p->pWith = W;
    parserDoubleLinkSelect(pParse, p);
  }else{
    sqlite3WithDelete(pParse->db, W);
  }
}
  A = p;
}

%ifndef SQLITE_OMIT_CTE
select(A) ::= WITH wqlist(W) selectnowith(X). {A = attachWithToSelect(pParse,X,W);}
select(A) ::= WITH RECURSIVE wqlist(W) selectnowith(X).
                                              {A = attachWithToSelect(pParse,X,W);}
%endif /* SQLITE_OMIT_CTE */
select(A) ::= selectnowith(X). {
  Select *p = X;
  if( p ){
    parserDoubleLinkSelect(pParse, p);
  }
  A = p; /*A-overwrites-X*/
}

selectnowith(A) ::= oneselect(A).
%ifndef SQLITE_OMIT_COMPOUND_SELECT
selectnowith(A) ::= selectnowith(A) multiselect_op(Y) oneselect(Z).  {
  Select *pRhs = Z;
  Select *pLhs = A;
  if( pRhs && pRhs->pPrior ){
    SrcList *pFrom;
    Token x;
    x.n = 0;
    parserDoubleLinkSelect(pParse, pRhs);
    pFrom = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&x,pRhs,0,0);
    pFrom = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&x,pRhs,0);
    pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0);
  }
  if( pRhs ){
    pRhs->op = (u8)Y;
    pRhs->pPrior = pLhs;
    if( ALWAYS(pLhs) ) pLhs->selFlags &= ~SF_MultiValue;
    pRhs->selFlags &= ~SF_MultiValue;
612
613
614
615
616
617
618
619

620
621
622
623
624
625
626
670
671
672
673
674
675
676

677
678
679
680
681
682
683
684







-
+







}
selcollist(A) ::= sclp(A) scanpt STAR. {
  Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0);
  A = sqlite3ExprListAppend(pParse, A, p);
}
selcollist(A) ::= sclp(A) scanpt nm(X) DOT STAR. {
  Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0);
  Expr *pLeft = sqlite3ExprAlloc(pParse->db, TK_ID, &X, 1);
  Expr *pLeft = tokenExpr(pParse, TK_ID, X);
  Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight);
  A = sqlite3ExprListAppend(pParse,A, pDot);
}

// An option "AS <id>" phrase that can follow one of the expressions that
// define the result set, or one of the tables in the FROM clause.
//
635
636
637
638
639
640
641
642

643
644
645

646
647
648
649
650
651
652
653
654
655
656
657





658
659
660

661
662

663
664
665
666

667
668

669
670

671
672

673
674
675

676
677
678


679
680
681



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

695
696

697
698
699
700
701
702
703
704
705
706
707
708

709
710
711
712

713
714
715
716
717
718
719

720
721

722
723

724
725
726
727

728
729
730
731
732
733
734
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
775
776
777
778

779
780

781
782

783
784
785
786

787
788
789
790
791
792
793
794







-
+


-
+









-
-
-
+
+
+
+
+


-
+
-
-
+



-
+
-
-
+

-
+
-
-
+


-
+

-
-
+
+



+
+
+












-
+

-
+











-
+



-
+






-
+

-
+

-
+



-
+







%type stl_prefix {SrcList*}
%destructor stl_prefix {sqlite3SrcListDelete(pParse->db, $$);}
%type from {SrcList*}
%destructor from {sqlite3SrcListDelete(pParse->db, $$);}

// A complete FROM clause.
//
from(A) ::= .                {A = sqlite3DbMallocZero(pParse->db, sizeof(*A));}
from(A) ::= .                {A = 0;}
from(A) ::= FROM seltablist(X). {
  A = X;
  sqlite3SrcListShiftJoinType(A);
  sqlite3SrcListShiftJoinType(pParse,A);
}

// "seltablist" is a "Select Table List" - the content of the FROM clause
// in a SELECT statement.  "stl_prefix" is a prefix of this list.
//
stl_prefix(A) ::= seltablist(A) joinop(Y).    {
   if( ALWAYS(A && A->nSrc>0) ) A->a[A->nSrc-1].fg.jointype = (u8)Y;
}
stl_prefix(A) ::= .                           {A = 0;}
seltablist(A) ::= stl_prefix(A) nm(Y) dbnm(D) as(Z) indexed_opt(I)
                  on_opt(N) using_opt(U). {
  A = sqlite3SrcListAppendFromTerm(pParse,A,&Y,&D,&Z,0,N,U);
seltablist(A) ::= stl_prefix(A) nm(Y) dbnm(D) as(Z) on_using(N). {
  A = sqlite3SrcListAppendFromTerm(pParse,A,&Y,&D,&Z,0,&N);
}
seltablist(A) ::= stl_prefix(A) nm(Y) dbnm(D) as(Z) indexed_by(I) on_using(N). {
  A = sqlite3SrcListAppendFromTerm(pParse,A,&Y,&D,&Z,0,&N);
  sqlite3SrcListIndexedBy(pParse, A, &I);
}
seltablist(A) ::= stl_prefix(A) nm(Y) dbnm(D) LP exprlist(E) RP as(Z)
seltablist(A) ::= stl_prefix(A) nm(Y) dbnm(D) LP exprlist(E) RP as(Z) on_using(N). {
                  on_opt(N) using_opt(U). {
  A = sqlite3SrcListAppendFromTerm(pParse,A,&Y,&D,&Z,0,N,U);
  A = sqlite3SrcListAppendFromTerm(pParse,A,&Y,&D,&Z,0,&N);
  sqlite3SrcListFuncArgs(pParse, A, E);
}
%ifndef SQLITE_OMIT_SUBQUERY
  seltablist(A) ::= stl_prefix(A) LP select(S) RP
  seltablist(A) ::= stl_prefix(A) LP select(S) RP as(Z) on_using(N). {
                    as(Z) on_opt(N) using_opt(U). {
    A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,S,N,U);
    A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,S,&N);
  }
  seltablist(A) ::= stl_prefix(A) LP seltablist(F) RP
  seltablist(A) ::= stl_prefix(A) LP seltablist(F) RP as(Z) on_using(N). {
                    as(Z) on_opt(N) using_opt(U). {
    if( A==0 && Z.n==0 && N==0 && U==0 ){
    if( A==0 && Z.n==0 && N.pOn==0 && N.pUsing==0 ){
      A = F;
    }else if( F->nSrc==1 ){
      A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,0,N,U);
      A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,0,&N);
      if( A ){
        struct SrcList_item *pNew = &A->a[A->nSrc-1];
        struct SrcList_item *pOld = F->a;
        SrcItem *pNew = &A->a[A->nSrc-1];
        SrcItem *pOld = F->a;
        pNew->zName = pOld->zName;
        pNew->zDatabase = pOld->zDatabase;
        pNew->pSelect = pOld->pSelect;
        if( pNew->pSelect && (pNew->pSelect->selFlags & SF_NestedFrom)!=0 ){
          pNew->fg.isNestedFrom = 1;
        }
        if( pOld->fg.isTabFunc ){
          pNew->u1.pFuncArg = pOld->u1.pFuncArg;
          pOld->u1.pFuncArg = 0;
          pOld->fg.isTabFunc = 0;
          pNew->fg.isTabFunc = 1;
        }
        pOld->zName = pOld->zDatabase = 0;
        pOld->pSelect = 0;
      }
      sqlite3SrcListDelete(pParse->db, F);
    }else{
      Select *pSubquery;
      sqlite3SrcListShiftJoinType(F);
      sqlite3SrcListShiftJoinType(pParse,F);
      pSubquery = sqlite3SelectNew(pParse,0,F,0,0,0,0,SF_NestedFrom,0);
      A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,pSubquery,N,U);
      A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,pSubquery,&N);
    }
  }
%endif  SQLITE_OMIT_SUBQUERY

%type dbnm {Token}
dbnm(A) ::= .          {A.z=0; A.n=0;}
dbnm(A) ::= DOT nm(X). {A = X;}

%type fullname {SrcList*}
%destructor fullname {sqlite3SrcListDelete(pParse->db, $$);}
fullname(A) ::= nm(X).  {
  A = sqlite3SrcListAppend(pParse->db,0,&X,0);
  A = sqlite3SrcListAppend(pParse,0,&X,0);
  if( IN_RENAME_OBJECT && A ) sqlite3RenameTokenMap(pParse, A->a[0].zName, &X);
}
fullname(A) ::= nm(X) DOT nm(Y). {
  A = sqlite3SrcListAppend(pParse->db,0,&X,&Y);
  A = sqlite3SrcListAppend(pParse,0,&X,&Y);
  if( IN_RENAME_OBJECT && A ) sqlite3RenameTokenMap(pParse, A->a[0].zName, &Y);
}

%type xfullname {SrcList*}
%destructor xfullname {sqlite3SrcListDelete(pParse->db, $$);}
xfullname(A) ::= nm(X).  
   {A = sqlite3SrcListAppend(pParse->db,0,&X,0); /*A-overwrites-X*/}
   {A = sqlite3SrcListAppend(pParse,0,&X,0); /*A-overwrites-X*/}
xfullname(A) ::= nm(X) DOT nm(Y).  
   {A = sqlite3SrcListAppend(pParse->db,0,&X,&Y); /*A-overwrites-X*/}
   {A = sqlite3SrcListAppend(pParse,0,&X,&Y); /*A-overwrites-X*/}
xfullname(A) ::= nm(X) DOT nm(Y) AS nm(Z).  {
   A = sqlite3SrcListAppend(pParse->db,0,&X,&Y); /*A-overwrites-X*/
   A = sqlite3SrcListAppend(pParse,0,&X,&Y); /*A-overwrites-X*/
   if( A ) A->a[0].zAlias = sqlite3NameFromToken(pParse->db, &Z);
}
xfullname(A) ::= nm(X) AS nm(Z). {  
   A = sqlite3SrcListAppend(pParse->db,0,&X,0); /*A-overwrites-X*/
   A = sqlite3SrcListAppend(pParse,0,&X,0); /*A-overwrites-X*/
   if( A ) A->a[0].zAlias = sqlite3NameFromToken(pParse->db, &Z);
}

%type joinop {int}
joinop(X) ::= COMMA|JOIN.              { X = JT_INNER; }
joinop(X) ::= JOIN_KW(A) JOIN.
                  {X = sqlite3JoinType(pParse,&A,0,0);  /*X-overwrites-A*/}
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
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







-
+


-
-
-
-
+
+
+
+
+












+

-
-
+
+
+
-
-
-
-
-
-













-
+

-
+

-
+

-
+








+
+
+
+
+







// the beginning of an ON CONFLICT clause, or the beginning of an ON
// clause associated with the JOIN.  The conflict is resolved in favor
// of the JOIN.  If an ON CONFLICT clause is intended, insert a dummy
// WHERE clause in between, like this:
//
//      INSERT INTO tab SELECT * FROM aaa JOIN bbb WHERE true ON CONFLICT ...
//
// The [AND] and [OR] precedence marks in the rules for on_opt cause the
// The [AND] and [OR] precedence marks in the rules for on_using cause the
// ON in this context to always be interpreted as belonging to the JOIN.
//
%type on_opt {Expr*}
%destructor on_opt {sqlite3ExprDelete(pParse->db, $$);}
on_opt(N) ::= ON expr(E).  {N = E;}
on_opt(N) ::= .     [OR]   {N = 0;}
%type on_using {OnOrUsing}
//%destructor on_using {sqlite3ClearOnOrUsing(pParse->db, &$$);}
on_using(N) ::= ON expr(E).            {N.pOn = E; N.pUsing = 0;}
on_using(N) ::= USING LP idlist(L) RP. {N.pOn = 0; N.pUsing = L;}
on_using(N) ::= .                 [OR] {N.pOn = 0; N.pUsing = 0;}

// Note that this block abuses the Token type just a little. If there is
// no "INDEXED BY" clause, the returned token is empty (z==0 && n==0). If
// there is an INDEXED BY clause, then the token is populated as per normal,
// with z pointing to the token data and n containing the number of bytes
// in the token.
//
// If there is a "NOT INDEXED" clause, then (z==0 && n==1), which is 
// normally illegal. The sqlite3SrcListIndexedBy() function 
// recognizes and interprets this as a special case.
//
%type indexed_opt {Token}
%type indexed_by  {Token}
indexed_opt(A) ::= .                 {A.z=0; A.n=0;}
indexed_opt(A) ::= INDEXED BY nm(X). {A = X;}
indexed_opt(A) ::= NOT INDEXED.      {A.z=0; A.n=1;}
indexed_opt(A) ::= indexed_by(A).
indexed_by(A)  ::= INDEXED BY nm(X). {A = X;}
indexed_by(A)  ::= NOT INDEXED.      {A.z=0; A.n=1;}

%type using_opt {IdList*}
%destructor using_opt {sqlite3IdListDelete(pParse->db, $$);}
using_opt(U) ::= USING LP idlist(L) RP.  {U = L;}
using_opt(U) ::= .                        {U = 0;}


%type orderby_opt {ExprList*}
%destructor orderby_opt {sqlite3ExprListDelete(pParse->db, $$);}

// the sortlist non-terminal stores a list of expression where each
// expression is optionally followed by ASC or DESC to indicate the
// sort order.
//
%type sortlist {ExprList*}
%destructor sortlist {sqlite3ExprListDelete(pParse->db, $$);}

orderby_opt(A) ::= .                          {A = 0;}
orderby_opt(A) ::= ORDER BY sortlist(X).      {A = X;}
sortlist(A) ::= sortlist(A) COMMA expr(Y) sortorder(Z). {
sortlist(A) ::= sortlist(A) COMMA expr(Y) sortorder(Z) nulls(X). {
  A = sqlite3ExprListAppend(pParse,A,Y);
  sqlite3ExprListSetSortOrder(A,Z);
  sqlite3ExprListSetSortOrder(A,Z,X);
}
sortlist(A) ::= expr(Y) sortorder(Z). {
sortlist(A) ::= expr(Y) sortorder(Z) nulls(X). {
  A = sqlite3ExprListAppend(pParse,0,Y); /*A-overwrites-Y*/
  sqlite3ExprListSetSortOrder(A,Z);
  sqlite3ExprListSetSortOrder(A,Z,X);
}

%type sortorder {int}

sortorder(A) ::= ASC.           {A = SQLITE_SO_ASC;}
sortorder(A) ::= DESC.          {A = SQLITE_SO_DESC;}
sortorder(A) ::= .              {A = SQLITE_SO_UNDEFINED;}

%type nulls {int}
nulls(A) ::= NULLS FIRST.       {A = SQLITE_SO_ASC;}
nulls(A) ::= NULLS LAST.        {A = SQLITE_SO_DESC;}
nulls(A) ::= .                  {A = SQLITE_SO_UNDEFINED;}

%type groupby_opt {ExprList*}
%destructor groupby_opt {sqlite3ExprListDelete(pParse->db, $$);}
groupby_opt(A) ::= .                      {A = 0;}
groupby_opt(A) ::= GROUP BY nexprlist(X). {A = X;}

%type having_opt {Expr*}
%destructor having_opt {sqlite3ExprDelete(pParse->db, $$);}
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
895
896
897
898
899
900
901


902
903
904
905
906
907
908
909
910
911
912
913
914

915


916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937



938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963

964



965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992







-
-
+
+


+
+
+
+
+
+
+


-
+
-
-
+







+
+



+
+
+
+
+
+



-
-
-
+
+
+

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

+
+
+
+
+
+
+


-
+
-
-
-
+
+


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



+
+







limit_opt(A) ::= LIMIT expr(X) OFFSET expr(Y). 
                         {A = sqlite3PExpr(pParse,TK_LIMIT,X,Y);}
limit_opt(A) ::= LIMIT expr(X) COMMA expr(Y). 
                         {A = sqlite3PExpr(pParse,TK_LIMIT,Y,X);}

/////////////////////////// The DELETE statement /////////////////////////////
//
%ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
cmd ::= with DELETE FROM xfullname(X) indexed_opt(I) where_opt(W) 
%if SQLITE_ENABLE_UPDATE_DELETE_LIMIT || SQLITE_UDL_CAPABLE_PARSER
cmd ::= with DELETE FROM xfullname(X) indexed_opt(I) where_opt_ret(W)
        orderby_opt(O) limit_opt(L). {
  sqlite3SrcListIndexedBy(pParse, X, &I);
#ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
  if( O || L ){
    updateDeleteLimitError(pParse,O,L);
    O = 0;
    L = 0;
  }
#endif
  sqlite3DeleteFrom(pParse,X,W,O,L);
}
%endif
%else
%ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
cmd ::= with DELETE FROM xfullname(X) indexed_opt(I) where_opt(W). {
cmd ::= with DELETE FROM xfullname(X) indexed_opt(I) where_opt_ret(W). {
  sqlite3SrcListIndexedBy(pParse, X, &I);
  sqlite3DeleteFrom(pParse,X,W,0,0);
}
%endif

%type where_opt {Expr*}
%destructor where_opt {sqlite3ExprDelete(pParse->db, $$);}
%type where_opt_ret {Expr*}
%destructor where_opt_ret {sqlite3ExprDelete(pParse->db, $$);}

where_opt(A) ::= .                    {A = 0;}
where_opt(A) ::= WHERE expr(X).       {A = X;}
where_opt_ret(A) ::= .                                      {A = 0;}
where_opt_ret(A) ::= WHERE expr(X).                         {A = X;}
where_opt_ret(A) ::= RETURNING selcollist(X).               
       {sqlite3AddReturning(pParse,X); A = 0;}
where_opt_ret(A) ::= WHERE expr(X) RETURNING selcollist(Y).
       {sqlite3AddReturning(pParse,Y); A = X;}

////////////////////////// The UPDATE command ////////////////////////////////
//
%ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
cmd ::= with UPDATE orconf(R) xfullname(X) indexed_opt(I) SET setlist(Y)
        where_opt(W) orderby_opt(O) limit_opt(L).  {
%if SQLITE_ENABLE_UPDATE_DELETE_LIMIT || SQLITE_UDL_CAPABLE_PARSER
cmd ::= with UPDATE orconf(R) xfullname(X) indexed_opt(I) SET setlist(Y) from(F)
        where_opt_ret(W) orderby_opt(O) limit_opt(L).  {
  sqlite3SrcListIndexedBy(pParse, X, &I);
  if( F ){
    SrcList *pFromClause = F;
    if( pFromClause->nSrc>1 ){
      Select *pSubquery;
      Token as;
      pSubquery = sqlite3SelectNew(pParse,0,pFromClause,0,0,0,0,SF_NestedFrom,0);
      as.n = 0;
      as.z = 0;
      pFromClause = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&as,pSubquery,0);
    }
    X = sqlite3SrcListAppendList(pParse, X, pFromClause);
  }
  sqlite3ExprListCheckLength(pParse,Y,"set list"); 
#ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
  if( O || L ){
    updateDeleteLimitError(pParse,O,L);
    O = 0;
    L = 0;
  }
#endif
  sqlite3Update(pParse,X,Y,W,R,O,L,0);
}
%endif
%else
%ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
cmd ::= with UPDATE orconf(R) xfullname(X) indexed_opt(I) SET setlist(Y)
        where_opt(W).  {
cmd ::= with UPDATE orconf(R) xfullname(X) indexed_opt(I) SET setlist(Y) from(F)
        where_opt_ret(W). {
  sqlite3SrcListIndexedBy(pParse, X, &I);
  sqlite3ExprListCheckLength(pParse,Y,"set list"); 
  if( F ){
    SrcList *pFromClause = F;
    if( pFromClause->nSrc>1 ){
      Select *pSubquery;
      Token as;
      pSubquery = sqlite3SelectNew(pParse,0,pFromClause,0,0,0,0,SF_NestedFrom,0);
      as.n = 0;
      as.z = 0;
      pFromClause = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&as,pSubquery,0);
    }
    X = sqlite3SrcListAppendList(pParse, X, pFromClause);
  }
  sqlite3Update(pParse,X,Y,W,R,0,0,0);
}
%endif



%type setlist {ExprList*}
%destructor setlist {sqlite3ExprListDelete(pParse->db, $$);}

setlist(A) ::= setlist(A) COMMA nm(X) EQ expr(Y). {
  A = sqlite3ExprListAppend(pParse, A, Y);
  sqlite3ExprListSetName(pParse, A, &X, 1);
896
897
898
899
900
901
902
903

904
905
906
907
908
909
910
911
912
913
914
915

916
917
918
919
920
921
922











923
924
925
926
927
928
929
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







-
+












+

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








////////////////////////// The INSERT command /////////////////////////////////
//
cmd ::= with insert_cmd(R) INTO xfullname(X) idlist_opt(F) select(S)
        upsert(U). {
  sqlite3Insert(pParse, X, S, F, R, U);
}
cmd ::= with insert_cmd(R) INTO xfullname(X) idlist_opt(F) DEFAULT VALUES.
cmd ::= with insert_cmd(R) INTO xfullname(X) idlist_opt(F) DEFAULT VALUES returning.
{
  sqlite3Insert(pParse, X, 0, F, R, 0);
}

%type upsert {Upsert*}

// Because upsert only occurs at the tip end of the INSERT rule for cmd,
// there is never a case where the value of the upsert pointer will not
// be destroyed by the cmd action.  So comment-out the destructor to
// avoid unreachable code.
//%destructor upsert {sqlite3UpsertDelete(pParse->db,$$);}
upsert(A) ::= . { A = 0; }
upsert(A) ::= RETURNING selcollist(X).  { A = 0; sqlite3AddReturning(pParse,X); }
upsert(A) ::= ON CONFLICT LP sortlist(T) RP where_opt(TW)
              DO UPDATE SET setlist(Z) where_opt(W).
              { A = sqlite3UpsertNew(pParse->db,T,TW,Z,W);}
upsert(A) ::= ON CONFLICT LP sortlist(T) RP where_opt(TW) DO NOTHING.
              { A = sqlite3UpsertNew(pParse->db,T,TW,0,0); }
upsert(A) ::= ON CONFLICT DO NOTHING.
              { A = sqlite3UpsertNew(pParse->db,0,0,0,0); }
              DO UPDATE SET setlist(Z) where_opt(W) upsert(N).
              { A = sqlite3UpsertNew(pParse->db,T,TW,Z,W,N);}
upsert(A) ::= ON CONFLICT LP sortlist(T) RP where_opt(TW) DO NOTHING upsert(N).
              { A = sqlite3UpsertNew(pParse->db,T,TW,0,0,N); }
upsert(A) ::= ON CONFLICT DO NOTHING returning.
              { A = sqlite3UpsertNew(pParse->db,0,0,0,0,0); }
upsert(A) ::= ON CONFLICT DO UPDATE SET setlist(Z) where_opt(W) returning.
              { A = sqlite3UpsertNew(pParse->db,0,0,Z,W,0);}

returning ::= RETURNING selcollist(X).  {sqlite3AddReturning(pParse,X);}
returning ::= .

%type insert_cmd {int}
insert_cmd(A) ::= INSERT orconf(R).   {A = R;}
insert_cmd(A) ::= REPLACE.            {A = OE_Replace;}

%type idlist_opt {IdList*}
%destructor idlist_opt {sqlite3IdListDelete(pParse->db, $$);}
943
944
945
946
947
948
949
950

951
952
953
954
955
956
957
958
959

960

961

962
963
964

965

966
967
968
969
970
971

972
973
974

975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994


995
996
997
998
999
1000
1001
1002
1003
1004



1005
1006
1007

1008
1009
1010
1011
1012
1013
1014
1015

1016
1017
1018
1019
1020
1021
1022
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







-
+
-
-
-





-
+

+
-
+

-

+
-
+






+

-
-
+


















-
-
+
+
-
-
-
-



-
-
-
+
+
+


-
+
-







+







%type expr {Expr*}
%destructor expr {sqlite3ExprDelete(pParse->db, $$);}
%type term {Expr*}
%destructor term {sqlite3ExprDelete(pParse->db, $$);}

%include {

  /* Construct a new Expr object from a single identifier.  Use the
  /* Construct a new Expr object from a single token */
  ** new Expr to populate pOut.  Set the span of pOut to be the identifier
  ** that created the expression.
  */
  static Expr *tokenExpr(Parse *pParse, int op, Token t){
    Expr *p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr)+t.n+1);
    if( p ){
      /* memset(p, 0, sizeof(Expr)); */
      p->op = (u8)op;
      p->affinity = 0;
      p->affExpr = 0;
      p->flags = EP_Leaf;
      ExprClearVVAProperties(p);
      p->iAgg = -1;
      /* p->iAgg = -1; // Not required */
      p->pLeft = p->pRight = 0;
      p->x.pList = 0;
      p->pAggInfo = 0;
      memset(&p->x, 0, sizeof(p->x));
      p->y.pTab = 0;
      memset(&p->y, 0, sizeof(p->y));
      p->op2 = 0;
      p->iTable = 0;
      p->iColumn = 0;
      p->u.zToken = (char*)&p[1];
      memcpy(p->u.zToken, t.z, t.n);
      p->u.zToken[t.n] = 0;
      p->w.iOfst = (int)(t.z - pParse->zTail);
      if( sqlite3Isquote(p->u.zToken[0]) ){
        if( p->u.zToken[0]=='"' ) p->flags |= EP_DblQuoted;
        sqlite3Dequote(p->u.zToken);
        sqlite3DequoteExpr(p);
      }
#if SQLITE_MAX_EXPR_DEPTH>0
      p->nHeight = 1;
#endif  
      if( IN_RENAME_OBJECT ){
        return (Expr*)sqlite3RenameTokenMap(pParse, (void*)p, &t);
      }
    }
    return p;
  }

}

expr(A) ::= term(A).
expr(A) ::= LP expr(X) RP. {A = X;}
expr(A) ::= id(X).          {A=tokenExpr(pParse,TK_ID,X); /*A-overwrites-X*/}
expr(A) ::= JOIN_KW(X).     {A=tokenExpr(pParse,TK_ID,X); /*A-overwrites-X*/}
expr(A) ::= nm(X) DOT nm(Y). {
  Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &X, 1);
  Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &Y, 1);
  Expr *temp1 = tokenExpr(pParse,TK_ID,X);
  Expr *temp2 = tokenExpr(pParse,TK_ID,Y);
  if( IN_RENAME_OBJECT ){
    sqlite3RenameTokenMap(pParse, (void*)temp2, &Y);
    sqlite3RenameTokenMap(pParse, (void*)temp1, &X);
  }
  A = sqlite3PExpr(pParse, TK_DOT, temp1, temp2);
}
expr(A) ::= nm(X) DOT nm(Y) DOT nm(Z). {
  Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &X, 1);
  Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &Y, 1);
  Expr *temp3 = sqlite3ExprAlloc(pParse->db, TK_ID, &Z, 1);
  Expr *temp1 = tokenExpr(pParse,TK_ID,X);
  Expr *temp2 = tokenExpr(pParse,TK_ID,Y);
  Expr *temp3 = tokenExpr(pParse,TK_ID,Z);
  Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3);
  if( IN_RENAME_OBJECT ){
    sqlite3RenameTokenMap(pParse, (void*)temp3, &Z);
    sqlite3RenameTokenRemap(pParse, 0, temp1);
    sqlite3RenameTokenMap(pParse, (void*)temp2, &Y);
  }
  A = sqlite3PExpr(pParse, TK_DOT, temp1, temp4);
}
term(A) ::= NULL|FLOAT|BLOB(X). {A=tokenExpr(pParse,@X,X); /*A-overwrites-X*/}
term(A) ::= STRING(X).          {A=tokenExpr(pParse,@X,X); /*A-overwrites-X*/}
term(A) ::= INTEGER(X). {
  A = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &X, 1);
  if( A ) A->w.iOfst = (int)(X.z - pParse->zTail);
}
expr(A) ::= VARIABLE(X).     {
  if( !(X.z[0]=='#' && sqlite3Isdigit(X.z[1])) ){
    u32 n = X.n;
    A = tokenExpr(pParse, TK_VARIABLE, X);
    sqlite3ExprAssignVarNumber(pParse, A, n);
  }else{
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
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







-
+



-
+














+
+
+





-
+







  A = sqlite3ExprFunction(pParse, Y, &X, D);
}
expr(A) ::= id(X) LP STAR RP. {
  A = sqlite3ExprFunction(pParse, 0, &X, 0);
}

%ifndef SQLITE_OMIT_WINDOWFUNC
expr(A) ::= id(X) LP distinct(D) exprlist(Y) RP over_clause(Z). {
expr(A) ::= id(X) LP distinct(D) exprlist(Y) RP filter_over(Z). {
  A = sqlite3ExprFunction(pParse, Y, &X, D);
  sqlite3WindowAttach(pParse, A, Z);
}
expr(A) ::= id(X) LP STAR RP over_clause(Z). {
expr(A) ::= id(X) LP STAR RP filter_over(Z). {
  A = sqlite3ExprFunction(pParse, 0, &X, 0);
  sqlite3WindowAttach(pParse, A, Z);
}
%endif

term(A) ::= CTIME_KW(OP). {
  A = sqlite3ExprFunction(pParse, 0, &OP, 0);
}

expr(A) ::= LP nexprlist(X) COMMA expr(Y) RP. {
  ExprList *pList = sqlite3ExprListAppend(pParse, X, Y);
  A = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
  if( A ){
    A->x.pList = pList;
    if( ALWAYS(pList->nExpr) ){
      A->flags |= pList->a[0].pExpr->flags & EP_Propagate;
    }
  }else{
    sqlite3ExprListDelete(pParse->db, pList);
  }
}

expr(A) ::= expr(A) AND(OP) expr(Y).    {A=sqlite3PExpr(pParse,@OP,A,Y);}
expr(A) ::= expr(A) AND expr(Y).        {A=sqlite3ExprAnd(pParse,A,Y);}
expr(A) ::= expr(A) OR(OP) expr(Y).     {A=sqlite3PExpr(pParse,@OP,A,Y);}
expr(A) ::= expr(A) LT|GT|GE|LE(OP) expr(Y).
                                        {A=sqlite3PExpr(pParse,@OP,A,Y);}
expr(A) ::= expr(A) EQ|NE(OP) expr(Y).  {A=sqlite3PExpr(pParse,@OP,A,Y);}
expr(A) ::= expr(A) BITAND|BITOR|LSHIFT|RSHIFT(OP) expr(Y).
                                        {A=sqlite3PExpr(pParse,@OP,A,Y);}
expr(A) ::= expr(A) PLUS|MINUS(OP) expr(Y).
1140
1141
1142
1143
1144
1145
1146








1147
1148
1149
1150
1151
1152
1153
1154
1155






1156
1157
1158
1159
1160
1161
1162
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
1286
1287







+
+
+
+
+
+
+
+









+
+
+
+
+
+







  A = sqlite3PExpr(pParse,TK_IS,A,Y);
  binaryToUnaryIfNull(pParse, Y, A, TK_ISNULL);
}
expr(A) ::= expr(A) IS NOT expr(Y). {
  A = sqlite3PExpr(pParse,TK_ISNOT,A,Y);
  binaryToUnaryIfNull(pParse, Y, A, TK_NOTNULL);
}
expr(A) ::= expr(A) IS NOT DISTINCT FROM expr(Y).     {
  A = sqlite3PExpr(pParse,TK_IS,A,Y);
  binaryToUnaryIfNull(pParse, Y, A, TK_ISNULL);
}
expr(A) ::= expr(A) IS DISTINCT FROM expr(Y). {
  A = sqlite3PExpr(pParse,TK_ISNOT,A,Y);
  binaryToUnaryIfNull(pParse, Y, A, TK_NOTNULL);
}

expr(A) ::= NOT(B) expr(X).  
              {A = sqlite3PExpr(pParse, @B, X, 0);/*A-overwrites-B*/}
expr(A) ::= BITNOT(B) expr(X).
              {A = sqlite3PExpr(pParse, @B, X, 0);/*A-overwrites-B*/}
expr(A) ::= PLUS|MINUS(B) expr(X). [BITNOT] {
  A = sqlite3PExpr(pParse, @B==TK_PLUS ? TK_UPLUS : TK_UMINUS, X, 0);
  /*A-overwrites-B*/
}

expr(A) ::= expr(B) PTR(C) expr(D). {
  ExprList *pList = sqlite3ExprListAppend(pParse, 0, B);
  pList = sqlite3ExprListAppend(pParse, pList, D);
  A = sqlite3ExprFunction(pParse, pList, &C, 0);
}

%type between_op {int}
between_op(A) ::= BETWEEN.     {A = 0;}
between_op(A) ::= NOT BETWEEN. {A = 1;}
expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
  ExprList *pList = sqlite3ExprListAppend(pParse,0, X);
  pList = sqlite3ExprListAppend(pParse,pList, Y);
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
1303
1304
1305
1306
1307
1308
1309



1310
1311
1312
1313
















1314
1315


1316
1317



1318









1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333


1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348

1349
1350
1351
1352
1353
1354
1355
1356







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

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














-
+







      **
      **      expr1 IN ()
      **      expr1 NOT IN ()
      **
      ** simplify to constants 0 (false) and 1 (true), respectively,
      ** regardless of the value of expr1.
      */
      sqlite3ExprDelete(pParse->db, A);
      A = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[N],1);
    }else if( Y->nExpr==1 ){
      sqlite3ExprUnmapAndDelete(pParse, A);
      A = sqlite3Expr(pParse->db, TK_STRING, N ? "true" : "false");
      if( A ) sqlite3ExprIdToTrueFalse(A);
    }else{
      /* Expressions of the form:
      **
      **      expr1 IN (?1)
      **      expr1 NOT IN (?2)
      **
      ** with exactly one value on the RHS can be simplified to something
      ** like this:
      **
      **      expr1 == ?1
      **      expr1 <> ?2
      **
      ** But, the RHS of the == or <> is marked with the EP_Generic flag
      ** so that it may not contribute to the computation of comparison
      ** affinity or the collating sequence to use for comparison.  Otherwise,
      ** the semantics would be subtly different from IN or NOT IN.
      */
      Expr *pRHS = Y->a[0].pExpr;
      if( Y->nExpr==1 && sqlite3ExprIsConstant(pRHS) && A->op!=TK_VECTOR ){
      Y->a[0].pExpr = 0;
      sqlite3ExprListDelete(pParse->db, Y);
        Y->a[0].pExpr = 0;
        sqlite3ExprListDelete(pParse->db, Y);
      /* pRHS cannot be NULL because a malloc error would have been detected
      ** before now and control would have never reached this point */
      if( ALWAYS(pRHS) ){
        pRHS = sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0);
        pRHS->flags &= ~EP_Collate;
        pRHS->flags |= EP_Generic;
      }
      A = sqlite3PExpr(pParse, N ? TK_NE : TK_EQ, A, pRHS);
    }else{
      A = sqlite3PExpr(pParse, TK_IN, A, 0);
      if( A ){
        A->x.pList = Y;
        sqlite3ExprSetHeightAndFlags(pParse, A);
        A = sqlite3PExpr(pParse, TK_EQ, A, pRHS);
      }else{
        A = sqlite3PExpr(pParse, TK_IN, A, 0);
        if( A==0 ){
          sqlite3ExprListDelete(pParse->db, Y);
        }else if( A->pLeft->op==TK_VECTOR ){
          int nExpr = A->pLeft->x.pList->nExpr;
          Select *pSelectRHS = sqlite3ExprListToValues(pParse, nExpr, Y);
          if( pSelectRHS ){
            parserDoubleLinkSelect(pParse, pSelectRHS);
            sqlite3PExprAddSelect(pParse, A, pSelectRHS);
          }
        }else{
          A->x.pList = Y;
          sqlite3ExprSetHeightAndFlags(pParse, A);
      }else{
        sqlite3ExprListDelete(pParse->db, Y);
        }
      }
      if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0);
    }
  }
  expr(A) ::= LP select(X) RP. {
    A = sqlite3PExpr(pParse, TK_SELECT, 0, 0);
    sqlite3PExprAddSelect(pParse, A, X);
  }
  expr(A) ::= expr(A) in_op(N) LP select(Y) RP.  [IN] {
    A = sqlite3PExpr(pParse, TK_IN, A, 0);
    sqlite3PExprAddSelect(pParse, A, Y);
    if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0);
  }
  expr(A) ::= expr(A) in_op(N) nm(Y) dbnm(Z) paren_exprlist(E). [IN] {
    SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&Y,&Z);
    SrcList *pSrc = sqlite3SrcListAppend(pParse, 0,&Y,&Z);
    Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0);
    if( E )  sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, E);
    A = sqlite3PExpr(pParse, TK_IN, A, 0);
    sqlite3PExprAddSelect(pParse, A, pSelect);
    if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0);
  }
  expr(A) ::= EXISTS LP select(Y) RP. {
1299
1300
1301
1302
1303
1304
1305
1306

1307
1308
1309
1310
1311
1312
1313
1413
1414
1415
1416
1417
1418
1419

1420
1421
1422
1423
1424
1425
1426
1427







-
+









///////////////////////////// The CREATE INDEX command ///////////////////////
//
cmd ::= createkw(S) uniqueflag(U) INDEX ifnotexists(NE) nm(X) dbnm(D)
        ON nm(Y) LP sortlist(Z) RP where_opt(W). {
  sqlite3CreateIndex(pParse, &X, &D, 
                     sqlite3SrcListAppend(pParse->db,0,&Y,0), Z, U,
                     sqlite3SrcListAppend(pParse,0,&Y,0), Z, U,
                      &S, W, SQLITE_SO_ASC, NE, SQLITE_IDXTYPE_APPDEF);
  if( IN_RENAME_OBJECT && pParse->pNewIndex ){
    sqlite3RenameTokenMap(pParse, pParse->pNewIndex->zName, &Y);
  }
}

%type uniqueflag {int}
1321
1322
1323
1324
1325
1326
1327
1328

1329
1330
1331
1332
1333
1334
1335
1435
1436
1437
1438
1439
1440
1441

1442
1443
1444
1445
1446
1447
1448
1449







-
+







// can be easily sent to sqlite3ColumnsExprList().
//
// eidlist is grouped with CREATE INDEX because it used to be the non-terminal
// used for the arguments to an index.  That is just an historical accident.
//
// IMPORTANT COMPATIBILITY NOTE:  Some prior versions of SQLite accepted
// COLLATE clauses and ASC or DESC keywords on ID lists in inappropriate
// places - places that might have been stored in the sqlite_master schema.
// places - places that might have been stored in the sqlite_schema table.
// Those extra features were ignored.  But because they might be in some
// (busted) old databases, we need to continue parsing them when loading
// historical schemas.
//
%type eidlist {ExprList*}
%destructor eidlist {sqlite3ExprListDelete(pParse->db, $$);}
%type eidlist_opt {ExprList*}
1376
1377
1378
1379
1380
1381
1382
1383

1384
1385
1386
1387
1388
1389
1390
1391

1392
1393
1394
1395
1396
1397
1398
1399
1490
1491
1492
1493
1494
1495
1496

1497

1498
1499
1500
1501
1502
1503

1504

1505
1506
1507
1508
1509
1510
1511







-
+
-






-
+
-








///////////////////////////// The DROP INDEX command /////////////////////////
//
cmd ::= DROP INDEX ifexists(E) fullname(X).   {sqlite3DropIndex(pParse, X, E);}

///////////////////////////// The VACUUM command /////////////////////////////
//
%ifndef SQLITE_OMIT_VACUUM
%if !SQLITE_OMIT_VACUUM && !SQLITE_OMIT_ATTACH
%ifndef SQLITE_OMIT_ATTACH
%type vinto {Expr*}
%destructor vinto {sqlite3ExprDelete(pParse->db, $$);}
cmd ::= VACUUM vinto(Y).                {sqlite3Vacuum(pParse,0,Y);}
cmd ::= VACUUM nm(X) vinto(Y).          {sqlite3Vacuum(pParse,&X,Y);}
vinto(A) ::= INTO expr(X).              {A = X;}
vinto(A) ::= .                          {A = 0;}
%endif  SQLITE_OMIT_ATTACH
%endif
%endif  SQLITE_OMIT_VACUUM

///////////////////////////// The PRAGMA command /////////////////////////////
//
%ifndef SQLITE_OMIT_PRAGMA
cmd ::= PRAGMA nm(X) dbnm(Z).                {sqlite3Pragma(pParse,&X,&Z,0,0);}
cmd ::= PRAGMA nm(X) dbnm(Z) EQ nmnum(Y).    {sqlite3Pragma(pParse,&X,&Z,&Y,0);}
cmd ::= PRAGMA nm(X) dbnm(Z) LP nmnum(Y) RP. {sqlite3Pragma(pParse,&X,&Z,&Y,0);}
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
1604
1605
1606
1607
1608
1609
1610


1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630

1631
1632
1633
1634

1635
1636

1637
1638
1639
1640
1641
1642
1643
1644







-
-
+
+


















-
+



-
+

-
+










%type trigger_cmd {TriggerStep*}
%destructor trigger_cmd {sqlite3DeleteTriggerStep(pParse->db, $$);}
// UPDATE 
trigger_cmd(A) ::=
   UPDATE(B) orconf(R) trnm(X) tridxby SET setlist(Y) where_opt(Z) scanpt(E).  
   {A = sqlite3TriggerUpdateStep(pParse, &X, Y, Z, R, B.z, E);}
   UPDATE(B) orconf(R) trnm(X) tridxby SET setlist(Y) from(F) where_opt(Z) scanpt(E).  
   {A = sqlite3TriggerUpdateStep(pParse, &X, F, Y, Z, R, B.z, E);}

// INSERT
trigger_cmd(A) ::= scanpt(B) insert_cmd(R) INTO
                      trnm(X) idlist_opt(F) select(S) upsert(U) scanpt(Z). {
   A = sqlite3TriggerInsertStep(pParse,&X,F,S,R,U,B,Z);/*A-overwrites-R*/
}
// DELETE
trigger_cmd(A) ::= DELETE(B) FROM trnm(X) tridxby where_opt(Y) scanpt(E).
   {A = sqlite3TriggerDeleteStep(pParse, &X, Y, B.z, E);}

// SELECT
trigger_cmd(A) ::= scanpt(B) select(X) scanpt(E).
   {A = sqlite3TriggerSelectStep(pParse->db, X, B, E); /*A-overwrites-X*/}

// The special RAISE expression that may occur in trigger programs
expr(A) ::= RAISE LP IGNORE RP.  {
  A = sqlite3PExpr(pParse, TK_RAISE, 0, 0); 
  if( A ){
    A->affinity = OE_Ignore;
    A->affExpr = OE_Ignore;
  }
}
expr(A) ::= RAISE LP raisetype(T) COMMA nm(Z) RP.  {
  A = sqlite3ExprAlloc(pParse->db, TK_RAISE, &Z, 1); 
  A = sqlite3ExprAlloc(pParse->db, TK_RAISE, &Z, 1);
  if( A ) {
    A->affinity = (char)T;
    A->affExpr = (char)T;
  }
}
%endif  !SQLITE_OMIT_TRIGGER

%type raisetype {int}
raisetype(A) ::= ROLLBACK.  {A = OE_Rollback;}
raisetype(A) ::= ABORT.     {A = OE_Abort;}
1567
1568
1569
1570
1571
1572
1573
1574


1575
1576
1577
1578
1579
1580
1581
1582




1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593

1594

1595
1596
1597
1598
1599
1600
1601
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







-
+
+








+
+
+
+











+
-
+







/////////////////////////////////// ANALYZE ///////////////////////////////////
%ifndef SQLITE_OMIT_ANALYZE
cmd ::= ANALYZE.                {sqlite3Analyze(pParse, 0, 0);}
cmd ::= ANALYZE nm(X) dbnm(Y).  {sqlite3Analyze(pParse, &X, &Y);}
%endif

//////////////////////// ALTER TABLE table ... ////////////////////////////////
%ifndef SQLITE_OMIT_ALTERTABLE
%ifndef SQLITE_OMIT_ALTERTABLE 
%ifndef SQLITE_OMIT_VIRTUALTABLE
cmd ::= ALTER TABLE fullname(X) RENAME TO nm(Z). {
  sqlite3AlterRenameTable(pParse,X,&Z);
}
cmd ::= ALTER TABLE add_column_fullname
        ADD kwcolumn_opt columnname(Y) carglist. {
  Y.n = (int)(pParse->sLastToken.z-Y.z) + pParse->sLastToken.n;
  sqlite3AlterFinishAddColumn(pParse, &Y);
}
cmd ::= ALTER TABLE fullname(X) DROP kwcolumn_opt nm(Y). {
  sqlite3AlterDropColumn(pParse, X, &Y);
}

add_column_fullname ::= fullname(X). {
  disableLookaside(pParse);
  sqlite3AlterBeginAddColumn(pParse, X);
}
cmd ::= ALTER TABLE fullname(X) RENAME kwcolumn_opt nm(Y) TO nm(Z). {
  sqlite3AlterRenameColumn(pParse, X, &Y, &Z);
}

kwcolumn_opt ::= .
kwcolumn_opt ::= COLUMNKW.

%endif SQLITE_OMIT_VIRTUALTABLE
%endif  SQLITE_OMIT_ALTERTABLE
%endif SQLITE_OMIT_ALTERTABLE

//////////////////////// CREATE VIRTUAL TABLE ... /////////////////////////////
%ifndef SQLITE_OMIT_VIRTUALTABLE
cmd ::= create_vtab.                       {sqlite3VtabFinishParse(pParse,0);}
cmd ::= create_vtab LP vtabarglist RP(X).  {sqlite3VtabFinishParse(pParse,&X);}
create_vtab ::= createkw VIRTUAL TABLE ifnotexists(E)
                nm(X) dbnm(Y) USING nm(Z). {
1613
1614
1615
1616
1617
1618
1619


1620
1621
1622
1623
1624
1625







1626
1627


1628
1629
1630


1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645

1646
1647
1648
1649
1650
1651
1652

1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669








1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681


1682
1683
1684
1685






1686


1687
1688
1689







1690
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










































1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752


1753
1754
1755


1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779

1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795


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


1814
1815




1816
1817
1818
1819
1820
1821
1822
1823
1824



1825
1826
1827
1828
1829
1830
1831
1832
1833

1834
1835


1836
1837
1838


1839
1840
1841
1842
1843

1844

1845





1846
1847
1848
1849
1850



1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876



1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892

1893

1894
1895
1896
1897



1898
1899
1900


1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944







+
+






+
+
+
+
+
+
+
-
-
+
+

-
-
+
+















+






-
+















-
-
+
+
+
+
+
+
+
+










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

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


-
+

-
-
+
+

-
-
+
+
+


-
+
-

-
-
-
-
-
+
+
+
+

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





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


-

-
+



-
-
-



-
-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
anylist ::= anylist ANY.
%endif  SQLITE_OMIT_VIRTUALTABLE


//////////////////////// COMMON TABLE EXPRESSIONS ////////////////////////////
%type wqlist {With*}
%destructor wqlist {sqlite3WithDelete(pParse->db, $$);}
%type wqitem {Cte*}
// %destructor wqitem {sqlite3CteDelete(pParse->db, $$);} // not reachable

with ::= .
%ifndef SQLITE_OMIT_CTE
with ::= WITH wqlist(W).              { sqlite3WithPush(pParse, W, 1); }
with ::= WITH RECURSIVE wqlist(W).    { sqlite3WithPush(pParse, W, 1); }

%type wqas {u8}
wqas(A)   ::= AS.                  {A = M10d_Any;}
wqas(A)   ::= AS MATERIALIZED.     {A = M10d_Yes;}
wqas(A)   ::= AS NOT MATERIALIZED. {A = M10d_No;}
wqitem(A) ::= nm(X) eidlist_opt(Y) wqas(M) LP select(Z) RP. {
  A = sqlite3CteNew(pParse, &X, Y, Z, M); /*A-overwrites-X*/
}
wqlist(A) ::= nm(X) eidlist_opt(Y) AS LP select(Z) RP. {
  A = sqlite3WithAdd(pParse, 0, &X, Y, Z); /*A-overwrites-X*/
wqlist(A) ::= wqitem(X). {
  A = sqlite3WithAdd(pParse, 0, X); /*A-overwrites-X*/
}
wqlist(A) ::= wqlist(A) COMMA nm(X) eidlist_opt(Y) AS LP select(Z) RP. {
  A = sqlite3WithAdd(pParse, A, &X, Y, Z);
wqlist(A) ::= wqlist(A) COMMA wqitem(X). {
  A = sqlite3WithAdd(pParse, A, X);
}
%endif  SQLITE_OMIT_CTE

//////////////////////// WINDOW FUNCTION EXPRESSIONS /////////////////////////
// These must be at the end of this file. Specifically, the rules that
// introduce tokens WINDOW, OVER and FILTER must appear last. This causes 
// the integer values assigned to these tokens to be larger than all other 
// tokens that may be output by the tokenizer except TK_SPACE and TK_ILLEGAL.
//
%ifndef SQLITE_OMIT_WINDOWFUNC
%type windowdefn_list {Window*}
%destructor windowdefn_list {sqlite3WindowListDelete(pParse->db, $$);}
windowdefn_list(A) ::= windowdefn(Z). { A = Z; }
windowdefn_list(A) ::= windowdefn_list(Y) COMMA windowdefn(Z). {
  assert( Z!=0 );
  sqlite3WindowChain(pParse, Z, Y);
  Z->pNextWin = Y;
  A = Z;
}

%type windowdefn {Window*}
%destructor windowdefn {sqlite3WindowDelete(pParse->db, $$);}
windowdefn(A) ::= nm(X) AS window(Y). {
windowdefn(A) ::= nm(X) AS LP window(Y) RP. {
  if( ALWAYS(Y) ){
    Y->zName = sqlite3DbStrNDup(pParse->db, X.z, X.n);
  }
  A = Y;
}

%type window {Window*}
%destructor window {sqlite3WindowDelete(pParse->db, $$);}

%type frame_opt {Window*}
%destructor frame_opt {sqlite3WindowDelete(pParse->db, $$);}

%type part_opt {ExprList*}
%destructor part_opt {sqlite3ExprListDelete(pParse->db, $$);}

%type filter_opt {Expr*}
%destructor filter_opt {sqlite3ExprDelete(pParse->db, $$);}
%type filter_clause {Expr*}
%destructor filter_clause {sqlite3ExprDelete(pParse->db, $$);}

%type over_clause {Window*}
%destructor over_clause {sqlite3WindowDelete(pParse->db, $$);}

%type filter_over {Window*}
%destructor filter_over {sqlite3WindowDelete(pParse->db, $$);}

%type range_or_rows {int}

%type frame_bound {struct FrameBound}
%destructor frame_bound {sqlite3ExprDelete(pParse->db, $$.pExpr);}
%type frame_bound_s {struct FrameBound}
%destructor frame_bound_s {sqlite3ExprDelete(pParse->db, $$.pExpr);}
%type frame_bound_e {struct FrameBound}
%destructor frame_bound_e {sqlite3ExprDelete(pParse->db, $$.pExpr);}

window(A) ::= LP part_opt(X) orderby_opt(Y) frame_opt(Z) RP. {
  A = Z;
window(A) ::= PARTITION BY nexprlist(X) orderby_opt(Y) frame_opt(Z). {
  A = sqlite3WindowAssemble(pParse, Z, X, Y, 0);
  if( ALWAYS(A) ){
    A->pPartition = X;
    A->pOrderBy = Y;
  }
}
window(A) ::= nm(W) PARTITION BY nexprlist(X) orderby_opt(Y) frame_opt(Z). {
  A = sqlite3WindowAssemble(pParse, Z, X, Y, &W);
}
window(A) ::= ORDER BY sortlist(Y) frame_opt(Z). {
  A = sqlite3WindowAssemble(pParse, Z, 0, Y, 0);
}
window(A) ::= nm(W) ORDER BY sortlist(Y) frame_opt(Z). {
  A = sqlite3WindowAssemble(pParse, Z, 0, Y, &W);

part_opt(A) ::= PARTITION BY nexprlist(X). { A = X; }
part_opt(A) ::= .                          { A = 0; }
}
window(A) ::= frame_opt(Z). {
  A = Z;
}
window(A) ::= nm(W) frame_opt(Z). {
  A = sqlite3WindowAssemble(pParse, Z, 0, 0, &W);
}

frame_opt(A) ::= .                             { 
  A = sqlite3WindowAlloc(pParse, TK_RANGE, TK_UNBOUNDED, 0, TK_CURRENT, 0);
  A = sqlite3WindowAlloc(pParse, 0, TK_UNBOUNDED, 0, TK_CURRENT, 0, 0);
}
frame_opt(A) ::= range_or_rows(X) frame_bound_s(Y). { 
  A = sqlite3WindowAlloc(pParse, X, Y.eType, Y.pExpr, TK_CURRENT, 0);
frame_opt(A) ::= range_or_rows(X) frame_bound_s(Y) frame_exclude_opt(Z). { 
  A = sqlite3WindowAlloc(pParse, X, Y.eType, Y.pExpr, TK_CURRENT, 0, Z);
}
frame_opt(A) ::= range_or_rows(X) BETWEEN frame_bound_s(Y) AND frame_bound_e(Z). { 
  A = sqlite3WindowAlloc(pParse, X, Y.eType, Y.pExpr, Z.eType, Z.pExpr);
frame_opt(A) ::= range_or_rows(X) BETWEEN frame_bound_s(Y) AND
                          frame_bound_e(Z) frame_exclude_opt(W). { 
  A = sqlite3WindowAlloc(pParse, X, Y.eType, Y.pExpr, Z.eType, Z.pExpr, W);
}

range_or_rows(A) ::= RANGE.   { A = TK_RANGE; }
range_or_rows(A) ::= RANGE|ROWS|GROUPS(X).   {A = @X; /*A-overwrites-X*/}
range_or_rows(A) ::= ROWS.    { A = TK_ROWS;  }


frame_bound_s(A) ::= frame_bound(X). { A = X; }
frame_bound_s(A) ::= UNBOUNDED PRECEDING. {A.eType = TK_UNBOUNDED; A.pExpr = 0;}
frame_bound_e(A) ::= frame_bound(X). { A = X; }
frame_bound_e(A) ::= UNBOUNDED FOLLOWING. {A.eType = TK_UNBOUNDED; A.pExpr = 0;}
frame_bound_s(A) ::= frame_bound(X).         {A = X;}
frame_bound_s(A) ::= UNBOUNDED(X) PRECEDING. {A.eType = @X; A.pExpr = 0;}
frame_bound_e(A) ::= frame_bound(X).         {A = X;}
frame_bound_e(A) ::= UNBOUNDED(X) FOLLOWING. {A.eType = @X; A.pExpr = 0;}

frame_bound(A) ::= expr(X) PRECEDING.   { A.eType = TK_PRECEDING; A.pExpr = X; }
frame_bound(A) ::= CURRENT ROW.         { A.eType = TK_CURRENT  ; A.pExpr = 0; }
frame_bound(A) ::= expr(X) FOLLOWING.   { A.eType = TK_FOLLOWING; A.pExpr = X; }
frame_bound(A) ::= expr(X) PRECEDING|FOLLOWING(Y).
                                             {A.eType = @Y; A.pExpr = X;}
frame_bound(A) ::= CURRENT(X) ROW.           {A.eType = @X; A.pExpr = 0;}

%type frame_exclude_opt {u8}
frame_exclude_opt(A) ::= . {A = 0;}
frame_exclude_opt(A) ::= EXCLUDE frame_exclude(X). {A = X;}

%type frame_exclude {u8}
frame_exclude(A) ::= NO(X) OTHERS.   {A = @X; /*A-overwrites-X*/}
frame_exclude(A) ::= CURRENT(X) ROW. {A = @X; /*A-overwrites-X*/}
frame_exclude(A) ::= GROUP|TIES(X).  {A = @X; /*A-overwrites-X*/}


%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;
  }else{
    sqlite3ExprDelete(pParse->db, F);
  }
  A = O;
}
%type over_clause {Window*}
%destructor over_clause {sqlite3WindowDelete(pParse->db, $$);}
over_clause(A) ::= filter_opt(W) OVER window(Z). {
filter_over(A) ::= over_clause(O). {
  A = O;
}
filter_over(A) ::= filter_clause(F). {
  A = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window));
  if( A ){
    A->eFrmType = TK_FILTER;
    A->pFilter = F;
  }else{
    sqlite3ExprDelete(pParse->db, F);
  }
}

over_clause(A) ::= OVER LP window(Z) RP. {
  A = Z;
  assert( A!=0 );
  A->pFilter = W;
}
over_clause(A) ::= filter_opt(W) OVER nm(Z). {
over_clause(A) ::= OVER nm(Z). {
  A = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window));
  if( A ){
    A->zName = sqlite3DbStrNDup(pParse->db, Z.z, Z.n);
    A->pFilter = W;
  }else{
    sqlite3ExprDelete(pParse->db, W);
  }
}

filter_opt(A) ::= .                            { A = 0; }
filter_opt(A) ::= FILTER LP WHERE expr(X) RP.  { A = X; }
filter_clause(A) ::= FILTER LP WHERE expr(X) RP.  { A = X; }
%endif /* SQLITE_OMIT_WINDOWFUNC */

/*
** The code generator needs some extra TK_ token values for tokens that
** are synthesized and do not actually appear in the grammar:
*/
%token
  COLUMN          /* Reference to a table column */
  AGG_FUNCTION    /* An aggregate function */
  AGG_COLUMN      /* An aggregated column */
  TRUEFALSE       /* True or false keyword */
  ISNOT           /* Combination of IS and NOT */
  FUNCTION        /* A function invocation */
  UMINUS          /* Unary minus */
  UPLUS           /* Unary plus */
  TRUTH           /* IS TRUE or IS FALSE or IS NOT TRUE or IS NOT FALSE */
  REGISTER        /* Reference to a VDBE register */
  CONCURRENT      /* BEGIN CONCURRENT */
  VECTOR          /* Vector */
  SELECT_COLUMN   /* Choose a single column from a multi-column SELECT */
  IF_NULL_ROW     /* the if-null-row operator */
  ASTERISK        /* The "*" in count(*) and similar */
  SPAN            /* The span operator */
  ERROR           /* An expression containing an error */
.
/* There must be no more than 255 tokens defined above.  If this grammar
** is extended with new rules and tokens, they must either be so few in
** number that TK_SPAN is no more than 255, or else the new tokens must
** appear after this line.
*/
%include {
#if TK_SPAN>255
# error too many tokens in the grammar
#endif
}

/*
** The TK_SPACE and TK_ILLEGAL tokens must be the last two tokens.  The
** parser depends on this.  Those tokens are not used in any grammar rule.
** They are only used by the tokenizer.  Declare them last so that they
** are guaranteed to be the last two tokens
*/
%token SPACE ILLEGAL.

Changes to src/pcache.c.

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







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

-
+

-
-








-
+
-
-
-
-
-
+




-
+

+



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


















-
-
+
+
+
+
+
+
+







** When sqlite3PcacheTrace is 2, a dump of the pcache showing all cache entries
** is displayed for many operations, resulting in a lot of output.
*/
#if defined(SQLITE_DEBUG) && 0
  int sqlite3PcacheTrace = 2;       /* 0: off  1: simple  2: cache dumps */
  int sqlite3PcacheMxDump = 9999;   /* Max cache entries for pcacheDump() */
# define pcacheTrace(X) if(sqlite3PcacheTrace){sqlite3DebugPrintf X;}
  static void pcachePageTrace(int i, sqlite3_pcache_page *pLower){
    PgHdr *pPg;
    unsigned char *a;
    int j;
    pPg = (PgHdr*)pLower->pExtra;
    printf("%3d: nRef %2d flgs %02x data ", i, pPg->nRef, pPg->flags);
    a = (unsigned char *)pLower->pBuf;
    for(j=0; j<12; j++) printf("%02x", a[j]);
    printf(" ptr %p\n", pPg);
  }
  void pcacheDump(PCache *pCache){
  static void pcacheDump(PCache *pCache){
    int N;
    int i, j;
    int i;
    sqlite3_pcache_page *pLower;
    PgHdr *pPg;
    unsigned char *a;
  
    if( sqlite3PcacheTrace<2 ) return;
    if( pCache->pCache==0 ) return;
    N = sqlite3PcachePagecount(pCache);
    if( N>sqlite3PcacheMxDump ) N = sqlite3PcacheMxDump;
    for(i=1; i<=N; i++){
       pLower = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, i, 0);
       if( pLower==0 ) continue;
       pPg = (PgHdr*)pLower->pExtra;
       pcachePageTrace(i, pLower);
       printf("%3d: nRef %2d flgs %02x data ", i, pPg->nRef, pPg->flags);
       a = (unsigned char *)pLower->pBuf;
       for(j=0; j<12; j++) printf("%02x", a[j]);
       printf("\n");
       if( pPg->pPage==0 ){
       if( ((PgHdr*)pLower)->pPage==0 ){
         sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, pLower, 0);
       }
    }
  }
  #else
#else
# define pcacheTrace(X)
# define pcachePageTrace(PGNO, X)
# define pcacheDump(X)
#endif

/*
** Return 1 if pPg is on the dirty list for pCache.  Return 0 if not.
** This routine runs inside of assert() statements only.
*/
#ifdef SQLITE_DEBUG
static int pageOnDirtyList(PCache *pCache, PgHdr *pPg){
  PgHdr *p;
  for(p=pCache->pDirty; p; p=p->pDirtyNext){
    if( p==pPg ) return 1;
  }
  return 0;
}
#endif

/*
** Check invariants on a PgHdr entry.  Return true if everything is OK.
** Return false if any invariant is violated.
**
** This routine is for use inside of assert() statements only.  For
** example:
**
**          assert( sqlite3PcachePageSanity(pPg) );
*/
#ifdef SQLITE_DEBUG
int sqlite3PcachePageSanity(PgHdr *pPg){
  PCache *pCache;
  assert( pPg!=0 );
  assert( pPg->pgno>0 || pPg->pPager==0 );    /* Page number is 1 or more */
  pCache = pPg->pCache;
  assert( pCache!=0 );      /* Every page has an associated PCache */
  if( pPg->flags & PGHDR_CLEAN ){
    assert( (pPg->flags & PGHDR_DIRTY)==0 );/* Cannot be both CLEAN and DIRTY */
    assert( pCache->pDirty!=pPg );          /* CLEAN pages not on dirty list */
    assert( pCache->pDirtyTail!=pPg );
    assert( !pageOnDirtyList(pCache, pPg) );/* CLEAN pages not on dirty list */
  }else{
    assert( (pPg->flags & PGHDR_DIRTY)!=0 );/* If not CLEAN must be DIRTY */
    assert( pPg->pDirtyNext==0 || pPg->pDirtyNext->pDirtyPrev==pPg );
    assert( pPg->pDirtyPrev==0 || pPg->pDirtyPrev->pDirtyNext==pPg );
    assert( pPg->pDirtyPrev!=0 || pCache->pDirty==pPg );
    assert( pageOnDirtyList(pCache, pPg) );
  }
  /* WRITEABLE pages must also be DIRTY */
  if( pPg->flags & PGHDR_WRITEABLE ){
    assert( pPg->flags & PGHDR_DIRTY );     /* WRITEABLE implies DIRTY */
  }
  /* NEED_SYNC can be set independently of WRITEABLE.  This can happen,
  ** for example, when using the sqlite3PagerDontWrite() optimization:
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
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







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














+







*/
static int numberOfCachePages(PCache *p){
  if( p->szCache>=0 ){
    /* IMPLEMENTATION-OF: R-42059-47211 If the argument N is positive then the
    ** suggested cache size is set to N. */
    return p->szCache;
  }else{
    i64 n;
    /* IMPLEMENTATION-OF: R-61436-13639 If the argument N is negative, then
    ** the number of cache pages is adjusted to use approximately abs(N*1024)
    ** bytes of memory. */
    return (int)((-1024*(i64)p->szCache)/(p->szPage+p->szExtra));
    /* IMPLEMANTATION-OF: R-59858-46238 If the argument N is negative, then the
    ** number of cache pages is adjusted to be a number of pages that would
    ** use approximately abs(N*1024) bytes of memory based on the current
    ** page size. */
    n = ((-1024*(i64)p->szCache)/(p->szPage+p->szExtra));
    if( n>1000000000 ) n = 1000000000;
    return (int)n;
  }
}

/*************************************************** General Interfaces ******
**
** Initialize and shutdown the page cache subsystem. Neither of these 
** functions are threadsafe.
*/
int sqlite3PcacheInitialize(void){
  if( sqlite3GlobalConfig.pcache2.xInit==0 ){
    /* IMPLEMENTATION-OF: R-26801-64137 If the xInit() method is NULL, then the
    ** built-in default page cache is used instead of the application defined
    ** page cache. */
    sqlite3PCacheSetDefault();
    assert( sqlite3GlobalConfig.pcache2.xInit!=0 );
  }
  return sqlite3GlobalConfig.pcache2.xInit(sqlite3GlobalConfig.pcache2.pArg);
}
void sqlite3PcacheShutdown(void){
  if( sqlite3GlobalConfig.pcache2.xShutdown ){
    /* IMPLEMENTATION-OF: R-26000-56589 The xShutdown() method may be NULL. */
    sqlite3GlobalConfig.pcache2.xShutdown(sqlite3GlobalConfig.pcache2.pArg);
379
380
381
382
383
384
385
386

387

388
389
390
391
392
393
394
408
409
410
411
412
413
414

415
416
417
418
419
420
421
422
423
424







-
+

+







  **          (createFlag==1 AND !(bPurgeable AND pDirty)
  */
  eCreate = createFlag & pCache->eCreate;
  assert( eCreate==0 || eCreate==1 || eCreate==2 );
  assert( createFlag==0 || pCache->eCreate==eCreate );
  assert( createFlag==0 || eCreate==1+(!pCache->bPurgeable||!pCache->pDirty) );
  pRes = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate);
  pcacheTrace(("%p.FETCH %d%s (result: %p)\n",pCache,pgno,
  pcacheTrace(("%p.FETCH %d%s (result: %p) ",pCache,pgno,
               createFlag?" create":"",pRes));
  pcachePageTrace(pgno, pRes);
  return pRes;
}

/*
** If the sqlite3PcacheFetch() routine is unable to allocate a new
** page because no clean pages are available for reuse and the cache
** size limit has been reached, then this routine can be invoked to 
508
509
510
511
512
513
514

515
516
517
518
519
520
521
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552







+







  assert( p->nRef>0 );
  p->pCache->nRefSum--;
  if( (--p->nRef)==0 ){
    if( p->flags&PGHDR_CLEAN ){
      pcacheUnpin(p);
    }else{
      pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT);
      assert( sqlite3PcachePageSanity(p) );
    }
  }
}

/*
** Increase the reference count of a supplied page by 1.
*/
551
552
553
554
555
556
557

558
559
560
561
562
563
564
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596







+







  if( p->flags & (PGHDR_CLEAN|PGHDR_DONT_WRITE) ){    /*OPTIMIZATION-IF-FALSE*/
    p->flags &= ~PGHDR_DONT_WRITE;
    if( p->flags & PGHDR_CLEAN ){
      p->flags ^= (PGHDR_DIRTY|PGHDR_CLEAN);
      pcacheTrace(("%p.DIRTY %d\n",p->pCache,p->pgno));
      assert( (p->flags & (PGHDR_DIRTY|PGHDR_CLEAN))==PGHDR_DIRTY );
      pcacheManageDirtyList(p, PCACHE_DIRTYLIST_ADD);
      assert( sqlite3PcachePageSanity(p) );
    }
    assert( sqlite3PcachePageSanity(p) );
  }
}

/*
** Make sure the page is marked as clean. If it isn't clean already,
613
614
615
616
617
618
619

620
621
622
623








624
625
626
627

628
629
630
631
632
633
634
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







+




+
+
+
+
+
+
+
+




+







}

/*
** Change the page number of page p to newPgno. 
*/
void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){
  PCache *pCache = p->pCache;
  sqlite3_pcache_page *pOther;
  assert( p->nRef>0 );
  assert( newPgno>0 );
  assert( sqlite3PcachePageSanity(p) );
  pcacheTrace(("%p.MOVE %d -> %d\n",pCache,p->pgno,newPgno));
  pOther = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, newPgno, 0);
  if( pOther ){
    PgHdr *pXPage = (PgHdr*)pOther->pExtra;
    assert( pXPage->nRef==0 );
    pXPage->nRef++;
    pCache->nRefSum++;
    sqlite3PcacheDrop(pXPage);
  }
  sqlite3GlobalConfig.pcache2.xRekey(pCache->pCache, p->pPage, p->pgno,newPgno);
  p->pgno = newPgno;
  if( (p->flags&PGHDR_DIRTY) && (p->flags&PGHDR_NEED_SYNC) ){
    pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT);
    assert( sqlite3PcachePageSanity(p) );
  }
}

/*
** Drop every cache entry whose page number is greater than "pgno". The
** caller must ensure that there are no outstanding references to any pages
** other than page 1 with a page number greater than pgno.

Changes to src/pcache1.c.

35
36
37
38
39
40
41
42
43



44
45
46




47
48
49
50
51
52
53
54
35
36
37
38
39
40
41


42
43
44



45
46
47
48

49
50
51
52
53
54
55







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







**
** The size of the extension (MemPage+PgHdr+PgHdr1) can be determined at
** runtime using sqlite3_config(SQLITE_CONFIG_PCACHE_HDRSZ, &size).  The
** sizes of the extensions sum to 272 bytes on x64 for 3.8.10, but this
** size can vary according to architecture, compile-time options, and
** SQLite library version number.
**
** If SQLITE_PCACHE_SEPARATE_HEADER is defined, then the extension is obtained
** using a separate memory allocation from the database page content.  This
** Historical note:  It used to be that if the SQLITE_PCACHE_SEPARATE_HEADER
** was defined, then the page content would be held in a separate memory
** allocation from the PgHdr1.  This was intended to avoid clownshoe memory
** seeks to overcome the "clownshoe" problem (also called "internal
** fragmentation" in academic literature) of allocating a few bytes more
** than a power of two with the memory allocator rounding up to the next
** allocations.  However, the btree layer needs a small (16-byte) overrun
** area after the page content buffer.  The header serves as that overrun
** area.  Therefore SQLITE_PCACHE_SEPARATE_HEADER was discontinued to avoid
** any possibility of a memory error.
** power of two, and leaving the rounded-up space unused.
**
** This module tracks pointers to PgHdr1 objects.  Only pcache.c communicates
** with this module.  Information is passed back and forth as PgHdr1 pointers.
**
** The pcache.c and pager.c modules deal pointers to PgHdr objects.
** The btree.c module deals with pointers to MemPage objects.
**
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
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







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


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







typedef struct PCache1 PCache1;
typedef struct PgHdr1 PgHdr1;
typedef struct PgFreeslot PgFreeslot;
typedef struct PGroup PGroup;

/*
** Each cache entry is represented by an instance of the following 
** structure. Unless SQLITE_PCACHE_SEPARATE_HEADER is defined, a buffer of
** PgHdr1.pCache->szPage bytes is allocated directly before this structure 
** in memory.
** structure. A buffer of PgHdr1.pCache->szPage bytes is allocated
** directly before this structure and is used to cache the page content.
**
** When reading a corrupt database file, it is possible that SQLite might
** read a few bytes (no more than 16 bytes) past the end of the page buffer.
** It will only read past the end of the page buffer, never write.  This
** object is positioned immediately after the page buffer to serve as an
** overrun area, so that overreads are harmless.
**
** Variables isBulkLocal and isAnchor were once type "u8". That works,
** but causes a 2-byte gap in the structure for most architectures (since 
** pointers must be either 4 or 8-byte aligned). As this structure is located
** in memory directly after the associated page data, if the database is
** corrupt, code at the b-tree layer may overread the page buffer and 
** read part of this structure before the corruption is detected. This
** can cause a valgrind error if the unitialized gap is accessed. Using u16
** ensures there is no such gap, and therefore no bytes of uninitialized
** memory in the structure.
**
** The pLruNext and pLruPrev pointers form a double-linked circular list
** of all pages that are unpinned.  The PGroup.lru element (which should be
** the only element on the list with PgHdr1.isAnchor set to 1) forms the
** beginning and the end of the list.
*/
struct PgHdr1 {
  sqlite3_pcache_page page;      /* Base class. Must be first. pBuf & pExtra */
  unsigned int iKey;             /* Key value (page number) */
  u8 isBulkLocal;                /* This page from bulk local storage */
  u8 isAnchor;                   /* This is the PGroup.lru element */
  PgHdr1 *pNext;                 /* Next in hash table chain */
  PCache1 *pCache;               /* Cache that currently owns this page */
  PgHdr1 *pLruNext;              /* Next in LRU list of unpinned pages */
  PgHdr1 *pLruPrev;              /* Previous in LRU list of unpinned pages */
                                 /* NB: pLruPrev is only valid if pLruNext!=0 */
  sqlite3_pcache_page page; /* Base class. Must be first. pBuf & pExtra */
  unsigned int iKey;        /* Key value (page number) */
  u16 isBulkLocal;          /* This page from bulk local storage */
  u16 isAnchor;             /* This is the PGroup.lru element */
  PgHdr1 *pNext;            /* Next in hash table chain */
  PCache1 *pCache;          /* Cache that currently owns this page */
  PgHdr1 *pLruNext;         /* Next in circular LRU list of unpinned pages */
  PgHdr1 *pLruPrev;         /* Previous in LRU list of unpinned pages */
                            /* NB: pLruPrev is only valid if pLruNext!=0 */
};

/*
** A page is pinned if it is not on the LRU list.  To be "pinned" means
** that the page is in active use and must not be deallocated.
*/
#define PAGE_IS_PINNED(p)    ((p)->pLruNext==0)
164
165
166
167
168
169
170

171
172
173
174
175
176
177
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199







+







  int szExtra;                        /* sizeof(MemPage)+sizeof(PgHdr) */
  int szAlloc;                        /* Total size of one pcache line */
  int bPurgeable;                     /* True if cache is purgeable */
  unsigned int nMin;                  /* Minimum number of pages reserved */
  unsigned int nMax;                  /* Configured "cache_size" value */
  unsigned int n90pct;                /* nMax*9/10 */
  unsigned int iMaxKey;               /* Largest key seen since xTruncate() */
  unsigned int nPurgeableDummy;       /* pnPurgeable points here when not used*/

  /* Hash table of all pages. The following variables may only be accessed
  ** when the accessor is holding the PGroup mutex.
  */
  unsigned int nRecyclable;           /* Number of pages in the LRU list */
  unsigned int nPage;                 /* Total number of pages in apHash */
  unsigned int nHash;                 /* Number of slots in apHash[] */
298
299
300
301
302
303
304

305
306
307
308
309
310
311
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334







+







    do{
      PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage];
      pX->page.pBuf = zBulk;
      pX->page.pExtra = &pX[1];
      pX->isBulkLocal = 1;
      pX->isAnchor = 0;
      pX->pNext = pCache->pFree;
      pX->pLruPrev = 0;           /* Initializing this saves a valgrind error */
      pCache->pFree = pX;
      zBulk += pCache->szAlloc;
    }while( --nBulk );
  }
  return pCache->pFree!=0;
}

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







+













-
-
-
-
-
-
-
-
-

-
-





+




+


















-
-
-










-
-
-
+







*/
static PgHdr1 *pcache1AllocPage(PCache1 *pCache, int benignMalloc){
  PgHdr1 *p = 0;
  void *pPg;

  assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
  if( pCache->pFree || (pCache->nPage==0 && pcache1InitBulk(pCache)) ){
    assert( pCache->pFree!=0 );
    p = pCache->pFree;
    pCache->pFree = p->pNext;
    p->pNext = 0;
  }else{
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
    /* The group mutex must be released before pcache1Alloc() is called. This
    ** is because it might call sqlite3_release_memory(), which assumes that 
    ** this mutex is not held. */
    assert( pcache1.separateCache==0 );
    assert( pCache->pGroup==&pcache1.grp );
    pcache1LeaveMutex(pCache->pGroup);
#endif
    if( benignMalloc ){ sqlite3BeginBenignMalloc(); }
#ifdef SQLITE_PCACHE_SEPARATE_HEADER
    pPg = pcache1Alloc(pCache->szPage);
    p = sqlite3Malloc(sizeof(PgHdr1) + pCache->szExtra);
    if( !pPg || !p ){
      pcache1Free(pPg);
      sqlite3_free(p);
      pPg = 0;
    }
#else
    pPg = pcache1Alloc(pCache->szAlloc);
    p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
#endif
    if( benignMalloc ){ sqlite3EndBenignMalloc(); }
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
    pcache1EnterMutex(pCache->pGroup);
#endif
    if( pPg==0 ) return 0;
    p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
    p->page.pBuf = pPg;
    p->page.pExtra = &p[1];
    p->isBulkLocal = 0;
    p->isAnchor = 0;
    p->pLruPrev = 0;           /* Initializing this saves a valgrind error */
  }
  (*pCache->pnPurgeable)++;
  return p;
}

/*
** Free a page object allocated by pcache1AllocPage().
*/
static void pcache1FreePage(PgHdr1 *p){
  PCache1 *pCache;
  assert( p!=0 );
  pCache = p->pCache;
  assert( sqlite3_mutex_held(p->pCache->pGroup->mutex) );
  if( p->isBulkLocal ){
    p->pNext = pCache->pFree;
    pCache->pFree = p;
  }else{
    pcache1Free(p->page.pBuf);
#ifdef SQLITE_PCACHE_SEPARATE_HEADER
    sqlite3_free(p);
#endif
  }
  (*pCache->pnPurgeable)--;
}

/*
** Malloc function used by SQLite to obtain space from the buffer configured
** using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no such buffer
** exists, this function falls back to sqlite3Malloc().
*/
void *sqlite3PageMalloc(int sz){
  /* During rebalance operations on a corrupt database file, it is sometimes
  ** (rarely) possible to overread the temporary page buffer by a few bytes.
  ** Enlarge the allocation slightly so that this does not cause problems. */
  assert( sz<=65536+8 ); /* These allocations are never very large */
  return pcache1Alloc(sz);
}

/*
** Free an allocated buffer obtained from sqlite3PageMalloc().
*/
void sqlite3PageFree(void *p){
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
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







+









-







-
-
+

















+
+



+
+
+
+
-
+

-
+















-
+







  if( pCache ){
    if( pcache1.separateCache ){
      pGroup = (PGroup*)&pCache[1];
      pGroup->mxPinned = 10;
    }else{
      pGroup = &pcache1.grp;
    }
    pcache1EnterMutex(pGroup);
    if( pGroup->lru.isAnchor==0 ){
      pGroup->lru.isAnchor = 1;
      pGroup->lru.pLruPrev = pGroup->lru.pLruNext = &pGroup->lru;
    }
    pCache->pGroup = pGroup;
    pCache->szPage = szPage;
    pCache->szExtra = szExtra;
    pCache->szAlloc = szPage + szExtra + ROUND8(sizeof(PgHdr1));
    pCache->bPurgeable = (bPurgeable ? 1 : 0);
    pcache1EnterMutex(pGroup);
    pcache1ResizeHash(pCache);
    if( bPurgeable ){
      pCache->nMin = 10;
      pGroup->nMinPage += pCache->nMin;
      pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
      pCache->pnPurgeable = &pGroup->nPurgeable;
    }else{
      static unsigned int dummyCurrentPage;
      pCache->pnPurgeable = &dummyCurrentPage;
      pCache->pnPurgeable = &pCache->nPurgeableDummy;
    }
    pcache1LeaveMutex(pGroup);
    if( pCache->nHash==0 ){
      pcache1Destroy((sqlite3_pcache*)pCache);
      pCache = 0;
    }
  }
  return (sqlite3_pcache *)pCache;
}

/*
** Implementation of the sqlite3_pcache.xCachesize method. 
**
** Configure the cache_size limit for a cache.
*/
static void pcache1Cachesize(sqlite3_pcache *p, int nMax){
  PCache1 *pCache = (PCache1 *)p;
  u32 n;
  assert( nMax>=0 );
  if( pCache->bPurgeable ){
    PGroup *pGroup = pCache->pGroup;
    pcache1EnterMutex(pGroup);
    n = (u32)nMax;
    if( n > 0x7fff0000 - pGroup->nMaxPage + pCache->nMax ){
      n = 0x7fff0000 - pGroup->nMaxPage + pCache->nMax;
    }
    pGroup->nMaxPage += (nMax - pCache->nMax);
    pGroup->nMaxPage += (n - pCache->nMax);
    pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
    pCache->nMax = nMax;
    pCache->nMax = n;
    pCache->n90pct = pCache->nMax*9/10;
    pcache1EnforceMaxPage(pCache);
    pcache1LeaveMutex(pGroup);
  }
}

/*
** Implementation of the sqlite3_pcache.xShrink method. 
**
** Free up as much memory as possible.
*/
static void pcache1Shrink(sqlite3_pcache *p){
  PCache1 *pCache = (PCache1*)p;
  if( pCache->bPurgeable ){
    PGroup *pGroup = pCache->pGroup;
    int savedMaxPage;
    unsigned int savedMaxPage;
    pcache1EnterMutex(pGroup);
    savedMaxPage = pGroup->nMaxPage;
    pGroup->nMaxPage = 0;
    pcache1EnforceMaxPage(pCache);
    pGroup->nMaxPage = savedMaxPage;
    pcache1LeaveMutex(pGroup);
  }
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
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







-
+


+



+
-
-
+
+





+
-
+

-
-
+
+







  sqlite3_pcache_page *pPg,
  unsigned int iOld,
  unsigned int iNew
){
  PCache1 *pCache = (PCache1 *)p;
  PgHdr1 *pPage = (PgHdr1 *)pPg;
  PgHdr1 **pp;
  unsigned int h; 
  unsigned int hOld, hNew; 
  assert( pPage->iKey==iOld );
  assert( pPage->pCache==pCache );
  assert( iOld!=iNew );               /* The page number really is changing */

  pcache1EnterMutex(pCache->pGroup);

  assert( pcache1FetchNoMutex(p, iOld, 0)==pPage ); /* pPg really is iOld */
  h = iOld%pCache->nHash;
  pp = &pCache->apHash[h];
  hOld = iOld%pCache->nHash;
  pp = &pCache->apHash[hOld];
  while( (*pp)!=pPage ){
    pp = &(*pp)->pNext;
  }
  *pp = pPage->pNext;

  assert( pcache1FetchNoMutex(p, iNew, 0)==0 ); /* iNew not in cache */
  h = iNew%pCache->nHash;
  hNew = iNew%pCache->nHash;
  pPage->iKey = iNew;
  pPage->pNext = pCache->apHash[h];
  pCache->apHash[h] = pPage;
  pPage->pNext = pCache->apHash[hNew];
  pCache->apHash[hNew] = pPage;
  if( iNew>pCache->iMaxKey ){
    pCache->iMaxKey = iNew;
  }

  pcache1LeaveMutex(pCache->pGroup);
}

1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1241
1242
1243
1244
1245
1246
1247



1248
1249
1250
1251
1252
1253
1254







-
-
-







    PgHdr1 *p;
    pcache1EnterMutex(&pcache1.grp);
    while( (nReq<0 || nFree<nReq)
       &&  (p=pcache1.grp.lru.pLruPrev)!=0
       &&  p->isAnchor==0
    ){
      nFree += pcache1MemSize(p->page.pBuf);
#ifdef SQLITE_PCACHE_SEPARATE_HEADER
      nFree += sqlite3MemSize(p);
#endif
      assert( PAGE_IS_UNPINNED(p) );
      pcache1PinPage(p);
      pcache1RemoveFromHash(p, 1);
    }
    pcache1LeaveMutex(&pcache1.grp);
  }
  return nFree;

Changes to src/pragma.c.

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
142
143







-
+
+
+







/*
** Invalidate temp storage, either when the temp storage is changed
** from default, or when 'file' and the temp_store_directory has changed
*/
static int invalidateTempStorage(Parse *pParse){
  sqlite3 *db = pParse->db;
  if( db->aDb[1].pBt!=0 ){
    if( !db->autoCommit || sqlite3BtreeIsInReadTrans(db->aDb[1].pBt) ){
    if( !db->autoCommit
     || sqlite3BtreeTxnState(db->aDb[1].pBt)!=SQLITE_TXN_NONE
    ){
      sqlite3ErrorMsg(pParse, "temporary storage cannot be changed "
        "from within a transaction");
      return SQLITE_ERROR;
    }
    sqlite3BtreeClose(db->aDb[1].pBt);
    db->aDb[1].pBt = 0;
    sqlite3ResetAllSchemasOfConnection(db);
256
257
258
259
260
261
262
263

264
265
266
267
268
269
270
271

272
273
274
275
276
277
278
258
259
260
261
262
263
264

265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281







-
+








+







** defined in pager.h. This function returns the associated lowercase
** journal-mode name.
*/
const char *sqlite3JournalModename(int eMode){
  static char * const azModeName[] = {
    "delete", "persist", "off", "truncate", "memory"
#ifndef SQLITE_OMIT_WAL
     , "wal"
     , "wal", "wal2"
#endif
  };
  assert( PAGER_JOURNALMODE_DELETE==0 );
  assert( PAGER_JOURNALMODE_PERSIST==1 );
  assert( PAGER_JOURNALMODE_OFF==2 );
  assert( PAGER_JOURNALMODE_TRUNCATE==3 );
  assert( PAGER_JOURNALMODE_MEMORY==4 );
  assert( PAGER_JOURNALMODE_WAL==5 );
  assert( PAGER_JOURNALMODE_WAL2==6 );
  assert( eMode>=0 && eMode<=ArraySize(azModeName) );

  if( eMode==ArraySize(azModeName) ) return 0;
  return azModeName[eMode];
}

/*
290
291
292
293
294
295
296


















































297
298
299
300
301
302
303
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







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







      upr = mid - 1;
    }else{
      lwr = mid + 1;
    }
  }
  return lwr>upr ? 0 : &aPragmaName[mid];
}

/*
** Create zero or more entries in the output for the SQL functions
** defined by FuncDef p.
*/
static void pragmaFunclistLine(
  Vdbe *v,               /* The prepared statement being created */
  FuncDef *p,            /* A particular function definition */
  int isBuiltin,         /* True if this is a built-in function */
  int showInternFuncs    /* True if showing internal functions */
){
  u32 mask = 
      SQLITE_DETERMINISTIC |
      SQLITE_DIRECTONLY |
      SQLITE_SUBTYPE |
      SQLITE_INNOCUOUS |
      SQLITE_FUNC_INTERNAL
  ;
  if( showInternFuncs ) mask = 0xffffffff;
  for(; p; p=p->pNext){
    const char *zType;
    static const char *azEnc[] = { 0, "utf8", "utf16le", "utf16be" };

    assert( SQLITE_FUNC_ENCMASK==0x3 );
    assert( strcmp(azEnc[SQLITE_UTF8],"utf8")==0 );
    assert( strcmp(azEnc[SQLITE_UTF16LE],"utf16le")==0 );
    assert( strcmp(azEnc[SQLITE_UTF16BE],"utf16be")==0 );

    if( p->xSFunc==0 ) continue;
    if( (p->funcFlags & SQLITE_FUNC_INTERNAL)!=0
     && showInternFuncs==0
    ){
      continue;
    }    
    if( p->xValue!=0 ){
      zType = "w";
    }else if( p->xFinalize!=0 ){
      zType = "a";
    }else{
      zType = "s";
    }
    sqlite3VdbeMultiLoad(v, 1, "sissii",
       p->zName, isBuiltin,
       zType, azEnc[p->funcFlags&SQLITE_FUNC_ENCMASK],
       p->nArg,
       (p->funcFlags & mask) ^ SQLITE_INNOCUOUS
    );
  }
}


/*
** Helper subroutine for PRAGMA integrity_check:
**
** Generate code to output a single-column result row with a value of the
** string held in register 3.  Decrement the result count in register 1
** and halt if the maximum number of result rows have been issued.
412
413
414
415
416
417
418
419





420
421
422
423
424
425
426
465
466
467
468
469
470
471

472
473
474
475
476
477
478
479
480
481
482
483







-
+
+
+
+
+







    pParse->nErr++;
    pParse->rc = rc;
    goto pragma_out;
  }

  /* Locate the pragma in the lookup table */
  pPragma = pragmaLocate(zLeft);
  if( pPragma==0 ) goto pragma_out;
  if( pPragma==0 ){
    /* IMP: R-43042-22504 No error messages are generated if an
    ** unknown pragma is issued. */
    goto pragma_out;
  }

  /* Make sure the database schema is loaded if the pragma requires that */
  if( (pPragma->mPragFlg & PragFlg_NeedSchema)!=0 ){
    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
  }

  /* Register the result column names for pragmas that return results */
502
503
504
505
506
507
508
509

510
511
512
513
514
515
516
559
560
561
562
563
564
565

566
567
568
569
570
571
572
573







-
+







      int size = ALWAYS(pBt) ? sqlite3BtreeGetPageSize(pBt) : 0;
      returnSingleInt(v, size);
    }else{
      /* Malloc may fail when setting the page-size, as there is an internal
      ** buffer that the pager module resizes using sqlite3_realloc().
      */
      db->nextPagesize = sqlite3Atoi(zRight);
      if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize,-1,0) ){
      if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize,0,0) ){
        sqlite3OomFault(db);
      }
    }
    break;
  }

  /*
558
559
560
561
562
563
564

565
566
567
568
569






570

571
572
573
574
575
576
577
578
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







+





+
+
+
+
+
+
-
+
-







  **
  **  PRAGMA [schema.]page_count
  **
  ** Return the number of pages in the specified database.
  */
  case PragTyp_PAGE_COUNT: {
    int iReg;
    i64 x = 0;
    sqlite3CodeVerifySchema(pParse, iDb);
    iReg = ++pParse->nMem;
    if( sqlite3Tolower(zLeft[0])=='p' ){
      sqlite3VdbeAddOp2(v, OP_Pagecount, iDb, iReg);
    }else{
      if( zRight && sqlite3DecOrHexToI64(zRight,&x)==0 ){
        if( x<0 ) x = 0;
        else if( x>0xfffffffe ) x = 0xfffffffe;
      }else{
        x = 0;
      }
      sqlite3VdbeAddOp3(v, OP_MaxPgcnt, iDb, iReg, 
      sqlite3VdbeAddOp3(v, OP_MaxPgcnt, iDb, iReg, (int)x);
                        sqlite3AbsInt32(sqlite3Atoi(zRight)));
    }
    sqlite3VdbeAddOp2(v, OP_ResultRow, iReg, 1);
    break;
  }

  /*
  **  PRAGMA [schema.]locking_mode
639
640
641
642
643
644
645





646
647
648
649
650
651
652
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720







+
+
+
+
+







      for(eMode=0; (zMode = sqlite3JournalModename(eMode))!=0; eMode++){
        if( sqlite3StrNICmp(zRight, zMode, n)==0 ) break;
      }
      if( !zMode ){
        /* If the "=MODE" part does not match any known journal mode,
        ** then do a query */
        eMode = PAGER_JOURNALMODE_QUERY;
      }
      if( eMode==PAGER_JOURNALMODE_OFF && (db->flags & SQLITE_Defensive)!=0 ){
        /* Do not allow journal-mode "OFF" in defensive since the database
        ** can become corrupted using ordinary SQL when the journal is off */
        eMode = PAGER_JOURNALMODE_QUERY;
      }
    }
    if( eMode==PAGER_JOURNALMODE_QUERY && pId2->n==0 ){
      /* Convert "PRAGMA journal_mode" into "PRAGMA main.journal_mode" */
      iDb = 0;
      pId2->n = 1;
    }
737
738
739
740
741
742
743
744

745
746
747
748
749
750
751
805
806
807
808
809
810
811

812
813
814
815
816
817
818
819







-
+







  /*
  **  PRAGMA [schema.]incremental_vacuum(N)
  **
  ** Do N steps of incremental vacuuming on a database.
  */
#ifndef SQLITE_OMIT_AUTOVACUUM
  case PragTyp_INCREMENTAL_VACUUM: {
    int iLimit, addr;
    int iLimit = 0, addr;
    if( zRight==0 || !sqlite3GetInt32(zRight, &iLimit) || iLimit<=0 ){
      iLimit = 0x7fffffff;
    }
    sqlite3BeginWriteOperation(pParse, 0, iDb);
    sqlite3VdbeAddOp2(v, OP_Integer, iLimit, 1);
    addr = sqlite3VdbeAddOp1(v, OP_IncrVacuum, iDb); VdbeCoverage(v);
    sqlite3VdbeAddOp1(v, OP_ResultRow, 1);
894
895
896
897
898
899
900

901
902
903
904
905
906
907
908
909

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

927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944

945
946
947
948
949
950
951
952
953

954
955
956
957
958
959
960
961
962
963
964

965
966
967
968
969
970
971
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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







+









+

















+


















+









+











+







  ** Return or set the local value of the temp_store_directory flag.  Changing
  ** the value sets a specific directory to be used for temporary files.
  ** Setting to a null string reverts to the default temporary directory search.
  ** If temporary directory is changed, then invalidateTempStorage.
  **
  */
  case PragTyp_TEMP_STORE_DIRECTORY: {
    sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
    if( !zRight ){
      returnSingleText(v, sqlite3_temp_directory);
    }else{
#ifndef SQLITE_OMIT_WSD
      if( zRight[0] ){
        int res;
        rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res);
        if( rc!=SQLITE_OK || res==0 ){
          sqlite3ErrorMsg(pParse, "not a writable directory");
          sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
          goto pragma_out;
        }
      }
      if( SQLITE_TEMP_STORE==0
       || (SQLITE_TEMP_STORE==1 && db->temp_store<=1)
       || (SQLITE_TEMP_STORE==2 && db->temp_store==1)
      ){
        invalidateTempStorage(pParse);
      }
      sqlite3_free(sqlite3_temp_directory);
      if( zRight[0] ){
        sqlite3_temp_directory = sqlite3_mprintf("%s", zRight);
      }else{
        sqlite3_temp_directory = 0;
      }
#endif /* SQLITE_OMIT_WSD */
    }
    sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
    break;
  }

#if SQLITE_OS_WIN
  /*
  **   PRAGMA data_store_directory
  **   PRAGMA data_store_directory = ""|"directory_name"
  **
  ** Return or set the local value of the data_store_directory flag.  Changing
  ** the value sets a specific directory to be used for database files that
  ** were specified with a relative pathname.  Setting to a null string reverts
  ** to the default database directory, which for database files specified with
  ** a relative path will probably be based on the current directory for the
  ** process.  Database file specified with an absolute path are not impacted
  ** by this setting, regardless of its value.
  **
  */
  case PragTyp_DATA_STORE_DIRECTORY: {
    sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
    if( !zRight ){
      returnSingleText(v, sqlite3_data_directory);
    }else{
#ifndef SQLITE_OMIT_WSD
      if( zRight[0] ){
        int res;
        rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res);
        if( rc!=SQLITE_OK || res==0 ){
          sqlite3ErrorMsg(pParse, "not a writable directory");
          sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
          goto pragma_out;
        }
      }
      sqlite3_free(sqlite3_data_directory);
      if( zRight[0] ){
        sqlite3_data_directory = sqlite3_mprintf("%s", zRight);
      }else{
        sqlite3_data_directory = 0;
      }
#endif /* SQLITE_OMIT_WSD */
    }
    sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
    break;
  }
#endif

#if SQLITE_ENABLE_LOCKING_STYLE
  /*
  **   PRAGMA [schema.]lock_proxy_file
1051
1052
1053
1054
1055
1056
1057








1058
1059
1060
1061
1062
1063
1064
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146







+
+
+
+
+
+
+
+







#endif

      if( sqlite3GetBoolean(zRight, 0) ){
        db->flags |= mask;
      }else{
        db->flags &= ~mask;
        if( mask==SQLITE_DeferFKs ) db->nDeferredImmCons = 0;
        if( (mask & SQLITE_WriteSchema)!=0
         && sqlite3_stricmp(zRight, "reset")==0
        ){
          /* IMP: R-60817-01178 If the argument is "RESET" then schema
          ** writing is disabled (as with "PRAGMA writable_schema=OFF") and,
          ** in addition, the schema is reloaded. */
          sqlite3ResetAllSchemasOfConnection(db);
        }
      }

      /* Many of the flag-pragmas modify the code generated by the SQL 
      ** compiler (eg. count_changes). So add an opcode to expire all
      ** compiled SQL statements after modifying a pragma value.
      */
      sqlite3VdbeAddOp0(v, OP_Expire);
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
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
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







+


-





-


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








+
-
+
+
+


-
+


-
+




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












-
+







  ** type:       Column declaration type.
  ** notnull:    True if 'NOT NULL' is part of column declaration
  ** dflt_value: The default value for the column, if any.
  ** pk:         Non-zero for PK fields.
  */
  case PragTyp_TABLE_INFO: if( zRight ){
    Table *pTab;
    sqlite3CodeVerifyNamedSchema(pParse, zDb);
    pTab = sqlite3LocateTable(pParse, LOCATE_NOERR, zRight, zDb);
    if( pTab ){
      int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
      int i, k;
      int nHidden = 0;
      Column *pCol;
      Index *pPk = sqlite3PrimaryKeyIndex(pTab);
      pParse->nMem = 7;
      sqlite3CodeVerifySchema(pParse, iTabDb);
      sqlite3ViewGetColumnNames(pParse, pTab);
      for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
        int isHidden = IsHiddenColumn(pCol);
        if( isHidden && pPragma->iArg==0 ){
          nHidden++;
          continue;
        int isHidden = 0;
        const Expr *pColExpr;
        if( pCol->colFlags & COLFLAG_NOINSERT ){
          if( pPragma->iArg==0 ){
            nHidden++;
            continue;
          }
          if( pCol->colFlags & COLFLAG_VIRTUAL ){
            isHidden = 2;  /* GENERATED ALWAYS AS ... VIRTUAL */
          }else if( pCol->colFlags & COLFLAG_STORED ){
            isHidden = 3;  /* GENERATED ALWAYS AS ... STORED */
          }else{ assert( pCol->colFlags & COLFLAG_HIDDEN );
            isHidden = 1;  /* HIDDEN */
          }
        }
        if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){
          k = 0;
        }else if( pPk==0 ){
          k = 1;
        }else{
          for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){}
        }
        pColExpr = sqlite3ColumnExpr(pTab,pCol);
        assert( pCol->pDflt==0 || pCol->pDflt->op==TK_SPAN );
        assert( pColExpr==0 || pColExpr->op==TK_SPAN || isHidden>=2 );
        assert( pColExpr==0 || !ExprHasProperty(pColExpr, EP_IntValue)
                  || isHidden>=2 );
        sqlite3VdbeMultiLoad(v, 1, pPragma->iArg ? "issisii" : "issisi",
               i-nHidden,
               pCol->zName,
               pCol->zCnName,
               sqlite3ColumnType(pCol,""),
               pCol->notNull ? 1 : 0,
               pCol->pDflt ? pCol->pDflt->u.zToken : 0,
               (isHidden>=2 || pColExpr==0) ? 0 : pColExpr->u.zToken,
               k,
               isHidden);
      }
    }
  }
  break;

  /*
  **   PRAGMA table_list
  **
  ** Return a single row for each table, virtual table, or view in the
  ** entire schema.
  **
  ** schema:     Name of attached database hold this table
  ** name:       Name of the table itself
  ** type:       "table", "view", "virtual", "shadow"
  ** ncol:       Number of columns
  ** wr:         True for a WITHOUT ROWID table
  ** strict:     True for a STRICT table
  */
  case PragTyp_TABLE_LIST: {
    int ii;
    pParse->nMem = 6;
    sqlite3CodeVerifyNamedSchema(pParse, zDb);
    for(ii=0; ii<db->nDb; ii++){
      HashElem *k;
      Hash *pHash;
      int initNCol;
      if( zDb && sqlite3_stricmp(zDb, db->aDb[ii].zDbSName)!=0 ) continue;

      /* Ensure that the Table.nCol field is initialized for all views
      ** and virtual tables.  Each time we initialize a Table.nCol value
      ** for a table, that can potentially disrupt the hash table, so restart
      ** the initialization scan.
      */
      pHash = &db->aDb[ii].pSchema->tblHash;
      initNCol = sqliteHashCount(pHash);
      while( initNCol-- ){
        for(k=sqliteHashFirst(pHash); 1; k=sqliteHashNext(k) ){
          Table *pTab;
          if( k==0 ){ initNCol = 0; break; }
          pTab = sqliteHashData(k);
          if( pTab->nCol==0 ){
            char *zSql = sqlite3MPrintf(db, "SELECT*FROM\"%w\"", pTab->zName);
            if( zSql ){
              sqlite3_stmt *pDummy = 0;
              (void)sqlite3_prepare(db, zSql, -1, &pDummy, 0);
              (void)sqlite3_finalize(pDummy);
              sqlite3DbFree(db, zSql);
            }
            if( db->mallocFailed ){
              sqlite3ErrorMsg(db->pParse, "out of memory");
              db->pParse->rc = SQLITE_NOMEM_BKPT;
            }
            pHash = &db->aDb[ii].pSchema->tblHash;
            break;
          }
        }
      }

      for(k=sqliteHashFirst(pHash); k; k=sqliteHashNext(k) ){
        Table *pTab = sqliteHashData(k);
        const char *zType;
        if( zRight && sqlite3_stricmp(zRight, pTab->zName)!=0 ) continue;
        if( IsView(pTab) ){
          zType = "view";
        }else if( IsVirtual(pTab) ){
          zType = "virtual";
        }else if( pTab->tabFlags & TF_Shadow ){
          zType = "shadow";
        }else{
          zType = "table";
        }
        sqlite3VdbeMultiLoad(v, 1, "sssiii",
           db->aDb[ii].zDbSName,
           sqlite3PreferredTableName(pTab->zName),
           zType,
           pTab->nCol,
           (pTab->tabFlags & TF_WithoutRowid)!=0,
           (pTab->tabFlags & TF_Strict)!=0
        );
      }
    }
  }
  break;

#ifdef SQLITE_DEBUG
  case PragTyp_STATS: {
    Index *pIdx;
    HashElem *i;
    pParse->nMem = 5;
    sqlite3CodeVerifySchema(pParse, iDb);
    for(i=sqliteHashFirst(&pDb->pSchema->tblHash); i; i=sqliteHashNext(i)){
      Table *pTab = sqliteHashData(i);
      sqlite3VdbeMultiLoad(v, 1, "ssiii",
           pTab->zName,
           sqlite3PreferredTableName(pTab->zName),
           0,
           pTab->szTabRow,
           pTab->nRowLogEst,
           pTab->tabFlags);
      for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
        sqlite3VdbeMultiLoad(v, 2, "siiiX",
           pIdx->zName,
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
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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







+
+
+
+
+
+
+
+
+



















-
+







  break;
#endif

  case PragTyp_INDEX_INFO: if( zRight ){
    Index *pIdx;
    Table *pTab;
    pIdx = sqlite3FindIndex(db, zRight, zDb);
    if( pIdx==0 ){
      /* If there is no index named zRight, check to see if there is a
      ** WITHOUT ROWID table named zRight, and if there is, show the
      ** structure of the PRIMARY KEY index for that table. */
      pTab = sqlite3LocateTable(pParse, LOCATE_NOERR, zRight, zDb);
      if( pTab && !HasRowid(pTab) ){
        pIdx = sqlite3PrimaryKeyIndex(pTab);
      }
    }
    if( pIdx ){
      int iIdxDb = sqlite3SchemaToIndex(db, pIdx->pSchema);
      int i;
      int mx;
      if( pPragma->iArg ){
        /* PRAGMA index_xinfo (newer version with more rows and columns) */
        mx = pIdx->nColumn;
        pParse->nMem = 6;
      }else{
        /* PRAGMA index_info (legacy version) */
        mx = pIdx->nKeyCol;
        pParse->nMem = 3;
      }
      pTab = pIdx->pTable;
      sqlite3CodeVerifySchema(pParse, iIdxDb);
      assert( pParse->nMem<=pPragma->nPragCName );
      for(i=0; i<mx; i++){
        i16 cnum = pIdx->aiColumn[i];
        sqlite3VdbeMultiLoad(v, 1, "iisX", i, cnum,
                             cnum<0 ? 0 : pTab->aCol[cnum].zName);
                             cnum<0 ? 0 : pTab->aCol[cnum].zCnName);
        if( pPragma->iArg ){
          sqlite3VdbeMultiLoad(v, 4, "isiX",
            pIdx->aSortOrder[i],
            pIdx->azColl[i],
            i<pIdx->nKeyCol);
        }
        sqlite3VdbeAddOp2(v, OP_ResultRow, 1, pParse->nMem);
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
1409
1410
1411
1412
1413
1414
1415

1416
1417
1418
1419
1420
1421

1422
1423
1424

1425

1426
1427
1428
1429
1430

1431
1432
1433
1434
1435
1436
1437
1438
1439







-
+




+
-
+


-
+
-
+




-
+
+







    for(p=sqliteHashFirst(&db->aCollSeq); p; p=sqliteHashNext(p)){
      CollSeq *pColl = (CollSeq *)sqliteHashData(p);
      sqlite3VdbeMultiLoad(v, 1, "is", i++, pColl->zName);
    }
  }
  break;

#ifdef SQLITE_INTROSPECTION_PRAGMAS
#ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS
  case PragTyp_FUNCTION_LIST: {
    int i;
    HashElem *j;
    FuncDef *p;
    int showInternFunc = (db->mDbFlags & DBFLAG_InternalFunc)!=0;
    pParse->nMem = 2;
    pParse->nMem = 6;
    for(i=0; i<SQLITE_FUNC_HASH_SZ; i++){
      for(p=sqlite3BuiltinFunctions.a[i]; p; p=p->u.pHash ){
        if( p->funcFlags & SQLITE_FUNC_INTERNAL ) continue;
        assert( p->funcFlags & SQLITE_FUNC_BUILTIN );
        sqlite3VdbeMultiLoad(v, 1, "si", p->zName, 1);
        pragmaFunclistLine(v, p, 1, showInternFunc);
      }
    }
    for(j=sqliteHashFirst(&db->aFunc); j; j=sqliteHashNext(j)){
      p = (FuncDef*)sqliteHashData(j);
      sqlite3VdbeMultiLoad(v, 1, "si", p->zName, 0);
      assert( (p->funcFlags & SQLITE_FUNC_BUILTIN)==0 );
      pragmaFunclistLine(v, p, 0, showInternFunc);
    }
  }
  break;

#ifndef SQLITE_OMIT_VIRTUALTABLE
  case PragTyp_MODULE_LIST: {
    HashElem *j;
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
1458
1459
1460
1461
1462
1463
1464


1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478

1479
1480
1481
1482
1483
1484
1485
1486







-
-
+
+












-
+







#endif /* SQLITE_OMIT_SCHEMA_PRAGMAS */

#ifndef SQLITE_OMIT_FOREIGN_KEY
  case PragTyp_FOREIGN_KEY_LIST: if( zRight ){
    FKey *pFK;
    Table *pTab;
    pTab = sqlite3FindTable(db, zRight, zDb);
    if( pTab ){
      pFK = pTab->pFKey;
    if( pTab && IsOrdinaryTable(pTab) ){
      pFK = pTab->u.tab.pFKey;
      if( pFK ){
        int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
        int i = 0; 
        pParse->nMem = 8;
        sqlite3CodeVerifySchema(pParse, iTabDb);
        while(pFK){
          int j;
          for(j=0; j<pFK->nCol; j++){
            sqlite3VdbeMultiLoad(v, 1, "iissssss",
                   i,
                   j,
                   pFK->zTo,
                   pTab->aCol[pFK->aCol[j].iFrom].zName,
                   pTab->aCol[pFK->aCol[j].iFrom].zCnName,
                   pFK->aCol[j].zCol,
                   actionName(pFK->aAction[1]),  /* ON UPDATE */
                   actionName(pFK->aAction[0]),  /* ON DELETE */
                   "NONE");
          }
          ++i;
          pFK = pFK->pNextFrom;
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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
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
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
1574
1575
1576
1577
1578

1579
1580

1581
1582
1583
1584
1585
1586

1587
1588
1589
1590
1591
1592
1593
1594







-







-



-







-
-
-
-
+
+
+
+
+

-
+

+
-
+



-
+



-
+

-
+











+
-
+





-
+

-
+





+









-
+

-
+





-
+







    Table *pParent;        /* Parent table that child points to */
    Index *pIdx;           /* Index in the parent table */
    int i;                 /* Loop counter:  Foreign key number for pTab */
    int j;                 /* Loop counter:  Field of the foreign key */
    HashElem *k;           /* Loop counter:  Next table in schema */
    int x;                 /* result variable */
    int regResult;         /* 3 registers to hold a result row */
    int regKey;            /* Register to hold key for checking the FK */
    int regRow;            /* Registers to hold a row from pTab */
    int addrTop;           /* Top of a loop checking foreign keys */
    int addrOk;            /* Jump here if the key is OK */
    int *aiCols;           /* child to parent column mapping */

    regResult = pParse->nMem+1;
    pParse->nMem += 4;
    regKey = ++pParse->nMem;
    regRow = ++pParse->nMem;
    k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash);
    while( k ){
      int iTabDb;
      if( zRight ){
        pTab = sqlite3LocateTable(pParse, 0, zRight, zDb);
        k = 0;
      }else{
        pTab = (Table*)sqliteHashData(k);
        k = sqliteHashNext(k);
      }
      if( pTab==0 || pTab->pFKey==0 ) continue;
      iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
      sqlite3CodeVerifySchema(pParse, iTabDb);
      sqlite3TableLock(pParse, iTabDb, pTab->tnum, 0, pTab->zName);
      if( pTab==0 || !IsOrdinaryTable(pTab) || pTab->u.tab.pFKey==0 ) continue;
      iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
      zDb = db->aDb[iDb].zDbSName;
      sqlite3CodeVerifySchema(pParse, iDb);
      sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
      if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow;
      sqlite3OpenTable(pParse, 0, iTabDb, pTab, OP_OpenRead);
      sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead);
      sqlite3VdbeLoadString(v, regResult, pTab->zName);
      assert( IsOrdinaryTable(pTab) );
      for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
      for(i=1, pFK=pTab->u.tab.pFKey; pFK; i++, pFK=pFK->pNextFrom){
        pParent = sqlite3FindTable(db, pFK->zTo, zDb);
        if( pParent==0 ) continue;
        pIdx = 0;
        sqlite3TableLock(pParse, iTabDb, pParent->tnum, 0, pParent->zName);
        sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName);
        x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0);
        if( x==0 ){
          if( pIdx==0 ){
            sqlite3OpenTable(pParse, i, iTabDb, pParent, OP_OpenRead);
            sqlite3OpenTable(pParse, i, iDb, pParent, OP_OpenRead);
          }else{
            sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iTabDb);
            sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb);
            sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
          }
        }else{
          k = 0;
          break;
        }
      }
      assert( pParse->nErr>0 || pFK==0 );
      if( pFK ) break;
      if( pParse->nTab<i ) pParse->nTab = i;
      addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); VdbeCoverage(v);
      assert( IsOrdinaryTable(pTab) );
      for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
      for(i=1, pFK=pTab->u.tab.pFKey; pFK; i++, pFK=pFK->pNextFrom){
        pParent = sqlite3FindTable(db, pFK->zTo, zDb);
        pIdx = 0;
        aiCols = 0;
        if( pParent ){
          x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols);
          assert( x==0 );
          assert( x==0 || db->mallocFailed );
        }
        addrOk = sqlite3VdbeMakeLabel(v);
        addrOk = sqlite3VdbeMakeLabel(pParse);

        /* Generate code to read the child key values into registers
        ** regRow..regRow+n. If any of the child key values are NULL, this 
        ** row cannot cause an FK violation. Jump directly to addrOk in 
        ** this case. */
        if( regRow+pFK->nCol>pParse->nMem ) pParse->nMem = regRow+pFK->nCol;
        for(j=0; j<pFK->nCol; j++){
          int iCol = aiCols ? aiCols[j] : pFK->aCol[j].iFrom;
          sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, iCol, regRow+j);
          sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); VdbeCoverage(v);
        }

        /* Generate code to query the parent index for a matching parent
        ** key. If a match is found, jump to addrOk. */
        if( pIdx ){
          sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, pFK->nCol, regKey,
          sqlite3VdbeAddOp4(v, OP_Affinity, regRow, pFK->nCol, 0,
              sqlite3IndexAffinityStr(db,pIdx), pFK->nCol);
          sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
          sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regRow, pFK->nCol);
          VdbeCoverage(v);
        }else if( pParent ){
          int jmp = sqlite3VdbeCurrentAddr(v)+2;
          sqlite3VdbeAddOp3(v, OP_SeekRowid, i, jmp, regRow); VdbeCoverage(v);
          sqlite3VdbeGoto(v, addrOk);
          assert( pFK->nCol==1 );
          assert( pFK->nCol==1 || db->mallocFailed );
        }

        /* Generate code to report an FK violation to the caller. */
        if( HasRowid(pTab) ){
          sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1);
        }else{
          sqlite3VdbeAddOp2(v, OP_Null, 0, regResult+1);
1417
1418
1419
1420
1421
1422
1423
1424

1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445

1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462












1463
1464
1465

1466
1467
1468
1469
1470
1471
1472
1602
1603
1604
1605
1606
1607
1608

1609












1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659







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









+

















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



+







      sqlite3VdbeJumpHere(v, addrTop);
    }
  }
  break;
#endif /* !defined(SQLITE_OMIT_TRIGGER) */
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */

#ifndef NDEBUG
#ifndef SQLITE_OMIT_CASE_SENSITIVE_LIKE_PRAGMA
  case PragTyp_PARSER_TRACE: {
    if( zRight ){
      if( sqlite3GetBoolean(zRight, 0) ){
        sqlite3ParserTrace(stdout, "parser: ");
      }else{
        sqlite3ParserTrace(0, 0);
      }
    }
  }
  break;
#endif

  /* Reinstall the LIKE and GLOB functions.  The variant of LIKE
  ** used will be case sensitive or not depending on the RHS.
  */
  case PragTyp_CASE_SENSITIVE_LIKE: {
    if( zRight ){
      sqlite3RegisterLikeFunctions(db, sqlite3GetBoolean(zRight, 0));
    }
  }
  break;
#endif /* SQLITE_OMIT_CASE_SENSITIVE_LIKE_PRAGMA */

#ifndef SQLITE_INTEGRITY_CHECK_ERROR_MAX
# define SQLITE_INTEGRITY_CHECK_ERROR_MAX 100
#endif

#ifndef SQLITE_OMIT_INTEGRITY_CHECK
  /*    PRAGMA integrity_check
  **    PRAGMA integrity_check(N)
  **    PRAGMA quick_check
  **    PRAGMA quick_check(N)
  **
  ** Verify the integrity of the database.
  **
  ** The "quick_check" is reduced version of 
  ** integrity_check designed to detect most database corruption
  ** without the overhead of cross-checking indexes.  Quick_check
  ** is linear time wherease integrity_check is O(NlogN).
  **
  ** The maximum nubmer of errors is 100 by default.  A different default
  ** can be specified using a numeric parameter N.
  **
  ** Or, the parameter N can be the name of a table.  In that case, only
  ** the one table named is verified.  The freelist is only verified if
  ** the named table is "sqlite_schema" (or one of its aliases).
  **
  ** All schemas are checked by default.  To check just a single
  ** schema, use the form:
  **
  **      PRAGMA schema.integrity_check;
  */
  case PragTyp_INTEGRITY_CHECK: {
    int i, j, addr, mxErr;
    Table *pObjTab = 0;     /* Check only this one table, if not NULL */

    int isQuick = (sqlite3Tolower(zLeft[0])=='q');

    /* If the PRAGMA command was of the form "PRAGMA <db>.integrity_check",
    ** then iDb is set to the index of the database identified by <db>.
    ** In this case, the integrity of database iDb only is verified by
    ** the VDBE created below.
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490







1491
1492
1493
1494
1495
1496
1497
1668
1669
1670
1671
1672
1673
1674



1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688







-
-
-
+
+
+
+
+
+
+








    /* Initialize the VDBE program */
    pParse->nMem = 6;

    /* Set the maximum error count */
    mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
    if( zRight ){
      sqlite3GetInt32(zRight, &mxErr);
      if( mxErr<=0 ){
        mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
      if( sqlite3GetInt32(zRight, &mxErr) ){
        if( mxErr<=0 ){
          mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
        }
      }else{
        pObjTab = sqlite3LocateTable(pParse, 0, zRight,
                      iDb>=0 ? db->aDb[iDb].zDbSName : 0);
      }
    }
    sqlite3VdbeAddOp2(v, OP_Integer, mxErr-1, 1); /* reg[1] holds errors left */

    /* Do an integrity check on each database file */
    for(i=0; i<db->nDb; i++){
      HashElem *x;     /* For looping over tables in the schema */
1512
1513
1514
1515
1516
1517
1518

1519
1520
1521
1522


1523
1524


1525

1526
1527

1528
1529
1530
1531
1532
1533
1534
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







+




+
+


+
+
-
+


+







      */
      assert( sqlite3SchemaMutexHeld(db, i, 0) );
      pTbls = &db->aDb[i].pSchema->tblHash;
      for(cnt=0, x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
        Table *pTab = sqliteHashData(x);  /* Current table */
        Index *pIdx;                      /* An index on pTab */
        int nIdx;                         /* Number of indexes on pTab */
        if( pObjTab && pObjTab!=pTab ) continue;
        if( HasRowid(pTab) ) cnt++;
        for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ cnt++; }
        if( nIdx>mxIdx ) mxIdx = nIdx;
      }
      if( cnt==0 ) continue;
      if( pObjTab ) cnt++;
      aRoot = sqlite3DbMallocRawNN(db, sizeof(int)*(cnt+1));
      if( aRoot==0 ) break;
      cnt = 0;
      if( pObjTab ) aRoot[++cnt] = 0;
      for(cnt=0, x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
      for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
        Table *pTab = sqliteHashData(x);
        Index *pIdx;
        if( pObjTab && pObjTab!=pTab ) continue;
        if( HasRowid(pTab) ) aRoot[++cnt] = pTab->tnum;
        for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
          aRoot[++cnt] = pIdx->tnum;
        }
      }
      aRoot[0] = cnt;

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
1574
1575
1576
1577
1578
1579
1580






















































1581
1582





1583

1584






1585
1586
1587
1588
1589
1590
1591

























































































1592
1593

1594
1595
1596
1597
1598
1599
1600


1601
1602
1603
1604
1605
1606
1607
1745
1746
1747
1748
1749
1750
1751

1752
1753
1754
1755
1756
1757
1758
1759
1760


1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782






1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843

1844
1845
1846
1847
1848
1849
1850
1851







1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941

1942
1943
1944
1945
1946
1947


1948
1949
1950
1951
1952
1953
1954
1955
1956







-
+



+
+
+

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













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


+
+
+
+
+
-
+

+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+





-
-
+
+







      sqlite3VdbeJumpHere(v, addr);

      /* Make sure all the indices are constructed correctly.
      */
      for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
        Table *pTab = sqliteHashData(x);
        Index *pIdx, *pPk;
        Index *pPrior = 0;
        Index *pPrior = 0;      /* Previous index */
        int loopTop;
        int iDataCur, iIdxCur;
        int r1 = -1;
        int bStrict;            /* True for a STRICT table */
        int r2;                 /* Previous key for WITHOUT ROWID tables */
        int mxCol;              /* Maximum non-virtual column number */

        if( !IsOrdinaryTable(pTab) ) continue;
        if( pTab->tnum<1 ) continue;  /* Skip VIEWs or VIRTUAL TABLEs */
        pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
        if( pObjTab && pObjTab!=pTab ) continue;
        if( isQuick || HasRowid(pTab) ){
          pPk = 0;
          r2 = 0;
        }else{
          pPk = sqlite3PrimaryKeyIndex(pTab);
          r2 = sqlite3GetTempRange(pParse, pPk->nKeyCol);
          sqlite3VdbeAddOp3(v, OP_Null, 1, r2, r2+pPk->nKeyCol-1);
        }
        sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0,
                                   1, 0, &iDataCur, &iIdxCur);
        /* reg[7] counts the number of entries in the table.
        ** reg[8+i] counts the number of entries in the i-th index 
        */
        sqlite3VdbeAddOp2(v, OP_Integer, 0, 7);
        for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
          sqlite3VdbeAddOp2(v, OP_Integer, 0, 8+j); /* index entries counter */
        }
        assert( pParse->nMem>=8+j );
        assert( sqlite3NoTempsInRange(pParse,1,7+j) );
        sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0); VdbeCoverage(v);
        loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1);
        if( !isQuick ){
          /* Sanity check on record header decoding */
          sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nCol-1, 3);
          sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
        }
        /* Verify that all NOT NULL columns really are NOT NULL */

        /* Fetch the right-most column from the table.  This will cause
        ** the entire record header to be parsed and sanity checked.  It
        ** will also prepopulate the cursor column cache that is used
        ** by the OP_IsType code, so it is a required step.
        */
        assert( !IsVirtual(pTab) );
        if( HasRowid(pTab) ){
          mxCol = -1;
          for(j=0; j<pTab->nCol; j++){
            if( (pTab->aCol[j].colFlags & COLFLAG_VIRTUAL)==0 ) mxCol++;
          }
          if( mxCol==pTab->iPKey ) mxCol--;
        }else{
          /* COLFLAG_VIRTUAL columns are not included in the WITHOUT ROWID
          ** PK index column-count, so there is no need to account for them 
          ** in this case. */
          mxCol = sqlite3PrimaryKeyIndex(pTab)->nColumn-1;
        }
        if( mxCol>=0 ){
          sqlite3VdbeAddOp3(v, OP_Column, iDataCur, mxCol, 3);
          sqlite3VdbeTypeofColumn(v, 3);
        }

        if( !isQuick ){
          if( pPk ){
            /* Verify WITHOUT ROWID keys are in ascending order */
            int a1;
            char *zErr;
            a1 = sqlite3VdbeAddOp4Int(v, OP_IdxGT, iDataCur, 0,r2,pPk->nKeyCol);
            VdbeCoverage(v);
            sqlite3VdbeAddOp1(v, OP_IsNull, r2); VdbeCoverage(v);
            zErr = sqlite3MPrintf(db,
                   "row not in PRIMARY KEY order for %s",
                    pTab->zName);
            sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
            integrityCheckResultRow(v);
            sqlite3VdbeJumpHere(v, a1);
            sqlite3VdbeJumpHere(v, a1+1);
            for(j=0; j<pPk->nKeyCol; j++){
              sqlite3ExprCodeLoadIndexColumn(pParse, pPk, iDataCur, j, r2+j);
            }
          }
        }
        /* Verify datatypes for all columns:
        **
        **   (1) NOT NULL columns may not contain a NULL
        **   (2) Datatype must be exact for non-ANY columns in STRICT tables
        **   (3) Datatype for TEXT columns in non-STRICT tables must be
        **       NULL, TEXT, or BLOB.
        **   (4) Datatype for numeric columns in non-STRICT tables must not
        **       be a TEXT value that can be losslessly converted to numeric.
        */
        bStrict = (pTab->tabFlags & TF_Strict)!=0;
        for(j=0; j<pTab->nCol; j++){
          char *zErr;
          Column *pCol = pTab->aCol + j;  /* The column to be checked */
          int labelError;               /* Jump here to report an error */
          int labelOk;                  /* Jump here if all looks ok */
          int p1, p3, p4;               /* Operands to the OP_IsType opcode */
          int doTypeCheck;              /* Check datatypes (besides NOT NULL) */
          int jmp2;

          if( j==pTab->iPKey ) continue;
          if( bStrict ){
            doTypeCheck = pCol->eCType>COLTYPE_ANY;
          }else{
            doTypeCheck = pCol->affinity>SQLITE_AFF_BLOB;
          }
          if( pCol->notNull==0 && !doTypeCheck ) continue;
          if( pTab->aCol[j].notNull==0 ) continue;
          sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3);
          sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
          jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v);
          zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
                              pTab->aCol[j].zName);
          sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);

          /* Compute the operands that will be needed for OP_IsType */
          p4 = SQLITE_NULL;
          if( pCol->colFlags & COLFLAG_VIRTUAL ){
            sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3);
            p1 = -1;
            p3 = 3;
          }else{
            if( pCol->iDflt ){
              sqlite3_value *pDfltValue = 0;
              sqlite3ValueFromExpr(db, sqlite3ColumnExpr(pTab,pCol), ENC(db),
                                   pCol->affinity, &pDfltValue);
              if( pDfltValue ){
                p4 = sqlite3_value_type(pDfltValue);
                sqlite3ValueFree(pDfltValue);
              }
            }
            p1 = iDataCur;
            if( !HasRowid(pTab) ){
              testcase( j!=sqlite3TableColumnToStorage(pTab, j) );
              p3 = sqlite3TableColumnToIndex(sqlite3PrimaryKeyIndex(pTab), j);
            }else{
              p3 = sqlite3TableColumnToStorage(pTab,j);
              testcase( p3!=j);
            }
          }

          labelError = sqlite3VdbeMakeLabel(pParse);
          labelOk = sqlite3VdbeMakeLabel(pParse);
          if( pCol->notNull ){
            /* (1) NOT NULL columns may not contain a NULL */
            int jmp2 = sqlite3VdbeAddOp4Int(v, OP_IsType, p1, labelOk, p3, p4);
            sqlite3VdbeChangeP5(v, 0x0f);
            VdbeCoverage(v);
            zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
                                pCol->zCnName);
            sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
            if( doTypeCheck ){
              sqlite3VdbeGoto(v, labelError);
              sqlite3VdbeJumpHere(v, jmp2);
            }else{
              /* VDBE byte code will fall thru */
            }
          }
          if( bStrict && doTypeCheck ){
            /* (2) Datatype must be exact for non-ANY columns in STRICT tables*/
            static unsigned char aStdTypeMask[] = {
               0x1f,    /* ANY */
               0x18,    /* BLOB */
               0x11,    /* INT */
               0x11,    /* INTEGER */
               0x13,    /* REAL */
               0x14     /* TEXT */
            };
            sqlite3VdbeAddOp4Int(v, OP_IsType, p1, labelOk, p3, p4);
            assert( pCol->eCType>=1 && pCol->eCType<=sizeof(aStdTypeMask) );
            sqlite3VdbeChangeP5(v, aStdTypeMask[pCol->eCType-1]);
            VdbeCoverage(v);
            zErr = sqlite3MPrintf(db, "non-%s value in %s.%s",
                                  sqlite3StdType[pCol->eCType-1],
                                  pTab->zName, pTab->aCol[j].zCnName);
            sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
          }else if( !bStrict && pCol->affinity==SQLITE_AFF_TEXT ){
            /* (3) Datatype for TEXT columns in non-STRICT tables must be
            **     NULL, TEXT, or BLOB. */
            sqlite3VdbeAddOp4Int(v, OP_IsType, p1, labelOk, p3, p4);
            sqlite3VdbeChangeP5(v, 0x1c); /* NULL, TEXT, or BLOB */
            VdbeCoverage(v);
            zErr = sqlite3MPrintf(db, "NUMERIC value in %s.%s",
                                  pTab->zName, pTab->aCol[j].zCnName);
            sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
          }else if( !bStrict && pCol->affinity>=SQLITE_AFF_NUMERIC ){
            /* (4) Datatype for numeric columns in non-STRICT tables must not
            **     be a TEXT value that can be converted to numeric. */
            sqlite3VdbeAddOp4Int(v, OP_IsType, p1, labelOk, p3, p4);
            sqlite3VdbeChangeP5(v, 0x1b); /* NULL, INT, FLOAT, or BLOB */
            VdbeCoverage(v);
            if( p1>=0 ){
              sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3);
            }
            sqlite3VdbeAddOp4(v, OP_Affinity, 3, 1, 0, "C", P4_STATIC);
            sqlite3VdbeAddOp4Int(v, OP_IsType, -1, labelOk, 3, p4);
            sqlite3VdbeChangeP5(v, 0x1c); /* NULL, TEXT, or BLOB */
            VdbeCoverage(v);
            zErr = sqlite3MPrintf(db, "TEXT value in %s.%s",
                                  pTab->zName, pTab->aCol[j].zCnName);
            sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
          }
          sqlite3VdbeResolveLabel(v, labelError);
          integrityCheckResultRow(v);
          sqlite3VdbeJumpHere(v, jmp2);
          sqlite3VdbeResolveLabel(v, labelOk);
        }
        /* Verify CHECK constraints */
        if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
          ExprList *pCheck = sqlite3ExprListDup(db, pTab->pCheck, 0);
          if( db->mallocFailed==0 ){
            int addrCkFault = sqlite3VdbeMakeLabel(v);
            int addrCkOk = sqlite3VdbeMakeLabel(v);
            int addrCkFault = sqlite3VdbeMakeLabel(pParse);
            int addrCkOk = sqlite3VdbeMakeLabel(pParse);
            char *zErr;
            int k;
            pParse->iSelfTab = iDataCur + 1;
            for(k=pCheck->nExpr-1; k>0; k--){
              sqlite3ExprIfFalse(pParse, pCheck->a[k].pExpr, addrCkFault, 0);
            }
            sqlite3ExprIfTrue(pParse, pCheck->a[0].pExpr, addrCkOk, 
1615
1616
1617
1618
1619
1620
1621
1622
1623



1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639




















1640
1641
1642
1643
1644

1645
1646
1647
1648
1649
1650
1651
1652
1653
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
1991
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
2017
2018
2019
2020
2021
2022







-
-
+
+
+
















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
+

-







            sqlite3VdbeResolveLabel(v, addrCkOk);
          }
          sqlite3ExprListDelete(db, pCheck);
        }
        if( !isQuick ){ /* Omit the remaining tests for quick_check */
          /* Validate index entries for the current row */
          for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
            int jmp2, jmp3, jmp4, jmp5;
            int ckUniq = sqlite3VdbeMakeLabel(v);
            int jmp2, jmp3, jmp4, jmp5, label6;
            int kk;
            int ckUniq = sqlite3VdbeMakeLabel(pParse);
            if( pPk==pIdx ) continue;
            r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3,
                                         pPrior, r1);
            pPrior = pIdx;
            sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1);/* increment entry count */
            /* Verify that an index entry exists for the current table row */
            jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1,
                                        pIdx->nColumn); VdbeCoverage(v);
            sqlite3VdbeLoadString(v, 3, "row ");
            sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3);
            sqlite3VdbeLoadString(v, 4, " missing from index ");
            sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
            jmp5 = sqlite3VdbeLoadString(v, 4, pIdx->zName);
            sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
            jmp4 = integrityCheckResultRow(v);
            sqlite3VdbeJumpHere(v, jmp2);

            /* Any indexed columns with non-BINARY collations must still hold
            ** the exact same text value as the table. */
            label6 = 0;
            for(kk=0; kk<pIdx->nKeyCol; kk++){
              if( pIdx->azColl[kk]==sqlite3StrBINARY ) continue;
              if( label6==0 ) label6 = sqlite3VdbeMakeLabel(pParse);
              sqlite3VdbeAddOp3(v, OP_Column, iIdxCur+j, kk, 3);
              sqlite3VdbeAddOp3(v, OP_Ne, 3, label6, r1+kk); VdbeCoverage(v);
            }
            if( label6 ){
              int jmp6 = sqlite3VdbeAddOp0(v, OP_Goto);
              sqlite3VdbeResolveLabel(v, label6);
              sqlite3VdbeLoadString(v, 3, "row ");
              sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3);
              sqlite3VdbeLoadString(v, 4, " values differ from index ");
              sqlite3VdbeGoto(v, jmp5-1);
              sqlite3VdbeJumpHere(v, jmp6);
            }
              
            /* For UNIQUE indexes, verify that only one entry exists with the
            ** current key.  The entry is unique if (1) any column is NULL
            ** or (2) the next entry has a different key */
            if( IsUniqueIndex(pIdx) ){
              int uniqOk = sqlite3VdbeMakeLabel(v);
              int uniqOk = sqlite3VdbeMakeLabel(pParse);
              int jmp6;
              int kk;
              for(kk=0; kk<pIdx->nKeyCol; kk++){
                int iCol = pIdx->aiColumn[kk];
                assert( iCol!=XN_ROWID && iCol<pTab->nCol );
                if( iCol>=0 && pTab->aCol[iCol].notNull ) continue;
                sqlite3VdbeAddOp2(v, OP_IsNull, r1+kk, uniqOk);
                VdbeCoverage(v);
              }
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
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







-












+
+
-
+
-
+







            }
            sqlite3VdbeJumpHere(v, jmp4);
            sqlite3ResolvePartIdxLabel(pParse, jmp3);
          }
        }
        sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v);
        sqlite3VdbeJumpHere(v, loopTop-1);
#ifndef SQLITE_OMIT_BTREECOUNT
        if( !isQuick ){
          sqlite3VdbeLoadString(v, 2, "wrong # of entries in index ");
          for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
            if( pPk==pIdx ) continue;
            sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3);
            addr = sqlite3VdbeAddOp3(v, OP_Eq, 8+j, 0, 3); VdbeCoverage(v);
            sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
            sqlite3VdbeLoadString(v, 4, pIdx->zName);
            sqlite3VdbeAddOp3(v, OP_Concat, 4, 2, 3);
            integrityCheckResultRow(v);
            sqlite3VdbeJumpHere(v, addr);
          }
          if( pPk ){
            sqlite3ReleaseTempRange(pParse, r2, pPk->nKeyCol);
        }
          }
#endif /* SQLITE_OMIT_BTREECOUNT */
        }
      } 
    }
    {
      static const int iLn = VDBE_OFFSET_LINENO(2);
      static const VdbeOpList endCode[] = {
        { OP_AddImm,      1, 0,        0},    /* 0 */
        { OP_IfNotZero,   1, 4,        0},    /* 1 */
1757
1758
1759
1760
1761
1762
1763
1764

1765
1766
1767
1768
1769
1770
1771



1772
1773
1774
1775
1776
1777
1778
2127
2128
2129
2130
2131
2132
2133

2134



2135
2136


2137
2138
2139
2140
2141
2142
2143
2144
2145
2146







-
+
-
-
-


-
-
+
+
+







      returnSingleText(v, encnames[ENC(pParse->db)].zName);
    }else{                        /* "PRAGMA encoding = XXX" */
      /* Only change the value of sqlite.enc if the database handle is not
      ** initialized. If the main database exists, the new sqlite.enc value
      ** will be overwritten when the schema is next loaded. If it does not
      ** already exists, it will be created to use the new encoding value.
      */
      if( 
      if( (db->mDbFlags & DBFLAG_EncodingFixed)==0 ){
        !(DbHasProperty(db, 0, DB_SchemaLoaded)) || 
        DbHasProperty(db, 0, DB_Empty) 
      ){
        for(pEnc=&encnames[0]; pEnc->zName; pEnc++){
          if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){
            SCHEMA_ENC(db) = ENC(db) =
                pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE;
            u8 enc = pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE;
            SCHEMA_ENC(db) = enc;
            sqlite3SetTextEncoding(db, enc);
            break;
          }
        }
        if( !pEnc->zName ){
          sqlite3ErrorMsg(pParse, "unsupported encoding: %s", zRight);
        }
      }
1827
1828
1829
1830
1831
1832
1833






1834
1835
1836
1837
1838
1839
1840
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214







+
+
+
+
+
+







      sqlite3VdbeVerifyNoMallocRequired(v, ArraySize(setCookie));
      aOp = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie, 0);
      if( ONLY_IF_REALLOC_STRESS(aOp==0) ) break;
      aOp[0].p1 = iDb;
      aOp[1].p1 = iDb;
      aOp[1].p2 = iCookie;
      aOp[1].p3 = sqlite3Atoi(zRight);
      aOp[1].p5 = 1;
      if( iCookie==BTREE_SCHEMA_VERSION && (db->flags & SQLITE_Defensive)!=0 ){
        /* Do not allow the use of PRAGMA schema_version=VALUE in defensive
        ** mode.  Change the OP_SetCookie opcode into a no-op.  */
        aOp[1].opcode = OP_Noop;
      }
    }else{
      /* Read the specified cookie value */
      static const VdbeOpList readCookie[] = {
        { OP_Transaction,     0,  0,  0},    /* 0 */
        { OP_ReadCookie,      0,  1,  0},    /* 1 */
        { OP_ResultRow,       1,  1,  0}
      };
1874
1875
1876
1877
1878
1879
1880
1881

1882
1883
1884
1885
1886
1887
1888
2248
2249
2250
2251
2252
2253
2254

2255
2256
2257
2258
2259
2260
2261
2262







-
+







#ifndef SQLITE_OMIT_WAL
  /*
  **   PRAGMA [schema.]wal_checkpoint = passive|full|restart|truncate
  **
  ** Checkpoint the database.
  */
  case PragTyp_WAL_CHECKPOINT: {
    int iBt = (pId2->z?iDb:SQLITE_MAX_ATTACHED);
    int iBt = (pId2->z?iDb:SQLITE_MAX_DB);
    int eMode = SQLITE_CHECKPOINT_PASSIVE;
    if( zRight ){
      if( sqlite3StrICmp(zRight, "full")==0 ){
        eMode = SQLITE_CHECKPOINT_FULL;
      }else if( sqlite3StrICmp(zRight, "restart")==0 ){
        eMode = SQLITE_CHECKPOINT_RESTART;
      }else if( sqlite3StrICmp(zRight, "truncate")==0 ){
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
2446
2447
2448
2449
2450
2451
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
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    sqlite3_int64 N;
    if( zRight && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK ){
      sqlite3_soft_heap_limit64(N);
    }
    returnSingleInt(v, sqlite3_soft_heap_limit64(-1));
    break;
  }

  /*
  **   PRAGMA hard_heap_limit
  **   PRAGMA hard_heap_limit = N
  **
  ** Invoke sqlite3_hard_heap_limit64() to query or set the hard heap
  ** limit.  The hard heap limit can be activated or lowered by this
  ** pragma, but not raised or deactivated.  Only the
  ** sqlite3_hard_heap_limit64() C-language API can raise or deactivate
  ** the hard heap limit.  This allows an application to set a heap limit
  ** constraint that cannot be relaxed by an untrusted SQL script.
  */
  case PragTyp_HARD_HEAP_LIMIT: {
    sqlite3_int64 N;
    if( zRight && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK ){
      sqlite3_int64 iPrior = sqlite3_hard_heap_limit64(-1);
      if( N>0 && (iPrior==0 || iPrior>N) ) sqlite3_hard_heap_limit64(N);
    }
    returnSingleInt(v, sqlite3_hard_heap_limit64(-1));
    break;
  }

  /*
  **   PRAGMA threads
  **   PRAGMA threads = N
  **
  ** Configure the maximum number of worker threads.  Return the new
  ** maximum, which might be less than requested.
  */
  case PragTyp_THREADS: {
    sqlite3_int64 N;
    if( zRight
     && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK
     && N>=0
    ){
      sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, (int)(N&0x7fffffff));
    }
    returnSingleInt(v, sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, -1));
    break;
  }

  /*
  **   PRAGMA analysis_limit
  **   PRAGMA analysis_limit = N
  **
  ** Configure the maximum number of rows that ANALYZE will examine
  ** in each index that it looks at.  Return the new limit.
  */
  case PragTyp_ANALYSIS_LIMIT: {
    sqlite3_int64 N;
    if( zRight
     && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK /* IMP: R-40975-20399 */
     && N>=0
    ){
      db->nAnalysisLimit = (int)(N&0x7fffffff);
    }
    returnSingleInt(v, db->nAnalysisLimit); /* IMP: R-57594-65522 */
    break;
  }

#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
  /*
  ** Report the current state of file logs for all databases
  */
  case PragTyp_LOCK_STATUS: {
    static const char *const azLockName[] = {
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
2534
2535
2536
2537
2538
2539
2540








































2541
2542






2543
2544
2545

2546
2547
2548
2549
2550
2551
2552







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+

-
-
-
-
-
-



-







      }
      sqlite3VdbeMultiLoad(v, 1, "ss", db->aDb[i].zDbSName, zState);
    }
    break;
  }
#endif

#ifdef SQLITE_HAS_CODEC
  /* Pragma        iArg
  ** ----------   ------
  **  key           0
  **  rekey         1
  **  hexkey        2
  **  hexrekey      3
  **  textkey       4
  **  textrekey     5
  */
  case PragTyp_KEY: {
    if( zRight ){
      int n = pPragma->iArg<4 ? sqlite3Strlen30(zRight) : -1;
      if( (pPragma->iArg & 1)==0 ){
        sqlite3_key_v2(db, zDb, zRight, n);
      }else{
        sqlite3_rekey_v2(db, zDb, zRight, n);
      }
    }
    break;
  }
  case PragTyp_HEXKEY: {
    if( zRight ){
      u8 iByte;
      int i;
      char zKey[40];
      for(i=0, iByte=0; i<sizeof(zKey)*2 && sqlite3Isxdigit(zRight[i]); i++){
        iByte = (iByte<<4) + sqlite3HexToInt(zRight[i]);
        if( (i&1)!=0 ) zKey[i/2] = iByte;
      }
      if( (pPragma->iArg & 1)==0 ){
        sqlite3_key_v2(db, zDb, zKey, i/2);
      }else{
        sqlite3_rekey_v2(db, zDb, zKey, i/2);
      }
    }
    break;
  }
#endif
#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
#if defined(SQLITE_ENABLE_CEROD)
  case PragTyp_ACTIVATE_EXTENSIONS: if( zRight ){
#ifdef SQLITE_HAS_CODEC
    if( sqlite3StrNICmp(zRight, "see-", 4)==0 ){
      sqlite3_activate_see(&zRight[4]);
    }
#endif
#ifdef SQLITE_ENABLE_CEROD
    if( sqlite3StrNICmp(zRight, "cerod-", 6)==0 ){
      sqlite3_activate_cerod(&zRight[6]);
    }
#endif
  }
  break;
#endif

  } /* End of the PRAGMA switch */

  /* The following block is a no-op unless SQLITE_DEBUG is defined. Its only

Changes to src/pragma.h.

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
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







+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
-







/* DO NOT EDIT!
** This file is automatically generated by the script at
** ../tool/mkpragmatab.tcl.  To update the set of pragmas, edit
** that script and rerun it.
*/

/* The various pragma types */
#define PragTyp_ACTIVATE_EXTENSIONS            0
#define PragTyp_ANALYSIS_LIMIT                 1
#define PragTyp_HEADER_VALUE                   0
#define PragTyp_AUTO_VACUUM                    1
#define PragTyp_FLAG                           2
#define PragTyp_BUSY_TIMEOUT                   3
#define PragTyp_CACHE_SIZE                     4
#define PragTyp_CACHE_SPILL                    5
#define PragTyp_CASE_SENSITIVE_LIKE            6
#define PragTyp_COLLATION_LIST                 7
#define PragTyp_COMPILE_OPTIONS                8
#define PragTyp_DATA_STORE_DIRECTORY           9
#define PragTyp_DATABASE_LIST                 10
#define PragTyp_DEFAULT_CACHE_SIZE            11
#define PragTyp_ENCODING                      12
#define PragTyp_FOREIGN_KEY_CHECK             13
#define PragTyp_FOREIGN_KEY_LIST              14
#define PragTyp_FUNCTION_LIST                 15
#define PragTyp_INCREMENTAL_VACUUM            16
#define PragTyp_INDEX_INFO                    17
#define PragTyp_INDEX_LIST                    18
#define PragTyp_INTEGRITY_CHECK               19
#define PragTyp_JOURNAL_MODE                  20
#define PragTyp_JOURNAL_SIZE_LIMIT            21
#define PragTyp_LOCK_PROXY_FILE               22
#define PragTyp_LOCKING_MODE                  23
#define PragTyp_PAGE_COUNT                    24
#define PragTyp_MMAP_SIZE                     25
#define PragTyp_MODULE_LIST                   26
#define PragTyp_OPTIMIZE                      27
#define PragTyp_PAGE_SIZE                     28
#define PragTyp_PRAGMA_LIST                   29
#define PragTyp_SECURE_DELETE                 30
#define PragTyp_SHRINK_MEMORY                 31
#define PragTyp_SOFT_HEAP_LIMIT               32
#define PragTyp_SYNCHRONOUS                   33
#define PragTyp_TABLE_INFO                    34
#define PragTyp_TEMP_STORE                    35
#define PragTyp_TEMP_STORE_DIRECTORY          36
#define PragTyp_THREADS                       37
#define PragTyp_WAL_AUTOCHECKPOINT            38
#define PragTyp_WAL_CHECKPOINT                39
#define PragTyp_HEADER_VALUE                   2
#define PragTyp_AUTO_VACUUM                    3
#define PragTyp_FLAG                           4
#define PragTyp_BUSY_TIMEOUT                   5
#define PragTyp_CACHE_SIZE                     6
#define PragTyp_CACHE_SPILL                    7
#define PragTyp_CASE_SENSITIVE_LIKE            8
#define PragTyp_COLLATION_LIST                 9
#define PragTyp_COMPILE_OPTIONS               10
#define PragTyp_DATA_STORE_DIRECTORY          11
#define PragTyp_DATABASE_LIST                 12
#define PragTyp_DEFAULT_CACHE_SIZE            13
#define PragTyp_ENCODING                      14
#define PragTyp_FOREIGN_KEY_CHECK             15
#define PragTyp_FOREIGN_KEY_LIST              16
#define PragTyp_FUNCTION_LIST                 17
#define PragTyp_HARD_HEAP_LIMIT               18
#define PragTyp_INCREMENTAL_VACUUM            19
#define PragTyp_INDEX_INFO                    20
#define PragTyp_INDEX_LIST                    21
#define PragTyp_INTEGRITY_CHECK               22
#define PragTyp_JOURNAL_MODE                  23
#define PragTyp_JOURNAL_SIZE_LIMIT            24
#define PragTyp_LOCK_PROXY_FILE               25
#define PragTyp_LOCKING_MODE                  26
#define PragTyp_PAGE_COUNT                    27
#define PragTyp_MMAP_SIZE                     28
#define PragTyp_MODULE_LIST                   29
#define PragTyp_OPTIMIZE                      30
#define PragTyp_PAGE_SIZE                     31
#define PragTyp_PRAGMA_LIST                   32
#define PragTyp_SECURE_DELETE                 33
#define PragTyp_SHRINK_MEMORY                 34
#define PragTyp_SOFT_HEAP_LIMIT               35
#define PragTyp_SYNCHRONOUS                   36
#define PragTyp_TABLE_INFO                    37
#define PragTyp_TABLE_LIST                    38
#define PragTyp_TEMP_STORE                    39
#define PragTyp_TEMP_STORE_DIRECTORY          40
#define PragTyp_THREADS                       41
#define PragTyp_WAL_AUTOCHECKPOINT            42
#define PragTyp_WAL_CHECKPOINT                43
#define PragTyp_ACTIVATE_EXTENSIONS           40
#define PragTyp_HEXKEY                        41
#define PragTyp_KEY                           42
#define PragTyp_LOCK_STATUS                   43
#define PragTyp_LOCK_STATUS                   44
#define PragTyp_PARSER_TRACE                  44
#define PragTyp_STATS                         45

/* Property flags associated with various pragma. */
#define PragFlg_NeedSchema 0x01 /* Force schema load before running */
#define PragFlg_NoColumns  0x02 /* OP_ResultRow called with zero columns */
#define PragFlg_NoColumns1 0x04 /* zero columns if RHS argument is present */
#define PragFlg_ReadOnly   0x08 /* Read-only HEADER_VALUE */
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
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







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+












-
+






+
+
+
+
+







  /*   9 */ "name",       
  /*  10 */ "type",       
  /*  11 */ "notnull",    
  /*  12 */ "dflt_value", 
  /*  13 */ "pk",         
  /*  14 */ "hidden",     
                           /* table_info reuses 8 */
  /*  15 */ "seqno",       /* Used by: index_xinfo */
  /*  16 */ "cid",        
  /*  17 */ "name",       
  /*  18 */ "desc",       
  /*  19 */ "coll",       
  /*  20 */ "key",        
  /*  21 */ "tbl",         /* Used by: stats */
  /*  22 */ "idx",        
  /*  23 */ "wdth",       
  /*  24 */ "hght",       
  /*  25 */ "flgs",       
  /*  26 */ "seq",         /* Used by: index_list */
  /*  27 */ "name",       
  /*  28 */ "unique",     
  /*  29 */ "origin",     
  /*  30 */ "partial",    
  /*  31 */ "table",       /* Used by: foreign_key_check */
  /*  32 */ "rowid",      
  /*  33 */ "parent",     
  /*  34 */ "fkid",       
  /*  15 */ "schema",      /* Used by: table_list */
  /*  16 */ "name",       
  /*  17 */ "type",       
  /*  18 */ "ncol",       
  /*  19 */ "wr",         
  /*  20 */ "strict",     
  /*  21 */ "seqno",       /* Used by: index_xinfo */
  /*  22 */ "cid",        
  /*  23 */ "name",       
  /*  24 */ "desc",       
  /*  25 */ "coll",       
  /*  26 */ "key",        
  /*  27 */ "name",        /* Used by: function_list */
  /*  28 */ "builtin",    
  /*  29 */ "type",       
  /*  30 */ "enc",        
  /*  31 */ "narg",       
  /*  32 */ "flags",      
  /*  33 */ "tbl",         /* Used by: stats */
  /*  34 */ "idx",        
                           /* index_info reuses 15 */
  /*  35 */ "seq",         /* Used by: database_list */
  /*  36 */ "name",       
  /*  37 */ "file",       
  /*  38 */ "busy",        /* Used by: wal_checkpoint */
  /*  39 */ "log",        
  /*  40 */ "checkpointed",
  /*  41 */ "name",        /* Used by: function_list */
  /*  42 */ "builtin",    
                           /* collation_list reuses 26 */
  /*  43 */ "database",    /* Used by: lock_status */
  /*  44 */ "status",     
  /*  45 */ "cache_size",  /* Used by: default_cache_size */
  /*  35 */ "wdth",       
  /*  36 */ "hght",       
  /*  37 */ "flgs",       
  /*  38 */ "seq",         /* Used by: index_list */
  /*  39 */ "name",       
  /*  40 */ "unique",     
  /*  41 */ "origin",     
  /*  42 */ "partial",    
  /*  43 */ "table",       /* Used by: foreign_key_check */
  /*  44 */ "rowid",      
  /*  45 */ "parent",     
  /*  46 */ "fkid",       
                           /* index_info reuses 21 */
  /*  47 */ "seq",         /* Used by: database_list */
  /*  48 */ "name",       
  /*  49 */ "file",       
  /*  50 */ "busy",        /* Used by: wal_checkpoint */
  /*  51 */ "log",        
  /*  52 */ "checkpointed",
                           /* collation_list reuses 38 */
  /*  53 */ "database",    /* Used by: lock_status */
  /*  54 */ "status",     
  /*  55 */ "cache_size",  /* Used by: default_cache_size */
                           /* module_list pragma_list reuses 9 */
  /*  46 */ "timeout",     /* Used by: busy_timeout */
  /*  56 */ "timeout",     /* Used by: busy_timeout */
};

/* Definitions of all built-in pragmas */
typedef struct PragmaName {
  const char *const zName; /* Name of pragma */
  u8 ePragTyp;             /* PragTyp_XXX value */
  u8 mPragFlg;             /* Zero or more PragFlg_XXX values */
  u8 iPragCName;           /* Start of column names in pragCName[] */
  u8 nPragCName;           /* Num of col names. 0 means use pragma name */
  u64 iArg;                /* Extra argument */
} PragmaName;
static const PragmaName aPragmaName[] = {
#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
#if defined(SQLITE_ENABLE_CEROD)
 {/* zName:     */ "activate_extensions",
  /* ePragTyp:  */ PragTyp_ACTIVATE_EXTENSIONS,
  /* ePragFlg:  */ 0,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ 0 },
#endif
 {/* zName:     */ "analysis_limit",
  /* ePragTyp:  */ PragTyp_ANALYSIS_LIMIT,
  /* ePragFlg:  */ PragFlg_Result0,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ 0 },
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
 {/* zName:     */ "application_id",
  /* ePragTyp:  */ PragTyp_HEADER_VALUE,
  /* ePragFlg:  */ PragFlg_NoColumns1|PragFlg_Result0,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ BTREE_APPLICATION_ID },
#endif
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
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







-
+















+





+
















-
+







  /* ColNames:  */ 0, 0,
  /* iArg:      */ SQLITE_AutoIndex },
#endif
#endif
 {/* zName:     */ "busy_timeout",
  /* ePragTyp:  */ PragTyp_BUSY_TIMEOUT,
  /* ePragFlg:  */ PragFlg_Result0,
  /* ColNames:  */ 46, 1,
  /* ColNames:  */ 56, 1,
  /* iArg:      */ 0 },
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
 {/* zName:     */ "cache_size",
  /* ePragTyp:  */ PragTyp_CACHE_SIZE,
  /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
 {/* zName:     */ "cache_spill",
  /* ePragTyp:  */ PragTyp_CACHE_SPILL,
  /* ePragFlg:  */ PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_CASE_SENSITIVE_LIKE_PRAGMA)
 {/* zName:     */ "case_sensitive_like",
  /* ePragTyp:  */ PragTyp_CASE_SENSITIVE_LIKE,
  /* ePragFlg:  */ PragFlg_NoColumns,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ 0 },
#endif
 {/* zName:     */ "cell_size_check",
  /* ePragTyp:  */ PragTyp_FLAG,
  /* ePragFlg:  */ PragFlg_Result0|PragFlg_NoColumns1,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ SQLITE_CellSizeCk },
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
 {/* zName:     */ "checkpoint_fullfsync",
  /* ePragTyp:  */ PragTyp_FLAG,
  /* ePragFlg:  */ PragFlg_Result0|PragFlg_NoColumns1,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ SQLITE_CkptFullFSync },
#endif
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
 {/* zName:     */ "collation_list",
  /* ePragTyp:  */ PragTyp_COLLATION_LIST,
  /* ePragFlg:  */ PragFlg_Result0,
  /* ColNames:  */ 26, 2,
  /* ColNames:  */ 38, 2,
  /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)
 {/* zName:     */ "compile_options",
  /* ePragTyp:  */ PragTyp_COMPILE_OPTIONS,
  /* ePragFlg:  */ PragFlg_Result0,
  /* ColNames:  */ 0, 0,
230
231
232
233
234
235
236
237
238


239
240
241
242
243
244
245

246
247
248
249
250
251
252
247
248
249
250
251
252
253


254
255
256
257
258
259
260
261

262
263
264
265
266
267
268
269







-
-
+
+






-
+







  /* ePragFlg:  */ PragFlg_ReadOnly|PragFlg_Result0,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ BTREE_DATA_VERSION },
#endif
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
 {/* zName:     */ "database_list",
  /* ePragTyp:  */ PragTyp_DATABASE_LIST,
  /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result0,
  /* ColNames:  */ 35, 3,
  /* ePragFlg:  */ PragFlg_Result0,
  /* ColNames:  */ 47, 3,
  /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
 {/* zName:     */ "default_cache_size",
  /* ePragTyp:  */ PragTyp_DEFAULT_CACHE_SIZE,
  /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
  /* ColNames:  */ 45, 1,
  /* ColNames:  */ 55, 1,
  /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
 {/* zName:     */ "defer_foreign_keys",
  /* ePragTyp:  */ PragTyp_FLAG,
  /* ePragFlg:  */ PragFlg_Result0|PragFlg_NoColumns1,
267
268
269
270
271
272
273
274
275


276
277
278
279
280
281
282
284
285
286
287
288
289
290


291
292
293
294
295
296
297
298
299







-
-
+
+







  /* ePragFlg:  */ PragFlg_Result0|PragFlg_NoColumns1,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
 {/* zName:     */ "foreign_key_check",
  /* ePragTyp:  */ PragTyp_FOREIGN_KEY_CHECK,
  /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result0,
  /* ColNames:  */ 31, 4,
  /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1|PragFlg_SchemaOpt,
  /* ColNames:  */ 43, 4,
  /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_FOREIGN_KEY)
 {/* zName:     */ "foreign_key_list",
  /* ePragTyp:  */ PragTyp_FOREIGN_KEY_LIST,
  /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
  /* ColNames:  */ 0, 8,
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
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







-
+



-
+



-
-
-
-
-
-
-
-
-
+
+
+

-
+
-




















-
+




-
+




-
+





-
+















-
-
-
-
-
-
-






-
-
-
-
-












-
+







 {/* zName:     */ "fullfsync",
  /* ePragTyp:  */ PragTyp_FLAG,
  /* ePragFlg:  */ PragFlg_Result0|PragFlg_NoColumns1,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ SQLITE_FullFSync },
#endif
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
#if defined(SQLITE_INTROSPECTION_PRAGMAS)
#if !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS)
 {/* zName:     */ "function_list",
  /* ePragTyp:  */ PragTyp_FUNCTION_LIST,
  /* ePragFlg:  */ PragFlg_Result0,
  /* ColNames:  */ 41, 2,
  /* ColNames:  */ 27, 6,
  /* iArg:      */ 0 },
#endif
#endif
#if defined(SQLITE_HAS_CODEC)
 {/* zName:     */ "hexkey",
  /* ePragTyp:  */ PragTyp_HEXKEY,
  /* ePragFlg:  */ 0,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ 2 },
 {/* zName:     */ "hexrekey",
  /* ePragTyp:  */ PragTyp_HEXKEY,
  /* ePragFlg:  */ 0,
 {/* zName:     */ "hard_heap_limit",
  /* ePragTyp:  */ PragTyp_HARD_HEAP_LIMIT,
  /* ePragFlg:  */ PragFlg_Result0,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ 3 },
  /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
#if !defined(SQLITE_OMIT_CHECK)
 {/* zName:     */ "ignore_check_constraints",
  /* ePragTyp:  */ PragTyp_FLAG,
  /* ePragFlg:  */ PragFlg_Result0|PragFlg_NoColumns1,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ SQLITE_IgnoreChecks },
#endif
#endif
#if !defined(SQLITE_OMIT_AUTOVACUUM)
 {/* zName:     */ "incremental_vacuum",
  /* ePragTyp:  */ PragTyp_INCREMENTAL_VACUUM,
  /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_NoColumns,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
 {/* zName:     */ "index_info",
  /* ePragTyp:  */ PragTyp_INDEX_INFO,
  /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
  /* ColNames:  */ 15, 3,
  /* ColNames:  */ 21, 3,
  /* iArg:      */ 0 },
 {/* zName:     */ "index_list",
  /* ePragTyp:  */ PragTyp_INDEX_LIST,
  /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
  /* ColNames:  */ 26, 5,
  /* ColNames:  */ 38, 5,
  /* iArg:      */ 0 },
 {/* zName:     */ "index_xinfo",
  /* ePragTyp:  */ PragTyp_INDEX_INFO,
  /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
  /* ColNames:  */ 15, 6,
  /* ColNames:  */ 21, 6,
  /* iArg:      */ 1 },
#endif
#if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
 {/* zName:     */ "integrity_check",
  /* ePragTyp:  */ PragTyp_INTEGRITY_CHECK,
  /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1,
  /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1|PragFlg_SchemaOpt,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
 {/* zName:     */ "journal_mode",
  /* ePragTyp:  */ PragTyp_JOURNAL_MODE,
  /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ 0 },
 {/* zName:     */ "journal_size_limit",
  /* ePragTyp:  */ PragTyp_JOURNAL_SIZE_LIMIT,
  /* ePragFlg:  */ PragFlg_Result0|PragFlg_SchemaReq,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ 0 },
#endif
#if defined(SQLITE_HAS_CODEC)
 {/* zName:     */ "key",
  /* ePragTyp:  */ PragTyp_KEY,
  /* ePragFlg:  */ 0,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
 {/* zName:     */ "legacy_alter_table",
  /* ePragTyp:  */ PragTyp_FLAG,
  /* ePragFlg:  */ PragFlg_Result0|PragFlg_NoColumns1,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ SQLITE_LegacyAlter },
 {/* zName:     */ "legacy_file_format",
  /* ePragTyp:  */ PragTyp_FLAG,
  /* ePragFlg:  */ PragFlg_Result0|PragFlg_NoColumns1,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ SQLITE_LegacyFileFmt },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_ENABLE_LOCKING_STYLE
 {/* zName:     */ "lock_proxy_file",
  /* ePragTyp:  */ PragTyp_LOCK_PROXY_FILE,
  /* ePragFlg:  */ PragFlg_NoColumns1,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ 0 },
#endif
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
 {/* zName:     */ "lock_status",
  /* ePragTyp:  */ PragTyp_LOCK_STATUS,
  /* ePragFlg:  */ PragFlg_Result0,
  /* ColNames:  */ 43, 2,
  /* ColNames:  */ 53, 2,
  /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
 {/* zName:     */ "locking_mode",
  /* ePragTyp:  */ PragTyp_LOCKING_MODE,
  /* ePragFlg:  */ PragFlg_Result0|PragFlg_SchemaReq,
  /* ColNames:  */ 0, 0,
431
432
433
434
435
436
437
438

439
440
441
442
443
444
445
429
430
431
432
433
434
435

436
437
438
439
440
441
442
443







-
+







  /* ePragTyp:  */ PragTyp_MMAP_SIZE,
  /* ePragFlg:  */ 0,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
#if !defined(SQLITE_OMIT_VIRTUALTABLE)
#if defined(SQLITE_INTROSPECTION_PRAGMAS)
#if !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS)
 {/* zName:     */ "module_list",
  /* ePragTyp:  */ PragTyp_MODULE_LIST,
  /* ePragFlg:  */ PragFlg_Result0,
  /* ColNames:  */ 9, 1,
  /* iArg:      */ 0 },
#endif
#endif
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
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







+
-
+

-
-
+
+

-
+

+
-
+
















-
+














-
-
-
-
-
-
-
-
-







  /* iArg:      */ 0 },
 {/* zName:     */ "page_size",
  /* ePragTyp:  */ PragTyp_PAGE_SIZE,
  /* ePragFlg:  */ PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_PARSER_TRACE)
#if defined(SQLITE_DEBUG)
 {/* zName:     */ "parser_trace",
  /* ePragTyp:  */ PragTyp_PARSER_TRACE,
  /* ePragFlg:  */ 0,
  /* ePragTyp:  */ PragTyp_FLAG,
  /* ePragFlg:  */ PragFlg_Result0|PragFlg_NoColumns1,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ 0 },
  /* iArg:      */ SQLITE_ParserTrace },
#endif
#endif
#if defined(SQLITE_INTROSPECTION_PRAGMAS)
#if !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS)
 {/* zName:     */ "pragma_list",
  /* ePragTyp:  */ PragTyp_PRAGMA_LIST,
  /* ePragFlg:  */ PragFlg_Result0,
  /* ColNames:  */ 9, 1,
  /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
 {/* zName:     */ "query_only",
  /* ePragTyp:  */ PragTyp_FLAG,
  /* ePragFlg:  */ PragFlg_Result0|PragFlg_NoColumns1,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ SQLITE_QueryOnly },
#endif
#if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
 {/* zName:     */ "quick_check",
  /* ePragTyp:  */ PragTyp_INTEGRITY_CHECK,
  /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1,
  /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1|PragFlg_SchemaOpt,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
 {/* zName:     */ "read_uncommitted",
  /* ePragTyp:  */ PragTyp_FLAG,
  /* ePragFlg:  */ PragFlg_Result0|PragFlg_NoColumns1,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ SQLITE_ReadUncommit },
 {/* zName:     */ "recursive_triggers",
  /* ePragTyp:  */ PragTyp_FLAG,
  /* ePragFlg:  */ PragFlg_Result0|PragFlg_NoColumns1,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ SQLITE_RecTriggers },
#endif
#if defined(SQLITE_HAS_CODEC)
 {/* zName:     */ "rekey",
  /* ePragTyp:  */ PragTyp_KEY,
  /* ePragFlg:  */ 0,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ 1 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
 {/* zName:     */ "reverse_unordered_selects",
  /* ePragTyp:  */ PragTyp_FLAG,
  /* ePragFlg:  */ PragFlg_Result0|PragFlg_NoColumns1,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ SQLITE_ReverseOrder },
#endif
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
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
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







-
+














+
+
+
+
+



















-
-
-
-
-
-
-
-
-
-
-
-





+
+
+
+
+
+
+







  /* iArg:      */ SQLITE_SqlTrace },
#endif
#endif
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) && defined(SQLITE_DEBUG)
 {/* zName:     */ "stats",
  /* ePragTyp:  */ PragTyp_STATS,
  /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
  /* ColNames:  */ 21, 5,
  /* ColNames:  */ 33, 5,
  /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
 {/* zName:     */ "synchronous",
  /* ePragTyp:  */ PragTyp_SYNCHRONOUS,
  /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
 {/* zName:     */ "table_info",
  /* ePragTyp:  */ PragTyp_TABLE_INFO,
  /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
  /* ColNames:  */ 8, 6,
  /* iArg:      */ 0 },
 {/* zName:     */ "table_list",
  /* ePragTyp:  */ PragTyp_TABLE_LIST,
  /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result1,
  /* ColNames:  */ 15, 6,
  /* iArg:      */ 0 },
 {/* zName:     */ "table_xinfo",
  /* ePragTyp:  */ PragTyp_TABLE_INFO,
  /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
  /* ColNames:  */ 8, 7,
  /* iArg:      */ 1 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
 {/* zName:     */ "temp_store",
  /* ePragTyp:  */ PragTyp_TEMP_STORE,
  /* ePragFlg:  */ PragFlg_Result0|PragFlg_NoColumns1,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ 0 },
 {/* zName:     */ "temp_store_directory",
  /* ePragTyp:  */ PragTyp_TEMP_STORE_DIRECTORY,
  /* ePragFlg:  */ PragFlg_NoColumns1,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ 0 },
#endif
#if defined(SQLITE_HAS_CODEC)
 {/* zName:     */ "textkey",
  /* ePragTyp:  */ PragTyp_KEY,
  /* ePragFlg:  */ 0,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ 4 },
 {/* zName:     */ "textrekey",
  /* ePragTyp:  */ PragTyp_KEY,
  /* ePragFlg:  */ 0,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ 5 },
#endif
 {/* zName:     */ "threads",
  /* ePragTyp:  */ PragTyp_THREADS,
  /* ePragFlg:  */ PragFlg_Result0,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ 0 },
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
 {/* zName:     */ "trusted_schema",
  /* ePragTyp:  */ PragTyp_FLAG,
  /* ePragFlg:  */ PragFlg_Result0|PragFlg_NoColumns1,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ SQLITE_TrustedSchema },
#endif
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
 {/* zName:     */ "user_version",
  /* ePragTyp:  */ PragTyp_HEADER_VALUE,
  /* ePragFlg:  */ PragFlg_NoColumns1|PragFlg_Result0,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ BTREE_USER_VERSION },
#endif
660
661
662
663
664
665
666
667

668
669
670
671
672
673
674
675
676
677
678

651
652
653
654
655
656
657

658
659
660
661
662
663
664
665
666
667
668

669







-
+










-
+
  /* ePragTyp:  */ PragTyp_WAL_AUTOCHECKPOINT,
  /* ePragFlg:  */ 0,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ 0 },
 {/* zName:     */ "wal_checkpoint",
  /* ePragTyp:  */ PragTyp_WAL_CHECKPOINT,
  /* ePragFlg:  */ PragFlg_NeedSchema,
  /* ColNames:  */ 38, 3,
  /* ColNames:  */ 50, 3,
  /* iArg:      */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
 {/* zName:     */ "writable_schema",
  /* ePragTyp:  */ PragTyp_FLAG,
  /* ePragFlg:  */ PragFlg_Result0|PragFlg_NoColumns1,
  /* ColNames:  */ 0, 0,
  /* iArg:      */ SQLITE_WriteSchema|SQLITE_NoSchemaError },
#endif
};
/* Number of pragmas: 62 on by default, 81 total. */
/* Number of pragmas: 68 on by default, 78 total. */

Changes to src/prepare.c.

17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32
33











34
35
36
37
38
39

40
41
42
43
44
45

























46
47
48
49
50
51
52
53

54
55
56




57
58
59
60
61
62
63
64

65
66
67



68
69

70
71
72
73
74
75
76
77





78
79
80
81





82
83
84
85
86
87
88
89
90







91


92

93
94
95
96
97
98
99
100
101

102
103
104
105

106
107
108

109
110
111


112
113
114
115
116
117
118
119
120

121
122
123




124
125

126
127
128
129





130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150

151
152
153

154

155
156
157
158
159
160
161
162
163
164
165


166
167
168

169
170
171




172
173

174
175
176
177
178


179


180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199

200
201
202
203
204
205
206
17
18
19
20
21
22
23

24
25
26
27
28
29
30
31


32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88



89
90
91
92
93
94
95
96
97
98
99

100
101
102

103
104
105
106

107
108
109
110
111




112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133

134
135
136
137
138
139
140
141
142
143

144
145
146
147
148
149
150
151
152

153
154
155
156

157
158
159
160
161
162


163
164
165
166
167
168
169
170
171
172

173
174


175
176
177
178


179




180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204

205
206
207

208
209
210
211
212
213
214
215
216
217
218
219


220
221
222
223
224
225



226
227
228
229
230

231
232
233
234
235
236
237
238

239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259

260
261
262
263
264
265
266
267







-
+







-
-
+
+
+
+
+
+
+
+
+
+
+





-
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








+
-
-
-
+
+
+
+







-
+


-
+
+
+

-
+




-
-
-
-
+
+
+
+
+




+
+
+
+
+








-
+
+
+
+
+
+
+

+
+
-
+








-
+



-
+



+

-
-
+
+








-
+

-
-
+
+
+
+
-
-
+
-
-
-
-
+
+
+
+
+




















-
+


-
+

+









-
-
+
+



+
-
-
-
+
+
+
+

-
+





+
+
-
+
+



















-
+








/*
** Fill the InitData structure with an error message that indicates
** that the database is corrupt.
*/
static void corruptSchema(
  InitData *pData,     /* Initialization context */
  const char *zObj,    /* Object being parsed at the point of error */
  char **azObj,        /* Type and name of object being parsed */
  const char *zExtra   /* Error information */
){
  sqlite3 *db = pData->db;
  if( db->mallocFailed ){
    pData->rc = SQLITE_NOMEM_BKPT;
  }else if( pData->pzErrMsg[0]!=0 ){
    /* A error message has already been generated.  Do not overwrite it */
  }else if( pData->mInitFlags & INITFLAG_AlterTable ){
    *pData->pzErrMsg = sqlite3DbStrDup(db, zExtra);
  }else if( pData->mInitFlags & (INITFLAG_AlterMask) ){
    static const char *azAlterType[] = {
       "rename",
       "drop column",
       "add column"
    };
    *pData->pzErrMsg = sqlite3MPrintf(db, 
        "error in %s %s after %s: %s", azObj[0], azObj[1], 
        azAlterType[(pData->mInitFlags&INITFLAG_AlterMask)-1], 
        zExtra
    );
    pData->rc = SQLITE_ERROR;
  }else if( db->flags & SQLITE_WriteSchema ){
    pData->rc = SQLITE_CORRUPT_BKPT;
  }else{
    char *z;
    if( zObj==0 ) zObj = "?";
    const char *zObj = azObj[1] ? azObj[1] : "?";
    z = sqlite3MPrintf(db, "malformed database schema (%s)", zObj);
    if( zExtra && zExtra[0] ) z = sqlite3MPrintf(db, "%z - %s", z, zExtra);
    *pData->pzErrMsg = z;
    pData->rc = SQLITE_CORRUPT_BKPT;
  }
}

/*
** Check to see if any sibling index (another index on the same table)
** of pIndex has the same root page number, and if it does, return true.
** This would indicate a corrupt schema.
*/
int sqlite3IndexHasDuplicateRootPage(Index *pIndex){
  Index *p;
  for(p=pIndex->pTable->pIndex; p; p=p->pNext){
    if( p->tnum==pIndex->tnum && p!=pIndex ) return 1;
  }
  return 0;
}

/* forward declaration */
static int sqlite3Prepare(
  sqlite3 *db,              /* Database handle. */
  const char *zSql,         /* UTF-8 encoded SQL statement. */
  int nBytes,               /* Length of zSql in bytes. */
  u32 prepFlags,            /* Zero or more SQLITE_PREPARE_* flags */
  Vdbe *pReprepare,         /* VM being reprepared */
  sqlite3_stmt **ppStmt,    /* OUT: A pointer to the prepared statement */
  const char **pzTail       /* OUT: End of parsed string */
);


/*
** This is the callback routine for the code that initializes the
** database.  See sqlite3Init() below for additional information.
** This routine is also called from the OP_ParseSchema opcode of the VDBE.
**
** Each callback contains the following information:
**
**     argv[0] = type of object: "table", "index", "trigger", or "view".
**     argv[0] = name of thing being created
**     argv[1] = root page number for table or index. 0 for trigger or view.
**     argv[2] = SQL text for the CREATE statement.
**     argv[1] = name of thing being created
**     argv[2] = associated table if an index or trigger
**     argv[3] = root page number for table or index. 0 for trigger or view.
**     argv[4] = SQL text for the CREATE statement.
**
*/
int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
  InitData *pData = (InitData*)pInit;
  sqlite3 *db = pData->db;
  int iDb = pData->iDb;

  assert( argc==3 );
  assert( argc==5 );
  UNUSED_PARAMETER2(NotUsed, argc);
  assert( sqlite3_mutex_held(db->mutex) );
  DbClearProperty(db, iDb, DB_Empty);
  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], 0);
    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[1]==0 ){
    corruptSchema(pData, argv[0], 0);
  }else if( sqlite3_strnicmp(argv[2],"create ",7)==0 ){
  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
    ** or executed.  All the parser does is build the internal data
    ** structures that describe the table, index, or view.
    **
    ** No other valid SQL statement, other than the variable CREATE statements,
    ** can begin with the letters "C" and "R".  Thus, it is not possible run
    ** any other kind of statement while parsing the schema, even a corrupt
    ** schema.
    */
    int rc;
    u8 saved_iDb = db->init.iDb;
    sqlite3_stmt *pStmt;
    TESTONLY(int rcp);            /* Return code from sqlite3_prepare() */

    assert( db->init.busy );
    db->init.iDb = iDb;
    db->init.newTnum = sqlite3Atoi(argv[1]);
    if( sqlite3GetUInt32(argv[3], &db->init.newTnum)==0
     || (db->init.newTnum>pData->mxPage && pData->mxPage>0)
    ){
      if( sqlite3Config.bExtraSchemaChecks ){
        corruptSchema(pData, argv, "invalid rootpage");
      }
    }
    db->init.orphanTrigger = 0;
    db->init.azInit = (const char**)argv;
    pStmt = 0;
    TESTONLY(rcp = ) sqlite3_prepare(db, argv[2], -1, &pStmt, 0);
    TESTONLY(rcp = ) sqlite3Prepare(db, argv[4], -1, 0, 0, &pStmt, 0);
    rc = db->errCode;
    assert( (rc&0xFF)==(rcp&0xFF) );
    db->init.iDb = saved_iDb;
    /* assert( saved_iDb==0 || (db->mDbFlags & DBFLAG_Vacuum)!=0 ); */
    if( SQLITE_OK!=rc ){
      if( db->init.orphanTrigger ){
        assert( iDb==1 );
      }else{
        pData->rc = rc;
        if( rc > pData->rc ) pData->rc = rc;
        if( rc==SQLITE_NOMEM ){
          sqlite3OomFault(db);
        }else if( rc!=SQLITE_INTERRUPT && (rc&0xFF)!=SQLITE_LOCKED ){
          corruptSchema(pData, argv[0], sqlite3_errmsg(db));
          corruptSchema(pData, argv, sqlite3_errmsg(db));
        }
      }
    }
    db->init.azInit = sqlite3StdType; /* Any array of string ptrs will do */
    sqlite3_finalize(pStmt);
  }else if( argv[0]==0 || (argv[2]!=0 && argv[2][0]!=0) ){
    corruptSchema(pData, argv[0], 0);
  }else if( argv[1]==0 || (argv[4]!=0 && argv[4][0]!=0) ){
    corruptSchema(pData, argv, 0);
  }else{
    /* If the SQL column is blank it means this is an index that
    ** was created to be the PRIMARY KEY or to fulfill a UNIQUE
    ** constraint for a CREATE TABLE.  The index should have already
    ** been created when we processed the CREATE TABLE.  All we have
    ** to do here is record the root page number for that index.
    */
    Index *pIndex;
    pIndex = sqlite3FindIndex(db, argv[0], db->aDb[iDb].zDbSName);
    pIndex = sqlite3FindIndex(db, argv[1], db->aDb[iDb].zDbSName);
    if( pIndex==0 ){
      /* This can occur if there exists an index on a TEMP table which
      ** has the same name as another index on a permanent index.  Since
      corruptSchema(pData, argv, "orphan index");
    }else
    if( sqlite3GetUInt32(argv[3],&pIndex->tnum)==0
     || pIndex->tnum<2
      ** the permanent table is hidden by the TEMP table, we can also
      ** safely ignore the index on the permanent table.
     || pIndex->tnum>pData->mxPage
      */
      /* Do Nothing */;
    }else if( sqlite3GetInt32(argv[1], &pIndex->tnum)==0 ){
      corruptSchema(pData, argv[0], "invalid rootpage");
     || sqlite3IndexHasDuplicateRootPage(pIndex)
    ){
      if( sqlite3Config.bExtraSchemaChecks ){
        corruptSchema(pData, argv, "invalid rootpage");
      }
    }
  }
  return 0;
}

/*
** Attempt to read the database schema and initialize internal
** data structures for a single database file.  The index of the
** database file is given by iDb.  iDb==0 is used for the main
** database.  iDb==1 should never be used.  iDb>=2 is used for
** auxiliary databases.  Return one of the SQLITE_ error codes to
** indicate success or failure.
*/
int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
  int rc;
  int i;
#ifndef SQLITE_OMIT_DEPRECATED
  int size;
#endif
  Db *pDb;
  char const *azArg[4];
  char const *azArg[6];
  int meta[5];
  InitData initData;
  const char *zMasterName;
  const char *zSchemaTabName;
  int openedTransaction = 0;
  int mask = ((db->mDbFlags & DBFLAG_EncodingFixed) | ~DBFLAG_EncodingFixed);

  assert( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0 );
  assert( iDb>=0 && iDb<db->nDb );
  assert( db->aDb[iDb].pSchema );
  assert( sqlite3_mutex_held(db->mutex) );
  assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );

  db->init.busy = 1;

  /* Construct the in-memory representation schema tables (sqlite_master or
  ** sqlite_temp_master) by invoking the parser directly.  The appropriate
  /* Construct the in-memory representation schema tables (sqlite_schema or
  ** sqlite_temp_schema) by invoking the parser directly.  The appropriate
  ** table name will be inserted automatically by the parser so we can just
  ** use the abbreviation "x" here.  The parser will also automatically tag
  ** the schema table as read-only. */
  azArg[0] = "table";
  azArg[0] = zMasterName = SCHEMA_TABLE(iDb);
  azArg[1] = "1";
  azArg[2] = "CREATE TABLE x(type text,name text,tbl_name text,"
  azArg[1] = zSchemaTabName = SCHEMA_TABLE(iDb);
  azArg[2] = azArg[1];
  azArg[3] = "1";
  azArg[4] = "CREATE TABLE x(type text,name text,tbl_name text,"
                            "rootpage int,sql text)";
  azArg[3] = 0;
  azArg[5] = 0;
  initData.db = db;
  initData.iDb = iDb;
  initData.rc = SQLITE_OK;
  initData.pzErrMsg = pzErrMsg;
  initData.mInitFlags = mFlags;
  initData.nInitRow = 0;
  initData.mxPage = 0;
  sqlite3InitCallback(&initData, 3, (char **)azArg, 0);
  sqlite3InitCallback(&initData, 5, (char **)azArg, 0);
  db->mDbFlags &= mask;
  if( initData.rc ){
    rc = initData.rc;
    goto error_out;
  }

  /* Create a cursor to hold the database open
  */
  pDb = &db->aDb[iDb];
  if( pDb->pBt==0 ){
    assert( iDb==1 );
    DbSetProperty(db, 1, DB_SchemaLoaded);
    rc = SQLITE_OK;
    goto error_out;
  }

  /* 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 before this function returns.  */
  sqlite3BtreeEnter(pDb->pBt);
  if( !sqlite3BtreeIsInReadTrans(pDb->pBt) ){
  if( sqlite3BtreeTxnState(pDb->pBt)==SQLITE_TXN_NONE ){
    rc = sqlite3BtreeBeginTrans(pDb->pBt, 0, 0);
    if( rc!=SQLITE_OK ){
      sqlite3SetString(pzErrMsg, db, sqlite3ErrStr(rc));
      goto initone_error_out;
    }
    openedTransaction = 1;
  }
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
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







-
+
-

+



-

-
+

+
+
+
-
+
+
+
+

-
+






-
-








  /* If opening a non-empty database, check the text encoding. For the
  ** main database, set sqlite3.enc to the encoding of the main database.
  ** For an attached db, it is an error if the encoding is not the same
  ** as sqlite3.enc.
  */
  if( meta[BTREE_TEXT_ENCODING-1] ){  /* text encoding */
    if( iDb==0 ){
    if( iDb==0 && (db->mDbFlags & DBFLAG_EncodingFixed)==0 ){
#ifndef SQLITE_OMIT_UTF16
      u8 encoding;
#ifndef SQLITE_OMIT_UTF16
      /* If opening the main database, set ENC(db). */
      encoding = (u8)meta[BTREE_TEXT_ENCODING-1] & 3;
      if( encoding==0 ) encoding = SQLITE_UTF8;
      ENC(db) = encoding;
#else
      ENC(db) = SQLITE_UTF8;
      encoding = SQLITE_UTF8;
#endif
      if( db->nVdbeActive>0 && encoding!=ENC(db) ){
        rc = SQLITE_LOCKED;
        goto initone_error_out;
    }else{
      }else{
        sqlite3SetTextEncoding(db, encoding);
      }
    }else{
      /* If opening an attached database, the encoding much match ENC(db) */
      if( meta[BTREE_TEXT_ENCODING-1]!=ENC(db) ){
      if( (meta[BTREE_TEXT_ENCODING-1] & 3)!=ENC(db) ){
        sqlite3SetString(pzErrMsg, db, "attached databases must use the same"
            " text encoding as main database");
        rc = SQLITE_ERROR;
        goto initone_error_out;
      }
    }
  }else{
    DbSetProperty(db, iDb, DB_Empty);
  }
  pDb->pSchema->enc = ENC(db);

  if( pDb->pSchema->cache_size==0 ){
#ifndef SQLITE_OMIT_DEPRECATED
    size = sqlite3AbsInt32(meta[BTREE_DEFAULT_CACHE_SIZE-1]);
    if( size==0 ){ size = SQLITE_DEFAULT_CACHE_SIZE; }
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
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







+



-
-
+
+



















+



+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+







  if( iDb==0 && meta[BTREE_FILE_FORMAT-1]>=4 ){
    db->flags &= ~(u64)SQLITE_LegacyFileFmt;
  }

  /* Read the schema information out of the schema tables
  */
  assert( db->init.busy );
  initData.mxPage = sqlite3BtreeLastPage(pDb->pBt);
  {
    char *zSql;
    zSql = sqlite3MPrintf(db, 
        "SELECT name, rootpage, sql FROM \"%w\".%s ORDER BY rowid",
        db->aDb[iDb].zDbSName, zMasterName);
        "SELECT*FROM\"%w\".%s ORDER BY rowid",
        db->aDb[iDb].zDbSName, zSchemaTabName);
#ifndef SQLITE_OMIT_AUTHORIZATION
    {
      sqlite3_xauth xAuth;
      xAuth = db->xAuth;
      db->xAuth = 0;
#endif
      rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
#ifndef SQLITE_OMIT_AUTHORIZATION
      db->xAuth = xAuth;
    }
#endif
    if( rc==SQLITE_OK ) rc = initData.rc;
    sqlite3DbFree(db, zSql);
#ifndef SQLITE_OMIT_ANALYZE
    if( rc==SQLITE_OK ){
      sqlite3AnalysisLoad(db, iDb);
    }
#endif
  }
  assert( pDb == &(db->aDb[iDb]) );
  if( db->mallocFailed ){
    rc = SQLITE_NOMEM_BKPT;
    sqlite3ResetAllSchemasOfConnection(db);
    pDb = &db->aDb[iDb];
  }
  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_master table
    ** even when its contents have been corrupted.
  }else
  if( rc==SQLITE_OK || ((db->flags&SQLITE_NoSchemaError) && rc!=SQLITE_NOMEM)){
    /* Hack: If the SQLITE_NoSchemaError flag is set, then consider
    ** the schema loaded, even if errors (other than OOM) occurred. In
    ** this situation the current sqlite3_prepare() operation will fail,
    ** but the following one will attempt to compile the supplied statement
    ** against whatever subset of the schema was loaded before the error
    ** occurred.
    **
    ** The primary purpose of this is to allow access to the sqlite_schema
    ** table even when its contents have been corrupted.
    */
    DbSetProperty(db, iDb, DB_SchemaLoaded);
    rc = SQLITE_OK;
  }

  /* Jump here for an error that occurs after successfully allocating
  ** curMain and calling sqlite3BtreeEnter(). For an error that occurs
364
365
366
367
368
369
370
371

372
373
374
375
376
377
378
379
433
434
435
436
437
438
439

440

441
442
443
444
445
446
447







-
+
-







/*
** Initialize all database files - the main database file, the file
** used to store temporary tables, and any additional database files
** created using ATTACH statements.  Return a success code.  If an
** error occurs, write an error message into *pzErrMsg.
**
** After a database is initialized, the DB_SchemaLoaded bit is set
** bit is set in the flags field of the Db structure. If the database
** bit is set in the flags field of the Db structure. 
** file was of zero-length, then the DB_Empty flag is also set.
*/
int sqlite3Init(sqlite3 *db, char **pzErrMsg){
  int i, rc;
  int commit_internal = !(db->mDbFlags&DBFLAG_SchemaChange);
  
  assert( sqlite3_mutex_held(db->mutex) );
  assert( sqlite3BtreeHoldsMutex(db->aDb[0].pBt) );
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
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690

691
692
693
694
695

696
697
698
699
700
701
702

703
704
705
706
707
708
709
710

711
712
713
714
715
716
717
718
719
720







-
+



+











+

-

















-
+

-
+




-
-
+
+

-
+
+

















-
+

+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
+
+
+
+
+
+
+












-




+
-
+

+
+
+


-
+







-
+

+







    int openedTransaction = 0;         /* True if a transaction is opened */
    Btree *pBt = db->aDb[iDb].pBt;     /* Btree database to read cookie from */
    if( pBt==0 ) continue;

    /* 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( !sqlite3BtreeIsInReadTrans(pBt) ){
    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,
    ** set Parse.rc to SQLITE_SCHEMA. */
    sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&cookie);
    assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
    if( cookie!=db->aDb[iDb].pSchema->schema_cookie ){
      if( DbHasProperty(db, iDb, DB_SchemaLoaded) ) pParse->rc = SQLITE_SCHEMA;
      sqlite3ResetOneSchema(db, iDb);
      pParse->rc = SQLITE_SCHEMA;
    }

    /* Close the transaction, if one was opened. */
    if( openedTransaction ){
      sqlite3BtreeCommit(pBt);
    }
  }
}

/*
** Convert a schema pointer into the iDb index that indicates
** which database file in db->aDb[] the schema refers to.
**
** If the same database is attached more than once, the first
** attached database is returned.
*/
int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){
  int i = -1000000;
  int i = -32768;

  /* If pSchema is NULL, then return -1000000. This happens when code in 
  /* If pSchema is NULL, then return -32768. This happens when code in 
  ** expr.c is trying to resolve a reference to a transient table (i.e. one
  ** created by a sub-select). In this case the return value of this 
  ** function should never be used.
  **
  ** We return -1000000 instead of the more usual -1 simply because using
  ** -1000000 as the incorrect index into db->aDb[] is much 
  ** We return -32768 instead of the more usual -1 simply because using
  ** -32768 as the incorrect index into db->aDb[] is much 
  ** more likely to cause a segfault than -1 (of course there are assert()
  ** statements too, but it never hurts to play the odds).
  ** statements too, but it never hurts to play the odds) and
  ** -32768 will still fit into a 16-bit signed integer.
  */
  assert( sqlite3_mutex_held(db->mutex) );
  if( pSchema ){
    for(i=0; 1; i++){
      assert( i<db->nDb );
      if( db->aDb[i].pSchema==pSchema ){
        break;
      }
    }
    assert( i>=0 && i<db->nDb );
  }
  return i;
}

/*
** Free all memory allocations in the pParse object
*/
void sqlite3ParserReset(Parse *pParse){
void sqlite3ParseObjectReset(Parse *pParse){
  sqlite3 *db = pParse->db;
  assert( db!=0 );
  assert( db->pParse==pParse );
  assert( pParse->nested==0 );
#ifndef SQLITE_OMIT_SHARED_CACHE
  if( pParse->aTableLock ) sqlite3DbNNFreeNN(db, pParse->aTableLock);
#endif
  while( pParse->pCleanup ){
    ParseCleanup *pCleanup = pParse->pCleanup;
    pParse->pCleanup = pCleanup->pNext;
    pCleanup->xCleanup(db, pCleanup->pPtr);
    sqlite3DbNNFreeNN(db, pCleanup);
  }
  sqlite3DbFree(db, pParse->aLabel);
  sqlite3ExprListDelete(db, pParse->pConstExpr);
  if( pParse->aLabel ) sqlite3DbNNFreeNN(db, pParse->aLabel);
  if( pParse->pConstExpr ){
    sqlite3ExprListDelete(db, pParse->pConstExpr);
  if( db ){
    assert( db->lookaside.bDisable >= pParse->disableLookaside );
    db->lookaside.bDisable -= pParse->disableLookaside;
  }
  pParse->disableLookaside = 0;
  }
  assert( db->lookaside.bDisable >= pParse->disableLookaside );
  db->lookaside.bDisable -= pParse->disableLookaside;
  db->lookaside.sz = db->lookaside.bDisable ? 0 : db->lookaside.szTrue;
  assert( pParse->db->pParse==pParse );
  db->pParse = pParse->pOuterParse;
  pParse->db = 0;
  pParse->disableLookaside = 0;
}

/*
** Add a new cleanup operation to a Parser.  The cleanup should happen when
** the parser object is destroyed.  But, beware: the cleanup might happen
** immediately.
**
** Use this mechanism for uncommon cleanups.  There is a higher setup
** cost for this mechansim (an extra malloc), so it should not be used
** for common cleanups that happen on most calls.  But for less
** common cleanups, we save a single NULL-pointer comparison in
** sqlite3ParseObjectReset(), which reduces the total CPU cycle count.
**
** If a memory allocation error occurs, then the cleanup happens immediately.
** When either SQLITE_DEBUG or SQLITE_COVERAGE_TEST are defined, the
** pParse->earlyCleanup flag is set in that case.  Calling code show verify
** that test cases exist for which this happens, to guard against possible
** use-after-free errors following an OOM.  The preferred way to do this is
** to immediately follow the call to this routine with:
**
**       testcase( pParse->earlyCleanup );
**
** This routine returns a copy of its pPtr input (the third parameter)
** except if an early cleanup occurs, in which case it returns NULL.  So
** another way to check for early cleanup is to check the return value.
** Or, stop using the pPtr parameter with this call and use only its
** return value thereafter.  Something like this:
**
**       pObj = sqlite3ParserAddCleanup(pParse, destructor, pObj);
*/
void *sqlite3ParserAddCleanup(
  Parse *pParse,                      /* Destroy when this Parser finishes */
  void (*xCleanup)(sqlite3*,void*),   /* The cleanup routine */
  void *pPtr                          /* Pointer to object to be cleaned up */
){
  ParseCleanup *pCleanup = sqlite3DbMallocRaw(pParse->db, sizeof(*pCleanup));
  if( pCleanup ){
    pCleanup->pNext = pParse->pCleanup;
    pParse->pCleanup = pCleanup;
    pCleanup->pPtr = pPtr;
    pCleanup->xCleanup = xCleanup;
  }else{
    xCleanup(pParse->db, pPtr);
    pPtr = 0;
#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
    pParse->earlyCleanup = 1;
#endif
  }
  return pPtr;
}

/*
** Turn bulk memory into a valid Parse object and link that Parse object
** into database connection db.
**
** Call sqlite3ParseObjectReset() to undo this operation.
**
** Caution:  Do not confuse this routine with sqlite3ParseObjectInit() which
** is generated by Lemon.
*/
void sqlite3ParseObjectInit(Parse *pParse, sqlite3 *db){
  memset(PARSE_HDR(pParse), 0, PARSE_HDR_SZ);
  memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ);
  assert( db->pParse!=pParse );
  pParse->pOuterParse = db->pParse;
  db->pParse = pParse;
  pParse->db = db;
  if( db->mallocFailed ) sqlite3ErrorMsg(pParse, "out of memory");
}

/*
** Maximum number of times that we will try again to prepare a statement
** that returns SQLITE_ERROR_RETRY.
*/
#ifndef SQLITE_MAX_PREPARE_RETRY
# define SQLITE_MAX_PREPARE_RETRY 25
#endif

/*
** Compile the UTF-8 encoded SQL statement zSql into a statement handle.
*/
static int sqlite3Prepare(
  sqlite3 *db,              /* Database handle. */
  const char *zSql,         /* UTF-8 encoded SQL statement. */
  int nBytes,               /* Length of zSql in bytes. */
  u32 prepFlags,            /* Zero or more SQLITE_PREPARE_* flags */
  Vdbe *pReprepare,         /* VM being reprepared */
  sqlite3_stmt **ppStmt,    /* OUT: A pointer to the prepared statement */
  const char **pzTail       /* OUT: End of parsed string */
){
  char *zErrMsg = 0;        /* Error message */
  int rc = SQLITE_OK;       /* Result code */
  int i;                    /* Loop counter */
  Parse sParse;             /* Parsing context */

  /* sqlite3ParseObjectInit(&sParse, db); // inlined for performance */
  memset(&sParse, 0, PARSE_HDR_SZ);
  memset(PARSE_HDR(&sParse), 0, PARSE_HDR_SZ);
  memset(PARSE_TAIL(&sParse), 0, PARSE_TAIL_SZ);
  sParse.pOuterParse = db->pParse;
  db->pParse = &sParse;
  sParse.db = db;
  sParse.pReprepare = pReprepare;
  assert( ppStmt && *ppStmt==0 );
  /* assert( !db->mallocFailed ); // not true with SQLITE_USE_ALLOCA */
  if( db->mallocFailed ) sqlite3ErrorMsg(&sParse, "out of memory");
  assert( sqlite3_mutex_held(db->mutex) );

  /* For a long-term use prepared statement avoid the use of
  ** lookaside memory.
  */
  if( prepFlags & SQLITE_PREPARE_PERSISTENT ){
    sParse.disableLookaside++;
    db->lookaside.bDisable++;
    DisableLookaside;
  }
  sParse.prepFlags = prepFlags & 0xff;

  /* Check to verify that it is possible to get a read lock on all
  ** database schemas.  The inability to get a read lock indicates that
  ** some other database connection is holding a write-lock, which in
  ** turn means that the other connection has made uncommitted changes
  ** to the schema.
  **
565
566
567
568
569
570
571

572
573
574
575
576
577
578
579
580
581











582
583
584
585

586


587
588
589
590
591
592
593
594
595
596
597
598
599
600
601

602
603
604
605
606
607
608

609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649








650
651


652
653
654
655
656
657
658
659
660
661
662
















663
664
665
666
667
668
669
670
671
672
673

674
675
676
677
678
679
680
731
732
733
734
735
736
737
738










739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754

755
756
757

758
759
760
761
762
763
764
765
766
767
768
769

770
771
772
773
774
775
776

777
778
779
780







781
782
783
























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







+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+




+
-
+
+

-












-
+






-
+



-
-
-
-
-
-
-



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-




+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










-
+







  ** locks on the schema, we just need to make sure nobody else is 
  ** holding them.
  **
  ** Note that setting READ_UNCOMMITTED overrides most lock detection,
  ** but it does *not* override schema lock detection, so this all still
  ** works even if READ_UNCOMMITTED is set.
  */
  if( !db->noSharedCache ){
  for(i=0; i<db->nDb; i++) {
    Btree *pBt = db->aDb[i].pBt;
    if( pBt ){
      assert( sqlite3BtreeHoldsMutex(pBt) );
      rc = sqlite3BtreeSchemaLocked(pBt);
      if( rc ){
        const char *zDb = db->aDb[i].zDbSName;
        sqlite3ErrorWithMsg(db, rc, "database schema is locked: %s", zDb);
        testcase( db->flags & SQLITE_ReadUncommit );
        goto end_prepare;
    for(i=0; i<db->nDb; i++) {
      Btree *pBt = db->aDb[i].pBt;
      if( pBt ){
        assert( sqlite3BtreeHoldsMutex(pBt) );
        rc = sqlite3BtreeSchemaLocked(pBt);
        if( rc ){
          const char *zDb = db->aDb[i].zDbSName;
          sqlite3ErrorWithMsg(db, rc, "database schema is locked: %s", zDb);
          testcase( db->flags & SQLITE_ReadUncommit );
          goto end_prepare;
        }
      }
    }
  }

#ifndef SQLITE_OMIT_VIRTUALTABLE
  sqlite3VtabUnlockList(db);
  if( db->pDisconnect ) sqlite3VtabUnlockList(db);
#endif

  sParse.db = db;
  if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){
    char *zSqlCopy;
    int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
    testcase( nBytes==mxLen );
    testcase( nBytes==mxLen+1 );
    if( nBytes>mxLen ){
      sqlite3ErrorWithMsg(db, SQLITE_TOOBIG, "statement too long");
      rc = sqlite3ApiExit(db, SQLITE_TOOBIG);
      goto end_prepare;
    }
    zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes);
    if( zSqlCopy ){
      sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg);
      sqlite3RunParser(&sParse, zSqlCopy);
      sParse.zTail = &zSql[sParse.zTail-zSqlCopy];
      sqlite3DbFree(db, zSqlCopy);
    }else{
      sParse.zTail = &zSql[nBytes];
    }
  }else{
    sqlite3RunParser(&sParse, zSql, &zErrMsg);
    sqlite3RunParser(&sParse, zSql);
  }
  assert( 0==sParse.nQueryLoop );

  if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK;
  if( sParse.checkSchema ){
    schemaIsValid(&sParse);
  }
  if( db->mallocFailed ){
    sParse.rc = SQLITE_NOMEM_BKPT;
  }
  if( pzTail ){
    *pzTail = sParse.zTail;
  }
  rc = sParse.rc;

#ifndef SQLITE_OMIT_EXPLAIN
  if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){
    static const char * const azColName[] = {
       "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment",
       "id", "parent", "notused", "detail"
    };
    int iFirst, mx;
    if( sParse.explain==2 ){
      sqlite3VdbeSetNumCols(sParse.pVdbe, 4);
      iFirst = 8;
      mx = 12;
    }else{
      sqlite3VdbeSetNumCols(sParse.pVdbe, 8);
      iFirst = 0;
      mx = 8;
    }
    for(i=iFirst; i<mx; i++){
      sqlite3VdbeSetColName(sParse.pVdbe, i-iFirst, COLNAME_NAME,
                            azColName[i], SQLITE_STATIC);
    }
  }
#endif

  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 && db->init.busy==0 ){
      schemaIsValid(&sParse);
    }
  if( sParse.pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){
    sqlite3VdbeFinalize(sParse.pVdbe);
    if( sParse.pVdbe ){
      sqlite3VdbeFinalize(sParse.pVdbe);
    assert(!(*ppStmt));
  }else{
    *ppStmt = (sqlite3_stmt*)sParse.pVdbe;
  }

  if( zErrMsg ){
    sqlite3ErrorWithMsg(db, rc, "%s", zErrMsg);
    sqlite3DbFree(db, zErrMsg);
  }else{
    sqlite3Error(db, rc);
  }
    }
    assert( 0==(*ppStmt) );
    rc = sParse.rc;
    if( sParse.zErrMsg ){
      sqlite3ErrorWithMsg(db, rc, "%s", sParse.zErrMsg);
      sqlite3DbFree(db, sParse.zErrMsg);
    }else{
      sqlite3Error(db, rc);
    }
  }else{
    assert( sParse.zErrMsg==0 );
    *ppStmt = (sqlite3_stmt*)sParse.pVdbe;
    rc = SQLITE_OK;
    sqlite3ErrorClear(db);
  }


  /* Delete any TriggerPrg structures allocated while parsing this statement. */
  while( sParse.pTriggerPrg ){
    TriggerPrg *pT = sParse.pTriggerPrg;
    sParse.pTriggerPrg = pT->pNext;
    sqlite3DbFree(db, pT);
  }

end_prepare:

  sqlite3ParserReset(&sParse);
  sqlite3ParseObjectReset(&sParse);
  return rc;
}
static int sqlite3LockAndPrepare(
  sqlite3 *db,              /* Database handle. */
  const char *zSql,         /* UTF-8 encoded SQL statement. */
  int nBytes,               /* Length of zSql in bytes. */
  u32 prepFlags,            /* Zero or more SQLITE_PREPARE_* flags */
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
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







+
-
+




+










-
+







  sqlite3BtreeEnterAll(db);
  do{
    /* Make multiple attempts to compile the SQL, until it either succeeds
    ** or encounters a permanent error.  A schema problem after one schema
    ** reset is considered a permanent error. */
    rc = sqlite3Prepare(db, zSql, nBytes, prepFlags, pOld, ppStmt, pzTail);
    assert( rc==SQLITE_OK || *ppStmt==0 );
    if( rc==SQLITE_OK || db->mallocFailed ) break;
  }while( rc==SQLITE_ERROR_RETRY
  }while( (rc==SQLITE_ERROR_RETRY && (cnt++)<SQLITE_MAX_PREPARE_RETRY)
       || (rc==SQLITE_SCHEMA && (sqlite3ResetOneSchema(db,-1), cnt++)==0) );
  sqlite3BtreeLeaveAll(db);
  rc = sqlite3ApiExit(db, rc);
  assert( (rc&db->errMask)==rc );
  db->busyHandler.nBusy = 0;
  sqlite3_mutex_leave(db->mutex);
  return rc;
}


/*
** Rerun the compilation of a statement after a schema change.
**
** If the statement is successfully recompiled, return SQLITE_OK. Otherwise,
** if the statement cannot be recompiled because another connection has
** locked the sqlite3_master table, return SQLITE_LOCKED. If any other error
** locked the sqlite3_schema table, return SQLITE_LOCKED. If any other error
** occurs, return SQLITE_SCHEMA.
*/
int sqlite3Reprepare(Vdbe *p){
  int rc;
  sqlite3_stmt *pNew;
  const char *zSql;
  sqlite3 *db;

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
114
115
116
117
118
119







-
+


+
+
+
+
+
+
+
+
+
+
+
+







  {  '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,
};

/*
** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating point
** conversions will work.
*/
#ifndef SQLITE_OMIT_FLOATING_POINT
/*
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
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







-
+


-
+
+


















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










+
+
+
+
+
+
+







  return (char)digit;
}
#endif /* SQLITE_OMIT_FLOATING_POINT */

/*
** Set the StrAccum object to an error mode.
*/
static void setStrAccumError(StrAccum *p, u8 eError){
void sqlite3StrAccumSetError(StrAccum *p, u8 eError){
  assert( eError==SQLITE_NOMEM || eError==SQLITE_TOOBIG );
  p->accError = eError;
  p->nAlloc = 0;
  if( p->mxAlloc ) sqlite3_str_reset(p);
  if( eError==SQLITE_TOOBIG ) sqlite3ErrorToParser(p->db, eError);
}

/*
** Extra argument values from a PrintfArguments object
*/
static sqlite3_int64 getIntArg(PrintfArguments *p){
  if( p->nArg<=p->nUsed ) return 0;
  return sqlite3_value_int64(p->apArg[p->nUsed++]);
}
static double getDoubleArg(PrintfArguments *p){
  if( p->nArg<=p->nUsed ) return 0.0;
  return sqlite3_value_double(p->apArg[p->nUsed++]);
}
static char *getTextArg(PrintfArguments *p){
  if( p->nArg<=p->nUsed ) return 0;
  return (char*)sqlite3_value_text(p->apArg[p->nUsed++]);
}

/*
** Allocate memory for a temporary buffer needed for printf rendering.
**
** If the requested size of the temp buffer is larger than the size
** of the output buffer in pAccum, then cause an SQLITE_TOOBIG error.
** Do the size check before the memory allocation to prevent rogue
** SQL from requesting large allocations using the precision or width
** field of the printf() function.
*/
static char *printfTempBuf(sqlite3_str *pAccum, sqlite3_int64 n){
  char *z;
  if( pAccum->accError ) return 0;
  if( n>pAccum->nAlloc && n>pAccum->mxAlloc ){
    sqlite3StrAccumSetError(pAccum, SQLITE_TOOBIG);
    return 0;
  }
  z = sqlite3DbMallocRaw(pAccum->db, n);
  if( z==0 ){
    sqlite3StrAccumSetError(pAccum, SQLITE_NOMEM);
  }
  return z;
}

/*
** On machines with a small stack size, you can redefine the
** SQLITE_PRINT_BUF_SIZE to be something smaller, if desired.
*/
#ifndef SQLITE_PRINT_BUF_SIZE
# define SQLITE_PRINT_BUF_SIZE 70
#endif
#define etBUFSIZE SQLITE_PRINT_BUF_SIZE  /* Size of the output buffer */

/*
** Hard limit on the precision of floating-point conversions.
*/
#ifndef SQLITE_PRINTF_PRECISION_LIMIT
# define SQLITE_FP_PRECISION_LIMIT 100000000
#endif

/*
** Render a string given by "fmt" into the StrAccum object.
*/
void sqlite3_str_vappendf(
  sqlite3_str *pAccum,       /* Accumulate results here */
  const char *fmt,           /* Format string */
  va_list ap                 /* arguments */
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
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







+
+
+










+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







      sqlite3_str_append(pAccum, "%", 1);
      break;
    }
    /* Find out what flags are present */
    flag_leftjustify = flag_prefix = cThousand =
     flag_alternateform = flag_altform2 = flag_zeropad = 0;
    done = 0;
    width = 0;
    flag_long = 0;
    precision = -1;
    do{
      switch( c ){
        case '-':   flag_leftjustify = 1;     break;
        case '+':   flag_prefix = '+';        break;
        case ' ':   flag_prefix = ' ';        break;
        case '#':   flag_alternateform = 1;   break;
        case '!':   flag_altform2 = 1;        break;
        case '0':   flag_zeropad = 1;         break;
        case ',':   cThousand = ',';          break;
        default:    done = 1;                 break;
        case 'l': {
          flag_long = 1;
          c = *++fmt;
          if( c=='l' ){
            c = *++fmt;
            flag_long = 2;
          }
          done = 1;
          break;
        }
        case '1': case '2': case '3': case '4': case '5':
        case '6': case '7': case '8': case '9': {
          unsigned wx = c - '0';
          while( (c = *++fmt)>='0' && c<='9' ){
            wx = wx*10 + c - '0';
          }
          testcase( wx>0x7fffffff );
          width = wx & 0x7fffffff;
#ifdef SQLITE_PRINTF_PRECISION_LIMIT
          if( width>SQLITE_PRINTF_PRECISION_LIMIT ){
            width = SQLITE_PRINTF_PRECISION_LIMIT;
          }
#endif
          if( c!='.' && c!='l' ){
            done = 1;
          }else{
            fmt--;
          }
          break;
        }
        case '*': {
          if( bArgList ){
            width = (int)getIntArg(pArgList);
          }else{
            width = va_arg(ap,int);
          }
          if( width<0 ){
            flag_leftjustify = 1;
            width = width >= -2147483647 ? -width : 0;
          }
#ifdef SQLITE_PRINTF_PRECISION_LIMIT
          if( width>SQLITE_PRINTF_PRECISION_LIMIT ){
            width = SQLITE_PRINTF_PRECISION_LIMIT;
          }
#endif
          if( (c = fmt[1])!='.' && c!='l' ){
            c = *++fmt;
            done = 1;
          }
          break;
        }
        case '.': {
          c = *++fmt;
          if( c=='*' ){
            if( bArgList ){
              precision = (int)getIntArg(pArgList);
            }else{
              precision = va_arg(ap,int);
            }
            if( precision<0 ){
              precision = precision >= -2147483647 ? -precision : -1;
            }
            c = *++fmt;
          }else{
            unsigned px = 0;
            while( c>='0' && c<='9' ){
              px = px*10 + c - '0';
              c = *++fmt;
            }
            testcase( px>0x7fffffff );
            precision = px & 0x7fffffff;
          }
#ifdef SQLITE_PRINTF_PRECISION_LIMIT
          if( precision>SQLITE_PRINTF_PRECISION_LIMIT ){
            precision = SQLITE_PRINTF_PRECISION_LIMIT;
          }
#endif
          if( c=='l' ){
            --fmt;
          }else{
            done = 1;
          }
          break;
        }
      }
    }while( !done && (c=(*++fmt))!=0 );
    /* Get the field width */
    if( c=='*' ){
      if( bArgList ){
        width = (int)getIntArg(pArgList);
      }else{
        width = va_arg(ap,int);
      }

      if( width<0 ){
        flag_leftjustify = 1;
        width = width >= -2147483647 ? -width : 0;
      }
      c = *++fmt;
    }else{
      unsigned wx = 0;
      while( c>='0' && c<='9' ){
        wx = wx*10 + c - '0';
        c = *++fmt;
      }
      testcase( wx>0x7fffffff );
      width = wx & 0x7fffffff;
    }
    assert( width>=0 );
#ifdef SQLITE_PRINTF_PRECISION_LIMIT
    if( width>SQLITE_PRINTF_PRECISION_LIMIT ){
      width = SQLITE_PRINTF_PRECISION_LIMIT;
    }
#endif

    /* Get the precision */
    if( c=='.' ){
      c = *++fmt;
      if( c=='*' ){
        if( bArgList ){
          precision = (int)getIntArg(pArgList);
        }else{
          precision = va_arg(ap,int);
        }
        c = *++fmt;
        if( precision<0 ){
          precision = precision >= -2147483647 ? -precision : -1;
        }
      }else{
        unsigned px = 0;
        while( c>='0' && c<='9' ){
          px = px*10 + c - '0';
          c = *++fmt;
        }
        testcase( px>0x7fffffff );
        precision = px & 0x7fffffff;
      }
    }else{
      precision = -1;
    }
    assert( precision>=(-1) );
#ifdef SQLITE_PRINTF_PRECISION_LIMIT
    if( precision>SQLITE_PRINTF_PRECISION_LIMIT ){
      precision = SQLITE_PRINTF_PRECISION_LIMIT;
    }
#endif


    /* Get the conversion type modifier */
    if( c=='l' ){
      flag_long = 1;
      c = *++fmt;
      if( c=='l' ){
        flag_long = 2;
        c = *++fmt;
      }
    }else{
      flag_long = 0;
    }
    /* Fetch the info entry for the field */
    infop = &fmtinfo[0];
    xtype = etINVALID;
    for(idx=0; idx<ArraySize(fmtinfo); idx++){
      if( c==fmtinfo[idx].fmttype ){
        infop = &fmtinfo[idx];
        xtype = infop->type;
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
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







+
+




-
+



-
+















-
-
+
+
+
-
-
+
-







    **   width                       The specified field width.  This is
    **                               always non-negative.  Zero is the default.
    **   precision                   The specified precision.  The default
    **                               is -1.
    **   xtype                       The class of the conversion.
    **   infop                       Pointer to the appropriate info struct.
    */
    assert( width>=0 );
    assert( precision>=(-1) );
    switch( xtype ){
      case etPOINTER:
        flag_long = sizeof(char*)==sizeof(i64) ? 2 :
                     sizeof(char*)==sizeof(long int) ? 1 : 0;
        /* Fall through into the next case */
        /* no break */ deliberate_fall_through
      case etORDINAL:
      case etRADIX:      
        cThousand = 0;
        /* Fall through into the next case */
        /* no break */ deliberate_fall_through
      case etDECIMAL:
        if( infop->flags & FLAG_SIGNED ){
          i64 v;
          if( bArgList ){
            v = getIntArg(pArgList);
          }else if( flag_long ){
            if( flag_long==2 ){
              v = va_arg(ap,i64) ;
            }else{
              v = va_arg(ap,long int);
            }
          }else{
            v = va_arg(ap,int);
          }
          if( v<0 ){
            if( v==SMALLEST_INT64 ){
              longvalue = ((u64)1)<<63;
            testcase( v==SMALLEST_INT64 );
            testcase( v==(-1) );
            longvalue = ~v;
            }else{
              longvalue = -v;
            longvalue++;
            }
            prefix = '-';
          }else{
            longvalue = v;
            prefix = flag_prefix;
          }
        }else{
          if( bArgList ){
401
402
403
404
405
406
407

408
409
410




411
412
413
414
415
416
417
418
419
420
460
461
462
463
464
465
466
467



468
469
470
471



472
473
474
475
476
477
478







+
-
-
-
+
+
+
+
-
-
-







        if( flag_zeropad && precision<width-(prefix!=0) ){
          precision = width-(prefix!=0);
        }
        if( precision<etBUFSIZE-10-etBUFSIZE/3 ){
          nOut = etBUFSIZE;
          zOut = buf;
        }else{
          u64 n;
          u64 n = (u64)precision + 10 + precision/3;
          zOut = zExtra = sqlite3Malloc( n );
          if( zOut==0 ){
          n = (u64)precision + 10;
          if( cThousand ) n += precision/3;
          zOut = zExtra = printfTempBuf(pAccum, n);
          if( zOut==0 ) return;
            setStrAccumError(pAccum, SQLITE_NOMEM);
            return;
          }
          nOut = (int)n;
        }
        bufpt = &zOut[nOut-1];
        if( xtype==etORDINAL ){
          static const char zOrd[] = "thstndrd";
          int x = (int)(longvalue % 10);
          if( x>=4 || (longvalue/10)%10==1 ){
467
468
469
470
471
472
473





474
475
476
477
478
479
480
481
482
483












484
485
486
487
488
489
490
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







+
+
+
+
+








-
-
+
+
+
+
+
+
+
+
+
+
+
+







        }else{
          realvalue = va_arg(ap,double);
        }
#ifdef SQLITE_OMIT_FLOATING_POINT
        length = 0;
#else
        if( precision<0 ) precision = 6;         /* Set default precision */
#ifdef SQLITE_FP_PRECISION_LIMIT
        if( precision>SQLITE_FP_PRECISION_LIMIT ){
          precision = SQLITE_FP_PRECISION_LIMIT;
        }
#endif
        if( realvalue<0.0 ){
          realvalue = -realvalue;
          prefix = '-';
        }else{
          prefix = flag_prefix;
        }
        if( xtype==etGENERIC && precision>0 ) precision--;
        testcase( precision>0xfff );
        for(idx=precision&0xfff, rounder=0.5; idx>0; idx--, rounder*=0.1){}
        if( xtype==etFLOAT ) realvalue += rounder;
        idx = precision & 0xfff;
        rounder = arRound[idx%10];
        while( idx>=10 ){ rounder *= 1.0e-10; idx -= 10; }
        if( xtype==etFLOAT ){
          double rx = (double)realvalue;
          sqlite3_uint64 u;
          int ex;
          memcpy(&u, &rx, sizeof(u));
          ex = -1023 + (int)((u>>52)&0x7ff);
          if( precision+(ex/3) < 15 ) rounder += realvalue*3e-16;
          realvalue += rounder;
        }
        /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
        exp = 0;
        if( sqlite3IsNaN((double)realvalue) ){
          bufpt = "NaN";
          length = 3;
          break;
        }
525
526
527
528
529
530
531


532
533



534
535

536
537
538
539
540
541
542
543
544
598
599
600
601
602
603
604
605
606


607
608
609


610


611
612
613
614
615
616
617







+
+
-
-
+
+
+
-
-
+
-
-







          flag_rtz = flag_altform2;
        }
        if( xtype==etEXP ){
          e2 = 0;
        }else{
          e2 = exp;
        }
        {
          i64 szBufNeeded;           /* Size of a temporary buffer needed */
        if( MAX(e2,0)+(i64)precision+(i64)width > etBUFSIZE - 15 ){
          bufpt = zExtra 
          szBufNeeded = MAX(e2,0)+(i64)precision+(i64)width+15;
          if( szBufNeeded > etBUFSIZE ){
            bufpt = zExtra = printfTempBuf(pAccum, szBufNeeded);
              = sqlite3Malloc( MAX(e2,0)+(i64)precision+(i64)width+15 );
          if( bufpt==0 ){
            if( bufpt==0 ) return;
            setStrAccumError(pAccum, SQLITE_NOMEM);
            return;
          }
        }
        zOut = bufpt;
        nsd = 16 + flag_altform2*10;
        flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2;
        /* The sign in front of the number */
        if( prefix ){
659
660
661
662
663
664
665

666
667
668
669
670


671
672












673
674
675
676
677
678
679
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







+





+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+







            buf[1] = 0x80 + (u8)((ch>>12) & 0x3f);
            buf[2] = 0x80 + (u8)((ch>>6) & 0x3f);
            buf[3] = 0x80 + (u8)(ch & 0x3f);
            length = 4;
          }
        }
        if( precision>1 ){
          i64 nPrior = 1;
          width -= precision-1;
          if( width>1 && !flag_leftjustify ){
            sqlite3_str_appendchar(pAccum, width-1, ' ');
            width = 0;
          }
          sqlite3_str_append(pAccum, buf, length);
          precision--;
          while( precision-- > 1 ){
            sqlite3_str_append(pAccum, buf, length);
          while( precision > 1 ){
            i64 nCopyBytes;
            if( nPrior > precision-1 ) nPrior = precision - 1;
            nCopyBytes = length*nPrior;
            if( nCopyBytes + pAccum->nChar >= pAccum->nAlloc ){
              sqlite3StrAccumEnlarge(pAccum, nCopyBytes);
            }
            if( pAccum->accError ) break;
            sqlite3_str_append(pAccum,
                 &pAccum->zText[pAccum->nChar-nCopyBytes], nCopyBytes);
            precision -= nPrior;
            nPrior *= 2;
          }
        }
        bufpt = buf;
        flag_altform2 = 1;
        goto adjust_width_for_utf8;
      case etSTRING:
      case etDYNSTRING:
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
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
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
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915







-
-
+
+











-
+














-
-
+
+
-
-
-
















-

+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+




-
+
-
-
-
+

-
+
-
-

-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







          int ii = length - 1;
          while( ii>=0 ) if( (bufpt[ii--] & 0xc0)==0x80 ) width++;
        }
        break;
      case etSQLESCAPE:           /* %q: Escape ' characters */
      case etSQLESCAPE2:          /* %Q: Escape ' and enclose in '...' */
      case etSQLESCAPE3: {        /* %w: Escape " characters */
        int i, j, k, n, isnull;
        int needQuote;
        i64 i, j, k, n;
        int needQuote, isnull;
        char ch;
        char q = ((xtype==etSQLESCAPE3)?'"':'\'');   /* Quote character */
        char *escarg;

        if( bArgList ){
          escarg = getTextArg(pArgList);
        }else{
          escarg = va_arg(ap,char*);
        }
        isnull = escarg==0;
        if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
        /* For %q, %Q, and %w, the precision is the number of byte (or
        /* For %q, %Q, and %w, the precision is the number of bytes (or
        ** characters if the ! flags is present) to use from the input.
        ** Because of the extra quoting characters inserted, the number
        ** of output characters may be larger than the precision.
        */
        k = precision;
        for(i=n=0; k!=0 && (ch=escarg[i])!=0; i++, k--){
          if( ch==q )  n++;
          if( flag_altform2 && (ch&0xc0)==0xc0 ){
            while( (escarg[i+1]&0xc0)==0x80 ){ i++; }
          }
        }
        needQuote = !isnull && xtype==etSQLESCAPE2;
        n += i + 3;
        if( n>etBUFSIZE ){
          bufpt = zExtra = sqlite3Malloc( n );
          if( bufpt==0 ){
          bufpt = zExtra = printfTempBuf(pAccum, n);
          if( bufpt==0 ) return;
            setStrAccumError(pAccum, SQLITE_NOMEM);
            return;
          }
        }else{
          bufpt = buf;
        }
        j = 0;
        if( needQuote ) bufpt[j++] = q;
        k = i;
        for(i=0; i<k; i++){
          bufpt[j++] = ch = escarg[i];
          if( ch==q ) bufpt[j++] = ch;
        }
        if( needQuote ) bufpt[j++] = q;
        bufpt[j] = 0;
        length = j;
        goto adjust_width_for_utf8;
      }
      case etTOKEN: {
        Token *pToken;
        if( (pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return;
        if( flag_alternateform ){
          /* %#T means an Expr pointer that uses Expr.u.zToken */
          Expr *pExpr = va_arg(ap,Expr*);
          if( ALWAYS(pExpr) && ALWAYS(!ExprHasProperty(pExpr,EP_IntValue)) ){
            sqlite3_str_appendall(pAccum, (const char*)pExpr->u.zToken);
            sqlite3RecordErrorOffsetOfExpr(pAccum->db, pExpr);
          }
        }else{
          /* %T means a Token pointer */
        pToken = va_arg(ap, Token*);
        assert( bArgList==0 );
        if( pToken && pToken->n ){
          sqlite3_str_append(pAccum, (const char*)pToken->z, pToken->n);
          Token *pToken = va_arg(ap, Token*);
          assert( bArgList==0 );
          if( pToken && pToken->n ){
            sqlite3_str_append(pAccum, (const char*)pToken->z, pToken->n);
            sqlite3RecordErrorByteOffset(pAccum->db, pToken->z);
          }
        }
        length = width = 0;
        break;
      }
      case etSRCLIST: {
      case etSRCITEM: {
        SrcList *pSrc;
        int k;
        struct SrcList_item *pItem;
        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{
          Select *pSel = pItem->pSelect;
          assert( pSel!=0 );
          if( pSel->selFlags & SF_NestedFrom ){
            sqlite3_str_appendf(pAccum, "(join-%u)", pSel->selId);
          }else{
            sqlite3_str_appendf(pAccum, "(subquery-%u)", pSel->selId);
          }
        }
        length = width = 0;
        break;
      }
      default: {
        assert( xtype==etINVALID );
        return;
      }
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
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985

986
987

988
989
990
991
992
993
994



995
996
997
998

999

1000
1001
1002
1003
1004
1005
1006

1007
1008
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
+

-
+






-
-
-
+
+


-
+
-







-
+







-
+









-
+



+
-
+







    if( zExtra ){
      sqlite3DbFree(pAccum->db, zExtra);
      zExtra = 0;
    }
  }/* End for loop over the format string */
} /* End of function */


/*
** The z string points to the first character of a token that is
** associated with an error.  If db does not already have an error
** byte offset recorded, try to compute the error byte offset for
** z and set the error byte offset in db.
*/
void sqlite3RecordErrorByteOffset(sqlite3 *db, const char *z){
  const Parse *pParse;
  const char *zText;
  const char *zEnd;
  assert( z!=0 );
  if( NEVER(db==0) ) return;
  if( db->errByteOffset!=(-2) ) return;
  pParse = db->pParse;
  if( NEVER(pParse==0) ) return;
  zText =pParse->zTail;
  if( NEVER(zText==0) ) return;
  zEnd = &zText[strlen(zText)];
  if( SQLITE_WITHIN(z,zText,zEnd) ){
    db->errByteOffset = (int)(z-zText);
  }
}

/*
** If pExpr has a byte offset for the start of a token, record that as
** as the error offset.
*/
void sqlite3RecordErrorOffsetOfExpr(sqlite3 *db, const Expr *pExpr){
  while( pExpr
     && (ExprHasProperty(pExpr,EP_OuterON|EP_InnerON) || pExpr->w.iOfst<=0)
  ){
    pExpr = pExpr->pLeft;
  }
  if( pExpr==0 ) return;
  db->errByteOffset = pExpr->w.iOfst;
}

/*
** Enlarge the memory allocation on a StrAccum object so that it is
** able to accept at least N more bytes of text.
**
** Return the number of bytes of text that StrAccum is able to accept
** after the attempted enlargement.  The value returned might be zero.
*/
static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
int sqlite3StrAccumEnlarge(StrAccum *p, i64 N){
  char *zNew;
  assert( p->nChar+(i64)N >= p->nAlloc ); /* Only called if really needed */
  assert( p->nChar+N >= p->nAlloc ); /* Only called if really needed */
  if( p->accError ){
    testcase(p->accError==SQLITE_TOOBIG);
    testcase(p->accError==SQLITE_NOMEM);
    return 0;
  }
  if( p->mxAlloc==0 ){
    N = p->nAlloc - p->nChar - 1;
    setStrAccumError(p, SQLITE_TOOBIG);
    return N;
    sqlite3StrAccumSetError(p, SQLITE_TOOBIG);
    return p->nAlloc - p->nChar - 1;
  }else{
    char *zOld = isMalloced(p) ? p->zText : 0;
    i64 szNew = p->nChar;
    i64 szNew = p->nChar + N + 1;
    szNew += N + 1;
    if( szNew+p->nChar<=p->mxAlloc ){
      /* Force exponential buffer size growth as long as it does not overflow,
      ** to avoid having to call this routine too often */
      szNew += p->nChar;
    }
    if( szNew > p->mxAlloc ){
      sqlite3_str_reset(p);
      setStrAccumError(p, SQLITE_TOOBIG);
      sqlite3StrAccumSetError(p, SQLITE_TOOBIG);
      return 0;
    }else{
      p->nAlloc = (int)szNew;
    }
    if( p->db ){
      zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
    }else{
      zNew = sqlite3_realloc64(zOld, p->nAlloc);
      zNew = sqlite3Realloc(zOld, p->nAlloc);
    }
    if( zNew ){
      assert( p->zText!=0 || p->nChar==0 );
      if( !isMalloced(p) && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
      p->zText = zNew;
      p->nAlloc = sqlite3DbMallocSize(p->db, zNew);
      p->printfFlags |= SQLITE_PRINTF_MALLOCED;
    }else{
      sqlite3_str_reset(p);
      setStrAccumError(p, SQLITE_NOMEM);
      sqlite3StrAccumSetError(p, SQLITE_NOMEM);
      return 0;
    }
  }
  assert( N>=0 && N<=0x7fffffff );
  return N;
  return (int)N;
}

/*
** Append N copies of character c to the given string buffer.
*/
void sqlite3_str_appendchar(sqlite3_str *p, int N, char c){
  testcase( p->nChar + (i64)N > 0x7fffffff );
922
923
924
925
926
927
928
929

930
931
932
933
934
935
936
1061
1062
1063
1064
1065
1066
1067

1068
1069
1070
1071
1072
1073
1074
1075







-
+







** Append N bytes of text from z to the StrAccum object.  Increase the
** size of the memory allocation for StrAccum if necessary.
*/
void sqlite3_str_append(sqlite3_str *p, const char *z, int N){
  assert( z!=0 || N==0 );
  assert( p->zText!=0 || p->nChar==0 || p->accError );
  assert( N>=0 );
  assert( p->accError==0 || p->nAlloc==0 );
  assert( p->accError==0 || p->nAlloc==0 || p->mxAlloc==0 );
  if( p->nChar+N >= p->nAlloc ){
    enlargeAndAppend(p,z,N);
  }else if( N ){
    assert( p->zText );
    p->nChar += N;
    memcpy(&p->zText[p->nChar-N], z, N);
  }
953
954
955
956
957
958
959
960

961
962
963
964
965
966
967
968
969
970
971
972
973
















974
975
976
977
978
979
980
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







-
+













+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  char *zText;
  assert( p->mxAlloc>0 && !isMalloced(p) );
  zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
  if( zText ){
    memcpy(zText, p->zText, p->nChar+1);
    p->printfFlags |= SQLITE_PRINTF_MALLOCED;
  }else{
    setStrAccumError(p, SQLITE_NOMEM);
    sqlite3StrAccumSetError(p, SQLITE_NOMEM);
  }
  p->zText = zText;
  return zText;
}
char *sqlite3StrAccumFinish(StrAccum *p){
  if( p->zText ){
    p->zText[p->nChar] = 0;
    if( p->mxAlloc>0 && !isMalloced(p) ){
      return strAccumFinishRealloc(p);
    }
  }
  return p->zText;
}

/*
** Use the content of the StrAccum passed as the second argument
** as the result of an SQL function.
*/
void sqlite3ResultStrAccum(sqlite3_context *pCtx, StrAccum *p){
  if( p->accError ){
    sqlite3_result_error_code(pCtx, p->accError);
    sqlite3_str_reset(p);
  }else if( isMalloced(p) ){
    sqlite3_result_text(pCtx, p->zText, p->nChar, SQLITE_DYNAMIC);
  }else{
    sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC);
    sqlite3_str_reset(p);
  }
}

/*
** This singleton is an sqlite3_str object that is returned if
** sqlite3_malloc() fails to provide space for a real one.  This
** sqlite3_str object accepts no new text and always returns
** an SQLITE_NOMEM error.
*/
1212
1213
1214
1215
1216
1217
1218
1219

1220
1221
1222
1223
1224
1225
1226
1367
1368
1369
1370
1371
1372
1373

1374
1375
1376
1377
1378
1379
1380
1381







-
+







** A version of printf() that understands %lld.  Used for debugging.
** The printf() built into some versions of windows does not understand %lld
** and segfaults if you give it a long long int.
*/
void sqlite3DebugPrintf(const char *zFormat, ...){
  va_list ap;
  StrAccum acc;
  char zBuf[500];
  char zBuf[SQLITE_PRINT_BUF_SIZE*10];
  sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
  va_start(ap,zFormat);
  sqlite3_str_vappendf(&acc, zFormat, ap);
  va_end(ap);
  sqlite3StrAccumFinish(&acc);
#ifdef SQLITE_OS_TRACE_PROC
  {

Changes to src/random.c.

18
19
20
21
22
23
24
25
26
27



28
29


























30
31
32
33
34
35
36
37
38
39
40
41
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







-
-
-
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-







#include "sqliteInt.h"


/* All threads share a single random number generator.
** This structure is the current state of the generator.
*/
static SQLITE_WSD struct sqlite3PrngType {
  unsigned char isInit;          /* True if initialized */
  unsigned char i, j;            /* State variables */
  unsigned char s[256];          /* State variables */
  u32 s[16];                 /* 64 bytes of chacha20 state */
  u8 out[64];                /* Output bytes */
  u8 n;                      /* Output bytes remaining */
} sqlite3Prng;


/* The RFC-7539 ChaCha20 block function
*/
#define ROTL(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
#define QR(a, b, c, d) ( \
    a += b, d ^= a, d = ROTL(d,16), \
    c += d, b ^= c, b = ROTL(b,12), \
    a += b, d ^= a, d = ROTL(d, 8), \
    c += d, b ^= c, b = ROTL(b, 7))
static void chacha_block(u32 *out, const u32 *in){
  int i;
  u32 x[16];
  memcpy(x, in, 64);
  for(i=0; i<10; i++){
    QR(x[0], x[4], x[ 8], x[12]);
    QR(x[1], x[5], x[ 9], x[13]);
    QR(x[2], x[6], x[10], x[14]);
    QR(x[3], x[7], x[11], x[15]);
    QR(x[0], x[5], x[10], x[15]);
    QR(x[1], x[6], x[11], x[12]);
    QR(x[2], x[7], x[ 8], x[13]);
    QR(x[3], x[4], x[ 9], x[14]);
  }
  for(i=0; i<16; i++) out[i] = x[i]+in[i];
}

/*
** Return N random bytes.
*/
void sqlite3_randomness(int N, void *pBuf){
  unsigned char t;
  unsigned char *zBuf = pBuf;

  /* The "wsdPrng" macro will resolve to the pseudo-random number generator
  ** state vector.  If writable static data is unsupported on the target,
  ** we have to locate the state vector at run-time.  In the more common
  ** case where writable static data is supported, wsdPrng can refer directly
  ** to the "sqlite3Prng" state vector declared above.
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
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







-
+





-
+
-
-
-
-
-
-

-
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-

-
-
-
+
-
-
+
-
-
+



-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+








#if SQLITE_THREADSAFE
  mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG);
#endif

  sqlite3_mutex_enter(mutex);
  if( N<=0 || pBuf==0 ){
    wsdPrng.isInit = 0;
    wsdPrng.s[0] = 0;
    sqlite3_mutex_leave(mutex);
    return;
  }

  /* Initialize the state of the random number generator once,
  ** the first time this routine is called.  The seed value does
  ** the first time this routine is called.
  ** not need to contain a lot of randomness since we are not
  ** trying to do secure encryption or anything like that...
  **
  ** Nothing in this file or anywhere else in SQLite does any kind of
  ** encryption.  The RC4 algorithm is being used as a PRNG (pseudo-random
  ** number generator) not as an encryption device.
  */
  if( !wsdPrng.isInit ){
  if( wsdPrng.s[0]==0 ){
    int i;
    char k[256];
    wsdPrng.j = 0;
    wsdPrng.i = 0;
    sqlite3OsRandomness(sqlite3_vfs_find(0), 256, k);
    sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
    static const u32 chacha20_init[] = {
      0x61707865, 0x3320646e, 0x79622d32, 0x6b206574
    };
    memcpy(&wsdPrng.s[0], chacha20_init, 16);
    if( NEVER(pVfs==0) ){
      memset(&wsdPrng.s[4], 0, 44);
    }else{
      sqlite3OsRandomness(pVfs, 44, (char*)&wsdPrng.s[4]);
    for(i=0; i<256; i++){
      wsdPrng.s[i] = (u8)i;
    }
    for(i=0; i<256; i++){
      wsdPrng.j += wsdPrng.s[i] + k[i];
      t = wsdPrng.s[wsdPrng.j];
    wsdPrng.s[15] = wsdPrng.s[12];
      wsdPrng.s[wsdPrng.j] = wsdPrng.s[i];
      wsdPrng.s[i] = t;
    wsdPrng.s[12] = 0;
    }
    wsdPrng.isInit = 1;
    wsdPrng.n = 0;
  }

  assert( N>0 );
  do{
    wsdPrng.i++;
    t = wsdPrng.s[wsdPrng.i];
    wsdPrng.j += t;
    wsdPrng.s[wsdPrng.i] = wsdPrng.s[wsdPrng.j];
    wsdPrng.s[wsdPrng.j] = t;
    t += wsdPrng.s[wsdPrng.i];
    *(zBuf++) = wsdPrng.s[t];
  while( 1 /* exit by break */ ){
    if( N<=wsdPrng.n ){
      memcpy(zBuf, &wsdPrng.out[wsdPrng.n-N], N);
      wsdPrng.n -= N;
      break;
    }
    if( wsdPrng.n>0 ){
      memcpy(zBuf, wsdPrng.out, wsdPrng.n);
      N -= wsdPrng.n;
      zBuf += wsdPrng.n;
    }
    wsdPrng.s[12]++;
    chacha_block((u32*)wsdPrng.out, wsdPrng.s);
    wsdPrng.n = 64;
  }while( --N );
  }
  sqlite3_mutex_leave(mutex);
}

/*
** Initialize a fast PRNG.  A Fast PRNG is called "fast" because it does
** not need a mutex to operate, though it does use a mutex to initialize.
** The quality of the randomness is not as good as the global PRNG.

Changes to src/resolve.c.

12
13
14
15
16
17
18





19
20
21
22
23
24
25
26


27
28
29
30
31
32
33
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







+
+
+
+
+








+
+







**
** This file contains routines used for walking the parser tree and
** resolve all identifiers by associating them with a particular
** table and column.
*/
#include "sqliteInt.h"

/*
** Magic table number to mean the EXCLUDED table in an UPSERT statement.
*/
#define EXCLUDED_TABLE_NUMBER  2

/*
** Walk the expression tree pExpr and increase the aggregate function
** depth (the Expr.op2 field) by N on every TK_AGG_FUNCTION node.
** This needs to occur when copying a TK_AGG_FUNCTION node from an
** outer query into an inner subquery.
**
** incrAggFunctionDepth(pExpr,n) is the main routine.  incrAggDepth(..)
** is a helper function - a callback for the tree walker.
**
** See also the sqlite3WindowExtraAggFuncDepth() routine in window.c
*/
static int incrAggDepth(Walker *pWalker, Expr *pExpr){
  if( pExpr->op==TK_AGG_FUNCTION ) pExpr->op2 += pWalker->u.n;
  return WRC_Continue;
}
static void incrAggFunctionDepth(Expr *pExpr, int N){
  if( N>0 ){
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
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







-











+
+
-
-
+
+
+
+

+


-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
+
+
-
-
+
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-









-
-
+
+





+
+
+















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







** structures must be increased by the nSubquery amount.
*/
static void resolveAlias(
  Parse *pParse,         /* Parsing context */
  ExprList *pEList,      /* A result set */
  int iCol,              /* A column in the result set.  0..pEList->nExpr-1 */
  Expr *pExpr,           /* Transform this into an alias to the result set */
  const char *zType,     /* "GROUP" or "ORDER" or "" */
  int nSubquery          /* Number of subqueries that the label is moving */
){
  Expr *pOrig;           /* The iCol-th column of the result set */
  Expr *pDup;            /* Copy of pOrig */
  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 ){
    if( zType[0]!='G' ) incrAggFunctionDepth(pDup, nSubquery);
    pDup = 0;
  }else{
    Expr temp;
    incrAggFunctionDepth(pDup, nSubquery);
    if( pExpr->op==TK_COLLATE ){
      assert( !ExprHasProperty(pExpr, EP_IntValue) );
      pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
    }

    memcpy(&temp, pDup, sizeof(Expr));
    /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This 
    ** prevents ExprDelete() from deleting the Expr structure itself,
    ** allowing it to be repopulated by the memcpy() on the following line.
    ** The pExpr->u.zToken might point into memory that will be freed by the
    ** sqlite3DbFree(db, pDup) on the last line of this block, so be sure to
    ** make a copy of the token before doing the sqlite3DbFree().
    */
    ExprSetProperty(pExpr, EP_Static);
    sqlite3ExprDelete(db, pExpr);
    memcpy(pExpr, pDup, sizeof(*pExpr));
    if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){
      assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 );
    memcpy(pDup, pExpr, sizeof(Expr));
    memcpy(pExpr, &temp, sizeof(Expr));
    if( ExprHasProperty(pExpr, EP_WinFunc) ){
      if( ALWAYS(pExpr->y.pWin!=0) ){
      pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken);
      pExpr->flags |= EP_MemToken;
    }
        pExpr->y.pWin->pOwner = pExpr;
      }
    sqlite3DbFree(db, pDup);
  }
    }
  ExprSetProperty(pExpr, EP_Alias);
}


    sqlite3ExprDeferredDelete(pParse, pDup);
  }
/*
** Return TRUE if the name zCol occurs anywhere in the USING clause.
**
** Return FALSE if the USING clause is NULL or if it does not contain
** zCol.
*/
static int nameInUsingClause(IdList *pUsing, const char *zCol){
  if( pUsing ){
    int k;
    for(k=0; k<pUsing->nId; k++){
      if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ) return 1;
    }
  }
  return 0;
}

/*
** Subqueries stores the original database, table and column names for their
** result sets in ExprList.a[].zSpan, in the form "DATABASE.TABLE.COLUMN".
** Check to see if the zSpan given to this routine matches the zDb, zTab,
** and zCol.  If any of zDb, zTab, and zCol are NULL then those fields will
** match anything.
*/
int sqlite3MatchSpanName(
  const char *zSpan,
int sqlite3MatchEName(
  const struct ExprList_item *pItem,
  const char *zCol,
  const char *zTab,
  const char *zDb
){
  int n;
  const char *zSpan;
  if( pItem->fg.eEName!=ENAME_TAB ) return 0;
  zSpan = pItem->zEName;
  for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
  if( zDb && (sqlite3StrNICmp(zSpan, zDb, n)!=0 || zDb[n]!=0) ){
    return 0;
  }
  zSpan += n+1;
  for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
  if( zTab && (sqlite3StrNICmp(zSpan, zTab, n)!=0 || zTab[n]!=0) ){
    return 0;
  }
  zSpan += n+1;
  if( zCol && sqlite3StrICmp(zSpan, zCol)!=0 ){
    return 0;
  }
  return 1;
}

/*
** Return TRUE if the double-quoted string  mis-feature should be supported.
*/
static int areDoubleQuotedStringsEnabled(sqlite3 *db, NameContext *pTopNC){
  if( db->init.busy ) return 1;  /* Always support for legacy schemas */
  if( pTopNC->ncFlags & NC_IsDDL ){
    /* Currently parsing a DDL statement */
    if( sqlite3WritableSchema(db) && (db->flags & SQLITE_DqsDML)!=0 ){
      return 1;
    }
    return (db->flags & SQLITE_DqsDDL)!=0;
  }else{
    /* Currently parsing a DML statement */
    return (db->flags & SQLITE_DqsDML)!=0;
  }
}

/*
** The argument is guaranteed to be a non-NULL Expr node of type TK_COLUMN.
** return the appropriate colUsed mask.
*/
Bitmask sqlite3ExprColUsed(Expr *pExpr){
  int n;
  Table *pExTab;

  n = pExpr->iColumn;
  assert( ExprUseYTab(pExpr) );
  pExTab = pExpr->y.pTab;
  assert( pExTab!=0 );
  if( (pExTab->tabFlags & TF_HasGenerated)!=0
   && (pExTab->aCol[n].colFlags & COLFLAG_GENERATED)!=0 
  ){
    testcase( pExTab->nCol==BMS-1 );
    testcase( pExTab->nCol==BMS );
    return pExTab->nCol>=BMS ? ALLBITS : MASKBIT(pExTab->nCol)-1;
  }else{
    testcase( n==BMS-1 );
    testcase( n==BMS );
    if( n>=BMS ) n = BMS-1;
    return ((Bitmask)1)<<n;
  }
}

/*
** Create a new expression term for the column specified by pMatch and
** iColumn.  Append this new expression term to the FULL JOIN Match set
** in *ppList.  Create a new *ppList if this is the first term in the
** set.
*/
static void extendFJMatch(
  Parse *pParse,          /* Parsing context */
  ExprList **ppList,      /* ExprList to extend */
  SrcItem *pMatch,        /* Source table containing the column */
  i16 iColumn             /* The column number */
){
  Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLUMN, 0, 0);
  if( pNew ){
    pNew->iTable = pMatch->iCursor;
    pNew->iColumn = iColumn;
    pNew->y.pTab = pMatch->pTab;
    assert( (pMatch->fg.jointype & (JT_LEFT|JT_LTORJ))!=0 );
    ExprSetProperty(pNew, EP_CanBeNull);
    *ppList = sqlite3ExprListAppend(pParse, *ppList, pNew);
  }
}

/*
** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
** that name in the set of source tables in pSrcList and make the pExpr 
** expression node refer back to that source column.  The following changes
** are made to pExpr:
**
184
185
186
187
188
189
190
191
192


193
194
195
196

197

198
199
200

201
202
203
204
205
206
207
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







-
-
+
+



-
+

+



+







  Expr *pExpr          /* Make this EXPR node point to the selected column */
){
  int i, j;                         /* Loop counters */
  int cnt = 0;                      /* Number of matching column names */
  int cntTab = 0;                   /* Number of matching table names */
  int nSubquery = 0;                /* How many levels of subquery */
  sqlite3 *db = pParse->db;         /* The database connection */
  struct SrcList_item *pItem;       /* Use for looping over pSrcList items */
  struct SrcList_item *pMatch = 0;  /* The matching pSrcList item */
  SrcItem *pItem;                   /* Use for looping over pSrcList items */
  SrcItem *pMatch = 0;              /* The matching pSrcList item */
  NameContext *pTopNC = pNC;        /* First namecontext in the list */
  Schema *pSchema = 0;              /* Schema of the expression */
  int eNewExprOp = TK_COLUMN;       /* New value for pExpr->op on success */
  Table *pTab = 0;                  /* Table hold the row */
  Table *pTab = 0;                  /* Table holding the row */
  Column *pCol;                     /* A column of pTab */
  ExprList *pFJMatch = 0;           /* Matches for FULL JOIN .. USING */

  assert( pNC );     /* the name context cannot be NULL. */
  assert( zCol );    /* The Z in X.Y.Z cannot be NULL */
  assert( zDb==0 || zTab!=0 );
  assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );

  /* Initialize the node to no-match */
  pExpr->iTable = -1;
  ExprSetVVAProperty(pExpr, EP_NoReduce);

  /* Translate the schema name in zDb into a pointer to the corresponding
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
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







+
+
+
+
+
+











+


-
-
+
+
+
+
+
+
+
+
+

+

+
+

-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+



+
+
+
+
-
-
-
+
+
+
-
-
+




+




-
-
+
-

+
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





+
+
+


+
+
+
+




+

-
-
-
+









-
+
+

-
+





+
+
+
+
+
+
+
-
+


-
+






-
+



-
+






+



+
-
+
+












+

-
+

+





-
+
+

-




+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-

+












-
+

-
+



-
+




















+
-
+
-





-
-
+
+
+
+


-
-
+
+




+
+
+
+
+
+





-
+







      for(i=0; i<db->nDb; i++){
        assert( db->aDb[i].zDbSName );
        if( sqlite3StrICmp(db->aDb[i].zDbSName,zDb)==0 ){
          pSchema = db->aDb[i].pSchema;
          break;
        }
      }
      if( i==db->nDb && sqlite3StrICmp("main", zDb)==0 ){
        /* This branch is taken when the main database has been renamed
        ** using SQLITE_DBCONFIG_MAINDBNAME. */
        pSchema = db->aDb[0].pSchema;
        zDb = db->aDb[0].zDbSName;
      }
    }
  }

  /* Start at the inner-most context and move outward until a match is found */
  assert( pNC && cnt==0 );
  do{
    ExprList *pEList;
    SrcList *pSrcList = pNC->pSrcList;

    if( pSrcList ){
      for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
        u8 hCol;
        pTab = pItem->pTab;
        assert( pTab!=0 && pTab->zName!=0 );
        assert( pTab->nCol>0 );
        if( pItem->pSelect && (pItem->pSelect->selFlags & SF_NestedFrom)!=0 ){
        assert( pTab->nCol>0 || pParse->nErr );
        assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) );
        if( pItem->fg.isNestedFrom ){
          /* In this case, pItem is a subquery that has been formed from a
          ** parenthesized subset of the FROM clause terms.  Example:
          **   .... FROM t1 LEFT JOIN (t2 RIGHT JOIN t3 USING(x)) USING(y) ...
          **                          \_________________________/
          **             This pItem -------------^
          */
          int hit = 0;
          assert( pItem->pSelect!=0 );
          pEList = pItem->pSelect->pEList;
          assert( pEList!=0 );
          assert( pEList->nExpr==pTab->nCol );
          for(j=0; j<pEList->nExpr; j++){
            if( sqlite3MatchSpanName(pEList->a[j].zSpan, zCol, zTab, zDb) ){
              cnt++;
              cntTab = 2;
              pMatch = pItem;
              pExpr->iColumn = j;
              hit = 1;
            if( !sqlite3MatchEName(&pEList->a[j], zCol, zTab, zDb) ){
              continue;
            }
            if( cnt>0 ){
              if( pItem->fg.isUsing==0
               || sqlite3IdListIndex(pItem->u3.pUsing, zCol)<0
              ){
                /* Two or more tables have the same column name which is
                ** not joined by USING.  This is an error.  Signal as much
                ** by clearing pFJMatch and letting cnt go above 1. */
                sqlite3ExprListDelete(db, pFJMatch);
                pFJMatch = 0;
              }else
              if( (pItem->fg.jointype & JT_RIGHT)==0 ){
                /* An INNER or LEFT JOIN.  Use the left-most table */
                continue;
              }else
              if( (pItem->fg.jointype & JT_LEFT)==0 ){
                /* A RIGHT JOIN.  Use the right-most table */
                cnt = 0;
                sqlite3ExprListDelete(db, pFJMatch);
                pFJMatch = 0;
              }else{
                /* For a FULL JOIN, we must construct a coalesce() func */
                extendFJMatch(pParse, &pFJMatch, pMatch, pExpr->iColumn);
              }
            }
            cnt++;
            cntTab = 2;
            pMatch = pItem;
            pExpr->iColumn = j;
            pEList->a[j].fg.bUsed = 1;
            hit = 1;
            }
            if( pEList->a[j].fg.bUsingTerm ) break;
          }
          if( hit || zTab==0 ) continue;
        }
        assert( zDb==0 || zTab!=0 );
        if( zTab ){
          const char *zTabName;
          if( zDb ){
        if( zDb && pTab->pSchema!=pSchema ){
          continue;
        }
            if( pTab->pSchema!=pSchema ) continue;
            if( pSchema==0 && strcmp(zDb,"*")!=0 ) continue;
          }
        if( zTab ){
          const char *zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName;
          zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName;
          assert( zTabName!=0 );
          if( sqlite3StrICmp(zTabName, zTab)!=0 ){
            continue;
          }
          assert( ExprUseYTab(pExpr) );
          if( IN_RENAME_OBJECT && pItem->zAlias ){
            sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->y.pTab);
          }
        }
        if( 0==(cntTab++) ){
          pMatch = pItem;
        hCol = sqlite3StrIHash(zCol);
        }
        for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
          if( pCol->hName==hCol
          if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
           && sqlite3StrICmp(pCol->zCnName, zCol)==0
            /* If there has been exactly one prior match and this match
            ** is for the right-hand table of a NATURAL JOIN or is in a 
            ** USING clause, then skip this match.
            */
            if( cnt==1 ){
              if( pItem->fg.jointype & JT_NATURAL ) continue;
              if( nameInUsingClause(pItem->pUsing, zCol) ) continue;
          ){
            if( cnt>0 ){
              if( pItem->fg.isUsing==0
               || sqlite3IdListIndex(pItem->u3.pUsing, zCol)<0
              ){
                /* Two or more tables have the same column name which is
                ** not joined by USING.  This is an error.  Signal as much
                ** by clearing pFJMatch and letting cnt go above 1. */
                sqlite3ExprListDelete(db, pFJMatch);
                pFJMatch = 0;
              }else
              if( (pItem->fg.jointype & JT_RIGHT)==0 ){
                /* An INNER or LEFT JOIN.  Use the left-most table */
                continue;
              }else
              if( (pItem->fg.jointype & JT_LEFT)==0 ){
                /* A RIGHT JOIN.  Use the right-most table */
                cnt = 0;
                sqlite3ExprListDelete(db, pFJMatch);
                pFJMatch = 0;
              }else{
                /* For a FULL JOIN, we must construct a coalesce() func */
                extendFJMatch(pParse, &pFJMatch, pMatch, pExpr->iColumn);
              }
            }
            cnt++;
            pMatch = pItem;
            /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
            pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j;
            if( pItem->fg.isNestedFrom ){
              sqlite3SrcItemColumnUsed(pItem, j);
            }
            break;
          }
        }
        if( 0==cnt && VisibleRowid(pTab) ){
          cntTab++;
          pMatch = pItem;
        }
      }
      if( pMatch ){
        pExpr->iTable = pMatch->iCursor;
        assert( ExprUseYTab(pExpr) );
        pExpr->y.pTab = pMatch->pTab;
        /* RIGHT JOIN not (yet) supported */
        assert( (pMatch->fg.jointype & JT_RIGHT)==0 );
        if( (pMatch->fg.jointype & JT_LEFT)!=0 ){
        if( (pMatch->fg.jointype & (JT_LEFT|JT_LTORJ))!=0 ){
          ExprSetProperty(pExpr, EP_CanBeNull);
        }
        pSchema = pExpr->y.pTab->pSchema;
      }
    } /* if( pSrcList ) */

#if !defined(SQLITE_OMIT_TRIGGER) || !defined(SQLITE_OMIT_UPSERT)
    /* If we have not already resolved the name, then maybe 
    ** it is a new.* or old.* trigger argument reference.  Or
    ** maybe it is an excluded.* from an upsert.
    ** maybe it is an excluded.* from an upsert.  Or maybe it is
    ** a reference in the RETURNING clause to a table being modified.
    */
    if( zDb==0 && zTab!=0 && cntTab==0 ){
    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 && 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 && sqlite3StrICmp("old",zTab)==0 ){
        }else if( op!=TK_INSERT && zTab && sqlite3StrICmp("old",zTab)==0 ){
          pExpr->iTable = 0;
          pTab = pParse->pTriggerTab;
        }
      }
#endif /* SQLITE_OMIT_TRIGGER */
#ifndef SQLITE_OMIT_UPSERT
      if( (pNC->ncFlags & NC_UUpsert)!=0 ){
      if( (pNC->ncFlags & NC_UUpsert)!=0 && zTab!=0 ){
        Upsert *pUpsert = pNC->uNC.pUpsert;
        if( pUpsert && sqlite3StrICmp("excluded",zTab)==0 ){
          pTab = pUpsert->pUpsertSrc->a[0].pTab;
          pExpr->iTable = 2;
          pExpr->iTable = EXCLUDED_TABLE_NUMBER;
        }
      }
#endif /* SQLITE_OMIT_UPSERT */

      if( pTab ){ 
        int iCol;
        u8 hCol = sqlite3StrIHash(zCol);
        pSchema = pTab->pSchema;
        cntTab++;
        for(iCol=0, pCol=pTab->aCol; iCol<pTab->nCol; iCol++, pCol++){
          if( pCol->hName==hCol
          if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
           && sqlite3StrICmp(pCol->zCnName, zCol)==0
          ){
            if( iCol==pTab->iPKey ){
              iCol = -1;
            }
            break;
          }
        }
        if( iCol>=pTab->nCol && sqlite3IsRowid(zCol) && VisibleRowid(pTab) ){
          /* IMP: R-51414-32910 */
          iCol = -1;
        }
        if( iCol<pTab->nCol ){
          cnt++;
          pMatch = 0;
#ifndef SQLITE_OMIT_UPSERT
          if( pExpr->iTable==2 ){
          if( pExpr->iTable==EXCLUDED_TABLE_NUMBER ){
            testcase( iCol==(-1) );
            assert( ExprUseYTab(pExpr) );
            if( IN_RENAME_OBJECT ){
              pExpr->iColumn = iCol;
              pExpr->y.pTab = pTab;
              eNewExprOp = TK_COLUMN;
            }else{
              pExpr->iTable = pNC->uNC.pUpsert->regData + iCol;
              pExpr->iTable = pNC->uNC.pUpsert->regData +
                 sqlite3TableColumnToStorage(pTab, iCol);
              eNewExprOp = TK_REGISTER;
              ExprSetProperty(pExpr, EP_Alias);
            }
          }else
#endif /* SQLITE_OMIT_UPSERT */
          {
            assert( ExprUseYTab(pExpr) );
            pExpr->y.pTab = pTab;
            if( pParse->bReturning ){
              eNewExprOp = TK_REGISTER;
              pExpr->op2 = TK_COLUMN;
              pExpr->iColumn = iCol;
              pExpr->iTable = pNC->uNC.iBaseReg + (pTab->nCol+1)*pExpr->iTable +
                 sqlite3TableColumnToStorage(pTab, iCol) + 1;
            }else{
              pExpr->iColumn = (i16)iCol;
              eNewExprOp = TK_TRIGGER;
#ifndef SQLITE_OMIT_TRIGGER
            if( iCol<0 ){
              pExpr->affinity = SQLITE_AFF_INTEGER;
            }else if( pExpr->iTable==0 ){
              testcase( iCol==31 );
              testcase( iCol==32 );
              pParse->oldmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol));
            }else{
              testcase( iCol==31 );
              testcase( iCol==32 );
              pParse->newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol));
            }
              if( iCol<0 ){
                pExpr->affExpr = SQLITE_AFF_INTEGER;
              }else if( pExpr->iTable==0 ){
                testcase( iCol==31 );
                testcase( iCol==32 );
                pParse->oldmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol));
              }else{
                testcase( iCol==31 );
                testcase( iCol==32 );
                pParse->newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol));
              }
            pExpr->y.pTab = pTab;
            pExpr->iColumn = (i16)iCol;
            eNewExprOp = TK_TRIGGER;
#endif /* SQLITE_OMIT_TRIGGER */
            }
          }
        }
      }
    }
#endif /* !defined(SQLITE_OMIT_TRIGGER) || !defined(SQLITE_OMIT_UPSERT) */

    /*
    ** Perhaps the name is a reference to the ROWID
    */
    if( cnt==0
     && cntTab==1
     && pMatch
     && (pNC->ncFlags & NC_IdxExpr)==0
     && (pNC->ncFlags & (NC_IdxExpr|NC_GenCol))==0
     && sqlite3IsRowid(zCol)
     && VisibleRowid(pMatch->pTab)
     && ALWAYS(VisibleRowid(pMatch->pTab))
    ){
      cnt = 1;
      pExpr->iColumn = -1;
      pExpr->affinity = SQLITE_AFF_INTEGER;
      pExpr->affExpr = SQLITE_AFF_INTEGER;
    }

    /*
    ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z
    ** might refer to an result-set alias.  This happens, for example, when
    ** we are resolving names in the WHERE clause of the following command:
    **
    **     SELECT a+b AS x FROM table WHERE x<10;
    **
    ** In cases like this, replace pExpr with a copy of the expression that
    ** forms the result set entry ("a+b" in the example) and return immediately.
    ** Note that the expression in the result set should have already been
    ** resolved by the time the WHERE clause is resolved.
    **
    ** 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].zName;
        if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
        char *zAs = pEList->a[j].zEName;
        if( pEList->a[j].fg.eEName==ENAME_NAME
         && sqlite3_stricmp(zAs, zCol)==0
        ){
          Expr *pOrig;
          assert( pExpr->pLeft==0 && pExpr->pRight==0 );
          assert( pExpr->x.pList==0 );
          assert( pExpr->x.pSelect==0 );
          assert( ExprUseXList(pExpr)==0 || pExpr->x.pList==0 );
          assert( ExprUseXSelect(pExpr)==0 || pExpr->x.pSelect==0 );
          pOrig = pEList->a[j].pExpr;
          if( (pNC->ncFlags&NC_AllowAgg)==0 && ExprHasProperty(pOrig, EP_Agg) ){
            sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
            return WRC_Abort;
          }
          if( ExprHasProperty(pOrig, EP_Win)
           && ((pNC->ncFlags&NC_AllowWin)==0 || pNC!=pTopNC )
          ){
            sqlite3ErrorMsg(pParse, "misuse of aliased window function %s",zAs);
            return WRC_Abort;
          }
          if( sqlite3ExprVectorSize(pOrig)!=1 ){
            sqlite3ErrorMsg(pParse, "row value misused");
            return WRC_Abort;
          }
          resolveAlias(pParse, pEList, j, pExpr, "", nSubquery);
          resolveAlias(pParse, pEList, j, pExpr, nSubquery);
          cnt = 1;
          pMatch = 0;
          assert( zTab==0 && zDb==0 );
          if( IN_RENAME_OBJECT ){
            sqlite3RenameTokenRemap(pParse, 0, (void*)pExpr);
          }
          goto lookupname_end;
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
624
625
626
627
628
629
630

631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653

654
655
656
657
658
659
660
661
662


663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703

704
705
706
707
708
709
710
711
712
713
714
715
716
717
718



719
720
721
722
723
724
725
726
727
728
729
730
731







732
733
734






735

736
737
738
739

740
741
742
743
744
745
746
747
748
749
750
751
752







-
+
+
+




















-
+








-
-
+
+
+
+
+

+
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








+

-
+
+
+
+
+
+
+
+
+
+
+




-
-
-
+
+
+
+
+
+
+
+
+
+
+


-
-
-
-
-
-
-
+


-
-
-
-
-
-

-



+
-
+
+
+


+







  ** pExpr.
  **
  ** 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) ){
    if( ExprHasProperty(pExpr,EP_DblQuoted)
     && areDoubleQuotedStringsEnabled(db, pTopNC)
    ){
      /* If a double-quoted identifier does not match any known column name,
      ** then treat it as a string.
      **
      ** This hack was added in the early days of SQLite in a misguided attempt
      ** to be compatible with MySQL 3.x, which used double-quotes for strings.
      ** I now sorely regret putting in this hack. The effect of this hack is
      ** that misspelled identifier names are silently converted into strings
      ** rather than causing an error, to the frustration of countless
      ** programmers. To all those frustrated programmers, my apologies.
      **
      ** Someday, I hope to get rid of this hack. Unfortunately there is
      ** a huge amount of legacy SQL that uses it. So for now, we just
      ** issue a warning.
      */
      sqlite3_log(SQLITE_WARNING,
        "double-quoted string literal: \"%w\"", zCol);
#ifdef SQLITE_ENABLE_NORMALIZE
      sqlite3VdbeAddDblquoteStr(db, pParse->pVdbe, zCol);
#endif
      pExpr->op = TK_STRING;
      pExpr->y.pTab = 0;
      memset(&pExpr->y, 0, sizeof(pExpr->y));
      return WRC_Prune;
    }
    if( sqlite3ExprIdToTrueFalse(pExpr) ){
      return WRC_Prune;
    }
  }

  /*
  ** cnt==0 means there was not match.  cnt>1 means there were two or
  ** more matches.  Either way, we have an error.
  ** cnt==0 means there was not match.
  ** cnt>1 means there were two or more matches.
  **
  ** cnt==0 is always an error.  cnt>1 is often an error, but might
  ** be multiple matches for a NATURAL LEFT JOIN or a LEFT JOIN USING.
  */
  assert( pFJMatch==0 || cnt>0 );
  assert( !ExprHasProperty(pExpr, EP_xIsSelect|EP_IntValue) );
  if( cnt!=1 ){
    const char *zErr;
    if( pFJMatch ){
      if( pFJMatch->nExpr==cnt-1 ){
        if( ExprHasProperty(pExpr,EP_Leaf) ){
          ExprClearProperty(pExpr,EP_Leaf);
        }else{
          sqlite3ExprDelete(db, pExpr->pLeft);
          pExpr->pLeft = 0;
          sqlite3ExprDelete(db, pExpr->pRight);
          pExpr->pRight = 0;
        }
        extendFJMatch(pParse, &pFJMatch, pMatch, pExpr->iColumn);
        pExpr->op = TK_FUNCTION;
        pExpr->u.zToken = "coalesce";
        pExpr->x.pList = pFJMatch;
        cnt = 1;
        goto lookupname_end;
      }else{
        sqlite3ExprListDelete(db, pFJMatch);
        pFJMatch = 0;
      }
    }
    zErr = cnt==0 ? "no such column" : "ambiguous column name";
    if( zDb ){
      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);
    }
    sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr);
    pParse->checkSchema = 1;
    pTopNC->nErr++;
    pTopNC->nNcErr++;
  }
  assert( pFJMatch==0 );

  /* Remove all substructure from pExpr */
  if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){
    sqlite3ExprDelete(db, pExpr->pLeft);
    pExpr->pLeft = 0;
    sqlite3ExprDelete(db, pExpr->pRight);
    pExpr->pRight = 0;
    ExprSetProperty(pExpr, EP_Leaf);
  }

  /* 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.  If the
  ** column number is greater than the number of bits in the bitmask
  ** then set the high-order bit of the bitmask.
  ** 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.
  **
  ** The colUsed mask is an optimization used to help determine if an
  ** index is a covering index.  The correct answer is still obtained
  ** if the mask contains extra set bits.  However, it is important to
  ** avoid setting bits beyond the maximum column number of the table.
  ** (See ticket [b92e5e8ec2cdbaa1]).
  **
  ** If a generated column is referenced, set bits for every column
  ** of the table.
  */
  if( pExpr->iColumn>=0 && pMatch!=0 ){
    int n = pExpr->iColumn;
    testcase( n==BMS-1 );
    if( n>=BMS ){
      n = BMS-1;
    }
    assert( pMatch->iCursor==pExpr->iTable );
    pMatch->colUsed |= ((Bitmask)1)<<n;
    pMatch->colUsed |= sqlite3ExprColUsed(pExpr);
  }

  /* Clean up and return
  */
  sqlite3ExprDelete(db, pExpr->pLeft);
  pExpr->pLeft = 0;
  sqlite3ExprDelete(db, pExpr->pRight);
  pExpr->pRight = 0;
  pExpr->op = eNewExprOp;
  ExprSetProperty(pExpr, EP_Leaf);
lookupname_end:
  if( cnt==1 ){
    assert( pNC!=0 );
#ifndef SQLITE_OMIT_AUTHORIZATION
    if( !ExprHasProperty(pExpr, EP_Alias) ){
    if( pParse->db->xAuth
     && (pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER)
    ){
      sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
    }
#endif
    /* Increment the nRef value on all name contexts from TopNC up to
    ** the point where the name matched. */
    for(;;){
      assert( pTopNC!=0 );
      pTopNC->nRef++;
      if( pTopNC==pNC ) break;
      pTopNC = pTopNC->pNext;
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
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







-
-
+
+
+
+





+
+
+
+
+
+
+
-
-
-
+
+
+
+








+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+
+

-
-
-
-
+
+

-
+

+
+
+
-
-
+
+
+
+
-
+
+
+









+







/*
** Allocate and return a pointer to an expression to load the column iCol
** from datasource iSrc in SrcList pSrc.
*/
Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSrc, int iCol){
  Expr *p = sqlite3ExprAlloc(db, TK_COLUMN, 0, 0);
  if( p ){
    struct SrcList_item *pItem = &pSrc->a[iSrc];
    p->y.pTab = pItem->pTab;
    SrcItem *pItem = &pSrc->a[iSrc];
    Table *pTab;
    assert( ExprUseYTab(p) );
    pTab = p->y.pTab = pItem->pTab;
    p->iTable = pItem->iCursor;
    if( p->y.pTab->iPKey==iCol ){
      p->iColumn = -1;
    }else{
      p->iColumn = (ynVar)iCol;
      if( (pTab->tabFlags & TF_HasGenerated)!=0
       && (pTab->aCol[iCol].colFlags & COLFLAG_GENERATED)!=0
      ){
        testcase( pTab->nCol==63 );
        testcase( pTab->nCol==64 );
        pItem->colUsed = pTab->nCol>=64 ? ALLBITS : MASKBIT(pTab->nCol)-1;
      }else{
      testcase( iCol==BMS );
      testcase( iCol==BMS-1 );
      pItem->colUsed |= ((Bitmask)1)<<(iCol>=BMS ? BMS-1 : iCol);
        testcase( iCol==BMS );
        testcase( iCol==BMS-1 );
        pItem->colUsed |= ((Bitmask)1)<<(iCol>=BMS ? BMS-1 : iCol);
      }
    }
  }
  return p;
}

/*
** Report an error that an expression is not valid for some set of
** pNC->ncFlags values determined by validMask.
**
** static void notValid(
**   Parse *pParse,       // Leave error message here
**   NameContext *pNC,    // The name context 
**   const char *zMsg,    // Type of error
**   int validMask,       // Set of contexts for which prohibited
**   Expr *pExpr          // Invalidate this expression on error
** ){...}
**
** As an optimization, since the conditional is almost always false
** (because errors are rare), the conditional is moved outside of the
** function call using a macro.
*/
static void notValid(
  Parse *pParse,       /* Leave error message here */
  NameContext *pNC,    /* The name context */
  const char *zMsg,    /* Type of error */
  int validMask        /* Set of contexts for which prohibited */
static void notValidImpl(
   Parse *pParse,       /* Leave error message here */
   NameContext *pNC,    /* The name context */
   const char *zMsg,    /* Type of error */
   Expr *pExpr,         /* Invalidate this expression on error */
   Expr *pError         /* Associate error with this expression */
){
  assert( (validMask&~(NC_IsCheck|NC_PartIdx|NC_IdxExpr))==0 );
  if( (pNC->ncFlags & validMask)!=0 ){
    const char *zIn = "partial index WHERE clauses";
    if( pNC->ncFlags & NC_IdxExpr )      zIn = "index expressions";
  const char *zIn = "partial index WHERE clauses";
  if( pNC->ncFlags & NC_IdxExpr )      zIn = "index expressions";
#ifndef SQLITE_OMIT_CHECK
    else if( pNC->ncFlags & NC_IsCheck ) zIn = "CHECK constraints";
  else if( pNC->ncFlags & NC_IsCheck ) zIn = "CHECK constraints";
#endif
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
  else if( pNC->ncFlags & NC_GenCol ) zIn = "generated columns";
#endif
    sqlite3ErrorMsg(pParse, "%s prohibited in %s", zMsg, zIn);
  }
  sqlite3ErrorMsg(pParse, "%s prohibited in %s", zMsg, zIn);
  if( pExpr ) pExpr->op = TK_NULL;
  sqlite3RecordErrorOffsetOfExpr(pParse->db, pError);
}
}
#define sqlite3ResolveNotValid(P,N,M,X,E,R) \
  assert( ((X)&~(NC_IsCheck|NC_PartIdx|NC_IdxExpr|NC_GenCol))==0 ); \
  if( ((N)->ncFlags & (X))!=0 ) notValidImpl(P,N,M,E,R);

/*
** Expression p should encode a floating point value between 1.0 and 0.0.
** Return 1024 times this value.  Or return -1 if p is not a floating point
** value between 1.0 and 0.0.
*/
static int exprProbability(Expr *p){
  double r = -1.0;
  if( p->op!=TK_FLOAT ) return -1;
  assert( !ExprHasProperty(p, EP_IntValue) );
  sqlite3AtoF(p->u.zToken, &r, sqlite3Strlen30(p->u.zToken), SQLITE_UTF8);
  assert( r>=0.0 );
  if( r>1.0 ) return -1;
  return (int)(r*134217728.0);
}

/*
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
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
900
901
902
903

904





905
906




907
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

935
936
937
938
939
940
941
942
943
944
945
946
947

948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966

967
968
969
970

971

972
973
974
975
976
977
978
870
871
872
873
874
875
876

877
878

879
880
881
882
883


884
885
886

887
888
889
890


891
892
893
894


895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962

963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994

995
996
997


998
999
1000
1001
1002
1003

1004
1005
1006
1007
1008
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
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299

1300
1301
1302
1303
1304
1305
1306
1307







-


-
+
+



-
-
+
+

-

+


-
-
+
+


-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



















+



+
+
-
+
+





+




+


+
















-



-
-
+
+
+
+
+

-











-
+




-
-
-
+
+
+



















-
-
-
+
+
+









-
+
+



+
-
+

-
-
-
+
+
+
+
+
+
+
+
+



-
+


-
+
+
+


+
+
+
+
+









-
+

-
+

-
+


-
-
+
+


-
+




-
-
+
+




-
-
+
+








-
-
+
+

-
-
-
+
+
+
+
+
+
+
+
+
+
+

+

+
+
+

-
+





+
+
+
+
+



-
+

+
+
+
+
+
-
-
-
+
+
+
-
-
-
+
-
-
-
-
-
+



-
+


+
+
+
+
+
+
-
+
+
+



-
-
+
+

+

+
-
-
-
-
+
+
+
+
+
+
-












-
+

+
+
+
+
+
-
-
+
+
+
+









+
+
+
+
-
+
+




-
+



-
+








-
+













+



















+




+
-
+







    for(i=0; i<pNC->pSrcList->nSrc; i++){
      assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursor<pParse->nTab);
    }
  }
#endif
  switch( pExpr->op ){

#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
    /* The special operator TK_ROW means use the rowid for the first
    ** column in the FROM clause.  This is used by the LIMIT and ORDER BY
    ** clause processing on UPDATE and DELETE statements.
    ** clause processing on UPDATE and DELETE statements, and by 
    ** UPDATE ... FROM statement processing.
    */
    case TK_ROW: {
      SrcList *pSrcList = pNC->pSrcList;
      struct SrcList_item *pItem;
      assert( pSrcList && pSrcList->nSrc==1 );
      SrcItem *pItem;
      assert( pSrcList && pSrcList->nSrc>=1 );
      pItem = pSrcList->a;
      assert( HasRowid(pItem->pTab) && pItem->pTab->pSelect==0 );
      pExpr->op = TK_COLUMN;
      assert( ExprUseYTab(pExpr) );
      pExpr->y.pTab = pItem->pTab;
      pExpr->iTable = pItem->iCursor;
      pExpr->iColumn = -1;
      pExpr->affinity = SQLITE_AFF_INTEGER;
      pExpr->iColumn--;
      pExpr->affExpr = SQLITE_AFF_INTEGER;
      break;
    }
#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT)
          && !defined(SQLITE_OMIT_SUBQUERY) */

    /* An optimization:  Attempt to convert
    **
    **      "expr IS NOT NULL"  -->  "TRUE"
    **      "expr IS NULL"      -->  "FALSE"
    **
    ** if we can prove that "expr" is never NULL.  Call this the
    ** "NOT NULL strength reduction optimization".
    **
    ** If this optimization occurs, also restore the NameContext ref-counts
    ** to the state they where in before the "column" LHS expression was
    ** resolved.  This prevents "column" from being counted as having been
    ** referenced, which might prevent a SELECT from being erroneously
    ** marked as correlated.
    */
    case TK_NOTNULL:
    case TK_ISNULL: {
      int anRef[8];
      NameContext *p;
      int i;
      for(i=0, p=pNC; p && i<ArraySize(anRef); p=p->pNext, i++){ 
        anRef[i] = p->nRef;
      }
      sqlite3WalkExpr(pWalker, pExpr->pLeft);
      if( 0==sqlite3ExprCanBeNull(pExpr->pLeft) && !IN_RENAME_OBJECT ){
        testcase( ExprHasProperty(pExpr, EP_OuterON) );
        assert( !ExprHasProperty(pExpr, EP_IntValue) );
        if( pExpr->op==TK_NOTNULL ){
          pExpr->u.zToken = "true";
          ExprSetProperty(pExpr, EP_IsTrue);
        }else{
          pExpr->u.zToken = "false";
          ExprSetProperty(pExpr, EP_IsFalse);
        }
        pExpr->op = TK_TRUEFALSE;
        for(i=0, p=pNC; p && i<ArraySize(anRef); p=p->pNext, i++){
          p->nRef = anRef[i];
        }
        sqlite3ExprDelete(pParse->db, pExpr->pLeft);
        pExpr->pLeft = 0;
      }
      return WRC_Prune;
    }

    /* A column name:                    ID
    ** Or table name and column name:    ID.ID
    ** Or a database, table and column:  ID.ID.ID
    **
    ** The TK_ID and TK_OUT cases are combined so that there will only
    ** be one call to lookupName().  Then the compiler will in-line 
    ** lookupName() for a size reduction and performance increase.
    */
    case TK_ID:
    case TK_DOT: {
      const char *zColumn;
      const char *zTable;
      const char *zDb;
      Expr *pRight;

      if( pExpr->op==TK_ID ){
        zDb = 0;
        zTable = 0;
        assert( !ExprHasProperty(pExpr, EP_IntValue) );
        zColumn = pExpr->u.zToken;
      }else{
        Expr *pLeft = pExpr->pLeft;
        testcase( pNC->ncFlags & NC_IdxExpr );
        testcase( pNC->ncFlags & NC_GenCol );
        notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr);
        sqlite3ResolveNotValid(pParse, pNC, "the \".\" operator",
                               NC_IdxExpr|NC_GenCol, 0, pExpr);
        pRight = pExpr->pRight;
        if( pRight->op==TK_ID ){
          zDb = 0;
        }else{
          assert( pRight->op==TK_DOT );
          assert( !ExprHasProperty(pRight, EP_IntValue) );
          zDb = pLeft->u.zToken;
          pLeft = pRight->pLeft;
          pRight = pRight->pRight;
        }
        assert( ExprUseUToken(pLeft) && ExprUseUToken(pRight) );
        zTable = pLeft->u.zToken;
        zColumn = pRight->u.zToken;
        assert( ExprUseYTab(pExpr) );
        if( IN_RENAME_OBJECT ){
          sqlite3RenameTokenRemap(pParse, (void*)pExpr, (void*)pRight);
          sqlite3RenameTokenRemap(pParse, (void*)&pExpr->y.pTab, (void*)pLeft);
        }
      }
      return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr);
    }

    /* Resolve function names
    */
    case TK_FUNCTION: {
      ExprList *pList = pExpr->x.pList;    /* The argument list */
      int n = pList ? pList->nExpr : 0;    /* Number of arguments */
      int no_such_func = 0;       /* True if no such function exists */
      int wrong_num_args = 0;     /* True if wrong number of arguments */
      int is_agg = 0;             /* True if is an aggregate function */
      int nId;                    /* Number of characters in function name */
      const char *zId;            /* The function name. */
      FuncDef *pDef;              /* Information about the function */
      u8 enc = ENC(pParse->db);   /* The database encoding */

      assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
      int savedAllowFlags = (pNC->ncFlags & (NC_AllowAgg | NC_AllowWin));
#ifndef SQLITE_OMIT_WINDOWFUNC
      Window *pWin = (IsWindowFunc(pExpr) ? pExpr->y.pWin : 0);
#endif
      assert( !ExprHasProperty(pExpr, EP_xIsSelect|EP_IntValue) );
      zId = pExpr->u.zToken;
      nId = sqlite3Strlen30(zId);
      pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0);
      if( pDef==0 ){
        pDef = sqlite3FindFunction(pParse->db, zId, -2, enc, 0);
        if( pDef==0 ){
          no_such_func = 1;
        }else{
          wrong_num_args = 1;
        }
      }else{
        is_agg = pDef->xFinalize!=0;
        if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){
          ExprSetProperty(pExpr, EP_Unlikely|EP_Skip);
          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++;
                "second argument to %#T() must be a "
                "constant between 0.0 and 1.0", pExpr);
              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
            ** for likelihood(X,0.9375).
            ** EVIDENCE-OF: R-53436-40973 The likely(X) function is equivalent
            ** to likelihood(X,0.9375). */
            /* TUNING: unlikely() probability is 0.0625.  likely() is 0.9375 */
            pExpr->iTable = pDef->zName[0]=='u' ? 8388608 : 125829120;
          }             
        }
#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++;
              sqlite3ErrorMsg(pParse, "not authorized to use function: %#T",
                                      pExpr);
              pNC->nNcErr++;
            }
            pExpr->op = TK_NULL;
            return WRC_Prune;
          }
        }
#endif
        if( pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG) ){
          /* For the purposes of the EP_ConstFunc flag, date and time
          ** functions and other functions that change slowly are considered
          ** constant because they are constant for the duration of one query */
          ** constant because they are constant for the duration of one query.
          ** This allows them to be factored out of inner loops. */
          ExprSetProperty(pExpr,EP_ConstFunc);
        }
        if( (pDef->funcFlags & SQLITE_FUNC_CONSTANT)==0 ){
          /* Clearly non-deterministic functions like random(), but also
          /* Date/time functions that use 'now', and other functions like
          ** date/time functions that use 'now', and other functions like
          ** sqlite_version() that might change over time cannot be used
          ** in an index. */
          notValid(pParse, pNC, "non-deterministic functions",
                   NC_IdxExpr|NC_PartIdx);
          ** in an index or generated column.  Curiously, they can be used
          ** in a CHECK constraint.  SQLServer, MySQL, and PostgreSQL all
          ** all this. */
          sqlite3ResolveNotValid(pParse, pNC, "non-deterministic functions",
                                 NC_IdxExpr|NC_PartIdx|NC_GenCol, 0, pExpr);
        }else{
          assert( (NC_SelfRef & 0xff)==NC_SelfRef ); /* Must fit in 8 bits */
          pExpr->op2 = pNC->ncFlags & NC_SelfRef;
          if( pNC->ncFlags & NC_FromDDL ) ExprSetProperty(pExpr, EP_FromDDL);
        }
        if( (pDef->funcFlags & SQLITE_FUNC_INTERNAL)!=0
         && pParse->nested==0
         && sqlite3Config.bInternalFunctions==0
         && (pParse->db->mDbFlags & DBFLAG_InternalFunc)==0
        ){
          /* Internal-use-only functions are disallowed unless the
          ** SQL is being compiled using sqlite3NestedParse() */
          ** SQL is being compiled using sqlite3NestedParse() or
          ** the SQLITE_TESTCTRL_INTERNAL_FUNCTIONS test-control has be
          ** used to activate internal functions for testing purposes */
          no_such_func = 1;
          pDef = 0;
        }else
        if( (pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE))!=0
         && !IN_RENAME_OBJECT
        ){
          sqlite3ExprFunctionUsable(pParse, pExpr, pDef);
        }
      }

      if( 0==IN_RENAME_OBJECT ){
#ifndef SQLITE_OMIT_WINDOWFUNC
        assert( is_agg==0 || (pDef->funcFlags & SQLITE_FUNC_MINMAX)
          || (pDef->xValue==0 && pDef->xInverse==0)
          || (pDef->xValue && pDef->xInverse && pDef->xSFunc && pDef->xFinalize)
        );
        if( pDef && pDef->xValue==0 && ExprHasProperty(pExpr, EP_WinFunc) ){
        if( pDef && pDef->xValue==0 && pWin ){
          sqlite3ErrorMsg(pParse, 
              "%.*s() may not be used as a window function", nId, zId
              "%#T() may not be used as a window function", pExpr
          );
          pNC->nErr++;
          pNC->nNcErr++;
        }else if( 
              (is_agg && (pNC->ncFlags & NC_AllowAgg)==0)
           || (is_agg && (pDef->funcFlags&SQLITE_FUNC_WINDOW) && !pExpr->y.pWin)
           || (is_agg && pExpr->y.pWin && (pNC->ncFlags & NC_AllowWin)==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) || pExpr->y.pWin ){
          if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pWin ){
            zType = "window";
          }else{
            zType = "aggregate";
          }
          sqlite3ErrorMsg(pParse, "misuse of %s function %.*s()",zType,nId,zId);
          pNC->nErr++;
          sqlite3ErrorMsg(pParse, "misuse of %s function %#T()",zType,pExpr);
          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++;
          sqlite3ErrorMsg(pParse,"misuse of aggregate function %#T()",pExpr);
          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++;
          sqlite3ErrorMsg(pParse, "no such function: %#T", pExpr);
          pNC->nNcErr++;
        }else if( wrong_num_args ){
          sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
               nId, zId);
          pNC->nErr++;
          sqlite3ErrorMsg(pParse,"wrong number of arguments to function %#T()",
               pExpr);
          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 %#T()",
              pExpr
          );
          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
          pNC->ncFlags &= ~(pExpr->y.pWin ? NC_AllowWin : NC_AllowAgg);
          pNC->ncFlags &= ~(NC_AllowWin | (!pWin ? NC_AllowAgg : 0));
#else
          pNC->ncFlags &= ~NC_AllowAgg;
#endif
        }
      }
#ifndef SQLITE_OMIT_WINDOWFUNC
      else if( ExprHasProperty(pExpr, EP_WinFunc) ){
        is_agg = 1;
      }
#endif
      sqlite3WalkExprList(pWalker, pList);
      if( is_agg ){
#ifndef SQLITE_OMIT_WINDOWFUNC
        if( pExpr->y.pWin ){
        if( pWin ){
          Select *pSel = pNC->pWinSelect;
          assert( pWin==0 || (ExprUseYWin(pExpr) && pWin==pExpr->y.pWin) );
          if( IN_RENAME_OBJECT==0 ){
            sqlite3WindowUpdate(pParse, pSel ? pSel->pWinDefn : 0, pWin, pDef);
            if( pParse->db->mallocFailed ) break;
          }
          sqlite3WalkExprList(pWalker, pExpr->y.pWin->pPartition);
          sqlite3WalkExprList(pWalker, pExpr->y.pWin->pOrderBy);
          sqlite3WalkExpr(pWalker, pExpr->y.pWin->pFilter);
          sqlite3WalkExprList(pWalker, pWin->pPartition);
          sqlite3WalkExprList(pWalker, pWin->pOrderBy);
          sqlite3WalkExpr(pWalker, pWin->pFilter);
          sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->y.pWin, pDef);
          if( 0==pSel->pWin 
           || 0==sqlite3WindowCompare(pParse, pSel->pWin, pExpr->y.pWin) 
          sqlite3WindowLink(pSel, pWin);
          ){
            pExpr->y.pWin->pNextWin = pSel->pWin;
            pSel->pWin = pExpr->y.pWin;
          }
          pNC->ncFlags |= NC_AllowWin;
          pNC->ncFlags |= NC_HasWin;
        }else
#endif /* SQLITE_OMIT_WINDOWFUNC */
        {
          NameContext *pNC2 = pNC;
          NameContext *pNC2;          /* For looping up thru outer contexts */
          pExpr->op = TK_AGG_FUNCTION;
          pExpr->op2 = 0;
#ifndef SQLITE_OMIT_WINDOWFUNC
          if( ExprHasProperty(pExpr, EP_WinFunc) ){
            sqlite3WalkExpr(pWalker, pExpr->y.pWin->pFilter);
          }
#endif
          pNC2 = pNC;
          while( pNC2 && !sqlite3FunctionUsesThisSrc(pExpr, pNC2->pSrcList) ){
          while( pNC2 
              && sqlite3ReferencesSrcList(pParse, pExpr, pNC2->pSrcList)==0
          ){
            pExpr->op2++;
            pNC2 = pNC2->pNext;
          }
          assert( pDef!=0 );
          if( pNC2 ){
          assert( pDef!=0 || IN_RENAME_OBJECT );
          if( pNC2 && pDef ){
            assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg );
            assert( SQLITE_FUNC_ANYORDER==NC_OrderAgg );
            testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 );
            testcase( (pDef->funcFlags & SQLITE_FUNC_ANYORDER)!=0 );
            pNC2->ncFlags |= NC_HasAgg | (pDef->funcFlags & SQLITE_FUNC_MINMAX);

          }
          pNC->ncFlags |= NC_AllowAgg;
            pNC2->ncFlags |= NC_HasAgg 
              | ((pDef->funcFlags^SQLITE_FUNC_ANYORDER)
                  & (SQLITE_FUNC_MINMAX|SQLITE_FUNC_ANYORDER));
          }
        }
        pNC->ncFlags |= savedAllowFlags;
        }
      }
      /* FIX ME:  Compute pExpr->affinity based on the expected return
      ** type of the function 
      */
      return WRC_Prune;
    }
#ifndef SQLITE_OMIT_SUBQUERY
    case TK_SELECT:
    case TK_EXISTS:  testcase( pExpr->op==TK_EXISTS );
#endif
    case TK_IN: {
      testcase( pExpr->op==TK_IN );
      if( ExprHasProperty(pExpr, EP_xIsSelect) ){
      if( ExprUseXSelect(pExpr) ){
        int nRef = pNC->nRef;
        testcase( pNC->ncFlags & NC_IsCheck );
        testcase( pNC->ncFlags & NC_PartIdx );
        testcase( pNC->ncFlags & NC_IdxExpr );
        testcase( pNC->ncFlags & NC_GenCol );
        if( pNC->ncFlags & NC_SelfRef ){
        notValid(pParse, pNC, "subqueries", NC_IsCheck|NC_PartIdx|NC_IdxExpr);
        sqlite3WalkSelect(pWalker, pExpr->x.pSelect);
          notValidImpl(pParse, pNC, "subqueries", pExpr, pExpr);
        }else{
          sqlite3WalkSelect(pWalker, pExpr->x.pSelect);
        }
        assert( pNC->nRef>=nRef );
        if( nRef!=pNC->nRef ){
          ExprSetProperty(pExpr, EP_VarSelect);
          pNC->ncFlags |= NC_VarSelect;
        }
      }
      break;
    }
    case TK_VARIABLE: {
      testcase( pNC->ncFlags & NC_IsCheck );
      testcase( pNC->ncFlags & NC_PartIdx );
      testcase( pNC->ncFlags & NC_IdxExpr );
      testcase( pNC->ncFlags & NC_GenCol );
      notValid(pParse, pNC, "parameters", NC_IsCheck|NC_PartIdx|NC_IdxExpr);
      sqlite3ResolveNotValid(pParse, pNC, "parameters",
               NC_IsCheck|NC_PartIdx|NC_IdxExpr|NC_GenCol, pExpr, pExpr);
      break;
    }
    case TK_IS:
    case TK_ISNOT: {
      Expr *pRight;
      Expr *pRight = sqlite3ExprSkipCollateAndLikely(pExpr->pRight);
      assert( !ExprHasProperty(pExpr, EP_Reduced) );
      /* Handle special cases of "x IS TRUE", "x IS FALSE", "x IS NOT TRUE",
      ** and "x IS NOT FALSE". */
      if( (pRight = pExpr->pRight)->op==TK_ID ){
      if( ALWAYS(pRight) && (pRight->op==TK_ID || pRight->op==TK_TRUEFALSE) ){
        int rc = resolveExprStep(pWalker, pRight);
        if( rc==WRC_Abort ) return WRC_Abort;
        if( pRight->op==TK_TRUEFALSE ){
          pExpr->op2 = pExpr->op;
          pExpr->op = TK_TRUTH;
          return WRC_Continue;
        }
      }
      /* Fall thru */
      /* no break */ deliberate_fall_through
    }
    case TK_BETWEEN:
    case TK_EQ:
    case TK_NE:
    case TK_LT:
    case TK_LE:
    case TK_GT:
    case TK_GE: {
      int nLeft, nRight;
      if( pParse->db->mallocFailed ) break;
      assert( pExpr->pLeft!=0 );
      nLeft = sqlite3ExprVectorSize(pExpr->pLeft);
      if( pExpr->op==TK_BETWEEN ){
        assert( ExprUseXList(pExpr) );
        nRight = sqlite3ExprVectorSize(pExpr->x.pList->a[0].pExpr);
        if( nRight==nLeft ){
          nRight = sqlite3ExprVectorSize(pExpr->x.pList->a[1].pExpr);
        }
      }else{
        assert( pExpr->pRight!=0 );
        nRight = sqlite3ExprVectorSize(pExpr->pRight);
      }
      if( nLeft!=nRight ){
        testcase( pExpr->op==TK_EQ );
        testcase( pExpr->op==TK_NE );
        testcase( pExpr->op==TK_LT );
        testcase( pExpr->op==TK_LE );
        testcase( pExpr->op==TK_GT );
        testcase( pExpr->op==TK_GE );
        testcase( pExpr->op==TK_IS );
        testcase( pExpr->op==TK_ISNOT );
        testcase( pExpr->op==TK_BETWEEN );
        sqlite3ErrorMsg(pParse, "row value misused");
        sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr);
      }
      break; 
    }
  }
  assert( pParse->db->mallocFailed==0 || pParse->nErr!=0 );
  return (pParse->nErr || pParse->db->mallocFailed) ? WRC_Abort : WRC_Continue;
  return pParse->nErr ? WRC_Abort : WRC_Continue;
}

/*
** pEList is a list of expressions which are really the result set of the
** a SELECT statement.  pE is a term in an ORDER BY or GROUP BY clause.
** This routine checks to see if pE is a simple identifier which corresponds
** to the AS-name of one of the terms of the expression list.  If it is,
989
990
991
992
993
994
995


996

997
998
999



1000
1001
1002
1003
1004
1005
1006
1318
1319
1320
1321
1322
1323
1324
1325
1326

1327
1328


1329
1330
1331
1332
1333
1334
1335
1336
1337
1338







+
+
-
+

-
-
+
+
+







  Expr *pE           /* Expression we are trying to match */
){
  int i;             /* Loop counter */

  UNUSED_PARAMETER(pParse);

  if( pE->op==TK_ID ){
    const char *zCol;
    assert( !ExprHasProperty(pE, EP_IntValue) );
    char *zCol = pE->u.zToken;
    zCol = pE->u.zToken;
    for(i=0; i<pEList->nExpr; i++){
      char *zAs = pEList->a[i].zName;
      if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
      if( pEList->a[i].fg.eEName==ENAME_NAME
       && sqlite3_stricmp(pEList->a[i].zEName, zCol)==0
      ){
        return i+1;
      }
    }
  }
  return 0;
}

1039
1040
1041
1042
1043
1044
1045
1046
1047


1048
1049
1050
1051
1052
1053
1054
1371
1372
1373
1374
1375
1376
1377


1378
1379
1380
1381
1382
1383
1384
1385
1386







-
-
+
+








  /* 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;
  db->suppressErr = 1;
  rc = sqlite3ResolveExprNames(&nc, pE);
  db->suppressErr = savedSuppErr;
  if( rc ) return 0;

1069
1070
1071
1072
1073
1074
1075
1076


1077
1078
1079
1080

1081
1082
1083
1084
1085
1086
1087
1401
1402
1403
1404
1405
1406
1407

1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421







-
+
+




+







/*
** Generate an ORDER BY or GROUP BY term out-of-range error.
*/
static void resolveOutOfRangeError(
  Parse *pParse,         /* The error context into which to write the error */
  const char *zType,     /* "ORDER" or "GROUP" */
  int i,                 /* The index (1-based) of the term out of range */
  int mx                 /* Largest permissible value of i */
  int mx,                /* Largest permissible value of i */
  Expr *pError           /* Associate the error with the expression */
){
  sqlite3ErrorMsg(pParse, 
    "%r %s BY term out of range - should be "
    "between 1 and %d", i, zType, mx);
  sqlite3RecordErrorOffsetOfExpr(pParse->db, pError);
}

/*
** Analyze the ORDER BY clause in a compound SELECT statement.   Modify
** each term of the ORDER BY clause is a constant integer between 1
** and N where N is the number of columns in the compound SELECT.
**
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
1443
1444
1445
1446
1447
1448
1449

1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464


1465
1466
1467
1468
1469

1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499

















1500
1501
1502
1503
1504
1505
1506
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







-
+














-
-
+
+
+


-
+





+
+
+
+
+
+
+
+
+
+
+




+
+
+






-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
+







  if( pOrderBy==0 ) return 0;
  db = pParse->db;
  if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
    sqlite3ErrorMsg(pParse, "too many terms in ORDER BY clause");
    return 1;
  }
  for(i=0; i<pOrderBy->nExpr; i++){
    pOrderBy->a[i].done = 0;
    pOrderBy->a[i].fg.done = 0;
  }
  pSelect->pNext = 0;
  while( pSelect->pPrior ){
    pSelect->pPrior->pNext = pSelect;
    pSelect = pSelect->pPrior;
  }
  while( pSelect && moreToDo ){
    struct ExprList_item *pItem;
    moreToDo = 0;
    pEList = pSelect->pEList;
    assert( pEList!=0 );
    for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
      int iCol = -1;
      Expr *pE, *pDup;
      if( pItem->done ) continue;
      pE = sqlite3ExprSkipCollate(pItem->pExpr);
      if( pItem->fg.done ) continue;
      pE = sqlite3ExprSkipCollateAndLikely(pItem->pExpr);
      if( NEVER(pE==0) ) continue;
      if( sqlite3ExprIsInteger(pE, &iCol) ){
        if( iCol<=0 || iCol>pEList->nExpr ){
          resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr);
          resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr, pE);
          return 1;
        }
      }else{
        iCol = resolveAsName(pParse, pEList, pE);
        if( iCol==0 ){
          /* Now test if expression pE matches one of the values returned
          ** by pSelect. In the usual case this is done by duplicating the 
          ** expression, resolving any symbols in it, and then comparing
          ** it against each expression returned by the SELECT statement.
          ** Once the comparisons are finished, the duplicate expression
          ** is deleted.
          **
          ** If this is running as part of an ALTER TABLE operation and
          ** the symbols resolve successfully, also resolve the symbols in the
          ** actual expression. This allows the code in alter.c to modify
          ** column references within the ORDER BY expression as required.  */
          pDup = sqlite3ExprDup(db, pE, 0);
          if( !db->mallocFailed ){
            assert(pDup);
            iCol = resolveOrderByTermToExprList(pParse, pSelect, pDup);
            if( IN_RENAME_OBJECT && iCol>0 ){
              resolveOrderByTermToExprList(pParse, pSelect, pE);
            }
          }
          sqlite3ExprDelete(db, pDup);
        }
      }
      if( iCol>0 ){
        /* Convert the ORDER BY term into an integer column number iCol,
        ** taking care to preserve the COLLATE clause if it exists */
        Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0);
        if( pNew==0 ) return 1;
        pNew->flags |= EP_IntValue;
        pNew->u.iValue = iCol;
        if( pItem->pExpr==pE ){
          pItem->pExpr = pNew;
        }else{
          Expr *pParent = pItem->pExpr;
          assert( pParent->op==TK_COLLATE );
          while( pParent->pLeft->op==TK_COLLATE ) pParent = pParent->pLeft;
          assert( pParent->pLeft==pE );
          pParent->pLeft = pNew;
        }
        sqlite3ExprDelete(db, pE);
        pItem->u.x.iOrderByCol = (u16)iCol;
        pItem->done = 1;
        ** taking care to preserve the COLLATE clause if it exists. */
        if( !IN_RENAME_OBJECT ){
          Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0);
          if( pNew==0 ) return 1;
          pNew->flags |= EP_IntValue;
          pNew->u.iValue = iCol;
          if( pItem->pExpr==pE ){
            pItem->pExpr = pNew;
          }else{
            Expr *pParent = pItem->pExpr;
            assert( pParent->op==TK_COLLATE );
            while( pParent->pLeft->op==TK_COLLATE ) pParent = pParent->pLeft;
            assert( pParent->pLeft==pE );
            pParent->pLeft = pNew;
          }
          sqlite3ExprDelete(db, pE);
          pItem->u.x.iOrderByCol = (u16)iCol;
        }
        pItem->fg.done = 1;
      }else{
        moreToDo = 1;
      }
    }
    pSelect = pSelect->pNext;
  }
  for(i=0; i<pOrderBy->nExpr; i++){
    if( pOrderBy->a[i].done==0 ){
    if( pOrderBy->a[i].fg.done==0 ){
      sqlite3ErrorMsg(pParse, "%r ORDER BY term does not match any "
            "column in the result set", i+1);
      return 1;
    }
  }
  return 0;
}
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
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
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611







-
+









-
+


-
+
-





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  const char *zType     /* "ORDER" or "GROUP" */
){
  int i;
  sqlite3 *db = pParse->db;
  ExprList *pEList;
  struct ExprList_item *pItem;

  if( pOrderBy==0 || pParse->db->mallocFailed ) return 0;
  if( pOrderBy==0 || pParse->db->mallocFailed || IN_RENAME_OBJECT ) return 0;
  if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
    sqlite3ErrorMsg(pParse, "too many terms in %s BY clause", zType);
    return 1;
  }
  pEList = pSelect->pEList;
  assert( pEList!=0 );  /* sqlite3SelectNew() guarantees this */
  for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
    if( pItem->u.x.iOrderByCol ){
      if( pItem->u.x.iOrderByCol>pEList->nExpr ){
        resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr);
        resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr, 0);
        return 1;
      }
      resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr,
      resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr,0);
                   zType,0);
    }
  }
  return 0;
}

#ifndef SQLITE_OMIT_WINDOWFUNC
/*
** Walker callback for windowRemoveExprFromSelect().
*/
static int resolveRemoveWindowsCb(Walker *pWalker, Expr *pExpr){
  UNUSED_PARAMETER(pWalker);
  if( ExprHasProperty(pExpr, EP_WinFunc) ){
    Window *pWin = pExpr->y.pWin;
    sqlite3WindowUnlinkFromSelect(pWin);
  }
  return WRC_Continue;
}

/*
** Remove any Window objects owned by the expression pExpr from the
** Select.pWin list of Select object pSelect.
*/
static void windowRemoveExprFromSelect(Select *pSelect, Expr *pExpr){
  if( pSelect->pWin ){
    Walker sWalker;
    memset(&sWalker, 0, sizeof(Walker));
    sWalker.xExprCallback = resolveRemoveWindowsCb;
    sWalker.u.pSelect = pSelect;
    sqlite3WalkExpr(&sWalker, pExpr);
  }
}
#else
# define windowRemoveExprFromSelect(a, b)
#endif /* SQLITE_OMIT_WINDOWFUNC */

/*
** pOrderBy is an ORDER BY or GROUP BY clause in SELECT statement pSelect.
** The Name context of the SELECT statement is pNC.  zType is either
** "ORDER" or "GROUP" depending on which type of clause pOrderBy is.
**
** This routine resolves each term of the clause into an expression.
** If the order-by term is an integer I between 1 and N (where N is the
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
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
1628
1629
1630
1631
1632
1633
1634

1635
1636
1637
1638
1639

1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657

1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671






1672
1673
1674
1675







1676
1677
1678
1679
1680
1681
1682







-
+




-
+
+
















-
+













-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-







){
  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 = sqlite3ExprSkipCollate(pE);
    Expr *pE2 = sqlite3ExprSkipCollateAndLikely(pE);
    if( NEVER(pE2==0) ) continue;
    if( zType[0]!='G' ){
      iCol = resolveAsName(pParse, pSelect->pEList, pE2);
      if( iCol>0 ){
        /* If an AS-name match is found, mark this ORDER BY column as being
        ** a copy of the iCol-th result-set column.  The subsequent call to
        ** sqlite3ResolveOrderGroupBy() will convert the expression to a
        ** copy of the iCol-th result-set expression. */
        pItem->u.x.iOrderByCol = (u16)iCol;
        continue;
      }
    }
    if( sqlite3ExprIsInteger(pE2, &iCol) ){
      /* The ORDER BY term is an integer constant.  Again, set the column
      ** number so that sqlite3ResolveOrderGroupBy() will convert the
      ** order-by term to a copy of the result-set expression */
      if( iCol<1 || iCol>0xffff ){
        resolveOutOfRangeError(pParse, zType, i+1, nResult);
        resolveOutOfRangeError(pParse, zType, i+1, nResult, pE2);
        return 1;
      }
      pItem->u.x.iOrderByCol = (u16)iCol;
      continue;
    }

    /* Otherwise, treat the ORDER BY term as an ordinary expression */
    pItem->u.x.iOrderByCol = 0;
    if( sqlite3ResolveExprNames(pNC, pE) ){
      return 1;
    }
    for(j=0; j<pSelect->pEList->nExpr; j++){
      if( sqlite3ExprCompare(0, pE, pSelect->pEList->a[j].pExpr, -1)==0 ){
#ifndef SQLITE_OMIT_WINDOWFUNC
        if( ExprHasProperty(pE, EP_WinFunc) ){
          /* Since this window function is being changed into a reference
          ** to the same window function the result set, remove the instance
          ** of this window function from the Select.pWin list. */
          Window **pp;
        /* Since this expresion is being changed into a reference
        ** to an identical expression in the result set, remove all Window
        ** objects belonging to the expression from the Select.pWin list. */
        windowRemoveExprFromSelect(pSelect, pE);
          for(pp=&pSelect->pWin; *pp; pp=&(*pp)->pNextWin){
            if( *pp==pE->y.pWin ){
              *pp = (*pp)->pNextWin;
            }    
          }
        }
#endif
        pItem->u.x.iOrderByCol = j+1;
      }
    }
  }
  return sqlite3ResolveOrderGroupBy(pParse, pSelect, pOrderBy, zType);
}

1337
1338
1339
1340
1341
1342
1343
1344

1345
1346
1347
1348
1349
1350
1351
1352

1353

1354
1355
1356
1357
1358
1359
1360
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







-
+








+

+







  ** prior call to sqlite3SelectExpand().  When that happens, let
  ** sqlite3SelectPrep() do all of the processing for this SELECT.
  ** sqlite3SelectPrep() will invoke both sqlite3SelectExpand() and
  ** this routine in the correct order.
  */
  if( (p->selFlags & SF_Expanded)==0 ){
    sqlite3SelectPrep(pParse, p, pOuterNC);
    return (pParse->nErr || db->mallocFailed) ? WRC_Abort : WRC_Prune;
    return pParse->nErr ? WRC_Abort : WRC_Prune;
  }

  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;
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
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







-
+


-
-
+
+
-
-
+


-
-
-
-
-
-
-



-
+
+

+
+
+
+
+
+
-
-
-
+
+
+
+







      Select *pSub = p->pSrc->a[0].pSelect;
      assert( p->pSrc->nSrc==1 && p->pOrderBy );
      assert( pSub->pPrior && pSub->pOrderBy==0 );
      pSub->pOrderBy = p->pOrderBy;
      p->pOrderBy = 0;
    }
  
    /* Recursively resolve names in all subqueries
    /* Recursively resolve names in all subqueries in the FROM clause
    */
    for(i=0; i<p->pSrc->nSrc; i++){
      struct SrcList_item *pItem = &p->pSrc->a[i];
      if( pItem->pSelect ){
      SrcItem *pItem = &p->pSrc->a[i];
      if( pItem->pSelect && (pItem->pSelect->selFlags & SF_Resolved)==0 ){
        NameContext *pNC;         /* Used to iterate name contexts */
        int nRef = 0;             /* Refcount for pOuterNC and outer contexts */
        int nRef = pOuterNC ? pOuterNC->nRef : 0;
        const char *zSavedContext = pParse->zAuthContext;

        /* Count the total number of references to pOuterNC and all of its
        ** parent contexts. After resolving references to expressions in
        ** pItem->pSelect, check if this value has changed. If so, then
        ** SELECT statement pItem->pSelect must be correlated. Set the
        ** pItem->fg.isCorrelated flag if this is the case. */
        for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef += pNC->nRef;

        if( pItem->zName ) pParse->zAuthContext = pItem->zName;
        sqlite3ResolveSelectNames(pParse, pItem->pSelect, pOuterNC);
        pParse->zAuthContext = zSavedContext;
        if( pParse->nErr || db->mallocFailed ) return WRC_Abort;
        if( pParse->nErr ) return WRC_Abort;
        assert( db->mallocFailed==0 );

        /* If the number of references to the outer context changed when
        ** expressions in the sub-select were resolved, the sub-select
        ** is correlated. It is not required to check the refcount on any
        ** but the innermost outer context object, as lookupName() increments
        ** the refcount on all contexts between the current one and the
        ** context containing the column when it resolves a name. */
        for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef;
        assert( pItem->fg.isCorrelated==0 && nRef<=0 );
        pItem->fg.isCorrelated = (nRef!=0);
        if( pOuterNC ){
          assert( pItem->fg.isCorrelated==0 && pOuterNC->nRef>=nRef );
          pItem->fg.isCorrelated = (pOuterNC->nRef>nRef);
        }
      }
    }
  
    /* Set up the local name-context to pass to sqlite3ResolveExprNames() to
    ** resolve the result-set expression list.
    */
    sNC.ncFlags = NC_AllowAgg|NC_AllowWin;
1417
1418
1419
1420
1421
1422
1423

1424

1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444

1445
1446





1447


1448
1449
1450
1451
1452

1453
1454
1455
1456
1457
1458













1459
1460
1461
1462
1463
1464
1465
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







+
-
+




-
-
-
-
-
-
-








-
+


+
+
+
+
+
-
+
+




-
+






+
+
+
+
+
+
+
+
+
+
+
+
+







    /* If there are no aggregate functions in the result-set, and no GROUP BY 
    ** expression, do not allow aggregates in any of the other expressions.
    */
    assert( (p->selFlags & SF_Aggregate)==0 );
    pGroupBy = p->pGroupBy;
    if( pGroupBy || (sNC.ncFlags & NC_HasAgg)!=0 ){
      assert( NC_MinMaxAgg==SF_MinMaxAgg );
      assert( NC_OrderAgg==SF_OrderByReqd );
      p->selFlags |= SF_Aggregate | (sNC.ncFlags&NC_MinMaxAgg);
      p->selFlags |= SF_Aggregate | (sNC.ncFlags&(NC_MinMaxAgg|NC_OrderAgg));
    }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))==0 );
    assert( (sNC.ncFlags & (NC_UAggInfo|NC_UUpsert|NC_UBaseReg))==0 );
    sNC.uNC.pEList = p->pEList;
    sNC.ncFlags |= NC_UEList;
    if( p->pHaving ){
      if( (p->selFlags & SF_Aggregate)==0 ){
        sqlite3ErrorMsg(pParse, "HAVING clause on a non-aggregate query");
        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++){
      struct SrcList_item *pItem = &p->pSrc->a[i];
      SrcItem *pItem = &p->pSrc->a[i];
      if( pItem->fg.isTabFunc
       && sqlite3ResolveExprListNames(&sNC, pItem->u1.pFuncArg) 
      ){
        return WRC_Abort;
      }
    }

#ifndef SQLITE_OMIT_WINDOWFUNC
    if( IN_RENAME_OBJECT ){
      Window *pWin;
      for(pWin=p->pWinDefn; pWin; pWin=pWin->pNextWin){
        if( sqlite3ResolveExprListNames(&sNC, pWin->pOrderBy)
         || sqlite3ResolveExprListNames(&sNC, pWin->pPartition)
        ){
          return WRC_Abort;
        }
      }
    }
#endif

    /* The ORDER BY and GROUP BY clauses may not refer to terms in
    ** outer queries 
    */
    sNC.pNext = 0;
    sNC.ncFlags |= NC_AllowAgg|NC_AllowWin;

1480
1481
1482
1483
1484
1485
1486

1487

1488
1489
1490
1491
1492
1493
1494
1867
1868
1869
1870
1871
1872
1873
1874

1875
1876
1877
1878
1879
1880
1881
1882







+
-
+







    ** 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;
    }
1583
1584
1585
1586
1587
1588
1589
1590

1591
1592
1593
1594
1595


1596
1597
1598

1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610


1611
1612



1613
1614
1615

1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627


1628
1629
1630















1631














1632




1633
1634
1635
1636
1637
1638
1639
1971
1972
1973
1974
1975
1976
1977

1978
1979
1980
1981


1982
1983
1984
1985

1986
1987
1988
1989
1990
1991
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
2017
2018
2019



2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049

2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060







-
+



-
-
+
+


-
+












+
+
-
-
+
+
+
-

-
+












+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+







** An error message is left in pParse if anything is amiss.  The number
** if errors is returned.
*/
int sqlite3ResolveExprNames( 
  NameContext *pNC,       /* Namespace to resolve expressions in. */
  Expr *pExpr             /* The expression to be analyzed. */
){
  u16 savedHasAgg;
  int savedHasAgg;
  Walker w;

  if( pExpr==0 ) return SQLITE_OK;
  savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg);
  pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg);
  savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
  pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
  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 );
  if( pNC->ncFlags & NC_HasAgg ){
    ExprSetProperty(pExpr, EP_Agg);
  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.
*/
int sqlite3ResolveExprListNames( 
  NameContext *pNC,       /* Namespace to resolve expressions in. */
  ExprList *pList         /* The expression list to be analyzed. */
){
  int i;
  int savedHasAgg = 0;
  Walker w;
  if( pList ){
    for(i=0; i<pList->nExpr; i++){
      if( sqlite3ResolveExprNames(pNC, pList->a[i].pExpr) ) return WRC_Abort;
  if( pList==0 ) return WRC_Continue;
  w.pParse = pNC->pParse;
  w.xExprCallback = resolveExprStep;
  w.xSelectCallback = resolveSelectStep;
  w.xSelectCallback2 = 0;
  w.u.pNC = pNC;
  savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
  pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
  for(i=0; i<pList->nExpr; i++){
    Expr *pExpr = pList->a[i].pExpr;
    if( pExpr==0 ) continue;
#if SQLITE_MAX_EXPR_DEPTH>0
    w.pParse->nHeight += pExpr->nHeight;
    if( sqlite3ExprCheckHeight(w.pParse, w.pParse->nHeight) ){
      return WRC_Abort;
    }
#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 );
    if( pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg) ){
      ExprSetProperty(pExpr, pNC->ncFlags & (NC_HasAgg|NC_HasWin) );
      savedHasAgg |= pNC->ncFlags &
                          (NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
      pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
  }
    }
    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
** decendents of the SELECT, including compounds off of p->pPrior,
** subqueries in expressions, and subqueries used as FROM clause
1658
1659
1660
1661
1662
1663
1664
1665


1666


1667
1668





1669
1670
1671



1672
1673
1674
1675
1676
1677
1678
1679
1680






1681
1682
1683

1684

1685


1686
1687

1688
1689
1690
1691










1692
1693
1694
1695
1696




1697
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







-
+
+

+
+
-
-
+
+
+
+
+

-
-
+
+
+



-
-
-
-
-
-
+
+
+
+
+
+



+

+
-
+
+


+
-
-
-
-
+
+
+
+
+
+
+
+
+
+


-
-
-
+
+
+
+

  w.xSelectCallback2 = 0;
  w.pParse = pParse;
  w.u.pNC = pOuterNC;
  sqlite3WalkSelect(&w, p);
}

/*
** Resolve names in expressions that can only reference a single table:
** Resolve names in expressions that can only reference a single table
** or which cannot reference any tables at all.  Examples:
**
**                                                    "type" flag
**                                                    ------------
**    *   CHECK constraints
**    *   WHERE clauses on partial indices
**    (1)   CHECK constraints                         NC_IsCheck
**    (2)   WHERE clauses on partial indices          NC_PartIdx
**    (3)   Expressions in indexes on expressions     NC_IdxExpr
**    (4)   Expression arguments to VACUUM INTO.      0
**    (5)   GENERATED ALWAYS as expressions           NC_GenCol
**
** The Expr.iTable value for Expr.op==TK_COLUMN nodes of the expression
** is set to -1 and the Expr.iColumn value is set to the column number.
** In all cases except (4), the Expr.iTable value for Expr.op==TK_COLUMN
** nodes of the expression is set to -1 and the Expr.iColumn value is
** set to the column number.  In case (4), TK_COLUMN nodes cause an error.
**
** Any errors cause an error message to be set in pParse.
*/
void sqlite3ResolveSelfReference(
  Parse *pParse,      /* Parsing context */
  Table *pTab,        /* The table being referenced */
  int type,           /* NC_IsCheck or NC_PartIdx or NC_IdxExpr */
  Expr *pExpr,        /* Expression to resolve.  May be NULL. */
  ExprList *pList     /* Expression list to resolve.  May be NULL. */
int sqlite3ResolveSelfReference(
  Parse *pParse,   /* Parsing context */
  Table *pTab,     /* The table being referenced, or NULL */
  int type,        /* NC_IsCheck, NC_PartIdx, NC_IdxExpr, NC_GenCol, or 0 */
  Expr *pExpr,     /* Expression to resolve.  May be NULL. */
  ExprList *pList  /* Expression list to resolve.  May be NULL. */
){
  SrcList sSrc;                   /* Fake SrcList for pParse->pNewTable */
  NameContext sNC;                /* Name context for pParse->pNewTable */
  int rc;

  assert( type==0 || pTab!=0 );
  assert( type==NC_IsCheck || type==NC_PartIdx || type==NC_IdxExpr );
  assert( type==NC_IsCheck || type==NC_PartIdx || type==NC_IdxExpr
          || type==NC_GenCol || pTab==0 );
  memset(&sNC, 0, sizeof(sNC));
  memset(&sSrc, 0, sizeof(sSrc));
  if( pTab ){
  sSrc.nSrc = 1;
  sSrc.a[0].zName = pTab->zName;
  sSrc.a[0].pTab = pTab;
  sSrc.a[0].iCursor = -1;
    sSrc.nSrc = 1;
    sSrc.a[0].zName = pTab->zName;
    sSrc.a[0].pTab = pTab;
    sSrc.a[0].iCursor = -1;
    if( pTab->pSchema!=pParse->db->aDb[1].pSchema ){
      /* Cause EP_FromDDL to be set on TK_FUNCTION nodes of non-TEMP
      ** schema elements */
      type |= NC_FromDDL;
    }
  }
  sNC.pParse = pParse;
  sNC.pSrcList = &sSrc;
  sNC.ncFlags = type;
  if( sqlite3ResolveExprNames(&sNC, pExpr) ) return;
  if( pList ) sqlite3ResolveExprListNames(&sNC, pList);
  sNC.ncFlags = type | NC_IsDDL;
  if( (rc = sqlite3ResolveExprNames(&sNC, pExpr))!=SQLITE_OK ) return rc;
  if( pList ) rc = sqlite3ResolveExprListNames(&sNC, pList);
  return rc;
}

Changes to src/rowset.c.

173
174
175
176
177
178
179
180

181
182
183
184
185
186
187
173
174
175
176
177
178
179

180
181
182
183
184
185
186
187







-
+







  sqlite3RowSetClear(pArg);
  sqlite3DbFree(((RowSet*)pArg)->db, pArg);
}

/*
** Allocate a new RowSetEntry object that is associated with the
** given RowSet.  Return a pointer to the new and completely uninitialized
** objected.
** object.
**
** In an OOM situation, the RowSet.db->mallocFailed flag is set and this
** routine returns NULL.
*/
static struct RowSetEntry *rowSetEntryAlloc(RowSet *p){
  assert( p!=0 );
  if( p->nFresh==0 ){  /*OPTIMIZATION-IF-FALSE*/
449
450
451
452
453
454
455
456

457
458
459
460
461
462
463
449
450
451
452
453
454
455

456
457
458
459
460
461
462
463







-
+







  ** To save unnecessary work, only do this when the batch number changes.
  */
  if( iBatch!=pRowSet->iBatch ){  /*OPTIMIZATION-IF-FALSE*/
    p = pRowSet->pEntry;
    if( p ){
      struct RowSetEntry **ppPrevTree = &pRowSet->pForest;
      if( (pRowSet->rsFlags & ROWSET_SORTED)==0 ){ /*OPTIMIZATION-IF-FALSE*/
        /* Only sort the current set of entiries if they need it */
        /* Only sort the current set of entries if they need it */
        p = rowSetEntrySort(p);
      }
      for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){
        ppPrevTree = &pTree->pRight;
        if( pTree->pLeft==0 ){
          pTree->pLeft = rowSetListToTree(p);
          break;

Changes to src/select.c.

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
9
10
11
12
13
14
15














16
17
18
19
20
21
22
23

24
25
26
27
28
29
30
31







-
-
-
-
-
-
-
-
-
-
-
-
-
-








-
+







**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
*/
#include "sqliteInt.h"

/*
** Trace output macros
*/
#if SELECTTRACE_ENABLED
/***/ int sqlite3SelectTrace = 0;
# define SELECTTRACE(K,P,S,X)  \
  if(sqlite3SelectTrace&(K))   \
    sqlite3DebugPrintf("%u/%d/%p: ",(S)->selId,(P)->addrExplain,(S)),\
    sqlite3DebugPrintf X
#else
# define SELECTTRACE(K,P,S,X)
#endif


/*
** An instance of the following object is used to record information about
** how to process the DISTINCT keyword, to simplify passing that information
** into the selectInnerLoop() routine.
*/
typedef struct DistinctCtx DistinctCtx;
struct DistinctCtx {
  u8 isTnct;      /* True if the DISTINCT keyword is present */
  u8 isTnct;      /* 0: Not distinct. 1: DISTICT  2: DISTINCT and ORDER BY */
  u8 eTnctType;   /* One of the WHERE_DISTINCT_* operators */
  int tabTnct;    /* Ephemeral table used for DISTINCT processing */
  int addrTnct;   /* Address of OP_OpenEphemeral opcode for tabTnct */
};

/*
** An instance of the following object is used to record information about
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
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







+
+
+
+





-
+
+
+
+


+









+




+
+
+
+

-
-
+











+







  struct DeferredCsr {
    Table *pTab;        /* Table definition */
    int iCsr;           /* Cursor number for table */
    int nKey;           /* Number of PK columns for table pTab (>=1) */
  } aDefer[4];
#endif
  struct RowLoadInfo *pDeferredRowLoad;  /* Deferred row loading info or NULL */
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
  int addrPush;         /* First instruction to push data into sorter */
  int addrPushEnd;      /* Last instruction that pushes data into sorter */
#endif
};
#define SORTFLAG_UseSorter  0x01   /* Use SorterOpen instead of OpenEphemeral */

/*
** Delete all the content of a Select structure.  Deallocate the structure
** itself only if bFree is true.
** itself depending on the value of bFree
**
** If bFree==1, call sqlite3DbFree() on the p object.
** If bFree==0, Leave the first Select object unfreed
*/
static void clearSelect(sqlite3 *db, Select *p, int bFree){
  assert( db!=0 );
  while( p ){
    Select *pPrior = p->pPrior;
    sqlite3ExprListDelete(db, p->pEList);
    sqlite3SrcListDelete(db, p->pSrc);
    sqlite3ExprDelete(db, p->pWhere);
    sqlite3ExprListDelete(db, p->pGroupBy);
    sqlite3ExprDelete(db, p->pHaving);
    sqlite3ExprListDelete(db, p->pOrderBy);
    sqlite3ExprDelete(db, p->pLimit);
    if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlite3WithDelete(db, p->pWith);
#ifndef SQLITE_OMIT_WINDOWFUNC
    if( OK_IF_ALWAYS_TRUE(p->pWinDefn) ){
      sqlite3WindowListDelete(db, p->pWinDefn);
    }
    while( p->pWin ){
      assert( p->pWin->ppThis==&p->pWin );
      sqlite3WindowUnlinkFromSelect(p->pWin);
    }
#endif
    if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlite3WithDelete(db, p->pWith);
    if( bFree ) sqlite3DbFreeNN(db, p);
    if( bFree ) sqlite3DbNNFreeNN(db, p);
    p = pPrior;
    bFree = 1;
  }
}

/*
** Initialize a SelectDest structure.
*/
void sqlite3SelectDestInit(SelectDest *pDest, int eDest, int iParm){
  pDest->eDest = (u8)eDest;
  pDest->iSDParm = iParm;
  pDest->iSDParm2 = 0;
  pDest->zAffSdst = 0;
  pDest->iSdst = 0;
  pDest->nSdst = 0;
}


/*
131
132
133
134
135
136
137
138

139
140

141
142
143
144
145
146
147
130
131
132
133
134
135
136

137
138

139
140
141
142
143
144
145
146







-
+

-
+







  Expr *pWhere,         /* the WHERE clause */
  ExprList *pGroupBy,   /* the GROUP BY clause */
  Expr *pHaving,        /* the HAVING clause */
  ExprList *pOrderBy,   /* the ORDER BY clause */
  u32 selFlags,         /* Flag parameters, such as SF_Distinct */
  Expr *pLimit          /* LIMIT value.  NULL means not used */
){
  Select *pNew;
  Select *pNew, *pAllocated;
  Select standin;
  pNew = sqlite3DbMallocRawNN(pParse->db, sizeof(*pNew) );
  pAllocated = pNew = sqlite3DbMallocRawNN(pParse->db, sizeof(*pNew) );
  if( pNew==0 ){
    assert( pParse->db->mallocFailed );
    pNew = &standin;
  }
  if( pEList==0 ){
    pEList = sqlite3ExprListAppend(pParse, 0,
                                   sqlite3Expr(pParse->db,TK_ASTERISK,0));
167
168
169
170
171
172
173
174

175
176
177
178
179

180
181
182
183
184
185
186
166
167
168
169
170
171
172

173
174
175
176


177
178
179
180
181
182
183
184







-
+



-
-
+







  pNew->pWith = 0;
#ifndef SQLITE_OMIT_WINDOWFUNC
  pNew->pWin = 0;
  pNew->pWinDefn = 0;
#endif
  if( pParse->db->mallocFailed ) {
    clearSelect(pParse->db, pNew, pNew!=&standin);
    pNew = 0;
    pAllocated = 0;
  }else{
    assert( pNew->pSrc!=0 || pParse->nErr>0 );
  }
  assert( pNew!=&standin );
  return pNew;
  return pAllocated;
}


/*
** Delete the given Select structure and all of its substructures.
*/
void sqlite3SelectDelete(sqlite3 *db, Select *p){
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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+












-
-
-
-
-
-
-
+
+
+
+
+
+
+







**     JT_LEFT
**     JT_RIGHT
**
** A full outer join is the combination of JT_LEFT and JT_RIGHT.
**
** If an illegal or unsupported join type is seen, then still return
** a join type, but put an error in the pParse structure.
**
** These are the valid join types:
**
**
**      pA       pB       pC               Return Value
**     -------  -----    -----             ------------
**     CROSS      -        -                 JT_CROSS
**     INNER      -        -                 JT_INNER
**     LEFT       -        -                 JT_LEFT|JT_OUTER
**     LEFT     OUTER      -                 JT_LEFT|JT_OUTER
**     RIGHT      -        -                 JT_RIGHT|JT_OUTER
**     RIGHT    OUTER      -                 JT_RIGHT|JT_OUTER
**     FULL       -        -                 JT_LEFT|JT_RIGHT|JT_OUTER
**     FULL     OUTER      -                 JT_LEFT|JT_RIGHT|JT_OUTER
**     NATURAL  INNER      -                 JT_NATURAL|JT_INNER
**     NATURAL  LEFT       -                 JT_NATURAL|JT_LEFT|JT_OUTER
**     NATURAL  LEFT     OUTER               JT_NATURAL|JT_LEFT|JT_OUTER
**     NATURAL  RIGHT      -                 JT_NATURAL|JT_RIGHT|JT_OUTER
**     NATURAL  RIGHT    OUTER               JT_NATURAL|JT_RIGHT|JT_OUTER
**     NATURAL  FULL       -                 JT_NATURAL|JT_LEFT|JT_RIGHT
**     NATURAL  FULL     OUTER               JT_NATRUAL|JT_LEFT|JT_RIGHT
**
** To preserve historical compatibly, SQLite also accepts a variety 
** of other non-standard and in many cases non-sensical join types.
** This routine makes as much sense at it can from the nonsense join
** type and returns a result.  Examples of accepted nonsense join types
** include but are not limited to:
**
**          INNER CROSS JOIN        ->   same as JOIN
**          NATURAL CROSS JOIN      ->   same as NATURAL JOIN
**          OUTER LEFT JOIN         ->   same as LEFT JOIN
**          LEFT NATURAL JOIN       ->   same as NATURAL LEFT JOIN
**          LEFT RIGHT JOIN         ->   same as FULL JOIN
**          RIGHT OUTER FULL JOIN   ->   same as FULL JOIN
**          CROSS CROSS CROSS JOIN  ->   same as JOIN
**
** The only restrictions on the join type name are:
**
**    *   "INNER" cannot appear together with "OUTER", "LEFT", "RIGHT",
**        or "FULL".
**
**    *   "CROSS" cannot appear together with "OUTER", "LEFT", "RIGHT,
**        or "FULL".
**
**    *   If "OUTER" is present then there must also be one of
**        "LEFT", "RIGHT", or "FULL"
*/
int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){
  int jointype = 0;
  Token *apAll[3];
  Token *p;
                             /*   0123456789 123456789 123456789 123 */
  static const char zKeyText[] = "naturaleftouterightfullinnercross";
  static const struct {
    u8 i;        /* Beginning of keyword text in zKeyText[] */
    u8 nChar;    /* Length of the keyword in characters */
    u8 code;     /* Join type mask */
  } aKeyword[] = {
    /* natural */ { 0,  7, JT_NATURAL                },
    /* left    */ { 6,  4, JT_LEFT|JT_OUTER          },
    /* outer   */ { 10, 5, JT_OUTER                  },
    /* right   */ { 14, 5, JT_RIGHT|JT_OUTER         },
    /* full    */ { 19, 4, JT_LEFT|JT_RIGHT|JT_OUTER },
    /* inner   */ { 23, 5, JT_INNER                  },
    /* cross   */ { 28, 5, JT_INNER|JT_CROSS         },
    /* (0) natural */ { 0,  7, JT_NATURAL                },
    /* (1) left    */ { 6,  4, JT_LEFT|JT_OUTER          },
    /* (2) outer   */ { 10, 5, JT_OUTER                  },
    /* (3) right   */ { 14, 5, JT_RIGHT|JT_OUTER         },
    /* (4) full    */ { 19, 4, JT_LEFT|JT_RIGHT|JT_OUTER },
    /* (5) inner   */ { 23, 5, JT_INNER                  },
    /* (6) cross   */ { 28, 5, JT_INNER|JT_CROSS         },
  };
  int i, j;
  apAll[0] = pA;
  apAll[1] = pB;
  apAll[2] = pC;
  for(i=0; i<3 && apAll[i]; i++){
    p = apAll[i];
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
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







-
+
+

-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-









-
+

+
+
-
-
+
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+








-
+
+


-
+
+




+
+

-
-
-
+
+
+
+
+
+

+










-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+


-
-
+
+





-
-
+
+












-
+
+

-
+


-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+




-
-
-
+
+
+
+
+
+
+

-
+
+
+
+
+

-
+

-
-
-
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+






+
+
+
+
+
-
-
+
+
+
+




-
+

-
+



-
+


-
-
+
+






-
+


-
+

-
-
+
+


+
-
+






-
-

+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-









-
-
+
+
+
+





+
+
+


-
+

-
+
+





-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
+
+
+
+
+
+
+
+
+







    if( j>=ArraySize(aKeyword) ){
      jointype |= JT_ERROR;
      break;
    }
  }
  if(
     (jointype & (JT_INNER|JT_OUTER))==(JT_INNER|JT_OUTER) ||
     (jointype & JT_ERROR)!=0
     (jointype & JT_ERROR)!=0 ||
     (jointype & (JT_OUTER|JT_LEFT|JT_RIGHT))==JT_OUTER
  ){
    const char *zSp = " ";
    assert( pB!=0 );
    if( pC==0 ){ zSp++; }
    sqlite3ErrorMsg(pParse, "unknown or unsupported join type: "
       "%T %T%s%T", pA, pB, zSp, pC);
    const char *zSp1 = " ";
    const char *zSp2 = " ";
    if( pB==0 ){ zSp1++; }
    if( pC==0 ){ zSp2++; }
    sqlite3ErrorMsg(pParse, "unknown join type: "
       "%T%s%T%s%T", pA, zSp1, pB, zSp2, pC);
    jointype = JT_INNER;
  }else if( (jointype & JT_OUTER)!=0 
         && (jointype & (JT_LEFT|JT_RIGHT))!=JT_LEFT ){
    sqlite3ErrorMsg(pParse, 
      "RIGHT and FULL OUTER JOINs are not currently supported");
    jointype = JT_INNER;
  }
  return jointype;
}

/*
** Return the index of a column in a table.  Return -1 if the column
** is not contained in the table.
*/
static int columnIndex(Table *pTab, const char *zCol){
int sqlite3ColumnIndex(Table *pTab, const char *zCol){
  int i;
  u8 h = sqlite3StrIHash(zCol);
  Column *pCol;
  for(i=0; i<pTab->nCol; i++){
    if( sqlite3StrICmp(pTab->aCol[i].zName, zCol)==0 ) return i;
  for(pCol=pTab->aCol, i=0; i<pTab->nCol; pCol++, i++){
    if( pCol->hName==h && sqlite3StrICmp(pCol->zCnName, zCol)==0 ) return i;
  }
  return -1;
}

/*
** Mark a subquery result column as having been used.
*/
void sqlite3SrcItemColumnUsed(SrcItem *pItem, int iCol){
  assert( pItem!=0 );
  assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) );
  if( pItem->fg.isNestedFrom ){
    ExprList *pResults;
    assert( pItem->pSelect!=0 );
    pResults = pItem->pSelect->pEList;
    assert( pResults!=0 );
    assert( iCol>=0 && iCol<pResults->nExpr );
    pResults->a[iCol].fg.bUsed = 1;
  }
}
** Search the first N tables in pSrc, from left to right, looking for a
** table that has a column named zCol.  

/*
** Search the tables iStart..iEnd (inclusive) in pSrc, looking for a
** table that has a column named zCol.  The search is left-to-right.
** The first match found is returned.
**
** When found, set *piTab and *piCol to the table index and column index
** of the matching column and return TRUE.
**
** If not found, return FALSE.
*/
static int tableAndColumnIndex(
  SrcList *pSrc,       /* Array of tables to search */
  int N,               /* Number of tables in pSrc->a[] to search */
  int iStart,          /* First member of pSrc->a[] to check */
  int iEnd,            /* Last member of pSrc->a[] to check */
  const char *zCol,    /* Name of the column we are looking for */
  int *piTab,          /* Write index of pSrc->a[] here */
  int *piCol           /* Write index of pSrc->a[*piTab].pTab->aCol[] here */
  int *piCol,          /* Write index of pSrc->a[*piTab].pTab->aCol[] here */
  int bIgnoreHidden    /* Ignore hidden columns */
){
  int i;               /* For looping over tables in pSrc */
  int iCol;            /* Index of column matching zCol */

  assert( iEnd<pSrc->nSrc );
  assert( iStart>=0 );
  assert( (piTab==0)==(piCol==0) );  /* Both or neither are NULL */
  for(i=0; i<N; i++){
    iCol = columnIndex(pSrc->a[i].pTab, zCol);
    if( iCol>=0 ){

  for(i=iStart; i<=iEnd; i++){
    iCol = sqlite3ColumnIndex(pSrc->a[i].pTab, zCol);
    if( iCol>=0 
     && (bIgnoreHidden==0 || IsHiddenColumn(&pSrc->a[i].pTab->aCol[iCol])==0)
    ){
      if( piTab ){
        sqlite3SrcItemColumnUsed(&pSrc->a[i], iCol);
        *piTab = i;
        *piCol = iCol;
      }
      return 1;
    }
  }
  return 0;
}

/*
** This function is used to add terms implied by JOIN syntax to the
** WHERE clause expression of a SELECT statement. The new term, which
** is ANDed with the existing WHERE clause, is of the form:
**
**    (tab1.col1 = tab2.col2)
**
** where tab1 is the iSrc'th table in SrcList pSrc and tab2 is the 
** (iSrc+1)'th. Column col1 is column iColLeft of tab1, and col2 is
** column iColRight of tab2.
*/
static void addWhereTerm(
  Parse *pParse,                  /* Parsing context */
  SrcList *pSrc,                  /* List of tables in FROM clause */
  int iLeft,                      /* Index of first table to join in pSrc */
  int iColLeft,                   /* Index of column in first table */
  int iRight,                     /* Index of second table in pSrc */
  int iColRight,                  /* Index of column in second table */
  int isOuterJoin,                /* True if this is an OUTER join */
  Expr **ppWhere                  /* IN/OUT: The WHERE clause to add to */
){
  sqlite3 *db = pParse->db;
  Expr *pE1;
  Expr *pE2;
  Expr *pEq;

  assert( iLeft<iRight );
  assert( pSrc->nSrc>iRight );
  assert( pSrc->a[iLeft].pTab );
  assert( pSrc->a[iRight].pTab );

  pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iColLeft);
  pE2 = sqlite3CreateColumnExpr(db, pSrc, iRight, iColRight);

  pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2);
  if( pEq && isOuterJoin ){
    ExprSetProperty(pEq, EP_FromJoin);
    assert( !ExprHasProperty(pEq, EP_TokenOnly|EP_Reduced) );
    ExprSetVVAProperty(pEq, EP_NoReduce);
    pEq->iRightJoinTable = (i16)pE2->iTable;
  }
  *ppWhere = sqlite3ExprAnd(db, *ppWhere, pEq);
}

/*
** Set the EP_FromJoin property on all terms of the given expression.
** And set the Expr.iRightJoinTable to iTable for every term in the
** Set the EP_OuterON property on all terms of the given expression.
** And set the Expr.w.iJoin to iTable for every term in the
** expression.
**
** The EP_FromJoin property is used on terms of an expression to tell
** the LEFT OUTER JOIN processing logic that this term is part of the
** The EP_OuterON property is used on terms of an expression to tell
** the OUTER JOIN processing logic that this term is part of the
** join restriction specified in the ON or USING clause and not a part
** of the more general WHERE clause.  These terms are moved over to the
** WHERE clause during join processing but we need to remember that they
** originated in the ON or USING clause.
**
** The Expr.iRightJoinTable tells the WHERE clause processing that the
** expression depends on table iRightJoinTable even if that table is not
** The Expr.w.iJoin tells the WHERE clause processing that the
** expression depends on table w.iJoin even if that table is not
** explicitly mentioned in the expression.  That information is needed
** for cases like this:
**
**    SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.b AND t1.x=5
**
** The where clause needs to defer the handling of the t1.x=5
** term until after the t2 loop of the join.  In that way, a
** NULL t2 row will be inserted whenever t1.x!=5.  If we do not
** defer the handling of t1.x=5, it will be processed immediately
** after the t1 loop and rows with t1.x!=5 will never appear in
** the output, which is incorrect.
*/
static void setJoinExpr(Expr *p, int iTable){
void sqlite3SetJoinExpr(Expr *p, int iTable, u32 joinFlag){
  assert( joinFlag==EP_OuterON || joinFlag==EP_InnerON );
  while( p ){
    ExprSetProperty(p, EP_FromJoin);
    ExprSetProperty(p, joinFlag);
    assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
    ExprSetVVAProperty(p, EP_NoReduce);
    p->iRightJoinTable = (i16)iTable;
    if( p->op==TK_FUNCTION && p->x.pList ){
      int i;
      for(i=0; i<p->x.pList->nExpr; i++){
        setJoinExpr(p->x.pList->a[i].pExpr, iTable);
      }
    }
    setJoinExpr(p->pLeft, iTable);
    p->w.iJoin = iTable;
    if( p->op==TK_FUNCTION ){
      assert( ExprUseXList(p) );
      if( p->x.pList ){
        int i;
        for(i=0; i<p->x.pList->nExpr; i++){
          sqlite3SetJoinExpr(p->x.pList->a[i].pExpr, iTable, joinFlag);
        }
      }
    }
    sqlite3SetJoinExpr(p->pLeft, iTable, joinFlag);
    p = p->pRight;
  } 
}

/* Undo the work of setJoinExpr().  In the expression tree p, convert every
** term that is marked with EP_FromJoin and iRightJoinTable==iTable into
** an ordinary term that omits the EP_FromJoin mark.
/* Undo the work of sqlite3SetJoinExpr().  This is used when a LEFT JOIN
** is simplified into an ordinary JOIN, and when an ON expression is
** "pushed down" into the WHERE clause of a subquery.
**
** Convert every term that is marked with EP_OuterON and w.iJoin==iTable into
** an ordinary term that omits the EP_OuterON mark.  Or if iTable<0, then
** just clear every EP_OuterON and EP_InnerON mark from the expression tree.
**
** This happens when a LEFT JOIN is simplified into an ordinary JOIN.
** If nullable is true, that means that Expr p might evaluate to NULL even
** if it is a reference to a NOT NULL column.  This can happen, for example,
** if the table that p references is on the left side of a RIGHT JOIN.
** If nullable is true, then take care to not remove the EP_CanBeNull bit.
** See forum thread https://sqlite.org/forum/forumpost/b40696f50145d21c
*/
static void unsetJoinExpr(Expr *p, int iTable){
static void unsetJoinExpr(Expr *p, int iTable, int nullable){
  while( p ){
    if( ExprHasProperty(p, EP_FromJoin)
     && (iTable<0 || p->iRightJoinTable==iTable) ){
      ExprClearProperty(p, EP_FromJoin);
    if( iTable<0 || (ExprHasProperty(p, EP_OuterON) && p->w.iJoin==iTable) ){
      ExprClearProperty(p, EP_OuterON|EP_InnerON);
      if( iTable>=0 ) ExprSetProperty(p, EP_InnerON);
    }
    if( p->op==TK_COLUMN && p->iTable==iTable && !nullable ){
      ExprClearProperty(p, EP_CanBeNull);
    }
    if( p->op==TK_FUNCTION && p->x.pList ){
      int i;
      for(i=0; i<p->x.pList->nExpr; i++){
        unsetJoinExpr(p->x.pList->a[i].pExpr, iTable);
      }
    }
    unsetJoinExpr(p->pLeft, iTable);
    if( p->op==TK_FUNCTION ){
      assert( ExprUseXList(p) );
      if( p->x.pList ){
        int i;
        for(i=0; i<p->x.pList->nExpr; i++){
          unsetJoinExpr(p->x.pList->a[i].pExpr, iTable, nullable);
        }
      }
    }
    unsetJoinExpr(p->pLeft, iTable, nullable);
    p = p->pRight;
  } 
}

/*
** This routine processes the join information for a SELECT statement.
**
**   *  A NATURAL join is converted into a USING join.  After that, we
**      do not need to be concerned with NATURAL joins and we only have
**      think about USING joins.
**
** ON and USING clauses are converted into extra terms of the WHERE clause.
** NATURAL joins also create extra WHERE clause terms.
**   *  ON and USING clauses result in extra terms being added to the
**      WHERE clause to enforce the specified constraints.  The extra
**      WHERE clause terms will be tagged with EP_OuterON or
**      EP_InnerON so that we know that they originated in ON/USING.
**
** The terms of a FROM clause are contained in the Select.pSrc structure.
** The left most table is the first entry in Select.pSrc.  The right-most
** table is the last entry.  The join operator is held in the entry to
** the left.  Thus entry 0 contains the join operator for the join between
** the right.  Thus entry 1 contains the join operator for the join between
** entries 0 and 1.  Any ON or USING clauses associated with the join are
** also attached to the left entry.
** also attached to the right entry.
**
** This routine returns the number of errors encountered.
*/
static int sqliteProcessJoin(Parse *pParse, Select *p){
static int sqlite3ProcessJoin(Parse *pParse, Select *p){
  SrcList *pSrc;                  /* All tables in the FROM clause */
  int i, j;                       /* Loop counters */
  struct SrcList_item *pLeft;     /* Left table being joined */
  struct SrcList_item *pRight;    /* Right table being joined */
  SrcItem *pLeft;                 /* Left table being joined */
  SrcItem *pRight;                /* Right table being joined */

  pSrc = p->pSrc;
  pLeft = &pSrc->a[0];
  pRight = &pLeft[1];
  for(i=0; i<pSrc->nSrc-1; i++, pRight++, pLeft++){
    Table *pRightTab = pRight->pTab;
    int isOuter;
    u32 joinType;

    if( NEVER(pLeft->pTab==0 || pRightTab==0) ) continue;
    isOuter = (pRight->fg.jointype & JT_OUTER)!=0;
    joinType = (pRight->fg.jointype & JT_OUTER)!=0 ? EP_OuterON : EP_InnerON;

    /* When the NATURAL keyword is present, add WHERE clause terms for
    ** every column that the two tables have in common.
    /* If this is a NATURAL join, synthesize an approprate USING clause
    ** to specify which columns should be joined.
    */
    if( pRight->fg.jointype & JT_NATURAL ){
      IdList *pUsing = 0;
      if( pRight->pOn || pRight->pUsing ){
      if( pRight->fg.isUsing || pRight->u3.pOn ){
        sqlite3ErrorMsg(pParse, "a NATURAL join may not have "
           "an ON or USING clause", 0);
        return 1;
      }
      for(j=0; j<pRightTab->nCol; j++){
        char *zName;   /* Name of column in the right table */
        int iLeft;     /* Matching left table */
        int iLeftCol;  /* Matching column in the left table */

        if( IsHiddenColumn(&pRightTab->aCol[j]) ) continue;
        zName = pRightTab->aCol[j].zName;
        if( tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol) ){
          addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, j,
                       isOuter, &p->pWhere);
        }
      }
    }

        zName = pRightTab->aCol[j].zCnName;
        if( tableAndColumnIndex(pSrc, 0, i, zName, 0, 0, 1) ){
          pUsing = sqlite3IdListAppend(pParse, pUsing, 0);
          if( pUsing ){
            assert( pUsing->nId>0 );
            assert( pUsing->a[pUsing->nId-1].zName==0 );
            pUsing->a[pUsing->nId-1].zName = sqlite3DbStrDup(pParse->db, zName);
          }
        }
      }
      if( pUsing ){
    /* Disallow both ON and USING clauses in the same join
    */
    if( pRight->pOn && pRight->pUsing ){
        pRight->fg.isUsing = 1;
      sqlite3ErrorMsg(pParse, "cannot have both ON and USING "
        "clauses in the same join");
      return 1;
    }

        pRight->fg.isSynthUsing = 1;
        pRight->u3.pUsing = pUsing;
      }
      if( pParse->nErr ) return 1;
    /* Add the ON clause to the end of the WHERE clause, connected by
    ** an AND operator.
    */
    if( pRight->pOn ){
      if( isOuter ) setJoinExpr(pRight->pOn, pRight->iCursor);
      p->pWhere = sqlite3ExprAnd(pParse->db, p->pWhere, pRight->pOn);
      pRight->pOn = 0;
    }

    /* Create extra terms on the WHERE clause for each column named
    ** in the USING clause.  Example: If the two tables to be joined are 
    ** A and B and the USING clause names X, Y, and Z, then add this
    ** to the WHERE clause:    A.X=B.X AND A.Y=B.Y AND A.Z=B.Z
    ** Report an error if any column mentioned in the USING clause is
    ** not contained in both tables to be joined.
    */
    if( pRight->pUsing ){
      IdList *pList = pRight->pUsing;
    if( pRight->fg.isUsing ){
      IdList *pList = pRight->u3.pUsing;
      sqlite3 *db = pParse->db;
      assert( pList!=0 );
      for(j=0; j<pList->nId; j++){
        char *zName;     /* Name of the term in the USING clause */
        int iLeft;       /* Table on the left with matching column name */
        int iLeftCol;    /* Column number of matching column on the left */
        int iRightCol;   /* Column number of matching column on the right */
        Expr *pE1;       /* Reference to the column on the LEFT of the join */
        Expr *pE2;       /* Reference to the column on the RIGHT of the join */
        Expr *pEq;       /* Equality constraint.  pE1 == pE2 */

        zName = pList->a[j].zName;
        iRightCol = columnIndex(pRightTab, zName);
        iRightCol = sqlite3ColumnIndex(pRightTab, zName);
        if( iRightCol<0
         || !tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol)
         || tableAndColumnIndex(pSrc, 0, i, zName, &iLeft, &iLeftCol,
                                pRight->fg.isSynthUsing)==0
        ){
          sqlite3ErrorMsg(pParse, "cannot join using column %s - column "
            "not present in both tables", zName);
          return 1;
        }
        addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, iRightCol,
                     isOuter, &p->pWhere);
        pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iLeftCol);
        sqlite3SrcItemColumnUsed(&pSrc->a[iLeft], iLeftCol);
        if( (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){
          /* This branch runs if the query contains one or more RIGHT or FULL
          ** JOINs.  If only a single table on the left side of this join
          ** contains the zName column, then this branch is a no-op.
          ** But if there are two or more tables on the left side
          ** of the join, construct a coalesce() function that gathers all
          ** such tables.  Raise an error if more than one of those references
          ** to zName is not also within a prior USING clause.
          **
          ** We really ought to raise an error if there are two or more
          ** non-USING references to zName on the left of an INNER or LEFT
          ** JOIN.  But older versions of SQLite do not do that, so we avoid
          ** adding a new error so as to not break legacy applications.
          */
          ExprList *pFuncArgs = 0;   /* Arguments to the coalesce() */
          static const Token tkCoalesce = { "coalesce", 8 };
          while( tableAndColumnIndex(pSrc, iLeft+1, i, zName, &iLeft, &iLeftCol,
                                     pRight->fg.isSynthUsing)!=0 ){
            if( pSrc->a[iLeft].fg.isUsing==0
             || sqlite3IdListIndex(pSrc->a[iLeft].u3.pUsing, zName)<0
            ){
              sqlite3ErrorMsg(pParse, "ambiguous reference to %s in USING()",
                              zName);
              break;
            }
            pFuncArgs = sqlite3ExprListAppend(pParse, pFuncArgs, pE1);
            pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iLeftCol);
            sqlite3SrcItemColumnUsed(&pSrc->a[iLeft], iLeftCol);
          }
          if( pFuncArgs ){
            pFuncArgs = sqlite3ExprListAppend(pParse, pFuncArgs, pE1);
            pE1 = sqlite3ExprFunction(pParse, pFuncArgs, &tkCoalesce, 0);
          }
        }
        pE2 = sqlite3CreateColumnExpr(db, pSrc, i+1, iRightCol);
        sqlite3SrcItemColumnUsed(pRight, iRightCol);
        pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2);
        assert( pE2!=0 || pEq==0 );
        if( pEq ){
          ExprSetProperty(pEq, joinType);
          assert( !ExprHasProperty(pEq, EP_TokenOnly|EP_Reduced) );
          ExprSetVVAProperty(pEq, EP_NoReduce);
          pEq->w.iJoin = pE2->iTable;
        }
        p->pWhere = sqlite3ExprAnd(pParse, p->pWhere, pEq);
      }
    }

    /* Add the ON clause to the end of the WHERE clause, connected by
    ** an AND operator.
    */
    else if( pRight->u3.pOn ){
      sqlite3SetJoinExpr(pRight->u3.pOn, pRight->iCursor, joinType);
      p->pWhere = sqlite3ExprAnd(pParse, p->pWhere, pRight->u3.pOn);
      pRight->u3.pOn = 0;
      pRight->fg.isOn = 1;
    }
  }
  return 0;
}

/*
** An instance of this object holds information (beyond pParse and pSelect)
** needed to load the next result row that is to be added to the sorter.
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
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







+
+
+
+










-
+







  **       the SQLITE_ENABLE_SORTER_REFERENCE optimization, or due to the
  **       SQLITE_ECEL_OMITREF optimization, or due to the 
  **       SortCtx.pDeferredRowLoad optimiation.  In any of these cases
  **       regOrigData is 0 to prevent this routine from trying to copy
  **       values that might not yet exist.
  */
  assert( nData==1 || regData==regOrigData || regOrigData==0 );

#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
  pSort->addrPush = sqlite3VdbeCurrentAddr(v);
#endif

  if( nPrefixReg ){
    assert( nPrefixReg==nExpr+bSeq );
    regBase = regData - nPrefixReg;
  }else{
    regBase = pParse->nMem + 1;
    pParse->nMem += nBase;
  }
  assert( pSelect->iOffset==0 || pSelect->iLimit!=0 );
  iLimit = pSelect->iOffset ? pSelect->iOffset+1 : pSelect->iLimit;
  pSort->labelDone = sqlite3VdbeMakeLabel(v);
  pSort->labelDone = sqlite3VdbeMakeLabel(pParse);
  sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, regOrigData,
                          SQLITE_ECEL_DUP | (regOrigData? SQLITE_ECEL_REF : 0));
  if( bSeq ){
    sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr);
  }
  if( nPrefixReg==0 && nData>0 ){
    sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+bSeq, nData);
659
660
661
662
663
664
665
666

667
668
669
670

671
672
673

674
675
676
677
678
679
680
766
767
768
769
770
771
772

773
774
775
776
777
778
779
780

781
782
783
784
785
786
787
788







-
+




+


-
+







    }
    VdbeCoverage(v);
    sqlite3VdbeAddOp3(v, OP_Compare, regPrevKey, regBase, pSort->nOBSat);
    pOp = sqlite3VdbeGetOp(v, pSort->addrSortIndex);
    if( pParse->db->mallocFailed ) return;
    pOp->p2 = nKey + nData;
    pKI = pOp->p4.pKeyInfo;
    memset(pKI->aSortOrder, 0, pKI->nKeyField); /* Makes OP_Jump testable */
    memset(pKI->aSortFlags, 0, pKI->nKeyField); /* Makes OP_Jump testable */
    sqlite3VdbeChangeP4(v, -1, (char*)pKI, P4_KEYINFO);
    testcase( pKI->nAllField > pKI->nKeyField+2 );
    pOp->p4.pKeyInfo = sqlite3KeyInfoFromExprList(pParse,pSort->pOrderBy,nOBSat,
                                           pKI->nAllField-pKI->nKeyField-1);
    pOp = 0; /* Ensure pOp not used after sqltie3VdbeAddOp3() */
    addrJmp = sqlite3VdbeCurrentAddr(v);
    sqlite3VdbeAddOp3(v, OP_Jump, addrJmp+1, 0, addrJmp+1); VdbeCoverage(v);
    pSort->labelBkOut = sqlite3VdbeMakeLabel(v);
    pSort->labelBkOut = sqlite3VdbeMakeLabel(pParse);
    pSort->regReturn = ++pParse->nMem;
    sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut);
    sqlite3VdbeAddOp1(v, OP_ResetSorter, pSort->iECursor);
    if( iLimit ){
      sqlite3VdbeAddOp2(v, OP_IfNot, iLimit, pSort->labelDone);
      VdbeCoverage(v);
    }
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
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
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
900
901
902
903
904


905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983




984
985
986
987






988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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







+
+
+

















-
-
-
-
+
+
+
+
+

+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+

+


+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



















-
+




















-
-
-
+
+
+
+
+
+
+




















+











-
+







  }
  sqlite3VdbeAddOp4Int(v, op, pSort->iECursor, regRecord,
                       regBase+nOBSat, nBase-nOBSat);
  if( iSkip ){
    sqlite3VdbeChangeP2(v, iSkip,
         pSort->labelOBLopt ? pSort->labelOBLopt : sqlite3VdbeCurrentAddr(v));
  }
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
  pSort->addrPushEnd = sqlite3VdbeCurrentAddr(v)-1;
#endif
}

/*
** Add code to implement the OFFSET
*/
static void codeOffset(
  Vdbe *v,          /* Generate code into this VM */
  int iOffset,      /* Register holding the offset counter */
  int iContinue     /* Jump here to skip the current record */
){
  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( pParse->nErr==0
   && (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 
** optimization should be used for. The sorter-reference optimization
** is used for SELECT queries like:
**
**   SELECT a, bigblob FROM t1 ORDER BY a LIMIT 10
**
** If the optimization is used for expression "bigblob", then instead of
** storing values read from that column in the sorter records, the PK of
** the row from table t1 is stored instead. Then, as records are extracted from
** the sorter to return to the user, the required value of bigblob is
** retrieved directly from table t1. If the values are very large, this 
** can be more efficient than storing them directly in the sorter records.
**
** The ExprList_item.bSorterRef flag is set for each expression in pEList 
** The ExprList_item.fg.bSorterRef flag is set for each expression in pEList 
** for which the sorter-reference optimization should be enabled. 
** Additionally, the pSort->aDefer[] array is populated with entries
** for all cursors required to evaluate all selected expressions. Finally.
** output variable (*ppExtra) is set to an expression list containing
** expressions for all extra PK values that should be stored in the
** sorter records.
*/
static void selectExprDefer(
  Parse *pParse,                  /* Leave any error here */
  SortCtx *pSort,                 /* Sorter context */
  ExprList *pEList,               /* Expressions destined for sorter */
  ExprList **ppExtra              /* Expressions to append to sorter record */
){
  int i;
  int nDefer = 0;
  ExprList *pExtra = 0;
  for(i=0; i<pEList->nExpr; i++){
    struct ExprList_item *pItem = &pEList->a[i];
    if( pItem->u.x.iOrderByCol==0 ){
      Expr *pExpr = pItem->pExpr;
      Table *pTab = pExpr->y.pTab;
      if( pExpr->op==TK_COLUMN && pExpr->iColumn>=0 && pTab && !IsVirtual(pTab)
       && (pTab->aCol[pExpr->iColumn].colFlags & COLFLAG_SORTERREF)
      Table *pTab;
      if( pExpr->op==TK_COLUMN
       && pExpr->iColumn>=0
       && ALWAYS( ExprUseYTab(pExpr) )
       && (pTab = pExpr->y.pTab)!=0
       && IsOrdinaryTable(pTab)
       && (pTab->aCol[pExpr->iColumn].colFlags & COLFLAG_SORTERREF)!=0
      ){
        int j;
        for(j=0; j<nDefer; j++){
          if( pSort->aDefer[j].iCsr==pExpr->iTable ) break;
        }
        if( j==nDefer ){
          if( nDefer==ArraySize(pSort->aDefer) ){
            continue;
          }else{
            int nKey = 1;
            int k;
            Index *pPk = 0;
            if( !HasRowid(pTab) ){
              pPk = sqlite3PrimaryKeyIndex(pTab);
              nKey = pPk->nKeyCol;
            }
            for(k=0; k<nKey; k++){
              Expr *pNew = sqlite3PExpr(pParse, TK_COLUMN, 0, 0);
              if( pNew ){
                pNew->iTable = pExpr->iTable;
                assert( ExprUseYTab(pNew) );
                pNew->y.pTab = pExpr->y.pTab;
                pNew->iColumn = pPk ? pPk->aiColumn[k] : -1;
                pExtra = sqlite3ExprListAppend(pParse, pExtra, pNew);
              }
            }
            pSort->aDefer[nDefer].pTab = pExpr->y.pTab;
            pSort->aDefer[nDefer].iCsr = pExpr->iTable;
            pSort->aDefer[nDefer].nKey = nKey;
            nDefer++;
          }
        }
        pItem->bSorterRef = 1;
        pItem->fg.bSorterRef = 1;
      }
    }
  }
  pSort->nDefer = (u8)nDefer;
  *ppExtra = pExtra;
}
#endif
912
913
914
915
916
917
918
919

920
921
922
923
924
925
926
1154
1155
1156
1157
1158
1159
1160

1161
1162
1163
1164
1165
1166
1167
1168







-
+







    pParse->nMem += nResultCol;
  }
  pDest->nSdst = nResultCol;
  regOrig = regResult = pDest->iSdst;
  if( srcTab>=0 ){
    for(i=0; i<nResultCol; i++){
      sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, regResult+i);
      VdbeComment((v, "%s", p->pEList->a[i].zName));
      VdbeComment((v, "%s", p->pEList->a[i].zEName));
    }
  }else if( eDest!=SRT_Exists ){
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
    ExprList *pExtra = 0;
#endif
    /* If the destination is an EXISTS(...) expression, the actual
    ** values returned by the SELECT are not required.
964
965
966
967
968
969
970
971

972
973
974
975
976
977
978
979
980
981
982
983
984
985


986
987
988
989
990
991
992
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







-
+













-
+
+








      /* Adjust nResultCol to account for columns that are omitted
      ** from the sorter by the optimizations in this branch */
      pEList = p->pEList;
      for(i=0; i<pEList->nExpr; i++){
        if( pEList->a[i].u.x.iOrderByCol>0
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
         || pEList->a[i].bSorterRef
         || pEList->a[i].fg.bSorterRef
#endif
        ){
          nResultCol--;
          regOrig = 0;
        }
      }

      testcase( regOrig );
      testcase( eDest==SRT_Set );
      testcase( eDest==SRT_Mem );
      testcase( eDest==SRT_Coroutine );
      testcase( eDest==SRT_Output );
      assert( eDest==SRT_Set || eDest==SRT_Mem 
           || eDest==SRT_Coroutine || eDest==SRT_Output );
           || eDest==SRT_Coroutine || eDest==SRT_Output
           || eDest==SRT_Upfrom );
    }
    sRowLoadInfo.regResult = regResult;
    sRowLoadInfo.ecelFlags = ecelFlags;
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
    sRowLoadInfo.pExtra = pExtra;
    sRowLoadInfo.regExtraResult = regResult + nResultCol;
    if( pExtra ) nResultCol += pExtra->nExpr;
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
1248
1249
1250
1251
1252
1253
1254

1255





1256




1257
1258







1259



































1260
1261
1262
1263
1264
1265
1266







-
+
-
-
-
-
-
+
-
-
-
-
+
+
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







  }

  /* 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;

        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
1125
1126
1127
1128
1129
1130
1131
























1132
1133
1134
1135
1136
1137
1138
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







        sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, r2);
        sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
        sqlite3ReleaseTempReg(pParse, r2);
      }
      sqlite3ReleaseTempRange(pParse, r1, nPrefixReg+1);
      break;
    }

    case SRT_Upfrom: {
      if( pSort ){
        pushOntoSorter(
            pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg);
      }else{
        int i2 = pDest->iSDParm2;
        int r1 = sqlite3GetTempReg(pParse);

        /* If the UPDATE FROM join is an aggregate that matches no rows, it
        ** might still be trying to return one row, because that is what
        ** aggregates do.  Don't record that empty row in the output table. */
        sqlite3VdbeAddOp2(v, OP_IsNull, regResult, iBreak); VdbeCoverage(v);

        sqlite3VdbeAddOp3(v, OP_MakeRecord,
                          regResult+(i2<0), nResultCol-(i2<0), r1);
        if( i2<0 ){
          sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, regResult);
        }else{
          sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, i2);
        }
      }
      break;
    }

#ifndef SQLITE_OMIT_SUBQUERY
    /* If we are creating a set for an "expr IN (SELECT ...)" construct,
    ** then there should be a single item on the stack.  Write this
    ** item into the set table with bogus data.
    */
    case SRT_Set: {
1149
1150
1151
1152
1153
1154
1155

1156
1157
1158
1159
1160
1161
1162
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383







+







        sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol, 
            r1, pDest->zAffSdst, nResultCol);
        sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol);
        sqlite3ReleaseTempReg(pParse, r1);
      }
      break;
    }


    /* If any row exist in the result set, record that fact and abort.
    */
    case SRT_Exists: {
      sqlite3VdbeAddOp2(v, OP_Integer, 1, iParm);
      /* The LIMIT clause will terminate the loop for us */
      break;
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
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







-
+







-
+









+


-
+







** Allocate a KeyInfo object sufficient for an index of N key columns and
** X extra columns.
*/
KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){
  int nExtra = (N+X)*(sizeof(CollSeq*)+1) - sizeof(CollSeq*);
  KeyInfo *p = sqlite3DbMallocRawNN(db, sizeof(KeyInfo) + nExtra);
  if( p ){
    p->aSortOrder = (u8*)&p->aColl[N+X];
    p->aSortFlags = (u8*)&p->aColl[N+X];
    p->nKeyField = (u16)N;
    p->nAllField = (u16)(N+X);
    p->enc = ENC(db);
    p->db = db;
    p->nRef = 1;
    memset(&p[1], 0, nExtra);
  }else{
    sqlite3OomFault(db);
    return (KeyInfo*)sqlite3OomFault(db);
  }
  return p;
}

/*
** Deallocate a KeyInfo object
*/
void sqlite3KeyInfoUnref(KeyInfo *p){
  if( p ){
    assert( p->db!=0 );
    assert( p->nRef>0 );
    p->nRef--;
    if( p->nRef==0 ) sqlite3DbFreeNN(p->db, p);
    if( p->nRef==0 ) sqlite3DbNNFreeNN(p->db, p);
  }
}

/*
** Make a new pointer to a KeyInfo object
*/
KeyInfo *sqlite3KeyInfoRef(KeyInfo *p){
1347
1348
1349
1350
1351
1352
1353
1354

1355
1356
1357
1358
1359
1360
1361
1362
1363

1364
1365
1366
1367
1368
1369
1370
1569
1570
1571
1572
1573
1574
1575

1576
1577
1578
1579
1580
1581
1582
1583
1584

1585
1586
1587
1588
1589
1590
1591
1592







-
+








-
+








  nExpr = pList->nExpr;
  pInfo = sqlite3KeyInfoAlloc(db, nExpr-iStart, nExtra+1);
  if( pInfo ){
    assert( sqlite3KeyInfoIsWriteable(pInfo) );
    for(i=iStart, pItem=pList->a+iStart; i<nExpr; i++, pItem++){
      pInfo->aColl[i-iStart] = sqlite3ExprNNCollSeq(pParse, pItem->pExpr);
      pInfo->aSortOrder[i-iStart] = pItem->sortOrder;
      pInfo->aSortFlags[i-iStart] = pItem->fg.sortFlags;
    }
  }
  return pInfo;
}

/*
** Name of the connection operator, used for error messages.
*/
static const char *selectOpName(int id){
const char *sqlite3SelectOpName(int id){
  char *z;
  switch( id ){
    case TK_ALL:       z = "UNION ALL";   break;
    case TK_INTERSECT: z = "INTERSECT";   break;
    case TK_EXCEPT:    z = "EXCEPT";      break;
    default:           z = "UNION";       break;
  }
1413
1414
1415
1416
1417
1418
1419
1420

1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435










1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455



1456
1457
1458
1459




1460


1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474

1475
1476
1477
1478
1479
1480
1481



1482
1483
1484
1485

1486
1487
1488
1489
1490
1491
1492
1635
1636
1637
1638
1639
1640
1641

1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698

1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713

1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727

1728
1729
1730
1731
1732
1733
1734
1735







-
+















+
+
+
+
+
+
+
+
+
+




















+
+
+




+
+
+
+
-
+
+













-
+







+
+
+



-
+







  Select *p,        /* The SELECT statement */
  SortCtx *pSort,   /* Information on the ORDER BY clause */
  int nColumn,      /* Number of columns of data */
  SelectDest *pDest /* Write the sorted results here */
){
  Vdbe *v = pParse->pVdbe;                     /* The prepared statement */
  int addrBreak = pSort->labelDone;            /* Jump here to exit loop */
  int addrContinue = sqlite3VdbeMakeLabel(v);  /* Jump here for next cycle */
  int addrContinue = sqlite3VdbeMakeLabel(pParse);/* Jump here for next cycle */
  int addr;                       /* Top of output loop. Jump for Next. */
  int addrOnce = 0;
  int iTab;
  ExprList *pOrderBy = pSort->pOrderBy;
  int eDest = pDest->eDest;
  int iParm = pDest->iSDParm;
  int regRow;
  int regRowid;
  int iCol;
  int nKey;                       /* Number of key columns in sorter record */
  int iSortTab;                   /* Sorter cursor to read from */
  int i;
  int bSeq;                       /* True if sorter record includes seq. no. */
  int nRefKey = 0;
  struct ExprList_item *aOutEx = p->pEList->a;
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
  int addrExplain;                /* Address of OP_Explain instruction */
#endif

  ExplainQueryPlan2(addrExplain, (pParse, 0, 
        "USE TEMP B-TREE FOR %sORDER BY", pSort->nOBSat>0?"RIGHT PART OF ":"")
  );
  sqlite3VdbeScanStatusRange(v, addrExplain,pSort->addrPush,pSort->addrPushEnd);
  sqlite3VdbeScanStatusCounters(v, addrExplain, addrExplain, pSort->addrPush);


  assert( addrBreak<0 );
  if( pSort->labelBkOut ){
    sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut);
    sqlite3VdbeGoto(v, addrBreak);
    sqlite3VdbeResolveLabel(v, pSort->labelBkOut);
  }

#ifdef SQLITE_ENABLE_SORTER_REFERENCES
  /* Open any cursors needed for sorter-reference expressions */
  for(i=0; i<pSort->nDefer; i++){
    Table *pTab = pSort->aDefer[i].pTab;
    int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
    sqlite3OpenTable(pParse, pSort->aDefer[i].iCsr, iDb, pTab, OP_OpenRead);
    nRefKey = MAX(nRefKey, pSort->aDefer[i].nKey);
  }
#endif

  iTab = pSort->iECursor;
  if( eDest==SRT_Output || eDest==SRT_Coroutine || eDest==SRT_Mem ){
    if( eDest==SRT_Mem && p->iOffset ){
      sqlite3VdbeAddOp2(v, OP_Null, 0, pDest->iSdst);
    }
    regRowid = 0;
    regRow = pDest->iSdst;
  }else{
    regRowid = sqlite3GetTempReg(pParse);
    if( eDest==SRT_EphemTab || eDest==SRT_Table ){
      regRow = sqlite3GetTempReg(pParse);
      nColumn = 0;
    }else{
    regRow = sqlite3GetTempRange(pParse, nColumn);
      regRow = sqlite3GetTempRange(pParse, nColumn);
    }
  }
  nKey = pOrderBy->nExpr - pSort->nOBSat;
  if( pSort->sortFlags & SORTFLAG_UseSorter ){
    int regSortOut = ++pParse->nMem;
    iSortTab = pParse->nTab++;
    if( pSort->labelBkOut ){
      addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
    }
    sqlite3VdbeAddOp3(v, OP_OpenPseudo, iSortTab, regSortOut, 
        nKey+1+nColumn+nRefKey);
    if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce);
    addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak);
    VdbeCoverage(v);
    codeOffset(v, p->iOffset, addrContinue);
    assert( p->iLimit==0 && p->iOffset==0 );
    sqlite3VdbeAddOp3(v, OP_SorterData, iTab, regSortOut, iSortTab);
    bSeq = 0;
  }else{
    addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); VdbeCoverage(v);
    codeOffset(v, p->iOffset, addrContinue);
    iSortTab = iTab;
    bSeq = 1;
    if( p->iOffset>0 ){
      sqlite3VdbeAddOp2(v, OP_AddImm, p->iLimit, -1);
    }
  }
  for(i=0, iCol=nKey+bSeq-1; i<nColumn; i++){
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
    if( aOutEx[i].bSorterRef ) continue;
    if( aOutEx[i].fg.bSorterRef ) continue;
#endif
    if( aOutEx[i].u.x.iOrderByCol==0 ) iCol++;
  }
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
  if( pSort->nDefer ){
    int iKey = iCol+1;
    int regKey = sqlite3GetTempRange(pParse, nRefKey);
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
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557











1558
1559
1560
1561
1562
1563
1564
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







-
+











-
+


+



+


















+
+
+
+
+
+
+
+
+
+
+







      }
    }
    sqlite3ReleaseTempRange(pParse, regKey, nRefKey);
  }
#endif
  for(i=nColumn-1; i>=0; i--){
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
    if( aOutEx[i].bSorterRef ){
    if( aOutEx[i].fg.bSorterRef ){
      sqlite3ExprCode(pParse, aOutEx[i].pExpr, regRow+i);
    }else
#endif
    {
      int iRead;
      if( aOutEx[i].u.x.iOrderByCol ){
        iRead = aOutEx[i].u.x.iOrderByCol-1;
      }else{
        iRead = iCol--;
      }
      sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iRead, regRow+i);
      VdbeComment((v, "%s", aOutEx[i].zName?aOutEx[i].zName : aOutEx[i].zSpan));
      VdbeComment((v, "%s", aOutEx[i].zEName));
    }
  }
  sqlite3VdbeScanStatusRange(v, addrExplain, addrExplain, -1);
  switch( eDest ){
    case SRT_Table:
    case SRT_EphemTab: {
      sqlite3VdbeAddOp3(v, OP_Column, iSortTab, nKey+bSeq, regRow);
      sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, regRowid);
      sqlite3VdbeAddOp3(v, OP_Insert, iParm, regRow, regRowid);
      sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
      break;
    }
#ifndef SQLITE_OMIT_SUBQUERY
    case SRT_Set: {
      assert( nColumn==sqlite3Strlen30(pDest->zAffSdst) );
      sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, nColumn, regRowid,
                        pDest->zAffSdst, nColumn);
      sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, regRowid, regRow, nColumn);
      break;
    }
    case SRT_Mem: {
      /* The LIMIT clause will terminate the loop for us */
      break;
    }
#endif
    case SRT_Upfrom: {
      int i2 = pDest->iSDParm2;
      int r1 = sqlite3GetTempReg(pParse);
      sqlite3VdbeAddOp3(v, OP_MakeRecord,regRow+(i2<0),nColumn-(i2<0),r1);
      if( i2<0 ){
        sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, regRow);
      }else{
        sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regRow, i2);
      }
      break;
    }
    default: {
      assert( eDest==SRT_Output || eDest==SRT_Coroutine ); 
      testcase( eDest==SRT_Output );
      testcase( eDest==SRT_Coroutine );
      if( eDest==SRT_Output ){
        sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iSdst, nColumn);
      }else{
1579
1580
1581
1582
1583
1584
1585

1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850



1851
1852
1853
1854
1855
1856
1857







+








-
-
-







  */
  sqlite3VdbeResolveLabel(v, addrContinue);
  if( pSort->sortFlags & SORTFLAG_UseSorter ){
    sqlite3VdbeAddOp2(v, OP_SorterNext, iTab, addr); VdbeCoverage(v);
  }else{
    sqlite3VdbeAddOp2(v, OP_Next, iTab, addr); VdbeCoverage(v);
  }
  sqlite3VdbeScanStatusRange(v, addrExplain, sqlite3VdbeCurrentAddr(v)-1, -1);
  if( pSort->regReturn ) sqlite3VdbeAddOp1(v, OP_Return, pSort->regReturn);
  sqlite3VdbeResolveLabel(v, addrBreak);
}

/*
** Return a pointer to a string containing the 'declaration type' of the
** expression pExpr. The string may be treated as static by the caller.
**
** Also try to estimate the size of the returned value and return that
** result in *pEstWidth.
**
** The declaration type is the exact datatype definition extracted from the
** original CREATE TABLE statement if the expression is a column. The
** declaration type for a ROWID field is INTEGER. Exactly when an expression
** is considered a column can be complex in the presence of subqueries. The
** result-set expression in all of the following SELECT statements is 
** considered a column by this function.
**
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1887
1888
1889
1890
1891
1892
1893


1894
1895
1896
1897
1898
1899
1900







-
-







  char const *zOrigDb = 0;
  char const *zOrigTab = 0;
  char const *zOrigCol = 0;
#endif

  assert( pExpr!=0 );
  assert( pNC->pSrcList!=0 );
  assert( pExpr->op!=TK_AGG_COLUMN );  /* This routine runes before aggregates
                                       ** are processed */
  switch( pExpr->op ){
    case TK_COLUMN: {
      /* The expression is a column. Locate the table the column is being
      ** extracted from in NameContext.pSrcList. This table may be real
      ** database table or a subquery.
      */
      Table *pTab = 0;            /* Table structure column is extracted from */
1676
1677
1678
1679
1680
1681
1682
1683

1684
1685
1686
1687
1688
1689







1690
1691
1692
1693
1694
1695
1696
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







-
+





-
+
+
+
+
+
+
+







        ** This is not a problem, as the column type of "t1.col" is never
        ** used. When columnType() is called on the expression 
        ** "(SELECT t1.col)", the correct type is returned (see the TK_SELECT
        ** branch below.  */
        break;
      }

      assert( pTab && pExpr->y.pTab==pTab );
      assert( pTab && ExprUseYTab(pExpr) && pExpr->y.pTab==pTab );
      if( pS ){
        /* The "table" is actually a sub-select or a view in the FROM clause
        ** of the SELECT statement. Return the declaration type and origin
        ** data for the result-set column of the sub-select.
        */
        if( iCol>=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;
1704
1705
1706
1707
1708
1709
1710
1711

1712
1713
1714
1715
1716
1717
1718
1962
1963
1964
1965
1966
1967
1968

1969
1970
1971
1972
1973
1974
1975
1976







-
+







#ifdef SQLITE_ENABLE_COLUMN_METADATA
        if( iCol<0 ) iCol = pTab->iPKey;
        assert( iCol==XN_ROWID || (iCol>=0 && iCol<pTab->nCol) );
        if( iCol<0 ){
          zType = "INTEGER";
          zOrigCol = "rowid";
        }else{
          zOrigCol = pTab->aCol[iCol].zName;
          zOrigCol = pTab->aCol[iCol].zCnName;
          zType = sqlite3ColumnType(&pTab->aCol[iCol],0);
        }
        zOrigTab = pTab->zName;
        if( pNC->pParse && pTab->pSchema ){
          int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema);
          zOrigDb = pNC->pParse->db->aDb[iDb].zDbSName;
        }
1730
1731
1732
1733
1734
1735
1736



1737
1738


1739
1740
1741
1742
1743
1744
1745
1746
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997


1998
1999

2000
2001
2002
2003
2004
2005
2006







+
+
+
-
-
+
+
-







#ifndef SQLITE_OMIT_SUBQUERY
    case TK_SELECT: {
      /* The expression is a sub-select. Return the declaration type and
      ** origin info for the single column in the result set of the SELECT
      ** statement.
      */
      NameContext sNC;
      Select *pS;
      Expr *p;
      assert( ExprUseXSelect(pExpr) );
      Select *pS = pExpr->x.pSelect;
      Expr *p = pS->pEList->a[0].pExpr;
      pS = pExpr->x.pSelect;
      p = pS->pEList->a[0].pExpr;
      assert( ExprHasProperty(pExpr, EP_xIsSelect) );
      sNC.pSrcList = pS->pSrc;
      sNC.pNext = pNC;
      sNC.pParse = pNC->pParse;
      zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol); 
      break;
    }
#endif
1824
1825
1826
1827
1828
1829
1830
1831

1832
1833
1834
1835
1836
1837
1838
2084
2085
2086
2087
2088
2089
2090

2091
2092
2093
2094
2095
2096
2097
2098







-
+







**                              result column name is just the table column
**                              name: COLUMN.  Otherwise use zSpan.
**
**    full=ON, short=ANY:       If the result refers directly to a table column,
**                              then the result column name with the table name
**                              prefix, ex: TABLE.COLUMN.  Otherwise use zSpan.
*/
static void generateColumnNames(
void sqlite3GenerateColumnNames(
  Parse *pParse,      /* Parser context */
  Select *pSelect     /* Generate column names for this SELECT statement */
){
  Vdbe *v = pParse->pVdbe;
  int i;
  Table *pTab;
  SrcList *pTabList;
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
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







-
+













-
-
+
+
+

-
+











-
+









-
+







    return;
  }
#endif

  if( pParse->colNamesSet ) return;
  /* Column names are determined by the left-most term of a compound select */
  while( pSelect->pPrior ) pSelect = pSelect->pPrior;
  SELECTTRACE(1,pParse,pSelect,("generating column names\n"));
  TREETRACE(0x80,pParse,pSelect,("generating column names\n"));
  pTabList = pSelect->pSrc;
  pEList = pSelect->pEList;
  assert( v!=0 );
  assert( pTabList!=0 );
  pParse->colNamesSet = 1;
  fullName = (db->flags & SQLITE_FullColNames)!=0;
  srcName = (db->flags & SQLITE_ShortColNames)!=0 || fullName;
  sqlite3VdbeSetNumCols(v, pEList->nExpr);
  for(i=0; i<pEList->nExpr; i++){
    Expr *p = pEList->a[i].pExpr;

    assert( p!=0 );
    assert( p->op!=TK_AGG_COLUMN );  /* Agg processing has not run yet */
    assert( p->op!=TK_COLUMN || p->y.pTab!=0 ); /* Covering idx not yet coded */
    if( pEList->a[i].zName ){
    assert( p->op!=TK_COLUMN
        || (ExprUseYTab(p) && p->y.pTab!=0) ); /* Covering idx not yet coded */
    if( pEList->a[i].zEName && pEList->a[i].fg.eEName==ENAME_NAME ){
      /* An AS clause always takes first priority */
      char *zName = pEList->a[i].zName;
      char *zName = pEList->a[i].zEName;
      sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT);
    }else if( srcName && p->op==TK_COLUMN ){
      char *zCol;
      int iCol = p->iColumn;
      pTab = p->y.pTab;
      assert( pTab!=0 );
      if( iCol<0 ) iCol = pTab->iPKey;
      assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
      if( iCol<0 ){
        zCol = "rowid";
      }else{
        zCol = pTab->aCol[iCol].zName;
        zCol = pTab->aCol[iCol].zCnName;
      }
      if( fullName ){
        char *zName = 0;
        zName = sqlite3MPrintf(db, "%s.%s", pTab->zName, zCol);
        sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_DYNAMIC);
      }else{
        sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, SQLITE_TRANSIENT);
      }
    }else{
      const char *z = pEList->a[i].zSpan;
      const char *z = pEList->a[i].zEName;
      z = z==0 ? sqlite3MPrintf(db, "column%d", i+1) : sqlite3DbStrDup(db, z);
      sqlite3VdbeSetColName(v, i, COLNAME_NAME, z, SQLITE_DYNAMIC);
    }
  }
  generateColumnTypes(pParse, pTabList, pEList);
}

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
1984
1985
1986
1987
1988
1989




1990
1991
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
2017
2018
2019
2020
2021
2022





2023
2024

2025
2026


2027
2028
2029
2030
2031





2032
2033
2034
2035
2036
2037

2038
2039

2040
2041
2042
2043


2044


2045
2046
2047
2048
2049
2050


2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
















2062
2063


2064


























2065
2066
2067



2068
2069
2070
2071
2072
2073
2074
2075
2076
2077

2078
2079
2080
2081
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
2175
2176
2177
2178
2179
2180
2181

2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
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

2234

2235
2236
2237
2238
2239
2240

2241
2242
2243

2244
2245
2246
2247
2248
2249
2250
2251
2252
2253

2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265



2266
2267
2268
2269
2270
2271
2272
2273
2274

2275
2276
2277
2278
2279

2280
2281

2282
2283
2284
2285
2286

2287
2288
2289
2290
2291
2292





2293
2294
2295
2296
2297

2298
2299


2300
2301
2302




2303
2304
2305
2306
2307
2308
2309

2310
2311

2312
2313
2314
2315
2316
2317
2318

2319
2320
2321
2322
2323
2324
2325

2326
2327

2328
2329
2330

2331
2332







2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352

2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379


2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391

2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403

2404
2405
2406
2407



2408
2409
2410
2411

2412
2413
2414
2415
2416
2417
2418
2419







-
+















+






-
+








-
+
+
+


-
+


-
-
+
+



-
-
+
+
+
+


-
+
-

-
+





-
+


-
+









-
+
+
+
+






+
+
-
-
-
+
+
+
+
+
+
+
+

-
+




-
+

-
+




-
+





-
-
-
-
-
+
+
+
+
+
-

+
-
-
+
+

-
-
-
-
+
+
+
+
+


-


-
+


+



-
+
+

+
+


-


-
+
+

-


-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+
+









-
+








+


-




-
-
-




-
+







** The only guarantee that SQLite makes about column names is that if the
** column has an AS clause assigning it a name, that will be the name used.
** That is the only documented guarantee.  However, countless applications
** developed over the years have made baseless assumptions about column names
** and will break if those assumptions changes.  Hence, use extreme caution
** when modifying this routine to avoid breaking legacy.
**
** See Also: generateColumnNames()
** See Also: sqlite3GenerateColumnNames()
*/
int sqlite3ColumnsFromExprList(
  Parse *pParse,          /* Parsing context */
  ExprList *pEList,       /* Expr list from which to derive column names */
  i16 *pnCol,             /* Write the number of columns here */
  Column **paCol          /* Write the new column list here */
){
  sqlite3 *db = pParse->db;   /* Database connection */
  int i, j;                   /* Loop counters */
  u32 cnt;                    /* Index added to make the name unique */
  Column *aCol, *pCol;        /* For looping over result columns */
  int nCol;                   /* Number of columns in the result set */
  char *zName;                /* Column name */
  int nName;                  /* Size of name in zName[] */
  Hash ht;                    /* Hash table of column names */
  Table *pTab;

  sqlite3HashInit(&ht);
  if( pEList ){
    nCol = pEList->nExpr;
    aCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol);
    testcase( aCol==0 );
    if( nCol>32767 ) nCol = 32767;
    if( NEVER(nCol>32767) ) nCol = 32767;
  }else{
    nCol = 0;
    aCol = 0;
  }
  assert( nCol==(i16)nCol );
  *pnCol = nCol;
  *paCol = aCol;

  for(i=0, pCol=aCol; i<nCol && !db->mallocFailed; i++, pCol++){
  for(i=0, pCol=aCol; i<nCol && !pParse->nErr; i++, pCol++){
    struct ExprList_item *pX = &pEList->a[i];
    struct ExprList_item *pCollide;
    /* Get an appropriate name for the column
    */
    if( (zName = pEList->a[i].zName)!=0 ){
    if( (zName = pX->zEName)!=0 && pX->fg.eEName==ENAME_NAME ){
      /* If the column contains an "AS <name>" phrase, use <name> as the name */
    }else{
      Expr *pColExpr = sqlite3ExprSkipCollate(pEList->a[i].pExpr);
      while( pColExpr->op==TK_DOT ){
      Expr *pColExpr = sqlite3ExprSkipCollateAndLikely(pX->pExpr);
      while( ALWAYS(pColExpr!=0) && pColExpr->op==TK_DOT ){
        pColExpr = pColExpr->pRight;
        assert( pColExpr!=0 );
      }
      assert( pColExpr->op!=TK_AGG_COLUMN );
      if( pColExpr->op==TK_COLUMN ){
      if( pColExpr->op==TK_COLUMN
       && ALWAYS( ExprUseYTab(pColExpr) )
       && ALWAYS( pColExpr->y.pTab!=0 )
      ){
        /* For columns use the column name name */
        int iCol = pColExpr->iColumn;
        Table *pTab = pColExpr->y.pTab;
        pTab = pColExpr->y.pTab;
        assert( pTab!=0 );
        if( iCol<0 ) iCol = pTab->iPKey;
        zName = iCol>=0 ? pTab->aCol[iCol].zName : "rowid";
        zName = iCol>=0 ? pTab->aCol[iCol].zCnName : "rowid";
      }else if( pColExpr->op==TK_ID ){
        assert( !ExprHasProperty(pColExpr, EP_IntValue) );
        zName = pColExpr->u.zToken;
      }else{
        /* Use the original text of the column expression as its name */
        zName = pEList->a[i].zSpan;
        assert( zName==pX->zEName );  /* pointer comparison intended */
      }
    }
    if( zName ){
    if( zName && !sqlite3IsTrueOrFalse(zName) ){
      zName = sqlite3DbStrDup(db, zName);
    }else{
      zName = sqlite3MPrintf(db,"column%d",i+1);
    }

    /* Make sure the column name is unique.  If the name is not unique,
    ** append an integer to the name so that it becomes unique.
    */
    cnt = 0;
    while( zName && sqlite3HashFind(&ht, zName)!=0 ){
    while( zName && (pCollide = sqlite3HashFind(&ht, zName))!=0 ){
      if( pCollide->fg.bUsingTerm ){
        pCol->colFlags |= COLFLAG_NOEXPAND;
      }
      nName = sqlite3Strlen30(zName);
      if( nName>0 ){
        for(j=nName-1; j>0 && sqlite3Isdigit(zName[j]); j--){}
        if( zName[j]==':' ) nName = j;
      }
      zName = sqlite3MPrintf(db, "%.*z:%u", nName, zName, ++cnt);
      sqlite3ProgressCheck(pParse);
      if( cnt>3 ){
      if( cnt>3 ) sqlite3FastRandomness(&db->sPrng, sizeof(cnt), &cnt);
    }
    pCol->zName = zName;
        sqlite3FastRandomness(&db->sPrng, sizeof(cnt), &cnt);
      }
    }
    pCol->zCnName = zName;
    pCol->hName = sqlite3StrIHash(zName);
    if( pX->fg.bNoExpand ){
      pCol->colFlags |= COLFLAG_NOEXPAND;
    }
    sqlite3ColumnPropertiesFromName(0, pCol);
    if( zName && sqlite3HashInsert(&ht, zName, pCol)==pCol ){
    if( zName && sqlite3HashInsert(&ht, zName, pX)==pX ){
      sqlite3OomFault(db);
    }
  }
  sqlite3HashClear(&ht);
  if( db->mallocFailed ){
  if( pParse->nErr ){
    for(j=0; j<i; j++){
      sqlite3DbFree(db, aCol[j].zName);
      sqlite3DbFree(db, aCol[j].zCnName);
    }
    sqlite3DbFree(db, aCol);
    *paCol = 0;
    *pnCol = 0;
    return SQLITE_NOMEM_BKPT;
    return pParse->rc;
  }
  return SQLITE_OK;
}

/*
** Add type and collation information to a column list based on
** a SELECT statement.
** 
** The column list presumably came from selectColumnNamesFromExprList().
** The column list has only names, not types or collations.  This
** pTab is a transient Table object that represents a subquery of some
** kind (maybe a parenthesized subquery in the FROM clause of a larger
** query, or a VIEW, or a CTE).  This routine computes type information
** for that Table object based on the Select object that implements the
** subquery.  For the purposes of this routine, "type infomation" means:
** routine goes through and adds the types and collations.
**
**    *   The datatype name, as it might appear in a CREATE TABLE statement
** This routine requires that all identifiers in the SELECT
** statement be resolved.
**    *   Which collating sequence to use for the column
**    *   The affinity of the column
*/
void sqlite3SelectAddColumnTypeAndCollation(
  Parse *pParse,        /* Parsing contexts */
  Table *pTab,          /* Add column type information to this table */
  Select *pSelect       /* SELECT used to determine types and collations */
void sqlite3SubqueryColumnTypes(
  Parse *pParse,      /* Parsing contexts */
  Table *pTab,        /* Add column type information to this table */
  Select *pSelect,    /* SELECT used to determine types and collations */
  char aff            /* Default affinity. */
){
  sqlite3 *db = pParse->db;
  NameContext sNC;
  Column *pCol;
  CollSeq *pColl;
  int i;
  int i,j;
  Expr *p;
  struct ExprList_item *a;
  NameContext sNC;

  assert( pSelect!=0 );
  assert( (pSelect->selFlags & SF_Resolved)!=0 );
  assert( pTab->nCol==pSelect->pEList->nExpr || db->mallocFailed );
  assert( pTab->nCol==pSelect->pEList->nExpr || pParse->nErr>0 );
  assert( aff==SQLITE_AFF_NONE || aff==SQLITE_AFF_BLOB );
  if( db->mallocFailed ) return;
  while( pSelect->pPrior ) pSelect = pSelect->pPrior;
  a = pSelect->pEList->a;
  memset(&sNC, 0, sizeof(sNC));
  sNC.pSrcList = pSelect->pSrc;
  a = pSelect->pEList->a;
  for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
    const char *zType;
    int n, m;
    i64 n;
    pTab->tabFlags |= (pCol->colFlags & COLFLAG_NOINSERT);
    p = a[i].pExpr;
    zType = columnType(&sNC, p, 0, 0, 0);
    /* pCol->szEst = ... // Column size est for SELECT tables never used */
    pCol->affinity = sqlite3ExprAffinity(p);
    if( zType ){
      m = sqlite3Strlen30(zType);
      n = sqlite3Strlen30(pCol->zName);
      pCol->zName = sqlite3DbReallocOrFree(db, pCol->zName, n+m+2);
      if( pCol->zName ){
        memcpy(&pCol->zName[n+1], zType, m+1);
        pCol->colFlags |= COLFLAG_HASTYPE;
    if( pCol->affinity<=SQLITE_AFF_NONE ){
      pCol->affinity = aff;
    }else if( pCol->affinity>=SQLITE_AFF_NUMERIC && p->op==TK_CAST ){
      pCol->affinity = SQLITE_AFF_FLEXNUM;
    }
    if( pCol->affinity>=SQLITE_AFF_TEXT && pSelect->pNext ){
      int m = 0;
      Select *pS2;
      for(m=0, pS2=pSelect->pNext; pS2; pS2=pS2->pNext){
        m |= sqlite3ExprDataType(pS2->pEList->a[i].pExpr);
      }
      if( pCol->affinity==SQLITE_AFF_TEXT && (m&0x01)!=0 ){
        pCol->affinity = SQLITE_AFF_BLOB;
      }else
      if( pCol->affinity>=SQLITE_AFF_NUMERIC && (m&0x02)!=0 ){
        pCol->affinity = SQLITE_AFF_BLOB;
      }
    }
    zType = columnType(&sNC, p, 0, 0, 0);
    if( zType==0 || pCol->affinity!=sqlite3AffinityType(zType, 0) ){
    if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_BLOB;
      if( pCol->affinity==SQLITE_AFF_NUMERIC
       || pCol->affinity==SQLITE_AFF_FLEXNUM
      ){
        zType = "NUM";
      }else{
        zType = 0;
        for(j=1; j<SQLITE_N_STDTYPE; j++){
          if( sqlite3StdTypeAffinity[j]==pCol->affinity ){
            zType = sqlite3StdType[j];
            break;
          }
        }
       }
     }
     if( zType ){
       i64 m = sqlite3Strlen30(zType);
       n = sqlite3Strlen30(pCol->zCnName);
       pCol->zCnName = sqlite3DbReallocOrFree(db, pCol->zCnName, n+m+2);
       if( pCol->zCnName ){
         memcpy(&pCol->zCnName[n+1], zType, m+1);
         pCol->colFlags |= COLFLAG_HASTYPE;
       }else{
         testcase( pCol->colFlags & COLFLAG_HASTYPE );
        pCol->colFlags &= ~(COLFLAG_HASTYPE|COLFLAG_HASCOLL);
      }
    }
    pColl = sqlite3ExprCollSeq(pParse, p);
    if( pColl && pCol->zColl==0 ){
      pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
    if( pColl ){
      assert( pTab->pIndex==0 );
      sqlite3ColumnSetColl(db, pCol, pColl->zName);
    }
  }
  pTab->szTabRow = 1; /* Any non-zero value works */
}

/*
** Given a SELECT statement, generate a Table structure that describes
** the result set of that SELECT.
*/
Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect, char aff){
  Table *pTab;
  sqlite3 *db = pParse->db;
  u64 savedFlags;

  savedFlags = db->flags;
  db->flags &= ~(u64)SQLITE_FullColNames;
  db->flags |= SQLITE_ShortColNames;
  sqlite3SelectPrep(pParse, pSelect, 0);
  db->flags = savedFlags;
  if( pParse->nErr ) return 0;
  while( pSelect->pPrior ) pSelect = pSelect->pPrior;
  db->flags = savedFlags;
  pTab = sqlite3DbMallocZero(db, sizeof(Table) );
  if( pTab==0 ){
    return 0;
  }
  /* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside
  ** is disabled */
  assert( db->lookaside.bDisable );
  pTab->nTabRef = 1;
  pTab->zName = 0;
  pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
  sqlite3ColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
  sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSelect);
  sqlite3SubqueryColumnTypes(pParse, pTab, pSelect, aff);
  pTab->iPKey = -1;
  if( db->mallocFailed ){
    sqlite3DeleteTable(db, pTab);
    return 0;
  }
  return pTab;
}
2227
2228
2229
2230
2231
2232
2233
2234

2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254

2255
2256
2257
2258
2259
2260
2261
2539
2540
2541
2542
2543
2544
2545

2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565

2566
2567
2568
2569
2570
2571
2572
2573







-
+



















-
+







**
** Space to hold the KeyInfo structure is obtained from malloc. The calling
** function is responsible for ensuring that this structure is eventually
** freed.
*/
static KeyInfo *multiSelectOrderByKeyInfo(Parse *pParse, Select *p, int nExtra){
  ExprList *pOrderBy = p->pOrderBy;
  int nOrderBy = p->pOrderBy->nExpr;
  int nOrderBy = ALWAYS(pOrderBy!=0) ? pOrderBy->nExpr : 0;
  sqlite3 *db = pParse->db;
  KeyInfo *pRet = sqlite3KeyInfoAlloc(db, nOrderBy+nExtra, 1);
  if( pRet ){
    int i;
    for(i=0; i<nOrderBy; i++){
      struct ExprList_item *pItem = &pOrderBy->a[i];
      Expr *pTerm = pItem->pExpr;
      CollSeq *pColl;

      if( pTerm->flags & EP_Collate ){
        pColl = sqlite3ExprCollSeq(pParse, pTerm);
      }else{
        pColl = multiSelectCollSeq(pParse, p, pItem->u.x.iOrderByCol-1);
        if( pColl==0 ) pColl = db->pDfltColl;
        pOrderBy->a[i].pExpr =
          sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName);
      }
      assert( sqlite3KeyInfoIsWriteable(pRet) );
      pRet->aColl[i] = pColl;
      pRet->aSortOrder[i] = pOrderBy->a[i].sortOrder;
      pRet->aSortFlags[i] = pOrderBy->a[i].fg.sortFlags;
    }
  }

  return pRet;
}

#ifndef SQLITE_OMIT_CTE
2299
2300
2301
2302
2303
2304
2305
2306


2307
2308
2309
2310
2311
2312
2313
2611
2612
2613
2614
2615
2616
2617

2618
2619
2620
2621
2622
2623
2624
2625
2626







-
+
+







  Parse *pParse,        /* Parsing context */
  Select *p,            /* The recursive SELECT to be coded */
  SelectDest *pDest     /* What to do with query results */
){
  SrcList *pSrc = p->pSrc;      /* The FROM clause of the recursive query */
  int nCol = p->pEList->nExpr;  /* Number of columns in the recursive table */
  Vdbe *v = pParse->pVdbe;      /* The prepared statement under construction */
  Select *pSetup = p->pPrior;   /* The setup query */
  Select *pSetup;               /* The setup query */
  Select *pFirstRec;            /* Left-most recursive term */
  int addrTop;                  /* Top of the loop */
  int addrCont, addrBreak;      /* CONTINUE and BREAK addresses */
  int iCurrent = 0;             /* The Current table */
  int regCurrent;               /* Register holding Current table */
  int iQueue;                   /* The Queue table */
  int iDistinct = 0;            /* To ensure unique results if UNION */
  int eDest = SRT_Fifo;         /* How to write to Queue */
2325
2326
2327
2328
2329
2330
2331
2332

2333
2334
2335
2336
2337
2338
2339
2638
2639
2640
2641
2642
2643
2644

2645
2646
2647
2648
2649
2650
2651
2652







-
+







  }
#endif

  /* Obtain authorization to do a recursive query */
  if( sqlite3AuthCheck(pParse, SQLITE_RECURSIVE, 0, 0, 0) ) return;

  /* Process the LIMIT and OFFSET clauses, if they exist */
  addrBreak = sqlite3VdbeMakeLabel(v);
  addrBreak = sqlite3VdbeMakeLabel(pParse);
  p->nSelectRow = 320;  /* 4 billion rows */
  computeLimitRegisters(pParse, p, addrBreak);
  pLimit = p->pLimit;
  regLimit = p->iLimit;
  regOffset = p->iOffset;
  p->pLimit = 0;
  p->iLimit = p->iOffset = 0;
2374
2375
2376
2377
2378
2379
2380
2381
















2382

2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402

2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422





2423
2424
2425
2426
2427
2428
2429
2430
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731

2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744








2745
2746
2747
2748
2749

2750
2751
2752
2753
2754
2755
2756








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+



















-
+












-
-
-
-
-
-
-
-
+
+
+
+
+
-







  if( iDistinct ){
    p->addrOpenEphm[0] = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iDistinct, 0);
    p->selFlags |= SF_UsesEphemeral;
  }

  /* Detach the ORDER BY clause from the compound SELECT */
  p->pOrderBy = 0;

  /* Figure out how many elements of the compound SELECT are part of the
  ** recursive query.  Make sure no recursive elements use aggregate
  ** functions.  Mark the recursive elements as UNION ALL even if they
  ** are really UNION because the distinctness will be enforced by the
  ** iDistinct table.  pFirstRec is left pointing to the left-most
  ** recursive term of the CTE.
  */
  for(pFirstRec=p; ALWAYS(pFirstRec!=0); pFirstRec=pFirstRec->pPrior){
    if( pFirstRec->selFlags & SF_Aggregate ){
      sqlite3ErrorMsg(pParse, "recursive aggregate queries not supported");
      goto end_of_recursive_query;
    }
    pFirstRec->op = TK_ALL;
    if( (pFirstRec->pPrior->selFlags & SF_Recursive)==0 ) break;
  }

  /* Store the results of the setup-query in Queue. */
  pSetup = pFirstRec->pPrior;
  pSetup->pNext = 0;
  ExplainQueryPlan((pParse, 1, "SETUP"));
  rc = sqlite3Select(pParse, pSetup, &destQueue);
  pSetup->pNext = p;
  if( rc ) goto end_of_recursive_query;

  /* Find the next row in the Queue and output that row */
  addrTop = sqlite3VdbeAddOp2(v, OP_Rewind, iQueue, addrBreak); VdbeCoverage(v);

  /* Transfer the next row in Queue over to Current */
  sqlite3VdbeAddOp1(v, OP_NullRow, iCurrent); /* To reset column cache */
  if( pOrderBy ){
    sqlite3VdbeAddOp3(v, OP_Column, iQueue, pOrderBy->nExpr+1, regCurrent);
  }else{
    sqlite3VdbeAddOp2(v, OP_RowData, iQueue, regCurrent);
  }
  sqlite3VdbeAddOp1(v, OP_Delete, iQueue);

  /* Output the single row in Current */
  addrCont = sqlite3VdbeMakeLabel(v);
  addrCont = sqlite3VdbeMakeLabel(pParse);
  codeOffset(v, regOffset, addrCont);
  selectInnerLoop(pParse, p, iCurrent,
      0, 0, pDest, addrCont, addrBreak);
  if( regLimit ){
    sqlite3VdbeAddOp2(v, OP_DecrJumpZero, regLimit, addrBreak);
    VdbeCoverage(v);
  }
  sqlite3VdbeResolveLabel(v, addrCont);

  /* Execute the recursive SELECT taking the single row in Current as
  ** the value for the recursive-table. Store the results in the Queue.
  */
  if( p->selFlags & SF_Aggregate ){
    sqlite3ErrorMsg(pParse, "recursive aggregate queries not supported");
  }else{
    p->pPrior = 0;
    ExplainQueryPlan((pParse, 1, "RECURSIVE STEP"));
    sqlite3Select(pParse, p, &destQueue);
    assert( p->pPrior==0 );
    p->pPrior = pSetup;
  pFirstRec->pPrior = 0;
  ExplainQueryPlan((pParse, 1, "RECURSIVE STEP"));
  sqlite3Select(pParse, p, &destQueue);
  assert( pFirstRec->pPrior==0 );
  pFirstRec->pPrior = pSetup;
  }

  /* Keep running the loop until the Queue is empty */
  sqlite3VdbeGoto(v, addrTop);
  sqlite3VdbeResolveLabel(v, addrBreak);

end_of_recursive_query:
  sqlite3ExprListDelete(pParse->db, p->pOrderBy);
2451
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
2481
2482
2483
2484
2485
2486
2487










2488
2489
2490
2491
2492
2493
2494
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
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833







-
+














+
+
+















+
+
+
+
+
+
+
+
+
+







**   (1) There is no LIMIT or OFFSET or else there is a LIMIT of exactly 1
**   (2) All terms are UNION ALL
**   (3) There is no ORDER BY clause
**
** The "LIMIT of exactly 1" case of condition (1) comes about when a VALUES
** clause occurs within scalar expression (ex: "SELECT (VALUES(1),(2),(3))").
** The sqlite3CodeSubselect will have added the LIMIT 1 clause in tht case.
** Since the limit is exactly 1, we only need to evalutes the left-most VALUES.
** Since the limit is exactly 1, we only need to evaluate the left-most VALUES.
*/
static int multiSelectValues(
  Parse *pParse,        /* Parsing context */
  Select *p,            /* The right-most of SELECTs to be coded */
  SelectDest *pDest     /* What to do with query results */
){
  int nRow = 1;
  int rc = 0;
  int bShowAll = p->pLimit==0;
  assert( p->selFlags & SF_MultiValue );
  do{
    assert( p->selFlags & SF_Values );
    assert( p->op==TK_ALL || (p->op==TK_SELECT && p->pPrior==0) );
    assert( p->pNext==0 || p->pEList->nExpr==p->pNext->pEList->nExpr );
#ifndef SQLITE_OMIT_WINDOWFUNC
    if( p->pWin ) return -1;
#endif
    if( p->pPrior==0 ) break;
    assert( p->pPrior->pNext==p );
    p = p->pPrior;
    nRow += bShowAll;
  }while(1);
  ExplainQueryPlan((pParse, 0, "SCAN %d CONSTANT ROW%s", nRow,
                    nRow==1 ? "" : "S"));
  while( p ){
    selectInnerLoop(pParse, p, -1, 0, 0, pDest, 1, 1);
    if( !bShowAll ) break;
    p->nSelectRow = nRow;
    p = p->pNext;
  }
  return rc;
}

/*
** Return true if the SELECT statement which is known to be the recursive
** part of a recursive CTE still has its anchor terms attached.  If the
** anchor terms have already been removed, then return false.
*/
static int hasAnchor(Select *p){
  while( p && (p->selFlags & SF_Recursive)!=0 ){ p = p->pPrior; }
  return p!=0;
}

/*
** This routine is called to process a compound query form from
** two or more separate queries using UNION, UNION ALL, EXCEPT, or
** INTERSECT
**
** "p" points to the right-most of the two queries.  the query on the
2530
2531
2532
2533
2534
2535
2536

2537
2538
2539
2540

2541
2542

2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562


2563
2564
2565
2566
2567
2568
2569
2570
2571
2572

2573
2574
2575
2576
2577
2578
2579
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879

2880


2881



2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897

2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908

2909
2910
2911
2912
2913
2914
2915
2916







+



-
+
-
-
+
-
-
-
















-
+
+









-
+







  sqlite3 *db;          /* Database connection */

  /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs.  Only
  ** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT.
  */
  assert( p && p->pPrior );  /* Calling function guarantees this much */
  assert( (p->selFlags & SF_Recursive)==0 || p->op==TK_ALL || p->op==TK_UNION );
  assert( p->selFlags & SF_Compound );
  db = pParse->db;
  pPrior = p->pPrior;
  dest = *pDest;
  if( pPrior->pOrderBy || pPrior->pLimit ){
  assert( pPrior->pOrderBy==0 );
    sqlite3ErrorMsg(pParse,"%s clause should come after %s not before",
      pPrior->pOrderBy!=0 ? "ORDER BY" : "LIMIT", selectOpName(p->op));
  assert( pPrior->pLimit==0 );
    rc = 1;
    goto multi_select_end;
  }

  v = sqlite3GetVdbe(pParse);
  assert( v!=0 );  /* The VDBE already created by calling function */

  /* Create the destination temporary table if necessary
  */
  if( dest.eDest==SRT_EphemTab ){
    assert( p->pEList );
    sqlite3VdbeAddOp2(v, OP_OpenEphemeral, dest.iSDParm, p->pEList->nExpr);
    dest.eDest = SRT_Table;
  }

  /* Special handling for a compound-select that originates as a VALUES clause.
  */
  if( p->selFlags & SF_MultiValue ){
    rc = multiSelectValues(pParse, p, &dest);
    goto multi_select_end;
    if( rc>=0 ) goto multi_select_end;
    rc = SQLITE_OK;
  }

  /* Make sure all SELECTs in the statement have the same number of elements
  ** in their result sets.
  */
  assert( p->pEList && pPrior->pEList );
  assert( p->pEList->nExpr==pPrior->pEList->nExpr );

#ifndef SQLITE_OMIT_CTE
  if( p->selFlags & SF_Recursive ){
  if( (p->selFlags & SF_Recursive)!=0 && hasAnchor(p) ){
    generateWithRecursiveQuery(pParse, p, &dest);
  }else
#endif

  /* Compound SELECTs that have an ORDER BY clause are handled separately.
  */
  if( p->pOrderBy ){
2588
2589
2590
2591
2592
2593
2594
2595

2596
2597
2598
2599

2600
2601

2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616

2617
2618
2619
2620
2621
2622
2623


2624
2625
2626
2627
2628
2629
2630
2925
2926
2927
2928
2929
2930
2931

2932
2933
2934
2935
2936
2937
2938

2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960


2961
2962
2963
2964
2965
2966
2967
2968
2969







-
+




+

-
+















+





-
-
+
+







#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;
        TREETRACE(0x200, pParse, p, ("multiSelect UNION ALL left...\n"));
        rc = sqlite3Select(pParse, pPrior, &dest);
        p->pLimit = 0;
        pPrior->pLimit = 0;
        if( rc ){
          goto multi_select_end;
        }
        p->pPrior = 0;
        p->iLimit = pPrior->iLimit;
        p->iOffset = pPrior->iOffset;
        if( p->iLimit ){
          addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v);
          VdbeComment((v, "Jump ahead if LIMIT reached"));
          if( p->iOffset ){
            sqlite3VdbeAddOp3(v, OP_OffsetLimit,
                              p->iLimit, p->iOffset+1, p->iOffset);
          }
        }
        ExplainQueryPlan((pParse, 1, "UNION ALL"));
        TREETRACE(0x200, pParse, p, ("multiSelect UNION ALL right...\n"));
        rc = sqlite3Select(pParse, p, &dest);
        testcase( rc!=SQLITE_OK );
        pDelete = p->pPrior;
        p->pPrior = pPrior;
        p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
        if( pPrior->pLimit
         && sqlite3ExprIsInteger(pPrior->pLimit->pLeft, &nLimit)
        if( p->pLimit
         && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit)
         && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit) 
        ){
          p->nSelectRow = sqlite3LogEst((u64)nLimit);
        }
        if( addr ){
          sqlite3VdbeJumpHere(v, addr);
        }
2656
2657
2658
2659
2660
2661
2662

2663
2664
2665
2666
2667

2668
2669
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
2704
2705
2706

2707

2708
2709
2710
2711


2712
2713
2714
2715
2716
2717
2718
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026

3027
3028
3029
3030



3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047

3048
3049



3050
3051
3052
3053
3054
3055
3056
3057
3058







+





+


















-
+
+


-
-
-
+















+
-
+

-
-
-
+
+







          assert( p->pOrderBy==0 );
          addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0);
          assert( p->addrOpenEphm[0] == -1 );
          p->addrOpenEphm[0] = addr;
          findRightmost(p)->selFlags |= SF_UsesEphemeral;
          assert( p->pEList );
        }
          
  
        /* Code the SELECT statements to our left
        */
        assert( !pPrior->pOrderBy );
        sqlite3SelectDestInit(&uniondest, priorOp, unionTab);
        TREETRACE(0x200, pParse, p, ("multiSelect EXCEPT/UNION left...\n"));
        rc = sqlite3Select(pParse, pPrior, &uniondest);
        if( rc ){
          goto multi_select_end;
        }
  
        /* Code the current SELECT statement
        */
        if( p->op==TK_EXCEPT ){
          op = SRT_Except;
        }else{
          assert( p->op==TK_UNION );
          op = SRT_Union;
        }
        p->pPrior = 0;
        pLimit = p->pLimit;
        p->pLimit = 0;
        uniondest.eDest = op;
        ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
                          selectOpName(p->op)));
                          sqlite3SelectOpName(p->op)));
        TREETRACE(0x200, pParse, p, ("multiSelect EXCEPT/UNION right...\n"));
        rc = sqlite3Select(pParse, p, &uniondest);
        testcase( rc!=SQLITE_OK );
        /* Query flattening in sqlite3Select() might refill p->pOrderBy.
        ** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */
        sqlite3ExprListDelete(db, p->pOrderBy);
        assert( p->pOrderBy==0 );
        pDelete = p->pPrior;
        p->pPrior = pPrior;
        p->pOrderBy = 0;
        if( p->op==TK_UNION ){
          p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
        }
        sqlite3ExprDelete(db, p->pLimit);
        p->pLimit = pLimit;
        p->iLimit = 0;
        p->iOffset = 0;
  
        /* Convert the data in the temporary table into whatever form
        ** it is that we currently need.
        */
        assert( unionTab==dest.iSDParm || dest.eDest!=priorOp );
        assert( p->pEList || db->mallocFailed );
        if( dest.eDest!=priorOp ){
        if( dest.eDest!=priorOp && db->mallocFailed==0 ){
          int iCont, iBreak, iStart;
          assert( p->pEList );
          iBreak = sqlite3VdbeMakeLabel(v);
          iCont = sqlite3VdbeMakeLabel(v);
          iBreak = sqlite3VdbeMakeLabel(pParse);
          iCont = sqlite3VdbeMakeLabel(pParse);
          computeLimitRegisters(pParse, p, iBreak);
          sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); VdbeCoverage(v);
          iStart = sqlite3VdbeCurrentAddr(v);
          selectInnerLoop(pParse, p, unionTab,
                          0, 0, &dest, iCont, iBreak);
          sqlite3VdbeResolveLabel(v, iCont);
          sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); VdbeCoverage(v);
2742
2743
2744
2745
2746
2747
2748

2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764


2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777

2778
2779
2780


2781
2782
2783
2784
2785
2786
2787
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104

3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121


3122
3123
3124
3125
3126
3127
3128
3129
3130







+















-
+
+













+

-
-
+
+







        p->addrOpenEphm[0] = addr;
        findRightmost(p)->selFlags |= SF_UsesEphemeral;
        assert( p->pEList );
  
        /* Code the SELECTs to our left into temporary table "tab1".
        */
        sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1);
        TREETRACE(0x400, pParse, p, ("multiSelect INTERSECT left...\n"));
        rc = sqlite3Select(pParse, pPrior, &intersectdest);
        if( rc ){
          goto multi_select_end;
        }
  
        /* Code the current SELECT into temporary table "tab2"
        */
        addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0);
        assert( p->addrOpenEphm[1] == -1 );
        p->addrOpenEphm[1] = addr;
        p->pPrior = 0;
        pLimit = p->pLimit;
        p->pLimit = 0;
        intersectdest.iSDParm = tab2;
        ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
                          selectOpName(p->op)));
                          sqlite3SelectOpName(p->op)));
        TREETRACE(0x400, pParse, p, ("multiSelect INTERSECT right...\n"));
        rc = sqlite3Select(pParse, p, &intersectdest);
        testcase( rc!=SQLITE_OK );
        pDelete = p->pPrior;
        p->pPrior = pPrior;
        if( p->nSelectRow>pPrior->nSelectRow ){
          p->nSelectRow = pPrior->nSelectRow;
        }
        sqlite3ExprDelete(db, p->pLimit);
        p->pLimit = pLimit;
  
        /* Generate code to take the intersection of the two temporary
        ** tables.
        */
        if( rc ) break;
        assert( p->pEList );
        iBreak = sqlite3VdbeMakeLabel(v);
        iCont = sqlite3VdbeMakeLabel(v);
        iBreak = sqlite3VdbeMakeLabel(pParse);
        iCont = sqlite3VdbeMakeLabel(pParse);
        computeLimitRegisters(pParse, p, iBreak);
        sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); VdbeCoverage(v);
        r1 = sqlite3GetTempReg(pParse);
        iStart = sqlite3VdbeAddOp2(v, OP_RowData, tab1, r1);
        sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0);
        VdbeCoverage(v);
        sqlite3ReleaseTempReg(pParse, r1);
2798
2799
2800
2801
2802
2803
2804

2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822

2823
2824
2825
2826
2827
2828
2829
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174







+


















+







  
  #ifndef SQLITE_OMIT_EXPLAIN
    if( p->pNext==0 ){
      ExplainQueryPlanPop(pParse);
    }
  #endif
  }
  if( pParse->nErr ) goto multi_select_end;
  
  /* Compute collating sequences used by 
  ** temporary tables needed to implement the compound select.
  ** Attach the KeyInfo structure to all temporary tables.
  **
  ** This section is run by the right-most SELECT statement only.
  ** SELECT statements to the left always skip this part.  The right-most
  ** SELECT might also skip this part if it has no ORDER BY clause and
  ** no temp tables are required.
  */
  if( p->selFlags & SF_UsesEphemeral ){
    int i;                        /* Loop counter */
    KeyInfo *pKeyInfo;            /* Collating sequence for the result set */
    Select *pLoop;                /* For looping through SELECT statements */
    CollSeq **apColl;             /* For looping through pKeyInfo->aColl[] */
    int nCol;                     /* Number of columns in result set */

    assert( p->pNext==0 );
    assert( p->pEList!=0 );
    nCol = p->pEList->nExpr;
    pKeyInfo = sqlite3KeyInfoAlloc(db, nCol, 1);
    if( !pKeyInfo ){
      rc = SQLITE_NOMEM_BKPT;
      goto multi_select_end;
    }
    for(i=0, apColl=pKeyInfo->aColl; i<nCol; i++, apColl++){
2850
2851
2852
2853
2854
2855
2856


2857



2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871


2872
2873
2874
2875
2876
2877
2878
3195
3196
3197
3198
3199
3200
3201
3202
3203

3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219

3220
3221
3222
3223
3224
3225
3226
3227
3228







+
+
-
+
+
+













-
+
+







    }
    sqlite3KeyInfoUnref(pKeyInfo);
  }

multi_select_end:
  pDest->iSdst = dest.iSdst;
  pDest->nSdst = dest.nSdst;
  if( pDelete ){
    sqlite3ParserAddCleanup(pParse,
  sqlite3SelectDelete(db, pDelete);
        (void(*)(sqlite3*,void*))sqlite3SelectDelete,
        pDelete);
  }
  return rc;
}
#endif /* SQLITE_OMIT_COMPOUND_SELECT */

/*
** Error message for when two or more terms of a compound select have different
** size result sets.
*/
void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p){
  if( p->selFlags & SF_Values ){
    sqlite3ErrorMsg(pParse, "all VALUES must have the same number of terms");
  }else{
    sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s"
      " do not have the same number of result columns", selectOpName(p->op));
      " do not have the same number of result columns",
      sqlite3SelectOpName(p->op));
  }
}

/*
** Code an output subroutine for a coroutine implementation of a
** SELECT statment.
**
2903
2904
2905
2906
2907
2908
2909
2910

2911
2912
2913
2914
2915
2916
2917
3253
3254
3255
3256
3257
3258
3259

3260
3261
3262
3263
3264
3265
3266
3267







-
+







  int iBreak              /* Jump here if we hit the LIMIT */
){
  Vdbe *v = pParse->pVdbe;
  int iContinue;
  int addr;

  addr = sqlite3VdbeCurrentAddr(v);
  iContinue = sqlite3VdbeMakeLabel(v);
  iContinue = sqlite3VdbeMakeLabel(pParse);

  /* Suppress duplicates for UNION, EXCEPT, and INTERSECT 
  */
  if( regPrev ){
    int addr1, addr2;
    addr1 = sqlite3VdbeAddOp1(v, OP_IfNot, regPrev); VdbeCoverage(v);
    addr2 = sqlite3VdbeAddOp4(v, OP_Compare, pIn->iSdst, regPrev+1, pIn->nSdst,
2957
2958
2959
2960
2961
2962
2963
2964


2965
2966
2967
2968


2969
2970
2971
2972
2973
2974
2975
3307
3308
3309
3310
3311
3312
3313

3314
3315
3316
3317


3318
3319
3320
3321
3322
3323
3324
3325
3326







-
+
+


-
-
+
+







                           pIn->iSdst, pIn->nSdst);
      sqlite3ReleaseTempReg(pParse, r1);
      break;
    }

    /* If this is a scalar select that is part of an expression, then
    ** store the results in the appropriate memory cell and break out
    ** of the scan loop.
    ** of the scan loop.  Note that the select might return multiple columns
    ** if it is the RHS of a row-value IN operator.
    */
    case SRT_Mem: {
      assert( pIn->nSdst==1 || pParse->nErr>0 );  testcase( pIn->nSdst!=1 );
      sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, 1);
      testcase( pIn->nSdst>1 );
      sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, pIn->nSdst);
      /* The LIMIT clause will jump out of the loop for us */
      break;
    }
#endif /* #ifndef SQLITE_OMIT_SUBQUERY */

    /* The results are stored in a sequence of registers
    ** starting at pDest->iSdst.  Then the co-routine yields.
3102
3103
3104
3105
3106
3107
3108


3109
3110
3111
3112
3113
3114
3115
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468







+
+







static int multiSelectOrderBy(
  Parse *pParse,        /* Parsing context */
  Select *p,            /* The right-most of SELECTs to be coded */
  SelectDest *pDest     /* What to do with query results */
){
  int i, j;             /* Loop counters */
  Select *pPrior;       /* Another SELECT immediately to our left */
  Select *pSplit;       /* Left-most SELECT in the right-hand group */
  int nSelect;          /* Number of SELECT statements in the compound */
  Vdbe *v;              /* Generate code to this VDBE */
  SelectDest destA;     /* Destination for coroutine A */
  SelectDest destB;     /* Destination for coroutine B */
  int regAddrA;         /* Address register for select-A coroutine */
  int regAddrB;         /* Address register for select-B coroutine */
  int addrSelectA;      /* Address of the select-A coroutine */
  int addrSelectB;      /* Address of the select-B coroutine */
3133
3134
3135
3136
3137
3138
3139
3140

3141
3142
3143
3144
3145
3146
3147
3148


3149
3150
3151
3152
3153
3154
3155

3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167

3168
3169
3170
3171
3172
3173
3174
3486
3487
3488
3489
3490
3491
3492

3493
3494
3495
3496
3497
3498
3499


3500
3501
3502
3503
3504
3505
3506


3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527







-
+






-
-
+
+





-
-
+












+







  int addr1;            /* Jump instructions that get retargetted */
  int op;               /* One of TK_ALL, TK_UNION, TK_EXCEPT, TK_INTERSECT */
  KeyInfo *pKeyDup = 0; /* Comparison information for duplicate removal */
  KeyInfo *pKeyMerge;   /* Comparison information for merging rows */
  sqlite3 *db;          /* Database connection */
  ExprList *pOrderBy;   /* The ORDER BY clause */
  int nOrderBy;         /* Number of terms in the ORDER BY clause */
  int *aPermute;        /* Mapping from ORDER BY terms to result set columns */
  u32 *aPermute;        /* Mapping from ORDER BY terms to result set columns */

  assert( p->pOrderBy!=0 );
  assert( pKeyDup==0 ); /* "Managed" code needs this.  Ticket #3382. */
  db = pParse->db;
  v = pParse->pVdbe;
  assert( v!=0 );       /* Already thrown the error if VDBE alloc failed */
  labelEnd = sqlite3VdbeMakeLabel(v);
  labelCmpr = sqlite3VdbeMakeLabel(v);
  labelEnd = sqlite3VdbeMakeLabel(pParse);
  labelCmpr = sqlite3VdbeMakeLabel(pParse);


  /* Patch up the ORDER BY clause
  */
  op = p->op;  
  pPrior = p->pPrior;
  assert( pPrior->pOrderBy==0 );
  assert( p->pPrior->pOrderBy==0 );
  pOrderBy = p->pOrderBy;
  assert( pOrderBy );
  nOrderBy = pOrderBy->nExpr;

  /* For operators other than UNION ALL we have to make sure that
  ** the ORDER BY clause covers every term of the result set.  Add
  ** terms to the ORDER BY clause as necessary.
  */
  if( op!=TK_ALL ){
    for(i=1; db->mallocFailed==0 && i<=p->pEList->nExpr; i++){
      struct ExprList_item *pItem;
      for(j=0, pItem=pOrderBy->a; j<nOrderBy; j++, pItem++){
        assert( pItem!=0 );
        assert( pItem->u.x.iOrderByCol>0 );
        if( pItem->u.x.iOrderByCol==i ) break;
      }
      if( j==nOrderBy ){
        Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0);
        if( pNew==0 ) return SQLITE_NOMEM_BKPT;
        pNew->flags |= EP_IntValue;
3182
3183
3184
3185
3186
3187
3188
3189

3190
3191
3192
3193

3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225

3226
3227
3228
3229
3230
3231

















3232

3233



3234
3235
3236

3237
3238
3239
3240
3241
3242
3243
3244
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
3569
3570
3571
3572
3573

3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597

3598
3599
3600
3601
3602
3603


3604

3605
3606
3607
3608
3609
3610
3611







-
+




+









-
-
-
-
-

















-
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+

+
+
+

-
-
+
-







  /* Compute the comparison permutation and keyinfo that is used with
  ** the permutation used to determine if the next
  ** row of results comes from selectA or selectB.  Also add explicit
  ** collations to the ORDER BY clause terms so that when the subqueries
  ** to the right and the left are evaluated, they use the correct
  ** collation.
  */
  aPermute = sqlite3DbMallocRawNN(db, sizeof(int)*(nOrderBy + 1));
  aPermute = sqlite3DbMallocRawNN(db, sizeof(u32)*(nOrderBy + 1));
  if( aPermute ){
    struct ExprList_item *pItem;
    aPermute[0] = nOrderBy;
    for(i=1, pItem=pOrderBy->a; i<=nOrderBy; i++, pItem++){
      assert( pItem!=0 );
      assert( pItem->u.x.iOrderByCol>0 );
      assert( pItem->u.x.iOrderByCol<=p->pEList->nExpr );
      aPermute[i] = pItem->u.x.iOrderByCol - 1;
    }
    pKeyMerge = multiSelectOrderByKeyInfo(pParse, p, 1);
  }else{
    pKeyMerge = 0;
  }

  /* Reattach the ORDER BY clause to the query.
  */
  p->pOrderBy = pOrderBy;
  pPrior->pOrderBy = sqlite3ExprListDup(pParse->db, pOrderBy, 0);

  /* Allocate a range of temporary registers and the KeyInfo needed
  ** for the logic that removes duplicate result rows when the
  ** operator is UNION, EXCEPT, or INTERSECT (but not UNION ALL).
  */
  if( op==TK_ALL ){
    regPrev = 0;
  }else{
    int nExpr = p->pEList->nExpr;
    assert( nOrderBy>=nExpr || db->mallocFailed );
    regPrev = pParse->nMem+1;
    pParse->nMem += nExpr+1;
    sqlite3VdbeAddOp2(v, OP_Integer, 0, regPrev);
    pKeyDup = sqlite3KeyInfoAlloc(db, nExpr, 1);
    if( pKeyDup ){
      assert( sqlite3KeyInfoIsWriteable(pKeyDup) );
      for(i=0; i<nExpr; i++){
        pKeyDup->aColl[i] = multiSelectCollSeq(pParse, p, i);
        pKeyDup->aSortOrder[i] = 0;
        pKeyDup->aSortFlags[i] = 0;
      }
    }
  }
 
  /* Separate the left and the right query from one another
  */
  nSelect = 1;
  if( (op==TK_ALL || op==TK_UNION)
   && OptimizationEnabled(db, SQLITE_BalancedMerge)
  ){
    for(pSplit=p; pSplit->pPrior!=0 && pSplit->op==op; pSplit=pSplit->pPrior){
      nSelect++;
      assert( pSplit->pPrior->pNext==pSplit );
    }
  }
  if( nSelect<=3 ){
    pSplit = p;
  }else{
    pSplit = p;
    for(i=2; i<nSelect; i+=2){ pSplit = pSplit->pPrior; }
  }
  pPrior = pSplit->pPrior;
  assert( pPrior!=0 );
  p->pPrior = 0;
  pSplit->pPrior = 0;
  pPrior->pNext = 0;
  assert( p->pOrderBy == pOrderBy );
  assert( pOrderBy!=0 || db->mallocFailed );
  pPrior->pOrderBy = sqlite3ExprListDup(pParse->db, pOrderBy, 0);
  sqlite3ResolveOrderGroupBy(pParse, p, p->pOrderBy, "ORDER");
  if( pPrior->pPrior==0 ){
    sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, "ORDER");
  sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, "ORDER");
  }

  /* Compute the limit registers */
  computeLimitRegisters(pParse, p, labelEnd);
  if( p->iLimit && op==TK_ALL ){
    regLimitA = ++pParse->nMem;
    regLimitB = ++pParse->nMem;
    sqlite3VdbeAddOp2(v, OP_Copy, p->iOffset ? p->iOffset+1 : p->iLimit,
3253
3254
3255
3256
3257
3258
3259
3260

3261
3262
3263
3264
3265
3266
3267
3620
3621
3622
3623
3624
3625
3626

3627
3628
3629
3630
3631
3632
3633
3634







-
+







  regAddrA = ++pParse->nMem;
  regAddrB = ++pParse->nMem;
  regOutA = ++pParse->nMem;
  regOutB = ++pParse->nMem;
  sqlite3SelectDestInit(&destA, SRT_Coroutine, regAddrA);
  sqlite3SelectDestInit(&destB, SRT_Coroutine, regAddrB);

  ExplainQueryPlan((pParse, 1, "MERGE (%s)", selectOpName(p->op)));
  ExplainQueryPlan((pParse, 1, "MERGE (%s)", sqlite3SelectOpName(p->op)));

  /* Generate a coroutine to evaluate the SELECT statement to the
  ** left of the compound operator - the "A" select.
  */
  addrSelectA = sqlite3VdbeCurrentAddr(v) + 1;
  addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrA, 0, addrSelectA);
  VdbeComment((v, "left SELECT"));
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389





3390
3391
3392




3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407




























3408
3409
3410
3411
3412
3413

3414

3415
3416
3417
3418
3419
3420
3421
3746
3747
3748
3749
3750
3751
3752




3753
3754
3755
3756
3757
3758


3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810

3811
3812
3813
3814
3815
3816
3817
3818
3819
3820







-
-
-
-
+
+
+
+
+

-
-
+
+
+
+















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+

+







  sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE);
  sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); VdbeCoverage(v);

  /* Jump to the this point in order to terminate the query.
  */
  sqlite3VdbeResolveLabel(v, labelEnd);

  /* Reassembly the compound query so that it will be freed correctly
  ** by the calling function */
  if( p->pPrior ){
    sqlite3SelectDelete(db, p->pPrior);
  /* Make arrangements to free the 2nd and subsequent arms of the compound
  ** after the parse has finished */
  if( pSplit->pPrior ){
    sqlite3ParserAddCleanup(pParse, 
       (void(*)(sqlite3*,void*))sqlite3SelectDelete, pSplit->pPrior);
  }
  p->pPrior = pPrior;
  pPrior->pNext = p;
  pSplit->pPrior = pPrior;
  pPrior->pNext = pSplit;
  sqlite3ExprListDelete(db, pPrior->pOrderBy);
  pPrior->pOrderBy = 0;

  /*** TBD:  Insert subroutine calls to close cursors on incomplete
  **** subqueries ****/
  ExplainQueryPlanPop(pParse);
  return pParse->nErr!=0;
}
#endif

#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)

/* An instance of the SubstContext object describes an substitution edit
** to be performed on a parse tree.
**
** All references to columns in table iTable are to be replaced by corresponding
** expressions in pEList.
**
** ## About "isOuterJoin":
**
** The isOuterJoin column indicates that the replacement will occur into a
** position in the parent that NULL-able due to an OUTER JOIN.  Either the
** target slot in the parent is the right operand of a LEFT JOIN, or one of
** the left operands of a RIGHT JOIN.  In either case, we need to potentially
** bypass the substituted expression with OP_IfNullRow.
**
** Suppose the original expression is an integer constant. Even though the table
** has the nullRow flag set, because the expression is an integer constant,
** it will not be NULLed out.  So instead, we insert an OP_IfNullRow opcode
** that checks to see if the nullRow flag is set on the table.  If the nullRow
** flag is set, then the value in the register is set to NULL and the original
** expression is bypassed.  If the nullRow flag is not set, then the original
** expression runs to populate the register.
**
** Example where this is needed:
**
**      CREATE TABLE t1(a INTEGER PRIMARY KEY, b INT);
**      CREATE TABLE t2(x INT UNIQUE);
**
**      SELECT a,b,m,x FROM t1 LEFT JOIN (SELECT 59 AS m,x FROM t2) ON b=x;
**
** When the subquery on the right side of the LEFT JOIN is flattened, we
** have to add OP_IfNullRow in front of the OP_Integer that implements the
** "m" value of the subquery so that a NULL will be loaded instead of 59
** when processing a non-matched row of the left.
*/
typedef struct SubstContext {
  Parse *pParse;            /* The parsing context */
  int iTable;               /* Replace references to this table */
  int iNewTable;            /* New table number */
  int isLeftJoin;           /* Add TK_IF_NULL_ROW opcodes on each replacement */
  int isOuterJoin;          /* Add TK_IF_NULL_ROW opcodes on each replacement */
  ExprList *pEList;         /* Replacement expressions */
  ExprList *pCList;         /* Collation sequences for replacement expr */
} SubstContext;

/* Forward Declarations */
static void substExprList(SubstContext*, ExprList*);
static void substSelect(SubstContext*, Select*, int);

/*
3432
3433
3434
3435
3436
3437
3438
3439
3440


3441

3442

3443
3444





3445
3446
3447



3448

3449

3450
3451

3452
3453
3454
3455
3456
3457

3458
3459
3460
3461


3462
3463
3464
3465




3466

3467
3468
3469
3470
3471



3472
3473
3474




















3475
3476
3477
3478
3479
3480
3481
3482
3483

3484
3485
3486
3487








3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507

3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526









































































































































































3527
3528
3529
3530
3531
3532
3533
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
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
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915

3916
3917
3918
3919
3920
3921
3922
3923
3924
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
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
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
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
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143







-
-
+
+

+
-
+

-
+
+
+
+
+


-
+
+
+

+
-
+

-
+





-
+




+
+




+
+
+
+
-
+


-
-
-
+
+
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








-
+




+
+
+
+
+
+
+
+



















-
+



















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







** of the subquery rather the result set of the subquery.
*/
static Expr *substExpr(
  SubstContext *pSubst,  /* Description of the substitution */
  Expr *pExpr            /* Expr in which substitution occurs */
){
  if( pExpr==0 ) return 0;
  if( ExprHasProperty(pExpr, EP_FromJoin)
   && pExpr->iRightJoinTable==pSubst->iTable
  if( ExprHasProperty(pExpr, EP_OuterON|EP_InnerON)
   && pExpr->w.iJoin==pSubst->iTable
  ){
    testcase( ExprHasProperty(pExpr, EP_InnerON) );
    pExpr->iRightJoinTable = pSubst->iNewTable;
    pExpr->w.iJoin = pSubst->iNewTable;
  }
  if( pExpr->op==TK_COLUMN && pExpr->iTable==pSubst->iTable ){
  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;
      int iColumn = pExpr->iColumn;
      Expr *pCopy = pSubst->pEList->a[pExpr->iColumn].pExpr;
      Expr *pCopy = pSubst->pEList->a[iColumn].pExpr;
      Expr ifNullRow;
      assert( pSubst->pEList!=0 && pExpr->iColumn<pSubst->pEList->nExpr );
      assert( pSubst->pEList!=0 && 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 ){
        if( pSubst->isOuterJoin && pCopy->op!=TK_COLUMN ){
          memset(&ifNullRow, 0, sizeof(ifNullRow));
          ifNullRow.op = TK_IF_NULL_ROW;
          ifNullRow.pLeft = pCopy;
          ifNullRow.iTable = pSubst->iNewTable;
          ifNullRow.iColumn = -99;
          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->isOuterJoin ){
          ExprSetProperty(pNew, EP_CanBeNull);
        }
        if( pNew && ExprHasProperty(pExpr,EP_FromJoin) ){
          pNew->iRightJoinTable = pExpr->iRightJoinTable;
          ExprSetProperty(pNew, EP_FromJoin);
        if( ExprHasProperty(pExpr,EP_OuterON|EP_InnerON) ){
          sqlite3SetJoinExpr(pNew, pExpr->w.iJoin,
                             pExpr->flags & (EP_OuterON|EP_InnerON));
        }
        sqlite3ExprDelete(db, pExpr);
        pExpr = pNew;
        if( pExpr->op==TK_TRUEFALSE ){
          pExpr->u.iValue = sqlite3ExprTruthValue(pExpr);
          pExpr->op = TK_INTEGER;
          ExprSetProperty(pExpr, EP_IntValue);
        }

        /* 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. */
        {
          CollSeq *pNat = sqlite3ExprCollSeq(pSubst->pParse, pExpr);
          CollSeq *pColl = sqlite3ExprCollSeq(pSubst->pParse,
                pSubst->pCList->a[iColumn].pExpr
          );
          if( pNat!=pColl || (pExpr->op!=TK_COLUMN && pExpr->op!=TK_COLLATE) ){
            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);
    pExpr->pRight = substExpr(pSubst, pExpr->pRight);
    if( ExprHasProperty(pExpr, EP_xIsSelect) ){
    if( ExprUseXSelect(pExpr) ){
      substSelect(pSubst, pExpr->x.pSelect, 1);
    }else{
      substExprList(pSubst, pExpr->x.pList);
    }
#ifndef SQLITE_OMIT_WINDOWFUNC
    if( ExprHasProperty(pExpr, EP_WinFunc) ){
      Window *pWin = pExpr->y.pWin;
      pWin->pFilter = substExpr(pSubst, pWin->pFilter);
      substExprList(pSubst, pWin->pPartition);
      substExprList(pSubst, pWin->pOrderBy);
    }
#endif
  }
  return pExpr;
}
static void substExprList(
  SubstContext *pSubst, /* Description of the substitution */
  ExprList *pList       /* List to scan and in which to make substitutes */
){
  int i;
  if( pList==0 ) return;
  for(i=0; i<pList->nExpr; i++){
    pList->a[i].pExpr = substExpr(pSubst, pList->a[i].pExpr);
  }
}
static void substSelect(
  SubstContext *pSubst, /* Description of the substitution */
  Select *p,            /* SELECT statement in which to make substitutions */
  int doPrior           /* Do substitutes on p->pPrior too */
){
  SrcList *pSrc;
  struct SrcList_item *pItem;
  SrcItem *pItem;
  int i;
  if( !p ) return;
  do{
    substExprList(pSubst, p->pEList);
    substExprList(pSubst, p->pGroupBy);
    substExprList(pSubst, p->pOrderBy);
    p->pHaving = substExpr(pSubst, p->pHaving);
    p->pWhere = substExpr(pSubst, p->pWhere);
    pSrc = p->pSrc;
    assert( pSrc!=0 );
    for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
      substSelect(pSubst, pItem->pSelect, 1);
      if( pItem->fg.isTabFunc ){
        substExprList(pSubst, pItem->u1.pFuncArg);
      }
    }
  }while( doPrior && (p = p->pPrior)!=0 );
}
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */

#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/*
** pSelect is a SELECT statement and pSrcItem is one item in the FROM
** clause of that SELECT.
**
** This routine scans the entire SELECT statement and recomputes the
** pSrcItem->colUsed mask.
*/
static int recomputeColumnsUsedExpr(Walker *pWalker, Expr *pExpr){
  SrcItem *pItem;
  if( pExpr->op!=TK_COLUMN ) return WRC_Continue;
  pItem = pWalker->u.pSrcItem;
  if( pItem->iCursor!=pExpr->iTable ) return WRC_Continue;
  if( pExpr->iColumn<0 ) return WRC_Continue;
  pItem->colUsed |= sqlite3ExprColUsed(pExpr);
  return WRC_Continue;
}
static void recomputeColumnsUsed(
  Select *pSelect,                 /* The complete SELECT statement */
  SrcItem *pSrcItem                /* Which FROM clause item to recompute */
){
  Walker w;
  if( NEVER(pSrcItem->pTab==0) ) return;
  memset(&w, 0, sizeof(w));
  w.xExprCallback = recomputeColumnsUsedExpr;
  w.xSelectCallback = sqlite3SelectWalkNoop;
  w.u.pSrcItem = pSrcItem;
  pSrcItem->colUsed = 0;
  sqlite3WalkSelect(&w, pSelect);
}
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */

#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/*
** Assign new cursor numbers to each of the items in pSrc. For each
** new cursor number assigned, set an entry in the aCsrMap[] array 
** to map the old cursor number to the new:
**
**     aCsrMap[iOld+1] = iNew;
**
** The array is guaranteed by the caller to be large enough for all
** existing cursor numbers in pSrc.  aCsrMap[0] is the array size.
**
** If pSrc contains any sub-selects, call this routine recursively
** on the FROM clause of each such sub-select, with iExcept set to -1.
*/
static void srclistRenumberCursors(
  Parse *pParse,                  /* Parse context */
  int *aCsrMap,                   /* Array to store cursor mappings in */
  SrcList *pSrc,                  /* FROM clause to renumber */
  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;
      assert( pItem->iCursor < aCsrMap[0] );
      if( !pItem->fg.isRecursive || aCsrMap[pItem->iCursor+1]==0 ){
        aCsrMap[pItem->iCursor+1] = pParse->nTab++;
      }
      pItem->iCursor = aCsrMap[pItem->iCursor+1];
      for(p=pItem->pSelect; p; p=p->pPrior){
        srclistRenumberCursors(pParse, aCsrMap, p->pSrc, -1);
      }
    }
  }
}

/*
** *piCursor is a cursor number.  Change it if it needs to be mapped.
*/
static void renumberCursorDoMapping(Walker *pWalker, int *piCursor){
  int *aCsrMap = pWalker->u.aiCol;
  int iCsr = *piCursor;
  if( iCsr < aCsrMap[0] && aCsrMap[iCsr+1]>0 ){
    *piCursor = aCsrMap[iCsr+1];
  }
}

/*
** Expression walker callback used by renumberCursors() to update
** Expr objects to match newly assigned cursor numbers.
*/
static int renumberCursorsCb(Walker *pWalker, Expr *pExpr){
  int op = pExpr->op;
  if( op==TK_COLUMN || op==TK_IF_NULL_ROW ){
    renumberCursorDoMapping(pWalker, &pExpr->iTable);
  }
  if( ExprHasProperty(pExpr, EP_OuterON) ){
    renumberCursorDoMapping(pWalker, &pExpr->w.iJoin);
  }
  return WRC_Continue;
}

/*
** Assign a new cursor number to each cursor in the FROM clause (Select.pSrc)
** of the SELECT statement passed as the second argument, and to each 
** cursor in the FROM clause of any FROM clause sub-selects, recursively.
** Except, do not assign a new cursor number to the iExcept'th element in
** the FROM clause of (*p). Update all expressions and other references 
** to refer to the new cursor numbers.
**
** Argument aCsrMap is an array that may be used for temporary working
** space. Two guarantees are made by the caller:
**
**   * the array is larger than the largest cursor number used within the
**     select statement passed as an argument, and
**
**   * the array entries for all cursor numbers that do *not* appear in 
**     FROM clauses of the select statement as described above are 
**     initialized to zero.
*/
static void renumberCursors(
  Parse *pParse,                  /* Parse context */
  Select *p,                      /* Select to renumber cursors within */
  int iExcept,                    /* FROM clause item to skip */
  int *aCsrMap                    /* Working space */
){
  Walker w;
  srclistRenumberCursors(pParse, aCsrMap, p->pSrc, iExcept);
  memset(&w, 0, sizeof(w));
  w.u.aiCol = aCsrMap;
  w.xExprCallback = renumberCursorsCb;
  w.xSelectCallback = sqlite3SelectWalkNoop;
  sqlite3WalkSelect(&w, p);
}
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */

/*
** If pSel is not part of a compound SELECT, return a pointer to its
** expression list. Otherwise, return a pointer to the expression list
** of the leftmost SELECT in the compound.
*/
static ExprList *findLeftmostExprlist(Select *pSel){
  while( pSel->pPrior ){
    pSel = pSel->pPrior;
  }
  return pSel->pEList;
}

/*
** Return true if any of the result-set columns in the compound query
** have incompatible affinities on one or more arms of the compound.
*/
static int compoundHasDifferentAffinities(Select *p){
  int ii;
  ExprList *pList;
  assert( p!=0 );
  assert( p->pEList!=0 );
  assert( p->pPrior!=0 );
  pList = p->pEList;
  for(ii=0; ii<pList->nExpr; ii++){
    char aff;
    Select *pSub1;
    assert( pList->a[ii].pExpr!=0 );
    aff = sqlite3ExprAffinity(pList->a[ii].pExpr);
    for(pSub1=p->pPrior; pSub1; pSub1=pSub1->pPrior){
      assert( pSub1->pEList!=0 );
      assert( pSub1->pEList->nExpr>ii );
      assert( pSub1->pEList->a[ii].pExpr!=0 );
      if( sqlite3ExprAffinity(pSub1->pEList->a[ii].pExpr)!=aff ){
        return 1;
      }
    }
  }
  return 0;
}

#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/*
** This routine attempts to flatten subqueries as a performance optimization.
** This routine returns 1 if it makes changes and 0 if no flattening occurs.
**
** To understand the concept of flattening, consider the following
3565
3566
3567
3568
3569
3570
3571


3572


3573
3574
3575
3576
3577
3578
3579
4175
4176
4177
4178
4179
4180
4181
4182
4183

4184
4185
4186
4187
4188
4189
4190
4191
4192







+
+
-
+
+







**             for flattening.  (This is due to ticket [2f7170d73bf9abf80]
**             from 2015-02-09.)
**
**   (3)  If the subquery is the right operand of a LEFT JOIN then
**        (3a) the subquery may not be a join and
**        (3b) the FROM clause of the subquery may not contain a virtual
**             table and
**        (**) Was: "The outer query may not have a GROUP BY." This case
**             is now managed correctly
**        (3c) the outer query may not be an aggregate.
**        (3d) the outer query may not be DISTINCT.
**        See also (26) for restrictions on RIGHT JOIN.
**
**   (4)  The subquery can not be DISTINCT.
**
**  (**)  At one point restrictions (4) and (5) defined a subset of DISTINCT
**        sub-queries that were excluded from this optimization. Restriction 
**        (4) has since been expanded to exclude all DISTINCT subqueries.
**
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
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669











3670
3671
3672
3673
3674
3675
3676
4227
4228
4229
4230
4231
4232
4233


4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257


4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274



4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306







-
-
+
+
+
+
+
+
+
+
+















-
-
+
+















-
-
-
+
+












+
+
+
+
+
+
+
+
+
+
+







**  (17)  If the subquery is a compound select, then
**        (17a) all compound operators must be a UNION ALL, and
**        (17b) no terms within the subquery compound may be aggregate
**              or DISTINCT, and
**        (17c) every term within the subquery compound must have a FROM clause
**        (17d) the outer query may not be
**              (17d1) aggregate, or
**              (17d2) DISTINCT, or
**              (17d3) a join.
**              (17d2) DISTINCT
**        (17e) the subquery may not contain window functions, and
**        (17f) the subquery must not be the RHS of a LEFT JOIN.
**        (17g) either the subquery is the first element of the outer
**              query or there are no RIGHT or FULL JOINs in any arm
**              of the subquery.  (This is a duplicate of condition (27b).)
**        (17h) The corresponding result set expressions in all arms of the
**              compound must have the same affinity. (See restriction (9)
**              on the push-down optimization.)
**
**        The parent and sub-query may contain WHERE clauses. Subject to
**        rules (11), (13) and (14), they may also contain ORDER BY,
**        LIMIT and OFFSET clauses.  The subquery cannot use any compound
**        operator other than UNION ALL because all the other compound
**        operators have an implied DISTINCT which is disallowed by
**        restriction (4).
**
**        Also, each component of the sub-query must return the same number
**        of result columns. This is actually a requirement for any compound
**        SELECT statement, but all the code here does is make sure that no
**        such (illegal) sub-query is flattened. The caller will detect the
**        syntax error and return a detailed message.
**
**  (18)  If the sub-query is a compound select, then all terms of the
**        ORDER BY clause of the parent must be simple references to 
**        columns of the sub-query.
**        ORDER BY clause of the parent must be copies of a term returned
**        by the parent query.
**
**  (19)  If the subquery uses LIMIT then the outer query may not
**        have a WHERE clause.
**
**  (20)  If the sub-query is a compound select, then it must not use
**        an ORDER BY clause.  Ticket #3773.  We could relax this constraint
**        somewhat by saying that the terms of the ORDER BY clause must
**        appear as unmodified result columns in the outer query.  But we
**        have other optimizations in mind to deal with that case.
**
**  (21)  If the subquery uses LIMIT then the outer query may not be
**        DISTINCT.  (See ticket [752e1646fc]).
**
**  (22)  The subquery may not be a recursive CTE.
**
**  (**)  Subsumed into restriction (17d3).  Was: If the outer query is
**        a recursive CTE, then the sub-query may not be a compound query.
**        This restriction is because transforming the
**  (23)  If the outer query is a recursive CTE, then the sub-query may not be
**        a compound query.  This restriction is because transforming the
**        parent to a compound query confuses the code that handles
**        recursive queries in multiSelect().
**
**  (**)  We no longer attempt to flatten aggregate subqueries.  Was:
**        The subquery may not be an aggregate that uses the built-in min() or 
**        or max() functions.  (Without this restriction, a query like:
**        "SELECT x FROM (SELECT max(y), x FROM t1)" would not necessarily
**        return the value X for which Y was maximal.)
**
**  (25)  If either the subquery or the parent query contains a window
**        function in the select list or ORDER BY clause, flattening
**        is not attempted.
**
**  (26)  The subquery may not be the right operand of a RIGHT JOIN.
**        See also (3) for restrictions on LEFT JOIN.
**
**  (27)  The subquery may not contain a FULL or RIGHT JOIN unless it
**        is the first element of the parent query.  Two subcases:
**        (27a) the subquery is not a compound query.
**        (27b) the subquery is a compound query and the RIGHT JOIN occurs
**              in any arm of the compound query.  (See also (17g).)
**
**  (28)  The subquery is not a MATERIALIZED CTE.
**
**
** In this routine, the "p" parameter is a pointer to the outer query.
** The subquery is p->pSrc->a[iFrom].  isAgg is true if the outer query
** uses aggregates.
**
** If flattening is not attempted, this routine is a no-op and returns 0.
3689
3690
3691
3692
3693
3694
3695
3696

3697
3698
3699

3700


3701
3702
3703
3704
3705
3706
3707
4319
4320
4321
4322
4323
4324
4325

4326
4327
4328

4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339







-
+


-
+

+
+







  Select *pParent;    /* Current UNION ALL term of the other query */
  Select *pSub;       /* The inner query or "subquery" */
  Select *pSub1;      /* Pointer to the rightmost select in sub-query */
  SrcList *pSrc;      /* The FROM clause of the outer query */
  SrcList *pSubSrc;   /* The FROM clause of the subquery */
  int iParent;        /* VDBE cursor number of the pSub result set temp table */
  int iNewParent = -1;/* Replacement table for iParent */
  int isLeftJoin = 0; /* True if pSub is the right side of a LEFT JOIN */    
  int isOuterJoin = 0; /* True if pSub is the right side of a LEFT JOIN */    
  int i;              /* Loop counter */
  Expr *pWhere;                    /* The WHERE clause */
  struct SrcList_item *pSubitem;   /* The subquery */
  SrcItem *pSubitem;               /* The subquery */
  sqlite3 *db = pParse->db;
  Walker w;                        /* Walker to persist agginfo data */
  int *aCsrMap = 0;

  /* Check to see if flattening is permitted.  Return 0 if not.
  */
  assert( p!=0 );
  assert( p->pPrior==0 );
  if( OptimizationDisabled(db, SQLITE_QueryFlattener) ) return 0;
  pSrc = p->pSrc;
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767

3768
3769
3770





3771
3772

3773
3774
3775



3776
3777



3778
3779

3780
3781
3782
3783
3784
3785
3786
3787
3788
3789

3790
3791
3792
3793
3794


3795
3796
3797
3798
3799

3800
3801
3802
3803



3804
3805






3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817



3818
3819
3820
3821



3822
3823


3824
3825
3826






3827
3828

3829
3830
3831
3832
3833
3834
3835











3836
3837
3838
3839
3840
3841
3842
4385
4386
4387
4388
4389
4390
4391





4392
4393

4394



4395
4396
4397
4398
4399
4400
4401
4402
4403


4404
4405
4406


4407
4408
4409


4410

4411

4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422


4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451

4452
4453
4454
4455

4456
4457
4458
4459



4460
4461
4462


4463
4464



4465
4466
4467
4468
4469
4470
4471

4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497







-
-
-
-
-


-
+
-
-
-
+
+
+
+
+


+

-
-
+
+
+
-
-
+
+
+
-
-
+
-

-







+



-
-
+
+





+




+
+
+


+
+
+
+
+
+






-




-
+
+
+

-
-
-
+
+
+
-
-
+
+
-
-
-
+
+
+
+
+
+

-
+







+
+
+
+
+
+
+
+
+
+
+







  **
  ** If we flatten the above, we would get
  **
  **         (t1 LEFT OUTER JOIN t2) JOIN t3
  **
  ** which is not at all the same thing.
  **
  ** If the subquery is the right operand of a LEFT JOIN, then the outer
  ** query cannot be an aggregate. (3c)  This is an artifact of the way
  ** aggregates are processed - there is no mechanism to determine if
  ** the LEFT JOIN table should be all-NULL.
  **
  ** See also tickets #306, #350, and #3300.
  */
  if( (pSubitem->fg.jointype & JT_OUTER)!=0 ){
  if( (pSubitem->fg.jointype & (JT_OUTER|JT_LTORJ))!=0 ){
    isLeftJoin = 1;
    if( pSubSrc->nSrc>1 || isAgg || IsVirtual(pSubSrc->a[0].pTab) ){
      /*  (3a)             (3c)     (3b) */
    if( pSubSrc->nSrc>1                        /* (3a) */
     || IsVirtual(pSubSrc->a[0].pTab)          /* (3b) */
     || (p->selFlags & SF_Distinct)!=0         /* (3d) */
     || (pSubitem->fg.jointype & JT_RIGHT)!=0  /* (26) */
    ){
      return 0;
    }
    isOuterJoin = 1;
  }
#ifdef SQLITE_EXTRA_IFNULLROW
  else if( iFrom>0 && !isAgg ){

  assert( pSubSrc->nSrc>0 );  /* True by restriction (7) */
  if( iFrom>0 && (pSubSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){
    /* Setting isLeftJoin to -1 causes OP_IfNullRow opcodes to be generated for
    ** every reference to any result column from subquery in a join, even
    return 0;   /* Restriction (27a) */
  }
  if( pSubitem->fg.isCte && pSubitem->u2.pCteUse->eM10d==M10d_Yes ){
    ** though they are not necessary.  This will stress-test the OP_IfNullRow 
    ** opcode. */
    return 0;       /* (28) */
    isLeftJoin = -1;
  }
#endif

  /* Restriction (17): If the sub-query is a compound SELECT, then it must
  ** use only the UNION ALL operator. And none of the simple select queries
  ** that make up the compound SELECT are allowed to be aggregate or distinct
  ** queries.
  */
  if( pSub->pPrior ){
    int ii;
    if( pSub->pOrderBy ){
      return 0;  /* Restriction (20) */
    }
    if( isAgg || (p->selFlags & SF_Distinct)!=0 || pSrc->nSrc!=1 ){
      return 0; /* (17d1), (17d2), or (17d3) */
    if( isAgg || (p->selFlags & SF_Distinct)!=0 || isOuterJoin>0 ){
      return 0; /* (17d1), (17d2), or (17f) */
    }
    for(pSub1=pSub; pSub1; pSub1=pSub1->pPrior){
      testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct );
      testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate );
      assert( pSub->pSrc!=0 );
      assert( (pSub->selFlags & SF_Recursive)==0 );
      assert( pSub->pEList->nExpr==pSub1->pEList->nExpr );
      if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0    /* (17b) */
       || (pSub1->pPrior && pSub1->op!=TK_ALL)                 /* (17a) */
       || pSub1->pSrc->nSrc<1                                  /* (17c) */
#ifndef SQLITE_OMIT_WINDOWFUNC
       || pSub1->pWin                                          /* (17e) */
#endif
      ){
        return 0;
      }
      if( iFrom>0 && (pSub1->pSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){
        /* Without this restriction, the JT_LTORJ flag would end up being
        ** omitted on left-hand tables of the right join that is being
        ** flattened. */
        return 0;   /* Restrictions (17g), (27b) */
      }
      testcase( pSub1->pSrc->nSrc>1 );
    }

    /* Restriction (18). */
    if( p->pOrderBy ){
      int ii;
      for(ii=0; ii<p->pOrderBy->nExpr; ii++){
        if( p->pOrderBy->a[ii].u.x.iOrderByCol==0 ) return 0;
      }
    }
  }

    /* Restriction (23) */
    if( (p->selFlags & SF_Recursive) ) return 0;

  /* Ex-restriction (23):
  ** The only way that the recursive part of a CTE can contain a compound
  ** subquery is for the subquery to be one term of a join.  But if the
    /* Restriction (17h) */
    if( compoundHasDifferentAffinities(pSub) ) return 0;

  ** subquery is a join, then the flattening has already been stopped by
  ** restriction (17d3)
    if( pSrc->nSrc>1 ){
      if( pParse->nSelect>500 ) return 0;
  */
  assert( (p->selFlags & SF_Recursive)==0 || pSub->pPrior==0 );

      if( OptimizationDisabled(db, SQLITE_FlttnUnionAll) ) return 0;
      aCsrMap = sqlite3DbMallocZero(db, ((i64)pParse->nTab+1)*sizeof(int));
      if( aCsrMap ) aCsrMap[0] = pParse->nTab;
    }
  }

  /***** If we reach this point, flattening is permitted. *****/
  SELECTTRACE(1,pParse,p,("flatten %u.%p from term %d\n",
  TREETRACE(0x4,pParse,p,("flatten %u.%p from term %d\n",
                   pSub->selId, pSub, iFrom));

  /* Authorize the subquery */
  pParse->zAuthContext = pSubitem->zName;
  TESTONLY(i =) sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0);
  testcase( i==SQLITE_DENY );
  pParse->zAuthContext = zSavedAuthContext;

  /* Delete the transient structures associated with thesubquery */
  pSub1 = pSubitem->pSelect;
  sqlite3DbFree(db, pSubitem->zDatabase);
  sqlite3DbFree(db, pSubitem->zName);
  sqlite3DbFree(db, pSubitem->zAlias);
  pSubitem->zDatabase = 0;
  pSubitem->zName = 0;
  pSubitem->zAlias = 0;
  pSubitem->pSelect = 0;
  assert( pSubitem->fg.isUsing!=0 || pSubitem->u3.pOn==0 );

  /* If the sub-query is a compound SELECT statement, then (by restrictions
  ** 17 and 18 above) it must be a UNION ALL and the parent query must 
  ** be of the form:
  **
  **     SELECT <expr-list> FROM (<sub-query>) <where-clause> 
  **
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
3899
3900
3901


3902
3903
3904
3905
3906

3907
3908
3909

3910
3911



3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923


3924
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
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
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010

4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032


4033




4034



4035
4036
4037
4038
4039
4040

4041

4042
4043
4044
4045
4046


4047
4048


4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059






4060
4061
4062
4063
4064


4065
4066
4067
4068
4069



4070
4071
4072
4073
4074
4075
4076
4077
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
4107
4108




4109
4110
4111



4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135






4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146

4147
4148
4149
4150
4151

4152
4153


4154
4155
4156
4157
4158

4159
4160
4161
4162
4163
4164
4165
4166







4167
4168





4169
4170

4171
4172
4173






4174
4175
4176
4177
4178



4179
4180
4181
4182
4183
4184

4185
4186
4187
4188
4189
4190




































4191
4192
4193
4194
4195
4196



4197
4198
4199
4200
4201
4202
4203
4204
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532

4533
4534
4535
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
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574


4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605



4606
4607








4608
4609

4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625

4626


4627

4628
4629
4630
4631
4632
4633
4634
4635



4636
4637
4638
4639
4640
4641
4642
4643

4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657

4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678


4679
4680
4681
4682
4683
4684
4685

4686
4687
4688
4689
4690
4691
4692
4693

4694
4695
4696
4697
4698
4699


4700
4701


4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729



4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758

4759
4760
4761
4762
4763
4764
4765



4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783




4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801

4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814


4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830

4831





4832


4833
4834





4835
4836
4837
4838
4839




4840
4841
4842
4843
4844
4845
4846
4847

4848
4849
4850
4851
4852
4853

4854
4855


4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921



4922
4923
4924

4925
4926
4927
4928
4929
4930
4931







+
+

-





-

+



+
+
+
+




-
+


-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
+
-
-
-
+
-
-
+
+
+












+
+
-
-
+
+



















+



+
+




-
-
-
+
+
-
-
-
-
-
-
-
-
+
+
-
















-
+
-
-
+
-
+






+
-
-
-
+
+
+
+



+
-
+













-
+




















-
-
+
+

+
+
+
+
-
+
+
+





-
+

+



-
-
+
+
-
-
+
+











+
+
+
+
+
+





+
+


-
-
-
+
+
+















+


+
+
+





-
+
+
+
+
+


-
-
-
+
+
+
+



+
+
+
+
+
+
+




-
-
-
-
+
+
+
+



+
+
+








-













-
-
+
+
+
+
+
+










-
+
-
-
-
-
-
+
-
-
+
+
-
-
-
-
-
+




-
-
-
-
+
+
+
+
+
+
+

-
+
+
+
+
+

-
+

-
-
+
+
+
+
+
+





+
+
+






+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
-
-
+
+
+
-







  ** We call this the "compound-subquery flattening".
  */
  for(pSub=pSub->pPrior; pSub; pSub=pSub->pPrior){
    Select *pNew;
    ExprList *pOrderBy = p->pOrderBy;
    Expr *pLimit = p->pLimit;
    Select *pPrior = p->pPrior;
    Table *pItemTab = pSubitem->pTab;
    pSubitem->pTab = 0;
    p->pOrderBy = 0;
    p->pSrc = 0;
    p->pPrior = 0;
    p->pLimit = 0;
    pNew = sqlite3SelectDup(db, p, 0);
    p->pLimit = pLimit;
    p->pOrderBy = pOrderBy;
    p->pSrc = pSrc;
    p->op = TK_ALL;
    pSubitem->pTab = pItemTab;
    if( pNew==0 ){
      p->pPrior = pPrior;
    }else{
      pNew->selId = ++pParse->nSelect;
      if( aCsrMap && ALWAYS(db->mallocFailed==0) ){
        renumberCursors(pParse, pNew, iFrom, aCsrMap);
      }
      pNew->pPrior = pPrior;
      if( pPrior ) pPrior->pNext = pNew;
      pNew->pNext = p;
      p->pPrior = pNew;
      SELECTTRACE(2,pParse,p,("compound-subquery flattener"
      TREETRACE(0x4,pParse,p,("compound-subquery flattener"
                              " creates %u as peer\n",pNew->selId));
    }
    if( db->mallocFailed ) return 1;
  }

  /* Begin flattening the iFrom-th entry of the FROM clause 
  ** in the outer query.
  */
  pSub = pSub1 = pSubitem->pSelect;

    assert( pSubitem->pSelect==0 );
  }
  /* Delete the transient table structure associated with the
  ** subquery
  */
  sqlite3DbFree(db, pSubitem->zDatabase);
  sqlite3DbFree(db, pSubitem->zName);
  sqlite3DbFree(db, aCsrMap);
  sqlite3DbFree(db, pSubitem->zAlias);
  pSubitem->zDatabase = 0;
  pSubitem->zName = 0;
  if( db->mallocFailed ){
  pSubitem->zAlias = 0;
  pSubitem->pSelect = 0;
    pSubitem->pSelect = pSub1;
    return 1;
  }

  /* Defer deleting the Table object associated with the
  ** subquery until code generation is
  ** complete, since there may still exist Expr.pTab entries that
  ** refer to the subquery even after flattening.  Ticket #3346.
  **
  ** pSubitem->pTab is always non-NULL by test restrictions and tests above.
  */
  if( ALWAYS(pSubitem->pTab!=0) ){
    Table *pTabToDel = pSubitem->pTab;
    if( pTabToDel->nTabRef==1 ){
      Parse *pToplevel = sqlite3ParseToplevel(pParse);
      sqlite3ParserAddCleanup(pToplevel, 
         (void(*)(sqlite3*,void*))sqlite3DeleteTable,
      pTabToDel->pNextZombie = pToplevel->pZombieTab;
      pToplevel->pZombieTab = pTabToDel;
         pTabToDel);
      testcase( pToplevel->earlyCleanup );
    }else{
      pTabToDel->nTabRef--;
    }
    pSubitem->pTab = 0;
  }

  /* The following loop runs once for each term in a compound-subquery
  ** flattening (as described above).  If we are doing a different kind
  ** of flattening - a flattening other than a compound-subquery flattening -
  ** then this loop only runs once.
  **
  ** This loop moves all of the FROM elements of the subquery into the
  ** the FROM clause of the outer query.  Before doing this, remember
  ** the cursor number for the original outer query FROM element in
  ** iParent.  The iParent cursor will never be used.  Subsequent code
  ** will scan expressions looking for iParent references and replace
  ** those references with expressions that resolve to the subquery FROM
  ** elements we are now copying in.
  */
  pSub = pSub1;
  for(pParent=p; pParent; pParent=pParent->pPrior, pSub=pSub->pPrior){
    int nSubSrc;
    u8 jointype = 0;
    u8 ltorj = pSrc->a[iFrom].fg.jointype & JT_LTORJ;
    assert( pSub!=0 );
    pSubSrc = pSub->pSrc;     /* FROM clause of subquery */
    nSubSrc = pSubSrc->nSrc;  /* Number of terms in subquery FROM clause */
    pSrc = pParent->pSrc;     /* FROM clause of the outer query */

    if( pSrc ){
      assert( pParent==p );  /* First time through the loop */
      jointype = pSubitem->fg.jointype;
    if( pParent==p ){
      jointype = pSubitem->fg.jointype;     /* First time through the loop */
    }else{
      assert( pParent!=p );  /* 2nd and subsequent times through the loop */
      pSrc = pParent->pSrc = sqlite3SrcListAppend(db, 0, 0, 0);
      if( pSrc==0 ){
        assert( db->mallocFailed );
        break;
      }
    }
    }
    

    /* The subquery uses a single slot of the FROM clause of the outer
    ** query.  If the subquery has more than one element in its FROM clause,
    ** then expand the outer query to make space for it to hold all elements
    ** of the subquery.
    **
    ** Example:
    **
    **    SELECT * FROM tabA, (SELECT * FROM sub1, sub2), tabB;
    **
    ** The outer query has 3 slots in its FROM clause.  One slot of the
    ** outer query (the middle slot) is used by the subquery.  The next
    ** block of code will expand the outer query FROM clause to 4 slots.
    ** The middle slot is expanded to two slots in order to make space
    ** for the two elements in the FROM clause of the subquery.
    */
    if( nSubSrc>1 ){
      pParent->pSrc = pSrc = sqlite3SrcListEnlarge(db, pSrc, nSubSrc-1,iFrom+1);
      pSrc = sqlite3SrcListEnlarge(pParse, pSrc, nSubSrc-1,iFrom+1);
      if( db->mallocFailed ){
        break;
      if( pSrc==0 ) break;
      }
      pParent->pSrc = pSrc;
    }

    /* Transfer the FROM clause terms from the subquery into the
    ** outer query.
    */
    for(i=0; i<nSubSrc; i++){
      SrcItem *pItem = &pSrc->a[i+iFrom];
      sqlite3IdListDelete(db, pSrc->a[i+iFrom].pUsing);
      assert( pSrc->a[i+iFrom].fg.isTabFunc==0 );
      pSrc->a[i+iFrom] = pSubSrc->a[i];
      if( pItem->fg.isUsing ) sqlite3IdListDelete(db, pItem->u3.pUsing);
      assert( pItem->fg.isTabFunc==0 );
      *pItem = pSubSrc->a[i];
      pItem->fg.jointype |= ltorj;
      iNewParent = pSubSrc->a[i].iCursor;
      memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
    }
    pSrc->a[iFrom].fg.jointype &= JT_LTORJ;
    pSrc->a[iFrom].fg.jointype = jointype;
    pSrc->a[iFrom].fg.jointype |= jointype | ltorj;
  
    /* Now begin substituting subquery result set expressions for 
    ** references to the iParent in the outer query.
    ** 
    ** Example:
    **
    **   SELECT a+5, b*10 FROM (SELECT x*3 AS a, y+10 AS b FROM t1) WHERE a>b;
    **   \                     \_____________ subquery __________/          /
    **    \_____________________ outer query ______________________________/
    **
    ** We look at every expression in the outer query and every place we see
    ** "a" we substitute "x*3" and every place we see "b" we substitute "y+10".
    */
    if( pSub->pOrderBy ){
    if( pSub->pOrderBy && (pParent->selFlags & SF_NoopOrderBy)==0 ){
      /* At this point, any non-zero iOrderByCol values indicate that the
      ** ORDER BY column expression is identical to the iOrderByCol'th
      ** expression returned by SELECT statement pSub. Since these values
      ** do not necessarily correspond to columns in SELECT statement pParent,
      ** zero them before transfering the ORDER BY clause.
      **
      ** Not doing this may cause an error if a subsequent call to this
      ** function attempts to flatten a compound sub-query into pParent
      ** (the only way this can happen is if the compound sub-query is
      ** currently part of pSub->pSrc). See ticket [d11a6e908f].  */
      ExprList *pOrderBy = pSub->pOrderBy;
      for(i=0; i<pOrderBy->nExpr; i++){
        pOrderBy->a[i].u.x.iOrderByCol = 0;
      }
      assert( pParent->pOrderBy==0 );
      pParent->pOrderBy = pOrderBy;
      pSub->pOrderBy = 0;
    }
    pWhere = pSub->pWhere;
    pSub->pWhere = 0;
    if( isLeftJoin>0 ){
      setJoinExpr(pWhere, iNewParent);
    if( isOuterJoin>0 ){
      sqlite3SetJoinExpr(pWhere, iNewParent, EP_OuterON);
    }
    if( pWhere ){
      if( pParent->pWhere ){
        pParent->pWhere = sqlite3PExpr(pParse, TK_AND, pWhere, pParent->pWhere);
      }else{
    pParent->pWhere = sqlite3ExprAnd(db, pWhere, pParent->pWhere);
        pParent->pWhere = pWhere;
      }
    }
    if( db->mallocFailed==0 ){
      SubstContext x;
      x.pParse = pParse;
      x.iTable = iParent;
      x.iNewTable = iNewParent;
      x.isLeftJoin = isLeftJoin;
      x.isOuterJoin = isOuterJoin;
      x.pEList = pSub->pEList;
      x.pCList = findLeftmostExprlist(pSub);
      substSelect(&x, pParent, 0);
    }
  
    /* The flattened query is distinct if either the inner or the
    ** outer query is distinct. 
    /* The flattened query is a compound if either the inner or the
    ** outer query is a compound. */
    */
    pParent->selFlags |= pSub->selFlags & SF_Distinct;
    pParent->selFlags |= pSub->selFlags & SF_Compound;
    assert( (pSub->selFlags & SF_Distinct)==0 ); /* restriction (17b) */
  
    /*
    ** SELECT ... FROM (SELECT ... LIMIT a OFFSET b) LIMIT x OFFSET y;
    **
    ** One is tempted to try to add a and b to combine the limits.  But this
    ** does not work if either limit is negative.
    */
    if( pSub->pLimit ){
      pParent->pLimit = pSub->pLimit;
      pSub->pLimit = 0;
    }

    /* Recompute the SrcItem.colUsed masks for the flattened
    ** tables. */
    for(i=0; i<nSubSrc; i++){
      recomputeColumnsUsed(pParent, &pSrc->a[i+iFrom]);
    }
  }

  /* Finially, delete what is left of the subquery and return
  ** success.
  */
  sqlite3AggInfoPersistWalkerInit(&w, pParse);
  sqlite3WalkSelect(&w,pSub1);
  sqlite3SelectDelete(db, pSub1);

#if SELECTTRACE_ENABLED
  if( sqlite3SelectTrace & 0x100 ){
    SELECTTRACE(0x100,pParse,p,("After flattening:\n"));
#if TREETRACE_ENABLED
  if( sqlite3TreeTrace & 0x4 ){
    TREETRACE(0x4,pParse,p,("After flattening:\n"));
    sqlite3TreeViewSelect(0, p, 0);
  }
#endif

  return 1;
}
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */

/*
** A structure to keep track of all of the column values that are fixed to
** a known value due to WHERE clause constraints of the form COLUMN=VALUE.
*/
typedef struct WhereConst WhereConst;
struct WhereConst {
  Parse *pParse;   /* Parsing context */
  u8 *pOomFault;   /* Pointer to pParse->db->mallocFailed */
  int nConst;      /* Number for COLUMN=CONSTANT terms */
  int nChng;       /* Number of times a constant is propagated */
  int bHasAffBlob; /* At least one column in apExpr[] as affinity BLOB */
  u32 mExcludeOn;  /* Which ON expressions to exclude from considertion.
                   ** Either EP_OuterON or EP_InnerON|EP_OuterON */
  Expr **apExpr;   /* [i*2] is COLUMN and [i*2+1] is VALUE */
};

/*
** Add a new entry to the pConst object.  Except, do not add duplicate
** pColumn entires.
** pColumn entires.  Also, do not add if doing so would not be appropriate.
**
** The caller guarantees the pColumn is a column and pValue is a constant.
** This routine has to do some additional checks before completing the
** insert.
*/
static void constInsert(
  WhereConst *pConst,      /* The WhereConst into which we are inserting */
  Expr *pColumn,           /* The COLUMN part of the constraint */
  Expr *pValue             /* The VALUE part of the constraint */
  WhereConst *pConst,  /* The WhereConst into which we are inserting */
  Expr *pColumn,       /* The COLUMN part of the constraint */
  Expr *pValue,        /* The VALUE part of the constraint */
  Expr *pExpr          /* Overall expression: COLUMN=VALUE or VALUE=COLUMN */
){
  int i;
  assert( pColumn->op==TK_COLUMN );
  assert( sqlite3ExprIsConstant(pValue) );

  if( ExprHasProperty(pColumn, EP_FixedCol) ) return;
  if( sqlite3ExprAffinity(pValue)!=0 ) return;
  if( !sqlite3IsBinary(sqlite3ExprCompareCollSeq(pConst->pParse,pExpr)) ){
    return;
  }

  /* 2018-10-25 ticket [cf5ed20f]
  ** Make sure the same pColumn is not inserted more than once */
  for(i=0; i<pConst->nConst; i++){
    const Expr *pExpr = pConst->apExpr[i*2];
    assert( pExpr->op==TK_COLUMN );
    if( pExpr->iTable==pColumn->iTable
     && pExpr->iColumn==pColumn->iColumn
    const Expr *pE2 = pConst->apExpr[i*2];
    assert( pE2->op==TK_COLUMN );
    if( pE2->iTable==pColumn->iTable
     && pE2->iColumn==pColumn->iColumn
    ){
      return;  /* Already present.  Return without doing anything. */
    }
  }
  if( sqlite3ExprAffinity(pColumn)==SQLITE_AFF_BLOB ){
    pConst->bHasAffBlob = 1;
  }

  pConst->nConst++;
  pConst->apExpr = sqlite3DbReallocOrFree(pConst->pParse->db, pConst->apExpr,
                         pConst->nConst*2*sizeof(Expr*));
  if( pConst->apExpr==0 ){
    pConst->nConst = 0;
  }else{
    if( ExprHasProperty(pValue, EP_FixedCol) ) pValue = pValue->pLeft;
    pConst->apExpr[pConst->nConst*2-2] = pColumn;
    pConst->apExpr[pConst->nConst*2-1] = pValue;
  }
}

/*
** Find all terms of COLUMN=VALUE or VALUE=COLUMN in pExpr where VALUE
** is a constant expression and where the term must be true because it
** is part of the AND-connected terms of the expression.  For each term
** found, add it to the pConst structure.
*/
static void findConstInWhere(WhereConst *pConst, Expr *pExpr){
  Expr *pRight, *pLeft;
  if( pExpr==0 ) return;
  if( ExprHasProperty(pExpr, EP_FromJoin) ) return;
  if( NEVER(pExpr==0) ) return;
  if( ExprHasProperty(pExpr, pConst->mExcludeOn) ){
    testcase( ExprHasProperty(pExpr, EP_OuterON) );
    testcase( ExprHasProperty(pExpr, EP_InnerON) );
    return;
  }
  if( pExpr->op==TK_AND ){
    findConstInWhere(pConst, pExpr->pRight);
    findConstInWhere(pConst, pExpr->pLeft);
    return;
  }
  if( pExpr->op!=TK_EQ ) return;
  pRight = pExpr->pRight;
  pLeft = pExpr->pLeft;
  assert( pRight!=0 );
  assert( pLeft!=0 );
  if( pRight->op==TK_COLUMN
  if( pRight->op==TK_COLUMN && sqlite3ExprIsConstant(pLeft) ){
   && !ExprHasProperty(pRight, EP_FixedCol)
   && sqlite3ExprIsConstant(pLeft)
   && sqlite3IsBinary(sqlite3BinaryCompareCollSeq(pConst->pParse,pLeft,pRight))
  ){
    constInsert(pConst, pRight, pLeft);
    constInsert(pConst,pRight,pLeft,pExpr);
  }else
  if( pLeft->op==TK_COLUMN
  }
  if( pLeft->op==TK_COLUMN && sqlite3ExprIsConstant(pRight) ){
   && !ExprHasProperty(pLeft, EP_FixedCol)
   && sqlite3ExprIsConstant(pRight)
   && sqlite3IsBinary(sqlite3BinaryCompareCollSeq(pConst->pParse,pLeft,pRight))
  ){
    constInsert(pConst, pLeft, pRight);
    constInsert(pConst,pLeft,pRight,pExpr);
  }
}

/*
** This is a Walker expression callback.  pExpr is a candidate expression
** to be replaced by a value.  If pExpr is equivalent to one of the
** columns named in pWalker->u.pConst, then overwrite it with its
** corresponding value.
** This is a helper function for Walker callback propagateConstantExprRewrite().
**
** Argument pExpr is a candidate expression to be replaced by a value. If 
** pExpr is equivalent to one of the columns named in pWalker->u.pConst, 
** then overwrite it with the corresponding value. Except, do not do so
** if argument bIgnoreAffBlob is non-zero and the affinity of pExpr
** is SQLITE_AFF_BLOB.
*/
static int propagateConstantExprRewrite(Walker *pWalker, Expr *pExpr){
static int propagateConstantExprRewriteOne(
  WhereConst *pConst,
  Expr *pExpr, 
  int bIgnoreAffBlob
){
  int i;
  WhereConst *pConst;
  if( pConst->pOomFault[0] ) return WRC_Prune;
  if( pExpr->op!=TK_COLUMN ) return WRC_Continue;
  if( ExprHasProperty(pExpr, EP_FixedCol) ) return WRC_Continue;
  pConst = pWalker->u.pConst;
  if( ExprHasProperty(pExpr, EP_FixedCol|pConst->mExcludeOn) ){
    testcase( ExprHasProperty(pExpr, EP_FixedCol) );
    testcase( ExprHasProperty(pExpr, EP_OuterON) );
    testcase( ExprHasProperty(pExpr, EP_InnerON) );
    return WRC_Continue;
  }
  for(i=0; i<pConst->nConst; i++){
    Expr *pColumn = pConst->apExpr[i*2];
    if( pColumn==pExpr ) continue;
    if( pColumn->iTable!=pExpr->iTable ) continue;
    if( pColumn->iColumn!=pExpr->iColumn ) continue;
    if( bIgnoreAffBlob && sqlite3ExprAffinity(pColumn)==SQLITE_AFF_BLOB ){
      break;
    }
    /* A match is found.  Add the EP_FixedCol property */
    pConst->nChng++;
    ExprClearProperty(pExpr, EP_Leaf);
    ExprSetProperty(pExpr, EP_FixedCol);
    assert( pExpr->pLeft==0 );
    pExpr->pLeft = sqlite3ExprDup(pConst->pParse->db, pConst->apExpr[i*2+1], 0);
    if( pConst->pParse->db->mallocFailed ) return WRC_Prune;
    break;
  }
  return WRC_Prune;
}

/*
** This is a Walker expression callback. pExpr is a node from the WHERE
** clause of a SELECT statement. This function examines pExpr to see if
** any substitutions based on the contents of pWalker->u.pConst should
** be made to pExpr or its immediate children.
**
** A substitution is made if:
**
**   + pExpr is a column with an affinity other than BLOB that matches
**     one of the columns in pWalker->u.pConst, or
**
**   + pExpr is a binary comparison operator (=, <=, >=, <, >) that
**     uses an affinity other than TEXT and one of its immediate
**     children is a column that matches one of the columns in 
**     pWalker->u.pConst.
*/
static int propagateConstantExprRewrite(Walker *pWalker, Expr *pExpr){
  WhereConst *pConst = pWalker->u.pConst;
  assert( TK_GT==TK_EQ+1 );
  assert( TK_LE==TK_EQ+2 );
  assert( TK_LT==TK_EQ+3 );
  assert( TK_GE==TK_EQ+4 );
  if( pConst->bHasAffBlob ){
    if( (pExpr->op>=TK_EQ && pExpr->op<=TK_GE)
     || pExpr->op==TK_IS
    ){
      propagateConstantExprRewriteOne(pConst, pExpr->pLeft, 0);
      if( pConst->pOomFault[0] ) return WRC_Prune;
      if( sqlite3ExprAffinity(pExpr->pLeft)!=SQLITE_AFF_TEXT ){
        propagateConstantExprRewriteOne(pConst, pExpr->pRight, 0);
      }
    }
  }
  return propagateConstantExprRewriteOne(pConst, pExpr, pConst->bHasAffBlob);
}

/*
** The WHERE-clause constant propagation optimization.
**
** If the WHERE clause contains terms of the form COLUMN=CONSTANT or
** CONSTANT=COLUMN that must be tree (in other words, if the terms top-level
** AND-connected terms that are not part of a ON clause from a LEFT JOIN)
** then throughout the query replace all other occurrences of COLUMN
** CONSTANT=COLUMN that are top-level AND-connected terms that are not
** part of a ON clause from a LEFT JOIN, then throughout the query
** replace all other occurrences of COLUMN with CONSTANT.
** with CONSTANT within the WHERE clause.
**
** For example, the query:
**
**      SELECT * FROM t1, t2, t3 WHERE t1.a=39 AND t2.b=t1.a AND t3.c=t2.b
**
** Is transformed into
**
4219
4220
4221
4222
4223
4224
4225















4226
4227
4228
4229
4230
4231
4232
4233
4234

4235
4236
4237
4238












4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255





























4256
4257
4258
4259
4260
4261
4262
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
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
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+









+




+
+
+
+
+
+
+
+
+
+
+
+

















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







** is false because it uses text affinity and '0123' is not the same as '123'.
** To work around this, the expression tree is not actually changed from
** "b=a" to "b=123" but rather the "a" in "b=a" is tagged with EP_FixedCol
** and the "123" value is hung off of the pLeft pointer.  Code generator
** routines know to generate the constant "123" instead of looking up the
** column value.  Also, to avoid collation problems, this optimization is
** only attempted if the "a=123" term uses the default BINARY collation.
**
** 2021-05-25 forum post 6a06202608: Another troublesome case is...
**
**    CREATE TABLE t1(x);
**    INSERT INTO t1 VALUES(10.0);
**    SELECT 1 FROM t1 WHERE x=10 AND x LIKE 10;
**
** The query should return no rows, because the t1.x value is '10.0' not '10'
** and '10.0' is not LIKE '10'.  But if we are not careful, the first WHERE
** term "x=10" will cause the second WHERE term to become "10 LIKE 10",
** resulting in a false positive.  To avoid this, constant propagation for
** columns with BLOB affinity is only allowed if the constant is used with
** operators ==, <=, <, >=, >, or IS in a way that will cause the correct
** type conversions to occur.  See logic associated with the bHasAffBlob flag
** for details.
*/
static int propagateConstants(
  Parse *pParse,   /* The parsing context */
  Select *p        /* The query in which to propagate constants */
){
  WhereConst x;
  Walker w;
  int nChng = 0;
  x.pParse = pParse;
  x.pOomFault = &pParse->db->mallocFailed;
  do{
    x.nConst = 0;
    x.nChng = 0;
    x.apExpr = 0;
    x.bHasAffBlob = 0;
    if( ALWAYS(p->pSrc!=0)
     && p->pSrc->nSrc>0
     && (p->pSrc->a[0].fg.jointype & JT_LTORJ)!=0
    ){
      /* Do not propagate constants on any ON clause if there is a
      ** RIGHT JOIN anywhere in the query */
      x.mExcludeOn = EP_InnerON | EP_OuterON;
    }else{
      /* Do not propagate constants through the ON clause of a LEFT JOIN */
      x.mExcludeOn = EP_OuterON;
    }
    findConstInWhere(&x, p->pWhere);
    if( x.nConst ){
      memset(&w, 0, sizeof(w));
      w.pParse = pParse;
      w.xExprCallback = propagateConstantExprRewrite;
      w.xSelectCallback = sqlite3SelectWalkNoop;
      w.xSelectCallback2 = 0;
      w.walkerDepth = 0;
      w.u.pConst = &x;
      sqlite3WalkExpr(&w, p->pWhere);
      sqlite3DbFree(x.pParse->db, x.apExpr);
      nChng += x.nChng;
    }
  }while( x.nChng );  
  return nChng;
}

#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
# if !defined(SQLITE_OMIT_WINDOWFUNC)
/*
** This function is called to determine whether or not it is safe to
** push WHERE clause expression pExpr down to FROM clause sub-query
** pSubq, which contains at least one window function. Return 1
** if it is safe and the expression should be pushed down, or 0 
** otherwise.
**
** It is only safe to push the expression down if it consists only 
** of constants and copies of expressions that appear in the PARTITION
** BY clause of all window function used by the sub-query. It is safe
** to filter out entire partitions, but not rows within partitions, as
** this may change the results of the window functions.
**
** At the time this function is called it is guaranteed that 
**
**   * the sub-query uses only one distinct window frame, and 
**   * that the window frame has a PARTITION BY clase.
*/
static int pushDownWindowCheck(Parse *pParse, Select *pSubq, Expr *pExpr){
  assert( pSubq->pWin->pPartition );
  assert( (pSubq->selFlags & SF_MultiPart)==0 );
  assert( pSubq->pPrior==0 );
  return sqlite3ExprIsConstantOrGroupBy(pParse, pExpr, pSubq->pWin->pPartition);
}
# endif /* SQLITE_OMIT_WINDOWFUNC */
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */

#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/*
** Make copies of relevant WHERE clause terms of the outer query into
** the WHERE clause of subquery.  Example:
**
**    SELECT * FROM (SELECT a AS x, c-d AS y FROM t1) WHERE x=5 AND y=10;
**
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305



























4306
4307
4308
4309
4310
4311
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
4360
4361

4362
4363
4364
4365



4366

4367








4368
4369

4370
4371

4372
4373
4374
4375
4376
4377
4378
5080
5081
5082
5083
5084
5085
5086



5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121

5122

5123
5124
5125
5126
5127
5128
5129


5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140

5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185

5186

5187
5188
5189
5190
5191


5192
5193
5194
5195
5196

5197
5198
5199
5200
5201
5202
5203

5204
5205
5206
5207
5208
5209

5210
5211



5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226

5227
5228

5229
5230
5231
5232
5233
5234
5235
5236







-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








-
+
-




+
+
+
-
-
+
+
+
+
+
+
+
+
+
+

-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


















-
+
-


+
+

-
-
+
+



-
+
+
+


+
+
-
+

+



-
+

-
-
-
+
+
+

+

+
+
+
+
+
+
+
+

-
+

-
+







**           JOIN (SELECT 1 AS b2 UNION ALL SELECT 2) AS bb ON (a1=b2)
**           LEFT JOIN (SELECT 8 AS c3 UNION ALL SELECT 9) AS cc ON (b2=2);
**
**       The correct answer is three rows:  (1,1,NULL),(2,2,8),(2,2,9).
**       But if the (b2=2) term were to be pushed down into the bb subquery,
**       then the (1,1,NULL) row would be suppressed.
**
**   (6) The inner query features one or more window-functions (since 
**       changes to the WHERE clause of the inner query could change the 
**       window over which window functions are calculated).
**   (6) Window functions make things tricky as changes to the WHERE clause 
**       of the inner query could change the window over which window 
**       functions are calculated. Therefore, do not attempt the optimization
**       if:
**
**     (6a) The inner query uses multiple incompatible window partitions.
**
**     (6b) The inner query is a compound and uses window-functions. 
**
**     (6c) The WHERE clause does not consist entirely of constants and
**          copies of expressions found in the PARTITION BY clause of
**          all window-functions used by the sub-query. It is safe to
**          filter out entire partitions, as this does not change the 
**          window over which any window-function is calculated.
**
**   (7) The inner query is a Common Table Expression (CTE) that should
**       be materialized.  (This restriction is implemented in the calling
**       routine.)
**
**   (8) If the subquery is a compound that uses UNION, INTERSECT,
**       or EXCEPT, then all of the result set columns for all arms of
**       the compound must use the BINARY collating sequence.
**
**   (9) If the subquery is a compound, then all arms of the compound must
**       have the same affinity.  (This is the same as restriction (17h)
**       for query flattening.)
**       
**
** Return 0 if no changes are made and non-zero if one or more WHERE clause
** terms are duplicated into the subquery.
*/
static int pushDownWhereTerms(
  Parse *pParse,        /* Parse context (for malloc() and error reporting) */
  Select *pSubq,        /* The subquery whose WHERE clause is to be augmented */
  Expr *pWhere,         /* The WHERE clause of the outer query */
  int iCursor,          /* Cursor number of the subquery */
  SrcItem *pSrc         /* The subquery term of the outer FROM clause */
  int isLeftJoin        /* True if pSubq is the right term of a LEFT JOIN */
){
  Expr *pNew;
  int nChng = 0;
  if( pWhere==0 ) return 0;
  if( pSubq->selFlags & (SF_Recursive|SF_MultiPart) ) return 0;
  if( pSrc->fg.jointype & (JT_LTORJ|JT_RIGHT) ) return 0;

  if( pSubq->selFlags & SF_Recursive ) return 0;  /* restriction (2) */

  if( pSubq->pPrior ){
    Select *pSel;
    int notUnionAll = 0;
    for(pSel=pSubq; pSel; pSel=pSel->pPrior){
      u8 op = pSel->op;
      assert( op==TK_ALL || op==TK_SELECT 
           || op==TK_UNION || op==TK_INTERSECT || op==TK_EXCEPT );
      if( op!=TK_ALL && op!=TK_SELECT ){
        notUnionAll = 1;
      }
#ifndef SQLITE_OMIT_WINDOWFUNC
  if( pSubq->pWin ) return 0;    /* restriction (6) */
      if( pSel->pWin ) return 0;    /* restriction (6b) */
#endif
    }
    if( compoundHasDifferentAffinities(pSubq) ){
      return 0;  /* restriction (9) */
    }
    if( notUnionAll ){
      /* If any of the compound arms are connected using UNION, INTERSECT,
      ** or EXCEPT, then we must ensure that none of the columns use a
      ** non-BINARY collating sequence. */
      for(pSel=pSubq; pSel; pSel=pSel->pPrior){
        int ii;
        const ExprList *pList = pSel->pEList;
        assert( pList!=0 );
        for(ii=0; ii<pList->nExpr; ii++){
          CollSeq *pColl = sqlite3ExprCollSeq(pParse, pList->a[ii].pExpr);
          if( !sqlite3IsBinary(pColl) ){
            return 0;  /* Restriction (8) */
          }
        }
      }
    }
  }else{
#ifndef SQLITE_OMIT_WINDOWFUNC
    if( pSubq->pWin && pSubq->pWin->pPartition==0 ) return 0;
#endif
  }

#ifdef SQLITE_DEBUG
  /* Only the first term of a compound can have a WITH clause.  But make
  ** sure no other terms are marked SF_Recursive in case something changes
  ** in the future.
  */
  {
    Select *pX;  
    for(pX=pSubq; pX; pX=pX->pPrior){
      assert( (pX->selFlags & (SF_Recursive))==0 );
    }
  }
#endif

  if( pSubq->pLimit!=0 ){
    return 0; /* restriction (3) */
  }
  while( pWhere->op==TK_AND ){
    nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight,
    nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, pSrc);
                                iCursor, isLeftJoin);
    pWhere = pWhere->pLeft;
  }

#if 0  /* Legacy code. Checks now done by sqlite3ExprIsTableConstraint() */
  if( isLeftJoin
   && (ExprHasProperty(pWhere,EP_FromJoin)==0
         || pWhere->iRightJoinTable!=iCursor)
   && (ExprHasProperty(pWhere,EP_OuterON)==0
         || pWhere->w.iJoin!=iCursor)
  ){
    return 0; /* restriction (4) */
  }
  if( ExprHasProperty(pWhere,EP_FromJoin) && pWhere->iRightJoinTable!=iCursor ){
  if( ExprHasProperty(pWhere,EP_OuterON)
   && pWhere->w.iJoin!=iCursor 
  ){
    return 0; /* restriction (5) */
  }
#endif

  if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){
  if( sqlite3ExprIsTableConstraint(pWhere, pSrc) ){
    nChng++;
    pSubq->selFlags |= SF_PushDown;
    while( pSubq ){
      SubstContext x;
      pNew = sqlite3ExprDup(pParse->db, pWhere, 0);
      unsetJoinExpr(pNew, -1);
      unsetJoinExpr(pNew, -1, 1);
      x.pParse = pParse;
      x.iTable = iCursor;
      x.iNewTable = iCursor;
      x.isLeftJoin = 0;
      x.iTable = pSrc->iCursor;
      x.iNewTable = pSrc->iCursor;
      x.isOuterJoin = 0;
      x.pEList = pSubq->pEList;
      x.pCList = findLeftmostExprlist(pSubq);
      pNew = substExpr(&x, pNew);
#ifndef SQLITE_OMIT_WINDOWFUNC
      if( pSubq->pWin && 0==pushDownWindowCheck(pParse, pSubq, pNew) ){
        /* Restriction 6c has prevented push-down in this case */
        sqlite3ExprDelete(pParse->db, pNew);
        nChng--;
        break;
      }
#endif
      if( pSubq->selFlags & SF_Aggregate ){
        pSubq->pHaving = sqlite3ExprAnd(pParse->db, pSubq->pHaving, pNew);
        pSubq->pHaving = sqlite3ExprAnd(pParse, pSubq->pHaving, pNew);
      }else{
        pSubq->pWhere = sqlite3ExprAnd(pParse->db, pSubq->pWhere, pNew);
        pSubq->pWhere = sqlite3ExprAnd(pParse, pSubq->pWhere, pNew);
      }
      pSubq = pSubq->pPrior;
    }
  }
  return nChng;
}
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
4391
4392
4393
4394
4395
4396
4397
4398

4399
4400
4401

4402
4403
4404



4405








4406
4407
4408

4409


4410
4411
4412

4413
4414
4415
4416
4417
4418

4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431







4432
4433
4434
4435
4436
4437
4438
4439
4440






4441
4442
4443
4444
4445
4446
4447
4448





4449
4450

4451

4452



4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464

4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478

















4479
4480
4481

4482
4483
4484
4485
4486
4487
4488
5249
5250
5251
5252
5253
5254
5255

5256
5257
5258

5259
5260
5261
5262
5263
5264
5265

5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277

5278
5279
5280
5281

5282
5283
5284
5285
5286
5287

5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300

5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314


5315
5316
5317
5318
5319
5320
5321
5322
5323
5324




5325
5326
5327
5328
5329
5330

5331
5332
5333

5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347

5348














5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365

5366
5367
5368
5369
5370
5371
5372
5373
5374
5375







-
+


-
+



+
+
+
-
+
+
+
+
+
+
+
+



+
-
+
+


-
+





-
+












-
+
+
+
+
+
+
+







-
-
+
+
+
+
+
+




-
-
-
-
+
+
+
+
+

-
+

+
-
+
+
+











-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-


+







**
** This routine must be called after aggregate functions have been
** located but before their arguments have been subjected to aggregate
** analysis.
*/
static u8 minMaxQuery(sqlite3 *db, Expr *pFunc, ExprList **ppMinMax){
  int eRet = WHERE_ORDERBY_NORMAL;      /* Return value */
  ExprList *pEList = pFunc->x.pList;    /* Arguments to agg function */
  ExprList *pEList;                     /* Arguments to agg function */
  const char *zFunc;                    /* Name of aggregate function pFunc */
  ExprList *pOrderBy;
  u8 sortOrder;
  u8 sortFlags = 0;

  assert( *ppMinMax==0 );
  assert( pFunc->op==TK_AGG_FUNCTION );
  assert( !IsWindowFunc(pFunc) );
  assert( ExprUseXList(pFunc) );
  pEList = pFunc->x.pList;
  if( pEList==0 || pEList->nExpr!=1 ) return eRet;
  if( pEList==0 
   || pEList->nExpr!=1
   || ExprHasProperty(pFunc, EP_WinFunc)
   || OptimizationDisabled(db, SQLITE_MinMaxOpt)
  ){
    return eRet;
  }
  assert( !ExprHasProperty(pFunc, EP_IntValue) );
  zFunc = pFunc->u.zToken;
  if( sqlite3StrICmp(zFunc, "min")==0 ){
    eRet = WHERE_ORDERBY_MIN;
    if( sqlite3ExprCanBeNull(pEList->a[0].pExpr) ){
    sortOrder = SQLITE_SO_ASC;
      sortFlags = KEYINFO_ORDER_BIGNULL;
    }
  }else if( sqlite3StrICmp(zFunc, "max")==0 ){
    eRet = WHERE_ORDERBY_MAX;
    sortOrder = SQLITE_SO_DESC;
    sortFlags = KEYINFO_ORDER_DESC;
  }else{
    return eRet;
  }
  *ppMinMax = pOrderBy = sqlite3ExprListDup(db, pEList, 0);
  assert( pOrderBy!=0 || db->mallocFailed );
  if( pOrderBy ) pOrderBy->a[0].sortOrder = sortOrder;
  if( pOrderBy ) pOrderBy->a[0].fg.sortFlags = sortFlags;
  return eRet;
}

/*
** The select statement passed as the first argument is an aggregate query.
** The second argument is the associated aggregate-info object. This 
** function tests if the SELECT is of the form:
**
**   SELECT count(*) FROM <tbl>
**
** where table is a database table, not a sub-select or view. If the query
** does match this pattern, then a pointer to the Table object representing
** <tbl> is returned. Otherwise, 0 is returned.
** <tbl> is returned. Otherwise, NULL is returned.
**
** This routine checks to see if it is safe to use the count optimization.
** A correct answer is still obtained (though perhaps more slowly) if
** this routine returns NULL when it could have returned a table pointer.
** But returning the pointer when NULL should have been returned can
** result in incorrect answers and/or crashes.  So, when in doubt, return NULL.
*/
static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
  Table *pTab;
  Expr *pExpr;

  assert( !p->pGroupBy );

  if( p->pWhere || p->pEList->nExpr!=1 
   || p->pSrc->nSrc!=1 || p->pSrc->a[0].pSelect
  if( p->pWhere 
   || p->pEList->nExpr!=1 
   || p->pSrc->nSrc!=1
   || p->pSrc->a[0].pSelect
   || pAggInfo->nFunc!=1
   || p->pHaving
  ){
    return 0;
  }
  pTab = p->pSrc->a[0].pTab;
  pExpr = p->pEList->a[0].pExpr;
  assert( pTab && !pTab->pSelect && pExpr );

  if( IsVirtual(pTab) ) return 0;
  assert( pTab!=0 );
  assert( !IsView(pTab) );
  if( !IsOrdinaryTable(pTab) ) return 0;
  pExpr = p->pEList->a[0].pExpr;
  assert( pExpr!=0 );
  if( pExpr->op!=TK_AGG_FUNCTION ) return 0;
  if( NEVER(pAggInfo->nFunc==0) ) return 0;
  if( pExpr->pAggInfo!=pAggInfo ) return 0;
  if( (pAggInfo->aFunc[0].pFunc->funcFlags&SQLITE_FUNC_COUNT)==0 ) return 0;
  assert( pAggInfo->aFunc[0].pFExpr==pExpr );
  if( pExpr->flags&EP_Distinct ) return 0;
  testcase( ExprHasProperty(pExpr, EP_Distinct) );
  testcase( ExprHasProperty(pExpr, EP_WinFunc) );
  if( ExprHasProperty(pExpr, EP_Distinct|EP_WinFunc) ) return 0;

  return pTab;
}

/*
** If the source-list item passed as an argument was augmented with an
** INDEXED BY clause, then try to locate the specified index. If there
** was such a clause and the named index cannot be found, return 
** SQLITE_ERROR and leave an error in pParse. Otherwise, populate 
** pFrom->pIndex and return SQLITE_OK.
*/
int sqlite3IndexedByLookup(Parse *pParse, struct SrcList_item *pFrom){
int sqlite3IndexedByLookup(Parse *pParse, SrcItem *pFrom){
  if( pFrom->pTab && pFrom->fg.isIndexedBy ){
    Table *pTab = pFrom->pTab;
    char *zIndexedBy = pFrom->u1.zIndexedBy;
    Index *pIdx;
    for(pIdx=pTab->pIndex; 
        pIdx && sqlite3StrICmp(pIdx->zName, zIndexedBy); 
        pIdx=pIdx->pNext
    );
    if( !pIdx ){
      sqlite3ErrorMsg(pParse, "no such index: %s", zIndexedBy, 0);
      pParse->checkSchema = 1;
      return SQLITE_ERROR;
    }
    pFrom->pIBIndex = pIdx;
  Table *pTab = pFrom->pTab;
  char *zIndexedBy = pFrom->u1.zIndexedBy;
  Index *pIdx;
  assert( pTab!=0 );
  assert( pFrom->fg.isIndexedBy!=0 );

  for(pIdx=pTab->pIndex; 
      pIdx && sqlite3StrICmp(pIdx->zName, zIndexedBy); 
      pIdx=pIdx->pNext
  );
  if( !pIdx ){
    sqlite3ErrorMsg(pParse, "no such index: %s", zIndexedBy, 0);
    pParse->checkSchema = 1;
    return SQLITE_ERROR;
  }
  assert( pFrom->fg.isCte==0 );
  pFrom->u2.pIBIndex = pIdx;
  }
  return SQLITE_OK;
}

/*
** Detect compound SELECT statements that use an ORDER BY clause with 
** an alternative collating sequence.
**
**    SELECT ... FROM t1 EXCEPT SELECT ... FROM t2 ORDER BY .. COLLATE ...
**
** These are rewritten as a subquery:
4511
4512
4513
4514
4515
4516
4517








4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530

4531
4532
4533
4534
4535
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
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578

4579
4580
4581

4582
4583
4584
4585
4586
4587
4588
4589
4590
4591











4592

4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603


4604
4605







4606
4607

4608
4609







4610
4611
4612



4613
4614



4615
4616
4617
4618
4619
4620
4621




4622
4623
4624


4625
4626
4627

4628
4629


4630
4631
4632
4633
4634




4635
4636
4637
4638
4639


4640
4641



4642



















4643
4644

4645
4646
4647
4648

4649
4650


4651
4652
4653
4654
4655
4656
4657
4658

4659
4660

4661
4662
4663
4664














4665
4666
4667
4668
4669
4670
4671


4672



4673





4674
4675

4676
4677

4678
4679


4680
4681

4682
4683
4684
4685

4686
4687
4688
4689

4690
4691
4692
4693

4694
4695
4696
4697
4698
4699
4700
4701
4702
4703














4704
4705
4706
4707
4708
4709
4710
4711
4712














4713
4714




4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726

4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741

4742
4743

4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757

4758
4759
4760
4761
4762

4763
4764
4765
4766
4767
4768
4769
4770
4771
4772

4773
4774

4775
4776
4777
4778

4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789

4790
4791
4792
4793
4794


4795
4796
4797






























4798

4799
4800
4801
4802
4803
4804
4805
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424

5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454

5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475

5476
5477
5478

5479










5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490

5491
5492
5493
5494
5495
5496
5497
5498
5499
5500


5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512

5513

5514
5515
5516
5517
5518
5519
5520
5521



5522
5523
5524


5525
5526
5527
5528
5529
5530
5531



5532
5533
5534
5535
5536


5537
5538


5539
5540


5541
5542

5543



5544
5545
5546
5547
5548




5549
5550
5551
5552
5553
5554
5555

5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593

5594
5595

5596
5597
5598


5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618

5619
5620
5621
5622
5623
5624

5625
5626
5627
5628
5629
5630

5631
5632

5633
5634

5635
5636
5637

5638
5639
5640
5641

5642
5643

5644

5645




5646










5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663






5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678

5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693

5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711

5712

5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724

5725
5726
5727
5728
5729

5730
5731
5732
5733
5734


5735
5736
5737

5738
5739

5740
5741
5742
5743

5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754

5755
5756
5757
5758
5759
5760
5761
5762



5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
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







+
+
+
+
+
+
+
+












-
+












+
+
+














-
+




















-
+


-
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
+









-
-
+
+


+
+
+
+
+
+
+

-
+
-

+
+
+
+
+
+
+
-
-
-
+
+
+
-
-
+
+
+




-
-
-
+
+
+
+

-
-
+
+
-
-

+
-
-
+
+
-

-
-
-
+
+
+
+

-
-
-
-
+
+


+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+




+


+
+







-
+

-
+


-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
+
+

+
+
+
-
+
+
+
+
+

-
+

-
+

-
+
+

-
+



-
+

-

-
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+
+
+
+











-
+















+

-
+
-












-
+




-
+




-
-



-
+

-
+



-
+










-
+





+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+







  Token dummy;

  if( p->pPrior==0 ) return WRC_Continue;
  if( p->pOrderBy==0 ) return WRC_Continue;
  for(pX=p; pX && (pX->op==TK_ALL || pX->op==TK_SELECT); pX=pX->pPrior){}
  if( pX==0 ) return WRC_Continue;
  a = p->pOrderBy->a;
#ifndef SQLITE_OMIT_WINDOWFUNC
  /* If iOrderByCol is already non-zero, then it has already been matched
  ** to a result column of the SELECT statement. This occurs when the
  ** SELECT is rewritten for window-functions processing and then passed
  ** to sqlite3SelectPrep() and similar a second time. The rewriting done
  ** by this function is not required in this case. */
  if( a[0].u.x.iOrderByCol ) return WRC_Continue;
#endif
  for(i=p->pOrderBy->nExpr-1; i>=0; i--){
    if( a[i].pExpr->flags & EP_Collate ) break;
  }
  if( i<0 ) return WRC_Continue;

  /* If we reach this point, that means the transformation is required. */

  pParse = pWalker->pParse;
  db = pParse->db;
  pNew = sqlite3DbMallocZero(db, sizeof(*pNew) );
  if( pNew==0 ) return WRC_Abort;
  memset(&dummy, 0, sizeof(dummy));
  pNewSrc = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&dummy,pNew,0,0);
  pNewSrc = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&dummy,pNew,0);
  if( pNewSrc==0 ) return WRC_Abort;
  *pNew = *p;
  p->pSrc = pNewSrc;
  p->pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ASTERISK, 0));
  p->op = TK_SELECT;
  p->pWhere = 0;
  pNew->pGroupBy = 0;
  pNew->pHaving = 0;
  pNew->pOrderBy = 0;
  p->pPrior = 0;
  p->pNext = 0;
  p->pWith = 0;
#ifndef SQLITE_OMIT_WINDOWFUNC
  p->pWinDefn = 0;
#endif
  p->selFlags &= ~SF_Compound;
  assert( (p->selFlags & SF_Converted)==0 );
  p->selFlags |= SF_Converted;
  assert( pNew->pPrior!=0 );
  pNew->pPrior->pNext = pNew;
  pNew->pLimit = 0;
  return WRC_Continue;
}

/*
** Check to see if the FROM clause term pFrom has table-valued function
** arguments.  If it does, leave an error message in pParse and return
** non-zero, since pFrom is not allowed to be a table-valued function.
*/
static int cannotBeFunction(Parse *pParse, struct SrcList_item *pFrom){
static int cannotBeFunction(Parse *pParse, SrcItem *pFrom){
  if( pFrom->fg.isTabFunc ){
    sqlite3ErrorMsg(pParse, "'%s' is not a function", pFrom->zName);
    return 1;
  }
  return 0;
}

#ifndef SQLITE_OMIT_CTE
/*
** Argument pWith (which may be NULL) points to a linked list of nested 
** WITH contexts, from inner to outermost. If the table identified by 
** FROM clause element pItem is really a common-table-expression (CTE) 
** then return a pointer to the CTE definition for that table. Otherwise
** return NULL.
**
** If a non-NULL value is returned, set *ppContext to point to the With
** object that the returned CTE belongs to.
*/
static struct Cte *searchWith(
  With *pWith,                    /* Current innermost WITH clause */
  struct SrcList_item *pItem,     /* FROM clause element to resolve */
  SrcItem *pItem,                 /* FROM clause element to resolve */
  With **ppContext                /* OUT: WITH clause return value belongs to */
){
  const char *zName;
  const char *zName = pItem->zName;
  if( pItem->zDatabase==0 && (zName = pItem->zName)!=0 ){
    With *p;
    for(p=pWith; p; p=p->pOuter){
      int i;
      for(i=0; i<p->nCte; i++){
        if( sqlite3StrICmp(zName, p->a[i].zName)==0 ){
          *ppContext = p;
          return &p->a[i];
        }
      }
  With *p;
  assert( pItem->zDatabase==0 );
  assert( zName!=0 );
  for(p=pWith; p; p=p->pOuter){
    int i;
    for(i=0; i<p->nCte; i++){
      if( sqlite3StrICmp(zName, p->a[i].zName)==0 ){
        *ppContext = p;
        return &p->a[i];
      }
    }
    }
    if( p->bView ) break;
  }
  return 0;
}

/* The code generator maintains a stack of active WITH clauses
** with the inner-most WITH clause being at the top of the stack.
**
** This routine pushes the WITH clause passed as the second argument
** onto the top of the stack. If argument bFree is true, then this
** WITH clause will never be popped from the stack. In this case it
** should be freed along with the Parse object. In other cases, when
** WITH clause will never be popped from the stack but should instead
** be freed along with the Parse object. In other cases, when
** bFree==0, the With object will be freed along with the SELECT 
** statement with which it is associated.
**
** This routine returns a copy of pWith.  Or, if bFree is true and
** the pWith object is destroyed immediately due to an OOM condition,
** then this routine return NULL.
**
** If bFree is true, do not continue to use the pWith pointer after
** calling this routine,  Instead, use only the return value.
*/
void sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){
With *sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){
  assert( bFree==0 || (pParse->pWith==0 && pParse->pWithToFree==0) );
  if( pWith ){
    if( bFree ){
      pWith = (With*)sqlite3ParserAddCleanup(pParse, 
                      (void(*)(sqlite3*,void*))sqlite3WithDelete,
                      pWith);
      if( pWith==0 ) return 0;
    }
    if( pParse->nErr==0 ){
    assert( pParse->pWith!=pWith );
    pWith->pOuter = pParse->pWith;
    pParse->pWith = pWith;
      assert( pParse->pWith!=pWith );
      pWith->pOuter = pParse->pWith;
      pParse->pWith = pWith;
    if( bFree ) pParse->pWithToFree = pWith;
  }
    }
  }
  return pWith;
}

/*
** This function checks if argument pFrom refers to a CTE declared by 
** a WITH clause on the stack currently maintained by the parser. And,
** if currently processing a CTE expression, if it is a recursive
** reference to the current CTE.
** a WITH clause on the stack currently maintained by the parser (on the
** pParse->pWith linked list).  And if currently processing a CTE
** CTE expression, through routine checks to see if the reference is
** a recursive reference to the CTE.
**
** If pFrom falls into either of the two categories above, pFrom->pTab
** and other fields are populated accordingly. The caller should check
** If pFrom matches a CTE according to either of these two above, pFrom->pTab
** and other fields are populated accordingly.
** (pFrom->pTab!=0) to determine whether or not a successful match
** was found.
**
** Return 0 if no match is found. 
** Whether or not a match is found, SQLITE_OK is returned if no error
** occurs. If an error does occur, an error message is stored in the
** Return 1 if a match is found.
** Return 2 if an error condition is detected.
** parser and some error code other than SQLITE_OK returned.
*/
static int withExpand(
  Walker *pWalker, 
  struct SrcList_item *pFrom
static int resolveFromTermToCte(
  Parse *pParse,                  /* The parsing context */
  Walker *pWalker,                /* Current tree walker */
  SrcItem *pFrom                  /* The FROM clause term to check */
){
  Parse *pParse = pWalker->pParse;
  sqlite3 *db = pParse->db;
  struct Cte *pCte;               /* Matched CTE (or NULL if no match) */
  With *pWith;                    /* WITH clause that pCte belongs to */
  Cte *pCte;               /* Matched CTE (or NULL if no match) */
  With *pWith;             /* The matching WITH */

  assert( pFrom->pTab==0 );
  if( pParse->pWith==0 ){
    /* There are no WITH clauses in the stack.  No match is possible */
    return 0;

  }
  if( pParse->nErr ){
    /* Prior errors might have left pParse->pWith in a goofy state, so
    ** go no further. */
    return 0;
  }
  if( pFrom->zDatabase!=0 ){
    /* The FROM term contains a schema qualifier (ex: main.t1) and so
    ** it cannot possibly be a CTE reference. */
    return 0;
  }
  if( pFrom->fg.notCte ){
    /* The FROM term is specifically excluded from matching a CTE.
    **   (1)  It is part of a trigger that used to have zDatabase but had
    **        zDatabase removed by sqlite3FixTriggerStep().
    **   (2)  This is the first term in the FROM clause of an UPDATE.
    */
    return 0;
  }
  pCte = searchWith(pParse->pWith, pFrom, &pWith);
  if( pCte ){
    sqlite3 *db = pParse->db;
    Table *pTab;
    ExprList *pEList;
    Select *pSel;
    Select *pLeft;                /* Left-most SELECT statement */
    Select *pRecTerm;             /* Left-most recursive term */
    int bMayRecursive;            /* True if compound joined by UNION [ALL] */
    With *pSavedWith;             /* Initial value of pParse->pWith */
    int iRecTab = -1;             /* Cursor for recursive table */
    CteUse *pCteUse;

    /* If pCte->zCteErr is non-NULL at this point, then this is an illegal
    ** recursive reference to CTE pCte. Leave an error in pParse and return
    ** early. If pCte->zCteErr is NULL, then this is not a recursive reference.
    ** In this case, proceed.  */
    if( pCte->zCteErr ){
      sqlite3ErrorMsg(pParse, pCte->zCteErr, pCte->zName);
      return SQLITE_ERROR;
      return 2;
    }
    if( cannotBeFunction(pParse, pFrom) ) return SQLITE_ERROR;
    if( cannotBeFunction(pParse, pFrom) ) return 2;

    assert( pFrom->pTab==0 );
    pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
    if( pTab==0 ) return WRC_Abort;
    pTab = sqlite3DbMallocZero(db, sizeof(Table));
    if( pTab==0 ) return 2;
    pCteUse = pCte->pUse;
    if( pCteUse==0 ){
      pCte->pUse = pCteUse = sqlite3DbMallocZero(db, sizeof(pCteUse[0]));
      if( pCteUse==0
       || sqlite3ParserAddCleanup(pParse,sqlite3DbFree,pCteUse)==0
      ){
        sqlite3DbFree(db, pTab);
        return 2;
      }
      pCteUse->eM10d = pCte->eM10d;
    }
    pFrom->pTab = pTab;
    pTab->nTabRef = 1;
    pTab->zName = sqlite3DbStrDup(db, pCte->zName);
    pTab->iPKey = -1;
    pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
    pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid;
    pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0);
    if( db->mallocFailed ) return SQLITE_NOMEM_BKPT;
    if( db->mallocFailed ) return 2;
    pFrom->pSelect->selFlags |= SF_CopyCte;
    assert( pFrom->pSelect );
    if( pFrom->fg.isIndexedBy ){
      sqlite3ErrorMsg(pParse, "no such index: \"%s\"", pFrom->u1.zIndexedBy);
      return 2;

    }
    pFrom->fg.isCte = 1;
    pFrom->u2.pCteUse = pCteUse;
    pCteUse->nUse++;

    /* Check if this is a recursive CTE. */
    pSel = pFrom->pSelect;
    pRecTerm = pSel = pFrom->pSelect;
    bMayRecursive = ( pSel->op==TK_ALL || pSel->op==TK_UNION );
    if( bMayRecursive ){
    while( bMayRecursive && pRecTerm->op==pSel->op ){
      int i;
      SrcList *pSrc = pFrom->pSelect->pSrc;
      SrcList *pSrc = pRecTerm->pSrc;
      assert( pRecTerm->pPrior!=0 );
      for(i=0; i<pSrc->nSrc; i++){
        struct SrcList_item *pItem = &pSrc->a[i];
        SrcItem *pItem = &pSrc->a[i];
        if( pItem->zDatabase==0 
         && pItem->zName!=0 
         && 0==sqlite3StrICmp(pItem->zName, pCte->zName)
          ){
        ){
          pItem->pTab = pTab;
          pItem->fg.isRecursive = 1;
          pTab->nTabRef++;
          pSel->selFlags |= SF_Recursive;
          pItem->fg.isRecursive = 1;
        }
      }
    }

          if( pRecTerm->selFlags & SF_Recursive ){
    /* Only one recursive reference is permitted. */ 
    if( pTab->nTabRef>2 ){
      sqlite3ErrorMsg(
          pParse, "multiple references to recursive table: %s", pCte->zName
      );
      return SQLITE_ERROR;
    }
    assert( pTab->nTabRef==1 || 
            ((pSel->selFlags&SF_Recursive) && pTab->nTabRef==2 ));

            sqlite3ErrorMsg(pParse,
               "multiple references to recursive table: %s", pCte->zName
            );
            return 2;
          }
          pRecTerm->selFlags |= SF_Recursive;
          if( iRecTab<0 ) iRecTab = pParse->nTab++;
          pItem->iCursor = iRecTab;
        }
      }
      if( (pRecTerm->selFlags & SF_Recursive)==0 ) break;
      pRecTerm = pRecTerm->pPrior;
    }

    pCte->zCteErr = "circular reference: %s";
    pSavedWith = pParse->pWith;
    pParse->pWith = pWith;
    if( bMayRecursive ){
      Select *pPrior = pSel->pPrior;
      assert( pPrior->pWith==0 );
      pPrior->pWith = pSel->pWith;
      sqlite3WalkSelect(pWalker, pPrior);
      pPrior->pWith = 0;
    if( pSel->selFlags & SF_Recursive ){
      int rc;
      assert( pRecTerm!=0 );
      assert( (pRecTerm->selFlags & SF_Recursive)==0 );
      assert( pRecTerm->pNext!=0 );
      assert( (pRecTerm->pNext->selFlags & SF_Recursive)!=0 );
      assert( pRecTerm->pWith==0 );
      pRecTerm->pWith = pSel->pWith;
      rc = sqlite3WalkSelect(pWalker, pRecTerm);
      pRecTerm->pWith = 0;
      if( rc ){
        pParse->pWith = pSavedWith;
        return 2;
      }
    }else{
      sqlite3WalkSelect(pWalker, pSel);
      if( sqlite3WalkSelect(pWalker, pSel) ){
        pParse->pWith = pSavedWith;
        return 2;
      }
    }
    pParse->pWith = pWith;

    for(pLeft=pSel; pLeft->pPrior; pLeft=pLeft->pPrior);
    pEList = pLeft->pEList;
    if( pCte->pCols ){
      if( pEList && pEList->nExpr!=pCte->pCols->nExpr ){
        sqlite3ErrorMsg(pParse, "table %s has %d values for %d columns",
            pCte->zName, pEList->nExpr, pCte->pCols->nExpr
        );
        pParse->pWith = pSavedWith;
        return SQLITE_ERROR;
        return 2;
      }
      pEList = pCte->pCols;
    }

    sqlite3ColumnsFromExprList(pParse, pEList, &pTab->nCol, &pTab->aCol);
    if( bMayRecursive ){
      if( pSel->selFlags & SF_Recursive ){
        pCte->zCteErr = "multiple recursive references: %s";
      }else{
        pCte->zCteErr = "recursive reference in a subquery: %s";
      }
      sqlite3WalkSelect(pWalker, pSel);
    }
    pCte->zCteErr = 0;
    pParse->pWith = pSavedWith;
    return 1;  /* Success */
  }

  return 0;  /* No match */
  return SQLITE_OK;
}
#endif

#ifndef SQLITE_OMIT_CTE
/*
** If the SELECT passed as the second argument has an associated WITH 
** clause, pop it from the stack stored as part of the Parse object.
**
** This function is used as the xSelectCallback2() callback by
** sqlite3SelectExpand() when walking a SELECT tree to resolve table
** names and other FROM clause elements. 
*/
static void selectPopWith(Walker *pWalker, Select *p){
void sqlite3SelectPopWith(Walker *pWalker, Select *p){
  Parse *pParse = pWalker->pParse;
  if( OK_IF_ALWAYS_TRUE(pParse->pWith) && p->pPrior==0 ){
    With *pWith = findRightmost(p)->pWith;
    if( pWith!=0 ){
      assert( pParse->pWith==pWith );
      assert( pParse->pWith==pWith || pParse->nErr );
      pParse->pWith = pWith->pOuter;
    }
  }
}
#else
#define selectPopWith 0
#endif

/*
** The SrcList_item structure passed as the second argument represents a
** The SrcItem structure passed as the second argument represents a
** sub-query in the FROM clause of a SELECT statement. This function
** allocates and populates the SrcList_item.pTab object. If successful,
** allocates and populates the SrcItem.pTab object. If successful,
** SQLITE_OK is returned. Otherwise, if an OOM error is encountered,
** SQLITE_NOMEM.
*/
int sqlite3ExpandSubquery(Parse *pParse, struct SrcList_item *pFrom){
int sqlite3ExpandSubquery(Parse *pParse, SrcItem *pFrom){
  Select *pSel = pFrom->pSelect;
  Table *pTab;

  assert( pSel );
  pFrom->pTab = pTab = sqlite3DbMallocZero(pParse->db, sizeof(Table));
  if( pTab==0 ) return SQLITE_NOMEM;
  pTab->nTabRef = 1;
  if( pFrom->zAlias ){
    pTab->zName = sqlite3DbStrDup(pParse->db, pFrom->zAlias);
  }else{
    pTab->zName = sqlite3MPrintf(pParse->db, "subquery_%u", pSel->selId);
    pTab->zName = sqlite3MPrintf(pParse->db, "%!S", pFrom);
  }
  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;

  return SQLITE_OK;
  pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid;
#else
  pTab->tabFlags |= TF_Ephemeral;  /* Legacy compatibility mode */
#endif
  return pParse->nErr ? SQLITE_ERROR : SQLITE_OK;
}


/*
** Check the N SrcItem objects to the right of pBase.  (N might be zero!)
** If any of those SrcItem objects have a USING clause containing zName
** then return true.
**
** If N is zero, or none of the N SrcItem objects to the right of pBase
** contains a USING clause, or if none of the USING clauses contain zName,
** then return false.
*/
static int inAnyUsingClause(
  const char *zName, /* Name we are looking for */
  SrcItem *pBase,    /* The base SrcItem.  Looking at pBase[1] and following */
  int N              /* How many SrcItems to check */
){
  while( N>0 ){
    N--;
    pBase++;
    if( pBase->fg.isUsing==0 ) continue;
    if( NEVER(pBase->u3.pUsing==0) ) continue;
    if( sqlite3IdListIndex(pBase->u3.pUsing, zName)>=0 ) return 1;
  }
  return 0;
}


/*
** This routine is a Walker callback for "expanding" a SELECT statement.
** "Expanding" means to do the following:
**
**    (1)  Make sure VDBE cursor numbers have been assigned to every
**         element of the FROM clause.
4819
4820
4821
4822
4823
4824
4825
4826

4827
4828
4829

4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842




4843
4844









4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860


4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873






4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890


4891

4892
4893







4894













4895
4896

4897

4898
4899
4900
4901
4902
4903
4904

4905
4906
4907
4908
4909
4910

4911

4912
4913
4914
4915
4916
4917
4918
5815
5816
5817
5818
5819
5820
5821

5822
5823
5824

5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867


5868
5869




5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899


5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912

5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936

5937
5938
5939
5940
5941
5942
5943
5944

5945
5946
5947
5948
5949
5950
5951
5952







-
+


-
+













+
+
+
+


+
+
+
+
+
+
+
+
+














-
-
+
+
-
-
-
-









+
+
+
+
+
+















-
-
+
+

+


+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+


+

+






-
+






+
-
+







**         for instances of the "*" operator or the TABLE.* operator.
**         If found, expand each "*" to be every column in every table
**         and TABLE.* to be every column in TABLE.
**
*/
static int selectExpander(Walker *pWalker, Select *p){
  Parse *pParse = pWalker->pParse;
  int i, j, k;
  int i, j, k, rc;
  SrcList *pTabList;
  ExprList *pEList;
  struct SrcList_item *pFrom;
  SrcItem *pFrom;
  sqlite3 *db = pParse->db;
  Expr *pE, *pRight, *pExpr;
  u16 selFlags = p->selFlags;
  u32 elistFlags = 0;

  p->selFlags |= SF_Expanded;
  if( db->mallocFailed  ){
    return WRC_Abort;
  }
  assert( p->pSrc!=0 );
  if( (selFlags & SF_Expanded)!=0 ){
    return WRC_Prune;
  }
  if( pWalker->eCode ){
    /* Renumber selId because it has been copied from a view */
    p->selId = ++pParse->nSelect;
  }
  pTabList = p->pSrc;
  pEList = p->pEList;
  if( pParse->pWith && (p->selFlags & SF_View) ){
    if( p->pWith==0 ){
      p->pWith = (With*)sqlite3DbMallocZero(db, sizeof(With));
      if( p->pWith==0 ){
        return WRC_Abort;
      }
    }
    p->pWith->bView = 1;
  }
  sqlite3WithPush(pParse, p->pWith, 0);

  /* Make sure cursor numbers have been assigned to all entries in
  ** the FROM clause of the SELECT statement.
  */
  sqlite3SrcListAssignCursors(pParse, pTabList);

  /* Look up every table named in the FROM clause of the select.  If
  ** an entry of the FROM clause is a subquery instead of a table or view,
  ** then create a transient table structure to describe the subquery.
  */
  for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
    Table *pTab;
    assert( pFrom->fg.isRecursive==0 || pFrom->pTab!=0 );
    if( pFrom->fg.isRecursive ) continue;
    assert( pFrom->pTab==0 );
    if( pFrom->pTab ) continue;
    assert( pFrom->fg.isRecursive==0 );
#ifndef SQLITE_OMIT_CTE
    if( withExpand(pWalker, pFrom) ) return WRC_Abort;
    if( pFrom->pTab ) {} else
#endif
    if( pFrom->zName==0 ){
#ifndef SQLITE_OMIT_SUBQUERY
      Select *pSel = pFrom->pSelect;
      /* A sub-query in the FROM clause of a SELECT */
      assert( pSel!=0 );
      assert( pFrom->pTab==0 );
      if( sqlite3WalkSelect(pWalker, pSel) ) return WRC_Abort;
      if( sqlite3ExpandSubquery(pParse, pFrom) ) return WRC_Abort;
#endif
#ifndef SQLITE_OMIT_CTE
    }else if( (rc = resolveFromTermToCte(pParse, pWalker, pFrom))!=0 ){
      if( rc>1 ) return WRC_Abort;
      pTab = pFrom->pTab;
      assert( pTab!=0 );
#endif
    }else{
      /* An ordinary table or view name in the FROM clause */
      assert( pFrom->pTab==0 );
      pFrom->pTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom);
      if( pTab==0 ) return WRC_Abort;
      if( pTab->nTabRef>=0xffff ){
        sqlite3ErrorMsg(pParse, "too many references to \"%s\": max 65535",
           pTab->zName);
        pFrom->pTab = 0;
        return WRC_Abort;
      }
      pTab->nTabRef++;
      if( !IsVirtual(pTab) && cannotBeFunction(pParse, pFrom) ){
        return WRC_Abort;
      }
#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
      if( IsVirtual(pTab) || pTab->pSelect ){
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
      if( !IsOrdinaryTable(pTab) ){
        i16 nCol;
        u8 eCodeOrig = pWalker->eCode;
        if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
        assert( pFrom->pSelect==0 );
        if( IsView(pTab) ){
          if( (db->flags & SQLITE_EnableView)==0
           && pTab->pSchema!=db->aDb[1].pSchema
          ){
            sqlite3ErrorMsg(pParse, "access to view \"%s\" prohibited",
              pTab->zName);
          }
        pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0);
          pFrom->pSelect = sqlite3SelectDup(db, pTab->u.view.pSelect, 0);
        }
#ifndef SQLITE_OMIT_VIRTUALTABLE
        else if( ALWAYS(IsVirtual(pTab))
         && pFrom->fg.fromDDL
         && ALWAYS(pTab->u.vtab.p!=0)
         && pTab->u.vtab.p->eVtabRisk > ((db->flags & SQLITE_TrustedSchema)!=0)
        ){
          sqlite3ErrorMsg(pParse, "unsafe use of virtual table \"%s\"",
                                  pTab->zName);
        }
        assert( SQLITE_VTABRISK_Normal==1 && SQLITE_VTABRISK_High==2 );
#endif
        nCol = pTab->nCol;
        pTab->nCol = -1;
        pWalker->eCode = 1;  /* Turn on Select.selId renumbering */
        sqlite3WalkSelect(pWalker, pFrom->pSelect);
        pWalker->eCode = eCodeOrig;
        pTab->nCol = nCol;
      }
#endif
    }

    /* Locate the index named by the INDEXED BY clause, if any. */
    if( sqlite3IndexedByLookup(pParse, pFrom) ){
    if( pFrom->fg.isIndexedBy && sqlite3IndexedByLookup(pParse, pFrom) ){
      return WRC_Abort;
    }
  }

  /* Process NATURAL keywords, and ON and USING clauses of joins.
  */
  assert( db->mallocFailed==0 || pParse->nErr!=0 );
  if( db->mallocFailed || sqliteProcessJoin(pParse, p) ){
  if( pParse->nErr || sqlite3ProcessJoin(pParse, p) ){
    return WRC_Abort;
  }

  /* For every "*" that occurs in the column list, insert the names of
  ** all columns in all tables.  And for every TABLE.* insert the names
  ** of all columns in TABLE.  The parser inserted a special expression
  ** with the TK_ASTERISK operator for each "*" that it found in the column
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960



4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980








4981
4982
4983

4984
4985






4986
4987
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
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033








5034
5035
5036



5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055









5056
5057
5058
5059



5060






5061
5062
5063









5064
5065
5066
5067
5068
5069
5070
5985
5986
5987
5988
5989
5990
5991



5992
5993
5994

5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007






6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019


6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054

6055



6056
6057
6058


6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082



6083
6084
6085
6086





6087
6088
6089
6090
6091
6092



6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110




6111
6112
6113
6114







6115
6116
6117
6118
6119
6120
6121
6122
6123
6124



6125
6126
6127
6128
6129
6130
6131
6132
6133
6134



6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150







-
-
-
+
+
+
-













-
-
-
-
-
-
+
+
+
+
+
+
+
+



+
-
-
+
+
+
+
+
+



+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+
-
-
-
+


-
-
+
+
+












+
+
+
+
+
+



-
-
-
+
+
+

-
-
-
-
-






-
-
-
+
+
+
+
+
+
+
+



+
+
+




-
-
-
-




-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+

-
-
-
+
+
+

+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+







      if( pE->op!=TK_ASTERISK
       && (pE->op!=TK_DOT || pRight->op!=TK_ASTERISK)
      ){
        /* This particular expression does not need to be expanded.
        */
        pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr);
        if( pNew ){
          pNew->a[pNew->nExpr-1].zName = a[k].zName;
          pNew->a[pNew->nExpr-1].zSpan = a[k].zSpan;
          a[k].zName = 0;
          pNew->a[pNew->nExpr-1].zEName = a[k].zEName;
          pNew->a[pNew->nExpr-1].fg.eEName = a[k].fg.eEName;
          a[k].zEName = 0;
          a[k].zSpan = 0;
        }
        a[k].pExpr = 0;
      }else{
        /* This expression is a "*" or a "TABLE.*" and needs to be
        ** expanded. */
        int tableSeen = 0;      /* Set to 1 when TABLE matches */
        char *zTName = 0;       /* text of name of TABLE */
        if( pE->op==TK_DOT ){
          assert( pE->pLeft!=0 );
          assert( !ExprHasProperty(pE->pLeft, EP_IntValue) );
          zTName = pE->pLeft->u.zToken;
        }
        for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
          Table *pTab = pFrom->pTab;
          Select *pSub = pFrom->pSelect;
          char *zTabName = pFrom->zAlias;
          const char *zSchemaName = 0;
          int iDb;
          if( zTabName==0 ){
          Table *pTab = pFrom->pTab;   /* Table for this data source */
          ExprList *pNestedFrom;       /* Result-set of a nested FROM clause */
          char *zTabName;              /* AS name for this data source */
          const char *zSchemaName = 0; /* Schema name for this data source */
          int iDb;                     /* Schema index for this data src */
          IdList *pUsing;              /* USING clause for pFrom[1] */

          if( (zTabName = pFrom->zAlias)==0 ){
            zTabName = pTab->zName;
          }
          if( db->mallocFailed ) break;
          assert( (int)pFrom->fg.isNestedFrom == IsNestedFrom(pFrom->pSelect) );
          if( pSub==0 || (pSub->selFlags & SF_NestedFrom)==0 ){
            pSub = 0;
          if( pFrom->fg.isNestedFrom ){
            assert( pFrom->pSelect!=0 );
            pNestedFrom = pFrom->pSelect->pEList;
            assert( pNestedFrom!=0 );
            assert( pNestedFrom->nExpr==pTab->nCol );
          }else{
            if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
              continue;
            }
            pNestedFrom = 0;
            iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
            zSchemaName = iDb>=0 ? db->aDb[iDb].zDbSName : "*";
          }
          if( i+1<pTabList->nSrc
           && pFrom[1].fg.isUsing
           && (selFlags & SF_NestedFrom)!=0
          ){
            int ii;
            pUsing = pFrom[1].u3.pUsing;
            for(ii=0; ii<pUsing->nId; ii++){
              const char *zUName = pUsing->a[ii].zName;
              pRight = sqlite3Expr(db, TK_ID, zUName);
              pNew = sqlite3ExprListAppend(pParse, pNew, pRight);
              if( pNew ){
                struct ExprList_item *pX = &pNew->a[pNew->nExpr-1];
                assert( pX->zEName==0 );
                pX->zEName = sqlite3MPrintf(db,"..%s", zUName);
                pX->fg.eEName = ENAME_TAB;
                pX->fg.bUsingTerm = 1;
              }
            }
          }else{
            pUsing = 0;
          }
          for(j=0; j<pTab->nCol; j++){
            char *zName = pTab->aCol[j].zName;
            char *zName = pTab->aCol[j].zCnName;
            char *zColname;  /* The computed column name */
            char *zToFree;   /* Malloced string that needs to be freed */
            Token sColname;  /* Computed column name as a token */
            struct ExprList_item *pX; /* Newly added ExprList term */

            assert( zName );
            if( zTName && pSub
             && sqlite3MatchSpanName(pSub->pEList->a[j].zSpan, 0, zTName, 0)==0
            if( zTName
             && pNestedFrom
             && sqlite3MatchEName(&pNestedFrom->a[j], 0, zTName, 0)==0
            ){
              continue;
            }

            /* If a column is marked as 'hidden', omit it from the expanded
            ** result-set list unless the SELECT has the SF_IncludeHidden
            ** bit set.
            */
            if( (p->selFlags & SF_IncludeHidden)==0
             && IsHiddenColumn(&pTab->aCol[j]) 
            ){
              continue;
            }
            if( (pTab->aCol[j].colFlags & COLFLAG_NOEXPAND)!=0
             && zTName==0
             && (selFlags & (SF_NestedFrom))==0
            ){
              continue;
            }
            tableSeen = 1;

            if( i>0 && zTName==0 ){
              if( (pFrom->fg.jointype & JT_NATURAL)!=0
                && tableAndColumnIndex(pTabList, i, zName, 0, 0)
            if( i>0 && zTName==0 && (selFlags & SF_NestedFrom)==0 ){
              if( pFrom->fg.isUsing
               && sqlite3IdListIndex(pFrom->u3.pUsing, zName)>=0
              ){
                /* In a NATURAL join, omit the join columns from the 
                ** table to the right of the join */
                continue;
              }
              if( sqlite3IdListIndex(pFrom->pUsing, zName)>=0 ){
                /* In a join with a USING clause, omit columns in the
                ** using clause from the table on the right. */
                continue;
              }
            }
            pRight = sqlite3Expr(db, TK_ID, zName);
            zColname = zName;
            zToFree = 0;
            if( longNames || pTabList->nSrc>1 ){
            if( (pTabList->nSrc>1
                 && (  (pFrom->fg.jointype & JT_LTORJ)==0
                     || (selFlags & SF_NestedFrom)!=0
                     || !inAnyUsingClause(zName,pFrom,pTabList->nSrc-i-1)
                    )
                )
             || IN_RENAME_OBJECT
            ){
              Expr *pLeft;
              pLeft = sqlite3Expr(db, TK_ID, zTabName);
              pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight);
              if( IN_RENAME_OBJECT && pE->pLeft ){
                sqlite3RenameTokenRemap(pParse, pLeft, pE->pLeft);
              }
              if( zSchemaName ){
                pLeft = sqlite3Expr(db, TK_ID, zSchemaName);
                pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pExpr);
              }
              if( longNames ){
                zColname = sqlite3MPrintf(db, "%s.%s", zTabName, zName);
                zToFree = zColname;
              }
            }else{
              pExpr = pRight;
            }
            pNew = sqlite3ExprListAppend(pParse, pNew, pExpr);
            sqlite3TokenInit(&sColname, zColname);
            sqlite3ExprListSetName(pParse, pNew, &sColname, 0);
            if( pNew && (p->selFlags & SF_NestedFrom)!=0 ){
              struct ExprList_item *pX = &pNew->a[pNew->nExpr-1];
              if( pSub ){
                pX->zSpan = sqlite3DbStrDup(db, pSub->pEList->a[j].zSpan);
                testcase( pX->zSpan==0 );
            if( pNew==0 ){
              break;  /* OOM */
            }
            pX = &pNew->a[pNew->nExpr-1];
            assert( pX->zEName==0 );
            if( (selFlags & SF_NestedFrom)!=0 && !IN_RENAME_OBJECT ){
              if( pNestedFrom ){
                pX->zEName = sqlite3DbStrDup(db, pNestedFrom->a[j].zEName);
                testcase( pX->zEName==0 );
              }else{
                pX->zSpan = sqlite3MPrintf(db, "%s.%s.%s",
                                           zSchemaName, zTabName, zColname);
                testcase( pX->zSpan==0 );
                pX->zEName = sqlite3MPrintf(db, "%s.%s.%s",
                                           zSchemaName, zTabName, zName);
                testcase( pX->zEName==0 );
              }
              pX->fg.eEName = ENAME_TAB;
              if( (pFrom->fg.isUsing
                   && sqlite3IdListIndex(pFrom->u3.pUsing, zName)>=0)
               || (pUsing && sqlite3IdListIndex(pUsing, zName)>=0)
               || (pTab->aCol[j].colFlags & COLFLAG_NOEXPAND)!=0
              ){
              pX->bSpanIsTab = 1;
            }
            sqlite3DbFree(db, zToFree);
                pX->fg.bNoExpand = 1;
              }
            }else if( longNames ){
              pX->zEName = sqlite3MPrintf(db, "%s.%s", zTabName, zName);
              pX->fg.eEName = ENAME_NAME;
            }else{
              pX->zEName = sqlite3DbStrDup(db, zName);
              pX->fg.eEName = ENAME_NAME;
            }
          }
        }
        if( !tableSeen ){
          if( zTName ){
            sqlite3ErrorMsg(pParse, "no such table: %s", zTName);
          }else{
            sqlite3ErrorMsg(pParse, "no tables specified");
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089

5090
5091
5092
5093
5094
5095
5096
5097

5098
5099


5100
5101
5102
5103


5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
6160
6161
6162
6163
6164
6165
6166



6167








6168


6169
6170




6171
6172






6173
6174
6175
6176
6177
6178
6179







-
-
-
+
-
-
-
-
-
-
-
-
+
-
-
+
+
-
-
-
-
+
+
-
-
-
-
-
-







      sqlite3ErrorMsg(pParse, "too many columns in result set");
      return WRC_Abort;
    }
    if( (elistFlags & (EP_HasFunc|EP_Subquery))!=0 ){
      p->selFlags |= SF_ComplexResult;
    }
  }
  return WRC_Continue;
}

#if TREETRACE_ENABLED
/*
** No-op routine for the parse-tree walker.
**
** When this routine is the Walker.xExprCallback then expression trees
** are walked without any actions being taken at each node.  Presumably,
** when this routine is used for Walker.xExprCallback then 
** Walker.xSelectCallback is set to do something useful for every 
** subquery in the parser tree.
  if( sqlite3TreeTrace & 0x8 ){
*/
int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
    TREETRACE(0x8,pParse,p,("After result-set wildcard expansion:\n"));
    sqlite3TreeViewSelect(0, p, 0);
  UNUSED_PARAMETER2(NotUsed, NotUsed2);
  return WRC_Continue;
}

  }
#endif
/*
** No-op routine for the parse-tree walker for SELECT statements.
** subquery in the parser tree.
*/
int sqlite3SelectWalkNoop(Walker *NotUsed, Select *NotUsed2){
  UNUSED_PARAMETER2(NotUsed, NotUsed2);
  return WRC_Continue;
}

#if SQLITE_DEBUG
/*
** Always assert.  This xSelectCallback2 implementation proves that the
** xSelectCallback2 is never invoked.
5139
5140
5141
5142
5143
5144
5145
5146


5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158



5159
5160
5161
5162
5163



5164
5165
5166
5167
5168
5169

5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184

5185
5186
5187
5188
5189
5190
5191
6202
6203
6204
6205
6206
6207
6208

6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219



6220
6221
6222
6223
6224



6225
6226
6227
6228
6229
6230
6231
6232

6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246


6247
6248
6249
6250
6251
6252
6253
6254







-
+
+









-
-
-
+
+
+


-
-
-
+
+
+





-
+













-
-
+







  w.pParse = pParse;
  if( OK_IF_ALWAYS_TRUE(pParse->hasCompound) ){
    w.xSelectCallback = convertCompoundSelectToSubquery;
    w.xSelectCallback2 = 0;
    sqlite3WalkSelect(&w, pSelect);
  }
  w.xSelectCallback = selectExpander;
  w.xSelectCallback2 = selectPopWith;
  w.xSelectCallback2 = sqlite3SelectPopWith;
  w.eCode = 0;
  sqlite3WalkSelect(&w, pSelect);
}


#ifndef SQLITE_OMIT_SUBQUERY
/*
** This is a Walker.xSelectCallback callback for the sqlite3SelectTypeInfo()
** interface.
**
** For each FROM-clause subquery, add Column.zType and Column.zColl
** information to the Table structure that represents the result set
** of that subquery.
** For each FROM-clause subquery, add Column.zType, Column.zColl, and
** Column.affinity information to the Table structure that represents
** the result set of that subquery.
**
** The Table structure that represents the result set was constructed
** by selectExpander() but the type and collation information was omitted
** at that point because identifiers had not yet been resolved.  This
** routine is called after identifier resolution.
** by selectExpander() but the type and collation and affinity information
** was omitted at that point because identifiers had not yet been resolved.
** This routine is called after identifier resolution.
*/
static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
  Parse *pParse;
  int i;
  SrcList *pTabList;
  struct SrcList_item *pFrom;
  SrcItem *pFrom;

  assert( p->selFlags & SF_Resolved );
  if( p->selFlags & SF_HasTypeInfo ) return;
  p->selFlags |= SF_HasTypeInfo;
  pParse = pWalker->pParse;
  pTabList = p->pSrc;
  for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
    Table *pTab = pFrom->pTab;
    assert( pTab!=0 );
    if( (pTab->tabFlags & TF_Ephemeral)!=0 ){
      /* A sub-query in the FROM clause of a SELECT */
      Select *pSel = pFrom->pSelect;
      if( pSel ){
        while( pSel->pPrior ) pSel = pSel->pPrior;
        sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSel);
        sqlite3SubqueryColumnTypes(pParse, pTab, pSel, SQLITE_AFF_NONE);
      }
    }
  }
}
#endif


5222
5223
5224
5225
5226
5227
5228

5229
5230
5231
5232

5233
5234

5235
5236







































































































































































5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250



5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265



5266
5267
5268
5269


5270
5271
5272
5273
5274
5275
5276
5277




5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294





5295
5296
5297
5298
5299
5300
5301
5302


5303
5304
5305
5306

5307
5308
5309






5310
5311
5312
5313
5314
5315
5316


5317
5318
5319
5320
5321
5322
5323


























5324
5325
5326
5327
5328
5329
5330
5331
5332
5333



5334
5335
5336



5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352

5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367

5368

5369
5370
5371

5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387

5388
5389
5390
5391
5392
5393
5394
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295

6296
6297

6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
6457
6458
6459
6460
6461
6462
6463
6464
6465
6466
6467
6468
6469
6470
6471
6472
6473
6474
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485














6486
6487
6488
6489
6490


6491
6492
6493
6494
6495
6496
6497
6498


6499
6500
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516



6517
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527


6528
6529
6530
6531
6532

6533
6534
6535

6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555


6556
6557
6558
6559
6560
6561
6562
6563
6564
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583
6584
6585
6586
6587
6588
6589


6590
6591
6592



6593
6594
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610

6611
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621
6622
6623
6624
6625

6626
6627
6628
6629
6630

6631
6632
6633
6634
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645
6646

6647
6648
6649
6650
6651
6652
6653
6654







+



-
+

-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+














+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+


-
-
+
+






-
-
+
+
+
+














-
-
-
+
+
+
+
+






-
-
+
+



-
+


-
+
+
+
+
+
+







+
+





-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








-
-
+
+
+
-
-
-
+
+
+















-
+














-
+

+


-
+















-
+







*/
void sqlite3SelectPrep(
  Parse *pParse,         /* The parser context */
  Select *p,             /* The SELECT statement being coded. */
  NameContext *pOuterNC  /* Name context for container */
){
  assert( p!=0 || pParse->db->mallocFailed );
  assert( pParse->db->pParse==pParse );
  if( pParse->db->mallocFailed ) return;
  if( p->selFlags & SF_HasTypeInfo ) return;
  sqlite3SelectExpand(pParse, p);
  if( pParse->nErr || pParse->db->mallocFailed ) return;
  if( pParse->nErr ) return;
  sqlite3ResolveSelectNames(pParse, p, pOuterNC);
  if( pParse->nErr || pParse->db->mallocFailed ) return;
  if( pParse->nErr ) return;
  sqlite3SelectAddTypeInfo(pParse, p);
}

#if TREETRACE_ENABLED
/*
** Display all information about an AggInfo object
*/
static void printAggInfo(AggInfo *pAggInfo){
  int ii;
  for(ii=0; ii<pAggInfo->nColumn; ii++){
    struct AggInfo_col *pCol = &pAggInfo->aCol[ii];
    sqlite3DebugPrintf(
       "agg-column[%d] pTab=%s iTable=%d iColumn=%d iMem=%d"
       " iSorterColumn=%d %s\n",
       ii, pCol->pTab ? pCol->pTab->zName : "NULL", 
       pCol->iTable, pCol->iColumn, pAggInfo->iFirstReg+ii,
       pCol->iSorterColumn, 
       ii>=pAggInfo->nAccumulator ? "" : " Accumulator");
    sqlite3TreeViewExpr(0, pAggInfo->aCol[ii].pCExpr, 0);
  }
  for(ii=0; ii<pAggInfo->nFunc; ii++){
    sqlite3DebugPrintf("agg-func[%d]: iMem=%d\n",
        ii, pAggInfo->iFirstReg+pAggInfo->nColumn+ii);
    sqlite3TreeViewExpr(0, pAggInfo->aFunc[ii].pFExpr, 0);
  }
}
#endif /* TREETRACE_ENABLED */

/*
** Analyze the arguments to aggregate functions.  Create new pAggInfo->aCol[]
** entries for columns that are arguments to aggregate functions but which
** are not otherwise used.
**
** The aCol[] entries in AggInfo prior to nAccumulator are columns that
** are referenced outside of aggregate functions.  These might be columns
** that are part of the GROUP by clause, for example.  Other database engines
** would throw an error if there is a column reference that is not in the
** GROUP BY clause and that is not part of an aggregate function argument.
** But SQLite allows this.
**
** The aCol[] entries beginning with the aCol[nAccumulator] and following
** are column references that are used exclusively as arguments to
** aggregate functions.  This routine is responsible for computing
** (or recomputing) those aCol[] entries.
*/
static void analyzeAggFuncArgs(
  AggInfo *pAggInfo,
  NameContext *pNC
){
  int i;
  assert( pAggInfo!=0 );
  assert( pAggInfo->iFirstReg==0 );
  pNC->ncFlags |= NC_InAggFunc;
  for(i=0; i<pAggInfo->nFunc; i++){
    Expr *pExpr = pAggInfo->aFunc[i].pFExpr;
    assert( ExprUseXList(pExpr) );
    sqlite3ExprAnalyzeAggList(pNC, pExpr->x.pList);
#ifndef SQLITE_OMIT_WINDOWFUNC
    assert( !IsWindowFunc(pExpr) );
    if( ExprHasProperty(pExpr, EP_WinFunc) ){
      sqlite3ExprAnalyzeAggregates(pNC, pExpr->y.pWin->pFilter);
    }
#endif
  }
  pNC->ncFlags &= ~NC_InAggFunc;
}

/*
** An index on expressions is being used in the inner loop of an
** aggregate query with a GROUP BY clause.  This routine attempts
** to adjust the AggInfo object to take advantage of index and to
** perhaps use the index as a covering index.
**
*/
static void optimizeAggregateUseOfIndexedExpr(
  Parse *pParse,          /* Parsing context */
  Select *pSelect,        /* The SELECT statement being processed */
  AggInfo *pAggInfo,      /* The aggregate info */
  NameContext *pNC        /* Name context used to resolve agg-func args */
){
  assert( pAggInfo->iFirstReg==0 );
  pAggInfo->nColumn = pAggInfo->nAccumulator;
  if( ALWAYS(pAggInfo->nSortingColumn>0) ){
    if( pAggInfo->nColumn==0 ){
      pAggInfo->nSortingColumn = 0;
    }else{
      pAggInfo->nSortingColumn =
        pAggInfo->aCol[pAggInfo->nColumn-1].iSorterColumn+1;
    }
  }
  analyzeAggFuncArgs(pAggInfo, pNC);
#if TREETRACE_ENABLED
  if( sqlite3TreeTrace & 0x20 ){
    IndexedExpr *pIEpr;
    TREETRACE(0x20, pParse, pSelect,
        ("AggInfo (possibly) adjusted for Indexed Exprs\n"));
    sqlite3TreeViewSelect(0, pSelect, 0);
    for(pIEpr=pParse->pIdxEpr; pIEpr; pIEpr=pIEpr->pIENext){
      printf("data-cursor=%d index={%d,%d}\n",
          pIEpr->iDataCur, pIEpr->iIdxCur, pIEpr->iIdxCol);
      sqlite3TreeViewExpr(0, pIEpr->pExpr, 0);
    }
    printAggInfo(pAggInfo);
  }
#else
  UNUSED_PARAMETER(pSelect);
  UNUSED_PARAMETER(pParse);
#endif
}

/*
** Walker callback for aggregateConvertIndexedExprRefToColumn().
*/
static int aggregateIdxEprRefToColCallback(Walker *pWalker, Expr *pExpr){
  AggInfo *pAggInfo;
  struct AggInfo_col *pCol;
  UNUSED_PARAMETER(pWalker);
  if( pExpr->pAggInfo==0 ) return WRC_Continue;
  if( pExpr->op==TK_AGG_COLUMN ) return WRC_Continue;
  if( pExpr->op==TK_AGG_FUNCTION ) return WRC_Continue;
  if( pExpr->op==TK_IF_NULL_ROW ) return WRC_Continue;
  pAggInfo = pExpr->pAggInfo;
  assert( pExpr->iAgg>=0 && pExpr->iAgg<pAggInfo->nColumn );
  pCol = &pAggInfo->aCol[pExpr->iAgg];
  pExpr->op = TK_AGG_COLUMN;
  pExpr->iTable = pCol->iTable;
  pExpr->iColumn = pCol->iColumn;
  return WRC_Prune;
}

/*
** Convert every pAggInfo->aFunc[].pExpr such that any node within
** those expressions that has pAppInfo set is changed into a TK_AGG_COLUMN
** opcode.
*/
static void aggregateConvertIndexedExprRefToColumn(AggInfo *pAggInfo){
  int i;
  Walker w;
  memset(&w, 0, sizeof(w));
  w.xExprCallback = aggregateIdxEprRefToColCallback;
  for(i=0; i<pAggInfo->nFunc; i++){
    sqlite3WalkExpr(&w, pAggInfo->aFunc[i].pFExpr);
  }
}


/*
** Allocate a block of registers so that there is one register for each
** pAggInfo->aCol[] and pAggInfo->aFunc[] entry in pAggInfo.  The first
** register in this block is stored in pAggInfo->iFirstReg.
**
** This routine may only be called once for each AggInfo object.  Prior
** to calling this routine:
**
**     *  The aCol[] and aFunc[] arrays may be modified
**     *  The AggInfoColumnReg() and AggInfoFuncReg() macros may not be used
**
** After clling this routine:
**
**     *  The aCol[] and aFunc[] arrays are fixed
**     *  The AggInfoColumnReg() and AggInfoFuncReg() macros may be used
**
*/
static void assignAggregateRegisters(Parse *pParse, AggInfo *pAggInfo){
  assert( pAggInfo!=0 );
  assert( pAggInfo->iFirstReg==0 );
  pAggInfo->iFirstReg = pParse->nMem + 1;
  pParse->nMem += pAggInfo->nColumn + pAggInfo->nFunc;
}

/*
** Reset the aggregate accumulator.
**
** The aggregate accumulator is a set of memory cells that hold
** intermediate results while calculating an aggregate.  This
** routine generates code that stores NULLs in all of those memory
** cells.
*/
static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
  Vdbe *v = pParse->pVdbe;
  int i;
  struct AggInfo_func *pFunc;
  int nReg = pAggInfo->nFunc + pAggInfo->nColumn;
  assert( pAggInfo->iFirstReg>0 );
  assert( pParse->db->pParse==pParse );
  assert( pParse->db->mallocFailed==0 || pParse->nErr!=0 );
  if( nReg==0 ) return;
#ifdef SQLITE_DEBUG
  /* Verify that all AggInfo registers are within the range specified by
  ** AggInfo.mnReg..AggInfo.mxReg */
  assert( nReg==pAggInfo->mxReg-pAggInfo->mnReg+1 );
  for(i=0; i<pAggInfo->nColumn; i++){
    assert( pAggInfo->aCol[i].iMem>=pAggInfo->mnReg
         && pAggInfo->aCol[i].iMem<=pAggInfo->mxReg );
  }
  for(i=0; i<pAggInfo->nFunc; i++){
    assert( pAggInfo->aFunc[i].iMem>=pAggInfo->mnReg
         && pAggInfo->aFunc[i].iMem<=pAggInfo->mxReg );
  }
#endif
  sqlite3VdbeAddOp3(v, OP_Null, 0, pAggInfo->mnReg, pAggInfo->mxReg);
  if( pParse->nErr ) return;
  sqlite3VdbeAddOp3(v, OP_Null, 0, pAggInfo->iFirstReg,
                    pAggInfo->iFirstReg+nReg-1);
  for(pFunc=pAggInfo->aFunc, i=0; i<pAggInfo->nFunc; i++, pFunc++){
    if( pFunc->iDistinct>=0 ){
      Expr *pE = pFunc->pExpr;
      assert( !ExprHasProperty(pE, EP_xIsSelect) );
      Expr *pE = pFunc->pFExpr;
      assert( ExprUseXList(pE) );
      if( pE->x.pList==0 || pE->x.pList->nExpr!=1 ){
        sqlite3ErrorMsg(pParse, "DISTINCT aggregates must have exactly one "
           "argument");
        pFunc->iDistinct = -1;
      }else{
        KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pE->x.pList,0,0);
        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
** in the AggInfo structure.
*/
static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
  Vdbe *v = pParse->pVdbe;
  int i;
  struct AggInfo_func *pF;
  for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
    ExprList *pList = pF->pExpr->x.pList;
    assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) );
    sqlite3VdbeAddOp2(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0);
    ExprList *pList;
    assert( ExprUseXList(pF->pFExpr) );
    pList = pF->pFExpr->x.pList;
    sqlite3VdbeAddOp2(v, OP_AggFinal, AggInfoFuncReg(pAggInfo,i),
                      pList ? pList->nExpr : 0);
    sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF);
  }
}


/*
** Update the accumulator memory cells for an aggregate based on
** the current cursor position.
** Generate code that will update the accumulator memory cells for an
** aggregate based on 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 i register regAcc contains 0. The caller will take care
** 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;

  assert( pAggInfo->iFirstReg>0 );
  if( pParse->nErr ) return;
  pAggInfo->directMode = 1;
  for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
    int nArg;
    int addrNext = 0;
    int regAgg;
    ExprList *pList = pF->pExpr->x.pList;
    assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) );
    ExprList *pList;
    assert( ExprUseXList(pF->pFExpr) );
    assert( !IsWindowFunc(pF->pFExpr) );
    pList = pF->pFExpr->x.pList;
    if( ExprHasProperty(pF->pFExpr, EP_WinFunc) ){
      Expr *pFilter = pF->pFExpr->y.pWin->pFilter;
      if( pAggInfo->nAccumulator 
       && (pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL) 
       && regAcc
      ){
        /* If regAcc==0, there there exists some min() or max() function
        ** without a FILTER clause that will ensure the magnet registers
        ** are populated. */
        if( regHit==0 ) regHit = ++pParse->nMem;
        /* If this is the first row of the group (regAcc contains 0), clear the
        ** "magnet" register regHit so that the accumulator registers
        ** are populated if the FILTER clause jumps over the the 
        ** invocation of min() or max() altogether. Or, if this is not
        ** the first row (regAcc contains 1), set the magnet register so that
        ** the accumulators are not populated unless the min()/max() is invoked
        ** and indicates that they should be.  */
        sqlite3VdbeAddOp2(v, OP_Copy, regAcc, regHit);
      }
      addrNext = sqlite3VdbeMakeLabel(pParse);
      sqlite3ExprIfFalse(pParse, pFilter, addrNext, SQLITE_JUMPIFNULL);
    }
    if( pList ){
      nArg = pList->nExpr;
      regAgg = sqlite3GetTempRange(pParse, nArg);
      sqlite3ExprCodeExprList(pParse, pList, regAgg, 0, SQLITE_ECEL_DUP);
    }else{
      nArg = 0;
      regAgg = 0;
    }
    if( pF->iDistinct>=0 ){
      addrNext = sqlite3VdbeMakeLabel(v);
    if( pF->iDistinct>=0 && pList ){
      if( addrNext==0 ){ 
        addrNext = sqlite3VdbeMakeLabel(pParse);
      testcase( nArg==0 );  /* Error condition */
      testcase( nArg>1 );   /* Also an error */
      codeDistinct(pParse, pF->iDistinct, addrNext, 1, regAgg);
      }
      pF->iDistinct = codeDistinct(pParse, eDistinctType, 
          pF->iDistinct, addrNext, pList, regAgg);
    }
    if( pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){
      CollSeq *pColl = 0;
      struct ExprList_item *pItem;
      int j;
      assert( pList!=0 );  /* pList!=0 if pF->pFunc has NEEDCOLL */
      for(j=0, pItem=pList->a; !pColl && j<nArg; j++, pItem++){
        pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr);
      }
      if( !pColl ){
        pColl = pParse->db->pDfltColl;
      }
      if( regHit==0 && pAggInfo->nAccumulator ) regHit = ++pParse->nMem;
      sqlite3VdbeAddOp4(v, OP_CollSeq, regHit, 0, 0, (char *)pColl, P4_COLLSEQ);
    }
    sqlite3VdbeAddOp3(v, OP_AggStep, 0, regAgg, pF->iMem);
    sqlite3VdbeAddOp3(v, OP_AggStep, 0, regAgg, AggInfoFuncReg(pAggInfo,i));
    sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF);
    sqlite3VdbeChangeP5(v, (u8)nArg);
    sqlite3ReleaseTempRange(pParse, regAgg, nArg);
    if( addrNext ){
      sqlite3VdbeResolveLabel(v, addrNext);
    }
  }
  if( regHit==0 && pAggInfo->nAccumulator ){
    regHit = regAcc;
  }
  if( regHit ){
    addrHitTest = sqlite3VdbeAddOp1(v, OP_If, regHit); VdbeCoverage(v);
  }
  for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){
    sqlite3ExprCode(pParse, pC->pExpr, pC->iMem);
    sqlite3ExprCode(pParse, pC->pCExpr, AggInfoColumnReg(pAggInfo,i));
  }

  pAggInfo->directMode = 0;
  if( addrHitTest ){
    sqlite3VdbeJumpHere(v, addrHitTest);
    sqlite3VdbeJumpHereOrPopInst(v, addrHitTest);
  }
}

/*
** Add a single OP_Explain instruction to the VDBE to explain a simple
** count(*) query ("SELECT count(*) FROM pTab").
*/
#ifndef SQLITE_OMIT_EXPLAIN
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
5405
5406
5407
5408
5409
5410
5411







5412




5413
5414

5415
5416
5417
5418

5419
5420
5421
5422
5423
5424
5425
6665
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







+
+
+
+
+
+
+
-
+
+
+
+

-
+



-
+







** sub-expression matches the criteria for being moved to the WHERE
** clause. If so, add it to the WHERE clause and replace the sub-expression
** within the HAVING expression with a constant "1".
*/
static int havingToWhereExprCb(Walker *pWalker, Expr *pExpr){
  if( pExpr->op!=TK_AND ){
    Select *pS = pWalker->u.pSelect;
    /* This routine is called before the HAVING clause of the current
    ** SELECT is analyzed for aggregates. So if pExpr->pAggInfo is set
    ** here, it indicates that the expression is a correlated reference to a
    ** column from an outer aggregate query, or an aggregate function that
    ** belongs to an outer query. Do not move the expression to the WHERE
    ** clause in this obscure case, as doing so may corrupt the outer Select
    ** statements AggInfo structure.  */
    if( sqlite3ExprIsConstantOrGroupBy(pWalker->pParse, pExpr, pS->pGroupBy) ){
    if( sqlite3ExprIsConstantOrGroupBy(pWalker->pParse, pExpr, pS->pGroupBy) 
     && ExprAlwaysFalse(pExpr)==0
     && pExpr->pAggInfo==0
    ){
      sqlite3 *db = pWalker->pParse->db;
      Expr *pNew = sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[1], 0);
      Expr *pNew = sqlite3Expr(db, TK_INTEGER, "1");
      if( pNew ){
        Expr *pWhere = pS->pWhere;
        SWAP(Expr, *pNew, *pExpr);
        pNew = sqlite3ExprAnd(db, pWhere, pNew);
        pNew = sqlite3ExprAnd(pWalker->pParse, pWhere, pNew);
        pS->pWhere = pNew;
        pWalker->eCode = 1;
      }
    }
    return WRC_Prune;
  }
  return WRC_Continue;
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452



5453
5454
5455
5456
5457
5458
5459
5460
5461






5462
5463

5464
5465


5466
5467
5468






5469
5470
5471

5472


5473
5474
5475

5476






5477
5478
5479
5480
5481
5482
5483
5484









5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501


5502
5503
5504
5505
5506
5507
5508
5509
5510
5511


5512
5513

5514

5515
5516
5517
5518
5519
5520
5521
6713
6714
6715
6716
6717
6718
6719



6720
6721
6722
6723
6724
6725
6726
6727
6728



6729
6730
6731
6732
6733
6734
6735

6736
6737

6738
6739
6740


6741
6742
6743
6744
6745
6746
6747
6748
6749
6750

6751
6752
6753


6754

6755
6756
6757
6758
6759
6760
6761
6762
6763
6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774
6775
6776
6777
6778
6779
6780
6781
6782
6783
6784
6785
6786
6787
6788
6789
6790
6791
6792
6793

6794
6795
6796
6797
6798
6799
6800
6801
6802
6803
6804
6805
6806
6807
6808
6809
6810
6811
6812
6813
6814
6815
6816
6817
6818
6819







-
-
-
+
+
+






-
-
-
+
+
+
+
+
+

-
+

-
+
+

-
-
+
+
+
+
+
+



+
-
+
+

-
-
+
-
+
+
+
+
+
+








+
+
+
+
+
+
+
+
+
















-
+
+










+
+


+

+







static void havingToWhere(Parse *pParse, Select *p){
  Walker sWalker;
  memset(&sWalker, 0, sizeof(sWalker));
  sWalker.pParse = pParse;
  sWalker.xExprCallback = havingToWhereExprCb;
  sWalker.u.pSelect = p;
  sqlite3WalkExpr(&sWalker, p->pHaving);
#if SELECTTRACE_ENABLED
  if( sWalker.eCode && (sqlite3SelectTrace & 0x100)!=0 ){
    SELECTTRACE(0x100,pParse,p,("Move HAVING terms into WHERE:\n"));
#if TREETRACE_ENABLED
  if( sWalker.eCode && (sqlite3TreeTrace & 0x100)!=0 ){
    TREETRACE(0x100,pParse,p,("Move HAVING terms into WHERE:\n"));
    sqlite3TreeViewSelect(0, p, 0);
  }
#endif
}

/*
** Check to see if the pThis entry of pTabList is a self-join of a prior view.
** If it is, then return the SrcList_item for the prior view.  If it is not,
** then return 0.
** Check to see if the pThis entry of pTabList is a self-join of another view.
** Search FROM-clause entries in the range of iFirst..iEnd, including iFirst
** but stopping before iEnd.
**
** If pThis is a self-join, then return the SrcItem for the first other
** instance of that view found.  If pThis is not a self-join then return 0.
*/
static struct SrcList_item *isSelfJoinView(
static SrcItem *isSelfJoinView(
  SrcList *pTabList,           /* Search for self-joins in this FROM clause */
  struct SrcList_item *pThis   /* Search for prior reference to this subquery */
  SrcItem *pThis,              /* Search for prior reference to this subquery */
  int iFirst, int iEnd        /* Range of FROM-clause entries to search. */
){
  struct SrcList_item *pItem;
  for(pItem = pTabList->a; pItem<pThis; pItem++){
  SrcItem *pItem;
  assert( pThis->pSelect!=0 );
  if( pThis->pSelect->selFlags & SF_PushDown ) return 0;
  while( iFirst<iEnd ){
    Select *pS1;
    pItem = &pTabList->a[iFirst++];
    if( pItem->pSelect==0 ) continue;
    if( pItem->fg.viaCoroutine ) continue;
    if( pItem->zName==0 ) continue;
    assert( pItem->pTab!=0 );
    if( sqlite3_stricmp(pItem->zDatabase, pThis->zDatabase)!=0 ) continue;
    assert( pThis->pTab!=0 );
    if( pItem->pTab->pSchema!=pThis->pTab->pSchema ) continue;
    if( sqlite3_stricmp(pItem->zName, pThis->zName)!=0 ) continue;
    if( sqlite3ExprCompare(0, 
          pThis->pSelect->pWhere, pItem->pSelect->pWhere, -1) 
    pS1 = pItem->pSelect;
    ){
    if( pItem->pTab->pSchema==0 && pThis->pSelect->selId!=pS1->selId ){
      /* The query flattener left two different CTE tables with identical
      ** names in the same FROM clause. */
      continue;
    }
    if( pItem->pSelect->selFlags & SF_PushDown ){
      /* The view was modified by some other optimization such as
      ** pushDownWhereTerms() */
      continue;
    }
    return pItem;
  }
  return 0;
}

/*
** Deallocate a single AggInfo object
*/
static void agginfoFree(sqlite3 *db, AggInfo *p){
  sqlite3DbFree(db, p->aCol);
  sqlite3DbFree(db, p->aFunc);
  sqlite3DbFreeNN(db, p);
}

#ifdef SQLITE_COUNTOFVIEW_OPTIMIZATION
/*
** Attempt to transform a query of the form
**
**    SELECT count(*) FROM (SELECT x FROM t1 UNION ALL SELECT y FROM t2)
**
** Into this:
**
**    SELECT (SELECT count(*) FROM t1)+(SELECT count(*) FROM t2)
**
** The transformation only works if all of the following are true:
**
**   *  The subquery is a UNION ALL of two or more terms
**   *  The subquery does not have a LIMIT clause
**   *  There is no WHERE or GROUP BY or HAVING clauses on the subqueries
**   *  The outer query is a simple count(*)
**   *  The outer query is a simple count(*) with no WHERE clause or other
**      extraneous syntax.
**
** Return TRUE if the optimization is undertaken.
*/
static int countOfViewOptimization(Parse *pParse, Select *p){
  Select *pSub, *pPrior;
  Expr *pExpr;
  Expr *pCount;
  sqlite3 *db;
  if( (p->selFlags & SF_Aggregate)==0 ) return 0;   /* This is an aggregate */
  if( p->pEList->nExpr!=1 ) return 0;               /* Single result column */
  if( p->pWhere ) return 0;
  if( p->pGroupBy ) return 0;
  pExpr = p->pEList->a[0].pExpr;
  if( pExpr->op!=TK_AGG_FUNCTION ) return 0;        /* Result is an aggregate */
  assert( ExprUseUToken(pExpr) );
  if( sqlite3_stricmp(pExpr->u.zToken,"count") ) return 0;  /* Is count() */
  assert( ExprUseXList(pExpr) );
  if( pExpr->x.pList!=0 ) return 0;                 /* Must be count(*) */
  if( p->pSrc->nSrc!=1 ) return 0;                  /* One table in FROM  */
  pSub = p->pSrc->a[0].pSelect;
  if( pSub==0 ) return 0;                           /* The FROM is a subquery */
  if( pSub->pPrior==0 ) return 0;                   /* Must be a compound ry */
  do{
    if( pSub->op!=TK_ALL && pSub->pPrior ) return 0;  /* Must be UNION ALL */
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562



5563
5564
5565
5566
5567
5568





















































































5569
5570
5571
5572
5573
5574
5575
6851
6852
6853
6854
6855
6856
6857



6858
6859
6860
6861
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
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
6903
6904
6905
6906
6907
6908
6909
6910
6911
6912
6913
6914
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
6943
6944
6945
6946
6947
6948
6949
6950
6951
6952
6953
6954
6955
6956
6957
6958







-
-
-
+
+
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







      pExpr = sqlite3PExpr(pParse, TK_PLUS, pTerm, pExpr);
    }
    pSub = pPrior;
  }
  p->pEList->a[0].pExpr = pExpr;
  p->selFlags &= ~SF_Aggregate;

#if SELECTTRACE_ENABLED
  if( sqlite3SelectTrace & 0x400 ){
    SELECTTRACE(0x400,pParse,p,("After count-of-view optimization:\n"));
#if TREETRACE_ENABLED
  if( sqlite3TreeTrace & 0x200 ){
    TREETRACE(0x200,pParse,p,("After count-of-view optimization:\n"));
    sqlite3TreeViewSelect(0, p, 0);
  }
#endif
  return 1;
}
#endif /* SQLITE_COUNTOFVIEW_OPTIMIZATION */

/*
** If any term of pSrc, or any SF_NestedFrom sub-query, is not the same
** as pSrcItem but has the same alias as p0, then return true.
** Otherwise return false.
*/
static int sameSrcAlias(SrcItem *p0, SrcList *pSrc){
  int i;
  for(i=0; i<pSrc->nSrc; i++){
    SrcItem *p1 = &pSrc->a[i];
    if( p1==p0 ) continue;
    if( p0->pTab==p1->pTab && 0==sqlite3_stricmp(p0->zAlias, p1->zAlias) ){
      return 1;
    }
    if( p1->pSelect
     && (p1->pSelect->selFlags & SF_NestedFrom)!=0
     && sameSrcAlias(p0, p1->pSelect->pSrc)
    ){
      return 1;
    }
  }
  return 0;
}

/*
** Return TRUE (non-zero) if the i-th entry in the pTabList SrcList can
** be implemented as a co-routine.  The i-th entry is guaranteed to be
** a subquery.
**
** The subquery is implemented as a co-routine if all of the following are
** true:
**
**    (1)  The subquery will likely be implemented in the outer loop of
**         the query.  This will be the case if any one of the following
**         conditions hold:
**         (a)  The subquery is the only term in the FROM clause
**         (b)  The subquery is the left-most term and a CROSS JOIN or similar
**              requires it to be the outer loop
**         (c)  All of the following are true:
**                (i) The subquery is the left-most subquery in the FROM clause
**               (ii) There is nothing that would prevent the subquery from
**                    being used as the outer loop if the sqlite3WhereBegin()
**                    routine nominates it to that position.
**              (iii) The query is not a UPDATE ... FROM
**    (2)  The subquery is not a CTE that should be materialized because
**         (a) the AS MATERIALIZED keyword is used, or
**         (b) the CTE is used multiple times and does not have the
**             NOT MATERIALIZED keyword
**    (3)  The subquery is not part of a left operand for a RIGHT JOIN
**    (4)  The SQLITE_Coroutine optimization disable flag is not set
**    (5)  The subquery is not self-joined
*/
static int fromClauseTermCanBeCoroutine(
  Parse *pParse,          /* Parsing context */
  SrcList *pTabList,      /* FROM clause */
  int i,                  /* Which term of the FROM clause holds the subquery */
  int selFlags            /* Flags on the SELECT statement */
){
  SrcItem *pItem = &pTabList->a[i];
  if( pItem->fg.isCte ){
    const CteUse *pCteUse = pItem->u2.pCteUse;
    if( pCteUse->eM10d==M10d_Yes ) return 0;                          /* (2a) */
    if( pCteUse->nUse>=2 && pCteUse->eM10d!=M10d_No ) return 0;       /* (2b) */
  }
  if( pTabList->a[0].fg.jointype & JT_LTORJ ) return 0;               /* (3)  */
  if( OptimizationDisabled(pParse->db, SQLITE_Coroutines) ) return 0; /* (4)  */
  if( isSelfJoinView(pTabList, pItem, i+1, pTabList->nSrc)!=0 ){
    return 0;                                                          /* (5) */
  }
  if( i==0 ){
    if( pTabList->nSrc==1 ) return 1;                             /* (1a) */
    if( pTabList->a[1].fg.jointype & JT_CROSS ) return 1;         /* (1b) */
    if( selFlags & SF_UpdateFrom )              return 0;         /* (1c-iii) */
    return 1;
  }
  if( selFlags & SF_UpdateFrom ) return 0;                        /* (1c-iii) */
  while( 1 /*exit-by-break*/ ){
    if( pItem->fg.jointype & (JT_OUTER|JT_CROSS)  ) return 0;     /* (1c-ii) */
    if( i==0 ) break;
    i--;
    pItem--;
    if( pItem->pSelect!=0 ) return 0;                             /* (1c-i) */
  }
  return 1;
}

/*
** Generate code for the SELECT statement given in the p argument.  
**
** The results are returned according to the SelectDest structure.
** See comments in sqliteInt.h for further information.
**
5590
5591
5592
5593
5594
5595
5596

5597
5598
5599
5600
5601
5602
5603
5604
5605
5606

5607
5608

5609
5610

5611
5612
5613
5614
5615
5616








5617
5618
5619
5620
5621
5622
5623
5624
5625
5626



5627
5628
5629
5630
5631
5632















5633

5634
5635
5636

5637
5638

5639
5640
5641
5642



5643
5644
5645
5646


























5647
5648

5649
5650
5651
5652

5653
5654
5655
5656
5657



5658
5659
5660
5661
5662
5663
5664
5665
5666
5667

5668
5669
5670
5671
5672

5673
5674





5675
5676
5677
5678
5679

5680
5681
5682
5683

5684
5685

5686


5687
5688
5689
5690
5691
5692
5693
6973
6974
6975
6976
6977
6978
6979
6980
6981
6982
6983

6984
6985
6986
6987
6988
6989
6990
6991

6992
6993
6994
6995
6996





6997
6998
6999
7000
7001
7002
7003
7004
7005
7006
7007
7008
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



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
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
7097

7098
7099
7100
7101
7102
7103
7104
7105
7106
7107
7108
7109

7110
7111
7112
7113

7114
7115
7116
7117

7118
7119
7120
7121
7122
7123
7124
7125
7126







+



-






+

-
+


+

-
-
-
-
-
+
+
+
+
+
+
+
+







-
-
-
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+


-
+


+

-
-
-
+
+
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+




+


-
-
-
+
+
+









-
+




-
+


+
+
+
+
+




-
+



-
+


+
-
+
+







  Vdbe *v;               /* The virtual machine under construction */
  int isAgg;             /* True for select lists like "count(*)" */
  ExprList *pEList = 0;  /* List of columns to extract. */
  SrcList *pTabList;     /* List of tables to select from */
  Expr *pWhere;          /* The WHERE clause.  May be NULL */
  ExprList *pGroupBy;    /* The GROUP BY clause.  May be NULL */
  Expr *pHaving;         /* The HAVING clause.  May be NULL */
  AggInfo *pAggInfo = 0; /* Aggregate information */
  int rc = 1;            /* Value to return from this function */
  DistinctCtx sDistinct; /* Info on how to code the DISTINCT keyword */
  SortCtx sSort;         /* Info on how to code the ORDER BY clause */
  AggInfo sAggInfo;      /* Information used by aggregate queries */
  int iEnd;              /* Address of the end of the query */
  sqlite3 *db;           /* The database connection */
  ExprList *pMinMaxOrderBy = 0;  /* Added ORDER BY for min/max queries */
  u8 minMaxFlag;                 /* Flag for min/max queries */

  db = pParse->db;
  assert( pParse==db->pParse );
  v = sqlite3GetVdbe(pParse);
  if( p==0 || db->mallocFailed || pParse->nErr ){
  if( p==0 || pParse->nErr ){
    return 1;
  }
  assert( db->mallocFailed==0 );
  if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
  memset(&sAggInfo, 0, sizeof(sAggInfo));
#if SELECTTRACE_ENABLED
  SELECTTRACE(1,pParse,p, ("begin processing:\n", pParse->addrExplain));
  if( sqlite3SelectTrace & 0x100 ){
    sqlite3TreeViewSelect(0, p, 0);
#if TREETRACE_ENABLED
  TREETRACE(0x1,pParse,p, ("begin processing:\n", pParse->addrExplain));
  if( sqlite3TreeTrace & 0x10000 ){
    if( (sqlite3TreeTrace & 0x10001)==0x10000 ){
      sqlite3TreeViewLine(0, "In sqlite3Select() at %s:%d",
                           __FILE__, __LINE__);
    }
    sqlite3ShowSelect(p);
  }
#endif

  assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistFifo );
  assert( p->pOrderBy==0 || pDest->eDest!=SRT_Fifo );
  assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistQueue );
  assert( p->pOrderBy==0 || pDest->eDest!=SRT_Queue );
  if( IgnorableOrderby(pDest) ){
    assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union || 
           pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard ||
  if( IgnorableDistinct(pDest) ){
    assert(pDest->eDest==SRT_Exists     || pDest->eDest==SRT_Union || 
           pDest->eDest==SRT_Except     || pDest->eDest==SRT_Discard ||
           pDest->eDest==SRT_Queue  || pDest->eDest==SRT_DistFifo ||
           pDest->eDest==SRT_DistQueue || pDest->eDest==SRT_Fifo);
    /* If ORDER BY makes no difference in the output then neither does
    ** DISTINCT so it can be removed too. */
    sqlite3ExprListDelete(db, p->pOrderBy);
    p->pOrderBy = 0;
           pDest->eDest==SRT_DistQueue  || pDest->eDest==SRT_DistFifo );
    /* All of these destinations are also able to ignore the ORDER BY clause */
    if( p->pOrderBy ){
#if TREETRACE_ENABLED
      TREETRACE(0x800,pParse,p, ("dropping superfluous ORDER BY:\n"));
      if( sqlite3TreeTrace & 0x800 ){
        sqlite3TreeViewExprList(0, p->pOrderBy, 0, "ORDERBY");
      }
#endif    
      sqlite3ParserAddCleanup(pParse,
        (void(*)(sqlite3*,void*))sqlite3ExprListDelete,
        p->pOrderBy);
      testcase( pParse->earlyCleanup );
      p->pOrderBy = 0;
    }
    p->selFlags &= ~SF_Distinct;
    p->selFlags |= SF_NoopOrderBy;
  }
  sqlite3SelectPrep(pParse, p, 0);
  if( pParse->nErr || db->mallocFailed ){
  if( pParse->nErr ){
    goto select_end;
  }
  assert( db->mallocFailed==0 );
  assert( p->pEList!=0 );
#if SELECTTRACE_ENABLED
  if( sqlite3SelectTrace & 0x104 ){
    SELECTTRACE(0x104,pParse,p, ("after name resolution:\n"));
#if TREETRACE_ENABLED
  if( sqlite3TreeTrace & 0x10 ){
    TREETRACE(0x10,pParse,p, ("after name resolution:\n"));
    sqlite3TreeViewSelect(0, p, 0);
  }
#endif

  /* If the SF_UFSrcCheck flag is set, then this function is being called
  ** as part of populating the temp table for an UPDATE...FROM statement.
  ** In this case, it is an error if the target object (pSrc->a[0]) name 
  ** or alias is duplicated within FROM clause (pSrc->a[1..n]).  
  **
  ** Postgres disallows this case too. The reason is that some other 
  ** systems handle this case differently, and not all the same way, 
  ** which is just confusing. To avoid this, we follow PG's lead and
  ** disallow it altogether.  */
  if( p->selFlags & SF_UFSrcCheck ){
    SrcItem *p0 = &p->pSrc->a[0];
    if( sameSrcAlias(p0, p->pSrc) ){
      sqlite3ErrorMsg(pParse, 
          "target object/alias may not appear in FROM clause: %s", 
          p0->zAlias ? p0->zAlias : p0->pTab->zName
      );
      goto select_end;
    }

    /* Clear the SF_UFSrcCheck flag. The check has already been performed,
    ** and leaving this flag set can cause errors if a compound sub-query
    ** in p->pSrc is flattened into this query and this function called
    ** again as part of compound SELECT processing.  */
    p->selFlags &= ~SF_UFSrcCheck;
  }

  if( pDest->eDest==SRT_Output ){
    generateColumnNames(pParse, p);
    sqlite3GenerateColumnNames(pParse, p);
  }

#ifndef SQLITE_OMIT_WINDOWFUNC
  if( sqlite3WindowRewrite(pParse, p) ){
    assert( pParse->nErr );
    goto select_end;
  }
#if SELECTTRACE_ENABLED
  if( sqlite3SelectTrace & 0x108 ){
    SELECTTRACE(0x104,pParse,p, ("after window rewrite:\n"));
#if TREETRACE_ENABLED
  if( p->pWin && (sqlite3TreeTrace & 0x40)!=0 ){
    TREETRACE(0x40,pParse,p, ("after window rewrite:\n"));
    sqlite3TreeViewSelect(0, p, 0);
  }
#endif
#endif /* SQLITE_OMIT_WINDOWFUNC */
  pTabList = p->pSrc;
  isAgg = (p->selFlags & SF_Aggregate)!=0;
  memset(&sSort, 0, sizeof(sSort));
  sSort.pOrderBy = p->pOrderBy;

  /* Try to various optimizations (flattening subqueries, and strength
  /* Try to do various optimizations (flattening subqueries, and strength
  ** reduction of join operators) in the FROM clause up into the main query
  */
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
  for(i=0; !p->pPrior && i<pTabList->nSrc; i++){
    struct SrcList_item *pItem = &pTabList->a[i];
    SrcItem *pItem = &pTabList->a[i];
    Select *pSub = pItem->pSelect;
    Table *pTab = pItem->pTab;

    /* The expander should have already created transient Table objects
    ** even for FROM clause elements such as subqueries that do not correspond
    ** to a real table */
    assert( pTab!=0 );

    /* Convert LEFT JOIN into JOIN if there are terms of the right table
    ** of the LEFT JOIN used in the WHERE clause.
    */
    if( (pItem->fg.jointype & JT_LEFT)!=0
    if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))==JT_LEFT
     && sqlite3ExprImpliesNonNullRow(p->pWhere, pItem->iCursor)
     && OptimizationEnabled(db, SQLITE_SimplifyJoin)
    ){
      SELECTTRACE(0x100,pParse,p,
      TREETRACE(0x1000,pParse,p,
                ("LEFT-JOIN simplifies to JOIN on term %d\n",i));
      pItem->fg.jointype &= ~(JT_LEFT|JT_OUTER);
      assert( pItem->iCursor>=0 );
      unsetJoinExpr(p->pWhere, pItem->iCursor);
      unsetJoinExpr(p->pWhere, pItem->iCursor,
                    pTabList->a[0].fg.jointype & JT_LTORJ);
    }

    /* No futher action if this term of the FROM clause is no a subquery */
    if( pSub==0 ) continue;

    /* Catch mismatch in the declared columns of a view and the number of
    ** columns in the SELECT on the RHS */
5702
5703
5704
5705
5706
5707
5708



































5709
5710
5711
5712
5713
5714
5715
7135
7136
7137
7138
7139
7140
7141
7142
7143
7144
7145
7146
7147
7148
7149
7150
7151
7152
7153
7154
7155
7156
7157
7158
7159
7160
7161
7162
7163
7164
7165
7166
7167
7168
7169
7170
7171
7172
7173
7174
7175
7176
7177
7178
7179
7180
7181
7182
7183







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    ** Flattening an aggregate subquery is only possible if the outer query
    ** is not a join.  But if the outer query is not a join, then the subquery
    ** will be implemented as a co-routine and there is no advantage to
    ** flattening in that case.
    */
    if( (pSub->selFlags & SF_Aggregate)!=0 ) continue;
    assert( pSub->pGroupBy==0 );

    /* If a FROM-clause subquery has an ORDER BY clause that is not
    ** really doing anything, then delete it now so that it does not
    ** interfere with query flattening.  See the discussion at
    ** https://sqlite.org/forum/forumpost/2d76f2bcf65d256a
    **
    ** Beware of these cases where the ORDER BY clause may not be safely
    ** omitted:
    **
    **    (1)   There is also a LIMIT clause
    **    (2)   The subquery was added to help with window-function
    **          processing
    **    (3)   The subquery is in the FROM clause of an UPDATE
    **    (4)   The outer query uses an aggregate function other than
    **          the built-in count(), min(), or max().
    **    (5)   The ORDER BY isn't going to accomplish anything because
    **          one of:
    **            (a)  The outer query has a different ORDER BY clause
    **            (b)  The subquery is part of a join
    **          See forum post 062d576715d277c8
    */
    if( pSub->pOrderBy!=0
     && (p->pOrderBy!=0 || pTabList->nSrc>1)      /* Condition (5) */
     && pSub->pLimit==0                           /* Condition (1) */
     && (pSub->selFlags & SF_OrderByReqd)==0      /* Condition (2) */
     && (p->selFlags & SF_OrderByReqd)==0         /* Condition (3) and (4) */
     && OptimizationEnabled(db, SQLITE_OmitOrderBy)
    ){
      TREETRACE(0x800,pParse,p,
                ("omit superfluous ORDER BY on %r FROM-clause subquery\n",i+1));
      sqlite3ParserAddCleanup(pParse, 
         (void(*)(sqlite3*,void*))sqlite3ExprListDelete,
         pSub->pOrderBy);
      pSub->pOrderBy = 0;
    }

    /* If the outer query contains a "complex" result set (that is,
    ** if the result set of the outer query uses functions or subqueries)
    ** and if the subquery contains an ORDER BY clause and if
    ** it will be implemented as a co-routine, then do not flatten.  This
    ** restriction allows SQL constructs like this:
    **
5725
5726
5727
5728
5729
5730
5731
5732

5733
5734
5735
5736
5737

5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757



5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771


5772
5773
5774
5775
5776
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
5803
5804
5805
5806
5807
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
7236
7237
7238
7239

7240
7241
7242
7243
7244



7245
7246
7247
7248
7249
7250
7251

7252
7253
7254
7255
7256
7257
7258
7259
7260
7261
7262
7263
7264
7265
7266
7267
7268
7269

7270
7271
7272
7273
7274
7275
7276
7277
7278







-
+





+

















-
-
-
+
+
+













-
+
+



-
-
-
+
+
+




-
+

















-
+
+







    **
    **  SELECT x FROM (SELECT x FROM tab ORDER BY y LIMIT 10);
    */
    if( pSub->pOrderBy!=0
     && i==0
     && (p->selFlags & SF_ComplexResult)!=0
     && (pTabList->nSrc==1
         || (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0)
         || (pTabList->a[1].fg.jointype&(JT_OUTER|JT_CROSS))!=0)
    ){
      continue;
    }

    if( flattenSubquery(pParse, p, i, isAgg) ){
      if( pParse->nErr ) goto select_end;
      /* This subquery can be absorbed into its parent. */
      i = -1;
    }
    pTabList = p->pSrc;
    if( db->mallocFailed ) goto select_end;
    if( !IgnorableOrderby(pDest) ){
      sSort.pOrderBy = p->pOrderBy;
    }
  }
#endif

#ifndef SQLITE_OMIT_COMPOUND_SELECT
  /* Handle compound SELECT statements using the separate multiSelect()
  ** procedure.
  */
  if( p->pPrior ){
    rc = multiSelect(pParse, p, pDest);
#if SELECTTRACE_ENABLED
    SELECTTRACE(0x1,pParse,p,("end compound-select processing\n"));
    if( (sqlite3SelectTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){
#if TREETRACE_ENABLED
    TREETRACE(0x400,pParse,p,("end compound-select processing\n"));
    if( (sqlite3TreeTrace & 0x400)!=0 && ExplainQueryPlanParent(pParse)==0 ){
      sqlite3TreeViewSelect(0, p, 0);
    }
#endif
    if( p->pNext==0 ) ExplainQueryPlanPop(pParse);
    return rc;
  }
#endif

  /* Do the WHERE-clause constant propagation optimization if this is
  ** a join.  No need to speed time on this operation for non-join queries
  ** as the equivalent optimization will be handled by query planner in
  ** sqlite3WhereBegin().
  */
  if( pTabList->nSrc>1
  if( p->pWhere!=0
   && p->pWhere->op==TK_AND
   && OptimizationEnabled(db, SQLITE_PropagateConst)
   && propagateConstants(pParse, p)
  ){
#if SELECTTRACE_ENABLED
    if( sqlite3SelectTrace & 0x100 ){
      SELECTTRACE(0x100,pParse,p,("After constant propagation:\n"));
#if TREETRACE_ENABLED
    if( sqlite3TreeTrace & 0x2000 ){
      TREETRACE(0x2000,pParse,p,("After constant propagation:\n"));
      sqlite3TreeViewSelect(0, p, 0);
    }
#endif
  }else{
    SELECTTRACE(0x100,pParse,p,("Constant propagation not helpful\n"));
    TREETRACE(0x2000,pParse,p,("Constant propagation not helpful\n"));
  }

#ifdef SQLITE_COUNTOFVIEW_OPTIMIZATION
  if( OptimizationEnabled(db, SQLITE_QueryFlattener|SQLITE_CountOfView)
   && countOfViewOptimization(pParse, p)
  ){
    if( db->mallocFailed ) goto select_end;
    pEList = p->pEList;
    pTabList = p->pSrc;
  }
#endif

  /* For each term in the FROM clause, do two things:
  ** (1) Authorized unreferenced tables
  ** (2) Generate code for all sub-queries
  */
  for(i=0; i<pTabList->nSrc; i++){
    struct SrcList_item *pItem = &pTabList->a[i];
    SrcItem *pItem = &pTabList->a[i];
    SrcItem *pPrior;
    SelectDest dest;
    Select *pSub;
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
    const char *zSavedAuthContext;
#endif

    /* Issue SQLITE_READ authorizations with a fake column name for any
5816
5817
5818
5819
5820
5821
5822
5823

5824
5825
5826
5827
5828
5829
5830
5831
5832
5833

5834
5835
5836
5837
5838
5839

5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862


5863

5864
5865
5866
5867
5868



5869
5870
5871
5872

5873
5874

5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890

5891
5892
5893
5894
5895
5896
5897
5898
5899
5900

5901
5902
5903

5904
5905
5906
5907
5908
5909
5910




















5911

5912
5913


5914
5915
5916
5917
5918

5919

5920

5921
5922
5923
5924

5925

5926
5927
5928
5929
5930
5931

5932
5933

5934
5935
5936
5937
5938
5939
5940
5941
5942
5943




5944
5945
5946
5947
5948
5949




5950







5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968



5969
5970
5971
5972
5973
5974
5975
7287
7288
7289
7290
7291
7292
7293

7294
7295
7296
7297
7298
7299
7300
7301
7302
7303

7304






7305









7306
7307
7308
7309
7310
7311
7312
7313
7314
7315
7316
7317
7318
7319
7320
7321

7322

7323



7324
7325
7326
7327
7328
7329
7330
7331
7332

7333
7334
7335
7336
7337
7338
7339







7340


7341


7342
7343
7344
7345
7346
7347
7348

7349
7350
7351

7352
7353
7354
7355
7356
7357
7358
7359
7360
7361
7362
7363
7364
7365
7366
7367
7368
7369
7370
7371
7372
7373
7374
7375
7376
7377
7378
7379
7380
7381


7382
7383



7384
7385
7386

7387

7388
7389

7390

7391
7392
7393
7394
7395
7396
7397
7398

7399
7400

7401
7402









7403
7404
7405
7406

7407
7408



7409
7410
7411
7412
7413
7414
7415
7416
7417
7418
7419
7420
7421
7422
7423
7424
7425
7426
7427
7428
7429
7430
7431
7432
7433
7434
7435



7436
7437
7438
7439
7440
7441
7442
7443
7444
7445







-
+









-
+
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-














+
+
-
+
-

-
-
-
+
+
+




+

-
+






-
-
-
-
-
-
-

-
-
+
-
-







-
+


-
+







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
-
-
+
+
-
-
-


+
-
+
-
+

-

-
+

+





-
+

-
+

-
-
-
-
-
-
-
-
-
+
+
+
+
-


-
-
-
+
+
+
+

+
+
+
+
+
+
+















-
-
-
+
+
+







    ** have a column named by the empty string, in which case there is no way to
    ** distinguish between an unreferenced table and an actual reference to the
    ** "" column. The original design was for the fake column name to be a NULL,
    ** which would be unambiguous.  But legacy authorization callbacks might
    ** assume the column name is non-NULL and segfault.  The use of an empty
    ** string for the fake column name seems safer.
    */
    if( pItem->colUsed==0 ){
    if( pItem->colUsed==0 && pItem->zName!=0 ){
      sqlite3AuthCheck(pParse, SQLITE_READ, pItem->zName, "", pItem->zDatabase);
    }

#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
    /* Generate code for all sub-queries in the FROM clause
    */
    pSub = pItem->pSelect;
    if( pSub==0 ) continue;

    /* Sometimes the code for a subquery will be generated more than
    /* The code for a subquery should only be generated once. */
    ** once, if the subquery is part of the WHERE clause in a LEFT JOIN,
    ** for example.  In that case, do not regenerate the code to manifest
    ** a view or the co-routine to implement a view.  The first instance
    ** is sufficient, though the subroutine to manifest the view does need
    ** to be invoked again. */
    if( pItem->addrFillSub ){
    assert( pItem->addrFillSub==0 );
      if( pItem->fg.viaCoroutine==0 ){
        /* The subroutine that manifests the view might be a one-time routine,
        ** or it might need to be rerun on each iteration because it
        ** encodes a correlated subquery. */
        testcase( sqlite3VdbeGetOp(v, pItem->addrFillSub)->opcode==OP_Once );
        sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub);
      }
      continue;
    }

    /* Increment Parse.nHeight by the height of the largest expression
    ** tree referred to by this, the parent select. The child select
    ** may contain expression trees of at most
    ** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit
    ** more conservative than necessary, but much easier than enforcing
    ** an exact limit.
    */
    pParse->nHeight += sqlite3SelectExprHeight(p);

    /* Make copies of constant WHERE-clause terms in the outer query down
    ** inside the subquery.  This can help the subquery to run more efficiently.
    */
    if( OptimizationEnabled(db, SQLITE_PushDown)
     && (pItem->fg.isCte==0 
         || (pItem->u2.pCteUse->eM10d!=M10d_Yes && pItem->u2.pCteUse->nUse<2))
     && pushDownWhereTerms(pParse, pSub, p->pWhere, pItem->iCursor,
     && pushDownWhereTerms(pParse, pSub, p->pWhere, pItem)
                           (pItem->fg.jointype & JT_OUTER)!=0)
    ){
#if SELECTTRACE_ENABLED
      if( sqlite3SelectTrace & 0x100 ){
        SELECTTRACE(0x100,pParse,p,
#if TREETRACE_ENABLED
      if( sqlite3TreeTrace & 0x4000 ){
        TREETRACE(0x4000,pParse,p,
            ("After WHERE-clause push-down into subquery %d:\n", pSub->selId));
        sqlite3TreeViewSelect(0, p, 0);
      }
#endif
      assert( pItem->pSelect && (pItem->pSelect->selFlags & SF_PushDown)!=0 );
    }else{
      SELECTTRACE(0x100,pParse,p,("Push-down not possible\n"));
      TREETRACE(0x4000,pParse,p,("Push-down not possible\n"));
    }

    zSavedAuthContext = pParse->zAuthContext;
    pParse->zAuthContext = pItem->zName;

    /* Generate code to implement the subquery
    **
    ** The subquery is implemented as a co-routine if the subquery is
    ** guaranteed to be the outer loop (so that it does not need to be
    ** computed more than once)
    **
    ** TODO: Are there other reasons beside (1) to use a co-routine
    ** implementation?
    */
    if( i==0
     && (pTabList->nSrc==1
    if( fromClauseTermCanBeCoroutine(pParse, pTabList, i, p->selFlags) ){
            || (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0)  /* (1) */
    ){
      /* 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);
    }else if( pItem->fg.isCte && pItem->u2.pCteUse->addrM9e>0 ){
      /* This is a CTE for which materialization code has already been
      ** generated.  Invoke the subroutine to compute the materialization,
      ** the make the pItem->iCursor be a copy of the ephemerial table that
      ** holds the result of the materialization. */
      CteUse *pCteUse = pItem->u2.pCteUse;
      sqlite3VdbeAddOp2(v, OP_Gosub, pCteUse->regRtn, pCteUse->addrM9e);
      if( pItem->iCursor!=pCteUse->iCur ){
        sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pCteUse->iCur);
        VdbeComment((v, "%!S", pItem));
      }
      pSub->nSelectRow = pCteUse->nRowEst;
    }else if( (pPrior = isSelfJoinView(pTabList, pItem, 0, i))!=0 ){
      /* This view has already been materialized by a prior entry in
      ** this same FROM clause.  Reuse it. */
      if( pPrior->addrFillSub ){
        sqlite3VdbeAddOp2(v, OP_Gosub, pPrior->regReturn, pPrior->addrFillSub);
      }
      sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pPrior->iCursor);
      pSub->nSelectRow = pPrior->pSelect->nSelectRow;
    }else{
      /* Materialize the view.  If the view is not correlated, generate a
      /* Generate a subroutine that will fill an ephemeral table with
      ** the content of this subquery.  pItem->addrFillSub will point
      ** subroutine to do the materialization so that subsequent uses of
      ** the same view can reuse the materialization. */
      ** to the address of the generated subroutine.  pItem->regReturn
      ** is a register allocated to hold the subroutine return address
      */
      int topAddr;
      int onceAddr = 0;
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
      int retAddr;
      int addrExplain;
      struct SrcList_item *pPrior;
#endif

      assert( pItem->addrFillSub==0 );
      pItem->regReturn = ++pParse->nMem;
      topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
      topAddr = sqlite3VdbeAddOp0(v, OP_Goto);
      pItem->addrFillSub = topAddr+1;
      pItem->fg.isMaterialized = 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));
      }
      pPrior = isSelfJoinView(pTabList, pItem);
      if( pPrior ){
        sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pPrior->iCursor);
        assert( pPrior->pSelect!=0 );
        pSub->nSelectRow = pPrior->pSelect->nSelectRow;
      }else{
        sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
        ExplainQueryPlan((pParse, 1, "MATERIALIZE %u", pSub->selId));
        sqlite3Select(pParse, pSub, &dest);
      sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);

      ExplainQueryPlan2(addrExplain, (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));
      sqlite3VdbeChangeP1(v, topAddr, retAddr);
      sqlite3VdbeAddOp2(v, OP_Return, pItem->regReturn, topAddr+1);
      VdbeComment((v, "end %!S", pItem));
      sqlite3VdbeScanStatusRange(v, addrExplain, addrExplain, -1);
      sqlite3VdbeJumpHere(v, topAddr);
      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;
        pCteUse->nRowEst = pSub->nSelectRow;
      }
    }
    if( db->mallocFailed ) goto select_end;
    pParse->nHeight -= sqlite3SelectExprHeight(p);
    pParse->zAuthContext = zSavedAuthContext;
#endif
  }

  /* Various elements of the SELECT copied into local variables for
  ** convenience */
  pEList = p->pEList;
  pWhere = p->pWhere;
  pGroupBy = p->pGroupBy;
  pHaving = p->pHaving;
  sDistinct.isTnct = (p->selFlags & SF_Distinct)!=0;

#if SELECTTRACE_ENABLED
  if( sqlite3SelectTrace & 0x400 ){
    SELECTTRACE(0x400,pParse,p,("After all FROM-clause analysis:\n"));
#if TREETRACE_ENABLED
  if( sqlite3TreeTrace & 0x8000 ){
    TREETRACE(0x8000,pParse,p,("After all FROM-clause analysis:\n"));
    sqlite3TreeViewSelect(0, p, 0);
  }
#endif

  /* If the query is DISTINCT with an ORDER BY but is not an aggregate, and 
  ** if the select-list is the same as the ORDER BY list, then this query
  ** can be rewritten as a GROUP BY. In other words, this:
5983
5984
5985
5986
5987
5988
5989



5990
5991
5992

5993
5994
5995
5996

5997
5998
5999
6000



6001
6002
6003
6004
6005
6006
6007
7453
7454
7455
7456
7457
7458
7459
7460
7461
7462
7463
7464
7465
7466
7467
7468
7469
7470
7471
7472



7473
7474
7475
7476
7477
7478
7479
7480
7481
7482







+
+
+



+




+

-
-
-
+
+
+







  ** The second form is preferred as a single index (or temp-table) may be 
  ** used for both the ORDER BY and DISTINCT processing. As originally 
  ** written the query must use a temp-table for at least one of the ORDER 
  ** BY and DISTINCT, and an index or separate temp-table for the other.
  */
  if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct 
   && sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0
#ifndef SQLITE_OMIT_WINDOWFUNC
   && p->pWin==0
#endif
  ){
    p->selFlags &= ~SF_Distinct;
    pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0);
    p->selFlags |= SF_Aggregate;
    /* Notice that even thought SF_Distinct has been cleared from p->selFlags,
    ** the sDistinct.isTnct is still set.  Hence, isTnct represents the
    ** original setting of the SF_Distinct flag, not the current setting */
    assert( sDistinct.isTnct );
    sDistinct.isTnct = 2;

#if SELECTTRACE_ENABLED
    if( sqlite3SelectTrace & 0x400 ){
      SELECTTRACE(0x400,pParse,p,("Transform DISTINCT into GROUP BY:\n"));
#if TREETRACE_ENABLED
    if( sqlite3TreeTrace & 0x20000 ){
      TREETRACE(0x20000,pParse,p,("Transform DISTINCT into GROUP BY:\n"));
      sqlite3TreeViewSelect(0, p, 0);
    }
#endif
  }

  /* If there is an ORDER BY clause, then create an ephemeral index to
  ** do the sorting.  But this sorting ephemeral index might end up
6025
6026
6027
6028
6029
6030
6031












6032
6033
6034
6035
6036

6037
6038
6039
6040

6041
6042
6043
6044
6045
6046
6047
7500
7501
7502
7503
7504
7505
7506
7507
7508
7509
7510
7511
7512
7513
7514
7515
7516
7517
7518
7519
7520
7521
7522

7523
7524
7525
7526

7527
7528
7529
7530
7531
7532
7533
7534







+
+
+
+
+
+
+
+
+
+
+
+




-
+



-
+







    sSort.addrSortIndex = -1;
  }

  /* If the output is destined for a temporary table, open that table.
  */
  if( pDest->eDest==SRT_EphemTab ){
    sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pDest->iSDParm, pEList->nExpr);
    if( p->selFlags & SF_NestedFrom ){
      /* Delete or NULL-out result columns that will never be used */
      int ii;
      for(ii=pEList->nExpr-1; ii>0 && pEList->a[ii].fg.bUsed==0; ii--){
        sqlite3ExprDelete(db, pEList->a[ii].pExpr);
        sqlite3DbFree(db, pEList->a[ii].zEName);
        pEList->nExpr--;
      }
      for(ii=0; ii<pEList->nExpr; ii++){
        if( pEList->a[ii].fg.bUsed==0 ) pEList->a[ii].pExpr->op = TK_NULL;
      }
    }
  }

  /* Set the limiter.
  */
  iEnd = sqlite3VdbeMakeLabel(v);
  iEnd = sqlite3VdbeMakeLabel(pParse);
  if( (p->selFlags & SF_FixedLimit)==0 ){
    p->nSelectRow = 320;  /* 4 billion rows */
  }
  computeLimitRegisters(pParse, p, iEnd);
  if( p->pLimit ) computeLimitRegisters(pParse, p, iEnd);
  if( p->iLimit==0 && sSort.addrSortIndex>=0 ){
    sqlite3VdbeChangeOpcode(v, sSort.addrSortIndex, OP_SorterOpen);
    sSort.sortFlags |= SORTFLAG_UseSorter;
  }

  /* Open an ephemeral index to use for the distinct set.
  */
6058
6059
6060
6061
6062
6063
6064
6065

6066
6067

6068
6069
6070
6071
6072
6073
6074

6075
6076

6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090

6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105



6106
6107
6108
6109
6110
6111
6112
7545
7546
7547
7548
7549
7550
7551

7552
7553

7554
7555
7556
7557
7558
7559
7560

7561
7562

7563
7564
7565
7566
7567
7568
7569
7570
7571
7572
7573
7574
7575
7576
7577
7578
7579
7580
7581
7582
7583
7584
7585
7586
7587
7588
7589
7590



7591
7592
7593
7594
7595
7596
7597
7598
7599
7600







-
+

-
+






-
+

-
+














+












-
-
-
+
+
+







  }

  if( !isAgg && pGroupBy==0 ){
    /* No aggregate functions and no GROUP BY clause */
    u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0)
                   | (p->selFlags & SF_FixedLimit);
#ifndef SQLITE_OMIT_WINDOWFUNC
    Window *pWin = p->pWin;      /* Master window object (or NULL) */
    Window *pWin = p->pWin;      /* Main window object (or NULL) */
    if( pWin ){
      sqlite3WindowCodeInit(pParse, pWin);
      sqlite3WindowCodeInit(pParse, p);
    }
#endif
    assert( WHERE_USE_LIMIT==SF_FixedLimit );


    /* Begin the database scan. */
    SELECTTRACE(1,pParse,p,("WhereBegin\n"));
    TREETRACE(0x2,pParse,p,("WhereBegin\n"));
    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, sSort.pOrderBy,
                               p->pEList, wctrlFlags, p->nSelectRow);
                               p->pEList, p, wctrlFlags, p->nSelectRow);
    if( pWInfo==0 ) goto select_end;
    if( sqlite3WhereOutputRowCount(pWInfo) < p->nSelectRow ){
      p->nSelectRow = sqlite3WhereOutputRowCount(pWInfo);
    }
    if( sDistinct.isTnct && sqlite3WhereIsDistinct(pWInfo) ){
      sDistinct.eTnctType = sqlite3WhereIsDistinct(pWInfo);
    }
    if( sSort.pOrderBy ){
      sSort.nOBSat = sqlite3WhereIsOrdered(pWInfo);
      sSort.labelOBLopt = sqlite3WhereOrderByLimitOptLabel(pWInfo);
      if( sSort.nOBSat==sSort.pOrderBy->nExpr ){
        sSort.pOrderBy = 0;
      }
    }
    TREETRACE(0x2,pParse,p,("WhereBegin returns\n"));

    /* If sorting index that was created by a prior OP_OpenEphemeral 
    ** instruction ended up not being needed, then change the OP_OpenEphemeral
    ** into an OP_Noop.
    */
    if( sSort.addrSortIndex>=0 && sSort.pOrderBy==0 ){
      sqlite3VdbeChangeToNoop(v, sSort.addrSortIndex);
    }

    assert( p->pEList==pEList );
#ifndef SQLITE_OMIT_WINDOWFUNC
    if( pWin ){
      int addrGosub = sqlite3VdbeMakeLabel(v);
      int iCont = sqlite3VdbeMakeLabel(v);
      int iBreak = sqlite3VdbeMakeLabel(v);
      int addrGosub = sqlite3VdbeMakeLabel(pParse);
      int iCont = sqlite3VdbeMakeLabel(pParse);
      int iBreak = sqlite3VdbeMakeLabel(pParse);
      int regGosub = ++pParse->nMem;

      sqlite3WindowCodeStep(pParse, p, pWInfo, regGosub, addrGosub);

      sqlite3VdbeAddOp2(v, OP_Goto, 0, iBreak);
      sqlite3VdbeResolveLabel(v, addrGosub);
      VdbeNoopComment((v, "inner-loop subroutine"));
6122
6123
6124
6125
6126
6127
6128

6129
6130
6131
6132
6133
6134
6135
7610
7611
7612
7613
7614
7615
7616
7617
7618
7619
7620
7621
7622
7623
7624







+







      /* Use the standard inner loop. */
      selectInnerLoop(pParse, p, -1, &sSort, &sDistinct, pDest,
          sqlite3WhereContinueLabel(pWInfo),
          sqlite3WhereBreakLabel(pWInfo));

      /* End the database scan loop.
      */
      TREETRACE(0x2,pParse,p,("WhereEnd\n"));
      sqlite3WhereEnd(pWInfo);
    }
  }else{
    /* This case when there exist aggregate functions or a GROUP BY clause
    ** or both */
    NameContext sNC;    /* Name context for processing aggregate information */
    int iAMem;          /* First Mem address for storing current GROUP BY */
6155
6156
6157
6158
6159
6160
6161

























6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180

6181
6182
6183
6184
6185













6186
6187
6188
6189

6190
6191
6192
6193


6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208



6209
6210
6211
6212
6213
6214

6215
6216
6217
6218
6219
6220
6221


6222
6223

6224
6225
6226


6227
6228

6229
6230
6231
6232

6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
















6252
6253
6254
6255
6256
6257
6258
6259



6260
6261

6262
6263
6264
6265
6266
6267
6268
6269

6270
6271

6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288




6289
6290










6291
6292
6293
6294
6295
6296
6297
7644
7645
7646
7647
7648
7649
7650
7651
7652
7653
7654
7655
7656
7657
7658
7659
7660
7661
7662
7663
7664
7665
7666
7667
7668
7669
7670
7671
7672
7673
7674
7675
7676
7677
7678
7679
7680












7681

7682
7683
7684
7685
7686
7687
7688
7689
7690
7691
7692
7693
7694
7695
7696
7697
7698
7699
7700
7701
7702
7703

7704
7705



7706
7707
7708
7709
7710
7711
7712
7713
7714
7715
7716
7717
7718
7719



7720
7721
7722
7723
7724
7725



7726




7727


7728
7729


7730
7731


7732
7733


7734
7735



7736


7737
7738
7739
7740
7741
7742
7743
7744
7745
7746
7747
7748
7749
7750
7751
7752
7753
7754
7755
7756
7757
7758
7759
7760
7761
7762
7763
7764
7765
7766
7767
7768
7769
7770
7771
7772
7773
7774
7775


7776
7777
7778
7779

7780
7781
7782
7783
7784
7785
7786
7787

7788
7789

7790
7791
7792
7793
7794
7795
7796
7797
7798
7799
7800
7801
7802
7803
7804



7805
7806
7807
7808
7809

7810
7811
7812
7813
7814
7815
7816
7817
7818
7819
7820
7821
7822
7823
7824
7825
7826







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
-
-
-
-
-
-
-
-
-
-
-

-
+





+
+
+
+
+
+
+
+
+
+
+
+
+



-
+

-
-
-
+
+












-
-
-
+
+
+



-
-
-
+
-
-
-
-

-
-
+
+
-
-
+

-
-
+
+
-
-
+

-
-
-
+
-
-

















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
-
+
+
+

-
+







-
+

-
+














-
-
-
+
+
+
+

-
+
+
+
+
+
+
+
+
+
+







        pItem->u.x.iAlias = 0;
      }
      for(k=pGroupBy->nExpr, pItem=pGroupBy->a; k>0; k--, pItem++){
        pItem->u.x.iAlias = 0;
      }
      assert( 66==sqlite3LogEst(100) );
      if( p->nSelectRow>66 ) p->nSelectRow = 66;

      /* If there is both a GROUP BY and an ORDER BY clause and they are
      ** identical, then it may be possible to disable the ORDER BY clause 
      ** on the grounds that the GROUP BY will cause elements to come out 
      ** in the correct order. It also may not - the GROUP BY might use a
      ** database index that causes rows to be grouped together as required
      ** but not actually sorted. Either way, record the fact that the
      ** ORDER BY and GROUP BY clauses are the same by setting the orderByGrp
      ** variable.  */
      if( sSort.pOrderBy && pGroupBy->nExpr==sSort.pOrderBy->nExpr ){
        int ii;
        /* The GROUP BY processing doesn't care whether rows are delivered in
        ** ASC or DESC order - only that each group is returned contiguously.
        ** So set the ASC/DESC flags in the GROUP BY to match those in the 
        ** ORDER BY to maximize the chances of rows being delivered in an 
        ** order that makes the ORDER BY redundant.  */
        for(ii=0; ii<pGroupBy->nExpr; ii++){
          u8 sortFlags;
          sortFlags = sSort.pOrderBy->a[ii].fg.sortFlags & KEYINFO_ORDER_DESC;
          pGroupBy->a[ii].fg.sortFlags = sortFlags;
        }
        if( sqlite3ExprListCompare(pGroupBy, sSort.pOrderBy, -1)==0 ){
          orderByGrp = 1;
        }
      }
    }else{
      assert( 0==sqlite3LogEst(1) );
      p->nSelectRow = 0;
    }

    /* If there is both a GROUP BY and an ORDER BY clause and they are
    ** identical, then it may be possible to disable the ORDER BY clause 
    ** on the grounds that the GROUP BY will cause elements to come out 
    ** in the correct order. It also may not - the GROUP BY might use a
    ** database index that causes rows to be grouped together as required
    ** but not actually sorted. Either way, record the fact that the
    ** ORDER BY and GROUP BY clauses are the same by setting the orderByGrp
    ** variable.  */
    if( sqlite3ExprListCompare(pGroupBy, sSort.pOrderBy, -1)==0 ){
      orderByGrp = 1;
    }
 
    /* Create a label to jump to when we want to abort the query */
    addrEnd = sqlite3VdbeMakeLabel(v);
    addrEnd = sqlite3VdbeMakeLabel(pParse);

    /* Convert TK_COLUMN nodes into TK_AGG_COLUMN and make entries in
    ** sAggInfo for all TK_AGG_FUNCTION nodes in expressions of the
    ** SELECT statement.
    */
    pAggInfo = sqlite3DbMallocZero(db, sizeof(*pAggInfo) );
    if( pAggInfo ){
      sqlite3ParserAddCleanup(pParse,
          (void(*)(sqlite3*,void*))agginfoFree, pAggInfo);
      testcase( pParse->earlyCleanup );
    }
    if( db->mallocFailed ){
      goto select_end;
    }
    pAggInfo->selId = p->selId;
#ifdef SQLITE_DEBUG
    pAggInfo->pSelect = p;
#endif
    memset(&sNC, 0, sizeof(sNC));
    sNC.pParse = pParse;
    sNC.pSrcList = pTabList;
    sNC.uNC.pAggInfo = &sAggInfo;
    sNC.uNC.pAggInfo = pAggInfo;
    VVA_ONLY( sNC.ncFlags = NC_UAggInfo; )
    sAggInfo.mnReg = pParse->nMem+1;
    sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr : 0;
    sAggInfo.pGroupBy = pGroupBy;
    pAggInfo->nSortingColumn = pGroupBy ? pGroupBy->nExpr : 0;
    pAggInfo->pGroupBy = pGroupBy;
    sqlite3ExprAnalyzeAggList(&sNC, pEList);
    sqlite3ExprAnalyzeAggList(&sNC, sSort.pOrderBy);
    if( pHaving ){
      if( pGroupBy ){
        assert( pWhere==p->pWhere );
        assert( pHaving==p->pHaving );
        assert( pGroupBy==p->pGroupBy );
        havingToWhere(pParse, p);
        pWhere = p->pWhere;
      }
      sqlite3ExprAnalyzeAggregates(&sNC, pHaving);
    }
    sAggInfo.nAccumulator = sAggInfo.nColumn;
    if( p->pGroupBy==0 && p->pHaving==0 && sAggInfo.nFunc==1 ){
      minMaxFlag = minMaxQuery(db, sAggInfo.aFunc[0].pExpr, &pMinMaxOrderBy);
    pAggInfo->nAccumulator = pAggInfo->nColumn;
    if( p->pGroupBy==0 && p->pHaving==0 && pAggInfo->nFunc==1 ){
      minMaxFlag = minMaxQuery(db, pAggInfo->aFunc[0].pFExpr, &pMinMaxOrderBy);
    }else{
      minMaxFlag = WHERE_ORDERBY_NORMAL;
    }
    for(i=0; i<sAggInfo.nFunc; i++){
      assert( !ExprHasProperty(sAggInfo.aFunc[i].pExpr, EP_xIsSelect) );
      sNC.ncFlags |= NC_InAggFunc;
    analyzeAggFuncArgs(pAggInfo, &sNC);
      sqlite3ExprAnalyzeAggList(&sNC, sAggInfo.aFunc[i].pExpr->x.pList);
      sNC.ncFlags &= ~NC_InAggFunc;
    }
    sAggInfo.mxReg = pParse->nMem;
    if( db->mallocFailed ) goto select_end;
#if SELECTTRACE_ENABLED
    if( sqlite3SelectTrace & 0x400 ){
#if TREETRACE_ENABLED
    if( sqlite3TreeTrace & 0x20 ){
      int ii;
      SELECTTRACE(0x400,pParse,p,("After aggregate analysis:\n"));
      TREETRACE(0x20,pParse,p,("After aggregate analysis %p:\n", pAggInfo));
      sqlite3TreeViewSelect(0, p, 0);
      for(ii=0; ii<sAggInfo.nColumn; ii++){
        sqlite3DebugPrintf("agg-column[%d] iMem=%d\n",
      if( minMaxFlag ){
        sqlite3DebugPrintf("MIN/MAX Optimization (0x%02x) adds:\n", minMaxFlag);
            ii, sAggInfo.aCol[ii].iMem);
        sqlite3TreeViewExpr(0, sAggInfo.aCol[ii].pExpr, 0);
        sqlite3TreeViewExprList(0, pMinMaxOrderBy, 0, "ORDERBY");
      }
      for(ii=0; ii<sAggInfo.nFunc; ii++){
        sqlite3DebugPrintf("agg-func[%d]: iMem=%d\n",
            ii, sAggInfo.aFunc[ii].iMem);
      printAggInfo(pAggInfo);
        sqlite3TreeViewExpr(0, sAggInfo.aFunc[ii].pExpr, 0);
      }
    }
#endif


    /* Processing for aggregates with GROUP BY is very different and
    ** much more complex than aggregates without a GROUP BY.
    */
    if( pGroupBy ){
      KeyInfo *pKeyInfo;  /* Keying information for the group by clause */
      int addr1;          /* A-vs-B comparision jump */
      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
       && ALWAYS(pAggInfo->aFunc[0].pFExpr!=0)
       && ALWAYS(ExprUseXList(pAggInfo->aFunc[0].pFExpr))
       && pAggInfo->aFunc[0].pFExpr->x.pList!=0
      ){
        Expr *pExpr = pAggInfo->aFunc[0].pFExpr->x.pList->a[0].pExpr;
        pExpr = sqlite3ExprDup(db, pExpr, 0);
        pDistinct = sqlite3ExprListDup(db, pGroupBy, 0);
        pDistinct = sqlite3ExprListAppend(pParse, pDistinct, pExpr);
        distFlag = pDistinct ? (WHERE_WANT_DISTINCT|WHERE_AGG_DISTINCT) : 0;
      }

      /* 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.  
      */
      sAggInfo.sortingIdx = pParse->nTab++;
      pKeyInfo = sqlite3KeyInfoFromExprList(pParse,pGroupBy,0,sAggInfo.nColumn);
      pAggInfo->sortingIdx = pParse->nTab++;
      pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pGroupBy,
                                            0, pAggInfo->nColumn);
      addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen, 
          sAggInfo.sortingIdx, sAggInfo.nSortingColumn, 
          pAggInfo->sortingIdx, pAggInfo->nSortingColumn, 
          0, (char*)pKeyInfo, P4_KEYINFO);

      /* Initialize memory locations used by GROUP BY aggregate processing
      */
      iUseFlag = ++pParse->nMem;
      iAbortFlag = ++pParse->nMem;
      regOutputRow = ++pParse->nMem;
      addrOutputRow = sqlite3VdbeMakeLabel(v);
      addrOutputRow = sqlite3VdbeMakeLabel(pParse);
      regReset = ++pParse->nMem;
      addrReset = sqlite3VdbeMakeLabel(v);
      addrReset = sqlite3VdbeMakeLabel(pParse);
      iAMem = pParse->nMem + 1;
      pParse->nMem += pGroupBy->nExpr;
      iBMem = pParse->nMem + 1;
      pParse->nMem += pGroupBy->nExpr;
      sqlite3VdbeAddOp2(v, OP_Integer, 0, iAbortFlag);
      VdbeComment((v, "clear abort flag"));
      sqlite3VdbeAddOp3(v, OP_Null, 0, iAMem, iAMem+pGroupBy->nExpr-1);

      /* 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
      TREETRACE(0x2,pParse,p,("WhereBegin\n"));
      pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, pDistinct,
          p, (sDistinct.isTnct==2 ? WHERE_DISTINCTBY : WHERE_GROUPBY) 
          |  (orderByGrp ? WHERE_SORTBYGROUP : 0) | distFlag, 0
      );
      if( pWInfo==0 ) goto select_end;
      if( pWInfo==0 ){
        sqlite3ExprListDelete(db, pDistinct);
        goto select_end;
      }
      if( pParse->pIdxEpr ){
        optimizeAggregateUseOfIndexedExpr(pParse, p, pAggInfo, &sNC);
      }
      assignAggregateRegisters(pParse, pAggInfo);
      eDist = sqlite3WhereIsDistinct(pWInfo);
      TREETRACE(0x2,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;
      }else{
6309
6310
6311
6312
6313
6314
6315
6316
6317


6318
6319
6320
6321
6322
6323
6324

6325
6326


6327
6328
6329

6330
6331
6332
6333

6334
6335
6336

6337
6338

6339
6340

6341
6342
6343

6344
6345


















6346
6347
6348
6349
6350
6351
6352
7838
7839
7840
7841
7842
7843
7844


7845
7846
7847
7848
7849
7850
7851
7852
7853
7854


7855
7856
7857


7858

7859
7860
7861
7862
7863
7864

7865
7866
7867
7868
7869

7870
7871
7872

7873
7874

7875
7876
7877
7878
7879
7880
7881
7882
7883
7884
7885
7886
7887
7888
7889
7890
7891
7892
7893
7894
7895
7896
7897
7898
7899







-
-
+
+







+
-
-
+
+

-
-
+
-



+


-
+


+

-
+


-
+

-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







            (sDistinct.isTnct && (p->selFlags&SF_Distinct)==0) ?
                    "DISTINCT" : "GROUP BY");

        groupBySort = 1;
        nGroupBy = pGroupBy->nExpr;
        nCol = nGroupBy;
        j = nGroupBy;
        for(i=0; i<sAggInfo.nColumn; i++){
          if( sAggInfo.aCol[i].iSorterColumn>=j ){
        for(i=0; i<pAggInfo->nColumn; i++){
          if( pAggInfo->aCol[i].iSorterColumn>=j ){
            nCol++;
            j++;
          }
        }
        regBase = sqlite3GetTempRange(pParse, nCol);
        sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, 0, 0);
        j = nGroupBy;
        pAggInfo->directMode = 1;
        for(i=0; i<sAggInfo.nColumn; i++){
          struct AggInfo_col *pCol = &sAggInfo.aCol[i];
        for(i=0; i<pAggInfo->nColumn; i++){
          struct AggInfo_col *pCol = &pAggInfo->aCol[i];
          if( pCol->iSorterColumn>=j ){
            int r1 = j + regBase;
            sqlite3ExprCodeGetColumnOfTable(v,
            sqlite3ExprCode(pParse, pCol->pCExpr, j + regBase);
                               pCol->pTab, pCol->iTable, pCol->iColumn, r1);
            j++;
          }
        }
        pAggInfo->directMode = 0;
        regRecord = sqlite3GetTempReg(pParse);
        sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regRecord);
        sqlite3VdbeAddOp2(v, OP_SorterInsert, sAggInfo.sortingIdx, regRecord);
        sqlite3VdbeAddOp2(v, OP_SorterInsert, pAggInfo->sortingIdx, regRecord);
        sqlite3ReleaseTempReg(pParse, regRecord);
        sqlite3ReleaseTempRange(pParse, regBase, nCol);
        TREETRACE(0x2,pParse,p,("WhereEnd\n"));
        sqlite3WhereEnd(pWInfo);
        sAggInfo.sortingIdxPTab = sortPTab = pParse->nTab++;
        pAggInfo->sortingIdxPTab = sortPTab = pParse->nTab++;
        sortOut = sqlite3GetTempReg(pParse);
        sqlite3VdbeAddOp3(v, OP_OpenPseudo, sortPTab, sortOut, nCol);
        sqlite3VdbeAddOp2(v, OP_SorterSort, sAggInfo.sortingIdx, addrEnd);
        sqlite3VdbeAddOp2(v, OP_SorterSort, pAggInfo->sortingIdx, addrEnd);
        VdbeComment((v, "GROUP BY sort")); VdbeCoverage(v);
        sAggInfo.useSortingIdx = 1;
        pAggInfo->useSortingIdx = 1;
      }

      /* If there entries in pAgggInfo->aFunc[] that contain subexpressions
      ** that are indexed (and that were previously identified and tagged
      ** in optimizeAggregateUseOfIndexedExpr()) then those subexpressions
      ** must now be converted into a TK_AGG_COLUMN node so that the value
      ** is correctly pulled from the index rather than being recomputed. */
      if( pParse->pIdxEpr ){
        aggregateConvertIndexedExprRefToColumn(pAggInfo);
#if TREETRACE_ENABLED
        if( sqlite3TreeTrace & 0x20 ){
          TREETRACE(0x20, pParse, p,
             ("AggInfo function expressions converted to reference index\n"));
          sqlite3TreeViewSelect(0, p, 0);
          printAggInfo(pAggInfo);
        }
#endif
      }

      /* If the index or temporary table used by the GROUP BY sort
      ** will naturally deliver rows in the order required by the ORDER BY
      ** clause, cancel the ephemeral table open coded earlier.
      **
      ** This is an optimization - the correct answer should result regardless.
6362
6363
6364
6365
6366
6367
6368
6369

6370
6371
6372
6373
6374
6375
6376

6377
6378
6379
6380
6381
6382
6383
7909
7910
7911
7912
7913
7914
7915

7916
7917
7918
7919
7920
7921
7922

7923
7924
7925
7926
7927
7928
7929
7930







-
+






-
+







      /* Evaluate the current GROUP BY terms and store in b0, b1, b2...
      ** (b0 is memory location iBMem+0, b1 is iBMem+1, and so forth)
      ** Then compare the current GROUP BY terms against the GROUP BY terms
      ** from the previous row currently stored in a0, a1, a2...
      */
      addrTopOfLoop = sqlite3VdbeCurrentAddr(v);
      if( groupBySort ){
        sqlite3VdbeAddOp3(v, OP_SorterData, sAggInfo.sortingIdx,
        sqlite3VdbeAddOp3(v, OP_SorterData, pAggInfo->sortingIdx,
                          sortOut, sortPTab);
      }
      for(j=0; j<pGroupBy->nExpr; j++){
        if( groupBySort ){
          sqlite3VdbeAddOp3(v, OP_Column, sortPTab, j, iBMem+j);
        }else{
          sAggInfo.directMode = 1;
          pAggInfo->directMode = 1;
          sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j);
        }
      }
      sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy->nExpr,
                          (char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO);
      addr1 = sqlite3VdbeCurrentAddr(v);
      sqlite3VdbeAddOp3(v, OP_Jump, addr1+1, 0, addr1+1); VdbeCoverage(v);
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
7946
7947
7948
7949
7950
7951
7952

7953
7954
7955
7956
7957
7958
7959

7960
7961
7962
7963
7964
7965
7966
7967
7968
7969
7970
7971
7972
7973
7974







-
+






-
+


+



+







      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, &sAggInfo);
      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, sAggInfo.sortingIdx, addrTopOfLoop);
        sqlite3VdbeAddOp2(v, OP_SorterNext, pAggInfo->sortingIdx,addrTopOfLoop);
        VdbeCoverage(v);
      }else{
        TREETRACE(0x2,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
6439
6440
6441
6442
6443
6444
6445
6446

6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
6457

6458
6459
6460
6461





6462
6463
6464
6465
6466

6467
6468
6469
6470
6471
6472
6473
6474
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485

6486
6487
6488
6489
6490
6491
6492
6493
6494
6495
6496
6497
6498
6499

6500
6501
6502
6503
6504
6505
6506








6507
6508
6509
6510
6511
6512
6513
6514
6515

6516
6517
6518

6519

6520
6521
6522

6523
6524
6525



6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536



















6537
6538
6539




6540

6541
6542
6543
6544
6545
6546
6547

6548
6549
6550
6551
6552
6553
6554
6555
6556
6557

6558
6559

6560
6561
6562


6563








6564
6565
6566


6567
6568
6569

6570
6571

6572
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583
6584
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608


6609








6610
6611
6612
6613
6614












6615
6616
6617
6618
6619
6620
7988
7989
7990
7991
7992
7993
7994

7995
7996
7997
7998
7999
8000
8001
8002
8003
8004
8005

8006
8007
8008
8009

8010
8011
8012
8013
8014
8015
8016

8017

8018
8019
8020
8021
8022
8023
8024
8025
8026
8027
8028
8029
8030
8031
8032
8033
8034
8035
8036

8037
8038
8039
8040
8041
8042
8043
8044
8045
8046
8047
8048
8049
8050
8051
8052







8053
8054
8055
8056
8057
8058
8059
8060
8061
8062
8063
8064
8065
8066
8067
8068

8069
8070
8071
8072
8073

8074
8075
8076

8077


8078
8079
8080
8081
8082










8083
8084
8085
8086
8087
8088
8089
8090
8091
8092
8093
8094
8095
8096
8097
8098
8099
8100
8101
8102
8103
8104
8105
8106
8107
8108
8109
8110
8111
8112
8113
8114
8115
8116

8117
8118
8119
8120
8121
8122
8123
8124
8125
8126

8127
8128

8129
8130
8131
8132
8133
8134

8135
8136
8137
8138
8139
8140
8141
8142
8143


8144
8145


8146
8147
8148

8149
8150
8151
8152
8153
8154
8155
8156
8157
8158
8159
8160
8161
8162
8163
8164
8165
8166
8167
8168


8169
8170
8171
8172
8173
8174
8175
8176
8177
8178
8179
8180
8181
8182
8183
8184
8185
8186
8187
8188
8189
8190
8191
8192
8193
8194
8195





8196
8197
8198
8199
8200
8201
8202
8203
8204
8205
8206
8207
8208
8209
8210
8211
8212
8213







-
+










-
+



-
+
+
+
+
+


-

-
+


















-
+














+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+








-
+



+
-
+


-
+
-
-

+
+
+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



+
+
+
+

+






-
+









-
+

-
+



+
+
-
+
+
+
+
+
+
+
+

-
-
+
+
-
-

+

-
+



















-
-
















+
+

+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+






      sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
      sqlite3VdbeResolveLabel(v, addrOutputRow);
      addrOutputRow = sqlite3VdbeCurrentAddr(v);
      sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2);
      VdbeCoverage(v);
      VdbeComment((v, "Groupby result generator entry point"));
      sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
      finalizeAggFunctions(pParse, &sAggInfo);
      finalizeAggFunctions(pParse, pAggInfo);
      sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL);
      selectInnerLoop(pParse, p, -1, &sSort,
                      &sDistinct, pDest,
                      addrOutputRow+1, addrSetAbort);
      sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
      VdbeComment((v, "end groupby result generator"));

      /* Generate a subroutine that will reset the group-by accumulator
      */
      sqlite3VdbeResolveLabel(v, addrReset);
      resetAccumulator(pParse, &sAggInfo);
      resetAccumulator(pParse, pAggInfo);
      sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag);
      VdbeComment((v, "indicate accumulator empty"));
      sqlite3VdbeAddOp1(v, OP_Return, regReset);
     

      if( distFlag!=0 && 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 {
#ifndef SQLITE_OMIT_BTREECOUNT
      Table *pTab;
      if( (pTab = isSimpleCount(p, &sAggInfo))!=0 ){
      if( (pTab = isSimpleCount(p, pAggInfo))!=0 ){
        /* If isSimpleCount() returns a pointer to a Table structure, then
        ** the SQL statement is of the form:
        **
        **   SELECT count(*) FROM <tbl>
        **
        ** where the Table structure returned represents table <tbl>.
        **
        ** This statement is so common that it is optimized specially. The
        ** OP_Count instruction is executed either on the intkey table that
        ** contains the data for table <tbl> or on one of its indexes. It
        ** is better to execute the op on an index, as indexes are almost
        ** always spread across less pages than their corresponding tables.
        */
        const int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
        const int iCsr = pParse->nTab++;     /* Cursor to scan b-tree */
        Index *pIdx;                         /* Iterator variable */
        KeyInfo *pKeyInfo = 0;               /* Keyinfo for scanned index */
        Index *pBest = 0;                    /* Best index found so far */
        int iRoot = pTab->tnum;              /* Root page of scanned b-tree */
        Pgno iRoot = pTab->tnum;             /* Root page of scanned b-tree */

        sqlite3CodeVerifySchema(pParse, iDb);
        sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);

        /* Search for the index that has the lowest scan cost.
        **
        ** (2011-04-15) Do not do a full scan of an unordered index.
        **
        ** (2013-10-03) Do not count the entries in a partial index.
        **
        ** In practice the KeyInfo structure will not be used. It is only 
        ** passed to keep OP_OpenRead happy.
        */
        if( !HasRowid(pTab) ) pBest = sqlite3PrimaryKeyIndex(pTab);
        if( !p->pSrc->a[0].fg.notIndexed ){
        for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
          if( pIdx->bUnordered==0
           && pIdx->szIdxRow<pTab->szTabRow
           && pIdx->pPartIdxWhere==0
           && (!pBest || pIdx->szIdxRow<pBest->szIdxRow)
          ){
            pBest = pIdx;
          for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
            if( pIdx->bUnordered==0
             && pIdx->szIdxRow<pTab->szTabRow
             && pIdx->pPartIdxWhere==0
             && (!pBest || pIdx->szIdxRow<pBest->szIdxRow)
            ){
              pBest = pIdx;
            }
          }
        }
        if( pBest ){
          iRoot = pBest->tnum;
          pKeyInfo = sqlite3KeyInfoOfIndex(pParse, pBest);
        }

        /* Open a read-only cursor, execute the OP_Count, close the cursor. */
        sqlite3VdbeAddOp4Int(v, OP_OpenRead, iCsr, iRoot, iDb, 1);
        sqlite3VdbeAddOp4Int(v, OP_OpenRead, iCsr, (int)iRoot, iDb, 1);
        if( pKeyInfo ){
          sqlite3VdbeChangeP4(v, -1, (char *)pKeyInfo, P4_KEYINFO);
        }
        assignAggregateRegisters(pParse, pAggInfo);
        sqlite3VdbeAddOp2(v, OP_Count, iCsr, sAggInfo.aFunc[0].iMem);
        sqlite3VdbeAddOp2(v, OP_Count, iCsr, AggInfoFuncReg(pAggInfo,0));
        sqlite3VdbeAddOp1(v, OP_Close, iCsr);
        explainSimpleCount(pParse, pTab, pBest);
      }else
      }else{
#endif /* SQLITE_OMIT_BTREECOUNT */
      {
        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,
        ** allocate register regAcc. Register regAcc will contain 0 the first
        ** time the inner loop runs, and 1 thereafter. The code generated
        ** by updateAccumulator() only updates the accumulator registers if
        ** regAcc contains 0.  */
        if( sAggInfo.nAccumulator ){
          for(i=0; i<sAggInfo.nFunc; i++){
            if( sAggInfo.aFunc[i].pFunc->funcFlags&SQLITE_FUNC_NEEDCOLL ) break;
          }
          if( i==sAggInfo.nFunc ){
        /* 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
        ** first row visited by the aggregate, so that they are updated at
        ** least once even if the FILTER clause means the min() or max() 
        ** function visits zero rows.  */
        if( pAggInfo->nAccumulator ){
          for(i=0; i<pAggInfo->nFunc; i++){
            if( ExprHasProperty(pAggInfo->aFunc[i].pFExpr, EP_WinFunc) ){
              continue;
            }
            if( pAggInfo->aFunc[i].pFunc->funcFlags&SQLITE_FUNC_NEEDCOLL ){
              break;
            }
          }
          if( i==pAggInfo->nFunc ){
            regAcc = ++pParse->nMem;
            sqlite3VdbeAddOp2(v, OP_Integer, 0, regAcc);
          }
        }else if( pAggInfo->nFunc==1 && pAggInfo->aFunc[0].iDistinct>=0 ){
          assert( ExprUseXList(pAggInfo->aFunc[0].pFExpr) );
          pDistinct = pAggInfo->aFunc[0].pFExpr->x.pList;
          distFlag = pDistinct ? (WHERE_WANT_DISTINCT|WHERE_AGG_DISTINCT) : 0;
        }
        assignAggregateRegisters(pParse, pAggInfo);

        /* 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, &sAggInfo);
        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"));
        TREETRACE(0x2,pParse,p,("WhereBegin\n"));
        pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMaxOrderBy,
                                   0, minMaxFlag, 0);
                                   pDistinct, p, minMaxFlag|distFlag, 0);
        if( pWInfo==0 ){
          goto select_end;
        }
        TREETRACE(0x2,pParse,p,("WhereBegin returns\n"));
        eDist = sqlite3WhereIsDistinct(pWInfo);
        updateAccumulator(pParse, regAcc, &sAggInfo);
        updateAccumulator(pParse, regAcc, pAggInfo, eDist);
        if( eDist!=WHERE_DISTINCT_NOOP ){
          struct AggInfo_func *pF = pAggInfo->aFunc;
          if( pF ){
            fixDistinctOpenEph(pParse, eDist, pF->iDistinct, pF->iDistAddr);
          }
        }

        if( regAcc ) sqlite3VdbeAddOp2(v, OP_Integer, 1, regAcc);
        if( sqlite3WhereIsOrdered(pWInfo)>0 ){
          sqlite3VdbeGoto(v, sqlite3WhereBreakLabel(pWInfo));
        if( minMaxFlag ){
          sqlite3WhereMinMaxOptEarlyOut(v, pWInfo);
          VdbeComment((v, "%s() by index",
                (minMaxFlag==WHERE_ORDERBY_MIN?"min":"max")));
        }
        TREETRACE(0x2,pParse,p,("WhereEnd\n"));
        sqlite3WhereEnd(pWInfo);
        finalizeAggFunctions(pParse, &sAggInfo);
        finalizeAggFunctions(pParse, pAggInfo);
      }

      sSort.pOrderBy = 0;
      sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL);
      selectInnerLoop(pParse, p, -1, 0, 0, 
                      pDest, addrEnd, addrEnd);
    }
    sqlite3VdbeResolveLabel(v, addrEnd);
    
  } /* endif aggregate query */

  if( sDistinct.eTnctType==WHERE_DISTINCT_UNORDERED ){
    explainTempTable(pParse, "DISTINCT");
  }

  /* If there is an ORDER BY clause, then we need to sort the results
  ** and send them to the callback one by one.
  */
  if( sSort.pOrderBy ){
    explainTempTable(pParse,
                     sSort.nOBSat>0 ? "RIGHT PART OF ORDER BY":"ORDER BY");
    assert( p->pEList==pEList );
    generateSortTail(pParse, p, &sSort, pEList->nExpr, pDest);
  }

  /* Jump here to skip this query
  */
  sqlite3VdbeResolveLabel(v, iEnd);

  /* The SELECT has been coded. If there is an error in the Parse structure,
  ** 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 );
  assert( db->mallocFailed==0 || pParse->nErr!=0 );
  sqlite3ExprListDelete(db, pMinMaxOrderBy);
#ifdef SQLITE_DEBUG
  if( pAggInfo && !db->mallocFailed ){
    for(i=0; i<pAggInfo->nColumn; i++){
      Expr *pExpr = pAggInfo->aCol[i].pCExpr;
      if( pExpr==0 ) continue;
      assert( pExpr->pAggInfo==pAggInfo );
      assert( pExpr->iAgg==i );
    }
  sqlite3DbFree(db, sAggInfo.aCol);
  sqlite3DbFree(db, sAggInfo.aFunc);
#if SELECTTRACE_ENABLED
  SELECTTRACE(0x1,pParse,p,("end processing\n"));
  if( (sqlite3SelectTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){
    for(i=0; i<pAggInfo->nFunc; i++){
      Expr *pExpr = pAggInfo->aFunc[i].pFExpr;
      assert( pExpr!=0 );
      assert( pExpr->pAggInfo==pAggInfo );
      assert( pExpr->iAgg==i );
    }
  }
#endif

#if TREETRACE_ENABLED
  TREETRACE(0x1,pParse,p,("end processing\n"));
  if( (sqlite3TreeTrace & 0x40000)!=0 && ExplainQueryPlanParent(pParse)==0 ){
    sqlite3TreeViewSelect(0, p, 0);
  }
#endif
  ExplainQueryPlanPop(pParse);
  return rc;
}

Changes to src/shell.c.in.

12
13
14
15
16
17
18































19
20
21
22
23
24
25
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







** This file contains code to implement the "sqlite" command line
** utility for accessing SQLite databases.
*/
#if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS)
/* This needs to come before any includes for MSVC compiler */
#define _CRT_SECURE_NO_WARNINGS
#endif
typedef unsigned int u32;
typedef unsigned short int u16;

/*
** Optionally #include a user-defined header, whereby compilation options
** may be set prior to where they take effect, but after platform setup.
** If SQLITE_CUSTOM_INCLUDE=? is defined, its value names the #include
** file. Note that this macro has a like effect on sqlite3.c compilation.
*/
# define SHELL_STRINGIFY_(f) #f
# define SHELL_STRINGIFY(f) SHELL_STRINGIFY_(f)
#ifdef SQLITE_CUSTOM_INCLUDE
# include SHELL_STRINGIFY(SQLITE_CUSTOM_INCLUDE)
#endif

/*
** Determine if we are dealing with WinRT, which provides only a subset of
** the full Win32 API.
*/
#if !defined(SQLITE_OS_WINRT)
# define SQLITE_OS_WINRT 0
#endif

/*
** If SQLITE_SHELL_FIDDLE is defined then the shell is modified
** somewhat for use as a WASM module in a web browser. This flag
** should only be used when building the "fiddle" web application, as
** the browser-mode build has much different user input requirements
** and this build mode rewires the user input subsystem to account for
** that.
*/

/*
** Warning pragmas copied from msvc.h in the core.
*/
#if defined(_MSC_VER)
#pragma warning(disable : 4054)
#pragma warning(disable : 4055)
51
52
53
54
55
56
57








58
59
60
61
62
63
64
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103







+
+
+
+
+
+
+
+







#ifndef SQLITE_DISABLE_LFS
# define _LARGE_FILE       1
# ifndef _FILE_OFFSET_BITS
#   define _FILE_OFFSET_BITS 64
# endif
# define _LARGEFILE_SOURCE 1
#endif

#if defined(SQLITE_SHELL_FIDDLE) && !defined(_POSIX_SOURCE)
/*
** emcc requires _POSIX_SOURCE (or one of several similar defines)
** to expose strdup().
*/
# define _POSIX_SOURCE
#endif

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "sqlite3.h"
typedef sqlite3_int64 i64;
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
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







+
+
+
+
+
+
+
+


+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







# define shell_read_history(X)
# define shell_write_history(X)
# define shell_stifle_history(X)

# define SHELL_USE_LOCAL_GETLINE 1
#endif

#ifndef deliberate_fall_through
/* Quiet some compilers about some of our intentional code. */
# if GCC_VERSION>=7000000
#  define deliberate_fall_through __attribute__((fallthrough));
# else
#  define deliberate_fall_through
# endif
#endif

#if defined(_WIN32) || defined(WIN32)
# if SQLITE_OS_WINRT
#  define SQLITE_OMIT_POPEN 1
# else
# include <io.h>
# include <fcntl.h>
# define isatty(h) _isatty(h)
# ifndef access
#  define access(f,m) _access((f),(m))
# endif
# ifndef unlink
#  define unlink _unlink
# endif
# undef popen
# define popen _popen
# undef pclose
# define pclose _pclose
#  include <io.h>
#  include <fcntl.h>
#  define isatty(h) _isatty(h)
#  ifndef access
#   define access(f,m) _access((f),(m))
#  endif
#  ifndef unlink
#   define unlink _unlink
#  endif
#  ifndef strdup
#   define strdup _strdup
#  endif
#  undef popen
#  define popen _popen
#  undef pclose
#  define pclose _pclose
# endif
#else
 /* Make sure isatty() has a prototype. */
 extern int isatty(int);

# if !defined(__RTP__) && !defined(_WRS_KERNEL)
  /* popen and pclose are not C89 functions and so are
  ** sometimes omitted from the <stdio.h> header */
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
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







+
+
+















-
+













-


+
+
+
+
+
+
+
+
+
+
+
+






+








/* ctype macros that work with signed characters */
#define IsSpace(X)  isspace((unsigned char)X)
#define IsDigit(X)  isdigit((unsigned char)X)
#define ToLower(X)  (char)tolower((unsigned char)X)

#if defined(_WIN32) || defined(WIN32)
#if SQLITE_OS_WINRT
#include <intrin.h>
#endif
#include <windows.h>

/* string conversion routines only needed on Win32 */
extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR);
extern char *sqlite3_win32_mbcs_to_utf8_v2(const char *, int);
extern char *sqlite3_win32_utf8_to_mbcs_v2(const char *, int);
extern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText);
#endif

/* On Windows, we normally run with output mode of TEXT so that \n characters
** are automatically translated into \r\n.  However, this behavior needs
** to be disabled in some cases (ex: when generating CSV output and when
** rendering quoted strings that contain \n characters).  The following
** routines take care of that.
*/
#if defined(_WIN32) || defined(WIN32)
#if (defined(_WIN32) || defined(WIN32)) && !SQLITE_OS_WINRT
static void setBinaryMode(FILE *file, int isOutput){
  if( isOutput ) fflush(file);
  _setmode(_fileno(file), _O_BINARY);
}
static void setTextMode(FILE *file, int isOutput){
  if( isOutput ) fflush(file);
  _setmode(_fileno(file), _O_TEXT);
}
#else
# define setBinaryMode(X,Y)
# define setTextMode(X,Y)
#endif


/* True if the timer is enabled */
static int enableTimer = 0;

/* A version of strcmp() that works with NULL values */
static int cli_strcmp(const char *a, const char *b){
  if( a==0 ) a = "";
  if( b==0 ) b = "";
  return strcmp(a,b);
}
static int cli_strncmp(const char *a, const char *b, size_t n){
  if( a==0 ) a = "";
  if( b==0 ) b = "";
  return strncmp(a,b,n);
}

/* Return the current wall-clock time */
static sqlite3_int64 timeOfDay(void){
  static sqlite3_vfs *clockVfs = 0;
  sqlite3_int64 t;
  if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
  if( clockVfs==0 ) return 0;  /* Never actually happens */
  if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){
    clockVfs->xCurrentTimeInt64(clockVfs, &t);
  }else{
    double r;
    clockVfs->xCurrentTime(clockVfs, &r);
    t = (sqlite3_int64)(r*86400000.0);
  }
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
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







+
















+







** Check to see if we have timer support.  Return 1 if necessary
** support found (or found previously).
*/
static int hasTimer(void){
  if( getProcessTimesAddr ){
    return 1;
  } else {
#if !SQLITE_OS_WINRT
    /* GetProcessTimes() isn't supported in WIN95 and some other Windows
    ** versions. See if the version we are running on has it, and if it
    ** does, save off a pointer to it and the current process handle.
    */
    hProcess = GetCurrentProcess();
    if( hProcess ){
      HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll"));
      if( NULL != hinstLib ){
        getProcessTimesAddr =
            (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes");
        if( NULL != getProcessTimesAddr ){
          return 1;
        }
        FreeLibrary(hinstLib);
      }
    }
#endif
  }
  return 0;
}

/*
** Begin timing an operation
*/
400
401
402
403
404
405
406


407
408




































































































409
410
411
412
413
414
415
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







+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







*/
static char *Argv0;

/*
** Prompt strings. Initialized in main. Settable with
**   .prompt main continue
*/
#define PROMPT_LEN_MAX 20
/* First line prompt.   default: "sqlite> " */
static char mainPrompt[20];     /* First line prompt. default: "sqlite> "*/
static char continuePrompt[20]; /* Continuation prompt. default: "   ...> " */
static char mainPrompt[PROMPT_LEN_MAX];
/* Continuation prompt. default: "   ...> " */
static char continuePrompt[PROMPT_LEN_MAX];

/* This is variant of the standard-library strncpy() routine with the
** one change that the destination string is always zero-terminated, even
** if there is no zero-terminator in the first n-1 characters of the source
** string.
*/
static char *shell_strncpy(char *dest, const char *src, size_t n){
  size_t i;
  for(i=0; i<n-1 && src[i]!=0; i++) dest[i] = src[i];
  dest[i] = 0;
  return dest;
}

/*
** Optionally disable dynamic continuation prompt.
** Unless disabled, the continuation prompt shows open SQL lexemes if any,
** or open parentheses level if non-zero, or continuation prompt as set.
** This facility interacts with the scanner and process_input() where the
** below 5 macros are used.
*/
#ifdef SQLITE_OMIT_DYNAPROMPT
# define CONTINUATION_PROMPT continuePrompt
# define CONTINUE_PROMPT_RESET
# define CONTINUE_PROMPT_AWAITS(p,s)
# define CONTINUE_PROMPT_AWAITC(p,c)
# define CONTINUE_PAREN_INCR(p,n)
# define CONTINUE_PROMPT_PSTATE 0
typedef void *t_NoDynaPrompt;
# define SCAN_TRACKER_REFTYPE t_NoDynaPrompt
#else
# define CONTINUATION_PROMPT dynamicContinuePrompt()
# define CONTINUE_PROMPT_RESET \
  do {setLexemeOpen(&dynPrompt,0,0); trackParenLevel(&dynPrompt,0);} while(0)
# define CONTINUE_PROMPT_AWAITS(p,s) \
  if(p && stdin_is_interactive) setLexemeOpen(p, s, 0)
# define CONTINUE_PROMPT_AWAITC(p,c) \
  if(p && stdin_is_interactive) setLexemeOpen(p, 0, c)
# define CONTINUE_PAREN_INCR(p,n) \
  if(p && stdin_is_interactive) (trackParenLevel(p,n))
# define CONTINUE_PROMPT_PSTATE (&dynPrompt)
typedef struct DynaPrompt *t_DynaPromptRef;
# define SCAN_TRACKER_REFTYPE t_DynaPromptRef

static struct DynaPrompt {
  char dynamicPrompt[PROMPT_LEN_MAX];
  char acAwait[2];
  int inParenLevel;
  char *zScannerAwaits;
} dynPrompt = { {0}, {0}, 0, 0 };

/* Record parenthesis nesting level change, or force level to 0. */
static void trackParenLevel(struct DynaPrompt *p, int ni){
  p->inParenLevel += ni;
  if( ni==0 ) p->inParenLevel = 0;
  p->zScannerAwaits = 0;
}

/* Record that a lexeme is opened, or closed with args==0. */
static void setLexemeOpen(struct DynaPrompt *p, char *s, char c){
  if( s!=0 || c==0 ){
    p->zScannerAwaits = s;
    p->acAwait[0] = 0;
  }else{
    p->acAwait[0] = c;
    p->zScannerAwaits = p->acAwait;
  }
}

/* Upon demand, derive the continuation prompt to display. */
static char *dynamicContinuePrompt(void){
  if( continuePrompt[0]==0
      || (dynPrompt.zScannerAwaits==0 && dynPrompt.inParenLevel == 0) ){
    return continuePrompt;
  }else{
    if( dynPrompt.zScannerAwaits ){
      size_t ncp = strlen(continuePrompt);
      size_t ndp = strlen(dynPrompt.zScannerAwaits);
      if( ndp > ncp-3 ) return continuePrompt;
      strcpy(dynPrompt.dynamicPrompt, dynPrompt.zScannerAwaits);
      while( ndp<3 ) dynPrompt.dynamicPrompt[ndp++] = ' ';
      shell_strncpy(dynPrompt.dynamicPrompt+3, continuePrompt+3,
              PROMPT_LEN_MAX-4);
    }else{
      if( dynPrompt.inParenLevel>9 ){
        shell_strncpy(dynPrompt.dynamicPrompt, "(..", 4);
      }else if( dynPrompt.inParenLevel<0 ){
        shell_strncpy(dynPrompt.dynamicPrompt, ")x!", 4);
      }else{
        shell_strncpy(dynPrompt.dynamicPrompt, "(x.", 4);
        dynPrompt.dynamicPrompt[2] = (char)('0'+dynPrompt.inParenLevel);
      }
      shell_strncpy(dynPrompt.dynamicPrompt+3, continuePrompt+3, PROMPT_LEN_MAX-4);
    }
  }
  return dynPrompt.dynamicPrompt;
}
#endif /* !defined(SQLITE_OMIT_DYNAPROMPT) */

/*
** Render output like fprintf().  Except, if the output is going to the
** console and if this is running on a Windows machine, translate the
** output from UTF-8 into MBCS.
*/
#if defined(_WIN32) || defined(WIN32)
440
441
442
443
444
445
446







447
448
449
450
451
452
453
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631







+
+
+
+
+
+
+







#endif

/* Indicate out-of-memory and exit. */
static void shell_out_of_memory(void){
  raw_printf(stderr,"Error: out of memory\n");
  exit(1);
}

/* Check a pointer to see if it is NULL.  If it is NULL, exit with an
** out-of-memory error.
*/
static void shell_check_oom(void *p){
  if( p==0 ) shell_out_of_memory();
}

/*
** Write I/O traces to the following stream.
*/
#ifdef SQLITE_ENABLE_IOTRACE
static FILE *iotrace = 0;
#endif
477
478
479
480
481
482
483
484

485
486
487
488
489
490
491
492
655
656
657
658
659
660
661

662

663
664
665
666
667
668
669







-
+
-







** in bytes.  This is different from the %*.*s specification in printf
** since with %*.*s the width is measured in bytes, not characters.
*/
static void utf8_width_print(FILE *pOut, int w, const char *zUtf){
  int i;
  int n;
  int aw = w<0 ? -w : w;
  char zBuf[1000];
  if( zUtf==0 ) zUtf = "";
  if( aw>(int)sizeof(zBuf)/3 ) aw = (int)sizeof(zBuf)/3;
  for(i=n=0; zUtf[i]; i++){
    if( (zUtf[i]&0xc0)!=0x80 ){
      n++;
      if( n==aw ){
        do{ i++; }while( (zUtf[i]&0xc0)==0x80 );
        break;
      }
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
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
775
776
777
778
779
780
781

782
783
784
785
786
787
788
789







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


















-
+







static int strlenChar(const char *z){
  int n = 0;
  while( *z ){
    if( (0xc0&*(z++))!=0x80 ) n++;
  }
  return n;
}

/*
** Return open FILE * if zFile exists, can be opened for read
** and is an ordinary file or a character stream source.
** Otherwise return 0.
*/
static FILE * openChrSource(const char *zFile){
#ifdef _WIN32
  struct _stat x = {0};
# define STAT_CHR_SRC(mode) ((mode & (_S_IFCHR|_S_IFIFO|_S_IFREG))!=0)
  /* On Windows, open first, then check the stream nature. This order
  ** is necessary because _stat() and sibs, when checking a named pipe,
  ** effectively break the pipe as its supplier sees it. */
  FILE *rv = fopen(zFile, "rb");
  if( rv==0 ) return 0;
  if( _fstat(_fileno(rv), &x) != 0
      || !STAT_CHR_SRC(x.st_mode)){
    fclose(rv);
    rv = 0;
  }
  return rv;
#else
  struct stat x = {0};
  int rc = stat(zFile, &x);
# define STAT_CHR_SRC(mode) (S_ISREG(mode)||S_ISFIFO(mode)||S_ISCHR(mode))
  if( rc!=0 ) return 0;
  if( STAT_CHR_SRC(x.st_mode) ){
    return fopen(zFile, "rb");
  }else{
    return 0;
  }
#endif
#undef STAT_CHR_SRC
}

/*
** This routine reads a line of text from FILE in, stores
** the text in memory obtained from malloc() and returns a pointer
** to the text.  NULL is returned at end of file, or if malloc()
** fails.
**
** If zLine is not NULL then it is a malloced buffer returned from
** a previous call to this routine that may be reused.
*/
static char *local_getline(char *zLine, FILE *in){
  int nLine = zLine==0 ? 0 : 100;
  int n = 0;

  while( 1 ){
    if( n+100>nLine ){
      nLine = nLine*2 + 100;
      zLine = realloc(zLine, nLine);
      if( zLine==0 ) shell_out_of_memory();
      shell_check_oom(zLine);
    }
    if( fgets(&zLine[n], nLine - n, in)==0 ){
      if( n==0 ){
        free(zLine);
        return 0;
      }
      zLine[n] = 0;
588
589
590
591
592
593
594
595

596
597
598

599
600
601
602
603
604
605
799
800
801
802
803
804
805

806
807
808

809
810
811
812
813
814
815
816







-
+


-
+







  }
#if defined(_WIN32) || defined(WIN32)
  /* For interactive input on Windows systems, translate the
  ** multi-byte characterset characters into UTF-8. */
  if( stdin_is_interactive && in==stdin ){
    char *zTrans = sqlite3_win32_mbcs_to_utf8_v2(zLine, 0);
    if( zTrans ){
      int nTrans = strlen30(zTrans)+1;
      i64 nTrans = strlen(zTrans)+1;
      if( nTrans>nLine ){
        zLine = realloc(zLine, nTrans);
        if( zLine==0 ) shell_out_of_memory();
        shell_check_oom(zLine);
      }
      memcpy(zLine, zTrans, nTrans);
      sqlite3_free(zTrans);
    }
  }
#endif /* defined(_WIN32) || defined(WIN32) */
  return zLine;
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
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







+






-
+












-
+







** If zPrior is not NULL then it is a buffer from a prior call to this
** routine that can be reused.
**
** The result is stored in space obtained from malloc() and must either
** be freed by the caller or else passed back into this routine via the
** zPrior argument for reuse.
*/
#ifndef SQLITE_SHELL_FIDDLE
static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
  char *zPrompt;
  char *zResult;
  if( in!=0 ){
    zResult = local_getline(zPrior, in);
  }else{
    zPrompt = isContinuation ? continuePrompt : mainPrompt;
    zPrompt = isContinuation ? CONTINUATION_PROMPT : mainPrompt;
#if SHELL_USE_LOCAL_GETLINE
    printf("%s", zPrompt);
    fflush(stdout);
    zResult = local_getline(zPrior, stdin);
#else
    free(zPrior);
    zResult = shell_readline(zPrompt);
    if( zResult && *zResult ) shell_add_history(zResult);
#endif
  }
  return zResult;
}

#endif /* !SQLITE_SHELL_FIDDLE */

/*
** Return the value of a hexadecimal digit.  Return -1 if the input
** is not a hex digit.
*/
static int hexDigitValue(char c){
  if( c>='0' && c<='9' ) return c - '0';
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
934
935
936
937
938
939
940




941
942
943
944
945
946
947
948
949
950
951
952
953

954
955
956

957
958
959
960
961
962
963
964







-
-
-
-
+
+
+
+









-
+


-
+







** from malloc(), or a NULL pointer. The string pointed to by zAppend is
** added to zIn, and the result returned in memory obtained from malloc().
** zIn, if it was not NULL, is freed.
**
** If the third argument, quote, is not '\0', then it is used as a
** quote character for zAppend.
*/
static void appendText(ShellText *p, char const *zAppend, char quote){
  int len;
  int i;
  int nAppend = strlen30(zAppend);
static void appendText(ShellText *p, const char *zAppend, char quote){
  i64 len;
  i64 i;
  i64 nAppend = strlen30(zAppend);

  len = nAppend+p->n+1;
  if( quote ){
    len += 2;
    for(i=0; i<nAppend; i++){
      if( zAppend[i]==quote ) len++;
    }
  }

  if( p->n+len>=p->nAlloc ){
  if( p->z==0 || p->n+len>=p->nAlloc ){
    p->nAlloc = p->nAlloc*2 + len + 20;
    p->z = realloc(p->z, p->nAlloc);
    if( p->z==0 ) shell_out_of_memory();
    shell_check_oom(p->z);
  }

  if( quote ){
    char *zCsr = p->z+p->n;
    *zCsr++ = quote;
    for(i=0; i<nAppend; i++){
      *zCsr++ = zAppend[i];
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
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







+
















+







  ShellText s;
  char cQuote;
  char *zDiv = "(";
  int nRow = 0;

  zSql = sqlite3_mprintf("PRAGMA \"%w\".table_info=%Q;",
                         zSchema ? zSchema : "main", zName);
  shell_check_oom(zSql);
  sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
  sqlite3_free(zSql);
  initText(&s);
  if( zSchema ){
    cQuote = quoteChar(zSchema);
    if( cQuote && sqlite3_stricmp(zSchema,"temp")==0 ) cQuote = 0;
    appendText(&s, zSchema, cQuote);
    appendText(&s, ".", 0);
  }
  cQuote = quoteChar(zName);
  appendText(&s, zName, cQuote);
  while( sqlite3_step(pStmt)==SQLITE_ROW ){
    const char *zCol = (const char*)sqlite3_column_text(pStmt, 1);
    nRow++;
    appendText(&s, zDiv, 0);
    zDiv = ",";
    if( zCol==0 ) zCol = "";
    cQuote = quoteChar(zCol);
    appendText(&s, zCol, cQuote);
  }
  appendText(&s, ")", 0);
  sqlite3_finalize(pStmt);
  if( nRow==0 ){
    freeText(&s);
832
833
834
835
836
837
838
839
840


841


842
843
844
845
846
847
848
1046
1047
1048
1049
1050
1051
1052


1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064







-
-
+
+

+
+







** table X.
*/
static void shellModuleSchema(
  sqlite3_context *pCtx,
  int nVal,
  sqlite3_value **apVal
){
  const char *zName = (const char*)sqlite3_value_text(apVal[0]);
  char *zFake = shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName);
  const char *zName;
  char *zFake;
  UNUSED_PARAMETER(nVal);
  zName = (const char*)sqlite3_value_text(apVal[0]);
  zFake = zName? shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName) : 0;
  if( zFake ){
    sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake),
                        -1, sqlite3_free);
    free(zFake);
  }
}

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
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







-
+




















-
-
+
+

-
+







**    CREATE INDEX
**    CREATE UNIQUE INDEX
**    CREATE VIEW
**    CREATE TRIGGER
**    CREATE VIRTUAL TABLE
**
** This UDF is used by the .schema command to insert the schema name of
** attached databases into the middle of the sqlite_master.sql field.
** attached databases into the middle of the sqlite_schema.sql field.
*/
static void shellAddSchemaName(
  sqlite3_context *pCtx,
  int nVal,
  sqlite3_value **apVal
){
  static const char *aPrefix[] = {
     "TABLE",
     "INDEX",
     "UNIQUE INDEX",
     "VIEW",
     "TRIGGER",
     "VIRTUAL TABLE"
  };
  int i = 0;
  const char *zIn = (const char*)sqlite3_value_text(apVal[0]);
  const char *zSchema = (const char*)sqlite3_value_text(apVal[1]);
  const char *zName = (const char*)sqlite3_value_text(apVal[2]);
  sqlite3 *db = sqlite3_context_db_handle(pCtx);
  UNUSED_PARAMETER(nVal);
  if( zIn!=0 && strncmp(zIn, "CREATE ", 7)==0 ){
    for(i=0; i<(int)(sizeof(aPrefix)/sizeof(aPrefix[0])); i++){
  if( zIn!=0 && cli_strncmp(zIn, "CREATE ", 7)==0 ){
    for(i=0; i<ArraySize(aPrefix); i++){
      int n = strlen30(aPrefix[i]);
      if( strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){
      if( cli_strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){
        char *z = 0;
        char *zFake = 0;
        if( zSchema ){
          char cQuote = quoteChar(zSchema);
          if( cQuote && sqlite3_stricmp(zSchema,"temp")!=0 ){
            z = sqlite3_mprintf("%.*s \"%w\".%s", n+7, zIn, zSchema, zIn+n+8);
          }else{
929
930
931
932
933
934
935

936













937
938
939

940
941
942
943
944
945
















946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
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







+

+
+
+
+
+
+
+
+
+
+
+
+
+



+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+














-
-
-
-
-
-
-
-
-
-
-
-







#define SQLITE_EXTENSION_INIT2(X) (void)(X)

#if defined(_WIN32) && defined(_MSC_VER)
INCLUDE test_windirent.h
INCLUDE test_windirent.c
#define dirent DIRENT
#endif
INCLUDE ../ext/misc/memtrace.c
INCLUDE ../ext/misc/shathree.c
INCLUDE ../ext/misc/uint.c
INCLUDE ../ext/misc/decimal.c
#undef sqlite3_base_init
#define sqlite3_base_init sqlite3_base64_init
INCLUDE ../ext/misc/base64.c
#undef sqlite3_base_init
#define sqlite3_base_init sqlite3_base85_init
#define OMIT_BASE85_CHECKER
INCLUDE ../ext/misc/base85.c
INCLUDE ../ext/misc/ieee754.c
INCLUDE ../ext/misc/series.c
INCLUDE ../ext/misc/regexp.c
#ifndef SQLITE_SHELL_FIDDLE
INCLUDE ../ext/misc/fileio.c
INCLUDE ../ext/misc/completion.c
INCLUDE ../ext/misc/appendvfs.c
#endif
#ifdef SQLITE_HAVE_ZLIB
INCLUDE ../ext/misc/zipfile.c
INCLUDE ../ext/misc/sqlar.c
#endif
INCLUDE ../ext/expert/sqlite3expert.h
INCLUDE ../ext/expert/sqlite3expert.c

#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
#define SQLITE_SHELL_HAVE_RECOVER 1
#else
#define SQLITE_SHELL_HAVE_RECOVER 0
#endif
#if SQLITE_SHELL_HAVE_RECOVER
INCLUDE ../ext/recover/sqlite3recover.h
# ifndef SQLITE_HAVE_SQLITE3R
INCLUDE ../ext/recover/dbdata.c
INCLUDE ../ext/recover/sqlite3recover.c
# endif
#endif
#ifdef SQLITE_SHELL_EXTSRC
# include SHELL_STRINGIFY(SQLITE_SHELL_EXTSRC)
#endif

#if defined(SQLITE_ENABLE_SESSION)
/*
** State information for a single open session
*/
typedef struct OpenSession OpenSession;
struct OpenSession {
  char *zName;             /* Symbolic name for this session */
  int nFilter;             /* Number of xFilter rejection GLOB patterns */
  char **azFilter;         /* Array of xFilter rejection GLOB patterns */
  sqlite3_session *p;      /* The open session */
};
#endif

/*
** Shell output mode information from before ".explain on",
** saved so that it can be restored by ".explain off"
*/
typedef struct SavedModeInfo SavedModeInfo;
struct SavedModeInfo {
  int valid;          /* Is there legit data in here? */
  int mode;           /* Mode prior to ".explain on" */
  int showHeader;     /* The ".header" setting prior to ".explain on" */
  int colWidth[100];  /* Column widths prior to ".explain on" */
};

typedef struct ExpertInfo ExpertInfo;
struct ExpertInfo {
  sqlite3expert *pExpert;
  int bVerbose;
};

/* A single line in the EQP output */
988
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
1045
1046

1047

1048

1049
1050





1051
1052
1053




1054
1055
1056
1057
1058
1059
1060
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
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
1318
1319

1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331







+
+
+
+
+
+
+
+
+










-
+





+
+
+
+

+



+











+
+
+

+
+







-
-
+
+
+



-
-
-


+
+
+
+
+
+
+
+
+
+



+

+
-
+
-
-
+
+
+
+
+

-

+
+
+
+







typedef struct EQPGraph EQPGraph;
struct EQPGraph {
  EQPGraphRow *pRow;    /* Linked list of all rows of the EQP output */
  EQPGraphRow *pLast;   /* Last element of the pRow list */
  char zPrefix[100];    /* Graph prefix */
};

/* Parameters affecting columnar mode result display (defaulting together) */
typedef struct ColModeOpts {
  int iWrap;            /* In columnar modes, wrap lines reaching this limit */
  u8 bQuote;            /* Quote results for .mode box and table */
  u8 bWordWrap;         /* In columnar modes, wrap at word boundaries  */
} ColModeOpts;
#define ColModeOpts_default { 60, 0, 0 }
#define ColModeOpts_default_qbox { 60, 1, 0 }

/*
** State information about the database connection is contained in an
** instance of the following structure.
*/
typedef struct ShellState ShellState;
struct ShellState {
  sqlite3 *db;           /* The database */
  u8 autoExplain;        /* Automatically turn on .explain mode */
  u8 autoEQP;            /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
  u8 autoEQPtest;        /* autoEQP is in test mode */
  u8 statsOn;            /* True to display memory stats before each finalize */
  u8 autoEQPtrace;       /* autoEQP is in trace mode */
  u8 scanstatsOn;        /* True to display scan stats before each finalize */
  u8 openMode;           /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
  u8 doXdgOpen;          /* Invoke start/open/xdg-open in output_reset() */
  u8 nEqpLevel;          /* Depth of the EQP output graph */
  u8 eTraceType;         /* SHELL_TRACE_* value for type of trace */
  u8 bSafeMode;          /* True to prohibit unsafe operations */
  u8 bSafeModePersist;   /* The long-term value of bSafeMode */
  ColModeOpts cmOpts;    /* Option values affecting columnar mode output */
  unsigned statsOn;      /* True to display memory stats before each finalize */
  unsigned mEqpLines;    /* Mask of veritical lines in the EQP output graph */
  int inputNesting;      /* Track nesting level of .read and other redirects */
  int outCount;          /* Revert to stdout when reaching zero */
  int cnt;               /* Number of records displayed so far */
  int lineno;            /* Line number of last line read from in */
  int openFlags;         /* Additional flags to open.  (SQLITE_OPEN_NOFOLLOW) */
  FILE *in;              /* Read commands from this stream */
  FILE *out;             /* Write results here */
  FILE *traceOut;        /* Output for sqlite3_trace() */
  int nErr;              /* Number of errors seen */
  int mode;              /* An output mode setting */
  int modePrior;         /* Saved mode */
  int cMode;             /* temporary output mode for the current query */
  int normalMode;        /* Output mode before ".explain on" */
  int writableSchema;    /* True if PRAGMA writable_schema=ON */
  int showHeader;        /* True to show column names in List or Column mode */
  int nCheck;            /* Number of ".check" commands run */
  unsigned nProgress;    /* Number of progress callbacks encountered */
  unsigned mxProgress;   /* Maximum progress callbacks before failing */
  unsigned flgProgress;  /* Flags for the progress callback */
  unsigned shellFlgs;    /* Various flags */
  unsigned priorShFlgs;  /* Saved copy of flags */
  sqlite3_int64 szMax;   /* --maxsize argument to .open */
  char *zDestTable;      /* Name of destination table when MODE_Insert */
  char *zTempFile;       /* Temporary file that might need deleting */
  char zTestcase[30];    /* Name of current test case */
  char colSeparator[20]; /* Column separator character for several modes */
  char rowSeparator[20]; /* Row separator character for MODE_Ascii */
  char colSepPrior[20];  /* Saved column separator */
  char rowSepPrior[20];  /* Saved row separator */
  int colWidth[100];     /* Requested width of each column when in column mode*/
  int actualWidth[100];  /* Actual width of each column */
  int *colWidth;         /* Requested width of each column in columnar modes */
  int *actualWidth;      /* Actual width of each column */
  int nWidth;            /* Number of slots in colWidth[] and actualWidth[] */
  char nullValue[20];    /* The text to print when a NULL comes back from
                         ** the database */
  char outfile[FILENAME_MAX]; /* Filename for *out */
  const char *zDbFilename;    /* name of the database file */
  char *zFreeOnClose;         /* Filename to free when closing */
  const char *zVfs;           /* Name of VFS to use */
  sqlite3_stmt *pStmt;   /* Current statement if any. */
  FILE *pLog;            /* Write log output here */
  struct AuxDb {         /* Storage space for auxiliary database connections */
    sqlite3 *db;               /* Connection pointer */
    const char *zDbFilename;   /* Filename used to open the connection */
    char *zFreeOnClose;        /* Free this memory allocation on close */
#if defined(SQLITE_ENABLE_SESSION)
    int nSession;              /* Number of active sessions */
    OpenSession aSession[4];   /* Array of sessions.  [0] is in focus. */
#endif
  } aAuxDb[5],           /* Array of all database connections */
    *pAuxDb;             /* Currently active database connection */
  int *aiIndent;         /* Array of indents used in MODE_Explain */
  int nIndent;           /* Size of array aiIndent[] */
  int iIndent;           /* Index of current op in aiIndent[] */
  char *zNonce;          /* Nonce for temporary safe-mode excapes */
  EQPGraph sGraph;       /* Information for the graphical EXPLAIN QUERY PLAN */
  ExpertInfo expert;     /* Valid if previous command was ".expert OPT..." */
#if defined(SQLITE_ENABLE_SESSION)
#ifdef SQLITE_SHELL_FIDDLE
  int nSession;             /* Number of active sessions */
  OpenSession aSession[4];  /* Array of sessions.  [0] is in focus. */
  struct {
    const char * zInput; /* Input string from wasm/JS proxy */
    const char * zPos;   /* Cursor pos into zInput */
    const char * zDefaultDbName; /* Default name for db file */
  } wasm;
#endif
  ExpertInfo expert;        /* Valid if previous command was ".expert OPT..." */
};

#ifdef SQLITE_SHELL_FIDDLE
static ShellState shellState;
#endif


/* Allowed values for ShellState.autoEQP
*/
#define AUTOEQP_off      0           /* Automatic EXPLAIN QUERY PLAN is off */
#define AUTOEQP_on       1           /* Automatic EQP is on */
#define AUTOEQP_trigger  2           /* On and also show plans for triggers */
1072
1073
1074
1075
1076
1077
1078







1079
1080
1081
1082
1083
1084
1085
1086
1087
1088




1089
1090
1091
1092
1093
1094
1095
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







+
+
+
+
+
+
+









-
+
+
+
+








/* Allowed values for ShellState.eTraceType
*/
#define SHELL_TRACE_PLAIN      0      /* Show input SQL text */
#define SHELL_TRACE_EXPANDED   1      /* Show expanded SQL text */
#define SHELL_TRACE_NORMALIZED 2      /* Show normalized SQL text */

/* Bits in the ShellState.flgProgress variable */
#define SHELL_PROGRESS_QUIET 0x01  /* Omit announcing every progress callback */
#define SHELL_PROGRESS_RESET 0x02  /* Reset the count when the progres
                                   ** callback limit is reached, and for each
                                   ** top-level SQL statement */
#define SHELL_PROGRESS_ONCE  0x04  /* Cancel the --limit after firing once */

/*
** These are the allowed shellFlgs values
*/
#define SHFLG_Pagecache      0x00000001 /* The --pagecache option is used */
#define SHFLG_Lookaside      0x00000002 /* Lookaside memory is used */
#define SHFLG_Backslash      0x00000004 /* The --backslash option is used */
#define SHFLG_PreserveRowid  0x00000008 /* .dump preserves rowid values */
#define SHFLG_Newlines       0x00000010 /* .dump --newline flag */
#define SHFLG_CountChanges   0x00000020 /* .changes setting */
#define SHFLG_Echo           0x00000040 /* .echo or --echo setting */
#define SHFLG_Echo           0x00000040 /* .echo on/off, or --echo setting */
#define SHFLG_HeaderSet      0x00000080 /* showHeader has been specified */
#define SHFLG_DumpDataOnly   0x00000100 /* .dump show data only */
#define SHFLG_DumpNoSys      0x00000200 /* .dump omits system tables */

/*
** Macros for testing and setting shellFlgs
*/
#define ShellHasFlag(P,X)    (((P)->shellFlgs & (X))!=0)
#define ShellSetFlag(P,X)    ((P)->shellFlgs|=(X))
#define ShellClearFlag(P,X)  ((P)->shellFlgs&=(~(X)))
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413

1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448







+
+
+
+
+
+














-
+
+
+
+
+
+
+















+
+
+
+
+
+







#define MODE_Quote    6  /* Quote values as for SQL */
#define MODE_Tcl      7  /* Generate ANSI-C or TCL quoted elements */
#define MODE_Csv      8  /* Quote strings, numbers are plain */
#define MODE_Explain  9  /* Like MODE_Column, but do not truncate data */
#define MODE_Ascii   10  /* Use ASCII unit and record separators (0x1F/0x1E) */
#define MODE_Pretty  11  /* Pretty-print schemas */
#define MODE_EQP     12  /* Converts EXPLAIN QUERY PLAN output into a graph */
#define MODE_Json    13  /* Output JSON */
#define MODE_Markdown 14 /* Markdown formatting */
#define MODE_Table   15  /* MySQL-style table formatting */
#define MODE_Box     16  /* Unicode box-drawing characters */
#define MODE_Count   17  /* Output only a count of the rows of output */
#define MODE_Off     18  /* No query output shown */

static const char *modeDescr[] = {
  "line",
  "column",
  "list",
  "semi",
  "html",
  "insert",
  "quote",
  "tcl",
  "csv",
  "explain",
  "ascii",
  "prettyprint",
  "eqp"
  "eqp",
  "json",
  "markdown",
  "table",
  "box",
  "count",
  "off"
};

/*
** These are the column/row/line separators used by the various
** import/export modes.
*/
#define SEP_Column    "|"
#define SEP_Row       "\n"
#define SEP_Tab       "\t"
#define SEP_Space     " "
#define SEP_Comma     ","
#define SEP_CrLf      "\r\n"
#define SEP_Unit      "\x1F"
#define SEP_Record    "\x1E"

/*
** Limit input nesting via .read or any other input redirect.
** It's not too expensive, so a generous allowance can be made.
*/
#define MAX_INPUT_NESTING 25

/*
** A callback for the sqlite3_log() interface.
*/
static void shellLog(void *pArg, int iErrCode, const char *zMsg){
  ShellState *p = (ShellState*)pArg;
  if( p->pLog==0 ) return;
  utf8_printf(p->pLog, "(%d) %s\n", iErrCode, zMsg);
1162
1163
1164
1165
1166
1167
1168





















1169
1170
1171
1172
1173
1174
1175
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  sqlite3_value **apVal
){
  ShellState *p = (ShellState*)sqlite3_user_data(pCtx);
  (void)nVal;
  utf8_printf(p->out, "%s\n", sqlite3_value_text(apVal[0]));
  sqlite3_result_value(pCtx, apVal[0]);
}

/*
** If in safe mode, print an error message described by the arguments
** and exit immediately.
*/
static void failIfSafeMode(
  ShellState *p,
  const char *zErrMsg,
  ...
){
  if( p->bSafeMode ){
    va_list ap;
    char *zMsg;
    va_start(ap, zErrMsg);
    zMsg = sqlite3_vmprintf(zErrMsg, ap);
    va_end(ap);
    raw_printf(stderr, "line %d: ", p->lineno);
    utf8_printf(stderr, "%s\n", zMsg);
    exit(1);
  }
}

/*
** SQL function:   edit(VALUE)
**                 edit(VALUE,EDITOR)
**
** These steps:
**
1232
1233
1234
1235
1236
1237
1238
1239

1240
1241
1242
1243
1244

1245
1246
1247
1248
1249
1250
1251
1552
1553
1554
1555
1556
1557
1558

1559
1560
1561
1562
1563

1564
1565
1566
1567
1568
1569
1570
1571







-
+




-
+







  f = fopen(zTempFile, bBin ? "wb" : "w");
  if( f==0 ){
    sqlite3_result_error(context, "edit() cannot open temp file", -1);
    goto edit_func_end;
  }
  sz = sqlite3_value_bytes(argv[0]);
  if( bBin ){
    x = fwrite(sqlite3_value_blob(argv[0]), 1, sz, f);
    x = fwrite(sqlite3_value_blob(argv[0]), 1, (size_t)sz, f);
  }else{
    const char *z = (const char*)sqlite3_value_text(argv[0]);
    /* Remember whether or not the value originally contained \r\n */
    if( z && strstr(z,"\r\n")!=0 ) hasCRNL = 1;
    x = fwrite(sqlite3_value_text(argv[0]), 1, sz, f);
    x = fwrite(sqlite3_value_text(argv[0]), 1, (size_t)sz, f);
  }
  fclose(f);
  f = 0;
  if( x!=sz ){
    sqlite3_result_error(context, "edit() could not write the whole file", -1);
    goto edit_func_end;
  }
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
1318

1319
1320
1321
1322
1323

1324
1325
1326
1327
1328
1329
1330
1331
1332

1333
1334
1335
1336
















1337
1338
1339
1340
1341
1342
1343
1585
1586
1587
1588
1589
1590
1591

1592
1593
1594
1595
1596

1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609

1610
1611
1612
1613
1614
1615
1616
1617
1618

1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654




1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677







-
+




-
+












-









-
+


















+





+









+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    sqlite3_result_error(context,
      "edit() cannot reopen temp file after edit", -1);
    goto edit_func_end;
  }
  fseek(f, 0, SEEK_END);
  sz = ftell(f);
  rewind(f);
  p = sqlite3_malloc64( sz+(bBin==0) );
  p = sqlite3_malloc64( sz+1 );
  if( p==0 ){
    sqlite3_result_error_nomem(context);
    goto edit_func_end;
  }
  x = fread(p, 1, sz, f);
  x = fread(p, 1, (size_t)sz, f);
  fclose(f);
  f = 0;
  if( x!=sz ){
    sqlite3_result_error(context, "could not read back the whole file", -1);
    goto edit_func_end;
  }
  if( bBin ){
    sqlite3_result_blob64(context, p, sz, sqlite3_free);
  }else{
    sqlite3_int64 i, j;
    if( hasCRNL ){
      /* If the original contains \r\n then do no conversions back to \n */
      j = sz;
    }else{
      /* If the file did not originally contain \r\n then convert any new
      ** \r\n back into \n */
      for(i=j=0; i<sz; i++){
        if( p[i]=='\r' && p[i+1]=='\n' ) i++;
        p[j++] = p[i];
      }
      sz = j;
      p[sz] = 0;
    } 
    }
    sqlite3_result_text64(context, (const char*)p, sz,
                          sqlite3_free, SQLITE_UTF8);
  }
  p = 0;

edit_func_end:
  if( f ) fclose(f);
  unlink(zTempFile);
  sqlite3_free(zTempFile);
  sqlite3_free(p);
}
#endif /* SQLITE_NOHAVE_SYSTEM */

/*
** Save or restore the current output mode
*/
static void outputModePush(ShellState *p){
  p->modePrior = p->mode;
  p->priorShFlgs = p->shellFlgs;
  memcpy(p->colSepPrior, p->colSeparator, sizeof(p->colSeparator));
  memcpy(p->rowSepPrior, p->rowSeparator, sizeof(p->rowSeparator));
}
static void outputModePop(ShellState *p){
  p->mode = p->modePrior;
  p->shellFlgs = p->priorShFlgs;
  memcpy(p->colSeparator, p->colSepPrior, sizeof(p->colSeparator));
  memcpy(p->rowSeparator, p->rowSepPrior, sizeof(p->rowSeparator));
}

/*
** Output the given string as a hex-encoded blob (eg. X'1234' )
*/
static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
  int i;
  unsigned char *aBlob = (unsigned char*)pBlob;
  char *zBlob = (char *)pBlob;
  raw_printf(out,"X'");
  for(i=0; i<nBlob; i++){ raw_printf(out,"%02x",zBlob[i]&0xff); }
  raw_printf(out,"'");

  char *zStr = sqlite3_malloc(nBlob*2 + 1);
  shell_check_oom(zStr);

  for(i=0; i<nBlob; i++){
    static const char aHex[] = {
        '0', '1', '2', '3', '4', '5', '6', '7',
        '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
    };
    zStr[i*2] = aHex[ (aBlob[i] >> 4) ];
    zStr[i*2+1] = aHex[ (aBlob[i] & 0x0F) ];
  }
  zStr[i*2] = '\0';

  raw_printf(out,"X'%s'", zStr);
  sqlite3_free(zStr);
}

/*
** Find a string that is not found anywhere in z[].  Return a pointer
** to that string.
**
** Try to use zA and zB first.  If both of those are already found in z[]
1485
1486
1487
1488
1489
1490
1491


































1492
1493
1494
1495
1496
1497
1498
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







      raw_printf(out, "\\%03o", c&0xff);
    }else{
      fputc(c, out);
    }
  }
  fputc('"', out);
}

/*
** Output the given string as a quoted according to JSON quoting rules.
*/
static void output_json_string(FILE *out, const char *z, i64 n){
  unsigned int c;
  if( n<0 ) n = strlen(z);
  fputc('"', out);
  while( n-- ){
    c = *(z++);
    if( c=='\\' || c=='"' ){
      fputc('\\', out);
      fputc(c, out);
    }else if( c<=0x1f ){
      fputc('\\', out);
      if( c=='\b' ){
        fputc('b', out);
      }else if( c=='\f' ){
        fputc('f', out);
      }else if( c=='\n' ){
        fputc('n', out);
      }else if( c=='\r' ){
        fputc('r', out);
      }else if( c=='\t' ){
        fputc('t', out);
      }else{
         raw_printf(out, "u%04x",c);
      }
    }else{
      fputc(c, out);
    }
  }
  fputc('"', out);
}

/*
** Output the given string with characters that are special to
** HTML escaped.
*/
static void output_html_string(FILE *out, const char *z){
  int i;
1555
1556
1557
1558
1559
1560
1561
1562

1563
1564
1565

1566
1567
1568
1569
1570
1571
1572

1573

1574
1575
1576
1577
1578
1579
1580
1923
1924
1925
1926
1927
1928
1929

1930

1931

1932


1933
1934
1935
1936

1937
1938
1939
1940
1941
1942
1943
1944
1945
1946







-
+
-

-
+
-
-




-
+

+







** is only issued if bSep is true.
*/
static void output_csv(ShellState *p, const char *z, int bSep){
  FILE *out = p->out;
  if( z==0 ){
    utf8_printf(out,"%s",p->nullValue);
  }else{
    int i;
    unsigned i;
    int nSep = strlen30(p->colSeparator);
    for(i=0; z[i]; i++){
      if( needCsvQuote[((unsigned char*)z)[i]]
      if( needCsvQuote[((unsigned char*)z)[i]] ){
         || (z[i]==p->colSeparator[0] &&
             (nSep==1 || memcmp(z, p->colSeparator, nSep)==0)) ){
        i = 0;
        break;
      }
    }
    if( i==0 ){
    if( i==0 || strstr(z, p->colSeparator)!=0 ){
      char *zQuoted = sqlite3_mprintf("\"%w\"", z);
      shell_check_oom(zQuoted);
      utf8_printf(out, "%s", zQuoted);
      sqlite3_free(zQuoted);
    }else{
      utf8_printf(out, "%s", z);
    }
  }
  if( bSep ){
1604
1605
1606
1607
1608
1609
1610















































1611
1612
1613
1614
1615
1616
1617
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
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
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    return TRUE;
  }
  return FALSE;
}
#endif

#ifndef SQLITE_OMIT_AUTHORIZATION
/*
** This authorizer runs in safe mode.
*/
static int safeModeAuth(
  void *pClientData,
  int op,
  const char *zA1,
  const char *zA2,
  const char *zA3,
  const char *zA4
){
  ShellState *p = (ShellState*)pClientData;
  static const char *azProhibitedFunctions[] = {
    "edit",
    "fts3_tokenizer",
    "load_extension",
    "readfile",
    "writefile",
    "zipfile",
    "zipfile_cds",
  };
  UNUSED_PARAMETER(zA1);
  UNUSED_PARAMETER(zA3);
  UNUSED_PARAMETER(zA4);
  switch( op ){
    case SQLITE_ATTACH: {
#ifndef SQLITE_SHELL_FIDDLE
      /* In WASM builds the filesystem is a virtual sandbox, so
      ** there's no harm in using ATTACH. */
      failIfSafeMode(p, "cannot run ATTACH in safe mode");
#endif
      break;
    }
    case SQLITE_FUNCTION: {
      int i;
      for(i=0; i<ArraySize(azProhibitedFunctions); i++){
        if( sqlite3_stricmp(zA2, azProhibitedFunctions[i])==0 ){
          failIfSafeMode(p, "cannot use the %s() function in safe mode",
                         azProhibitedFunctions[i]);
        }
      }
      break;
    }
  }
  return SQLITE_OK;
}

/*
** When the ".auth ON" is set, the following authorizer callback is
** invoked.  It always returns SQLITE_OK.
*/
static int shellAuth(
  void *pClientData,
  int op,
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
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







+









+
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





+







    if( az[i] ){
      output_c_string(p->out, az[i]);
    }else{
      raw_printf(p->out, "NULL");
    }
  }
  raw_printf(p->out, "\n");
  if( p->bSafeMode ) (void)safeModeAuth(pClientData, op, zA1, zA2, zA3, zA4);
  return SQLITE_OK;
}
#endif

/*
** Print a schema statement.  Part of MODE_Semi and MODE_Pretty output.
**
** This routine converts some CREATE TABLE statements for shadow tables
** in FTS3/4/5 into CREATE TABLE IF NOT EXISTS statements.
**
** If the schema statement in z[] contains a start-of-comment and if
** sqlite3_complete() returns false, try to terminate the comment before
** printing the result.  https://sqlite.org/forum/forumpost/d7be961c5c
*/
static void printSchemaLine(FILE *out, const char *z, const char *zTail){
  char *zToFree = 0;
  if( z==0 ) return;
  if( zTail==0 ) return;
  if( zTail[0]==';' && (strstr(z, "/*")!=0 || strstr(z,"--")!=0) ){
    const char *zOrig = z;
    static const char *azTerm[] = { "", "*/", "\n" };
    int i;
    for(i=0; i<ArraySize(azTerm); i++){
      char *zNew = sqlite3_mprintf("%s%s;", zOrig, azTerm[i]);
      if( sqlite3_complete(zNew) ){
        size_t n = strlen(zNew);
        zNew[n-1] = 0;
        zToFree = zNew;
        z = zNew;
        break;
      }
      sqlite3_free(zNew);
    }
  }
  if( sqlite3_strglob("CREATE TABLE ['\"]*", z)==0 ){
    utf8_printf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail);
  }else{
    utf8_printf(out, "%s%s", z, zTail);
  }
  sqlite3_free(zToFree);
}
static void printSchemaLineN(FILE *out, char *z, int n, const char *zTail){
  char c = z[n];
  z[n] = 0;
  printSchemaLine(out, z, zTail);
  z[n] = c;
}
1690
1691
1692
1693
1694
1695
1696


1697

1698
1699
1700
1701
1702

1703
1704
1705
1706
1707
1708
1709
2128
2129
2130
2131
2132
2133
2134
2135
2136

2137
2138
2139
2140
2141

2142
2143
2144
2145
2146
2147
2148
2149







+
+
-
+




-
+







}

/*
** Add a new entry to the EXPLAIN QUERY PLAN data
*/
static void eqp_append(ShellState *p, int iEqpId, int p2, const char *zText){
  EQPGraphRow *pNew;
  i64 nText;
  if( zText==0 ) return;
  int nText = strlen30(zText);
  nText = strlen(zText);
  if( p->autoEQPtest ){
    utf8_printf(p->out, "%d,%d,%s\n", iEqpId, p2, zText);
  }
  pNew = sqlite3_malloc64( sizeof(*pNew) + nText );
  if( pNew==0 ) shell_out_of_memory();
  shell_check_oom(pNew);
  pNew->iEqpId = iEqpId;
  pNew->iParentId = p2;
  memcpy(pNew->zText, zText, nText+1);
  pNew->pNext = 0;
  if( p->sGraph.pLast ){
    p->sGraph.pLast->pNext = pNew;
  }else{
1735
1736
1737
1738
1739
1740
1741
1742

1743
1744
1745
1746
1747
1748



1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759

1760
1761
1762
1763
1764
1765
1766
1767
1768
1769


1770
1771
1772
1773
1774
1775
1776
1777






















































1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788

1789
1790
1791
1792
1793
1794




1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809

1810
1811
1812


1813
1814
1815
1816
1817
1818
1819
1820

1821
1822
1823
1824
1825
1826
1827
1828

1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844



1845
1846
1847

1848
1849
1850

1851
1852
1853
1854
1855

1856
1857
1858

1859
1860
1861
1862
1863
1864
1865
1866

1867
1868

1869
1870

1871
1872
1873
1874
1875
1876
1877
1878
1879
1880

1881
1882
1883
1884
1885
1886
1887
2175
2176
2177
2178
2179
2180
2181

2182
2183
2184
2185
2186


2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199

2200
2201
2202
2203
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
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284

2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309

2310



2311
2312








2313


2314
2315
2316



2317
















2318
2319
2320



2321



2322





2323



2324

2325
2326
2327
2328



2329


2330


2331
2332
2333
2334
2335
2336
2337
2338
2339
2340

2341
2342
2343
2344
2345
2346
2347
2348







-
+




-
-
+
+
+










-
+










+
+








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










-
+






+
+
+
+














-
+
-
-
-
+
+
-
-
-
-
-
-
-
-
+
-
-



-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
+
-
-
-
+
-
-
-
-
-
+
-
-
-
+
-




-
-
-
+
-
-
+
-
-
+









-
+







}

/* Render a single level of the graph that has iEqpId as its parent.  Called
** recursively to render sublevels.
*/
static void eqp_render_level(ShellState *p, int iEqpId){
  EQPGraphRow *pRow, *pNext;
  int n = strlen30(p->sGraph.zPrefix);
  i64 n = strlen(p->sGraph.zPrefix);
  char *z;
  for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){
    pNext = eqp_next_row(p, iEqpId, pRow);
    z = pRow->zText;
    utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix, pNext ? "|--" : "`--", z);
    if( n<(int)sizeof(p->sGraph.zPrefix)-7 ){
    utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix,
                pNext ? "|--" : "`--", z);
    if( n<(i64)sizeof(p->sGraph.zPrefix)-7 ){
      memcpy(&p->sGraph.zPrefix[n], pNext ? "|  " : "   ", 4);
      eqp_render_level(p, pRow->iEqpId);
      p->sGraph.zPrefix[n] = 0;
    }
  }
}

/*
** Display and reset the EXPLAIN QUERY PLAN data
*/
static void eqp_render(ShellState *p){
static void eqp_render(ShellState *p, i64 nCycle){
  EQPGraphRow *pRow = p->sGraph.pRow;
  if( pRow ){
    if( pRow->zText[0]=='-' ){
      if( pRow->pNext==0 ){
        eqp_reset(p);
        return;
      }
      utf8_printf(p->out, "%s\n", pRow->zText+3);
      p->sGraph.pRow = pRow->pNext;
      sqlite3_free(pRow);
    }else if( nCycle>0 ){
      utf8_printf(p->out, "QUERY PLAN (cycles=%lld [100%%])\n", nCycle);
    }else{
      utf8_printf(p->out, "QUERY PLAN\n");
    }
    p->sGraph.zPrefix[0] = 0;
    eqp_render_level(p, 0);
    eqp_reset(p);
  }
}

#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
/*
** Progress handler callback.
*/
static int progress_handler(void *pClientData) {
  ShellState *p = (ShellState*)pClientData;
  p->nProgress++;
  if( p->nProgress>=p->mxProgress && p->mxProgress>0 ){
    raw_printf(p->out, "Progress limit reached (%u)\n", p->nProgress);
    if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
    if( p->flgProgress & SHELL_PROGRESS_ONCE ) p->mxProgress = 0;
    return 1;
  }
  if( (p->flgProgress & SHELL_PROGRESS_QUIET)==0 ){
    raw_printf(p->out, "Progress %u\n", p->nProgress);
  }
  return 0;
}
#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */

/*
** Print N dashes
*/
static void print_dashes(FILE *out, int N){
  const char zDash[] = "--------------------------------------------------";
  const int nDash = sizeof(zDash) - 1;
  while( N>nDash ){
    fputs(zDash, out);
    N -= nDash;
  }
  raw_printf(out, "%.*s", N, zDash);
}

/*
** Print a markdown or table-style row separator using ascii-art
*/
static void print_row_separator(
  ShellState *p,
  int nArg,
  const char *zSep
){
  int i;
  if( nArg>0 ){
    fputs(zSep, p->out);
    print_dashes(p->out, p->actualWidth[0]+2);
    for(i=1; i<nArg; i++){
      fputs(zSep, p->out);
      print_dashes(p->out, p->actualWidth[i]+2);
    }
    fputs(zSep, p->out);
  }
  fputs("\n", p->out);
}

/*
** This is the callback routine that the shell
** invokes for each row of a query result.
*/
static int shell_callback(
  void *pArg,
  int nArg,        /* Number of result columns */
  char **azArg,    /* Text of each result column */
  char **azCol,    /* Column names */
  int *aiType      /* Column types */
  int *aiType      /* Column types.  Might be NULL */
){
  int i;
  ShellState *p = (ShellState*)pArg;

  if( azArg==0 ) return 0;
  switch( p->cMode ){
    case MODE_Count:
    case MODE_Off: {
      break;
    }
    case MODE_Line: {
      int w = 5;
      if( azArg==0 ) break;
      for(i=0; i<nArg; i++){
        int len = strlen30(azCol[i] ? azCol[i] : "");
        if( len>w ) w = len;
      }
      if( p->cnt++>0 ) utf8_printf(p->out, "%s", p->rowSeparator);
      for(i=0; i<nArg; i++){
        utf8_printf(p->out,"%*s = %s%s", w, azCol[i],
                azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator);
      }
      break;
    }
    case MODE_Explain:
    case MODE_Explain: {
    case MODE_Column: {
      static const int aExplainWidths[] = {4, 13, 4, 4, 4, 13, 2, 13};
      const int *colWidth;
      static const int aExplainWidth[] = {4, 13, 4, 4, 4, 13, 2, 13};
      if( nArg>ArraySize(aExplainWidth) ){
      int showHdr;
      char *rowSep;
      if( p->cMode==MODE_Column ){
        colWidth = p->colWidth;
        showHdr = p->showHeader;
        rowSep = p->rowSeparator;
      }else{
        colWidth = aExplainWidths;
        nArg = ArraySize(aExplainWidth);
        showHdr = 1;
        rowSep = SEP_Row;
      }
      if( p->cnt++==0 ){
        for(i=0; i<nArg; i++){
          int w, n;
          if( i<ArraySize(p->colWidth) ){
            w = colWidth[i];
          int w = aExplainWidth[i];
          }else{
            w = 0;
          }
          if( w==0 ){
            w = strlenChar(azCol[i] ? azCol[i] : "");
            if( w<10 ) w = 10;
            n = strlenChar(azArg && azArg[i] ? azArg[i] : p->nullValue);
            if( w<n ) w = n;
          }
          if( i<ArraySize(p->actualWidth) ){
            p->actualWidth[i] = w;
          }
          if( showHdr ){
            utf8_width_print(p->out, w, azCol[i]);
            utf8_printf(p->out, "%s", i==nArg-1 ? rowSep : "  ");
          }
          utf8_width_print(p->out, w, azCol[i]);
          fputs(i==nArg-1 ? "\n" : "  ", p->out);
        }
        }
        if( showHdr ){
          for(i=0; i<nArg; i++){
        for(i=0; i<nArg; i++){
            int w;
            if( i<ArraySize(p->actualWidth) ){
               w = p->actualWidth[i];
          int w = aExplainWidth[i];
               if( w<0 ) w = -w;
            }else{
               w = 10;
            }
            utf8_printf(p->out,"%-*.*s%s",w,w,
          print_dashes(p->out, w);
                   "----------------------------------------------------------"
                   "----------------------------------------------------------",
                    i==nArg-1 ? rowSep : "  ");
          fputs(i==nArg-1 ? "\n" : "  ", p->out);
          }
        }
      }
      if( azArg==0 ) break;
      for(i=0; i<nArg; i++){
        int w;
        if( i<ArraySize(p->actualWidth) ){
           w = p->actualWidth[i];
        int w = aExplainWidth[i];
        }else{
           w = 10;
        if( i==nArg-1 ) w = 0;
        }
        if( p->cMode==MODE_Explain && azArg[i] && strlenChar(azArg[i])>w ){
        if( azArg[i] && strlenChar(azArg[i])>w ){
          w = strlenChar(azArg[i]);
        }
        if( i==1 && p->aiIndent && p->pStmt ){
          if( p->iIndent<p->nIndent ){
            utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], "");
          }
          p->iIndent++;
        }
        utf8_width_print(p->out, w, azArg[i] ? azArg[i] : p->nullValue);
        utf8_printf(p->out, "%s", i==nArg-1 ? rowSep : "  ");
        fputs(i==nArg-1 ? "\n" : "  ", p->out);
      }
      break;
    }
    case MODE_Semi: {   /* .schema and .fullschema output */
      printSchemaLine(p->out, azArg[0], ";\n");
      break;
    }
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
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379

2380
2381
2382
2383
2384
2385
2386
2387







+














-
+







      if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0
       || sqlite3_strlike("CREATE TRIG%", azArg[0], 0)==0
      ){
        utf8_printf(p->out, "%s;\n", azArg[0]);
        break;
      }
      z = sqlite3_mprintf("%s", azArg[0]);
      shell_check_oom(z);
      j = 0;
      for(i=0; IsSpace(z[i]); i++){}
      for(; (c = z[i])!=0; i++){
        if( IsSpace(c) ){
          if( z[j-1]=='\r' ) z[j-1] = '\n';
          if( IsSpace(z[j-1]) || z[j-1]=='(' ) continue;
        }else if( (c=='(' || c==')') && j>0 && IsSpace(z[j-1]) ){
          j--;
        }
        z[j++] = c;
      }
      while( j>0 && IsSpace(z[j-1]) ){ j--; }
      z[j] = 0;
      if( strlen30(z)>=79 ){
        for(i=j=0; (c = z[i])!=0; i++){  /* Copy changes from z[i] back to z[j] */
        for(i=j=0; (c = z[i])!=0; i++){ /* Copy from z[i] back to z[j] */
          if( c==cEnd ){
            cEnd = 0;
          }else if( c=='"' || c=='\'' || c=='`' ){
            cEnd = c;
          }else if( c=='[' ){
            cEnd = ']';
          }else if( c=='-' && z[i+1]=='-' ){
2028
2029
2030
2031
2032
2033
2034

2035
2036
2037
2038
2039
2040
2041
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504







+







      utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);
      if( p->showHeader ){
        raw_printf(p->out,"(");
        for(i=0; i<nArg; i++){
          if( i>0 ) raw_printf(p->out, ",");
          if( quoteChar(azCol[i]) ){
            char *z = sqlite3_mprintf("\"%w\"", azCol[i]);
            shell_check_oom(z);
            utf8_printf(p->out, "%s", z);
            sqlite3_free(z);
          }else{
            raw_printf(p->out, "%s", azCol[i]);
          }
        }
        raw_printf(p->out,")");
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
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532

2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551

2552
2553



2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600

2601
2602
2603
2604

2605
2606
2607
2608
2609
2610
2611
2612







+
+
+
+
-
+
+

















-
+

-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+



-
+







          sqlite3_uint64 ur;
          memcpy(&ur,&r,sizeof(r));
          if( ur==0x7ff0000000000000LL ){
            raw_printf(p->out, "1e999");
          }else if( ur==0xfff0000000000000LL ){
            raw_printf(p->out, "-1e999");
          }else{
            sqlite3_int64 ir = (sqlite3_int64)r;
            if( r==(double)ir ){
              sqlite3_snprintf(50,z,"%lld.0", ir);
            }else{
            sqlite3_snprintf(50,z,"%!.20g", r);
              sqlite3_snprintf(50,z,"%!.20g", r);
            }
            raw_printf(p->out, "%s", z);
          }
        }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
          const void *pBlob = sqlite3_column_blob(p->pStmt, i);
          int nBlob = sqlite3_column_bytes(p->pStmt, i);
          output_hex_blob(p->out, pBlob, nBlob);
        }else if( isNumber(azArg[i], 0) ){
          utf8_printf(p->out,"%s", azArg[i]);
        }else if( ShellHasFlag(p, SHFLG_Newlines) ){
          output_quoted_string(p->out, azArg[i]);
        }else{
          output_quoted_escaped_string(p->out, azArg[i]);
        }
      }
      raw_printf(p->out,");\n");
      break;
    }
    case MODE_Quote: {
    case MODE_Json: {
      if( azArg==0 ) break;
      if( p->cnt==0 && p->showHeader ){
        for(i=0; i<nArg; i++){
          if( i>0 ) raw_printf(p->out, ",");
      if( p->cnt==0 ){
        fputs("[{", p->out);
      }else{
        fputs(",\n{", p->out);
      }
      p->cnt++;
      for(i=0; i<nArg; i++){
        output_json_string(p->out, azCol[i], -1);
        putc(':', p->out);
        if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
          fputs("null",p->out);
        }else if( aiType && aiType[i]==SQLITE_FLOAT ){
          char z[50];
          double r = sqlite3_column_double(p->pStmt, i);
          sqlite3_uint64 ur;
          memcpy(&ur,&r,sizeof(r));
          if( ur==0x7ff0000000000000LL ){
            raw_printf(p->out, "1e999");
          }else if( ur==0xfff0000000000000LL ){
            raw_printf(p->out, "-1e999");
          }else{
            sqlite3_snprintf(50,z,"%!.20g", r);
            raw_printf(p->out, "%s", z);
          }
        }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
          const void *pBlob = sqlite3_column_blob(p->pStmt, i);
          int nBlob = sqlite3_column_bytes(p->pStmt, i);
          output_json_string(p->out, pBlob, nBlob);
        }else if( aiType && aiType[i]==SQLITE_TEXT ){
          output_json_string(p->out, azArg[i], -1);
        }else{
          utf8_printf(p->out,"%s", azArg[i]);
        }
        if( i<nArg-1 ){
          putc(',', p->out);
        }
      }
      putc('}', p->out);
      break;
    }
    case MODE_Quote: {
      if( azArg==0 ) break;
      if( p->cnt==0 && p->showHeader ){
        for(i=0; i<nArg; i++){
          if( i>0 ) fputs(p->colSeparator, p->out);
          output_quoted_string(p->out, azCol[i]);
        }
        raw_printf(p->out,"\n");
        fputs(p->rowSeparator, p->out);
      }
      p->cnt++;
      for(i=0; i<nArg; i++){
        if( i>0 ) raw_printf(p->out, ",");
        if( i>0 ) fputs(p->colSeparator, p->out);
        if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
          utf8_printf(p->out,"NULL");
        }else if( aiType && aiType[i]==SQLITE_TEXT ){
          output_quoted_string(p->out, azArg[i]);
        }else if( aiType && aiType[i]==SQLITE_INTEGER ){
          utf8_printf(p->out,"%s", azArg[i]);
        }else if( aiType && aiType[i]==SQLITE_FLOAT ){
2110
2111
2112
2113
2114
2115
2116
2117

2118
2119
2120
2121
2122
2123
2124
2620
2621
2622
2623
2624
2625
2626

2627
2628
2629
2630
2631
2632
2633
2634







-
+







          output_hex_blob(p->out, pBlob, nBlob);
        }else if( isNumber(azArg[i], 0) ){
          utf8_printf(p->out,"%s", azArg[i]);
        }else{
          output_quoted_string(p->out, azArg[i]);
        }
      }
      raw_printf(p->out,"\n");
      fputs(p->rowSeparator, p->out);
      break;
    }
    case MODE_Ascii: {
      if( p->cnt++==0 && p->showHeader ){
        for(i=0; i<nArg; i++){
          if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
          utf8_printf(p->out,"%s",azCol[i] ? azCol[i] : "");
2183
2184
2185
2186
2187
2188
2189
2190

2191
2192

2193
2194
2195
2196
2197
2198
2199

2200
2201
2202
2203
2204
2205
2206
2693
2694
2695
2696
2697
2698
2699

2700
2701

2702
2703
2704
2705
2706
2707
2708

2709
2710
2711
2712
2713
2714
2715
2716







-
+

-
+






-
+







    "CREATE TEMP TABLE [_shell$self](op,cmd,ans);\n"
    "INSERT INTO [_shell$self](rowid,op,cmd)\n"
    "  VALUES(coalesce((SELECT (max(tno)+100)/10 FROM selftest),10),\n"
    "         'memo','Tests generated by --init');\n"
    "INSERT INTO [_shell$self]\n"
    "  SELECT 'run',\n"
    "    'SELECT hex(sha3_query(''SELECT type,name,tbl_name,sql "
                                 "FROM sqlite_master ORDER BY 2'',224))',\n"
                                 "FROM sqlite_schema ORDER BY 2'',224))',\n"
    "    hex(sha3_query('SELECT type,name,tbl_name,sql "
                          "FROM sqlite_master ORDER BY 2',224));\n"
                          "FROM sqlite_schema ORDER BY 2',224));\n"
    "INSERT INTO [_shell$self]\n"
    "  SELECT 'run',"
    "    'SELECT hex(sha3_query(''SELECT * FROM \"' ||"
    "        printf('%w',name) || '\" NOT INDEXED'',224))',\n"
    "    hex(sha3_query(printf('SELECT * FROM \"%w\" NOT INDEXED',name),224))\n"
    "  FROM (\n"
    "    SELECT name FROM sqlite_master\n"
    "    SELECT name FROM sqlite_schema\n"
    "     WHERE type='table'\n"
    "       AND name<>'selftest'\n"
    "       AND coalesce(rootpage,0)>0\n"
    "  )\n"
    " ORDER BY name;\n"
    "INSERT INTO [_shell$self]\n"
    "  VALUES('run','PRAGMA integrity_check','ok');\n"
2231
2232
2233
2234
2235
2236
2237
2238

2239
2240
2241
2242
2243
2244
2245
2246
2247










































2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262

2263
2264
2265
2266
2267
2268
2269
2270
2271

2272
2273



2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2741
2742
2743
2744
2745
2746
2747

2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
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
2811
2812
2813

2814

2815
2816
2817
2818
2819
2820
2821
2822
2823


2824
2825
2826
2827
2828
2829
2830
2831
2832




2833
2834
2835
2836
2837
2838
2839







-
+









+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+














-
+
-








+
-
-
+
+
+






-
-
-
-







    p->zDestTable = 0;
  }
  if( zName==0 ) return;
  cQuote = quoteChar(zName);
  n = strlen30(zName);
  if( cQuote ) n += n+2;
  z = p->zDestTable = malloc( n+1 );
  if( z==0 ) shell_out_of_memory();
  shell_check_oom(z);
  n = 0;
  if( cQuote ) z[n++] = cQuote;
  for(i=0; zName[i]; i++){
    z[n++] = zName[i];
    if( zName[i]==cQuote ) z[n++] = cQuote;
  }
  if( cQuote ) z[n++] = cQuote;
  z[n] = 0;
}

/*
** Maybe construct two lines of text that point out the position of a
** syntax error.  Return a pointer to the text, in memory obtained from
** sqlite3_malloc().  Or, if the most recent error does not involve a
** specific token that we can point to, return an empty string.
**
** In all cases, the memory returned is obtained from sqlite3_malloc64()
** and should be released by the caller invoking sqlite3_free().
*/
static char *shell_error_context(const char *zSql, sqlite3 *db){
  int iOffset;
  size_t len;
  char *zCode;
  char *zMsg;
  int i;
  if( db==0
   || zSql==0
   || (iOffset = sqlite3_error_offset(db))<0
  ){
    return sqlite3_mprintf("");
  }
  while( iOffset>50 ){
    iOffset--;
    zSql++;
    while( (zSql[0]&0xc0)==0x80 ){ zSql++; iOffset--; }
  }
  len = strlen(zSql);
  if( len>78 ){
    len = 78;
    while( (zSql[len]&0xc0)==0x80 ) len--;
  }
  zCode = sqlite3_mprintf("%.*s", len, zSql);
  shell_check_oom(zCode);
  for(i=0; zCode[i]; i++){ if( IsSpace(zSql[i]) ) zCode[i] = ' '; }
  if( iOffset<25 ){
    zMsg = sqlite3_mprintf("\n  %z\n  %*s^--- error here", zCode,iOffset,"");
  }else{
    zMsg = sqlite3_mprintf("\n  %z\n  %*serror here ---^", zCode,iOffset-14,"");
  }
  return zMsg;
}


/*
** Execute a query statement that will generate SQL output.  Print
** the result columns, comma-separated, on a line and then add a
** semicolon terminator to the end of that line.
**
** If the number of columns is 1 and that column contains text "--"
** then write the semicolon on a separate line.  That way, if a
** "--" comment occurs at the end of the statement, the comment
** won't consume the semicolon terminator.
*/
static int run_table_dump_query(
  ShellState *p,           /* Query context */
  const char *zSelect,     /* SELECT statement to extract content */
  const char *zSelect      /* SELECT statement to extract content */
  const char *zFirstRow    /* Print before first row, if not NULL */
){
  sqlite3_stmt *pSelect;
  int rc;
  int nResult;
  int i;
  const char *z;
  rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
  if( rc!=SQLITE_OK || !pSelect ){
    char *zContext = shell_error_context(zSelect, p->db);
    utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
                sqlite3_errmsg(p->db));
    utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n%s", rc,
                sqlite3_errmsg(p->db), zContext);
    sqlite3_free(zContext);
    if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
    return rc;
  }
  rc = sqlite3_step(pSelect);
  nResult = sqlite3_column_count(pSelect);
  while( rc==SQLITE_ROW ){
    if( zFirstRow ){
      utf8_printf(p->out, "%s", zFirstRow);
      zFirstRow = 0;
    }
    z = (const char*)sqlite3_column_text(pSelect, 0);
    utf8_printf(p->out, "%s", z);
    for(i=1; i<nResult; i++){
      utf8_printf(p->out, ",%s", sqlite3_column_text(pSelect, i));
    }
    if( z==0 ) z = "";
    while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
2301
2302
2303
2304
2305
2306
2307
2308

2309
2310
2311




2312
2313
2314
2315
2316











2317


2318

2319
2320
2321
2322
2323
2324
2325
2850
2851
2852
2853
2854
2855
2856

2857
2858
2859

2860
2861
2862
2863
2864




2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878

2879
2880
2881
2882
2883
2884
2885
2886







-
+


-
+
+
+
+

-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

+
+
-
+







                sqlite3_errmsg(p->db));
    if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
  }
  return rc;
}

/*
** Allocate space and save off current error string.
** Allocate space and save off string indicating current error.
*/
static char *save_err_msg(
  sqlite3 *db            /* Database to query */
  sqlite3 *db,           /* Database to query */
  const char *zPhase,    /* When the error occcurs */
  int rc,                /* Error code returned from API */
  const char *zSql       /* SQL string, or NULL */
){
  int nErrMsg = 1+strlen30(sqlite3_errmsg(db));
  char *zErrMsg = sqlite3_malloc64(nErrMsg);
  if( zErrMsg ){
    memcpy(zErrMsg, sqlite3_errmsg(db), nErrMsg);
  char *zErr;
  char *zContext;
  sqlite3_str *pStr = sqlite3_str_new(0);
  sqlite3_str_appendf(pStr, "%s, %s", zPhase, sqlite3_errmsg(db));
  if( rc>1 ){
    sqlite3_str_appendf(pStr, " (%d)", rc);
  }
  zContext = shell_error_context(zSql, db);
  if( zContext ){
    sqlite3_str_appendall(pStr, zContext);
    sqlite3_free(zContext);
  }
  zErr = sqlite3_str_finish(pStr);
  shell_check_oom(zErr);
  return zErrMsg;
  return zErr;
}

#ifdef __linux__
/*
** Attempt to display I/O stats on Linux using /proc/PID/io
*/
static void displayLinuxIoStats(FILE *out){
2340
2341
2342
2343
2344
2345
2346
2347

2348
2349
2350
2351
2352
2353
2354
2901
2902
2903
2904
2905
2906
2907

2908
2909
2910
2911
2912
2913
2914
2915







-
+







      { "read_bytes: ",             "Bytes read from storage:"  },
      { "write_bytes: ",            "Bytes written to storage:" },
      { "cancelled_write_bytes: ",  "Cancelled write bytes:"    },
    };
    int i;
    for(i=0; i<ArraySize(aTrans); i++){
      int n = strlen30(aTrans[i].zPattern);
      if( strncmp(aTrans[i].zPattern, z, n)==0 ){
      if( cli_strncmp(aTrans[i].zPattern, z, n)==0 ){
        utf8_printf(out, "%-36s %s", aTrans[i].zDesc, &z[n]);
        break;
      }
    }
  }
  fclose(in);
}
2390
2391
2392
2393
2394
2395
2396
2397

2398
2399
2400
2401
2402
2403
2404
2951
2952
2953
2954
2955
2956
2957

2958
2959
2960
2961
2962
2963
2964
2965







-
+







){
  int iCur;
  int iHiwtr;
  FILE *out;
  if( pArg==0 || pArg->out==0 ) return 0;
  out = pArg->out;

  if( pArg->pStmt && (pArg->statsOn & 2) ){
  if( pArg->pStmt && pArg->statsOn==2 ){
    int nCol, i, x;
    sqlite3_stmt *pStmt = pArg->pStmt;
    char z[100];
    nCol = sqlite3_column_count(pStmt);
    raw_printf(out, "%-36s %d\n", "Number of output columns:", nCol);
    for(i=0; i<nCol; i++){
      sqlite3_snprintf(sizeof(z),z,"Column %d %nname:", i, &x);
2413
2414
2415
2416
2417
2418
2419








2420
2421
2422
2423
2424
2425
2426
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995







+
+
+
+
+
+
+
+







      sqlite3_snprintf(30, z+x, "table name:");
      utf8_printf(out, "%-36s %s\n", z, sqlite3_column_table_name(pStmt,i));
      sqlite3_snprintf(30, z+x, "origin name:");
      utf8_printf(out, "%-36s %s\n", z, sqlite3_column_origin_name(pStmt,i));
#endif
    }
  }

  if( pArg->statsOn==3 ){
    if( pArg->pStmt ){
      iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP,bReset);
      raw_printf(pArg->out, "VM-steps: %d\n", iCur);
    }
    return 0;
  }

  displayStatLine(pArg, "Memory Used:",
     "%lld (max %lld) bytes", SQLITE_STATUS_MEMORY_USED, bReset);
  displayStatLine(pArg, "Number of Outstanding Allocations:",
     "%lld (max %lld)", SQLITE_STATUS_MALLOC_COUNT, bReset);
  if( pArg->shellFlgs & SHFLG_Pagecache ){
    displayStatLine(pArg, "Number of Pcache Pages Used:",
2481
2482
2483
2484
2485
2486
2487

2488
2489
2490
2491
2492
2493
2494








2495
2496
2497

2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513





























2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524


2525
2526
2527
2528
















2529
2530


2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544































2545
2546
2547
2548
2549





2550
2551
2552
2553
2554






2555
2556
2557
2558






2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571

2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585



2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601


2602
2603
2604
2605
2606
2607
2608
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074

3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133




3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149


3150
3151














3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183




3184
3185
3186
3187
3188





3189
3190
3191
3192
3193
3194
3195
3196


3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214

3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247

3248
3249
3250
3251
3252
3253
3254
3255
3256







+







+
+
+
+
+
+
+
+


-
+
















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+











+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+


-
-
+
+
+
+
+
+












-
+














+
+
+















-
+
+







    iHiwtr = iCur = -1;
    sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
    raw_printf(pArg->out, "Statement Heap/Lookaside Usage:      %d bytes\n",
            iCur);
  }

  if( pArg->pStmt ){
    int iHit, iMiss;
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
                               bReset);
    raw_printf(pArg->out, "Fullscan Steps:                      %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
    raw_printf(pArg->out, "Sort Operations:                     %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset);
    raw_printf(pArg->out, "Autoindex Inserts:                   %d\n", iCur);
    iHit = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FILTER_HIT,
                               bReset);
    iMiss = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FILTER_MISS,
                                bReset);
    if( iHit || iMiss ){
      raw_printf(pArg->out, "Bloom filter bypass taken:           %d/%d\n",
            iHit, iHit+iMiss);
    }
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
    raw_printf(pArg->out, "Virtual Machine Steps:               %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE, bReset);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset);
    raw_printf(pArg->out, "Reprepare operations:                %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset);
    raw_printf(pArg->out, "Number of times run:                 %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset);
    raw_printf(pArg->out, "Memory used by prepared stmt:        %d\n", iCur);
  }

#ifdef __linux__
  displayLinuxIoStats(pArg->out);
#endif

  /* Do not remove this machine readable comment: extra-stats-output-here */

  return 0;
}


#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
static int scanStatsHeight(sqlite3_stmt *p, int iEntry){
  int iPid = 0;
  int ret = 1;
  sqlite3_stmt_scanstatus_v2(p, iEntry,
      SQLITE_SCANSTAT_SELECTID, SQLITE_SCANSTAT_COMPLEX, (void*)&iPid
  );
  while( iPid!=0 ){
    int ii;
    for(ii=0; 1; ii++){
      int iId;
      int res;
      res = sqlite3_stmt_scanstatus_v2(p, ii,
          SQLITE_SCANSTAT_SELECTID, SQLITE_SCANSTAT_COMPLEX, (void*)&iId
      );
      if( res ) break;
      if( iId==iPid ){
        sqlite3_stmt_scanstatus_v2(p, ii,
            SQLITE_SCANSTAT_PARENTID, SQLITE_SCANSTAT_COMPLEX, (void*)&iPid
        );
      }
    }
    ret++;
  }
  return ret;
}
#endif

/*
** Display scan stats.
*/
static void display_scanstats(
  sqlite3 *db,                    /* Database to query */
  ShellState *pArg                /* Pointer to ShellState */
){
#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
  UNUSED_PARAMETER(db);
  UNUSED_PARAMETER(pArg);
#else
  static const int f = SQLITE_SCANSTAT_COMPLEX;
  sqlite3_stmt *p = pArg->pStmt;
  int i, k, n, mx;
  raw_printf(pArg->out, "-------- scanstats --------\n");
  mx = 0;
  for(k=0; k<=mx; k++){
  int ii = 0;
  i64 nTotal = 0;
  int nWidth = 0;
  eqp_reset(pArg);

  for(ii=0; 1; ii++){
    const char *z = 0;
    int n = 0;
    if( sqlite3_stmt_scanstatus_v2(p,ii,SQLITE_SCANSTAT_EXPLAIN,f,(void*)&z) ){
      break;
    }
    n = strlen(z) + scanStatsHeight(p, ii)*3;
    if( n>nWidth ) nWidth = n;
  }
  nWidth += 4;

    double rEstLoop = 1.0;
    for(i=n=0; 1; i++){
  sqlite3_stmt_scanstatus_v2(p, -1, SQLITE_SCANSTAT_NCYCLE, f, (void*)&nTotal);
  for(ii=0; 1; ii++){
      sqlite3_stmt *p = pArg->pStmt;
      sqlite3_int64 nLoop, nVisit;
      double rEst;
      int iSid;
      const char *zExplain;
      if( sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop) ){
        break;
      }
      sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_SELECTID, (void*)&iSid);
      if( iSid>mx ) mx = iSid;
      if( iSid!=k ) continue;
      if( n==0 ){
        rEstLoop = (double)nLoop;
        if( k>0 ) raw_printf(pArg->out, "-------- subquery %d -------\n", k);
    i64 nLoop = 0;
    i64 nRow = 0;
    i64 nCycle = 0;
    int iId = 0;
    int iPid = 0;
    const char *z = 0;
    const char *zName = 0;
    char *zText = 0;
    double rEst = 0.0;

    if( sqlite3_stmt_scanstatus_v2(p,ii,SQLITE_SCANSTAT_EXPLAIN,f,(void*)&z) ){
      break;
    }
    sqlite3_stmt_scanstatus_v2(p, ii, SQLITE_SCANSTAT_EST,f,(void*)&rEst);
    sqlite3_stmt_scanstatus_v2(p, ii, SQLITE_SCANSTAT_NLOOP,f,(void*)&nLoop);
    sqlite3_stmt_scanstatus_v2(p, ii, SQLITE_SCANSTAT_NVISIT,f,(void*)&nRow);
    sqlite3_stmt_scanstatus_v2(p, ii, SQLITE_SCANSTAT_NCYCLE,f,(void*)&nCycle);
    sqlite3_stmt_scanstatus_v2(p, ii, SQLITE_SCANSTAT_SELECTID,f,(void*)&iId);
    sqlite3_stmt_scanstatus_v2(p, ii, SQLITE_SCANSTAT_PARENTID,f,(void*)&iPid);
    sqlite3_stmt_scanstatus_v2(p, ii, SQLITE_SCANSTAT_NAME,f,(void*)&zName);

    zText = sqlite3_mprintf("%s", z);
    if( nCycle>=0 || nLoop>=0 || nRow>=0 ){
      char *z = 0;
      if( nCycle>=0 && nTotal>0 ){
        z = sqlite3_mprintf("%zcycles=%lld [%d%%]", z,
            nCycle, ((nCycle*100)+nTotal/2) / nTotal
        );
      }
      if( nLoop>=0 ){
        z = sqlite3_mprintf("%z%sloops=%lld", z, z ? " " : "", nLoop);
      }
      n++;
      sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
      sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EST, (void*)&rEst);
      sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
      if( nRow>=0 ){
        z = sqlite3_mprintf("%z%srows=%lld", z, z ? " " : "", nRow);
      }

      if( zName && pArg->scanstatsOn>1 ){
      utf8_printf(pArg->out, "Loop %2d: %s\n", n, zExplain);
      rEstLoop *= rEst;
      raw_printf(pArg->out,
          "         nLoop=%-8lld nRow=%-8lld estRow=%-8lld estRow/Loop=%-8g\n",
          nLoop, nVisit, (sqlite3_int64)(rEstLoop+0.5), rEst
        double rpl = (double)nRow / (double)nLoop;
        z = sqlite3_mprintf("%z rpl=%.1f est=%.1f", z, rpl, rEst);
      }

      zText = sqlite3_mprintf(
          "% *z (%z)", -1*(nWidth-scanStatsHeight(p, ii)*3), zText, z
      );
    }
  }
  raw_printf(pArg->out, "---------------------------\n");

    eqp_append(pArg, iId, iPid, zText);
    sqlite3_free(zText);
  }

  eqp_render(pArg, nTotal);
#endif
}

/*
** Parameter azArray points to a zero-terminated array of strings. zStr
** points to a single nul-terminated string. Return non-zero if zStr
** is equal, according to strcmp(), to any of the strings in the array.
** Otherwise, return zero.
*/
static int str_in_array(const char *zStr, const char **azArray){
  int i;
  for(i=0; azArray[i]; i++){
    if( 0==strcmp(zStr, azArray[i]) ) return 1;
    if( 0==cli_strcmp(zStr, azArray[i]) ) return 1;
  }
  return 0;
}

/*
** If compiled statement pSql appears to be an EXPLAIN statement, allocate
** and populate the ShellState.aiIndent[] array with the number of
** spaces each opcode should be indented before it is output.
**
** The indenting rules are:
**
**     * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent
**       all opcodes that occur between the p2 jump destination and the opcode
**       itself by 2 spaces.
**
**     * Do the previous for "Return" instructions for when P2 is positive.
**       See tag-20220407a in wherecode.c and vdbe.c.
**
**     * For each "Goto", if the jump destination is earlier in the program
**       and ends on one of:
**          Yield  SeekGt  SeekLt  RowSetRead  Rewind
**       or if the P1 parameter is one instead of zero,
**       then indent all opcodes between the earlier instruction
**       and "Goto" by 2 spaces.
*/
static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
  const char *zSql;               /* The text of the SQL statement */
  const char *z;                  /* Used to check if this is an EXPLAIN */
  int *abYield = 0;               /* True if op is an OP_Yield */
  int nAlloc = 0;                 /* Allocated size of p->aiIndent[], abYield */
  int iOp;                        /* Index of operation in p->aiIndent[] */

  const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", 0 };
  const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext",
                           "Return", 0 };
  const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead",
                            "Rewind", 0 };
  const char *azGoto[] = { "Goto", 0 };

  /* Try to figure out if this is really an EXPLAIN statement. If this
  ** cannot be verified, return early.  */
  if( sqlite3_column_count(pSql)!=8 ){
2635
2636
2637
2638
2639
2640
2641
2642

2643
2644
2645
2646
2647
2648
2649
2650
2651

2652
2653

2654
2655
2656
2657
2658
2659

2660
2661
2662
2663
2664
2665
2666
3283
3284
3285
3286
3287
3288
3289

3290
3291
3292
3293
3294
3295
3296
3297
3298

3299
3300

3301
3302
3303
3304
3305
3306

3307
3308
3309
3310
3311
3312
3313
3314







-
+








-
+

-
+





-
+







      if( iOp==0 ){
        /* Do further verfication that this is explain output.  Abort if
        ** it is not */
        static const char *explainCols[] = {
           "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment" };
        int jj;
        for(jj=0; jj<ArraySize(explainCols); jj++){
          if( strcmp(sqlite3_column_name(pSql,jj),explainCols[jj])!=0 ){
          if( cli_strcmp(sqlite3_column_name(pSql,jj),explainCols[jj])!=0 ){
            p->cMode = p->mode;
            sqlite3_reset(pSql);
            return;
          }
        }
      }
      nAlloc += 100;
      p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int));
      if( p->aiIndent==0 ) shell_out_of_memory();
      shell_check_oom(p->aiIndent);
      abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int));
      if( abYield==0 ) shell_out_of_memory();
      shell_check_oom(abYield);
    }
    abYield[iOp] = str_in_array(zOp, azYield);
    p->aiIndent[iOp] = 0;
    p->nIndent = iOp+1;

    if( str_in_array(zOp, azNext) ){
    if( str_in_array(zOp, azNext) && p2op>0 ){
      for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
    }
    if( str_in_array(zOp, azGoto) && p2op<p->nIndent
     && (abYield[p2op] || sqlite3_column_int(pSql, 2))
    ){
      for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
    }
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
2704
2705



2706
2707
2708
2709
2710
2711








































































































































































































































































































































































































































































































2712
2713
2714
2715
2716
2717
2718
2719
2720
2721










2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733

2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744

2745
2746
2747
2748




2749
2750
2751
2752
2753
2754
2755
3326
3327
3328
3329
3330
3331
3332

3333
3334



3335




3336

3337



3338
3339
3340




3341
3342

3343
3344
3345
3346
3347






3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
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
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
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
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
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
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







-
+

-
-
-
+
-
-
-
-
+
-

-
-
-
+
+
+
-
-
-
-
+
+
-


+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










+
+
+
+
+
+
+
+
+
+











-
+











+



-
+
+
+
+







  sqlite3_free(p->aiIndent);
  p->aiIndent = 0;
  p->nIndent = 0;
  p->iIndent = 0;
}

/*
** Disable and restore .wheretrace and .selecttrace settings.
** Disable and restore .wheretrace and .treetrace/.selecttrace settings.
*/
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
extern int sqlite3SelectTrace;
static int savedSelectTrace;
static unsigned int savedSelectTrace;
#endif
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
extern int sqlite3WhereTrace;
static int savedWhereTrace;
static unsigned int savedWhereTrace;
#endif
static void disable_debug_trace_modes(void){
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
  savedSelectTrace = sqlite3SelectTrace;
  sqlite3SelectTrace = 0;
  unsigned int zero = 0;
  sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 0, &savedSelectTrace);
  sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &zero);
#endif
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
  savedWhereTrace = sqlite3WhereTrace;
  sqlite3WhereTrace = 0;
  sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 2, &savedWhereTrace);
  sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &zero);
#endif
}
static void restore_debug_trace_modes(void){
  sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &savedSelectTrace);
  sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &savedWhereTrace);
}
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
  sqlite3SelectTrace = savedSelectTrace;
#endif
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
  sqlite3WhereTrace = savedWhereTrace;
#endif

/* Create the TEMP table used to store parameter bindings */
static void bind_table_init(ShellState *p){
  int wrSchema = 0;
  int defensiveMode = 0;
  sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, -1, &defensiveMode);
  sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, 0, 0);
  sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema);
  sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);
  sqlite3_exec(p->db,
    "CREATE TABLE IF NOT EXISTS temp.sqlite_parameters(\n"
    "  key TEXT PRIMARY KEY,\n"
    "  value\n"
    ") WITHOUT ROWID;",
    0, 0, 0);
  sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0);
  sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, defensiveMode, 0);
}

/*
** Bind parameters on a prepared statement.
**
** Parameter bindings are taken from a TEMP table of the form:
**
**    CREATE TEMP TABLE sqlite_parameters(key TEXT PRIMARY KEY, value)
**    WITHOUT ROWID;
**
** No bindings occur if this table does not exist.  The name of the table
** begins with "sqlite_" so that it will not collide with ordinary application
** tables.  The table must be in the TEMP schema.
*/
static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){
  int nVar;
  int i;
  int rc;
  sqlite3_stmt *pQ = 0;

  nVar = sqlite3_bind_parameter_count(pStmt);
  if( nVar==0 ) return;  /* Nothing to do */
  if( sqlite3_table_column_metadata(pArg->db, "TEMP", "sqlite_parameters",
                                    "key", 0, 0, 0, 0, 0)!=SQLITE_OK ){
    return; /* Parameter table does not exist */
  }
  rc = sqlite3_prepare_v2(pArg->db,
          "SELECT value FROM temp.sqlite_parameters"
          " WHERE key=?1", -1, &pQ, 0);
  if( rc || pQ==0 ) return;
  for(i=1; i<=nVar; i++){
    char zNum[30];
    const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
    if( zVar==0 ){
      sqlite3_snprintf(sizeof(zNum),zNum,"?%d",i);
      zVar = zNum;
    }
    sqlite3_bind_text(pQ, 1, zVar, -1, SQLITE_STATIC);
    if( sqlite3_step(pQ)==SQLITE_ROW ){
      sqlite3_bind_value(pStmt, i, sqlite3_column_value(pQ, 0));
    }else{
      sqlite3_bind_null(pStmt, i);
    }
    sqlite3_reset(pQ);
  }
  sqlite3_finalize(pQ);
}

/*
** UTF8 box-drawing characters.  Imagine box lines like this:
**
**           1
**           |
**       4 --+-- 2
**           |
**           3
**
** Each box characters has between 2 and 4 of the lines leading from
** the center.  The characters are here identified by the numbers of
** their corresponding lines.
*/
#define BOX_24   "\342\224\200"  /* U+2500 --- */
#define BOX_13   "\342\224\202"  /* U+2502  |  */
#define BOX_23   "\342\224\214"  /* U+250c  ,- */
#define BOX_34   "\342\224\220"  /* U+2510 -,  */
#define BOX_12   "\342\224\224"  /* U+2514  '- */
#define BOX_14   "\342\224\230"  /* U+2518 -'  */
#define BOX_123  "\342\224\234"  /* U+251c  |- */
#define BOX_134  "\342\224\244"  /* U+2524 -|  */
#define BOX_234  "\342\224\254"  /* U+252c -,- */
#define BOX_124  "\342\224\264"  /* U+2534 -'- */
#define BOX_1234 "\342\224\274"  /* U+253c -|- */

/* Draw horizontal line N characters long using unicode box
** characters
*/
static void print_box_line(FILE *out, int N){
  const char zDash[] =
      BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24
      BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24;
  const int nDash = sizeof(zDash) - 1;
  N *= 3;
  while( N>nDash ){
    utf8_printf(out, zDash);
    N -= nDash;
  }
  utf8_printf(out, "%.*s", N, zDash);
}

/*
** Draw a horizontal separator for a MODE_Box table.
*/
static void print_box_row_separator(
  ShellState *p,
  int nArg,
  const char *zSep1,
  const char *zSep2,
  const char *zSep3
){
  int i;
  if( nArg>0 ){
    utf8_printf(p->out, "%s", zSep1);
    print_box_line(p->out, p->actualWidth[0]+2);
    for(i=1; i<nArg; i++){
      utf8_printf(p->out, "%s", zSep2);
      print_box_line(p->out, p->actualWidth[i]+2);
    }
    utf8_printf(p->out, "%s", zSep3);
  }
  fputs("\n", p->out);
}

/*
** z[] is a line of text that is to be displayed the .mode box or table or
** similar tabular formats.  z[] might contain control characters such
** as \n, \t, \f, or \r.
**
** Compute characters to display on the first line of z[].  Stop at the
** first \r, \n, or \f.  Expand \t into spaces.  Return a copy (obtained
** from malloc()) of that first line, which caller should free sometime.
** Write anything to display on the next line into *pzTail.  If this is
** the last line, write a NULL into *pzTail. (*pzTail is not allocated.)
*/
static char *translateForDisplayAndDup(
  const unsigned char *z,            /* Input text to be transformed */
  const unsigned char **pzTail,      /* OUT: Tail of the input for next line */
  int mxWidth,                       /* Max width.  0 means no limit */
  u8 bWordWrap                       /* If true, avoid breaking mid-word */
){
  int i;                 /* Input bytes consumed */
  int j;                 /* Output bytes generated */
  int k;                 /* Input bytes to be displayed */
  int n;                 /* Output column number */
  unsigned char *zOut;   /* Output text */

  if( z==0 ){
    *pzTail = 0;
    return 0;
  }
  if( mxWidth<0 ) mxWidth = -mxWidth;
  if( mxWidth==0 ) mxWidth = 1000000;
  i = j = n = 0;
  while( n<mxWidth ){
    if( z[i]>=' ' ){
      n++;
      do{ i++; j++; }while( (z[i]&0xc0)==0x80 );
      continue;
    }
    if( z[i]=='\t' ){
      do{
        n++;
        j++;
      }while( (n&7)!=0 && n<mxWidth );
      i++;
      continue;
    }
    break;
  }
  if( n>=mxWidth && bWordWrap  ){
    /* Perhaps try to back up to a better place to break the line */
    for(k=i; k>i/2; k--){
      if( isspace(z[k-1]) ) break;
    }
    if( k<=i/2 ){
      for(k=i; k>i/2; k--){
        if( isalnum(z[k-1])!=isalnum(z[k]) && (z[k]&0xc0)!=0x80 ) break;
      }
    }
    if( k<=i/2 ){
      k = i;
    }else{
      i = k;
      while( z[i]==' ' ) i++;
    }
  }else{
    k = i;
  }
  if( n>=mxWidth && z[i]>=' ' ){
   *pzTail = &z[i];
  }else if( z[i]=='\r' && z[i+1]=='\n' ){
    *pzTail = z[i+2] ? &z[i+2] : 0;
  }else if( z[i]==0 || z[i+1]==0 ){
    *pzTail = 0;
  }else{
    *pzTail = &z[i+1];
  }
  zOut = malloc( j+1 );
  shell_check_oom(zOut);
  i = j = n = 0;
  while( i<k ){
    if( z[i]>=' ' ){
      n++;
      do{ zOut[j++] = z[i++]; }while( (z[i]&0xc0)==0x80 );
      continue;
    }
    if( z[i]=='\t' ){
      do{
        n++;
        zOut[j++] = ' ';
      }while( (n&7)!=0 && n<mxWidth );
      i++;
      continue;
    }
    break;
  }
  zOut[j] = 0;
  return (char*)zOut;
}

/* Extract the value of the i-th current column for pStmt as an SQL literal
** value.  Memory is obtained from sqlite3_malloc64() and must be freed by
** the caller.
*/
static char *quoted_column(sqlite3_stmt *pStmt, int i){
  switch( sqlite3_column_type(pStmt, i) ){
    case SQLITE_NULL: {
      return sqlite3_mprintf("NULL");
    }
    case SQLITE_INTEGER:
    case SQLITE_FLOAT: {
      return sqlite3_mprintf("%s",sqlite3_column_text(pStmt,i));
    }
    case SQLITE_TEXT: {
      return sqlite3_mprintf("%Q",sqlite3_column_text(pStmt,i));
    }
    case SQLITE_BLOB: {
      int j;
      sqlite3_str *pStr = sqlite3_str_new(0);
      const unsigned char *a = sqlite3_column_blob(pStmt,i);
      int n = sqlite3_column_bytes(pStmt,i);
      sqlite3_str_append(pStr, "x'", 2);
      for(j=0; j<n; j++){
        sqlite3_str_appendf(pStr, "%02x", a[j]);
      }
      sqlite3_str_append(pStr, "'", 1);
      return sqlite3_str_finish(pStr);
    }
  }
  return 0; /* Not reached */
}

/*
** Run a prepared statement and output the result in one of the
** table-oriented formats: MODE_Column, MODE_Markdown, MODE_Table,
** or MODE_Box.
**
** This is different from ordinary exec_prepared_stmt() in that
** it has to run the entire query and gather the results into memory
** first, in order to determine column widths, before providing
** any output.
*/
static void exec_prepared_stmt_columnar(
  ShellState *p,                        /* Pointer to ShellState */
  sqlite3_stmt *pStmt                   /* Statment to run */
){
  sqlite3_int64 nRow = 0;
  int nColumn = 0;
  char **azData = 0;
  sqlite3_int64 nAlloc = 0;
  char *abRowDiv = 0;
  const unsigned char *uz;
  const char *z;
  char **azQuoted = 0;
  int rc;
  sqlite3_int64 i, nData;
  int j, nTotal, w, n;
  const char *colSep = 0;
  const char *rowSep = 0;
  const unsigned char **azNextLine = 0;
  int bNextLine = 0;
  int bMultiLineRowExists = 0;
  int bw = p->cmOpts.bWordWrap;
  const char *zEmpty = "";
  const char *zShowNull = p->nullValue;

  rc = sqlite3_step(pStmt);
  if( rc!=SQLITE_ROW ) return;
  nColumn = sqlite3_column_count(pStmt);
  nAlloc = nColumn*4;
  if( nAlloc<=0 ) nAlloc = 1;
  azData = sqlite3_malloc64( nAlloc*sizeof(char*) );
  shell_check_oom(azData);
  azNextLine = sqlite3_malloc64( nColumn*sizeof(char*) );
  shell_check_oom((void*)azNextLine);
  memset((void*)azNextLine, 0, nColumn*sizeof(char*) );
  if( p->cmOpts.bQuote ){
    azQuoted = sqlite3_malloc64( nColumn*sizeof(char*) );
    shell_check_oom(azQuoted);
    memset(azQuoted, 0, nColumn*sizeof(char*) );
  }
  abRowDiv = sqlite3_malloc64( nAlloc/nColumn );
  shell_check_oom(abRowDiv);
  if( nColumn>p->nWidth ){
    p->colWidth = realloc(p->colWidth, (nColumn+1)*2*sizeof(int));
    shell_check_oom(p->colWidth);
    for(i=p->nWidth; i<nColumn; i++) p->colWidth[i] = 0;
    p->nWidth = nColumn;
    p->actualWidth = &p->colWidth[nColumn];
  }
  memset(p->actualWidth, 0, nColumn*sizeof(int));
  for(i=0; i<nColumn; i++){
    w = p->colWidth[i];
    if( w<0 ) w = -w;
    p->actualWidth[i] = w;
  }
  for(i=0; i<nColumn; i++){
    const unsigned char *zNotUsed;
    int wx = p->colWidth[i];
    if( wx==0 ){
      wx = p->cmOpts.iWrap;
    }
    if( wx<0 ) wx = -wx;
    uz = (const unsigned char*)sqlite3_column_name(pStmt,i);
    azData[i] = translateForDisplayAndDup(uz, &zNotUsed, wx, bw);
  }
  do{
    int useNextLine = bNextLine;
    bNextLine = 0;
    if( (nRow+2)*nColumn >= nAlloc ){
      nAlloc *= 2;
      azData = sqlite3_realloc64(azData, nAlloc*sizeof(char*));
      shell_check_oom(azData);
      abRowDiv = sqlite3_realloc64(abRowDiv, nAlloc/nColumn);
      shell_check_oom(abRowDiv);
    }
    abRowDiv[nRow] = 1;
    nRow++;
    for(i=0; i<nColumn; i++){
      int wx = p->colWidth[i];
      if( wx==0 ){
        wx = p->cmOpts.iWrap;
      }
      if( wx<0 ) wx = -wx;
      if( useNextLine ){
        uz = azNextLine[i];
        if( uz==0 ) uz = (u8*)zEmpty;
      }else if( p->cmOpts.bQuote ){
        sqlite3_free(azQuoted[i]);
        azQuoted[i] = quoted_column(pStmt,i);
        uz = (const unsigned char*)azQuoted[i];
      }else{
        uz = (const unsigned char*)sqlite3_column_text(pStmt,i);
        if( uz==0 ) uz = (u8*)zShowNull;
      }
      azData[nRow*nColumn + i]
        = translateForDisplayAndDup(uz, &azNextLine[i], wx, bw);
      if( azNextLine[i] ){
        bNextLine = 1;
        abRowDiv[nRow-1] = 0;
        bMultiLineRowExists = 1;
      }
    }
  }while( bNextLine || sqlite3_step(pStmt)==SQLITE_ROW );
  nTotal = nColumn*(nRow+1);
  for(i=0; i<nTotal; i++){
    z = azData[i];
    if( z==0 ) z = (char*)zEmpty;
    n = strlenChar(z);
    j = i%nColumn;
    if( n>p->actualWidth[j] ) p->actualWidth[j] = n;
  }
  if( seenInterrupt ) goto columnar_end;
  if( nColumn==0 ) goto columnar_end;
  switch( p->cMode ){
    case MODE_Column: {
      colSep = "  ";
      rowSep = "\n";
      if( p->showHeader ){
        for(i=0; i<nColumn; i++){
          w = p->actualWidth[i];
          if( p->colWidth[i]<0 ) w = -w;
          utf8_width_print(p->out, w, azData[i]);
          fputs(i==nColumn-1?"\n":"  ", p->out);
        }
        for(i=0; i<nColumn; i++){
          print_dashes(p->out, p->actualWidth[i]);
          fputs(i==nColumn-1?"\n":"  ", p->out);
        }
      }
      break;
    }
    case MODE_Table: {
      colSep = " | ";
      rowSep = " |\n";
      print_row_separator(p, nColumn, "+");
      fputs("| ", p->out);
      for(i=0; i<nColumn; i++){
        w = p->actualWidth[i];
        n = strlenChar(azData[i]);
        utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
        fputs(i==nColumn-1?" |\n":" | ", p->out);
      }
      print_row_separator(p, nColumn, "+");
      break;
    }
    case MODE_Markdown: {
      colSep = " | ";
      rowSep = " |\n";
      fputs("| ", p->out);
      for(i=0; i<nColumn; i++){
        w = p->actualWidth[i];
        n = strlenChar(azData[i]);
        utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
        fputs(i==nColumn-1?" |\n":" | ", p->out);
      }
      print_row_separator(p, nColumn, "|");
      break;
    }
    case MODE_Box: {
      colSep = " " BOX_13 " ";
      rowSep = " " BOX_13 "\n";
      print_box_row_separator(p, nColumn, BOX_23, BOX_234, BOX_34);
      utf8_printf(p->out, BOX_13 " ");
      for(i=0; i<nColumn; i++){
        w = p->actualWidth[i];
        n = strlenChar(azData[i]);
        utf8_printf(p->out, "%*s%s%*s%s",
            (w-n)/2, "", azData[i], (w-n+1)/2, "",
            i==nColumn-1?" "BOX_13"\n":" "BOX_13" ");
      }
      print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134);
      break;
    }
  }
  for(i=nColumn, j=0; i<nTotal; i++, j++){
    if( j==0 && p->cMode!=MODE_Column ){
      utf8_printf(p->out, "%s", p->cMode==MODE_Box?BOX_13" ":"| ");
    }
    z = azData[i];
    if( z==0 ) z = p->nullValue;
    w = p->actualWidth[j];
    if( p->colWidth[j]<0 ) w = -w;
    utf8_width_print(p->out, w, z);
    if( j==nColumn-1 ){
      utf8_printf(p->out, "%s", rowSep);
      if( bMultiLineRowExists && abRowDiv[i/nColumn-1] && i+1<nTotal ){
        if( p->cMode==MODE_Table ){
          print_row_separator(p, nColumn, "+");
        }else if( p->cMode==MODE_Box ){
          print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134);
        }else if( p->cMode==MODE_Column ){
          raw_printf(p->out, "\n");
        }
      }
      j = -1;
      if( seenInterrupt ) goto columnar_end;
    }else{
      utf8_printf(p->out, "%s", colSep);
    }
  }
  if( p->cMode==MODE_Table ){
    print_row_separator(p, nColumn, "+");
  }else if( p->cMode==MODE_Box ){
    print_box_row_separator(p, nColumn, BOX_12, BOX_124, BOX_14);
  }
columnar_end:
  if( seenInterrupt ){
    utf8_printf(p->out, "Interrupt\n");
  }
  nData = (nRow+1)*nColumn;
  for(i=0; i<nData; i++){
    z = azData[i];
    if( z!=zEmpty && z!=zShowNull ) free(azData[i]);
  }
  sqlite3_free(azData);
  sqlite3_free((void*)azNextLine);
  sqlite3_free(abRowDiv);
  if( azQuoted ){
    for(i=0; i<nColumn; i++) sqlite3_free(azQuoted[i]);
    sqlite3_free(azQuoted);
  }
}

/*
** Run a prepared statement
*/
static void exec_prepared_stmt(
  ShellState *pArg,                                /* Pointer to ShellState */
  sqlite3_stmt *pStmt                              /* Statment to run */
){
  int rc;
  sqlite3_uint64 nRow = 0;

  if( pArg->cMode==MODE_Column
   || pArg->cMode==MODE_Table
   || pArg->cMode==MODE_Box
   || pArg->cMode==MODE_Markdown
  ){
    exec_prepared_stmt_columnar(pArg, pStmt);
    return;
  }

  /* perform the first step.  this will tell us if we
  ** have a result set or not and how wide it is.
  */
  rc = sqlite3_step(pStmt);
  /* if we have a result set... */
  if( SQLITE_ROW == rc ){
    /* allocate space for col name ptr, value ptr, and type */
    int nCol = sqlite3_column_count(pStmt);
    void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);
    if( !pData ){
      rc = SQLITE_NOMEM;
      shell_out_of_memory();
    }else{
      char **azCols = (char **)pData;      /* Names of result columns */
      char **azVals = &azCols[nCol];       /* Results */
      int *aiTypes = (int *)&azVals[nCol]; /* Result types */
      int i, x;
      assert(sizeof(int) <= sizeof(char *));
      /* save off ptrs to column names */
      for(i=0; i<nCol; i++){
        azCols[i] = (char *)sqlite3_column_name(pStmt, i);
      }
      do{
        nRow++;
        /* extract the data and data types */
        for(i=0; i<nCol; i++){
          aiTypes[i] = x = sqlite3_column_type(pStmt, i);
          if( x==SQLITE_BLOB && pArg && pArg->cMode==MODE_Insert ){
          if( x==SQLITE_BLOB
           && pArg
           && (pArg->cMode==MODE_Insert || pArg->cMode==MODE_Quote)
          ){
            azVals[i] = "";
          }else{
            azVals[i] = (char*)sqlite3_column_text(pStmt, i);
          }
          if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
            rc = SQLITE_NOMEM;
            break; /* from for */
2763
2764
2765
2766
2767
2768
2769








2770
2771
2772
2773
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
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
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







+
+
+
+
+
+
+
+
















-
-
+
+









-
+







            rc = SQLITE_ABORT;
          }else{
            rc = sqlite3_step(pStmt);
          }
        }
      } while( SQLITE_ROW == rc );
      sqlite3_free(pData);
      if( pArg->cMode==MODE_Json ){
        fputs("]\n", pArg->out);
      }else if( pArg->cMode==MODE_Count ){
        char zBuf[200];
        sqlite3_snprintf(sizeof(zBuf), zBuf, "%llu row%s\n",
                         nRow, nRow!=1 ? "s" : "");
        printf("%s", zBuf);
      }
    }
  }
}

#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** This function is called to process SQL if the previous shell command
** was ".expert". It passes the SQL in the second argument directly to
** the sqlite3expert object.
**
** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
** code. In this case, (*pzErr) may be set to point to a buffer containing
** an English language error message. It is the responsibility of the
** caller to eventually free this buffer using sqlite3_free().
*/
static int expertHandleSQL(
  ShellState *pState, 
  const char *zSql, 
  ShellState *pState,
  const char *zSql,
  char **pzErr
){
  assert( pState->expert.pExpert );
  assert( pzErr==0 || *pzErr==0 );
  return sqlite3_expert_sql(pState->expert.pExpert, zSql, pzErr);
}

/*
** This function is called either to silently clean up the object
** created by the ".expert" command (if bCancel==1), or to generate a 
** created by the ".expert" command (if bCancel==1), or to generate a
** report from it and then clean it up (if bCancel==0).
**
** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
** code. In this case, (*pzErr) may be set to point to a buffer containing
** an English language error message. It is the responsibility of the
** caller to eventually free this buffer using sqlite3_free().
*/
2861
2862
2863
2864
2865
2866
2867
2868

2869
2870
2871

2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892


2893
2894
2895
2896
2897
2898
2899

2900
2901
2902
2903
2904
2905
2906
4007
4008
4009
4010
4011
4012
4013

4014
4015
4016

4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037

4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054







-
+


-
+




















-
+
+







+







  memset(&pState->expert, 0, sizeof(ExpertInfo));

  for(i=1; rc==SQLITE_OK && i<nArg; i++){
    char *z = azArg[i];
    int n;
    if( z[0]=='-' && z[1]=='-' ) z++;
    n = strlen30(z);
    if( n>=2 && 0==strncmp(z, "-verbose", n) ){
    if( n>=2 && 0==cli_strncmp(z, "-verbose", n) ){
      pState->expert.bVerbose = 1;
    }
    else if( n>=2 && 0==strncmp(z, "-sample", n) ){
    else if( n>=2 && 0==cli_strncmp(z, "-sample", n) ){
      if( i==(nArg-1) ){
        raw_printf(stderr, "option requires an argument: %s\n", z);
        rc = SQLITE_ERROR;
      }else{
        iSample = (int)integerValue(azArg[++i]);
        if( iSample<0 || iSample>100 ){
          raw_printf(stderr, "value out of range: %s\n", azArg[i]);
          rc = SQLITE_ERROR;
        }
      }
    }
    else{
      raw_printf(stderr, "unknown option: %s\n", z);
      rc = SQLITE_ERROR;
    }
  }

  if( rc==SQLITE_OK ){
    pState->expert.pExpert = sqlite3_expert_new(pState->db, &zErr);
    if( pState->expert.pExpert==0 ){
      raw_printf(stderr, "sqlite3_expert_new: %s\n", zErr);
      raw_printf(stderr, "sqlite3_expert_new: %s\n",
                 zErr ? zErr : "out of memory");
      rc = SQLITE_ERROR;
    }else{
      sqlite3_expert_config(
          pState->expert.pExpert, EXPERT_CONFIG_SAMPLE, iSample
      );
    }
  }
  sqlite3_free(zErr);

  return rc;
}
#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */

/*
** Execute a statement or set of statements.  Print
2934
2935
2936
2937
2938
2939
2940
2941

2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966

2967
2968
2969
2970
2971
2972
2973
2974
2975

2976
2977
2978
2979
2980
2981

2982

2983
2984
2985

2986
2987
2988
2989
2990
2991

2992
2993
2994
2995
2996
2997
2998
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
4107





4108

4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126

4127
4128
4129

4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144







-
+


















-
-
-
-
-

-
+









+






+
-
+


-
+






+







#endif

  while( zSql[0] && (SQLITE_OK == rc) ){
    static const char *zStmtSql;
    rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
    if( SQLITE_OK != rc ){
      if( pzErrMsg ){
        *pzErrMsg = save_err_msg(db);
        *pzErrMsg = save_err_msg(db, "in prepare", rc, zSql);
      }
    }else{
      if( !pStmt ){
        /* this happens for a comment or white-space */
        zSql = zLeftover;
        while( IsSpace(zSql[0]) ) zSql++;
        continue;
      }
      zStmtSql = sqlite3_sql(pStmt);
      if( zStmtSql==0 ) zStmtSql = "";
      while( IsSpace(zStmtSql[0]) ) zStmtSql++;

      /* save off the prepared statment handle and reset row count */
      if( pArg ){
        pArg->pStmt = pStmt;
        pArg->cnt = 0;
      }

      /* echo the sql statement if echo on */
      if( pArg && ShellHasFlag(pArg, SHFLG_Echo) ){
        utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
      }

      /* Show the EXPLAIN QUERY PLAN if .eqp is on */
      if( pArg && pArg->autoEQP && sqlite3_strlike("EXPLAIN%",zStmtSql,0)!=0 ){
      if( pArg && pArg->autoEQP && sqlite3_stmt_isexplain(pStmt)==0 ){
        sqlite3_stmt *pExplain;
        char *zEQP;
        int triggerEQP = 0;
        disable_debug_trace_modes();
        sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP);
        if( pArg->autoEQP>=AUTOEQP_trigger ){
          sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0);
        }
        zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zStmtSql);
        shell_check_oom(zEQP);
        rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
        if( rc==SQLITE_OK ){
          while( sqlite3_step(pExplain)==SQLITE_ROW ){
            const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
            int iEqpId = sqlite3_column_int(pExplain, 0);
            int iParentId = sqlite3_column_int(pExplain, 1);
            if( zEQPLine==0 ) zEQPLine = "";
            if( zEQPLine[0]=='-' ) eqp_render(pArg);
            if( zEQPLine[0]=='-' ) eqp_render(pArg, 0);
            eqp_append(pArg, iEqpId, iParentId, zEQPLine);
          }
          eqp_render(pArg);
          eqp_render(pArg, 0);
        }
        sqlite3_finalize(pExplain);
        sqlite3_free(zEQP);
        if( pArg->autoEQP>=AUTOEQP_full ){
          /* Also do an EXPLAIN for ".eqp full" mode */
          zEQP = sqlite3_mprintf("EXPLAIN %s", zStmtSql);
          shell_check_oom(zEQP);
          rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
          if( rc==SQLITE_OK ){
            pArg->cMode = MODE_Explain;
            explain_data_prepare(pArg, pExplain);
            exec_prepared_stmt(pArg, pExplain);
            explain_data_delete(pArg);
          }
3008
3009
3010
3011
3012
3013
3014
3015

3016
3017
3018
3019
3020

3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032

3033
3034
3035

3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056

3057
3058
3059
3060
3061
3062
3063
4154
4155
4156
4157
4158
4159
4160

4161


4162
4163

4164

4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178

4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199

4200
4201
4202
4203
4204
4205
4206
4207







-
+
-
-


-
+
-











+


-
+




















-
+







        }
        restore_debug_trace_modes();
      }

      if( pArg ){
        pArg->cMode = pArg->mode;
        if( pArg->autoExplain ){
          if( sqlite3_column_count(pStmt)==8
          if( sqlite3_stmt_isexplain(pStmt)==1 ){
           && sqlite3_strlike("EXPLAIN%", zStmtSql,0)==0
          ){
            pArg->cMode = MODE_Explain;
          }
          if( sqlite3_column_count(pStmt)==4
          if( sqlite3_stmt_isexplain(pStmt)==2 ){
           && sqlite3_strlike("EXPLAIN QUERY PLAN%", zStmtSql,0)==0 ){
            pArg->cMode = MODE_EQP;
          }
        }

        /* If the shell is currently in ".explain" mode, gather the extra
        ** data required to add indents to the output.*/
        if( pArg->cMode==MODE_Explain ){
          explain_data_prepare(pArg, pStmt);
        }
      }

      bind_prepared_stmt(pArg, pStmt);
      exec_prepared_stmt(pArg, pStmt);
      explain_data_delete(pArg);
      eqp_render(pArg);
      eqp_render(pArg, 0);

      /* print usage stats if stats on */
      if( pArg && pArg->statsOn ){
        display_stats(db, pArg, 0);
      }

      /* print loop-counters if required */
      if( pArg && pArg->scanstatsOn ){
        display_scanstats(db, pArg);
      }

      /* Finalize the statement just executed. If this fails, save a
      ** copy of the error message. Otherwise, set zSql to point to the
      ** next statement to execute. */
      rc2 = sqlite3_finalize(pStmt);
      if( rc!=SQLITE_NOMEM ) rc = rc2;
      if( rc==SQLITE_OK ){
        zSql = zLeftover;
        while( IsSpace(zSql[0]) ) zSql++;
      }else if( pzErrMsg ){
        *pzErrMsg = save_err_msg(db);
        *pzErrMsg = save_err_msg(db, "stepping", rc, 0);
      }

      /* clear saved stmt handle */
      if( pArg ){
        pArg->pStmt = NULL;
      }
    }
3099
3100
3101
3102
3103
3104
3105

3106
3107
3108
3109
3110
3111
3112
3113

3114
3115

3116
3117
3118
3119
3120
3121
3122
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257

4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268







+







-
+


+







  int nAlloc = 0;
  int nPK = 0;       /* Number of PRIMARY KEY columns seen */
  int isIPK = 0;     /* True if one PRIMARY KEY column of type INTEGER */
  int preserveRowid = ShellHasFlag(p, SHFLG_PreserveRowid);
  int rc;

  zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab);
  shell_check_oom(zSql);
  rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
  sqlite3_free(zSql);
  if( rc ) return 0;
  while( sqlite3_step(pStmt)==SQLITE_ROW ){
    if( nCol>=nAlloc-2 ){
      nAlloc = nAlloc*2 + nCol + 10;
      azCol = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0]));
      if( azCol==0 ) shell_out_of_memory();
      shell_check_oom(azCol);
    }
    azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
    shell_check_oom(azCol[nCol]);
    if( sqlite3_column_int(pStmt, 5) ){
      nPK++;
      if( nPK==1
       && sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2),
                          "INTEGER")==0
      ){
        isIPK = 1;
3142
3143
3144
3145
3146
3147
3148

3149
3150
3151
3152
3153
3154
3155
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302







+







    ** table or a INTEGER PRIMARY KEY DESC column, neither of which are
    ** ROWID aliases.  To distinguish these cases, check to see if
    ** there is a "pk" entry in "PRAGMA index_list".  There will be
    ** no "pk" index if the PRIMARY KEY really is an alias for the ROWID.
    */
    zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)"
                           " WHERE origin='pk'", zTab);
    shell_check_oom(zSql);
    rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
    sqlite3_free(zSql);
    if( rc ){
      freeColumnList(azCol);
      return 0;
    }
    rc = sqlite3_step(pStmt);
3204
3205
3206
3207
3208
3209
3210


3211
3212
3213
3214
3215
3216




3217
3218
3219
3220
3221
3222





3223


3224

3225
3226
3227
3228
3229
3230
3231

3232
3233

3234
3235
3236
3237
3238
3239
3240
3241

3242
3243
3244
3245
3246
3247
3248
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
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
4394
4395
4396

4397
4398
4399
4400
4401
4402
4403
4404







+
+






+
+
+
+

-
-
-
-
-
+
+
+
+
+

+
+
-
+






-
+


+







-
+







*/
static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
  int rc;
  const char *zTable;
  const char *zType;
  const char *zSql;
  ShellState *p = (ShellState *)pArg;
  int dataOnly;
  int noSys;

  UNUSED_PARAMETER(azNotUsed);
  if( nArg!=3 || azArg==0 ) return 0;
  zTable = azArg[0];
  zType = azArg[1];
  zSql = azArg[2];
  if( zTable==0 ) return 0;
  if( zType==0 ) return 0;
  dataOnly = (p->shellFlgs & SHFLG_DumpDataOnly)!=0;
  noSys    = (p->shellFlgs & SHFLG_DumpNoSys)!=0;

  if( strcmp(zTable, "sqlite_sequence")==0 ){
    raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
  }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){
    raw_printf(p->out, "ANALYZE sqlite_master;\n");
  }else if( strncmp(zTable, "sqlite_", 7)==0 ){
  if( cli_strcmp(zTable, "sqlite_sequence")==0 && !noSys ){
    if( !dataOnly ) raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
  }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){
    if( !dataOnly ) raw_printf(p->out, "ANALYZE sqlite_schema;\n");
  }else if( cli_strncmp(zTable, "sqlite_", 7)==0 ){
    return 0;
  }else if( dataOnly ){
    /* no-op */
  }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
  }else if( cli_strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
    char *zIns;
    if( !p->writableSchema ){
      raw_printf(p->out, "PRAGMA writable_schema=ON;\n");
      p->writableSchema = 1;
    }
    zIns = sqlite3_mprintf(
       "INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)"
       "INSERT INTO sqlite_schema(type,name,tbl_name,rootpage,sql)"
       "VALUES('table','%q','%q',0,'%q');",
       zTable, zTable, zSql);
    shell_check_oom(zIns);
    utf8_printf(p->out, "%s\n", zIns);
    sqlite3_free(zIns);
    return 0;
  }else{
    printSchemaLine(p->out, zSql, ";\n");
  }

  if( strcmp(zType, "table")==0 ){
  if( cli_strcmp(zType, "table")==0 ){
    ShellText sSelect;
    ShellText sTable;
    char **azCol;
    int i;
    char *savedDestTable;
    int savedMode;

3345
3346
3347
3348
3349
3350
3351
3352

3353
3354
3355
3356
3357
3358


3359
3360
3361
3362



3363
3364
3365
3366
3367
3368
3369




3370
3371
3372
3373
3374



3375
3376

3377
3378
3379
3380

3381

3382
3383


3384
3385

3386

3387

3388
3389


3390
3391

3392

3393

3394
3395

3396


3397


3398
3399
3400












3401

3402

3403
3404
3405




3406
3407
3408

3409














3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423

3424
3425

3426

3427

3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438

























3439

3440

3441
3442
3443
3444






3445
3446
3447

3448
3449
3450




3451
3452

3453
3454

3455
3456













3457







3458

3459
3460












3461
3462
3463



3464
3465
3466



3467
3468
3469
3470
3471
3472
3473
4501
4502
4503
4504
4505
4506
4507

4508
4509
4510
4511
4512
4513

4514
4515
4516
4517
4518

4519
4520
4521
4522
4523
4524
4525



4526
4527
4528
4529
4530
4531



4532
4533
4534
4535

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
4562

4563
4564

4565
4566
4567
4568

4569
4570
4571


4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585

4586



4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622

4623
4624
4625
4626
4627
4628

4629
4630










4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657

4658
4659



4660
4661
4662
4663
4664
4665
4666
4667
4668
4669



4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680

4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703


4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716


4717
4718
4719
4720


4721
4722
4723
4724
4725
4726
4727
4728
4729
4730







-
+





-
+
+



-
+
+
+




-
-
-
+
+
+
+


-
-
-
+
+
+

-
+




+

+

-
+
+


+

+

+


+
+


+

+
-
+

-
+

+
+
-
+
+

-
-
+
+
+
+
+
+
+
+
+
+
+
+

+
-
+
-
-
-
+
+
+
+



+

+
+
+
+
+
+
+
+
+
+
+
+
+
+













-
+


+

+
-
+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
-
+

-
-
-
+
+
+
+
+
+



+
-
-
-
+
+
+
+


+


+

-
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+

+
-
-
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+
+

-
-
+
+
+







  return rc;
}

/*
** Text of help messages.
**
** The help text for each individual command begins with a line that starts
** with ".".  Subsequent lines are supplimental information.
** with ".".  Subsequent lines are supplemental information.
**
** There must be two or more spaces between the end of the command and the
** start of the description of what that command does.
*/
static const char *(azHelp[]) = {
#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE) \
  && !defined(SQLITE_SHELL_FIDDLE)
  ".archive ...             Manage SQL archives",
  "   Each command must have exactly one of the following options:",
  "     -c, --create               Create a new archive",
  "     -u, --update               Update or add files to an existing archive",
  "     -u, --update               Add or update files with changed mtime",
  "     -i, --insert               Like -u but always add even if unchanged",
  "     -r, --remove               Remove files from archive",
  "     -t, --list                 List contents of archive",
  "     -x, --extract              Extract files from archive",
  "   Optional arguments:",
  "     -v, --verbose              Print each filename as it is processed",
  "     -f FILE, --file FILE       Operate on archive FILE (default is current db)",
  "     -a FILE, --append FILE     Operate on FILE opened using the apndvfs VFS",
  "     -C DIR, --directory DIR    Change to directory DIR to read/extract files",
  "     -f FILE, --file FILE       Use archive FILE (default is current db)",
  "     -a FILE, --append FILE     Open FILE using the apndvfs VFS",
  "     -C DIR, --directory DIR    Read/extract files from directory DIR",
  "     -g, --glob                 Use glob matching for names in archive",
  "     -n, --dryrun               Show the SQL that would have occurred",
  "   Examples:",
  "     .ar -cf archive.sar foo bar  # Create archive.sar from files foo and bar",
  "     .ar -tf archive.sar          # List members of archive.sar",
  "     .ar -xvf archive.sar         # Verbosely extract files from archive.sar",
  "     .ar -cf ARCHIVE foo bar  # Create ARCHIVE from files foo and bar",
  "     .ar -tf ARCHIVE          # List members of ARCHIVE",
  "     .ar -xvf ARCHIVE         # Verbosely extract files from ARCHIVE",
  "   See also:",
  "      http://sqlite.org/cli.html#sqlar_archive_support",
  "      http://sqlite.org/cli.html#sqlite_archive_support",
#endif
#ifndef SQLITE_OMIT_AUTHORIZATION
  ".auth ON|OFF             Show authorizer callbacks",
#endif
#ifndef SQLITE_SHELL_FIDDLE
  ".backup ?DB? FILE        Backup DB (default \"main\") to FILE",
  "   Options:",
  "       --append            Use the appendvfs",
  "       --async             Write to FILE without a journal and without fsync()",
  "       --async             Write to FILE without journal and fsync()",
#endif
  ".bail on|off             Stop after hitting an error.  Default OFF",
  ".binary on|off           Turn binary output on or off.  Default OFF",
#ifndef SQLITE_SHELL_FIDDLE
  ".cd DIRECTORY            Change the working directory to DIRECTORY",
#endif
  ".changes on|off          Show number of rows changed by SQL",
#ifndef SQLITE_SHELL_FIDDLE
  ".check GLOB              Fail if output since .testcase does not match",
  ".clone NEWDB             Clone data into NEWDB from the existing database",
#endif
  ".connection [close] [#]  Open or close an auxiliary database connection",
  ".databases               List names and files of attached databases",
  ".dbconfig ?op? ?val?     List or change sqlite3_db_config() options",
#if SQLITE_SHELL_HAVE_RECOVER
  ".dbinfo ?DB?             Show status information about the database",
#endif
  ".dump ?TABLE? ...        Render all database content as SQL",
  ".dump ?OBJECTS?          Render database content as SQL",
  "   Options:",
  "     --preserve-rowids      Include ROWID values in the output",
  "     --data-only            Output only INSERT statements",
  "     --newlines             Allow unescaped newline characters in output",
  "     --nosys                Omit system tables (ex: \"sqlite_stat1\")",
  "     --preserve-rowids      Include ROWID values in the output",
  "   TABLE is LIKE pattern for the tables to dump",
  "   OBJECTS is a LIKE pattern for tables, indexes, triggers or views to dump",
  "   Additional LIKE patterns can be given in subsequent arguments",
  ".echo on|off             Turn command echo on or off",
  ".eqp on|off|full         Enable or disable automatic EXPLAIN QUERY PLAN",
  ".excel                   Display the output of next command in a spreadsheet",
  ".eqp on|off|full|...     Enable or disable automatic EXPLAIN QUERY PLAN",
  "   Other Modes:",
#ifdef SQLITE_DEBUG
  "      test                  Show raw EXPLAIN QUERY PLAN output",
  "      trace                 Like \"full\" but enable \"PRAGMA vdbe_trace\"",
#endif
  "      trigger               Like \"full\" but also show trigger bytecode",
#ifndef SQLITE_SHELL_FIDDLE
  ".excel                   Display the output of next command in spreadsheet",
  "   --bom                   Put a UTF8 byte-order mark on intermediate file",
#endif
#ifndef SQLITE_SHELL_FIDDLE
  ".exit ?CODE?             Exit this program with return-code CODE",
#endif
  ".expert                  EXPERIMENTAL. Suggest indexes for specified queries",
  ".expert                  EXPERIMENTAL. Suggest indexes for queries",
/* Because explain mode comes on automatically now, the ".explain" mode
** is removed from the help screen.  It is still supported for legacy, however */
/*".explain ?on|off|auto?   Turn EXPLAIN output mode on or off or to automatic",*/
  ".explain ?on|off|auto?   Change the EXPLAIN formatting mode.  Default: auto",
  ".filectrl CMD ...        Run various sqlite3_file_control() operations",
  "   --schema SCHEMA         Use SCHEMA instead of \"main\"",
  "   --help                  Show CMD details",
  ".fullschema ?--indent?   Show schema and the content of sqlite_stat tables",
  ".headers on|off          Turn display of headers on or off",
  ".help ?-all? ?PATTERN?   Show help text for PATTERN",
#ifndef SQLITE_SHELL_FIDDLE
  ".import FILE TABLE       Import data from FILE into TABLE",
  "   Options:",
  "     --ascii               Use \\037 and \\036 as column and row separators",
  "     --csv                 Use , and \\n as column and row separators",
  "     --skip N              Skip the first N rows of input",
  "     --schema S            Target table to be S.TABLE",
  "     -v                    \"Verbose\" - increase auxiliary output",
  "   Notes:",
  "     *  If TABLE does not exist, it is created.  The first row of input",
  "        determines the column names.",
  "     *  If neither --csv or --ascii are used, the input mode is derived",
  "        from the \".mode\" output mode",
  "     *  If FILE begins with \"|\" then it is a command that generates the",
  "        input text.",
#endif
#ifndef SQLITE_OMIT_TEST_CONTROL
  ".imposter INDEX TABLE    Create imposter table TABLE on index INDEX",
#endif
  ".indexes ?TABLE?         Show names of indexes",
  "                           If TABLE is specified, only show indexes for",
  "                           tables matching TABLE using the LIKE operator.",
#ifdef SQLITE_ENABLE_IOTRACE
  ".iotrace FILE            Enable I/O diagnostic logging to FILE",
#endif
  ".limit ?LIMIT? ?VAL?     Display or change the value of an SQLITE_LIMIT",
  ".lint OPTIONS            Report potential schema issues.",
  "     Options:",
  "        fkey-indexes     Find missing foreign key indexes",
#ifndef SQLITE_OMIT_LOAD_EXTENSION
#if !defined(SQLITE_OMIT_LOAD_EXTENSION) && !defined(SQLITE_SHELL_FIDDLE)
  ".load FILE ?ENTRY?       Load an extension library",
#endif
#ifndef SQLITE_SHELL_FIDDLE
  ".log FILE|off            Turn logging on or off.  FILE can be stderr/stdout",
#endif
  ".mode MODE ?TABLE?       Set output mode",
  ".mode MODE ?OPTIONS?     Set output mode",
  "   MODE is one of:",
  "     ascii    Columns/rows delimited by 0x1F and 0x1E",
  "     csv      Comma-separated values",
  "     column   Left-aligned columns.  (See .width)",
  "     html     HTML <table> code",
  "     insert   SQL insert statements for TABLE",
  "     line     One value per line",
  "     list     Values delimited by \"|\"",
  "     quote    Escape answers as for SQL",
  "     tabs     Tab-separated values",
  "     tcl      TCL list elements",
  "     ascii       Columns/rows delimited by 0x1F and 0x1E",
  "     box         Tables using unicode box-drawing characters",
  "     csv         Comma-separated values",
  "     column      Output in columns.  (See .width)",
  "     html        HTML <table> code",
  "     insert      SQL insert statements for TABLE",
  "     json        Results in a JSON array",
  "     line        One value per line",
  "     list        Values delimited by \"|\"",
  "     markdown    Markdown table format",
  "     qbox        Shorthand for \"box --wrap 60 --quote\"",
  "     quote       Escape answers as for SQL",
  "     table       ASCII-art table",
  "     tabs        Tab-separated values",
  "     tcl         TCL list elements",
  "   OPTIONS: (for columnar modes or insert mode):",
  "     --wrap N       Wrap output lines to no longer than N characters",
  "     --wordwrap B   Wrap or not at word boundaries per B (on/off)",
  "     --ww           Shorthand for \"--wordwrap 1\"",
  "     --quote        Quote output text as SQL literals",
  "     --noquote      Do not quote output text",
  "     TABLE          The name of SQL table used for \"insert\" mode",
#ifndef SQLITE_SHELL_FIDDLE
  ".nonce STRING            Suspend safe mode for one command if nonce matches",
#endif
  ".nullvalue STRING        Use STRING in place of NULL values",
#ifndef SQLITE_SHELL_FIDDLE
  ".once (-e|-x|FILE)       Output for the next SQL command only to FILE",
  ".once ?OPTIONS? ?FILE?   Output for the next SQL command only to FILE",
  "     If FILE begins with '|' then open as a pipe",
  "     Other options:",
  "       -e    Invoke system text editor",
  "       -x    Open in a spreadsheet",
  "       --bom  Put a UTF8 byte-order mark at the beginning",
  "       -e     Send output to the system text editor",
  "       -x     Send output as CSV to a spreadsheet (same as \".excel\")",
  /* Note that .open is (partially) available in WASM builds but is
  ** currently only intended to be used by the fiddle tool, not
  ** end users, so is "undocumented." */
  ".open ?OPTIONS? ?FILE?   Close existing database and reopen FILE",
  "     Options:",
  "        --append        Use appendvfs to append database to the end of FILE",
#endif
#ifdef SQLITE_ENABLE_DESERIALIZE
  "        --deserialize   Load into memory useing sqlite3_deserialize()",
  "        --hexdb         Load the output of \"dbtotxt\" as an in-memory database",
#ifndef SQLITE_OMIT_DESERIALIZE
  "        --deserialize   Load into memory using sqlite3_deserialize()",
  "        --hexdb         Load the output of \"dbtotxt\" as an in-memory db",
  "        --maxsize N     Maximum size for --hexdb or --deserialized database",
#endif
  "        --new           Initialize FILE to an empty database",
  "        --nofollow      Do not follow symbolic links",
  "        --readonly      Open FILE readonly",
  "        --zip           FILE is a ZIP archive",
#ifndef SQLITE_SHELL_FIDDLE
  ".output ?FILE?           Send output to FILE or stdout if FILE is omitted",
  "     If FILE begins with '|' then open it as a pipe.",
  "   If FILE begins with '|' then open it as a pipe.",
  "   Options:",
  "     --bom                 Prefix output with a UTF8 byte-order mark",
  "     -e                    Send output to the system text editor",
  "     -x                    Send output as CSV to a spreadsheet",
#endif
  ".parameter CMD ...       Manage SQL parameter bindings",
  "   clear                   Erase all bindings",
  "   init                    Initialize the TEMP table that holds bindings",
  "   list                    List the current parameter bindings",
  "   set PARAMETER VALUE     Given SQL parameter PARAMETER a value of VALUE",
  "                           PARAMETER should start with one of: $ : @ ?",
  "   unset PARAMETER         Remove PARAMETER from the binding table",
  ".print STRING...         Print literal STRING",
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  ".progress N              Invoke progress handler after every N opcodes",
  "   --limit N                 Interrupt after N progress callbacks",
  "   --once                    Do no more than one progress interrupt",
  "   --quiet|-q                No output except at interrupts",
  "   --reset                   Reset the count for each input and interrupt",
#endif
  ".prompt MAIN CONTINUE    Replace the standard prompts",
#ifndef SQLITE_SHELL_FIDDLE
  ".quit                    Exit this program",
  ".read FILE               Read input from FILE",
  ".quit                    Stop interpreting input stream, exit if primary.",
  ".read FILE               Read input from FILE or command output",
  "    If FILE begins with \"|\", it is a command that generates the input.",
#endif
#if SQLITE_SHELL_HAVE_RECOVER
  ".recover                 Recover as much data as possible from corrupt db.",
  "   --ignore-freelist        Ignore pages that appear to be on db freelist",
  "   --lost-and-found TABLE   Alternative name for the lost-and-found table",
  "   --no-rowids              Do not attempt to recover rowid values",
  "                            that are not also INTEGER PRIMARY KEYs",
#endif
#ifndef SQLITE_SHELL_FIDDLE
  ".restore ?DB? FILE       Restore content of DB (default \"main\") from FILE",
  ".save FILE               Write in-memory database into FILE",
  ".scanstats on|off        Turn sqlite3_stmt_scanstatus() metrics on or off",
  ".save ?OPTIONS? FILE     Write database to FILE (an alias for .backup ...)",
#endif
  ".scanstats on|off|est    Turn sqlite3_stmt_scanstatus() metrics on or off",
  ".schema ?PATTERN?        Show the CREATE statements matching PATTERN",
  "     Options:",
  "         --indent            Try to pretty-print the schema",
  "   Options:",
  "      --indent             Try to pretty-print the schema",
  "      --nosys              Omit objects whose names start with \"sqlite_\"",
  ".selftest ?OPTIONS?      Run tests defined in the SELFTEST table",
  "    Options:",
  "       --init               Create a new SELFTEST table",
  "       -v                   Verbose output",
  ".separator COL ?ROW?     Change the column and row separators",
#if defined(SQLITE_ENABLE_SESSION)
  ".session ?NAME? CMD ...  Create or control sessions",
3482
3483
3484
3485
3486
3487
3488
3489

3490
3491

3492
3493
3494
3495

3496
3497
3498
3499
3500






3501
3502
3503

3504



3505
3506
3507
3508
3509
3510
3511
3512
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
4739
4740
4741
4742
4743
4744
4745

4746
4747

4748
4749
4750
4751

4752
4753
4754
4755


4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795

4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815


4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838







-
+

-
+



-
+



-
-
+
+
+
+
+
+



+

+
+
+


















+
+
+
+
+



-
+



















-
-
+
+
+












+







  "     list                     List currently open session names",
  "     open DB NAME             Open a new session on DB",
  "     patchset FILE            Write a patchset into FILE",
  "   If ?NAME? is omitted, the first defined session is used.",
#endif
  ".sha3sum ...             Compute a SHA3 hash of database content",
  "    Options:",
  "      --schema              Also hash the sqlite_master table",
  "      --schema              Also hash the sqlite_schema table",
  "      --sha3-224            Use the sha3-224 algorithm",
  "      --sha3-256            Use the sha3-256 algorithm.  This is the default.",
  "      --sha3-256            Use the sha3-256 algorithm (default)",
  "      --sha3-384            Use the sha3-384 algorithm",
  "      --sha3-512            Use the sha3-512 algorithm",
  "    Any other argument is a LIKE pattern for tables to hash",
#ifndef SQLITE_NOHAVE_SYSTEM
#if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE)
  ".shell CMD ARGS...       Run CMD ARGS... in a system shell",
#endif
  ".show                    Show the current values for various settings",
  ".stats ?on|off?          Show stats or turn stats on or off",
#ifndef SQLITE_NOHAVE_SYSTEM
  ".stats ?ARG?             Show stats or turn stats on or off",
  "   off                      Turn off automatic stat display",
  "   on                       Turn on automatic stat display",
  "   stmt                     Show statement stats",
  "   vmstep                   Show the virtual machine step count only",
#if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE)
  ".system CMD ARGS...      Run CMD ARGS... in a system shell",
#endif
  ".tables ?TABLE?          List names of tables matching LIKE pattern TABLE",
#ifndef SQLITE_SHELL_FIDDLE
  ".testcase NAME           Begin redirecting output to 'testcase-out.txt'",
#endif
  ".testctrl CMD ...        Run various sqlite3_test_control() operations",
  "                           Run \".testctrl\" with no arguments for details",
  ".timeout MS              Try opening locked tables for MS milliseconds",
  ".timer on|off            Turn SQL timer on or off",
#ifndef SQLITE_OMIT_TRACE
  ".trace ?OPTIONS?         Output each SQL statement as it is run",
  "    FILE                    Send output to FILE",
  "    stdout                  Send output to stdout",
  "    stderr                  Send output to stderr",
  "    off                     Disable tracing",
  "    --expanded              Expand query parameters",
#ifdef SQLITE_ENABLE_NORMALIZE
  "    --normalized            Normal the SQL statements",
#endif
  "    --plain                 Show SQL as it is input",
  "    --stmt                  Trace statement execution (SQLITE_TRACE_STMT)",
  "    --profile               Profile statements (SQLITE_TRACE_PROFILE)",
  "    --row                   Trace each row (SQLITE_TRACE_ROW)",
  "    --close                 Trace connection close (SQLITE_TRACE_CLOSE)",
#endif /* SQLITE_OMIT_TRACE */
#ifdef SQLITE_DEBUG
  ".unmodule NAME ...       Unregister virtual table modules",
  "    --allexcept             Unregister everything except those named",
#endif
  ".version                 Show source, library and compiler versions",
  ".vfsinfo ?AUX?           Information about the top-level VFS",
  ".vfslist                 List all available VFSes",
  ".vfsname ?AUX?           Print the name of the VFS stack",
  ".width NUM1 NUM2 ...     Set column widths for \"column\" mode",
  ".width NUM1 NUM2 ...     Set minimum column widths for columnar output",
  "     Negative values right-justify",
};

/*
** Output help text.
**
** zPattern describes the set of commands for which help text is provided.
** If zPattern is NULL, then show all commands, but only give a one-line
** description of each.
**
** Return the number of matches.
*/
static int showHelp(FILE *out, const char *zPattern){
  int i = 0;
  int j = 0;
  int n = 0;
  char *zPat;
  if( zPattern==0
   || zPattern[0]=='0'
   || strcmp(zPattern,"-a")==0
   || strcmp(zPattern,"-all")==0
   || cli_strcmp(zPattern,"-a")==0
   || cli_strcmp(zPattern,"-all")==0
   || cli_strcmp(zPattern,"--all")==0
  ){
    /* Show all commands, but only one line per command */
    if( zPattern==0 ) zPattern = "";
    for(i=0; i<ArraySize(azHelp); i++){
      if( azHelp[i][0]=='.' || zPattern[0] ){
        utf8_printf(out, "%s\n", azHelp[i]);
        n++;
      }
    }
  }else{
    /* Look for commands that for which zPattern is an exact prefix */
    zPat = sqlite3_mprintf(".%s*", zPattern);
    shell_check_oom(zPat);
    for(i=0; i<ArraySize(azHelp); i++){
      if( sqlite3_strglob(zPat, azHelp[i])==0 ){
        utf8_printf(out, "%s\n", azHelp[i]);
        j = i+1;
        n++;
      }
    }
3575
3576
3577
3578
3579
3580
3581

3582
3583
3584
3585
3586
3587
3588
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861







+







        }
      }
      return n;
    }
    /* Look for commands that contain zPattern anywhere.  Show the complete
    ** text of all commands that match. */
    zPat = sqlite3_mprintf("%%%s%%", zPattern);
    shell_check_oom(zPat);
    for(i=0; i<ArraySize(azHelp); i++){
      if( azHelp[i][0]=='.' ) j = i;
      if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){
        utf8_printf(out, "%s\n", azHelp[j]);
        while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]!='.' ){
          j++;
          utf8_printf(out, "%s\n", azHelp[j]);
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663





3664
3665

3666
3667
3668

3669
3670
3671
3672
3673
3674
3675
4926
4927
4928
4929
4930
4931
4932




4933
4934
4935
4936
4937
4938

4939
4940
4941

4942
4943
4944
4945
4946
4947
4948
4949







-
-
-
-
+
+
+
+
+

-
+


-
+







}
#endif

/*
** Close all OpenSession objects and release all associated resources.
*/
#if defined(SQLITE_ENABLE_SESSION)
static void session_close_all(ShellState *p){
  int i;
  for(i=0; i<p->nSession; i++){
    session_close(&p->aSession[i]);
static void session_close_all(ShellState *p, int i){
  int j;
  struct AuxDb *pAuxDb = i<0 ? p->pAuxDb : &p->aAuxDb[i];
  for(j=0; j<pAuxDb->nSession; j++){
    session_close(&pAuxDb->aSession[j]);
  }
  p->nSession = 0;
  pAuxDb->nSession = 0;
}
#else
# define session_close_all(X)
# define session_close_all(X,Y)
#endif

/*
** Implementation of the xFilter function for an open session.  Omit
** any tables named by ".session filter" but let all other table through.
*/
#if defined(SQLITE_ENABLE_SESSION)
3720
3721
3722
3723
3724
3725
3726
3727

3728
3729
3730

3731
3732
3733
3734


3735
3736
3737
3738
3739
3740
3741
3742
3743
3744

3745

3746
3747
3748


3749
3750

3751
3752
3753
3754
3755
3756

3757
3758
3759
3760
3761
3762
3763
3764




3765
3766
3767

3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780

3781
3782
3783

3784
3785
3786
3787
3788
3789
3790



3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803

3804
3805
3806
3807
3808

3809
3810
3811
3812
3813
3814
3815
3816

























































































































































3817
3818
3819
3820
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
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

3899
3900
3901


3902
3903
3904
3905

3906
3907
3908
3909
3910
3911
3912

3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
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
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
4000
4001
4002
4003
4004
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
5024

5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038


5039
5040
5041
5042



5043

5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054

5055
5056
5057

5058

5059
5060
5061
5062


5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077

5078
5079
5080
5081
5082

5083
5084
5085
5086
5087
5088
5089
5090

5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265

5266
5267
5268

5269
5270
5271
5272
5273
5274


5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288

5289
5290
5291
5292
5293
5294

5295
5296
5297
5298
5299
5300
5301
5302


5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313

5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330


5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385

5386
5387
5388
5389
5390

5391
5392
5393
5394
5395
5396
5397

5398
5399
5400
5401

5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429

5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449

5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470


5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492

5493
5494
5495
5496
5497
5498
5499
5500







-
+


-
+


-
-
+
+










+
-
+

-
-
+
+

-
+






+






-
-
+
+
+
+
-
-
-
+
-











-
+


-
+
-




-
-
+
+
+












-
+




-
+







-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




















+

-
+


-
+





-
-
+
+












-
+
+




-
+
+






-
-
+
+
+
+
+


+



-

+
+
+
+
+
+
+
+
+

+
+
+
+

+
-
-
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






+
+
+
+
+
+
+
+






+


-
+
+



-
+






-
+



-









+
+
+



+
+
+










-
+














+




-
+
+








+
+









-
-
+
+













+






-
+







       && zBuf[3]==0x06 ){
      rc = SHELL_OPEN_ZIPFILE;
    }else if( n==0 && dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
      rc = SHELL_OPEN_ZIPFILE;
    }
  }
  fclose(f);
  return rc;  
  return rc;
}

#ifdef SQLITE_ENABLE_DESERIALIZE
#ifndef SQLITE_OMIT_DESERIALIZE
/*
** Reconstruct an in-memory database using the output from the "dbtotxt"
** program.  Read content from the file in p->zDbFilename.  If p->zDbFilename
** is 0, then read from standard input.
** program.  Read content from the file in p->aAuxDb[].zDbFilename.
** If p->aAuxDb[].zDbFilename is 0, then read from standard input.
*/
static unsigned char *readHexDb(ShellState *p, int *pnData){
  unsigned char *a = 0;
  int nLine;
  int n = 0;
  int pgsz = 0;
  int iOffset = 0;
  int j, k;
  int rc;
  FILE *in;
  const char *zDbFilename = p->pAuxDb->zDbFilename;
  unsigned char x[16];
  unsigned int x[16];
  char zLine[1000];
  if( p->zDbFilename ){
    in = fopen(p->zDbFilename, "r");
  if( zDbFilename ){
    in = fopen(zDbFilename, "r");
    if( in==0 ){
      utf8_printf(stderr, "cannot open \"%s\" for reading\n", p->zDbFilename);
      utf8_printf(stderr, "cannot open \"%s\" for reading\n", zDbFilename);
      return 0;
    }
    nLine = 0;
  }else{
    in = p->in;
    nLine = p->lineno;
    if( in==0 ) in = stdin;
  }
  *pnData = 0;
  nLine++;
  if( fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error;
  rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz);
  if( rc!=2 ) goto readHexDb_error;
  if( n<=0 ) goto readHexDb_error;
  a = sqlite3_malloc( n );
  if( n<0 ) goto readHexDb_error;
  if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ) goto readHexDb_error;
  n = (n+pgsz-1)&~(pgsz-1);  /* Round n up to the next multiple of pgsz */
  a = sqlite3_malloc( n ? n : 1 );
  if( a==0 ){
    utf8_printf(stderr, "Out of memory!\n");
    goto readHexDb_error;
  shell_check_oom(a);
  }
  memset(a, 0, n);
  if( pgsz<512 || pgsz>65536 || (pgsz & (pgsz-1))!=0 ){
    utf8_printf(stderr, "invalid pagesize\n");
    goto readHexDb_error;
  }
  for(nLine++; fgets(zLine, sizeof(zLine), in)!=0; nLine++){
    rc = sscanf(zLine, "| page %d offset %d", &j, &k);
    if( rc==2 ){
      iOffset = k;
      continue;
    }
    if( strncmp(zLine, "| end ", 6)==0 ){
    if( cli_strncmp(zLine, "| end ", 6)==0 ){
      break;
    }
    rc = sscanf(zLine,"| %d: %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx"
    rc = sscanf(zLine,"| %d: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
                      "  %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx",
                &j, &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
                &x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], &x[15]);
    if( rc==17 ){
      k = iOffset+j;
      if( k+16<=n ){
        memcpy(a+k, x, 16);
      if( k+16<=n && k>=0 ){
        int ii;
        for(ii=0; ii<16; ii++) a[k+ii] = x[ii]&0xff;
      }
    }
  }
  *pnData = n;
  if( in!=p->in ){
    fclose(in);
  }else{
    p->lineno = nLine;
  }
  return a;

readHexDb_error:
  if( in!=stdin ){
  if( in!=p->in ){
    fclose(in);
  }else{
    while( fgets(zLine, sizeof(zLine), p->in)!=0 ){
      nLine++;
      if(strncmp(zLine, "| end ", 6)==0 ) break;
      if(cli_strncmp(zLine, "| end ", 6)==0 ) break;
    }
    p->lineno = nLine;
  }
  sqlite3_free(a);
  utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine);
  return 0;
}
#endif /* SQLITE_ENABLE_DESERIALIZE */
#endif /* SQLITE_OMIT_DESERIALIZE */

/*
** Scalar function "shell_int32". The first argument to this function
** must be a blob. The second a non-negative integer. This function
** reads and returns a 32-bit big-endian integer from byte
** offset (4*<arg2>) of the blob.
*/
static void shellInt32(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const unsigned char *pBlob;
  int nBlob;
  int iInt;

  UNUSED_PARAMETER(argc);
  nBlob = sqlite3_value_bytes(argv[0]);
  pBlob = (const unsigned char*)sqlite3_value_blob(argv[0]);
  iInt = sqlite3_value_int(argv[1]);

  if( iInt>=0 && (iInt+1)*4<=nBlob ){
    const unsigned char *a = &pBlob[iInt*4];
    sqlite3_int64 iVal = ((sqlite3_int64)a[0]<<24)
                       + ((sqlite3_int64)a[1]<<16)
                       + ((sqlite3_int64)a[2]<< 8)
                       + ((sqlite3_int64)a[3]<< 0);
    sqlite3_result_int64(context, iVal);
  }
}

/*
** Scalar function "shell_idquote(X)" returns string X quoted as an identifier,
** using "..." with internal double-quote characters doubled.
*/
static void shellIdQuote(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const char *zName = (const char*)sqlite3_value_text(argv[0]);
  UNUSED_PARAMETER(argc);
  if( zName ){
    char *z = sqlite3_mprintf("\"%w\"", zName);
    sqlite3_result_text(context, z, -1, sqlite3_free);
  }
}

/*
** Scalar function "usleep(X)" invokes sqlite3_sleep(X) and returns X.
*/
static void shellUSleepFunc(
  sqlite3_context *context,
  int argcUnused,
  sqlite3_value **argv
){
  int sleep = sqlite3_value_int(argv[0]);
  (void)argcUnused;
  sqlite3_sleep(sleep/1000);
  sqlite3_result_int(context, sleep);
}

/*
** Scalar function "shell_escape_crnl" used by the .recover command.
** The argument passed to this function is the output of built-in
** function quote(). If the first character of the input is "'",
** indicating that the value passed to quote() was a text value,
** then this function searches the input for "\n" and "\r" characters
** and adds a wrapper similar to the following:
**
**   replace(replace(<input>, '\n', char(10), '\r', char(13));
**
** Or, if the first character of the input is not "'", then a copy
** of the input is returned.
*/
static void shellEscapeCrnl(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const char *zText = (const char*)sqlite3_value_text(argv[0]);
  UNUSED_PARAMETER(argc);
  if( zText && zText[0]=='\'' ){
    i64 nText = sqlite3_value_bytes(argv[0]);
    i64 i;
    char zBuf1[20];
    char zBuf2[20];
    const char *zNL = 0;
    const char *zCR = 0;
    i64 nCR = 0;
    i64 nNL = 0;

    for(i=0; zText[i]; i++){
      if( zNL==0 && zText[i]=='\n' ){
        zNL = unused_string(zText, "\\n", "\\012", zBuf1);
        nNL = strlen(zNL);
      }
      if( zCR==0 && zText[i]=='\r' ){
        zCR = unused_string(zText, "\\r", "\\015", zBuf2);
        nCR = strlen(zCR);
      }
    }

    if( zNL || zCR ){
      i64 iOut = 0;
      i64 nMax = (nNL > nCR) ? nNL : nCR;
      i64 nAlloc = nMax * nText + (nMax+64)*2;
      char *zOut = (char*)sqlite3_malloc64(nAlloc);
      if( zOut==0 ){
        sqlite3_result_error_nomem(context);
        return;
      }

      if( zNL && zCR ){
        memcpy(&zOut[iOut], "replace(replace(", 16);
        iOut += 16;
      }else{
        memcpy(&zOut[iOut], "replace(", 8);
        iOut += 8;
      }
      for(i=0; zText[i]; i++){
        if( zText[i]=='\n' ){
          memcpy(&zOut[iOut], zNL, nNL);
          iOut += nNL;
        }else if( zText[i]=='\r' ){
          memcpy(&zOut[iOut], zCR, nCR);
          iOut += nCR;
        }else{
          zOut[iOut] = zText[i];
          iOut++;
        }
      }

      if( zNL ){
        memcpy(&zOut[iOut], ",'", 2); iOut += 2;
        memcpy(&zOut[iOut], zNL, nNL); iOut += nNL;
        memcpy(&zOut[iOut], "', char(10))", 12); iOut += 12;
      }
      if( zCR ){
        memcpy(&zOut[iOut], ",'", 2); iOut += 2;
        memcpy(&zOut[iOut], zCR, nCR); iOut += nCR;
        memcpy(&zOut[iOut], "', char(13))", 12); iOut += 12;
      }

      sqlite3_result_text(context, zOut, iOut, SQLITE_TRANSIENT);
      sqlite3_free(zOut);
      return;
    }
  }

  sqlite3_result_value(context, argv[0]);
}

/* Flags for open_db().
**
** The default behavior of open_db() is to exit(1) if the database fails to
** open.  The OPEN_DB_KEEPALIVE flag changes that so that it prints an error
** but still returns without calling exit.
**
** The OPEN_DB_ZIPFILE flag causes open_db() to prefer to open files as a
** ZIP archive if the file does not exist or is empty and its name matches
** the *.zip pattern.
*/
#define OPEN_DB_KEEPALIVE   0x001   /* Return after error if true */
#define OPEN_DB_ZIPFILE     0x002   /* Open as ZIP if name matches *.zip */

/*
** Make sure the database is open.  If it is not, then open it.  If
** the database fails to open, print an error message and exit.
*/
static void open_db(ShellState *p, int openFlags){
  if( p->db==0 ){
    const char *zDbFilename = p->pAuxDb->zDbFilename;
    if( p->openMode==SHELL_OPEN_UNSPEC ){
      if( p->zDbFilename==0 || p->zDbFilename[0]==0 ){
      if( zDbFilename==0 || zDbFilename[0]==0 ){
        p->openMode = SHELL_OPEN_NORMAL;
      }else{
        p->openMode = (u8)deduceDatabaseType(p->zDbFilename, 
        p->openMode = (u8)deduceDatabaseType(zDbFilename,
                             (openFlags & OPEN_DB_ZIPFILE)!=0);
      }
    }
    switch( p->openMode ){
      case SHELL_OPEN_APPENDVFS: {
        sqlite3_open_v2(p->zDbFilename, &p->db, 
           SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, "apndvfs");
        sqlite3_open_v2(zDbFilename, &p->db,
           SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, "apndvfs");
        break;
      }
      case SHELL_OPEN_HEXDB:
      case SHELL_OPEN_DESERIALIZE: {
        sqlite3_open(0, &p->db);
        break;
      }
      case SHELL_OPEN_ZIPFILE: {
        sqlite3_open(":memory:", &p->db);
        break;
      }
      case SHELL_OPEN_READONLY: {
        sqlite3_open_v2(p->zDbFilename, &p->db, SQLITE_OPEN_READONLY, 0);
        sqlite3_open_v2(zDbFilename, &p->db,
            SQLITE_OPEN_READONLY|p->openFlags, 0);
        break;
      }
      case SHELL_OPEN_UNSPEC:
      case SHELL_OPEN_NORMAL: {
        sqlite3_open(p->zDbFilename, &p->db);
        sqlite3_open_v2(zDbFilename, &p->db,
           SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, 0);
        break;
      }
    }
    globalDb = p->db;
    if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
      utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
          p->zDbFilename, sqlite3_errmsg(p->db));
      if( openFlags & OPEN_DB_KEEPALIVE ) return;
          zDbFilename, sqlite3_errmsg(p->db));
      if( openFlags & OPEN_DB_KEEPALIVE ){
        sqlite3_open(":memory:", &p->db);
        return;
      }
      exit(1);
    }

#ifndef SQLITE_OMIT_LOAD_EXTENSION
    sqlite3_enable_load_extension(p->db, 1);
#endif
    sqlite3_fileio_init(p->db, 0, 0);
    sqlite3_shathree_init(p->db, 0, 0);
    sqlite3_uint_init(p->db, 0, 0);
    sqlite3_decimal_init(p->db, 0, 0);
    sqlite3_base64_init(p->db, 0, 0);
    sqlite3_base85_init(p->db, 0, 0);
    sqlite3_regexp_init(p->db, 0, 0);
    sqlite3_ieee_init(p->db, 0, 0);
    sqlite3_series_init(p->db, 0, 0);
#ifndef SQLITE_SHELL_FIDDLE
    sqlite3_fileio_init(p->db, 0, 0);
    sqlite3_completion_init(p->db, 0, 0);
#endif
#if SQLITE_SHELL_HAVE_RECOVER
    sqlite3_dbdata_init(p->db, 0, 0);
#endif
#ifdef SQLITE_HAVE_ZLIB
    if( !p->bSafeModePersist ){
    sqlite3_zipfile_init(p->db, 0, 0);
    sqlite3_sqlar_init(p->db, 0, 0);
      sqlite3_zipfile_init(p->db, 0, 0);
      sqlite3_sqlar_init(p->db, 0, 0);
    }
#endif
#ifdef SQLITE_SHELL_EXTFUNCS
    /* Create a preprocessing mechanism for extensions to make
     * their own provisions for being built into the shell.
     * This is a short-span macro. See further below for usage.
     */
#define SHELL_SUB_MACRO(base, variant) base ## _ ## variant
#define SHELL_SUBMACRO(base, variant) SHELL_SUB_MACRO(base, variant)
    /* Let custom-included extensions get their ..._init() called.
     * The WHATEVER_INIT( db, pzErrorMsg, pApi ) macro should cause
     * the extension's sqlite3_*_init( db, pzErrorMsg, pApi )
     * inititialization routine to be called.
     */
    {
      int irc = SHELL_SUBMACRO(SQLITE_SHELL_EXTFUNCS, INIT)(p->db);
    /* Let custom-included extensions expose their functionality.
     * The WHATEVER_EXPOSE( db, pzErrorMsg ) macro should cause
     * the SQL functions, virtual tables, collating sequences or
     * VFS's implemented by the extension to be registered.
     */
      if( irc==SQLITE_OK
          || irc==SQLITE_OK_LOAD_PERMANENTLY ){
        SHELL_SUBMACRO(SQLITE_SHELL_EXTFUNCS, EXPOSE)(p->db, 0);
      }
#undef SHELL_SUB_MACRO
#undef SHELL_SUBMACRO
    }
#endif

    sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0,
                            shellAddSchemaName, 0, 0);
    sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0,
                            shellModuleSchema, 0, 0);
    sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p,
                            shellPutsFunc, 0, 0);
    sqlite3_create_function(p->db, "shell_escape_crnl", 1, SQLITE_UTF8, 0,
                            shellEscapeCrnl, 0, 0);
    sqlite3_create_function(p->db, "shell_int32", 2, SQLITE_UTF8, 0,
                            shellInt32, 0, 0);
    sqlite3_create_function(p->db, "shell_idquote", 1, SQLITE_UTF8, 0,
                            shellIdQuote, 0, 0);
    sqlite3_create_function(p->db, "usleep",1,SQLITE_UTF8,0,
                            shellUSleepFunc, 0, 0);
#ifndef SQLITE_NOHAVE_SYSTEM
    sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,
                            editFunc, 0, 0);
    sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0,
                            editFunc, 0, 0);
#endif

    if( p->openMode==SHELL_OPEN_ZIPFILE ){
      char *zSql = sqlite3_mprintf(
         "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", p->zDbFilename);
         "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", zDbFilename);
      shell_check_oom(zSql);
      sqlite3_exec(p->db, zSql, 0, 0, 0);
      sqlite3_free(zSql);
    }
#ifdef SQLITE_ENABLE_DESERIALIZE
#ifndef SQLITE_OMIT_DESERIALIZE
    else
    if( p->openMode==SHELL_OPEN_DESERIALIZE || p->openMode==SHELL_OPEN_HEXDB ){
      int rc;
      int nData = 0;
      unsigned char *aData;
      if( p->openMode==SHELL_OPEN_DESERIALIZE ){
        aData = (unsigned char*)readFile(p->zDbFilename, &nData);
        aData = (unsigned char*)readFile(zDbFilename, &nData);
      }else{
        aData = readHexDb(p, &nData);
        if( aData==0 ){
          utf8_printf(stderr, "Error in hexdb input\n");
          return;
        }
      }
      rc = sqlite3_deserialize(p->db, "main", aData, nData, nData,
                   SQLITE_DESERIALIZE_RESIZEABLE |
                   SQLITE_DESERIALIZE_FREEONCLOSE);
      if( rc ){
        utf8_printf(stderr, "Error: sqlite3_deserialize() returns %d\n", rc);
      }
      if( p->szMax>0 ){
        sqlite3_file_control(p->db, "main", SQLITE_FCNTL_SIZE_LIMIT, &p->szMax);
      }
    }
#endif
  }
  if( p->bSafeModePersist && p->db!=0 ){
    sqlite3_set_authorizer(p->db, safeModeAuth, p);
  }
}

/*
** Attempt to close the databaes connection.  Report errors.
*/
void close_db(sqlite3 *db){
  int rc = sqlite3_close(db);
  if( rc ){
    utf8_printf(stderr, "Error: sqlite3_close() returns %d: %s\n",
        rc, sqlite3_errmsg(db));
  } 
  }
}

#if HAVE_READLINE || HAVE_EDITLINE
/*
** Readline completion callbacks
*/
static char *readline_completion_generator(const char *text, int state){
  static sqlite3_stmt *pStmt = 0;
  char *zRet;
  if( state==0 ){
    char *zSql;
    sqlite3_finalize(pStmt);
    zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
                           "  FROM completion(%Q) ORDER BY 1", text);
    shell_check_oom(zSql);
    sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
    sqlite3_free(zSql);
  }
  if( sqlite3_step(pStmt)==SQLITE_ROW ){
    zRet = strdup((const char*)sqlite3_column_text(pStmt, 0));
    const char *z = (const char*)sqlite3_column_text(pStmt,0);
    zRet = z ? strdup(z) : 0;
  }else{
    sqlite3_finalize(pStmt);
    pStmt = 0;
    zRet = 0;
  }
  return zRet;
}
static char **readline_completion(const char *zText, int iStart, int iEnd){
  (void)iStart;
  (void)iEnd;
  rl_attempted_completion_over = 1;
  return rl_completion_matches(zText, readline_completion_generator);
}

#elif HAVE_LINENOISE
/*
** Linenoise completion callback
*/
static void linenoise_completion(const char *zLine, linenoiseCompletions *lc){
  int nLine = strlen30(zLine);
  int i, iStart;
  i64 nLine = strlen(zLine);
  i64 i, iStart;
  sqlite3_stmt *pStmt = 0;
  char *zSql;
  char zBuf[1000];

  if( nLine>sizeof(zBuf)-30 ) return;
  if( zLine[0]=='.' || zLine[0]=='#') return;
  for(i=nLine-1; i>=0 && (isalnum(zLine[i]) || zLine[i]=='_'); i--){}
  if( i==nLine-1 ) return;
  iStart = i+1;
  memcpy(zBuf, zLine, iStart);
  zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
                         "  FROM completion(%Q,%Q) ORDER BY 1",
                         &zLine[iStart], zLine);
  shell_check_oom(zSql);
  sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
  sqlite3_free(zSql);
  sqlite3_exec(globalDb, "PRAGMA page_count", 0, 0, 0); /* Load the schema */
  while( sqlite3_step(pStmt)==SQLITE_ROW ){
    const char *zCompletion = (const char*)sqlite3_column_text(pStmt, 0);
    int nCompletion = sqlite3_column_bytes(pStmt, 0);
    if( iStart+nCompletion < sizeof(zBuf)-1 ){
    if( iStart+nCompletion < sizeof(zBuf)-1 && zCompletion ){
      memcpy(zBuf+iStart, zCompletion, nCompletion+1);
      linenoiseAddCompletion(lc, zBuf);
    }
  }
  sqlite3_finalize(pStmt);
}
#endif
4107
4108
4109
4110
4111
4112
4113
4114

4115
4116

4117
4118

4119
4120
4121
4122
4123
4124
4125
5603
5604
5605
5606
5607
5608
5609

5610
5611

5612
5613

5614
5615
5616
5617
5618
5619
5620
5621







-
+

-
+

-
+







/*
** Try to open an output file.   The names "stdout" and "stderr" are
** recognized and do the right thing.  NULL is returned if the output
** filename is "off".
*/
static FILE *output_file_open(const char *zFile, int bTextMode){
  FILE *f;
  if( strcmp(zFile,"stdout")==0 ){
  if( cli_strcmp(zFile,"stdout")==0 ){
    f = stdout;
  }else if( strcmp(zFile, "stderr")==0 ){
  }else if( cli_strcmp(zFile, "stderr")==0 ){
    f = stderr;
  }else if( strcmp(zFile, "off")==0 ){
  }else if( cli_strcmp(zFile, "off")==0 ){
    f = 0;
  }else{
    f = fopen(zFile, bTextMode ? "w" : "wb");
    if( f==0 ){
      utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
    }
  }
4135
4136
4137
4138
4139
4140
4141
4142

4143
4144
4145
4146
4147
4148
4149
5631
5632
5633
5634
5635
5636
5637

5638
5639
5640
5641
5642
5643
5644
5645







-
+







  void *pArg,             /* The ShellState pointer */
  void *pP,               /* Usually a pointer to sqlite_stmt */
  void *pX                /* Auxiliary output */
){
  ShellState *p = (ShellState*)pArg;
  sqlite3_stmt *pStmt;
  const char *zSql;
  int nSql;
  i64 nSql;
  if( p->traceOut==0 ) return 0;
  if( mType==SQLITE_TRACE_CLOSE ){
    utf8_printf(p->traceOut, "-- closing database connection\n");
    return 0;
  }
  if( mType!=SQLITE_TRACE_ROW && ((const char*)pX)[0]=='-' ){
    zSql = (const char*)pX;
4163
4164
4165
4166
4167
4168
4169
4170


4171
4172
4173
4174
4175

4176
4177
4178
4179
4180

4181
4182
4183
4184
4185
4186
4187
5659
5660
5661
5662
5663
5664
5665

5666
5667
5668
5669
5670
5671

5672
5673
5674
5675
5676

5677
5678
5679
5680
5681
5682
5683
5684







-
+
+




-
+




-
+







      default: {
        zSql = sqlite3_sql(pStmt);
        break;
      }
    }
  }
  if( zSql==0 ) return 0;
  nSql = strlen30(zSql);
  nSql = strlen(zSql);
  if( nSql>1000000000 ) nSql = 1000000000;
  while( nSql>0 && zSql[nSql-1]==';' ){ nSql--; }
  switch( mType ){
    case SQLITE_TRACE_ROW:
    case SQLITE_TRACE_STMT: {
      utf8_printf(p->traceOut, "%.*s;\n", nSql, zSql);
      utf8_printf(p->traceOut, "%.*s;\n", (int)nSql, zSql);
      break;
    }
    case SQLITE_TRACE_PROFILE: {
      sqlite3_int64 nNanosec = *(sqlite3_int64*)pX;
      utf8_printf(p->traceOut, "%.*s; -- %lld ns\n", nSql, zSql, nNanosec);
      utf8_printf(p->traceOut, "%.*s; -- %lld ns\n", (int)nSql, zSql, nNanosec);
      break;
    }
  }
  return 0;
}
#endif

4197
4198
4199
4200
4201
4202
4203

4204
4205
4206
4207


4208
4209
4210
4211
4212










4213
4214
4215
4216
4217
4218
4219

4220
4221
4222
4223
4224
4225
4226
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728

5729
5730
5731
5732
5733
5734
5735
5736







+




+
+





+
+
+
+
+
+
+
+
+
+






-
+







/*
** An object used to read a CSV and other files for import.
*/
typedef struct ImportCtx ImportCtx;
struct ImportCtx {
  const char *zFile;  /* Name of the input file */
  FILE *in;           /* Read the CSV text from this input stream */
  int (SQLITE_CDECL *xCloser)(FILE*);      /* Func to close in */
  char *z;            /* Accumulated text for a field */
  int n;              /* Number of bytes in z */
  int nAlloc;         /* Space allocated for z[] */
  int nLine;          /* Current line number */
  int nRow;           /* Number of rows imported */
  int nErr;           /* Number of errors encountered */
  int bNotFirst;      /* True if one or more bytes already read */
  int cTerm;          /* Character that terminated the most recent field */
  int cColSep;        /* The column separator character.  (Usually ",") */
  int cRowSep;        /* The row separator character.  (Usually "\n") */
};

/* Clean up resourced used by an ImportCtx */
static void import_cleanup(ImportCtx *p){
  if( p->in!=0 && p->xCloser!=0 ){
    p->xCloser(p->in);
    p->in = 0;
  }
  sqlite3_free(p->z);
  p->z = 0;
}

/* Append a single byte to z[] */
static void import_append_char(ImportCtx *p, int c){
  if( p->n+1>=p->nAlloc ){
    p->nAlloc += p->nAlloc + 100;
    p->z = sqlite3_realloc64(p->z, p->nAlloc);
    if( p->z==0 ) shell_out_of_memory();
    shell_check_oom(p->z);
  }
  p->z[p->n++] = (char)c;
}

/* Read a single field of CSV text.  Compatible with rfc4180 and extended
** with the option of having a separator other than ",".
**
4364
4365
4366
4367
4368
4369
4370

4371
4372
4373
4374
4375
4376
4377
4378
4379
4380

4381
4382
4383
4384
4385
4386
4387
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890

5891
5892
5893
5894
5895
5896
5897
5898







+









-
+







  int i, j, n;
  int nTable = strlen30(zTable);
  int k = 0;
  int cnt = 0;
  const int spinRate = 10000;

  zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
  shell_check_oom(zQuery);
  rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
  if( rc ){
    utf8_printf(stderr, "Error %d: %s on [%s]\n",
            sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
            zQuery);
    goto end_data_xfer;
  }
  n = sqlite3_column_count(pQuery);
  zInsert = sqlite3_malloc64(200 + nTable + n*3);
  if( zInsert==0 ) shell_out_of_memory();
  shell_check_oom(zInsert);
  sqlite3_snprintf(200+nTable,zInsert,
                   "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable);
  i = strlen30(zInsert);
  for(j=1; j<n; j++){
    memcpy(zInsert+i, ",?", 2);
    i += 2;
  }
4436
4437
4438
4439
4440
4441
4442

4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462

4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478



4479
4480
4481
4482
4483
4484
4485
4486
4487
4488


4489
4490
4491
4492
4493
4494







4495
4496
4497
4498
4499
4500
4501
4502
4503
4504

4505

4506
4507
4508
4509
4510
4511
4512
4513

4514
4515


4516
4517
4518
4519
4520
4521
4522
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973

5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988


5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003






6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019

6020
6021
6022
6023
6024
6025
6026
6027
6028
6029

6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041







+



















-
+














-
-
+
+
+










+
+
-
-
-
-
-
-
+
+
+
+
+
+
+









-
+

+







-
+


+
+







      }
    } /* End while */
    if( rc==SQLITE_DONE ) break;
    sqlite3_finalize(pQuery);
    sqlite3_free(zQuery);
    zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;",
                             zTable);
    shell_check_oom(zQuery);
    rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
    if( rc ){
      utf8_printf(stderr, "Warning: cannot step \"%s\" backwards", zTable);
      break;
    }
  } /* End for(k=0...) */

end_data_xfer:
  sqlite3_finalize(pQuery);
  sqlite3_finalize(pInsert);
  sqlite3_free(zQuery);
  sqlite3_free(zInsert);
}


/*
** Try to transfer all rows of the schema that match zWhere.  For
** each row, invoke xForEach() on the object defined by that row.
** If an error is encountered while moving forward through the
** sqlite_master table, try again moving backwards.
** sqlite_schema table, try again moving backwards.
*/
static void tryToCloneSchema(
  ShellState *p,
  sqlite3 *newDb,
  const char *zWhere,
  void (*xForEach)(ShellState*,sqlite3*,const char*)
){
  sqlite3_stmt *pQuery = 0;
  char *zQuery = 0;
  int rc;
  const unsigned char *zName;
  const unsigned char *zSql;
  char *zErrMsg = 0;

  zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master"
                           " WHERE %s", zWhere);
  zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
                           " WHERE %s ORDER BY rowid ASC", zWhere);
  shell_check_oom(zQuery);
  rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
  if( rc ){
    utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
                    sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
                    zQuery);
    goto end_schema_xfer;
  }
  while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
    zName = sqlite3_column_text(pQuery, 0);
    zSql = sqlite3_column_text(pQuery, 1);
    if( zName==0 || zSql==0 ) continue;
    if( sqlite3_stricmp((char*)zName, "sqlite_sequence")!=0 ){
    printf("%s... ", zName); fflush(stdout);
    sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
    if( zErrMsg ){
      utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
      sqlite3_free(zErrMsg);
      zErrMsg = 0;
      printf("%s... ", zName); fflush(stdout);
      sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
      if( zErrMsg ){
        utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
        sqlite3_free(zErrMsg);
        zErrMsg = 0;
      }
    }
    if( xForEach ){
      xForEach(p, newDb, (const char*)zName);
    }
    printf("done\n");
  }
  if( rc!=SQLITE_DONE ){
    sqlite3_finalize(pQuery);
    sqlite3_free(zQuery);
    zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master"
    zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
                             " WHERE %s ORDER BY rowid DESC", zWhere);
    shell_check_oom(zQuery);
    rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
    if( rc ){
      utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
                      sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
                      zQuery);
      goto end_schema_xfer;
    }
    while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
    while( sqlite3_step(pQuery)==SQLITE_ROW ){
      zName = sqlite3_column_text(pQuery, 0);
      zSql = sqlite3_column_text(pQuery, 1);
      if( zName==0 || zSql==0 ) continue;
      if( sqlite3_stricmp((char*)zName, "sqlite_sequence")!=0 ) continue;
      printf("%s... ", zName); fflush(stdout);
      sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
      if( zErrMsg ){
        utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
        sqlite3_free(zErrMsg);
        zErrMsg = 0;
      }
4582
4583
4584
4585
4586
4587
4588





4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603

4604
4605
4606

4607
4608
4609
4610
4611
4612
4613

4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625

4626
4627
4628
4629
4630
4631
4632
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126

6127
6128
6129

6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149

6150
6151
6152
6153
6154
6155
6156
6157







+
+
+
+
+














-
+


-
+







+











-
+







#else
      "xdg-open";
#endif
      char *zCmd;
      zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile);
      if( system(zCmd) ){
        utf8_printf(stderr, "Failed: [%s]\n", zCmd);
      }else{
        /* Give the start/open/xdg-open command some time to get
        ** going before we continue, and potential delete the
        ** p->zTempFile data file out from under it */
        sqlite3_sleep(2000);
      }
      sqlite3_free(zCmd);
      outputModePop(p);
      p->doXdgOpen = 0;
    }
#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
  }
  p->outfile[0] = 0;
  p->out = stdout;
}

/*
** Run an SQL command and return the single integer result.
*/
static int db_int(ShellState *p, const char *zSql){
static int db_int(sqlite3 *db, const char *zSql){
  sqlite3_stmt *pStmt;
  int res = 0;
  sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
  sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
  if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
    res = sqlite3_column_int(pStmt,0);
  }
  sqlite3_finalize(pStmt);
  return res;
}

#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
/*
** Convert a 2-byte or 4-byte big-endian integer into a native integer
*/
static unsigned int get2byteInt(unsigned char *a){
  return (a[0]<<8) + a[1];
}
static unsigned int get4byteInt(unsigned char *a){
  return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3];
}

/*
** Implementation of the ".info" command.
** Implementation of the ".dbinfo" command.
**
** Return 1 on error, 2 to exit, and 0 otherwise.
*/
static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
  static const struct { const char *zName; int ofst; } aField[] = {
     { "file change counter:",  24  },
     { "database page count:",  28  },
4649
4650
4651
4652
4653
4654
4655
4656

4657
4658
4659
4660
4661
4662
4663

4664
4665







4666
4667
4668
4669
4670
4671
4672
6174
6175
6176
6177
6178
6179
6180

6181
6182
6183
6184
6185
6186
6187
6188
6189


6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203







-
+







+
-
-
+
+
+
+
+
+
+







     { "number of triggers:",
       "SELECT count(*) FROM %s WHERE type='trigger'" },
     { "number of views:",
       "SELECT count(*) FROM %s WHERE type='view'" },
     { "schema size:",
       "SELECT total(length(sql)) FROM %s" },
  };
  int i;
  int i, rc;
  unsigned iDataVersion;
  char *zSchemaTab;
  char *zDb = nArg>=2 ? azArg[1] : "main";
  sqlite3_stmt *pStmt = 0;
  unsigned char aHdr[100];
  open_db(p, 0);
  if( p->db==0 ) return 1;
  rc = sqlite3_prepare_v2(p->db,
  sqlite3_prepare_v2(p->db,"SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
                     -1, &pStmt, 0);
             "SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
             -1, &pStmt, 0);
  if( rc ){
    utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db));
    sqlite3_finalize(pStmt);
    return 1;
  }
  sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC);
  if( sqlite3_step(pStmt)==SQLITE_ROW
   && sqlite3_column_bytes(pStmt,0)>100
  ){
    memcpy(aHdr, sqlite3_column_blob(pStmt,0), 100);
    sqlite3_finalize(pStmt);
  }else{
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699



4700
4701

4702
4703
4704
4705

4706
4707
4708
4709
4710
4711
4712
4713

4714
4715
4716
4717
4718
4719
4720
6221
6222
6223
6224
6225
6226
6227



6228
6229
6230
6231

6232
6233
6234
6235

6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252







-
-
-
+
+
+

-
+



-
+








+







        if( val==2 ) raw_printf(p->out, " (utf16le)");
        if( val==3 ) raw_printf(p->out, " (utf16be)");
      }
    }
    raw_printf(p->out, "\n");
  }
  if( zDb==0 ){
    zSchemaTab = sqlite3_mprintf("main.sqlite_master");
  }else if( strcmp(zDb,"temp")==0 ){
    zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_master");
    zSchemaTab = sqlite3_mprintf("main.sqlite_schema");
  }else if( cli_strcmp(zDb,"temp")==0 ){
    zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_schema");
  }else{
    zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_master", zDb);
    zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_schema", zDb);
  }
  for(i=0; i<ArraySize(aQuery); i++){
    char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
    int val = db_int(p, zSql);
    int val = db_int(p->db, zSql);
    sqlite3_free(zSql);
    utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val);
  }
  sqlite3_free(zSchemaTab);
  sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_DATA_VERSION, &iDataVersion);
  utf8_printf(p->out, "%-20s %u\n", "data version", iDataVersion);
  return 0;
}
#endif /* SQLITE_SHELL_HAVE_RECOVER */

/*
** Print the current sqlite3_errmsg() value to stderr and return 1.
*/
static int shellDatabaseError(sqlite3 *db){
  const char *zErr = sqlite3_errmsg(db);
  utf8_printf(stderr, "Error: %s\n", zErr);
4823
4824
4825
4826
4827
4828
4829
4830

4831
4832
4833
4834
4835
4836
4837
6355
6356
6357
6358
6359
6360
6361

6362
6363
6364
6365
6366
6367
6368
6369







-
+







** Compare the string as a command-line option with either one or two
** initial "-" characters.
*/
static int optionMatch(const char *zStr, const char *zOpt){
  if( zStr[0]!='-' ) return 0;
  zStr++;
  if( zStr[0]=='-' ) zStr++;
  return strcmp(zStr, zOpt)==0;
  return cli_strcmp(zStr, zOpt)==0;
}

/*
** Delete a file.
*/
int shellDeleteFile(const char *zFilename){
  int rc;
4864
4865
4866
4867
4868
4869
4870



4871
4872









4873

4874
4875
4876
4877

4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
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







+
+
+


+
+
+
+
+
+
+
+
+
-
+



-
+
-
-
-







  clearTempFile(p);
  sqlite3_free(p->zTempFile);
  p->zTempFile = 0;
  if( p->db ){
    sqlite3_file_control(p->db, 0, SQLITE_FCNTL_TEMPFILENAME, &p->zTempFile);
  }
  if( p->zTempFile==0 ){
    /* If p->db is an in-memory database then the TEMPFILENAME file-control
    ** will not work and we will need to fallback to guessing */
    char *zTemp;
    sqlite3_uint64 r;
    sqlite3_randomness(sizeof(r), &r);
    zTemp = getenv("TEMP");
    if( zTemp==0 ) zTemp = getenv("TMP");
    if( zTemp==0 ){
#ifdef _WIN32
      zTemp = "\\tmp";
#else
      zTemp = "/tmp";
#endif
    }
    p->zTempFile = sqlite3_mprintf("temp%llx.%s", r, zSuffix);
    p->zTempFile = sqlite3_mprintf("%s/temp%llx.%s", zTemp, r, zSuffix);
  }else{
    p->zTempFile = sqlite3_mprintf("%z.%s", p->zTempFile, zSuffix);
  }
  if( p->zTempFile==0 ){
  shell_check_oom(p->zTempFile);
    raw_printf(stderr, "out of memory\n");
    exit(1);
  }
}


/*
** The implementation of SQL scalar function fkey_collate_clause(), used
** by the ".lint fkey-indexes" command. This scalar function is always
** called with four arguments - the parent table name, the parent column name,
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
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







-
+














-
+




-
+







  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_master AS s, pragma_foreign_key_list(s.name) AS f "
    "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 ){
5054
5055
5056
5057
5058
5059
5060


5061
5062
5063
5064
5065
5066
5067


5068
5069
5070
5071
5072
5073
5074
5075
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607



6608
6609

6610
6611
6612
6613
6614
6615
6616







+
+




-
-
-
+
+
-







      const char *zEQP = (const char*)sqlite3_column_text(pSql, 0);
      const char *zGlob = (const char*)sqlite3_column_text(pSql, 1);
      const char *zFrom = (const char*)sqlite3_column_text(pSql, 2);
      const char *zTarget = (const char*)sqlite3_column_text(pSql, 3);
      const char *zCI = (const char*)sqlite3_column_text(pSql, 4);
      const char *zParent = (const char*)sqlite3_column_text(pSql, 5);

      if( zEQP==0 ) continue;
      if( zGlob==0 ) continue;
      rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
      if( rc!=SQLITE_OK ) break;
      if( SQLITE_ROW==sqlite3_step(pExplain) ){
        const char *zPlan = (const char*)sqlite3_column_text(pExplain, 3);
        res = (
              0==sqlite3_strglob(zGlob, zPlan)
           || 0==sqlite3_strglob(zGlobIPK, zPlan)
        res = zPlan!=0 && (  0==sqlite3_strglob(zGlob, zPlan)
                          || 0==sqlite3_strglob(zGlobIPK, zPlan));
        );
      }
      rc = sqlite3_finalize(pExplain);
      if( rc!=SQLITE_OK ) break;

      if( res<0 ){
        raw_printf(stderr, "Error: internal error");
        break;
5126
5127
5128
5129
5130
5131
5132
5133

5134
5135
5136
5137
5138
5139
5140



5141
5142
5143
5144
5145
5146
5147

5148
5149
5150
5151
5152
5153
5154







5155
5156
5157



5158
5159

5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177






5178
5179


5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193






5194
5195


5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206






5207
5208
5209
5210
5211
5212
5213
5214
5215
5216

5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236

5237
5238
5239
5240
5241
5242
5243
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
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
6735
6736
6737
6738
6739
6740
6741
6742
6743
6744
6745
6746
6747
6748
6749
6750


6751
6752
6753
6754
6755
6756
6757
6758
6759
6760
6761
6762
6763
6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774
6775
6776
6777
6778
6779
6780
6781
6782
6783
6784
6785
6786
6787
6788
6789
6790
6791
6792
6793
6794
6795
6796
6797
6798
6799

6800
6801
6802
6803
6804
6805
6806
6807







-
+
-
-
-

-
-
-
+
+
+






-
+







+
+
+
+
+
+
+
-
-
-
+
+
+

-
+


















+
+
+
+
+
+
-
-
+
+














+
+
+
+
+
+
-
-
+
+











+
+
+
+
+
+










+



















-
+







 usage:
  raw_printf(stderr, "Usage %s sub-command ?switches...?\n", azArg[0]);
  raw_printf(stderr, "Where sub-commands are:\n");
  raw_printf(stderr, "    fkey-indexes\n");
  return SQLITE_ERROR;
}

#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
#if !defined SQLITE_OMIT_VIRTUALTABLE
/*********************************************************************************
** The ".archive" or ".ar" command.
*/
static void shellPrepare(
  sqlite3 *db, 
  int *pRc, 
  const char *zSql, 
  sqlite3 *db,
  int *pRc,
  const char *zSql,
  sqlite3_stmt **ppStmt
){
  *ppStmt = 0;
  if( *pRc==SQLITE_OK ){
    int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0);
    if( rc!=SQLITE_OK ){
      raw_printf(stderr, "sql error: %s (%d)\n", 
      raw_printf(stderr, "sql error: %s (%d)\n",
          sqlite3_errmsg(db), sqlite3_errcode(db)
      );
      *pRc = rc;
    }
  }
}

/*
** Create a prepared statement using printf-style arguments for the SQL.
**
** This routine is could be marked "static".  But it is not always used,
** depending on compile-time options.  By omitting the "static", we avoid
** nuisance compiler warnings about "defined but not used".
*/
static void shellPreparePrintf(
  sqlite3 *db, 
  int *pRc, 
void shellPreparePrintf(
  sqlite3 *db,
  int *pRc,
  sqlite3_stmt **ppStmt,
  const char *zFmt, 
  const char *zFmt,
  ...
){
  *ppStmt = 0;
  if( *pRc==SQLITE_OK ){
    va_list ap;
    char *z;
    va_start(ap, zFmt);
    z = sqlite3_vmprintf(zFmt, ap);
    va_end(ap);
    if( z==0 ){
      *pRc = SQLITE_NOMEM;
    }else{
      shellPrepare(db, pRc, z, ppStmt);
      sqlite3_free(z);
    }
  }
}

/* Finalize the prepared statement created using shellPreparePrintf().
**
** This routine is could be marked "static".  But it is not always used,
** depending on compile-time options.  By omitting the "static", we avoid
** nuisance compiler warnings about "defined but not used".
*/
static void shellFinalize(
  int *pRc, 
void shellFinalize(
  int *pRc,
  sqlite3_stmt *pStmt
){
  if( pStmt ){
    sqlite3 *db = sqlite3_db_handle(pStmt);
    int rc = sqlite3_finalize(pStmt);
    if( *pRc==SQLITE_OK ){
      if( rc!=SQLITE_OK ){
        raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
      }
      *pRc = rc;
    }
  }
}

/* Reset the prepared statement created using shellPreparePrintf().
**
** This routine is could be marked "static".  But it is not always used,
** depending on compile-time options.  By omitting the "static", we avoid
** nuisance compiler warnings about "defined but not used".
*/
static void shellReset(
  int *pRc, 
void shellReset(
  int *pRc,
  sqlite3_stmt *pStmt
){
  int rc = sqlite3_reset(pStmt);
  if( *pRc==SQLITE_OK ){
    if( rc!=SQLITE_OK ){
      sqlite3 *db = sqlite3_db_handle(pStmt);
      raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
    }
    *pRc = rc;
  }
}
#endif /* !defined SQLITE_OMIT_VIRTUALTABLE */

#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
/******************************************************************************
** The ".archive" or ".ar" command.
*/
/*
** Structure representing a single ".ar" command.
*/
typedef struct ArCommand ArCommand;
struct ArCommand {
  u8 eCmd;                        /* An AR_CMD_* value */
  u8 bVerbose;                    /* True if --verbose */
  u8 bZip;                        /* True if the archive is a ZIP */
  u8 bDryRun;                     /* True if --dry-run */
  u8 bAppend;                     /* True if --append */
  u8 bGlob;                       /* True if --glob */
  u8 fromCmdLine;                 /* Run from -A instead of .archive */
  int nArg;                       /* Number of command arguments */
  char *zSrcTable;                /* "sqlar", "zipfile($file)" or "zip" */
  const char *zFile;              /* --file argument, or NULL */
  const char *zDir;               /* --directory argument, or NULL */
  char **azArg;                   /* Array of command arguments */
  ShellState *p;                  /* Shell state */
  sqlite3 *db;                    /* Database containing the archive */
};

/*
** Print a usage message for the .ar command to stderr and return SQLITE_ERROR.
*/
static int arUsage(FILE *f){
  showHelp(f,"archive");
  return SQLITE_ERROR;
}

/*
** Print an error message for the .ar command to stderr and return 
** Print an error message for the .ar command to stderr and return
** SQLITE_ERROR.
*/
static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){
  va_list ap;
  char *z;
  va_start(ap, zFmt);
  z = sqlite3_vmprintf(zFmt, ap);
5252
5253
5254
5255
5256
5257
5258


5259
5260
5261
5262




5263
5264
5265
5266
5267
5268
5269
5270
5271






5272
5273
5274
5275
5276
5277

5278

5279
5280
5281
5282
5283
5284
5285
5286
5287



5288
5289
5290
5291
5292
5293
5294

5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309

5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324

5325

5326
5327
5328
5329
5330
5331
5332

5333
5334
5335
5336
5337
5338
5339
6816
6817
6818
6819
6820
6821
6822
6823
6824




6825
6826
6827
6828
6829
6830
6831
6832





6833
6834
6835
6836
6837
6838
6839
6840
6841
6842
6843
6844
6845
6846
6847
6848
6849
6850
6851
6852
6853
6854
6855
6856
6857
6858
6859
6860
6861
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
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
6903
6904
6905
6906
6907
6908
6909
6910
6911
6912
6913
6914







+
+
-
-
-
-
+
+
+
+




-
-
-
-
-
+
+
+
+
+
+






+

+









+
+
+






-
+














-
+















+

+







+







  return SQLITE_ERROR;
}

/*
** Values for ArCommand.eCmd.
*/
#define AR_CMD_CREATE       1
#define AR_CMD_UPDATE       2
#define AR_CMD_INSERT       3
#define AR_CMD_EXTRACT      2
#define AR_CMD_LIST         3
#define AR_CMD_UPDATE       4
#define AR_CMD_HELP         5
#define AR_CMD_EXTRACT      4
#define AR_CMD_LIST         5
#define AR_CMD_HELP         6
#define AR_CMD_REMOVE       7

/*
** Other (non-command) switches.
*/
#define AR_SWITCH_VERBOSE     6
#define AR_SWITCH_FILE        7
#define AR_SWITCH_DIRECTORY   8
#define AR_SWITCH_APPEND      9
#define AR_SWITCH_DRYRUN     10
#define AR_SWITCH_VERBOSE     8
#define AR_SWITCH_FILE        9
#define AR_SWITCH_DIRECTORY  10
#define AR_SWITCH_APPEND     11
#define AR_SWITCH_DRYRUN     12
#define AR_SWITCH_GLOB       13

static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
  switch( eSwitch ){
    case AR_CMD_CREATE:
    case AR_CMD_EXTRACT:
    case AR_CMD_LIST:
    case AR_CMD_REMOVE:
    case AR_CMD_UPDATE:
    case AR_CMD_INSERT:
    case AR_CMD_HELP:
      if( pAr->eCmd ){
        return arErrorMsg(pAr, "multiple command options");
      }
      pAr->eCmd = eSwitch;
      break;

    case AR_SWITCH_DRYRUN:
      pAr->bDryRun = 1;
      break;
    case AR_SWITCH_GLOB:
      pAr->bGlob = 1;
      break;
    case AR_SWITCH_VERBOSE:
      pAr->bVerbose = 1;
      break;
    case AR_SWITCH_APPEND:
      pAr->bAppend = 1;
      /* Fall thru into --file */
      deliberate_fall_through;
    case AR_SWITCH_FILE:
      pAr->zFile = zArg;
      break;
    case AR_SWITCH_DIRECTORY:
      pAr->zDir = zArg;
      break;
  }

  return SQLITE_OK;
}

/*
** Parse the command line for an ".ar" command. The results are written into
** structure (*pAr). SQLITE_OK is returned if the command line is parsed
** successfully, otherwise an error message is written to stderr and 
** successfully, otherwise an error message is written to stderr and
** SQLITE_ERROR returned.
*/
static int arParseCommand(
  char **azArg,                   /* Array of arguments passed to dot command */
  int nArg,                       /* Number of entries in azArg[] */
  ArCommand *pAr                  /* Populate this object */
){
  struct ArSwitch {
    const char *zLong;
    char cShort;
    u8 eSwitch;
    u8 bArg;
  } aSwitch[] = {
    { "create",    'c', AR_CMD_CREATE,       0 },
    { "extract",   'x', AR_CMD_EXTRACT,      0 },
    { "insert",    'i', AR_CMD_INSERT,       0 },
    { "list",      't', AR_CMD_LIST,         0 },
    { "remove",    'r', AR_CMD_REMOVE,       0 },
    { "update",    'u', AR_CMD_UPDATE,       0 },
    { "help",      'h', AR_CMD_HELP,         0 },
    { "verbose",   'v', AR_SWITCH_VERBOSE,   0 },
    { "file",      'f', AR_SWITCH_FILE,      1 },
    { "append",    'a', AR_SWITCH_APPEND,    1 },
    { "directory", 'C', AR_SWITCH_DIRECTORY, 1 },
    { "dryrun",    'n', AR_SWITCH_DRYRUN,    0 },
    { "glob",      'g', AR_SWITCH_GLOB,      0 },
  };
  int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
  struct ArSwitch *pEnd = &aSwitch[nSwitch];

  if( nArg<=1 ){
    utf8_printf(stderr, "Wrong number of arguments.  Usage:\n");
    return arUsage(stderr);
5392
5393
5394
5395
5396
5397
5398
5399


5400
5401
5402
5403
5404
5405
5406
6967
6968
6969
6970
6971
6972
6973

6974
6975
6976
6977
6978
6979
6980
6981
6982







-
+
+







            }
            if( pOpt->bArg ){
              if( i<(n-1) ){
                zArg = &z[i+1];
                i = n;
              }else{
                if( iArg>=(nArg-1) ){
                  return arErrorMsg(pAr, "option requires an argument: %c",z[i]);
                  return arErrorMsg(pAr, "option requires an argument: %c",
                                    z[i]);
                }
                zArg = azArg[++iArg];
              }
            }
            if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
          }
        }else if( z[2]=='\0' ){
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452







5453
5454
5455
5456
5457
5458
5459
5460
5461
5462



5463
5464

5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
7017
7018
7019
7020
7021
7022
7023





7024
7025
7026
7027
7028
7029
7030
7031
7032
7033
7034
7035
7036
7037
7038
7039
7040
7041
7042
7043
7044

7045



7046
7047
7048
7049
7050
7051
7052







-
-
-
-
-
+
+
+
+
+
+
+










+
+
+

-
+
-
-
-







  }

  return SQLITE_OK;
}

/*
** This function assumes that all arguments within the ArCommand.azArg[]
** array refer to archive members, as for the --extract or --list commands. 
** It checks that each of them are present. If any specified file is not
** present in the archive, an error is printed to stderr and an error
** code returned. Otherwise, if all specified arguments are present in
** the archive, SQLITE_OK is returned.
** array refer to archive members, as for the --extract, --list or --remove
** commands. It checks that each of them are "present". If any specified
** file is not present in the archive, an error is printed to stderr and an
** error code returned. Otherwise, if all specified arguments are present
** in the archive, SQLITE_OK is returned. Here, "present" means either an
** exact equality when pAr->bGlob is false or a "name GLOB pattern" match
** when pAr->bGlob is true.
**
** This function strips any trailing '/' characters from each argument.
** This is consistent with the way the [tar] command seems to work on
** Linux.
*/
static int arCheckEntries(ArCommand *pAr){
  int rc = SQLITE_OK;
  if( pAr->nArg ){
    int i, j;
    sqlite3_stmt *pTest = 0;
    const char *zSel = (pAr->bGlob)
      ? "SELECT name FROM %s WHERE glob($name,name)"
      : "SELECT name FROM %s WHERE name=$name";

    shellPreparePrintf(pAr->db, &rc, &pTest,
    shellPreparePrintf(pAr->db, &rc, &pTest, zSel, pAr->zSrcTable);
        "SELECT name FROM %s WHERE name=$name", 
        pAr->zSrcTable
    );
    j = sqlite3_bind_parameter_index(pTest, "$name");
    for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
      char *z = pAr->azArg[i];
      int n = strlen30(z);
      int bOk = 0;
      while( n>0 && z[n-1]=='/' ) n--;
      z[n] = '\0';
5488
5489
5490
5491
5492
5493
5494
5495


5496
5497
5498
5499


5500
5501
5502

5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513


5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527

5528
5529
5530

5531
5532
5533
5534
5535
5536
5537
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
7097
7098
7099
7100
7101
7102
7103
7104
7105
7106

7107
7108
7109

7110
7111
7112
7113
7114
7115
7116
7117







-
+
+


-
-
+
+



+









-
-
+
+













-
+


-
+







}

/*
** Format a WHERE clause that can be used against the "sqlar" table to
** identify all archive members that match the command arguments held
** in (*pAr). Leave this WHERE clause in (*pzWhere) before returning.
** The caller is responsible for eventually calling sqlite3_free() on
** any non-NULL (*pzWhere) value.
** any non-NULL (*pzWhere) value. Here, "match" means strict equality
** when pAr->bGlob is false and GLOB match when pAr->bGlob is true.
*/
static void arWhereClause(
  int *pRc, 
  ArCommand *pAr, 
  int *pRc,
  ArCommand *pAr,
  char **pzWhere                  /* OUT: New WHERE clause */
){
  char *zWhere = 0;
  const char *zSameOp = (pAr->bGlob)? "GLOB" : "=";
  if( *pRc==SQLITE_OK ){
    if( pAr->nArg==0 ){
      zWhere = sqlite3_mprintf("1");
    }else{
      int i;
      const char *zSep = "";
      for(i=0; i<pAr->nArg; i++){
        const char *z = pAr->azArg[i];
        zWhere = sqlite3_mprintf(
          "%z%s name = '%q' OR substr(name,1,%d) = '%q/'", 
          zWhere, zSep, z, strlen30(z)+1, z
          "%z%s name %s '%q' OR substr(name,1,%d) %s '%q/'",
          zWhere, zSep, zSameOp, z, strlen30(z)+1, zSameOp, z
        );
        if( zWhere==0 ){
          *pRc = SQLITE_NOMEM;
          break;
        }
        zSep = " OR ";
      }
    }
  }
  *pzWhere = zWhere;
}

/*
** Implementation of .ar "lisT" command. 
** Implementation of .ar "lisT" command.
*/
static int arListCommand(ArCommand *pAr){
  const char *zSql = "SELECT %s FROM %s WHERE %s"; 
  const char *zSql = "SELECT %s FROM %s WHERE %s";
  const char *azCols[] = {
    "name",
    "lsmode(mode), sz, datetime(mtime, 'unixepoch'), name"
  };

  char *zWhere = 0;
  sqlite3_stmt *pSql = 0;
5545
5546
5547
5548
5549
5550
5551
5552

5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567









































5568

5569
5570
5571

5572
5573
5574
5575
5576
5577
5578

5579
5580
5581
5582
5583
5584
5585
7125
7126
7127
7128
7129
7130
7131

7132
7133
7134
7135
7136
7137
7138
7139
7140
7141
7142
7143
7144
7145
7146
7147
7148
7149
7150
7151
7152
7153
7154
7155
7156
7157
7158
7159
7160
7161
7162
7163
7164
7165
7166
7167
7168
7169
7170
7171
7172
7173
7174
7175
7176
7177
7178
7179
7180
7181
7182
7183
7184
7185
7186
7187
7188

7189
7190
7191

7192
7193
7194
7195
7196
7197
7198

7199
7200
7201
7202
7203
7204
7205
7206







-
+















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+


-
+






-
+







  if( pAr->bDryRun ){
    utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
  }else{
    while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
      if( pAr->bVerbose ){
        utf8_printf(pAr->p->out, "%s % 10d  %s  %s\n",
            sqlite3_column_text(pSql, 0),
            sqlite3_column_int(pSql, 1), 
            sqlite3_column_int(pSql, 1),
            sqlite3_column_text(pSql, 2),
            sqlite3_column_text(pSql, 3)
        );
      }else{
        utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
      }
    }
  }
  shellFinalize(&rc, pSql);
  sqlite3_free(zWhere);
  return rc;
}


/*
** Implementation of .ar "Remove" command.
*/
static int arRemoveCommand(ArCommand *pAr){
  int rc = 0;
  char *zSql = 0;
  char *zWhere = 0;

  if( pAr->nArg ){
    /* Verify that args actually exist within the archive before proceeding.
    ** And formulate a WHERE clause to match them.  */
    rc = arCheckEntries(pAr);
    arWhereClause(&rc, pAr, &zWhere);
  }
  if( rc==SQLITE_OK ){
    zSql = sqlite3_mprintf("DELETE FROM %s WHERE %s;",
                           pAr->zSrcTable, zWhere);
    if( pAr->bDryRun ){
      utf8_printf(pAr->p->out, "%s\n", zSql);
    }else{
      char *zErr = 0;
      rc = sqlite3_exec(pAr->db, "SAVEPOINT ar;", 0, 0, 0);
      if( rc==SQLITE_OK ){
        rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
        if( rc!=SQLITE_OK ){
          sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
        }else{
          rc = sqlite3_exec(pAr->db, "RELEASE ar;", 0, 0, 0);
        }
      }
      if( zErr ){
        utf8_printf(stdout, "ERROR: %s\n", zErr);
        sqlite3_free(zErr);
      }
    }
  }
  sqlite3_free(zWhere);
  sqlite3_free(zSql);
  return rc;
}

/*
** Implementation of .ar "eXtract" command. 
** Implementation of .ar "eXtract" command.
*/
static int arExtractCommand(ArCommand *pAr){
  const char *zSql1 = 
  const char *zSql1 =
    "SELECT "
    " ($dir || name),"
    " writefile(($dir || name), %s, mode, mtime) "
    "FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)"
    " AND name NOT GLOB '*..[/\\]*'";

  const char *azExtraArg[] = { 
  const char *azExtraArg[] = {
    "sqlar_uncompress(data, sz)",
    "data"
  };

  sqlite3_stmt *pSql = 0;
  int rc = SQLITE_OK;
  char *zDir = 0;
5597
5598
5599
5600
5601
5602
5603
5604

5605
5606
5607
5608
5609
5610
5611
7218
7219
7220
7221
7222
7223
7224

7225
7226
7227
7228
7229
7230
7231
7232







-
+







      zDir = sqlite3_mprintf("%s/", pAr->zDir);
    }else{
      zDir = sqlite3_mprintf("");
    }
    if( zDir==0 ) rc = SQLITE_NOMEM;
  }

  shellPreparePrintf(pAr->db, &rc, &pSql, zSql1, 
  shellPreparePrintf(pAr->db, &rc, &pSql, zSql1,
      azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere
  );

  if( rc==SQLITE_OK ){
    j = sqlite3_bind_parameter_index(pSql, "$dir");
    sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC);

5653
5654
5655
5656
5657
5658
5659
5660






5661
5662
5663
5664
5665
5666
5667
5668



5669
5670
5671
5672


5673
5674

5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695



5696
5697
5698
5699
5700
5701
5702
5703


5704
5705
5706
5707
5708
5709

5710
5711
5712
5713
5714

5715
5716
5717
5718
5719
5720
5721
7274
7275
7276
7277
7278
7279
7280

7281
7282
7283
7284
7285
7286
7287
7288
7289
7290
7291
7292
7293

7294
7295
7296
7297
7298
7299

7300
7301
7302

7303
7304
7305
7306
7307
7308
7309
7310
7311
7312
7313
7314
7315
7316
7317
7318
7319
7320
7321
7322


7323
7324
7325
7326
7327
7328
7329
7330
7331


7332
7333
7334
7335
7336
7337
7338
7339
7340
7341
7342
7343
7344

7345
7346
7347
7348
7349
7350
7351
7352







-
+
+
+
+
+
+







-
+
+
+



-
+
+

-
+



















-
-
+
+
+






-
-
+
+






+




-
+







    }
  }
  return rc;
}


/*
** Implementation of .ar "create" and "update" commands.
** Implementation of .ar "create", "insert", and "update" commands.
**
**     create    ->     Create a new SQL archive
**     insert    ->     Insert or reinsert all files listed
**     update    ->     Insert files that have changed or that were not
**                      previously in the archive
**
** Create the "sqlar" table in the database if it does not already exist.
** Then add each file in the azFile[] array to the archive. Directories
** are added recursively. If argument bVerbose is non-zero, a message is
** printed on stdout for each file archived.
**
** The create command is the same as update, except that it drops
** any existing "sqlar" table before beginning.
** any existing "sqlar" table before beginning.  The "insert" command
** always overwrites every file named on the command-line, where as
** "update" only overwrites if the size or mtime or mode has changed.
*/
static int arCreateOrUpdateCommand(
  ArCommand *pAr,                 /* Command arguments and options */
  int bUpdate                     /* true for a --create.  false for --update */
  int bUpdate,                    /* true for a --create. */
  int bOnlyIfChanged              /* Only update if file has changed */
){
  const char *zCreate = 
  const char *zCreate =
      "CREATE TABLE IF NOT EXISTS sqlar(\n"
      "  name TEXT PRIMARY KEY,  -- name of the file\n"
      "  mode INT,               -- access permissions\n"
      "  mtime INT,              -- last modification time\n"
      "  sz INT,                 -- original file size\n"
      "  data BLOB               -- compressed content\n"
      ")";
  const char *zDrop = "DROP TABLE IF EXISTS sqlar";
  const char *zInsertFmt[2] = {
     "REPLACE INTO %s(name,mode,mtime,sz,data)\n"
     "  SELECT\n"
     "    %s,\n"
     "    mode,\n"
     "    mtime,\n"
     "    CASE substr(lsmode(mode),1,1)\n"
     "      WHEN '-' THEN length(data)\n"
     "      WHEN 'd' THEN 0\n"
     "      ELSE -1 END,\n"
     "    sqlar_compress(data)\n"
     "  FROM fsdir(%Q,%Q)\n"
     "  WHERE lsmode(mode) NOT LIKE '?%%';",
     "  FROM fsdir(%Q,%Q) AS disk\n"
     "  WHERE lsmode(mode) NOT LIKE '?%%'%s;"
     ,
     "REPLACE INTO %s(name,mode,mtime,data)\n"
     "  SELECT\n"
     "    %s,\n"
     "    mode,\n"
     "    mtime,\n"
     "    data\n"
     "  FROM fsdir(%Q,%Q)\n"
     "  WHERE lsmode(mode) NOT LIKE '?%%';"
     "  FROM fsdir(%Q,%Q) AS disk\n"
     "  WHERE lsmode(mode) NOT LIKE '?%%'%s;"
  };
  int i;                          /* For iterating through azFile[] */
  int rc;                         /* Return code */
  const char *zTab = 0;           /* SQL table into which to insert */
  char *zSql;
  char zTemp[50];
  char *zExists = 0;

  arExecSql(pAr, "PRAGMA page_size=512");
  rc = arExecSql(pAr, "SAVEPOINT ar;");
  if( rc!=SQLITE_OK ) return rc;
  zTemp[0] = 0; 
  zTemp[0] = 0;
  if( pAr->bZip ){
    /* Initialize the zipfile virtual table, if necessary */
    if( pAr->zFile ){
      sqlite3_uint64 r;
      sqlite3_randomness(sizeof(r),&r);
      sqlite3_snprintf(sizeof(zTemp),zTemp,"zip%016llx",r);
      zTab = zTemp;
5733
5734
5735
5736
5737
5738
5739











5740
5741
5742
5743

5744
5745
5746
5747
5748
5749

5750
5751
5752
5753
5754
5755
5756
5757

5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768




5769
5770
5771
5772
5773
5774
5775
7364
7365
7366
7367
7368
7369
7370
7371
7372
7373
7374
7375
7376
7377
7378
7379
7380
7381
7382
7383
7384

7385
7386
7387
7388
7389
7390

7391
7392
7393
7394
7395
7396
7397
7398
7399
7400
7401
7402
7403
7404
7405
7406
7407




7408
7409
7410
7411
7412
7413
7414
7415
7416
7417
7418







+
+
+
+
+
+
+
+
+
+
+



-
+





-
+








+







-
-
-
-
+
+
+
+







    zTab = "sqlar";
    if( bUpdate==0 ){
      rc = arExecSql(pAr, zDrop);
      if( rc!=SQLITE_OK ) goto end_ar_transaction;
    }
    rc = arExecSql(pAr, zCreate);
  }
  if( bOnlyIfChanged ){
    zExists = sqlite3_mprintf(
      " AND NOT EXISTS("
          "SELECT 1 FROM %s AS mem"
          " WHERE mem.name=disk.name"
          " AND mem.mtime=disk.mtime"
          " AND mem.mode=disk.mode)", zTab);
  }else{
    zExists = sqlite3_mprintf("");
  }
  if( zExists==0 ) rc = SQLITE_NOMEM;
  for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
    char *zSql2 = sqlite3_mprintf(zInsertFmt[pAr->bZip], zTab,
        pAr->bVerbose ? "shell_putsnl(name)" : "name",
        pAr->azArg[i], pAr->zDir);
        pAr->azArg[i], pAr->zDir, zExists);
    rc = arExecSql(pAr, zSql2);
    sqlite3_free(zSql2);
  }
end_ar_transaction:
  if( rc!=SQLITE_OK ){
    arExecSql(pAr, "ROLLBACK TO ar; RELEASE ar;");
    sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
  }else{
    rc = arExecSql(pAr, "RELEASE ar;");
    if( pAr->bZip && pAr->zFile ){
      zSql = sqlite3_mprintf("DROP TABLE %s", zTemp);
      arExecSql(pAr, zSql);
      sqlite3_free(zSql);
    }
  }
  sqlite3_free(zExists);
  return rc;
}

/*
** Implementation of ".ar" dot command.
*/
static int arDotCommand(
  ShellState *pState,             /* Current shell tool state */
  int fromCmdLine,                /* True if -A command-line option, not .ar cmd */
  char **azArg,                   /* Array of arguments passed to dot command */
  int nArg                        /* Number of entries in azArg[] */
  ShellState *pState,          /* Current shell tool state */
  int fromCmdLine,             /* True if -A command-line option, not .ar cmd */
  char **azArg,                /* Array of arguments passed to dot command */
  int nArg                     /* Number of entries in azArg[] */
){
  ArCommand cmd;
  int rc;
  memset(&cmd, 0, sizeof(cmd));
  cmd.fromCmdLine = fromCmdLine;
  rc = arParseCommand(azArg, nArg, &cmd);
  if( rc==SQLITE_OK ){
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
7432
7433
7434
7435
7436
7437
7438

7439
7440
7441
7442
7443
7444
7445
7446
7447
7448
7449

7450
7451
7452

7453
7454
7455
7456
7457
7458
7459
7460







-
+
+









-
+


-
+







          cmd.zSrcTable = sqlite3_mprintf("zipfile(%Q)", cmd.zFile);
        }
      }
      cmd.bZip = 1;
    }else if( cmd.zFile ){
      int flags;
      if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS;
      if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_UPDATE ){
      if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_INSERT
           || cmd.eCmd==AR_CMD_REMOVE || cmd.eCmd==AR_CMD_UPDATE ){
        flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
      }else{
        flags = SQLITE_OPEN_READONLY;
      }
      cmd.db = 0;
      if( cmd.bDryRun ){
        utf8_printf(pState->out, "-- open database '%s'%s\n", cmd.zFile,
             eDbType==SHELL_OPEN_APPENDVFS ? " using 'apndvfs'" : "");
      }
      rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags, 
      rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags,
             eDbType==SHELL_OPEN_APPENDVFS ? "apndvfs" : 0);
      if( rc!=SQLITE_OK ){
        utf8_printf(stderr, "cannot open file: %s (%s)\n", 
        utf8_printf(stderr, "cannot open file: %s (%s)\n",
            cmd.zFile, sqlite3_errmsg(cmd.db)
        );
        goto end_ar_command;
      }
      sqlite3_fileio_init(cmd.db, 0, 0);
      sqlite3_sqlar_init(cmd.db, 0, 0);
      sqlite3_create_function(cmd.db, "shell_putsnl", 1, SQLITE_UTF8, cmd.p,
5826
5827
5828
5829
5830
5831
5832
5833

5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847








5848
5849
5850

5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863

5864
5865






































































































































































































































































































5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878

5879
5880
5881
5882
5883
5884
5885
5886
5887
5888

5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908

5909
5910
5911
5912
5913
5914
5915
5916
5917
5918

5919
5920
5921
5922
5923
5924
5925
5926


5927
5928
5929
5930
5931
5932
5933
5934



5935

5936
5937
5938
5939

5940
5941


5942
5943
5944
5945
5946
5947
5948
5949

5950
5951
5952
5953
5954

5955
5956
5957

5958
5959
5960
5961
5962
5963
5964
7470
7471
7472
7473
7474
7475
7476

7477
7478
7479
7480
7481
7482
7483
7484
7485
7486
7487
7488
7489
7490
7491
7492
7493
7494
7495
7496
7497
7498
7499
7500
7501

7502
7503
7504
7505
7506
7507
7508
7509
7510
7511
7512
7513
7514

7515
7516
7517
7518
7519
7520
7521
7522
7523
7524
7525
7526
7527
7528
7529
7530
7531
7532
7533
7534
7535
7536
7537
7538
7539
7540
7541
7542
7543
7544
7545
7546
7547
7548
7549
7550
7551
7552
7553
7554
7555
7556
7557
7558
7559
7560
7561
7562
7563
7564
7565
7566
7567
7568
7569
7570
7571
7572
7573
7574
7575
7576
7577
7578
7579
7580
7581
7582
7583
7584
7585
7586
7587
7588
7589
7590
7591
7592
7593
7594
7595
7596
7597
7598
7599
7600
7601
7602
7603
7604
7605
7606
7607
7608
7609
7610
7611
7612
7613
7614
7615
7616
7617
7618
7619
7620
7621
7622
7623
7624
7625
7626
7627
7628
7629
7630
7631
7632
7633
7634
7635
7636
7637
7638
7639
7640
7641
7642
7643
7644
7645
7646
7647
7648
7649
7650
7651
7652
7653
7654
7655
7656
7657
7658
7659
7660
7661
7662
7663
7664
7665
7666
7667
7668
7669
7670
7671
7672
7673
7674
7675
7676
7677
7678
7679
7680
7681
7682
7683
7684
7685
7686
7687
7688
7689
7690
7691
7692
7693
7694
7695
7696
7697
7698
7699
7700
7701
7702
7703
7704
7705
7706
7707
7708
7709
7710
7711
7712
7713
7714
7715
7716
7717
7718
7719
7720
7721
7722
7723
7724
7725
7726
7727
7728
7729
7730
7731
7732
7733
7734
7735
7736
7737
7738
7739
7740
7741
7742
7743
7744
7745
7746
7747
7748
7749
7750
7751
7752
7753
7754
7755
7756
7757
7758
7759
7760
7761
7762
7763
7764
7765
7766
7767
7768
7769
7770
7771
7772
7773
7774
7775
7776
7777
7778
7779
7780
7781
7782
7783
7784
7785
7786
7787
7788
7789
7790
7791
7792
7793
7794
7795
7796
7797
7798
7799
7800
7801
7802
7803
7804
7805
7806
7807
7808
7809
7810
7811
7812
7813
7814
7815
7816
7817
7818
7819
7820
7821
7822
7823

7824
7825
7826
7827
7828
7829
7830
7831
7832
7833

7834
7835
7836
7837
7838
7839
7840
7841
7842
7843
7844
7845
7846
7847
7848
7849
7850
7851
7852
7853
7854
7855
7856
7857
7858
7859
7860
7861
7862
7863
7864

7865
7866
7867
7868
7869
7870
7871
7872
7873
7874
7875
7876
7877
7878
7879
7880
7881


7882
7883
7884
7885
7886
7887
7888
7889
7890
7891


7892
7893
7894
7895
7896
7897
7898
7899
7900
7901
7902
7903
7904
7905
7906

7907
7908
7909

7910
7911
7912
7913
7914
7915
7916
7917







-
+














+
+
+
+
+
+
+
+


-
+












-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+












-
+









-
+




















+









-
+








+
+






-
-
+
+
+

+




+
-
-
+
+








+




-
+


-
+







        goto end_ar_command;
      }
      cmd.zSrcTable = sqlite3_mprintf("sqlar");
    }

    switch( cmd.eCmd ){
      case AR_CMD_CREATE:
        rc = arCreateOrUpdateCommand(&cmd, 0);
        rc = arCreateOrUpdateCommand(&cmd, 0, 0);
        break;

      case AR_CMD_EXTRACT:
        rc = arExtractCommand(&cmd);
        break;

      case AR_CMD_LIST:
        rc = arListCommand(&cmd);
        break;

      case AR_CMD_HELP:
        arUsage(pState->out);
        break;

      case AR_CMD_INSERT:
        rc = arCreateOrUpdateCommand(&cmd, 1, 0);
        break;

      case AR_CMD_REMOVE:
        rc = arRemoveCommand(&cmd);
        break;

      default:
        assert( cmd.eCmd==AR_CMD_UPDATE );
        rc = arCreateOrUpdateCommand(&cmd, 1);
        rc = arCreateOrUpdateCommand(&cmd, 1, 1);
        break;
    }
  }
end_ar_command:
  if( cmd.db!=pState->db ){
    close_db(cmd.db);
  }
  sqlite3_free(cmd.zSrcTable);

  return rc;
}
/* End of the ".archive" or ".ar" command logic
**********************************************************************************/
*******************************************************************************/
#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */

#if SQLITE_SHELL_HAVE_RECOVER

/*
** This function is used as a callback by the recover extension. Simply
** print the supplied SQL statement to stdout.
*/
static int recoverSqlCb(void *pCtx, const char *zSql){
  ShellState *pState = (ShellState*)pCtx;
  utf8_printf(pState->out, "%s;\n", zSql);
  return SQLITE_OK;
}

/*
** This function is called to recover data from the database. A script
** to construct a new database containing all recovered data is output
** on stream pState->out.
*/
static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
  int rc = SQLITE_OK;
  const char *zRecoveryDb = "";   /* Name of "recovery" database.  Debug only */
  const char *zLAF = "lost_and_found";
  int bFreelist = 1;              /* 0 if --ignore-freelist is specified */
  int bRowids = 1;                /* 0 if --no-rowids */
  sqlite3_recover *p = 0;
  int i = 0;

  for(i=1; i<nArg; i++){
    char *z = azArg[i];
    int n;
    if( z[0]=='-' && z[1]=='-' ) z++;
    n = strlen30(z);
    if( n<=17 && memcmp("-ignore-freelist", z, n)==0 ){
      bFreelist = 0;
    }else
    if( n<=12 && memcmp("-recovery-db", z, n)==0 && i<(nArg-1) ){
      /* This option determines the name of the ATTACH-ed database used
      ** internally by the recovery extension.  The default is "" which
      ** means to use a temporary database that is automatically deleted
      ** when closed.  This option is undocumented and might disappear at
      ** any moment. */
      i++;
      zRecoveryDb = azArg[i];
    }else
    if( n<=15 && memcmp("-lost-and-found", z, n)==0 && i<(nArg-1) ){
      i++;
      zLAF = azArg[i];
    }else
    if( n<=10 && memcmp("-no-rowids", z, n)==0 ){
      bRowids = 0;
    }
    else{
      utf8_printf(stderr, "unexpected option: %s\n", azArg[i]);
      showHelp(pState->out, azArg[0]);
      return 1;
    }
  }

  p = sqlite3_recover_init_sql(
      pState->db, "main", recoverSqlCb, (void*)pState
  );

  sqlite3_recover_config(p, 789, (void*)zRecoveryDb);  /* Debug use only */
  sqlite3_recover_config(p, SQLITE_RECOVER_LOST_AND_FOUND, (void*)zLAF);
  sqlite3_recover_config(p, SQLITE_RECOVER_ROWIDS, (void*)&bRowids);
  sqlite3_recover_config(p, SQLITE_RECOVER_FREELIST_CORRUPT,(void*)&bFreelist);

  sqlite3_recover_run(p);
  if( sqlite3_recover_errcode(p)!=SQLITE_OK ){
    const char *zErr = sqlite3_recover_errmsg(p);
    int errCode = sqlite3_recover_errcode(p);
    raw_printf(stderr, "sql error: %s (%d)\n", zErr, errCode);
  }
  rc = sqlite3_recover_finish(p);
  return rc;
}
#endif /* SQLITE_SHELL_HAVE_RECOVER */


/*
 * zAutoColumn(zCol, &db, ?) => Maybe init db, add column zCol to it.
 * zAutoColumn(0, &db, ?) => (db!=0) Form columns spec for CREATE TABLE,
 *   close db and set it to 0, and return the columns spec, to later
 *   be sqlite3_free()'ed by the caller.
 * The return is 0 when either:
 *   (a) The db was not initialized and zCol==0 (There are no columns.)
 *   (b) zCol!=0  (Column was added, db initialized as needed.)
 * The 3rd argument, pRenamed, references an out parameter. If the
 * pointer is non-zero, its referent will be set to a summary of renames
 * done if renaming was necessary, or set to 0 if none was done. The out
 * string (if any) must be sqlite3_free()'ed by the caller.
 */
#ifdef SHELL_DEBUG
#define rc_err_oom_die(rc) \
  if( rc==SQLITE_NOMEM ) shell_check_oom(0); \
  else if(!(rc==SQLITE_OK||rc==SQLITE_DONE)) \
    fprintf(stderr,"E:%d\n",rc), assert(0)
#else
static void rc_err_oom_die(int rc){
  if( rc==SQLITE_NOMEM ) shell_check_oom(0);
  assert(rc==SQLITE_OK||rc==SQLITE_DONE);
}
#endif

#ifdef SHELL_COLFIX_DB /* If this is set, the DB can be in a file. */
static char zCOL_DB[] = SHELL_STRINGIFY(SHELL_COLFIX_DB);
#else  /* Otherwise, memory is faster/better for the transient DB. */
static const char *zCOL_DB = ":memory:";
#endif

/* Define character (as C string) to separate generated column ordinal
 * from protected part of incoming column names. This defaults to "_"
 * so that incoming column identifiers that did not need not be quoted
 * remain usable without being quoted. It must be one character.
 */
#ifndef SHELL_AUTOCOLUMN_SEP
# define AUTOCOLUMN_SEP "_"
#else
# define AUTOCOLUMN_SEP SHELL_STRINGIFY(SHELL_AUTOCOLUMN_SEP)
#endif

static char *zAutoColumn(const char *zColNew, sqlite3 **pDb, char **pzRenamed){
  /* Queries and D{D,M}L used here */
  static const char * const zTabMake = "\
CREATE TABLE ColNames(\
 cpos INTEGER PRIMARY KEY,\
 name TEXT, nlen INT, chop INT, reps INT, suff TEXT);\
CREATE VIEW RepeatedNames AS \
SELECT DISTINCT t.name FROM ColNames t \
WHERE t.name COLLATE NOCASE IN (\
 SELECT o.name FROM ColNames o WHERE o.cpos<>t.cpos\
);\
";
  static const char * const zTabFill = "\
INSERT INTO ColNames(name,nlen,chop,reps,suff)\
 VALUES(iif(length(?1)>0,?1,'?'),max(length(?1),1),0,0,'')\
";
  static const char * const zHasDupes = "\
SELECT count(DISTINCT (substring(name,1,nlen-chop)||suff) COLLATE NOCASE)\
 <count(name) FROM ColNames\
";
#ifdef SHELL_COLUMN_RENAME_CLEAN
  static const char * const zDedoctor = "\
UPDATE ColNames SET chop=iif(\
  (substring(name,nlen,1) BETWEEN '0' AND '9')\
  AND (rtrim(name,'0123456790') glob '*"AUTOCOLUMN_SEP"'),\
 nlen-length(rtrim(name, '"AUTOCOLUMN_SEP"0123456789')),\
 0\
)\
";
#endif
  static const char * const zSetReps = "\
UPDATE ColNames AS t SET reps=\
(SELECT count(*) FROM ColNames d \
 WHERE substring(t.name,1,t.nlen-t.chop)=substring(d.name,1,d.nlen-d.chop)\
 COLLATE NOCASE\
)\
";
#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
  static const char * const zColDigits = "\
SELECT CAST(ceil(log(count(*)+0.5)) AS INT) FROM ColNames \
";
#else
  /* Counting on SQLITE_MAX_COLUMN < 100,000 here. (32767 is the hard limit.) */
  static const char * const zColDigits = "\
SELECT CASE WHEN (nc < 10) THEN 1 WHEN (nc < 100) THEN 2 \
 WHEN (nc < 1000) THEN 3 WHEN (nc < 10000) THEN 4 \
 ELSE 5 FROM (SELECT count(*) AS nc FROM ColNames) \
";
#endif
  static const char * const zRenameRank =
#ifdef SHELL_COLUMN_RENAME_CLEAN
    "UPDATE ColNames AS t SET suff="
    "iif(reps>1, printf('%c%0*d', '"AUTOCOLUMN_SEP"', $1, cpos), '')"
#else /* ...RENAME_MINIMAL_ONE_PASS */
"WITH Lzn(nlz) AS (" /* Find minimum extraneous leading 0's for uniqueness */
"  SELECT 0 AS nlz"
"  UNION"
"  SELECT nlz+1 AS nlz FROM Lzn"
"  WHERE EXISTS("
"   SELECT 1"
"   FROM ColNames t, ColNames o"
"   WHERE"
"    iif(t.name IN (SELECT * FROM RepeatedNames),"
"     printf('%s"AUTOCOLUMN_SEP"%s',"
"      t.name, substring(printf('%.*c%0.*d',nlz+1,'0',$1,t.cpos),2)),"
"     t.name"
"    )"
"    ="
"    iif(o.name IN (SELECT * FROM RepeatedNames),"
"     printf('%s"AUTOCOLUMN_SEP"%s',"
"      o.name, substring(printf('%.*c%0.*d',nlz+1,'0',$1,o.cpos),2)),"
"     o.name"
"    )"
"    COLLATE NOCASE"
"    AND o.cpos<>t.cpos"
"   GROUP BY t.cpos"
"  )"
") UPDATE Colnames AS t SET"
" chop = 0," /* No chopping, never touch incoming names. */
" suff = iif(name IN (SELECT * FROM RepeatedNames),"
"  printf('"AUTOCOLUMN_SEP"%s', substring("
"   printf('%.*c%0.*d',(SELECT max(nlz) FROM Lzn)+1,'0',1,t.cpos),2)),"
"  ''"
" )"
#endif
    ;
  static const char * const zCollectVar = "\
SELECT\
 '('||x'0a'\
 || group_concat(\
  cname||' TEXT',\
  ','||iif((cpos-1)%4>0, ' ', x'0a'||' '))\
 ||')' AS ColsSpec \
FROM (\
 SELECT cpos, printf('\"%w\"',printf('%!.*s%s', nlen-chop,name,suff)) AS cname \
 FROM ColNames ORDER BY cpos\
)";
  static const char * const zRenamesDone =
    "SELECT group_concat("
    " printf('\"%w\" to \"%w\"',name,printf('%!.*s%s', nlen-chop, name, suff)),"
    " ','||x'0a')"
    "FROM ColNames WHERE suff<>'' OR chop!=0"
    ;
  int rc;
  sqlite3_stmt *pStmt = 0;
  assert(pDb!=0);
  if( zColNew ){
    /* Add initial or additional column. Init db if necessary. */
    if( *pDb==0 ){
      if( SQLITE_OK!=sqlite3_open(zCOL_DB, pDb) ) return 0;
#ifdef SHELL_COLFIX_DB
      if(*zCOL_DB!=':')
        sqlite3_exec(*pDb,"drop table if exists ColNames;"
                     "drop view if exists RepeatedNames;",0,0,0);
#endif
      rc = sqlite3_exec(*pDb, zTabMake, 0, 0, 0);
      rc_err_oom_die(rc);
    }
    assert(*pDb!=0);
    rc = sqlite3_prepare_v2(*pDb, zTabFill, -1, &pStmt, 0);
    rc_err_oom_die(rc);
    rc = sqlite3_bind_text(pStmt, 1, zColNew, -1, 0);
    rc_err_oom_die(rc);
    rc = sqlite3_step(pStmt);
    rc_err_oom_die(rc);
    sqlite3_finalize(pStmt);
    return 0;
  }else if( *pDb==0 ){
    return 0;
  }else{
    /* Formulate the columns spec, close the DB, zero *pDb. */
    char *zColsSpec = 0;
    int hasDupes = db_int(*pDb, zHasDupes);
    int nDigits = (hasDupes)? db_int(*pDb, zColDigits) : 0;
    if( hasDupes ){
#ifdef SHELL_COLUMN_RENAME_CLEAN
      rc = sqlite3_exec(*pDb, zDedoctor, 0, 0, 0);
      rc_err_oom_die(rc);
#endif
      rc = sqlite3_exec(*pDb, zSetReps, 0, 0, 0);
      rc_err_oom_die(rc);
      rc = sqlite3_prepare_v2(*pDb, zRenameRank, -1, &pStmt, 0);
      rc_err_oom_die(rc);
      sqlite3_bind_int(pStmt, 1, nDigits);
      rc = sqlite3_step(pStmt);
      sqlite3_finalize(pStmt);
      assert(rc==SQLITE_DONE);
    }
    assert(db_int(*pDb, zHasDupes)==0); /* Consider: remove this */
    rc = sqlite3_prepare_v2(*pDb, zCollectVar, -1, &pStmt, 0);
    rc_err_oom_die(rc);
    rc = sqlite3_step(pStmt);
    if( rc==SQLITE_ROW ){
      zColsSpec = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
    }else{
      zColsSpec = 0;
    }
    if( pzRenamed!=0 ){
      if( !hasDupes ) *pzRenamed = 0;
      else{
        sqlite3_finalize(pStmt);
        if( SQLITE_OK==sqlite3_prepare_v2(*pDb, zRenamesDone, -1, &pStmt, 0)
            && SQLITE_ROW==sqlite3_step(pStmt) ){
          *pzRenamed = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
        }else
          *pzRenamed = 0;
      }
    }
    sqlite3_finalize(pStmt);
    sqlite3_close(*pDb);
    *pDb = 0;
    return zColsSpec;
  }
}

/*
** If an input line begins with "." then invoke this routine to
** process that line.
**
** Return 1 on error, 2 to exit, and 0 otherwise.
*/
static int do_meta_command(char *zLine, ShellState *p){
  int h = 1;
  int nArg = 0;
  int n, c;
  int rc = 0;
  char *azArg[50];
  char *azArg[52];

#ifndef SQLITE_OMIT_VIRTUALTABLE
  if( p->expert.pExpert ){
    expertFinish(p, 1, 0);
  }
#endif

  /* Parse the input line into tokens.
  */
  while( zLine[h] && nArg<ArraySize(azArg) ){
  while( zLine[h] && nArg<ArraySize(azArg)-1 ){
    while( IsSpace(zLine[h]) ){ h++; }
    if( zLine[h]==0 ) break;
    if( zLine[h]=='\'' || zLine[h]=='"' ){
      int delim = zLine[h++];
      azArg[nArg++] = &zLine[h];
      while( zLine[h] && zLine[h]!=delim ){
        if( zLine[h]=='\\' && delim=='"' && zLine[h+1]!=0 ) h++;
        h++;
      }
      if( zLine[h]==delim ){
        zLine[h++] = 0;
      }
      if( delim=='"' ) resolve_backslashes(azArg[nArg-1]);
    }else{
      azArg[nArg++] = &zLine[h];
      while( zLine[h] && !IsSpace(zLine[h]) ){ h++; }
      if( zLine[h] ) zLine[h++] = 0;
      resolve_backslashes(azArg[nArg-1]);
    }
  }
  azArg[nArg] = 0;

  /* Process the input line.
  */
  if( nArg==0 ) return 0; /* no tokens, no error */
  n = strlen30(azArg[0]);
  c = azArg[0][0];
  clearTempFile(p);

#ifndef SQLITE_OMIT_AUTHORIZATION
  if( c=='a' && strncmp(azArg[0], "auth", n)==0 ){
  if( c=='a' && cli_strncmp(azArg[0], "auth", n)==0 ){
    if( nArg!=2 ){
      raw_printf(stderr, "Usage: .auth ON|OFF\n");
      rc = 1;
      goto meta_command_exit;
    }
    open_db(p, 0);
    if( booleanValue(azArg[1]) ){
      sqlite3_set_authorizer(p->db, shellAuth, p);
    }else if( p->bSafeModePersist ){
      sqlite3_set_authorizer(p->db, safeModeAuth, p);
    }else{
      sqlite3_set_authorizer(p->db, 0, 0);
    }
  }else
#endif

#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
  if( c=='a' && strncmp(azArg[0], "archive", n)==0 ){
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) \
  && !defined(SQLITE_SHELL_FIDDLE)
  if( c=='a' && cli_strncmp(azArg[0], "archive", n)==0 ){
    open_db(p, 0);
    failIfSafeMode(p, "cannot run .archive in safe mode");
    rc = arDotCommand(p, 0, azArg, nArg);
  }else
#endif

#ifndef SQLITE_SHELL_FIDDLE
  if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0)
   || (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0)
  if( (c=='b' && n>=3 && cli_strncmp(azArg[0], "backup", n)==0)
   || (c=='s' && n>=3 && cli_strncmp(azArg[0], "save", n)==0)
  ){
    const char *zDestFile = 0;
    const char *zDb = 0;
    sqlite3 *pDest;
    sqlite3_backup *pBackup;
    int j;
    int bAsync = 0;
    const char *zVfs = 0;
    failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
    for(j=1; j<nArg; j++){
      const char *z = azArg[j];
      if( z[0]=='-' ){
        if( z[1]=='-' ) z++;
        if( strcmp(z, "-append")==0 ){
        if( cli_strcmp(z, "-append")==0 ){
          zVfs = "apndvfs";
        }else
        if( strcmp(z, "-async")==0 ){
        if( cli_strcmp(z, "-async")==0 ){
          bAsync = 1;
        }else
        {
          utf8_printf(stderr, "unknown option: %s\n", azArg[j]);
          return 1;
        }
      }else if( zDestFile==0 ){
5972
5973
5974
5975
5976
5977
5978
5979

5980
5981
5982
5983
5984
5985
5986
7925
7926
7927
7928
7929
7930
7931

7932
7933
7934
7935
7936
7937
7938
7939







-
+







      }
    }
    if( zDestFile==0 ){
      raw_printf(stderr, "missing FILENAME argument on .backup\n");
      return 1;
    }
    if( zDb==0 ) zDb = "main";
    rc = sqlite3_open_v2(zDestFile, &pDest, 
    rc = sqlite3_open_v2(zDestFile, &pDest,
                  SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs);
    if( rc!=SQLITE_OK ){
      utf8_printf(stderr, "Error: cannot open \"%s\"\n", zDestFile);
      close_db(pDest);
      return 1;
    }
    if( bAsync ){
6000
6001
6002
6003
6004
6005
6006

6007
6008

6009
6010
6011
6012
6013
6014
6015
6016
6017

6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029








6030


6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048

6049
6050
6051
6052
6053
6054
6055
6056

6057
6058
6059
6060
6061
6062
6063
6064

6065
6066
6067
6068
6069

6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088

6089

6090


6091
6092
6093
6094
6095
6096
6097

6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111























































6112
6113











6114















6115
6116
6117

6118
6119
6120
6121



6122
6123
6124
6125
6126
6127
6128
6129
6130













6131
6132
6133
6134
6135

6136
6137
6138
6139
6140

6141
6142
6143
6144
6145
6146

6147
6148

6149

6150
6151
6152






6153
6154



6155
6156
6157

6158


6159
6160
6161
6162
6163

6164
6165
6166
6167

6168
6169
6170
6171
6172
6173

6174
6175






6176
6177
6178

6179
6180
6181
6182
6183
6184















6185
6186
6187
6188
6189








6190


6191
6192
6193
6194
6195






6196
6197
6198
6199

6200
6201
6202
6203

6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223










6224
6225
6226
6227
6228
6229






6230
6231

6232
6233
6234
6235
6236
6237

6238


6239
6240
6241
6242
6243

6244
6245
6246
6247
6248
6249
6250
6251
6252

6253
6254




6255

6256
6257

6258

6259

6260
6261







6262
6263
6264
6265
6266

6267
6268
6269
6270

6271

6272
6273
6274

6275
6276
6277
6278

6279
6280
6281

6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303










6304
6305
6306



















































































































































6307

6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328


6329
6330
6331


6332
6333
6334
6335
6336

6337
6338
6339
6340
6341
6342
6343
6344
6345

6346
6347
6348
6349
6350

6351
6352
6353
6354
6355


6356
6357
6358
6359

6360
6361

6362
6363
6364
6365
6366
6367
6368

6369
6370
6371
6372
6373
6374
6375
6376
6377
6378

6379
6380
6381




6382
6383
6384
6385
6386
6387
6388

6389
6390
6391
6392


6393
6394
6395
6396
6397




6398
6399
6400


6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429





















































































6430
6431
6432
6433
6434
6435
6436

6437
6438
6439
6440

6441
6442
6443
6444

6445
6446
6447
6448
6449
6450
6451
6452
6453

6454



6455
6456
6457
6458
6459

























6460
6461
6462
6463
6464
6465



6466

6467
6468
6469

6470
6471
6472

6473










6474
6475
6476



6477
6478


6479
6480




6481
6482
6483
6484
6485
6486


6487
6488
6489


6490
6491
6492
6493
6494
6495
6496

6497
6498

6499
6500
6501
6502
6503
6504
6505

6506
6507
6508

6509
6510
6511
6512
6513
6514
6515



6516
6517
6518
6519
6520
6521

6522
6523


6524
6525
6526
6527
6528
6529
6530
7953
7954
7955
7956
7957
7958
7959
7960
7961

7962
7963
7964
7965
7966
7967
7968
7969
7970

7971
7972
7973
7974
7975
7976
7977
7978
7979
7980
7981
7982
7983
7984
7985
7986
7987
7988
7989
7990
7991

7992
7993
7994
7995
7996
7997
7998
7999
8000
8001
8002
8003
8004
8005
8006
8007
8008
8009
8010

8011






8012

8013
8014
8015
8016
8017
8018
8019
8020
8021
8022
8023
8024
8025
8026

8027
8028
8029
8030
8031
8032
8033
8034
8035
8036
8037
8038
8039
8040
8041
8042
8043
8044
8045
8046
8047
8048
8049

8050
8051
8052
8053
8054
8055
8056
8057
8058
8059
8060













8061
8062
8063
8064
8065
8066
8067
8068
8069
8070
8071
8072
8073
8074
8075
8076
8077
8078
8079
8080
8081
8082
8083
8084
8085
8086
8087
8088
8089
8090
8091
8092
8093
8094
8095
8096
8097
8098
8099
8100
8101
8102
8103
8104
8105
8106
8107
8108
8109
8110
8111
8112
8113
8114
8115

8116
8117
8118
8119
8120
8121
8122
8123
8124
8125
8126
8127
8128
8129
8130
8131
8132
8133
8134
8135
8136
8137
8138
8139
8140
8141
8142
8143
8144
8145

8146
8147
8148
8149
8150
8151
8152
8153









8154
8155
8156
8157
8158
8159
8160
8161
8162
8163
8164
8165
8166
8167
8168
8169
8170

8171
8172
8173
8174
8175

8176
8177
8178
8179
8180
8181

8182
8183
8184
8185

8186
8187
8188
8189
8190
8191
8192
8193
8194
8195


8196
8197
8198
8199
8200
8201
8202

8203
8204
8205
8206
8207
8208

8209
8210
8211
8212
8213
8214
8215
8216
8217
8218
8219

8220
8221
8222
8223
8224
8225
8226
8227
8228
8229
8230
8231
8232
8233
8234




8235
8236
8237
8238
8239
8240
8241
8242
8243
8244
8245
8246
8247
8248
8249





8250
8251
8252
8253
8254
8255
8256
8257
8258
8259
8260





8261
8262
8263
8264
8265
8266
8267
8268
8269

8270
8271
8272
8273

8274




















8275
8276
8277
8278
8279
8280
8281
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
8318
8319
8320
8321
8322
8323

8324
8325

8326
8327
8328

8329
8330
8331
8332
8333
8334
8335
8336
8337
8338
8339
8340
8341
8342

8343
8344
8345
8346
8347
8348

8349
8350
8351
8352
8353
8354
8355
8356

8357
8358
8359

8360
8361
8362
8363
8364
8365
8366
8367
8368
8369
8370
8371
8372
8373
8374
8375
8376
8377
8378
8379



8380
8381
8382
8383
8384
8385
8386
8387
8388
8389
8390
8391
8392
8393
8394
8395
8396
8397
8398
8399
8400
8401
8402
8403
8404
8405
8406
8407
8408
8409
8410
8411
8412
8413
8414
8415
8416
8417
8418
8419
8420
8421
8422
8423
8424
8425
8426
8427
8428
8429
8430
8431
8432
8433
8434
8435
8436
8437
8438
8439
8440
8441
8442
8443
8444
8445
8446
8447
8448
8449
8450
8451
8452
8453
8454
8455
8456
8457
8458
8459
8460
8461
8462
8463
8464
8465
8466
8467
8468
8469
8470
8471
8472
8473
8474
8475
8476
8477
8478
8479
8480
8481
8482
8483
8484
8485
8486
8487
8488
8489
8490
8491
8492
8493
8494
8495
8496
8497
8498
8499
8500
8501
8502
8503
8504
8505
8506
8507
8508
8509
8510
8511
8512
8513
8514
8515
8516
8517
8518
8519
8520
8521
8522
8523
8524
8525
8526
8527
8528
8529
8530
8531
8532
8533
8534
8535
8536
8537
8538
8539

8540
8541

8542
8543
8544
8545
8546
8547
8548
8549
8550
8551
8552
8553
8554
8555
8556
8557
8558


8559
8560
8561


8562
8563
8564
8565
8566
8567

8568
8569
8570
8571
8572
8573
8574
8575
8576

8577


8578
8579

8580


8581


8582
8583
8584
8585
8586

8587
8588
8589
8590
8591
8592
8593
8594
8595
8596

8597
8598
8599
8600
8601
8602
8603
8604
8605
8606
8607
8608



8609
8610
8611
8612
8613
8614
8615
8616
8617
8618
8619
8620
8621
8622


8623
8624





8625
8626
8627
8628


8629
8630
8631





























8632
8633
8634
8635
8636
8637
8638
8639
8640
8641
8642
8643
8644
8645
8646
8647
8648
8649
8650
8651
8652
8653
8654
8655
8656
8657
8658
8659
8660
8661
8662
8663
8664
8665
8666
8667
8668
8669
8670
8671
8672
8673
8674
8675
8676
8677
8678
8679
8680
8681
8682
8683
8684
8685
8686
8687
8688
8689
8690
8691
8692
8693
8694
8695
8696
8697
8698
8699
8700
8701
8702
8703
8704
8705
8706
8707
8708
8709
8710
8711
8712
8713
8714
8715
8716
8717
8718
8719
8720
8721
8722

8723
8724
8725
8726

8727
8728
8729
8730

8731





8732
8733
8734

8735
8736
8737
8738
8739





8740
8741
8742
8743
8744
8745
8746
8747
8748
8749
8750
8751
8752
8753
8754
8755
8756
8757
8758
8759
8760
8761
8762
8763
8764
8765
8766
8767
8768
8769
8770
8771
8772
8773

8774

8775

8776

8777
8778
8779

8780
8781
8782
8783
8784
8785
8786
8787
8788
8789
8790


8791
8792
8793


8794
8795
8796

8797
8798
8799
8800
8801

8802



8803
8804


8805
8806
8807
8808
8809

8810
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
8836

8837
8838
8839

8840

8841
8842
8843
8844
8845
8846
8847
8848
8849
8850







+

-
+








-
+












+
+
+
+
+
+
+
+
-
+
+

















-
+
-
-
-
-
-
-

-
+








+




-
+



















+

+
-
+
+







+

-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-

+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+




+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+




-
+




-
+





-
+


+
-
+



+
+
+
+
+
+
-
-
+
+
+



+
-
+
+




-
+




+





-
+


+
+
+
+
+
+



+


-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+

+
+
-
-
-
-
-
+
+
+
+
+
+



-
+



-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+
+


+






+
-
+
+




-
+








-
+


+
+
+
+
-
+

-
+

+
-
+


+
+
+
+
+
+
+




-
+




+
-
+



+



-
+


-
+



















-
-
-
+
+
+
+
+
+
+
+
+
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+

-

















-
-
+
+

-
-
+
+




-
+








-
+
-
-


-
+
-
-

-
-
+
+



-
+


+






-
+










+
-
-
-
+
+
+
+







+


-
-
+
+
-
-
-
-
-
+
+
+
+
-
-

+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
+



-
+



-
+
-
-
-
-
-



-
+

+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






+
+
+
-
+
-

-
+
-


+
-
+
+
+
+
+
+
+
+
+
+

-
-
+
+
+
-
-
+
+

-
+
+
+
+

-

-
-
-
+
+
-
-

+
+


-



-
+
-

+






-
+


-
+







+
+
+

-



-
+
-

+
+







      rc = 0;
    }else{
      utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
      rc = 1;
    }
    close_db(pDest);
  }else
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

  if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){
  if( c=='b' && n>=3 && cli_strncmp(azArg[0], "bail", n)==0 ){
    if( nArg==2 ){
      bail_on_error = booleanValue(azArg[1]);
    }else{
      raw_printf(stderr, "Usage: .bail on|off\n");
      rc = 1;
    }
  }else

  if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){
  if( c=='b' && n>=3 && cli_strncmp(azArg[0], "binary", n)==0 ){
    if( nArg==2 ){
      if( booleanValue(azArg[1]) ){
        setBinaryMode(p->out, 1);
      }else{
        setTextMode(p->out, 1);
      }
    }else{
      raw_printf(stderr, "Usage: .binary on|off\n");
      rc = 1;
    }
  }else

  /* The undocumented ".breakpoint" command causes a call to the no-op
  ** routine named test_breakpoint().
  */
  if( c=='b' && n>=3 && cli_strncmp(azArg[0], "breakpoint", n)==0 ){
    test_breakpoint();
  }else

#ifndef SQLITE_SHELL_FIDDLE
  if( c=='c' && strcmp(azArg[0],"cd")==0 ){
  if( c=='c' && cli_strcmp(azArg[0],"cd")==0 ){
    failIfSafeMode(p, "cannot run .cd in safe mode");
    if( nArg==2 ){
#if defined(_WIN32) || defined(WIN32)
      wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]);
      rc = !SetCurrentDirectoryW(z);
      sqlite3_free(z);
#else
      rc = chdir(azArg[1]);
#endif
      if( rc ){
        utf8_printf(stderr, "Cannot change to directory \"%s\"\n", azArg[1]);
        rc = 1;
      }
    }else{
      raw_printf(stderr, "Usage: .cd DIRECTORY\n");
      rc = 1;
    }
  }else

#endif /* !defined(SQLITE_SHELL_FIDDLE) */
  /* The undocumented ".breakpoint" command causes a call to the no-op
  ** routine named test_breakpoint().
  */
  if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){
    test_breakpoint();
  }else

  if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){
  if( c=='c' && n>=3 && cli_strncmp(azArg[0], "changes", n)==0 ){
    if( nArg==2 ){
      setOrClearFlag(p, SHFLG_CountChanges, azArg[1]);
    }else{
      raw_printf(stderr, "Usage: .changes on|off\n");
      rc = 1;
    }
  }else

#ifndef SQLITE_SHELL_FIDDLE
  /* Cancel output redirection, if it is currently set (by .testcase)
  ** Then read the content of the testcase-out.txt file and compare against
  ** azArg[1].  If there are differences, report an error and exit.
  */
  if( c=='c' && n>=3 && strncmp(azArg[0], "check", n)==0 ){
  if( c=='c' && n>=3 && cli_strncmp(azArg[0], "check", n)==0 ){
    char *zRes = 0;
    output_reset(p);
    if( nArg!=2 ){
      raw_printf(stderr, "Usage: .check GLOB-PATTERN\n");
      rc = 2;
    }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){
      raw_printf(stderr, "Error: cannot read 'testcase-out.txt'\n");
      rc = 2;
    }else if( testcase_glob(azArg[1],zRes)==0 ){
      utf8_printf(stderr,
                 "testcase-%s FAILED\n Expected: [%s]\n      Got: [%s]\n",
                 p->zTestcase, azArg[1], zRes);
      rc = 1;
    }else{
      utf8_printf(stdout, "testcase-%s ok\n", p->zTestcase);
      p->nCheck++;
    }
    sqlite3_free(zRes);
  }else
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

#ifndef SQLITE_SHELL_FIDDLE
  if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){
  if( c=='c' && cli_strncmp(azArg[0], "clone", n)==0 ){
    failIfSafeMode(p, "cannot run .clone in safe mode");
    if( nArg==2 ){
      tryToClone(p, azArg[1]);
    }else{
      raw_printf(stderr, "Usage: .clone FILENAME\n");
      rc = 1;
    }
  }else
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

  if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
    ShellState data;
    char *zErrMsg = 0;
    open_db(p, 0);
    memcpy(&data, p, sizeof(data));
    data.showHeader = 0;
    data.cMode = data.mode = MODE_List;
    sqlite3_snprintf(sizeof(data.colSeparator),data.colSeparator,": ");
    data.cnt = 0;
    sqlite3_exec(p->db, "SELECT name, file FROM pragma_database_list",
                 callback, &data, &zErrMsg);
    if( zErrMsg ){
      utf8_printf(stderr,"Error: %s\n", zErrMsg);
  if( c=='c' && cli_strncmp(azArg[0], "connection", n)==0 ){
    if( nArg==1 ){
      /* List available connections */
      int i;
      for(i=0; i<ArraySize(p->aAuxDb); i++){
        const char *zFile = p->aAuxDb[i].zDbFilename;
        if( p->aAuxDb[i].db==0 && p->pAuxDb!=&p->aAuxDb[i] ){
          zFile = "(not open)";
        }else if( zFile==0 ){
          zFile = "(memory)";
        }else if( zFile[0]==0 ){
          zFile = "(temporary-file)";
        }
        if( p->pAuxDb == &p->aAuxDb[i] ){
          utf8_printf(stdout, "ACTIVE %d: %s\n", i, zFile);
        }else if( p->aAuxDb[i].db!=0 ){
          utf8_printf(stdout, "       %d: %s\n", i, zFile);
        }
      }
    }else if( nArg==2 && IsDigit(azArg[1][0]) && azArg[1][1]==0 ){
      int i = azArg[1][0] - '0';
      if( p->pAuxDb != &p->aAuxDb[i] && i>=0 && i<ArraySize(p->aAuxDb) ){
        p->pAuxDb->db = p->db;
        p->pAuxDb = &p->aAuxDb[i];
        globalDb = p->db = p->pAuxDb->db;
        p->pAuxDb->db = 0;
      }
    }else if( nArg==3 && cli_strcmp(azArg[1], "close")==0
           && IsDigit(azArg[2][0]) && azArg[2][1]==0 ){
      int i = azArg[2][0] - '0';
      if( i<0 || i>=ArraySize(p->aAuxDb) ){
        /* No-op */
      }else if( p->pAuxDb == &p->aAuxDb[i] ){
        raw_printf(stderr, "cannot close the active database connection\n");
        rc = 1;
      }else if( p->aAuxDb[i].db ){
        session_close_all(p, i);
        close_db(p->aAuxDb[i].db);
        p->aAuxDb[i].db = 0;
      }
    }else{
      raw_printf(stderr, "Usage: .connection [close] [CONNECTION-NUMBER]\n");
      rc = 1;
    }
  }else

  if( c=='d' && n>1 && cli_strncmp(azArg[0], "databases", n)==0 ){
    char **azName = 0;
    int nName = 0;
    sqlite3_stmt *pStmt;
    int i;
    open_db(p, 0);
    rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
    if( rc ){
      utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
      sqlite3_free(zErrMsg);
      rc = 1;
    }else{
      while( sqlite3_step(pStmt)==SQLITE_ROW ){
        const char *zSchema = (const char *)sqlite3_column_text(pStmt,1);
        const char *zFile = (const char*)sqlite3_column_text(pStmt,2);
        if( zSchema==0 || zFile==0 ) continue;
        azName = sqlite3_realloc(azName, (nName+1)*2*sizeof(char*));
        shell_check_oom(azName);
        azName[nName*2] = strdup(zSchema);
        azName[nName*2+1] = strdup(zFile);
        nName++;
      }
    }
    sqlite3_finalize(pStmt);
    for(i=0; i<nName; i++){
      int eTxn = sqlite3_txn_state(p->db, azName[i*2]);
      int bRdonly = sqlite3_db_readonly(p->db, azName[i*2]);
      const char *z = azName[i*2+1];
      utf8_printf(p->out, "%s: %s %s%s\n",
         azName[i*2],
         z && z[0] ? z : "\"\"",
         bRdonly ? "r/o" : "r/w",
         eTxn==SQLITE_TXN_NONE ? "" :
            eTxn==SQLITE_TXN_READ ? " read-txn" : " write-txn");
      free(azName[i*2]);
      free(azName[i*2+1]);
    }
    sqlite3_free(azName);
  }else

  if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){
  if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbconfig", n)==0 ){
    static const struct DbConfigChoices {
      const char *zName;
      int op;
    } aDbConfig[] = {
        { "defensive",          SQLITE_DBCONFIG_DEFENSIVE             },
        { "dqs_ddl",            SQLITE_DBCONFIG_DQS_DDL               },
        { "dqs_dml",            SQLITE_DBCONFIG_DQS_DML               },
        { "enable_fkey",      SQLITE_DBCONFIG_ENABLE_FKEY            },
        { "enable_trigger",   SQLITE_DBCONFIG_ENABLE_TRIGGER         },
        { "fts3_tokenizer",   SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER  },
        { "load_extension",   SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION  },
        { "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE       },
        { "enable_qpsg",      SQLITE_DBCONFIG_ENABLE_QPSG            },
        { "trigger_eqp",      SQLITE_DBCONFIG_TRIGGER_EQP            },
        { "reset_database",   SQLITE_DBCONFIG_RESET_DATABASE         },
        { "defensive",        SQLITE_DBCONFIG_DEFENSIVE              },
        { "enable_fkey",        SQLITE_DBCONFIG_ENABLE_FKEY           },
        { "enable_qpsg",        SQLITE_DBCONFIG_ENABLE_QPSG           },
        { "enable_trigger",     SQLITE_DBCONFIG_ENABLE_TRIGGER        },
        { "enable_view",        SQLITE_DBCONFIG_ENABLE_VIEW           },
        { "fts3_tokenizer",     SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
        { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE    },
        { "legacy_file_format", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT    },
        { "load_extension",     SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
        { "no_ckpt_on_close",   SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE      },
        { "reset_database",     SQLITE_DBCONFIG_RESET_DATABASE        },
        { "trigger_eqp",        SQLITE_DBCONFIG_TRIGGER_EQP           },
        { "trusted_schema",     SQLITE_DBCONFIG_TRUSTED_SCHEMA        },
        { "writable_schema",    SQLITE_DBCONFIG_WRITABLE_SCHEMA       },
    };
    int ii, v;
    open_db(p, 0);
    for(ii=0; ii<ArraySize(aDbConfig); ii++){
      if( nArg>1 && strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue;
      if( nArg>1 && cli_strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue;
      if( nArg>=3 ){
        sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
      }
      sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v);
      utf8_printf(p->out, "%18s %s\n", aDbConfig[ii].zName, v ? "on" : "off");
      utf8_printf(p->out, "%19s %s\n", aDbConfig[ii].zName, v ? "on" : "off");
      if( nArg>1 ) break;
    }
    if( nArg>1 && ii==ArraySize(aDbConfig) ){
      utf8_printf(stderr, "Error: unknown dbconfig \"%s\"\n", azArg[1]);
      utf8_printf(stderr, "Enter \".dbconfig\" with no arguments for a list\n");
    }   
    }
  }else

#if SQLITE_SHELL_HAVE_RECOVER
  if( c=='d' && n>=3 && strncmp(azArg[0], "dbinfo", n)==0 ){
  if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbinfo", n)==0 ){
    rc = shell_dbinfo_command(p, nArg, azArg);
  }else

  if( c=='r' && cli_strncmp(azArg[0], "recover", n)==0 ){
    open_db(p, 0);
    rc = recoverDatabaseCmd(p, nArg, azArg);
  }else
#endif /* SQLITE_SHELL_HAVE_RECOVER */

  if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
    const char *zLike = 0;
  if( c=='d' && cli_strncmp(azArg[0], "dump", n)==0 ){
    char *zLike = 0;
    char *zSql;
    int i;
    int savedShowHeader = p->showHeader;
    int savedShellFlags = p->shellFlgs;
    ShellClearFlag(p,
    ShellClearFlag(p, SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo);
       SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo
       |SHFLG_DumpDataOnly|SHFLG_DumpNoSys);
    for(i=1; i<nArg; i++){
      if( azArg[i][0]=='-' ){
        const char *z = azArg[i]+1;
        if( z[0]=='-' ) z++;
        if( strcmp(z,"preserve-rowids")==0 ){
        if( cli_strcmp(z,"preserve-rowids")==0 ){
#ifdef SQLITE_OMIT_VIRTUALTABLE
          raw_printf(stderr, "The --preserve-rowids option is not compatible"
                             " with SQLITE_OMIT_VIRTUALTABLE\n");
          rc = 1;
          sqlite3_free(zLike);
          goto meta_command_exit;
#else
          ShellSetFlag(p, SHFLG_PreserveRowid);
#endif
        }else
        if( strcmp(z,"newlines")==0 ){
        if( cli_strcmp(z,"newlines")==0 ){
          ShellSetFlag(p, SHFLG_Newlines);
        }else
        if( cli_strcmp(z,"data-only")==0 ){
          ShellSetFlag(p, SHFLG_DumpDataOnly);
        }else
        if( cli_strcmp(z,"nosys")==0 ){
          ShellSetFlag(p, SHFLG_DumpNoSys);
        }else
        {
          raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
          rc = 1;
          sqlite3_free(zLike);
          goto meta_command_exit;
        }
      }else if( zLike ){
        raw_printf(stderr, "Usage: .dump ?--preserve-rowids? "
                           "?--newlines? ?LIKE-PATTERN?\n");
        rc = 1;
      }else{
        /* azArg[i] contains a LIKE pattern. This ".dump" request should
        ** only dump data for tables for which either the table name matches
        ** the LIKE pattern, or the table appears to be a shadow table of
        ** a virtual table for which the name matches the LIKE pattern.
        */
        char *zExpr = sqlite3_mprintf(
            "name LIKE %Q ESCAPE '\\' OR EXISTS ("
            "  SELECT 1 FROM sqlite_schema WHERE "
            "    name LIKE %Q ESCAPE '\\' AND"
            "    sql LIKE 'CREATE VIRTUAL TABLE%%' AND"
            "    substr(o.name, 1, length(name)+1) == (name||'_')"
            ")", azArg[i], azArg[i]
        );

        goto meta_command_exit;
      }else{
        zLike = azArg[i];
      }
    }
        if( zLike ){
          zLike = sqlite3_mprintf("%z OR %z", zLike, zExpr);
        }else{
          zLike = zExpr;
        }
      }
    }

    open_db(p, 0);

    if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
    /* When playing back a "dump", the content might appear in an order
    ** which causes immediate foreign key constraints to be violated.
    ** So disable foreign-key constraint enforcement to prevent problems. */
    raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
    raw_printf(p->out, "BEGIN TRANSACTION;\n");
      /* When playing back a "dump", the content might appear in an order
      ** which causes immediate foreign key constraints to be violated.
      ** So disable foreign-key constraint enforcement to prevent problems. */
      raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
      raw_printf(p->out, "BEGIN TRANSACTION;\n");
    }
    p->writableSchema = 0;
    p->showHeader = 0;
    /* Set writable_schema=ON since doing so forces SQLite to initialize
    ** as much of the schema as it can even if the sqlite_master table is
    ** as much of the schema as it can even if the sqlite_schema table is
    ** corrupt. */
    sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
    p->nErr = 0;
    if( zLike==0 ){
    if( zLike==0 ) zLike = sqlite3_mprintf("true");
      run_schema_dump_query(p,
        "SELECT name, type, sql FROM sqlite_master "
        "WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'"
      );
      run_schema_dump_query(p,
        "SELECT name, type, sql FROM sqlite_master "
        "WHERE name=='sqlite_sequence'"
      );
      run_table_dump_query(p,
        "SELECT sql FROM sqlite_master "
        "WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0
      );
    }else{
      char *zSql;
      zSql = sqlite3_mprintf(
        "SELECT name, type, sql FROM sqlite_master "
        "WHERE tbl_name LIKE %Q AND type=='table'"
        "  AND sql NOT NULL", zLike);
      run_schema_dump_query(p,zSql);
      sqlite3_free(zSql);
    zSql = sqlite3_mprintf(
      "SELECT name, type, sql FROM sqlite_schema AS o "
      "WHERE (%s) AND type=='table'"
      "  AND sql NOT NULL"
      " ORDER BY tbl_name='sqlite_sequence', rowid",
      zLike
    );
    run_schema_dump_query(p,zSql);
    sqlite3_free(zSql);
    if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
      zSql = sqlite3_mprintf(
        "SELECT sql FROM sqlite_master "
        "WHERE sql NOT NULL"
        "  AND type IN ('index','trigger','view')"
        "  AND tbl_name LIKE %Q", zLike);
      run_table_dump_query(p, zSql, 0);
        "SELECT sql FROM sqlite_schema AS o "
        "WHERE (%s) AND sql NOT NULL"
        "  AND type IN ('index','trigger','view')",
        zLike
      );
      run_table_dump_query(p, zSql);
      sqlite3_free(zSql);
    }
    sqlite3_free(zLike);
    if( p->writableSchema ){
      raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
      p->writableSchema = 0;
    }
    sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
    sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
    if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
    raw_printf(p->out, p->nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n");
      raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
    }
    p->showHeader = savedShowHeader;
    p->shellFlgs = savedShellFlags;
  }else

  if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){
  if( c=='e' && cli_strncmp(azArg[0], "echo", n)==0 ){
    if( nArg==2 ){
      setOrClearFlag(p, SHFLG_Echo, azArg[1]);
    }else{
      raw_printf(stderr, "Usage: .echo on|off\n");
      rc = 1;
    }
  }else

  if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){
  if( c=='e' && cli_strncmp(azArg[0], "eqp", n)==0 ){
    if( nArg==2 ){
      p->autoEQPtest = 0;
      if( p->autoEQPtrace ){
        if( p->db ) sqlite3_exec(p->db, "PRAGMA vdbe_trace=OFF;", 0, 0, 0);
        p->autoEQPtrace = 0;
      }
      if( strcmp(azArg[1],"full")==0 ){
      if( cli_strcmp(azArg[1],"full")==0 ){
        p->autoEQP = AUTOEQP_full;
      }else if( strcmp(azArg[1],"trigger")==0 ){
      }else if( cli_strcmp(azArg[1],"trigger")==0 ){
        p->autoEQP = AUTOEQP_trigger;
#ifdef SQLITE_DEBUG
      }else if( strcmp(azArg[1],"test")==0 ){
      }else if( cli_strcmp(azArg[1],"test")==0 ){
        p->autoEQP = AUTOEQP_on;
        p->autoEQPtest = 1;
      }else if( cli_strcmp(azArg[1],"trace")==0 ){
        p->autoEQP = AUTOEQP_full;
        p->autoEQPtrace = 1;
        open_db(p, 0);
        sqlite3_exec(p->db, "SELECT name FROM sqlite_schema LIMIT 1", 0, 0, 0);
        sqlite3_exec(p->db, "PRAGMA vdbe_trace=ON;", 0, 0, 0);
#endif
      }else{
        p->autoEQP = (u8)booleanValue(azArg[1]);
      }
    }else{
      raw_printf(stderr, "Usage: .eqp off|on|trigger|full\n");
      raw_printf(stderr, "Usage: .eqp off|on|trace|trigger|full\n");
      rc = 1;
    }
  }else

#ifndef SQLITE_SHELL_FIDDLE
  if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
  if( c=='e' && cli_strncmp(azArg[0], "exit", n)==0 ){
    if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
    rc = 2;
  }else
#endif

  /* The ".explain" command is automatic now.  It is largely pointless.  It
  ** retained purely for backwards compatibility */
  if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
  if( c=='e' && cli_strncmp(azArg[0], "explain", n)==0 ){
    int val = 1;
    if( nArg>=2 ){
      if( strcmp(azArg[1],"auto")==0 ){
      if( cli_strcmp(azArg[1],"auto")==0 ){
        val = 99;
      }else{
        val =  booleanValue(azArg[1]);
      }
    }
    if( val==1 && p->mode!=MODE_Explain ){
      p->normalMode = p->mode;
      p->mode = MODE_Explain;
      p->autoExplain = 0;
    }else if( val==0 ){
      if( p->mode==MODE_Explain ) p->mode = p->normalMode;
      p->autoExplain = 0;
    }else if( val==99 ){
      if( p->mode==MODE_Explain ) p->mode = p->normalMode;
      p->autoExplain = 1;
    }
  }else

#ifndef SQLITE_OMIT_VIRTUALTABLE
  if( c=='e' && strncmp(azArg[0], "expert", n)==0 ){
    open_db(p, 0);
    expertDotCommand(p, azArg, nArg);
  if( c=='e' && cli_strncmp(azArg[0], "expert", n)==0 ){
    if( p->bSafeMode ){
      raw_printf(stderr,
        "Cannot run experimental commands such as \"%s\" in safe mode\n",
        azArg[0]);
      rc = 1;
    }else{
      open_db(p, 0);
      expertDotCommand(p, azArg, nArg);
    }
  }else
#endif

  if( c=='f' && cli_strncmp(azArg[0], "filectrl", n)==0 ){
    static const struct {
       const char *zCtrlName;   /* Name of a test-control option */
       int ctrlCode;            /* Integer code for that option */
       const char *zUsage;      /* Usage notes */
    } aCtrl[] = {
      { "chunk_size",     SQLITE_FCNTL_CHUNK_SIZE,      "SIZE"           },
      { "data_version",   SQLITE_FCNTL_DATA_VERSION,    ""               },
      { "has_moved",      SQLITE_FCNTL_HAS_MOVED,       ""               },
      { "lock_timeout",   SQLITE_FCNTL_LOCK_TIMEOUT,    "MILLISEC"       },
      { "persist_wal",    SQLITE_FCNTL_PERSIST_WAL,     "[BOOLEAN]"      },
   /* { "pragma",         SQLITE_FCNTL_PRAGMA,          "NAME ARG"       },*/
      { "psow",       SQLITE_FCNTL_POWERSAFE_OVERWRITE, "[BOOLEAN]"      },
      { "reserve_bytes",  SQLITE_FCNTL_RESERVE_BYTES,   "[N]"            },
      { "size_limit",     SQLITE_FCNTL_SIZE_LIMIT,      "[LIMIT]"        },
      { "tempfilename",   SQLITE_FCNTL_TEMPFILENAME,    ""               },
   /* { "win32_av_retry", SQLITE_FCNTL_WIN32_AV_RETRY,  "COUNT DELAY"    },*/
    };
    int filectrl = -1;
    int iCtrl = -1;
    sqlite3_int64 iRes = 0;  /* Integer result to display if rc2==1 */
    int isOk = 0;            /* 0: usage  1: %lld  2: no-result */
    int n2, i;
    const char *zCmd = 0;
    const char *zSchema = 0;

    open_db(p, 0);
    zCmd = nArg>=2 ? azArg[1] : "help";

    if( zCmd[0]=='-'
     && (cli_strcmp(zCmd,"--schema")==0 || cli_strcmp(zCmd,"-schema")==0)
     && nArg>=4
    ){
      zSchema = azArg[2];
      for(i=3; i<nArg; i++) azArg[i-2] = azArg[i];
      nArg -= 2;
      zCmd = azArg[1];
    }

    /* The argument can optionally begin with "-" or "--" */
    if( zCmd[0]=='-' && zCmd[1] ){
      zCmd++;
      if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
    }

    /* --help lists all file-controls */
    if( cli_strcmp(zCmd,"help")==0 ){
      utf8_printf(p->out, "Available file-controls:\n");
      for(i=0; i<ArraySize(aCtrl); i++){
        utf8_printf(p->out, "  .filectrl %s %s\n",
                    aCtrl[i].zCtrlName, aCtrl[i].zUsage);
      }
      rc = 1;
      goto meta_command_exit;
    }

    /* convert filectrl text option to value. allow any unique prefix
    ** of the option name, or a numerical value. */
    n2 = strlen30(zCmd);
    for(i=0; i<ArraySize(aCtrl); i++){
      if( cli_strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
        if( filectrl<0 ){
          filectrl = aCtrl[i].ctrlCode;
          iCtrl = i;
        }else{
          utf8_printf(stderr, "Error: ambiguous file-control: \"%s\"\n"
                              "Use \".filectrl --help\" for help\n", zCmd);
          rc = 1;
          goto meta_command_exit;
        }
      }
    }
    if( filectrl<0 ){
      utf8_printf(stderr,"Error: unknown file-control: %s\n"
                         "Use \".filectrl --help\" for help\n", zCmd);
    }else{
      switch(filectrl){
        case SQLITE_FCNTL_SIZE_LIMIT: {
          if( nArg!=2 && nArg!=3 ) break;
          iRes = nArg==3 ? integerValue(azArg[2]) : -1;
          sqlite3_file_control(p->db, zSchema, SQLITE_FCNTL_SIZE_LIMIT, &iRes);
          isOk = 1;
          break;
        }
        case SQLITE_FCNTL_LOCK_TIMEOUT:
        case SQLITE_FCNTL_CHUNK_SIZE: {
          int x;
          if( nArg!=3 ) break;
          x = (int)integerValue(azArg[2]);
          sqlite3_file_control(p->db, zSchema, filectrl, &x);
          isOk = 2;
          break;
        }
        case SQLITE_FCNTL_PERSIST_WAL:
        case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
          int x;
          if( nArg!=2 && nArg!=3 ) break;
          x = nArg==3 ? booleanValue(azArg[2]) : -1;
          sqlite3_file_control(p->db, zSchema, filectrl, &x);
          iRes = x;
          isOk = 1;
          break;
        }
        case SQLITE_FCNTL_DATA_VERSION:
        case SQLITE_FCNTL_HAS_MOVED: {
          int x;
          if( nArg!=2 ) break;
          sqlite3_file_control(p->db, zSchema, filectrl, &x);
          iRes = x;
          isOk = 1;
          break;
        }
        case SQLITE_FCNTL_TEMPFILENAME: {
          char *z = 0;
          if( nArg!=2 ) break;
          sqlite3_file_control(p->db, zSchema, filectrl, &z);
          if( z ){
            utf8_printf(p->out, "%s\n", z);
            sqlite3_free(z);
          }
          isOk = 2;
          break;
        }
        case SQLITE_FCNTL_RESERVE_BYTES: {
          int x;
          if( nArg>=3 ){
            x = atoi(azArg[2]);
            sqlite3_file_control(p->db, zSchema, filectrl, &x);
          }
          x = -1;
          sqlite3_file_control(p->db, zSchema, filectrl, &x);
          utf8_printf(p->out,"%d\n", x);
          isOk = 2;
          break;
        }
      }
    }
    if( isOk==0 && iCtrl>=0 ){
      utf8_printf(p->out, "Usage: .filectrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
      rc = 1;
    }else if( isOk==1 ){
      char zBuf[100];
      sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", iRes);
      raw_printf(p->out, "%s\n", zBuf);
    }
  }else

  if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){
  if( c=='f' && cli_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;
    }
    if( nArg!=1 ){
      raw_printf(stderr, "Usage: .fullschema ?--indent?\n");
      rc = 1;
      goto meta_command_exit;
    }
    open_db(p, 0);
    rc = sqlite3_exec(p->db,
       "SELECT sql FROM"
       "  (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
       "     FROM sqlite_master UNION ALL"
       "   SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) "
       "     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
       "ORDER BY x",
       callback, &data, 0
    );
    if( rc==SQLITE_OK ){
      sqlite3_stmt *pStmt;
      rc = sqlite3_prepare_v2(p->db,
               "SELECT rowid FROM sqlite_master"
               "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_master;\n");
      raw_printf(p->out, "ANALYZE sqlite_schema;\n");
      sqlite3_exec(p->db, "SELECT 'ANALYZE sqlite_master'",
                   callback, &data, &zErrMsg);
      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_stat3";
      shell_exec(&data, "SELECT * FROM sqlite_stat3", &zErrMsg);
      data.zDestTable = "sqlite_stat4";
      shell_exec(&data, "SELECT * FROM sqlite_stat4", &zErrMsg);
      raw_printf(p->out, "ANALYZE sqlite_master;\n");
      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( c=='h' && cli_strncmp(azArg[0], "headers", n)==0 ){
    if( nArg==2 ){
      p->showHeader = booleanValue(azArg[1]);
      p->shellFlgs |= SHFLG_HeaderSet;
    }else{
      raw_printf(stderr, "Usage: .headers on|off\n");
      rc = 1;
    }
  }else

  if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
  if( c=='h' && cli_strncmp(azArg[0], "help", n)==0 ){
    if( nArg>=2 ){
      n = showHelp(p->out, azArg[1]);
      if( n==0 ){
        utf8_printf(p->out, "Nothing matches '%s'\n", azArg[1]);
      }
    }else{
      showHelp(p->out, 0);
    }
  }else

#ifndef SQLITE_SHELL_FIDDLE
  if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
    char *zTable;               /* Insert data into this table */
    char *zFile;                /* Name of file to extra content from */
  if( c=='i' && cli_strncmp(azArg[0], "import", n)==0 ){
    char *zTable = 0;           /* Insert data into this table */
    char *zSchema = 0;          /* within this schema (may default to "main") */
    char *zFile = 0;            /* Name of file to extra content from */
    sqlite3_stmt *pStmt = NULL; /* A statement */
    int nCol;                   /* Number of columns in the table */
    int nByte;                  /* Number of bytes in an SQL string */
    int i, j;                   /* Loop counters */
    int needCommit;             /* True to COMMIT or ROLLBACK at end */
    int nSep;                   /* Number of bytes in p->colSeparator[] */
    char *zSql;                 /* An SQL statement */
    char *zFullTabName;         /* Table name with schema if applicable */
    ImportCtx sCtx;             /* Reader context */
    char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
    int (SQLITE_CDECL *xCloser)(FILE*);      /* Func to close file */

    int eVerbose = 0;           /* Larger for more console output */
    int nSkip = 0;              /* Initial lines to skip */
    if( nArg!=3 ){
      raw_printf(stderr, "Usage: .import FILE TABLE\n");
      goto meta_command_exit;
    }
    zFile = azArg[1];
    int useOutputMode = 1;      /* Use output mode to determine separators */
    char *zCreate = 0;          /* CREATE TABLE statement text */

    failIfSafeMode(p, "cannot run .import in safe mode");
    zTable = azArg[2];
    seenInterrupt = 0;
    memset(&sCtx, 0, sizeof(sCtx));
    if( p->mode==MODE_Ascii ){
      xRead = ascii_read_one_field;
    open_db(p, 0);
    nSep = strlen30(p->colSeparator);
    if( nSep==0 ){
      raw_printf(stderr,
                 "Error: non-null column separator required for import\n");
      return 1;
    }
    if( nSep>1 ){
      raw_printf(stderr, "Error: multi-character column separators not allowed"
                      " for import\n");
      return 1;
    }
    nSep = strlen30(p->rowSeparator);
    if( nSep==0 ){
      raw_printf(stderr, "Error: non-null row separator required for import\n");
      return 1;
    }
    if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator, SEP_CrLf)==0 ){
      /* When importing CSV (only), if the row separator is set to the
      ** default output row separator, change it to the default input
      ** row separator.  This avoids having to maintain different input
      ** and output row separators. */
      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
      nSep = strlen30(p->rowSeparator);
    }
    if( nSep>1 ){
      raw_printf(stderr, "Error: multi-character row separators not allowed"
                      " for import\n");
      return 1;
    }else{
      xRead = csv_read_one_field;
    }
    rc = 1;
    for(i=1; i<nArg; i++){
      char *z = azArg[i];
      if( z[0]=='-' && z[1]=='-' ) z++;
      if( z[0]!='-' ){
        if( zFile==0 ){
          zFile = z;
        }else if( zTable==0 ){
          zTable = z;
        }else{
          utf8_printf(p->out, "ERROR: extra argument: \"%s\".  Usage:\n", z);
          showHelp(p->out, "import");
          goto meta_command_exit;
        }
      }else if( cli_strcmp(z,"-v")==0 ){
        eVerbose++;
      }else if( cli_strcmp(z,"-schema")==0 && i<nArg-1 ){
        zSchema = azArg[++i];
      }else if( cli_strcmp(z,"-skip")==0 && i<nArg-1 ){
        nSkip = integerValue(azArg[++i]);
      }else if( cli_strcmp(z,"-ascii")==0 ){
        sCtx.cColSep = SEP_Unit[0];
        sCtx.cRowSep = SEP_Record[0];
        xRead = ascii_read_one_field;
        useOutputMode = 0;
      }else if( cli_strcmp(z,"-csv")==0 ){
        sCtx.cColSep = ',';
        sCtx.cRowSep = '\n';
        xRead = csv_read_one_field;
        useOutputMode = 0;
      }else{
        utf8_printf(p->out, "ERROR: unknown option: \"%s\".  Usage:\n", z);
        showHelp(p->out, "import");
        goto meta_command_exit;
      }
    }
    if( zTable==0 ){
      utf8_printf(p->out, "ERROR: missing %s argument. Usage:\n",
                  zFile==0 ? "FILE" : "TABLE");
      showHelp(p->out, "import");
      goto meta_command_exit;
    }
    seenInterrupt = 0;
    open_db(p, 0);
    if( useOutputMode ){
      /* If neither the --csv or --ascii options are specified, then set
      ** the column and row separator characters from the output mode. */
      nSep = strlen30(p->colSeparator);
      if( nSep==0 ){
        raw_printf(stderr,
                   "Error: non-null column separator required for import\n");
        goto meta_command_exit;
      }
      if( nSep>1 ){
        raw_printf(stderr,
              "Error: multi-character column separators not allowed"
              " for import\n");
        goto meta_command_exit;
      }
      nSep = strlen30(p->rowSeparator);
      if( nSep==0 ){
        raw_printf(stderr,
            "Error: non-null row separator required for import\n");
        goto meta_command_exit;
      }
      if( nSep==2 && p->mode==MODE_Csv
       && cli_strcmp(p->rowSeparator,SEP_CrLf)==0
      ){
        /* When importing CSV (only), if the row separator is set to the
        ** default output row separator, change it to the default input
        ** row separator.  This avoids having to maintain different input
        ** and output row separators. */
        sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
        nSep = strlen30(p->rowSeparator);
      }
      if( nSep>1 ){
        raw_printf(stderr, "Error: multi-character row separators not allowed"
                           " for import\n");
        goto meta_command_exit;
      }
      sCtx.cColSep = p->colSeparator[0];
      sCtx.cRowSep = p->rowSeparator[0];
    }
    sCtx.zFile = zFile;
    sCtx.nLine = 1;
    if( sCtx.zFile[0]=='|' ){
#ifdef SQLITE_OMIT_POPEN
      raw_printf(stderr, "Error: pipes are not supported in this OS\n");
      return 1;
      goto meta_command_exit;
#else
      sCtx.in = popen(sCtx.zFile+1, "r");
      sCtx.zFile = "<pipe>";
      xCloser = pclose;
      sCtx.xCloser = pclose;
#endif
    }else{
      sCtx.in = fopen(sCtx.zFile, "rb");
      xCloser = fclose;
      sCtx.xCloser = fclose;
    }
    if( p->mode==MODE_Ascii ){
      xRead = ascii_read_one_field;
    }else{
      xRead = csv_read_one_field;
    }
    if( sCtx.in==0 ){
      utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
      return 1;
      goto meta_command_exit;
    }
    if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
      char zSep[2];
      zSep[1] = 0;
    sCtx.cColSep = p->colSeparator[0];
    sCtx.cRowSep = p->rowSeparator[0];
    zSql = sqlite3_mprintf("SELECT * FROM %s", zTable);
    if( zSql==0 ){
      xCloser(sCtx.in);
      zSep[0] = sCtx.cColSep;
      utf8_printf(p->out, "Column separator ");
      output_c_string(p->out, zSep);
      utf8_printf(p->out, ", row separator ");
      zSep[0] = sCtx.cRowSep;
      output_c_string(p->out, zSep);
      utf8_printf(p->out, "\n");
    }
    sCtx.z = sqlite3_malloc64(120);
    if( sCtx.z==0 ){
      import_cleanup(&sCtx);
      shell_out_of_memory();
    }
    /* Below, resources must be freed before exit. */
    while( (nSkip--)>0 ){
      while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
    }
    if( zSchema!=0 ){
      zFullTabName = sqlite3_mprintf("\"%w\".\"%w\"", zSchema, zTable);
    }else{
      zFullTabName = sqlite3_mprintf("\"%w\"", zTable);
    }
    zSql = sqlite3_mprintf("SELECT * FROM %s", zFullTabName);
    if( zSql==0 || zFullTabName==0 ){
      import_cleanup(&sCtx);
      shell_out_of_memory();
    }
    nByte = strlen30(zSql);
    rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
    import_append_char(&sCtx, 0);    /* To ensure sCtx.z is allocated */
    if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
      sqlite3 *dbCols = 0;
      char *zRenames = 0;
      char *zColDefs;
      char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable);
      zCreate = sqlite3_mprintf("CREATE TABLE %s", zFullTabName);
      char cSep = '(';
      while( xRead(&sCtx) ){
        zCreate = sqlite3_mprintf("%z%c\n  \"%w\" TEXT", zCreate, cSep, sCtx.z);
        zAutoColumn(sCtx.z, &dbCols, 0);
        cSep = ',';
        if( sCtx.cTerm!=sCtx.cColSep ) break;
      }
      zColDefs = zAutoColumn(0, &dbCols, &zRenames);
      if( cSep=='(' ){
      if( zRenames!=0 ){
        utf8_printf((stdin_is_interactive && p->in==stdin)? p->out : stderr,
                    "Columns renamed during .import %s due to duplicates:\n"
                    "%s\n", sCtx.zFile, zRenames);
        sqlite3_free(zRenames);
      }
      assert(dbCols==0);
      if( zColDefs==0 ){
        utf8_printf(stderr,"%s: empty file\n", sCtx.zFile);
      import_fail:
        sqlite3_free(zCreate);
        sqlite3_free(sCtx.z);
        xCloser(sCtx.in);
        sqlite3_free(zSql);
        sqlite3_free(zFullTabName);
        import_cleanup(&sCtx);
        utf8_printf(stderr,"%s: empty file\n", sCtx.zFile);
        return 1;
        rc = 1;
        goto meta_command_exit;
      }
      zCreate = sqlite3_mprintf("%z\n)", zCreate);
      zCreate = sqlite3_mprintf("%z%z\n", zCreate, zColDefs);
      if( eVerbose>=1 ){
        utf8_printf(p->out, "%s\n", zCreate);
      }
      rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
      sqlite3_free(zCreate);
      if( rc ){
        utf8_printf(stderr, "CREATE TABLE %s(...) failed: %s\n", zTable,
                sqlite3_errmsg(p->db));
        sqlite3_free(sCtx.z);
        utf8_printf(stderr, "%s failed:\n%s\n", zCreate, sqlite3_errmsg(p->db));
        goto import_fail;
        xCloser(sCtx.in);
        return 1;
      }
      sqlite3_free(zCreate);
      zCreate = 0;
      rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
    }
    sqlite3_free(zSql);
    if( rc ){
      if (pStmt) sqlite3_finalize(pStmt);
      utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
      xCloser(sCtx.in);
      goto import_fail;
      return 1;
    }
    sqlite3_free(zSql);
    nCol = sqlite3_column_count(pStmt);
    sqlite3_finalize(pStmt);
    pStmt = 0;
    if( nCol==0 ) return 0; /* no columns, no error */
    zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
    if( zSql==0 ){
      xCloser(sCtx.in);
      import_cleanup(&sCtx);
      shell_out_of_memory();
    }
    sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
    sqlite3_snprintf(nByte+20, zSql, "INSERT INTO %s VALUES(?", zFullTabName);
    j = strlen30(zSql);
    for(i=1; i<nCol; i++){
      zSql[j++] = ',';
      zSql[j++] = '?';
    }
    zSql[j++] = ')';
    zSql[j] = 0;
    if( eVerbose>=2 ){
      utf8_printf(p->out, "Insert using: %s\n", zSql);
    }
    rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
    sqlite3_free(zSql);
    if( rc ){
      utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
      if (pStmt) sqlite3_finalize(pStmt);
      xCloser(sCtx.in);
      goto import_fail;
      return 1;
    }
    sqlite3_free(zSql);
    sqlite3_free(zFullTabName);
    needCommit = sqlite3_get_autocommit(p->db);
    if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
    do{
      int startLine = sCtx.nLine;
      for(i=0; i<nCol; i++){
        char *z = xRead(&sCtx);
        /*
6558
6559
6560
6561
6562
6563
6564



6565
6566
6567
6568
6569

6570
6571
6572





6573

6574
6575
6576

6577
6578
6579
6580


6581
6582
6583
6584







6585
6586
6587
6588
6589
6590
6591
6592
6593
6594









6595
6596
6597
6598

6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610

6611
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621



6622
6623
6624
6625
6626
6627
6628







6629
6630
6631


6632
6633
6634
6635
6636
6637
6638
6639
6640
6641
6642


6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653
6654

6655
6656
6657
6658
6659
6660

6661
6662
6663
6664
6665
6666
6667
6668
6669
6670
6671
6672
6673
6674
6675
6676

6677
6678
6679
6680
6681
6682
6683
8878
8879
8880
8881
8882
8883
8884
8885
8886
8887
8888
8889
8890
8891

8892

8893
8894
8895
8896
8897
8898
8899
8900
8901
8902
8903

8904
8905
8906
8907
8908
8909
8910
8911
8912
8913
8914
8915
8916
8917
8918
8919
8920
8921
8922
8923
8924
8925
8926
8927
8928
8929


8930
8931
8932
8933
8934
8935
8936
8937
8938
8939
8940
8941
8942
8943
8944
8945





8946
8947
8948
8949

8950
8951
8952
8953
8954
8955
8956
8957
8958
8959
8960
8961
8962
8963
8964
8965
8966
8967
8968
8969
8970
8971
8972
8973
8974
8975
8976
8977
8978
8979


8980
8981
8982
8983
8984
8985
8986
8987
8988
8989
8990
8991

8992
8993
8994
8995
8996
8997
8998
8999
9000
9001
9002
9003
9004

9005
9006
9007
9008
9009
9010

9011
9012
9013
9014
9015
9016
9017
9018
9019
9020
9021
9022
9023
9024
9025
9026

9027
9028
9029
9030
9031
9032
9033
9034







+
+
+




-
+
-


+
+
+
+
+

+


-
+




+
+




+
+
+
+
+
+
+








-
-
+
+
+
+
+
+
+
+
+




+


-
-
-
-
-




-
+











+
+
+







+
+
+
+
+
+
+

-
-
+
+










-
+
+











-
+





-
+















-
+







      }
      if( i>=nCol ){
        sqlite3_step(pStmt);
        rc = sqlite3_reset(pStmt);
        if( rc!=SQLITE_OK ){
          utf8_printf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile,
                      startLine, sqlite3_errmsg(p->db));
          sCtx.nErr++;
        }else{
          sCtx.nRow++;
        }
      }
    }while( sCtx.cTerm!=EOF );

    xCloser(sCtx.in);
    import_cleanup(&sCtx);
    sqlite3_free(sCtx.z);
    sqlite3_finalize(pStmt);
    if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
    if( eVerbose>0 ){
      utf8_printf(p->out,
          "Added %d rows with %d errors using %d lines of input\n",
          sCtx.nRow, sCtx.nErr, sCtx.nLine-1);
    }
  }else
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

#ifndef SQLITE_UNTESTABLE
  if( c=='i' && strncmp(azArg[0], "imposter", n)==0 ){
  if( c=='i' && cli_strncmp(azArg[0], "imposter", n)==0 ){
    char *zSql;
    char *zCollist = 0;
    sqlite3_stmt *pStmt;
    int tnum = 0;
    int isWO = 0;  /* True if making an imposter of a WITHOUT ROWID table */
    int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */
    int i;
    if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){
      utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n"
                          "       .imposter off\n");
      /* Also allowed, but not documented:
      **
      **    .imposter TABLE IMPOSTER
      **
      ** where TABLE is a WITHOUT ROWID table.  In that case, the
      ** imposter is another WITHOUT ROWID table with the columns in
      ** storage order. */
      rc = 1;
      goto meta_command_exit;
    }
    open_db(p, 0);
    if( nArg==2 ){
      sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1);
      goto meta_command_exit;
    }
    zSql = sqlite3_mprintf("SELECT rootpage FROM sqlite_master"
                           " WHERE name='%q' AND type='index'", azArg[1]);
    zSql = sqlite3_mprintf(
      "SELECT rootpage, 0 FROM sqlite_schema"
      " WHERE name='%q' AND type='index'"
      "UNION ALL "
      "SELECT rootpage, 1 FROM sqlite_schema"
      " WHERE name='%q' AND type='table'"
      "   AND sql LIKE '%%without%%rowid%%'",
      azArg[1], azArg[1]
    );
    sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
    sqlite3_free(zSql);
    if( sqlite3_step(pStmt)==SQLITE_ROW ){
      tnum = sqlite3_column_int(pStmt, 0);
      isWO = sqlite3_column_int(pStmt, 1);
    }
    sqlite3_finalize(pStmt);
    if( tnum==0 ){
      utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]);
      rc = 1;
      goto meta_command_exit;
    }
    zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]);
    rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
    sqlite3_free(zSql);
    i = 0;
    while( sqlite3_step(pStmt)==SQLITE_ROW ){
    while( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
      char zLabel[20];
      const char *zCol = (const char*)sqlite3_column_text(pStmt,2);
      i++;
      if( zCol==0 ){
        if( sqlite3_column_int(pStmt,1)==-1 ){
          zCol = "_ROWID_";
        }else{
          sqlite3_snprintf(sizeof(zLabel),zLabel,"expr%d",i);
          zCol = zLabel;
        }
      }
      if( isWO && lenPK==0 && sqlite3_column_int(pStmt,5)==0 && zCollist ){
        lenPK = (int)strlen(zCollist);
      }
      if( zCollist==0 ){
        zCollist = sqlite3_mprintf("\"%w\"", zCol);
      }else{
        zCollist = sqlite3_mprintf("%z,\"%w\"", zCollist, zCol);
      }
    }
    sqlite3_finalize(pStmt);
    if( i==0 || tnum==0 ){
      utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]);
      rc = 1;
      sqlite3_free(zCollist);
      goto meta_command_exit;
    }
    if( lenPK==0 ) lenPK = 100000;
    zSql = sqlite3_mprintf(
          "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%s))WITHOUT ROWID",
          azArg[2], zCollist, zCollist);
          "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%.*s))WITHOUT ROWID",
          azArg[2], zCollist, lenPK, zCollist);
    sqlite3_free(zCollist);
    rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum);
    if( rc==SQLITE_OK ){
      rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
      sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0);
      if( rc ){
        utf8_printf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db));
      }else{
        utf8_printf(stdout, "%s;\n", zSql);
        raw_printf(stdout,
           "WARNING: writing to an imposter table will corrupt the index!\n"
          "WARNING: writing to an imposter table will corrupt the \"%s\" %s!\n",
          azArg[1], isWO ? "table" : "index"
        );
      }
    }else{
      raw_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
      rc = 1;
    }
    sqlite3_free(zSql);
  }else
#endif /* !defined(SQLITE_OMIT_TEST_CONTROL) */

#ifdef SQLITE_ENABLE_IOTRACE
  if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){
  if( c=='i' && cli_strncmp(azArg[0], "iotrace", n)==0 ){
    SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...);
    if( iotrace && iotrace!=stdout ) fclose(iotrace);
    iotrace = 0;
    if( nArg<2 ){
      sqlite3IoTrace = 0;
    }else if( strcmp(azArg[1], "-")==0 ){
    }else if( cli_strcmp(azArg[1], "-")==0 ){
      sqlite3IoTrace = iotracePrintf;
      iotrace = stdout;
    }else{
      iotrace = fopen(azArg[1], "w");
      if( iotrace==0 ){
        utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
        sqlite3IoTrace = 0;
        rc = 1;
      }else{
        sqlite3IoTrace = iotracePrintf;
      }
    }
  }else
#endif

  if( c=='l' && n>=5 && strncmp(azArg[0], "limits", n)==0 ){
  if( c=='l' && n>=5 && cli_strncmp(azArg[0], "limits", n)==0 ){
    static const struct {
       const char *zLimitName;   /* Name of a limit */
       int limitCode;            /* Integer code for that limit */
    } aLimit[] = {
      { "length",                SQLITE_LIMIT_LENGTH                    },
      { "sql_length",            SQLITE_LIMIT_SQL_LENGTH                },
      { "column",                SQLITE_LIMIT_COLUMN                    },
6728
6729
6730
6731
6732
6733
6734
6735

6736
6737
6738
6739
6740
6741


6742
6743

6744
6745
6746
6747
6748
6749
6750
6751
6752
6753
6754
6755
6756
6757
6758
6759
6760

6761


6762
6763
6764
6765
6766
6767
6768
6769
6770

6771
6772
6773
6774





























































6775
6776

6777
6778
6779

6780



6781

6782

6783
6784
6785
6786

6787
6788

6789
6790
6791
6792

6793
6794
6795
6796

6797
6798
6799

6800
6801
6802


6803


6804

6805
6806
6807






6808
6809









6810
6811
6812


6813
6814
6815
6816
6817

















6818

6819
6820
6821
6822
6823
6824
6825
6826
6827
6828
6829
6830
6831





6832
6833
6834
6835
6836
6837
6838
6839


6840
6841

6842

6843
6844
6845
6846
6847

6848
6849
6850

6851
6852
6853




6854
6855

6856
6857
6858
6859







6860
6861
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

6890







6891

6892
6893
6894



6895
6896

6897


6898
6899
6900
6901
6902
6903
6904



























6905

6906

6907
6908





6909
6910
6911
6912
6913
6914
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

6943
6944
6945
6946
6947
6948
6949

6950
6951
6952
6953
6954

6955
6956
6957

6958

6959








































































































6960

6961
6962
6963
6964
6965
6966
6967
6968














































6969

6970
6971

6972
6973
6974

6975
6976
6977

6978

6979
6980

6981

6982

6983
6984

6985
6986
6987
6988
6989






6990
6991










6992
6993
6994
6995
6996
6997
6998
6999
7000

7001

7002

7003
7004
7005
7006
7007
7008

7009
7010
7011
7012
7013
7014
7015
9079
9080
9081
9082
9083
9084
9085

9086
9087
9088
9089
9090


9091
9092
9093
9094
9095
9096
9097
9098
9099
9100
9101
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
9137
9138
9139
9140
9141
9142
9143
9144
9145
9146
9147
9148
9149
9150
9151
9152
9153
9154
9155
9156
9157
9158
9159
9160
9161
9162
9163
9164
9165
9166
9167
9168
9169
9170
9171
9172
9173
9174
9175
9176
9177
9178
9179
9180
9181
9182
9183
9184
9185
9186
9187


9188
9189
9190

9191
9192
9193
9194
9195
9196
9197

9198
9199
9200
9201

9202
9203

9204
9205
9206
9207

9208
9209
9210
9211

9212
9213
9214

9215
9216


9217
9218
9219
9220
9221

9222
9223
9224
9225
9226
9227
9228
9229
9230
9231


9232
9233
9234
9235
9236
9237
9238
9239
9240
9241
9242

9243
9244
9245
9246
9247
9248
9249
9250
9251
9252
9253
9254
9255
9256
9257
9258
9259
9260
9261
9262
9263
9264
9265
9266

9267
9268
9269
9270
9271
9272
9273
9274
9275
9276




9277
9278
9279
9280
9281








9282
9283
9284

9285
9286
9287
9288
9289
9290
9291

9292
9293
9294

9295
9296


9297
9298
9299
9300
9301

9302
9303



9304
9305
9306
9307
9308
9309
9310
9311
9312
9313
9314
9315
9316
9317
9318
9319
9320
9321
9322
9323
9324
9325
9326
9327
9328
9329
9330
9331
9332
9333
9334




9335
9336
9337
9338
9339
9340
9341
9342
9343
9344
9345
9346
9347
9348
9349
9350
9351
9352
9353
9354
9355
9356
9357
9358
9359

9360
9361
9362
9363
9364

9365
9366
9367
9368
9369
9370
9371


9372
9373
9374
9375

9376
9377
9378
9379
9380
9381
9382
9383
9384

9385



9386
9387
9388


9389
9390
9391
9392







9393
9394
9395
9396
9397
9398
9399
9400
9401
9402
9403
9404
9405
9406
9407
9408
9409
9410
9411
9412
9413
9414
9415
9416
9417
9418
9419

9420
9421
9422
9423
9424
9425
9426
9427
9428
9429
9430
9431
9432
9433
9434

9435

9436
9437
9438

9439
9440
9441
9442
9443
9444
9445
9446
9447
9448
9449
9450
9451

9452
9453
9454
9455
9456
9457
9458
9459
9460
9461
9462
9463
9464
9465
9466
9467
9468
9469
9470
9471
9472
9473
9474

9475
9476
9477
9478
9479
9480
9481
9482
9483
9484
9485
9486
9487
9488
9489
9490
9491
9492
9493
9494
9495
9496
9497
9498
9499
9500
9501
9502
9503
9504
9505
9506
9507
9508
9509
9510
9511
9512
9513
9514
9515
9516
9517
9518
9519
9520
9521
9522
9523
9524
9525
9526
9527
9528
9529
9530
9531
9532
9533
9534
9535
9536
9537
9538
9539
9540
9541
9542
9543
9544
9545
9546
9547
9548
9549
9550
9551
9552
9553
9554
9555
9556
9557
9558
9559
9560
9561
9562
9563
9564
9565
9566
9567
9568
9569
9570
9571
9572
9573
9574
9575
9576
9577
9578
9579
9580
9581
9582
9583
9584
9585
9586
9587
9588
9589
9590
9591
9592

9593
9594
9595
9596
9597
9598
9599
9600
9601
9602
9603
9604
9605
9606
9607
9608
9609
9610
9611
9612
9613
9614
9615
9616
9617
9618
9619
9620
9621
9622
9623
9624
9625
9626
9627
9628
9629
9630
9631
9632
9633
9634
9635
9636
9637
9638
9639
9640
9641
9642
9643
9644
9645
9646
9647

9648
9649

9650
9651
9652

9653
9654
9655
9656
9657

9658
9659
9660
9661
9662
9663

9664
9665
9666
9667
9668
9669
9670
9671
9672
9673
9674
9675
9676
9677
9678


9679
9680
9681
9682
9683
9684
9685
9686
9687
9688
9689
9690
9691
9692
9693
9694
9695
9696
9697
9698
9699
9700

9701
9702
9703
9704
9705
9706
9707
9708
9709
9710
9711
9712
9713
9714
9715







-
+




-
-
+
+


+

















+
-
+
+









+

-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+


-
+

+
+
+

+
-
+



-
+

-
+



-
+



-
+


-
+

-
-
+
+

+
+
-
+



+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+


-
+
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+









-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+

-
+

+




-
+


-
+

-
-
+
+
+
+

-
+

-
-
-
+
+
+
+
+
+
+



+
+
+
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+




-
+




+

-
-
+
+
+

-
+

+
+
+
+
+
+
+
-
+
-
-
-
+
+
+
-
-
+

+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+

+


+
+
+
+
+





-

-
+


-
+
+

+




+



+
-
+


+












+






-
+





+



+

+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+

-
+


-
+



+
-
+


+

+
-
+


+





+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+









+

+
-
+






+







                      (int)integerValue(azArg[2]));
      }
      printf("%20s %d\n", aLimit[iLimit].zLimitName,
             sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
    }
  }else

  if( c=='l' && n>2 && strncmp(azArg[0], "lint", n)==0 ){
  if( c=='l' && n>2 && cli_strncmp(azArg[0], "lint", n)==0 ){
    open_db(p, 0);
    lintDotCommand(p, azArg, nArg);
  }else

#ifndef SQLITE_OMIT_LOAD_EXTENSION
  if( c=='l' && strncmp(azArg[0], "load", n)==0 ){
#if !defined(SQLITE_OMIT_LOAD_EXTENSION) && !defined(SQLITE_SHELL_FIDDLE)
  if( c=='l' && cli_strncmp(azArg[0], "load", n)==0 ){
    const char *zFile, *zProc;
    char *zErrMsg = 0;
    failIfSafeMode(p, "cannot run .load in safe mode");
    if( nArg<2 ){
      raw_printf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n");
      rc = 1;
      goto meta_command_exit;
    }
    zFile = azArg[1];
    zProc = nArg>=3 ? azArg[2] : 0;
    open_db(p, 0);
    rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg);
    if( rc!=SQLITE_OK ){
      utf8_printf(stderr, "Error: %s\n", zErrMsg);
      sqlite3_free(zErrMsg);
      rc = 1;
    }
  }else
#endif

#ifndef SQLITE_SHELL_FIDDLE
  if( c=='l' && strncmp(azArg[0], "log", n)==0 ){
  if( c=='l' && cli_strncmp(azArg[0], "log", n)==0 ){
    failIfSafeMode(p, "cannot run .log in safe mode");
    if( nArg!=2 ){
      raw_printf(stderr, "Usage: .log FILENAME\n");
      rc = 1;
    }else{
      const char *zFile = azArg[1];
      output_file_close(p->pLog);
      p->pLog = output_file_open(zFile, 0);
    }
  }else
#endif

  if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){
    const char *zMode = nArg>=2 ? azArg[1] : "";
    int n2 = strlen30(zMode);
  if( c=='m' && cli_strncmp(azArg[0], "mode", n)==0 ){
    const char *zMode = 0;
    const char *zTabname = 0;
    int i, n2;
    ColModeOpts cmOpts = ColModeOpts_default;
    for(i=1; i<nArg; i++){
      const char *z = azArg[i];
      if( optionMatch(z,"wrap") && i+1<nArg ){
        cmOpts.iWrap = integerValue(azArg[++i]);
      }else if( optionMatch(z,"ww") ){
        cmOpts.bWordWrap = 1;
      }else if( optionMatch(z,"wordwrap") && i+1<nArg ){
        cmOpts.bWordWrap = (u8)booleanValue(azArg[++i]);
      }else if( optionMatch(z,"quote") ){
        cmOpts.bQuote = 1;
      }else if( optionMatch(z,"noquote") ){
        cmOpts.bQuote = 0;
      }else if( zMode==0 ){
        zMode = z;
        /* Apply defaults for qbox pseudo-mode.  If that
         * overwrites already-set values, user was informed of this.
         */
        if( cli_strcmp(z, "qbox")==0 ){
          ColModeOpts cmo = ColModeOpts_default_qbox;
          zMode = "box";
          cmOpts = cmo;
        }
      }else if( zTabname==0 ){
        zTabname = z;
      }else if( z[0]=='-' ){
        utf8_printf(stderr, "unknown option: %s\n", z);
        utf8_printf(stderr, "options:\n"
                            "  --noquote\n"
                            "  --quote\n"
                            "  --wordwrap on/off\n"
                            "  --wrap N\n"
                            "  --ww\n");
        rc = 1;
        goto meta_command_exit;
      }else{
        utf8_printf(stderr, "extra argument: \"%s\"\n", z);
        rc = 1;
        goto meta_command_exit;
      }
    }
    if( zMode==0 ){
      if( p->mode==MODE_Column
       || (p->mode>=MODE_Markdown && p->mode<=MODE_Box)
      ){
        raw_printf
          (p->out,
           "current output mode: %s --wrap %d --wordwrap %s --%squote\n",
           modeDescr[p->mode], p->cmOpts.iWrap,
           p->cmOpts.bWordWrap ? "on" : "off",
           p->cmOpts.bQuote ? "" : "no");
      }else{
        raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
      }
      zMode = modeDescr[p->mode];
    }
    n2 = strlen30(zMode);
    int c2 = zMode[0];
    if( c2=='l' && n2>2 && strncmp(azArg[1],"lines",n2)==0 ){
    if( cli_strncmp(zMode,"lines",n2)==0 ){
      p->mode = MODE_Line;
      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
    }else if( c2=='c' && strncmp(azArg[1],"columns",n2)==0 ){
    }else if( cli_strncmp(zMode,"columns",n2)==0 ){
      p->mode = MODE_Column;
      if( (p->shellFlgs & SHFLG_HeaderSet)==0 ){
        p->showHeader = 1;
      }
      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
      p->cmOpts = cmOpts;
    }else if( c2=='l' && n2>2 && strncmp(azArg[1],"list",n2)==0 ){
    }else if( cli_strncmp(zMode,"list",n2)==0 ){
      p->mode = MODE_List;
      sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Column);
      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
    }else if( c2=='h' && strncmp(azArg[1],"html",n2)==0 ){
    }else if( cli_strncmp(zMode,"html",n2)==0 ){
      p->mode = MODE_Html;
    }else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){
    }else if( cli_strncmp(zMode,"tcl",n2)==0 ){
      p->mode = MODE_Tcl;
      sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space);
      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
    }else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){
    }else if( cli_strncmp(zMode,"csv",n2)==0 ){
      p->mode = MODE_Csv;
      sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
    }else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){
    }else if( cli_strncmp(zMode,"tabs",n2)==0 ){
      p->mode = MODE_List;
      sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab);
    }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){
    }else if( cli_strncmp(zMode,"insert",n2)==0 ){
      p->mode = MODE_Insert;
      set_table_name(p, nArg>=3 ? azArg[2] : "table");
    }else if( c2=='q' && strncmp(azArg[1],"quote",n2)==0 ){
      set_table_name(p, zTabname ? zTabname : "table");
    }else if( cli_strncmp(zMode,"quote",n2)==0 ){
      p->mode = MODE_Quote;
      sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
    }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){
    }else if( cli_strncmp(zMode,"ascii",n2)==0 ){
      p->mode = MODE_Ascii;
      sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
    }else if( cli_strncmp(zMode,"markdown",n2)==0 ){
      p->mode = MODE_Markdown;
      p->cmOpts = cmOpts;
    }else if( cli_strncmp(zMode,"table",n2)==0 ){
      p->mode = MODE_Table;
      p->cmOpts = cmOpts;
    }else if( nArg==1 ){
      raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
    }else if( cli_strncmp(zMode,"box",n2)==0 ){
      p->mode = MODE_Box;
      p->cmOpts = cmOpts;
    }else if( cli_strncmp(zMode,"count",n2)==0 ){
      p->mode = MODE_Count;
    }else if( cli_strncmp(zMode,"off",n2)==0 ){
      p->mode = MODE_Off;
    }else if( cli_strncmp(zMode,"json",n2)==0 ){
      p->mode = MODE_Json;
    }else{
      raw_printf(stderr, "Error: mode should be one of: "
         "ascii column csv html insert line list quote tabs tcl\n");
         "ascii box column csv html insert json line list markdown "
         "qbox quote table tabs tcl\n");
      rc = 1;
    }
    p->cMode = p->mode;
  }else

#ifndef SQLITE_SHELL_FIDDLE
  if( c=='n' && cli_strcmp(azArg[0], "nonce")==0 ){
    if( nArg!=2 ){
      raw_printf(stderr, "Usage: .nonce NONCE\n");
      rc = 1;
    }else if( p->zNonce==0 || cli_strcmp(azArg[1],p->zNonce)!=0 ){
      raw_printf(stderr, "line %d: incorrect nonce: \"%s\"\n",
                 p->lineno, azArg[1]);
      exit(1);
    }else{
      p->bSafeMode = 0;
      return 0;  /* Return immediately to bypass the safe mode reset
                 ** at the end of this procedure */
    }
  }else
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

  if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){
  if( c=='n' && cli_strncmp(azArg[0], "nullvalue", n)==0 ){
    if( nArg==2 ){
      sqlite3_snprintf(sizeof(p->nullValue), p->nullValue,
                       "%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]);
    }else{
      raw_printf(stderr, "Usage: .nullvalue STRING\n");
      rc = 1;
    }
  }else

  if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
    char *zNewFilename;  /* Name of the database file to open */
    int iName = 1;       /* Index in azArg[] of the filename */
    int newFlag = 0;     /* True to delete file before opening */
  if( c=='o' && cli_strncmp(azArg[0], "open", n)==0 && n>=2 ){
    const char *zFN = 0;     /* Pointer to constant filename */
    char *zNewFilename = 0;  /* Name of the database file to open */
    int iName = 1;           /* Index in azArg[] of the filename */
    int newFlag = 0;         /* True to delete file before opening */
    /* Close the existing database */
    session_close_all(p);
    close_db(p->db);
    p->db = 0;
    p->zDbFilename = 0;
    sqlite3_free(p->zFreeOnClose);
    p->zFreeOnClose = 0;
    p->openMode = SHELL_OPEN_UNSPEC;
    int openMode = SHELL_OPEN_UNSPEC;

    /* Check for command-line arguments */
    for(iName=1; iName<nArg && azArg[iName][0]=='-'; iName++){
    for(iName=1; iName<nArg; iName++){
      const char *z = azArg[iName];
#ifndef SQLITE_SHELL_FIDDLE
      if( optionMatch(z,"new") ){
        newFlag = 1;
#ifdef SQLITE_HAVE_ZLIB
      }else if( optionMatch(z, "zip") ){
        p->openMode = SHELL_OPEN_ZIPFILE;
        openMode = SHELL_OPEN_ZIPFILE;
#endif
      }else if( optionMatch(z, "append") ){
        p->openMode = SHELL_OPEN_APPENDVFS;
        openMode = SHELL_OPEN_APPENDVFS;
      }else if( optionMatch(z, "readonly") ){
        p->openMode = SHELL_OPEN_READONLY;
#ifdef SQLITE_ENABLE_DESERIALIZE
        openMode = SHELL_OPEN_READONLY;
      }else if( optionMatch(z, "nofollow") ){
        p->openFlags |= SQLITE_OPEN_NOFOLLOW;
#ifndef SQLITE_OMIT_DESERIALIZE
      }else if( optionMatch(z, "deserialize") ){
        p->openMode = SHELL_OPEN_DESERIALIZE;
        openMode = SHELL_OPEN_DESERIALIZE;
      }else if( optionMatch(z, "hexdb") ){
        p->openMode = SHELL_OPEN_HEXDB;
#endif /* SQLITE_ENABLE_DESERIALIZE */
      }else if( z[0]=='-' ){
        openMode = SHELL_OPEN_HEXDB;
      }else if( optionMatch(z, "maxsize") && iName+1<nArg ){
        p->szMax = integerValue(azArg[++iName]);
#endif /* SQLITE_OMIT_DESERIALIZE */
      }else
#endif /* !SQLITE_SHELL_FIDDLE */
      if( z[0]=='-' ){
        utf8_printf(stderr, "unknown option: %s\n", z);
        rc = 1;
        goto meta_command_exit;
      }else if( zFN ){
        utf8_printf(stderr, "extra argument: \"%s\"\n", z);
        rc = 1;
        goto meta_command_exit;
      }else{
        zFN = z;
      }
    }

    /* Close the existing database */
    session_close_all(p, -1);
    close_db(p->db);
    p->db = 0;
    p->pAuxDb->zDbFilename = 0;
    sqlite3_free(p->pAuxDb->zFreeOnClose);
    p->pAuxDb->zFreeOnClose = 0;
    p->openMode = openMode;
    p->openFlags = 0;
    p->szMax = 0;

    /* If a filename is specified, try to open it first */
    zNewFilename = nArg>iName ? sqlite3_mprintf("%s", azArg[iName]) : 0;
    if( zNewFilename || p->openMode==SHELL_OPEN_HEXDB ){
      if( newFlag ) shellDeleteFile(zNewFilename);
      p->zDbFilename = zNewFilename;
    if( zFN || p->openMode==SHELL_OPEN_HEXDB ){
      if( newFlag && zFN && !p->bSafeMode ) shellDeleteFile(zFN);
#ifndef SQLITE_SHELL_FIDDLE
      if( p->bSafeMode
       && p->openMode!=SHELL_OPEN_HEXDB
       && zFN
       && cli_strcmp(zFN,":memory:")!=0
      ){
        failIfSafeMode(p, "cannot open disk-based database files in safe mode");
      }
#else
      /* WASM mode has its own sandboxed pseudo-filesystem. */
#endif
      if( zFN ){
        zNewFilename = sqlite3_mprintf("%s", zFN);
        shell_check_oom(zNewFilename);
      }else{
        zNewFilename = 0;
      }
      p->pAuxDb->zDbFilename = zNewFilename;
      open_db(p, OPEN_DB_KEEPALIVE);
      if( p->db==0 ){
        utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename);
        sqlite3_free(zNewFilename);
      }else{
        p->zFreeOnClose = zNewFilename;
        p->pAuxDb->zFreeOnClose = zNewFilename;
      }
    }
    if( p->db==0 ){
      /* As a fall-back open a TEMP database */
      p->zDbFilename = 0;
      p->pAuxDb->zDbFilename = 0;
      open_db(p, 0);
    }
  }else

#ifndef SQLITE_SHELL_FIDDLE
  if( (c=='o'
        && (strncmp(azArg[0], "output", n)==0||strncmp(azArg[0], "once", n)==0))
   || (c=='e' && n==5 && strcmp(azArg[0],"excel")==0)
        && (cli_strncmp(azArg[0], "output", n)==0
            || cli_strncmp(azArg[0], "once", n)==0))
   || (c=='e' && n==5 && cli_strcmp(azArg[0],"excel")==0)
  ){
    const char *zFile = nArg>=2 ? azArg[1] : "stdout";
    char *zFile = 0;
    int bTxtMode = 0;
    int i;
    int eMode = 0;
    int bOnce = 0;            /* 0: .output, 1: .once, 2: .excel */
    unsigned char zBOM[4];    /* Byte-order mark to using if --bom is present */

    zBOM[0] = 0;
    failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
    if( azArg[0][0]=='e' ){
    if( c=='e' ){
      /* Transform the ".excel" command into ".once -x" */
      nArg = 2;
      azArg[0] = "once";
      eMode = 'x';
      bOnce = 2;
    }else if( cli_strncmp(azArg[0],"once",n)==0 ){
      zFile = azArg[1] = "-x";
      n = 4;
      bOnce = 1;
    }
    for(i=1; i<nArg; i++){
      char *z = azArg[i];
    if( nArg>2 ){
      utf8_printf(stderr, "Usage: .%s [-e|-x|FILE]\n", azArg[0]);
      rc = 1;
      goto meta_command_exit;
    }
    if( n>1 && strncmp(azArg[0], "once", n)==0 ){
      if( nArg<2 ){
      if( z[0]=='-' ){
        if( z[1]=='-' ) z++;
        if( cli_strcmp(z,"-bom")==0 ){
          zBOM[0] = 0xef;
          zBOM[1] = 0xbb;
          zBOM[2] = 0xbf;
          zBOM[3] = 0;
        }else if( c!='e' && cli_strcmp(z,"-x")==0 ){
          eMode = 'x';  /* spreadsheet */
        }else if( c!='e' && cli_strcmp(z,"-e")==0 ){
          eMode = 'e';  /* text editor */
        }else{
          utf8_printf(p->out, "ERROR: unknown option: \"%s\".  Usage:\n",
                      azArg[i]);
          showHelp(p->out, azArg[0]);
          rc = 1;
          goto meta_command_exit;
        }
      }else if( zFile==0 && eMode!='e' && eMode!='x' ){
        zFile = sqlite3_mprintf("%s", z);
        if( zFile && zFile[0]=='|' ){
          while( i+1<nArg ) zFile = sqlite3_mprintf("%z %s", zFile, azArg[++i]);
          break;
        }
      }else{
        utf8_printf(p->out,"ERROR: extra parameter: \"%s\".  Usage:\n",
                    azArg[i]);
        raw_printf(stderr, "Usage: .once (-e|-x|FILE)\n");
        showHelp(p->out, azArg[0]);
        rc = 1;
        sqlite3_free(zFile);
        goto meta_command_exit;
      }
    }
    if( zFile==0 ){
      zFile = sqlite3_mprintf("stdout");
    }
    if( bOnce ){
      p->outCount = 2;
    }else{
      p->outCount = 0;
    }
    output_reset(p);
    if( zFile[0]=='-' && zFile[1]=='-' ) zFile++;
#ifndef SQLITE_NOHAVE_SYSTEM
    if( strcmp(zFile, "-e")==0 || strcmp(zFile, "-x")==0 ){
    if( eMode=='e' || eMode=='x' ){
      p->doXdgOpen = 1;
      outputModePush(p);
      if( zFile[1]=='x' ){
      if( eMode=='x' ){
        /* spreadsheet mode.  Output as CSV. */
        newTempFile(p, "csv");
        ShellClearFlag(p, SHFLG_Echo);
        p->mode = MODE_Csv;
        sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
        sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
      }else{
        /* text editor mode */
        newTempFile(p, "txt");
        bTxtMode = 1;
      }
      sqlite3_free(zFile);
      zFile = p->zTempFile;
      zFile = sqlite3_mprintf("%s", p->zTempFile);
    }
#endif /* SQLITE_NOHAVE_SYSTEM */
    shell_check_oom(zFile);
    if( zFile[0]=='|' ){
#ifdef SQLITE_OMIT_POPEN
      raw_printf(stderr, "Error: pipes are not supported in this OS\n");
      rc = 1;
      p->out = stdout;
#else
      p->out = popen(zFile + 1, "w");
      if( p->out==0 ){
        utf8_printf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
        p->out = stdout;
        rc = 1;
      }else{
        if( zBOM[0] ) fwrite(zBOM, 1, 3, p->out);
        sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
      }
#endif
    }else{
      p->out = output_file_open(zFile, bTxtMode);
      if( p->out==0 ){
        if( strcmp(zFile,"off")!=0 ){
        if( cli_strcmp(zFile,"off")!=0 ){
          utf8_printf(stderr,"Error: cannot write to \"%s\"\n", zFile);
        }
        p->out = stdout;
        rc = 1;
      } else {
        if( zBOM[0] ) fwrite(zBOM, 1, 3, p->out);
        sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
      }
    }
    sqlite3_free(zFile);
  }else
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

  if( c=='p' && n>=3 && cli_strncmp(azArg[0], "parameter", n)==0 ){
    open_db(p,0);
    if( nArg<=1 ) goto parameter_syntax_error;

    /* .parameter clear
    ** Clear all bind parameters by dropping the TEMP table that holds them.
    */
    if( nArg==2 && cli_strcmp(azArg[1],"clear")==0 ){
      sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp.sqlite_parameters;",
                   0, 0, 0);
    }else

    /* .parameter list
    ** List all bind parameters.
    */
    if( nArg==2 && cli_strcmp(azArg[1],"list")==0 ){
      sqlite3_stmt *pStmt = 0;
      int rx;
      int len = 0;
      rx = sqlite3_prepare_v2(p->db,
             "SELECT max(length(key)) "
             "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
      if( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
        len = sqlite3_column_int(pStmt, 0);
        if( len>40 ) len = 40;
      }
      sqlite3_finalize(pStmt);
      pStmt = 0;
      if( len ){
        rx = sqlite3_prepare_v2(p->db,
             "SELECT key, quote(value) "
             "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
        while( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
          utf8_printf(p->out, "%-*s %s\n", len, sqlite3_column_text(pStmt,0),
                      sqlite3_column_text(pStmt,1));
        }
        sqlite3_finalize(pStmt);
      }
    }else

    /* .parameter init
    ** Make sure the TEMP table used to hold bind parameters exists.
    ** Create it if necessary.
    */
    if( nArg==2 && cli_strcmp(azArg[1],"init")==0 ){
      bind_table_init(p);
    }else

    /* .parameter set NAME VALUE
    ** Set or reset a bind parameter.  NAME should be the full parameter
    ** name exactly as it appears in the query.  (ex: $abc, @def).  The
    ** VALUE can be in either SQL literal notation, or if not it will be
    ** understood to be a text string.
    */
    if( nArg==4 && cli_strcmp(azArg[1],"set")==0 ){
      int rx;
      char *zSql;
      sqlite3_stmt *pStmt;
      const char *zKey = azArg[2];
      const char *zValue = azArg[3];
      bind_table_init(p);
      zSql = sqlite3_mprintf(
                  "REPLACE INTO temp.sqlite_parameters(key,value)"
                  "VALUES(%Q,%s);", zKey, zValue);
      shell_check_oom(zSql);
      pStmt = 0;
      rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
      sqlite3_free(zSql);
      if( rx!=SQLITE_OK ){
        sqlite3_finalize(pStmt);
        pStmt = 0;
        zSql = sqlite3_mprintf(
                   "REPLACE INTO temp.sqlite_parameters(key,value)"
                   "VALUES(%Q,%Q);", zKey, zValue);
        shell_check_oom(zSql);
        rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
        sqlite3_free(zSql);
        if( rx!=SQLITE_OK ){
          utf8_printf(p->out, "Error: %s\n", sqlite3_errmsg(p->db));
          sqlite3_finalize(pStmt);
          pStmt = 0;
          rc = 1;
        }
      }
      sqlite3_step(pStmt);
      sqlite3_finalize(pStmt);
    }else

    /* .parameter unset NAME
    ** Remove the NAME binding from the parameter binding table, if it
    ** exists.
    */
    if( nArg==3 && cli_strcmp(azArg[1],"unset")==0 ){
      char *zSql = sqlite3_mprintf(
          "DELETE FROM temp.sqlite_parameters WHERE key=%Q", azArg[2]);
      shell_check_oom(zSql);
      sqlite3_exec(p->db, zSql, 0, 0, 0);
      sqlite3_free(zSql);
    }else
    /* If no command name matches, show a syntax error */
    parameter_syntax_error:
    showHelp(p->out, "parameter");
  }else

  if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){
  if( c=='p' && n>=3 && cli_strncmp(azArg[0], "print", n)==0 ){
    int i;
    for(i=1; i<nArg; i++){
      if( i>1 ) raw_printf(p->out, " ");
      utf8_printf(p->out, "%s", azArg[i]);
    }
    raw_printf(p->out, "\n");
  }else

#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  if( c=='p' && n>=3 && cli_strncmp(azArg[0], "progress", n)==0 ){
    int i;
    int nn = 0;
    p->flgProgress = 0;
    p->mxProgress = 0;
    p->nProgress = 0;
    for(i=1; i<nArg; i++){
      const char *z = azArg[i];
      if( z[0]=='-' ){
        z++;
        if( z[0]=='-' ) z++;
        if( cli_strcmp(z,"quiet")==0 || cli_strcmp(z,"q")==0 ){
          p->flgProgress |= SHELL_PROGRESS_QUIET;
          continue;
        }
        if( cli_strcmp(z,"reset")==0 ){
          p->flgProgress |= SHELL_PROGRESS_RESET;
          continue;
        }
        if( cli_strcmp(z,"once")==0 ){
          p->flgProgress |= SHELL_PROGRESS_ONCE;
          continue;
        }
        if( cli_strcmp(z,"limit")==0 ){
          if( i+1>=nArg ){
            utf8_printf(stderr, "Error: missing argument on --limit\n");
            rc = 1;
            goto meta_command_exit;
          }else{
            p->mxProgress = (int)integerValue(azArg[++i]);
          }
          continue;
        }
        utf8_printf(stderr, "Error: unknown option: \"%s\"\n", azArg[i]);
        rc = 1;
        goto meta_command_exit;
      }else{
        nn = (int)integerValue(z);
      }
    }
    open_db(p, 0);
    sqlite3_progress_handler(p->db, nn, progress_handler, p);
  }else
#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */

  if( c=='p' && strncmp(azArg[0], "prompt", n)==0 ){
  if( c=='p' && cli_strncmp(azArg[0], "prompt", n)==0 ){
    if( nArg >= 2) {
      strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
      shell_strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
    }
    if( nArg >= 3) {
      strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1);
      shell_strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1);
    }
  }else

#ifndef SQLITE_SHELL_FIDDLE
  if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
  if( c=='q' && cli_strncmp(azArg[0], "quit", n)==0 ){
    rc = 2;
  }else
#endif

#ifndef SQLITE_SHELL_FIDDLE
  if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){
  if( c=='r' && n>=3 && cli_strncmp(azArg[0], "read", n)==0 ){
    FILE *inSaved = p->in;
    int savedLineno = p->lineno;
    failIfSafeMode(p, "cannot run .read in safe mode");
    if( nArg!=2 ){
      raw_printf(stderr, "Usage: .read FILE\n");
      rc = 1;
      goto meta_command_exit;
    }
    if( azArg[1][0]=='|' ){
#ifdef SQLITE_OMIT_POPEN
      raw_printf(stderr, "Error: pipes are not supported in this OS\n");
      rc = 1;
      p->out = stdout;
#else
    p->in = fopen(azArg[1], "rb");
    if( p->in==0 ){
      p->in = popen(azArg[1]+1, "r");
      if( p->in==0 ){
        utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
        rc = 1;
      }else{
        rc = process_input(p);
        pclose(p->in);
      }
#endif
    }else if( (p->in = openChrSource(azArg[1]))==0 ){
      utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
      rc = 1;
    }else{
      rc = process_input(p);
      fclose(p->in);
    }
    p->in = inSaved;
    p->lineno = savedLineno;
  }else
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

#ifndef SQLITE_SHELL_FIDDLE
  if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 ){
  if( c=='r' && n>=3 && cli_strncmp(azArg[0], "restore", n)==0 ){
    const char *zSrcFile;
    const char *zDb;
    sqlite3 *pSrc;
    sqlite3_backup *pBackup;
    int nTimeout = 0;

    failIfSafeMode(p, "cannot run .restore in safe mode");
    if( nArg==2 ){
      zSrcFile = azArg[1];
      zDb = "main";
    }else if( nArg==3 ){
      zSrcFile = azArg[2];
      zDb = azArg[1];
    }else{
7045
7046
7047
7048
7049
7050
7051

7052
7053

7054



7055


7056
7057
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
7097
7098
7099
7100
7101
7102
7103
7104


7105
7106
7107
7108
7109
7110
7111
9745
9746
9747
9748
9749
9750
9751
9752
9753

9754
9755
9756
9757
9758

9759
9760
9761
9762
9763
9764

9765
9766
9767
9768
9769

9770
9771
9772
9773
9774
9775
9776
9777
9778
9779
9780
9781
9782
9783
9784
9785
9786
9787
9788
9789
9790
9791
9792
9793
9794
9795
9796
9797
9798
9799

9800
9801
9802
9803
9804
9805
9806


9807
9808
9809
9810
9811
9812
9813
9814
9815
9816
9817
9818
9819

9820
9821
9822
9823
9824
9825
9826
9827
9828







+

-
+

+
+
+
-
+
+




-
+




-
+







+












+
+
+
+
+
+



-
+
+





-
-
+
+
+
+
+








-
+
+







      rc = 1;
    }else{
      utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
      rc = 1;
    }
    close_db(pSrc);
  }else
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

  if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){
  if( c=='s' && cli_strncmp(azArg[0], "scanstats", n)==0 ){
    if( nArg==2 ){
      if( cli_strcmp(azArg[1], "est")==0 ){
        p->scanstatsOn = 2;
      }else{
      p->scanstatsOn = (u8)booleanValue(azArg[1]);
        p->scanstatsOn = (u8)booleanValue(azArg[1]);
      }
#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
      raw_printf(stderr, "Warning: .scanstats not available in this build.\n");
#endif
    }else{
      raw_printf(stderr, "Usage: .scanstats on|off\n");
      raw_printf(stderr, "Usage: .scanstats on|off|est\n");
      rc = 1;
    }
  }else

  if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
  if( c=='s' && cli_strncmp(azArg[0], "schema", n)==0 ){
    ShellText sSelect;
    ShellState data;
    char *zErrMsg = 0;
    const char *zDiv = "(";
    const char *zName = 0;
    int iSchema = 0;
    int bDebug = 0;
    int bNoSystemTabs = 0;
    int ii;

    open_db(p, 0);
    memcpy(&data, p, sizeof(data));
    data.showHeader = 0;
    data.cMode = data.mode = MODE_Semi;
    initText(&sSelect);
    for(ii=1; ii<nArg; ii++){
      if( optionMatch(azArg[ii],"indent") ){
        data.cMode = data.mode = MODE_Pretty;
      }else if( optionMatch(azArg[ii],"debug") ){
        bDebug = 1;
      }else if( optionMatch(azArg[ii],"nosys") ){
        bNoSystemTabs = 1;
      }else if( azArg[ii][0]=='-' ){
        utf8_printf(stderr, "Unknown option: \"%s\"\n", azArg[ii]);
        rc = 1;
        goto meta_command_exit;
      }else if( zName==0 ){
        zName = azArg[ii];
      }else{
        raw_printf(stderr, "Usage: .schema ?--indent? ?LIKE-PATTERN?\n");
        raw_printf(stderr,
                   "Usage: .schema ?--indent? ?--nosys? ?LIKE-PATTERN?\n");
        rc = 1;
        goto meta_command_exit;
      }
    }
    if( zName!=0 ){
      int isMaster = sqlite3_strlike(zName, "sqlite_master", '\\')==0;
      if( isMaster || sqlite3_strlike(zName,"sqlite_temp_master", '\\')==0 ){
      int isSchema = sqlite3_strlike(zName, "sqlite_master", '\\')==0
                  || sqlite3_strlike(zName, "sqlite_schema", '\\')==0
                  || sqlite3_strlike(zName,"sqlite_temp_master", '\\')==0
                  || sqlite3_strlike(zName,"sqlite_temp_schema", '\\')==0;
      if( isSchema ){
        char *new_argv[2], *new_colv[2];
        new_argv[0] = sqlite3_mprintf(
                      "CREATE TABLE %s (\n"
                      "  type text,\n"
                      "  name text,\n"
                      "  tbl_name text,\n"
                      "  rootpage integer,\n"
                      "  sql text\n"
                      ")", isMaster ? "sqlite_master" : "sqlite_temp_master");
                      ")", zName);
        shell_check_oom(new_argv[0]);
        new_argv[1] = 0;
        new_colv[0] = "sql";
        new_colv[1] = 0;
        callback(&data, 1, new_argv, new_colv);
        sqlite3_free(new_argv[0]);
      }
    }
7125
7126
7127
7128
7129
7130
7131
7132

7133
7134
7135
7136
7137
7138
7139
7140
7141
7142


7143
7144
7145

7146
7147
7148
7149


7150
7151
7152
7153
7154


7155
7156


7157
7158
7159
7160
7161
7162
7163
7164
7165
7166
7167
7168
7169



7170

7171
7172
7173
7174
7175
7176
7177
7178
7179
7180
7181
7182
7183
7184
7185
7186
7187
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
7236
7237
7238
7239
7240
7241
7242



7243

7244
7245
7246
7247
7248


7249
7250
7251
7252
7253
7254
7255
9842
9843
9844
9845
9846
9847
9848

9849
9850
9851
9852
9853
9854
9855
9856
9857


9858
9859
9860
9861

9862
9863
9864
9865

9866
9867
9868
9869
9870
9871
9872
9873
9874


9875
9876
9877
9878
9879
9880
9881
9882
9883
9884
9885
9886
9887
9888
9889
9890
9891
9892

9893
9894
9895
9896
9897
9898
9899
9900
9901
9902
9903
9904
9905
9906
9907
9908
9909
9910
9911
9912
9913



9914
9915
9916
9917
9918
9919

9920
9921


9922
9923
9924
9925
9926
9927
9928
9929
9930
9931


9932
9933
9934


9935
9936
9937
9938
9939

9940
9941
9942
9943
9944
9945
9946
9947
9948

9949
9950
9951
9952
9953
9954
9955
9956
9957
9958
9959
9960
9961
9962
9963
9964
9965
9966

9967
9968
9969
9970
9971
9972
9973
9974
9975

9976
9977
9978
9979
9980
9981
9982
9983
9984







-
+








-
-
+
+


-
+



-
+
+





+
+
-
-
+
+













+
+
+
-
+




















-
-
-
+
+
+
+
+

-


-
-
+
+
+







-
-
+
+

-
-
+
+



-
+








-
+

















-
+
+
+

+




-
+
+







        const char *zDb = (const char*)sqlite3_column_text(pStmt, 0);
        char zScNum[30];
        sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema);
        appendText(&sSelect, zDiv, 0);
        zDiv = " UNION ALL ";
        appendText(&sSelect, "SELECT shell_add_schema(sql,", 0);
        if( sqlite3_stricmp(zDb, "main")!=0 ){
          appendText(&sSelect, zDb, '"');
          appendText(&sSelect, zDb, '\'');
        }else{
          appendText(&sSelect, "NULL", 0);
        }
        appendText(&sSelect, ",name) AS sql, type, tbl_name, name, rowid,", 0);
        appendText(&sSelect, zScNum, 0);
        appendText(&sSelect, " AS snum, ", 0);
        appendText(&sSelect, zDb, '\'');
        appendText(&sSelect, " AS sname FROM ", 0);
        appendText(&sSelect, zDb, '"');
        appendText(&sSelect, ".sqlite_master", 0);
        appendText(&sSelect, zDb, quoteChar(zDb));
        appendText(&sSelect, ".sqlite_schema", 0);
      }
      sqlite3_finalize(pStmt);
#ifdef SQLITE_INTROSPECTION_PRAGMAS
#ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS
      if( zName ){
        appendText(&sSelect,
           " UNION ALL SELECT shell_module_schema(name),"
           " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list", 0);
           " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list",
        0);
      }
#endif
      appendText(&sSelect, ") WHERE ", 0);
      if( zName ){
        char *zQarg = sqlite3_mprintf("%Q", zName);
        int bGlob;
        shell_check_oom(zQarg);
        int bGlob = strchr(zName, '*') != 0 || strchr(zName, '?') != 0 ||
                    strchr(zName, '[') != 0;
        bGlob = strchr(zName, '*') != 0 || strchr(zName, '?') != 0 ||
                strchr(zName, '[') != 0;
        if( strchr(zName, '.') ){
          appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0);
        }else{
          appendText(&sSelect, "lower(tbl_name)", 0);
        }
        appendText(&sSelect, bGlob ? " GLOB " : " LIKE ", 0);
        appendText(&sSelect, zQarg, 0);
        if( !bGlob ){
          appendText(&sSelect, " ESCAPE '\\' ", 0);
        }
        appendText(&sSelect, " AND ", 0);
        sqlite3_free(zQarg);
      }
      if( bNoSystemTabs ){
        appendText(&sSelect, "name NOT LIKE 'sqlite_%%' AND ", 0);
      }
      appendText(&sSelect, "type!='meta' AND sql IS NOT NULL"
      appendText(&sSelect, "sql IS NOT NULL"
                           " ORDER BY snum, rowid", 0);
      if( bDebug ){
        utf8_printf(p->out, "SQL: %s;\n", sSelect.z);
      }else{
        rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg);
      }
      freeText(&sSelect);
    }
    if( zErrMsg ){
      utf8_printf(stderr,"Error: %s\n", zErrMsg);
      sqlite3_free(zErrMsg);
      rc = 1;
    }else if( rc != SQLITE_OK ){
      raw_printf(stderr,"Error: querying schema information\n");
      rc = 1;
    }else{
      rc = 0;
    }
  }else

#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
  if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
    sqlite3SelectTrace = (int)integerValue(azArg[1]);
  if( (c=='s' && n==11 && cli_strncmp(azArg[0], "selecttrace", n)==0)
   || (c=='t' && n==9  && cli_strncmp(azArg[0], "treetrace", n)==0)
  ){
    unsigned int x = nArg>=2? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
    sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &x);
  }else
#endif

#if defined(SQLITE_ENABLE_SESSION)
  if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){
    OpenSession *pSession = &p->aSession[0];
  if( c=='s' && cli_strncmp(azArg[0],"session",n)==0 && n>=3 ){
    struct AuxDb *pAuxDb = p->pAuxDb;
    OpenSession *pSession = &pAuxDb->aSession[0];
    char **azCmd = &azArg[1];
    int iSes = 0;
    int nCmd = nArg - 1;
    int i;
    if( nArg<=1 ) goto session_syntax_error;
    open_db(p, 0);
    if( nArg>=3 ){
      for(iSes=0; iSes<p->nSession; iSes++){
        if( strcmp(p->aSession[iSes].zName, azArg[1])==0 ) break;
      for(iSes=0; iSes<pAuxDb->nSession; iSes++){
        if( cli_strcmp(pAuxDb->aSession[iSes].zName, azArg[1])==0 ) break;
      }
      if( iSes<p->nSession ){
        pSession = &p->aSession[iSes];
      if( iSes<pAuxDb->nSession ){
        pSession = &pAuxDb->aSession[iSes];
        azCmd++;
        nCmd--;
      }else{
        pSession = &p->aSession[0];
        pSession = &pAuxDb->aSession[0];
        iSes = 0;
      }
    }

    /* .session attach TABLE
    ** Invoke the sqlite3session_attach() interface to attach a particular
    ** table so that it is never filtered.
    */
    if( strcmp(azCmd[0],"attach")==0 ){
    if( cli_strcmp(azCmd[0],"attach")==0 ){
      if( nCmd!=2 ) goto session_syntax_error;
      if( pSession->p==0 ){
        session_not_open:
        raw_printf(stderr, "ERROR: No sessions are open\n");
      }else{
        rc = sqlite3session_attach(pSession->p, azCmd[1]);
        if( rc ){
          raw_printf(stderr, "ERROR: sqlite3session_attach() returns %d\n", rc);
          rc = 0;
        }
      }
    }else

    /* .session changeset FILE
    ** .session patchset FILE
    ** Write a changeset or patchset into a file.  The file is overwritten.
    */
    if( strcmp(azCmd[0],"changeset")==0 || strcmp(azCmd[0],"patchset")==0 ){
    if( cli_strcmp(azCmd[0],"changeset")==0
     || cli_strcmp(azCmd[0],"patchset")==0
    ){
      FILE *out = 0;
      failIfSafeMode(p, "cannot run \".session %s\" in safe mode", azCmd[0]);
      if( nCmd!=2 ) goto session_syntax_error;
      if( pSession->p==0 ) goto session_not_open;
      out = fopen(azCmd[1], "wb");
      if( out==0 ){
        utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n", azCmd[1]);
        utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n",
                    azCmd[1]);
      }else{
        int szChng;
        void *pChng;
        if( azCmd[0][0]=='c' ){
          rc = sqlite3session_changeset(pSession->p, &szChng, &pChng);
        }else{
          rc = sqlite3session_patchset(pSession->p, &szChng, &pChng);
7267
7268
7269
7270
7271
7272
7273
7274

7275
7276

7277
7278

7279
7280
7281
7282
7283
7284
7285

7286
7287
7288
7289

7290
7291
7292
7293
7294
7295
7296
7297
7298
7299

7300
7301
7302

7303
7304
7305
7306
7307
7308
7309
7310
7311
7312
7313
7314


7315
7316
7317
7318
7319
7320
7321
7322
7323

7324
7325
7326
7327

7328
7329
7330
7331
7332
7333
7334
7335
7336
7337

7338
7339
7340

7341
7342
7343
7344
7345
7346
7347
7348
7349
7350
7351
7352



7353
7354
7355
7356
7357
7358
7359
7360

7361
7362
7363
7364
7365
7366


7367
7368
7369
7370
7371
7372



7373
7374
7375

7376
7377
7378
7379
7380
7381
7382
7383
7384

7385

7386
7387
7388
7389
7390
7391
7392
7393
7394
7395
7396
7397


7398
7399
7400
7401
7402
7403
7404

7405
7406
7407
7408
7409
7410
7411
7412
7413
7414
7415
7416

7417
7418
7419
7420
7421
7422
7423
7424
7425
7426
7427
7428
7429
7430

7431
7432
7433

7434
7435
7436
7437
7438
7439
7440
9996
9997
9998
9999
10000
10001
10002

10003
10004

10005
10006

10007
10008
10009
10010
10011
10012
10013

10014
10015
10016
10017

10018
10019
10020
10021
10022
10023
10024
10025
10026
10027

10028
10029
10030

10031
10032
10033
10034
10035
10036
10037
10038
10039
10040
10041
10042

10043
10044
10045
10046
10047
10048
10049
10050
10051
10052

10053
10054
10055
10056

10057
10058
10059
10060
10061
10062
10063
10064
10065
10066

10067
10068
10069

10070
10071
10072
10073
10074
10075
10076
10077
10078
10079



10080
10081
10082
10083
10084
10085
10086
10087
10088
10089

10090
10091
10092
10093
10094


10095
10096
10097
10098
10099
10100


10101
10102
10103
10104
10105

10106
10107
10108
10109
10110
10111
10112
10113
10114

10115
10116
10117
10118
10119
10120
10121
10122
10123
10124
10125
10126
10127


10128
10129
10130
10131
10132
10133
10134
10135

10136
10137
10138
10139
10140
10141
10142
10143
10144
10145
10146
10147

10148
10149
10150
10151
10152
10153
10154
10155
10156
10157
10158
10159
10160
10161

10162
10163
10164

10165
10166
10167
10168
10169
10170
10171
10172







-
+

-
+

-
+






-
+



-
+









-
+


-
+











-
+
+








-
+



-
+









-
+


-
+









-
-
-
+
+
+







-
+




-
-
+
+




-
-
+
+
+


-
+








-
+

+










-
-
+
+






-
+











-
+













-
+


-
+







        fclose(out);
      }
    }else

    /* .session close
    ** Close the identified session
    */
    if( strcmp(azCmd[0], "close")==0 ){
    if( cli_strcmp(azCmd[0], "close")==0 ){
      if( nCmd!=1 ) goto session_syntax_error;
      if( p->nSession ){
      if( pAuxDb->nSession ){
        session_close(pSession);
        p->aSession[iSes] = p->aSession[--p->nSession];
        pAuxDb->aSession[iSes] = pAuxDb->aSession[--pAuxDb->nSession];
      }
    }else

    /* .session enable ?BOOLEAN?
    ** Query or set the enable flag
    */
    if( strcmp(azCmd[0], "enable")==0 ){
    if( cli_strcmp(azCmd[0], "enable")==0 ){
      int ii;
      if( nCmd>2 ) goto session_syntax_error;
      ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
      if( p->nSession ){
      if( pAuxDb->nSession ){
        ii = sqlite3session_enable(pSession->p, ii);
        utf8_printf(p->out, "session %s enable flag = %d\n",
                    pSession->zName, ii);
      }
    }else

    /* .session filter GLOB ....
    ** Set a list of GLOB patterns of table names to be excluded.
    */
    if( strcmp(azCmd[0], "filter")==0 ){
    if( cli_strcmp(azCmd[0], "filter")==0 ){
      int ii, nByte;
      if( nCmd<2 ) goto session_syntax_error;
      if( p->nSession ){
      if( pAuxDb->nSession ){
        for(ii=0; ii<pSession->nFilter; ii++){
          sqlite3_free(pSession->azFilter[ii]);
        }
        sqlite3_free(pSession->azFilter);
        nByte = sizeof(pSession->azFilter[0])*(nCmd-1);
        pSession->azFilter = sqlite3_malloc( nByte );
        if( pSession->azFilter==0 ){
          raw_printf(stderr, "Error: out or memory\n");
          exit(1);
        }
        for(ii=1; ii<nCmd; ii++){
          pSession->azFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]);
          char *x = pSession->azFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]);
          shell_check_oom(x);
        }
        pSession->nFilter = ii-1;
      }
    }else

    /* .session indirect ?BOOLEAN?
    ** Query or set the indirect flag
    */
    if( strcmp(azCmd[0], "indirect")==0 ){
    if( cli_strcmp(azCmd[0], "indirect")==0 ){
      int ii;
      if( nCmd>2 ) goto session_syntax_error;
      ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
      if( p->nSession ){
      if( pAuxDb->nSession ){
        ii = sqlite3session_indirect(pSession->p, ii);
        utf8_printf(p->out, "session %s indirect flag = %d\n",
                    pSession->zName, ii);
      }
    }else

    /* .session isempty
    ** Determine if the session is empty
    */
    if( strcmp(azCmd[0], "isempty")==0 ){
    if( cli_strcmp(azCmd[0], "isempty")==0 ){
      int ii;
      if( nCmd!=1 ) goto session_syntax_error;
      if( p->nSession ){
      if( pAuxDb->nSession ){
        ii = sqlite3session_isempty(pSession->p);
        utf8_printf(p->out, "session %s isempty flag = %d\n",
                    pSession->zName, ii);
      }
    }else

    /* .session list
    ** List all currently open sessions
    */
    if( strcmp(azCmd[0],"list")==0 ){
      for(i=0; i<p->nSession; i++){
        utf8_printf(p->out, "%d %s\n", i, p->aSession[i].zName);
    if( cli_strcmp(azCmd[0],"list")==0 ){
      for(i=0; i<pAuxDb->nSession; i++){
        utf8_printf(p->out, "%d %s\n", i, pAuxDb->aSession[i].zName);
      }
    }else

    /* .session open DB NAME
    ** Open a new session called NAME on the attached database DB.
    ** DB is normally "main".
    */
    if( strcmp(azCmd[0],"open")==0 ){
    if( cli_strcmp(azCmd[0],"open")==0 ){
      char *zName;
      if( nCmd!=3 ) goto session_syntax_error;
      zName = azCmd[2];
      if( zName[0]==0 ) goto session_syntax_error;
      for(i=0; i<p->nSession; i++){
        if( strcmp(p->aSession[i].zName,zName)==0 ){
      for(i=0; i<pAuxDb->nSession; i++){
        if( cli_strcmp(pAuxDb->aSession[i].zName,zName)==0 ){
          utf8_printf(stderr, "Session \"%s\" already exists\n", zName);
          goto meta_command_exit;
        }
      }
      if( p->nSession>=ArraySize(p->aSession) ){
        raw_printf(stderr, "Maximum of %d sessions\n", ArraySize(p->aSession));
      if( pAuxDb->nSession>=ArraySize(pAuxDb->aSession) ){
        raw_printf(stderr,
                   "Maximum of %d sessions\n", ArraySize(pAuxDb->aSession));
        goto meta_command_exit;
      }
      pSession = &p->aSession[p->nSession];
      pSession = &pAuxDb->aSession[pAuxDb->nSession];
      rc = sqlite3session_create(p->db, azCmd[1], &pSession->p);
      if( rc ){
        raw_printf(stderr, "Cannot open session: error code=%d\n", rc);
        rc = 0;
        goto meta_command_exit;
      }
      pSession->nFilter = 0;
      sqlite3session_table_filter(pSession->p, session_filter, pSession);
      p->nSession++;
      pAuxDb->nSession++;
      pSession->zName = sqlite3_mprintf("%s", zName);
      shell_check_oom(pSession->zName);
    }else
    /* If no command name matches, show a syntax error */
    session_syntax_error:
    showHelp(p->out, "session");
  }else
#endif

#ifdef SQLITE_DEBUG
  /* Undocumented commands for internal testing.  Subject to change
  ** without notice. */
  if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){
    if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){
  if( c=='s' && n>=10 && cli_strncmp(azArg[0], "selftest-", 9)==0 ){
    if( cli_strncmp(azArg[0]+9, "boolean", n-9)==0 ){
      int i, v;
      for(i=1; i<nArg; i++){
        v = booleanValue(azArg[i]);
        utf8_printf(p->out, "%s: %d 0x%x\n", azArg[i], v, v);
      }
    }
    if( strncmp(azArg[0]+9, "integer", n-9)==0 ){
    if( cli_strncmp(azArg[0]+9, "integer", n-9)==0 ){
      int i; sqlite3_int64 v;
      for(i=1; i<nArg; i++){
        char zBuf[200];
        v = integerValue(azArg[i]);
        sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v);
        utf8_printf(p->out, "%s", zBuf);
      }
    }
  }else
#endif

  if( c=='s' && n>=4 && strncmp(azArg[0],"selftest",n)==0 ){
  if( c=='s' && n>=4 && cli_strncmp(azArg[0],"selftest",n)==0 ){
    int bIsInit = 0;         /* True to initialize the SELFTEST table */
    int bVerbose = 0;        /* Verbose output */
    int bSelftestExists;     /* True if SELFTEST already exists */
    int i, k;                /* Loop counters */
    int nTest = 0;           /* Number of tests runs */
    int nErr = 0;            /* Number of errors seen */
    ShellText str;           /* Answer for a query */
    sqlite3_stmt *pStmt = 0; /* Query against the SELFTEST table */

    open_db(p,0);
    for(i=1; i<nArg; i++){
      const char *z = azArg[i];
      if( z[0]=='-' && z[1]=='-' ) z++;
      if( strcmp(z,"-init")==0 ){
      if( cli_strcmp(z,"-init")==0 ){
        bIsInit = 1;
      }else
      if( strcmp(z,"-v")==0 ){
      if( cli_strcmp(z,"-v")==0 ){
        bVerbose++;
      }else
      {
        utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
                    azArg[i], azArg[0]);
        raw_printf(stderr, "Should be one of: --init -v\n");
        rc = 1;
7472
7473
7474
7475
7476
7477
7478



7479
7480
7481
7482
7483
7484
7485

7486
7487
7488

7489
7490
7491
7492
7493
7494
7495
7496
7497
7498
7499
7500
7501
7502

7503
7504
7505
7506
7507
7508
7509
7510
7511
7512
7513
7514
7515
7516
7517
7518
7519
7520
7521
7522

7523
7524
7525
7526
7527
7528
7529
7530
7531
7532
7533
7534
7535
7536
7537

7538
7539
7540
7541
7542
7543
7544
7545
7546
7547
7548
7549
7550
7551
7552
7553
7554
7555

7556
7557
7558
7559


7560
7561
7562
7563

7564
7565
7566
7567
7568
7569

7570
7571
7572
7573
7574
7575
7576
7577
7578
7579
7580
7581
7582
7583
7584
7585

7586
7587

7588
7589
7590

7591
7592
7593
7594
7595
7596
7597
7598
7599
7600
7601

7602
7603

7604
7605
7606
7607
7608


7609
7610

7611
7612
7613

7614
7615
7616
7617

7618
7619
7620
7621
7622
7623
7624
10204
10205
10206
10207
10208
10209
10210
10211
10212
10213
10214
10215

10216

10217

10218
10219
10220

10221
10222
10223
10224
10225
10226
10227
10228
10229
10230
10231
10232
10233
10234

10235
10236
10237
10238
10239
10240
10241
10242
10243
10244
10245
10246
10247
10248
10249
10250
10251
10252
10253
10254

10255
10256
10257
10258
10259
10260
10261
10262
10263
10264
10265
10266
10267
10268
10269

10270
10271
10272
10273
10274
10275
10276
10277
10278
10279
10280
10281
10282
10283
10284
10285
10286
10287

10288
10289
10290


10291
10292
10293
10294
10295

10296
10297
10298
10299
10300
10301

10302

10303
10304
10305
10306
10307
10308
10309
10310
10311
10312
10313
10314
10315
10316

10317
10318

10319
10320
10321

10322
10323
10324
10325
10326
10327
10328
10329
10330
10331
10332
10333
10334
10335

10336
10337
10338
10339


10340
10341
10342

10343
10344
10345

10346
10347
10348


10349
10350
10351
10352
10353
10354
10355
10356







+
+
+


-

-

-
+


-
+













-
+



















-
+














-
+

















-
+


-
-
+
+



-
+





-
+
-














-
+

-
+


-
+











+

-
+



-
-
+
+

-
+


-
+


-
-
+







      }
      for(i=1; sqlite3_step(pStmt)==SQLITE_ROW; i++){
        int tno = sqlite3_column_int(pStmt, 0);
        const char *zOp = (const char*)sqlite3_column_text(pStmt, 1);
        const char *zSql = (const char*)sqlite3_column_text(pStmt, 2);
        const char *zAns = (const char*)sqlite3_column_text(pStmt, 3);

        if( zOp==0 ) continue;
        if( zSql==0 ) continue;
        if( zAns==0 ) continue;
        k = 0;
        if( bVerbose>0 ){
          char *zQuote = sqlite3_mprintf("%q", zSql);
          printf("%d: %s %s\n", tno, zOp, zSql);
          sqlite3_free(zQuote);
        }
        if( strcmp(zOp,"memo")==0 ){
        if( cli_strcmp(zOp,"memo")==0 ){
          utf8_printf(p->out, "%s\n", zSql);
        }else
        if( strcmp(zOp,"run")==0 ){
        if( cli_strcmp(zOp,"run")==0 ){
          char *zErrMsg = 0;
          str.n = 0;
          str.z[0] = 0;
          rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg);
          nTest++;
          if( bVerbose ){
            utf8_printf(p->out, "Result: %s\n", str.z);
          }
          if( rc || zErrMsg ){
            nErr++;
            rc = 1;
            utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg);
            sqlite3_free(zErrMsg);
          }else if( strcmp(zAns,str.z)!=0 ){
          }else if( cli_strcmp(zAns,str.z)!=0 ){
            nErr++;
            rc = 1;
            utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns);
            utf8_printf(p->out, "%d:      Got: [%s]\n", tno, str.z);
          }
        }else
        {
          utf8_printf(stderr,
            "Unknown operation \"%s\" on selftest line %d\n", zOp, tno);
          rc = 1;
          break;
        }
      } /* End loop over rows of content from SELFTEST */
      sqlite3_finalize(pStmt);
    } /* End loop over k */
    freeText(&str);
    utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest);
  }else

  if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
  if( c=='s' && cli_strncmp(azArg[0], "separator", n)==0 ){
    if( nArg<2 || nArg>3 ){
      raw_printf(stderr, "Usage: .separator COL ?ROW?\n");
      rc = 1;
    }
    if( nArg>=2 ){
      sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator,
                       "%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]);
    }
    if( nArg>=3 ){
      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator,
                       "%.*s", (int)ArraySize(p->rowSeparator)-1, azArg[2]);
    }
  }else

  if( c=='s' && n>=4 && strncmp(azArg[0],"sha3sum",n)==0 ){
  if( c=='s' && n>=4 && cli_strncmp(azArg[0],"sha3sum",n)==0 ){
    const char *zLike = 0;   /* Which table to checksum. 0 means everything */
    int i;                   /* Loop counter */
    int bSchema = 0;         /* Also hash the schema */
    int bSeparate = 0;       /* Hash each table separately */
    int iSize = 224;         /* Hash algorithm to use */
    int bDebug = 0;          /* Only show the query that would have run */
    sqlite3_stmt *pStmt;     /* For querying tables names */
    char *zSql;              /* SQL to be run */
    char *zSep;              /* Separator */
    ShellText sSql;          /* Complete SQL for the query to run the hash */
    ShellText sQuery;        /* Set of queries used to read all content */
    open_db(p, 0);
    for(i=1; i<nArg; i++){
      const char *z = azArg[i];
      if( z[0]=='-' ){
        z++;
        if( z[0]=='-' ) z++;
        if( strcmp(z,"schema")==0 ){
        if( cli_strcmp(z,"schema")==0 ){
          bSchema = 1;
        }else
        if( strcmp(z,"sha3-224")==0 || strcmp(z,"sha3-256")==0
         || strcmp(z,"sha3-384")==0 || strcmp(z,"sha3-512")==0
        if( cli_strcmp(z,"sha3-224")==0 || cli_strcmp(z,"sha3-256")==0
         || cli_strcmp(z,"sha3-384")==0 || cli_strcmp(z,"sha3-512")==0
        ){
          iSize = atoi(&z[5]);
        }else
        if( strcmp(z,"debug")==0 ){
        if( cli_strcmp(z,"debug")==0 ){
          bDebug = 1;
        }else
        {
          utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
                      azArg[i], azArg[0]);
          raw_printf(stderr, "Should be one of: --schema"
          showHelp(p->out, azArg[0]);
                             " --sha3-224 --sha3-256 --sha3-384 --sha3-512\n");
          rc = 1;
          goto meta_command_exit;
        }
      }else if( zLike ){
        raw_printf(stderr, "Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n");
        rc = 1;
        goto meta_command_exit;
      }else{
        zLike = z;
        bSeparate = 1;
        if( sqlite3_strlike("sqlite\\_%", zLike, '\\')==0 ) bSchema = 1;
      }
    }
    if( bSchema ){
      zSql = "SELECT lower(name) FROM sqlite_master"
      zSql = "SELECT lower(name) as tname FROM sqlite_schema"
             " WHERE type='table' AND coalesce(rootpage,0)>1"
             " UNION ALL SELECT 'sqlite_master'"
             " UNION ALL SELECT 'sqlite_schema'"
             " ORDER BY 1 collate nocase";
    }else{
      zSql = "SELECT lower(name) FROM sqlite_master"
      zSql = "SELECT lower(name) as tname FROM sqlite_schema"
             " WHERE type='table' AND coalesce(rootpage,0)>1"
             " AND name NOT LIKE 'sqlite_%'"
             " ORDER BY 1 collate nocase";
    }
    sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
    initText(&sQuery);
    initText(&sSql);
    appendText(&sSql, "WITH [sha3sum$query](a,b) AS(",0);
    zSep = "VALUES(";
    while( SQLITE_ROW==sqlite3_step(pStmt) ){
      const char *zTab = (const char*)sqlite3_column_text(pStmt,0);
      if( zTab==0 ) continue;
      if( zLike && sqlite3_strlike(zLike, zTab, 0)!=0 ) continue;
      if( strncmp(zTab, "sqlite_",7)!=0 ){
      if( cli_strncmp(zTab, "sqlite_",7)!=0 ){
        appendText(&sQuery,"SELECT * FROM ", 0);
        appendText(&sQuery,zTab,'"');
        appendText(&sQuery," NOT INDEXED;", 0);
      }else if( strcmp(zTab, "sqlite_master")==0 ){
        appendText(&sQuery,"SELECT type,name,tbl_name,sql FROM sqlite_master"
      }else if( cli_strcmp(zTab, "sqlite_schema")==0 ){
        appendText(&sQuery,"SELECT type,name,tbl_name,sql FROM sqlite_schema"
                           " ORDER BY name;", 0);
      }else if( strcmp(zTab, "sqlite_sequence")==0 ){
      }else if( cli_strcmp(zTab, "sqlite_sequence")==0 ){
        appendText(&sQuery,"SELECT name,seq FROM sqlite_sequence"
                           " ORDER BY name;", 0);
      }else if( strcmp(zTab, "sqlite_stat1")==0 ){
      }else if( cli_strcmp(zTab, "sqlite_stat1")==0 ){
        appendText(&sQuery,"SELECT tbl,idx,stat FROM sqlite_stat1"
                           " ORDER BY tbl,idx;", 0);
      }else if( strcmp(zTab, "sqlite_stat3")==0
             || strcmp(zTab, "sqlite_stat4")==0 ){
      }else if( cli_strcmp(zTab, "sqlite_stat4")==0 ){
        appendText(&sQuery, "SELECT * FROM ", 0);
        appendText(&sQuery, zTab, 0);
        appendText(&sQuery, " ORDER BY tbl, idx, rowid;\n", 0);
      }
      appendText(&sSql, zSep, 0);
      appendText(&sSql, sQuery.z, '\'');
      sQuery.n = 0;
7636
7637
7638
7639
7640
7641
7642

7643
7644
7645
7646
7647
7648
7649




















































7650
7651
7652
7653

7654

7655

7656
7657
7658

7659
7660
7661
7662
7663
7664
7665

7666
7667
7668
7669

7670
7671
7672
7673

7674
7675

7676

7677
7678
7679
7680
7681
7682
7683
7684

7685
7686
7687
7688









7689


7690
7691
7692
7693
7694
7695
7696
7697
7698
7699
7700






7701

7702
7703

7704
7705
7706
7707
7708

7709
7710
7711

7712





7713


7714
7715
7716
7717

7718
7719
7720
7721
7722
7723
7724



7725
7726
7727
7728
7729
7730
7731
10368
10369
10370
10371
10372
10373
10374
10375
10376
10377
10378
10379
10380
10381
10382
10383
10384
10385
10386
10387
10388
10389
10390
10391
10392
10393
10394
10395
10396
10397
10398
10399
10400
10401
10402
10403
10404
10405
10406
10407
10408
10409
10410
10411
10412
10413
10414
10415
10416
10417
10418
10419
10420
10421
10422
10423
10424
10425
10426
10427
10428
10429
10430
10431
10432
10433
10434
10435
10436
10437

10438
10439
10440

10441
10442
10443
10444
10445
10446
10447
10448
10449
10450
10451

10452
10453
10454
10455

10456
10457
10458
10459

10460
10461

10462
10463
10464
10465
10466
10467
10468
10469
10470
10471

10472
10473
10474
10475
10476
10477
10478
10479
10480
10481
10482
10483
10484
10485

10486
10487
10488
10489
10490
10491
10492
10493
10494
10495
10496
10497
10498
10499
10500
10501
10502
10503
10504

10505
10506

10507
10508
10509
10510
10511

10512
10513
10514

10515
10516
10517
10518
10519
10520
10521

10522
10523
10524
10525
10526

10527
10528
10529
10530
10531



10532
10533
10534
10535
10536
10537
10538
10539
10540
10541







+







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+

+
-
+



+






-
+



-
+



-
+

-
+

+







-
+




+
+
+
+
+
+
+
+
+
-
+
+











+
+
+
+
+
+
-
+

-
+




-
+


-
+

+
+
+
+
+
-
+
+



-
+




-
-
-
+
+
+







    }else{
      zSql = sqlite3_mprintf(
          "%s))"
          " SELECT lower(hex(sha3_query(group_concat(a,''),%d))) AS hash"
          "   FROM [sha3sum$query]",
          sSql.z, iSize);
    }
    shell_check_oom(zSql);
    freeText(&sQuery);
    freeText(&sSql);
    if( bDebug ){
      utf8_printf(p->out, "%s\n", zSql);
    }else{
      shell_exec(p, zSql, 0);
    }
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) && !defined(SQLITE_OMIT_VIRTUALTABLE)
    {
      int lrc;
      char *zRevText = /* Query for reversible to-blob-to-text check */
        "SELECT lower(name) as tname FROM sqlite_schema\n"
        "WHERE type='table' AND coalesce(rootpage,0)>1\n"
        "AND name NOT LIKE 'sqlite_%%'%s\n"
        "ORDER BY 1 collate nocase";
      zRevText = sqlite3_mprintf(zRevText, zLike? " AND name LIKE $tspec" : "");
      zRevText = sqlite3_mprintf(
          /* lower-case query is first run, producing upper-case query. */
          "with tabcols as materialized(\n"
          "select tname, cname\n"
          "from ("
          " select ss.tname as tname, ti.name as cname\n"
          " from (%z) ss\n inner join pragma_table_info(tname) ti))\n"
          "select 'SELECT total(bad_text_count) AS bad_text_count\n"
          "FROM ('||group_concat(query, ' UNION ALL ')||')' as btc_query\n"
          " from (select 'SELECT COUNT(*) AS bad_text_count\n"
          "FROM '||tname||' WHERE '\n"
          "||group_concat('CAST(CAST('||cname||' AS BLOB) AS TEXT)<>'||cname\n"
          "|| ' AND typeof('||cname||')=''text'' ',\n"
          "' OR ') as query, tname from tabcols group by tname)"
          , zRevText);
      shell_check_oom(zRevText);
      if( bDebug ) utf8_printf(p->out, "%s\n", zRevText);
      lrc = sqlite3_prepare_v2(p->db, zRevText, -1, &pStmt, 0);
      assert(lrc==SQLITE_OK);
      if( zLike ) sqlite3_bind_text(pStmt,1,zLike,-1,SQLITE_STATIC);
      lrc = SQLITE_ROW==sqlite3_step(pStmt);
      if( lrc ){
        const char *zGenQuery = (char*)sqlite3_column_text(pStmt,0);
        sqlite3_stmt *pCheckStmt;
        lrc = sqlite3_prepare_v2(p->db, zGenQuery, -1, &pCheckStmt, 0);
        if( bDebug ) utf8_printf(p->out, "%s\n", zGenQuery);
        if( SQLITE_OK==lrc ){
          if( SQLITE_ROW==sqlite3_step(pCheckStmt) ){
            double countIrreversible = sqlite3_column_double(pCheckStmt, 0);
            if( countIrreversible>0 ){
              int sz = (int)(countIrreversible + 0.5);
              utf8_printf(stderr,
                 "Digest includes %d invalidly encoded text field%s.\n",
                 sz, (sz>1)? "s": "");
            }
          }
          sqlite3_finalize(pCheckStmt);
        }
        sqlite3_finalize(pStmt);
      }
      sqlite3_free(zRevText);
    }
#endif /* !defined(*_OMIT_SCHEMA_PRAGMAS) && !defined(*_OMIT_VIRTUALTABLE) */
    sqlite3_free(zSql);
  }else

#ifndef SQLITE_NOHAVE_SYSTEM
#if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE)
  if( c=='s'
   && (cli_strncmp(azArg[0], "shell", n)==0
   && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
       || cli_strncmp(azArg[0],"system",n)==0)
  ){
    char *zCmd;
    int i, x;
    failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
    if( nArg<2 ){
      raw_printf(stderr, "Usage: .system COMMAND\n");
      rc = 1;
      goto meta_command_exit;
    }
    zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
    for(i=2; i<nArg; i++){
    for(i=2; i<nArg && zCmd!=0; i++){
      zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
                             zCmd, azArg[i]);
    }
    x = system(zCmd);
    x = zCmd!=0 ? system(zCmd) : 1;
    sqlite3_free(zCmd);
    if( x ) raw_printf(stderr, "System command returns %d\n", x);
  }else
#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
#endif /* !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE) */

  if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
  if( c=='s' && cli_strncmp(azArg[0], "show", n)==0 ){
    static const char *azBool[] = { "off", "on", "trigger", "full"};
    const char *zOut;
    int i;
    if( nArg!=1 ){
      raw_printf(stderr, "Usage: .show\n");
      rc = 1;
      goto meta_command_exit;
    }
    utf8_printf(p->out, "%12.12s: %s\n","echo",
                                  azBool[ShellHasFlag(p, SHFLG_Echo)]);
                azBool[ShellHasFlag(p, SHFLG_Echo)]);
    utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);
    utf8_printf(p->out, "%12.12s: %s\n","explain",
         p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off");
    utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]);
    if( p->mode==MODE_Column
     || (p->mode>=MODE_Markdown && p->mode<=MODE_Box)
    ){
      utf8_printf
        (p->out, "%12.12s: %s --wrap %d --wordwrap %s --%squote\n", "mode",
         modeDescr[p->mode], p->cmOpts.iWrap,
         p->cmOpts.bWordWrap ? "on" : "off",
         p->cmOpts.bQuote ? "" : "no");
    }else{
    utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]);
      utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]);
    }
    utf8_printf(p->out, "%12.12s: ", "nullvalue");
      output_c_string(p->out, p->nullValue);
      raw_printf(p->out, "\n");
    utf8_printf(p->out,"%12.12s: %s\n","output",
            strlen30(p->outfile) ? p->outfile : "stdout");
    utf8_printf(p->out,"%12.12s: ", "colseparator");
      output_c_string(p->out, p->colSeparator);
      raw_printf(p->out, "\n");
    utf8_printf(p->out,"%12.12s: ", "rowseparator");
      output_c_string(p->out, p->rowSeparator);
      raw_printf(p->out, "\n");
    switch( p->statsOn ){
      case 0:  zOut = "off";     break;
      default: zOut = "on";      break;
      case 2:  zOut = "stmt";    break;
      case 3:  zOut = "vmstep";  break;
    }
    utf8_printf(p->out, "%12.12s: %s\n","stats", azBool[p->statsOn!=0]);
    utf8_printf(p->out, "%12.12s: %s\n","stats", zOut);
    utf8_printf(p->out, "%12.12s: ", "width");
    for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
    for (i=0;i<p->nWidth;i++) {
      raw_printf(p->out, "%d ", p->colWidth[i]);
    }
    raw_printf(p->out, "\n");
    utf8_printf(p->out, "%12.12s: %s\n", "filename",
                p->zDbFilename ? p->zDbFilename : "");
                p->pAuxDb->zDbFilename ? p->pAuxDb->zDbFilename : "");
  }else

  if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){
  if( c=='s' && cli_strncmp(azArg[0], "stats", n)==0 ){
    if( nArg==2 ){
      if( cli_strcmp(azArg[1],"stmt")==0 ){
        p->statsOn = 2;
      }else if( cli_strcmp(azArg[1],"vmstep")==0 ){
        p->statsOn = 3;
      }else{
      p->statsOn = (u8)booleanValue(azArg[1]);
        p->statsOn = (u8)booleanValue(azArg[1]);
      }
    }else if( nArg==1 ){
      display_stats(p->db, p, 0);
    }else{
      raw_printf(stderr, "Usage: .stats ?on|off?\n");
      raw_printf(stderr, "Usage: .stats ?on|off|stmt|vmstep?\n");
      rc = 1;
    }
  }else

  if( (c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0)
   || (c=='i' && (strncmp(azArg[0], "indices", n)==0
                 || strncmp(azArg[0], "indexes", n)==0) )
  if( (c=='t' && n>1 && cli_strncmp(azArg[0], "tables", n)==0)
   || (c=='i' && (cli_strncmp(azArg[0], "indices", n)==0
                 || cli_strncmp(azArg[0], "indexes", n)==0) )
  ){
    sqlite3_stmt *pStmt;
    char **azResult;
    int nRow, nAlloc;
    int ii;
    ShellText s;
    initText(&s);
7753
7754
7755
7756
7757
7758
7759
7760

7761
7762
7763
7764
7765
7766
7767
7768
7769
7770

7771
7772



7773
7774
7775
7776
7777
7778
7779
7780
7781
7782
7783
7784
7785
7786
7787
7788
7789
7790

7791
7792
7793
7794
7795

7796
7797
7798
7799
7800
7801
7802
10563
10564
10565
10566
10567
10568
10569

10570
10571
10572
10573
10574
10575
10576
10577
10578
10579
10580
10581


10582
10583
10584
10585
10586
10587
10588
10589
10590
10591
10592
10593
10594
10595
10596
10597
10598
10599
10600
10601

10602
10603
10604
10605
10606

10607
10608
10609
10610
10611
10612
10613
10614







-
+










+
-
-
+
+
+

















-
+




-
+







        appendText(&s, "SELECT name FROM ", 0);
      }else{
        appendText(&s, "SELECT ", 0);
        appendText(&s, zDbName, '\'');
        appendText(&s, "||'.'||name FROM ", 0);
      }
      appendText(&s, zDbName, '"');
      appendText(&s, ".sqlite_master ", 0);
      appendText(&s, ".sqlite_schema ", 0);
      if( c=='t' ){
        appendText(&s," WHERE type IN ('table','view')"
                      "   AND name NOT LIKE 'sqlite_%'"
                      "   AND name LIKE ?1", 0);
      }else{
        appendText(&s," WHERE type='index'"
                      "   AND tbl_name LIKE ?1", 0);
      }
    }
    rc = sqlite3_finalize(pStmt);
    if( rc==SQLITE_OK ){
    appendText(&s, " ORDER BY 1", 0);
    rc = sqlite3_prepare_v2(p->db, s.z, -1, &pStmt, 0);
      appendText(&s, " ORDER BY 1", 0);
      rc = sqlite3_prepare_v2(p->db, s.z, -1, &pStmt, 0);
    }
    freeText(&s);
    if( rc ) return shellDatabaseError(p->db);

    /* Run the SQL statement prepared by the above block. Store the results
    ** as an array of nul-terminated strings in azResult[].  */
    nRow = nAlloc = 0;
    azResult = 0;
    if( nArg>1 ){
      sqlite3_bind_text(pStmt, 1, azArg[1], -1, SQLITE_TRANSIENT);
    }else{
      sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC);
    }
    while( sqlite3_step(pStmt)==SQLITE_ROW ){
      if( nRow>=nAlloc ){
        char **azNew;
        int n2 = nAlloc*2 + 10;
        azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2);
        if( azNew==0 ) shell_out_of_memory();
        shell_check_oom(azNew);
        nAlloc = n2;
        azResult = azNew;
      }
      azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
      if( 0==azResult[nRow] ) shell_out_of_memory();
      shell_check_oom(azResult[nRow]);
      nRow++;
    }
    if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
      rc = shellDatabaseError(p->db);
    }

    /* Pretty-print the contents of array azResult[] to the output */
7821
7822
7823
7824
7825
7826
7827

7828
7829

7830
7831
7832
7833
7834
7835
7836
7837
7838
7839
7840

7841
7842
7843

7844
7845
7846

7847
7848
7849
7850
7851
7852
7853
7854
7855
7856
7857
7858
7859












7860
7861

7862
7863

7864
7865
7866
7867






7868
7869
7870
7871
7872
7873
7874
7875
7876
7877
7878
7879
7880
7881
7882
7883
7884
7885
7886

7887
7888
7889
7890
7891
7892
7893
7894
7895
7896
7897
7898
7899
7900

7901
7902
7903
7904
7905
7906
7907
7908
7909
7910
7911
7912
7913
7914





7915
7916
7917
7918
7919
7920
7921
7922

7923
7924
7925
7926
7927
7928
7929
7930
7931
7932
7933
7934
7935
7936
7937
7938
7939
7940
7941
7942
7943
7944
7945
7946





















7947
7948
7949
7950
7951
7952
7953
7954
7955
7956
7957
7958
7959
7960
7961
7962
7963
7964
7965
7966
7967






7968
7969
7970
7971
7972
7973
7974
7975
7976
7977
7978








7979
7980

7981
7982
7983
7984


7985


































7986
7987
7988
7989

7990
7991
7992
7993
7994
7995
7996
7997
7998
7999

8000
8001
8002
8003
8004

8005
8006
8007
8008
8009
8010
8011
8012
8013
8014
8015
8016
8017
8018

8019
8020
8021
8022
8023
8024
8025
10633
10634
10635
10636
10637
10638
10639
10640
10641

10642
10643
10644
10645
10646
10647
10648
10649
10650
10651
10652
10653
10654
10655
10656

10657
10658
10659
10660
10661
10662
10663











10664
10665
10666
10667
10668
10669
10670
10671
10672
10673
10674
10675
10676

10677
10678

10679




10680
10681
10682
10683
10684
10685
10686
10687
10688
10689
10690
10691
10692
10693
10694
10695
10696
10697
10698
10699
10700
10701
10702
10703

10704
10705
10706
10707
10708
10709
10710
10711
10712
10713
10714
10715
10716
10717

10718
10719
10720
10721
10722
10723
10724
10725
10726
10727
10728
10729
10730
10731
10732
10733
10734
10735
10736
10737
10738
10739
10740
10741
10742

10743

10744
10745
10746
10747
10748
10749
10750
10751
10752

10753
10754
10755
10756
10757
10758
10759
10760
10761
10762
10763
10764
10765
10766
10767
10768
10769
10770
10771
10772
10773
10774
10775
10776
10777
10778
10779
10780
10781
10782
10783
10784
10785
10786
10787
10788
10789
10790
10791
10792

10793
10794
10795
10796
10797
10798
10799
10800
10801
10802
10803
10804
10805
10806
10807
10808
10809
10810
10811
10812
10813
10814
10815
10816
10817
10818
10819
10820
10821
10822
10823
10824
10825
10826
10827
10828
10829
10830
10831
10832
10833
10834

10835
10836
10837
10838
10839
10840
10841
10842
10843
10844
10845
10846
10847
10848
10849
10850
10851
10852
10853
10854
10855
10856
10857
10858
10859
10860
10861
10862
10863
10864
10865
10866
10867
10868
10869
10870
10871
10872
10873
10874
10875
10876
10877
10878
10879

10880
10881
10882
10883
10884
10885
10886
10887
10888
10889

10890
10891
10892
10893
10894

10895
10896
10897
10898
10899
10900
10901
10902
10903
10904
10905
10906
10907
10908

10909
10910
10911
10912
10913
10914
10915
10916







+

-
+











+


-
+



+


-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

-
+

-
+
-
-
-
-
+
+
+
+
+
+


















-
+













-
+














+
+
+
+
+





-

-
+








-















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
















+
+
+
+
+
+











+
+
+
+
+
+
+
+

-
+




+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+









-
+




-
+













-
+







      }
    }

    for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]);
    sqlite3_free(azResult);
  }else

#ifndef SQLITE_SHELL_FIDDLE
  /* Begin redirecting output to the file "testcase-out.txt" */
  if( c=='t' && strcmp(azArg[0],"testcase")==0 ){
  if( c=='t' && cli_strcmp(azArg[0],"testcase")==0 ){
    output_reset(p);
    p->out = output_file_open("testcase-out.txt", 0);
    if( p->out==0 ){
      raw_printf(stderr, "Error: cannot open 'testcase-out.txt'\n");
    }
    if( nArg>=2 ){
      sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]);
    }else{
      sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?");
    }
  }else
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

#ifndef SQLITE_UNTESTABLE
  if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 ){
  if( c=='t' && n>=8 && cli_strncmp(azArg[0], "testctrl", n)==0 ){
    static const struct {
       const char *zCtrlName;   /* Name of a test-control option */
       int ctrlCode;            /* Integer code for that option */
       int unSafe;              /* Not valid for --safe mode */
       const char *zUsage;      /* Usage notes */
    } aCtrl[] = {
      { "always",             SQLITE_TESTCTRL_ALWAYS,        "BOOLEAN"            },
      { "assert",             SQLITE_TESTCTRL_ASSERT,        "BOOLEAN"            },
    /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, ""          },*/
    /*{ "bitvec_test",        SQLITE_TESTCTRL_BITVEC_TEST,   ""                },*/
      { "byteorder",          SQLITE_TESTCTRL_BYTEORDER,     ""                   },
    /*{ "fault_install",      SQLITE_TESTCTRL_FAULT_INSTALL, ""                }, */
      { "imposter",           SQLITE_TESTCTRL_IMPOSTER,   "SCHEMA ON/OFF ROOTPAGE"},
      { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, "BOOLEAN"       },
      { "localtime_fault",    SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN"           },
      { "never_corrupt",      SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN"            },
      { "optimizations",      SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK"       },
    {"always",             SQLITE_TESTCTRL_ALWAYS, 1,     "BOOLEAN"         },
    {"assert",             SQLITE_TESTCTRL_ASSERT, 1,     "BOOLEAN"         },
  /*{"benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,1, ""        },*/
  /*{"bitvec_test",        SQLITE_TESTCTRL_BITVEC_TEST, 1,  ""              },*/
    {"byteorder",          SQLITE_TESTCTRL_BYTEORDER, 0,  ""                },
    {"extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,0,"BOOLEAN"  },
  /*{"fault_install",      SQLITE_TESTCTRL_FAULT_INSTALL, 1,""              },*/
    {"imposter",         SQLITE_TESTCTRL_IMPOSTER,1,"SCHEMA ON/OFF ROOTPAGE"},
    {"internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS,0,""          },
    {"localtime_fault",    SQLITE_TESTCTRL_LOCALTIME_FAULT,0,"BOOLEAN"      },
    {"never_corrupt",      SQLITE_TESTCTRL_NEVER_CORRUPT,1, "BOOLEAN"       },
    {"optimizations",      SQLITE_TESTCTRL_OPTIMIZATIONS,0,"DISABLE-MASK"   },
#ifdef YYCOVERAGE
      { "parser_coverage",    SQLITE_TESTCTRL_PARSER_COVERAGE, ""                 },
    {"parser_coverage",    SQLITE_TESTCTRL_PARSER_COVERAGE,0,""             },
#endif
      { "pending_byte",       SQLITE_TESTCTRL_PENDING_BYTE,  "OFFSET  "           },
    {"pending_byte",       SQLITE_TESTCTRL_PENDING_BYTE,0, "OFFSET  "       },
      { "prng_reset",         SQLITE_TESTCTRL_PRNG_RESET,    ""                   },
      { "prng_restore",       SQLITE_TESTCTRL_PRNG_RESTORE,  ""                   },
      { "prng_save",          SQLITE_TESTCTRL_PRNG_SAVE,     ""                   },
      { "reserve",            SQLITE_TESTCTRL_RESERVE,       "BYTES-OF-RESERVE"   },
    {"prng_restore",       SQLITE_TESTCTRL_PRNG_RESTORE,0, ""               },
    {"prng_save",          SQLITE_TESTCTRL_PRNG_SAVE,   0, ""               },
    {"prng_seed",          SQLITE_TESTCTRL_PRNG_SEED,   0, "SEED ?db?"      },
    {"seek_count",         SQLITE_TESTCTRL_SEEK_COUNT,  0, ""               },
    {"sorter_mmap",        SQLITE_TESTCTRL_SORTER_MMAP, 0, "NMAX"           },
    {"tune",               SQLITE_TESTCTRL_TUNE,        1, "ID VALUE"       },
    };
    int testctrl = -1;
    int iCtrl = -1;
    int rc2 = 0;    /* 0: usage.  1: %d  2: %x  3: no-output */
    int isOk = 0;
    int i, n2;
    const char *zCmd = 0;

    open_db(p, 0);
    zCmd = nArg>=2 ? azArg[1] : "help";

    /* The argument can optionally begin with "-" or "--" */
    if( zCmd[0]=='-' && zCmd[1] ){
      zCmd++;
      if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
    }

    /* --help lists all test-controls */
    if( strcmp(zCmd,"help")==0 ){
    if( cli_strcmp(zCmd,"help")==0 ){
      utf8_printf(p->out, "Available test-controls:\n");
      for(i=0; i<ArraySize(aCtrl); i++){
        utf8_printf(p->out, "  .testctrl %s %s\n",
                    aCtrl[i].zCtrlName, aCtrl[i].zUsage);
      }
      rc = 1;
      goto meta_command_exit;
    }

    /* convert testctrl text option to value. allow any unique prefix
    ** of the option name, or a numerical value. */
    n2 = strlen30(zCmd);
    for(i=0; i<ArraySize(aCtrl); i++){
      if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
      if( cli_strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
        if( testctrl<0 ){
          testctrl = aCtrl[i].ctrlCode;
          iCtrl = i;
        }else{
          utf8_printf(stderr, "Error: ambiguous test-control: \"%s\"\n"
                              "Use \".testctrl --help\" for help\n", zCmd);
          rc = 1;
          goto meta_command_exit;
        }
      }
    }
    if( testctrl<0 ){
      utf8_printf(stderr,"Error: unknown test-control: %s\n"
                         "Use \".testctrl --help\" for help\n", zCmd);
    }else if( aCtrl[iCtrl].unSafe && p->bSafeMode ){
      utf8_printf(stderr,
         "line %d: \".testctrl %s\" may not be used in safe mode\n",
         p->lineno, aCtrl[iCtrl].zCtrlName);
      exit(1);
    }else{
      switch(testctrl){

        /* sqlite3_test_control(int, db, int) */
        case SQLITE_TESTCTRL_OPTIMIZATIONS:
        case SQLITE_TESTCTRL_RESERVE:
          if( nArg==3 ){
            int opt = (int)strtol(azArg[2], 0, 0);
            unsigned int opt = (unsigned int)strtol(azArg[2], 0, 0);
            rc2 = sqlite3_test_control(testctrl, p->db, opt);
            isOk = 3;
          }
          break;

        /* sqlite3_test_control(int) */
        case SQLITE_TESTCTRL_PRNG_SAVE:
        case SQLITE_TESTCTRL_PRNG_RESTORE:
        case SQLITE_TESTCTRL_PRNG_RESET:
        case SQLITE_TESTCTRL_BYTEORDER:
          if( nArg==2 ){
            rc2 = sqlite3_test_control(testctrl);
            isOk = testctrl==SQLITE_TESTCTRL_BYTEORDER ? 1 : 3;
          }
          break;

        /* sqlite3_test_control(int, uint) */
        case SQLITE_TESTCTRL_PENDING_BYTE:
          if( nArg==3 ){
            unsigned int opt = (unsigned int)integerValue(azArg[2]);
            rc2 = sqlite3_test_control(testctrl, opt);
            isOk = 3;
          }
          break;

        /* sqlite3_test_control(int, int, sqlite3*) */
        case SQLITE_TESTCTRL_PRNG_SEED:
          if( nArg==3 || nArg==4 ){
            int ii = (int)integerValue(azArg[2]);
            sqlite3 *db;
            if( ii==0 && cli_strcmp(azArg[2],"random")==0 ){
              sqlite3_randomness(sizeof(ii),&ii);
              printf("-- random seed: %d\n", ii);
            }
            if( nArg==3 ){
              db = 0;
            }else{
              db = p->db;
              /* Make sure the schema has been loaded */
              sqlite3_table_column_metadata(db, 0, "x", 0, 0, 0, 0, 0, 0);
            }
            rc2 = sqlite3_test_control(testctrl, ii, db);
            isOk = 3;
          }
          break;

        /* sqlite3_test_control(int, int) */
        case SQLITE_TESTCTRL_ASSERT:
        case SQLITE_TESTCTRL_ALWAYS:
        case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS:
          if( nArg==3 ){
            int opt = booleanValue(azArg[2]);
            rc2 = sqlite3_test_control(testctrl, opt);
            isOk = 1;
          }
          break;

        /* sqlite3_test_control(int, int) */
        case SQLITE_TESTCTRL_LOCALTIME_FAULT:
        case SQLITE_TESTCTRL_NEVER_CORRUPT:
          if( nArg==3 ){
            int opt = booleanValue(azArg[2]);
            rc2 = sqlite3_test_control(testctrl, opt);
            isOk = 3;
          }
          break;

        /* sqlite3_test_control(sqlite3*) */
        case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS:
          rc2 = sqlite3_test_control(testctrl, p->db);
          isOk = 3;
          break;

        case SQLITE_TESTCTRL_IMPOSTER:
          if( nArg==5 ){
            rc2 = sqlite3_test_control(testctrl, p->db,
                          azArg[2],
                          integerValue(azArg[3]),
                          integerValue(azArg[4]));
            isOk = 3;
          }
          break;

        case SQLITE_TESTCTRL_SEEK_COUNT: {
          u64 x = 0;
          rc2 = sqlite3_test_control(testctrl, p->db, &x);
          utf8_printf(p->out, "%llu\n", x);
          isOk = 3;
          break;
        }

#ifdef YYCOVERAGE
        case SQLITE_TESTCTRL_PARSER_COVERAGE:
        case SQLITE_TESTCTRL_PARSER_COVERAGE: {
          if( nArg==2 ){
            sqlite3_test_control(testctrl, p->out);
            isOk = 3;
          }
          break;
        }
#endif
#ifdef SQLITE_DEBUG
        case SQLITE_TESTCTRL_TUNE: {
          if( nArg==4 ){
            int id = (int)integerValue(azArg[2]);
            int val = (int)integerValue(azArg[3]);
            sqlite3_test_control(testctrl, id, &val);
            isOk = 3;
          }else if( nArg==3 ){
            int id = (int)integerValue(azArg[2]);
            sqlite3_test_control(testctrl, -id, &rc2);
            isOk = 1;
          }else if( nArg==2 ){
            int id = 1;
            while(1){
              int val = 0;
              rc2 = sqlite3_test_control(testctrl, -id, &val);
              if( rc2!=SQLITE_OK ) break;
              if( id>1 ) utf8_printf(p->out, "  ");
              utf8_printf(p->out, "%d: %d", id, val);
              id++;
            }
            if( id>1 ) utf8_printf(p->out, "\n");
            isOk = 3;
          }
          break;
        }
#endif
        case SQLITE_TESTCTRL_SORTER_MMAP:
          if( nArg==3 ){
            int opt = (unsigned int)integerValue(azArg[2]);
            rc2 = sqlite3_test_control(testctrl, p->db, opt);
            isOk = 3;
          }
          break;
      }
    }
    if( isOk==0 && iCtrl>=0 ){
      utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd, aCtrl[iCtrl].zUsage);
      utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
      rc = 1;
    }else if( isOk==1 ){
      raw_printf(p->out, "%d\n", rc2);
    }else if( isOk==2 ){
      raw_printf(p->out, "0x%08x\n", rc2);
    }
  }else
#endif /* !defined(SQLITE_UNTESTABLE) */

  if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){
  if( c=='t' && n>4 && cli_strncmp(azArg[0], "timeout", n)==0 ){
    open_db(p, 0);
    sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0);
  }else

  if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 ){
  if( c=='t' && n>=5 && cli_strncmp(azArg[0], "timer", n)==0 ){
    if( nArg==2 ){
      enableTimer = booleanValue(azArg[1]);
      if( enableTimer && !HAS_TIMER ){
        raw_printf(stderr, "Error: timer not available on this system.\n");
        enableTimer = 0;
      }
    }else{
      raw_printf(stderr, "Usage: .timer on|off\n");
      rc = 1;
    }
  }else

#ifndef SQLITE_OMIT_TRACE
  if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){
  if( c=='t' && cli_strncmp(azArg[0], "trace", n)==0 ){
    int mType = 0;
    int jj;
    open_db(p, 0);
    for(jj=1; jj<nArg; jj++){
      const char *z = azArg[jj];
      if( z[0]=='-' ){
        if( optionMatch(z, "expanded") ){
8048
8049
8050
8051
8052
8053
8054
8055

8056
8057
8058
8059
8060
8061
8062
8063
8064
8065
8066

























8067
8068

8069
8070
8071
8072
8073
8074
8075

8076
8077
8078
8079
8080
8081


8082
8083
8084
8085
8086

8087
8088
8089
8090
8091
8092
8093
8094
8095
8096
8097
8098

8099
8100
8101
8102
8103
8104
8105
8106
8107
8108
8109
8110

8111
8112
8113
8114
8115
8116
8117
8118
8119
8120
8121
8122
8123
8124
8125
8126
8127
8128
8129

8130
8131
8132
8133
8134
8135
8136
8137
8138
8139
8140
8141
8142
8143
8144
8145
8146
8147
8148

8149
8150
8151
8152
8153
8154
8155
8156
8157
8158
8159
8160
8161
8162

8163
8164
8165
8166
8167
8168
8169
8170
8171
8172
8173
8174
8175
8176
8177
8178
8179
8180

8181
8182
8183
8184
8185
8186
8187
8188
8189
8190
8191
8192
8193
8194



8195
8196
8197
8198

8199
8200




8201

8202
8203
8204
8205
8206
8207
8208
8209
8210
8211
8212
8213
8214
8215
8216

8217
8218
8219
















8220


8221

8222
8223


8224
8225
8226
8227
8228
8229
8230





















































8231
8232
8233
8234
8235


8236
8237


8238
8239
8240
8241
8242









8243
8244



8245
8246
8247
8248





8249
8250
8251




8252
8253
8254
8255
8256
8257
8258
8259

8260
8261
8262


8263
8264

8265
8266

8267
8268



8269
8270
8271
8272
8273


8274
8275
8276
8277
8278

8279
8280
8281
8282
8283
8284
8285
10939
10940
10941
10942
10943
10944
10945

10946
10947
10948
10949
10950
10951
10952
10953
10954
10955
10956
10957
10958
10959
10960
10961
10962
10963
10964
10965
10966
10967
10968
10969
10970
10971
10972
10973
10974
10975
10976
10977
10978
10979
10980
10981
10982
10983

10984
10985
10986
10987
10988
10989
10990

10991
10992
10993
10994
10995
10996

10997
10998
10999
11000
11001
11002

11003
11004
11005
11006
11007
11008
11009
11010
11011
11012
11013
11014

11015
11016
11017
11018
11019
11020
11021
11022
11023
11024
11025
11026

11027
11028
11029
11030
11031
11032
11033
11034
11035
11036
11037
11038
11039
11040
11041
11042
11043
11044
11045

11046
11047
11048
11049
11050
11051
11052
11053
11054
11055
11056
11057
11058
11059
11060
11061
11062
11063
11064

11065
11066
11067
11068
11069
11070
11071
11072
11073
11074
11075
11076
11077
11078

11079
11080
11081
11082
11083
11084
11085
11086
11087
11088
11089
11090
11091
11092
11093
11094
11095
11096

11097
11098
11099
11100
11101
11102
11103
11104
11105
11106
11107
11108



11109
11110
11111
11112

11113

11114
11115
11116
11117
11118
11119
11120

11121
11122
11123
11124
11125
11126
11127
11128
11129
11130
11131
11132
11133
11134
11135
11136
11137
11138
11139
11140
11141
11142
11143
11144
11145
11146
11147
11148
11149
11150
11151
11152
11153
11154
11155
11156
11157
11158
11159

11160

11161
11162
11163







11164
11165
11166
11167
11168
11169
11170
11171
11172
11173
11174
11175
11176
11177
11178
11179
11180
11181
11182
11183
11184
11185
11186
11187
11188
11189
11190
11191
11192
11193
11194
11195
11196
11197
11198
11199
11200
11201
11202
11203
11204
11205
11206
11207
11208
11209
11210
11211
11212
11213
11214
11215
11216





11217
11218


11219
11220





11221
11222
11223
11224
11225
11226
11227
11228
11229


11230
11231
11232




11233
11234
11235
11236
11237



11238
11239
11240
11241
11242
11243
11244
11245
11246
11247
11248

11249
11250


11251
11252


11253


11254


11255
11256
11257
11258
11259
11260


11261
11262


11263
11264

11265
11266
11267
11268
11269
11270
11271
11272







-
+











+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+






-
+





-
+
+




-
+











-
+











-
+


















-
+


















-
+













-
+

















-
+











-
-
-
+
+
+

-

-
+


+
+
+
+
-
+















+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
-
+
-

+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
-
-
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
+
+
+
-
-
-
-
+
+
+
+
+
-
-
-
+
+
+
+







-
+

-
-
+
+
-
-
+
-
-
+
-
-
+
+
+



-
-
+
+
-
-


-
+







        else {
          raw_printf(stderr, "Unknown option \"%s\" on \".trace\"\n", z);
          rc = 1;
          goto meta_command_exit;
        }
      }else{
        output_file_close(p->traceOut);
        p->traceOut = output_file_open(azArg[1], 0);
        p->traceOut = output_file_open(z, 0);
      }
    }
    if( p->traceOut==0 ){
      sqlite3_trace_v2(p->db, 0, 0, 0);
    }else{
      if( mType==0 ) mType = SQLITE_TRACE_STMT;
      sqlite3_trace_v2(p->db, mType, sql_trace_callback, p);
    }
  }else
#endif /* !defined(SQLITE_OMIT_TRACE) */

#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_VIRTUALTABLE)
  if( c=='u' && cli_strncmp(azArg[0], "unmodule", n)==0 ){
    int ii;
    int lenOpt;
    char *zOpt;
    if( nArg<2 ){
      raw_printf(stderr, "Usage: .unmodule [--allexcept] NAME ...\n");
      rc = 1;
      goto meta_command_exit;
    }
    open_db(p, 0);
    zOpt = azArg[1];
    if( zOpt[0]=='-' && zOpt[1]=='-' && zOpt[2]!=0 ) zOpt++;
    lenOpt = (int)strlen(zOpt);
    if( lenOpt>=3 && cli_strncmp(zOpt, "-allexcept",lenOpt)==0 ){
      assert( azArg[nArg]==0 );
      sqlite3_drop_modules(p->db, nArg>2 ? (const char**)(azArg+2) : 0);
    }else{
      for(ii=1; ii<nArg; ii++){
        sqlite3_create_module(p->db, azArg[ii], 0, 0);
      }
    }
  }else
#endif

#if SQLITE_USER_AUTHENTICATION
  if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
  if( c=='u' && cli_strncmp(azArg[0], "user", n)==0 ){
    if( nArg<2 ){
      raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n");
      rc = 1;
      goto meta_command_exit;
    }
    open_db(p, 0);
    if( strcmp(azArg[1],"login")==0 ){
    if( cli_strcmp(azArg[1],"login")==0 ){
      if( nArg!=4 ){
        raw_printf(stderr, "Usage: .user login USER PASSWORD\n");
        rc = 1;
        goto meta_command_exit;
      }
      rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3], strlen30(azArg[3]));
      rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3],
                                     strlen30(azArg[3]));
      if( rc ){
        utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]);
        rc = 1;
      }
    }else if( strcmp(azArg[1],"add")==0 ){
    }else if( cli_strcmp(azArg[1],"add")==0 ){
      if( nArg!=5 ){
        raw_printf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n");
        rc = 1;
        goto meta_command_exit;
      }
      rc = sqlite3_user_add(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
                            booleanValue(azArg[4]));
      if( rc ){
        raw_printf(stderr, "User-Add failed: %d\n", rc);
        rc = 1;
      }
    }else if( strcmp(azArg[1],"edit")==0 ){
    }else if( cli_strcmp(azArg[1],"edit")==0 ){
      if( nArg!=5 ){
        raw_printf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n");
        rc = 1;
        goto meta_command_exit;
      }
      rc = sqlite3_user_change(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
                              booleanValue(azArg[4]));
      if( rc ){
        raw_printf(stderr, "User-Edit failed: %d\n", rc);
        rc = 1;
      }
    }else if( strcmp(azArg[1],"delete")==0 ){
    }else if( cli_strcmp(azArg[1],"delete")==0 ){
      if( nArg!=3 ){
        raw_printf(stderr, "Usage: .user delete USER\n");
        rc = 1;
        goto meta_command_exit;
      }
      rc = sqlite3_user_delete(p->db, azArg[2]);
      if( rc ){
        raw_printf(stderr, "User-Delete failed: %d\n", rc);
        rc = 1;
      }
    }else{
      raw_printf(stderr, "Usage: .user login|add|edit|delete ...\n");
      rc = 1;
      goto meta_command_exit;
    }
  }else
#endif /* SQLITE_USER_AUTHENTICATION */

  if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
  if( c=='v' && cli_strncmp(azArg[0], "version", n)==0 ){
    utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
        sqlite3_libversion(), sqlite3_sourceid());
#if SQLITE_HAVE_ZLIB
    utf8_printf(p->out, "zlib version %s\n", zlibVersion());
#endif
#define CTIMEOPT_VAL_(opt) #opt
#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
#if defined(__clang__) && defined(__clang_major__)
    utf8_printf(p->out, "clang-" CTIMEOPT_VAL(__clang_major__) "."
                    CTIMEOPT_VAL(__clang_minor__) "."
                    CTIMEOPT_VAL(__clang_patchlevel__) "\n");
#elif defined(_MSC_VER)
    utf8_printf(p->out, "msvc-" CTIMEOPT_VAL(_MSC_VER) "\n");
#elif defined(__GNUC__) && defined(__VERSION__)
    utf8_printf(p->out, "gcc-" __VERSION__ "\n");
#endif
  }else

  if( c=='v' && strncmp(azArg[0], "vfsinfo", n)==0 ){
  if( c=='v' && cli_strncmp(azArg[0], "vfsinfo", n)==0 ){
    const char *zDbName = nArg==2 ? azArg[1] : "main";
    sqlite3_vfs *pVfs = 0;
    if( p->db ){
      sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs);
      if( pVfs ){
        utf8_printf(p->out, "vfs.zName      = \"%s\"\n", pVfs->zName);
        raw_printf(p->out, "vfs.iVersion   = %d\n", pVfs->iVersion);
        raw_printf(p->out, "vfs.szOsFile   = %d\n", pVfs->szOsFile);
        raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
      }
    }
  }else

  if( c=='v' && strncmp(azArg[0], "vfslist", n)==0 ){
  if( c=='v' && cli_strncmp(azArg[0], "vfslist", n)==0 ){
    sqlite3_vfs *pVfs;
    sqlite3_vfs *pCurrent = 0;
    if( p->db ){
      sqlite3_file_control(p->db, "main", SQLITE_FCNTL_VFS_POINTER, &pCurrent);
    }
    for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){
      utf8_printf(p->out, "vfs.zName      = \"%s\"%s\n", pVfs->zName,
           pVfs==pCurrent ? "  <--- CURRENT" : "");
      raw_printf(p->out, "vfs.iVersion   = %d\n", pVfs->iVersion);
      raw_printf(p->out, "vfs.szOsFile   = %d\n", pVfs->szOsFile);
      raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
      if( pVfs->pNext ){
        raw_printf(p->out, "-----------------------------------\n");
      }
    }
  }else

  if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){
  if( c=='v' && cli_strncmp(azArg[0], "vfsname", n)==0 ){
    const char *zDbName = nArg==2 ? azArg[1] : "main";
    char *zVfsName = 0;
    if( p->db ){
      sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName);
      if( zVfsName ){
        utf8_printf(p->out, "%s\n", zVfsName);
        sqlite3_free(zVfsName);
      }
    }
  }else

#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
  if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
    sqlite3WhereTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff;
  if( c=='w' && cli_strncmp(azArg[0], "wheretrace", n)==0 ){
    unsigned int x = nArg>=2? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
    sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &x);
  }else
#endif

  if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
  if( c=='w' && cli_strncmp(azArg[0], "width", n)==0 ){
    int j;
    assert( nArg<=ArraySize(azArg) );
    p->nWidth = nArg-1;
    p->colWidth = realloc(p->colWidth, (p->nWidth+1)*sizeof(int)*2);
    if( p->colWidth==0 && p->nWidth>0 ) shell_out_of_memory();
    if( p->nWidth ) p->actualWidth = &p->colWidth[p->nWidth];
    for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){
    for(j=1; j<nArg; j++){
      p->colWidth[j-1] = (int)integerValue(azArg[j]);
    }
  }else

  {
    utf8_printf(stderr, "Error: unknown command or invalid arguments: "
      " \"%s\". Enter \".help\" for help\n", azArg[0]);
    rc = 1;
  }

meta_command_exit:
  if( p->outCount ){
    p->outCount--;
    if( p->outCount==0 ) output_reset(p);
  }
  p->bSafeMode = p->bSafeModePersist;
  return rc;
}

/* Line scan result and intermediate states (supporting scan resumption)
*/
#ifndef CHAR_BIT
# define CHAR_BIT 8
#endif
typedef enum {
  QSS_HasDark = 1<<CHAR_BIT, QSS_EndingSemi = 2<<CHAR_BIT,
  QSS_CharMask = (1<<CHAR_BIT)-1, QSS_ScanMask = 3<<CHAR_BIT,
  QSS_Start = 0
} QuickScanState;
#define QSS_SETV(qss, newst) ((newst) | ((qss) & QSS_ScanMask))
#define QSS_INPLAIN(qss) (((qss)&QSS_CharMask)==QSS_Start)
#define QSS_PLAINWHITE(qss) (((qss)&~QSS_EndingSemi)==QSS_Start)
#define QSS_PLAINDARK(qss) (((qss)&~QSS_EndingSemi)==QSS_HasDark)
#define QSS_SEMITERM(qss) (((qss)&~QSS_HasDark)==QSS_EndingSemi)

/*
** Scan line for classification to guide shell's handling.
** The scan is resumable for subsequent lines when prior
** Return TRUE if a semicolon occurs anywhere in the first N characters
** return values are passed as the 2nd argument.
** of string z[].
*/
static QuickScanState quickscan(char *zLine, QuickScanState qss,
                                SCAN_TRACKER_REFTYPE pst){
static int line_contains_semicolon(const char *z, int N){
  int i;
  for(i=0; i<N; i++){  if( z[i]==';' ) return 1; }
  return 0;
}

/*
  char cin;
  char cWait = (char)qss; /* intentional narrowing loss */
  if( cWait==0 ){
  PlainScan:
    assert( cWait==0 );
    while( (cin = *zLine++)!=0 ){
      if( IsSpace(cin) )
        continue;
      switch (cin){
      case '-':
        if( *zLine!='-' )
          break;
        while((cin = *++zLine)!=0 )
          if( cin=='\n')
            goto PlainScan;
        return qss;
      case ';':
        qss |= QSS_EndingSemi;
        continue;
      case '/':
        if( *zLine=='*' ){
          ++zLine;
          cWait = '*';
          CONTINUE_PROMPT_AWAITS(pst, "/*");
          qss = QSS_SETV(qss, cWait);
          goto TermScan;
        }
        break;
      case '[':
        cin = ']';
        deliberate_fall_through;
      case '`': case '\'': case '"':
        cWait = cin;
        qss = QSS_HasDark | cWait;
        CONTINUE_PROMPT_AWAITC(pst, cin);
        goto TermScan;
      case '(':
        CONTINUE_PAREN_INCR(pst, 1);
        break;
      case ')':
        CONTINUE_PAREN_INCR(pst, -1);
        break;
      default:
        break;
      }
      qss = (qss & ~QSS_EndingSemi) | QSS_HasDark;
    }
  }else{
  TermScan:
    while( (cin = *zLine++)!=0 ){
      if( cin==cWait ){
        switch( cWait ){
        case '*':
** Test to see if a line consists entirely of whitespace.
*/
static int _all_whitespace(const char *z){
  for(; *z; z++){
    if( IsSpace(z[0]) ) continue;
          if( *zLine != '/' )
            continue;
    if( *z=='/' && z[1]=='*' ){
      z += 2;
          ++zLine;
          cWait = 0;
      while( *z && (*z!='*' || z[1]!='/') ){ z++; }
      if( *z==0 ) return 0;
      z++;
      continue;
    }
          CONTINUE_PROMPT_AWAITC(pst, 0);
          qss = QSS_SETV(qss, 0);
          goto PlainScan;
        case '`': case '\'': case '"':
          if(*zLine==cWait){
            /* Swallow doubled end-delimiter.*/
            ++zLine;
            continue;
          }
    if( *z=='-' && z[1]=='-' ){
      z += 2;
          deliberate_fall_through;
        case ']':
          cWait = 0;
      while( *z && *z!='\n' ){ z++; }
      if( *z==0 ) return 1;
      continue;
    }
          CONTINUE_PROMPT_AWAITC(pst, 0);
          qss = QSS_SETV(qss, 0);
          goto PlainScan;
        default: assert(0);
        }
    return 0;
  }
  return 1;
      }
    }
  }
  return qss;
}

/*
** Return TRUE if the line typed in is an SQL command terminator other
** than a semi-colon.  The SQL Server style "go" command is understood
** as is the Oracle "/".
*/
static int line_is_command_terminator(const char *zLine){
static int line_is_command_terminator(char *zLine){
  while( IsSpace(zLine[0]) ){ zLine++; };
  if( zLine[0]=='/' && _all_whitespace(&zLine[1]) ){
    return 1;  /* Oracle */
  if( zLine[0]=='/' )
    zLine += 1; /* Oracle */
  }
  if( ToLower(zLine[0])=='g' && ToLower(zLine[1])=='o'
  else if ( ToLower(zLine[0])=='g' && ToLower(zLine[1])=='o' )
         && _all_whitespace(&zLine[2]) ){
    return 1;  /* SQL Server */
    zLine += 2; /* SQL Server */
  }
  return 0;
  else
    return 0;
  return quickscan(zLine, QSS_Start, 0)==QSS_Start;
}

/*
** We need a default sqlite3_complete() implementation to use in case
** the shell is compiled with SQLITE_OMIT_COMPLETE.  The default assumes
** The CLI needs a working sqlite3_complete() to work properly.  So error
** out of the build if compiling with SQLITE_OMIT_COMPLETE.
** any arbitrary text is a complete SQL statement.  This is not very
** user-friendly, but it does seem to work.
*/
#ifdef SQLITE_OMIT_COMPLETE
#define sqlite3_complete(x) 1
# error the CLI application is imcompatable with SQLITE_OMIT_COMPLETE.
#endif

/*
** Return true if zSql is a complete SQL statement.  Return false if it
** ends in the middle of a string literal or C-style comment.
*/
static int line_is_complete(char *zSql, int nSql){
8297
8298
8299
8300
8301
8302
8303

8304
8305
8306
8307
8308















8309
8310
8311

8312
8313

8314
8315
8316
8317
8318



8319
8320
8321
8322
8323


8324
8325



8326
8327
8328
8329




































8330
8331
8332
8333
8334
8335
8336
8337
8338
8339
8340
8341
8342
8343
8344
8345



8346
8347
8348
8349


8350







8351

8352
8353
8354
8355
8356
8357
8358
8359
8360
8361
8362
8363
8364







8365
8366



8367
8368
8369

8370

8371
8372
8373
8374
8375
8376
8377
8378

8379
8380
8381
8382

8383
8384

8385

8386

8387
8388

8389
8390
8391
8392

8393
8394
8395
8396
8397
8398
8399
8400
8401
8402
8403
8404


8405

8406
8407
8408
8409
8410
8411
8412


8413
8414


8415

8416
8417
8418



8419

8420
8421
8422

8423
8424
8425
8426
8427
8428
8429
11284
11285
11286
11287
11288
11289
11290
11291
11292
11293
11294
11295
11296
11297
11298
11299
11300
11301
11302
11303
11304
11305
11306
11307
11308
11309
11310
11311
11312
11313

11314
11315

11316
11317




11318
11319
11320



11321
11322
11323
11324


11325
11326
11327
11328
11329
11330
11331
11332
11333
11334
11335
11336
11337
11338
11339
11340
11341
11342
11343
11344
11345
11346
11347
11348
11349
11350
11351
11352
11353
11354
11355
11356
11357
11358
11359
11360
11361
11362
11363
11364
11365
11366
11367
11368
11369
11370
11371
11372
11373
11374
11375
11376
11377
11378
11379
11380



11381
11382
11383

11384
11385

11386
11387
11388
11389
11390
11391
11392
11393
11394
11395
11396
11397
11398
11399
11400
11401
11402
11403
11404
11405
11406
11407
11408
11409
11410
11411
11412
11413
11414
11415
11416
11417


11418
11419
11420
11421
11422
11423
11424

11425
11426
11427
11428
11429
11430
11431
11432
11433
11434
11435
11436


11437


11438
11439
11440

11441
11442

11443
11444

11445

11446
11447
11448
11449
11450
11451
11452
11453
11454
11455
11456


11457
11458
11459
11460
11461
11462
11463
11464
11465
11466
11467
11468
11469


11470
11471
11472
11473
11474
11475

11476
11477
11478
11479
11480
11481
11482
11483
11484
11485
11486
11487
11488
11489
11490
11491







+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+

-
+

-
-
-
-
+
+
+
-
-
-


+
+
-
-
+
+
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+













-
-
-
+
+
+
-


-
+
+

+
+
+
+
+
+
+

+













+
+
+
+
+
+
+
-
-
+
+
+



+
-
+








+


-
-
+
-
-
+

+
-
+

-
+

-

-
+










-
-
+
+

+







+
+
-
-
+
+

+


-
+
+
+

+



+







*/
static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
  int rc;
  char *zErrMsg = 0;

  open_db(p, 0);
  if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql);
  if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
  BEGIN_TIMER;
  rc = shell_exec(p, zSql, &zErrMsg);
  END_TIMER;
  if( rc || zErrMsg ){
    char zPrefix[100];
    const char *zErrorTail;
    const char *zErrorType;
    if( zErrMsg==0 ){
      zErrorType = "Error";
      zErrorTail = sqlite3_errmsg(p->db);
    }else if( cli_strncmp(zErrMsg, "in prepare, ",12)==0 ){
      zErrorType = "Parse error";
      zErrorTail = &zErrMsg[12];
    }else if( cli_strncmp(zErrMsg, "stepping, ", 10)==0 ){
      zErrorType = "Runtime error";
      zErrorTail = &zErrMsg[10];
    }else{
      zErrorType = "Error";
      zErrorTail = zErrMsg;
    }
    if( in!=0 || !stdin_is_interactive ){
      sqlite3_snprintf(sizeof(zPrefix), zPrefix,
                       "Error: near line %d:", startline);
                       "%s near line %d:", zErrorType, startline);
    }else{
      sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:");
      sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%s:", zErrorType);
    }
    if( zErrMsg!=0 ){
      utf8_printf(stderr, "%s %s\n", zPrefix, zErrMsg);
      sqlite3_free(zErrMsg);
      zErrMsg = 0;
    utf8_printf(stderr, "%s %s\n", zPrefix, zErrorTail);
    sqlite3_free(zErrMsg);
    zErrMsg = 0;
    }else{
      utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db));
    }
    return 1;
  }else if( ShellHasFlag(p, SHFLG_CountChanges) ){
    char zLineBuf[2000];
    sqlite3_snprintf(sizeof(zLineBuf), zLineBuf,
    raw_printf(p->out, "changes: %3d   total_changes: %d\n",
            sqlite3_changes(p->db), sqlite3_total_changes(p->db));
            "changes: %lld   total_changes: %lld",
            sqlite3_changes64(p->db), sqlite3_total_changes64(p->db));
    raw_printf(p->out, "%s\n", zLineBuf);
  }
  return 0;
}

static void echo_group_input(ShellState *p, const char *zDo){
  if( ShellHasFlag(p, SHFLG_Echo) ) utf8_printf(p->out, "%s\n", zDo);
}

#ifdef SQLITE_SHELL_FIDDLE
/*
** Alternate one_input_line() impl for wasm mode. This is not in the primary
** impl because we need the global shellState and cannot access it from that
** function without moving lots of code around (creating a larger/messier diff).
*/
static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
  /* Parse the next line from shellState.wasm.zInput. */
  const char *zBegin = shellState.wasm.zPos;
  const char *z = zBegin;
  char *zLine = 0;
  i64 nZ = 0;

  UNUSED_PARAMETER(in);
  UNUSED_PARAMETER(isContinuation);
  if(!z || !*z){
    return 0;
  }
  while(*z && isspace(*z)) ++z;
  zBegin = z;
  for(; *z && '\n'!=*z; ++nZ, ++z){}
  if(nZ>0 && '\r'==zBegin[nZ-1]){
    --nZ;
  }
  shellState.wasm.zPos = z;
  zLine = realloc(zPrior, nZ+1);
  shell_check_oom(zLine);
  memcpy(zLine, zBegin, nZ);
  zLine[nZ] = 0;
  return zLine;
}
#endif /* SQLITE_SHELL_FIDDLE */

/*
** Read input from *in and process it.  If *in==0 then input
** is interactive - the user is typing it it.  Otherwise, input
** is coming from a file or device.  A prompt is issued and history
** is saved only if input is interactive.  An interrupt signal will
** cause this routine to exit immediately, unless input is interactive.
**
** Return the number of errors.
*/
static int process_input(ShellState *p){
  char *zLine = 0;          /* A single input line */
  char *zSql = 0;           /* Accumulated SQL text */
  int nLine;                /* Length of current line */
  int nSql = 0;             /* Bytes of zSql[] used */
  int nAlloc = 0;           /* Allocated zSql[] space */
  i64 nLine;                /* Length of current line */
  i64 nSql = 0;             /* Bytes of zSql[] used */
  i64 nAlloc = 0;           /* Allocated zSql[] space */
  int nSqlPrior = 0;        /* Bytes of zSql[] used by prior line */
  int rc;                   /* Error code */
  int errCnt = 0;           /* Number of errors seen */
  int startline = 0;        /* Line number for start of current input */
  i64 startline = 0;        /* Line number for start of current input */
  QuickScanState qss = QSS_Start; /* Accumulated line status (so far) */

  if( p->inputNesting==MAX_INPUT_NESTING ){
    /* This will be more informative in a later version. */
    utf8_printf(stderr,"Input nesting limit (%d) reached at line %d."
                " Check recursion.\n", MAX_INPUT_NESTING, p->lineno);
    return 1;
  }
  ++p->inputNesting;
  p->lineno = 0;
  CONTINUE_PROMPT_RESET;
  while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){
    fflush(p->out);
    zLine = one_input_line(p->in, zLine, nSql>0);
    if( zLine==0 ){
      /* End of input */
      if( p->in==0 && stdin_is_interactive ) printf("\n");
      break;
    }
    if( seenInterrupt ){
      if( p->in!=0 ) break;
      seenInterrupt = 0;
    }
    p->lineno++;
    if( QSS_INPLAIN(qss)
        && line_is_command_terminator(zLine)
        && line_is_complete(zSql, nSql) ){
      memcpy(zLine,";",2);
    }
    qss = quickscan(zLine, qss, CONTINUE_PROMPT_PSTATE);
    if( QSS_PLAINWHITE(qss) && nSql==0 ){
    if( nSql==0 && _all_whitespace(zLine) ){
      if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine);
      /* Just swallow single-line whitespace */
      echo_group_input(p, zLine);
      qss = QSS_Start;
      continue;
    }
    if( zLine && (zLine[0]=='.' || zLine[0]=='#') && nSql==0 ){
      CONTINUE_PROMPT_RESET;
      if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine);
      echo_group_input(p, zLine);
      if( zLine[0]=='.' ){
        rc = do_meta_command(zLine, p);
        if( rc==2 ){ /* exit requested */
          break;
        }else if( rc ){
          errCnt++;
        }
      }
      qss = QSS_Start;
      continue;
    }
    if( line_is_command_terminator(zLine) && line_is_complete(zSql, nSql) ){
      memcpy(zLine,";",2);
    /* No single-line dispositions remain; accumulate line(s). */
    }
    nLine = strlen30(zLine);
    nLine = strlen(zLine);
    if( nSql+nLine+2>=nAlloc ){
      /* Grow buffer by half-again increments when big. */
      nAlloc = nSql+nLine+100;
      nAlloc = nSql+(nSql>>1)+nLine+100;
      zSql = realloc(zSql, nAlloc);
      if( zSql==0 ) shell_out_of_memory();
      shell_check_oom(zSql);
    }
    nSqlPrior = nSql;
    if( nSql==0 ){
      int i;
      i64 i;
      for(i=0; zLine[i] && IsSpace(zLine[i]); i++){}
      assert( nAlloc>0 && zSql!=0 );
      memcpy(zSql, zLine+i, nLine+1-i);
      startline = p->lineno;
      nSql = nLine-i;
    }else{
      zSql[nSql++] = '\n';
      memcpy(zSql+nSql, zLine, nLine+1);
      nSql += nLine;
    }
    if( nSql && line_contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior)
                && sqlite3_complete(zSql) ){
    if( nSql && QSS_SEMITERM(qss) && sqlite3_complete(zSql) ){
      echo_group_input(p, zSql);
      errCnt += runOneSqlLine(p, zSql, p->in, startline);
      CONTINUE_PROMPT_RESET;
      nSql = 0;
      if( p->outCount ){
        output_reset(p);
        p->outCount = 0;
      }else{
        clearTempFile(p);
      }
      p->bSafeMode = p->bSafeModePersist;
      qss = QSS_Start;
    }else if( nSql && _all_whitespace(zSql) ){
      if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zSql);
    }else if( nSql && QSS_PLAINWHITE(qss) ){
      echo_group_input(p, zSql);
      nSql = 0;
      qss = QSS_Start;
    }
  }
  if( nSql && !_all_whitespace(zSql) ){
  if( nSql ){
    /* This may be incomplete. Let the SQL parser deal with that. */
    echo_group_input(p, zSql);
    errCnt += runOneSqlLine(p, zSql, p->in, startline);
    CONTINUE_PROMPT_RESET;
  }
  free(zSql);
  free(zLine);
  --p->inputNesting;
  return errCnt>0;
}

/*
** Return a pathname which is the user's home directory.  A
** 0 return indicates an error of some kind.
*/
8479
8480
8481
8482
8483
8484
8485
8486

8487
8488
8489
8490
8491
8492
8493
8494
8495

































8496
8497


8498
8499
8500
8501
8502
8503
8504
8505
8506
8507
8508
8509
8510
8511




8512
8513
8514
8515
8516
8517
8518

8519
8520
8521
8522
8523
8524
8525
8526

8527



8528
8529
8530
8531
8532
8533
8534
8535
8536
8537
8538
8539
8540
8541
8542
8543
8544

8545
8546
8547



8548

8549
8550
8551
8552
8553
8554
8555
8556

8557
8558
8559





8560
8561
8562
8563
8564


8565
8566
8567
8568

8569
8570
8571
8572
8573


8574
8575
8576
8577
8578
8579
8580
11541
11542
11543
11544
11545
11546
11547

11548
11549
11550
11551
11552
11553
11554
11555
11556
11557
11558
11559
11560
11561
11562
11563
11564
11565
11566
11567
11568
11569
11570
11571
11572
11573
11574
11575
11576
11577
11578
11579
11580
11581
11582
11583
11584
11585
11586
11587
11588
11589
11590
11591

11592
11593
11594
11595
11596
11597
11598
11599
11600
11601
11602
11603
11604
11605
11606

11607
11608
11609
11610
11611
11612
11613
11614
11615
11616
11617
11618
11619
11620
11621
11622
11623
11624
11625

11626
11627
11628
11629
11630
11631
11632
11633
11634
11635
11636
11637
11638
11639
11640
11641
11642
11643
11644
11645
11646
11647
11648
11649
11650
11651
11652
11653
11654

11655
11656
11657
11658
11659
11660
11661
11662
11663
11664
11665
11666
11667
11668
11669
11670
11671
11672
11673
11674
11675
11676
11677
11678
11679
11680
11681
11682
11683
11684
11685
11686
11687
11688
11689
11690
11691
11692
11693
11694
11695
11696
11697
11698







-
+









+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+
+













-
+
+
+
+







+







-
+

+
+
+

















+



+
+
+
-
+








+



+
+
+
+
+





+
+




+





+
+







    home_dir = "c:\\";
  }
#endif

#endif /* !_WIN32_WCE */

  if( home_dir ){
    int n = strlen30(home_dir) + 1;
    i64 n = strlen(home_dir) + 1;
    char *z = malloc( n );
    if( z ) memcpy(z, home_dir, n);
    home_dir = z;
  }

  return home_dir;
}

/*
** On non-Windows platforms, look for $XDG_CONFIG_HOME.
** If ${XDG_CONFIG_HOME}/sqlite3/sqliterc is found, return
** the path to it, else return 0. The result is cached for
** subsequent calls.
*/
static const char *find_xdg_config(void){
#if defined(_WIN32) || defined(WIN32) || defined(_WIN32_WCE) \
     || defined(__RTP__) || defined(_WRS_KERNEL)
  return 0;
#else
  static int alreadyTried = 0;
  static char *zConfig = 0;
  const char *zXdgHome;

  if( alreadyTried!=0 ){
    return zConfig;
  }
  alreadyTried = 1;
  zXdgHome = getenv("XDG_CONFIG_HOME");
  if( zXdgHome==0 ){
    return 0;
  }
  zConfig = sqlite3_mprintf("%s/sqlite3/sqliterc", zXdgHome);
  shell_check_oom(zConfig);
  if( access(zConfig,0)!=0 ){
    sqlite3_free(zConfig);
    zConfig = 0;
  }
  return zConfig;
#endif
}

/*
** Read input from the file given by sqliterc_override.  Or if that
** parameter is NULL, take input from ~/.sqliterc
** parameter is NULL, take input from the first of find_xdg_config()
** or ~/.sqliterc which is found.
**
** Returns the number of errors.
*/
static void process_sqliterc(
  ShellState *p,                  /* Configuration data */
  const char *sqliterc_override   /* Name of config file. NULL to use default */
){
  char *home_dir = NULL;
  const char *sqliterc = sqliterc_override;
  char *zBuf = 0;
  FILE *inSaved = p->in;
  int savedLineno = p->lineno;

  if (sqliterc == NULL) {
  if( sqliterc == NULL ){
    sqliterc = find_xdg_config();
  }
  if( sqliterc == NULL ){
    home_dir = find_home_dir(0);
    if( home_dir==0 ){
      raw_printf(stderr, "-- warning: cannot find home directory;"
                      " cannot read ~/.sqliterc\n");
      return;
    }
    zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
    shell_check_oom(zBuf);
    sqliterc = zBuf;
  }
  p->in = fopen(sqliterc,"rb");
  if( p->in ){
    if( stdin_is_interactive ){
      utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
    }
    process_input(p);
    if( process_input(p) && bail_on_error ) exit(1);
    fclose(p->in);
  }else if( sqliterc_override!=0 ){
    utf8_printf(stderr,"cannot open: \"%s\"\n", sqliterc);
    if( bail_on_error ) exit(1);
  }
  p->in = inSaved;
  p->lineno = savedLineno;
  sqlite3_free(zBuf);
}

/*
** Show available command line options
*/
static const char zOptions[] =
#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
  "   -A ARGS...           run \".archive ARGS\" and exit\n"
#endif
  "   -append              append the database to the end of the file\n"
  "   -ascii               set output mode to 'ascii'\n"
  "   -bail                stop after hitting an error\n"
  "   -batch               force batch I/O\n"
  "   -box                 set output mode to 'box'\n"
  "   -column              set output mode to 'column'\n"
  "   -cmd COMMAND         run \"COMMAND\" before reading stdin\n"
  "   -csv                 set output mode to 'csv'\n"
#if !defined(SQLITE_OMIT_DESERIALIZE)
  "   -deserialize         open the database using sqlite3_deserialize()\n"
#endif
  "   -echo                print commands before execution\n"
  "   -echo                print inputs before execution\n"
  "   -init FILENAME       read/process named file\n"
  "   -[no]header          turn headers on or off\n"
#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
  "   -heap SIZE           Size of heap for memsys3 or memsys5\n"
#endif
  "   -help                show this message\n"
  "   -html                set output mode to HTML\n"
  "   -interactive         force interactive I/O\n"
  "   -json                set output mode to 'json'\n"
  "   -line                set output mode to 'line'\n"
  "   -list                set output mode to 'list'\n"
  "   -lookaside SIZE N    use N entries of SZ bytes for lookaside memory\n"
  "   -markdown            set output mode to 'markdown'\n"
#if !defined(SQLITE_OMIT_DESERIALIZE)
  "   -maxsize N           maximum size for a --deserialize database\n"
#endif
  "   -memtrace            trace all memory allocations and deallocations\n"
  "   -mmap N              default mmap size set to N\n"
#ifdef SQLITE_ENABLE_MULTIPLEX
  "   -multiplex           enable the multiplexor VFS\n"
#endif
  "   -newline SEP         set output row separator. Default: '\\n'\n"
  "   -nofollow            refuse to open symbolic links to database files\n"
  "   -nonce STRING        set the safe-mode escape nonce\n"
  "   -nullvalue TEXT      set text string for NULL values. Default ''\n"
  "   -pagecache SIZE N    use N slots of SZ bytes each for page cache memory\n"
  "   -quote               set output mode to 'quote'\n"
  "   -readonly            open the database read-only\n"
  "   -safe                enable safe-mode\n"
  "   -separator SEP       set output column separator. Default: '|'\n"
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
  "   -sorterref SIZE      sorter references threshold size\n"
#endif
  "   -stats               print memory stats before each finalize\n"
  "   -table               set output mode to 'table'\n"
  "   -tabs                set output mode to 'tabs'\n"
  "   -version             show SQLite version\n"
  "   -vfs NAME            use NAME as the default VFS\n"
#ifdef SQLITE_ENABLE_VFSTRACE
  "   -vfstrace            enable tracing of all VFS calls\n"
#endif
#ifdef SQLITE_HAVE_ZLIB
  "   -zip                 open the file as a ZIP Archive\n"
8607
8608
8609
8610
8611
8612
8613

8614
8615
8616
8617
8618
8619
8620
8621
8622
8623
8624
8625
8626
8627
8628
8629
8630

8631
8632
8633
8634
8635
8636

8637

8638

8639
8640
8641
8642
8643
8644
8645
11725
11726
11727
11728
11729
11730
11731
11732
11733
11734
11735
11736
11737
11738
11739
11740
11741
11742
11743
11744
11745
11746
11747
11748
11749
11750
11751
11752
11753
11754
11755
11756
11757
11758
11759
11760
11761
11762
11763
11764
11765
11766
11767
11768







+

















+






+

+

+







/*
** Initialize the state information in data
*/
static void main_init(ShellState *data) {
  memset(data, 0, sizeof(*data));
  data->normalMode = data->cMode = data->mode = MODE_List;
  data->autoExplain = 1;
  data->pAuxDb = &data->aAuxDb[0];
  memcpy(data->colSeparator,SEP_Column, 2);
  memcpy(data->rowSeparator,SEP_Row, 2);
  data->showHeader = 0;
  data->shellFlgs = SHFLG_Lookaside;
  verify_uninitialized();
  sqlite3_config(SQLITE_CONFIG_URI, 1);
  sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
  sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
  sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
  sqlite3_snprintf(sizeof(continuePrompt), continuePrompt,"   ...> ");
}

/*
** Output text to the console in a font that attracts extra attention.
*/
#ifdef _WIN32
static void printBold(const char *zText){
#if !SQLITE_OS_WINRT
  HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
  CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo;
  GetConsoleScreenBufferInfo(out, &defaultScreenInfo);
  SetConsoleTextAttribute(out,
         FOREGROUND_RED|FOREGROUND_INTENSITY
  );
#endif
  printf("%s", zText);
#if !SQLITE_OS_WINRT
  SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes);
#endif
}
#else
static void printBold(const char *zText){
  printf("\033[1m%s\033[0m", zText);
}
#endif

8653
8654
8655
8656
8657
8658
8659
8660


8661
8662
8663
8664
8665




8666
8667
8668
8669
8670
8671
8672



8673



8674

8675
8676
8677
8678
8679
8680
8681
8682
8683
8684
8685
8686
8687
8688
8689





8690
8691

8692
8693
8694
8695
8696
8697
8698
8699
8700
8701



8702

8703
8704
8705
8706
8707
8708
8709
8710
8711

8712
8713
8714
8715
8716
8717
8718
8719
8720
8721
8722
8723
8724
8725
8726
8727

8728
8729
8730
8731
8732
8733
8734
8735



8736
8737

8738
8739
8740
8741
8742
8743
8744
11776
11777
11778
11779
11780
11781
11782

11783
11784
11785
11786
11787
11788
11789
11790
11791
11792
11793
11794
11795
11796
11797
11798
11799
11800
11801
11802
11803
11804
11805
11806
11807
11808
11809
11810
11811
11812
11813
11814
11815
11816
11817
11818
11819
11820
11821
11822
11823
11824
11825
11826
11827
11828
11829
11830
11831
11832
11833
11834
11835
11836
11837
11838
11839
11840
11841
11842
11843
11844
11845
11846
11847
11848
11849
11850
11851
11852
11853
11854
11855

11856
11857
11858
11859
11860
11861
11862
11863
11864
11865
11866
11867
11868
11869
11870
11871
11872
11873
11874
11875

11876
11877



11878
11879
11880
11881

11882
11883
11884
11885
11886
11887
11888
11889







-
+
+





+
+
+
+







+
+
+

+
+
+

+















+
+
+
+
+


+










+
+
+

+








-
+
















+


-


-
-
-
+
+
+

-
+







            argv[0], argv[argc-1]);
    exit(1);
  }
  return argv[i];
}

#ifndef SQLITE_SHELL_IS_UTF8
#  if (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
#  if (defined(_WIN32) || defined(WIN32)) \
   && (defined(_MSC_VER) || (defined(UNICODE) && defined(__GNUC__)))
#    define SQLITE_SHELL_IS_UTF8          (0)
#  else
#    define SQLITE_SHELL_IS_UTF8          (1)
#  endif
#endif

#ifdef SQLITE_SHELL_FIDDLE
#  define main fiddle_main
#endif

#if SQLITE_SHELL_IS_UTF8
int SQLITE_CDECL main(int argc, char **argv){
#else
int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
  char **argv;
#endif
#ifdef SQLITE_DEBUG
  sqlite3_int64 mem_main_enter = sqlite3_memory_used();
#endif
  char *zErrMsg = 0;
#ifdef SQLITE_SHELL_FIDDLE
#  define data shellState
#else
  ShellState data;
#endif
  const char *zInitFile = 0;
  int i;
  int rc = 0;
  int warnInmemoryDb = 0;
  int readStdin = 1;
  int nCmd = 0;
  char **azCmd = 0;
  const char *zVfs = 0;           /* Value of -vfs command-line option */
#if !SQLITE_SHELL_IS_UTF8
  char **argvToFree = 0;
  int argcToFree = 0;
#endif

  setBinaryMode(stdin, 0);
  setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
#ifdef SQLITE_SHELL_FIDDLE
  stdin_is_interactive = 0;
  stdout_is_console = 1;
  data.wasm.zDefaultDbName = "/fiddle.sqlite3";
#else
  stdin_is_interactive = isatty(0);
  stdout_is_console = isatty(1);
#endif

#if !defined(_WIN32_WCE)
  if( getenv("SQLITE_DEBUG_BREAK") ){
    if( isatty(0) && isatty(2) ){
      fprintf(stderr,
          "attach debugger to process %d and press any key to continue.\n",
          GETPID());
      fgetc(stdin);
    }else{
#if defined(_WIN32) || defined(WIN32)
#if SQLITE_OS_WINRT
      __debugbreak();
#else
      DebugBreak();
#endif
#elif defined(SIGTRAP)
      raise(SIGTRAP);
#endif
    }
  }
#endif

#if USE_SYSTEM_SQLITE+0!=1
  if( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){
  if( cli_strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){
    utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
            sqlite3_sourceid(), SQLITE_SOURCE_ID);
    exit(1);
  }
#endif
  main_init(&data);

  /* On Windows, we must translate command-line arguments into UTF-8.
  ** The SQLite memory allocator subsystem has to be enabled in order to
  ** do this.  But we want to run an sqlite3_shutdown() afterwards so that
  ** subsequent sqlite3_config() calls will work.  So copy all results into
  ** memory that does not come from the SQLite memory allocator.
  */
#if !SQLITE_SHELL_IS_UTF8
  sqlite3_initialize();
  argvToFree = malloc(sizeof(argv[0])*argc*2);
  shell_check_oom(argvToFree);
  argcToFree = argc;
  argv = argvToFree + argc;
  if( argv==0 ) shell_out_of_memory();
  for(i=0; i<argc; i++){
    char *z = sqlite3_win32_unicode_to_utf8(wargv[i]);
    int n;
    if( z==0 ) shell_out_of_memory();
    n = (int)strlen(z);
    i64 n;
    shell_check_oom(z);
    n = strlen(z);
    argv[i] = malloc( n+1 );
    if( argv[i]==0 ) shell_out_of_memory();
    shell_check_oom(argv[i]);
    memcpy(argv[i], z, n+1);
    argvToFree[i] = argv[i];
    sqlite3_free(z);
  }
  sqlite3_shutdown();
#endif

8757
8758
8759
8760
8761
8762
8763
8764

8765
8766
8767
8768
8769
8770
8771
8772
8773
8774
8775
8776
8777
8778
8779
8780


8781
8782
8783
8784
8785
8786
8787

8788
8789
8790
8791
8792
8793
8794
8795




8796
8797
8798

8799
8800

8801
8802
8803
8804
8805
8806

8807
8808
8809
8810
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
8836

8837
8838
8839
8840
8841
8842
8843
8844
8845
8846
8847

8848
8849
8850
8851

8852
8853
8854
8855

8856
8857
8858
8859

8860
8861
8862

8863
8864
8865

8866
8867
8868


8869


8870
8871

8872


8873
8874

8875
8876
8877
8878









8879
8880
8881
8882
8883
8884
8885
11902
11903
11904
11905
11906
11907
11908

11909
11910
11911
11912
11913
11914
11915
11916
11917
11918
11919
11920
11921
11922
11923


11924
11925
11926
11927
11928
11929
11930
11931

11932
11933
11934
11935
11936




11937
11938
11939
11940
11941
11942

11943
11944

11945
11946
11947
11948
11949
11950

11951
11952
11953
11954
11955
11956
11957
11958
11959
11960
11961
11962



11963
11964
11965
11966
11967

11968
11969
11970
11971
11972
11973
11974

11975
11976
11977
11978
11979
11980
11981
11982
11983
11984
11985
11986
11987
11988
11989
11990
11991

11992
11993
11994
11995
11996
11997
11998
11999
12000
12001
12002

12003
12004
12005
12006

12007
12008
12009
12010

12011
12012
12013
12014

12015
12016
12017

12018
12019
12020

12021
12022


12023
12024
12025
12026
12027
12028

12029
12030
12031
12032
12033

12034
12035
12036
12037
12038
12039
12040
12041
12042
12043
12044
12045
12046
12047
12048
12049
12050
12051
12052
12053
12054







-
+














-
-
+
+






-
+




-
-
-
-
+
+
+
+


-
+

-
+





-
+











-
-
-
+
+
+


-
+
+
+
+



-
+







+
+
+
+
+
+
+
+

-
+










-
+



-
+



-
+



-
+


-
+


-
+

-
-
+
+

+
+

-
+

+
+

-
+




+
+
+
+
+
+
+
+
+







#ifdef SQLITE_SHELL_DBNAME_PROC
  {
    /* If the SQLITE_SHELL_DBNAME_PROC macro is defined, then it is the name
    ** of a C-function that will provide the name of the database file.  Use
    ** this compile-time option to embed this shell program in larger
    ** applications. */
    extern void SQLITE_SHELL_DBNAME_PROC(const char**);
    SQLITE_SHELL_DBNAME_PROC(&data.zDbFilename);
    SQLITE_SHELL_DBNAME_PROC(&data.pAuxDb->zDbFilename);
    warnInmemoryDb = 0;
  }
#endif

  /* Do an initial pass through the command-line argument to locate
  ** the name of the database file, the name of the initialization file,
  ** the size of the alternative malloc heap,
  ** and the first command to execute.
  */
  verify_uninitialized();
  for(i=1; i<argc; i++){
    char *z;
    z = argv[i];
    if( z[0]!='-' ){
      if( data.zDbFilename==0 ){
        data.zDbFilename = z;
      if( data.aAuxDb->zDbFilename==0 ){
        data.aAuxDb->zDbFilename = z;
      }else{
        /* Excesss arguments are interpreted as SQL (or dot-commands) and
        ** mean that nothing is read from stdin */
        readStdin = 0;
        nCmd++;
        azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd);
        if( azCmd==0 ) shell_out_of_memory();
        shell_check_oom(azCmd);
        azCmd[nCmd-1] = z;
      }
    }
    if( z[1]=='-' ) z++;
    if( strcmp(z,"-separator")==0
     || strcmp(z,"-nullvalue")==0
     || strcmp(z,"-newline")==0
     || strcmp(z,"-cmd")==0
    if( cli_strcmp(z,"-separator")==0
     || cli_strcmp(z,"-nullvalue")==0
     || cli_strcmp(z,"-newline")==0
     || cli_strcmp(z,"-cmd")==0
    ){
      (void)cmdline_option_value(argc, argv, ++i);
    }else if( strcmp(z,"-init")==0 ){
    }else if( cli_strcmp(z,"-init")==0 ){
      zInitFile = cmdline_option_value(argc, argv, ++i);
    }else if( strcmp(z,"-batch")==0 ){
    }else if( cli_strcmp(z,"-batch")==0 ){
      /* Need to check for batch mode here to so we can avoid printing
      ** informational messages (like from process_sqliterc) before
      ** we do the actual processing of arguments later in a second pass.
      */
      stdin_is_interactive = 0;
    }else if( strcmp(z,"-heap")==0 ){
    }else if( cli_strcmp(z,"-heap")==0 ){
#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
      const char *zSize;
      sqlite3_int64 szHeap;

      zSize = cmdline_option_value(argc, argv, ++i);
      szHeap = integerValue(zSize);
      if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000;
      sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
#else
      (void)cmdline_option_value(argc, argv, ++i);
#endif
    }else if( strcmp(z,"-pagecache")==0 ){
      int n, sz;
      sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
    }else if( cli_strcmp(z,"-pagecache")==0 ){
      sqlite3_int64 n, sz;
      sz = integerValue(cmdline_option_value(argc,argv,++i));
      if( sz>70000 ) sz = 70000;
      if( sz<0 ) sz = 0;
      n = (int)integerValue(cmdline_option_value(argc,argv,++i));
      n = integerValue(cmdline_option_value(argc,argv,++i));
      if( sz>0 && n>0 && 0xffffffffffffLL/sz<n ){
        n = 0xffffffffffffLL/sz;
      }
      sqlite3_config(SQLITE_CONFIG_PAGECACHE,
                    (n>0 && sz>0) ? malloc(n*sz) : 0, sz, n);
      data.shellFlgs |= SHFLG_Pagecache;
    }else if( strcmp(z,"-lookaside")==0 ){
    }else if( cli_strcmp(z,"-lookaside")==0 ){
      int n, sz;
      sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
      if( sz<0 ) sz = 0;
      n = (int)integerValue(cmdline_option_value(argc,argv,++i));
      if( n<0 ) n = 0;
      sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, n);
      if( sz*n==0 ) data.shellFlgs &= ~SHFLG_Lookaside;
    }else if( cli_strcmp(z,"-threadsafe")==0 ){
      int n;
      n = (int)integerValue(cmdline_option_value(argc,argv,++i));
      switch( n ){
         case 0:  sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);  break;
         case 2:  sqlite3_config(SQLITE_CONFIG_MULTITHREAD);   break;
         default: sqlite3_config(SQLITE_CONFIG_SERIALIZED);    break;
      }
#ifdef SQLITE_ENABLE_VFSTRACE
    }else if( strcmp(z,"-vfstrace")==0 ){
    }else if( cli_strcmp(z,"-vfstrace")==0 ){
      extern int vfstrace_register(
         const char *zTraceName,
         const char *zOldVfsName,
         int (*xOut)(const char*,void*),
         void *pOutArg,
         int makeDefault
      );
      vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1);
#endif
#ifdef SQLITE_ENABLE_MULTIPLEX
    }else if( strcmp(z,"-multiplex")==0 ){
    }else if( cli_strcmp(z,"-multiplex")==0 ){
      extern int sqlite3_multiple_initialize(const char*,int);
      sqlite3_multiplex_initialize(0, 1);
#endif
    }else if( strcmp(z,"-mmap")==0 ){
    }else if( cli_strcmp(z,"-mmap")==0 ){
      sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
      sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, sz, sz);
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
    }else if( strcmp(z,"-sorterref")==0 ){
    }else if( cli_strcmp(z,"-sorterref")==0 ){
      sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
      sqlite3_config(SQLITE_CONFIG_SORTERREF_SIZE, (int)sz);
#endif
    }else if( strcmp(z,"-vfs")==0 ){
    }else if( cli_strcmp(z,"-vfs")==0 ){
      zVfs = cmdline_option_value(argc, argv, ++i);
#ifdef SQLITE_HAVE_ZLIB
    }else if( strcmp(z,"-zip")==0 ){
    }else if( cli_strcmp(z,"-zip")==0 ){
      data.openMode = SHELL_OPEN_ZIPFILE;
#endif
    }else if( strcmp(z,"-append")==0 ){
    }else if( cli_strcmp(z,"-append")==0 ){
      data.openMode = SHELL_OPEN_APPENDVFS;
#ifdef SQLITE_ENABLE_DESERIALIZE
    }else if( strcmp(z,"-deserialize")==0 ){
#ifndef SQLITE_OMIT_DESERIALIZE
    }else if( cli_strcmp(z,"-deserialize")==0 ){
      data.openMode = SHELL_OPEN_DESERIALIZE;
    }else if( cli_strcmp(z,"-maxsize")==0 && i+1<argc ){
      data.szMax = integerValue(argv[++i]);
#endif
    }else if( strcmp(z,"-readonly")==0 ){
    }else if( cli_strcmp(z,"-readonly")==0 ){
      data.openMode = SHELL_OPEN_READONLY;
    }else if( cli_strcmp(z,"-nofollow")==0 ){
      data.openFlags = SQLITE_OPEN_NOFOLLOW;
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
    }else if( strncmp(z, "-A",2)==0 ){
    }else if( cli_strncmp(z, "-A",2)==0 ){
      /* All remaining command-line arguments are passed to the ".archive"
      ** command, so ignore them */
      break;
#endif
    }else if( cli_strcmp(z, "-memtrace")==0 ){
      sqlite3MemTraceActivate(stderr);
    }else if( cli_strcmp(z,"-bail")==0 ){
      bail_on_error = 1;
    }else if( cli_strcmp(z,"-nonce")==0 ){
      free(data.zNonce);
      data.zNonce = strdup(argv[++i]);
    }else if( cli_strcmp(z,"-safe")==0 ){
      /* no-op - catch this on the second pass */
    }
  }
  verify_uninitialized();


#ifdef SQLITE_SHELL_INIT_PROC
  {
8897
8898
8899
8900
8901
8902
8903
8904

8905
8906
8907
8908
8909

8910
8911

8912
8913
8914
8915
8916
8917
8918

8919

8920
8921
8922
8923
8924
8925
8926

8927
8928
8929
8930
8931
8932
8933
8934
8935
8936
8937
8938
8939
8940
8941
8942
8943
8944
8945

8946
8947

8948
8949

8950
8951

8952


8953

8954
8955

8956








8957

8958
8959
8960
8961

8962
8963
8964

8965
8966
8967


8968


8969
8970

8971


8972

8973
8974

8975
8976
8977
8978






8979
8980
8981

8982
8983
8984

8985
8986
8987

8988

8989

8990

8991

8992
8993

8994
8995

8996
8997

8998
8999

9000
9001

9002
9003
9004
9005
9006
9007
9008
9009
9010



9011
9012
9013

9014
9015

9016
9017

9018
9019

9020
9021

9022




9023

9024


9025
9026

9027
9028
9029

9030
9031
9032

9033
9034
9035
9036

9037
9038
9039

9040
9041

9042
9043
9044
9045
9046
9047
9048
12066
12067
12068
12069
12070
12071
12072

12073
12074
12075
12076
12077

12078
12079

12080
12081
12082
12083
12084
12085
12086
12087
12088
12089
12090
12091
12092
12093
12094
12095
12096

12097
12098
12099
12100
12101
12102
12103
12104
12105
12106
12107
12108
12109
12110
12111
12112
12113
12114
12115

12116
12117

12118
12119

12120
12121

12122
12123
12124
12125

12126
12127

12128
12129
12130
12131
12132
12133
12134
12135
12136
12137

12138
12139
12140
12141

12142
12143
12144

12145
12146


12147
12148
12149
12150
12151
12152

12153
12154
12155
12156

12157
12158

12159




12160
12161
12162
12163
12164
12165
12166
12167

12168
12169
12170

12171
12172
12173

12174
12175
12176

12177
12178
12179

12180
12181

12182
12183

12184
12185

12186
12187

12188
12189

12190
12191
12192
12193
12194
12195
12196



12197
12198
12199
12200
12201

12202
12203

12204
12205

12206
12207

12208
12209

12210
12211
12212
12213
12214
12215

12216
12217
12218
12219
12220

12221
12222
12223

12224
12225
12226

12227
12228
12229
12230

12231
12232
12233

12234
12235

12236
12237
12238
12239
12240
12241
12242
12243







-
+




-
+

-
+







+

+






-
+


















-
+

-
+

-
+

-
+

+
+
-
+

-
+

+
+
+
+
+
+
+
+
-
+



-
+


-
+

-
-
+
+

+
+

-
+

+
+
-
+

-
+
-
-
-
-
+
+
+
+
+
+


-
+


-
+


-
+

+
-
+

+
-
+

-
+

-
+

-
+

-
+

-
+






-
-
-
+
+
+


-
+

-
+

-
+

-
+

-
+

+
+
+
+
-
+

+
+

-
+


-
+


-
+



-
+


-
+

-
+







#endif

  if( zVfs ){
    sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs);
    if( pVfs ){
      sqlite3_vfs_register(pVfs, 1);
    }else{
      utf8_printf(stderr, "no such VFS: \"%s\"\n", argv[i]);
      utf8_printf(stderr, "no such VFS: \"%s\"\n", zVfs);
      exit(1);
    }
  }

  if( data.zDbFilename==0 ){
  if( data.pAuxDb->zDbFilename==0 ){
#ifndef SQLITE_OMIT_MEMORYDB
    data.zDbFilename = ":memory:";
    data.pAuxDb->zDbFilename = ":memory:";
    warnInmemoryDb = argc==1;
#else
    utf8_printf(stderr,"%s: Error: no database filename specified\n", Argv0);
    return 1;
#endif
  }
  data.out = stdout;
#ifndef SQLITE_SHELL_FIDDLE
  sqlite3_appendvfs_init(0,0,0);
#endif

  /* Go ahead and open the database file if it already exists.  If the
  ** file does not exist, delay opening it.  This prevents empty database
  ** files from being created if a user mistypes the database name argument
  ** to the sqlite command-line tool.
  */
  if( access(data.zDbFilename, 0)==0 ){
  if( access(data.pAuxDb->zDbFilename, 0)==0 ){
    open_db(&data, 0);
  }

  /* Process the initialization file if there is one.  If no -init option
  ** is given on the command line, look for a file named ~/.sqliterc and
  ** try to process it.
  */
  process_sqliterc(&data,zInitFile);

  /* Make a second pass through the command-line argument and set
  ** options.  This second pass is delayed until after the initialization
  ** file is processed so that the command-line arguments will override
  ** settings in the initialization file.
  */
  for(i=1; i<argc; i++){
    char *z = argv[i];
    if( z[0]!='-' ) continue;
    if( z[1]=='-' ){ z++; }
    if( strcmp(z,"-init")==0 ){
    if( cli_strcmp(z,"-init")==0 ){
      i++;
    }else if( strcmp(z,"-html")==0 ){
    }else if( cli_strcmp(z,"-html")==0 ){
      data.mode = MODE_Html;
    }else if( strcmp(z,"-list")==0 ){
    }else if( cli_strcmp(z,"-list")==0 ){
      data.mode = MODE_List;
    }else if( strcmp(z,"-quote")==0 ){
    }else if( cli_strcmp(z,"-quote")==0 ){
      data.mode = MODE_Quote;
      sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Comma);
      sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
    }else if( strcmp(z,"-line")==0 ){
    }else if( cli_strcmp(z,"-line")==0 ){
      data.mode = MODE_Line;
    }else if( strcmp(z,"-column")==0 ){
    }else if( cli_strcmp(z,"-column")==0 ){
      data.mode = MODE_Column;
    }else if( cli_strcmp(z,"-json")==0 ){
      data.mode = MODE_Json;
    }else if( cli_strcmp(z,"-markdown")==0 ){
      data.mode = MODE_Markdown;
    }else if( cli_strcmp(z,"-table")==0 ){
      data.mode = MODE_Table;
    }else if( cli_strcmp(z,"-box")==0 ){
      data.mode = MODE_Box;
    }else if( strcmp(z,"-csv")==0 ){
    }else if( cli_strcmp(z,"-csv")==0 ){
      data.mode = MODE_Csv;
      memcpy(data.colSeparator,",",2);
#ifdef SQLITE_HAVE_ZLIB
    }else if( strcmp(z,"-zip")==0 ){
    }else if( cli_strcmp(z,"-zip")==0 ){
      data.openMode = SHELL_OPEN_ZIPFILE;
#endif
    }else if( strcmp(z,"-append")==0 ){
    }else if( cli_strcmp(z,"-append")==0 ){
      data.openMode = SHELL_OPEN_APPENDVFS;
#ifdef SQLITE_ENABLE_DESERIALIZE
    }else if( strcmp(z,"-deserialize")==0 ){
#ifndef SQLITE_OMIT_DESERIALIZE
    }else if( cli_strcmp(z,"-deserialize")==0 ){
      data.openMode = SHELL_OPEN_DESERIALIZE;
    }else if( cli_strcmp(z,"-maxsize")==0 && i+1<argc ){
      data.szMax = integerValue(argv[++i]);
#endif
    }else if( strcmp(z,"-readonly")==0 ){
    }else if( cli_strcmp(z,"-readonly")==0 ){
      data.openMode = SHELL_OPEN_READONLY;
    }else if( cli_strcmp(z,"-nofollow")==0 ){
      data.openFlags |= SQLITE_OPEN_NOFOLLOW;
    }else if( strcmp(z,"-ascii")==0 ){
    }else if( cli_strcmp(z,"-ascii")==0 ){
      data.mode = MODE_Ascii;
      sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
      sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,SEP_Unit);
                       SEP_Unit);
      sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
                       SEP_Record);
    }else if( strcmp(z,"-separator")==0 ){
      sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,SEP_Record);
    }else if( cli_strcmp(z,"-tabs")==0 ){
      data.mode = MODE_List;
      sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,SEP_Tab);
      sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,SEP_Row);
    }else if( cli_strcmp(z,"-separator")==0 ){
      sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
                       "%s",cmdline_option_value(argc,argv,++i));
    }else if( strcmp(z,"-newline")==0 ){
    }else if( cli_strcmp(z,"-newline")==0 ){
      sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
                       "%s",cmdline_option_value(argc,argv,++i));
    }else if( strcmp(z,"-nullvalue")==0 ){
    }else if( cli_strcmp(z,"-nullvalue")==0 ){
      sqlite3_snprintf(sizeof(data.nullValue), data.nullValue,
                       "%s",cmdline_option_value(argc,argv,++i));
    }else if( strcmp(z,"-header")==0 ){
    }else if( cli_strcmp(z,"-header")==0 ){
      data.showHeader = 1;
      ShellSetFlag(&data, SHFLG_HeaderSet);
    }else if( strcmp(z,"-noheader")==0 ){
     }else if( cli_strcmp(z,"-noheader")==0 ){
      data.showHeader = 0;
      ShellSetFlag(&data, SHFLG_HeaderSet);
    }else if( strcmp(z,"-echo")==0 ){
    }else if( cli_strcmp(z,"-echo")==0 ){
      ShellSetFlag(&data, SHFLG_Echo);
    }else if( strcmp(z,"-eqp")==0 ){
    }else if( cli_strcmp(z,"-eqp")==0 ){
      data.autoEQP = AUTOEQP_on;
    }else if( strcmp(z,"-eqpfull")==0 ){
    }else if( cli_strcmp(z,"-eqpfull")==0 ){
      data.autoEQP = AUTOEQP_full;
    }else if( strcmp(z,"-stats")==0 ){
    }else if( cli_strcmp(z,"-stats")==0 ){
      data.statsOn = 1;
    }else if( strcmp(z,"-scanstats")==0 ){
    }else if( cli_strcmp(z,"-scanstats")==0 ){
      data.scanstatsOn = 1;
    }else if( strcmp(z,"-backslash")==0 ){
    }else if( cli_strcmp(z,"-backslash")==0 ){
      /* Undocumented command-line option: -backslash
      ** Causes C-style backslash escapes to be evaluated in SQL statements
      ** prior to sending the SQL into SQLite.  Useful for injecting
      ** crazy bytes in the middle of SQL statements for testing and debugging.
      */
      ShellSetFlag(&data, SHFLG_Backslash);
    }else if( strcmp(z,"-bail")==0 ){
      bail_on_error = 1;
    }else if( strcmp(z,"-version")==0 ){
    }else if( cli_strcmp(z,"-bail")==0 ){
      /* No-op.  The bail_on_error flag should already be set. */
    }else if( cli_strcmp(z,"-version")==0 ){
      printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid());
      return 0;
    }else if( strcmp(z,"-interactive")==0 ){
    }else if( cli_strcmp(z,"-interactive")==0 ){
      stdin_is_interactive = 1;
    }else if( strcmp(z,"-batch")==0 ){
    }else if( cli_strcmp(z,"-batch")==0 ){
      stdin_is_interactive = 0;
    }else if( strcmp(z,"-heap")==0 ){
    }else if( cli_strcmp(z,"-heap")==0 ){
      i++;
    }else if( strcmp(z,"-pagecache")==0 ){
    }else if( cli_strcmp(z,"-pagecache")==0 ){
      i+=2;
    }else if( strcmp(z,"-lookaside")==0 ){
    }else if( cli_strcmp(z,"-lookaside")==0 ){
      i+=2;
    }else if( cli_strcmp(z,"-threadsafe")==0 ){
      i+=2;
    }else if( cli_strcmp(z,"-nonce")==0 ){
      i += 2;
    }else if( strcmp(z,"-mmap")==0 ){
    }else if( cli_strcmp(z,"-mmap")==0 ){
      i++;
    }else if( cli_strcmp(z,"-memtrace")==0 ){
      i++;
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
    }else if( strcmp(z,"-sorterref")==0 ){
    }else if( cli_strcmp(z,"-sorterref")==0 ){
      i++;
#endif
    }else if( strcmp(z,"-vfs")==0 ){
    }else if( cli_strcmp(z,"-vfs")==0 ){
      i++;
#ifdef SQLITE_ENABLE_VFSTRACE
    }else if( strcmp(z,"-vfstrace")==0 ){
    }else if( cli_strcmp(z,"-vfstrace")==0 ){
      i++;
#endif
#ifdef SQLITE_ENABLE_MULTIPLEX
    }else if( strcmp(z,"-multiplex")==0 ){
    }else if( cli_strcmp(z,"-multiplex")==0 ){
      i++;
#endif
    }else if( strcmp(z,"-help")==0 ){
    }else if( cli_strcmp(z,"-help")==0 ){
      usage(1);
    }else if( strcmp(z,"-cmd")==0 ){
    }else if( cli_strcmp(z,"-cmd")==0 ){
      /* Run commands that follow -cmd first and separately from commands
      ** that simply appear on the command-line.  This seems goofy.  It would
      ** be better if all commands ran in the order that they appear.  But
      ** we retain the goofy behavior for historical compatibility. */
      if( i==argc-1 ) break;
      z = cmdline_option_value(argc,argv,++i);
      if( z[0]=='.' ){
9056
9057
9058
9059
9060
9061
9062
9063

9064
9065
9066
9067
9068
9069
9070
9071
9072
9073
9074
9075
9076
9077
9078


9079
9080
9081
9082
9083
9084
9085
9086
9087
9088
9089
9090
9091
9092
9093
9094


9095


9096
9097
9098

9099
9100


9101
9102
9103
9104






9105
9106
9107
9108
9109
9110
9111
9112
9113
9114
9115
12251
12252
12253
12254
12255
12256
12257

12258
12259
12260
12261
12262
12263
12264
12265
12266
12267
12268
12269
12270
12271
12272
12273
12274
12275
12276
12277
12278
12279
12280
12281
12282
12283
12284
12285
12286
12287
12288
12289
12290
12291
12292
12293

12294
12295
12296
12297
12298
12299


12300
12301




12302
12303
12304
12305
12306
12307
12308
12309
12310

12311
12312
12313
12314
12315
12316
12317







-
+















+
+
















+
+
-
+
+



+
-
-
+
+
-
-
-
-
+
+
+
+
+
+



-







          if( bail_on_error ) return rc!=0 ? rc : 1;
        }else if( rc!=0 ){
          utf8_printf(stderr,"Error: unable to process SQL \"%s\"\n", z);
          if( bail_on_error ) return rc;
        }
      }
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
    }else if( strncmp(z, "-A", 2)==0 ){
    }else if( cli_strncmp(z, "-A", 2)==0 ){
      if( nCmd>0 ){
        utf8_printf(stderr, "Error: cannot mix regular SQL or dot-commands"
                            " with \"%s\"\n", z);
        return 1;
      }
      open_db(&data, OPEN_DB_ZIPFILE);
      if( z[2] ){
        argv[i] = &z[2];
        arDotCommand(&data, 1, argv+(i-1), argc-(i-1));
      }else{
        arDotCommand(&data, 1, argv+i, argc-i);
      }
      readStdin = 0;
      break;
#endif
    }else if( cli_strcmp(z,"-safe")==0 ){
      data.bSafeMode = data.bSafeModePersist = 1;
    }else{
      utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
      raw_printf(stderr,"Use -help for a list of options.\n");
      return 1;
    }
    data.cMode = data.mode;
  }

  if( !readStdin ){
    /* Run all arguments that do not begin with '-' as if they were separate
    ** command-line inputs, except for the argToSkip argument which contains
    ** the database filename.
    */
    for(i=0; i<nCmd; i++){
      if( azCmd[i][0]=='.' ){
        rc = do_meta_command(azCmd[i], &data);
        if( rc ){
          free(azCmd);
        if( rc ) return rc==2 ? 0 : rc;
          return rc==2 ? 0 : rc;
        }
      }else{
        open_db(&data, 0);
        rc = shell_exec(&data, azCmd[i], &zErrMsg);
        if( zErrMsg || rc ){
        if( zErrMsg!=0 ){
          utf8_printf(stderr,"Error: %s\n", zErrMsg);
          if( zErrMsg!=0 ){
            utf8_printf(stderr,"Error: %s\n", zErrMsg);
          return rc!=0 ? rc : 1;
        }else if( rc!=0 ){
          utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
          return rc;
          }else{
            utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
          }
          sqlite3_free(zErrMsg);
          free(azCmd);
          return rc!=0 ? rc : 1;
        }
      }
    }
    free(azCmd);
  }else{
    /* Run commands received from standard input
    */
    if( stdin_is_interactive ){
      char *zHome;
      char *zHistory;
      int nHistory;
9147
9148
9149
9150
9151
9152
9153




9154
9155
9156

9157
9158

9159






9160
9161
9162
9163
9164
9165
9166
9167


9168
9169
9170







9171
9172





























































































































12349
12350
12351
12352
12353
12354
12355
12356
12357
12358
12359
12360
12361

12362
12363
12364
12365

12366
12367
12368
12369
12370
12371
12372
12373
12374
12375
12376
12377
12378
12379
12380
12381
12382
12383
12384
12385
12386
12387
12388
12389
12390
12391
12392
12393
12394
12395
12396
12397
12398
12399
12400
12401
12402
12403
12404
12405
12406
12407
12408
12409
12410
12411
12412
12413
12414
12415
12416
12417
12418
12419
12420
12421
12422
12423
12424
12425
12426
12427
12428
12429
12430
12431
12432
12433
12434
12435
12436
12437
12438
12439
12440
12441
12442
12443
12444
12445
12446
12447
12448
12449
12450
12451
12452
12453
12454
12455
12456
12457
12458
12459
12460
12461
12462
12463
12464
12465
12466
12467
12468
12469
12470
12471
12472
12473
12474
12475
12476
12477
12478
12479
12480
12481
12482
12483
12484
12485
12486
12487
12488
12489
12490
12491
12492
12493
12494
12495
12496
12497
12498
12499
12500
12501
12502
12503
12504
12505
12506
12507
12508
12509
12510
12511
12512
12513
12514
12515
12516
12517
12518







+
+
+
+


-
+


+
-
+
+
+
+
+
+








+
+



+
+
+
+
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
        free(zHistory);
      }
    }else{
      data.in = stdin;
      rc = process_input(&data);
    }
  }
#ifndef SQLITE_SHELL_FIDDLE
  /* In WASM mode we have to leave the db state in place so that
  ** client code can "push" SQL into it after this call returns. */
  free(azCmd);
  set_table_name(&data, 0);
  if( data.db ){
    session_close_all(&data);
    session_close_all(&data, -1);
    close_db(data.db);
  }
  for(i=0; i<ArraySize(data.aAuxDb); i++){
  sqlite3_free(data.zFreeOnClose);
    sqlite3_free(data.aAuxDb[i].zFreeOnClose);
    if( data.aAuxDb[i].db ){
      session_close_all(&data, i);
      close_db(data.aAuxDb[i].db);
    }
  }
  find_home_dir(1);
  output_reset(&data);
  data.doXdgOpen = 0;
  clearTempFile(&data);
#if !SQLITE_SHELL_IS_UTF8
  for(i=0; i<argcToFree; i++) free(argvToFree[i]);
  free(argvToFree);
#endif
  free(data.colWidth);
  free(data.zNonce);
  /* Clear the global data structure so that valgrind will detect memory
  ** leaks */
  memset(&data, 0, sizeof(data));
#ifdef SQLITE_DEBUG
  if( sqlite3_memory_used()>mem_main_enter ){
    utf8_printf(stderr, "Memory leaked: %u bytes\n",
                (unsigned int)(sqlite3_memory_used()-mem_main_enter));
  }
#endif
#endif /* !SQLITE_SHELL_FIDDLE */
  return rc;
}


#ifdef SQLITE_SHELL_FIDDLE
/* Only for emcc experimentation purposes. */
int fiddle_experiment(int a,int b){
  return a + b;
}

/*
** Returns a pointer to the current DB handle.
*/
sqlite3 * fiddle_db_handle(){
  return globalDb;
}

/*
** Returns a pointer to the given DB name's VFS. If zDbName is 0 then
** "main" is assumed. Returns 0 if no db with the given name is
** open.
*/
sqlite3_vfs * fiddle_db_vfs(const char *zDbName){
  sqlite3_vfs * pVfs = 0;
  if(globalDb){
    sqlite3_file_control(globalDb, zDbName ? zDbName : "main",
                         SQLITE_FCNTL_VFS_POINTER, &pVfs);
  }
  return pVfs;
}

/* Only for emcc experimentation purposes. */
sqlite3 * fiddle_db_arg(sqlite3 *arg){
    printf("fiddle_db_arg(%p)\n", (const void*)arg);
    return arg;
}

/*
** Intended to be called via a SharedWorker() while a separate
** SharedWorker() (which manages the wasm module) is performing work
** which should be interrupted. Unfortunately, SharedWorker is not
** portable enough to make real use of.
*/
void fiddle_interrupt(void){
  if( globalDb ) sqlite3_interrupt(globalDb);
}

/*
** Returns the filename of the given db name, assuming "main" if
** zDbName is NULL. Returns NULL if globalDb is not opened.
*/
const char * fiddle_db_filename(const char * zDbName){
    return globalDb
      ? sqlite3_db_filename(globalDb, zDbName ? zDbName : "main")
      : NULL;
}

/*
** Completely wipes out the contents of the currently-opened database
** but leaves its storage intact for reuse.
*/
void fiddle_reset_db(void){
  if( globalDb ){
    int rc = sqlite3_db_config(globalDb, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0);
    if( 0==rc ) rc = sqlite3_exec(globalDb, "VACUUM", 0, 0, 0);
    sqlite3_db_config(globalDb, SQLITE_DBCONFIG_RESET_DATABASE, 0, 0);
  }
}

/*
** Uses the current database's VFS xRead to stream the db file's
** contents out to the given callback. The callback gets a single
** chunk of size n (its 2nd argument) on each call and must return 0
** on success, non-0 on error. This function returns 0 on success,
** SQLITE_NOTFOUND if no db is open, or propagates any other non-0
** code from the callback. Note that this is not thread-friendly: it
** expects that it will be the only thread reading the db file and
** takes no measures to ensure that is the case.
*/
int fiddle_export_db( int (*xCallback)(unsigned const char *zOut, int n) ){
  sqlite3_int64 nSize = 0;
  sqlite3_int64 nPos = 0;
  sqlite3_file * pFile = 0;
  unsigned char buf[1024 * 8];
  int nBuf = (int)sizeof(buf);
  int rc = shellState.db
    ? sqlite3_file_control(shellState.db, "main",
                           SQLITE_FCNTL_FILE_POINTER, &pFile)
    : SQLITE_NOTFOUND;
  if( rc ) return rc;
  rc = pFile->pMethods->xFileSize(pFile, &nSize);
  if( rc ) return rc;
  if(nSize % nBuf){
    /* DB size is not an even multiple of the buffer size. Reduce
    ** buffer size so that we do not unduly inflate the db size when
    ** exporting. */
    if(0 == nSize % 4096) nBuf = 4096;
    else if(0 == nSize % 2048) nBuf = 2048;
    else if(0 == nSize % 1024) nBuf = 1024;
    else nBuf = 512;
  }
  for( ; 0==rc && nPos<nSize; nPos += nBuf ){
    rc = pFile->pMethods->xRead(pFile, buf, nBuf, nPos);
    if(SQLITE_IOERR_SHORT_READ == rc){
      rc = (nPos + nBuf) < nSize ? rc : 0/*assume EOF*/;
    }
    if( 0==rc ) rc = xCallback(buf, nBuf);
  }
  return rc;
}

/*
** Trivial exportable function for emscripten. It processes zSql as if
** it were input to the sqlite3 shell and redirects all output to the
** wasm binding. fiddle_main() must have been called before this
** is called, or results are undefined.
*/
void fiddle_exec(const char * zSql){
  if(zSql && *zSql){
    if('.'==*zSql) puts(zSql);
    shellState.wasm.zInput = zSql;
    shellState.wasm.zPos = zSql;
    process_input(&shellState);
    shellState.wasm.zInput = shellState.wasm.zPos = 0;
  }
}
#endif /* SQLITE_SHELL_FIDDLE */

Changes to src/sqlite.h.in.

39
40
41
42
43
44
45
46
























47
48
49
50
51
52
53
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







-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







*/
#ifdef __cplusplus
extern "C" {
#endif


/*
** Provide the ability to override linkage features of the interface.
** Facilitate override of interface linkage and calling conventions.
** Be aware that these macros may not be used within this particular
** translation of the amalgamation and its associated header file.
**
** The SQLITE_EXTERN and SQLITE_API macros are used to instruct the
** compiler that the target identifier should have external linkage.
**
** The SQLITE_CDECL macro is used to set the calling convention for
** public functions that accept a variable number of arguments.
**
** The SQLITE_APICALL macro is used to set the calling convention for
** public functions that accept a fixed number of arguments.
**
** The SQLITE_STDCALL macro is no longer used and is now deprecated.
**
** The SQLITE_CALLBACK macro is used to set the calling convention for
** function pointers.
**
** The SQLITE_SYSAPI macro is used to set the calling convention for
** functions provided by the operating system.
**
** Currently, the SQLITE_CDECL, SQLITE_APICALL, SQLITE_CALLBACK, and
** SQLITE_SYSAPI macros are used only when building for environments
** that require non-default calling conventions.
*/
#ifndef SQLITE_EXTERN
# define SQLITE_EXTERN extern
#endif
#ifndef SQLITE_API
# define SQLITE_API
#endif
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
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







-
-
+
+














-
-
-
-
+
+
+
+




-
-
+
+



-
+








+
+
+












-
+







**
** ^The sqlite3_version[] string constant contains the text of [SQLITE_VERSION]
** macro.  ^The sqlite3_libversion() function returns a pointer to the
** to the sqlite3_version[] string constant.  The sqlite3_libversion()
** function is provided for use in DLLs since DLL users usually do not have
** direct access to string constants within the DLL.  ^The
** sqlite3_libversion_number() function returns an integer equal to
** [SQLITE_VERSION_NUMBER].  ^(The sqlite3_sourceid() function returns 
** a pointer to a string constant whose value is the same as the 
** [SQLITE_VERSION_NUMBER].  ^(The sqlite3_sourceid() function returns
** a pointer to a string constant whose value is the same as the
** [SQLITE_SOURCE_ID] C preprocessor macro.  Except if SQLite is built
** using an edited copy of [the amalgamation], then the last four characters
** of the hash might be different from [SQLITE_SOURCE_ID].)^
**
** See also: [sqlite_version()] and [sqlite_source_id()].
*/
SQLITE_EXTERN const char sqlite3_version[];
const char *sqlite3_libversion(void);
const char *sqlite3_sourceid(void);
int sqlite3_libversion_number(void);

/*
** CAPI3REF: Run-Time Library Compilation Options Diagnostics
**
** ^The sqlite3_compileoption_used() function returns 0 or 1 
** indicating whether the specified option was defined at 
** compile time.  ^The SQLITE_ prefix may be omitted from the 
** option name passed to sqlite3_compileoption_used().  
** ^The sqlite3_compileoption_used() function returns 0 or 1
** indicating whether the specified option was defined at
** compile time.  ^The SQLITE_ prefix may be omitted from the
** option name passed to sqlite3_compileoption_used().
**
** ^The sqlite3_compileoption_get() function allows iterating
** over the list of options that were defined at compile time by
** returning the N-th compile time option string.  ^If N is out of range,
** sqlite3_compileoption_get() returns a NULL pointer.  ^The SQLITE_ 
** prefix is omitted from any strings returned by 
** sqlite3_compileoption_get() returns a NULL pointer.  ^The SQLITE_
** prefix is omitted from any strings returned by
** sqlite3_compileoption_get().
**
** ^Support for the diagnostic functions sqlite3_compileoption_used()
** and sqlite3_compileoption_get() may be omitted by specifying the 
** and sqlite3_compileoption_get() may be omitted by specifying the
** [SQLITE_OMIT_COMPILEOPTION_DIAGS] option at compile time.
**
** See also: SQL functions [sqlite_compileoption_used()] and
** [sqlite_compileoption_get()] and the [compile_options pragma].
*/
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
int sqlite3_compileoption_used(const char *zOptName);
const char *sqlite3_compileoption_get(int N);
#else
# define sqlite3_compileoption_used(X) 0
# define sqlite3_compileoption_get(X)  ((void*)0)
#endif

/*
** CAPI3REF: Test To See If The Library Is Threadsafe
**
** ^The sqlite3_threadsafe() function returns zero if and only if
** SQLite was compiled with mutexing code omitted due to the
** [SQLITE_THREADSAFE] compile-time option being set to 0.
**
** SQLite can be compiled with or without mutexes.  When
** the [SQLITE_THREADSAFE] C preprocessor macro is 1 or 2, mutexes
** are enabled and SQLite is threadsafe.  When the
** [SQLITE_THREADSAFE] macro is 0, 
** [SQLITE_THREADSAFE] macro is 0,
** the mutexes are omitted.  Without the mutexes, it is not safe
** to use SQLite concurrently from more than one thread.
**
** Enabling mutexes incurs a measurable performance penalty.
** So if speed is of utmost importance, it makes sense to disable
** the mutexes.  But for maximum safety, mutexes should be enabled.
** ^The default behavior is for mutexes to be enabled.
254
255
256
257
258
259
260
261

262
263
264
265
266
267
268

269
270
271
272
273
274
275
280
281
282
283
284
285
286

287
288
289
290
291
292
293

294
295
296
297
298
299
300
301







-
+






-
+







**
** The sqlite3_int64 and sqlite3_uint64 are the preferred type definitions.
** The sqlite_int64 and sqlite_uint64 types are supported for backwards
** compatibility only.
**
** ^The sqlite3_int64 and sqlite_int64 types can store integer values
** between -9223372036854775808 and +9223372036854775807 inclusive.  ^The
** sqlite3_uint64 and sqlite_uint64 types can store integer values 
** sqlite3_uint64 and sqlite_uint64 types can store integer values
** between 0 and +18446744073709551615 inclusive.
*/
#ifdef SQLITE_INT64_TYPE
  typedef SQLITE_INT64_TYPE sqlite_int64;
# ifdef SQLITE_UINT64_TYPE
    typedef SQLITE_UINT64_TYPE sqlite_uint64;
# else  
# else
    typedef unsigned SQLITE_INT64_TYPE sqlite_uint64;
# endif
#elif defined(_MSC_VER) || defined(__BORLANDC__)
  typedef __int64 sqlite_int64;
  typedef unsigned __int64 sqlite_uint64;
#else
  typedef long long int sqlite_int64;
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
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







+
+
+
+

-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-







**
** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors
** for the [sqlite3] object.
** ^Calls to sqlite3_close() and sqlite3_close_v2() return [SQLITE_OK] if
** the [sqlite3] object is successfully destroyed and all associated
** resources are deallocated.
**
** Ideally, applications should [sqlite3_finalize | finalize] all
** [prepared statements], [sqlite3_blob_close | close] all [BLOB handles], and
** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
** with the [sqlite3] object prior to attempting to close the object.
** ^If the database connection is associated with unfinalized prepared
** statements or unfinished sqlite3_backup objects then sqlite3_close()
** will leave the database connection open and return [SQLITE_BUSY].
** ^If sqlite3_close_v2() is called with unfinalized prepared statements
** and/or unfinished sqlite3_backups, then the database connection becomes
** an unusable "zombie" which will automatically be deallocated when the
** last prepared statement is finalized or the last sqlite3_backup is
** finished.  The sqlite3_close_v2() interface is intended for use with
** host languages that are garbage collected, and where the order in which
** destructors are called is arbitrary.
** statements, BLOB handlers, and/or unfinished sqlite3_backup objects then
** sqlite3_close() will leave the database connection open and return
** [SQLITE_BUSY]. ^If sqlite3_close_v2() is called with unfinalized prepared
** statements, unclosed BLOB handlers, and/or unfinished sqlite3_backups,
** it returns [SQLITE_OK] regardless, but instead of deallocating the database
** connection immediately, it marks the database connection as an unusable
** "zombie" and makes arrangements to automatically deallocate the database
** connection after all prepared statements are finalized, all BLOB handles
** are closed, and all backups have finished. The sqlite3_close_v2() interface
** is intended for use with host languages that are garbage collected, and
** where the order in which destructors are called is arbitrary.
**
** Applications should [sqlite3_finalize | finalize] all [prepared statements],
** [sqlite3_blob_close | close] all [BLOB handles], and 
** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
** with the [sqlite3] object prior to attempting to close the object.  ^If
** sqlite3_close_v2() is called on a [database connection] that still has
** outstanding [prepared statements], [BLOB handles], and/or
** [sqlite3_backup] objects then it returns [SQLITE_OK] and the deallocation
** of resources is deferred until all [prepared statements], [BLOB handles],
** and [sqlite3_backup] objects are also destroyed.
**
** ^If an [sqlite3] object is destroyed while a transaction is open,
** the transaction is automatically rolled back.
**
** The C parameter to [sqlite3_close(C)] and [sqlite3_close_v2(C)]
** must be either a NULL
** pointer or an [sqlite3] object pointer obtained
341
342
343
344
345
346
347
348

349
350
351
352
353
354
355
363
364
365
366
367
368
369

370
371
372
373
374
375
376
377







-
+







/*
** CAPI3REF: One-Step Query Execution Interface
** METHOD: sqlite3
**
** The sqlite3_exec() interface is a convenience wrapper around
** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()],
** that allows an application to run multiple statements of SQL
** without having to use a lot of C code. 
** without having to use a lot of C code.
**
** ^The sqlite3_exec() interface runs zero or more UTF-8 encoded,
** semicolon-separate SQL statements passed into its 2nd argument,
** in the context of the [database connection] passed in as its 1st
** argument.  ^If the callback function of the 3rd argument to
** sqlite3_exec() is not NULL, then it is invoked for each result row
** coming out of the evaluated SQL statements.  ^The 4th argument to
381
382
383
384
385
386
387
388

389
390
391
392
393
394
395
403
404
405
406
407
408
409

410
411
412
413
414
415
416
417







-
+







** result row is NULL then the corresponding string pointer for the
** sqlite3_exec() callback is a NULL pointer.  ^The 4th argument to the
** sqlite3_exec() callback is an array of pointers to strings where each
** entry represents the name of corresponding result column as obtained
** from [sqlite3_column_name()].
**
** ^If the 2nd parameter to sqlite3_exec() is a NULL pointer, a pointer
** to an empty string, or a pointer that contains only whitespace and/or 
** to an empty string, or a pointer that contains only whitespace and/or
** SQL comments, then no SQL statements are evaluated and the database
** is not changed.
**
** Restrictions:
**
** <ul>
** <li> The application must ensure that the 1st parameter to sqlite3_exec()
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
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







+
+




+





+


+

















+
+


+



+







+
+
+
+
+
+
+
+
+
+
+
+
+















-
+





+
+


+
+
+







#define SQLITE_IOERR_GETTEMPPATH       (SQLITE_IOERR | (25<<8))
#define SQLITE_IOERR_CONVPATH          (SQLITE_IOERR | (26<<8))
#define SQLITE_IOERR_VNODE             (SQLITE_IOERR | (27<<8))
#define SQLITE_IOERR_AUTH              (SQLITE_IOERR | (28<<8))
#define SQLITE_IOERR_BEGIN_ATOMIC      (SQLITE_IOERR | (29<<8))
#define SQLITE_IOERR_COMMIT_ATOMIC     (SQLITE_IOERR | (30<<8))
#define SQLITE_IOERR_ROLLBACK_ATOMIC   (SQLITE_IOERR | (31<<8))
#define SQLITE_IOERR_DATA              (SQLITE_IOERR | (32<<8))
#define SQLITE_IOERR_CORRUPTFS         (SQLITE_IOERR | (33<<8))
#define SQLITE_LOCKED_SHAREDCACHE      (SQLITE_LOCKED |  (1<<8))
#define SQLITE_LOCKED_VTAB             (SQLITE_LOCKED |  (2<<8))
#define SQLITE_BUSY_RECOVERY           (SQLITE_BUSY   |  (1<<8))
#define SQLITE_BUSY_SNAPSHOT           (SQLITE_BUSY   |  (2<<8))
#define SQLITE_BUSY_TIMEOUT            (SQLITE_BUSY   |  (3<<8))
#define SQLITE_CANTOPEN_NOTEMPDIR      (SQLITE_CANTOPEN | (1<<8))
#define SQLITE_CANTOPEN_ISDIR          (SQLITE_CANTOPEN | (2<<8))
#define SQLITE_CANTOPEN_FULLPATH       (SQLITE_CANTOPEN | (3<<8))
#define SQLITE_CANTOPEN_CONVPATH       (SQLITE_CANTOPEN | (4<<8))
#define SQLITE_CANTOPEN_DIRTYWAL       (SQLITE_CANTOPEN | (5<<8)) /* Not Used */
#define SQLITE_CANTOPEN_SYMLINK        (SQLITE_CANTOPEN | (6<<8))
#define SQLITE_CORRUPT_VTAB            (SQLITE_CORRUPT | (1<<8))
#define SQLITE_CORRUPT_SEQUENCE        (SQLITE_CORRUPT | (2<<8))
#define SQLITE_CORRUPT_INDEX           (SQLITE_CORRUPT | (3<<8))
#define SQLITE_READONLY_RECOVERY       (SQLITE_READONLY | (1<<8))
#define SQLITE_READONLY_CANTLOCK       (SQLITE_READONLY | (2<<8))
#define SQLITE_READONLY_ROLLBACK       (SQLITE_READONLY | (3<<8))
#define SQLITE_READONLY_DBMOVED        (SQLITE_READONLY | (4<<8))
#define SQLITE_READONLY_CANTINIT       (SQLITE_READONLY | (5<<8))
#define SQLITE_READONLY_DIRECTORY      (SQLITE_READONLY | (6<<8))
#define SQLITE_ABORT_ROLLBACK          (SQLITE_ABORT | (2<<8))
#define SQLITE_CONSTRAINT_CHECK        (SQLITE_CONSTRAINT | (1<<8))
#define SQLITE_CONSTRAINT_COMMITHOOK   (SQLITE_CONSTRAINT | (2<<8))
#define SQLITE_CONSTRAINT_FOREIGNKEY   (SQLITE_CONSTRAINT | (3<<8))
#define SQLITE_CONSTRAINT_FUNCTION     (SQLITE_CONSTRAINT | (4<<8))
#define SQLITE_CONSTRAINT_NOTNULL      (SQLITE_CONSTRAINT | (5<<8))
#define SQLITE_CONSTRAINT_PRIMARYKEY   (SQLITE_CONSTRAINT | (6<<8))
#define SQLITE_CONSTRAINT_TRIGGER      (SQLITE_CONSTRAINT | (7<<8))
#define SQLITE_CONSTRAINT_UNIQUE       (SQLITE_CONSTRAINT | (8<<8))
#define SQLITE_CONSTRAINT_VTAB         (SQLITE_CONSTRAINT | (9<<8))
#define SQLITE_CONSTRAINT_ROWID        (SQLITE_CONSTRAINT |(10<<8))
#define SQLITE_CONSTRAINT_PINNED       (SQLITE_CONSTRAINT |(11<<8))
#define SQLITE_CONSTRAINT_DATATYPE     (SQLITE_CONSTRAINT |(12<<8))
#define SQLITE_NOTICE_RECOVER_WAL      (SQLITE_NOTICE | (1<<8))
#define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8))
#define SQLITE_NOTICE_RBU              (SQLITE_NOTICE | (3<<8))
#define SQLITE_WARNING_AUTOINDEX       (SQLITE_WARNING | (1<<8))
#define SQLITE_AUTH_USER               (SQLITE_AUTH | (1<<8))
#define SQLITE_OK_LOAD_PERMANENTLY     (SQLITE_OK | (1<<8))
#define SQLITE_OK_SYMLINK              (SQLITE_OK | (2<<8)) /* internal use only */

/*
** CAPI3REF: Flags For File Open Operations
**
** These bit values are intended for use in the
** 3rd parameter to the [sqlite3_open_v2()] interface and
** in the 4th parameter to the [sqlite3_vfs.xOpen] method.
**
** Only those flags marked as "Ok for sqlite3_open_v2()" may be
** used as the third argument to the [sqlite3_open_v2()] interface.
** The other flags have historically been ignored by sqlite3_open_v2(),
** though future versions of SQLite might change so that an error is
** raised if any of the disallowed bits are passed into sqlite3_open_v2().
** Applications should not depend on the historical behavior.
**
** Note in particular that passing the SQLITE_OPEN_EXCLUSIVE flag into
** [sqlite3_open_v2()] does *not* cause the underlying database file
** to be opened using O_EXCL.  Passing SQLITE_OPEN_EXCLUSIVE into
** [sqlite3_open_v2()] has historically be a no-op and might become an
** error in future versions of SQLite.
*/
#define SQLITE_OPEN_READONLY         0x00000001  /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_READWRITE        0x00000002  /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_CREATE           0x00000004  /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_DELETEONCLOSE    0x00000008  /* VFS only */
#define SQLITE_OPEN_EXCLUSIVE        0x00000010  /* VFS only */
#define SQLITE_OPEN_AUTOPROXY        0x00000020  /* VFS only */
#define SQLITE_OPEN_URI              0x00000040  /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_MEMORY           0x00000080  /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_MAIN_DB          0x00000100  /* VFS only */
#define SQLITE_OPEN_TEMP_DB          0x00000200  /* VFS only */
#define SQLITE_OPEN_TRANSIENT_DB     0x00000400  /* VFS only */
#define SQLITE_OPEN_MAIN_JOURNAL     0x00000800  /* VFS only */
#define SQLITE_OPEN_TEMP_JOURNAL     0x00001000  /* VFS only */
#define SQLITE_OPEN_SUBJOURNAL       0x00002000  /* VFS only */
#define SQLITE_OPEN_MASTER_JOURNAL   0x00004000  /* VFS only */
#define SQLITE_OPEN_SUPER_JOURNAL    0x00004000  /* VFS only */
#define SQLITE_OPEN_NOMUTEX          0x00008000  /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_FULLMUTEX        0x00010000  /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_SHAREDCACHE      0x00020000  /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_PRIVATECACHE     0x00040000  /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_WAL              0x00080000  /* VFS only */
#define SQLITE_OPEN_NOFOLLOW         0x01000000  /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_EXRESCODE        0x02000000  /* Extended result codes */

/* Reserved:                         0x00F00000 */
/* Legacy compatibility: */
#define SQLITE_OPEN_MASTER_JOURNAL   0x00004000  /* VFS only */


/*
** CAPI3REF: Device Characteristics
**
** The xDeviceCharacteristics method of the [sqlite3_io_methods]
** object returns an integer which is a vector of these
** bit values expressing I/O characteristics of the mass storage
618
619
620
621
622
623
624
625





626
627
628
629
630
631





632
633
634
635
636
637
638
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







-
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+







#define SQLITE_IOCAP_BATCH_ATOMIC           0x00004000

/*
** CAPI3REF: File Locking Levels
**
** SQLite uses one of these integer values as the second
** argument to calls it makes to the xLock() and xUnlock() methods
** of an [sqlite3_io_methods] object.
** of an [sqlite3_io_methods] object.  These values are ordered from
** lest restrictive to most restrictive.
**
** The argument to xLock() is always SHARED or higher.  The argument to
** xUnlock is either SHARED or NONE.
*/
#define SQLITE_LOCK_NONE          0
#define SQLITE_LOCK_SHARED        1
#define SQLITE_LOCK_RESERVED      2
#define SQLITE_LOCK_PENDING       3
#define SQLITE_LOCK_EXCLUSIVE     4
#define SQLITE_LOCK_NONE          0       /* xUnlock() only */
#define SQLITE_LOCK_SHARED        1       /* xLock() or xUnlock() */
#define SQLITE_LOCK_RESERVED      2       /* xLock() only */
#define SQLITE_LOCK_PENDING       3       /* xLock() only */
#define SQLITE_LOCK_EXCLUSIVE     4       /* xLock() only */

/*
** CAPI3REF: Synchronization Type Flags
**
** When SQLite invokes the xSync() method of an
** [sqlite3_io_methods] object it uses a combination of
** these integer values as the second argument.
702
703
704
705
706
707
708







709

710
711
712
713
714
715
716
755
756
757
758
759
760
761
762
763
764
765
766
767
768

769
770
771
772
773
774
775
776







+
+
+
+
+
+
+
-
+







** <ul>
** <li> [SQLITE_LOCK_NONE],
** <li> [SQLITE_LOCK_SHARED],
** <li> [SQLITE_LOCK_RESERVED],
** <li> [SQLITE_LOCK_PENDING], or
** <li> [SQLITE_LOCK_EXCLUSIVE].
** </ul>
** xLock() upgrades the database file lock.  In other words, xLock() moves the
** database file lock in the direction NONE toward EXCLUSIVE. The argument to
** xLock() is always on of SHARED, RESERVED, PENDING, or EXCLUSIVE, never
** SQLITE_LOCK_NONE.  If the database file lock is already at or above the
** requested lock, then the call to xLock() is a no-op.
** xUnlock() downgrades the database file lock to either SHARED or NONE.
*  If the lock is already at or below the requested lock state, then the call
** xLock() increases the lock. xUnlock() decreases the lock.
** to xUnlock() is a no-op.
** The xCheckReservedLock() method checks whether any database connection,
** either in this process or in some other process, is holding a RESERVED,
** PENDING, or EXCLUSIVE lock on the file.  It returns true
** if such a lock exists and false otherwise.
**
** The xFileControl() method is a generic interface that allows custom
** VFS implementations to directly control an open file using the
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
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







-
-
+
+
-









+
+
+
+
+
+
+
+
+



-
+







**
** <ul>
** <li>[[SQLITE_FCNTL_LOCKSTATE]]
** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging.  This
** opcode causes the xFileControl method to write the current state of
** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED],
** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE])
** into an integer that the pArg argument points to. This capability
** is used during testing and is only available when the SQLITE_TEST
** into an integer that the pArg argument points to.
** This capability is only available if SQLite is compiled with [SQLITE_DEBUG].
** compile-time option is used.
**
** <li>[[SQLITE_FCNTL_SIZE_HINT]]
** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS
** layer a hint of how large the database file will grow to be during the
** current transaction.  This hint is not guaranteed to be accurate but it
** is often close.  The underlying VFS might choose to preallocate database
** file space based on this hint in order to help writes to the database
** file run faster.
**
** <li>[[SQLITE_FCNTL_SIZE_LIMIT]]
** The [SQLITE_FCNTL_SIZE_LIMIT] opcode is used by in-memory VFS that
** implements [sqlite3_deserialize()] to set an upper bound on the size
** of the in-memory database.  The argument is a pointer to a [sqlite3_int64].
** If the integer pointed to is negative, then it is filled in with the
** current limit.  Otherwise the limit is set to the larger of the value
** of the integer pointed to and the current database size.  The integer
** pointed to is set to the new limit.
**
** <li>[[SQLITE_FCNTL_CHUNK_SIZE]]
** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS
** extends and truncates the database file in chunks of a size specified
** by the user. The fourth argument to [sqlite3_file_control()] should 
** by the user. The fourth argument to [sqlite3_file_control()] should
** point to an integer (type int) containing the new chunk-size to use
** for the nominated database. Allocating database file space in large
** chunks (say 1MB at a time), may reduce file-system fragmentation and
** improve performance on some systems.
**
** <li>[[SQLITE_FCNTL_FILE_POINTER]]
** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer
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
913
914
915
916
917
918
919



920
921
922
923
924
925




926
927
928
929
930
931
932
933
934
935


936
937
938
939
940
941
942
943
944







-
-
-
+
+
+



-
-
-
-
+
+
+
+






-
-
+
+







**
** <li>[[SQLITE_FCNTL_SYNC_OMITTED]]
** No longer in use.
**
** <li>[[SQLITE_FCNTL_SYNC]]
** The [SQLITE_FCNTL_SYNC] opcode is generated internally by SQLite and
** sent to the VFS immediately before the xSync method is invoked on a
** database file descriptor. Or, if the xSync method is not invoked 
** because the user has configured SQLite with 
** [PRAGMA synchronous | PRAGMA synchronous=OFF] it is invoked in place 
** database file descriptor. Or, if the xSync method is not invoked
** because the user has configured SQLite with
** [PRAGMA synchronous | PRAGMA synchronous=OFF] it is invoked in place
** of the xSync method. In most cases, the pointer argument passed with
** this file-control is NULL. However, if the database file is being synced
** as part of a multi-database commit, the argument points to a nul-terminated
** string containing the transactions master-journal file name. VFSes that 
** do not need this signal should silently ignore this opcode. Applications 
** should not call [sqlite3_file_control()] with this opcode as doing so may 
** disrupt the operation of the specialized VFSes that do require it.  
** string containing the transactions super-journal file name. VFSes that
** do not need this signal should silently ignore this opcode. Applications
** should not call [sqlite3_file_control()] with this opcode as doing so may
** disrupt the operation of the specialized VFSes that do require it.
**
** <li>[[SQLITE_FCNTL_COMMIT_PHASETWO]]
** The [SQLITE_FCNTL_COMMIT_PHASETWO] opcode is generated internally by SQLite
** and sent to the VFS after a transaction has been committed immediately
** but before the database is unlocked. VFSes that do not need this signal
** should silently ignore this opcode. Applications should not call
** [sqlite3_file_control()] with this opcode as doing so may disrupt the 
** operation of the specialized VFSes that do require it.  
** [sqlite3_file_control()] with this opcode as doing so may disrupt the
** operation of the specialized VFSes that do require it.
**
** <li>[[SQLITE_FCNTL_WIN32_AV_RETRY]]
** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
** retry counts and intervals for certain disk I/O operations for the
** windows [VFS] in order to provide robustness in the presence of
** anti-virus programs.  By default, the windows VFS will retry file read,
** file write, and file delete operations up to 10 times, with a delay
935
936
937
938
939
940
941
942

943
944
945
946
947
948
949
950
951
952
953

954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970

971
972

973
974
975
976
977
978
979

980
981
982
983
984
985
986
987
988
989
990
991
992
993

994
995
996
997
998
999
1000
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







-
+










-
+
















-
+

-
+






-
+













-
+







** sqlite3_file_control(db,SQLITE_FCNTL_VFS_POINTER,X) must be
** of type "[sqlite3_vfs] **".  This opcodes will set *X
** to a pointer to the top-level VFS.)^
** ^When there are multiple VFS shims in the stack, this opcode finds the
** upper-most shim only.
**
** <li>[[SQLITE_FCNTL_PRAGMA]]
** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA] 
** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA]
** file control is sent to the open [sqlite3_file] object corresponding
** to the database file to which the pragma statement refers. ^The argument
** to the [SQLITE_FCNTL_PRAGMA] file control is an array of
** pointers to strings (char**) in which the second element of the array
** is the name of the pragma and the third element is the argument to the
** pragma or NULL if the pragma has no argument.  ^The handler for an
** [SQLITE_FCNTL_PRAGMA] file control can optionally make the first element
** of the char** argument point to a string obtained from [sqlite3_mprintf()]
** or the equivalent and that string will become the result of the pragma or
** the error message if the pragma fails. ^If the
** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal 
** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal
** [PRAGMA] processing continues.  ^If the [SQLITE_FCNTL_PRAGMA]
** file control returns [SQLITE_OK], then the parser assumes that the
** VFS has handled the PRAGMA itself and the parser generates a no-op
** prepared statement if result string is NULL, or that returns a copy
** of the result string if the string is non-NULL.
** ^If the [SQLITE_FCNTL_PRAGMA] file control returns
** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means
** that the VFS encountered an error while handling the [PRAGMA] and the
** compilation of the PRAGMA fails with an error.  ^The [SQLITE_FCNTL_PRAGMA]
** file control occurs at the beginning of pragma statement analysis and so
** it is able to override built-in [PRAGMA] statements.
**
** <li>[[SQLITE_FCNTL_BUSYHANDLER]]
** ^The [SQLITE_FCNTL_BUSYHANDLER]
** file-control may be invoked by SQLite on the database file handle
** shortly after it is opened in order to provide a custom VFS with access
** to the connections busy-handler callback. The argument is of type (void **)
** to the connection's busy-handler callback. The argument is of type (void**)
** - an array of two (void *) values. The first (void *) actually points
** to a function of type (int (*)(void *)). In order to invoke the connections
** to a function of type (int (*)(void *)). In order to invoke the connection's
** busy-handler, this function should be invoked with the second (void *) in
** the array as the only argument. If it returns non-zero, then the operation
** should be retried. If it returns zero, the custom VFS should abandon the
** current operation.
**
** <li>[[SQLITE_FCNTL_TEMPFILENAME]]
** ^Application can invoke the [SQLITE_FCNTL_TEMPFILENAME] file-control
** ^Applications can invoke the [SQLITE_FCNTL_TEMPFILENAME] file-control
** to have SQLite generate a
** temporary filename using the same algorithm that is followed to generate
** temporary filenames for TEMP tables and other internal uses.  The
** argument should be a char** which will be filled with the filename
** written into memory obtained from [sqlite3_malloc()].  The caller should
** invoke [sqlite3_free()] on the result to avoid a memory leak.
**
** <li>[[SQLITE_FCNTL_MMAP_SIZE]]
** The [SQLITE_FCNTL_MMAP_SIZE] file control is used to query or set the
** maximum number of bytes that will be used for memory-mapped I/O.
** The argument is a pointer to a value of type sqlite3_int64 that
** is an advisory maximum number of bytes in the file to memory map.  The
** pointer is overwritten with the old value.  The limit is not changed if
** the value originally pointed to is negative, and so the current limit 
** the value originally pointed to is negative, and so the current limit
** can be queried by passing in a pointer to a negative number.  This
** file-control is used internally to implement [PRAGMA mmap_size].
**
** <li>[[SQLITE_FCNTL_TRACE]]
** The [SQLITE_FCNTL_TRACE] file control provides advisory information
** to the VFS about what the higher layers of the SQLite stack are doing.
** This file control is used by some VFS activity tracing [shims].
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
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







-
+
















-
+











-
+







-
-
+
+
+
-
-
+
+
+














-
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







** <li>[[SQLITE_FCNTL_ZIPVFS]]
** The [SQLITE_FCNTL_ZIPVFS] opcode is implemented by zipvfs only. All other
** VFS should return SQLITE_NOTFOUND for this opcode.
**
** <li>[[SQLITE_FCNTL_RBU]]
** The [SQLITE_FCNTL_RBU] opcode is implemented by the special VFS used by
** the RBU extension only.  All other VFS should return SQLITE_NOTFOUND for
** this opcode.  
** this opcode.
**
** <li>[[SQLITE_FCNTL_BEGIN_ATOMIC_WRITE]]
** If the [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] opcode returns SQLITE_OK, then
** the file descriptor is placed in "batch write mode", which
** means all subsequent write operations will be deferred and done
** atomically at the next [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE].  Systems
** that do not support batch atomic writes will return SQLITE_NOTFOUND.
** ^Following a successful SQLITE_FCNTL_BEGIN_ATOMIC_WRITE and prior to
** the closing [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE] or
** [SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE], SQLite will make
** no VFS interface calls on the same [sqlite3_file] file descriptor
** except for calls to the xWrite method and the xFileControl method
** with [SQLITE_FCNTL_SIZE_HINT].
**
** <li>[[SQLITE_FCNTL_COMMIT_ATOMIC_WRITE]]
** The [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE] opcode causes all write
** operations since the previous successful call to 
** operations since the previous successful call to
** [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] to be performed atomically.
** This file control returns [SQLITE_OK] if and only if the writes were
** all performed successfully and have been committed to persistent storage.
** ^Regardless of whether or not it is successful, this file control takes
** the file descriptor out of batch write mode so that all subsequent
** write operations are independent.
** ^SQLite will never invoke SQLITE_FCNTL_COMMIT_ATOMIC_WRITE without
** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE].
**
** <li>[[SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE]]
** The [SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE] opcode causes all write
** operations since the previous successful call to 
** operations since the previous successful call to
** [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] to be rolled back.
** ^This file control takes the file descriptor out of batch write mode
** so that all subsequent write operations are independent.
** ^SQLite will never invoke SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE without
** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE].
**
** <li>[[SQLITE_FCNTL_LOCK_TIMEOUT]]
** The [SQLITE_FCNTL_LOCK_TIMEOUT] opcode causes attempts to obtain
** a file lock using the xLock or xShmLock methods of the VFS to wait
** The [SQLITE_FCNTL_LOCK_TIMEOUT] opcode is used to configure a VFS
** to block for up to M milliseconds before failing when attempting to
** obtain a file lock using the xLock or xShmLock methods of the VFS.
** for up to M milliseconds before failing, where M is the single 
** unsigned integer parameter.
** The parameter is a pointer to a 32-bit signed integer that contains
** the value that M is to be set to. Before returning, the 32-bit signed
** integer is overwritten with the previous value of M.
**
** <li>[[SQLITE_FCNTL_DATA_VERSION]]
** The [SQLITE_FCNTL_DATA_VERSION] opcode is used to detect changes to
** a database file.  The argument is a pointer to a 32-bit unsigned integer.
** The "data version" for the pager is written into the pointer.  The
** "data version" changes whenever any change occurs to the corresponding
** database file, either through SQL statements on the same database
** connection or through transactions committed by separate database
** connections possibly in other processes. The [sqlite3_total_changes()]
** interface can be used to find if any database on the connection has changed,
** but that interface responds to changes on TEMP as well as MAIN and does
** not provide a mechanism to detect changes to MAIN only.  Also, the
** [sqlite3_total_changes()] interface responds to internal changes only and
** omits changes made by other database connections.  The
** [PRAGMA data_version] command provide a mechanism to detect changes to
** [PRAGMA data_version] command provides a mechanism to detect changes to
** a single attached database that occur due to other database connections,
** but omits changes implemented by the database connection on which it is
** called.  This file control is the only mechanism to detect changes that
** happen either internally or externally and that are associated with
** a particular attached database.
**
** <li>[[SQLITE_FCNTL_CKPT_START]]
** The [SQLITE_FCNTL_CKPT_START] opcode is invoked from within a checkpoint
** in wal mode before the client starts to copy pages from the wal
** file to the database file.
**
** <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.
**
** <li>[[SQLITE_FCNTL_RESET_CACHE]]
** If there is currently no transaction open on the database, and the 
** database is not a temp db, then this file-control purges the contents
** of the in-memory page cache. If there is an open transaction, or if
** the db is a temp-db, it is a no-op, not an error.
** </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
1127
1128
1129
1130
1131
1132
1133







1134
1135
1136
1137
1138
1139
1140
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251







+
+
+
+
+
+
+







#define SQLITE_FCNTL_WIN32_GET_HANDLE       29
#define SQLITE_FCNTL_PDB                    30
#define SQLITE_FCNTL_BEGIN_ATOMIC_WRITE     31
#define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE    32
#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
#define SQLITE_FCNTL_RESET_CACHE            42

/* 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


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
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
1318
1319
1320







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
















-
-
+
+

-
+







** A pointer to the opaque sqlite3_api_routines structure is passed as
** the third parameter to entry points of [loadable extensions].  This
** structure must be typedefed in order to work around compiler warnings
** on some platforms.
*/
typedef struct sqlite3_api_routines sqlite3_api_routines;

/*
** CAPI3REF: File Name
**
** Type [sqlite3_filename] is used by SQLite to pass filenames to the
** xOpen method of a [VFS]. It may be cast to (const char*) and treated
** as a normal, nul-terminated, UTF-8 buffer containing the filename, but
** may also be passed to special APIs such as:
**
** <ul>
** <li>  sqlite3_filename_database()
** <li>  sqlite3_filename_journal()
** <li>  sqlite3_filename_wal()
** <li>  sqlite3_uri_parameter()
** <li>  sqlite3_uri_boolean()
** <li>  sqlite3_uri_int64()
** <li>  sqlite3_uri_key()
** </ul>
*/
typedef const char *sqlite3_filename;

/*
** CAPI3REF: OS Interface Object
**
** An instance of the sqlite3_vfs object defines the interface between
** the SQLite core and the underlying operating system.  The "vfs"
** in the name of the object stands for "virtual file system".  See
** the [VFS | VFS documentation] for further information.
**
** The VFS interface is sometimes extended by adding new methods onto
** the end.  Each time such an extension occurs, the iVersion field
** is incremented.  The iVersion value started out as 1 in
** SQLite [version 3.5.0] on [dateof:3.5.0], then increased to 2
** with SQLite [version 3.7.0] on [dateof:3.7.0], and then increased
** to 3 with SQLite [version 3.7.6] on [dateof:3.7.6].  Additional fields
** may be appended to the sqlite3_vfs object and the iVersion value
** may increase again in future versions of SQLite.
** Note that the structure
** of the sqlite3_vfs object changes in the transition from
** Note that due to an oversight, the structure
** of the sqlite3_vfs object changed in the transition from
** SQLite [version 3.5.9] to [version 3.6.0] on [dateof:3.6.0]
** and yet the iVersion field was not modified.
** and yet the iVersion field was not increased.
**
** The szOsFile field is the size of the subclassed [sqlite3_file]
** structure used by this VFS.  mxPathname is the maximum length of
** a pathname in this VFS.
**
** Registered sqlite3_vfs objects are kept on a linked list formed by
** the pNext pointer.  The [sqlite3_vfs_register()]
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
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







-
+






-
+













-
+







** 11 alphanumeric and/or "-" characters.
** ^SQLite further guarantees that
** the string will be valid and unchanged until xClose() is
** called. Because of the previous sentence,
** the [sqlite3_file] can safely store a pointer to the
** filename if it needs to remember the filename for some reason.
** If the zFilename parameter to xOpen is a NULL pointer then xOpen
** must invent its own temporary name for the file.  ^Whenever the 
** must invent its own temporary name for the file.  ^Whenever the
** xFilename parameter is NULL it will also be the case that the
** flags parameter will include [SQLITE_OPEN_DELETEONCLOSE].
**
** The flags argument to xOpen() includes all bits set in
** the flags argument to [sqlite3_open_v2()].  Or if [sqlite3_open()]
** or [sqlite3_open16()] is used, then flags includes at least
** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]. 
** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE].
** If xOpen() opens a file read-only then it sets *pOutFlags to
** include [SQLITE_OPEN_READONLY].  Other bits in *pOutFlags may be set.
**
** ^(SQLite will also add one of the following flags to the xOpen()
** call, depending on the object being opened:
**
** <ul>
** <li>  [SQLITE_OPEN_MAIN_DB]
** <li>  [SQLITE_OPEN_MAIN_JOURNAL]
** <li>  [SQLITE_OPEN_TEMP_DB]
** <li>  [SQLITE_OPEN_TEMP_JOURNAL]
** <li>  [SQLITE_OPEN_TRANSIENT_DB]
** <li>  [SQLITE_OPEN_SUBJOURNAL]
** <li>  [SQLITE_OPEN_MASTER_JOURNAL]
** <li>  [SQLITE_OPEN_SUPER_JOURNAL]
** <li>  [SQLITE_OPEN_WAL]
** </ul>)^
**
** The file I/O implementation can use the object type flags to
** change the way it deals with files.  For example, an application
** that does not care about crash recovery or rollback might make
** the open of a journal file a no-op.  Writes to this journal would
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
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335

1336
1337
1338
1339
1340
1341
1342
1390
1391
1392
1393
1394
1395
1396

1397
1398
1399

1400
1401
1402
1403

1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416


1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443


1444
1445
1446

1447
1448
1449
1450
1451
1452

1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471

1472
1473
1474
1475
1476
1477
1478
1479







-
+


-
+



-
+












-
-
+
+
+
+
+
+
+
+



















-
-
+
+

-
+





-
+


















-
+







** deleted when it is closed.  ^The [SQLITE_OPEN_DELETEONCLOSE]
** will be set for TEMP databases and their journals, transient
** databases, and subjournals.
**
** ^The [SQLITE_OPEN_EXCLUSIVE] flag is always used in conjunction
** with the [SQLITE_OPEN_CREATE] flag, which are both directly
** analogous to the O_EXCL and O_CREAT flags of the POSIX open()
** API.  The SQLITE_OPEN_EXCLUSIVE flag, when paired with the 
** API.  The SQLITE_OPEN_EXCLUSIVE flag, when paired with the
** SQLITE_OPEN_CREATE, is used to indicate that file should always
** be created, and that it is an error if it already exists.
** It is <i>not</i> used to indicate the file should be opened 
** It is <i>not</i> used to indicate the file should be opened
** for exclusive access.
**
** ^At least szOsFile bytes of memory are allocated by SQLite
** to hold the  [sqlite3_file] structure passed as the third
** to hold the [sqlite3_file] structure passed as the third
** argument to xOpen.  The xOpen method does not have to
** allocate the structure; it should just fill it in.  Note that
** the xOpen method must set the sqlite3_file.pMethods to either
** a valid [sqlite3_io_methods] object or to NULL.  xOpen must do
** this even if the open fails.  SQLite expects that the sqlite3_file.pMethods
** element will be valid after xOpen returns regardless of the success
** or failure of the xOpen call.
**
** [[sqlite3_vfs.xAccess]]
** ^The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS]
** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to
** test whether a file is readable and writable, or [SQLITE_ACCESS_READ]
** to test whether a file is at least readable.   The file can be a
** directory.
** to test whether a file is at least readable.  The SQLITE_ACCESS_READ
** flag is never actually used and is not implemented in the built-in
** VFSes of SQLite.  The file is named by the second argument and can be a
** directory. The xAccess method returns [SQLITE_OK] on success or some
** non-zero error code if there is an I/O error or if the name of
** the file given in the second argument is illegal.  If SQLITE_OK
** is returned, then non-zero or zero is written into *pResOut to indicate
** whether or not the file is accessible.
**
** ^SQLite will always allocate at least mxPathname+1 bytes for the
** output buffer xFullPathname.  The exact size of the output buffer
** is also passed as a parameter to both  methods. If the output buffer
** is not large enough, [SQLITE_CANTOPEN] should be returned. Since this is
** handled as a fatal error by SQLite, vfs implementations should endeavor
** to prevent this by setting mxPathname to a sufficiently large value.
**
** The xRandomness(), xSleep(), xCurrentTime(), and xCurrentTimeInt64()
** interfaces are not strictly a part of the filesystem, but they are
** included in the VFS structure for completeness.
** The xRandomness() function attempts to return nBytes bytes
** of good-quality randomness into zOut.  The return value is
** the actual number of bytes of randomness obtained.
** The xSleep() method causes the calling thread to sleep for at
** least the number of microseconds given.  ^The xCurrentTime()
** method returns a Julian Day Number for the current date and time as
** a floating point value.
** ^The xCurrentTimeInt64() method returns, as an integer, the Julian
** Day Number multiplied by 86400000 (the number of milliseconds in 
** a 24-hour day).  
** Day Number multiplied by 86400000 (the number of milliseconds in
** a 24-hour day).
** ^SQLite will use the xCurrentTimeInt64() method to get the current
** date and time if that method is available (if iVersion is 2 or 
** date and time if that method is available (if iVersion is 2 or
** greater and the function pointer is not NULL) and will fall back
** to xCurrentTime() if xCurrentTimeInt64() is unavailable.
**
** ^The xSetSystemCall(), xGetSystemCall(), and xNestSystemCall() interfaces
** are not used by the SQLite core.  These optional interfaces are provided
** by some VFSes to facilitate testing of the VFS code. By overriding 
** by some VFSes to facilitate testing of the VFS code. By overriding
** system calls with functions under its control, a test program can
** simulate faults and error conditions that would otherwise be difficult
** or impossible to induce.  The set of system calls that can be overridden
** varies from one VFS to another, and from one version of the same VFS to the
** next.  Applications that use these interfaces must be prepared for any
** or all of these interfaces to be NULL or for their behavior to change
** from one release to the next.  Applications must not attempt to access
** any of these methods if the iVersion of the VFS is less than 3.
*/
typedef struct sqlite3_vfs sqlite3_vfs;
typedef void (*sqlite3_syscall_ptr)(void);
struct sqlite3_vfs {
  int iVersion;            /* Structure version number (currently 3) */
  int szOsFile;            /* Size of subclassed sqlite3_file */
  int mxPathname;          /* Maximum file pathname length */
  sqlite3_vfs *pNext;      /* Next registered VFS */
  const char *zName;       /* Name of this virtual file system */
  void *pAppData;          /* Pointer to application-specific data */
  int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*,
  int (*xOpen)(sqlite3_vfs*, sqlite3_filename zName, sqlite3_file*,
               int flags, int *pOutFlags);
  int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir);
  int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut);
  int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut);
  void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename);
  void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg);
  void (*(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void);
1400
1401
1402
1403
1404
1405
1406
1407

1408
1409
1410
1411
1412
1413
1414
1537
1538
1539
1540
1541
1542
1543

1544
1545
1546
1547
1548
1549
1550
1551







-
+







** <li>  SQLITE_SHM_LOCK | SQLITE_SHM_SHARED
** <li>  SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE
** <li>  SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED
** <li>  SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE
** </ul>
**
** When unlocking, the same SHARED or EXCLUSIVE flag must be supplied as
** was given on the corresponding lock.  
** was given on the corresponding lock.
**
** The xShmLock method can transition between unlocked and SHARED or
** between unlocked and EXCLUSIVE.  It cannot transition between SHARED
** and EXCLUSIVE.
*/
#define SQLITE_SHM_UNLOCK       1
#define SQLITE_SHM_LOCK         2
1563
1564
1565
1566
1567
1568
1569
1570

1571
1572
1573
1574
1575
1576
1577
1700
1701
1702
1703
1704
1705
1706

1707
1708
1709
1710
1711
1712
1713
1714







-
+







**
** An instance of this object defines the interface between SQLite
** and low-level memory allocation routines.
**
** This object is used in only one place in the SQLite interface.
** A pointer to an instance of this object is the argument to
** [sqlite3_config()] when the configuration option is
** [SQLITE_CONFIG_MALLOC] or [SQLITE_CONFIG_GETMALLOC].  
** [SQLITE_CONFIG_MALLOC] or [SQLITE_CONFIG_GETMALLOC].
** By creating an instance of this object
** and passing it to [sqlite3_config]([SQLITE_CONFIG_MALLOC])
** during configuration, an application can specify an alternative
** memory allocation subsystem for SQLite to use for all of its
** dynamic memory needs.
**
** Note that SQLite comes with several [built-in memory allocators]
1597
1598
1599
1600
1601
1602
1603
1604

1605
1606
1607
1608
1609
1610

1611
1612
1613
1614
1615
1616
1617
1734
1735
1736
1737
1738
1739
1740

1741
1742
1743
1744
1745
1746

1747
1748
1749
1750
1751
1752
1753
1754







-
+





-
+







** allocators round up memory allocations at least to the next multiple
** of 8.  Some allocators round up to a larger multiple or to a power of 2.
** Every memory allocation request coming in through [sqlite3_malloc()]
** or [sqlite3_realloc()] first calls xRoundup.  If xRoundup returns 0, 
** that causes the corresponding memory allocation to fail.
**
** The xInit method initializes the memory allocator.  For example,
** it might allocate any require mutexes or initialize internal data
** it might allocate any required mutexes or initialize internal data
** structures.  The xShutdown method is invoked (indirectly) by
** [sqlite3_shutdown()] and should deallocate any resources acquired
** by xInit.  The pAppData pointer is used as the only parameter to
** xInit and xShutdown.
**
** SQLite holds the [SQLITE_MUTEX_STATIC_MASTER] mutex when it invokes
** SQLite holds the [SQLITE_MUTEX_STATIC_MAIN] mutex when it invokes
** the xInit method, so the xInit method need not be threadsafe.  The
** xShutdown method is only called from [sqlite3_shutdown()] so it does
** not need to be threadsafe either.  For all other methods, SQLite
** holds the [SQLITE_MUTEX_STATIC_MEM] mutex as long as the
** [SQLITE_CONFIG_MEMSTATUS] configuration option is turned on (which
** it is by default) and so the methods are automatically serialized.
** However, if [SQLITE_CONFIG_MEMSTATUS] is disabled, then the other
1686
1687
1688
1689
1690
1691
1692
1693

1694
1695
1696
1697
1698
1699
1700
1823
1824
1825
1826
1827
1828
1829

1830
1831
1832
1833
1834
1835
1836
1837







-
+







** ^If SQLite is compiled with
** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
** it is not possible to set the Serialized [threading mode] and
** [sqlite3_config()] will return [SQLITE_ERROR] if called with the
** SQLITE_CONFIG_SERIALIZED configuration option.</dd>
**
** [[SQLITE_CONFIG_MALLOC]] <dt>SQLITE_CONFIG_MALLOC</dt>
** <dd> ^(The SQLITE_CONFIG_MALLOC option takes a single argument which is 
** <dd> ^(The SQLITE_CONFIG_MALLOC option takes a single argument which is
** a pointer to an instance of the [sqlite3_mem_methods] structure.
** The argument specifies
** alternative low-level memory allocation routines to be used in place of
** the memory allocation routines built into SQLite.)^ ^SQLite makes
** its own private copy of the content of the [sqlite3_mem_methods] structure
** before the [sqlite3_config()] call returns.</dd>
**
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
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







+

















-
-
+
+







**
** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt>
** <dd> ^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int,
** interpreted as a boolean, which enables or disables the collection of
** memory allocation statistics. ^(When memory allocation statistics are
** disabled, the following SQLite interfaces become non-operational:
**   <ul>
**   <li> [sqlite3_hard_heap_limit64()]
**   <li> [sqlite3_memory_used()]
**   <li> [sqlite3_memory_highwater()]
**   <li> [sqlite3_soft_heap_limit64()]
**   <li> [sqlite3_status64()]
**   </ul>)^
** ^Memory allocation statistics are enabled by default unless SQLite is
** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory
** allocation statistics are disabled by default.
** </dd>
**
** [[SQLITE_CONFIG_SCRATCH]] <dt>SQLITE_CONFIG_SCRATCH</dt>
** <dd> The SQLITE_CONFIG_SCRATCH option is no longer used.
** </dd>
**
** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt>
** <dd> ^The SQLITE_CONFIG_PAGECACHE option specifies a memory pool
** that SQLite can use for the database page cache with the default page
** cache implementation.  
** This configuration option is a no-op if an application-define page
** cache implementation.
** This configuration option is a no-op if an application-defined page
** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2].
** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to
** 8-byte aligned memory (pMem), the size of each page cache line (sz),
** and the number of cache lines (N).
** The sz argument should be the size of the largest database page
** (a power of two between 512 and 65536) plus some extra bytes for each
** page header.  ^The number of extra bytes needed by the page header
1764
1765
1766
1767
1768
1769
1770
1771

1772
1773
1774
1775
1776
1777
1778
1902
1903
1904
1905
1906
1907
1908

1909
1910
1911
1912
1913
1914
1915
1916







-
+







** from [sqlite3_malloc()] sufficient for N cache lines if N is positive or
** of -1024*N bytes if N is negative, . ^If additional
** page cache memory is needed beyond what is provided by the initial
** allocation, then SQLite goes to [sqlite3_malloc()] separately for each
** additional cache line. </dd>
**
** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt>
** <dd> ^The SQLITE_CONFIG_HEAP option specifies a static memory buffer 
** <dd> ^The SQLITE_CONFIG_HEAP option specifies a static memory buffer
** that SQLite will use for all of its dynamic memory allocation needs
** beyond those provided for by [SQLITE_CONFIG_PAGECACHE].
** ^The SQLITE_CONFIG_HEAP option is only available if SQLite is compiled
** with either [SQLITE_ENABLE_MEMSYS3] or [SQLITE_ENABLE_MEMSYS5] and returns
** [SQLITE_ERROR] if invoked otherwise.
** ^There are three arguments to SQLITE_CONFIG_HEAP:
** An 8-byte aligned pointer to the memory,
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
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







-
+













-
+







** size of each lookaside buffer slot and the second is the number of
** slots allocated to each database connection.)^  ^(SQLITE_CONFIG_LOOKASIDE
** sets the <i>default</i> lookaside size. The [SQLITE_DBCONFIG_LOOKASIDE]
** option to [sqlite3_db_config()] can be used to change the lookaside
** configuration on individual connections.)^ </dd>
**
** [[SQLITE_CONFIG_PCACHE2]] <dt>SQLITE_CONFIG_PCACHE2</dt>
** <dd> ^(The SQLITE_CONFIG_PCACHE2 option takes a single argument which is 
** <dd> ^(The SQLITE_CONFIG_PCACHE2 option takes a single argument which is
** a pointer to an [sqlite3_pcache_methods2] object.  This object specifies
** the interface to a custom page cache implementation.)^
** ^SQLite makes a copy of the [sqlite3_pcache_methods2] object.</dd>
**
** [[SQLITE_CONFIG_GETPCACHE2]] <dt>SQLITE_CONFIG_GETPCACHE2</dt>
** <dd> ^(The SQLITE_CONFIG_GETPCACHE2 option takes a single argument which
** is a pointer to an [sqlite3_pcache_methods2] object.  SQLite copies of
** the current page cache implementation into that object.)^ </dd>
**
** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt>
** <dd> The SQLITE_CONFIG_LOG option is used to configure the SQLite
** global [error log].
** (^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a
** function with a call signature of void(*)(void*,int,const char*), 
** function with a call signature of void(*)(void*,int,const char*),
** and a pointer to void. ^If the function pointer is not NULL, it is
** invoked by [sqlite3_log()] to process each logging event.  ^If the
** function pointer is NULL, the [sqlite3_log()] interface becomes a no-op.
** ^The void pointer that is the second argument to SQLITE_CONFIG_LOG is
** passed through as the first parameter to the application-defined logger
** function whenever that function is invoked.  ^The second parameter to
** the logger function is a copy of the first parameter to the corresponding
1942
1943
1944
1945
1946
1947
1948
1949

1950
1951
1952
1953
1954
1955
1956
2080
2081
2082
2083
2084
2085
2086

2087
2088
2089
2090
2091
2092
2093
2094







-
+







** is enabled (using the [PRAGMA threads] command) and the amount of content
** to be sorted exceeds the page size times the minimum of the
** [PRAGMA cache_size] setting and this value.
**
** [[SQLITE_CONFIG_STMTJRNL_SPILL]]
** <dt>SQLITE_CONFIG_STMTJRNL_SPILL
** <dd>^The SQLITE_CONFIG_STMTJRNL_SPILL option takes a single parameter which
** becomes the [statement journal] spill-to-disk threshold.  
** becomes the [statement journal] spill-to-disk threshold.
** [Statement journals] are held in memory until their size (in bytes)
** exceeds this threshold, at which point they are written to disk.
** Or if the threshold is -1, statement journals are always held
** exclusively in memory.
** Since many statement journals never become large, setting the spill
** threshold to a value such as 64KiB can greatly reduce the amount of
** I/O required to support statement rollback.
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
1991
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
2017
2018
2019
2020
2021
2022

2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038

2039
2040

2041
2042
2043
2044
2045
2046
2047
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
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







-
+



+
+
+
+
+
+
+
+
+
+
+













-
+
















+

















-
+















-
+

-
+







** Usually, when SQLite uses an external sort to order records according
** to an ORDER BY clause, all fields required by the caller are present in the
** sorted records. However, if SQLite determines based on the declared type
** of a table column that its values are likely to be very large - larger
** than the configured sorter-reference size threshold - then a reference
** is stored in each sorted record and the required column values loaded
** from the database as records are returned in sorted order. The default
** value for this option is to never use this optimization. Specifying a 
** value for this option is to never use this optimization. Specifying a
** negative value for this option restores the default behaviour.
** This option is only available if SQLite is compiled with the
** [SQLITE_ENABLE_SORTER_REFERENCES] compile-time option.
**
** [[SQLITE_CONFIG_MEMDB_MAXSIZE]]
** <dt>SQLITE_CONFIG_MEMDB_MAXSIZE
** <dd>The SQLITE_CONFIG_MEMDB_MAXSIZE option accepts a single parameter
** [sqlite3_int64] parameter which is the default maximum size for an in-memory
** database created using [sqlite3_deserialize()].  This default maximum
** size can be adjusted up or down for individual databases using the
** [SQLITE_FCNTL_SIZE_LIMIT] [sqlite3_file_control|file-control].  If this
** configuration setting is never used, then the default maximum is determined
** by the [SQLITE_MEMDB_DEFAULT_MAXSIZE] compile-time option.  If that
** compile-time option is not set, then the default maximum is 1073741824.
** </dl>
*/
#define SQLITE_CONFIG_SINGLETHREAD  1  /* nil */
#define SQLITE_CONFIG_MULTITHREAD   2  /* nil */
#define SQLITE_CONFIG_SERIALIZED    3  /* nil */
#define SQLITE_CONFIG_MALLOC        4  /* sqlite3_mem_methods* */
#define SQLITE_CONFIG_GETMALLOC     5  /* sqlite3_mem_methods* */
#define SQLITE_CONFIG_SCRATCH       6  /* No longer used */
#define SQLITE_CONFIG_PAGECACHE     7  /* void*, int sz, int N */
#define SQLITE_CONFIG_HEAP          8  /* void*, int nByte, int min */
#define SQLITE_CONFIG_MEMSTATUS     9  /* boolean */
#define SQLITE_CONFIG_MUTEX        10  /* sqlite3_mutex_methods* */
#define SQLITE_CONFIG_GETMUTEX     11  /* sqlite3_mutex_methods* */
/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ 
/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */
#define SQLITE_CONFIG_LOOKASIDE    13  /* int int */
#define SQLITE_CONFIG_PCACHE       14  /* no-op */
#define SQLITE_CONFIG_GETPCACHE    15  /* no-op */
#define SQLITE_CONFIG_LOG          16  /* xFunc, void* */
#define SQLITE_CONFIG_URI          17  /* int */
#define SQLITE_CONFIG_PCACHE2      18  /* sqlite3_pcache_methods2* */
#define SQLITE_CONFIG_GETPCACHE2   19  /* sqlite3_pcache_methods2* */
#define SQLITE_CONFIG_COVERING_INDEX_SCAN 20  /* int */
#define SQLITE_CONFIG_SQLLOG       21  /* xSqllog, void* */
#define SQLITE_CONFIG_MMAP_SIZE    22  /* sqlite3_int64, sqlite3_int64 */
#define SQLITE_CONFIG_WIN32_HEAPSIZE      23  /* int nByte */
#define SQLITE_CONFIG_PCACHE_HDRSZ        24  /* int *psz */
#define SQLITE_CONFIG_PMASZ               25  /* unsigned int szPma */
#define SQLITE_CONFIG_STMTJRNL_SPILL      26  /* int nByte */
#define SQLITE_CONFIG_SMALL_MALLOC        27  /* boolean */
#define SQLITE_CONFIG_SORTERREF_SIZE      28  /* int nByte */
#define SQLITE_CONFIG_MEMDB_MAXSIZE       29  /* sqlite3_int64 */

/*
** CAPI3REF: Database Connection Configuration Options
**
** These constants are the available integer configuration options that
** can be passed as the second argument to the [sqlite3_db_config()] interface.
**
** New configuration options may be added in future releases of SQLite.
** Existing configuration options might be discontinued.  Applications
** should check the return code from [sqlite3_db_config()] to make sure that
** the call worked.  ^The [sqlite3_db_config()] interface will return a
** non-zero [error code] if a discontinued or unsupported configuration option
** is invoked.
**
** <dl>
** [[SQLITE_DBCONFIG_LOOKASIDE]]
** <dt>SQLITE_DBCONFIG_LOOKASIDE</dt>
** <dd> ^This option takes three additional arguments that determine the 
** <dd> ^This option takes three additional arguments that determine the
** [lookaside memory allocator] configuration for the [database connection].
** ^The first argument (the third parameter to [sqlite3_db_config()] is a
** pointer to a memory buffer to use for lookaside memory.
** ^The first argument after the SQLITE_DBCONFIG_LOOKASIDE verb
** may be NULL in which case SQLite will allocate the
** lookaside buffer itself using [sqlite3_malloc()]. ^The second argument is the
** size of each lookaside buffer slot.  ^The third argument is the number of
** slots.  The size of the buffer in the first argument must be greater than
** or equal to the product of the second and third arguments.  The buffer
** must be aligned to an 8-byte boundary.  ^If the second argument to
** SQLITE_DBCONFIG_LOOKASIDE is not a multiple of 8, it is internally
** rounded down to the next smaller multiple of 8.  ^(The lookaside memory
** configuration for a database connection can only be changed when that
** connection is not currently using lookaside memory, or in other words
** when the "current value" returned by
** [sqlite3_db_status](D,[SQLITE_CONFIG_LOOKASIDE],...) is zero.
** [sqlite3_db_status](D,[SQLITE_DBSTATUS_LOOKASIDE_USED],...) is zero.
** Any attempt to change the lookaside memory configuration when lookaside
** memory is in use leaves the configuration unchanged and returns 
** memory is in use leaves the configuration unchanged and returns
** [SQLITE_BUSY].)^</dd>
**
** [[SQLITE_DBCONFIG_ENABLE_FKEY]]
** <dt>SQLITE_DBCONFIG_ENABLE_FKEY</dt>
** <dd> ^This option is used to enable or disable the enforcement of
** [foreign key constraints].  There should be two additional arguments.
** The first argument is an integer which is 0 to disable FK enforcement,
2056
2057
2058
2059
2060
2061
2062
2063

2064























2065
2066
2067
2068


2069
2070
2071
2072
2073
2074
2075
2206
2207
2208
2209
2210
2211
2212

2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239


2240
2241
2242
2243
2244
2245
2246
2247
2248







-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
+
+







** <dd> ^This option is used to enable or disable [CREATE TRIGGER | triggers].
** There should be two additional arguments.
** The first argument is an integer which is 0 to disable triggers,
** positive to enable triggers or negative to leave the setting unchanged.
** The second parameter is a pointer to an integer into which
** is written 0 or 1 to indicate whether triggers are disabled or enabled
** following this call.  The second parameter may be a NULL pointer, in
** which case the trigger setting is not reported back. </dd>
** which case the trigger setting is not reported back.
**
** <p>Originally this option disabled all triggers.  ^(However, since
** SQLite version 3.35.0, TEMP triggers are still allowed even if
** this option is off.  So, in other words, this option now only disables
** triggers in the main database schema or in the schemas of ATTACH-ed
** databases.)^ </dd>
**
** [[SQLITE_DBCONFIG_ENABLE_VIEW]]
** <dt>SQLITE_DBCONFIG_ENABLE_VIEW</dt>
** <dd> ^This option is used to enable or disable [CREATE VIEW | views].
** There should be two additional arguments.
** The first argument is an integer which is 0 to disable views,
** positive to enable views or negative to leave the setting unchanged.
** The second parameter is a pointer to an integer into which
** is written 0 or 1 to indicate whether views are disabled or enabled
** following this call.  The second parameter may be a NULL pointer, in
** which case the view setting is not reported back.
**
** <p>Originally this option disabled all views.  ^(However, since
** SQLite version 3.35.0, TEMP views are still allowed even if
** this option is off.  So, in other words, this option now only disables
** views in the main database schema or in the schemas of ATTACH-ed
** databases.)^ </dd>
**
** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]]
** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
** <dd> ^This option is used to enable or disable the two-argument
** version of the [fts3_tokenizer()] function which is part of the
** <dd> ^This option is used to enable or disable the
** [fts3_tokenizer()] function which is part of the
** [FTS3] full-text search engine extension.
** There should be two additional arguments.
** The first argument is an integer which is 0 to disable fts3_tokenizer() or
** positive to enable fts3_tokenizer() or negative to leave the setting
** unchanged.
** The second parameter is a pointer to an integer into which
** is written 0 or 1 to indicate whether fts3_tokenizer is disabled or enabled
2158
2159
2160
2161
2162
2163
2164
2165
2166






2167
2168
2169
2170
2171
2172
2173
2174
2175


2176
2177
2178
2179

















































































2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192







2193

2194
2195
2196
2197
2198
2199
2200
2331
2332
2333
2334
2335
2336
2337


2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459

2460
2461
2462
2463
2464
2465
2466
2467







-
-
+
+
+
+
+
+









+
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+













+
+
+
+
+
+
+
-
+







**      the database in WAL mode after the reset if it was in WAL mode before
**      the reset.  
** <li> sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0);
** <li> [sqlite3_exec](db, "[VACUUM]", 0, 0, 0);
** <li> sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 0, 0);
** </ol>
** Because resetting a database is destructive and irreversible, the
** process requires the use of this obscure API and multiple steps to help
** ensure that it does not happen by accident.
** process requires the use of this obscure API and multiple steps to
** help ensure that it does not happen by accident. Because this
** feature must be capable of resetting corrupt databases, and
** shutting down virtual tables may require access to that corrupt
** storage, the library must abandon any installed virtual tables
** without calling their xDestroy() methods.
**
** [[SQLITE_DBCONFIG_DEFENSIVE]] <dt>SQLITE_DBCONFIG_DEFENSIVE</dt>
** <dd>The SQLITE_DBCONFIG_DEFENSIVE option activates or deactivates the
** "defensive" flag for a database connection.  When the defensive
** flag is enabled, language features that allow ordinary SQL to 
** deliberately corrupt the database file are disabled.  The disabled
** features include but are not limited to the following:
** <ul>
** <li> The [PRAGMA writable_schema=ON] statement.
** <li> The [PRAGMA journal_mode=OFF] statement.
** <li> The [PRAGMA schema_version=N] statement.
** <li> Writes to the [sqlite_dbpage] virtual table.
** <li> Direct writes to [shadow tables].
** </ul>
** </dd>
**
** [[SQLITE_DBCONFIG_WRITABLE_SCHEMA]] <dt>SQLITE_DBCONFIG_WRITABLE_SCHEMA</dt>
** <dd>The SQLITE_DBCONFIG_WRITABLE_SCHEMA option activates or deactivates the
** "writable_schema" flag. This has the same effect and is logically equivalent
** to setting [PRAGMA writable_schema=ON] or [PRAGMA writable_schema=OFF].
** The first argument to this setting is an integer which is 0 to disable 
** the writable_schema, positive to enable writable_schema, or negative to
** leave the setting unchanged. The second parameter is a pointer to an
** integer into which is written 0 or 1 to indicate whether the writable_schema
** is enabled or disabled following this call.
** </dd>
**
** [[SQLITE_DBCONFIG_LEGACY_ALTER_TABLE]]
** <dt>SQLITE_DBCONFIG_LEGACY_ALTER_TABLE</dt>
** <dd>The SQLITE_DBCONFIG_LEGACY_ALTER_TABLE option activates or deactivates
** the legacy behavior of the [ALTER TABLE RENAME] command such it
** behaves as it did prior to [version 3.24.0] (2018-06-04).  See the
** "Compatibility Notice" on the [ALTER TABLE RENAME documentation] for
** additional information. This feature can also be turned on and off
** using the [PRAGMA legacy_alter_table] statement.
** </dd>
**
** [[SQLITE_DBCONFIG_DQS_DML]]
** <dt>SQLITE_DBCONFIG_DQS_DML</td>
** <dd>The SQLITE_DBCONFIG_DQS_DML option activates or deactivates
** the legacy [double-quoted string literal] misfeature for DML statements
** only, that is DELETE, INSERT, SELECT, and UPDATE statements. The
** default value of this setting is determined by the [-DSQLITE_DQS]
** compile-time option.
** </dd>
**
** [[SQLITE_DBCONFIG_DQS_DDL]]
** <dt>SQLITE_DBCONFIG_DQS_DDL</td>
** <dd>The SQLITE_DBCONFIG_DQS option activates or deactivates
** the legacy [double-quoted string literal] misfeature for DDL statements,
** such as CREATE TABLE and CREATE INDEX. The
** default value of this setting is determined by the [-DSQLITE_DQS]
** compile-time option.
** </dd>
**
** [[SQLITE_DBCONFIG_TRUSTED_SCHEMA]]
** <dt>SQLITE_DBCONFIG_TRUSTED_SCHEMA</td>
** <dd>The SQLITE_DBCONFIG_TRUSTED_SCHEMA option tells SQLite to
** assume that database schemas are untainted by malicious content.
** When the SQLITE_DBCONFIG_TRUSTED_SCHEMA option is disabled, SQLite
** takes additional defensive steps to protect the application from harm
** including:
** <ul>
** <li> Prohibit the use of SQL functions inside triggers, views,
** CHECK constraints, DEFAULT clauses, expression indexes, 
** partial indexes, or generated columns
** unless those functions are tagged with [SQLITE_INNOCUOUS].
** <li> Prohibit the use of virtual tables inside of triggers or views
** unless those virtual tables are tagged with [SQLITE_VTAB_INNOCUOUS].
** </ul>
** This setting defaults to "on" for legacy compatibility, however
** all applications are advised to turn it off if possible. This setting
** can also be controlled using the [PRAGMA trusted_schema] statement.
** </dd>
**
** [[SQLITE_DBCONFIG_LEGACY_FILE_FORMAT]]
** <dt>SQLITE_DBCONFIG_LEGACY_FILE_FORMAT</td>
** <dd>The SQLITE_DBCONFIG_LEGACY_FILE_FORMAT option activates or deactivates
** the legacy file format flag.  When activated, this flag causes all newly
** created database file to have a schema format version number (the 4-byte
** integer found at offset 44 into the database header) of 1.  This in turn
** means that the resulting database file will be readable and writable by
** any SQLite version back to 3.0.0 ([dateof:3.0.0]).  Without this setting,
** newly created databases are generally not understandable by SQLite versions
** prior to 3.3.0 ([dateof:3.3.0]).  As these words are written, there
** is now scarcely any need to generated database files that are compatible 
** all the way back to version 3.0.0, and so this setting is of little
** practical use, but is provided so that SQLite can continue to claim the
** ability to generate new database files that are compatible with  version
** 3.0.0.
** <p>Note that when the SQLITE_DBCONFIG_LEGACY_FILE_FORMAT setting is on,
** the [VACUUM] command will fail with an obscure error when attempting to
** process a table with generated columns and a descending index.  This is
** not considered a bug since SQLite versions 3.3.0 and earlier do not support
** either generated columns or decending indexes.
** </dd>
** </dl>
*/
#define SQLITE_DBCONFIG_MAINDBNAME            1000 /* const char* */
#define SQLITE_DBCONFIG_LOOKASIDE             1001 /* void* int int */
#define SQLITE_DBCONFIG_ENABLE_FKEY           1002 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_TRIGGER        1003 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */
#define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE      1006 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_QPSG           1007 /* int int* */
#define SQLITE_DBCONFIG_TRIGGER_EQP           1008 /* int int* */
#define SQLITE_DBCONFIG_RESET_DATABASE        1009 /* int int* */
#define SQLITE_DBCONFIG_DEFENSIVE             1010 /* int int* */
#define SQLITE_DBCONFIG_WRITABLE_SCHEMA       1011 /* int int* */
#define SQLITE_DBCONFIG_LEGACY_ALTER_TABLE    1012 /* int int* */
#define SQLITE_DBCONFIG_DQS_DML               1013 /* int int* */
#define SQLITE_DBCONFIG_DQS_DDL               1014 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_VIEW           1015 /* int int* */
#define SQLITE_DBCONFIG_LEGACY_FILE_FORMAT    1016 /* int int* */
#define SQLITE_DBCONFIG_TRUSTED_SCHEMA        1017 /* int int* */
#define SQLITE_DBCONFIG_MAX                   1010 /* Largest DBCONFIG */
#define SQLITE_DBCONFIG_MAX                   1017 /* Largest DBCONFIG */

/*
** CAPI3REF: Enable Or Disable Extended Result Codes
** METHOD: sqlite3
**
** ^The sqlite3_extended_result_codes() routine enables or disables the
** [extended result codes] feature of SQLite. ^The extended result
2274
2275
2276
2277
2278
2279
2280
2281

2282
2283




2284

2285
2286
2287
2288
2289
2290
2291
2292
2541
2542
2543
2544
2545
2546
2547

2548
2549
2550
2551
2552
2553
2554

2555

2556
2557
2558
2559
2560
2561
2562







-
+


+
+
+
+
-
+
-







*/
void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64);

/*
** CAPI3REF: Count The Number Of Rows Modified
** METHOD: sqlite3
**
** ^This function returns the number of rows modified, inserted or
** ^These functions return the number of rows modified, inserted or
** deleted by the most recently completed INSERT, UPDATE or DELETE
** statement on the database connection specified by the only parameter.
** The two functions are identical except for the type of the return value
** and that if the number of rows modified by the most recent INSERT, UPDATE 
** or DELETE is greater than the maximum value supported by type "int", then
** the return value of sqlite3_changes() is undefined. ^Executing any other
** ^Executing any other type of SQL statement does not modify the value
** type of SQL statement does not modify the value returned by these functions.
** returned by this function.
**
** ^Only changes made directly by the INSERT, UPDATE or DELETE statement are
** considered - auxiliary changes caused by [CREATE TRIGGER | triggers], 
** [foreign key actions] or [REPLACE] constraint resolution are not counted.
** 
** Changes to a view that are intercepted by 
** [INSTEAD OF trigger | INSTEAD OF triggers] are not counted. ^The value 
2327
2328
2329
2330
2331
2332
2333

2334
2335
2336
2337
2338
2339

2340
2341




2342
2343


2344
2345
2346
2347
2348
2349
2350

2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370

2371
2372
2373
2374
2375
2376
2377
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609

2610
2611
2612
2613
2614
2615
2616


2617
2618
2619
2620
2621
2622
2623
2624

2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653







+





-
+


+
+
+
+
-
-
+
+






-
+




















+







** <li> the [sqlite3_total_changes()] interface
** <li> the [count_changes pragma]
** <li> the [changes() SQL function]
** <li> the [data_version pragma]
** </ul>
*/
int sqlite3_changes(sqlite3*);
sqlite3_int64 sqlite3_changes64(sqlite3*);

/*
** CAPI3REF: Total Number Of Rows Modified
** METHOD: sqlite3
**
** ^This function returns the total number of rows inserted, modified or
** ^These functions return the total number of rows inserted, modified or
** deleted by all [INSERT], [UPDATE] or [DELETE] statements completed
** since the database connection was opened, including those executed as
** part of trigger programs. The two functions are identical except for the 
** type of the return value and that if the number of rows modified by the 
** connection exceeds the maximum value supported by type "int", then
** the return value of sqlite3_total_changes() is undefined. ^Executing 
** part of trigger programs. ^Executing any other type of SQL statement
** does not affect the value returned by sqlite3_total_changes().
** any other type of SQL statement does not affect the value returned by 
** sqlite3_total_changes().
** 
** ^Changes made as part of [foreign key actions] are included in the
** count, but those made as part of REPLACE constraint resolution are
** not. ^Changes to a view that are intercepted by INSTEAD OF triggers 
** are not counted.
**
** This the [sqlite3_total_changes(D)] interface only reports the number
** The [sqlite3_total_changes(D)] interface only reports the number
** of rows that changed due to SQL statement run against database
** connection D.  Any changes by other database connections are ignored.
** To detect changes against a database file from other database
** connections use the [PRAGMA data_version] command or the
** [SQLITE_FCNTL_DATA_VERSION] [file control].
** 
** If a separate thread makes changes on the same database connection
** while [sqlite3_total_changes()] is running then the value
** returned is unpredictable and not meaningful.
**
** See also:
** <ul>
** <li> the [sqlite3_changes()] interface
** <li> the [count_changes pragma]
** <li> the [changes() SQL function]
** <li> the [data_version pragma]
** <li> the [SQLITE_FCNTL_DATA_VERSION] [file control]
** </ul>
*/
int sqlite3_total_changes(sqlite3*);
sqlite3_int64 sqlite3_total_changes64(sqlite3*);

/*
** CAPI3REF: Interrupt A Long-Running Query
** METHOD: sqlite3
**
** ^This function causes any pending database operation to abort and
** return at its earliest opportunity. This routine is typically
2392
2393
2394
2395
2396
2397
2398
2399

2400
2401
2402
2403
2404
2405



2406
2407

2408
2409
2410
2411
2412
2413
2414
2668
2669
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







-
+






+
+
+


+







** ^If the interrupted SQL operation is an INSERT, UPDATE, or DELETE
** that is inside an explicit transaction, then the entire transaction
** will be rolled back automatically.
**
** ^The sqlite3_interrupt(D) call is in effect until all currently running
** SQL statements on [database connection] D complete.  ^Any new SQL statements
** that are started after the sqlite3_interrupt() call and before the 
** running statements reaches zero are interrupted as if they had been
** running statement count reaches zero are interrupted as if they had been
** running prior to the sqlite3_interrupt() call.  ^New SQL statements
** that are started after the running statement count reaches zero are
** not effected by the sqlite3_interrupt().
** ^A call to sqlite3_interrupt(D) that occurs when there are no running
** SQL statements is a no-op and has no effect on SQL statements
** that are started after the sqlite3_interrupt() call returns.
**
** ^The [sqlite3_is_interrupted(D)] interface can be used to determine whether
** or not an interrupt is currently in effect for [database connection] D.
*/
void sqlite3_interrupt(sqlite3*);
int sqlite3_is_interrupted(sqlite3*);

/*
** CAPI3REF: Determine If An SQL Statement Is Complete
**
** These routines are useful during command-line input to determine if the
** currently entered text seems to form a complete SQL statement or
** if additional input is needed before sending the text into
2560
2561
2562
2563
2564
2565
2566
2567

2568
2569

2570
2571
2572
2573
2574
2575
2576
2840
2841
2842
2843
2844
2845
2846

2847
2848

2849
2850
2851
2852
2853
2854
2855
2856







-
+

-
+







**        Name        | Age
**        -----------------------
**        Alice       | 43
**        Bob         | 28
**        Cindy       | 21
** </pre></blockquote>
**
** There are two column (M==2) and three rows (N==3).  Thus the
** There are two columns (M==2) and three rows (N==3).  Thus the
** result table has 8 entries.  Suppose the result table is stored
** in an array names azResult.  Then azResult holds this content:
** in an array named azResult.  Then azResult holds this content:
**
** <blockquote><pre>
**        azResult&#91;0] = "Name";
**        azResult&#91;1] = "Age";
**        azResult&#91;2] = "Alice";
**        azResult&#91;3] = "43";
**        azResult&#91;4] = "Bob";
2655
2656
2657
2658
2659
2660
2661
2662

2663
2664
2665
2666
2667
2668
2669
2935
2936
2937
2938
2939
2940
2941

2942
2943
2944
2945
2946
2947
2948
2949







-
+







char *sqlite3_vsnprintf(int,char*,const char*, va_list);

/*
** CAPI3REF: Memory Allocation Subsystem
**
** The SQLite core uses these three routines for all of its own
** internal memory allocation needs. "Core" in the previous sentence
** does not include operating-system specific VFS implementation.  The
** does not include operating-system specific [VFS] implementation.  The
** Windows VFS uses native malloc() and free() for some operations.
**
** ^The sqlite3_malloc() routine returns a pointer to a block
** of memory at least N bytes in length, where N is the parameter.
** ^If sqlite3_malloc() is unable to obtain sufficient free
** memory, it returns a NULL pointer.  ^If the parameter N to
** sqlite3_malloc() is zero or negative then sqlite3_malloc() returns
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2996
2997
2998
2999
3000
3001
3002













3003
3004
3005
3006
3007
3008
3009







-
-
-
-
-
-
-
-
-
-
-
-
-







**
** ^The memory returned by sqlite3_malloc(), sqlite3_realloc(),
** sqlite3_malloc64(), and sqlite3_realloc64()
** is always aligned to at least an 8 byte boundary, or to a
** 4 byte boundary if the [SQLITE_4_BYTE_ALIGNED_MALLOC] compile-time
** option is used.
**
** In SQLite version 3.5.0 and 3.5.1, it was possible to define
** the SQLITE_OMIT_MEMORY_ALLOCATION which would cause the built-in
** implementation of these routines to be omitted.  That capability
** is no longer provided.  Only built-in memory allocators can be used.
**
** Prior to SQLite version 3.7.10, the Windows OS interface layer called
** the system malloc() and free() directly when converting
** filenames between the UTF-8 encoding used by SQLite
** and whatever filename encoding is used by the particular Windows
** installation.  Memory allocation errors were detected, but
** they were reported back as [SQLITE_CANTOPEN] or
** [SQLITE_IOERR] rather than [SQLITE_NOMEM].
**
** The pointer arguments to [sqlite3_free()] and [sqlite3_realloc()]
** must be either NULL or else pointers obtained from a prior
** invocation of [sqlite3_malloc()] or [sqlite3_realloc()] that have
** not yet been released.
**
** The application must not read or write any part of
** a block of memory after it has been released using
2777
2778
2779
2780
2781
2782
2783
2784

2785
2786
2787
2788
2789
2790
2791
3044
3045
3046
3047
3048
3049
3050

3051
3052
3053
3054
3055
3056
3057
3058







-
+








/*
** CAPI3REF: Pseudo-Random Number Generator
**
** SQLite contains a high-quality pseudo-random number generator (PRNG) used to
** select random [ROWID | ROWIDs] when inserting new records into a table that
** already uses the largest possible [ROWID].  The PRNG is also used for
** the build-in random() and randomblob() SQL functions.  This interface allows
** the built-in random() and randomblob() SQL functions.  This interface allows
** applications to access the same PRNG for other purposes.
**
** ^A call to this routine stores N bytes of randomness into buffer P.
** ^The P parameter can be a NULL pointer.
**
** ^If this routine has not been previously called or if the previous
** call had N less than one or a NULL pointer for P, then the PRNG is
3021
3022
3023
3024
3025
3026
3027
3028

3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039


3040
3041
3042
3043
3044

3045
3046
3047
3048
3049
3050
3051
3288
3289
3290
3291
3292
3293
3294

3295
3296
3297
3298
3299
3300
3301
3302
3303
3304


3305
3306
3307
3308
3309
3310

3311
3312
3313
3314
3315
3316
3317
3318







-
+









-
-
+
+




-
+







** <dl>
** [[SQLITE_TRACE_STMT]] <dt>SQLITE_TRACE_STMT</dt>
** <dd>^An SQLITE_TRACE_STMT callback is invoked when a prepared statement
** first begins running and possibly at other times during the
** execution of the prepared statement, such as at the start of each
** trigger subprogram. ^The P argument is a pointer to the
** [prepared statement]. ^The X argument is a pointer to a string which
** is the unexpanded SQL text of the prepared statement or an SQL comment 
** is the unexpanded SQL text of the prepared statement or an SQL comment
** that indicates the invocation of a trigger.  ^The callback can compute
** the same text that would have been returned by the legacy [sqlite3_trace()]
** interface by using the X argument when X begins with "--" and invoking
** [sqlite3_expanded_sql(P)] otherwise.
**
** [[SQLITE_TRACE_PROFILE]] <dt>SQLITE_TRACE_PROFILE</dt>
** <dd>^An SQLITE_TRACE_PROFILE callback provides approximately the same
** information as is provided by the [sqlite3_profile()] callback.
** ^The P argument is a pointer to the [prepared statement] and the
** X argument points to a 64-bit integer which is the estimated of
** the number of nanosecond that the prepared statement took to run.
** X argument points to a 64-bit integer which is approximately
** the number of nanoseconds that the prepared statement took to run.
** ^The SQLITE_TRACE_PROFILE callback is invoked when the statement finishes.
**
** [[SQLITE_TRACE_ROW]] <dt>SQLITE_TRACE_ROW</dt>
** <dd>^An SQLITE_TRACE_ROW callback is invoked whenever a prepared
** statement generates a single row of result.  
** statement generates a single row of result.
** ^The P argument is a pointer to the [prepared statement] and the
** X argument is unused.
**
** [[SQLITE_TRACE_CLOSE]] <dt>SQLITE_TRACE_CLOSE</dt>
** <dd>^An SQLITE_TRACE_CLOSE callback is invoked when a database
** connection closes.
** ^The P argument is a pointer to the [database connection] object
3095
3096
3097
3098
3099
3100
3101
3102

3103
3104
3105
3106
3107
3108
3109
3362
3363
3364
3365
3366
3367
3368

3369
3370
3371
3372
3373
3374
3375
3376







-
+








/*
** CAPI3REF: Query Progress Callbacks
** METHOD: sqlite3
**
** ^The sqlite3_progress_handler(D,N,X,P) interface causes the callback
** function X to be invoked periodically during long running calls to
** [sqlite3_exec()], [sqlite3_step()] and [sqlite3_get_table()] for
** [sqlite3_step()] and [sqlite3_prepare()] and similar for
** database connection D.  An example use for this
** interface is to keep a GUI updated during a large query.
**
** ^The parameter P is passed through as the only parameter to the 
** callback function X.  ^The parameter N is the approximate number of 
** [virtual machine instructions] that are evaluated between successive
** invocations of the callback X.  ^If N is less than one then the progress
3120
3121
3122
3123
3124
3125
3126







3127
3128
3129
3130
3131
3132
3133
3134

3135
3136
3137
3138
3139
3140
3141
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407

3408
3409
3410
3411
3412
3413
3414
3415







+
+
+
+
+
+
+







-
+







** "Cancel" button on a GUI progress dialog box.
**
** The progress handler callback must not do anything that will modify
** the database connection that invoked the progress handler.
** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their
** database connections for the meaning of "modify" in this paragraph.
**
** The progress handler callback would originally only be invoked from the
** bytecode engine.  It still might be invoked during [sqlite3_prepare()]
** and similar because those routines might force a reparse of the schema
** which involves running the bytecode engine.  However, beginning with
** SQLite version 3.41.0, the progress handler callback might also be
** invoked directly from [sqlite3_prepare()] while analyzing and generating
** code for complex queries.
*/
void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);

/*
** CAPI3REF: Opening A New Database Connection
** CONSTRUCTOR: sqlite3
**
** ^These routines open an SQLite database file as specified by the 
** ^These routines open an SQLite database file as specified by the
** filename argument. ^The filename argument is interpreted as UTF-8 for
** sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte
** order for sqlite3_open16(). ^(A [database connection] handle is usually
** returned in *ppDb, even if an error occurs.  The only exception is that
** if SQLite is unable to allocate memory to hold the [sqlite3] object,
** a NULL will be written into *ppDb instead of a pointer to the [sqlite3]
** object.)^ ^(If the database is opened (and/or created) successfully, then
3151
3152
3153
3154
3155
3156
3157
3158
3159


3160
3161
3162
3163
3164
3165
3166


3167
3168
3169
3170
3171








3172
3173
3174
3175
3176
3177
3178



















































3179
3180

3181
3182
3183
3184





3185
3186
3187

3188
3189
3190

3191
3192


3193
3194
3195
3196
3197
3198
3199
3200
3201
3425
3426
3427
3428
3429
3430
3431


3432
3433


3434
3435
3436


3437
3438
3439
3440



3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507

3508
3509



3510
3511
3512
3513
3514



3515



3516


3517
3518


3519
3520
3521
3522
3523
3524
3525







-
-
+
+
-
-



-
-
+
+


-
-
-
+
+
+
+
+
+
+
+







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+

-
-
-
+
+
+
+
+
-
-
-
+
-
-
-
+
-
-
+
+
-
-







** Whether or not an error occurs when it is opened, resources
** associated with the [database connection] handle should be released by
** passing it to [sqlite3_close()] when it is no longer required.
**
** The sqlite3_open_v2() interface works like sqlite3_open()
** except that it accepts two additional parameters for additional control
** over the new database connection.  ^(The flags parameter to
** sqlite3_open_v2() can take one of
** the following three values, optionally combined with the 
** sqlite3_open_v2() must include, at a minimum, one of the following
** three flag combinations:)^
** [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], [SQLITE_OPEN_SHAREDCACHE],
** [SQLITE_OPEN_PRIVATECACHE], and/or [SQLITE_OPEN_URI] flags:)^
**
** <dl>
** ^(<dt>[SQLITE_OPEN_READONLY]</dt>
** <dd>The database is opened in read-only mode.  If the database does not
** already exist, an error is returned.</dd>)^
** <dd>The database is opened in read-only mode.  If the database does
** not already exist, an error is returned.</dd>)^
**
** ^(<dt>[SQLITE_OPEN_READWRITE]</dt>
** <dd>The database is opened for reading and writing if possible, or reading
** only if the file is write protected by the operating system.  In either
** case the database must already exist, otherwise an error is returned.</dd>)^
** <dd>The database is opened for reading and writing if possible, or
** reading only if the file is write protected by the operating
** system.  In either case the database must already exist, otherwise
** an error is returned.  For historical reasons, if opening in
** read-write mode fails due to OS-level permissions, an attempt is
** made to open it in read-only mode. [sqlite3_db_readonly()] can be
** used to determine whether the database is actually
** read-write.</dd>)^
**
** ^(<dt>[SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]</dt>
** <dd>The database is opened for reading and writing, and is created if
** it does not already exist. This is the behavior that is always used for
** sqlite3_open() and sqlite3_open16().</dd>)^
** </dl>
**
** In addition to the required flags, the following optional flags are
** also supported:
**
** <dl>
** ^(<dt>[SQLITE_OPEN_URI]</dt>
** <dd>The filename can be interpreted as a URI if this flag is set.</dd>)^
**
** ^(<dt>[SQLITE_OPEN_MEMORY]</dt>
** <dd>The database will be opened as an in-memory database.  The database
** is named by the "filename" argument for the purposes of cache-sharing,
** if shared cache mode is enabled, but the "filename" is otherwise ignored.
** </dd>)^
**
** ^(<dt>[SQLITE_OPEN_NOMUTEX]</dt>
** <dd>The new database connection will use the "multi-thread"
** [threading mode].)^  This means that separate threads are allowed
** to use SQLite at the same time, as long as each thread is using
** a different [database connection].
**
** ^(<dt>[SQLITE_OPEN_FULLMUTEX]</dt>
** <dd>The new database connection will use the "serialized"
** [threading mode].)^  This means the multiple threads can safely
** attempt to use the same database connection at the same time.
** (Mutexes will block any actual concurrency, but in this mode
** there is no harm in trying.)
**
** ^(<dt>[SQLITE_OPEN_SHAREDCACHE]</dt>
** <dd>The database is opened [shared cache] enabled, overriding
** the default shared cache setting provided by
** [sqlite3_enable_shared_cache()].)^
** The [use of shared cache mode is discouraged] and hence shared cache
** capabilities may be omitted from many builds of SQLite.  In such cases,
** this option is a no-op.
**
** ^(<dt>[SQLITE_OPEN_PRIVATECACHE]</dt>
** <dd>The database is opened [shared cache] disabled, overriding
** the default shared cache setting provided by
** [sqlite3_enable_shared_cache()].)^
**
** [[OPEN_EXRESCODE]] ^(<dt>[SQLITE_OPEN_EXRESCODE]</dt>
** <dd>The database connection comes up in "extended result code mode".
** In other words, the database behaves has if
** [sqlite3_extended_result_codes(db,1)] where called on the database
** connection as soon as the connection is created. In addition to setting
** the extended result code mode, this flag also causes [sqlite3_open_v2()]
** to return an extended result code.</dd>
**
** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt>
** <dd>The database filename is not allowed to contain a symbolic link</dd>
** </dl>)^
**
** If the 3rd parameter to sqlite3_open_v2() is not one of the
** combinations shown above optionally combined with other
** required combinations shown above optionally combined with other
** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits]
** then the behavior is undefined.
**
** ^If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection
** then the behavior is undefined.  Historic versions of SQLite
** have silently ignored surplus bits in the flags parameter to
** sqlite3_open_v2(), however that behavior might not be carried through
** into future versions of SQLite and so applications should not rely
** upon it.  Note in particular that the SQLITE_OPEN_EXCLUSIVE flag is a no-op
** opens in the multi-thread [threading mode] as long as the single-thread
** mode has not been set at compile-time or start-time.  ^If the
** [SQLITE_OPEN_FULLMUTEX] flag is set then the database connection opens
** for sqlite3_open_v2().  The SQLITE_OPEN_EXCLUSIVE does *not* cause
** in the serialized [threading mode] unless single-thread was
** previously selected at compile-time or start-time.
** ^The [SQLITE_OPEN_SHAREDCACHE] flag causes the database connection to be
** the open to fail if the database already exists.  The SQLITE_OPEN_EXCLUSIVE
** eligible to use [shared cache mode], regardless of whether or not shared
** cache is enabled using [sqlite3_enable_shared_cache()].  ^The
** flag is intended for use by the [sqlite3_vfs|VFS interface] only, and not
** by sqlite3_open_v2().
** [SQLITE_OPEN_PRIVATECACHE] flag causes the database connection to not
** participate in [shared cache mode] even if it is enabled.
**
** ^The fourth parameter to sqlite3_open_v2() is the name of the
** [sqlite3_vfs] object that defines the operating system interface that
** the new database connection should use.  ^If the fourth parameter is
** a NULL pointer then the default [sqlite3_vfs] object is used.
**
** ^If the filename is ":memory:", then a private, temporary in-memory database
3327
3328
3329
3330
3331
3332
3333

3334
3335
3336
3337
3338
3339
3340
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665







+







**          Regardless of whether or not shared-cache mode is enabled by
**          default, use a private cache.
** <tr><td> file:/home/fred/data.db?vfs=unix-dotfile <td>
**          Open file "/home/fred/data.db". Use the special VFS "unix-dotfile"
**          that uses dot-files in place of posix advisory locking.
** <tr><td> file:data.db?mode=readonly <td> 
**          An error. "readonly" is not a valid option for the "mode" parameter.
**          Use "ro" instead:  "file:data.db?mode=ro".
** </table>
**
** ^URI hexadecimal escape sequences (%HH) are supported within the path and
** query components of a URI. A hexadecimal escape sequence consists of a
** percent sign - "%" - followed by exactly two hexadecimal digits 
** specifying an octet value. ^Before the path or query components of a
** URI filename are interpreted, they are encoded using UTF-8 and all 
3368
3369
3370
3371
3372
3373
3374
3375
3376


3377
3378




3379
3380
3381
3382










3383
3384
3385

3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397

3398
3399
3400
3401
3402
3403







3404
3405
3406
3407
3408
3409













3410
3411
3412
3413




3414







































































































3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433

3434
3435
3436
3437
3438
3439

3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452







3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472

3473
3474
3475
3476
3477
3478
3479
3693
3694
3695
3696
3697
3698
3699


3700
3701
3702
3703
3704
3705
3706
3707




3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719

3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731

3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748



3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762



3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
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
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
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944







-
-
+
+


+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+


-
+











-
+






+
+
+
+
+
+
+



-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


















-
+






+













+
+
+
+
+
+
+




















+







  int flags,              /* Flags */
  const char *zVfs        /* Name of VFS module to use */
);

/*
** CAPI3REF: Obtain Values For URI Parameters
**
** These are utility routines, useful to VFS implementations, that check
** to see if a database file was a URI that contained a specific query 
** These are utility routines, useful to [VFS|custom VFS implementations],
** that check if a database file was a URI that contained a specific query 
** parameter, and if so obtains the value of that query parameter.
**
** The first parameter to these interfaces (hereafter referred to
** as F) must be one of:
** <ul>
** <li> A database filename pointer created by the SQLite core and
** If F is the database filename pointer passed into the xOpen() method of 
** a VFS implementation when the flags parameter to xOpen() has one or 
** more of the [SQLITE_OPEN_URI] or [SQLITE_OPEN_MAIN_DB] bits set and
** P is the name of the query parameter, then
** passed into the xOpen() method of a VFS implemention, or
** <li> A filename obtained from [sqlite3_db_filename()], or
** <li> A new filename constructed using [sqlite3_create_filename()].
** </ul>
** If the F parameter is not one of the above, then the behavior is
** undefined and probably undesirable.  Older versions of SQLite were
** more tolerant of invalid F parameters than newer versions.
**
** If F is a suitable filename (as described in the previous paragraph)
** and if P is the name of the query parameter, then
** sqlite3_uri_parameter(F,P) returns the value of the P
** parameter if it exists or a NULL pointer if P does not appear as a 
** query parameter on F.  If P is a query parameter of F
** query parameter on F.  If P is a query parameter of F and it
** has no explicit value, then sqlite3_uri_parameter(F,P) returns
** a pointer to an empty string.
**
** The sqlite3_uri_boolean(F,P,B) routine assumes that P is a boolean
** parameter and returns true (1) or false (0) according to the value
** of P.  The sqlite3_uri_boolean(F,P,B) routine returns true (1) if the
** value of query parameter P is one of "yes", "true", or "on" in any
** case or if the value begins with a non-zero number.  The 
** sqlite3_uri_boolean(F,P,B) routines returns false (0) if the value of
** query parameter P is one of "no", "false", or "off" in any case or
** if the value begins with a numeric zero.  If P is not a query
** parameter on F or if the value of P is does not match any of the
** parameter on F or if the value of P does not match any of the
** above, then sqlite3_uri_boolean(F,P,B) returns (B!=0).
**
** The sqlite3_uri_int64(F,P,D) routine converts the value of P into a
** 64-bit signed integer and returns that integer, or D if P does not
** exist.  If the value of P is something other than an integer, then
** zero is returned.
**
** The sqlite3_uri_key(F,N) returns a pointer to the name (not
** the value) of the N-th query parameter for filename F, or a NULL
** pointer if N is less than zero or greater than the number of query
** parameters minus 1.  The N value is zero-based so N should be 0 to obtain
** the name of the first query parameter, 1 for the second parameter, and
** so forth.
** 
** If F is a NULL pointer, then sqlite3_uri_parameter(F,P) returns NULL and
** sqlite3_uri_boolean(F,P,B) returns B.  If F is not a NULL pointer and
** is not a database file pathname pointer that SQLite passed into the xOpen
** VFS method, then the behavior of this routine is undefined and probably
** undesirable.
** is not a database file pathname pointer that the SQLite core passed
** into the xOpen VFS method, then the behavior of this routine is undefined
** and probably undesirable.
**
** Beginning with SQLite [version 3.31.0] ([dateof:3.31.0]) the input F
** parameter can also be the name of a rollback journal file or WAL file
** in addition to the main database file.  Prior to version 3.31.0, these
** routines would only work if F was the name of the main database file.
** When the F parameter is the name of the rollback journal or WAL file,
** it has access to all the same query parameters as were found on the
** main database file.
**
** See the [URI filename] documentation for additional information.
*/
const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault);
sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64);
const char *sqlite3_uri_parameter(sqlite3_filename z, const char *zParam);
int sqlite3_uri_boolean(sqlite3_filename z, const char *zParam, int bDefault);
sqlite3_int64 sqlite3_uri_int64(sqlite3_filename, const char*, sqlite3_int64);
const char *sqlite3_uri_key(sqlite3_filename z, int N);

/*
** CAPI3REF:  Translate filenames
**
** These routines are available to [VFS|custom VFS implementations] for
** translating filenames between the main database file, the journal file,
** and the WAL file.
**
** If F is the name of an sqlite database file, journal file, or WAL file
** passed by the SQLite core into the VFS, then sqlite3_filename_database(F)
** returns the name of the corresponding database file.
**
** If F is the name of an sqlite database file, journal file, or WAL file
** passed by the SQLite core into the VFS, or if F is a database filename
** obtained from [sqlite3_db_filename()], then sqlite3_filename_journal(F)
** returns the name of the corresponding rollback journal file.
**
** If F is the name of an sqlite database file, journal file, or WAL file
** that was passed by the SQLite core into the VFS, or if F is a database
** filename obtained from [sqlite3_db_filename()], then
** sqlite3_filename_wal(F) returns the name of the corresponding
** WAL file.
**
** In all of the above, if F is not the name of a database, journal or WAL
** filename passed into the VFS from the SQLite core and F is not the
** return value from [sqlite3_db_filename()], then the result is
** undefined and is likely a memory access violation.
*/
const char *sqlite3_filename_database(sqlite3_filename);
const char *sqlite3_filename_journal(sqlite3_filename);
const char *sqlite3_filename_wal(sqlite3_filename);

/*
** CAPI3REF:  Database File Corresponding To A Journal
**
** ^If X is the name of a rollback or WAL-mode journal file that is
** passed into the xOpen method of [sqlite3_vfs], then 
** sqlite3_database_file_object(X) returns a pointer to the [sqlite3_file]
** object that represents the main database file.
**
** This routine is intended for use in custom [VFS] implementations
** only.  It is not a general-purpose interface.
** The argument sqlite3_file_object(X) must be a filename pointer that
** has been passed into [sqlite3_vfs].xOpen method where the 
** flags parameter to xOpen contains one of the bits
** [SQLITE_OPEN_MAIN_JOURNAL] or [SQLITE_OPEN_WAL].  Any other use
** of this routine results in undefined and probably undesirable
** behavior.
*/
sqlite3_file *sqlite3_database_file_object(const char*);

/*
** CAPI3REF: Create and Destroy VFS Filenames
**
** These interfces are provided for use by [VFS shim] implementations and
** are not useful outside of that context.
**
** The sqlite3_create_filename(D,J,W,N,P) allocates memory to hold a version of
** database filename D with corresponding journal file J and WAL file W and
** with N URI parameters key/values pairs in the array P.  The result from
** sqlite3_create_filename(D,J,W,N,P) is a pointer to a database filename that
** is safe to pass to routines like:
** <ul>
** <li> [sqlite3_uri_parameter()],
** <li> [sqlite3_uri_boolean()],
** <li> [sqlite3_uri_int64()],
** <li> [sqlite3_uri_key()], 
** <li> [sqlite3_filename_database()],
** <li> [sqlite3_filename_journal()], or
** <li> [sqlite3_filename_wal()].
** </ul>
** If a memory allocation error occurs, sqlite3_create_filename() might
** return a NULL pointer.  The memory obtained from sqlite3_create_filename(X)
** must be released by a corresponding call to sqlite3_free_filename(Y).
**
** The P parameter in sqlite3_create_filename(D,J,W,N,P) should be an array
** of 2*N pointers to strings.  Each pair of pointers in this array corresponds
** to a key and value for a query parameter.  The P parameter may be a NULL
** pointer if N is zero.  None of the 2*N pointers in the P array may be
** NULL pointers and key pointers should not be empty strings.
** None of the D, J, or W parameters to sqlite3_create_filename(D,J,W,N,P) may
** be NULL pointers, though they can be empty strings.
**
** The sqlite3_free_filename(Y) routine releases a memory allocation
** previously obtained from sqlite3_create_filename().  Invoking
** sqlite3_free_filename(Y) where Y is a NULL pointer is a harmless no-op.
**
** If the Y parameter to sqlite3_free_filename(Y) is anything other
** than a NULL pointer or a pointer previously acquired from
** sqlite3_create_filename(), then bad things such as heap
** corruption or segfaults may occur. The value Y should not be 
** used again after sqlite3_free_filename(Y) has been called.  This means
** that if the [sqlite3_vfs.xOpen()] method of a VFS has been called using Y,
** then the corresponding [sqlite3_module.xClose() method should also be
** invoked prior to calling sqlite3_free_filename(Y).
*/
sqlite3_filename sqlite3_create_filename(
  const char *zDatabase,
  const char *zJournal,
  const char *zWal,
  int nParam,
  const char **azParam
);
void sqlite3_free_filename(sqlite3_filename);

/*
** CAPI3REF: Error Codes And Messages
** METHOD: sqlite3
**
** ^If the most recent sqlite3_* API call associated with 
** [database connection] D failed, then the sqlite3_errcode(D) interface
** returns the numeric [result code] or [extended result code] for that
** API call.
** ^The sqlite3_extended_errcode()
** interface is the same except that it always returns the 
** [extended result code] even when extended result codes are
** disabled.
**
** The values returned by sqlite3_errcode() and/or
** sqlite3_extended_errcode() might change with each API call.
** Except, there are some interfaces that are guaranteed to never
** change the value of the error code.  The error-code preserving
** interfaces are:
** interfaces include the following:
**
** <ul>
** <li> sqlite3_errcode()
** <li> sqlite3_extended_errcode()
** <li> sqlite3_errmsg()
** <li> sqlite3_errmsg16()
** <li> sqlite3_error_offset()
** </ul>
**
** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language
** text that describes the error, as either UTF-8 or UTF-16 respectively.
** ^(Memory to hold the error message string is managed internally.
** The application does not need to worry about freeing the result.
** However, the error string might be overwritten or deallocated by
** subsequent calls to other SQLite interface functions.)^
**
** ^The sqlite3_errstr() interface returns the English-language text
** that describes the [result code], as UTF-8.
** ^(Memory to hold the error message string is managed internally
** and must not be freed by the application)^.
**
** ^If the most recent error references a specific token in the input
** SQL, the sqlite3_error_offset() interface returns the byte offset
** of the start of that token.  ^The byte offset returned by
** sqlite3_error_offset() assumes that the input SQL is UTF8.
** ^If the most recent error does not reference a specific token in the input
** SQL, then the sqlite3_error_offset() function returns -1.
**
** When the serialized [threading mode] is in use, it might be the
** case that a second error occurs on a separate thread in between
** the time of the first error and the call to these interfaces.
** When that happens, the second error will be reported since these
** interfaces always report the most recent result.  To avoid
** this, each thread can obtain exclusive use of the [database connection] D
** by invoking [sqlite3_mutex_enter]([sqlite3_db_mutex](D)) before beginning
** to use D and invoking [sqlite3_mutex_leave]([sqlite3_db_mutex](D)) after
** all calls to the interfaces listed here are completed.
**
** If an interface fails with SQLITE_MISUSE, that means the interface
** was invoked incorrectly by the application.  In that case, the
** error code and message may or may not be set.
*/
int sqlite3_errcode(sqlite3 *db);
int sqlite3_extended_errcode(sqlite3 *db);
const char *sqlite3_errmsg(sqlite3*);
const void *sqlite3_errmsg16(sqlite3*);
const char *sqlite3_errstr(int);
int sqlite3_error_offset(sqlite3 *db);

/*
** CAPI3REF: Prepared Statement Object
** KEYWORDS: {prepared statement} {prepared statements}
**
** An instance of this object represents a single SQL statement that
** has been compiled into binary form and is ready to be evaluated.
3632
3633
3634
3635
3636
3637
3638





3639
3640
3641
3642

3643
3644
3645
3646
3647
3648
3649
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120







+
+
+
+
+




+







** [[SQLITE_PREPARE_NORMALIZE]] <dt>SQLITE_PREPARE_NORMALIZE</dt>
** <dd>The SQLITE_PREPARE_NORMALIZE flag is a no-op. This flag used
** to be required for any prepared statement that wanted to use the
** [sqlite3_normalized_sql()] interface.  However, the
** [sqlite3_normalized_sql()] interface is now available to all
** prepared statements, regardless of whether or not they use this
** flag.
**
** [[SQLITE_PREPARE_NO_VTAB]] <dt>SQLITE_PREPARE_NO_VTAB</dt>
** <dd>The SQLITE_PREPARE_NO_VTAB flag causes the SQL compiler
** to return an error (error code SQLITE_ERROR) if the statement uses
** any virtual tables.
** </dl>
*/
#define SQLITE_PREPARE_PERSISTENT              0x01
#define SQLITE_PREPARE_NORMALIZE               0x02
#define SQLITE_PREPARE_NO_VTAB                 0x04

/*
** CAPI3REF: Compiling An SQL Statement
** KEYWORDS: {SQL statement compiler}
** METHOD: sqlite3
** CONSTRUCTOR: sqlite3_stmt
**
3719
3720
3721
3722
3723
3724
3725
3726

3727
3728
3729

3730
3731

3732
3733
3734

3735
3736
3737
3738
3739
3740
3741
4190
4191
4192
4193
4194
4195
4196

4197
4198
4199

4200
4201

4202
4203
4204

4205
4206
4207
4208
4209
4210
4211
4212







-
+


-
+

-
+


-
+







** [sqlite3_step()] would only return a generic [SQLITE_ERROR] result code
** and the application would have to make a second call to [sqlite3_reset()]
** in order to find the underlying cause of the problem. With the "v2" prepare
** interfaces, the underlying reason for the error is returned immediately.
** </li>
**
** <li>
** ^If the specific value bound to [parameter | host parameter] in the 
** ^If the specific value bound to a [parameter | host parameter] in the 
** WHERE clause might influence the choice of query plan for a statement,
** then the statement will be automatically recompiled, as if there had been 
** a schema change, on the first  [sqlite3_step()] call following any change
** a schema change, on the first [sqlite3_step()] call following any change
** to the [sqlite3_bind_text | bindings] of that [parameter]. 
** ^The specific value of WHERE-clause [parameter] might influence the 
** ^The specific value of a WHERE-clause [parameter] might influence the 
** choice of query plan if the parameter is the left-hand side of a [LIKE]
** or [GLOB] operator or if the parameter is compared to an indexed column
** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled.
** and the [SQLITE_ENABLE_STAT4] compile-time option is enabled.
** </li>
** </ol>
**
** <p>^sqlite3_prepare_v3() differs from sqlite3_prepare_v2() only in having
** the extra prepFlags parameter, which is a bit array consisting of zero or
** more of the [SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_*] flags.  ^The
** sqlite3_prepare_v2() interface works exactly the same as
3817
3818
3819
3820
3821
3822
3823
3824

3825



3826
3827
3828

3829

3830
3831
3832
3833
3834
3835
3836
4288
4289
4290
4291
4292
4293
4294

4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312







-
+

+
+
+



+

+







** bound parameter expansions.  ^The [SQLITE_OMIT_TRACE] compile-time
** option causes sqlite3_expanded_sql() to always return NULL.
**
** ^The strings returned by sqlite3_sql(P) and sqlite3_normalized_sql(P)
** are managed by SQLite and are automatically freed when the prepared
** statement is finalized.
** ^The string returned by sqlite3_expanded_sql(P), on the other hand,
** is obtained from [sqlite3_malloc()] and must be free by the application
** is obtained from [sqlite3_malloc()] and must be freed by the application
** by passing it to [sqlite3_free()].
**
** ^The sqlite3_normalized_sql() interface is only available if
** the [SQLITE_ENABLE_NORMALIZE] compile-time option is defined.
*/
const char *sqlite3_sql(sqlite3_stmt *pStmt);
char *sqlite3_expanded_sql(sqlite3_stmt *pStmt);
#ifdef SQLITE_ENABLE_NORMALIZE
const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt);
#endif

/*
** CAPI3REF: Determine If An SQL Statement Writes The Database
** METHOD: sqlite3_stmt
**
** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if
** and only if the [prepared statement] X makes no direct changes to
3857
3858
3859
3860
3861
3862
3863













3864
3865
3866












3867
3868
3869
3870
3871
3872
3873
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
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374







+
+
+
+
+
+
+
+
+
+
+
+
+



+
+
+
+
+
+
+
+
+
+
+
+







** sqlite3_stmt_readonly() to return true since, while those statements
** change the configuration of a database connection, they do not make 
** changes to the content of the database files on disk.
** ^The sqlite3_stmt_readonly() interface returns true for [BEGIN] since
** [BEGIN] merely sets internal flags, but the [BEGIN|BEGIN IMMEDIATE] and
** [BEGIN|BEGIN EXCLUSIVE] commands do touch the database and so
** sqlite3_stmt_readonly() returns false for those commands.
**
** ^This routine returns false if there is any possibility that the
** statement might change the database file.  ^A false return does
** not guarantee that the statement will change the database file.
** ^For example, an UPDATE statement might have a WHERE clause that
** makes it a no-op, but the sqlite3_stmt_readonly() result would still
** be false.  ^Similarly, a CREATE TABLE IF NOT EXISTS statement is a
** read-only no-op if the table already exists, but 
** sqlite3_stmt_readonly() still returns false for such a statement.
**
** ^If prepared statement X is an [EXPLAIN] or [EXPLAIN QUERY PLAN]
** statement, then sqlite3_stmt_readonly(X) returns the same value as
** if the EXPLAIN or EXPLAIN QUERY PLAN prefix were omitted.
*/
int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);

/*
** CAPI3REF: Query The EXPLAIN Setting For A Prepared Statement
** METHOD: sqlite3_stmt
**
** ^The sqlite3_stmt_isexplain(S) interface returns 1 if the
** prepared statement S is an EXPLAIN statement, or 2 if the
** statement S is an EXPLAIN QUERY PLAN.
** ^The sqlite3_stmt_isexplain(S) interface returns 0 if S is
** an ordinary statement or a NULL pointer.
*/
int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt);

/*
** CAPI3REF: Determine If A Prepared Statement Has Been Reset
** METHOD: sqlite3_stmt
**
** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the
** [prepared statement] S has been stepped at least once using 
** [sqlite3_step(S)] but has neither run to completion (returned
3913
3914
3915
3916
3917
3918
3919


3920
3921
3922
3923
3924
3925
3926
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429







+
+







** sqlite3_value objects and they can be used interchangeably.  However,
** for maximum code portability it is recommended that applications
** still make the distinction between protected and unprotected
** sqlite3_value objects even when not strictly required.
**
** ^The sqlite3_value objects that are passed as parameters into the
** implementation of [application-defined SQL functions] are protected.
** ^The sqlite3_value objects returned by [sqlite3_vtab_rhs_value()]
** are protected.
** ^The sqlite3_value object returned by
** [sqlite3_column_value()] is unprotected.
** Unprotected sqlite3_value objects may only be used as arguments
** to [sqlite3_result_value()], [sqlite3_bind_value()], and
** [sqlite3_value_dup()].
** The [sqlite3_value_blob | sqlite3_value_type()] family of
** interfaces require protected sqlite3_value objects.
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
4000
4001
4002
4003
4004
4005
4006
4007
4008








4009
4010





4011
4012



4013
4014
4015
4016
4017
4018
4019
4475
4476
4477
4478
4479
4480
4481

4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518

4519
4520
4521
4522
4523






4524
4525
4526
4527
4528
4529
4530
4531


4532
4533
4534
4535
4536


4537
4538
4539
4540
4541
4542
4543
4544
4545
4546







-
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+













-
+




-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
-
-
+
+
+







** ^The leftmost SQL parameter has an index of 1.  ^When the same named
** SQL parameter is used more than once, second and subsequent
** occurrences have the same index as the first occurrence.
** ^The index for named parameters can be looked up using the
** [sqlite3_bind_parameter_index()] API if desired.  ^The index
** for "?NNN" parameters is the value of NNN.
** ^The NNN value must be between 1 and the [sqlite3_limit()]
** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 999).
** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 32766).
**
** ^The third argument is the value to bind to the parameter.
** ^If the third parameter to sqlite3_bind_text() or sqlite3_bind_text16()
** or sqlite3_bind_blob() is a NULL pointer then the fourth parameter
** is ignored and the end result is the same as sqlite3_bind_null().
** ^If the third parameter to sqlite3_bind_text() is not NULL, then
** it should be a pointer to well-formed UTF8 text.
** ^If the third parameter to sqlite3_bind_text16() is not NULL, then
** it should be a pointer to well-formed UTF16 text.
** ^If the third parameter to sqlite3_bind_text64() is not NULL, then
** it should be a pointer to a well-formed unicode string that is
** either UTF8 if the sixth parameter is SQLITE_UTF8, or UTF16
** otherwise.
**
** [[byte-order determination rules]] ^The byte-order of
** UTF16 input text is determined by the byte-order mark (BOM, U+FEFF)
** found in first character, which is removed, or in the absence of a BOM
** the byte order is the native byte order of the host
** machine for sqlite3_bind_text16() or the byte order specified in
** the 6th parameter for sqlite3_bind_text64().)^ 
** ^If UTF16 input text contains invalid unicode
** characters, then SQLite might change those invalid characters
** into the unicode replacement character: U+FFFD.
**
** ^(In those routines that have a fourth argument, its value is the
** number of bytes in the parameter.  To be clear: the value is the
** number of <u>bytes</u> in the value, not the number of characters.)^
** ^If the fourth parameter to sqlite3_bind_text() or sqlite3_bind_text16()
** is negative, then the length of the string is
** the number of bytes up to the first zero terminator.
** If the fourth parameter to sqlite3_bind_blob() is negative, then
** the behavior is undefined.
** If a non-negative fourth parameter is provided to sqlite3_bind_text()
** or sqlite3_bind_text16() or sqlite3_bind_text64() then
** that parameter must be the byte offset
** where the NUL terminator would occur assuming the string were NUL
** terminated.  If any NUL characters occur at byte offsets less than 
** 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 bind API fails.
** ^If the fifth argument is
** the special value [SQLITE_STATIC], then SQLite assumes that the
** ^The fifth argument to the BLOB and string binding interfaces controls
** or indicates the lifetime of the object referenced by the third parameter.
** These three options exist:
** ^ (1) A destructor to dispose of the BLOB or string after SQLite has finished
** with it may be passed. ^It is called to dispose of the BLOB or string even
** if the call to the bind API fails, except the destructor is not called if
** the third parameter is a NULL pointer or the fourth parameter is negative.
** ^ (2) The special constant, [SQLITE_STATIC], may be passsed to indicate that
** information is in static, unmanaged space and does not need to be freed.
** ^If the fifth argument has the value [SQLITE_TRANSIENT], then
** 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
4219
4220
4221
4222
4223
4224
4225
4226

4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4746
4747
4748
4749
4750
4751
4752

4753
4754
4755
4756
4757
4758
4759
4760
4761
4762




4763
4764
4765
4766
4767
4768
4769







-
+









-
-
-
-







** ^The first argument to these interfaces is a [prepared statement].
** ^These functions return information about the Nth result column returned by
** the statement, where N is the second function argument.
** ^The left-most column is column 0 for these routines.
**
** ^If the Nth column returned by the statement is an expression or
** subquery and is not a column value, then all of these functions return
** NULL.  ^These routine might also return NULL if a memory allocation error
** NULL.  ^These routines might also return NULL if a memory allocation error
** occurs.  ^Otherwise, they return the name of the attached database, table,
** or column that query result column was extracted from.
**
** ^As with all other SQLite APIs, those whose names end with "16" return
** UTF-16 encoded strings and the other functions return UTF-8.
**
** ^These APIs are only available if the library was compiled with the
** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol.
**
** If two or more threads call one or more of these routines against the same
** prepared statement and column at the same time then the results are
** undefined.
**
** If two or more threads call one or more
** [sqlite3_column_database_name | column metadata interfaces]
** for the same [prepared statement] and result column
** at the same time then the results are undefined.
*/
const char *sqlite3_column_database_name(sqlite3_stmt*,int);
const void *sqlite3_column_database_name16(sqlite3_stmt*,int);
4369
4370
4371
4372
4373
4374
4375
4376

4377
4378
4379
4380
4381
4382
4383
4892
4893
4894
4895
4896
4897
4898

4899
4900
4901
4902
4903
4904
4905
4906







-
+







/*
** CAPI3REF: Number of columns in a result set
** METHOD: sqlite3_stmt
**
** ^The sqlite3_data_count(P) interface returns the number of columns in the
** current row of the result set of [prepared statement] P.
** ^If prepared statement P does not have results ready to return
** (via calls to the [sqlite3_column_int | sqlite3_column_*()] of
** (via calls to the [sqlite3_column_int | sqlite3_column()] family of
** interfaces) then sqlite3_data_count(P) returns 0.
** ^The sqlite3_data_count(P) routine also returns 0 if P is a NULL pointer.
** ^The sqlite3_data_count(P) routine returns 0 if the previous call to
** [sqlite3_step](P) returned [SQLITE_DONE].  ^The sqlite3_data_count(P)
** will return non-zero if previous call to [sqlite3_step](P) returned
** [SQLITE_ROW], except in the case of the [PRAGMA incremental_vacuum]
** where it always returns zero since each step of that multi-step
4513
4514
4515
4516
4517
4518
4519




4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534

4535
4536
4537
4538
4539
4540
4541
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060

5061
5062
5063
5064
5065
5066
5067
5068







+
+
+
+














-
+







** of the string.  ^For clarity: the values returned by
** [sqlite3_column_bytes()] and [sqlite3_column_bytes16()] are the number of
** bytes in the string, not the number of characters.
**
** ^Strings returned by sqlite3_column_text() and sqlite3_column_text16(),
** even empty strings, are always zero-terminated.  ^The return
** value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer.
**
** ^Strings returned by sqlite3_column_text16() always have the endianness
** which is native to the platform, regardless of the text encoding set
** for the database.
**
** <b>Warning:</b> ^The object returned by [sqlite3_column_value()] is an
** [unprotected sqlite3_value] object.  In a multithreaded environment,
** an unprotected sqlite3_value object may only be used safely with
** [sqlite3_bind_value()] and [sqlite3_result_value()].
** If the [unprotected sqlite3_value] object returned by
** [sqlite3_column_value()] is used in any other way, including calls
** to routines like [sqlite3_value_int()], [sqlite3_value_text()],
** or [sqlite3_value_bytes()], the behavior is not threadsafe.
** Hence, the sqlite3_column_value() interface
** is normally only useful within the implementation of 
** [application-defined SQL functions] or [virtual tables], not within
** top-level application code.
**
** The these routines may attempt to convert the datatype of the result.
** These routines may attempt to convert the datatype of the result.
** ^For example, if the internal representation is FLOAT and a text result
** is requested, [sqlite3_snprintf()] is used internally to perform the
** conversion automatically.  ^(The following table details the conversions
** that are applied:
**
** <blockquote>
** <table border="1">
4552
4553
4554
4555
4556
4557
4558
4559

4560
4561
4562
4563
4564
4565
4566
5079
5080
5081
5082
5083
5084
5085

5086
5087
5088
5089
5090
5091
5092
5093







-
+







** <tr><td>  FLOAT   <td>   TEXT    <td> ASCII rendering of the float
** <tr><td>  FLOAT   <td>   BLOB    <td> [CAST] to BLOB
** <tr><td>  TEXT    <td> INTEGER   <td> [CAST] to INTEGER
** <tr><td>  TEXT    <td>  FLOAT    <td> [CAST] to REAL
** <tr><td>  TEXT    <td>   BLOB    <td> No change
** <tr><td>  BLOB    <td> INTEGER   <td> [CAST] to INTEGER
** <tr><td>  BLOB    <td>  FLOAT    <td> [CAST] to REAL
** <tr><td>  BLOB    <td>   TEXT    <td> Add a zero terminator if needed
** <tr><td>  BLOB    <td>   TEXT    <td> [CAST] to TEXT, ensure zero terminator
** </table>
** </blockquote>)^
**
** Note that when type conversions occur, pointers returned by prior
** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or
** sqlite3_column_text16() may be invalidated.
** Type conversions and pointer invalidations might occur
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
5220
5221
5222
5223
5224
5225
5226


5227
5228
5229
5230
5231
5232
5233







-
-







** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S.
*/
int sqlite3_reset(sqlite3_stmt *pStmt);

/*
** CAPI3REF: Create Or Redefine SQL Functions
** KEYWORDS: {function creation routines}
** KEYWORDS: {application-defined SQL function}
** KEYWORDS: {application-defined SQL functions}
** METHOD: sqlite3
**
** ^These functions (collectively known as "function creation routines")
** are used to add SQL functions or aggregates or to redefine the behavior
** of existing SQL functions or aggregates. The only differences between
** the three "sqlite3_create_function*" routines are the text encoding 
** expected for the second parameter (the name of the function being 
4747
4748
4749
4750
4751
4752
4753















4754
4755
4756
4757
4758
4759
4760
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







** ^The fourth parameter may optionally be ORed with [SQLITE_DETERMINISTIC]
** to signal that the function will always return the same result given
** the same inputs within a single SQL statement.  Most SQL functions are
** deterministic.  The built-in [random()] SQL function is an example of a
** function that is not deterministic.  The SQLite query planner is able to
** perform additional optimizations on deterministic functions, so use
** of the [SQLITE_DETERMINISTIC] flag is recommended where possible.
**
** ^The fourth parameter may also optionally include the [SQLITE_DIRECTONLY]
** flag, which if present prevents the function from being invoked from
** within VIEWs, TRIGGERs, CHECK constraints, generated column expressions,
** index expressions, or the WHERE clause of partial indexes.
**
** For best security, the [SQLITE_DIRECTONLY] flag is recommended for
** all application-defined SQL functions that do not need to be
** used inside of triggers, view, CHECK constraints, or other elements of
** the database schema.  This flags is especially recommended for SQL 
** functions that have side effects or reveal internal application state.
** Without this flag, an attacker might be able to modify the schema of
** a database file to include invocations of the function with parameters
** chosen by the attacker, which the application will then execute when
** the database file is opened and read.
**
** ^(The fifth parameter is an arbitrary pointer.  The implementation of the
** function can gain access to this pointer using [sqlite3_user_data()].)^
**
** ^The sixth, seventh and eighth parameters passed to the three
** "sqlite3_create_function*" functions, xFunc, xStep and xFinal, are
** pointers to C-language functions that implement the SQL function or
4864
4865
4866
4867
4868
4869
4870




































































4871
4872




4873
4874
4875
4876
4877
4878
4879
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479

5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+
+
+
+







/*
** CAPI3REF: Function Flags
**
** These constants may be ORed together with the 
** [SQLITE_UTF8 | preferred text encoding] as the fourth argument
** to [sqlite3_create_function()], [sqlite3_create_function16()], or
** [sqlite3_create_function_v2()].
**
** <dl>
** [[SQLITE_DETERMINISTIC]] <dt>SQLITE_DETERMINISTIC</dt><dd>
** The SQLITE_DETERMINISTIC flag means that the new function always gives
** the same output when the input parameters are the same.
** The [abs|abs() function] is deterministic, for example, but
** [randomblob|randomblob()] is not.  Functions must
** be deterministic in order to be used in certain contexts such as
** with the WHERE clause of [partial indexes] or in [generated columns].
** SQLite might also optimize deterministic functions by factoring them
** out of inner loops.
** </dd>
** 
** [[SQLITE_DIRECTONLY]] <dt>SQLITE_DIRECTONLY</dt><dd>
** The SQLITE_DIRECTONLY flag means that the function may only be invoked
** from top-level SQL, and cannot be used in VIEWs or TRIGGERs nor in 
** schema structures such as [CHECK constraints], [DEFAULT clauses],
** [expression indexes], [partial indexes], or [generated columns].
** <p>
** The SQLITE_DIRECTONLY flag is recommended for any 
** [application-defined SQL function]
** that has side-effects or that could potentially leak sensitive information.
** This will prevent attacks in which an application is tricked
** into using a database file that has had its schema surreptiously
** modified to invoke the application-defined function in ways that are
** harmful.
** <p>
** Some people say it is good practice to set SQLITE_DIRECTONLY on all
** [application-defined SQL functions], regardless of whether or not they
** are security sensitive, as doing so prevents those functions from being used
** inside of the database schema, and thus ensures that the database
** can be inspected and modified using generic tools (such as the [CLI])
** that do not have access to the application-defined functions.
** </dd>
**
** [[SQLITE_INNOCUOUS]] <dt>SQLITE_INNOCUOUS</dt><dd>
** The SQLITE_INNOCUOUS flag means that the function is unlikely
** to cause problems even if misused.  An innocuous function should have
** no side effects and should not depend on any values other than its
** input parameters. The [abs|abs() function] is an example of an
** innocuous function.
** The [load_extension() SQL function] is not innocuous because of its
** side effects.
** <p> SQLITE_INNOCUOUS is similar to SQLITE_DETERMINISTIC, but is not
** exactly the same.  The [random|random() function] is an example of a
** function that is innocuous but not deterministic.
** <p>Some heightened security settings
** ([SQLITE_DBCONFIG_TRUSTED_SCHEMA] and [PRAGMA trusted_schema=OFF])
** disable the use of SQL functions inside views and triggers and in
** schema structures such as [CHECK constraints], [DEFAULT clauses],
** [expression indexes], [partial indexes], and [generated columns] unless
** the function is tagged with SQLITE_INNOCUOUS.  Most built-in functions
** are innocuous.  Developers are advised to avoid using the
** SQLITE_INNOCUOUS flag for application-defined functions unless the
** function has been carefully audited and found to be free of potentially
** security-adverse side-effects and information-leaks.
** </dd>
**
** [[SQLITE_SUBTYPE]] <dt>SQLITE_SUBTYPE</dt><dd>
** The SQLITE_SUBTYPE flag indicates to SQLite that a function may call
** [sqlite3_value_subtype()] to inspect the sub-types of its arguments.
** Specifying this flag makes no difference for scalar or aggregate user
** functions. However, if it is not specified for a user-defined window
** function, then any sub-types belonging to arguments passed to the window
** function may be discarded before the window function is called (i.e.
** sqlite3_value_subtype() will always return 0).
** </dd>
** </dl>
*/
#define SQLITE_DETERMINISTIC    0x800
#define SQLITE_DETERMINISTIC    0x000000800
#define SQLITE_DIRECTONLY       0x000080000
#define SQLITE_SUBTYPE          0x000100000
#define SQLITE_INNOCUOUS        0x000200000

/*
** CAPI3REF: Deprecated Functions
** DEPRECATED
**
** These functions are [deprecated].  In order to maintain
** backwards compatibility with older code, these functions continue 
4916
4917
4918
4919
4920
4921
4922


4923
4924
4925
4926
4927
4928
4929
4930


4931
4932
4933
4934
4935
4936
4937
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541


5542
5543
5544
5545
5546
5547
5548
5549
5550







+
+






-
-
+
+







** <tr><td><b>sqlite3_value_type</b><td>&rarr;<td>Default
** datatype of the value
** <tr><td><b>sqlite3_value_numeric_type&nbsp;&nbsp;</b>
** <td>&rarr;&nbsp;&nbsp;<td>Best numeric datatype of the value
** <tr><td><b>sqlite3_value_nochange&nbsp;&nbsp;</b>
** <td>&rarr;&nbsp;&nbsp;<td>True if the column is unchanged in an UPDATE
** against a virtual table.
** <tr><td><b>sqlite3_value_frombind&nbsp;&nbsp;</b>
** <td>&rarr;&nbsp;&nbsp;<td>True if value originated from a [bound parameter]
** </table></blockquote>
**
** <b>Details:</b>
**
** These routines extract type, size, and content information from
** [protected sqlite3_value] objects.  Protected sqlite3_value objects
** are used to pass parameter information into implementation of
** [application-defined SQL functions] and [virtual tables].
** are used to pass parameter information into the functions that
** implement [application-defined SQL functions] and [virtual tables].
**
** These routines work only with [protected sqlite3_value] objects.
** Any attempt to use these routines on an [unprotected sqlite3_value]
** is not threadsafe.
**
** ^These routines work just like the corresponding [column access functions]
** except that these routines take a single [protected sqlite3_value] object
4976
4977
4978
4979
4980
4981
4982





4983
4984
4985
4986
4987
4988
4989
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607







+
+
+
+
+







** the value for that column returned without setting a result (probably
** because it queried [sqlite3_vtab_nochange()] and found that the column
** was unchanging).  ^Within an [xUpdate] method, any value for which
** sqlite3_value_nochange(X) is true will in all other respects appear
** to be a NULL value.  If sqlite3_value_nochange(X) is invoked anywhere other
** than within an [xUpdate] method call for an UPDATE statement, then
** the return value is arbitrary and meaningless.
**
** ^The sqlite3_value_frombind(X) interface returns non-zero if the
** value X originated from one of the [sqlite3_bind_int|sqlite3_bind()]
** interfaces.  ^If X comes from an SQL literal value, or a table column,
** or an expression, then sqlite3_value_frombind(X) returns zero.
**
** Please pay particular attention to the fact that the pointer returned
** from [sqlite3_value_blob()], [sqlite3_value_text()], or
** [sqlite3_value_text16()] can be invalidated by a subsequent call to
** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()],
** or [sqlite3_value_text16()].
**
5022
5023
5024
5025
5026
5027
5028























5029
5030
5031
5032
5033
5034
5035
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







const void *sqlite3_value_text16le(sqlite3_value*);
const void *sqlite3_value_text16be(sqlite3_value*);
int sqlite3_value_bytes(sqlite3_value*);
int sqlite3_value_bytes16(sqlite3_value*);
int sqlite3_value_type(sqlite3_value*);
int sqlite3_value_numeric_type(sqlite3_value*);
int sqlite3_value_nochange(sqlite3_value*);
int sqlite3_value_frombind(sqlite3_value*);

/*
** CAPI3REF: Report the internal text encoding state of an sqlite3_value object
** METHOD: sqlite3_value
**
** ^(The sqlite3_value_encoding(X) interface returns one of [SQLITE_UTF8],
** [SQLITE_UTF16BE], or [SQLITE_UTF16LE] according to the current text encoding
** of the value X, assuming that X has type TEXT.)^  If sqlite3_value_type(X)
** returns something other than SQLITE_TEXT, then the return value from
** sqlite3_value_encoding(X) is meaningless.  ^Calls to
** [sqlite3_value_text(X)], [sqlite3_value_text16(X)], [sqlite3_value_text16be(X)],
** [sqlite3_value_text16le(X)], [sqlite3_value_bytes(X)], or
** [sqlite3_value_bytes16(X)] might change the encoding of the value X and
** thus change the return from subsequent calls to sqlite3_value_encoding(X).
**
** This routine is intended for used by applications that test and validate
** the SQLite implementation.  This routine is inquiring about the opaque
** internal state of an [sqlite3_value] object.  Ordinary applications should
** not need to know what the internal state of an sqlite3_value object is and
** hence should not need to use this interface.
*/
int sqlite3_value_encoding(sqlite3_value*);

/*
** CAPI3REF: Finding The Subtype Of SQL Values
** METHOD: sqlite3_value
**
** The sqlite3_value_subtype(V) function returns the subtype for
** an [application-defined SQL function] argument V.  The subtype
5043
5044
5045
5046
5047
5048
5049
5050


5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068


5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081

5082
5083
5084
5085

5086
5087
5088
5089
5090
5091
5092
5684
5685
5686
5687
5688
5689
5690

5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708


5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722

5723
5724
5725
5726

5727
5728
5729
5730
5731
5732
5733
5734







-
+
+
















-
-
+
+












-
+



-
+







** CAPI3REF: Copy And Free SQL Values
** METHOD: sqlite3_value
**
** ^The sqlite3_value_dup(V) interface makes a copy of the [sqlite3_value]
** object D and returns a pointer to that copy.  ^The [sqlite3_value] returned
** is a [protected sqlite3_value] object even if the input is not.
** ^The sqlite3_value_dup(V) interface returns NULL if V is NULL or if a
** memory allocation fails.
** memory allocation fails. ^If V is a [pointer value], then the result
** of sqlite3_value_dup(V) is a NULL value.
**
** ^The sqlite3_value_free(V) interface frees an [sqlite3_value] object
** previously obtained from [sqlite3_value_dup()].  ^If V is a NULL pointer
** then sqlite3_value_free(V) is a harmless no-op.
*/
sqlite3_value *sqlite3_value_dup(const sqlite3_value*);
void sqlite3_value_free(sqlite3_value*);

/*
** CAPI3REF: Obtain Aggregate Function Context
** METHOD: sqlite3_context
**
** Implementations of aggregate SQL functions use this
** routine to allocate memory for storing their state.
**
** ^The first time the sqlite3_aggregate_context(C,N) routine is called 
** for a particular aggregate function, SQLite
** allocates N of memory, zeroes out that memory, and returns a pointer
** for a particular aggregate function, SQLite allocates
** N bytes of memory, zeroes out that memory, and returns a pointer
** to the new memory. ^On second and subsequent calls to
** sqlite3_aggregate_context() for the same aggregate function instance,
** the same buffer is returned.  Sqlite3_aggregate_context() is normally
** called once for each invocation of the xStep callback and then one
** last time when the xFinal callback is invoked.  ^(When no rows match
** an aggregate query, the xStep() callback of the aggregate function
** implementation is never called and xFinal() is called exactly once.
** In those cases, sqlite3_aggregate_context() might be called for the
** first time from within xFinal().)^
**
** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer 
** when first called if N is less than or equal to zero or if a memory
** allocate error occurs.
** allocation error occurs.
**
** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is
** determined by the N parameter on first successful call.  Changing the
** value of N in subsequent call to sqlite3_aggregate_context() within
** value of N in any subsequent call to sqlite3_aggregate_context() within
** the same aggregate function instance will not resize the memory
** allocation.)^  Within the xFinal callback, it is customary to set
** N=0 in calls to sqlite3_aggregate_context(C,N) so that no 
** pointless memory allocations occur.
**
** ^SQLite automatically frees the memory allocated by 
** sqlite3_aggregate_context() when the aggregate query concludes.
5235
5236
5237
5238
5239
5240
5241
5242
5243



5244
5245
5246
5247
5248
5249
5250
5877
5878
5879
5880
5881
5882
5883


5884
5885
5886
5887
5888
5889
5890
5891
5892
5893







-
-
+
+
+







**
** ^The sqlite3_result_error() and sqlite3_result_error16() functions
** cause the implemented SQL function to throw an exception.
** ^SQLite uses the string pointed to by the
** 2nd parameter of sqlite3_result_error() or sqlite3_result_error16()
** as the text of an error message.  ^SQLite interprets the error
** message string from sqlite3_result_error() as UTF-8. ^SQLite
** interprets the string from sqlite3_result_error16() as UTF-16 in native
** byte order.  ^If the third parameter to sqlite3_result_error()
** interprets the string from sqlite3_result_error16() as UTF-16 using
** the same [byte-order determination rules] as [sqlite3_bind_text16()].
** ^If the third parameter to sqlite3_result_error()
** or sqlite3_result_error16() is negative then SQLite takes as the error
** message all text up through the first zero character.
** ^If the third parameter to sqlite3_result_error() or
** sqlite3_result_error16() is non-negative then SQLite takes that many
** bytes (not characters) from the 2nd parameter as the error message.
** ^The sqlite3_result_error() and sqlite3_result_error16()
** routines make a private copy of the error message text before
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287




5288
5289
5290
5291
5292
5293
5294
5921
5922
5923
5924
5925
5926
5927



5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938







-
-
-
+
+
+
+







** UTF-16 little endian, or UTF-16 big endian, respectively.
** ^The sqlite3_result_text64() interface sets the return value of an
** application-defined function to be a text string in an encoding
** specified by the fifth (and last) parameter, which must be one
** of [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE].
** ^SQLite takes the text result from the application from
** the 2nd parameter of the sqlite3_result_text* interfaces.
** ^If the 3rd parameter to the sqlite3_result_text* interfaces
** is negative, then SQLite takes result text from the 2nd parameter
** through the first zero character.
** ^If the 3rd parameter to any of the sqlite3_result_text* interfaces
** other than sqlite3_result_text64() is negative, then SQLite computes
** the string length itself by searching the 2nd parameter for the first
** zero character.
** ^If the 3rd parameter to the sqlite3_result_text* interfaces
** is non-negative, then as many bytes (not characters) of the text
** pointed to by the 2nd parameter are taken as the application-defined
** function result.  If the 3rd parameter is non-negative, then it
** must be the byte offset into the string where the NUL terminator would
** appear if the string where NUL terminated.  If any NUL characters occur
** in the string at a byte offset that is less than the value of the 3rd
5303
5304
5305
5306
5307
5308
5309



















5310
5311
5312
5313
5314
5315
5316
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







** assumes that the text or BLOB result is in constant space and does not
** copy the content of the parameter nor call a destructor on the content
** when it has finished using that result.
** ^If the 4th parameter to the sqlite3_result_text* interfaces
** or sqlite3_result_blob is the special constant SQLITE_TRANSIENT
** then SQLite makes a copy of the result into space obtained
** from [sqlite3_malloc()] before it returns.
**
** ^For the sqlite3_result_text16(), sqlite3_result_text16le(), and
** sqlite3_result_text16be() routines, and for sqlite3_result_text64()
** when the encoding is not UTF8, if the input UTF16 begins with a
** byte-order mark (BOM, U+FEFF) then the BOM is removed from the
** string and the rest of the string is interpreted according to the
** byte-order specified by the BOM.  ^The byte-order specified by
** the BOM at the beginning of the text overrides the byte-order
** specified by the interface procedure.  ^So, for example, if
** sqlite3_result_text16le() is invoked with text that begins
** with bytes 0xfe, 0xff (a big-endian byte-order mark) then the
** first two bytes of input are skipped and the remaining input
** is interpreted as UTF16BE text.
**
** ^For UTF16 input text to the sqlite3_result_text16(),
** sqlite3_result_text16be(), sqlite3_result_text16le(), and
** sqlite3_result_text64() routines, if the text contains invalid
** UTF16 characters, the invalid characters might be converted
** into the unicode replacement character, U+FFFD.
**
** ^The sqlite3_result_value() interface sets the result of
** the application-defined function to be a copy of the
** [unprotected sqlite3_value] object specified by the 2nd parameter.  ^The
** sqlite3_result_value() interface makes a copy of the [sqlite3_value]
** so that the [sqlite3_value] specified in the parameter may change or
** be deallocated after sqlite3_result_value() returns without harm.
5389
5390
5391
5392
5393
5394
5395
5396

5397
5398
5399
5400
5401
5402
5403
5404
5405

5406
5407
5408
5409

5410
5411
5412
5413
5414
5415
5416



5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433

5434
5435
5436
5437
5438
5439
5440
6052
6053
6054
6055
6056
6057
6058

6059
6060
6061
6062
6063
6064
6065
6066
6067

6068
6069
6070
6071

6072
6073
6074
6075
6076
6077


6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096

6097
6098
6099
6100
6101
6102
6103
6104







-
+








-
+



-
+





-
-
+
+
+
















-
+







** <li> [SQLITE_UTF8],
** <li> [SQLITE_UTF16LE],
** <li> [SQLITE_UTF16BE],
** <li> [SQLITE_UTF16], or
** <li> [SQLITE_UTF16_ALIGNED].
** </ul>)^
** ^The eTextRep argument determines the encoding of strings passed
** to the collating function callback, xCallback.
** to the collating function callback, xCompare.
** ^The [SQLITE_UTF16] and [SQLITE_UTF16_ALIGNED] values for eTextRep
** force strings to be UTF16 with native byte order.
** ^The [SQLITE_UTF16_ALIGNED] value for eTextRep forces strings to begin
** on an even byte address.
**
** ^The fourth argument, pArg, is an application data pointer that is passed
** through as the first argument to the collating function callback.
**
** ^The fifth argument, xCallback, is a pointer to the collating function.
** ^The fifth argument, xCompare, is a pointer to the collating function.
** ^Multiple collating functions can be registered using the same name but
** with different eTextRep parameters and SQLite will use whichever
** function requires the least amount of data transformation.
** ^If the xCallback argument is NULL then the collating function is
** ^If the xCompare argument is NULL then the collating function is
** deleted.  ^When all collating functions having the same name are deleted,
** that collation is no longer usable.
**
** ^The collating function callback is invoked with a copy of the pArg 
** application data pointer and with two strings in the encoding specified
** by the eTextRep argument.  The collating function must return an
** integer that is negative, zero, or positive
** by the eTextRep argument.  The two integer parameters to the collating
** function callback are the length of the two strings, in bytes. The collating
** function must return an integer that is negative, zero, or positive
** if the first string is less than, equal to, or greater than the second,
** respectively.  A collating function must always return the same answer
** given the same inputs.  If two or more collating functions are registered
** to the same collation name (using different eTextRep values) then all
** must give an equivalent answer when invoked with equivalent strings.
** The collating function must obey the following properties for all
** strings A, B, and C:
**
** <ol>
** <li> If A==B then B==A.
** <li> If A==B and B==C then A==C.
** <li> If A&lt;B THEN B&gt;A.
** <li> If A&lt;B and B&lt;C then A&lt;C.
** </ol>
**
** If a collating function fails any of the above constraints and that
** collating function is  registered and used, then the behavior of SQLite
** collating function is registered and used, then the behavior of SQLite
** is undefined.
**
** ^The sqlite3_create_collation_v2() works like sqlite3_create_collation()
** with the addition that the xDestroy callback is invoked on pArg when
** the collating function is deleted.
** ^Collating functions are deleted when they are overridden by later
** calls to the collation creation functions or when the
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
6172
6173
6174
6175
6176
6177
6178













































6179
6180
6181
6182
6183
6184
6185







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







);
int sqlite3_collation_needed16(
  sqlite3*, 
  void*,
  void(*)(void*,sqlite3*,int eTextRep,const void*)
);

#ifdef SQLITE_HAS_CODEC
/*
** Specify the key for an encrypted database.  This routine should be
** called right after sqlite3_open().
**
** The code to implement this API is not available in the public release
** of SQLite.
*/
int sqlite3_key(
  sqlite3 *db,                   /* Database to be rekeyed */
  const void *pKey, int nKey     /* The key */
);
int sqlite3_key_v2(
  sqlite3 *db,                   /* Database to be rekeyed */
  const char *zDbName,           /* Name of the database */
  const void *pKey, int nKey     /* The key */
);

/*
** Change the key on an open database.  If the current database is not
** encrypted, this routine will encrypt it.  If pNew==0 or nNew==0, the
** database is decrypted.
**
** The code to implement this API is not available in the public release
** of SQLite.
*/
int sqlite3_rekey(
  sqlite3 *db,                   /* Database to be rekeyed */
  const void *pKey, int nKey     /* The new key */
);
int sqlite3_rekey_v2(
  sqlite3 *db,                   /* Database to be rekeyed */
  const char *zDbName,           /* Name of the database */
  const void *pKey, int nKey     /* The new key */
);

/*
** Specify the activation key for a SEE database.  Unless 
** activated, none of the SEE routines will work.
*/
void sqlite3_activate_see(
  const char *zPassPhrase        /* Activation phrase */
);
#endif

#ifdef SQLITE_ENABLE_CEROD
/*
** Specify the activation key for a CEROD database.  Unless 
** activated, none of the CEROD routines will work.
*/
void sqlite3_activate_cerod(
  const char *zPassPhrase        /* Activation phrase */
5749
5750
5751
5752
5753
5754
5755






















5756
5757
5758
5759
5760
5761
5762



5763
5764





5765
5766
5767
5768
5769











5770
5771

5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782



















































5783
5784
5785
5786
5787
5788
5789
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400



6401
6402
6403
6404

6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426

6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
6457
6458
6459
6460
6461
6462
6463
6464
6465
6466
6467
6468
6469
6470
6471
6472
6473
6474
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485
6486
6487
6488
6489
6490
6491
6492
6493
6494
6495
6496







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
-
-
+
+
+

-
+
+
+
+
+





+
+
+
+
+
+
+
+
+
+
+

-
+











+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







** returned by sqlite3_db_handle is the same [database connection]
** that was the first argument
** to the [sqlite3_prepare_v2()] call (or its variants) that was used to
** create the statement in the first place.
*/
sqlite3 *sqlite3_db_handle(sqlite3_stmt*);

/*
** CAPI3REF: Return The Schema Name For A Database Connection
** METHOD: sqlite3
**
** ^The sqlite3_db_name(D,N) interface returns a pointer to the schema name
** for the N-th database on database connection D, or a NULL pointer of N is
** out of range.  An N value of 0 means the main database file.  An N of 1 is
** the "temp" schema.  Larger values of N correspond to various ATTACH-ed
** databases.
**
** Space to hold the string that is returned by sqlite3_db_name() is managed
** by SQLite itself.  The string might be deallocated by any operation that
** changes the schema, including [ATTACH] or [DETACH] or calls to
** [sqlite3_serialize()] or [sqlite3_deserialize()], even operations that
** occur on a different thread.  Applications that need to
** remember the string long-term should make their own copy.  Applications that
** are accessing the same database connection simultaneously on multiple
** threads should mutex-protect calls to this API and should make their own
** private copy of the result prior to releasing the mutex.
*/
const char *sqlite3_db_name(sqlite3 *db, int N);

/*
** CAPI3REF: Return The Filename For A Database Connection
** METHOD: sqlite3
**
** ^The sqlite3_db_filename(D,N) interface returns a pointer to a filename
** associated with database N of connection D.  ^The main database file
** has the name "main".  If there is no attached database N on the database
** ^The sqlite3_db_filename(D,N) interface returns a pointer to the filename
** associated with database N of connection D.
** ^If there is no attached database N on the database
** connection D, or if database N is a temporary or in-memory database, then
** a NULL pointer is returned.
** this function will return either a NULL pointer or an empty string.
**
** ^The string value returned by this routine is owned and managed by
** the database connection.  ^The value will be valid until the database N
** is [DETACH]-ed or until the database connection closes.
**
** ^The filename returned by this function is the output of the
** xFullPathname method of the [VFS].  ^In other words, the filename
** will be an absolute pathname, even if the filename used
** to open the database originally was a URI or relative pathname.
**
** If the filename pointer returned by this routine is not NULL, then it
** can be used as the filename input parameter to these routines:
** <ul>
** <li> [sqlite3_uri_parameter()]
** <li> [sqlite3_uri_boolean()]
** <li> [sqlite3_uri_int64()]
** <li> [sqlite3_filename_database()]
** <li> [sqlite3_filename_journal()]
** <li> [sqlite3_filename_wal()]
** </ul>
*/
const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
sqlite3_filename sqlite3_db_filename(sqlite3 *db, const char *zDbName);

/*
** CAPI3REF: Determine if a database is read-only
** METHOD: sqlite3
**
** ^The sqlite3_db_readonly(D,N) interface returns 1 if the database N
** of connection D is read-only, 0 if it is read/write, or -1 if N is not
** the name of a database on connection D.
*/
int sqlite3_db_readonly(sqlite3 *db, const char *zDbName);

/*
** CAPI3REF: Determine the transaction state of a database
** METHOD: sqlite3
**
** ^The sqlite3_txn_state(D,S) interface returns the current
** [transaction state] of schema S in database connection D.  ^If S is NULL,
** then the highest transaction state of any schema on database connection D
** is returned.  Transaction states are (in order of lowest to highest):
** <ol>
** <li value="0"> SQLITE_TXN_NONE
** <li value="1"> SQLITE_TXN_READ
** <li value="2"> SQLITE_TXN_WRITE
** </ol>
** ^If the S argument to sqlite3_txn_state(D,S) is not the name of
** a valid schema, then -1 is returned.
*/
int sqlite3_txn_state(sqlite3*,const char *zSchema);

/*
** CAPI3REF: Allowed return values from [sqlite3_txn_state()]
** KEYWORDS: {transaction state}
**
** These constants define the current transaction state of a database file.
** ^The [sqlite3_txn_state(D,S)] interface returns one of these
** constants in order to describe the transaction state of schema S
** in [database connection] D.
**
** <dl>
** [[SQLITE_TXN_NONE]] <dt>SQLITE_TXN_NONE</dt>
** <dd>The SQLITE_TXN_NONE state means that no transaction is currently
** pending.</dd>
**
** [[SQLITE_TXN_READ]] <dt>SQLITE_TXN_READ</dt>
** <dd>The SQLITE_TXN_READ state means that the database is currently
** in a read transaction.  Content has been read from the database file
** but nothing in the database file has changed.  The transaction state
** will advanced to SQLITE_TXN_WRITE if any changes occur and there are
** no other conflicting concurrent write transactions.  The transaction
** state will revert to SQLITE_TXN_NONE following a [ROLLBACK] or
** [COMMIT].</dd>
**
** [[SQLITE_TXN_WRITE]] <dt>SQLITE_TXN_WRITE</dt>
** <dd>The SQLITE_TXN_WRITE state means that the database is currently
** in a write transaction.  Content has been written to the database file
** but has not yet committed.  The transaction state will change to
** to SQLITE_TXN_NONE at the next [ROLLBACK] or [COMMIT].</dd>
*/
#define SQLITE_TXN_NONE  0
#define SQLITE_TXN_READ  1
#define SQLITE_TXN_WRITE 2

/*
** CAPI3REF: Find the next prepared statement
** METHOD: sqlite3
**
** ^This interface returns a pointer to the next [prepared statement] after
** pStmt associated with the [database connection] pDb.  ^If pStmt is NULL
** then this interface returns a pointer to the first prepared statement
5841
5842
5843
5844
5845
5846
5847


































































5848
5849
5850
5851
5852
5853
5854
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561
6562
6563
6564
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583
6584
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621
6622
6623
6624
6625
6626
6627







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







** ^The rollback callback is not invoked if a transaction is
** automatically rolled back because the database connection is closed.
**
** See also the [sqlite3_update_hook()] interface.
*/
void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*);
void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);

/*
** CAPI3REF: Autovacuum Compaction Amount Callback
** METHOD: sqlite3
**
** ^The sqlite3_autovacuum_pages(D,C,P,X) interface registers a callback 
** function C that is invoked prior to each autovacuum of the database
** file.  ^The callback is passed a copy of the generic data pointer (P),
** the schema-name of the attached database that is being autovacuumed,
** the size of the database file in pages, the number of free pages,
** and the number of bytes per page, respectively.  The callback should
** return the number of free pages that should be removed by the
** autovacuum.  ^If the callback returns zero, then no autovacuum happens.
** ^If the value returned is greater than or equal to the number of
** free pages, then a complete autovacuum happens.
**
** <p>^If there are multiple ATTACH-ed database files that are being
** modified as part of a transaction commit, then the autovacuum pages
** callback is invoked separately for each file.
**
** <p><b>The callback is not reentrant.</b> The callback function should
** not attempt to invoke any other SQLite interface.  If it does, bad
** things may happen, including segmentation faults and corrupt database
** files.  The callback function should be a simple function that
** does some arithmetic on its input parameters and returns a result.
**
** ^The X parameter to sqlite3_autovacuum_pages(D,C,P,X) is an optional
** destructor for the P parameter.  ^If X is not NULL, then X(P) is
** invoked whenever the database connection closes or when the callback
** is overwritten by another invocation of sqlite3_autovacuum_pages().
**
** <p>^There is only one autovacuum pages callback per database connection.
** ^Each call to the sqlite3_autovacuum_pages() interface overrides all
** previous invocations for that database connection.  ^If the callback
** argument (C) to sqlite3_autovacuum_pages(D,C,P,X) is a NULL pointer,
** then the autovacuum steps callback is cancelled.  The return value
** from sqlite3_autovacuum_pages() is normally SQLITE_OK, but might
** be some other error code if something goes wrong.  The current
** implementation will only return SQLITE_OK or SQLITE_MISUSE, but other
** return codes might be added in future releases.
**
** <p>If no autovacuum pages callback is specified (the usual case) or
** a NULL pointer is provided for the callback,
** then the default behavior is to vacuum all free pages.  So, in other
** words, the default behavior is the same as if the callback function
** were something like this:
**
** <blockquote><pre>
** &nbsp;   unsigned int demonstration_autovac_pages_callback(
** &nbsp;     void *pClientData,
** &nbsp;     const char *zSchema,
** &nbsp;     unsigned int nDbPage,
** &nbsp;     unsigned int nFreePage,
** &nbsp;     unsigned int nBytePerPage
** &nbsp;   ){
** &nbsp;     return nFreePage;
** &nbsp;   }
** </pre></blockquote>
*/
int sqlite3_autovacuum_pages(
  sqlite3 *db,
  unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int),
  void*,
  void(*)(void*)
);


/*
** CAPI3REF: Data Change Notification Callbacks
** METHOD: sqlite3
**
** ^The sqlite3_update_hook() interface registers a callback function
** with the [database connection] identified by the first argument
5866
5867
5868
5869
5870
5871
5872
5873

5874
5875
5876
5877
5878
5879
5880
6639
6640
6641
6642
6643
6644
6645

6646
6647
6648
6649
6650
6651
6652
6653







-
+







** to be invoked.
** ^The third and fourth arguments to the callback contain pointers to the
** database and table name containing the affected row.
** ^The final callback parameter is the [rowid] of the row.
** ^In the case of an update, this is the [rowid] after the update takes place.
**
** ^(The update hook is not invoked when internal system tables are
** modified (i.e. sqlite_master and sqlite_sequence).)^
** modified (i.e. sqlite_sequence).)^
** ^The update hook is not invoked when [WITHOUT ROWID] tables are modified.
**
** ^In the current implementation, the update hook
** is not invoked when conflicting rows are deleted because of an
** [ON CONFLICT | ON CONFLICT REPLACE] clause.  ^Nor is the update hook
** invoked when rows are deleted using the [truncate optimization].
** The exceptions defined in this paragraph might change in a future
5904
5905
5906
5907
5908
5909
5910





5911
5912
5913
5914
5915
5916
5917
5918
5919

5920
5921
5922
5923
5924
5925
5926
5927







5928
5929
5930
5931
5932
5933
5934
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
6710
6711
6712
6713
6714
6715
6716







+
+
+
+
+








-
+





-
-
-
+
+
+
+
+
+
+







/*
** CAPI3REF: Enable Or Disable Shared Pager Cache
**
** ^(This routine enables or disables the sharing of the database cache
** and schema data structures between [database connection | connections]
** to the same database. Sharing is enabled if the argument is true
** and disabled if the argument is false.)^
**
** This interface is omitted if SQLite is compiled with
** [-DSQLITE_OMIT_SHARED_CACHE].  The [-DSQLITE_OMIT_SHARED_CACHE]
** compile-time option is recommended because the
** [use of shared cache mode is discouraged].
**
** ^Cache sharing is enabled and disabled for an entire process.
** This is a change as of SQLite [version 3.5.0] ([dateof:3.5.0]). 
** In prior versions of SQLite,
** sharing was enabled or disabled for each thread separately.
**
** ^(The cache sharing mode set by this interface effects all subsequent
** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()].
** Existing database connections continue use the sharing mode
** Existing database connections continue to use the sharing mode
** that was in effect at the time they were opened.)^
**
** ^(This routine returns [SQLITE_OK] if shared cache was enabled or disabled
** successfully.  An [error code] is returned otherwise.)^
**
** ^Shared cache is disabled by default. But this might change in
** future releases of SQLite.  Applications that care about shared
** cache setting should set it explicitly.
** ^Shared cache is disabled by default. It is recommended that it stay
** that way.  In other words, do not use this routine.  This interface
** continues to be provided for historical compatibility, but its use is
** discouraged.  Any use of shared cache is discouraged.  If shared cache
** must be used, it is recommended that shared cache only be enabled for
** individual database connections using the [sqlite3_open_v2()] interface
** with the [SQLITE_OPEN_SHAREDCACHE] flag.
**
** Note: This method is disabled on MacOS X 10.7 and iOS version 5.0
** and will always return SQLITE_MISUSE. On those systems, 
** shared cache mode should be enabled per-database connection via 
** [sqlite3_open_v2()] with [SQLITE_OPEN_SHAREDCACHE].
**
** This interface is threadsafe on processors where writing a
5966
5967
5968
5969
5970
5971
5972



5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983







5984
5985


5986
5987
5988
5989



5990





5991







5992



5993

5994
5995
5996
5997

5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019

6020
6021
6022

6023
6024
6025
6026
6027
6028
6029
6748
6749
6750
6751
6752
6753
6754
6755
6756
6757
6758
6759
6760
6761
6762
6763
6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774
6775


6776
6777
6778



6779
6780
6781
6782
6783
6784
6785
6786
6787

6788
6789
6790
6791
6792
6793
6794
6795
6796
6797
6798

6799
6800
6801
6802

6803
6804
6805
6806
6807
6808
6809
6810
6811
6812
6813












6814
6815
6816
6817
6818
6819
6820
6821
6822
6823
6824
6825







+
+
+











+
+
+
+
+
+
+
-
-
+
+

-
-
-
+
+
+

+
+
+
+
+
-
+
+
+
+
+
+
+

+
+
+
-
+



-
+










-
-
-
-
-
-
-
-
-
-
-
-
+



+







**
** See also: [sqlite3_release_memory()]
*/
int sqlite3_db_release_memory(sqlite3*);

/*
** CAPI3REF: Impose A Limit On Heap Size
**
** These interfaces impose limits on the amount of heap memory that will be
** by all database connections within a single process.
**
** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the
** soft limit on the amount of heap memory that may be allocated by SQLite.
** ^SQLite strives to keep heap memory utilization below the soft heap
** limit by reducing the number of pages held in the page cache
** as heap memory usages approaches the limit.
** ^The soft heap limit is "soft" because even though SQLite strives to stay
** below the limit, it will exceed the limit rather than generate
** an [SQLITE_NOMEM] error.  In other words, the soft heap limit 
** is advisory only.
**
** ^The sqlite3_hard_heap_limit64(N) interface sets a hard upper bound of
** N bytes on the amount of memory that will be allocated.  ^The
** sqlite3_hard_heap_limit64(N) interface is similar to
** sqlite3_soft_heap_limit64(N) except that memory allocations will fail
** when the hard heap limit is reached.
**
** ^The return value from both sqlite3_soft_heap_limit64() and
** ^The return value from sqlite3_soft_heap_limit64() is the size of
** the soft heap limit prior to the call, or negative in the case of an
** sqlite3_hard_heap_limit64() is the size of
** the heap limit prior to the call, or negative in the case of an
** error.  ^If the argument N is negative
** then no change is made to the soft heap limit.  Hence, the current
** size of the soft heap limit can be determined by invoking
** sqlite3_soft_heap_limit64() with a negative argument.
** then no change is made to the heap limit.  Hence, the current
** size of heap limits can be determined by invoking
** sqlite3_soft_heap_limit64(-1) or sqlite3_hard_heap_limit(-1).
**
** ^Setting the heap limits to zero disables the heap limiter mechanism.
**
** ^The soft heap limit may not be greater than the hard heap limit.
** ^If the hard heap limit is enabled and if sqlite3_soft_heap_limit(N)
** is invoked with a value of N that is greater than the hard heap limit,
** ^If the argument N is zero then the soft heap limit is disabled.
** the soft heap limit is set to the value of the hard heap limit.
** ^The soft heap limit is automatically enabled whenever the hard heap
** limit is enabled. ^When sqlite3_hard_heap_limit64(N) is invoked and
** the soft heap limit is outside the range of 1..N, then the soft heap
** limit is set to N.  ^Invoking sqlite3_soft_heap_limit64(0) when the
** hard heap limit is enabled makes the soft heap limit equal to the
** hard heap limit.
**
** The memory allocation limits can also be adjusted using
** [PRAGMA soft_heap_limit] and [PRAGMA hard_heap_limit].
**
** ^(The soft heap limit is not enforced in the current implementation
** ^(The heap limits are not enforced in the current implementation
** if one or more of following conditions are true:
**
** <ul>
** <li> The soft heap limit is set to zero.
** <li> The limit value is set to zero.
** <li> Memory accounting is disabled using a combination of the
**      [sqlite3_config]([SQLITE_CONFIG_MEMSTATUS],...) start-time option and
**      the [SQLITE_DEFAULT_MEMSTATUS] compile-time option.
** <li> An alternative page cache implementation is specified using
**      [sqlite3_config]([SQLITE_CONFIG_PCACHE2],...).
** <li> The page cache allocates from its own memory pool supplied
**      by [sqlite3_config]([SQLITE_CONFIG_PAGECACHE],...) rather than
**      from the heap.
** </ul>)^
**
** Beginning with SQLite [version 3.7.3] ([dateof:3.7.3]), 
** the soft heap limit is enforced
** regardless of whether or not the [SQLITE_ENABLE_MEMORY_MANAGEMENT]
** compile-time option is invoked.  With [SQLITE_ENABLE_MEMORY_MANAGEMENT],
** the soft heap limit is enforced on every memory allocation.  Without
** [SQLITE_ENABLE_MEMORY_MANAGEMENT], the soft heap limit is only enforced
** when memory is allocated by the page cache.  Testing suggests that because
** the page cache is the predominate memory user in SQLite, most
** applications will achieve adequate soft heap limit enforcement without
** the use of [SQLITE_ENABLE_MEMORY_MANAGEMENT].
**
** The circumstances under which SQLite will enforce the soft heap limit may
** The circumstances under which SQLite will enforce the heap limits may
** changes in future releases of SQLite.
*/
sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N);
sqlite3_int64 sqlite3_hard_heap_limit64(sqlite3_int64 N);

/*
** CAPI3REF: Deprecated Soft Heap Limit Interface
** DEPRECATED
**
** This is a deprecated version of the [sqlite3_soft_heap_limit64()]
** interface.  This routine is provided for historical compatibility
6039
6040
6041
6042
6043
6044
6045
6046

6047
6048
6049
6050
6051
6052
6053
6835
6836
6837
6838
6839
6840
6841

6842
6843
6844
6845
6846
6847
6848
6849







-
+







**
** ^(The sqlite3_table_column_metadata(X,D,T,C,....) routine returns
** information about column C of table T in database D
** on [database connection] X.)^  ^The sqlite3_table_column_metadata()
** interface returns SQLITE_OK and fills in the non-NULL pointers in
** the final five arguments with appropriate values if the specified
** column exists.  ^The sqlite3_table_column_metadata() interface returns
** SQLITE_ERROR and if the specified column does not exist.
** SQLITE_ERROR if the specified column does not exist.
** ^If the column-name parameter to sqlite3_table_column_metadata() is a
** NULL pointer, then this routine simply checks for the existence of the
** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it
** does not.  If the table name parameter T in a call to
** sqlite3_table_column_metadata(X,D,T,C,...) is NULL then the result is
** undefined behavior.
**
6181
6182
6183
6184
6185
6186
6187
6188

6189
6190
6191
6192
6193
6194
6195
6977
6978
6979
6980
6981
6982
6983

6984
6985
6986
6987
6988
6989
6990
6991







-
+







**
** ^This interface enables or disables both the C-API
** [sqlite3_load_extension()] and the SQL function [load_extension()].
** ^(Use [sqlite3_db_config](db,[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION],..)
** to enable or disable only the C-API.)^
**
** <b>Security warning:</b> It is recommended that extension loading
** be disabled using the [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method
** be enabled using the [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method
** rather than this interface, so the [load_extension()] SQL function
** remains disabled. This will prevent SQL injections from giving attackers
** access to extension loading capabilities.
*/
int sqlite3_enable_load_extension(sqlite3 *db, int onoff);

/*
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275

6276
6277
6278
6279
6280
6281
6282
7042
7043
7044
7045
7046
7047
7048









7049
7050
7051
7052
7053
7054
7055
7056
7057
7058
7059
7060
7061

7062
7063
7064
7065
7066
7067
7068
7069







-
-
-
-
-
-
-
-
-













-
+







** CAPI3REF: Reset Automatic Extension Loading
**
** ^This interface disables all automatic extensions previously
** registered using [sqlite3_auto_extension()].
*/
void sqlite3_reset_auto_extension(void);

/*
** The interface to the virtual-table mechanism is currently considered
** to be experimental.  The interface might change in incompatible ways.
** If this is a problem for you, do not use the interface at this time.
**
** When the virtual-table mechanism stabilizes, we will declare the
** interface fixed, support it indefinitely, and remove this comment.
*/

/*
** Structures used by the virtual table interface
*/
typedef struct sqlite3_vtab sqlite3_vtab;
typedef struct sqlite3_index_info sqlite3_index_info;
typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor;
typedef struct sqlite3_module sqlite3_module;

/*
** CAPI3REF: Virtual Table Object
** KEYWORDS: sqlite3_module {virtual table module}
**
** This structure, sometimes called a "virtual table module", 
** defines the implementation of a [virtual tables].  
** defines the implementation of a [virtual table].  
** This structure consists mostly of methods for the module.
**
** ^A virtual table module is created by filling in a persistent
** instance of this structure and passing a pointer to that instance
** to [sqlite3_create_module()] or [sqlite3_create_module_v2()].
** ^The registration remains valid until it is replaced by a different
** module or until the [database connection] closes.  The content
6365
6366
6367
6368
6369
6370
6371
6372







6373
6374

6375
6376
6377


6378
6379
6380
6381
6382
6383
6384
7152
7153
7154
7155
7156
7157
7158

7159
7160
7161
7162
7163
7164
7165
7166

7167
7168


7169
7170
7171
7172
7173
7174
7175
7176
7177







-
+
+
+
+
+
+
+

-
+

-
-
+
+







** non-zero.
**
** The [xBestIndex] method must fill aConstraintUsage[] with information
** about what parameters to pass to xFilter.  ^If argvIndex>0 then
** the right-hand side of the corresponding aConstraint[] is evaluated
** and becomes the argvIndex-th entry in argv.  ^(If aConstraintUsage[].omit
** is true, then the constraint is assumed to be fully handled by the
** virtual table and is not checked again by SQLite.)^
** virtual table and might not be checked again by the byte code.)^ ^(The
** aConstraintUsage[].omit flag is an optimization hint. When the omit flag
** is left in its default setting of false, the constraint will always be
** checked separately in byte code.  If the omit flag is change to true, then
** the constraint may or may not be checked in byte code.  In other words,
** when the omit flag is true there is no guarantee that the constraint will
** not be checked again using byte code.)^
**
** ^The idxNum and idxPtr values are recorded and passed into the
** ^The idxNum and idxStr values are recorded and passed into the
** [xFilter] method.
** ^[sqlite3_free()] is used to free idxPtr if and only if
** needToFreeIdxPtr is true.
** ^[sqlite3_free()] is used to free idxStr if and only if
** needToFreeIdxStr is true.
**
** ^The orderByConsumed means that output from [xFilter]/[xNext] will occur in
** the correct order to satisfy the ORDER BY clause so that no separate
** sorting step is required.
**
** ^The estimatedCost value is an estimate of the cost of a particular
** strategy. A cost of N indicates that the cost of the strategy is similar
6405
6406
6407
6408
6409
6410
6411
6412

6413
6414
6415
6416
6417
6418
6419
7198
7199
7200
7201
7202
7203
7204

7205
7206
7207
7208
7209
7210
7211
7212







-
+







** the xUpdate method are automatically rolled back by SQLite.
**
** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info
** structure for SQLite [version 3.8.2] ([dateof:3.8.2]). 
** If a virtual table extension is
** used with an SQLite version earlier than 3.8.2, the results of attempting 
** to read or write the estimatedRows field are undefined (but are likely 
** to included crashing the application). The estimatedRows field should
** to include crashing the application). The estimatedRows field should
** therefore only be used if [sqlite3_libversion_number()] returns a
** value greater than or equal to 3008002. Similarly, the idxFlags field
** was added for [version 3.9.0] ([dateof:3.9.0]). 
** It may therefore only be used if
** sqlite3_libversion_number() returns a value greater than or equal to
** 3009000.
*/
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
7250
7251
7252
7253
7254
7255
7256

7257
7258

7259
7260
7261
7262
7263
7264
7265
7266
7267
7268
7269
7270
7271
7272
7273
7274
7275
7276
7277
7278
7279
7280
7281
7282
7283
7284
7285
7286
7287
7288
7289
7290
7291















7292
7293
7294
7295
7296
7297
7298
7299
7300
7301
7302
7303
7304
7305
7306
7307
7308
7309
7310
7311
7312
7313
7314
7315







-
+

-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







** these bits.
*/
#define SQLITE_INDEX_SCAN_UNIQUE      1     /* Scan visits at most 1 row */

/*
** CAPI3REF: Virtual Table Constraint Operator Codes
**
** These macros defined the allowed values for the
** These macros define the allowed values for the
** [sqlite3_index_info].aConstraint[].op field.  Each value represents
** an operator that is part of a constraint term in the wHERE clause of
** an operator that is part of a constraint term in the WHERE clause of
** a query that uses a [virtual table].
**
** ^The left-hand operand of the operator is given by the corresponding
** aConstraint[].iColumn field.  ^An iColumn of -1 indicates the left-hand
** operand is the rowid.
** The SQLITE_INDEX_CONSTRAINT_LIMIT and SQLITE_INDEX_CONSTRAINT_OFFSET
** operators have no left-hand operand, and so for those operators the
** corresponding aConstraint[].iColumn is meaningless and should not be
** used.
**
** All operator values from SQLITE_INDEX_CONSTRAINT_FUNCTION through
** value 255 are reserved to represent functions that are overloaded
** by the [xFindFunction|xFindFunction method] of the virtual table
** implementation.
**
** The right-hand operands for each constraint might be accessible using
** the [sqlite3_vtab_rhs_value()] interface.  Usually the right-hand
** operand is only available if it appears as a single constant literal
** in the input SQL.  If the right-hand operand is another column or an
** expression (even a constant expression) or a parameter, then the
** sqlite3_vtab_rhs_value() probably will not be able to extract it.
** ^The SQLITE_INDEX_CONSTRAINT_ISNULL and
** SQLITE_INDEX_CONSTRAINT_ISNOTNULL operators have no right-hand operand
** and hence calls to sqlite3_vtab_rhs_value() for those operators will
** always return SQLITE_NOTFOUND.
**
** The collating sequence to be used for comparison can be found using
** the [sqlite3_vtab_collation()] interface.  For most real-world virtual
** tables, the collating sequence of constraints does not matter (for example
** because the constraints are numeric) and so the sqlite3_vtab_collation()
** interface is not commonly needed.
*/
#define SQLITE_INDEX_CONSTRAINT_EQ         2
#define SQLITE_INDEX_CONSTRAINT_GT         4
#define SQLITE_INDEX_CONSTRAINT_LE         8
#define SQLITE_INDEX_CONSTRAINT_LT        16
#define SQLITE_INDEX_CONSTRAINT_GE        32
#define SQLITE_INDEX_CONSTRAINT_MATCH     64
#define SQLITE_INDEX_CONSTRAINT_LIKE      65
#define SQLITE_INDEX_CONSTRAINT_GLOB      66
#define SQLITE_INDEX_CONSTRAINT_REGEXP    67
#define SQLITE_INDEX_CONSTRAINT_NE        68
#define SQLITE_INDEX_CONSTRAINT_ISNOT     69
#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70
#define SQLITE_INDEX_CONSTRAINT_ISNULL    71
#define SQLITE_INDEX_CONSTRAINT_IS        72
#define SQLITE_INDEX_CONSTRAINT_FUNCTION 150
#define SQLITE_INDEX_CONSTRAINT_EQ          2
#define SQLITE_INDEX_CONSTRAINT_GT          4
#define SQLITE_INDEX_CONSTRAINT_LE          8
#define SQLITE_INDEX_CONSTRAINT_LT         16
#define SQLITE_INDEX_CONSTRAINT_GE         32
#define SQLITE_INDEX_CONSTRAINT_MATCH      64
#define SQLITE_INDEX_CONSTRAINT_LIKE       65
#define SQLITE_INDEX_CONSTRAINT_GLOB       66
#define SQLITE_INDEX_CONSTRAINT_REGEXP     67
#define SQLITE_INDEX_CONSTRAINT_NE         68
#define SQLITE_INDEX_CONSTRAINT_ISNOT      69
#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL  70
#define SQLITE_INDEX_CONSTRAINT_ISNULL     71
#define SQLITE_INDEX_CONSTRAINT_IS         72
#define SQLITE_INDEX_CONSTRAINT_LIMIT      73
#define SQLITE_INDEX_CONSTRAINT_OFFSET     74
#define SQLITE_INDEX_CONSTRAINT_FUNCTION  150

/*
** CAPI3REF: Register A Virtual Table Implementation
** METHOD: sqlite3
**
** ^These routines are used to register a new [virtual table module] name.
** ^Module names must be registered before
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
7328
7329
7330
7331
7332
7333
7334
7335
7336
7337
7338
7339
7340
7341
7342
7343
7344
7345
7346
7347
7348
7349
7350
7351
7352
7353
7354
7355
7356
7357
7358
7359
7360
7361
7362
7363
7364
7365
7366
7367
7368
7369
7370
7371
7372
7373
7374
7375
7376
7377
7378







+
+
+
+
+
+














+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







** is a pointer to a destructor for the pClientData.  ^SQLite will
** invoke the destructor function (if it is not NULL) when SQLite
** no longer needs the pClientData pointer.  ^The destructor will also
** be invoked if the call to sqlite3_create_module_v2() fails.
** ^The sqlite3_create_module()
** interface is equivalent to sqlite3_create_module_v2() with a NULL
** destructor.
**
** ^If the third parameter (the pointer to the sqlite3_module object) is
** NULL then no new module is created and any existing modules with the
** same name are dropped.
**
** See also: [sqlite3_drop_modules()]
*/
int sqlite3_create_module(
  sqlite3 *db,               /* SQLite connection to register module with */
  const char *zName,         /* Name of the module */
  const sqlite3_module *p,   /* Methods for the module */
  void *pClientData          /* Client data for xCreate/xConnect */
);
int sqlite3_create_module_v2(
  sqlite3 *db,               /* SQLite connection to register module with */
  const char *zName,         /* Name of the module */
  const sqlite3_module *p,   /* Methods for the module */
  void *pClientData,         /* Client data for xCreate/xConnect */
  void(*xDestroy)(void*)     /* Module destructor function */
);

/*
** CAPI3REF: Remove Unnecessary Virtual Table Implementations
** METHOD: sqlite3
**
** ^The sqlite3_drop_modules(D,L) interface removes all virtual
** table modules from database connection D except those named on list L.
** The L parameter must be either NULL or a pointer to an array of pointers
** to strings where the array is terminated by a single NULL pointer.
** ^If the L parameter is NULL, then all virtual table modules are removed.
**
** See also: [sqlite3_create_module()]
*/
int sqlite3_drop_modules(
  sqlite3 *db,                /* Remove modules from this connection */
  const char **azKeep         /* Except, do not remove the ones named here */
);

/*
** CAPI3REF: Virtual Table Instance Object
** KEYWORDS: sqlite3_vtab
**
** Every [virtual table module] implementation uses a subclass
** of this object to describe a particular instance
6594
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
6615
6616
6617
7442
7443
7444
7445
7446
7447
7448










7449
7450
7451
7452
7453
7454
7455







-
-
-
-
-
-
-
-
-
-







** of the new function always causes an exception to be thrown.  So
** the new function is not good for anything by itself.  Its only
** purpose is to be a placeholder function that can be overloaded
** by a [virtual table].
*/
int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);

/*
** The interface to the virtual-table mechanism defined above (back up
** to a comment remarkably similar to this one) is currently considered
** to be experimental.  The interface might change in incompatible ways.
** If this is a problem for you, do not use the interface at this time.
**
** When the virtual-table mechanism stabilizes, we will declare the
** interface fixed, support it indefinitely, and remove this comment.
*/

/*
** CAPI3REF: A Handle To An Open BLOB
** KEYWORDS: {BLOB handle} {BLOB handles}
**
** An instance of this object represents an open BLOB on which
** [sqlite3_blob_open | incremental BLOB I/O] can be performed.
** ^Objects of this type are created by [sqlite3_blob_open()]
6921
6922
6923
6924
6925
6926
6927
6928

6929
6930
6931
6932
6933
6934
6935
7759
7760
7761
7762
7763
7764
7765

7766
7767
7768
7769
7770
7771
7772
7773







-
+







** routine returns NULL if it is unable to allocate the requested
** mutex.  The argument to sqlite3_mutex_alloc() must one of these
** integer constants:
**
** <ul>
** <li>  SQLITE_MUTEX_FAST
** <li>  SQLITE_MUTEX_RECURSIVE
** <li>  SQLITE_MUTEX_STATIC_MASTER
** <li>  SQLITE_MUTEX_STATIC_MAIN
** <li>  SQLITE_MUTEX_STATIC_MEM
** <li>  SQLITE_MUTEX_STATIC_OPEN
** <li>  SQLITE_MUTEX_STATIC_PRNG
** <li>  SQLITE_MUTEX_STATIC_LRU
** <li>  SQLITE_MUTEX_STATIC_PMEM
** <li>  SQLITE_MUTEX_STATIC_APP1
** <li>  SQLITE_MUTEX_STATIC_APP2
7044
7045
7046
7047
7048
7049
7050
7051

7052
7053
7054
7055
7056
7057
7058
7882
7883
7884
7885
7886
7887
7888

7889
7890
7891
7892
7893
7894
7895
7896







-
+







**   <li>  [sqlite3_mutex_held()] </li>
**   <li>  [sqlite3_mutex_notheld()] </li>
** </ul>)^
**
** The only difference is that the public sqlite3_XXX functions enumerated
** above silently ignore any invocations that pass a NULL pointer instead
** of a valid mutex handle. The implementations of the methods defined
** by this structure are not required to handle this case, the results
** by this structure are not required to handle this case. The results
** of passing a NULL pointer instead of a valid mutex handle are undefined
** (i.e. it is acceptable to provide an implementation that segfaults if
** it is passed a NULL pointer).
**
** The xMutexInit() method must be threadsafe.  It must be harmless to
** invoke xMutexInit() multiple times within the same process and without
** intervening calls to xMutexEnd().  Second and subsequent calls to
7123
7124
7125
7126
7127
7128
7129
7130

7131
7132
7133
7134
7135
7136
7137
7138
7139
7140
7141
7142
7143




7144
7145
7146
7147
7148
7149
7150
7961
7962
7963
7964
7965
7966
7967

7968
7969
7970
7971
7972
7973
7974
7975
7976
7977
7978
7979
7980
7981
7982
7983
7984
7985
7986
7987
7988
7989
7990
7991
7992







-
+













+
+
+
+







**
** The set of static mutexes may change from one SQLite release to the
** next.  Applications that override the built-in mutex logic must be
** prepared to accommodate additional static mutexes.
*/
#define SQLITE_MUTEX_FAST             0
#define SQLITE_MUTEX_RECURSIVE        1
#define SQLITE_MUTEX_STATIC_MASTER    2
#define SQLITE_MUTEX_STATIC_MAIN      2
#define SQLITE_MUTEX_STATIC_MEM       3  /* sqlite3_malloc() */
#define SQLITE_MUTEX_STATIC_MEM2      4  /* NOT USED */
#define SQLITE_MUTEX_STATIC_OPEN      4  /* sqlite3BtreeOpen() */
#define SQLITE_MUTEX_STATIC_PRNG      5  /* sqlite3_randomness() */
#define SQLITE_MUTEX_STATIC_LRU       6  /* lru page list */
#define SQLITE_MUTEX_STATIC_LRU2      7  /* NOT USED */
#define SQLITE_MUTEX_STATIC_PMEM      7  /* sqlite3PageMalloc() */
#define SQLITE_MUTEX_STATIC_APP1      8  /* For use by application */
#define SQLITE_MUTEX_STATIC_APP2      9  /* For use by application */
#define SQLITE_MUTEX_STATIC_APP3     10  /* For use by application */
#define SQLITE_MUTEX_STATIC_VFS1     11  /* For use by built-in VFS */
#define SQLITE_MUTEX_STATIC_VFS2     12  /* For use by extension VFS */
#define SQLITE_MUTEX_STATIC_VFS3     13  /* For use by application VFS */

/* Legacy compatibility: */
#define SQLITE_MUTEX_STATIC_MASTER    2


/*
** CAPI3REF: Retrieve the mutex for a database connection
** METHOD: sqlite3
**
** ^This interface returns a pointer the [sqlite3_mutex] object that 
** serializes access to the [database connection] given in the argument
7226
7227
7228
7229
7230
7231
7232
7233

7234
7235
7236
7237
7238
7239
7240

7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254







7255

7256
7257
7258
7259
7260
7261
7262
8068
8069
8070
8071
8072
8073
8074

8075
8076
8077
8078
8079
8080
8081

8082
8083
8084
8085
8086
8087
8088
8089
8090
8091
8092
8093
8094
8095
8096
8097
8098
8099
8100
8101
8102
8103

8104
8105
8106
8107
8108
8109
8110
8111







-
+






-
+














+
+
+
+
+
+
+
-
+







** without notice.  These values are for testing purposes only.
** Applications should not use any of these parameters or the
** [sqlite3_test_control()] interface.
*/
#define SQLITE_TESTCTRL_FIRST                    5
#define SQLITE_TESTCTRL_PRNG_SAVE                5
#define SQLITE_TESTCTRL_PRNG_RESTORE             6
#define SQLITE_TESTCTRL_PRNG_RESET               7
#define SQLITE_TESTCTRL_PRNG_RESET               7  /* NOT USED */
#define SQLITE_TESTCTRL_BITVEC_TEST              8
#define SQLITE_TESTCTRL_FAULT_INSTALL            9
#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS     10
#define SQLITE_TESTCTRL_PENDING_BYTE            11
#define SQLITE_TESTCTRL_ASSERT                  12
#define SQLITE_TESTCTRL_ALWAYS                  13
#define SQLITE_TESTCTRL_RESERVE                 14
#define SQLITE_TESTCTRL_RESERVE                 14  /* NOT USED */
#define SQLITE_TESTCTRL_OPTIMIZATIONS           15
#define SQLITE_TESTCTRL_ISKEYWORD               16  /* NOT USED */
#define SQLITE_TESTCTRL_SCRATCHMALLOC           17  /* NOT USED */
#define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS      17
#define SQLITE_TESTCTRL_LOCALTIME_FAULT         18
#define SQLITE_TESTCTRL_EXPLAIN_STMT            19  /* NOT USED */
#define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD    19
#define SQLITE_TESTCTRL_NEVER_CORRUPT           20
#define SQLITE_TESTCTRL_VDBE_COVERAGE           21
#define SQLITE_TESTCTRL_BYTEORDER               22
#define SQLITE_TESTCTRL_ISINIT                  23
#define SQLITE_TESTCTRL_SORTER_MMAP             24
#define SQLITE_TESTCTRL_IMPOSTER                25
#define SQLITE_TESTCTRL_PARSER_COVERAGE         26
#define SQLITE_TESTCTRL_RESULT_INTREAL          27
#define SQLITE_TESTCTRL_PRNG_SEED               28
#define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS     29
#define SQLITE_TESTCTRL_SEEK_COUNT              30
#define SQLITE_TESTCTRL_TRACEFLAGS              31
#define SQLITE_TESTCTRL_TUNE                    32
#define SQLITE_TESTCTRL_LOGEST                  33
#define SQLITE_TESTCTRL_LAST                    26  /* Largest TESTCTRL */
#define SQLITE_TESTCTRL_LAST                    33  /* Largest TESTCTRL */

/*
** CAPI3REF: SQL Keyword Checking
**
** These routines provide access to the set of SQL language keywords 
** recognized by SQLite.  Applications can uses these routines to determine
** whether or not a specific identifier needs to be escaped (for example,
7514
7515
7516
7517
7518
7519
7520
7521

7522
7523
7524
7525
7526
7527
7528
8363
8364
8365
8366
8367
8368
8369

8370
8371
8372
8373
8374
8375
8376
8377







-
+







** returned value includes allocations that overflowed because they
** where too large (they were larger than the "sz" parameter to
** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because
** no space was left in the page cache.</dd>)^
**
** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^(<dt>SQLITE_STATUS_PAGECACHE_SIZE</dt>
** <dd>This parameter records the largest memory allocation request
** handed to [pagecache memory allocator].  Only the value returned in the
** handed to the [pagecache memory allocator].  Only the value returned in the
** *pHighwater parameter to [sqlite3_status()] is of interest.  
** The value written into the *pCurrent parameter is undefined.</dd>)^
**
** [[SQLITE_STATUS_SCRATCH_USED]] <dt>SQLITE_STATUS_SCRATCH_USED</dt>
** <dd>No longer used.</dd>
**
** [[SQLITE_STATUS_SCRATCH_OVERFLOW]] ^(<dt>SQLITE_STATUS_SCRATCH_OVERFLOW</dt>
7590
7591
7592
7593
7594
7595
7596
7597

7598
7599
7600
7601
7602
7603
7604
8439
8440
8441
8442
8443
8444
8445

8446
8447
8448
8449
8450
8451
8452
8453







-
+







**
** <dl>
** [[SQLITE_DBSTATUS_LOOKASIDE_USED]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_USED</dt>
** <dd>This parameter returns the number of lookaside memory slots currently
** checked out.</dd>)^
**
** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt>
** <dd>This parameter returns the number malloc attempts that were 
** <dd>This parameter returns the number of malloc attempts that were 
** satisfied using lookaside memory. Only the high-water value is meaningful;
** the current value is always zero.)^
**
** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE]]
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE</dt>
** <dd>This parameter returns the number malloc attempts that might have
** been satisfied using lookaside memory but failed due to the amount of
7672
7673
7674
7675
7676
7677
7678
7679

7680
7681
7682
7683
7684
7685
7686
8521
8522
8523
8524
8525
8526
8527

8528
8529
8530
8531
8532
8533
8534
8535







-
+







**
** [[SQLITE_DBSTATUS_CACHE_SPILL]] ^(<dt>SQLITE_DBSTATUS_CACHE_SPILL</dt>
** <dd>This parameter returns the number of dirty cache entries that have
** been written to disk in the middle of a transaction due to the page
** cache overflowing. Transactions are more efficient if they are written
** to disk all at once. When pages spill mid-transaction, that introduces
** additional overhead. This parameter can be used help identify
** inefficiencies that can be resolve by increasing the cache size.
** inefficiencies that can be resolved by increasing the cache size.
** </dd>
**
** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(<dt>SQLITE_DBSTATUS_DEFERRED_FKS</dt>
** <dd>This parameter returns zero for the current value if and only if
** all foreign key constraints (deferred or immediate) have been
** resolved.)^  ^The highwater mark is always 0.
** </dd>
7761
7762
7763
7764
7765
7766
7767
7768

7769
7770
7771
7772
7773
7774
7775
7776










7777
7778
7779
7780
7781
7782
7783
7784
7785
7786
7787
7788
7789
7790
7791


7792
7793
7794
7795
7796
7797
7798
8610
8611
8612
8613
8614
8615
8616

8617
8618
8619
8620
8621
8622
8623
8624
8625
8626
8627
8628
8629
8630
8631
8632
8633
8634
8635
8636
8637
8638
8639
8640
8641
8642
8643
8644
8645
8646
8647
8648
8649
8650
8651
8652
8653
8654
8655
8656
8657
8658
8659







-
+








+
+
+
+
+
+
+
+
+
+















+
+







** to 2147483647.  The number of virtual machine operations can be 
** used as a proxy for the total work done by the prepared statement.
** If the number of virtual machine operations exceeds 2147483647
** then the value returned by this statement status code is undefined.
**
** [[SQLITE_STMTSTATUS_REPREPARE]] <dt>SQLITE_STMTSTATUS_REPREPARE</dt>
** <dd>^This is the number of times that the prepare statement has been
** automatically regenerated due to schema changes or change to 
** automatically regenerated due to schema changes or changes to 
** [bound parameters] that might affect the query plan.
**
** [[SQLITE_STMTSTATUS_RUN]] <dt>SQLITE_STMTSTATUS_RUN</dt>
** <dd>^This is the number of times that the prepared statement has
** been run.  A single "run" for the purposes of this counter is one
** or more calls to [sqlite3_step()] followed by a call to [sqlite3_reset()].
** The counter is incremented on the first [sqlite3_step()] call of each
** cycle.
**
** [[SQLITE_STMTSTATUS_FILTER_MISS]]
** [[SQLITE_STMTSTATUS_FILTER HIT]] 
** <dt>SQLITE_STMTSTATUS_FILTER_HIT<br>
** SQLITE_STMTSTATUS_FILTER_MISS</dt>
** <dd>^SQLITE_STMTSTATUS_FILTER_HIT is the number of times that a join
** step was bypassed because a Bloom filter returned not-found.  The
** corresponding SQLITE_STMTSTATUS_FILTER_MISS value is the number of
** times that the Bloom filter returned a find, and thus the join step
** had to be processed as normal.
**
** [[SQLITE_STMTSTATUS_MEMUSED]] <dt>SQLITE_STMTSTATUS_MEMUSED</dt>
** <dd>^This is the approximate number of bytes of heap memory
** used to store the prepared statement.  ^This value is not actually
** a counter, and so the resetFlg parameter to sqlite3_stmt_status()
** is ignored when the opcode is SQLITE_STMTSTATUS_MEMUSED.
** </dd>
** </dl>
*/
#define SQLITE_STMTSTATUS_FULLSCAN_STEP     1
#define SQLITE_STMTSTATUS_SORT              2
#define SQLITE_STMTSTATUS_AUTOINDEX         3
#define SQLITE_STMTSTATUS_VM_STEP           4
#define SQLITE_STMTSTATUS_REPREPARE         5
#define SQLITE_STMTSTATUS_RUN               6
#define SQLITE_STMTSTATUS_FILTER_MISS       7
#define SQLITE_STMTSTATUS_FILTER_HIT        8
#define SQLITE_STMTSTATUS_MEMUSED           99

/*
** CAPI3REF: Custom Page Cache Object
**
** The sqlite3_pcache type is opaque.  It is implemented by
** the pluggable module.  The SQLite core has no knowledge of
7932
7933
7934
7935
7936
7937
7938
7939

7940
7941
7942
7943
7944
7945
7946
8793
8794
8795
8796
8797
8798
8799

8800
8801
8802
8803
8804
8805
8806
8807







-
+







**                 Otherwise return NULL.
** <tr><td> 2 <td> Make every effort to allocate a new page.  Only return
**                 NULL if allocating a new page is effectively impossible.
** </table>
**
** ^(SQLite will normally invoke xFetch() with a createFlag of 0 or 1.  SQLite
** will only use a createFlag of 2 after a prior call with a createFlag of 1
** failed.)^  In between the to xFetch() calls, SQLite may
** failed.)^  In between the xFetch() calls, SQLite may
** attempt to unpin one or more cache pages by spilling the content of
** pinned pages to disk and synching the operating system disk cache.
**
** [[the xUnpin() page cache method]]
** ^xUnpin() is called by SQLite with a pointer to a currently pinned page
** as its second argument.  If the third parameter, discard, is non-zero,
** then the page must be evicted from the cache.
8196
8197
8198
8199
8200
8201
8202
8203

8204
8205
8206
8207
8208
8209
8210
9057
9058
9059
9060
9061
9062
9063

9064
9065
9066
9067
9068
9069
9070
9071







-
+







** However, the application must guarantee that the destination 
** [database connection] is not passed to any other API (by any thread) after 
** sqlite3_backup_init() is called and before the corresponding call to
** sqlite3_backup_finish().  SQLite does not currently check to see
** if the application incorrectly accesses the destination [database connection]
** and so no error code is reported, but the operations may malfunction
** nevertheless.  Use of the destination database connection while a
** backup is in progress might also also cause a mutex deadlock.
** backup is in progress might also cause a mutex deadlock.
**
** If running in [shared cache mode], the application must
** guarantee that the shared cache used by the destination database
** is not accessed while the backup is running. In practice this means
** that the application must guarantee that the disk file being 
** backed up to is not accessed by any connection within the process,
** not just the specific connection that was passed to sqlite3_backup_init().
8250
8251
8252
8253
8254
8255
8256
8257

8258
8259
8260
8261
8262
8263
8264
9111
9112
9113
9114
9115
9116
9117

9118
9119
9120
9121
9122
9123
9124
9125







-
+







** identity of the database connection (the blocking connection) that
** has locked the required resource is stored internally. ^After an 
** application receives an SQLITE_LOCKED error, it may call the
** sqlite3_unlock_notify() method with the blocked connection handle as 
** the first argument to register for a callback that will be invoked
** when the blocking connections current transaction is concluded. ^The
** callback is invoked from within the [sqlite3_step] or [sqlite3_close]
** call that concludes the blocking connections transaction.
** call that concludes the blocking connection's transaction.
**
** ^(If sqlite3_unlock_notify() is called in a multi-threaded application,
** there is a chance that the blocking connection will have already
** concluded its transaction by the time sqlite3_unlock_notify() is invoked.
** If this happens, then the specified callback is invoked immediately,
** from within the call to sqlite3_unlock_notify().)^
**
8288
8289
8290
8291
8292
8293
8294
8295

8296
8297
8298
8299
8300
8301
8302
9149
9150
9151
9152
9153
9154
9155

9156
9157
9158
9159
9160
9161
9162
9163







-
+







** When an unlock-notify callback is registered, the application provides a 
** single void* pointer that is passed to the callback when it is invoked.
** However, the signature of the callback function allows SQLite to pass
** it an array of void* context pointers. The first argument passed to
** an unlock-notify callback is a pointer to an array of void* pointers,
** and the second is the number of entries in the array.
**
** When a blocking connections transaction is concluded, there may be
** When a blocking connection's transaction is concluded, there may be
** more than one blocked connection that has registered for an unlock-notify
** callback. ^If two or more such blocked connections have specified the
** same callback function, then instead of invoking the callback function
** multiple times, it is invoked once with the set of void* context pointers
** specified by the blocked connections bundled together into an array.
** This gives the application an opportunity to prioritize any actions 
** related to the set of unblocked database connections.
8448
8449
8450
8451
8452
8453
8454
8455
8456



8457
8458
8459
8460
8461
8462
8463
9309
9310
9311
9312
9313
9314
9315


9316
9317
9318
9319
9320
9321
9322
9323
9324
9325







-
-
+
+
+







** to report an error, though the commit will have still occurred. If the
** callback returns [SQLITE_ROW] or [SQLITE_DONE], or if it returns a value
** that does not correspond to any valid SQLite error code, the results
** are undefined.
**
** A single database handle may have at most a single write-ahead log callback 
** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any
** previously registered write-ahead log callback. ^Note that the
** [sqlite3_wal_autocheckpoint()] interface and the
** previously registered write-ahead log callback. ^The return value is
** a copy of the third parameter from the previous call, if any, or 0.
** ^Note that the [sqlite3_wal_autocheckpoint()] interface and the
** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will
** overwrite any prior [sqlite3_wal_hook()] settings.
*/
void *sqlite3_wal_hook(
  sqlite3*, 
  int(*)(void *,sqlite3*,const char*,int),
  void*
8623
8624
8625
8626
8627
8628
8629
8630

8631
8632
8633
8634
8635
8636
8637
8638
8639
8640
8641
8642
8643
8644
8645







8646
8647
8648
8649
8650


8651
8652
8653
8654
8655
8656
8657
8658

8659
8660
8661
8662
8663
8664
8665
9485
9486
9487
9488
9489
9490
9491

9492
9493
9494
9495
9496
9497
9498
9499
9500
9501
9502
9503
9504



9505
9506
9507
9508
9509
9510
9511
9512
9513
9514
9515
9516
9517
9518
9519
9520
9521
9522
9523
9524
9525

9526
9527
9528
9529
9530
9531
9532
9533







-
+












-
-
-
+
+
+
+
+
+
+





+
+







-
+







** These constants define all valid values for the "checkpoint mode" passed
** as the third parameter to the [sqlite3_wal_checkpoint_v2()] interface.
** See the [sqlite3_wal_checkpoint_v2()] documentation for details on the
** meaning of each of these checkpoint modes.
*/
#define SQLITE_CHECKPOINT_PASSIVE  0  /* Do as much as possible w/o blocking */
#define SQLITE_CHECKPOINT_FULL     1  /* Wait for writers, then checkpoint */
#define SQLITE_CHECKPOINT_RESTART  2  /* Like FULL but wait for for readers */
#define SQLITE_CHECKPOINT_RESTART  2  /* Like FULL but wait for readers */
#define SQLITE_CHECKPOINT_TRUNCATE 3  /* Like RESTART but also truncate WAL */

/*
** CAPI3REF: Virtual Table Interface Configuration
**
** This function may be called by either the [xConnect] or [xCreate] method
** of a [virtual table] implementation to configure
** various facets of the virtual table interface.
**
** If this interface is invoked outside the context of an xConnect or
** xCreate virtual table method then the behavior is undefined.
**
** At present, there is only one option that may be configured using
** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].)  Further options
** may be added in the future.
** In the call sqlite3_vtab_config(D,C,...) the D parameter is the
** [database connection] in which the virtual table is being created and
** which is passed in as the first argument to the [xConnect] or [xCreate]
** method that is invoking sqlite3_vtab_config().  The C parameter is one
** of the [virtual table configuration options].  The presence and meaning
** of parameters after C depend on which [virtual table configuration option]
** is used.
*/
int sqlite3_vtab_config(sqlite3*, int op, ...);

/*
** CAPI3REF: Virtual Table Configuration Options
** KEYWORDS: {virtual table configuration options} 
** KEYWORDS: {virtual table configuration option}
**
** These macros define the various options to the
** [sqlite3_vtab_config()] interface that [virtual table] implementations
** can use to customize and optimize their behavior.
**
** <dl>
** [[SQLITE_VTAB_CONSTRAINT_SUPPORT]]
** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT
** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT</dt>
** <dd>Calls of the form
** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported,
** where X is an integer.  If X is zero, then the [virtual table] whose
** [xCreate] or [xConnect] method invoked [sqlite3_vtab_config()] does not
** support constraints.  In this configuration (which is the default) if
** a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], then the entire
** statement is rolled back as if [ON CONFLICT | OR ABORT] had been
8680
8681
8682
8683
8684
8685
8686




















8687
8688
8689


8690
8691
8692
8693
8694
8695
8696
8697
8698
8699
8700
8701
8702
8703
8704
8705
8706
8707

8708
8709
8710



8711
8712
8713
8714
8715
8716
8717
8718






8719
8720
8721
8722
8723

8724
8725
8726



8727
8728
8729
8730
8731
8732
8733



































































































































































































































































8734
8735

8736
8737
8738
8739
8740
8741
8742
9548
9549
9550
9551
9552
9553
9554
9555
9556
9557
9558
9559
9560
9561
9562
9563
9564
9565
9566
9567
9568
9569
9570
9571
9572
9573
9574
9575
9576
9577
9578
9579
9580
9581
9582
9583
9584
9585
9586
9587
9588
9589
9590
9591
9592
9593
9594
9595
9596

9597
9598


9599
9600
9601
9602
9603
9604
9605
9606
9607
9608
9609
9610
9611
9612
9613
9614
9615
9616
9617
9618
9619
9620
9621
9622
9623

9624
9625
9626
9627






9628
9629
9630
9631
9632
9633
9634
9635
9636
9637
9638
9639
9640
9641
9642
9643
9644
9645
9646
9647
9648
9649
9650
9651
9652
9653
9654
9655
9656
9657
9658
9659
9660
9661
9662
9663
9664
9665
9666
9667
9668
9669
9670
9671
9672
9673
9674
9675
9676
9677
9678
9679
9680
9681
9682
9683
9684
9685
9686
9687
9688
9689
9690
9691
9692
9693
9694
9695
9696
9697
9698
9699
9700
9701
9702
9703
9704
9705
9706
9707
9708
9709
9710
9711
9712
9713
9714
9715
9716
9717
9718
9719
9720
9721
9722
9723
9724
9725
9726
9727
9728
9729
9730
9731
9732
9733
9734
9735
9736
9737
9738
9739
9740
9741
9742
9743
9744
9745
9746
9747
9748
9749
9750
9751
9752
9753
9754
9755
9756
9757
9758
9759
9760
9761
9762
9763
9764
9765
9766
9767
9768
9769
9770
9771
9772
9773
9774
9775
9776
9777
9778
9779
9780
9781
9782
9783
9784
9785
9786
9787
9788
9789
9790
9791
9792
9793
9794
9795
9796
9797
9798
9799
9800
9801
9802
9803
9804
9805
9806
9807
9808
9809
9810
9811
9812
9813
9814
9815
9816
9817
9818
9819
9820
9821
9822
9823
9824
9825
9826
9827
9828
9829
9830
9831
9832
9833
9834
9835
9836
9837
9838
9839
9840
9841
9842
9843
9844
9845
9846
9847
9848
9849
9850
9851
9852
9853
9854
9855
9856
9857
9858
9859
9860
9861
9862
9863
9864
9865
9866
9867
9868
9869
9870
9871
9872
9873
9874
9875
9876
9877
9878
9879
9880
9881
9882
9883
9884
9885
9886
9887

9888
9889
9890
9891
9892
9893
9894
9895







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



+
+

















-
+

-
-
+
+
+








+
+
+
+
+
+





+


-
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+







** must do so within the [xUpdate] method. If a call to the 
** [sqlite3_vtab_on_conflict()] function indicates that the current ON 
** CONFLICT policy is REPLACE, the virtual table implementation should 
** silently replace the appropriate rows within the xUpdate callback and
** return SQLITE_OK. Or, if this is not possible, it may return
** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT 
** constraint handling.
** </dd>
**
** [[SQLITE_VTAB_DIRECTONLY]]<dt>SQLITE_VTAB_DIRECTONLY</dt>
** <dd>Calls of the form
** [sqlite3_vtab_config](db,SQLITE_VTAB_DIRECTONLY) from within the
** the [xConnect] or [xCreate] methods of a [virtual table] implmentation
** prohibits that virtual table from being used from within triggers and
** views.
** </dd>
**
** [[SQLITE_VTAB_INNOCUOUS]]<dt>SQLITE_VTAB_INNOCUOUS</dt>
** <dd>Calls of the form
** [sqlite3_vtab_config](db,SQLITE_VTAB_INNOCUOUS) from within the
** the [xConnect] or [xCreate] methods of a [virtual table] implmentation
** identify that virtual table as being safe to use from within triggers
** and views.  Conceptually, the SQLITE_VTAB_INNOCUOUS tag means that the
** virtual table can do no serious harm even if it is controlled by a
** malicious hacker.  Developers should avoid setting the SQLITE_VTAB_INNOCUOUS
** flag unless absolutely necessary.
** </dd>
** </dl>
*/
#define SQLITE_VTAB_CONSTRAINT_SUPPORT 1
#define SQLITE_VTAB_INNOCUOUS          2
#define SQLITE_VTAB_DIRECTONLY         3

/*
** CAPI3REF: Determine The Virtual Table Conflict Policy
**
** This function may only be called from within a call to the [xUpdate] method
** of a [virtual table] implementation for an INSERT or UPDATE operation. ^The
** value returned is one of [SQLITE_ROLLBACK], [SQLITE_IGNORE], [SQLITE_FAIL],
** [SQLITE_ABORT], or [SQLITE_REPLACE], according to the [ON CONFLICT] mode
** of the SQL statement that triggered the call to the [xUpdate] method of the
** [virtual table].
*/
int sqlite3_vtab_on_conflict(sqlite3 *);

/*
** CAPI3REF: Determine If Virtual Table Column Access Is For UPDATE
**
** If the sqlite3_vtab_nochange(X) routine is called within the [xColumn]
** method of a [virtual table], then it returns true if and only if the
** method of a [virtual table], then it might return true if the
** column is being fetched as part of an UPDATE operation during which the
** column value will not change.  Applications might use this to substitute
** a return value that is less expensive to compute and that the corresponding
** column value will not change.  The virtual table implementation can use
** this hint as permission to substitute a return value that is less
** expensive to compute and that the corresponding
** [xUpdate] method understands as a "no-change" value.
**
** If the [xColumn] method calls sqlite3_vtab_nochange() and finds that
** the column is not changed by the UPDATE statement, then the xColumn
** method can optionally return without setting a result, without calling
** any of the [sqlite3_result_int|sqlite3_result_xxxxx() interfaces].
** In that case, [sqlite3_value_nochange(X)] will return true for the
** same column in the [xUpdate] method.
**
** The sqlite3_vtab_nochange() routine is an optimization.  Virtual table
** implementations should continue to give a correct answer even if the
** sqlite3_vtab_nochange() interface were to always return false.  In the
** current implementation, the sqlite3_vtab_nochange() interface does always
** returns false for the enhanced [UPDATE FROM] statement.
*/
int sqlite3_vtab_nochange(sqlite3_context*);

/*
** CAPI3REF: Determine The Collation For a Virtual Table Constraint
** METHOD: sqlite3_index_info
**
** This function may only be called from within a call to the [xBestIndex]
** method of a [virtual table]. 
** method of a [virtual table].  This function returns a pointer to a string
** that is the name of the appropriate collation sequence to use for text
** comparisons on the constraint identified by its arguments.
**
** The first argument must be the sqlite3_index_info object that is the
** first parameter to the xBestIndex() method. The second argument must be
** an index into the aConstraint[] array belonging to the sqlite3_index_info
** structure passed to xBestIndex. This function returns a pointer to a buffer 
** containing the name of the collation sequence for the corresponding
** constraint.
** The first argument must be the pointer to the [sqlite3_index_info] object
** that is the first parameter to the xBestIndex() method. The second argument
** must be an index into the aConstraint[] array belonging to the
** sqlite3_index_info structure passed to xBestIndex.
**
** Important:
** The first parameter must be the same pointer that is passed into the
** xBestMethod() method.  The first parameter may not be a pointer to a
** different [sqlite3_index_info] object, even an exact copy.
**
** The return value is computed as follows:
**
** <ol>
** <li><p> If the constraint comes from a WHERE clause expression that contains
**         a [COLLATE operator], then the name of the collation specified by
**         that COLLATE operator is returned.
** <li><p> If there is no COLLATE operator, but the column that is the subject
**         of the constraint specifies an alternative collating sequence via
**         a [COLLATE clause] on the column definition within the CREATE TABLE
**         statement that was passed into [sqlite3_declare_vtab()], then the
**         name of that alternative collating sequence is returned.
** <li><p> Otherwise, "BINARY" is returned.
** </ol>
*/
const char *sqlite3_vtab_collation(sqlite3_index_info*,int);

/*
** CAPI3REF: Determine if a virtual table query is DISTINCT
** METHOD: sqlite3_index_info
**
** This API may only be used from within an [xBestIndex|xBestIndex method]
** of a [virtual table] implementation. The result of calling this
** interface from outside of xBestIndex() is undefined and probably harmful.
**
** ^The sqlite3_vtab_distinct() interface returns an integer between 0 and
** 3.  The integer returned by sqlite3_vtab_distinct()
** gives the virtual table additional information about how the query
** planner wants the output to be ordered. As long as the virtual table
** can meet the ordering requirements of the query planner, it may set
** the "orderByConsumed" flag.
**
** <ol><li value="0"><p>
** ^If the sqlite3_vtab_distinct() interface returns 0, that means
** that the query planner needs the virtual table to return all rows in the
** sort order defined by the "nOrderBy" and "aOrderBy" fields of the
** [sqlite3_index_info] object.  This is the default expectation.  If the
** virtual table outputs all rows in sorted order, then it is always safe for
** the xBestIndex method to set the "orderByConsumed" flag, regardless of
** the return value from sqlite3_vtab_distinct().
** <li value="1"><p>
** ^(If the sqlite3_vtab_distinct() interface returns 1, that means
** that the query planner does not need the rows to be returned in sorted order
** as long as all rows with the same values in all columns identified by the
** "aOrderBy" field are adjacent.)^  This mode is used when the query planner
** is doing a GROUP BY.
** <li value="2"><p>
** ^(If the sqlite3_vtab_distinct() interface returns 2, that means
** that the query planner does not need the rows returned in any particular
** order, as long as rows with the same values in all "aOrderBy" columns
** are adjacent.)^  ^(Furthermore, only a single row for each particular
** combination of values in the columns identified by the "aOrderBy" field
** needs to be returned.)^  ^It is always ok for two or more rows with the same
** values in all "aOrderBy" columns to be returned, as long as all such rows
** are adjacent.  ^The virtual table may, if it chooses, omit extra rows
** that have the same value for all columns identified by "aOrderBy".
** ^However omitting the extra rows is optional.
** This mode is used for a DISTINCT query.
** <li value="3"><p>
** ^(If the sqlite3_vtab_distinct() interface returns 3, that means
** that the query planner needs only distinct rows but it does need the
** rows to be sorted.)^ ^The virtual table implementation is free to omit
** rows that are identical in all aOrderBy columns, if it wants to, but
** it is not required to omit any rows.  This mode is used for queries
** that have both DISTINCT and ORDER BY clauses.
** </ol>
**
** ^For the purposes of comparing virtual table output values to see if the
** values are same value for sorting purposes, two NULL values are considered
** to be the same.  In other words, the comparison operator is "IS"
** (or "IS NOT DISTINCT FROM") and not "==".
**
** If a virtual table implementation is unable to meet the requirements
** specified above, then it must not set the "orderByConsumed" flag in the
** [sqlite3_index_info] object or an incorrect answer may result.
**
** ^A virtual table implementation is always free to return rows in any order
** it wants, as long as the "orderByConsumed" flag is not set.  ^When the
** the "orderByConsumed" flag is unset, the query planner will add extra
** [bytecode] to ensure that the final results returned by the SQL query are
** ordered correctly.  The use of the "orderByConsumed" flag and the
** sqlite3_vtab_distinct() interface is merely an optimization.  ^Careful
** use of the sqlite3_vtab_distinct() interface and the "orderByConsumed"
** flag might help queries against a virtual table to run faster.  Being
** overly aggressive and setting the "orderByConsumed" flag when it is not
** valid to do so, on the other hand, might cause SQLite to return incorrect
** results.
*/
int sqlite3_vtab_distinct(sqlite3_index_info*);

/*
** CAPI3REF: Identify and handle IN constraints in xBestIndex
**
** This interface may only be used from within an 
** [xBestIndex|xBestIndex() method] of a [virtual table] implementation.
** The result of invoking this interface from any other context is
** undefined and probably harmful.
**
** ^(A constraint on a virtual table of the form
** "[IN operator|column IN (...)]" is
** communicated to the xBestIndex method as a
** [SQLITE_INDEX_CONSTRAINT_EQ] constraint.)^  If xBestIndex wants to use
** this constraint, it must set the corresponding
** aConstraintUsage[].argvIndex to a postive integer.  ^(Then, under
** the usual mode of handling IN operators, SQLite generates [bytecode]
** that invokes the [xFilter|xFilter() method] once for each value
** on the right-hand side of the IN operator.)^  Thus the virtual table
** only sees a single value from the right-hand side of the IN operator
** at a time.
**
** In some cases, however, it would be advantageous for the virtual
** table to see all values on the right-hand of the IN operator all at
** once.  The sqlite3_vtab_in() interfaces facilitates this in two ways:
**
** <ol>
** <li><p>
**   ^A call to sqlite3_vtab_in(P,N,-1) will return true (non-zero)
**   if and only if the [sqlite3_index_info|P->aConstraint][N] constraint
**   is an [IN operator] that can be processed all at once.  ^In other words,
**   sqlite3_vtab_in() with -1 in the third argument is a mechanism
**   by which the virtual table can ask SQLite if all-at-once processing
**   of the IN operator is even possible.
**
** <li><p>
**   ^A call to sqlite3_vtab_in(P,N,F) with F==1 or F==0 indicates
**   to SQLite that the virtual table does or does not want to process
**   the IN operator all-at-once, respectively.  ^Thus when the third
**   parameter (F) is non-negative, this interface is the mechanism by
**   which the virtual table tells SQLite how it wants to process the
**   IN operator.
** </ol>
**
** ^The sqlite3_vtab_in(P,N,F) interface can be invoked multiple times
** within the same xBestIndex method call.  ^For any given P,N pair,
** the return value from sqlite3_vtab_in(P,N,F) will always be the same
** within the same xBestIndex call.  ^If the interface returns true
** (non-zero), that means that the constraint is an IN operator
** that can be processed all-at-once.  ^If the constraint is not an IN
** operator or cannot be processed all-at-once, then the interface returns
** false.
**
** ^(All-at-once processing of the IN operator is selected if both of the
** following conditions are met:
**
** <ol>
** <li><p> The P->aConstraintUsage[N].argvIndex value is set to a positive
** integer.  This is how the virtual table tells SQLite that it wants to
** use the N-th constraint.
**
** <li><p> The last call to sqlite3_vtab_in(P,N,F) for which F was
** non-negative had F>=1.
** </ol>)^
** 
** ^If either or both of the conditions above are false, then SQLite uses
** the traditional one-at-a-time processing strategy for the IN constraint.
** ^If both conditions are true, then the argvIndex-th parameter to the
** xFilter method will be an [sqlite3_value] that appears to be NULL,
** but which can be passed to [sqlite3_vtab_in_first()] and
** [sqlite3_vtab_in_next()] to find all values on the right-hand side
** of the IN constraint.
*/
int sqlite3_vtab_in(sqlite3_index_info*, int iCons, int bHandle);

/*
** CAPI3REF: Find all elements on the right-hand side of an IN constraint.
**
** These interfaces are only useful from within the
** [xFilter|xFilter() method] of a [virtual table] implementation.
** The result of invoking these interfaces from any other context
** is undefined and probably harmful.
**
** The X parameter in a call to sqlite3_vtab_in_first(X,P) or
** sqlite3_vtab_in_next(X,P) should be one of the parameters to the
** xFilter method which invokes these routines, and specifically
** a parameter that was previously selected for all-at-once IN constraint
** processing use the [sqlite3_vtab_in()] interface in the
** [xBestIndex|xBestIndex method].  ^(If the X parameter is not
** an xFilter argument that was selected for all-at-once IN constraint
** processing, then these routines return [SQLITE_ERROR].)^
**
** ^(Use these routines to access all values on the right-hand side
** of the IN constraint using code like the following:
**
** <blockquote><pre>
** &nbsp;  for(rc=sqlite3_vtab_in_first(pList, &pVal);
** &nbsp;      rc==SQLITE_OK && pVal
** &nbsp;      rc=sqlite3_vtab_in_next(pList, &pVal)
** &nbsp;  ){
** &nbsp;    // do something with pVal
** &nbsp;  }
** &nbsp;  if( rc!=SQLITE_OK ){
** &nbsp;    // an error has occurred
** &nbsp;  }
** </pre></blockquote>)^
**
** ^On success, the sqlite3_vtab_in_first(X,P) and sqlite3_vtab_in_next(X,P)
** routines return SQLITE_OK and set *P to point to the first or next value
** on the RHS of the IN constraint.  ^If there are no more values on the
** right hand side of the IN constraint, then *P is set to NULL and these
** routines return [SQLITE_DONE].  ^The return value might be
** some other value, such as SQLITE_NOMEM, in the event of a malfunction.
**
** The *ppOut values returned by these routines are only valid until the
** next call to either of these routines or until the end of the xFilter
** method from which these routines were called.  If the virtual table
** implementation needs to retain the *ppOut values for longer, it must make
** copies.  The *ppOut values are [protected sqlite3_value|protected].
*/
int sqlite3_vtab_in_first(sqlite3_value *pVal, sqlite3_value **ppOut);
int sqlite3_vtab_in_next(sqlite3_value *pVal, sqlite3_value **ppOut);

/*
** CAPI3REF: Constraint values in xBestIndex()
** METHOD: sqlite3_index_info
**
** This API may only be used from within the [xBestIndex|xBestIndex method]
** of a [virtual table] implementation. The result of calling this interface
** from outside of an xBestIndex method are undefined and probably harmful.
**
** ^When the sqlite3_vtab_rhs_value(P,J,V) interface is invoked from within
** the [xBestIndex] method of a [virtual table] implementation, with P being
** a copy of the [sqlite3_index_info] object pointer passed into xBestIndex and
** J being a 0-based index into P->aConstraint[], then this routine
** attempts to set *V to the value of the right-hand operand of
** that constraint if the right-hand operand is known.  ^If the
** right-hand operand is not known, then *V is set to a NULL pointer.
** ^The sqlite3_vtab_rhs_value(P,J,V) interface returns SQLITE_OK if
** and only if *V is set to a value.  ^The sqlite3_vtab_rhs_value(P,J,V) 
** inteface returns SQLITE_NOTFOUND if the right-hand side of the J-th
** constraint is not available.  ^The sqlite3_vtab_rhs_value() interface
** can return an result code other than SQLITE_OK or SQLITE_NOTFOUND if
** something goes wrong.
**
** The sqlite3_vtab_rhs_value() interface is usually only successful if
** the right-hand operand of a constraint is a literal value in the original
** SQL statement.  If the right-hand operand is an expression or a reference
** to some other column or a [host parameter], then sqlite3_vtab_rhs_value()
** will probably return [SQLITE_NOTFOUND].
**
** ^(Some constraints, such as [SQLITE_INDEX_CONSTRAINT_ISNULL] and
** [SQLITE_INDEX_CONSTRAINT_ISNOTNULL], have no right-hand operand.  For such
** constraints, sqlite3_vtab_rhs_value() always returns SQLITE_NOTFOUND.)^
**
** ^The [sqlite3_value] object returned in *V is a protected sqlite3_value
** and remains valid for the duration of the xBestIndex method call.
** ^When xBestIndex returns, the sqlite3_value object returned by
** sqlite3_vtab_rhs_value() is automatically deallocated.
**
** The "_rhs_" in the name of this routine is an abbreviation for
** "Right-Hand Side".
*/
SQLITE_EXPERIMENTAL const char *sqlite3_vtab_collation(sqlite3_index_info*,int);
int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value **ppVal);

/*
** CAPI3REF: Conflict resolution modes
** KEYWORDS: {conflict resolution mode}
**
** These constants are returned by [sqlite3_vtab_on_conflict()] to
** inform a [virtual table] implementation what the [ON CONFLICT] mode
8760
8761
8762
8763
8764
8765
8766




8767
8768
8769

8770
8771
8772
8773

8774
8775
8776
8777

8778
8779
8780
8781
8782
8783
8784
8785

8786
8787
8788
8789
8790

8791
8792
8793
8794
8795
8796



8797
8798
8799


8800













8801
8802
8803
8804
8805
8806
8807


8808
8809
8810
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
8836
8837
8838
8839
8840
8841
8842
8843
8844
8845













8846
8847
8848
8849
8850
8851
8852
8853
8854
8855
8856
8857
8858
8859

8860
8861
8862
8863
8864
8865
8866
9913
9914
9915
9916
9917
9918
9919
9920
9921
9922
9923
9924
9925

9926
9927
9928
9929

9930
9931
9932
9933

9934
9935
9936
9937
9938
9939
9940
9941

9942
9943
9944
9945
9946

9947
9948
9949
9950



9951
9952
9953



9954
9955
9956
9957
9958
9959
9960
9961
9962
9963
9964
9965
9966
9967
9968
9969
9970
9971
9972
9973
9974
9975
9976
9977
9978
9979
9980
9981
9982
9983

9984
9985
9986
9987
9988
9989
9990
9991
9992
9993
9994








9995
9996
9997
9998
9999
10000
10001
10002
10003
10004
10005
10006
10007
10008
10009
10010
10011
10012
10013





10014
10015
10016
10017
10018
10019
10020
10021
10022
10023
10024
10025
10026
10027
10028
10029
10030
10031
10032
10033
10034
10035
10036
10037
10038
10039
10040
10041
10042
10043
10044
10045
10046
10047
10048
10049
10050
10051
10052
10053
10054
10055
10056
10057







+
+
+
+


-
+



-
+



-
+







-
+




-
+



-
-
-
+
+
+
-
-
-
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+







+
+





-
+










-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-









+
+
+
+
+
+
+
+
+
+
+
+
+














+







** [sqlite3_stmt_scanstatus(S,X,T,V)] interface.  Each constant designates a
** different metric for sqlite3_stmt_scanstatus() to return.
**
** When the value returned to V is a string, space to hold that string is
** managed by the prepared statement S and will be automatically freed when
** S is finalized.
**
** Not all values are available for all query elements. When a value is
** not available, the output variable is set to -1 if the value is numeric,
** or to NULL if it is a string (SQLITE_SCANSTAT_NAME).
**
** <dl>
** [[SQLITE_SCANSTAT_NLOOP]] <dt>SQLITE_SCANSTAT_NLOOP</dt>
** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be
** <dd>^The [sqlite3_int64] variable pointed to by the V parameter will be
** set to the total number of times that the X-th loop has run.</dd>
**
** [[SQLITE_SCANSTAT_NVISIT]] <dt>SQLITE_SCANSTAT_NVISIT</dt>
** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be set
** <dd>^The [sqlite3_int64] variable pointed to by the V parameter will be set
** to the total number of rows examined by all iterations of the X-th loop.</dd>
**
** [[SQLITE_SCANSTAT_EST]] <dt>SQLITE_SCANSTAT_EST</dt>
** <dd>^The "double" variable pointed to by the T parameter will be set to the
** <dd>^The "double" variable pointed to by the V parameter will be set to the
** query planner's estimate for the average number of rows output from each
** iteration of the X-th loop.  If the query planner's estimates was accurate,
** then this value will approximate the quotient NVISIT/NLOOP and the
** product of this value for all prior loops with the same SELECTID will
** be the NLOOP value for the current loop.
**
** [[SQLITE_SCANSTAT_NAME]] <dt>SQLITE_SCANSTAT_NAME</dt>
** <dd>^The "const char *" variable pointed to by the T parameter will be set
** <dd>^The "const char *" variable pointed to by the V parameter will be set
** to a zero-terminated UTF-8 string containing the name of the index or table
** used for the X-th loop.
**
** [[SQLITE_SCANSTAT_EXPLAIN]] <dt>SQLITE_SCANSTAT_EXPLAIN</dt>
** <dd>^The "const char *" variable pointed to by the T parameter will be set
** <dd>^The "const char *" variable pointed to by the V parameter will be set
** to a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN]
** description for the X-th loop.
**
** [[SQLITE_SCANSTAT_SELECTID]] <dt>SQLITE_SCANSTAT_SELECT</dt>
** <dd>^The "int" variable pointed to by the T parameter will be set to the
** "select-id" for the X-th loop.  The select-id identifies which query or
** [[SQLITE_SCANSTAT_SELECTID]] <dt>SQLITE_SCANSTAT_SELECTID</dt>
** <dd>^The "int" variable pointed to by the V parameter will be set to the
** id for the X-th query plan element. The id value is unique within the
** subquery the loop is part of.  The main query has a select-id of zero.
** The select-id is the same value as is output in the first column
** of an [EXPLAIN QUERY PLAN] query.
** statement. The select-id is the same value as is output in the first 
** column of an [EXPLAIN QUERY PLAN] query.
** </dl>
**
** [[SQLITE_SCANSTAT_PARENTID]] <dt>SQLITE_SCANSTAT_PARENTID</dt>
** <dd>The "int" variable pointed to by the V parameter will be set to the
** the id of the parent of the current query element, if applicable, or
** to zero if the query element has no parent. This is the same value as
** returned in the second column of an [EXPLAIN QUERY PLAN] query. 
**
** [[SQLITE_SCANSTAT_NCYCLE]] <dt>SQLITE_SCANSTAT_NCYCLE</dt>
** <dd>The sqlite3_int64 output value is set to the number of cycles,
** according to the processor time-stamp counter, that elapsed while the
** query element was being processed. This value is not available for
** all query elements - if it is unavailable the output variable is
** set to -1.
*/
#define SQLITE_SCANSTAT_NLOOP    0
#define SQLITE_SCANSTAT_NVISIT   1
#define SQLITE_SCANSTAT_EST      2
#define SQLITE_SCANSTAT_NAME     3
#define SQLITE_SCANSTAT_EXPLAIN  4
#define SQLITE_SCANSTAT_SELECTID 5
#define SQLITE_SCANSTAT_PARENTID 6
#define SQLITE_SCANSTAT_NCYCLE   7

/*
** CAPI3REF: Prepared Statement Scan Status
** METHOD: sqlite3_stmt
**
** This interface returns information about the predicted and measured
** These interfaces return information about the predicted and measured
** performance for pStmt.  Advanced applications can use this
** interface to compare the predicted and the measured performance and
** issue warnings and/or rerun [ANALYZE] if discrepancies are found.
**
** Since this interface is expected to be rarely used, it is only
** available if SQLite is compiled using the [SQLITE_ENABLE_STMT_SCANSTATUS]
** compile-time option.
**
** The "iScanStatusOp" parameter determines which status information to return.
** The "iScanStatusOp" must be one of the [scanstatus options] or the behavior
** of this interface is undefined.
** ^The requested measurement is written into a variable pointed to by
** the "pOut" parameter.
** Parameter "idx" identifies the specific loop to retrieve statistics for.
** Loops are numbered starting from zero. ^If idx is out of range - less than
** zero or greater than or equal to the total number of loops used to implement
** the statement - a non-zero value is returned and the variable that pOut
** points to is unchanged.
** of this interface is undefined. ^The requested measurement is written into 
** a variable pointed to by the "pOut" parameter.
**
** The "flags" parameter must be passed a mask of flags. At present only
** one flag is defined - SQLITE_SCANSTAT_COMPLEX. If SQLITE_SCANSTAT_COMPLEX
** is specified, then status information is available for all elements 
** of a query plan that are reported by "EXPLAIN QUERY PLAN" output. If
** SQLITE_SCANSTAT_COMPLEX is not specified, then only query plan elements
** that correspond to query loops (the "SCAN..." and "SEARCH..." elements of
** the EXPLAIN QUERY PLAN output) are available. Invoking API
** sqlite3_stmt_scanstatus() is equivalent to calling 
** sqlite3_stmt_scanstatus_v2() with a zeroed flags parameter.
** 
** Parameter "idx" identifies the specific query element to retrieve statistics
** for. Query elements are numbered starting from zero. A value of -1 may be
** to query for statistics regarding the entire query. ^If idx is out of range
** - less than -1 or greater than or equal to the total number of query 
** elements used to implement the statement - a non-zero value is returned and
** the variable that pOut points to is unchanged.
**
** ^Statistics might not be available for all loops in all statements. ^In cases
** where there exist loops with no available statistics, this function behaves
** as if the loop did not exist - it returns non-zero and leave the variable
** that pOut points to unchanged.
**
** See also: [sqlite3_stmt_scanstatus_reset()]
*/
int sqlite3_stmt_scanstatus(
  sqlite3_stmt *pStmt,      /* Prepared statement for which info desired */
  int idx,                  /* Index of loop to report on */
  int iScanStatusOp,        /* Information desired.  SQLITE_SCANSTAT_* */
  void *pOut                /* Result written here */
);     
int sqlite3_stmt_scanstatus_v2(
  sqlite3_stmt *pStmt,      /* Prepared statement for which info desired */
  int idx,                  /* Index of loop to report on */
  int iScanStatusOp,        /* Information desired.  SQLITE_SCANSTAT_* */
  int flags,                /* Mask of flags defined below */
  void *pOut                /* Result written here */
);     

/*
** CAPI3REF: Prepared Statement Scan Status
** KEYWORDS: {scan status flags}
*/
#define SQLITE_SCANSTAT_COMPLEX 0x0001

/*
** CAPI3REF: Zero Scan-Status Counters
** METHOD: sqlite3_stmt
**
** ^Zero all [sqlite3_stmt_scanstatus()] related event counters.
**
** This API is only available if the library is built with pre-processor
** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined.
*/
void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);

/*
** CAPI3REF: Flush caches to disk mid-transaction
** METHOD: sqlite3
**
** ^If a write-transaction is open on [database connection] D when the
** [sqlite3_db_cacheflush(D)] interface invoked, any dirty
** pages in the pager-cache that are not currently in use are written out 
** to disk. A dirty page may be in use if a database cursor created by an
** active SQL statement is reading from it, or if it is page 1 of a database
** file (page 1 is always "in use").  ^The [sqlite3_db_cacheflush(D)]
8885
8886
8887
8888
8889
8890
8891

8892
8893
8894
8895
8896
8897
8898
8899
8900
8901
8902
8903
8904
8905
8906
8907
8908
8909

8910
8911
8912
8913
8914
8915
8916
10076
10077
10078
10079
10080
10081
10082
10083
10084
10085
10086
10087
10088
10089
10090
10091
10092
10093
10094
10095
10096
10097
10098
10099
10100

10101
10102
10103
10104
10105
10106
10107
10108







+

















-
+







** ^This function does not set the database handle error code or message
** returned by the [sqlite3_errcode()] and [sqlite3_errmsg()] functions.
*/
int sqlite3_db_cacheflush(sqlite3*);

/*
** CAPI3REF: The pre-update hook.
** METHOD: sqlite3
**
** ^These interfaces are only available if SQLite is compiled using the
** [SQLITE_ENABLE_PREUPDATE_HOOK] compile-time option.
**
** ^The [sqlite3_preupdate_hook()] interface registers a callback function
** that is invoked prior to each [INSERT], [UPDATE], and [DELETE] operation
** on a database table.
** ^At most one preupdate hook may be registered at a time on a single
** [database connection]; each call to [sqlite3_preupdate_hook()] overrides
** the previous setting.
** ^The preupdate hook is disabled by invoking [sqlite3_preupdate_hook()]
** with a NULL pointer as the second parameter.
** ^The third parameter to [sqlite3_preupdate_hook()] is passed through as
** the first parameter to callbacks.
**
** ^The preupdate hook only fires for changes to real database tables; the
** preupdate hook is not invoked for changes to [virtual tables] or to
** system tables like sqlite_master or sqlite_stat1.
** system tables like sqlite_sequence or sqlite_stat1.
**
** ^The second parameter to the preupdate callback is a pointer to
** the [database connection] that registered the preupdate hook.
** ^The third parameter to the preupdate callback is one of the constants
** [SQLITE_INSERT], [SQLITE_DELETE], or [SQLITE_UPDATE] to identify the
** kind of update operation that is about to occur.
** ^(The fourth parameter to the preupdate callback is the name of the
8925
8926
8927
8928
8929
8930
8931
8932





8933
8934
8935
8936
8937
8938
8939
10117
10118
10119
10120
10121
10122
10123

10124
10125
10126
10127
10128
10129
10130
10131
10132
10133
10134
10135







-
+
+
+
+
+







** parameter passed to the preupdate callback is the initial [rowid] of the 
** row being modified or deleted. For an INSERT operation on a rowid table,
** or any operation on a WITHOUT ROWID table, the value of the sixth 
** parameter is undefined. For an INSERT or UPDATE on a rowid table the
** seventh parameter is the final rowid value of the row being inserted
** or updated. The value of the seventh parameter passed to the callback
** function is not defined for operations on WITHOUT ROWID tables, or for
** INSERT operations on rowid tables.
** DELETE operations on rowid tables.
**
** ^The sqlite3_update_hook(D,C,P) function returns the P argument from
** the previous call on the same [database connection] D, or NULL for
** the first call on D.
**
** The [sqlite3_preupdate_old()], [sqlite3_preupdate_new()],
** [sqlite3_preupdate_count()], and [sqlite3_preupdate_depth()] interfaces
** provide additional information about a preupdate event. These routines
** may only be called from within a preupdate callback.  Invoking any of
** these routines from outside of a preupdate callback or with a
** [database connection] pointer that is different from the one supplied
8963
8964
8965
8966
8967
8968
8969









8970
8971
8972
8973
8974
8975
8976
8977
8978
8979
8980
8981
8982
8983
8984
8985
8986
8987
8988
8989

8990
8991
8992
8993

8994
8995
8996
8997
8998
8999
9000
10159
10160
10161
10162
10163
10164
10165
10166
10167
10168
10169
10170
10171
10172
10173
10174
10175
10176
10177
10178
10179
10180
10181
10182
10183
10184
10185
10186
10187
10188
10189
10190
10191
10192
10193
10194
10195
10196
10197
10198
10199
10200
10201
10202
10203
10204
10205
10206
10207







+
+
+
+
+
+
+
+
+




















+




+







**
** ^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
** number that caused the most recent I/O error or failure to open a file.
** The return value is OS-dependent.  For example, on unix systems, after
** [sqlite3_open_v2()] returns [SQLITE_CANTOPEN], this interface could be
** called to get back the underlying "errno" that caused the problem, such
** as ENOSPC, EAUTH, EISDIR, and so forth.  
9245
9246
9247
9248
9249
9250
9251
9252
9253


9254
9255
9256
9257
9258
9259
9260
10452
10453
10454
10455
10456
10457
10458


10459
10460
10461
10462
10463
10464
10465
10466
10467







-
-
+
+







** SQLITE_SERIALIZE_NOCOPY bit is set but no contiguous copy
** of the database exists.
**
** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the
** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory
** allocation error occurs.
**
** This interface is only available if SQLite is compiled with the
** [SQLITE_ENABLE_DESERIALIZE] option.
** This interface is omitted if SQLite is compiled with the
** [SQLITE_OMIT_DESERIALIZE] option.
*/
unsigned char *sqlite3_serialize(
  sqlite3 *db,           /* The database connection */
  const char *zSchema,   /* Which DB to serialize. ex: "main", "temp", ... */
  sqlite3_int64 *piSize, /* Write size of the DB here, if not NULL */
  unsigned int mFlags    /* Zero or more SQLITE_SERIALIZE_* flags */
);
9292
9293
9294
9295
9296
9297
9298




9299
9300
9301
9302
9303
9304
9305


9306
9307
9308
9309
9310
9311
9312
10499
10500
10501
10502
10503
10504
10505
10506
10507
10508
10509
10510
10511
10512
10513
10514


10515
10516
10517
10518
10519
10520
10521
10522
10523







+
+
+
+





-
-
+
+







** connection closes.  If the SQLITE_DESERIALIZE_RESIZEABLE bit is set, then
** SQLite will try to increase the buffer size using sqlite3_realloc64()
** if writes on the database cause it to grow larger than M bytes.
**
** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the
** database is currently in a read transaction or is involved in a backup
** operation.
**
** It is not possible to deserialized into the TEMP database.  If the
** S argument to sqlite3_deserialize(D,S,P,N,M,F) is "temp" then the
** function returns SQLITE_ERROR.
**
** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the 
** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then
** [sqlite3_free()] is invoked on argument P prior to returning.
**
** This interface is only available if SQLite is compiled with the
** [SQLITE_ENABLE_DESERIALIZE] option.
** This interface is omitted if SQLite is compiled with the
** [SQLITE_OMIT_DESERIALIZE] option.
*/
int sqlite3_deserialize(
  sqlite3 *db,            /* The database connection */
  const char *zSchema,    /* Which DB to reopen with the deserialization */
  unsigned char *pData,   /* The serialized database content */
  sqlite3_int64 szDb,     /* Number bytes in the deserialization */
  sqlite3_int64 szBuf,    /* Total size of buffer pData[] */

Changes to src/sqlite3ext.h.

315
316
317
318
319
320
321










































322
323
324
325
326
327
328
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







                            void (*xStep)(sqlite3_context*,int,sqlite3_value**),
                            void (*xFinal)(sqlite3_context*),
                            void (*xValue)(sqlite3_context*),
                            void (*xInv)(sqlite3_context*,int,sqlite3_value**),
                            void(*xDestroy)(void*));
  /* Version 3.26.0 and later */
  const char *(*normalized_sql)(sqlite3_stmt*);
  /* Version 3.28.0 and later */
  int (*stmt_isexplain)(sqlite3_stmt*);
  int (*value_frombind)(sqlite3_value*);
  /* Version 3.30.0 and later */
  int (*drop_modules)(sqlite3*,const char**);
  /* Version 3.31.0 and later */
  sqlite3_int64 (*hard_heap_limit64)(sqlite3_int64);
  const char *(*uri_key)(const char*,int);
  const char *(*filename_database)(const char*);
  const char *(*filename_journal)(const char*);
  const char *(*filename_wal)(const char*);
  /* Version 3.32.0 and later */
  const char *(*create_filename)(const char*,const char*,const char*,
                           int,const char**);
  void (*free_filename)(const char*);
  sqlite3_file *(*database_file_object)(const char*);
  /* Version 3.34.0 and later */
  int (*txn_state)(sqlite3*,const char*);
  /* Version 3.36.1 and later */
  sqlite3_int64 (*changes64)(sqlite3*);
  sqlite3_int64 (*total_changes64)(sqlite3*);
  /* Version 3.37.0 and later */
  int (*autovacuum_pages)(sqlite3*,
     unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int),
     void*, void(*)(void*));
  /* Version 3.38.0 and later */
  int (*error_offset)(sqlite3*);
  int (*vtab_rhs_value)(sqlite3_index_info*,int,sqlite3_value**);
  int (*vtab_distinct)(sqlite3_index_info*);
  int (*vtab_in)(sqlite3_index_info*,int,int);
  int (*vtab_in_first)(sqlite3_value*,sqlite3_value**);
  int (*vtab_in_next)(sqlite3_value*,sqlite3_value**);
  /* Version 3.39.0 and later */
  int (*deserialize)(sqlite3*,const char*,unsigned char*,
                     sqlite3_int64,sqlite3_int64,unsigned);
  unsigned char *(*serialize)(sqlite3*,const char *,sqlite3_int64*,
                              unsigned int);
  const char *(*db_name)(sqlite3*,int);
  /* Version 3.40.0 and later */
  int (*value_encoding)(sqlite3_value*);
  /* Version 3.41.0 and later */
  int (*is_interrupted)(sqlite3*);
};

/*
** This is the function signature used for all extension entry points.  It
** is also defined in the file "loadext.c".
*/
typedef int (*sqlite3_loadext_entry)(
604
605
606
607
608
609
610







































611
612
613
614
615
616
617
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







#define sqlite3_str_errcode            sqlite3_api->str_errcode
#define sqlite3_str_length             sqlite3_api->str_length
#define sqlite3_str_value              sqlite3_api->str_value
/* Version 3.25.0 and later */
#define sqlite3_create_window_function sqlite3_api->create_window_function
/* Version 3.26.0 and later */
#define sqlite3_normalized_sql         sqlite3_api->normalized_sql
/* Version 3.28.0 and later */
#define sqlite3_stmt_isexplain         sqlite3_api->stmt_isexplain
#define sqlite3_value_frombind         sqlite3_api->value_frombind
/* Version 3.30.0 and later */
#define sqlite3_drop_modules           sqlite3_api->drop_modules
/* Version 3.31.0 and later */
#define sqlite3_hard_heap_limit64      sqlite3_api->hard_heap_limit64
#define sqlite3_uri_key                sqlite3_api->uri_key
#define sqlite3_filename_database      sqlite3_api->filename_database
#define sqlite3_filename_journal       sqlite3_api->filename_journal
#define sqlite3_filename_wal           sqlite3_api->filename_wal
/* Version 3.32.0 and later */
#define sqlite3_create_filename        sqlite3_api->create_filename
#define sqlite3_free_filename          sqlite3_api->free_filename
#define sqlite3_database_file_object   sqlite3_api->database_file_object
/* Version 3.34.0 and later */
#define sqlite3_txn_state              sqlite3_api->txn_state
/* Version 3.36.1 and later */
#define sqlite3_changes64              sqlite3_api->changes64
#define sqlite3_total_changes64        sqlite3_api->total_changes64
/* Version 3.37.0 and later */
#define sqlite3_autovacuum_pages       sqlite3_api->autovacuum_pages
/* Version 3.38.0 and later */
#define sqlite3_error_offset           sqlite3_api->error_offset
#define sqlite3_vtab_rhs_value         sqlite3_api->vtab_rhs_value
#define sqlite3_vtab_distinct          sqlite3_api->vtab_distinct
#define sqlite3_vtab_in                sqlite3_api->vtab_in
#define sqlite3_vtab_in_first          sqlite3_api->vtab_in_first
#define sqlite3_vtab_in_next           sqlite3_api->vtab_in_next
/* Version 3.39.0 and later */
#ifndef SQLITE_OMIT_DESERIALIZE
#define sqlite3_deserialize            sqlite3_api->deserialize
#define sqlite3_serialize              sqlite3_api->serialize
#endif
#define sqlite3_db_name                sqlite3_api->db_name
/* Version 3.40.0 and later */
#define sqlite3_value_encoding         sqlite3_api->value_encoding
/* Version 3.41.0 and later */
#define sqlite3_is_interrupted         sqlite3_api->is_interrupted
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */

#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
  /* This case when the file really is being compiled as a loadable 
  ** extension */
# define SQLITE_EXTENSION_INIT1     const sqlite3_api_routines *sqlite3_api=0;
# define SQLITE_EXTENSION_INIT2(v)  sqlite3_api=v;

Changes to src/sqliteInt.h.

115
116
117
118
119
120
121












122
123
124
125
126
127
128
129
130









131
132
133
134
135
136
137
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







+
+
+
+
+
+
+
+
+
+
+
+









+
+
+
+
+
+
+
+
+







#endif
#if defined(_MSC_VER) && !defined(SQLITE_DISABLE_INTRINSIC)
# define MSVC_VERSION _MSC_VER
#else
# define MSVC_VERSION 0
#endif

/*
** Some C99 functions in "math.h" are only present for MSVC when its version
** is associated with Visual Studio 2013 or higher.
*/
#ifndef SQLITE_HAVE_C99_MATH_FUNCS
# if MSVC_VERSION==0 || MSVC_VERSION>=1800
#  define SQLITE_HAVE_C99_MATH_FUNCS (1)
# else
#  define SQLITE_HAVE_C99_MATH_FUNCS (0)
# endif
#endif

/* Needed for various definitions... */
#if defined(__GNUC__) && !defined(_GNU_SOURCE)
# define _GNU_SOURCE
#endif

#if defined(__OpenBSD__) && !defined(_BSD_SOURCE)
# define _BSD_SOURCE
#endif

/*
** Macro to disable warnings about missing "break" at the end of a "case".
*/
#if GCC_VERSION>=7000000
# define deliberate_fall_through __attribute__((fallthrough));
#else
# define deliberate_fall_through
#endif

/*
** For MinGW, check to see if we can include the header file containing its
** version information, among other things.  Normally, this internal MinGW
** header file would [only] be included automatically by other MinGW header
** files; however, the contained version information is now required by this
** header file to work around binary compatibility issues (see below) and
** this is the only known way to reliably obtain it.  This entire #if block
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
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







+
+
+
+
+
+
+
+
+
+
+







+
+
+
+
+





-
+














+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







*/
#if !defined(_USE_32BIT_TIME_T) && !defined(_USE_64BIT_TIME_T) && \
    defined(_WIN32) && !defined(_WIN64) && \
    defined(__MINGW_MAJOR_VERSION) && __MINGW_MAJOR_VERSION >= 4 && \
    defined(__MSVCRT__)
# define _USE_32BIT_TIME_T
#endif

/* Optionally #include a user-defined header, whereby compilation options
** may be set prior to where they take effect, but after platform setup. 
** If SQLITE_CUSTOM_INCLUDE=? is defined, its value names the #include
** file.
*/
#ifdef SQLITE_CUSTOM_INCLUDE
# define INC_STRINGIFY_(f) #f
# define INC_STRINGIFY(f) INC_STRINGIFY_(f)
# include INC_STRINGIFY(SQLITE_CUSTOM_INCLUDE)
#endif

/* The public SQLite interface.  The _FILE_OFFSET_BITS macro must appear
** first in QNX.  Also, the _USE_32BIT_TIME_T macro must appear first for
** MinGW.
*/
#include "sqlite3.h"

/*
** Reuse the STATIC_LRU for mutex access to sqlite3_temp_directory.
*/
#define SQLITE_MUTEX_STATIC_TEMPDIR SQLITE_MUTEX_STATIC_VFS1

/*
** Include the configuration header output by 'configure' if we're using the
** autoconf-based build
*/
#if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H)
#include "config.h"
#include "sqlite_cfg.h"
#define SQLITECONFIG_H 1
#endif

#include "sqliteLimit.h"

/* Disable nuisance warnings on Borland compilers */
#if defined(__BORLANDC__)
#pragma warn -rch /* unreachable code */
#pragma warn -ccc /* Condition is always true or false */
#pragma warn -aus /* Assigned value is never used */
#pragma warn -csu /* Comparing signed and unsigned */
#pragma warn -spa /* Suspicious pointer arithmetic */
#endif

/*
** WAL mode depends on atomic aligned 32-bit loads and stores in a few
** places.  The following macros try to make this explicit.
*/
#ifndef __has_extension
# define __has_extension(x) 0     /* compatibility with non-clang compilers */
#endif
#if GCC_VERSION>=4007000 || __has_extension(c_atomic) 
# define SQLITE_ATOMIC_INTRINSICS 1
# define AtomicLoad(PTR)       __atomic_load_n((PTR),__ATOMIC_RELAXED)
# define AtomicStore(PTR,VAL)  __atomic_store_n((PTR),(VAL),__ATOMIC_RELAXED)
#else
# define SQLITE_ATOMIC_INTRINSICS 0
# define AtomicLoad(PTR)       (*(PTR))
# define AtomicStore(PTR,VAL)  (*(PTR) = (VAL))
#endif

/*
** Include standard header files as necessary
*/
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#ifdef HAVE_INTTYPES_H
208
209
210
211
212
213
214



215

216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
262
263
264
265
266
267
268
269
270
271

272
273
274
275
276
277



278
279
280
281
282
283
284







+
+
+
-
+





-
-
-







** that vary from one machine to the next.
**
** Ticket #3860:  The llvm-gcc-4.2 compiler from Apple chokes on
** the ((void*)&((char*)0)[X]) construct.  But MSVC chokes on ((void*)(X)).
** So we have to define the macros in different ways depending on the
** compiler.
*/
#if defined(HAVE_STDINT_H)   /* Use this case if we have ANSI headers */
# define SQLITE_INT_TO_PTR(X)  ((void*)(intptr_t)(X))
# define SQLITE_PTR_TO_INT(X)  ((int)(intptr_t)(X))
#if defined(__PTRDIFF_TYPE__)  /* This case should work for GCC */
#elif defined(__PTRDIFF_TYPE__)  /* This case should work for GCC */
# define SQLITE_INT_TO_PTR(X)  ((void*)(__PTRDIFF_TYPE__)(X))
# define SQLITE_PTR_TO_INT(X)  ((int)(__PTRDIFF_TYPE__)(X))
#elif !defined(__GNUC__)       /* Works for compilers other than LLVM */
# define SQLITE_INT_TO_PTR(X)  ((void*)&((char*)0)[X])
# define SQLITE_PTR_TO_INT(X)  ((int)(((char*)X)-(char*)0))
#elif defined(HAVE_STDINT_H)   /* Use this case if we have ANSI headers */
# define SQLITE_INT_TO_PTR(X)  ((void*)(intptr_t)(X))
# define SQLITE_PTR_TO_INT(X)  ((int)(intptr_t)(X))
#else                          /* Generates a warning - but it always works */
# define SQLITE_INT_TO_PTR(X)  ((void*)(X))
# define SQLITE_PTR_TO_INT(X)  ((int)(X))
#endif

/*
** A macro to hint to the compiler that a function should not be
382
383
384
385
386
387
388
389
390
391
392
393





394
395
396
397
398
399
400
436
437
438
439
440
441
442

443



444
445
446
447
448
449
450
451
452
453
454
455







-

-
-
-
+
+
+
+
+







** to help ensure adequate test coverage in places where simple
** condition/decision coverage is inadequate.  For example, testcase()
** can be used to make sure boundary values are tested.  For
** bitmask tests, testcase() can be used to make sure each bit
** is significant and used at least once.  On switch statements
** where multiple cases go to the same block of code, testcase()
** can insure that all cases are evaluated.
**
*/
#ifdef SQLITE_COVERAGE_TEST
  void sqlite3Coverage(int);
# define testcase(X)  if( X ){ sqlite3Coverage(__LINE__); }
#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG)
# ifndef SQLITE_AMALGAMATION
    extern unsigned int sqlite3CoverageCounter;
# endif
# define testcase(X)  if( X ){ sqlite3CoverageCounter += (unsigned)__LINE__; }
#else
# define testcase(X)
#endif

/*
** The TESTONLY macro is used to enclose variable declarations or
** other bits of code that are needed to support the arguments
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
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







+
+
+
+
+
+
+
+















-
+







*/
#ifndef NDEBUG
# define VVA_ONLY(X)  X
#else
# define VVA_ONLY(X)
#endif

/*
** Disable ALWAYS() and NEVER() (make them pass-throughs) for coverage
** and mutation testing
*/
#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
# define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS  1
#endif

/*
** The ALWAYS and NEVER macros surround boolean expressions which
** are intended to always be true or false, respectively.  Such
** expressions could be omitted from the code completely.  But they
** are included in a few cases in order to enhance the resilience
** of SQLite to unexpected behavior - to make the code "self-healing"
** or "ductile" rather than being "brittle" and crashing at the first
** hint of unplanned behavior.
**
** In other words, ALWAYS and NEVER are added for defensive code.
**
** When doing coverage testing ALWAYS and NEVER are hard-coded to
** be true and false so that the unreachable code they specify will
** not be counted as untested code.
*/
#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
#if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
# define ALWAYS(X)      (1)
# define NEVER(X)       (0)
#elif !defined(NDEBUG)
# define ALWAYS(X)      ((X)?1:(assert(0),0))
# define NEVER(X)       ((X)?(assert(0),1):0)
#else
# define ALWAYS(X)      (X)
505
506
507
508
509
510
511







512
513
514
515
516
517
518
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588







+
+
+
+
+
+
+







/*
** SQLITE_ENABLE_EXPLAIN_COMMENTS is incompatible with SQLITE_OMIT_EXPLAIN
*/
#ifdef SQLITE_OMIT_EXPLAIN
# undef SQLITE_ENABLE_EXPLAIN_COMMENTS
#endif

/*
** SQLITE_OMIT_VIRTUALTABLE implies SQLITE_OMIT_ALTERTABLE
*/
#if defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_ALTERTABLE)
# define SQLITE_OMIT_ALTERTABLE
#endif

/*
** Return true (non-zero) if the input is an integer that is too large
** to fit in 32-bits.  This macro is used inside of various testcase()
** macros to verify that we have tested SQLite for large-file support.
*/
#define IS_BIG_INT(X)  (((X)&~(i64)0xffffffff)!=0)

626
627
628
629
630
631
632
633

634
635
636
637
638
639
640
696
697
698
699
700
701
702

703
704
705
706
707
708
709
710







-
+








/*
** The default initial allocation for the pagecache when using separate
** pagecaches for each database connection.  A positive number is the
** number of pages.  A negative number N translations means that a buffer
** of -1024*N bytes is allocated and used for as many pages as it will hold.
**
** The default value of "20" was choosen to minimize the run-time of the
** The default value of "20" was chosen to minimize the run-time of the
** speedtest1 test program with options: --shrink-memory --reprepare
*/
#ifndef SQLITE_DEFAULT_PCACHE_INITSZ
# define SQLITE_DEFAULT_PCACHE_INITSZ 20
#endif

/*
788
789
790
791
792
793
794

795
796
797
798
799
800
801
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872







+







** Set the SQLITE_PTRSIZE macro to the number of bytes in a pointer
*/
#ifndef SQLITE_PTRSIZE
# if defined(__SIZEOF_POINTER__)
#   define SQLITE_PTRSIZE __SIZEOF_POINTER__
# elif defined(i386)     || defined(__i386__)   || defined(_M_IX86) ||    \
       defined(_M_ARM)   || defined(__arm__)    || defined(__x86)   ||    \
      (defined(__APPLE__) && defined(__POWERPC__)) ||                     \
      (defined(__TOS_AIX__) && !defined(__64BIT__))
#   define SQLITE_PTRSIZE 4
# else
#   define SQLITE_PTRSIZE 8
# endif
#endif

826
827
828
829
830
831
832
833
834
835
836




837
838


839
840
841
842
843
844
845
897
898
899
900
901
902
903




904
905
906
907
908

909
910
911
912
913
914
915
916
917







-
-
-
-
+
+
+
+

-
+
+







**
** For best performance, an attempt is made to guess at the byte-order
** using C-preprocessor macros.  If that is unsuccessful, or if
** -DSQLITE_BYTEORDER=0 is set, then byte-order is determined
** at run-time.
*/
#ifndef SQLITE_BYTEORDER
# if defined(i386)     || defined(__i386__)   || defined(_M_IX86) ||    \
     defined(__x86_64) || defined(__x86_64__) || defined(_M_X64)  ||    \
     defined(_M_AMD64) || defined(_M_ARM)     || defined(__x86)   ||    \
     defined(__arm__)  || defined(_M_ARM64)
# if defined(i386)      || defined(__i386__)      || defined(_M_IX86) ||    \
     defined(__x86_64)  || defined(__x86_64__)    || defined(_M_X64)  ||    \
     defined(_M_AMD64)  || defined(_M_ARM)        || defined(__x86)   ||    \
     defined(__ARMEL__) || defined(__AARCH64EL__) || defined(_M_ARM64)
#   define SQLITE_BYTEORDER    1234
# elif defined(sparc)    || defined(__ppc__)
# elif defined(sparc)     || defined(__ppc__) || \
       defined(__ARMEB__) || defined(__AARCH64EB__)
#   define SQLITE_BYTEORDER    4321
# else
#   define SQLITE_BYTEORDER 0
# endif
#endif
#if SQLITE_BYTEORDER==4321
# define SQLITE_BIGENDIAN    1
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
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975

976
977

978
979
980
981
982
983
984
985







+





+
+
+
+
+
+


+
+
+
+
+
















-
+

-
+








/*
** Constants for the largest and smallest possible 64-bit signed integers.
** These macros are designed to work correctly on both 32-bit and 64-bit
** compilers.
*/
#define LARGEST_INT64  (0xffffffff|(((i64)0x7fffffff)<<32))
#define LARGEST_UINT64 (0xffffffff|(((u64)0xffffffff)<<32))
#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64)

/*
** Round up a number to the next larger multiple of 8.  This is used
** to force 8-byte alignment on 64-bit architectures.
**
** ROUND8() always does the rounding, for any argument.
**
** ROUND8P() assumes that the argument is already an integer number of
** pointers in size, and so it is a no-op on systems where the pointer
** size is 8.
*/
#define ROUND8(x)     (((x)+7)&~7)
#if SQLITE_PTRSIZE==8
# define ROUND8P(x)   (x)
#else
# define ROUND8P(x)   (((x)+7)&~7)
#endif

/*
** Round down to the nearest multiple of 8
*/
#define ROUNDDOWN8(x) ((x)&~7)

/*
** Assert that the pointer X is aligned to an 8-byte boundary.  This
** macro is used only within assert() to verify that the code gets
** all alignment restrictions correct.
**
** Except, if SQLITE_4_BYTE_ALIGNED_MALLOC is defined, then the
** underlying malloc() implementation might return us 4-byte aligned
** pointers.  In that case, only verify 4-byte alignment.
*/
#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
# define EIGHT_BYTE_ALIGNMENT(X)   ((((char*)(X) - (char*)0)&3)==0)
# define EIGHT_BYTE_ALIGNMENT(X)   ((((uptr)(X) - (uptr)0)&3)==0)
#else
# define EIGHT_BYTE_ALIGNMENT(X)   ((((char*)(X) - (char*)0)&7)==0)
# define EIGHT_BYTE_ALIGNMENT(X)   ((((uptr)(X) - (uptr)0)&7)==0)
#endif

/*
** Disable MMAP on platforms where it is known to not work
*/
#if defined(__OpenBSD__) || defined(__QNXNTO__)
# undef SQLITE_MAX_MMAP_SIZE
931
932
933
934
935
936
937
938
939


940
941
942
943
944
945
946
947
948














949
950























951
952
953

954

955
956




957
958

959































960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981















982
983
984




985

986
987

988
989

990
991
992

993
994


995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015

1016
1017
1018
1019
1020
1021
1022
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







-
-
+
+
-

-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+

+
-
-
+
+
+
+

-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+















-



-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+
+
+

+

-
+

-
+


-
+

-
+
+




















-
+







#endif
#if SQLITE_DEFAULT_MMAP_SIZE>SQLITE_MAX_MMAP_SIZE
# undef SQLITE_DEFAULT_MMAP_SIZE
# define SQLITE_DEFAULT_MMAP_SIZE SQLITE_MAX_MMAP_SIZE
#endif

/*
** Only one of SQLITE_ENABLE_STAT3 or SQLITE_ENABLE_STAT4 can be defined.
** Priority is given to SQLITE_ENABLE_STAT4.  If either are defined, also
** TREETRACE_ENABLED will be either 1 or 0 depending on whether or not
** the Abstract Syntax Tree tracing logic is turned on.
** define SQLITE_ENABLE_STAT3_OR_STAT4
*/
#ifdef SQLITE_ENABLE_STAT4
# undef SQLITE_ENABLE_STAT3
# define SQLITE_ENABLE_STAT3_OR_STAT4 1
#elif SQLITE_ENABLE_STAT3
# define SQLITE_ENABLE_STAT3_OR_STAT4 1
#elif SQLITE_ENABLE_STAT3_OR_STAT4
# undef SQLITE_ENABLE_STAT3_OR_STAT4
#if !defined(SQLITE_AMALGAMATION)
extern u32 sqlite3TreeTrace;
#endif
#if defined(SQLITE_DEBUG) \
    && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_SELECTTRACE) \
                             || defined(SQLITE_ENABLE_TREETRACE))
# define TREETRACE_ENABLED 1
# define TREETRACE(K,P,S,X)  \
  if(sqlite3TreeTrace&(K))   \
    sqlite3DebugPrintf("%u/%d/%p: ",(S)->selId,(P)->addrExplain,(S)),\
    sqlite3DebugPrintf X
#else
# define TREETRACE(K,P,S,X)
# define TREETRACE_ENABLED 0
#endif

/* TREETRACE flag meanings:
**
**   0x00000001     Beginning and end of SELECT processing
**   0x00000002     WHERE clause processing
**   0x00000004     Query flattener
**   0x00000008     Result-set wildcard expansion
**   0x00000010     Query name resolution
**   0x00000020     Aggregate analysis
**   0x00000040     Window functions
**   0x00000080     Generated column names
**   0x00000100     Move HAVING terms into WHERE
**   0x00000200     Count-of-view optimization
**   0x00000400     Compound SELECT processing
**   0x00000800     Drop superfluous ORDER BY
**   0x00001000     LEFT JOIN simplifies to JOIN
**   0x00002000     Constant propagation
**   0x00004000     Push-down optimization
**   0x00008000     After all FROM-clause analysis
**   0x00010000     Beginning of DELETE/INSERT/UPDATE processing
**   0x00020000     Transform DISTINCT into GROUP BY
**   0x00040000     SELECT tree dump after all code has been generated
*/

/*
** SELECTTRACE_ENABLED will be either 1 or 0 depending on whether or not
** the Select query generator tracing logic is turned on.
** Macros for "wheretrace"
*/
extern u32 sqlite3WhereTrace;
#if defined(SQLITE_ENABLE_SELECTTRACE)
# define SELECTTRACE_ENABLED 1
#if defined(SQLITE_DEBUG) \
    && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE))
# define WHERETRACE(K,X)  if(sqlite3WhereTrace&(K)) sqlite3DebugPrintf X
# define WHERETRACE_ENABLED 1
#else
# define SELECTTRACE_ENABLED 0
# define WHERETRACE(K,X)
#endif

/*
** Bits for the sqlite3WhereTrace mask:
**
** (---any--)   Top-level block structure
** 0x-------F   High-level debug messages
** 0x----FFF-   More detail
** 0xFFFF----   Low-level debug messages
**
** 0x00000001   Code generation
** 0x00000002   Solver
** 0x00000004   Solver costs
** 0x00000008   WhereLoop inserts
**
** 0x00000010   Display sqlite3_index_info xBestIndex calls
** 0x00000020   Range an equality scan metrics
** 0x00000040   IN operator decisions
** 0x00000080   WhereLoop cost adjustements
** 0x00000100
** 0x00000200   Covering index decisions
** 0x00000400   OR optimization
** 0x00000800   Index scanner
** 0x00001000   More details associated with code generation
** 0x00002000
** 0x00004000   Show all WHERE terms at key points
** 0x00008000   Show the full SELECT statement at key places
**
** 0x00010000   Show more detail when printing WHERE terms
** 0x00020000   Show WHERE terms returned from whereScanNext()
*/


/*
** An instance of the following structure is used to store the busy-handler
** callback for a given sqlite handle.
**
** The sqlite.busyHandler member of the sqlite struct contains the busy
** callback for the database handle. Each pager opened via the sqlite
** handle is passed a pointer to sqlite.busyHandler. The busy-handler
** callback is currently invoked only from within pager.c.
*/
typedef struct BusyHandler BusyHandler;
struct BusyHandler {
  int (*xBusyHandler)(void *,int);  /* The busy callback */
  void *pBusyArg;                   /* First arg to busy callback */
  int nBusy;                        /* Incremented with each busy call */
  u8 bExtraFileArg;                 /* Include sqlite3_file as callback arg */
};

/*
** Name of the master database table.  The master database table
** is a special table that holds the names and attributes of all
** user tables and indices.
** Name of table that holds the database schema.
**
** The PREFERRED names are used whereever possible.  But LEGACY is also
** used for backwards compatibility.
**
**  1.  Queries can use either the PREFERRED or the LEGACY names
**  2.  The sqlite3_set_authorizer() callback uses the LEGACY name
**  3.  The PRAGMA table_list statement uses the PREFERRED name
**
** The LEGACY names are stored in the internal symbol hash table
** in support of (2).  Names are translated using sqlite3PreferredTableName()
** for (3).  The sqlite3FindTable() function takes care of translating
** names for (1).
**
** Note that "sqlite_temp_schema" can also be called "temp.sqlite_schema".
*/
#define MASTER_NAME       "sqlite_master"
#define TEMP_MASTER_NAME  "sqlite_temp_master"
#define LEGACY_SCHEMA_TABLE          "sqlite_master"
#define LEGACY_TEMP_SCHEMA_TABLE     "sqlite_temp_master"
#define PREFERRED_SCHEMA_TABLE       "sqlite_schema"
#define PREFERRED_TEMP_SCHEMA_TABLE  "sqlite_temp_schema"


/*
** The root-page of the master database table.
** The root-page of the schema table.
*/
#define MASTER_ROOT       1
#define SCHEMA_ROOT    1

/*
** The name of the schema table.
** The name of the schema table.  The name is different for TEMP.
*/
#define SCHEMA_TABLE(x)  ((!OMIT_TEMPDB)&&(x==1)?TEMP_MASTER_NAME:MASTER_NAME)
#define SCHEMA_TABLE(x) \
    ((!OMIT_TEMPDB)&&(x==1)?LEGACY_TEMP_SCHEMA_TABLE:LEGACY_SCHEMA_TABLE)

/*
** A convenience macro that returns the number of elements in
** an array.
*/
#define ArraySize(X)    ((int)(sizeof(X)/sizeof(X[0])))

/*
** Determine if the argument is a power of two
*/
#define IsPowerOfTwo(X) (((X)&((X)-1))==0)

/*
** The following value as a destructor means to use sqlite3DbFree().
** The sqlite3DbFree() routine requires two parameters instead of the
** one parameter that destructors normally want.  So we have to introduce
** this magic value that the code knows to handle differently.  Any
** pointer will work here as long as it is distinct from SQLITE_STATIC
** and SQLITE_TRANSIENT.
*/
#define SQLITE_DYNAMIC   ((sqlite3_destructor_type)sqlite3MallocSize)
#define SQLITE_DYNAMIC   ((sqlite3_destructor_type)sqlite3OomClear)

/*
** When SQLITE_OMIT_WSD is defined, it means that the target platform does
** not support Writable Static Data (WSD) such as global and static variables.
** All variables must either be on the stack or dynamically allocated from
** the heap.  When WSD is unsupported, the variable declarations scattered
** throughout the SQLite code must become constants instead.  The SQLITE_WSD
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
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







+
+

+



+






+







+

+



-
+





+







*/
typedef struct AggInfo AggInfo;
typedef struct AuthContext AuthContext;
typedef struct AutoincInfo AutoincInfo;
typedef struct Bitvec Bitvec;
typedef struct CollSeq CollSeq;
typedef struct Column Column;
typedef struct Cte Cte;
typedef struct CteUse CteUse;
typedef struct Db Db;
typedef struct DbFixer DbFixer;
typedef struct Schema Schema;
typedef struct Expr Expr;
typedef struct ExprList ExprList;
typedef struct FastPrng FastPrng;
typedef struct FKey FKey;
typedef struct FuncDestructor FuncDestructor;
typedef struct FuncDef FuncDef;
typedef struct FuncDefHash FuncDefHash;
typedef struct IdList IdList;
typedef struct Index Index;
typedef struct IndexedExpr IndexedExpr;
typedef struct IndexSample IndexSample;
typedef struct KeyClass KeyClass;
typedef struct KeyInfo KeyInfo;
typedef struct Lookaside Lookaside;
typedef struct LookasideSlot LookasideSlot;
typedef struct Module Module;
typedef struct NameContext NameContext;
typedef struct OnOrUsing OnOrUsing;
typedef struct Parse Parse;
typedef struct ParseCleanup ParseCleanup;
typedef struct PreUpdate PreUpdate;
typedef struct PrintfArguments PrintfArguments;
typedef struct RenameToken RenameToken;
typedef struct FastPrng FastPrng;
typedef struct Returning Returning;
typedef struct RowSet RowSet;
typedef struct Savepoint Savepoint;
typedef struct Select Select;
typedef struct SQLiteThread SQLiteThread;
typedef struct SelectDest SelectDest;
typedef struct SrcItem SrcItem;
typedef struct SrcList SrcList;
typedef struct sqlite3_str StrAccum; /* Internal alias for sqlite3_str */
typedef struct Table Table;
typedef struct TableLock TableLock;
typedef struct Token Token;
typedef struct TreeView TreeView;
typedef struct Trigger Trigger;
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
1300
1301
1302
1303
1304
1305
1306



1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326





1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338







-
-
-
+
+
+
+
+
+














-
-
-
-
-
+
+
+
+
+







** The number of bits in a Bitmask.  "BMS" means "BitMask Size".
*/
#define BMS  ((int)(sizeof(Bitmask)*8))

/*
** A bit in a Bitmask
*/
#define MASKBIT(n)   (((Bitmask)1)<<(n))
#define MASKBIT32(n) (((unsigned int)1)<<(n))
#define ALLBITS      ((Bitmask)-1)
#define MASKBIT(n)    (((Bitmask)1)<<(n))
#define MASKBIT64(n)  (((u64)1)<<(n))
#define MASKBIT32(n)  (((unsigned int)1)<<(n))
#define SMASKBIT32(n) ((n)<=31?((unsigned int)1)<<(n):0)
#define ALLBITS       ((Bitmask)-1)
#define TOPBIT        (((Bitmask)1)<<(BMS-1))

/* A VList object records a mapping between parameters/variables/wildcards
** in the SQL statement (such as $abc, @pqr, or :xyz) and the integer
** variable number associated with that parameter.  See the format description
** on the sqlite3VListAdd() routine for more information.  A VList is really
** just an array of integers.
*/
typedef int VList;

/*
** Defer sourcing vdbe.h and btree.h until after the "u8" and
** "BusyHandler" typedefs. vdbe.h also requires a few of the opaque
** pointer types (i.e. FuncDef) defined above.
*/
#include "btree.h"
#include "vdbe.h"
#include "pager.h"
#include "pcache.h"
#include "os.h"
#include "os.h"
#include "pager.h"
#include "btree.h"
#include "vdbe.h"
#include "pcache.h"
#include "mutex.h"

/* The SQLITE_EXTRA_DURABLE compile-time option used to set the default
** synchronous setting to EXTRA.  It is no longer supported.
*/
#ifdef SQLITE_EXTRA_DURABLE
# warning Use SQLITE_DEFAULT_SYNCHRONOUS=3 instead of SQLITE_EXTRA_DURABLE
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1433
1434
1435
1436
1437
1438
1439

1440
1441
1442
1443
1444
1445
1446







-







**
** DB_UnresetViews means that one or more views have column names that
** have been filled out.  If the schema changes, these column names might
** changes and so the view will need to be reset.
*/
#define DB_SchemaLoaded    0x0001  /* The schema has been loaded */
#define DB_UnresetViews    0x0002  /* Some views have defined column names */
#define DB_Empty           0x0004  /* The file is empty (length 0 bytes) */
#define DB_ResetWanted     0x0008  /* Reset the schema when nSchemaLock==0 */

/*
** The number of different kinds of things that can be limited
** using the sqlite3_limit() interface.
*/
#define SQLITE_N_LIMIT (SQLITE_LIMIT_WORKER_THREADS+1)
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
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




+





+
+
+
+
+
+


+




+
+
+
+
+
+
+
+
+
+
+







**
** Lookaside allocations are only allowed for objects that are associated
** with a particular database connection.  Hence, schema information cannot
** be stored in lookaside because in shared cache mode the schema information
** is shared by multiple database connections.  Therefore, while parsing
** schema information, the Lookaside.bEnabled flag is cleared so that
** lookaside allocations are not used to construct the schema objects.
**
** New lookaside allocations are only allowed if bDisable==0.  When
** bDisable is greater than zero, sz is set to zero which effectively
** disables lookaside without adding a new test for the bDisable flag
** in a performance-critical path.  sz should be set by to szTrue whenever
** bDisable changes back to zero.
**
** Lookaside buffers are initially held on the pInit list.  As they are
** used and freed, they are added back to the pFree list.  New allocations
** come off of pFree first, then pInit as a fallback.  This dual-list
** allows use to compute a high-water mark - the maximum number of allocations
** outstanding at any point in the past - by subtracting the number of
** allocations on the pInit list from the total number of allocations.
**
** Enhancement on 2019-12-12:  Two-size-lookaside
** The default lookaside configuration is 100 slots of 1200 bytes each.
** The larger slot sizes are important for performance, but they waste
** a lot of space, as most lookaside allocations are less than 128 bytes.
** The two-size-lookaside enhancement breaks up the lookaside allocation
** into two pools:  One of 128-byte slots and the other of the default size
** (1200-byte) slots.   Allocations are filled from the small-pool first,
** failing over to the full-size pool if that does not work.  Thus more
** lookaside slots are available while also using less memory.
** This enhancement can be omitted by compiling with
** SQLITE_OMIT_TWOSIZE_LOOKASIDE.
*/
struct Lookaside {
  u32 bDisable;           /* Only operate the lookaside when zero */
  u16 sz;                 /* Size of each buffer in bytes */
  u16 szTrue;             /* True value of sz, even if disabled */
  u8 bMalloced;           /* True if pStart obtained from sqlite3_malloc() */
  u32 nSlot;              /* Number of lookaside slots allocated */
  u32 anStat[3];          /* 0: hits.  1: size misses.  2: full misses */
  LookasideSlot *pInit;   /* List of buffers not previously used */
  LookasideSlot *pFree;   /* List of available buffers */
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
  LookasideSlot *pSmallInit; /* List of small buffers not prediously used */
  LookasideSlot *pSmallFree; /* List of available small buffers */
  void *pMiddle;          /* First byte past end of full-size buffers and
                          ** the first byte of LOOKASIDE_SMALL buffers */
#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
  void *pStart;           /* First byte of available memory space */
  void *pEnd;             /* First byte past end of available space */
  void *pTrueEnd;         /* True value of pEnd, when db->pnBytesFreed!=0 */
};
struct LookasideSlot {
  LookasideSlot *pNext;    /* Next buffer in the list of free buffers */
};

#define DisableLookaside  db->lookaside.bDisable++;db->lookaside.sz=0
#define EnableLookaside   db->lookaside.bDisable--;\
   db->lookaside.sz=db->lookaside.bDisable?0:db->lookaside.szTrue

/* Size of the smaller allocations in two-size lookside */
#ifdef SQLITE_OMIT_TWOSIZE_LOOKASIDE
#  define LOOKASIDE_SMALL           0
#else
#  define LOOKASIDE_SMALL         128
#endif

/*
** A hash table for built-in function definitions.  (Application-defined
** functions use a regular table table from hash.h.)
**
** Hash each FuncDef structure into one of the FuncDefHash.a[] slots.
** Collisions are on the FuncDef.u.pHash chain.  Use the SQLITE_FUNC_HASH()
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
1430
1431
1432


1433
1434



1435
1436
1437
1438
1439
1440
1441
1442
1443
1444




1445
1446
1447
1448
1449
1450
1451
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602

1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616

1617
1618
1619

1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633

1634


1635
1636
1637
1638
1639

1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656


1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680







+
+
+
+
+







-
+










+


-
+


-
+











+

-

-
-
+
+



-
+





+








+
+
-
-
+
+
+










+
+
+
+







#define SQLITE_TRACE_XPROFILE        0x80     /* Use the legacy xProfile */
#else
#define SQLITE_TRACE_LEGACY          0
#define SQLITE_TRACE_XPROFILE        0
#endif /* SQLITE_OMIT_DEPRECATED */
#define SQLITE_TRACE_NONLEGACY_MASK  0x0f     /* Normal flags */

/*
** Maximum number of sqlite3.aDb[] entries.  This is the number of attached
** databases plus 2 for "main" and "temp".
*/
#define SQLITE_MAX_DB (SQLITE_MAX_ATTACHED+2)

/*
** Each database connection is an instance of the following structure.
*/
struct sqlite3 {
  sqlite3_vfs *pVfs;            /* OS Interface */
  struct Vdbe *pVdbe;           /* List of active virtual machines */
  CollSeq *pDfltColl;           /* The default collating sequence (BINARY) */
  CollSeq *pDfltColl;           /* BINARY collseq for the database encoding */
  sqlite3_mutex *mutex;         /* Connection mutex */
  Db *aDb;                      /* All backends */
  int nDb;                      /* Number of backends currently in use */
  u32 mDbFlags;                 /* flags recording internal state */
  u64 flags;                    /* flags settable by pragmas. See below */
  i64 lastRowid;                /* ROWID of most recent insert (see above) */
  i64 szMmap;                   /* Default mmap_size setting */
  u32 nSchemaLock;              /* Do not reset the schema when non-zero */
  unsigned int openFlags;       /* Flags passed to sqlite3_vfs.xOpen() */
  int errCode;                  /* Most recent error code (SQLITE_*) */
  int errByteOffset;            /* Byte offset of error in SQL statement */
  int errMask;                  /* & result codes with this before returning */
  int iSysErrno;                /* Errno value from last system error */
  u16 dbOptFlags;               /* Flags to enable/disable optimizations */
  u32 dbOptFlags;               /* Flags to enable/disable optimizations */
  u8 enc;                       /* Text encoding */
  u8 autoCommit;                /* The auto-commit flag. */
  u8 bConcurrent;               /* Current transaction is "CONCURRENT" */
  u8 eConcurrent;               /* CONCURRENT_* value */
  u8 temp_store;                /* 1: file 2: memory 0: default */
  u8 mallocFailed;              /* True if we have seen a malloc failure */
  u8 bBenignMalloc;             /* Do not require OOMs if true */
  u8 dfltLockMode;              /* Default locking-mode for attached dbs */
  signed char nextAutovac;      /* Autovac setting after VACUUM if >=0 */
  u8 suppressErr;               /* Do not issue error messages if true */
  u8 vtabOnConflict;            /* Value to return for s3_vtab_on_conflict() */
  u8 isTransactionSavepoint;    /* True if the outermost savepoint is a TS */
  u8 mTrace;                    /* zero or more SQLITE_TRACE flags */
  u8 noSharedCache;             /* True if no shared-cache backends */
  u8 nSqlExec;                  /* Number of pending OP_SqlExec opcodes */
  u8 eOpenState;                /* Current condition of the connection */
  int nextPagesize;             /* Pagesize after VACUUM if >0 */
  u32 magic;                    /* Magic number for detect library misuse */
  FastPrng sPrng;               /* State of the per-connection PRNG */
  int nChange;                  /* Value returned by sqlite3_changes() */
  int nTotalChange;             /* Value returned by sqlite3_total_changes() */
  i64 nChange;                  /* Value returned by sqlite3_changes() */
  i64 nTotalChange;             /* Value returned by sqlite3_total_changes() */
  int aLimit[SQLITE_N_LIMIT];   /* Limits */
  int nMaxSorterMmap;           /* Maximum size of regions mapped by sorter */
  struct sqlite3InitInfo {      /* Information used during initialization */
    int newTnum;                /* Rootpage of table being initialized */
    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 */
    const char **azInit;        /* "type", "name", and "tbl_name" columns */
  } init;
  int nVdbeActive;              /* Number of VDBEs currently running */
  int nVdbeRead;                /* Number of active VDBEs that read or write */
  int nVdbeWrite;               /* Number of active VDBEs that read and write */
  int nVdbeExec;                /* Number of nested calls to VdbeExec() */
  int nVDestroy;                /* Number of active OP_VDestroy operations */
  int nExtension;               /* Number of loaded extensions */
  void **aExtension;            /* Array of shared library handles */
  union {
    void (*xLegacy)(void*,const char*);   /* mTrace==SQLITE_TRACE_LEGACY */
  int (*xTrace)(u32,void*,void*,void*);     /* Trace function */
  void *pTraceArg;                          /* Argument to the trace function */
    int (*xV2)(u32,void*,void*,void*);    /* All other mTrace values */
  } trace;
  void *pTraceArg;                        /* Argument to the trace function */
#ifndef SQLITE_OMIT_DEPRECATED
  void (*xProfile)(void*,const char*,u64);  /* Profiling function */
  void *pProfileArg;                        /* Argument to profile function */
#endif
  void *pCommitArg;                 /* Argument to xCommitCallback() */
  int (*xCommitCallback)(void*);    /* Invoked at every commit. */
  void *pRollbackArg;               /* Argument to xRollbackCallback() */
  void (*xRollbackCallback)(void*); /* Invoked at every commit. */
  void *pUpdateArg;
  void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64);
  void *pAutovacPagesArg;           /* Client argument to autovac_pages */
  void (*xAutovacDestr)(void*);     /* Destructor for pAutovacPAgesArg */
  unsigned int (*xAutovacPages)(void*,const char*,u32,u32,u32);
  Parse *pParse;                /* Current parse */
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
  void *pPreUpdateArg;          /* First argument to xPreUpdateCallback */
  void (*xPreUpdateCallback)(   /* Registered using sqlite3_preupdate_hook() */
    void*,sqlite3*,int,char const*,char const*,sqlite3_int64,sqlite3_int64
  );
  PreUpdate *pPreUpdate;        /* Context for active pre-update callback */
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
1479
1480
1481
1482
1483
1484
1485

1486
1487
1488
1489
1490
1491
1492
1493

1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
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
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
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







+







-
+




















+
+
+
+
+
+
+






+
+
+
+
+
+
+








-
+






-
-
+
+
-







  VTable *pDisconnect;          /* Disconnect these in next sqlite3_prepare() */
#endif
  Hash aFunc;                   /* Hash table of connection functions */
  Hash aCollSeq;                /* All collating sequences */
  BusyHandler busyHandler;      /* Busy callback */
  Db aDbStatic[2];              /* Static space for the 2 default backends */
  Savepoint *pSavepoint;        /* List of active savepoints */
  int nAnalysisLimit;           /* Number of index rows to ANALYZE */
  int busyTimeout;              /* Busy handler timeout, in msec */
  int nSavepoint;               /* Number of non-transaction savepoints */
  int nStatement;               /* Number of nested statement-transactions  */
  i64 nDeferredCons;            /* Net deferred constraints this transaction. */
  i64 nDeferredImmCons;         /* Net deferred immediate constraints */
  int *pnBytesFreed;            /* If not NULL, increment this in DbFree() */
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
  /* The following variables are all protected by the STATIC_MASTER
  /* The following variables are all protected by the STATIC_MAIN
  ** mutex, not by sqlite3.mutex. They are used by code in notify.c.
  **
  ** When X.pUnlockConnection==Y, that means that X is waiting for Y to
  ** unlock so that it can proceed.
  **
  ** When X.pBlockingConnection==Y, that means that something that X tried
  ** tried to do recently failed with an SQLITE_LOCKED error due to locks
  ** held by Y.
  */
  sqlite3 *pBlockingConnection; /* Connection that caused SQLITE_LOCKED */
  sqlite3 *pUnlockConnection;           /* Connection to watch for unlock */
  void *pUnlockArg;                     /* Argument to xUnlockNotify */
  void (*xUnlockNotify)(void **, int);  /* Unlock notify callback */
  sqlite3 *pNextBlocked;        /* Next in list of all blocked connections */
#endif
#ifdef SQLITE_USER_AUTHENTICATION
  sqlite3_userauth auth;        /* User authentication information */
#endif
};

/*
** Candidate values for sqlite3.eConcurrent
*/
#define CONCURRENT_NONE   0
#define CONCURRENT_OPEN   1
#define CONCURRENT_SCHEMA 2

/*
** A macro to discover the encoding of a database.
*/
#define SCHEMA_ENC(db) ((db)->aDb[0].pSchema->enc)
#define ENC(db)        ((db)->enc)

/*
** A u64 constant where the lower 32 bits are all zeros.  Only the
** upper 32 bits are included in the argument.  Necessary because some
** C-compilers still do not accept LL integer literals.
*/
#define HI(X)  ((u64)(X)<<32)

/*
** Possible values for the sqlite3.flags.
**
** Value constraints (enforced via assert()):
**      SQLITE_FullFSync     == PAGER_FULLFSYNC
**      SQLITE_CkptFullFSync == PAGER_CKPT_FULLFSYNC
**      SQLITE_CacheSpill    == PAGER_CACHE_SPILL
*/
#define SQLITE_WriteSchema    0x00000001  /* OK to update SQLITE_MASTER */
#define SQLITE_WriteSchema    0x00000001  /* OK to update SQLITE_SCHEMA */
#define SQLITE_LegacyFileFmt  0x00000002  /* Create new databases in format 1 */
#define SQLITE_FullColNames   0x00000004  /* Show full column names on SELECT */
#define SQLITE_FullFSync      0x00000008  /* Use full fsync on the backend */
#define SQLITE_CkptFullFSync  0x00000010  /* Use full fsync for checkpoint */
#define SQLITE_CacheSpill     0x00000020  /* OK to spill pager cache */
#define SQLITE_ShortColNames  0x00000040  /* Show short columns names */
#define SQLITE_CountRows      0x00000080  /* Count rows changed by INSERT, */
                                          /*   DELETE, or UPDATE and return */
#define SQLITE_TrustedSchema  0x00000080  /* Allow unsafe functions and
                                          ** vtabs in the schema definition */
                                          /*   the count using a callback. */
#define SQLITE_NullCallback   0x00000100  /* Invoke the callback once if the */
                                          /*   result set is empty */
#define SQLITE_IgnoreChecks   0x00000200  /* Do not enforce check constraints */
#define SQLITE_ReadUncommit   0x00000400  /* READ UNCOMMITTED in shared-cache */
#define SQLITE_NoCkptOnClose  0x00000800  /* No checkpoint on close()/DETACH */
#define SQLITE_ReverseOrder   0x00001000  /* Reverse unordered SELECTs */
#define SQLITE_RecTriggers    0x00002000  /* Enable recursive triggers */
1553
1554
1555
1556
1557
1558
1559







1560
1561
1562
1563
1564
1565
1566
1567
1568
1569






1570
1571
1572
1573
1574
1575
1576
1577

1578



1579
1580
1581
1582
1583
1584
1585

1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602





























1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618


1619

1620
1621
1622
1623
1624
1625
1626






1627
1628
1629
1630
1631
1632
1633
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







+
+
+
+
+
+
+



-

-
-
-
-
-
+
+
+
+
+
+








+
-
+
+
+






-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+













-
-
-
+
+
-
+

-
-
-
-
-
-
+
+
+
+
+
+







#define SQLITE_Fts3Tokenizer  0x00400000  /* Enable fts3_tokenizer(2) */
#define SQLITE_EnableQPSG     0x00800000  /* Query Planner Stability Guarantee*/
#define SQLITE_TriggerEQP     0x01000000  /* Show trigger EXPLAIN QUERY PLAN */
#define SQLITE_ResetDatabase  0x02000000  /* Reset the database */
#define SQLITE_LegacyAlter    0x04000000  /* Legacy ALTER TABLE behaviour */
#define SQLITE_NoSchemaError  0x08000000  /* Do not report schema parse errors*/
#define SQLITE_Defensive      0x10000000  /* Input SQL is likely hostile */
#define SQLITE_DqsDDL         0x20000000  /* dbl-quoted strings allowed in DDL*/
#define SQLITE_DqsDML         0x40000000  /* dbl-quoted strings allowed in DML*/
#define SQLITE_EnableView     0x80000000  /* Enable the use of views */
#define SQLITE_CountRows      HI(0x00001) /* Count rows changed by INSERT, */
                                          /*   DELETE, or UPDATE and return */
                                          /*   the count using a callback. */
#define SQLITE_CorruptRdOnly  HI(0x00002) /* Prohibit writes due to error */

#define SQLITE_NoopUpdate     0x01000000  /* UPDATE operations are no-ops */
/* Flags used only if debugging */
#define HI(X)  ((u64)(X)<<32)
#ifdef SQLITE_DEBUG
#define SQLITE_SqlTrace       HI(0x0001)  /* Debug print SQL as it executes */
#define SQLITE_VdbeListing    HI(0x0002)  /* Debug listings of VDBE progs */
#define SQLITE_VdbeTrace      HI(0x0004)  /* True to trace VDBE execution */
#define SQLITE_VdbeAddopTrace HI(0x0008)  /* Trace sqlite3VdbeAddOp() calls */
#define SQLITE_VdbeEQP        HI(0x0010)  /* Debug EXPLAIN QUERY PLAN */
#define SQLITE_SqlTrace       HI(0x0100000) /* Debug print SQL as it executes */
#define SQLITE_VdbeListing    HI(0x0200000) /* Debug listings of VDBE progs */
#define SQLITE_VdbeTrace      HI(0x0400000) /* True to trace VDBE execution */
#define SQLITE_VdbeAddopTrace HI(0x0800000) /* Trace sqlite3VdbeAddOp() calls */
#define SQLITE_VdbeEQP        HI(0x1000000) /* Debug EXPLAIN QUERY PLAN */
#define SQLITE_ParserTrace    HI(0x2000000) /* PRAGMA parser_trace=ON */
#endif

/*
** Allowed values for sqlite3.mDbFlags
*/
#define DBFLAG_SchemaChange   0x0001  /* Uncommitted Hash table changes */
#define DBFLAG_PreferBuiltin  0x0002  /* Preference to built-in funcs */
#define DBFLAG_Vacuum         0x0004  /* Currently in a VACUUM */
#define DBFLAG_VacuumInto     0x0008  /* Currently running VACUUM INTO */
#define DBFLAG_SchemaKnownOk  0x0008  /* Schema is known to be valid */
#define DBFLAG_SchemaKnownOk  0x0010  /* Schema is known to be valid */
#define DBFLAG_InternalFunc   0x0020  /* Allow use of internal functions */
#define DBFLAG_EncodingFixed  0x0040  /* No longer possible to change enc. */

/*
** Bits of the sqlite3.dbOptFlags field that are used by the
** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to
** selectively disable various optimizations.
*/
#define SQLITE_QueryFlattener 0x0001   /* Query flattening */
#define SQLITE_QueryFlattener 0x00000001 /* Query flattening */
                          /*  0x0002   available for reuse */
#define SQLITE_GroupByOrder   0x0004   /* GROUPBY cover of ORDERBY */
#define SQLITE_FactorOutConst 0x0008   /* Constant factoring */
#define SQLITE_DistinctOpt    0x0010   /* DISTINCT using indexes */
#define SQLITE_CoverIdxScan   0x0020   /* Covering index scans */
#define SQLITE_OrderByIdxJoin 0x0040   /* ORDER BY of joins via index */
#define SQLITE_Transitive     0x0080   /* Transitive constraints */
#define SQLITE_OmitNoopJoin   0x0100   /* Omit unused tables in joins */
#define SQLITE_CountOfView    0x0200   /* The count-of-view optimization */
#define SQLITE_CursorHints    0x0400   /* Add OP_CursorHint opcodes */
#define SQLITE_Stat34         0x0800   /* Use STAT3 or STAT4 data */
   /* TH3 expects the Stat34  ^^^^^^ value to be 0x0800.  Don't change it */
#define SQLITE_PushDown       0x1000   /* The push-down optimization */
#define SQLITE_SimplifyJoin   0x2000   /* Convert LEFT JOIN to JOIN */
#define SQLITE_SkipScan       0x4000   /* Skip-scans */
#define SQLITE_PropagateConst 0x8000   /* The constant propagation opt */
#define SQLITE_AllOpts        0xffff   /* All optimizations */
#define SQLITE_WindowFunc     0x00000002 /* Use xInverse for window functions */
#define SQLITE_GroupByOrder   0x00000004 /* GROUPBY cover of ORDERBY */
#define SQLITE_FactorOutConst 0x00000008 /* Constant factoring */
#define SQLITE_DistinctOpt    0x00000010 /* DISTINCT using indexes */
#define SQLITE_CoverIdxScan   0x00000020 /* Covering index scans */
#define SQLITE_OrderByIdxJoin 0x00000040 /* ORDER BY of joins via index */
#define SQLITE_Transitive     0x00000080 /* Transitive constraints */
#define SQLITE_OmitNoopJoin   0x00000100 /* Omit unused tables in joins */
#define SQLITE_CountOfView    0x00000200 /* The count-of-view optimization */
#define SQLITE_CursorHints    0x00000400 /* Add OP_CursorHint opcodes */
#define SQLITE_Stat4          0x00000800 /* Use STAT4 data */
   /* TH3 expects this value  ^^^^^^^^^^ to be 0x0000800. Don't change it */
#define SQLITE_PushDown       0x00001000 /* The push-down optimization */
#define SQLITE_SimplifyJoin   0x00002000 /* Convert LEFT JOIN to JOIN */
#define SQLITE_SkipScan       0x00004000 /* Skip-scans */
#define SQLITE_PropagateConst 0x00008000 /* The constant propagation opt */
#define SQLITE_MinMaxOpt      0x00010000 /* The min/max optimization */
#define SQLITE_SeekScan       0x00020000 /* The OP_SeekScan optimization */
#define SQLITE_OmitOrderBy    0x00040000 /* Omit pointless ORDER BY */
   /* TH3 expects this value  ^^^^^^^^^^ to be 0x40000. Coordinate any change */
#define SQLITE_BloomFilter    0x00080000 /* Use a Bloom filter on searches */
#define SQLITE_BloomPulldown  0x00100000 /* Run Bloom filters early */
#define SQLITE_BalancedMerge  0x00200000 /* Balance multi-way merges */
#define SQLITE_ReleaseReg     0x00400000 /* Use OP_ReleaseReg for testing */
#define SQLITE_FlttnUnionAll  0x00800000 /* Disable the UNION ALL flattener */
   /* TH3 expects this value  ^^^^^^^^^^ See flatten04.test */
#define SQLITE_IndexedExpr    0x01000000 /* Pull exprs from index when able */
#define SQLITE_Coroutines     0x02000000 /* Co-routines for subqueries */
#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)

/*
** Return true if it OK to factor constant expressions into the initialization
** code. The argument is a Parse object for the code generator.
*/
#define ConstFactorOk(P) ((P)->okConstFactor)

/*
** Possible values for the sqlite.magic field.
** The numbers are obtained at random and have no special meaning, other
/* Possible values for the sqlite3.eOpenState field.
** The numbers are randomly selected such that a minimum of three bits must
** than being distinct from one another.
** change to convert any number to another or to zero
*/
#define SQLITE_MAGIC_OPEN     0xa029a697  /* Database is open */
#define SQLITE_MAGIC_CLOSED   0x9f3c2d33  /* Database is closed */
#define SQLITE_MAGIC_SICK     0x4b771290  /* Error and awaiting close */
#define SQLITE_MAGIC_BUSY     0xf03b7906  /* Database currently in use */
#define SQLITE_MAGIC_ERROR    0xb5357930  /* An SQLITE_MISUSE error occurred */
#define SQLITE_MAGIC_ZOMBIE   0x64cffc7f  /* Close with last statement close */
#define SQLITE_STATE_OPEN     0x76  /* Database is open */
#define SQLITE_STATE_CLOSED   0xce  /* Database is closed */
#define SQLITE_STATE_SICK     0xba  /* Error and awaiting close */
#define SQLITE_STATE_BUSY     0x6d  /* Database currently in use */
#define SQLITE_STATE_ERROR    0xd5  /* An SQLITE_MISUSE error occurred */
#define SQLITE_STATE_ZOMBIE   0xa7  /* Close with last statement close */

/*
** Each SQL function is defined by an instance of the following
** structure.  For global built-in functions (ex: substr(), max(), count())
** a pointer to this structure is held in the sqlite3BuiltinFunctions object.
** For per-connection application-defined functions, a pointer to this
** structure is held in the db->aHash hash table.
1644
1645
1646
1647
1648
1649
1650
1651

1652
1653
1654
1655
1656
1657
1658
1908
1909
1910
1911
1912
1913
1914

1915
1916
1917
1918
1919
1920
1921
1922







-
+







  void (*xFinalize)(sqlite3_context*);                  /* Agg finalizer */
  void (*xValue)(sqlite3_context*);                     /* Current agg value */
  void (*xInverse)(sqlite3_context*,int,sqlite3_value**); /* inverse agg-step */
  const char *zName;   /* SQL name of the function. */
  union {
    FuncDef *pHash;      /* Next with a different name but the same hash */
    FuncDestructor *pDestructor;   /* Reference counted destructor function */
  } u;
  } u; /* pHash if SQLITE_FUNC_BUILTIN, pDestructor otherwise */
};

/*
** This structure encapsulates a user-function destructor callback (as
** configured using create_function_v2()) and a reference counter. When
** create_function_v2() is called to create a function with a destructor,
** a single object of this type is allocated. FuncDestructor.nRef is set to
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
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754

1755

1756
1757
1758

1759
1760
1761





















1762
1763

1764

1765
1766

1767

1768
1769

1770

1771
1772
1773

1774
1775
1776
1777
1778
1779
1780
1781
1782

1783
1784

1785

1786
1787
1788
1789
1790
1791
1792
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
1984
1985
1986
1987
1988
1989
1990
1991
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
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046

2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062

2063
2064
2065

2066
2067


2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
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







-
-
-
-
+
+
+
+
+
+
+

+
+
+
+
+
+









-
+





-
-
+
+

-

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







+
+
+












-
+














+
-
+


-
+

-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
-
+


+
-
+


+
-
+


-
+

-
-
-
-
-
-

-
+


+
-
+







/*
** Possible values for FuncDef.flags.  Note that the _LENGTH and _TYPEOF
** values must correspond to OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG.  And
** SQLITE_FUNC_CONSTANT must be the same as SQLITE_DETERMINISTIC.  There
** are assert() statements in the code to verify this.
**
** Value constraints (enforced via assert()):
**     SQLITE_FUNC_MINMAX    ==  NC_MinMaxAgg      == SF_MinMaxAgg
**     SQLITE_FUNC_LENGTH    ==  OPFLAG_LENGTHARG
**     SQLITE_FUNC_TYPEOF    ==  OPFLAG_TYPEOFARG
**     SQLITE_FUNC_CONSTANT  ==  SQLITE_DETERMINISTIC from the API
**     SQLITE_FUNC_MINMAX      ==  NC_MinMaxAgg      == SF_MinMaxAgg
**     SQLITE_FUNC_ANYORDER    ==  NC_OrderAgg       == SF_OrderByReqd
**     SQLITE_FUNC_LENGTH      ==  OPFLAG_LENGTHARG
**     SQLITE_FUNC_TYPEOF      ==  OPFLAG_TYPEOFARG
**     SQLITE_FUNC_CONSTANT    ==  SQLITE_DETERMINISTIC from the API
**     SQLITE_FUNC_DIRECT      ==  SQLITE_DIRECTONLY from the API
**     SQLITE_FUNC_UNSAFE      ==  SQLITE_INNOCUOUS  -- opposite meanings!!!
**     SQLITE_FUNC_ENCMASK   depends on SQLITE_UTF* macros in the API
**
** Note that even though SQLITE_FUNC_UNSAFE and SQLITE_INNOCUOUS have the
** same bit value, their meanings are inverted.  SQLITE_FUNC_UNSAFE is
** used internally and if set means tha the function has side effects.
** SQLITE_INNOCUOUS is used by application code and means "not unsafe".
** See multiple instances of tag-20230109-1.
*/
#define SQLITE_FUNC_ENCMASK  0x0003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */
#define SQLITE_FUNC_LIKE     0x0004 /* Candidate for the LIKE optimization */
#define SQLITE_FUNC_CASE     0x0008 /* Case-sensitive LIKE-type function */
#define SQLITE_FUNC_EPHEM    0x0010 /* Ephemeral.  Delete with VDBE */
#define SQLITE_FUNC_NEEDCOLL 0x0020 /* sqlite3GetFuncCollSeq() might be called*/
#define SQLITE_FUNC_LENGTH   0x0040 /* Built-in length() function */
#define SQLITE_FUNC_TYPEOF   0x0080 /* Built-in typeof() function */
#define SQLITE_FUNC_COUNT    0x0100 /* Built-in count(*) aggregate */
#define SQLITE_FUNC_COALESCE 0x0200 /* Built-in coalesce() or ifnull() */
/*                           0x0200 -- available for reuse */
#define SQLITE_FUNC_UNLIKELY 0x0400 /* Built-in unlikely() function */
#define SQLITE_FUNC_CONSTANT 0x0800 /* Constant inputs give a constant output */
#define SQLITE_FUNC_MINMAX   0x1000 /* True for min() and max() aggregates */
#define SQLITE_FUNC_SLOCHNG  0x2000 /* "Slow Change". Value constant during a
                                    ** single query - might change over time */
#define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */
#define SQLITE_FUNC_OFFSET   0x8000 /* Built-in sqlite_offset() function */
#define SQLITE_FUNC_TEST     0x4000 /* Built-in testing functions */
/*                           0x8000 -- available for reuse */
#define SQLITE_FUNC_WINDOW   0x00010000 /* Built-in window-only function */
#define SQLITE_FUNC_WINDOW_SIZE 0x20000 /* Requires partition size as arg. */
#define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */
#define SQLITE_FUNC_DIRECT   0x00080000 /* Not for use in TRIGGERs or VIEWs */
#define SQLITE_FUNC_SUBTYPE  0x00100000 /* Result likely to have sub-type */
#define SQLITE_FUNC_UNSAFE   0x00200000 /* Function has side effects */
#define SQLITE_FUNC_INLINE   0x00400000 /* Functions implemented in-line */
#define SQLITE_FUNC_BUILTIN  0x00800000 /* This is a built-in function */
#define SQLITE_FUNC_ANYORDER 0x08000000 /* count/min/max aggregate */

/* Identifier numbers for each in-line function */
#define INLINEFUNC_coalesce             0
#define INLINEFUNC_implies_nonnull_row  1
#define INLINEFUNC_expr_implies_expr    2
#define INLINEFUNC_expr_compare         3      
#define INLINEFUNC_affinity             4
#define INLINEFUNC_iif                  5
#define INLINEFUNC_sqlite_offset        6
#define INLINEFUNC_unlikely            99  /* Default case */

/*
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
** used to create the initializers for the FuncDef structures.
**
**   FUNCTION(zName, nArg, iArg, bNC, xFunc)
**     Used to create a scalar function definition of a function zName
**     implemented by C function xFunc that accepts nArg arguments. The
**     value passed as iArg is cast to a (void*) and made available
**     as the user-data (sqlite3_user_data()) for the function. If
**     argument bNC is true, then the SQLITE_FUNC_NEEDCOLL flag is set.
**
**   VFUNCTION(zName, nArg, iArg, bNC, xFunc)
**     Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag.
**
**   SFUNCTION(zName, nArg, iArg, bNC, xFunc)
**     Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag and
**     adds the SQLITE_DIRECTONLY flag.
**
**   INLINE_FUNC(zName, nArg, iFuncId, mFlags)
**     zName is the name of a function that is implemented by in-line
**     byte code rather than by the usual callbacks. The iFuncId
**     parameter determines the function id.  The mFlags parameter is
**     optional SQLITE_FUNC_ flags for this function.
**
**   TEST_FUNC(zName, nArg, iFuncId, mFlags)
**     zName is the name of a test-only function implemented by in-line
**     byte code rather than by the usual callbacks. The iFuncId
**     parameter determines the function id.  The mFlags parameter is
**     optional SQLITE_FUNC_ flags for this function.
**
**   DFUNCTION(zName, nArg, iArg, bNC, xFunc)
**     Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag and
**     adds the SQLITE_FUNC_SLOCHNG flag.  Used for date & time functions
**     and functions like sqlite_version() that can change, but not during
**     a single query.  The iArg is ignored.  The user-data is always set
**     to a NULL pointer.  The bNC parameter is not used.
**
**   MFUNCTION(zName, nArg, xPtr, xFunc)
**     For math-library functions.  xPtr is an arbitrary pointer.
**
**   PURE_DATE(zName, nArg, iArg, bNC, xFunc)
**     Used for "pure" date/time functions, this macro is like DFUNCTION
**     except that it does set the SQLITE_FUNC_CONSTANT flags.  iArg is
**     ignored and the user-data for these functions is set to an 
**     arbitrary non-NULL pointer.  The bNC parameter is not used.
**
**   AGGREGATE(zName, nArg, iArg, bNC, xStep, xFinal)
**     Used to create an aggregate function definition implemented by
**     the C functions xStep and xFinal. The first four parameters
**     are interpreted in the same way as the first 4 parameters to
**     FUNCTION().
**
**   WFUNCTION(zName, nArg, iArg, xStep, xFinal, xValue, xInverse)
**   WAGGREGATE(zName, nArg, iArg, xStep, xFinal, xValue, xInverse)
**     Used to create an aggregate function definition implemented by
**     the C functions xStep and xFinal. The first four parameters
**     are interpreted in the same way as the first 4 parameters to
**     FUNCTION().
**
**   LIKEFUNC(zName, nArg, pArg, flags)
**     Used to create a scalar function definition of a function zName
**     that accepts nArg arguments and is implemented by a call to C
**     function likeFunc. Argument pArg is cast to a (void *) and made
**     available as the function user-data (sqlite3_user_data()). The
**     FuncDef.flags variable is set to the value passed as the flags
**     parameter.
*/
#define FUNCTION(zName, nArg, iArg, bNC, xFunc) \
  {nArg, SQLITE_FUNC_BUILTIN|\
  {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
   SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
   SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
#define VFUNCTION(zName, nArg, iArg, bNC, xFunc) \
  {nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
  {nArg, SQLITE_FUNC_BUILTIN|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
   SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
#define DFUNCTION(zName, nArg, iArg, bNC, xFunc) \
  {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8, \
#define SFUNCTION(zName, nArg, iArg, bNC, xFunc) \
  {nArg, SQLITE_FUNC_BUILTIN|SQLITE_UTF8|SQLITE_DIRECTONLY|SQLITE_FUNC_UNSAFE, \
   SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
#define MFUNCTION(zName, nArg, xPtr, xFunc) \
  {nArg, SQLITE_FUNC_BUILTIN|SQLITE_FUNC_CONSTANT|SQLITE_UTF8, \
   xPtr, 0, xFunc, 0, 0, 0, #zName, {0} }
#define JFUNCTION(zName, nArg, iArg, xFunc) \
  {nArg, SQLITE_FUNC_BUILTIN|SQLITE_DETERMINISTIC|\
   SQLITE_FUNC_CONSTANT|SQLITE_UTF8, \
   SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
#define INLINE_FUNC(zName, nArg, iArg, mFlags) \
  {nArg, SQLITE_FUNC_BUILTIN|\
   SQLITE_UTF8|SQLITE_FUNC_INLINE|SQLITE_FUNC_CONSTANT|(mFlags), \
   SQLITE_INT_TO_PTR(iArg), 0, noopFunc, 0, 0, 0, #zName, {0} }
#define TEST_FUNC(zName, nArg, iArg, mFlags) \
  {nArg, SQLITE_FUNC_BUILTIN|\
         SQLITE_UTF8|SQLITE_FUNC_INTERNAL|SQLITE_FUNC_TEST| \
         SQLITE_FUNC_INLINE|SQLITE_FUNC_CONSTANT|(mFlags), \
   SQLITE_INT_TO_PTR(iArg), 0, noopFunc, 0, 0, 0, #zName, {0} }
#define DFUNCTION(zName, nArg, iArg, bNC, xFunc) \
  {nArg, SQLITE_FUNC_BUILTIN|SQLITE_FUNC_SLOCHNG|SQLITE_UTF8, \
   0, 0, xFunc, 0, 0, 0, #zName, {0} }
#define PURE_DATE(zName, nArg, iArg, bNC, xFunc) \
  {nArg, SQLITE_FUNC_BUILTIN|\
  {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \
         SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \
   (void*)&sqlite3Config, 0, xFunc, 0, 0, 0, #zName, {0} }
#define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \
  {nArg, SQLITE_FUNC_BUILTIN|\
  {nArg,SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags,\
   SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags,\
   SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
#define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \
  {nArg, SQLITE_FUNC_BUILTIN|\
  {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
   SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
   pArg, 0, xFunc, 0, 0, 0, #zName, }
#define LIKEFUNC(zName, nArg, arg, flags) \
  {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|flags, \
  {nArg, SQLITE_FUNC_BUILTIN|SQLITE_FUNC_CONSTANT|SQLITE_UTF8|flags, \
   (void *)arg, 0, likeFunc, 0, 0, 0, #zName, {0} }
#define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal, xValue) \
  {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL), \
   SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xValue,0,#zName, {0}}
#define AGGREGATE2(zName, nArg, arg, nc, xStep, xFinal, extraFlags) \
  {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|extraFlags, \
   SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xFinal,0,#zName, {0}}
#define WAGGREGATE(zName, nArg, arg, nc, xStep, xFinal, xValue, xInverse, f) \
  {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|f, \
  {nArg, SQLITE_FUNC_BUILTIN|SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|f, \
   SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xValue,xInverse,#zName, {0}}
#define INTERNAL_FUNCTION(zName, nArg, xFunc) \
  {nArg, SQLITE_FUNC_BUILTIN|\
  {nArg, SQLITE_FUNC_INTERNAL|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \
   SQLITE_FUNC_INTERNAL|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \
   0, 0, xFunc, 0, 0, 0, #zName, {0} }


/*
** All current savepoints are stored in a linked list starting at
** sqlite3.pSavepoint. The first element in the list is the most recently
** opened savepoint. Savepoints are added to the list by the vdbe
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
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150


2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175

2176






2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201

2202
2203
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







+






-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+
-
-
-
-
-
-
+
+
+
+
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+

-
-
-
-
+
+
+
+

+
+
+
+
+
+
+
+







** Each SQLite module (virtual table definition) is defined by an
** instance of the following structure, stored in the sqlite3.aModule
** hash table.
*/
struct Module {
  const sqlite3_module *pModule;       /* Callback pointers */
  const char *zName;                   /* Name passed to create_module() */
  int nRefModule;                      /* Number of pointers to this object */
  void *pAux;                          /* pAux passed to create_module() */
  void (*xDestroy)(void *);            /* Module destructor function */
  Table *pEpoTab;                      /* Eponymous table for this module */
};

/*
** information about each column of an SQL table is held in an instance
** of this structure.
** Information about each column of an SQL table is held in an instance
** of the Column structure, in the Table.aCol[] array.
**
** Definitions:
**
**   "table column index"     This is the index of the column in the
**                            Table.aCol[] array, and also the index of
**                            the column in the original CREATE TABLE stmt.
**
**   "storage column index"   This is the index of the column in the
**                            record BLOB generated by the OP_MakeRecord
**                            opcode.  The storage column index is less than
**                            or equal to the table column index.  It is
**                            equal if and only if there are no VIRTUAL
**                            columns to the left.
**
** Notes on zCnName:
** The zCnName field stores the name of the column, the datatype of the
** column, and the collating sequence for the column, in that order, all in
** a single allocation.  Each string is 0x00 terminated.  The datatype
** is only included if the COLFLAG_HASTYPE bit of colFlags is set and the
** collating sequence name is only included if the COLFLAG_HASCOLL bit is
** set.
*/
struct Column {
  char *zName;     /* Name of this column, \000, then the type */
  char *zCnName;        /* Name of this column */
  Expr *pDflt;     /* Default value of this column */
  char *zColl;     /* Collating sequence.  If NULL, use the default */
  u8 notNull;      /* An OE_ code for handling a NOT NULL constraint */
  char affinity;   /* One of the SQLITE_AFF_... values */
  u8 szEst;        /* Estimated size of value in this column. sizeof(INT)==1 */
  u8 colFlags;     /* Boolean properties.  See COLFLAG_ defines below */
  unsigned notNull :4;  /* An OE_ code for handling a NOT NULL constraint */
  unsigned eCType :4;   /* One of the standard types */
  char affinity;        /* One of the SQLITE_AFF_... values */
  u8 szEst;             /* Est size of value in this column. sizeof(INT)==1 */
  u8 hName;             /* Column name hash for faster lookup */
  u16 iDflt;            /* 1-based index of DEFAULT.  0 means "none" */
  u16 colFlags;         /* Boolean properties.  See COLFLAG_ defines below */
};

/* Allowed values for Column.eCType.
**
** Values must match entries in the global constant arrays
** sqlite3StdTypeLen[] and sqlite3StdType[].  Each value is one more
** than the offset into these arrays for the corresponding name.
** Adjust the SQLITE_N_STDTYPE value if adding or removing entries.
*/
#define COLTYPE_CUSTOM      0   /* Type appended to zName */
#define COLTYPE_ANY         1
#define COLTYPE_BLOB        2
#define COLTYPE_INT         3
#define COLTYPE_INTEGER     4
#define COLTYPE_REAL        5
#define COLTYPE_TEXT        6
#define SQLITE_N_STDTYPE    6  /* Number of standard types */

/* Allowed values for Column.colFlags:
/* Allowed values for Column.colFlags.
**
** Constraints:
**         TF_HasVirtual == COLFLAG_VIRTUAL
**         TF_HasStored  == COLFLAG_STORED
**         TF_HasHidden  == COLFLAG_HIDDEN
*/
#define COLFLAG_PRIMKEY  0x0001    /* Column is part of the primary key */
#define COLFLAG_HIDDEN   0x0002    /* A hidden column in a virtual table */
#define COLFLAG_HASTYPE  0x0004    /* Type name follows column name */
#define COLFLAG_UNIQUE   0x0008    /* Column def contains "UNIQUE" or "PK" */
#define COLFLAG_PRIMKEY   0x0001   /* Column is part of the primary key */
#define COLFLAG_HIDDEN    0x0002   /* A hidden column in a virtual table */
#define COLFLAG_HASTYPE   0x0004   /* Type name follows column name */
#define COLFLAG_UNIQUE    0x0008   /* Column def contains "UNIQUE" or "PK" */
#define COLFLAG_SORTERREF 0x0010   /* Use sorter-refs with this column */
#define COLFLAG_VIRTUAL   0x0020   /* GENERATED ALWAYS AS ... VIRTUAL */
#define COLFLAG_STORED    0x0040   /* GENERATED ALWAYS AS ... STORED */
#define COLFLAG_NOTAVAIL  0x0080   /* STORED column not yet calculated */
#define COLFLAG_BUSY      0x0100   /* Blocks recursion on GENERATED columns */
#define COLFLAG_HASCOLL   0x0200   /* Has collating sequence name in zCnName */
#define COLFLAG_NOEXPAND  0x0400   /* Omit this column when expanding "*" */
#define COLFLAG_GENERATED 0x0060   /* Combo: _STORED, _VIRTUAL */
#define COLFLAG_NOINSERT  0x0062   /* Combo: _HIDDEN, _STORED, _VIRTUAL */

/*
** A "Collating Sequence" is defined by an instance of the following
** structure. Conceptually, a collating sequence consists of a name and
** a comparison routine that defines the order of that sequence.
**
** If CollSeq.xCmp is NULL, it means that the
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
2254
2255
2256
2257
2258
2259
2260
2261





2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285

2286

2287
2288
2289
2290
2291
2292
2293







+
-
-
-
-
-
+
+
+
+
+
+


















-

-







** But rather than start with 0 or 1, we begin with 'A'.  That way,
** when multiple affinity types are concatenated into a string and
** used as the P4 operand, they will be more readable.
**
** Note also that the numeric types are grouped together so that testing
** for a numeric type is a single comparison.  And the BLOB type is first.
*/
#define SQLITE_AFF_NONE     0x40  /* '@' */
#define SQLITE_AFF_BLOB     'A'
#define SQLITE_AFF_TEXT     'B'
#define SQLITE_AFF_NUMERIC  'C'
#define SQLITE_AFF_INTEGER  'D'
#define SQLITE_AFF_REAL     'E'
#define SQLITE_AFF_BLOB     0x41  /* 'A' */
#define SQLITE_AFF_TEXT     0x42  /* 'B' */
#define SQLITE_AFF_NUMERIC  0x43  /* 'C' */
#define SQLITE_AFF_INTEGER  0x44  /* 'D' */
#define SQLITE_AFF_REAL     0x45  /* 'E' */
#define SQLITE_AFF_FLEXNUM  0x46  /* 'F' */

#define sqlite3IsNumericAffinity(X)  ((X)>=SQLITE_AFF_NUMERIC)

/*
** The SQLITE_AFF_MASK values masks off the significant bits of an
** affinity value.
*/
#define SQLITE_AFF_MASK     0x47

/*
** Additional bit values that can be ORed with an affinity without
** 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.
**
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
1984
1985
1986
1987
1988
1989
1990
1991











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









2017
2018
2019

2020


2021
2022
















2023
2024
2025
2026
2027
2028
2029
2030



2031
2032

2033
2034
2035
2036
2037
2038
2039
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349


2350
2351
2352
2353
2354
2355
2356


2357
2358
2359

2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371



2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382




2383
2384
2385
2386


2387
2388
2389
2390

2391
2392
2393
2394
2395
2396
2397
2398
2399

2400
2401
2402
2403
2404
2405
2406
2407






2408
2409
2410
2411
2412
2413
2414
2415
2416



2417
2418
2419
2420


2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443

2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456







+




+
+
+
+
+
+

-
-
+
+





-
-



-
+




+






-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
+
+
+

-









-
+
+
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
+

+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
+
+
+


+







*/
struct VTable {
  sqlite3 *db;              /* Database connection associated with this table */
  Module *pMod;             /* Pointer to module implementation */
  sqlite3_vtab *pVtab;      /* Pointer to vtab instance */
  int nRef;                 /* Number of pointers to this structure */
  u8 bConstraint;           /* True if constraints are supported */
  u8 eVtabRisk;             /* Riskiness of allowing hacker access */
  int iSavepoint;           /* Depth of the SAVEPOINT stack */
  VTable *pNext;            /* Next in linked list (see above) */
};

/* Allowed values for VTable.eVtabRisk
*/
#define SQLITE_VTABRISK_Low          0
#define SQLITE_VTABRISK_Normal       1
#define SQLITE_VTABRISK_High         2

/*
** The schema for each SQL table and view is represented in memory
** by an instance of the following structure.
** The schema for each SQL table, virtual table, and view is represented
** in memory by an instance of the following structure.
*/
struct Table {
  char *zName;         /* Name of the table or view */
  Column *aCol;        /* Information about each column */
  Index *pIndex;       /* List of SQL indexes on this table. */
  Select *pSelect;     /* NULL for tables.  Points to definition if a view. */
  FKey *pFKey;         /* Linked list of all foreign keys in this table */
  char *zColAff;       /* String defining the affinity of each column */
  ExprList *pCheck;    /* All CHECK constraints */
                       /*   ... also used as column name list in a VIEW */
  int tnum;            /* Root BTree page for this table */
  Pgno tnum;           /* Root BTree page for this table */
  u32 nTabRef;         /* Number of pointers to this Table */
  u32 tabFlags;        /* Mask of TF_* values */
  i16 iPKey;           /* If not negative, use aCol[iPKey] as the rowid */
  i16 nCol;            /* Number of columns in this table */
  i16 nNVCol;          /* Number of columns that are not VIRTUAL */
  LogEst nRowLogEst;   /* Estimated rows in table - from sqlite_stat1 table */
  LogEst szTabRow;     /* Estimated size of each table row in bytes */
#ifdef SQLITE_ENABLE_COSTMULT
  LogEst costMult;     /* Cost multiplier for using this table */
#endif
  u8 keyConf;          /* What to do in case of uniqueness conflict on iPKey */
#ifndef SQLITE_OMIT_ALTERTABLE
  int addColOffset;    /* Offset in CREATE TABLE stmt to add a new column */
#endif
  u8 eTabType;         /* 0: normal, 1: virtual, 2: view */
  union {
    struct {             /* Used by ordinary tables: */
      int addColOffset;    /* Offset in CREATE TABLE stmt to add a new column */
      FKey *pFKey;         /* Linked list of all foreign keys in this table */
      ExprList *pDfltList; /* DEFAULT clauses on various columns.
                           ** Or the AS clause for generated columns. */
    } tab;
    struct {             /* Used by views: */
      Select *pSelect;     /* View definition */
    } view;
#ifndef SQLITE_OMIT_VIRTUALTABLE
  int nModuleArg;      /* Number of arguments to the module */
  char **azModuleArg;  /* 0: module 1: schema 2: vtab name 3...: args */
  VTable *pVTable;     /* List of VTable objects. */
    struct {             /* Used by virtual tables only: */
      int nArg;            /* Number of arguments to the module */
      char **azArg;        /* 0: module 1: schema 2: vtab name 3...: args */
      VTable *p;           /* List of VTable objects. */
#endif
  Trigger *pTrigger;   /* List of triggers stored in pSchema */
    } vtab;
  } u;
  Trigger *pTrigger;   /* List of triggers on this object */
  Schema *pSchema;     /* Schema that contains this table */
  Table *pNextZombie;  /* Next on the Parse.pZombieTab list */
};

/*
** Allowed values for Table.tabFlags.
**
** TF_OOOHidden applies to tables or view that have hidden columns that are
** followed by non-hidden columns.  Example:  "CREATE VIRTUAL TABLE x USING
** vtab1(a HIDDEN, b);".  Since "b" is a non-hidden column but "a" is hidden,
** the TF_OOOHidden attribute would apply in this case.  Such tables require
** special handling during INSERT processing.
** special handling during INSERT processing. The "OOO" means "Out Of Order".
**
** Constraints:
**
**         TF_HasVirtual == COLFLAG_VIRTUAL
**         TF_HasStored  == COLFLAG_STORED
**         TF_HasHidden  == COLFLAG_HIDDEN
*/
#define TF_Readonly        0x0001    /* Read-only system table */
#define TF_Ephemeral       0x0002    /* An ephemeral table */
#define TF_HasPrimaryKey   0x0004    /* Table has a primary key */
#define TF_Autoincrement   0x0008    /* Integer primary key is autoincrement */
#define TF_HasStat1        0x0010    /* nRowLogEst set from sqlite_stat1 */
#define TF_WithoutRowid    0x0020    /* No rowid.  PRIMARY KEY is the key */
#define TF_Readonly       0x00000001 /* Read-only system table */
#define TF_HasHidden      0x00000002 /* Has one or more hidden columns */
#define TF_HasPrimaryKey  0x00000004 /* Table has a primary key */
#define TF_Autoincrement  0x00000008 /* Integer primary key is autoincrement */
#define TF_HasStat1       0x00000010 /* nRowLogEst set from sqlite_stat1 */
#define TF_HasVirtual     0x00000020 /* Has one or more VIRTUAL columns */
#define TF_HasStored      0x00000040 /* Has one or more STORED columns */
#define TF_HasGenerated   0x00000060 /* Combo: HasVirtual + HasStored */
#define TF_WithoutRowid   0x00000080 /* No rowid.  PRIMARY KEY is the key */
#define TF_NoVisibleRowid  0x0040    /* No user-visible "rowid" column */
#define TF_OOOHidden       0x0080    /* Out-of-Order hidden columns */
#define TF_StatsUsed       0x0100    /* Query planner decisions affected by
#define TF_StatsUsed      0x00000100 /* Query planner decisions affected by
                                     ** Index.aiRowLogEst[] values */
#define TF_NoVisibleRowid 0x00000200 /* No user-visible "rowid" column */
#define TF_OOOHidden      0x00000400 /* Out-of-Order hidden columns */
#define TF_HasNotNull      0x0200    /* Contains NOT NULL constraints */
#define TF_Shadow          0x0400    /* True for a shadow table */
#define TF_HasNotNull     0x00000800 /* Contains NOT NULL constraints */
#define TF_Shadow         0x00001000 /* True for a shadow table */
#define TF_HasStat4       0x00002000 /* STAT4 info available for this table */
#define TF_Ephemeral      0x00004000 /* An ephemeral table */
#define TF_Eponymous      0x00008000 /* An eponymous virtual table */
#define TF_Strict         0x00010000 /* STRICT mode */

/*
** Allowed values for Table.eTabType
*/
#define TABTYP_NORM      0     /* Ordinary table */
#define TABTYP_VTAB      1     /* Virtual table */
#define TABTYP_VIEW      2     /* A view */

#define IsView(X)           ((X)->eTabType==TABTYP_VIEW)
#define IsOrdinaryTable(X)  ((X)->eTabType==TABTYP_NORM)

/*
** 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
#  define IsVirtual(X)      ((X)->nModuleArg)
#  define IsVirtual(X)      ((X)->eTabType==TABTYP_VTAB)
#  define ExprIsVtab(X)  \
   ((X)->op==TK_COLUMN && (X)->y.pTab->eTabType==TABTYP_VTAB)
#else
#  define IsVirtual(X)      0
#  define ExprIsVtab(X)     0
#endif

/*
** Macros to determine if a column is hidden.  IsOrdinaryHiddenColumn()
** only works for non-virtual tables (ordinary tables and views) and is
** always false unless SQLITE_ENABLE_HIDDEN_COLUMNS is defined.  The
** IsHiddenColumn() macro is general purpose.
2109
2110
2111
2112
2113
2114
2115


2116
2117

2118
2119

2120

2121
2122
2123



2124
2125

2126
2127
2128
2129
2130
2131
2132
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535

2536
2537
2538
2539

2540
2541
2542
2543
2544
2545
2546
2547

2548
2549
2550
2551
2552
2553
2554
2555







+
+

-
+


+
-
+



+
+
+

-
+







** the operation in progress stops and returns an error code.  But prior
** changes due to the same operation are not backed out and no rollback
** occurs.  IGNORE means that the particular row that caused the constraint
** error is not inserted or updated.  Processing continues and no error
** is returned.  REPLACE means that preexisting database rows that caused
** a UNIQUE constraint violation are removed so that the new insert or
** update can proceed.  Processing continues and no error is reported.
** UPDATE applies to insert operations only and means that the insert
** is omitted and the DO UPDATE clause of an upsert is run instead.
**
** RESTRICT, SETNULL, and CASCADE actions apply only to foreign keys.
** RESTRICT, SETNULL, SETDFLT, and CASCADE actions apply only to foreign keys.
** RESTRICT is the same as ABORT for IMMEDIATE foreign keys and the
** same as ROLLBACK for DEFERRED keys.  SETNULL means that the foreign
** key is set to NULL.  SETDFLT means that the foreign key is set
** key is set to NULL.  CASCADE means that a DELETE or UPDATE of the
** to its default value.  CASCADE means that a DELETE or UPDATE of the
** referenced table row is propagated into the row that holds the
** foreign key.
**
** The OE_Default value is a place holder that means to use whatever
** conflict resolution algorthm is required from context.
**
** The following symbolic values are used to record which type
** of action to take.
** of conflict resolution action to take.
*/
#define OE_None     0   /* There is no constraint to check */
#define OE_Rollback 1   /* Fail the operation and rollback the transaction */
#define OE_Abort    2   /* Back out changes but do no rollback transaction */
#define OE_Fail     3   /* Stop the operation but leave all prior changes */
#define OE_Ignore   4   /* Ignore the error. Do not do the INSERT or UPDATE */
#define OE_Replace  5   /* Delete existing record, then do INSERT or UPDATE */
2149
2150
2151
2152
2153
2154
2155
2156

2157
2158
2159






2160
2161
2162
2163
2164
2165
2166
2572
2573
2574
2575
2576
2577
2578

2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595







-
+



+
+
+
+
+
+







*/
struct KeyInfo {
  u32 nRef;           /* Number of references to this KeyInfo object */
  u8 enc;             /* Text encoding - one of the SQLITE_UTF* values */
  u16 nKeyField;      /* Number of key columns in the index */
  u16 nAllField;      /* Total columns, including key plus others */
  sqlite3 *db;        /* The database connection */
  u8 *aSortOrder;     /* Sort order for each column. */
  u8 *aSortFlags;     /* Sort order for each column. */
  CollSeq *aColl[1];  /* Collating sequence for each term of the key */
};

/*
** Allowed bit values for entries in the KeyInfo.aSortFlags[] array.
*/
#define KEYINFO_ORDER_DESC    0x01    /* DESC sort order */
#define KEYINFO_ORDER_BIGNULL 0x02    /* NULL is larger than any other value */

/*
** This object holds a record which has been parsed out into individual
** fields, for the purposes of doing a comparison.
**
** A record is an object that contains one or more fields of data.
** Records are used to store the content of a table row and to store
** the key of an index.  A blob encoding of a record is created by
2191
2192
2193
2194
2195
2196
2197





2198
2199
2200
2201
2202
2203
2204
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638







+
+
+
+
+







** before the first match or immediately after the last match.  The
** eqSeen field will indicate whether or not an exact match exists in the
** b-tree.
*/
struct UnpackedRecord {
  KeyInfo *pKeyInfo;  /* Collation and sort-order information */
  Mem *aMem;          /* Values */
  union {
    char *z;            /* Cache of aMem[0].z for vdbeRecordCompareString() */
    i64 i;              /* Cache of aMem[0].u.i for vdbeRecordCompareInt() */
  } u;
  int n;              /* Cache of aMem[0].n used by vdbeRecordCompareString() */
  u16 nField;         /* Number of entries in apMem[] */
  i8 default_rc;      /* Comparison result if keys are equal */
  u8 errCode;         /* Error detected by xRecordCompare (CORRUPT or NOMEM) */
  i8 r1;              /* Value to return if (lhs < rhs) */
  i8 r2;              /* Value to return if (lhs > rhs) */
  u8 eqSeen;          /* True if an equality comparison has been seen */
};
2222
2223
2224
2225
2226
2227
2228
2229
2230


2231
2232












2233
2234

2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253

2254
2255
2256
2257
2258

2259
2260
2261
2262
2263
2264
2265




2266

2267
2268
2269
2270
2271
2272
2273
2274

2275
2276
2277
2278
2279
2280
2281
2282

2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297

2298
2299
2300
2301
2302
2303
2304
2656
2657
2658
2659
2660
2661
2662


2663
2664
2665
2666
2667
2668
2669
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

2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715

2716
2717
2718
2719
2720
2721
2722
2723

2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747

2748
2749
2750
2751
2752
2753
2754
2755







-
-
+
+


+
+
+
+
+
+
+
+
+
+
+
+

-
+


















-
+




-
+







+
+
+
+
-
+







-
+








+














-
+







** first column to be indexed (c3) has an index of 2 in Ex1.aCol[].
** The second column to be indexed (c1) has an index of 0 in
** Ex1.aCol[], hence Ex2.aiColumn[1]==0.
**
** The Index.onError field determines whether or not the indexed columns
** must be unique and what to do if they are not.  When Index.onError=OE_None,
** it means this is not a unique index.  Otherwise it is a unique index
** and the value of Index.onError indicate the which conflict resolution
** algorithm to employ whenever an attempt is made to insert a non-unique
** and the value of Index.onError indicates which conflict resolution
** algorithm to employ when an attempt is made to insert a non-unique
** element.
**
** The colNotIdxed bitmask is used in combination with SrcItem.colUsed
** for a fast test to see if an index can serve as a covering index.
** colNotIdxed has a 1 bit for every column of the original table that
** is *not* available in the index.  Thus the expression
** "colUsed & colNotIdxed" will be non-zero if the index is not a
** covering index.  The most significant bit of of colNotIdxed will always
** be true (note-20221022-a).  If a column beyond the 63rd column of the
** table is used, the "colUsed & colNotIdxed" test will always be non-zero
** and we have to assume either that the index is not covering, or use
** an alternative (slower) algorithm to determine whether or not
** the index is covering.
**
** While parsing a CREATE TABLE or CREATE INDEX statement in order to
** generate VDBE code (as opposed to parsing one read from an sqlite_master
** generate VDBE code (as opposed to parsing one read from an sqlite_schema
** table as part of parsing an existing database schema), transient instances
** of this structure may be created. In this case the Index.tnum variable is
** used to store the address of a VDBE instruction, not a database page
** number (it cannot - the database page is not allocated until the VDBE
** program is executed). See convertToWithoutRowidTable() for details.
*/
struct Index {
  char *zName;             /* Name of this index */
  i16 *aiColumn;           /* Which columns are used by this index.  1st is 0 */
  LogEst *aiRowLogEst;     /* From ANALYZE: Est. rows selected by each column */
  Table *pTable;           /* The SQL table being indexed */
  char *zColAff;           /* String defining the affinity of each column */
  Index *pNext;            /* The next index associated with the same table */
  Schema *pSchema;         /* Schema containing this index */
  u8 *aSortOrder;          /* for each column: True==DESC, False==ASC */
  const char **azColl;     /* Array of collation sequence names for index */
  Expr *pPartIdxWhere;     /* WHERE clause for partial indices */
  ExprList *aColExpr;      /* Column expressions */
  int tnum;                /* DB Page containing root of this index */
  Pgno tnum;               /* DB Page containing root of this index */
  LogEst szIdxRow;         /* Estimated average row size in bytes */
  u16 nKeyCol;             /* Number of columns forming the key */
  u16 nColumn;             /* Number of columns stored in the index */
  u8 onError;              /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
  unsigned idxType:2;      /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
  unsigned idxType:2;      /* 0:Normal 1:UNIQUE, 2:PRIMARY KEY, 3:IPK */
  unsigned bUnordered:1;   /* Use this index for == or IN queries only */
  unsigned uniqNotNull:1;  /* True if UNIQUE and NOT NULL for all columns */
  unsigned isResized:1;    /* True if resizeIndexObject() has been called */
  unsigned isCovering:1;   /* True if this is a covering index */
  unsigned noSkipScan:1;   /* Do not try to use skip-scan if true */
  unsigned hasStat1:1;     /* aiRowLogEst values come from sqlite_stat1 */
  unsigned bNoQuery:1;     /* Do not use this index to optimize queries */
  unsigned bAscKeyBug:1;   /* True if the bba7b69f9849b5bf bug applies */
  unsigned bHasVCol:1;     /* Index references one or more VIRTUAL columns */
  unsigned bHasExpr:1;     /* Index contains an expression, either a literal
                           ** expression, or a reference to a VIRTUAL column */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
  int nSample;             /* Number of elements in aSample[] */
  int nSampleCol;          /* Size of IndexSample.anEq[] and so on */
  tRowcnt *aAvgEq;         /* Average nEq values for keys not in aSample */
  IndexSample *aSample;    /* Samples of the left-most key */
  tRowcnt *aiRowEst;       /* Non-logarithmic stat1 data for this index */
  tRowcnt nRowEst0;        /* Non-logarithmic number of rows in the index */
#endif
  Bitmask colNotIdxed;     /* 0 for unindexed columns in pTab */
  Bitmask colNotIdxed;     /* Unindexed columns in pTab */
};

/*
** Allowed values for Index.idxType
*/
#define SQLITE_IDXTYPE_APPDEF      0   /* Created using CREATE INDEX */
#define SQLITE_IDXTYPE_UNIQUE      1   /* Implements a UNIQUE constraint */
#define SQLITE_IDXTYPE_PRIMARYKEY  2   /* Is the PRIMARY KEY for the table */
#define SQLITE_IDXTYPE_IPK         3   /* INTEGER PRIMARY KEY index */

/* Return true if index X is a PRIMARY KEY index */
#define IsPrimaryKeyIndex(X)  ((X)->idxType==SQLITE_IDXTYPE_PRIMARYKEY)

/* Return true if index X is a UNIQUE index */
#define IsUniqueIndex(X)      ((X)->onError!=OE_None)

/* The Index.aiColumn[] values are normally positive integer.  But
** there are some negative values that have special meaning:
*/
#define XN_ROWID     (-1)     /* Indexed column is the rowid */
#define XN_EXPR      (-2)     /* Indexed column is an expression */

/*
** Each sample stored in the sqlite_stat3 table is represented in memory
** Each sample stored in the sqlite_stat4 table is represented in memory
** using a structure of this type.  See documentation at the top of the
** analyze.c source file for additional information.
*/
struct IndexSample {
  void *p;          /* Pointer to sampled record */
  int n;            /* Size of record in bytes */
  tRowcnt *anEq;    /* Est. number of rows where the key equals this sample */
2328
2329
2330
2331
2332
2333
2334
2335

2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347

2348
2349
2350
2351

2352
2353
2354

2355
2356
2357


2358
2359
2360
2361
2362
2363
2364
2365
2366

2367
2368
2369

2370
2371




2372
2373











2374
2375
2376
2377
2378
2379
2380
2381

2382
2383
2384

2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402


2403
2404

2405
2406
2407
2408
2409
2410
2411
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

2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845

2846
2847
2848

2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865


2866
2867
2868

2869
2870
2871
2872
2873
2874
2875
2876







-
+












+


-
-
+



+

-
-
+
+
-
-






-
+

-

+


+
+
+
+


+
+
+
+
+
+
+
+
+
+
+







-
+


-
+
















-
-
+
+

-
+







};

/*
** An instance of this structure contains information needed to generate
** code for a SELECT that contains aggregate functions.
**
** If Expr.op==TK_AGG_COLUMN or TK_AGG_FUNCTION then Expr.pAggInfo is a
** pointer to this structure.  The Expr.iColumn field is the index in
** pointer to this structure.  The Expr.iAgg field is the index in
** AggInfo.aCol[] or AggInfo.aFunc[] of information needed to generate
** code for that node.
**
** AggInfo.pGroupBy and AggInfo.aFunc.pExpr point to fields within the
** original Select structure that describes the SELECT statement.  These
** fields do not need to be freed when deallocating the AggInfo structure.
*/
struct AggInfo {
  u8 directMode;          /* Direct rendering mode means take data directly
                          ** from source tables rather than from accumulators */
  u8 useSortingIdx;       /* In direct mode, reference the sorting index rather
                          ** than the source table */
  u16 nSortingColumn;     /* Number of columns in the sorting index */
  int sortingIdx;         /* Cursor number of the sorting index */
  int sortingIdxPTab;     /* Cursor number of pseudo-table */
  int nSortingColumn;     /* Number of columns in the sorting index */
  int mnReg, mxReg;       /* Range of registers allocated for aCol and aFunc */
  int iFirstReg;          /* First register in range for aCol[] and aFunc[] */
  ExprList *pGroupBy;     /* The group by clause */
  struct AggInfo_col {    /* For each column used in source tables */
    Table *pTab;             /* Source table */
    Expr *pCExpr;            /* The original expression */
    int iTable;              /* Cursor number of the source table */
    int iColumn;             /* Column number within the source table */
    int iSorterColumn;       /* Column number in the sorting index */
    i16 iColumn;             /* Column number within the source table */
    i16 iSorterColumn;       /* Column number in the sorting index */
    int iMem;                /* Memory location that acts as accumulator */
    Expr *pExpr;             /* The original expression */
  } *aCol;
  int nColumn;            /* Number of used entries in aCol[] */
  int nAccumulator;       /* Number of columns that show through to the output.
                          ** Additional columns are used only as parameters to
                          ** aggregate functions */
  struct AggInfo_func {   /* For each aggregate function */
    Expr *pExpr;             /* Expression encoding the 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 */
#ifdef SQLITE_DEBUG
  Select *pSelect;        /* SELECT statement that this AggInfo supports */
#endif
};

/*
** Macros to compute aCol[] and aFunc[] register numbers.
**
** These macros should not be used prior to the call to 
** assignAggregateRegisters() that computes the value of pAggInfo->iFirstReg.
** The assert()s that are part of this macro verify that constraint.
*/
#define AggInfoColumnReg(A,I)  (assert((A)->iFirstReg),(A)->iFirstReg+(I))
#define AggInfoFuncReg(A,I)    \
                      (assert((A)->iFirstReg),(A)->iFirstReg+(A)->nColumn+(I))

/*
** The datatype ynVar is a signed integer, either 16-bit or 32-bit.
** Usually it is 16-bits.  But if SQLITE_MAX_VARIABLE_NUMBER is greater
** than 32767 we have to make it 32-bit.  16-bit is preferred because
** it uses less memory in the Expr object, which is a big memory user
** in systems with lots of prepared statements.  And few applications
** need more than about 10 or 20 variables.  But some extreme users want
** to have prepared statements with over 32767 variables, and for them
** to have prepared statements with over 32766 variables, and for them
** the option is available (at compile-time).
*/
#if SQLITE_MAX_VARIABLE_NUMBER<=32767
#if SQLITE_MAX_VARIABLE_NUMBER<32767
typedef i16 ynVar;
#else
typedef int ynVar;
#endif

/*
** Each node of an expression in the parse tree is an instance
** of this structure.
**
** Expr.op is the opcode. The integer parser token codes are reused
** as opcodes here. For example, the parser defines TK_GE to be an integer
** code representing the ">=" operator. This same integer code is reused
** to represent the greater-than-or-equal-to operator in the expression
** tree.
**
** If the expression is an SQL literal (TK_INTEGER, TK_FLOAT, TK_BLOB,
** or TK_STRING), then Expr.token contains the text of the SQL literal. If
** the expression is a variable (TK_VARIABLE), then Expr.token contains the
** or TK_STRING), then Expr.u.zToken contains the text of the SQL literal. If
** the expression is a variable (TK_VARIABLE), then Expr.u.zToken contains the
** variable name. Finally, if the expression is an SQL function (TK_FUNCTION),
** then Expr.token contains the name of the function.
** then Expr.u.zToken contains the name of the function.
**
** Expr.pRight and Expr.pLeft are the left and right subexpressions of a
** binary operator. Either or both may be NULL.
**
** Expr.x.pList is a list of arguments if the expression is an SQL function,
** a CASE expression or an IN expression of the form "<lhs> IN (<y>, <z>...)".
** Expr.x.pSelect is used if the expression is a sub-select or an expression of
2437
2438
2439
2440
2441
2442
2443
2444

2445
2446
2447
2448
2449
2450
2451
2452
2453
2454






2455


2456
2457
2458
2459
2460
2461
2462
2902
2903
2904
2905
2906
2907
2908

2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925

2926
2927
2928
2929
2930
2931
2932
2933
2934







-
+










+
+
+
+
+
+
-
+
+







**
** ALLOCATION NOTES:
**
** Expr objects can use a lot of memory space in database schema.  To
** help reduce memory requirements, sometimes an Expr object will be
** truncated.  And to reduce the number of memory allocations, sometimes
** two or more Expr objects will be stored in a single memory allocation,
** together with Expr.zToken strings.
** together with Expr.u.zToken strings.
**
** If the EP_Reduced and EP_TokenOnly flags are set when
** an Expr object is truncated.  When EP_Reduced is set, then all
** the child Expr objects in the Expr.pLeft and Expr.pRight subtrees
** are contained within the same memory allocation.  Note, however, that
** the subtrees in Expr.x.pList or Expr.x.pSelect are always separately
** allocated, regardless of whether or not EP_Reduced is set.
*/
struct Expr {
  u8 op;                 /* Operation performed by this node */
  char affExpr;          /* affinity, or RAISE type */
  u8 op2;                /* TK_REGISTER/TK_TRUTH: original value of Expr.op
                         ** TK_COLUMN: the value of p5 for OP_Column
                         ** TK_AGG_FUNCTION: nesting depth
                         ** TK_FUNCTION: NC_SelfRef flag if needs OP_PureFunc */
#ifdef SQLITE_DEBUG
  char affinity;         /* The affinity of the column or 0 if not a column */
  u8 vvaFlags;           /* Verification flags. */
#endif
  u32 flags;             /* Various flags.  EP_* See below */
  union {
    char *zToken;          /* Token value. Zero terminated and dequoted */
    int iValue;            /* Non-negative integer value if EP_IntValue */
  } u;

  /* If the EP_TokenOnly flag is set in the Expr.flags mask, then no
2479
2480
2481
2482
2483
2484
2485


2486
2487
2488
2489
2490

2491
2492


2493
2494

2495
2496
2497
2498
2499





2500
2501
2502
2503
2504





2505
2506
2507
2508
2509






2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520











2521
2522
2523
2524
2525
2526
2527






2528
2529
2530









2531
2532
2533

2534
2535
2536
2537
2538
2539

2540
2541
2542
2543
2544
2545


















2546
2547
2548
2549
2550
2551
2552



2553
2554


2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571












2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586













2587
2588
2589

2590
2591
2592
2593
2594
2595





2596
2597
2598








2599
2600

2601
2602
2603
2604


2605
2606
2607
2608







2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624


2625
2626

2627
2628



2629

2630
2631
2632
2633
2634
2635
2636



2637
2638
2639
2640
2641







2642
2643
2644
2645
2646
2647
2648
2649


































































2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
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
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716

2717
2718

2719
2720
2721
2722
2723
2724
2725
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965


2966
2967


2968
2969
2970
2971
2972

2973
2974
2975
2976
2977
2978
2979
2980


2981
2982
2983
2984
2985
2986




2987
2988
2989
2990
2991
2992











2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003







3004
3005
3006
3007
3008
3009



3010
3011
3012
3013
3014
3015
3016
3017
3018
3019


3020
3021
3022
3023
3024


3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055

3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099







3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118




3119
3120
3121
3122
3123



3124
3125
3126
3127
3128
3129
3130
3131
3132

3133
3134
3135
3136

3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170


3171
3172
3173

3174
3175
3176
3177




3178
3179
3180





3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265





























3266
3267
3268
3269
3270
3271







3272
3273
3274
3275
3276
3277
3278
3279
3280

3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300

3301
3302

3303
3304
3305
3306
3307
3308
3309
3310







+
+





+
-
-
+
+
-
-
+




-
+
+
+
+
+



-
-
+
+
+
+
+

-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+

-
-
+




-
-
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
+
+
+


+
+

















+
+
+
+
+
+
+
+
+
+
+
+








-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+



+


-
-
-
-
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+

-
+



-
+
+




+
+
+
+
+
+
+
















+
+


+
-
-
+
+
+
-
+



-
-
-
-
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+





-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-




















-
+

-
+







#if SQLITE_MAX_EXPR_DEPTH>0
  int nHeight;           /* Height of the tree headed by this node */
#endif
  int iTable;            /* TK_COLUMN: cursor number of table holding column
                         ** TK_REGISTER: register number
                         ** TK_TRIGGER: 1 -> new, 0 -> old
                         ** EP_Unlikely:  134217728 times likelihood
                         ** TK_IN: ephemerial table holding RHS
                         ** TK_SELECT_COLUMN: Number of columns on the LHS
                         ** TK_SELECT: 1st register of result vector */
  ynVar iColumn;         /* TK_COLUMN: column index.  -1 for rowid.
                         ** TK_VARIABLE: variable number (always >= 1).
                         ** TK_SELECT_COLUMN: column of the result vector */
  i16 iAgg;              /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
  union {
  i16 iRightJoinTable;   /* If EP_FromJoin, the right table of the join */
  u8 op2;                /* TK_REGISTER: original value of Expr.op
    int iJoin;             /* If EP_OuterON or EP_InnerON, the right table */
    int iOfst;             /* else: start of token from start of statement */
                         ** TK_COLUMN: the value of p5 for OP_Column
                         ** TK_AGG_FUNCTION: nesting depth */
  } w;
  AggInfo *pAggInfo;     /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
  union {
    Table *pTab;           /* TK_COLUMN: Table containing column. Can be NULL
                           ** for a column of an index on an expression */
    Window *pWin;          /* TK_FUNCTION: Window definition for the func */
    Window *pWin;          /* EP_WinFunc: Window/Filter defn for a function */
    struct {               /* TK_IN, TK_SELECT, and TK_EXISTS */
      int iAddr;             /* Subroutine entry address */
      int regReturn;         /* Register used to hold return address */
    } sub;
  } y;
};

/*
** The following are the meanings of bits in the Expr.flags field.
/* The following are the meanings of bits in the Expr.flags field.
** Value restrictions:
**
**          EP_Agg == NC_HasAgg == SF_HasAgg
**          EP_Win == NC_HasWin
*/
#define EP_FromJoin  0x000001 /* Originates in ON/USING clause of outer join */
#define EP_Agg       0x000002 /* Contains one or more aggregate functions */
#define EP_HasFunc   0x000004 /* Contains one or more functions of any kind */
#define EP_FixedCol  0x000008 /* TK_Column with a known fixed value */
#define EP_OuterON    0x000001 /* Originates in ON/USING clause of outer join */
#define EP_InnerON    0x000002 /* Originates in ON/USING of an inner join */
#define EP_Distinct   0x000004 /* Aggregate function with DISTINCT keyword */
#define EP_HasFunc    0x000008 /* Contains one or more functions of any kind */
#define EP_Agg        0x000010 /* Contains one or more aggregate functions */
#define EP_FixedCol   0x000020 /* TK_Column with a known fixed value */
#define EP_Distinct  0x000010 /* Aggregate function with DISTINCT keyword */
#define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */
#define EP_DblQuoted 0x000040 /* token.z was originally in "..." */
#define EP_InfixFunc 0x000080 /* True for an infix function: LIKE, GLOB, etc */
#define EP_Collate   0x000100 /* Tree contains a TK_COLLATE operator */
#define EP_Generic   0x000200 /* Ignore COLLATE or affinity on this tree */
#define EP_IntValue  0x000400 /* Integer value contained in u.iValue */
#define EP_xIsSelect 0x000800 /* x.pSelect is valid (otherwise x.pList is) */
#define EP_Skip      0x001000 /* COLLATE, AS, or UNLIKELY */
#define EP_Reduced   0x002000 /* Expr struct EXPR_REDUCEDSIZE bytes only */
#define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */
#define EP_VarSelect  0x000040 /* pSelect is correlated, not constant */
#define EP_DblQuoted  0x000080 /* token.z was originally in "..." */
#define EP_InfixFunc  0x000100 /* True for an infix function: LIKE, GLOB, etc */
#define EP_Collate    0x000200 /* Tree contains a TK_COLLATE operator */
#define EP_Commuted   0x000400 /* Comparison operator has been commuted */
#define EP_IntValue   0x000800 /* Integer value contained in u.iValue */
#define EP_xIsSelect  0x001000 /* x.pSelect is valid (otherwise x.pList is) */
#define EP_Skip       0x002000 /* Operator does not contribute to affinity */
#define EP_Reduced    0x004000 /* Expr struct EXPR_REDUCEDSIZE bytes only */
#define EP_Win        0x008000 /* Contains window functions */
#define EP_TokenOnly  0x010000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */
#define EP_Static    0x008000 /* Held in memory not obtained from malloc() */
#define EP_MemToken  0x010000 /* Need to sqlite3DbFree() Expr.zToken */
#define EP_NoReduce  0x020000 /* Cannot EXPRDUP_REDUCE this Expr */
#define EP_Unlikely  0x040000 /* unlikely() or likelihood() function */
#define EP_ConstFunc 0x080000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */
#define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */
#define EP_Subquery  0x200000 /* Tree contains a TK_SELECT operator */
                   /* 0x020000 // Available for reuse */
#define EP_IfNullRow  0x040000 /* The TK_IF_NULL_ROW opcode */
#define EP_Unlikely   0x080000 /* unlikely() or likelihood() function */
#define EP_ConstFunc  0x100000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */
#define EP_CanBeNull  0x200000 /* Can be null despite NOT NULL constraint */
#define EP_Subquery   0x400000 /* Tree contains a TK_SELECT operator */
#define EP_Alias     0x400000 /* Is an alias for a result set column */
#define EP_Leaf      0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */
#define EP_WinFunc  0x1000000 /* TK_FUNCTION with Expr.y.pWin set */
#define EP_Leaf       0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */
#define EP_WinFunc   0x1000000 /* TK_FUNCTION with Expr.y.pWin set */
#define EP_Subrtn    0x2000000 /* Uses Expr.y.sub. TK_IN, _SELECT, or _EXISTS */
#define EP_Quoted    0x4000000 /* TK_ID was originally quoted */
#define EP_Static    0x8000000 /* Held in memory not obtained from malloc() */
#define EP_IsTrue   0x10000000 /* Always has boolean value of TRUE */
#define EP_IsFalse  0x20000000 /* Always has boolean value of FALSE */
#define EP_FromDDL  0x40000000 /* Originates from sqlite_schema */
               /*   0x80000000 // Available */

/*
** The EP_Propagate mask is a set of properties that automatically propagate
/* The EP_Propagate mask is a set of properties that automatically propagate
** upwards into parent nodes.
*/
#define EP_Propagate (EP_Collate|EP_Subquery|EP_HasFunc)

/*
** These macros can be used to test, set, or clear bits in the
/* Macros can be used to test, set, or clear bits in the
** Expr.flags field.
*/
#define ExprHasProperty(E,P)     (((E)->flags&(P))!=0)
#define ExprHasAllProperty(E,P)  (((E)->flags&(P))==(P))
#define ExprSetProperty(E,P)     (E)->flags|=(P)
#define ExprClearProperty(E,P)   (E)->flags&=~(P)
#define ExprAlwaysTrue(E)   (((E)->flags&(EP_OuterON|EP_IsTrue))==EP_IsTrue)
#define ExprAlwaysFalse(E)  (((E)->flags&(EP_OuterON|EP_IsFalse))==EP_IsFalse)

/* Macros used to ensure that the correct members of unions are accessed
** in Expr.
*/
#define ExprUseUToken(E)    (((E)->flags&EP_IntValue)==0)
#define ExprUseUValue(E)    (((E)->flags&EP_IntValue)!=0)
#define ExprUseXList(E)     (((E)->flags&EP_xIsSelect)==0)
#define ExprUseXSelect(E)   (((E)->flags&EP_xIsSelect)!=0)
#define ExprUseYTab(E)      (((E)->flags&(EP_WinFunc|EP_Subrtn))==0)
#define ExprUseYWin(E)      (((E)->flags&EP_WinFunc)!=0)
#define ExprUseYSub(E)      (((E)->flags&EP_Subrtn)!=0)

/* Flags for use with Expr.vvaFlags
*/
#define EP_NoReduce   0x01  /* Cannot EXPRDUP_REDUCE this Expr */
#define EP_Immutable  0x02  /* Do not change this Expr node */

/* The ExprSetVVAProperty() macro is used for Verification, Validation,
** and Accreditation only.  It works like ExprSetProperty() during VVA
** processes but is a no-op for delivery.
*/
#ifdef SQLITE_DEBUG
# define ExprSetVVAProperty(E,P)  (E)->flags|=(P)
# define ExprSetVVAProperty(E,P)   (E)->vvaFlags|=(P)
# define ExprHasVVAProperty(E,P)   (((E)->vvaFlags&(P))!=0)
# define ExprClearVVAProperties(E) (E)->vvaFlags = 0
#else
# define ExprSetVVAProperty(E,P)
# define ExprHasVVAProperty(E,P)   0
# define ExprClearVVAProperties(E)
#endif

/*
** Macros to determine the number of bytes required by a normal Expr
** struct, an Expr struct with the EP_Reduced flag set in Expr.flags
** and an Expr struct with the EP_TokenOnly flag set.
*/
#define EXPR_FULLSIZE           sizeof(Expr)           /* Full size */
#define EXPR_REDUCEDSIZE        offsetof(Expr,iTable)  /* Common features */
#define EXPR_TOKENONLYSIZE      offsetof(Expr,pLeft)   /* Fewer features */

/*
** Flags passed to the sqlite3ExprDup() function. See the header comment
** above sqlite3ExprDup() for details.
*/
#define EXPRDUP_REDUCE         0x0001  /* Used reduced-size Expr nodes */

/*
** True if the expression passed as an argument was a function with
** an OVER() clause (a window function).
*/
#ifdef SQLITE_OMIT_WINDOWFUNC
# define IsWindowFunc(p) 0
#else
# define IsWindowFunc(p) ( \
    ExprHasProperty((p), EP_WinFunc) && p->y.pWin->eFrmType!=TK_FILTER \
 )
#endif

/*
** A list of expressions.  Each expression may optionally have a
** name.  An expr/name combination can be used in several ways, such
** as the list of "expr AS ID" fields following a "SELECT" or in the
** list of "ID = expr" items in an UPDATE.  A list of expressions can
** also be used as the argument to a function, in which case the a.zName
** field is not used.
**
** By default the Expr.zSpan field holds a human-readable description of
** the expression that is used in the generation of error messages and
** column labels.  In this case, Expr.zSpan is typically the text of a
** column expression as it exists in a SELECT statement.  However, if
** the bSpanIsTab flag is set, then zSpan is overloaded to mean the name
** of the result column in the form: DATABASE.TABLE.COLUMN.  This later
** form is used for name resolution with nested FROM clauses.
** In order to try to keep memory usage down, the Expr.a.zEName field
** is used for multiple purposes:
**
**     eEName          Usage
**    ----------       -------------------------
**    ENAME_NAME       (1) the AS of result set column
**                     (2) COLUMN= of an UPDATE
**
**    ENAME_TAB        DB.TABLE.NAME used to resolve names
**                     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 *zName;            /* Token associated with this expression */
    char *zSpan;            /* Original text of the expression */
    u8 sortOrder;           /* 1 for DESC or 0 for ASC */
    unsigned done :1;       /* A flag to indicate when processing is finished */
    char *zEName;           /* Token associated with this expression */
    struct {
      u8 sortFlags;           /* Mask of KEYINFO_ORDER_* flags */
      unsigned eEName :2;     /* Meaning of zEName */
      unsigned done :1;       /* Indicates when processing is finished */
    unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */
    unsigned reusable :1;   /* Constant expression is reusable */
    unsigned bSorterRef :1; /* Defer evaluation until after sorting */
      unsigned reusable :1;   /* Constant expression is reusable */
      unsigned bSorterRef :1; /* Defer evaluation until after sorting */
      unsigned bNulls :1;     /* True if explicit "NULLS FIRST/LAST" */
      unsigned bUsed :1;      /* This column used in a SF_NestedFrom subquery */
      unsigned bUsingTerm:1;  /* Term from the USING clause of a NestedFrom */
      unsigned bNoExpand: 1;  /* Term is an auxiliary in NestedFrom and should
                              ** not be expanded by "*" in parent queries */
    } fg;
    union {
      struct {
      struct {             /* Used by any ExprList other than Parse.pConsExpr */
        u16 iOrderByCol;      /* For ORDER BY, column number in result set */
        u16 iAlias;           /* Index into Parse.aAlias[] for zName */
      } x;
      int iConstExprReg;      /* Register in which Expr value is cached */
      int iConstExprReg;   /* Register in which Expr value is cached. Used only
                           ** by Parse.pConstExpr */
    } u;
  } a[1];                  /* One slot for each expression in the list */
};

/*
** Allowed values for Expr.a.eEName
*/
#define ENAME_NAME  0       /* The AS clause of a result set */
#define ENAME_SPAN  1       /* Complete text of the result set expression */
#define ENAME_TAB   2       /* "DB.TABLE.NAME" for the result set */

/*
** An instance of this structure can hold a simple list of identifiers,
** such as the list "a,b,c" in the following statements:
**
**      INSERT INTO t(a,b,c) VALUES ...;
**      CREATE INDEX idx ON t(a,b,c);
**      CREATE TRIGGER trig BEFORE UPDATE ON t(a,b,c) ...;
**
** The IdList.a.idx field is used when the IdList represents the list of
** column names after a table name in an INSERT statement.  In the statement
**
**     INSERT INTO t(a,b,c) ...
**
** If "a" is the k-th column of table "t", then IdList.a[0].idx==k.
*/
struct IdList {
  int nId;         /* Number of identifiers on the list */
  u8 eU4;          /* Which element of a.u4 is valid */
  struct IdList_item {
    char *zName;      /* Name of the identifier */
    union {
    int idx;          /* Index in some Table.aCol[] of a column named zName */
  } *a;
      int idx;          /* Index in some Table.aCol[] of a column named zName */
      Expr *pExpr;      /* Expr to implement a USING variable -- NOT USED */
    } u4;
  int nId;         /* Number of identifiers on the list */
  } a[1];
};

/*
** The following structure describes the FROM clause of a SELECT statement.
** Each table or subquery in the FROM clause is a separate element of
** the SrcList.a[] array.
**
** Allowed values for IdList.eType, which determines which value of the a.u4
** is valid.
*/
** With the addition of multiple database support, the following structure
** can also be used to describe a particular table such as the table that
** is modified by an INSERT, DELETE, or UPDATE statement.  In standard SQL,
** such a table must be a simple name: ID.  But in SQLite, the table can
** now be identified by a database name, a dot, then the table name: ID.ID.
#define EU4_NONE   0   /* Does not use IdList.a.u4 */
#define EU4_IDX    1   /* Uses IdList.a.u4.idx */
#define EU4_EXPR   2   /* Uses IdList.a.u4.pExpr -- NOT CURRENTLY USED */

/*
** The SrcItem object represents a single term in the FROM clause of a query.
** The SrcList object is mostly an array of SrcItems.
**
** The jointype starts out showing the join type between the current table
** and the next table on the list.  The parser builds the list this way.
** But sqlite3SrcListShiftJoinType() later shifts the jointypes so that each
** jointype expresses the join between the table and the previous table.
**
** In the colUsed field, the high-order bit (bit 63) is set if the table
** contains more than 63 columns and the 64-th or later column is used.
**
** Union member validity:
**
**    u1.zIndexedBy          fg.isIndexedBy && !fg.isTabFunc
**    u1.pFuncArg            fg.isTabFunc   && !fg.isIndexedBy
**    u2.pIBIndex            fg.isIndexedBy && !fg.isCte
**    u2.pCteUse             fg.isCte       && !fg.isIndexedBy
*/
struct SrcItem {
  Schema *pSchema;  /* Schema to which this item is fixed */
  char *zDatabase;  /* Name of database holding this table */
  char *zName;      /* Name of the table */
  char *zAlias;     /* The "B" part of a "A AS B" phrase.  zName is the "A" */
  Table *pTab;      /* An SQL table corresponding to zName */
  Select *pSelect;  /* A SELECT statement used in place of a table name */
  int addrFillSub;  /* Address of subroutine to manifest a subquery */
  int regReturn;    /* Register holding return address of addrFillSub */
  int regResult;    /* Registers holding results of a co-routine */
  struct {
    u8 jointype;      /* Type of join between this table and the previous */
    unsigned notIndexed :1;    /* True if there is a NOT INDEXED clause */
    unsigned isIndexedBy :1;   /* True if there is an INDEXED BY clause */
    unsigned isTabFunc :1;     /* True if table-valued-function syntax */
    unsigned isCorrelated :1;  /* True if sub-query is correlated */
    unsigned isMaterialized:1; /* This is a materialized view */
    unsigned viaCoroutine :1;  /* Implemented as a co-routine */
    unsigned isRecursive :1;   /* True for recursive reference in WITH */
    unsigned fromDDL :1;       /* Comes from sqlite_schema */
    unsigned isCte :1;         /* This is a CTE */
    unsigned notCte :1;        /* This item may not match a CTE */
    unsigned isUsing :1;       /* u3.pUsing is valid */
    unsigned isOn :1;          /* u3.pOn was once valid and non-NULL */
    unsigned isSynthUsing :1;  /* u3.pUsing is synthensized from NATURAL */
    unsigned isNestedFrom :1;  /* pSelect is a SF_NestedFrom subquery */
  } fg;
  int iCursor;      /* The VDBE cursor number used to access this table */
  union {
    Expr *pOn;        /* fg.isUsing==0 =>  The ON clause of a join */
    IdList *pUsing;   /* fg.isUsing==1 =>  The USING clause of a join */
  } u3;
  Bitmask colUsed;  /* Bit N set if column N used. Details above for N>62 */
  union {
    char *zIndexedBy;    /* Identifier from "INDEXED BY <zIndex>" clause */
    ExprList *pFuncArg;  /* Arguments to table-valued-function */
  } u1;
  union {
    Index *pIBIndex;  /* Index structure corresponding to u1.zIndexedBy */
    CteUse *pCteUse;  /* CTE Usage info when fg.isCte is true */
  } u2;
};

/*
** The OnOrUsing object represents either an ON clause or a USING clause.
** It can never be both at the same time, but it can be neither.
*/
struct OnOrUsing {
  Expr *pOn;         /* The ON clause of a join */
  IdList *pUsing;    /* The USING clause of a join */
};

/*
** This object represents one or more tables that are the source of
** content for an SQL statement.  For example, a single SrcList object
** is used to hold the FROM clause of a SELECT statement.  SrcList also
** represents the target tables for DELETE, INSERT, and UPDATE statements.
**
*/
struct SrcList {
  int nSrc;        /* Number of tables or subqueries in the FROM clause */
  u32 nAlloc;      /* Number of entries allocated in a[] below */
  struct SrcList_item {
    Schema *pSchema;  /* Schema to which this item is fixed */
    char *zDatabase;  /* Name of database holding this table */
    char *zName;      /* Name of the table */
    char *zAlias;     /* The "B" part of a "A AS B" phrase.  zName is the "A" */
    Table *pTab;      /* An SQL table corresponding to zName */
    Select *pSelect;  /* A SELECT statement used in place of a table name */
    int addrFillSub;  /* Address of subroutine to manifest a subquery */
    int regReturn;    /* Register holding return address of addrFillSub */
    int regResult;    /* Registers holding results of a co-routine */
    struct {
      u8 jointype;      /* Type of join between this table and the previous */
      unsigned notIndexed :1;    /* True if there is a NOT INDEXED clause */
      unsigned isIndexedBy :1;   /* True if there is an INDEXED BY clause */
      unsigned isTabFunc :1;     /* True if table-valued-function syntax */
      unsigned isCorrelated :1;  /* True if sub-query is correlated */
      unsigned viaCoroutine :1;  /* Implemented as a co-routine */
      unsigned isRecursive :1;   /* True for recursive reference in WITH */
    } fg;
    int iCursor;      /* The VDBE cursor number used to access this table */
    Expr *pOn;        /* The ON clause of a join */
    IdList *pUsing;   /* The USING clause of a join */
    Bitmask colUsed;  /* Bit N (1<<N) set if column N of pTab is used */
    union {
      char *zIndexedBy;    /* Identifier from "INDEXED BY <zIndex>" clause */
      ExprList *pFuncArg;  /* Arguments to table-valued-function */
    } u1;
    Index *pIBIndex;  /* Index structure corresponding to u1.zIndexedBy */
  } a[1];             /* One entry for each identifier on the list */
  SrcItem a[1];    /* One entry for each identifier on the list */
};

/*
** Permitted values of the SrcList.a.jointype field
*/
#define JT_INNER     0x0001    /* Any kind of inner or cross join */
#define JT_CROSS     0x0002    /* Explicit use of the CROSS keyword */
#define JT_NATURAL   0x0004    /* True for a "natural" join */
#define JT_LEFT      0x0008    /* Left outer join */
#define JT_RIGHT     0x0010    /* Right outer join */
#define JT_OUTER     0x0020    /* The "OUTER" keyword is present */
#define JT_ERROR     0x0040    /* unknown or unsupported join type */
#define JT_INNER     0x01    /* Any kind of inner or cross join */
#define JT_CROSS     0x02    /* Explicit use of the CROSS keyword */
#define JT_NATURAL   0x04    /* True for a "natural" join */
#define JT_LEFT      0x08    /* Left outer join */
#define JT_RIGHT     0x10    /* Right outer join */
#define JT_OUTER     0x20    /* The "OUTER" keyword is present */
#define JT_LTORJ     0x40    /* One of the LEFT operands of a RIGHT JOIN
                             ** Mnemonic: Left Table Of Right Join */
#define JT_ERROR     0x80    /* unknown or unsupported join type */


/*
** Flags appropriate for the wctrlFlags parameter of sqlite3WhereBegin()
** and the WhereInfo.wctrlFlags member.
**
** Value constraints (enforced via assert()):
**     WHERE_USE_LIMIT  == SF_FixedLimit
*/
#define WHERE_ORDERBY_NORMAL   0x0000 /* No-op */
#define WHERE_ORDERBY_MIN      0x0001 /* ORDER BY processing for min() func */
#define WHERE_ORDERBY_MAX      0x0002 /* ORDER BY processing for max() func */
#define WHERE_ONEPASS_DESIRED  0x0004 /* Want to do one-pass UPDATE/DELETE */
#define WHERE_ONEPASS_MULTIROW 0x0008 /* ONEPASS is ok with multiple rows */
#define WHERE_DUPLICATES_OK    0x0010 /* Ok to return a row more than once */
#define WHERE_OR_SUBCLAUSE     0x0020 /* Processing a sub-WHERE as part of
                                      ** the OR optimization  */
#define WHERE_GROUPBY          0x0040 /* pOrderBy is really a GROUP BY */
#define WHERE_DISTINCTBY       0x0080 /* pOrderby is really a DISTINCT clause */
#define WHERE_WANT_DISTINCT    0x0100 /* All output needs to be distinct */
#define WHERE_SORTBYGROUP      0x0200 /* Support sqlite3WhereIsSorted() */
#define WHERE_SEEK_TABLE       0x0400 /* Do not defer seeks on main table */
#define WHERE_AGG_DISTINCT     0x0400 /* Query is "SELECT agg(DISTINCT ...)" */
#define WHERE_ORDERBY_LIMIT    0x0800 /* ORDERBY+LIMIT on the inner loop */
#define WHERE_SEEK_UNIQ_TABLE  0x1000 /* Do not defer seeks if unique */
#define WHERE_RIGHT_JOIN       0x1000 /* Processing a RIGHT JOIN */
                        /*     0x2000    not currently used */
#define WHERE_USE_LIMIT        0x4000 /* Use the LIMIT in cost estimates */
                        /*     0x8000    not currently used */

/* Allowed return values from sqlite3WhereIsDistinct()
*/
#define WHERE_DISTINCT_NOOP      0  /* DISTINCT keyword not used */
2751
2752
2753
2754
2755
2756
2757

2758
2759
2760
2761
2762


2763
2764
2765
2766
2767
2768
2769
2770
2771




2772
2773
2774
2775
2776
2777
2778
2779
2780
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
2818
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346


3347
3348
3349
3350
3351
3352
3353
3354
3355


3356
3357
3358
3359
3360
3361













3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398

3399
3400
3401
3402
3403
3404



3405
3406
3407
3408
3409
3410


3411
3412
3413
3414
3415
3416
3417
3418
3419
3420







+



-
-
+
+







-
-
+
+
+
+


-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
















-
+



+
+
-
-
-
+
+
+
+
+
+
-
-
+
+
+







struct NameContext {
  Parse *pParse;       /* The parser */
  SrcList *pSrcList;   /* One or more tables used to resolve names */
  union {
    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 */
  u16 ncFlags;         /* Zero or more NC_* flags defined below */
  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.
**
** Value constraints (all checked via assert()):
**    NC_HasAgg    == SF_HasAgg
**    NC_MinMaxAgg == SF_MinMaxAgg == SQLITE_FUNC_MINMAX
**    NC_HasAgg    == SF_HasAgg       == EP_Agg
**    NC_MinMaxAgg == SF_MinMaxAgg    == SQLITE_FUNC_MINMAX
**    NC_OrderAgg  == SF_OrderByReqd  == SQLITE_FUNC_ANYORDER
**    NC_HasWin    == EP_Win
**
*/
#define NC_AllowAgg  0x0001  /* Aggregate functions are allowed here */
#define NC_PartIdx   0x0002  /* True if resolving a partial index WHERE */
#define NC_IsCheck   0x0004  /* True if resolving names in a CHECK constraint */
#define NC_InAggFunc 0x0008  /* True if analyzing arguments to an agg func */
#define NC_HasAgg    0x0010  /* One or more aggregate functions seen */
#define NC_IdxExpr   0x0020  /* True if resolving columns of CREATE INDEX */
#define NC_VarSelect 0x0040  /* A correlated subquery has been seen */
#define NC_UEList    0x0080  /* True if uNC.pEList is used */
#define NC_UAggInfo  0x0100  /* True if uNC.pAggInfo is used */
#define NC_UUpsert   0x0200  /* True if uNC.pUpsert is used */
#define NC_MinMaxAgg 0x1000  /* min/max aggregates seen.  See note above */
#define NC_Complex   0x2000  /* True if a function or subquery seen */
#define NC_AllowWin  0x4000  /* Window functions are allowed here */
#define NC_AllowAgg  0x000001 /* Aggregate functions are allowed here */
#define NC_PartIdx   0x000002 /* True if resolving a partial index WHERE */
#define NC_IsCheck   0x000004 /* True if resolving a CHECK constraint */
#define NC_GenCol    0x000008 /* True for a GENERATED ALWAYS AS clause */
#define NC_HasAgg    0x000010 /* One or more aggregate functions seen */
#define NC_IdxExpr   0x000020 /* True if resolving columns of CREATE INDEX */
#define NC_SelfRef   0x00002e /* Combo: PartIdx, isCheck, GenCol, and IdxExpr */
#define NC_VarSelect 0x000040 /* A correlated subquery has been seen */
#define NC_UEList    0x000080 /* True if uNC.pEList is used */
#define NC_UAggInfo  0x000100 /* True if uNC.pAggInfo is used */
#define NC_UUpsert   0x000200 /* True if uNC.pUpsert is used */
#define NC_UBaseReg  0x000400 /* True if uNC.iBaseReg is used */
#define NC_MinMaxAgg 0x001000 /* min/max aggregates seen.  See note above */
#define NC_Complex   0x002000 /* True if a function or subquery seen */
#define NC_AllowWin  0x004000 /* Window functions are allowed here */
#define NC_HasWin    0x008000 /* One or more window functions seen */
#define NC_IsDDL     0x010000 /* Resolving names in a CREATE statement */
#define NC_InAggFunc 0x020000 /* True if analyzing arguments to an agg func */
#define NC_FromDDL   0x040000 /* SQL text comes from sqlite_schema */
#define NC_NoSelect  0x080000 /* Do not descend into sub-selects */
#define NC_OrderAgg 0x8000000 /* Has an aggregate other than count/min/max */

/*
** 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
** conflict-target clause.)  The pUpsertTargetWhere is the optional
** WHERE clause used to identify partial unique indexes.
**
** pUpsertSet is the list of column=expr terms of the UPDATE statement. 
** The pUpsertSet field is NULL for a ON CONFLICT DO NOTHING.  The
** pUpsertWhere is the WHERE clause for the UPDATE and is NULL if the
** WHERE clause is omitted.
*/
struct Upsert {
  ExprList *pUpsertTarget;  /* Optional description of conflicting index */
  ExprList *pUpsertTarget;  /* Optional description of conflict target */
  Expr *pUpsertTargetWhere; /* WHERE clause for partial index targets */
  ExprList *pUpsertSet;     /* The SET clause from an ON CONFLICT UPDATE */
  Expr *pUpsertWhere;       /* WHERE clause for the ON CONFLICT UPDATE */
  Upsert *pNextUpsert;      /* Next ON CONFLICT clause in the list */
  u8 isDoUpdate;            /* True for DO UPDATE.  False for DO NOTHING */
  /* The fields above comprise the parse tree for the upsert clause.
  ** The fields below are used to transfer information from the INSERT
  ** processing down into the UPDATE processing while generating code.
  /* Above this point is the parse tree for the ON CONFLICT clauses.
  ** The next group of fields stores intermediate data. */
  void *pToFree;            /* Free memory when deleting the Upsert object */
  /* All fields above are owned by the Upsert object and must be freed
  ** when the Upsert is destroyed.  The fields below are used to transfer
  ** information from the INSERT processing down into the UPDATE processing
  ** Upsert owns the memory allocated above, but not the memory below. */
  Index *pUpsertIdx;        /* Constraint that pUpsertTarget identifies */
  ** while generating code.  The fields below are owned by the INSERT
  ** statement and will be freed by INSERT processing. */
  Index *pUpsertIdx;        /* UNIQUE constraint specified by pUpsertTarget */
  SrcList *pUpsertSrc;      /* Table to be updated */
  int regData;              /* First register holding array of VALUES */
  int iDataCur;             /* Index of the data cursor */
  int iIdxCur;              /* Index of the first index cursor */
};

/*
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842

2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865




2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
































2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
3431
3432
3433
3434
3435
3436
3437

3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464



3465
3466
3467
3468
3469



















3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519



3520
3521
3522
3523
3524
3525
3526







-






+




















-
-
-
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


















-
-
-







** as the OP_OpenEphm instruction is coded because not
** enough information about the compound query is known at that point.
** The KeyInfo for addrOpenTran[0] and [1] contains collating sequences
** for the result set.  The KeyInfo for addrOpenEphm[2] contains collating
** sequences for the ORDER BY clause.
*/
struct Select {
  ExprList *pEList;      /* The fields of the result */
  u8 op;                 /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
  LogEst nSelectRow;     /* Estimated number of result rows */
  u32 selFlags;          /* Various SF_* values */
  int iLimit, iOffset;   /* Memory registers holding LIMIT & OFFSET counters */
  u32 selId;             /* Unique identifier number for this SELECT */
  int addrOpenEphm[2];   /* OP_OpenEphem opcodes related to this select */
  ExprList *pEList;      /* The fields of the result */
  SrcList *pSrc;         /* The FROM clause */
  Expr *pWhere;          /* The WHERE clause */
  ExprList *pGroupBy;    /* The GROUP BY clause */
  Expr *pHaving;         /* The HAVING clause */
  ExprList *pOrderBy;    /* The ORDER BY clause */
  Select *pPrior;        /* Prior select in a compound select statement */
  Select *pNext;         /* Next select to the left in a compound */
  Expr *pLimit;          /* LIMIT expression. NULL means not used. */
  With *pWith;           /* WITH clause attached to this select. Or NULL. */
#ifndef SQLITE_OMIT_WINDOWFUNC
  Window *pWin;          /* List of window functions */
  Window *pWinDefn;      /* List of named window definitions */
#endif
};

/*
** Allowed values for Select.selFlags.  The "SF" prefix stands for
** "Select Flag".
**
** Value constraints (all checked via assert())
**     SF_HasAgg     == NC_HasAgg
**     SF_MinMaxAgg  == NC_MinMaxAgg     == SQLITE_FUNC_MINMAX
**     SF_FixedLimit == WHERE_USE_LIMIT
**     SF_HasAgg      == NC_HasAgg
**     SF_MinMaxAgg   == NC_MinMaxAgg     == SQLITE_FUNC_MINMAX
**     SF_OrderByReqd == NC_OrderAgg      == SQLITE_FUNC_ANYORDER
**     SF_FixedLimit  == WHERE_USE_LIMIT
*/
#define SF_Distinct       0x00001  /* Output should be DISTINCT */
#define SF_All            0x00002  /* Includes the ALL keyword */
#define SF_Resolved       0x00004  /* Identifiers have been resolved */
#define SF_Aggregate      0x00008  /* Contains agg functions or a GROUP BY */
#define SF_HasAgg         0x00010  /* Contains aggregate functions */
#define SF_UsesEphemeral  0x00020  /* Uses the OpenEphemeral opcode */
#define SF_Expanded       0x00040  /* sqlite3SelectExpand() called on this */
#define SF_HasTypeInfo    0x00080  /* FROM subqueries have Table metadata */
#define SF_Compound       0x00100  /* Part of a compound query */
#define SF_Values         0x00200  /* Synthesized from VALUES clause */
#define SF_MultiValue     0x00400  /* Single VALUES term with multiple rows */
#define SF_NestedFrom     0x00800  /* Part of a parenthesized FROM clause */
#define SF_MinMaxAgg      0x01000  /* Aggregate containing min() or max() */
#define SF_Recursive      0x02000  /* The recursive part of a recursive CTE */
#define SF_FixedLimit     0x04000  /* nSelectRow set by a constant LIMIT */
#define SF_MaybeConvert   0x08000  /* Need convertCompoundSelectToSubquery() */
#define SF_Converted      0x10000  /* By convertCompoundSelectToSubquery() */
#define SF_IncludeHidden  0x20000  /* Include hidden columns in output */
#define SF_ComplexResult  0x40000  /* Result contains subquery or function */
#define SF_Distinct      0x0000001 /* Output should be DISTINCT */
#define SF_All           0x0000002 /* Includes the ALL keyword */
#define SF_Resolved      0x0000004 /* Identifiers have been resolved */
#define SF_Aggregate     0x0000008 /* Contains agg functions or a GROUP BY */
#define SF_HasAgg        0x0000010 /* Contains aggregate functions */
#define SF_UsesEphemeral 0x0000020 /* Uses the OpenEphemeral opcode */
#define SF_Expanded      0x0000040 /* sqlite3SelectExpand() called on this */
#define SF_HasTypeInfo   0x0000080 /* FROM subqueries have Table metadata */
#define SF_Compound      0x0000100 /* Part of a compound query */
#define SF_Values        0x0000200 /* Synthesized from VALUES clause */
#define SF_MultiValue    0x0000400 /* Single VALUES term with multiple rows */
#define SF_NestedFrom    0x0000800 /* Part of a parenthesized FROM clause */
#define SF_MinMaxAgg     0x0001000 /* Aggregate containing min() or max() */
#define SF_Recursive     0x0002000 /* The recursive part of a recursive CTE */
#define SF_FixedLimit    0x0004000 /* nSelectRow set by a constant LIMIT */
#define SF_MaybeConvert  0x0008000 /* Need convertCompoundSelectToSubquery() */
#define SF_Converted     0x0010000 /* By convertCompoundSelectToSubquery() */
#define SF_IncludeHidden 0x0020000 /* Include hidden columns in output */
#define SF_ComplexResult 0x0040000 /* Result contains subquery or function */
#define SF_WhereBegin    0x0080000 /* Really a WhereBegin() call.  Debug Only */
#define SF_WinRewrite    0x0100000 /* Window function rewrite accomplished */
#define SF_View          0x0200000 /* SELECT statement is a view */
#define SF_NoopOrderBy   0x0400000 /* ORDER BY is ignored for this query */
#define SF_UFSrcCheck    0x0800000 /* Check pSrc as required by UPDATE...FROM */
#define SF_PushDown      0x1000000 /* SELECT has be modified by push-down opt */
#define SF_MultiPart     0x2000000 /* Has multiple incompatible PARTITIONs */
#define SF_CopyCte       0x4000000 /* SELECT statement is a copy of a CTE */
#define SF_OrderByReqd   0x8000000 /* The ORDER BY clause may not be omitted */
#define SF_UpdateFrom   0x10000000 /* Query originates with UPDATE FROM */

/* True if S exists and has SF_NestedFrom */
#define IsNestedFrom(S) ((S)!=0 && ((S)->selFlags&SF_NestedFrom)!=0)

/*
** The results of a SELECT can be distributed in several ways, as defined
** by one of the following macros.  The "SRT" prefix means "SELECT Result
** Type".
**
**     SRT_Union       Store results as a key in a temporary index
**                     identified by pDest->iSDParm.
**
**     SRT_Except      Remove results from the temporary index pDest->iSDParm.
**
**     SRT_Exists      Store a 1 in memory cell pDest->iSDParm if the result
**                     set is not empty.
**
**     SRT_Discard     Throw the results away.  This is used by SELECT
**                     statements within triggers whose only purpose is
**                     the side-effects of functions.
**
** All of the above are free to ignore their ORDER BY clause. Those that
** follow must honor the ORDER BY clause.
**
**     SRT_Output      Generate a row of output (using the OP_ResultRow
**                     opcode) for each row in the result set.
**
**     SRT_Mem         Only valid if the result is a single column.
**                     Store the first column of the first result row
**                     in register pDest->iSDParm then abandon the rest
**                     of the query.  This destination implies "LIMIT 1".
2943
2944
2945
2946
2947
2948
2949








2950
2951
2952
2953
2954


2955
2956





2957
2958

2959
2960
2961

2962
2963
2964
2965
2966
2967
2968

2969
2970
2971
2972
2973
2974
2975

2976

2977
2978
2979

2980
2981
2982
2983
2984
2985
2986
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577


3578
3579
3580
3581
3582
3583

3584
3585
3586

3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601

3602
3603
3604
3605
3606

3607
3608
3609
3610
3611
3612
3613
3614







+
+
+
+
+
+
+
+





+
+
-
-
+
+
+
+
+

-
+


-
+







+






-
+

+


-
+







**     SRT_Queue       Store results in priority queue pDest->iSDParm (really
**                     an index).  Append a sequence number so that all entries
**                     are distinct.
**
**     SRT_DistQueue   Store results in priority queue pDest->iSDParm only if
**                     the same record has never been stored before.  The
**                     index at pDest->iSDParm+1 hold all prior stores.
**
**     SRT_Upfrom      Store results in the temporary table already opened by
**                     pDest->iSDParm. If (pDest->iSDParm<0), then the temp
**                     table is an intkey table - in this case the first
**                     column returned by the SELECT is used as the integer
**                     key. If (pDest->iSDParm>0), then the table is an index
**                     table. (pDest->iSDParm) is the number of key columns in
**                     each index record in this case.
*/
#define SRT_Union        1  /* Store result as keys in an index */
#define SRT_Except       2  /* Remove result from a UNION index */
#define SRT_Exists       3  /* Store 1 if the result is not empty */
#define SRT_Discard      4  /* Do not save the results anywhere */
#define SRT_DistFifo     5  /* Like SRT_Fifo, but unique results only */
#define SRT_DistQueue    6  /* Like SRT_Queue, but unique results only */
#define SRT_Fifo         5  /* Store result as data with an automatic rowid */
#define SRT_DistFifo     6  /* Like SRT_Fifo, but unique results only */

/* The DISTINCT clause is ignored for all of the above.  Not that
** IgnorableDistinct() implies IgnorableOrderby() */
#define IgnorableDistinct(X) ((X->eDest)<=SRT_DistQueue)

#define SRT_Queue        7  /* Store result in an queue */
#define SRT_DistQueue    8  /* Like SRT_Queue, but unique results only */
#define SRT_Fifo         8  /* Store result as data with an automatic rowid */

/* The ORDER BY clause is ignored for all of the above */
#define IgnorableOrderby(X) ((X->eDest)<=SRT_DistQueue)
#define IgnorableOrderby(X) ((X->eDest)<=SRT_Fifo)

#define SRT_Output       9  /* Output each row of result */
#define SRT_Mem         10  /* Store result in a memory cell */
#define SRT_Set         11  /* Store results as keys in an index */
#define SRT_EphemTab    12  /* Create transient tab and store like SRT_Table */
#define SRT_Coroutine   13  /* Generate a single row of result */
#define SRT_Table       14  /* Store result as data with an automatic rowid */
#define SRT_Upfrom      15  /* Store result as data with rowid */

/*
** An instance of this object describes where to put of the results of
** a SELECT statement.
*/
struct SelectDest {
  u8 eDest;            /* How to dispose of the results.  On of SRT_* above. */
  u8 eDest;            /* How to dispose of the results.  One of SRT_* above. */
  int iSDParm;         /* A parameter used by the eDest disposal method */
  int iSDParm2;        /* A second parameter for the eDest disposal method */
  int iSdst;           /* Base register where results are written */
  int nSdst;           /* Number of registers allocated */
  char *zAffSdst;      /* Affinity used when eDest==SRT_Set */
  char *zAffSdst;      /* Affinity used for SRT_Set */
  ExprList *pOrderBy;  /* Key columns for SRT_Queue and SRT_DistQueue */
};

/*
** During code generation of statements that do inserts into AUTOINCREMENT
** tables, the following information is attached to the Table.u.autoInc.p
** pointer of each autoincrement table to record some side information that
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041




3042

































3043
3044
3045
3046
3047
3048
3049
3659
3660
3661
3662
3663
3664
3665




3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710







-
-
-
-
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







# define DbMaskZero(M)      memset((M),0,sizeof(M))
# define DbMaskSet(M,I)     (M)[(I)/8]|=(1<<((I)&7))
# define DbMaskAllZero(M)   sqlite3DbMaskAllZero(M)
# define DbMaskNonZero(M)   (sqlite3DbMaskAllZero(M)==0)
#else
  typedef unsigned int yDbMask;
# define DbMaskTest(M,I)    (((M)&(((yDbMask)1)<<(I)))!=0)
# define DbMaskZero(M)      (M)=0
# define DbMaskSet(M,I)     (M)|=(((yDbMask)1)<<(I))
# define DbMaskAllZero(M)   (M)==0
# define DbMaskNonZero(M)   (M)!=0
# define DbMaskZero(M)      ((M)=0)
# define DbMaskSet(M,I)     ((M)|=(((yDbMask)1)<<(I)))
# define DbMaskAllZero(M)   ((M)==0)
# define DbMaskNonZero(M)   ((M)!=0)
#endif

/*
** For each index X that has as one of its arguments either an expression
** or the name of a virtual generated column, and if X is in scope such that
** the value of the expression can simply be read from the index, then
** there is an instance of this object on the Parse.pIdxExpr list.
**
** During code generation, while generating code to evaluate expressions,
** this list is consulted and if a matching expression is found, the value
** is read from the index rather than being recomputed.
*/
struct IndexedExpr {
  Expr *pExpr;            /* The expression contained in the index */
  int iDataCur;           /* The data cursor associated with the index */
  int iIdxCur;            /* The index cursor */
  int iIdxCol;            /* The index column that contains value of pExpr */
  u8 bMaybeNullRow;       /* True if we need an OP_IfNullRow check */
  IndexedExpr *pIENext;   /* Next in a list of all indexed expressions */
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
  const char *zIdxName;   /* Name of index, used only for bytecode comments */
#endif
};

/*
** An instance of the ParseCleanup object specifies an operation that
** should be performed after parsing to deallocation resources obtained
** during the parse and which are no longer needed.
*/
struct ParseCleanup {
  ParseCleanup *pNext;               /* Next cleanup task */
  void *pPtr;                        /* Pointer to object to deallocate */
  void (*xCleanup)(sqlite3*,void*);  /* Deallocation routine */
};

/*
** An SQL parser context.  A copy of this structure is passed through
** the parser and down into all the parser action routine in order to
** carry around information that is global to the entire parse.
**
** The structure is divided into two parts.  When the parser and code
3067
3068
3069
3070
3071
3072
3073





3074
3075
3076
3077
3078
3079
3080
3081
3082
3083


3084
3085

3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099



3100



3101
3102
3103



3104

3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115

3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143



3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158


3159
3160
3161
3162


3163
3164
3165
3166

3167

3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184

3185
3186
3187
3188
3189
3190
3191
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744

3745
3746
3747

3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769

3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805

3806

3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817

3818
3819
3820
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
3866
3867
3868







+
+
+
+
+





-



-
+
+


+














+
+
+
-
+
+
+



+
+
+

+











+













-

-











-
+
+
+






-
-

-





+
+


-
-
+
+




+
-
+
















-
+







  u8 nested;           /* Number of nested calls to the parser/code generator */
  u8 nTempReg;         /* Number of temporary registers in aTempReg[] */
  u8 isMultiWrite;     /* True if statement may modify/insert multiple rows */
  u8 mayAbort;         /* True if statement may throw an ABORT exception */
  u8 hasCompound;      /* Need to invoke convertCompoundSelectToSubquery() */
  u8 okConstFactor;    /* OK to factor out constants */
  u8 disableLookaside; /* Number of times lookaside has been disabled */
  u8 prepFlags;        /* SQLITE_PREPARE_* flags */
  u8 withinRJSubrtn;   /* Nesting level for RIGHT JOIN body subroutines */
#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
  u8 earlyCleanup;     /* OOM inside sqlite3ParserAddCleanup() */
#endif
  int nRangeReg;       /* Size of the temporary register block */
  int iRangeReg;       /* First register in temporary register block */
  int nErr;            /* Number of errors seen */
  int nTab;            /* Number of previously allocated VDBE cursors */
  int nMem;            /* Number of memory cells used so far */
  int nOpAlloc;        /* Number of slots allocated for Vdbe.aOp[] */
  int szOpAlloc;       /* Bytes of memory space allocated for Vdbe.aOp[] */
  int iSelfTab;        /* Table associated with an index on expr, or negative
                       ** of the base register during check-constraint eval */
  int nLabel;          /* Number of labels used */
  int nLabel;          /* The *negative* of the number of labels used */
  int nLabelAlloc;     /* Number of slots in aLabel */
  int *aLabel;         /* Space to hold the labels */
  ExprList *pConstExpr;/* Constant expressions */
  IndexedExpr *pIdxEpr;/* List of expressions used by active indexes */
  Token constraintName;/* Name of the constraint currently being parsed */
  yDbMask writeMask;   /* Start a write transaction on these databases */
  yDbMask cookieMask;  /* Bitmask of schema verified databases */
  int regRowid;        /* Register holding rowid of CREATE TABLE entry */
  int regRoot;         /* Register holding root page number for new objects */
  int nMaxArg;         /* Max args passed to user function by sub-program */
  int nSelect;         /* Number of SELECT stmts. Counter for Select.selId */
#ifndef SQLITE_OMIT_SHARED_CACHE
  int nTableLock;        /* Number of locks in aTableLock */
  TableLock *aTableLock; /* Required table locks for shared-cache mode */
#endif
  AutoincInfo *pAinc;  /* Information about AUTOINCREMENT counters */
  Parse *pToplevel;    /* Parse structure for main program (or NULL) */
  Table *pTriggerTab;  /* Table triggers are being coded for */
  TriggerPrg *pTriggerPrg;  /* Linked list of coded triggers */
  ParseCleanup *pCleanup;   /* List of cleanup operations to run after parse */
  union {
  int addrCrTab;       /* Address of OP_CreateBtree opcode on CREATE TABLE */
    int addrCrTab;         /* Address of OP_CreateBtree on CREATE TABLE */
    Returning *pReturning; /* The RETURNING clause */
  } u1;
  u32 nQueryLoop;      /* Est number of iterations of a query (10*log2(N)) */
  u32 oldmask;         /* Mask of old.* columns referenced */
  u32 newmask;         /* Mask of new.* columns referenced */
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  u32 nProgressSteps;  /* xProgress steps taken during sqlite3_prepare() */
#endif
  u8 eTriggerOp;       /* TK_UPDATE, TK_INSERT or TK_DELETE */
  u8 bReturning;       /* Coding a RETURNING trigger */
  u8 eOrconf;          /* Default ON CONFLICT policy for trigger steps */
  u8 disableTriggers;  /* True to disable triggers */

  /**************************************************************************
  ** Fields above must be initialized to zero.  The fields that follow,
  ** down to the beginning of the recursive section, do not need to be
  ** initialized as they will be set before being used.  The boundary is
  ** determined by offsetof(Parse,aTempReg).
  **************************************************************************/

  int aTempReg[8];        /* Holding area for temporary registers */
  Parse *pOuterParse;     /* Outer Parse object when nested */
  Token sNameToken;       /* Token with unqualified schema object name */

  /************************************************************************
  ** Above is constant between recursions.  Below is reset before and after
  ** each recursion.  The boundary between these two regions is determined
  ** using offsetof(Parse,sLastToken) so the sLastToken field must be the
  ** first field in the recursive region.
  ************************************************************************/

  Token sLastToken;       /* The last token parsed */
  ynVar nVar;               /* Number of '?' variables seen in the SQL so far */
  u8 iPkSortOrder;          /* ASC or DESC for INTEGER PRIMARY KEY */
  u8 explain;               /* True if the EXPLAIN flag is found on the query */
#if !(defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_OMIT_ALTERTABLE))
  u8 eParseMode;            /* PARSE_MODE_XXX constant */
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
  int nVtabLock;            /* Number of virtual tables to lock */
#endif
  int nHeight;              /* Expression tree height of current sub-select */
#ifndef SQLITE_OMIT_EXPLAIN
  int addrExplain;          /* Address of current OP_Explain opcode */
#endif
  VList *pVList;            /* Mapping between variable names and numbers */
  Vdbe *pReprepare;         /* VM being reprepared (sqlite3Reprepare()) */
  const char *zTail;        /* All SQL text past the last semicolon parsed */
  Table *pNewTable;         /* A table being constructed by CREATE TABLE */
  Index *pNewIndex;         /* An index being constructed by CREATE INDEX */
  Index *pNewIndex;         /* An index being constructed by CREATE INDEX.
                            ** Also used to hold redundant UNIQUE constraints
                            ** during a RENAME COLUMN */
  Trigger *pNewTrigger;     /* Trigger under construct by a CREATE TRIGGER */
  const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */
#ifndef SQLITE_OMIT_VIRTUALTABLE
  Token sArg;               /* Complete text of a module argument */
  Table **apVtabLock;       /* Pointer to virtual tables needing locking */
#endif
  Table *pZombieTab;        /* List of Table objects to delete after code gen */
  TriggerPrg *pTriggerPrg;  /* Linked list of coded triggers */
  With *pWith;              /* Current WITH clause, or NULL */
  With *pWithToFree;        /* Free this WITH object at the end of the parse */
#ifndef SQLITE_OMIT_ALTERTABLE
  RenameToken *pRename;     /* Tokens subject to renaming by ALTER TABLE */
#endif
};

/* Allowed values for Parse.eParseMode
*/
#define PARSE_MODE_NORMAL        0
#define PARSE_MODE_DECLARE_VTAB  1
#define PARSE_MODE_RENAME_COLUMN 2
#define PARSE_MODE_RENAME_TABLE  3
#define PARSE_MODE_RENAME        2
#define PARSE_MODE_UNMAP         3

/*
** Sizes and pointers of various parts of the Parse object.
*/
#define PARSE_HDR(X)  (((char*)(X))+offsetof(Parse,zErrMsg))
#define PARSE_HDR_SZ offsetof(Parse,aTempReg) /* Recursive part w/o aColCache*/
#define PARSE_HDR_SZ (offsetof(Parse,aTempReg)-offsetof(Parse,zErrMsg)) /* Recursive part w/o aColCache*/
#define PARSE_RECURSE_SZ offsetof(Parse,sLastToken)    /* Recursive part */
#define PARSE_TAIL_SZ (sizeof(Parse)-PARSE_RECURSE_SZ) /* Non-recursive part */
#define PARSE_TAIL(X) (((char*)(X))+PARSE_RECURSE_SZ)  /* Pointer to tail */

/*
** Return true if currently inside an sqlite3_declare_vtab() call.
*/
#ifdef SQLITE_OMIT_VIRTUALTABLE
  #define IN_DECLARE_VTAB 0
#else
  #define IN_DECLARE_VTAB (pParse->eParseMode==PARSE_MODE_DECLARE_VTAB)
#endif

#if defined(SQLITE_OMIT_ALTERTABLE)
  #define IN_RENAME_OBJECT 0
#else
  #define IN_RENAME_OBJECT (pParse->eParseMode>=PARSE_MODE_RENAME_COLUMN)
  #define IN_RENAME_OBJECT (pParse->eParseMode>=PARSE_MODE_RENAME)
#endif

#if defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_OMIT_ALTERTABLE)
  #define IN_SPECIAL_PARSE 0
#else
  #define IN_SPECIAL_PARSE (pParse->eParseMode!=PARSE_MODE_NORMAL)
#endif
3226
3227
3228
3229
3230
3231
3232

3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248














3249
3250
3251
3252
3253

3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290

















3291
3292
3293
3294
3295



3296
3297
3298

3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310





















3311
3312


3313
3314
3315
3316

3317
3318

3319
3320
3321
3322
3323
3324
3325
3326
3327

3328
3329
3330
3331
3332
3333
3334
3335
3336








3337
3338
3339
3340
3341
3342
3343
3344
3345
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912














3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
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
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
4000
4001
4002
4003

4004
4005
4006
4007
4008
4009
4010
4011
4012

4013


4014






4015
4016
4017
4018
4019
4020
4021
4022


4023
4024
4025
4026
4027
4028
4029







+


-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+





+




















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+
+




+

-
+








-
+
-
-

-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-







#define OPFLAG_SEEKEQ        0x02    /* OP_Open** cursor uses EQ seek only */
#define OPFLAG_FORDELETE     0x08    /* OP_Open should use BTREE_FORDELETE */
#define OPFLAG_P2ISREG       0x10    /* P2 to OP_Open** is a register number */
#define OPFLAG_PERMUTE       0x01    /* OP_Compare: use the permutation */
#define OPFLAG_SAVEPOSITION  0x02    /* OP_Delete/Insert: save cursor pos */
#define OPFLAG_AUXDELETE     0x04    /* OP_Delete: index in a DELETE op */
#define OPFLAG_NOCHNG_MAGIC  0x6d    /* OP_MakeRecord: serialtype 10 is ok */
#define OPFLAG_PREFORMAT     0x80    /* OP_Insert uses preformatted cell */ 

/*
 * Each trigger present in the database schema is stored as an instance of
 * struct Trigger.
 *
 * Pointers to instances of struct Trigger are stored in two ways.
 * 1. In the "trigHash" hash table (part of the sqlite3* that represents the
 *    database). This allows Trigger structures to be retrieved by name.
 * 2. All triggers associated with a single table form a linked list, using the
 *    pNext member of struct Trigger. A pointer to the first element of the
 *    linked list is stored as the "pTrigger" member of the associated
 *    struct Table.
 *
 * The "step_list" member points to the first element of a linked list
 * containing the SQL statements specified as the trigger program.
 */
** Each trigger present in the database schema is stored as an instance of
** struct Trigger.
**
** Pointers to instances of struct Trigger are stored in two ways.
** 1. In the "trigHash" hash table (part of the sqlite3* that represents the
**    database). This allows Trigger structures to be retrieved by name.
** 2. All triggers associated with a single table form a linked list, using the
**    pNext member of struct Trigger. A pointer to the first element of the
**    linked list is stored as the "pTrigger" member of the associated
**    struct Table.
**
** The "step_list" member points to the first element of a linked list
** containing the SQL statements specified as the trigger program.
*/
struct Trigger {
  char *zName;            /* The name of the trigger                        */
  char *table;            /* The table or view to which the trigger applies */
  u8 op;                  /* One of TK_DELETE, TK_UPDATE, TK_INSERT         */
  u8 tr_tm;               /* One of TRIGGER_BEFORE, TRIGGER_AFTER */
  u8 bReturning;          /* This trigger implements a RETURNING clause */
  Expr *pWhen;            /* The WHEN clause of the expression (may be NULL) */
  IdList *pColumns;       /* If this is an UPDATE OF <column-list> trigger,
                             the <column-list> is stored here */
  Schema *pSchema;        /* Schema containing the trigger */
  Schema *pTabSchema;     /* Schema containing the table */
  TriggerStep *step_list; /* Link list of trigger program steps             */
  Trigger *pNext;         /* Next trigger associated with the table */
};

/*
** A trigger is either a BEFORE or an AFTER trigger.  The following constants
** determine which.
**
** If there are multiple triggers, you might of some BEFORE and some AFTER.
** In that cases, the constants below can be ORed together.
*/
#define TRIGGER_BEFORE  1
#define TRIGGER_AFTER   2

/*
 * An instance of struct TriggerStep is used to store a single SQL statement
 * that is a part of a trigger-program.
 *
 * Instances of struct TriggerStep are stored in a singly linked list (linked
 * using the "pNext" member) referenced by the "step_list" member of the
 * associated struct Trigger instance. The first element of the linked list is
 * the first step of the trigger-program.
 *
 * The "op" member indicates whether this is a "DELETE", "INSERT", "UPDATE" or
 * "SELECT" statement. The meanings of the other members is determined by the
 * value of "op" as follows:
 *
 * (op == TK_INSERT)
 * orconf    -> stores the ON CONFLICT algorithm
 * pSelect   -> If this is an INSERT INTO ... SELECT ... statement, then
 *              this stores a pointer to the SELECT statement. Otherwise NULL.
 * zTarget   -> Dequoted name of the table to insert into.
** An instance of struct TriggerStep is used to store a single SQL statement
** that is a part of a trigger-program.
**
** Instances of struct TriggerStep are stored in a singly linked list (linked
** using the "pNext" member) referenced by the "step_list" member of the
** associated struct Trigger instance. The first element of the linked list is
** the first step of the trigger-program.
**
** The "op" member indicates whether this is a "DELETE", "INSERT", "UPDATE" or
** "SELECT" statement. The meanings of the other members is determined by the
** value of "op" as follows:
**
** (op == TK_INSERT)
** orconf    -> stores the ON CONFLICT algorithm
** pSelect   -> The content to be inserted - either a SELECT statement or
**              a VALUES clause.
** zTarget   -> Dequoted name of the table to insert into.
 * pExprList -> If this is an INSERT INTO ... VALUES ... statement, then
 *              this stores values to be inserted. Otherwise NULL.
 * pIdList   -> If this is an INSERT INTO ... (<column-names>) VALUES ...
 *              statement, then this stores the column-names to be
 *              inserted into.
** pIdList   -> If this is an INSERT INTO ... (<column-names>) VALUES ...
**              statement, then this stores the column-names to be
**              inserted into.
 *
 * (op == TK_DELETE)
 * zTarget   -> Dequoted name of the table to delete from.
** pUpsert   -> The ON CONFLICT clauses for an Upsert
 * pWhere    -> The WHERE clause of the DELETE statement if one is specified.
 *              Otherwise NULL.
 *
 * (op == TK_UPDATE)
 * zTarget   -> Dequoted name of the table to update.
 * pWhere    -> The WHERE clause of the UPDATE statement if one is specified.
 *              Otherwise NULL.
 * pExprList -> A list of the columns to update and the expressions to update
 *              them to. See sqlite3Update() documentation of "pChanges"
 *              argument.
 *
 */
**
** (op == TK_DELETE)
** zTarget   -> Dequoted name of the table to delete from.
** pWhere    -> The WHERE clause of the DELETE statement if one is specified.
**              Otherwise NULL.
**
** (op == TK_UPDATE)
** zTarget   -> Dequoted name of the table to update.
** pWhere    -> The WHERE clause of the UPDATE statement if one is specified.
**              Otherwise NULL.
** pExprList -> A list of the columns to update and the expressions to update
**              them to. See sqlite3Update() documentation of "pChanges"
**              argument.
**
** (op == TK_SELECT)
** pSelect   -> The SELECT statement
**
** (op == TK_RETURNING)
** pExprList -> The list of expressions that follow the RETURNING keyword.
**
*/
struct TriggerStep {
  u8 op;               /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT */
  u8 op;               /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT,
                       ** or TK_RETURNING */
  u8 orconf;           /* OE_Rollback etc. */
  Trigger *pTrig;      /* The trigger that this step is a part of */
  Select *pSelect;     /* SELECT statement or RHS of INSERT INTO SELECT ... */
  char *zTarget;       /* Target table for DELETE, UPDATE, INSERT */
  SrcList *pFrom;      /* FROM clause for UPDATE statement (if any) */
  Expr *pWhere;        /* The WHERE clause for DELETE or UPDATE steps */
  ExprList *pExprList; /* SET clause for UPDATE */
  ExprList *pExprList; /* SET clause for UPDATE, or RETURNING clause */
  IdList *pIdList;     /* Column names for INSERT */
  Upsert *pUpsert;     /* Upsert clauses on an INSERT */
  char *zSpan;         /* Original SQL text of this command */
  TriggerStep *pNext;  /* Next in the link-list */
  TriggerStep *pLast;  /* Last element in link-list. Valid for 1st elem only */
};

/*
** The following structure contains information used by the sqliteFix...
** Information about a RETURNING clause
** routines as they walk the parse tree to make database references
** explicit.
*/
typedef struct DbFixer DbFixer;
struct DbFixer {
  Parse *pParse;      /* The parsing context.  Error messages written here */
  Schema *pSchema;    /* Fix items to this schema */
  int bVarOnly;       /* Check for variable references only */
  const char *zDb;    /* Make sure all objects are contained in this database */
struct Returning {
  Parse *pParse;        /* The parse that includes the RETURNING clause */
  ExprList *pReturnEL;  /* List of expressions to return */
  Trigger retTrig;      /* The transient trigger that implements RETURNING */
  TriggerStep retTStep; /* The trigger step */
  int iRetCur;          /* Transient table holding RETURNING results */
  int nRetCol;          /* Number of in pReturnEL after expansion */
  int iRetReg;          /* Register array for holding a row of RETURNING */
  const char *zType;  /* Type of the container - used for error messages */
  const Token *pName; /* Name of the container - used for error messages */
};

/*
** An objected used to accumulate the text of a string where we
** do not necessarily know how big the string will be in the end.
*/
struct sqlite3_str {
3364
3365
3366
3367
3368
3369
3370


3371
3372
3373
3374
3375




3376
















3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389






3390
3391
3392
3393
3394
3395
3396
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065

4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
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







+
+





+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








-
-
-
-
-
+
+
+
+
+
+







*/
typedef struct {
  sqlite3 *db;        /* The database being initialized */
  char **pzErrMsg;    /* Error message stored here */
  int iDb;            /* 0 for main database.  1 for TEMP, 2.. for ATTACHed */
  int rc;             /* Result code stored here */
  u32 mInitFlags;     /* Flags controlling error messages */
  u32 nInitRow;       /* Number of rows processed */
  Pgno mxPage;        /* Maximum page number.  0 for no limit. */
} InitData;

/*
** Allowed values for mInitFlags
*/
#define INITFLAG_AlterMask     0x0003  /* Types of ALTER */
#define INITFLAG_AlterRename   0x0001  /* Reparse after a RENAME */
#define INITFLAG_AlterDrop     0x0002  /* Reparse after a DROP COLUMN */
#define INITFLAG_AlterAdd      0x0003  /* Reparse after an ADD COLUMN */
#define INITFLAG_AlterTable   0x0001  /* This is a reparse after ALTER TABLE */

/* Tuning parameters are set using SQLITE_TESTCTRL_TUNE and are controlled
** on debug-builds of the CLI using ".testctrl tune ID VALUE".  Tuning
** parameters are for temporary use during development, to help find
** optimial values for parameters in the query planner.  The should not
** be used on trunk check-ins.  They are a temporary mechanism available
** for transient development builds only.
**
** Tuning parameters are numbered starting with 1.
*/
#define SQLITE_NTUNE  6             /* Should be zero for all trunk check-ins */
#ifdef SQLITE_DEBUG
# define Tuning(X)  (sqlite3Config.aTune[(X)-1])
#else
# define Tuning(X)  0
#endif

/*
** Structure containing global configuration data for the SQLite library.
**
** This structure also contains some state information.
*/
struct Sqlite3Config {
  int bMemstat;                     /* True to enable memory status */
  int bCoreMutex;                   /* True to enable core mutexing */
  int bFullMutex;                   /* True to enable full mutexing */
  int bOpenUri;                     /* True to interpret filenames as URIs */
  int bUseCis;                      /* Use covering indices for full-scans */
  int bSmallMalloc;                 /* Avoid large memory allocations if true */
  u8 bCoreMutex;                    /* True to enable core mutexing */
  u8 bFullMutex;                    /* True to enable full mutexing */
  u8 bOpenUri;                      /* True to interpret filenames as URIs */
  u8 bUseCis;                       /* Use covering indices for full-scans */
  u8 bSmallMalloc;                  /* Avoid large memory allocations if true */
  u8 bExtraSchemaChecks;            /* Verify type,name,tbl_name in schema */
  int mxStrlen;                     /* Maximum string length */
  int neverCorrupt;                 /* Database is always well-formed */
  int szLookaside;                  /* Default lookaside buffer size */
  int nLookaside;                   /* Default lookaside buffer count */
  int nStmtSpill;                   /* Stmt-journal spill-to-disk threshold */
  sqlite3_mem_methods m;            /* Low-level memory allocation interface */
  sqlite3_mutex_methods mutex;      /* Low-level mutex interface */
3424
3425
3426
3427
3428
3429
3430



3431
3432
3433
3434
3435

3436
3437





3438
3439
3440
3441
3442
3443
3444
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143

4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158







+
+
+




-
+


+
+
+
+
+







#ifdef SQLITE_VDBE_COVERAGE
  /* The following callback (if not NULL) is invoked on every VDBE branch
  ** operation.  Set the callback using SQLITE_TESTCTRL_VDBE_COVERAGE.
  */
  void (*xVdbeBranch)(void*,unsigned iSrcLine,u8 eThis,u8 eMx);  /* Callback */
  void *pVdbeBranchArg;                                     /* 1st argument */
#endif
#ifndef SQLITE_OMIT_DESERIALIZE
  sqlite3_int64 mxMemdbSize;        /* Default max memdb size */
#endif
#ifndef SQLITE_UNTESTABLE
  int (*xTestCallback)(int);        /* Invoked by sqlite3FaultSim() */
#endif
  int bLocaltimeFault;              /* True to fail localtime() calls */
  int bInternalFunctions;           /* Internal SQL functions are visible */
  int (*xAltLocaltime)(const void*,void*); /* Alternative localtime() routine */
  int iOnceResetThreshold;          /* When to reset OP_Once counters */
  u32 szSorterRef;                  /* Min size in bytes to use sorter-refs */
  unsigned int iPrngSeed;           /* Alternative fixed seed for the PRNG */
  /* vvvv--- must be last ---vvv */
#ifdef SQLITE_DEBUG
  sqlite3_int64 aTune[SQLITE_NTUNE]; /* Tuning parameters */
#endif
};

/*
** This macro is used inside of assert() statements to indicate that
** the assert is only valid on a well-formed database.  Instead of:
**
**     assert( X );
3460
3461
3462
3463
3464
3465
3466
3467

3468
3469
3470
3471
3472
3473
3474

3475
3476
3477
3478
3479
3480
3481
3482




3483
3484















3485
3486
3487
3488
3489
3490
3491
3492
3493
3494




3495
3496
3497






3498
3499
3500
3501
3502
3503
3504
3505
3506
3507










3508
3509











3510
3511
3512
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

3569
3570
3571
3572





3573
3574
3575
3576

3577
3578

3579

3580
3581


3582
3583
3584
3585
3586
3587
3588


3589
3590
3591
3592
3593
3594
3595
4174
4175
4176
4177
4178
4179
4180

4181
4182
4183
4184
4185
4186

4187
4188
4189
4190

4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259


4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272







4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296

4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311

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
4360
4361
4362
4363
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







-
+





-

+


-





+
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










+
+
+
+



+
+
+
+
+
+










+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+


-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-

+













-
+
+


-
+










+
+
+
+

-
+



+


-
+


+
+


+


-
+

-
-
+
+


-
+
-



+
+
+
+
+




+

-
+

+
-
-
+
+


-




+
+







*/
struct Walker {
  Parse *pParse;                            /* Parser context.  */
  int (*xExprCallback)(Walker*, Expr*);     /* Callback for expressions */
  int (*xSelectCallback)(Walker*,Select*);  /* Callback for SELECTs */
  void (*xSelectCallback2)(Walker*,Select*);/* Second callback for SELECTs */
  int walkerDepth;                          /* Number of subqueries */
  u8 eCode;                                 /* A small processing code */
  u16 eCode;                                /* A small processing code */
  union {                                   /* Extra data for callback */
    NameContext *pNC;                         /* Naming context */
    int n;                                    /* A counter */
    int iCur;                                 /* A cursor number */
    SrcList *pSrcList;                        /* FROM clause */
    struct SrcCount *pSrcCount;               /* Counting column references */
    struct CCurHint *pCCurHint;               /* Used by codeCursorHint() */
    struct RefSrcList *pRefSrcList;           /* sqlite3ReferencesSrcList() */
    int *aiCol;                               /* array of column indexes */
    struct IdxCover *pIdxCover;               /* Check for index coverage */
    struct IdxExprTrans *pIdxTrans;           /* Convert idxed expr to column */
    ExprList *pGroupBy;                       /* GROUP BY clause */
    Select *pSelect;                          /* HAVING to WHERE clause ctx */
    struct WindowRewrite *pRewrite;           /* Window rewrite context */
    struct WhereConst *pConst;                /* WHERE clause constants */
    struct RenameCtx *pRename;                /* RENAME COLUMN context */
    struct Table *pTab;                       /* Table of generated column */
    struct CoveringIndexCheck *pCovIdxCk;     /* Check for covering index */
    SrcItem *pSrcItem;                        /* A single FROM clause item */
    DbFixer *pFix;                            /* See sqlite3FixSelect() */
  } u;
};

/*
** The following structure contains information used by the sqliteFix...
** routines as they walk the parse tree to make database references
** explicit.
*/
struct DbFixer {
  Parse *pParse;      /* The parsing context.  Error messages written here */
  Walker w;           /* Walker object */
  Schema *pSchema;    /* Fix items to this schema */
  u8 bTemp;           /* True for TEMP schema entries */
  const char *zDb;    /* Make sure all objects are contained in this database */
  const char *zType;  /* Type of the container - used for error messages */
  const Token *pName; /* Name of the container - used for error messages */
};

/* Forward declarations */
int sqlite3WalkExpr(Walker*, Expr*);
int sqlite3WalkExprList(Walker*, ExprList*);
int sqlite3WalkSelect(Walker*, Select*);
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

#ifndef SQLITE_OMIT_CTE
void sqlite3SelectPopWith(Walker*, Select*);
#else
# define sqlite3SelectPopWith 0
#endif

/*
** Return code from the parse-tree walking primitives and their
** callbacks.
*/
#define WRC_Continue    0   /* Continue down into children */
#define WRC_Prune       1   /* Omit children but continue walking siblings */
#define WRC_Abort       2   /* Abandon the tree walk */

/*
** A single common table expression
*/
struct Cte {
  char *zName;            /* Name of this CTE */
  ExprList *pCols;        /* List of explicit column names, or NULL */
  Select *pSelect;        /* The definition of this CTE */
  const char *zCteErr;    /* Error message for circular references */
  CteUse *pUse;           /* Usage information for this CTE */
  u8 eM10d;               /* The MATERIALIZED flag */
};
** An instance of this structure represents a set of one or more CTEs
** (common table expressions) created by a single WITH clause.

/*
** Allowed values for the materialized flag (eM10d):
*/
#define M10d_Yes       0  /* AS MATERIALIZED */
#define M10d_Any       1  /* Not specified.  Query planner's choice */
#define M10d_No        2  /* AS NOT MATERIALIZED */

/*
** An instance of the With object represents a WITH clause containing
** one or more CTEs (common table expressions).
*/
struct With {
  int nCte;                       /* Number of CTEs in the WITH clause */
  With *pOuter;                   /* Containing WITH clause, or NULL */
  struct Cte {                    /* For each CTE in the WITH clause.... */
    char *zName;                    /* Name of this CTE */
    ExprList *pCols;                /* List of explicit column names, or NULL */
    Select *pSelect;                /* The definition of this CTE */
    const char *zCteErr;            /* Error message for circular references */
  int nCte;               /* Number of CTEs in the WITH clause */
  int bView;              /* Belongs to the outermost Select of a view */
  With *pOuter;           /* Containing WITH clause, or NULL */
  Cte a[1];               /* For each CTE in the WITH clause.... */
};

/*
** The Cte object is not guaranteed to persist for the entire duration
** of code generation.  (The query flattener or other parser tree
** edits might delete it.)  The following object records information
** about each Common Table Expression that must be preserved for the
** duration of the parse.
**
** The CteUse objects are freed using sqlite3ParserAddCleanup() rather
** than sqlite3SelectDelete(), which is what enables them to persist
** until the end of code generation.
*/
struct CteUse {
  int nUse;              /* Number of users of this CTE */
  int addrM9e;           /* Start of subroutine to compute materialization */
  int regRtn;            /* Return address register for addrM9e subroutine */
  int iCur;              /* Ephemeral table holding the materialization */
  LogEst nRowEst;        /* Estimated number of rows in the table */
  u8 eM10d;              /* The MATERIALIZED flag */
  } a[1];
};


#ifdef SQLITE_DEBUG
/*
** An instance of the TreeView object is used for printing the content of
** data structures on sqlite3DebugPrintf() using a tree-like view.
*/
struct TreeView {
  int iLevel;             /* Which level of the tree we are on */
  u8  bLine[100];         /* Draw vertical in column i if bLine[i] is true */
};
#endif /* SQLITE_DEBUG */

/*
** This object is used in varioius ways, all related to window functions
** This object is used in various ways, most (but not all) related to window
** functions.
**
**   (1) A single instance of this structure is attached to the
**       the Expr.pWin field for each window function in an expression tree.
**       the Expr.y.pWin field for each window function in an expression tree.
**       This object holds the information contained in the OVER clause,
**       plus additional fields used during code generation.
**
**   (2) All window functions in a single SELECT form a linked-list
**       attached to Select.pWin.  The Window.pFunc and Window.pExpr
**       fields point back to the expression that is the window function.
**
**   (3) The terms of the WINDOW clause of a SELECT are instances of this
**       object on a linked list attached to Select.pWinDefn.
**
**   (4) For an aggregate function with a FILTER clause, an instance
**       of this object is stored in Expr.y.pWin with eFrmType set to
**       TK_FILTER. In this case the only field used is Window.pFilter.
**
** The uses (1) and (2) are really the same Window object that just happens
** to be accessible in two different ways.  Use (3) is are separate objects.
** to be accessible in two different ways.  Use case (3) are separate objects.
*/
struct Window {
  char *zName;            /* Name of window (may be NULL) */
  char *zBase;            /* Name of base window for chaining (may be NULL) */
  ExprList *pPartition;   /* PARTITION BY clause */
  ExprList *pOrderBy;     /* ORDER BY clause */
  u8 eType;               /* TK_RANGE or TK_ROWS */
  u8 eFrmType;            /* TK_RANGE, TK_GROUPS, TK_ROWS, or 0 */
  u8 eStart;              /* UNBOUNDED, CURRENT, PRECEDING or FOLLOWING */
  u8 eEnd;                /* UNBOUNDED, CURRENT, PRECEDING or FOLLOWING */
  u8 bImplicitFrame;      /* True if frame was implicitly specified */
  u8 eExclude;            /* TK_NO, TK_CURRENT, TK_TIES, TK_GROUP, or 0 */
  Expr *pStart;           /* Expression for "<expr> PRECEDING" */
  Expr *pEnd;             /* Expression for "<expr> FOLLOWING" */
  Window **ppThis;        /* Pointer to this object in Select.pWin list */
  Window *pNextWin;       /* Next window function belonging to this SELECT */
  Expr *pFilter;          /* The FILTER expression */
  FuncDef *pFunc;         /* The function */
  FuncDef *pWFunc;        /* The function */
  int iEphCsr;            /* Partition buffer or Peer buffer */
  int regAccum;
  int regResult;
  int regAccum;           /* Accumulator */
  int regResult;          /* Interim result */
  int csrApp;             /* Function cursor (used by min/max) */
  int regApp;             /* Function register (also used by min/max) */
  int regPart;            /* First in a set of registers holding PARTITION BY
  int regPart;            /* Array of registers for PARTITION BY values */
                          ** and ORDER BY values for the window */
  Expr *pOwner;           /* Expression object this window is attached to */
  int nBufferCol;         /* Number of columns in buffer table */
  int iArgCol;            /* Offset of first argument for this function */
  int regOne;             /* Register containing constant value 1 */
  int regStartRowid;
  int regEndRowid;
  u8 bExprArgs;           /* Defer evaluation of window function arguments
                          ** due to the SQLITE_SUBTYPE flag */
};

#ifndef SQLITE_OMIT_WINDOWFUNC
void sqlite3WindowDelete(sqlite3*, Window*);
void sqlite3WindowUnlinkFromSelect(Window*);
void sqlite3WindowListDelete(sqlite3 *db, Window *p);
Window *sqlite3WindowAlloc(Parse*, int, int, Expr*, int , Expr*);
Window *sqlite3WindowAlloc(Parse*, int, int, Expr*, int , Expr*, u8);
void sqlite3WindowAttach(Parse*, Expr*, Window*);
void sqlite3WindowLink(Select *pSel, Window *pWin);
int sqlite3WindowCompare(Parse*, Window*, Window*);
void sqlite3WindowCodeInit(Parse*, Window*);
int sqlite3WindowCompare(const Parse*, const Window*, const Window*, int);
void sqlite3WindowCodeInit(Parse*, Select*);
void sqlite3WindowCodeStep(Parse*, Select*, WhereInfo*, int, int);
int sqlite3WindowRewrite(Parse*, Select*);
int sqlite3ExpandSubquery(Parse*, struct SrcList_item*);
void sqlite3WindowUpdate(Parse*, Window*, Window*, FuncDef*);
Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p);
Window *sqlite3WindowListDup(sqlite3 *db, Window *p);
void sqlite3WindowFunctions(void);
void sqlite3WindowChain(Parse*, Window*, Window*);
Window *sqlite3WindowAssemble(Parse*, Window*, ExprList*, ExprList*, Token*);
#else
# define sqlite3WindowDelete(a,b)
# define sqlite3WindowFunctions()
# define sqlite3WindowAttach(a,b,c)
#endif

/*
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628





3629
3630
3631
3632
3633
3634
3635
4409
4410
4411
4412
4413
4414
4415

4416
4417

4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432







-


-



+
+
+
+
+







int sqlite3CantopenError(int);
#define SQLITE_CORRUPT_BKPT sqlite3CorruptError(__LINE__)
#define SQLITE_MISUSE_BKPT sqlite3MisuseError(__LINE__)
#define SQLITE_CANTOPEN_BKPT sqlite3CantopenError(__LINE__)
#ifdef SQLITE_DEBUG
  int sqlite3NomemError(int);
  int sqlite3IoerrnomemError(int);
  int sqlite3CorruptPgnoError(int,Pgno);
# define SQLITE_NOMEM_BKPT sqlite3NomemError(__LINE__)
# define SQLITE_IOERR_NOMEM_BKPT sqlite3IoerrnomemError(__LINE__)
# define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptPgnoError(__LINE__,(P))
#else
# define SQLITE_NOMEM_BKPT SQLITE_NOMEM
# define SQLITE_IOERR_NOMEM_BKPT SQLITE_IOERR_NOMEM
#endif
#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_CORRUPT_PGNO)
  int sqlite3CorruptPgnoError(int,Pgno);
# define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptPgnoError(__LINE__,(P))
#else
# define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptError(__LINE__)
#endif

/*
** FTS3 and FTS4 both require virtual table support
*/
#if defined(SQLITE_OMIT_VIRTUALTABLE)
3701
3702
3703
3704
3705
3706
3707

3708
3709


3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728

3729

3730
3731
3732

3733

3734
3735
3736
3737
3738
3739
3740
4498
4499
4500
4501
4502
4503
4504
4505


4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525

4526
4527
4528
4529
4530

4531
4532
4533
4534
4535
4536
4537
4538
4539
4540







+
-
-
+
+


















-
+

+


-
+

+







char *sqlite3DbStrNDup(sqlite3*,const char*, u64);
char *sqlite3DbSpanDup(sqlite3*,const char*,const char*);
void *sqlite3Realloc(void*, u64);
void *sqlite3DbReallocOrFree(sqlite3 *, void *, u64);
void *sqlite3DbRealloc(sqlite3 *, void *, u64);
void sqlite3DbFree(sqlite3*, void*);
void sqlite3DbFreeNN(sqlite3*, void*);
void sqlite3DbNNFreeNN(sqlite3*, void*);
int sqlite3MallocSize(void*);
int sqlite3DbMallocSize(sqlite3*, void*);
int sqlite3MallocSize(const void*);
int sqlite3DbMallocSize(sqlite3*, const void*);
void *sqlite3PageMalloc(int);
void sqlite3PageFree(void*);
void sqlite3MemSetDefault(void);
#ifndef SQLITE_UNTESTABLE
void sqlite3BenignMallocHooks(void (*)(void), void (*)(void));
#endif
int sqlite3HeapNearlyFull(void);

/*
** On systems with ample stack space and that support alloca(), make
** use of alloca() to obtain space for large automatic objects.  By default,
** obtain space from malloc().
**
** The alloca() routine never returns NULL.  This will cause code paths
** that deal with sqlite3StackAlloc() failures to be unreachable.
*/
#ifdef SQLITE_USE_ALLOCA
# define sqlite3StackAllocRaw(D,N)   alloca(N)
# define sqlite3StackAllocZero(D,N)  memset(alloca(N), 0, N)
# define sqlite3StackAllocRawNN(D,N) alloca(N)
# define sqlite3StackFree(D,P)
# define sqlite3StackFreeNN(D,P)
#else
# define sqlite3StackAllocRaw(D,N)   sqlite3DbMallocRaw(D,N)
# define sqlite3StackAllocZero(D,N)  sqlite3DbMallocZero(D,N)
# define sqlite3StackAllocRawNN(D,N) sqlite3DbMallocRawNN(D,N)
# define sqlite3StackFree(D,P)       sqlite3DbFree(D,P)
# define sqlite3StackFreeNN(D,P)     sqlite3DbFreeNN(D,P)
#endif

/* Do not allow both MEMSYS5 and MEMSYS3 to be defined together.  If they
** are, disable MEMSYS3
*/
#ifdef SQLITE_ENABLE_MEMSYS5
const sqlite3_mem_methods *sqlite3MemGetMemsys5(void);
3771
3772
3773
3774
3775
3776
3777



3778
3779

3780
3781
3782
3783
3784
3785
3786
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590







+
+
+


+







#if defined(SQLITE_ENABLE_MULTITHREADED_CHECKS) && !defined(SQLITE_MUTEX_OMIT)
void sqlite3MutexWarnOnContention(sqlite3_mutex*);
#else
# define sqlite3MutexWarnOnContention(x)
#endif

#ifndef SQLITE_OMIT_FLOATING_POINT
# define EXP754 (((u64)0x7ff)<<52)
# define MAN754 ((((u64)1)<<52)-1)
# define IsNaN(X) (((X)&EXP754)==EXP754 && ((X)&MAN754)!=0)
  int sqlite3IsNaN(double);
#else
# define IsNaN(X)         0
# define sqlite3IsNaN(X)  0
#endif

/*
** An instance of the following structure holds information about SQL
** functions arguments that are the parameters to the printf() function.
*/
3796
3797
3798
3799
3800
3801
3802

3803
3804
3805



3806
3807
3808















3809
3810
3811
3812












3813
3814





3815
3816

3817

3818


3819
3820
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
3866
3867
3868
3869
3870
3871

3872
3873
3874

3875
3876

3877


3878
3879

3880
3881
3882
3883
3884
3885
3886
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648

4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663

4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678


4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689


4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713



4714
4715
4716
4717

4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731

4732
4733
4734

4735
4736
4737
4738

4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750







+



+
+
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




+
+
+
+
+
+
+
+
+
+
+
+

-
+
+
+
+
+


+

+

+
+


-
+














-
-
+
+
+
+


+
+


+
-
-
+
+



+











+
+
+
+

+

-
-
-
+
+
+

-
+
+
+
+
+
+
+
+






-
+


-
+


+
-
+
+


+







  void sqlite3DebugPrintf(const char*, ...);
#endif
#if defined(SQLITE_TEST)
  void *sqlite3TestTextToPtr(const char*);
#endif

#if defined(SQLITE_DEBUG)
  void sqlite3TreeViewLine(TreeView*, const char *zFormat, ...);
  void sqlite3TreeViewExpr(TreeView*, const Expr*, u8);
  void sqlite3TreeViewBareExprList(TreeView*, const ExprList*, const char*);
  void sqlite3TreeViewExprList(TreeView*, const ExprList*, u8, const char*);
  void sqlite3TreeViewBareIdList(TreeView*, const IdList*, const char*);
  void sqlite3TreeViewIdList(TreeView*, const IdList*, u8, const char*);
  void sqlite3TreeViewColumnList(TreeView*, const Column*, int, u8);
  void sqlite3TreeViewSrcList(TreeView*, const SrcList*);
  void sqlite3TreeViewSelect(TreeView*, const Select*, u8);
  void sqlite3TreeViewWith(TreeView*, const With*, u8);
  void sqlite3TreeViewUpsert(TreeView*, const Upsert*, u8);
#if TREETRACE_ENABLED
  void sqlite3TreeViewDelete(const With*, const SrcList*, const Expr*,
                             const ExprList*,const Expr*, const Trigger*);
  void sqlite3TreeViewInsert(const With*, const SrcList*,
                             const IdList*, const Select*, const ExprList*,
                             int, const Upsert*, const Trigger*);
  void sqlite3TreeViewUpdate(const With*, const SrcList*, const ExprList*,
                             const Expr*, int, const ExprList*, const Expr*,
                             const Upsert*, const Trigger*);
#endif
#ifndef SQLITE_OMIT_TRIGGER
  void sqlite3TreeViewTriggerStep(TreeView*, const TriggerStep*, u8, u8);
  void sqlite3TreeViewTrigger(TreeView*, const Trigger*, u8, u8);
#endif
#ifndef SQLITE_OMIT_WINDOWFUNC
  void sqlite3TreeViewWindow(TreeView*, const Window*, u8);
  void sqlite3TreeViewWinFunc(TreeView*, const Window*, u8);
#endif
  void sqlite3ShowExpr(const Expr*);
  void sqlite3ShowExprList(const ExprList*);
  void sqlite3ShowIdList(const IdList*);
  void sqlite3ShowSrcList(const SrcList*);
  void sqlite3ShowSelect(const Select*);
  void sqlite3ShowWith(const With*);
  void sqlite3ShowUpsert(const Upsert*);
#ifndef SQLITE_OMIT_TRIGGER
  void sqlite3ShowTriggerStep(const TriggerStep*);
  void sqlite3ShowTriggerStepList(const TriggerStep*);
  void sqlite3ShowTrigger(const Trigger*);
  void sqlite3ShowTriggerList(const Trigger*);
#endif

#ifndef SQLITE_OMIT_WINDOWFUNC
  void sqlite3ShowWindow(const Window*);
  void sqlite3ShowWinFunc(const Window*);
#endif
#endif

void sqlite3SetString(char **, sqlite3*, const char*);
void sqlite3ProgressCheck(Parse*);
void sqlite3ErrorMsg(Parse*, const char*, ...);
int sqlite3ErrorToParser(sqlite3*,int);
void sqlite3Dequote(char*);
void sqlite3DequoteExpr(Expr*);
void sqlite3DequoteToken(Token*);
void sqlite3TokenInit(Token*,char*);
int sqlite3KeywordCode(const unsigned char*, int);
int sqlite3RunParser(Parse*, const char*, char **);
int sqlite3RunParser(Parse*, const char*);
void sqlite3FinishCoding(Parse*);
int sqlite3GetTempReg(Parse*);
void sqlite3ReleaseTempReg(Parse*,int);
int sqlite3GetTempRange(Parse*,int);
void sqlite3ReleaseTempRange(Parse*,int,int);
void sqlite3ClearTempRegCache(Parse*);
#ifdef SQLITE_DEBUG
int sqlite3NoTempsInRange(Parse*,int,int);
#endif
Expr *sqlite3ExprAlloc(sqlite3*,int,const Token*,int);
Expr *sqlite3Expr(sqlite3*,int,const char*);
void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*);
Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*);
void sqlite3PExprAddSelect(Parse*, Expr*, Select*);
Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*);
Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*, int);
Expr *sqlite3ExprAnd(Parse*,Expr*, Expr*);
Expr *sqlite3ExprSimplifiedAndOr(Expr*);
Expr *sqlite3ExprFunction(Parse*,ExprList*, const Token*, int);
void sqlite3ExprFunctionUsable(Parse*,const Expr*,const 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*);
Select *sqlite3ExprListToValues(Parse*, int, ExprList*);
void sqlite3ExprListSetSortOrder(ExprList*,int);
void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
void sqlite3ExprListSetSortOrder(ExprList*,int,int);
void sqlite3ExprListSetName(Parse*,ExprList*,const Token*,int);
void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*);
void sqlite3ExprListDelete(sqlite3*, ExprList*);
u32 sqlite3ExprListFlags(const ExprList*);
int sqlite3IndexHasDuplicateRootPage(Index*);
int sqlite3Init(sqlite3*, char**);
int sqlite3InitCallback(void*, int, char**, char**);
int sqlite3InitOne(sqlite3*, int, char**, u32);
void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
#ifndef SQLITE_OMIT_VIRTUALTABLE
Module *sqlite3PragmaVtabRegister(sqlite3*,const char *zName);
#endif
void sqlite3ResetAllSchemasOfConnection(sqlite3*);
void sqlite3ResetOneSchema(sqlite3*,int);
void sqlite3CollapseDatabaseArray(sqlite3*);
void sqlite3CommitInternalChanges(sqlite3*);
void sqlite3ColumnSetExpr(Parse*,Table*,Column*,Expr*);
Expr *sqlite3ColumnExpr(Table*,Column*);
void sqlite3ColumnSetColl(sqlite3*,Column*,const char*zColl);
const char *sqlite3ColumnColl(Column*);
void sqlite3DeleteColumnNames(sqlite3*,Table*);
void sqlite3GenerateColumnNames(Parse *pParse, Select *pSelect);
int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**);
void sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*);
Table *sqlite3ResultSetOfSelect(Parse*,Select*);
void sqlite3OpenMasterTable(Parse *, int);
void sqlite3SubqueryColumnTypes(Parse*,Table*,Select*,char);
Table *sqlite3ResultSetOfSelect(Parse*,Select*,char);
void sqlite3OpenSchemaTable(Parse *, int);
Index *sqlite3PrimaryKeyIndex(Table*);
i16 sqlite3ColumnOfIndex(Index*, i16);
i16 sqlite3TableColumnToIndex(Index*, i16);
#ifdef SQLITE_OMIT_GENERATED_COLUMNS
# define sqlite3TableColumnToStorage(T,X) (X)  /* No-op pass-through */
# define sqlite3StorageColumnToTable(T,X) (X)  /* No-op pass-through */
#else
  i16 sqlite3TableColumnToStorage(Table*, i16);
  i16 sqlite3StorageColumnToTable(Table*, i16);
#endif
void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int);
#if SQLITE_ENABLE_HIDDEN_COLUMNS
  void sqlite3ColumnPropertiesFromName(Table*, Column*);
#else
# define sqlite3ColumnPropertiesFromName(T,C) /* no-op */
#endif
void sqlite3AddColumn(Parse*,Token*,Token*);
void sqlite3AddColumn(Parse*,Token,Token);
void sqlite3AddNotNull(Parse*, int);
void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int);
void sqlite3AddCheckConstraint(Parse*, Expr*);
void sqlite3AddCheckConstraint(Parse*, Expr*, const char*, const char*);
void sqlite3AddDefaultValue(Parse*,Expr*,const char*,const char*);
void sqlite3AddCollateType(Parse*, Token*);
void sqlite3AddGenerated(Parse*,Expr*,Token*);
void sqlite3EndTable(Parse*,Token*,Token*,u8,Select*);
void sqlite3EndTable(Parse*,Token*,Token*,u32,Select*);
void sqlite3AddReturning(Parse*,ExprList*);
int sqlite3ParseUri(const char*,const char*,unsigned int*,
                    sqlite3_vfs**,char**,char **);
#define sqlite3CodecQueryParameters(A,B,C) 0
Btree *sqlite3DbNameToBtree(sqlite3*,const char*);

#ifdef SQLITE_UNTESTABLE
# define sqlite3FaultSim(X) SQLITE_OK
#else
  int sqlite3FaultSim(int);
#endif
3922
3923
3924
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
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
4000
4001
4002
4003
4004
4005
4006





4007

4008
4009
4010
4011

4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026

4027
4028
4029
4030
4031
4032
4033

4034
4035
4036
4037

4038
4039
4040
4041
4042
4043
4044
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798


4799
4800
4801
4802

4803
4804
4805


4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829

4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855

4856
4857
4858

4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871

4872
4873
4874
4875
4876
4877





4878
4879
4880
4881
4882
4883
4884
4885
4886
4887

4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915

4916
4917
4918
4919
4920
4921
4922
4923







+
+
+



-
-
+
+
+

-
+


-
-
+
+


+















+



-
+
+





+







+





+
+
+


-
+


-












+
-
+





-
-
-
-
-
+
+
+
+
+

+



-
+















+







+



-
+







  void sqlite3AutoincrementBegin(Parse *pParse);
  void sqlite3AutoincrementEnd(Parse *pParse);
#else
# define sqlite3AutoincrementBegin(X)
# define sqlite3AutoincrementEnd(X)
#endif
void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int, Upsert*);
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
  void sqlite3ComputeGeneratedColumns(Parse*, int, Table*);
#endif
void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*);
IdList *sqlite3IdListAppend(Parse*, IdList*, Token*);
int sqlite3IdListIndex(IdList*,const char*);
SrcList *sqlite3SrcListEnlarge(sqlite3*, SrcList*, int, int);
SrcList *sqlite3SrcListAppend(sqlite3*, SrcList*, Token*, Token*);
SrcList *sqlite3SrcListEnlarge(Parse*, SrcList*, int, int);
SrcList *sqlite3SrcListAppendList(Parse *pParse, SrcList *p1, SrcList *p2);
SrcList *sqlite3SrcListAppend(Parse*, SrcList*, Token*, Token*);
SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*,
                                      Token*, Select*, Expr*, IdList*);
                                      Token*, Select*, OnOrUsing*);
void sqlite3SrcListIndexedBy(Parse *, SrcList *, Token *);
void sqlite3SrcListFuncArgs(Parse*, SrcList*, ExprList*);
int sqlite3IndexedByLookup(Parse *, struct SrcList_item *);
void sqlite3SrcListShiftJoinType(SrcList*);
int sqlite3IndexedByLookup(Parse *, SrcItem *);
void sqlite3SrcListShiftJoinType(Parse*,SrcList*);
void sqlite3SrcListAssignCursors(Parse*, SrcList*);
void sqlite3IdListDelete(sqlite3*, IdList*);
void sqlite3ClearOnOrUsing(sqlite3*, OnOrUsing*);
void sqlite3SrcListDelete(sqlite3*, SrcList*);
Index *sqlite3AllocateIndexObject(sqlite3*,i16,int,char**);
void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
                          Expr*, int, int, u8);
void sqlite3DropIndex(Parse*, SrcList*, int);
int sqlite3Select(Parse*, Select*, SelectDest*);
Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
                         Expr*,ExprList*,u32,Expr*);
void sqlite3SelectDelete(sqlite3*, Select*);
Table *sqlite3SrcListLookup(Parse*, SrcList*);
int sqlite3IsReadOnly(Parse*, Table*, int);
void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,char*);
#endif
void sqlite3CodeChangeCount(Vdbe*,int,const char*);
void sqlite3DeleteFrom(Parse*, SrcList*, Expr*, ExprList*, Expr*);
void sqlite3Update(Parse*, SrcList*, ExprList*,Expr*,int,ExprList*,Expr*,
                   Upsert*);
WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int);
WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,
                             ExprList*,Select*,u16,int);
void sqlite3WhereEnd(WhereInfo*);
LogEst sqlite3WhereOutputRowCount(WhereInfo*);
int sqlite3WhereIsDistinct(WhereInfo*);
int sqlite3WhereIsOrdered(WhereInfo*);
int sqlite3WhereOrderByLimitOptLabel(WhereInfo*);
void sqlite3WhereMinMaxOptEarlyOut(Vdbe*,WhereInfo*);
int sqlite3WhereIsSorted(WhereInfo*);
int sqlite3WhereContinueLabel(WhereInfo*);
int sqlite3WhereBreakLabel(WhereInfo*);
int sqlite3WhereOkOnePass(WhereInfo*, int*);
#define ONEPASS_OFF      0        /* Use of ONEPASS not allowed */
#define ONEPASS_SINGLE   1        /* ONEPASS valid for a single row update */
#define ONEPASS_MULTI    2        /* ONEPASS is valid for multiple rows */
int sqlite3WhereUsesDeferredSeek(WhereInfo*);
void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int);
int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
void sqlite3ExprCodeMove(Parse*, int, int, int);
void sqlite3ExprCode(Parse*, Expr*, int);
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
void sqlite3ExprCodeGeneratedColumn(Parse*, Table*, Column*, int);
#endif
void sqlite3ExprCodeCopy(Parse*, Expr*, int);
void sqlite3ExprCodeFactorable(Parse*, Expr*, int);
int sqlite3ExprCodeAtInit(Parse*, Expr*, int);
int sqlite3ExprCodeRunJustOnce(Parse*, Expr*, int);
int sqlite3ExprCodeTemp(Parse*, Expr*, int*);
int sqlite3ExprCodeTarget(Parse*, Expr*, int);
void sqlite3ExprCodeAndCache(Parse*, Expr*, int);
int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int, u8);
#define SQLITE_ECEL_DUP      0x01  /* Deep, not shallow copies */
#define SQLITE_ECEL_FACTOR   0x02  /* Factor out constant terms */
#define SQLITE_ECEL_REF      0x04  /* Use ExprList.u.x.iOrderByCol */
#define SQLITE_ECEL_OMITREF  0x08  /* Omit if ExprList.u.x.iOrderByCol */
void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
void sqlite3ExprIfFalseDup(Parse*, Expr*, int, int);
Table *sqlite3FindTable(sqlite3*,const char*, const char*);
#define LOCATE_VIEW    0x01
#define LOCATE_NOERR   0x02
Table *sqlite3LocateTable(Parse*,u32 flags,const char*, const char*);
const char *sqlite3PreferredTableName(const char*);
Table *sqlite3LocateTableItem(Parse*,u32 flags,struct SrcList_item *);
Table *sqlite3LocateTableItem(Parse*,u32 flags,SrcItem *);
Index *sqlite3FindIndex(sqlite3*,const char*, const char*);
void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*);
void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*);
void sqlite3Vacuum(Parse*,Token*,Expr*);
int sqlite3RunVacuum(char**, sqlite3*, int, sqlite3_value*);
char *sqlite3NameFromToken(sqlite3*, Token*);
int sqlite3ExprCompare(Parse*,Expr*, Expr*, int);
int sqlite3ExprCompareSkip(Expr*, Expr*, int);
int sqlite3ExprListCompare(ExprList*, ExprList*, int);
int sqlite3ExprImpliesExpr(Parse*,Expr*, Expr*, int);
char *sqlite3NameFromToken(sqlite3*, const Token*);
int sqlite3ExprCompare(const Parse*,const Expr*,const Expr*, int);
int sqlite3ExprCompareSkip(Expr*,Expr*,int);
int sqlite3ExprListCompare(const ExprList*,const ExprList*, int);
int sqlite3ExprImpliesExpr(const Parse*,const Expr*,const Expr*, int);
int sqlite3ExprImpliesNonNullRow(Expr*,int);
void sqlite3AggInfoPersistWalkerInit(Walker*,Parse*);
void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx);
int sqlite3FunctionUsesThisSrc(Expr*, SrcList*);
int sqlite3ReferencesSrcList(Parse*, Expr*, SrcList*);
Vdbe *sqlite3GetVdbe(Parse*);
#ifndef SQLITE_UNTESTABLE
void sqlite3PrngSaveState(void);
void sqlite3PrngRestoreState(void);
#endif
void sqlite3FastPrngInit(FastPrng*);
void sqlite3FastRandomness(FastPrng*, int N, void *P);
void sqlite3RollbackAll(sqlite3*,int);
void sqlite3CodeVerifySchema(Parse*, int);
void sqlite3CodeVerifyNamedSchema(Parse*, const char *zDb);
void sqlite3BeginTransaction(Parse*, int);
void sqlite3EndTransaction(Parse*,int);
void sqlite3Savepoint(Parse*, int, Token*);
void sqlite3CloseSavepoints(sqlite3 *);
void sqlite3LeaveMutexAndCloseZombie(sqlite3*);
u32 sqlite3IsTrueOrFalse(const char*);
int sqlite3ExprIdToTrueFalse(Expr*);
int sqlite3ExprTruthValue(const Expr*);
int sqlite3ExprIsConstant(Expr*);
int sqlite3ExprIsConstantNotJoin(Expr*);
int sqlite3ExprIsConstantOrFunction(Expr*, u8);
int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*);
int sqlite3ExprIsTableConstant(Expr*,int);
int sqlite3ExprIsTableConstraint(Expr*,const SrcItem*);
#ifdef SQLITE_ENABLE_CURSOR_HINTS
int sqlite3ExprContainsSubquery(Expr*);
#endif
int sqlite3ExprIsInteger(Expr*, int*);
int sqlite3ExprIsInteger(const Expr*, int*);
int sqlite3ExprCanBeNull(const Expr*);
int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
int sqlite3IsRowid(const char*);
void sqlite3GenerateRowDelete(
    Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8,int);
void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int);
int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int);
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066





4067
4068
4069

4070
4071

4072



4073
4074
4075

4076
4077
4078
4079
4080
4081
4082
4934
4935
4936
4937
4938
4939
4940





4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967







-
-
-
-
-
+
+
+
+
+



+


+

+
+
+



+







int sqlite3OpenTableAndIndices(Parse*, Table*, int, u8, int, u8*, int*, int*);
void sqlite3BeginWriteOperation(Parse*, int, int);
void sqlite3MultiWrite(Parse*);
void sqlite3MayAbort(Parse*);
void sqlite3HaltConstraint(Parse*, int, int, char*, i8, u8);
void sqlite3UniqueConstraint(Parse*, int, Index*);
void sqlite3RowidConstraint(Parse*, int, Table*);
Expr *sqlite3ExprDup(sqlite3*,Expr*,int);
ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int);
SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int);
IdList *sqlite3IdListDup(sqlite3*,IdList*);
Select *sqlite3SelectDup(sqlite3*,Select*,int);
Expr *sqlite3ExprDup(sqlite3*,const Expr*,int);
ExprList *sqlite3ExprListDup(sqlite3*,const ExprList*,int);
SrcList *sqlite3SrcListDup(sqlite3*,const SrcList*,int);
IdList *sqlite3IdListDup(sqlite3*,const IdList*);
Select *sqlite3SelectDup(sqlite3*,const Select*,int);
FuncDef *sqlite3FunctionSearch(int,const char*);
void sqlite3InsertBuiltinFuncs(FuncDef*,int);
FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,u8,u8);
void sqlite3QuoteValue(StrAccum*,sqlite3_value*);
void sqlite3RegisterBuiltinFunctions(void);
void sqlite3RegisterDateTimeFunctions(void);
void sqlite3RegisterJsonFunctions(void);
void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3*);
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON)
  int sqlite3JsonTableFunctions(sqlite3*);
#endif
int sqlite3SafetyCheckOk(sqlite3*);
int sqlite3SafetyCheckSickOrOk(sqlite3*);
void sqlite3ChangeCookie(Parse*, int);
With *sqlite3WithDup(sqlite3 *db, With *p);

#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int);
#endif

#ifndef SQLITE_OMIT_TRIGGER
  void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*,
4092
4093
4094
4095
4096
4097
4098
4099
4100


4101
4102
4103
4104
4105

4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118

4119
4120
4121



4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135

4136
4137
4138
4139
4140
4141
4142
4143



4144
4145

4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4977
4978
4979
4980
4981
4982
4983


4984
4985
4986
4987
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
5024
5025
5026
5027
5028
5029
5030
5031
5032

5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047

5048




5049

5050
5051
5052
5053
5054
5055
5056







-
-
+
+





+













+



+
+
+














+






-

+
+
+


+








-

-
-
-
-

-







  void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*);
  void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*);
  TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*,
                                        const char*,const char*);
  TriggerStep *sqlite3TriggerInsertStep(Parse*,Token*, IdList*,
                                        Select*,u8,Upsert*,
                                        const char*,const char*);
  TriggerStep *sqlite3TriggerUpdateStep(Parse*,Token*,ExprList*, Expr*, u8,
                                        const char*,const char*);
  TriggerStep *sqlite3TriggerUpdateStep(Parse*,Token*,SrcList*,ExprList*,
                                        Expr*, u8, const char*,const char*);
  TriggerStep *sqlite3TriggerDeleteStep(Parse*,Token*, Expr*,
                                        const char*,const char*);
  void sqlite3DeleteTrigger(sqlite3*, Trigger*);
  void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*);
  u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int);
  SrcList *sqlite3TriggerStepSrc(Parse*, TriggerStep*);
# define sqlite3ParseToplevel(p) ((p)->pToplevel ? (p)->pToplevel : (p))
# define sqlite3IsToplevel(p) ((p)->pToplevel==0)
#else
# define sqlite3TriggersExist(B,C,D,E,F) 0
# define sqlite3DeleteTrigger(A,B)
# define sqlite3DropTriggerPtr(A,B)
# define sqlite3UnlinkAndDeleteTrigger(A,B,C)
# define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I)
# define sqlite3CodeRowTriggerDirect(A,B,C,D,E,F)
# define sqlite3TriggerList(X, Y) 0
# define sqlite3ParseToplevel(p) p
# define sqlite3IsToplevel(p) 1
# define sqlite3TriggerColmask(A,B,C,D,E,F,G) 0
# define sqlite3TriggerStepSrc(A,B) 0
#endif

int sqlite3JoinType(Parse*, Token*, Token*, Token*);
int sqlite3ColumnIndex(Table *pTab, const char *zCol);
void sqlite3SrcItemColumnUsed(SrcItem*,int);
void sqlite3SetJoinExpr(Expr*,int,u32);
void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int);
void sqlite3DeferForeignKey(Parse*, int);
#ifndef SQLITE_OMIT_AUTHORIZATION
  void sqlite3AuthRead(Parse*,Expr*,Schema*,SrcList*);
  int sqlite3AuthCheck(Parse*,int, const char*, const char*, const char*);
  void sqlite3AuthContextPush(Parse*, AuthContext*, const char*);
  void sqlite3AuthContextPop(AuthContext*);
  int sqlite3AuthReadCol(Parse*, const char *, const char *, int);
#else
# define sqlite3AuthRead(a,b,c,d)
# define sqlite3AuthCheck(a,b,c,d,e)    SQLITE_OK
# define sqlite3AuthContextPush(a,b,c)
# define sqlite3AuthContextPop(a)  ((void)(a))
#endif
int sqlite3DbIsNamed(sqlite3 *db, int iDb, const char *zName);
void sqlite3Attach(Parse*, Expr*, Expr*, Expr*);
void sqlite3Detach(Parse*, Expr*);
void sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*);
int sqlite3FixSrcList(DbFixer*, SrcList*);
int sqlite3FixSelect(DbFixer*, Select*);
int sqlite3FixExpr(DbFixer*, Expr*);
int sqlite3FixExprList(DbFixer*, ExprList*);
int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
int sqlite3RealSameAsInt(double,sqlite3_int64);
i64 sqlite3RealToI64(double);
int sqlite3Int64ToText(i64,char*);
int sqlite3AtoF(const char *z, double*, int, u8);
int sqlite3GetInt32(const char *, int*);
int sqlite3GetUInt32(const char*, u32*);
int sqlite3Atoi(const char*);
#ifndef SQLITE_OMIT_UTF16
int sqlite3Utf16ByteLen(const void *pData, int nChar);
#endif
int sqlite3Utf8CharLen(const char *pData, int nByte);
u32 sqlite3Utf8Read(const u8**);
LogEst sqlite3LogEst(u64);
LogEst sqlite3LogEstAdd(LogEst,LogEst);
#ifndef SQLITE_OMIT_VIRTUALTABLE
LogEst sqlite3LogEstFromDouble(double);
#endif
#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \
    defined(SQLITE_ENABLE_STAT3_OR_STAT4) || \
    defined(SQLITE_EXPLAIN_ESTIMATED_ROWS)
u64 sqlite3LogEstToInt(LogEst);
#endif
VList *sqlite3VListAdd(sqlite3*,VList*,const char*,int,int);
const char *sqlite3VListNumToName(VList*,int);
int sqlite3VListNameToNum(VList*,const char*,int);

/*
** Routines to read and write variable-length integers.  These used to
** be defined locally, but now we use the varint routines in the util.c
4176
4177
4178
4179
4180
4181
4182


4183
4184
4185
4186
4187
4188
4189
4190

4191
4192
4193
4194
4195





4196
4197
4198
4199

4200
4201
4202
4203
4204
4205
4206
4207
4208
4209

4210



4211
4212
4213
4214
4215
4216
4217

4218
4219
4220
4221
4222





4223

4224
4225
4226
4227


4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244



4245
4246
4247
4248
4249

4250
4251
4252
4253



4254
4255
4256




4257
4258
4259
4260
4261
4262

4263
4264
4265
4266

4267
4268
4269
4270
4271
4272
4273

4274

4275

4276
4277








4278
4279
4280
4281

4282
4283
4284
4285

4286
4287


4288
4289
4290
4291
4292
4293

4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308


4309
4310
4311
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
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082




5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101

5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114





5115
5116
5117
5118
5119
5120
5121
5122
5123


5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149

5150
5151
5152
5153
5154
5155
5156
5157
5158


5159
5160
5161
5162
5163
5164
5165
5166
5167

5168
5169
5170
5171

5172
5173
5174
5175
5176
5177
5178
5179
5180

5181
5182
5183
5184

5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195

5196
5197
5198
5199
5200
5201


5202
5203
5204
5205
5206
5207
5208

5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239

5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263

5264

5265
5266
5267
5268
5269
5270
5271







+
+








+

-
-
-
-
+
+
+
+
+




+









-
+

+
+
+







+
-
-
-
-
-
+
+
+
+
+

+


-
-
+
+

















+
+
+




-
+




+
+
+

-
-
+
+
+
+





-
+



-
+







+
-
+

+

-
+
+
+
+
+
+
+
+



-
+




+
-
-
+
+





-
+















+
+













-
+





+

+
+


+
+










-
+
-







/*
** The common case is for a varint to be a single byte.  They following
** macros handle the common case without a procedure call, but then call
** the procedure for larger varints.
*/
#define getVarint32(A,B)  \
  (u8)((*(A)<(u8)0x80)?((B)=(u32)*(A)),1:sqlite3GetVarint32((A),(u32 *)&(B)))
#define getVarint32NR(A,B) \
  B=(u32)*(A);if(B>=0x80)sqlite3GetVarint32((A),(u32*)&(B))
#define putVarint32(A,B)  \
  (u8)(((u32)(B)<(u32)0x80)?(*(A)=(unsigned char)(B)),1:\
  sqlite3PutVarint((A),(B)))
#define getVarint    sqlite3GetVarint
#define putVarint    sqlite3PutVarint


const char *sqlite3IndexAffinityStr(sqlite3*, Index*);
char *sqlite3TableAffinityStr(sqlite3*,const Table*);
void sqlite3TableAffinity(Vdbe*, Table*, int);
char sqlite3CompareAffinity(Expr *pExpr, char aff2);
int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
char sqlite3TableColumnAffinity(Table*,int);
char sqlite3ExprAffinity(Expr *pExpr);
char sqlite3CompareAffinity(const Expr *pExpr, char aff2);
int sqlite3IndexAffinityOk(const Expr *pExpr, char idx_affinity);
char sqlite3TableColumnAffinity(const Table*,int);
char sqlite3ExprAffinity(const Expr *pExpr);
int sqlite3ExprDataType(const Expr *pExpr);
int sqlite3Atoi64(const char*, i64*, int, u8);
int sqlite3DecOrHexToI64(const char*, i64*);
void sqlite3ErrorWithMsg(sqlite3*, int, const char*,...);
void sqlite3Error(sqlite3*,int);
void sqlite3ErrorClear(sqlite3*);
void sqlite3SystemError(sqlite3*,int);
void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
u8 sqlite3HexToInt(int h);
int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);

#if defined(SQLITE_NEED_ERR_NAME)
const char *sqlite3ErrName(int);
#endif

#ifdef SQLITE_ENABLE_DESERIALIZE
#ifndef SQLITE_OMIT_DESERIALIZE
int sqlite3MemdbInit(void);
int sqlite3IsMemdb(const sqlite3_vfs*);
#else
# define sqlite3IsMemdb(X) 0
#endif

const char *sqlite3ErrStr(int);
int sqlite3ReadSchema(Parse *pParse);
CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
int sqlite3IsBinary(const CollSeq*);
CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
void sqlite3SetTextEncoding(sqlite3 *db, u8);
CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr);
int sqlite3ExprCollSeqMatch(Parse*,Expr*,Expr*);
Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int);
Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr);
CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, const Expr *pExpr);
int sqlite3ExprCollSeqMatch(Parse*,const Expr*,const Expr*);
Expr *sqlite3ExprAddCollateToken(const Parse *pParse, Expr*, const Token*, int);
Expr *sqlite3ExprAddCollateString(const Parse*,Expr*,const char*);
Expr *sqlite3ExprSkipCollate(Expr*);
Expr *sqlite3ExprSkipCollateAndLikely(Expr*);
int sqlite3CheckCollSeq(Parse *, CollSeq *);
int sqlite3WritableSchema(sqlite3*);
int sqlite3CheckObjectName(Parse *, const char *);
void sqlite3VdbeSetChanges(sqlite3 *, int);
int sqlite3CheckObjectName(Parse*, const char*,const char*,const char*);
void sqlite3VdbeSetChanges(sqlite3 *, i64);
int sqlite3AddInt64(i64*,i64);
int sqlite3SubInt64(i64*,i64);
int sqlite3MulInt64(i64*,i64);
int sqlite3AbsInt32(int);
#ifdef SQLITE_ENABLE_8_3_NAMES
void sqlite3FileSuffix3(const char*, char*);
#else
# define sqlite3FileSuffix3(X,Y)
#endif
u8 sqlite3GetBoolean(const char *z,u8);

const void *sqlite3ValueText(sqlite3_value*, u8);
int sqlite3ValueBytes(sqlite3_value*, u8);
void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8,
                        void(*)(void*));
void sqlite3ValueSetNull(sqlite3_value*);
void sqlite3ValueFree(sqlite3_value*);
#ifndef SQLITE_UNTESTABLE
void sqlite3ResultIntReal(sqlite3_context*);
#endif
sqlite3_value *sqlite3ValueNew(sqlite3 *);
#ifndef SQLITE_OMIT_UTF16
char *sqlite3Utf16to8(sqlite3 *, const void*, int, u8);
#endif
int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **);
int sqlite3ValueFromExpr(sqlite3 *, const 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 sqlite3StdTypeLen[];
extern const char sqlite3StdTypeAffinity[];
extern const char *sqlite3StdType[];
extern const unsigned char sqlite3UpperToLower[];
extern const unsigned char sqlite3CtypeMap[];
extern const Token sqlite3IntTokens[];
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
#endif /* SQLITE_AMALGAMATION */
#ifdef VDBE_PROFILE
extern sqlite3_uint64 sqlite3NProfileCnt;
#endif
void sqlite3RootPageMoved(sqlite3*, int, int, int);
void sqlite3RootPageMoved(sqlite3*, int, Pgno, Pgno);
void sqlite3Reindex(Parse*, Token*, Token*);
void sqlite3AlterFunctions(void);
void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*);
int sqlite3GetToken(const unsigned char *, int *);
void sqlite3NestedParse(Parse*, const char*, ...);
void sqlite3ExpirePreparedStatements(sqlite3*, int);
void sqlite3CodeRhsOfIN(Parse*, Expr*, int);
int sqlite3CodeSubselect(Parse*, Expr *, int, int);
int sqlite3CodeSubselect(Parse*, Expr*);
void sqlite3SelectPrep(Parse*, Select*, NameContext*);
int sqlite3ExpandSubquery(Parse*, SrcItem*);
void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p);
int sqlite3MatchSpanName(const char*, const char*, const char*, const char*);
int sqlite3MatchEName(
  const struct ExprList_item*,
  const char*,
  const char*,
  const char*
);
Bitmask sqlite3ExprColUsed(Expr*);
u8 sqlite3StrIHash(const char*);
int sqlite3ResolveExprNames(NameContext*, Expr*);
int sqlite3ResolveExprListNames(NameContext*, ExprList*);
void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);
void sqlite3ResolveSelfReference(Parse*,Table*,int,Expr*,ExprList*);
int sqlite3ResolveSelfReference(Parse*,Table*,int,Expr*,ExprList*);
int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
void sqlite3AlterFinishAddColumn(Parse *, Token *);
void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
void sqlite3AlterDropColumn(Parse*, SrcList*, const Token*);
void *sqlite3RenameTokenMap(Parse*, void*, Token*);
void sqlite3RenameTokenRemap(Parse*, void *pTo, void *pFrom);
const void *sqlite3RenameTokenMap(Parse*, const void*, const Token*);
void sqlite3RenameTokenRemap(Parse*, const void *pTo, const void *pFrom);
void sqlite3RenameExprUnmap(Parse*, Expr*);
void sqlite3RenameExprlistUnmap(Parse*, ExprList*);
CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*);
char sqlite3AffinityType(const char*, Column*);
void sqlite3Analyze(Parse*, Token*, Token*);
int sqlite3InvokeBusyHandler(BusyHandler*, sqlite3_file*);
int sqlite3InvokeBusyHandler(BusyHandler*);
int sqlite3FindDb(sqlite3*, Token*);
int sqlite3FindDbName(sqlite3 *, const char *);
int sqlite3AnalysisLoad(sqlite3*,int iDB);
void sqlite3DeleteIndexSamples(sqlite3*,Index*);
void sqlite3DefaultRowEst(Index*);
void sqlite3RegisterLikeFunctions(sqlite3*, int);
int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*);
void sqlite3SchemaClear(void *);
Schema *sqlite3SchemaGet(sqlite3 *, Btree *);
int sqlite3SchemaToIndex(sqlite3 *db, Schema *);
KeyInfo *sqlite3KeyInfoAlloc(sqlite3*,int,int);
void sqlite3KeyInfoUnref(KeyInfo*);
KeyInfo *sqlite3KeyInfoRef(KeyInfo*);
KeyInfo *sqlite3KeyInfoOfIndex(Parse*, Index*);
KeyInfo *sqlite3KeyInfoFromExprList(Parse*, ExprList*, int, int);
const char *sqlite3SelectOpName(int);
int sqlite3HasExplicitNulls(Parse*, ExprList*);

#ifdef SQLITE_DEBUG
int sqlite3KeyInfoIsWriteable(KeyInfo*);
#endif
int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *,
  void (*)(sqlite3_context*,int,sqlite3_value **),
  void (*)(sqlite3_context*,int,sqlite3_value **), 
  void (*)(sqlite3_context*),
  void (*)(sqlite3_context*),
  void (*)(sqlite3_context*,int,sqlite3_value **), 
  FuncDestructor *pDestructor
);
void sqlite3NoopDestructor(void*);
void sqlite3OomFault(sqlite3*);
void *sqlite3OomFault(sqlite3*);
void sqlite3OomClear(sqlite3*);
int sqlite3ApiExit(sqlite3 *db, int);
int sqlite3OpenTempDatabase(Parse *);

void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int);
int sqlite3StrAccumEnlarge(StrAccum*, i64);
char *sqlite3StrAccumFinish(StrAccum*);
void sqlite3StrAccumSetError(StrAccum*, u8);
void sqlite3ResultStrAccum(sqlite3_context*,StrAccum*);
void sqlite3SelectDestInit(SelectDest*,int,int);
Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int);
void sqlite3RecordErrorByteOffset(sqlite3*,const char*);
void sqlite3RecordErrorOffsetOfExpr(sqlite3*,const Expr*);

void sqlite3BackupRestart(sqlite3_backup *);
void sqlite3BackupUpdate(sqlite3_backup *, Pgno, const u8 *);

#ifndef SQLITE_OMIT_SUBQUERY
int sqlite3ExprCheckIN(Parse*, Expr*);
#else
# define sqlite3ExprCheckIN(x,y) SQLITE_OK
#endif

#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
void sqlite3AnalyzeFunctions(void);
int sqlite3Stat4ProbeSetValue(
    Parse*,Index*,UnpackedRecord**,Expr*,int,int,int*);
int sqlite3Stat4ValueFromExpr(Parse*, Expr*, u8, sqlite3_value**);
void sqlite3Stat4ProbeFree(UnpackedRecord*);
int sqlite3Stat4Column(sqlite3*, const void*, int, int, sqlite3_value**);
char sqlite3IndexColumnAffinity(sqlite3*, Index*, int);
#endif
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
4394
4395
4396
4397
4398
4399

4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411










4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423

4424




4425
4426
4427

4428


4429
4430
4431
4432
4433

4434

4435
4436
4437
4438
4439
4440
4441


4442

4443
4444

4445

4446
4447




4448
4449
4450

4451
4452
4453
4454


4455
4456

4457
4458



4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475

4476
4477
4478
4479
4480
4481
4482

4483
4484
4485
4486
4487
4488
4489
5287
5288
5289
5290
5291
5292
5293

5294
5295
5296
5297
5298
5299
5300
5301
5302
5303

5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367

5368
5369
5370
5371
5372
5373
5374
5375

5376
5377
5378
5379
5380
5381
5382
5383
5384
5385

5386
5387

5388
5389
5390


5391
5392
5393
5394
5395
5396

5397
5398
5399
5400
5401
5402
5403
5404

5405
5406

5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442







-
+









-
+






+











+












+
+
+
+
+
+
+
+
+
+












+

+
+
+
+



+
-
+
+





+
-
+







+
+
-
+

-
+

+
-
-
+
+
+
+


-
+




+
+

-
+

-
+
+
+

















+







+







#ifndef SQLITE_OMIT_LOAD_EXTENSION
  void sqlite3CloseExtensions(sqlite3*);
#else
# define sqlite3CloseExtensions(X)
#endif

#ifndef SQLITE_OMIT_SHARED_CACHE
  void sqlite3TableLock(Parse *, int, int, u8, const char *);
  void sqlite3TableLock(Parse *, int, Pgno, u8, const char *);
#else
  #define sqlite3TableLock(v,w,x,y,z)
#endif

#ifdef SQLITE_TEST
  int sqlite3Utf8To8(unsigned char*);
#endif

#ifdef SQLITE_OMIT_VIRTUALTABLE
#  define sqlite3VtabClear(Y)
#  define sqlite3VtabClear(D,T)
#  define sqlite3VtabSync(X,Y) SQLITE_OK
#  define sqlite3VtabRollback(X)
#  define sqlite3VtabCommit(X)
#  define sqlite3VtabInSync(db) 0
#  define sqlite3VtabLock(X)
#  define sqlite3VtabUnlock(X)
#  define sqlite3VtabModuleUnref(D,X)
#  define sqlite3VtabUnlockList(X)
#  define sqlite3VtabSavepoint(X, Y, Z) SQLITE_OK
#  define sqlite3GetVTable(X,Y)  ((VTable*)0)
#else
   void sqlite3VtabClear(sqlite3 *db, Table*);
   void sqlite3VtabDisconnect(sqlite3 *db, Table *p);
   int sqlite3VtabSync(sqlite3 *db, Vdbe*);
   int sqlite3VtabRollback(sqlite3 *db);
   int sqlite3VtabCommit(sqlite3 *db);
   void sqlite3VtabLock(VTable *);
   void sqlite3VtabUnlock(VTable *);
   void sqlite3VtabModuleUnref(sqlite3*,Module*);
   void sqlite3VtabUnlockList(sqlite3*);
   int sqlite3VtabSavepoint(sqlite3 *, int, int);
   void sqlite3VtabImportErrmsg(Vdbe*, sqlite3_vtab*);
   VTable *sqlite3GetVTable(sqlite3*, Table*);
   Module *sqlite3VtabCreateModule(
     sqlite3*,
     const char*,
     const sqlite3_module*,
     void*,
     void(*)(void*)
   );
#  define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
#endif
int sqlite3ReadOnlyShadowTables(sqlite3 *db);
#ifndef SQLITE_OMIT_VIRTUALTABLE
  int sqlite3ShadowTableName(sqlite3 *db, const char *zName);
  int sqlite3IsShadowTableOf(sqlite3*,Table*,const char*);
  void sqlite3MarkAllShadowTablesOf(sqlite3*, Table*);
#else
# define sqlite3ShadowTableName(A,B) 0
# define sqlite3IsShadowTableOf(A,B,C) 0
# define sqlite3MarkAllShadowTablesOf(A,B)
#endif
int sqlite3VtabEponymousTableInit(Parse*,Module*);
void sqlite3VtabEponymousTableClear(sqlite3*,Module*);
void sqlite3VtabMakeWritable(Parse*,Table*);
void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*, int);
void sqlite3VtabFinishParse(Parse*, Token*);
void sqlite3VtabArgInit(Parse*);
void sqlite3VtabArgExtend(Parse*, Token*);
int sqlite3VtabCallCreate(sqlite3*, int, const char *, char **);
int sqlite3VtabCallConnect(Parse*, Table*);
int sqlite3VtabCallDestroy(sqlite3*, int, const char *);
int sqlite3VtabBegin(sqlite3 *, VTable *);

FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*);
#if (defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)) \
    && !defined(SQLITE_OMIT_VIRTUALTABLE)
  void sqlite3VtabUsesAllSchemas(sqlite3_index_info*);
#endif
sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*);
int sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
void sqlite3ParseObjectInit(Parse*,sqlite3*);
void sqlite3ParserReset(Parse*);
void sqlite3ParseObjectReset(Parse*);
void *sqlite3ParserAddCleanup(Parse*,void(*)(sqlite3*,void*),void*);
#ifdef SQLITE_ENABLE_NORMALIZE
char *sqlite3Normalize(Vdbe*, const char*);
#endif
int sqlite3Reprepare(Vdbe*);
void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
CollSeq *sqlite3ExprCompareCollSeq(Parse*,const Expr*);
CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
CollSeq *sqlite3BinaryCompareCollSeq(Parse *, const Expr*, const Expr*);
int sqlite3TempInMemory(const sqlite3*);
const char *sqlite3JournalModename(int);
#ifndef SQLITE_OMIT_WAL
  int sqlite3Checkpoint(sqlite3*, int, int, int*, int*);
  int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int);
#endif
#ifndef SQLITE_OMIT_CTE
  Cte *sqlite3CteNew(Parse*,Token*,ExprList*,Select*,u8);
  void sqlite3CteDelete(sqlite3*,Cte*);
  With *sqlite3WithAdd(Parse*,With*,Token*,ExprList*,Select*);
  With *sqlite3WithAdd(Parse*,With*,Cte*);
  void sqlite3WithDelete(sqlite3*,With*);
  void sqlite3WithPush(Parse*, With*, u8);
  With *sqlite3WithPush(Parse*, With*, u8);
#else
# define sqlite3CteNew(P,T,E,S)   ((void*)0)
#define sqlite3WithPush(x,y,z)
#define sqlite3WithDelete(x,y)
# define sqlite3CteDelete(D,C)
# define sqlite3CteWithAdd(P,W,C) ((void*)0)
# define sqlite3WithDelete(x,y)
# define sqlite3WithPush(x,y,z) ((void*)0)
#endif
#ifndef SQLITE_OMIT_UPSERT
  Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*);
  Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*,Upsert*);
  void sqlite3UpsertDelete(sqlite3*,Upsert*);
  Upsert *sqlite3UpsertDup(sqlite3*,Upsert*);
  int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*);
  void sqlite3UpsertDoUpdate(Parse*,Upsert*,Table*,Index*,int);
  Upsert *sqlite3UpsertOfIndex(Upsert*,Index*);
  int sqlite3UpsertNextIsIPK(Upsert*);
#else
#define sqlite3UpsertNew(v,w,x,y,z) ((Upsert*)0)
#define sqlite3UpsertNew(u,v,w,x,y,z) ((Upsert*)0)
#define sqlite3UpsertDelete(x,y)
#define sqlite3UpsertDup(x,y)       ((Upsert*)0)
#define sqlite3UpsertDup(x,y)         ((Upsert*)0)
#define sqlite3UpsertOfIndex(x,y)     ((Upsert*)0)
#define sqlite3UpsertNextIsIPK(x)     0
#endif


/* Declarations for functions in fkey.c. All of these are replaced by
** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign
** key functionality is available. If OMIT_TRIGGER is defined but
** OMIT_FOREIGN_KEY is not, only some of the functions are no-oped. In
** this case foreign keys are parsed, but no other functionality is
** provided (enforcement of FK constraints requires the triggers sub-system).
*/
#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
  void sqlite3FkCheck(Parse*, Table*, int, int, int*, int);
  void sqlite3FkDropTable(Parse*, SrcList *, Table*);
  void sqlite3FkActions(Parse*, Table*, ExprList*, int, int*, int);
  int sqlite3FkRequired(Parse*, Table*, int*, int);
  u32 sqlite3FkOldmask(Parse*, Table*);
  FKey *sqlite3FkReferences(Table *);
  void sqlite3FkClearTriggerCache(sqlite3*,int);
#else
  #define sqlite3FkActions(a,b,c,d,e,f)
  #define sqlite3FkCheck(a,b,c,d,e,f)
  #define sqlite3FkDropTable(a,b,c)
  #define sqlite3FkOldmask(a,b)         0
  #define sqlite3FkRequired(a,b,c,d)    0
  #define sqlite3FkReferences(a)        0
  #define sqlite3FkClearTriggerCache(a,b)
#endif
#ifndef SQLITE_OMIT_FOREIGN_KEY
  void sqlite3FkDelete(sqlite3 *, Table*);
  int sqlite3FkLocateIndex(Parse*,Table*,FKey*,Index**,int**);
#else
  #define sqlite3FkDelete(a,b)
  #define sqlite3FkLocateIndex(a,b,c,d,e)
4519
4520
4521
4522
4523
4524
4525
4526

4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540

4541
4542
4543
4544
4545
4546
4547
5472
5473
5474
5475
5476
5477
5478

5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492

5493
5494
5495
5496
5497
5498
5499
5500







-
+













-
+







#define IN_INDEX_NOOP         5   /* No table available. Use comparisons */
/*
** Allowed flags for the 3rd parameter to sqlite3FindInIndex().
*/
#define IN_INDEX_NOOP_OK     0x0001  /* OK to return IN_INDEX_NOOP */
#define IN_INDEX_MEMBERSHIP  0x0002  /* IN operator used for membership test */
#define IN_INDEX_LOOP        0x0004  /* IN operator used as a loop */
int sqlite3FindInIndex(Parse *, Expr *, u32, int*, int*);
int sqlite3FindInIndex(Parse *, Expr *, u32, int*, int*, int*);

int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int);
int sqlite3JournalSize(sqlite3_vfs *);
#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \
 || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
  int sqlite3JournalCreate(sqlite3_file *);
#endif

int sqlite3JournalIsInMemory(sqlite3_file *p);
void sqlite3MemJournalOpen(sqlite3_file *);

void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p);
#if SQLITE_MAX_EXPR_DEPTH>0
  int sqlite3SelectExprHeight(Select *);
  int sqlite3SelectExprHeight(const Select *);
  int sqlite3ExprCheckHeight(Parse*, int);
#else
  #define sqlite3SelectExprHeight(x) 0
  #define sqlite3ExprCheckHeight(x,y)
#endif

u32 sqlite3Get4byte(const u8*);
4604
4605
4606
4607
4608
4609
4610
4611
4612


4613
4614
4615
4616
4617
4618
4619
5557
5558
5559
5560
5561
5562
5563


5564
5565
5566
5567
5568
5569
5570
5571
5572







-
-
+
+







** this constraint.
**
** All of this is no-op for a production build.  It only comes into
** play when the SQLITE_MEMDEBUG compile-time option is used.
*/
#ifdef SQLITE_MEMDEBUG
  void sqlite3MemdebugSetType(void*,u8);
  int sqlite3MemdebugHasType(void*,u8);
  int sqlite3MemdebugNoType(void*,u8);
  int sqlite3MemdebugHasType(const void*,u8);
  int sqlite3MemdebugNoType(const void*,u8);
#else
# define sqlite3MemdebugSetType(X,Y)  /* no-op */
# define sqlite3MemdebugHasType(X,Y)  1
# define sqlite3MemdebugNoType(X,Y)   1
#endif
#define MEMTYPE_HEAP       0x01  /* General heap allocations */
#define MEMTYPE_LOOKASIDE  0x02  /* Heap that might have been lookaside */
4630
4631
4632
4633
4634
4635
4636
4637
4638


4639
4640

4641
4642
4643
4644
4645
4646










4647
5583
5584
5585
5586
5587
5588
5589


5590
5591
5592

5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610







-
-
+
+

-
+






+
+
+
+
+
+
+
+
+
+

#if defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)
int sqlite3DbpageRegister(sqlite3*);
#endif
#if defined(SQLITE_ENABLE_DBSTAT_VTAB) || defined(SQLITE_TEST)
int sqlite3DbstatRegister(sqlite3*);
#endif

int sqlite3ExprVectorSize(Expr *pExpr);
int sqlite3ExprIsVector(Expr *pExpr);
int sqlite3ExprVectorSize(const Expr *pExpr);
int sqlite3ExprIsVector(const Expr *pExpr);
Expr *sqlite3VectorFieldSubexpr(Expr*, int);
Expr *sqlite3ExprForVectorField(Parse*,Expr*,int);
Expr *sqlite3ExprForVectorField(Parse*,Expr*,int,int);
void sqlite3VectorErrorMsg(Parse*, Expr*);

#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
const char **sqlite3CompileOptions(int *pnOpt);
#endif

#if SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL)
int sqlite3KvvfsInit(void);
#endif

#if defined(VDBE_PROFILE) \
 || defined(SQLITE_PERFORMANCE_TRACE) \
 || defined(SQLITE_ENABLE_STMT_SCANSTATUS)
sqlite3_uint64 sqlite3Hwtime(void);
#endif

#endif /* SQLITEINT_H */

Changes to src/sqliteLimit.h.

56
57
58
59
60
61
62
63

64
65
66
67
68
69
70
71
72
73
74
56
57
58
59
60
61
62

63




64
65
66
67
68
69
70







-
+
-
-
-
-







# define SQLITE_MAX_SQL_LENGTH 1000000000
#endif

/*
** The maximum depth of an expression tree. This is limited to 
** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might 
** want to place more severe limits on the complexity of an 
** expression.
** expression. A value of 0 means that there is no limit.
**
** A value of 0 used to mean that the limit was not enforced.
** But that is no longer true.  The limit is now strictly enforced
** at all times.
*/
#ifndef SQLITE_MAX_EXPR_DEPTH
# define SQLITE_MAX_EXPR_DEPTH 1000
#endif

/*
** The maximum number of terms in a compound SELECT statement.
127
128
129
130
131
132
133



134
135
136

137
138
139
140
141
142
143
123
124
125
126
127
128
129
130
131
132
133
134

135
136
137
138
139
140
141
142







+
+
+


-
+







#ifndef SQLITE_MAX_ATTACHED
# define SQLITE_MAX_ATTACHED 10
#endif


/*
** The maximum value of a ?nnn wildcard that the parser will accept.
** If the value exceeds 32767 then extra space is required for the Expr
** structure.  But otherwise, we believe that the number can be as large
** as a signed 32-bit integer can hold.
*/
#ifndef SQLITE_MAX_VARIABLE_NUMBER
# define SQLITE_MAX_VARIABLE_NUMBER 999
# define SQLITE_MAX_VARIABLE_NUMBER 32766
#endif

/* Maximum page size.  The upper bound on this value is 65536.  This a limit
** imposed by the use of 16-bit offsets within each page.
**
** Earlier versions of SQLite allowed the user to change this value at
** compile time. This is no longer permitted, on the grounds that it creates

Changes to src/status.c.

184
185
186
187
188
189
190




191
192
193
194
195
196
197
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201







+
+
+
+








/*
** Count the number of slots of lookaside memory that are outstanding
*/
int sqlite3LookasideUsed(sqlite3 *db, int *pHighwater){
  u32 nInit = countLookasideSlots(db->lookaside.pInit);
  u32 nFree = countLookasideSlots(db->lookaside.pFree);
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
  nInit += countLookasideSlots(db->lookaside.pSmallInit);
  nFree += countLookasideSlots(db->lookaside.pSmallFree);
#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
  if( pHighwater ) *pHighwater = db->lookaside.nSlot - nInit;
  return db->lookaside.nSlot - (nInit+nFree);
}

/*
** Query status information for a single database connection
*/
216
217
218
219
220
221
222









223
224
225
226
227
228
229
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242







+
+
+
+
+
+
+
+
+







        LookasideSlot *p = db->lookaside.pFree;
        if( p ){
          while( p->pNext ) p = p->pNext;
          p->pNext = db->lookaside.pInit;
          db->lookaside.pInit = db->lookaside.pFree;
          db->lookaside.pFree = 0;
        }
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
        p = db->lookaside.pSmallFree;
        if( p ){
          while( p->pNext ) p = p->pNext;
          p->pNext = db->lookaside.pSmallInit;
          db->lookaside.pSmallInit = db->lookaside.pSmallFree;
          db->lookaside.pSmallFree = 0;
        }
#endif
      }
      break;
    }

    case SQLITE_DBSTATUS_LOOKASIDE_HIT:
    case SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE:
    case SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL: {
274
275
276
277
278
279
280


281
282
283
284
285
286
287
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302







+
+







    */
    case SQLITE_DBSTATUS_SCHEMA_USED: {
      int i;                      /* Used to iterate through schemas */
      int nByte = 0;              /* Used to accumulate return value */

      sqlite3BtreeEnterAll(db);
      db->pnBytesFreed = &nByte;
      assert( db->lookaside.pEnd==db->lookaside.pTrueEnd );
      db->lookaside.pEnd = db->lookaside.pStart;
      for(i=0; i<db->nDb; i++){
        Schema *pSchema = db->aDb[i].pSchema;
        if( ALWAYS(pSchema!=0) ){
          HashElem *p;

          nByte += sqlite3GlobalConfig.m.xRoundup(sizeof(HashElem)) * (
              pSchema->tblHash.count 
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
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







+

















+
+
-
-
+
+
-

+















-
+







          }
          for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){
            sqlite3DeleteTable(db, (Table *)sqliteHashData(p));
          }
        }
      }
      db->pnBytesFreed = 0;
      db->lookaside.pEnd = db->lookaside.pTrueEnd;
      sqlite3BtreeLeaveAll(db);

      *pHighwater = 0;
      *pCurrent = nByte;
      break;
    }

    /*
    ** *pCurrent gets an accurate estimate of the amount of memory used
    ** to store all prepared statements.
    ** *pHighwater is set to zero.
    */
    case SQLITE_DBSTATUS_STMT_USED: {
      struct Vdbe *pVdbe;         /* Used to iterate through VMs */
      int nByte = 0;              /* Used to accumulate return value */

      db->pnBytesFreed = &nByte;
      assert( db->lookaside.pEnd==db->lookaside.pTrueEnd );
      db->lookaside.pEnd = db->lookaside.pStart;
      for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){
        sqlite3VdbeClearObject(db, pVdbe);
      for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pVNext){
        sqlite3VdbeDelete(pVdbe);
        sqlite3DbFree(db, pVdbe);
      }
      db->lookaside.pEnd = db->lookaside.pTrueEnd;
      db->pnBytesFreed = 0;

      *pHighwater = 0;  /* IMP: R-64479-57858 */
      *pCurrent = nByte;

      break;
    }

    /*
    ** Set *pCurrent to the total cache hits or misses encountered by all
    ** pagers the database handle is connected to. *pHighwater is always set 
    ** to zero.
    */
    case SQLITE_DBSTATUS_CACHE_SPILL:
      op = SQLITE_DBSTATUS_CACHE_WRITE+1;
      /* Fall through into the next case */
      /* no break */ deliberate_fall_through
    case SQLITE_DBSTATUS_CACHE_HIT:
    case SQLITE_DBSTATUS_CACHE_MISS:
    case SQLITE_DBSTATUS_CACHE_WRITE:{
      int i;
      int nRet = 0;
      assert( SQLITE_DBSTATUS_CACHE_MISS==SQLITE_DBSTATUS_CACHE_HIT+1 );
      assert( SQLITE_DBSTATUS_CACHE_WRITE==SQLITE_DBSTATUS_CACHE_HIT+2 );

Changes to src/table.c.

52
53
54
55
56
57
58
59

60
61
62
63
64
65
66
52
53
54
55
56
57
58

59
60
61
62
63
64
65
66







-
+







    need = nCol*2;
  }else{
    need = nCol;
  }
  if( p->nData + need > p->nAlloc ){
    char **azNew;
    p->nAlloc = p->nAlloc*2 + need;
    azNew = sqlite3_realloc64( p->azResult, sizeof(char*)*p->nAlloc );
    azNew = sqlite3Realloc( p->azResult, sizeof(char*)*p->nAlloc );
    if( azNew==0 ) goto malloc_failed;
    p->azResult = azNew;
  }

  /* If this is the first row, then generate an extra row containing
  ** the names of all columns.
  */
161
162
163
164
165
166
167
168

169
170
171
172
173
174
175
161
162
163
164
165
166
167

168
169
170
171
172
173
174
175







-
+







  sqlite3_free(res.zErrMsg);
  if( rc!=SQLITE_OK ){
    sqlite3_free_table(&res.azResult[1]);
    return rc;
  }
  if( res.nAlloc>res.nData ){
    char **azNew;
    azNew = sqlite3_realloc64( res.azResult, sizeof(char*)*res.nData );
    azNew = sqlite3Realloc( res.azResult, sizeof(char*)*res.nData );
    if( azNew==0 ){
      sqlite3_free_table(&res.azResult[1]);
      db->errCode = SQLITE_NOMEM;
      return SQLITE_NOMEM_BKPT;
    }
    res.azResult = azNew;
  }

Changes to src/tclsqlite.c.

89
90
91
92
93
94
95








96
97
98
99
100
101
102

103
104
105
106
107
108
109
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







+
+
+
+
+
+
+
+







+








/* Forward declaration */
typedef struct SqliteDb SqliteDb;

/*
** New SQL functions can be created as TCL scripts.  Each such function
** is described by an instance of the following structure.
**
** Variable eType may be set to SQLITE_INTEGER, SQLITE_FLOAT, SQLITE_TEXT,
** SQLITE_BLOB or SQLITE_NULL. If it is SQLITE_NULL, then the implementation
** attempts to determine the type of the result based on the Tcl object.
** If it is SQLITE_TEXT or SQLITE_BLOB, then a text (sqlite3_result_text())
** or blob (sqlite3_result_blob()) is returned. If it is SQLITE_INTEGER
** or SQLITE_FLOAT, then an attempt is made to return an integer or float
** value, falling back to float and then text if this is not possible.
*/
typedef struct SqlFunc SqlFunc;
struct SqlFunc {
  Tcl_Interp *interp;   /* The TCL interpret to execute the function */
  Tcl_Obj *pScript;     /* The Tcl_Obj representation of the script */
  SqliteDb *pDb;        /* Database connection that owns this function */
  int useEvalObjv;      /* True if it is safe to use Tcl_EvalObjv */
  int eType;            /* Type of value to return */
  char *zName;          /* Name of this function */
  SqlFunc *pNext;       /* Next function on the list of them all */
};

/*
** New collation sequences function can be created as TCL scripts.  Each such
** function is described by an instance of the following structure.
146
147
148
149
150
151
152

153
154
155
156
157
158
159
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169







+







  Tcl_Interp *interp;        /* The interpreter used for this database */
  char *zBusy;               /* The busy callback routine */
  char *zCommit;             /* The commit hook callback routine */
  char *zTrace;              /* The trace callback routine */
  char *zTraceV2;            /* The trace_v2 callback routine */
  char *zProfile;            /* The profile callback routine */
  char *zProgress;           /* The progress callback routine */
  char *zBindFallback;       /* Callback to invoke on a binding miss */
  char *zAuth;               /* The authorization callback routine */
  int disableAuth;           /* Disable the authorizer if it exists */
  char *zNull;               /* Text to substitute for an SQL NULL value */
  SqlFunc *pFunc;            /* List of SQL functions */
  Tcl_Obj *pUpdateHook;      /* Update hook script (if any) */
  Tcl_Obj *pPreUpdateHook;   /* Pre-update hook script (if any) */
  Tcl_Obj *pRollbackHook;    /* Rollback hook script (if any) */
167
168
169
170
171
172
173

174
175
176
177
178
179
180
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191







+







  int maxStmt;               /* The next maximum number of stmtList */
  int nStmt;                 /* Number of statements in stmtList */
  IncrblobChannel *pIncrblob;/* Linked list of open incrblob channels */
  int nStep, nSort, nIndex;  /* Statistics for most recent operation */
  int nVMStep;               /* Another statistic for most recent operation */
  int nTransaction;          /* Number of nested [transaction] methods */
  int openFlags;             /* Flags used to open.  (SQLITE_OPEN_URI) */
  int nRef;                  /* Delete object when this reaches 0 */
#ifdef SQLITE_TEST
  int bLegacyPrepare;        /* True to use sqlite3_prepare() */
#endif
};

struct IncrblobChannel {
  sqlite3_blob *pBlob;      /* sqlite3 blob handle */
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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







    pNext = pPreStmt->pNext;
    dbFreeStmt(pPreStmt);
  }
  pDb->nStmt = 0;
  pDb->stmtLast = 0;
  pDb->stmtList = 0;
}

/*
** Increment the reference counter on the SqliteDb object. The reference
** should be released by calling delDatabaseRef().
*/
static void addDatabaseRef(SqliteDb *pDb){
  pDb->nRef++;
}

/*
** Decrement the reference counter associated with the SqliteDb object.
** If it reaches zero, delete the object.
*/
static void delDatabaseRef(SqliteDb *pDb){
  assert( pDb->nRef>0 );
  pDb->nRef--;
  if( pDb->nRef==0 ){
    flushStmtCache(pDb);
    closeIncrblobChannels(pDb);
    sqlite3_close(pDb->db);
    while( pDb->pFunc ){
      SqlFunc *pFunc = pDb->pFunc;
      pDb->pFunc = pFunc->pNext;
      assert( pFunc->pDb==pDb );
      Tcl_DecrRefCount(pFunc->pScript);
      Tcl_Free((char*)pFunc);
    }
    while( pDb->pCollate ){
      SqlCollate *pCollate = pDb->pCollate;
      pDb->pCollate = pCollate->pNext;
      Tcl_Free((char*)pCollate);
    }
    if( pDb->zBusy ){
      Tcl_Free(pDb->zBusy);
    }
    if( pDb->zTrace ){
      Tcl_Free(pDb->zTrace);
    }
    if( pDb->zTraceV2 ){
      Tcl_Free(pDb->zTraceV2);
    }
    if( pDb->zProfile ){
      Tcl_Free(pDb->zProfile);
    }
    if( pDb->zBindFallback ){
      Tcl_Free(pDb->zBindFallback);
    }
    if( pDb->zAuth ){
      Tcl_Free(pDb->zAuth);
    }
    if( pDb->zNull ){
      Tcl_Free(pDb->zNull);
    }
    if( pDb->pUpdateHook ){
      Tcl_DecrRefCount(pDb->pUpdateHook);
    }
    if( pDb->pPreUpdateHook ){
      Tcl_DecrRefCount(pDb->pPreUpdateHook);
    }
    if( pDb->pRollbackHook ){
      Tcl_DecrRefCount(pDb->pRollbackHook);
    }
    if( pDb->pWalHook ){
      Tcl_DecrRefCount(pDb->pWalHook);
    }
    if( pDb->pCollateNeeded ){
      Tcl_DecrRefCount(pDb->pCollateNeeded);
    }
    Tcl_Free((char*)pDb);
  }
}

/*
** TCL calls this procedure when an sqlite3 database command is
** deleted.
*/
static void SQLITE_TCLAPI DbDeleteCmd(void *db){
  SqliteDb *pDb = (SqliteDb*)db;
  flushStmtCache(pDb);
  delDatabaseRef(pDb);
  closeIncrblobChannels(pDb);
  sqlite3_close(pDb->db);
  while( pDb->pFunc ){
    SqlFunc *pFunc = pDb->pFunc;
    pDb->pFunc = pFunc->pNext;
    assert( pFunc->pDb==pDb );
    Tcl_DecrRefCount(pFunc->pScript);
    Tcl_Free((char*)pFunc);
  }
  while( pDb->pCollate ){
    SqlCollate *pCollate = pDb->pCollate;
    pDb->pCollate = pCollate->pNext;
    Tcl_Free((char*)pCollate);
  }
  if( pDb->zBusy ){
    Tcl_Free(pDb->zBusy);
  }
  if( pDb->zTrace ){
    Tcl_Free(pDb->zTrace);
  }
  if( pDb->zTraceV2 ){
    Tcl_Free(pDb->zTraceV2);
  }
  if( pDb->zProfile ){
    Tcl_Free(pDb->zProfile);
  }
  if( pDb->zAuth ){
    Tcl_Free(pDb->zAuth);
  }
  if( pDb->zNull ){
    Tcl_Free(pDb->zNull);
  }
  if( pDb->pUpdateHook ){
    Tcl_DecrRefCount(pDb->pUpdateHook);
  }
  if( pDb->pPreUpdateHook ){
    Tcl_DecrRefCount(pDb->pPreUpdateHook);
  }
  if( pDb->pRollbackHook ){
    Tcl_DecrRefCount(pDb->pRollbackHook);
  }
  if( pDb->pWalHook ){
    Tcl_DecrRefCount(pDb->pWalHook);
  }
  if( pDb->pCollateNeeded ){
    Tcl_DecrRefCount(pDb->pCollateNeeded);
  }
  Tcl_Free((char*)pDb);
}

/*
** This routine is called when a database file is locked while trying
** to execute SQL.
*/
static int DbBusyHandler(void *cd, int nTries){
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
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







+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
+
-
-
+
+
+
+
-
-
-
-
+
+
+
+
+
+







    sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);
  }else{
    Tcl_Obj *pVar = Tcl_GetObjResult(p->interp);
    int n;
    u8 *data;
    const char *zType = (pVar->typePtr ? pVar->typePtr->name : "");
    char c = zType[0];
    int eType = p->eType;

    if( eType==SQLITE_NULL ){
    if( c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0 ){
      /* Only return a BLOB type if the Tcl variable is a bytearray and
      ** has no string representation. */
      data = Tcl_GetByteArrayFromObj(pVar, &n);
      sqlite3_result_blob(context, data, n, SQLITE_TRANSIENT);
      if( c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0 ){
        /* Only return a BLOB type if the Tcl variable is a bytearray and
        ** has no string representation. */
        eType = SQLITE_BLOB;
      }else if( (c=='b' && strcmp(zType,"boolean")==0)
             || (c=='w' && strcmp(zType,"wideInt")==0)
             || (c=='i' && strcmp(zType,"int")==0) 
      ){
        eType = SQLITE_INTEGER;
      }else if( c=='d' && strcmp(zType,"double")==0 ){
        eType = SQLITE_FLOAT;
      }else{
        eType = SQLITE_TEXT;
      }
    }

    switch( eType ){
      case SQLITE_BLOB: {
        data = Tcl_GetByteArrayFromObj(pVar, &n);
        sqlite3_result_blob(context, data, n, SQLITE_TRANSIENT);
    }else if( c=='b' && strcmp(zType,"boolean")==0 ){
      Tcl_GetIntFromObj(0, pVar, &n);
      sqlite3_result_int(context, n);
        break;
      }
      case SQLITE_INTEGER: {
        Tcl_WideInt v;
        if( TCL_OK==Tcl_GetWideIntFromObj(0, pVar, &v) ){
          sqlite3_result_int64(context, v);
    }else if( c=='d' && strcmp(zType,"double")==0 ){
      double r;
      Tcl_GetDoubleFromObj(0, pVar, &r);
      sqlite3_result_double(context, r);
          break;
        }
        /* fall-through */
      }
      case SQLITE_FLOAT: {
        double r;
        if( TCL_OK==Tcl_GetDoubleFromObj(0, pVar, &r) ){
          sqlite3_result_double(context, r);
    }else if( (c=='w' && strcmp(zType,"wideInt")==0) ||
          (c=='i' && strcmp(zType,"int")==0) ){
      Tcl_WideInt v;
          break;
      Tcl_GetWideIntFromObj(0, pVar, &v);
      sqlite3_result_int64(context, v);
        }
        /* fall-through */
      }
      default: {
    }else{
      data = (unsigned char *)Tcl_GetStringFromObj(pVar, &n);
      sqlite3_result_text(context, (char *)data, n, SQLITE_TRANSIENT);
    }
        data = (unsigned char *)Tcl_GetStringFromObj(pVar, &n);
        sqlite3_result_text(context, (char *)data, n, SQLITE_TRANSIENT);
        break;
      }
    }

  }
}

#ifndef SQLITE_OMIT_AUTHORIZATION
/*
** This is the authentication function.  It appends the authentication
** type code and the two arguments to zCmd[] then invokes the result
1202
1203
1204
1205
1206
1207
1208

1209
1210
1211
1212
1213
1214
1215
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277







+







      Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), (char*)0);
      rc = TCL_ERROR;
    }
    sqlite3_exec(pDb->db, "ROLLBACK", 0, 0, 0);
  }
  pDb->disableAuth--;

  delDatabaseRef(pDb);
  return rc;
}

/*
** Unless SQLITE_TEST is defined, this function is a simple wrapper around
** sqlite3_prepare_v2(). If SQLITE_TEST is defined, then it uses either
** sqlite3_prepare_v2() or legacy interface sqlite3_prepare(), depending
1261
1262
1263
1264
1265
1266
1267


1268
1269
1270
1271
1272
1273
1274
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338







+
+







  sqlite3_stmt *pStmt = 0;        /* Prepared statement object */
  SqlPreparedStmt *pPreStmt;      /* Pointer to cached statement */
  int nSql;                       /* Length of zSql in bytes */
  int nVar = 0;                   /* Number of variables in statement */
  int iParm = 0;                  /* Next free entry in apParm */
  char c;
  int i;
  int needResultReset = 0;        /* Need to invoke Tcl_ResetResult() */
  int rc = SQLITE_OK;             /* Value to return */
  Tcl_Interp *interp = pDb->interp;

  *ppPreStmt = 0;

  /* Trim spaces from the start of zSql and calculate the remaining length. */
  while( (c = zSql[0])==' ' || c=='\t' || c=='\r' || c=='\n' ){ zSql++; }
  nSql = strlen30(zSql);
1348
1349
1350
1351
1352
1353
1354



















1355
1356
1357
1358
1359
1360
1361
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  assert( 0==memcmp(pPreStmt->zSql, zSql, pPreStmt->nSql) );

  /* Bind values to parameters that begin with $ or : */
  for(i=1; i<=nVar; i++){
    const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
    if( zVar!=0 && (zVar[0]=='$' || zVar[0]==':' || zVar[0]=='@') ){
      Tcl_Obj *pVar = Tcl_GetVar2Ex(interp, &zVar[1], 0, 0);
      if( pVar==0 && pDb->zBindFallback!=0 ){
        Tcl_Obj *pCmd;
        int rx;
        pCmd = Tcl_NewStringObj(pDb->zBindFallback, -1);
        Tcl_IncrRefCount(pCmd);
        Tcl_ListObjAppendElement(interp, pCmd, Tcl_NewStringObj(zVar,-1));
        if( needResultReset ) Tcl_ResetResult(interp);
        needResultReset = 1;
        rx = Tcl_EvalObjEx(interp, pCmd, TCL_EVAL_DIRECT);
        Tcl_DecrRefCount(pCmd);
        if( rx==TCL_OK ){
          pVar = Tcl_GetObjResult(interp);
        }else if( rx==TCL_ERROR ){
          rc = TCL_ERROR;
          break;
        }else{
          pVar = 0;
        }
      }
      if( pVar ){
        int n;
        u8 *data;
        const char *zType = (pVar->typePtr ? pVar->typePtr->name : "");
        c = zType[0];
        if( zVar[0]=='@' ||
           (c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0) ){
1383
1384
1385
1386
1387
1388
1389

1390
1391
1392
1393

1394
1395

1396
1397
1398
1399
1400
1401
1402
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479

1480
1481
1482
1483
1484
1485
1486
1487







+




+

-
+







          sqlite3_bind_text(pStmt, i, (char *)data, n, SQLITE_STATIC);
          Tcl_IncrRefCount(pVar);
          pPreStmt->apParm[iParm++] = pVar;
        }
      }else{
        sqlite3_bind_null(pStmt, i);
      }
      if( needResultReset ) Tcl_ResetResult(pDb->interp);
    }
  }
  pPreStmt->nParm = iParm;
  *ppPreStmt = pPreStmt;
  if( needResultReset && rc==TCL_OK ) Tcl_ResetResult(pDb->interp);

  return TCL_OK;
  return rc;
}

/*
** Release a statement reference obtained by calling dbPrepareAndBind().
** There should be exactly one call to this function for each call to
** dbPrepareAndBind().
**
1512
1513
1514
1515
1516
1517
1518

1519
1520
1521
1522
1523
1524
1525
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611







+







  p->pSql = pSql;
  Tcl_IncrRefCount(pSql);
  if( pArray ){
    p->pArray = pArray;
    Tcl_IncrRefCount(pArray);
  }
  p->evalFlags = evalFlags;
  addDatabaseRef(p->pDb);
}

/*
** Obtain information about the row that the DbEvalContext passed as the
** first argument currently points to.
*/
static void dbEvalRowInfo(
1652
1653
1654
1655
1656
1657
1658

1659
1660
1661
1662
1663
1664
1665
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752







+







  }
  if( p->pArray ){
    Tcl_DecrRefCount(p->pArray);
    p->pArray = 0;
  }
  Tcl_DecrRefCount(p->pSql);
  dbReleaseColumnNames(p);
  delDatabaseRef(p->pDb);
}

/*
** Return a pointer to a Tcl_Obj structure with ref-count 0 that contains
** the value for the iCol'th column of the row currently pointed to by
** the DbEvalContext structure passed as the first argument.
*/
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
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







-
-
-
-
-
+
+
+
+
+
+











-
-
-
-
-
+
+
+
+
+
+







-
+







  int objc,
  Tcl_Obj *const*objv
){
  SqliteDb *pDb = (SqliteDb*)cd;
  int choice;
  int rc = TCL_OK;
  static const char *DB_strs[] = {
    "authorizer",             "backup",                "busy",
    "cache",                  "changes",               "close",
    "collate",                "collation_needed",      "commit_hook",
    "complete",               "copy",                  "deserialize",
    "enable_load_extension",  "errorcode",             "eval",
    "authorizer",             "backup",                "bind_fallback",
    "busy",                   "cache",                 "changes",
    "close",                  "collate",               "collation_needed",
    "commit_hook",            "complete",              "config",
    "copy",                   "deserialize",           "enable_load_extension",
    "errorcode",              "erroroffset",           "eval",
    "exists",                 "function",              "incrblob",
    "interrupt",              "last_insert_rowid",     "nullvalue",
    "onecolumn",              "preupdate",             "profile",
    "progress",               "rekey",                 "restore",
    "rollback_hook",          "serialize",             "status",
    "timeout",                "total_changes",         "trace",
    "trace_v2",               "transaction",           "unlock_notify",
    "update_hook",            "version",               "wal_hook",
    0                        
  };
  enum DB_enum {
    DB_AUTHORIZER,            DB_BACKUP,               DB_BUSY,
    DB_CACHE,                 DB_CHANGES,              DB_CLOSE,
    DB_COLLATE,               DB_COLLATION_NEEDED,     DB_COMMIT_HOOK,
    DB_COMPLETE,              DB_COPY,                 DB_DESERIALIZE,
    DB_ENABLE_LOAD_EXTENSION, DB_ERRORCODE,            DB_EVAL,
    DB_AUTHORIZER,            DB_BACKUP,               DB_BIND_FALLBACK,
    DB_BUSY,                  DB_CACHE,                DB_CHANGES,
    DB_CLOSE,                 DB_COLLATE,              DB_COLLATION_NEEDED,
    DB_COMMIT_HOOK,           DB_COMPLETE,             DB_CONFIG,
    DB_COPY,                  DB_DESERIALIZE,          DB_ENABLE_LOAD_EXTENSION,
    DB_ERRORCODE,             DB_ERROROFFSET,          DB_EVAL,
    DB_EXISTS,                DB_FUNCTION,             DB_INCRBLOB,
    DB_INTERRUPT,             DB_LAST_INSERT_ROWID,    DB_NULLVALUE,
    DB_ONECOLUMN,             DB_PREUPDATE,            DB_PROFILE,
    DB_PROGRESS,              DB_REKEY,                DB_RESTORE,
    DB_ROLLBACK_HOOK,         DB_SERIALIZE,            DB_STATUS,
    DB_TIMEOUT,               DB_TOTAL_CHANGES,        DB_TRACE,
    DB_TRACE_V2,              DB_TRANSACTION,          DB_UNLOCK_NOTIFY,
    DB_UPDATE_HOOK,           DB_VERSION,              DB_WAL_HOOK
    DB_UPDATE_HOOK,           DB_VERSION,              DB_WAL_HOOK,
  };
  /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */

  if( objc<2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
    return TCL_ERROR;
  }
1996
1997
1998
1999
2000
2001
2002











































2003
2004
2005
2006
2007
2008
2009
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







      Tcl_AppendResult(interp, "backup failed: ",
           sqlite3_errmsg(pDest), (char*)0);
      rc = TCL_ERROR;
    }
    sqlite3_close(pDest);
    break;
  }

  /*    $db bind_fallback ?CALLBACK?
  **
  ** When resolving bind parameters in an SQL statement, if the parameter
  ** cannot be associated with a TCL variable then invoke CALLBACK with a
  ** single argument that is the name of the parameter and use the return
  ** value of the CALLBACK as the binding.  If CALLBACK returns something
  ** other than TCL_OK or TCL_ERROR then bind a NULL.
  **
  ** If CALLBACK is an empty string, then revert to the default behavior 
  ** which is to set the binding to NULL.
  **
  ** If CALLBACK returns an error, that causes the statement execution to
  ** abort.  Hence, to configure a connection so that it throws an error
  ** on an attempt to bind an unknown variable, do something like this:
  **
  **     proc bind_error {name} {error "no such variable: $name"}
  **     db bind_fallback bind_error
  */
  case DB_BIND_FALLBACK: {
    if( objc>3 ){
      Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?");
      return TCL_ERROR;
    }else if( objc==2 ){
      if( pDb->zBindFallback ){
        Tcl_AppendResult(interp, pDb->zBindFallback, (char*)0);
      }
    }else{
      char *zCallback;
      int len;
      if( pDb->zBindFallback ){
        Tcl_Free(pDb->zBindFallback);
      }
      zCallback = Tcl_GetStringFromObj(objv[2], &len);
      if( zCallback && len>0 ){
        pDb->zBindFallback = Tcl_Alloc( len + 1 );
        memcpy(pDb->zBindFallback, zCallback, len+1);
      }else{
        pDb->zBindFallback = 0;
      }
    }
    break;
  }

  /*    $db busy ?CALLBACK?
  **
  ** Invoke the given callback if an SQL statement attempts to open
  ** a locked database file.
  */
  case DB_BUSY: {
2096
2097
2098
2099
2100
2101
2102
2103

2104
2105
2106
2107
2108
2109
2110
2228
2229
2230
2231
2232
2233
2234

2235
2236
2237
2238
2239
2240
2241
2242







-
+







  case DB_CHANGES: {
    Tcl_Obj *pResult;
    if( objc!=2 ){
      Tcl_WrongNumArgs(interp, 2, objv, "");
      return TCL_ERROR;
    }
    pResult = Tcl_GetObjResult(interp);
    Tcl_SetIntObj(pResult, sqlite3_changes(pDb->db));
    Tcl_SetWideIntObj(pResult, sqlite3_changes64(pDb->db));
    break;
  }

  /*    $db close
  **
  ** Shutdown the database
  */
2219
2220
2221
2222
2223
2224
2225






































































2226
2227
2228
2229
2230
2231
2232
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    }
    isComplete = sqlite3_complete( Tcl_GetStringFromObj(objv[2], 0) );
    pResult = Tcl_GetObjResult(interp);
    Tcl_SetBooleanObj(pResult, isComplete);
#endif
    break;
  }

  /*    $db config ?OPTION? ?BOOLEAN?
  **
  ** Configure the database connection using the sqlite3_db_config()
  ** interface.
  */
  case DB_CONFIG: {
    static const struct DbConfigChoices {
      const char *zName;
      int op;
    } aDbConfig[] = {
        { "defensive",          SQLITE_DBCONFIG_DEFENSIVE             },
        { "dqs_ddl",            SQLITE_DBCONFIG_DQS_DDL               },
        { "dqs_dml",            SQLITE_DBCONFIG_DQS_DML               },
        { "enable_fkey",        SQLITE_DBCONFIG_ENABLE_FKEY           },
        { "enable_qpsg",        SQLITE_DBCONFIG_ENABLE_QPSG           },
        { "enable_trigger",     SQLITE_DBCONFIG_ENABLE_TRIGGER        },
        { "enable_view",        SQLITE_DBCONFIG_ENABLE_VIEW           },
        { "fts3_tokenizer",     SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
        { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE    },
        { "legacy_file_format", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT    },
        { "load_extension",     SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
        { "no_ckpt_on_close",   SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE      },
        { "reset_database",     SQLITE_DBCONFIG_RESET_DATABASE        },
        { "trigger_eqp",        SQLITE_DBCONFIG_TRIGGER_EQP           },
        { "trusted_schema",     SQLITE_DBCONFIG_TRUSTED_SCHEMA        },
        { "writable_schema",    SQLITE_DBCONFIG_WRITABLE_SCHEMA       },
    };
    Tcl_Obj *pResult;
    int ii;
    if( objc>4 ){
      Tcl_WrongNumArgs(interp, 2, objv, "?OPTION? ?BOOLEAN?");
      return TCL_ERROR;
    }
    if( objc==2 ){
      /* With no arguments, list all configuration options and with the
      ** current value */
      pResult = Tcl_NewListObj(0,0);
      for(ii=0; ii<sizeof(aDbConfig)/sizeof(aDbConfig[0]); ii++){
        int v = 0;
        sqlite3_db_config(pDb->db, aDbConfig[ii].op, -1, &v);
        Tcl_ListObjAppendElement(interp, pResult,
           Tcl_NewStringObj(aDbConfig[ii].zName,-1));
        Tcl_ListObjAppendElement(interp, pResult,
           Tcl_NewIntObj(v));
      }
    }else{
      const char *zOpt = Tcl_GetString(objv[2]);
      int onoff = -1;
      int v = 0;
      if( zOpt[0]=='-' ) zOpt++;
      for(ii=0; ii<sizeof(aDbConfig)/sizeof(aDbConfig[0]); ii++){
        if( strcmp(aDbConfig[ii].zName, zOpt)==0 ) break;
      }
      if( ii>=sizeof(aDbConfig)/sizeof(aDbConfig[0]) ){
        Tcl_AppendResult(interp, "unknown config option: \"", zOpt,
                                "\"", (void*)0);
        return TCL_ERROR;
      }
      if( objc==4 ){
        if( Tcl_GetBooleanFromObj(interp, objv[3], &onoff) ){
          return TCL_ERROR;
        }
      }
      sqlite3_db_config(pDb->db, aDbConfig[ii].op, onoff, &v);
      pResult = Tcl_NewIntObj(v);
    }
    Tcl_SetObjResult(interp, pResult);
    break;
  }

  /*    $db copy conflict-algorithm table filename ?SEPARATOR? ?NULLINDICATOR?
  **
  ** Copy data into table from filename, optionally using SEPARATOR
  ** as column separators.  If a column contains a null string, or the
  ** value of NULLINDICATOR, a NULL is inserted for the column.
  ** conflict-algorithm is one of the sqlite conflict algorithms:
2414
2415
2416
2417
2418
2419
2420
2421

2422
2423
2424
2425
2426

2427
2428
2429
2430
2431
2432


2433
2434
2435



2436
2437



2438
2439
2440
2441
2442
2443
2444
2445
2446
2447























2448
2449
2450
2451
2452
2453

2454
2455
2456
2457






2458
2459
2460
2461


2462



2463
2464
2465
2466
2467
2468
2469
2616
2617
2618
2619
2620
2621
2622

2623
2624
2625
2626
2627

2628
2629
2630
2631
2632


2633
2634
2635
2636
2637
2638
2639
2640


2641
2642
2643






2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
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







-
+




-
+




-
-
+
+



+
+
+
-
-
+
+
+
-
-
-
-
-
-




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






+

-
-
-
+
+
+
+
+
+




+
+
-
+
+
+







                       (char*)0);
      rc = TCL_ERROR;
    }
    break;
  }

  /*
  **     $db deserialize ?DATABASE? VALUE
  **     $db deserialize ?-maxsize N? ?-readonly BOOL? ?DATABASE? VALUE
  **
  ** Reopen DATABASE (default "main") using the content in $VALUE
  */
  case DB_DESERIALIZE: {
#ifndef SQLITE_ENABLE_DESERIALIZE
#ifdef SQLITE_OMIT_DESERIALIZE
    Tcl_AppendResult(interp, "MEMDB not available in this build",
                     (char*)0);
    rc = TCL_ERROR;
#else
    const char *zSchema;
    Tcl_Obj *pValue;
    const char *zSchema = 0;
    Tcl_Obj *pValue = 0;
    unsigned char *pBA;
    unsigned char *pData;
    int len, xrc;
    sqlite3_int64 mxSize = 0;
    int i;
    int isReadonly = 0;
    
    if( objc==3 ){


    if( objc<3 ){
      zSchema = 0;
      pValue = objv[2];
    }else if( objc==4 ){
      zSchema = Tcl_GetString(objv[2]);
      pValue = objv[3];
    }else{
      Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE? VALUE");
      rc = TCL_ERROR;
      break;
    }
    for(i=2; i<objc-1; i++){
      const char *z = Tcl_GetString(objv[i]);
      if( strcmp(z,"-maxsize")==0 && i<objc-2 ){
        Tcl_WideInt x;
        rc = Tcl_GetWideIntFromObj(interp, objv[++i], &x);
        if( rc ) goto deserialize_error;
        mxSize = x;
        continue;
      }
      if( strcmp(z,"-readonly")==0 && i<objc-2 ){
        rc = Tcl_GetBooleanFromObj(interp, objv[++i], &isReadonly);
        if( rc ) goto deserialize_error;
        continue;
      }
      if( zSchema==0 && i==objc-2 && z[0]!='-' ){
        zSchema = z;
        continue;
      }
      Tcl_AppendResult(interp, "unknown option: ", z, (char*)0);
      rc = TCL_ERROR;
      goto deserialize_error;
    }
    pValue = objv[objc-1];
    pBA = Tcl_GetByteArrayFromObj(pValue, &len);
    pData = sqlite3_malloc64( len );
    if( pData==0 && len>0 ){
      Tcl_AppendResult(interp, "out of memory", (char*)0);
      rc = TCL_ERROR;
    }else{
      int flags;
      if( len>0 ) memcpy(pData, pBA, len);
      xrc = sqlite3_deserialize(pDb->db, zSchema, pData, len, len,
                SQLITE_DESERIALIZE_FREEONCLOSE |
                SQLITE_DESERIALIZE_RESIZEABLE);
      if( isReadonly ){
        flags = SQLITE_DESERIALIZE_FREEONCLOSE | SQLITE_DESERIALIZE_READONLY;
      }else{
        flags = SQLITE_DESERIALIZE_FREEONCLOSE | SQLITE_DESERIALIZE_RESIZEABLE;
      }
      xrc = sqlite3_deserialize(pDb->db, zSchema, pData, len, len, flags);
      if( xrc ){
        Tcl_AppendResult(interp, "unable to set MEMDB content", (char*)0);
        rc = TCL_ERROR;
      }
      if( mxSize>0 ){
        sqlite3_file_control(pDb->db, zSchema,SQLITE_FCNTL_SIZE_LIMIT,&mxSize);
    }
      }
    }
deserialize_error:
#endif
    break; 
  }

  /*
  **    $db enable_load_extension BOOLEAN
  **
2495
2496
2497
2498
2499
2500
2501











2502
2503
2504
2505
2506
2507
2508
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







+
+
+
+
+
+
+
+
+
+
+







  ** Return the numeric error code that was returned by the most recent
  ** call to sqlite3_exec().
  */
  case DB_ERRORCODE: {
    Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_errcode(pDb->db)));
    break;
  }

  /*
  **    $db erroroffset
  **
  ** Return the numeric error code that was returned by the most recent
  ** call to sqlite3_exec().
  */
  case DB_ERROROFFSET: {
    Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_error_offset(pDb->db)));
    break;
  }

  /*
  **    $db exists $sql
  **    $db onecolumn $sql
  **
  ** The onecolumn method is the equivalent of:
  **     lindex [$db eval $sql] 0
2603
2604
2605
2606
2607
2608
2609
2610

2611
2612
2613







2614
2615
2616
2617
2618
2619
2620
2621

2622
2623
2624
2625
2626
2627
2628
2629

2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642

2643




















2644
2645
2646


2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661

2662
2663
2664
2665
2666
2667
2668
2845
2846
2847
2848
2849
2850
2851

2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878

2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891

2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915

2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940







-
+



+
+
+
+
+
+
+








+







-
+












-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+
+















+







      cd2[1] = (void *)pScript;
      rc = DbEvalNextCmd(cd2, interp, TCL_OK);
    }
    break;
  }

  /*
  **     $db function NAME [-argcount N] [-deterministic] SCRIPT
  **     $db function NAME [OPTIONS] SCRIPT
  **
  ** Create a new SQL function called NAME.  Whenever that function is
  ** called, invoke SCRIPT to evaluate the function.
  **
  ** Options:
  **         --argcount N           Function has exactly N arguments
  **         --deterministic        The function is pure
  **         --directonly           Prohibit use inside triggers and views
  **         --innocuous            Has no side effects or information leaks
  **         --returntype TYPE      Specify the return type of the function
  */
  case DB_FUNCTION: {
    int flags = SQLITE_UTF8;
    SqlFunc *pFunc;
    Tcl_Obj *pScript;
    char *zName;
    int nArg = -1;
    int i;
    int eType = SQLITE_NULL;
    if( objc<4 ){
      Tcl_WrongNumArgs(interp, 2, objv, "NAME ?SWITCHES? SCRIPT");
      return TCL_ERROR;
    }
    for(i=3; i<(objc-1); i++){
      const char *z = Tcl_GetString(objv[i]);
      int n = strlen30(z);
      if( n>2 && strncmp(z, "-argcount",n)==0 ){
      if( n>1 && strncmp(z, "-argcount",n)==0 ){
        if( i==(objc-2) ){
          Tcl_AppendResult(interp, "option requires an argument: ", z,(char*)0);
          return TCL_ERROR;
        }
        if( Tcl_GetIntFromObj(interp, objv[i+1], &nArg) ) return TCL_ERROR;
        if( nArg<0 ){
          Tcl_AppendResult(interp, "number of arguments must be non-negative",
                           (char*)0);
          return TCL_ERROR;
        }
        i++;
      }else
      if( n>2 && strncmp(z, "-deterministic",n)==0 ){
      if( n>1 && strncmp(z, "-deterministic",n)==0 ){
        flags |= SQLITE_DETERMINISTIC;
      }else
      if( n>1 && strncmp(z, "-directonly",n)==0 ){
        flags |= SQLITE_DIRECTONLY;
      }else
      if( n>1 && strncmp(z, "-innocuous",n)==0 ){
        flags |= SQLITE_INNOCUOUS;
      }else
      if( n>1 && strncmp(z, "-returntype", n)==0 ){
        const char *azType[] = {"integer", "real", "text", "blob", "any", 0};
        assert( SQLITE_INTEGER==1 && SQLITE_FLOAT==2 && SQLITE_TEXT==3 );
        assert( SQLITE_BLOB==4 && SQLITE_NULL==5 );
        if( i==(objc-2) ){
          Tcl_AppendResult(interp, "option requires an argument: ", z,(char*)0);
          return TCL_ERROR;
        }
        i++;
        if( Tcl_GetIndexFromObj(interp, objv[i], azType, "type", 0, &eType) ){
          return TCL_ERROR;
        }
        eType++;
      }else{
        Tcl_AppendResult(interp, "bad option \"", z,
            "\": must be -argcount or -deterministic", (char*)0
            "\": must be -argcount, -deterministic, -directonly,"
            " -innocuous, or -returntype", (char*)0
        );
        return TCL_ERROR;
      }
    }

    pScript = objv[objc-1];
    zName = Tcl_GetStringFromObj(objv[2], 0);
    pFunc = findSqlFunc(pDb, zName);
    if( pFunc==0 ) return TCL_ERROR;
    if( pFunc->pScript ){
      Tcl_DecrRefCount(pFunc->pScript);
    }
    pFunc->pScript = pScript;
    Tcl_IncrRefCount(pScript);
    pFunc->useEvalObjv = safeToUseEvalObjv(interp, pScript);
    pFunc->eType = eType;
    rc = sqlite3_create_function(pDb->db, zName, nArg, flags,
        pFunc, tclSqlFunc, 0, 0);
    if( rc!=SQLITE_OK ){
      rc = TCL_ERROR;
      Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE);
    }
    break;
2689
2690
2691
2692
2693
2694
2695
2696

2697
2698
2699
2700
2701
2702
2703
2961
2962
2963
2964
2965
2966
2967

2968
2969
2970
2971
2972
2973
2974
2975







-
+








    if( objc!=(5+isReadonly) && objc!=(6+isReadonly) ){
      Tcl_WrongNumArgs(interp, 2, objv, "?-readonly? ?DB? TABLE COLUMN ROWID");
      return TCL_ERROR;
    }

    if( objc==(6+isReadonly) ){
      zDb = Tcl_GetString(objv[2]);
      zDb = Tcl_GetString(objv[2+isReadonly]);
    }
    zTable = Tcl_GetString(objv[objc-3]);
    zColumn = Tcl_GetString(objv[objc-2]);
    rc = Tcl_GetWideIntFromObj(interp, objv[objc-1], &iRow);

    if( rc==TCL_OK ){
      rc = createIncrblobChannel(
2778
2779
2780
2781
2782
2783
2784



2785
2786
2787
2788
2789
2790
2791
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066







+
+
+







  ** queries.
  */
  case DB_PROGRESS: {
    if( objc==2 ){
      if( pDb->zProgress ){
        Tcl_AppendResult(interp, pDb->zProgress, (char*)0);
      }
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
      sqlite3_progress_handler(pDb->db, 0, 0, 0);
#endif
    }else if( objc==4 ){
      char *zProgress;
      int len;
      int N;
      if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &N) ){
        return TCL_ERROR;
      };
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
3131
3132
3133
3134
3135
3136
3137




3138
3139
3140
3141








3142
3143
3144
3145
3146
3147
3148







-
-
-
-




-
-
-
-
-
-
-
-








  /*
  **     $db rekey KEY
  **
  ** Change the encryption key on the currently open database.
  */
  case DB_REKEY: {
#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
    int nKey;
    void *pKey;
#endif
    if( objc!=3 ){
      Tcl_WrongNumArgs(interp, 2, objv, "KEY");
      return TCL_ERROR;
    }
#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
    pKey = Tcl_GetByteArrayFromObj(objv[2], &nKey);
    rc = sqlite3_rekey(pDb->db, pKey, nKey);
    if( rc ){
      Tcl_AppendResult(interp, sqlite3_errstr(rc), (char*)0);
      rc = TCL_ERROR;
    }
#endif
    break;
  }

  /*    $db restore ?DATABASE? FILENAME
  **
  ** Open a database file named FILENAME.  Transfer the content
  ** of FILENAME into the local database DATABASE (default: "main").
2941
2942
2943
2944
2945
2946
2947
2948

2949
2950
2951
2952
2953
2954
2955
3204
3205
3206
3207
3208
3209
3210

3211
3212
3213
3214
3215
3216
3217
3218







-
+








  /*
  **     $db serialize ?DATABASE?
  **
  ** Return a serialization of a database.  
  */
  case DB_SERIALIZE: {
#ifndef SQLITE_ENABLE_DESERIALIZE
#ifdef SQLITE_OMIT_DESERIALIZE
    Tcl_AppendResult(interp, "MEMDB not available in this build",
                     (char*)0);
    rc = TCL_ERROR;
#else
    const char *zSchema = objc>=3 ? Tcl_GetString(objv[2]) : "main";
    sqlite3_int64 sz = 0;
    unsigned char *pData;
3029
3030
3031
3032
3033
3034
3035
3036

3037
3038
3039
3040
3041
3042
3043
3292
3293
3294
3295
3296
3297
3298

3299
3300
3301
3302
3303
3304
3305
3306







-
+







  case DB_TOTAL_CHANGES: {
    Tcl_Obj *pResult;
    if( objc!=2 ){
      Tcl_WrongNumArgs(interp, 2, objv, "");
      return TCL_ERROR;
    }
    pResult = Tcl_GetObjResult(interp);
    Tcl_SetIntObj(pResult, sqlite3_total_changes(pDb->db));
    Tcl_SetWideIntObj(pResult, sqlite3_total_changes64(pDb->db));
    break;
  }

  /*    $db trace ?CALLBACK?
  **
  ** Make arrangements to invoke the CALLBACK routine for each SQL statement
  ** that is executed.  The text of the SQL is appended to CALLBACK before
3209
3210
3211
3212
3213
3214
3215

3216
3217
3218
3219
3220
3221
3222
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486







+







    pDb->nTransaction++;

    /* If using NRE, schedule a callback to invoke the script pScript, then
    ** a second callback to commit (or rollback) the transaction or savepoint
    ** opened above. If not using NRE, evaluate the script directly, then
    ** call function DbTransPostCmd() to commit (or rollback) the transaction
    ** or savepoint.  */
    addDatabaseRef(pDb);          /* DbTransPostCmd() calls delDatabaseRef() */
    if( DbUseNre() ){
      Tcl_NRAddCallback(interp, DbTransPostCmd, cd, 0, 0, 0);
      (void)Tcl_NREvalObj(interp, pScript, 0);
    }else{
      rc = DbTransPostCmd(&cd, interp, Tcl_EvalObjEx(interp, pScript, 0));
    }
    break;
3438
3439
3440
3441
3442
3443
3444

3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455

3456
3457
3458
3459
3460
3461
3462
3702
3703
3704
3705
3706
3707
3708
3709
3710



3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725







+

-
-
-







+







*/
static int sqliteCmdUsage(
  Tcl_Interp *interp,
  Tcl_Obj *const*objv
){
  Tcl_WrongNumArgs(interp, 1, objv,
    "HANDLE ?FILENAME? ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN?"
    " ?-nofollow BOOLEAN?"
    " ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?"
#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
    " ?-key CODECKEY?"
#endif
  );
  return TCL_ERROR;
}

/*
**   sqlite3 DBNAME FILENAME ?-vfs VFSNAME? ?-key KEY? ?-readonly BOOLEAN?
**                           ?-create BOOLEAN? ?-nomutex BOOLEAN?
**                           ?-nofollow BOOLEAN?
**
** This is the main Tcl command.  When the "sqlite" Tcl command is
** invoked, this routine runs to process that command.
**
** The first argument, DBNAME, is an arbitrary name for a new
** database connection.  This command creates a new command named
** DBNAME that is used to control that connection.  The database
3474
3475
3476
3477
3478
3479
3480

3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3737
3738
3739
3740
3741
3742
3743
3744
3745




3746
3747
3748
3749
3750
3751
3752







+

-
-
-
-







  SqliteDb *p;
  const char *zArg;
  char *zErrMsg;
  int i;
  const char *zFile = 0;
  const char *zVfs = 0;
  int flags;
  int bTranslateFileName = 1;
  Tcl_DString translatedFilename;
#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
  void *pKey = 0;
  int nKey = 0;
#endif
  int rc;

  /* In normal use, each TCL interpreter runs in a single thread.  So
  ** by default, we can turn off mutexing on SQLite database connections.
  ** However, for testing purposes it is useful to have mutexes turned
  ** on.  So, by default, mutexes default off.  But if compiled with
  ** SQLITE_TCL_DEFAULT_FULLMUTEX then mutexes default on.
3505
3506
3507
3508
3509
3510
3511
3512
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
3765
3766
3767
3768
3769
3770
3771



3772

3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786



3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821







-
-
-

-














-
-
-
+



















+
+
+
+
+
+
+
+







      return TCL_OK;
    }
    if( strcmp(zArg,"-sourceid")==0 ){
      Tcl_AppendResult(interp,sqlite3_sourceid(), (char*)0);
      return TCL_OK;
    }
    if( strcmp(zArg,"-has-codec")==0 ){
#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
      Tcl_AppendResult(interp,"1",(char*)0);
#else
      Tcl_AppendResult(interp,"0",(char*)0);
#endif
      return TCL_OK;
    }
    if( zArg[0]=='-' ) return sqliteCmdUsage(interp, objv);
  }
  for(i=2; i<objc; i++){
    zArg = Tcl_GetString(objv[i]);
    if( zArg[0]!='-' ){
      if( zFile!=0 ) return sqliteCmdUsage(interp, objv);
      zFile = zArg;
      continue;
    }
    if( i==objc-1 ) return sqliteCmdUsage(interp, objv);
    i++;
    if( strcmp(zArg,"-key")==0 ){
#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
      pKey = Tcl_GetByteArrayFromObj(objv[i], &nKey);
#endif
      /* no-op */
    }else if( strcmp(zArg, "-vfs")==0 ){
      zVfs = Tcl_GetString(objv[i]);
    }else if( strcmp(zArg, "-readonly")==0 ){
      int b;
      if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR;
      if( b ){
        flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
        flags |= SQLITE_OPEN_READONLY;
      }else{
        flags &= ~SQLITE_OPEN_READONLY;
        flags |= SQLITE_OPEN_READWRITE;
      }
    }else if( strcmp(zArg, "-create")==0 ){
      int b;
      if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR;
      if( b && (flags & SQLITE_OPEN_READONLY)==0 ){
        flags |= SQLITE_OPEN_CREATE;
      }else{
        flags &= ~SQLITE_OPEN_CREATE;
      }
    }else if( strcmp(zArg, "-nofollow")==0 ){
      int b;
      if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR;
      if( b ){
        flags |= SQLITE_OPEN_NOFOLLOW;
      }else{
        flags &= ~SQLITE_OPEN_NOFOLLOW;
      }
    }else if( strcmp(zArg, "-nomutex")==0 ){
      int b;
      if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR;
      if( b ){
        flags |= SQLITE_OPEN_NOMUTEX;
        flags &= ~SQLITE_OPEN_FULLMUTEX;
3573
3574
3575
3576
3577
3578
3579




3580
3581
3582
3583
3584
3585
3586
3587
3588

3589


3590

3591


3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621

3622
3623
3624
3625
3626
3627
3628
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
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







+
+
+
+









+
-
+
+

+
-
+
+









-
-
-
-
-
















+







      int b;
      if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR;
      if( b ){
        flags |= SQLITE_OPEN_URI;
      }else{
        flags &= ~SQLITE_OPEN_URI;
      }
    }else if( strcmp(zArg, "-translatefilename")==0 ){
      if( Tcl_GetBooleanFromObj(interp, objv[i], &bTranslateFileName) ){
        return TCL_ERROR;
      }
    }else{
      Tcl_AppendResult(interp, "unknown option: ", zArg, (char*)0);
      return TCL_ERROR;
    }
  }
  zErrMsg = 0;
  p = (SqliteDb*)Tcl_Alloc( sizeof(*p) );
  memset(p, 0, sizeof(*p));
  if( zFile==0 ) zFile = "";
  if( bTranslateFileName ){
  zFile = Tcl_TranslateFileName(interp, zFile, &translatedFilename);
    zFile = Tcl_TranslateFileName(interp, zFile, &translatedFilename);
  }
  rc = sqlite3_open_v2(zFile, &p->db, flags, zVfs);
  if( bTranslateFileName ){
  Tcl_DStringFree(&translatedFilename);
    Tcl_DStringFree(&translatedFilename);
  }
  if( p->db ){
    if( SQLITE_OK!=sqlite3_errcode(p->db) ){
      zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(p->db));
      sqlite3_close(p->db);
      p->db = 0;
    }
  }else{
    zErrMsg = sqlite3_mprintf("%s", sqlite3_errstr(rc));
  }
#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
  if( p->db ){
    sqlite3_key(p->db, pKey, nKey);
  }
#endif
  if( p->db==0 ){
    Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE);
    Tcl_Free((char*)p);
    sqlite3_free(zErrMsg);
    return TCL_ERROR;
  }
  p->maxStmt = NUM_PREPARED_STMTS;
  p->openFlags = flags & SQLITE_OPEN_URI;
  p->interp = interp;
  zArg = Tcl_GetStringFromObj(objv[1], 0);
  if( DbUseNre() ){
    Tcl_NRCreateCommand(interp, zArg, DbObjCmdAdaptor, DbObjCmd,
                        (char*)p, DbDeleteCmd);
  }else{
    Tcl_CreateObjCommand(interp, zArg, DbObjCmd, (char*)p, DbDeleteCmd);
  }
  p->nRef = 1;
  return TCL_OK;
}

/*
** Provide a dummy Tcl_InitStubs if we are using this as a static
** library.
*/
3722
3723
3724
3725
3726
3727
3728

3729


3730
3731
3732
3733
3734
3735
3736
3988
3989
3990
3991
3992
3993
3994
3995

3996
3997
3998
3999
4000
4001
4002
4003
4004







+
-
+
+







        "}\n"
      "}\n"
    "}\n"
  ;
  return zMainloop;
}

#ifndef TCLSH_MAIN
#define TCLSH_MAIN main   /* Needed to fake out mktclapp */
# define TCLSH_MAIN main
#endif
int SQLITE_CDECL TCLSH_MAIN(int argc, char **argv){
  Tcl_Interp *interp;
  int i;
  const char *zScript = 0;
  char zArgc[32];
#if defined(TCLSH_INIT_PROC)
  extern const char *TCLSH_INIT_PROC(Tcl_Interp*);

Changes to src/test1.c.

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
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







-
-
-
-
-
-
-
-
-
-
-
-
-
-














-
-
-
-
-
-
-
-
-
-
-
-
-
-







*/
static int SQLITE_TCLAPI test_key(
  void *NotUsed,
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int argc,              /* Number of arguments */
  char **argv            /* Text of each argument */
){
#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
  sqlite3 *db;
  const char *zKey;
  int nKey;
  if( argc!=3 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
       " FILENAME\"", 0);
    return TCL_ERROR;
  }
  if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
  zKey = argv[2];
  nKey = strlen(zKey);
  sqlite3_key(db, zKey, nKey);
#endif
  return TCL_OK;
}

/*
** Usage:  sqlite3_rekey DB KEY
**
** Change the codec key.
*/
static int SQLITE_TCLAPI test_rekey(
  void *NotUsed,
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int argc,              /* Number of arguments */
  char **argv            /* Text of each argument */
){
#ifdef SQLITE_HAS_CODEC
  sqlite3 *db;
  const char *zKey;
  int nKey;
  if( argc!=3 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
       " FILENAME\"", 0);
    return TCL_ERROR;
  }
  if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
  zKey = argv[2];
  nKey = strlen(zKey);
  sqlite3_rekey(db, zKey, nKey);
#endif
  return TCL_OK;
}

/*
** Usage:  sqlite3_close DB
**
** Closes the database opened by sqlite3_open.
993
994
995
996
997
998
999














1000
1001
1002
1003
1004
1005
1006
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992







+
+
+
+
+
+
+
+
+
+
+
+
+
+







  sqlite3_context *context, 
  int argc,  
  sqlite3_value **argv
){
  static int cnt = 0;
  sqlite3_result_int(context, cnt++);
}

/*
** This SQL function returns the integer value of its argument as a MEM_IntReal
** value.
*/
static void intrealFunction(
  sqlite3_context *context, 
  int argc,  
  sqlite3_value **argv
){
  sqlite3_int64 v = sqlite3_value_int64(argv[0]);
  sqlite3_result_int64(context, v);
  sqlite3_test_control(SQLITE_TESTCTRL_RESULT_INTREAL, context);
}

/*
** Usage:  sqlite3_create_function DB
**
** Call the sqlite3_create_function API on the given database in order
** to create a function named "x_coalesce".  This function does the same thing
** as the "coalesce" function.  This function also registers an SQL function
1057
1058
1059
1060
1061
1062
1063








1064
1065
1066
1067
1068
1069
1070
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064







+
+
+
+
+
+
+
+







    rc = sqlite3_create_function(db, "counter1", -1, SQLITE_UTF8,
          0, nondeterministicFunction, 0, 0);
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "counter2", -1, SQLITE_UTF8|SQLITE_DETERMINISTIC,
          0, nondeterministicFunction, 0, 0);
  }

  /* The intreal() function converts its argument to an integer and returns
  ** it as a MEM_IntReal.
  */
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "intreal", 1, SQLITE_UTF8,
          0, intrealFunction, 0, 0);
  }

#ifndef SQLITE_OMIT_UTF16
  /* Use the sqlite3_create_function16() API here. Mainly for fun, but also 
  ** because it is not tested anywhere else. */
  if( rc==SQLITE_OK ){
    const void *zUtf16;
    sqlite3_value *pVal;
1083
1084
1085
1086
1087
1088
1089



























1090
1091
1092
1093
1094
1095
1096
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  }
#endif

  if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
  Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
  return TCL_OK;
}

/*
** Usage:  sqlite3_drop_modules DB ?NAME ...?
**
** Invoke the sqlite3_drop_modules(D,L) interface on database
** connection DB, in order to drop all modules except those named in
** the argument.
*/
static int SQLITE_TCLAPI test_drop_modules(
  void *NotUsed,
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int argc,              /* Number of arguments */
  char **argv            /* Text of each argument */
){
  sqlite3 *db;

  if( argc<2 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
       " DB\"", 0);
    return TCL_ERROR;
  }
  if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
#ifndef SQLITE_OMIT_VIRTUALTABLE
  sqlite3_drop_modules(db, argc>2 ? (const char**)(argv+2) : 0);
#endif
  return TCL_OK;
}

/*
** Routines to implement the x_count() aggregate function.
**
** x_count() counts the number of non-null arguments.  But there are
** some twists for testing purposes.
**
1827
1828
1829
1830
1831
1832
1833
1834


1835
1836
1837
1838
1839
1840
1841
1848
1849
1850
1851
1852
1853
1854

1855
1856
1857
1858
1859
1860
1861
1862
1863







-
+
+







    int enc;
  } aEnc[] = {
    {"utf8",    SQLITE_UTF8 },
    {"utf16",   SQLITE_UTF16 },
    {"utf16le", SQLITE_UTF16LE },
    {"utf16be", SQLITE_UTF16BE },
    {"any",     SQLITE_ANY },
    {"0", 0 }
    {"0", 0 },
    {0, 0 }
  };

  if( objc<5 || (objc%2)==0 ){
    Tcl_WrongNumArgs(interp, 1, objv, "DB NAME NARG ENC SWITCHES...");
    return TCL_ERROR;
  }

2162
2163
2164
2165
2166
2167
2168
2169

2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183

2184
2185



2186


























2187
2188


2189
2190
2191
2192
2193
2194
2195







2196














2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213


































2214
2215
2216
2217
2218
2219
2220
2184
2185
2186
2187
2188
2189
2190

2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
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
2234
2235
2236
2237
2238


2239
2240
2241
2242





2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264

















2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305







-
+














+


+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+


-
-
-
-
-
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  iValue = sqlite3_stmt_status(pStmt, op, resetFlag);
  Tcl_SetObjResult(interp, Tcl_NewIntObj(iValue));
  return TCL_OK;
}

#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
/*
** Usage:  sqlite3_stmt_scanstatus STMT IDX
** Usage:  sqlite3_stmt_scanstatus ?-flags FLAGS? STMT IDX
*/
static int SQLITE_TCLAPI test_stmt_scanstatus(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  sqlite3_stmt *pStmt;            /* First argument */
  int idx;                        /* Second argument */

  const char *zName;
  const char *zExplain;
  sqlite3_int64 nLoop;
  sqlite3_int64 nVisit;
  sqlite3_int64 nCycle;
  double rEst;
  int res;
  int flags = 0;
  int iSelectId = 0;
  int iParentId = 0;

  if( objc==5 ){
    struct Flag {
      const char *zFlag;
      int flag;
    } aTbl[] = {
      {"complex", SQLITE_SCANSTAT_COMPLEX},
      {0, 0}
    };

    Tcl_Obj **aFlag = 0;
    int nFlag = 0;
    int ii;

    if( Tcl_ListObjGetElements(interp, objv[2], &nFlag, &aFlag) ){
      return TCL_ERROR;
    }
    for(ii=0; ii<nFlag; ii++){
      int iVal = 0;
      int res = Tcl_GetIndexFromObjStruct(
          interp, aFlag[ii], aTbl, sizeof(aTbl[0]), "flag", 0, &iVal
      );
      if( res ) return TCL_ERROR;
      flags |= aTbl[iVal].flag;
    }
  }

  if( objc!=3 ){
    Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX");
  if( objc!=3 && objc!=5 ){
    Tcl_WrongNumArgs(interp, 1, objv, "-flags FLAGS STMT IDX");
    return TCL_ERROR;
  }
  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;

  res = sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop);
  if( res==0 ){
  if( getStmtPointer(interp, Tcl_GetString(objv[objc-2]), &pStmt) 
   || Tcl_GetIntFromObj(interp, objv[objc-1], &idx)
  ){
    return TCL_ERROR;
  }

  if( idx<0 ){
    Tcl_Obj *pRet = Tcl_NewObj();
    res = sqlite3_stmt_scanstatus_v2(
        pStmt, -1, SQLITE_SCANSTAT_NCYCLE, flags, (void*)&nCycle
    );
    sqlite3_stmt_scanstatus_v2(
        pStmt, idx, SQLITE_SCANSTAT_NCYCLE, flags, (void*)&nCycle);
    Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nCycle", -1));
    Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nCycle));
    Tcl_SetObjResult(interp, pRet);
  }else{
    res = sqlite3_stmt_scanstatus_v2(
        pStmt, idx, SQLITE_SCANSTAT_NLOOP, flags, (void*)&nLoop
    );
    if( res==0 ){
      Tcl_Obj *pRet = Tcl_NewObj();
    Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nLoop", -1));
    Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nLoop));
    sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
    Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nVisit", -1));
    Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nVisit));
    sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_EST, (void*)&rEst);
    Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nEst", -1));
    Tcl_ListObjAppendElement(0, pRet, Tcl_NewDoubleObj(rEst));
    sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NAME, (void*)&zName);
    Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("zName", -1));
    Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zName, -1));
    sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
    Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("zExplain", -1));
    Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zExplain, -1));
    Tcl_SetObjResult(interp, pRet);
  }else{
    Tcl_ResetResult(interp);
      Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nLoop", -1));
      Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nLoop));
      sqlite3_stmt_scanstatus_v2(
          pStmt, idx, SQLITE_SCANSTAT_NVISIT, flags, (void*)&nVisit);
      Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nVisit", -1));
      Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nVisit));
      sqlite3_stmt_scanstatus_v2(
          pStmt, idx, SQLITE_SCANSTAT_EST, flags, (void*)&rEst);
      Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nEst", -1));
      Tcl_ListObjAppendElement(0, pRet, Tcl_NewDoubleObj(rEst));
      sqlite3_stmt_scanstatus_v2(
          pStmt, idx, SQLITE_SCANSTAT_NAME, flags, (void*)&zName);
      Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("zName", -1));
      Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zName, -1));
      sqlite3_stmt_scanstatus_v2(
          pStmt, idx, SQLITE_SCANSTAT_EXPLAIN, flags, (void*)&zExplain);
      Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("zExplain", -1));
      Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zExplain, -1));
      sqlite3_stmt_scanstatus_v2(
          pStmt, idx, SQLITE_SCANSTAT_SELECTID, flags, (void*)&iSelectId);
      Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("iSelectId", -1));
      Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(iSelectId));
      sqlite3_stmt_scanstatus_v2(
          pStmt, idx, SQLITE_SCANSTAT_PARENTID, flags, (void*)&iParentId);
      Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("iParentId", -1));
      Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(iParentId));
      sqlite3_stmt_scanstatus_v2(
          pStmt, idx, SQLITE_SCANSTAT_NCYCLE, flags, (void*)&nCycle);
      Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nCycle", -1));
      Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nCycle));
      Tcl_SetObjResult(interp, pRet);
    }else{
      Tcl_ResetResult(interp);
    }
  }
  return TCL_OK;
}

/*
** Usage:  sqlite3_stmt_scanstatus_reset  STMT
*/
2669
2670
2671
2672
2673
2674
2675



























2676
2677
2678
2679
2680
2681
2682
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  }

  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  rc = sqlite3_stmt_readonly(pStmt);
  Tcl_SetObjResult(interp, Tcl_NewBooleanObj(rc));
  return TCL_OK;
}

/*
** Usage:  sqlite3_stmt_isexplain  STMT
**
** Return 1, 2, or 0 respectively if STMT is an EXPLAIN statement, an
** EXPLAIN QUERY PLAN statement or an ordinary statement or NULL pointer.
*/
static int SQLITE_TCLAPI test_stmt_isexplain(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  sqlite3_stmt *pStmt;
  int rc;

  if( objc!=2 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"",
        Tcl_GetStringFromObj(objv[0], 0), " STMT", 0);
    return TCL_ERROR;
  }

  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  rc = sqlite3_stmt_isexplain(pStmt);
  Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
  return TCL_OK;
}

/*
** Usage:  sqlite3_stmt_busy  STMT
**
** Return true if STMT is a non-NULL pointer to a statement
** that has been stepped but not to completion.
*/
3773
3774
3775
3776
3777
3778
3779

3780
3781
3782

3783
3784
3785
3786
3787
3788
3789
3790
3791
3792

3793





3794





3795

3796
3797
3798

3799
3800
3801
3802
3803
3804
3805
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
3923
3924
3925
3926
3927
3928
3929







+



+









-
+

+
+
+
+
+
-
+
+
+
+
+

+


-
+







  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;
}

/*
3817
3818
3819
3820
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
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
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







+

+















-
+

+
+
+
+
+
-
+
+
+
+
+

+







  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 */
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
4024
4025
4026
4027
4028
4029
4030

4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
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
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
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
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377







-
+












+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  value = (char*)Tcl_GetByteArrayFromObj(objv[3], &len);
  if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;

  if( bytes>len ){
    char zBuf[200];
    sqlite3_snprintf(sizeof(zBuf), zBuf,
                     "cannot use %d blob bytes, have %d", bytes, len);
    Tcl_AppendResult(interp, zBuf, -1);
    Tcl_AppendResult(interp, zBuf, (char*)0);
    return TCL_ERROR;
  }

  rc = sqlite3_bind_blob(pStmt, idx, value, bytes, xDestructor);
  if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
  if( rc!=SQLITE_OK ){
    return TCL_ERROR;
  }

  return TCL_OK;
}

/*
** Usage:   sqlite3_bind_value_from_preupdate STMT N NEW|OLD IDX
**
** Test the sqlite3_bind_value interface using sqlite3_value objects
** obtained from either sqlite3_preupdate_new() (if arg[3]=="new") or
** sqlite3_preupdate_old() if (arg[3]=="old"). IDX is the index to
** pass to the sqlite3_preupdate_xxx() function.
*/
static int SQLITE_TCLAPI test_bind_value_from_preupdate(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  sqlite3_stmt *pStmt;
  int idx;
  int bidx;
  const char *z3 = 0;
  sqlite3 *db = 0;
  sqlite3_value *pVal = 0;

  if( objc!=5 ){
    Tcl_WrongNumArgs(interp, 1, objv, "STMT N NEW|OLD IDX");
    return TCL_ERROR;
  }

  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
  z3 = Tcl_GetString(objv[3]);
  if( Tcl_GetIntFromObj(interp, objv[4], &bidx) ) return TCL_ERROR;
  db = sqlite3_db_handle(pStmt);

#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
  if( z3[0]=='n' ){
    sqlite3_preupdate_new(db, bidx, &pVal);
  }else if( z3[0]=='o' ){
    sqlite3_preupdate_old(db, bidx, &pVal);
  }else{
    Tcl_AppendResult(interp, "expected new or old, got: ", z3, (char*)0);
    return TCL_ERROR;
  }
  sqlite3_bind_value(pStmt, idx, pVal);
#endif

  return TCL_OK;
}

/*
** Usage:   sqlite3_bind_value_from_select STMT N SELECT
**
** Test the sqlite3_bind_value interface.  STMT is a prepared statement.
** N is the index of a wildcard in the prepared statement. 
*/
static int SQLITE_TCLAPI test_bind_value_from_select(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  sqlite3_stmt *pStmt;
  sqlite3_stmt *pStmt2;
  int idx;
  const char *zSql = 0;
  sqlite3 *db = 0;
  int rc = SQLITE_OK;

  if( objc!=4 ){
    Tcl_WrongNumArgs(interp, 1, objv, "STMT N SELECT");
    return TCL_ERROR;
  }

  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
  zSql = Tcl_GetString(objv[3]);
  db = sqlite3_db_handle(pStmt);

  rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt2, 0);
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, "error in SQL: ", sqlite3_errmsg(db), (char*)0);
    return TCL_ERROR;
  }
  if( sqlite3_step(pStmt2)==SQLITE_ROW ){
    sqlite3_value *pVal = sqlite3_column_value(pStmt2, 0);
    sqlite3_bind_value(pStmt, idx, pVal);
  }
  rc = sqlite3_finalize(pStmt2);
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, 
        "error runnning SQL: ", sqlite3_errmsg(db), (char*)0
    );
    return TCL_ERROR;
  }

  return TCL_OK;
}

#ifdef _WIN32
  struct iovec {
    void *iov_base;
    size_t iov_len;
  };
#else
# include <sys/uio.h>
#endif

#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** sqlite3_carray_bind [options...] STMT NAME VALUE ...
**
** Options:
**    -transient
**    -static
**    -int32
**    -int64
**    -double
**    -text
**    -blob
**
** Each call clears static data.  Called with no options does nothing
** but clear static data.
*/
static int SQLITE_TCLAPI test_carray_bind(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  sqlite3_stmt *pStmt;
  int eType = 0;   /* CARRAY_INT32 */
  int nData = 0;
  void *aData = 0;
  int isTransient = 0;
  int isStatic = 0;
  int idx;
  int i, j;
  int rc;
  void (*xDel)(void*) = sqlite3_free;
  static void *aStaticData = 0;
  static int nStaticData = 0;
  static int eStaticType = 0;
  extern int sqlite3_carray_bind(
    sqlite3_stmt *pStmt,
    int i,
    void *aData,
    int nData,
    int mFlags,
    void (*xDestroy)(void*)
  );
  
  if( aStaticData ){
    /* Always clear preexisting static data on every call */
    if( eStaticType==3 ){
      for(i=0; i<nStaticData; i++){
        sqlite3_free(((char**)aStaticData)[i]);
      }
    }
    if( eStaticType==4 ){
      for(i=0; i<nStaticData; i++){
        sqlite3_free(((struct iovec*)aStaticData)[i].iov_base);
      }
    } 
    sqlite3_free(aStaticData);
    aStaticData = 0;
    nStaticData = 0;
    eStaticType = 0;
  }
  if( objc==1 ) return TCL_OK;

  for(i=1; i<objc && Tcl_GetString(objv[i])[0]=='-'; i++){
    const char *z = Tcl_GetString(objv[i]);
    if( strcmp(z, "-transient")==0 ){
      isTransient = 1;
      xDel = SQLITE_TRANSIENT;
    }else
    if( strcmp(z, "-static")==0 ){
      isStatic = 1;
      xDel = SQLITE_STATIC;
    }else
    if( strcmp(z, "-int32")==0 ){
      eType = 0;  /* CARRAY_INT32 */
    }else
    if( strcmp(z, "-int64")==0 ){
      eType = 1;  /* CARRAY_INT64 */
    }else
    if( strcmp(z, "-double")==0 ){
      eType = 2;  /* CARRAY_DOUBLE */
    }else
    if( strcmp(z, "-text")==0 ){
      eType = 3;  /* CARRAY_TEXT */
    }else
    if( strcmp(z, "-blob")==0 ){
      eType = 4;  /* CARRAY_BLOB */
    }else
    if( strcmp(z, "--")==0 ){
      break;
    }else
    {
      Tcl_AppendResult(interp, "unknown option: ", z, (char*)0);
      return TCL_ERROR;
    }
  }
  if( eType==3 && !isStatic && !isTransient ){
    Tcl_AppendResult(interp, "text data must be either -static or -transient",
                     (char*)0);
    return TCL_ERROR;
  }
  if( eType==4 && !isStatic && !isTransient ){
    Tcl_AppendResult(interp, "blob data must be either -static or -transient",
                     (char*)0);
    return TCL_ERROR;
  }
  if( isStatic && isTransient ){
    Tcl_AppendResult(interp, "cannot be both -static and -transient",
                     (char*)0);
    return TCL_ERROR;
  }
  if( objc-i < 2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "[OPTIONS] STMT IDX VALUE ...");
    return TCL_ERROR;
  }
  if( getStmtPointer(interp, Tcl_GetString(objv[i]), &pStmt) ) return TCL_ERROR;
  i++;
  if( Tcl_GetIntFromObj(interp, objv[i], &idx) ) return TCL_ERROR;
  i++;
  nData = objc - i;
  switch( eType + 5*(nData<=0) ){
    case 0: { /* INT32 */
      int *a = sqlite3_malloc( sizeof(int)*nData );
      if( a==0 ){ rc = SQLITE_NOMEM; goto carray_bind_done; }
      for(j=0; j<nData; j++){
        int v;
        if( Tcl_GetIntFromObj(interp, objv[i+j], &v) ){
          sqlite3_free(a);
          return TCL_ERROR;
        }
        a[j] = v;
      }
      aData = a;
      break;
    }
    case 1: { /* INT64 */
      sqlite3_int64 *a = sqlite3_malloc( sizeof(sqlite3_int64)*nData );
      if( a==0 ){ rc = SQLITE_NOMEM; goto carray_bind_done; }
      for(j=0; j<nData; j++){
        Tcl_WideInt v;
        if( Tcl_GetWideIntFromObj(interp, objv[i+j], &v) ){
          sqlite3_free(a);
          return TCL_ERROR;
        }
        a[j] = v;
      }
      aData = a;
      break;
    }
    case 2: { /* DOUBLE */
      double *a = sqlite3_malloc( sizeof(double)*nData );
      if( a==0 ){ rc = SQLITE_NOMEM; goto carray_bind_done; }
      for(j=0; j<nData; j++){
        double v;
        if( Tcl_GetDoubleFromObj(interp, objv[i+j], &v) ){
          sqlite3_free(a);
          return TCL_ERROR;
        }
        a[j] = v;
      }
      aData = a;
      break;
    }
    case 3: { /* TEXT */
      char **a = sqlite3_malloc( sizeof(char*)*nData );
      if( a==0 ){ rc = SQLITE_NOMEM; goto carray_bind_done; }
      for(j=0; j<nData; j++){
        const char *v = Tcl_GetString(objv[i+j]);
        a[j] = sqlite3_mprintf("%s", v);
      }
      aData = a;
      break;
    }
    case 4: { /* BLOB */
      struct iovec *a = sqlite3_malloc( sizeof(struct iovec)*nData );
      if( a==0 ){ rc = SQLITE_NOMEM; goto carray_bind_done; }
      for(j=0; j<nData; j++){
        int n = 0;
        unsigned char *v = Tcl_GetByteArrayFromObj(objv[i+i], &n);
        a[j].iov_len = n;
        a[j].iov_base = sqlite3_malloc64( n );
        if( a[j].iov_base==0 ){
          a[j].iov_len = 0;
        }else{
          memcpy(a[j].iov_base, v, n);
        }
      }
      aData = a;
      break;
    }
    case 5: { /* nData==0 */
      aData = "";
      xDel = SQLITE_STATIC;
      isTransient = 0;
      isStatic = 0;
      break;
    }
  }
  if( isStatic ){
    aStaticData = aData;
    nStaticData = nData;
    eStaticType = eType;
  }
  rc = sqlite3_carray_bind(pStmt, idx, aData, nData, eType, xDel);
  if( isTransient ){
    if( eType==3 ){
      for(i=0; i<nData; i++) sqlite3_free(((char**)aData)[i]);
    }
    if( eType==4 ){
      for(i=0; i<nData; i++) sqlite3_free(((struct iovec*)aData)[i].iov_base);
    }
    sqlite3_free(aData);
  }
carray_bind_done:
  if( rc ){
    Tcl_AppendResult(interp, sqlite3_errstr(rc), (char*)0);
    return TCL_ERROR;
  }
  return TCL_OK;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */

/*
** Usage:   sqlite3_bind_parameter_count  STMT
**
** Return the number of wildcards in the given statement.
*/
static int SQLITE_TCLAPI test_bind_parameter_count(
  void * clientData,
4101
4102
4103
4104
4105
4106
4107




























4108
4109
4110
4111
4112
4113
4114
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;

  zErr = sqlite3_errmsg(db);
  Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1));
  return TCL_OK;
}


/*
** Usage:   sqlite3_error_offset DB
**
** Return the byte offset into the input UTF8 SQL for the most recent
** error, or -1 of the error does not refer to a specific token.
*/
static int SQLITE_TCLAPI test_error_offset(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  sqlite3 *db;
  int iByteOffset;

  if( objc!=2 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"", 
       Tcl_GetString(objv[0]), " DB", 0);
    return TCL_ERROR;
  }
  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;

  iByteOffset = sqlite3_error_offset(db);
  Tcl_SetObjResult(interp, Tcl_NewIntObj(iByteOffset));
  return TCL_OK;
}

/*
** Usage:   test_errmsg16 DB
**
** Returns the UTF-16 representation of the error message string for the
** most recent sqlite3_* API call. This is a byte array object at the TCL 
** level, and it includes the 0x00 0x00 terminator bytes at the end of the
** UTF-16 string.
4241
4242
4243
4244
4245
4246
4247
4248
4249




4250
4251
4252
4253
4254

4255
4256
4257
4258
4259
4260
4261
4732
4733
4734
4735
4736
4737
4738


4739
4740
4741
4742
4743
4744
4745
4746

4747
4748
4749
4750
4751
4752
4753
4754







-
-
+
+
+
+




-
+







  }else{
    int n = (int)strlen(zSql) + 1;
    zCopy = malloc(n);
    memcpy(zCopy, zSql, n);
  }
  pzTail = objc>=5 ? &zTail : 0;
  rc = sqlite3_prepare_v2(db, zCopy, bytes, &pStmt, pzTail);
  free(zCopy);
  zTail = &zSql[(zTail - zCopy)];
  if( objc>=5 ){
    zTail = &zSql[(zTail - zCopy)];
  }
  free(zCopy);

  assert(rc==SQLITE_OK || pStmt==0);
  Tcl_ResetResult(interp);
  if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
  if( rc==SQLITE_OK && zTail && objc>=5 ){
  if( rc==SQLITE_OK && objc>=5 && zTail ){
    if( bytes>=0 ){
      bytes = bytes - (int)(zTail-zSql);
    }
    Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
  }
  if( rc!=SQLITE_OK ){
    assert( pStmt==0 );
4576
4577
4578
4579
4580
4581
4582
4583

4584
4585
4586
4587
4588
4589

4590
4591
4592
4593
4594
4595
4596
5069
5070
5071
5072
5073
5074
5075

5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090







-
+






+







      { "SQLITE_OPEN_AUTOPROXY", SQLITE_OPEN_AUTOPROXY },
      { "SQLITE_OPEN_MAIN_DB", SQLITE_OPEN_MAIN_DB },
      { "SQLITE_OPEN_TEMP_DB", SQLITE_OPEN_TEMP_DB },
      { "SQLITE_OPEN_TRANSIENT_DB", SQLITE_OPEN_TRANSIENT_DB },
      { "SQLITE_OPEN_MAIN_JOURNAL", SQLITE_OPEN_MAIN_JOURNAL },
      { "SQLITE_OPEN_TEMP_JOURNAL", SQLITE_OPEN_TEMP_JOURNAL },
      { "SQLITE_OPEN_SUBJOURNAL", SQLITE_OPEN_SUBJOURNAL },
      { "SQLITE_OPEN_MASTER_JOURNAL", SQLITE_OPEN_MASTER_JOURNAL },
      { "SQLITE_OPEN_SUPER_JOURNAL", SQLITE_OPEN_SUPER_JOURNAL },
      { "SQLITE_OPEN_NOMUTEX", SQLITE_OPEN_NOMUTEX },
      { "SQLITE_OPEN_FULLMUTEX", SQLITE_OPEN_FULLMUTEX },
      { "SQLITE_OPEN_SHAREDCACHE", SQLITE_OPEN_SHAREDCACHE },
      { "SQLITE_OPEN_PRIVATECACHE", SQLITE_OPEN_PRIVATECACHE },
      { "SQLITE_OPEN_WAL", SQLITE_OPEN_WAL },
      { "SQLITE_OPEN_URI", SQLITE_OPEN_URI },
      { "SQLITE_OPEN_EXRESCODE", SQLITE_OPEN_EXRESCODE },
      { 0, 0 }
    };
    rc = Tcl_GetIndexFromObjStruct(interp, apFlag[i], aFlag, sizeof(aFlag[0]), 
        "flag", 0, &iFlag
    );
    if( rc!=TCL_OK ) return rc;
    flags |= aFlag[iFlag].flag;
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139























5140
5141
5142
5143
5144
5145
5146
5575
5576
5577
5578
5579
5580
5581
































5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-




















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;

  Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col)));
  return TCL_OK;
}

/*
** Usage:  sqlite_set_magic  DB  MAGIC-NUMBER
**
** Set the db->magic value.  This is used to test error recovery logic.
*/
static int SQLITE_TCLAPI sqlite_set_magic(
  void * clientData,
  Tcl_Interp *interp,
  int argc,
  char **argv
){
  sqlite3 *db;
  if( argc!=3 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
         " DB MAGIC", 0);
    return TCL_ERROR;
  }
  if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
  if( strcmp(argv[2], "SQLITE_MAGIC_OPEN")==0 ){
    db->magic = SQLITE_MAGIC_OPEN;
  }else if( strcmp(argv[2], "SQLITE_MAGIC_CLOSED")==0 ){
    db->magic = SQLITE_MAGIC_CLOSED;
  }else if( strcmp(argv[2], "SQLITE_MAGIC_BUSY")==0 ){
    db->magic = SQLITE_MAGIC_BUSY;
  }else if( strcmp(argv[2], "SQLITE_MAGIC_ERROR")==0 ){
    db->magic = SQLITE_MAGIC_ERROR;
  }else if( Tcl_GetInt(interp, argv[2], (int*)&db->magic) ){
    return TCL_ERROR;
  }
  return TCL_OK;
}

/*
** Usage:  sqlite3_interrupt  DB 
**
** Trigger an interrupt on DB
*/
static int SQLITE_TCLAPI test_interrupt(
  void * clientData,
  Tcl_Interp *interp,
  int argc,
  char **argv
){
  sqlite3 *db;
  if( argc!=2 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB", 0);
    return TCL_ERROR;
  }
  if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
  sqlite3_interrupt(db);
  return TCL_OK;
}

/*
** Usage:  sqlite3_is_interrupted  DB 
**
** return true if an interrupt is current in effect on DB
*/
static int SQLITE_TCLAPI test_is_interrupted(
  void * clientData,
  Tcl_Interp *interp,
  int argc,
  char **argv
){
  sqlite3 *db;
  int rc;
  if( argc!=2 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB", 0);
    return TCL_ERROR;
  }
  if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
  rc = sqlite3_is_interrupted(db);
  Tcl_AppendResult(interp, rc ? "1" : "0", (void*)0);
  return TCL_OK;
}

/*
** Usage: sqlite_delete_function DB function-name
**
** Delete the user function 'function-name' from database handle DB. It
** is assumed that the user function was created as UTF8, any number of
** arguments (the way the TCL interface does it).
5443
5444
5445
5446
5447
5448
5449



























5450
5451
5452
5453
5454
5455
5456
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  if( objc==2 ){
    if( Tcl_GetWideIntFromObj(interp, objv[1], &N) ) return TCL_ERROR;
  }
  amt = sqlite3_soft_heap_limit64(N);
  Tcl_SetObjResult(interp, Tcl_NewWideIntObj(amt));
  return TCL_OK;
}

/*
** Usage:  sqlite3_hard_heap_limit ?N?
**
** Query or set the hard heap limit for the current thread.  The
** limit is only changed if the N is present.  The previous limit
** is returned.
*/
static int SQLITE_TCLAPI test_hard_heap_limit(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  sqlite3_int64 amt;
  Tcl_WideInt N = -1;
  if( objc!=1 && objc!=2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "?N?");
    return TCL_ERROR;
  }
  if( objc==2 ){
    if( Tcl_GetWideIntFromObj(interp, objv[1], &N) ) return TCL_ERROR;
  }
  amt = sqlite3_hard_heap_limit64(N);
  Tcl_SetObjResult(interp, Tcl_NewWideIntObj(amt));
  return TCL_OK;
}

/*
** Usage:   sqlite3_thread_cleanup
**
** Call the sqlite3_thread_cleanup API.
*/
static int SQLITE_TCLAPI test_thread_cleanup(
6157
6158
6159
6160
6161
6162
6163






























6164
6165
6166
6167
6168
6169
6170
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
6710
6711
6712







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    zDbName = Tcl_GetString(objv[2]);
  }
  sqlite3_file_control(db, zDbName, SQLITE_FCNTL_VFSNAME,(void*)&zVfsName);
  Tcl_AppendResult(interp, zVfsName, (char*)0);
  sqlite3_free(zVfsName);
  return TCL_OK;  
}

/*
** tclcmd:   file_control_reservebytes DB N
*/
static int SQLITE_TCLAPI file_control_reservebytes(
  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 *zDbName = "main";
  int n = 0;
  int rc;

  if( objc!=3 ){
    Tcl_WrongNumArgs(interp, 1, objv, "DB N");
    return TCL_ERROR;
  }
  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db)
   || Tcl_GetIntFromObj(interp, objv[2], &n) 
  ){
    return TCL_ERROR;
  }

  rc = sqlite3_file_control(db, zDbName, SQLITE_FCNTL_RESERVE_BYTES, (void*)&n);
  Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
  return TCL_OK;  
}


/*
** tclcmd:   file_control_tempfilename DB ?AUXDB?
**
** Return a string that is a temporary filename
*/
static int SQLITE_TCLAPI file_control_tempfilename(
6189
6190
6191
6192
6193
6194
6195




































6196
6197
6198
6199
6200
6201
6202
6731
6732
6733
6734
6735
6736
6737
6738
6739
6740
6741
6742
6743
6744
6745
6746
6747
6748
6749
6750
6751
6752
6753
6754
6755
6756
6757
6758
6759
6760
6761
6762
6763
6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774
6775
6776
6777
6778
6779
6780







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    zDbName = Tcl_GetString(objv[2]);
  }
  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.
*/
6318
6319
6320
6321
6322
6323
6324


































6325

























6326
6327
6328
6329
6330
6331
6332
6896
6897
6898
6899
6900
6901
6902
6903
6904
6905
6906
6907
6908
6909
6910
6911
6912
6913
6914
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
6943
6944
6945
6946
6947
6948
6949
6950
6951
6952
6953
6954
6955
6956
6957
6958
6959
6960
6961
6962
6963
6964
6965
6966
6967
6968







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







*/
static int SQLITE_TCLAPI reset_prng_state(
  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_randomness(0,0);
  return TCL_OK;
}
/*
** tclcmd:  prng_seed INT ?DB?
**
** Set up the SQLITE_TESTCTRL_PRNG_SEED pragma with parameter INT and DB.
** INT is an integer.  DB is a database connection, or a NULL pointer if
** omitted.
**
** When INT!=0 and DB!=0, set the PRNG seed to the value of the schema
** cookie for DB, or to INT if the schema cookie happens to be zero.
**
** When INT!=0 and DB==0, set the PRNG seed to just INT.
**
** If INT==0 and DB==0 then use the default procedure of calling the
** xRandomness method on the default VFS to get the PRNG seed.
*/
static int SQLITE_TCLAPI prng_seed(
  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 */
){
  int i = 0;
  sqlite3 *db = 0;
  if( objc!=2 && objc!=3 ){
    Tcl_WrongNumArgs(interp, 1, objv, "SEED ?DB?");
    return TCL_ERROR;
  }
  if( Tcl_GetIntFromObj(interp,objv[1],&i) ) return TCL_ERROR;
  if( objc==3 && getDbPointer(interp, Tcl_GetString(objv[2]), &db) ){
    return TCL_ERROR;
  }
  sqlite3_test_control(SQLITE_TESTCTRL_PRNG_RESET);
  sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SEED, i, db);
  return TCL_OK;
}

/*
** tclcmd:  extra_schema_checks BOOLEAN
**
** Enable or disable schema checks when parsing the sqlite_schema file.
** This is always enabled in production, but it is sometimes useful to
** disable the checks in order to make some internal error states reachable
** for testing.
*/
static int SQLITE_TCLAPI extra_schema_checks(
  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 */
){
  int i = 0;
  if( objc!=2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN");
    return TCL_ERROR;
  }
  if( Tcl_GetBooleanFromObj(interp,objv[1],&i) ) return TCL_ERROR;
  sqlite3_test_control(SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS, i);
  return TCL_OK;
}

/*
** tclcmd:  database_may_be_corrupt
**
** Indicate that database files might be corrupt. In other words, set the normal
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
6735
6736










6737
6738
6739
6740

6741
6742
6743
6744


6745
6746
6747
6748
6749
6750
6751
7330
7331
7332
7333
7334
7335
7336
7337
7338
7339
7340
7341
7342
7343
7344
7345
7346
7347
7348
7349
7350
7351
7352
7353
7354
7355
7356
7357
7358
7359
7360
7361
7362
7363
7364
7365
7366
7367
7368
7369
7370
7371
7372
7373
7374
7375
7376
7377
7378
7379
7380
7381
7382
7383
7384
7385
7386
7387
7388
7389
7390
7391
7392
7393
7394
7395
7396
7397
7398
7399
7400
7401
7402
7403
7404
7405
7406
7407
7408
7409
7410
7411
7412
7413
7414
7415
7416
7417
7418
7419
7420
7421

7422
7423
7424
7425
7426
7427
7428
7429
7430
7431
7432
7433
7434

7435
7436
7437


7438
7439
7440
7441
7442
7443
7444
7445
7446







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


















+

















-
+
+
+
+
+
+
+
+
+
+



-
+


-
-
+
+







  ** printExplainQueryPlan() immediately.
  */
  fflush(stdout);
  Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
  return TCL_OK;
}
#endif /* SQLITE_OMIT_EXPLAIN */

#include <time.h>
/*
** This is an alternative localtime_r() implementation used for testing
** the 'localtime' and 'utc' modifiers of date-time functions.  Because
** the OS-supplied localtime_r() is locale-dependent, this alternative is
** provided as a stable test platform.
**
** Operation:
**
**     (1)  Localtime is 30 minutes earlier than (west of) UTC on
**          even days (counting from 1970-01-01)
**
**     (2)  Localtime is 30 minutes later than (east of) UTC on odd days.
**
**     (3)  The function fails for the specific date/time value
**          of 2000-05-29 14:16:00 in order to test the ability of
**          SQLite to deal with localtime_r() failures.
*/
static int testLocaltime(const void *aliasT, void *aliasTM){
  const time_t t = *(const time_t*)aliasT;
  struct tm *pTm = (struct tm *)aliasTM;
  time_t altT;
  sqlite3_int64 iJD;
  int Z, A, B, C, D, E, X1, S;

  if( (t/86400) & 1 ){
    altT = t + 1800;  /* 30 minutes later on odd days */
  }else{
    altT = t - 1800;  /* 30 minutes earlier on even days */
  }
  iJD = (sqlite3_int64)(altT + 210866760000);
  Z = (int)((iJD + 43200)/86400);
  A = (int)((Z - 1867216.25)/36524.25);
  A = Z + 1 + A - (A/4);
  B = A + 1524;
  C = (int)((B - 122.1)/365.25);
  D = (36525*(C&32767))/100;
  E = (int)((B-D)/30.6001);
  X1 = (int)(30.6001*E);
  pTm->tm_mday = B - D - X1;
  pTm->tm_mon = E<14 ? E-2 : E-14;
  pTm->tm_year = (pTm->tm_mon>1 ? C - 4716 : C - 4715) - 1900;
  S = (int)((iJD + 43200)%86400);
  pTm->tm_hour = S/3600;
  pTm->tm_min = (S/60)%60;
  pTm->tm_sec = S % 60;
  return t==959609760; /* Special case: 2000-05-29 14:16:00 fails */
}

/*
** sqlite3_test_control VERB ARGS...
*/
static int SQLITE_TCLAPI test_test_control(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  struct Verb {
    const char *zName;
    int i;
  } aVerb[] = {
    { "SQLITE_TESTCTRL_LOCALTIME_FAULT",    SQLITE_TESTCTRL_LOCALTIME_FAULT }, 
    { "SQLITE_TESTCTRL_SORTER_MMAP",        SQLITE_TESTCTRL_SORTER_MMAP     }, 
    { "SQLITE_TESTCTRL_IMPOSTER",           SQLITE_TESTCTRL_IMPOSTER        },
    { "SQLITE_TESTCTRL_INTERNAL_FUNCTIONS", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS},
    { 0, 0 }
  };
  int iVerb;
  int iFlag;
  int rc;

  if( objc<2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "VERB ARGS...");
    return TCL_ERROR;
  }

  rc = Tcl_GetIndexFromObjStruct(
      interp, objv[1], aVerb, sizeof(aVerb[0]), "VERB", 0, &iVerb
  );
  if( rc!=TCL_OK ) return rc;

  iFlag = aVerb[iVerb].i;
  switch( iFlag ){
    case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS:
    case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS: {
      sqlite3 *db = 0;
      if( objc!=3 ){
        Tcl_WrongNumArgs(interp, 2, objv, "DB");
        return TCL_ERROR;
      }
      if( getDbPointer(interp, Tcl_GetString(objv[2]), &db) ) return TCL_ERROR;
      sqlite3_test_control(SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, db);
      break;
    }
    case SQLITE_TESTCTRL_LOCALTIME_FAULT: {
      int val;
      if( objc!=3 ){
        Tcl_WrongNumArgs(interp, 2, objv, "ONOFF");
        Tcl_WrongNumArgs(interp, 2, objv, "0|1|2");
        return TCL_ERROR;
      }
      if( Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
      sqlite3_test_control(iFlag, val);
      if( Tcl_GetIntFromObj(interp, objv[2], &val) ) return TCL_ERROR;
      sqlite3_test_control(iFlag, val, testLocaltime);
      break;
    }

    case SQLITE_TESTCTRL_SORTER_MMAP: {
      int val;
      sqlite3 *db;
      if( objc!=4 ){
7057
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
7097
7098
7099
7100
7101
7102
7103
7104
7105


7106

7107
7108
7109
7110

7111
7112
7113
7114
7115
7116
7117
7118

7119
7120
7121
7122
7123
7124
7125
7126
7127
7128
7129
7130
7131
7132
7133


7134
7135
7136
7137
7138
7139

7140
7141
7142
7143




7144
7145
7146
7147
7148
7149
7150
7151
7152
7153
7154
7155
7156
7157
7158


7159
7160
7161

7162
7163
7164
7165
7166
7167
7168




7169
7170
7171
7172
7173
7174
7175
7752
7753
7754
7755
7756
7757
7758

7759
7760
7761
7762
7763
7764
7765
7766
7767
7768
7769
7770
7771
7772
7773
7774
7775
7776
7777
7778
7779
7780
7781
7782
7783
7784
7785
7786
7787
7788
7789
7790
7791


7792
7793
7794
7795
7796
7797
7798
7799
7800
7801
7802
7803
7804
7805
7806


7807
7808

7809
7810
7811
7812

7813
7814
7815
7816
7817
7818
7819
7820
7821
7822
7823
7824
7825
7826
7827
7828
7829
7830
7831
7832
7833
7834
7835
7836
7837
7838
7839
7840
7841
7842
7843
7844
7845
7846
7847
7848
7849
7850
7851
7852
7853
7854
7855
7856
7857
7858
7859
7860
7861
7862
7863
7864
7865
7866
7867
7868
7869
7870
7871
7872
7873
7874
7875
7876
7877
7878
7879
7880
7881
7882
7883
7884
7885
7886
7887
7888
7889
7890
7891
7892
7893







-
+
+
+
+
+
+












+














-
-
+

+
+
+










-
-
+
+
-
+



-
+








+















+
+






+




+
+
+
+















+
+



+







+
+
+
+









/*
**      optimization_control DB OPT BOOLEAN
**
** Enable or disable query optimizations using the sqlite3_test_control()
** interface.  Disable if BOOLEAN is false and enable if BOOLEAN is true.
** OPT is the name of the optimization to be disabled.
** OPT is the name of the optimization to be disabled.  OPT can also be a
** list or optimizations names, in which case all optimizations named are
** enabled or disabled.
**
** Each invocation of this control overrides all prior invocations.  The
** changes are not cumulative.
*/
static int SQLITE_TCLAPI optimization_control(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  int i;
  sqlite3 *db;
  const char *zOpt;
  int onoff;
  int mask = 0;
  int cnt = 0;
  static const struct {
    const char *zOptName;
    int mask;
  } aOpt[] = {
    { "all",                 SQLITE_AllOpts        },
    { "none",                0                     },
    { "query-flattener",     SQLITE_QueryFlattener },
    { "groupby-order",       SQLITE_GroupByOrder   },
    { "factor-constants",    SQLITE_FactorOutConst },
    { "distinct-opt",        SQLITE_DistinctOpt    },
    { "cover-idx-scan",      SQLITE_CoverIdxScan   },
    { "order-by-idx-join",   SQLITE_OrderByIdxJoin },
    { "transitive",          SQLITE_Transitive     },
    { "omit-noop-join",      SQLITE_OmitNoopJoin   },
    { "stat3",               SQLITE_Stat34         },
    { "stat4",               SQLITE_Stat34         },
    { "stat4",               SQLITE_Stat4          },
    { "skip-scan",           SQLITE_SkipScan       },
    { "push-down",           SQLITE_PushDown       },
    { "balanced-merge",      SQLITE_BalancedMerge  },
    { "propagate-const",     SQLITE_PropagateConst },
  };

  if( objc!=4 ){
    Tcl_WrongNumArgs(interp, 1, objv, "DB OPT BOOLEAN");
    return TCL_ERROR;
  }
  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  if( Tcl_GetBooleanFromObj(interp, objv[3], &onoff) ) return TCL_ERROR;
  zOpt = Tcl_GetString(objv[2]);
  for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){
    if( strcmp(zOpt, aOpt[i].zOptName)==0 ){
      mask = aOpt[i].mask;
    if( strstr(zOpt, aOpt[i].zOptName)!=0 ){
      mask |= aOpt[i].mask;
      break;
      cnt++;
    }
  }
  if( onoff ) mask = ~mask;
  if( i>=sizeof(aOpt)/sizeof(aOpt[0]) ){
  if( cnt==0 ){
    Tcl_AppendResult(interp, "unknown optimization - should be one of:",
                     (char*)0);
    for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){
      Tcl_AppendResult(interp, " ", aOpt[i].zOptName, (char*)0);
    }
    return TCL_ERROR;
  }
  sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, db, mask);
  Tcl_SetObjResult(interp, Tcl_NewIntObj(mask));
  return TCL_OK;
}

/*
**     load_static_extension DB NAME ...
**
** Load one or more statically linked extensions.
*/
static int SQLITE_TCLAPI tclLoadStaticExtensionCmd(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  extern int sqlite3_amatch_init(sqlite3*,char**,const sqlite3_api_routines*);
  extern int sqlite3_appendvfs_init(sqlite3*,char**,const sqlite3_api_routines*);
  extern int sqlite3_basexx_init(sqlite3*,char**,const sqlite3_api_routines*);
  extern int sqlite3_carray_init(sqlite3*,char**,const sqlite3_api_routines*);
  extern int sqlite3_closure_init(sqlite3*,char**,const sqlite3_api_routines*);
  extern int sqlite3_csv_init(sqlite3*,char**,const sqlite3_api_routines*);
  extern int sqlite3_eval_init(sqlite3*,char**,const sqlite3_api_routines*);
  extern int sqlite3_explain_init(sqlite3*,char**,const sqlite3_api_routines*);
  extern int sqlite3_fileio_init(sqlite3*,char**,const sqlite3_api_routines*);
  extern int sqlite3_decimal_init(sqlite3*,char**,const sqlite3_api_routines*);
  extern int sqlite3_fuzzer_init(sqlite3*,char**,const sqlite3_api_routines*);
  extern int sqlite3_ieee_init(sqlite3*,char**,const sqlite3_api_routines*);
  extern int sqlite3_nextchar_init(sqlite3*,char**,const sqlite3_api_routines*);
  extern int sqlite3_percentile_init(sqlite3*,char**,const sqlite3_api_routines*);
#ifndef SQLITE_OMIT_VIRTUALTABLE
  extern int sqlite3_prefixes_init(sqlite3*,char**,const sqlite3_api_routines*);
#endif
  extern int sqlite3_qpvtab_init(sqlite3*,char**,const sqlite3_api_routines*);
  extern int sqlite3_regexp_init(sqlite3*,char**,const sqlite3_api_routines*);
  extern int sqlite3_remember_init(sqlite3*,char**,const sqlite3_api_routines*);
  extern int sqlite3_series_init(sqlite3*,char**,const sqlite3_api_routines*);
  extern int sqlite3_spellfix_init(sqlite3*,char**,const sqlite3_api_routines*);
  extern int sqlite3_totype_init(sqlite3*,char**,const sqlite3_api_routines*);
  extern int sqlite3_wholenumber_init(sqlite3*,char**,const sqlite3_api_routines*);
  extern int sqlite3_unionvtab_init(sqlite3*,char**,const sqlite3_api_routines*);
#ifdef SQLITE_HAVE_ZLIB
  extern int sqlite3_zipfile_init(sqlite3*,char**,const sqlite3_api_routines*);
#endif
  static const struct {
    const char *zExtName;
    int (*pInit)(sqlite3*,char**,const sqlite3_api_routines*);
  } aExtension[] = {
    { "amatch",                sqlite3_amatch_init               },
    { "appendvfs",             sqlite3_appendvfs_init            },
    { "basexx",                sqlite3_basexx_init               },
    { "carray",                sqlite3_carray_init               },
    { "closure",               sqlite3_closure_init              },
    { "csv",                   sqlite3_csv_init                  },
    { "decimal",               sqlite3_decimal_init              },
    { "eval",                  sqlite3_eval_init                 },
    { "explain",               sqlite3_explain_init              },
    { "fileio",                sqlite3_fileio_init               },
    { "fuzzer",                sqlite3_fuzzer_init               },
    { "ieee754",               sqlite3_ieee_init                 },
    { "nextchar",              sqlite3_nextchar_init             },
    { "percentile",            sqlite3_percentile_init           },
#ifndef SQLITE_OMIT_VIRTUALTABLE
    { "prefixes",              sqlite3_prefixes_init             },
#endif
    { "qpvtab",                sqlite3_qpvtab_init               },
    { "regexp",                sqlite3_regexp_init               },
    { "remember",              sqlite3_remember_init             },
    { "series",                sqlite3_series_init               },
    { "spellfix",              sqlite3_spellfix_init             },
    { "totype",                sqlite3_totype_init               },
    { "unionvtab",             sqlite3_unionvtab_init            },
    { "wholenumber",           sqlite3_wholenumber_init          },
7196
7197
7198
7199
7200
7201
7202
7203

7204
7205
7206
7207
7208
7209
7210
7914
7915
7916
7917
7918
7919
7920

7921
7922
7923
7924
7925
7926
7927
7928







-
+







      return TCL_ERROR;
    }
    if( aExtension[i].pInit ){
      rc = aExtension[i].pInit(db, &zErrMsg, 0);
    }else{
      rc = SQLITE_OK;
    }
    if( rc!=SQLITE_OK || zErrMsg ){
    if( (rc!=SQLITE_OK && rc!=SQLITE_OK_LOAD_PERMANENTLY) || zErrMsg ){
      Tcl_AppendResult(interp, "initialization of ", zName, " failed: ", zErrMsg,
                       (char*)0);
      sqlite3_free(zErrMsg);
      return TCL_ERROR;
    }
  }
  return TCL_OK;
7547
7548
7549
7550
7551
7552
7553
7554
7555
7556
7557
7558
7559
7560
7561
7562














7563
7564
7565

7566
7567
7568
7569
7570


7571
7572
7573
7574
7575
7576
7577
7578
7579
7580
7581
7582
7583
7584
7585

7586




7587
7588
7589
7590



























7591
7592
7593
7594
7595
7596
7597
8265
8266
8267
8268
8269
8270
8271









8272
8273
8274
8275
8276
8277
8278
8279
8280
8281
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
8318
8319
8320
8321
8322
8323
8324
8325
8326
8327
8328
8329
8330
8331
8332
8333
8334
8335
8336
8337
8338
8339
8340
8341
8342
8343
8344
8345
8346
8347
8348
8349
8350
8351







-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+



-
-
+
+















+
-
+
+
+
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  int objc,
  Tcl_Obj *CONST objv[]
){
  static const struct {
    const char *zName;
    int eVal;
  } aSetting[] = {
    { "FKEY",            SQLITE_DBCONFIG_ENABLE_FKEY },
    { "TRIGGER",         SQLITE_DBCONFIG_ENABLE_TRIGGER },
    { "FTS3_TOKENIZER",  SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
    { "LOAD_EXTENSION",  SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
    { "NO_CKPT_ON_CLOSE",SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE },
    { "QPSG",            SQLITE_DBCONFIG_ENABLE_QPSG },
    { "TRIGGER_EQP",     SQLITE_DBCONFIG_TRIGGER_EQP },
    { "RESET_DB",        SQLITE_DBCONFIG_RESET_DATABASE },
    { "DEFENSIVE",       SQLITE_DBCONFIG_DEFENSIVE },
    { "FKEY",               SQLITE_DBCONFIG_ENABLE_FKEY },
    { "TRIGGER",            SQLITE_DBCONFIG_ENABLE_TRIGGER },
    { "FTS3_TOKENIZER",     SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
    { "LOAD_EXTENSION",     SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
    { "NO_CKPT_ON_CLOSE",   SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE },
    { "QPSG",               SQLITE_DBCONFIG_ENABLE_QPSG },
    { "TRIGGER_EQP",        SQLITE_DBCONFIG_TRIGGER_EQP },
    { "RESET_DB",           SQLITE_DBCONFIG_RESET_DATABASE },
    { "DEFENSIVE",          SQLITE_DBCONFIG_DEFENSIVE },
    { "WRITABLE_SCHEMA",    SQLITE_DBCONFIG_WRITABLE_SCHEMA },
    { "LEGACY_ALTER_TABLE", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE },
    { "DQS_DML",            SQLITE_DBCONFIG_DQS_DML },
    { "DQS_DDL",            SQLITE_DBCONFIG_DQS_DDL },
    { "LEGACY_FILE_FORMAT", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT },
  };
  int i;
  int v;
  int v = 0;
  const char *zSetting;
  sqlite3 *db;

  if( objc!=4 ){
    Tcl_WrongNumArgs(interp, 1, objv, "DB SETTING VALUE");
  if( objc!=4 && objc!=3 ){
    Tcl_WrongNumArgs(interp, 1, objv, "DB SETTING [VALUE]");
    return TCL_ERROR;
  }
  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  zSetting = Tcl_GetString(objv[2]);
  if( sqlite3_strglob("SQLITE_*", zSetting)==0 ) zSetting += 7;
  if( sqlite3_strglob("DBCONFIG_*", zSetting)==0 ) zSetting += 9;
  if( sqlite3_strglob("ENABLE_*", zSetting)==0 ) zSetting += 7;
  for(i=0; i<ArraySize(aSetting); i++){
    if( strcmp(zSetting, aSetting[i].zName)==0 ) break;
  }
  if( i>=ArraySize(aSetting) ){
    Tcl_SetObjResult(interp,
      Tcl_NewStringObj("unknown sqlite3_db_config setting", -1));
    return TCL_ERROR;
  }
  if( objc==4 ){
  if( Tcl_GetIntFromObj(interp, objv[3], &v) ) return TCL_ERROR;
    if( Tcl_GetIntFromObj(interp, objv[3], &v) ) return TCL_ERROR;
  }else{
    v = -1;
  }
  sqlite3_db_config(db, aSetting[i].eVal, v, &v);
  Tcl_SetObjResult(interp, Tcl_NewIntObj(v));
  return TCL_OK;
}
/*
** tclcmd:   sqlite3_txn_state DB ?SCHEMA?
**
** Invoke sqlite3_txn_state(DB,SCHEMA) and return the
** numeric value that results.  Use NULL for SCHEMA if the 3 argument
** is omitted.
*/
static int SQLITE_TCLAPI test_sqlite3_txn_state(
  void *clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  sqlite3 *db;
  const char *zSchema;
  int iTxn;

  if( objc!=2 && objc!=3 ){
    Tcl_WrongNumArgs(interp, 1, objv, "DB ?SCHEMA?");
    return TCL_ERROR;
  }
  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  zSchema = objc==3 ? Tcl_GetString(objv[2]) : 0;
  iTxn = sqlite3_txn_state(db, zSchema);
  Tcl_SetObjResult(interp, Tcl_NewIntObj(iTxn));
  return TCL_OK;
}

/*
** Change the name of the main database schema from "main" to "icecube".
*/
static int SQLITE_TCLAPI test_dbconfig_maindbname_icecube(
  void * clientData,
  Tcl_Interp *interp,
7671
7672
7673
7674
7675
7676
7677













































































7678
7679
7680
7681
7682
7683
7684
8425
8426
8427
8428
8429
8430
8431
8432
8433
8434
8435
8436
8437
8438
8439
8440
8441
8442
8443
8444
8445
8446
8447
8448
8449
8450
8451
8452
8453
8454
8455
8456
8457
8458
8459
8460
8461
8462
8463
8464
8465
8466
8467
8468
8469
8470
8471
8472
8473
8474
8475
8476
8477
8478
8479
8480
8481
8482
8483
8484
8485
8486
8487
8488
8489
8490
8491
8492
8493
8494
8495
8496
8497
8498
8499
8500
8501
8502
8503
8504
8505
8506
8507
8508
8509
8510
8511
8512
8513
8514
8515







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







      zDb = Tcl_GetString(objv[2]);
    }
    rc = sqlite3_mmap_warm(db, zDb);
    Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
    return TCL_OK;
  }
}

/*
** Usage:  test_write_db DB OFFSET DATA
**
** Obtain the sqlite3_file* object for the database file for the "main" db
** of handle DB. Then invoke its xWrite method to write data DATA to offset
** OFFSET.
*/
static int SQLITE_TCLAPI test_write_db(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  sqlite3 *db = 0;
  Tcl_WideInt iOff = 0;
  const unsigned char *aData = 0;
  int nData = 0;
  sqlite3_file *pFile = 0;
  int rc;

  if( objc!=4 ){
    Tcl_WrongNumArgs(interp, 1, objv, "DB OFFSET DATA");
    return TCL_ERROR;
  }
  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  if( Tcl_GetWideIntFromObj(interp, objv[2], &iOff) ) return TCL_ERROR;
  aData = Tcl_GetByteArrayFromObj(objv[3], &nData);

  sqlite3_file_control(db, "main", SQLITE_FCNTL_FILE_POINTER, (void*)&pFile);
  rc = pFile->pMethods->xWrite(pFile, aData, nData, iOff);

  Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
  return TCL_OK;
}

/*
** Usage:  sqlite3_register_cksumvfs
**
*/
static int SQLITE_TCLAPI test_register_cksumvfs(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  if( objc!=1 ){
    Tcl_WrongNumArgs(interp, 1, objv, "");
    return TCL_ERROR;
  }else{
    extern int sqlite3_register_cksumvfs(const char*);
    int rc = sqlite3_register_cksumvfs(0);
    Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
  }
  return TCL_OK;
}

/*
** Usage:  sqlite3_unregister_cksumvfs
**
*/
static int SQLITE_TCLAPI test_unregister_cksumvfs(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  if( objc!=1 ){
    Tcl_WrongNumArgs(interp, 1, objv, "");
    return TCL_ERROR;
  }else{
    extern int sqlite3_unregister_cksumvfs(void);
    int rc = sqlite3_unregister_cksumvfs();
    Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
  }
  return TCL_OK;
}

/*
** Usage:  decode_hexdb TEXT
**
** Example:   db deserialize [decode_hexdb $output_of_dbtotxt]
**
** This routine returns a byte-array for an SQLite database file that
7695
7696
7697
7698
7699
7700
7701
7702

7703
7704
7705
7706
7707
7708
7709
7710
7711
7712
7713
7714
7715
7716





7717
7718
7719
7720
7721
7722
7723
7724
7725
7726
7727
7728
7729
7730
7731
7732
7733
7734

7735
7736
7737
7738
7739
7740
7741


7742
7743
7744
7745
7746
7747
7748
7749


























































































7750
7751
7752
7753
7754
7755
7756
8526
8527
8528
8529
8530
8531
8532

8533
8534
8535
8536
8537
8538
8539
8540
8541
8542
8543
8544
8545
8546
8547
8548
8549
8550
8551
8552
8553
8554
8555
8556
8557
8558
8559
8560
8561
8562
8563
8564
8565
8566
8567
8568
8569

8570

8571
8572
8573
8574
8575

8576
8577
8578
8579
8580
8581
8582
8583
8584
8585
8586
8587
8588
8589
8590
8591
8592
8593
8594
8595
8596
8597
8598
8599
8600
8601
8602
8603
8604
8605
8606
8607
8608
8609
8610
8611
8612
8613
8614
8615
8616
8617
8618
8619
8620
8621
8622
8623
8624
8625
8626
8627
8628
8629
8630
8631
8632
8633
8634
8635
8636
8637
8638
8639
8640
8641
8642
8643
8644
8645
8646
8647
8648
8649
8650
8651
8652
8653
8654
8655
8656
8657
8658
8659
8660
8661
8662
8663
8664
8665
8666
8667
8668
8669
8670
8671
8672
8673
8674
8675
8676
8677
8678
8679
8680
8681
8682







-
+














+
+
+
+
+

















-
+
-





-
+
+








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  unsigned char *a = 0;
  int n = 0;
  int lineno = 0;
  int i, iNext;
  int iOffset = 0;
  int j, k;
  int rc;
  unsigned char x[16];
  unsigned int x[16];
  if( objc!=2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "HEXDB");
    return TCL_ERROR;
  }
  zIn = Tcl_GetString(objv[1]);
  for(i=0; zIn[i]; i=iNext){
    lineno++;
    for(iNext=i; zIn[iNext] && zIn[iNext]!='\n'; iNext++){}
    if( zIn[iNext]=='\n' ) iNext++;
    while( zIn[i]==' ' || zIn[i]=='\t' ){ i++; }
    if( a==0 ){
      int pgsz;
      rc = sscanf(zIn+i, "| size %d pagesize %d", &n, &pgsz);
      if( rc!=2 ) continue;
      if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ){
        Tcl_AppendResult(interp, "bad 'pagesize' field", (void*)0);
        return TCL_ERROR;
      }
      n = (n+pgsz-1)&~(pgsz-1);  /* Round n up to the next multiple of pgsz */
      if( n<512 ){
        Tcl_AppendResult(interp, "bad 'size' field", (void*)0);
        return TCL_ERROR;
      }
      a = malloc( n );
      if( a==0 ){
        Tcl_AppendResult(interp, "out of memory", (void*)0);
        return TCL_ERROR;
      }
      memset(a, 0, n);
      continue;
    }
    rc = sscanf(zIn+i, "| page %d offset %d", &j, &k);
    if( rc==2 ){
      iOffset = k;
      continue;
    }
    rc = sscanf(zIn+i,"| %d: %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx"
    rc = sscanf(zIn+i,"| %d: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
                      "  %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx",
                &j, &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
                &x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], &x[15]);
    if( rc==17 ){
      k = iOffset+j;
      if( k+16<=n ){
        memcpy(a+k, x, 16);
        int ii;
        for(ii=0; ii<16; ii++) a[k+ii] = x[ii]&0xff;
      }
      continue;
    }
  }
  Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(a, n));
  free(a);
  return TCL_OK;
}

/*
** Client data for the autovacuum_pages callback.
*/
struct AutovacPageData {
  Tcl_Interp *interp;
  char *zScript;
};
typedef struct AutovacPageData AutovacPageData;

/*
** Callback functions for sqlite3_autovacuum_pages
*/
static unsigned int test_autovacuum_pages_callback(
  void *pClientData,
  const char *zSchema,
  unsigned int nFilePages,
  unsigned int nFreePages,
  unsigned int nBytePerPage
){
  AutovacPageData *pData = (AutovacPageData*)pClientData;
  Tcl_DString str;
  unsigned int x;
  char zBuf[100];
  Tcl_DStringInit(&str);
  Tcl_DStringAppend(&str, pData->zScript, -1);
  Tcl_DStringAppendElement(&str, zSchema);
  sqlite3_snprintf(sizeof(zBuf), zBuf, "%u", nFilePages);
  Tcl_DStringAppendElement(&str, zBuf);
  sqlite3_snprintf(sizeof(zBuf), zBuf, "%u", nFreePages);
  Tcl_DStringAppendElement(&str, zBuf);
  sqlite3_snprintf(sizeof(zBuf), zBuf, "%u", nBytePerPage);
  Tcl_DStringAppendElement(&str, zBuf);
  Tcl_ResetResult(pData->interp);
  Tcl_Eval(pData->interp, Tcl_DStringValue(&str));
  Tcl_DStringFree(&str);
  x = nFreePages;
  (void)Tcl_GetIntFromObj(0, Tcl_GetObjResult(pData->interp), (int*)&x);
  return x;
}

/*
** Usage:  sqlite3_autovacuum_pages DB SCRIPT
**
** Add an autovacuum-pages callback to database connection DB.  The callback
** will invoke SCRIPT, after appending parameters.
**
** If SCRIPT is an empty string or is omitted, then the callback is
** cancelled.
*/
static int SQLITE_TCLAPI test_autovacuum_pages(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  AutovacPageData *pData;
  sqlite3 *db;
  int rc;
  const char *zScript;
  if( objc!=2 && objc!=3 ){
    Tcl_WrongNumArgs(interp, 1, objv, "DB ?SCRIPT?");
    return TCL_ERROR;
  }
  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  zScript = objc==3 ? Tcl_GetString(objv[2]) : 0;
  if( zScript ){
    size_t nScript = strlen(zScript);
    pData = sqlite3_malloc64( sizeof(*pData) + nScript + 1 );
    if( pData==0 ){
      Tcl_AppendResult(interp, "out of memory", (void*)0);
      return TCL_ERROR;
    }
    pData->interp = interp;
    pData->zScript = (char*)&pData[1];
    memcpy(pData->zScript, zScript, nScript+1);
    rc = sqlite3_autovacuum_pages(db,test_autovacuum_pages_callback,
                                  pData, sqlite3_free);
  }else{
    rc = sqlite3_autovacuum_pages(db, 0, 0, 0);
  }
  if( rc ){
    char zBuf[1000];
    sqlite3_snprintf(sizeof(zBuf), zBuf,
       "sqlite3_autovacuum_pages() returns %d", rc);
    Tcl_AppendResult(interp, zBuf, (void*)0);
    return TCL_ERROR;
  }
  return TCL_OK;
}


/*
** Register commands with the TCL interpreter.
*/
int Sqlitetest1_Init(Tcl_Interp *interp){
  extern int sqlite3_search_count;
7792
7793
7794
7795
7796
7797
7798

7799
7800
7801
7802
7803
7804
7805
7806

7807
7808
7809
7810
7811
7812
7813
7814
7815
7816
7817
7818
7819
7820

7821
7822
7823
7824
7825
7826
7827
7828
7829
7830
7831
7832
7833
7834
7835
7836





7837
7838
7839
7840
7841
7842
7843
7844

7845
7846
7847
7848
7849
7850
7851
8718
8719
8720
8721
8722
8723
8724
8725
8726
8727
8728
8729
8730
8731

8732
8733
8734
8735
8736
8737
8738
8739
8740
8741
8742
8743
8744
8745
8746
8747
8748
8749
8750
8751
8752
8753
8754
8755
8756
8757
8758
8759
8760
8761
8762
8763
8764
8765
8766
8767
8768
8769
8770
8771
8772
8773
8774
8775
8776
8777
8778
8779
8780
8781
8782
8783
8784
8785







+






-

+














+
















+
+
+
+
+








+







#ifndef SQLITE_OMIT_GET_TABLE
     { "sqlite3_get_table_printf",      (Tcl_CmdProc*)test_get_table_printf },
#endif
     { "sqlite3_close",                 (Tcl_CmdProc*)sqlite_test_close     },
     { "sqlite3_close_v2",              (Tcl_CmdProc*)sqlite_test_close_v2  },
     { "sqlite3_create_function",       (Tcl_CmdProc*)test_create_function  },
     { "sqlite3_create_aggregate",      (Tcl_CmdProc*)test_create_aggregate },
     { "sqlite3_drop_modules",          (Tcl_CmdProc*)test_drop_modules     },
     { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func    },
     { "sqlite_abort",                  (Tcl_CmdProc*)sqlite_abort          },
     { "sqlite_bind",                   (Tcl_CmdProc*)test_bind             },
     { "breakpoint",                    (Tcl_CmdProc*)test_breakpoint       },
     { "sqlite3_key",                   (Tcl_CmdProc*)test_key              },
     { "sqlite3_rekey",                 (Tcl_CmdProc*)test_rekey            },
     { "sqlite_set_magic",              (Tcl_CmdProc*)sqlite_set_magic      },
     { "sqlite3_interrupt",             (Tcl_CmdProc*)test_interrupt        },
     { "sqlite3_is_interrupted",        (Tcl_CmdProc*)test_is_interrupted   },
     { "sqlite_delete_function",        (Tcl_CmdProc*)delete_function       },
     { "sqlite_delete_collation",       (Tcl_CmdProc*)delete_collation      },
     { "sqlite3_get_autocommit",        (Tcl_CmdProc*)get_autocommit        },
     { "sqlite3_busy_timeout",          (Tcl_CmdProc*)test_busy_timeout     },
     { "printf",                        (Tcl_CmdProc*)test_printf           },
     { "sqlite3IoTrace",              (Tcl_CmdProc*)test_io_trace         },
     { "clang_sanitize_address",        (Tcl_CmdProc*)clang_sanitize_address },
  };
  static struct {
     char *zName;
     Tcl_ObjCmdProc *xProc;
     void *clientData;
  } aObjCmd[] = {
     { "sqlite3_db_config",             test_sqlite3_db_config, 0 },
     { "sqlite3_txn_state",             test_sqlite3_txn_state, 0 },
     { "bad_behavior",                  test_bad_behavior,  (void*)&iZero },
     { "register_dbstat_vtab",          test_register_dbstat_vtab  },
     { "sqlite3_connection_pointer",    get_sqlite_pointer, 0 },
     { "intarray_addr",                 test_intarray_addr, 0 },
     { "int64array_addr",               test_int64array_addr, 0 },
     { "doublearray_addr",              test_doublearray_addr, 0 },
     { "textarray_addr",                test_textarray_addr, 0 },
     { "sqlite3_bind_int",              test_bind_int,      0 },
     { "sqlite3_bind_zeroblob",         test_bind_zeroblob, 0 },
     { "sqlite3_bind_zeroblob64",       test_bind_zeroblob64, 0 },
     { "sqlite3_bind_int64",            test_bind_int64,    0 },
     { "sqlite3_bind_double",           test_bind_double,   0 },
     { "sqlite3_bind_null",             test_bind_null     ,0 },
     { "sqlite3_bind_text",             test_bind_text     ,0 },
     { "sqlite3_bind_text16",           test_bind_text16   ,0 },
     { "sqlite3_bind_blob",             test_bind_blob     ,0 },
     { "sqlite3_bind_value_from_select",test_bind_value_from_select ,0 },
     { "sqlite3_bind_value_from_preupdate",test_bind_value_from_preupdate ,0 },
#ifndef SQLITE_OMIT_VIRTUALTABLE
     { "sqlite3_carray_bind",           test_carray_bind   ,0 },
#endif
     { "sqlite3_bind_parameter_count",  test_bind_parameter_count, 0},
     { "sqlite3_bind_parameter_name",   test_bind_parameter_name,  0},
     { "sqlite3_bind_parameter_index",  test_bind_parameter_index, 0},
     { "sqlite3_clear_bindings",        test_clear_bindings, 0},
     { "sqlite3_sleep",                 test_sleep,          0},
     { "sqlite3_errcode",               test_errcode       ,0 },
     { "sqlite3_extended_errcode",      test_ex_errcode    ,0 },
     { "sqlite3_errmsg",                test_errmsg        ,0 },
     { "sqlite3_error_offset",          test_error_offset  ,0 },
     { "sqlite3_errmsg16",              test_errmsg16      ,0 },
     { "sqlite3_open",                  test_open          ,0 },
     { "sqlite3_open16",                test_open16        ,0 },
     { "sqlite3_open_v2",               test_open_v2       ,0 },
     { "sqlite3_complete16",            test_complete16    ,0 },
     { "sqlite3_normalize",             test_normalize     ,0 },

7865
7866
7867
7868
7869
7870
7871

7872
7873
7874
7875
7876
7877
7878
7879
7880
7881


7882
7883
7884
7885
7886
7887
7888
7889
7890
7891
7892
7893


7894
7895
7896
7897
7898
7899
7900
8799
8800
8801
8802
8803
8804
8805
8806
8807
8808
8809
8810
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
8836
8837
8838
8839







+










+
+












+
+







     { "sqlite3_sql",                   test_sql           ,0 },
     { "sqlite3_expanded_sql",          test_ex_sql        ,0 },
#ifdef SQLITE_ENABLE_NORMALIZE
     { "sqlite3_normalized_sql",        test_norm_sql      ,0 },
#endif
     { "sqlite3_next_stmt",             test_next_stmt     ,0 },
     { "sqlite3_stmt_readonly",         test_stmt_readonly ,0 },
     { "sqlite3_stmt_isexplain",        test_stmt_isexplain,0 },
     { "sqlite3_stmt_busy",             test_stmt_busy     ,0 },
     { "uses_stmt_journal",             uses_stmt_journal ,0 },

     { "sqlite3_release_memory",        test_release_memory,     0},
     { "sqlite3_db_release_memory",     test_db_release_memory,  0},
     { "sqlite3_db_cacheflush",         test_db_cacheflush,      0},
     { "sqlite3_system_errno",          test_system_errno,       0},
     { "sqlite3_db_filename",           test_db_filename,        0},
     { "sqlite3_db_readonly",           test_db_readonly,        0},
     { "sqlite3_soft_heap_limit",       test_soft_heap_limit,    0},
     { "sqlite3_soft_heap_limit64",     test_soft_heap_limit,    0},
     { "sqlite3_hard_heap_limit64",     test_hard_heap_limit,    0},
     { "sqlite3_thread_cleanup",        test_thread_cleanup,     0},
     { "sqlite3_pager_refcounts",       test_pager_refcounts,    0},

     { "sqlite3_load_extension",        test_load_extension,     0},
     { "sqlite3_enable_load_extension", test_enable_load,        0},
     { "sqlite3_extended_result_codes", test_extended_result_codes, 0},
     { "sqlite3_limit",                 test_limit,                 0},
     { "dbconfig_maindbname_icecube",   test_dbconfig_maindbname_icecube },

     { "save_prng_state",               save_prng_state,    0 },
     { "restore_prng_state",            restore_prng_state, 0 },
     { "reset_prng_state",              reset_prng_state,   0 },
     { "prng_seed",                     prng_seed,          0 },
     { "extra_schema_checks",           extra_schema_checks,    0},
     { "database_never_corrupt",        database_never_corrupt, 0},
     { "database_may_be_corrupt",       database_may_be_corrupt, 0},
     { "optimization_control",          optimization_control,0},
#if SQLITE_OS_WIN
     { "lock_win32_file",               win32_file_lock,    0 },
     { "exists_win32_path",             win32_exists_path,  0 },
     { "find_win32_file",               win32_find_file,    0 },
7956
7957
7958
7959
7960
7961
7962

7963

7964
7965
7966
7967
7968
7969
7970
8895
8896
8897
8898
8899
8900
8901
8902
8903
8904
8905
8906
8907
8908
8909
8910
8911







+

+







     { "file_control_win32_av_retry", file_control_win32_av_retry,  0   },
     { "file_control_win32_get_handle", file_control_win32_get_handle, 0  },
     { "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     },
8025
8026
8027
8028
8029
8030
8031

8032



8033
8034
8035
8036
8037
8038
8039
8040
8041
8042
8043
8044
8045
8046
8047
8048

8049
8050
8051
8052
8053
8054
8055
8056
8057
8058
8059
8060
8061
8062
8063
8064
8065
8066
8966
8967
8968
8969
8970
8971
8972
8973
8974
8975
8976
8977
8978
8979
8980
8981
8982
8983
8984
8985
8986
8987
8988
8989
8990
8991
8992

8993
8994
8995
8996
8997
8998
8999
9000
9001



9002
9003
9004
9005
9006
9007
9008







+

+
+
+















-
+








-
-
-







     { "sqlite3_snapshot_cmp_blob", test_snapshot_cmp_blob, 0 },
#endif
     { "sqlite3_delete_database", test_delete_database, 0 },
     { "sqlite3_wal_info", test_wal_info, 0 },
     { "atomic_batch_write",      test_atomic_batch_write,     0   },
     { "sqlite3_mmap_warm",       test_mmap_warm,          0 },
     { "sqlite3_config_sorterref", test_config_sorterref,   0 },
     { "sqlite3_autovacuum_pages", test_autovacuum_pages,   0 },
     { "decode_hexdb",             test_decode_hexdb,       0 },
     { "test_write_db",            test_write_db,           0 },
     { "sqlite3_register_cksumvfs", test_register_cksumvfs,  0 },
     { "sqlite3_unregister_cksumvfs", test_unregister_cksumvfs,  0 },
  };
  static int bitmask_size = sizeof(Bitmask)*8;
  static int longdouble_size = sizeof(LONGDOUBLE_TYPE);
  int i;
  extern int sqlite3_sync_count, sqlite3_fullsync_count;
  extern int sqlite3_opentemp_count;
  extern int sqlite3_like_count;
  extern int sqlite3_xferopt_count;
  extern int sqlite3_pager_readdb_count;
  extern int sqlite3_pager_writedb_count;
  extern int sqlite3_pager_writej_count;
#if SQLITE_OS_WIN
  extern LONG volatile sqlite3_os_type;
#endif
#ifdef SQLITE_DEBUG
  extern int sqlite3WhereTrace;
  extern u32 sqlite3WhereTrace;
  extern int sqlite3OSTrace;
  extern int sqlite3WalTrace;
#endif
#ifdef SQLITE_TEST
#ifdef SQLITE_ENABLE_FTS3
  extern int sqlite3_fts3_enable_parentheses;
#endif
#endif
#if defined(SQLITE_ENABLE_SELECTTRACE)
  extern int sqlite3SelectTrace;
#endif

  for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
    Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
  }
  for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
    Tcl_CreateObjCommand(interp, aObjCmd[i].zName, 
        aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
8138
8139
8140
8141
8142
8143
8144
8145
8146
8147



8148
8149
8150
8151
8152
8153
8154
9080
9081
9082
9083
9084
9085
9086



9087
9088
9089
9090
9091
9092
9093
9094
9095
9096







-
-
-
+
+
+







      (char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
  Tcl_LinkVar(interp, "longdouble_size",
      (char*)&longdouble_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
  Tcl_LinkVar(interp, "sqlite_sync_count",
      (char*)&sqlite3_sync_count, TCL_LINK_INT);
  Tcl_LinkVar(interp, "sqlite_fullsync_count",
      (char*)&sqlite3_fullsync_count, TCL_LINK_INT);
#if defined(SQLITE_ENABLE_SELECTTRACE)
  Tcl_LinkVar(interp, "sqlite3SelectTrace",
      (char*)&sqlite3SelectTrace, TCL_LINK_INT);
#if defined(SQLITE_ENABLE_TREETRACE)
  Tcl_LinkVar(interp, "sqlite3_unsupported_treetrace",
      (char*)&sqlite3TreeTrace, TCL_LINK_INT);
#endif
#if defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_TEST)
  Tcl_LinkVar(interp, "sqlite_fts3_enable_parentheses",
      (char*)&sqlite3_fts3_enable_parentheses, TCL_LINK_INT);
#endif
  return TCL_OK;
}

Changes to src/test2.c.

517
518
519
520
521
522
523








524
525
526
527
528
529
530
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538







+
+
+
+
+
+
+
+







  int nFile;
  if( argc!=3 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
       " N-MEGABYTES FILE\"", 0);
    return TCL_ERROR;
  }
  if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR;
#if defined(_WIN32)
  if( n>2 ){
    Tcl_AppendResult(interp, "cannot create ", argv[1],
       "MB file because Windows "
       "does not support sparse files", (void*)0);
    return TCL_ERROR;
  }
#endif

  pVfs = sqlite3_vfs_find(0);
  nFile = (int)strlen(argv[2]);
  zFile = sqlite3_malloc( nFile+2 );
  if( zFile==0 ) return TCL_ERROR;
  memcpy(zFile, argv[2], nFile+1);
  zFile[nFile+1] = 0;

Changes to src/test4.c.

28
29
30
31
32
33
34
35

36
37
38
39
40
41
42
43
44

45
46
47
48
49
50
51
52
53
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
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







-
+








-
+


















+
+
+
+
+




-
+











+


+






+


+













+








/*
** Each thread is controlled by an instance of the following
** structure.
*/
typedef struct Thread Thread;
struct Thread {
  /* The first group of fields are writable by the master and read-only
  /* The first group of fields are writable by the leader and read-only
  ** to the thread. */
  char *zFilename;       /* Name of database file */
  void (*xOp)(Thread*);  /* next operation to do */
  char *zArg;            /* argument usable by xOp */
  int opnum;             /* Operation number */
  int busy;              /* True if this thread is in use */

  /* The next group of fields are writable by the thread but read-only to the
  ** master. */
  ** leader. */
  int completed;        /* Number of operations completed */
  sqlite3 *db;           /* Open database */
  sqlite3_stmt *pStmt;     /* Pending operation */
  char *zErr;           /* operation error */
  char *zStaticErr;     /* Static error message */
  int rc;               /* operation return code */
  int argc;             /* number of columns in result */
  const char *argv[100];    /* result columns */
  const char *colv[100];    /* result column names */
};

/*
** There can be as many as 26 threads running at once.  Each is named
** by a capital letter: A, B, C, ..., Y, Z.
*/
#define N_THREAD 26
static Thread threadset[N_THREAD];

static void test_barrier(){
  sqlite3_mutex *pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_APP1);
  sqlite3_mutex_enter(pMutex);
  sqlite3_mutex_leave(pMutex);
}

/*
** The main loop for a thread.  Threads use busy waiting. 
*/
static void *thread_main(void *pArg){
static void *test_thread_main(void *pArg){
  Thread *p = (Thread*)pArg;
  if( p->db ){
    sqlite3_close(p->db);
  }
  sqlite3_open(p->zFilename, &p->db);
  if( SQLITE_OK!=sqlite3_errcode(p->db) ){
    p->zErr = strdup(sqlite3_errmsg(p->db));
    sqlite3_close(p->db);
    p->db = 0;
  }
  p->pStmt = 0;
  test_barrier();
  p->completed = 1;
  while( p->opnum<=p->completed ) sched_yield();
  test_barrier();
  while( p->xOp ){
    if( p->zErr && p->zErr!=p->zStaticErr ){
      sqlite3_free(p->zErr);
      p->zErr = 0;
    }
    (*p->xOp)(p);
    test_barrier();
    p->completed++;
    while( p->opnum<=p->completed ) sched_yield();
    test_barrier();
  }
  if( p->pStmt ){
    sqlite3_finalize(p->pStmt);
    p->pStmt = 0;
  }
  if( p->db ){
    sqlite3_close(p->db);
    p->db = 0;
  }
  if( p->zErr && p->zErr!=p->zStaticErr ){
    sqlite3_free(p->zErr);
    p->zErr = 0;
  }
  test_barrier();
  p->completed++;
#ifndef SQLITE_OMIT_DEPRECATED
  sqlite3_thread_cleanup();
#endif
  return 0;
}

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
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







-
+













-
+
+

+







    return TCL_ERROR;
  }
  threadset[i].busy = 1;
  sqlite3_free(threadset[i].zFilename);
  threadset[i].zFilename = sqlite3_mprintf("%s", argv[2]);
  threadset[i].opnum = 1;
  threadset[i].completed = 0;
  rc = pthread_create(&x, 0, thread_main, &threadset[i]);
  rc = pthread_create(&x, 0, test_thread_main, &threadset[i]);
  if( rc ){
    Tcl_AppendResult(interp, "failed to create the thread", 0);
    sqlite3_free(threadset[i].zFilename);
    threadset[i].busy = 0;
    return TCL_ERROR;
  }
  pthread_detach(x);
  return TCL_OK;
}

/*
** Wait for a thread to reach its idle state.
*/
static void thread_wait(Thread *p){
static void test_thread_wait(Thread *p){
  test_barrier();
  while( p->opnum>p->completed ) sched_yield();
  test_barrier();
}

/*
** Usage:  thread_wait ID
**
** Wait on thread ID to reach its idle state.
*/
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
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







-
+






-
-
+
+


-
+







  }
  i = parse_thread_id(interp, argv[1]);
  if( i<0 ) return TCL_ERROR;
  if( !threadset[i].busy ){
    Tcl_AppendResult(interp, "no such thread", 0);
    return TCL_ERROR;
  }
  thread_wait(&threadset[i]);
  test_thread_wait(&threadset[i]);
  return TCL_OK;
}

/*
** Stop a thread.
*/
static void stop_thread(Thread *p){
  thread_wait(p);
static void test_stop_thread(Thread *p){
  test_thread_wait(p);
  p->xOp = 0;
  p->opnum++;
  thread_wait(p);
  test_thread_wait(p);
  sqlite3_free(p->zArg);
  p->zArg = 0;
  sqlite3_free(p->zFilename);
  p->zFilename = 0;
  p->busy = 0;
}

229
230
231
232
233
234
235
236

237
238
239
240
241
242
243
244
245

246
247
248
249
250
251
252
241
242
243
244
245
246
247

248
249
250
251
252
253
254
255
256

257
258
259
260
261
262
263
264







-
+








-
+







  if( argc!=2 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
       " ID", 0);
    return TCL_ERROR;
  }
  if( argv[1][0]=='*' && argv[1][1]==0 ){
    for(i=0; i<N_THREAD; i++){
      if( threadset[i].busy ) stop_thread(&threadset[i]);
      if( threadset[i].busy ) test_stop_thread(&threadset[i]);
    }
  }else{
    i = parse_thread_id(interp, argv[1]);
    if( i<0 ) return TCL_ERROR;
    if( !threadset[i].busy ){
      Tcl_AppendResult(interp, "no such thread", 0);
      return TCL_ERROR;
    }
    stop_thread(&threadset[i]);
    test_stop_thread(&threadset[i]);
  }
  return TCL_OK;
}

/*
** Usage: thread_argc  ID
**
269
270
271
272
273
274
275
276

277
278
279
280
281
282
283
281
282
283
284
285
286
287

288
289
290
291
292
293
294
295







-
+







  }
  i = parse_thread_id(interp, argv[1]);
  if( i<0 ) return TCL_ERROR;
  if( !threadset[i].busy ){
    Tcl_AppendResult(interp, "no such thread", 0);
    return TCL_ERROR;
  }
  thread_wait(&threadset[i]);
  test_thread_wait(&threadset[i]);
  sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", threadset[i].argc);
  Tcl_AppendResult(interp, zBuf, 0);
  return TCL_OK;
}

/*
** Usage: thread_argv  ID   N
302
303
304
305
306
307
308
309

310
311
312
313
314
315
316
314
315
316
317
318
319
320

321
322
323
324
325
326
327
328







-
+







  i = parse_thread_id(interp, argv[1]);
  if( i<0 ) return TCL_ERROR;
  if( !threadset[i].busy ){
    Tcl_AppendResult(interp, "no such thread", 0);
    return TCL_ERROR;
  }
  if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR;
  thread_wait(&threadset[i]);
  test_thread_wait(&threadset[i]);
  if( n<0 || n>=threadset[i].argc ){
    Tcl_AppendResult(interp, "column number out of range", 0);
    return TCL_ERROR;
  }
  Tcl_AppendResult(interp, threadset[i].argv[n], 0);
  return TCL_OK;
}
338
339
340
341
342
343
344
345

346
347
348
349
350
351
352
350
351
352
353
354
355
356

357
358
359
360
361
362
363
364







-
+







  i = parse_thread_id(interp, argv[1]);
  if( i<0 ) return TCL_ERROR;
  if( !threadset[i].busy ){
    Tcl_AppendResult(interp, "no such thread", 0);
    return TCL_ERROR;
  }
  if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR;
  thread_wait(&threadset[i]);
  test_thread_wait(&threadset[i]);
  if( n<0 || n>=threadset[i].argc ){
    Tcl_AppendResult(interp, "column number out of range", 0);
    return TCL_ERROR;
  }
  Tcl_AppendResult(interp, threadset[i].colv[n], 0);
  return TCL_OK;
}
373
374
375
376
377
378
379
380

381
382
383
384
385
386
387
385
386
387
388
389
390
391

392
393
394
395
396
397
398
399







-
+







  }
  i = parse_thread_id(interp, argv[1]);
  if( i<0 ) return TCL_ERROR;
  if( !threadset[i].busy ){
    Tcl_AppendResult(interp, "no such thread", 0);
    return TCL_ERROR;
  }
  thread_wait(&threadset[i]);
  test_thread_wait(&threadset[i]);
  zName = sqlite3ErrName(threadset[i].rc);
  Tcl_AppendResult(interp, zName, 0);
  return TCL_OK;
}

/*
** Usage: thread_error  ID
404
405
406
407
408
409
410
411

412
413
414
415
416
417
418
416
417
418
419
420
421
422

423
424
425
426
427
428
429
430







-
+







  }
  i = parse_thread_id(interp, argv[1]);
  if( i<0 ) return TCL_ERROR;
  if( !threadset[i].busy ){
    Tcl_AppendResult(interp, "no such thread", 0);
    return TCL_ERROR;
  }
  thread_wait(&threadset[i]);
  test_thread_wait(&threadset[i]);
  Tcl_AppendResult(interp, threadset[i].zErr, 0);
  return TCL_OK;
}

/*
** This procedure runs in the thread to compile an SQL statement.
*/
448
449
450
451
452
453
454
455

456
457
458

459
460
461
462
463
464
465
460
461
462
463
464
465
466

467
468
469
470
471
472
473
474
475
476
477
478







-
+



+







  }
  i = parse_thread_id(interp, argv[1]);
  if( i<0 ) return TCL_ERROR;
  if( !threadset[i].busy ){
    Tcl_AppendResult(interp, "no such thread", 0);
    return TCL_ERROR;
  }
  thread_wait(&threadset[i]);
  test_thread_wait(&threadset[i]);
  threadset[i].xOp = do_compile;
  sqlite3_free(threadset[i].zArg);
  threadset[i].zArg = sqlite3_mprintf("%s", argv[2]);
  test_barrier();
  threadset[i].opnum++;
  return TCL_OK;
}

/*
** This procedure runs in the thread to step the virtual machine.
*/
501
502
503
504
505
506
507
508

509

510
511
512
513
514
515
516
514
515
516
517
518
519
520

521
522
523
524
525
526
527
528
529
530







-
+

+







  }
  i = parse_thread_id(interp, argv[1]);
  if( i<0 ) return TCL_ERROR;
  if( !threadset[i].busy ){
    Tcl_AppendResult(interp, "no such thread", 0);
    return TCL_ERROR;
  }
  thread_wait(&threadset[i]);
  test_thread_wait(&threadset[i]);
  threadset[i].xOp = do_step;
  test_barrier();
  threadset[i].opnum++;
  return TCL_OK;
}

/*
** This procedure runs in the thread to finalize a virtual machine.
*/
543
544
545
546
547
548
549
550

551
552
553

554
555
556
557
558
559
560
557
558
559
560
561
562
563

564
565
566
567
568
569
570
571
572
573
574
575







-
+



+







  }
  i = parse_thread_id(interp, argv[1]);
  if( i<0 ) return TCL_ERROR;
  if( !threadset[i].busy ){
    Tcl_AppendResult(interp, "no such thread", 0);
    return TCL_ERROR;
  }
  thread_wait(&threadset[i]);
  test_thread_wait(&threadset[i]);
  threadset[i].xOp = do_finalize;
  sqlite3_free(threadset[i].zArg);
  threadset[i].zArg = 0;
  test_barrier();
  threadset[i].opnum++;
  return TCL_OK;
}

/*
** Usage: thread_swap ID ID
**
575
576
577
578
579
580
581
582

583
584
585
586
587
588
589

590
591
592
593
594
595
596
590
591
592
593
594
595
596

597
598
599
600
601
602
603

604
605
606
607
608
609
610
611







-
+






-
+







  }
  i = parse_thread_id(interp, argv[1]);
  if( i<0 ) return TCL_ERROR;
  if( !threadset[i].busy ){
    Tcl_AppendResult(interp, "no such thread", 0);
    return TCL_ERROR;
  }
  thread_wait(&threadset[i]);
  test_thread_wait(&threadset[i]);
  j = parse_thread_id(interp, argv[2]);
  if( j<0 ) return TCL_ERROR;
  if( !threadset[j].busy ){
    Tcl_AppendResult(interp, "no such thread", 0);
    return TCL_ERROR;
  }
  thread_wait(&threadset[j]);
  test_thread_wait(&threadset[j]);
  temp = threadset[i].db;
  threadset[i].db = threadset[j].db;
  threadset[j].db = temp;
  return TCL_OK;
}

/*
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







-
+







  }
  i = parse_thread_id(interp, argv[1]);
  if( i<0 ) return TCL_ERROR;
  if( !threadset[i].busy ){
    Tcl_AppendResult(interp, "no such thread", 0);
    return TCL_ERROR;
  }
  thread_wait(&threadset[i]);
  test_thread_wait(&threadset[i]);
  sqlite3TestMakePointerStr(interp, zBuf, threadset[i].db);
  threadset[i].db = 0;
  Tcl_AppendResult(interp, zBuf, (char*)0);
  return TCL_OK;
}

/*
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







-
+







  }
  i = parse_thread_id(interp, argv[1]);
  if( i<0 ) return TCL_ERROR;
  if( !threadset[i].busy ){
    Tcl_AppendResult(interp, "no such thread", 0);
    return TCL_ERROR;
  }
  thread_wait(&threadset[i]);
  test_thread_wait(&threadset[i]);
  assert( !threadset[i].db );
  threadset[i].db = (sqlite3*)sqlite3TestTextToPtr(argv[2]);
  return TCL_OK;
}

/*
** Usage: thread_stmt_get ID
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







-
+







  }
  i = parse_thread_id(interp, argv[1]);
  if( i<0 ) return TCL_ERROR;
  if( !threadset[i].busy ){
    Tcl_AppendResult(interp, "no such thread", 0);
    return TCL_ERROR;
  }
  thread_wait(&threadset[i]);
  test_thread_wait(&threadset[i]);
  sqlite3TestMakePointerStr(interp, zBuf, threadset[i].pStmt);
  threadset[i].pStmt = 0;
  Tcl_AppendResult(interp, zBuf, (char*)0);
  return TCL_OK;
}

/*

Changes to src/test6.c.

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
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







-
+
+


-
+
+


-
+
+








-
+
+







  return g.iDeviceCharacteristics;
}

/*
** Pass-throughs for WAL support.
*/
static int cfShmLock(sqlite3_file *pFile, int ofst, int n, int flags){
  return sqlite3OsShmLock(((CrashFile*)pFile)->pRealFile, ofst, n, flags);
  sqlite3_file *pReal = ((CrashFile*)pFile)->pRealFile;
  return pReal->pMethods->xShmLock(pReal, ofst, n, flags);
}
static void cfShmBarrier(sqlite3_file *pFile){
  sqlite3OsShmBarrier(((CrashFile*)pFile)->pRealFile);
  sqlite3_file *pReal = ((CrashFile*)pFile)->pRealFile;
  pReal->pMethods->xShmBarrier(pReal);
}
static int cfShmUnmap(sqlite3_file *pFile, int delFlag){
  return sqlite3OsShmUnmap(((CrashFile*)pFile)->pRealFile, delFlag);
  sqlite3_file *pReal = ((CrashFile*)pFile)->pRealFile;
  return pReal->pMethods->xShmUnmap(pReal, delFlag);
}
static int cfShmMap(
  sqlite3_file *pFile,            /* Handle open on database file */
  int iRegion,                    /* Region to retrieve */
  int sz,                         /* Size of regions */
  int w,                          /* True to extend file if necessary */
  void volatile **pp              /* OUT: Mapped memory */
){
  return sqlite3OsShmMap(((CrashFile*)pFile)->pRealFile, iRegion, sz, w, pp);
  sqlite3_file *pReal = ((CrashFile*)pFile)->pRealFile;
  return pReal->pMethods->xShmMap(pReal, iRegion, sz, w, pp);
}

static const sqlite3_io_methods CrashFileVtab = {
  2,                            /* iVersion */
  cfClose,                      /* xClose */
  cfRead,                       /* xRead */
  cfWrite,                      /* xWrite */

Changes to src/test8.c.

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







-
+







  sqlite3 *db 
){
  int rc = SQLITE_OK;

  if( pVtab->zTableName ){
    sqlite3_stmt *pStmt = 0;
    rc = sqlite3_prepare(db, 
        "SELECT sql FROM sqlite_master WHERE type = 'table' AND name = ?",
        "SELECT sql FROM sqlite_schema WHERE type = 'table' AND name = ?",
        -1, &pStmt, 0);
    if( rc==SQLITE_OK ){
      sqlite3_bind_text(pStmt, 1, pVtab->zTableName, -1, 0);
      if( sqlite3_step(pStmt)==SQLITE_ROW ){
        int rc2;
        const char *zCreateTable = (const char *)sqlite3_column_text(pStmt, 0);
        rc = sqlite3_declare_vtab(db, zCreateTable);
385
386
387
388
389
390
391

392
393
394
395
396
397
398
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399







+







  sqlite3_free(p);
  return 0;
}

typedef struct EchoModule EchoModule;
struct EchoModule {
  Tcl_Interp *interp;
  sqlite3 *db;
};

/*
** This function is called to do the work of the xConnect() method -
** to allocate the required in-memory structures for a newly connected
** virtual table.
*/
1348
1349
1350
1351
1352
1353
1354



1355
1356
1357
1358
1359
1360
1361
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365







+
+
+







/*
** Decode a pointer to an sqlite3 object.
*/
extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);
extern const char *sqlite3ErrName(int);

static void moduleDestroy(void *p){
  EchoModule *pMod = (EchoModule*)p;
  sqlite3_create_function(pMod->db, "function_that_does_not_exist_0982ma98",
                          SQLITE_ANY, 1, 0, 0, 0, 0);
  sqlite3_free(p);
}

/*
** Register the echo virtual table module.
*/
static int SQLITE_TCLAPI register_echo_module(
1372
1373
1374
1375
1376
1377
1378

1379
1380
1381
1382
1383
1384
1385
1386

1387
1388
1389
1390
1391
1392
1393
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399







+








+







    return TCL_ERROR;
  }
  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;

  /* Virtual table module "echo" */
  pMod = sqlite3_malloc(sizeof(EchoModule));
  pMod->interp = interp;
  pMod->db = db;
  rc = sqlite3_create_module_v2(
      db, "echo", &echoModule, (void*)pMod, moduleDestroy
  );

  /* Virtual table module "echo_v2" */
  if( rc==SQLITE_OK ){
    pMod = sqlite3_malloc(sizeof(EchoModule));
    pMod->interp = interp;
    pMod->db = db;
    rc = sqlite3_create_module_v2(db, "echo_v2", 
        &echoModuleV2, (void*)pMod, moduleDestroy
    );
  }

  Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
  return TCL_OK;

Changes to src/test_bestindex.c.

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
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







+



+








+








+
+
+
+
+
+
+







#if defined(INCLUDE_SQLITE_TCL_H)
#  include "sqlite_tcl.h"
#else
#  include "tcl.h"
#endif

#ifndef SQLITE_OMIT_VIRTUALTABLE


typedef struct tcl_vtab tcl_vtab;
typedef struct tcl_cursor tcl_cursor;
typedef struct TestFindFunction TestFindFunction;

/* 
** A fs virtual-table object 
*/
struct tcl_vtab {
  sqlite3_vtab base;
  Tcl_Interp *interp;
  Tcl_Obj *pCmd;
  TestFindFunction *pFindFunctionList;
  sqlite3 *db;
};

/* A tcl cursor object */
struct tcl_cursor {
  sqlite3_vtab_cursor base;
  sqlite3_stmt *pStmt;            /* Read data from here */
};

struct TestFindFunction {
  tcl_vtab *pTab;
  const char *zName;
  TestFindFunction *pNext;
};


/*
** Dequote string z in place.
*/
static void tclDequote(char *z){
  char q = z[0];

219
220
221
222
223
224
225





226
227
228
229
230
231
232
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247







+
+
+
+
+







  *ppVtab = &pTab->base;
  return rc;
}

/* The xDisconnect and xDestroy methods are also the same */
static int tclDisconnect(sqlite3_vtab *pVtab){
  tcl_vtab *pTab = (tcl_vtab*)pVtab;
  while( pTab->pFindFunctionList ){
    TestFindFunction *p = pTab->pFindFunctionList;
    pTab->pFindFunctionList = p->pNext;
    sqlite3_free(p);
  }
  Tcl_DecrRefCount(pTab->pCmd);
  sqlite3_free(pTab);
  return SQLITE_OK;
}

/*
** Open a new tcl cursor.
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







+

+
+
+
+
+
+
+
+
+
+
+
+
+








  pArg = Tcl_NewObj();
  Tcl_IncrRefCount(pArg);
  for(ii=0; ii<argc; ii++){
    const char *zVal = (const char*)sqlite3_value_text(argv[ii]);
    Tcl_Obj *pVal;
    if( zVal==0 ){
      sqlite3_value *pMem;
      pVal = Tcl_NewObj();
      for(rc=sqlite3_vtab_in_first(argv[ii], &pMem); 
          rc==SQLITE_OK && pMem;
          rc=sqlite3_vtab_in_next(argv[ii], &pMem)
      ){
        Tcl_Obj *pVal2 = 0;
        zVal = (const char*)sqlite3_value_text(pMem);
        if( zVal ){
          pVal2 = Tcl_NewStringObj(zVal, -1);
        }else{
          pVal2 = Tcl_NewObj();
        }
        Tcl_ListObjAppendElement(interp, pVal, pVal2);
      }
    }else{
      pVal = Tcl_NewStringObj(zVal, -1);
    }
    Tcl_ListObjAppendElement(interp, pArg, pVal);
  }
  Tcl_ListObjAppendElement(interp, pScript, pArg);
  Tcl_DecrRefCount(pArg);
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
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







-
+
-
-
-
+
+
-
+

-
-
-
-
-
-
-
-
+
+



-
+







}

static int tclEof(sqlite3_vtab_cursor *pVtabCursor){
  tcl_cursor *pCsr = (tcl_cursor*)pVtabCursor;
  return (pCsr->pStmt==0);
}

static int tclBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
static void testBestIndexObjConstraints(
  tcl_vtab *pTab = (tcl_vtab*)tab;
  Tcl_Interp *interp = pTab->interp;
  Tcl_Obj *pArg;
  Tcl_Interp *interp, 
  sqlite3_index_info *pIdxInfo
  Tcl_Obj *pScript;
){
  int ii;
  int rc = SQLITE_OK;

  pScript = Tcl_DuplicateObj(pTab->pCmd);
  Tcl_IncrRefCount(pScript);
  Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj("xBestIndex", -1));

  pArg = Tcl_NewObj();
  Tcl_IncrRefCount(pArg);
  Tcl_Obj *pRes = Tcl_NewObj();
  Tcl_IncrRefCount(pRes);
  for(ii=0; ii<pIdxInfo->nConstraint; ii++){
    struct sqlite3_index_constraint const *pCons = &pIdxInfo->aConstraint[ii];
    Tcl_Obj *pElem = Tcl_NewObj();
    const char *zOp = "?";
    const char *zOp = 0;

    Tcl_IncrRefCount(pElem);

    switch( pCons->op ){
      case SQLITE_INDEX_CONSTRAINT_EQ:
        zOp = "eq"; break;
      case SQLITE_INDEX_CONSTRAINT_GT:
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
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
638
639
640
641







+
+
+
+



+
-
+
+
+
+





-
+



-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+










-
+



-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+
+

+

+







        zOp = "isnot"; break;
      case SQLITE_INDEX_CONSTRAINT_ISNOTNULL:
        zOp = "isnotnull"; break;
      case SQLITE_INDEX_CONSTRAINT_ISNULL:
        zOp = "isnull"; break;
      case SQLITE_INDEX_CONSTRAINT_IS:
        zOp = "is"; break;
      case SQLITE_INDEX_CONSTRAINT_LIMIT:
        zOp = "limit"; break;
      case SQLITE_INDEX_CONSTRAINT_OFFSET:
        zOp = "offset"; break;
    }

    Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("op", -1));
    if( zOp ){
    Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj(zOp, -1));
      Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj(zOp, -1));
    }else{
      Tcl_ListObjAppendElement(0, pElem, Tcl_NewIntObj(pCons->op));
    }
    Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("column", -1));
    Tcl_ListObjAppendElement(0, pElem, Tcl_NewIntObj(pCons->iColumn));
    Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("usable", -1));
    Tcl_ListObjAppendElement(0, pElem, Tcl_NewIntObj(pCons->usable));

    Tcl_ListObjAppendElement(0, pArg, pElem);
    Tcl_ListObjAppendElement(0, pRes, pElem);
    Tcl_DecrRefCount(pElem);
  }

  Tcl_ListObjAppendElement(0, pScript, pArg);
  Tcl_DecrRefCount(pArg);

  pArg = Tcl_NewObj();
  Tcl_IncrRefCount(pArg);
  Tcl_SetObjResult(interp, pRes);
  Tcl_DecrRefCount(pRes);
}

static void testBestIndexObjOrderby(
  Tcl_Interp *interp, 
  sqlite3_index_info *pIdxInfo
){
  int ii;
  Tcl_Obj *pRes = Tcl_NewObj();
  Tcl_IncrRefCount(pRes);
  for(ii=0; ii<pIdxInfo->nOrderBy; ii++){
    struct sqlite3_index_orderby const *pOrder = &pIdxInfo->aOrderBy[ii];
    Tcl_Obj *pElem = Tcl_NewObj();
    Tcl_IncrRefCount(pElem);

    Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("column", -1));
    Tcl_ListObjAppendElement(0, pElem, Tcl_NewIntObj(pOrder->iColumn));
    Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("desc", -1));
    Tcl_ListObjAppendElement(0, pElem, Tcl_NewIntObj(pOrder->desc));

    Tcl_ListObjAppendElement(0, pArg, pElem);
    Tcl_ListObjAppendElement(0, pRes, pElem);
    Tcl_DecrRefCount(pElem);
  }

  Tcl_ListObjAppendElement(0, pScript, pArg);
  Tcl_DecrRefCount(pArg);
  Tcl_SetObjResult(interp, pRes);
  Tcl_DecrRefCount(pRes);
}

/*
** Implementation of the handle passed to each xBestIndex callback. This
** object features the following sub-commands:
**
**    $hdl constraints
**    $hdl orderby
**    $hdl mask
**
**    $hdl distinct
**      Return the result (an integer) of calling sqlite3_vtab_distinct()
**      on the index-info structure.
**
**    $hdl in IDX BOOLEAN
**      Wrapper around sqlite3_vtab_in(). Returns an integer.
**
**    $hdl rhs_value IDX ?DEFAULT?
**      Wrapper around sqlite3_vtab_rhs_value().
*/
static int SQLITE_TCLAPI testBestIndexObj(
  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 */
){
  const char *azSub[] = {
    "constraints",                /* 0 */
    "orderby",                    /* 1 */
    "mask",                       /* 2 */
    "distinct",                   /* 3 */
    "in",                         /* 4 */
    "rhs_value",                  /* 5 */
    0
  };
  int ii;
  sqlite3_index_info *pIdxInfo = (sqlite3_index_info*)clientData;

  if( objc<2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND");
    return TCL_ERROR;
  }
  if( Tcl_GetIndexFromObj(interp, objv[1], azSub, "sub-command", 0, &ii) ){
    return TCL_ERROR;
  }

  if( ii<4 && objc!=2 ){
    Tcl_WrongNumArgs(interp, 2, objv, "");
    return TCL_ERROR;
  }
  if( ii==4 && objc!=4 ){
    Tcl_WrongNumArgs(interp, 2, objv, "INDEX BOOLEAN");
    return TCL_ERROR;
  }
  if( ii==5 && objc!=3 && objc!=4 ){
    Tcl_WrongNumArgs(interp, 2, objv, "INDEX ?DEFAULT?");
    return TCL_ERROR;
  }

  switch( ii ){
    case 0: assert( sqlite3_stricmp(azSub[ii], "constraints")==0 );
      testBestIndexObjConstraints(interp, pIdxInfo);
      break;

    case 1: assert( sqlite3_stricmp(azSub[ii], "orderby")==0 );
      testBestIndexObjOrderby(interp, pIdxInfo);
      break;

    case 2: assert( sqlite3_stricmp(azSub[ii], "mask")==0 );
      Tcl_SetObjResult(interp, Tcl_NewWideIntObj(pIdxInfo->colUsed));
      break;

    case 3: assert( sqlite3_stricmp(azSub[ii], "distinct")==0 ); {
      int bDistinct = sqlite3_vtab_distinct(pIdxInfo);
      Tcl_SetObjResult(interp, Tcl_NewIntObj(bDistinct));
      break;
    }

    case 4: assert( sqlite3_stricmp(azSub[ii], "in")==0 ); {
      int iCons;
      int bHandle;
      if( Tcl_GetIntFromObj(interp, objv[2], &iCons) 
       || Tcl_GetBooleanFromObj(interp, objv[3], &bHandle) 
      ){
        return TCL_ERROR;
      }
      Tcl_SetObjResult(interp, 
          Tcl_NewIntObj(sqlite3_vtab_in(pIdxInfo, iCons, bHandle))
      );
      break;
    }

    case 5: assert( sqlite3_stricmp(azSub[ii], "rhs_value")==0 ); {
      int iCons = 0;
      int rc;
      sqlite3_value *pVal = 0;
      const char *zVal = "";
      if( Tcl_GetIntFromObj(interp, objv[2], &iCons) ){
        return TCL_ERROR;
      }
      rc = sqlite3_vtab_rhs_value(pIdxInfo, iCons, &pVal);
      if( rc!=SQLITE_OK && rc!=SQLITE_NOTFOUND ){
        Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
        return TCL_ERROR;
      }
      if( pVal ){
        zVal = (const char*)sqlite3_value_text(pVal);
      }else if( objc==4 ){
        zVal = Tcl_GetString(objv[3]);
      }
      Tcl_SetObjResult(interp, Tcl_NewStringObj(zVal, -1));
      break;
    }
  }

  return TCL_OK;
}

static int tclBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
  tcl_vtab *pTab = (tcl_vtab*)tab;
  Tcl_Interp *interp = pTab->interp;
  int rc = SQLITE_OK;

  static int iNext = 43;
  char zHdl[24];
  Tcl_Obj *pScript;

  pScript = Tcl_DuplicateObj(pTab->pCmd);
  Tcl_IncrRefCount(pScript);
  Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj("xBestIndex", -1));

  Tcl_ListObjAppendElement(0, pScript, Tcl_NewWideIntObj(pIdxInfo->colUsed));

  sqlite3_snprintf(sizeof(zHdl), zHdl, "bestindex%d", iNext++);
  Tcl_CreateObjCommand(interp, zHdl, testBestIndexObj, pIdxInfo, 0);
  Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj(zHdl, -1));
  rc = Tcl_EvalObjEx(interp, pScript, TCL_EVAL_GLOBAL);
  Tcl_DeleteCommand(interp, zHdl);
  Tcl_DecrRefCount(pScript);

  if( rc!=TCL_OK ){
    const char *zErr = Tcl_GetStringResult(interp);
    rc = SQLITE_ERROR;
    pTab->base.zErrMsg = sqlite3_mprintf("%s", zErr);
  }else{
    /* Analyze the scripts return value. The return value should be a tcl 
    ** list object with an even number of elements. The first element of each
485
486
487
488
489
490
491

492
493
494
495
496
497
498
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668







+







    int nElem;
    rc = Tcl_ListObjGetElements(interp, pRes, &nElem, &apElem);
    if( rc!=TCL_OK ){
      const char *zErr = Tcl_GetStringResult(interp);
      rc = SQLITE_ERROR;
      pTab->base.zErrMsg = sqlite3_mprintf("%s", zErr);
    }else{
      int ii;
      int iArgv = 1;
      for(ii=0; rc==SQLITE_OK && ii<nElem; ii+=2){
        const char *zCmd = Tcl_GetString(apElem[ii]);
        Tcl_Obj *p = apElem[ii+1];
        if( sqlite3_stricmp("cost", zCmd)==0 ){
          rc = Tcl_GetDoubleFromObj(interp, p, &pIdxInfo->estimatedCost);
        }else
537
538
539
540
541
542
543













































































544
545
546
547
548
549
550
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
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







        }
      }
    }
  }

  return rc;
}

static void tclFunction(sqlite3_context *pCtx, int nArg, sqlite3_value **apArg){
  TestFindFunction *p = (TestFindFunction*)sqlite3_user_data(pCtx);
  Tcl_Interp *interp = p->pTab->interp;
  Tcl_Obj *pScript = 0;
  Tcl_Obj *pRet = 0;
  int ii;

  pScript = Tcl_DuplicateObj(p->pTab->pCmd);
  Tcl_IncrRefCount(pScript);
  Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj("function", -1));
  Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj(p->zName, -1));

  for(ii=0; ii<nArg; ii++){
    const char *zArg = (const char*)sqlite3_value_text(apArg[ii]);
    Tcl_ListObjAppendElement(interp, pScript,
        (zArg ? Tcl_NewStringObj(zArg, -1) : Tcl_NewObj())
    );
  }
  Tcl_EvalObjEx(interp, pScript, TCL_EVAL_GLOBAL);
  Tcl_DecrRefCount(pScript);

  pRet = Tcl_GetObjResult(interp);
  sqlite3_result_text(pCtx, Tcl_GetString(pRet), -1, SQLITE_TRANSIENT);
}

static int tclFindFunction(
  sqlite3_vtab *tab, 
  int nArg, 
  const char *zName,
  void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),   /* OUT */
  void **ppArg                                             /* OUT */
){
  int iRet = 0;
  tcl_vtab *pTab = (tcl_vtab*)tab;
  Tcl_Interp *interp = pTab->interp;
  Tcl_Obj *pScript = 0;
  int rc = SQLITE_OK;

  pScript = Tcl_DuplicateObj(pTab->pCmd);
  Tcl_IncrRefCount(pScript);
  Tcl_ListObjAppendElement(
      interp, pScript, Tcl_NewStringObj("xFindFunction", -1)
  );
  Tcl_ListObjAppendElement(interp, pScript, Tcl_NewIntObj(nArg));
  Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj(zName, -1));
  rc = Tcl_EvalObjEx(interp, pScript, TCL_EVAL_GLOBAL);
  Tcl_DecrRefCount(pScript);

  if( rc==SQLITE_OK ){
    Tcl_Obj *pObj = Tcl_GetObjResult(interp);

    if( Tcl_GetIntFromObj(interp, pObj, &iRet) ){
      rc = SQLITE_ERROR;
    }else if( iRet>0 ){
      sqlite3_int64 nName = strlen(zName);
      sqlite3_int64 nByte = nName + 1 + sizeof(TestFindFunction);
      TestFindFunction *pNew = 0;

      pNew = (TestFindFunction*)sqlite3_malloc64(nByte);
      if( pNew==0 ){
        iRet = 0;
      }else{
        memset(pNew, 0, nByte);
        pNew->zName = (const char*)&pNew[1];
        memcpy((char*)pNew->zName, zName, nName);
        pNew->pTab = pTab;
        pNew->pNext = pTab->pFindFunctionList;
        pTab->pFindFunctionList = pNew;
        *ppArg = (void*)pNew;
        *pxFunc = tclFunction;
      }
    }
  }

  return iRet;
}

/*
** A virtual table module that provides read-only access to a
** Tcl global variable namespace.
*/
static sqlite3_module tclModule = {
  0,                         /* iVersion */
561
562
563
564
565
566
567
568

569
570
571
572
573
574
575
808
809
810
811
812
813
814

815
816
817
818
819
820
821
822







-
+







  tclColumn,                    /* xColumn - read data */
  tclRowid,                     /* xRowid - read data */
  0,                           /* xUpdate */
  0,                           /* xBegin */
  0,                           /* xSync */
  0,                           /* xCommit */
  0,                           /* xRollback */
  0,                           /* xFindMethod */
  tclFindFunction,             /* xFindFunction */
  0,                           /* xRename */
};

/*
** Decode a pointer to an sqlite3 object.
*/
extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);

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

144
145
146
147
148
149
150
151

152
153
154
155






156
157
158
159
160
161
162
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







-
+




+
+
+
+
+
+








#ifdef SQLITE_ENABLE_HIDDEN_COLUMNS
  Tcl_SetVar2(interp, "sqlite_options", "hiddencolumns", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "hiddencolumns", "0", TCL_GLOBAL_ONLY);
#endif

#ifdef SQLITE_ENABLE_DESERIALIZE
#ifndef SQLITE_OMIT_DESERIALIZE
  Tcl_SetVar2(interp, "sqlite_options", "deserialize", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "deserialize", "0", TCL_GLOBAL_ONLY);
#endif

#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
  Tcl_SetVar2(interp, "sqlite_options", "mathlib", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "mathlib", "0", TCL_GLOBAL_ONLY);
#endif

#ifdef SQLITE_ENABLE_MEMSYS3
  Tcl_SetVar2(interp, "sqlite_options", "mem3", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "mem3", "0", TCL_GLOBAL_ONLY);
#endif

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
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







-
+
+
+
+
+
+
+





-
-
-

-








#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_JSON1
#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

#ifndef SQLITE_OMIT_JSON
  Tcl_SetVar2(interp, "sqlite_options", "json1", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "json1", "0", TCL_GLOBAL_ONLY);
#endif

#ifdef SQLITE_HAS_CODEC
  Tcl_SetVar2(interp, "sqlite_options", "has_codec", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "has_codec", "0", TCL_GLOBAL_ONLY);
#endif

#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
  Tcl_SetVar2(interp, "sqlite_options", "like_match_blobs", "0", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "like_match_blobs", "1", TCL_GLOBAL_ONLY);
#endif

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
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







-
+










-
-
-
-
-
-








#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
  Tcl_SetVar2(interp, "sqlite_options", "schema_version", "0", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "schema_version", "1", TCL_GLOBAL_ONLY);
#endif

#ifdef SQLITE_ENABLE_SESSION
#if defined(SQLITE_ENABLE_SESSION) && defined(SQLITE_ENABLE_PREUPDATE_HOOK)
  Tcl_SetVar2(interp, "sqlite_options", "session", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "session", "0", TCL_GLOBAL_ONLY);
#endif

#ifdef SQLITE_ENABLE_STAT4
  Tcl_SetVar2(interp, "sqlite_options", "stat4", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "stat4", "0", TCL_GLOBAL_ONLY);
#endif
#if defined(SQLITE_ENABLE_STAT3) && !defined(SQLITE_ENABLE_STAT4)
  Tcl_SetVar2(interp, "sqlite_options", "stat3", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "stat3", "0", TCL_GLOBAL_ONLY);
#endif

#if defined(SQLITE_ENABLE_STMTVTAB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
  Tcl_SetVar2(interp, "sqlite_options", "stmtvtab", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "stmtvtab", "0", TCL_GLOBAL_ONLY);
#endif

#ifdef SQLITE_ENABLE_STMT_SCANSTATUS

Changes to src/test_demovfs.c.

236
237
238
239
240
241
242



243
244
245
246
247
248
249
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252







+
+
+







    return SQLITE_IOERR_READ;
  }
  nRead = read(p->fd, zBuf, iAmt);

  if( nRead==iAmt ){
    return SQLITE_OK;
  }else if( nRead>=0 ){
    if( nRead<iAmt ){
      memset(&((char*)zBuf)[nRead], 0, iAmt-nRead);
    }
    return SQLITE_IOERR_SHORT_READ;
  }

  return SQLITE_IOERR_READ;
}

/*
365
366
367
368
369
370
371
372

373
374
375
376
377
378
379
368
369
370
371
372
373
374

375
376
377
378
379
380
381
382







-
+







  return SQLITE_OK;
}

/*
** No xFileControl() verbs are implemented by this VFS.
*/
static int demoFileControl(sqlite3_file *pFile, int op, void *pArg){
  return SQLITE_OK;
  return SQLITE_NOTFOUND;
}

/*
** The xSectorSize() and xDeviceCharacteristics() methods. These two
** may return special values allowing SQLite to optimize file-system 
** access to some extent. But it is also safe to simply return 0.
*/
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
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







-
+





-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+







  int rc;                         /* Return code */

  rc = unlink(zPath);
  if( rc!=0 && errno==ENOENT ) return SQLITE_OK;

  if( rc==0 && dirSync ){
    int dfd;                      /* File descriptor open on directory */
    int i;                        /* Iterator variable */
    char *zSlash;
    char zDir[MAXPATHNAME+1];     /* Name of directory containing file zPath */

    /* Figure out the directory name from the path of the file deleted. */
    sqlite3_snprintf(MAXPATHNAME, zDir, "%s", zPath);
    zDir[MAXPATHNAME] = '\0';
    for(i=strlen(zDir); i>1 && zDir[i]!='/'; i++);
    zDir[i] = '\0';

    /* Open a file-descriptor on the directory. Sync. Close. */
    dfd = open(zDir, O_RDONLY, 0);
    if( dfd<0 ){
      rc = -1;
    }else{
      rc = fsync(dfd);
      close(dfd);
    zSlash = strrchr(zDir,'/');
    if( zSlash ){
      /* Open a file-descriptor on the directory. Sync. Close. */
      zSlash[0] = 0;
      dfd = open(zDir, O_RDONLY, 0);
      if( dfd<0 ){
        rc = -1;
      }else{
        rc = fsync(dfd);
        close(dfd);
      }
    }
  }
  return (rc==0 ? SQLITE_OK : SQLITE_IOERR_DELETE);
}

#ifndef F_OK
# define F_OK 0

Changes to src/test_devsym.c.

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
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







-
+









-
+



-
+



-
+







}

/*
** Shared-memory methods are all pass-thrus.
*/
static int devsymShmLock(sqlite3_file *pFile, int ofst, int n, int flags){
  devsym_file *p = (devsym_file *)pFile;
  return sqlite3OsShmLock(p->pReal, ofst, n, flags);
  return p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags);
}
static int devsymShmMap(
  sqlite3_file *pFile, 
  int iRegion, 
  int szRegion, 
  int isWrite, 
  void volatile **pp
){
  devsym_file *p = (devsym_file *)pFile;
  return sqlite3OsShmMap(p->pReal, iRegion, szRegion, isWrite, pp);
  return p->pReal->pMethods->xShmMap(p->pReal, iRegion, szRegion, isWrite, pp);
}
static void devsymShmBarrier(sqlite3_file *pFile){
  devsym_file *p = (devsym_file *)pFile;
  sqlite3OsShmBarrier(p->pReal);
  p->pReal->pMethods->xShmBarrier(p->pReal);
}
static int devsymShmUnmap(sqlite3_file *pFile, int delFlag){
  devsym_file *p = (devsym_file *)pFile;
  return sqlite3OsShmUnmap(p->pReal, delFlag);
  return p->pReal->pMethods->xShmUnmap(p->pReal, delFlag);
}



/*
** Open an devsym file handle.
*/
501
502
503
504
505
506
507

508
509
510
511
512
513
514
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515







+







  }else{
    g.iSectorSize = 512;
  }
}

void devsym_unregister(){
  sqlite3_vfs_unregister(&devsym_vfs);
  sqlite3_vfs_unregister(&writecrash_vfs);
  g.pVfs = 0;
  g.iDeviceChar = 0;
  g.iSectorSize = 0;
}

void devsym_crash_on_write(int nWrite){
  if( g.pVfs==0 ){

Changes to src/test_fs.c.

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







-
+







};

struct FsdirCsr {
  sqlite3_vtab_cursor base;
  char *zDir;                     /* Buffer containing directory scanned */
  DIR *pDir;                      /* Open directory */
  sqlite3_int64 iRowid;
  struct DIRENT entry;            /* Current entry */
  struct DIRENT *pEntry;
};

/*
** This function is the implementation of both the xConnect and xCreate
** methods of the fsdir virtual table.
**
** The argv[] array contains the following:
232
233
234
235
236
237
238
239
240
241
242


243
244
245
246
247
248
249
250
251
252
253
254
255
232
233
234
235
236
237
238




239
240






241
242
243
244
245
246
247







-
-
-
-
+
+
-
-
-
-
-
-







/*
** Skip the cursor to the next entry.
*/
static int fsdirNext(sqlite3_vtab_cursor *cur){
  FsdirCsr *pCsr = (FsdirCsr*)cur;

  if( pCsr->pDir ){
    struct DIRENT *pRes = 0;
#if defined(__MINGW_H)
    pRes = readdir(pCsr->pDir);
    if( pRes!=0 ){
    pCsr->pEntry = readdir(pCsr->pDir);
    if( pCsr->pEntry==0 ){
      memcpy(&pCsr->entry, pRes, sizeof(struct DIRENT));
    }
#else
    readdir_r(pCsr->pDir, &pCsr->entry, &pRes);
#endif
    if( pRes==0 ){
      closedir(pCsr->pDir);
      pCsr->pDir = 0;
    }
    pCsr->iRowid++;
  }

  return SQLITE_OK;
304
305
306
307
308
309
310
311

312
313
314
315
316
317
318
296
297
298
299
300
301
302

303
304
305
306
307
308
309
310







-
+







  FsdirCsr *pCsr = (FsdirCsr*)cur;
  switch( i ){
    case 0: /* dir */
      sqlite3_result_text(ctx, pCsr->zDir, -1, SQLITE_STATIC);
      break;

    case 1: /* name */
      sqlite3_result_text(ctx, pCsr->entry.d_name, -1, SQLITE_TRANSIENT);
      sqlite3_result_text(ctx, pCsr->pEntry->d_name, -1, SQLITE_TRANSIENT);
      break;

    default:
      assert( 0 );
  }

  return SQLITE_OK;
740
741
742
743
744
745
746
747

748
749
750
751
752
753
754
732
733
734
735
736
737
738

739
740
741
742
743
744
745
746







-
+








    int n;
    fd = open(zFile, O_RDONLY);
    if( fd<0 ) return SQLITE_IOERR;
    fstat(fd, &sbuf);

    if( sbuf.st_size>=pCur->nAlloc ){
      int nNew = sbuf.st_size*2;
      sqlite3_int64 nNew = sbuf.st_size*2;
      char *zNew;
      if( nNew<1024 ) nNew = 1024;

      zNew = sqlite3Realloc(pCur->zBuf, nNew);
      if( zNew==0 ){
        close(fd);
        return SQLITE_NOMEM;

Changes to src/test_func.c.

495
496
497
498
499
500
501
502


503
504
505
506
507
508
509
495
496
497
498
499
500
501

502
503
504
505
506
507
508
509
510







-
+
+







    u64 iSerialType;
    Mem mem;

    memset(&mem, 0, sizeof(mem));
    mem.db = db;
    mem.enc = ENC(db);
    pHdr += sqlite3GetVarint(pHdr, &iSerialType);
    pBody += sqlite3VdbeSerialGet(pBody, (u32)iSerialType, &mem);
    sqlite3VdbeSerialGet(pBody, (u32)iSerialType, &mem);
    pBody += sqlite3VdbeSerialTypeLen((u32)iSerialType);

    if( iCurrent==iIdx ){
      sqlite3_result_value(context, &mem);
    }

    if( mem.szMalloc ) sqlite3DbFree(db, mem.zMalloc);
  }
543
544
545
546
547
548
549
550


551
552
553
554
555
556
557
544
545
546
547
548
549
550

551
552
553
554
555
556
557
558
559







-
+
+







    u64 iSerialType;
    Mem mem;

    memset(&mem, 0, sizeof(mem));
    mem.db = db;
    mem.enc = ENC(db);
    pHdr += sqlite3GetVarint(pHdr, &iSerialType);
    pBody += sqlite3VdbeSerialGet(pBody, (u32)iSerialType, &mem);
    sqlite3VdbeSerialGet(pBody, (u32)iSerialType, &mem);
    pBody += sqlite3VdbeSerialTypeLen((u32)iSerialType);

    switch( sqlite3_value_type(&mem) ){
      case SQLITE_TEXT:
        pVal = Tcl_NewStringObj((const char*)sqlite3_value_text(&mem), -1);
        break;

      case SQLITE_BLOB: {
625
626
627
628
629
630
631


















632
633
634
635
636
637
638
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







static void test_getsubtype(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  sqlite3_result_int(context, (int)sqlite3_value_subtype(argv[0]));
}

/*         test_frombind(A,B,C,...)
**
** Return an integer bitmask that has a bit set for every argument
** (up to the first 63 arguments) that originates from a bind a parameter.
*/
static void test_frombind(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  sqlite3_uint64 m = 0;
  int i;
  for(i=0; i<argc && i<63; i++){
    if( sqlite3_value_frombind(argv[i]) ) m |= ((sqlite3_uint64)1)<<i;
  }
  sqlite3_result_int64(context, (sqlite3_int64)m);
}

/*         test_setsubtype(V, T)
**
** Return the value V with its subtype changed to T
*/
static void test_setsubtype(
  sqlite3_context *context,
671
672
673
674
675
676
677

678
679
680
681
682
683
684
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705







+







    { "test_counter",          1, SQLITE_UTF8, counterFunc},
    { "real2hex",              1, SQLITE_UTF8, real2hex},
    { "test_decode",           1, SQLITE_UTF8, test_decode},
    { "test_extract",          2, SQLITE_UTF8, test_extract},
    { "test_zeroblob",  1, SQLITE_UTF8|SQLITE_DETERMINISTIC, test_zeroblob},
    { "test_getsubtype",       1, SQLITE_UTF8, test_getsubtype},
    { "test_setsubtype",       2, SQLITE_UTF8, test_setsubtype},
    { "test_frombind",        -1, SQLITE_UTF8, test_frombind},
  };
  int i;

  for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
    sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg,
        aFuncs[i].eTextRep, 0, aFuncs[i].xFunc, 0, 0);
  }

Changes to src/test_hexio.c.

164
165
166
167
168
169
170
171

172
173
174
175
176
177
178
164
165
166
167
168
169
170

171
172
173
174
175
176
177
178







-
+







  if( objc!=4 ){
    Tcl_WrongNumArgs(interp, 1, objv, "FILENAME OFFSET HEXDATA");
    return TCL_ERROR;
  }
  if( Tcl_GetIntFromObj(interp, objv[2], &offset) ) return TCL_ERROR;
  zFile = Tcl_GetString(objv[1]);
  zIn = (const unsigned char *)Tcl_GetStringFromObj(objv[3], &nIn);
  aOut = sqlite3_malloc( nIn/2 );
  aOut = sqlite3_malloc( 1 + nIn/2 );
  if( aOut==0 ){
    return TCL_ERROR;
  }
  nOut = sqlite3TestHexToBin(zIn, nIn, aOut);
  out = fopen(zFile, "r+b");
  if( out==0 ){
    out = fopen(zFile, "r+");
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
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







-
+
















+

-
-
+
+
+
+
+
+
+
+
+


-
-
+
+











+
+
+
-
+
+







  sqlite3_free(aOut);
  fclose(out);
  Tcl_SetObjResult(interp, Tcl_NewIntObj(written));
  return TCL_OK;
}

/*
** USAGE:   hexio_get_int   HEXDATA
** USAGE:   hexio_get_int [-littleendian] HEXDATA
**
** Interpret the HEXDATA argument as a big-endian integer.  Return
** the value of that integer.  HEXDATA can contain between 2 and 8
** hexadecimal digits.
*/
static int SQLITE_TCLAPI hexio_get_int(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  int val;
  int nIn, nOut;
  const unsigned char *zIn;
  unsigned char *aOut;
  unsigned char aNum[4];
  int bLittle = 0;

  if( objc!=2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "HEXDATA");
  if( objc==3 ){
    int n;
    char *z = Tcl_GetStringFromObj(objv[1], &n);
    if( n>=2 && n<=13 && memcmp(z, "-littleendian", n)==0 ){
      bLittle = 1;
    }
  }
  if( (objc-bLittle)!=2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "[-littleendian] HEXDATA");
    return TCL_ERROR;
  }
  zIn = (const unsigned char *)Tcl_GetStringFromObj(objv[1], &nIn);
  aOut = sqlite3_malloc( nIn/2 );
  zIn = (const unsigned char *)Tcl_GetStringFromObj(objv[1+bLittle], &nIn);
  aOut = sqlite3_malloc( 1 + nIn/2 );
  if( aOut==0 ){
    return TCL_ERROR;
  }
  nOut = sqlite3TestHexToBin(zIn, nIn, aOut);
  if( nOut>=4 ){
    memcpy(aNum, aOut, 4);
  }else{
    memset(aNum, 0, sizeof(aNum));
    memcpy(&aNum[4-nOut], aOut, nOut);
  }
  sqlite3_free(aOut);
  if( bLittle ){
    val = (aNum[3]<<24) | (aNum[2]<<16) | (aNum[1]<<8) | aNum[0];
  }else{
  val = (aNum[0]<<24) | (aNum[1]<<16) | (aNum[2]<<8) | aNum[3];
    val = (aNum[0]<<24) | (aNum[1]<<16) | (aNum[2]<<8) | aNum[3];
  }
  Tcl_SetObjResult(interp, Tcl_NewIntObj(val));
  return TCL_OK;
}


/*
** USAGE:   hexio_render_int16   INTEGER
305
306
307
308
309
310
311
312

313
314
315
316
317
318
319
317
318
319
320
321
322
323

324
325
326
327
328
329
330
331







-
+







  const unsigned char *zOrig;
  unsigned char *z;
  if( objc!=2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "HEX");
    return TCL_ERROR;
  }
  zOrig = (unsigned char *)Tcl_GetStringFromObj(objv[1], &n);
  z = sqlite3_malloc( n+3 );
  z = sqlite3_malloc( n+4 );
  n = sqlite3TestHexToBin(zOrig, n, z);
  z[n] = 0;
  nOut = sqlite3Utf8To8(z);
  sqlite3TestBinToHex(z,nOut);
  Tcl_AppendResult(interp, (char*)z, 0);
  sqlite3_free(z);
  return TCL_OK;
333
334
335
336
337
338
339











340
341
342
343
344
345
346
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







+
+
+
+
+
+
+
+
+
+
+







    y <<= 7;
  }
  x += y * (*q++);
  *v = (sqlite_int64) x;
  return (int) (q - (unsigned char *)p);
}

static int putFts3Varint(char *p, sqlite_int64 v){
  unsigned char *q = (unsigned char *) p;
  sqlite_uint64 vu = v;
  do{
    *q++ = (unsigned char) ((vu & 0x7f) | 0x80);
    vu >>= 7;
  }while( vu!=0 );
  q[-1] &= 0x7f;  /* turn off high bit in final byte */
  assert( q - (unsigned char *)p <= 10 );
  return (int) (q - (unsigned char *)p);
}

/*
** USAGE:  read_fts3varint BLOB VARNAME
**
** Read a varint from the start of BLOB. Set variable VARNAME to contain
** the interpreted value. Return the number of bytes of BLOB consumed.
*/
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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
















+








  nVal = getFts3Varint((char*)zBlob, (sqlite3_int64 *)(&iVal));
  Tcl_ObjSetVar2(interp, objv[2], 0, Tcl_NewWideIntObj(iVal), 0);
  Tcl_SetObjResult(interp, Tcl_NewIntObj(nVal));
  return TCL_OK;
}

/*
** USAGE:  make_fts3record ARGLIST
*/
static int SQLITE_TCLAPI make_fts3record(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  Tcl_Obj **aArg = 0;
  int nArg = 0;
  unsigned char *aOut = 0;
  int nOut = 0;
  int nAlloc = 0;
  int i;

  if( objc!=2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "LIST");
    return TCL_ERROR;
  }
  if( Tcl_ListObjGetElements(interp, objv[1], &nArg, &aArg) ){
    return TCL_ERROR;
  }

  for(i=0; i<nArg; i++){
    sqlite3_int64 iVal;
    if( TCL_OK==Tcl_GetWideIntFromObj(0, aArg[i], &iVal) ){
      if( nOut+10>nAlloc ){
        int nNew = nAlloc?nAlloc*2:128;
        unsigned char *aNew = sqlite3_realloc(aOut, nNew);
        if( aNew==0 ){
          sqlite3_free(aOut);
          return TCL_ERROR;
        }
        aOut = aNew;
        nAlloc = nNew;
      }
      nOut += putFts3Varint((char*)&aOut[nOut], iVal);
    }else{
      int nVal = 0;
      char *zVal = Tcl_GetStringFromObj(aArg[i], &nVal);
      while( (nOut + nVal)>nAlloc ){
        int nNew = nAlloc?nAlloc*2:128;
        unsigned char *aNew = sqlite3_realloc(aOut, nNew);
        if( aNew==0 ){
          sqlite3_free(aOut);
          return TCL_ERROR;
        }
        aOut = aNew;
        nAlloc = nNew;
      }
      memcpy(&aOut[nOut], zVal, nVal);
      nOut += nVal;
    }
  }

  Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(aOut, nOut));
  sqlite3_free(aOut);
  return TCL_OK;
}


/*
** Register commands with the TCL interpreter.
*/
int Sqlitetest_hexio_Init(Tcl_Interp *interp){
  static struct {
     char *zName;
     Tcl_ObjCmdProc *xProc;
  } aObjCmd[] = {
     { "hexio_read",                   hexio_read            },
     { "hexio_write",                  hexio_write           },
     { "hexio_get_int",                hexio_get_int         },
     { "hexio_render_int16",           hexio_render_int16    },
     { "hexio_render_int32",           hexio_render_int32    },
     { "utf8_to_utf8",                 utf8_to_utf8          },
     { "read_fts3varint",              read_fts3varint       },
     { "make_fts3record",              make_fts3record       },
  };
  int i;
  for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
    Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0);
  }
  return TCL_OK;
}

Changes to src/test_journal.c.

556
557
558
559
560
561
562
563

564
565
566
567
568
569
570
556
557
558
559
560
561
562

563
564
565
566
567
568
569
570







-
+







    }else{
      u32 pgno = (u32)(iOfst/p->nPagesize + 1);
      assert( (iAmt==1||iAmt==(int)p->nPagesize) &&
              ((iOfst+iAmt)%p->nPagesize)==0 );
      /* The following assert() statements may fail if this layer is used
      ** with a connection in "PRAGMA synchronous=off" mode. If they
      ** fail with sync=normal or sync=full, this may indicate problem.  */
      assert( pgno<=p->nPage || p->nSync>0 );
      assert( p->nPage==0 || pgno<=p->nPage || p->nSync>0 );
      assert( pgno>p->nPage || sqlite3BitvecTest(p->pWritable, pgno) );
    }
  }

  rc = sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst);
  if( (p->flags&SQLITE_OPEN_MAIN_JOURNAL) && iAmt==12 ){
    jt_file *pMain = locateDatabaseHandle(p->zName, 0);

Changes to src/test_malloc.c.

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
108
109
110
111
112
113
114


























115
116
117
118
119
120
121







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







  void *p = 0;
  if( !faultsimStep() ){
    p = memfault.m.xRealloc(pOld, n);
  }
  return p;
}

/* 
** The following method calls are passed directly through to the underlying
** malloc system:
**
**     xFree
**     xSize
**     xRoundup
**     xInit
**     xShutdown
*/
static void faultsimFree(void *p){
  memfault.m.xFree(p);
}
static int faultsimSize(void *p){
  return memfault.m.xSize(p);
}
static int faultsimRoundup(int n){
  return memfault.m.xRoundup(n);
}
static int faultsimInit(void *p){
  return memfault.m.xInit(memfault.m.pAppData);
}
static void faultsimShutdown(void *p){
  memfault.m.xShutdown(memfault.m.pAppData);
}

/*
** This routine configures the malloc failure simulation.  After
** calling this routine, the next nDelay mallocs will succeed, followed
** by a block of nRepeat failures, after which malloc() calls will begin
** to succeed again.
*/
static void faultsimConfig(int nDelay, int nRepeat){
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
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







-
-
-
-
-
-
-
-
-
-













+
+
+







}

/*
** Add or remove the fault-simulation layer using sqlite3_config(). If
** the argument is non-zero, the 
*/
static int faultsimInstall(int install){
  static struct sqlite3_mem_methods m = {
    faultsimMalloc,                   /* xMalloc */
    faultsimFree,                     /* xFree */
    faultsimRealloc,                  /* xRealloc */
    faultsimSize,                     /* xSize */
    faultsimRoundup,                  /* xRoundup */
    faultsimInit,                     /* xInit */
    faultsimShutdown,                 /* xShutdown */
    0                                 /* pAppData */
  };
  int rc;

  install = (install ? 1 : 0);
  assert(memfault.isInstalled==1 || memfault.isInstalled==0);

  if( install==memfault.isInstalled ){
    return SQLITE_ERROR;
  }

  if( install ){
    rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memfault.m);
    assert(memfault.m.xMalloc);
    if( rc==SQLITE_OK ){
      sqlite3_mem_methods m = memfault.m;
      m.xMalloc = faultsimMalloc;
      m.xRealloc = faultsimRealloc;
      rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &m);
    }
    sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, 
        faultsimBeginBenign, faultsimEndBenign
    );
  }else{
    sqlite3_mem_methods m2;

Changes to src/test_multiplex.c.

263
264
265
266
267
268
269
270

271
272
273
274



275
276
277
278
279
280
281
263
264
265
266
267
268
269

270
271
272
273
274
275
276
277
278
279
280
281
282
283
284







-
+




+
+
+







    memset(&p[pGroup->nReal], 0, sizeof(p[0])*(iChunk+1-pGroup->nReal));
    pGroup->aReal = p;
    pGroup->nReal = iChunk+1;
  }
  if( pGroup->zName && pGroup->aReal[iChunk].z==0 ){
    char *z;
    int n = pGroup->nName;
    pGroup->aReal[iChunk].z = z = sqlite3_malloc64( n+5 );
    z = sqlite3_malloc64( n+5 );
    if( z==0 ){
      return SQLITE_NOMEM;
    }
    multiplexFilename(pGroup->zName, pGroup->nName, pGroup->flags, iChunk, z);
    pGroup->aReal[iChunk].z = (char*)sqlite3_create_filename(z,"","",0,0);
    sqlite3_free(z);
    if( pGroup->aReal[iChunk].z==0 ) return SQLITE_NOMEM;
  }
  return SQLITE_OK;
}

/* Translate an sqlite3_file* that is really a multiplexGroup* into
** the sqlite3_file* for the underlying original VFS.
**
434
435
436
437
438
439
440
441

442
443
444
445
446
447
448
437
438
439
440
441
442
443

444
445
446
447
448
449
450
451







-
+







  if( pSubOpen ){
    pSubOpen->pMethods->xClose(pSubOpen);
    if( pOrigVfs && pGroup->aReal[iChunk].z ){
      pOrigVfs->xDelete(pOrigVfs, pGroup->aReal[iChunk].z, 0);
    }
    sqlite3_free(pGroup->aReal[iChunk].p);
  }
  sqlite3_free(pGroup->aReal[iChunk].z);
  sqlite3_free_filename(pGroup->aReal[iChunk].z);
  memset(&pGroup->aReal[iChunk], 0, sizeof(pGroup->aReal[iChunk]));
}

/*
** Deallocate memory held by a multiplexGroup
*/
static void multiplexFreeComponents(multiplexGroup *pGroup){
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
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







-
+











-
+







#else
      int sqlite3PendingByte = 0x40000000;
#endif
      while( (sqlite3PendingByte % pGroup->szChunk)>=(pGroup->szChunk-65536) ){
        pGroup->szChunk += 65536;
      }
    }
    pGroup->flags = flags;
    pGroup->flags = (flags & ~SQLITE_OPEN_URI);
    rc = multiplexSubFilename(pGroup, 1);
    if( rc==SQLITE_OK ){
      pSubOpen = multiplexSubOpen(pGroup, 0, &rc, pOutFlags, 0);
      if( pSubOpen==0 && rc==SQLITE_OK ) rc = SQLITE_CANTOPEN;
    }
    if( rc==SQLITE_OK ){
      sqlite3_int64 sz64;

      rc = pSubOpen->pMethods->xFileSize(pSubOpen, &sz64);
      if( rc==SQLITE_OK && zName ){
        int bExists;
        if( flags & SQLITE_OPEN_MASTER_JOURNAL ){
        if( flags & SQLITE_OPEN_SUPER_JOURNAL ){
          pGroup->bEnabled = 0;
        }else
        if( sz64==0 ){
          if( flags & SQLITE_OPEN_MAIN_JOURNAL ){
            /* If opening a main journal file and the first chunk is zero
            ** bytes in size, delete any subsequent chunks from the 
            ** file-system. */
584
585
586
587
588
589
590
591

592
593

594
595
596
597
598
599
600
587
588
589
590
591
592
593

594
595

596
597
598
599
600
601
602
603







-
+

-
+







          }
        }
      }
    }

    if( rc==SQLITE_OK ){
      if( pSubOpen->pMethods->iVersion==1 ){
        pMultiplexOpen->base.pMethods = &gMultiplex.sIoMethodsV1;
        pConn->pMethods = &gMultiplex.sIoMethodsV1;
      }else{
        pMultiplexOpen->base.pMethods = &gMultiplex.sIoMethodsV2;
        pConn->pMethods = &gMultiplex.sIoMethodsV2;
      }
    }else{
      multiplexFreeComponents(pGroup);
      sqlite3_free(pGroup);
    }
  }
  sqlite3_free(zToFree);
955
956
957
958
959
960
961











962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981






























































982
983
984
985
986
987
988
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975




















976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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







+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







      /*
      ** EVIDENCE-OF: R-29875-31678 The argument to the SQLITE_FCNTL_PRAGMA
      ** file control is an array of pointers to strings (char**) in which the
      ** second element of the array is the name of the pragma and the third
      ** element is the argument to the pragma or NULL if the pragma has no
      ** argument.
      */
      if( aFcntl[1] && sqlite3_strnicmp(aFcntl[1],"multiplex_",10)==0 ){
        sqlite3_int64 sz = 0;
        (void)multiplexFileSize(pConn, &sz);
        /*
        ** PRAGMA multiplex_truncate=BOOLEAN;
        ** PRAGMA multiplex_truncate;
        **
        ** Turn the multiplexor truncate feature on or off.  Return either
        ** "on" or "off" to indicate the new setting.  If the BOOLEAN argument
        ** is omitted, just return the current value for the truncate setting.
        */
      if( aFcntl[1] && sqlite3_stricmp(aFcntl[1],"multiplex_truncate")==0 ){
        if( aFcntl[2] && aFcntl[2][0] ){
          if( sqlite3_stricmp(aFcntl[2], "on")==0
           || sqlite3_stricmp(aFcntl[2], "1")==0 ){
            pGroup->bTruncate = 1;
          }else
          if( sqlite3_stricmp(aFcntl[2], "off")==0
           || sqlite3_stricmp(aFcntl[2], "0")==0 ){
            pGroup->bTruncate = 0;
          }
        }
        /* EVIDENCE-OF: R-27806-26076 The handler for an SQLITE_FCNTL_PRAGMA
        ** file control can optionally make the first element of the char**
        ** argument point to a string obtained from sqlite3_mprintf() or the
        ** equivalent and that string will become the result of the pragma
        ** or the error message if the pragma fails.
        */
        aFcntl[0] = sqlite3_mprintf(pGroup->bTruncate ? "on" : "off");
        rc = SQLITE_OK;
        break;
        if( sqlite3_stricmp(aFcntl[1],"multiplex_truncate")==0 ){
          if( aFcntl[2] && aFcntl[2][0] ){
            if( sqlite3_stricmp(aFcntl[2], "on")==0
             || sqlite3_stricmp(aFcntl[2], "1")==0 ){
              pGroup->bTruncate = 1;
            }else
            if( sqlite3_stricmp(aFcntl[2], "off")==0
             || sqlite3_stricmp(aFcntl[2], "0")==0 ){
              pGroup->bTruncate = 0;
            }
          }
          /* EVIDENCE-OF: R-27806-26076 The handler for an SQLITE_FCNTL_PRAGMA
          ** file control can optionally make the first element of the char**
          ** argument point to a string obtained from sqlite3_mprintf() or the
          ** equivalent and that string will become the result of the pragma
          ** or the error message if the pragma fails.
          */
          aFcntl[0] = sqlite3_mprintf(pGroup->bTruncate ? "on" : "off");
          rc = SQLITE_OK;
          break;
        }
        /*
        ** PRAGMA multiplex_enabled;
        **
        ** Return 0 or 1 depending on whether the multiplexor is enabled or
        ** disabled, respectively.
        */
        if( sqlite3_stricmp(aFcntl[1],"multiplex_enabled")==0 ){
          aFcntl[0] = sqlite3_mprintf("%d", pGroup->bEnabled!=0);
          rc = SQLITE_OK;
          break;
        }
        /*
        ** PRAGMA multiplex_chunksize;
        **
        ** Return the chunksize for the multiplexor, or no-op if the 
        ** multiplexor is not active.
        */
        if( sqlite3_stricmp(aFcntl[1],"multiplex_chunksize")==0
         && pGroup->bEnabled
        ){
          aFcntl[0] = sqlite3_mprintf("%u", pGroup->szChunk);
          rc = SQLITE_OK;
          break;
        }
        /*
        ** PRAGMA multiplex_filecount;
        **
        ** Return the number of disk files currently in use by the
        ** multiplexor.  This should be the total database size size
        ** divided by the chunksize and rounded up.
        */
        if( sqlite3_stricmp(aFcntl[1],"multiplex_filecount")==0 ){
          int n = 0;
          int ii;
          for(ii=0; ii<pGroup->nReal; ii++){
            if( pGroup->aReal[ii].p!=0 ) n++;
          }
          aFcntl[0] = sqlite3_mprintf("%d", n);
          rc = SQLITE_OK;
          break;
        }
      }
      /* If the multiplexor does not handle the pragma, pass it through
      ** into the default case. */
    }
    default:
      pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0);
      if( pSubOpen ){

Changes to src/test_mutex.c.

26
27
28
29
30
31
32
33

34
35
36
37
38
39
40
26
27
28
29
30
31
32

33
34
35
36
37
38
39
40







-
+







#define MAX_MUTEXES        (SQLITE_MUTEX_STATIC_VFS3+1)
#define STATIC_MUTEXES     (MAX_MUTEXES-(SQLITE_MUTEX_RECURSIVE+1))

/* defined in main.c */
extern const char *sqlite3ErrName(int);

static const char *aName[MAX_MUTEXES+1] = {
  "fast",        "recursive",   "static_master", "static_mem",
  "fast",        "recursive",   "static_main",   "static_mem",
  "static_open", "static_prng", "static_lru",    "static_pmem",
  "static_app1", "static_app2", "static_app3",   "static_vfs1",
  "static_vfs2", "static_vfs3", 0
};

/* A countable mutex */
struct sqlite3_mutex {

Changes to src/test_osinst.c.

736
737
738
739
740
741
742
743

744
745
746
747
748
749
750
736
737
738
739
740
741
742

743
744
745
746
747
748
749
750







-
+







  p->base.zName = &((char *)p->pLog)[pParent->szOsFile];
  p->base.szOsFile += pParent->szOsFile;
  memcpy((char *)p->base.zName, zVfs, nVfs);

  zFile = (char *)&p->base.zName[nVfs+1];
  pParent->xFullPathname(pParent, zLog, pParent->mxPathname, zFile);

  flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MASTER_JOURNAL;
  flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_SUPER_JOURNAL;
  pParent->xDelete(pParent, zFile, 0);
  rc = pParent->xOpen(pParent, zFile, p->pLog, flags, &flags);
  if( rc==SQLITE_OK ){
    memcpy(p->aBuf, "sqlite_ostrace1.....", 20);
    p->iOffset = 0;
    p->nBuf = 20;
    rc = sqlite3_vfs_register((sqlite3_vfs *)p, 1);
889
890
891
892
893
894
895
896

897
898
899
900
901
902
903
889
890
891
892
893
894
895

896
897
898
899
900
901
902
903







-
+







    sqlite3_free(p);
    return SQLITE_NOMEM;
  }
  dequote(zFile);
  pVfs->xFullPathname(pVfs, zFile, pVfs->mxPathname, p->zFile);
  sqlite3_free(zFile);

  flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MASTER_JOURNAL;
  flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_SUPER_JOURNAL;
  rc = pVfs->xOpen(pVfs, p->zFile, p->pFd, flags, &flags);

  if( rc==SQLITE_OK ){
    p->pFd->pMethods->xFileSize(p->pFd, &p->nByte);
    sqlite3_declare_vtab(db, 
        "CREATE TABLE xxx(event, file, click, rc, size, offset)"
    );

Changes to src/test_schema.c.

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
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







-
+





-
+




-
+







      assert(pCur->pDbList);
      while( SQLITE_ROW!=sqlite3_step(pCur->pDbList) ){
        rc = finalize(&pCur->pDbList);
        goto next_exit;
      }

      /* Set zSql to the SQL to pull the list of tables from the 
      ** sqlite_master (or sqlite_temp_master) table of the database
      ** sqlite_schema (or sqlite_temp_schema) table of the database
      ** identified by the row pointed to by the SQL statement pCur->pDbList
      ** (iterating through a "PRAGMA database_list;" statement).
      */
      if( sqlite3_column_int(pCur->pDbList, 0)==1 ){
        zSql = sqlite3_mprintf(
            "SELECT name FROM sqlite_temp_master WHERE type='table'"
            "SELECT name FROM sqlite_temp_schema WHERE type='table'"
        );
      }else{
        sqlite3_stmt *pDbList = pCur->pDbList;
        zSql = sqlite3_mprintf(
            "SELECT name FROM %Q.sqlite_master WHERE type='table'",
            "SELECT name FROM %Q.sqlite_schema WHERE type='table'",
             sqlite3_column_text(pDbList, 1)
        );
      }
      if( !zSql ){
        rc = SQLITE_NOMEM;
        goto next_exit;
      }

Changes to src/test_sqllog.c.

114
115
116
117
118
119
120
121

122
123
124
125
126
127
128
114
115
116
117
118
119
120

121
122
123
124
125
126
127
128







-
+







  int iLog;                       /* First integer value used in file names */
  FILE *fd;                       /* File descriptor for log file */
};

/* This object is a singleton that keeps track of all data loggers.
*/
static struct SLGlobal {
  /* Protected by MUTEX_STATIC_MASTER */
  /* Protected by MUTEX_STATIC_MAIN */
  sqlite3_mutex *mutex;           /* Recursive mutex */
  int nConn;                      /* Size of aConn[] array */

  /* Protected by SLGlobal.mutex */
  int bConditional;               /* Only trace if *-sqllog file is present */
  int bReuse;                     /* True to avoid extra copies of db files */
  char zPrefix[SQLLOG_NAMESZ];    /* Prefix for all created files */
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
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







-
+






-
+



-
+




-
+




-
+


















-
+
















-
+







** The pCtx parameter is a copy of the pointer that was originally passed
** into the sqlite3_config(SQLITE_CONFIG_SQLLOG) statement.  In this
** particular implementation, pCtx is always a pointer to the 
** sqllogglobal global variable define above.
*/
static void testSqllog(void *pCtx, sqlite3 *db, const char *zSql, int eType){
  struct SLConn *p = 0;
  sqlite3_mutex *master = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
  sqlite3_mutex *mainmtx = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MAIN);

  assert( eType==0 || eType==1 || eType==2 );
  assert( (eType==2)==(zSql==0) );

  /* This is a database open command. */
  if( eType==0 ){
    sqlite3_mutex_enter(master);
    sqlite3_mutex_enter(mainmtx);
    if( sqllogglobal.mutex==0 ){
      sqllogglobal.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_RECURSIVE);
    }
    sqlite3_mutex_leave(master);
    sqlite3_mutex_leave(mainmtx);

    sqlite3_mutex_enter(sqllogglobal.mutex);
    if( sqllogglobal.bRec==0 && sqllogTraceDb(db) ){

      sqlite3_mutex_enter(master);
      sqlite3_mutex_enter(mainmtx);
      p = &sqllogglobal.aConn[sqllogglobal.nConn++];
      p->fd = 0;
      p->db = db;
      p->iLog = sqllogglobal.iNextLog++;
      sqlite3_mutex_leave(master);
      sqlite3_mutex_leave(mainmtx);

      /* Open the log and take a copy of the main database file */
      sqllogOpenlog(p);
      if( p->fd ) sqllogCopydb(p, "main", 0);
    }
    sqlite3_mutex_leave(sqllogglobal.mutex);
  }

  else{

    int i;
    for(i=0; i<sqllogglobal.nConn; i++){
      p = &sqllogglobal.aConn[i];
      if( p->db==db ) break;
    }

    /* A database handle close command */
    if( eType==2 ){
      sqlite3_mutex_enter(master);
      sqlite3_mutex_enter(mainmtx);
      if( i<sqllogglobal.nConn ){
        if( p->fd ) fclose(p->fd);
        p->db = 0;
        p->fd = 0;
        sqllogglobal.nConn--;
      }

      if( sqllogglobal.nConn==0 ){
        sqlite3_mutex_free(sqllogglobal.mutex);
        sqllogglobal.mutex = 0;
      }else if( i<sqllogglobal.nConn ){
        int nShift = &sqllogglobal.aConn[sqllogglobal.nConn] - p;
        if( nShift>0 ){
          memmove(p, &p[1], nShift*sizeof(struct SLConn));
        }
      }
      sqlite3_mutex_leave(master);
      sqlite3_mutex_leave(mainmtx);

    /* An ordinary SQL command. */
    }else if( i<sqllogglobal.nConn && p->fd ){
      sqlite3_mutex_enter(sqllogglobal.mutex);
      if( sqllogglobal.bRec==0 ){
        testSqllogStmt(p, zSql);
      }

Changes to src/test_superlock.c.

37
38
39
40
41
42
43


44
45
46
47
48
49
50
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52







+
+







** An instance of the following structure is allocated for each active
** superlock. The opaque handle returned by sqlite3demo_superlock() is
** actually a pointer to an instance of this structure.
*/
struct Superlock {
  sqlite3 *db;                    /* Database handle used to lock db */
  int bWal;                       /* True if db is a WAL database */
  int bRecoveryLocked;            /* True if WAL RECOVERY lock is held */
  int bReaderLocked;              /* True if WAL READER locks are held */
};
typedef struct Superlock Superlock;

/*
** The pCtx pointer passed to this function is actually a pointer to a
** SuperlockBusy structure. Invoke the busy-handler function encapsulated
** by the structure and return the result.
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
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







-
+





+








+


+
















+

+
















+
-
-
+
+
+
+
+
+
+







}

/*
** Obtain the extra locks on the database file required for WAL databases.
** Invoke the supplied busy-handler as required.
*/
static int superlockWalLock(
  sqlite3 *db,                    /* Database handle open on WAL database */
  Superlock *pLock,               /* Superlock handle */
  SuperlockBusy *pBusy            /* Busy handler wrapper object */
){
  int rc;                         /* Return code */
  sqlite3_file *fd = 0;           /* Main database file handle */
  void volatile *p = 0;           /* Pointer to first page of shared memory */
  sqlite3 *db = pLock->db;

  /* Obtain a pointer to the sqlite3_file object open on the main db file. */
  rc = sqlite3_file_control(db, "main", SQLITE_FCNTL_FILE_POINTER, (void *)&fd);
  if( rc!=SQLITE_OK ) return rc;

  /* Obtain the "recovery" lock. Normally, this lock is only obtained by
  ** clients running database recovery.  
  */
  assert( pLock->bRecoveryLocked==0 );
  rc = superlockShmLock(fd, 2, 1, pBusy);
  if( rc!=SQLITE_OK ) return rc;
  pLock->bRecoveryLocked = 1;

  /* Zero the start of the first shared-memory page. This means that any
  ** clients that open read or write transactions from this point on will
  ** have to run recovery before proceeding. Since they need the "recovery"
  ** lock that this process is holding to do that, no new read or write
  ** transactions may now be opened. Nor can a checkpoint be run, for the
  ** same reason.
  */
  rc = fd->pMethods->xShmMap(fd, 0, 32*1024, 1, &p);
  if( rc!=SQLITE_OK ) return rc;
  memset((void *)p, 0, 32);

  /* Obtain exclusive locks on all the "read-lock" slots. Once these locks
  ** are held, it is guaranteed that there are no active reader, writer or 
  ** checkpointer clients.
  */
  assert( pLock->bReaderLocked==0 );
  rc = superlockShmLock(fd, 3, SQLITE_SHM_NLOCK-3, pBusy);
  if( rc==SQLITE_OK ) pLock->bReaderLocked = 1;
  return rc;
}

/*
** Release a superlock held on a database file. The argument passed to 
** this function must have been obtained from a successful call to
** sqlite3demo_superlock().
*/
void sqlite3demo_superunlock(void *pLock){
  Superlock *p = (Superlock *)pLock;
  if( p->bWal ){
    int rc;                         /* Return code */
    int flags = SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE;
    sqlite3_file *fd = 0;
    rc = sqlite3_file_control(p->db, "main", SQLITE_FCNTL_FILE_POINTER, (void *)&fd);
    if( rc==SQLITE_OK ){
      if( p->bRecoveryLocked ){
      fd->pMethods->xShmLock(fd, 2, 1, flags);
      fd->pMethods->xShmLock(fd, 3, SQLITE_SHM_NLOCK-3, flags);
        fd->pMethods->xShmLock(fd, 2, 1, flags);
        p->bRecoveryLocked = 0;
      }
      if( p->bReaderLocked ){
        fd->pMethods->xShmLock(fd, 3, SQLITE_SHM_NLOCK-3, flags);
        p->bReaderLocked = 0;
      }
    }
  }
  sqlite3_close(p->db);
  sqlite3_free(p);
}

/*
228
229
230
231
232
233
234
235

236
237
238
239
240
241
242
241
242
243
244
245
246
247

248
249
250
251
252
253
254
255







-
+







  ** to drop the WAL read and write locks currently held. Otherwise, the
  ** new WAL locks may conflict with the old.
  */
  if( rc==SQLITE_OK ){
    if( SQLITE_OK==(rc = superlockIsWal(pLock)) && pLock->bWal ){
      rc = sqlite3_exec(pLock->db, "COMMIT", 0, 0, 0);
      if( rc==SQLITE_OK ){
        rc = superlockWalLock(pLock->db, &busy);
        rc = superlockWalLock(pLock, &busy);
      }
    }
  }

  if( rc!=SQLITE_OK ){
    sqlite3demo_superunlock(pLock);
    *ppLock = 0;

Changes to src/test_tclsh.c.

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
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







+











+








+
+







  extern int SqlitetestThread_Init(Tcl_Interp*);
  extern int SqlitetestOnefile_Init();
  extern int SqlitetestOsinst_Init(Tcl_Interp*);
  extern int Sqlitetestbackup_Init(Tcl_Interp*);
  extern int Sqlitetestintarray_Init(Tcl_Interp*);
  extern int Sqlitetestvfs_Init(Tcl_Interp *);
  extern int Sqlitetestrtree_Init(Tcl_Interp*);
  extern int Sqlitetestrtreedoc_Init(Tcl_Interp*);
  extern int Sqlitequota_Init(Tcl_Interp*);
  extern int Sqlitemultiplex_Init(Tcl_Interp*);
  extern int SqliteSuperlock_Init(Tcl_Interp*);
  extern int SqlitetestSyscall_Init(Tcl_Interp*);
#if defined(SQLITE_ENABLE_SESSION) && defined(SQLITE_ENABLE_PREUPDATE_HOOK)
  extern int TestSession_Init(Tcl_Interp*);
#endif
  extern int Md5_Init(Tcl_Interp*);
  extern int Fts5tcl_Init(Tcl_Interp *);
  extern int SqliteRbu_Init(Tcl_Interp*);
  extern int Sqlitetesttcl_Init(Tcl_Interp*);
  extern int Bgckpt_Init(Tcl_Interp*);
#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
  extern int Sqlitetestfts3_Init(Tcl_Interp *interp);
#endif
#ifdef SQLITE_ENABLE_ZIPVFS
  extern int Zipvfs_Init(Tcl_Interp*);
#endif
  extern int TestExpert_Init(Tcl_Interp*);
  extern int Sqlitetest_window_Init(Tcl_Interp *);
  extern int Sqlitetestvdbecov_Init(Tcl_Interp *);
  extern int TestRecover_Init(Tcl_Interp*);

  Tcl_CmdInfo cmdInfo;

  /* Since the primary use case for this binary is testing of SQLite,
  ** be sure to generate core files if we crash */
#if defined(unix)
  { struct rlimit x;
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
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







+










+
+






+
+







  SqlitetestThread_Init(interp);
  SqlitetestOnefile_Init();
  SqlitetestOsinst_Init(interp);
  Sqlitetestbackup_Init(interp);
  Sqlitetestintarray_Init(interp);
  Sqlitetestvfs_Init(interp);
  Sqlitetestrtree_Init(interp);
  Sqlitetestrtreedoc_Init(interp);
  Sqlitequota_Init(interp);
  Sqlitemultiplex_Init(interp);
  SqliteSuperlock_Init(interp);
  SqlitetestSyscall_Init(interp);
#if defined(SQLITE_ENABLE_SESSION) && defined(SQLITE_ENABLE_PREUPDATE_HOOK)
  TestSession_Init(interp);
#endif
  Fts5tcl_Init(interp);
  SqliteRbu_Init(interp);
  Sqlitetesttcl_Init(interp);
  Bgckpt_Init(interp);


#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
  Sqlitetestfts3_Init(interp);
#endif
  TestExpert_Init(interp);
  Sqlitetest_window_Init(interp);
  Sqlitetestvdbecov_Init(interp);
  TestRecover_Init(interp);

  Tcl_CreateObjCommand(
      interp, "load_testfixture_extensions", load_testfixture_extensions,0,0
  );
  return 0;
}

Changes to src/test_thread.c.

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
283
284
285
286
287
288
289
















290
291
292
293
294
295
296







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







  extern int Md5_Register(sqlite3*,char**,const sqlite3_api_routines*);

  UNUSED_PARAMETER(clientData);
  UNUSED_PARAMETER(objc);

  zFilename = Tcl_GetString(objv[2]);
  sqlite3_open(zFilename, &db);
#ifdef SQLITE_HAS_CODEC
  if( db && objc>=4 ){
    const char *zKey;
    int nKey;
    int rc;
    zKey = Tcl_GetStringFromObj(objv[3], &nKey);
    rc = sqlite3_key(db, zKey, nKey);
    if( rc!=SQLITE_OK ){
      char *zErrMsg = sqlite3_mprintf("error %d: %s", rc, sqlite3_errmsg(db));
      sqlite3_close(db);
      Tcl_AppendResult(interp, zErrMsg, (char*)0);
      sqlite3_free(zErrMsg);
      return TCL_ERROR;
    }
  }
#endif
  Md5_Register(db, 0, 0);
  sqlite3_busy_handler(db, xBusy, 0);
  
  if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
  Tcl_AppendResult(interp, zBuf, 0);

  return TCL_OK;

Added src/test_vdbecov.c.

























































































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2019 April 02
**
** 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.
**
******************************************************************************
**
*/
#if SQLITE_TEST          /* This file is used for testing only */

#include "sqlite3.h"
#include "sqliteInt.h"
#if defined(INCLUDE_SQLITE_TCL_H)
#  include "sqlite_tcl.h"
#else
#  include "tcl.h"
#endif

#ifdef SQLITE_VDBE_COVERAGE

static u8 aBranchArray[200000];

static void test_vdbe_branch(
  void *pCtx, 
  unsigned int iSrc, 
  unsigned char iBranch, 
  unsigned char iType
){
  if( iSrc<sizeof(aBranchArray) ){
    aBranchArray[iSrc] |= iBranch;
  }
}

static void appendToList(
  Tcl_Obj *pList, 
  int iLine, 
  int iPath, 
  const char *zNever
){
  Tcl_Obj *pNew = Tcl_NewObj();
  Tcl_IncrRefCount(pNew);
  Tcl_ListObjAppendElement(0, pNew, Tcl_NewIntObj(iLine));
  Tcl_ListObjAppendElement(0, pNew, Tcl_NewIntObj(iPath));
  Tcl_ListObjAppendElement(0, pNew, Tcl_NewStringObj(zNever, -1));
  Tcl_ListObjAppendElement(0, pList, pNew);
  Tcl_DecrRefCount(pNew);
}


static int SQLITE_TCLAPI test_vdbe_coverage(
  ClientData cd,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  const char *aSub[] = { "start", "report", "stop", 0 };
  int iSub = -1;
  if( objc!=2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "sub-command");
    return TCL_ERROR;
  }

  if( Tcl_GetIndexFromObj(interp, objv[1], aSub, "sub-command", 0, &iSub) ){
    return TCL_ERROR;
  }

  Tcl_ResetResult(interp);
  assert( iSub==0 || iSub==1 || iSub==2 );
  switch( iSub ){
    case 0:       /* start */
      memset(aBranchArray, 0, sizeof(aBranchArray));
      sqlite3_test_control(SQLITE_TESTCTRL_VDBE_COVERAGE, test_vdbe_branch, 0);
      break;
    case 1: {     /* report */
      int i;
      Tcl_Obj *pRes = Tcl_NewObj();
      Tcl_IncrRefCount(pRes);
      for(i=0; i<sizeof(aBranchArray); i++){
        u8 b = aBranchArray[i];
        int bFlag = ((b >> 4)==4);
        if( b ){
          if( (b & 0x01)==0 ){
            appendToList(pRes, i, 0, bFlag ? "less than" : "falls through");
          }
          if( (b & 0x02)==0 ){
            appendToList(pRes, i, 1, bFlag ? "equal" : "taken");
          }
          if( (b & 0x04)==0 ){
            appendToList(pRes, i, 2, bFlag ? "greater-than" : "NULL");
          }
        }
      }
      Tcl_SetObjResult(interp, pRes);
      Tcl_DecrRefCount(pRes);
      break;
    };
      
    default:      /* stop */         
      sqlite3_test_control(SQLITE_TESTCTRL_VDBE_COVERAGE, 0, 0);
      break;
  }

  return TCL_OK;
}

#endif  /* SQLITE_VDBE_COVERAGE */

int Sqlitetestvdbecov_Init(Tcl_Interp *interp){
#ifdef SQLITE_VDBE_COVERAGE
  Tcl_CreateObjCommand(interp, "vdbe_coverage", test_vdbe_coverage, 0, 0);
#endif
  return TCL_OK;
}

#endif

Changes to src/test_vfs.c.

224
225
226
227
228
229
230
231
232
233
234
235









236
237
238
239
240
241
242
224
225
226
227
228
229
230





231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246







-
-
-
-
-
+
+
+
+
+
+
+
+
+







};

static int tvfsResultCode(Testvfs *p, int *pRc){
  struct errcode {
    int eCode;
    const char *zCode;
  } aCode[] = {
    { SQLITE_OK,     "SQLITE_OK"     },
    { SQLITE_ERROR,  "SQLITE_ERROR"  },
    { SQLITE_IOERR,  "SQLITE_IOERR"  },
    { SQLITE_LOCKED, "SQLITE_LOCKED" },
    { SQLITE_BUSY,   "SQLITE_BUSY"   },
    { SQLITE_OK,       "SQLITE_OK"     },
    { SQLITE_ERROR,    "SQLITE_ERROR"  },
    { SQLITE_IOERR,    "SQLITE_IOERR"  },
    { SQLITE_LOCKED,   "SQLITE_LOCKED" },
    { SQLITE_BUSY,     "SQLITE_BUSY"   },
    { SQLITE_READONLY, "SQLITE_READONLY"   },
    { SQLITE_READONLY_CANTINIT, "SQLITE_READONLY_CANTINIT"   },
    { SQLITE_NOTFOUND, "SQLITE_NOTFOUND"   },
    { -1,              "SQLITE_OMIT"   },
  };

  const char *z;
  int i;

  z = Tcl_GetStringResult(p->interp);
  for(i=0; i<ArraySize(aCode); i++){
376
377
378
379
380
381
382

383
384
385
386
387
388
389
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394







+








  if( p->pScript && p->mask&TESTVFS_WRITE_MASK ){
    tvfsExecTcl(p, "xWrite", 
        Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 
        Tcl_NewWideIntObj(iOfst), Tcl_NewIntObj(iAmt)
    );
    tvfsResultCode(p, &rc);
    if( rc<0 ) return SQLITE_OK;
  }

  if( rc==SQLITE_OK && tvfsInjectFullerr(p) ){
    rc = SQLITE_FULL;
  }
  if( rc==SQLITE_OK && p->mask&TESTVFS_WRITE_MASK && tvfsInjectIoerr(p) ){
    rc = SQLITE_IOERR;
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
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







+
+
+
















-
+







  TestvfsFd *pFd = tvfsGetFd(pFile);
  Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
  if( p->pScript && p->mask&TESTVFS_LOCK_MASK ){
    char zLock[30];
    sqlite3_snprintf(sizeof(zLock),zLock,"%d",eLock);
    tvfsExecTcl(p, "xLock", Tcl_NewStringObj(pFd->zFilename, -1), 
                   Tcl_NewStringObj(zLock, -1), 0, 0);
  }
  if( p->mask&TESTVFS_LOCK_MASK && tvfsInjectIoerr(p) ){
    return SQLITE_IOERR_LOCK;
  }
  return sqlite3OsLock(pFd->pReal, eLock);
}

/*
** Unlock an tvfs-file.
*/
static int tvfsUnlock(sqlite3_file *pFile, int eLock){
  TestvfsFd *pFd = tvfsGetFd(pFile);
  Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
  if( p->pScript && p->mask&TESTVFS_UNLOCK_MASK ){
    char zLock[30];
    sqlite3_snprintf(sizeof(zLock),zLock,"%d",eLock);
    tvfsExecTcl(p, "xUnlock", Tcl_NewStringObj(pFd->zFilename, -1), 
                   Tcl_NewStringObj(zLock, -1), 0, 0);
  }
  if( p->mask&TESTVFS_WRITE_MASK && tvfsInjectIoerr(p) ){
  if( p->mask&TESTVFS_UNLOCK_MASK && tvfsInjectIoerr(p) ){
    return SQLITE_IOERR_UNLOCK;
  }
  return sqlite3OsUnlock(pFd->pReal, eLock);
}

/*
** Check if another file-handle holds a RESERVED lock on an tvfs-file.
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
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







+













-
+







  if( p->pScript && (p->mask&TESTVFS_FCNTL_MASK) ){
    struct Fcntl {
      int iFnctl;
      const char *zFnctl;
    } aF[] = {
      { SQLITE_FCNTL_BEGIN_ATOMIC_WRITE, "BEGIN_ATOMIC_WRITE" },
      { SQLITE_FCNTL_COMMIT_ATOMIC_WRITE, "COMMIT_ATOMIC_WRITE" },
      { SQLITE_FCNTL_ZIPVFS, "ZIPVFS" },
    };
    int i;
    for(i=0; i<sizeof(aF)/sizeof(aF[0]); i++){
      if( op==aF[i].iFnctl ) break;
    }
    if( i<sizeof(aF)/sizeof(aF[0]) ){
      int rc = 0;
      tvfsExecTcl(p, "xFileControl", 
          Tcl_NewStringObj(pFd->zFilename, -1), 
          Tcl_NewStringObj(aF[i].zFnctl, -1),
          0, 0
      );
      tvfsResultCode(p, &rc);
      if( rc ) return rc;
      if( rc ) return (rc<0 ? SQLITE_OK : rc);
    }
  }
  return sqlite3OsFileControl(pFd->pReal, op, pArg);
}

/*
** Return the sector-size in bytes for an tvfs-file.
861
862
863
864
865
866
867
868

869
870
871
872
873
874
875
870
871
872
873
874
875
876

877
878
879
880
881
882
883
884







-
+







    p->pBuffer = pBuffer;
  }

  /* Connect the TestvfsBuffer to the new TestvfsShm handle and return. */
  pFd->pNext = pBuffer->pFile;
  pBuffer->pFile = pFd;
  pFd->pShm = pBuffer;
  return SQLITE_OK;
  return rc;
}

static void tvfsAllocPage(TestvfsBuffer *p, int iPage, int pgsz){
  assert( iPage<TESTVFS_MAX_PAGES );
  if( p->aPage[iPage]==0 ){
    p->aPage[iPage] = (u8 *)ckalloc(pgsz);
    memset(p->aPage[iPage], 0, pgsz);
885
886
887
888
889
890
891

892

893
894
895
896
897
898
899
894
895
896
897
898
899
900
901

902
903
904
905
906
907
908
909







+
-
+







  void volatile **pp              /* OUT: Mapped memory */
){
  int rc = SQLITE_OK;
  TestvfsFd *pFd = tvfsGetFd(pFile);
  Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);

  if( p->isFullshm ){
    sqlite3_file *pReal = pFd->pReal;
    return sqlite3OsShmMap(pFd->pReal, iPage, pgsz, isWrite, pp);
    return pReal->pMethods->xShmMap(pReal, iPage, pgsz, isWrite, pp);
  }

  if( 0==pFd->pShm ){
    rc = tvfsShmOpen(pFile);
    if( rc!=SQLITE_OK ){
      return rc;
    }
914
915
916
917
918
919
920

921


922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939

940

941
942
943
944
945
946
947
924
925
926
927
928
929
930
931

932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952

953
954
955
956
957
958
959
960







+
-
+
+


















+
-
+







  if( rc==SQLITE_OK && p->mask&TESTVFS_SHMMAP_MASK && tvfsInjectIoerr(p) ){
    rc = SQLITE_IOERR;
  }

  if( rc==SQLITE_OK && isWrite && !pFd->pShm->aPage[iPage] ){
    tvfsAllocPage(pFd->pShm, iPage, pgsz);
  }
  if( rc==SQLITE_OK || rc==SQLITE_READONLY ){
  *pp = (void volatile *)pFd->pShm->aPage[iPage];
    *pp = (void volatile *)pFd->pShm->aPage[iPage];
  }

  return rc;
}


static int tvfsShmLock(
  sqlite3_file *pFile,
  int ofst,
  int n,
  int flags
){
  int rc = SQLITE_OK;
  TestvfsFd *pFd = tvfsGetFd(pFile);
  Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
  int nLock;
  char zLock[80];

  if( p->isFullshm ){
    sqlite3_file *pReal = pFd->pReal;
    return sqlite3OsShmLock(pFd->pReal, ofst, n, flags);
    return pReal->pMethods->xShmLock(pReal, ofst, n, flags);
  }

  if( p->pScript && p->mask&TESTVFS_SHMLOCK_MASK ){
    sqlite3_snprintf(sizeof(zLock), zLock, "%d %d", ofst, n);
    nLock = (int)strlen(zLock);
    if( flags & SQLITE_SHM_LOCK ){
      strcpy(&zLock[nLock], " lock");
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
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







+
-
+















+
-
+








  if( p->pScript && p->mask&TESTVFS_SHMBARRIER_MASK ){
    const char *z = pFd->pShm ? pFd->pShm->zFile : "";
    tvfsExecTcl(p, "xShmBarrier", Tcl_NewStringObj(z, -1), pFd->pShmId, 0, 0);
  }

  if( p->isFullshm ){
    sqlite3_file *pReal = pFd->pReal;
    sqlite3OsShmBarrier(pFd->pReal);
    pReal->pMethods->xShmBarrier(pReal);
    return;
  }
}

static int tvfsShmUnmap(
  sqlite3_file *pFile,
  int deleteFlag
){
  int rc = SQLITE_OK;
  TestvfsFd *pFd = tvfsGetFd(pFile);
  Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
  TestvfsBuffer *pBuffer = pFd->pShm;
  TestvfsFd **ppFd;

  if( p->isFullshm ){
    sqlite3_file *pReal = pFd->pReal;
    return sqlite3OsShmUnmap(pFd->pReal, deleteFlag);
    return pReal->pMethods->xShmUnmap(pReal, deleteFlag);
  }

  if( !pBuffer ) return SQLITE_OK;
  assert( pFd->pShmId && pFd->pShm );

  if( p->pScript && p->mask&TESTVFS_SHMCLOSE_MASK ){
    tvfsExecTcl(p, "xShmUnmap", 
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







+

+







  return TCL_OK;
}

static void SQLITE_TCLAPI testvfs_obj_del(ClientData cd){
  Testvfs *p = (Testvfs *)cd;
  if( p->pScript ) Tcl_DecrRefCount(p->pScript);
  sqlite3_vfs_unregister(p->pVfs);
  memset(p->pVfs, 0, sizeof(sqlite3_vfs));
  ckfree((char *)p->pVfs);
  memset(p, 0, sizeof(Testvfs));
  ckfree((char *)p);
}

/*
** Usage:  testvfs VFSNAME ?SWITCHES?
**
** Switches are:
1558
1559
1560
1561
1562
1563
1564
1565









































































































1566
1567


1568
1569
1570
1571
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
+





  return TCL_OK;

 bad_args:
  Tcl_WrongNumArgs(interp, 1, objv, "VFSNAME ?-noshm BOOL? ?-fullshm BOOL? ?-default BOOL? ?-mxpathname INT? ?-szosfile INT? ?-iversion INT?");
  return TCL_ERROR;
}

extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);
extern const char *sqlite3ErrName(int);

/*
** tclcmd: vfs_shmlock DB DBNAME (shared|exclusive) (lock|unlock) OFFSET N
*/
static int SQLITE_TCLAPI test_vfs_shmlock(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  const char *azArg1[] = {"shared", "exclusive", 0};
  const char *azArg2[] = {"lock", "unlock", 0};
  sqlite3 *db = 0;
  int rc = SQLITE_OK;
  const char *zDbname = 0;
  int iArg1 = 0;
  int iArg2 = 0;
  int iOffset = 0;
  int n = 0;
  sqlite3_file *pFd;

  if( objc!=7 ){
    Tcl_WrongNumArgs(interp, 1, objv, 
        "DB DBNAME (shared|exclusive) (lock|unlock) OFFSET N"
    );
    return TCL_ERROR;
  }

  zDbname = Tcl_GetString(objv[2]);
  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) 
   || Tcl_GetIndexFromObj(interp, objv[3], azArg1, "ARG", 0, &iArg1) 
   || Tcl_GetIndexFromObj(interp, objv[4], azArg2, "ARG", 0, &iArg2) 
   || Tcl_GetIntFromObj(interp, objv[5], &iOffset)
   || Tcl_GetIntFromObj(interp, objv[6], &n)
  ){
    return TCL_ERROR;
  }

  sqlite3_file_control(db, zDbname, SQLITE_FCNTL_FILE_POINTER, (void*)&pFd);
  if( pFd==0 ){
    return TCL_ERROR;
  }
  rc = pFd->pMethods->xShmLock(pFd, iOffset, n, 
      (iArg1==0 ? SQLITE_SHM_SHARED : SQLITE_SHM_EXCLUSIVE)
    | (iArg2==0 ? SQLITE_SHM_LOCK : SQLITE_SHM_UNLOCK)
  );
  Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
  return TCL_OK;
}

static int SQLITE_TCLAPI test_vfs_set_readmark(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  sqlite3 *db = 0;
  int rc = SQLITE_OK;
  const char *zDbname = 0;
  int iSlot = 0;
  int iVal = -1;
  sqlite3_file *pFd;
  void volatile *pShm = 0;
  u32 *aShm;
  int iOff;

  if( objc!=4 && objc!=5 ){
    Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SLOT ?VALUE?");
    return TCL_ERROR;
  }

  zDbname = Tcl_GetString(objv[2]);
  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) 
   || Tcl_GetIntFromObj(interp, objv[3], &iSlot)
   || (objc==5 && Tcl_GetIntFromObj(interp, objv[4], &iVal))
  ){
    return TCL_ERROR;
  }

  sqlite3_file_control(db, zDbname, SQLITE_FCNTL_FILE_POINTER, (void*)&pFd);
  if( pFd==0 ){
    return TCL_ERROR;
  }
  rc = pFd->pMethods->xShmMap(pFd, 0, 32*1024, 0, &pShm);
  if( rc!=SQLITE_OK ){
    Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
    return TCL_ERROR;
  }
  if( pShm==0 ){
    Tcl_AppendResult(interp, "*-shm is not yet mapped", 0);
    return TCL_ERROR;
  }
  aShm = (u32*)pShm;
  iOff = 12*2+1+iSlot;

  if( objc==5 ){
    aShm[iOff] = iVal;
  }
  Tcl_SetObjResult(interp, Tcl_NewIntObj(aShm[iOff]));

  return TCL_OK;
}

int Sqlitetestvfs_Init(Tcl_Interp *interp){
  Tcl_CreateObjCommand(interp, "testvfs", testvfs_cmd, 0, 0);
  Tcl_CreateObjCommand(interp, "vfs_shmlock", test_vfs_shmlock, 0, 0);
  Tcl_CreateObjCommand(interp, "vfs_set_readmark", test_vfs_set_readmark, 0, 0);
  return TCL_OK;
}

#endif

Changes to src/tokenize.c.

23
24
25
26
27
28
29

30

31
32
33
34
35
36
37
38
23
24
25
26
27
28
29
30

31

32
33
34
35
36
37
38







+
-
+
-







** In the sqlite3GetToken() function, a switch() on aiClass[c] is implemented
** using a lookup table, whereas a switch() directly on c uses a binary search.
** The lookup table is much faster.  To maximize speed, and to ensure that
** a lookup table is used, all of the classes need to be small integers and
** all of them need to be used within the switch.
*/
#define CC_X          0    /* The letter 'x', or start of BLOB literal */
#define CC_KYWD0      1    /* First letter of a keyword */
#define CC_KYWD       1    /* Alphabetics or '_'.  Usable in a keyword */
#define CC_KYWD       2    /* Alphabetics or '_'.  Usable in a keyword */
#define CC_ID         2    /* unicode characters usable in IDs */
#define CC_DIGIT      3    /* Digits */
#define CC_DOLLAR     4    /* '$' */
#define CC_VARALPHA   5    /* '@', '#', ':'.  Alphabetic SQL variables */
#define CC_VARNUM     6    /* '?'.  Numeric SQL variables */
#define CC_SPACE      7    /* Space characters */
#define CC_QUOTE      8    /* '"', '\'', or '`'.  String literals, quoted ids */
#define CC_QUOTE2     9    /* '['.   [...] style quoted ids */
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
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







+
-
-
+
+
+




-
-
+
+



-
+

-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







#define CC_PLUS      20    /* '+' */
#define CC_STAR      21    /* '*' */
#define CC_PERCENT   22    /* '%' */
#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   27    /* Illegal character */
#define CC_NUL       28    /* 0x00 */
#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 */   28, 27, 27, 27, 27, 27, 27, 27, 27,  7,  7, 27,  7,  7, 27, 27,
/* 1x */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
/* 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,  1,  1,  9, 27, 27, 27,  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,  1,  1, 27, 10, 27, 25, 27,
/* 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
/* 7x */    1,  1,  1,  1,  1,  1,  1,  1,  0,  2,  2, 28, 10, 28, 25, 28,
/* 8x */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
/* 9x */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
/* Ax */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
/* Bx */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
/* Cx */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
/* Dx */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
/* Ex */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 30,
/* Fx */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27
#endif
#ifdef SQLITE_EBCDIC
/*         x0  x1  x2  x3  x4  x5  x6  x7  x8  x9  xa  xb  xc  xd  xe  xf */
/* 0x */   27, 27, 27, 27, 27,  7, 27, 27, 27, 27, 27, 27,  7,  7, 27, 27,
/* 1x */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
/* 2x */   27, 27, 27, 27, 27,  7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
/* 3x */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
/* 4x */    7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 26, 12, 17, 20, 10,
/* 5x */   24, 27, 27, 27, 27, 27, 27, 27, 27, 27, 15,  4, 21, 18, 19, 27,
/* 6x */   11, 16, 27, 27, 27, 27, 27, 27, 27, 27, 27, 23, 22,  1, 13,  6,
/* 7x */   27, 27, 27, 27, 27, 27, 27, 27, 27,  8,  5,  5,  5,  8, 14,  8,
/* 8x */   27,  1,  1,  1,  1,  1,  1,  1,  1,  1, 27, 27, 27, 27, 27, 27,
/* 9x */   27,  1,  1,  1,  1,  1,  1,  1,  1,  1, 27, 27, 27, 27, 27, 27,
/* Ax */   27, 25,  1,  1,  1,  1,  1,  0,  1,  1, 27, 27, 27, 27, 27, 27,
/* Bx */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  9, 27, 27, 27, 27, 27,
/* Cx */   27,  1,  1,  1,  1,  1,  1,  1,  1,  1, 27, 27, 27, 27, 27, 27,
/* Dx */   27,  1,  1,  1,  1,  1,  1,  1,  1,  1, 27, 27, 27, 27, 27, 27,
/* Ex */   27, 27,  1,  1,  1,  1,  1,  0,  1,  1, 27, 27, 27, 27, 27, 27,
/* Fx */    3,  3,  3,  3,  3,  3,  3,  3,  3,  3, 27, 27, 27, 27, 27, 27,
/* 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,
/* 4x */    7, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 26, 12, 17, 20, 10,
/* 5x */   24, 28, 28, 28, 28, 28, 28, 28, 28, 28, 15,  4, 21, 18, 19, 28,
/* 6x */   11, 16, 28, 28, 28, 28, 28, 28, 28, 28, 28, 23, 22,  2, 13,  6,
/* 7x */   28, 28, 28, 28, 28, 28, 28, 28, 28,  8,  5,  5,  5,  8, 14,  8,
/* 8x */   28,  1,  1,  1,  1,  1,  1,  1,  1,  1, 28, 28, 28, 28, 28, 28,
/* 9x */   28,  1,  1,  1,  1,  1,  1,  1,  1,  1, 28, 28, 28, 28, 28, 28,
/* Ax */   28, 25,  1,  1,  1,  1,  1,  0,  2,  2, 28, 28, 28, 28, 28, 28,
/* Bx */   28, 28, 28, 28, 28, 28, 28, 28, 28, 28,  9, 28, 28, 28, 28, 28,
/* Cx */   28,  1,  1,  1,  1,  1,  1,  1,  1,  1, 28, 28, 28, 28, 28, 28,
/* Dx */   28,  1,  1,  1,  1,  1,  1,  1,  1,  1, 28, 28, 28, 28, 28, 28,
/* Ex */   28, 28,  1,  1,  1,  1,  1,  0,  2,  2, 28, 28, 28, 28, 28, 28,
/* Fx */    3,  3,  3,  3,  3,  3,  3,  3,  3,  3, 28, 28, 28, 28, 28, 28,
#endif
};

/*
** The charMap() macro maps alphabetic characters (only) into their
** lower-case ASCII equivalent.  On ASCII machines, this is just
** an upper-to-lower case map.  On EBCDIC machines we also need
284
285
286
287
288
289
290



291
292
293
294
295
296
297
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302







+
+
+







      return i;
    }
    case CC_MINUS: {
      if( z[1]=='-' ){
        for(i=2; (c=z[i])!=0 && c!='\n'; i++){}
        *tokenType = TK_SPACE;   /* IMP: R-22934-25134 */
        return i;
      }else if( z[1]=='>' ){
        *tokenType = TK_PTR;
        return 2 + (z[2]=='>');
      }
      *tokenType = TK_MINUS;
      return 1;
    }
    case CC_LP: {
      *tokenType = TK_LP;
      return 1;
418
419
420
421
422
423
424

425
426
427
428
429
430
431
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437







+







#endif
      {
        *tokenType = TK_DOT;
        return 1;
      }
      /* If the next character is a digit, this is a floating point
      ** number that begins with ".".  Fall thru into the next case */
      /* no break */ deliberate_fall_through
    }
    case CC_DIGIT: {
      testcase( z[0]=='0' );  testcase( z[0]=='1' );  testcase( z[0]=='2' );
      testcase( z[0]=='3' );  testcase( z[0]=='4' );  testcase( z[0]=='5' );
      testcase( z[0]=='6' );  testcase( z[0]=='7' );  testcase( z[0]=='8' );
      testcase( z[0]=='9' );
      *tokenType = TK_INTEGER;
494
495
496
497
498
499
500
501

502
503
504
505
506
507
508
500
501
502
503
504
505
506

507
508
509
510
511
512
513
514







-
+







        }else{
          break;
        }
      }
      if( n==0 ) *tokenType = TK_ILLEGAL;
      return i;
    }
    case CC_KYWD: {
    case CC_KYWD0: {
      for(i=1; aiClass[z[i]]<=CC_KYWD; i++){}
      if( IdChar(z[i]) ){
        /* This token started out using characters that can appear in keywords,
        ** but z[i] is a character not allowed within keywords, so this must
        ** be an identifier instead */
        i++;
        break;
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
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
638







+

+

+
+
+
+
+
+
+
+


















-
+
-
-
-
-

-
+







+



+




-
+



+
+
-
-
+
+
+
+
+
+














+
+





+











-
+

+







        }
        if( z[i] ) i++;
        return i;
      }
#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;
    }
    default: {
      *tokenType = TK_ILLEGAL;
      return 1;
    }
  }
  while( IdChar(z[i]) ){ i++; }
  *tokenType = TK_ID;
  return i;
}

/*
** Run the parser on the given SQL string.  The parser structure is
** Run the parser on the given SQL string.
** passed in.  An SQLITE_ status code is returned.  If an error occurs
** then an and attempt is made to write an error message into 
** memory obtained from sqlite3_malloc() and to make *pzErrMsg point to that
** error message.
*/
int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
int sqlite3RunParser(Parse *pParse, const char *zSql){
  int nErr = 0;                   /* Number of errors encountered */
  void *pEngine;                  /* The LEMON-generated LALR(1) parser */
  int n = 0;                      /* Length of the next token token */
  int tokenType;                  /* type of the next token */
  int lastTokenParsed = -1;       /* type of the previous token */
  sqlite3 *db = pParse->db;       /* The database connection */
  int mxSqlLen;                   /* Max length of an SQL string */
  Parse *pParentParse = 0;        /* Outer parse context, if any */
#ifdef sqlite3Parser_ENGINEALWAYSONSTACK
  yyParser sEngine;    /* Space to hold the Lemon-generated Parser object */
#endif
  VVA_ONLY( u8 startedWithOom = db->mallocFailed );

  assert( zSql!=0 );
  mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
  if( db->nVdbeActive==0 ){
    db->u1.isInterrupted = 0;
    AtomicStore(&db->u1.isInterrupted, 0);
  }
  pParse->rc = SQLITE_OK;
  pParse->zTail = zSql;
#ifdef SQLITE_DEBUG
  if( db->flags & SQLITE_ParserTrace ){
  assert( pzErrMsg!=0 );
  /* sqlite3ParserTrace(stdout, "parser: "); */
    printf("parser: [[[%s]]]\n", zSql);
    sqlite3ParserTrace(stdout, "parser: ");
  }else{
    sqlite3ParserTrace(0, 0);
  }
#endif
#ifdef sqlite3Parser_ENGINEALWAYSONSTACK
  pEngine = &sEngine;
  sqlite3ParserInit(pEngine, pParse);
#else
  pEngine = sqlite3ParserAlloc(sqlite3Malloc, pParse);
  if( pEngine==0 ){
    sqlite3OomFault(db);
    return SQLITE_NOMEM_BKPT;
  }
#endif
  assert( pParse->pNewTable==0 );
  assert( pParse->pNewTrigger==0 );
  assert( pParse->nVar==0 );
  assert( pParse->pVList==0 );
  pParentParse = db->pParse;
  db->pParse = pParse;
  while( 1 ){
    n = sqlite3GetToken((u8*)zSql, &tokenType);
    mxSqlLen -= n;
    if( mxSqlLen<0 ){
      pParse->rc = SQLITE_TOOBIG;
      pParse->nErr++;
      break;
    }
#ifndef SQLITE_OMIT_WINDOWFUNC
    if( tokenType>=TK_WINDOW ){
      assert( tokenType==TK_SPACE || tokenType==TK_OVER || tokenType==TK_FILTER
           || tokenType==TK_ILLEGAL || tokenType==TK_WINDOW 
      );
#else
    if( tokenType>=TK_SPACE ){
      assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL );
#endif /* SQLITE_OMIT_WINDOWFUNC */
      if( db->u1.isInterrupted ){
      if( AtomicLoad(&db->u1.isInterrupted) ){
        pParse->rc = SQLITE_INTERRUPT;
        pParse->nErr++;
        break;
      }
      if( tokenType==TK_SPACE ){
        zSql += n;
        continue;
      }
      if( zSql[0]==0 ){
630
631
632
633
634
635
636



637

638
639
640
641
642
643
644
645

646

647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666




667
668
669
670

671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691

692
693
694
695
696
697
698

699
700
701
702
703
704


705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
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







+
+
+
-
+








+
-
+

















-
-
-
+
+
+
+
-
-
-
-
+
-
-



-
-
-
-
-
-
-
-
-
-
-




-
+






-
+


-
-
-
-
+
+
-
-
-
-
-
-
-
-
-







        assert( n==4 );
        tokenType = analyzeOverKeyword((const u8*)&zSql[4], lastTokenParsed);
      }else if( tokenType==TK_FILTER ){
        assert( n==6 );
        tokenType = analyzeFilterKeyword((const u8*)&zSql[6], lastTokenParsed);
#endif /* SQLITE_OMIT_WINDOWFUNC */
      }else{
        Token x;
        x.z = zSql;
        x.n = n;
        sqlite3ErrorMsg(pParse, "unrecognized token: \"%.*s\"", n, zSql);
        sqlite3ErrorMsg(pParse, "unrecognized token: \"%T\"", &x);
        break;
      }
    }
    pParse->sLastToken.z = zSql;
    pParse->sLastToken.n = n;
    sqlite3Parser(pEngine, tokenType, pParse->sLastToken);
    lastTokenParsed = tokenType;
    zSql += n;
    assert( db->mallocFailed==0 || pParse->rc!=SQLITE_OK || startedWithOom );
    if( pParse->rc!=SQLITE_OK || db->mallocFailed ) break;
    if( pParse->rc!=SQLITE_OK ) break;
  }
  assert( nErr==0 );
#ifdef YYTRACKMAXSTACKDEPTH
  sqlite3_mutex_enter(sqlite3MallocMutex());
  sqlite3StatusHighwater(SQLITE_STATUS_PARSER_STACK,
      sqlite3ParserStackPeak(pEngine)
  );
  sqlite3_mutex_leave(sqlite3MallocMutex());
#endif /* YYDEBUG */
#ifdef sqlite3Parser_ENGINEALWAYSONSTACK
  sqlite3ParserFinalize(pEngine);
#else
  sqlite3ParserFree(pEngine, sqlite3_free);
#endif
  if( db->mallocFailed ){
    pParse->rc = SQLITE_NOMEM_BKPT;
  }
  if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){
    pParse->zErrMsg = sqlite3MPrintf(db, "%s", sqlite3ErrStr(pParse->rc));
  }
  if( pParse->zErrMsg || (pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE) ){
    if( pParse->zErrMsg==0 ){
      pParse->zErrMsg = sqlite3MPrintf(db, "%s", sqlite3ErrStr(pParse->rc));
    }
  assert( pzErrMsg!=0 );
  if( pParse->zErrMsg ){
    *pzErrMsg = pParse->zErrMsg;
    sqlite3_log(pParse->rc, "%s in \"%s\"", 
    sqlite3_log(pParse->rc, "%s in \"%s\"", pParse->zErrMsg, pParse->zTail);
                *pzErrMsg, pParse->zTail);
    pParse->zErrMsg = 0;
    nErr++;
  }
  pParse->zTail = zSql;
  if( pParse->pVdbe && pParse->nErr>0 && pParse->nested==0 ){
    sqlite3VdbeDelete(pParse->pVdbe);
    pParse->pVdbe = 0;
  }
#ifndef SQLITE_OMIT_SHARED_CACHE
  if( pParse->nested==0 ){
    sqlite3DbFree(db, pParse->aTableLock);
    pParse->aTableLock = 0;
    pParse->nTableLock = 0;
  }
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
  sqlite3_free(pParse->apVtabLock);
#endif

  if( !IN_SPECIAL_PARSE ){
  if( pParse->pNewTable && !IN_SPECIAL_PARSE ){
    /* If the pParse->declareVtab flag is set, do not delete any table 
    ** structure built up in pParse->pNewTable. The calling code (see vtab.c)
    ** will take responsibility for freeing the Table structure.
    */
    sqlite3DeleteTable(db, pParse->pNewTable);
  }
  if( !IN_RENAME_OBJECT ){
  if( pParse->pNewTrigger && !IN_RENAME_OBJECT ){
    sqlite3DeleteTrigger(db, pParse->pNewTrigger);
  }

  if( pParse->pWithToFree ) sqlite3WithDelete(db, pParse->pWithToFree);
  sqlite3DbFree(db, pParse->pVList);
  while( pParse->pAinc ){
  if( pParse->pVList ) sqlite3DbNNFreeNN(db, pParse->pVList);
  db->pParse = pParentParse;
    AutoincInfo *p = pParse->pAinc;
    pParse->pAinc = p->pNext;
    sqlite3DbFreeNN(db, p);
  }
  while( pParse->pZombieTab ){
    Table *p = pParse->pZombieTab;
    pParse->pZombieTab = p->pNextZombie;
    sqlite3DeleteTable(db, p);
  }
  assert( nErr==0 || pParse->rc!=SQLITE_OK );
  return nErr;
}


#ifdef SQLITE_ENABLE_NORMALIZE
/*
736
737
738
739
740
741
742
743

744
745
746
747

748
749
750
751
752
753
754
738
739
740
741
742
743
744

745
746
747
748

749
750
751
752
753
754
755
756







-
+



-
+







  Vdbe *pVdbe,       /* VM being reprepared */
  const char *zSql   /* The original SQL string */
){
  sqlite3 *db;       /* The database connection */
  int i;             /* Next unread byte of zSql[] */
  int n;             /* length of current token */
  int tokenType;     /* type of current token */
  int prevType;      /* Previous non-whitespace token */
  int prevType = 0;  /* Previous non-whitespace token */
  int nParen;        /* Number of nested levels of parentheses */
  int iStartIN;      /* Start of RHS of IN operator in z[] */
  int nParenAtIN;    /* Value of nParent at start of RHS of IN operator */
  int j;             /* Bytes of normalized SQL generated so far */
  u32 j;             /* Bytes of normalized SQL generated so far */
  sqlite3_str *pStr; /* The normalized SQL string under construction */

  db = sqlite3VdbeDb(pVdbe);
  tokenType = -1;
  nParen = iStartIN = nParenAtIN = 0;
  pStr = sqlite3_str_new(db);
  assert( pStr!=0 );  /* sqlite3_str_new() never returns NULL */
784
785
786
787
788
789
790
791

792
793
794
795
796
797
798
786
787
788
789
790
791
792

793
794
795
796
797
798
799
800







-
+







          nParenAtIN = nParen;
        }
        sqlite3_str_append(pStr, "(", 1);
        break;
      }
      case TK_RP: {
        if( iStartIN>0 && nParen==nParenAtIN ){
          assert( pStr->nChar>=iStartIN );
          assert( pStr->nChar>=(u32)iStartIN );
          pStr->nChar = iStartIN+1;
          sqlite3_str_append(pStr, "?,?,?", 5);
          iStartIN = 0;
        }
        nParen--;
        sqlite3_str_append(pStr, ")", 1);
        break;

Changes to src/treeview.c.

20
21
22
23
24
25
26
27


28
29
30


31
32
33
34
35
36

37
38
39
40
41
42
43


44
45
46




47
48
49
50
51
52
53

54
55
56
57

58
59
60

61
62
63
64
65
66
67
68
69

70
71
72
73
74
75
76
77
78
79
80
81

82
83















































84
85
86
87
88
89
90
91
92
93
94
95
96
97
98

99
100
101
102
103
104
105
106
107
108
109

110
111
112
113

114







115
116
117
118

119
120

121
122
123
124
125
126
127
128

129
130

131

132

133

134
135
136
137
138













139
140
141


142
143
144


145
146
147





148







149
150








151





152

153
154
155
156
157

158
159
160
161
162
163
164
165
166
167
168
169
170
171

172
173
174
175

176
177



178
179
180
181
182
183
184
185









186
187
188
189
190
191
192
193
194
195
196
197
198
199
200

201



202
203
204
205

206
207
208
209
210

211
212
213
214

215
216
217

218
219
220
221
222

223
224
225
226
227
228
229
230

231
232
233
234
235
236
237
238
239

240
241
242
243
244
245
246
247
248
249
250
251

252
253

254
255
256
257
258
259
260
261
262
263
264
265
266

267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282

283
284
285
286
287

288
289
290
291
292
293

294
295
296
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
20
21
22
23
24
25
26

27
28
29


30
31
32
33
34
35
36

37

38
39
40
41
42

43
44
45
46

47
48
49
50
51
52
53
54
55
56

57
58
59
60

61
62
63

64
65
66
67
68
69
70
71
72

73
74
75
76
77
78
79
80
81
82
83
84

85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148

149
150
151
152
153
154
155
156
157
158
159

160
161
162
163
164
165

166
167
168
169
170
171
172
173
174
175

176
177

178
179
180
181
182
183
184
185
186
187
188

189
190
191

192
193
194





195
196
197
198
199
200
201
202
203
204
205
206
207
208


209
210
211


212
213
214


215
216
217
218
219
220
221
222
223
224
225
226
227
228

229
230
231
232
233
234
235
236
237
238
239
240
241
242

243
244
245
246
247

248
249
250
251
252
253
254
255
256
257
258
259
260
261

262
263
264
265

266
267
268
269
270
271








272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296

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







-
+
+

-
-
+
+





-
+
-





-
+
+


-
+
+
+
+






-
+



-
+


-
+








-
+











-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+














-
+










-
+




+
-
+
+
+
+
+
+
+



-
+

-
+








+

-
+

+
-
+

+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+

-
-
+
+

-
-
+
+
+
+
+

+
+
+
+
+
+
+

-
+
+
+
+
+
+
+
+

+
+
+
+
+
-
+




-
+













-
+



-
+


+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+















+
-
+
+
+



-
+




-
+



-
+


-
+




-
+







-
+








-
+











-
+

-
+












-
+















-
+




-
+





-
+





-
+











+
+
+
+
+
+
+
-
+

-
+

-
+

+
+
+
+
+
+
+
+
+

-
+


-
+

-
-
+
+
+
+
+
+
+
+


-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+








+
-
+

-
+

-
+









-
-
+
+


-
+


-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+

+












+
+
+
+
+
+
-
+
+

+
-
-
+
+
+
















+





+








-
-
+
+




+





+









+






+







#include "sqliteInt.h"
#ifdef SQLITE_DEBUG

/*
** Add a new subitem to the tree.  The moreToFollow flag indicates that this
** is not the last item in the tree.
*/
static TreeView *sqlite3TreeViewPush(TreeView *p, u8 moreToFollow){
static void sqlite3TreeViewPush(TreeView **pp, u8 moreToFollow){
  TreeView *p = *pp;
  if( p==0 ){
    p = sqlite3_malloc64( sizeof(*p) );
    if( p==0 ) return 0;
    *pp = p = sqlite3_malloc64( sizeof(*p) );
    if( p==0 ) return;
    memset(p, 0, sizeof(*p));
  }else{
    p->iLevel++;
  }
  assert( moreToFollow==0 || moreToFollow==1 );
  if( p->iLevel<sizeof(p->bLine) ) p->bLine[p->iLevel] = moreToFollow;
  if( p->iLevel<(int)sizeof(p->bLine) ) p->bLine[p->iLevel] = moreToFollow;
  return p;
}

/*
** Finished with one layer of the tree
*/
static void sqlite3TreeViewPop(TreeView *p){
static void sqlite3TreeViewPop(TreeView **pp){
  TreeView *p = *pp;
  if( p==0 ) return;
  p->iLevel--;
  if( p->iLevel<0 ) sqlite3_free(p);
  if( p->iLevel<0 ){
    sqlite3_free(p);
    *pp = 0;
  }
}

/*
** Generate a single line of output for the tree, with a prefix that contains
** all the appropriate tree lines
*/
static void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){
void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){
  va_list ap;
  int i;
  StrAccum acc;
  char zBuf[500];
  char zBuf[1000];
  sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
  if( p ){
    for(i=0; i<p->iLevel && i<sizeof(p->bLine)-1; i++){
    for(i=0; i<p->iLevel && i<(int)sizeof(p->bLine)-1; i++){
      sqlite3_str_append(&acc, p->bLine[i] ? "|   " : "    ", 4);
    }
    sqlite3_str_append(&acc, p->bLine[i] ? "|-- " : "'-- ", 4);
  }
  if( zFormat!=0 ){
    va_start(ap, zFormat);
    sqlite3_str_vappendf(&acc, zFormat, ap);
    va_end(ap);
    assert( acc.nChar>0 );
    assert( acc.nChar>0 || acc.accError );
    sqlite3_str_append(&acc, "\n", 1);
  }
  sqlite3StrAccumFinish(&acc);
  fprintf(stdout,"%s", zBuf);
  fflush(stdout);
}

/*
** Shorthand for starting a new tree item that consists of a single label
*/
static void sqlite3TreeViewItem(TreeView *p, const char *zLabel,u8 moreFollows){
  p = sqlite3TreeViewPush(p, moreFollows);
  sqlite3TreeViewPush(&p, moreFollows);
  sqlite3TreeViewLine(p, "%s", zLabel);
}

/*
** Show a list of Column objects in tree format.
*/
void sqlite3TreeViewColumnList(
  TreeView *pView,
  const Column *aCol,
  int nCol,
  u8 moreToFollow
){
  int i;
  sqlite3TreeViewPush(&pView, moreToFollow);
  sqlite3TreeViewLine(pView, "COLUMNS");
  for(i=0; i<nCol; i++){
    u16 flg = aCol[i].colFlags;
    int colMoreToFollow = i<(nCol - 1);
    sqlite3TreeViewPush(&pView, colMoreToFollow);
    sqlite3TreeViewLine(pView, 0);
    printf(" %s", aCol[i].zCnName);
    switch( aCol[i].eCType ){
      case COLTYPE_ANY:      printf(" ANY");        break;
      case COLTYPE_BLOB:     printf(" BLOB");       break;
      case COLTYPE_INT:      printf(" INT");        break;
      case COLTYPE_INTEGER:  printf(" INTEGER");    break;
      case COLTYPE_REAL:     printf(" REAL");       break;
      case COLTYPE_TEXT:     printf(" TEXT");       break;
      case COLTYPE_CUSTOM: {
        if( flg & COLFLAG_HASTYPE ){
          const char *z = aCol[i].zCnName;
          z += strlen(z)+1;
          printf(" X-%s", z);
          break;
        }
      }
    }
    if( flg & COLFLAG_PRIMKEY ) printf(" PRIMARY KEY");
    if( flg & COLFLAG_HIDDEN ) printf(" HIDDEN");
#ifdef COLFLAG_NOEXPAND
    if( flg & COLFLAG_NOEXPAND ) printf(" NO-EXPAND");
#endif
    if( flg ) printf(" flags=%04x", flg);
    printf("\n");      
    fflush(stdout);
    sqlite3TreeViewPop(&pView);
  }
  sqlite3TreeViewPop(&pView);
}

/*
** Generate a human-readable description of a WITH clause.
*/
void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 moreToFollow){
  int i;
  if( pWith==0 ) return;
  if( pWith->nCte==0 ) return;
  if( pWith->pOuter ){
    sqlite3TreeViewLine(pView, "WITH (0x%p, pOuter=0x%p)",pWith,pWith->pOuter);
  }else{
    sqlite3TreeViewLine(pView, "WITH (0x%p)", pWith);
  }
  if( pWith->nCte>0 ){
    pView = sqlite3TreeViewPush(pView, 1);
    sqlite3TreeViewPush(&pView, moreToFollow);
    for(i=0; i<pWith->nCte; i++){
      StrAccum x;
      char zLine[1000];
      const struct Cte *pCte = &pWith->a[i];
      sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
      sqlite3_str_appendf(&x, "%s", pCte->zName);
      if( pCte->pCols && pCte->pCols->nExpr>0 ){
        char cSep = '(';
        int j;
        for(j=0; j<pCte->pCols->nExpr; j++){
          sqlite3_str_appendf(&x, "%c%s", cSep, pCte->pCols->a[j].zName);
          sqlite3_str_appendf(&x, "%c%s", cSep, pCte->pCols->a[j].zEName);
          cSep = ',';
        }
        sqlite3_str_appendf(&x, ")");
      }
      if( pCte->eM10d!=M10d_Any ){
      sqlite3_str_appendf(&x, " AS");
        sqlite3_str_appendf(&x, " %sMATERIALIZED", 
           pCte->eM10d==M10d_No ? "NOT " : "");
      }
      if( pCte->pUse ){
        sqlite3_str_appendf(&x, " (pUse=0x%p, nUse=%d)", pCte->pUse,
                 pCte->pUse->nUse);
      }
      sqlite3StrAccumFinish(&x);
      sqlite3TreeViewItem(pView, zLine, i<pWith->nCte-1);
      sqlite3TreeViewSelect(pView, pCte->pSelect, 0);
      sqlite3TreeViewPop(pView);
      sqlite3TreeViewPop(&pView);
    }
    sqlite3TreeViewPop(pView);
    sqlite3TreeViewPop(&pView);
  }
}

/*
** Generate a human-readable description of a SrcList object.
*/
void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){
  int i;
  if( pSrc==0 ) return;
  for(i=0; i<pSrc->nSrc; i++){
    const struct SrcList_item *pItem = &pSrc->a[i];
    const SrcItem *pItem = &pSrc->a[i];
    StrAccum x;
    int n = 0;
    char zLine[100];
    char zLine[1000];
    sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
    x.printfFlags |= SQLITE_PRINTF_INTERNAL;
    sqlite3_str_appendf(&x, "{%d,*}", pItem->iCursor);
    if( pItem->zDatabase ){
      sqlite3_str_appendf(&x, " %s.%s", pItem->zDatabase, pItem->zName);
    }else if( pItem->zName ){
      sqlite3_str_appendf(&x, " %s", pItem->zName);
    sqlite3_str_appendf(&x, "{%d:*} %!S", pItem->iCursor, pItem);
    if( pItem->pTab ){
      sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx",
           pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab, pItem->colUsed);
    }
    if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))==(JT_LEFT|JT_RIGHT) ){
      sqlite3_str_appendf(&x, " FULL-OUTER-JOIN");
    }else if( pItem->fg.jointype & JT_LEFT ){
      sqlite3_str_appendf(&x, " LEFT-JOIN");
    }else if( pItem->fg.jointype & JT_RIGHT ){
      sqlite3_str_appendf(&x, " RIGHT-JOIN");
    }else if( pItem->fg.jointype & JT_CROSS ){
      sqlite3_str_appendf(&x, " CROSS-JOIN");
    }
    if( pItem->pTab ){
      sqlite3_str_appendf(&x, " tabname=%Q", pItem->pTab->zName);
    if( pItem->fg.jointype & JT_LTORJ ){
      sqlite3_str_appendf(&x, " LTORJ");
    }
    if( pItem->zAlias ){
      sqlite3_str_appendf(&x, " (AS %s)", pItem->zAlias);
    if( pItem->fg.fromDDL ){
      sqlite3_str_appendf(&x, " DDL");
    }
    if( pItem->fg.jointype & JT_LEFT ){
      sqlite3_str_appendf(&x, " LEFT-JOIN");
    if( pItem->fg.isCte ){
      sqlite3_str_appendf(&x, " CteUse=0x%p", pItem->u2.pCteUse);
    }
    if( pItem->fg.isOn || (pItem->fg.isUsing==0 && pItem->u3.pOn!=0) ){
      sqlite3_str_appendf(&x, " ON");
    }
    if( pItem->fg.isTabFunc )      sqlite3_str_appendf(&x, " isTabFunc");
    if( pItem->fg.isCorrelated )   sqlite3_str_appendf(&x, " isCorrelated");
    if( pItem->fg.isMaterialized ) sqlite3_str_appendf(&x, " isMaterialized");
    if( pItem->fg.viaCoroutine )   sqlite3_str_appendf(&x, " viaCoroutine");
    if( pItem->fg.notCte )         sqlite3_str_appendf(&x, " notCte");
    if( pItem->fg.isNestedFrom )   sqlite3_str_appendf(&x, " isNestedFrom");

    sqlite3StrAccumFinish(&x);
    sqlite3TreeViewItem(pView, zLine, i<pSrc->nSrc-1); 
    sqlite3TreeViewItem(pView, zLine, i<pSrc->nSrc-1);
    n = 0;
    if( pItem->pSelect ) n++;
    if( pItem->fg.isTabFunc ) n++;
    if( pItem->fg.isUsing ) n++;
    if( pItem->fg.isUsing ){
      sqlite3TreeViewIdList(pView, pItem->u3.pUsing, (--n)>0, "USING");
    }
    if( pItem->pSelect ){
      if( pItem->pTab ){
        Table *pTab = pItem->pTab;
        sqlite3TreeViewColumnList(pView, pTab->aCol, pTab->nCol, 1);
      }
      assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) );
      sqlite3TreeViewSelect(pView, pItem->pSelect, 0);
      sqlite3TreeViewSelect(pView, pItem->pSelect, (--n)>0);
    }
    if( pItem->fg.isTabFunc ){
      sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:");
    }
    sqlite3TreeViewPop(pView);
    sqlite3TreeViewPop(&pView);
  }
}

/*
** Generate a human-readable description of a Select object.
*/
void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
  int n = 0;
  int cnt = 0;
  if( p==0 ){
    sqlite3TreeViewLine(pView, "nil-SELECT");
    return;
  } 
  pView = sqlite3TreeViewPush(pView, moreToFollow);
  sqlite3TreeViewPush(&pView, moreToFollow);
  if( p->pWith ){
    sqlite3TreeViewWith(pView, p->pWith, 1);
    cnt = 1;
    sqlite3TreeViewPush(pView, 1);
    sqlite3TreeViewPush(&pView, 1);
  }
  do{
    if( p->selFlags & SF_WhereBegin ){
      sqlite3TreeViewLine(pView, "sqlite3WhereBegin()");
    }else{
    sqlite3TreeViewLine(pView,
      "SELECT%s%s (%u/%p) selFlags=0x%x nSelectRow=%d",
      ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
      ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""),
      p->selId, p, p->selFlags,
      (int)p->nSelectRow
    );
    if( cnt++ ) sqlite3TreeViewPop(pView);
      sqlite3TreeViewLine(pView,
        "SELECT%s%s (%u/%p) selFlags=0x%x nSelectRow=%d",
        ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
        ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""),
        p->selId, p, p->selFlags,
        (int)p->nSelectRow
      );
    }
    if( cnt++ ) sqlite3TreeViewPop(&pView);
    if( p->pPrior ){
      n = 1000;
    }else{
      n = 0;
      if( p->pSrc && p->pSrc->nSrc ) n++;
      if( p->pWhere ) n++;
      if( p->pGroupBy ) n++;
      if( p->pHaving ) n++;
      if( p->pOrderBy ) n++;
      if( p->pLimit ) n++;
#ifndef SQLITE_OMIT_WINDOWFUNC
      if( p->pWin ) n++;
      if( p->pWinDefn ) n++;
#endif
    }
    if( p->pEList ){
    sqlite3TreeViewExprList(pView, p->pEList, (n--)>0, "result-set");
      sqlite3TreeViewExprList(pView, p->pEList, n>0, "result-set");
    }
    n--;
#ifndef SQLITE_OMIT_WINDOWFUNC
    if( p->pWin ){
      Window *pX;
      pView = sqlite3TreeViewPush(pView, (n--)>0);
      sqlite3TreeViewPush(&pView, (n--)>0);
      sqlite3TreeViewLine(pView, "window-functions");
      for(pX=p->pWin; pX; pX=pX->pNextWin){
        sqlite3TreeViewWinFunc(pView, pX, pX->pNextWin!=0);
      }
      sqlite3TreeViewPop(pView);
      sqlite3TreeViewPop(&pView);
    }
#endif
    if( p->pSrc && p->pSrc->nSrc ){
      pView = sqlite3TreeViewPush(pView, (n--)>0);
      sqlite3TreeViewPush(&pView, (n--)>0);
      sqlite3TreeViewLine(pView, "FROM");
      sqlite3TreeViewSrcList(pView, p->pSrc);
      sqlite3TreeViewPop(pView);
      sqlite3TreeViewPop(&pView);
    }
    if( p->pWhere ){
      sqlite3TreeViewItem(pView, "WHERE", (n--)>0);
      sqlite3TreeViewExpr(pView, p->pWhere, 0);
      sqlite3TreeViewPop(pView);
      sqlite3TreeViewPop(&pView);
    }
    if( p->pGroupBy ){
      sqlite3TreeViewExprList(pView, p->pGroupBy, (n--)>0, "GROUPBY");
    }
    if( p->pHaving ){
      sqlite3TreeViewItem(pView, "HAVING", (n--)>0);
      sqlite3TreeViewExpr(pView, p->pHaving, 0);
      sqlite3TreeViewPop(pView);
      sqlite3TreeViewPop(&pView);
    }
#ifndef SQLITE_OMIT_WINDOWFUNC
    if( p->pWinDefn ){
      Window *pX;
      sqlite3TreeViewItem(pView, "WINDOW", (n--)>0);
      for(pX=p->pWinDefn; pX; pX=pX->pNextWin){
        sqlite3TreeViewWindow(pView, pX, pX->pNextWin!=0);
      }
      sqlite3TreeViewPop(pView);
      sqlite3TreeViewPop(&pView);
    }
#endif
    if( p->pOrderBy ){
      sqlite3TreeViewExprList(pView, p->pOrderBy, (n--)>0, "ORDERBY");
    }
    if( p->pLimit ){
      sqlite3TreeViewItem(pView, "LIMIT", (n--)>0);
      sqlite3TreeViewExpr(pView, p->pLimit->pLeft, p->pLimit->pRight!=0);
      if( p->pLimit->pRight ){
        sqlite3TreeViewItem(pView, "OFFSET", (n--)>0);
        sqlite3TreeViewExpr(pView, p->pLimit->pRight, 0);
        sqlite3TreeViewPop(pView);
        sqlite3TreeViewPop(&pView);
      }
      sqlite3TreeViewPop(pView);
      sqlite3TreeViewPop(&pView);
    }
    if( p->pPrior ){
      const char *zOp = "UNION";
      switch( p->op ){
        case TK_ALL:         zOp = "UNION ALL";  break;
        case TK_INTERSECT:   zOp = "INTERSECT";  break;
        case TK_EXCEPT:      zOp = "EXCEPT";     break;
      }
      sqlite3TreeViewItem(pView, zOp, 1);
    }
    p = p->pPrior;
  }while( p!=0 );
  sqlite3TreeViewPop(pView);
  sqlite3TreeViewPop(&pView);
}

#ifndef SQLITE_OMIT_WINDOWFUNC
/*
** Generate a description of starting or stopping bounds
*/
void sqlite3TreeViewBound(
  TreeView *pView,        /* View context */
  u8 eBound,              /* UNBOUNDED, CURRENT, PRECEDING, FOLLOWING */
  Expr *pExpr,            /* Value for PRECEDING or FOLLOWING */
  u8 moreToFollow         /* True if more to follow */
){
  switch( eBound ){
    case TK_UNBOUNDED: {
      sqlite3TreeViewItem(pView, "UNBOUNDED", moreToFollow);
      sqlite3TreeViewPop(pView);
      sqlite3TreeViewPop(&pView);
      break;
    }
    case TK_CURRENT: {
      sqlite3TreeViewItem(pView, "CURRENT", moreToFollow);
      sqlite3TreeViewPop(pView);
      sqlite3TreeViewPop(&pView);
      break;
    }
    case TK_PRECEDING: {
      sqlite3TreeViewItem(pView, "PRECEDING", moreToFollow);
      sqlite3TreeViewExpr(pView, pExpr, 0);
      sqlite3TreeViewPop(pView);
      sqlite3TreeViewPop(&pView);
      break;
    }
    case TK_FOLLOWING: {
      sqlite3TreeViewItem(pView, "FOLLOWING", moreToFollow);
      sqlite3TreeViewExpr(pView, pExpr, 0);
      sqlite3TreeViewPop(pView);
      sqlite3TreeViewPop(&pView);
      break;
    }
  }
}
#endif /* SQLITE_OMIT_WINDOWFUNC */

#ifndef SQLITE_OMIT_WINDOWFUNC
/*
** Generate a human-readable explanation for a Window object
*/
void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u8 more){
  int nElement = 0;
  if( pWin==0 ) return;
  if( pWin->pFilter ){
    sqlite3TreeViewItem(pView, "FILTER", 1);
    sqlite3TreeViewExpr(pView, pWin->pFilter, 0);
    sqlite3TreeViewPop(&pView);
  }
  pView = sqlite3TreeViewPush(pView, more);
  sqlite3TreeViewPush(&pView, more);
  if( pWin->zName ){
    sqlite3TreeViewLine(pView, "OVER %s", pWin->zName);
    sqlite3TreeViewLine(pView, "OVER %s (%p)", pWin->zName, pWin);
  }else{
    sqlite3TreeViewLine(pView, "OVER");
    sqlite3TreeViewLine(pView, "OVER (%p)", pWin);
  }
  if( pWin->zBase )    nElement++;
  if( pWin->pOrderBy ) nElement++;
  if( pWin->eFrmType ) nElement++;
  if( pWin->eExclude ) nElement++;
  if( pWin->zBase ){
    sqlite3TreeViewPush(&pView, (--nElement)>0);
    sqlite3TreeViewLine(pView, "window: %s", pWin->zBase);
    sqlite3TreeViewPop(&pView);
  }
  if( pWin->pPartition ){
    sqlite3TreeViewExprList(pView, pWin->pPartition, 1, "PARTITION-BY");
    sqlite3TreeViewExprList(pView, pWin->pPartition, nElement>0,"PARTITION-BY");
  }
  if( pWin->pOrderBy ){
    sqlite3TreeViewExprList(pView, pWin->pOrderBy, 1, "ORDER-BY");
    sqlite3TreeViewExprList(pView, pWin->pOrderBy, (--nElement)>0, "ORDER-BY");
  }
  if( pWin->eType ){
    sqlite3TreeViewItem(pView, pWin->eType==TK_RANGE ? "RANGE" : "ROWS", 0);
  if( pWin->eFrmType ){
    char zBuf[30];
    const char *zFrmType = "ROWS";
    if( pWin->eFrmType==TK_RANGE ) zFrmType = "RANGE";
    if( pWin->eFrmType==TK_GROUPS ) zFrmType = "GROUPS";
    sqlite3_snprintf(sizeof(zBuf),zBuf,"%s%s",zFrmType,
        pWin->bImplicitFrame ? " (implied)" : "");
    sqlite3TreeViewItem(pView, zBuf, (--nElement)>0);
    sqlite3TreeViewBound(pView, pWin->eStart, pWin->pStart, 1);
    sqlite3TreeViewBound(pView, pWin->eEnd, pWin->pEnd, 0);
    sqlite3TreeViewPop(pView);
    sqlite3TreeViewPop(&pView);
  }
  if( pWin->eExclude ){
    char zBuf[30];
    const char *zExclude;
    switch( pWin->eExclude ){
      case TK_NO:      zExclude = "NO OTHERS";   break;
      case TK_CURRENT: zExclude = "CURRENT ROW"; break;
      case TK_GROUP:   zExclude = "GROUP";       break;
      case TK_TIES:    zExclude = "TIES";        break;
      default:
        sqlite3_snprintf(sizeof(zBuf),zBuf,"invalid(%d)", pWin->eExclude);
        zExclude = zBuf;
        break;
    }
    sqlite3TreeViewPush(&pView, 0);
    sqlite3TreeViewLine(pView, "EXCLUDE %s", zExclude);
  sqlite3TreeViewPop(pView);
    sqlite3TreeViewPop(&pView);
  }
  sqlite3TreeViewPop(&pView);
}
#endif /* SQLITE_OMIT_WINDOWFUNC */

#ifndef SQLITE_OMIT_WINDOWFUNC
/*
** Generate a human-readable explanation for a Window Function object
*/
void sqlite3TreeViewWinFunc(TreeView *pView, const Window *pWin, u8 more){
  if( pWin==0 ) return;
  pView = sqlite3TreeViewPush(pView, more);
  sqlite3TreeViewPush(&pView, more);
  sqlite3TreeViewLine(pView, "WINFUNC %s(%d)",
                       pWin->pFunc->zName, pWin->pFunc->nArg);
                       pWin->pWFunc->zName, pWin->pWFunc->nArg);
  sqlite3TreeViewWindow(pView, pWin, 0);
  sqlite3TreeViewPop(pView);
  sqlite3TreeViewPop(&pView);
}
#endif /* SQLITE_OMIT_WINDOWFUNC */

/*
** Generate a human-readable explanation of an expression tree.
*/
void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
  const char *zBinOp = 0;   /* Binary operator */
  const char *zUniOp = 0;   /* Unary operator */
  char zFlgs[60];
  pView = sqlite3TreeViewPush(pView, moreToFollow);
  char zFlgs[200];
  sqlite3TreeViewPush(&pView, moreToFollow);
  if( pExpr==0 ){
    sqlite3TreeViewLine(pView, "nil");
    sqlite3TreeViewPop(pView);
    sqlite3TreeViewPop(&pView);
    return;
  }
  if( pExpr->flags ){
    if( ExprHasProperty(pExpr, EP_FromJoin) ){
      sqlite3_snprintf(sizeof(zFlgs),zFlgs,"  flags=0x%x iRJT=%d",
                       pExpr->flags, pExpr->iRightJoinTable);
  if( pExpr->flags || pExpr->affExpr || pExpr->vvaFlags || pExpr->pAggInfo ){
    StrAccum x;
    sqlite3StrAccumInit(&x, 0, zFlgs, sizeof(zFlgs), 0);
    sqlite3_str_appendf(&x, " fg.af=%x.%c",
      pExpr->flags, pExpr->affExpr ? pExpr->affExpr : 'n');
    if( ExprHasProperty(pExpr, EP_OuterON) ){
      sqlite3_str_appendf(&x, " outer.iJoin=%d", pExpr->w.iJoin);
    }
    if( ExprHasProperty(pExpr, EP_InnerON) ){
      sqlite3_str_appendf(&x, " inner.iJoin=%d", pExpr->w.iJoin);
    }
    if( ExprHasProperty(pExpr, EP_FromDDL) ){
      sqlite3_str_appendf(&x, " DDL");
    }
    if( ExprHasVVAProperty(pExpr, EP_Immutable) ){
      sqlite3_str_appendf(&x, " IMMUTABLE");
    }
    if( pExpr->pAggInfo!=0 ){
    }else{
      sqlite3_snprintf(sizeof(zFlgs),zFlgs,"  flags=0x%x",pExpr->flags);
      sqlite3_str_appendf(&x, " agg-column[%d]", pExpr->iAgg);
    }
    sqlite3StrAccumFinish(&x);
  }else{
    zFlgs[0] = 0;
  }
  switch( pExpr->op ){
    case TK_AGG_COLUMN: {
      sqlite3TreeViewLine(pView, "AGG{%d:%d}%s",
            pExpr->iTable, pExpr->iColumn, zFlgs);
      break;
    }
    case TK_COLUMN: {
      if( pExpr->iTable<0 ){
        /* This only happens when coding check constraints */
        char zOp2[16];
        if( pExpr->op2 ){
          sqlite3_snprintf(sizeof(zOp2),zOp2," op2=0x%02x",pExpr->op2);
        }else{
          zOp2[0] = 0;
        }
        sqlite3TreeViewLine(pView, "COLUMN(%d)%s", pExpr->iColumn, zFlgs);
        sqlite3TreeViewLine(pView, "COLUMN(%d)%s%s",
                                    pExpr->iColumn, zFlgs, zOp2);
      }else{
        assert( ExprUseYTab(pExpr) );
        sqlite3TreeViewLine(pView, "{%d:%d}%s",
                             pExpr->iTable, pExpr->iColumn, zFlgs);
        sqlite3TreeViewLine(pView, "{%d:%d} pTab=%p%s",
                        pExpr->iTable, pExpr->iColumn,
                        pExpr->y.pTab, zFlgs);
      }
      if( ExprHasProperty(pExpr, EP_FixedCol) ){
        sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
      }
      break;
    }
    case TK_INTEGER: {
      if( pExpr->flags & EP_IntValue ){
        sqlite3TreeViewLine(pView, "%d", pExpr->u.iValue);
      }else{
        sqlite3TreeViewLine(pView, "%s", pExpr->u.zToken);
      }
      break;
    }
#ifndef SQLITE_OMIT_FLOATING_POINT
    case TK_FLOAT: {
      assert( !ExprHasProperty(pExpr, EP_IntValue) );
      sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
      break;
    }
#endif
    case TK_STRING: {
      assert( !ExprHasProperty(pExpr, EP_IntValue) );
      sqlite3TreeViewLine(pView,"%Q", pExpr->u.zToken);
      break;
    }
    case TK_NULL: {
      sqlite3TreeViewLine(pView,"NULL");
      break;
    }
    case TK_TRUEFALSE: {
      sqlite3TreeViewLine(pView,
         sqlite3ExprTruthValue(pExpr) ? "TRUE" : "FALSE");
      sqlite3TreeViewLine(pView,"%s%s",
         sqlite3ExprTruthValue(pExpr) ? "TRUE" : "FALSE", zFlgs);
      break;
    }
#ifndef SQLITE_OMIT_BLOB_LITERAL
    case TK_BLOB: {
      assert( !ExprHasProperty(pExpr, EP_IntValue) );
      sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
      break;
    }
#endif
    case TK_VARIABLE: {
      assert( !ExprHasProperty(pExpr, EP_IntValue) );
      sqlite3TreeViewLine(pView,"VARIABLE(%s,%d)",
                          pExpr->u.zToken, pExpr->iColumn);
      break;
    }
    case TK_REGISTER: {
      sqlite3TreeViewLine(pView,"REGISTER(%d)", pExpr->iTable);
      break;
    }
    case TK_ID: {
      assert( !ExprHasProperty(pExpr, EP_IntValue) );
      sqlite3TreeViewLine(pView,"ID \"%w\"", pExpr->u.zToken);
      break;
    }
#ifndef SQLITE_OMIT_CAST
    case TK_CAST: {
      /* Expressions of the form:   CAST(pLeft AS token) */
      assert( !ExprHasProperty(pExpr, EP_IntValue) );
      sqlite3TreeViewLine(pView,"CAST %Q", pExpr->u.zToken);
      sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
      break;
    }
#endif /* SQLITE_OMIT_CAST */
    case TK_LT:      zBinOp = "LT";     break;
    case TK_LE:      zBinOp = "LE";     break;
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
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645

646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665

666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683

684
685
686
687
688
689
690


691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706

707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727

728
729
730
731
732
733
734
735
736
737
738
739
740
741

742
743
744

745
746
747
748
749
750
751
752
753
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







+















-
+






+






+
+
+
+
+
+
-
+
+
+












+


-
+




+

-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+













+





+
-
+




+
+
+
+
+
+
+
+
+
-
+
+

-
+




















+
-
-
-
+
+
+
+
+







    case TK_BITAND:  zBinOp = "BITAND"; break;
    case TK_BITOR:   zBinOp = "BITOR";  break;
    case TK_SLASH:   zBinOp = "DIV";    break;
    case TK_LSHIFT:  zBinOp = "LSHIFT"; break;
    case TK_RSHIFT:  zBinOp = "RSHIFT"; break;
    case TK_CONCAT:  zBinOp = "CONCAT"; break;
    case TK_DOT:     zBinOp = "DOT";    break;
    case TK_LIMIT:   zBinOp = "LIMIT";  break;

    case TK_UMINUS:  zUniOp = "UMINUS"; break;
    case TK_UPLUS:   zUniOp = "UPLUS";  break;
    case TK_BITNOT:  zUniOp = "BITNOT"; break;
    case TK_NOT:     zUniOp = "NOT";    break;
    case TK_ISNULL:  zUniOp = "ISNULL"; break;
    case TK_NOTNULL: zUniOp = "NOTNULL"; break;

    case TK_TRUTH: {
      int x;
      const char *azOp[] = {
         "IS-FALSE", "IS-TRUE", "IS-NOT-FALSE", "IS-NOT-TRUE"
      };
      assert( pExpr->op2==TK_IS || pExpr->op2==TK_ISNOT );
      assert( pExpr->pRight );
      assert( pExpr->pRight->op==TK_TRUEFALSE );
      assert( sqlite3ExprSkipCollate(pExpr->pRight)->op==TK_TRUEFALSE );
      x = (pExpr->op2==TK_ISNOT)*2 + sqlite3ExprTruthValue(pExpr->pRight);
      zUniOp = azOp[x];
      break;
    }

    case TK_SPAN: {
      assert( !ExprHasProperty(pExpr, EP_IntValue) );
      sqlite3TreeViewLine(pView, "SPAN %Q", pExpr->u.zToken);
      sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
      break;
    }

    case TK_COLLATE: {
      /* COLLATE operators without the EP_Collate flag are intended to
      ** emulate collation associated with a table column.  These show
      ** up in the treeview output as "SOFT-COLLATE".  Explicit COLLATE
      ** operators that appear in the original SQL always have the
      ** EP_Collate bit set and appear in treeview output as just "COLLATE" */
      assert( !ExprHasProperty(pExpr, EP_IntValue) );
      sqlite3TreeViewLine(pView, "COLLATE %Q", pExpr->u.zToken);
      sqlite3TreeViewLine(pView, "%sCOLLATE %Q%s",
        !ExprHasProperty(pExpr, EP_Collate) ? "SOFT-" : "",
        pExpr->u.zToken, zFlgs);
      sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
      break;
    }

    case TK_AGG_FUNCTION:
    case TK_FUNCTION: {
      ExprList *pFarg;       /* List of function arguments */
      Window *pWin;
      if( ExprHasProperty(pExpr, EP_TokenOnly) ){
        pFarg = 0;
        pWin = 0;
      }else{
        assert( ExprUseXList(pExpr) );
        pFarg = pExpr->x.pList;
#ifndef SQLITE_OMIT_WINDOWFUNC
        pWin = pExpr->y.pWin;
        pWin = ExprHasProperty(pExpr, EP_WinFunc) ? pExpr->y.pWin : 0;
#else
        pWin = 0;
#endif 
      }
      assert( !ExprHasProperty(pExpr, EP_IntValue) );
      if( pExpr->op==TK_AGG_FUNCTION ){
        sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q",
                             pExpr->op2, pExpr->u.zToken);
        sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q%s agg=%d[%d]/%p",
                             pExpr->op2, pExpr->u.zToken, zFlgs,
                             pExpr->pAggInfo ? pExpr->pAggInfo->selId : 0,
                             pExpr->iAgg, pExpr->pAggInfo);
      }else if( pExpr->op2!=0 ){
        const char *zOp2;
        char zBuf[8];
        sqlite3_snprintf(sizeof(zBuf),zBuf,"0x%02x",pExpr->op2);
        zOp2 = zBuf;
        if( pExpr->op2==NC_IsCheck ) zOp2 = "NC_IsCheck";
        if( pExpr->op2==NC_IdxExpr ) zOp2 = "NC_IdxExpr";
        if( pExpr->op2==NC_PartIdx ) zOp2 = "NC_PartIdx";
        if( pExpr->op2==NC_GenCol ) zOp2 = "NC_GenCol";
        sqlite3TreeViewLine(pView, "FUNCTION %Q%s op2=%s",
                            pExpr->u.zToken, zFlgs, zOp2);
      }else{
        sqlite3TreeViewLine(pView, "FUNCTION %Q", pExpr->u.zToken);
        sqlite3TreeViewLine(pView, "FUNCTION %Q%s", pExpr->u.zToken, zFlgs);
      }
      if( pFarg ){
        sqlite3TreeViewExprList(pView, pFarg, pWin!=0, 0);
      }
#ifndef SQLITE_OMIT_WINDOWFUNC
      if( pWin ){
        sqlite3TreeViewWindow(pView, pWin, 0);
      }
#endif
      break;
    }
#ifndef SQLITE_OMIT_SUBQUERY
    case TK_EXISTS: {
      assert( ExprUseXSelect(pExpr) );
      sqlite3TreeViewLine(pView, "EXISTS-expr flags=0x%x", pExpr->flags);
      sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
      break;
    }
    case TK_SELECT: {
      assert( ExprUseXSelect(pExpr) );
      sqlite3TreeViewLine(pView, "SELECT-expr flags=0x%x", pExpr->flags);
      sqlite3TreeViewLine(pView, "subquery-expr flags=0x%x", pExpr->flags);
      sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
      break;
    }
    case TK_IN: {
      sqlite3_str *pStr = sqlite3_str_new(0);
      char *z;
      sqlite3_str_appendf(pStr, "IN flags=0x%x", pExpr->flags);
      if( pExpr->iTable ) sqlite3_str_appendf(pStr, " iTable=%d",pExpr->iTable);
      if( ExprHasProperty(pExpr, EP_Subrtn) ){
        sqlite3_str_appendf(pStr, " subrtn(%d,%d)",
            pExpr->y.sub.regReturn, pExpr->y.sub.iAddr);
      }
      z = sqlite3_str_finish(pStr);
      sqlite3TreeViewLine(pView, "IN flags=0x%x", pExpr->flags);
      sqlite3TreeViewLine(pView, z);
      sqlite3_free(z);
      sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
      if( ExprHasProperty(pExpr, EP_xIsSelect) ){
      if( ExprUseXSelect(pExpr) ){
        sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
      }else{
        sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
      }
      break;
    }
#endif /* SQLITE_OMIT_SUBQUERY */

    /*
    **    x BETWEEN y AND z
    **
    ** This is equivalent to
    **
    **    x>=y AND x<=z
    **
    ** X is stored in pExpr->pLeft.
    ** Y is stored in pExpr->pList->a[0].pExpr.
    ** Z is stored in pExpr->pList->a[1].pExpr.
    */
    case TK_BETWEEN: {
      const Expr *pX, *pY, *pZ;
      Expr *pX = pExpr->pLeft;
      Expr *pY = pExpr->x.pList->a[0].pExpr;
      Expr *pZ = pExpr->x.pList->a[1].pExpr;
      pX = pExpr->pLeft;
      assert( ExprUseXList(pExpr) );
      assert( pExpr->x.pList->nExpr==2 );
      pY = pExpr->x.pList->a[0].pExpr;
      pZ = pExpr->x.pList->a[1].pExpr;
      sqlite3TreeViewLine(pView, "BETWEEN");
      sqlite3TreeViewExpr(pView, pX, 1);
      sqlite3TreeViewExpr(pView, pY, 1);
      sqlite3TreeViewExpr(pView, pZ, 0);
      break;
    }
    case TK_TRIGGER: {
579
580
581
582
583
584
585

586
587
588
589
590
591
592

593
594
595
596
597

598
599
600
601
602
603
604
605
606
607
608


609


610
611
612
613




614
615
616
617
618
619
620

















621
622
623
624
625
626
627
628
629
630
631
632
633

634
635

636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655

656
657
658

659
660
661


662












663
664
665
666
667
668
669
670
671
672

673
674
675
676
677
678
679
680
681
682
683

684
685









































































































































































































































































































































































686







687
688
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300







+






-
+





+











+
+
-
+
+



-
+
+
+
+







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+












-
+

-
+



















-
+


-
+



+
+
-
+
+
+
+
+
+
+
+
+
+
+
+









-
+










-
+

-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+


      sqlite3TreeViewLine(pView, "%s(%d)", 
          pExpr->iTable ? "NEW" : "OLD", pExpr->iColumn);
      break;
    }
    case TK_CASE: {
      sqlite3TreeViewLine(pView, "CASE");
      sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
      assert( ExprUseXList(pExpr) );
      sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
      break;
    }
#ifndef SQLITE_OMIT_TRIGGER
    case TK_RAISE: {
      const char *zType = "unk";
      switch( pExpr->affinity ){
      switch( pExpr->affExpr ){
        case OE_Rollback:   zType = "rollback";  break;
        case OE_Abort:      zType = "abort";     break;
        case OE_Fail:       zType = "fail";      break;
        case OE_Ignore:     zType = "ignore";    break;
      }
      assert( !ExprHasProperty(pExpr, EP_IntValue) );
      sqlite3TreeViewLine(pView, "RAISE %s(%Q)", zType, pExpr->u.zToken);
      break;
    }
#endif
    case TK_MATCH: {
      sqlite3TreeViewLine(pView, "MATCH {%d:%d}%s",
                          pExpr->iTable, pExpr->iColumn, zFlgs);
      sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
      break;
    }
    case TK_VECTOR: {
      char *z = sqlite3_mprintf("VECTOR%s",zFlgs);
      assert( ExprUseXList(pExpr) );
      sqlite3TreeViewBareExprList(pView, pExpr->x.pList, "VECTOR");
      sqlite3TreeViewBareExprList(pView, pExpr->x.pList, z);
      sqlite3_free(z);
      break;
    }
    case TK_SELECT_COLUMN: {
      sqlite3TreeViewLine(pView, "SELECT-COLUMN %d", pExpr->iColumn);
      sqlite3TreeViewLine(pView, "SELECT-COLUMN %d of [0..%d]%s",
              pExpr->iColumn, pExpr->iTable-1,
              pExpr->pRight==pExpr->pLeft ? " (SELECT-owner)" : "");
      assert( ExprUseXSelect(pExpr->pLeft) );
      sqlite3TreeViewSelect(pView, pExpr->pLeft->x.pSelect, 0);
      break;
    }
    case TK_IF_NULL_ROW: {
      sqlite3TreeViewLine(pView, "IF-NULL-ROW %d", pExpr->iTable);
      sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
      break;
    }
    case TK_ERROR: {
      Expr tmp;
      sqlite3TreeViewLine(pView, "ERROR");
      tmp = *pExpr;
      tmp.op = pExpr->op2;
      sqlite3TreeViewExpr(pView, &tmp, 0);
      break;
    }
    case TK_ROW: {
      if( pExpr->iColumn<=0 ){
        sqlite3TreeViewLine(pView, "First FROM table rowid");
      }else{
        sqlite3TreeViewLine(pView, "First FROM table column %d",
            pExpr->iColumn-1);
      }
      break;
    }
    default: {
      sqlite3TreeViewLine(pView, "op=%d", pExpr->op);
      break;
    }
  }
  if( zBinOp ){
    sqlite3TreeViewLine(pView, "%s%s", zBinOp, zFlgs);
    sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
    sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
  }else if( zUniOp ){
    sqlite3TreeViewLine(pView, "%s%s", zUniOp, zFlgs);
    sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
   sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
  }
  sqlite3TreeViewPop(pView);
  sqlite3TreeViewPop(&pView);
}


/*
** Generate a human-readable explanation of an expression list.
*/
void sqlite3TreeViewBareExprList(
  TreeView *pView,
  const ExprList *pList,
  const char *zLabel
){
  if( zLabel==0 || zLabel[0]==0 ) zLabel = "LIST";
  if( pList==0 ){
    sqlite3TreeViewLine(pView, "%s (empty)", zLabel);
  }else{
    int i;
    sqlite3TreeViewLine(pView, "%s", zLabel);
    for(i=0; i<pList->nExpr; i++){
      int j = pList->a[i].u.x.iOrderByCol;
      char *zName = pList->a[i].zName;
      char *zName = pList->a[i].zEName;
      int moreToFollow = i<pList->nExpr - 1;
      if( j || zName ){
        sqlite3TreeViewPush(pView, moreToFollow);
        sqlite3TreeViewPush(&pView, moreToFollow);
        moreToFollow = 0;
        sqlite3TreeViewLine(pView, 0);
        if( zName ){
          switch( pList->a[i].fg.eEName ){
            default:
          fprintf(stdout, "AS %s ", zName);
              fprintf(stdout, "AS %s ", zName);
              break;
            case ENAME_TAB:
              fprintf(stdout, "TABLE-ALIAS-NAME(\"%s\") ", zName);
              if( pList->a[i].fg.bUsed ) fprintf(stdout, "(used) ");
              if( pList->a[i].fg.bUsingTerm ) fprintf(stdout, "(USING-term) ");
              if( pList->a[i].fg.bNoExpand ) fprintf(stdout, "(NoExpand) ");
              break;
            case ENAME_SPAN:
              fprintf(stdout, "SPAN(\"%s\") ", zName);
              break;
          }
        }
        if( j ){
          fprintf(stdout, "iOrderByCol=%d", j);
        }
        fprintf(stdout, "\n");
        fflush(stdout);
      }
      sqlite3TreeViewExpr(pView, pList->a[i].pExpr, moreToFollow);
      if( j || zName ){
        sqlite3TreeViewPop(pView);
        sqlite3TreeViewPop(&pView);
      }
    }
  }
}
void sqlite3TreeViewExprList(
  TreeView *pView,
  const ExprList *pList,
  u8 moreToFollow,
  const char *zLabel
){
  pView = sqlite3TreeViewPush(pView, moreToFollow);
  sqlite3TreeViewPush(&pView, moreToFollow);
  sqlite3TreeViewBareExprList(pView, pList, zLabel);
  sqlite3TreeViewPop(pView);
  sqlite3TreeViewPop(&pView);
}

/*
** Generate a human-readable explanation of an id-list.
*/
void sqlite3TreeViewBareIdList(
  TreeView *pView,
  const IdList *pList,
  const char *zLabel
){
  if( zLabel==0 || zLabel[0]==0 ) zLabel = "LIST";
  if( pList==0 ){
    sqlite3TreeViewLine(pView, "%s (empty)", zLabel);
  }else{
    int i;
    sqlite3TreeViewLine(pView, "%s", zLabel);
    for(i=0; i<pList->nId; i++){
      char *zName = pList->a[i].zName;
      int moreToFollow = i<pList->nId - 1;
      if( zName==0 ) zName = "(null)";
      sqlite3TreeViewPush(&pView, moreToFollow);
      sqlite3TreeViewLine(pView, 0);
      if( pList->eU4==EU4_NONE ){
        fprintf(stdout, "%s\n", zName);
      }else if( pList->eU4==EU4_IDX ){
        fprintf(stdout, "%s (%d)\n", zName, pList->a[i].u4.idx);
      }else{
        assert( pList->eU4==EU4_EXPR );
        if( pList->a[i].u4.pExpr==0 ){
          fprintf(stdout, "%s (pExpr=NULL)\n", zName);
        }else{
          fprintf(stdout, "%s\n", zName);
          sqlite3TreeViewPush(&pView, i<pList->nId-1);
          sqlite3TreeViewExpr(pView, pList->a[i].u4.pExpr, 0);
          sqlite3TreeViewPop(&pView);
        }
      }
      sqlite3TreeViewPop(&pView);
    }
  }
}
void sqlite3TreeViewIdList(
  TreeView *pView,
  const IdList *pList,
  u8 moreToFollow,
  const char *zLabel
){
  sqlite3TreeViewPush(&pView, moreToFollow);
  sqlite3TreeViewBareIdList(pView, pList, zLabel);
  sqlite3TreeViewPop(&pView);
}

/*
** Generate a human-readable explanation of a list of Upsert objects
*/
void sqlite3TreeViewUpsert(
  TreeView *pView,
  const Upsert *pUpsert,
  u8 moreToFollow
){
  if( pUpsert==0 ) return;
  sqlite3TreeViewPush(&pView, moreToFollow);
  while( pUpsert ){
    int n;
    sqlite3TreeViewPush(&pView, pUpsert->pNextUpsert!=0 || moreToFollow);
    sqlite3TreeViewLine(pView, "ON CONFLICT DO %s", 
         pUpsert->isDoUpdate ? "UPDATE" : "NOTHING");
    n = (pUpsert->pUpsertSet!=0) + (pUpsert->pUpsertWhere!=0);
    sqlite3TreeViewExprList(pView, pUpsert->pUpsertTarget, (n--)>0, "TARGET");
    sqlite3TreeViewExprList(pView, pUpsert->pUpsertSet, (n--)>0, "SET");
    if( pUpsert->pUpsertWhere ){
      sqlite3TreeViewItem(pView, "WHERE", (n--)>0);
      sqlite3TreeViewExpr(pView, pUpsert->pUpsertWhere, 0);
      sqlite3TreeViewPop(&pView);
    }
    sqlite3TreeViewPop(&pView);
    pUpsert = pUpsert->pNextUpsert;
  }
  sqlite3TreeViewPop(&pView);
}

#if TREETRACE_ENABLED
/*
** Generate a human-readable diagram of the data structure that go
** into generating an DELETE statement.
*/
void sqlite3TreeViewDelete(
  const With *pWith,
  const SrcList *pTabList,
  const Expr *pWhere,
  const ExprList *pOrderBy,
  const Expr *pLimit,
  const Trigger *pTrigger
){
  int n = 0;
  TreeView *pView = 0;
  sqlite3TreeViewPush(&pView, 0);
  sqlite3TreeViewLine(pView, "DELETE");
  if( pWith ) n++;
  if( pTabList ) n++;
  if( pWhere ) n++;
  if( pOrderBy ) n++;
  if( pLimit ) n++;
  if( pTrigger ) n++;
  if( pWith ){
    sqlite3TreeViewPush(&pView, (--n)>0);
    sqlite3TreeViewWith(pView, pWith, 0);
    sqlite3TreeViewPop(&pView);
  }
  if( pTabList ){
    sqlite3TreeViewPush(&pView, (--n)>0);
    sqlite3TreeViewLine(pView, "FROM");
    sqlite3TreeViewSrcList(pView, pTabList);
    sqlite3TreeViewPop(&pView);
  }
  if( pWhere ){
    sqlite3TreeViewPush(&pView, (--n)>0);
    sqlite3TreeViewLine(pView, "WHERE");
    sqlite3TreeViewExpr(pView, pWhere, 0);
    sqlite3TreeViewPop(&pView);
  }
  if( pOrderBy ){
    sqlite3TreeViewExprList(pView, pOrderBy, (--n)>0, "ORDER-BY");
  }
  if( pLimit ){
    sqlite3TreeViewPush(&pView, (--n)>0);
    sqlite3TreeViewLine(pView, "LIMIT");
    sqlite3TreeViewExpr(pView, pLimit, 0);
    sqlite3TreeViewPop(&pView);
  }
  if( pTrigger ){
    sqlite3TreeViewTrigger(pView, pTrigger, (--n)>0, 1);
  }
  sqlite3TreeViewPop(&pView);
}
#endif /* TREETRACE_ENABLED */

#if TREETRACE_ENABLED
/*
** Generate a human-readable diagram of the data structure that go
** into generating an INSERT statement.
*/
void sqlite3TreeViewInsert(
  const With *pWith,
  const SrcList *pTabList,
  const IdList *pColumnList,
  const Select *pSelect,
  const ExprList *pExprList,
  int onError,
  const Upsert *pUpsert,
  const Trigger *pTrigger
){
  TreeView *pView = 0;
  int n = 0;
  const char *zLabel = "INSERT";
  switch( onError ){
    case OE_Replace:  zLabel = "REPLACE";             break;
    case OE_Ignore:   zLabel = "INSERT OR IGNORE";    break;
    case OE_Rollback: zLabel = "INSERT OR ROLLBACK";  break;
    case OE_Abort:    zLabel = "INSERT OR ABORT";     break;
    case OE_Fail:     zLabel = "INSERT OR FAIL";      break;
  }
  sqlite3TreeViewPush(&pView, 0);
  sqlite3TreeViewLine(pView, zLabel);
  if( pWith ) n++;
  if( pTabList ) n++;
  if( pColumnList ) n++;
  if( pSelect ) n++;
  if( pExprList ) n++;
  if( pUpsert ) n++;
  if( pTrigger ) n++;
  if( pWith ){
    sqlite3TreeViewPush(&pView, (--n)>0);
    sqlite3TreeViewWith(pView, pWith, 0);
    sqlite3TreeViewPop(&pView);
  }
  if( pTabList ){
    sqlite3TreeViewPush(&pView, (--n)>0);
    sqlite3TreeViewLine(pView, "INTO");
    sqlite3TreeViewSrcList(pView, pTabList);
    sqlite3TreeViewPop(&pView);
  }
  if( pColumnList ){
    sqlite3TreeViewIdList(pView, pColumnList, (--n)>0, "COLUMNS");
  }
  if( pSelect ){
    sqlite3TreeViewPush(&pView, (--n)>0);
    sqlite3TreeViewLine(pView, "DATA-SOURCE");
    sqlite3TreeViewSelect(pView, pSelect, 0);
    sqlite3TreeViewPop(&pView);
  }
  if( pExprList ){
    sqlite3TreeViewExprList(pView, pExprList, (--n)>0, "VALUES");
  }
  if( pUpsert ){
    sqlite3TreeViewPush(&pView, (--n)>0);
    sqlite3TreeViewLine(pView, "UPSERT");
    sqlite3TreeViewUpsert(pView, pUpsert, 0);
    sqlite3TreeViewPop(&pView);
  }
  if( pTrigger ){
    sqlite3TreeViewTrigger(pView, pTrigger, (--n)>0, 1);
  }
  sqlite3TreeViewPop(&pView);
}
#endif /* TREETRACE_ENABLED */

#if TREETRACE_ENABLED
/*
** Generate a human-readable diagram of the data structure that go
** into generating an UPDATE statement.
*/
void sqlite3TreeViewUpdate(
  const With *pWith,
  const SrcList *pTabList,
  const ExprList *pChanges,
  const Expr *pWhere,
  int onError,
  const ExprList *pOrderBy,
  const Expr *pLimit,
  const Upsert *pUpsert,
  const Trigger *pTrigger
){
  int n = 0;
  TreeView *pView = 0;
  const char *zLabel = "UPDATE";
  switch( onError ){
    case OE_Replace:  zLabel = "UPDATE OR REPLACE";   break;
    case OE_Ignore:   zLabel = "UPDATE OR IGNORE";    break;
    case OE_Rollback: zLabel = "UPDATE OR ROLLBACK";  break;
    case OE_Abort:    zLabel = "UPDATE OR ABORT";     break;
    case OE_Fail:     zLabel = "UPDATE OR FAIL";      break;
  }
  sqlite3TreeViewPush(&pView, 0);
  sqlite3TreeViewLine(pView, zLabel);
  if( pWith ) n++;
  if( pTabList ) n++;
  if( pChanges ) n++;
  if( pWhere ) n++;
  if( pOrderBy ) n++;
  if( pLimit ) n++;
  if( pUpsert ) n++;
  if( pTrigger ) n++;
  if( pWith ){
    sqlite3TreeViewPush(&pView, (--n)>0);
    sqlite3TreeViewWith(pView, pWith, 0);
    sqlite3TreeViewPop(&pView);
  }
  if( pTabList ){
    sqlite3TreeViewPush(&pView, (--n)>0);
    sqlite3TreeViewLine(pView, "FROM");
    sqlite3TreeViewSrcList(pView, pTabList);
    sqlite3TreeViewPop(&pView);
  }
  if( pChanges ){
    sqlite3TreeViewExprList(pView, pChanges, (--n)>0, "SET");
  }
  if( pWhere ){
    sqlite3TreeViewPush(&pView, (--n)>0);
    sqlite3TreeViewLine(pView, "WHERE");
    sqlite3TreeViewExpr(pView, pWhere, 0);
    sqlite3TreeViewPop(&pView);
  }
  if( pOrderBy ){
    sqlite3TreeViewExprList(pView, pOrderBy, (--n)>0, "ORDER-BY");
  }
  if( pLimit ){
    sqlite3TreeViewPush(&pView, (--n)>0);
    sqlite3TreeViewLine(pView, "LIMIT");
    sqlite3TreeViewExpr(pView, pLimit, 0);
    sqlite3TreeViewPop(&pView);
  }
  if( pUpsert ){
    sqlite3TreeViewPush(&pView, (--n)>0);
    sqlite3TreeViewLine(pView, "UPSERT");
    sqlite3TreeViewUpsert(pView, pUpsert, 0);
    sqlite3TreeViewPop(&pView);
  }
  if( pTrigger ){
    sqlite3TreeViewTrigger(pView, pTrigger, (--n)>0, 1);
  }
  sqlite3TreeViewPop(&pView);
}
#endif /* TREETRACE_ENABLED */

#ifndef SQLITE_OMIT_TRIGGER
/*
** Show a human-readable graph of a TriggerStep
*/
void sqlite3TreeViewTriggerStep(
  TreeView *pView,
  const TriggerStep *pStep,
  u8 moreToFollow,
  u8 showFullList
){
  int cnt = 0;
  if( pStep==0 ) return;
  sqlite3TreeViewPush(&pView, 
      moreToFollow || (showFullList && pStep->pNext!=0));
  do{
    if( cnt++ && pStep->pNext==0 ){
      sqlite3TreeViewPop(&pView);
      sqlite3TreeViewPush(&pView, 0);
    }
    sqlite3TreeViewLine(pView, "%s", pStep->zSpan ? pStep->zSpan : "RETURNING");
  }while( showFullList && (pStep = pStep->pNext)!=0 );
  sqlite3TreeViewPop(&pView);
}
  
/*
** Show a human-readable graph of a Trigger
*/
void sqlite3TreeViewTrigger(
  TreeView *pView,
  const Trigger *pTrigger,
  u8 moreToFollow,
  u8 showFullList
){
  int cnt = 0;
  if( pTrigger==0 ) return;
  sqlite3TreeViewPush(&pView,
     moreToFollow || (showFullList && pTrigger->pNext!=0));
  do{
    if( cnt++ && pTrigger->pNext==0 ){
      sqlite3TreeViewPop(&pView);
      sqlite3TreeViewPush(&pView, 0);
    }
    sqlite3TreeViewLine(pView, "TRIGGER %s", pTrigger->zName);
    sqlite3TreeViewPush(&pView, 0);
    sqlite3TreeViewTriggerStep(pView, pTrigger->step_list, 0, 1);
    sqlite3TreeViewPop(&pView);
  }while( showFullList && (pTrigger = pTrigger->pNext)!=0 );
  sqlite3TreeViewPop(&pView);
}
#endif /* SQLITE_OMIT_TRIGGER */
  

/*
** These simplified versions of the tree-view routines omit unnecessary
** parameters.  These variants are intended to be used from a symbolic
** debugger, such as "gdb", during interactive debugging sessions.
**
** This routines are given external linkage so that they will always be
** accessible to the debugging, and to avoid warnings about unused
** functions.  But these routines only exist in debugging builds, so they
** do not contaminate the interface.
*/
void sqlite3ShowExpr(const Expr *p){ sqlite3TreeViewExpr(0,p,0); }
void sqlite3ShowExprList(const ExprList *p){ sqlite3TreeViewExprList(0,p,0,0);}
void sqlite3ShowIdList(const IdList *p){ sqlite3TreeViewIdList(0,p,0,0); }
void sqlite3ShowSrcList(const SrcList *p){ sqlite3TreeViewSrcList(0,p); }
void sqlite3ShowSelect(const Select *p){ sqlite3TreeViewSelect(0,p,0); }
void sqlite3ShowWith(const With *p){ sqlite3TreeViewWith(0,p,0); }
void sqlite3ShowUpsert(const Upsert *p){ sqlite3TreeViewUpsert(0,p,0); }
#ifndef SQLITE_OMIT_TRIGGER
void sqlite3ShowTriggerStep(const TriggerStep *p){
  sqlite3TreeViewTriggerStep(0,p,0,0);
}
void sqlite3ShowTriggerStepList(const TriggerStep *p){
  sqlite3TreeViewTriggerStep(0,p,0,1);
}
void sqlite3ShowTrigger(const Trigger *p){ sqlite3TreeViewTrigger(0,p,0,0); }
void sqlite3ShowTriggerList(const Trigger *p){ sqlite3TreeViewTrigger(0,p,0,1);}
#endif
#ifndef SQLITE_OMIT_WINDOWFUNC
void sqlite3ShowWindow(const Window *p){ sqlite3TreeViewWindow(0,p,0); }
void sqlite3ShowWinFunc(const Window *p){ sqlite3TreeViewWinFunc(0,p,0); }
#endif

#endif /* SQLITE_DEBUG */

Changes to src/trigger.c.

22
23
24
25
26
27
28

29
30
31
32
33
34
35
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36







+







    pTriggerStep = pTriggerStep->pNext;

    sqlite3ExprDelete(db, pTmp->pWhere);
    sqlite3ExprListDelete(db, pTmp->pExprList);
    sqlite3SelectDelete(db, pTmp->pSelect);
    sqlite3IdListDelete(db, pTmp->pIdList);
    sqlite3UpsertDelete(db, pTmp->pUpsert);
    sqlite3SrcListDelete(db, pTmp->pFrom);
    sqlite3DbFree(db, pTmp->zSpan);

    sqlite3DbFree(db, pTmp);
  }
}

/*
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
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







-
-
+
+
+

-
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







** and returns the combined list.
**
** To state it another way:  This routine returns a list of all triggers
** that fire off of pTab.  The list will include any TEMP triggers on
** pTab as well as the triggers lised in pTab->pTrigger.
*/
Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){
  Schema * const pTmpSchema = pParse->db->aDb[1].pSchema;
  Trigger *pList = 0;                  /* List of triggers to return */
  Schema *pTmpSchema;       /* Schema of the pTab table */
  Trigger *pList;           /* List of triggers to return */
  HashElem *p;              /* Loop variable for TEMP triggers */

  if( pParse->disableTriggers ){
  assert( pParse->disableTriggers==0 );
    return 0;
  }

  pTmpSchema = pParse->db->aDb[1].pSchema;
  if( pTmpSchema!=pTab->pSchema ){
    HashElem *p;
    assert( sqlite3SchemaMutexHeld(pParse->db, 0, pTmpSchema) );
    for(p=sqliteHashFirst(&pTmpSchema->trigHash); p; p=sqliteHashNext(p)){
      Trigger *pTrig = (Trigger *)sqliteHashData(p);
      if( pTrig->pTabSchema==pTab->pSchema
       && 0==sqlite3StrICmp(pTrig->table, pTab->zName) 
      ){
        pTrig->pNext = (pList ? pList : pTab->pTrigger);
        pList = pTrig;
      }
    }
  }

  return (pList ? pList : pTab->pTrigger);
  p = sqliteHashFirst(&pTmpSchema->trigHash);
  pList = pTab->pTrigger;
  while( p ){
    Trigger *pTrig = (Trigger *)sqliteHashData(p);
    if( pTrig->pTabSchema==pTab->pSchema
     && pTrig->table
     && 0==sqlite3StrICmp(pTrig->table, pTab->zName)
     && (pTrig->pTabSchema!=pTmpSchema || pTrig->bReturning)
    ){
      pTrig->pNext = pList;
      pList = pTrig;
    }else if( pTrig->op==TK_RETURNING ){
#ifndef SQLITE_OMIT_VIRTUALTABLE
      assert( 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
** in pParse->pNewTrigger.  After the trigger actions have been parsed, the
124
125
126
127
128
129
130
131

132
133
134
135
136
137
138
145
146
147
148
149
150
151

152
153
154
155
156
157
158
159







-
+








  /* A long-standing parser bug is that this syntax was allowed:
  **
  **    CREATE TRIGGER attached.demo AFTER INSERT ON attached.tab ....
  **                                                 ^^^^^^^^
  **
  ** To maintain backwards compatibility, ignore the database
  ** name on pTableName if we are reparsing out of SQLITE_MASTER.
  ** name on pTableName if we are reparsing out of the schema table
  */
  if( db->init.busy && iDb!=1 ){
    sqlite3DbFree(db, pTableName->a[0].zDatabase);
    pTableName->a[0].zDatabase = 0;
  }

  /* If the trigger name was unqualified, and the table is a temp table,
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
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







-
-
-
-
-
-
-
-
-
-
-
-
+



-
+





+
+
+
+
-
+







  sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName);
  if( sqlite3FixSrcList(&sFix, pTableName) ){
    goto trigger_cleanup;
  }
  pTab = sqlite3SrcListLookup(pParse, pTableName);
  if( !pTab ){
    /* The table does not exist. */
    if( db->init.iDb==1 ){
      /* Ticket #3810.
      ** Normally, whenever a table is dropped, all associated triggers are
      ** dropped too.  But if a TEMP trigger is created on a non-TEMP table
      ** and the table is dropped by a different database connection, the
      ** trigger is not visible to the database connection that does the
      ** drop so the trigger cannot be dropped.  This results in an
      ** "orphaned trigger" - a trigger whose associated table is missing.
      */
      db->init.orphanTrigger = 1;
    }
    goto trigger_cleanup;
    goto trigger_orphan_error;
  }
  if( IsVirtual(pTab) ){
    sqlite3ErrorMsg(pParse, "cannot create triggers on virtual tables");
    goto trigger_cleanup;
    goto trigger_orphan_error;
  }

  /* Check that the trigger name is not reserved and that no trigger of the
  ** specified name exists */
  zName = sqlite3NameFromToken(db, pName);
  if( zName==0 ){
    assert( db->mallocFailed );
    goto trigger_cleanup;
  }
  if( !zName || SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
  if( sqlite3CheckObjectName(pParse, zName, "trigger", pTab->zName) ){
    goto trigger_cleanup;
  }
  assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
  if( !IN_RENAME_OBJECT ){
    if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash),zName) ){
      if( !noErr ){
        sqlite3ErrorMsg(pParse, "trigger %T already exists", pName);
198
199
200
201
202
203
204
205

206
207
208


209
210

211
212
213


214
215
216
217
218
219
220
212
213
214
215
216
217
218

219
220


221
222
223

224
225


226
227
228
229
230
231
232
233
234







-
+

-
-
+
+

-
+

-
-
+
+







    sqlite3ErrorMsg(pParse, "cannot create trigger on system table");
    goto trigger_cleanup;
  }

  /* INSTEAD of triggers are only for views and views only support INSTEAD
  ** of triggers.
  */
  if( pTab->pSelect && tr_tm!=TK_INSTEAD ){
  if( IsView(pTab) && tr_tm!=TK_INSTEAD ){
    sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S", 
        (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0);
    goto trigger_cleanup;
        (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName->a);
    goto trigger_orphan_error;
  }
  if( !pTab->pSelect && tr_tm==TK_INSTEAD ){
  if( !IsView(pTab) && tr_tm==TK_INSTEAD ){
    sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF"
        " trigger on table: %S", pTableName, 0);
    goto trigger_cleanup;
        " 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;
    const char *zDb = db->aDb[iTabDb].zDbSName;
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  sqlite3IdListDelete(db, pColumns);
  sqlite3ExprDelete(db, pWhen);
  if( !pParse->pNewTrigger ){
    sqlite3DeleteTrigger(db, pTrigger);
  }else{
    assert( pParse->pNewTrigger==pTrigger );
  }
  return;

trigger_orphan_error:
  if( db->init.iDb==1 ){
    /* Ticket #3810.
    ** Normally, whenever a table is dropped, all associated triggers are
    ** dropped too.  But if a TEMP trigger is created on a non-TEMP table
    ** and the table is dropped by a different database connection, the
    ** trigger is not visible to the database connection that does the
    ** drop so the trigger cannot be dropped.  This results in an
    ** "orphaned trigger" - a trigger whose associated table is missing.
    **
    ** 2020-11-05 see also https://sqlite.org/forum/forumpost/157dc791df
    */
    db->init.orphanTrigger = 1;
  }
  goto trigger_cleanup;
}

/*
** This routine is called after all of the trigger actions have been parsed
** in order to complete the process of building the trigger.
*/
void sqlite3FinishTrigger(
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
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







-
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+






+
-
-
+
+




-
+






+







    assert( !db->init.busy );
    pParse->pNewTrigger = pTrig;
    pTrig = 0;
  }else
#endif

  /* if we are not initializing,
  ** build the sqlite_master entry
  ** build the sqlite_schema entry
  */
  if( !db->init.busy ){
    Vdbe *v;
    char *z;

    /* If this is a new CREATE TABLE statement, and if shadow tables
    ** are read-only, and the trigger makes a change to a shadow table,
    ** then raise an error - do not allow the trigger to be created. */
    if( sqlite3ReadOnlyShadowTables(db) ){
      TriggerStep *pStep;
      for(pStep=pTrig->step_list; pStep; pStep=pStep->pNext){
        if( pStep->zTarget!=0
         && sqlite3ShadowTableName(db, pStep->zTarget)
        ){
          sqlite3ErrorMsg(pParse, 
            "trigger \"%s\" may not write to shadow table \"%s\"",
            pTrig->zName, pStep->zTarget);
          goto triggerfinish_cleanup;
        }
      }
    }

    /* Make an entry in the sqlite_master table */
    /* Make an entry in the sqlite_schema table */
    v = sqlite3GetVdbe(pParse);
    if( v==0 ) goto triggerfinish_cleanup;
    sqlite3BeginWriteOperation(pParse, 0, iDb);
    z = sqlite3DbStrNDup(db, (char*)pAll->z, pAll->n);
    testcase( z==0 );
    sqlite3NestedParse(pParse,
       "INSERT INTO %Q." LEGACY_SCHEMA_TABLE
       "INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')",
       db->aDb[iDb].zDbSName, MASTER_NAME, zName,
       " VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')",
       db->aDb[iDb].zDbSName, zName,
       pTrig->table, z);
    sqlite3DbFree(db, z);
    sqlite3ChangeCookie(pParse, iDb);
    sqlite3VdbeAddParseSchemaOp(v, iDb,
        sqlite3MPrintf(db, "type='trigger' AND name='%q'", zName));
        sqlite3MPrintf(db, "type='trigger' AND name='%q'", zName), 0);
  }

  if( db->init.busy ){
    Trigger *pLink = pTrig;
    Hash *pHash = &db->aDb[iDb].pSchema->trigHash;
    assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
    assert( pLink!=0 );
    pTrig = sqlite3HashInsert(pHash, zName, pTrig);
    if( pTrig ){
      sqlite3OomFault(db);
    }else if( pLink->pSchema==pLink->pTabSchema ){
      Table *pTab;
      pTab = sqlite3HashFind(&pLink->pTabSchema->tblHash, pLink->table);
      assert( pTab!=0 );
406
407
408
409
410
411
412

413
414
415
416
417
418
419
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470







+







  Token *pName,               /* The target name */
  const char *zStart,         /* Start of SQL text */
  const char *zEnd            /* End of SQL text */
){
  sqlite3 *db = pParse->db;
  TriggerStep *pTriggerStep;

  if( pParse->nErr ) return 0;
  pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n + 1);
  if( pTriggerStep ){
    char *z = (char*)&pTriggerStep[1];
    memcpy(z, pName->z, pName->n);
    sqlite3Dequote(z);
    pTriggerStep->zTarget = z;
    pTriggerStep->op = op;
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
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







+
+
+



















+














+


+



+





+







      pSelect = 0;
    }else{
      pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
    }
    pTriggerStep->pIdList = pColumn;
    pTriggerStep->pUpsert = pUpsert;
    pTriggerStep->orconf = orconf;
    if( pUpsert ){
      sqlite3HasExplicitNulls(pParse, pUpsert->pUpsertTarget);
    }
  }else{
    testcase( pColumn );
    sqlite3IdListDelete(db, pColumn);
    testcase( pUpsert );
    sqlite3UpsertDelete(db, pUpsert);
  }
  sqlite3SelectDelete(db, pSelect);

  return pTriggerStep;
}

/*
** Construct a trigger step that implements an UPDATE statement and return
** a pointer to that trigger step.  The parser calls this routine when it
** sees an UPDATE statement inside the body of a CREATE TRIGGER.
*/
TriggerStep *sqlite3TriggerUpdateStep(
  Parse *pParse,          /* Parser */
  Token *pTableName,   /* Name of the table to be updated */
  SrcList *pFrom,      /* FROM clause for an UPDATE-FROM, or NULL */
  ExprList *pEList,    /* The SET clause: list of column and new values */
  Expr *pWhere,        /* The WHERE clause */
  u8 orconf,           /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
  const char *zStart,  /* Start of SQL text */
  const char *zEnd     /* End of SQL text */
){
  sqlite3 *db = pParse->db;
  TriggerStep *pTriggerStep;

  pTriggerStep = triggerStepAllocate(pParse, TK_UPDATE, pTableName,zStart,zEnd);
  if( pTriggerStep ){
    if( IN_RENAME_OBJECT ){
      pTriggerStep->pExprList = pEList;
      pTriggerStep->pWhere = pWhere;
      pTriggerStep->pFrom = pFrom;
      pEList = 0;
      pWhere = 0;
      pFrom = 0;
    }else{
      pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE);
      pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
      pTriggerStep->pFrom = sqlite3SrcListDup(db, pFrom, EXPRDUP_REDUCE);
    }
    pTriggerStep->orconf = orconf;
  }
  sqlite3ExprListDelete(db, pEList);
  sqlite3ExprDelete(db, pWhere);
  sqlite3SrcListDelete(db, pFrom);
  return pTriggerStep;
}

/*
** Construct a trigger step that implements a DELETE statement and return
** a pointer to that trigger step.  The parser calls this routine when it
** sees a DELETE statement inside the body of a CREATE TRIGGER.
533
534
535
536
537
538
539
540

541
542
543
544
545
546
547
592
593
594
595
596
597
598

599
600
601
602
603
604
605
606







-
+







  return pTriggerStep;
}

/* 
** Recursively delete a Trigger structure
*/
void sqlite3DeleteTrigger(sqlite3 *db, Trigger *pTrigger){
  if( pTrigger==0 ) return;
  if( pTrigger==0 || pTrigger->bReturning ) return;
  sqlite3DeleteTriggerStep(db, pTrigger->step_list);
  sqlite3DbFree(db, pTrigger->zName);
  sqlite3DbFree(db, pTrigger->table);
  sqlite3ExprDelete(db, pTrigger->pWhen);
  sqlite3IdListDelete(db, pTrigger->pColumns);
  sqlite3DbFree(db, pTrigger);
}
568
569
570
571
572
573
574
575

576
577
578
579
580
581
582

583
584
585
586
587
588
589
627
628
629
630
631
632
633

634
635
636
637
638
639
640

641
642
643
644
645
646
647
648







-
+






-
+








  assert( pName->nSrc==1 );
  zDb = pName->a[0].zDatabase;
  zName = pName->a[0].zName;
  assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) );
  for(i=OMIT_TEMPDB; i<db->nDb; i++){
    int j = (i<2) ? i^1 : i;  /* Search TEMP before MAIN */
    if( zDb && sqlite3StrICmp(db->aDb[j].zDbSName, zDb) ) continue;
    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);
609
610
611
612
613
614
615
616
617

618
619

620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637


638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656

657
658
659








660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679

680
681
682









683
684
685
686
687
688
689
690

691
692
693
694
695
696
697
698
699
700





701
702
703










704
705
706
707
708
709
































710
711
712
713
714
















715
716
717
718
719
720
721
722
723
724
725
726

727
728
729
730
731
732
733
734





735

736
737
738
739
740
741
742
743















744


745
746
747












































































































































748
749
750
751
752
753
754
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
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031







-
-
+

-
+













-


-
-
+
+



















+
-
-
-
+
+
+
+
+
+
+
+



















-
+



+
+
+
+
+
+
+
+
+







-
+










+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+











-
+




-
-
-
-
+
+
+
+
+

+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  Vdbe *v;
  sqlite3 *db = pParse->db;
  int iDb;

  iDb = sqlite3SchemaToIndex(pParse->db, pTrigger->pSchema);
  assert( iDb>=0 && iDb<db->nDb );
  pTable = tableOfTrigger(pTrigger);
  assert( pTable );
  assert( pTable->pSchema==pTrigger->pSchema || iDb==1 );
  assert( (pTable && pTable->pSchema==pTrigger->pSchema) || iDb==1 );
#ifndef SQLITE_OMIT_AUTHORIZATION
  {
  if( pTable ){
    int code = SQLITE_DROP_TRIGGER;
    const char *zDb = db->aDb[iDb].zDbSName;
    const char *zTab = SCHEMA_TABLE(iDb);
    if( iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER;
    if( sqlite3AuthCheck(pParse, code, pTrigger->zName, pTable->zName, zDb) ||
      sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){
      return;
    }
  }
#endif

  /* Generate code to destroy the database record of the trigger.
  */
  assert( pTable!=0 );
  if( (v = sqlite3GetVdbe(pParse))!=0 ){
    sqlite3NestedParse(pParse,
       "DELETE FROM %Q.%s WHERE name=%Q AND type='trigger'",
       db->aDb[iDb].zDbSName, MASTER_NAME, pTrigger->zName
       "DELETE FROM %Q." LEGACY_SCHEMA_TABLE " WHERE name=%Q AND type='trigger'",
       db->aDb[iDb].zDbSName, pTrigger->zName
    );
    sqlite3ChangeCookie(pParse, iDb);
    sqlite3VdbeAddOp4(v, OP_DropTrigger, iDb, 0, 0, pTrigger->zName, 0);
  }
}

/*
** Remove a trigger from the hash tables of the sqlite* pointer.
*/
void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){
  Trigger *pTrigger;
  Hash *pHash;

  assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
  pHash = &(db->aDb[iDb].pSchema->trigHash);
  pTrigger = sqlite3HashInsert(pHash, zName, 0);
  if( ALWAYS(pTrigger) ){
    if( pTrigger->pSchema==pTrigger->pTabSchema ){
      Table *pTab = tableOfTrigger(pTrigger);
      if( pTab ){
      Trigger **pp;
      for(pp=&pTab->pTrigger; *pp!=pTrigger; pp=&((*pp)->pNext));
      *pp = (*pp)->pNext;
        Trigger **pp;
        for(pp=&pTab->pTrigger; *pp; pp=&((*pp)->pNext)){
          if( *pp==pTrigger ){
            *pp = (*pp)->pNext;
            break;
          }
        }
      }
    }
    sqlite3DeleteTrigger(db, pTrigger);
    db->mDbFlags |= DBFLAG_SchemaChange;
  }
}

/*
** pEList is the SET clause of an UPDATE statement.  Each entry
** in pEList is of the format <id>=<expr>.  If any of the entries
** in pEList have an <id> which matches an identifier in pIdList,
** then return TRUE.  If pIdList==NULL, then it is considered a
** wildcard that matches anything.  Likewise if pEList==NULL then
** it matches anything so always return true.  Return false only
** if there is no match.
*/
static int checkColumnOverlap(IdList *pIdList, ExprList *pEList){
  int e;
  if( pIdList==0 || NEVER(pEList==0) ) return 1;
  for(e=0; e<pEList->nExpr; e++){
    if( sqlite3IdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1;
    if( sqlite3IdListIndex(pIdList, pEList->a[e].zEName)>=0 ) return 1;
  }
  return 0; 
}

/*
** Return true if any TEMP triggers exist
*/
static int tempTriggersExist(sqlite3 *db){
  if( NEVER(db->aDb[1].pSchema==0) ) return 0;
  if( sqliteHashFirst(&db->aDb[1].pSchema->trigHash)==0 ) return 0;
  return 1;
}

/*
** Return a list of all triggers on table pTab if there exists at least
** one trigger that must be fired when an operation of type 'op' is 
** performed on the table, and, if that operation is an UPDATE, if at
** least one of the columns in pChanges is being modified.
*/
Trigger *sqlite3TriggersExist(
static SQLITE_NOINLINE Trigger *triggersReallyExist(
  Parse *pParse,          /* Parse context */
  Table *pTab,            /* The table the contains the triggers */
  int op,                 /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
  ExprList *pChanges,     /* Columns that change in an UPDATE statement */
  int *pMask              /* OUT: Mask of TRIGGER_BEFORE|TRIGGER_AFTER */
){
  int mask = 0;
  Trigger *pList = 0;
  Trigger *p;

  pList = sqlite3TriggerList(pParse, pTab);
  assert( pList==0 || IsVirtual(pTab)==0 
           || (pList->bReturning && pList->pNext==0) );
  if( pList!=0 ){
    p = pList;
  if( (pParse->db->flags & SQLITE_EnableTrigger)!=0 ){
    pList = sqlite3TriggerList(pParse, pTab);
  }
    if( (pParse->db->flags & SQLITE_EnableTrigger)==0
     && pTab->pTrigger!=0
    ){
      /* The SQLITE_DBCONFIG_ENABLE_TRIGGER setting is off.  That means that
      ** only TEMP triggers are allowed.  Truncate the pList so that it
      ** includes only TEMP triggers */
      if( pList==pTab->pTrigger ){
        pList = 0;
        goto exit_triggers_exist;
      }
  assert( pList==0 || IsVirtual(pTab)==0 );
  for(p=pList; p; p=p->pNext){
    if( p->op==op && checkColumnOverlap(p->pColumns, pChanges) ){
      mask |= p->tr_tm;
    }
  }
      while( ALWAYS(p->pNext) && p->pNext!=pTab->pTrigger ) p = p->pNext;
      p->pNext = 0;
      p = pList;
    }
    do{
      if( p->op==op && checkColumnOverlap(p->pColumns, pChanges) ){
        mask |= p->tr_tm;
      }else if( p->op==TK_RETURNING ){
        /* The first time a RETURNING trigger is seen, the "op" value tells
        ** us what time of trigger it should be. */
        assert( sqlite3IsToplevel(pParse) );
        p->op = op;
        if( IsVirtual(pTab) ){
          if( op!=TK_INSERT ){
            sqlite3ErrorMsg(pParse,
              "%s RETURNING is not available on virtual tables",
              op==TK_DELETE ? "DELETE" : "UPDATE");
          }
          p->tr_tm = TRIGGER_BEFORE;
        }else{
          p->tr_tm = TRIGGER_AFTER;
        }
        mask |= p->tr_tm;
      }else if( p->bReturning && p->op==TK_INSERT && op==TK_UPDATE
                && sqlite3IsToplevel(pParse) ){
        /* Also fire a RETURNING trigger for an UPSERT */
        mask |= p->tr_tm;
      }
      p = p->pNext;
    }while( p );
  }
exit_triggers_exist:
  if( pMask ){
    *pMask = mask;
  }
  return (mask ? pList : 0);
}
Trigger *sqlite3TriggersExist(
  Parse *pParse,          /* Parse context */
  Table *pTab,            /* The table the contains the triggers */
  int op,                 /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
  ExprList *pChanges,     /* Columns that change in an UPDATE statement */
  int *pMask              /* OUT: Mask of TRIGGER_BEFORE|TRIGGER_AFTER */
){
  assert( pTab!=0 );
  if( (pTab->pTrigger==0 && !tempTriggersExist(pParse->db))
   || pParse->disableTriggers
  ){
    if( pMask ) *pMask = 0;
    return 0;
  }
  return triggersReallyExist(pParse,pTab,op,pChanges,pMask);
}

/*
** Convert the pStep->zTarget string into a SrcList and return a pointer
** to that SrcList.
**
** This routine adds a specific database name, if needed, to the target when
** forming the SrcList.  This prevents a trigger in one database from
** referring to a target in another database.  An exception is when the
** trigger is in TEMP in which case it can refer to any other database it
** wants.
*/
static SrcList *targetSrcList(
SrcList *sqlite3TriggerStepSrc(
  Parse *pParse,       /* The parsing context */
  TriggerStep *pStep   /* The trigger containing the target token */
){
  sqlite3 *db = pParse->db;
  int iDb;             /* Index of the database to use */
  SrcList *pSrc;       /* SrcList to be returned */

  pSrc = sqlite3SrcListAppend(db, 0, 0, 0);
  SrcList *pSrc;                  /* SrcList to be returned */
  char *zName = sqlite3DbStrDup(db, pStep->zTarget);
  pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
  assert( pSrc==0 || pSrc->nSrc==1 );
  assert( zName || pSrc==0 );
  if( pSrc ){
    Schema *pSchema = pStep->pTrig->pSchema;
    assert( pSrc->nSrc>0 );
    pSrc->a[pSrc->nSrc-1].zName = sqlite3DbStrDup(db, pStep->zTarget);
    iDb = sqlite3SchemaToIndex(db, pStep->pTrig->pSchema);
    if( iDb==0 || iDb>=2 ){
      const char *zDb;
      assert( iDb<db->nDb );
      zDb = db->aDb[iDb].zDbSName;
      pSrc->a[pSrc->nSrc-1].zDatabase =  sqlite3DbStrDup(db, zDb);
    pSrc->a[0].zName = zName;
    if( pSchema!=db->aDb[1].pSchema ){
      pSrc->a[0].pSchema = pSchema;
    }
    if( pStep->pFrom ){
      SrcList *pDup = sqlite3SrcListDup(db, pStep->pFrom, 0);
      if( pDup && pDup->nSrc>1 && !IN_RENAME_OBJECT ){
        Select *pSubquery;
        Token as;
        pSubquery = sqlite3SelectNew(pParse,0,pDup,0,0,0,0,SF_NestedFrom,0);
        as.n = 0;
        as.z = 0;
        pDup = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&as,pSubquery,0);
      }
      pSrc = sqlite3SrcListAppendList(pParse, pSrc, pDup);
    }
  }else{
    sqlite3DbFree(db, zName);
  }
  return pSrc;
}

/*
** Return true if the pExpr term from the RETURNING clause argument
** list is of the form "*".  Raise an error if the terms if of the
** form "table.*".
*/
static int isAsteriskTerm(
  Parse *pParse,      /* Parsing context */
  Expr *pTerm         /* A term in the RETURNING clause */
){
  assert( pTerm!=0 );
  if( pTerm->op==TK_ASTERISK ) return 1;
  if( pTerm->op!=TK_DOT ) return 0;
  assert( pTerm->pRight!=0 );
  assert( pTerm->pLeft!=0 );
  if( pTerm->pRight->op!=TK_ASTERISK ) return 0;
  sqlite3ErrorMsg(pParse, "RETURNING may not use \"TABLE.*\" wildcards");
  return 1;
}

/* The input list pList is the list of result set terms from a RETURNING
** clause.  The table that we are returning from is pTab.
**
** This routine makes a copy of the pList, and at the same time expands
** any "*" wildcards to be the complete set of columns from pTab.
*/
static ExprList *sqlite3ExpandReturning(
  Parse *pParse,        /* Parsing context */
  ExprList *pList,      /* The arguments to RETURNING */
  Table *pTab           /* The table being updated */
){
  ExprList *pNew = 0;
  sqlite3 *db = pParse->db;
  int i;

  for(i=0; i<pList->nExpr; i++){
    Expr *pOldExpr = pList->a[i].pExpr;
    if( NEVER(pOldExpr==0) ) continue;
    if( isAsteriskTerm(pParse, pOldExpr) ){
      int jj;
      for(jj=0; jj<pTab->nCol; jj++){
        Expr *pNewExpr;
        if( IsHiddenColumn(pTab->aCol+jj) ) continue;
        pNewExpr = sqlite3Expr(db, TK_ID, pTab->aCol[jj].zCnName);
        pNew = sqlite3ExprListAppend(pParse, pNew, pNewExpr);
        if( !db->mallocFailed ){
          struct ExprList_item *pItem = &pNew->a[pNew->nExpr-1];
          pItem->zEName = sqlite3DbStrDup(db, pTab->aCol[jj].zCnName);
          pItem->fg.eEName = ENAME_NAME;
        }
      }
    }else{
      Expr *pNewExpr = sqlite3ExprDup(db, pOldExpr, 0);
      pNew = sqlite3ExprListAppend(pParse, pNew, pNewExpr);
      if( !db->mallocFailed && ALWAYS(pList->a[i].zEName!=0) ){
        struct ExprList_item *pItem = &pNew->a[pNew->nExpr-1];
        pItem->zEName = sqlite3DbStrDup(db, pList->a[i].zEName);
        pItem->fg.eEName = pList->a[i].fg.eEName;
      }
    }
  }
  return pNew;
}

/*
** Generate code for the RETURNING trigger.  Unlike other triggers
** that invoke a subprogram in the bytecode, the code for RETURNING
** is generated in-line.
*/
static void codeReturningTrigger(
  Parse *pParse,       /* Parse context */
  Trigger *pTrigger,   /* The trigger step that defines the RETURNING */
  Table *pTab,         /* The table to code triggers from */
  int regIn            /* The first in an array of registers */
){
  Vdbe *v = pParse->pVdbe;
  sqlite3 *db = pParse->db;
  ExprList *pNew;
  Returning *pReturning;
  Select sSelect;
  SrcList sFrom;

  assert( v!=0 );
  assert( pParse->bReturning );
  assert( db->pParse==pParse );
  pReturning = pParse->u1.pReturning;
  assert( pTrigger == &(pReturning->retTrig) );
  memset(&sSelect, 0, sizeof(sSelect));
  memset(&sFrom, 0, sizeof(sFrom));
  sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0);
  sSelect.pSrc = &sFrom;
  sFrom.nSrc = 1;
  sFrom.a[0].pTab = pTab;
  sFrom.a[0].iCursor = -1;
  sqlite3SelectPrep(pParse, &sSelect, 0);
  if( pParse->nErr==0 ){
    assert( db->mallocFailed==0 );
    sqlite3GenerateColumnNames(pParse, &sSelect);
  }
  sqlite3ExprListDelete(db, sSelect.pEList);
  pNew = sqlite3ExpandReturning(pParse, pReturning->pReturnEL, pTab);
  if( !db->mallocFailed ){
    NameContext sNC;
    memset(&sNC, 0, sizeof(sNC));
    if( pReturning->nRetCol==0 ){
      pReturning->nRetCol = pNew->nExpr;
      pReturning->iRetCur = pParse->nTab++;
    }
    sNC.pParse = pParse;
    sNC.uNC.iBaseReg = regIn;
    sNC.ncFlags = NC_UBaseReg;
    pParse->eTriggerOp = pTrigger->op;
    pParse->pTriggerTab = pTab;
    if( sqlite3ResolveExprListNames(&sNC, pNew)==SQLITE_OK
     && ALWAYS(!db->mallocFailed)
    ){
      int i;
      int nCol = pNew->nExpr;
      int reg = pParse->nMem+1;
      pParse->nMem += nCol+2;
      pReturning->iRetReg = reg;
      for(i=0; i<nCol; i++){
        Expr *pCol = pNew->a[i].pExpr;
        assert( pCol!=0 ); /* Due to !db->mallocFailed ~9 lines above */
        sqlite3ExprCodeFactorable(pParse, pCol, reg+i);
        if( sqlite3ExprAffinity(pCol)==SQLITE_AFF_REAL ){
          sqlite3VdbeAddOp1(v, OP_RealAffinity, reg+i);
        }
      }
      sqlite3VdbeAddOp3(v, OP_MakeRecord, reg, i, reg+i);
      sqlite3VdbeAddOp2(v, OP_NewRowid, pReturning->iRetCur, reg+i+1);
      sqlite3VdbeAddOp3(v, OP_Insert, pReturning->iRetCur, reg+i, reg+i+1);
    }
  }
  sqlite3ExprListDelete(db, pNew);
  pParse->eTriggerOp = 0;
  pParse->pTriggerTab = 0;
}



/*
** Generate VDBE code for the statements inside the body of a single 
** trigger.
*/
static int codeTriggerProgram(
  Parse *pParse,            /* The parser context */
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
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







-
+




+




-
+





+




-
+


+











-
-
-







                        P4_DYNAMIC);
    }
#endif

    switch( pStep->op ){
      case TK_UPDATE: {
        sqlite3Update(pParse, 
          targetSrcList(pParse, pStep),
          sqlite3TriggerStepSrc(pParse, pStep),
          sqlite3ExprListDup(db, pStep->pExprList, 0), 
          sqlite3ExprDup(db, pStep->pWhere, 0), 
          pParse->eOrconf, 0, 0, 0
        );
        sqlite3VdbeAddOp0(v, OP_ResetCount);
        break;
      }
      case TK_INSERT: {
        sqlite3Insert(pParse, 
          targetSrcList(pParse, pStep),
          sqlite3TriggerStepSrc(pParse, pStep),
          sqlite3SelectDup(db, pStep->pSelect, 0), 
          sqlite3IdListDup(db, pStep->pIdList), 
          pParse->eOrconf,
          sqlite3UpsertDup(db, pStep->pUpsert)
        );
        sqlite3VdbeAddOp0(v, OP_ResetCount);
        break;
      }
      case TK_DELETE: {
        sqlite3DeleteFrom(pParse, 
          targetSrcList(pParse, pStep),
          sqlite3TriggerStepSrc(pParse, pStep),
          sqlite3ExprDup(db, pStep->pWhere, 0), 0, 0
        );
        sqlite3VdbeAddOp0(v, OP_ResetCount);
        break;
      }
      default: assert( pStep->op==TK_SELECT ); {
        SelectDest sDest;
        Select *pSelect = sqlite3SelectDup(db, pStep->pSelect, 0);
        sqlite3SelectDestInit(&sDest, SRT_Discard, 0);
        sqlite3Select(pParse, pSelect, &sDest);
        sqlite3SelectDelete(db, pSelect);
        break;
      }
    } 
    if( pStep->op!=TK_SELECT ){
      sqlite3VdbeAddOp0(v, OP_ResetCount);
    }
  }

  return 0;
}

#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
/*
879
880
881
882
883
884
885
886
887

888
889
890
891
892
893
894
1156
1157
1158
1159
1160
1161
1162

1163
1164
1165
1166
1167
1168
1169
1170
1171







-

+







  Parse *pTop = sqlite3ParseToplevel(pParse);
  sqlite3 *db = pParse->db;   /* Database handle */
  TriggerPrg *pPrg;           /* Value to return */
  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 */
  Parse sSubParse;            /* Parse context for sub-vdbe */

  assert( pTrigger->zName==0 || 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.  */
902
903
904
905
906
907
908
909
910

911
912

913
914
915
916
917
918






919
920

921
922
923
924
925
926
927
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







-
-
+

-
+
-
-
-
-
-
-
+
+
+
+
+
+

-
+







  pPrg->pTrigger = pTrigger;
  pPrg->orconf = orconf;
  pPrg->aColmask[0] = 0xffffffff;
  pPrg->aColmask[1] = 0xffffffff;

  /* Allocate and populate a new Parse context to use for coding the 
  ** trigger sub-program.  */
  pSubParse = sqlite3StackAllocZero(db, sizeof(Parse));
  if( !pSubParse ) return 0;
  sqlite3ParseObjectInit(&sSubParse, db);
  memset(&sNC, 0, sizeof(sNC));
  sNC.pParse = pSubParse;
  sNC.pParse = &sSubParse;
  pSubParse->db = db;
  pSubParse->pTriggerTab = pTab;
  pSubParse->pToplevel = pTop;
  pSubParse->zAuthContext = pTrigger->zName;
  pSubParse->eTriggerOp = pTrigger->op;
  pSubParse->nQueryLoop = pParse->nQueryLoop;
  sSubParse.pTriggerTab = pTab;
  sSubParse.pToplevel = pTop;
  sSubParse.zAuthContext = pTrigger->zName;
  sSubParse.eTriggerOp = pTrigger->op;
  sSubParse.nQueryLoop = pParse->nQueryLoop;
  sSubParse.prepFlags = pParse->prepFlags;

  v = sqlite3GetVdbe(pSubParse);
  v = sqlite3GetVdbe(&sSubParse);
  if( v ){
    VdbeComment((v, "Start: %s.%s (%s %s%s%s ON %s)", 
      pTrigger->zName, onErrorText(orconf),
      (pTrigger->tr_tm==TRIGGER_BEFORE ? "BEFORE" : "AFTER"),
        (pTrigger->op==TK_UPDATE ? "UPDATE" : ""),
        (pTrigger->op==TK_INSERT ? "INSERT" : ""),
        (pTrigger->op==TK_DELETE ? "DELETE" : ""),
936
937
938
939
940
941
942

943

944
945
946
947


948
949
950
951
952
953

954
955
956
957
958
959
960

961
962
963


964
965
966
967


968
969
970


971


972
973
974
975
976


977
978
979
980
981
982
983
984
985
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







+
-
+
-

-
-
+
+





-
+







+

-
-
+
+


-
-
+
+

-
-
+
+

+
+


-
-
-
+
+
-
-







#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(v);
        sqlite3ExprIfFalse(pSubParse, pWhen, iEndTrigger, SQLITE_JUMPIFNULL);
        iEndTrigger = sqlite3VdbeMakeLabel(&sSubParse);
        sqlite3ExprIfFalse(&sSubParse, pWhen, iEndTrigger, SQLITE_JUMPIFNULL);
      }
      sqlite3ExprDelete(db, pWhen);
    }

    /* Code the trigger program into the sub-vdbe. */
    codeTriggerProgram(pSubParse, pTrigger->step_list, orconf);
    codeTriggerProgram(&sSubParse, pTrigger->step_list, orconf);

    /* Insert an OP_Halt at the end of the sub-program. */
    if( iEndTrigger ){
      sqlite3VdbeResolveLabel(v, iEndTrigger);
    }
    sqlite3VdbeAddOp0(v, OP_Halt);
    VdbeComment((v, "End: %s.%s", pTrigger->zName, onErrorText(orconf)));
    transferParseError(pParse, &sSubParse);

    transferParseError(pParse, pSubParse);
    if( db->mallocFailed==0 && pParse->nErr==0 ){
    if( pParse->nErr==0 ){
      assert( db->mallocFailed==0 );
      pProgram->aOp = sqlite3VdbeTakeOpArray(v, &pProgram->nOp, &pTop->nMaxArg);
    }
    pProgram->nMem = pSubParse->nMem;
    pProgram->nCsr = pSubParse->nTab;
    pProgram->nMem = sSubParse.nMem;
    pProgram->nCsr = sSubParse.nTab;
    pProgram->token = (void *)pTrigger;
    pPrg->aColmask[0] = pSubParse->oldmask;
    pPrg->aColmask[1] = pSubParse->newmask;
    pPrg->aColmask[0] = sSubParse.oldmask;
    pPrg->aColmask[1] = sSubParse.newmask;
    sqlite3VdbeDelete(v);
  }else{
    transferParseError(pParse, &sSubParse);
  }

  assert( !pSubParse->pAinc       && !pSubParse->pZombieTab );
  assert( !pSubParse->pTriggerPrg && !pSubParse->nMaxArg );
  sqlite3ParserReset(pSubParse);
  assert( !sSubParse.pTriggerPrg && !sSubParse.nMaxArg );
  sqlite3ParseObjectReset(&sSubParse);
  sqlite3StackFree(db, pSubParse);

  return pPrg;
}
    
/*
** Return a pointer to a TriggerPrg object containing the sub-program for
** trigger pTrigger with default ON CONFLICT algorithm orconf. If no such
** TriggerPrg object exists, a new object is allocated and populated before
1004
1005
1006
1007
1008
1009
1010

1011
1012
1013
1014
1015
1016
1017
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294







+







      pPrg && (pPrg->pTrigger!=pTrigger || pPrg->orconf!=orconf); 
      pPrg=pPrg->pNext
  );

  /* If an existing TriggerPrg could not be located, create a new one. */
  if( !pPrg ){
    pPrg = codeRowTrigger(pParse, pTrigger, pTab, orconf);
    pParse->db->errByteOffset = -1;
  }

  return pPrg;
}

/*
** Generate code for the trigger program associated with trigger p on 
1026
1027
1028
1029
1030
1031
1032
1033

1034
1035
1036
1037
1038
1039
1040
1303
1304
1305
1306
1307
1308
1309

1310
1311
1312
1313
1314
1315
1316
1317







-
+







  int reg,             /* Reg array containing OLD.* and NEW.* values */
  int orconf,          /* ON CONFLICT policy */
  int ignoreJump       /* Instruction to jump to for RAISE(IGNORE) */
){
  Vdbe *v = sqlite3GetVdbe(pParse); /* Main VM */
  TriggerPrg *pPrg;
  pPrg = getRowTrigger(pParse, p, pTab, orconf);
  assert( pPrg || pParse->nErr || pParse->db->mallocFailed );
  assert( pPrg || pParse->nErr );

  /* Code the OP_Program opcode in the parent VDBE. P4 of the OP_Program 
  ** is a pointer to the sub-vdbe containing the trigger program.  */
  if( pPrg ){
    int bRecursive = (p->zName && 0==(pParse->db->flags&SQLITE_RecTriggers));

    sqlite3VdbeAddOp4(v, OP_Program, reg, ignoreJump, ++pParse->nMem,
1069
1070
1071
1072
1073
1074
1075
1076

1077
1078
1079
1080
1081
1082
1083
1346
1347
1348
1349
1350
1351
1352

1353
1354
1355
1356
1357
1358
1359
1360







-
+







**   Register       Contains
**   ------------------------------------------------------
**   reg+0          OLD.rowid
**   reg+1          OLD.* value of left-most column of pTab
**   ...            ...
**   reg+N          OLD.* value of right-most column of pTab
**   reg+N+1        NEW.rowid
**   reg+N+2        OLD.* value of left-most column of pTab
**   reg+N+2        NEW.* value of left-most column of pTab
**   ...            ...
**   reg+N+N+1      NEW.* value of right-most column of pTab
**
** For ON DELETE triggers, the registers containing the NEW.* values will
** never be accessed by the trigger program, so they are not allocated or 
** populated by the caller (there is no data to populate them with anyway). 
** Similarly, for ON INSERT triggers the values stored in the OLD.* registers
1114
1115
1116
1117
1118
1119
1120
1121
1122






1123
1124
1125

1126




1127
1128
1129
1130
1131
1132
1133
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







-
-
+
+
+
+
+
+



+
-
+
+
+
+







    ** always defined.  The trigger must be in the same schema as the table
    ** or else it must be a TEMP trigger. */
    assert( p->pSchema!=0 );
    assert( p->pTabSchema!=0 );
    assert( p->pSchema==p->pTabSchema 
         || p->pSchema==pParse->db->aDb[1].pSchema );

    /* Determine whether we should code this trigger */
    if( p->op==op 
    /* Determine whether we should code this trigger.  One of two choices:
    **   1. The trigger is an exact match to the current DML statement
    **   2. This is a RETURNING trigger for INSERT but we are currently
    **      doing the UPDATE part of an UPSERT.
    */
    if( (p->op==op || (p->bReturning && p->op==TK_INSERT && op==TK_UPDATE))
     && p->tr_tm==tr_tm 
     && checkColumnOverlap(p->pColumns, pChanges)
    ){
      if( !p->bReturning ){
      sqlite3CodeRowTriggerDirect(pParse, p, pTab, reg, orconf, ignoreJump);
        sqlite3CodeRowTriggerDirect(pParse, p, pTab, reg, orconf, ignoreJump);
      }else if( sqlite3IsToplevel(pParse) ){
        codeReturningTrigger(pParse, p, pTab, reg);
      }
    }
  }
}

/*
** Triggers may access values stored in the old.* or new.* pseudo-table. 
** This function returns a 32-bit bitmask indicating which columns of the 
1164
1165
1166
1167
1168
1169
1170
1171


1172
1173



1174
1175
1176
1177





1178
1179
1180
1181
1182
1183
1184
1185
1449
1450
1451
1452
1453
1454
1455

1456
1457
1458
1459
1460
1461
1462




1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475







-
+
+


+
+
+
-
-
-
-
+
+
+
+
+








){
  const int op = pChanges ? TK_UPDATE : TK_DELETE;
  u32 mask = 0;
  Trigger *p;

  assert( isNew==1 || isNew==0 );
  for(p=pTrigger; p; p=p->pNext){
    if( p->op==op && (tr_tm&p->tr_tm)
    if( p->op==op
     && (tr_tm&p->tr_tm)
     && checkColumnOverlap(p->pColumns,pChanges)
    ){
      if( p->bReturning ){
        mask = 0xffffffff;
      }else{
      TriggerPrg *pPrg;
      pPrg = getRowTrigger(pParse, p, pTab, orconf);
      if( pPrg ){
        mask |= pPrg->aColmask[isNew];
        TriggerPrg *pPrg;
        pPrg = getRowTrigger(pParse, p, pTab, orconf);
        if( pPrg ){
          mask |= pPrg->aColmask[isNew];
        }
      }
    }
  }

  return mask;
}

#endif /* !defined(SQLITE_OMIT_TRIGGER) */

Changes to src/update.c.

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
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







-
+






+
+
-
+
-
-
-
+


+

+
-
+
+


-
-
+
+

-
+
+






-
+







** If the former, then all row-records are guaranteed to include a value
** for the column and the P4 value is not required.
**
** Column definitions created by an ALTER TABLE command may only have 
** literal default values specified: a number, null or a string. (If a more
** complicated default expression value was provided, it is evaluated 
** when the ALTER TABLE is executed and one of the literal values written
** into the sqlite_master table.)
** into the sqlite_schema table.)
**
** Therefore, the P4 parameter is only required if the default value for
** the column is a literal number, string or null. The sqlite3ValueFromExpr()
** function is capable of transforming these types of expressions into
** sqlite3_value objects.
**
** If column as REAL affinity and the table is an ordinary b-tree table
** (not a virtual table) then the value might have been stored as an
** If parameter iReg is not negative, code an OP_RealAffinity instruction
** integer.  In that case, add an OP_RealAffinity opcode to make sure
** on register iReg. This is used when an equivalent integer value is 
** stored in place of an 8-byte floating point value in order to save 
** space.
** it has been converted into REAL.
*/
void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
  Column *pCol;
  assert( pTab!=0 );
  assert( pTab->nCol>i );
  if( !pTab->pSelect ){
  pCol = &pTab->aCol[i];
  if( pCol->iDflt ){
    sqlite3_value *pValue = 0;
    u8 enc = ENC(sqlite3VdbeDb(v));
    Column *pCol = &pTab->aCol[i];
    VdbeComment((v, "%s.%s", pTab->zName, pCol->zName));
    assert( !IsView(pTab) );
    VdbeComment((v, "%s.%s", pTab->zName, pCol->zCnName));
    assert( i<pTab->nCol );
    sqlite3ValueFromExpr(sqlite3VdbeDb(v), pCol->pDflt, enc, 
    sqlite3ValueFromExpr(sqlite3VdbeDb(v), 
                         sqlite3ColumnExpr(pTab,pCol), enc, 
                         pCol->affinity, &pValue);
    if( pValue ){
      sqlite3VdbeAppendP4(v, pValue, P4_MEM);
    }
  }
#ifndef SQLITE_OMIT_FLOATING_POINT
  if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){
  if( pCol->affinity==SQLITE_AFF_REAL && !IsVirtual(pTab) ){
    sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
  }
#endif
}

/*
** Check to see if column iCol of index pIdx references any of the
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
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









+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
-
+
+
+
+
+











-
+


-
+




+




-
+








+







  int *aXRef,       /* aXRef[j]>=0 if column j is being updated */
  int chngRowid     /* true if the rowid is being updated */
){
  if( pIdx->pPartIdxWhere==0 ) return 0;
  return sqlite3ExprReferencesUpdatedColumn(pIdx->pPartIdxWhere,
                                            aXRef, chngRowid);
}

/*
** Allocate and return a pointer to an expression of type TK_ROW with
** Expr.iColumn set to value (iCol+1). The resolver will modify the
** expression to be a TK_COLUMN reading column iCol of the first
** table in the source-list (pSrc->a[0]).
*/
static Expr *exprRowColumn(Parse *pParse, int iCol){
  Expr *pRet = sqlite3PExpr(pParse, TK_ROW, 0, 0);
  if( pRet ) pRet->iColumn = iCol+1;
  return pRet;
}

/*
** Assuming both the pLimit and pOrderBy parameters are NULL, this function
** generates VM code to run the query:
**
**   SELECT <other-columns>, pChanges FROM pTabList WHERE pWhere 
**
** and write the results to the ephemeral table already opened as cursor 
** iEph. None of pChanges, pTabList or pWhere are modified or consumed by 
** this function, they must be deleted by the caller.
**
** Or, if pLimit and pOrderBy are not NULL, and pTab is not a view:
**
**   SELECT <other-columns>, pChanges FROM pTabList 
**   WHERE pWhere
**   GROUP BY <other-columns> 
**   ORDER BY pOrderBy LIMIT pLimit
**
** If pTab is a view, the GROUP BY clause is omitted.
**
** Exactly how results are written to table iEph, and exactly what
** the <other-columns> in the query above are is determined by the type
** of table pTabList->a[0].pTab.
**
** If the table is a WITHOUT ROWID table, then argument pPk must be its
** PRIMARY KEY. In this case <other-columns> are the primary key columns
** of the table, in order. The results of the query are written to ephemeral
** table iEph as index keys, using OP_IdxInsert.
**
** If the table is actually a view, then <other-columns> are all columns of
** the view. The results are written to the ephemeral table iEph as records
** with automatically assigned integer keys.
**
** If the table is a virtual or ordinary intkey table, then <other-columns> 
** is its rowid. For a virtual table, the results are written to iEph as
** records with automatically assigned integer keys For intkey tables, the
** rowid value in <other-columns> is used as the integer key, and the 
** remaining fields make up the table record. 
*/
static void updateFromSelect(
  Parse *pParse,                  /* Parse context */
  int iEph,                       /* Cursor for open eph. table */
  Index *pPk,                     /* PK if table 0 is WITHOUT ROWID */
  ExprList *pChanges,             /* List of expressions to return */
  SrcList *pTabList,              /* List of tables to select from */
  Expr *pWhere,                   /* WHERE clause for query */
  ExprList *pOrderBy,             /* ORDER BY clause */
  Expr *pLimit                    /* LIMIT clause */
){
  int i;
  SelectDest dest;
  Select *pSelect = 0;
  ExprList *pList = 0;
  ExprList *pGrp = 0;
  Expr *pLimit2 = 0;
  ExprList *pOrderBy2 = 0;
  sqlite3 *db = pParse->db;
  Table *pTab = pTabList->a[0].pTab;
  SrcList *pSrc;
  Expr *pWhere2;
  int eDest;

#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
  if( pOrderBy && pLimit==0 ) {
    sqlite3ErrorMsg(pParse, "ORDER BY without LIMIT on UPDATE");
    return;
  }
  pOrderBy2 = sqlite3ExprListDup(db, pOrderBy, 0);
  pLimit2 = sqlite3ExprDup(db, pLimit, 0);
#else
  UNUSED_PARAMETER(pOrderBy);
  UNUSED_PARAMETER(pLimit);
#endif

  pSrc = sqlite3SrcListDup(db, pTabList, 0);
  pWhere2 = sqlite3ExprDup(db, pWhere, 0);

  assert( pTabList->nSrc>1 );
  if( pSrc ){
    pSrc->a[0].fg.notCte = 1;
    pSrc->a[0].iCursor = -1;
    pSrc->a[0].pTab->nTabRef--;
    pSrc->a[0].pTab = 0;
  }
  if( pPk ){
    for(i=0; i<pPk->nKeyCol; i++){
      Expr *pNew = exprRowColumn(pParse, pPk->aiColumn[i]);
#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
      if( pLimit ){
        pGrp = sqlite3ExprListAppend(pParse, pGrp, sqlite3ExprDup(db, pNew, 0));
      }
#endif
      pList = sqlite3ExprListAppend(pParse, pList, pNew);
    }
    eDest = IsVirtual(pTab) ? SRT_Table : SRT_Upfrom;
  }else if( IsView(pTab) ){
    for(i=0; i<pTab->nCol; i++){
      pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i));
    }
    eDest = SRT_Table;
  }else{
    eDest = IsVirtual(pTab) ? SRT_Table : SRT_Upfrom;
    pList = sqlite3ExprListAppend(pParse, 0, sqlite3PExpr(pParse,TK_ROW,0,0));
#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
    if( pLimit ){
      pGrp = sqlite3ExprListAppend(pParse, 0, sqlite3PExpr(pParse,TK_ROW,0,0));
    }
#endif
  }
  assert( pChanges!=0 || pParse->db->mallocFailed );
  if( pChanges ){
    for(i=0; i<pChanges->nExpr; i++){
      pList = sqlite3ExprListAppend(pParse, pList, 
          sqlite3ExprDup(db, pChanges->a[i].pExpr, 0)
      );
    }
  }
  pSelect = sqlite3SelectNew(pParse, pList, 
      pSrc, pWhere2, pGrp, 0, pOrderBy2, 
      SF_UFSrcCheck|SF_IncludeHidden|SF_UpdateFrom, pLimit2
  );
  if( pSelect ) pSelect->selFlags |= SF_OrderByReqd;
  sqlite3SelectDestInit(&dest, eDest, iEph);
  dest.iSDParm2 = (pPk ? pPk->nKeyCol : -1);
  sqlite3Select(pParse, pSelect, &dest);
  sqlite3SelectDelete(db, pSelect);
}

/*
** Process an UPDATE statement.
**
**   UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL;
**          \_______/ \________/     \______/       \________________/
*            onError   pTabList      pChanges             pWhere
**   UPDATE OR IGNORE tbl SET a=b, c=d FROM tbl2... WHERE e<5 AND f NOT NULL;
**          \_______/ \_/     \______/      \_____/       \________________/
**           onError   |      pChanges         |                pWhere
**                     \_______________________/
**                               pTabList
*/
void sqlite3Update(
  Parse *pParse,         /* The parser context */
  SrcList *pTabList,     /* The table in which we should change things */
  ExprList *pChanges,    /* Things to be changed */
  Expr *pWhere,          /* The WHERE clause.  May be null */
  int onError,           /* How to handle constraint errors */
  ExprList *pOrderBy,    /* ORDER BY clause. May be null */
  Expr *pLimit,          /* LIMIT clause. May be null */
  Upsert *pUpsert        /* ON CONFLICT clause, or null */
){
  int i, j;              /* Loop counters */
  int i, j, k;           /* Loop counters */
  Table *pTab;           /* The table to be updated */
  int addrTop = 0;       /* VDBE instruction address of the start of the loop */
  WhereInfo *pWInfo;     /* Information about the WHERE clause */
  WhereInfo *pWInfo = 0; /* Information about the WHERE clause */
  Vdbe *v;               /* The virtual database engine */
  Index *pIdx;           /* For looping over indices */
  Index *pPk;            /* The PRIMARY KEY index for WITHOUT ROWID tables */
  int nIdx;              /* Number of indices that need updating */
  int nAllIdx;           /* Total number of indexes */
  int iBaseCur;          /* Base cursor number */
  int iDataCur;          /* Cursor for the canonical data btree */
  int iIdxCur;           /* Cursor for the first index */
  sqlite3 *db;           /* The database structure */
  int *aRegIdx = 0;      /* First register in array assigned to each index */
  int *aRegIdx = 0;      /* Registers for to each index and the main table */
  int *aXRef = 0;        /* aXRef[i] is the index in pChanges->a[] of the
                         ** an expression for the i-th column of the table.
                         ** aXRef[i]==-1 if the i-th column is not changed. */
  u8 *aToOpen;           /* 1 for tables and indices to be opened */
  u8 chngPk;             /* PRIMARY KEY changed in a WITHOUT ROWID table */
  u8 chngRowid;          /* Rowid changed in a normal table */
  u8 chngKey;            /* Either chngPk or chngRowid */
  Expr *pRowidExpr = 0;  /* Expression defining the new record number */
  int iRowidExpr = -1;   /* Index of "rowid=" (or IPK) assignment in pChanges */
  AuthContext sContext;  /* The authorization context */
  NameContext sNC;       /* The name-context to resolve expressions in */
  int iDb;               /* Database containing the table being updated */
  int eOnePass;          /* ONEPASS_XXX value from where.c */
  int hasFK;             /* True if foreign key processing is required */
  int labelBreak;        /* Jump here to break out of UPDATE loop */
  int labelContinue;     /* Jump here to continue next step of UPDATE loop */
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
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







+
+












+
-
+


-
+












-
+











+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+







  int iEph = 0;          /* Ephemeral table holding all primary key values */
  int nKey = 0;          /* Number of elements in regKey for WITHOUT ROWID */
  int aiCurOnePass[2];   /* The write cursors opened by WHERE_ONEPASS */
  int addrOpen = 0;      /* Address of OP_OpenEphemeral */
  int iPk = 0;           /* First of nPk cells holding PRIMARY KEY value */
  i16 nPk = 0;           /* Number of components of the PRIMARY KEY */
  int bReplace = 0;      /* True if REPLACE conflict resolution might happen */
  int bFinishSeek = 1;   /* The OP_FinishSeek opcode is needed */
  int nChangeFrom = 0;   /* If there is a FROM, pChanges->nExpr, else 0 */

  /* Register Allocations */
  int regRowCount = 0;   /* A count of rows changed */
  int regOldRowid = 0;   /* The old rowid */
  int regNewRowid = 0;   /* The new rowid */
  int regNew = 0;        /* Content of the NEW.* table in triggers */
  int regOld = 0;        /* Content of OLD.* table in triggers */
  int regRowSet = 0;     /* Rowset of rows to be updated */
  int regKey = 0;        /* composite PRIMARY KEY value */

  memset(&sContext, 0, sizeof(sContext));
  db = pParse->db;
  assert( db->pParse==pParse );
  if( pParse->nErr || db->mallocFailed ){
  if( pParse->nErr ){
    goto update_cleanup;
  }
  assert( pTabList->nSrc==1 );
  assert( db->mallocFailed==0 );

  /* Locate the table which we want to update. 
  */
  pTab = sqlite3SrcListLookup(pParse, pTabList);
  if( pTab==0 ) goto update_cleanup;
  iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);

  /* Figure out if we have any triggers and if the table being
  ** updated is a view.
  */
#ifndef SQLITE_OMIT_TRIGGER
  pTrigger = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges, &tmask);
  isView = pTab->pSelect!=0;
  isView = IsView(pTab);
  assert( pTrigger || tmask==0 );
#else
# define pTrigger 0
# define isView 0
# define tmask 0
#endif
#ifdef SQLITE_OMIT_VIEW
# undef isView
# define isView 0
#endif

#if TREETRACE_ENABLED
  if( sqlite3TreeTrace & 0x10000 ){
    sqlite3TreeViewLine(0, "In sqlite3Update() at %s:%d", __FILE__, __LINE__);
    sqlite3TreeViewUpdate(pParse->pWith, pTabList, pChanges, pWhere,
                          onError, pOrderBy, pLimit, pUpsert, pTrigger);
  }
#endif

  /* If there was a FROM clause, set nChangeFrom to the number of expressions
  ** in the change-list. Otherwise, set it to 0. There cannot be a FROM
  ** clause if this function is being called to generate code for part of
  ** an UPSERT statement.  */
  nChangeFrom = (pTabList->nSrc>1) ? pChanges->nExpr : 0;
  assert( nChangeFrom==0 || pUpsert==0 );

#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
  if( !isView ){
  if( !isView && nChangeFrom==0 ){
    pWhere = sqlite3LimitWhere(
        pParse, pTabList, pWhere, pOrderBy, pLimit, "UPDATE"
    );
    pOrderBy = 0;
    pLimit = 0;
  }
#endif
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
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







-
+


-
+











+
+
+
+












-
+






+
+
+
-
+



+
-
+
+



+



+
+
+
+
+
+
+
+
+
+





-
+



+

-
+








-
+













+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+














+
-
+












-
-
+
-






-
-
+
+

+






-
-
-





+
+
+
+
+
+
-
+







    pParse->nTab = iBaseCur;
  }
  pTabList->a[0].iCursor = iDataCur;

  /* Allocate space for aXRef[], aRegIdx[], and aToOpen[].  
  ** Initialize aXRef[] and aToOpen[] to their default values.
  */
  aXRef = sqlite3DbMallocRawNN(db, sizeof(int) * (pTab->nCol+nIdx) + nIdx+2 );
  aXRef = sqlite3DbMallocRawNN(db, sizeof(int) * (pTab->nCol+nIdx+1) + nIdx+2 );
  if( aXRef==0 ) goto update_cleanup;
  aRegIdx = aXRef+pTab->nCol;
  aToOpen = (u8*)(aRegIdx+nIdx);
  aToOpen = (u8*)(aRegIdx+nIdx+1);
  memset(aToOpen, 1, nIdx+1);
  aToOpen[nIdx+1] = 0;
  for(i=0; i<pTab->nCol; i++) aXRef[i] = -1;

  /* Initialize the name-context */
  memset(&sNC, 0, sizeof(sNC));
  sNC.pParse = pParse;
  sNC.pSrcList = pTabList;
  sNC.uNC.pUpsert = pUpsert;
  sNC.ncFlags = NC_UUpsert;

  /* Begin generating code. */
  v = sqlite3GetVdbe(pParse);
  if( v==0 ) goto update_cleanup;

  /* Resolve the column names in all the expressions of the
  ** of the UPDATE statement.  Also find the column index
  ** for each column to be updated in the pChanges array.  For each
  ** column to be updated, make sure we have authorization to change
  ** that column.
  */
  chngRowid = chngPk = 0;
  for(i=0; i<pChanges->nExpr; i++){
#if defined(SQLITE_ENABLE_NOOP_UPDATE) && !defined(SQLITE_OMIT_FLAG_PRAGMAS)
    if( db->flags & SQLITE_NoopUpdate ){
      Token x;
      sqlite3ExprDelete(db, pChanges->a[i].pExpr);
      x.z = pChanges->a[i].zName;
      x.z = pChanges->a[i].zEName;
      x.n = sqlite3Strlen30(x.z);
      pChanges->a[i].pExpr =
         sqlite3PExpr(pParse, TK_UPLUS, sqlite3ExprAlloc(db, TK_ID, &x, 0), 0);
      if( db->mallocFailed ) goto update_cleanup;
    }
#endif
    u8 hCol = sqlite3StrIHash(pChanges->a[i].zEName);
    /* If this is an UPDATE with a FROM clause, do not resolve expressions
    ** here. The call to sqlite3Select() below will do that. */
    if( sqlite3ResolveExprNames(&sNC, pChanges->a[i].pExpr) ){
    if( nChangeFrom==0 && sqlite3ResolveExprNames(&sNC, pChanges->a[i].pExpr) ){
      goto update_cleanup;
    }
    for(j=0; j<pTab->nCol; j++){
      if( pTab->aCol[j].hName==hCol
      if( sqlite3StrICmp(pTab->aCol[j].zName, pChanges->a[i].zName)==0 ){
       && sqlite3StrICmp(pTab->aCol[j].zCnName, pChanges->a[i].zEName)==0
      ){
        if( j==pTab->iPKey ){
          chngRowid = 1;
          pRowidExpr = pChanges->a[i].pExpr;
          iRowidExpr = i;
        }else if( pPk && (pTab->aCol[j].colFlags & COLFLAG_PRIMKEY)!=0 ){
          chngPk = 1;
        }
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
        else if( pTab->aCol[j].colFlags & COLFLAG_GENERATED ){
          testcase( pTab->aCol[j].colFlags & COLFLAG_VIRTUAL );
          testcase( pTab->aCol[j].colFlags & COLFLAG_STORED );
          sqlite3ErrorMsg(pParse, 
             "cannot UPDATE generated column \"%s\"",
             pTab->aCol[j].zCnName);
          goto update_cleanup;
        }
#endif
        aXRef[j] = i;
        break;
      }
    }
    if( j>=pTab->nCol ){
      if( pPk==0 && sqlite3IsRowid(pChanges->a[i].zName) ){
      if( pPk==0 && sqlite3IsRowid(pChanges->a[i].zEName) ){
        j = -1;
        chngRowid = 1;
        pRowidExpr = pChanges->a[i].pExpr;
        iRowidExpr = i;
      }else{
        sqlite3ErrorMsg(pParse, "no such column: %s", pChanges->a[i].zName);
        sqlite3ErrorMsg(pParse, "no such column: %s", pChanges->a[i].zEName);
        pParse->checkSchema = 1;
        goto update_cleanup;
      }
    }
#ifndef SQLITE_OMIT_AUTHORIZATION
    {
      int rc;
      rc = sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab->zName,
                            j<0 ? "ROWID" : pTab->aCol[j].zName,
                            j<0 ? "ROWID" : pTab->aCol[j].zCnName,
                            db->aDb[iDb].zDbSName);
      if( rc==SQLITE_DENY ){
        goto update_cleanup;
      }else if( rc==SQLITE_IGNORE ){
        aXRef[j] = -1;
      }
    }
#endif
  }
  assert( (chngRowid & chngPk)==0 );
  assert( chngRowid==0 || chngRowid==1 );
  assert( chngPk==0 || chngPk==1 );
  chngKey = chngRowid + chngPk;

#ifndef SQLITE_OMIT_GENERATED_COLUMNS
  /* Mark generated columns as changing if their generator expressions
  ** reference any changing column.  The actual aXRef[] value for 
  ** generated expressions is not used, other than to check to see that it
  ** is non-negative, so the value of aXRef[] for generated columns can be
  ** set to any non-negative number.  We use 99999 so that the value is
  ** obvious when looking at aXRef[] in a symbolic debugger. 
  */
  if( pTab->tabFlags & TF_HasGenerated ){
    int bProgress;
    testcase( pTab->tabFlags & TF_HasVirtual );
    testcase( pTab->tabFlags & TF_HasStored );
    do{
      bProgress = 0;
      for(i=0; i<pTab->nCol; i++){
        if( aXRef[i]>=0 ) continue;
        if( (pTab->aCol[i].colFlags & COLFLAG_GENERATED)==0 ) continue;
        if( sqlite3ExprReferencesUpdatedColumn(
                sqlite3ColumnExpr(pTab, &pTab->aCol[i]),
                 aXRef, chngRowid)
        ){
          aXRef[i] = 99999;
          bProgress = 1;
        }
      }
    }while( bProgress );
  }
#endif

  /* The SET expressions are not actually used inside the WHERE loop.  
  ** So reset the colUsed mask. Unless this is a virtual table. In that
  ** case, set all bits of the colUsed mask (to ensure that the virtual
  ** table implementation makes all columns available).
  */
  pTabList->a[0].colUsed = IsVirtual(pTab) ? ALLBITS : 0;

  hasFK = sqlite3FkRequired(pParse, pTab, aXRef, chngKey);

  /* There is one entry in the aRegIdx[] array for each index on the table
  ** being updated.  Fill in aRegIdx[] with a register number that will hold
  ** the key for accessing each index.
  */
  if( onError==OE_Replace ) bReplace = 1;
  for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
  for(nAllIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nAllIdx++){
    int reg;
    if( chngKey || hasFK>1 || pIdx==pPk
     || indexWhereClauseMightChange(pIdx,aXRef,chngRowid)
    ){
      reg = ++pParse->nMem;
      pParse->nMem += pIdx->nColumn;
    }else{
      reg = 0;
      for(i=0; i<pIdx->nKeyCol; i++){
        if( indexColumnIsBeingUpdated(pIdx, i, aXRef, chngRowid) ){
          reg = ++pParse->nMem;
          pParse->nMem += pIdx->nColumn;
          if( (onError==OE_Replace)
           || (onError==OE_Default && pIdx->onError==OE_Replace) 
          if( onError==OE_Default && pIdx->onError==OE_Replace ){
          ){
            bReplace = 1;
          }
          break;
        }
      }
    }
    if( reg==0 ) aToOpen[j+1] = 0;
    aRegIdx[j] = reg;
    if( reg==0 ) aToOpen[nAllIdx+1] = 0;
    aRegIdx[nAllIdx] = reg;
  }
  aRegIdx[nAllIdx] = ++pParse->nMem;  /* Register storing the table record */
  if( bReplace ){
    /* If REPLACE conflict resolution might be invoked, open cursors on all 
    ** indexes in case they are needed to delete records.  */
    memset(aToOpen, 1, nIdx+1);
  }

  /* Begin generating code. */
  v = sqlite3GetVdbe(pParse);
  if( v==0 ) goto update_cleanup;
  if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
  sqlite3BeginWriteOperation(pParse, pTrigger || hasFK, iDb);

  /* Allocate required registers. */
  if( !IsVirtual(pTab) ){
    /* For now, regRowSet and aRegIdx[nAllIdx] share the same register.
    ** If regRowSet turns out to be needed, then aRegIdx[nAllIdx] will be
    ** reallocated.  aRegIdx[nAllIdx] is the register in which the main
    ** table record is written.  regRowSet holds the RowSet for the
    ** two-pass update algorithm. */
    assert( aRegIdx[nAllIdx]==pParse->nMem );
    regRowSet = ++pParse->nMem;
    regRowSet = aRegIdx[nAllIdx];
    regOldRowid = regNewRowid = ++pParse->nMem;
    if( chngPk || pTrigger || hasFK ){
      regOld = pParse->nMem + 1;
      pParse->nMem += pTab->nCol;
    }
    if( chngKey || pTrigger || hasFK ){
      regNewRowid = ++pParse->nMem;
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
638
639
640
641
642
640
641
642
643
644
645
646

647
648
649
650
651
652
653
654
655
656
657
658

659
660
661
662
663
664
665
666
667
668
669
670
671
672

673
674
675
676
677
678
679
680
681
682
683
684
685
686

687
688
689
690
691


692
693
694
695
696
697
698
699
700




















































701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
908
909
910
911
912
913

914
915
916

917
918

919
920
921
922
923
924
925
926







-
+











-
+













-
+






+






-
+

+
+

-
-
+
+


+


+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+

















-
+
+
+




+
-
+
+
+
+
+





-
+




-
-
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+

+
-
-
+
+












+
+
-
+
+
+
+











+
+


-
+


-
+

-
+







    sqlite3AuthContextPush(pParse, &sContext, pTab->zName);
  }

  /* If we are trying to update a view, realize that view into
  ** an ephemeral table.
  */
#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
  if( isView ){
  if( nChangeFrom==0 && isView ){
    sqlite3MaterializeView(pParse, pTab, 
        pWhere, pOrderBy, pLimit, iDataCur
    );
    pOrderBy = 0;
    pLimit = 0;
  }
#endif

  /* Resolve the column names in all the expressions in the
  ** WHERE clause.
  */
  if( sqlite3ResolveExprNames(&sNC, pWhere) ){
  if( nChangeFrom==0 && sqlite3ResolveExprNames(&sNC, pWhere) ){
    goto update_cleanup;
  }

#ifndef SQLITE_OMIT_VIRTUALTABLE
  /* Virtual tables must be handled separately */
  if( IsVirtual(pTab) ){
    updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef,
                       pWhere, onError);
    goto update_cleanup;
  }
#endif

  /* Jump to labelBreak to abandon further processing of this UPDATE */
  labelContinue = labelBreak = sqlite3VdbeMakeLabel(v);
  labelContinue = labelBreak = sqlite3VdbeMakeLabel(pParse);

  /* Not an UPSERT.  Normal processing.  Begin by
  ** initialize the count of updated rows */
  if( (db->flags&SQLITE_CountRows)!=0
   && !pParse->pTriggerTab
   && !pParse->nested
   && !pParse->bReturning
   && pUpsert==0
  ){
    regRowCount = ++pParse->nMem;
    sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount);
  }

  if( HasRowid(pTab) ){
  if( nChangeFrom==0 && HasRowid(pTab) ){
    sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid);
    iEph = pParse->nTab++;
    addrOpen = sqlite3VdbeAddOp3(v, OP_OpenEphemeral, iEph, 0, regRowSet);
  }else{
    assert( pPk!=0 );
    nPk = pPk->nKeyCol;
    assert( pPk!=0 || HasRowid(pTab) );
    nPk = pPk ? pPk->nKeyCol : 0;
    iPk = pParse->nMem+1;
    pParse->nMem += nPk;
    pParse->nMem += nChangeFrom;
    regKey = ++pParse->nMem;
    if( pUpsert==0 ){
      int nEphCol = nPk + nChangeFrom + (isView ? pTab->nCol : 0);
      iEph = pParse->nTab++;
        sqlite3VdbeAddOp3(v, OP_Null, 0, iPk, iPk+nPk-1);
      addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nPk);
      sqlite3VdbeSetP4KeyInfo(pParse, pPk);
    }
  }
  
  if( pUpsert ){
    /* If this is an UPSERT, then all cursors have already been opened by
    ** the outer INSERT and the data cursor should be pointing at the row
    ** that is to be updated.  So bypass the code that searches for the
    ** row(s) to be updated.
    */
    pWInfo = 0;
    eOnePass = ONEPASS_SINGLE;
    sqlite3ExprIfFalse(pParse, pWhere, labelBreak, SQLITE_JUMPIFNULL);
  }else{
    /* Begin the database scan. 
    **
    ** Do not consider a single-pass strategy for a multi-row update if
    ** there are any triggers or foreign keys to process, or rows may
    ** be deleted as a result of REPLACE conflict handling. Any of these
    ** things might disturb a cursor being used to scan through the table
    ** or index, causing a single-pass approach to malfunction.  */
    flags = WHERE_ONEPASS_DESIRED|WHERE_SEEK_UNIQ_TABLE;
    if( !pParse->nested && !pTrigger && !hasFK && !chngKey && !bReplace ){
      flags |= WHERE_ONEPASS_MULTIROW;
    }
    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, flags, iIdxCur);
    if( pWInfo==0 ) goto update_cleanup;
  
    /* A one-pass strategy that might update more than one row may not
    ** be used if any column of the index used for the scan is being
    ** updated. Otherwise, if there is an index on "b", statements like
    ** the following could create an infinite loop:
    **
    **   UPDATE t1 SET b=b+1 WHERE b>?
    **
    ** Fall back to ONEPASS_OFF if where.c has selected a ONEPASS_MULTI
    ** strategy that uses an index for which one or more columns are being
    ** updated.  */
    eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
    if( eOnePass!=ONEPASS_SINGLE ){
      sqlite3MultiWrite(pParse);
      if( eOnePass==ONEPASS_MULTI ){
        int iCur = aiCurOnePass[1];
        if( iCur>=0 && iCur!=iDataCur && aToOpen[iCur-iBaseCur] ){
          eOnePass = ONEPASS_OFF;
        }
        assert( iCur!=iDataCur || !HasRowid(pTab) );
      }
    }
  }
      if( pPk ) sqlite3VdbeAddOp3(v, OP_Null, 0, iPk, iPk+nPk-1);
      addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nEphCol);
      if( pPk ){
        KeyInfo *pKeyInfo = sqlite3KeyInfoOfIndex(pParse, pPk);
        if( pKeyInfo ){
          pKeyInfo->nAllField = nEphCol;
          sqlite3VdbeAppendP4(v, pKeyInfo, P4_KEYINFO);
        }
      }
      if( nChangeFrom ){
        updateFromSelect(
            pParse, iEph, pPk, pChanges, pTabList, pWhere, pOrderBy, pLimit
        );
#ifndef SQLITE_OMIT_SUBQUERY
        if( isView ) iDataCur = iEph;
#endif
      }
    }
  }
  
  if( nChangeFrom ){
    sqlite3MultiWrite(pParse);
    eOnePass = ONEPASS_OFF;
    nKey = nPk;
    regKey = iPk;
  }else{
    if( pUpsert ){
      /* If this is an UPSERT, then all cursors have already been opened by
      ** the outer INSERT and the data cursor should be pointing at the row
      ** that is to be updated.  So bypass the code that searches for the
      ** row(s) to be updated.
      */
      pWInfo = 0;
      eOnePass = ONEPASS_SINGLE;
      sqlite3ExprIfFalse(pParse, pWhere, labelBreak, SQLITE_JUMPIFNULL);
      bFinishSeek = 0;
    }else{
      /* Begin the database scan. 
      **
      ** Do not consider a single-pass strategy for a multi-row update if
      ** there are any triggers or foreign keys to process, or rows may
      ** be deleted as a result of REPLACE conflict handling. Any of these
      ** things might disturb a cursor being used to scan through the table
      ** or index, causing a single-pass approach to malfunction.  */
      flags = WHERE_ONEPASS_DESIRED;
      if( !pParse->nested && !pTrigger && !hasFK && !chngKey && !bReplace ){
        flags |= WHERE_ONEPASS_MULTIROW;
      }
      pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0,0,0,flags,iIdxCur);
      if( pWInfo==0 ) goto update_cleanup;

      /* A one-pass strategy that might update more than one row may not
      ** be used if any column of the index used for the scan is being
      ** updated. Otherwise, if there is an index on "b", statements like
      ** the following could create an infinite loop:
      **
      **   UPDATE t1 SET b=b+1 WHERE b>?
      **
      ** Fall back to ONEPASS_OFF if where.c has selected a ONEPASS_MULTI
      ** strategy that uses an index for which one or more columns are being
      ** updated.  */
      eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
      bFinishSeek = sqlite3WhereUsesDeferredSeek(pWInfo);
      if( eOnePass!=ONEPASS_SINGLE ){
        sqlite3MultiWrite(pParse);
        if( eOnePass==ONEPASS_MULTI ){
          int iCur = aiCurOnePass[1];
          if( iCur>=0 && iCur!=iDataCur && aToOpen[iCur-iBaseCur] ){
            eOnePass = ONEPASS_OFF;
          }
          assert( iCur!=iDataCur || !HasRowid(pTab) );
        }
      }
    }

  if( HasRowid(pTab) ){
    /* Read the rowid of the current row of the WHERE scan. In ONEPASS_OFF
    ** mode, write the rowid into the FIFO. In either of the one-pass modes,
    ** leave it in register regOldRowid.  */
    sqlite3VdbeAddOp2(v, OP_Rowid, iDataCur, regOldRowid);
    if( eOnePass==ONEPASS_OFF ){
      sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid);
    }
  }else{
    /* Read the PK of the current row into an array of registers. In
    ** ONEPASS_OFF mode, serialize the array into a record and store it in
    ** the ephemeral table. Or, in ONEPASS_SINGLE or MULTI mode, change
    ** the OP_OpenEphemeral instruction to a Noop (the ephemeral table 
    ** is not required) and leave the PK fields in the array of registers.  */
    for(i=0; i<nPk; i++){
      assert( pPk->aiColumn[i]>=0 );
      sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur,pPk->aiColumn[i],iPk+i);
    }
    if( eOnePass ){
      if( addrOpen ) sqlite3VdbeChangeToNoop(v, addrOpen);
      nKey = nPk;
      regKey = iPk;
    }else{
      sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, regKey,
                        sqlite3IndexAffinityStr(db, pPk), nPk);
      sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iEph, regKey, iPk, nPk);
    }
  }

    if( HasRowid(pTab) ){
      /* Read the rowid of the current row of the WHERE scan. In ONEPASS_OFF
      ** mode, write the rowid into the FIFO. In either of the one-pass modes,
      ** leave it in register regOldRowid.  */
      sqlite3VdbeAddOp2(v, OP_Rowid, iDataCur, regOldRowid);
      if( eOnePass==ONEPASS_OFF ){
        aRegIdx[nAllIdx] = ++pParse->nMem;
        sqlite3VdbeAddOp3(v, OP_Insert, iEph, regRowSet, regOldRowid);
      }else{
        if( ALWAYS(addrOpen) ) sqlite3VdbeChangeToNoop(v, addrOpen);
      }
    }else{
      /* Read the PK of the current row into an array of registers. In
      ** ONEPASS_OFF mode, serialize the array into a record and store it in
      ** the ephemeral table. Or, in ONEPASS_SINGLE or MULTI mode, change
      ** the OP_OpenEphemeral instruction to a Noop (the ephemeral table 
      ** is not required) and leave the PK fields in the array of registers.  */
      for(i=0; i<nPk; i++){
        assert( pPk->aiColumn[i]>=0 );
        sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur,
                                        pPk->aiColumn[i], iPk+i);
      }
      if( eOnePass ){
        if( addrOpen ) sqlite3VdbeChangeToNoop(v, addrOpen);
        nKey = nPk;
        regKey = iPk;
      }else{
        sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, regKey,
                          sqlite3IndexAffinityStr(db, pPk), nPk);
        sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iEph, regKey, iPk, nPk);
      }
    }
  }

  if( pUpsert==0 ){
    if( eOnePass!=ONEPASS_MULTI ){
    if( nChangeFrom==0 && eOnePass!=ONEPASS_MULTI ){
      sqlite3WhereEnd(pWInfo);
    }
  
    if( !isView ){
      int addrOnce = 0;
  
      /* Open every index that needs updating. */
      if( eOnePass!=ONEPASS_OFF ){
        if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iBaseCur] = 0;
        if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iBaseCur] = 0;
      }
  
      if( eOnePass==ONEPASS_MULTI && (nIdx-(aiCurOnePass[1]>=0))>0 ){
        addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
      }
      sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, iBaseCur,
                                 aToOpen, 0, 0);
      if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce);
      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(v);
        labelContinue = sqlite3VdbeMakeLabel(pParse);
      }
      sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak);
      VdbeCoverageIf(v, pPk==0);
      VdbeCoverageIf(v, pPk!=0);
    }else if( pPk ){
      labelContinue = sqlite3VdbeMakeLabel(v);
    }else if( pPk || nChangeFrom ){
      labelContinue = sqlite3VdbeMakeLabel(pParse);
      sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v);
      addrTop = sqlite3VdbeCurrentAddr(v);
      if( nChangeFrom ){
        if( !isView ){
          if( pPk ){
            for(i=0; i<nPk; i++){
              sqlite3VdbeAddOp3(v, OP_Column, iEph, i, iPk+i);
            }
            sqlite3VdbeAddOp4Int(
                v, OP_NotFound, iDataCur, labelContinue, iPk, nPk
            ); VdbeCoverage(v);
          }else{
            sqlite3VdbeAddOp2(v, OP_Rowid, iEph, regOldRowid);
            sqlite3VdbeAddOp3(
                v, OP_NotExists, iDataCur, labelContinue, regOldRowid
            ); VdbeCoverage(v);
          }
        }
      }else{
      addrTop = sqlite3VdbeAddOp2(v, OP_RowData, iEph, regKey);
      sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0);
      VdbeCoverage(v);
        sqlite3VdbeAddOp2(v, OP_RowData, iEph, regKey);
        sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey,0);
        VdbeCoverage(v);
      }
    }else{
      sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v);
      labelContinue = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet,labelBreak,
                               regOldRowid);
      labelContinue = sqlite3VdbeMakeLabel(pParse);
      addrTop = sqlite3VdbeAddOp2(v, OP_Rowid, iEph, regOldRowid);
      VdbeCoverage(v);
      sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid);
      VdbeCoverage(v);
    }
  }

  /* If the rowid value will change, set register regNewRowid to
  ** contain the new value. If the rowid is not being modified,
  ** then regNewRowid is the same register as regOldRowid, which is
  ** already populated.  */
  assert( chngKey || pTrigger || hasFK || regOldRowid==regNewRowid );
  if( chngRowid ){
    assert( iRowidExpr>=0 );
    if( nChangeFrom==0 ){
    sqlite3ExprCode(pParse, pRowidExpr, regNewRowid);
      sqlite3ExprCode(pParse, pRowidExpr, regNewRowid);
    }else{
      sqlite3VdbeAddOp3(v, OP_Column, iEph, iRowidExpr, regNewRowid);
    }
    sqlite3VdbeAddOp1(v, OP_MustBeInt, regNewRowid); VdbeCoverage(v);
  }

  /* Compute the old pre-UPDATE content of the row being changed, if that
  ** information is needed */
  if( chngPk || hasFK || pTrigger ){
    u32 oldmask = (hasFK ? sqlite3FkOldmask(pParse, pTab) : 0);
    oldmask |= sqlite3TriggerColmask(pParse, 
        pTrigger, pChanges, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onError
    );
    for(i=0; i<pTab->nCol; i++){
      u32 colFlags = pTab->aCol[i].colFlags;
      k = sqlite3TableColumnToStorage(pTab, i) + regOld;
      if( oldmask==0xffffffff
       || (i<32 && (oldmask & MASKBIT32(i))!=0)
       || (pTab->aCol[i].colFlags & COLFLAG_PRIMKEY)!=0
       || (colFlags & COLFLAG_PRIMKEY)!=0
      ){
        testcase(  oldmask!=0xffffffff && i==31 );
        sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regOld+i);
        sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, k);
      }else{
        sqlite3VdbeAddOp2(v, OP_Null, 0, regOld+i);
        sqlite3VdbeAddOp2(v, OP_Null, 0, k);
      }
    }
    if( chngRowid==0 && pPk==0 ){
      sqlite3VdbeAddOp2(v, OP_Copy, regOldRowid, regNewRowid);
    }
  }

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
936
937
938
939
940
941
942

943
944

945
946
947
948
949
950
951
952
953
954
955

956
957
958
959
960
961
962
963
964
965

966
967
968

969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989













990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003













1004
1005
1006
1007
1008
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







-
+

-
+
+
+



+
+
+
+
+
-
+
+








-
+
+

-
+



+
+
+
+
+
+
+









+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
-





+
+
+
+
+
+
+
+
+
+
+
+







-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+

-







  ** the database after the BEFORE triggers are fired anyway (as the trigger 
  ** may have modified them). So not loading those that are not going to
  ** be used eliminates some redundant opcodes.
  */
  newmask = sqlite3TriggerColmask(
      pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError
  );
  for(i=0; i<pTab->nCol; i++){
  for(i=0, k=regNew; i<pTab->nCol; i++, k++){
    if( i==pTab->iPKey ){
      sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
      sqlite3VdbeAddOp2(v, OP_Null, 0, k);
    }else if( (pTab->aCol[i].colFlags & COLFLAG_GENERATED)!=0 ){
      if( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ) k--;
    }else{
      j = aXRef[i];
      if( j>=0 ){
        if( nChangeFrom ){
          int nOff = (isView ? pTab->nCol : nPk);
          assert( eOnePass==ONEPASS_OFF );
          sqlite3VdbeAddOp3(v, OP_Column, iEph, nOff+j, k);
        }else{
        sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i);
          sqlite3ExprCode(pParse, pChanges->a[j].pExpr, k);
        }
      }else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask & MASKBIT32(i)) ){
        /* This branch loads the value of a column that will not be changed 
        ** into a register. This is done if there are no BEFORE triggers, or
        ** if there are one or more BEFORE triggers that use this value via
        ** a new.* reference in a trigger program.
        */
        testcase( i==31 );
        testcase( i==32 );
        sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i);
        sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, k);
        bFinishSeek = 0;
      }else{
        sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
        sqlite3VdbeAddOp2(v, OP_Null, 0, k);
      }
    }
  }
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
  if( pTab->tabFlags & TF_HasGenerated ){
    testcase( pTab->tabFlags & TF_HasVirtual );
    testcase( pTab->tabFlags & TF_HasStored );
    sqlite3ComputeGeneratedColumns(pParse, regNew, pTab);
  }
#endif

  /* Fire any BEFORE UPDATE triggers. This happens before constraints are
  ** verified. One could argue that this is wrong.
  */
  if( tmask&TRIGGER_BEFORE ){
    sqlite3TableAffinity(v, pTab, regNew);
    sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, 
        TRIGGER_BEFORE, pTab, regOldRowid, onError, labelContinue);

    if( !isView ){
    /* The row-trigger may have deleted the row being updated. In this
    ** case, jump to the next row. No updates or AFTER triggers are 
    ** required. This behavior - what happens when the row being updated
    ** is deleted or renamed by a BEFORE trigger - is left undefined in the
    ** documentation.
    */
    if( pPk ){
      sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue,regKey,nKey);
      VdbeCoverage(v);
    }else{
      sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid);
      VdbeCoverage(v);
    }
      /* The row-trigger may have deleted the row being updated. In this
      ** case, jump to the next row. No updates or AFTER triggers are 
      ** required. This behavior - what happens when the row being updated
      ** is deleted or renamed by a BEFORE trigger - is left undefined in the
      ** documentation.
      */
      if( pPk ){
        sqlite3VdbeAddOp4Int(v, OP_NotFound,iDataCur,labelContinue,regKey,nKey);
        VdbeCoverage(v);
      }else{
        sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue,regOldRowid);
        VdbeCoverage(v);
      }

    /* After-BEFORE-trigger-reload-loop:
    ** If it did not delete it, the BEFORE trigger may still have modified 
    ** some of the columns of the row being updated. Load the values for 
    ** all columns not modified by the update statement into their registers
    ** in case this has happened. Only unmodified columns are reloaded.
    ** The values computed for modified columns use the values before the
    ** BEFORE trigger runs.  See test case trigger1-18.0 (added 2018-04-26)
    ** for an example.
    */
    for(i=0; i<pTab->nCol; i++){
      if( aXRef[i]<0 && i!=pTab->iPKey ){
        sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i);
      }
      /* After-BEFORE-trigger-reload-loop:
      ** If it did not delete it, the BEFORE trigger may still have modified 
      ** some of the columns of the row being updated. Load the values for 
      ** all columns not modified by the update statement into their registers
      ** in case this has happened. Only unmodified columns are reloaded.
      ** The values computed for modified columns use the values before the
      ** BEFORE trigger runs.  See test case trigger1-18.0 (added 2018-04-26)
      ** for an example.
      */
      for(i=0, k=regNew; i<pTab->nCol; i++, k++){
        if( pTab->aCol[i].colFlags & COLFLAG_GENERATED ){
          if( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ) k--;
        }else if( aXRef[i]<0 && i!=pTab->iPKey ){
          sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, k);
        }
      }
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
      if( pTab->tabFlags & TF_HasGenerated ){
        testcase( pTab->tabFlags & TF_HasVirtual );
        testcase( pTab->tabFlags & TF_HasStored );
        sqlite3ComputeGeneratedColumns(pParse, regNew, pTab);
      }
#endif 
    }
  }

  if( !isView ){
    int addr1 = 0;        /* Address of jump instruction */

    /* Do constraint checks. */
    assert( regOldRowid>0 );
    sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur,
        regNewRowid, regOldRowid, chngKey, onError, labelContinue, &bReplace,
        aXRef, 0);

    /* If REPLACE conflict handling may have been used, or if the PK of the
    ** row is changing, then the GenerateConstraintChecks() above may have
    ** moved cursor iDataCur. Reseek it. */
    if( bReplace || chngKey ){
      if( pPk ){
        sqlite3VdbeAddOp4Int(v, OP_NotFound,iDataCur,labelContinue,regKey,nKey);
      }else{
        sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue,regOldRowid);
      }
      VdbeCoverage(v);
    }

    /* Do FK constraint checks. */
    if( hasFK ){
      sqlite3FkCheck(pParse, pTab, regOldRowid, 0, aXRef, chngKey);
    }

    /* Delete the index entries associated with the current record.  */
    if( bReplace || chngKey ){
      if( pPk ){
        addr1 = sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, 0, regKey, nKey);
      }else{
        addr1 = sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, 0, regOldRowid);
      }
      VdbeCoverageNeverTaken(v);
    sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx, -1);

    /* We must run the OP_FinishSeek opcode to resolve a prior
    ** OP_DeferredSeek if there is any possibility that there have been
    ** no OP_Column opcodes since the OP_DeferredSeek was issued.  But
    ** we want to avoid the OP_FinishSeek if possible, as running it
    ** costs CPU cycles. */
    if( bFinishSeek ){
      sqlite3VdbeAddOp1(v, OP_FinishSeek, iDataCur);
    }
    sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx, -1);

    /* If changing the rowid value, or if there are foreign key constraints
    ** to process, delete the old record. Otherwise, add a noop OP_Delete
    ** to invoke the pre-update hook.
    **
    ** That (regNew==regnewRowid+1) is true is also important for the 
    ** pre-update hook. If the caller invokes preupdate_new(), the returned
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
1086
1087
1088
1089
1090
1091
1092



1093
1094
1095
1096
1097
1098
1099







-
-
-







      sqlite3VdbeAppendP4(v, pTab, P4_TABLE);
    }
#else
    if( hasFK>1 || chngKey ){
      sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, 0);
    }
#endif
    if( bReplace || chngKey ){
      sqlite3VdbeJumpHere(v, addr1);
    }

    if( hasFK ){
      sqlite3FkCheck(pParse, pTab, 0, regNewRowid, aXRef, chngKey);
    }
  
    /* Insert the new index entries and the new record. */
    sqlite3CompleteInsertion(
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
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







-
+


-
-
















-
+
-
-







  ** all record selected by the WHERE clause have been updated.
  */
  if( eOnePass==ONEPASS_SINGLE ){
    /* Nothing to do at end-of-loop for a single-pass */
  }else if( eOnePass==ONEPASS_MULTI ){
    sqlite3VdbeResolveLabel(v, labelContinue);
    sqlite3WhereEnd(pWInfo);
  }else if( pPk ){
  }else{
    sqlite3VdbeResolveLabel(v, labelContinue);
    sqlite3VdbeAddOp2(v, OP_Next, iEph, addrTop); VdbeCoverage(v);
  }else{
    sqlite3VdbeGoto(v, labelContinue);
  }
  sqlite3VdbeResolveLabel(v, labelBreak);

  /* Update the sqlite_sequence table by storing the content of the
  ** maximum rowid counter values recorded while inserting into
  ** autoincrement tables.
  */
  if( pParse->nested==0 && pParse->pTriggerTab==0 && pUpsert==0 ){
    sqlite3AutoincrementEnd(pParse);
  }

  /*
  ** Return the number of rows that were changed, if we are tracking
  ** that information.
  */
  if( regRowCount ){
    sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1);
    sqlite3CodeChangeCount(v, regRowCount, "rows updated");
    sqlite3VdbeSetNumCols(v, 1);
    sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", SQLITE_STATIC);
  }

update_cleanup:
  sqlite3AuthContextPop(&sContext);
  sqlite3DbFree(db, aXRef); /* Also frees aRegIdx[] and aToOpen[] */
  sqlite3SrcListDelete(db, pTabList);
  sqlite3ExprListDelete(db, pChanges);
889
890
891
892
893
894
895
896

897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913






































914
915


916
917
918
919





920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946



























947
948

949
950
951


952
953
954
955
956
957
958
959
960
961
962
963
964
965
966














967
968
969



970
971
972
973
974

975


976
977
978
979
980
981
982
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
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
1318
1319
1320
1321
1322
1323


1324
1325
1326
1327
1328
1329
1330
1331
1332

1333
1334
1335
1336
1337
1338
1339
1340
1341







-
+

















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+

-
-
-
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+

-
-
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+
+





+
-
+
+







  int onError          /* ON CONFLICT strategy */
){
  Vdbe *v = pParse->pVdbe;  /* Virtual machine under construction */
  int ephemTab;             /* Table holding the result of the SELECT */
  int i;                    /* Loop counter */
  sqlite3 *db = pParse->db; /* Database connection */
  const char *pVTab = (const char*)sqlite3GetVTable(db, pTab);
  WhereInfo *pWInfo;
  WhereInfo *pWInfo = 0;
  int nArg = 2 + pTab->nCol;      /* Number of arguments to VUpdate */
  int regArg;                     /* First register in VUpdate arg array */
  int regRec;                     /* Register in which to assemble record */
  int regRowid;                   /* Register for ephem table rowid */
  int iCsr = pSrc->a[0].iCursor;  /* Cursor used for virtual table scan */
  int aDummy[2];                  /* Unused arg for sqlite3WhereOkOnePass() */
  int eOnePass;                   /* True to use onepass strategy */
  int addr;                       /* Address of OP_OpenEphemeral */

  /* Allocate nArg registers in which to gather the arguments for VUpdate. Then
  ** create and open the ephemeral table in which the records created from
  ** these arguments will be temporarily stored. */
  assert( v );
  ephemTab = pParse->nTab++;
  addr= sqlite3VdbeAddOp2(v, OP_OpenEphemeral, ephemTab, nArg);
  regArg = pParse->nMem + 1;
  pParse->nMem += nArg;
  if( pSrc->nSrc>1 ){
    Index *pPk = 0;
    Expr *pRow;
    ExprList *pList;
    if( HasRowid(pTab) ){
      if( pRowid ){
        pRow = sqlite3ExprDup(db, pRowid, 0);
      }else{
        pRow = sqlite3PExpr(pParse, TK_ROW, 0, 0);
      }
    }else{
      i16 iPk;      /* PRIMARY KEY column */
      pPk = sqlite3PrimaryKeyIndex(pTab);
      assert( pPk!=0 );
      assert( pPk->nKeyCol==1 );
      iPk = pPk->aiColumn[0];
      if( aXRef[iPk]>=0 ){
        pRow = sqlite3ExprDup(db, pChanges->a[aXRef[iPk]].pExpr, 0);
      }else{
        pRow = exprRowColumn(pParse, iPk);
      }
    }
    pList = sqlite3ExprListAppend(pParse, 0, pRow);

    for(i=0; i<pTab->nCol; i++){
      if( aXRef[i]>=0 ){
        pList = sqlite3ExprListAppend(pParse, pList,
          sqlite3ExprDup(db, pChanges->a[aXRef[i]].pExpr, 0)
        );
      }else{
        pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i));
      }
    }

    updateFromSelect(pParse, ephemTab, pPk, pList, pSrc, pWhere, 0, 0);
    sqlite3ExprListDelete(db, pList);
    eOnePass = ONEPASS_OFF;
  }else{
  regRec = ++pParse->nMem;
  regRowid = ++pParse->nMem;
    regRec = ++pParse->nMem;
    regRowid = ++pParse->nMem;

  /* Start scanning the virtual table */
  pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0,0,WHERE_ONEPASS_DESIRED,0);
  if( pWInfo==0 ) return;
    /* Start scanning the virtual table */
    pWInfo = sqlite3WhereBegin(
        pParse, pSrc, pWhere, 0, 0, 0, WHERE_ONEPASS_DESIRED, 0
    );
    if( pWInfo==0 ) return;

  /* Populate the argument registers. */
  for(i=0; i<pTab->nCol; i++){
    if( aXRef[i]>=0 ){
      sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i);
    }else{
      sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, i, regArg+2+i);
      sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG);/* Enable sqlite3_vtab_nochange() */
    }
  }
  if( HasRowid(pTab) ){
    sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg);
    if( pRowid ){
      sqlite3ExprCode(pParse, pRowid, regArg+1);
    }else{
      sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg+1);
    }
  }else{
    Index *pPk;   /* PRIMARY KEY index */
    i16 iPk;      /* PRIMARY KEY column */
    pPk = sqlite3PrimaryKeyIndex(pTab);
    assert( pPk!=0 );
    assert( pPk->nKeyCol==1 );
    iPk = pPk->aiColumn[0];
    sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, iPk, regArg);
    sqlite3VdbeAddOp2(v, OP_SCopy, regArg+2+iPk, regArg+1);
  }
    /* Populate the argument registers. */
    for(i=0; i<pTab->nCol; i++){
      assert( (pTab->aCol[i].colFlags & COLFLAG_GENERATED)==0 );
      if( aXRef[i]>=0 ){
        sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i);
      }else{
        sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, i, regArg+2+i);
        sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG);/* For sqlite3_vtab_nochange() */
      }
    }
    if( HasRowid(pTab) ){
      sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg);
      if( pRowid ){
        sqlite3ExprCode(pParse, pRowid, regArg+1);
      }else{
        sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg+1);
      }
    }else{
      Index *pPk;   /* PRIMARY KEY index */
      i16 iPk;      /* PRIMARY KEY column */
      pPk = sqlite3PrimaryKeyIndex(pTab);
      assert( pPk!=0 );
      assert( pPk->nKeyCol==1 );
      iPk = pPk->aiColumn[0];
      sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, iPk, regArg);
      sqlite3VdbeAddOp2(v, OP_SCopy, regArg+2+iPk, regArg+1);
    }

  eOnePass = sqlite3WhereOkOnePass(pWInfo, aDummy);
    eOnePass = sqlite3WhereOkOnePass(pWInfo, aDummy);

  /* There is no ONEPASS_MULTI on virtual tables */
  assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE );
    /* There is no ONEPASS_MULTI on virtual tables */
    assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE );

  if( eOnePass ){
    /* If using the onepass strategy, no-op out the OP_OpenEphemeral coded
    ** above. */
    sqlite3VdbeChangeToNoop(v, addr);
    sqlite3VdbeAddOp1(v, OP_Close, iCsr);
  }else{
    /* Create a record from the argument register contents and insert it into
    ** the ephemeral table. */
    sqlite3MultiWrite(pParse);
    sqlite3VdbeAddOp3(v, OP_MakeRecord, regArg, nArg, regRec);
#ifdef SQLITE_DEBUG
    /* Signal an assert() within OP_MakeRecord that it is allowed to
    ** accept no-change records with serial_type 10 */
    sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG_MAGIC);
    if( eOnePass ){
      /* If using the onepass strategy, no-op out the OP_OpenEphemeral coded
      ** above. */
      sqlite3VdbeChangeToNoop(v, addr);
      sqlite3VdbeAddOp1(v, OP_Close, iCsr);
    }else{
      /* Create a record from the argument register contents and insert it into
      ** the ephemeral table. */
      sqlite3MultiWrite(pParse);
      sqlite3VdbeAddOp3(v, OP_MakeRecord, regArg, nArg, regRec);
#if defined(SQLITE_DEBUG) && !defined(SQLITE_ENABLE_NULL_TRIM)
      /* Signal an assert() within OP_MakeRecord that it is allowed to
      ** accept no-change records with serial_type 10 */
      sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG_MAGIC);
#endif
    sqlite3VdbeAddOp2(v, OP_NewRowid, ephemTab, regRowid);
    sqlite3VdbeAddOp3(v, OP_Insert, ephemTab, regRec, regRowid);
      sqlite3VdbeAddOp2(v, OP_NewRowid, ephemTab, regRowid);
      sqlite3VdbeAddOp3(v, OP_Insert, ephemTab, regRec, regRowid);
    }
  }


  if( eOnePass==ONEPASS_OFF ){
    /* End the virtual table scan */
    if( pSrc->nSrc==1 ){
    sqlite3WhereEnd(pWInfo);
      sqlite3WhereEnd(pWInfo);
    }

    /* Begin scannning through the ephemeral table. */
    addr = sqlite3VdbeAddOp1(v, OP_Rewind, ephemTab); VdbeCoverage(v);

    /* Extract arguments from the current row of the ephemeral table and 
    ** invoke the VUpdate method.  */
    for(i=0; i<nArg; i++){

Changes to src/upsert.c.

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
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







-
-
+
+
+




+

+
+
-
+
+
+

+










-
+
+











-
+
+


-
+





+






+
-
+







*/
#include "sqliteInt.h"

#ifndef SQLITE_OMIT_UPSERT
/*
** Free a list of Upsert objects
*/
void sqlite3UpsertDelete(sqlite3 *db, Upsert *p){
  if( p ){
static void SQLITE_NOINLINE upsertDelete(sqlite3 *db, Upsert *p){
  do{
    Upsert *pNext = p->pNextUpsert;
    sqlite3ExprListDelete(db, p->pUpsertTarget);
    sqlite3ExprDelete(db, p->pUpsertTargetWhere);
    sqlite3ExprListDelete(db, p->pUpsertSet);
    sqlite3ExprDelete(db, p->pUpsertWhere);
    sqlite3DbFree(db, p->pToFree);
    sqlite3DbFree(db, p);
    p = pNext;
  }while( p );
  }
}
void sqlite3UpsertDelete(sqlite3 *db, Upsert *p){
  if( p ) upsertDelete(db, p);
}


/*
** Duplicate an Upsert object.
*/
Upsert *sqlite3UpsertDup(sqlite3 *db, Upsert *p){
  if( p==0 ) return 0;
  return sqlite3UpsertNew(db,
           sqlite3ExprListDup(db, p->pUpsertTarget, 0),
           sqlite3ExprDup(db, p->pUpsertTargetWhere, 0),
           sqlite3ExprListDup(db, p->pUpsertSet, 0),
           sqlite3ExprDup(db, p->pUpsertWhere, 0)
           sqlite3ExprDup(db, p->pUpsertWhere, 0),
           sqlite3UpsertDup(db, p->pNextUpsert)
         );
}

/*
** Create a new Upsert object.
*/
Upsert *sqlite3UpsertNew(
  sqlite3 *db,           /* Determines which memory allocator to use */
  ExprList *pTarget,     /* Target argument to ON CONFLICT, or NULL */
  Expr *pTargetWhere,    /* Optional WHERE clause on the target */
  ExprList *pSet,        /* UPDATE columns, or NULL for a DO NOTHING */
  Expr *pWhere           /* WHERE clause for the ON CONFLICT UPDATE */
  Expr *pWhere,          /* WHERE clause for the ON CONFLICT UPDATE */
  Upsert *pNext          /* Next ON CONFLICT clause in the list */
){
  Upsert *pNew;
  pNew = sqlite3DbMallocRaw(db, sizeof(Upsert));
  pNew = sqlite3DbMallocZero(db, sizeof(Upsert));
  if( pNew==0 ){
    sqlite3ExprListDelete(db, pTarget);
    sqlite3ExprDelete(db, pTargetWhere);
    sqlite3ExprListDelete(db, pSet);
    sqlite3ExprDelete(db, pWhere);
    sqlite3UpsertDelete(db, pNext);
    return 0;
  }else{
    pNew->pUpsertTarget = pTarget;
    pNew->pUpsertTargetWhere = pTargetWhere;
    pNew->pUpsertSet = pSet;
    pNew->pUpsertWhere = pWhere;
    pNew->isDoUpdate = pSet!=0;
    pNew->pUpsertIdx = 0;
    pNew->pNextUpsert = pNext;
  }
  return pNew;
}

/*
** Analyze the ON CONFLICT clause described by pUpsert.  Resolve all
** symbols in the conflict-target.
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
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







+













+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  int rc;                 /* Result code */
  int iCursor;            /* Cursor used by pTab */
  Index *pIdx;            /* One of the indexes of pTab */
  ExprList *pTarget;      /* The conflict-target clause */
  Expr *pTerm;            /* One term of the conflict-target clause */
  NameContext sNC;        /* Context for resolving symbolic names */
  Expr sCol[2];           /* Index column converted into an Expr */
  int nClause = 0;        /* Counter of ON CONFLICT clauses */

  assert( pTabList->nSrc==1 );
  assert( pTabList->a[0].pTab!=0 );
  assert( pUpsert!=0 );
  assert( pUpsert->pUpsertTarget!=0 );

  /* Resolve all symbolic names in the conflict-target clause, which
  ** includes both the list of columns and the optional partial-index
  ** WHERE clause.
  */
  memset(&sNC, 0, sizeof(sNC));
  sNC.pParse = pParse;
  sNC.pSrcList = pTabList;
  for(; pUpsert && pUpsert->pUpsertTarget;
        pUpsert=pUpsert->pNextUpsert, nClause++){
  rc = sqlite3ResolveExprListNames(&sNC, pUpsert->pUpsertTarget);
  if( rc ) return rc;
  rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertTargetWhere);
  if( rc ) return rc;

  /* Check to see if the conflict target matches the rowid. */  
  pTab = pTabList->a[0].pTab;
  pTarget = pUpsert->pUpsertTarget;
  iCursor = pTabList->a[0].iCursor;
  if( HasRowid(pTab) 
   && pTarget->nExpr==1
   && (pTerm = pTarget->a[0].pExpr)->op==TK_COLUMN
   && pTerm->iColumn==XN_ROWID
  ){
    /* The conflict-target is the rowid of the primary table */
    assert( pUpsert->pUpsertIdx==0 );
    rc = sqlite3ResolveExprListNames(&sNC, pUpsert->pUpsertTarget);
    if( rc ) return rc;
    rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertTargetWhere);
    if( rc ) return rc;
  
    /* Check to see if the conflict target matches the rowid. */  
    pTab = pTabList->a[0].pTab;
    pTarget = pUpsert->pUpsertTarget;
    iCursor = pTabList->a[0].iCursor;
    if( HasRowid(pTab) 
     && pTarget->nExpr==1
     && (pTerm = pTarget->a[0].pExpr)->op==TK_COLUMN
     && pTerm->iColumn==XN_ROWID
    ){
      /* The conflict-target is the rowid of the primary table */
      assert( pUpsert->pUpsertIdx==0 );
    return SQLITE_OK;
  }

  /* Initialize sCol[0..1] to be an expression parse tree for a
  ** single column of an index.  The sCol[0] node will be the TK_COLLATE
  ** operator and sCol[1] will be the TK_COLUMN operator.  Code below
  ** will populate the specific collation and column number values
  ** prior to comparing against the conflict-target expression.
  */
  memset(sCol, 0, sizeof(sCol));
  sCol[0].op = TK_COLLATE;
  sCol[0].pLeft = &sCol[1];
  sCol[1].op = TK_COLUMN;
  sCol[1].iTable = pTabList->a[0].iCursor;

  /* Check for matches against other indexes */
  for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
    int ii, jj, nn;
    if( !IsUniqueIndex(pIdx) ) continue;
    if( pTarget->nExpr!=pIdx->nKeyCol ) continue;
    if( pIdx->pPartIdxWhere ){
      if( pUpsert->pUpsertTargetWhere==0 ) continue;
      if( sqlite3ExprCompare(pParse, pUpsert->pUpsertTargetWhere,
                             pIdx->pPartIdxWhere, iCursor)!=0 ){
        continue;
      }
    }
    nn = pIdx->nKeyCol;
    for(ii=0; ii<nn; ii++){
      Expr *pExpr;
      sCol[0].u.zToken = (char*)pIdx->azColl[ii];
      if( pIdx->aiColumn[ii]==XN_EXPR ){
        assert( pIdx->aColExpr!=0 );
        assert( pIdx->aColExpr->nExpr>ii );
        pExpr = pIdx->aColExpr->a[ii].pExpr;
        if( pExpr->op!=TK_COLLATE ){
          sCol[0].pLeft = pExpr;
          pExpr = &sCol[0];
        }
      }else{
        sCol[0].pLeft = &sCol[1];
        sCol[1].iColumn = pIdx->aiColumn[ii];
        pExpr = &sCol[0];
      }
      for(jj=0; jj<nn; jj++){
        if( sqlite3ExprCompare(pParse, pTarget->a[jj].pExpr, pExpr,iCursor)<2 ){
          break;  /* Column ii of the index matches column jj of target */
        }
      }
      if( jj>=nn ){
        /* The target contains no match for column jj of the index */
        break;
      }
    }
    if( ii<nn ){
      /* Column ii of the index did not match any term of the conflict target.
      ** Continue the search with the next index. */
      continue;
    }
    pUpsert->pUpsertIdx = pIdx;
    return SQLITE_OK;
  }
  sqlite3ErrorMsg(pParse, "ON CONFLICT clause does not match any "
                          "PRIMARY KEY or UNIQUE constraint");
  return SQLITE_ERROR;
      continue;
    }
  
    /* Initialize sCol[0..1] to be an expression parse tree for a
    ** single column of an index.  The sCol[0] node will be the TK_COLLATE
    ** operator and sCol[1] will be the TK_COLUMN operator.  Code below
    ** will populate the specific collation and column number values
    ** prior to comparing against the conflict-target expression.
    */
    memset(sCol, 0, sizeof(sCol));
    sCol[0].op = TK_COLLATE;
    sCol[0].pLeft = &sCol[1];
    sCol[1].op = TK_COLUMN;
    sCol[1].iTable = pTabList->a[0].iCursor;
  
    /* Check for matches against other indexes */
    for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
      int ii, jj, nn;
      if( !IsUniqueIndex(pIdx) ) continue;
      if( pTarget->nExpr!=pIdx->nKeyCol ) continue;
      if( pIdx->pPartIdxWhere ){
        if( pUpsert->pUpsertTargetWhere==0 ) continue;
        if( sqlite3ExprCompare(pParse, pUpsert->pUpsertTargetWhere,
                               pIdx->pPartIdxWhere, iCursor)!=0 ){
          continue;
        }
      }
      nn = pIdx->nKeyCol;
      for(ii=0; ii<nn; ii++){
        Expr *pExpr;
        sCol[0].u.zToken = (char*)pIdx->azColl[ii];
        if( pIdx->aiColumn[ii]==XN_EXPR ){
          assert( pIdx->aColExpr!=0 );
          assert( pIdx->aColExpr->nExpr>ii );
          assert( pIdx->bHasExpr );
          pExpr = pIdx->aColExpr->a[ii].pExpr;
          if( pExpr->op!=TK_COLLATE ){
            sCol[0].pLeft = pExpr;
            pExpr = &sCol[0];
          }
        }else{
          sCol[0].pLeft = &sCol[1];
          sCol[1].iColumn = pIdx->aiColumn[ii];
          pExpr = &sCol[0];
        }
        for(jj=0; jj<nn; jj++){
          if( sqlite3ExprCompare(pParse,pTarget->a[jj].pExpr,pExpr,iCursor)<2 ){
            break;  /* Column ii of the index matches column jj of target */
          }
        }
        if( jj>=nn ){
          /* The target contains no match for column jj of the index */
          break;
        }
      }
      if( ii<nn ){
        /* Column ii of the index did not match any term of the conflict target.
        ** Continue the search with the next index. */
        continue;
      }
      pUpsert->pUpsertIdx = pIdx;
      break;
    }
    if( pUpsert->pUpsertIdx==0 ){
      char zWhich[16];
      if( nClause==0 && pUpsert->pNextUpsert==0 ){
        zWhich[0] = 0;
      }else{
        sqlite3_snprintf(sizeof(zWhich),zWhich,"%r ", nClause+1);
      }
      sqlite3ErrorMsg(pParse, "%sON CONFLICT clause does not match any "
                              "PRIMARY KEY or UNIQUE constraint", zWhich);
      return SQLITE_ERROR;
    }
  }
  return SQLITE_OK;
}

/*
** Return true if pUpsert is the last ON CONFLICT clause with a
** conflict target, or if pUpsert is followed by another ON CONFLICT
** clause that targets the INTEGER PRIMARY KEY.
*/
int sqlite3UpsertNextIsIPK(Upsert *pUpsert){
  Upsert *pNext;
  if( NEVER(pUpsert==0) ) return 0;
  pNext = pUpsert->pNextUpsert;
  if( pNext==0 ) return 1;
  if( pNext->pUpsertTarget==0 ) return 1;
  if( pNext->pUpsertIdx==0 ) return 1;
  return 0;
}

/*
** Given the list of ON CONFLICT clauses described by pUpsert, and
** a particular index pIdx, return a pointer to the particular ON CONFLICT
** clause that applies to the index.  Or, if the index is not subject to
** any ON CONFLICT clause, return NULL.
*/
Upsert *sqlite3UpsertOfIndex(Upsert *pUpsert, Index *pIdx){
  while(
      pUpsert
   && pUpsert->pUpsertTarget!=0
   && pUpsert->pUpsertIdx!=pIdx
  ){
     pUpsert = pUpsert->pNextUpsert;
  }
  return pUpsert;
}

/*
** Generate bytecode that does an UPDATE as part of an upsert.
**
** If pIdx is NULL, then the UNIQUE constraint that failed was the IPK.
** In this case parameter iCur is a cursor open on the table b-tree that
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
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







+
+



-

+
+











-




-
+


-
+






+



-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-




  Index *pIdx,          /* The UNIQUE constraint that failed */
  int iCur              /* Cursor for pIdx (or pTab if pIdx==NULL) */
){
  Vdbe *v = pParse->pVdbe;
  sqlite3 *db = pParse->db;
  SrcList *pSrc;            /* FROM clause for the UPDATE */
  int iDataCur;
  int i;
  Upsert *pTop = pUpsert;

  assert( v!=0 );
  assert( pUpsert!=0 );
  VdbeNoopComment((v, "Begin DO UPDATE of UPSERT"));
  iDataCur = pUpsert->iDataCur;
  pUpsert = sqlite3UpsertOfIndex(pTop, pIdx);
  VdbeNoopComment((v, "Begin DO UPDATE of UPSERT"));
  if( pIdx && iCur!=iDataCur ){
    if( HasRowid(pTab) ){
      int regRowid = sqlite3GetTempReg(pParse);
      sqlite3VdbeAddOp2(v, OP_IdxRowid, iCur, regRowid);
      sqlite3VdbeAddOp3(v, OP_SeekRowid, iDataCur, 0, regRowid);
      VdbeCoverage(v);
      sqlite3ReleaseTempReg(pParse, regRowid);
    }else{
      Index *pPk = sqlite3PrimaryKeyIndex(pTab);
      int nPk = pPk->nKeyCol;
      int iPk = pParse->nMem+1;
      int i;
      pParse->nMem += nPk;
      for(i=0; i<nPk; i++){
        int k;
        assert( pPk->aiColumn[i]>=0 );
        k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[i]);
        k = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[i]);
        sqlite3VdbeAddOp3(v, OP_Column, iCur, k, iPk+i);
        VdbeComment((v, "%s.%s", pIdx->zName,
                    pTab->aCol[pPk->aiColumn[i]].zName));
                    pTab->aCol[pPk->aiColumn[i]].zCnName));
      }
      sqlite3VdbeVerifyAbortable(v, OE_Abort);
      i = sqlite3VdbeAddOp4Int(v, OP_Found, iDataCur, 0, iPk, nPk);
      VdbeCoverage(v);
      sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CORRUPT, OE_Abort, 0, 
            "corrupt database", P4_STATIC);
      sqlite3MayAbort(pParse);
      sqlite3VdbeJumpHere(v, i);
    }
  }
  /* pUpsert does not own pUpsertSrc - the outer INSERT statement does.  So
  ** we have to make a copy before passing it down into sqlite3Update() */
  pSrc = sqlite3SrcListDup(db, pUpsert->pUpsertSrc, 0);
  sqlite3Update(pParse, pSrc, pUpsert->pUpsertSet,
      pUpsert->pUpsertWhere, OE_Abort, 0, 0, pUpsert);
  /* pUpsert does not own pTop->pUpsertSrc - the outer INSERT statement does.
  ** So we have to make a copy before passing it down into sqlite3Update() */
  pSrc = sqlite3SrcListDup(db, pTop->pUpsertSrc, 0);
  /* excluded.* columns of type REAL need to be converted to a hard real */
  for(i=0; i<pTab->nCol; i++){
    if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){
      sqlite3VdbeAddOp1(v, OP_RealAffinity, pTop->regData+i);
    }
  }
  sqlite3Update(pParse, pSrc, sqlite3ExprListDup(db,pUpsert->pUpsertSet,0),
      sqlite3ExprDup(db,pUpsert->pUpsertWhere,0), OE_Abort, 0, 0, pUpsert);
  pUpsert->pUpsertSet = 0;    /* Will have been deleted by sqlite3Update() */
  pUpsert->pUpsertWhere = 0;  /* Will have been deleted by sqlite3Update() */
  VdbeNoopComment((v, "End DO UPDATE of UPSERT"));
}

#endif /* SQLITE_OMIT_UPSERT */

Changes to src/utf.c.

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
101
102
103
104
105
106
107




















108
109
110
111
112
113
114







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







    *zOut++ = (u8)(0x00D8 + (((c-0x10000)>>18)&0x03));              \
    *zOut++ = (u8)(((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0));  \
    *zOut++ = (u8)(0x00DC + ((c>>8)&0x03));                         \
    *zOut++ = (u8)(c&0x00FF);                                       \
  }                                                                 \
}

#define READ_UTF16LE(zIn, TERM, c){                                   \
  c = (*zIn++);                                                       \
  c += ((*zIn++)<<8);                                                 \
  if( c>=0xD800 && c<0xE000 && TERM ){                                \
    int c2 = (*zIn++);                                                \
    c2 += ((*zIn++)<<8);                                              \
    c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10);   \
  }                                                                   \
}

#define READ_UTF16BE(zIn, TERM, c){                                   \
  c = ((*zIn++)<<8);                                                  \
  c += (*zIn++);                                                      \
  if( c>=0xD800 && c<0xE000 && TERM ){                                \
    int c2 = ((*zIn++)<<8);                                           \
    c2 += (*zIn++);                                                   \
    c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10);   \
  }                                                                   \
}

/*
** Translate a single UTF-8 character.  Return the unicode value.
**
** During translation, assume that the byte that zTerm points
** is a 0x00.
**
** Write a pointer to the next unread byte back into *pzNext.
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
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







-
-
-
-
-
+
+
+
+
+










+
-
-
-
+
+
+
+







#ifndef SQLITE_OMIT_UTF16
/*
** This routine transforms the internal text encoding used by pMem to
** desiredEnc. It is an error if the string is already of the desired
** encoding, or if *pMem does not contain a string value.
*/
SQLITE_NOINLINE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
  int len;                    /* Maximum length of output string in bytes */
  unsigned char *zOut;                  /* Output buffer */
  unsigned char *zIn;                   /* Input iterator */
  unsigned char *zTerm;                 /* End of input */
  unsigned char *z;                     /* Output iterator */
  sqlite3_int64 len;          /* Maximum length of output string in bytes */
  unsigned char *zOut;        /* Output buffer */
  unsigned char *zIn;         /* Input iterator */
  unsigned char *zTerm;       /* End of input */
  unsigned char *z;           /* Output iterator */
  unsigned int c;

  assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
  assert( pMem->flags&MEM_Str );
  assert( pMem->enc!=desiredEnc );
  assert( pMem->enc!=0 );
  assert( pMem->n>=0 );

#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG)
  {
    StrAccum acc;
    char zBuf[100];
    sqlite3VdbeMemPrettyPrint(pMem, zBuf);
    fprintf(stderr, "INPUT:  %s\n", zBuf);
    char zBuf[1000];
    sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);  
    sqlite3VdbeMemPrettyPrint(pMem, &acc);
    fprintf(stderr, "INPUT:  %s\n", sqlite3StrAccumFinish(&acc));
  }
#endif

  /* If the translation is between UTF-16 little and big endian, then 
  ** all that is required is to swap the byte order. This case is handled
  ** differently from the others.
  */
249
250
251
252
253
254
255
256

257
258
259
260
261
262
263

264
265
266
267
268
269
270
231
232
233
234
235
236
237

238
239
240
241
242
243
244

245
246
247
248
249
250
251
252







-
+






-
+







  if( desiredEnc==SQLITE_UTF8 ){
    /* When converting from UTF-16, the maximum growth results from
    ** translating a 2-byte character to a 4-byte UTF-8 character.
    ** A single byte is required for the output string
    ** nul-terminator.
    */
    pMem->n &= ~1;
    len = pMem->n * 2 + 1;
    len = 2 * (sqlite3_int64)pMem->n + 1;
  }else{
    /* When converting from UTF-8 to UTF-16 the maximum growth is caused
    ** when a 1-byte UTF-8 character is translated into a 2-byte UTF-16
    ** character. Two bytes are required in the output buffer for the
    ** nul-terminator.
    */
    len = pMem->n * 2 + 2;
    len = 2 * (sqlite3_int64)pMem->n + 2;
  }

  /* Set zIn to point at the start of the input buffer and zTerm to point 1
  ** byte past the end.
  **
  ** Variable zOut is set to point at the output buffer, space obtained
  ** from sqlite3_malloc().
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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+








-
+

-
+








+
-
-
-
+
+
+
+







    pMem->n = (int)(z - zOut);
    *z++ = 0;
  }else{
    assert( desiredEnc==SQLITE_UTF8 );
    if( pMem->enc==SQLITE_UTF16LE ){
      /* UTF-16 Little-endian -> UTF-8 */
      while( zIn<zTerm ){
        c = *(zIn++);
        c += (*(zIn++))<<8;
        if( c>=0xd800 && c<0xe000 ){
#ifdef SQLITE_REPLACE_INVALID_UTF
          if( c>=0xdc00 || zIn>=zTerm ){
            c = 0xfffd;
          }else{
            int c2 = *(zIn++);
            c2 += (*(zIn++))<<8;
            if( c2<0xdc00 || c2>=0xe000 ){
              zIn -= 2;
              c = 0xfffd;
            }else{
              c = ((c&0x3ff)<<10) + (c2&0x3ff) + 0x10000;
            }
          }
#else
        READ_UTF16LE(zIn, zIn<zTerm, c); 
          if( zIn<zTerm ){
            int c2 = (*zIn++);
            c2 += ((*zIn++)<<8);
            c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10);
          }
#endif
        }
        WRITE_UTF8(z, c);
      }
    }else{
      /* UTF-16 Big-endian -> UTF-8 */
      while( zIn<zTerm ){
        c = (*(zIn++))<<8;
        c += *(zIn++);
        if( c>=0xd800 && c<0xe000 ){
#ifdef SQLITE_REPLACE_INVALID_UTF
          if( c>=0xdc00 || zIn>=zTerm ){
            c = 0xfffd;
          }else{
            int c2 = (*(zIn++))<<8;
            c2 += *(zIn++);
            if( c2<0xdc00 || c2>=0xe000 ){
              zIn -= 2;
              c = 0xfffd;
            }else{
              c = ((c&0x3ff)<<10) + (c2&0x3ff) + 0x10000;
            }
          }
#else
        READ_UTF16BE(zIn, zIn<zTerm, c); 
          if( zIn<zTerm ){
            int c2 = ((*zIn++)<<8);
            c2 += (*zIn++);
            c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10);
          }
#endif
        }
        WRITE_UTF8(z, c);
      }
    }
    pMem->n = (int)(z - zOut);
  }
  *z = 0;
  assert( (pMem->n+(desiredEnc==SQLITE_UTF8?1:2))<=len );

  c = pMem->flags;
  c = MEM_Str|MEM_Term|(pMem->flags&(MEM_AffMask|MEM_Subtype));
  sqlite3VdbeMemRelease(pMem);
  pMem->flags = MEM_Str|MEM_Term|(c&(MEM_AffMask|MEM_Subtype));
  pMem->flags = c;
  pMem->enc = desiredEnc;
  pMem->z = (char*)zOut;
  pMem->zMalloc = pMem->z;
  pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->z);

translate_out:
#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG)
  {
    StrAccum acc;
    char zBuf[100];
    sqlite3VdbeMemPrettyPrint(pMem, zBuf);
    fprintf(stderr, "OUTPUT: %s\n", zBuf);
    char zBuf[1000];
    sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);  
    sqlite3VdbeMemPrettyPrint(pMem, &acc);
    fprintf(stderr, "OUTPUT: %s\n", sqlite3StrAccumFinish(&acc));
  }
#endif
  return SQLITE_OK;
}
#endif /* SQLITE_OMIT_UTF16 */

#ifndef SQLITE_OMIT_UTF16
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
488
489
490
491
492
493
494




495
496
497
498






499
500
501


502
503
504
505
506
507
508
509
510







-
-
-
-
+
+
+
+
-
-
-
-
-
-
+
+
+
-
-
+
+







** in pZ.  nChar must be non-negative.
*/
int sqlite3Utf16ByteLen(const void *zIn, int nChar){
  int c;
  unsigned char const *z = zIn;
  int n = 0;
  
  if( SQLITE_UTF16NATIVE==SQLITE_UTF16BE ){
    while( n<nChar ){
      READ_UTF16BE(z, 1, c);
      n++;
  if( SQLITE_UTF16NATIVE==SQLITE_UTF16LE ) z++;
  while( n<nChar ){
    c = z[0];
    z += 2;
    }
  }else{
    while( n<nChar ){
      READ_UTF16LE(z, 1, c);
      n++;
    }
    if( c>=0xd8 && c<0xdc && z[0]>=0xdc && z[0]<0xe0 ) z += 2;
    n++;
  }
  }
  return (int)(z-(unsigned char const *)zIn);
  return (int)(z-(unsigned char const *)zIn) 
              - (SQLITE_UTF16NATIVE==SQLITE_UTF16LE);
}

#if defined(SQLITE_TEST)
/*
** This routine is called from the TCL test function "translate_selftest".
** It checks that the primitives for serializing and deserializing
** characters in each encoding are inverses of each other.
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
524
525
526
527
528
529
530
























531
532
533
534
535







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-





    z[0] = 0;
    z = zBuf;
    c = sqlite3Utf8Read((const u8**)&z);
    t = i;
    if( i>=0xD800 && i<=0xDFFF ) t = 0xFFFD;
    if( (i&0xFFFFFFFE)==0xFFFE ) t = 0xFFFD;
    assert( c==t );
    assert( (z-zBuf)==n );
  }
  for(i=0; i<0x00110000; i++){
    if( i>=0xD800 && i<0xE000 ) continue;
    z = zBuf;
    WRITE_UTF16LE(z, i);
    n = (int)(z-zBuf);
    assert( n>0 && n<=4 );
    z[0] = 0;
    z = zBuf;
    READ_UTF16LE(z, 1, c);
    assert( c==i );
    assert( (z-zBuf)==n );
  }
  for(i=0; i<0x00110000; i++){
    if( i>=0xD800 && i<0xE000 ) continue;
    z = zBuf;
    WRITE_UTF16BE(z, i);
    n = (int)(z-zBuf);
    assert( n>0 && n<=4 );
    z[0] = 0;
    z = zBuf;
    READ_UTF16BE(z, 1, c);
    assert( c==i );
    assert( (z-zBuf)==n );
  }
}
#endif /* SQLITE_TEST */
#endif /* SQLITE_OMIT_UTF16 */

Changes to src/util.c.

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
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







-
-
+
+



-
-
+
+
+
+
-
-
+
-
-
-
-
-
+
-
-
-
-

+
+
+
-
-
+
+

-
+
-
+
+
+


















-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+







**
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
*/
#include "sqliteInt.h"
#include <stdarg.h>
#if HAVE_ISNAN || SQLITE_HAVE_ISNAN
# include <math.h>
#ifndef SQLITE_OMIT_FLOATING_POINT
#include <math.h>
#endif

/*
** Routine needed to support the testcase() macro.
*/
** Calls to sqlite3FaultSim() are used to simulate a failure during testing,
** or to bypass normal error detection during testing in order to let 
** execute proceed futher downstream.
**
#ifdef SQLITE_COVERAGE_TEST
void sqlite3Coverage(int x){
** In deployment, sqlite3FaultSim() *always* return SQLITE_OK (0).  The
  static unsigned dummy = 0;
  dummy += (unsigned)x;
}
#endif

** sqlite3FaultSim() function only returns non-zero during testing.
/*
** Give a callback to the test harness that can be used to simulate faults
** in places where it is difficult or expensive to do so purely by means
** of inputs.
**
** During testing, if the test harness has set a fault-sim callback using
** a call to sqlite3_test_control(SQLITE_TESTCTRL_FAULT_INSTALL), then
** each call to sqlite3FaultSim() is relayed to that application-supplied
** The intent of the integer argument is to let the fault simulator know
** which of multiple sqlite3FaultSim() calls has been hit.
** callback and the integer return value form the application-supplied
** callback is returned by sqlite3FaultSim().
**
** Return whatever integer value the test callback returns, or return
** The integer argument to sqlite3FaultSim() is a code to identify which
** SQLITE_OK if no test callback is installed.
** sqlite3FaultSim() instance is being invoked. Each call to sqlite3FaultSim()
** should have a unique code.  To prevent legacy testing applications from
** breaking, the codes should not be changed or reused.
*/
#ifndef SQLITE_UNTESTABLE
int sqlite3FaultSim(int iTest){
  int (*xCallback)(int) = sqlite3GlobalConfig.xTestCallback;
  return xCallback ? xCallback(iTest) : SQLITE_OK;
}
#endif

#ifndef SQLITE_OMIT_FLOATING_POINT
/*
** Return true if the floating point value is Not a Number (NaN).
**
** Use the math library isnan() function if compiled with SQLITE_HAVE_ISNAN.
** Otherwise, we have our own implementation that works on most systems.
*/
int sqlite3IsNaN(double x){
  int rc;   /* The value return */
#if !SQLITE_HAVE_ISNAN && !HAVE_ISNAN
  /*
  ** Systems that support the isnan() library function should probably
  ** make use of it by compiling with -DSQLITE_HAVE_ISNAN.  But we have
  ** found that many systems do not have a working isnan() function so
  ** this implementation is provided as an alternative.
  **
  ** This NaN test sometimes fails if compiled on GCC with -ffast-math.
  ** On the other hand, the use of -ffast-math comes with the following
  ** warning:
  u64 y;
  **
  **      This option [-ffast-math] should never be turned on by any
  **      -O option since it can result in incorrect output for programs
  **      which depend on an exact implementation of IEEE or ISO 
  **      rules/specifications for math functions.
  **
  ** Under MSVC, this NaN test may fail if compiled with a floating-
  ** point precision mode other than /fp:precise.  From the MSDN 
  ** documentation:
  memcpy(&y,&x,sizeof(y));
  **
  **      The compiler [with /fp:precise] will properly handle comparisons 
  **      involving NaN. For example, x != x evaluates to true if x is NaN 
  **      ...
  */
#ifdef __FAST_MATH__
# error SQLite will not work correctly with the -ffast-math option of GCC.
#endif
  volatile double y = x;
  volatile double z = y;
  rc = (y!=z);
#else  /* if HAVE_ISNAN */
  rc = IsNaN(y);
#else
  rc = isnan(x);
#endif /* HAVE_ISNAN */
  testcase( rc );
  return rc;
}
#endif /* SQLITE_OMIT_FLOATING_POINT */

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
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







-
-
+
+
+
+
+
+
+
+




















-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



















-
-
-
-
-
-
-
-
-
-
-
+
+






















-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+












+
+
+



+


+
+
+
+





+


+
+
+
+
+
+
+
+
+
+
+
+
+














-
+







** Return the declared type of a column.  Or return zDflt if the column 
** has no declared type.
**
** The column type is an extra string stored after the zero-terminator on
** the column name if and only if the COLFLAG_HASTYPE flag is set.
*/
char *sqlite3ColumnType(Column *pCol, char *zDflt){
  if( (pCol->colFlags & COLFLAG_HASTYPE)==0 ) return zDflt;
  return pCol->zName + strlen(pCol->zName) + 1;
  if( pCol->colFlags & COLFLAG_HASTYPE ){
    return pCol->zCnName + strlen(pCol->zCnName) + 1;
  }else if( pCol->eCType ){
    assert( pCol->eCType<=SQLITE_N_STDTYPE );
    return (char*)sqlite3StdType[pCol->eCType-1];
  }else{
    return zDflt;
  }
}

/*
** Helper function for sqlite3Error() - called rarely.  Broken out into
** a separate routine to avoid unnecessary register saves on entry to
** sqlite3Error().
*/
static SQLITE_NOINLINE void  sqlite3ErrorFinish(sqlite3 *db, int err_code){
  if( db->pErr ) sqlite3ValueSetNull(db->pErr);
  sqlite3SystemError(db, err_code);
}

/*
** Set the current error code to err_code and clear any prior error message.
** Also set iSysErrno (by calling sqlite3System) if the err_code indicates
** that would be appropriate.
*/
void sqlite3Error(sqlite3 *db, int err_code){
  assert( db!=0 );
  db->errCode = err_code;
  if( err_code || db->pErr ) sqlite3ErrorFinish(db, err_code);
  if( err_code || db->pErr ){
    sqlite3ErrorFinish(db, err_code);
  }else{
    db->errByteOffset = -1;
  }
}

/*
** The equivalent of sqlite3Error(db, SQLITE_OK).  Clear the error state
** and error message.
*/
void sqlite3ErrorClear(sqlite3 *db){
  assert( db!=0 );
  db->errCode = SQLITE_OK;
  db->errByteOffset = -1;
  if( db->pErr ) sqlite3ValueSetNull(db->pErr);
}

/*
** Load the sqlite3.iSysErrno field if that is an appropriate thing
** to do based on the SQLite error code in rc.
*/
void sqlite3SystemError(sqlite3 *db, int rc){
  if( rc==SQLITE_IOERR_NOMEM ) return;
  rc &= 0xff;
  if( rc==SQLITE_CANTOPEN || rc==SQLITE_IOERR ){
    db->iSysErrno = sqlite3OsGetLastError(db->pVfs);
  }
}

/*
** Set the most recent error code and error string for the sqlite
** handle "db". The error code is set to "err_code".
**
** If it is not NULL, string zFormat specifies the format of the
** error string in the style of the printf functions: The following
** format characters are allowed:
**
**      %s      Insert a string
**      %z      A string that should be freed after use
**      %d      Insert an integer
**      %T      Insert a token
**      %S      Insert the first element of a SrcList
**
** zFormat and any string tokens that follow it are assumed to be
** encoded in UTF-8.
** error string.  zFormat and any string tokens that follow it are
** assumed to be encoded in UTF-8.
**
** To clear the most recent error for sqlite handle "db", sqlite3Error
** should be called with err_code set to SQLITE_OK and zFormat set
** to NULL.
*/
void sqlite3ErrorWithMsg(sqlite3 *db, int err_code, const char *zFormat, ...){
  assert( db!=0 );
  db->errCode = err_code;
  sqlite3SystemError(db, err_code);
  if( zFormat==0 ){
    sqlite3Error(db, err_code);
  }else if( db->pErr || (db->pErr = sqlite3ValueNew(db))!=0 ){
    char *z;
    va_list ap;
    va_start(ap, zFormat);
    z = sqlite3VMPrintf(db, zFormat, ap);
    va_end(ap);
    sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, SQLITE_DYNAMIC);
  }
}

/*
** Add an error message to pParse->zErrMsg and increment pParse->nErr.
** Check for interrupts and invoke progress callback.
** The following formatting characters are allowed:
**
**      %s      Insert a string
**      %z      A string that should be freed after use
**      %d      Insert an integer
**      %T      Insert a token
**      %S      Insert the first element of a SrcList
*/
void sqlite3ProgressCheck(Parse *p){
  sqlite3 *db = p->db;
  if( AtomicLoad(&db->u1.isInterrupted) ){
    p->nErr++;
    p->rc = SQLITE_INTERRUPT;
  }
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  if( db->xProgress && (++p->nProgressSteps)>=db->nProgressOps ){
    if( db->xProgress(db->pProgressArg) ){
      p->nErr++;
      p->rc = SQLITE_INTERRUPT;
    }
    p->nProgressSteps = 0;
  }
#endif
}

/*
** Add an error message to pParse->zErrMsg and increment pParse->nErr.
**
** This function should be used to report any error that occurs while
** compiling an SQL statement (i.e. within sqlite3_prepare()). The
** last thing the sqlite3_prepare() function does is copy the error
** stored by this function into the database handle using sqlite3Error().
** Functions sqlite3Error() or sqlite3ErrorWithMsg() should be used
** during statement execution (sqlite3_step() etc.).
*/
void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){
  char *zMsg;
  va_list ap;
  sqlite3 *db = pParse->db;
  assert( db!=0 );
  assert( db->pParse==pParse || db->pParse->pToplevel==pParse );
  db->errByteOffset = -2;
  va_start(ap, zFormat);
  zMsg = sqlite3VMPrintf(db, zFormat, ap);
  va_end(ap);
  if( db->errByteOffset<-1 ) db->errByteOffset = -1;
  if( db->suppressErr ){
    sqlite3DbFree(db, zMsg);
    if( db->mallocFailed ){
      pParse->nErr++;
      pParse->rc = SQLITE_NOMEM;
    }
  }else{
    pParse->nErr++;
    sqlite3DbFree(db, pParse->zErrMsg);
    pParse->zErrMsg = zMsg;
    pParse->rc = SQLITE_ERROR;
    pParse->pWith = 0;
  }
}

/*
** If database connection db is currently parsing SQL, then transfer
** error code errCode to that parser if the parser has not already
** encountered some other kind of error.
*/
int sqlite3ErrorToParser(sqlite3 *db, int errCode){
  Parse *pParse;
  if( db==0 || (pParse = db->pParse)==0 ) return errCode;
  pParse->rc = errCode;
  pParse->nErr++;
  return errCode;
}

/*
** Convert an SQL-style quoted string into a normal string by removing
** the quote characters.  The conversion is done in-place.  If the
** input does not begin with a quote character, then this routine
** is a no-op.
**
** The input string must be zero-terminated.  A new zero-terminator
** is added to the dequoted string.
**
** The return value is -1 if no dequoting occurs or the length of the
** dequoted string, exclusive of the zero terminator, if dequoting does
** occur.
**
** 2002-Feb-14: This routine is extended to remove MS-Access style
** 2002-02-14: This routine is extended to remove MS-Access style
** brackets from around identifiers.  For example:  "[a-b-c]" becomes
** "a-b-c".
*/
void sqlite3Dequote(char *z){
  char quote;
  int i, j;
  if( z==0 ) return;
259
260
261
262
263
264
265




























266
267
268
269
270
271
272
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







        break;
      }
    }else{
      z[j++] = z[i];
    }
  }
  z[j] = 0;
}
void sqlite3DequoteExpr(Expr *p){
  assert( !ExprHasProperty(p, EP_IntValue) );
  assert( sqlite3Isquote(p->u.zToken[0]) );
  p->flags |= p->u.zToken[0]=='"' ? EP_Quoted|EP_DblQuoted : EP_Quoted;
  sqlite3Dequote(p->u.zToken);
}

/*
** If the input token p is quoted, try to adjust the token to remove
** the quotes.  This is not always possible:
**
**     "abc"     ->   abc
**     "ab""cd"  ->   (not possible because of the interior "")
**
** Remove the quotes if possible.  This is a optimization.  The overall
** system should still return the correct answer even if this routine
** is always a no-op.
*/
void sqlite3DequoteToken(Token *p){
  unsigned int i;
  if( p->n<2 ) return;
  if( !sqlite3Isquote(p->z[0]) ) return;
  for(i=1; i<p->n-1; i++){
    if( sqlite3Isquote(p->z[i]) ) return;
  }
  p->n -= 2;
  p->z++;
}

/*
** Generate a Token object from a string
*/
void sqlite3TokenInit(Token *p, char *z){
  p->z = z;
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
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







-
+



+
+
+
+
+
-
-
+
+
+

















+
+
+
+
+
+
+
+
+
+
+
+
+










-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+







  }else if( zRight==0 ){
    return 1;
  }
  return sqlite3StrICmp(zLeft, zRight);
}
int sqlite3StrICmp(const char *zLeft, const char *zRight){
  unsigned char *a, *b;
  int c;
  int c, x;
  a = (unsigned char *)zLeft;
  b = (unsigned char *)zRight;
  for(;;){
    c = *a;
    x = *b;
    if( c==x ){
      if( c==0 ) break;
    }else{
    c = (int)UpperToLower[*a] - (int)UpperToLower[*b];
    if( c || *a==0 ) break;
      c = (int)UpperToLower[c] - (int)UpperToLower[x];
      if( c ) break;
    }
    a++;
    b++;
  }
  return c;
}
int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){
  register unsigned char *a, *b;
  if( zLeft==0 ){
    return zRight ? -1 : 0;
  }else if( zRight==0 ){
    return 1;
  }
  a = (unsigned char *)zLeft;
  b = (unsigned char *)zRight;
  while( N-- > 0 && *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
  return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b];
}

/*
** Compute an 8-bit hash on a string that is insensitive to case differences
*/
u8 sqlite3StrIHash(const char *z){
  u8 h = 0;
  if( z==0 ) return 0;
  while( z[0] ){
    h += UpperToLower[(unsigned char)z[0]];
    z++;
  }
  return h;
}

/*
** Compute 10 to the E-th power.  Examples:  E==1 results in 10.
** E==2 results in 100.  E==50 results in 1.0e50.
**
** This routine only works for values of E between 1 and 341.
*/
static LONGDOUBLE_TYPE sqlite3Pow10(int E){
#if defined(_MSC_VER)
  static const LONGDOUBLE_TYPE x[] = {
    1.0e+001,
    1.0e+002,
    1.0e+004,
    1.0e+008,
    1.0e+016,
    1.0e+032,
    1.0e+064,
    1.0e+128,
    1.0e+256
    1.0e+001L,
    1.0e+002L,
    1.0e+004L,
    1.0e+008L,
    1.0e+016L,
    1.0e+032L,
    1.0e+064L,
    1.0e+128L,
    1.0e+256L
  };
  LONGDOUBLE_TYPE r = 1.0;
  int i;
  assert( E>=0 && E<=307 );
  for(i=0; E!=0; i++, E >>=1){
    if( E & 1 ) r *= x[i];
  }
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
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







-
-
+
+
+
+
+
+
+
+
+












+
+
+



-
+








-
-
+
+



+



+



+

+
+

-
+

















-
+

-
+
-
-
-
-
-
+
+
+
+
+
+





+






+

-
+








+







** The string z[] is an text representation of a real number.
** Convert this string to a double and write it into *pResult.
**
** The string z[] is length bytes in length (bytes, not characters) and
** uses the encoding enc.  The string is not necessarily zero-terminated.
**
** Return TRUE if the result is a valid real number (or integer) and FALSE
** if the string is empty or contains extraneous text.  Valid numbers
** are in one of these formats:
** if the string is empty or contains extraneous text.  More specifically
** return
**      1          =>  The input string is a pure integer
**      2 or more  =>  The input has a decimal point or eNNN clause
**      0 or less  =>  The input string is not a valid number
**     -1          =>  Not a valid number, but has a valid prefix which 
**                     includes a decimal point and/or an eNNN clause
**
** Valid numbers are in one of these formats:
**
**    [+-]digits[E[+-]digits]
**    [+-]digits.[digits][E[+-]digits]
**    [+-].digits[E[+-]digits]
**
** Leading and trailing whitespace is ignored for the purpose of determining
** validity.
**
** If some prefix of the input string is a valid number, this routine
** returns FALSE but it still converts the prefix and writes the result
** into *pResult.
*/
#if defined(_MSC_VER)
#pragma warning(disable : 4756)
#endif
int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
#ifndef SQLITE_OMIT_FLOATING_POINT
  int incr;
  const char *zEnd = z + length;
  const char *zEnd;
  /* sign * significand * (10 ^ (esign * exponent)) */
  int sign = 1;    /* sign of significand */
  i64 s = 0;       /* significand */
  int d = 0;       /* adjust exponent for shifting decimal point */
  int esign = 1;   /* sign of exponent */
  int e = 0;       /* exponent */
  int eValid = 1;  /* True exponent is either not used or is well-formed */
  double result;
  int nDigits = 0;
  int nonNum = 0;  /* True if input contains UTF16 with high byte non-zero */
  int nDigit = 0;  /* Number of digits processed */
  int eType = 1;   /* 1: pure integer,  2+: fractional  -1 or less: bad UTF16 */

  assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
  *pResult = 0.0;   /* Default return value, in case of an error */
  if( length==0 ) return 0;

  if( enc==SQLITE_UTF8 ){
    incr = 1;
    zEnd = z + length;
  }else{
    int i;
    incr = 2;
    length &= ~1;
    assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
    testcase( enc==SQLITE_UTF16LE );
    testcase( enc==SQLITE_UTF16BE );
    for(i=3-enc; i<length && z[i]==0; i+=2){}
    nonNum = i<length;
    if( i<length ) eType = -100;
    zEnd = &z[i^1];
    z += (enc&1);
  }

  /* skip leading spaces */
  while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
  if( z>=zEnd ) return 0;

  /* get sign of significand */
  if( *z=='-' ){
    sign = -1;
    z+=incr;
  }else if( *z=='+' ){
    z+=incr;
  }

  /* copy max significant digits to significand */
  while( z<zEnd && sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){
  while( z<zEnd && sqlite3Isdigit(*z) ){
    s = s*10 + (*z - '0');
    z+=incr; nDigits++;
    z+=incr; nDigit++;
  }

  /* skip non-significant significand digits
  ** (increase exponent by d to shift decimal left) */
  while( z<zEnd && sqlite3Isdigit(*z) ){ z+=incr; nDigits++; d++; }
    if( s>=((LARGEST_INT64-9)/10) ){
      /* skip non-significant significand digits
      ** (increase exponent by d to shift decimal left) */
      while( z<zEnd && sqlite3Isdigit(*z) ){ z+=incr; d++; }
    }
  }
  if( z>=zEnd ) goto do_atof_calc;

  /* if decimal point is present */
  if( *z=='.' ){
    z+=incr;
    eType++;
    /* copy digits from after decimal to significand
    ** (decrease exponent by d to shift decimal right) */
    while( z<zEnd && sqlite3Isdigit(*z) ){
      if( s<((LARGEST_INT64-9)/10) ){
        s = s*10 + (*z - '0');
        d--;
        nDigit++;
      }
      z+=incr; nDigits++;
      z+=incr;
    }
  }
  if( z>=zEnd ) goto do_atof_calc;

  /* if exponent is present */
  if( *z=='e' || *z=='E' ){
    z+=incr;
    eValid = 0;
    eType++;

    /* This branch is needed to avoid a (harmless) buffer overread.  The 
    ** special comment alerts the mutation tester that the correct answer
    ** is obtained even if the branch is omitted */
    if( z>=zEnd ) goto do_atof_calc;              /*PREVENTS-HARMLESS-OVERREAD*/

    /* get sign of exponent */
547
548
549
550
551
552
553
554







555
556
557
558































559
560
561
562
563
564
565
632
633
634
635
636
637
638

639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687







-
+
+
+
+
+
+
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    }
  }

  /* store the result */
  *pResult = result;

  /* return true if number and no extra non-whitespace chracters after */
  return z==zEnd && nDigits>0 && eValid && nonNum==0;
  if( z==zEnd && nDigit>0 && eValid && eType>0 ){
    return eType;
  }else if( eType>=2 && (eType==3 || eValid) && nDigit>0 ){
    return -1;
  }else{
    return 0;
  }
#else
  return !sqlite3Atoi64(z, pResult, length, enc);
#endif /* SQLITE_OMIT_FLOATING_POINT */
}
#if defined(_MSC_VER)
#pragma warning(default : 4756)
#endif

/*
** Render an signed 64-bit integer as text.  Store the result in zOut[] and
** return the length of the string that was stored, in bytes.  The value
** returned does not include the zero terminator at the end of the output
** string.
**
** The caller must ensure that zOut[] is at least 21 bytes in size.
*/
int sqlite3Int64ToText(i64 v, char *zOut){
  int i;
  u64 x;
  char zTemp[22];
  if( v<0 ){
    x = (v==SMALLEST_INT64) ? ((u64)1)<<63 : (u64)-v;
  }else{
    x = v;
  }
  i = sizeof(zTemp)-2;
  zTemp[sizeof(zTemp)-1] = 0;
  do{
    zTemp[i--] = (x%10) + '0';
    x = x/10;
  }while( x );
  if( v<0 ) zTemp[i--] = '-';
  memcpy(zOut, &zTemp[i+1], sizeof(zTemp)-1-i);
  return sizeof(zTemp)-2-i;
}

/*
** Compare the 19-character string zNum against the text representation
** value 2^63:  9223372036854775808.  Return negative, zero, or positive
** if zNum is less than, equal to, or greater than the string.
** Note that zNum must contain exactly 19 characters.
**
590
591
592
593
594
595
596

597
598
599
600
601
602
603
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726







+








/*
** Convert zNum to a 64-bit signed integer.  zNum must be decimal. This
** routine does *not* accept hexadecimal notation.
**
** Returns:
**
**    -1    Not even a prefix of the input text looks like an integer
**     0    Successful transformation.  Fits in a 64-bit signed integer.
**     1    Excess non-space text after the integer value
**     2    Integer too large for a 64-bit signed integer or is malformed
**     3    Special case of 9223372036854775808
**
** length is the number of bytes in the string (bytes, not characters).
** The string is not necessarily zero-terminated.  The encoding is
614
615
616
617
618
619
620

621
622
623
624
625
626
627
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751







+







  const char *zStart;
  const char *zEnd = zNum + length;
  assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
  if( enc==SQLITE_UTF8 ){
    incr = 1;
  }else{
    incr = 2;
    length &= ~1;
    assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
    for(i=3-enc; i<length && zNum[i]==0; i+=2){}
    nonNum = i<length;
    zEnd = &zNum[i^1];
    zNum += (enc&1);
  }
  while( zNum<zEnd && sqlite3Isspace(*zNum) ) zNum+=incr;
649
650
651
652
653
654
655
656
657



658
659
660
661
662
663
664
665
773
774
775
776
777
778
779


780
781
782

783
784
785
786
787
788
789







-
-
+
+
+
-







    *pNum = neg ? SMALLEST_INT64 : LARGEST_INT64;
  }else if( neg ){
    *pNum = -(i64)u;
  }else{
    *pNum = (i64)u;
  }
  rc = 0;
  if( (i==0 && zStart==zNum)     /* No digits */
   || nonNum                     /* UTF16 with high-order bytes non-zero */
  if( i==0 && zStart==zNum ){    /* No digits */
    rc = -1;
  }else if( nonNum ){            /* UTF16 with high-order bytes non-zero */
  ){
    rc = 1;
  }else if( &zNum[i]<zEnd ){     /* Extra bytes at the end */
    int jj = i;
    do{
      if( !sqlite3Isspace(zNum[jj]) ){
        rc = 1;          /* Extra non-space text after the integer */
        break;
792
793
794
795
796
797
798
799

800
801


















802
803
804
805
806
807
808
916
917
918
919
920
921
922

923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950







-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








/*
** Return a 32-bit integer value extracted from a string.  If the
** string is not an integer, just return 0.
*/
int sqlite3Atoi(const char *z){
  int x = 0;
  if( z ) sqlite3GetInt32(z, &x);
  sqlite3GetInt32(z, &x);
  return x;
}

/*
** Try to convert z into an unsigned 32-bit integer.  Return true on
** success and false if there is an error.
**
** Only decimal notation is accepted.
*/
int sqlite3GetUInt32(const char *z, u32 *pI){
  u64 v = 0;
  int i;
  for(i=0; sqlite3Isdigit(z[i]); i++){
    v = v*10 + z[i] - '0';
    if( v>4294967296LL ){ *pI = 0; return 0; }
  }
  if( i==0 || z[i]!=0 ){ *pI = 0; return 0; }
  *pI = (u32)v;
  return 1;
}

/*
** The variable-length integer encoding is as follows:
**
** KEY:
**         A = 0xxxxxxx    7 bits of data and one flag bit
**         B = 1xxxxxxx    7 bits of data and one flag bit
882
883
884
885
886
887
888

889

890
891
892
893
894
895
896

897
898
899
900
901
902
903
904
905

906
907
908
909
910
911
912
913
914



915
916
917
918
919
920
921
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







+
-
+
-
-
-
-


-
+
-
-
-
-
-
-
-
-
-
+







-
-
+
+
+







/*
** Read a 64-bit variable-length integer from memory starting at p[0].
** Return the number of bytes read.  The value is stored in *v.
*/
u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
  u32 a,b,s;

  if( ((signed char*)p)[0]>=0 ){
  a = *p;
    *v = *p;
  /* a: p0 (unmasked) */
  if (!(a&0x80))
  {
    *v = a;
    return 1;
  }

  if( ((signed char*)p)[1]>=0 ){
  p++;
  b = *p;
  /* b: p1 (unmasked) */
  if (!(b&0x80))
  {
    a &= 0x7f;
    a = a<<7;
    a |= b;
    *v = a;
    *v = ((u32)(p[0]&0x7f)<<7) | p[1];
    return 2;
  }

  /* Verify that constants are precomputed correctly */
  assert( SLOT_2_0 == ((0x7f<<14) | (0x7f)) );
  assert( SLOT_4_2_0 == ((0xfU<<28) | (0x7f<<14) | (0x7f)) );

  p++;
  a = a<<14;
  a = ((u32)p[0])<<14;
  b = p[1];
  p += 2;
  a |= *p;
  /* a: p0<<14 | p2 (unmasked) */
  if (!(a&0x80))
  {
    a &= SLOT_2_0;
    b &= 0x7f;
    b = b<<7;
1108
1109
1110
1111
1112
1113
1114
1115
1116

1117
1118
1119
1120
1121
1122
1123
1240
1241
1242
1243
1244
1245
1246


1247
1248
1249
1250
1251
1252
1253
1254







-
-
+







  ** routine.
  */
#if 1
  {
    u64 v64;
    u8 n;

    p -= 2;
    n = sqlite3GetVarint(p, &v64);
    n = sqlite3GetVarint(p-2, &v64);
    assert( n>3 && n<=9 );
    if( (v64 & SQLITE_MAX_U32)!=v64 ){
      *v = 0xffffffff;
    }else{
      *v = (u32)v64;
    }
    return n;
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
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







-
+




















-
+







#endif
#ifdef SQLITE_EBCDIC
  h += 9*(1&~(h>>4));
#endif
  return (u8)(h & 0xf);
}

#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
#if !defined(SQLITE_OMIT_BLOB_LITERAL)
/*
** Convert a BLOB literal of the form "x'hhhhhh'" into its binary
** value.  Return a pointer to its binary value.  Space to hold the
** binary value has been obtained from malloc and must be freed by
** the calling routine.
*/
void *sqlite3HexToBlob(sqlite3 *db, const char *z, int n){
  char *zBlob;
  int i;

  zBlob = (char *)sqlite3DbMallocRawNN(db, n/2 + 1);
  n--;
  if( zBlob ){
    for(i=0; i<n; i+=2){
      zBlob[i/2] = (sqlite3HexToInt(z[i])<<4) | sqlite3HexToInt(z[i+1]);
    }
    zBlob[i/2] = 0;
  }
  return zBlob;
}
#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */
#endif /* !SQLITE_OMIT_BLOB_LITERAL */

/*
** Log an error that is an API call on a connection pointer that should
** not have been used.  The "type" of connection pointer is given as the
** argument.  The zType is a word like "NULL" or "closed" or "invalid".
*/
static void logBadConnection(const char *zType){
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
1318
1319
1320
1321
1417
1418
1419
1420
1421
1422
1423

1424
1425
1426
1427
1428


1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440





1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452







-
+




-
-
+
+










-
-
-
-
-
+
+
+
+
+







**
** sqlite3SafetyCheckOk() requires that the db pointer be valid for
** use.  sqlite3SafetyCheckSickOrOk() allows a db pointer that failed to
** open properly and is not fit for general use but which can be
** used as an argument to sqlite3_errmsg() or sqlite3_close().
*/
int sqlite3SafetyCheckOk(sqlite3 *db){
  u32 magic;
  u8 eOpenState;
  if( db==0 ){
    logBadConnection("NULL");
    return 0;
  }
  magic = db->magic;
  if( magic!=SQLITE_MAGIC_OPEN ){
  eOpenState = db->eOpenState;
  if( eOpenState!=SQLITE_STATE_OPEN ){
    if( sqlite3SafetyCheckSickOrOk(db) ){
      testcase( sqlite3GlobalConfig.xLog!=0 );
      logBadConnection("unopened");
    }
    return 0;
  }else{
    return 1;
  }
}
int sqlite3SafetyCheckSickOrOk(sqlite3 *db){
  u32 magic;
  magic = db->magic;
  if( magic!=SQLITE_MAGIC_SICK &&
      magic!=SQLITE_MAGIC_OPEN &&
      magic!=SQLITE_MAGIC_BUSY ){
  u8 eOpenState;
  eOpenState = db->eOpenState;
  if( eOpenState!=SQLITE_STATE_SICK &&
      eOpenState!=SQLITE_STATE_OPEN &&
      eOpenState!=SQLITE_STATE_BUSY ){
    testcase( sqlite3GlobalConfig.xLog!=0 );
    logBadConnection("invalid");
    return 0;
  }else{
    return 1;
  }
}
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1603
1604
1605
1606
1607
1608
1609

1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623

1624



1625
1626



1627
1628
1629
1630
1631
1632
1633


1634





1635
1636

1637
1638
1639
1640
1641
1642
1643







-














-

-
-
-


-
-
-







-
-

-
-
-
-
-


-







    while( x>255 ){ y += 40; x >>= 4; }  /*OPTIMIZATION-IF-TRUE*/
    while( x>15 ){  y += 10; x >>= 1; }
#endif
  }
  return a[x&7] + y - 10;
}

#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Convert a double into a LogEst
** In other words, compute an approximation for 10*log2(x).
*/
LogEst sqlite3LogEstFromDouble(double x){
  u64 a;
  LogEst e;
  assert( sizeof(x)==8 && sizeof(a)==8 );
  if( x<=1 ) return 0;
  if( x<=2000000000 ) return sqlite3LogEst((u64)x);
  memcpy(&a, &x, 8);
  e = (a>>52) - 1022;
  return e*10;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */

#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \
    defined(SQLITE_ENABLE_STAT3_OR_STAT4) || \
    defined(SQLITE_EXPLAIN_ESTIMATED_ROWS)
/*
** Convert a LogEst into an integer.
**
** Note that this routine is only used when one or more of various
** non-standard compile-time options is enabled.
*/
u64 sqlite3LogEstToInt(LogEst x){
  u64 n;
  n = x%10;
  x /= 10;
  if( n>=5 ) n -= 2;
  else if( n>=1 ) n -= 1;
#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \
    defined(SQLITE_EXPLAIN_ESTIMATED_ROWS)
  if( x>60 ) return (u64)LARGEST_INT64;
#else
  /* If only SQLITE_ENABLE_STAT3_OR_STAT4 is on, then the largest input
  ** possible to this routine is 310, resulting in a maximum x of 31 */
  assert( x<=60 );
#endif
  return x>=3 ? (n+8)<<(x-3) : (n+8)>>(3-x);
}
#endif /* defined SCANSTAT or STAT4 or ESTIMATED_ROWS */

/*
** Add a new name/number pair to a VList.  This might require that the
** VList object be reallocated, so return the new VList.  If an OOM
** error occurs, the original VList returned and the
** db->mallocFailed flag is set.
**
1567
1568
1569
1570
1571
1572
1573
1574

1575
1576
1577
1578
1579
1580
1581
1682
1683
1684
1685
1686
1687
1688

1689
1690
1691
1692
1693
1694
1695
1696







-
+







  char *z;               /* Pointer to where zName will be stored */
  int i;                 /* Index in pIn[] where zName is stored */

  nInt = nName/4 + 3;
  assert( pIn==0 || pIn[0]>=3 );  /* Verify ok to add new elements */
  if( pIn==0 || pIn[1]+nInt > pIn[0] ){
    /* Enlarge the allocation */
    int nAlloc = (pIn ? pIn[0]*2 : 10) + nInt;
    sqlite3_int64 nAlloc = (pIn ? 2*(sqlite3_int64)pIn[0] : 10) + nInt;
    VList *pOut = sqlite3DbRealloc(db, pIn, nAlloc*sizeof(int));
    if( pOut==0 ) return pIn;
    if( pIn==0 ) pOut[1] = 2;
    pIn = pOut;
    pIn[0] = nAlloc;
  }
  i = pIn[1];
1618
1619
1620
1621
1622
1623
1624









1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748







+
+
+
+
+
+
+
+
+
  do{
    const char *z = (const char*)&pIn[i+2];
    if( strncmp(z,zName,nName)==0 && z[nName]==0 ) return pIn[i];
    i += pIn[i+1];
  }while( i<mx );
  return 0;
}

/*
** High-resolution hardware timer used for debugging and testing only.
*/
#if defined(VDBE_PROFILE)  \
 || defined(SQLITE_PERFORMANCE_TRACE) \
 || defined(SQLITE_ENABLE_STMT_SCANSTATUS) 
# include "hwtime.h"
#endif

Changes to src/vacuum.c.

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







-
+







  rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
  if( rc!=SQLITE_OK ) return rc;
  while( SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){
    const char *zSubSql = (const char*)sqlite3_column_text(pStmt,0);
    assert( sqlite3_strnicmp(zSql,"SELECT",6)==0 );
    /* The secondary SQL must be one of CREATE TABLE, CREATE INDEX,
    ** or INSERT.  Historically there have been attacks that first
    ** corrupt the sqlite_master.sql field with other kinds of statements
    ** corrupt the sqlite_schema.sql field with other kinds of statements
    ** then run VACUUM to get those statements to execute at inappropriate
    ** times. */
    if( zSubSql
     && (strncmp(zSubSql,"CRE",3)==0 || strncmp(zSubSql,"INS",3)==0)
    ){
      rc = execSql(db, pzErrMsg, zSubSql);
      if( rc!=SQLITE_OK ) break;
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
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







+


















-
+














-
+



-
+






-
-
+
+
+







+



-
+



-
+

+






+
+







** transient would cause the database file to appear to be deleted
** following reboot.
*/
void sqlite3Vacuum(Parse *pParse, Token *pNm, Expr *pInto){
  Vdbe *v = sqlite3GetVdbe(pParse);
  int iDb = 0;
  if( v==0 ) goto build_vacuum_end;
  if( pParse->nErr ) goto build_vacuum_end;
  if( pNm ){
#ifndef SQLITE_BUG_COMPATIBLE_20160819
    /* Default behavior:  Report an error if the argument to VACUUM is
    ** not recognized */
    iDb = sqlite3TwoPartName(pParse, pNm, pNm, &pNm);
    if( iDb<0 ) goto build_vacuum_end;
#else
    /* When SQLITE_BUG_COMPATIBLE_20160819 is defined, unrecognized arguments
    ** to VACUUM are silently ignored.  This is a back-out of a bug fix that
    ** occurred on 2016-08-19 (https://www.sqlite.org/src/info/083f9e6270).
    ** The buggy behavior is required for binary compatibility with some
    ** legacy applications. */
    iDb = sqlite3FindDb(pParse->db, pNm);
    if( iDb<0 ) iDb = 0;
#endif
  }
  if( iDb!=1 ){
    int iIntoReg = 0;
    if( pInto ){
    if( pInto && sqlite3ResolveSelfReference(pParse,0,0,pInto,0)==0 ){
      iIntoReg = ++pParse->nMem;
      sqlite3ExprCode(pParse, pInto, iIntoReg);
    }
    sqlite3VdbeAddOp2(v, OP_Vacuum, iDb, iIntoReg);
    sqlite3VdbeUsesBtree(v, iDb);
  }
build_vacuum_end:
  sqlite3ExprDelete(pParse->db, pInto);
  return;
}

/*
** This routine implements the OP_Vacuum opcode of the VDBE.
*/
int sqlite3RunVacuum(
SQLITE_NOINLINE int sqlite3RunVacuum(
  char **pzErrMsg,        /* Write error message here */
  sqlite3 *db,            /* Database connection */
  int iDb,                /* Which attached DB to vacuum */
  sqlite3_value *pOut     /* Write results here, if not NULL */
  sqlite3_value *pOut     /* Write results here, if not NULL. VACUUM INTO */
){
  int rc = SQLITE_OK;     /* Return code from service routines */
  Btree *pMain;           /* The database being vacuumed */
  Btree *pTemp;           /* The temporary database we vacuum into */
  u32 saved_mDbFlags;     /* Saved value of db->mDbFlags */
  u64 saved_flags;        /* Saved value of db->flags */
  int saved_nChange;      /* Saved value of db->nChange */
  int saved_nTotalChange; /* Saved value of db->nTotalChange */
  i64 saved_nChange;      /* Saved value of db->nChange */
  i64 saved_nTotalChange; /* Saved value of db->nTotalChange */
  u32 saved_openFlags;    /* Saved value of db->openFlags */
  u8 saved_mTrace;        /* Saved trace settings */
  Db *pDb = 0;            /* Database to detach at end of vacuum */
  int isMemDb;            /* True if vacuuming a :memory: database */
  int nRes;               /* Bytes of reserved space at the end of each page */
  int nDb;                /* Number of attached databases */
  const char *zDbMain;    /* Schema name of database to vacuum */
  const char *zOut;       /* Name of output file */
  u32 pgflags = PAGER_SYNCHRONOUS_OFF; /* sync flags for output db */

  if( !db->autoCommit ){
    sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction");
    return SQLITE_ERROR;
    return SQLITE_ERROR; /* IMP: R-12218-18073 */
  }
  if( db->nVdbeActive>1 ){
    sqlite3SetString(pzErrMsg, db,"cannot VACUUM - SQL statements in progress");
    return SQLITE_ERROR;
    return SQLITE_ERROR; /* IMP: R-15610-35227 */
  }
  saved_openFlags = db->openFlags;
  if( pOut ){
    if( sqlite3_value_type(pOut)!=SQLITE_TEXT ){
      sqlite3SetString(pzErrMsg, db, "non-text filename");
      return SQLITE_ERROR;
    }
    zOut = (const char*)sqlite3_value_text(pOut);
    db->openFlags &= ~SQLITE_OPEN_READONLY;
    db->openFlags |= SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE;
  }else{
    zOut = "";
  }

  /* Save the current value of the database flags so that it can be 
  ** restored before returning. Then set the writable-schema flag, and
  ** disable CHECK and foreign key constraints.  */
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
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







+













+
-
+
-
-
-
+
+
-
-
-
-
-
+
-
-
+

-
+



-
+












-
+
+
+







  ** actually occurs when doing a vacuum since the vacuum_db is initially
  ** empty.  Only the journal header is written.  Apparently it takes more
  ** time to parse and run the PRAGMA to turn journalling off than it does
  ** to write the journal header file.
  */
  nDb = db->nDb;
  rc = execSqlF(db, pzErrMsg, "ATTACH %Q AS vacuum_db", zOut);
  db->openFlags = saved_openFlags;
  if( rc!=SQLITE_OK ) goto end_of_vacuum;
  assert( (db->nDb-1)==nDb );
  pDb = &db->aDb[nDb];
  assert( strcmp(pDb->zDbSName,"vacuum_db")==0 );
  pTemp = pDb->pBt;
  if( pOut ){
    sqlite3_file *id = sqlite3PagerFile(sqlite3BtreePager(pTemp));
    i64 sz = 0;
    if( id->pMethods!=0 && (sqlite3OsFileSize(id, &sz)!=SQLITE_OK || sz>0) ){
      rc = SQLITE_ERROR;
      sqlite3SetString(pzErrMsg, db, "output file already exists");
      goto end_of_vacuum;
    }
    db->mDbFlags |= DBFLAG_VacuumInto;
  }

  nRes = sqlite3BtreeGetOptimalReserve(pMain);

  /* A VACUUM cannot change the pagesize of an encrypted database. */
    /* For a VACUUM INTO, the pager-flags are set to the same values as
    ** they are for the database being vacuumed, except that PAGER_CACHESPILL
#ifdef SQLITE_HAS_CODEC
  if( db->nextPagesize ){
    extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*);
    int nKey;
    char *zKey;
    ** is always set. */
    sqlite3CodecGetKey(db, iDb, (void**)&zKey, &nKey);
    if( nKey ) db->nextPagesize = 0;
    pgflags = db->aDb[iDb].safety_level | (db->flags & PAGER_FLAGS_MASK);
  }
#endif
  nRes = sqlite3BtreeGetRequestedReserve(pMain);

  sqlite3BtreeSetCacheSize(pTemp, db->aDb[iDb].pSchema->cache_size);
  sqlite3BtreeSetSpillSize(pTemp, sqlite3BtreeSetSpillSize(pMain,0));
  sqlite3BtreeSetPagerFlags(pTemp, PAGER_SYNCHRONOUS_OFF|PAGER_CACHESPILL);
  sqlite3BtreeSetPagerFlags(pTemp, pgflags|PAGER_CACHESPILL);

  /* Begin a transaction and take an exclusive lock on the main database
  ** file. This is done before the sqlite3BtreeGetPageSize(pMain) call below,
  ** to ensure that we do not try to change the page-size on a WAL database.
  */
  rc = execSql(db, pzErrMsg, "BEGIN");
  if( rc!=SQLITE_OK ) goto end_of_vacuum;
  rc = sqlite3BtreeBeginTrans(pMain, pOut==0 ? 2 : 0, 0);
  if( rc!=SQLITE_OK ) goto end_of_vacuum;

  /* Do not attempt to change the page size for a WAL database */
  if( sqlite3PagerGetJournalMode(sqlite3BtreePager(pMain))
                                               ==PAGER_JOURNALMODE_WAL ){
                                               ==PAGER_JOURNALMODE_WAL
   && pOut==0
  ){
    db->nextPagesize = 0;
  }

  if( sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain), nRes, 0)
   || (!isMemDb && sqlite3BtreeSetPageSize(pTemp, db->nextPagesize, nRes, 0))
   || NEVER(db->mallocFailed)
  ){
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
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







-
+






-
+













-
+










-
+


-
-
+
+







#endif

  /* Query the schema of the main database. Create a mirror schema
  ** in the temporary database.
  */
  db->init.iDb = nDb; /* force new CREATE statements into vacuum_db */
  rc = execSqlF(db, pzErrMsg,
      "SELECT sql FROM \"%w\".sqlite_master"
      "SELECT sql FROM \"%w\".sqlite_schema"
      " WHERE type='table'AND name<>'sqlite_sequence'"
      " AND coalesce(rootpage,1)>0",
      zDbMain
  );
  if( rc!=SQLITE_OK ) goto end_of_vacuum;
  rc = execSqlF(db, pzErrMsg,
      "SELECT sql FROM \"%w\".sqlite_master"
      "SELECT sql FROM \"%w\".sqlite_schema"
      " WHERE type='index'",
      zDbMain
  );
  if( rc!=SQLITE_OK ) goto end_of_vacuum;
  db->init.iDb = 0;

  /* Loop through the tables in the main database. For each, do
  ** an "INSERT INTO vacuum_db.xxx SELECT * FROM main.xxx;" to copy
  ** the contents to the temporary database.
  */
  rc = execSqlF(db, pzErrMsg,
      "SELECT'INSERT INTO vacuum_db.'||quote(name)"
      "||' SELECT*FROM\"%w\".'||quote(name)"
      "FROM vacuum_db.sqlite_master "
      "FROM vacuum_db.sqlite_schema "
      "WHERE type='table'AND coalesce(rootpage,1)>0",
      zDbMain
  );
  assert( (db->mDbFlags & DBFLAG_Vacuum)!=0 );
  db->mDbFlags &= ~DBFLAG_Vacuum;
  if( rc!=SQLITE_OK ) goto end_of_vacuum;

  /* Copy the triggers, views, and virtual tables from the main database
  ** over to the temporary database.  None of these objects has any
  ** associated storage, so all we have to do is copy their entries
  ** from the SQLITE_MASTER table.
  ** from the schema table.
  */
  rc = execSqlF(db, pzErrMsg,
      "INSERT INTO vacuum_db.sqlite_master"
      " SELECT*FROM \"%w\".sqlite_master"
      "INSERT INTO vacuum_db.sqlite_schema"
      " SELECT*FROM \"%w\".sqlite_schema"
      " WHERE type IN('view','trigger')"
      " OR(type='table'AND rootpage=0)",
      zDbMain
  );
  if( rc ) goto end_of_vacuum;

  /* At this point, there is a write transaction open on both the 
339
340
341
342
343
344
345
346
347


348
349
350
351
352
353
354
343
344
345
346
347
348
349


350
351
352
353
354
355
356
357
358







-
-
+
+







       BTREE_SCHEMA_VERSION,     1,  /* Add one to the old schema cookie */
       BTREE_DEFAULT_CACHE_SIZE, 0,  /* Preserve the default page cache size */
       BTREE_TEXT_ENCODING,      0,  /* Preserve the text encoding */
       BTREE_USER_VERSION,       0,  /* Preserve the user version */
       BTREE_APPLICATION_ID,     0,  /* Preserve the application id */
    };

    assert( 1==sqlite3BtreeIsInTrans(pTemp) );
    assert( pOut!=0 || 1==sqlite3BtreeIsInTrans(pMain) );
    assert( SQLITE_TXN_WRITE==sqlite3BtreeTxnState(pTemp) );
    assert( pOut!=0 || SQLITE_TXN_WRITE==sqlite3BtreeTxnState(pMain) );

    /* Copy Btree meta values */
    for(i=0; i<ArraySize(aCopy); i+=2){
      /* GetMeta() and UpdateMeta() cannot fail in this context because
      ** we already have page 1 loaded into cache and marked dirty. */
      sqlite3BtreeGetMeta(pMain, aCopy[i], &meta);
      rc = sqlite3BtreeUpdateMeta(pTemp, aCopy[i], meta+aCopy[i+1]);
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
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







+











-
+









-
+







      sqlite3BtreeSetAutoVacuum(pMain, sqlite3BtreeGetAutoVacuum(pTemp));
    }
#endif
  }

  assert( rc==SQLITE_OK );
  if( pOut==0 ){
    nRes = sqlite3BtreeGetRequestedReserve(pTemp);
    rc = sqlite3BtreeSetPageSize(pMain, sqlite3BtreeGetPageSize(pTemp), nRes,1);
  }

end_of_vacuum:
  /* Restore the original value of db->flags */
  db->init.iDb = 0;
  db->mDbFlags = saved_mDbFlags;
  db->flags = saved_flags;
  db->nChange = saved_nChange;
  db->nTotalChange = saved_nTotalChange;
  db->mTrace = saved_mTrace;
  sqlite3BtreeSetPageSize(pMain, -1, -1, 1);
  sqlite3BtreeSetPageSize(pMain, -1, 0, 1);

  /* Currently there is an SQL level transaction open on the vacuum
  ** database. No locks are held on any other files (since the main file
  ** was committed at the btree level). So it safe to end the transaction
  ** by manually setting the autoCommit flag to true and detaching the
  ** vacuum database. The vacuum_db journal file is deleted when the pager
  ** is closed by the DETACH.
  */
  db->autoCommit = 1;
  assert( db->bConcurrent==0 );
  assert( db->eConcurrent==0 );

  if( pDb ){
    sqlite3BtreeClose(pDb->pBt);
    pDb->pBt = 0;
    pDb->pSchema = 0;
  }

Changes to src/vdbe.c.

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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-










-
+

-
+







*/
#if defined(SQLITE_TEST) && !defined(SQLITE_UNTESTABLE)
# define UPDATE_MAX_BLOBSIZE(P)  updateMaxBlobsize(P)
#else
# define UPDATE_MAX_BLOBSIZE(P)
#endif

#ifdef SQLITE_DEBUG
/* This routine provides a convenient place to set a breakpoint during
** tracing with PRAGMA vdbe_trace=on.  The breakpoint fires right after
** each opcode is printed.  Variables "pc" (program counter) and pOp are
** available to add conditionals to the breakpoint.  GDB example:
**
**         break test_trace_breakpoint if pc=22
**
** Other useful labels for breakpoints include:
**   test_addop_breakpoint(pc,pOp)
**   sqlite3CorruptError(lineno)
**   sqlite3MisuseError(lineno)
**   sqlite3CantopenError(lineno)
*/
static void test_trace_breakpoint(int pc, Op *pOp, Vdbe *v){
  static int n = 0;
  (void)pc;
  (void)pOp;
  (void)v;
  n++;
}
#endif

/*
** Invoke the VDBE coverage callback, if that callback is defined.  This
** feature is used for test suite validation only and does not appear an
** production builds.
**
** M is an integer between 2 and 4.  2 indicates a ordinary two-way
** branch (I=0 means fall through and I=1 means taken).  3 indicates
** a 3-way branch where the third way is when one of the operands is
** NULL.  4 indicates the OP_Jump instruction which has three destinations
** depending on whether the first operand is less than, equal to, or greater
** M is the type of branch.  I is the direction taken for this instance of
** the branch.
**
**   M: 2 - two-way branch (I=0: fall-thru   1: jump                )
**      3 - two-way + NULL (I=0: fall-thru   1: jump      2: NULL   )
**      4 - OP_Jump        (I=0: jump p1     1: jump p2   2: jump p3)
**
** In other words, if M is 2, then I is either 0 (for fall-through) or
** 1 (for when the branch is taken).  If M is 3, the I is 0 for an
** ordinary fall-through, I is 1 if the branch was taken, and I is 2 
** if the result of comparison is NULL.  For M=3, I=2 the jump may or
** may not be taken, depending on the SQLITE_JUMPIFNULL flags in p5.
** When M is 4, that means that an OP_Jump is being run.  I is 0, 1, or 2
** depending on if the operands are less than, equal, or greater than.
** than the second. 
**
** iSrcLine is the source code line (from the __LINE__ macro) that
** generated the VDBE instruction combined with flag bits.  The source
** code line number is in the lower 24 bits of iSrcLine and the upper
** 8 bytes are flags.  The lower three bits of the flags indicate
** values for I that should never occur.  For example, if the branch is
** always taken, the flags should be 0x05 since the fall-through and
** alternate branch are never taken.  If a branch is never taken then
** flags should be 0x06 since only the fall-through approach is allowed.
**
** Bit 0x04 of the flags indicates an OP_Jump opcode that is only
** Bit 0x08 of the flags indicates an OP_Jump opcode that is only
** interested in equal or not-equal.  In other words, I==0 and I==2
** should be treated the same.
** should be treated as equivalent
**
** Since only a line number is retained, not the filename, this macro
** only works for amalgamation builds.  But that is ok, since these macros
** should be no-ops except for special builds used to measure test coverage.
*/
#if !defined(SQLITE_VDBE_COVERAGE)
# define VdbeBranchTaken(I,M)
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
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







+
+
+
+
+
+
+
+
+
+
+
+











-
-
-
-
-
-
-
-







    /* The upper 8 bits of iSrcLine are flags.  The lower three bits of
    ** the flags indicate directions that the branch can never go.  If
    ** a branch really does go in one of those directions, assert right
    ** away. */
    mNever = iSrcLine >> 24;
    assert( (I & mNever)==0 );
    if( sqlite3GlobalConfig.xVdbeBranch==0 ) return;  /*NO_TEST*/
    /* Invoke the branch coverage callback with three arguments:
    **    iSrcLine - the line number of the VdbeCoverage() macro, with
    **               flags removed.
    **    I        - Mask of bits 0x07 indicating which cases are are
    **               fulfilled by this instance of the jump.  0x01 means
    **               fall-thru, 0x02 means taken, 0x04 means NULL.  Any
    **               impossible cases (ex: if the comparison is never NULL)
    **               are filled in automatically so that the coverage
    **               measurement logic does not flag those impossible cases
    **               as missed coverage.
    **    M        - Type of jump.  Same as M argument above
    */
    I |= mNever;
    if( M==2 ) I |= 0x04;
    if( M==4 ){
      I |= 0x08;
      if( (mNever&0x08)!=0 && (I&0x05)!=0) I |= 0x05; /*NO_TEST*/
    }
    sqlite3GlobalConfig.xVdbeBranch(sqlite3GlobalConfig.pVdbeBranchArg,
                                    iSrcLine&0xffffff, I, M);
  }
#endif

/*
** Convert the given register into a string if it isn't one
** already. Return non-zero if a malloc() fails.
*/
#define Stringify(P, enc) \
   if(((P)->flags&(MEM_Str|MEM_Blob))==0 && sqlite3VdbeMemStringify(P,enc,0)) \
     { goto no_mem; }

/*
** An ephemeral string value (signified by the MEM_Ephem flag) contains
** a pointer to a dynamically allocated string where some other entity
** is responsible for deallocating that string.  Because the register
** does not control the string, it might be deleted without the register
** knowing it.
**
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
240
241
242
243
244
245
246

247
248
249
250
251
252
253







-







** Allocate VdbeCursor number iCur.  Return a pointer to it.  Return NULL
** if we run out of memory.
*/
static VdbeCursor *allocateCursor(
  Vdbe *p,              /* The virtual machine */
  int iCur,             /* Index of the new VdbeCursor */
  int nField,           /* Number of fields in the table or index */
  int iDb,              /* Database the cursor belongs to, or -1 */
  u8 eCurType           /* Type of the new cursor */
){
  /* Find the memory cell that will be used to store the blob of memory
  ** required for this VdbeCursor structure. It is convenient to use a 
  ** vdbe memory cell to manage the memory allocation required for a
  ** VdbeCursor structure for the following reasons:
  **
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
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







-
+




-
+


+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


















-

+
-
-
-
-
+
+
+
+







  ** Cursor 2 is at Mem[p->nMem-2]. And so forth.
  */
  Mem *pMem = iCur>0 ? &p->aMem[p->nMem-iCur] : p->aMem;

  int nByte;
  VdbeCursor *pCx = 0;
  nByte = 
      ROUND8(sizeof(VdbeCursor)) + 2*sizeof(u32)*nField + 
      ROUND8P(sizeof(VdbeCursor)) + 2*sizeof(u32)*nField + 
      (eCurType==CURTYPE_BTREE?sqlite3BtreeCursorSize():0);

  assert( iCur>=0 && iCur<p->nCursor );
  if( p->apCsr[iCur] ){ /*OPTIMIZATION-IF-FALSE*/
    sqlite3VdbeFreeCursor(p, p->apCsr[iCur]);
    sqlite3VdbeFreeCursorNN(p, p->apCsr[iCur]);
    p->apCsr[iCur] = 0;
  }

  if( SQLITE_OK==sqlite3VdbeMemClearAndResize(pMem, nByte) ){
    p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->z;
    memset(pCx, 0, offsetof(VdbeCursor,pAltCursor));
    pCx->eCurType = eCurType;
  /* There used to be a call to sqlite3VdbeMemClearAndResize() to make sure
  ** the pMem used to hold space for the cursor has enough storage available
  ** in pMem->zMalloc.  But for the special case of the aMem[] entries used
  ** to hold cursors, it is faster to in-line the logic. */
  assert( pMem->flags==MEM_Undefined );
  assert( (pMem->flags & MEM_Dyn)==0 );
  assert( pMem->szMalloc==0 || pMem->z==pMem->zMalloc );
  if( pMem->szMalloc<nByte ){
    if( pMem->szMalloc>0 ){
      sqlite3DbFreeNN(pMem->db, pMem->zMalloc);
    }
    pMem->z = pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, nByte);
    if( pMem->zMalloc==0 ){
      pMem->szMalloc = 0;
      return 0;
    }
    pMem->szMalloc = nByte;
  }

  p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->zMalloc;
  memset(pCx, 0, offsetof(VdbeCursor,pAltCursor));
  pCx->eCurType = eCurType;
    pCx->iDb = iDb;
    pCx->nField = nField;
    pCx->aOffset = &pCx->aType[nField];
    if( eCurType==CURTYPE_BTREE ){
      pCx->uc.pCursor = (BtCursor*)
          &pMem->z[ROUND8(sizeof(VdbeCursor))+2*sizeof(u32)*nField];
      sqlite3BtreeCursorZero(pCx->uc.pCursor);
    }
  }
  return pCx;
}
  pCx->nField = nField;
  pCx->aOffset = &pCx->aType[nField];
  if( eCurType==CURTYPE_BTREE ){
    pCx->uc.pCursor = (BtCursor*)
        &pMem->z[ROUND8P(sizeof(VdbeCursor))+2*sizeof(u32)*nField];
    sqlite3BtreeCursorZero(pCx->uc.pCursor);
  }
  return pCx;
}

/*
** The string in pRec is known to look like an integer and to have a
** floating point value of rValue.  Return true and set *piValue to the
** integer value if the string is in range to be an integer.  Otherwise,
** return false.
*/
static int alsoAnInt(Mem *pRec, double rValue, i64 *piValue){
  i64 iValue;
  iValue = sqlite3RealToI64(rValue);
  if( sqlite3RealSameAsInt(rValue,iValue) ){
    *piValue = iValue;
    return 1;
  }
  return 0==sqlite3Atoi64(pRec->z, piValue, pRec->n, pRec->enc);
}

/*
** Try to convert a value into a numeric representation if we can
** do so without loss of information.  In other words, if the string
** looks like a number, convert it into a number.  If it does not
** look like a number, leave it alone.
**
** If the bTryForInt flag is true, then extra effort is made to give
** an integer representation.  Strings that look like floating point
** values but which have no fractional component (example: '48.00')
** will have a MEM_Int representation when bTryForInt is true.
**
** If bTryForInt is false, then if the input string contains a decimal
** point or exponential notation, the result is only MEM_Real, even
** if there is an exact integer representation of the quantity.
*/
static void applyNumericAffinity(Mem *pRec, int bTryForInt){
  double rValue;
  i64 iValue;
  u8 enc = pRec->enc;
  int rc;
  assert( (pRec->flags & (MEM_Str|MEM_Int|MEM_Real))==MEM_Str );
  if( sqlite3AtoF(pRec->z, &rValue, pRec->n, enc)==0 ) return;
  if( 0==sqlite3Atoi64(pRec->z, &iValue, pRec->n, enc) ){
    pRec->u.i = iValue;
  assert( (pRec->flags & (MEM_Str|MEM_Int|MEM_Real|MEM_IntReal))==MEM_Str );
  rc = sqlite3AtoF(pRec->z, &rValue, pRec->n, enc);
  if( rc<=0 ) return;
  if( rc==1 && alsoAnInt(pRec, rValue, &pRec->u.i) ){
    pRec->flags |= MEM_Int;
  }else{
    pRec->u.r = rValue;
    pRec->flags |= MEM_Real;
    if( bTryForInt ) sqlite3VdbeIntegerAffinity(pRec);
  }
  /* TEXT->NUMERIC is many->one.  Hence, it is important to invalidate the
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
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







+
+
+
+




+









-
+

-
+

-
+










-
+
+
+
+



-
+







** SQLITE_AFF_NUMERIC:
**    Try to convert pRec to an integer representation or a 
**    floating-point representation if an integer representation
**    is not possible.  Note that the integer representation is
**    always preferred, even if the affinity is REAL, because
**    an integer representation is more space efficient on disk.
**
** SQLITE_AFF_FLEXNUM:
**    If the value is text, then try to convert it into a number of
**    some kind (integer or real) but do not make any other changes.
**
** SQLITE_AFF_TEXT:
**    Convert pRec to a text representation.
**
** SQLITE_AFF_BLOB:
** SQLITE_AFF_NONE:
**    No-op.  pRec is unchanged.
*/
static void applyAffinity(
  Mem *pRec,          /* The value to apply affinity to */
  char affinity,      /* The affinity to be applied */
  u8 enc              /* Use this text encoding */
){
  if( affinity>=SQLITE_AFF_NUMERIC ){
    assert( affinity==SQLITE_AFF_INTEGER || affinity==SQLITE_AFF_REAL
             || affinity==SQLITE_AFF_NUMERIC );
             || affinity==SQLITE_AFF_NUMERIC || affinity==SQLITE_AFF_FLEXNUM );
    if( (pRec->flags & MEM_Int)==0 ){ /*OPTIMIZATION-IF-FALSE*/
      if( (pRec->flags & MEM_Real)==0 ){
      if( (pRec->flags & (MEM_Real|MEM_IntReal))==0 ){
        if( pRec->flags & MEM_Str ) applyNumericAffinity(pRec,1);
      }else{
      }else if( affinity<=SQLITE_AFF_REAL ){
        sqlite3VdbeIntegerAffinity(pRec);
      }
    }
  }else if( affinity==SQLITE_AFF_TEXT ){
    /* Only attempt the conversion to TEXT if there is an integer or real
    ** representation (blob and NULL do not get converted) but no string
    ** representation.  It would be harmless to repeat the conversion if 
    ** there is already a string rep, but it is pointless to waste those
    ** CPU cycles. */
    if( 0==(pRec->flags&MEM_Str) ){ /*OPTIMIZATION-IF-FALSE*/
      if( (pRec->flags&(MEM_Real|MEM_Int)) ){
      if( (pRec->flags&(MEM_Real|MEM_Int|MEM_IntReal)) ){
        testcase( pRec->flags & MEM_Int );
        testcase( pRec->flags & MEM_Real );
        testcase( pRec->flags & MEM_IntReal );
        sqlite3VdbeMemStringify(pRec, enc, 1);
      }
    }
    pRec->flags &= ~(MEM_Real|MEM_Int);
    pRec->flags &= ~(MEM_Real|MEM_Int|MEM_IntReal);
  }
}

/*
** Try to convert the type of a function argument or a result column
** into a numeric representation.  Use either INTEGER or REAL whichever
** is appropriate.  But only do the conversion if it is possible without
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
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







+
+
-
+

+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+













+
+
-
-
+
+
+
+
+

-
-
+
+
+
+
-








-
+
-

-

-















-
-
+
-
-
-
+
+
-

+
-
+

-
-
+

-
+

-
+
-

-

-
-
+
+

-
+


-
+


-
+


-
+

-
-
+
-
-
-
-
-
+
+
+
-
-
-
-
+
-
-
-
+
-
-















+
+




-
+




+
-
-
-
+
+
+
+




-
+

+
+
+



+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+





-
-
-
-
-
-
-
-
-
-
-







/*
** pMem currently only holds a string type (or maybe a BLOB that we can
** interpret as a string if we want to).  Compute its corresponding
** numeric type, if has one.  Set the pMem->u.r and pMem->u.i fields
** accordingly.
*/
static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){
  int rc;
  sqlite3_int64 ix;
  assert( (pMem->flags & (MEM_Int|MEM_Real))==0 );
  assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal))==0 );
  assert( (pMem->flags & (MEM_Str|MEM_Blob))!=0 );
  if( ExpandBlob(pMem) ){
    pMem->u.i = 0;
    return MEM_Int;
  }
  if( sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc)==0 ){
    return 0;
  }
  if( sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc)==0 ){
  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;
    }
  }else if( rc==1 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)==0 ){
    pMem->u.i = ix;
    return MEM_Int;
  }
  return MEM_Real;
}

/*
** Return the numeric type for pMem, either MEM_Int or MEM_Real or both or
** none.  
**
** Unlike applyNumericAffinity(), this routine does not modify pMem->flags.
** But it does set pMem->u.r and pMem->u.i appropriately.
*/
static u16 numericType(Mem *pMem){
  assert( (pMem->flags & MEM_Null)==0
       || pMem->db==0 || pMem->db->mallocFailed );
  if( pMem->flags & (MEM_Int|MEM_Real) ){
    return pMem->flags & (MEM_Int|MEM_Real);
  if( pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Null) ){
    testcase( pMem->flags & MEM_Int );
    testcase( pMem->flags & MEM_Real );
    testcase( pMem->flags & MEM_IntReal );
    return pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Null);
  }
  if( pMem->flags & (MEM_Str|MEM_Blob) ){
    return computeNumericType(pMem);
  assert( pMem->flags & (MEM_Str|MEM_Blob) );
  testcase( pMem->flags & MEM_Str );
  testcase( pMem->flags & MEM_Blob );
  return computeNumericType(pMem);
  }
  return 0;
}

#ifdef SQLITE_DEBUG
/*
** Write a nice string representation of the contents of cell pMem
** into buffer zBuf, length nBuf.
*/
void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){
void sqlite3VdbeMemPrettyPrint(Mem *pMem, StrAccum *pStr){
  char *zCsr = zBuf;
  int f = pMem->flags;

  static const char *const encnames[] = {"(X)", "(8)", "(16LE)", "(16BE)"};

  if( f&MEM_Blob ){
    int i;
    char c;
    if( f & MEM_Dyn ){
      c = 'z';
      assert( (f & (MEM_Static|MEM_Ephem))==0 );
    }else if( f & MEM_Static ){
      c = 't';
      assert( (f & (MEM_Dyn|MEM_Ephem))==0 );
    }else if( f & MEM_Ephem ){
      c = 'e';
      assert( (f & (MEM_Static|MEM_Dyn))==0 );
    }else{
      c = 's';
    }
    *(zCsr++) = c;
    sqlite3_snprintf(100, zCsr, "%d[", pMem->n);
    sqlite3_str_appendf(pStr, "%cx[", c);
    zCsr += sqlite3Strlen30(zCsr);
    for(i=0; i<16 && i<pMem->n; i++){
      sqlite3_snprintf(100, zCsr, "%02X", ((int)pMem->z[i] & 0xFF));
    for(i=0; i<25 && i<pMem->n; i++){
      sqlite3_str_appendf(pStr, "%02X", ((int)pMem->z[i] & 0xFF));
      zCsr += sqlite3Strlen30(zCsr);
    }
    sqlite3_str_appendf(pStr, "|");
    for(i=0; i<16 && i<pMem->n; i++){
    for(i=0; i<25 && i<pMem->n; i++){
      char z = pMem->z[i];
      if( z<32 || z>126 ) *zCsr++ = '.';
      else *zCsr++ = z;
      sqlite3_str_appendchar(pStr, 1, (z<32||z>126)?'.':z);
    }
    *(zCsr++) = ']';
    sqlite3_str_appendf(pStr,"]");
    if( f & MEM_Zero ){
      sqlite3_snprintf(100, zCsr,"+%dz",pMem->u.nZero);
      sqlite3_str_appendf(pStr, "+%dz",pMem->u.nZero);
      zCsr += sqlite3Strlen30(zCsr);
    }
    *zCsr = '\0';
  }else if( f & MEM_Str ){
    int j, k;
    zBuf[0] = ' ';
    int j;
    u8 c;
    if( f & MEM_Dyn ){
      zBuf[1] = 'z';
      c = 'z';
      assert( (f & (MEM_Static|MEM_Ephem))==0 );
    }else if( f & MEM_Static ){
      zBuf[1] = 't';
      c = 't';
      assert( (f & (MEM_Dyn|MEM_Ephem))==0 );
    }else if( f & MEM_Ephem ){
      zBuf[1] = 'e';
      c = 'e';
      assert( (f & (MEM_Static|MEM_Dyn))==0 );
    }else{
      zBuf[1] = 's';
      c = 's';
    }
    k = 2;
    sqlite3_snprintf(100, &zBuf[k], "%d", pMem->n);
    sqlite3_str_appendf(pStr, " %c%d[", c, pMem->n);
    k += sqlite3Strlen30(&zBuf[k]);
    zBuf[k++] = '[';
    for(j=0; j<15 && j<pMem->n; j++){
      u8 c = pMem->z[j];
      if( c>=0x20 && c<0x7f ){
    for(j=0; j<25 && j<pMem->n; j++){
      c = pMem->z[j];
      sqlite3_str_appendchar(pStr, 1, (c>=0x20&&c<=0x7f) ? c : '.');
        zBuf[k++] = c;
      }else{
        zBuf[k++] = '.';
      }
    }
    }
    zBuf[k++] = ']';
    sqlite3_snprintf(100,&zBuf[k], encnames[pMem->enc]);
    sqlite3_str_appendf(pStr, "]%s", encnames[pMem->enc]);
    k += sqlite3Strlen30(&zBuf[k]);
    zBuf[k++] = 0;
  }
}
#endif

#ifdef SQLITE_DEBUG
/*
** Print the value of a register for tracing purposes:
*/
static void memTracePrint(Mem *p){
  if( p->flags & MEM_Undefined ){
    printf(" undefined");
  }else if( p->flags & MEM_Null ){
    printf(p->flags & MEM_Zero ? " NULL-nochng" : " NULL");
  }else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){
    printf(" si:%lld", p->u.i);
  }else if( (p->flags & (MEM_IntReal))!=0 ){
    printf(" ir:%lld", p->u.i);
  }else if( p->flags & MEM_Int ){
    printf(" i:%lld", p->u.i);
#ifndef SQLITE_OMIT_FLOATING_POINT
  }else if( p->flags & MEM_Real ){
    printf(" r:%g", p->u.r);
    printf(" r:%.17g", p->u.r);
#endif
  }else if( sqlite3VdbeMemIsRowSet(p) ){
    printf(" (rowset)");
  }else{
    StrAccum acc;
    char zBuf[200];
    sqlite3VdbeMemPrettyPrint(p, zBuf);
    printf(" %s", zBuf);
    char zBuf[1000];
    sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
    sqlite3VdbeMemPrettyPrint(p, &acc);
    printf(" %s", sqlite3StrAccumFinish(&acc));
  }
  if( p->flags & MEM_Subtype ) printf(" subtype=0x%02x", p->eSubtype);
}
static void registerTrace(int iReg, Mem *p){
  printf("REG[%d] = ", iReg);
  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.
*/
void sqlite3VdbeRegisterDump(Vdbe *v){
  int i;
  for(i=1; i<v->nMem; i++) registerTrace(i, v->aMem+i);
}
#endif /* SQLITE_DEBUG */


#ifdef SQLITE_DEBUG
#  define REGISTER_TRACE(R,M) if(db->flags&SQLITE_VdbeTrace)registerTrace(R,M)
#else
#  define REGISTER_TRACE(R,M)
#endif


#ifdef VDBE_PROFILE

/* 
** hwtime.h contains inline assembler code for implementing 
** high-performance timing routines.
*/
#include "hwtime.h"

#endif

#ifndef NDEBUG
/*
** This function is only called from within an assert() expression. It
** checks that the sqlite3.nTransaction variable is correctly set to
** the number of non-transaction savepoints currently in the 
575
576
577
578
579
580
581




































582
583
584
585
586
587
588
589
590
591
592

593
594
595
596

597
598
599
600
601
602
603

604
605

606
607
608
609
610
611
612
613


614
615
616
617
618













619
620
621
622
623
624


625
626
627
628
629
630

631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










-
+

-
-

+






-
+

-
+






-
-
+
+



-
-
+
+
+
+
+
+
+
+
+
+
+
+
+






+
+



-

-
+

-
-
-
-
-
-
-
-
-







    return out2PrereleaseWithClear(pOut);
  }else{
    pOut->flags = MEM_Int;
    return pOut;
  }
}

/*
** Compute a bloom filter hash using pOp->p4.i registers from aMem[] beginning
** with pOp->p3.  Return the hash.
*/
static u64 filterHash(const Mem *aMem, const Op *pOp){
  int i, mx;
  u64 h = 0;

  assert( pOp->p4type==P4_INT32 );
  for(i=pOp->p3, mx=i+pOp->p4.i; i<mx; i++){
    const Mem *p = &aMem[i];
    if( p->flags & (MEM_Int|MEM_IntReal) ){
      h += p->u.i;
    }else if( p->flags & MEM_Real ){
      h += sqlite3VdbeIntValue(p);
    }else if( p->flags & (MEM_Str|MEM_Blob) ){
      h += p->n;
      if( p->flags & MEM_Zero ) h += p->u.nZero;
    }
  }
  return h;
}

/*
** Return the symbolic name for the data type of a pMem
*/
static const char *vdbeMemTypeName(Mem *pMem){
  static const char *azTypes[] = {
      /* SQLITE_INTEGER */ "INT",
      /* SQLITE_FLOAT   */ "REAL",
      /* SQLITE_TEXT    */ "TEXT",
      /* SQLITE_BLOB    */ "BLOB",
      /* SQLITE_NULL    */ "NULL"
  };
  return azTypes[sqlite3_value_type(pMem)-1];
}

/*
** Execute as much of a VDBE program as we can.
** This is the core of sqlite3_step().  
*/
int sqlite3VdbeExec(
  Vdbe *p                    /* The VDBE */
){
  Op *aOp = p->aOp;          /* Copy of p->aOp */
  Op *pOp = aOp;             /* Current operation */
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
#ifdef SQLITE_DEBUG
  Op *pOrigOp;               /* Value of pOp at the top of the loop */
#endif
#ifdef SQLITE_DEBUG
  int nExtraDelete = 0;      /* Verifies FORDELETE and AUXDELETE flags */
  u8 iCompareIsInit = 0;     /* iCompare is initialized */
#endif
  int rc = SQLITE_OK;        /* Value to return */
  sqlite3 *db = p->db;       /* The database */
  u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */
  u8 encoding = ENC(db);     /* The database encoding */
  int iCompare = 0;          /* Result of last comparison */
  unsigned nVmStep = 0;      /* Number of virtual machine steps */
  u64 nVmStep = 0;           /* Number of virtual machine steps */
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  unsigned nProgressLimit;   /* Invoke xProgress() when nVmStep reaches this */
  u64 nProgressLimit;        /* Invoke xProgress() when nVmStep reaches this */
#endif
  Mem *aMem = p->aMem;       /* Copy of p->aMem */
  Mem *pIn1 = 0;             /* 1st input operand */
  Mem *pIn2 = 0;             /* 2nd input operand */
  Mem *pIn3 = 0;             /* 3rd input operand */
  Mem *pOut = 0;             /* Output operand */
#ifdef VDBE_PROFILE
  u64 start;                 /* CPU clock count at start of opcode */
#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE)
  u64 *pnCycle = 0;
#endif
  /*** INSERT STACK UNION HERE ***/

  assert( p->magic==VDBE_MAGIC_RUN );  /* sqlite3_step() verifies this */
  sqlite3VdbeEnter(p);
  assert( p->eVdbeState==VDBE_RUN_STATE );  /* sqlite3_step() verifies this */
  if( DbMaskNonZero(p->lockMask) ){
    sqlite3VdbeEnter(p);
  }
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  if( db->xProgress ){
    u32 iPrior = p->aCounter[SQLITE_STMTSTATUS_VM_STEP];
    assert( 0 < db->nProgressOps );
    nProgressLimit = db->nProgressOps - (iPrior % db->nProgressOps);
  }else{
    nProgressLimit = LARGEST_UINT64;
  }
#endif
  if( p->rc==SQLITE_NOMEM ){
    /* This happens if a malloc() inside a call to sqlite3_column_text() or
    ** sqlite3_column_text16() failed.  */
    goto no_mem;
  }
  assert( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_BUSY );
  testcase( p->rc!=SQLITE_OK );
  p->rc = SQLITE_OK;
  assert( p->bIsReader || p->readOnly!=0 );
  p->iCurrentTime = 0;
  assert( p->explain==0 );
  p->pResultSet = 0;
  db->busyHandler.nBusy = 0;
  if( db->u1.isInterrupted ) goto abort_due_to_interrupt;
  if( AtomicLoad(&db->u1.isInterrupted) ) goto abort_due_to_interrupt;
  sqlite3VdbeIOTraceSql(p);
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  if( db->xProgress ){
    u32 iPrior = p->aCounter[SQLITE_STMTSTATUS_VM_STEP];
    assert( 0 < db->nProgressOps );
    nProgressLimit = db->nProgressOps - (iPrior % db->nProgressOps);
  }else{
    nProgressLimit = 0xffffffff;
  }
#endif
#ifdef SQLITE_DEBUG
  sqlite3BeginBenignMalloc();
  if( p->pc==0
   && (p->db->flags & (SQLITE_VdbeListing|SQLITE_VdbeEQP|SQLITE_VdbeTrace))!=0
  ){
    int i;
    int once = 1;
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
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







+
+
+
+
-
-
-
-
+
+
+
+
-
-







+







#endif
  for(pOp=&aOp[p->pc]; 1; pOp++){
    /* Errors are detected by individual opcodes, with an immediate
    ** jumps to abort_due_to_error. */
    assert( rc==SQLITE_OK );

    assert( pOp>=aOp && pOp<&aOp[p->nOp]);
    nVmStep++;
#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE)
    pOp->nExec++;
    pnCycle = &pOp->nCycle;
#ifdef VDBE_PROFILE
    start = sqlite3NProfileCnt ? sqlite3NProfileCnt : sqlite3Hwtime();
#endif
    nVmStep++;
# ifdef VDBE_PROFILE
    if( sqlite3NProfileCnt==0 )
# endif
      *pnCycle -= sqlite3Hwtime();
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
    if( p->anExec ) p->anExec[(int)(pOp-aOp)]++;
#endif

    /* Only allow tracing if SQLITE_DEBUG is defined.
    */
#ifdef SQLITE_DEBUG
    if( db->flags & SQLITE_VdbeTrace ){
      sqlite3VdbePrintOp(stdout, (int)(pOp - aOp), pOp);
      test_trace_breakpoint((int)(pOp - aOp),pOp,p);
    }
#endif
      

    /* Check to see if we need to simulate an interrupt.  This only happens
    ** if we have a special test build.
    */
733
734
735
736
737
738
739
740

741
742
743
744
745
746
747
862
863
864
865
866
867
868

869
870
871
872
873
874
875
876







-
+







      if( (opProperty & OPFLG_OUT3)!=0 ){
        assert( pOp->p3>0 );
        assert( pOp->p3<=(p->nMem+1 - p->nCursor) );
        memAboutToChange(p, &aMem[pOp->p3]);
      }
    }
#endif
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
#ifdef SQLITE_DEBUG
    pOrigOp = pOp;
#endif
  
    switch( pOp->opcode ){

/*****************************************************************************
** What follows is a massive switch statement where each case implements a
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
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950

951
952
953
954
955
956
957
958

959
960

961
962
963
964
965
966
967
968
969
970







+
+
+
+
+
+
+
+
+
+
+
+
+
+














-
+







-
+

-
+

+







**
** The P1 parameter is not actually used by this opcode.  However, it
** is sometimes set to 1 instead of 0 as a hint to the command-line shell
** that this Goto is the bottom of a loop and that the lines from P2 down
** to the current line should be indented for EXPLAIN output.
*/
case OP_Goto: {             /* jump */

#ifdef SQLITE_DEBUG
  /* In debuggging mode, when the p5 flags is set on an OP_Goto, that
  ** means we should really jump back to the preceeding OP_ReleaseReg
  ** instruction. */
  if( pOp->p5 ){
    assert( pOp->p2 < (int)(pOp - aOp) );
    assert( pOp->p2 > 1 );
    pOp = &aOp[pOp->p2 - 2];
    assert( pOp[1].opcode==OP_ReleaseReg );
    goto check_for_interrupt;
  }
#endif

jump_to_p2_and_check_for_interrupt:
  pOp = &aOp[pOp->p2 - 1];

  /* Opcodes that are used as the bottom of a loop (OP_Next, OP_Prev,
  ** OP_VNext, or OP_SorterNext) all jump here upon
  ** completion.  Check to see if sqlite3_interrupt() has been called
  ** or if the progress callback needs to be invoked. 
  **
  ** This code uses unstructured "goto" statements and does not look clean.
  ** But that is not due to sloppy coding habits. The code is written this
  ** way for performance, to avoid having to run the interrupt and progress
  ** checks on every opcode.  This helps sqlite3_step() to run about 1.5%
  ** faster according to "valgrind --tool=cachegrind" */
check_for_interrupt:
  if( db->u1.isInterrupted ) goto abort_due_to_interrupt;
  if( AtomicLoad(&db->u1.isInterrupted) ) goto abort_due_to_interrupt;
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  /* Call the progress callback if it is configured and the required number
  ** of VDBE ops have been executed (either since this invocation of
  ** sqlite3VdbeExec() or since last time the progress callback was called).
  ** If the progress callback returns non-zero, exit the virtual machine with
  ** a return code SQLITE_ABORT.
  */
  if( nVmStep>=nProgressLimit && db->xProgress!=0 ){
  while( nVmStep>=nProgressLimit && db->xProgress!=0 ){
    assert( db->nProgressOps!=0 );
    nProgressLimit = nVmStep + db->nProgressOps - (nVmStep%db->nProgressOps);
    nProgressLimit += db->nProgressOps;
    if( db->xProgress(db->pProgressArg) ){
      nProgressLimit = LARGEST_UINT64;
      rc = SQLITE_INTERRUPT;
      goto abort_due_to_error;
    }
  }
#endif
  
  break;
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
979
980
981
982
983
984
985




986


987
988

989
990


991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012


1013
1014
1015

1016
1017
1018
1019
1020
1021
1022
1023
1024
1025







-
-
-
-
+
-
-


-
+

-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
-
+
+
+
-
+
+
+







  assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) );
  pIn1 = &aMem[pOp->p1];
  assert( VdbeMemDynamic(pIn1)==0 );
  memAboutToChange(p, pIn1);
  pIn1->flags = MEM_Int;
  pIn1->u.i = (int)(pOp-aOp);
  REGISTER_TRACE(pOp->p1, pIn1);

  /* Most jump operations do a goto to this spot in order to update
  ** the pOp pointer. */
jump_to_p2:
  goto jump_to_p2_and_check_for_interrupt;
  pOp = &aOp[pOp->p2 - 1];
  break;
}

/* Opcode:  Return P1 * * * *
/* Opcode:  Return P1 P2 P3 * *
**
** Jump to the next instruction after the address in register P1.  After
** the jump, register P1 becomes undefined.
** Jump to the address stored in register P1.  If P1 is a return address
** register, then this accomplishes a return from a subroutine.
**
** If P3 is 1, then the jump is only taken if register P1 holds an integer
** values, otherwise execution falls through to the next opcode, and the
** OP_Return becomes a no-op. If P3 is 0, then register P1 must hold an
** integer or else an assert() is raised.  P3 should be set to 1 when
** this opcode is used in combination with OP_BeginSubrtn, and set to 0
** otherwise.
**
** The value in register P1 is unchanged by this opcode.
**
** P2 is not used by the byte-code engine.  However, if P2 is positive
** and also less than the current address, then the "EXPLAIN" output
** formatter in the CLI will indent all opcodes from the P2 opcode up
** to be not including the current Return.   P2 should be the first opcode
** in the subroutine from which this opcode is returning.  Thus the P2
** value is a byte-code indentation hint.  See tag-20220407a in
** wherecode.c and shell.c.
*/
case OP_Return: {           /* in1 */
  pIn1 = &aMem[pOp->p1];
  assert( pIn1->flags==MEM_Int );
  pOp = &aOp[pIn1->u.i];
  if( pIn1->flags & MEM_Int ){
    if( pOp->p3 ){ VdbeBranchTaken(1, 2); }
    pOp = &aOp[pIn1->u.i];
  pIn1->flags = MEM_Undefined;
  }else if( ALWAYS(pOp->p3) ){
    VdbeBranchTaken(0, 2);
  }
  break;
}

/* Opcode: InitCoroutine P1 P2 P3 * *
**
** Set up register P1 so that it will Yield to the coroutine
** located at address P3.
875
876
877
878
879
880
881




882




883
884
885
886
887
888
889
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044

1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055







+
+
+
+
-
+
+
+
+







  assert( pOp->p1>0 &&  pOp->p1<=(p->nMem+1 - p->nCursor) );
  assert( pOp->p2>=0 && pOp->p2<p->nOp );
  assert( pOp->p3>=0 && pOp->p3<p->nOp );
  pOut = &aMem[pOp->p1];
  assert( !VdbeMemDynamic(pOut) );
  pOut->u.i = pOp->p3 - 1;
  pOut->flags = MEM_Int;
  if( pOp->p2==0 ) break;

  /* Most jump operations do a goto to this spot in order to update
  ** the pOp pointer. */
  if( pOp->p2 ) goto jump_to_p2;
jump_to_p2:
  assert( pOp->p2>0 );       /* There are never any jumps to instruction 0 */
  assert( pOp->p2<p->nOp );  /* Jumps must be in range */
  pOp = &aOp[pOp->p2 - 1];
  break;
}

/* Opcode:  EndCoroutine P1 * * * *
**
** The instruction at the address in register P1 is a Yield.
** Jump to the P2 parameter of that Yield.
940
941
942
943
944
945
946

947
948
949
950
951
952
953
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120







+







case OP_HaltIfNull: {      /* in3 */
  pIn3 = &aMem[pOp->p3];
#ifdef SQLITE_DEBUG
  if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); }
#endif
  if( (pIn3->flags & MEM_Null)==0 ) break;
  /* Fall through into OP_Halt */
  /* no break */ deliberate_fall_through
}

/* Opcode:  Halt P1 P2 * P4 P5
**
** Exit immediately.  All open cursors, etc are closed
** automatically.
**
976
977
978
979
980
981
982
983
984
985
986






987

988
989
990
991
992
993
994
1143
1144
1145
1146
1147
1148
1149

1150
1151
1152
1153
1154
1155
1156
1157
1158

1159
1160
1161
1162
1163
1164
1165
1166







-



+
+
+
+
+
+
-
+







** every program.  So a jump past the last instruction of the program
** is the same as executing Halt.
*/
case OP_Halt: {
  VdbeFrame *pFrame;
  int pcx;

  pcx = (int)(pOp - aOp);
#ifdef SQLITE_DEBUG
  if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); }
#endif

  /* A deliberately coded "OP_Halt SQLITE_INTERNAL * * * *" opcode indicates
  ** something is wrong with the code generator.  Raise and assertion in order
  ** to bring this to the attention of fuzzers and other testing tools. */
  assert( pOp->p1!=SQLITE_INTERNAL );

  if( pOp->p1==SQLITE_OK && p->pFrame ){
  if( p->pFrame && pOp->p1==SQLITE_OK ){
    /* Halt the sub-program. Return control to the parent frame. */
    pFrame = p->pFrame;
    p->pFrame = pFrame->pParent;
    p->nFrame--;
    sqlite3VdbeSetChanges(db, p->nChange);
    pcx = sqlite3VdbeFrameRestore(pFrame);
    if( pOp->p2==OE_Ignore ){
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
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







-
















+







    aOp = p->aOp;
    aMem = p->aMem;
    pOp = &aOp[pcx];
    break;
  }
  p->rc = pOp->p1;
  p->errorAction = (u8)pOp->p2;
  p->pc = pcx;
  assert( pOp->p5<=4 );
  if( p->rc ){
    if( pOp->p5 ){
      static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK",
                                             "FOREIGN KEY" };
      testcase( pOp->p5==1 );
      testcase( pOp->p5==2 );
      testcase( pOp->p5==3 );
      testcase( pOp->p5==4 );
      sqlite3VdbeError(p, "%s constraint failed", azType[pOp->p5-1]);
      if( pOp->p4.z ){
        p->zErrMsg = sqlite3MPrintf(db, "%z: %s", p->zErrMsg, pOp->p4.z);
      }
    }else{
      sqlite3VdbeError(p, "%s", pOp->p4.z);
    }
    pcx = (int)(pOp - aOp);
    sqlite3_log(pOp->p1, "abort at %d in [%s]: %s", pcx, p->zSql, p->zErrMsg);
  }
  rc = sqlite3VdbeHalt(p);
  assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR );
  if( rc==SQLITE_BUSY ){
    p->rc = SQLITE_BUSY;
  }else{
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
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
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296







-






+












-




+


+







** into a String opcode before it is executed for the first time.  During
** this transformation, the length of string P4 is computed and stored
** as the P1 parameter.
*/
case OP_String8: {         /* same as TK_STRING, out2 */
  assert( pOp->p4.z!=0 );
  pOut = out2Prerelease(p, pOp);
  pOp->opcode = OP_String;
  pOp->p1 = sqlite3Strlen30(pOp->p4.z);

#ifndef SQLITE_OMIT_UTF16
  if( encoding!=SQLITE_UTF8 ){
    rc = sqlite3VdbeMemSetStr(pOut, pOp->p4.z, -1, SQLITE_UTF8, SQLITE_STATIC);
    assert( rc==SQLITE_OK || rc==SQLITE_TOOBIG );
    if( rc ) goto too_big;
    if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem;
    assert( pOut->szMalloc>0 && pOut->zMalloc==pOut->z );
    assert( VdbeMemDynamic(pOut)==0 );
    pOut->szMalloc = 0;
    pOut->flags |= MEM_Static;
    if( pOp->p4type==P4_DYNAMIC ){
      sqlite3DbFree(db, pOp->p4.z);
    }
    pOp->p4type = P4_DYNAMIC;
    pOp->p4.z = pOut->z;
    pOp->p1 = pOut->n;
  }
  testcase( rc==SQLITE_TOOBIG );
#endif
  if( pOp->p1>db->aLimit[SQLITE_LIMIT_LENGTH] ){
    goto too_big;
  }
  pOp->opcode = OP_String;
  assert( rc==SQLITE_OK );
  /* Fall through to the next case, OP_String */
  /* no break */ deliberate_fall_through
}
  
/* Opcode: String P1 P2 P3 P4 P5
** Synopsis: r[P2]='P4' (len=P1)
**
** The string value P4 of length P1 (bytes) is stored in register P2.
**
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
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+












+







    assert( pIn3->flags & MEM_Int );
    if( pIn3->u.i==pOp->p5 ) pOut->flags = MEM_Blob|MEM_Static|MEM_Term;
  }
#endif
  break;
}

/* Opcode: BeginSubrtn * P2 * * *
** Synopsis: r[P2]=NULL
**
** Mark the beginning of a subroutine that can be entered in-line
** or that can be called using OP_Gosub.  The subroutine should
** be terminated by an OP_Return instruction that has a P1 operand that
** is the same as the P2 operand to this opcode and that has P3 set to 1.
** If the subroutine is entered in-line, then the OP_Return will simply
** fall through.  But if the subroutine is entered using OP_Gosub, then
** the OP_Return will jump back to the first instruction after the OP_Gosub.
**
** This routine works by loading a NULL into the P2 register.  When the
** return address register contains a NULL, the OP_Return instruction is
** a no-op that simply falls through to the next instruction (assuming that
** the OP_Return opcode has a P3 value of 1).  Thus if the subroutine is
** entered in-line, then the OP_Return will cause in-line execution to
** continue.  But if the subroutine is entered via OP_Gosub, then the
** OP_Return will cause a return to the address following the OP_Gosub.
**
** This opcode is identical to OP_Null.  It has a different name
** only to make the byte code easier to read and verify.
*/
/* Opcode: Null P1 P2 P3 * *
** Synopsis: r[P2..P3]=NULL
**
** Write a NULL into registers P2.  If P3 greater than P2, then also write
** NULL into register P3 and every register in between P2 and P3.  If P3
** is less than P2 (typically P3 is zero) then only register P2 is
** set to NULL.
**
** If the P1 value is non-zero, then also set the MEM_Cleared flag so that
** NULL values will not compare equal even if SQLITE_NULLEQ is set on
** OP_Ne or OP_Eq.
*/
case OP_BeginSubrtn:
case OP_Null: {           /* out2 */
  int cnt;
  u16 nullFlag;
  pOut = out2Prerelease(p, pOp);
  cnt = pOp->p3-pOp->p2;
  assert( pOp->p3<=(p->nMem+1 - p->nCursor) );
  pOut->flags = nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null;
1196
1197
1198
1199
1200
1201
1202
1203


1204
1205
1206
1207




1208


1209
1210
1211
1212
1213
1214
1215
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







-
+
+




+
+
+
+
-
+
+







  break;
}

/* Opcode: Blob P1 P2 * P4 *
** Synopsis: r[P2]=P4 (len=P1)
**
** P4 points to a blob of data P1 bytes long.  Store this
** blob in register P2.
** blob in register P2.  If P4 is a NULL pointer, then construct
** a zero-filled blob that is P1 bytes long in P2.
*/
case OP_Blob: {                /* out2 */
  assert( pOp->p1 <= SQLITE_MAX_LENGTH );
  pOut = out2Prerelease(p, pOp);
  if( pOp->p4.z==0 ){
    sqlite3VdbeMemSetZeroBlob(pOut, pOp->p1);
    if( sqlite3VdbeMemExpandBlob(pOut) ) goto no_mem;
  }else{
  sqlite3VdbeMemSetStr(pOut, pOp->p4.z, pOp->p1, 0, 0);
    sqlite3VdbeMemSetStr(pOut, pOp->p4.z, pOp->p1, 0, 0);
  }
  pOut->enc = encoding;
  UPDATE_MAX_BLOBSIZE(pOut);
  break;
}

/* Opcode: Variable P1 P2 * P4 *
** Synopsis: r[P2]=parameter(P1,P4)
1225
1226
1227
1228
1229
1230
1231

1232



1233
1234
1235
1236
1237
1238
1239
1427
1428
1429
1430
1431
1432
1433
1434

1435
1436
1437
1438
1439
1440
1441
1442
1443
1444







+
-
+
+
+







  assert( pOp->p1>0 && pOp->p1<=p->nVar );
  assert( pOp->p4.z==0 || pOp->p4.z==sqlite3VListNumToName(p->pVList,pOp->p1) );
  pVar = &p->aVar[pOp->p1 - 1];
  if( sqlite3VdbeMemTooBig(pVar) ){
    goto too_big;
  }
  pOut = &aMem[pOp->p2];
  if( VdbeMemDynamic(pOut) ) sqlite3VdbeMemSetNull(pOut);
  sqlite3VdbeMemShallowCopy(pOut, pVar, MEM_Static);
  memcpy(pOut, pVar, MEMCELLSIZE);
  pOut->flags &= ~(MEM_Dyn|MEM_Ephem);
  pOut->flags |= MEM_Static|MEM_FromBind;
  UPDATE_MAX_BLOBSIZE(pOut);
  break;
}

/* Opcode: Move P1 P2 P3 * *
** Synopsis: r[P2@P3]=r[P1@P3]
**
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
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296



1297
1298
1299
1300
1301
1302
1303
1464
1465
1466
1467
1468
1469
1470


1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487

1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521







-
-
+
+
+
+
+
+
+










-
+



+
+
+
+
+















+
+
+







  do{
    assert( pOut<=&aMem[(p->nMem+1 - p->nCursor)] );
    assert( pIn1<=&aMem[(p->nMem+1 - p->nCursor)] );
    assert( memIsValid(pIn1) );
    memAboutToChange(p, pOut);
    sqlite3VdbeMemMove(pOut, pIn1);
#ifdef SQLITE_DEBUG
    if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrom<pOut ){
      pOut->pScopyFrom += pOp->p2 - p1;
    pIn1->pScopyFrom = 0;
    { int i;
      for(i=1; i<p->nMem; i++){
        if( aMem[i].pScopyFrom==pIn1 ){
          aMem[i].pScopyFrom = pOut;
        }
      }
    }
#endif
    Deephemeralize(pOut);
    REGISTER_TRACE(p2++, pOut);
    pIn1++;
    pOut++;
  }while( --n );
  break;
}

/* Opcode: Copy P1 P2 P3 * *
/* Opcode: Copy P1 P2 P3 * P5
** Synopsis: r[P2@P3+1]=r[P1@P3+1]
**
** Make a copy of registers P1..P1+P3 into registers P2..P2+P3.
**
** If the 0x0002 bit of P5 is set then also clear the MEM_Subtype flag in the
** destination.  The 0x0001 bit of P5 indicates that this Copy opcode cannot
** be merged.  The 0x0001 bit is used by the query planner and does not
** come into play during query execution.
**
** This instruction makes a deep copy of the value.  A duplicate
** is made of any string or blob constant.  See also OP_SCopy.
*/
case OP_Copy: {
  int n;

  n = pOp->p3;
  pIn1 = &aMem[pOp->p1];
  pOut = &aMem[pOp->p2];
  assert( pOut!=pIn1 );
  while( 1 ){
    memAboutToChange(p, pOut);
    sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
    Deephemeralize(pOut);
    if( (pOut->flags & MEM_Subtype)!=0 &&  (pOp->p5 & 0x0002)!=0 ){
      pOut->flags &= ~MEM_Subtype;
    }
#ifdef SQLITE_DEBUG
    pOut->pScopyFrom = 0;
#endif
    REGISTER_TRACE(pOp->p2+pOp->p3-n, pOut);
    if( (n--)==0 ) break;
    pOut++;
    pIn1++;
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
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448



1449
1450
1451
1452

1453



1454

1455
1456
1457




1458
1459
1460











1461
1462
1463
1464
1465
1466
1467
1468
1469
1470


1471
1472



1473
1474
1475
1476
1477
1478
1479
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594


1595

1596
1597
1598









































1599
1600
1601

1602







1603
1604
1605
1606






1607
1608
1609
1610
1611
1612
1613
1614


1615
1616
1617
1618

1619
1620



1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639

1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651

1652
1653
1654
1655
1656
1657
1658
1659



1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+











-
-

-
+


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

+
+
-
+
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
+
+
+

-
+

-
-
-



















-
+
+
+




+

+
+
+
-
+



+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+










+
+


+
+
+







case OP_IntCopy: {            /* out2 */
  pIn1 = &aMem[pOp->p1];
  assert( (pIn1->flags & MEM_Int)!=0 );
  pOut = &aMem[pOp->p2];
  sqlite3VdbeMemSetInt64(pOut, pIn1->u.i);
  break;
}

/* Opcode: FkCheck * * * * *
**
** Halt with an SQLITE_CONSTRAINT error if there are any unresolved
** foreign key constraint violations.  If there are no foreign key
** constraint violations, this is a no-op.
**
** FK constraint violations are also checked when the prepared statement
** exits.  This opcode is used to raise foreign key constraint errors prior
** to returning results such as a row change count or the result of a 
** RETURNING clause.
*/
case OP_FkCheck: {
  if( (rc = sqlite3VdbeCheckFk(p,0))!=SQLITE_OK ){
    goto abort_due_to_error;
  }
  break;
}

/* Opcode: ResultRow P1 P2 * * *
** Synopsis: output=r[P1@P2]
**
** The registers P1 through P1+P2-1 contain a single row of
** results. This opcode causes the sqlite3_step() call to terminate
** with an SQLITE_ROW return code and it sets up the sqlite3_stmt
** 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 );

#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  /* Run the progress counter just before returning.
  */
  if( db->xProgress!=0
   && nVmStep>=nProgressLimit 
   && db->xProgress(db->pProgressArg)!=0
  ){
    rc = SQLITE_INTERRUPT;
    goto abort_due_to_error;
  }
#endif

  /* If this statement has violated immediate foreign key constraints, do
  ** not return the number of rows modified. And do not RELEASE the statement
  ** transaction. It needs to be rolled back.  */
  if( SQLITE_OK!=(rc = sqlite3VdbeCheckFk(p, 0)) ){
    assert( db->flags&SQLITE_CountRows );
    assert( p->usesStmtJournal );
    goto abort_due_to_error;
  }

  /* If the SQLITE_CountRows flag is set in sqlite3.flags mask, then 
  ** DML statements invoke this opcode to return the number of rows 
  ** modified to the user. This is the only way that a VM that
  ** opens a statement transaction may invoke this opcode.
  **
  ** In case this is such a statement, close any statement transaction
  ** opened by this VM before returning control to the user. This is to
  ** ensure that statement-transactions are always nested, not overlapping.
  ** If the open statement-transaction is not closed here, then the user
  ** may step another VM that opens its own statement transaction. This
  ** may lead to overlapping statement transactions.
  **
  ** The statement transaction is never a top-level transaction.  Hence
  ** the RELEASE call below can never fail.
  */
  assert( p->iStatement==0 || db->flags&SQLITE_CountRows );
  rc = sqlite3VdbeCloseStatement(p, SAVEPOINT_RELEASE);
  assert( rc==SQLITE_OK );

  /* Invalidate all ephemeral cursor row caches */
  p->cacheCtr = (p->cacheCtr + 2)|1;
  p->pResultRow = &aMem[pOp->p1];
#ifdef SQLITE_DEBUG

  {
  /* Make sure the results of the current row are \000 terminated
  ** and have an assigned type.  The results are de-ephemeralized as
  ** a side effect.
  */
  pMem = p->pResultSet = &aMem[pOp->p1];
  for(i=0; i<pOp->p2; i++){
    assert( memIsValid(&pMem[i]) );
    Mem *pMem = p->pResultRow;
    int i;
    for(i=0; i<pOp->p2; i++){
      assert( memIsValid(&pMem[i]) );
    Deephemeralize(&pMem[i]);
    assert( (pMem[i].flags & MEM_Ephem)==0
            || (pMem[i].flags & (MEM_Str|MEM_Blob))==0 );
    sqlite3VdbeMemNulTerminate(&pMem[i]);
    REGISTER_TRACE(pOp->p1+i, &pMem[i]);
  }
      REGISTER_TRACE(pOp->p1+i, &pMem[i]);
      /* The registers in the result will not be used again when the
      ** prepared statement restarts.  This is because sqlite3_column()
      ** APIs might have caused type conversions of made other changes to
      ** the register values.  Therefore, we can go ahead and break any
      ** OP_SCopy dependencies. */
      pMem[i].pScopyFrom = 0;
    }
  if( db->mallocFailed ) goto no_mem;

  }
#endif
  if( db->mallocFailed ) goto no_mem;
  if( db->mTrace & SQLITE_TRACE_ROW ){
    db->xTrace(SQLITE_TRACE_ROW, db->pTraceArg, p, 0);
    db->trace.xV2(SQLITE_TRACE_ROW, db->pTraceArg, p, 0);
  }

  /* Return SQLITE_ROW
  */
  p->pc = (int)(pOp - aOp) + 1;
  rc = SQLITE_ROW;
  goto vdbe_return;
}

/* Opcode: Concat P1 P2 P3 * *
** Synopsis: r[P3]=r[P2]+r[P1]
**
** Add the text in register P1 onto the end of the text in
** register P2 and store the result in register P3.
** If either the P1 or P2 text are NULL then store NULL in P3.
**
**   P3 = P2 || P1
**
** It is illegal for P1 and P3 to be the same register. Sometimes,
** if P3 is the same register as P2, the implementation is able
** to avoid a memcpy().
*/
case OP_Concat: {           /* same as TK_CONCAT, in1, in2, out3 */
  i64 nByte;
  i64 nByte;          /* Total size of the output string or blob */
  u16 flags1;         /* Initial flags for P1 */
  u16 flags2;         /* Initial flags for P2 */

  pIn1 = &aMem[pOp->p1];
  pIn2 = &aMem[pOp->p2];
  pOut = &aMem[pOp->p3];
  testcase( pOut==pIn2 );
  assert( pIn1!=pOut );
  flags1 = pIn1->flags;
  testcase( flags1 & MEM_Null );
  testcase( pIn2->flags & MEM_Null );
  if( (pIn1->flags | pIn2->flags) & MEM_Null ){
  if( (flags1 | pIn2->flags) & MEM_Null ){
    sqlite3VdbeMemSetNull(pOut);
    break;
  }
  if( (flags1 & (MEM_Str|MEM_Blob))==0 ){
    if( sqlite3VdbeMemStringify(pIn1,encoding,0) ) goto no_mem;
    flags1 = pIn1->flags & ~MEM_Str;
  }else if( (flags1 & MEM_Zero)!=0 ){
  if( ExpandBlob(pIn1) || ExpandBlob(pIn2) ) goto no_mem;
  Stringify(pIn1, encoding);
  Stringify(pIn2, encoding);
    if( sqlite3VdbeMemExpandBlob(pIn1) ) goto no_mem;
    flags1 = pIn1->flags & ~MEM_Str;
  }
  flags2 = pIn2->flags;
  if( (flags2 & (MEM_Str|MEM_Blob))==0 ){
    if( sqlite3VdbeMemStringify(pIn2,encoding,0) ) goto no_mem;
    flags2 = pIn2->flags & ~MEM_Str;
  }else if( (flags2 & MEM_Zero)!=0 ){
    if( sqlite3VdbeMemExpandBlob(pIn2) ) goto no_mem;
    flags2 = pIn2->flags & ~MEM_Str;
  }
  nByte = pIn1->n + pIn2->n;
  if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
    goto too_big;
  }
  if( sqlite3VdbeMemGrow(pOut, (int)nByte+2, pOut==pIn2) ){
    goto no_mem;
  }
  MemSetTypeFlag(pOut, MEM_Str);
  if( pOut!=pIn2 ){
    memcpy(pOut->z, pIn2->z, pIn2->n);
    assert( (pIn2->flags & MEM_Dyn) == (flags2 & MEM_Dyn) );
    pIn2->flags = flags2;
  }
  memcpy(&pOut->z[pIn2->n], pIn1->z, pIn1->n);
  assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) );
  pIn1->flags = flags1;
  if( encoding>SQLITE_UTF8 ) nByte &= ~1;
  pOut->z[nByte]=0;
  pOut->z[nByte+1] = 0;
  pOut->flags |= MEM_Term;
  pOut->n = (int)nByte;
  pOut->enc = encoding;
  UPDATE_MAX_BLOBSIZE(pOut);
  break;
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
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
1574
1575
1576
1577
1578
1579
1580
1581
1582


1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1733
1734
1735
1736
1737
1738
1739


1740
1741
1742
1743
1744
1745
1746
1747

1748
1749

1750
1751

1752
1753
1754
1755

1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774

1775
1776
1777

1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794


1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811



1812
1813
1814
1815
1816
1817
1818







-
-








-
+

-
+

-

+


-



















-
+


-
+
+
+














-
-
+
+















-
-
-







** If either operand is NULL, the result is NULL.
*/
case OP_Add:                   /* same as TK_PLUS, in1, in2, out3 */
case OP_Subtract:              /* same as TK_MINUS, in1, in2, out3 */
case OP_Multiply:              /* same as TK_STAR, in1, in2, out3 */
case OP_Divide:                /* same as TK_SLASH, in1, in2, out3 */
case OP_Remainder: {           /* same as TK_REM, in1, in2, out3 */
  char bIntint;   /* Started out as two integer operands */
  u16 flags;      /* Combined MEM_* flags from both inputs */
  u16 type1;      /* Numeric type of left operand */
  u16 type2;      /* Numeric type of right operand */
  i64 iA;         /* Integer value of left operand */
  i64 iB;         /* Integer value of right operand */
  double rA;      /* Real value of left operand */
  double rB;      /* Real value of right operand */

  pIn1 = &aMem[pOp->p1];
  type1 = numericType(pIn1);
  type1 = pIn1->flags;
  pIn2 = &aMem[pOp->p2];
  type2 = numericType(pIn2);
  type2 = pIn2->flags;
  pOut = &aMem[pOp->p3];
  flags = pIn1->flags | pIn2->flags;
  if( (type1 & type2 & MEM_Int)!=0 ){
int_math:
    iA = pIn1->u.i;
    iB = pIn2->u.i;
    bIntint = 1;
    switch( pOp->opcode ){
      case OP_Add:       if( sqlite3AddInt64(&iB,iA) ) goto fp_math;  break;
      case OP_Subtract:  if( sqlite3SubInt64(&iB,iA) ) goto fp_math;  break;
      case OP_Multiply:  if( sqlite3MulInt64(&iB,iA) ) goto fp_math;  break;
      case OP_Divide: {
        if( iA==0 ) goto arithmetic_result_is_null;
        if( iA==-1 && iB==SMALLEST_INT64 ) goto fp_math;
        iB /= iA;
        break;
      }
      default: {
        if( iA==0 ) goto arithmetic_result_is_null;
        if( iA==-1 ) iA = 1;
        iB %= iA;
        break;
      }
    }
    pOut->u.i = iB;
    MemSetTypeFlag(pOut, MEM_Int);
  }else if( (flags & MEM_Null)!=0 ){
  }else if( ((type1 | type2) & MEM_Null)!=0 ){
    goto arithmetic_result_is_null;
  }else{
    bIntint = 0;
    type1 = numericType(pIn1);
    type2 = numericType(pIn2);
    if( (type1 & type2 & MEM_Int)!=0 ) goto int_math;
fp_math:
    rA = sqlite3VdbeRealValue(pIn1);
    rB = sqlite3VdbeRealValue(pIn2);
    switch( pOp->opcode ){
      case OP_Add:         rB += rA;       break;
      case OP_Subtract:    rB -= rA;       break;
      case OP_Multiply:    rB *= rA;       break;
      case OP_Divide: {
        /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
        if( rA==(double)0 ) goto arithmetic_result_is_null;
        rB /= rA;
        break;
      }
      default: {
        iA = (i64)rA;
        iB = (i64)rB;
        iA = sqlite3VdbeIntValue(pIn1);
        iB = sqlite3VdbeIntValue(pIn2);
        if( iA==0 ) goto arithmetic_result_is_null;
        if( iA==-1 ) iA = 1;
        rB = (double)(iB % iA);
        break;
      }
    }
#ifdef SQLITE_OMIT_FLOATING_POINT
    pOut->u.i = rB;
    MemSetTypeFlag(pOut, MEM_Int);
#else
    if( sqlite3IsNaN(rB) ){
      goto arithmetic_result_is_null;
    }
    pOut->u.r = rB;
    MemSetTypeFlag(pOut, MEM_Real);
    if( ((type1|type2)&MEM_Real)==0 && !bIntint ){
      sqlite3VdbeIntegerAffinity(pOut);
    }
#endif
  }
  break;

arithmetic_result_is_null:
  sqlite3VdbeMemSetNull(pOut);
  break;
1735
1736
1737
1738
1739
1740
1741
1742
1743

1744
1745
1746
1747
1748
1749
1750
1751

1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767

1768


1769

1770
1771
1772
1773
1774
1775
1776
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
1984
1985
1986
1987
1988
1989
1990
1991







-

+








+
















+
-
+
+

+







** without data loss, then jump immediately to P2, or if P2==0
** raise an SQLITE_MISMATCH exception.
*/
case OP_MustBeInt: {            /* jump, in1 */
  pIn1 = &aMem[pOp->p1];
  if( (pIn1->flags & MEM_Int)==0 ){
    applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding);
    VdbeBranchTaken((pIn1->flags&MEM_Int)==0, 2);
    if( (pIn1->flags & MEM_Int)==0 ){
      VdbeBranchTaken(1, 2);
      if( pOp->p2==0 ){
        rc = SQLITE_MISMATCH;
        goto abort_due_to_error;
      }else{
        goto jump_to_p2;
      }
    }
  }
  VdbeBranchTaken(0, 2);
  MemSetTypeFlag(pIn1, MEM_Int);
  break;
}

#ifndef SQLITE_OMIT_FLOATING_POINT
/* Opcode: RealAffinity P1 * * * *
**
** If register P1 holds an integer convert it to a real value.
**
** This opcode is used when extracting information from a column that
** has REAL affinity.  Such column values may still be stored as
** integers, for space efficiency, but after extraction we want them
** to have only a real value.
*/
case OP_RealAffinity: {                  /* in1 */
  pIn1 = &aMem[pOp->p1];
  if( pIn1->flags & (MEM_Int|MEM_IntReal) ){
  if( pIn1->flags & MEM_Int ){
    testcase( pIn1->flags & MEM_Int );
    testcase( pIn1->flags & MEM_IntReal );
    sqlite3VdbeMemRealify(pIn1);
    REGISTER_TRACE(pOp->p1, pIn1);
  }
  break;
}
#endif

#ifndef SQLITE_OMIT_CAST
/* Opcode: Cast P1 P2 * * *
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
2009
2010
2011
2012
2013
2014
2015
2016

2017

2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028

2029

2030
2031
2032
2033
2034
2035
2036







+
-
+
-

+
+








-
+
-







  testcase( pOp->p2==SQLITE_AFF_BLOB );
  testcase( pOp->p2==SQLITE_AFF_NUMERIC );
  testcase( pOp->p2==SQLITE_AFF_INTEGER );
  testcase( pOp->p2==SQLITE_AFF_REAL );
  pIn1 = &aMem[pOp->p1];
  memAboutToChange(p, pIn1);
  rc = ExpandBlob(pIn1);
  if( rc ) goto abort_due_to_error;
  sqlite3VdbeMemCast(pIn1, pOp->p2, encoding);
  rc = sqlite3VdbeMemCast(pIn1, pOp->p2, encoding);
  UPDATE_MAX_BLOBSIZE(pIn1);
  if( rc ) goto abort_due_to_error;
  UPDATE_MAX_BLOBSIZE(pIn1);
  REGISTER_TRACE(pOp->p1, pIn1);
  break;
}
#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
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
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







-
-
+
+
-







-
-
-
-





-
+
-







**
** 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 
1875
1876
1877
1878
1879
1880
1881



1882
1883
1884
1885
1886
1887
1888
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101







+
+
+







** 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.
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


1984
1985

1986
1987
1988
1989

1990
1991

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

2017
2018
2019

2020


2021
2022
2023
2024
2025
2026
2027

2028
2029
2030

2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046

2047
2048
2049
2050
2051
2052
2053
2054
2055




2056
2057
2058
2059
2060

2061
2062
2063
2064
2065
2066









2067
2068
2069
2070
2071
2072
2073















2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084


2085
2086
2087
2088
2089
2090
2091
2092
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165

2166

2167
2168
2169
2170
2171
2172
2173

2174
2175
2176
2177
2178
2179
2180











2181
2182
2183
2184

2185
2186
2187
2188
2189

2190
2191
2192
2193
2194

2195
2196

2197





2198
2199

2200
2201
2202
2203










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
2234

2235


2236
2237


2238
2239


2240
2241
2242
2243
2244
2245


2246
2247

2248



2249
















2250









2251
2252
2253
2254

2255
2256
2257

2258
2259





2260
2261
2262
2263
2264
2265
2266
2267
2268
2269






2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293


2294
2295

2296
2297
2298
2299
2300
2301
2302







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-

-
+
+





-
+






-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
+
+



-
+
+



-
+

-
+
-
-
-
-
-


-
+



-
-
-
-
-
-
-
-
-
-
+
+


+



-
+

-
+


+








-
+








-
+
-
-
+

-
-
+

-
-
+

+
+


-
-


-
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
-



-
+

-
-
-
-
-
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+









-
-
+
+
-







  u16 flags1;         /* Copy of initial value of pIn1->flags */
  u16 flags3;         /* Copy of initial value of pIn3->flags */

  pIn1 = &aMem[pOp->p1];
  pIn3 = &aMem[pOp->p3];
  flags1 = pIn1->flags;
  flags3 = pIn3->flags;
  if( (flags1 & flags3 & MEM_Int)!=0 ){
    /* Common case of comparison of two integers */
    if( pIn3->u.i > pIn1->u.i ){
      if( sqlite3aGTb[pOp->opcode] ){
        VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3);
        goto jump_to_p2;
      }
      iCompare = +1;
      VVA_ONLY( iCompareIsInit = 1; )
    }else if( pIn3->u.i < pIn1->u.i ){
      if( sqlite3aLTb[pOp->opcode] ){
        VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3);
        goto jump_to_p2;
      }
      iCompare = -1;
      VVA_ONLY( iCompareIsInit = 1; )
    }else{
      if( sqlite3aEQb[pOp->opcode] ){
        VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3);
        goto jump_to_p2;
      }
      iCompare = 0;
      VVA_ONLY( iCompareIsInit = 1; )
    }
    VdbeBranchTaken(0, (pOp->p5 & SQLITE_NULLEQ)?2:3);
    break;
  }
  if( (flags1 | flags3)&MEM_Null ){
    /* One or both operands are NULL */
    if( pOp->p5 & SQLITE_NULLEQ ){
      /* If SQLITE_NULLEQ is set (which will only happen if the operator is
      ** OP_Eq or OP_Ne) then take the jump or not depending on whether
      ** or not both operands are null.
      */
      assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne );
      assert( (flags1 & MEM_Cleared)==0 );
      assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 );
      assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 || CORRUPT_DB );
      testcase( (pOp->p5 & SQLITE_JUMPIFNULL)!=0 );
      if( (flags1&flags3&MEM_Null)!=0
       && (flags3&MEM_Cleared)==0
      ){
        res = 0;  /* Operands are equal */
      }else{
        res = 1;  /* Operands are not equal */
        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 */
        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;
      }
      }
      iCompare = 1;    /* Operands are not equal */
      VVA_ONLY( iCompareIsInit = 1; )
      break;
    }
  }else{
    /* Neither operand is NULL.  Do a comparison. */
    /* Neither operand is NULL and we couldn't do the special high-speed
    ** integer comparison case.  So do a general-case comparison. */
    affinity = pOp->p5 & SQLITE_AFF_MASK;
    if( affinity>=SQLITE_AFF_NUMERIC ){
      if( (flags1 | flags3)&MEM_Str ){
        if( (flags1 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
        if( (flags1 & (MEM_Int|MEM_IntReal|MEM_Real|MEM_Str))==MEM_Str ){
          applyNumericAffinity(pIn1,0);
          assert( flags3==pIn3->flags );
          assert( flags3==pIn3->flags || CORRUPT_DB );
          /* testcase( flags3!=pIn3->flags );
          ** this used to be possible with pIn1==pIn3, but not since
          ** the column cache was removed.  The following assignment
          ** is essentially a no-op.  But, it provides defense-in-depth
          ** in case our analysis is incorrect, so it is left in. */
          flags3 = pIn3->flags;
        }
        if( (flags3 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
        if( (flags3 & (MEM_Int|MEM_IntReal|MEM_Real|MEM_Str))==MEM_Str ){
          applyNumericAffinity(pIn3,0);
        }
      }
      /* Handle the common case of integer comparison here, as an
      ** optimization, to avoid a call to sqlite3MemCompare() */
      if( (pIn1->flags & pIn3->flags & MEM_Int)!=0 ){
        if( pIn3->u.i > pIn1->u.i ){ res = +1; goto compare_op; }
        if( pIn3->u.i < pIn1->u.i ){ res = -1; goto compare_op; }
        res = 0;
        goto compare_op;
      }
    }else if( affinity==SQLITE_AFF_TEXT ){
      if( (flags1 & MEM_Str)==0 && (flags1 & (MEM_Int|MEM_Real))!=0 ){
    }else if( affinity==SQLITE_AFF_TEXT && ((flags1 | flags3) & MEM_Str)!=0 ){
      if( (flags1 & MEM_Str)==0 && (flags1&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){
        testcase( pIn1->flags & MEM_Int );
        testcase( pIn1->flags & MEM_Real );
        testcase( pIn1->flags & MEM_IntReal );
        sqlite3VdbeMemStringify(pIn1, encoding, 1);
        testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) );
        flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask);
        assert( pIn1!=pIn3 );
        if( NEVER(pIn1==pIn3) ) flags3 = flags1 | MEM_Str;
      }
      if( (flags3 & MEM_Str)==0 && (flags3 & (MEM_Int|MEM_Real))!=0 ){
      if( (flags3 & MEM_Str)==0 && (flags3&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){
        testcase( pIn3->flags & MEM_Int );
        testcase( pIn3->flags & MEM_Real );
        testcase( pIn3->flags & MEM_IntReal );
        sqlite3VdbeMemStringify(pIn3, encoding, 1);
        testcase( (flags3&MEM_Dyn) != (pIn3->flags&MEM_Dyn) );
        flags3 = (pIn3->flags & ~MEM_TypeMask) | (flags3 & MEM_TypeMask);
      }
    }
    assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
    res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
  }
compare_op:

  /* At this point, res is negative, zero, or positive if reg[P1] is
  ** less than, equal to, or greater than reg[P3], respectively.  Compute
  ** the answer to this operator in res2, depending on what the comparison
  ** operator actually is.  The next block of code depends on the fact
  ** that the 6 comparison operators are consecutive integers in this
  ** order:  NE, EQ, GT, LE, LT, GE */
  assert( OP_Eq==OP_Ne+1 ); assert( OP_Gt==OP_Ne+2 ); assert( OP_Le==OP_Ne+3 );
  assert( OP_Lt==OP_Ne+4 ); assert( OP_Ge==OP_Ne+5 );
  if( res<0 ){                        /* 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;
  VVA_ONLY( iCompareIsInit = 1; )

  /* Undo any changes made by applyAffinity() to the input registers. */
  assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) );
  pIn1->flags = flags1;
  assert( (pIn3->flags & MEM_Dyn) == (flags3 & MEM_Dyn) );
  pIn3->flags = flags3;

  assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) );
  if( pOp->p5 & SQLITE_STOREP2 ){
    pOut = &aMem[pOp->p2];
    iCompare = res;
  pIn1->flags = flags1;
    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(res!=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 immediately follow an OP_Lt or OP_Gt comparison operator.
** If result of an OP_Eq comparison on the same two operands
** would have be 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.
** This opcode must follow an OP_Lt or OP_Gt comparison operator.  There
** can be zero or more OP_ReleaseReg opcodes intervening, but no other
** opcodes are allowed to occur between this instruction and the previous
** OP_Lt or OP_Gt. 
**
** If result of an OP_Eq comparison on the same two operands as the
** prior OP_Lt or OP_Gt would have been true, then jump to P2.
** If the result of an OP_Eq comparison on the two previous
** operands would have been false or NULL, then fall through.
*/
case OP_ElseNotEq: {       /* same as TK_ESCAPE, jump */
  assert( pOp>aOp );
  assert( pOp[-1].opcode==OP_Lt || pOp[-1].opcode==OP_Gt );
  assert( pOp[-1].p5 & SQLITE_STOREP2 );
  VdbeBranchTaken(iCompare!=0, 2);
  if( iCompare!=0 ) goto jump_to_p2;
case OP_ElseEq: {       /* same as TK_ESCAPE, jump */

#ifdef SQLITE_DEBUG
  /* Verify the preconditions of this opcode - that it follows an OP_Lt or
  ** OP_Gt with zero or more intervening OP_ReleaseReg opcodes */
  int iAddr;
  for(iAddr = (int)(pOp - aOp) - 1; ALWAYS(iAddr>=0); iAddr--){
    if( aOp[iAddr].opcode==OP_ReleaseReg ) continue;
    assert( aOp[iAddr].opcode==OP_Lt || aOp[iAddr].opcode==OP_Gt );
    break;
  }
#endif /* SQLITE_DEBUG */
  assert( iCompareIsInit );
  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
** instruction.  The permutation is stored in the P4 operand.
**
** The permutation is only valid until the next OP_Compare that has
** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should 
** The permutation is only valid for the next opcode which must be
** an OP_Compare that has the OPFLAG_PERMUTE bit set in P5.
** occur immediately prior to the OP_Compare.
**
** The first integer in the P4 integer array is the length of the array
** and does not become part of the permutation.
*/
case OP_Permutation: {
  assert( pOp->p4type==P4_INTARRAY );
  assert( pOp->p4.ai );
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
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335

2336
2337
2338

2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358

2359
2360
2361
2362
2363
2364
2365
2366
2367

2368
2369
2370
2371
2372
2373
2374

2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409







+
+







-
+


-
+



















-
+








-
+






-
+

+

+
+
+
+
+




+








+
+


+
+







** P4 is a KeyInfo structure that defines collating sequences and sort
** orders for the comparison.  The permutation applies to registers
** only.  The KeyInfo elements are used sequentially.
**
** The comparison is a sort comparison, so NULLs compare equal,
** NULLs are less than numbers, numbers are less than strings,
** and strings are less than blobs.
**
** This opcode must be immediately followed by an OP_Jump opcode.
*/
case OP_Compare: {
  int n;
  int i;
  int p1;
  int p2;
  const KeyInfo *pKeyInfo;
  int idx;
  u32 idx;
  CollSeq *pColl;    /* Collating sequence to use on this term */
  int bRev;          /* True for DESCENDING sort order */
  int *aPermute;     /* The permutation */
  u32 *aPermute;     /* The permutation */

  if( (pOp->p5 & OPFLAG_PERMUTE)==0 ){
    aPermute = 0;
  }else{
    assert( pOp>aOp );
    assert( pOp[-1].opcode==OP_Permutation );
    assert( pOp[-1].p4type==P4_INTARRAY );
    aPermute = pOp[-1].p4.ai + 1;
    assert( aPermute!=0 );
  }
  n = pOp->p3;
  pKeyInfo = pOp->p4.pKeyInfo;
  assert( n>0 );
  assert( pKeyInfo!=0 );
  p1 = pOp->p1;
  p2 = pOp->p2;
#ifdef SQLITE_DEBUG
  if( aPermute ){
    int k, mx = 0;
    for(k=0; k<n; k++) if( aPermute[k]>mx ) mx = aPermute[k];
    for(k=0; k<n; k++) if( aPermute[k]>(u32)mx ) mx = aPermute[k];
    assert( p1>0 && p1+mx<=(p->nMem+1 - p->nCursor)+1 );
    assert( p2>0 && p2+mx<=(p->nMem+1 - p->nCursor)+1 );
  }else{
    assert( p1>0 && p1+n<=(p->nMem+1 - p->nCursor)+1 );
    assert( p2>0 && p2+n<=(p->nMem+1 - p->nCursor)+1 );
  }
#endif /* SQLITE_DEBUG */
  for(i=0; i<n; i++){
    idx = aPermute ? aPermute[i] : i;
    idx = aPermute ? aPermute[i] : (u32)i;
    assert( memIsValid(&aMem[p1+idx]) );
    assert( memIsValid(&aMem[p2+idx]) );
    REGISTER_TRACE(p1+idx, &aMem[p1+idx]);
    REGISTER_TRACE(p2+idx, &aMem[p2+idx]);
    assert( i<pKeyInfo->nKeyField );
    pColl = pKeyInfo->aColl[i];
    bRev = pKeyInfo->aSortOrder[i];
    bRev = (pKeyInfo->aSortFlags[i] & KEYINFO_ORDER_DESC);
    iCompare = sqlite3MemCompare(&aMem[p1+idx], &aMem[p2+idx], pColl);
    VVA_ONLY( iCompareIsInit = 1; )
    if( iCompare ){
      if( (pKeyInfo->aSortFlags[i] & KEYINFO_ORDER_BIGNULL) 
       && ((aMem[p1+idx].flags & MEM_Null) || (aMem[p2+idx].flags & MEM_Null))
      ){
        iCompare = -iCompare;
      }
      if( bRev ) iCompare = -iCompare;
      break;
    }
  }
  assert( pOp[1].opcode==OP_Jump );
  break;
}

/* Opcode: Jump P1 P2 P3 * *
**
** Jump to the instruction at address P1, P2, or P3 depending on whether
** in the most recent OP_Compare instruction the P1 vector was less than
** equal to, or greater than the P2 vector, respectively.
**
** This opcode must immediately follow an OP_Compare opcode.
*/
case OP_Jump: {             /* jump */
  assert( pOp>aOp && pOp[-1].opcode==OP_Compare );
  assert( iCompareIsInit );
  if( iCompare<0 ){
    VdbeBranchTaken(0,4); pOp = &aOp[pOp->p1 - 1];
  }else if( iCompare==0 ){
    VdbeBranchTaken(1,4); pOp = &aOp[pOp->p2 - 1];
  }else{
    VdbeBranchTaken(2,4); pOp = &aOp[pOp->p3 - 1];
  }
2371
2372
2373
2374
2375
2376
2377









































































































2378
2379
2380
2381
2382
2383
2384
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
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
2704
2705
2706
2707
2708
2709
2710
2711
2712







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  pIn1 = &aMem[pOp->p1];
  VdbeBranchTaken( (pIn1->flags & MEM_Null)!=0, 2);
  if( (pIn1->flags & MEM_Null)!=0 ){
    goto jump_to_p2;
  }
  break;
}

/* Opcode: IsType P1 P2 P3 P4 P5
** Synopsis: if typeof(P1.P3) in P5 goto P2
**
** Jump to P2 if the type of a column in a btree is one of the types specified
** by the P5 bitmask.
**
** P1 is normally a cursor on a btree for which the row decode cache is
** valid through at least column P3.  In other words, there should have been
** a prior OP_Column for column P3 or greater.  If the cursor is not valid,
** then this opcode might give spurious results.
** The the btree row has fewer than P3 columns, then use P4 as the
** datatype.
**
** If P1 is -1, then P3 is a register number and the datatype is taken
** from the value in that register.
**
** P5 is a bitmask of data types.  SQLITE_INTEGER is the least significant
** (0x01) bit. SQLITE_FLOAT is the 0x02 bit. SQLITE_TEXT is 0x04.
** SQLITE_BLOB is 0x08.  SQLITE_NULL is 0x10.
**
** Take the jump to address P2 if and only if the datatype of the
** value determined by P1 and P3 corresponds to one of the bits in the
** P5 bitmask.
**
*/
case OP_IsType: {        /* jump */
  VdbeCursor *pC;
  u16 typeMask;
  u32 serialType;

  assert( pOp->p1>=(-1) && pOp->p1<p->nCursor );
  assert( pOp->p1>=0 || (pOp->p3>=0 && pOp->p3<=(p->nMem+1 - p->nCursor)) );
  if( pOp->p1>=0 ){
    pC = p->apCsr[pOp->p1];
    assert( pC!=0 );
    assert( pOp->p3>=0 );
    if( pOp->p3<pC->nHdrParsed ){
      serialType = pC->aType[pOp->p3];
      if( serialType>=12 ){
        if( serialType&1 ){
          typeMask = 0x04;   /* SQLITE_TEXT */
        }else{
          typeMask = 0x08;   /* SQLITE_BLOB */
        }
      }else{
        static const unsigned char aMask[] = {
           0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x2,
           0x01, 0x01, 0x10, 0x10
        };
        testcase( serialType==0 );
        testcase( serialType==1 );
        testcase( serialType==2 );
        testcase( serialType==3 );
        testcase( serialType==4 );
        testcase( serialType==5 );
        testcase( serialType==6 );
        testcase( serialType==7 );
        testcase( serialType==8 );
        testcase( serialType==9 );
        testcase( serialType==10 );
        testcase( serialType==11 );
        typeMask = aMask[serialType];
      }
    }else{
      typeMask = 1 << (pOp->p4.i - 1);
      testcase( typeMask==0x01 );
      testcase( typeMask==0x02 );
      testcase( typeMask==0x04 );
      testcase( typeMask==0x08 );
      testcase( typeMask==0x10 );
    }
  }else{
    assert( memIsValid(&aMem[pOp->p3]) );
    typeMask = 1 << (sqlite3_value_type((sqlite3_value*)&aMem[pOp->p3])-1);
    testcase( typeMask==0x01 );
    testcase( typeMask==0x02 );
    testcase( typeMask==0x04 );
    testcase( typeMask==0x08 );
    testcase( typeMask==0x10 );
  }
  VdbeBranchTaken( (typeMask & pOp->p5)!=0, 2);
  if( typeMask & pOp->p5 ){
    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 */
2393
2394
2395
2396
2397
2398
2399


2400
2401

2402
2403
2404


2405
2406
2407
2408
2409
2410
2411
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733


2734
2735
2736
2737
2738
2739
2740
2741
2742







+
+


+

-
-
+
+







/* Opcode: IfNullRow P1 P2 P3 * *
** Synopsis: if P1.nullRow then r[P3]=NULL, goto P2
**
** Check the cursor P1 to see if it is currently pointing at a NULL row.
** If it is, then set register P3 to NULL and jump immediately to P2.
** If P1 is not on a NULL row, then fall through without making any
** changes.
**
** If P1 is not an open cursor, then this opcode is a no-op.
*/
case OP_IfNullRow: {         /* jump */
  VdbeCursor *pC;
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( p->apCsr[pOp->p1]!=0 );
  if( p->apCsr[pOp->p1]->nullRow ){
  pC = p->apCsr[pOp->p1];
  if( ALWAYS(pC) && pC->nullRow ){
    sqlite3VdbeMemSetNull(aMem + pOp->p3);
    goto jump_to_p2;
  }
  break;
}

#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
2425
2426
2427
2428
2429
2430
2431
2432

2433
2434







2435


2436
2437
2438
2439
2440
2441
2442

2443
2444
2445
2446
2447

2448
2449
2450
2451
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
2481


2482
2483

2484
2485
2486
2487
2488
2489
2490

2491
2492
2493
2494
2495
2496


2497

2498
2499
2500
2501
2502
2503
2504

2505
2506
2507
2508
2509
2510
2511
2512
2513


2514
2515
2516
2517
2518















2519
2520
2521
2522
2523
2524
2525
2526
2527
2528

2529
2530

2531
2532
2533





2534
2535
2536
2537
2538
2539
2540
2756
2757
2758
2759
2760
2761
2762

2763
2764
2765
2766
2767
2768
2769
2770
2771
2772

2773
2774
2775
2776
2777
2778
2779
2780

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
2818
2819
2820

2821
2822






2823




2824

2825
2826
2827
2828
2829
2830
2831
2832
2833
2834

2835
2836
2837

2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872



2873

2874
2875



2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887







-
+


+
+
+
+
+
+
+
-
+
+






-
+




-
+








-
-
-
+
+
+
-
-
-
+
-
-
-
+
+

-
-
+
+

-
+












+
+

-
+

-
-
-
-
-
-
+
-
-
-
-

-
+
+

+






-
+


-






+
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
-
-
+
-

+
-
-
-
+
+
+
+
+







** -DSQLITE_ENABLE_OFFSET_SQL_FUNC option.
*/
case OP_Offset: {          /* out3 */
  VdbeCursor *pC;    /* The VDBE cursor */
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  pC = p->apCsr[pOp->p1];
  pOut = &p->aMem[pOp->p3];
  if( NEVER(pC==0) || pC->eCurType!=CURTYPE_BTREE ){
  if( pC==0 || pC->eCurType!=CURTYPE_BTREE ){
    sqlite3VdbeMemSetNull(pOut);
  }else{
    if( pC->deferredMoveto ){
      rc = sqlite3VdbeFinishMoveto(pC);
      if( rc ) goto abort_due_to_error;
    }
    if( sqlite3BtreeEof(pC->uc.pCursor) ){
      sqlite3VdbeMemSetNull(pOut);
    }else{
    sqlite3VdbeMemSetInt64(pOut, sqlite3BtreeOffset(pC->uc.pCursor));
      sqlite3VdbeMemSetInt64(pOut, sqlite3BtreeOffset(pC->uc.pCursor));
    }
  }
  break;
}
#endif /* SQLITE_ENABLE_OFFSET_SQL_FUNC */

/* Opcode: Column P1 P2 P3 P4 P5
** Synopsis: r[P3]=PX
** Synopsis: r[P3]=PX cursor P1 column P2
**
** Interpret the data that cursor P1 points to as a structure built using
** the MakeRecord instruction.  (See the MakeRecord opcode for additional
** information about the format of the data.)  Extract the P2-th column
** from this record.  If there are less that (P2+1) 
** from this record.  If there are less than (P2+1) 
** values in the record, extract a NULL.
**
** The value extracted is stored in register P3.
**
** If the record contains fewer than P2 fields, then extract a NULL.  Or,
** if the P4 argument is a P4_MEM use the value of the P4 argument as
** the result.
**
** If the OPFLAG_CLEARCACHE bit is set on P5 and P1 is a pseudo-table cursor,
** then the cache of the cursor is reset prior to extracting the column.
** The first OP_Column against a pseudo-table after the value of the content
** If the OPFLAG_LENGTHARG bit is set in P5 then the result is guaranteed
** to only be used by the length() function or the equivalent.  The content
** of large blobs is not loaded, thus saving CPU cycles.  If the
** register has changed should have this bit set.
**
** If the OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG bits are set on P5 then
** OPFLAG_TYPEOFARG bit is set then the result will only be used by the
** the result is guaranteed to only be used as the argument of a length()
** or typeof() function, respectively.  The loading of large blobs can be
** skipped for length() and all content loading can be skipped for typeof().
** typeof() function or the IS NULL or IS NOT NULL operators or the
** equivalent.  In this case, all content loading can be omitted.
*/
case OP_Column: {
  int p2;            /* column number to retrieve */
case OP_Column: {            /* ncycle */
  u32 p2;            /* column number to retrieve */
  VdbeCursor *pC;    /* The VDBE cursor */
  BtCursor *pCrsr;   /* The BTree cursor */
  BtCursor *pCrsr;   /* The B-Tree cursor corresponding to pC */
  u32 *aOffset;      /* aOffset[i] is offset to start of data for i-th column */
  int len;           /* The length of the serialized data for the column */
  int i;             /* Loop counter */
  Mem *pDest;        /* Where to write the extracted value */
  Mem sMem;          /* For storing the record being decoded */
  const u8 *zData;   /* Part of the record being decoded */
  const u8 *zHdr;    /* Next unparsed byte of the header */
  const u8 *zEndHdr; /* Pointer to first byte after the header */
  u64 offset64;      /* 64-bit offset */
  u32 t;             /* A type code from the record header */
  Mem *pReg;         /* PseudoTable input register */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
  pC = p->apCsr[pOp->p1];
  p2 = pOp->p2;
  p2 = (u32)pOp->p2;

  /* If the cursor cache is stale (meaning it is not currently point at
  ** the correct row) then bring it up-to-date by doing the necessary 
  ** B-Tree seek. */
  rc = sqlite3VdbeCursorMoveto(&pC, &p2);
  if( rc ) goto abort_due_to_error;

op_column_restart:
  assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
  pDest = &aMem[pOp->p3];
  memAboutToChange(p, pDest);
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( pC!=0 );
  assert( p2<pC->nField );
  assert( p2<(u32)pC->nField
       || (pC->eCurType==CURTYPE_PSEUDO && pC->seekResult==0) );
  aOffset = pC->aOffset;
  assert( aOffset==pC->aType+pC->nField );
  assert( pC->eCurType!=CURTYPE_VTAB );
  assert( pC->eCurType!=CURTYPE_PSEUDO || pC->nullRow );
  assert( pC->eCurType!=CURTYPE_SORTER );

  if( pC->cacheStatus!=p->cacheCtr ){                /*OPTIMIZATION-IF-FALSE*/
    if( pC->nullRow ){
      if( pC->eCurType==CURTYPE_PSEUDO ){
      if( pC->eCurType==CURTYPE_PSEUDO && pC->seekResult>0 ){
        /* For the special case of as pseudo-cursor, the seekResult field
        ** identifies the register that holds the record */
        assert( pC->seekResult>0 );
        pReg = &aMem[pC->seekResult];
        assert( pReg->flags & MEM_Blob );
        assert( memIsValid(pReg) );
        pC->payloadSize = pC->szRow = pReg->n;
        pC->aRow = (u8*)pReg->z;
      }else{
        pDest = &aMem[pOp->p3];
        memAboutToChange(p, pDest);
        sqlite3VdbeMemSetNull(pDest);
        goto op_column_out;
      }
    }else{
      pCrsr = pC->uc.pCursor;
      if( pC->deferredMoveto ){
        u32 iMap;
        assert( !pC->isEphemeral );
        if( pC->ub.aAltMap && (iMap = pC->ub.aAltMap[1+p2])>0  ){
          pC = pC->pAltCursor;
          p2 = iMap - 1;
          goto op_column_restart;
        }
        rc = sqlite3VdbeFinishMoveto(pC);
        if( rc ) goto abort_due_to_error;
      }else if( sqlite3BtreeCursorHasMoved(pCrsr) ){
        rc = sqlite3VdbeHandleMovedCursor(pC);
        if( rc ) goto abort_due_to_error;
        goto op_column_restart;
      }
      assert( pC->eCurType==CURTYPE_BTREE );
      assert( pCrsr );
      assert( sqlite3BtreeCursorIsValid(pCrsr) );
      pC->payloadSize = sqlite3BtreePayloadSize(pCrsr);
      pC->aRow = sqlite3BtreePayloadFetch(pCrsr, &pC->szRow);
      assert( pC->szRow<=pC->payloadSize );
      assert( pC->szRow<=65536 );  /* Maximum page size is 64KiB */
      if( pC->payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
        goto too_big;
      }
    }
    }
    pC->cacheStatus = p->cacheCtr;
    if( (aOffset[0] = pC->aRow[0])<0x80 ){
    pC->iHdrOffset = getVarint32(pC->aRow, aOffset[0]);
    pC->nHdrParsed = 0;

      pC->iHdrOffset = 1;
    }else{
      pC->iHdrOffset = sqlite3GetVarint32(pC->aRow, aOffset);
    }
    pC->nHdrParsed = 0;

    if( pC->szRow<aOffset[0] ){      /*OPTIMIZATION-IF-FALSE*/
      /* pC->aRow does not have to hold the entire row, but it does at least
      ** need to cover the header of the record.  If pC->aRow does not contain
      ** the complete header, then set it to zero, forcing the header to be
      ** dynamically allocated. */
      pC->aRow = 0;
2567
2568
2569
2570
2571
2572
2573




2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587

2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602

2603
2604
2605
2606

2607
2608
2609
2610
2611


2612
2613
2614
2615
2616
2617
2618
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937

2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952

2953
2954
2955
2956
2957
2958
2959
2960



2961
2962
2963
2964
2965
2966
2967
2968
2969







+
+
+
+













-
+














-
+




+


-
-
-
+
+







      ** database file.
      */
      zData = pC->aRow;
      assert( pC->nHdrParsed<=p2 );         /* Conditional skipped */
      testcase( aOffset[0]==0 );
      goto op_column_read_header;
    }
  }else if( sqlite3BtreeCursorHasMoved(pC->uc.pCursor) ){
    rc = sqlite3VdbeHandleMovedCursor(pC);
    if( rc ) goto abort_due_to_error;
    goto op_column_restart;
  }

  /* Make sure at least the first p2+1 entries of the header have been
  ** parsed and valid information is in aOffset[] and pC->aType[].
  */
  if( pC->nHdrParsed<=p2 ){
    /* If there is more header available for parsing in the record, try
    ** to extract additional fields up through the p2+1-th field 
    */
    if( pC->iHdrOffset<aOffset[0] ){
      /* Make sure zData points to enough of the record to cover the header. */
      if( pC->aRow==0 ){
        memset(&sMem, 0, sizeof(sMem));
        rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, 0, aOffset[0], &sMem);
        rc = sqlite3VdbeMemFromBtreeZeroOffset(pC->uc.pCursor,aOffset[0],&sMem);
        if( rc!=SQLITE_OK ) goto abort_due_to_error;
        zData = (u8*)sMem.z;
      }else{
        zData = pC->aRow;
      }
  
      /* Fill in pC->aType[i] and aOffset[i] values through the p2-th field. */
    op_column_read_header:
      i = pC->nHdrParsed;
      offset64 = aOffset[i];
      zHdr = zData + pC->iHdrOffset;
      zEndHdr = zData + aOffset[0];
      testcase( zHdr>=zEndHdr );
      do{
        if( (t = zHdr[0])<0x80 ){
        if( (pC->aType[i] = t = zHdr[0])<0x80 ){
          zHdr++;
          offset64 += sqlite3VdbeOneByteSerialTypeLen(t);
        }else{
          zHdr += sqlite3GetVarint32(zHdr, &t);
          pC->aType[i] = t;
          offset64 += sqlite3VdbeSerialTypeLen(t);
        }
        pC->aType[i++] = t;
        aOffset[i] = (u32)(offset64 & 0xffffffff);
      }while( i<=p2 && zHdr<zEndHdr );
        aOffset[++i] = (u32)(offset64 & 0xffffffff);
      }while( (u32)i<=p2 && zHdr<zEndHdr );

      /* The record is corrupt if any of the following are true:
      ** (1) the bytes of the header extend past the declared header size
      ** (2) the entire header was used but not all data was used
      ** (3) the end of the data extends beyond the end of the record.
      */
      if( (zHdr>=zEndHdr && (zHdr>zEndHdr || offset64!=pC->payloadSize))
2635
2636
2637
2638
2639
2640
2641


2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658


2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678

2679
2680
2681
2682
2683
2684
2685
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041







+
+

















+
+




















+







    }

    /* If after trying to extract new entries from the header, nHdrParsed is
    ** still not up to p2, that means that the record has fewer than p2
    ** columns.  So the result will be either the default value or a NULL.
    */
    if( pC->nHdrParsed<=p2 ){
      pDest = &aMem[pOp->p3];
      memAboutToChange(p, pDest);
      if( pOp->p4type==P4_MEM ){
        sqlite3VdbeMemShallowCopy(pDest, pOp->p4.pMem, MEM_Static);
      }else{
        sqlite3VdbeMemSetNull(pDest);
      }
      goto op_column_out;
    }
  }else{
    t = pC->aType[p2];
  }

  /* Extract the content for the p2+1-th column.  Control can only
  ** reach this point if aOffset[p2], aOffset[p2+1], and pC->aType[p2] are
  ** all valid.
  */
  assert( p2<pC->nHdrParsed );
  assert( rc==SQLITE_OK );
  pDest = &aMem[pOp->p3];
  memAboutToChange(p, pDest);
  assert( sqlite3VdbeCheckMemInvariants(pDest) );
  if( VdbeMemDynamic(pDest) ){
    sqlite3VdbeMemSetNull(pDest);
  }
  assert( t==pC->aType[p2] );
  if( pC->szRow>=aOffset[p2+1] ){
    /* This is the common case where the desired content fits on the original
    ** page - where the content is not on an overflow page */
    zData = pC->aRow + aOffset[p2];
    if( t<12 ){
      sqlite3VdbeSerialGet(zData, t, pDest);
    }else{
      /* If the column value is a string, we need a persistent value, not
      ** a MEM_Ephem value.  This branch is a fast short-cut that is equivalent
      ** to calling sqlite3VdbeSerialGet() and sqlite3VdbeDeephemeralize().
      */
      static const u16 aFlag[] = { MEM_Blob, MEM_Str|MEM_Term };
      pDest->n = len = (t-12)/2;
      pDest->enc = encoding;
      if( pDest->szMalloc < len+2 ){
        if( len>db->aLimit[SQLITE_LIMIT_LENGTH] ) goto too_big;
        pDest->flags = MEM_Null;
        if( sqlite3VdbeMemGrow(pDest, len+2, 0) ) goto no_mem;
      }else{
        pDest->z = pDest->zMalloc;
      }
      memcpy(pDest->z, zData, len);
      pDest->z[len] = 0;
2698
2699
2700
2701
2702
2703
2704

2705


2706
2707
2708

2709

2710
2711
2712
2713
2714
2715
2716
3054
3055
3056
3057
3058
3059
3060
3061

3062
3063
3064


3065
3066
3067
3068
3069
3070
3071
3072
3073
3074







+
-
+
+

-
-
+

+







      **    2. the length(X) function if X is a blob, and
      **    3. if the content length is zero.
      ** So we might as well use bogus content rather than reading
      ** content from disk. 
      **
      ** Although sqlite3VdbeSerialGet() may read at most 8 bytes from the
      ** buffer passed to it, debugging function VdbeMemPrettyPrint() may
      ** read more.  Use the global constant sqlite3CtypeMap[] as the array,
      ** read up to 16. So 16 bytes of bogus content is supplied.
      ** as that array is 256 bytes long (plenty for VdbeMemPrettyPrint())
      ** and it begins with a bunch of zeros.
      */
      static u8 aZero[16];  /* This is the bogus content */
      sqlite3VdbeSerialGet(aZero, t, pDest);
      sqlite3VdbeSerialGet((u8*)sqlite3CtypeMap, t, pDest);
    }else{
      if( len>db->aLimit[SQLITE_LIMIT_LENGTH] ) goto too_big;
      rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, aOffset[p2], len, pDest);
      if( rc!=SQLITE_OK ) goto abort_due_to_error;
      sqlite3VdbeSerialGet((const u8*)pDest->z, t, pDest);
      pDest->flags &= ~MEM_Ephem;
    }
  }

2724
2725
2726
2727
2728
2729
2730








































































































2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749

2750
2751
2752























2753
2754

2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772











2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790


2791
2792
2793
2794
2795
2796
2797
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210

3211
3212


3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236

3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268

3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279



3280
3281
3282
3283
3284
3285
3286
3287
3288
3289







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


















-
+

-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+


















+
+
+
+
+
+
+
+
+
+
+


-











-
-
-

+
+







    pOp = &aOp[aOp[0].p3-1];
    break;
  }else{
    rc = SQLITE_CORRUPT_BKPT;
    goto abort_due_to_error;
  }
}

/* Opcode: TypeCheck P1 P2 P3 P4 *
** Synopsis: typecheck(r[P1@P2])
**
** Apply affinities to the range of P2 registers beginning with P1.
** Take the affinities from the Table object in P4.  If any value
** cannot be coerced into the correct type, then raise an error.
**
** This opcode is similar to OP_Affinity except that this opcode
** forces the register type to the Table column type.  This is used
** to implement "strict affinity".
**
** GENERATED ALWAYS AS ... STATIC columns are only checked if P3
** is zero.  When P3 is non-zero, no type checking occurs for
** static generated columns.  Virtual columns are computed at query time
** and so they are never checked.
**
** Preconditions:
**
** <ul>
** <li> P2 should be the number of non-virtual columns in the
**      table of P4.
** <li> Table P4 should be a STRICT table.
** </ul>
**
** If any precondition is false, an assertion fault occurs.
*/
case OP_TypeCheck: {
  Table *pTab;
  Column *aCol;
  int i;

  assert( pOp->p4type==P4_TABLE );
  pTab = pOp->p4.pTab;
  assert( pTab->tabFlags & TF_Strict );
  assert( pTab->nNVCol==pOp->p2 );
  aCol = pTab->aCol;
  pIn1 = &aMem[pOp->p1];
  for(i=0; i<pTab->nCol; i++){
    if( aCol[i].colFlags & COLFLAG_GENERATED ){
      if( aCol[i].colFlags & COLFLAG_VIRTUAL ) continue;
      if( pOp->p3 ){ pIn1++; continue; }
    }
    assert( pIn1 < &aMem[pOp->p1+pOp->p2] );
    applyAffinity(pIn1, aCol[i].affinity, encoding);
    if( (pIn1->flags & MEM_Null)==0 ){
      switch( aCol[i].eCType ){
        case COLTYPE_BLOB: {
          if( (pIn1->flags & MEM_Blob)==0 ) goto vdbe_type_error;
          break;
        }
        case COLTYPE_INTEGER:
        case COLTYPE_INT: {
          if( (pIn1->flags & MEM_Int)==0 ) goto vdbe_type_error;
          break;
        }
        case COLTYPE_TEXT: {
          if( (pIn1->flags & MEM_Str)==0 ) goto vdbe_type_error;
          break;
        }
        case COLTYPE_REAL: {
          testcase( (pIn1->flags & (MEM_Real|MEM_IntReal))==MEM_Real );
          assert( (pIn1->flags & MEM_IntReal)==0 );
          if( pIn1->flags & MEM_Int ){
            /* When applying REAL affinity, if the result is still an MEM_Int
            ** that will fit in 6 bytes, then change the type to MEM_IntReal
            ** so that we keep the high-resolution integer value but know that
            ** the type really wants to be REAL. */
            testcase( pIn1->u.i==140737488355328LL );
            testcase( pIn1->u.i==140737488355327LL );
            testcase( pIn1->u.i==-140737488355328LL );
            testcase( pIn1->u.i==-140737488355329LL );
            if( pIn1->u.i<=140737488355327LL && pIn1->u.i>=-140737488355328LL){
              pIn1->flags |= MEM_IntReal;
              pIn1->flags &= ~MEM_Int;
            }else{
              pIn1->u.r = (double)pIn1->u.i;
              pIn1->flags |= MEM_Real;
              pIn1->flags &= ~MEM_Int;
            }
          }else if( (pIn1->flags & (MEM_Real|MEM_IntReal))==0 ){
            goto vdbe_type_error;
          }
          break;
        }
        default: {
          /* COLTYPE_ANY.  Accept anything. */
          break;
        }
      }
    }
    REGISTER_TRACE((int)(pIn1-aMem), pIn1);
    pIn1++;
  }
  assert( pIn1 == &aMem[pOp->p1+pOp->p2] );
  break;

vdbe_type_error:
  sqlite3VdbeError(p, "cannot store %s value in %s column %s.%s",
     vdbeMemTypeName(pIn1), sqlite3StdType[aCol[i].eCType-1],
     pTab->zName, aCol[i].zCnName);
  rc = SQLITE_CONSTRAINT_DATATYPE;
  goto abort_due_to_error;
}

/* Opcode: Affinity P1 P2 * P4 *
** Synopsis: affinity(r[P1@P2])
**
** Apply affinities to a range of P2 registers starting with P1.
**
** P4 is a string that is P2 characters long. The N-th character of the
** string indicates the column affinity that should be used for the N-th
** memory cell in the range.
*/
case OP_Affinity: {
  const char *zAffinity;   /* The affinity to be applied */

  zAffinity = pOp->p4.z;
  assert( zAffinity!=0 );
  assert( pOp->p2>0 );
  assert( zAffinity[pOp->p2]==0 );
  pIn1 = &aMem[pOp->p1];
  do{
  while( 1 /*exit-by-break*/ ){
    assert( pIn1 <= &p->aMem[(p->nMem+1 - p->nCursor)] );
    assert( memIsValid(pIn1) );
    applyAffinity(pIn1, *(zAffinity++), encoding);
    assert( zAffinity[0]==SQLITE_AFF_NONE || memIsValid(pIn1) );
    applyAffinity(pIn1, zAffinity[0], encoding);
    if( zAffinity[0]==SQLITE_AFF_REAL && (pIn1->flags & MEM_Int)!=0 ){
      /* When applying REAL affinity, if the result is still an MEM_Int
      ** that will fit in 6 bytes, then change the type to MEM_IntReal
      ** so that we keep the high-resolution integer value but know that
      ** the type really wants to be REAL. */
      testcase( pIn1->u.i==140737488355328LL );
      testcase( pIn1->u.i==140737488355327LL );
      testcase( pIn1->u.i==-140737488355328LL );
      testcase( pIn1->u.i==-140737488355329LL );
      if( pIn1->u.i<=140737488355327LL && pIn1->u.i>=-140737488355328LL ){
        pIn1->flags |= MEM_IntReal;
        pIn1->flags &= ~MEM_Int;
      }else{
        pIn1->u.r = (double)pIn1->u.i;
        pIn1->flags |= MEM_Real;
        pIn1->flags &= ~MEM_Int;
      }
    }
    REGISTER_TRACE((int)(pIn1-aMem), pIn1);
    zAffinity++;
    if( zAffinity[0]==0 ) break;
    pIn1++;
  }while( zAffinity[0] );
  }
  break;
}

/* Opcode: MakeRecord P1 P2 P3 P4 *
** Synopsis: r[P3]=mkrec(r[P1@P2])
**
** Convert P2 registers beginning with P1 into the [record format]
** use as a data record in a database table or as a key
** in an index.  The OP_Column opcode can decode the record later.
**
** P4 may be a string that is P2 characters long.  The N-th character of the
** string indicates the column affinity that should be used for the N-th
** field of the index key.
**
** The mapping from character to affinity is given by the SQLITE_AFF_
** macros defined in sqliteInt.h.
**
** If P4 is NULL then all index fields have the affinity BLOB.
**
** The meaning of P5 depends on whether or not the SQLITE_ENABLE_NULL_TRIM
** compile-time option is enabled:
**
**   * If SQLITE_ENABLE_NULL_TRIM is enabled, then the P5 is the index
**     of the right-most table that can be null-trimmed.
**
**   * If SQLITE_ENABLE_NULL_TRIM is omitted, then P5 has the value
**     OPFLAG_NOCHNG_MAGIC if the OP_MakeRecord opcode is allowed to
**     accept no-change records with serial_type 10.  This value is
**     only used inside an assert() and does not affect the end result.
*/
case OP_MakeRecord: {
  u8 *zNewRecord;        /* A buffer to hold the data for the new record */
  Mem *pRec;             /* The new record */
  u64 nData;             /* Number of bytes of data space */
  int nHdr;              /* Number of bytes of header space */
  i64 nByte;             /* Data space required for this record */
  i64 nZero;             /* Number of zero bytes at the end of the record */
  int nVarint;           /* Number of bytes in a varint */
  u32 serial_type;       /* Type field */
  Mem *pData0;           /* First field to be combined into the record */
  Mem *pLast;            /* Last field of the record */
  int nField;            /* Number of fields in the record */
  char *zAffinity;       /* The affinity string for the record */
  int file_format;       /* File format to use for encoding */
  int i;                 /* Space used in zNewRecord[] header */
  int j;                 /* Space used in zNewRecord[] content */
  u32 len;               /* Length of a field */
  u8 *zHdr;              /* Where to write next byte of the header */
  u8 *zPayload;          /* Where to write next byte of the payload */

  /* Assuming the record contains N fields, the record format looks
  ** like this:
  **
  ** ------------------------------------------------------------------------
  ** | hdr-size | type 0 | type 1 | ... | type N-1 | data0 | ... | data N-1 | 
  ** ------------------------------------------------------------------------
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829








2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
























2850
2851
2852
2853
2854
2855


2856
2857
2858
2859
2860
2861
2862

2863


































































2864
2865
2866
2867
2868






2869
2870
2871
2872



2873
2874
2875
2876



2877
2878
2879
2880
2881
2882
2883
3301
3302
3303
3304
3305
3306
3307

3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319

3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346

3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374


3375
3376

3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450





3451
3452
3453
3454
3455
3456




3457
3458
3459




3460
3461
3462
3463
3464
3465
3466
3467
3468
3469







-












-
+
+
+
+
+
+
+
+



















-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
-
+
+
-






+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+







  nZero = 0;         /* Number of zero bytes at the end of the record */
  nField = pOp->p1;
  zAffinity = pOp->p4.z;
  assert( nField>0 && pOp->p2>0 && pOp->p2+nField<=(p->nMem+1 - p->nCursor)+1 );
  pData0 = &aMem[nField];
  nField = pOp->p2;
  pLast = &pData0[nField-1];
  file_format = p->minWriteFileFormat;

  /* Identify the output register */
  assert( pOp->p3<pOp->p1 || pOp->p3>=pOp->p1+pOp->p2 );
  pOut = &aMem[pOp->p3];
  memAboutToChange(p, pOut);

  /* Apply the requested affinity to all inputs
  */
  assert( pData0<=pLast );
  if( zAffinity ){
    pRec = pData0;
    do{
      applyAffinity(pRec++, *(zAffinity++), encoding);
      applyAffinity(pRec, zAffinity[0], encoding);
      if( zAffinity[0]==SQLITE_AFF_REAL && (pRec->flags & MEM_Int) ){
        pRec->flags |= MEM_IntReal;
        pRec->flags &= ~(MEM_Int);
      }
      REGISTER_TRACE((int)(pRec-aMem), pRec);
      zAffinity++;
      pRec++;
      assert( zAffinity[0]==0 || pRec<=pLast );
    }while( zAffinity[0] );
  }

#ifdef SQLITE_ENABLE_NULL_TRIM
  /* NULLs can be safely trimmed from the end of the record, as long as
  ** as the schema format is 2 or more and none of the omitted columns
  ** have a non-NULL default value.  Also, the record must be left with
  ** at least one field.  If P5>0 then it will be one more than the
  ** index of the right-most column with a non-NULL default value */
  if( pOp->p5 ){
    while( (pLast->flags & MEM_Null)!=0 && nField>pOp->p5 ){
      pLast--;
      nField--;
    }
  }
#endif

  /* Loop through the elements that will make up the record to figure
  ** out how much space is required for the new record.
  ** out how much space is required for the new record.  After this loop,
  ** the Mem.uTemp field of each term should hold the serial-type that will
  ** be used for that term in the generated record:
  **
  **   Mem.uTemp value    type
  **   ---------------    ---------------
  **      0               NULL
  **      1               1-byte signed integer
  **      2               2-byte signed integer
  **      3               3-byte signed integer
  **      4               4-byte signed integer
  **      5               6-byte signed integer
  **      6               8-byte signed integer
  **      7               IEEE float
  **      8               Integer constant 0
  **      9               Integer constant 1
  **     10,11            reserved for expansion
  **    N>=12 and even    BLOB
  **    N>=13 and odd     text
  **
  ** The following additional values are computed:
  **     nHdr        Number of bytes needed for the record header
  **     nData       Number of bytes of data space needed for the record
  **     nZero       Zero bytes at the end of the record
  */
  pRec = pLast;
  do{
    assert( memIsValid(pRec) );
    serial_type = sqlite3VdbeSerialType(pRec, file_format, &len);
    if( pRec->flags & MEM_Zero ){
    if( pRec->flags & MEM_Null ){
      if( pRec->flags & MEM_Zero ){
      if( serial_type==0 ){
        /* Values with MEM_Null and MEM_Zero are created by xColumn virtual
        ** table methods that never invoke sqlite3_result_xxxxx() while
        ** computing an unchanging column value in an UPDATE statement.
        ** Give such values a special internal-use-only serial-type of 10
        ** so that they can be passed through to xUpdate and have
        ** a true sqlite3_value_nochange(). */
#ifndef SQLITE_ENABLE_NULL_TRIM
        assert( pOp->p5==OPFLAG_NOCHNG_MAGIC || CORRUPT_DB );
#endif
        pRec->uTemp = 10;
      }else{
        pRec->uTemp = 0;
      }
      nHdr++;
    }else if( pRec->flags & (MEM_Int|MEM_IntReal) ){
      /* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */
      i64 i = pRec->u.i;
      u64 uu;
      testcase( pRec->flags & MEM_Int );
      testcase( pRec->flags & MEM_IntReal );
      if( i<0 ){
        uu = ~i;
      }else{
        uu = i;
      }
      nHdr++;
      testcase( uu==127 );               testcase( uu==128 );
      testcase( uu==32767 );             testcase( uu==32768 );
      testcase( uu==8388607 );           testcase( uu==8388608 );
      testcase( uu==2147483647 );        testcase( uu==2147483648LL );
      testcase( uu==140737488355327LL ); testcase( uu==140737488355328LL );
      if( uu<=127 ){
        if( (i&1)==i && p->minWriteFileFormat>=4 ){
          pRec->uTemp = 8+(u32)uu;
        }else{
          nData++;
          pRec->uTemp = 1;
        }
      }else if( uu<=32767 ){
        nData += 2;
        pRec->uTemp = 2;
      }else if( uu<=8388607 ){
        nData += 3;
        pRec->uTemp = 3;
      }else if( uu<=2147483647 ){
        nData += 4;
        pRec->uTemp = 4;
      }else if( uu<=140737488355327LL ){
        nData += 6;
        pRec->uTemp = 5;
      }else{
        nData += 8;
        if( pRec->flags & MEM_IntReal ){
          /* If the value is IntReal and is going to take up 8 bytes to store
          ** as an integer, then we might as well make it an 8-byte floating
          ** point value */
          pRec->u.r = (double)pRec->u.i;
          pRec->flags &= ~MEM_IntReal;
          pRec->flags |= MEM_Real;
          pRec->uTemp = 7;
        }else{
          pRec->uTemp = 6;
        }
      }
    }else if( pRec->flags & MEM_Real ){
      nHdr++;
      nData += 8;
      pRec->uTemp = 7;
    }else{
      assert( db->mallocFailed || pRec->flags&(MEM_Str|MEM_Blob) );
      assert( pRec->n>=0 );
      len = (u32)pRec->n;
      serial_type = (len*2) + 12 + ((pRec->flags & MEM_Str)!=0);
      if( pRec->flags & MEM_Zero ){
        serial_type = 10;
      }else if( nData ){
        if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem;
      }else{
        nZero += pRec->u.nZero;
        serial_type += pRec->u.nZero*2;
        if( nData ){
          if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem;
          len += pRec->u.nZero;
        }else{
          nZero += pRec->u.nZero;
        len -= pRec->u.nZero;
      }
    }
    nData += len;
        }
      }
      nData += len;
    testcase( serial_type==127 );
    testcase( serial_type==128 );
    nHdr += serial_type<=127 ? 1 : sqlite3VarintLen(serial_type);
    pRec->uTemp = serial_type;
      nHdr += sqlite3VarintLen(serial_type);
      pRec->uTemp = serial_type;
    }
    if( pRec==pData0 ) break;
    pRec--;
  }while(1);

  /* EVIDENCE-OF: R-22564-11647 The header begins with a single varint
  ** which determines the total number of bytes in the header. The varint
  ** value is the size of the header in bytes including the size varint
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944































































2945
2946
2947
2948

2949
2950
2951
2952





2953
2954
2955
2956
2957
2958
2959
2960
2961



2962
2963
2964




2965
2966
2967

2968
2969
2970
2971
2972
2973
2974
2975



2976
2977
2978
2979
2980
2981
2982
3496
3497
3498
3499
3500
3501
3502




















3503
3504
3505
3506
3507
3508

3509
3510
3511
3512
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
3569
3570
3571
3572
3573
3574
3575

3576
3577
3578
3579

3580
3581
3582
3583
3584
3585

3586
3587
3588
3589
3590
3591
3592
3593
3594
3595



3596
3597
3598
3599
3600
3601

3602
3603

3604
3605
3606
3607


3608
3609
3610
3611
3612
3613
3614
3615
3616
3617







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-






-

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+



-
+
+
+
+
+

-







+
+
+
-
-
-
+
+
+
+


-
+

-




-
-
+
+
+







    if( nByte+nZero>db->aLimit[SQLITE_LIMIT_LENGTH] ){
      goto too_big;
    }
    if( sqlite3VdbeMemClearAndResize(pOut, (int)nByte) ){
      goto no_mem;
    }
  }
  zNewRecord = (u8 *)pOut->z;

  /* Write the record */
  i = putVarint32(zNewRecord, nHdr);
  j = nHdr;
  assert( pData0<=pLast );
  pRec = pData0;
  do{
    serial_type = pRec->uTemp;
    /* EVIDENCE-OF: R-06529-47362 Following the size varint are one or more
    ** additional varints, one per column. */
    i += putVarint32(&zNewRecord[i], serial_type);            /* serial type */
    /* EVIDENCE-OF: R-64536-51728 The values for each column in the record
    ** immediately follow the header. */
    j += sqlite3VdbeSerialPut(&zNewRecord[j], pRec, serial_type); /* content */
  }while( (++pRec)<=pLast );
  assert( i==nHdr );
  assert( j==nByte );

  assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
  pOut->n = (int)nByte;
  pOut->flags = MEM_Blob;
  if( nZero ){
    pOut->u.nZero = nZero;
    pOut->flags |= MEM_Zero;
  }
  REGISTER_TRACE(pOp->p3, pOut);
  UPDATE_MAX_BLOBSIZE(pOut);
  zHdr = (u8 *)pOut->z;
  zPayload = zHdr + nHdr;

  /* Write the record */
  if( nHdr<0x80 ){
    *(zHdr++) = nHdr;
  }else{
    zHdr += sqlite3PutVarint(zHdr,nHdr);
  }
  assert( pData0<=pLast );
  pRec = pData0;
  while( 1 /*exit-by-break*/ ){
    serial_type = pRec->uTemp;
    /* EVIDENCE-OF: R-06529-47362 Following the size varint are one or more
    ** additional varints, one per column.
    ** EVIDENCE-OF: R-64536-51728 The values for each column in the record
    ** immediately follow the header. */
    if( serial_type<=7 ){
      *(zHdr++) = serial_type;
      if( serial_type==0 ){
        /* NULL value.  No change in zPayload */
      }else{
        u64 v;
        u32 i;
        if( serial_type==7 ){
          assert( sizeof(v)==sizeof(pRec->u.r) );
          memcpy(&v, &pRec->u.r, sizeof(v));
          swapMixedEndianFloat(v);
        }else{
          v = pRec->u.i;
        }
        len = i = sqlite3SmallTypeSizes[serial_type];
        assert( i>0 );
        while( 1 /*exit-by-break*/ ){
          zPayload[--i] = (u8)(v&0xFF);
          if( i==0 ) break;
          v >>= 8;
        }
        zPayload += len;
      }
    }else if( serial_type<0x80 ){
      *(zHdr++) = serial_type;
      if( serial_type>=14 && pRec->n>0 ){
        assert( pRec->z!=0 );
        memcpy(zPayload, pRec->z, pRec->n);
        zPayload += pRec->n;
      }
    }else{
      zHdr += sqlite3PutVarint(zHdr, serial_type);
      if( pRec->n ){
        assert( pRec->z!=0 );
        memcpy(zPayload, pRec->z, pRec->n);
        zPayload += pRec->n;
      }
    }
    if( pRec==pLast ) break;
    pRec++;
  }
  assert( nHdr==(int)(zHdr - (u8*)pOut->z) );
  assert( nByte==(int)(zPayload - (u8*)pOut->z) );

  assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
  REGISTER_TRACE(pOp->p3, pOut);
  break;
}

/* Opcode: Count P1 P2 * * *
/* Opcode: Count P1 P2 P3 * *
** Synopsis: r[P2]=count()
**
** Store the number of entries (an integer value) in the table or index 
** opened by cursor P1 in register P2
** opened by cursor P1 in register P2.
**
** If P3==0, then an exact count is obtained, which involves visiting
** every btree page of the table.  But if P3 is non-zero, an estimate
** is returned based on the current cursor position.  
*/
#ifndef SQLITE_OMIT_BTREECOUNT
case OP_Count: {         /* out2 */
  i64 nEntry;
  BtCursor *pCrsr;

  assert( p->apCsr[pOp->p1]->eCurType==CURTYPE_BTREE );
  pCrsr = p->apCsr[pOp->p1]->uc.pCursor;
  assert( pCrsr );
  if( pOp->p3 ){
    nEntry = sqlite3BtreeRowCountEst(pCrsr);
  }else{
  nEntry = 0;  /* Not needed.  Only used to silence a warning. */
  rc = sqlite3BtreeCount(pCrsr, &nEntry);
  if( rc ) goto abort_due_to_error;
    nEntry = 0;  /* Not needed.  Only used to silence a warning. */
    rc = sqlite3BtreeCount(db, pCrsr, &nEntry);
    if( rc ) goto abort_due_to_error;
  }
  pOut = out2Prerelease(p, pOp);
  pOut->u.i = nEntry;
  break;
  goto check_for_interrupt;
}
#endif

/* Opcode: Savepoint P1 * * P4 *
**
** Open, release or rollback the savepoint named by parameter P4, depending
** on the value of P1. To open a new savepoint, P1==0. To release (commit) an
** existing savepoint, P1==1, or to rollback an existing savepoint P1==2.
** on the value of P1. To open a new savepoint set P1==0 (SAVEPOINT_BEGIN).
** To release (commit) an existing savepoint set P1==1 (SAVEPOINT_RELEASE).
** To rollback an existing savepoint set P1==2 (SAVEPOINT_ROLLBACK).
*/
case OP_Savepoint: {
  int p1;                         /* Value of P1 operand */
  char *zName;                    /* Name of savepoint */
  int nName;
  Savepoint *pNew;
  Savepoint *pSavepoint;
3036
3037
3038
3039
3040
3041
3042

3043
3044
3045
3046
3047
3048
3049
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685







+







        pNew->pNext = db->pSavepoint;
        db->pSavepoint = pNew;
        pNew->nDeferredCons = db->nDeferredCons;
        pNew->nDeferredImmCons = db->nDeferredImmCons;
      }
    }
  }else{
    assert( p1==SAVEPOINT_RELEASE || p1==SAVEPOINT_ROLLBACK );
    iSavepoint = 0;

    /* Find the named savepoint. If there is no such savepoint, then an
    ** an error is returned to the user.  */
    for(
      pSavepoint = db->pSavepoint; 
      pSavepoint && sqlite3StrICmp(pSavepoint->zName, zName);
3064
3065
3066
3067
3068
3069
3070
3071

3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084





3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096

3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110

3111
3112
3113
3114
3115
3116
3117
3700
3701
3702
3703
3704
3705
3706

3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718

3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759







-
+











-

+
+
+
+
+












+














+







    }else{

      /* Determine whether or not this is a transaction savepoint. If so,
      ** and this is a RELEASE command, then the current transaction 
      ** is committed. 
      */
      int isTransaction = pSavepoint->pNext==0 && db->isTransactionSavepoint;
      assert( db->bConcurrent==0 || db->isTransactionSavepoint==0 );
      assert( db->eConcurrent==0 || db->isTransactionSavepoint==0 );
      if( isTransaction && p1==SAVEPOINT_RELEASE ){
        if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){
          goto vdbe_return;
        }
        db->autoCommit = 1;
        if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){
          p->pc = (int)(pOp - aOp);
          db->autoCommit = 0;
          p->rc = rc = SQLITE_BUSY;
          goto vdbe_return;
        }
        db->isTransactionSavepoint = 0;
        rc = p->rc;
        if( rc ){
          db->autoCommit = 0;
        }else{
          db->isTransactionSavepoint = 0;
        }
      }else{
        int isSchemaChange;
        iSavepoint = db->nSavepoint - iSavepoint - 1;
        if( p1==SAVEPOINT_ROLLBACK ){
          isSchemaChange = (db->mDbFlags & DBFLAG_SchemaChange)!=0;
          for(ii=0; ii<db->nDb; ii++){
            rc = sqlite3BtreeTripAllCursors(db->aDb[ii].pBt,
                                       SQLITE_ABORT_ROLLBACK,
                                       isSchemaChange==0);
            if( rc!=SQLITE_OK ) goto abort_due_to_error;
          }
        }else{
          assert( p1==SAVEPOINT_RELEASE );
          isSchemaChange = 0;
        }
        for(ii=0; ii<db->nDb; ii++){
          rc = sqlite3BtreeSavepoint(db->aDb[ii].pBt, p1, iSavepoint);
          if( rc!=SQLITE_OK ){
            goto abort_due_to_error;
          }
        }
        if( isSchemaChange ){
          sqlite3ExpirePreparedStatements(db, 0);
          sqlite3ResetAllSchemasOfConnection(db);
          db->mDbFlags |= DBFLAG_SchemaChange;
        }
      }
      if( rc ) goto abort_due_to_error;
  
      /* Regardless of whether this is a RELEASE or ROLLBACK, destroy all 
      ** savepoints nested inside of the savepoint being operated on. */
      while( db->pSavepoint!=pSavepoint ){
        pTmp = db->pSavepoint;
        db->pSavepoint = pTmp->pNext;
        sqlite3DbFree(db, pTmp);
3126
3127
3128
3129
3130
3131
3132

3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143



3144

3145
3146
3147
3148
3149
3150
3151
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789

3790
3791
3792
3793
3794
3795
3796
3797







+











+
+
+
-
+







        assert( pSavepoint==db->pSavepoint );
        db->pSavepoint = pSavepoint->pNext;
        sqlite3DbFree(db, pSavepoint);
        if( !isTransaction ){
          db->nSavepoint--;
        }
      }else{
        assert( p1==SAVEPOINT_ROLLBACK );
        db->nDeferredCons = pSavepoint->nDeferredCons;
        db->nDeferredImmCons = pSavepoint->nDeferredImmCons;
      }

      if( !isTransaction || p1==SAVEPOINT_ROLLBACK ){
        rc = sqlite3VtabSavepoint(db, p1, iSavepoint);
        if( rc!=SQLITE_OK ) goto abort_due_to_error;
      }
    }
  }
  if( rc ) goto abort_due_to_error;
  if( p->eVdbeState==VDBE_HALT_STATE ){
    rc = SQLITE_DONE;
    goto vdbe_return;

  }
  break;
}

/* Opcode: AutoCommit P1 P2 P3 * *
**
** Set the database auto-commit flag to P1 (1 or 0). If P2 is true, roll
** back any currently active btree transactions. If there are any active
3165
3166
3167
3168
3169
3170
3171
3172

3173
3174
3175
3176
3177
3178
3179
3180
3181

3182
3183

3184
3185
3186
3187
3188
3189
3190
3811
3812
3813
3814
3815
3816
3817

3818
3819
3820
3821
3822
3823
3824
3825
3826

3827
3828

3829
3830
3831
3832
3833
3834
3835
3836







-
+








-
+

-
+








  desiredAutoCommit = pOp->p1;
  iRollback = pOp->p2;
  bConcurrent = pOp->p3;
  assert( desiredAutoCommit==1 || desiredAutoCommit==0 );
  assert( desiredAutoCommit==1 || iRollback==0 );
  assert( desiredAutoCommit==0 || bConcurrent==0 );
  assert( db->autoCommit==0 || db->bConcurrent==0 );
  assert( db->autoCommit==0 || db->eConcurrent==CONCURRENT_NONE );
  assert( db->nVdbeActive>0 );  /* At least this one VM is active */
  assert( p->bIsReader );

  if( desiredAutoCommit!=db->autoCommit ){
    if( iRollback ){
      assert( desiredAutoCommit==1 );
      sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
      db->autoCommit = 1;
      db->bConcurrent = 0;
      db->eConcurrent = CONCURRENT_NONE;
    }else if( desiredAutoCommit
            && (db->nVdbeWrite>0 || (db->bConcurrent && db->nVdbeActive>1)) ){
            && (db->nVdbeWrite>0 || (db->eConcurrent && db->nVdbeActive>1)) ){
      /* A transaction may only be committed if there are no other active
      ** writer VMs. If the transaction is CONCURRENT, then it may only be
      ** committed if there are no active VMs at all (readers or writers).
      **
      ** If this instruction is a COMMIT and the transaction may not be
      ** committed due to one of the conditions above, return an error
      ** indicating that other VMs must complete before the COMMIT can 
3202
3203
3204
3205
3206
3207
3208

3209

3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227

3228
3229
3230
3231
3232
3233
3234
3235
3236


3237
3238
3239
3240
3241
3242
3243
3848
3849
3850
3851
3852
3853
3854
3855

3856

3857
3858
3859
3860
3861
3862
3863
3864
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







+
-
+
-
















-
+








-
+
+







    if( (hrc & 0xFF)==SQLITE_BUSY ){
      p->pc = (int)(pOp - aOp);
      db->autoCommit = (u8)(1-desiredAutoCommit);
      p->rc = hrc;
      rc = SQLITE_BUSY;
      goto vdbe_return;
    }
    assert( bConcurrent==CONCURRENT_NONE || bConcurrent==CONCURRENT_OPEN );
    db->bConcurrent = (u8)bConcurrent;
    db->eConcurrent = (u8)bConcurrent;
    assert( db->nStatement==0 );
    sqlite3CloseSavepoints(db);
    if( p->rc==SQLITE_OK ){
      rc = SQLITE_DONE;
    }else{
      rc = SQLITE_ERROR;
    }
    goto vdbe_return;
  }else{
    sqlite3VdbeError(p,
        (!desiredAutoCommit)?"cannot start a transaction within a transaction":(
        (iRollback)?"cannot rollback - no transaction is active":
                   "cannot commit - no transaction is active"));
         
    rc = SQLITE_ERROR;
    goto abort_due_to_error;
  }
  break;
  /*NOTREACHED*/ assert(0);
}

/* Opcode: Transaction P1 P2 P3 P4 P5
**
** Begin a transaction on database P1 if a transaction is not already
** active.
** If P2 is non-zero, then a write-transaction is started, or if a 
** read-transaction is already active, it is upgraded to a write-transaction.
** If P2 is zero, then a read-transaction is started.
** If P2 is zero, then a read-transaction is started.  If P2 is 2 or more
** then an exclusive transaction is started.
**
** P1 is the index of the database file on which the transaction is
** started.  Index 0 is the main database file and index 1 is the
** file used for temporary tables.  Indices of 2 or more are used for
** attached databases.
**
** If a write-transaction is started and the Vdbe.usesStmtJournal flag is
3259
3260
3261
3262
3263
3264
3265

3266
3267
3268
3269

3270
3271

3272
3273









3274
3275
3276


3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291


3292
3293
3294

3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313

3314
3315


3316
3317
3318
3319
3320
3321
3322
3323
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921


3922
3923
3924
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
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973


3974
3975

3976
3977
3978
3979
3980
3981
3982







+




+


+
-
-
+
+
+
+
+
+
+
+
+


-
+
+














-
+
+


-
+



















+
-
-
+
+
-







** if the schema generation counter in P4 differs from the current
** generation counter, then an SQLITE_SCHEMA error is raised and execution
** halts.  The sqlite3_step() wrapper function might then reprepare the
** statement and rerun it from the beginning.
*/
case OP_Transaction: {
  Btree *pBt;
  Db *pDb;
  int iMeta = 0;

  assert( p->bIsReader );
  assert( p->readOnly==0 || pOp->p2==0 );
  assert( pOp->p2>=0 && pOp->p2<=2 );
  assert( pOp->p1>=0 && pOp->p1<db->nDb );
  assert( DbMaskTest(p->btreeMask, pOp->p1) );
  assert( rc==SQLITE_OK );
  if( pOp->p2 && (db->flags & SQLITE_QueryOnly)!=0 ){
    rc = SQLITE_READONLY;
  if( pOp->p2 && (db->flags & (SQLITE_QueryOnly|SQLITE_CorruptRdOnly))!=0 ){
    if( db->flags & SQLITE_QueryOnly ){
      /* Writes prohibited by the "PRAGMA query_only=TRUE" statement */
      rc = SQLITE_READONLY;
    }else{
      /* Writes prohibited due to a prior SQLITE_CORRUPT in the current
      ** transaction */
      rc = SQLITE_CORRUPT;
    }
    goto abort_due_to_error;
  }
  pBt = db->aDb[pOp->p1].pBt;
  pDb = &db->aDb[pOp->p1];
  pBt = pDb->pBt;

  if( pBt ){
    rc = sqlite3BtreeBeginTrans(pBt, pOp->p2, &iMeta);
    testcase( rc==SQLITE_BUSY_SNAPSHOT );
    testcase( rc==SQLITE_BUSY_RECOVERY );
    if( rc!=SQLITE_OK ){
      if( (rc&0xff)==SQLITE_BUSY ){
        p->pc = (int)(pOp - aOp);
        p->rc = rc;
        goto vdbe_return;
      }
      goto abort_due_to_error;
    }

    if( pOp->p2 && p->usesStmtJournal 
    if( p->usesStmtJournal
     && pOp->p2
     && (db->autoCommit==0 || db->nVdbeRead>1) 
    ){
      assert( sqlite3BtreeIsInTrans(pBt) );
      assert( sqlite3BtreeTxnState(pBt)==SQLITE_TXN_WRITE );
      if( p->iStatement==0 ){
        assert( db->nStatement>=0 && db->nSavepoint>=0 );
        db->nStatement++; 
        p->iStatement = db->nSavepoint + db->nStatement;
      }

      rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, p->iStatement-1);
      if( rc==SQLITE_OK ){
        rc = sqlite3BtreeBeginStmt(pBt, p->iStatement);
      }

      /* Store the current value of the database handles deferred constraint
      ** counter. If the statement transaction needs to be rolled back,
      ** the value of this counter needs to be restored too.  */
      p->nStmtDefCons = db->nDeferredCons;
      p->nStmtDefImmCons = db->nDeferredImmCons;
    }
  }
  assert( pOp->p5==0 || pOp->p4type==P4_INT32 );
  if( rc==SQLITE_OK
  if( pOp->p5
   && (iMeta!=pOp->p3
   && pOp->p5
   && (iMeta!=pOp->p3 || pDb->pSchema->iGeneration!=pOp->p4.i)
      || db->aDb[pOp->p1].pSchema->iGeneration!=pOp->p4.i)
  ){
    /*
    ** IMPLEMENTATION-OF: R-03189-51135 As each SQL statement runs, the schema
    ** version is checked to ensure that the schema has not changed since the
    ** SQL statement was prepared.
    */
    sqlite3DbFree(db, p->zErrMsg);
3336
3337
3338
3339
3340
3341
3342





3343
3344
3345
3346
3347
3348
3349
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013







+
+
+
+
+







    ** a v-table method.
    */
    if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){
      sqlite3ResetOneSchema(db, pOp->p1);
    }
    p->expired = 1;
    rc = SQLITE_SCHEMA;

    /* Set changeCntOn to 0 to prevent the value returned by sqlite3_changes()
    ** from being modified in sqlite3VdbeHalt(). If this statement is
    ** reprepared, changeCntOn will be set again. */
    p->changeCntOn = 0;
  }
  if( rc ) goto abort_due_to_error;
  break;
}

/* Opcode: ReadCookie P1 P2 P3 * *
**
3372
3373
3374
3375
3376
3377
3378
3379

3380
3381
3382
3383
3384
3385
3386
3387





3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401

3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416

3417

3418
3419
3420
3421
3422
3423
3424
4036
4037
4038
4039
4040
4041
4042

4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069

4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083


4084
4085
4086
4087
4088
4089
4090
4091
4092
4093







-
+








+
+
+
+
+













-
+













-
-
+

+








  sqlite3BtreeGetMeta(db->aDb[iDb].pBt, iCookie, (u32 *)&iMeta);
  pOut = out2Prerelease(p, pOp);
  pOut->u.i = iMeta;
  break;
}

/* Opcode: SetCookie P1 P2 P3 * *
/* Opcode: SetCookie P1 P2 P3 * P5
**
** Write the integer value P3 into cookie number P2 of database P1.
** P2==1 is the schema version.  P2==2 is the database format.
** P2==3 is the recommended pager cache 
** size, and so forth.  P1==0 is the main database file and P1==1 is the 
** database file used to store temporary tables.
**
** A transaction must be started before executing this opcode.
**
** If P2 is the SCHEMA_VERSION cookie (cookie number 1) then the internal
** schema version is set to P3-P5.  The "PRAGMA schema_version=N" statement
** has P5 set to 1, so that the internal schema version will be different
** from the database schema version, resulting in a schema reset.
*/
case OP_SetCookie: {
  Db *pDb;

  sqlite3VdbeIncrWriteCounter(p, 0);
  assert( pOp->p2<SQLITE_N_BTREE_META );
  assert( pOp->p1>=0 && pOp->p1<db->nDb );
  assert( DbMaskTest(p->btreeMask, pOp->p1) );
  assert( p->readOnly==0 );
  pDb = &db->aDb[pOp->p1];
  assert( pDb->pBt!=0 );
  assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) );
#ifndef SQLITE_OMIT_CONCURRENT
  if( db->bConcurrent 
  if( db->eConcurrent 
   && (pOp->p2==BTREE_USER_VERSION || pOp->p2==BTREE_APPLICATION_ID)
  ){
    rc = SQLITE_ERROR;
    sqlite3VdbeError(p, "cannot modify %s within CONCURRENT transaction",
        pOp->p2==BTREE_USER_VERSION ? "user_version" : "application_id"
    );
    goto abort_due_to_error;
  }
#endif
  /* See note about index shifting on OP_ReadCookie */
  rc = sqlite3BtreeUpdateMeta(pDb->pBt, pOp->p2, pOp->p3);
  if( pOp->p2==BTREE_SCHEMA_VERSION ){
    /* When the schema cookie changes, record the new cookie internally */
    assert( pOp->p1==1 || db->bConcurrent==0 );
    pDb->pSchema->schema_cookie = pOp->p3;
    *(u32*)&pDb->pSchema->schema_cookie = *(u32*)&pOp->p3 - pOp->p5;
    db->mDbFlags |= DBFLAG_SchemaChange;
    sqlite3FkClearTriggerCache(db, pOp->p1);
  }else if( pOp->p2==BTREE_FILE_FORMAT ){
    /* Record changes in the file format */
    pDb->pSchema->file_format = pOp->p3;
  }
  if( pOp->p1==1 ){
    /* Invalidate all prepared statements whenever the TEMP database
    ** schema is changed.  Ticket #1644 */
3440
3441
3442
3443
3444
3445
3446
3447

3448
3449
3450
3451
3452
3453
3454
4109
4110
4111
4112
4113
4114
4115

4116
4117
4118
4119
4120
4121
4122
4123







-
+







** values need not be contiguous but all P1 values should be small integers.
** It is an error for P1 to be negative.
**
** Allowed P5 bits:
** <ul>
** <li>  <b>0x02 OPFLAG_SEEKEQ</b>: This cursor will only be used for
**       equality lookups (implemented as a pair of opcodes OP_SeekGE/OP_IdxGT
**       of OP_SeekLE/OP_IdxGT)
**       of OP_SeekLE/OP_IdxLT)
** </ul>
**
** The P4 value may be either an integer (P4_INT32) or a pointer to
** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo 
** object, then table being opened must be an [index b-tree] where the
** KeyInfo object defines the content and collating 
** sequence of that index b-tree. Otherwise, if P4 is an integer 
3470
3471
3472
3473
3474
3475
3476
3477

3478
3479
3480
3481
3482
3483
3484
4139
4140
4141
4142
4143
4144
4145

4146
4147
4148
4149
4150
4151
4152
4153







-
+







** be the same as every other ReopenIdx or OpenRead for the same cursor
** number.
**
** Allowed P5 bits:
** <ul>
** <li>  <b>0x02 OPFLAG_SEEKEQ</b>: This cursor will only be used for
**       equality lookups (implemented as a pair of opcodes OP_SeekGE/OP_IdxGT
**       of OP_SeekLE/OP_IdxGT)
**       of OP_SeekLE/OP_IdxLT)
** </ul>
**
** See also: OP_OpenRead, OP_OpenWrite
*/
/* Opcode: OpenWrite P1 P2 P3 P4 P5
** Synopsis: root=P2 iDb=P3
**
3494
3495
3496
3497
3498
3499
3500
3501

3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
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
3569

3570
3571
3572
3573
3574
3575
3576
4163
4164
4165
4166
4167
4168
4169

4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184

4185
4186
4187

4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205

4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220

4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244

4245
4246
4247
4248
4249
4250
4251
4252







-
+














-
+


-
+











+
+




-
+














-
+







+
+
+
+
+











-
+







** value, then the table being opened must be a [table b-tree] with a
** number of columns no less than the value of P4.
**
** Allowed P5 bits:
** <ul>
** <li>  <b>0x02 OPFLAG_SEEKEQ</b>: This cursor will only be used for
**       equality lookups (implemented as a pair of opcodes OP_SeekGE/OP_IdxGT
**       of OP_SeekLE/OP_IdxGT)
**       of OP_SeekLE/OP_IdxLT)
** <li>  <b>0x08 OPFLAG_FORDELETE</b>: This cursor is used only to seek
**       and subsequently delete entries in an index btree.  This is a
**       hint to the storage engine that the storage engine is allowed to
**       ignore.  The hint is not used by the official SQLite b*tree storage
**       engine, but is used by COMDB2.
** <li>  <b>0x10 OPFLAG_P2ISREG</b>: Use the content of register P2
**       as the root page, not the value of P2 itself.
** </ul>
**
** This instruction works like OpenRead except that it opens the cursor
** in read/write mode.
**
** See also: OP_OpenRead, OP_ReopenIdx
*/
case OP_ReopenIdx: {
case OP_ReopenIdx: {         /* ncycle */
  int nField;
  KeyInfo *pKeyInfo;
  int p2;
  u32 p2;
  int iDb;
  int wrFlag;
  Btree *pX;
  VdbeCursor *pCur;
  Db *pDb;

  assert( pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ );
  assert( pOp->p4type==P4_KEYINFO );
  pCur = p->apCsr[pOp->p1];
  if( pCur && pCur->pgnoRoot==(u32)pOp->p2 ){
    assert( pCur->iDb==pOp->p3 );      /* Guaranteed by the code generator */
    assert( pCur->eCurType==CURTYPE_BTREE );
    sqlite3BtreeClearCursor(pCur->uc.pCursor);
    goto open_cursor_set_hints;
  }
  /* If the cursor is not currently open or is open on a different
  ** index, then fall through into OP_OpenRead to force a reopen */
case OP_OpenRead:
case OP_OpenRead:            /* ncycle */
case OP_OpenWrite:

  assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ );
  assert( p->bIsReader );
  assert( pOp->opcode==OP_OpenRead || pOp->opcode==OP_ReopenIdx
          || p->readOnly==0 );

  if( p->expired==1 ){
    rc = SQLITE_ABORT_ROLLBACK;
    goto abort_due_to_error;
  }

  nField = 0;
  pKeyInfo = 0;
  p2 = pOp->p2;
  p2 = (u32)pOp->p2;
  iDb = pOp->p3;
  assert( iDb>=0 && iDb<db->nDb );
  assert( DbMaskTest(p->btreeMask, iDb) );
  pDb = &db->aDb[iDb];
  pX = pDb->pBt;
  assert( pX!=0 );
  if( pOp->opcode==OP_OpenWrite ){
#ifndef SQLITE_OMIT_CONCURRENT
    if( db->eConcurrent==CONCURRENT_OPEN && p2==1 && iDb!=1 ){
      db->eConcurrent = CONCURRENT_SCHEMA;
    }
#endif
    assert( OPFLAG_FORDELETE==BTREE_FORDELETE );
    wrFlag = BTREE_WRCSR | (pOp->p5 & OPFLAG_FORDELETE);
    assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
    if( pDb->pSchema->file_format < p->minWriteFileFormat ){
      p->minWriteFileFormat = pDb->pSchema->file_format;
    }
  }else{
    wrFlag = 0;
  }
  if( pOp->p5 & OPFLAG_P2ISREG ){
    assert( p2>0 );
    assert( p2<=(p->nMem+1 - p->nCursor) );
    assert( p2<=(u32)(p->nMem+1 - p->nCursor) );
    assert( pOp->opcode==OP_OpenWrite );
    pIn2 = &aMem[p2];
    assert( memIsValid(pIn2) );
    assert( (pIn2->flags & MEM_Int)!=0 );
    sqlite3VdbeMemIntegerify(pIn2);
    p2 = (int)pIn2->u.i;
    /* The p2 value always comes from a prior OP_CreateBtree opcode and
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
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
3659



3660
3661
3662
3663
3664
3665
3666
3667
3668
3669




3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680


3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691



















3692
3693


3694
3695
3696
3697
3698
3699






3700
3701
3702
3703
3704
3705
3706
3707







3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
























3725
3726

3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745

3746
3747
3748
3749
3750
3751
3752
4262
4263
4264
4265
4266
4267
4268

4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289

4290

4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304

4305
4306
4307
4308
4309
4310

4311
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
4360
4361
4362
4363
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
4394
4395
4396
4397
4398


4399
4400






4401
4402
4403
4404
4405
4406








4407
4408
4409
4410
4411
4412
4413

















4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438

4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457

4458
4459
4460
4461
4462
4463
4464
4465







-
+

+


















-

-














-
+




+
-
+

-
+





+
+
+
+
+
-
+









-
+






+
+
+










+
+
+
+









-
-
+
+











+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+


















-
+







    nField = pKeyInfo->nAllField;
  }else if( pOp->p4type==P4_INT32 ){
    nField = pOp->p4.i;
  }
  assert( pOp->p1>=0 );
  assert( nField>=0 );
  testcase( nField==0 );  /* Table with INTEGER PRIMARY KEY and nothing else */
  pCur = allocateCursor(p, pOp->p1, nField, iDb, CURTYPE_BTREE);
  pCur = allocateCursor(p, pOp->p1, nField, CURTYPE_BTREE);
  if( pCur==0 ) goto no_mem;
  pCur->iDb = iDb;
  pCur->nullRow = 1;
  pCur->isOrdered = 1;
  pCur->pgnoRoot = p2;
#ifdef SQLITE_DEBUG
  pCur->wrFlag = wrFlag;
#endif
  rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->uc.pCursor);
  pCur->pKeyInfo = pKeyInfo;
  /* Set the VdbeCursor.isTable variable. Previous versions of
  ** SQLite used to check if the root-page flags were sane at this point
  ** and report database corruption if they were not, but this check has
  ** since moved into the btree layer.  */  
  pCur->isTable = pOp->p4type!=P4_KEYINFO;

open_cursor_set_hints:
  assert( OPFLAG_BULKCSR==BTREE_BULKLOAD );
  assert( OPFLAG_SEEKEQ==BTREE_SEEK_EQ );
  testcase( pOp->p5 & OPFLAG_BULKCSR );
#ifdef SQLITE_ENABLE_CURSOR_HINTS
  testcase( pOp->p2 & OPFLAG_SEEKEQ );
#endif
  sqlite3BtreeCursorHintFlags(pCur->uc.pCursor,
                               (pOp->p5 & (OPFLAG_BULKCSR|OPFLAG_SEEKEQ)));
  if( rc ) goto abort_due_to_error;
  break;
}

/* Opcode: OpenDup P1 P2 * * *
**
** Open a new cursor P1 that points to the same ephemeral table as
** cursor P2.  The P2 cursor must have been opened by a prior OP_OpenEphemeral
** opcode.  Only ephemeral cursors may be duplicated.
**
** Duplicate ephemeral cursors are used for self-joins of materialized views.
*/
case OP_OpenDup: {
case OP_OpenDup: {           /* ncycle */
  VdbeCursor *pOrig;    /* The original cursor to be duplicated */
  VdbeCursor *pCx;      /* The new cursor */

  pOrig = p->apCsr[pOp->p2];
  assert( pOrig );
  assert( pOrig->pBtx!=0 );  /* Only ephemeral cursors can be duplicated */
  assert( pOrig->isEphemeral );  /* Only ephemeral cursors can be duplicated */

  pCx = allocateCursor(p, pOp->p1, pOrig->nField, -1, CURTYPE_BTREE);
  pCx = allocateCursor(p, pOp->p1, pOrig->nField, CURTYPE_BTREE);
  if( pCx==0 ) goto no_mem;
  pCx->nullRow = 1;
  pCx->isEphemeral = 1;
  pCx->pKeyInfo = pOrig->pKeyInfo;
  pCx->isTable = pOrig->isTable;
  pCx->pgnoRoot = pOrig->pgnoRoot;
  pCx->isOrdered = pOrig->isOrdered;
  pCx->ub.pBtx = pOrig->ub.pBtx;
  pCx->noReuse = 1;
  pOrig->noReuse = 1;
  rc = sqlite3BtreeCursor(pOrig->pBtx, MASTER_ROOT, BTREE_WRCSR,
  rc = sqlite3BtreeCursor(pCx->ub.pBtx, pCx->pgnoRoot, BTREE_WRCSR, 
                          pCx->pKeyInfo, pCx->uc.pCursor);
  /* The sqlite3BtreeCursor() routine can only fail for the first cursor
  ** opened for a database.  Since there is already an open cursor when this
  ** opcode is run, the sqlite3BtreeCursor() cannot fail */
  assert( rc==SQLITE_OK );
  break;
}


/* Opcode: OpenEphemeral P1 P2 * P4 P5
/* Opcode: OpenEphemeral P1 P2 P3 P4 P5
** Synopsis: nColumn=P2
**
** Open a new cursor P1 to a transient table.
** The cursor is always opened read/write even if 
** the main database is read-only.  The ephemeral
** table is deleted automatically when the cursor is closed.
**
** If the cursor P1 is already opened on an ephemeral table, the table
** is cleared (all content is erased).
**
** P2 is the number of columns in the ephemeral table.
** The cursor points to a BTree table if P4==0 and to a BTree index
** if P4 is not 0.  If P4 is not NULL, it points to a KeyInfo structure
** that defines the format of keys in the index.
**
** The P5 parameter can be a mask of the BTREE_* flags defined
** in btree.h.  These flags control aspects of the operation of
** the btree.  The BTREE_OMIT_JOURNAL and BTREE_SINGLE flags are
** added automatically.
**
** If P3 is positive, then reg[P3] is modified slightly so that it
** can be used as zero-length data for OP_Insert.  This is an optimization
** that avoids an extra OP_Blob opcode to initialize that register.
*/
/* Opcode: OpenAutoindex P1 P2 * P4 *
** Synopsis: nColumn=P2
**
** This opcode works the same as OP_OpenEphemeral.  It has a
** different name to distinguish its use.  Tables created using
** by this opcode will be used for automatically created transient
** indices in joins.
*/
case OP_OpenAutoindex: 
case OP_OpenEphemeral: {
case OP_OpenAutoindex:       /* ncycle */
case OP_OpenEphemeral: {     /* ncycle */
  VdbeCursor *pCx;
  KeyInfo *pKeyInfo;

  static const int vfsFlags = 
      SQLITE_OPEN_READWRITE |
      SQLITE_OPEN_CREATE |
      SQLITE_OPEN_EXCLUSIVE |
      SQLITE_OPEN_DELETEONCLOSE |
      SQLITE_OPEN_TRANSIENT_DB;
  assert( pOp->p1>=0 );
  assert( pOp->p2>=0 );
  if( pOp->p3>0 ){
    /* Make register reg[P3] into a value that can be used as the data
    ** form sqlite3BtreeInsert() where the length of the data is zero. */
    assert( pOp->p2==0 ); /* Only used when number of columns is zero */
    assert( pOp->opcode==OP_OpenEphemeral );
    assert( aMem[pOp->p3].flags & MEM_Null );
    aMem[pOp->p3].n = 0;
    aMem[pOp->p3].z = "";
  }
  pCx = p->apCsr[pOp->p1];
  if( pCx && !pCx->noReuse &&  ALWAYS(pOp->p2<=pCx->nField) ){
    /* If the ephermeral table is already open and has no duplicates from
    ** OP_OpenDup, then erase all existing content so that the table is
    ** empty again, rather than creating a new table. */
    assert( pCx->isEphemeral );
    pCx->seqCount = 0;
    pCx->cacheStatus = CACHE_STALE;
    rc = sqlite3BtreeClearTable(pCx->ub.pBtx, pCx->pgnoRoot, 0);
  }else{
  pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, CURTYPE_BTREE);
  if( pCx==0 ) goto no_mem;
    pCx = allocateCursor(p, pOp->p1, pOp->p2, CURTYPE_BTREE);
    if( pCx==0 ) goto no_mem;
  pCx->nullRow = 1;
  pCx->isEphemeral = 1;
  rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBtx, 
                        BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
  if( rc==SQLITE_OK ){
    rc = sqlite3BtreeBeginTrans(pCx->pBtx, 1, 0);
    pCx->isEphemeral = 1;
    rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->ub.pBtx, 
                          BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5,
                          vfsFlags);
    if( rc==SQLITE_OK ){
      rc = sqlite3BtreeBeginTrans(pCx->ub.pBtx, 1, 0);
  }
  if( rc==SQLITE_OK ){
    /* If a transient index is required, create it by calling
    ** sqlite3BtreeCreateTable() with the BTREE_BLOBKEY flag before
    ** opening it. If a transient table is required, just use the
    ** automatically created table with root-page 1 (an BLOB_INTKEY table).
    */
    if( (pCx->pKeyInfo = pKeyInfo = pOp->p4.pKeyInfo)!=0 ){
      if( rc==SQLITE_OK ){
        /* If a transient index is required, create it by calling
        ** sqlite3BtreeCreateTable() with the BTREE_BLOBKEY flag before
        ** opening it. If a transient table is required, just use the
        ** automatically created table with root-page 1 (an BLOB_INTKEY table).
        */
        if( (pCx->pKeyInfo = pKeyInfo = pOp->p4.pKeyInfo)!=0 ){
      int pgno;
      assert( pOp->p4type==P4_KEYINFO );
      rc = sqlite3BtreeCreateTable(pCx->pBtx, &pgno, BTREE_BLOBKEY | pOp->p5); 
      if( rc==SQLITE_OK ){
        assert( pgno==MASTER_ROOT+1 );
        assert( pKeyInfo->db==db );
        assert( pKeyInfo->enc==ENC(db) );
        rc = sqlite3BtreeCursor(pCx->pBtx, pgno, BTREE_WRCSR,
                                pKeyInfo, pCx->uc.pCursor);
      }
      pCx->isTable = 0;
    }else{
      rc = sqlite3BtreeCursor(pCx->pBtx, MASTER_ROOT, BTREE_WRCSR,
                              0, pCx->uc.pCursor);
      pCx->isTable = 1;
    }
  }
          assert( pOp->p4type==P4_KEYINFO );
          rc = sqlite3BtreeCreateTable(pCx->ub.pBtx, &pCx->pgnoRoot,
              BTREE_BLOBKEY | pOp->p5); 
          if( rc==SQLITE_OK ){
            assert( pCx->pgnoRoot==SCHEMA_ROOT+1 );
            assert( pKeyInfo->db==db );
            assert( pKeyInfo->enc==ENC(db) );
            rc = sqlite3BtreeCursor(pCx->ub.pBtx, pCx->pgnoRoot, BTREE_WRCSR,
                pKeyInfo, pCx->uc.pCursor);
          }
          pCx->isTable = 0;
        }else{
          pCx->pgnoRoot = SCHEMA_ROOT;
          rc = sqlite3BtreeCursor(pCx->ub.pBtx, SCHEMA_ROOT, BTREE_WRCSR,
              0, pCx->uc.pCursor);
          pCx->isTable = 1;
        }
      }
      pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
      if( rc ){
        sqlite3BtreeClose(pCx->ub.pBtx);
      }
    }
  }
  if( rc ) goto abort_due_to_error;
  pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
  pCx->nullRow = 1;
  break;
}

/* Opcode: SorterOpen P1 P2 P3 P4 *
**
** This opcode works like OP_OpenEphemeral except that it opens
** a transient index that is specifically designed to sort large
** tables using an external merge-sort algorithm.
**
** If argument P3 is non-zero, then it indicates that the sorter may
** assume that a stable sort considering the first P3 fields of each
** key is sufficient to produce the required results.
*/
case OP_SorterOpen: {
  VdbeCursor *pCx;

  assert( pOp->p1>=0 );
  assert( pOp->p2>=0 );
  pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, CURTYPE_SORTER);
  pCx = allocateCursor(p, pOp->p1, pOp->p2, CURTYPE_SORTER);
  if( pCx==0 ) goto no_mem;
  pCx->pKeyInfo = pOp->p4.pKeyInfo;
  assert( pCx->pKeyInfo->db==db );
  assert( pCx->pKeyInfo->enc==ENC(db) );
  rc = sqlite3VdbeSorterInit(db, pOp->p3, pCx);
  if( rc ) goto abort_due_to_error;
  break;
3787
3788
3789
3790
3791
3792
3793
3794

3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813

3814
3815
3816
3817
3818
3819
3820
4500
4501
4502
4503
4504
4505
4506

4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525

4526
4527
4528
4529
4530
4531
4532
4533







-
+


















-
+







** the pseudo-table.
*/
case OP_OpenPseudo: {
  VdbeCursor *pCx;

  assert( pOp->p1>=0 );
  assert( pOp->p3>=0 );
  pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, CURTYPE_PSEUDO);
  pCx = allocateCursor(p, pOp->p1, pOp->p3, CURTYPE_PSEUDO);
  if( pCx==0 ) goto no_mem;
  pCx->nullRow = 1;
  pCx->seekResult = pOp->p2;
  pCx->isTable = 1;
  /* Give this pseudo-cursor a fake BtCursor pointer so that pCx
  ** can be safely passed to sqlite3VdbeCursorMoveto().  This avoids a test
  ** for pCx->eCurType==CURTYPE_BTREE inside of sqlite3VdbeCursorMoveto()
  ** which is a performance optimization */
  pCx->uc.pCursor = sqlite3BtreeFakeValidCursor();
  assert( pOp->p5==0 );
  break;
}

/* Opcode: Close P1 * * * *
**
** Close a cursor previously opened as P1.  If P1 is not
** currently open, this instruction is a no-op.
*/
case OP_Close: {
case OP_Close: {             /* ncycle */
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  sqlite3VdbeFreeCursor(p, p->apCsr[pOp->p1]);
  p->apCsr[pOp->p1] = 0;
  break;
}

#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857







3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873

3874
3875
3876
3877
3878
3879
3880
4559
4560
4561
4562
4563
4564
4565





4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587

4588
4589
4590
4591
4592
4593
4594
4595







-
-
-
-
-
+
+
+
+
+
+
+















-
+







** that are used as an unpacked index key. 
**
** Reposition cursor P1 so that  it points to the smallest entry that 
** is greater than or equal to the key value. If there are no records 
** greater than or equal to the key and P2 is not zero, then jump to P2.
**
** If the cursor P1 was opened using the OPFLAG_SEEKEQ flag, then this
** opcode will always land on a record that equally equals the key, or
** else jump immediately to P2.  When the cursor is OPFLAG_SEEKEQ, this
** opcode must be followed by an IdxLE opcode with the same arguments.
** The IdxLE opcode will be skipped if this opcode succeeds, but the
** IdxLE opcode will be used on subsequent loop iterations.
** opcode will either land on a record that exactly matches the key, or
** else it will cause a jump to P2.  When the cursor is OPFLAG_SEEKEQ,
** this opcode must be followed by an IdxLE opcode with the same arguments.
** The IdxGT opcode will be skipped if this opcode succeeds, but the
** IdxGT opcode will be used on subsequent loop iterations.  The 
** OPFLAG_SEEKEQ flags is a hint to the btree layer to say that this
** is an equality search.
**
** This opcode leaves the cursor configured to move in forward order,
** from the beginning toward the end.  In other words, the cursor is
** configured to use Next, not Prev.
**
** See also: Found, NotFound, SeekLt, SeekGt, SeekLe
*/
/* Opcode: SeekGT P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), 
** use the value in register P3 as a key. If cursor P1 refers 
** to an SQL index, then P3 is the first in an array of P4 registers 
** that are used as an unpacked index key. 
**
** Reposition cursor P1 so that  it points to the smallest entry that 
** Reposition cursor P1 so that it points to the smallest entry that 
** is greater than the key value. If there are no records greater than 
** the key and P2 is not zero, then jump to P2.
**
** This opcode leaves the cursor configured to move in forward order,
** from the beginning toward the end.  In other words, the cursor is
** configured to use Next, not Prev.
**
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920



3921
3922



3923
3924
3925
3926
3927
3928
3929




3930
3931
3932
3933
3934
3935
3936
4626
4627
4628
4629
4630
4631
4632



4633
4634
4635
4636

4637
4638
4639
4640
4641
4642




4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653







-
-
-
+
+
+

-
+
+
+



-
-
-
-
+
+
+
+







** less than or equal to the key and P2 is not zero, then jump to P2.
**
** This opcode leaves the cursor configured to move in reverse order,
** from the end toward the beginning.  In other words, the cursor is
** configured to use Prev, not Next.
**
** If the cursor P1 was opened using the OPFLAG_SEEKEQ flag, then this
** opcode will always land on a record that equally equals the key, or
** else jump immediately to P2.  When the cursor is OPFLAG_SEEKEQ, this
** opcode must be followed by an IdxGE opcode with the same arguments.
** opcode will either land on a record that exactly matches the key, or
** else it will cause a jump to P2.  When the cursor is OPFLAG_SEEKEQ,
** this opcode must be followed by an IdxLE opcode with the same arguments.
** The IdxGE opcode will be skipped if this opcode succeeds, but the
** IdxGE opcode will be used on subsequent loop iterations.
** IdxGE opcode will be used on subsequent loop iterations.  The 
** OPFLAG_SEEKEQ flags is a hint to the btree layer to say that this
** is an equality search.
**
** See also: Found, NotFound, SeekGt, SeekGe, SeekLt
*/
case OP_SeekLT:         /* jump, in3, group */
case OP_SeekLE:         /* jump, in3, group */
case OP_SeekGE:         /* jump, in3, group */
case OP_SeekGT: {       /* jump, in3, group */
case OP_SeekLT:         /* jump, in3, group, ncycle */
case OP_SeekLE:         /* jump, in3, group, ncycle */
case OP_SeekGE:         /* jump, in3, group, ncycle */
case OP_SeekGT: {       /* jump, in3, group, ncycle */
  int res;           /* Comparison result */
  int oc;            /* Opcode */
  VdbeCursor *pC;    /* The cursor to seek */
  UnpackedRecord r;  /* The key to seek for */
  int nField;        /* Number of columns or fields in the key */
  i64 iKey;          /* The rowid we are to seek to */
  int eqOnly;        /* Only interested in == results */
3948
3949
3950
3951
3952
3953
3954


3955

3956

3957
3958
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
4000
4001
4002


4003
4004
4005
4006
4007
4008
4009
4010




4011
4012
4013
4014
4015


4016
4017
4018
4019
4020
4021
4022
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675

4676
4677
4678
4679
4680
4681
4682
4683
4684

4685
4686
4687

4688
4689
4690
4691
4692
4693


4694
4695
4696





4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714

4715
4716
4717
4718
4719
4720
4721
4722
4723

4724
4725
4726
4727
4728
4729


4730
4731
4732
4733
4734
4735
4736



4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754







+
+

+
-
+







+
-
+


-
+
+
+



-
-
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+








-
+








-
+





-
-
+
+





-
-
-
+
+
+
+





+
+







  oc = pOp->opcode;
  eqOnly = 0;
  pC->nullRow = 0;
#ifdef SQLITE_DEBUG
  pC->seekOp = pOp->opcode;
#endif

  pC->deferredMoveto = 0;
  pC->cacheStatus = CACHE_STALE;
  if( pC->isTable ){
    u16 flags3, newType;
    /* The BTREE_SEEK_EQ flag is only set on index cursors */
    /* The OPFLAG_SEEKEQ/BTREE_SEEK_EQ flag is only set on index cursors */
    assert( sqlite3BtreeCursorHasHint(pC->uc.pCursor, BTREE_SEEK_EQ)==0
              || CORRUPT_DB );

    /* The input value in P3 might be of any type: integer, real, string,
    ** blob, or NULL.  But it needs to be an integer before we can do
    ** the seek, so convert it. */
    pIn3 = &aMem[pOp->p3];
    flags3 = pIn3->flags;
    if( (pIn3->flags & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
    if( (flags3 & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Str))==MEM_Str ){
      applyNumericAffinity(pIn3, 0);
    }
    iKey = sqlite3VdbeIntValue(pIn3);
    iKey = sqlite3VdbeIntValue(pIn3); /* Get the integer key value */
    newType = pIn3->flags; /* Record the type after applying numeric affinity */
    pIn3->flags = flags3;  /* But convert the type back to its original */

    /* If the P3 value could not be converted into an integer without
    ** loss of information, then special processing is required... */
    if( (pIn3->flags & MEM_Int)==0 ){
      if( (pIn3->flags & MEM_Real)==0 ){
    if( (newType & (MEM_Int|MEM_IntReal))==0 ){
      int c;
      if( (newType & MEM_Real)==0 ){
        /* If the P3 value cannot be converted into any kind of a number,
        ** then the seek is not possible, so jump to P2 */
        VdbeBranchTaken(1,2); goto jump_to_p2;
        break;
      }
        if( (newType & MEM_Null) || oc>=OP_SeekGE ){
          VdbeBranchTaken(1,2);
          goto jump_to_p2;
        }else{
          rc = sqlite3BtreeLast(pC->uc.pCursor, &res);
          if( rc!=SQLITE_OK ) goto abort_due_to_error;
          goto seek_not_found;
        }
      }
      c = sqlite3IntFloatCompare(iKey, pIn3->u.r);

      /* If the approximation iKey is larger than the actual real search
      ** term, substitute >= for > and < for <=. e.g. if the search term
      ** is 4.9 and the integer approximation 5:
      **
      **        (x >  4.9)    ->     (x >= 5)
      **        (x <= 4.9)    ->     (x <  5)
      */
      if( pIn3->u.r<(double)iKey ){
      if( c>0 ){
        assert( OP_SeekGE==(OP_SeekGT-1) );
        assert( OP_SeekLT==(OP_SeekLE-1) );
        assert( (OP_SeekLE & 0x0001)==(OP_SeekGT & 0x0001) );
        if( (oc & 0x0001)==(OP_SeekGT & 0x0001) ) oc--;
      }

      /* If the approximation iKey is smaller than the actual real search
      ** term, substitute <= for < and > for >=.  */
      else if( pIn3->u.r>(double)iKey ){
      else if( c<0 ){
        assert( OP_SeekLE==(OP_SeekLT+1) );
        assert( OP_SeekGT==(OP_SeekGE+1) );
        assert( (OP_SeekLT & 0x0001)==(OP_SeekGE & 0x0001) );
        if( (oc & 0x0001)==(OP_SeekLT & 0x0001) ) oc++;
      }
    } 
    rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, 0, (u64)iKey, 0, &res);
    }
    rc = sqlite3BtreeTableMoveto(pC->uc.pCursor, (u64)iKey, 0, &res);
    pC->movetoTarget = iKey;  /* Used by OP_Delete */
    if( rc!=SQLITE_OK ){
      goto abort_due_to_error;
    }
  }else{
    /* For a cursor with the BTREE_SEEK_EQ hint, only the OP_SeekGE and
    ** OP_SeekLE opcodes are allowed, and these must be immediately followed
    ** by an OP_IdxGT or OP_IdxLT opcode, respectively, with the same key.
    /* For a cursor with the OPFLAG_SEEKEQ/BTREE_SEEK_EQ hint, only the
    ** OP_SeekGE and OP_SeekLE opcodes are allowed, and these must be
    ** immediately followed by an OP_IdxGT or OP_IdxLT opcode, respectively,
    ** with the same key.
    */
    if( sqlite3BtreeCursorHasHint(pC->uc.pCursor, BTREE_SEEK_EQ) ){
      eqOnly = 1;
      assert( pOp->opcode==OP_SeekGE || pOp->opcode==OP_SeekLE );
      assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT );
      assert( pOp->opcode==OP_SeekGE || pOp[1].opcode==OP_IdxLT );
      assert( pOp->opcode==OP_SeekLE || pOp[1].opcode==OP_IdxGT );
      assert( pOp[1].p1==pOp[0].p1 );
      assert( pOp[1].p2==pOp[0].p2 );
      assert( pOp[1].p3==pOp[0].p3 );
      assert( pOp[1].p4.i==pOp[0].p4.i );
    }

    nField = pOp->p4.i;
4036
4037
4038
4039
4040
4041
4042



4043




4044
4045
4046

4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777

4778
4779
4780
4781
4782
4783

4784
4785
4786
4787
4788
4789
4790
4791
4792


4793
4794
4795
4796
4797
4798
4799







+
+
+
-
+
+
+
+


-
+








-
-







    assert( oc!=OP_SeekGT || r.default_rc==-1 );
    assert( oc!=OP_SeekLE || r.default_rc==-1 );
    assert( oc!=OP_SeekGE || r.default_rc==+1 );
    assert( oc!=OP_SeekLT || r.default_rc==+1 );

    r.aMem = &aMem[pOp->p3];
#ifdef SQLITE_DEBUG
    {
      int i;
      for(i=0; i<r.nField; i++){
    { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
        assert( memIsValid(&r.aMem[i]) );
        if( i>0 ) REGISTER_TRACE(pOp->p3+i, &r.aMem[i]);
      }
    }
#endif
    r.eqSeen = 0;
    rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, &r, 0, 0, &res);
    rc = sqlite3BtreeIndexMoveto(pC->uc.pCursor, &r, &res);
    if( rc!=SQLITE_OK ){
      goto abort_due_to_error;
    }
    if( eqOnly && r.eqSeen==0 ){
      assert( res!=0 );
      goto seek_not_found;
    }
  }
  pC->deferredMoveto = 0;
  pC->cacheStatus = CACHE_STALE;
#ifdef SQLITE_TEST
  sqlite3_search_count++;
#endif
  if( oc>=OP_SeekGE ){  assert( oc==OP_SeekGE || oc==OP_SeekGT );
    if( res<0 || (res==0 && oc==OP_SeekGT) ){
      res = 0;
      rc = sqlite3BtreeNext(pC->uc.pCursor, 0);
4100
4101
4102
4103
4104
4105
4106

4107
4108


4109






































































4110
4111









































































































4112









4113

4114
4115
4116

4117
4118
4119
4120
4121
4122


































4123
4124
4125
4126
4127
4128
4129
4836
4837
4838
4839
4840
4841
4842
4843


4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916


4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
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
5024
5025
5026
5027
5028
5029
5030
5031

5032

5033

5034
5035
5036
5037
5038


5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079







+
-
-
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
-
+
-

-
+




-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  }else if( eqOnly ){
    assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT );
    pOp++; /* Skip the OP_IdxLt or OP_IdxGT that follows */
  }
  break;
}


/* Opcode: SeekHit P1 P2 * * *
** Synopsis: seekHit=P2
/* Opcode: SeekScan  P1 P2 * * P5
** Synopsis: Scan-ahead up to P1 rows
**
** This opcode is a prefix opcode to OP_SeekGE.  In other words, this
** opcode must be immediately followed by OP_SeekGE. This constraint is
** checked by assert() statements.
**
** This opcode uses the P1 through P4 operands of the subsequent
** OP_SeekGE.  In the text that follows, the operands of the subsequent
** OP_SeekGE opcode are denoted as SeekOP.P1 through SeekOP.P4.   Only
** the P1, P2 and P5 operands of this opcode are also used, and  are called
** This.P1, This.P2 and This.P5.
**
** This opcode helps to optimize IN operators on a multi-column index
** where the IN operator is on the later terms of the index by avoiding
** unnecessary seeks on the btree, substituting steps to the next row
** of the b-tree instead.  A correct answer is obtained if this opcode
** is omitted or is a no-op.
**
** The SeekGE.P3 and SeekGE.P4 operands identify an unpacked key which
** is the desired entry that we want the cursor SeekGE.P1 to be pointing
** to.  Call this SeekGE.P3/P4 row the "target".
**
** If the SeekGE.P1 cursor is not currently pointing to a valid row,
** then this opcode is a no-op and control passes through into the OP_SeekGE.
**
** If the SeekGE.P1 cursor is pointing to a valid row, then that row
** might be the target row, or it might be near and slightly before the
** target row, or it might be after the target row.  If the cursor is
** currently before the target row, then this opcode attempts to position
** the cursor on or after the target row by invoking sqlite3BtreeStep()
** on the cursor between 1 and This.P1 times.
**
** The This.P5 parameter is a flag that indicates what to do if the
** cursor ends up pointing at a valid row that is past the target
** row.  If This.P5 is false (0) then a jump is made to SeekGE.P2.  If
** This.P5 is true (non-zero) then a jump is made to This.P2.  The P5==0
** case occurs when there are no inequality constraints to the right of
** the IN constraing.  The jump to SeekGE.P2 ends the loop.  The P5!=0 case
** occurs when there are inequality constraints to the right of the IN
** operator.  In that case, the This.P2 will point either directly to or
** to setup code prior to the OP_IdxGT or OP_IdxGE opcode that checks for
** loop terminate.
**
** Possible outcomes from this opcode:<ol>
**
** <li> If the cursor is initally not pointed to any valid row, then
**      fall through into the subsequent OP_SeekGE opcode.
**
** <li> If the cursor is left pointing to a row that is before the target
**      row, even after making as many as This.P1 calls to
**      sqlite3BtreeNext(), then also fall through into OP_SeekGE.
**
** <li> If the cursor is left pointing at the target row, either because it
**      was at the target row to begin with or because one or more
**      sqlite3BtreeNext() calls moved the cursor to the target row,
**      then jump to This.P2..,
**
** <li> If the cursor started out before the target row and a call to
**      to sqlite3BtreeNext() moved the cursor off the end of the index
**      (indicating that the target row definitely does not exist in the
**      btree) then jump to SeekGE.P2, ending the loop.
**
** <li> If the cursor ends up on a valid row that is past the target row 
**      (indicating that the target row does not exist in the btree) then
**      jump to SeekOP.P2 if This.P5==0 or to This.P2 if This.P5>0.
** </ol>
*/
case OP_SeekScan: {          /* ncycle */
  VdbeCursor *pC;
  int res;
  int nStep;
  UnpackedRecord r;
** Set the seekHit flag on cursor P1 to the value in P2.
** The seekHit flag is used by the IfNoHope opcode.

  assert( pOp[1].opcode==OP_SeekGE );

  /* If pOp->p5 is clear, then pOp->p2 points to the first instruction past the
  ** OP_IdxGT that follows the OP_SeekGE. Otherwise, it points to the first
  ** opcode past the OP_SeekGE itself.  */
  assert( pOp->p2>=(int)(pOp-aOp)+2 );
#ifdef SQLITE_DEBUG
  if( pOp->p5==0 ){
    /* There are no inequality constraints following the IN constraint. */
    assert( pOp[1].p1==aOp[pOp->p2-1].p1 );
    assert( pOp[1].p2==aOp[pOp->p2-1].p2 );
    assert( pOp[1].p3==aOp[pOp->p2-1].p3 );
    assert( aOp[pOp->p2-1].opcode==OP_IdxGT 
         || aOp[pOp->p2-1].opcode==OP_IdxGE );
    testcase( aOp[pOp->p2-1].opcode==OP_IdxGE );
  }else{
    /* There are inequality constraints.  */
    assert( pOp->p2==(int)(pOp-aOp)+2 );
    assert( aOp[pOp->p2-1].opcode==OP_SeekGE );
  }
#endif

  assert( pOp->p1>0 );
  pC = p->apCsr[pOp[1].p1];
  assert( pC!=0 );
  assert( pC->eCurType==CURTYPE_BTREE );
  assert( !pC->isTable );
  if( !sqlite3BtreeCursorIsValidNN(pC->uc.pCursor) ){
#ifdef SQLITE_DEBUG
     if( db->flags&SQLITE_VdbeTrace ){
       printf("... cursor not valid - fall through\n");
     }        
#endif
    break;
  }
  nStep = pOp->p1;
  assert( nStep>=1 );
  r.pKeyInfo = pC->pKeyInfo;
  r.nField = (u16)pOp[1].p4.i;
  r.default_rc = 0;
  r.aMem = &aMem[pOp[1].p3];
#ifdef SQLITE_DEBUG
  {
    int i;
    for(i=0; i<r.nField; i++){
      assert( memIsValid(&r.aMem[i]) );
      REGISTER_TRACE(pOp[1].p3+i, &aMem[pOp[1].p3+i]);
    }
  }
#endif
  res = 0;  /* Not needed.  Only used to silence a warning. */
  while(1){
    rc = sqlite3VdbeIdxKeyCompare(db, pC, &r, &res);
    if( rc ) goto abort_due_to_error;
    if( res>0 && pOp->p5==0 ){
      seekscan_search_fail:
      /* Jump to SeekGE.P2, ending the loop */
#ifdef SQLITE_DEBUG
      if( db->flags&SQLITE_VdbeTrace ){
        printf("... %d steps and then skip\n", pOp->p1 - nStep);
      }        
#endif
      VdbeBranchTaken(1,3);
      pOp++;
      goto jump_to_p2;
    }
    if( res>=0 ){
      /* Jump to This.P2, bypassing the OP_SeekGE opcode */
#ifdef SQLITE_DEBUG
      if( db->flags&SQLITE_VdbeTrace ){
        printf("... %d steps and then success\n", pOp->p1 - nStep);
      }        
#endif
      VdbeBranchTaken(2,3);
      goto jump_to_p2;
      break;
    }
    if( nStep<=0 ){
#ifdef SQLITE_DEBUG
      if( db->flags&SQLITE_VdbeTrace ){
        printf("... fall through after %d steps\n", pOp->p1);
      }        
#endif
      VdbeBranchTaken(0,3);
      break;
    }
    nStep--;
    rc = sqlite3BtreeNext(pC->uc.pCursor, 0);
    if( rc ){
      if( rc==SQLITE_DONE ){
        rc = SQLITE_OK;
        goto seekscan_search_fail;
      }else{
        goto abort_due_to_error;
      }
    }
  }
  
  break;
}


/* Opcode: SeekHit P1 P2 P3 * *
** Synopsis: set P2<=seekHit<=P3
**
** Increase or decrease the seekHit value for cursor P1, if necessary,
** so that it is no less than P2 and no greater than P3.
**
** The seekHit integer represents the maximum of terms in an index for which
** there is known to be at least one match.  If the seekHit value is smaller
** than the total number of equality terms in an index lookup, then the
** OP_IfNoHope opcode might run to see if the IN loop can be abandoned
** early, thus saving work.  This is part of the IN-early-out optimization.
**
** P1 must be a valid b-tree cursor.  P2 must be a boolean value,
** P1 must be a valid b-tree cursor.
** either 0 or 1.
*/
case OP_SeekHit: {
case OP_SeekHit: {           /* ncycle */
  VdbeCursor *pC;
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  pC = p->apCsr[pOp->p1];
  assert( pC!=0 );
  assert( pOp->p2==0 || pOp->p2==1 );
  pC->seekHit = pOp->p2 & 1;
  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
**
** If cursor P1 is not open or if P1 is set to a NULL row using the
** OP_NullRow opcode, then jump to instruction P2. Otherwise, fall through.
*/
case OP_IfNotOpen: {        /* jump */
  VdbeCursor *pCur;

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  pCur = p->apCsr[pOp->p1];
  VdbeBranchTaken(pCur==0 || pCur->nullRow, 2);
  if( pCur==0 || pCur->nullRow ){
    goto jump_to_p2_and_check_for_interrupt;
  }
  break;
}

/* Opcode: Found P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** If P4==0 then register P3 holds a blob constructed by MakeRecord.  If
4159
4160
4161
4162
4163
4164
4165
4166



4167
4168
4169

4170
4171
4172


4173





4174

4175
4176
4177
4178
4179
4180
4181
4182
5109
5110
5111
5112
5113
5114
5115

5116
5117
5118
5119


5120



5121
5122
5123
5124
5125
5126
5127
5128

5129

5130
5131
5132
5133
5134
5135
5136







-
+
+
+

-
-
+
-
-
-
+
+

+
+
+
+
+
-
+
-







**
** See also: Found, NotExists, NoConflict, IfNoHope
*/
/* Opcode: IfNoHope P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** Register P3 is the first of P4 registers that form an unpacked
** record.
** record.  Cursor P1 is an index btree.  P2 is a jump destination.
** In other words, the operands to this opcode are the same as the
** operands to OP_NotFound and OP_IdxGT.
**
** Cursor P1 is on an index btree.  If the seekHit flag is set on P1, then
** this opcode is a no-op.  But if the seekHit flag of P1 is clear, then
** This opcode is an optimization attempt only.  If this opcode always
** check to see if there is any entry in P1 that matches the
** prefix identified by P3 and P4.  If no entry matches the prefix,
** jump to P2.  Otherwise fall through.
** falls through, the correct answer is still obtained, but extra works
** is performed.
**
** A value of N in the seekHit flag of cursor P1 means that there exists
** a key P3:N that will match some record in the index.  We want to know
** if it is possible for a record P3:P4 to match some record in the
** index.  If it is not possible, we can skips some work.  So if seekHit
** is less than P4, attempt to find out if a match is possible by running
** This opcode behaves like OP_NotFound if the seekHit
** OP_NotFound.
** flag is clear and it behaves like OP_Noop if the seekHit flag is set.
**
** This opcode is used in IN clause processing for a multi-column key.
** If an IN clause is attached to an element of the key other than the
** left-most element, and if there are no matches on the most recent
** seek over the whole key, then it might be that one of the key element
** to the left is prohibiting a match, and hence there is "no hope" of
** any match regardless of how many IN clause elements are checked.
4205
4206
4207
4208
4209
4210
4211
4212

4213
4214
4215
4216





4217

4218

4219
4220
4221
4222



4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243

4244
4245
4246
4247



4248
4249
4250

4251
4252
4253
4254
4255
4256
4257
4258

4259
4260

4261
4262



4263
4264
4265

4266
4267

4268
4269
4270


4271
4272
4273
4274
4275
4276

4277
4278
4279

4280
4281
4282
4283
4284
4285
4286
4287
4288

4289
4290
4291
4292
4293
4294
4295

4296
4297


















4298
4299
4300
4301
4302
4303
4304
5159
5160
5161
5162
5163
5164
5165

5166
5167
5168
5169
5170
5171
5172
5173
5174
5175

5176
5177
5178
5179



5180
5181
5182
5183

5184
5185


5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199

5200
5201
5202
5203

5204
5205
5206
5207


5208
5209
5210
5211
5212
5213
5214
5215

5216

5217
5218


5219
5220
5221
5222
5223

5224
5225

5226



5227
5228






5229



5230




5231
5232
5233


5234
5235
5236
5237
5238
5239
5240
5241
5242


5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267







-
+




+
+
+
+
+
-
+

+

-
-
-
+
+
+

-


-
-














-
+



-
+
+
+

-
-
+







-
+
-

+
-
-
+
+
+


-
+

-
+
-
-
-
+
+
-
-
-
-
-
-
+
-
-
-
+
-
-
-
-



-
-
+







+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







**
** This operation leaves the cursor in a state where it cannot be
** advanced in either direction.  In other words, the Next and Prev
** opcodes do not work after this operation.
**
** See also: NotFound, Found, NotExists
*/
case OP_IfNoHope: {     /* jump, in3 */
case OP_IfNoHope: {     /* jump, in3, ncycle */
  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 ) break;
  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 */
case OP_NoConflict:     /* jump, in3, ncycle */
case OP_NotFound:       /* jump, in3, ncycle */
case OP_Found: {        /* jump, in3, ncycle */
  int alreadyExists;
  int takeJump;
  int ii;
  VdbeCursor *pC;
  int res;
  UnpackedRecord *pFree;
  UnpackedRecord *pIdxKey;
  UnpackedRecord r;

#ifdef SQLITE_TEST
  if( pOp->opcode!=OP_NoConflict ) sqlite3_found_count++;
#endif

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( pOp->p4type==P4_INT32 );
  pC = p->apCsr[pOp->p1];
  assert( pC!=0 );
#ifdef SQLITE_DEBUG
  pC->seekOp = pOp->opcode;
#endif
  pIn3 = &aMem[pOp->p3];
  r.aMem = &aMem[pOp->p3];
  assert( pC->eCurType==CURTYPE_BTREE );
  assert( pC->uc.pCursor!=0 );
  assert( pC->isTable==0 );
  if( pOp->p4.i>0 ){
  r.nField = (u16)pOp->p4.i;
  if( r.nField>0 ){
    /* Key values in an array of registers */
    r.pKeyInfo = pC->pKeyInfo;
    r.nField = (u16)pOp->p4.i;
    r.aMem = pIn3;
    r.default_rc = 0;
#ifdef SQLITE_DEBUG
    for(ii=0; ii<r.nField; ii++){
      assert( memIsValid(&r.aMem[ii]) );
      assert( (r.aMem[ii].flags & MEM_Zero)==0 || r.aMem[ii].n==0 );
      if( ii ) REGISTER_TRACE(pOp->p3+ii, &r.aMem[ii]);
    }
#endif
    pIdxKey = &r;
    rc = sqlite3BtreeIndexMoveto(pC->uc.pCursor, &r, &pC->seekResult);
    pFree = 0;
  }else{
    /* Composite key generated by OP_MakeRecord */
    assert( pIn3->flags & MEM_Blob );
    rc = ExpandBlob(pIn3);
    assert( r.aMem->flags & MEM_Blob );
    assert( pOp->opcode!=OP_NoConflict );
    rc = ExpandBlob(r.aMem);
    assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
    if( rc ) goto no_mem;
    pFree = pIdxKey = sqlite3VdbeAllocUnpackedRecord(pC->pKeyInfo);
    pIdxKey = sqlite3VdbeAllocUnpackedRecord(pC->pKeyInfo);
    if( pIdxKey==0 ) goto no_mem;
    sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey);
    sqlite3VdbeRecordUnpack(pC->pKeyInfo, r.aMem->n, r.aMem->z, pIdxKey);
  }
  pIdxKey->default_rc = 0;
  takeJump = 0;
    pIdxKey->default_rc = 0;
    rc = sqlite3BtreeIndexMoveto(pC->uc.pCursor, pIdxKey, &pC->seekResult);
  if( pOp->opcode==OP_NoConflict ){
    /* For the OP_NoConflict opcode, take the jump if any of the
    ** input fields are NULL, since any key with a NULL will not
    ** conflict */
    for(ii=0; ii<pIdxKey->nField; ii++){
      if( pIdxKey->aMem[ii].flags & MEM_Null ){
    sqlite3DbFreeNN(db, pIdxKey);
        takeJump = 1;
        break;
      }
  }
    }
  }
  rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, pIdxKey, 0, 0, &res);
  if( pFree ) sqlite3DbFreeNN(db, pFree);
  if( rc!=SQLITE_OK ){
    goto abort_due_to_error;
  }
  pC->seekResult = res;
  alreadyExists = (res==0);
  alreadyExists = (pC->seekResult==0);
  pC->nullRow = 1-alreadyExists;
  pC->deferredMoveto = 0;
  pC->cacheStatus = CACHE_STALE;
  if( pOp->opcode==OP_Found ){
    VdbeBranchTaken(alreadyExists!=0,2);
    if( alreadyExists ) goto jump_to_p2;
  }else{
    if( !alreadyExists ){
    VdbeBranchTaken(takeJump||alreadyExists==0,2);
    if( takeJump || !alreadyExists ) goto jump_to_p2;
      VdbeBranchTaken(1,2);
      goto jump_to_p2;
    }
    if( pOp->opcode==OP_NoConflict ){
      /* For the OP_NoConflict opcode, take the jump if any of the
      ** input fields are NULL, since any key with a NULL will not
      ** conflict */
      for(ii=0; ii<r.nField; ii++){
        if( r.aMem[ii].flags & MEM_Null ){
          VdbeBranchTaken(1,2);
          goto jump_to_p2;
        }
      }
    }
    VdbeBranchTaken(0,2);
    if( pOp->opcode==OP_IfNoHope ){
      pC->seekHit = pOp->p4.i;
    }
  }
  break;
}

/* Opcode: SeekRowid P1 P2 P3 * *
** Synopsis: intkey=r[P3]
**
4342
4343
4344
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
4371
4372


4373
4374
4375
4376

4377
4378
4379
4380
4381
4382
4383
4384

4385
4386
4387
4388
4389
4390
4391
5305
5306
5307
5308
5309
5310
5311

5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322




5323
5324
5325
5326
5327
5328


5329





5330
5331
5332
5333
5334
5335
5336

5337
5338
5339
5340
5341
5342
5343
5344
5345

5346
5347
5348
5349
5350
5351
5352


5353
5354
5355
5356
5357
5358
5359
5360







-
+






+
+
+
+
-
-
-
-
+
+
+
+
+
+
-
-
+
-
-
-
-
-
+
+
+
+


+
-
+



+
+



-
+






-
-
+







**
** This opcode leaves the cursor in a state where it cannot be advanced
** in either direction.  In other words, the Next and Prev opcodes will
** not work following this opcode.
**
** See also: Found, NotFound, NoConflict, SeekRowid
*/
case OP_SeekRowid: {        /* jump, in3 */
case OP_SeekRowid: {        /* jump, in3, ncycle */
  VdbeCursor *pC;
  BtCursor *pCrsr;
  int res;
  u64 iKey;

  pIn3 = &aMem[pOp->p3];
  testcase( pIn3->flags & MEM_Int );
  testcase( pIn3->flags & MEM_IntReal );
  testcase( pIn3->flags & MEM_Real );
  testcase( (pIn3->flags & (MEM_Str|MEM_Int))==MEM_Str );
  if( (pIn3->flags & MEM_Int)==0 ){
    /* Make sure pIn3->u.i contains a valid integer representation of
    ** the key value, but do not change the datatype of the register, as
    ** other parts of the perpared statement might be depending on the
  if( (pIn3->flags & (MEM_Int|MEM_IntReal))==0 ){
    /* If pIn3->u.i does not contain an integer, compute iKey as the
    ** integer value of pIn3.  Jump to P2 if pIn3 cannot be converted
    ** into an integer without loss of information.  Take care to avoid
    ** changing the datatype of pIn3, however, as it is used by other
    ** parts of the prepared statement. */
    ** current datatype. */
    u16 origFlags = pIn3->flags;
    Mem x = pIn3[0];
    int isNotInt;
    applyAffinity(pIn3, SQLITE_AFF_NUMERIC, encoding);
    isNotInt = (pIn3->flags & MEM_Int)==0;
    pIn3->flags = origFlags;
    if( isNotInt ) goto jump_to_p2;
    applyAffinity(&x, SQLITE_AFF_NUMERIC, encoding);
    if( (x.flags & MEM_Int)==0 ) goto jump_to_p2;
    iKey = x.u.i;
    goto notExistsWithKey;
  }
  /* Fall through into OP_NotExists */
  /* no break */ deliberate_fall_through
case OP_NotExists:          /* jump, in3 */
case OP_NotExists:          /* jump, in3, ncycle */
  pIn3 = &aMem[pOp->p3];
  assert( (pIn3->flags & MEM_Int)!=0 || pOp->opcode==OP_SeekRowid );
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  iKey = pIn3->u.i;
notExistsWithKey:
  pC = p->apCsr[pOp->p1];
  assert( pC!=0 );
#ifdef SQLITE_DEBUG
  pC->seekOp = OP_SeekRowid;
  if( pOp->opcode==OP_SeekRowid ) pC->seekOp = OP_SeekRowid;
#endif
  assert( pC->isTable );
  assert( pC->eCurType==CURTYPE_BTREE );
  pCrsr = pC->uc.pCursor;
  assert( pCrsr!=0 );
  res = 0;
  iKey = pIn3->u.i;
  rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res);
  rc = sqlite3BtreeTableMoveto(pCrsr, iKey, 0, &res);
  assert( rc==SQLITE_OK || res==0 );
  pC->movetoTarget = iKey;  /* Used by OP_Delete */
  pC->nullRow = 0;
  pC->cacheStatus = CACHE_STALE;
  pC->deferredMoveto = 0;
  VdbeBranchTaken(res!=0,2);
  pC->seekResult = res;
4435
4436
4437
4438
4439
4440
4441

4442
4443

4444
4445
4446
4447
4448
4449
4450
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421







+


+







** AUTOINCREMENT feature.
*/
case OP_NewRowid: {           /* out2 */
  i64 v;                 /* The new rowid */
  VdbeCursor *pC;        /* Cursor of table to get the new rowid */
  int res;               /* Result of an sqlite3BtreeLast() */
  int cnt;               /* Counter to limit the number of searches */
#ifndef SQLITE_OMIT_AUTOINCREMENT
  Mem *pMem;             /* Register holding largest rowid for AUTOINCREMENT */
  VdbeFrame *pFrame;     /* Root frame of VDBE */
#endif

  v = 0;
  res = 0;
  pOut = out2Prerelease(p, pOp);
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  pC = p->apCsr[pOp->p1];
  assert( pC!=0 );
4532
4533
4534
4535
4536
4537
4538
4539

4540
4541
4542
4543
4544
4545
4546
5503
5504
5505
5506
5507
5508
5509

5510
5511
5512
5513
5514
5515
5516
5517







-
+







      ** it finds one that is not previously used. */
      assert( pOp->p3==0 );  /* We cannot be in random rowid mode if this is
                             ** an AUTOINCREMENT table. */
      cnt = 0;
      do{
        sqlite3_randomness(sizeof(v), &v);
        v &= (MAX_ROWID>>1); v++;  /* Ensure that v is greater than zero */
      }while(  ((rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, 0, (u64)v,
      }while(  ((rc = sqlite3BtreeTableMoveto(pC->uc.pCursor, (u64)v,
                                                 0, &res))==SQLITE_OK)
            && (res==0)
            && (++cnt<100));
      if( rc ) goto abort_due_to_error;
      if( res==0 ){
        rc = SQLITE_FULL;   /* IMP: R-38219-53002 */
        goto abort_due_to_error;
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600

4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615

4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627





4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640

4641
4642
4643
4644
4645
4646
4647

4648
4649
4650
4651
4652
4653
4654
4655
4656

4657
4658
4659





4660
4661
4662
4663
4664
4665
4666
4667
4668

4669
4670


4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685



























4686
4687
4688
4689
4690
4691
4692
5558
5559
5560
5561
5562
5563
5564







5565

5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586






5587
5588
5589
5590
5591




5592
5593
5594
5595
5596
5597
5598
5599

5600
5601
5602
5603
5604
5605
5606

5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617



5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633

5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684







-
-
-
-
-
-
-
+
-














+






-
-
-
-
-
-
+
+
+
+
+
-
-
-
-








-
+






-
+









+
-
-
-
+
+
+
+
+









+

-
+
+















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







** and register P2 becomes ephemeral.  If the cursor is changed, the
** value of register P2 will then change.  Make sure this does not
** cause any problems.)
**
** This instruction only works on tables.  The equivalent instruction
** for indices is OP_IdxInsert.
*/
/* Opcode: InsertInt P1 P2 P3 P4 P5
** Synopsis: intkey=P3 data=r[P2]
**
** This works exactly like OP_Insert except that the key is the
** integer value P3, not the value of the integer stored in register P3.
*/
case OP_Insert: 
case OP_Insert: {
case OP_InsertInt: {
  Mem *pData;       /* MEM cell holding data for the record to be inserted */
  Mem *pKey;        /* MEM cell holding key  for the record */
  VdbeCursor *pC;   /* Cursor to table into which insert is written */
  int seekResult;   /* Result of prior seek or 0 if no USESEEKRESULT flag */
  const char *zDb;  /* database name - used by the update hook */
  Table *pTab;      /* Table structure - used by update and pre-update hooks */
  BtreePayload x;   /* Payload to be inserted */

  pData = &aMem[pOp->p2];
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( memIsValid(pData) );
  pC = p->apCsr[pOp->p1];
  assert( pC!=0 );
  assert( pC->eCurType==CURTYPE_BTREE );
  assert( pC->deferredMoveto==0 );
  assert( pC->uc.pCursor!=0 );
  assert( (pOp->p5 & OPFLAG_ISNOOP) || pC->isTable );
  assert( pOp->p4type==P4_TABLE || pOp->p4type>=P4_STATIC );
  REGISTER_TRACE(pOp->p2, pData);
  sqlite3VdbeIncrWriteCounter(p, pC);

  if( pOp->opcode==OP_Insert ){
    pKey = &aMem[pOp->p3];
    assert( pKey->flags & MEM_Int );
    assert( memIsValid(pKey) );
    REGISTER_TRACE(pOp->p3, pKey);
    x.nKey = pKey->u.i;
  pKey = &aMem[pOp->p3];
  assert( pKey->flags & MEM_Int );
  assert( memIsValid(pKey) );
  REGISTER_TRACE(pOp->p3, pKey);
  x.nKey = pKey->u.i;
  }else{
    assert( pOp->opcode==OP_InsertInt );
    x.nKey = pOp->p3;
  }

  if( pOp->p4type==P4_TABLE && HAS_UPDATE_HOOK(db) ){
    assert( pC->iDb>=0 );
    zDb = db->aDb[pC->iDb].zDbSName;
    pTab = pOp->p4.pTab;
    assert( (pOp->p5 & OPFLAG_ISNOOP) || HasRowid(pTab) );
  }else{
    pTab = 0;
    zDb = 0;  /* Not needed.  Silence a compiler warning. */
    zDb = 0;
  }

#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
  /* Invoke the pre-update hook, if any */
  if( pTab ){
    if( db->xPreUpdateCallback && !(pOp->p5 & OPFLAG_ISUPDATE) ){
      sqlite3VdbePreUpdateHook(p, pC, SQLITE_INSERT, zDb, pTab, x.nKey,pOp->p2);
      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;
#endif

  assert( (pOp->p5 & OPFLAG_LASTROWID)==0 || (pOp->p5 & OPFLAG_NCHANGE)!=0 );
  if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
  if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = x.nKey;
  assert( pData->flags & (MEM_Blob|MEM_Str) );
  if( pOp->p5 & OPFLAG_NCHANGE ){
    p->nChange++;
    if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = x.nKey;
  }
  assert( (pData->flags & (MEM_Blob|MEM_Str))!=0 || pData->n==0 );
  x.pData = pData->z;
  x.nData = pData->n;
  seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0);
  if( pData->flags & MEM_Zero ){
    x.nZero = pData->u.nZero;
  }else{
    x.nZero = 0;
  }
  x.pKey = 0;
  assert( BTREE_PREFORMAT==OPFLAG_PREFORMAT );
  rc = sqlite3BtreeInsert(pC->uc.pCursor, &x,
      (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION)), seekResult
      (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION|OPFLAG_PREFORMAT)), 
      seekResult
  );
  pC->deferredMoveto = 0;
  pC->cacheStatus = CACHE_STALE;

  /* Invoke the update-hook if required. */
  if( rc ) goto abort_due_to_error;
  if( pTab ){
    assert( db->xUpdateCallback!=0 );
    assert( pTab->aCol!=0 );
    db->xUpdateCallback(db->pUpdateArg,
           (pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT,
           zDb, pTab->zName, x.nKey);
  }
  break;
}

/* Opcode: RowCell P1 P2 P3 * *
**
** P1 and P2 are both open cursors. Both must be opened on the same type
** of table - intkey or index. This opcode is used as part of copying
** the current row from P2 into P1. If the cursors are opened on intkey
** tables, register P3 contains the rowid to use with the new record in
** P1. If they are opened on index tables, P3 is not used.
**
** This opcode must be followed by either an Insert or InsertIdx opcode
** with the OPFLAG_PREFORMAT flag set to complete the insert operation.
*/
case OP_RowCell: {
  VdbeCursor *pDest;              /* Cursor to write to */
  VdbeCursor *pSrc;               /* Cursor to read from */
  i64 iKey;                       /* Rowid value to insert with */
  assert( pOp[1].opcode==OP_Insert || pOp[1].opcode==OP_IdxInsert );
  assert( pOp[1].opcode==OP_Insert    || pOp->p3==0 );
  assert( pOp[1].opcode==OP_IdxInsert || pOp->p3>0 );
  assert( pOp[1].p5 & OPFLAG_PREFORMAT );
  pDest = p->apCsr[pOp->p1];
  pSrc = p->apCsr[pOp->p2];
  iKey = pOp->p3 ? aMem[pOp->p3].u.i : 0;
  rc = sqlite3BtreeTransferRow(pDest->uc.pCursor, pSrc->uc.pCursor, iKey);
  if( rc!=SQLITE_OK ) goto abort_due_to_error;
  break;
};

/* Opcode: Delete P1 P2 P3 P4 P5
**
** Delete the record at which the P1 cursor is currently pointing.
**
** If the OPFLAG_SAVEPOSITION bit of the P5 parameter is set, then
** the cursor will be left pointing at  either the next or the previous
4731
4732
4733
4734
4735
4736
4737
4738





4739
4740
4741
4742
4743

4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762


4763
4764
4765
4766

4767

4768
4769
4770
4771
4772
4773
4774
4775

4776
4777
4778
4779
4780
4781
4782
5723
5724
5725
5726
5727
5728
5729

5730
5731
5732
5733
5734
5735
5736
5737
5738

5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756


5757
5758
5759
5760
5761
5762
5763

5764
5765
5766
5767
5768
5769
5770
5771

5772
5773
5774
5775
5776
5777
5778
5779







-
+
+
+
+
+




-
+

















-
-
+
+




+
-
+







-
+







  assert( pC!=0 );
  assert( pC->eCurType==CURTYPE_BTREE );
  assert( pC->uc.pCursor!=0 );
  assert( pC->deferredMoveto==0 );
  sqlite3VdbeIncrWriteCounter(p, pC);

#ifdef SQLITE_DEBUG
  if( pOp->p4type==P4_TABLE && HasRowid(pOp->p4.pTab) && pOp->p5==0 ){
  if( pOp->p4type==P4_TABLE
   && HasRowid(pOp->p4.pTab)
   && pOp->p5==0
   && sqlite3BtreeCursorIsValidNN(pC->uc.pCursor)
  ){
    /* If p5 is zero, the seek operation that positioned the cursor prior to
    ** OP_Delete will have also set the pC->movetoTarget field to the rowid of
    ** the row that is being deleted */
    i64 iKey = sqlite3BtreeIntegerKey(pC->uc.pCursor);
    assert( pC->movetoTarget==iKey );
    assert( CORRUPT_DB || pC->movetoTarget==iKey );
  }
#endif

  /* If the update-hook or pre-update-hook will be invoked, set zDb to
  ** the name of the db to pass as to it. Also set local pTab to a copy
  ** of p4.pTab. Finally, if p5 is true, indicating that this cursor was
  ** last moved with OP_Next or OP_Prev, not Seek or NotFound, set 
  ** VdbeCursor.movetoTarget to the current rowid.  */
  if( pOp->p4type==P4_TABLE && HAS_UPDATE_HOOK(db) ){
    assert( pC->iDb>=0 );
    assert( pOp->p4.pTab!=0 );
    zDb = db->aDb[pC->iDb].zDbSName;
    pTab = pOp->p4.pTab;
    if( (pOp->p5 & OPFLAG_SAVEPOSITION)!=0 && pC->isTable ){
      pC->movetoTarget = sqlite3BtreeIntegerKey(pC->uc.pCursor);
    }
  }else{
    zDb = 0;   /* Not needed.  Silence a compiler warning. */
    pTab = 0;  /* Not needed.  Silence a compiler warning. */
    zDb = 0;
    pTab = 0;
  }

#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
  /* Invoke the pre-update-hook if required. */
  assert( db->xPreUpdateCallback==0 || pTab==pOp->p4.pTab );
  if( db->xPreUpdateCallback && pOp->p4.pTab ){
  if( db->xPreUpdateCallback && pTab ){
    assert( !(opflags & OPFLAG_ISUPDATE) 
         || HasRowid(pTab)==0 
         || (aMem[pOp->p3].flags & MEM_Int) 
    );
    sqlite3VdbePreUpdateHook(p, pC,
        (opflags & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_DELETE, 
        zDb, pTab, pC->movetoTarget,
        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 );
4801
4802
4803
4804
4805
4806
4807
4808

4809
4810
4811
4812
4813
4814
4815
5798
5799
5800
5801
5802
5803
5804

5805
5806
5807
5808
5809
5810
5811
5812







-
+







  pC->cacheStatus = CACHE_STALE;
  pC->seekResult = 0;
  if( rc ) goto abort_due_to_error;

  /* Invoke the update-hook if required. */
  if( opflags & OPFLAG_NCHANGE ){
    p->nChange++;
    if( db->xUpdateCallback && HasRowid(pTab) ){
    if( db->xUpdateCallback && ALWAYS(pTab!=0) && HasRowid(pTab) ){
      db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, pTab->zName,
          pC->movetoTarget);
      assert( pC->iDb>=0 );
    }
  }

  break;
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953

4954
4955
4956
4957
4958
4959
4960
4961
4962

4963
4964
4965
4966
4967
4968
4969
4970
4971

4972
4973
4974
4975
4976
4977
4978
5933
5934
5935
5936
5937
5938
5939




5940
5941
5942
5943
5944
5945

5946
5947
5948
5949
5950
5951
5952
5953
5954

5955
5956
5957
5958
5959
5960
5961
5962
5963

5964
5965
5966
5967
5968
5969
5970
5971







-
-
-
-






-
+








-
+








-
+







  ** If this where not the case, on of the following assert()s
  ** would fail.  Should this ever change (because of changes in the code
  ** generator) then the fix would be to insert a call to
  ** sqlite3VdbeCursorMoveto().
  */
  assert( pC->deferredMoveto==0 );
  assert( sqlite3BtreeCursorIsValid(pCrsr) );
#if 0  /* Not required due to the previous to assert() statements */
  rc = sqlite3VdbeCursorMoveto(pC);
  if( rc!=SQLITE_OK ) goto abort_due_to_error;
#endif

  n = sqlite3BtreePayloadSize(pCrsr);
  if( n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
    goto too_big;
  }
  testcase( n==0 );
  rc = sqlite3VdbeMemFromBtree(pCrsr, 0, n, pOut);
  rc = sqlite3VdbeMemFromBtreeZeroOffset(pCrsr, n, pOut);
  if( rc ) goto abort_due_to_error;
  if( !pOp->p3 ) Deephemeralize(pOut);
  UPDATE_MAX_BLOBSIZE(pOut);
  REGISTER_TRACE(pOp->p2, pOut);
  break;
}

/* Opcode: Rowid P1 P2 * * *
** Synopsis: r[P2]=rowid
** Synopsis: r[P2]=PX rowid of P1
**
** Store in register P2 an integer which is the key of the table entry that
** P1 is currently point to.
**
** P1 can be either an ordinary table or a virtual table.  There used to
** be a separate OP_VRowid opcode for use with virtual tables, but this
** one opcode now works for both table types.
*/
case OP_Rowid: {                 /* out2 */
case OP_Rowid: {                 /* out2, ncycle */
  VdbeCursor *pC;
  i64 v;
  sqlite3_vtab *pVtab;
  const sqlite3_module *pModule;

  pOut = out2Prerelease(p, pOp);
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
5010
5011
5012
5013
5014
5015
5016



5017
5018
5019
5020
5021
5022
5023










5024
5025
5026
5027
5028
5029
5030
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018

6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035







+
+
+






-
+
+
+
+
+
+
+
+
+
+







}

/* Opcode: NullRow P1 * * * *
**
** Move the cursor P1 to a null row.  Any OP_Column operations
** that occur while the cursor is on the null row will always
** write a NULL.
**
** If cursor P1 is not previously opened, open it now to a special
** pseudo-cursor that always returns NULL for every column.
*/
case OP_NullRow: {
  VdbeCursor *pC;

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  pC = p->apCsr[pOp->p1];
  assert( pC!=0 );
  if( pC==0 ){
    /* If the cursor is not already open, create a special kind of
    ** pseudo-cursor that always gives null rows. */
    pC = allocateCursor(p, pOp->p1, 1, CURTYPE_PSEUDO);
    if( pC==0 ) goto no_mem;
    pC->seekResult = 0;
    pC->isTable = 1;
    pC->noReuse = 1;
    pC->uc.pCursor = sqlite3BtreeFakeValidCursor();
  }
  pC->nullRow = 1;
  pC->cacheStatus = CACHE_STALE;
  if( pC->eCurType==CURTYPE_BTREE ){
    assert( pC->uc.pCursor!=0 );
    sqlite3BtreeClearCursor(pC->uc.pCursor);
  }
#ifdef SQLITE_DEBUG
5051
5052
5053
5054
5055
5056
5057
5058
5059


5060
5061
5062
5063
5064
5065
5066
6056
6057
6058
6059
6060
6061
6062


6063
6064
6065
6066
6067
6068
6069
6070
6071







-
-
+
+







** If P2 is 0 or if the table or index is not empty, fall through
** to the following instruction.
**
** This opcode leaves the cursor configured to move in reverse order,
** from the end toward the beginning.  In other words, the cursor is
** configured to use Prev, not Next.
*/
case OP_SeekEnd:
case OP_Last: {        /* jump */
case OP_SeekEnd:             /* ncycle */
case OP_Last: {              /* jump, ncycle */
  VdbeCursor *pC;
  BtCursor *pCrsr;
  int res;

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  pC = p->apCsr[pOp->p1];
  assert( pC!=0 );
5143
5144
5145
5146
5147
5148
5149

5150
5151

5152
5153
5154
5155
5156
5157
5158
5159

5160
5161

5162
5163
5164
5165
5166
5167

5168
5169
5170
5171
5172



5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197




5198
5199
5200
5201

5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228

5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267

5268
5269
















5270
5271



5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284



5285
5286
5287
5288


5289
5290
5291
5292
5293
5294
5295
5296
5297
6148
6149
6150
6151
6152
6153
6154
6155
6156

6157
6158
6159
6160
6161
6162
6163
6164

6165


6166
6167
6168
6169
6170
6171

6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194



6195
6196
6197
6198
6199



6200
6201
6202
6203
6204
6205
6206

6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225



6226
6227
6228
6229
6230

6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250



6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268


6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285

6286
6287
6288
6289
6290
6291
6292









6293
6294
6295




6296
6297
6298

6299
6300
6301
6302
6303
6304
6305







+

-
+







-
+
-
-
+





-
+





+
+
+














-
-
-





-
-
-
+
+
+
+



-
+


















-
-
-





-
+



















-
-
-

















+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+
+
+




-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
+
+

-







case OP_Sort: {        /* jump */
#ifdef SQLITE_TEST
  sqlite3_sort_count++;
  sqlite3_search_count--;
#endif
  p->aCounter[SQLITE_STMTSTATUS_SORT]++;
  /* Fall through into OP_Rewind */
  /* no break */ deliberate_fall_through
}
/* Opcode: Rewind P1 P2 * * P5
/* Opcode: Rewind P1 P2 * * *
**
** The next use of the Rowid or Column or Next instruction for P1 
** will refer to the first entry in the database table or index.
** If the table or index is empty, jump immediately to P2.
** If the table or index is not empty, fall through to the following 
** instruction.
**
** If P5 is non-zero and the table is not empty, then the "skip-next"
** If P2 is zero, that is an assertion that the P1 table is never
** flag is set on the cursor so that the next OP_Next instruction 
** executed on it is a no-op.
** empty and hence the jump will never be taken.
**
** This opcode leaves the cursor configured to move in forward order,
** from the beginning toward the end.  In other words, the cursor is
** configured to use Next, not Prev.
*/
case OP_Rewind: {        /* jump */
case OP_Rewind: {        /* jump, ncycle */
  VdbeCursor *pC;
  BtCursor *pCrsr;
  int res;

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( pOp->p5==0 );
  assert( pOp->p2>=0 && pOp->p2<p->nOp );

  pC = p->apCsr[pOp->p1];
  assert( pC!=0 );
  assert( isSorter(pC)==(pOp->opcode==OP_SorterSort) );
  res = 1;
#ifdef SQLITE_DEBUG
  pC->seekOp = OP_Rewind;
#endif
  if( isSorter(pC) ){
    rc = sqlite3VdbeSorterRewind(pC, &res);
  }else{
    assert( pC->eCurType==CURTYPE_BTREE );
    pCrsr = pC->uc.pCursor;
    assert( pCrsr );
    rc = sqlite3BtreeFirst(pCrsr, &res);
#ifndef SQLITE_OMIT_WINDOWFUNC
    if( pOp->p5 ) sqlite3BtreeSkipNext(pCrsr);
#endif
    pC->deferredMoveto = 0;
    pC->cacheStatus = CACHE_STALE;
  }
  if( rc ) goto abort_due_to_error;
  pC->nullRow = (u8)res;
  assert( pOp->p2>0 && pOp->p2<p->nOp );
  VdbeBranchTaken(res!=0,2);
  if( res ) goto jump_to_p2;
  if( pOp->p2>0 ){
    VdbeBranchTaken(res!=0,2);
    if( res ) goto jump_to_p2;
  }
  break;
}

/* Opcode: Next P1 P2 P3 P4 P5
/* Opcode: Next P1 P2 P3 * P5
**
** Advance cursor P1 so that it points to the next key/data pair in its
** table or index.  If there are no more key/value pairs then fall through
** to the following instruction.  But if the cursor advance was successful,
** jump immediately to P2.
**
** The Next opcode is only valid following an SeekGT, SeekGE, or
** OP_Rewind opcode used to position the cursor.  Next is not allowed
** to follow SeekLT, SeekLE, or OP_Last.
**
** The P1 cursor must be for a real table, not a pseudo-table.  P1 must have
** been opened prior to this opcode or the program will segfault.
**
** The P3 value is a hint to the btree implementation. If P3==1, that
** means P1 is an SQL index and that this instruction could have been
** omitted if that index had been unique.  P3 is usually 0.  P3 is
** always either 0 or 1.
**
** P4 is always of type P4_ADVANCE. The function pointer points to
** sqlite3BtreeNext().
**
** If P5 is positive and the jump is taken, then event counter
** number P5-1 in the prepared statement is incremented.
**
** See also: Prev
*/
/* Opcode: Prev P1 P2 P3 P4 P5
/* Opcode: Prev P1 P2 P3 * P5
**
** Back up cursor P1 so that it points to the previous key/data pair in its
** table or index.  If there is no previous key/value pairs then fall through
** to the following instruction.  But if the cursor backup was successful,
** jump immediately to P2.
**
**
** The Prev opcode is only valid following an SeekLT, SeekLE, or
** OP_Last opcode used to position the cursor.  Prev is not allowed
** to follow SeekGT, SeekGE, or OP_Rewind.
**
** The P1 cursor must be for a real table, not a pseudo-table.  If P1 is
** not open then the behavior is undefined.
**
** The P3 value is a hint to the btree implementation. If P3==1, that
** means P1 is an SQL index and that this instruction could have been
** omitted if that index had been unique.  P3 is usually 0.  P3 is
** always either 0 or 1.
**
** P4 is always of type P4_ADVANCE. The function pointer points to
** sqlite3BtreePrevious().
**
** If P5 is positive and the jump is taken, then event counter
** number P5-1 in the prepared statement is incremented.
*/
/* Opcode: SorterNext P1 P2 * * P5
**
** This opcode works just like OP_Next except that P1 must be a
** sorter object for which the OP_SorterSort opcode has been
** invoked.  This opcode advances the cursor to the next sorted
** record, or jumps to P2 if there are no more sorted records.
*/
case OP_SorterNext: {  /* jump */
  VdbeCursor *pC;

  pC = p->apCsr[pOp->p1];
  assert( isSorter(pC) );
  rc = sqlite3VdbeSorterNext(db, pC);
  goto next_tail;

case OP_Prev:          /* jump */
case OP_Next:          /* jump */
case OP_Prev:          /* jump, ncycle */
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( pOp->p5==0
       || pOp->p5==SQLITE_STMTSTATUS_FULLSCAN_STEP
       || pOp->p5==SQLITE_STMTSTATUS_AUTOINDEX);
  pC = p->apCsr[pOp->p1];
  assert( pC!=0 );
  assert( pC->deferredMoveto==0 );
  assert( pC->eCurType==CURTYPE_BTREE );
  assert( pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE
       || pC->seekOp==OP_Last   || pC->seekOp==OP_IfNoHope
       || pC->seekOp==OP_NullRow);
  rc = sqlite3BtreePrevious(pC->uc.pCursor, pOp->p3);
  goto next_tail;

case OP_Next:          /* jump, ncycle */
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( pOp->p5<ArraySize(p->aCounter) );
  assert( pOp->p5==0
       || pOp->p5==SQLITE_STMTSTATUS_FULLSCAN_STEP
       || pOp->p5==SQLITE_STMTSTATUS_AUTOINDEX);
  pC = p->apCsr[pOp->p1];
  assert( pC!=0 );
  assert( pC->deferredMoveto==0 );
  assert( pC->eCurType==CURTYPE_BTREE );
  assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
  assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );

  /* The Next opcode is only used after SeekGT, SeekGE, Rewind, and Found.
  ** The Prev opcode is only used after SeekLT, SeekLE, and Last. */
  assert( pOp->opcode!=OP_Next
       || pC->seekOp==OP_SeekGT || pC->seekOp==OP_SeekGE
       || pC->seekOp==OP_Rewind || pC->seekOp==OP_Found 
       || pC->seekOp==OP_NullRow);
  assert( pC->seekOp==OP_SeekGT || pC->seekOp==OP_SeekGE
       || pC->seekOp==OP_Rewind || pC->seekOp==OP_Found
       || pC->seekOp==OP_NullRow|| pC->seekOp==OP_SeekRowid
  assert( pOp->opcode!=OP_Prev
       || pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE
       || pC->seekOp==OP_Last 
       || pC->seekOp==OP_NullRow);
       || pC->seekOp==OP_IfNoHope);
  rc = sqlite3BtreeNext(pC->uc.pCursor, pOp->p3);

  rc = pOp->p4.xAdvance(pC->uc.pCursor, pOp->p3);
next_tail:
  pC->cacheStatus = CACHE_STALE;
  VdbeBranchTaken(rc==SQLITE_OK,2);
  if( rc==SQLITE_OK ){
    pC->nullRow = 0;
    p->aCounter[pOp->p5]++;
#ifdef SQLITE_TEST
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352

5353
5354

5355
5356



































5357
5358
5359
5360
5361

5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378

5379
5380
5381
5382
5383








5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405

5406
5407
5408
5409



5410
5411
5412
5413
5414
5415
5416
6337
6338
6339
6340
6341
6342
6343








6344
6345
6346
6347
6348
6349
6350
6351

6352
6353

6354
6355

6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393


6394












6395
6396
6397
6398

6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428

6429
6430
6431
6432

6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447







-
-
-
-
-
-
-
-








-
+

-
+

-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
-
+
-
-
-
-
-
-
-
-
-
-
-
-




-
+





+
+
+
+
+
+
+
+
















-




-
+




+
+
+







** the OPFLAG_USESEEKRESULT flag must only be set if there have been no prior
** seeks on the cursor or if the most recent seek used a key equivalent
** to P2. 
**
** This instruction only works for indices.  The equivalent instruction
** for tables is OP_Insert.
*/
/* Opcode: SorterInsert P1 P2 * * *
** Synopsis: key=r[P2]
**
** Register P2 holds an SQL index key made using the
** MakeRecord instructions.  This opcode writes that key
** into the sorter P1.  Data for the entry is nil.
*/
case OP_SorterInsert:       /* in2 */
case OP_IdxInsert: {        /* in2 */
  VdbeCursor *pC;
  BtreePayload x;

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  pC = p->apCsr[pOp->p1];
  sqlite3VdbeIncrWriteCounter(p, pC);
  assert( pC!=0 );
  assert( isSorter(pC)==(pOp->opcode==OP_SorterInsert) );
  assert( !isSorter(pC) );
  pIn2 = &aMem[pOp->p2];
  assert( pIn2->flags & MEM_Blob );
  assert( (pIn2->flags & MEM_Blob) || (pOp->p5 & OPFLAG_PREFORMAT) );
  if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
  assert( pC->eCurType==CURTYPE_BTREE || pOp->opcode==OP_SorterInsert );
  assert( pC->eCurType==CURTYPE_BTREE );
  assert( pC->isTable==0 );
  rc = ExpandBlob(pIn2);
  if( rc ) goto abort_due_to_error;
  x.nKey = pIn2->n;
  x.pKey = pIn2->z;
  x.aMem = aMem + pOp->p3;
  x.nMem = (u16)pOp->p4.i;
  rc = sqlite3BtreeInsert(pC->uc.pCursor, &x,
       (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION|OPFLAG_PREFORMAT)), 
      ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0)
      );
  assert( pC->deferredMoveto==0 );
  pC->cacheStatus = CACHE_STALE;
  if( rc) goto abort_due_to_error;
  break;
}

/* Opcode: SorterInsert P1 P2 * * *
** Synopsis: key=r[P2]
**
** Register P2 holds an SQL index key made using the
** MakeRecord instructions.  This opcode writes that key
** into the sorter P1.  Data for the entry is nil.
*/
case OP_SorterInsert: {     /* in2 */
  VdbeCursor *pC;

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  pC = p->apCsr[pOp->p1];
  sqlite3VdbeIncrWriteCounter(p, pC);
  assert( pC!=0 );
  assert( isSorter(pC) );
  pIn2 = &aMem[pOp->p2];
  assert( pIn2->flags & MEM_Blob );
  assert( pC->isTable==0 );
  rc = ExpandBlob(pIn2);
  if( rc ) goto abort_due_to_error;
  if( pOp->opcode==OP_SorterInsert ){
    rc = sqlite3VdbeSorterWrite(pC, pIn2);
  rc = sqlite3VdbeSorterWrite(pC, pIn2);
  }else{
    x.nKey = pIn2->n;
    x.pKey = pIn2->z;
    x.aMem = aMem + pOp->p3;
    x.nMem = (u16)pOp->p4.i;
    rc = sqlite3BtreeInsert(pC->uc.pCursor, &x,
         (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION)), 
        ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0)
        );
    assert( pC->deferredMoveto==0 );
    pC->cacheStatus = CACHE_STALE;
  }
  if( rc) goto abort_due_to_error;
  break;
}

/* Opcode: IdxDelete P1 P2 P3 * *
/* Opcode: IdxDelete P1 P2 P3 * P5
** Synopsis: key=r[P2@P3]
**
** The content of P3 registers starting at register P2 form
** an unpacked index key. This opcode removes that entry from the 
** index opened by cursor P1.
**
** If P5 is not zero, then raise an SQLITE_CORRUPT_INDEX error
** if no matching index entry is found.  This happens when running
** an UPDATE or DELETE statement and the index entry to be updated
** or deleted is not found.  For some uses of IdxDelete
** (example:  the EXCEPT operator) it does not matter that no matching
** entry is found.  For those cases, P5 is zero.  Also, do not raise
** this (self-correcting and non-critical) error if in writable_schema mode.
*/
case OP_IdxDelete: {
  VdbeCursor *pC;
  BtCursor *pCrsr;
  int res;
  UnpackedRecord r;

  assert( pOp->p3>0 );
  assert( pOp->p2>0 && pOp->p2+pOp->p3<=(p->nMem+1 - p->nCursor)+1 );
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  pC = p->apCsr[pOp->p1];
  assert( pC!=0 );
  assert( pC->eCurType==CURTYPE_BTREE );
  sqlite3VdbeIncrWriteCounter(p, pC);
  pCrsr = pC->uc.pCursor;
  assert( pCrsr!=0 );
  assert( pOp->p5==0 );
  r.pKeyInfo = pC->pKeyInfo;
  r.nField = (u16)pOp->p3;
  r.default_rc = 0;
  r.aMem = &aMem[pOp->p2];
  rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res);
  rc = sqlite3BtreeIndexMoveto(pCrsr, &r, &res);
  if( rc ) goto abort_due_to_error;
  if( res==0 ){
    rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE);
    if( rc ) goto abort_due_to_error;
  }else if( pOp->p5 && !sqlite3WritableSchema(db) ){
    rc = sqlite3ReportError(SQLITE_CORRUPT_INDEX, __LINE__, "index corruption");
    goto abort_due_to_error;
  }
  assert( pC->deferredMoveto==0 );
  pC->cacheStatus = CACHE_STALE;
  pC->seekResult = 0;
  break;
}

5438
5439
5440
5441
5442
5443
5444
5445
5446


5447
5448
5449
5450
5451
5452
5453
5454

5455
5456

5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467




5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484

5485

5486


5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498


















5499

5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510

5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521

5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532

5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546




5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580

























5581
5582
5583
5584
5585
5586
5587
5588
5589
5590

5591
5592
5593
5594
5595
5596
5597
6469
6470
6471
6472
6473
6474
6475


6476
6477
6478
6479
6480
6481
6482
6483
6484

6485
6486

6487
6488
6489
6490
6491
6492
6493
6494




6495
6496
6497
6498
6499
6500
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516
6517
6518

6519
6520
6521
6522
6523
6524
6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550

6551
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561

6562
6563
6564
6565
6566
6567
6568
6569
6570
6571
6572

6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583

6584
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594




6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609

6610
6611
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621
6622
6623
6624
6625
6626
6627
6628
6629


6630
6631
6632
6633
6634
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663

6664
6665
6666
6667
6668
6669
6670
6671







-
-
+
+







-
+

-
+







-
-
-
-
+
+
+
+

















+

+
-
+
+












+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+










-
+










-
+










-
+










-
-
-
-
+
+
+
+











-




















-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+









-
+







**
** Write into register P2 an integer which is the last entry in the record at
** the end of the index key pointed to by cursor P1.  This integer should be
** the rowid of the table entry to which this index entry points.
**
** See also: Rowid, MakeRecord.
*/
case OP_DeferredSeek:
case OP_IdxRowid: {           /* out2 */
case OP_DeferredSeek:         /* ncycle */
case OP_IdxRowid: {           /* out2, ncycle */
  VdbeCursor *pC;             /* The P1 index cursor */
  VdbeCursor *pTabCur;        /* The P2 table cursor (OP_DeferredSeek only) */
  i64 rowid;                  /* Rowid that P1 current points to */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  pC = p->apCsr[pOp->p1];
  assert( pC!=0 );
  assert( pC->eCurType==CURTYPE_BTREE );
  assert( pC->eCurType==CURTYPE_BTREE || IsNullCursor(pC) );
  assert( pC->uc.pCursor!=0 );
  assert( pC->isTable==0 );
  assert( pC->isTable==0 || IsNullCursor(pC) );
  assert( pC->deferredMoveto==0 );
  assert( !pC->nullRow || pOp->opcode==OP_IdxRowid );

  /* The IdxRowid and Seek opcodes are combined because of the commonality
  ** of sqlite3VdbeCursorRestore() and sqlite3VdbeIdxRowid(). */
  rc = sqlite3VdbeCursorRestore(pC);

  /* sqlite3VbeCursorRestore() can only fail if the record has been deleted
  ** out from under the cursor.  That will never happens for an IdxRowid
  ** or Seek opcode */
  if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
  /* sqlite3VdbeCursorRestore() may fail if the cursor has been disturbed
  ** since it was last positioned and an error (e.g. OOM or an IO error)
  ** occurs while trying to reposition it. */
  if( rc!=SQLITE_OK ) goto abort_due_to_error;

  if( !pC->nullRow ){
    rowid = 0;  /* Not needed.  Only used to silence a warning. */
    rc = sqlite3VdbeIdxRowid(db, pC->uc.pCursor, &rowid);
    if( rc!=SQLITE_OK ){
      goto abort_due_to_error;
    }
    if( pOp->opcode==OP_DeferredSeek ){
      assert( pOp->p3>=0 && pOp->p3<p->nCursor );
      pTabCur = p->apCsr[pOp->p3];
      assert( pTabCur!=0 );
      assert( pTabCur->eCurType==CURTYPE_BTREE );
      assert( pTabCur->uc.pCursor!=0 );
      assert( pTabCur->isTable );
      pTabCur->nullRow = 0;
      pTabCur->movetoTarget = rowid;
      pTabCur->deferredMoveto = 1;
      pTabCur->cacheStatus = CACHE_STALE;
      assert( pOp->p4type==P4_INTARRAY || pOp->p4.ai==0 );
      assert( !pTabCur->isEphemeral );
      pTabCur->aAltMap = pOp->p4.ai;
      pTabCur->ub.aAltMap = pOp->p4.ai;
      assert( !pC->isEphemeral );
      pTabCur->pAltCursor = pC;
    }else{
      pOut = out2Prerelease(p, pOp);
      pOut->u.i = rowid;
    }
  }else{
    assert( pOp->opcode==OP_IdxRowid );
    sqlite3VdbeMemSetNull(&aMem[pOp->p2]);
  }
  break;
}

/* Opcode: FinishSeek P1 * * * *
** 
** If cursor P1 was previously moved via OP_DeferredSeek, complete that
** seek operation now, without further delay.  If the cursor seek has
** already occurred, this instruction is a no-op.
*/
case OP_FinishSeek: {        /* ncycle */
  VdbeCursor *pC;            /* The P1 index cursor */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  pC = p->apCsr[pOp->p1];
  if( pC->deferredMoveto ){
    rc = sqlite3VdbeFinishMoveto(pC);
    if( rc ) goto abort_due_to_error;
  }
  break;
}

/* Opcode: IdxGE P1 P2 P3 P4 P5
/* Opcode: IdxGE P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** The P4 register values beginning with P3 form an unpacked index 
** key that omits the PRIMARY KEY.  Compare this key value against the index 
** that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID 
** fields at the end.
**
** If the P1 index entry is greater than or equal to the key value
** then jump to P2.  Otherwise fall through to the next instruction.
*/
/* Opcode: IdxGT P1 P2 P3 P4 P5
/* Opcode: IdxGT P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** The P4 register values beginning with P3 form an unpacked index 
** key that omits the PRIMARY KEY.  Compare this key value against the index 
** that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID 
** fields at the end.
**
** If the P1 index entry is greater than the key value
** then jump to P2.  Otherwise fall through to the next instruction.
*/
/* Opcode: IdxLT P1 P2 P3 P4 P5
/* Opcode: IdxLT P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** The P4 register values beginning with P3 form an unpacked index 
** key that omits the PRIMARY KEY or ROWID.  Compare this key value against
** the index that P1 is currently pointing to, ignoring the PRIMARY KEY or
** ROWID on the P1 index.
**
** If the P1 index entry is less than the key value then jump to P2.
** Otherwise fall through to the next instruction.
*/
/* Opcode: IdxLE P1 P2 P3 P4 P5
/* Opcode: IdxLE P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** The P4 register values beginning with P3 form an unpacked index 
** key that omits the PRIMARY KEY or ROWID.  Compare this key value against
** the index that P1 is currently pointing to, ignoring the PRIMARY KEY or
** ROWID on the P1 index.
**
** If the P1 index entry is less than or equal to the key value then jump
** to P2. Otherwise fall through to the next instruction.
*/
case OP_IdxLE:          /* jump */
case OP_IdxGT:          /* jump */
case OP_IdxLT:          /* jump */
case OP_IdxGE:  {       /* jump */
case OP_IdxLE:          /* jump, ncycle */
case OP_IdxGT:          /* jump, ncycle */
case OP_IdxLT:          /* jump, ncycle */
case OP_IdxGE:  {       /* jump, ncycle */
  VdbeCursor *pC;
  int res;
  UnpackedRecord r;

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  pC = p->apCsr[pOp->p1];
  assert( pC!=0 );
  assert( pC->isOrdered );
  assert( pC->eCurType==CURTYPE_BTREE );
  assert( pC->uc.pCursor!=0);
  assert( pC->deferredMoveto==0 );
  assert( pOp->p5==0 || pOp->p5==1 );
  assert( pOp->p4type==P4_INT32 );
  r.pKeyInfo = pC->pKeyInfo;
  r.nField = (u16)pOp->p4.i;
  if( pOp->opcode<OP_IdxLT ){
    assert( pOp->opcode==OP_IdxLE || pOp->opcode==OP_IdxGT );
    r.default_rc = -1;
  }else{
    assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxLT );
    r.default_rc = 0;
  }
  r.aMem = &aMem[pOp->p3];
#ifdef SQLITE_DEBUG
  {
    int i;
    for(i=0; i<r.nField; i++){
      assert( memIsValid(&r.aMem[i]) );
      REGISTER_TRACE(pOp->p3+i, &aMem[pOp->p3+i]);
    }
  }
#endif
  res = 0;  /* Not needed.  Only used to silence a warning. */
  rc = sqlite3VdbeIdxKeyCompare(db, pC, &r, &res);

  /* Inlined version of sqlite3VdbeIdxKeyCompare() */
  {
    i64 nCellKey = 0;
    BtCursor *pCur;
    Mem m;

    assert( pC->eCurType==CURTYPE_BTREE );
    pCur = pC->uc.pCursor;
    assert( sqlite3BtreeCursorIsValid(pCur) );
    nCellKey = sqlite3BtreePayloadSize(pCur);
    /* nCellKey will always be between 0 and 0xffffffff because of the way
    ** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */
    if( nCellKey<=0 || nCellKey>0x7fffffff ){
      rc = SQLITE_CORRUPT_BKPT;
      goto abort_due_to_error;
    }
    sqlite3VdbeMemInit(&m, db, 0);
    rc = sqlite3VdbeMemFromBtreeZeroOffset(pCur, (u32)nCellKey, &m);
    if( rc ) goto abort_due_to_error;
    res = sqlite3VdbeRecordCompareWithSkip(m.n, m.z, &r, 0);
    sqlite3VdbeMemReleaseMalloc(&m);
  }
  /* End of inlined sqlite3VdbeIdxKeyCompare() */

  assert( (OP_IdxLE&1)==(OP_IdxLT&1) && (OP_IdxGE&1)==(OP_IdxGT&1) );
  if( (pOp->opcode&1)==(OP_IdxLT&1) ){
    assert( pOp->opcode==OP_IdxLE || pOp->opcode==OP_IdxLT );
    res = -res;
  }else{
    assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxGT );
    res++;
  }
  VdbeBranchTaken(res>0,2);
  if( rc ) goto abort_due_to_error;
  assert( rc==SQLITE_OK );
  if( res>0 ) goto jump_to_p2;
  break;
}

/* Opcode: Destroy P1 P2 P3 * *
**
** Delete an entire database table or index whose root page in the database
5658
5659
5660
5661
5662
5663
5664
5665

5666
5667
5668
5669



5670
5671
5672
5673
5674

5675
5676
5677
5678
5679
5680

5681
5682
5683
5684
5685
5686
5687
5688
5689
6732
6733
6734
6735
6736
6737
6738

6739




6740
6741
6742
6743
6744
6745
6746

6747
6748
6749
6750
6751
6752

6753


6754
6755
6756
6757
6758
6759
6760







-
+
-
-
-
-
+
+
+




-
+





-
+
-
-







** in the database file is given by P1.  But, unlike Destroy, do not
** remove the table or index from the database file.
**
** The table being clear is in the main database file if P2==0.  If
** P2==1 then the table to be clear is in the auxiliary database file
** that is used to store tables create using CREATE TEMPORARY TABLE.
**
** If the P3 value is non-zero, then the table referred to must be an
** If the P3 value is non-zero, then the row change count is incremented
** intkey table (an SQL table, not an index). In this case the row change 
** count is incremented by the number of rows in the table being cleared. 
** If P3 is greater than zero, then the value stored in register P3 is
** also incremented by the number of rows in the table being cleared.
** by the number of rows in the table being cleared. If P3 is greater
** than zero, then the value stored in register P3 is also incremented
** by the number of rows in the table being cleared.
**
** See also: Destroy
*/
case OP_Clear: {
  int nChange;
  i64 nChange;
 
  sqlite3VdbeIncrWriteCounter(p, 0);
  nChange = 0;
  assert( p->readOnly==0 );
  assert( DbMaskTest(p->btreeMask, pOp->p2) );
  rc = sqlite3BtreeClearTable(
  rc = sqlite3BtreeClearTable(db->aDb[pOp->p2].pBt, (u32)pOp->p1, &nChange);
      db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &nChange : 0)
  );
  if( pOp->p3 ){
    p->nChange += nChange;
    if( pOp->p3>0 ){
      assert( memIsValid(&aMem[pOp->p3]) );
      memAboutToChange(p, &aMem[pOp->p3]);
      aMem[pOp->p3].u.i += nChange;
    }
5723
5724
5725
5726
5727
5728
5729
5730

5731
5732
5733
5734
5735
5736
5737
6794
6795
6796
6797
6798
6799
6800

6801
6802
6803
6804
6805
6806
6807
6808







-
+







** Allocate a new b-tree in the main database file if P1==0 or in the
** TEMP database file if P1==1 or in an attached database if
** P1>1.  The P3 argument must be 1 (BTREE_INTKEY) for a rowid table
** it must be 2 (BTREE_BLOBKEY) for an index or WITHOUT ROWID table.
** The root page number of the new b-tree is stored in register P2.
*/
case OP_CreateBtree: {          /* out2 */
  int pgno;
  Pgno pgno;
  Db *pDb;

  sqlite3VdbeIncrWriteCounter(p, 0);
  pOut = out2Prerelease(p, pOp);
  pgno = 0;
  assert( pOp->p3==BTREE_INTKEY || pOp->p3==BTREE_BLOBKEY );
  assert( pOp->p1>=0 && pOp->p1<db->nDb );
5756
5757
5758
5759
5760
5761
5762
5763

5764
5765
5766
5767
5768
5769
5770
5771
5772

5773
5774
5775
5776
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
5803
5804

5805
5806
5807


5808
5809
5810
5811
5812
5813

5814
5815
5816






5817
5818
5819
5820
5821
5822
5823
6827
6828
6829
6830
6831
6832
6833

6834
6835
6836
6837
6838
6839
6840
6841
6842

6843
6844
6845
6846
6847
6848
6849
6850
6851
6852
6853
6854
6855
6856
6857
6858

6859
6860
6861
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
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
6903
6904







-
+








-
+















-
+
+
+





-
+





-
+




+

-
-
+
+






+



+
+
+
+
+
+







  db->nSqlExec--;
  if( rc ) goto abort_due_to_error;
  break;
}

/* Opcode: ParseSchema P1 * * P4 *
**
** Read and parse all entries from the SQLITE_MASTER table of database P1
** Read and parse all entries from the schema table of database P1
** that match the WHERE clause P4.  If P4 is a NULL pointer, then the
** entire schema for P1 is reparsed.
**
** This opcode invokes the parser to create a new virtual machine,
** then runs the new virtual machine.  It is thus a re-entrant opcode.
*/
case OP_ParseSchema: {
  int iDb;
  const char *zMaster;
  const char *zSchema;
  char *zSql;
  InitData initData;

  /* Any prepared statement that invokes this opcode will hold mutexes
  ** on every btree.  This is a prerequisite for invoking 
  ** sqlite3InitCallback().
  */
#ifdef SQLITE_DEBUG
  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
           || (CORRUPT_DB && (db->flags & SQLITE_NoSchemaError)!=0) );

#ifndef SQLITE_OMIT_ALTERTABLE
  if( pOp->p4.z==0 ){
    sqlite3SchemaClear(db->aDb[iDb].pSchema);
    db->mDbFlags &= ~DBFLAG_SchemaKnownOk;
    rc = sqlite3InitOne(db, iDb, &p->zErrMsg, INITFLAG_AlterTable);
    rc = sqlite3InitOne(db, iDb, &p->zErrMsg, pOp->p5);
    db->mDbFlags |= DBFLAG_SchemaChange;
    p->expired = 0;
  }else
#endif
  {
    zMaster = MASTER_NAME;
    zSchema = LEGACY_SCHEMA_TABLE;
    initData.db = db;
    initData.iDb = iDb;
    initData.pzErrMsg = &p->zErrMsg;
    initData.mInitFlags = 0;
    initData.mxPage = sqlite3BtreeLastPage(db->aDb[iDb].pBt);
    zSql = sqlite3MPrintf(db,
       "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
       db->aDb[iDb].zDbSName, zMaster, pOp->p4.z);
       "SELECT*FROM\"%w\".%s WHERE %s ORDER BY rowid",
       db->aDb[iDb].zDbSName, zSchema, pOp->p4.z);
    if( zSql==0 ){
      rc = SQLITE_NOMEM_BKPT;
    }else{
      assert( db->init.busy==0 );
      db->init.busy = 1;
      initData.rc = SQLITE_OK;
      initData.nInitRow = 0;
      assert( !db->mallocFailed );
      rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
      if( rc==SQLITE_OK ) rc = initData.rc;
      if( rc==SQLITE_OK && initData.nInitRow==0 ){
        /* The OP_ParseSchema opcode with a non-NULL P4 argument should parse
        ** at least one SQL statement. Any less than that indicates that
        ** the sqlite_schema table is corrupt. */
        rc = SQLITE_CORRUPT_BKPT;
      }
      sqlite3DbFreeNN(db, zSql);
      db->init.busy = 0;
    }
  }
  if( rc ){
    sqlite3ResetAllSchemasOfConnection(db);
    if( rc==SQLITE_NOMEM ){
5904
5905
5906
5907
5908
5909
5910
5911

5912
5913
5914
5915
5916
5917
5918
5919
5920

5921
5922
5923
5924
5925
5926
5927
5928
5929


5930
5931
5932
5933
5934



5935
5936
5937
5938
5939
5940
5941

5942
5943
5944
5945
5946
5947
5948
6985
6986
6987
6988
6989
6990
6991

6992
6993
6994
6995
6996
6997
6998
6999
7000

7001
7002
7003
7004
7005
7006
7007
7008


7009
7010
7011
7012
7013


7014
7015
7016
7017
7018
7019
7020
7021
7022

7023
7024
7025
7026
7027
7028
7029
7030







-
+








-
+







-
-
+
+



-
-
+
+
+






-
+







** If P5 is not zero, the check is done on the auxiliary database
** file, not the main database file.
**
** This opcode is used to implement the integrity_check pragma.
*/
case OP_IntegrityCk: {
  int nRoot;      /* Number of tables to check.  (Number of root pages.) */
  int *aRoot;     /* Array of rootpage numbers for tables to be checked */
  Pgno *aRoot;    /* Array of rootpage numbers for tables to be checked */
  int nErr;       /* Number of errors reported */
  char *z;        /* Text of the error report */
  Mem *pnErr;     /* Register keeping track of errors remaining */

  assert( p->bIsReader );
  nRoot = pOp->p2;
  aRoot = pOp->p4.ai;
  assert( nRoot>0 );
  assert( aRoot[0]==nRoot );
  assert( aRoot[0]==(Pgno)nRoot );
  assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
  pnErr = &aMem[pOp->p3];
  assert( (pnErr->flags & MEM_Int)!=0 );
  assert( (pnErr->flags & (MEM_Str|MEM_Blob))==0 );
  pIn1 = &aMem[pOp->p1];
  assert( pOp->p5<db->nDb );
  assert( DbMaskTest(p->btreeMask, pOp->p5) );
  z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, &aRoot[1], nRoot,
                                 (int)pnErr->u.i+1, &nErr);
  rc = sqlite3BtreeIntegrityCheck(db, db->aDb[pOp->p5].pBt, &aRoot[1], nRoot,
                                 (int)pnErr->u.i+1, &nErr, &z);
  sqlite3VdbeMemSetNull(pIn1);
  if( nErr==0 ){
    assert( z==0 );
  }else if( z==0 ){
    goto no_mem;
  }else if( rc ){
    sqlite3_free(z);
    goto abort_due_to_error;
  }else{
    pnErr->u.i -= nErr-1;
    sqlite3VdbeMemSetStr(pIn1, z, -1, SQLITE_UTF8, sqlite3_free);
  }
  UPDATE_MAX_BLOBSIZE(pIn1);
  sqlite3VdbeChangeEncoding(pIn1, encoding);
  break;
  goto check_for_interrupt;
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */

/* Opcode: RowSetAdd P1 P2 * * *
** Synopsis: rowset(P1)=r[P2]
**
** Insert the integer value held by register P2 into a RowSet object
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
7213
7214
7215
7216
7217
7218
7219



7220
7221
7222
7223
7224
7225
7226







-
-
-







    pFrame->aMem = p->aMem;
    pFrame->nMem = p->nMem;
    pFrame->apCsr = p->apCsr;
    pFrame->nCursor = p->nCursor;
    pFrame->aOp = p->aOp;
    pFrame->nOp = p->nOp;
    pFrame->token = pProgram->token;
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
    pFrame->anExec = p->anExec;
#endif
#ifdef SQLITE_DEBUG
    pFrame->iFrameMagic = SQLITE_FRAME_MAGIC;
#endif

    pEnd = &VdbeFrameMem(pFrame)[pFrame->nChildMem];
    for(pMem=VdbeFrameMem(pFrame); pMem!=pEnd; pMem++){
      pMem->flags = MEM_Undefined;
6170
6171
6172
6173
6174
6175
6176
6177
6178










6179
6180
6181

6182
6183
6184
6185
6186
6187
6188
6189
7249
7250
7251
7252
7253
7254
7255


7256
7257
7258
7259
7260
7261
7262
7263
7264
7265
7266
7267

7268

7269
7270
7271
7272
7273
7274
7275







-
-
+
+
+
+
+
+
+
+
+
+


-
+
-







  p->nMem = pFrame->nChildMem;
  p->nCursor = (u16)pFrame->nChildCsr;
  p->apCsr = (VdbeCursor **)&aMem[p->nMem];
  pFrame->aOnce = (u8*)&p->apCsr[pProgram->nCsr];
  memset(pFrame->aOnce, 0, (pProgram->nOp + 7)/8);
  p->aOp = aOp = pProgram->aOp;
  p->nOp = pProgram->nOp;
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
  p->anExec = 0;
#ifdef SQLITE_DEBUG
  /* Verify that second and subsequent executions of the same trigger do not
  ** try to reuse register values from the first use. */
  {
    int i;
    for(i=0; i<p->nMem; i++){
      aMem[i].pScopyFrom = 0;  /* Prevent false-positive AboutToChange() errs */
      MemSetTypeFlag(&aMem[i], MEM_Undefined); /* Fault if this reg is reused */
    }
  }
#endif
  pOp = &aOp[-1];

  goto check_for_interrupt;
  break;
}

/* Opcode: Param P1 P2 * * *
**
** This opcode is only ever present in sub-programs called via the 
** OP_Program instruction. Copy a value currently stored in a memory 
** cell of the calling (parent) frame to cell P2 in the current frames 
6302
6303
6304
6305
6306
6307
6308
6309

6310
6311
6312
6313
6314
6315
6316
7388
7389
7390
7391
7392
7393
7394

7395
7396
7397
7398
7399
7400
7401
7402







-
+







  break;
}

/* Opcode: OffsetLimit P1 P2 P3 * *
** Synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)
**
** This opcode performs a commonly used computation associated with
** LIMIT and OFFSET process.  r[P1] holds the limit counter.  r[P3]
** LIMIT and OFFSET processing.  r[P1] holds the limit counter.  r[P3]
** holds the offset counter.  The opcode computes the combined value
** of the LIMIT and OFFSET and stores that value in r[P2].  The r[P2]
** value computed is the total number of rows that will need to be
** visited in order to complete the query.
**
** If r[P3] is zero or negative, that means there is no OFFSET
** and r[P2] is set to be the value of the LIMIT, r[P1].
6434
6435
6436
6437
6438
6439
6440

6441
6442
6443
6444
6445
6446
6447
6448
6449

6450
6451
6452
6453
6454
6455
6456
7520
7521
7522
7523
7524
7525
7526
7527
7528
7529
7530
7531
7532
7533
7534
7535
7536
7537
7538
7539
7540
7541
7542
7543
7544







+









+







  pCtx->pOut = (Mem*)&(pCtx->argv[n]);
  sqlite3VdbeMemInit(pCtx->pOut, db, MEM_Null);
  pCtx->pFunc = pOp->p4.pFunc;
  pCtx->iOp = (int)(pOp - aOp);
  pCtx->pVdbe = p;
  pCtx->skipFlag = 0;
  pCtx->isError = 0;
  pCtx->enc = encoding;
  pCtx->argc = n;
  pOp->p4type = P4_FUNCCTX;
  pOp->p4.pCtx = pCtx;

  /* OP_AggInverse must have P1==1 and OP_AggStep must have P1==0 */
  assert( pOp->p1==(pOp->opcode==OP_AggInverse) );

  pOp->opcode = OP_AggStep1;
  /* Fall through into OP_AggStep */
  /* no break */ deliberate_fall_through
}
case OP_AggStep1: {
  int i;
  sqlite3_context *pCtx;
  Mem *pMem;

  assert( pOp->p4type==P4_FUNCCTX );
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
7635
7636
7637
7638
7639
7640
7641
7642
7643
7644
7645
7646
7647
7648
7649
7650
7651
7652
7653
7654
7655
7656



7657
7658
7659
7660
7661
7662
7663







+














-
-
-







  Mem *pMem;
  assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) );
  assert( pOp->p3==0 || pOp->opcode==OP_AggValue );
  pMem = &aMem[pOp->p1];
  assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
#ifndef SQLITE_OMIT_WINDOWFUNC
  if( pOp->p3 ){
    memAboutToChange(p, &aMem[pOp->p3]);
    rc = sqlite3VdbeMemAggValue(pMem, &aMem[pOp->p3], pOp->p4.pFunc);
    pMem = &aMem[pOp->p3];
  }else
#endif
  {
    rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc);
  }
  
  if( rc ){
    sqlite3VdbeError(p, "%s", sqlite3_value_text(pMem));
    goto abort_due_to_error;
  }
  sqlite3VdbeChangeEncoding(pMem, encoding);
  UPDATE_MAX_BLOBSIZE(pMem);
  if( sqlite3VdbeMemTooBig(pMem) ){
    goto too_big;
  }
  break;
}

#ifndef SQLITE_OMIT_WAL
/* Opcode: Checkpoint P1 P2 P3 * *
**
** Checkpoint database P1. This is a no-op if P1 is not currently in
6634
6635
6636
6637
6638
6639
6640

6641
6642
6643
6644
6645
6646
6647
6648
6649

6650
6651
6652
6653
6654
6655
6656
6657
6658

6659
6660
6661
6662
6663
6664
6665
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
7720
7721
7722
7723
7724
7725
7726
7727
7728
7729
7730
7731
7732
7733
7734
7735
7736
7737
7738
7739
7740
7741
7742
7743
7744
7745

7746
7747
7748
7749
7750
7751
7752



7753
7754
7755
7756
7757
7758
7759
7760
7761
7762
7763
7764
7765
7766
7767
7768
7769
7770
7771
























7772
7773
7774
7775
7776
7777
7778
7779
7780
7781
7782
7783
7784
7785
7786
7787
7788
7789
7790
7791
7792
7793
7794
7795
7796

7797
7798
7799
7800
7801
7802
7803
7804
7805







+









+








-
+






-
-
-
+
+
+
+
+
+
+
+
+
+
+
+







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+







  eNew = pOp->p3;
  assert( eNew==PAGER_JOURNALMODE_DELETE 
       || eNew==PAGER_JOURNALMODE_TRUNCATE 
       || eNew==PAGER_JOURNALMODE_PERSIST 
       || eNew==PAGER_JOURNALMODE_OFF
       || eNew==PAGER_JOURNALMODE_MEMORY
       || eNew==PAGER_JOURNALMODE_WAL
       || eNew==PAGER_JOURNALMODE_WAL2
       || eNew==PAGER_JOURNALMODE_QUERY
  );
  assert( pOp->p1>=0 && pOp->p1<db->nDb );
  assert( p->readOnly==0 );

  pBt = db->aDb[pOp->p1].pBt;
  pPager = sqlite3BtreePager(pBt);
  eOld = sqlite3PagerGetJournalMode(pPager);
  if( eNew==PAGER_JOURNALMODE_QUERY ) eNew = eOld;
  assert( sqlite3BtreeHoldsMutex(pBt) );
  if( !sqlite3PagerOkToChangeJournalMode(pPager) ) eNew = eOld;

#ifndef SQLITE_OMIT_WAL
  zFilename = sqlite3PagerFilename(pPager, 1);

  /* Do not allow a transition to journal_mode=WAL for a database
  ** in temporary storage or if the VFS does not support shared memory 
  */
  if( eNew==PAGER_JOURNALMODE_WAL
  if( isWalMode(eNew)
   && (sqlite3Strlen30(zFilename)==0           /* Temp file */
       || !sqlite3PagerWalSupported(pPager))   /* No shared-memory support */
  ){
    eNew = eOld;
  }

  if( (eNew!=eOld)
   && (eOld==PAGER_JOURNALMODE_WAL || eNew==PAGER_JOURNALMODE_WAL)
  ){
  if( eNew!=eOld && (isWalMode(eNew) || isWalMode(eOld)) ){

    /* Prevent changing directly to wal2 from wal mode. And vice versa. */
    if( isWalMode(eNew) && isWalMode(eOld) ){
      rc = SQLITE_ERROR;
      sqlite3VdbeError(p, "cannot change from %s to %s mode",
          sqlite3JournalModename(eOld), sqlite3JournalModename(eNew)
      );
      goto abort_due_to_error;
    }

    /* Prevent switching into or out of wal/wal2 mode mid-transaction */
    if( !db->autoCommit || db->nVdbeRead>1 ){
      rc = SQLITE_ERROR;
      sqlite3VdbeError(p,
          "cannot change %s wal mode from within a transaction",
          (eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of")
      );
      goto abort_due_to_error;
    }else{
 
      if( eOld==PAGER_JOURNALMODE_WAL ){
        /* If leaving WAL mode, close the log file. If successful, the call
        ** to PagerCloseWal() checkpoints and deletes the write-ahead-log 
        ** file. An EXCLUSIVE lock may still be held on the database file 
        ** after a successful return. 
        */
        rc = sqlite3PagerCloseWal(pPager, db);
        if( rc==SQLITE_OK ){
          sqlite3PagerSetJournalMode(pPager, eNew);
        }
      }else if( eOld==PAGER_JOURNALMODE_MEMORY ){
        /* Cannot transition directly from MEMORY to WAL.  Use mode OFF
        ** as an intermediate */
        sqlite3PagerSetJournalMode(pPager, PAGER_JOURNALMODE_OFF);
      }
  
      /* Open a transaction on the database file. Regardless of the journal
      ** mode, this transaction always uses a rollback journal.
      */
      assert( sqlite3BtreeIsInTrans(pBt)==0 );
      if( rc==SQLITE_OK ){
        rc = sqlite3BtreeSetVersion(pBt, (eNew==PAGER_JOURNALMODE_WAL ? 2 : 1));
    }
 
    if( isWalMode(eOld) ){
      /* If leaving WAL mode, close the log file. If successful, the call
      ** to PagerCloseWal() checkpoints and deletes the write-ahead-log 
      ** file. An EXCLUSIVE lock may still be held on the database file 
      ** after a successful return. 
      */
      rc = sqlite3PagerCloseWal(pPager, db);
      if( rc==SQLITE_OK ){
        sqlite3PagerSetJournalMode(pPager, eNew);
      }
    }else if( eOld==PAGER_JOURNALMODE_MEMORY ){
      /* Cannot transition directly from MEMORY to WAL.  Use mode OFF
      ** as an intermediate */
      sqlite3PagerSetJournalMode(pPager, PAGER_JOURNALMODE_OFF);
    }

    /* Open a transaction on the database file. Regardless of the journal
    ** mode, this transaction always uses a rollback journal.
    */
    assert( sqlite3BtreeTxnState(pBt)!=SQLITE_TXN_WRITE );
    if( rc==SQLITE_OK ){
      /* 1==rollback, 2==wal, 3==wal2 */
      rc = sqlite3BtreeSetVersion(pBt, 
      }
          1 + isWalMode(eNew) + (eNew==PAGER_JOURNALMODE_WAL2)
      );
    }
  }
#endif /* ifndef SQLITE_OMIT_WAL */

  if( rc ) eNew = eOld;
  eNew = sqlite3PagerSetJournalMode(pPager, eNew);

6779
6780
6781
6782
6783
6784
6785






























6786
6787
6788
6789
6790
6791
6792
6793
6794
6795
6796
6797
6798
6799
6800
6801
6802
6803
6804
6805
6806

6807
6808
6809

6810
6811
6812
6813
6814
6815
6816
6817
7878
7879
7880
7881
7882
7883
7884
7885
7886
7887
7888
7889
7890
7891
7892
7893
7894
7895
7896
7897
7898
7899
7900
7901
7902
7903
7904
7905
7906
7907
7908
7909
7910
7911
7912
7913
7914
7915
7916
7917
7918
7919
7920
7921
7922
7923
7924
7925
7926
7927
7928
7929
7930
7931
7932
7933
7934

7935



7936

7937
7938
7939
7940
7941
7942
7943







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




















-
+
-
-
-
+
-







  if( !pOp->p1 ){
    sqlite3ExpirePreparedStatements(db, pOp->p2);
  }else{
    p->expired = pOp->p2+1;
  }
  break;
}

/* Opcode: CursorLock P1 * * * *
**
** Lock the btree to which cursor P1 is pointing so that the btree cannot be
** written by an other cursor.
*/
case OP_CursorLock: {
  VdbeCursor *pC;
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  pC = p->apCsr[pOp->p1];
  assert( pC!=0 );
  assert( pC->eCurType==CURTYPE_BTREE );
  sqlite3BtreeCursorPin(pC->uc.pCursor);
  break;
}

/* Opcode: CursorUnlock P1 * * * *
**
** Unlock the btree to which cursor P1 is pointing so that it can be
** written by other cursors.
*/
case OP_CursorUnlock: {
  VdbeCursor *pC;
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  pC = p->apCsr[pOp->p1];
  assert( pC!=0 );
  assert( pC->eCurType==CURTYPE_BTREE );
  sqlite3BtreeCursorUnpin(pC->uc.pCursor);
  break;
}

#ifndef SQLITE_OMIT_SHARED_CACHE
/* Opcode: TableLock P1 P2 P3 P4 *
** Synopsis: iDb=P1 root=P2 write=P3
**
** Obtain a lock on a particular table. This instruction is only used when
** the shared-cache feature is enabled. 
**
** P1 is the index of the database in sqlite3.aDb[] of the database
** on which the lock is acquired.  A readlock is obtained if P3==0 or
** a write lock if P3==1.
**
** P2 contains the root-page of the table to lock.
**
** P4 contains a pointer to the name of the table being locked. This is only
** used to generate an error message if the lock cannot be obtained.
*/
case OP_TableLock: {
  u8 isWriteLock = (u8)pOp->p3;
#ifndef SQLITE_OMIT_CONCURRENT
  if( isWriteLock && db->bConcurrent && pOp->p2==1 && pOp->p1!=1 ){
  if( isWriteLock && db->eConcurrent && pOp->p2==1 && pOp->p1!=1 ){
    rc = SQLITE_ERROR;
    sqlite3VdbeError(p, 
        "cannot modify database schema within CONCURRENT transaction");
    db->eConcurrent = CONCURRENT_SCHEMA;
    goto abort_due_to_error;
  }
#endif
  if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommit) ){
    int p1 = pOp->p1; 
    assert( p1>=0 && p1<db->nDb );
    assert( DbMaskTest(p->btreeMask, p1) );
    assert( isWriteLock==0 || isWriteLock==1 );
6883
6884
6885
6886
6887
6888
6889

6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902

6903
6904
6905
6906
6907
6908
6909
8009
8010
8011
8012
8013
8014
8015
8016
8017
8018
8019
8020
8021
8022
8023
8024
8025
8026
8027
8028

8029
8030
8031
8032
8033
8034
8035
8036







+












-
+







** P4 is the name of a virtual table in database P1.  Call the xDestroy method
** of that table.
*/
case OP_VDestroy: {
  db->nVDestroy++;
  rc = sqlite3VtabCallDestroy(db, pOp->p1, pOp->p4.z);
  db->nVDestroy--;
  assert( p->errorAction==OE_Abort && p->usesStmtJournal );
  if( rc ) goto abort_due_to_error;
  break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */

#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VOpen P1 * * P4 *
**
** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
** P1 is a cursor number.  This opcode opens a cursor to the virtual
** table and stores that cursor in P1.
*/
case OP_VOpen: {
case OP_VOpen: {             /* ncycle */
  VdbeCursor *pCur;
  sqlite3_vtab_cursor *pVCur;
  sqlite3_vtab *pVtab;
  const sqlite3_module *pModule;

  assert( p->bIsReader );
  pCur = 0;
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
6943
8045
8046
8047
8048
8049
8050
8051

8052
8053
8054
8055
8056
8057
8058
8059
8060
8061
8062
8063
8064
8065
8066
8067
8068
8069
8070
8071
8072
8073
8074
8075
8076
8077
8078
8079
8080
8081
8082
8083
8084
8085
8086
8087
8088
8089
8090
8091
8092
8093
8094
8095
8096
8097
8098







-
+











+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  sqlite3VtabImportErrmsg(p, pVtab);
  if( rc ) goto abort_due_to_error;

  /* Initialize sqlite3_vtab_cursor base class */
  pVCur->pVtab = pVtab;

  /* Initialize vdbe cursor object */
  pCur = allocateCursor(p, pOp->p1, 0, -1, CURTYPE_VTAB);
  pCur = allocateCursor(p, pOp->p1, 0, CURTYPE_VTAB);
  if( pCur ){
    pCur->uc.pVCur = pVCur;
    pVtab->nRef++;
  }else{
    assert( db->mallocFailed );
    pModule->xClose(pVCur);
    goto no_mem;
  }
  break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */

#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VInitIn P1 P2 P3 * *
** Synopsis: r[P2]=ValueList(P1,P3)
**
** Set register P2 to be a pointer to a ValueList object for cursor P1
** with cache register P3 and output register P3+1.  This ValueList object
** can be used as the first argument to sqlite3_vtab_in_first() and
** sqlite3_vtab_in_next() to extract all of the values stored in the P1
** cursor.  Register P3 is used to hold the values returned by
** sqlite3_vtab_in_first() and sqlite3_vtab_in_next().
*/
case OP_VInitIn: {        /* out2, ncycle */
  VdbeCursor *pC;         /* The cursor containing the RHS values */
  ValueList *pRhs;        /* New ValueList object to put in reg[P2] */

  pC = p->apCsr[pOp->p1];
  pRhs = sqlite3_malloc64( sizeof(*pRhs) );
  if( pRhs==0 ) goto no_mem;
  pRhs->pCsr = pC->uc.pCursor;
  pRhs->pOut = &aMem[pOp->p3];
  pOut = out2Prerelease(p, pOp);
  pOut->flags = MEM_Null;
  sqlite3VdbeMemSetPointer(pOut, pRhs, "ValueList", sqlite3VdbeValueListFree);
  break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */


#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VFilter P1 P2 P3 P4 *
** Synopsis: iplan=r[P3] zplan='P4'
**
** P1 is a cursor opened using VOpen.  P2 is an address to jump to if
** the filtered result set is empty.
6951
6952
6953
6954
6955
6956
6957
6958

6959
6960
6961
6962
6963
6964
6965
6966
6967
6968
6969
6970
6971
6972
6973
6974
6975

6976
6977
6978
6979
6980
6981
6982
6983
6984
6985
6986
6987
6988
6989
6990
6991
6992
6993
6994
8106
8107
8108
8109
8110
8111
8112

8113
8114
8115
8116
8117
8118
8119
8120
8121
8122
8123
8124
8125
8126
8127
8128
8129
8130
8131
8132
8133
8134
8135
8136
8137
8138
8139
8140
8141
8142

8143
8144
8145
8146
8147
8148
8149







-
+

















+











-







** P3. Register P3+1 stores the argc parameter to be passed to the
** xFilter method. Registers P3+2..P3+1+argc are the argc
** additional parameters which are passed to
** xFilter as argv. Register P3+2 becomes argv[0] when passed to xFilter.
**
** A jump is made to P2 if the result set after filtering would be empty.
*/
case OP_VFilter: {   /* jump */
case OP_VFilter: {   /* jump, ncycle */
  int nArg;
  int iQuery;
  const sqlite3_module *pModule;
  Mem *pQuery;
  Mem *pArgc;
  sqlite3_vtab_cursor *pVCur;
  sqlite3_vtab *pVtab;
  VdbeCursor *pCur;
  int res;
  int i;
  Mem **apArg;

  pQuery = &aMem[pOp->p3];
  pArgc = &pQuery[1];
  pCur = p->apCsr[pOp->p1];
  assert( memIsValid(pQuery) );
  REGISTER_TRACE(pOp->p3, pQuery);
  assert( pCur!=0 );
  assert( pCur->eCurType==CURTYPE_VTAB );
  pVCur = pCur->uc.pVCur;
  pVtab = pVCur->pVtab;
  pModule = pVtab->pModule;

  /* Grab the index number and argc parameters */
  assert( (pQuery->flags&MEM_Int)!=0 && pArgc->flags==MEM_Int );
  nArg = (int)pArgc->u.i;
  iQuery = (int)pQuery->u.i;

  /* Invoke the xFilter method */
  res = 0;
  apArg = p->apArg;
  for(i = 0; i<nArg; i++){
    apArg[i] = &pArgc[i+1];
  }
  rc = pModule->xFilter(pVCur, iQuery, pOp->p4.z, nArg, apArg);
  sqlite3VtabImportErrmsg(p, pVtab);
  if( rc ) goto abort_due_to_error;
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
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
7066
7067
7068
7069
7070
7071

7072
7073
7074
7075
7076
7077
7078

7079
7080
7081
7082
7083
7084
7085
8166
8167
8168
8169
8170
8171
8172

8173
8174
8175
8176
8177
8178
8179

8180
8181
8182
8183
8184
8185
8186
8187
8188
8189
8190
8191
8192
8193
8194

8195
8196
8197
8198
8199
8200
8201
8202
8203
8204
8205
8206
8207
8208
8209
8210
8211
8212



8213
8214
8215
8216
8217
8218
8219
8220
8221
8222
8223
8224

8225
8226
8227
8228
8229
8230

8231
8232
8233
8234
8235
8236
8237
8238
8239







-
+






-
+







+





+
-
+

















-
-
-












-
+





-

+







** an unchanging column during an UPDATE operation, then the P5
** value is OPFLAG_NOCHNG.  This will cause the sqlite3_vtab_nochange()
** function to return true inside the xColumn method of the virtual
** table implementation.  The P5 column might also contain other
** bits (OPFLAG_LENGTHARG or OPFLAG_TYPEOFARG) but those bits are
** unused by OP_VColumn.
*/
case OP_VColumn: {
case OP_VColumn: {           /* ncycle */
  sqlite3_vtab *pVtab;
  const sqlite3_module *pModule;
  Mem *pDest;
  sqlite3_context sContext;

  VdbeCursor *pCur = p->apCsr[pOp->p1];
  assert( pCur->eCurType==CURTYPE_VTAB );
  assert( pCur!=0 );
  assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
  pDest = &aMem[pOp->p3];
  memAboutToChange(p, pDest);
  if( pCur->nullRow ){
    sqlite3VdbeMemSetNull(pDest);
    break;
  }
  assert( pCur->eCurType==CURTYPE_VTAB );
  pVtab = pCur->uc.pVCur->pVtab;
  pModule = pVtab->pModule;
  assert( pModule->xColumn );
  memset(&sContext, 0, sizeof(sContext));
  sContext.pOut = pDest;
  sContext.enc = encoding;
  testcase( (pOp->p5 & OPFLAG_NOCHNG)==0 && pOp->p5!=0 );
  assert( pOp->p5==OPFLAG_NOCHNG || pOp->p5==0 );
  if( pOp->p5 & OPFLAG_NOCHNG ){
    sqlite3VdbeMemSetNull(pDest);
    pDest->flags = MEM_Null|MEM_Zero;
    pDest->u.nZero = 0;
  }else{
    MemSetTypeFlag(pDest, MEM_Null);
  }
  rc = pModule->xColumn(pCur->uc.pVCur, &sContext, pOp->p2);
  sqlite3VtabImportErrmsg(p, pVtab);
  if( sContext.isError>0 ){
    sqlite3VdbeError(p, "%s", sqlite3_value_text(pDest));
    rc = sContext.isError;
  }
  sqlite3VdbeChangeEncoding(pDest, encoding);
  REGISTER_TRACE(pOp->p3, pDest);
  UPDATE_MAX_BLOBSIZE(pDest);

  if( sqlite3VdbeMemTooBig(pDest) ){
    goto too_big;
  }
  if( rc ) goto abort_due_to_error;
  break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */

#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VNext P1 P2 * * *
**
** Advance virtual table P1 to the next row in its result set and
** jump to instruction P2.  Or, if the virtual table has reached
** the end of its result set, then fall through to the next instruction.
*/
case OP_VNext: {   /* jump */
case OP_VNext: {   /* jump, ncycle */
  sqlite3_vtab *pVtab;
  const sqlite3_module *pModule;
  int res;
  VdbeCursor *pCur;

  res = 0;
  pCur = p->apCsr[pOp->p1];
  assert( pCur!=0 );
  assert( pCur->eCurType==CURTYPE_VTAB );
  if( pCur->nullRow ){
    break;
  }
  pVtab = pCur->uc.pVCur->pVtab;
  pModule = pVtab->pModule;
  assert( pModule->xNext );
7167
7168
7169
7170
7171
7172
7173
7174

7175
7176
7177
7178
7179
7180
7181
8321
8322
8323
8324
8325
8326
8327

8328
8329
8330
8331
8332
8333
8334
8335







-
+







** apply in the case of a constraint failure on an insert or update.
*/
case OP_VUpdate: {
  sqlite3_vtab *pVtab;
  const sqlite3_module *pModule;
  int nArg;
  int i;
  sqlite_int64 rowid;
  sqlite_int64 rowid = 0;
  Mem **apArg;
  Mem *pX;

  assert( pOp->p2==1        || pOp->p5==OE_Fail   || pOp->p5==OE_Rollback 
       || pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace
  );
  assert( p->readOnly==0 );
7256
7257
7258
7259
7260
7261
7262
7263
7264


7265
7266
7267
7268
7269






7270
7271
7272
7273
7274
7275
7276
7277
7278

7279
7280
7281


7282
7283
7284
7285




7286
7287
7288
7289
7290
7291
7292
7293
7294
7295
7296
7297
7298





7299
7300


7301
7302

7303
7304
7305
7306
7307
7308
7309
7310
7311
7312
7313
7314
7315
7316
7317
7318
7319
7320
7321
7322
7323
7324
7325
7326
7327
7328
7329
7330
7331
7332
7333
7334
7335
7336
7337
7338
7339
7340
7341
7342

7343

7344
7345

7346
7347
7348
7349
7350
7351
7352
8410
8411
8412
8413
8414
8415
8416


8417
8418
8419




8420
8421
8422
8423
8424
8425
8426
8427
8428
8429
8430
8431
8432
8433

8434
8435


8436
8437
8438
8439


8440
8441
8442
8443
8444
8445
8446
8447
8448
8449
8450
8451
8452




8453
8454
8455
8456
8457


8458
8459
8460

8461
8462

























8463
8464
8465
8466
8467
8468
8469
8470
8471
8472
8473
8474
8475
8476
8477
8478
8479
8480
8481
8482
8483
8484
8485
8486
8487
8488
8489







-
-
+
+

-
-
-
-
+
+
+
+
+
+








-
+

-
-
+
+


-
-
+
+
+
+









-
-
-
-
+
+
+
+
+
-
-
+
+

-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-














+

+


+







    if( newMax < (unsigned)pOp->p3 ) newMax = (unsigned)pOp->p3;
  }
  pOut->u.i = sqlite3BtreeMaxPageCount(pBt, newMax);
  break;
}
#endif

/* Opcode: Function0 P1 P2 P3 P4 P5
** Synopsis: r[P3]=func(r[P2@P5])
/* Opcode: Function P1 P2 P3 P4 *
** Synopsis: r[P3]=func(r[P2@NP])
**
** Invoke a user function (P4 is a pointer to a FuncDef object that
** defines the function) with P5 arguments taken from register P2 and
** successors.  The result of the function is stored in register P3.
** Register P3 must not be one of the function inputs.
** Invoke a user function (P4 is a pointer to an sqlite3_context object that
** contains a pointer to the function to be run) with arguments taken
** from register P2 and successors.  The number of arguments is in
** the sqlite3_context object that P4 points to.
** The result of the function is stored
** in register P3.  Register P3 must not be one of the function inputs.
**
** P1 is a 32-bit bitmask indicating whether or not each argument to the 
** function was determined to be constant at compile time. If the first
** argument was constant then bit 0 of P1 is set. This is used to determine
** whether meta data associated with a user function argument using the
** sqlite3_set_auxdata() API may be safely retained until the next
** invocation of this opcode.
**
** See also: Function, AggStep, AggFinal
** See also: AggStep, AggFinal, PureFunc
*/
/* Opcode: Function P1 P2 P3 P4 P5
** Synopsis: r[P3]=func(r[P2@P5])
/* Opcode: PureFunc P1 P2 P3 P4 *
** Synopsis: r[P3]=func(r[P2@NP])
**
** Invoke a user function (P4 is a pointer to an sqlite3_context object that
** contains a pointer to the function to be run) with P5 arguments taken
** from register P2 and successors.  The result of the function is stored
** contains a pointer to the function to be run) with arguments taken
** from register P2 and successors.  The number of arguments is in
** the sqlite3_context object that P4 points to.
** The result of the function is stored
** in register P3.  Register P3 must not be one of the function inputs.
**
** P1 is a 32-bit bitmask indicating whether or not each argument to the 
** function was determined to be constant at compile time. If the first
** argument was constant then bit 0 of P1 is set. This is used to determine
** whether meta data associated with a user function argument using the
** sqlite3_set_auxdata() API may be safely retained until the next
** invocation of this opcode.
**
** SQL functions are initially coded as OP_Function0 with P4 pointing
** to a FuncDef object.  But on first evaluation, the P4 operand is
** automatically converted into an sqlite3_context object and the operation
** changed to this OP_Function opcode.  In this way, the initialization of
** This opcode works exactly like OP_Function.  The only difference is in
** its name.  This opcode is used in places where the function must be
** purely non-deterministic.  Some built-in date/time functions can be
** either determinitic of non-deterministic, depending on their arguments.
** When those function are used in a non-deterministic way, they will check
** the sqlite3_context object occurs only once, rather than once for each
** evaluation of the function.
** to see if they were called using OP_PureFunc instead of OP_Function, and
** if they were, they throw an error.
**
** See also: Function0, AggStep, AggFinal
** See also: AggStep, AggFinal, Function
*/
case OP_PureFunc0:              /* group */
case OP_Function0: {            /* group */
  int n;
  sqlite3_context *pCtx;

  assert( pOp->p4type==P4_FUNCDEF );
  n = pOp->p5;
  assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
  assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem+1 - p->nCursor)+1) );
  assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n );
  pCtx = sqlite3DbMallocRawNN(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*));
  if( pCtx==0 ) goto no_mem;
  pCtx->pOut = 0;
  pCtx->pFunc = pOp->p4.pFunc;
  pCtx->iOp = (int)(pOp - aOp);
  pCtx->pVdbe = p;
  pCtx->isError = 0;
  pCtx->argc = n;
  pOp->p4type = P4_FUNCCTX;
  pOp->p4.pCtx = pCtx;
  assert( OP_PureFunc == OP_PureFunc0+2 );
  assert( OP_Function == OP_Function0+2 );
  pOp->opcode += 2;
  /* Fall through into OP_Function */
}
case OP_PureFunc:              /* group */
case OP_Function: {            /* group */
  int i;
  sqlite3_context *pCtx;

  assert( pOp->p4type==P4_FUNCCTX );
  pCtx = pOp->p4.pCtx;

  /* If this function is inside of a trigger, the register array in aMem[]
  ** might change from one evaluation to the next.  The next block of code
  ** checks to see if the register array has changed, and if so it
  ** reinitializes the relavant parts of the sqlite3_context object */
  pOut = &aMem[pOp->p3];
  if( pCtx->pOut != pOut ){
    pCtx->pVdbe = p;
    pCtx->pOut = pOut;
    pCtx->enc = encoding;
    for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i];
  }
  assert( pCtx->pVdbe==p );

  memAboutToChange(p, pOut);
#ifdef SQLITE_DEBUG
  for(i=0; i<pCtx->argc; i++){
    assert( memIsValid(pCtx->argv[i]) );
    REGISTER_TRACE(pOp->p2+i, pCtx->argv[i]);
  }
7362
7363
7364
7365
7366
7367
7368
7369
7370
7371
7372
7373





7374
7375
7376
7377
7378


















































































7379
7380
7381
7382
7383
7384
7385
8499
8500
8501
8502
8503
8504
8505





8506
8507
8508
8509
8510

8511
8512
8513
8514
8515
8516
8517
8518
8519
8520
8521
8522
8523
8524
8525
8526
8527
8528
8529
8530
8531
8532
8533
8534
8535
8536
8537
8538
8539
8540
8541
8542
8543
8544
8545
8546
8547
8548
8549
8550
8551
8552
8553
8554
8555
8556
8557
8558
8559
8560
8561
8562
8563
8564
8565
8566
8567
8568
8569
8570
8571
8572
8573
8574
8575
8576
8577
8578
8579
8580
8581
8582
8583
8584
8585
8586
8587
8588
8589
8590
8591
8592
8593
8594
8595
8596
8597
8598
8599
8600
8601
8602
8603







-
-
-
-
-
+
+
+
+
+
-




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







      rc = pCtx->isError;
    }
    sqlite3VdbeDeleteAuxData(db, &p->pAuxData, pCtx->iOp, pOp->p1);
    pCtx->isError = 0;
    if( rc ) goto abort_due_to_error;
  }

  /* Copy the result of the function into register P3 */
  if( pOut->flags & (MEM_Str|MEM_Blob) ){
    sqlite3VdbeChangeEncoding(pOut, encoding);
    if( sqlite3VdbeMemTooBig(pOut) ) goto too_big;
  }
  assert( (pOut->flags&MEM_Str)==0 
       || pOut->enc==encoding
       || db->mallocFailed );
  assert( !sqlite3VdbeMemTooBig(pOut) );


  REGISTER_TRACE(pOp->p3, pOut);
  UPDATE_MAX_BLOBSIZE(pOut);
  break;
}

/* Opcode: ClrSubtype P1 * * * *
** Synopsis:  r[P1].subtype = 0
**
** Clear the subtype from register P1.
*/
case OP_ClrSubtype: {   /* in1 */
  pIn1 = &aMem[pOp->p1];
  pIn1->flags &= ~MEM_Subtype;
  break;
}

/* Opcode: FilterAdd P1 * P3 P4 *
** Synopsis: filter(P1) += key(P3@P4)
**
** Compute a hash on the P4 registers starting with r[P3] and
** add that hash to the bloom filter contained in r[P1].
*/
case OP_FilterAdd: {
  u64 h;

  assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) );
  pIn1 = &aMem[pOp->p1];
  assert( pIn1->flags & MEM_Blob );
  assert( pIn1->n>0 );
  h = filterHash(aMem, pOp);
#ifdef SQLITE_DEBUG
  if( db->flags&SQLITE_VdbeTrace ){
    int ii;
    for(ii=pOp->p3; ii<pOp->p3+pOp->p4.i; ii++){
      registerTrace(ii, &aMem[ii]);
    }
    printf("hash: %llu modulo %d -> %u\n", h, pIn1->n, (int)(h%pIn1->n));
  }
#endif
  h %= pIn1->n;
  pIn1->z[h/8] |= 1<<(h&7);
  break;
}

/* Opcode: Filter P1 P2 P3 P4 *
** Synopsis: if key(P3@P4) not in filter(P1) goto P2
**
** Compute a hash on the key contained in the P4 registers starting
** with r[P3].  Check to see if that hash is found in the
** bloom filter hosted by register P1.  If it is not present then
** maybe jump to P2.  Otherwise fall through.
**
** False negatives are harmless.  It is always safe to fall through,
** even if the value is in the bloom filter.  A false negative causes
** more CPU cycles to be used, but it should still yield the correct
** answer.  However, an incorrect answer may well arise from a
** false positive - if the jump is taken when it should fall through.
*/
case OP_Filter: {          /* jump */
  u64 h;

  assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) );
  pIn1 = &aMem[pOp->p1];
  assert( (pIn1->flags & MEM_Blob)!=0 );
  assert( pIn1->n >= 1 );
  h = filterHash(aMem, pOp);
#ifdef SQLITE_DEBUG
  if( db->flags&SQLITE_VdbeTrace ){
    int ii;
    for(ii=pOp->p3; ii<pOp->p3+pOp->p4.i; ii++){
      registerTrace(ii, &aMem[ii]);
    }
    printf("hash: %llu modulo %d -> %u\n", h, pIn1->n, (int)(h%pIn1->n));
  }
#endif
  h %= pIn1->n;
  if( (pIn1->z[h/8] & (1<<(h&7)))==0 ){
    VdbeBranchTaken(1, 2);
    p->aCounter[SQLITE_STMTSTATUS_FILTER_HIT]++;
    goto jump_to_p2;
  }else{
    p->aCounter[SQLITE_STMTSTATUS_FILTER_MISS]++;
    VdbeBranchTaken(0, 2);
  }
  break;
}

/* Opcode: Trace P1 P2 * P4 *
**
** Write P4 on the statement trace output if statement tracing is
** enabled.
**
** Operand P1 must be 0x7fffffff and P2 must positive.
7421
7422
7423
7424
7425
7426
7427
7428

7429
7430
7431
7432
7433
7434
7435

7436
7437
7438
7439
7440
7441

7442
7443
7444

7445
7446
7447
7448
7449
7450
7451
8639
8640
8641
8642
8643
8644
8645

8646
8647
8648
8649
8650

8651

8652
8653
8654
8655
8656
8657

8658
8659
8660

8661
8662
8663
8664
8665
8666
8667
8668







-
+




-

-
+





-
+


-
+







  assert( pOp->p4.z==0 || strncmp(pOp->p4.z, "-" "- ", 3)==0 );

  /* OP_Init is always instruction 0 */
  assert( pOp==p->aOp || pOp->opcode==OP_Trace );

#ifndef SQLITE_OMIT_TRACE
  if( (db->mTrace & (SQLITE_TRACE_STMT|SQLITE_TRACE_LEGACY))!=0
   && !p->doingRerun
   && p->minWriteFileFormat!=254  /* tag-20220401a */
   && (zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
  ){
#ifndef SQLITE_OMIT_DEPRECATED
    if( db->mTrace & SQLITE_TRACE_LEGACY ){
      void (*x)(void*,const char*) = (void(*)(void*,const char*))db->xTrace;
      char *z = sqlite3VdbeExpandSql(p, zTrace);
      x(db->pTraceArg, z);
      db->trace.xLegacy(db->pTraceArg, z);
      sqlite3_free(z);
    }else
#endif
    if( db->nVdbeExec>1 ){
      char *z = sqlite3MPrintf(db, "-- %s", zTrace);
      (void)db->xTrace(SQLITE_TRACE_STMT, db->pTraceArg, p, z);
      (void)db->trace.xV2(SQLITE_TRACE_STMT, db->pTraceArg, p, z);
      sqlite3DbFree(db, z);
    }else{
      (void)db->xTrace(SQLITE_TRACE_STMT, db->pTraceArg, p, zTrace);
      (void)db->trace.xV2(SQLITE_TRACE_STMT, db->pTraceArg, p, zTrace);
    }
  }
#ifdef SQLITE_USE_FCNTL_TRACE
  zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql);
  if( zTrace ){
    int j;
    for(j=0; j<db->nDb; j++){
7509
7510
7511
7512
7513
7514
7515

















































7516
7517
7518
7519
7520
7521
7522
8726
8727
8728
8729
8730
8731
8732
8733
8734
8735
8736
8737
8738
8739
8740
8741
8742
8743
8744
8745
8746
8747
8748
8749
8750
8751
8752
8753
8754
8755
8756
8757
8758
8759
8760
8761
8762
8763
8764
8765
8766
8767
8768
8769
8770
8771
8772
8773
8774
8775
8776
8777
8778
8779
8780
8781
8782
8783
8784
8785
8786
8787
8788







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







** an active statement journal.
*/
case OP_Abortable: {
  sqlite3VdbeAssertAbortable(p);
  break;
}
#endif

#ifdef SQLITE_DEBUG
/* Opcode:  ReleaseReg   P1 P2 P3 * P5
** Synopsis: release r[P1@P2] mask P3
**
** Release registers from service.  Any content that was in the
** the registers is unreliable after this opcode completes.
**
** The registers released will be the P2 registers starting at P1,
** except if bit ii of P3 set, then do not release register P1+ii.
** In other words, P3 is a mask of registers to preserve.
**
** Releasing a register clears the Mem.pScopyFrom pointer.  That means
** that if the content of the released register was set using OP_SCopy,
** a change to the value of the source register for the OP_SCopy will no longer
** generate an assertion fault in sqlite3VdbeMemAboutToChange().
**
** If P5 is set, then all released registers have their type set
** to MEM_Undefined so that any subsequent attempt to read the released
** register (before it is reinitialized) will generate an assertion fault.
**
** P5 ought to be set on every call to this opcode.
** However, there are places in the code generator will release registers
** before their are used, under the (valid) assumption that the registers
** will not be reallocated for some other purpose before they are used and
** hence are safe to release.
**
** This opcode is only available in testing and debugging builds.  It is
** not generated for release builds.  The purpose of this opcode is to help
** validate the generated bytecode.  This opcode does not actually contribute
** to computing an answer.
*/
case OP_ReleaseReg: {
  Mem *pMem;
  int i;
  u32 constMask;
  assert( pOp->p1>0 );
  assert( pOp->p1+pOp->p2<=(p->nMem+1 - p->nCursor)+1 );
  pMem = &aMem[pOp->p1];
  constMask = pOp->p3;
  for(i=0; i<pOp->p2; i++, pMem++){
    if( i>=32 || (constMask & MASKBIT32(i))==0 ){
      pMem->pScopyFrom = 0;
      if( i<32 && pOp->p5 ) MemSetTypeFlag(pMem, MEM_Undefined);
    }
  }
  break;
}
#endif

/* Opcode: Noop * * * * *
**
** Do nothing.  This instruction is often useful as a jump
** destination.
*/
/*
7535
7536
7537
7538
7539
7540
7541
7542

7543
7544
7545
7546




7547

7548
7549
7550
7551
7552
7553
7554
7555
7556
7557
7558
7559
7560
7561
7562
7563
7564
7565
7566
7567






7568
7569
7570
7571
7572
7573
7574
7575
7576
7577





7578












7579
7580
7581
7582
7583
7584
7585
7586
7587

7588



7589
7590
7591
7592
7593
7594
7595
7596
7597











7598











7599

7600


7601
7602
7603
7604
7605
7606
7607
8801
8802
8803
8804
8805
8806
8807

8808




8809
8810
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
8836
8837
8838
8839
8840
8841
8842
8843
8844
8845
8846
8847
8848

8849
8850
8851
8852
8853
8854
8855
8856
8857
8858
8859
8860
8861
8862
8863
8864
8865
8866
8867
8868
8869
8870
8871
8872
8873
8874

8875
8876
8877
8878
8879
8880
8881
8882
8883
8884
8885
8886
8887
8888
8889
8890
8891
8892
8893
8894
8895
8896
8897
8898
8899

8900
8901
8902
8903
8904
8905
8906
8907
8908
8909
8910
8911
8912

8913
8914
8915
8916
8917
8918
8919
8920
8921







-
+
-
-
-
-
+
+
+
+
-
+




















+
+
+
+
+
+









-
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+








-
+

+
+
+









+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+

+
-
+
+







** The cases of the switch statement above this line should all be indented
** by 6 spaces.  But the left-most 6 spaces have been removed to improve the
** readability.  From this point on down, the normal indentation rules are
** restored.
*****************************************************************************/
    }

#ifdef VDBE_PROFILE
#if defined(VDBE_PROFILE)
    {
      u64 endTime = sqlite3NProfileCnt ? sqlite3NProfileCnt : sqlite3Hwtime();
      if( endTime>start ) pOrigOp->cycles += endTime - start;
      pOrigOp->cnt++;
    *pnCycle += sqlite3NProfileCnt ? sqlite3NProfileCnt : sqlite3Hwtime();
    pnCycle = 0;
#elif defined(SQLITE_ENABLE_STMT_SCANSTATUS)
    *pnCycle += sqlite3Hwtime();
    }
    pnCycle = 0;
#endif

    /* The following code adds nothing to the actual functionality
    ** of the program.  It is only here for testing and debugging.
    ** On the other hand, it does burn CPU cycles every time through
    ** the evaluator loop.  So we can leave it out when NDEBUG is defined.
    */
#ifndef NDEBUG
    assert( pOp>=&aOp[-1] && pOp<&aOp[p->nOp-1] );

#ifdef SQLITE_DEBUG
    if( db->flags & SQLITE_VdbeTrace ){
      u8 opProperty = sqlite3OpcodeProperty[pOrigOp->opcode];
      if( rc!=0 ) printf("rc=%d\n",rc);
      if( opProperty & (OPFLG_OUT2) ){
        registerTrace(pOrigOp->p2, &aMem[pOrigOp->p2]);
      }
      if( opProperty & OPFLG_OUT3 ){
        registerTrace(pOrigOp->p3, &aMem[pOrigOp->p3]);
      }
      if( opProperty==0xff ){
        /* Never happens.  This code exists to avoid a harmless linkage
        ** warning aboud sqlite3VdbeRegisterDump() being defined but not
        ** used. */
        sqlite3VdbeRegisterDump(p);
      }
    }
#endif  /* SQLITE_DEBUG */
#endif  /* NDEBUG */
  }  /* The end of the for(;;) loop the loops through opcodes */

  /* If we reach this point, it means that execution is finished with
  ** an error of some kind.
  */
abort_due_to_error:
  if( db->mallocFailed ) rc = SQLITE_NOMEM_BKPT;
  if( db->mallocFailed ){
    rc = SQLITE_NOMEM_BKPT;
  }else if( rc==SQLITE_IOERR_CORRUPTFS ){
    rc = SQLITE_CORRUPT_BKPT;
  }
  assert( rc );
#ifdef SQLITE_DEBUG
  if( db->flags & SQLITE_VdbeTrace ){
    const char *zTrace = p->zSql;
    if( zTrace==0 ){
      if( aOp[0].opcode==OP_Trace ){
        zTrace = aOp[0].p4.z;
      }
      if( zTrace==0 ) zTrace = "???";
    }
    printf("ABORT-due-to-error (rc=%d): %s\n", rc, zTrace);
  }
#endif
  if( p->zErrMsg==0 && rc!=SQLITE_IOERR_NOMEM ){
    sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc));
  }
  p->rc = rc;
  sqlite3SystemError(db, rc);
  testcase( sqlite3GlobalConfig.xLog!=0 );
  sqlite3_log(rc, "statement aborts at %d: [%s] %s", 
                   (int)(pOp - aOp), p->zSql, p->zErrMsg);
  sqlite3VdbeHalt(p);
  if( p->eVdbeState==VDBE_RUN_STATE ) sqlite3VdbeHalt(p);
  if( rc==SQLITE_IOERR_NOMEM ) sqlite3OomFault(db);
  if( rc==SQLITE_CORRUPT && db->autoCommit==0 ){
    db->flags |= SQLITE_CorruptRdOnly;
  }
  rc = SQLITE_ERROR;
  if( resetSchemaOnFault>0 ){
    sqlite3ResetOneSchema(db, resetSchemaOnFault-1);
  }

  /* This is the only way out of this procedure.  We have to
  ** release the mutexes on btrees that were acquired at the
  ** top. */
vdbe_return:
#if defined(VDBE_PROFILE)
  if( pnCycle ){
    *pnCycle += sqlite3NProfileCnt ? sqlite3NProfileCnt : sqlite3Hwtime();
    pnCycle = 0;
  }
#elif defined(SQLITE_ENABLE_STMT_SCANSTATUS)
  if( pnCycle ){
    *pnCycle += sqlite3Hwtime();
    pnCycle = 0;
  }
#endif
  testcase( nVmStep>0 );

#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  while( nVmStep>=nProgressLimit && db->xProgress!=0 ){
    nProgressLimit += db->nProgressOps;
    if( db->xProgress(db->pProgressArg) ){
      nProgressLimit = LARGEST_UINT64;
      rc = SQLITE_INTERRUPT;
      goto abort_due_to_error;
    }
  }
#endif
  p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep;
  if( DbMaskNonZero(p->lockMask) ){
  sqlite3VdbeLeave(p);
    sqlite3VdbeLeave(p);
  }
  assert( rc!=SQLITE_OK || nExtraDelete==0 
       || sqlite3_strlike("DELETE%",p->zSql,0)!=0 
  );
  return rc;

  /* Jump to here if a string or blob larger than SQLITE_MAX_LENGTH
  ** is encountered.
7619
7620
7621
7622
7623
7624
7625
7626
7627


7628
7629
7630
7631
8933
8934
8935
8936
8937
8938
8939


8940
8941


8942
8943







-
-
+
+
-
-


  rc = SQLITE_NOMEM_BKPT;
  goto abort_due_to_error;

  /* Jump to here if the sqlite3_interrupt() API sets the interrupt
  ** flag.
  */
abort_due_to_interrupt:
  assert( db->u1.isInterrupted );
  rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT;
  assert( AtomicLoad(&db->u1.isInterrupted) );
  rc = SQLITE_INTERRUPT;
  p->rc = rc;
  sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc));
  goto abort_due_to_error;
}

Changes to src/vdbe.h.

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
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







-
+





-




-
-
-
-



+
+
+
+







    double *pReal;         /* Used when p4type is P4_REAL */
    FuncDef *pFunc;        /* Used when p4type is P4_FUNCDEF */
    sqlite3_context *pCtx; /* Used when p4type is P4_FUNCCTX */
    CollSeq *pColl;        /* Used when p4type is P4_COLLSEQ */
    Mem *pMem;             /* Used when p4type is P4_MEM */
    VTable *pVtab;         /* Used when p4type is P4_VTAB */
    KeyInfo *pKeyInfo;     /* Used when p4type is P4_KEYINFO */
    int *ai;               /* Used when p4type is P4_INTARRAY */
    u32 *ai;               /* Used when p4type is P4_INTARRAY */
    SubProgram *pProgram;  /* Used when p4type is P4_SUBPROGRAM */
    Table *pTab;           /* Used when p4type is P4_TABLE */
#ifdef SQLITE_ENABLE_CURSOR_HINTS
    Expr *pExpr;           /* Used when p4type is P4_EXPR */
#endif
    int (*xAdvance)(BtCursor *, int);
  } p4;
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
  char *zComment;          /* Comment to improve readability */
#endif
#ifdef VDBE_PROFILE
  u32 cnt;                 /* Number of times this instruction was executed */
  u64 cycles;              /* Total time spent executing this instruction */
#endif
#ifdef SQLITE_VDBE_COVERAGE
  u32 iSrcLine;            /* Source-code line that generated this opcode
                           ** with flags in the upper 8 bits */
#endif
#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE)
  u64 nExec;
  u64 nCycle;
#endif
};
typedef struct VdbeOp VdbeOp;


/*
** A sub-routine used to implement a trigger program.
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
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







-
-
+

-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-







*/
#define P4_NOTUSED      0   /* The P4 parameter is not used */
#define P4_TRANSIENT    0   /* P4 is a pointer to a transient string */
#define P4_STATIC     (-1)  /* Pointer to a static string */
#define P4_COLLSEQ    (-2)  /* P4 is a pointer to a CollSeq structure */
#define P4_INT32      (-3)  /* P4 is a 32-bit signed integer */
#define P4_SUBPROGRAM (-4)  /* P4 is a pointer to a SubProgram structure */
#define P4_ADVANCE    (-5)  /* P4 is a pointer to BtreeNext() or BtreePrev() */
#define P4_TABLE      (-6)  /* P4 is a pointer to a Table structure */
#define P4_TABLE      (-5)  /* P4 is a pointer to a Table structure */
/* Above do not own any resources.  Must free those below */
#define P4_FREE_IF_LE (-7)
#define P4_DYNAMIC    (-7)  /* Pointer to memory from sqliteMalloc() */
#define P4_FUNCDEF    (-8)  /* P4 is a pointer to a FuncDef structure */
#define P4_KEYINFO    (-9)  /* P4 is a pointer to a KeyInfo structure */
#define P4_EXPR       (-10) /* P4 is a pointer to an Expr tree */
#define P4_MEM        (-11) /* P4 is a pointer to a Mem*    structure */
#define P4_VTAB       (-12) /* P4 is a pointer to an sqlite3_vtab structure */
#define P4_REAL       (-13) /* P4 is a 64-bit floating point value */
#define P4_INT64      (-14) /* P4 is a 64-bit signed integer */
#define P4_INTARRAY   (-15) /* P4 is a vector of 32-bit integers */
#define P4_FUNCCTX    (-16) /* P4 is a pointer to an sqlite3_context object */
#define P4_FREE_IF_LE (-6)
#define P4_DYNAMIC    (-6)  /* Pointer to memory from sqliteMalloc() */
#define P4_FUNCDEF    (-7)  /* P4 is a pointer to a FuncDef structure */
#define P4_KEYINFO    (-8)  /* P4 is a pointer to a KeyInfo structure */
#define P4_EXPR       (-9) /* P4 is a pointer to an Expr tree */
#define P4_MEM        (-10) /* P4 is a pointer to a Mem*    structure */
#define P4_VTAB       (-11) /* P4 is a pointer to an sqlite3_vtab structure */
#define P4_REAL       (-12) /* P4 is a 64-bit floating point value */
#define P4_INT64      (-13) /* P4 is a 64-bit signed integer */
#define P4_INTARRAY   (-14) /* P4 is a vector of 32-bit integers */
#define P4_FUNCCTX    (-15) /* P4 is a pointer to an sqlite3_context object */
#define P4_DYNBLOB    (-17) /* Pointer to memory from sqliteMalloc() */

/* Error message codes for OP_Halt */
#define P5_ConstraintNotNull 1
#define P5_ConstraintUnique  2
#define P5_ConstraintCheck   3
#define P5_ConstraintFK      4

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
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







-
-
+
+
-
-
+

-
+


















+










+










+


+



-
+



+
+
+
+
+




+


+

+
+
+
+
+
-
-
-
-
-
+
+
+
+
+

+

+


+
+
+
+
+





+
-
+



-







#   define COLNAME_N      1      /* Store only the name */
# else
#   define COLNAME_N      2      /* Store the name and decltype */
# endif
#endif

/*
** The following macro converts a relative address in the p2 field
** of a VdbeOp structure into a negative number so that 
** The following macro converts a label returned by sqlite3VdbeMakeLabel()
** into an index into the Parse.aLabel[] array that contains the resolved
** sqlite3VdbeAddOpList() knows that the address is relative.  Calling
** the macro again restores the address.
** address of that label.
*/
#define ADDR(X)  (-1-(X))
#define ADDR(X)  (~(X))

/*
** The makefile scans the vdbe.c source file and creates the "opcodes.h"
** header file that defines a number for each opcode used by the VDBE.
*/
#include "opcodes.h"

/*
** Additional non-public SQLITE_PREPARE_* flags
*/
#define SQLITE_PREPARE_SAVESQL  0x80  /* Preserve SQL text */
#define SQLITE_PREPARE_MASK     0x0f  /* Mask of public flags */

/*
** Prototypes for the VDBE interface.  See comments on the implementation
** for a description of what each of these routines does.
*/
Vdbe *sqlite3VdbeCreate(Parse*);
Parse *sqlite3VdbeParser(Vdbe*);
int sqlite3VdbeAddOp0(Vdbe*,int);
int sqlite3VdbeAddOp1(Vdbe*,int,int);
int sqlite3VdbeAddOp2(Vdbe*,int,int,int);
int sqlite3VdbeGoto(Vdbe*,int);
int sqlite3VdbeLoadString(Vdbe*,int,const char*);
void sqlite3VdbeMultiLoad(Vdbe*,int,const char*,...);
int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int);
int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int);
int sqlite3VdbeAddOp4Dup8(Vdbe*,int,int,int,int,const u8*,int);
int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int);
int sqlite3VdbeAddFunctionCall(Parse*,int,int,int,int,const FuncDef*,int);
void sqlite3VdbeEndCoroutine(Vdbe*,int);
#if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS)
  void sqlite3VdbeVerifyNoMallocRequired(Vdbe *p, int N);
  void sqlite3VdbeVerifyNoResultRow(Vdbe *p);
#else
# define sqlite3VdbeVerifyNoMallocRequired(A,B)
# define sqlite3VdbeVerifyNoResultRow(A)
#endif
#if defined(SQLITE_DEBUG)
  void sqlite3VdbeVerifyAbortable(Vdbe *p, int);
  void sqlite3VdbeNoJumpsOutsideSubrtn(Vdbe*,int,int,int);
#else
# define sqlite3VdbeVerifyAbortable(A,B)
# define sqlite3VdbeNoJumpsOutsideSubrtn(A,B,C,D)
#endif
VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp,int iLineno);
#ifndef SQLITE_OMIT_EXPLAIN
  void sqlite3VdbeExplain(Parse*,u8,const char*,...);
  int sqlite3VdbeExplain(Parse*,u8,const char*,...);
  void sqlite3VdbeExplainPop(Parse*);
  int sqlite3VdbeExplainParent(Parse*);
# define ExplainQueryPlan(P)        sqlite3VdbeExplain P
# ifdef SQLITE_ENABLE_STMT_SCANSTATUS
#  define ExplainQueryPlan2(V,P)     (V = sqlite3VdbeExplain P)
# else
#  define ExplainQueryPlan2(V,P)     ExplainQueryPlan(P)
# endif
# define ExplainQueryPlanPop(P)     sqlite3VdbeExplainPop(P)
# define ExplainQueryPlanParent(P)  sqlite3VdbeExplainParent(P)
#else
# define ExplainQueryPlan(P)
# define ExplainQueryPlan2(V,P)
# define ExplainQueryPlanPop(P)
# define ExplainQueryPlanParent(P) 0
# define sqlite3ExplainBreakpoint(A,B) /*no-op*/
#endif
#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_EXPLAIN)
  void sqlite3ExplainBreakpoint(const char*,const char*);
#else
# define sqlite3ExplainBreakpoint(A,B) /*no-op*/
#endif
void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
void sqlite3VdbeChangeOpcode(Vdbe*, u32 addr, u8);
void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1);
void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2);
void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3);
void sqlite3VdbeAddParseSchemaOp(Vdbe*, int, char*, u16);
void sqlite3VdbeChangeOpcode(Vdbe*, int addr, u8);
void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1);
void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2);
void sqlite3VdbeChangeP3(Vdbe*, int addr, int P3);
void sqlite3VdbeChangeP5(Vdbe*, u16 P5);
void sqlite3VdbeTypeofColumn(Vdbe*, int);
void sqlite3VdbeJumpHere(Vdbe*, int addr);
void sqlite3VdbeJumpHereOrPopInst(Vdbe*, int addr);
int sqlite3VdbeChangeToNoop(Vdbe*, int addr);
int sqlite3VdbeDeletePriorOpcode(Vdbe*, u8 op);
#ifdef SQLITE_DEBUG
  void sqlite3VdbeReleaseRegisters(Parse*,int addr, int n, u32 mask, int);
#else
# define sqlite3VdbeReleaseRegisters(P,A,N,M,F)
#endif
void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
void sqlite3VdbeAppendP4(Vdbe*, void *pP4, int p4type);
void sqlite3VdbeSetP4KeyInfo(Parse*, Index*);
void sqlite3VdbeUsesBtree(Vdbe*, int);
VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
VdbeOp *sqlite3VdbeGetLastOp(Vdbe*);
int sqlite3VdbeMakeLabel(Vdbe*);
int sqlite3VdbeMakeLabel(Parse*);
void sqlite3VdbeRunOnlyOnce(Vdbe*);
void sqlite3VdbeReusable(Vdbe*);
void sqlite3VdbeDelete(Vdbe*);
void sqlite3VdbeClearObject(sqlite3*,Vdbe*);
void sqlite3VdbeMakeReady(Vdbe*,Parse*);
int sqlite3VdbeFinalize(Vdbe*);
void sqlite3VdbeResolveLabel(Vdbe*, int);
int sqlite3VdbeCurrentAddr(Vdbe*);
#ifdef SQLITE_DEBUG
  int sqlite3VdbeAssertMayAbort(Vdbe *, int);
#endif
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







-

-
+


+
+
+







int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
int sqlite3VdbeRecordCompareWithSkip(int, const void *, UnpackedRecord *, int);
UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo*);

typedef int (*RecordCompare)(int,const void*,UnpackedRecord*);
RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*);

#ifndef SQLITE_OMIT_TRIGGER
void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
#endif
int sqlite3VdbeHasSubProgram(Vdbe*);

int sqlite3NotPureFunc(sqlite3_context*);
#ifdef SQLITE_ENABLE_BYTECODE_VTAB
int sqlite3VdbeBytecodeVtabInit(sqlite3*);
#endif

/* Use SQLITE_ENABLE_COMMENTS to enable generation of extra comments on
** each VDBE opcode.
**
** Use the SQLITE_ENABLE_MODULE_COMMENTS macro to see some extra no-op
** comments in VDBE programs that show key decision points in the code
** generator.
366
367
368
369
370
371
372


373
374



375
376
377
378
379
380
381
387
388
389
390
391
392
393
394
395
396

397
398
399
400
401
402
403
404
405
406







+
+

-
+
+
+







# define VdbeCoverageNeverNullIf(v,x)
# define VdbeCoverageEqNe(v)
# define VDBE_OFFSET_LINENO(x) 0
#endif

#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
void sqlite3VdbeScanStatus(Vdbe*, int, int, int, LogEst, const char*);
void sqlite3VdbeScanStatusRange(Vdbe*, int, int, int);
void sqlite3VdbeScanStatusCounters(Vdbe*, int, int, int);
#else
# define sqlite3VdbeScanStatus(a,b,c,d,e)
# define sqlite3VdbeScanStatus(a,b,c,d,e,f)
# define sqlite3VdbeScanStatusRange(a,b,c,d)
# define sqlite3VdbeScanStatusCounters(a,b,c,d)
#endif

#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
void sqlite3VdbePrintOp(FILE*, int, VdbeOp*);
#endif

#endif /* SQLITE_VDBE_H */

Changes to src/vdbeInt.h.

27
28
29
30
31
32
33
34


35
36
37
38
39
40
41
27
28
29
30
31
32
33

34
35
36
37
38
39
40
41
42







-
+
+







#endif

/*
** VDBE_DISPLAY_P4 is true or false depending on whether or not the
** "explain" P4 display logic is enabled.
*/
#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \
     || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
     || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) \
     || defined(SQLITE_ENABLE_BYTECODE_VTAB)
# define VDBE_DISPLAY_P4 1
#else
# define VDBE_DISPLAY_P4 0
#endif

/*
** SQL is translated into a sequence of instructions to be
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
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







-
+










+
-
-
+
+
+
+
+

-







**      * A sorter
**      * A virtual table
**      * A one-row "pseudotable" stored in a single register
*/
typedef struct VdbeCursor VdbeCursor;
struct VdbeCursor {
  u8 eCurType;            /* One of the CURTYPE_* values above */
  i8 iDb;                 /* Index of cursor database in db->aDb[] (or -1) */
  i8 iDb;                 /* Index of cursor database in db->aDb[] */
  u8 nullRow;             /* True if pointing to a row with no data */
  u8 deferredMoveto;      /* A call to sqlite3BtreeMoveto() is needed */
  u8 isTable;             /* True for rowid tables.  False for indexes */
#ifdef SQLITE_DEBUG
  u8 seekOp;              /* Most recent seek operation on this cursor */
  u8 wrFlag;              /* The wrFlag argument to sqlite3BtreeCursor() */
#endif
  Bool isEphemeral:1;     /* True for an ephemeral table */
  Bool useRandomRowid:1;  /* Generate new record numbers semi-randomly */
  Bool isOrdered:1;       /* True if the table is not BTREE_UNORDERED */
  Bool noReuse:1;         /* OpenEphemeral may not reuse this cursor */
  Bool seekHit:1;         /* See the OP_SeekHit and OP_IfNoHope opcodes */
  Btree *pBtx;            /* Separate file holding temporary table */
  u16 seekHit;            /* See the OP_SeekHit and OP_IfNoHope opcodes */
  union {                 /* pBtx for isEphermeral.  pAltMap otherwise */
    Btree *pBtx;            /* Separate file holding temporary table */
    u32 *aAltMap;           /* Mapping from table to index column numbers */
  } ub;
  i64 seqCount;           /* Sequence counter */
  int *aAltMap;           /* Mapping from table to index column numbers */

  /* Cached OP_Column parse information is only valid if cacheStatus matches
  ** Vdbe.cacheCtr.  Vdbe.cacheCtr will never take on the value of
  ** CACHE_STALE (0) and so setting cacheStatus=CACHE_STALE guarantees that
  ** the cache is out of date. */
  u32 cacheStatus;        /* Cache is valid if this matches Vdbe.cacheCtr */
  int seekResult;         /* Result of previous sqlite3BtreeMoveto() or 0
126
127
128
129
130
131
132





133
134
135
136
137
138
139
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148







+
+
+
+
+








  /* 2*nField extra array elements allocated for aType[], beyond the one
  ** static element declared in the structure.  nField total array slots for
  ** aType[] and nField+1 array slots for aOffset[] */
  u32 aType[1];           /* Type values record decode.  MUST BE LAST */
};

/* Return true if P is a null-only cursor
*/
#define IsNullCursor(P) \
  ((P)->eCurType==CURTYPE_PSEUDO && (P)->nullRow && (P)->seekResult==0)


/*
** A value for VdbeCursor.cacheStatus that means the cache is always invalid.
*/
#define CACHE_STALE 0

/*
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
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







-















-
-
+
+







** set to NULL if the currently executing frame is the main program.
*/
typedef struct VdbeFrame VdbeFrame;
struct VdbeFrame {
  Vdbe *v;                /* VM this frame belongs to */
  VdbeFrame *pParent;     /* Parent of this frame, or NULL if parent is main */
  Op *aOp;                /* Program instructions for parent frame */
  i64 *anExec;            /* Event counters from parent frame */
  Mem *aMem;              /* Array of memory cells for parent frame */
  VdbeCursor **apCsr;     /* Array of Vdbe cursors for parent frame */
  u8 *aOnce;              /* Bitmask used by OP_Once */
  void *token;            /* Copy of SubProgram.token */
  i64 lastRowid;          /* Last insert rowid (sqlite3.lastRowid) */
  AuxData *pAuxData;      /* Linked list of auxdata allocations */
#if SQLITE_DEBUG
  u32 iFrameMagic;        /* magic number for sanity checking */
#endif
  int nCursor;            /* Number of entries in apCsr */
  int pc;                 /* Program Counter in parent (calling) frame */
  int nOp;                /* Size of aOp array */
  int nMem;               /* Number of entries in aMem */
  int nChildMem;          /* Number of memory cells for child frame */
  int nChildCsr;          /* Number of cursors for child frame */
  int nChange;            /* Statement changes (Vdbe.nChange)     */
  int nDbChange;          /* Value of db->nChange */
  i64 nChange;            /* Statement changes (Vdbe.nChange)     */
  i64 nDbChange;          /* Value of db->nChange */
};

/* Magic number for sanity checking on VdbeFrame objects */
#define SQLITE_FRAME_MAGIC 0x879fb71e

/*
** Return a pointer to the array of registers allocated for use
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
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







+
+



-
-

-
+


-
+











-
+

-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










+





+
-
-
-
-
+
+
+
+
+
+

+
+
+
-
+

-
+
-
-
-
-
+

-
-
-
-
-
+
+
+
+
-
-
-
-
-
-














+
+
+
+
+
+
+
-
+

+
+
+
+


-
+







  union MemValue {
    double r;           /* Real value used when MEM_Real is set in flags */
    i64 i;              /* Integer value used when MEM_Int is set in flags */
    int nZero;          /* Extra zero bytes when MEM_Zero and MEM_Blob set */
    const char *zPType; /* Pointer type when MEM_Term|MEM_Subtype|MEM_Null */
    FuncDef *pDef;      /* Used only when flags==MEM_Agg */
  } u;
  char *z;            /* String or BLOB value */
  int n;              /* Number of characters in string value, excluding '\0' */
  u16 flags;          /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
  u8  enc;            /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */
  u8  eSubtype;       /* Subtype for this value */
  int n;              /* Number of characters in string value, excluding '\0' */
  char *z;            /* String or BLOB value */
  /* ShallowCopy only needs to copy the information above */
  char *zMalloc;      /* Space to hold MEM_Str or MEM_Blob if szMalloc>0 */
  sqlite3 *db;        /* The associated database connection */
  int szMalloc;       /* Size of the zMalloc allocation */
  u32 uTemp;          /* Transient storage for serial_type in OP_MakeRecord */
  sqlite3 *db;        /* The associated database connection */
  char *zMalloc;      /* Space to hold MEM_Str or MEM_Blob if szMalloc>0 */
  void (*xDel)(void*);/* Destructor for Mem.z - only valid if MEM_Dyn */
#ifdef SQLITE_DEBUG
  Mem *pScopyFrom;    /* This Mem is a shallow copy of pScopyFrom */
  u16 mScopyFlags;    /* flags value immediately after the shallow copy */
#endif
};

/*
** Size of struct Mem not including the Mem.zMalloc member or anything that
** follows.
*/
#define MEMCELLSIZE offsetof(Mem,zMalloc)
#define MEMCELLSIZE offsetof(Mem,db)

/* One or more of the following flags are set to indicate the validOK
/* One or more of the following flags are set to indicate the
** representations of the value stored in the Mem struct.
**
**  *  MEM_Null                An SQL NULL value
**
**  *  MEM_Null|MEM_Zero       An SQL NULL with the virtual table
**                             UPDATE no-change flag set
**
**  *  MEM_Null|MEM_Term|      An SQL NULL, but also contains a
**        MEM_Subtype          pointer accessible using
**                             sqlite3_value_pointer().
**
**  *  MEM_Null|MEM_Cleared    Special SQL NULL that compares non-equal
**                             to other NULLs even using the IS operator.
**
**  *  MEM_Str                 A string, stored in Mem.z with
**                             length Mem.n.  Zero-terminated if
**                             MEM_Term is set.  This flag is
**                             incompatible with MEM_Blob and
**                             MEM_Null, but can appear with MEM_Int,
**                             MEM_Real, and MEM_IntReal.
**
**  *  MEM_Blob                A blob, stored in Mem.z length Mem.n.
**                             Incompatible with MEM_Str, MEM_Null,
**                             MEM_Int, MEM_Real, and MEM_IntReal.
**
**  *  MEM_Blob|MEM_Zero       A blob in Mem.z of length Mem.n plus
**                             MEM.u.i extra 0x00 bytes at the end.
**                                       
**  *  MEM_Int                 Integer stored in Mem.u.i.
**
**  *  MEM_Real                Real stored in Mem.u.r.
**
**  *  MEM_IntReal             Real stored as an integer in Mem.u.i.
**
** If the MEM_Null flag is set, then the value is an SQL NULL value.
** For a pointer type created using sqlite3_bind_pointer() or
** sqlite3_result_pointer() the MEM_Term and MEM_Subtype flags are also set.
**
** If the MEM_Str flag is set then Mem.z points at a string representation.
** Usually this is encoded in the same unicode encoding as the main
** database (see below for exceptions). If the MEM_Term flag is also
** set, then the string is nul terminated. The MEM_Int and MEM_Real 
** flags may coexist with the MEM_Str flag.
*/
#define MEM_Undefined 0x0000   /* Value is undefined */
#define MEM_Null      0x0001   /* Value is NULL (or a pointer) */
#define MEM_Str       0x0002   /* Value is a string */
#define MEM_Int       0x0004   /* Value is an integer */
#define MEM_Real      0x0008   /* Value is a real number */
#define MEM_Blob      0x0010   /* Value is a BLOB */
#define MEM_IntReal   0x0020   /* MEM_Int that stringifies like MEM_Real */
#define MEM_AffMask   0x001f   /* Mask of affinity bits */
/* Available          0x0020   */
/* Available          0x0040   */
#define MEM_Undefined 0x0080   /* Value is undefined */
#define MEM_AffMask   0x003f   /* Mask of affinity bits */

/* Extra bits that modify the meanings of the core datatypes above
*/
#define MEM_FromBind  0x0040   /* Value originates from sqlite3_bind() */
 /*                   0x0080   // Available */
#define MEM_Cleared   0x0100   /* NULL set by OP_Null, not from data */
#define MEM_Term      0x0200   /* String in Mem.z is zero terminated */
#define MEM_Zero      0x0400   /* Mem.i contains count of 0s appended to blob */
#define MEM_Subtype   0x0800   /* Mem.eSubtype is valid */
#define MEM_TypeMask  0xc1ff   /* Mask of type bits */
#define MEM_TypeMask  0x0dbf   /* Mask of type bits */


/* Bits that determine the storage for Mem.z for a string or blob or
/* Whenever Mem contains a valid string or blob representation, one of
** the following flags must be set to determine the memory management
** policy for Mem.z.  The MEM_Term flag tells us whether or not the
** string is \000 or \u0000 terminated
** aggregate accumulator.
*/
#define MEM_Term      0x0200   /* String in Mem.z is zero terminated */
#define MEM_Dyn       0x0400   /* Need to call Mem.xDel() on Mem.z */
#define MEM_Static    0x0800   /* Mem.z points to a static string */
#define MEM_Ephem     0x1000   /* Mem.z points to an ephemeral string */
#define MEM_Agg       0x2000   /* Mem.z points to an agg function context */
#define MEM_Dyn       0x1000   /* Need to call Mem.xDel() on Mem.z */
#define MEM_Static    0x2000   /* Mem.z points to a static string */
#define MEM_Ephem     0x4000   /* Mem.z points to an ephemeral string */
#define MEM_Agg       0x8000   /* Mem.z points to an agg function context */
#define MEM_Zero      0x4000   /* Mem.i contains count of 0s appended to blob */
#define MEM_Subtype   0x8000   /* Mem.eSubtype is valid */
#ifdef SQLITE_OMIT_INCRBLOB
  #undef MEM_Zero
  #define MEM_Zero 0x0000
#endif

/* Return TRUE if Mem X contains dynamically allocated content - anything
** that needs to be deallocated to avoid a leak.
*/
#define VdbeMemDynamic(X)  \
  (((X)->flags&(MEM_Agg|MEM_Dyn))!=0)

/*
** Clear any existing type flags from a Mem and replace them with f
*/
#define MemSetTypeFlag(p, f) \
   ((p)->flags = ((p)->flags&~(MEM_TypeMask|MEM_Zero))|f)

/*
** True if Mem X is a NULL-nochng type.
*/
#define MemNullNochng(X) \
  (((X)->flags&MEM_TypeMask)==(MEM_Null|MEM_Zero) \
    && (X)->n==0 && (X)->u.nZero==0)

/*
** Return true if a memory cell is not marked as invalid.  This macro
** Return true if a memory cell has been initialized and is valid.
** is for use inside assert() statements only.
**
** A Memory cell is initialized if at least one of the 
** MEM_Null, MEM_Str, MEM_Int, MEM_Real, MEM_Blob, or MEM_IntReal bits
** is set.  It is "undefined" if all those bits are zero.
*/
#ifdef SQLITE_DEBUG
#define memIsValid(M)  ((M)->flags & MEM_Undefined)==0
#define memIsValid(M)  ((M)->flags & MEM_AffMask)!=0
#endif

/*
** Each auxiliary data pointer stored by a user defined function 
** implementation calling sqlite3_set_auxdata() is stored in an instance
** of this structure. All such structures associated with a single VM
** are stored in a linked list headed at Vdbe.pAuxData. All are destroyed
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
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







+












+
+
+
+
+
+
+
+




+







struct sqlite3_context {
  Mem *pOut;              /* The return value is stored here */
  FuncDef *pFunc;         /* Pointer to function information */
  Mem *pMem;              /* Memory cell used to store aggregate context */
  Vdbe *pVdbe;            /* The VM that owns this context */
  int iOp;                /* Instruction number of OP_Function */
  int isError;            /* Error code returned by the function. */
  u8 enc;                 /* Encoding to use for results */
  u8 skipFlag;            /* Skip accumulator loading if true */
  u8 argc;                /* Number of arguments */
  sqlite3_value *argv[1]; /* Argument set */
};

/* A bitfield type for use inside of structures.  Always follow with :N where
** N is the number of bits.
*/
typedef unsigned bft;  /* Bit Field Type */

/* The ScanStatus object holds a single value for the
** sqlite3_stmt_scanstatus() interface.
**
** aAddrRange[]:
**   This array is used by ScanStatus elements associated with EQP 
**   notes that make an SQLITE_SCANSTAT_NCYCLE value available. It is
**   an array of up to 3 ranges of VM addresses for which the Vdbe.anCycle[]
**   values should be summed to calculate the NCYCLE value. Each pair of
**   integer addresses is a start and end address (both inclusive) for a range
**   instructions. A start value of 0 indicates an empty range.
*/
typedef struct ScanStatus ScanStatus;
struct ScanStatus {
  int addrExplain;                /* OP_Explain for loop */
  int aAddrRange[6];
  int addrLoop;                   /* Address of "loops" counter */
  int addrVisit;                  /* Address of "rows visited" counter */
  int iSelectID;                  /* The "Select-ID" for this loop */
  LogEst nEst;                    /* Estimated output rows per loop */
  char *zName;                    /* Name of table or index */
};

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
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
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







-
+


-





-
+





+
+
+
+





-
-
+
+

-
+

-
-




-








+


-

-





-
+













-






-
+

-
-
-
-
+
+
+
+
-














+







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





+

+
-
+



+
-
-
-
+
+
+
+
+
+






+
+
+
+
+
+
+
-
+









-
+









+

+
+
+






+
-
+






-
+

+

+




-
+












-
+
+











+
+







** state of the virtual machine.
**
** The "sqlite3_stmt" structure pointer that is returned by sqlite3_prepare()
** is really a pointer to an instance of this structure.
*/
struct Vdbe {
  sqlite3 *db;            /* The database connection that owns this statement */
  Vdbe *pPrev,*pNext;     /* Linked list of VDBEs with the same Vdbe.db */
  Vdbe **ppVPrev,*pVNext; /* Linked list of VDBEs with the same Vdbe.db */
  Parse *pParse;          /* Parsing context used to create this Vdbe */
  ynVar nVar;             /* Number of entries in aVar[] */
  u32 magic;              /* Magic number for sanity checking */
  int nMem;               /* Number of memory locations currently allocated */
  int nCursor;            /* Number of slots in apCsr[] */
  u32 cacheCtr;           /* VdbeCursor row cache generation counter */
  int pc;                 /* The program counter */
  int rc;                 /* Value to return */
  int nChange;            /* Number of db changes made since last reset */
  i64 nChange;            /* Number of db changes made since last reset */
  int iStatement;         /* Statement number (or 0 if has no opened stmt) */
  i64 iCurrentTime;       /* Value of julianday('now') for this statement */
  i64 nFkConstraint;      /* Number of imm. FK constraints this VM */
  i64 nStmtDefCons;       /* Number of def. constraints when stmt started */
  i64 nStmtDefImmCons;    /* Number of def. imm constraints when stmt started */
  Mem *aMem;              /* The memory locations */
  Mem **apArg;            /* Arguments to currently executing user function */
  VdbeCursor **apCsr;     /* One element of this array for each open cursor */
  Mem *aVar;              /* Values for the OP_Variable opcode. */

  /* When allocating a new Vdbe object, all of the fields below should be
  ** initialized to zero or NULL */

  Op *aOp;                /* Space to hold the virtual machine's program */
  Mem *aMem;              /* The memory locations */
  Mem **apArg;            /* Arguments to currently executing user function */
  int nOp;                /* Number of instructions in the program */
  int nOpAlloc;           /* Slots allocated for aOp[] */
  Mem *aColName;          /* Column names to return */
  Mem *pResultSet;        /* Pointer to an array of results */
  Mem *pResultRow;        /* Current output row */
  char *zErrMsg;          /* Error message written here */
  VdbeCursor **apCsr;     /* One element of this array for each open cursor */
  Mem *aVar;              /* Values for the OP_Variable opcode. */
  VList *pVList;          /* Name of variables */
#ifndef SQLITE_OMIT_TRACE
  i64 startTime;          /* Time when query started - used for profiling */
#endif
  int nOp;                /* Number of instructions in the program */
#ifdef SQLITE_DEBUG
  int rcApp;              /* errcode set by sqlite3_result_error_code() */
  u32 nWrite;             /* Number of write operations that have occurred */
#endif
  u16 nResColumn;         /* Number of columns in one row of the result set */
  u8 errorAction;         /* Recovery action to do in case of an error */
  u8 minWriteFileFormat;  /* Minimum file format for writable database files */
  u8 prepFlags;           /* SQLITE_PREPARE_* flags */
  u8 eVdbeState;          /* On of the VDBE_*_STATE values */
  bft expired:2;          /* 1: recompile VM immediately  2: when convenient */
  bft explain:2;          /* True if EXPLAIN present on SQL command */
  bft doingRerun:1;       /* True if rerunning after an auto-reprepare */
  bft changeCntOn:1;      /* True to update the change-counter */
  bft runOnlyOnce:1;      /* Automatically expire on reset */
  bft usesStmtJournal:1;  /* True if uses a statement journal */
  bft readOnly:1;         /* True for statements that do not write */
  bft bIsReader:1;        /* True for statements that read */
  yDbMask btreeMask;      /* Bitmask of db->aDb[] entries referenced */
  yDbMask lockMask;       /* Subset of btreeMask that requires a lock */
  u32 aCounter[7];        /* Counters used by sqlite3_stmt_status() */
  u32 aCounter[9];        /* Counters used by sqlite3_stmt_status() */
  char *zSql;             /* Text of the SQL statement that generated this */
#ifdef SQLITE_ENABLE_NORMALIZE
  char *zNormSql;         /* Normalization of the associated SQL statement */
  DblquoteStr *pDblStr;   /* List of double-quoted string literals */
#endif
  void *pFree;            /* Free this when deleting the vdbe */
  VdbeFrame *pFrame;      /* Parent frame */
  VdbeFrame *pDelFrame;   /* List of frame objects to free on VM reset */
  int nFrame;             /* Number of frames in pFrame list */
  u32 expmask;            /* Binding to these vars invalidates VM */
  SubProgram *pProgram;   /* Linked list of all sub-programs used by VM */
  AuxData *pAuxData;      /* Linked list of auxdata allocations */
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
  i64 *anExec;            /* Number of times each op has been executed */
  int nScan;              /* Entries in aScan[] */
  ScanStatus *aScan;      /* Scan definitions for sqlite3_stmt_scanstatus() */
#endif
};

/*
** The following are allowed values for Vdbe.magic
** The following are allowed values for Vdbe.eVdbeState
*/
#define VDBE_MAGIC_INIT     0x16bceaa5    /* Building a VDBE program */
#define VDBE_MAGIC_RUN      0x2df20da3    /* VDBE is ready to execute */
#define VDBE_MAGIC_HALT     0x319c2973    /* VDBE has completed execution */
#define VDBE_MAGIC_RESET    0x48fa9f76    /* Reset and ready to run again */
#define VDBE_INIT_STATE     0   /* Prepared statement under construction */
#define VDBE_READY_STATE    1   /* Ready to run but not yet started */
#define VDBE_RUN_STATE      2   /* Run in progress */
#define VDBE_HALT_STATE     3   /* Finished.  Need reset() or finalize() */
#define VDBE_MAGIC_DEAD     0x5606c3c8    /* The VDBE has been deallocated */

/*
** Structure used to store the context required by the 
** sqlite3_preupdate_*() API functions.
*/
struct PreUpdate {
  Vdbe *v;
  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 */
};

/*
** An instance of this object is used to pass an vector of values into
** OP_VFilter, the xFilter method of a virtual table.  The vector is the
** set of values on the right-hand side of an IN constraint.
**
** The value as passed into xFilter is an sqlite3_value with a "pointer"
** type, such as is generated by sqlite3_result_pointer() and read by
** sqlite3_value_pointer.  Such values have MEM_Term|MEM_Subtype|MEM_Null
** and a subtype of 'p'.  The sqlite3_vtab_in_first() and _next() interfaces
** know how to use this object to step through all the values in the
** right operand of the IN constraint.
*/
typedef struct ValueList ValueList;
struct ValueList {
  BtCursor *pCsr;          /* An ephemeral table holding all values */
  sqlite3_value *pOut;     /* Register to hold each decoded output value */
};

/* Size of content associated with serial types that fit into a
** single-byte varint.
*/
#ifndef SQLITE_AMALGAMATION
extern const u8 sqlite3SmallTypeSizes[];
#endif

/*
** Function prototypes
*/
void sqlite3VdbeError(Vdbe*, const char *, ...);
void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*);
void sqlite3VdbeFreeCursorNN(Vdbe*,VdbeCursor*);
void sqliteVdbePopStack(Vdbe*,int);
int SQLITE_NOINLINE sqlite3VdbeHandleMovedCursor(VdbeCursor *p);
int sqlite3VdbeCursorMoveto(VdbeCursor**, int*);
int SQLITE_NOINLINE sqlite3VdbeFinishMoveto(VdbeCursor*);
int sqlite3VdbeCursorRestore(VdbeCursor*);
u32 sqlite3VdbeSerialTypeLen(u32);
u8 sqlite3VdbeOneByteSerialTypeLen(u8);
#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
u32 sqlite3VdbeSerialType(Mem*, int, u32*);
u32 sqlite3VdbeSerialPut(unsigned char*, Mem*, u32);
u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
  u64 sqlite3FloatSwap(u64 in);
# define swapMixedEndianFloat(X)  X = sqlite3FloatSwap(X)
#else
# define swapMixedEndianFloat(X)
#endif
void sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
void sqlite3VdbeDeleteAuxData(sqlite3*, AuxData**, int, int);

int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
int sqlite3VdbeIdxKeyCompare(sqlite3*,VdbeCursor*,UnpackedRecord*,int*);
int sqlite3VdbeIdxRowid(sqlite3*, BtCursor*, i64*);
int sqlite3VdbeExec(Vdbe*);
#if !defined(SQLITE_OMIT_EXPLAIN) || defined(SQLITE_ENABLE_BYTECODE_VTAB)
int sqlite3VdbeNextOpcode(Vdbe*,Mem*,int,int*,int*,Op**);
char *sqlite3VdbeDisplayP4(sqlite3*,Op*);
#endif
#if defined(SQLITE_ENABLE_EXPLAIN_COMMENTS)
char *sqlite3VdbeDisplayComment(sqlite3*,const Op*,const char*);
#endif
#ifndef SQLITE_OMIT_EXPLAIN
#if !defined(SQLITE_OMIT_EXPLAIN)
int sqlite3VdbeList(Vdbe*);
#endif
int sqlite3VdbeHalt(Vdbe*);
int sqlite3VdbeChangeEncoding(Mem *, int);
int sqlite3VdbeMemTooBig(Mem*);
int sqlite3VdbeMemCopy(Mem*, const Mem*);
void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int);
void sqlite3VdbeMemMove(Mem*, Mem*);
int sqlite3VdbeMemNulTerminate(Mem*);
int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*));
int sqlite3VdbeMemSetStr(Mem*, const char*, i64, u8, void(*)(void*));
void sqlite3VdbeMemSetInt64(Mem*, i64);
#ifdef SQLITE_OMIT_FLOATING_POINT
# define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64
#else
  void sqlite3VdbeMemSetDouble(Mem*, double);
#endif
void sqlite3VdbeMemSetPointer(Mem*, void*, const char*, void(*)(void*));
void sqlite3VdbeMemInit(Mem*,sqlite3*,u16);
void sqlite3VdbeMemSetNull(Mem*);
#ifndef SQLITE_OMIT_INCRBLOB
void sqlite3VdbeMemSetZeroBlob(Mem*,int);
#else
int sqlite3VdbeMemSetZeroBlob(Mem*,int);
#endif
#ifdef SQLITE_DEBUG
int sqlite3VdbeMemIsRowSet(const Mem*);
#endif
int sqlite3VdbeMemSetRowSet(Mem*);
int sqlite3VdbeMemMakeWriteable(Mem*);
int sqlite3VdbeMemStringify(Mem*, u8, u8);
int sqlite3IntFloatCompare(i64,double);
i64 sqlite3VdbeIntValue(Mem*);
i64 sqlite3VdbeIntValue(const Mem*);
int sqlite3VdbeMemIntegerify(Mem*);
double sqlite3VdbeRealValue(Mem*);
int sqlite3VdbeBooleanValue(Mem*, int ifNull);
void sqlite3VdbeIntegerAffinity(Mem*);
int sqlite3VdbeMemRealify(Mem*);
int sqlite3VdbeMemNumerify(Mem*);
void sqlite3VdbeMemCast(Mem*,u8,u8);
int sqlite3VdbeMemCast(Mem*,u8,u8);
int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,Mem*);
int sqlite3VdbeMemFromBtreeZeroOffset(BtCursor*,u32,Mem*);
void sqlite3VdbeMemRelease(Mem *p);
void sqlite3VdbeMemReleaseMalloc(Mem*p);
int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
#ifndef SQLITE_OMIT_WINDOWFUNC
int sqlite3VdbeMemAggValue(Mem*, Mem*, FuncDef*);
#endif
#ifndef SQLITE_OMIT_EXPLAIN
#if !defined(SQLITE_OMIT_EXPLAIN) || defined(SQLITE_ENABLE_BYTECODE_VTAB)
const char *sqlite3OpcodeName(int);
#endif
int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
int sqlite3VdbeMemClearAndResize(Mem *pMem, int n);
int sqlite3VdbeCloseStatement(Vdbe *, int);
#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 *);
int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *);
int sqlite3VdbeSorterRewind(const VdbeCursor *, int *);
int sqlite3VdbeSorterWrite(const VdbeCursor *, Mem *);
int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *);

void sqlite3VdbeValueListFree(void*);

#ifdef SQLITE_DEBUG
  void sqlite3VdbeIncrWriteCounter(Vdbe*, VdbeCursor*);
  void sqlite3VdbeAssertAbortable(Vdbe*);
#else
# define sqlite3VdbeIncrWriteCounter(V,C)
# define sqlite3VdbeAssertAbortable(V)
584
585
586
587
588
589
590
591

592
593
594
595
596
597
598
688
689
690
691
692
693
694

695
696
697
698
699
700
701
702







-
+







int sqlite3VdbeCheckFk(Vdbe *, int);
#else
# define sqlite3VdbeCheckFk(p,i) 0
#endif

#ifdef SQLITE_DEBUG
  void sqlite3VdbePrintSql(Vdbe*);
  void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf);
  void sqlite3VdbeMemPrettyPrint(Mem *pMem, StrAccum *pStr);
#endif
#ifndef SQLITE_OMIT_UTF16
  int sqlite3VdbeMemTranslate(Mem*, u8);
  int sqlite3VdbeMemHandleBom(Mem *pMem);
#endif

#ifndef SQLITE_OMIT_INCRBLOB

Changes to src/vdbeapi.c.

11
12
13
14
15
16
17

18
19
20
21
22
23
24
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25







+







*************************************************************************
**
** This file contains code use to implement APIs that are part of the
** VDBE.
*/
#include "sqliteInt.h"
#include "vdbeInt.h"
#include "opcodes.h"

#ifndef SQLITE_OMIT_DEPRECATED
/*
** Return TRUE (non-zero) of the statement supplied as an argument needs
** to be recompiled.  A statement needs to be recompiled whenever the
** execution environment changes in a way that would alter the program
** that sqlite3_prepare() generates.  For example, if new functions or
63
64
65
66
67
68
69
70

71
72
73
74
75
76

77
78
79
80
81
82
83
64
65
66
67
68
69
70

71
72
73
74
75
76

77
78
79
80
81
82
83
84







-
+





-
+







  sqlite3_int64 iElapse;
  assert( p->startTime>0 );
  assert( (db->mTrace & (SQLITE_TRACE_PROFILE|SQLITE_TRACE_XPROFILE))!=0 );
  assert( db->init.busy==0 );
  assert( p->zSql!=0 );
  sqlite3OsCurrentTimeInt64(db->pVfs, &iNow);
  iElapse = (iNow - p->startTime)*1000000;
#ifndef SQLITE_OMIT_DEPRECATED  	
#ifndef SQLITE_OMIT_DEPRECATED
  if( db->xProfile ){
    db->xProfile(db->pProfileArg, p->zSql, iElapse);
  }
#endif
  if( db->mTrace & SQLITE_TRACE_PROFILE ){
    db->xTrace(SQLITE_TRACE_PROFILE, db->pTraceArg, p, (void*)&iElapse);
    db->trace.xV2(SQLITE_TRACE_PROFILE, db->pTraceArg, p, (void*)&iElapse);
  }
  p->startTime = 0;
}
/*
** The checkProfileCallback(DB,P) macro checks to see if a profile callback
** is needed, and it invokes the callback if it is needed.
*/
104
105
106
107
108
109
110

111


112
113
114
115
116
117
118
105
106
107
108
109
110
111
112

113
114
115
116
117
118
119
120
121







+
-
+
+







    rc = SQLITE_OK;
  }else{
    Vdbe *v = (Vdbe*)pStmt;
    sqlite3 *db = v->db;
    if( vdbeSafety(v) ) return SQLITE_MISUSE_BKPT;
    sqlite3_mutex_enter(db->mutex);
    checkProfileCallback(db, v);
    assert( v->eVdbeState>=VDBE_READY_STATE );
    rc = sqlite3VdbeFinalize(v);
    rc = sqlite3VdbeReset(v);
    sqlite3VdbeDelete(v);
    rc = sqlite3ApiExit(db, rc);
    sqlite3LeaveMutexAndCloseZombie(db);
  }
  return rc;
}

/*
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
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







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+






+
+
+
+
+



















+
+
+

















-
-
+
+











+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
















-
+







#endif /* SQLITE_OMIT_UTF16 */
/* EVIDENCE-OF: R-12793-43283 Every value in SQLite has one of five
** fundamental datatypes: 64-bit signed integer 64-bit IEEE floating
** point number string BLOB NULL
*/
int sqlite3_value_type(sqlite3_value* pVal){
  static const u8 aType[] = {
     SQLITE_BLOB,     /* 0x00 */
     SQLITE_NULL,     /* 0x01 */
     SQLITE_TEXT,     /* 0x02 */
     SQLITE_NULL,     /* 0x03 */
     SQLITE_INTEGER,  /* 0x04 */
     SQLITE_NULL,     /* 0x05 */
     SQLITE_INTEGER,  /* 0x06 */
     SQLITE_NULL,     /* 0x07 */
     SQLITE_FLOAT,    /* 0x08 */
     SQLITE_NULL,     /* 0x09 */
     SQLITE_FLOAT,    /* 0x0a */
     SQLITE_NULL,     /* 0x0b */
     SQLITE_INTEGER,  /* 0x0c */
     SQLITE_NULL,     /* 0x0d */
     SQLITE_INTEGER,  /* 0x0e */
     SQLITE_NULL,     /* 0x0f */
     SQLITE_BLOB,     /* 0x10 */
     SQLITE_NULL,     /* 0x11 */
     SQLITE_TEXT,     /* 0x12 */
     SQLITE_NULL,     /* 0x13 */
     SQLITE_INTEGER,  /* 0x14 */
     SQLITE_NULL,     /* 0x15 */
     SQLITE_INTEGER,  /* 0x16 */
     SQLITE_NULL,     /* 0x17 */
     SQLITE_FLOAT,    /* 0x18 */
     SQLITE_NULL,     /* 0x19 */
     SQLITE_FLOAT,    /* 0x1a */
     SQLITE_NULL,     /* 0x1b */
     SQLITE_INTEGER,  /* 0x1c */
     SQLITE_NULL,     /* 0x1d */
     SQLITE_INTEGER,  /* 0x1e */
     SQLITE_NULL,     /* 0x1f */
     SQLITE_BLOB,     /* 0x00 (not possible) */
     SQLITE_NULL,     /* 0x01 NULL */
     SQLITE_TEXT,     /* 0x02 TEXT */
     SQLITE_NULL,     /* 0x03 (not possible) */
     SQLITE_INTEGER,  /* 0x04 INTEGER */
     SQLITE_NULL,     /* 0x05 (not possible) */
     SQLITE_INTEGER,  /* 0x06 INTEGER + TEXT */
     SQLITE_NULL,     /* 0x07 (not possible) */
     SQLITE_FLOAT,    /* 0x08 FLOAT */
     SQLITE_NULL,     /* 0x09 (not possible) */
     SQLITE_FLOAT,    /* 0x0a FLOAT + TEXT */
     SQLITE_NULL,     /* 0x0b (not possible) */
     SQLITE_INTEGER,  /* 0x0c (not possible) */
     SQLITE_NULL,     /* 0x0d (not possible) */
     SQLITE_INTEGER,  /* 0x0e (not possible) */
     SQLITE_NULL,     /* 0x0f (not possible) */
     SQLITE_BLOB,     /* 0x10 BLOB */
     SQLITE_NULL,     /* 0x11 (not possible) */
     SQLITE_TEXT,     /* 0x12 (not possible) */
     SQLITE_NULL,     /* 0x13 (not possible) */
     SQLITE_INTEGER,  /* 0x14 INTEGER + BLOB */
     SQLITE_NULL,     /* 0x15 (not possible) */
     SQLITE_INTEGER,  /* 0x16 (not possible) */
     SQLITE_NULL,     /* 0x17 (not possible) */
     SQLITE_FLOAT,    /* 0x18 FLOAT + BLOB */
     SQLITE_NULL,     /* 0x19 (not possible) */
     SQLITE_FLOAT,    /* 0x1a (not possible) */
     SQLITE_NULL,     /* 0x1b (not possible) */
     SQLITE_INTEGER,  /* 0x1c (not possible) */
     SQLITE_NULL,     /* 0x1d (not possible) */
     SQLITE_INTEGER,  /* 0x1e (not possible) */
     SQLITE_NULL,     /* 0x1f (not possible) */
     SQLITE_FLOAT,    /* 0x20 INTREAL */
     SQLITE_NULL,     /* 0x21 (not possible) */
     SQLITE_TEXT,     /* 0x22 INTREAL + TEXT */
     SQLITE_NULL,     /* 0x23 (not possible) */
     SQLITE_FLOAT,    /* 0x24 (not possible) */
     SQLITE_NULL,     /* 0x25 (not possible) */
     SQLITE_FLOAT,    /* 0x26 (not possible) */
     SQLITE_NULL,     /* 0x27 (not possible) */
     SQLITE_FLOAT,    /* 0x28 (not possible) */
     SQLITE_NULL,     /* 0x29 (not possible) */
     SQLITE_FLOAT,    /* 0x2a (not possible) */
     SQLITE_NULL,     /* 0x2b (not possible) */
     SQLITE_FLOAT,    /* 0x2c (not possible) */
     SQLITE_NULL,     /* 0x2d (not possible) */
     SQLITE_FLOAT,    /* 0x2e (not possible) */
     SQLITE_NULL,     /* 0x2f (not possible) */
     SQLITE_BLOB,     /* 0x30 (not possible) */
     SQLITE_NULL,     /* 0x31 (not possible) */
     SQLITE_TEXT,     /* 0x32 (not possible) */
     SQLITE_NULL,     /* 0x33 (not possible) */
     SQLITE_FLOAT,    /* 0x34 (not possible) */
     SQLITE_NULL,     /* 0x35 (not possible) */
     SQLITE_FLOAT,    /* 0x36 (not possible) */
     SQLITE_NULL,     /* 0x37 (not possible) */
     SQLITE_FLOAT,    /* 0x38 (not possible) */
     SQLITE_NULL,     /* 0x39 (not possible) */
     SQLITE_FLOAT,    /* 0x3a (not possible) */
     SQLITE_NULL,     /* 0x3b (not possible) */
     SQLITE_FLOAT,    /* 0x3c (not possible) */
     SQLITE_NULL,     /* 0x3d (not possible) */
     SQLITE_FLOAT,    /* 0x3e (not possible) */
     SQLITE_NULL,     /* 0x3f (not possible) */
  };
#ifdef SQLITE_DEBUG
  {
    int eType = SQLITE_BLOB;
    if( pVal->flags & MEM_Null ){
      eType = SQLITE_NULL;
    }else if( pVal->flags & (MEM_Real|MEM_IntReal) ){
      eType = SQLITE_FLOAT;
    }else if( pVal->flags & MEM_Int ){
      eType = SQLITE_INTEGER;
    }else if( pVal->flags & MEM_Str ){
      eType = SQLITE_TEXT;
    }
    assert( eType == aType[pVal->flags&MEM_AffMask] );
  }
#endif
  return aType[pVal->flags&MEM_AffMask];
}
int sqlite3_value_encoding(sqlite3_value *pVal){
  return pVal->enc;
}

/* Return true if a parameter to xUpdate represents an unchanged column */
int sqlite3_value_nochange(sqlite3_value *pVal){
  return (pVal->flags&(MEM_Null|MEM_Zero))==(MEM_Null|MEM_Zero);
}

/* Return true if a parameter value originated from an sqlite3_bind() */
int sqlite3_value_frombind(sqlite3_value *pVal){
  return (pVal->flags&MEM_FromBind)!=0;
}

/* Make a copy of an sqlite3_value object
*/
sqlite3_value *sqlite3_value_dup(const sqlite3_value *pOrig){
  sqlite3_value *pNew;
  if( pOrig==0 ) return 0;
  pNew = sqlite3_malloc( sizeof(*pNew) );
  if( pNew==0 ) return 0;
  memset(pNew, 0, sizeof(*pNew));
  memcpy(pNew, pOrig, MEMCELLSIZE);
  pNew->flags &= ~MEM_Dyn;
  pNew->db = 0;
  if( pNew->flags&(MEM_Str|MEM_Blob) ){
    pNew->flags &= ~(MEM_Static|MEM_Dyn);
    pNew->flags |= MEM_Ephem;
    if( sqlite3VdbeMemMakeWriteable(pNew)!=SQLITE_OK ){
      sqlite3ValueFree(pNew);
      pNew = 0;
    }
  }else if( pNew->flags & MEM_Null ){
    /* Do not duplicate pointer values */
    pNew->flags &= ~(MEM_Term|MEM_Subtype);
  }
  return pNew;
}

/* Destroy an sqlite3_value object previously obtained from
** sqlite3_value_dup().
*/
void sqlite3_value_free(sqlite3_value *pOld){
  sqlite3ValueFree(pOld);
}
  

/**************************** sqlite3_result_  *******************************
** The following routines are used by user-defined functions to specify
** the function result.
**
** The setStrOrError() function calls sqlite3VdbeMemSetStr() to store the
** result as a string or blob but if the string or blob is too large, it
** then sets the error code to SQLITE_TOOBIG
** result as a string or blob.  Appropriate errors are set if the string/blob
** is too big or if an OOM occurs.
**
** The invokeValueDestructor(P,X) routine invokes destructor function X()
** on value P is not going to be used and need to be destroyed.
*/
static void setResultStrOrError(
  sqlite3_context *pCtx,  /* Function context */
  const char *z,          /* String pointer */
  int n,                  /* Bytes in string, or negative */
  u8 enc,                 /* Encoding of z.  0 for BLOBs */
  void (*xDel)(void*)     /* Destructor function */
){
  Mem *pOut = pCtx->pOut;
  int rc = sqlite3VdbeMemSetStr(pOut, z, n, enc, xDel);
  if( rc ){
    if( rc==SQLITE_TOOBIG ){
      sqlite3_result_error_toobig(pCtx);
    }else{
      /* The only errors possible from sqlite3VdbeMemSetStr are
      ** SQLITE_TOOBIG and SQLITE_NOMEM */
      assert( rc==SQLITE_NOMEM );
      sqlite3_result_error_nomem(pCtx);
    }
    return;
  }
  sqlite3VdbeChangeEncoding(pOut, pCtx->enc);
  if( sqlite3VdbeMemSetStr(pCtx->pOut, z, n, enc, xDel)==SQLITE_TOOBIG ){
  if( sqlite3VdbeMemTooBig(pOut) ){
    sqlite3_result_error_toobig(pCtx);
  }
}
static int invokeValueDestructor(
  const void *p,             /* Value to destroy */
  void (*xDel)(void*),       /* The destructor */
  sqlite3_context *pCtx      /* Set a SQLITE_TOOBIG error if no NULL */
){
  assert( xDel!=SQLITE_DYNAMIC );
  if( xDel==0 ){
    /* noop */
  }else if( xDel==SQLITE_TRANSIENT ){
    /* noop */
  }else{
    xDel((void*)p);
  }
  if( pCtx ) sqlite3_result_error_toobig(pCtx);
  sqlite3_result_error_toobig(pCtx);
  return SQLITE_TOOBIG;
}
void sqlite3_result_blob(
  sqlite3_context *pCtx, 
  const void *z, 
  int n, 
  void (*xDel)(void *)
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
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







+
-
+
+
+














-
+








-
+








-
+



+

-
-
+
+
+
+
+
+

-
+
-





+


+


+
+
+







-
-
+
+


















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  const char *z, 
  sqlite3_uint64 n,
  void (*xDel)(void *),
  unsigned char enc
){
  assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
  assert( xDel!=SQLITE_DYNAMIC );
  if( enc!=SQLITE_UTF8 ){
  if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
    if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
    n &= ~(u64)1;
  }
  if( n>0x7fffffff ){
    (void)invokeValueDestructor(z, xDel, pCtx);
  }else{
    setResultStrOrError(pCtx, z, (int)n, enc, xDel);
  }
}
#ifndef SQLITE_OMIT_UTF16
void sqlite3_result_text16(
  sqlite3_context *pCtx, 
  const void *z, 
  int n, 
  void (*xDel)(void *)
){
  assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
  setResultStrOrError(pCtx, z, n, SQLITE_UTF16NATIVE, xDel);
  setResultStrOrError(pCtx, z, n & ~(u64)1, SQLITE_UTF16NATIVE, xDel);
}
void sqlite3_result_text16be(
  sqlite3_context *pCtx, 
  const void *z, 
  int n, 
  void (*xDel)(void *)
){
  assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
  setResultStrOrError(pCtx, z, n, SQLITE_UTF16BE, xDel);
  setResultStrOrError(pCtx, z, n & ~(u64)1, SQLITE_UTF16BE, xDel);
}
void sqlite3_result_text16le(
  sqlite3_context *pCtx, 
  const void *z, 
  int n, 
  void (*xDel)(void *)
){
  assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
  setResultStrOrError(pCtx, z, n, SQLITE_UTF16LE, xDel);
  setResultStrOrError(pCtx, z, n & ~(u64)1, SQLITE_UTF16LE, xDel);
}
#endif /* SQLITE_OMIT_UTF16 */
void sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){
  Mem *pOut = pCtx->pOut;
  assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
  sqlite3VdbeMemCopy(pCtx->pOut, pValue);
}
  sqlite3VdbeMemCopy(pOut, pValue);
  sqlite3VdbeChangeEncoding(pOut, pCtx->enc);
  if( sqlite3VdbeMemTooBig(pOut) ){
    sqlite3_result_error_toobig(pCtx);
  }
}
void sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){
  assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
  sqlite3_result_zeroblob64(pCtx, n>0 ? n : 0);
  sqlite3VdbeMemSetZeroBlob(pCtx->pOut, n);
}
int sqlite3_result_zeroblob64(sqlite3_context *pCtx, u64 n){
  Mem *pOut = pCtx->pOut;
  assert( sqlite3_mutex_held(pOut->db->mutex) );
  if( n>(u64)pOut->db->aLimit[SQLITE_LIMIT_LENGTH] ){
    sqlite3_result_error_toobig(pCtx);
    return SQLITE_TOOBIG;
  }
#ifndef SQLITE_OMIT_INCRBLOB
  sqlite3VdbeMemSetZeroBlob(pCtx->pOut, (int)n);
  return SQLITE_OK;
#else
  return sqlite3VdbeMemSetZeroBlob(pCtx->pOut, (int)n);
#endif
}
void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
  pCtx->isError = errCode ? errCode : -1;
#ifdef SQLITE_DEBUG
  if( pCtx->pVdbe ) pCtx->pVdbe->rcApp = errCode;
#endif
  if( pCtx->pOut->flags & MEM_Null ){
    sqlite3VdbeMemSetStr(pCtx->pOut, sqlite3ErrStr(errCode), -1, 
                         SQLITE_UTF8, SQLITE_STATIC);
    setResultStrOrError(pCtx, sqlite3ErrStr(errCode), -1, SQLITE_UTF8,
                        SQLITE_STATIC);
  }
}

/* Force an SQLITE_TOOBIG error. */
void sqlite3_result_error_toobig(sqlite3_context *pCtx){
  assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
  pCtx->isError = SQLITE_TOOBIG;
  sqlite3VdbeMemSetStr(pCtx->pOut, "string or blob too big", -1, 
                       SQLITE_UTF8, SQLITE_STATIC);
}

/* An SQLITE_NOMEM error. */
void sqlite3_result_error_nomem(sqlite3_context *pCtx){
  assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
  sqlite3VdbeMemSetNull(pCtx->pOut);
  pCtx->isError = SQLITE_NOMEM_BKPT;
  sqlite3OomFault(pCtx->pOut->db);
}

#ifndef SQLITE_UNTESTABLE
/* Force the INT64 value currently stored as the result to be
** a MEM_IntReal value.  See the SQLITE_TESTCTRL_RESULT_INTREAL
** test-control.
*/
void sqlite3ResultIntReal(sqlite3_context *pCtx){ 
  assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
  if( pCtx->pOut->flags & MEM_Int ){
    pCtx->pOut->flags &= ~MEM_Int;
    pCtx->pOut->flags |= MEM_IntReal;
  }
}
#endif


/*
** This function is called after a transaction has been committed. It 
** invokes callbacks registered with sqlite3_wal_hook() as required.
*/
static int doWalCallbacks(sqlite3 *db){
  int rc = SQLITE_OK;
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
638
639

640
641
642
643
644
645






646
647
648
649
650
651

652
653
654
655
656
657



658
659
660
661

662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
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
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







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
+
+
+


-
-
-
-
-
-
+
+
+
+
+
+


-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+














-
+
+
+
+
+
+




-
+






+
+
+
+
+
+






+


-
-
-
-
+
+
+
-
-
-
-
+


-
-
-
-
-
-
-
-
-
-
-



















-







** outer sqlite3_step() wrapper procedure.
*/
static int sqlite3Step(Vdbe *p){
  sqlite3 *db;
  int rc;

  assert(p);
  if( p->magic!=VDBE_MAGIC_RUN ){
    /* We used to require that sqlite3_reset() be called before retrying
    ** sqlite3_step() after any error or after SQLITE_DONE.  But beginning
    ** with version 3.7.0, we changed this so that sqlite3_reset() would
    ** be called automatically instead of throwing the SQLITE_MISUSE error.
    ** This "automatic-reset" change is not technically an incompatibility, 
    ** since any application that receives an SQLITE_MISUSE is broken by
    ** definition.
    **
    ** Nevertheless, some published applications that were originally written
    ** for version 3.6.23 or earlier do in fact depend on SQLITE_MISUSE 
    ** returns, and those were broken by the automatic-reset change.  As a
    ** a work-around, the SQLITE_OMIT_AUTORESET compile-time restores the
    ** legacy behavior of returning SQLITE_MISUSE for cases where the 
    ** previous sqlite3_step() returned something other than a SQLITE_LOCKED
    ** or SQLITE_BUSY error.
    */
#ifdef SQLITE_OMIT_AUTORESET
    if( (rc = p->rc&0xff)==SQLITE_BUSY || rc==SQLITE_LOCKED ){
      sqlite3_reset((sqlite3_stmt*)p);
    }else{
      return SQLITE_MISUSE_BKPT;
    }
#else
    sqlite3_reset((sqlite3_stmt*)p);
#endif
  }

  /* Check that malloc() has not failed. If it has, return early. */
  db = p->db;
  if( db->mallocFailed ){
  if( p->eVdbeState!=VDBE_RUN_STATE ){
    p->rc = SQLITE_NOMEM;
    return SQLITE_NOMEM_BKPT;
    restart_step:
  }

  if( p->pc<0 && p->expired ){
    p->rc = SQLITE_SCHEMA;
    rc = SQLITE_ERROR;
    goto end_of_step;
  }
  if( p->pc<0 ){
    /* If there are no other statements currently running, then
    ** reset the interrupt flag.  This prevents a call to sqlite3_interrupt
    ** from interrupting a statement that has not yet started.
    */
    if( db->nVdbeActive==0 ){
      db->u1.isInterrupted = 0;
    }
    if( p->eVdbeState==VDBE_READY_STATE ){
      if( p->expired ){
        p->rc = SQLITE_SCHEMA;
        rc = SQLITE_ERROR;
        if( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 ){
          /* If this statement was prepared using saved SQL and an 
          ** error has occurred, then return the error code in p->rc to the
          ** caller. Set the error code in the database handle to the same
          ** value.
          */ 
          rc = sqlite3VdbeTransferError(p);
        }
        goto end_of_step;
      }

      /* If there are no other statements currently running, then
      ** reset the interrupt flag.  This prevents a call to sqlite3_interrupt
      ** from interrupting a statement that has not yet started.
      */
      if( db->nVdbeActive==0 ){
        AtomicStore(&db->u1.isInterrupted, 0);
      }

    assert( db->nVdbeWrite>0 || db->autoCommit==0 
        || (db->nDeferredCons==0 && db->nDeferredImmCons==0)
    );
      assert( db->nVdbeWrite>0 || db->autoCommit==0 
          || (db->nDeferredCons==0 && db->nDeferredImmCons==0)
      );

#ifndef SQLITE_OMIT_TRACE
    if( (db->mTrace & (SQLITE_TRACE_PROFILE|SQLITE_TRACE_XPROFILE))!=0
        && !db->init.busy && p->zSql ){
      sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime);
    }else{
      assert( p->startTime==0 );
    }
      if( (db->mTrace & (SQLITE_TRACE_PROFILE|SQLITE_TRACE_XPROFILE))!=0
          && !db->init.busy && p->zSql ){
        sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime);
      }else{
        assert( p->startTime==0 );
      }
#endif

    db->nVdbeActive++;
    if( p->readOnly==0 ) db->nVdbeWrite++;
    if( p->bIsReader ) db->nVdbeRead++;
    p->pc = 0;
  }
      db->nVdbeActive++;
      if( p->readOnly==0 ) db->nVdbeWrite++;
      if( p->bIsReader ) db->nVdbeRead++;
      p->pc = 0;
      p->eVdbeState = VDBE_RUN_STATE;
    }else

    if( ALWAYS(p->eVdbeState==VDBE_HALT_STATE) ){
      /* We used to require that sqlite3_reset() be called before retrying
      ** sqlite3_step() after any error or after SQLITE_DONE.  But beginning
      ** with version 3.7.0, we changed this so that sqlite3_reset() would
      ** be called automatically instead of throwing the SQLITE_MISUSE error.
      ** This "automatic-reset" change is not technically an incompatibility, 
      ** since any application that receives an SQLITE_MISUSE is broken by
      ** definition.
      **
      ** Nevertheless, some published applications that were originally written
      ** for version 3.6.23 or earlier do in fact depend on SQLITE_MISUSE 
      ** returns, and those were broken by the automatic-reset change.  As a
      ** a work-around, the SQLITE_OMIT_AUTORESET compile-time restores the
      ** legacy behavior of returning SQLITE_MISUSE for cases where the 
      ** previous sqlite3_step() returned something other than a SQLITE_LOCKED
      ** or SQLITE_BUSY error.
      */
#ifdef SQLITE_OMIT_AUTORESET
      if( (rc = p->rc&0xff)==SQLITE_BUSY || rc==SQLITE_LOCKED ){
        sqlite3_reset((sqlite3_stmt*)p);
      }else{
        return SQLITE_MISUSE_BKPT;
      }
#else
      sqlite3_reset((sqlite3_stmt*)p);
#endif
      assert( p->eVdbeState==VDBE_READY_STATE );
      goto restart_step;
    }
  }

#ifdef SQLITE_DEBUG
  p->rcApp = SQLITE_OK;
#endif
#ifndef SQLITE_OMIT_EXPLAIN
  if( p->explain ){
    rc = sqlite3VdbeList(p);
  }else
#endif /* SQLITE_OMIT_EXPLAIN */
  {
    db->nVdbeExec++;
    rc = sqlite3VdbeExec(p);
    db->nVdbeExec--;
  }

  if( rc!=SQLITE_ROW ){
  if( rc==SQLITE_ROW ){
    assert( p->rc==SQLITE_OK );
    assert( db->mallocFailed==0 );
    db->errCode = SQLITE_ROW;
    return SQLITE_ROW;
  }else{
#ifndef SQLITE_OMIT_TRACE
    /* If the statement completed successfully, invoke the profile callback */
    checkProfileCallback(db, p);
#endif

    p->pResultRow = 0;
    if( rc==SQLITE_DONE && db->autoCommit ){
      assert( p->rc==SQLITE_OK );
      p->rc = doWalCallbacks(db);
      if( p->rc!=SQLITE_OK ){
        rc = SQLITE_ERROR;
      }
    }else if( rc!=SQLITE_DONE && (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 ){
      /* If this statement was prepared using saved SQL and an 
      ** error has occurred, then return the error code in p->rc to the
      ** caller. Set the error code in the database handle to the same value.
      */ 
      rc = sqlite3VdbeTransferError(p);
    }
  }

  db->errCode = rc;
  if( SQLITE_NOMEM==sqlite3ApiExit(p->db, p->rc) ){
    p->rc = SQLITE_NOMEM_BKPT;
    if( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 ) rc = p->rc;
  }
end_of_step:
  /* At this point local variable rc holds the value that should be 
  ** returned if this statement was compiled using the legacy 
  ** sqlite3_prepare() interface. According to the docs, this can only
  ** be one of the values in the first assert() below. Variable p->rc 
  /* There are only a limited number of result codes allowed from the
  ** statements prepared using the legacy sqlite3_prepare() interface */
  assert( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0
  ** contains the value that would be returned if sqlite3_finalize() 
  ** were called on statement p.
  */
  assert( rc==SQLITE_ROW  || rc==SQLITE_DONE   || rc==SQLITE_ERROR 
       || rc==SQLITE_ROW  || rc==SQLITE_DONE   || rc==SQLITE_ERROR 
       || (rc&0xff)==SQLITE_BUSY || rc==SQLITE_MISUSE
  );
  assert( (p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE) || p->rc==p->rcApp );
  if( rc!=SQLITE_ROW 
   && rc!=SQLITE_DONE
   && (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0
  ){
    /* If this statement was prepared using saved SQL and an 
    ** error has occurred, then return the error code in p->rc to the
    ** caller. Set the error code in the database handle to the same value.
    */ 
    rc = sqlite3VdbeTransferError(p);
  }
  return (rc&db->errMask);
}

/*
** This is the top-level implementation of sqlite3_step().  Call
** sqlite3Step() to do most of the work.  If a schema error occurs,
** call sqlite3Reprepare() and try again.
*/
int sqlite3_step(sqlite3_stmt *pStmt){
  int rc = SQLITE_OK;      /* Result from sqlite3Step() */
  Vdbe *v = (Vdbe*)pStmt;  /* the prepared statement */
  int cnt = 0;             /* Counter to prevent infinite loop of reprepares */
  sqlite3 *db;             /* The database connection */

  if( vdbeSafetyNotNull(v) ){
    return SQLITE_MISUSE_BKPT;
  }
  db = v->db;
  sqlite3_mutex_enter(db->mutex);
  v->doingRerun = 0;
  while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
         && cnt++ < SQLITE_MAX_SCHEMA_RETRY ){
    int savedPc = v->pc;
    rc = sqlite3Reprepare(v);
    if( rc!=SQLITE_OK ){
      /* This case occurs after failing to recompile an sql statement. 
      ** The error message from the SQL compiler has already been loaded 
713
714
715
716
717
718
719
720







721
722
723
724
725
726
727
821
822
823
824
825
826
827

828
829
830
831
832
833
834
835
836
837
838
839
840
841







-
+
+
+
+
+
+
+







      } else {
        v->zErrMsg = 0;
        v->rc = rc = SQLITE_NOMEM_BKPT;
      }
      break;
    }
    sqlite3_reset(pStmt);
    if( savedPc>=0 ) v->doingRerun = 1;
    if( savedPc>=0 ){
      /* Setting minWriteFileFormat to 254 is a signal to the OP_Init and
      ** OP_Trace opcodes to *not* perform SQLITE_TRACE_STMT because it has
      ** already been done once on a prior invocation that failed due to
      ** SQLITE_SCHEMA.   tag-20220401a  */
      v->minWriteFileFormat = 254;
    }
    assert( v->expired==0 );
  }
  sqlite3_mutex_leave(db->mutex);
  return rc;
}


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
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975

976
977
978
979
980
981
982
983









+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








-
+







** performance by substituting a NULL result, or some other light-weight
** value, as a signal to the xUpdate routine that the column is unchanged.
*/
int sqlite3_vtab_nochange(sqlite3_context *p){
  assert( p );
  return sqlite3_value_nochange(p->pOut);
}

/*
** The destructor function for a ValueList object.  This needs to be
** a separate function, unknowable to the application, to ensure that
** calls to sqlite3_vtab_in_first()/sqlite3_vtab_in_next() that are not
** preceeded by activation of IN processing via sqlite3_vtab_int() do not
** try to access a fake ValueList object inserted by a hostile extension.
*/
void sqlite3VdbeValueListFree(void *pToDelete){
  sqlite3_free(pToDelete);
}

/*
** Implementation of sqlite3_vtab_in_first() (if bNext==0) and
** sqlite3_vtab_in_next() (if bNext!=0).
*/
static int valueFromValueList(
  sqlite3_value *pVal,        /* Pointer to the ValueList object */
  sqlite3_value **ppOut,      /* Store the next value from the list here */
  int bNext                   /* 1 for _next(). 0 for _first() */
){
  int rc;
  ValueList *pRhs;

  *ppOut = 0;
  if( pVal==0 ) return SQLITE_MISUSE;
  if( (pVal->flags & MEM_Dyn)==0 || pVal->xDel!=sqlite3VdbeValueListFree ){
    return SQLITE_ERROR;
  }else{
    assert( (pVal->flags&(MEM_TypeMask|MEM_Term|MEM_Subtype)) ==
                 (MEM_Null|MEM_Term|MEM_Subtype) );
    assert( pVal->eSubtype=='p' );
    assert( pVal->u.zPType!=0 && strcmp(pVal->u.zPType,"ValueList")==0 );
    pRhs = (ValueList*)pVal->z;
  }
  if( bNext ){
    rc = sqlite3BtreeNext(pRhs->pCsr, 0);
  }else{
    int dummy = 0;
    rc = sqlite3BtreeFirst(pRhs->pCsr, &dummy);
    assert( rc==SQLITE_OK || sqlite3BtreeEof(pRhs->pCsr) );
    if( sqlite3BtreeEof(pRhs->pCsr) ) rc = SQLITE_DONE;
  }
  if( rc==SQLITE_OK ){
    u32 sz;       /* Size of current row in bytes */
    Mem sMem;     /* Raw content of current row */
    memset(&sMem, 0, sizeof(sMem));
    sz = sqlite3BtreePayloadSize(pRhs->pCsr);
    rc = sqlite3VdbeMemFromBtreeZeroOffset(pRhs->pCsr,(int)sz,&sMem);
    if( rc==SQLITE_OK ){
      u8 *zBuf = (u8*)sMem.z;
      u32 iSerial;
      sqlite3_value *pOut = pRhs->pOut;
      int iOff = 1 + getVarint32(&zBuf[1], iSerial);
      sqlite3VdbeSerialGet(&zBuf[iOff], iSerial, pOut);
      pOut->enc = ENC(pOut->db);
      if( (pOut->flags & MEM_Ephem)!=0 && sqlite3VdbeMemMakeWriteable(pOut) ){
        rc = SQLITE_NOMEM;
      }else{
        *ppOut = pOut;
      }
    }
    sqlite3VdbeMemRelease(&sMem);
  }
  return rc;
}

/*
** Set the iterator value pVal to point to the first value in the set.
** Set (*ppOut) to point to this value before returning.
*/
int sqlite3_vtab_in_first(sqlite3_value *pVal, sqlite3_value **ppOut){
  return valueFromValueList(pVal, ppOut, 0);
}

/*
** Set the iterator value pVal to point to the next value in the set.
** Set (*ppOut) to point to this value before returning.
*/
int sqlite3_vtab_in_next(sqlite3_value *pVal, sqlite3_value **ppOut){
  return valueFromValueList(pVal, ppOut, 1);
}

/*
** Return the current time for a statement.  If the current time
** is requested more than once within the same run of a single prepared
** statement, the exact same time is returned for each invocation regardless
** of the amount of time that elapses between invocations.  In other words,
** the time returned is always the time of the first call.
*/
sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context *p){
  int rc;
#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
#ifndef SQLITE_ENABLE_STAT4
  sqlite3_int64 *piTime = &p->pVdbe->iCurrentTime;
  assert( p->pVdbe!=0 );
#else
  sqlite3_int64 iTime = 0;
  sqlite3_int64 *piTime = p->pVdbe!=0 ? &p->pVdbe->iCurrentTime : &iTime;
#endif
  if( *piTime==0 ){
838
839
840
841
842
843
844
845

846
847
848
849
850
851
852
1034
1035
1036
1037
1038
1039
1040

1041
1042
1043
1044
1045
1046
1047
1048







-
+







** auxiliary data pointers that is available to all functions within a
** single prepared statement.  The iArg values must match.
*/
void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){
  AuxData *pAuxData;

  assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
#if SQLITE_ENABLE_STAT3_OR_STAT4
#if SQLITE_ENABLE_STAT4
  if( pCtx->pVdbe==0 ) return 0;
#else
  assert( pCtx->pVdbe!=0 );
#endif
  for(pAuxData=pCtx->pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNextAux){
    if(  pAuxData->iAuxArg==iArg && (pAuxData->iAuxOp==pCtx->iOp || iArg<0) ){
      return pAuxData->pAux;
872
873
874
875
876
877
878
879

880
881
882
883
884
885
886
1068
1069
1070
1071
1072
1073
1074

1075
1076
1077
1078
1079
1080
1081
1082







-
+







  void *pAux, 
  void (*xDelete)(void*)
){
  AuxData *pAuxData;
  Vdbe *pVdbe = pCtx->pVdbe;

  assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
  if( pVdbe==0 ) goto failed;
#else
  assert( pVdbe!=0 );
#endif

  for(pAuxData=pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNextAux){
    if( pAuxData->iAuxArg==iArg && (pAuxData->iAuxOp==pCtx->iOp || iArg<0) ){
935
936
937
938
939
940
941
942

943
944
945
946
947
948
949
1131
1132
1133
1134
1135
1136
1137

1138
1139
1140
1141
1142
1143
1144
1145







-
+








/*
** Return the number of values available from the current row of the
** currently executing statement pStmt.
*/
int sqlite3_data_count(sqlite3_stmt *pStmt){
  Vdbe *pVm = (Vdbe *)pStmt;
  if( pVm==0 || pVm->pResultSet==0 ) return 0;
  if( pVm==0 || pVm->pResultRow==0 ) return 0;
  return pVm->nResColumn;
}

/*
** Return a pointer to static memory containing an SQL NULL value.
*/
static const Mem *columnNullValue(void){
958
959
960
961
962
963
964


965
966
967
968

969
970
971
972
973

974
975
976
977
978
979
980
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165

1166


1167
1168

1169
1170
1171
1172
1173
1174
1175
1176







+
+



-
+
-
-


-
+







  ** __attribute__((aligned(8))) macro.  */
  static const Mem nullMem 
#if defined(SQLITE_DEBUG) && defined(__GNUC__)
    __attribute__((aligned(8))) 
#endif
    = {
        /* .u          = */ {0},
        /* .z          = */ (char*)0,
        /* .n          = */ (int)0,
        /* .flags      = */ (u16)MEM_Null,
        /* .enc        = */ (u8)0,
        /* .eSubtype   = */ (u8)0,
        /* .n          = */ (int)0,
        /* .db         = */ (sqlite3*)0,
        /* .z          = */ (char*)0,
        /* .zMalloc    = */ (char*)0,
        /* .szMalloc   = */ (int)0,
        /* .uTemp      = */ (u32)0,
        /* .db         = */ (sqlite3*)0,
        /* .zMalloc    = */ (char*)0,
        /* .xDel       = */ (void(*)(void*))0,
#ifdef SQLITE_DEBUG
        /* .pScopyFrom = */ (Mem*)0,
        /* .mScopyFlags= */ 0,
#endif
      };
  return &nullMem;
990
991
992
993
994
995
996
997
998


999
1000
1001
1002
1003
1004
1005
1186
1187
1188
1189
1190
1191
1192


1193
1194
1195
1196
1197
1198
1199
1200
1201







-
-
+
+







  Vdbe *pVm;
  Mem *pOut;

  pVm = (Vdbe *)pStmt;
  if( pVm==0 ) return (Mem*)columnNullValue();
  assert( pVm->db );
  sqlite3_mutex_enter(pVm->db->mutex);
  if( pVm->pResultSet!=0 && i<pVm->nResColumn && i>=0 ){
    pOut = &pVm->pResultSet[i];
  if( pVm->pResultRow!=0 && i<pVm->nResColumn && i>=0 ){
    pOut = &pVm->pResultRow[i];
  }else{
    sqlite3Error(pVm->db, SQLITE_RANGE);
    pOut = (Mem*)columnNullValue();
  }
  return pOut;
}

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
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
1318
1319
1320
1321
1322

1323
1324
1325
1326
1327
1328
1329
1312
1313
1314
1315
1316
1317
1318




1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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
1430
1431
1432
1433
1434

1435

1436
1437
1438

1439

1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459

1460
1461
1462
1463
1464
1465

1466
1467
1468
1469
1470
1471
1472

1473
1474
1475
1476
1477

1478
1479
1480
1481
1482
1483
1484
1485

1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505

1506
1507
1508
1509
1510
1511
1512
1513

1514
1515
1516
1517
1518
1519
1520
1521







-
-
-
-
+
+
+
+




















+
+
+
+
+
+
-
-
+
+
+
















-
+
-



-
+
-


















-
+
-



-
+
-











-
+
-



-
+
-









-
+
-



-
+
-









-
+
-



-
+
-




















-
+





-
+






-
+




-








-
+



















-
+







-
+







**    3      The name of the table that the column derives from
**    4      The name of the table column that the result column derives from
**
** If the result is not a simple column reference (if it is an expression
** or a constant) then useTypes 2, 3, and 4 return NULL.
*/
static const void *columnName(
  sqlite3_stmt *pStmt,
  int N,
  const void *(*xFunc)(Mem*),
  int useType
  sqlite3_stmt *pStmt,     /* The statement */
  int N,                   /* Which column to get the name for */
  int useUtf16,            /* True to return the name as UTF16 */
  int useType              /* What type of name */
){
  const void *ret;
  Vdbe *p;
  int n;
  sqlite3 *db;
#ifdef SQLITE_ENABLE_API_ARMOR
  if( pStmt==0 ){
    (void)SQLITE_MISUSE_BKPT;
    return 0;
  }
#endif
  ret = 0;
  p = (Vdbe *)pStmt;
  db = p->db;
  assert( db!=0 );
  n = sqlite3_column_count(pStmt);
  if( N<n && N>=0 ){
    N += useType*n;
    sqlite3_mutex_enter(db->mutex);
    assert( db->mallocFailed==0 );
#ifndef SQLITE_OMIT_UTF16
    if( useUtf16 ){
      ret = sqlite3_value_text16((sqlite3_value*)&p->aColName[N]);
    }else
#endif
    {
    ret = xFunc(&p->aColName[N]);
     /* A malloc may have failed inside of the xFunc() call. If this
      ret = sqlite3_value_text((sqlite3_value*)&p->aColName[N]);
    }
    /* A malloc may have failed inside of the _text() call. If this
    ** is the case, clear the mallocFailed flag and return NULL.
    */
    if( db->mallocFailed ){
      sqlite3OomClear(db);
      ret = 0;
    }
    sqlite3_mutex_leave(db->mutex);
  }
  return ret;
}

/*
** Return the name of the Nth column of the result set returned by SQL
** statement pStmt.
*/
const char *sqlite3_column_name(sqlite3_stmt *pStmt, int N){
  return columnName(
  return columnName(pStmt, N, 0, COLNAME_NAME);
      pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_NAME);
}
#ifndef SQLITE_OMIT_UTF16
const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){
  return columnName(
  return columnName(pStmt, N, 1, COLNAME_NAME);
      pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_NAME);
}
#endif

/*
** Constraint:  If you have ENABLE_COLUMN_METADATA then you must
** not define OMIT_DECLTYPE.
*/
#if defined(SQLITE_OMIT_DECLTYPE) && defined(SQLITE_ENABLE_COLUMN_METADATA)
# error "Must not define both SQLITE_OMIT_DECLTYPE \
         and SQLITE_ENABLE_COLUMN_METADATA"
#endif

#ifndef SQLITE_OMIT_DECLTYPE
/*
** Return the column declaration type (if applicable) of the 'i'th column
** of the result set of SQL statement pStmt.
*/
const char *sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){
  return columnName(
  return columnName(pStmt, N, 0, COLNAME_DECLTYPE);
      pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DECLTYPE);
}
#ifndef SQLITE_OMIT_UTF16
const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){
  return columnName(
  return columnName(pStmt, N, 1, COLNAME_DECLTYPE);
      pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DECLTYPE);
}
#endif /* SQLITE_OMIT_UTF16 */
#endif /* SQLITE_OMIT_DECLTYPE */

#ifdef SQLITE_ENABLE_COLUMN_METADATA
/*
** Return the name of the database from which a result column derives.
** NULL is returned if the result column is an expression or constant or
** anything else which is not an unambiguous reference to a database column.
*/
const char *sqlite3_column_database_name(sqlite3_stmt *pStmt, int N){
  return columnName(
  return columnName(pStmt, N, 0, COLNAME_DATABASE);
      pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DATABASE);
}
#ifndef SQLITE_OMIT_UTF16
const void *sqlite3_column_database_name16(sqlite3_stmt *pStmt, int N){
  return columnName(
  return columnName(pStmt, N, 1, COLNAME_DATABASE);
      pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DATABASE);
}
#endif /* SQLITE_OMIT_UTF16 */

/*
** Return the name of the table from which a result column derives.
** NULL is returned if the result column is an expression or constant or
** anything else which is not an unambiguous reference to a database column.
*/
const char *sqlite3_column_table_name(sqlite3_stmt *pStmt, int N){
  return columnName(
  return columnName(pStmt, N, 0, COLNAME_TABLE);
      pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_TABLE);
}
#ifndef SQLITE_OMIT_UTF16
const void *sqlite3_column_table_name16(sqlite3_stmt *pStmt, int N){
  return columnName(
  return columnName(pStmt, N, 1, COLNAME_TABLE);
      pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_TABLE);
}
#endif /* SQLITE_OMIT_UTF16 */

/*
** Return the name of the table column from which a result column derives.
** NULL is returned if the result column is an expression or constant or
** anything else which is not an unambiguous reference to a database column.
*/
const char *sqlite3_column_origin_name(sqlite3_stmt *pStmt, int N){
  return columnName(
  return columnName(pStmt, N, 0, COLNAME_COLUMN);
      pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_COLUMN);
}
#ifndef SQLITE_OMIT_UTF16
const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){
  return columnName(
  return columnName(pStmt, N, 1, COLNAME_COLUMN);
      pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_COLUMN);
}
#endif /* SQLITE_OMIT_UTF16 */
#endif /* SQLITE_ENABLE_COLUMN_METADATA */


/******************************* sqlite3_bind_  ***************************
** 
** Routines used to attach values to wildcards in a compiled SQL statement.
*/
/*
** Unbind the value bound to variable i in virtual machine p. This is the 
** the same as binding a NULL value to the column. If the "i" parameter is
** out of range, then SQLITE_RANGE is returned. Othewise SQLITE_OK.
**
** A successful evaluation of this routine acquires the mutex on p.
** the mutex is released if any kind of error occurs.
**
** The error code stored in database p->db is overwritten with the return
** value in any case.
*/
static int vdbeUnbind(Vdbe *p, int i){
static int vdbeUnbind(Vdbe *p, unsigned int i){
  Mem *pVar;
  if( vdbeSafetyNotNull(p) ){
    return SQLITE_MISUSE_BKPT;
  }
  sqlite3_mutex_enter(p->db->mutex);
  if( p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){
  if( p->eVdbeState!=VDBE_READY_STATE ){
    sqlite3Error(p->db, SQLITE_MISUSE);
    sqlite3_mutex_leave(p->db->mutex);
    sqlite3_log(SQLITE_MISUSE, 
        "bind on a busy prepared statement: [%s]", p->zSql);
    return SQLITE_MISUSE_BKPT;
  }
  if( i<1 || i>p->nVar ){
  if( i>=(unsigned int)p->nVar ){
    sqlite3Error(p->db, SQLITE_RANGE);
    sqlite3_mutex_leave(p->db->mutex);
    return SQLITE_RANGE;
  }
  i--;
  pVar = &p->aVar[i];
  sqlite3VdbeMemRelease(pVar);
  pVar->flags = MEM_Null;
  p->db->errCode = SQLITE_OK;

  /* If the bit corresponding to this variable in Vdbe.expmask is set, then 
  ** binding a new value to this variable invalidates the current query plan.
  **
  ** IMPLEMENTATION-OF: R-48440-37595 If the specific value bound to host
  ** IMPLEMENTATION-OF: R-57496-20354 If the specific value bound to a host
  ** parameter in the WHERE clause might influence the choice of query plan
  ** for a statement, then the statement will be automatically recompiled,
  ** as if there had been a schema change, on the first sqlite3_step() call
  ** following any change to the bindings of that parameter.
  */
  assert( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 || p->expmask==0 );
  if( p->expmask!=0 && (p->expmask & (i>=31 ? 0x80000000 : (u32)1<<i))!=0 ){
    p->expired = 1;
  }
  return SQLITE_OK;
}

/*
** Bind a text or BLOB value.
*/
static int bindText(
  sqlite3_stmt *pStmt,   /* The statement to bind against */
  int i,                 /* Index of the parameter to bind */
  const void *zData,     /* Pointer to the data to be bound */
  int nData,             /* Number of bytes of data to be bound */
  i64 nData,             /* Number of bytes of data to be bound */
  void (*xDel)(void*),   /* Destructor for the data */
  u8 encoding            /* Encoding for the data */
){
  Vdbe *p = (Vdbe *)pStmt;
  Mem *pVar;
  int rc;

  rc = vdbeUnbind(p, i);
  rc = vdbeUnbind(p, (u32)(i-1));
  if( rc==SQLITE_OK ){
    if( zData!=0 ){
      pVar = &p->aVar[i-1];
      rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel);
      if( rc==SQLITE_OK && encoding!=0 ){
        rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db));
      }
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
1551
1552
1553
1554
1555
1556
1557




1558

1559
1560
1561
1562

1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575

1576
1577
1578
1579
1580
1581
1582
1583
1584
1585

1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600

1601
1602
1603
1604
1605
1606
1607
1608







-
-
-
-
+
-




-
+












-
+









-
+














-
+







  sqlite3_stmt *pStmt, 
  int i, 
  const void *zData, 
  sqlite3_uint64 nData, 
  void (*xDel)(void*)
){
  assert( xDel!=SQLITE_DYNAMIC );
  if( nData>0x7fffffff ){
    return invokeValueDestructor(zData, xDel, 0);
  }else{
    return bindText(pStmt, i, zData, (int)nData, xDel, 0);
  return bindText(pStmt, i, zData, nData, xDel, 0);
  }
}
int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){
  int rc;
  Vdbe *p = (Vdbe *)pStmt;
  rc = vdbeUnbind(p, i);
  rc = vdbeUnbind(p, (u32)(i-1));
  if( rc==SQLITE_OK ){
    sqlite3VdbeMemSetDouble(&p->aVar[i-1], rValue);
    sqlite3_mutex_leave(p->db->mutex);
  }
  return rc;
}
int sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){
  return sqlite3_bind_int64(p, i, (i64)iValue);
}
int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){
  int rc;
  Vdbe *p = (Vdbe *)pStmt;
  rc = vdbeUnbind(p, i);
  rc = vdbeUnbind(p, (u32)(i-1));
  if( rc==SQLITE_OK ){
    sqlite3VdbeMemSetInt64(&p->aVar[i-1], iValue);
    sqlite3_mutex_leave(p->db->mutex);
  }
  return rc;
}
int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){
  int rc;
  Vdbe *p = (Vdbe*)pStmt;
  rc = vdbeUnbind(p, i);
  rc = vdbeUnbind(p, (u32)(i-1));
  if( rc==SQLITE_OK ){
    sqlite3_mutex_leave(p->db->mutex);
  }
  return rc;
}
int sqlite3_bind_pointer(
  sqlite3_stmt *pStmt,
  int i,
  void *pPtr,
  const char *zPTtype,
  void (*xDestructor)(void*)
){
  int rc;
  Vdbe *p = (Vdbe*)pStmt;
  rc = vdbeUnbind(p, i);
  rc = vdbeUnbind(p, (u32)(i-1));
  if( rc==SQLITE_OK ){
    sqlite3VdbeMemSetPointer(&p->aVar[i-1], pPtr, zPTtype, xDestructor);
    sqlite3_mutex_leave(p->db->mutex);
  }else if( xDestructor ){
    xDestructor(pPtr);
  }
  return rc;
1433
1434
1435
1436
1437
1438
1439
1440

1441
1442
1443
1444

1445

1446
1447
1448
1449
1450
1451
1452

1453
1454
1455

1456
1457
1458
1459
1460
1461
1462
1463
1464
1465

1466



1467
1468
1469
1470
1471
1472
1473
1621
1622
1623
1624
1625
1626
1627

1628


1629

1630
1631
1632
1633
1634
1635
1636
1637
1638

1639
1640
1641

1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653

1654
1655
1656
1657
1658
1659
1660
1661
1662
1663







-
+
-
-

-
+

+






-
+


-
+










+
-
+
+
+







  int i, 
  const char *zData, 
  sqlite3_uint64 nData, 
  void (*xDel)(void*),
  unsigned char enc
){
  assert( xDel!=SQLITE_DYNAMIC );
  if( nData>0x7fffffff ){
  if( enc!=SQLITE_UTF8 ){
    return invokeValueDestructor(zData, xDel, 0);
  }else{
    if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
    return bindText(pStmt, i, zData, (int)nData, xDel, enc);
    nData &= ~(u16)1;
  }
  return bindText(pStmt, i, zData, nData, xDel, enc);
}
#ifndef SQLITE_OMIT_UTF16
int sqlite3_bind_text16(
  sqlite3_stmt *pStmt, 
  int i, 
  const void *zData, 
  int nData, 
  int n, 
  void (*xDel)(void*)
){
  return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF16NATIVE);
  return bindText(pStmt, i, zData, n & ~(u64)1, xDel, SQLITE_UTF16NATIVE);
}
#endif /* SQLITE_OMIT_UTF16 */
int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){
  int rc;
  switch( sqlite3_value_type((sqlite3_value*)pValue) ){
    case SQLITE_INTEGER: {
      rc = sqlite3_bind_int64(pStmt, i, pValue->u.i);
      break;
    }
    case SQLITE_FLOAT: {
      assert( pValue->flags & (MEM_Real|MEM_IntReal) );
      rc = sqlite3_bind_double(pStmt, i, pValue->u.r);
      rc = sqlite3_bind_double(pStmt, i, 
          (pValue->flags & MEM_Real) ? pValue->u.r : (double)pValue->u.i
      );
      break;
    }
    case SQLITE_BLOB: {
      if( pValue->flags & MEM_Zero ){
        rc = sqlite3_bind_zeroblob(pStmt, i, pValue->u.nZero);
      }else{
        rc = sqlite3_bind_blob(pStmt, i, pValue->z, pValue->n,SQLITE_TRANSIENT);
1485
1486
1487
1488
1489
1490
1491
1492

1493

1494



1495
1496
1497
1498
1499
1500
1501
1675
1676
1677
1678
1679
1680
1681

1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695







-
+

+

+
+
+







    }
  }
  return rc;
}
int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){
  int rc;
  Vdbe *p = (Vdbe *)pStmt;
  rc = vdbeUnbind(p, i);
  rc = vdbeUnbind(p, (u32)(i-1));
  if( rc==SQLITE_OK ){
#ifndef SQLITE_OMIT_INCRBLOB
    sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n);
#else
    rc = sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n);
#endif
    sqlite3_mutex_leave(p->db->mutex);
  }
  return rc;
}
int sqlite3_bind_zeroblob64(sqlite3_stmt *pStmt, int i, sqlite3_uint64 n){
  int rc;
  Vdbe *p = (Vdbe *)pStmt;
1606
1607
1608
1609
1610
1611
1612








1613
1614
1615
1616
1617
1618
1619

1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640

1641
1642
1643
1644
1645
1646
1647
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







+
+
+
+
+
+
+
+






-
+




















-
+







/*
** Return true if the prepared statement is guaranteed to not modify the
** database.
*/
int sqlite3_stmt_readonly(sqlite3_stmt *pStmt){
  return pStmt ? ((Vdbe*)pStmt)->readOnly : 1;
}

/*
** Return 1 if the statement is an EXPLAIN and return 2 if the
** statement is an EXPLAIN QUERY PLAN
*/
int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt){
  return pStmt ? ((Vdbe*)pStmt)->explain : 0;
}

/*
** Return true if the prepared statement is in need of being reset.
*/
int sqlite3_stmt_busy(sqlite3_stmt *pStmt){
  Vdbe *v = (Vdbe*)pStmt;
  return v!=0 && v->magic==VDBE_MAGIC_RUN && v->pc>=0;
  return v!=0 && v->eVdbeState==VDBE_RUN_STATE;
}

/*
** Return a pointer to the next prepared statement after pStmt associated
** with database connection pDb.  If pStmt is NULL, return the first
** prepared statement for the database connection.  Return NULL if there
** are no more.
*/
sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt){
  sqlite3_stmt *pNext;
#ifdef SQLITE_ENABLE_API_ARMOR
  if( !sqlite3SafetyCheckOk(pDb) ){
    (void)SQLITE_MISUSE_BKPT;
    return 0;
  }
#endif
  sqlite3_mutex_enter(pDb->mutex);
  if( pStmt==0 ){
    pNext = (sqlite3_stmt*)pDb->pVdbe;
  }else{
    pNext = (sqlite3_stmt*)((Vdbe*)pStmt)->pNext;
    pNext = (sqlite3_stmt*)((Vdbe*)pStmt)->pVNext;
  }
  sqlite3_mutex_leave(pDb->mutex);
  return pNext;
}

/*
** Return the value of a status counter for a prepared statement
1658
1659
1660
1661
1662
1663
1664


1665

1666
1667

1668
1669
1670
1671
1672
1673
1674
1860
1861
1862
1863
1864
1865
1866
1867
1868

1869

1870
1871
1872
1873
1874
1875
1876
1877
1878







+
+
-
+
-

+







  }
#endif
  if( op==SQLITE_STMTSTATUS_MEMUSED ){
    sqlite3 *db = pVdbe->db;
    sqlite3_mutex_enter(db->mutex);
    v = 0;
    db->pnBytesFreed = (int*)&v;
    assert( db->lookaside.pEnd==db->lookaside.pTrueEnd );
    db->lookaside.pEnd = db->lookaside.pStart;
    sqlite3VdbeClearObject(db, pVdbe);
    sqlite3VdbeDelete(pVdbe);
    sqlite3DbFree(db, pVdbe);
    db->pnBytesFreed = 0;
    db->lookaside.pEnd = db->lookaside.pTrueEnd;
    sqlite3_mutex_leave(db->mutex);
  }else{
    v = pVdbe->aCounter[op];
    if( resetFlag ) pVdbe->aCounter[op] = 0;
  }
  return (int)v;
}
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
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







-
+











+







  /* Test that this call is being made from within an SQLITE_DELETE or
  ** SQLITE_UPDATE pre-update callback, and that iIdx is within range. */
  if( !p || p->op==SQLITE_INSERT ){
    rc = SQLITE_MISUSE_BKPT;
    goto preupdate_old_out;
  }
  if( p->pPk ){
    iIdx = sqlite3ColumnOfIndex(p->pPk, iIdx);
    iIdx = sqlite3TableColumnToIndex(p->pPk, iIdx);
  }
  if( iIdx>=p->pCsr->nField || iIdx<0 ){
    rc = SQLITE_RANGE;
    goto preupdate_old_out;
  }

  /* If the old.* record has not yet been loaded into memory, do so now. */
  if( p->pUnpacked==0 ){
    u32 nRec;
    u8 *aRec;

    assert( p->pCsr->eCurType==CURTYPE_BTREE );
    nRec = sqlite3BtreePayloadSize(p->pCsr->uc.pCursor);
    aRec = sqlite3DbMallocRaw(db, nRec);
    if( !aRec ) goto preupdate_old_out;
    rc = sqlite3BtreePayload(p->pCsr->uc.pCursor, 0, nRec, aRec);
    if( rc==SQLITE_OK ){
      p->pUnpacked = vdbeUnpackRecord(&p->keyinfo, nRec, aRec);
      if( !p->pUnpacked ) rc = SQLITE_NOMEM;
1788
1789
1790
1791
1792
1793
1794

1795


1796
1797
1798
1799
1800
1801
1802
1993
1994
1995
1996
1997
1998
1999
2000

2001
2002
2003
2004
2005
2006
2007
2008
2009







+
-
+
+








  pMem = *ppValue = &p->pUnpacked->aMem[iIdx];
  if( iIdx==p->pTab->iPKey ){
    sqlite3VdbeMemSetInt64(pMem, p->iKey1);
  }else if( iIdx>=p->pUnpacked->nField ){
    *ppValue = (sqlite3_value *)columnNullValue();
  }else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){
    if( pMem->flags & (MEM_Int|MEM_IntReal) ){
    if( pMem->flags & MEM_Int ){
      testcase( pMem->flags & MEM_Int );
      testcase( pMem->flags & MEM_IntReal );
      sqlite3VdbeMemRealify(pMem);
    }
  }

 preupdate_old_out:
  sqlite3Error(db, rc);
  return sqlite3ApiExit(db, rc);
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
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







+
+
+
+
+
+
+
+
+
+
+
















-
+







** 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){
  PreUpdate *p = db->pPreUpdate;
  int rc = SQLITE_OK;
  Mem *pMem;

  if( !p || p->op==SQLITE_DELETE ){
    rc = SQLITE_MISUSE_BKPT;
    goto preupdate_new_out;
  }
  if( p->pPk && p->op!=SQLITE_UPDATE ){
    iIdx = sqlite3ColumnOfIndex(p->pPk, iIdx);
    iIdx = sqlite3TableColumnToIndex(p->pPk, iIdx);
  }
  if( iIdx>=p->pCsr->nField || iIdx<0 ){
    rc = SQLITE_RANGE;
    goto preupdate_new_out;
  }

  if( p->op==SQLITE_INSERT ){
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
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







-
+

-
+

+




+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
+
+
-
+
+



+
+
+
-
+
+







}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */

#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
/*
** Return status data for a single loop within query pStmt.
*/
int sqlite3_stmt_scanstatus(
int sqlite3_stmt_scanstatus_v2(
  sqlite3_stmt *pStmt,            /* Prepared statement being queried */
  int idx,                        /* Index of loop to report on */
  int iScan,                      /* Index of loop to report on */
  int iScanStatusOp,              /* Which metric to return */
  int flags,
  void *pOut                      /* OUT: Write the answer here */
){
  Vdbe *p = (Vdbe*)pStmt;
  ScanStatus *pScan;
  int idx;

  if( iScan<0 ){
    int ii;
    if( iScanStatusOp==SQLITE_SCANSTAT_NCYCLE ){
      i64 res = 0;
      for(ii=0; ii<p->nOp; ii++){
        res += p->aOp[ii].nCycle;
      }
      *(i64*)pOut = res;
      return 0;
    }
  if( idx<0 || idx>=p->nScan ) return 1;
  pScan = &p->aScan[idx];
    return 1;
  }
  if( flags & SQLITE_SCANSTAT_COMPLEX ){
    idx = iScan;
    pScan = &p->aScan[idx];
  }else{
    /* If the COMPLEX flag is clear, then this function must ignore any 
    ** ScanStatus structures with ScanStatus.addrLoop set to 0. */
    for(idx=0; idx<p->nScan; idx++){
      pScan = &p->aScan[idx];
      if( pScan->zName ){
        iScan--;
        if( iScan<0 ) break;
      }
    }
  }
  if( idx>=p->nScan ) return 1;

  switch( iScanStatusOp ){
    case SQLITE_SCANSTAT_NLOOP: {
      if( pScan->addrLoop>0 ){
        *(sqlite3_int64*)pOut = p->aOp[pScan->addrLoop].nExec;
      }else{
      *(sqlite3_int64*)pOut = p->anExec[pScan->addrLoop];
        *(sqlite3_int64*)pOut = -1;
      }
      break;
    }
    case SQLITE_SCANSTAT_NVISIT: {
      if( pScan->addrVisit>0 ){
        *(sqlite3_int64*)pOut = p->aOp[pScan->addrVisit].nExec;
      }else{
      *(sqlite3_int64*)pOut = p->anExec[pScan->addrVisit];
        *(sqlite3_int64*)pOut = -1;
      }
      break;
    }
    case SQLITE_SCANSTAT_EST: {
      double r = 1.0;
      LogEst x = pScan->nEst;
      while( x<100 ){
        x += 10;
1956
1957
1958
1959
1960
1961
1962







































1963
1964
1965
1966
1967
1968
1969












1970
1971
1972
1973
1974
1975

1976
1977






1978
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282


2283
2284
2285
2286
2287
2288
2289







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







+
+
+
+
+
+
+
+
+
+
+
+






+
-
-
+
+
+
+
+
+

    case SQLITE_SCANSTAT_SELECTID: {
      if( pScan->addrExplain ){
        *(int*)pOut = p->aOp[ pScan->addrExplain ].p1;
      }else{
        *(int*)pOut = -1;
      }
      break;
    }
    case SQLITE_SCANSTAT_PARENTID: {
      if( pScan->addrExplain ){
        *(int*)pOut = p->aOp[ pScan->addrExplain ].p2;
      }else{
        *(int*)pOut = -1;
      }
      break;
    }
    case SQLITE_SCANSTAT_NCYCLE: {
      i64 res = 0;
      if( pScan->aAddrRange[0]==0 ){
        res = -1;
      }else{
        int ii;
        for(ii=0; ii<ArraySize(pScan->aAddrRange); ii+=2){
          int iIns = pScan->aAddrRange[ii];
          int iEnd = pScan->aAddrRange[ii+1];
          if( iIns==0 ) break;
          if( iIns>0 ){
            while( iIns<=iEnd ){
              res += p->aOp[iIns].nCycle;
              iIns++;
            }
          }else{
            int iOp;
            for(iOp=0; iOp<p->nOp; iOp++){
              Op *pOp = &p->aOp[iOp];
              if( pOp->p1!=iEnd ) continue;
              if( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_NCYCLE)==0 ){
                continue;
              }
              res += p->aOp[iOp].nCycle;
            }
          }
        }
      }
      *(i64*)pOut = res;
      break;
    }
    default: {
      return 1;
    }
  }
  return 0;
}

/*
** Return status data for a single loop within query pStmt.
*/
int sqlite3_stmt_scanstatus(
  sqlite3_stmt *pStmt,            /* Prepared statement being queried */
  int iScan,                      /* Index of loop to report on */
  int iScanStatusOp,              /* Which metric to return */
  void *pOut                      /* OUT: Write the answer here */
){
  return sqlite3_stmt_scanstatus_v2(pStmt, iScan, iScanStatusOp, 0, pOut);
}

/*
** Zero all counters associated with the sqlite3_stmt_scanstatus() data.
*/
void sqlite3_stmt_scanstatus_reset(sqlite3_stmt *pStmt){
  Vdbe *p = (Vdbe*)pStmt;
  int ii;
  memset(p->anExec, 0, p->nOp * sizeof(i64));
}
  for(ii=0; ii<p->nOp; ii++){
    Op *pOp = &p->aOp[ii];
    pOp->nExec = 0;
    pOp->nCycle = 0;
  }
}
#endif /* SQLITE_ENABLE_STMT_SCANSTATUS */

Changes to src/vdbeaux.c.

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
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







+
+
+
+











-
+

-
-
+
+

-
+




-
+




+
+
+
+
+
+
+







*************************************************************************
** This file contains code used for creating, destroying, and populating
** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.) 
*/
#include "sqliteInt.h"
#include "vdbeInt.h"

/* Forward references */
static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef);
static void vdbeFreeOpArray(sqlite3 *, Op *, int);

/*
** Create a new virtual database engine.
*/
Vdbe *sqlite3VdbeCreate(Parse *pParse){
  sqlite3 *db = pParse->db;
  Vdbe *p;
  p = sqlite3DbMallocRawNN(db, sizeof(Vdbe) );
  if( p==0 ) return 0;
  memset(&p->aOp, 0, sizeof(Vdbe)-offsetof(Vdbe,aOp));
  p->db = db;
  if( db->pVdbe ){
    db->pVdbe->pPrev = p;
    db->pVdbe->ppVPrev = &p->pVNext;
  }
  p->pNext = db->pVdbe;
  p->pPrev = 0;
  p->pVNext = db->pVdbe;
  p->ppVPrev = &db->pVdbe;
  db->pVdbe = p;
  p->magic = VDBE_MAGIC_INIT;
  assert( p->eVdbeState==VDBE_INIT_STATE );
  p->pParse = pParse;
  pParse->pVdbe = p;
  assert( pParse->aLabel==0 );
  assert( pParse->nLabel==0 );
  assert( pParse->nOpAlloc==0 );
  assert( p->nOpAlloc==0 );
  assert( pParse->szOpAlloc==0 );
  sqlite3VdbeAddOp2(p, OP_Init, 0, 1);
  return p;
}

/*
** Return the Parse object that owns a Vdbe object.
*/
Parse *sqlite3VdbeParser(Vdbe *p){
  return p->pParse;
}

/*
** Change the error string stored in Vdbe.zErrMsg
*/
void sqlite3VdbeError(Vdbe *p, const char *zFormat, ...){
  va_list ap;
  sqlite3DbFree(p->db, p->zErrMsg);
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
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







-
+
+
+
+
+
+
+
+


-
+





-
-
-
-
-
-
+
+
+
+
+
+



-
+
















-
+















+
-
+

+
-
+









-
-
+
+



-
+








-
+
+
+
+
+
+
+
+

-
+

+
+







    if( strcmp(zId, pStr->z)==0 ) return 1;
  }
  return 0;
}
#endif

/*
** Swap all content between two VDBE structures.
** Swap byte-code between two VDBE structures.
**
** This happens after pB was previously run and returned
** SQLITE_SCHEMA.  The statement was then reprepared in pA.
** This routine transfers the new bytecode in pA over to pB
** so that pB can be run again.  The old pB byte code is
** moved back to pA so that it will be cleaned up when pA is
** finalized.
*/
void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){
  Vdbe tmp, *pTmp;
  Vdbe tmp, *pTmp, **ppTmp;
  char *zTmp;
  assert( pA->db==pB->db );
  tmp = *pA;
  *pA = *pB;
  *pB = tmp;
  pTmp = pA->pNext;
  pA->pNext = pB->pNext;
  pB->pNext = pTmp;
  pTmp = pA->pPrev;
  pA->pPrev = pB->pPrev;
  pB->pPrev = pTmp;
  pTmp = pA->pVNext;
  pA->pVNext = pB->pVNext;
  pB->pVNext = pTmp;
  ppTmp = pA->ppVPrev;
  pA->ppVPrev = pB->ppVPrev;
  pB->ppVPrev = ppTmp;
  zTmp = pA->zSql;
  pA->zSql = pB->zSql;
  pB->zSql = zTmp;
#if 0
#ifdef SQLITE_ENABLE_NORMALIZE
  zTmp = pA->zNormSql;
  pA->zNormSql = pB->zNormSql;
  pB->zNormSql = zTmp;
#endif
  pB->expmask = pA->expmask;
  pB->prepFlags = pA->prepFlags;
  memcpy(pB->aCounter, pA->aCounter, sizeof(pB->aCounter));
  pB->aCounter[SQLITE_STMTSTATUS_REPREPARE]++;
}

/*
** Resize the Vdbe.aOp array so that it is at least nOp elements larger 
** than its current size. nOp is guaranteed to be less than or equal
** to 1024/sizeof(Op).
**
** If an out-of-memory error occurs while resizing the array, return
** SQLITE_NOMEM. In this case Vdbe.aOp and Parse.nOpAlloc remain 
** SQLITE_NOMEM. In this case Vdbe.aOp and Vdbe.nOpAlloc remain 
** unchanged (this is so that any opcodes already allocated can be 
** correctly deallocated along with the rest of the Vdbe).
*/
static int growOpArray(Vdbe *v, int nOp){
  VdbeOp *pNew;
  Parse *p = v->pParse;

  /* The SQLITE_TEST_REALLOC_STRESS compile-time option is designed to force
  ** more frequent reallocs and hence provide more opportunities for 
  ** simulated OOM faults.  SQLITE_TEST_REALLOC_STRESS is generally used
  ** during testing only.  With SQLITE_TEST_REALLOC_STRESS grow the op array
  ** by the minimum* amount required until the size reaches 512.  Normal
  ** operation (without SQLITE_TEST_REALLOC_STRESS) is to double the current
  ** size of the op array or add 1KB of space, whichever is smaller. */
#ifdef SQLITE_TEST_REALLOC_STRESS
  sqlite3_int64 nNew = (v->nOpAlloc>=512 ? 2*(sqlite3_int64)v->nOpAlloc
  int nNew = (p->nOpAlloc>=512 ? p->nOpAlloc*2 : p->nOpAlloc+nOp);
                        : (sqlite3_int64)v->nOpAlloc+nOp);
#else
  sqlite3_int64 nNew = (v->nOpAlloc ? 2*(sqlite3_int64)v->nOpAlloc
  int nNew = (p->nOpAlloc ? p->nOpAlloc*2 : (int)(1024/sizeof(Op)));
                        : (sqlite3_int64)(1024/sizeof(Op)));
  UNUSED_PARAMETER(nOp);
#endif

  /* Ensure that the size of a VDBE does not grow too large */
  if( nNew > p->db->aLimit[SQLITE_LIMIT_VDBE_OP] ){
    sqlite3OomFault(p->db);
    return SQLITE_NOMEM;
  }

  assert( nOp<=(1024/sizeof(Op)) );
  assert( nNew>=(p->nOpAlloc+nOp) );
  assert( nOp<=(int)(1024/sizeof(Op)) );
  assert( nNew>=(v->nOpAlloc+nOp) );
  pNew = sqlite3DbRealloc(p->db, v->aOp, nNew*sizeof(Op));
  if( pNew ){
    p->szOpAlloc = sqlite3DbMallocSize(p->db, pNew);
    p->nOpAlloc = p->szOpAlloc/sizeof(Op);
    v->nOpAlloc = p->szOpAlloc/sizeof(Op);
    v->aOp = pNew;
  }
  return (pNew ? SQLITE_OK : SQLITE_NOMEM_BKPT);
}

#ifdef SQLITE_DEBUG
/* This routine is just a convenient place to set a breakpoint that will
** fire after each opcode is inserted and displayed using
** "PRAGMA vdbe_addoptrace=on".
** "PRAGMA vdbe_addoptrace=on".  Parameters "pc" (program counter) and
** pOp are available to make the breakpoint conditional.
**
** Other useful labels for breakpoints include:
**   test_trace_breakpoint(pc,pOp)
**   sqlite3CorruptError(lineno)
**   sqlite3MisuseError(lineno)
**   sqlite3CantopenError(lineno)
*/
static void test_addop_breakpoint(void){
static void test_addop_breakpoint(int pc, Op *pOp){
  static int n = 0;
  (void)pc;
  (void)pOp;
  n++;
}
#endif

/*
** Add a new instruction to the list of instructions current in the
** VDBE.  Return the address of the new instruction.
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
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







-
+

-
+







-
+

-
+


+


+









+
+
+
+




-
+


-
-
-
-







**    p1, p2, p3      Operands
**
** Use the sqlite3VdbeResolveLabel() function to fix an address and
** the sqlite3VdbeChangeP4() function to change the value of the P4
** operand.
*/
static SQLITE_NOINLINE int growOp3(Vdbe *p, int op, int p1, int p2, int p3){
  assert( p->pParse->nOpAlloc<=p->nOp );
  assert( p->nOpAlloc<=p->nOp );
  if( growOpArray(p, 1) ) return 1;
  assert( p->pParse->nOpAlloc>p->nOp );
  assert( p->nOpAlloc>p->nOp );
  return sqlite3VdbeAddOp3(p, op, p1, p2, p3);
}
int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
  int i;
  VdbeOp *pOp;

  i = p->nOp;
  assert( p->magic==VDBE_MAGIC_INIT );
  assert( p->eVdbeState==VDBE_INIT_STATE );
  assert( op>=0 && op<0xff );
  if( p->pParse->nOpAlloc<=i ){
  if( p->nOpAlloc<=i ){
    return growOp3(p, op, p1, p2, p3);
  }
  assert( p->aOp!=0 );
  p->nOp++;
  pOp = &p->aOp[i];
  assert( pOp!=0 );
  pOp->opcode = (u8)op;
  pOp->p5 = 0;
  pOp->p1 = p1;
  pOp->p2 = p2;
  pOp->p3 = p3;
  pOp->p4.p = 0;
  pOp->p4type = P4_NOTUSED;
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
  pOp->zComment = 0;
#endif
#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE)
  pOp->nExec = 0;
  pOp->nCycle = 0;
#endif
#ifdef SQLITE_DEBUG
  if( p->db->flags & SQLITE_VdbeAddopTrace ){
    sqlite3VdbePrintOp(0, i, &p->aOp[i]);
    test_addop_breakpoint();
    test_addop_breakpoint(i, &p->aOp[i]);
  }
#endif
#ifdef VDBE_PROFILE
  pOp->cycles = 0;
  pOp->cnt = 0;
#endif
#ifdef SQLITE_VDBE_COVERAGE
  pOp->iSrcLine = 0;
#endif
  return i;
}
int sqlite3VdbeAddOp0(Vdbe *p, int op){
  return sqlite3VdbeAddOp3(p, op, 0, 0, 0);
314
315
316
317
318
319
320












































321
322
323
324
325
326
327
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  const char *zP4,    /* The P4 operand */
  int p4type          /* P4 operand type */
){
  int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3);
  sqlite3VdbeChangeP4(p, addr, zP4, p4type);
  return addr;
}

/*
** Add an OP_Function or OP_PureFunc opcode.
**
** The eCallCtx argument is information (typically taken from Expr.op2)
** that describes the calling context of the function.  0 means a general
** function call.  NC_IsCheck means called by a check constraint,
** NC_IdxExpr means called as part of an index expression.  NC_PartIdx
** means in the WHERE clause of a partial index.  NC_GenCol means called
** while computing a generated column value.  0 is the usual case.
*/
int sqlite3VdbeAddFunctionCall(
  Parse *pParse,        /* Parsing context */
  int p1,               /* Constant argument mask */
  int p2,               /* First argument register */
  int p3,               /* Register into which results are written */
  int nArg,             /* Number of argument */
  const FuncDef *pFunc, /* The function to be invoked */
  int eCallCtx          /* Calling context */
){
  Vdbe *v = pParse->pVdbe;
  int nByte;
  int addr;
  sqlite3_context *pCtx;
  assert( v );
  nByte = sizeof(*pCtx) + (nArg-1)*sizeof(sqlite3_value*);
  pCtx = sqlite3DbMallocRawNN(pParse->db, nByte);
  if( pCtx==0 ){
    assert( pParse->db->mallocFailed );
    freeEphemeralFunction(pParse->db, (FuncDef*)pFunc);
    return 0;
  }
  pCtx->pOut = 0;
  pCtx->pFunc = (FuncDef*)pFunc;
  pCtx->pVdbe = 0;
  pCtx->isError = 0;
  pCtx->argc = nArg;
  pCtx->iOp = sqlite3VdbeCurrentAddr(v);
  addr = sqlite3VdbeAddOp4(v, eCallCtx ? OP_PureFunc : OP_Function,
                           p1, p2, p3, (char*)pCtx, P4_FUNCCTX);
  sqlite3VdbeChangeP5(v, eCallCtx & NC_SelfRef);
  sqlite3MayAbort(pParse);
  return addr;
}

/*
** Add an opcode that includes the p4 value with a P4_INT64 or
** P4_REAL type.
*/
int sqlite3VdbeAddOp4Dup8(
  Vdbe *p,            /* Add the opcode to this VM */
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
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







+
+
+
+
+
+
+
+
+
+
+






-
-
+
+
+
+
+
+
+
+









-
+

+
+
-
-
+
+
+
+
+






+












-
+


+

+







int sqlite3VdbeExplainParent(Parse *pParse){
  VdbeOp *pOp;
  if( pParse->addrExplain==0 ) return 0;
  pOp = sqlite3VdbeGetOp(pParse->pVdbe, pParse->addrExplain);
  return pOp->p2;
}

/*
** Set a debugger breakpoint on the following routine in order to
** monitor the EXPLAIN QUERY PLAN code generation.
*/
#if defined(SQLITE_DEBUG)
void sqlite3ExplainBreakpoint(const char *z1, const char *z2){
  (void)z1;
  (void)z2;
}
#endif

/*
** Add a new OP_Explain opcode.
**
** If the bPush flag is true, then make this opcode the parent for
** subsequent Explains until sqlite3VdbeExplainPop() is called.
*/
void sqlite3VdbeExplain(Parse *pParse, u8 bPush, const char *zFmt, ...){
  if( pParse->explain==2 ){
int sqlite3VdbeExplain(Parse *pParse, u8 bPush, const char *zFmt, ...){
  int addr = 0;
#if !defined(SQLITE_DEBUG) && !defined(SQLITE_ENABLE_STMT_SCANSTATUS)
  /* Always include the OP_Explain opcodes if SQLITE_DEBUG is defined.
  ** But omit them (for performance) during production builds */
  if( pParse->explain==2 )
#endif
  {
    char *zMsg;
    Vdbe *v;
    va_list ap;
    int iThis;
    va_start(ap, zFmt);
    zMsg = sqlite3VMPrintf(pParse->db, zFmt, ap);
    va_end(ap);
    v = pParse->pVdbe;
    iThis = v->nOp;
    sqlite3VdbeAddOp4(v, OP_Explain, iThis, pParse->addrExplain, 0,
    addr = sqlite3VdbeAddOp4(v, OP_Explain, iThis, pParse->addrExplain, 0,
                      zMsg, P4_DYNAMIC);
    sqlite3ExplainBreakpoint(bPush?"PUSH":"", sqlite3VdbeGetLastOp(v)->p4.z);
    if( bPush){
    if( bPush) pParse->addrExplain = iThis;
  }
      pParse->addrExplain = iThis;
    }
    sqlite3VdbeScanStatus(v, iThis, 0, 0, 0, 0);
  }
  return addr;
}

/*
** Pop the EXPLAIN QUERY PLAN stack one level.
*/
void sqlite3VdbeExplainPop(Parse *pParse){
  sqlite3ExplainBreakpoint("POP", 0);
  pParse->addrExplain = sqlite3VdbeExplainParent(pParse);
}
#endif /* SQLITE_OMIT_EXPLAIN */

/*
** Add an OP_ParseSchema opcode.  This routine is broken out from
** sqlite3VdbeAddOp4() since it needs to also needs to mark all btrees
** as having been used.
**
** The zWhere string must have been obtained from sqlite3_malloc().
** This routine will take ownership of the allocated memory.
*/
void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere){
void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere, u16 p5){
  int j;
  sqlite3VdbeAddOp4(p, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC);
  sqlite3VdbeChangeP5(p, p5);
  for(j=0; j<p->db->nDb; j++) sqlite3VdbeUsesBtree(p, j);
  sqlite3MayAbort(p->pParse);
}

/*
** Add an opcode that includes the p4 value as an integer.
*/
int sqlite3VdbeAddOp4Int(
  Vdbe *p,            /* Add the opcode to this VM */
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
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







+
+

+
-
+
+
+
+
+
+
+
+
+

-
+
-
-
+
-
-
-
-
-
-
-
-
-







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
-
+
+

-

-
-
-
+
+
+

+
+
+









-
+



-
+


+
+
+
-
+
+
+
+







** the label is resolved to a specific address, the VDBE will scan
** through its operation list and change all values of P2 which match
** the label into the resolved address.
**
** The VDBE knows that a P2 value is a label because labels are
** always negative and P2 values are suppose to be non-negative.
** Hence, a negative P2 value is a label that has yet to be resolved.
** (Later:) This is only true for opcodes that have the OPFLG_JUMP
** property.
**
** Variable usage notes:
** Zero is returned if a malloc() fails.
**
**     Parse.aLabel[x]     Stores the address that the x-th label resolves
**                         into.  For testing (SQLITE_DEBUG), unresolved
**                         labels stores -1, but that is not required.
**     Parse.nLabelAlloc   Number of slots allocated to Parse.aLabel[]
**     Parse.nLabel        The *negative* of the number of labels that have
**                         been issued.  The negative is stored because
**                         that gives a performance improvement over storing
**                         the equivalent positive value.
*/
int sqlite3VdbeMakeLabel(Vdbe *v){
int sqlite3VdbeMakeLabel(Parse *pParse){
  Parse *p = v->pParse;
  int i = p->nLabel++;
  return --pParse->nLabel;
  assert( v->magic==VDBE_MAGIC_INIT );
  if( (i & (i-1))==0 ){
    p->aLabel = sqlite3DbReallocOrFree(p->db, p->aLabel, 
                                       (i*2+1)*sizeof(p->aLabel[0]));
  }
  if( p->aLabel ){
    p->aLabel[i] = -1;
  }
  return ADDR(i);
}

/*
** Resolve label "x" to be the address of the next instruction to
** be inserted.  The parameter "x" must have been obtained from
** a prior call to sqlite3VdbeMakeLabel().
*/
static SQLITE_NOINLINE void resizeResolveLabel(Parse *p, Vdbe *v, int j){
  int nNewSize = 10 - p->nLabel;
  p->aLabel = sqlite3DbReallocOrFree(p->db, p->aLabel,
                     nNewSize*sizeof(p->aLabel[0]));
  if( p->aLabel==0 ){
    p->nLabelAlloc = 0;
  }else{
#ifdef SQLITE_DEBUG
    int i;
    for(i=p->nLabelAlloc; i<nNewSize; i++) p->aLabel[i] = -1;
#endif
    if( nNewSize>=100 && (nNewSize/100)>(p->nLabelAlloc/100) ){
      sqlite3ProgressCheck(p);
    }
    p->nLabelAlloc = nNewSize;
    p->aLabel[j] = v->nOp;
  }
}
void sqlite3VdbeResolveLabel(Vdbe *v, int x){
  Parse *p = v->pParse;
  int j = ADDR(x);
  assert( v->magic==VDBE_MAGIC_INIT );
  assert( j<p->nLabel );
  assert( v->eVdbeState==VDBE_INIT_STATE );
  assert( j<-p->nLabel );
  assert( j>=0 );
  if( p->aLabel ){
#ifdef SQLITE_DEBUG
    if( p->db->flags & SQLITE_VdbeAddopTrace ){
      printf("RESOLVE LABEL %d to %d\n", x, v->nOp);
    }
  if( p->db->flags & SQLITE_VdbeAddopTrace ){
    printf("RESOLVE LABEL %d to %d\n", x, v->nOp);
  }
#endif
  if( p->nLabelAlloc + p->nLabel < 0 ){
    resizeResolveLabel(p,v,j);
  }else{
    assert( p->aLabel[j]==(-1) ); /* Labels may only be resolved once */
    p->aLabel[j] = v->nOp;
  }
}

/*
** Mark the VDBE as one that can only be run one time.
*/
void sqlite3VdbeRunOnlyOnce(Vdbe *p){
  p->runOnlyOnce = 1;
  sqlite3VdbeAddOp2(p, OP_Expire, 1, 1);
}

/*
** Mark the VDBE as one that can only be run multiple times.
** Mark the VDBE as one that can be run multiple times.
*/
void sqlite3VdbeReusable(Vdbe *p){
  int i;
  for(i=1; ALWAYS(i<p->nOp); i++){
    if( ALWAYS(p->aOp[i].opcode==OP_Expire) ){
  p->runOnlyOnce = 0;
      p->aOp[1].opcode = OP_Noop;
      break;
    }
  }
}

#ifdef SQLITE_DEBUG /* sqlite3AssertMayAbort() logic */

/*
** The following type and function are used to iterate through all opcodes
** in a Vdbe main program and each of the sub-programs (triggers) it may 
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
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







+
















+



+
+






+
+
+
+

-
+





+
+
+
+
+
+
+
+















-
+
+







** to be rolled back). This condition is true if the main program or any
** sub-programs contains any of the following:
**
**   *  OP_Halt with P1=SQLITE_CONSTRAINT and P2=OE_Abort.
**   *  OP_HaltIfNull with P1=SQLITE_CONSTRAINT and P2=OE_Abort.
**   *  OP_Destroy
**   *  OP_VUpdate
**   *  OP_VCreate
**   *  OP_VRename
**   *  OP_FkCounter with P2==0 (immediate foreign key constraint)
**   *  OP_CreateBtree/BTREE_INTKEY and OP_InitCoroutine 
**      (for CREATE TABLE AS SELECT ...)
**
** Then check that the value of Parse.mayAbort is true if an
** ABORT may be thrown, or false otherwise. Return true if it does
** match, or false otherwise. This function is intended to be used as
** part of an assert statement in the compiler. Similar to:
**
**   assert( sqlite3VdbeAssertMayAbort(pParse->pVdbe, pParse->mayAbort) );
*/
int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
  int hasAbort = 0;
  int hasFkCounter = 0;
  int hasCreateTable = 0;
  int hasCreateIndex = 0;
  int hasInitCoroutine = 0;
  Op *pOp;
  VdbeOpIter sIter;

  if( v==0 ) return 0;
  memset(&sIter, 0, sizeof(sIter));
  sIter.v = v;

  while( (pOp = opIterNext(&sIter))!=0 ){
    int opcode = pOp->opcode;
    if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename 
     || opcode==OP_VDestroy
     || opcode==OP_VCreate
     || opcode==OP_ParseSchema
     || opcode==OP_Function || opcode==OP_PureFunc
     || ((opcode==OP_Halt || opcode==OP_HaltIfNull) 
      && ((pOp->p1&0xff)==SQLITE_CONSTRAINT && pOp->p2==OE_Abort))
      && ((pOp->p1)!=SQLITE_OK && pOp->p2==OE_Abort))
    ){
      hasAbort = 1;
      break;
    }
    if( opcode==OP_CreateBtree && pOp->p3==BTREE_INTKEY ) hasCreateTable = 1;
    if( mayAbort ){
      /* hasCreateIndex may also be set for some DELETE statements that use
      ** OP_Clear. So this routine may end up returning true in the case 
      ** where a "DELETE FROM tbl" has a statement-journal but does not
      ** require one. This is not so bad - it is an inefficiency, not a bug. */
      if( opcode==OP_CreateBtree && pOp->p3==BTREE_BLOBKEY ) hasCreateIndex = 1;
      if( opcode==OP_Clear ) hasCreateIndex = 1;
    }
    if( opcode==OP_InitCoroutine ) hasInitCoroutine = 1;
#ifndef SQLITE_OMIT_FOREIGN_KEY
    if( opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1 ){
      hasFkCounter = 1;
    }
#endif
  }
  sqlite3DbFree(v->db, sIter.apSub);

  /* Return true if hasAbort==mayAbort. Or if a malloc failure occurred.
  ** If malloc failed, then the while() loop above may not have iterated
  ** through all opcodes and hasAbort may be set incorrectly. Return
  ** true for this case to prevent the assert() in the callers frame
  ** from failing.  */
  return ( v->db->mallocFailed || hasAbort==mayAbort || hasFkCounter
              || (hasCreateTable && hasInitCoroutine) );
        || (hasCreateTable && hasInitCoroutine) || hasCreateIndex
  );
}
#endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */

#ifdef SQLITE_DEBUG
/*
** Increment the nWrite counter in the VDBE if the cursor is not an
** ephemeral cursor, or if the cursor argument is NULL.
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
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
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992

993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006

1007
1008
1009
1010
1011
1012
1013
1014







-
+















-
-
+
+












-
+















-
+
-
-
-
-
-
-

-
-
-
-
-
-
-
-
+
-
-













+








-
+










-
+


+
+
-
-
+
+
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
+













-
+







**
** (2) Compute the maximum number of arguments used by any SQL function
**     and store that value in *pMaxFuncArgs.
**
** (3) Update the Vdbe.readOnly and Vdbe.bIsReader flags to accurately
**     indicate what the prepared statement actually does.
**
** (4) Initialize the p4.xAdvance pointer on opcodes that use it.
** (4) (discontinued)
**
** (5) Reclaim the memory allocated for storing labels.
**
** This routine will only function correctly if the mkopcodeh.tcl generator
** script numbers the opcodes correctly.  Changes to this routine must be
** coordinated with changes to mkopcodeh.tcl.
*/
static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
  int nMaxArgs = *pMaxFuncArgs;
  Op *pOp;
  Parse *pParse = p->pParse;
  int *aLabel = pParse->aLabel;
  p->readOnly = 1;
  p->bIsReader = 0;
  pOp = &p->aOp[p->nOp-1];
  while(1){

  assert( p->aOp[0].opcode==OP_Init );
  while( 1 /* Loop termates when it reaches the OP_Init opcode */ ){
    /* Only JUMP opcodes and the short list of special opcodes in the switch
    ** below need to be considered.  The mkopcodeh.tcl generator script groups
    ** all these opcodes together near the front of the opcode list.  Skip
    ** any opcode that does not need processing by virtual of the fact that
    ** it is larger than SQLITE_MX_JUMP_OPCODE, as a performance optimization.
    */
    if( pOp->opcode<=SQLITE_MX_JUMP_OPCODE ){
      /* NOTE: Be sure to update mkopcodeh.tcl when adding or removing
      ** cases from this switch! */
      switch( pOp->opcode ){
        case OP_Transaction: {
          if( pOp->p2!=0 ) p->readOnly = 0;
          /* fall thru */
          /* no break */ deliberate_fall_through
        }
        case OP_AutoCommit:
        case OP_Savepoint: {
          p->bIsReader = 1;
          break;
        }
#ifndef SQLITE_OMIT_WAL
        case OP_Checkpoint:
#endif
        case OP_Vacuum:
        case OP_JournalMode: {
          p->readOnly = 0;
          p->bIsReader = 1;
          break;
        }
        case OP_Next:
        case OP_Init: {
        case OP_SorterNext: {
          pOp->p4.xAdvance = sqlite3BtreeNext;
          pOp->p4type = P4_ADVANCE;
          /* The code generator never codes any of these opcodes as a jump
          ** to a label.  They are always coded as a jump backwards to a 
          ** known address */
          assert( pOp->p2>=0 );
          break;
        }
        case OP_Prev: {
          pOp->p4.xAdvance = sqlite3BtreePrevious;
          pOp->p4type = P4_ADVANCE;
          /* The code generator never codes any of these opcodes as a jump
          ** to a label.  They are always coded as a jump backwards to a 
          ** known address */
          goto resolve_p2_values_loop_exit;
          assert( pOp->p2>=0 );
          break;
        }
#ifndef SQLITE_OMIT_VIRTUALTABLE
        case OP_VUpdate: {
          if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;
          break;
        }
        case OP_VFilter: {
          int n;
          assert( (pOp - p->aOp) >= 3 );
          assert( pOp[-1].opcode==OP_Integer );
          n = pOp[-1].p1;
          if( n>nMaxArgs ) nMaxArgs = n;
          /* Fall through into the default case */
          /* no break */ deliberate_fall_through
        }
#endif
        default: {
          if( pOp->p2<0 ){
            /* The mkopcodeh.tcl script has so arranged things that the only
            ** non-jump opcodes less than SQLITE_MX_JUMP_CODE are guaranteed to
            ** have non-negative values for P2. */
            assert( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP)!=0 );
            assert( ADDR(pOp->p2)<pParse->nLabel );
            assert( ADDR(pOp->p2)<-pParse->nLabel );
            pOp->p2 = aLabel[ADDR(pOp->p2)];
          }
          break;
        }
      }
      /* The mkopcodeh.tcl script has so arranged things that the only
      ** non-jump opcodes less than SQLITE_MX_JUMP_CODE are guaranteed to
      ** have non-negative values for P2. */
      assert( (sqlite3OpcodeProperty[pOp->opcode]&OPFLG_JUMP)==0 || pOp->p2>=0);
    }
    if( pOp==p->aOp ) break;
    assert( pOp>p->aOp );    
    pOp--;
  }
resolve_p2_values_loop_exit:
  if( aLabel ){
  sqlite3DbFree(p->db, pParse->aLabel);
  pParse->aLabel = 0;
    sqlite3DbNNFreeNN(p->db, pParse->aLabel);
    pParse->aLabel = 0;
  }
  pParse->nLabel = 0;
  *pMaxFuncArgs = nMaxArgs;
  assert( p->bIsReader!=0 || DbMaskAllZero(p->btreeMask) );
}

#ifdef SQLITE_DEBUG
/*
** Check to see if a subroutine contains a jump to a location outside of
** the subroutine.  If a jump outside the subroutine is detected, add code
** that will cause the program to halt with an error message.
**
** The subroutine consists of opcodes between iFirst and iLast.  Jumps to
** locations within the subroutine are acceptable.  iRetReg is a register
** that contains the return address.  Jumps to outside the range of iFirst
** through iLast are also acceptable as long as the jump destination is
** an OP_Return to iReturnAddr.
**
** A jump to an unresolved label means that the jump destination will be
** beyond the current address.  That is normally a jump to an early
** termination and is consider acceptable.
**
** This routine only runs during debug builds.  The purpose is (of course)
** to detect invalid escapes out of a subroutine.  The OP_Halt opcode
** is generated rather than an assert() or other error, so that ".eqp full"
** will still work to show the original bytecode, to aid in debugging.
*/
void sqlite3VdbeNoJumpsOutsideSubrtn(
  Vdbe *v,          /* The byte-code program under construction */
  int iFirst,       /* First opcode of the subroutine */
  int iLast,        /* Last opcode of the subroutine */
  int iRetReg       /* Subroutine return address register */
){
  VdbeOp *pOp;
  Parse *pParse;
  int i;
  sqlite3_str *pErr = 0;
  assert( v!=0 );
  pParse = v->pParse;
  assert( pParse!=0 );
  if( pParse->nErr ) return;
  assert( iLast>=iFirst );
  assert( iLast<v->nOp );
  pOp = &v->aOp[iFirst];
  for(i=iFirst; i<=iLast; i++, pOp++){
    if( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP)!=0 ){
      int iDest = pOp->p2;   /* Jump destination */
      if( iDest==0 ) continue;
      if( pOp->opcode==OP_Gosub ) continue;
      if( iDest<0 ){
        int j = ADDR(iDest);
        assert( j>=0 );
        if( j>=-pParse->nLabel || pParse->aLabel[j]<0 ){
          continue;
        }
        iDest = pParse->aLabel[j];
      }
      if( iDest<iFirst || iDest>iLast ){
        int j = iDest;
        for(; j<v->nOp; j++){
          VdbeOp *pX = &v->aOp[j];
          if( pX->opcode==OP_Return ){
            if( pX->p1==iRetReg ) break;
            continue;
          }
          if( pX->opcode==OP_Noop ) continue;
          if( pX->opcode==OP_Explain ) continue;
          if( pErr==0 ){
            pErr = sqlite3_str_new(0);
          }else{
            sqlite3_str_appendchar(pErr, 1, '\n');
          }
          sqlite3_str_appendf(pErr,
              "Opcode at %d jumps to %d which is outside the "
              "subroutine at %d..%d",
              i, iDest, iFirst, iLast);
          break;
        }
      }
    }
  }
  if( pErr ){
    char *zErr = sqlite3_str_finish(pErr);
    sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_INTERNAL, OE_Abort, 0, zErr, 0);
    sqlite3_free(zErr);
    sqlite3MayAbort(pParse);
  }
}
#endif /* SQLITE_DEBUG */

/*
** Return the address of the next instruction to be inserted.
*/
int sqlite3VdbeCurrentAddr(Vdbe *p){
  assert( p->magic==VDBE_MAGIC_INIT );
  assert( p->eVdbeState==VDBE_INIT_STATE );
  return p->nOp;
}

/*
** Verify that at least N opcode slots are available in p without
** having to malloc for more space (except when compiled using
** SQLITE_TEST_REALLOC_STRESS).  This interface is used during testing
** to verify that certain calls to sqlite3VdbeAddOpList() can never
** fail due to a OOM fault and hence that the return value from
** sqlite3VdbeAddOpList() will always be non-NULL.
*/
#if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS)
void sqlite3VdbeVerifyNoMallocRequired(Vdbe *p, int N){
  assert( p->nOp + N <= p->pParse->nOpAlloc );
  assert( p->nOp + N <= p->nOpAlloc );
}
#endif

/*
** Verify that the VM passed as the only argument does not contain
** an OP_ResultRow opcode. Fail an assert() if it does. This is used
** by code in pragma.c to ensure that the implementation of certain
854
855
856
857
858
859
860
861
862


863
864
865
866
867
868
869
1071
1072
1073
1074
1075
1076
1077


1078
1079
1080
1081
1082
1083
1084
1085
1086







-
-
+
+







  int nOp,                     /* Number of opcodes to add */
  VdbeOpList const *aOp,       /* The opcodes to be added */
  int iLineno                  /* Source-file line number of first opcode */
){
  int i;
  VdbeOp *pOut, *pFirst;
  assert( nOp>0 );
  assert( p->magic==VDBE_MAGIC_INIT );
  if( p->nOp + nOp > p->pParse->nOpAlloc && growOpArray(p, nOp) ){
  assert( p->eVdbeState==VDBE_INIT_STATE );
  if( p->nOp + nOp > p->nOpAlloc && growOpArray(p, nOp) ){
    return 0;
  }
  pFirst = pOut = &p->aOp[p->nOp];
  for(i=0; i<nOp; i++, aOp++, pOut++){
    pOut->opcode = aOp->opcode;
    pOut->p1 = aOp->p1;
    pOut->p2 = aOp->p2;
901
902
903
904
905
906
907
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


935
936
937


938
939
940
941
942
943












944
945
946
947
948
949
950
951
952




























953
954
955
956
957
958

959
960

961
962
963
964
965
966
967
968
969
970
971

972
973

974
975

976
977
978
979
980
981
982
983
984
985
986
987
988
989

990
991
992
993
994
995
996
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
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







-
+




+








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
+
+


-
+
+


-
+
+


-
+
+






+
+
+
+
+
+
+
+
+
+
+
+









+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






+

-
+



-
-





-
+


+

-
+











-

-
+







  Vdbe *p,                        /* VM to add scanstatus() to */
  int addrExplain,                /* Address of OP_Explain (or 0) */
  int addrLoop,                   /* Address of loop counter */ 
  int addrVisit,                  /* Address of rows visited counter */
  LogEst nEst,                    /* Estimated number of output rows */
  const char *zName               /* Name of table or index being scanned */
){
  int nByte = (p->nScan+1) * sizeof(ScanStatus);
  sqlite3_int64 nByte = (p->nScan+1) * sizeof(ScanStatus);
  ScanStatus *aNew;
  aNew = (ScanStatus*)sqlite3DbRealloc(p->db, p->aScan, nByte);
  if( aNew ){
    ScanStatus *pNew = &aNew[p->nScan++];
    memset(pNew, 0, sizeof(ScanStatus));
    pNew->addrExplain = addrExplain;
    pNew->addrLoop = addrLoop;
    pNew->addrVisit = addrVisit;
    pNew->nEst = nEst;
    pNew->zName = sqlite3DbStrDup(p->db, zName);
    p->aScan = aNew;
  }
}

/*
** Add the range of instructions from addrStart to addrEnd (inclusive) to
** the set of those corresponding to the sqlite3_stmt_scanstatus() counters
** associated with the OP_Explain instruction at addrExplain. The
** sum of the sqlite3Hwtime() values for each of these instructions 
** will be returned for SQLITE_SCANSTAT_NCYCLE requests.
*/
void sqlite3VdbeScanStatusRange(
  Vdbe *p, 
  int addrExplain, 
  int addrStart, 
  int addrEnd
){
  ScanStatus *pScan = 0;
  int ii;
  for(ii=p->nScan-1; ii>=0; ii--){
    pScan = &p->aScan[ii];
    if( pScan->addrExplain==addrExplain ) break;
    pScan = 0;
  }
  if( pScan ){
    if( addrEnd<0 ) addrEnd = sqlite3VdbeCurrentAddr(p)-1;
    for(ii=0; ii<ArraySize(pScan->aAddrRange); ii+=2){
      if( pScan->aAddrRange[ii]==0 ){
        pScan->aAddrRange[ii] = addrStart;
        pScan->aAddrRange[ii+1] = addrEnd;
        break;
      }
    }
  }
}

/*
** Set the addresses for the SQLITE_SCANSTAT_NLOOP and SQLITE_SCANSTAT_NROW
** counters for the query element associated with the OP_Explain at
** addrExplain.
*/
void sqlite3VdbeScanStatusCounters(
  Vdbe *p, 
  int addrExplain, 
  int addrLoop, 
  int addrVisit
){
  ScanStatus *pScan = 0;
  int ii;
  for(ii=p->nScan-1; ii>=0; ii--){
    pScan = &p->aScan[ii];
    if( pScan->addrExplain==addrExplain ) break;
    pScan = 0;
  }
  if( pScan ){
    pScan->addrLoop = addrLoop;
    pScan->addrVisit = addrVisit;
  }
}
#endif


/*
** Change the value of the opcode, or P1, P2, P3, or P5 operands
** for a specific instruction.
*/
void sqlite3VdbeChangeOpcode(Vdbe *p, u32 addr, u8 iNewOpcode){
void sqlite3VdbeChangeOpcode(Vdbe *p, int addr, u8 iNewOpcode){
  assert( addr>=0 );
  sqlite3VdbeGetOp(p,addr)->opcode = iNewOpcode;
}
void sqlite3VdbeChangeP1(Vdbe *p, u32 addr, int val){
void sqlite3VdbeChangeP1(Vdbe *p, int addr, int val){
  assert( addr>=0 );
  sqlite3VdbeGetOp(p,addr)->p1 = val;
}
void sqlite3VdbeChangeP2(Vdbe *p, u32 addr, int val){
void sqlite3VdbeChangeP2(Vdbe *p, int addr, int val){
  assert( addr>=0 || p->db->mallocFailed );
  sqlite3VdbeGetOp(p,addr)->p2 = val;
}
void sqlite3VdbeChangeP3(Vdbe *p, u32 addr, int val){
void sqlite3VdbeChangeP3(Vdbe *p, int addr, int val){
  assert( addr>=0 );
  sqlite3VdbeGetOp(p,addr)->p3 = val;
}
void sqlite3VdbeChangeP5(Vdbe *p, u16 p5){
  assert( p->nOp>0 || p->db->mallocFailed );
  if( p->nOp>0 ) p->aOp[p->nOp-1].p5 = p5;
}

/*
** If the previous opcode is an OP_Column that delivers results
** into register iDest, then add the OPFLAG_TYPEOFARG flag to that
** opcode.
*/
void sqlite3VdbeTypeofColumn(Vdbe *p, int iDest){
  VdbeOp *pOp = sqlite3VdbeGetLastOp(p);
  if( pOp->p3==iDest && pOp->opcode==OP_Column ){
    pOp->p5 |= OPFLAG_TYPEOFARG;
  }
}

/*
** Change the P2 operand of instruction addr so that it points to
** the address of the next instruction to be coded.
*/
void sqlite3VdbeJumpHere(Vdbe *p, int addr){
  sqlite3VdbeChangeP2(p, addr, p->nOp);
}

/*
** Change the P2 operand of the jump instruction at addr so that
** the jump lands on the next opcode.  Or if the jump instruction was
** the previous opcode (and is thus a no-op) then simply back up
** the next instruction counter by one slot so that the jump is
** overwritten by the next inserted opcode.
**
** This routine is an optimization of sqlite3VdbeJumpHere() that
** strives to omit useless byte-code like this:
**
**        7   Once 0 8 0
**        8   ...
*/
void sqlite3VdbeJumpHereOrPopInst(Vdbe *p, int addr){
  if( addr==p->nOp-1 ){
    assert( p->aOp[addr].opcode==OP_Once
         || p->aOp[addr].opcode==OP_If
         || p->aOp[addr].opcode==OP_FkIfZero );
    assert( p->aOp[addr].p4type==0 );
#ifdef SQLITE_VDBE_COVERAGE
    sqlite3VdbeGetLastOp(p)->iSrcLine = 0;  /* Erase VdbeCoverage() macros */
#endif
    p->nOp--;
  }else{
    sqlite3VdbeChangeP2(p, addr, p->nOp);
  }
}


/*
** If the input FuncDef structure is ephemeral, then free it.  If
** the FuncDef is not ephermal, then do nothing.
*/
static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef){
  assert( db!=0 );
  if( (pDef->funcFlags & SQLITE_FUNC_EPHEM)!=0 ){
    sqlite3DbFreeNN(db, pDef);
    sqlite3DbNNFreeNN(db, pDef);
  }
}

static void vdbeFreeOpArray(sqlite3 *, Op *, int);

/*
** Delete a P4 value if necessary.
*/
static SQLITE_NOINLINE void freeP4Mem(sqlite3 *db, Mem *p){
  if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc);
  sqlite3DbFreeNN(db, p);
  sqlite3DbNNFreeNN(db, p);
}
static SQLITE_NOINLINE void freeP4FuncCtx(sqlite3 *db, sqlite3_context *p){
  assert( db!=0 );
  freeEphemeralFunction(db, p->pFunc);
 sqlite3DbFreeNN(db, p);
  sqlite3DbNNFreeNN(db, p);
}
static void freeP4(sqlite3 *db, int p4type, void *p4){
  assert( db );
  switch( p4type ){
    case P4_FUNCCTX: {
      freeP4FuncCtx(db, (sqlite3_context*)p4);
      break;
    }
    case P4_REAL:
    case P4_INT64:
    case P4_DYNAMIC:
    case P4_DYNBLOB:
    case P4_INTARRAY: {
      sqlite3DbFree(db, p4);
      if( p4 ) sqlite3DbNNFreeNN(db, p4);
      break;
    }
    case P4_KEYINFO: {
      if( db->pnBytesFreed==0 ) sqlite3KeyInfoUnref((KeyInfo*)p4);
      break;
    }
#ifdef SQLITE_ENABLE_CURSOR_HINTS
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
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







+
+

-
+
-
+




+
+

-
+












+
+
+
+
+
+
+








/*
** Free the space allocated for aOp and any p4 values allocated for the
** opcodes contained within. If aOp is not NULL it is assumed to contain 
** nOp entries. 
*/
static void vdbeFreeOpArray(sqlite3 *db, Op *aOp, int nOp){
  assert( nOp>=0 );
  assert( db!=0 );
  if( aOp ){
    Op *pOp;
    Op *pOp = &aOp[nOp-1];
    for(pOp=&aOp[nOp-1]; pOp>=aOp; pOp--){
    while(1){  /* Exit via break */
      if( pOp->p4type <= P4_FREE_IF_LE ) freeP4(db, pOp->p4type, pOp->p4.p);
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
      sqlite3DbFree(db, pOp->zComment);
#endif     
      if( pOp==aOp ) break;
      pOp--;
    }
    sqlite3DbFreeNN(db, aOp);
    sqlite3DbNNFreeNN(db, aOp);
  }
}

/*
** Link the SubProgram object passed as the second argument into the linked
** list at Vdbe.pSubProgram. This list is used to delete all sub-program
** objects when the VM is no longer required.
*/
void sqlite3VdbeLinkSubProgram(Vdbe *pVdbe, SubProgram *p){
  p->pNext = pVdbe->pProgram;
  pVdbe->pProgram = p;
}

/*
** Return true if the given Vdbe has any SubPrograms.
*/
int sqlite3VdbeHasSubProgram(Vdbe *pVdbe){
  return pVdbe->pProgram!=0;
}

/*
** Change the opcode at addr into OP_Noop
*/
int sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
  VdbeOp *pOp;
  if( p->db->mallocFailed ) return 0;
1068
1069
1070
1071
1072
1073
1074



































1075
1076
1077
1078
1079
1080
1081
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







int sqlite3VdbeDeletePriorOpcode(Vdbe *p, u8 op){
  if( p->nOp>0 && p->aOp[p->nOp-1].opcode==op ){
    return sqlite3VdbeChangeToNoop(p, p->nOp-1);
  }else{
    return 0;
  }
}

#ifdef SQLITE_DEBUG
/*
** Generate an OP_ReleaseReg opcode to indicate that a range of
** registers, except any identified by mask, are no longer in use.
*/
void sqlite3VdbeReleaseRegisters(
  Parse *pParse,       /* Parsing context */
  int iFirst,          /* Index of first register to be released */
  int N,               /* Number of registers to release */
  u32 mask,            /* Mask of registers to NOT release */
  int bUndefine        /* If true, mark registers as undefined */
){
  if( N==0 || OptimizationDisabled(pParse->db, SQLITE_ReleaseReg) ) return;
  assert( pParse->pVdbe );
  assert( iFirst>=1 );
  assert( iFirst+N-1<=pParse->nMem );
  if( N<=31 && mask!=0 ){
    while( N>0 && (mask&1)!=0 ){
      mask >>= 1;
      iFirst++;
      N--;
    }
    while( N>0 && N<=32 && (mask & MASKBIT32(N-1))!=0 ){
      mask &= ~MASKBIT32(N-1);
      N--;
    }
  }
  if( N>0 ){
    sqlite3VdbeAddOp3(pParse->pVdbe, OP_ReleaseReg, iFirst, N, *(int*)&mask);
    if( bUndefine ) sqlite3VdbeChangeP5(pParse->pVdbe, 1);
  }
}
#endif /* SQLITE_DEBUG */


/*
** Change the value of the P4 operand for a specific instruction.
** This routine is useful when a large program is loaded from a
** static array using sqlite3VdbeAddOpList but we want to make a
** few minor changes to the program.
**
1110
1111
1112
1113
1114
1115
1116
1117

1118
1119
1120
1121
1122
1123
1124
1473
1474
1475
1476
1477
1478
1479

1480
1481
1482
1483
1484
1485
1486
1487







-
+







  }
}
void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int n){
  Op *pOp;
  sqlite3 *db;
  assert( p!=0 );
  db = p->db;
  assert( p->magic==VDBE_MAGIC_INIT );
  assert( p->eVdbeState==VDBE_INIT_STATE );
  assert( p->aOp!=0 || db->mallocFailed );
  if( db->mallocFailed ){
    if( n!=P4_VTAB ) freeP4(db, n, (void*)*(char**)&zP4);
    return;
  }
  assert( p->nOp>0 );
  assert( addr<p->nOp );
1155
1156
1157
1158
1159
1160
1161
1162

1163
1164
1165
1166
1167
1168
1169
1518
1519
1520
1521
1522
1523
1524

1525
1526
1527
1528
1529
1530
1531
1532







-
+







void sqlite3VdbeAppendP4(Vdbe *p, void *pP4, int n){
  VdbeOp *pOp;
  assert( n!=P4_INT32 && n!=P4_VTAB );
  assert( n<=0 );
  if( p->db->mallocFailed ){
    freeP4(p->db, n, pP4);
  }else{
    assert( pP4!=0 );
    assert( pP4!=0 || n==P4_DYNAMIC );
    assert( p->nOp>0 );
    pOp = &p->aOp[p->nOp-1];
    assert( pOp->p4type==P4_NOTUSED );
    pOp->p4type = n;
    pOp->p4.p = pP4;
  }
}
1186
1187
1188
1189
1190
1191
1192
1193

1194
1195
1196
1197
1198
1199
1200
1549
1550
1551
1552
1553
1554
1555

1556
1557
1558
1559
1560
1561
1562
1563







-
+







** Change the comment on the most recently coded instruction.  Or
** insert a No-op and add the comment to that new instruction.  This
** makes the code easier to read during debugging.  None of this happens
** in a production build.
*/
static void vdbeVComment(Vdbe *p, const char *zFormat, va_list ap){
  assert( p->nOp>0 || p->aOp==0 );
  assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed );
  assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->pParse->nErr>0 );
  if( p->nOp ){
    assert( p->aOp );
    sqlite3DbFree(p->db, p->aOp[p->nOp-1].zComment);
    p->aOp[p->nOp-1].zComment = sqlite3VMPrintf(p->db, zFormat, ap);
  }
}
void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){
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
1580
1581
1582
1583
1584
1585
1586

1587
1588
1589
1590
1591


1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607

1608



1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628







-
+




-
-
+
+














-
+
-
-
-







+
+
+
+
+
+







#endif  /* NDEBUG */

#ifdef SQLITE_VDBE_COVERAGE
/*
** Set the value if the iSrcLine field for the previously coded instruction.
*/
void sqlite3VdbeSetLineNumber(Vdbe *v, int iLine){
  sqlite3VdbeGetOp(v,-1)->iSrcLine = iLine;
  sqlite3VdbeGetLastOp(v)->iSrcLine = iLine;
}
#endif /* SQLITE_VDBE_COVERAGE */

/*
** Return the opcode for a given address.  If the address is -1, then
** return the most recently inserted opcode.
** Return the opcode for a given address.  The address must be non-negative.
** See sqlite3VdbeGetLastOp() to get the most recently added opcode.
**
** If a memory allocation error has occurred prior to the calling of this
** routine, then a pointer to a dummy VdbeOp will be returned.  That opcode
** is readable but not writable, though it is cast to a writable value.
** The return of a dummy opcode allows the call to continue functioning
** after an OOM fault without having to check to see if the return from 
** this routine is a valid pointer.  But because the dummy.opcode is 0,
** dummy will never be written to.  This is verified by code inspection and
** by running with Valgrind.
*/
VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
  /* C89 specifies that the constant "dummy" will be initialized to all
  ** zeros, which is correct.  MSVC generates a warning, nevertheless. */
  static VdbeOp dummy;  /* Ignore the MSVC warning about no initializer */
  assert( p->magic==VDBE_MAGIC_INIT );
  assert( p->eVdbeState==VDBE_INIT_STATE );
  if( addr<0 ){
    addr = p->nOp - 1;
  }
  assert( (addr>=0 && addr<p->nOp) || p->db->mallocFailed );
  if( p->db->mallocFailed ){
    return (VdbeOp*)&dummy;
  }else{
    return &p->aOp[addr];
  }
}

/* Return the most recently added opcode
*/
VdbeOp * sqlite3VdbeGetLastOp(Vdbe *p){
  return sqlite3VdbeGetOp(p, p->nOp - 1);
}

#if defined(SQLITE_ENABLE_EXPLAIN_COMMENTS)
/*
** Return an integer value for one of the parameters to the opcode pOp
** determined by character c.
*/
static int translateP(char c, const Op *pOp){
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329




1330














1331
1332
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
1642
1643
1644
1645
1646
1647
1648

1649
1650
1651

1652


1653
1654
1655
1656

1657
1658
1659
1660
1661
1662
1663
1664
1665
1666

1667
1668




1669

1670
1671

1672
1673
1674
1675

1676
1677
1678


1679
1680
1681
1682
1683
1684
1685

1686
1687

1688
1689
1690
1691
1692


1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711




1712
1713
1714
1715

1716
1717

1718
1719
1720


1721
1722

1723

1724


1725
1726
1727
1728



1729

1730
1731

1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750







-
+
+

-
+
-
-




-
+

+
+
+





-
+

-
-
-
-
+
-


-
+



-
+

+
-
-
+
+
+
+



-


-





-
-
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
+

-
+


-
-
+
+
-

-

-
-
+
+
+
+
-
-
-

-
+

-
+










+







** Some translation occurs:
**
**       "PX"      ->  "r[X]"
**       "PX@PY"   ->  "r[X..X+Y-1]"  or "r[x]" if y is 0 or 1
**       "PX@PY+1" ->  "r[X..X+Y]"    or "r[x]" if y is 0
**       "PY..PY"  ->  "r[X..Y]"      or "r[x]" if y<=x
*/
static int displayComment(
char *sqlite3VdbeDisplayComment(
  sqlite3 *db,       /* Optional - Oom error reporting only */
  const Op *pOp,     /* The opcode to be commented */
  const char *zP4,   /* Previously obtained value for P4 */
  const char *zP4    /* Previously obtained value for P4 */
  char *zTemp,       /* Write result here */
  int nTemp          /* Space available in zTemp[] */
){
  const char *zOpName;
  const char *zSynopsis;
  int nOpName;
  int ii, jj;
  int ii;
  char zAlt[50];
  StrAccum x;

  sqlite3StrAccumInit(&x, 0, 0, 0, SQLITE_MAX_LENGTH);
  zOpName = sqlite3OpcodeName(pOp->opcode);
  nOpName = sqlite3Strlen30(zOpName);
  if( zOpName[nOpName+1] ){
    int seenCom = 0;
    char c;
    zSynopsis = zOpName += nOpName + 1;
    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=jj=0; jj<nTemp-1 && (c = zSynopsis[ii])!=0; ii++){
    for(ii=0; (c = zSynopsis[ii])!=0; ii++){
      if( c=='P' ){
        c = zSynopsis[++ii];
        if( c=='4' ){
          sqlite3_snprintf(nTemp-jj, zTemp+jj, "%s", zP4);
          sqlite3_str_appendall(&x, zP4);
        }else if( c=='X' ){
          if( pOp->zComment && pOp->zComment[0] ){
          sqlite3_snprintf(nTemp-jj, zTemp+jj, "%s", pOp->zComment);
          seenCom = 1;
            sqlite3_str_appendall(&x, pOp->zComment);
            seenCom = 1;
            break;
          }
        }else{
          int v1 = translateP(c, pOp);
          int v2;
          sqlite3_snprintf(nTemp-jj, zTemp+jj, "%d", v1);
          if( strncmp(zSynopsis+ii+1, "@P", 2)==0 ){
            ii += 3;
            jj += sqlite3Strlen30(zTemp+jj);
            v2 = translateP(zSynopsis[ii], pOp);
            if( strncmp(zSynopsis+ii+1,"+1",2)==0 ){
              ii += 2;
              v2++;
            }
            if( v2>1 ){
              sqlite3_snprintf(nTemp-jj, zTemp+jj, "..%d", v1+v2-1);
            if( v2<2 ){
              sqlite3_str_appendf(&x, "%d", v1);
            }else{
              sqlite3_str_appendf(&x, "%d..%d", v1, v1+v2-1);
            }
          }else if( strncmp(zSynopsis+ii+1, "@NP", 3)==0 ){
            sqlite3_context *pCtx = pOp->p4.pCtx;
            if( pOp->p4type!=P4_FUNCCTX || pCtx->argc==1 ){
              sqlite3_str_appendf(&x, "%d", v1);
            }else if( pCtx->argc>1 ){
              sqlite3_str_appendf(&x, "%d..%d", v1, v1+pCtx->argc-1);
            }else if( x.accError==0 ){
              assert( x.nChar>2 );
              x.nChar -= 2;
              ii++;
            }
            ii += 3;
          }else{
            sqlite3_str_appendf(&x, "%d", v1);
          }else if( strncmp(zSynopsis+ii+1, "..P3", 4)==0 && pOp->p3==0 ){
            ii += 4;
          }
        }
            if( strncmp(zSynopsis+ii+1, "..P3", 4)==0 && pOp->p3==0 ){
              ii += 4;
            }
          }
        jj += sqlite3Strlen30(zTemp+jj);
        }
      }else{
        zTemp[jj++] = c;
        sqlite3_str_appendchar(&x, 1, c);
      }
    }
    if( !seenCom && jj<nTemp-5 && pOp->zComment ){
      sqlite3_snprintf(nTemp-jj, zTemp+jj, "; %s", pOp->zComment);
    if( !seenCom && pOp->zComment ){
      sqlite3_str_appendf(&x, "; %s", pOp->zComment);
      jj += sqlite3Strlen30(zTemp+jj);
    }
    if( jj<nTemp ) zTemp[jj] = 0;
  }else if( pOp->zComment ){
    sqlite3_snprintf(nTemp, zTemp, "%s", pOp->zComment);
    jj = sqlite3Strlen30(zTemp);
    sqlite3_str_appendall(&x, pOp->zComment);
  }
  if( (x.accError & SQLITE_NOMEM)!=0 && db!=0 ){
    sqlite3OomFault(db);
  }else{
    zTemp[0] = 0;
    jj = 0;
  }
  return jj;
  return sqlite3StrAccumFinish(&x);
}
#endif /* SQLITE_DEBUG */
#endif /* SQLITE_ENABLE_EXPLAIN_COMMENTS */

#if VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS)
/*
** Translate the P4.pExpr value for an OP_CursorHint opcode into text
** that can be displayed in the P4 column of EXPLAIN output.
*/
static void displayP4Expr(StrAccum *p, Expr *pExpr){
  const char *zOp = 0;
  switch( pExpr->op ){
    case TK_STRING:
      assert( !ExprHasProperty(pExpr, EP_IntValue) );
      sqlite3_str_appendf(p, "%Q", pExpr->u.zToken);
      break;
    case TK_INTEGER:
      sqlite3_str_appendf(p, "%d", pExpr->u.iValue);
      break;
    case TK_NULL:
      sqlite3_str_appendf(p, "NULL");
1428
1429
1430
1431
1432
1433
1434
1435
1436


1437
1438
1439


1440
1441
1442
1443
1444

1445
1446
1447
1448
1449
1450
1451




1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462

1463

1464


1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495

1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
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





1546
1547

1548
1549
1550
1551
1552
1553
1554
1555
1556
1807
1808
1809
1810
1811
1812
1813


1814
1815
1816


1817
1818
1819
1820
1821
1822

1823
1824
1825
1826
1827
1828


1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846

1847
1848
1849
1850
1851
1852
1853
1854
1855

1856
1857
1858
1859
1860

1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876

1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896



1897
1898
1899
1900
1901

1902
1903

1904
1905
1906
1907

1908





1909
1910
1911

1912
1913
1914
1915
1916





1917
1918
1919
1920
1921
1922

1923


1924
1925
1926
1927
1928
1929
1930







-
-
+
+

-
-
+
+




-
+





-
-
+
+
+
+











+

+
-
+
+







-





-
















-
+



















-
-
-
+
+
+


-
+

-




-
+
-
-
-
-
-



-
+




-
-
-
-
-
+
+
+
+
+

-
+
-
-









#if VDBE_DISPLAY_P4
/*
** Compute a string that describes the P4 parameter for an opcode.
** Use zTemp for any required temporary buffer space.
*/
static char *displayP4(Op *pOp, char *zTemp, int nTemp){
  char *zP4 = zTemp;
char *sqlite3VdbeDisplayP4(sqlite3 *db, Op *pOp){
  char *zP4 = 0;
  StrAccum x;
  assert( nTemp>=20 );
  sqlite3StrAccumInit(&x, 0, zTemp, nTemp, 0);

  sqlite3StrAccumInit(&x, 0, 0, 0, SQLITE_MAX_LENGTH);
  switch( pOp->p4type ){
    case P4_KEYINFO: {
      int j;
      KeyInfo *pKeyInfo = pOp->p4.pKeyInfo;
      assert( pKeyInfo->aSortOrder!=0 );
      assert( pKeyInfo->aSortFlags!=0 );
      sqlite3_str_appendf(&x, "k(%d", pKeyInfo->nKeyField);
      for(j=0; j<pKeyInfo->nKeyField; j++){
        CollSeq *pColl = pKeyInfo->aColl[j];
        const char *zColl = pColl ? pColl->zName : "";
        if( strcmp(zColl, "BINARY")==0 ) zColl = "B";
        sqlite3_str_appendf(&x, ",%s%s", 
               pKeyInfo->aSortOrder[j] ? "-" : "", zColl);
        sqlite3_str_appendf(&x, ",%s%s%s", 
               (pKeyInfo->aSortFlags[j] & KEYINFO_ORDER_DESC) ? "-" : "", 
               (pKeyInfo->aSortFlags[j] & KEYINFO_ORDER_BIGNULL)? "N." : "", 
               zColl);
      }
      sqlite3_str_append(&x, ")", 1);
      break;
    }
#ifdef SQLITE_ENABLE_CURSOR_HINTS
    case P4_EXPR: {
      displayP4Expr(&x, pOp->p4.pExpr);
      break;
    }
#endif
    case P4_COLLSEQ: {
      static const char *const encnames[] = {"?", "8", "16LE", "16BE"};
      CollSeq *pColl = pOp->p4.pColl;
      assert( pColl->enc<4 );
      sqlite3_str_appendf(&x, "(%.20s)", pColl->zName);
      sqlite3_str_appendf(&x, "%.18s-%s", pColl->zName,
                          encnames[pColl->enc]);
      break;
    }
    case P4_FUNCDEF: {
      FuncDef *pDef = pOp->p4.pFunc;
      sqlite3_str_appendf(&x, "%s(%d)", pDef->zName, pDef->nArg);
      break;
    }
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
    case P4_FUNCCTX: {
      FuncDef *pDef = pOp->p4.pCtx->pFunc;
      sqlite3_str_appendf(&x, "%s(%d)", pDef->zName, pDef->nArg);
      break;
    }
#endif
    case P4_INT64: {
      sqlite3_str_appendf(&x, "%lld", *pOp->p4.pI64);
      break;
    }
    case P4_INT32: {
      sqlite3_str_appendf(&x, "%d", pOp->p4.i);
      break;
    }
    case P4_REAL: {
      sqlite3_str_appendf(&x, "%.16g", *pOp->p4.pReal);
      break;
    }
    case P4_MEM: {
      Mem *pMem = pOp->p4.pMem;
      if( pMem->flags & MEM_Str ){
        zP4 = pMem->z;
      }else if( pMem->flags & MEM_Int ){
      }else if( pMem->flags & (MEM_Int|MEM_IntReal) ){
        sqlite3_str_appendf(&x, "%lld", pMem->u.i);
      }else if( pMem->flags & MEM_Real ){
        sqlite3_str_appendf(&x, "%.16g", pMem->u.r);
      }else if( pMem->flags & MEM_Null ){
        zP4 = "NULL";
      }else{
        assert( pMem->flags & MEM_Blob );
        zP4 = "(blob)";
      }
      break;
    }
#ifndef SQLITE_OMIT_VIRTUALTABLE
    case P4_VTAB: {
      sqlite3_vtab *pVtab = pOp->p4.pVtab->pVtab;
      sqlite3_str_appendf(&x, "vtab:%p", pVtab);
      break;
    }
#endif
    case P4_INTARRAY: {
      int i;
      int *ai = pOp->p4.ai;
      int n = ai[0];   /* The first element of an INTARRAY is always the
      u32 i;
      u32 *ai = pOp->p4.ai;
      u32 n = ai[0];   /* The first element of an INTARRAY is always the
                       ** count of the number of elements to follow */
      for(i=1; i<=n; i++){
        sqlite3_str_appendf(&x, ",%d", ai[i]);
        sqlite3_str_appendf(&x, "%c%u", (i==1 ? '[' : ','), ai[i]);
      }
      zTemp[0] = '[';
      sqlite3_str_append(&x, "]", 1);
      break;
    }
    case P4_SUBPROGRAM: {
      sqlite3_str_appendf(&x, "program");
      zP4 = "program";
      break;
    }
    case P4_DYNBLOB:
    case P4_ADVANCE: {
      zTemp[0] = 0;
      break;
    }
    case P4_TABLE: {
      sqlite3_str_appendf(&x, "%s", pOp->p4.pTab->zName);
      zP4 = pOp->p4.pTab->zName;
      break;
    }
    default: {
      zP4 = pOp->p4.z;
      if( zP4==0 ){
        zP4 = zTemp;
        zTemp[0] = 0;
      }
    }
    }
  }
  if( zP4 ) sqlite3_str_appendall(&x, zP4);
  if( (x.accError & SQLITE_NOMEM)!=0 ){
    sqlite3OomFault(db);
  }
  sqlite3StrAccumFinish(&x);
  return sqlite3StrAccumFinish(&x);
  assert( zP4!=0 );
  return zP4;
}
#endif /* VDBE_DISPLAY_P4 */

/*
** Declare to the Vdbe that the BTree object at db->aDb[i] is used.
**
** The prepared statements need to know in advance the complete set of
1632
1633
1634
1635
1636
1637
1638
1639
1640


1641
1642


1643

1644
1645

1646
1647

1648
1649
1650
1651
1652
1653
1654



1655
1656



1657
1658
1659
1660
1661












1662
1663
1664
1665
1666
1667





1668
1669

1670
1671


1672
1673
1674
1675
1676






1677
1678
1679
1680
1681
1682
1683
2006
2007
2008
2009
2010
2011
2012


2013
2014
2015
2016
2017
2018

2019
2020

2021
2022

2023
2024
2025
2026
2027
2028


2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055




2056
2057
2058
2059
2060
2061

2062
2063

2064
2065
2066
2067
2068
2069

2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082







-
-
+
+


+
+
-
+

-
+

-
+





-
-
+
+
+


+
+
+





+
+
+
+
+
+
+
+
+
+
+
+


-
-
-
-
+
+
+
+
+

-
+

-
+
+




-
+
+
+
+
+
+








#if defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
/*
** Print a single opcode.  This routine is used for debugging only.
*/
void sqlite3VdbePrintOp(FILE *pOut, int pc, VdbeOp *pOp){
  char *zP4;
  char zPtr[50];
  char zCom[100];
  char *zCom;
  sqlite3 dummyDb;
  static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-13s %.2X %s\n";
  if( pOut==0 ) pOut = stdout;
  sqlite3BeginBenignMalloc();
  dummyDb.mallocFailed = 1;
  zP4 = displayP4(pOp, zPtr, sizeof(zPtr));
  zP4 = sqlite3VdbeDisplayP4(&dummyDb, pOp);
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
  displayComment(pOp, zP4, zCom, sizeof(zCom));
  zCom = sqlite3VdbeDisplayComment(0, pOp, zP4);
#else
  zCom[0] = 0;
  zCom = 0;
#endif
  /* NB:  The sqlite3OpcodeName() function is implemented by code created
  ** by the mkopcodeh.awk and mkopcodec.awk scripts which extract the
  ** information from the vdbe.c source text */
  fprintf(pOut, zFormat1, pc, 
      sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, zP4, pOp->p5,
      zCom
      sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, 
      zP4 ? zP4 : "", pOp->p5,
      zCom ? zCom : ""
  );
  fflush(pOut);
  sqlite3_free(zP4);
  sqlite3_free(zCom);
  sqlite3EndBenignMalloc();
}
#endif

/*
** Initialize an array of N Mem element.
**
** This is a high-runner, so only those fields that really do need to
** be initialized are set.  The Mem structure is organized so that
** the fields that get initialized are nearby and hopefully on the same
** cache line.
**
**    Mem.flags = flags
**    Mem.db = db
**    Mem.szMalloc = 0
**
** All other fields of Mem can safely remain uninitialized for now.  They
** will be initialized before use.
*/
static void initMemArray(Mem *p, int N, sqlite3 *db, u16 flags){
  while( (N--)>0 ){
    p->db = db;
    p->flags = flags;
    p->szMalloc = 0;
  if( N>0 ){
    do{
      p->flags = flags;
      p->db = db;
      p->szMalloc = 0;
#ifdef SQLITE_DEBUG
    p->pScopyFrom = 0;
      p->pScopyFrom = 0;
#endif
    p++;
      p++;
    }while( (--N)>0 );
  }
}

/*
** Release an array of N Mem elements
** Release auxiliary memory held in an array of N Mem elements.
**
** After this routine returns, all Mem elements in the array will still
** be valid.  Those Mem elements that were not holding auxiliary resources
** will be unchanged.  Mem elements which had something freed will be
** set to MEM_Undefined.
*/
static void releaseMemArray(Mem *p, int N){
  if( p && N ){
    Mem *pEnd = &p[N];
    sqlite3 *db = p->db;
    if( db->pnBytesFreed ){
      do{
1699
1700
1701
1702
1703
1704
1705
1706
1707

1708

1709
1710

1711

1712
1713
1714





1715
1716
1717
1718
1719
1720
1721
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







-

+

+

-
+

+

-
-
+
+
+
+
+







      ** sqlite3MemRelease() were called from here. With -O2, this jumps
      ** to 6.6 percent. The test case is inserting 1000 rows into a table 
      ** with no indexes using a single prepared INSERT statement, bind() 
      ** and reset(). Inserts are grouped into a transaction.
      */
      testcase( p->flags & MEM_Agg );
      testcase( p->flags & MEM_Dyn );
      testcase( p->xDel==sqlite3VdbeFrameMemDel );
      if( p->flags&(MEM_Agg|MEM_Dyn) ){
        testcase( (p->flags & MEM_Dyn)!=0 && p->xDel==sqlite3VdbeFrameMemDel );
        sqlite3VdbeMemRelease(p);
        p->flags = MEM_Undefined;
      }else if( p->szMalloc ){
        sqlite3DbFreeNN(db, p->zMalloc);
        sqlite3DbNNFreeNN(db, p->zMalloc);
        p->szMalloc = 0;
        p->flags = MEM_Undefined;
      }

      p->flags = MEM_Undefined;
#ifdef SQLITE_DEBUG
      else{
        p->flags = MEM_Undefined;
      }
#endif
    }while( (++p)<pEnd );
  }
}

#ifdef SQLITE_DEBUG
/*
** Verify that pFrame is a valid VdbeFrame pointer.  Return true if it is
1740
1741
1742
1743
1744
1745
1746



















































































































1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758

1759
1760
1761
1762
1763
1764
1765
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
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
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276

2277
2278
2279
2280
2281
2282
2283
2284







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+











-
+







void sqlite3VdbeFrameMemDel(void *pArg){
  VdbeFrame *pFrame = (VdbeFrame*)pArg;
  assert( sqlite3VdbeFrameIsValid(pFrame) );
  pFrame->pParent = pFrame->v->pDelFrame;
  pFrame->v->pDelFrame = pFrame;
}

#if defined(SQLITE_ENABLE_BYTECODE_VTAB) || !defined(SQLITE_OMIT_EXPLAIN)
/*
** Locate the next opcode to be displayed in EXPLAIN or EXPLAIN
** QUERY PLAN output.
**
** Return SQLITE_ROW on success.  Return SQLITE_DONE if there are no
** more opcodes to be displayed.
*/
int sqlite3VdbeNextOpcode(
  Vdbe *p,         /* The statement being explained */
  Mem *pSub,       /* Storage for keeping track of subprogram nesting */
  int eMode,       /* 0: normal.  1: EQP.  2:  TablesUsed */
  int *piPc,       /* IN/OUT: Current rowid.  Overwritten with next rowid */
  int *piAddr,     /* OUT: Write index into (*paOp)[] here */
  Op **paOp        /* OUT: Write the opcode array here */
){
  int nRow;                            /* Stop when row count reaches this */
  int nSub = 0;                        /* Number of sub-vdbes seen so far */
  SubProgram **apSub = 0;              /* Array of sub-vdbes */
  int i;                               /* Next instruction address */
  int rc = SQLITE_OK;                  /* Result code */
  Op *aOp = 0;                         /* Opcode array */
  int iPc;                             /* Rowid.  Copy of value in *piPc */

  /* When the number of output rows reaches nRow, that means the
  ** listing has finished and sqlite3_step() should return SQLITE_DONE.
  ** nRow is the sum of the number of rows in the main program, plus
  ** the sum of the number of rows in all trigger subprograms encountered
  ** so far.  The nRow value will increase as new trigger subprograms are
  ** encountered, but p->pc will eventually catch up to nRow.
  */
  nRow = p->nOp;
  if( pSub!=0 ){
    if( pSub->flags&MEM_Blob ){
      /* pSub is initiallly NULL.  It is initialized to a BLOB by
      ** the P4_SUBPROGRAM processing logic below */
      nSub = pSub->n/sizeof(Vdbe*);
      apSub = (SubProgram **)pSub->z;
    }
    for(i=0; i<nSub; i++){
      nRow += apSub[i]->nOp;
    }
  }
  iPc = *piPc;
  while(1){  /* Loop exits via break */
    i = iPc++;
    if( i>=nRow ){
      p->rc = SQLITE_OK;
      rc = SQLITE_DONE;
      break;
    }
    if( i<p->nOp ){
      /* The rowid is small enough that we are still in the
      ** main program. */
      aOp = p->aOp;
    }else{
      /* We are currently listing subprograms.  Figure out which one and
      ** pick up the appropriate opcode. */
      int j;
      i -= p->nOp;
      assert( apSub!=0 );
      assert( nSub>0 );
      for(j=0; i>=apSub[j]->nOp; j++){
        i -= apSub[j]->nOp;
        assert( i<apSub[j]->nOp || j+1<nSub );
      }
      aOp = apSub[j]->aOp;
    }

    /* When an OP_Program opcode is encounter (the only opcode that has
    ** a P4_SUBPROGRAM argument), expand the size of the array of subprograms
    ** kept in p->aMem[9].z to hold the new program - assuming this subprogram
    ** has not already been seen.
    */
    if( pSub!=0 && aOp[i].p4type==P4_SUBPROGRAM ){
      int nByte = (nSub+1)*sizeof(SubProgram*);
      int j;
      for(j=0; j<nSub; j++){
        if( apSub[j]==aOp[i].p4.pProgram ) break;
      }
      if( j==nSub ){
        p->rc = sqlite3VdbeMemGrow(pSub, nByte, nSub!=0);
        if( p->rc!=SQLITE_OK ){
          rc = SQLITE_ERROR;
          break;
        }
        apSub = (SubProgram **)pSub->z;
        apSub[nSub++] = aOp[i].p4.pProgram;
        MemSetTypeFlag(pSub, MEM_Blob);
        pSub->n = nSub*sizeof(SubProgram*);
        nRow += aOp[i].p4.pProgram->nOp;
      }
    }
    if( eMode==0 ) break;
#ifdef SQLITE_ENABLE_BYTECODE_VTAB
    if( eMode==2 ){
      Op *pOp = aOp + i;
      if( pOp->opcode==OP_OpenRead ) break;
      if( pOp->opcode==OP_OpenWrite && (pOp->p5 & OPFLAG_P2ISREG)==0 ) break;
      if( pOp->opcode==OP_ReopenIdx ) break;      
    }else
#endif
    {
      assert( eMode==1 );
      if( aOp[i].opcode==OP_Explain ) break;
      if( aOp[i].opcode==OP_Init && iPc>1 ) break;
    }
  }
  *piPc = iPc;
  *piAddr = i;
  *paOp = aOp;
  return rc;
}
#endif /* SQLITE_ENABLE_BYTECODE_VTAB || !SQLITE_OMIT_EXPLAIN */


/*
** Delete a VdbeFrame object and its contents. VdbeFrame objects are
** allocated by the OP_Program opcode in sqlite3VdbeExec().
*/
void sqlite3VdbeFrameDelete(VdbeFrame *p){
  int i;
  Mem *aMem = VdbeFrameMem(p);
  VdbeCursor **apCsr = (VdbeCursor **)&aMem[p->nChildMem];
  assert( sqlite3VdbeFrameIsValid(p) );
  for(i=0; i<p->nChildCsr; i++){
    sqlite3VdbeFreeCursor(p->v, apCsr[i]);
    if( apCsr[i] ) sqlite3VdbeFreeCursorNN(p->v, apCsr[i]);
  }
  releaseMemArray(aMem, p->nChildMem);
  sqlite3VdbeDeleteAuxData(p->v->db, &p->pAuxData, -1, 0);
  sqlite3DbFree(p->v->db, p);
}

#ifndef SQLITE_OMIT_EXPLAIN
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795

1796

1797
1798
1799

1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853

1854
1855
1856
1857
1858
1859
1860


1861
1862
1863


1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876

1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893

1894

1895
1896
1897
1898
1899
1900


1901
1902
1903
1904

1905
1906
1907
1908
1909
1910
1911
1912

1913
1914
1915
1916

1917
1918
1919
1920

1921
1922
1923
1924

1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
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
2299
2300
2301
2302
2303
2304
2305



2306
2307
2308
2309
2310
2311
2312

2313
2314
2315

2316
2317
2318
2319
2320
2321
2322
2323

2324
2325
2326
2327
2328
2329
2330
2331








2332
2333
2334
2335
2336
2337
2338























2339







2340
2341



2342
2343













2344















2345
2346
2347

2348
2349
2350
2351
2352


2353
2354




2355








2356




2357




2358




2359









2360



2361
2362
2363



2364
2365


2366







2367
2368
2369


2370


2371


2372
2373



2374

2375
2376






2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394







-
-
-






+
-
+


-
+







-








-
-
-
-
-
-
-
-







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
+
+
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-


+
-
+




-
-
+
+
-
-
-
-
+
-
-
-
-
-
-
-
-
+
-
-
-
-
+
-
-
-
-
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-

-
-
-
+
+
+
-
-
-
+
+
-
-
+
-
-
-
-
-
-
-
+
+
+
-
-
+
-
-
+
-
-
+

-
-
-

-
+

-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+







**
** When p->explain==1, first the main program is listed, then each of
** the trigger subprograms are listed one by one.
*/
int sqlite3VdbeList(
  Vdbe *p                   /* The VDBE */
){
  int nRow;                            /* Stop when row count reaches this */
  int nSub = 0;                        /* Number of sub-vdbes seen so far */
  SubProgram **apSub = 0;              /* Array of sub-vdbes */
  Mem *pSub = 0;                       /* Memory cell hold array of subprogs */
  sqlite3 *db = p->db;                 /* The database connection */
  int i;                               /* Loop counter */
  int rc = SQLITE_OK;                  /* Return code */
  Mem *pMem = &p->aMem[1];             /* First Mem of result set */
  int bListSubprogs = (p->explain==1 || (db->flags & SQLITE_TriggerEQP)!=0);
  Op *aOp;                             /* Array of opcodes */
  Op *pOp = 0;
  Op *pOp;                             /* Current opcode */

  assert( p->explain );
  assert( p->magic==VDBE_MAGIC_RUN );
  assert( p->eVdbeState==VDBE_RUN_STATE );
  assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY || p->rc==SQLITE_NOMEM );

  /* Even though this opcode does not use dynamic strings for
  ** the result, result columns may become dynamic if the user calls
  ** sqlite3_column_text16(), causing a translation to UTF-16 encoding.
  */
  releaseMemArray(pMem, 8);
  p->pResultSet = 0;

  if( p->rc==SQLITE_NOMEM ){
    /* This happens if a malloc() inside a call to sqlite3_column_text() or
    ** sqlite3_column_text16() failed.  */
    sqlite3OomFault(db);
    return SQLITE_ERROR;
  }

  /* When the number of output rows reaches nRow, that means the
  ** listing has finished and sqlite3_step() should return SQLITE_DONE.
  ** nRow is the sum of the number of rows in the main program, plus
  ** the sum of the number of rows in all trigger subprograms encountered
  ** so far.  The nRow value will increase as new trigger subprograms are
  ** encountered, but p->pc will eventually catch up to nRow.
  */
  nRow = p->nOp;
  if( bListSubprogs ){
    /* The first 8 memory cells are used for the result set.  So we will
    ** commandeer the 9th cell to use as storage for an array of pointers
    ** to trigger subprograms.  The VDBE is guaranteed to have at least 9
    ** cells.  */
    assert( p->nMem>9 );
    pSub = &p->aMem[9];
    if( pSub->flags&MEM_Blob ){
      /* On the first call to sqlite3_step(), pSub will hold a NULL.  It is
      ** initialized to a BLOB by the P4_SUBPROGRAM processing logic below */
      nSub = pSub->n/sizeof(Vdbe*);
      apSub = (SubProgram **)pSub->z;
    }
    for(i=0; i<nSub; i++){
      nRow += apSub[i]->nOp;
    }
  }

  while(1){  /* Loop exits via break */
    i = p->pc++;
    if( i>=nRow ){
      p->rc = SQLITE_OK;
      rc = SQLITE_DONE;
      break;
    }
    if( i<p->nOp ){
      /* The output line number is small enough that we are still in the
      ** main program. */
      pOp = &p->aOp[i];
    }else{
  }else{
      /* We are currently listing subprograms.  Figure out which one and
      ** pick up the appropriate opcode. */
      int j;
      i -= p->nOp;
      for(j=0; i>=apSub[j]->nOp; j++){
        i -= apSub[j]->nOp;
      }
    pSub = 0;
  }
      pOp = &apSub[j]->aOp[i];
    }


  /* Figure out which opcode is next to display */
    /* When an OP_Program opcode is encounter (the only opcode that has
    ** a P4_SUBPROGRAM argument), expand the size of the array of subprograms
    ** kept in p->aMem[9].z to hold the new program - assuming this subprogram
    ** has not already been seen.
    */
    if( bListSubprogs && pOp->p4type==P4_SUBPROGRAM ){
      int nByte = (nSub+1)*sizeof(SubProgram*);
      int j;
      for(j=0; j<nSub; j++){
        if( apSub[j]==pOp->p4.pProgram ) break;
      }
      if( j==nSub ){
        p->rc = sqlite3VdbeMemGrow(pSub, nByte, nSub!=0);
  rc = sqlite3VdbeNextOpcode(p, pSub, p->explain==2, &p->pc, &i, &aOp);
        if( p->rc!=SQLITE_OK ){
          rc = SQLITE_ERROR;
          break;
        }
        apSub = (SubProgram **)pSub->z;
        apSub[nSub++] = pOp->p4.pProgram;
        pSub->flags |= MEM_Blob;
        pSub->n = nSub*sizeof(SubProgram*);
        nRow += pOp->p4.pProgram->nOp;
      }
    }
    if( p->explain<2 ) break;
    if( pOp->opcode==OP_Explain ) break;
    if( pOp->opcode==OP_Init && p->pc>1 ) break;
  }

  if( rc==SQLITE_OK ){
    pOp = aOp + i;
    if( db->u1.isInterrupted ){
    if( AtomicLoad(&db->u1.isInterrupted) ){
      p->rc = SQLITE_INTERRUPT;
      rc = SQLITE_ERROR;
      sqlite3VdbeError(p, sqlite3ErrStr(p->rc));
    }else{
      char *zP4;
      if( p->explain==1 ){
      char *zP4 = sqlite3VdbeDisplayP4(db, pOp);
      if( p->explain==2 ){
        pMem->flags = MEM_Int;
        pMem->u.i = i;                                /* Program counter */
        pMem++;
    
        sqlite3VdbeMemSetInt64(pMem, pOp->p1);
        pMem->flags = MEM_Static|MEM_Str|MEM_Term;
        pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */
        assert( pMem->z!=0 );
        pMem->n = sqlite3Strlen30(pMem->z);
        pMem->enc = SQLITE_UTF8;
        pMem++;
      }

        sqlite3VdbeMemSetInt64(pMem+1, pOp->p2);
      pMem->flags = MEM_Int;
      pMem->u.i = pOp->p1;                          /* P1 */
      pMem++;

        sqlite3VdbeMemSetInt64(pMem+2, pOp->p3);
      pMem->flags = MEM_Int;
      pMem->u.i = pOp->p2;                          /* P2 */
      pMem++;

        sqlite3VdbeMemSetStr(pMem+3, zP4, -1, SQLITE_UTF8, sqlite3_free);     
      pMem->flags = MEM_Int;
      pMem->u.i = pOp->p3;                          /* P3 */
      pMem++;

        p->nResColumn = 4;
      if( sqlite3VdbeMemClearAndResize(pMem, 100) ){ /* P4 */
        assert( p->db->mallocFailed );
        return SQLITE_ERROR;
      }
      pMem->flags = MEM_Str|MEM_Term;
      zP4 = displayP4(pOp, pMem->z, pMem->szMalloc);
      if( zP4!=pMem->z ){
        pMem->n = 0;
        sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0);
      }else{
        assert( pMem->z!=0 );
        pMem->n = sqlite3Strlen30(pMem->z);
        pMem->enc = SQLITE_UTF8;
        sqlite3VdbeMemSetInt64(pMem+0, i);
        sqlite3VdbeMemSetStr(pMem+1, (char*)sqlite3OpcodeName(pOp->opcode),
                             -1, SQLITE_UTF8, SQLITE_STATIC);
      }
      pMem++;

        sqlite3VdbeMemSetInt64(pMem+2, pOp->p1);
        sqlite3VdbeMemSetInt64(pMem+3, pOp->p2);
      if( p->explain==1 ){
        if( sqlite3VdbeMemClearAndResize(pMem, 4) ){
        sqlite3VdbeMemSetInt64(pMem+4, pOp->p3);
          assert( p->db->mallocFailed );
          return SQLITE_ERROR;
        }
        pMem->flags = MEM_Str|MEM_Term;
        pMem->n = 2;
        sqlite3_snprintf(3, pMem->z, "%.2x", pOp->p5);   /* P5 */
        pMem->enc = SQLITE_UTF8;
        /* pMem+5 for p4 is done last */
        sqlite3VdbeMemSetInt64(pMem+6, pOp->p5);
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
        pMem++;
    
        {
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
        if( sqlite3VdbeMemClearAndResize(pMem, 500) ){
          char *zCom = sqlite3VdbeDisplayComment(db, pOp, zP4);
          assert( p->db->mallocFailed );
          return SQLITE_ERROR;
          sqlite3VdbeMemSetStr(pMem+7, zCom, -1, SQLITE_UTF8, sqlite3_free);
        }
        pMem->flags = MEM_Str|MEM_Term;
        pMem->n = displayComment(pOp, zP4, pMem->z, 500);
        pMem->enc = SQLITE_UTF8;
#else
        pMem->flags = MEM_Null;                       /* Comment */
        sqlite3VdbeMemSetNull(pMem+7);
#endif
      }

      p->nResColumn = 8 - 4*(p->explain-1);
      p->pResultSet = &p->aMem[1];
      p->rc = SQLITE_OK;
      rc = SQLITE_ROW;
        sqlite3VdbeMemSetStr(pMem+5, zP4, -1, SQLITE_UTF8, sqlite3_free);
        p->nResColumn = 8;
      }
      p->pResultRow = pMem;
      if( db->mallocFailed ){
        p->rc = SQLITE_NOMEM;
        rc = SQLITE_ERROR;
      }else{
        p->rc = SQLITE_OK;
        rc = SQLITE_ROW;
      }
    }
  }
  return rc;
}
#endif /* SQLITE_OMIT_EXPLAIN */

#ifdef SQLITE_DEBUG
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031



2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051

2052
2053
2054
2055

2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072

2073
2074
2075
2076



2077
2078
2079
2080
2081
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
2441
2442
2443
2444
2445
2446
2447



2448
2449
2450
2451
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
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490

2491
2492
2493
2494

2495
2496
2497
2498
2499
2500
2501
2502


2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519


2520
2521
2522
2523
2524
2525
2526
2527
2528







-
-
-
+
+
+



















-
+



-
+
















-
+



-
+
+
+





-
-
+
















-
-
+
+







#endif /* !SQLITE_OMIT_TRACE && SQLITE_ENABLE_IOTRACE */

/* An instance of this object describes bulk memory available for use
** by subcomponents of a prepared statement.  Space is allocated out
** of a ReusableSpace object by the allocSpace() routine below.
*/
struct ReusableSpace {
  u8 *pSpace;          /* Available memory */
  int nFree;           /* Bytes of available memory */
  int nNeeded;         /* Total bytes that could not be allocated */
  u8 *pSpace;            /* Available memory */
  sqlite3_int64 nFree;   /* Bytes of available memory */
  sqlite3_int64 nNeeded; /* Total bytes that could not be allocated */
};

/* Try to allocate nByte bytes of 8-byte aligned bulk memory for pBuf
** from the ReusableSpace object.  Return a pointer to the allocated
** memory on success.  If insufficient memory is available in the
** ReusableSpace object, increase the ReusableSpace.nNeeded
** value by the amount needed and return NULL.
**
** If pBuf is not initially NULL, that means that the memory has already
** been allocated by a prior call to this routine, so just return a copy
** of pBuf and leave ReusableSpace unchanged.
**
** This allocator is employed to repurpose unused slots at the end of the
** opcode array of prepared state for other memory needs of the prepared
** statement.
*/
static void *allocSpace(
  struct ReusableSpace *p,  /* Bulk memory available for allocation */
  void *pBuf,               /* Pointer to a prior allocation */
  int nByte                 /* Bytes of memory needed */
  sqlite3_int64 nByte       /* Bytes of memory needed. */
){
  assert( EIGHT_BYTE_ALIGNMENT(p->pSpace) );
  if( pBuf==0 ){
    nByte = ROUND8(nByte);
    nByte = ROUND8P(nByte);
    if( nByte <= p->nFree ){
      p->nFree -= nByte;
      pBuf = &p->pSpace[p->nFree];
    }else{
      p->nNeeded += nByte;
    }
  }
  assert( EIGHT_BYTE_ALIGNMENT(pBuf) );
  return pBuf;
}

/*
** Rewind the VDBE back to the beginning in preparation for
** running it.
*/
void sqlite3VdbeRewind(Vdbe *p){
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
#if defined(SQLITE_DEBUG)
  int i;
#endif
  assert( p!=0 );
  assert( p->magic==VDBE_MAGIC_INIT || p->magic==VDBE_MAGIC_RESET );
  assert( p->eVdbeState==VDBE_INIT_STATE
       || p->eVdbeState==VDBE_READY_STATE
       || p->eVdbeState==VDBE_HALT_STATE );

  /* There should be at least one opcode.
  */
  assert( p->nOp>0 );

  /* Set the magic to VDBE_MAGIC_RUN sooner rather than later. */
  p->magic = VDBE_MAGIC_RUN;
  p->eVdbeState = VDBE_READY_STATE;

#ifdef SQLITE_DEBUG
  for(i=0; i<p->nMem; i++){
    assert( p->aMem[i].db==p->db );
  }
#endif
  p->pc = -1;
  p->rc = SQLITE_OK;
  p->errorAction = OE_Abort;
  p->nChange = 0;
  p->cacheCtr = 1;
  p->minWriteFileFormat = 255;
  p->iStatement = 0;
  p->nFkConstraint = 0;
#ifdef VDBE_PROFILE
  for(i=0; i<p->nOp; i++){
    p->aOp[i].cnt = 0;
    p->aOp[i].cycles = 0;
    p->aOp[i].nExec = 0;
    p->aOp[i].nCycle = 0;
  }
#endif
}

/*
** Prepare a virtual machine for execution for the first time after
** creating the virtual machine.  This involves things such
2132
2133
2134
2135
2136
2137
2138
2139

2140


2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160

2161
2162
2163
2164
2165
2166
2167
2168
2169
2170





















2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189





2190
2191
2192
2193

2194
2195
2196
2197
2198








2199
2200
2201
2202
2203
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
2234
2235
2236
2237
2238
2239
2240


2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267






2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2552
2553
2554
2555
2556
2557
2558

2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581

2582
2583
2584
2585
2586
2587
2588
2589
2590


2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624






2625
2626
2627
2628
2629




2630
2631
2632



2633
2634
2635
2636
2637
2638
2639
2640


2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651



2652
2653
2654
2655
2656
2657
2658
2659
2660

2661


2662

2663
2664
2665
2666
2667
2668
2669







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
2704
2705
2706
2707
2708



2709
2710
2711
2712
2713
2714
2715







-
+

+
+



















-
+








-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+













-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
+


-
-
-
+
+
+
+
+
+
+
+
-
-











-
-
-









-
+
-
-
+
-
+






-
-
-
-
-
-
-
+
+
-



















-
-
-
-
-
-
-
+
+
+
+
+
+
-












-
-
-







  int nArg;                      /* Number of arguments in subprograms */
  int n;                         /* Loop counter */
  struct ReusableSpace x;        /* Reusable bulk memory */

  assert( p!=0 );
  assert( p->nOp>0 );
  assert( pParse!=0 );
  assert( p->magic==VDBE_MAGIC_INIT );
  assert( p->eVdbeState==VDBE_INIT_STATE );
  assert( pParse==p->pParse );
  p->pVList = pParse->pVList;
  pParse->pVList =  0;
  db = p->db;
  assert( db->mallocFailed==0 );
  nVar = pParse->nVar;
  nMem = pParse->nMem;
  nCursor = pParse->nTab;
  nArg = pParse->nMaxArg;
  
  /* Each cursor uses a memory cell.  The first cursor (cursor 0) can
  ** use aMem[0] which is not otherwise used by the VDBE program.  Allocate
  ** space at the end of aMem[] for cursors 1 and greater.
  ** See also: allocateCursor().
  */
  nMem += nCursor;
  if( nCursor==0 && nMem>0 ) nMem++;  /* Space for aMem[0] even if not used */

  /* Figure out how much reusable memory is available at the end of the
  ** opcode array.  This extra memory will be reallocated for other elements
  ** of the prepared statement.
  */
  n = ROUND8(sizeof(Op)*p->nOp);              /* Bytes of opcode memory used */
  n = ROUND8P(sizeof(Op)*p->nOp);             /* Bytes of opcode memory used */
  x.pSpace = &((u8*)p->aOp)[n];               /* Unused opcode memory */
  assert( EIGHT_BYTE_ALIGNMENT(x.pSpace) );
  x.nFree = ROUNDDOWN8(pParse->szOpAlloc - n);  /* Bytes of unused memory */
  assert( x.nFree>=0 );
  assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) );

  resolveP2Values(p, &nArg);
  p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort);
  if( pParse->explain && nMem<10 ){
    nMem = 10;
  if( pParse->explain ){
    static const char * const azColName[] = {
       "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment",
       "id", "parent", "notused", "detail"
    };
    int iFirst, mx, i;
    if( nMem<10 ) nMem = 10;
    p->explain = pParse->explain;
    if( pParse->explain==2 ){
      sqlite3VdbeSetNumCols(p, 4);
      iFirst = 8;
      mx = 12;
    }else{
      sqlite3VdbeSetNumCols(p, 8);
      iFirst = 0;
      mx = 8;
    }
    for(i=iFirst; i<mx; i++){
      sqlite3VdbeSetColName(p, i-iFirst, COLNAME_NAME,
                            azColName[i], SQLITE_STATIC);
    }
  }
  p->expired = 0;

  /* Memory for registers, parameters, cursor, etc, is allocated in one or two
  ** passes.  On the first pass, we try to reuse unused memory at the 
  ** end of the opcode array.  If we are unable to satisfy all memory
  ** requirements by reusing the opcode array tail, then the second
  ** pass will fill in the remainder using a fresh memory allocation.  
  **
  ** This two-pass approach that reuses as much memory as possible from
  ** the leftover memory at the end of the opcode array.  This can significantly
  ** reduce the amount of memory held by a prepared statement.
  */
  do {
    x.nNeeded = 0;
    p->aMem = allocSpace(&x, p->aMem, nMem*sizeof(Mem));
    p->aVar = allocSpace(&x, p->aVar, nVar*sizeof(Mem));
    p->apArg = allocSpace(&x, p->apArg, nArg*sizeof(Mem*));
    p->apCsr = allocSpace(&x, p->apCsr, nCursor*sizeof(VdbeCursor*));
  x.nNeeded = 0;
  p->aMem = allocSpace(&x, 0, nMem*sizeof(Mem));
  p->aVar = allocSpace(&x, 0, nVar*sizeof(Mem));
  p->apArg = allocSpace(&x, 0, nArg*sizeof(Mem*));
  p->apCsr = allocSpace(&x, 0, nCursor*sizeof(VdbeCursor*));
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
    p->anExec = allocSpace(&x, p->anExec, p->nOp*sizeof(i64));
#endif
    if( x.nNeeded==0 ) break;
  if( x.nNeeded ){
    x.pSpace = p->pFree = sqlite3DbMallocRawNN(db, x.nNeeded);
    x.nFree = x.nNeeded;
  }while( !db->mallocFailed );

  p->pVList = pParse->pVList;
    if( !db->mallocFailed ){
      p->aMem = allocSpace(&x, p->aMem, nMem*sizeof(Mem));
      p->aVar = allocSpace(&x, p->aVar, nVar*sizeof(Mem));
      p->apArg = allocSpace(&x, p->apArg, nArg*sizeof(Mem*));
      p->apCsr = allocSpace(&x, p->apCsr, nCursor*sizeof(VdbeCursor*));
    }
  }

  pParse->pVList =  0;
  p->explain = pParse->explain;
  if( db->mallocFailed ){
    p->nVar = 0;
    p->nCursor = 0;
    p->nMem = 0;
  }else{
    p->nCursor = nCursor;
    p->nVar = (ynVar)nVar;
    initMemArray(p->aVar, nVar, db, MEM_Null);
    p->nMem = nMem;
    initMemArray(p->aMem, nMem, db, MEM_Undefined);
    memset(p->apCsr, 0, nCursor*sizeof(VdbeCursor*));
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
    memset(p->anExec, 0, p->nOp*sizeof(i64));
#endif
  }
  sqlite3VdbeRewind(p);
}

/*
** Close a VDBE cursor and release all the resources that cursor 
** happens to hold.
*/
void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
  if( pCx==0 ){
  if( pCx ) sqlite3VdbeFreeCursorNN(p,pCx);
    return;
  }
}
  assert( pCx->pBtx==0 || pCx->eCurType==CURTYPE_BTREE );
void sqlite3VdbeFreeCursorNN(Vdbe *p, VdbeCursor *pCx){
  switch( pCx->eCurType ){
    case CURTYPE_SORTER: {
      sqlite3VdbeSorterClose(p->db, pCx);
      break;
    }
    case CURTYPE_BTREE: {
      if( pCx->isEphemeral ){
        if( pCx->pBtx ) sqlite3BtreeClose(pCx->pBtx);
        /* The pCx->pCursor will be close automatically, if it exists, by
        ** the call above. */
      }else{
        assert( pCx->uc.pCursor!=0 );
        sqlite3BtreeCloseCursor(pCx->uc.pCursor);
      assert( pCx->uc.pCursor!=0 );
      sqlite3BtreeCloseCursor(pCx->uc.pCursor);
      }
      break;
    }
#ifndef SQLITE_OMIT_VIRTUALTABLE
    case CURTYPE_VTAB: {
      sqlite3_vtab_cursor *pVCur = pCx->uc.pVCur;
      const sqlite3_module *pModule = pVCur->pVtab->pModule;
      assert( pVCur->pVtab->nRef>0 );
      pVCur->pVtab->nRef--;
      pModule->xClose(pVCur);
      break;
    }
#endif
  }
}

/*
** Close all cursors in the current frame.
*/
static void closeCursorsInFrame(Vdbe *p){
  if( p->apCsr ){
    int i;
    for(i=0; i<p->nCursor; i++){
      VdbeCursor *pC = p->apCsr[i];
      if( pC ){
        sqlite3VdbeFreeCursor(p, pC);
        p->apCsr[i] = 0;
  int i;
  for(i=0; i<p->nCursor; i++){
    VdbeCursor *pC = p->apCsr[i];
    if( pC ){
      sqlite3VdbeFreeCursorNN(p, pC);
      p->apCsr[i] = 0;
      }
    }
  }
}

/*
** Copy the values stored in the VdbeFrame structure to its Vdbe. This
** is used, for example, when a trigger sub-program is halted to restore
** control to the main program.
*/
int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){
  Vdbe *v = pFrame->v;
  closeCursorsInFrame(v);
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
  v->anExec = pFrame->anExec;
#endif
  v->aOp = pFrame->aOp;
  v->nOp = pFrame->nOp;
  v->aMem = pFrame->aMem;
  v->nMem = pFrame->nMem;
  v->apCsr = pFrame->apCsr;
  v->nCursor = pFrame->nCursor;
  v->db->lastRowid = pFrame->lastRowid;
2310
2311
2312
2313
2314
2315
2316
2317
2318

2319
2320
2321
2322
2323
2324
2325
2326
2735
2736
2737
2738
2739
2740
2741


2742

2743
2744
2745
2746
2747
2748
2749







-
-
+
-







    for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent);
    sqlite3VdbeFrameRestore(pFrame);
    p->pFrame = 0;
    p->nFrame = 0;
  }
  assert( p->nFrame==0 );
  closeCursorsInFrame(p);
  if( p->aMem ){
    releaseMemArray(p->aMem, p->nMem);
  releaseMemArray(p->aMem, p->nMem);
  }
  while( p->pDelFrame ){
    VdbeFrame *pDel = p->pDelFrame;
    p->pDelFrame = pDel->pParent;
    sqlite3VdbeFrameDelete(pDel);
  }

  /* Delete any auxdata allocations made by the VM */
2381
2382
2383
2384
2385
2386
2387
2388

2389
2390
2391
2392
2393
2394

2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407

2408
2409
2410
2411
2412
2413
2414
2415
2416

2417
2418
2419
2420
2421
2422


2423
2424

2425
2426
2427
2428
2429
2430
2431
2804
2805
2806
2807
2808
2809
2810

2811
2812
2813
2814
2815
2816

2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829

2830
2831
2832
2833
2834
2835
2836
2837
2838

2839
2840
2841
2842
2843


2844
2845
2846

2847
2848
2849
2850
2851
2852
2853
2854







-
+





-
+












-
+








-
+




-
-
+
+

-
+







  return rc;
}

/*
** A read or write transaction may or may not be active on database handle
** db. If a transaction is active, commit it. If there is a
** write-transaction spanning more than one database file, this routine
** takes care of the master journal trickery.
** takes care of the super-journal trickery.
*/
static int vdbeCommit(sqlite3 *db, Vdbe *p){
  int i;
  int nTrans = 0;  /* Number of databases with an active write-transaction
                   ** that are candidates for a two-phase commit using a
                   ** master-journal */
                   ** super-journal */
  int rc = SQLITE_OK;
  int needXcommit = 0;

#ifdef SQLITE_OMIT_VIRTUALTABLE
  /* With this option, sqlite3VtabSync() is defined to be simply 
  ** SQLITE_OK so p is not used. 
  */
  UNUSED_PARAMETER(p);
#endif

  /* Before doing anything else, call the xSync() callback for any
  ** virtual module tables written in this transaction. This has to
  ** be done before determining whether a master journal file is 
  ** be done before determining whether a super-journal file is 
  ** required, as an xSync() callback may add an attached database
  ** to the transaction.
  */
  rc = sqlite3VtabSync(db, p);

  /* This loop determines (a) if the commit hook should be invoked and
  ** (b) how many database files have open write transactions, not 
  ** including the temp database. (b) is important because if more than 
  ** one database file has an open write transaction, a master journal
  ** one database file has an open write transaction, a super-journal
  ** file is required for an atomic commit.
  */ 
  for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ 
    Btree *pBt = db->aDb[i].pBt;
    if( sqlite3BtreeIsInTrans(pBt) ){
      /* Whether or not a database might need a master journal depends upon
    if( sqlite3BtreeTxnState(pBt)==SQLITE_TXN_WRITE ){
      /* Whether or not a database might need a super-journal depends upon
      ** its journal mode (among other things).  This matrix determines which
      ** journal modes use a master journal and which do not */
      ** journal modes use a super-journal and which do not */
      static const u8 aMJNeeded[] = {
        /* DELETE   */  1,
        /* PERSIST   */ 1,
        /* OFF       */ 0,
        /* TRUNCATE  */ 1,
        /* MEMORY    */ 0,
        /* WAL       */ 0
2443
2444
2445
2446
2447
2448
2449
2450

2451
2452
2453
2454
2455
2456

2457
2458
2459
2460
2461
2462
2463
2866
2867
2868
2869
2870
2871
2872

2873
2874
2875
2876
2877
2878

2879
2880
2881
2882
2883
2884
2885
2886







-
+





-
+







      }
      rc = sqlite3BtreeExclusiveLock(pBt);
      sqlite3BtreeLeave(pBt);
    }
  }

#ifndef SQLITE_OMIT_CONCURRENT
  if( db->bConcurrent && (rc & 0xFF)==SQLITE_BUSY ){
  if( db->eConcurrent && (rc & 0xFF)==SQLITE_BUSY ){
    /* An SQLITE_BUSY or SQLITE_BUSY_SNAPSHOT was encountered while 
    ** attempting to take the WRITER lock on a wal file. Release the
    ** WRITER locks on all wal files and return early.  */
    for(i=0; i<db->nDb; i++){
      Btree *pBt = db->aDb[i].pBt;
      if( sqlite3BtreeIsInTrans(pBt) ){
      if( sqlite3BtreeTxnState(pBt)==SQLITE_TXN_WRITE ){
        sqlite3BtreeEnter(pBt);
        sqlite3PagerDropExclusiveLock(sqlite3BtreePager(pBt));
        sqlite3BtreeLeave(pBt);
      }
    }
  }
#endif
2472
2473
2474
2475
2476
2477
2478
2479

2480
2481
2482
2483
2484
2485
2486
2895
2896
2897
2898
2899
2900
2901

2902
2903
2904
2905
2906
2907
2908
2909







-
+







    if( rc ){
      return SQLITE_CONSTRAINT_COMMITHOOK;
    }
  }

  /* The simple case - no more than one database file (not counting the
  ** TEMP database) has a transaction active.   There is no need for the
  ** master-journal.
  ** super-journal.
  **
  ** If the return value of sqlite3BtreeGetFilename() is a zero length
  ** string, it means the main database is :memory: or a temp file.  In 
  ** that case we do not support atomic multi-file commits, so use the 
  ** simple case then too.
  */
  if( 0==sqlite3Strlen30(sqlite3BtreeGetFilename(db->aDb[0].pBt))
2506
2507
2508
2509
2510
2511
2512
2513

2514
2515
2516
2517
2518
2519

2520
2521

2522
2523
2524
2525
2526
2527

2528
2529
2530



2531
2532
2533
2534
2535
2536


2537
2538
2539

2540
2541
2542
2543
2544

2545
2546

2547
2548
2549
2550



2551
2552
2553
2554


2555
2556

2557
2558
2559
2560

2561
2562
2563
2564
2565
2566
2567



2568
2569
2570
2571
2572

2573
2574
2575
2576
2577
2578

2579
2580
2581
2582
2583



2584
2585
2586
2587
2588
2589

2590
2591
2592
2593


2594
2595
2596
2597



2598
2599
2600
2601
2602
2603


2604
2605
2606
2607
2608


2609
2610
2611
2612
2613
2614

2615
2616
2617

2618
2619
2620

2621
2622
2623
2624

2625
2626
2627
2628
2629
2630



2631
2632
2633
2634
2635
2636
2637
2929
2930
2931
2932
2933
2934
2935

2936
2937
2938
2939
2940
2941

2942
2943

2944
2945
2946
2947
2948
2949

2950
2951


2952
2953
2954
2955
2956
2957
2958


2959
2960
2961
2962

2963
2964
2965
2966
2967

2968
2969

2970
2971



2972
2973
2974
2975
2976


2977
2978
2979

2980
2981
2982
2983

2984
2985
2986
2987
2988



2989
2990
2991
2992
2993
2994
2995

2996
2997
2998
2999
3000
3001

3002
3003
3004



3005
3006
3007
3008
3009
3010
3011
3012

3013
3014
3015


3016
3017
3018



3019
3020
3021
3022
3023
3024
3025


3026
3027
3028
3029
3030


3031
3032
3033
3034
3035
3036
3037

3038
3039
3040

3041
3042
3043

3044
3045
3046
3047

3048
3049
3050
3051



3052
3053
3054
3055
3056
3057
3058
3059
3060
3061







-
+





-
+

-
+





-
+

-
-
+
+
+




-
-
+
+


-
+




-
+

-
+

-
-
-
+
+
+


-
-
+
+

-
+



-
+




-
-
-
+
+
+




-
+





-
+


-
-
-
+
+
+





-
+


-
-
+
+

-
-
-
+
+
+




-
-
+
+



-
-
+
+





-
+


-
+


-
+



-
+



-
-
-
+
+
+







    }
    if( rc==SQLITE_OK ){
      sqlite3VtabCommit(db);
    }
  }

  /* The complex case - There is a multi-file write-transaction active.
  ** This requires a master journal file to ensure the transaction is
  ** This requires a super-journal file to ensure the transaction is
  ** committed atomically.
  */
#ifndef SQLITE_OMIT_DISKIO
  else{
    sqlite3_vfs *pVfs = db->pVfs;
    char *zMaster = 0;   /* File-name for the master journal */
    char *zSuper = 0;   /* File-name for the super-journal */
    char const *zMainFile = sqlite3BtreeGetFilename(db->aDb[0].pBt);
    sqlite3_file *pMaster = 0;
    sqlite3_file *pSuperJrnl = 0;
    i64 offset = 0;
    int res;
    int retryCount = 0;
    int nMainFile;

    /* Select a master journal file name */
    /* Select a super-journal file name */
    nMainFile = sqlite3Strlen30(zMainFile);
    zMaster = sqlite3MPrintf(db, "%s-mjXXXXXX9XXz", zMainFile);
    if( zMaster==0 ) return SQLITE_NOMEM_BKPT;
    zSuper = sqlite3MPrintf(db, "%.4c%s%.16c", 0,zMainFile,0);
    if( zSuper==0 ) return SQLITE_NOMEM_BKPT;
    zSuper += 4;
    do {
      u32 iRandom;
      if( retryCount ){
        if( retryCount>100 ){
          sqlite3_log(SQLITE_FULL, "MJ delete: %s", zMaster);
          sqlite3OsDelete(pVfs, zMaster, 0);
          sqlite3_log(SQLITE_FULL, "MJ delete: %s", zSuper);
          sqlite3OsDelete(pVfs, zSuper, 0);
          break;
        }else if( retryCount==1 ){
          sqlite3_log(SQLITE_FULL, "MJ collide: %s", zMaster);
          sqlite3_log(SQLITE_FULL, "MJ collide: %s", zSuper);
        }
      }
      retryCount++;
      sqlite3_randomness(sizeof(iRandom), &iRandom);
      sqlite3_snprintf(13, &zMaster[nMainFile], "-mj%06X9%02X",
      sqlite3_snprintf(13, &zSuper[nMainFile], "-mj%06X9%02X",
                               (iRandom>>8)&0xffffff, iRandom&0xff);
      /* The antipenultimate character of the master journal name must
      /* The antipenultimate character of the super-journal name must
      ** be "9" to avoid name collisions when using 8+3 filenames. */
      assert( zMaster[sqlite3Strlen30(zMaster)-3]=='9' );
      sqlite3FileSuffix3(zMainFile, zMaster);
      rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res);
      assert( zSuper[sqlite3Strlen30(zSuper)-3]=='9' );
      sqlite3FileSuffix3(zMainFile, zSuper);
      rc = sqlite3OsAccess(pVfs, zSuper, SQLITE_ACCESS_EXISTS, &res);
    }while( rc==SQLITE_OK && res );
    if( rc==SQLITE_OK ){
      /* Open the master journal. */
      rc = sqlite3OsOpenMalloc(pVfs, zMaster, &pMaster, 
      /* Open the super-journal. */
      rc = sqlite3OsOpenMalloc(pVfs, zSuper, &pSuperJrnl, 
          SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|
          SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_MASTER_JOURNAL, 0
          SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_SUPER_JOURNAL, 0
      );
    }
    if( rc!=SQLITE_OK ){
      sqlite3DbFree(db, zMaster);
      sqlite3DbFree(db, zSuper-4);
      return rc;
    }
 
    /* Write the name of each database file in the transaction into the new
    ** master journal file. If an error occurs at this point close
    ** and delete the master journal file. All the individual journal files
    ** still have 'null' as the master journal pointer, so they will roll
    ** super-journal file. If an error occurs at this point close
    ** and delete the super-journal file. All the individual journal files
    ** still have 'null' as the super-journal pointer, so they will roll
    ** back independently if a failure occurs.
    */
    for(i=0; i<db->nDb; i++){
      Btree *pBt = db->aDb[i].pBt;
      if( sqlite3BtreeIsInTrans(pBt) ){
      if( sqlite3BtreeTxnState(pBt)==SQLITE_TXN_WRITE ){
        char const *zFile = sqlite3BtreeGetJournalname(pBt);
        if( zFile==0 ){
          continue;  /* Ignore TEMP and :memory: databases */
        }
        assert( zFile[0]!=0 );
        rc = sqlite3OsWrite(pMaster, zFile, sqlite3Strlen30(zFile)+1, offset);
        rc = sqlite3OsWrite(pSuperJrnl, zFile, sqlite3Strlen30(zFile)+1,offset);
        offset += sqlite3Strlen30(zFile)+1;
        if( rc!=SQLITE_OK ){
          sqlite3OsCloseFree(pMaster);
          sqlite3OsDelete(pVfs, zMaster, 0);
          sqlite3DbFree(db, zMaster);
          sqlite3OsCloseFree(pSuperJrnl);
          sqlite3OsDelete(pVfs, zSuper, 0);
          sqlite3DbFree(db, zSuper-4);
          return rc;
        }
      }
    }

    /* Sync the master journal file. If the IOCAP_SEQUENTIAL device
    /* Sync the super-journal file. If the IOCAP_SEQUENTIAL device
    ** flag is set this is not required.
    */
    if( 0==(sqlite3OsDeviceCharacteristics(pMaster)&SQLITE_IOCAP_SEQUENTIAL)
     && SQLITE_OK!=(rc = sqlite3OsSync(pMaster, SQLITE_SYNC_NORMAL))
    if( 0==(sqlite3OsDeviceCharacteristics(pSuperJrnl)&SQLITE_IOCAP_SEQUENTIAL)
     && SQLITE_OK!=(rc = sqlite3OsSync(pSuperJrnl, SQLITE_SYNC_NORMAL))
    ){
      sqlite3OsCloseFree(pMaster);
      sqlite3OsDelete(pVfs, zMaster, 0);
      sqlite3DbFree(db, zMaster);
      sqlite3OsCloseFree(pSuperJrnl);
      sqlite3OsDelete(pVfs, zSuper, 0);
      sqlite3DbFree(db, zSuper-4);
      return rc;
    }

    /* Sync all the db files involved in the transaction. The same call
    ** sets the master journal pointer in each individual journal. If
    ** an error occurs here, do not delete the master journal file.
    ** sets the super-journal pointer in each individual journal. If
    ** an error occurs here, do not delete the super-journal file.
    **
    ** If the error occurs during the first call to
    ** sqlite3BtreeCommitPhaseOne(), then there is a chance that the
    ** master journal file will be orphaned. But we cannot delete it,
    ** in case the master journal file name was written into the journal
    ** super-journal file will be orphaned. But we cannot delete it,
    ** in case the super-journal file name was written into the journal
    ** file before the failure occurred.
    */
    for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ 
      Btree *pBt = db->aDb[i].pBt;
      if( pBt ){
        rc = sqlite3BtreeCommitPhaseOne(pBt, zMaster);
        rc = sqlite3BtreeCommitPhaseOne(pBt, zSuper);
      }
    }
    sqlite3OsCloseFree(pMaster);
    sqlite3OsCloseFree(pSuperJrnl);
    assert( rc!=SQLITE_BUSY );
    if( rc!=SQLITE_OK ){
      sqlite3DbFree(db, zMaster);
      sqlite3DbFree(db, zSuper-4);
      return rc;
    }

    /* Delete the master journal file. This commits the transaction. After
    /* Delete the super-journal file. This commits the transaction. After
    ** doing this the directory is synced again before any individual
    ** transaction files are deleted.
    */
    rc = sqlite3OsDelete(pVfs, zMaster, 1);
    sqlite3DbFree(db, zMaster);
    zMaster = 0;
    rc = sqlite3OsDelete(pVfs, zSuper, 1);
    sqlite3DbFree(db, zSuper-4);
    zSuper = 0;
    if( rc ){
      return rc;
    }

    /* All files and directories have already been synced, so the following
    ** calls to sqlite3BtreeCommitPhaseTwo() are only closing files and
    ** deleting or truncating journals. If something goes wrong while
2675
2676
2677
2678
2679
2680
2681
2682

2683
2684
2685
2686
2687
2688
2689
3099
3100
3101
3102
3103
3104
3105

3106
3107
3108
3109
3110
3111
3112
3113







-
+







  p = db->pVdbe;
  while( p ){
    if( sqlite3_stmt_busy((sqlite3_stmt*)p) ){
      cnt++;
      if( p->readOnly==0 ) nWrite++;
      if( p->bIsReader ) nRead++;
    }
    p = p->pNext;
    p = p->pVNext;
  }
  assert( cnt==db->nVdbeActive );
  assert( nWrite==db->nVdbeWrite );
  assert( nRead==db->nVdbeRead );
}
#else
#define checkActiveVdbeCnt(x)
2768
2769
2770
2771
2772
2773
2774

2775

2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788



2789
2790
2791
2792
2793
2794
2795
3192
3193
3194
3195
3196
3197
3198
3199

3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210



3211
3212
3213
3214
3215
3216
3217
3218
3219
3220







+
-
+










-
-
-
+
+
+







  sqlite3 *db = p->db;
  if( (deferred && (db->nDeferredCons+db->nDeferredImmCons)>0) 
   || (!deferred && p->nFkConstraint>0) 
  ){
    p->rc = SQLITE_CONSTRAINT_FOREIGNKEY;
    p->errorAction = OE_Abort;
    sqlite3VdbeError(p, "FOREIGN KEY constraint failed");
    if( (p->prepFlags & SQLITE_PREPARE_SAVESQL)==0 ) return SQLITE_ERROR;
    return SQLITE_ERROR;
    return SQLITE_CONSTRAINT_FOREIGNKEY;
  }
  return SQLITE_OK;
}
#endif

/*
** This routine is called the when a VDBE tries to halt.  If the VDBE
** has made changes and is in autocommit mode, then commit those
** changes.  If a rollback is needed, then do the rollback.
**
** This routine is the only way to move the state of a VM from
** SQLITE_MAGIC_RUN to SQLITE_MAGIC_HALT.  It is harmless to
** call this on a VM that is in the SQLITE_MAGIC_HALT state.
** This routine is the only way to move the sqlite3eOpenState of a VM from
** SQLITE_STATE_RUN to SQLITE_STATE_HALT.  It is harmless to
** call this on a VM that is in the SQLITE_STATE_HALT state.
**
** Return an error code.  If the commit could not complete because of
** lock contention, return SQLITE_BUSY.  If SQLITE_BUSY is returned, it
** means the close did not happen and needs to be repeated.
*/
int sqlite3VdbeHalt(Vdbe *p){
  int rc;                         /* Used to store transient return codes */
2807
2808
2809
2810
2811
2812
2813
2814

2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825

2826
2827
2828
2829
2830
2831
2832
2833

2834
2835
2836








2837
2838
2839
2840
2841
2842
2843
3232
3233
3234
3235
3236
3237
3238

3239


3240
3241
3242
3243
3244
3245
3246
3247

3248
3249
3250
3251
3252
3253
3254
3255
3256
3257



3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272







-
+
-
-








-
+








+
-
-
-
+
+
+
+
+
+
+
+







  **     SQLITE_INTERRUPT
  **
  ** Then the internal cache might have been left in an inconsistent
  ** state.  We need to rollback the statement transaction, if there is
  ** one, or the complete transaction if there is no statement transaction.
  */

  if( p->magic!=VDBE_MAGIC_RUN ){
  assert( p->eVdbeState==VDBE_RUN_STATE );
    return SQLITE_OK;
  }
  if( db->mallocFailed ){
    p->rc = SQLITE_NOMEM_BKPT;
  }
  closeAllCursors(p);
  checkActiveVdbeCnt(db);

  /* No commit or rollback needed if the program never started or if the
  ** SQL statement does not read or write a database file.  */
  if( p->pc>=0 && p->bIsReader ){
  if( p->bIsReader ){
    int mrc;   /* Primary error code from p->rc */
    int eStatementOp = 0;
    int isSpecialError;            /* Set to true if a 'special' error */

    /* Lock all btrees used by the statement */
    sqlite3VdbeEnter(p);

    /* Check for one of the special errors */
    if( p->rc ){
    mrc = p->rc & 0xff;
    isSpecialError = mrc==SQLITE_NOMEM || mrc==SQLITE_IOERR
                     || mrc==SQLITE_INTERRUPT || mrc==SQLITE_FULL;
      mrc = p->rc & 0xff;
      isSpecialError = mrc==SQLITE_NOMEM
                    || mrc==SQLITE_IOERR
                    || mrc==SQLITE_INTERRUPT
                    || mrc==SQLITE_FULL;
    }else{
      mrc = isSpecialError = 0;
    }
    if( isSpecialError ){
      /* If the query was read-only and the error code is SQLITE_INTERRUPT, 
      ** no rollback is necessary. Otherwise, at least a savepoint 
      ** transaction must be rolled back to restore the database to a 
      ** consistent state.
      **
      ** Even if the statement is read-only, it is important to perform
2853
2854
2855
2856
2857
2858
2859
2860

2861
2862
2863
2864
2865
2866
2867

2868
2869
2870
2871
2872
2873
2874
3282
3283
3284
3285
3286
3287
3288

3289
3290
3291
3292
3293
3294
3295

3296
3297
3298
3299
3300
3301
3302
3303







-
+






-
+







        }else{
          /* We are forced to roll back the active transaction. Before doing
          ** so, abort any other statements this handle currently has active.
          */
          sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
          sqlite3CloseSavepoints(db);
          db->autoCommit = 1;
          db->bConcurrent = 0;
          db->eConcurrent = CONCURRENT_NONE;
          p->nChange = 0;
        }
      }
    }

    /* Check for immediate foreign key violations. */
    if( p->rc==SQLITE_OK ){
    if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){
      sqlite3VdbeCheckFk(p, 0);
    }
  
    /* If the auto-commit flag is set and this is the only active writer 
    ** VM, then we do either a commit or rollback of the current transaction. 
    **
    ** Note: This block also runs if one of the special errors handled 
2882
2883
2884
2885
2886
2887
2888



2889
2890
2891
2892
2893
2894
2895
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327







+
+
+







        rc = sqlite3VdbeCheckFk(p, 1);
        if( rc!=SQLITE_OK ){
          if( NEVER(p->readOnly) ){
            sqlite3VdbeLeave(p);
            return SQLITE_ERROR;
          }
          rc = SQLITE_CONSTRAINT_FOREIGNKEY;
        }else if( db->flags & SQLITE_CorruptRdOnly ){
          rc = SQLITE_CORRUPT;
          db->flags &= ~SQLITE_CorruptRdOnly;
        }else{ 
          /* The auto-commit flag is true, the vdbe program was successful 
          ** or hit an 'OR FAIL' constraint and there are no deferred foreign
          ** key constraints to hold up the transaction. This means a commit 
          ** is required. */
          rc = vdbeCommit(db, p);
        }
2916
2917
2918
2919
2920
2921
2922
2923

2924
2925
2926
2927
2928
2929
2930
3348
3349
3350
3351
3352
3353
3354

3355
3356
3357
3358
3359
3360
3361
3362







-
+







        eStatementOp = SAVEPOINT_RELEASE;
      }else if( p->errorAction==OE_Abort ){
        eStatementOp = SAVEPOINT_ROLLBACK;
      }else{
        sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
        sqlite3CloseSavepoints(db);
        db->autoCommit = 1;
        db->bConcurrent = 0;
        db->eConcurrent = CONCURRENT_NONE;
        p->nChange = 0;
      }
    }
  
    /* If eStatementOp is non-zero, then a statement transaction needs to
    ** be committed or rolled back. Call sqlite3VdbeCloseStatement() to
    ** do so. If this operation returns an error, and the current statement
2938
2939
2940
2941
2942
2943
2944
2945

2946
2947
2948
2949
2950
2951
2952
3370
3371
3372
3373
3374
3375
3376

3377
3378
3379
3380
3381
3382
3383
3384







-
+







          p->rc = rc;
          sqlite3DbFree(db, p->zErrMsg);
          p->zErrMsg = 0;
        }
        sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
        sqlite3CloseSavepoints(db);
        db->autoCommit = 1;
        db->bConcurrent = 0;
        db->eConcurrent = CONCURRENT_NONE;
        p->nChange = 0;
      }
    }
  
    /* If this was an INSERT, UPDATE or DELETE and no statement transaction
    ** has been rolled back, update the database connection change-counter. 
    */
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973






2974
2975

2976
2977
2978
2979
2980
2981
2982
3392
3393
3394
3395
3396
3397
3398







3399
3400
3401
3402
3403
3404


3405
3406
3407
3408
3409
3410
3411
3412







-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
+







    }

    /* Release the locks */
    sqlite3VdbeLeave(p);
  }

  /* We have successfully halted and closed the VM.  Record this fact. */
  if( p->pc>=0 ){
    db->nVdbeActive--;
    if( !p->readOnly ) db->nVdbeWrite--;
    if( p->bIsReader ) db->nVdbeRead--;
    assert( db->nVdbeActive>=db->nVdbeRead );
    assert( db->nVdbeRead>=db->nVdbeWrite );
    assert( db->nVdbeWrite>=0 );
  db->nVdbeActive--;
  if( !p->readOnly ) db->nVdbeWrite--;
  if( p->bIsReader ) db->nVdbeRead--;
  assert( db->nVdbeActive>=db->nVdbeRead );
  assert( db->nVdbeRead>=db->nVdbeWrite );
  assert( db->nVdbeWrite>=0 );
  }
  p->magic = VDBE_MAGIC_HALT;
  p->eVdbeState = VDBE_HALT_STATE;
  checkActiveVdbeCnt(db);
  if( db->mallocFailed ){
    p->rc = SQLITE_NOMEM_BKPT;
  }

  /* If the auto-commit flag is set to true, then any locks that were held
  ** by connection db have now been released. Call sqlite3ConnectionUnlocked() 
3017
3018
3019
3020
3021
3022
3023

3024
3025
3026
3027
3028
3029
3030
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461







+







    sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT);
    sqlite3EndBenignMalloc();
    db->bBenignMalloc--;
  }else if( db->pErr ){
    sqlite3ValueSetNull(db->pErr);
  }
  db->errCode = rc;
  db->errByteOffset = -1;
  return rc;
}

#ifdef SQLITE_ENABLE_SQLLOG
/*
** If an SQLITE_CONFIG_SQLLOG hook is registered and the VM has been run, 
** invoke it.
3049
3050
3051
3052
3053
3054
3055
3056
3057


3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071

3072
3073
3074
3075
3076
3077
3078
3079

3080

3081
3082

3083
3084
3085
3086
3087


3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099

3100
3101
3102




3103
3104
3105
3106
3107
3108
3109
3480
3481
3482
3483
3484
3485
3486


3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501

3502
3503
3504
3505
3506
3507
3508
3509
3510
3511

3512


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







-
-
+
+













-
+








+
-
+
-
-
+
-
-
-
-
-
+
+












+
-
-
-
+
+
+
+







** Clean up a VDBE after execution but do not delete the VDBE just yet.
** Write any error messages into *pzErrMsg.  Return the result code.
**
** After this routine is run, the VDBE should be ready to be executed
** again.
**
** To look at it another way, this routine resets the state of the
** virtual machine from VDBE_MAGIC_RUN or VDBE_MAGIC_HALT back to
** VDBE_MAGIC_INIT.
** virtual machine from VDBE_RUN_STATE or VDBE_HALT_STATE back to
** VDBE_READY_STATE.
*/
int sqlite3VdbeReset(Vdbe *p){
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
  int i;
#endif

  sqlite3 *db;
  db = p->db;

  /* If the VM did not run to completion or if it encountered an
  ** error, then it might not have been halted properly.  So halt
  ** it now.
  */
  sqlite3VdbeHalt(p);
  if( p->eVdbeState==VDBE_RUN_STATE ) sqlite3VdbeHalt(p);

  /* If the VDBE has been run even partially, then transfer the error code
  ** and error message from the VDBE into the main database structure.  But
  ** if the VDBE has just been set to run but has not actually executed any
  ** instructions yet, leave the main database error information unchanged.
  */
  if( p->pc>=0 ){
    vdbeInvokeSqllog(p);
    if( db->pErr || p->zErrMsg ){
    sqlite3VdbeTransferError(p);
      sqlite3VdbeTransferError(p);
    if( p->runOnlyOnce ) p->expired = 1;
  }else if( p->rc && p->expired ){
    }else{
    /* The expired flag was set on the VDBE before the first call
    ** to sqlite3_step(). For consistency (since sqlite3_step() was
    ** called), set the database error in this case as well.
    */
    sqlite3ErrorWithMsg(db, p->rc, p->zErrMsg ? "%s" : 0, p->zErrMsg);
      db->errCode = p->rc;
    }
  }

  /* Reset register contents and reclaim error message memory.
  */
#ifdef SQLITE_DEBUG
  /* Execute assert() statements to ensure that the Vdbe.apCsr[] and 
  ** Vdbe.aMem[] arrays have already been cleaned up.  */
  if( p->apCsr ) for(i=0; i<p->nCursor; i++) assert( p->apCsr[i]==0 );
  if( p->aMem ){
    for(i=0; i<p->nMem; i++) assert( p->aMem[i].flags==MEM_Undefined );
  }
#endif
  if( p->zErrMsg ){
  sqlite3DbFree(db, p->zErrMsg);
  p->zErrMsg = 0;
  p->pResultSet = 0;
    sqlite3DbFree(db, p->zErrMsg);
    p->zErrMsg = 0;
  }
  p->pResultRow = 0;
#ifdef SQLITE_DEBUG
  p->nWrite = 0;
#endif

  /* Save profiling information from this VDBE run.
  */
#ifdef VDBE_PROFILE
3123
3124
3125
3126
3127
3128
3129


3130
3131
3132
3133



3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151



3152

3153
3154
3155
3156
3157
3158
3159
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562



3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573

3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585

3586
3587
3588
3589
3590
3591
3592
3593







+
+

-
-
-
+
+
+








-









+
+
+
-
+







          putc(c, out);
          pc = c;
        }
        if( pc!='\n' ) fprintf(out, "\n");
      }
      for(i=0; i<p->nOp; i++){
        char zHdr[100];
        i64 cnt = p->aOp[i].nExec;
        i64 cycles = p->aOp[i].nCycle;
        sqlite3_snprintf(sizeof(zHdr), zHdr, "%6u %12llu %8llu ",
           p->aOp[i].cnt,
           p->aOp[i].cycles,
           p->aOp[i].cnt>0 ? p->aOp[i].cycles/p->aOp[i].cnt : 0
           cnt,
           cycles,
           cnt>0 ? cycles/cnt : 0
        );
        fprintf(out, "%s", zHdr);
        sqlite3VdbePrintOp(out, i, &p->aOp[i]);
      }
      fclose(out);
    }
  }
#endif
  p->magic = VDBE_MAGIC_RESET;
  return p->rc & db->errMask;
}
 
/*
** Clean up and delete a VDBE after execution.  Return an integer which is
** the result code.  Write any error message text into *pzErrMsg.
*/
int sqlite3VdbeFinalize(Vdbe *p){
  int rc = SQLITE_OK;
  assert( VDBE_RUN_STATE>VDBE_READY_STATE );
  assert( VDBE_HALT_STATE>VDBE_READY_STATE );
  assert( VDBE_INIT_STATE<VDBE_READY_STATE );
  if( p->magic==VDBE_MAGIC_RUN || p->magic==VDBE_MAGIC_HALT ){
  if( p->eVdbeState>=VDBE_READY_STATE ){
    rc = sqlite3VdbeReset(p);
    assert( (rc & p->db->errMask)==rc );
  }
  sqlite3VdbeDelete(p);
  return rc;
}

3197
3198
3199
3200
3201
3202
3203
3204

3205

3206

3207



3208
3209
3210
3211
3212
3213

3214
3215
3216


3217
3218
3219
3220

3221
3222
3223
3224
3225
3226
3227
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
3659
3660
3661
3662
3663
3664







-
+

+

+
-
+
+
+





-
+

-
-
+
+


-
-
+







** Free all memory associated with the Vdbe passed as the second argument,
** except for object itself, which is preserved.
**
** The difference between this function and sqlite3VdbeDelete() is that
** VdbeDelete() also unlinks the Vdbe from the list of VMs associated with
** the database connection and frees the object itself.
*/
void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
static void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
  SubProgram *pSub, *pNext;
  assert( db!=0 );
  assert( p->db==0 || p->db==db );
  if( p->aColName ){
  releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
    releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
    sqlite3DbNNFreeNN(db, p->aColName);
  }
  for(pSub=p->pProgram; pSub; pSub=pNext){
    pNext = pSub->pNext;
    vdbeFreeOpArray(db, pSub->aOp, pSub->nOp);
    sqlite3DbFree(db, pSub);
  }
  if( p->magic!=VDBE_MAGIC_INIT ){
  if( p->eVdbeState!=VDBE_INIT_STATE ){
    releaseMemArray(p->aVar, p->nVar);
    sqlite3DbFree(db, p->pVList);
    sqlite3DbFree(db, p->pFree);
    if( p->pVList ) sqlite3DbNNFreeNN(db, p->pVList);
    if( p->pFree ) sqlite3DbNNFreeNN(db, p->pFree);
  }
  vdbeFreeOpArray(db, p->aOp, p->nOp);
  sqlite3DbFree(db, p->aColName);
  sqlite3DbFree(db, p->zSql);
  if( p->zSql ) sqlite3DbNNFreeNN(db, p->zSql);
#ifdef SQLITE_ENABLE_NORMALIZE
  sqlite3DbFree(db, p->zNormSql);
  {
    DblquoteStr *pThis, *pNext;
    for(pThis=p->pDblStr; pThis; pThis=pNext){
      pNext = pThis->pNextStr;
      sqlite3DbFree(db, pThis);
3243
3244
3245
3246
3247
3248
3249

3250
3251

3252
3253


3254
3255
3256
3257



3258
3259
3260
3261
3262
3263

3264
3265
3266
3267
3268
3269
3270
3271

3272
3273
3274
3275
3276
3277
3278
3279

3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297

3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313

3314
3315

3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357

3358
3359
3360
3361
3362
3363
3364
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690


3691
3692




3693
3694
3695


3696



3697
3698
3699
3700
3701
3702
3703
3704

3705
3706
3707
3708
3709
3710
3711
3712

3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730

3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746

3747
3748

3749































3750
3751
3752
3753
3754
3755
3756
3757
3758
3759

3760
3761
3762
3763
3764
3765
3766
3767







+


+
-
-
+
+
-
-
-
-
+
+
+
-
-

-
-
-
+







-
+







-
+

















-
+















-
+

-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-










-
+







** Delete an entire VDBE.
*/
void sqlite3VdbeDelete(Vdbe *p){
  sqlite3 *db;

  assert( p!=0 );
  db = p->db;
  assert( db!=0 );
  assert( sqlite3_mutex_held(db->mutex) );
  sqlite3VdbeClearObject(db, p);
  if( db->pnBytesFreed==0 ){
  if( p->pPrev ){
    p->pPrev->pNext = p->pNext;
    assert( p->ppVPrev!=0 );
    *p->ppVPrev = p->pVNext;
  }else{
    assert( db->pVdbe==p );
    db->pVdbe = p->pNext;
  }
    if( p->pVNext ){
      p->pVNext->ppVPrev = p->ppVPrev;
    }
  if( p->pNext ){
    p->pNext->pPrev = p->pPrev;
  }
  p->magic = VDBE_MAGIC_DEAD;
  p->db = 0;
  sqlite3DbFreeNN(db, p);
  sqlite3DbNNFreeNN(db, p);
}

/*
** The cursor "p" has a pending seek operation that has not yet been
** carried out.  Seek the cursor now.  If an error occurs, return
** the appropriate error code.
*/
static int SQLITE_NOINLINE handleDeferredMoveto(VdbeCursor *p){
int SQLITE_NOINLINE sqlite3VdbeFinishMoveto(VdbeCursor *p){
  int res, rc;
#ifdef SQLITE_TEST
  extern int sqlite3_search_count;
#endif
  assert( p->deferredMoveto );
  assert( p->isTable );
  assert( p->eCurType==CURTYPE_BTREE );
  rc = sqlite3BtreeMovetoUnpacked(p->uc.pCursor, 0, p->movetoTarget, 0, &res);
  rc = sqlite3BtreeTableMoveto(p->uc.pCursor, p->movetoTarget, 0, &res);
  if( rc ) return rc;
  if( res!=0 ) return SQLITE_CORRUPT_BKPT;
#ifdef SQLITE_TEST
  sqlite3_search_count++;
#endif
  p->deferredMoveto = 0;
  p->cacheStatus = CACHE_STALE;
  return SQLITE_OK;
}

/*
** Something has moved cursor "p" out of place.  Maybe the row it was
** pointed to was deleted out from under it.  Or maybe the btree was
** rebalanced.  Whatever the cause, try to restore "p" to the place it
** is supposed to be pointing.  If the row was deleted out from under the
** cursor, set the cursor to point to a NULL row.
*/
static int SQLITE_NOINLINE handleMovedCursor(VdbeCursor *p){
int SQLITE_NOINLINE sqlite3VdbeHandleMovedCursor(VdbeCursor *p){
  int isDifferentRow, rc;
  assert( p->eCurType==CURTYPE_BTREE );
  assert( p->uc.pCursor!=0 );
  assert( sqlite3BtreeCursorHasMoved(p->uc.pCursor) );
  rc = sqlite3BtreeCursorRestore(p->uc.pCursor, &isDifferentRow);
  p->cacheStatus = CACHE_STALE;
  if( isDifferentRow ) p->nullRow = 1;
  return rc;
}

/*
** Check to ensure that the cursor is valid.  Restore the cursor
** if need be.  Return any I/O error from the restore operation.
*/
int sqlite3VdbeCursorRestore(VdbeCursor *p){
  assert( p->eCurType==CURTYPE_BTREE );
  assert( p->eCurType==CURTYPE_BTREE || IsNullCursor(p) );
  if( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){
    return handleMovedCursor(p);
    return sqlite3VdbeHandleMovedCursor(p);
  }
  return SQLITE_OK;
}

/*
** Make sure the cursor p is ready to read or write the row to which it
** was last positioned.  Return an error code if an OOM fault or I/O error
** prevents us from positioning the cursor to its correct position.
**
** If a MoveTo operation is pending on the given cursor, then do that
** MoveTo now.  If no move is pending, check to see if the row has been
** deleted out from under the cursor and if it has, mark the row as
** a NULL row.
**
** If the cursor is already pointing to the correct row and that row has
** not been deleted out from under the cursor, then this routine is a no-op.
*/
int sqlite3VdbeCursorMoveto(VdbeCursor **pp, int *piCol){
  VdbeCursor *p = *pp;
  assert( p->eCurType==CURTYPE_BTREE || p->eCurType==CURTYPE_PSEUDO );
  if( p->deferredMoveto ){
    int iMap;
    if( p->aAltMap && (iMap = p->aAltMap[1+*piCol])>0 ){
      *pp = p->pAltCursor;
      *piCol = iMap - 1;
      return SQLITE_OK;
    }
    return handleDeferredMoveto(p);
  }
  if( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){
    return handleMovedCursor(p);
  }
  return SQLITE_OK;
}

/*
** The following functions:
**
** sqlite3VdbeSerialType()
** sqlite3VdbeSerialTypeLen()
** sqlite3VdbeSerialLen()
** sqlite3VdbeSerialPut()
** sqlite3VdbeSerialPut()  <--- in-lined into OP_MakeRecord as of 2022-04-02
** sqlite3VdbeSerialGet()
**
** encapsulate the code that serializes values for storage in SQLite
** data and index records. Each serialized value consists of a
** 'serial-type' and a blob of data. The serial type is an 8-byte unsigned
** integer, stored as a varint.
**
3386
3387
3388
3389
3390
3391
3392

3393
3394








3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405

3406
3407
3408
3409


3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428









3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443

3444
3445
3446
3447
3448

3449
3450
3451
3452
3453
3454
3455
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816

3817
3818
3819
3820
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
3866
3867
3868
3869
3870
3871

3872
3873
3874
3875
3876
3877
3878
3879







+


+
+
+
+
+
+
+
+










-
+




+
+



















+
+
+
+
+
+
+
+
+















+




-
+







**    N>=12 and even       (N-12)/2        BLOB
**    N>=13 and odd        (N-13)/2        text
**
** The 8 and 9 types were added in 3.3.0, file format 4.  Prior versions
** of SQLite will not understand those serial types.
*/

#if 0 /* Inlined into the OP_MakeRecord opcode */
/*
** Return the serial-type for the value stored in pMem.
**
** This routine might convert a large MEM_IntReal value into MEM_Real.
**
** 2019-07-11:  The primary user of this subroutine was the OP_MakeRecord
** opcode in the byte-code engine.  But by moving this routine in-line, we
** can omit some redundant tests and make that opcode a lot faster.  So
** this routine is now only used by the STAT3 logic and STAT3 support has
** ended.  The code is kept here for historical reference only.
*/
u32 sqlite3VdbeSerialType(Mem *pMem, int file_format, u32 *pLen){
  int flags = pMem->flags;
  u32 n;

  assert( pLen!=0 );
  if( flags&MEM_Null ){
    *pLen = 0;
    return 0;
  }
  if( flags&MEM_Int ){
  if( flags&(MEM_Int|MEM_IntReal) ){
    /* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */
#   define MAX_6BYTE ((((i64)0x00008000)<<32)-1)
    i64 i = pMem->u.i;
    u64 u;
    testcase( flags & MEM_Int );
    testcase( flags & MEM_IntReal );
    if( i<0 ){
      u = ~i;
    }else{
      u = i;
    }
    if( u<=127 ){
      if( (i&1)==i && file_format>=4 ){
        *pLen = 0;
        return 8+(u32)u;
      }else{
        *pLen = 1;
        return 1;
      }
    }
    if( u<=32767 ){ *pLen = 2; return 2; }
    if( u<=8388607 ){ *pLen = 3; return 3; }
    if( u<=2147483647 ){ *pLen = 4; return 4; }
    if( u<=MAX_6BYTE ){ *pLen = 6; return 5; }
    *pLen = 8;
    if( flags&MEM_IntReal ){
      /* If the value is IntReal and is going to take up 8 bytes to store
      ** as an integer, then we might as well make it an 8-byte floating
      ** point value */
      pMem->u.r = (double)pMem->u.i;
      pMem->flags &= ~MEM_IntReal;
      pMem->flags |= MEM_Real;
      return 7;
    }
    return 6;
  }
  if( flags&MEM_Real ){
    *pLen = 8;
    return 7;
  }
  assert( pMem->db->mallocFailed || flags&(MEM_Str|MEM_Blob) );
  assert( pMem->n>=0 );
  n = (u32)pMem->n;
  if( flags & MEM_Zero ){
    n += pMem->u.nZero;
  }
  *pLen = n;
  return ((n*2) + 12 + ((flags&MEM_Str)!=0));
}
#endif /* inlined into OP_MakeRecord */

/*
** The sizes for serial types less than 128
*/
static const u8 sqlite3SmallTypeSizes[] = {
const u8 sqlite3SmallTypeSizes[128] = {
        /*  0   1   2   3   4   5   6   7   8   9 */   
/*   0 */   0,  1,  2,  3,  4,  6,  8,  8,  0,  0,
/*  10 */   0,  0,  0,  0,  1,  1,  2,  2,  3,  3,
/*  20 */   4,  4,  5,  5,  6,  6,  7,  7,  8,  8,
/*  30 */   9,  9, 10, 10, 11, 11, 12, 12, 13, 13,
/*  40 */  14, 14, 15, 15, 16, 16, 17, 17, 18, 18,
/*  50 */  19, 19, 20, 20, 21, 21, 22, 22, 23, 23,
3510
3511
3512
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
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595

3596
3597
3598
3599
3600
3601
3602

3603
3604
3605
3606
3607
3608
3609
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
3962
3963
3964
3965
3966
3967

3968
3969
3970
3971
3972
3973
3974

3975
3976
3977
3978
3979
3980
3981
3982







-
+












-
-
-
-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-












-
+






-
+







** the necessary byte swapping is carried out using a 64-bit integer
** rather than a 64-bit float.  Frank assures us that the code here
** works for him.  We, the developers, have no way to independently
** verify this, but Frank seems to know what he is talking about
** so we trust him.
*/
#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
static u64 floatSwap(u64 in){
u64 sqlite3FloatSwap(u64 in){
  union {
    u64 r;
    u32 i[2];
  } u;
  u32 t;

  u.r = in;
  t = u.i[0];
  u.i[0] = u.i[1];
  u.i[1] = t;
  return u.r;
}
# define swapMixedEndianFloat(X)  X = floatSwap(X)
#else
# define swapMixedEndianFloat(X)
#endif
#endif /* SQLITE_MIXED_ENDIAN_64BIT_FLOAT */

/*
** Write the serialized data blob for the value stored in pMem into 
** buf. It is assumed that the caller has allocated sufficient space.
** Return the number of bytes written.
**
** nBuf is the amount of space left in buf[].  The caller is responsible
** for allocating enough space to buf[] to hold the entire field, exclusive
** of the pMem->u.nZero bytes for a MEM_Zero value.
**
** Return the number of bytes actually written into buf[].  The number
** of bytes in the zero-filled tail is included in the return value only
** if those bytes were zeroed in buf[].
*/ 
u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){
  u32 len;

  /* Integer and Real */
  if( serial_type<=7 && serial_type>0 ){
    u64 v;
    u32 i;
    if( serial_type==7 ){
      assert( sizeof(v)==sizeof(pMem->u.r) );
      memcpy(&v, &pMem->u.r, sizeof(v));
      swapMixedEndianFloat(v);
    }else{
      v = pMem->u.i;
    }
    len = i = sqlite3SmallTypeSizes[serial_type];
    assert( i>0 );
    do{
      buf[--i] = (u8)(v&0xFF);
      v >>= 8;
    }while( i );
    return len;
  }

  /* String or blob */
  if( serial_type>=12 ){
    assert( pMem->n + ((pMem->flags & MEM_Zero)?pMem->u.nZero:0)
             == (int)sqlite3VdbeSerialTypeLen(serial_type) );
    len = pMem->n;
    if( len>0 ) memcpy(buf, pMem->z, len);
    return len;
  }

  /* NULL or constants 0 or 1 */
  return 0;
}

/* Input "x" is a sequence of unsigned characters that represent a
** big-endian integer.  Return the equivalent native integer
*/
#define ONE_BYTE_INT(x)    ((i8)(x)[0])
#define TWO_BYTE_INT(x)    (256*(i8)((x)[0])|(x)[1])
#define THREE_BYTE_INT(x)  (65536*(i8)((x)[0])|((x)[1]<<8)|(x)[2])
#define FOUR_BYTE_UINT(x)  (((u32)(x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
#define FOUR_BYTE_INT(x) (16777216*(i8)((x)[0])|((x)[1]<<16)|((x)[2]<<8)|(x)[3])

/*
** Deserialize the data blob pointed to by buf as serial type serial_type
** and store the result in pMem.  Return the number of bytes read.
** and store the result in pMem.
**
** This function is implemented as two separate routines for performance.
** The few cases that require local variables are broken out into a separate
** routine so that in most cases the overhead of moving the stack pointer
** is avoided.
*/ 
static u32 SQLITE_NOINLINE serialGet(
static void serialGet(
  const unsigned char *buf,     /* Buffer to deserialize from */
  u32 serial_type,              /* Serial type to deserialize */
  Mem *pMem                     /* Memory cell to write value into */
){
  u64 x = FOUR_BYTE_UINT(buf);
  u32 y = FOUR_BYTE_UINT(buf+4);
  x = (x<<32) + y;
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
3659
3660
3661
3662
3663

3664
3665
3666
3667
3668
3669
3670
3671

3672
3673
3674
3675
3676
3677
3678
3679

3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691

3692
3693
3694
3695
3696
3697
3698
3699

3700
3701
3702
3703
3704
3705


3706
3707
3708
3709
3710
3711
3712
3713

3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724

3725
3726
3727

3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748

3749
3750
3751
3752


3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770

3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781

3782
3783
3784
3785
3786
3787
3788
3789
3790


3791
3792
3793







3794
3795
3796
3797
3798
3799
3800
4000
4001
4002
4003
4004
4005
4006

4007
4008

4009

4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020

4021
4022
4023
4024
4025
4026

4027
4028
4029
4030
4031
4032
4033
4034

4035
4036
4037
4038
4039
4040
4041
4042

4043
4044
4045
4046
4047
4048
4049
4050

4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062

4063
4064
4065
4066
4067
4068
4069
4070

4071
4072
4073
4074
4075
4076

4077
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
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120

4121
4122
4123


4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142

4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153

4154
4155
4156
4157
4158
4159
4160
4161
4162

4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181







-
+

-

-
+










-
+





-
+







-
+







-
+







-
+











-
+







-
+





-
+
+







-
+










-
+


-
+




















-
+


-
-
+
+

















-
+










-
+








-
+
+



+
+
+
+
+
+
+







    u64 t2 = t1;
    swapMixedEndianFloat(t2);
    assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 );
#endif
    assert( sizeof(x)==8 && sizeof(pMem->u.r)==8 );
    swapMixedEndianFloat(x);
    memcpy(&pMem->u.r, &x, sizeof(x));
    pMem->flags = sqlite3IsNaN(pMem->u.r) ? MEM_Null : MEM_Real;
    pMem->flags = IsNaN(x) ? MEM_Null : MEM_Real;
  }
  return 8;
}
u32 sqlite3VdbeSerialGet(
void sqlite3VdbeSerialGet(
  const unsigned char *buf,     /* Buffer to deserialize from */
  u32 serial_type,              /* Serial type to deserialize */
  Mem *pMem                     /* Memory cell to write value into */
){
  switch( serial_type ){
    case 10: { /* Internal use only: NULL with virtual table
               ** UPDATE no-change flag set */
      pMem->flags = MEM_Null|MEM_Zero;
      pMem->n = 0;
      pMem->u.nZero = 0;
      break;
      return;
    }
    case 11:   /* Reserved for future use */
    case 0: {  /* Null */
      /* EVIDENCE-OF: R-24078-09375 Value is a NULL. */
      pMem->flags = MEM_Null;
      break;
      return;
    }
    case 1: {
      /* EVIDENCE-OF: R-44885-25196 Value is an 8-bit twos-complement
      ** integer. */
      pMem->u.i = ONE_BYTE_INT(buf);
      pMem->flags = MEM_Int;
      testcase( pMem->u.i<0 );
      return 1;
      return;
    }
    case 2: { /* 2-byte signed integer */
      /* EVIDENCE-OF: R-49794-35026 Value is a big-endian 16-bit
      ** twos-complement integer. */
      pMem->u.i = TWO_BYTE_INT(buf);
      pMem->flags = MEM_Int;
      testcase( pMem->u.i<0 );
      return 2;
      return;
    }
    case 3: { /* 3-byte signed integer */
      /* EVIDENCE-OF: R-37839-54301 Value is a big-endian 24-bit
      ** twos-complement integer. */
      pMem->u.i = THREE_BYTE_INT(buf);
      pMem->flags = MEM_Int;
      testcase( pMem->u.i<0 );
      return 3;
      return;
    }
    case 4: { /* 4-byte signed integer */
      /* EVIDENCE-OF: R-01849-26079 Value is a big-endian 32-bit
      ** twos-complement integer. */
      pMem->u.i = FOUR_BYTE_INT(buf);
#ifdef __HP_cc 
      /* Work around a sign-extension bug in the HP compiler for HP/UX */
      if( buf[0]&0x80 ) pMem->u.i |= 0xffffffff80000000LL;
#endif
      pMem->flags = MEM_Int;
      testcase( pMem->u.i<0 );
      return 4;
      return;
    }
    case 5: { /* 6-byte signed integer */
      /* EVIDENCE-OF: R-50385-09674 Value is a big-endian 48-bit
      ** twos-complement integer. */
      pMem->u.i = FOUR_BYTE_UINT(buf+2) + (((i64)1)<<32)*TWO_BYTE_INT(buf);
      pMem->flags = MEM_Int;
      testcase( pMem->u.i<0 );
      return 6;
      return;
    }
    case 6:   /* 8-byte signed integer */
    case 7: { /* IEEE floating point */
      /* These use local variables, so do them in a separate routine
      ** to avoid having to move the frame pointer in the common case */
      return serialGet(buf,serial_type,pMem);
      serialGet(buf,serial_type,pMem);
      return;
    }
    case 8:    /* Integer 0 */
    case 9: {  /* Integer 1 */
      /* EVIDENCE-OF: R-12976-22893 Value is the integer 0. */
      /* EVIDENCE-OF: R-18143-12121 Value is the integer 1. */
      pMem->u.i = serial_type-8;
      pMem->flags = MEM_Int;
      return 0;
      return;
    }
    default: {
      /* EVIDENCE-OF: R-14606-31564 Value is a BLOB that is (N-12)/2 bytes in
      ** length.
      ** EVIDENCE-OF: R-28401-00140 Value is a string in the text encoding and
      ** (N-13)/2 bytes in length. */
      static const u16 aFlag[] = { MEM_Blob|MEM_Ephem, MEM_Str|MEM_Ephem };
      pMem->z = (char *)buf;
      pMem->n = (serial_type-12)/2;
      pMem->flags = aFlag[serial_type&1];
      return pMem->n;
      return;
    }
  }
  return 0;
  return;
}
/*
** This routine is used to allocate sufficient space for an UnpackedRecord
** structure large enough to be used with sqlite3VdbeRecordUnpack() if
** the first argument is a pointer to KeyInfo structure pKeyInfo.
**
** The space is either allocated using sqlite3DbMallocRaw() or from within
** the unaligned buffer passed via the second and third arguments (presumably
** stack space). If the former, then *ppFree is set to a pointer that should
** be eventually freed by the caller using sqlite3DbFree(). Or, if the 
** allocation comes from the pSpace/szSpace buffer, *ppFree is set to NULL
** before returning.
**
** If an OOM error occurs, NULL is returned.
*/
UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(
  KeyInfo *pKeyInfo               /* Description of the record */
){
  UnpackedRecord *p;              /* Unpacked record to return */
  int nByte;                      /* Number of bytes required for *p */
  nByte = ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nKeyField+1);
  nByte = ROUND8P(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nKeyField+1);
  p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte);
  if( !p ) return 0;
  p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))];
  assert( pKeyInfo->aSortOrder!=0 );
  p->aMem = (Mem*)&((char*)p)[ROUND8P(sizeof(UnpackedRecord))];
  assert( pKeyInfo->aSortFlags!=0 );
  p->pKeyInfo = pKeyInfo;
  p->nField = pKeyInfo->nKeyField + 1;
  return p;
}

/*
** Given the nKey-byte encoding of a record in pKey[], populate the 
** UnpackedRecord structure indicated by the fourth argument with the
** contents of the decoded record.
*/ 
void sqlite3VdbeRecordUnpack(
  KeyInfo *pKeyInfo,     /* Information about the record format */
  int nKey,              /* Size of the binary record */
  const void *pKey,      /* The binary record */
  UnpackedRecord *p      /* Populate this structure before returning. */
){
  const unsigned char *aKey = (const unsigned char *)pKey;
  int d; 
  u32 d; 
  u32 idx;                        /* Offset in aKey[] to read from */
  u16 u;                          /* Unsigned loop counter */
  u32 szHdr;
  Mem *pMem = p->aMem;

  p->default_rc = 0;
  assert( EIGHT_BYTE_ALIGNMENT(pMem) );
  idx = getVarint32(aKey, szHdr);
  d = szHdr;
  u = 0;
  while( idx<szHdr && d<=nKey ){
  while( idx<szHdr && d<=(u32)nKey ){
    u32 serial_type;

    idx += getVarint32(&aKey[idx], serial_type);
    pMem->enc = pKeyInfo->enc;
    pMem->db = pKeyInfo->db;
    /* pMem->flags = 0; // sqlite3VdbeSerialGet() will set this for us */
    pMem->szMalloc = 0;
    pMem->z = 0;
    d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem);
    sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem);
    d += sqlite3VdbeSerialTypeLen(serial_type);
    pMem++;
    if( (++u)>=p->nField ) break;
  }
  if( d>(u32)nKey && u ){
    assert( CORRUPT_DB );
    /* In a corrupt record entry, the last pMem might have been set up using 
    ** uninitialized memory. Overwrite its value with NULL, to prevent
    ** warnings from MSAN. */
    sqlite3VdbeMemSetNull(pMem-1);
  }
  assert( u<=pKeyInfo->nKeyField + 1 );
  p->nField = u;
}

#ifdef SQLITE_DEBUG
/*
** This function compares two index or table record keys in the same way
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
3866
3867


3868
3869
3870
3871


3872
3873





3874

3875
3876
3877
3878
3879
3880
3881
4218
4219
4220
4221
4222
4223
4224

4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239


4240
4241
4242
4243
4244
4245
4246
4247

4248
4249
4250
4251
4252

4253
4254
4255
4256
4257
4258
4259
4260
4261

4262
4263
4264
4265
4266
4267
4268
4269







-
+














-
-
+
+






-
+
+



-
+
+


+
+
+
+
+
-
+







  */
  /*  mem1.u.i = 0;  // not needed, here to silence compiler warning */
  
  idx1 = getVarint32(aKey1, szHdr1);
  if( szHdr1>98307 ) return SQLITE_CORRUPT;
  d1 = szHdr1;
  assert( pKeyInfo->nAllField>=pPKey2->nField || CORRUPT_DB );
  assert( pKeyInfo->aSortOrder!=0 );
  assert( pKeyInfo->aSortFlags!=0 );
  assert( pKeyInfo->nKeyField>0 );
  assert( idx1<=szHdr1 || CORRUPT_DB );
  do{
    u32 serial_type1;

    /* Read the serial types for the next element in each key. */
    idx1 += getVarint32( aKey1+idx1, serial_type1 );

    /* Verify that there is enough key space remaining to avoid
    ** a buffer overread.  The "d1+serial_type1+2" subexpression will
    ** always be greater than or equal to the amount of required key space.
    ** Use that approximation to avoid the more expensive call to
    ** sqlite3VdbeSerialTypeLen() in the common case.
    */
    if( d1+serial_type1+2>(u32)nKey1
     && d1+sqlite3VdbeSerialTypeLen(serial_type1)>(u32)nKey1 
    if( d1+(u64)serial_type1+2>(u64)nKey1
     && d1+(u64)sqlite3VdbeSerialTypeLen(serial_type1)>(u64)nKey1 
    ){
      break;
    }

    /* Extract the values to be compared.
    */
    d1 += sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1);
    sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1);
    d1 += sqlite3VdbeSerialTypeLen(serial_type1);

    /* Do the comparison
    */
    rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i], pKeyInfo->aColl[i]);
    rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i],
                           pKeyInfo->nAllField>i ? pKeyInfo->aColl[i] : 0);
    if( rc!=0 ){
      assert( mem1.szMalloc==0 );  /* See comment below */
      if( (pKeyInfo->aSortFlags[i] & KEYINFO_ORDER_BIGNULL)
       && ((mem1.flags & MEM_Null) || (pPKey2->aMem[i].flags & MEM_Null)) 
      ){
        rc = -rc;
      }
      if( pKeyInfo->aSortOrder[i] ){
      if( pKeyInfo->aSortFlags[i] & KEYINFO_ORDER_DESC ){
        rc = -rc;  /* Invert the result for DESC sort order. */
      }
      goto debugCompareEnd;
    }
    i++;
  }while( idx1<szHdr1 && i<pPKey2->nField );

3965
3966
3967
3968
3969
3970
3971
3972
3973


3974
3975
3976
3977
3978
3979
3980
4353
4354
4355
4356
4357
4358
4359


4360
4361
4362
4363
4364
4365
4366
4367
4368







-
-
+
+







    v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc);
    if( (v1==0 || v2==0) ){
      if( prcErr ) *prcErr = SQLITE_NOMEM_BKPT;
      rc = 0;
    }else{
      rc = pColl->xCmp(pColl->pUser, c1.n, v1, c2.n, v2);
    }
    sqlite3VdbeMemRelease(&c1);
    sqlite3VdbeMemRelease(&c2);
    sqlite3VdbeMemReleaseMalloc(&c1);
    sqlite3VdbeMemReleaseMalloc(&c2);
    return rc;
  }
}

/*
** The input pBlob is guaranteed to be a Blob that is not marked
** with MEM_Zero.  Return true if it could be a zero-blob.
4021
4022
4023
4024
4025
4026
4027
4028

4029
4030



4031
4032
4033


4034
4035
4036
4037
4038
4039
4040
4409
4410
4411
4412
4413
4414
4415

4416
4417
4418
4419
4420
4421
4422


4423
4424
4425
4426
4427
4428
4429
4430
4431







-
+


+
+
+

-
-
+
+







}

/*
** Do a comparison between a 64-bit signed integer and a 64-bit floating-point
** number.  Return negative, zero, or positive if the first (i64) is less than,
** equal to, or greater than the second (double).
*/
static int sqlite3IntFloatCompare(i64 i, double r){
int sqlite3IntFloatCompare(i64 i, double r){
  if( sizeof(LONGDOUBLE_TYPE)>8 ){
    LONGDOUBLE_TYPE x = (LONGDOUBLE_TYPE)i;
    testcase( x<r );
    testcase( x>r );
    testcase( x==r );
    if( x<r ) return -1;
    if( x>r ) return +1;
    return 0;
    if( x>r ) return +1;  /*NO_TEST*/ /* work around bugs in gcov */
    return 0;             /*NO_TEST*/ /* work around bugs in gcov */
  }else{
    i64 y;
    double s;
    if( r<-9223372036854775808.0 ) return +1;
    if( r>=9223372036854775808.0 ) return -1;
    y = (i64)r;
    if( i<y ) return -1;
4069
4070
4071
4072
4073
4074
4075
4076
4077







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
4460
4461
4462
4463
4464
4465
4466


4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483

4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497

4498
4499
4500
4501
4502
4503
4504
4505
4506







-
-
+
+
+
+
+
+
+









+
-
+
+


+
+
+
+





+
-
+
+







  */
  if( combined_flags&MEM_Null ){
    return (f2&MEM_Null) - (f1&MEM_Null);
  }

  /* At least one of the two values is a number
  */
  if( combined_flags&(MEM_Int|MEM_Real) ){
    if( (f1 & f2 & MEM_Int)!=0 ){
  if( combined_flags&(MEM_Int|MEM_Real|MEM_IntReal) ){
    testcase( combined_flags & MEM_Int );
    testcase( combined_flags & MEM_Real );
    testcase( combined_flags & MEM_IntReal );
    if( (f1 & f2 & (MEM_Int|MEM_IntReal))!=0 ){
      testcase( f1 & f2 & MEM_Int );
      testcase( f1 & f2 & MEM_IntReal );
      if( pMem1->u.i < pMem2->u.i ) return -1;
      if( pMem1->u.i > pMem2->u.i ) return +1;
      return 0;
    }
    if( (f1 & f2 & MEM_Real)!=0 ){
      if( pMem1->u.r < pMem2->u.r ) return -1;
      if( pMem1->u.r > pMem2->u.r ) return +1;
      return 0;
    }
    if( (f1&(MEM_Int|MEM_IntReal))!=0 ){
    if( (f1&MEM_Int)!=0 ){
      testcase( f1 & MEM_Int );
      testcase( f1 & MEM_IntReal );
      if( (f2&MEM_Real)!=0 ){
        return sqlite3IntFloatCompare(pMem1->u.i, pMem2->u.r);
      }else if( (f2&(MEM_Int|MEM_IntReal))!=0 ){
        if( pMem1->u.i < pMem2->u.i ) return -1;
        if( pMem1->u.i > pMem2->u.i ) return +1;
        return 0;
      }else{
        return -1;
      }
    }
    if( (f1&MEM_Real)!=0 ){
      if( (f2&(MEM_Int|MEM_IntReal))!=0 ){
      if( (f2&MEM_Int)!=0 ){
        testcase( f2 & MEM_Int );
        testcase( f2 & MEM_IntReal );
        return -sqlite3IntFloatCompare(pMem2->u.i, pMem1->u.r);
      }else{
        return -1;
      }
    }
    return +1;
  }
4211
4212
4213
4214
4215
4216
4217
4218
4219






4220
4221
4222
4223
4224

4225




4226


4227
4228
4229
4230




4231
4232
4233
4234
4235
4236
4237

4238
4239
4240

4241
4242
4243

4244


4245
4246
4247
4248

4249
4250
4251
4252
4253
4254
4255
4615
4616
4617
4618
4619
4620
4621


4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633

4634
4635
4636
4637
4638
4639
4640




4641
4642
4643
4644


4645
4646
4647
4648

4649
4650
4651

4652
4653
4654
4655
4656

4657
4658
4659
4660
4661

4662
4663
4664
4665
4666
4667
4668
4669







-
-
+
+
+
+
+
+





+
-
+
+
+
+

+
+
-
-
-
-
+
+
+
+
-
-




-
+


-
+



+
-
+
+



-
+







  const unsigned char *aKey1 = (const unsigned char *)pKey1;
  Mem mem1;

  /* If bSkip is true, then the caller has already determined that the first
  ** two elements in the keys are equal. Fix the various stack variables so
  ** that this routine begins comparing at the second field. */
  if( bSkip ){
    u32 s1;
    idx1 = 1 + getVarint32(&aKey1[1], s1);
    u32 s1 = aKey1[1];
    if( s1<0x80 ){
      idx1 = 2;
    }else{
      idx1 = 1 + sqlite3GetVarint32(&aKey1[1], &s1);
    }
    szHdr1 = aKey1[0];
    d1 = szHdr1 + sqlite3VdbeSerialTypeLen(s1);
    i = 1;
    pRhs++;
  }else{
    if( (szHdr1 = aKey1[0])<0x80 ){
    idx1 = getVarint32(aKey1, szHdr1);
      idx1 = 1;
    }else{
      idx1 = sqlite3GetVarint32(aKey1, &szHdr1);
    }
    d1 = szHdr1;
    i = 0;
  }
    if( d1>(unsigned)nKey1 ){ 
      pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
      return 0;  /* Corruption */
    }
  if( d1>(unsigned)nKey1 ){ 
    pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
    return 0;  /* Corruption */
  }
    i = 0;
  }

  VVA_ONLY( mem1.szMalloc = 0; ) /* Only needed by assert() statements */
  assert( pPKey2->pKeyInfo->nAllField>=pPKey2->nField 
       || CORRUPT_DB );
  assert( pPKey2->pKeyInfo->aSortOrder!=0 );
  assert( pPKey2->pKeyInfo->aSortFlags!=0 );
  assert( pPKey2->pKeyInfo->nKeyField>0 );
  assert( idx1<=szHdr1 || CORRUPT_DB );
  do{
  while( 1 /*exit-by-break*/ ){
    u32 serial_type;

    /* RHS is an integer */
    if( pRhs->flags & (MEM_Int|MEM_IntReal) ){
    if( pRhs->flags & MEM_Int ){
      testcase( pRhs->flags & MEM_Int );
      testcase( pRhs->flags & MEM_IntReal );
      serial_type = aKey1[idx1];
      testcase( serial_type==12 );
      if( serial_type>=10 ){
        rc = +1;
        rc = serial_type==10 ? -1 : +1;
      }else if( serial_type==0 ){
        rc = -1;
      }else if( serial_type==7 ){
        sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
        rc = -sqlite3IntFloatCompare(pRhs->u.i, mem1.u.r);
      }else{
        i64 lhs = vdbeRecordDecodeInt(serial_type, &aKey1[d1]);
4266
4267
4268
4269
4270
4271
4272
4273

4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292

4293
4294
4295
4296
4297
4298
4299
4300
4301
4302



4303
4304
4305

4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324

4325
4326
4327
4328
4329
4330
4331
4680
4681
4682
4683
4684
4685
4686

4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705

4706
4707
4708
4709
4710
4711
4712
4713
4714
4715

4716
4717
4718
4719
4720

4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739

4740
4741
4742
4743
4744
4745
4746
4747







-
+


















-
+









-
+
+
+


-
+


















-
+







    else if( pRhs->flags & MEM_Real ){
      serial_type = aKey1[idx1];
      if( serial_type>=10 ){
        /* Serial types 12 or greater are strings and blobs (greater than
        ** numbers). Types 10 and 11 are currently "reserved for future 
        ** use", so it doesn't really matter what the results of comparing
        ** them to numberic values are.  */
        rc = +1;
        rc = serial_type==10 ? -1 : +1;
      }else if( serial_type==0 ){
        rc = -1;
      }else{
        sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
        if( serial_type==7 ){
          if( mem1.u.r<pRhs->u.r ){
            rc = -1;
          }else if( mem1.u.r>pRhs->u.r ){
            rc = +1;
          }
        }else{
          rc = sqlite3IntFloatCompare(mem1.u.i, pRhs->u.r);
        }
      }
    }

    /* RHS is a string */
    else if( pRhs->flags & MEM_Str ){
      getVarint32(&aKey1[idx1], serial_type);
      getVarint32NR(&aKey1[idx1], serial_type);
      testcase( serial_type==12 );
      if( serial_type<12 ){
        rc = -1;
      }else if( !(serial_type & 0x01) ){
        rc = +1;
      }else{
        mem1.n = (serial_type - 12) / 2;
        testcase( (d1+mem1.n)==(unsigned)nKey1 );
        testcase( (d1+mem1.n+1)==(unsigned)nKey1 );
        if( (d1+mem1.n) > (unsigned)nKey1 ){
        if( (d1+mem1.n) > (unsigned)nKey1
         || (pKeyInfo = pPKey2->pKeyInfo)->nAllField<=i
        ){
          pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
          return 0;                /* Corruption */
        }else if( (pKeyInfo = pPKey2->pKeyInfo)->aColl[i] ){
        }else if( pKeyInfo->aColl[i] ){
          mem1.enc = pKeyInfo->enc;
          mem1.db = pKeyInfo->db;
          mem1.flags = MEM_Str;
          mem1.z = (char*)&aKey1[d1];
          rc = vdbeCompareMemString(
              &mem1, pRhs, pKeyInfo->aColl[i], &pPKey2->errCode
          );
        }else{
          int nCmp = MIN(mem1.n, pRhs->n);
          rc = memcmp(&aKey1[d1], pRhs->z, nCmp);
          if( rc==0 ) rc = mem1.n - pRhs->n; 
        }
      }
    }

    /* RHS is a blob */
    else if( pRhs->flags & MEM_Blob ){
      assert( (pRhs->flags & MEM_Zero)==0 || pRhs->n==0 );
      getVarint32(&aKey1[idx1], serial_type);
      getVarint32NR(&aKey1[idx1], serial_type);
      testcase( serial_type==12 );
      if( serial_type<12 || (serial_type & 0x01) ){
        rc = -1;
      }else{
        int nStr = (serial_type - 12) / 2;
        testcase( (d1+nStr)==(unsigned)nKey1 );
        testcase( (d1+nStr+1)==(unsigned)nKey1 );
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
4371
4372
4373
4374
4375
4376
4761
4762
4763
4764
4765
4766
4767

4768
4769
4770
4771


4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791

4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803







-
+



-
-
+
+
+
+
+
+
+
+










+

-
+
+
+
+
+







        }
      }
    }

    /* RHS is null */
    else{
      serial_type = aKey1[idx1];
      rc = (serial_type!=0);
      rc = (serial_type!=0 && serial_type!=10);
    }

    if( rc!=0 ){
      if( pPKey2->pKeyInfo->aSortOrder[i] ){
        rc = -rc;
      int sortFlags = pPKey2->pKeyInfo->aSortFlags[i];
      if( sortFlags ){
        if( (sortFlags & KEYINFO_ORDER_BIGNULL)==0
         || ((sortFlags & KEYINFO_ORDER_DESC)
           !=(serial_type==0 || (pRhs->flags&MEM_Null)))
        ){
          rc = -rc;
        }
      }
      assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, rc) );
      assert( mem1.szMalloc==0 );  /* See comment below */
      return rc;
    }

    i++;
    if( i==pPKey2->nField ) break;
    pRhs++;
    d1 += sqlite3VdbeSerialTypeLen(serial_type);
    if( d1>(unsigned)nKey1 ) break;
    idx1 += sqlite3VarintLen(serial_type);
  }while( idx1<(unsigned)szHdr1 && d1<=(unsigned)nKey1 );
    if( idx1>=(unsigned)szHdr1 ){
      pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
      return 0;  /* Corrupt index */
    }
  }

  /* No memory allocation is ever used on mem1.  Prove this using
  ** the following assert().  If the assert() fails, it indicates a
  ** memory leak and a need to call sqlite3VdbeMemRelease(&mem1).  */
  assert( mem1.szMalloc==0 );

  /* rc==0 here means that one or both of the keys ran out of fields and
4464
4465
4466
4467
4468
4469
4470

4471

4472
4473
4474
4475
4476
4477
4478
4891
4892
4893
4894
4895
4896
4897
4898

4899
4900
4901
4902
4903
4904
4905
4906







+
-
+







    case 0: case 7:
      return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2);

    default:
      return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2);
  }

  assert( pPKey2->u.i == pPKey2->aMem[0].u.i );
  v = pPKey2->aMem[0].u.i;
  v = pPKey2->u.i;
  if( v>lhs ){
    res = pPKey2->r1;
  }else if( v<lhs ){
    res = pPKey2->r2;
  }else if( pPKey2->nField>1 ){
    /* The first fields of the two keys are equal. Compare the trailing 
    ** fields.  */
4499
4500
4501
4502
4503
4504
4505


4506

4507


4508





4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523


4524
4525
4526






4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937

4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958


4959
4960
4961


4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979




4980
4981
4982
4983
4984
4985
4986







+
+

+
-
+
+

+
+
+
+
+













-
-
+
+

-
-
+
+
+
+
+
+












-
-
-
-







  UnpackedRecord *pPKey2        /* Right key */
){
  const u8 *aKey1 = (const u8*)pKey1;
  int serial_type;
  int res;

  assert( pPKey2->aMem[0].flags & MEM_Str );
  assert( pPKey2->aMem[0].n == pPKey2->n );
  assert( pPKey2->aMem[0].z == pPKey2->u.z );
  vdbeAssertFieldCountWithinLimits(nKey1, pKey1, pPKey2->pKeyInfo);
  serial_type = (signed char)(aKey1[1]);
  getVarint32(&aKey1[1], serial_type);

vrcs_restart:
  if( serial_type<12 ){
    if( serial_type<0 ){
      sqlite3GetVarint32(&aKey1[1], (u32*)&serial_type);
      if( serial_type>=12 ) goto vrcs_restart;
      assert( CORRUPT_DB );
    }
    res = pPKey2->r1;      /* (pKey1/nKey1) is a number or a null */
  }else if( !(serial_type & 0x01) ){ 
    res = pPKey2->r2;      /* (pKey1/nKey1) is a blob */
  }else{
    int nCmp;
    int nStr;
    int szHdr = aKey1[0];

    nStr = (serial_type-12) / 2;
    if( (szHdr + nStr) > nKey1 ){
      pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
      return 0;    /* Corruption */
    }
    nCmp = MIN( pPKey2->aMem[0].n, nStr );
    res = memcmp(&aKey1[szHdr], pPKey2->aMem[0].z, nCmp);
    nCmp = MIN( pPKey2->n, nStr );
    res = memcmp(&aKey1[szHdr], pPKey2->u.z, nCmp);

    if( res==0 ){
      res = nStr - pPKey2->aMem[0].n;
    if( res>0 ){
      res = pPKey2->r2;
    }else if( res<0 ){
      res = pPKey2->r1;
    }else{
      res = nStr - pPKey2->n;
      if( res==0 ){
        if( pPKey2->nField>1 ){
          res = sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1);
        }else{
          res = pPKey2->default_rc;
          pPKey2->eqSeen = 1;
        }
      }else if( res>0 ){
        res = pPKey2->r2;
      }else{
        res = pPKey2->r1;
      }
    }else if( res>0 ){
      res = pPKey2->r2;
    }else{
      res = pPKey2->r1;
    }
  }

  assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, res)
       || CORRUPT_DB
       || pPKey2->pKeyInfo->db->mallocFailed
  );
4567
4568
4569
4570
4571
4572
4573
4574




4575
4576
4577
4578
4579
4580
4581

4582
4583
4584
4585
4586

4587


4588


4589
4590
4591
4592
4593
4594
4595
5004
5005
5006
5007
5008
5009
5010

5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028

5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040







-
+
+
+
+







+





+
-
+
+

+
+







  ** is an integer.
  **
  ** The easiest way to enforce this limit is to consider only records with
  ** 13 fields or less. If the first field is an integer, the maximum legal
  ** header size is (12*5 + 1 + 1) bytes.  */
  if( p->pKeyInfo->nAllField<=13 ){
    int flags = p->aMem[0].flags;
    if( p->pKeyInfo->aSortOrder[0] ){
    if( p->pKeyInfo->aSortFlags[0] ){
      if( p->pKeyInfo->aSortFlags[0] & KEYINFO_ORDER_BIGNULL ){
        return sqlite3VdbeRecordCompare;
      }
      p->r1 = 1;
      p->r2 = -1;
    }else{
      p->r1 = -1;
      p->r2 = 1;
    }
    if( (flags & MEM_Int) ){
      p->u.i = p->aMem[0].u.i;
      return vdbeRecordCompareInt;
    }
    testcase( flags & MEM_Real );
    testcase( flags & MEM_Null );
    testcase( flags & MEM_Blob );
    if( (flags & (MEM_Real|MEM_IntReal|MEM_Null|MEM_Blob))==0
    if( (flags & (MEM_Real|MEM_Null|MEM_Blob))==0 && p->pKeyInfo->aColl[0]==0 ){
     && p->pKeyInfo->aColl[0]==0
    ){
      assert( flags & MEM_Str );
      p->u.z = p->aMem[0].z;
      p->n = p->aMem[0].n;
      return vdbeRecordCompareString;
    }
  }

  return sqlite3VdbeRecordCompare;
}

4616
4617
4618
4619
4620
4621
4622
4623

4624
4625
4626
4627
4628
4629

4630
4631

4632
4633
4634
4635
4636
4637
4638
4639
4640

4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661

4662
4663
4664
4665
4666
4667
4668

4669
4670
4671
4672
4673
4674
4675
5061
5062
5063
5064
5065
5066
5067

5068
5069
5070
5071
5072
5073

5074
5075

5076
5077
5078
5079
5080
5081
5082
5083
5084

5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105

5106
5107
5108
5109
5110
5111
5112

5113
5114
5115
5116
5117
5118
5119
5120







-
+





-
+

-
+








-
+




















-
+






-
+







  */
  assert( sqlite3BtreeCursorIsValid(pCur) );
  nCellKey = sqlite3BtreePayloadSize(pCur);
  assert( (nCellKey & SQLITE_MAX_U32)==(u64)nCellKey );

  /* Read in the complete content of the index entry */
  sqlite3VdbeMemInit(&m, db, 0);
  rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, &m);
  rc = sqlite3VdbeMemFromBtreeZeroOffset(pCur, (u32)nCellKey, &m);
  if( rc ){
    return rc;
  }

  /* The index entry must begin with a header size */
  (void)getVarint32((u8*)m.z, szHdr);
  getVarint32NR((u8*)m.z, szHdr);
  testcase( szHdr==3 );
  testcase( szHdr==m.n );
  testcase( szHdr==(u32)m.n );
  testcase( szHdr>0x7fffffff );
  assert( m.n>=0 );
  if( unlikely(szHdr<3 || szHdr>(unsigned)m.n) ){
    goto idx_rowid_corruption;
  }

  /* The last field of the index should be an integer - the ROWID.
  ** Verify that the last entry really is an integer. */
  (void)getVarint32((u8*)&m.z[szHdr-1], typeRowid);
  getVarint32NR((u8*)&m.z[szHdr-1], typeRowid);
  testcase( typeRowid==1 );
  testcase( typeRowid==2 );
  testcase( typeRowid==3 );
  testcase( typeRowid==4 );
  testcase( typeRowid==5 );
  testcase( typeRowid==6 );
  testcase( typeRowid==8 );
  testcase( typeRowid==9 );
  if( unlikely(typeRowid<1 || typeRowid>9 || typeRowid==7) ){
    goto idx_rowid_corruption;
  }
  lenRowid = sqlite3SmallTypeSizes[typeRowid];
  testcase( (u32)m.n==szHdr+lenRowid );
  if( unlikely((u32)m.n<szHdr+lenRowid) ){
    goto idx_rowid_corruption;
  }

  /* Fetch the integer off the end of the index record */
  sqlite3VdbeSerialGet((u8*)&m.z[m.n-lenRowid], typeRowid, &v);
  *rowid = v.u.i;
  sqlite3VdbeMemRelease(&m);
  sqlite3VdbeMemReleaseMalloc(&m);
  return SQLITE_OK;

  /* Jump here if database corruption is detected after m has been
  ** allocated.  Free the m object and return SQLITE_CORRUPT. */
idx_rowid_corruption:
  testcase( m.szMalloc!=0 );
  sqlite3VdbeMemRelease(&m);
  sqlite3VdbeMemReleaseMalloc(&m);
  return SQLITE_CORRUPT_BKPT;
}

/*
** Compare the key of the index entry that cursor pC is pointing to against
** the key string in pUnpacked.  Write into *pRes a number
** that is negative, zero, or positive if pC is less than, equal to,
4698
4699
4700
4701
4702
4703
4704
4705

4706
4707
4708
4709
4710

4711
4712
4713
4714
4715
4716
4717
4718

4719
4720
4721
4722
4723
4724
4725
5143
5144
5145
5146
5147
5148
5149

5150
5151
5152
5153
5154

5155
5156
5157
5158
5159
5160
5161
5162

5163
5164
5165
5166
5167
5168
5169
5170







-
+




-
+







-
+







  /* nCellKey will always be between 0 and 0xffffffff because of the way
  ** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */
  if( nCellKey<=0 || nCellKey>0x7fffffff ){
    *res = 0;
    return SQLITE_CORRUPT_BKPT;
  }
  sqlite3VdbeMemInit(&m, db, 0);
  rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, &m);
  rc = sqlite3VdbeMemFromBtreeZeroOffset(pCur, (u32)nCellKey, &m);
  if( rc ){
    return rc;
  }
  *res = sqlite3VdbeRecordCompareWithSkip(m.n, m.z, pUnpacked, 0);
  sqlite3VdbeMemRelease(&m);
  sqlite3VdbeMemReleaseMalloc(&m);
  return SQLITE_OK;
}

/*
** This routine sets the value to be returned by subsequent calls to
** sqlite3_changes() on the database handle 'db'. 
*/
void sqlite3VdbeSetChanges(sqlite3 *db, int nChange){
void sqlite3VdbeSetChanges(sqlite3 *db, i64 nChange){
  assert( sqlite3_mutex_held(db->mutex) );
  db->nChange = nChange;
  db->nTotalChange += nChange;
}

/*
** Set a flag in the vdbe to update the change counter when it is finalised
4745
4746
4747
4748
4749
4750
4751
4752

4753
4754
4755
4756
4757
4758
4759
5190
5191
5192
5193
5194
5195
5196

5197
5198
5199
5200
5201
5202
5203
5204







-
+







**
** Internally, this function just sets the Vdbe.expired flag on all
** prepared statements.  The flag is set to 1 for an immediate expiration
** and set to 2 for an advisory expiration.
*/
void sqlite3ExpirePreparedStatements(sqlite3 *db, int iCode){
  Vdbe *p;
  for(p = db->pVdbe; p; p=p->pNext){
  for(p = db->pVdbe; p; p=p->pVNext){
    p->expired = iCode+1;
  }
}

/*
** Return the database associated with the Vdbe.
*/
4814
4815
4816
4817
4818
4819
4820

4821

4822
4823

4824
4825













4826
4827

4828
4829
4830
4831
4832
4833
4834
5259
5260
5261
5262
5263
5264
5265
5266

5267
5268
5269
5270


5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283


5284
5285
5286
5287
5288
5289
5290
5291







+
-
+


+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+







**
** OP_PureFunc means that the function must be deterministic, and should
** throw an error if it is given inputs that would make it non-deterministic.
** This routine is invoked by date/time functions that use non-deterministic
** features such as 'now'.
*/
int sqlite3NotPureFunc(sqlite3_context *pCtx){
  const VdbeOp *pOp;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
  if( pCtx->pVdbe==0 ) return 1;
#endif
  pOp = pCtx->pVdbe->aOp + pCtx->iOp;
  if( pCtx->pVdbe->aOp[pCtx->iOp].opcode==OP_PureFunc ){
    sqlite3_result_error(pCtx, 
  if( pOp->opcode==OP_PureFunc ){
    const char *zContext;
    char *zMsg;
    if( pOp->p5 & NC_IsCheck ){
      zContext = "a CHECK constraint";
    }else if( pOp->p5 & NC_GenCol ){
      zContext = "a generated column";
    }else{
      zContext = "an index";
    }
    zMsg = sqlite3_mprintf("non-deterministic use of %s() in %s",
                           pCtx->pFunc->zName, zContext);
    sqlite3_result_error(pCtx, zMsg, -1);
       "non-deterministic function in index expression or CHECK constraint",
       -1);
    sqlite3_free(zMsg);
    return 0;
  }
  return 1;
}

#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
4854
4855
4856
4857
4858
4859
4860

4861
4862
4863
4864
4865

4866
4867

4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886


4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906


4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918

4919
4920
4921

4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934

4935
4936
4937
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322

5323
5324

5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343

5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378

5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395

5396
5397
5398
5399







+




-
+

-
+


















-
+
+




















+
+











-
+



+












-
+



** with the memory cells in the p->aMem[] array. Also free the UnpackedRecord
** structure itself, using sqlite3DbFree().
**
** This function is used to free UnpackedRecord structures allocated by
** the vdbeUnpackRecord() function found in vdbeapi.c.
*/
static void vdbeFreeUnpacked(sqlite3 *db, int nField, UnpackedRecord *p){
  assert( db!=0 );
  if( p ){
    int i;
    for(i=0; i<nField; i++){
      Mem *pMem = &p->aMem[i];
      if( pMem->zMalloc ) sqlite3VdbeMemRelease(pMem);
      if( pMem->zMalloc ) sqlite3VdbeMemReleaseMalloc(pMem);
    }
    sqlite3DbFreeNN(db, p);
    sqlite3DbNNFreeNN(db, p);
  }
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */

#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
/*
** Invoke the pre-update hook. If this is an UPDATE or DELETE pre-update call,
** then cursor passed as the second argument should point to the row about
** to be update or deleted. If the application calls sqlite3_preupdate_old(),
** the required value will be read from the row the cursor points to.
*/
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;

  assert( db->pPreUpdate==0 );
  memset(&preupdate, 0, sizeof(PreUpdate));
  if( HasRowid(pTab)==0 ){
    iKey1 = iKey2 = 0;
    preupdate.pPk = sqlite3PrimaryKeyIndex(pTab);
  }else{
    if( op==SQLITE_UPDATE ){
      iKey2 = v->aMem[iReg].u.i;
    }else{
      iKey2 = iKey1;
    }
  }

  assert( pCsr!=0 );
  assert( pCsr->eCurType==CURTYPE_BTREE );
  assert( pCsr->nField==pTab->nCol 
       || (pCsr->nField==pTab->nCol+1 && op==SQLITE_DELETE && iReg==-1)
  );

  preupdate.v = v;
  preupdate.pCsr = pCsr;
  preupdate.op = op;
  preupdate.iNewReg = iReg;
  preupdate.keyinfo.db = db;
  preupdate.keyinfo.enc = ENC(db);
  preupdate.keyinfo.nKeyField = pTab->nCol;
  preupdate.keyinfo.aSortOrder = (u8*)&fakeSortOrder;
  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);
  if( preupdate.aNew ){
    int i;
    for(i=0; i<pCsr->nField; i++){
      sqlite3VdbeMemRelease(&preupdate.aNew[i]);
    }
    sqlite3DbFreeNN(db, preupdate.aNew);
    sqlite3DbNNFreeNN(db, preupdate.aNew);
  }
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */

Changes to src/vdbeblob.c.

71
72
73
74
75
76
77



78

79
80
81
82
83
84
85
71
72
73
74
75
76
77
78
79
80

81
82
83
84
85
86
87
88







+
+
+
-
+







    assert( v->aOp[v->pc].opcode==OP_NotExists );
    rc = sqlite3VdbeExec(v);
  }else{
    rc = sqlite3_step(p->pStmt);
  }
  if( rc==SQLITE_ROW ){
    VdbeCursor *pC = v->apCsr[0];
    u32 type;
    assert( pC!=0 );
    assert( pC->eCurType==CURTYPE_BTREE );
    u32 type = pC->nHdrParsed>p->iCol ? pC->aType[p->iCol] : 0;
    type = pC->nHdrParsed>p->iCol ? pC->aType[p->iCol] : 0;
    testcase( pC->nHdrParsed==p->iCol );
    testcase( pC->nHdrParsed==p->iCol+1 );
    if( type<12 ){
      zErr = sqlite3MPrintf(p->db, "cannot open value of type %s",
          type==0?"null": type==7?"real": "integer"
      );
      rc = SQLITE_ERROR;
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
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







-
-
+
+

-














-
+



















-
+







  }
#endif
  wrFlag = !!wrFlag;                /* wrFlag = (wrFlag ? 1 : 0); */

  sqlite3_mutex_enter(db->mutex);

  pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob));
  do {
    memset(&sParse, 0, sizeof(Parse));
  while(1){
    sqlite3ParseObjectInit(&sParse,db);
    if( !pBlob ) goto blob_open_out;
    sParse.db = db;
    sqlite3DbFree(db, zErr);
    zErr = 0;

    sqlite3BtreeEnterAll(db);
    pTab = sqlite3LocateTable(&sParse, 0, zTable, zDb);
    if( pTab && IsVirtual(pTab) ){
      pTab = 0;
      sqlite3ErrorMsg(&sParse, "cannot open virtual table: %s", zTable);
    }
    if( pTab && !HasRowid(pTab) ){
      pTab = 0;
      sqlite3ErrorMsg(&sParse, "cannot open table without rowid: %s", zTable);
    }
#ifndef SQLITE_OMIT_VIEW
    if( pTab && pTab->pSelect ){
    if( pTab && IsView(pTab) ){
      pTab = 0;
      sqlite3ErrorMsg(&sParse, "cannot open view: %s", zTable);
    }
#endif
    if( !pTab ){
      if( sParse.zErrMsg ){
        sqlite3DbFree(db, zErr);
        zErr = sParse.zErrMsg;
        sParse.zErrMsg = 0;
      }
      rc = SQLITE_ERROR;
      sqlite3BtreeLeaveAll(db);
      goto blob_open_out;
    }
    pBlob->pTab = pTab;
    pBlob->zDb = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zDbSName;

    /* Now search pTab for the exact column. */
    for(iCol=0; iCol<pTab->nCol; iCol++) {
      if( sqlite3StrICmp(pTab->aCol[iCol].zName, zColumn)==0 ){
      if( sqlite3StrICmp(pTab->aCol[iCol].zCnName, zColumn)==0 ){
        break;
      }
    }
    if( iCol==pTab->nCol ){
      sqlite3DbFree(db, zErr);
      zErr = sqlite3MPrintf(db, "no such column: \"%s\"", zColumn);
      rc = SQLITE_ERROR;
208
209
210
211
212
213
214

215

216
217
218
219
220
221
222
210
211
212
213
214
215
216
217

218
219
220
221
222
223
224
225







+
-
+







#ifndef SQLITE_OMIT_FOREIGN_KEY
      if( db->flags&SQLITE_ForeignKeys ){
        /* Check that the column is not part of an FK child key definition. It
        ** is not necessary to check if it is part of a parent key, as parent
        ** key columns must be indexed. The check below will pick up this 
        ** case.  */
        FKey *pFKey;
        assert( IsOrdinaryTable(pTab) );
        for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){
        for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){
          int j;
          for(j=0; j<pFKey->nCol; j++){
            if( pFKey->aCol[j].iFrom==iCol ){
              zFault = "foreign key";
            }
          }
        }
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
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







-
+
+
+










-
+















+


-


+







    pBlob->iCol = iCol;
    pBlob->db = db;
    sqlite3BtreeLeaveAll(db);
    if( db->mallocFailed ){
      goto blob_open_out;
    }
    rc = blobSeekToRow(pBlob, iRow, &zErr);
  } while( (++nAttempt)<SQLITE_MAX_SCHEMA_RETRY && rc==SQLITE_SCHEMA );
    if( (++nAttempt)>=SQLITE_MAX_SCHEMA_RETRY || rc!=SQLITE_SCHEMA ) break;
    sqlite3ParseObjectReset(&sParse);
  }

blob_open_out:
  if( rc==SQLITE_OK && db->mallocFailed==0 ){
    *ppBlob = (sqlite3_blob *)pBlob;
  }else{
    if( pBlob && pBlob->pStmt ) sqlite3VdbeFinalize((Vdbe *)pBlob->pStmt);
    sqlite3DbFree(db, pBlob);
  }
  sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr);
  sqlite3DbFree(db, zErr);
  sqlite3ParserReset(&sParse);
  sqlite3ParseObjectReset(&sParse);
  rc = sqlite3ApiExit(db, rc);
  sqlite3_mutex_leave(db->mutex);
  return rc;
}

/*
** Close a blob handle that was previously created using
** sqlite3_blob_open().
*/
int sqlite3_blob_close(sqlite3_blob *pBlob){
  Incrblob *p = (Incrblob *)pBlob;
  int rc;
  sqlite3 *db;

  if( p ){
    sqlite3_stmt *pStmt = p->pStmt;
    db = p->db;
    sqlite3_mutex_enter(db->mutex);
    rc = sqlite3_finalize(p->pStmt);
    sqlite3DbFree(db, p);
    sqlite3_mutex_leave(db->mutex);
    rc = sqlite3_finalize(pStmt);
  }else{
    rc = SQLITE_OK;
  }
  return rc;
}

/*
414
415
416
417
418
419
420


421
422

423
424
425
426
427
428
429
420
421
422
423
424
425
426
427
428
429

430
431
432
433
434
435
436
437







+
+

-
+







      ** same way as an SQLITE_DELETE (the SQLITE_DELETE code is actually
      ** slightly more efficient). Since you cannot write to a PK column
      ** using the incremental-blob API, this works. For the sessions module
      ** anyhow.
      */
      sqlite3_int64 iKey;
      iKey = sqlite3BtreeIntegerKey(p->pCsr);
      assert( v->apCsr[0]!=0 );
      assert( v->apCsr[0]->eCurType==CURTYPE_BTREE );
      sqlite3VdbePreUpdateHook(
          v, v->apCsr[0], SQLITE_DELETE, p->zDb, p->pTab, iKey, -1
          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 ){
486
487
488
489
490
491
492

493
494
495
496
497
498
499
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508







+







  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/vdbemem.c.

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
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







+
+
+
+
+



















-
-
+
+


















-
+












+
+
-
+





















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
+
-
+
+

















-
+
+




-
-
-
-
+
+
+
+
+
+
+
+
-
+
+

+
+
+







** stores a single value in the VDBE.  Mem is an opaque structure visible
** only within the VDBE.  Interface routines refer to a Mem using the
** name sqlite_value
*/
#include "sqliteInt.h"
#include "vdbeInt.h"

/* True if X is a power of two.  0 is considered a power of two here.
** In other words, return true if X has at most one bit set.
*/
#define ISPOWEROF2(X)  (((X)&((X)-1))==0)

#ifdef SQLITE_DEBUG
/*
** Check invariants on a Mem object.
**
** This routine is intended for use inside of assert() statements, like
** this:    assert( sqlite3VdbeCheckMemInvariants(pMem) );
*/
int sqlite3VdbeCheckMemInvariants(Mem *p){
  /* If MEM_Dyn is set then Mem.xDel!=0.  
  ** Mem.xDel might not be initialized if MEM_Dyn is clear.
  */
  assert( (p->flags & MEM_Dyn)==0 || p->xDel!=0 );

  /* MEM_Dyn may only be set if Mem.szMalloc==0.  In this way we
  ** ensure that if Mem.szMalloc>0 then it is safe to do
  ** Mem.z = Mem.zMalloc without having to check Mem.flags&MEM_Dyn.
  ** That saves a few cycles in inner loops. */
  assert( (p->flags & MEM_Dyn)==0 || p->szMalloc==0 );

  /* Cannot be both MEM_Int and MEM_Real at the same time */
  assert( (p->flags & (MEM_Int|MEM_Real))!=(MEM_Int|MEM_Real) );
  /* Cannot have more than one of MEM_Int, MEM_Real, or MEM_IntReal */
  assert( ISPOWEROF2(p->flags & (MEM_Int|MEM_Real|MEM_IntReal)) );

  if( p->flags & MEM_Null ){
    /* Cannot be both MEM_Null and some other type */
    assert( (p->flags & (MEM_Int|MEM_Real|MEM_Str|MEM_Blob|MEM_Agg))==0 );

    /* If MEM_Null is set, then either the value is a pure NULL (the usual
    ** case) or it is a pointer set using sqlite3_bind_pointer() or
    ** sqlite3_result_pointer().  If a pointer, then MEM_Term must also be
    ** set.
    */
    if( (p->flags & (MEM_Term|MEM_Subtype))==(MEM_Term|MEM_Subtype) ){
      /* This is a pointer type.  There may be a flag to indicate what to
      ** do with the pointer. */
      assert( ((p->flags&MEM_Dyn)!=0 ? 1 : 0) +
              ((p->flags&MEM_Ephem)!=0 ? 1 : 0) +
              ((p->flags&MEM_Static)!=0 ? 1 : 0) <= 1 );

      /* No other bits set */
      assert( (p->flags & ~(MEM_Null|MEM_Term|MEM_Subtype
      assert( (p->flags & ~(MEM_Null|MEM_Term|MEM_Subtype|MEM_FromBind
                           |MEM_Dyn|MEM_Ephem|MEM_Static))==0 );
    }else{
      /* A pure NULL might have other flags, such as MEM_Static, MEM_Dyn,
      ** MEM_Ephem, MEM_Cleared, or MEM_Subtype */
    }
  }else{
    /* The MEM_Cleared bit is only allowed on NULLs */
    assert( (p->flags & MEM_Cleared)==0 );
  }

  /* The szMalloc field holds the correct memory allocation size */
  assert( p->szMalloc==0
       || (p->flags==MEM_Undefined 
           && p->szMalloc<=sqlite3DbMallocSize(p->db,p->zMalloc))
       || p->szMalloc==sqlite3DbMallocSize(p->db,p->zMalloc) );
       || p->szMalloc==sqlite3DbMallocSize(p->db,p->zMalloc));

  /* If p holds a string or blob, the Mem.z must point to exactly
  ** one of the following:
  **
  **   (1) Memory in Mem.zMalloc and managed by the Mem object
  **   (2) Memory to be freed using Mem.xDel
  **   (3) An ephemeral string or blob
  **   (4) A static string or blob
  */
  if( (p->flags & (MEM_Str|MEM_Blob)) && p->n>0 ){
    assert( 
      ((p->szMalloc>0 && p->z==p->zMalloc)? 1 : 0) +
      ((p->flags&MEM_Dyn)!=0 ? 1 : 0) +
      ((p->flags&MEM_Ephem)!=0 ? 1 : 0) +
      ((p->flags&MEM_Static)!=0 ? 1 : 0) == 1
    );
  }
  return 1;
}
#endif

/*
** Render a Mem object which is one of MEM_Int, MEM_Real, or MEM_IntReal
** into a buffer.
*/
static void vdbeMemRenderNum(int sz, char *zBuf, Mem *p){
  StrAccum acc;
  assert( p->flags & (MEM_Int|MEM_Real|MEM_IntReal) );
  assert( sz>22 );
  if( p->flags & MEM_Int ){
#if GCC_VERSION>=7000000
    /* Work-around for GCC bug
    ** https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96270 */
    i64 x;
    assert( (p->flags&MEM_Int)*2==sizeof(x) );
    memcpy(&x, (char*)&p->u, (p->flags&MEM_Int)*2);
    p->n = sqlite3Int64ToText(x, zBuf);
#else
    p->n = sqlite3Int64ToText(p->u.i, zBuf);
#endif
  }else{
    sqlite3StrAccumInit(&acc, 0, zBuf, sz, 0);
    sqlite3_str_appendf(&acc, "%!.15g", 
         (p->flags & MEM_IntReal)!=0 ? (double)p->u.i : p->u.r);
    assert( acc.zText==zBuf && acc.mxAlloc<=0 );
    zBuf[acc.nChar] = 0; /* Fast version of sqlite3StrAccumFinish(&acc) */
    p->n = acc.nChar;
  }
}

#ifdef SQLITE_DEBUG
/*
** Validity checks on pMem.  pMem holds a string.
**
** Check that string value of pMem agrees with its integer or real value.
** (1) Check that string value of pMem agrees with its integer or real value.
** (2) Check that the string is correctly zero terminated
**
** A single int or real value always converts to the same strings.  But
** many different strings can be converted into the same int or real.
** If a table contains a numeric value and an index is based on the
** corresponding string value, then it is important that the string be
** derived from the numeric value, not the other way around, to ensure
** that the index and table are consistent.  See ticket
** https://www.sqlite.org/src/info/343634942dd54ab (2018-01-31) for
** an example.
**
** This routine looks at pMem to verify that if it has both a numeric
** representation and a string representation then the string rep has
** been derived from the numeric and not the other way around.  It returns
** true if everything is ok and false if there is a problem.
**
** This routine is for use inside of assert() statements only.
*/
int sqlite3VdbeMemConsistentDualRep(Mem *p){
int sqlite3VdbeMemValidStrRep(Mem *p){
  Mem tmp;
  char zBuf[100];
  char *z;
  int i, j, incr;
  if( (p->flags & MEM_Str)==0 ) return 1;
  if( (p->flags & (MEM_Int|MEM_Real))==0 ) return 1;
  if( p->flags & MEM_Int ){
    sqlite3_snprintf(sizeof(zBuf),zBuf,"%lld",p->u.i);
  }else{
  if( p->flags & MEM_Term ){
    /* Insure that the string is properly zero-terminated.  Pay particular
    ** attention to the case where p->n is odd */
    if( p->szMalloc>0 && p->z==p->zMalloc ){
      assert( p->enc==SQLITE_UTF8 || p->szMalloc >= ((p->n+1)&~1)+2 );
      assert( p->enc!=SQLITE_UTF8 || p->szMalloc >= p->n+1 );
    }
    assert( p->z[p->n]==0 );
    sqlite3_snprintf(sizeof(zBuf),zBuf,"%!.15g",p->u.r);
    assert( p->enc==SQLITE_UTF8 || p->z[(p->n+1)&~1]==0 );
    assert( p->enc==SQLITE_UTF8 || p->z[((p->n+1)&~1)+1]==0 );
  }
  if( (p->flags & (MEM_Int|MEM_Real|MEM_IntReal))==0 ) return 1;
  memcpy(&tmp, p, sizeof(tmp));
  vdbeMemRenderNum(sizeof(zBuf), zBuf, &tmp);
  z = p->z;
  i = j = 0;
  incr = 1;
  if( p->enc!=SQLITE_UTF8 ){
    incr = 2;
    if( p->enc==SQLITE_UTF16BE ) z++;
  }
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
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







+



-
+
+
+
+
+



















-
+
-

















+
+
-
+
-

+
-
+
+
+
+
+
+







** SQLITE_NOMEM may be returned if a malloc() fails during conversion
** between formats.
*/
int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
#ifndef SQLITE_OMIT_UTF16
  int rc;
#endif
  assert( pMem!=0 );
  assert( !sqlite3VdbeMemIsRowSet(pMem) );
  assert( desiredEnc==SQLITE_UTF8 || desiredEnc==SQLITE_UTF16LE
           || desiredEnc==SQLITE_UTF16BE );
  if( !(pMem->flags&MEM_Str) || pMem->enc==desiredEnc ){
  if( !(pMem->flags&MEM_Str) ){
    pMem->enc = desiredEnc;
    return SQLITE_OK;
  }
  if( pMem->enc==desiredEnc ){
    return SQLITE_OK;
  }
  assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
#ifdef SQLITE_OMIT_UTF16
  return SQLITE_ERROR;
#else

  /* MemTranslate() may return SQLITE_OK or SQLITE_NOMEM. If NOMEM is returned,
  ** then the encoding of the value may not have changed.
  */
  rc = sqlite3VdbeMemTranslate(pMem, (u8)desiredEnc);
  assert(rc==SQLITE_OK    || rc==SQLITE_NOMEM);
  assert(rc==SQLITE_OK    || pMem->enc!=desiredEnc);
  assert(rc==SQLITE_NOMEM || pMem->enc==desiredEnc);
  return rc;
#endif
}

/*
** Make sure pMem->z points to a writable allocation of at least 
** Make sure pMem->z points to a writable allocation of at least n bytes.
** min(n,32) bytes.
**
** If the bPreserve argument is true, then copy of the content of
** pMem->z into the new allocation.  pMem must be either a string or
** blob if bPreserve is true.  If bPreserve is false, any prior content
** in pMem->z is discarded.
*/
SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
  assert( sqlite3VdbeCheckMemInvariants(pMem) );
  assert( !sqlite3VdbeMemIsRowSet(pMem) );
  testcase( pMem->db==0 );

  /* If the bPreserve flag is set to true, then the memory cell must already
  ** contain a valid string or blob value.  */
  assert( bPreserve==0 || pMem->flags&(MEM_Blob|MEM_Str) );
  testcase( bPreserve && pMem->z==0 );

  assert( pMem->szMalloc==0
       || (pMem->flags==MEM_Undefined 
           && pMem->szMalloc<=sqlite3DbMallocSize(pMem->db,pMem->zMalloc))
       || pMem->szMalloc==sqlite3DbMallocSize(pMem->db, pMem->zMalloc) );
       || pMem->szMalloc==sqlite3DbMallocSize(pMem->db,pMem->zMalloc));
  if( n<32 ) n = 32;
  if( pMem->szMalloc>0 && bPreserve && pMem->z==pMem->zMalloc ){
    if( pMem->db ){
    pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
      pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
    }else{
      pMem->zMalloc = sqlite3Realloc(pMem->z, n);
      if( pMem->zMalloc==0 ) sqlite3_free(pMem->z);
      pMem->z = pMem->zMalloc;
    }
    bPreserve = 0;
  }else{
    if( pMem->szMalloc>0 ) sqlite3DbFreeNN(pMem->db, pMem->zMalloc);
    pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n);
  }
  if( pMem->zMalloc==0 ){
    sqlite3VdbeMemSetNull(pMem);
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
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







-
-
+
+





-
+






-
+






+
+
+
+
+


-
+




+











+







/*
** Change the pMem->zMalloc allocation to be at least szNew bytes.
** If pMem->zMalloc already meets or exceeds the requested size, this
** routine is a no-op.
**
** Any prior string or blob content in the pMem object may be discarded.
** The pMem->xDel destructor is called, if it exists.  Though MEM_Str
** and MEM_Blob values may be discarded, MEM_Int, MEM_Real, and MEM_Null
** values are preserved.
** and MEM_Blob values may be discarded, MEM_Int, MEM_Real, MEM_IntReal,
** and MEM_Null values are preserved.
**
** Return SQLITE_OK on success or an error code (probably SQLITE_NOMEM)
** if unable to complete the resizing.
*/
int sqlite3VdbeMemClearAndResize(Mem *pMem, int szNew){
  assert( szNew>0 );
  assert( CORRUPT_DB || szNew>0 );
  assert( (pMem->flags & MEM_Dyn)==0 || pMem->szMalloc==0 );
  if( pMem->szMalloc<szNew ){
    return sqlite3VdbeMemGrow(pMem, szNew, 0);
  }
  assert( (pMem->flags & MEM_Dyn)==0 );
  pMem->z = pMem->zMalloc;
  pMem->flags &= (MEM_Null|MEM_Int|MEM_Real);
  pMem->flags &= (MEM_Null|MEM_Int|MEM_Real|MEM_IntReal);
  return SQLITE_OK;
}

/*
** It is already known that pMem contains an unterminated string.
** Add the zero terminator.
**
** Three bytes of zero are added.  In this way, there is guaranteed
** to be a double-zero byte at an even byte boundary in order to
** terminate a UTF16 string, even if the initial size of the buffer
** is an odd number of bytes.
*/
static SQLITE_NOINLINE int vdbeMemAddTerminator(Mem *pMem){
  if( sqlite3VdbeMemGrow(pMem, pMem->n+2, 1) ){
  if( sqlite3VdbeMemGrow(pMem, pMem->n+3, 1) ){
    return SQLITE_NOMEM_BKPT;
  }
  pMem->z[pMem->n] = 0;
  pMem->z[pMem->n+1] = 0;
  pMem->z[pMem->n+2] = 0;
  pMem->flags |= MEM_Term;
  return SQLITE_OK;
}

/*
** Change pMem so that its MEM_Str or MEM_Blob value is stored in
** MEM.zMalloc, where it can be safely written.
**
** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails.
*/
int sqlite3VdbeMemMakeWriteable(Mem *pMem){
  assert( pMem!=0 );
  assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
  assert( !sqlite3VdbeMemIsRowSet(pMem) );
  if( (pMem->flags & (MEM_Str|MEM_Blob))!=0 ){
    if( ExpandBlob(pMem) ) return SQLITE_NOMEM;
    if( pMem->szMalloc==0 || pMem->z!=pMem->zMalloc ){
      int rc = vdbeMemAddTerminator(pMem);
      if( rc ) return rc;
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
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







-
-
+
+
+
+






+





+
+












+











-
-
-
+
+
+

-
-
+
+








-


+

-
-
-
+
+
+









-
-
-
-
-
-
-
-
+
-
-
-
-

-
+


-
+
















+
+


-
+







+


















-



+
-
+

-
-
-




+







/*
** If the given Mem* has a zero-filled tail, turn it into an ordinary
** blob stored in dynamically allocated space.
*/
#ifndef SQLITE_OMIT_INCRBLOB
int sqlite3VdbeMemExpandBlob(Mem *pMem){
  int nByte;
  assert( pMem->flags & MEM_Zero );
  assert( pMem->flags&MEM_Blob );
  assert( pMem!=0 );
  assert( pMem->flags & MEM_Zero );
  assert( (pMem->flags&MEM_Blob)!=0 || MemNullNochng(pMem) );
  testcase( sqlite3_value_nochange(pMem) );
  assert( !sqlite3VdbeMemIsRowSet(pMem) );
  assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );

  /* Set nByte to the number of bytes required to store the expanded blob. */
  nByte = pMem->n + pMem->u.nZero;
  if( nByte<=0 ){
    if( (pMem->flags & MEM_Blob)==0 ) return SQLITE_OK;
    nByte = 1;
  }
  if( sqlite3VdbeMemGrow(pMem, nByte, 1) ){
    return SQLITE_NOMEM_BKPT;
  }
  assert( pMem->z!=0 );
  assert( sqlite3DbMallocSize(pMem->db,pMem->z) >= nByte );

  memset(&pMem->z[pMem->n], 0, pMem->u.nZero);
  pMem->n += pMem->u.nZero;
  pMem->flags &= ~(MEM_Zero|MEM_Term);
  return SQLITE_OK;
}
#endif

/*
** Make sure the given Mem is \u0000 terminated.
*/
int sqlite3VdbeMemNulTerminate(Mem *pMem){
  assert( pMem!=0 );
  assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
  testcase( (pMem->flags & (MEM_Term|MEM_Str))==(MEM_Term|MEM_Str) );
  testcase( (pMem->flags & (MEM_Term|MEM_Str))==0 );
  if( (pMem->flags & (MEM_Term|MEM_Str))!=MEM_Str ){
    return SQLITE_OK;   /* Nothing to do */
  }else{
    return vdbeMemAddTerminator(pMem);
  }
}

/*
** Add MEM_Str to the set of representations for the given Mem.  Numbers
** are converted using sqlite3_snprintf().  Converting a BLOB to a string
** is a no-op.
** Add MEM_Str to the set of representations for the given Mem.  This
** routine is only called if pMem is a number of some kind, not a NULL
** or a BLOB.
**
** Existing representations MEM_Int and MEM_Real are invalidated if
** bForce is true but are retained if bForce is false.
** Existing representations MEM_Int, MEM_Real, or MEM_IntReal are invalidated
** if bForce is true but are retained if bForce is false.
**
** A MEM_Null value will never be passed to this function. This function is
** used for converting values to text for returning to the user (i.e. via
** sqlite3_value_text()), or for ensuring that values to be used as btree
** keys are strings. In the former case a NULL pointer is returned the
** user and the latter is an internal programming error.
*/
int sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){
  int fg = pMem->flags;
  const int nByte = 32;

  assert( pMem!=0 );
  assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
  assert( !(fg&MEM_Zero) );
  assert( !(fg&(MEM_Str|MEM_Blob)) );
  assert( fg&(MEM_Int|MEM_Real) );
  assert( !(pMem->flags&MEM_Zero) );
  assert( !(pMem->flags&(MEM_Str|MEM_Blob)) );
  assert( pMem->flags&(MEM_Int|MEM_Real|MEM_IntReal) );
  assert( !sqlite3VdbeMemIsRowSet(pMem) );
  assert( EIGHT_BYTE_ALIGNMENT(pMem) );


  if( sqlite3VdbeMemClearAndResize(pMem, nByte) ){
    pMem->enc = 0;
    return SQLITE_NOMEM_BKPT;
  }

  /* For a Real or Integer, use sqlite3_snprintf() to produce the UTF-8
  ** string representation of the value. Then, if the required encoding
  ** is UTF-16le or UTF-16be do a translation.
  ** 
  ** FIX ME: It would be better if sqlite3_snprintf() could do UTF-16.
  */
  if( fg & MEM_Int ){
    sqlite3_snprintf(nByte, pMem->z, "%lld", pMem->u.i);
  vdbeMemRenderNum(nByte, pMem->z, pMem);
  }else{
    assert( fg & MEM_Real );
    sqlite3_snprintf(nByte, pMem->z, "%!.15g", pMem->u.r);
  }
  assert( pMem->z!=0 );
  pMem->n = sqlite3Strlen30NN(pMem->z);
  assert( pMem->n==sqlite3Strlen30NN(pMem->z) );
  pMem->enc = SQLITE_UTF8;
  pMem->flags |= MEM_Str|MEM_Term;
  if( bForce ) pMem->flags &= ~(MEM_Int|MEM_Real);
  if( bForce ) pMem->flags &= ~(MEM_Int|MEM_Real|MEM_IntReal);
  sqlite3VdbeChangeEncoding(pMem, enc);
  return SQLITE_OK;
}

/*
** Memory cell pMem contains the context of an aggregate function.
** This routine calls the finalize method for that function.  The
** result of the aggregate is stored back into pMem.
**
** Return SQLITE_ERROR if the finalizer reports an error.  SQLITE_OK
** otherwise.
*/
int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){
  sqlite3_context ctx;
  Mem t;
  assert( pFunc!=0 );
  assert( pMem!=0 );
  assert( pMem->db!=0 );
  assert( pFunc->xFinalize!=0 );
  assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef );
  assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
  assert( sqlite3_mutex_held(pMem->db->mutex) );
  memset(&ctx, 0, sizeof(ctx));
  memset(&t, 0, sizeof(t));
  t.flags = MEM_Null;
  t.db = pMem->db;
  ctx.pOut = &t;
  ctx.pMem = pMem;
  ctx.pFunc = pFunc;
  ctx.enc = ENC(t.db);
  pFunc->xFinalize(&ctx); /* IMP: R-24505-23230 */
  assert( (pMem->flags & MEM_Dyn)==0 );
  if( pMem->szMalloc>0 ) sqlite3DbFreeNN(pMem->db, pMem->zMalloc);
  memcpy(pMem, &t, sizeof(t));
  return ctx.isError;
}

/*
** Memory cell pAccum contains the context of an aggregate function.
** This routine calls the xValue method for that function and stores
** the results in memory cell pMem.
**
** SQLITE_ERROR is returned if xValue() reports an error. SQLITE_OK 
** otherwise.
*/
#ifndef SQLITE_OMIT_WINDOWFUNC
int sqlite3VdbeMemAggValue(Mem *pAccum, Mem *pOut, FuncDef *pFunc){
  sqlite3_context ctx;
  Mem t;
  assert( pFunc!=0 );
  assert( pFunc->xValue!=0 );
  assert( (pAccum->flags & MEM_Null)!=0 || pFunc==pAccum->u.pDef );
  assert( pAccum->db!=0 );
  assert( pAccum->db==0 || sqlite3_mutex_held(pAccum->db->mutex) );
  assert( sqlite3_mutex_held(pAccum->db->mutex) );
  memset(&ctx, 0, sizeof(ctx));
  memset(&t, 0, sizeof(t));
  t.flags = MEM_Null;
  t.db = pAccum->db;
  sqlite3VdbeMemSetNull(pOut);
  ctx.pOut = pOut;
  ctx.pMem = pAccum;
  ctx.pFunc = pFunc;
  ctx.enc = ENC(pAccum->db);
  pFunc->xValue(&ctx);
  return ctx.isError;
}
#endif /* SQLITE_OMIT_WINDOWFUNC */

/*
** If the memory cell contains a value that must be freed by
499
500
501
502
503
504
505








506
507
508
509
510
511
512
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582







+
+
+
+
+
+
+
+







*/
void sqlite3VdbeMemRelease(Mem *p){
  assert( sqlite3VdbeCheckMemInvariants(p) );
  if( VdbeMemDynamic(p) || p->szMalloc ){
    vdbeMemClear(p);
  }
}

/* Like sqlite3VdbeMemRelease() but faster for cases where we
** know in advance that the Mem is not MEM_Dyn or MEM_Agg.
*/
void sqlite3VdbeMemReleaseMalloc(Mem *p){
  assert( !VdbeMemDynamic(p) );
  if( p->szMalloc ) vdbeMemClear(p);
}

/*
** Convert a 64-bit IEEE double into a 64-bit signed integer.
** If the double is out of range of a 64-bit signed integer then
** return the closest available 64-bit signed integer.
*/
static SQLITE_NOINLINE i64 doubleToInt64(double r){
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
638
639

640
641
642
643
644
645
646
647
648
649
650
651
652
653

654
655
656
657
658
659
660
661
662
663


664
665
666
667
668
669

670

671












672
673
674
675

676
677
678
679
680
681
682





683

684

685
686
687
688
689
690
691
692
693
694
695
696
697
698
699










700
701

702
703
704
705
706
707
708
709
710
711
712
713
714


715
716
717
718
719
720
721
611
612
613
614
615
616
617

618
619
620
621
622

623
624
625
626
627
628
629

630
631
632
633

634

635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658

659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674

675
676
677
678
679
680
681


682
683
684
685


686
687
688
689
690
691
692
693
694

695
696













697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750

751
752
753

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







-
+




-
+

+



+
-
+



-
+
-



















+




-
+
+














-
+
+





-
-
+
+


-
-
+
+




+
+
+
-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+







+














+










+
+





-
+

+
-
+
+
+
+
+
+
+
+
+
+
+
+



-
+







+
+
+
+
+
-
+

+


-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
+











-
-
+
+







** a floating-point then the value returned is the integer part.
** If pMem is a string or blob, then we make an attempt to convert
** it into an integer and return that.  If pMem represents an
** an SQL-NULL value, return 0.
**
** If pMem represents a string value, its encoding might be changed.
*/
static SQLITE_NOINLINE i64 memIntValue(Mem *pMem){
static SQLITE_NOINLINE i64 memIntValue(const Mem *pMem){
  i64 value = 0;
  sqlite3Atoi64(pMem->z, &value, pMem->n, pMem->enc);
  return value;
}
i64 sqlite3VdbeIntValue(Mem *pMem){
i64 sqlite3VdbeIntValue(const Mem *pMem){
  int flags;
  assert( pMem!=0 );
  assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
  assert( EIGHT_BYTE_ALIGNMENT(pMem) );
  flags = pMem->flags;
  if( flags & (MEM_Int|MEM_IntReal) ){
  if( flags & MEM_Int ){
    testcase( flags & MEM_IntReal );
    return pMem->u.i;
  }else if( flags & MEM_Real ){
    return doubleToInt64(pMem->u.r);
  }else if( flags & (MEM_Str|MEM_Blob) ){
  }else if( (flags & (MEM_Str|MEM_Blob))!=0 && pMem->z!=0 ){
    assert( pMem->z || pMem->n==0 );
    return memIntValue(pMem);
  }else{
    return 0;
  }
}

/*
** Return the best representation of pMem that we can get into a
** double.  If pMem is already a double or an integer, return its
** value.  If it is a string or blob, try to convert it to a double.
** If it is a NULL, return 0.0.
*/
static SQLITE_NOINLINE double memRealValue(Mem *pMem){
  /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
  double val = (double)0;
  sqlite3AtoF(pMem->z, &val, pMem->n, pMem->enc);
  return val;
}
double sqlite3VdbeRealValue(Mem *pMem){
  assert( pMem!=0 );
  assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
  assert( EIGHT_BYTE_ALIGNMENT(pMem) );
  if( pMem->flags & MEM_Real ){
    return pMem->u.r;
  }else if( pMem->flags & MEM_Int ){
  }else if( pMem->flags & (MEM_Int|MEM_IntReal) ){
    testcase( pMem->flags & MEM_IntReal );
    return (double)pMem->u.i;
  }else if( pMem->flags & (MEM_Str|MEM_Blob) ){
    return memRealValue(pMem);
  }else{
    /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
    return (double)0;
  }
}

/*
** Return 1 if pMem represents true, and return 0 if pMem represents false.
** Return the value ifNull if pMem is NULL.  
*/
int sqlite3VdbeBooleanValue(Mem *pMem, int ifNull){
  if( pMem->flags & MEM_Int ) return pMem->u.i!=0;
  testcase( pMem->flags & MEM_IntReal );
  if( pMem->flags & (MEM_Int|MEM_IntReal) ) return pMem->u.i!=0;
  if( pMem->flags & MEM_Null ) return ifNull;
  return sqlite3VdbeRealValue(pMem)!=0.0;
}

/*
** The MEM structure is already a MEM_Real.  Try to also make it a
** MEM_Int if we can.
** The MEM structure is already a MEM_Real or MEM_IntReal. Try to 
** make it a MEM_Int if we can.
*/
void sqlite3VdbeIntegerAffinity(Mem *pMem){
  i64 ix;
  assert( pMem->flags & MEM_Real );
  assert( pMem!=0 );
  assert( pMem->flags & (MEM_Real|MEM_IntReal) );
  assert( !sqlite3VdbeMemIsRowSet(pMem) );
  assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
  assert( EIGHT_BYTE_ALIGNMENT(pMem) );

  if( pMem->flags & MEM_IntReal ){
    MemSetTypeFlag(pMem, MEM_Int);
  }else{
  ix = doubleToInt64(pMem->u.r);
    i64 ix = doubleToInt64(pMem->u.r);

  /* Only mark the value as an integer if
  **
  **    (1) the round-trip conversion real->int->real is a no-op, and
  **    (2) The integer is neither the largest nor the smallest
  **        possible integer (ticket #3922)
  **
  ** The second and third terms in the following conditional enforces
  ** the second condition under the assumption that addition overflow causes
  ** values to wrap around.
  */
  if( pMem->u.r==ix && ix>SMALLEST_INT64 && ix<LARGEST_INT64 ){
    pMem->u.i = ix;
    MemSetTypeFlag(pMem, MEM_Int);
    /* Only mark the value as an integer if
    **
    **    (1) the round-trip conversion real->int->real is a no-op, and
    **    (2) The integer is neither the largest nor the smallest
    **        possible integer (ticket #3922)
    **
    ** The second and third terms in the following conditional enforces
    ** the second condition under the assumption that addition overflow causes
    ** values to wrap around.
    */
    if( pMem->u.r==ix && ix>SMALLEST_INT64 && ix<LARGEST_INT64 ){
      pMem->u.i = ix;
      MemSetTypeFlag(pMem, MEM_Int);
    }
  }
}

/*
** Convert pMem to type integer.  Invalidate any prior representations.
*/
int sqlite3VdbeMemIntegerify(Mem *pMem){
  assert( pMem!=0 );
  assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
  assert( !sqlite3VdbeMemIsRowSet(pMem) );
  assert( EIGHT_BYTE_ALIGNMENT(pMem) );

  pMem->u.i = sqlite3VdbeIntValue(pMem);
  MemSetTypeFlag(pMem, MEM_Int);
  return SQLITE_OK;
}

/*
** Convert pMem so that it is of type MEM_Real.
** Invalidate any prior representations.
*/
int sqlite3VdbeMemRealify(Mem *pMem){
  assert( pMem!=0 );
  assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
  assert( EIGHT_BYTE_ALIGNMENT(pMem) );

  pMem->u.r = sqlite3VdbeRealValue(pMem);
  MemSetTypeFlag(pMem, MEM_Real);
  return SQLITE_OK;
}

/* Compare a floating point value to an integer.  Return true if the two
** values are the same within the precision of the floating point value.
**
** This function assumes that i was obtained by assignment from r1.
**
** For some versions of GCC on 32-bit machines, if you do the more obvious
** comparison of "r1==(double)i" you sometimes get an answer of false even
** though the r1 and (double)i values are bit-for-bit the same.
*/
static int sqlite3RealSameAsInt(double r1, sqlite3_int64 i){
int sqlite3RealSameAsInt(double r1, sqlite3_int64 i){
  double r2 = (double)i;
  return r1==0.0
  return memcmp(&r1, &r2, sizeof(r1))==0;
      || (memcmp(&r1, &r2, sizeof(r1))==0
          && i >= -2251799813685248LL && i < 2251799813685248LL);
}

/* Convert a floating point value to its closest integer.  Do so in
** a way that avoids 'outside the range of representable values' warnings
** from UBSAN.
*/
i64 sqlite3RealToI64(double r){
  if( r<=(double)SMALLEST_INT64 ) return SMALLEST_INT64;
  if( r>=(double)LARGEST_INT64) return LARGEST_INT64;
  return (i64)r;
}

/*
** Convert pMem so that it has types MEM_Real or MEM_Int or both.
** Convert pMem so that it has type MEM_Real or MEM_Int.
** Invalidate any prior representations.
**
** Every effort is made to force the conversion, even if the input
** is a string that does not look completely like a number.  Convert
** as much of the string as we can and ignore the rest.
*/
int sqlite3VdbeMemNumerify(Mem *pMem){
  assert( pMem!=0 );
  testcase( pMem->flags & MEM_Int );
  testcase( pMem->flags & MEM_Real );
  testcase( pMem->flags & MEM_IntReal );
  testcase( pMem->flags & MEM_Null );
  if( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 ){
  if( (pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Null))==0 ){
    int rc;
    sqlite3_int64 ix;
    assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 );
    assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
    rc = sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc);
    if( rc==0 ){
      MemSetTypeFlag(pMem, MEM_Int);
    }else{
      i64 i = pMem->u.i;
      sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc);
      if( rc==1 && sqlite3RealSameAsInt(pMem->u.r, i) ){
        pMem->u.i = i;
        MemSetTypeFlag(pMem, MEM_Int);
      }else{
        MemSetTypeFlag(pMem, MEM_Real);
      }
    }
    rc = sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc);
    if( ((rc==0 || rc==1) && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1)
     || sqlite3RealSameAsInt(pMem->u.r, (ix = sqlite3RealToI64(pMem->u.r)))
    ){
      pMem->u.i = ix;
      MemSetTypeFlag(pMem, MEM_Int);
    }else{
      MemSetTypeFlag(pMem, MEM_Real);
    }
  }
  }
  assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))!=0 );
  assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Null))!=0 );
  pMem->flags &= ~(MEM_Str|MEM_Blob|MEM_Zero);
  return SQLITE_OK;
}

/*
** Cast the datatype of the value in pMem according to the affinity
** "aff".  Casting is different from applying affinity in that a cast
** is forced.  In other words, the value is converted into the desired
** affinity even if that results in loss of data.  This routine is
** used (for example) to implement the SQL "cast()" operator.
*/
void sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){
  if( pMem->flags & MEM_Null ) return;
int sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){
  if( pMem->flags & MEM_Null ) return SQLITE_OK;
  switch( aff ){
    case SQLITE_AFF_BLOB: {   /* Really a cast to BLOB */
      if( (pMem->flags & MEM_Blob)==0 ){
        sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding);
        assert( pMem->flags & MEM_Str || pMem->db->mallocFailed );
        if( pMem->flags & MEM_Str ) MemSetTypeFlag(pMem, MEM_Blob);
      }else{
737
738
739
740
741
742
743
744
745



746
747

748
749
750
751
752
753
754
833
834
835
836
837
838
839


840
841
842
843
844
845
846
847
848
849
850
851
852







-
-
+
+
+


+







    }
    default: {
      assert( aff==SQLITE_AFF_TEXT );
      assert( MEM_Str==(MEM_Blob>>3) );
      pMem->flags |= (pMem->flags&MEM_Blob)>>3;
      sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding);
      assert( pMem->flags & MEM_Str || pMem->db->mallocFailed );
      pMem->flags &= ~(MEM_Int|MEM_Real|MEM_Blob|MEM_Zero);
      break;
      pMem->flags &= ~(MEM_Int|MEM_Real|MEM_IntReal|MEM_Blob|MEM_Zero);
      if( encoding!=SQLITE_UTF8 ) pMem->n &= ~1;
      return sqlite3VdbeChangeEncoding(pMem, encoding);
    }
  }
  return SQLITE_OK;
}

/*
** Initialize bulk memory to be a consistent Mem object.
**
** The minimum amount of initialization feasible is performed.
*/
783
784
785
786
787
788
789

790
791
792
793
794
795
796
797
798















799
800
801
802
803
804
805
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919







+









+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  sqlite3VdbeMemSetNull((Mem*)p); 
}

/*
** Delete any previous value and set the value to be a BLOB of length
** n containing all zeros.
*/
#ifndef SQLITE_OMIT_INCRBLOB
void sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){
  sqlite3VdbeMemRelease(pMem);
  pMem->flags = MEM_Blob|MEM_Zero;
  pMem->n = 0;
  if( n<0 ) n = 0;
  pMem->u.nZero = n;
  pMem->enc = SQLITE_UTF8;
  pMem->z = 0;
}
#else
int sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){
  int nByte = n>0?n:1;
  if( sqlite3VdbeMemGrow(pMem, nByte, 0) ){
    return SQLITE_NOMEM_BKPT;
  }
  assert( pMem->z!=0 );
  assert( sqlite3DbMallocSize(pMem->db, pMem->z)>=nByte );
  memset(pMem->z, 0, nByte);
  pMem->n = n>0?n:0;
  pMem->flags = MEM_Blob;
  pMem->enc = SQLITE_UTF8;
  return SQLITE_OK;
}
#endif

/*
** The pMem is known to contain content that needs to be destroyed prior
** to a value change.  So invoke the destructor, then set the value to
** a 64-bit integer.
*/
static SQLITE_NOINLINE void vdbeReleaseAndSetInt64(Mem *pMem, i64 val){
831
832
833
834
835
836
837

838
839
840
841
842
843
844
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959







+







void sqlite3VdbeMemSetPointer(
  Mem *pMem,
  void *pPtr,
  const char *zPType,
  void (*xDestructor)(void*)
){
  assert( pMem->flags==MEM_Null );
  vdbeMemClear(pMem);
  pMem->u.zPType = zPType ? zPType : "";
  pMem->z = pPtr;
  pMem->flags = MEM_Null|MEM_Dyn|MEM_Subtype|MEM_Term;
  pMem->eSubtype = 'p';
  pMem->xDel = xDestructor ? xDestructor : sqlite3NoopDestructor;
}

906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
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







-
-
+
+




-
+

+
+
+
+
+
-
+





-
-
+
+
-
-
-










-








#ifdef SQLITE_DEBUG
/*
** This routine prepares a memory cell for modification by breaking
** its link to a shallow copy and by marking any current shallow
** copies of this cell as invalid.
**
** This is used for testing and debugging only - to make sure shallow
** copies are not misused.
** This is used for testing and debugging only - to help ensure that shallow
** copies (created by OP_SCopy) are not misused.
*/
void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){
  int i;
  Mem *pX;
  for(i=0, pX=pVdbe->aMem; i<pVdbe->nMem; i++, pX++){
  for(i=1, pX=pVdbe->aMem+1; i<pVdbe->nMem; i++, pX++){
    if( pX->pScopyFrom==pMem ){
      u16 mFlags;
      if( pVdbe->db->flags & SQLITE_VdbeTrace ){
        sqlite3DebugPrintf("Invalidate R[%d] due to change in R[%d]\n",
          (int)(pX - pVdbe->aMem), (int)(pMem - pVdbe->aMem));
      }
      /* If pX is marked as a shallow copy of pMem, then verify that
      /* If pX is marked as a shallow copy of pMem, then try to verify that
      ** no significant changes have been made to pX since the OP_SCopy.
      ** A significant change would indicated a missed call to this
      ** function for pX.  Minor changes, such as adding or removing a
      ** dual type, are allowed, as long as the underlying value is the
      ** same. */
      u16 mFlags = pMem->flags & pX->flags & pX->mScopyFlags;
      assert( (mFlags&MEM_Int)==0 || pMem->u.i==pX->u.i );
      mFlags = pMem->flags & pX->flags & pX->mScopyFlags;
      assert( (mFlags&(MEM_Int|MEM_IntReal))==0 || pMem->u.i==pX->u.i );
      assert( (mFlags&MEM_Real)==0 || pMem->u.r==pX->u.r );
      assert( (mFlags&MEM_Str)==0  || (pMem->n==pX->n && pMem->z==pX->z) );
      assert( (mFlags&MEM_Blob)==0  || sqlite3BlobCompare(pMem,pX)==0 );
      
      /* pMem is the register that is changing.  But also mark pX as
      ** undefined so that we can quickly detect the shallow-copy error */
      pX->flags = MEM_Undefined;
      pX->pScopyFrom = 0;
    }
  }
  pMem->pScopyFrom = 0;
}
#endif /* SQLITE_DEBUG */


/*
** Make an shallow copy of pFrom into pTo.  Prior contents of
** pTo are freed.  The pFrom->z field is not duplicated.  If
** pFrom->z is used, then pTo->z points to the same thing as pFrom->z
** and flags gets srcType (either MEM_Ephem or MEM_Static).
*/
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
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
1286
1287
1288
1289


1290
1291
1292

1293

1294
1295
1296

1297
1298
1299
1300
1301
1302
1303
1304







+
+
+
+
+
+
+




-
+



-
+

-
+

+


+












-



-
+
-



+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
+



-
-
-



-
+



-
-
-
-



+
+
+
+
-
-
-
-
-
+
+
+
+
+
+

-
+


-
+




-
-
-



















-
+







+
+
+












-
+

-



-









-
-
+
+

-
+
-



-
+







** pointer copied.
**
** If the string is too large (if it exceeds the SQLITE_LIMIT_LENGTH
** size limit) then no memory allocation occurs.  If the string can be
** stored without allocating memory, then it is.  If a memory allocation
** is required to store the string, then value of pMem is unchanged.  In
** either case, SQLITE_TOOBIG is returned.
**
** The "enc" parameter is the text encoding for the string, or zero
** to store a blob.
**
** If n is negative, then the string consists of all bytes up to but
** excluding the first zero character.  The n parameter must be
** non-negative for blobs.
*/
int sqlite3VdbeMemSetStr(
  Mem *pMem,          /* Memory cell to set to string value */
  const char *z,      /* String pointer */
  int n,              /* Bytes in string, or negative */
  i64 n,              /* Bytes in string, or negative */
  u8 enc,             /* Encoding of z.  0 for BLOBs */
  void (*xDel)(void*) /* Destructor function */
){
  int nByte = n;      /* New value for pMem->n */
  i64 nByte = n;      /* New value for pMem->n */
  int iLimit;         /* Maximum allowed string or blob size */
  u16 flags = 0;      /* New value for pMem->flags */
  u16 flags;          /* New value for pMem->flags */

  assert( pMem!=0 );
  assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
  assert( !sqlite3VdbeMemIsRowSet(pMem) );
  assert( enc!=0 || n>=0 );

  /* If z is a NULL pointer, set pMem to contain an SQL NULL. */
  if( !z ){
    sqlite3VdbeMemSetNull(pMem);
    return SQLITE_OK;
  }

  if( pMem->db ){
    iLimit = pMem->db->aLimit[SQLITE_LIMIT_LENGTH];
  }else{
    iLimit = SQLITE_MAX_LENGTH;
  }
  flags = (enc==0?MEM_Blob:MEM_Str);
  if( nByte<0 ){
    assert( enc!=0 );
    if( enc==SQLITE_UTF8 ){
      nByte = 0x7fffffff & (int)strlen(z);
      nByte = strlen(z);
      if( nByte>iLimit ) nByte = iLimit+1;
    }else{
      for(nByte=0; nByte<=iLimit && (z[nByte] | z[nByte+1]); nByte+=2){}
    }
    flags= MEM_Str|MEM_Term;
  }else if( enc==0 ){
    flags |= MEM_Term;
    flags = MEM_Blob;
    enc = SQLITE_UTF8;
  }else{
    flags = MEM_Str;
  }
  if( nByte>iLimit ){
    if( xDel && xDel!=SQLITE_TRANSIENT ){
      if( xDel==SQLITE_DYNAMIC ){
        sqlite3DbFree(pMem->db, (void*)z);
      }else{
        xDel((void*)z);
      }
    }
    sqlite3VdbeMemSetNull(pMem);
    return sqlite3ErrorToParser(pMem->db, SQLITE_TOOBIG);
  }

  /* The following block sets the new values of Mem.z and Mem.xDel. It
  ** also sets a flag in local variable "flags" to indicate the memory
  ** management (one of MEM_Dyn or MEM_Static).
  */
  if( xDel==SQLITE_TRANSIENT ){
    int nAlloc = nByte;
    i64 nAlloc = nByte;
    if( flags&MEM_Term ){
      nAlloc += (enc==SQLITE_UTF8?1:2);
    }
    if( nByte>iLimit ){
      return SQLITE_TOOBIG;
    }
    testcase( nAlloc==0 );
    testcase( nAlloc==31 );
    testcase( nAlloc==32 );
    if( sqlite3VdbeMemClearAndResize(pMem, MAX(nAlloc,32)) ){
    if( sqlite3VdbeMemClearAndResize(pMem, (int)MAX(nAlloc,32)) ){
      return SQLITE_NOMEM_BKPT;
    }
    memcpy(pMem->z, z, nAlloc);
  }else if( xDel==SQLITE_DYNAMIC ){
    sqlite3VdbeMemRelease(pMem);
    pMem->zMalloc = pMem->z = (char *)z;
    pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc);
  }else{
    sqlite3VdbeMemRelease(pMem);
    pMem->z = (char *)z;
    if( xDel==SQLITE_DYNAMIC ){
      pMem->zMalloc = pMem->z;
      pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc);
    }else{
    pMem->xDel = xDel;
    flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn);
  }

  pMem->n = nByte;
      pMem->xDel = xDel;
      flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn);
    }
  }

  pMem->n = (int)(nByte & 0x7fffffff);
  pMem->flags = flags;
  pMem->enc = (enc==0 ? SQLITE_UTF8 : enc);
  pMem->enc = enc;

#ifndef SQLITE_OMIT_UTF16
  if( pMem->enc!=SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){
  if( enc>SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){
    return SQLITE_NOMEM_BKPT;
  }
#endif

  if( nByte>iLimit ){
    return SQLITE_TOOBIG;
  }

  return SQLITE_OK;
}

/*
** Move data out of a btree key or data field and into a Mem structure.
** The data is payload from the entry that pCur is currently pointing
** to.  offset and amt determine what portion of the data or key to retrieve.
** The result is written into the pMem element.
**
** The pMem object must have been initialized.  This routine will use
** pMem->zMalloc to hold the content from the btree, if possible.  New
** pMem->zMalloc space will be allocated if necessary.  The calling routine
** is responsible for making sure that the pMem object is eventually
** destroyed.
**
** If this routine fails for any reason (malloc returns NULL or unable
** to read from the disk) then the pMem is left in an inconsistent state.
*/
static SQLITE_NOINLINE int vdbeMemFromBtreeResize(
int sqlite3VdbeMemFromBtree(
  BtCursor *pCur,   /* Cursor pointing at record to retrieve. */
  u32 offset,       /* Offset from the start of data to return bytes from. */
  u32 amt,          /* Number of bytes to return. */
  Mem *pMem         /* OUT: Return data in this Mem structure. */
){
  int rc;
  pMem->flags = MEM_Null;
  if( sqlite3BtreeMaxRecordSize(pCur)<offset+amt ){
    return SQLITE_CORRUPT_BKPT;
  }
  if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+1)) ){
    rc = sqlite3BtreePayload(pCur, offset, amt, pMem->z);
    if( rc==SQLITE_OK ){
      pMem->z[amt] = 0;   /* Overrun area used when reading malformed records */
      pMem->flags = MEM_Blob;
      pMem->n = (int)amt;
    }else{
      sqlite3VdbeMemRelease(pMem);
    }
  }
  return rc;
}
int sqlite3VdbeMemFromBtree(
int sqlite3VdbeMemFromBtreeZeroOffset(
  BtCursor *pCur,   /* Cursor pointing at record to retrieve. */
  u32 offset,       /* Offset from the start of data to return bytes from. */
  u32 amt,          /* Number of bytes to return. */
  Mem *pMem         /* OUT: Return data in this Mem structure. */
){
  char *zData;        /* Data from the btree layer */
  u32 available = 0;  /* Number of bytes available on the local btree page */
  int rc = SQLITE_OK; /* Return code */

  assert( sqlite3BtreeCursorIsValid(pCur) );
  assert( !VdbeMemDynamic(pMem) );

  /* Note: the calls to BtreeKeyFetch() and DataFetch() below assert() 
  ** that both the BtShared and database handle mutexes are held. */
  assert( !sqlite3VdbeMemIsRowSet(pMem) );
  zData = (char *)sqlite3BtreePayloadFetch(pCur, &available);
  assert( zData!=0 );
  pMem->z = (char *)sqlite3BtreePayloadFetch(pCur, &available);
  assert( pMem->z!=0 );

  if( offset+amt<=available ){
  if( amt<=available ){
    pMem->z = &zData[offset];
    pMem->flags = MEM_Blob|MEM_Ephem;
    pMem->n = (int)amt;
  }else{
    rc = vdbeMemFromBtreeResize(pCur, offset, amt, pMem);
    rc = sqlite3VdbeMemFromBtree(pCur, 0, amt, pMem);
  }

  return rc;
}

/*
** The pVal argument is known to be a value other than NULL.
1193
1194
1195
1196
1197
1198
1199
1200

1201
1202
1203
1204
1205
1206
1207
1327
1328
1329
1330
1331
1332
1333

1334
1335
1336
1337
1338
1339
1340
1341







-
+







  }else{
    sqlite3VdbeMemStringify(pVal, enc, 0);
    assert( 0==(1&SQLITE_PTR_TO_INT(pVal->z)) );
  }
  assert(pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) || pVal->db==0
              || pVal->db->mallocFailed );
  if( pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) ){
    assert( sqlite3VdbeMemConsistentDualRep(pVal) );
    assert( sqlite3VdbeMemValidStrRep(pVal) );
    return pVal->z;
  }else{
    return 0;
  }
}

/* This function is only available internally, it is not part of the
1216
1217
1218
1219
1220
1221
1222
1223

1224
1225
1226
1227
1228
1229
1230
1350
1351
1352
1353
1354
1355
1356

1357
1358
1359
1360
1361
1362
1363
1364







-
+







*/
const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){
  if( !pVal ) return 0;
  assert( pVal->db==0 || sqlite3_mutex_held(pVal->db->mutex) );
  assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) );
  assert( !sqlite3VdbeMemIsRowSet(pVal) );
  if( (pVal->flags&(MEM_Str|MEM_Term))==(MEM_Str|MEM_Term) && pVal->enc==enc ){
    assert( sqlite3VdbeMemConsistentDualRep(pVal) );
    assert( sqlite3VdbeMemValidStrRep(pVal) );
    return pVal->z;
  }
  if( pVal->flags&MEM_Null ){
    return 0;
  }
  return valueToText(pVal, enc);
}
1260
1261
1262
1263
1264
1265
1266
1267

1268
1269
1270
1271
1272
1273
1274
1394
1395
1396
1397
1398
1399
1400

1401
1402
1403
1404
1405
1406
1407
1408







-
+







** Otherwise, if the second argument is non-zero, then this function is 
** being called indirectly by sqlite3Stat4ProbeSetValue(). If it has not
** already been allocated, allocate the UnpackedRecord structure that 
** that function will return to its caller here. Then return a pointer to
** an sqlite3_value within the UnpackedRecord.a[] array.
*/
static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
  if( p ){
    UnpackedRecord *pRec = p->ppRec[0];

    if( pRec==0 ){
      Index *pIdx = p->pIdx;      /* Index being probed */
      int nByte;                  /* Bytes of space to allocate */
      int i;                      /* Counter variable */
1296
1297
1298
1299
1300
1301
1302
1303

1304
1305
1306
1307
1308
1309
1310
1430
1431
1432
1433
1434
1435
1436

1437
1438
1439
1440
1441
1442
1443
1444







-
+







    }
  
    pRec->nField = p->iVal+1;
    return &pRec->aMem[p->iVal];
  }
#else
  UNUSED_PARAMETER(p);
#endif /* defined(SQLITE_ENABLE_STAT3_OR_STAT4) */
#endif /* defined(SQLITE_ENABLE_STAT4) */
  return sqlite3ValueNew(db);
}

/*
** The expression object indicated by the second argument is guaranteed
** to be a scalar SQL function. If
**
1320
1321
1322
1323
1324
1325
1326
1327

1328
1329
1330

1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346

1347
1348

1349
1350
1351
1352
1353
1354
1355
1454
1455
1456
1457
1458
1459
1460

1461
1462
1463

1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491







-
+


-
+
















+


+







** If the result is a text value, the sqlite3_value object uses encoding 
** enc.
**
** If the conditions above are not met, this function returns SQLITE_OK
** and sets (*ppVal) to NULL. Or, if an error occurs, (*ppVal) is set to
** NULL and an SQLite error code returned.
*/
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
static int valueFromFunction(
  sqlite3 *db,                    /* The database connection */
  Expr *p,                        /* The expression to evaluate */
  const Expr *p,                  /* The expression to evaluate */
  u8 enc,                         /* Encoding to use */
  u8 aff,                         /* Affinity to use */
  sqlite3_value **ppVal,          /* Write the new value here */
  struct ValueNewStat4Ctx *pCtx   /* Second argument for valueNew() */
){
  sqlite3_context ctx;            /* Context object for function invocation */
  sqlite3_value **apVal = 0;      /* Function arguments */
  int nVal = 0;                   /* Size of apVal[] array */
  FuncDef *pFunc = 0;             /* Function definition */
  sqlite3_value *pVal = 0;        /* New value */
  int rc = SQLITE_OK;             /* Return code */
  ExprList *pList = 0;            /* Function arguments */
  int i;                          /* Iterator variable */

  assert( pCtx!=0 );
  assert( (p->flags & EP_TokenOnly)==0 );
  assert( ExprUseXList(p) );
  pList = p->x.pList;
  if( pList ) nVal = pList->nExpr;
  assert( !ExprHasProperty(p, EP_IntValue) );
  pFunc = sqlite3FindFunction(db, p->u.zToken, nVal, enc, 0);
  assert( pFunc );
  if( (pFunc->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG))==0 
   || (pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL)
  ){
    return SQLITE_OK;
  }
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
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451


1452

1453
1454
1455
1456
1457


1458
1459
1460
1461
1462
1463
1464
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
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
1574
1575
1576
1577

1578



1579
1580
1581
1582
1583
1584
1585
1586
1587
1588

1589
1590
1591
1592


1593
1594
1595
1596
1597
1598
1599
1600
1601







-



+







+
+





+



















-
+













-
+














-

-
-
-








+
+
-
+



-
-
+
+








  pVal = valueNew(db, pCtx);
  if( pVal==0 ){
    rc = SQLITE_NOMEM_BKPT;
    goto value_from_function_out;
  }

  assert( pCtx->pParse->rc==SQLITE_OK );
  memset(&ctx, 0, sizeof(ctx));
  ctx.pOut = pVal;
  ctx.pFunc = pFunc;
  ctx.enc = ENC(db);
  pFunc->xSFunc(&ctx, nVal, apVal);
  if( ctx.isError ){
    rc = ctx.isError;
    sqlite3ErrorMsg(pCtx->pParse, "%s", sqlite3_value_text(pVal));
  }else{
    sqlite3ValueApplyAffinity(pVal, aff, SQLITE_UTF8);
    assert( rc==SQLITE_OK );
    assert( enc==pVal->enc || db->mallocFailed );
#if 0  /* Not reachable except after a prior failure */
    rc = sqlite3VdbeChangeEncoding(pVal, enc);
    if( rc==SQLITE_OK && sqlite3VdbeMemTooBig(pVal) ){
      rc = SQLITE_TOOBIG;
      pCtx->pParse->nErr++;
    }
#endif
  }
  pCtx->pParse->rc = rc;

 value_from_function_out:
  if( rc!=SQLITE_OK ){
    pVal = 0;
  }
  if( apVal ){
    for(i=0; i<nVal; i++){
      sqlite3ValueFree(apVal[i]);
    }
    sqlite3DbFreeNN(db, apVal);
  }

  *ppVal = pVal;
  return rc;
}
#else
# define valueFromFunction(a,b,c,d,e,f) SQLITE_OK
#endif /* defined(SQLITE_ENABLE_STAT3_OR_STAT4) */
#endif /* defined(SQLITE_ENABLE_STAT4) */

/*
** Extract a value from the supplied expression in the manner described
** above sqlite3ValueFromExpr(). Allocate the sqlite3_value object
** using valueNew().
**
** If pCtx is NULL and an error occurs after the sqlite3_value object
** has been allocated, it is freed before returning. Or, if pCtx is not
** NULL, it is assumed that the caller will free any allocated object
** in all cases.
*/
static int valueFromExpr(
  sqlite3 *db,                    /* The database connection */
  Expr *pExpr,                    /* The expression to evaluate */
  const Expr *pExpr,              /* The expression to evaluate */
  u8 enc,                         /* Encoding to use */
  u8 affinity,                    /* Affinity to use */
  sqlite3_value **ppVal,          /* Write the new value here */
  struct ValueNewStat4Ctx *pCtx   /* Second argument for valueNew() */
){
  int op;
  char *zVal = 0;
  sqlite3_value *pVal = 0;
  int negInt = 1;
  const char *zNeg = "";
  int rc = SQLITE_OK;

  assert( pExpr!=0 );
  while( (op = pExpr->op)==TK_UPLUS || op==TK_SPAN ) pExpr = pExpr->pLeft;
#if defined(SQLITE_ENABLE_STAT3_OR_STAT4)
  if( op==TK_REGISTER ) op = pExpr->op2;
#else
  if( NEVER(op==TK_REGISTER) ) op = pExpr->op2;
#endif

  /* Compressed expressions only appear when parsing the DEFAULT clause
  ** on a table column definition, and hence only when pCtx==0.  This
  ** check ensures that an EP_TokenOnly expression is never passed down
  ** into valueFromFunction(). */
  assert( (pExpr->flags & EP_TokenOnly)==0 || pCtx==0 );

  if( op==TK_CAST ){
    u8 aff;
    assert( !ExprHasProperty(pExpr, EP_IntValue) );
    u8 aff = sqlite3AffinityType(pExpr->u.zToken,0);
    aff = sqlite3AffinityType(pExpr->u.zToken,0);
    rc = valueFromExpr(db, pExpr->pLeft, enc, aff, ppVal, pCtx);
    testcase( rc!=SQLITE_OK );
    if( *ppVal ){
      sqlite3VdbeMemCast(*ppVal, aff, SQLITE_UTF8);
      sqlite3ValueApplyAffinity(*ppVal, affinity, SQLITE_UTF8);
      sqlite3VdbeMemCast(*ppVal, aff, enc);
      sqlite3ValueApplyAffinity(*ppVal, affinity, enc);
    }
    return rc;
  }

  /* Handle negative integers in a single step.  This is needed in the
  ** case when the value is -9223372036854775808.
  */
1481
1482
1483
1484
1485
1486
1487

1488





1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500

1501



1502
1503
1504
1505
1506
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
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
1574
1575
1576

1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1618
1619
1620
1621
1622
1623
1624
1625

1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656

1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673

1674
1675
1676
1677
1678
1679
1680



1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
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







+
-
+
+
+
+
+












+

+
+
+









-
+




+











-
+





+
-
-
-
+
+
+
+
+






-
-
+
+




-
+



















-
+







-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







      sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC);
    }
    if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_BLOB ){
      sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8);
    }else{
      sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8);
    }
    assert( (pVal->flags & MEM_IntReal)==0 );
    if( pVal->flags & (MEM_Int|MEM_Real) ) pVal->flags &= ~MEM_Str;
    if( pVal->flags & (MEM_Int|MEM_IntReal|MEM_Real) ){
      testcase( pVal->flags & MEM_Int );
      testcase( pVal->flags & MEM_Real );
      pVal->flags &= ~MEM_Str;
    }
    if( enc!=SQLITE_UTF8 ){
      rc = sqlite3VdbeChangeEncoding(pVal, enc);
    }
  }else if( op==TK_UMINUS ) {
    /* This branch happens for multiple negative signs.  Ex: -(-5) */
    if( SQLITE_OK==valueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal,pCtx) 
     && pVal!=0
    ){
      sqlite3VdbeMemNumerify(pVal);
      if( pVal->flags & MEM_Real ){
        pVal->u.r = -pVal->u.r;
      }else if( pVal->u.i==SMALLEST_INT64 ){
#ifndef SQLITE_OMIT_FLOATING_POINT
        pVal->u.r = -(double)SMALLEST_INT64;
#else
        pVal->u.r = LARGEST_INT64;
#endif
        MemSetTypeFlag(pVal, MEM_Real);
      }else{
        pVal->u.i = -pVal->u.i;
      }
      sqlite3ValueApplyAffinity(pVal, affinity, enc);
    }
  }else if( op==TK_NULL ){
    pVal = valueNew(db, pCtx);
    if( pVal==0 ) goto no_mem;
    sqlite3VdbeMemNumerify(pVal);
    sqlite3VdbeMemSetNull(pVal);
  }
#ifndef SQLITE_OMIT_BLOB_LITERAL
  else if( op==TK_BLOB ){
    int nVal;
    assert( !ExprHasProperty(pExpr, EP_IntValue) );
    assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' );
    assert( pExpr->u.zToken[1]=='\'' );
    pVal = valueNew(db, pCtx);
    if( !pVal ) goto no_mem;
    zVal = &pExpr->u.zToken[2];
    nVal = sqlite3Strlen30(zVal)-1;
    assert( zVal[nVal]=='\'' );
    sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal, nVal), nVal/2,
                         0, SQLITE_DYNAMIC);
  }
#endif
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
  else if( op==TK_FUNCTION && pCtx!=0 ){
    rc = valueFromFunction(db, pExpr, enc, affinity, &pVal, pCtx);
  }
#endif
  else if( op==TK_TRUEFALSE ){
    assert( !ExprHasProperty(pExpr, EP_IntValue) );
     pVal = valueNew(db, pCtx);
     pVal->flags = MEM_Int;
     pVal->u.i = pExpr->u.zToken[4]==0;
    pVal = valueNew(db, pCtx);
    if( pVal ){
      pVal->flags = MEM_Int;
      pVal->u.i = pExpr->u.zToken[4]==0;
    }
  }

  *ppVal = pVal;
  return rc;

no_mem:
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  if( pCtx==0 || pCtx->pParse->nErr==0 )
#ifdef SQLITE_ENABLE_STAT4
  if( pCtx==0 || NEVER(pCtx->pParse->nErr==0) )
#endif
    sqlite3OomFault(db);
  sqlite3DbFree(db, zVal);
  assert( *ppVal==0 );
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
  if( pCtx==0 ) sqlite3ValueFree(pVal);
#else
  assert( pCtx==0 ); sqlite3ValueFree(pVal);
#endif
  return SQLITE_NOMEM_BKPT;
}

/*
** Create a new sqlite3_value object, containing the value of pExpr.
**
** This only works for very simple expressions that consist of one constant
** token (i.e. "5", "5.1", "'a string'"). If the expression can
** be converted directly into a value, then the value is allocated and
** a pointer written to *ppVal. The caller is responsible for deallocating
** the value by passing it to sqlite3ValueFree() later on. If the expression
** cannot be converted to a value, then *ppVal is set to NULL.
*/
int sqlite3ValueFromExpr(
  sqlite3 *db,              /* The database connection */
  Expr *pExpr,              /* The expression to evaluate */
  const Expr *pExpr,        /* The expression to evaluate */
  u8 enc,                   /* Encoding to use */
  u8 affinity,              /* Affinity to use */
  sqlite3_value **ppVal     /* Write the new value here */
){
  return pExpr ? valueFromExpr(db, pExpr, enc, affinity, ppVal, 0) : 0;
}

#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
/*
** The implementation of the sqlite_record() function. This function accepts
** a single argument of any type. The return value is a formatted database 
** record (a blob) containing the argument value.
**
** This is used to convert the value stored in the 'sample' column of the
** sqlite_stat3 table to the record format SQLite uses internally.
*/
static void recordFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const int file_format = 1;
  u32 iSerial;                    /* Serial type */
  int nSerial;                    /* Bytes of space for iSerial as varint */
  u32 nVal;                       /* Bytes of space required for argv[0] */
  int nRet;
  sqlite3 *db;
  u8 *aRet;

  UNUSED_PARAMETER( argc );
  iSerial = sqlite3VdbeSerialType(argv[0], file_format, &nVal);
  nSerial = sqlite3VarintLen(iSerial);
  db = sqlite3_context_db_handle(context);

  nRet = 1 + nSerial + nVal;
  aRet = sqlite3DbMallocRawNN(db, nRet);
  if( aRet==0 ){
    sqlite3_result_error_nomem(context);
  }else{
    aRet[0] = nSerial+1;
    putVarint32(&aRet[1], iSerial);
    sqlite3VdbeSerialPut(&aRet[1+nSerial], argv[0], iSerial);
    sqlite3_result_blob(context, aRet, nRet, SQLITE_TRANSIENT);
    sqlite3DbFreeNN(db, aRet);
  }
}

/*
** Register built-in functions used to help read ANALYZE data.
*/
void sqlite3AnalyzeFunctions(void){
  static FuncDef aAnalyzeTableFuncs[] = {
    FUNCTION(sqlite_record,   1, 0, 0, recordFunc),
  };
  sqlite3InsertBuiltinFuncs(aAnalyzeTableFuncs, ArraySize(aAnalyzeTableFuncs));
}

/*
** Attempt to extract a value from pExpr and use it to construct *ppVal.
**
** If pAlloc is not NULL, then an UnpackedRecord object is created for
** pAlloc if one does not exist and the new value is added to the
** UnpackedRecord object.
**
1869
1870
1871
1872
1873
1874
1875



1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990







+
+
+











  return valueToText(pVal, enc)!=0 ? pVal->n : 0;
}
int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){
  Mem *p = (Mem*)pVal;
  assert( (p->flags & MEM_Null)==0 || (p->flags & (MEM_Str|MEM_Blob))==0 );
  if( (p->flags & MEM_Str)!=0 && pVal->enc==enc ){
    return p->n;
  }
  if( (p->flags & MEM_Str)!=0 && enc!=SQLITE_UTF8 && pVal->enc!=SQLITE_UTF8 ){
    return p->n;
  }
  if( (p->flags & MEM_Blob)!=0 ){
    if( p->flags & MEM_Zero ){
      return p->n + p->u.nZero;
    }else{
      return p->n;
    }
  }
  if( p->flags & MEM_Null ) return 0;
  return valueBytes(pVal, enc);
}

Changes to src/vdbesort.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







-
+







    ** In this case, allocate space at p->aAlloc[] to copy the requested
    ** range into. Then return a copy of pointer p->aAlloc to the caller.  */
    int nRem;                     /* Bytes remaining to copy */

    /* Extend the p->aAlloc[] allocation if required. */
    if( p->nAlloc<nByte ){
      u8 *aNew;
      int nNew = MAX(128, p->nAlloc*2);
      sqlite3_int64 nNew = MAX(128, 2*(sqlite3_int64)p->nAlloc);
      while( nByte>nNew ) nNew = nNew*2;
      aNew = sqlite3Realloc(p->aAlloc, nNew);
      if( !aNew ) return SQLITE_NOMEM_BKPT;
      p->nAlloc = nNew;
      p->aAlloc = aNew;
    }

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
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







-
-
+
+












+
-
+







  const u8 * const v1 = &p1[ p1[0] ];   /* Pointer to value 1 */
  const u8 * const v2 = &p2[ p2[0] ];   /* Pointer to value 2 */

  int n1;
  int n2;
  int res;

  getVarint32(&p1[1], n1);
  getVarint32(&p2[1], n2);
  getVarint32NR(&p1[1], n1);
  getVarint32NR(&p2[1], n2);
  res = memcmp(v1, v2, (MIN(n1, n2) - 13)/2);
  if( res==0 ){
    res = n1 - n2;
  }

  if( res==0 ){
    if( pTask->pSorter->pKeyInfo->nKeyField>1 ){
      res = vdbeSorterCompareTail(
          pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2
      );
    }
  }else{
    assert( !(pTask->pSorter->pKeyInfo->aSortFlags[0]&KEYINFO_ORDER_BIGNULL) );
    if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){
    if( pTask->pSorter->pKeyInfo->aSortFlags[0] ){
      res = res * -1;
    }
  }

  return res;
}

893
894
895
896
897
898
899
900


901
902
903
904
905
906
907
894
895
896
897
898
899
900

901
902
903
904
905
906
907
908
909







-
+
+








  if( res==0 ){
    if( pTask->pSorter->pKeyInfo->nKeyField>1 ){
      res = vdbeSorterCompareTail(
          pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2
      );
    }
  }else if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){
  }else if( pTask->pSorter->pKeyInfo->aSortFlags[0] ){
    assert( !(pTask->pSorter->pKeyInfo->aSortFlags[0]&KEYINFO_ORDER_BIGNULL) );
    res = res * -1;
  }

  return res;
}

/*
954
955
956
957
958
959
960
961


962
963
964
965
966
967
968
969
970

971
972
973
974
975
976

977


978
979
980
981
982
983
984
956
957
958
959
960
961
962

963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981

982
983
984
985
986
987
988
989
990







-
+
+









+






+
-
+
+







  ** to exceed the maximum merge count */
#if SQLITE_MAX_WORKER_THREADS>=SORTER_MAX_MERGE_COUNT
  if( nWorker>=SORTER_MAX_MERGE_COUNT ){
    nWorker = SORTER_MAX_MERGE_COUNT-1;
  }
#endif

  assert( pCsr->pKeyInfo && pCsr->pBtx==0 );
  assert( pCsr->pKeyInfo );
  assert( !pCsr->isEphemeral );
  assert( pCsr->eCurType==CURTYPE_SORTER );
  szKeyInfo = sizeof(KeyInfo) + (pCsr->pKeyInfo->nKeyField-1)*sizeof(CollSeq*);
  sz = sizeof(VdbeSorter) + nWorker * sizeof(SortSubtask);

  pSorter = (VdbeSorter*)sqlite3DbMallocZero(db, sz + szKeyInfo);
  pCsr->uc.pSorter = pSorter;
  if( pSorter==0 ){
    rc = SQLITE_NOMEM_BKPT;
  }else{
    Btree *pBt = db->aDb[0].pBt;
    pSorter->pKeyInfo = pKeyInfo = (KeyInfo*)((u8*)pSorter + sz);
    memcpy(pKeyInfo, pCsr->pKeyInfo, szKeyInfo);
    pKeyInfo->db = 0;
    if( nField && nWorker==0 ){
      pKeyInfo->nKeyField = nField;
    }
    sqlite3BtreeEnter(pBt);
    pSorter->pgsz = pgsz = sqlite3BtreeGetPageSize(db->aDb[0].pBt);
    pSorter->pgsz = pgsz = sqlite3BtreeGetPageSize(pBt);
    sqlite3BtreeLeave(pBt);
    pSorter->nTask = nWorker + 1;
    pSorter->iPrev = (u8)(nWorker - 1);
    pSorter->bUseThreads = (pSorter->nTask>1);
    pSorter->db = db;
    for(i=0; i<pSorter->nTask; i++){
      SortSubtask *pTask = &pSorter->aTask[i];
      pTask->pSorter = pSorter;
1008
1009
1010
1011
1012
1013
1014

1015
1016
1017
1018
1019
1020
1021
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028







+







        pSorter->list.aMemory = (u8*)sqlite3Malloc(pgsz);
        if( !pSorter->list.aMemory ) rc = SQLITE_NOMEM_BKPT;
      }
    }

    if( pKeyInfo->nAllField<13 
     && (pKeyInfo->aColl[0]==0 || pKeyInfo->aColl[0]==db->pDfltColl)
     && (pKeyInfo->aSortFlags[0] & KEYINFO_ORDER_BIGNULL)==0
    ){
      pSorter->typeMask = SORTER_TYPE_INTEGER | SORTER_TYPE_TEXT;
    }
  }

  return rc;
}
1063
1064
1065
1066
1067
1068
1069
1070
1071



1072
1073
1074
1075
1076
1077
1078
1070
1071
1072
1073
1074
1075
1076


1077
1078
1079
1080
1081
1082
1083
1084
1085
1086







-
-
+
+
+







static void vdbeSorterWorkDebug(SortSubtask *pTask, const char *zEvent){
  i64 t;
  int iTask = (pTask - pTask->pSorter->aTask);
  sqlite3OsCurrentTimeInt64(pTask->pSorter->db->pVfs, &t);
  fprintf(stderr, "%lld:%d %s\n", t, iTask, zEvent);
}
static void vdbeSorterRewindDebug(const char *zEvent){
  i64 t;
  sqlite3OsCurrentTimeInt64(sqlite3_vfs_find(0), &t);
  i64 t = 0;
  sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
  if( ALWAYS(pVfs) ) sqlite3OsCurrentTimeInt64(pVfs, &t);
  fprintf(stderr, "%lld:X %s\n", t, zEvent);
}
static void vdbeSorterPopulateDebug(
  SortSubtask *pTask,
  const char *zEvent
){
  i64 t;
1278
1279
1280
1281
1282
1283
1284
1285

1286
1287
1288
1289
1290
1291
1292
1286
1287
1288
1289
1290
1291
1292

1293
1294
1295
1296
1297
1298
1299
1300







-
+







static void vdbeSorterExtendFile(sqlite3 *db, sqlite3_file *pFd, i64 nByte){
  if( nByte<=(i64)(db->nMaxSorterMmap) && pFd->pMethods->iVersion>=3 ){
    void *p = 0;
    int chunksize = 4*1024;
    sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_CHUNK_SIZE, &chunksize);
    sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_SIZE_HINT, &nByte);
    sqlite3OsFetch(pFd, 0, (int)nByte, &p);
    sqlite3OsUnfetch(pFd, 0, p);
    if( p ) sqlite3OsUnfetch(pFd, 0, p);
  }
}
#else
# define vdbeSorterExtendFile(x,y,z)
#endif

/*
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
1397
1398
1399
1400
1401
1402
1403

1404
1405
1406
1407
1408
1409
1410
1411
1412

1413




1414
1415
1416
1417
1418
1419
1420







-


+






-
+
-
-
-
-







/*
** Sort the linked list of records headed at pTask->pList. Return 
** SQLITE_OK if successful, or an SQLite error code (i.e. SQLITE_NOMEM) if 
** an error occurs.
*/
static int vdbeSorterSort(SortSubtask *pTask, SorterList *pList){
  int i;
  SorterRecord **aSlot;
  SorterRecord *p;
  int rc;
  SorterRecord *aSlot[64];

  rc = vdbeSortAllocUnpacked(pTask);
  if( rc!=SQLITE_OK ) return rc;

  p = pList->pList;
  pTask->xCompare = vdbeSorterGetCompare(pTask->pSorter);

  memset(aSlot, 0, sizeof(aSlot));
  aSlot = (SorterRecord **)sqlite3MallocZero(64 * sizeof(SorterRecord *));
  if( !aSlot ){
    return SQLITE_NOMEM_BKPT;
  }

  while( p ){
    SorterRecord *pNext;
    if( pList->aMemory ){
      if( (u8*)p==pList->aMemory ){
        pNext = 0;
      }else{
1427
1428
1429
1430
1431
1432
1433
1434

1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1431
1432
1433
1434
1435
1436
1437

1438
1439
1440
1441
1442
1443

1444
1445
1446
1447
1448
1449
1450







-
+





-







      aSlot[i] = 0;
    }
    aSlot[i] = p;
    p = pNext;
  }

  p = 0;
  for(i=0; i<64; i++){
  for(i=0; i<ArraySize(aSlot); i++){
    if( aSlot[i]==0 ) continue;
    p = p ? vdbeSorterMerge(pTask, p, aSlot[i]) : aSlot[i];
  }
  pList->pList = p;

  sqlite3_free(aSlot);
  assert( pTask->pUnpacked->errCode==SQLITE_OK 
       || pTask->pUnpacked->errCode==SQLITE_NOMEM 
  );
  return pTask->pUnpacked->errCode;
}

/*
1724
1725
1726
1727
1728
1729
1730
1731
1732


1733

1734
1735
1736
1737


1738
1739
1740
1741
1742
1743
1744
1727
1728
1729
1730
1731
1732
1733


1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750







-
-
+
+

+




+
+








  if( rc==SQLITE_OK ){
    if( i==nWorker ){
      /* Use the foreground thread for this operation */
      rc = vdbeSorterListToPMA(&pSorter->aTask[nWorker], &pSorter->list);
    }else{
      /* Launch a background thread for this operation */
      u8 *aMem = pTask->list.aMemory;
      void *pCtx = (void*)pTask;
      u8 *aMem;
      void *pCtx;

      assert( pTask!=0 );
      assert( pTask->pThread==0 && pTask->bDone==0 );
      assert( pTask->list.pList==0 );
      assert( pTask->list.aMemory==0 || pSorter->list.aMemory!=0 );

      aMem = pTask->list.aMemory;
      pCtx = (void*)pTask;
      pSorter->iPrev = (u8)(pTask - pSorter->aTask);
      pTask->list = pSorter->list;
      pSorter->list.pList = 0;
      pSorter->list.szPMA = 0;
      if( aMem ){
        pSorter->list.aMemory = aMem;
        pSorter->nMemory = sqlite3MallocSize(aMem);
1768
1769
1770
1771
1772
1773
1774
1775

1776
1777
1778
1779
1780
1781
1782
1774
1775
1776
1777
1778
1779
1780

1781
1782
1783
1784
1785
1786
1787
1788







-
+







  int bFlush;                     /* True to flush contents of memory to PMA */
  int nReq;                       /* Bytes of memory required */
  int nPMA;                       /* Bytes of PMA space required */
  int t;                          /* serial type of first record field */

  assert( pCsr->eCurType==CURTYPE_SORTER );
  pSorter = pCsr->uc.pSorter;
  getVarint32((const u8*)&pVal->z[1], t);
  getVarint32NR((const u8*)&pVal->z[1], t);
  if( t>0 && t<10 && t!=7 ){
    pSorter->typeMask &= SORTER_TYPE_INTEGER;
  }else if( t>10 && (t & 0x01) ){
    pSorter->typeMask &= SORTER_TYPE_TEXT;
  }else{
    pSorter->typeMask = 0;
  }
1824
1825
1826
1827
1828
1829
1830



1831

1832

1833
1834
1835
1836
1837
1838

1839


1840
1841
1842
1843
1844
1845
1846
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







+
+
+
-
+
-
+



-


+
-
+
+







  }

  if( pSorter->list.aMemory ){
    int nMin = pSorter->iMemory + nReq;

    if( nMin>pSorter->nMemory ){
      u8 *aNew;
      sqlite3_int64 nNew = 2 * (sqlite3_int64)pSorter->nMemory;
      int iListOff = -1;
      if( pSorter->list.pList ){
      int iListOff = (u8*)pSorter->list.pList - pSorter->list.aMemory;
        iListOff = (u8*)pSorter->list.pList - pSorter->list.aMemory;
      int nNew = pSorter->nMemory * 2;
      }
      while( nNew < nMin ) nNew = nNew*2;
      if( nNew > pSorter->mxPmaSize ) nNew = pSorter->mxPmaSize;
      if( nNew < nMin ) nNew = nMin;

      aNew = sqlite3Realloc(pSorter->list.aMemory, nNew);
      if( !aNew ) return SQLITE_NOMEM_BKPT;
      if( iListOff>=0 ){
      pSorter->list.pList = (SorterRecord*)&aNew[iListOff];
        pSorter->list.pList = (SorterRecord*)&aNew[iListOff];
      }
      pSorter->list.aMemory = aNew;
      pSorter->nMemory = nNew;
    }

    pNew = (SorterRecord*)&pSorter->list.aMemory[pSorter->iMemory];
    pSorter->iMemory += ROUND8(nReq);
    if( pSorter->list.pList ){
1994
1995
1996
1997
1998
1999
2000

2001
2002
2003
2004
2005
2006
2007
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018







+







    pIncr->pTask = pTask;
    pIncr->mxSz = MAX(pTask->pSorter->mxKeysize+9,pTask->pSorter->mxPmaSize/2);
    pTask->file2.iEof += pIncr->mxSz;
  }else{
    vdbeMergeEngineFree(pMerger);
    rc = SQLITE_NOMEM_BKPT;
  }
  assert( *ppOut!=0 || rc!=SQLITE_OK );
  return rc;
}

#if SQLITE_MAX_WORKER_THREADS>0
/*
** Set the "use-threads" flag on object pIncr.
*/

Changes to src/vdbetrace.c.

80
81
82
83
84
85
86
87
88
89
90

91
92
93
94
95
96
97
98
80
81
82
83
84
85
86

87
88

89

90
91
92
93
94
95
96







-


-
+
-







  int nToken;              /* Length of the parameter token */
  int i;                   /* Loop counter */
  Mem *pVar;               /* Value of a host parameter */
  StrAccum out;            /* Accumulate the output here */
#ifndef SQLITE_OMIT_UTF16
  Mem utf8;                /* Used to convert UTF16 into UTF8 for display */
#endif
  char zBase[100];         /* Initial working space */

  db = p->db;
  sqlite3StrAccumInit(&out, 0, zBase, sizeof(zBase), 
  sqlite3StrAccumInit(&out, 0, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
                      db->aLimit[SQLITE_LIMIT_LENGTH]);
  if( db->nVdbeExec>1 ){
    while( *zRawSql ){
      const char *zStart = zRawSql;
      while( *(zRawSql++)!='\n' && *zRawSql );
      sqlite3_str_append(&out, "-- ", 3);
      assert( (zRawSql - zStart) > 0 );
      sqlite3_str_append(&out, zStart, (int)(zRawSql-zStart));
121
122
123
124
125
126
127
128

129
130
131
132
133

134
135
136
137
138
139
140
119
120
121
122
123
124
125

126
127
128
129
130

131
132
133
134
135
136
137
138







-
+




-
+







        testcase( zRawSql[0]=='$' );
        testcase( zRawSql[0]=='@' );
        testcase( zRawSql[0]=='#' );
        idx = sqlite3VdbeParameterIndex(p, zRawSql, nToken);
        assert( idx>0 );
      }
      zRawSql += nToken;
      nextIndex = idx + 1;
      nextIndex = MAX(idx + 1, nextIndex);
      assert( idx>0 && idx<=p->nVar );
      pVar = &p->aVar[idx-1];
      if( pVar->flags & MEM_Null ){
        sqlite3_str_append(&out, "NULL", 4);
      }else if( pVar->flags & MEM_Int ){
      }else if( pVar->flags & (MEM_Int|MEM_IntReal) ){
        sqlite3_str_appendf(&out, "%lld", pVar->u.i);
      }else if( pVar->flags & MEM_Real ){
        sqlite3_str_appendf(&out, "%!.15g", pVar->u.r);
      }else if( pVar->flags & MEM_Str ){
        int nOut;  /* Number of bytes of the string text to include in output */
#ifndef SQLITE_OMIT_UTF16
        u8 enc = ENC(db);

Added src/vdbevtab.c.













































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2020-03-23
**
** 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 virtual-tables for examining the bytecode content
** of a prepared statement.
*/
#include "sqliteInt.h"
#if defined(SQLITE_ENABLE_BYTECODE_VTAB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
#include "vdbeInt.h"

/* An instance of the bytecode() table-valued function.
*/
typedef struct bytecodevtab bytecodevtab;
struct bytecodevtab {
  sqlite3_vtab base;     /* Base class - must be first */
  sqlite3 *db;           /* Database connection */
  int bTablesUsed;       /* 2 for tables_used().  0 for bytecode(). */
};

/* A cursor for scanning through the bytecode
*/
typedef struct bytecodevtab_cursor bytecodevtab_cursor;
struct bytecodevtab_cursor {
  sqlite3_vtab_cursor base;  /* Base class - must be first */
  sqlite3_stmt *pStmt;       /* The statement whose bytecode is displayed */
  int iRowid;                /* The rowid of the output table */
  int iAddr;                 /* Address */
  int needFinalize;          /* Cursors owns pStmt and must finalize it */
  int showSubprograms;       /* Provide a listing of subprograms */
  Op *aOp;                   /* Operand array */
  char *zP4;                 /* Rendered P4 value */
  const char *zType;         /* tables_used.type */
  const char *zSchema;       /* tables_used.schema */
  const char *zName;         /* tables_used.name */
  Mem sub;                   /* Subprograms */
};

/*
** Create a new bytecode() table-valued function.
*/
static int bytecodevtabConnect(
  sqlite3 *db,
  void *pAux,
  int argc, const char *const*argv,
  sqlite3_vtab **ppVtab,
  char **pzErr
){
  bytecodevtab *pNew;
  int rc;
  int isTabUsed = pAux!=0;
  const char *azSchema[2] = {
    /* bytecode() schema */
    "CREATE TABLE x("
      "addr INT,"
      "opcode TEXT,"
      "p1 INT,"
      "p2 INT,"
      "p3 INT,"
      "p4 TEXT,"
      "p5 INT,"
      "comment TEXT,"
      "subprog TEXT," 
      "stmt HIDDEN"
    ");",

    /* Tables_used() schema */
    "CREATE TABLE x("
      "type TEXT,"
      "schema TEXT,"
      "name TEXT,"
      "wr INT,"
      "subprog TEXT," 
      "stmt HIDDEN"
   ");"
  };

  (void)argc;
  (void)argv;
  (void)pzErr;
  rc = sqlite3_declare_vtab(db, azSchema[isTabUsed]);
  if( rc==SQLITE_OK ){
    pNew = sqlite3_malloc( sizeof(*pNew) );
    *ppVtab = (sqlite3_vtab*)pNew;
    if( pNew==0 ) return SQLITE_NOMEM;
    memset(pNew, 0, sizeof(*pNew));
    pNew->db = db;
    pNew->bTablesUsed = isTabUsed*2;
  }
  return rc;
}

/*
** This method is the destructor for bytecodevtab objects.
*/
static int bytecodevtabDisconnect(sqlite3_vtab *pVtab){
  bytecodevtab *p = (bytecodevtab*)pVtab;
  sqlite3_free(p);
  return SQLITE_OK;
}

/*
** Constructor for a new bytecodevtab_cursor object.
*/
static int bytecodevtabOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
  bytecodevtab *pVTab = (bytecodevtab*)p;
  bytecodevtab_cursor *pCur;
  pCur = sqlite3_malloc( sizeof(*pCur) );
  if( pCur==0 ) return SQLITE_NOMEM;
  memset(pCur, 0, sizeof(*pCur));
  sqlite3VdbeMemInit(&pCur->sub, pVTab->db, 1);
  *ppCursor = &pCur->base;
  return SQLITE_OK;
}

/*
** Clear all internal content from a bytecodevtab cursor.
*/
static void bytecodevtabCursorClear(bytecodevtab_cursor *pCur){
  sqlite3_free(pCur->zP4);
  pCur->zP4 = 0;
  sqlite3VdbeMemRelease(&pCur->sub);
  sqlite3VdbeMemSetNull(&pCur->sub);
  if( pCur->needFinalize ){
    sqlite3_finalize(pCur->pStmt);
  }
  pCur->pStmt = 0;
  pCur->needFinalize = 0;
  pCur->zType = 0;
  pCur->zSchema = 0;
  pCur->zName = 0;
}

/*
** Destructor for a bytecodevtab_cursor.
*/
static int bytecodevtabClose(sqlite3_vtab_cursor *cur){
  bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
  bytecodevtabCursorClear(pCur);
  sqlite3_free(pCur);
  return SQLITE_OK;
}


/*
** Advance a bytecodevtab_cursor to its next row of output.
*/
static int bytecodevtabNext(sqlite3_vtab_cursor *cur){
  bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
  bytecodevtab *pTab = (bytecodevtab*)cur->pVtab;
  int rc;
  if( pCur->zP4 ){
    sqlite3_free(pCur->zP4);
    pCur->zP4 = 0;
  }
  if( pCur->zName ){
    pCur->zName = 0;
    pCur->zType = 0;
    pCur->zSchema = 0;
  }
  rc = sqlite3VdbeNextOpcode(
           (Vdbe*)pCur->pStmt, 
           pCur->showSubprograms ? &pCur->sub : 0,
           pTab->bTablesUsed,
           &pCur->iRowid,
           &pCur->iAddr,
           &pCur->aOp);
  if( rc!=SQLITE_OK ){
    sqlite3VdbeMemSetNull(&pCur->sub);
    pCur->aOp = 0;
  }
  return SQLITE_OK;
}

/*
** Return TRUE if the cursor has been moved off of the last
** row of output.
*/
static int bytecodevtabEof(sqlite3_vtab_cursor *cur){
  bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
  return pCur->aOp==0;
}

/*
** Return values of columns for the row at which the bytecodevtab_cursor
** is currently pointing.
*/
static int bytecodevtabColumn(
  sqlite3_vtab_cursor *cur,   /* The cursor */
  sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
  int i                       /* Which column to return */
){
  bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
  bytecodevtab *pVTab = (bytecodevtab*)cur->pVtab;
  Op *pOp = pCur->aOp + pCur->iAddr;
  if( pVTab->bTablesUsed ){
    if( i==4 ){
      i = 8;
    }else{
      if( i<=2 && pCur->zType==0 ){
        Schema *pSchema;
        HashElem *k;
        int iDb = pOp->p3;
        Pgno iRoot = (Pgno)pOp->p2;
        sqlite3 *db = pVTab->db;
        pSchema = db->aDb[iDb].pSchema;
        pCur->zSchema = db->aDb[iDb].zDbSName;
        for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){
          Table *pTab = (Table*)sqliteHashData(k);
          if( !IsVirtual(pTab) && pTab->tnum==iRoot ){
            pCur->zName = pTab->zName;
            pCur->zType = "table";
            break;
          }
        }
        if( pCur->zName==0 ){
          for(k=sqliteHashFirst(&pSchema->idxHash); k; k=sqliteHashNext(k)){
            Index *pIdx = (Index*)sqliteHashData(k);
            if( pIdx->tnum==iRoot ){
              pCur->zName = pIdx->zName;
              pCur->zType = "index";
            }
          }
        }
      }
      i += 10;
    }
  }
  switch( i ){
    case 0:   /* addr */
      sqlite3_result_int(ctx, pCur->iAddr);
      break;
    case 1:   /* opcode */
      sqlite3_result_text(ctx, (char*)sqlite3OpcodeName(pOp->opcode),
                          -1, SQLITE_STATIC);
      break;
    case 2:   /* p1 */
      sqlite3_result_int(ctx, pOp->p1);
      break;
    case 3:   /* p2 */
      sqlite3_result_int(ctx, pOp->p2);
      break;
    case 4:   /* p3 */
      sqlite3_result_int(ctx, pOp->p3);
      break;
    case 5:   /* p4 */
    case 7:   /* comment */
      if( pCur->zP4==0 ){
        pCur->zP4 = sqlite3VdbeDisplayP4(pVTab->db, pOp);
      }
      if( i==5 ){
        sqlite3_result_text(ctx, pCur->zP4, -1, SQLITE_STATIC);
      }else{
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
        char *zCom = sqlite3VdbeDisplayComment(pVTab->db, pOp, pCur->zP4);
        sqlite3_result_text(ctx, zCom, -1, sqlite3_free);
#endif
      }
      break;
    case 6:     /* p5 */
      sqlite3_result_int(ctx, pOp->p5);
      break;
    case 8: {   /* subprog */
      Op *aOp = pCur->aOp;
      assert( aOp[0].opcode==OP_Init );
      assert( aOp[0].p4.z==0 || strncmp(aOp[0].p4.z,"-" "- ",3)==0 );
      if( pCur->iRowid==pCur->iAddr+1 ){
        break;  /* Result is NULL for the main program */
      }else if( aOp[0].p4.z!=0 ){
         sqlite3_result_text(ctx, aOp[0].p4.z+3, -1, SQLITE_STATIC);
      }else{
         sqlite3_result_text(ctx, "(FK)", 4, SQLITE_STATIC);
      }
      break;
    }
    case 10:  /* tables_used.type */
      sqlite3_result_text(ctx, pCur->zType, -1, SQLITE_STATIC);
      break;
    case 11:  /* tables_used.schema */
      sqlite3_result_text(ctx, pCur->zSchema, -1, SQLITE_STATIC);
      break;
    case 12:  /* tables_used.name */
      sqlite3_result_text(ctx, pCur->zName, -1, SQLITE_STATIC);
      break;
    case 13:  /* tables_used.wr */
      sqlite3_result_int(ctx, pOp->opcode==OP_OpenWrite);
      break;
  }
  return SQLITE_OK;
}

/*
** Return the rowid for the current row.  In this implementation, the
** rowid is the same as the output value.
*/
static int bytecodevtabRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
  bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
  *pRowid = pCur->iRowid;
  return SQLITE_OK;
}

/*
** Initialize a cursor.
**
**    idxNum==0     means show all subprograms
**    idxNum==1     means show only the main bytecode and omit subprograms.
*/
static int bytecodevtabFilter(
  sqlite3_vtab_cursor *pVtabCursor, 
  int idxNum, const char *idxStr,
  int argc, sqlite3_value **argv
){
  bytecodevtab_cursor *pCur = (bytecodevtab_cursor *)pVtabCursor;
  bytecodevtab *pVTab = (bytecodevtab *)pVtabCursor->pVtab;
  int rc = SQLITE_OK;
  (void)idxStr;

  bytecodevtabCursorClear(pCur);
  pCur->iRowid = 0;
  pCur->iAddr = 0;
  pCur->showSubprograms = idxNum==0;
  assert( argc==1 );
  if( sqlite3_value_type(argv[0])==SQLITE_TEXT ){
    const char *zSql = (const char*)sqlite3_value_text(argv[0]);
    if( zSql==0 ){
      rc = SQLITE_NOMEM;
    }else{
      rc = sqlite3_prepare_v2(pVTab->db, zSql, -1, &pCur->pStmt, 0);
      pCur->needFinalize = 1;
    }
  }else{
    pCur->pStmt = (sqlite3_stmt*)sqlite3_value_pointer(argv[0],"stmt-pointer");
  }
  if( pCur->pStmt==0 ){
    pVTab->base.zErrMsg = sqlite3_mprintf(
       "argument to %s() is not a valid SQL statement",
       pVTab->bTablesUsed ? "tables_used" : "bytecode"
    );
    rc = SQLITE_ERROR;
  }else{
    bytecodevtabNext(pVtabCursor);
  }
  return rc;
}

/*
** We must have a single stmt=? constraint that will be passed through
** into the xFilter method.  If there is no valid stmt=? constraint,
** then return an SQLITE_CONSTRAINT error.
*/
static int bytecodevtabBestIndex(
  sqlite3_vtab *tab,
  sqlite3_index_info *pIdxInfo
){
  int i;
  int rc = SQLITE_CONSTRAINT;
  struct sqlite3_index_constraint *p;
  bytecodevtab *pVTab = (bytecodevtab*)tab;
  int iBaseCol = pVTab->bTablesUsed ? 4 : 8;
  pIdxInfo->estimatedCost = (double)100;
  pIdxInfo->estimatedRows = 100;
  pIdxInfo->idxNum = 0;
  for(i=0, p=pIdxInfo->aConstraint; i<pIdxInfo->nConstraint; i++, p++){
    if( p->usable==0 ) continue;
    if( p->op==SQLITE_INDEX_CONSTRAINT_EQ && p->iColumn==iBaseCol+1 ){
      rc = SQLITE_OK;
      pIdxInfo->aConstraintUsage[i].omit = 1;
      pIdxInfo->aConstraintUsage[i].argvIndex = 1;
    }
    if( p->op==SQLITE_INDEX_CONSTRAINT_ISNULL && p->iColumn==iBaseCol ){
      pIdxInfo->aConstraintUsage[i].omit = 1;
      pIdxInfo->idxNum = 1;
    }
  }
  return rc;
}

/*
** This following structure defines all the methods for the 
** virtual table.
*/
static sqlite3_module bytecodevtabModule = {
  /* iVersion    */ 0,
  /* xCreate     */ 0,
  /* xConnect    */ bytecodevtabConnect,
  /* xBestIndex  */ bytecodevtabBestIndex,
  /* xDisconnect */ bytecodevtabDisconnect,
  /* xDestroy    */ 0,
  /* xOpen       */ bytecodevtabOpen,
  /* xClose      */ bytecodevtabClose,
  /* xFilter     */ bytecodevtabFilter,
  /* xNext       */ bytecodevtabNext,
  /* xEof        */ bytecodevtabEof,
  /* xColumn     */ bytecodevtabColumn,
  /* xRowid      */ bytecodevtabRowid,
  /* xUpdate     */ 0,
  /* xBegin      */ 0,
  /* xSync       */ 0,
  /* xCommit     */ 0,
  /* xRollback   */ 0,
  /* xFindMethod */ 0,
  /* xRename     */ 0,
  /* xSavepoint  */ 0,
  /* xRelease    */ 0,
  /* xRollbackTo */ 0,
  /* xShadowName */ 0
};


int sqlite3VdbeBytecodeVtabInit(sqlite3 *db){
  int rc;
  rc = sqlite3_create_module(db, "bytecode", &bytecodevtabModule, 0);
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_module(db, "tables_used", &bytecodevtabModule, &db);
  }
  return rc;
}
#elif defined(SQLITE_ENABLE_BYTECODE_VTAB)
int sqlite3VdbeBytecodeVtabInit(sqlite3 *db){ return SQLITE_OK; }
#endif /* SQLITE_ENABLE_BYTECODE_VTAB */

Changes to src/vtab.c.

28
29
30
31
32
33
34



35
36
37
38
39
40
41
42
43






44
45
46
47
48





49
50


51
52
53
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
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







+
+
+









+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
+
+






+
+
-
-
-
+
+
+



+
+
+




















-
-
-
-
+
-







  int bDeclared;      /* True after sqlite3_declare_vtab() is called */
};

/*
** Construct and install a Module object for a virtual table.  When this
** routine is called, it is guaranteed that all appropriate locks are held
** and the module is not already part of the connection.
**
** If there already exists a module with zName, replace it with the new one.
** If pModule==0, then delete the module zName if it exists.
*/
Module *sqlite3VtabCreateModule(
  sqlite3 *db,                    /* Database in which module is registered */
  const char *zName,              /* Name assigned to this module */
  const sqlite3_module *pModule,  /* The definition of the module */
  void *pAux,                     /* Context pointer for xCreate/xConnect */
  void (*xDestroy)(void *)        /* Module destructor function */
){
  Module *pMod;
  Module *pDel;
  char *zCopy;
  if( pModule==0 ){
    zCopy = (char*)zName;
    pMod = 0;
  }else{
  int nName = sqlite3Strlen30(zName);
  pMod = (Module *)sqlite3Malloc(sizeof(Module) + nName + 1);
  if( pMod==0 ){
    sqlite3OomFault(db);
  }else{
    int nName = sqlite3Strlen30(zName);
    pMod = (Module *)sqlite3Malloc(sizeof(Module) + nName + 1);
    if( pMod==0 ){
      sqlite3OomFault(db);
      return 0;
    Module *pDel;
    char *zCopy = (char *)(&pMod[1]);
    }
    zCopy = (char *)(&pMod[1]);
    memcpy(zCopy, zName, nName+1);
    pMod->zName = zCopy;
    pMod->pModule = pModule;
    pMod->pAux = pAux;
    pMod->xDestroy = xDestroy;
    pMod->pEpoTab = 0;
    pMod->nRefModule = 1;
  }
    pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod);
    assert( pDel==0 || pDel==pMod );
    if( pDel ){
  pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod);
  if( pDel ){
    if( pDel==pMod ){
      sqlite3OomFault(db);
      sqlite3DbFree(db, pDel);
      pMod = 0;
    }else{
      sqlite3VtabEponymousTableClear(db, pDel);
      sqlite3VtabModuleUnref(db, pDel);
    }
  }
  return pMod;
}

/*
** The actual function that does the work of creating a new module.
** This function implements the sqlite3_create_module() and
** sqlite3_create_module_v2() interfaces.
*/
static int createModule(
  sqlite3 *db,                    /* Database in which module is registered */
  const char *zName,              /* Name assigned to this module */
  const sqlite3_module *pModule,  /* The definition of the module */
  void *pAux,                     /* Context pointer for xCreate/xConnect */
  void (*xDestroy)(void *)        /* Module destructor function */
){
  int rc = SQLITE_OK;

  sqlite3_mutex_enter(db->mutex);
  if( sqlite3HashFind(&db->aModule, zName) ){
    rc = SQLITE_MISUSE_BKPT;
  }else{
    (void)sqlite3VtabCreateModule(db, zName, pModule, pAux, xDestroy);
  (void)sqlite3VtabCreateModule(db, zName, pModule, pAux, xDestroy);
  }
  rc = sqlite3ApiExit(db, rc);
  if( rc!=SQLITE_OK && xDestroy ) xDestroy(pAux);
  sqlite3_mutex_leave(db->mutex);
  return rc;
}


118
119
120
121
122
123
124






































125
126
127
128
129
130
131
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  void (*xDestroy)(void *)        /* Module destructor function */
){
#ifdef SQLITE_ENABLE_API_ARMOR
  if( !sqlite3SafetyCheckOk(db) || zName==0 ) return SQLITE_MISUSE_BKPT;
#endif
  return createModule(db, zName, pModule, pAux, xDestroy);
}

/*
** External API to drop all virtual-table modules, except those named
** on the azNames list.
*/
int sqlite3_drop_modules(sqlite3 *db, const char** azNames){
  HashElem *pThis, *pNext;
#ifdef SQLITE_ENABLE_API_ARMOR
  if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
#endif
  for(pThis=sqliteHashFirst(&db->aModule); pThis; pThis=pNext){
    Module *pMod = (Module*)sqliteHashData(pThis);
    pNext = sqliteHashNext(pThis);
    if( azNames ){
      int ii;
      for(ii=0; azNames[ii]!=0 && strcmp(azNames[ii],pMod->zName)!=0; ii++){}
      if( azNames[ii]!=0 ) continue;
    }
    createModule(db, pMod->zName, 0, 0, 0);
  }
  return SQLITE_OK;
}

/*
** Decrement the reference count on a Module object.  Destroy the
** module when the reference count reaches zero.
*/
void sqlite3VtabModuleUnref(sqlite3 *db, Module *pMod){
  assert( pMod->nRefModule>0 );
  pMod->nRefModule--;
  if( pMod->nRefModule==0 ){
    if( pMod->xDestroy ){
      pMod->xDestroy(pMod->pAux);
    }
    assert( pMod->pEpoTab==0 );
    sqlite3DbFree(db, pMod);
  }
}

/*
** Lock the virtual table so that it cannot be disconnected.
** Locks nest.  Every lock should have a corresponding unlock.
** If an unlock is omitted, resources leaks will occur.  
**
** If a disconnect is attempted while a virtual table is locked,
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
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







-
+












-
+
+







+






-
+


-
+



-
-
+
+
+
+
+





-
+









-
+







** pTab is a pointer to a Table structure representing a virtual-table.
** Return a pointer to the VTable object used by connection db to access 
** this virtual-table, if one has been created, or NULL otherwise.
*/
VTable *sqlite3GetVTable(sqlite3 *db, Table *pTab){
  VTable *pVtab;
  assert( IsVirtual(pTab) );
  for(pVtab=pTab->pVTable; pVtab && pVtab->db!=db; pVtab=pVtab->pNext);
  for(pVtab=pTab->u.vtab.p; pVtab && pVtab->db!=db; pVtab=pVtab->pNext);
  return pVtab;
}

/*
** Decrement the ref-count on a virtual table object. When the ref-count
** reaches zero, call the xDisconnect() method to delete the object.
*/
void sqlite3VtabUnlock(VTable *pVTab){
  sqlite3 *db = pVTab->db;

  assert( db );
  assert( pVTab->nRef>0 );
  assert( db->magic==SQLITE_MAGIC_OPEN || db->magic==SQLITE_MAGIC_ZOMBIE );
  assert( db->eOpenState==SQLITE_STATE_OPEN
       || db->eOpenState==SQLITE_STATE_ZOMBIE );

  pVTab->nRef--;
  if( pVTab->nRef==0 ){
    sqlite3_vtab *p = pVTab->pVtab;
    if( p ){
      p->pModule->xDisconnect(p);
    }
    sqlite3VtabModuleUnref(pVTab->db, pVTab->pMod);
    sqlite3DbFree(db, pVTab);
  }
}

/*
** Table p is a virtual table. This function moves all elements in the
** p->pVTable list to the sqlite3.pDisconnect lists of their associated
** p->u.vtab.p list to the sqlite3.pDisconnect lists of their associated
** database connections to be disconnected at the next opportunity. 
** Except, if argument db is not NULL, then the entry associated with
** connection db is left in the p->pVTable list.
** connection db is left in the p->u.vtab.p list.
*/
static VTable *vtabDisconnectAll(sqlite3 *db, Table *p){
  VTable *pRet = 0;
  VTable *pVTable = p->pVTable;
  p->pVTable = 0;
  VTable *pVTable;

  assert( IsVirtual(p) );
  pVTable = p->u.vtab.p;
  p->u.vtab.p = 0;

  /* Assert that the mutex (if any) associated with the BtShared database 
  ** that contains table p is held by the caller. See header comments 
  ** above function sqlite3VtabUnlockList() for an explanation of why
  ** this makes it safe to access the sqlite3.pDisconnect list of any
  ** database connection that may have an entry in the p->pVTable list.
  ** database connection that may have an entry in the p->u.vtab.p list.
  */
  assert( db==0 || sqlite3SchemaMutexHeld(db, 0, p->pSchema) );

  while( pVTable ){
    sqlite3 *db2 = pVTable->db;
    VTable *pNext = pVTable->pNext;
    assert( db2 );
    if( db2==db ){
      pRet = pVTable;
      p->pVTable = pRet;
      p->u.vtab.p = pRet;
      pRet->pNext = 0;
    }else{
      pVTable->pNext = db2->pDisconnect;
      db2->pDisconnect = pVTable;
    }
    pVTable = pNext;
  }
219
220
221
222
223
224
225
226

227
228
229
230
231
232
233
272
273
274
275
276
277
278

279
280
281
282
283
284
285
286







-
+







void sqlite3VtabDisconnect(sqlite3 *db, Table *p){
  VTable **ppVTab;

  assert( IsVirtual(p) );
  assert( sqlite3BtreeHoldsAllMutexes(db) );
  assert( sqlite3_mutex_held(db->mutex) );

  for(ppVTab=&p->pVTable; *ppVTab; ppVTab=&(*ppVTab)->pNext){
  for(ppVTab=&p->u.vtab.p; *ppVTab; ppVTab=&(*ppVTab)->pNext){
    if( (*ppVTab)->db==db  ){
      VTable *pVTab = *ppVTab;
      *ppVTab = pVTab->pNext;
      sqlite3VtabUnlock(pVTab);
      break;
    }
  }
252
253
254
255
256
257
258
259
260
261
262
263
264

265
266
267
268
269
270
271
305
306
307
308
309
310
311

312
313
314
315
316
317
318
319
320
321
322
323
324







-





+







**      the database handle mutex is held.
**
** As a result, a sqlite3.pDisconnect cannot be accessed simultaneously 
** by multiple threads. It is thread-safe.
*/
void sqlite3VtabUnlockList(sqlite3 *db){
  VTable *p = db->pDisconnect;
  db->pDisconnect = 0;

  assert( sqlite3BtreeHoldsAllMutexes(db) );
  assert( sqlite3_mutex_held(db->mutex) );

  if( p ){
    db->pDisconnect = 0;
    sqlite3ExpirePreparedStatements(db, 0);
    do {
      VTable *pNext = p->pNext;
      sqlite3VtabUnlock(p);
      p = pNext;
    }while( p );
  }
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
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







+
+
-
-
+
+

-
-
+
+

-
+




-
+




-
-
+
+

+
+
+
+
+
+
+
-
+



-
+


-
+







** The reference count of the VTable structure associated with database 
** connection db is decremented immediately (which may lead to the 
** structure being xDisconnected and free). Any other VTable structures
** in the list are moved to the sqlite3.pDisconnect list of the associated 
** database connection.
*/
void sqlite3VtabClear(sqlite3 *db, Table *p){
  assert( IsVirtual(p) );
  assert( db!=0 );
  if( !db || db->pnBytesFreed==0 ) vtabDisconnectAll(0, p);
  if( p->azModuleArg ){
  if( db->pnBytesFreed==0 ) vtabDisconnectAll(0, p);
  if( p->u.vtab.azArg ){
    int i;
    for(i=0; i<p->nModuleArg; i++){
      if( i!=1 ) sqlite3DbFree(db, p->azModuleArg[i]);
    for(i=0; i<p->u.vtab.nArg; i++){
      if( i!=1 ) sqlite3DbFree(db, p->u.vtab.azArg[i]);
    }
    sqlite3DbFree(db, p->azModuleArg);
    sqlite3DbFree(db, p->u.vtab.azArg);
  }
}

/*
** Add a new module argument to pTable->azModuleArg[].
** Add a new module argument to pTable->u.vtab.azArg[].
** The string is not copied - the pointer is stored.  The
** string will be freed automatically when the table is
** deleted.
*/
static void addModuleArgument(sqlite3 *db, Table *pTable, char *zArg){
  int nBytes = sizeof(char *)*(2+pTable->nModuleArg);
static void addModuleArgument(Parse *pParse, Table *pTable, char *zArg){
  sqlite3_int64 nBytes;
  char **azModuleArg;
  sqlite3 *db = pParse->db;

  assert( IsVirtual(pTable) );
  nBytes = sizeof(char *)*(2+pTable->u.vtab.nArg);
  if( pTable->u.vtab.nArg+3>=db->aLimit[SQLITE_LIMIT_COLUMN] ){
    sqlite3ErrorMsg(pParse, "too many columns on %s", pTable->zName);
  }
  azModuleArg = sqlite3DbRealloc(db, pTable->azModuleArg, nBytes);
  azModuleArg = sqlite3DbRealloc(db, pTable->u.vtab.azArg, nBytes);
  if( azModuleArg==0 ){
    sqlite3DbFree(db, zArg);
  }else{
    int i = pTable->nModuleArg++;
    int i = pTable->u.vtab.nArg++;
    azModuleArg[i] = zArg;
    azModuleArg[i+1] = 0;
    pTable->azModuleArg = azModuleArg;
    pTable->u.vtab.azArg = azModuleArg;
  }
}

/*
** The parser calls this routine when it first sees a CREATE VIRTUAL TABLE
** statement.  The module name has been parsed, but the optional list
** of parameters that follow the module name are still pending.
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
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







+



-
-
-
-
+
+
+
+










-
+


-
+



-
+














-
+












+


-
+



-
+

-
+







+
+








-
+



-
+




-
+


-
+





-




-
-
+
+
+




-
+
-
-
-
+
+
-
-
-
-



-
+
+







  Table *pTable;        /* The new virtual table */
  sqlite3 *db;          /* Database connection */

  sqlite3StartTable(pParse, pName1, pName2, 0, 0, 1, ifNotExists);
  pTable = pParse->pNewTable;
  if( pTable==0 ) return;
  assert( 0==pTable->pIndex );
  pTable->eTabType = TABTYP_VTAB;

  db = pParse->db;

  assert( pTable->nModuleArg==0 );
  addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName));
  addModuleArgument(db, pTable, 0);
  addModuleArgument(db, pTable, sqlite3DbStrDup(db, pTable->zName));
  assert( pTable->u.vtab.nArg==0 );
  addModuleArgument(pParse, pTable, sqlite3NameFromToken(db, pModuleName));
  addModuleArgument(pParse, pTable, 0);
  addModuleArgument(pParse, pTable, sqlite3DbStrDup(db, pTable->zName));
  assert( (pParse->sNameToken.z==pName2->z && pName2->z!=0)
       || (pParse->sNameToken.z==pName1->z && pName2->z==0)
  );
  pParse->sNameToken.n = (int)(
      &pModuleName->z[pModuleName->n] - pParse->sNameToken.z
  );

#ifndef SQLITE_OMIT_AUTHORIZATION
  /* Creating a virtual table invokes the authorization callback twice.
  ** The first invocation, to obtain permission to INSERT a row into the
  ** sqlite_master table, has already been made by sqlite3StartTable().
  ** sqlite_schema table, has already been made by sqlite3StartTable().
  ** The second call, to obtain permission to create the table, is made now.
  */
  if( pTable->azModuleArg ){
  if( pTable->u.vtab.azArg ){
    int iDb = sqlite3SchemaToIndex(db, pTable->pSchema);
    assert( iDb>=0 ); /* The database the table is being created in */
    sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName, 
            pTable->azModuleArg[0], pParse->db->aDb[iDb].zDbSName);
            pTable->u.vtab.azArg[0], pParse->db->aDb[iDb].zDbSName);
  }
#endif
}

/*
** This routine takes the module argument that has been accumulating
** in pParse->zArg[] and appends it to the list of arguments on the
** virtual table currently under construction in pParse->pTable.
*/
static void addArgumentToVtab(Parse *pParse){
  if( pParse->sArg.z && pParse->pNewTable ){
    const char *z = (const char*)pParse->sArg.z;
    int n = pParse->sArg.n;
    sqlite3 *db = pParse->db;
    addModuleArgument(db, pParse->pNewTable, sqlite3DbStrNDup(db, z, n));
    addModuleArgument(pParse, pParse->pNewTable, sqlite3DbStrNDup(db, z, n));
  }
}

/*
** The parser calls this routine after the CREATE VIRTUAL TABLE statement
** has been completely parsed.
*/
void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
  Table *pTab = pParse->pNewTable;  /* The table being constructed */
  sqlite3 *db = pParse->db;         /* The database connection */

  if( pTab==0 ) return;
  assert( IsVirtual(pTab) );
  addArgumentToVtab(pParse);
  pParse->sArg.z = 0;
  if( pTab->nModuleArg<1 ) return;
  if( pTab->u.vtab.nArg<1 ) return;
  
  /* If the CREATE VIRTUAL TABLE statement is being entered for the
  ** first time (in other words if the virtual table is actually being
  ** created now instead of just being read out of sqlite_master) then
  ** created now instead of just being read out of sqlite_schema) then
  ** do additional initialization work and store the statement text
  ** in the sqlite_master table.
  ** in the sqlite_schema table.
  */
  if( !db->init.busy ){
    char *zStmt;
    char *zWhere;
    int iDb;
    int iReg;
    Vdbe *v;

    sqlite3MayAbort(pParse);

    /* Compute the complete text of the CREATE VIRTUAL TABLE statement */
    if( pEnd ){
      pParse->sNameToken.n = (int)(pEnd->z - pParse->sNameToken.z) + pEnd->n;
    }
    zStmt = sqlite3MPrintf(db, "CREATE VIRTUAL TABLE %T", &pParse->sNameToken);

    /* A slot for the record has already been allocated in the 
    ** SQLITE_MASTER table.  We just need to update that slot with all
    ** schema table.  We just need to update that slot with all
    ** the information we've collected.  
    **
    ** The VM register number pParse->regRowid holds the rowid of an
    ** entry in the sqlite_master table tht was created for this vtab
    ** entry in the sqlite_schema table tht was created for this vtab
    ** by sqlite3StartTable().
    */
    iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
    sqlite3NestedParse(pParse,
      "UPDATE %Q.%s "
      "UPDATE %Q." LEGACY_SCHEMA_TABLE " "
         "SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q "
       "WHERE rowid=#%d",
      db->aDb[iDb].zDbSName, MASTER_NAME,
      db->aDb[iDb].zDbSName,
      pTab->zName,
      pTab->zName,
      zStmt,
      pParse->regRowid
    );
    sqlite3DbFree(db, zStmt);
    v = sqlite3GetVdbe(pParse);
    sqlite3ChangeCookie(pParse, iDb);

    sqlite3VdbeAddOp0(v, OP_Expire);
    zWhere = sqlite3MPrintf(db, "name='%q' AND type='table'", pTab->zName);
    sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere);
    zWhere = sqlite3MPrintf(db, "name=%Q AND sql=%Q", pTab->zName, zStmt);
    sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere, 0);
    sqlite3DbFree(db, zStmt);

    iReg = ++pParse->nMem;
    sqlite3VdbeLoadString(v, iReg, pTab->zName);
    sqlite3VdbeAddOp2(v, OP_VCreate, iDb, iReg);
  }
  }else{

  /* If we are rereading the sqlite_master table create the in-memory
  ** record of the table. The xConnect() method is not called until
    /* If we are rereading the sqlite_schema table create the in-memory
    ** record of the table. */
  ** the first time the virtual table is used in an SQL statement. This
  ** allows a schema that contains virtual tables to be loaded before
  ** the required virtual table implementations are registered.  */
  else {
    Table *pOld;
    Schema *pSchema = pTab->pSchema;
    const char *zName = pTab->zName;
    assert( sqlite3SchemaMutexHeld(db, 0, pSchema) );
    assert( zName!=0 );
    sqlite3MarkAllShadowTablesOf(db, pTab);
    pOld = sqlite3HashInsert(&pSchema->tblHash, zName, pTab);
    if( pOld ){
      sqlite3OomFault(db);
      assert( pTab==pOld );  /* Malloc must have failed inside HashInsert() */
      return;
    }
    pParse->pNewTable = 0;
498
499
500
501
502
503
504
505
506


507
508
509
510
511



512
513
514
515
516
517
518
560
561
562
563
564
565
566


567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583







-
-
+
+





+
+
+







  Module *pMod,
  int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**),
  char **pzErr
){
  VtabCtx sCtx;
  VTable *pVTable;
  int rc;
  const char *const*azArg = (const char *const*)pTab->azModuleArg;
  int nArg = pTab->nModuleArg;
  const char *const*azArg;
  int nArg = pTab->u.vtab.nArg;
  char *zErr = 0;
  char *zModuleName;
  int iDb;
  VtabCtx *pCtx;

  assert( IsVirtual(pTab) );
  azArg = (const char *const*)pTab->u.vtab.azArg;

  /* Check that the virtual-table is not already being initialized */
  for(pCtx=db->pVtabCtx; pCtx; pCtx=pCtx->pPrior){
    if( pCtx->pTab==pTab ){
      *pzErr = sqlite3MPrintf(db, 
          "vtable constructor called recursively: %s", pTab->zName
      );
      return SQLITE_LOCKED;
528
529
530
531
532
533
534

535
536
537

538
539
540
541
542
543
544
593
594
595
596
597
598
599
600
601
602

603
604
605
606
607
608
609
610







+


-
+







  if( !pVTable ){
    sqlite3OomFault(db);
    sqlite3DbFree(db, zModuleName);
    return SQLITE_NOMEM_BKPT;
  }
  pVTable->db = db;
  pVTable->pMod = pMod;
  pVTable->eVtabRisk = SQLITE_VTABRISK_Normal;

  iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
  pTab->azModuleArg[1] = db->aDb[iDb].zDbSName;
  pTab->u.vtab.azArg[1] = db->aDb[iDb].zDbSName;

  /* Invoke the virtual table constructor */
  assert( &db->pVtabCtx );
  assert( xConstruct );
  sCtx.pTab = pTab;
  sCtx.pVTable = pVTable;
  sCtx.pPrior = db->pVtabCtx;
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
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







+








-
+

-
+



-
-
+
+







    }
    sqlite3DbFree(db, pVTable);
  }else if( ALWAYS(pVTable->pVtab) ){
    /* Justification of ALWAYS():  A correct vtab constructor must allocate
    ** the sqlite3_vtab object if successful.  */
    memset(pVTable->pVtab, 0, sizeof(pVTable->pVtab[0]));
    pVTable->pVtab->pModule = pMod->pModule;
    pMod->nRefModule++;
    pVTable->nRef = 1;
    if( sCtx.bDeclared==0 ){
      const char *zFormat = "vtable constructor did not declare schema: %s";
      *pzErr = sqlite3MPrintf(db, zFormat, pTab->zName);
      sqlite3VtabUnlock(pVTable);
      rc = SQLITE_ERROR;
    }else{
      int iCol;
      u8 oooHidden = 0;
      u16 oooHidden = 0;
      /* If everything went according to plan, link the new VTable structure
      ** into the linked list headed by pTab->pVTable. Then loop through the 
      ** into the linked list headed by pTab->u.vtab.p. Then loop through the 
      ** columns of the table to see if any of them contain the token "hidden".
      ** If so, set the Column COLFLAG_HIDDEN flag and remove the token from
      ** the type string.  */
      pVTable->pNext = pTab->pVTable;
      pTab->pVTable = pVTable;
      pVTable->pNext = pTab->u.vtab.p;
      pTab->u.vtab.p = pVTable;

      for(iCol=0; iCol<pTab->nCol; iCol++){
        char *zType = sqlite3ColumnType(&pTab->aCol[iCol], "");
        int nType;
        int i = 0;
        nType = sqlite3Strlen30(zType);
        for(i=0; i<nType; i++){
599
600
601
602
603
604
605

606
607
608
609
610
611
612
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680







+







            zType[j] = zType[j+nDel];
          }
          if( zType[i]=='\0' && i>0 ){
            assert(zType[i-1]==' ');
            zType[i-1] = '\0';
          }
          pTab->aCol[iCol].colFlags |= COLFLAG_HIDDEN;
          pTab->tabFlags |= TF_HasHidden;
          oooHidden = TF_OOOHidden;
        }else{
          pTab->tabFlags |= oooHidden;
        }
      }
    }
  }
625
626
627
628
629
630
631

632

633
634
635
636
637

638
639
640
641

642
643
644
645
646
647
648
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







+
-
+




-
+



-
+







int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){
  sqlite3 *db = pParse->db;
  const char *zMod;
  Module *pMod;
  int rc;

  assert( pTab );
  assert( IsVirtual(pTab) );
  if( !IsVirtual(pTab) || sqlite3GetVTable(db, pTab) ){
  if( sqlite3GetVTable(db, pTab) ){
    return SQLITE_OK;
  }

  /* Locate the required virtual table module */
  zMod = pTab->azModuleArg[0];
  zMod = pTab->u.vtab.azArg[0];
  pMod = (Module*)sqlite3HashFind(&db->aModule, zMod);

  if( !pMod ){
    const char *zModule = pTab->azModuleArg[0];
    const char *zModule = pTab->u.vtab.azArg[0];
    sqlite3ErrorMsg(pParse, "no such module: %s", zModule);
    rc = SQLITE_ERROR;
  }else{
    char *zErr = 0;
    rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xConnect, &zErr);
    if( rc!=SQLITE_OK ){
      sqlite3ErrorMsg(pParse, "%s", zErr);
659
660
661
662
663
664
665
666


667
668
669
670
671
672
673
728
729
730
731
732
733
734

735
736
737
738
739
740
741
742
743







-
+
+







*/
static int growVTrans(sqlite3 *db){
  const int ARRAY_INCR = 5;

  /* Grow the sqlite3.aVTrans array if required */
  if( (db->nVTrans%ARRAY_INCR)==0 ){
    VTable **aVTrans;
    int nBytes = sizeof(sqlite3_vtab *) * (db->nVTrans + ARRAY_INCR);
    sqlite3_int64 nBytes = sizeof(sqlite3_vtab*)*
                                 ((sqlite3_int64)db->nVTrans + ARRAY_INCR);
    aVTrans = sqlite3DbRealloc(db, (void *)db->aVTrans, nBytes);
    if( !aVTrans ){
      return SQLITE_NOMEM_BKPT;
    }
    memset(&aVTrans[db->nVTrans], 0, sizeof(sqlite3_vtab *)*ARRAY_INCR);
    db->aVTrans = aVTrans;
  }
696
697
698
699
700
701
702
703

704
705
706

707
708
709
710
711
712
713
766
767
768
769
770
771
772

773
774
775

776
777
778
779
780
781
782
783







-
+


-
+







int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){
  int rc = SQLITE_OK;
  Table *pTab;
  Module *pMod;
  const char *zMod;

  pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName);
  assert( pTab && IsVirtual(pTab) && !pTab->pVTable );
  assert( pTab && IsVirtual(pTab) && !pTab->u.vtab.p );

  /* Locate the required virtual table module */
  zMod = pTab->azModuleArg[0];
  zMod = pTab->u.vtab.azArg[0];
  pMod = (Module*)sqlite3HashFind(&db->aModule, zMod);

  /* If the module has been registered and includes a Create method, 
  ** invoke it now. If the module has not been registered, return an 
  ** error. Otherwise, do nothing.
  */
  if( pMod==0 || pMod->pModule->xCreate==0 || pMod->pModule->xDestroy==0 ){
734
735
736
737
738
739
740
741
742

743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759

760
761







762
763
764
765



766
767

768

769
770
771
772

773

774
775
776
777
778
779
780
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







-

+
















-
+

-
+
+
+
+
+
+
+

-
-
-
+
+
+
-
-
+

+




+
-
+







** valid to call this function from within the xCreate() or xConnect() of a
** virtual table module.
*/
int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
  VtabCtx *pCtx;
  int rc = SQLITE_OK;
  Table *pTab;
  char *zErr = 0;
  Parse sParse;
  int initBusy;

#ifdef SQLITE_ENABLE_API_ARMOR
  if( !sqlite3SafetyCheckOk(db) || zCreateTable==0 ){
    return SQLITE_MISUSE_BKPT;
  }
#endif
  sqlite3_mutex_enter(db->mutex);
  pCtx = db->pVtabCtx;
  if( !pCtx || pCtx->bDeclared ){
    sqlite3Error(db, SQLITE_MISUSE);
    sqlite3_mutex_leave(db->mutex);
    return SQLITE_MISUSE_BKPT;
  }
  pTab = pCtx->pTab;
  assert( IsVirtual(pTab) );

  memset(&sParse, 0, sizeof(sParse));
  sqlite3ParseObjectInit(&sParse, db);
  sParse.eParseMode = PARSE_MODE_DECLARE_VTAB;
  sParse.db = db;
  sParse.disableTriggers = 1;
  /* We should never be able to reach this point while loading the
  ** schema.  Nevertheless, defend against that (turn off db->init.busy)
  ** in case a bug arises. */
  assert( db->init.busy==0 );
  initBusy = db->init.busy;
  db->init.busy = 0;
  sParse.nQueryLoop = 1;
  if( SQLITE_OK==sqlite3RunParser(&sParse, zCreateTable, &zErr) 
   && sParse.pNewTable
   && !db->mallocFailed
  if( SQLITE_OK==sqlite3RunParser(&sParse, zCreateTable) 
   && ALWAYS(sParse.pNewTable!=0)
   && ALWAYS(!db->mallocFailed)
   && !sParse.pNewTable->pSelect
   && !IsVirtual(sParse.pNewTable)
   && IsOrdinaryTable(sParse.pNewTable)
  ){
    assert( sParse.zErrMsg==0 );
    if( !pTab->aCol ){
      Table *pNew = sParse.pNewTable;
      Index *pIdx;
      pTab->aCol = pNew->aCol;
      sqlite3ExprListDelete(db, pNew->u.tab.pDfltList);
      pTab->nCol = pNew->nCol;
      pTab->nNVCol = pTab->nCol = pNew->nCol;
      pTab->tabFlags |= pNew->tabFlags & (TF_WithoutRowid|TF_NoVisibleRowid);
      pNew->nCol = 0;
      pNew->aCol = 0;
      assert( pTab->pIndex==0 );
      assert( HasRowid(pNew) || sqlite3PrimaryKeyIndex(pNew)!=0 );
      if( !HasRowid(pNew)
       && pCtx->pVTable->pMod->pModule->xUpdate!=0
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
867
868
869
870
871
872
873


874
875
876
877
878
879
880
881
882
883
884

885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907

908
909
910
911

912
913
914
915
916
917
918
919
920

921
922
923
924
925

926
927

928
929
930
931
932
933
934
935
936
937
938







-
-
+
+
+








-
+
+



















+
+
-
+
+


-
+







+
-
+
+



-
+

-
+


+







        pTab->pIndex = pIdx;
        pNew->pIndex = 0;
        pIdx->pTable = pTab;
      }
    }
    pCtx->bDeclared = 1;
  }else{
    sqlite3ErrorWithMsg(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr);
    sqlite3DbFree(db, zErr);
    sqlite3ErrorWithMsg(db, SQLITE_ERROR,
          (sParse.zErrMsg ? "%s" : 0), sParse.zErrMsg);
    sqlite3DbFree(db, sParse.zErrMsg);
    rc = SQLITE_ERROR;
  }
  sParse.eParseMode = PARSE_MODE_NORMAL;

  if( sParse.pVdbe ){
    sqlite3VdbeFinalize(sParse.pVdbe);
  }
  sqlite3DeleteTable(db, sParse.pNewTable);
  sqlite3ParserReset(&sParse);
  sqlite3ParseObjectReset(&sParse);
  db->init.busy = initBusy;

  assert( (rc&0xff)==rc );
  rc = sqlite3ApiExit(db, rc);
  sqlite3_mutex_leave(db->mutex);
  return rc;
}

/*
** This function is invoked by the vdbe to call the xDestroy method
** of the virtual table named zTab in database iDb. This occurs
** when a DROP TABLE is mentioned.
**
** This call is a no-op if zTab is not a virtual table.
*/
int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab){
  int rc = SQLITE_OK;
  Table *pTab;

  pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName);
  if( ALWAYS(pTab!=0)
   && ALWAYS(IsVirtual(pTab))
  if( pTab!=0 && ALWAYS(pTab->pVTable!=0) ){
   && ALWAYS(pTab->u.vtab.p!=0)
  ){
    VTable *p;
    int (*xDestroy)(sqlite3_vtab *);
    for(p=pTab->pVTable; p; p=p->pNext){
    for(p=pTab->u.vtab.p; p; p=p->pNext){
      assert( p->pVtab );
      if( p->pVtab->nRef>0 ){
        return SQLITE_LOCKED;
      }
    }
    p = vtabDisconnectAll(db, pTab);
    xDestroy = p->pMod->pModule->xDestroy;
    if( xDestroy==0 ) xDestroy = p->pMod->pModule->xDisconnect;
    assert( xDestroy!=0 );  /* Checked before the virtual table is created */
    assert( xDestroy!=0 );
    pTab->nTabRef++;
    rc = xDestroy(p->pVtab);
    /* Remove the sqlite3_vtab* from the aVTrans[] array, if applicable */
    if( rc==SQLITE_OK ){
      assert( pTab->pVTable==p && p->pNext==0 );
      assert( pTab->u.vtab.p==p && p->pNext==0 );
      p->pVtab = 0;
      pTab->pVTable = 0;
      pTab->u.vtab.p = 0;
      sqlite3VtabUnlock(p);
    }
    sqlite3DeleteTable(db, pTab);
  }

  return rc;
}

/*
** This function invokes either the xRollback or xCommit method
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
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







+















+







  if( db->aVTrans ){
    int i;
    for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){
      VTable *pVTab = db->aVTrans[i];
      const sqlite3_module *pMod = pVTab->pMod->pModule;
      if( pVTab->pVtab && pMod->iVersion>=2 ){
        int (*xMethod)(sqlite3_vtab *, int);
        sqlite3VtabLock(pVTab);
        switch( op ){
          case SAVEPOINT_BEGIN:
            xMethod = pMod->xSavepoint;
            pVTab->iSavepoint = iSavepoint+1;
            break;
          case SAVEPOINT_ROLLBACK:
            xMethod = pMod->xRollbackTo;
            break;
          default:
            xMethod = pMod->xRelease;
            break;
        }
        if( xMethod && pVTab->iSavepoint>iSavepoint ){
          rc = xMethod(pVTab->pVtab, iSavepoint);
        }
        sqlite3VtabUnlock(pVTab);
      }
    }
  }
  return rc;
}

/*
1048
1049
1050
1051
1052
1053
1054

1055
1056

1057
1058
1059
1060
1061
1062
1063
1135
1136
1137
1138
1139
1140
1141
1142
1143

1144
1145
1146
1147
1148
1149
1150
1151







+

-
+







  void *pArg = 0;
  FuncDef *pNew;
  int rc = 0;

  /* Check to see the left operand is a column in a virtual table */
  if( NEVER(pExpr==0) ) return pDef;
  if( pExpr->op!=TK_COLUMN ) return pDef;
  assert( ExprUseYTab(pExpr) );
  pTab = pExpr->y.pTab;
  if( pTab==0 ) return pDef;
  if( NEVER(pTab==0) ) return pDef;
  if( !IsVirtual(pTab) ) return pDef;
  pVtab = sqlite3GetVTable(db, pTab)->pVtab;
  assert( pVtab!=0 );
  assert( pVtab->pModule!=0 );
  pMod = (sqlite3_module *)pVtab->pModule;
  if( pMod->xFindFunction==0 ) return pDef;
 
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
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







-
+











-
-
+
+
+







  Table **apVtabLock;

  assert( IsVirtual(pTab) );
  for(i=0; i<pToplevel->nVtabLock; i++){
    if( pTab==pToplevel->apVtabLock[i] ) return;
  }
  n = (pToplevel->nVtabLock+1)*sizeof(pToplevel->apVtabLock[0]);
  apVtabLock = sqlite3_realloc64(pToplevel->apVtabLock, n);
  apVtabLock = sqlite3Realloc(pToplevel->apVtabLock, n);
  if( apVtabLock ){
    pToplevel->apVtabLock = apVtabLock;
    pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab;
  }else{
    sqlite3OomFault(pToplevel->db);
  }
}

/*
** Check to see if virtual table module pMod can be have an eponymous
** virtual table instance.  If it can, create one if one does not already
** exist. Return non-zero if the eponymous virtual table instance exists
** when this routine returns, and return zero if it does not exist.
** exist. Return non-zero if either the eponymous virtual table instance 
** exists when this routine returns or if an attempt to create it failed
** and an error message was left in pParse.
**
** An eponymous virtual table instance is one that is named after its
** module, and more importantly, does not require a CREATE VIRTUAL TABLE
** statement in order to come into existance.  Eponymous virtual table
** instances always exist.  They cannot be DROP-ed.
**
** Any virtual table module for which xConnect and xCreate are the same
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
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







+

-
+

+
-
-
-
+
+
+





-







  pTab->zName = sqlite3DbStrDup(db, pMod->zName);
  if( pTab->zName==0 ){
    sqlite3DbFree(db, pTab);
    return 0;
  }
  pMod->pEpoTab = pTab;
  pTab->nTabRef = 1;
  pTab->eTabType = TABTYP_VTAB;
  pTab->pSchema = db->aDb[0].pSchema;
  assert( pTab->nModuleArg==0 );
  assert( pTab->u.vtab.nArg==0 );
  pTab->iPKey = -1;
  pTab->tabFlags |= TF_Eponymous;
  addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName));
  addModuleArgument(db, pTab, 0);
  addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName));
  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);
    sqlite3VtabEponymousTableClear(db, pMod);
    return 0;
  }
  return 1;
}

/*
** Erase the eponymous virtual table instance associated with
** virtual table module pMod, if it exists.
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
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312








1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325







1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345







+





-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

+

+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+







** Call from within the xCreate() or xConnect() methods to provide 
** the SQLite core with additional information about the behavior
** of the virtual table being implemented.
*/
int sqlite3_vtab_config(sqlite3 *db, int op, ...){
  va_list ap;
  int rc = SQLITE_OK;
  VtabCtx *p;

#ifdef SQLITE_ENABLE_API_ARMOR
  if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
#endif
  sqlite3_mutex_enter(db->mutex);
  va_start(ap, op);
  switch( op ){
    case SQLITE_VTAB_CONSTRAINT_SUPPORT: {
      VtabCtx *p = db->pVtabCtx;
      if( !p ){
        rc = SQLITE_MISUSE_BKPT;
      }else{
        assert( p->pTab==0 || IsVirtual(p->pTab) );
  p = db->pVtabCtx;
  if( !p ){
    rc = SQLITE_MISUSE_BKPT;
  }else{
    assert( p->pTab==0 || IsVirtual(p->pTab) );
    va_start(ap, op);
    switch( op ){
      case SQLITE_VTAB_CONSTRAINT_SUPPORT: {
        p->pVTable->bConstraint = (u8)va_arg(ap, int);
        break;
      }
      case SQLITE_VTAB_INNOCUOUS: {
        p->pVTable->eVtabRisk = SQLITE_VTABRISK_Low;
      break;
    }
    default:
      rc = SQLITE_MISUSE_BKPT;
      break;
  }
  va_end(ap);
        break;
      }
      case SQLITE_VTAB_DIRECTONLY: {
        p->pVTable->eVtabRisk = SQLITE_VTABRISK_High;
        break;
      }
      default: {
        rc = SQLITE_MISUSE_BKPT;
        break;
      }
    }
    va_end(ap);
  }

  if( rc!=SQLITE_OK ) sqlite3Error(db, rc);
  sqlite3_mutex_leave(db->mutex);
  return rc;
}

#endif /* SQLITE_OMIT_VIRTUALTABLE */

Changes to src/wal.c.

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







-
+







** being considered valid at the same time and being checkpointing together
** following a crash.
**
** READER ALGORITHM
**
** To read a page from the database (call it page number P), a reader
** first checks the WAL to see if it contains page P.  If so, then the
** last valid instance of page P that is a followed by a commit frame
** last valid instance of page P that is followed by a commit frame
** or is a commit frame itself becomes the value read.  If the WAL
** contains no copies of page P that are valid and which are a commit
** frame or are followed by a commit frame, then page P is read from
** the database file.
**
** To start a read transaction, the reader records the index of the last
** valid frame in the WAL.  The reader uses this recorded "mxFrame" value
157
158
159
160
161
162
163
164




165
166
167
168
169
170
171
157
158
159
160
161
162
163

164
165
166
167
168
169
170
171
172
173
174







-
+
+
+
+







** in the mxFrame field.
**
** Each index block except for the first contains information on 
** HASHTABLE_NPAGE frames. The first index block contains information on
** HASHTABLE_NPAGE_ONE frames. The values of HASHTABLE_NPAGE_ONE and 
** HASHTABLE_NPAGE are selected so that together the wal-index header and
** first index block are the same size as all other index blocks in the
** wal-index.
** wal-index.  The values are:
**
**   HASHTABLE_NPAGE      4096
**   HASHTABLE_NPAGE_ONE  4062
**
** Each index block contains two sections, a page-mapping that contains the
** database page number associated with each wal frame, and a hash-table 
** that allows readers to query an index block for a specific page number.
** The page-mapping is an array of HASHTABLE_NPAGE (or HASHTABLE_NPAGE_ONE
** for the first index block) 32-bit page numbers. The first entry in the 
** first index-block contains the database page number corresponding to the
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
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







-
+










+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+















-
-
+
+
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
-
-
-
+
+

-
-
+
+
-
-
+

-
-
+
+







**
** Note that entries are added in order of increasing K.  Hence, one
** reader might be using some value K0 and a second reader that started
** at a later time (after additional transactions were added to the WAL
** and to the wal-index) might be using a different value K1, where K1>K0.
** Both readers can use the same hash table and mapping section to get
** the correct result.  There may be entries in the hash table with
** K>K0 but to the first reader, those entries will appear to be unused
** K>K0, but to the first reader those entries will appear to be unused
** slots in the hash table and so the first reader will get an answer as
** if no values greater than K0 had ever been inserted into the hash table
** in the first place - which is what reader one wants.  Meanwhile, the
** second reader using K1 will see additional values that were inserted
** later, which is exactly what reader two wants.  
**
** When a rollback occurs, the value of K is decreased. Hash table entries
** that correspond to frames greater than the new K value are removed
** from the hash table at this point.
*/

/*
** WAL2 NOTES
**
** This file also contains the implementation of "wal2" mode - activated
** using "PRAGMA journal_mode = wal2". Wal2 mode is very similar to wal
** mode, except that it uses two wal files instead of one. Under some
** circumstances, wal2 mode provides more concurrency than legacy wal 
** mode.
**
** THE PROBLEM WAL2 SOLVES:
**
** In legacy wal mode, if a writer wishes to write to the database while
** a checkpoint is ongoing, it may append frames to the existing wal file.
** This means that after the checkpoint has finished, the wal file consists
** of a large block of checkpointed frames, followed by a block of
** uncheckpointed frames. In a deployment that features a high volume of
** write traffic, this may mean that the wal file is never completely
** checkpointed. And so grows indefinitely.
**
** An alternative is to use "PRAGMA wal_checkpoint=RESTART" or similar to
** force a complete checkpoint of the wal file. But this must:
**
**   1) Wait on all existing readers to finish,
**   2) Wait on any existing writer, and then block all new writers,
**   3) Do the checkpoint,
**   4) Wait on any new readers that started during steps 2 and 3. Writers
**      are still blocked during this step.
**
** This means that in order to avoid the wal file growing indefinitely 
** in a busy system, writers must periodically pause to allow a checkpoint
** to complete. In a system with long running readers, such pauses may be
** for a non-trivial amount of time.
**
** OVERVIEW OF SOLUTION
**
** Wal2 mode uses two wal files. After writers have grown the first wal 
** file to a pre-configured size, they begin appending transactions to 
** the second wal file. Once all existing readers are reading snapshots
** new enough to include the entire first wal file, a checkpointer can
** checkpoint it.
**
** Meanwhile, writers are writing transactions to the second wal file.
** Once that wal file has grown larger than the pre-configured size, each
** new writer checks if:
**
**    * the first wal file has been checkpointed, and if so, if
**    * there are no readers still reading from the first wal file (once
**      it has been checkpointed, new readers read only from the second
**      wal file).
**
** If both these conditions are true, the writer may switch back to the
** first wal file. Eventually, a checkpointer can checkpoint the second
** wal file, and so on.
**
** The wal file that writers are currently appending to (the one they
** don't have to check the above two criteria before writing to) is called
** the "current" wal file.
**
** The first wal file takes the same name as the wal file in legacy wal
** mode systems - "<db>-wal". The second is named "<db>-wal2".

**
** CHECKPOINTS
**
** The "pre-configured size" mentioned above is the value set by 
** "PRAGMA journal_size_limit". Or, if journal_size_limit is not set, 
** 1000 pages.
**
** There is only a single type of checkpoint in wal2 mode (no "truncate",
** "restart" etc.), and it always checkpoints the entire contents of a single
** wal file. A wal file cannot be checkpointed until after a writer has written
** the first transaction into the other wal file and all readers are reading a
** snapshot that includes at least one transaction from the other wal file.
**
** The wal-hook, if one is registered, is invoked after a write-transaction
** is committed, just as it is in legacy wal mode. The integer parameter
** passed to the wal-hook is the total number of uncheckpointed frames in both
** wal files. Except, the parameter is set to zero if there is no frames 
** that may be checkpointed. This happens in two scenarios:
**
**   1. The "other" wal file (the one that the writer did not just append to)
**      is completely empty, or
**
**   2. The "other" wal file (the one that the writer did not just append to)
**      has already been checkpointed.
**
**
** WAL FILE FORMAT
**
** The file format used for each wal file in wal2 mode is the same as for
** legacy wal mode.  Except, the file format field is set to 3021000 
** instead of 3007000.
**
** WAL-INDEX FORMAT
**
** The wal-index format is also very similar. Even though there are two
** wal files, there is still a single wal-index shared-memory area (*-shm
** file with the default unix or win32 VFS). The wal-index header is the
** same size, with the following exceptions it has the same format:
**
**   * The version field is set to 3021000 instead of 3007000.
**
**   * An unused 32-bit field in the legacy wal-index header is
**     now used to store (a) a single bit indicating which of the
**     two wal files writers should append to and (b) the number
**     of frames in the second wal file (31 bits).
**
** The first hash table in the wal-index contains entries corresponding
** to the first HASHTABLE_NPAGE_ONE frames stored in the first wal file.
** The second hash table in the wal-index contains entries indexing the
** first HASHTABLE_NPAGE frames in the second wal file. The third hash
** table contains the next HASHTABLE_NPAGE frames in the first wal file,
** and so on.
**
** LOCKS
**
** Read-locks are simpler than for legacy wal mode. There are no locking
** slots that contain frame numbers. Instead, there are four distinct
** combinations of read locks a reader may hold:
**
**   WAL_LOCK_PART1:       "part" lock on first wal, none of second.
**   WAL_LOCK_PART1_FULL2: "part" lock on first wal, "full" of second.
**   WAL_LOCK_PART2: no lock on first wal, "part" lock on second.
**   WAL_LOCK_PART2_FULL1: "full" lock on first wal, "part" lock on second.
**
** When a reader reads the wal-index header as part of opening a read
** transaction, it takes a "part" lock on the current wal file. "Part" 
** because the wal file may grow while the read transaction is active, in 
** which case the reader would be reading only part of the wal file. 
** A part lock prevents a checkpointer from checkpointing the wal file 
** on which it is held.
**
** If there is data in the non-current wal file that has not been 
** checkpointed, the reader takes a "full" lock on that wal file. A 
** "full" lock indicates that the reader is using the entire wal file.
** A full lock prevents a writer from overwriting the wal file on which
** it is held, but does not prevent a checkpointer from checkpointing 
** it.
**
** There is still a single WRITER and a single CHECKPOINTER lock. The
** recovery procedure still takes the same exclusive lock on the entire
** range of SQLITE_SHM_NLOCK shm-locks. This works because the read-locks
** above use four of the six read-locking slots used by legacy wal mode.
**
** STARTUP/RECOVERY
**
** The read and write version fields of the database header in a wal2
** database are set to 0x03, instead of 0x02 as in legacy wal mode.
**
** The wal file format used in wal2 mode is the same as the format used
** in legacy wal mode. However, in order to support recovery, there are two
** differences in the way wal file header fields are populated, as follows:
**
**   * When the first wal file is first created, the "nCkpt" field in
**     the wal file header is set to 0. Thereafter, each time the writer
**     switches wal file, it sets the nCkpt field in the new wal file
**     header to ((nCkpt0 + 1) & 0x0F), where nCkpt0 is the value in
**     the previous wal file header. This means that the first wal file
**     always has an even value in the nCkpt field, and the second wal
**     file always has an odd value.
**
**   * When a writer switches wal file, it sets the salt values in the
**     new wal file to a copy of the checksum for the final frame in
**     the previous wal file.
**
** Recovery proceeds as follows:
**
** 1. Each wal file is recovered separately. Except, if the first wal 
**    file does not exist or is zero bytes in size, the second wal file
**    is truncated to zero bytes before it is "recovered".
**
** 2. If both wal files contain valid headers, then the nCkpt fields
**    are compared to see which of the two wal files is older. If the
**    salt keys in the second wal file match the final frame checksum 
**    in the older wal file, then both wal files are used. Otherwise,
**    the newer wal file is ignored.
**
** 3. Or, if only one or neither of the wal files has a valid header, 
**    then only a single or no wal files are recovered into the 
**    reconstructed wal-index.
**
** Refer to header comments for walIndexRecover() for further details.
*/

#ifndef SQLITE_OMIT_WAL

#include "wal.h"

/*
** Trace output macros
*/
#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
int sqlite3WalTrace = 0;
# define WALTRACE(X)  if(sqlite3WalTrace) sqlite3DebugPrintf X
#else
# define WALTRACE(X)
#endif

/*
** WAL mode depends on atomic aligned 32-bit loads and stores in a few
** places.  The following macros try to make this explicit.
** Both the wal-file and the wal-index contain version fields 
** indicating the current version of the system. If a client
*/
#if GCC_VESRION>=5004000
# define AtomicLoad(PTR)       __atomic_load_n((PTR),__ATOMIC_RELAXED)
# define AtomicStore(PTR,VAL)  __atomic_store_n((PTR),(VAL),__ATOMIC_RELAXED)
#else
# define AtomicLoad(PTR)       (*(PTR))
# define AtomicStore(PTR,VAL)  (*(PTR) = (VAL))
#endif

** reads the header of a wal file (as part of recovery), or the
/*
** The maximum (and only) versions of the wal and wal-index formats
** wal-index (as part of opening a read transaction) and (a) the
** that may be interpreted by this version of SQLite.
**
** If a client begins recovering a WAL file and finds that (a) the checksum
** values in the wal-header are correct and (b) the version field is not
** WAL_MAX_VERSION, recovery fails and SQLite returns SQLITE_CANTOPEN.
** header checksum is correct but (b) the version field is not
** recognized, the operation fails with SQLITE_CANTOPEN.
**
** Similarly, if a client successfully reads a wal-index header (i.e. the 
** checksum test is successful) and finds that the version field is not
** Currently, clients support both version-1 ("journal_mode=wal") and
** version-2 ("journal_mode=wal2"). Legacy clients may support version-1
** WALINDEX_MAX_VERSION, then no read-transaction is opened and SQLite
** returns SQLITE_CANTOPEN.
** only.
*/
#define WAL_MAX_VERSION      3007000
#define WALINDEX_MAX_VERSION 3007000
#define WAL_VERSION1 3007000      /* For "journal_mode=wal" */
#define WAL_VERSION2 3021000      /* For "journal_mode=wal2" */

/*
** Index numbers for various locking bytes.   WAL_NREADER is the number
** of available reader locks and should be at least 3.  The default
** is SQLITE_SHM_NLOCK==8 and  WAL_NREADER==5.
**
** Technically, the various VFSes are free to implement these locks however
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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



















+
+
+
+
+
+



-
+




-
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







#define WAL_WRITE_LOCK         0
#define WAL_ALL_BUT_WRITE      1
#define WAL_CKPT_LOCK          1
#define WAL_RECOVER_LOCK       2
#define WAL_READ_LOCK(I)       (3+(I))
#define WAL_NREADER            (SQLITE_SHM_NLOCK-3)

/*
** Values that may be stored in Wal.readLock in wal2 mode.
**
** In wal mode, the Wal.readLock member is set to -1 when no read-lock
** is held, or else is the index of the read-mark on which a lock is
** held.
**
** In wal2 mode, a value of -1 still indicates that no read-lock is held.
** And a non-zero value still represents the index of the read-mark on
** which a lock is held. There are two differences:
**
**   1. wal2 mode never uses read-mark 0.
**
**   2. locks on each read-mark have a different interpretation, as 
**      indicated by the symbolic names below.
*/
#define WAL_LOCK_NONE        -1
#define WAL_LOCK_PART1        1
#define WAL_LOCK_PART1_FULL2  2
#define WAL_LOCK_PART2_FULL1  3
#define WAL_LOCK_PART2        4

/* 
** This constant is used in wal2 mode only.
**
** In wal2 mode, when committing a transaction, if the current wal file 
** is sufficiently large and there are no conflicting locks held, the
** writer writes the new transaction into the start of the other wal
** file. Usually, "sufficiently large" is defined by the value configured
** using "PRAGMA journal_size_limit". However, if no such value has been
** configured, sufficiently large defaults to WAL_DEFAULT_WALSIZE frames.
*/
#define WAL_DEFAULT_WALSIZE 1000

/* Object declarations */
typedef struct WalIndexHdr WalIndexHdr;
typedef struct WalIterator WalIterator;
typedef struct WalCkptInfo WalCkptInfo;


/*
** The following object holds a copy of the wal-index header content.
**
** The actual header in the wal-index consists of two copies of this
** object followed by one instance of the WalCkptInfo object.
** For all versions of SQLite through 3.10.0 and probably beyond,
** the locking bytes (WalCkptInfo.aLock) start at offset 120 and
** the total header size is 136 bytes.
**
** The szPage value can be any power of 2 between 512 and 32768, inclusive.
** Or it can be 1 to represent a 65536-byte page.  The latter case was
** added in 3.7.1 when support for 64K pages was added.  
**
** WAL2 mode notes: Member variable mxFrame2 is only used in wal2 mode
** (when iVersion is set to WAL_VERSION2). The lower 31 bits store
** the maximum frame number in file *-wal2. The most significant bit
** is a flag - set if clients are currently appending to *-wal2, clear
** otherwise.
*/
struct WalIndexHdr {
  u32 iVersion;                   /* Wal-index version */
  u32 unused;                     /* Unused (padding) field */
  u32 mxFrame2;                   /* See "WAL2 mode notes" above */
  u32 iChange;                    /* Counter incremented each transaction */
  u8 isInit;                      /* 1 when initialized */
  u8 bigEndCksum;                 /* True if checksums in WAL are big-endian */
  u16 szPage;                     /* Database page size in bytes. 1==64K */
  u32 mxFrame;                    /* Index of last valid frame in the WAL */
  u32 mxFrame;                    /* Index of last valid frame in each WAL */
  u32 nPage;                      /* Size of database in pages */
  u32 aFrameCksum[2];             /* Checksum of last frame in log */
  u32 aSalt[2];                   /* Two salt values copied from WAL header */
  u32 aCksum[2];                  /* Checksum over all prior fields */
};

/*
** The following macros and functions are get/set methods for the maximum
** frame numbers and current wal file values stored in the WalIndexHdr
** structure. These are helpful because of the unorthodox way in which
** the values are stored in wal2 mode (see above). They are equivalent
** to functions with the following signatures.
**
**   u32  walidxGetMxFrame(WalIndexHdr*, int iWal);          // get mxFrame
**   void walidxSetMxFrame(WalIndexHdr*, int iWal, u32 val); // set mxFrame
**   int  walidxGetFile(WalIndexHdr*)                        // get file
**   void walidxSetFile(WalIndexHdr*, int val);              // set file
*/
#define walidxGetMxFrame(pHdr, iWal) \
  ((iWal) ? ((pHdr)->mxFrame2 & 0x7FFFFFFF) : (pHdr)->mxFrame)

static void walidxSetMxFrame(WalIndexHdr *pHdr, int iWal, u32 mxFrame){
  if( iWal ){
    pHdr->mxFrame2 = (pHdr->mxFrame2 & 0x80000000) | mxFrame;
  }else{
    pHdr->mxFrame = mxFrame;
  }
  assert( walidxGetMxFrame(pHdr, iWal)==mxFrame );
}

#define walidxGetFile(pHdr) ((pHdr)->mxFrame2 >> 31)

#define walidxSetFile(pHdr, iWal) (                                   \
    (pHdr)->mxFrame2 = ((pHdr)->mxFrame2 & 0x7FFFFFFF) | ((iWal)<<31) \
)

/*
** Argument is a pointer to a Wal structure. Return true if the current
** cache of the wal-index header indicates "journal_mode=wal2" mode, or
** false otherwise.
*/
#define isWalMode2(pWal) ((pWal)->hdr.iVersion==WAL_VERSION2)

/*
** A copy of the following object occurs in the wal-index immediately
** following the second copy of the WalIndexHdr.  This object stores
** information used by checkpoint.
**
** nBackfill is the number of frames in the WAL that have been written
** back into the database. (We call the act of moving content from WAL to
405
406
407
408
409
410
411
































































412
413
414
415
416
417
418
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  u32 aReadMark[WAL_NREADER];     /* Reader marks */
  u8 aLock[SQLITE_SHM_NLOCK];     /* Reserved space for locks */
  u32 nBackfillAttempted;         /* WAL frames perhaps written, or maybe not */
  u32 notUsed0;                   /* Available for future enhancements */
};
#define READMARK_NOT_USED  0xffffffff

/*
** This is a schematic view of the complete 136-byte header of the
** wal-index file (also known as the -shm file):
**
**      +-----------------------------+
**   0: | iVersion                    | \
**      +-----------------------------+  |
**   4: | (unused padding)            |  |
**      +-----------------------------+  |
**   8: | iChange                     |  |
**      +-------+-------+-------------+  |
**  12: | bInit |  bBig |   szPage    |  |
**      +-------+-------+-------------+  |
**  16: | mxFrame                     |  |  First copy of the
**      +-----------------------------+  |  WalIndexHdr object
**  20: | nPage                       |  |
**      +-----------------------------+  |
**  24: | aFrameCksum                 |  |
**      |                             |  |
**      +-----------------------------+  |
**  32: | aSalt                       |  |
**      |                             |  |
**      +-----------------------------+  |
**  40: | aCksum                      |  |
**      |                             | /
**      +-----------------------------+
**  48: | iVersion                    | \
**      +-----------------------------+  |
**  52: | (unused padding)            |  |
**      +-----------------------------+  |
**  56: | iChange                     |  |
**      +-------+-------+-------------+  |
**  60: | bInit |  bBig |   szPage    |  |
**      +-------+-------+-------------+  |  Second copy of the
**  64: | mxFrame                     |  |  WalIndexHdr
**      +-----------------------------+  |
**  68: | nPage                       |  |
**      +-----------------------------+  |
**  72: | aFrameCksum                 |  |
**      |                             |  |
**      +-----------------------------+  |
**  80: | aSalt                       |  |
**      |                             |  |
**      +-----------------------------+  |
**  88: | aCksum                      |  |
**      |                             | /
**      +-----------------------------+
**  96: | nBackfill                   |
**      +-----------------------------+
** 100: | 5 read marks                |
**      |                             |
**      |                             |
**      |                             |
**      |                             |
**      +-------+-------+------+------+
** 120: | Write | Ckpt  | Rcvr | Rd0  | \
**      +-------+-------+------+------+  ) 8 lock bytes
**      | Read1 | Read2 | Rd3  | Rd4  | /
**      +-------+-------+------+------+
** 128: | nBackfillAttempted          |
**      +-----------------------------+
** 132: | (unused padding)            |
**      +-----------------------------+
*/

/* A block of WALINDEX_LOCK_RESERVED bytes beginning at
** WALINDEX_LOCK_OFFSET is reserved for locks. Since some systems
** only support mandatory file-locks, we do not read or write data
** from the region of the file on which locks are applied.
*/
#define WALINDEX_LOCK_OFFSET (sizeof(WalIndexHdr)*2+offsetof(WalCkptInfo,aLock))
447
448
449
450
451
452
453
454

455
456
457
458
459
460
461
762
763
764
765
766
767
768

769
770
771
772
773
774
775
776







-
+







/*
** An open write-ahead log file is represented by an instance of the
** following object.
*/
struct Wal {
  sqlite3_vfs *pVfs;         /* The VFS used to create pDbFd */
  sqlite3_file *pDbFd;       /* File handle for the database file */
  sqlite3_file *pWalFd;      /* File handle for WAL file */
  sqlite3_file *apWalFd[2];  /* File handle for "*-wal" and "*-wal2" */
  u32 iCallback;             /* Value to pass to log callback (or 0) */
  i64 mxWalSize;             /* Truncate WAL to this size upon reset */
  int nWiData;               /* Size of array apWiData */
  int szFirstBlock;          /* Size of first block written to WAL file */
  volatile u32 **apWiData;   /* Pointer to wal-index content in memory */
  u32 szPage;                /* Database page size */
  i16 readLock;              /* Which read lock is being held.  -1 for none */
469
470
471
472
473
474
475

476
477
478
479
480
481
482





483
484
485
486
487
488
489
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







+







+
+
+
+
+







  u8 padToSectorBoundary;    /* Pad transactions out to the next sector */
  u8 bShmUnreliable;         /* SHM content is read-only and unreliable */
  WalIndexHdr hdr;           /* Wal-index header for current transaction */
  u32 minFrame;              /* Ignore wal frames before this one */
  u32 iReCksum;              /* On commit, recalculate checksums from here */
  u32 nPriorFrame;           /* For sqlite3WalInfo() */
  const char *zWalName;      /* Name of WAL file */
  const char *zWalName2;     /* Name of second WAL file */
  u32 nCkpt;                 /* Checkpoint sequence counter in the wal-header */
  FastPrng sPrng;            /* Random number generator */
#ifdef SQLITE_DEBUG
  u8 lockError;              /* True if a locking error has occurred */
#endif
#ifdef SQLITE_ENABLE_SNAPSHOT
  WalIndexHdr *pSnapshot;    /* Start transaction here if not NULL */
#endif
  int bClosing;              /* Set to true at start of sqlite3WalClose() */
  int bWal2;                 /* bWal2 flag passed to WalOpen() */
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
  sqlite3 *db;
#endif
};

/*
** Candidate values for Wal.exclusiveMode.
*/
#define WAL_NORMAL_MODE     0
515
516
517
518
519
520
521
522

523
524
525
526
527
528
529
836
837
838
839
840
841
842

843
844
845
846
847
848
849
850







-
+







**   walIteratorInit() - Create a new iterator,
**   walIteratorNext() - Step an iterator,
**   walIteratorFree() - Free an iterator.
**
** This functionality is used by the checkpoint code (see walCheckpoint()).
*/
struct WalIterator {
  int iPrior;                     /* Last result returned from the iterator */
  u32 iPrior;                     /* Last result returned from the iterator */
  int nSegment;                   /* Number of entries in aSegment[] */
  struct WalSegment {
    int iNext;                    /* Next slot in aIndex[] not yet returned */
    ht_slot *aIndex;              /* i0, i1, i2... such that aPgno[iN] ascend */
    u32 *aPgno;                   /* Array of page numbers. */
    int nEntry;                   /* Nr. of entries in aPgno[] and aIndex[] */
    int iZero;                    /* Frame number associated with aPgno[0] */
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
881
882
883
884
885
886
887



888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904

905
906

907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926

927
928
929
930
931
932

933
934
935
936
937
938
939
940







-
-
-
+
+
+
+
+
+
+










-
+

-
+



















-
+
+
+

+
+
-
+







** numbered from zero.
**
** If the wal-index is currently smaller the iPage pages then the size
** of the wal-index might be increased, but only if it is safe to do
** so.  It is safe to enlarge the wal-index if pWal->writeLock is true
** or pWal->exclusiveMode==WAL_HEAPMEMORY_MODE.
**
** If this call is successful, *ppPage is set to point to the wal-index
** page and SQLITE_OK is returned. If an error (an OOM or VFS error) occurs,
** then an SQLite error code is returned and *ppPage is set to 0.
** Three possible result scenarios:
**
**   (1)  rc==SQLITE_OK    and *ppPage==Requested-Wal-Index-Page
**   (2)  rc>=SQLITE_ERROR and *ppPage==NULL
**   (3)  rc==SQLITE_OK    and *ppPage==NULL  // only if iPage==0 
**
** Scenario (3) can only occur when pWal->writeLock is false and iPage==0
*/
static SQLITE_NOINLINE int walIndexPageRealloc(
  Wal *pWal,               /* The WAL context */
  int iPage,               /* The page we seek */
  volatile u32 **ppPage    /* Write the page pointer here */
){
  int rc = SQLITE_OK;

  /* Enlarge the pWal->apWiData[] array if required */
  if( pWal->nWiData<=iPage ){
    int nByte = sizeof(u32*)*(iPage+1);
    sqlite3_int64 nByte = sizeof(u32*)*(iPage+1);
    volatile u32 **apNew;
    apNew = (volatile u32 **)sqlite3_realloc64((void *)pWal->apWiData, nByte);
    apNew = (volatile u32 **)sqlite3Realloc((void *)pWal->apWiData, nByte);
    if( !apNew ){
      *ppPage = 0;
      return SQLITE_NOMEM_BKPT;
    }
    memset((void*)&apNew[pWal->nWiData], 0,
           sizeof(u32*)*(iPage+1-pWal->nWiData));
    pWal->apWiData = apNew;
    pWal->nWiData = iPage+1;
  }

  /* Request a pointer to the required page from the VFS */
  assert( pWal->apWiData[iPage]==0 );
  if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){
    pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ);
    if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM_BKPT;
  }else{
    rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ, 
        pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
    );
    assert( pWal->apWiData[iPage]!=0 || rc!=SQLITE_OK || pWal->writeLock==0 );
    assert( pWal->apWiData[iPage]!=0
         || rc!=SQLITE_OK
         || (pWal->writeLock==0 && iPage==0) );
    testcase( pWal->apWiData[iPage]==0 && rc==SQLITE_OK );
    if( rc==SQLITE_OK ){
      if( iPage>0 && sqlite3FaultSim(600) ) rc = SQLITE_NOMEM;
    if( (rc&0xff)==SQLITE_READONLY ){
    }else if( (rc&0xff)==SQLITE_READONLY ){
      pWal->readOnly |= WAL_SHM_RDONLY;
      if( rc==SQLITE_READONLY ){
        rc = SQLITE_OK;
      }
    }
  }

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
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







+


















+
+
+
+






+
+
+
+
+
+
+
+
+
+
+
+
+





-
+





-
+

+







    s2 = aIn[1];
  }else{
    s1 = s2 = 0;
  }

  assert( nByte>=8 );
  assert( (nByte&0x00000007)==0 );
  assert( nByte<=65536 );

  if( nativeCksum ){
    do {
      s1 += *aData++ + s2;
      s2 += *aData++ + s1;
    }while( aData<aEnd );
  }else{
    do {
      s1 += BYTESWAP32(aData[0]) + s2;
      s2 += BYTESWAP32(aData[1]) + s1;
      aData += 2;
    }while( aData<aEnd );
  }

  aOut[0] = s1;
  aOut[1] = s2;
}

/*
** If there is the possibility of concurrent access to the SHM file
** from multiple threads and/or processes, then do a memory barrier.
*/
static void walShmBarrier(Wal *pWal){
  if( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE ){
    sqlite3OsShmBarrier(pWal->pDbFd);
  }
}

/*
** Add the SQLITE_NO_TSAN as part of the return-type of a function
** definition as a hint that the function contains constructs that
** might give false-positive TSAN warnings.
**
** See tag-20200519-1.
*/
#if defined(__clang__) && !defined(SQLITE_NO_TSAN)
# define SQLITE_NO_TSAN __attribute__((no_sanitize_thread))
#else
# define SQLITE_NO_TSAN
#endif

/*
** Write the header information in pWal->hdr into the wal-index.
**
** The checksum on pWal->hdr is updated before it is written.
*/
static void walIndexWriteHdr(Wal *pWal){
static SQLITE_NO_TSAN void walIndexWriteHdr(Wal *pWal){
  volatile WalIndexHdr *aHdr = walIndexHdr(pWal);
  const int nCksum = offsetof(WalIndexHdr, aCksum);

  assert( pWal->writeLock );
  pWal->hdr.isInit = 1;
  pWal->hdr.iVersion = WALINDEX_MAX_VERSION;
  assert( pWal->hdr.iVersion==WAL_VERSION1||pWal->hdr.iVersion==WAL_VERSION2 );
  walChecksumBytes(1, (u8*)&pWal->hdr, nCksum, 0, pWal->hdr.aCksum);
  /* Possible TSAN false-positive.  See tag-20200519-1 */
  memcpy((void*)&aHdr[1], (const void*)&pWal->hdr, sizeof(WalIndexHdr));
  walShmBarrier(pWal);
  memcpy((void*)&aHdr[0], (const void*)&pWal->hdr, sizeof(WalIndexHdr));
}

/*
** This function encodes a single frame header and writes it to a buffer
790
791
792
793
794
795
796
797

798
799
800
801
802
803
804
1138
1139
1140
1141
1142
1143
1144

1145
1146
1147
1148
1149
1150
1151
1152







-
+







  */
  pgno = sqlite3Get4byte(&aFrame[0]);
  if( pgno==0 ){
    return 0;
  }

  /* A frame is only valid if a checksum of the WAL header,
  ** all prior frams, the first 16 bytes of this frame-header, 
  ** all prior frames, the first 16 bytes of this frame-header, 
  ** and the frame-data matches the checksum in the last 8 
  ** bytes of this frame-header.
  */
  nativeCksum = (pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN);
  walChecksumBytes(nativeCksum, aFrame, 8, aCksum, aCksum);
  walChecksumBytes(nativeCksum, aData, pWal->szPage, aCksum, aCksum);
  if( aCksum[0]!=sqlite3Get4byte(&aFrame[16]) 
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
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







-
+















-
+







static int walLockShared(Wal *pWal, int lockIdx){
  int rc;
  if( pWal->exclusiveMode ) return SQLITE_OK;
  rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1,
                        SQLITE_SHM_LOCK | SQLITE_SHM_SHARED);
  WALTRACE(("WAL%p: acquire SHARED-%s %s\n", pWal,
            walLockName(lockIdx), rc ? "failed" : "ok"));
  VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && rc!=SQLITE_BUSY); )
  VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); )
  return rc;
}
static void walUnlockShared(Wal *pWal, int lockIdx){
  if( pWal->exclusiveMode ) return;
  (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1,
                         SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED);
  WALTRACE(("WAL%p: release SHARED-%s\n", pWal, walLockName(lockIdx)));
}
static int walLockExclusive(Wal *pWal, int lockIdx, int n){
  int rc;
  if( pWal->exclusiveMode ) return SQLITE_OK;
  rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, n,
                        SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE);
  WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal,
            walLockName(lockIdx), n, rc ? "failed" : "ok"));
  VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && rc!=SQLITE_BUSY); )
  VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); )
  return rc;
}
static void walUnlockExclusive(Wal *pWal, int lockIdx, int n){
  if( pWal->exclusiveMode ) return;
  (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, n,
                         SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE);
  WALTRACE(("WAL%p: release EXCLUSIVE-%s cnt=%d\n", pWal,
913
914
915
916
917
918
919
920
921


922
923
924
925
926
927
928
929
930
931
932
933

934
935
936
937
938
939
940

941

942
943
944
































945
946
947
948
949
950
951
952
953
954
955
956
957
958
959

960
961
















962
963
964
965
966
967
968
969
970
971
972




973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990


991








992
993
994
995



996
997

998
999
1000
1001

1002
1003
1004
1005




1006
1007
1008
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
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
1318
1319


1320
1321
1322
1323
1324
1325
1326
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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
1430
1431

1432



1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443

1444
1445

1446
1447

1448
1449
1450
1451
1452
1453

1454
1455
1456
1457

1458
1459
1460
1461


1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479

1480
1481
1482
1483
1484
1485
1486



1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497

1498
1499

1500
1501
1502
1503
1504
1505
1506
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
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
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
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
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762


1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780






1781
1782
1783
1784
1785
1786


1787
1788



1789
1790
1791


1792




1793






1794
1795
1796
1797
1798


1799






1800





1801
1802
1803











1804



1805
1806




1807
1808






1809





1810



1811
1812




1813
1814
1815





1816






1817




1818




1819
1820





1821
1822





1823
1824

1825


1826


1827
1828



1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875


1876
1877
1878
1879





1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902

1903

1904
1905




1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919

1920
1921

1922
1923
1924
1925

1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947







-
-
+
+











-
+







+
-
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+















+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+











+
+
+
+


















+
+

+
+
+
+
+
+
+
+

-
-
-
+
+
+

-
+



-
+

-
-
-
+
+
+
+




-
+








-
+
-
-
-
+
+
+








-
+

-
+

-
+





-




-
+


+
-
-
+
+
+
+
+
+
+
+
+









-
+






-
-
-
+
+
+








-
+

-
+







-
-
+
+



















-
+



-
+

-
+





+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+













-
-

+
+
+
+













-
-
-
-
-
-






-
-
+
+
-
-
-
+
+
+
-
-
+
-
-
-
-
+
-
-
-
-
-
-
+
+
+
+
+
-
-
+
-
-
-
-
-
-
+
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+
+
-
-
-
-
+
+
-
-
-
-
-
-
+
-
-
-
-
-
+
-
-
-
+
+
-
-
-
-
+
+
+
-
-
-
-
-
+
-
-
-
-
-
-
+
-
-
-
-
+
-
-
-
-
+
+
-
-
-
-
-
+
+
-
-
-
-
-


-
+
-
-
+
-
-


-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
-
+
+


-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
+
-

+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+



-


-




-
+












+
+







**
** Set output variable pLoc->aHash to point to the start of the hash table
** in the wal-index file. Set pLoc->iZero to one less than the frame 
** number of the first frame indexed by this hash table. If a
** slot in the hash table is set to N, it refers to frame number 
** (pLoc->iZero+N) in the log.
**
** Finally, set pLoc->aPgno so that pLoc->aPgno[1] is the page number of the
** first frame indexed by the hash table, frame (pLoc->iZero+1).
** Finally, set pLoc->aPgno so that pLoc->aPgno[0] is the page number of the
** first frame indexed by the hash table, frame (pLoc->iZero).
*/
static int walHashGet(
  Wal *pWal,                      /* WAL handle */
  int iHash,                      /* Find the iHash'th table */
  WalHashLoc *pLoc                /* OUT: Hash table location */
){
  int rc;                         /* Return code */

  rc = walIndexPage(pWal, iHash, &pLoc->aPgno);
  assert( rc==SQLITE_OK || iHash>0 );

  if( rc==SQLITE_OK ){
  if( pLoc->aPgno ){
    pLoc->aHash = (volatile ht_slot *)&pLoc->aPgno[HASHTABLE_NPAGE];
    if( iHash==0 ){
      pLoc->aPgno = &pLoc->aPgno[WALINDEX_HDR_SIZE/sizeof(u32)];
      pLoc->iZero = 0;
    }else{
      pLoc->iZero = HASHTABLE_NPAGE_ONE + (iHash-1)*HASHTABLE_NPAGE;
    }
  }else if( NEVER(rc==SQLITE_OK) ){
    pLoc->aPgno = &pLoc->aPgno[-1];
    rc = SQLITE_ERROR;
  }
  return rc;
}

static u32 walExternalEncode(int iWal, u32 iFrame){
  u32 iRet;
  if( iWal ){
    iRet = HASHTABLE_NPAGE_ONE + iFrame;
    iRet += ((iFrame-1) / HASHTABLE_NPAGE) * HASHTABLE_NPAGE;
  }else{
    iRet = iFrame;
    iFrame += HASHTABLE_NPAGE - HASHTABLE_NPAGE_ONE;
    iRet += ((iFrame-1) / HASHTABLE_NPAGE) * HASHTABLE_NPAGE;
  }
  return iRet;
}

/*
** Parameter iExternal is an external frame identifier. This function
** transforms it to a wal file number (0 or 1) and frame number within
** this wal file (reported via output parameter *piRead).
*/
static int walExternalDecode(u32 iExternal, u32 *piRead){
  int iHash = (iExternal+HASHTABLE_NPAGE-HASHTABLE_NPAGE_ONE-1)/HASHTABLE_NPAGE;

  if( 0==(iHash & 0x01) ){
    /* A frame in wal file 0 */
    *piRead = (iExternal <= HASHTABLE_NPAGE_ONE) ? iExternal :
      iExternal - (iHash/2) * HASHTABLE_NPAGE;
    return 0;
  }

  *piRead = iExternal - HASHTABLE_NPAGE_ONE - ((iHash-1)/2) * HASHTABLE_NPAGE;
  return 1;
}

/*
** Return the number of the wal-index page that contains the hash-table
** and page-number array that contain entries corresponding to WAL frame
** iFrame. The wal-index is broken up into 32KB pages. Wal-index pages 
** are numbered starting from 0.
*/
static int walFramePage(u32 iFrame){
  int iHash = (iFrame+HASHTABLE_NPAGE-HASHTABLE_NPAGE_ONE-1) / HASHTABLE_NPAGE;
  assert( (iHash==0 || iFrame>HASHTABLE_NPAGE_ONE)
       && (iHash>=1 || iFrame<=HASHTABLE_NPAGE_ONE)
       && (iHash<=1 || iFrame>(HASHTABLE_NPAGE_ONE+HASHTABLE_NPAGE))
       && (iHash>=2 || iFrame<=HASHTABLE_NPAGE_ONE+HASHTABLE_NPAGE)
       && (iHash<=2 || iFrame>(HASHTABLE_NPAGE_ONE+2*HASHTABLE_NPAGE))
  );
  assert( iHash>=0 );
  return iHash;
}

/*
** Return the index of the hash-table corresponding to frame iFrame of wal
** file iWal.
*/
static int walFramePage2(int iWal, u32 iFrame){
  int iRet;
  assert( iWal==0 || iWal==1 );
  assert( iFrame>0 );
  if( iWal==0 ){
    iRet = 2*((iFrame+HASHTABLE_NPAGE-HASHTABLE_NPAGE_ONE-1)/HASHTABLE_NPAGE);
  }else{
    iRet = 1 + 2 * ((iFrame-1) / HASHTABLE_NPAGE);
  }
  return iRet;
}

/*
** Return the page number associated with frame iFrame in this WAL.
*/
static u32 walFramePgno(Wal *pWal, u32 iFrame){
  int iHash = walFramePage(iFrame);
  if( iHash==0 ){
    return pWal->apWiData[0][WALINDEX_HDR_SIZE/sizeof(u32) + iFrame - 1];
  }
  return pWal->apWiData[iHash][(iFrame-1-HASHTABLE_NPAGE_ONE)%HASHTABLE_NPAGE];
}

static u32 walFramePgno2(Wal *pWal, int iWal, u32 iFrame){
  return walFramePgno(pWal, walExternalEncode(iWal, iFrame));
}

/*
** Remove entries from the hash table that point to WAL slots greater
** than pWal->hdr.mxFrame.
**
** This function is called whenever pWal->hdr.mxFrame is decreased due
** to a rollback or savepoint.
**
** At most only the hash table containing pWal->hdr.mxFrame needs to be
** updated.  Any later hash tables will be automatically cleared when
** pWal->hdr.mxFrame advances to the point where those hash tables are
** 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 iWal = walidxGetFile(&pWal->hdr);
  u32 mxFrame = walidxGetMxFrame(&pWal->hdr, iWal);

  u32 iExternal;
  if( isWalMode2(pWal) ){
    iExternal = walExternalEncode(iWal, mxFrame);
  }else{
    assert( iWal==0 );
    iExternal = mxFrame;
  }

  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 );
  testcase( mxFrame==HASHTABLE_NPAGE_ONE-1 );
  testcase( mxFrame==HASHTABLE_NPAGE_ONE );
  testcase( mxFrame==HASHTABLE_NPAGE_ONE+1 );

  if( pWal->hdr.mxFrame==0 ) return;
  if( 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.
  ** 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)] );
  walHashGet(pWal, walFramePage(pWal->hdr.mxFrame), &sLoc);
  assert( pWal->nWiData>walFramePage(iExternal) );
  assert( pWal->apWiData[walFramePage(iExternal)] );
  i = walHashGet(pWal, walFramePage(iExternal), &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;
  iLimit = iExternal - sLoc.iZero;
  assert( iLimit>0 );
  for(i=0; i<HASHTABLE_NSLOT; i++){
    if( sLoc.aHash[i]>iLimit ){
      sLoc.aHash[i] = 0;
    }
  }
  
  /* Zero the entries in the aPgno array that correspond to frames with
  ** frame numbers greater than pWal->hdr.mxFrame. 
  ** frame numbers greater than pWal->hdr.mxFrame.  */
  */
  nByte = (int)((char *)sLoc.aHash - (char *)&sLoc.aPgno[iLimit+1]);
  memset((void *)&sLoc.aPgno[iLimit+1], 0, nByte);
  nByte = (int)((char *)sLoc.aHash - (char *)&sLoc.aPgno[iLimit]);
  assert( nByte>=0 );
  memset((void *)&sLoc.aPgno[iLimit], 0, nByte);

#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
  /* Verify that the every entry in the mapping region is still reachable
  ** via the hash table even after the cleanup.
  */
  if( iLimit ){
    int j;           /* Loop counter */
    int iKey;        /* Hash key */
    for(j=1; j<=iLimit; j++){
    for(j=0; j<iLimit; j++){
      for(iKey=walHash(sLoc.aPgno[j]);sLoc.aHash[iKey];iKey=walNextHash(iKey)){
        if( sLoc.aHash[iKey]==j ) break;
        if( sLoc.aHash[iKey]==j+1 ) break;
      }
      assert( sLoc.aHash[iKey]==j );
      assert( sLoc.aHash[iKey]==j+1 );
    }
  }
#endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */
}


/*
** Set an entry in the wal-index that will map database page number
** pPage into WAL frame iFrame.
*/
static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
static int walIndexAppend(Wal *pWal, int iWal, u32 iFrame, u32 iPage){
  int rc;                         /* Return code */
  WalHashLoc sLoc;                /* Wal-index hash table location */
  u32 iExternal;

  rc = walHashGet(pWal, walFramePage(iFrame), &sLoc);
  
  if( isWalMode2(pWal) ){
    iExternal = walExternalEncode(iWal, iFrame);
  }else{
    assert( iWal==0 );
    iExternal = iFrame;
  }

  rc = walHashGet(pWal, walFramePage(iExternal), &sLoc);

  /* Assuming the wal-index file was successfully mapped, populate the
  ** page number array and hash table entry.
  */
  if( rc==SQLITE_OK ){
    int iKey;                     /* Hash table key */
    int idx;                      /* Value to write to hash-table slot */
    int nCollide;                 /* Number of hash collisions */

    idx = iFrame - sLoc.iZero;
    idx = iExternal - sLoc.iZero;
    assert( idx <= HASHTABLE_NSLOT/2 + 1 );
    
    /* If this is the first entry to be added to this hash-table, zero the
    ** entire hash table and aPgno[] array before proceeding. 
    */
    if( idx==1 ){
      int nByte = (int)((u8 *)&sLoc.aHash[HASHTABLE_NSLOT]
                               - (u8 *)&sLoc.aPgno[1]);
      memset((void*)&sLoc.aPgno[1], 0, nByte);
      int nByte = (int)((u8*)&sLoc.aHash[HASHTABLE_NSLOT] - (u8*)sLoc.aPgno);
      assert( nByte>=0 );
      memset((void*)sLoc.aPgno, 0, nByte);
    }

    /* If the entry in aPgno[] is already set, then the previous writer
    ** must have exited unexpectedly in the middle of a transaction (after
    ** writing one or more dirty pages to the WAL to free up memory). 
    ** Remove the remnants of that writers uncommitted transaction from 
    ** the hash-table before writing any new entries.
    */
    if( sLoc.aPgno[idx] ){
    if( sLoc.aPgno[idx-1] ){
      walCleanupHash(pWal);
      assert( !sLoc.aPgno[idx] );
      assert( !sLoc.aPgno[idx-1] );
    }

    /* Write the aPgno[] array entry and the hash-table slot. */
    nCollide = idx;
    for(iKey=walHash(iPage); sLoc.aHash[iKey]; iKey=walNextHash(iKey)){
      if( (nCollide--)==0 ) return SQLITE_CORRUPT_BKPT;
    }
    sLoc.aPgno[idx] = iPage;
    sLoc.aHash[iKey] = (ht_slot)idx;
    sLoc.aPgno[idx-1] = iPage;
    AtomicStore(&sLoc.aHash[iKey], (ht_slot)idx);

#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
    /* Verify that the number of entries in the hash table exactly equals
    ** the number of entries in the mapping region.
    */
    {
      int i;           /* Loop counter */
      int nEntry = 0;  /* Number of entries in the hash table */
      for(i=0; i<HASHTABLE_NSLOT; i++){ if( sLoc.aHash[i] ) nEntry++; }
      assert( nEntry==idx );
    }

    /* Verify that the every entry in the mapping region is reachable
    ** via the hash table.  This turns out to be a really, really expensive
    ** thing to check, so only do this occasionally - not on every
    ** iteration.
    */
    if( (idx&0x3ff)==0 ){
      int i;           /* Loop counter */
      for(i=1; i<=idx; i++){
      for(i=0; i<idx; i++){
        for(iKey=walHash(sLoc.aPgno[i]);
            sLoc.aHash[iKey];
            iKey=walNextHash(iKey)){
          if( sLoc.aHash[iKey]==i ) break;
          if( sLoc.aHash[iKey]==i+1 ) break;
        }
        assert( sLoc.aHash[iKey]==i );
        assert( sLoc.aHash[iKey]==i+1 );
      }
    }
#endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */
  }

  return rc;

  return rc;
}

}

/*
** Recover a single wal file - *-wal if iWal==0, or *-wal2 if iWal==1.
*/
static int walIndexRecoverOne(Wal *pWal, int iWal, u32 *pnCkpt, int *pbZero){
  i64 nSize;                      /* Size of log file */
  u32 aFrameCksum[2] = {0, 0};
  int rc;
  sqlite3_file *pWalFd = pWal->apWalFd[iWal];

  assert( iWal==0 || iWal==1 );

  memset(&pWal->hdr, 0, sizeof(WalIndexHdr));
  sqlite3FastRandomness(&pWal->sPrng, 8, pWal->hdr.aSalt);

  rc = sqlite3OsFileSize(pWalFd, &nSize);
  if( rc==SQLITE_OK ){
    if( nSize>WAL_HDRSIZE ){
      u8 aBuf[WAL_HDRSIZE];         /* Buffer to load WAL header into */
      u32 *aPrivate = 0;            /* Heap copy of *-shm pg being populated */
      u8 *aFrame = 0;               /* Malloc'd buffer to load entire frame */
      int szFrame;                  /* Number of bytes in buffer aFrame[] */
      u8 *aData;                    /* Pointer to data part of aFrame buffer */
      int szPage;                   /* Page size according to the log */
      u32 magic;                    /* Magic value read from WAL header */
      u32 version;                  /* Magic value read from WAL header */
      int isValid;                  /* True if this frame is valid */
      int iPg;                      /* Current 32KB wal-index page */
      int iLastFrame;               /* Last frame in wal, based on size alone */
      int iLastPg;                  /* Last shm page used by this wal */
  
      /* Read in the WAL header. */
      rc = sqlite3OsRead(pWalFd, aBuf, WAL_HDRSIZE, 0);
      if( rc!=SQLITE_OK ){
        return rc;
      }
  
      /* If the database page size is not a power of two, or is greater than
      ** SQLITE_MAX_PAGE_SIZE, conclude that the WAL file contains no valid 
      ** data. Similarly, if the 'magic' value is invalid, ignore the whole
      ** WAL file.
      */
      magic = sqlite3Get4byte(&aBuf[0]);
      szPage = sqlite3Get4byte(&aBuf[8]);
      if( (magic&0xFFFFFFFE)!=WAL_MAGIC 
       || szPage&(szPage-1) 
       || szPage>SQLITE_MAX_PAGE_SIZE 
       || szPage<512 
      ){
        return SQLITE_OK;
      }
      pWal->hdr.bigEndCksum = (u8)(magic&0x00000001);
      pWal->szPage = szPage;
  
      /* Verify that the WAL header checksum is correct */
      walChecksumBytes(pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN, 
          aBuf, WAL_HDRSIZE-2*4, 0, pWal->hdr.aFrameCksum
      );
      if( pWal->hdr.aFrameCksum[0]!=sqlite3Get4byte(&aBuf[24])
       || pWal->hdr.aFrameCksum[1]!=sqlite3Get4byte(&aBuf[28])
      ){
        return SQLITE_OK;
      }
  
      memcpy(&pWal->hdr.aSalt, &aBuf[16], 8);
      *pnCkpt = sqlite3Get4byte(&aBuf[12]);
  
      /* Verify that the version number on the WAL format is one that
      ** are able to understand */
      version = sqlite3Get4byte(&aBuf[4]);
      if( version!=WAL_VERSION1 && version!=WAL_VERSION2 ){
        return SQLITE_CANTOPEN_BKPT;
      }
      pWal->hdr.iVersion = version;
  
      /* Malloc a buffer to read frames into. */
      szFrame = szPage + WAL_FRAME_HDRSIZE;
      aFrame = (u8 *)sqlite3_malloc64(szFrame + WALINDEX_PGSZ);
      if( !aFrame ){
        return SQLITE_NOMEM_BKPT;
      }
      aData = &aFrame[WAL_FRAME_HDRSIZE];
      aPrivate = (u32*)&aData[szPage];
  
      /* Read all frames from the log file. */
      iLastFrame = (nSize - WAL_HDRSIZE) / szFrame;
      if( version==WAL_VERSION2 ){
        iLastPg = walFramePage2(iWal, iLastFrame);
      }else{
        iLastPg = walFramePage(iLastFrame);
      }
      for(iPg=iWal; iPg<=iLastPg; iPg+=(version==WAL_VERSION2 ? 2 : 1)){
        u32 *aShare;
        int iFrame;                 /* Index of last frame read */
        int iLast;
        int iFirst;
        int nHdr, nHdr32;

        rc = walIndexPage(pWal, iPg, (volatile u32**)&aShare);
        assert( aShare!=0 || rc!=SQLITE_OK );
        if( aShare==0 ) break;
        pWal->apWiData[iPg] = aPrivate;

        if( iWal ){
          assert( version==WAL_VERSION2 );
          iFirst = 1 + (iPg/2)*HASHTABLE_NPAGE;
          iLast = iFirst + HASHTABLE_NPAGE - 1;
        }else{
          int i2 = (version==WAL_VERSION2) ? (iPg/2) : iPg;
          iLast = HASHTABLE_NPAGE_ONE+i2*HASHTABLE_NPAGE;
          iFirst = 1 + (i2==0?0:HASHTABLE_NPAGE_ONE+(i2-1)*HASHTABLE_NPAGE);
        }
        iLast = MIN(iLast, iLastFrame);

        for(iFrame=iFirst; iFrame<=iLast; iFrame++){
          i64 iOffset = walFrameOffset(iFrame, szPage);
          u32 pgno;                 /* Database page number for frame */
          u32 nTruncate;            /* dbsize field from frame header */

          /* Read and decode the next log frame. */
          rc = sqlite3OsRead(pWalFd, aFrame, szFrame, iOffset);
          if( rc!=SQLITE_OK ) break;
          isValid = walDecodeFrame(pWal, &pgno, &nTruncate, aData, aFrame);
          if( !isValid ) break;
          rc = walIndexAppend(pWal, iWal, iFrame, pgno);
          if( NEVER(rc!=SQLITE_OK) ) break;
  
          /* If nTruncate is non-zero, this is a commit record. */
          if( nTruncate ){
            pWal->hdr.mxFrame = iFrame;
            pWal->hdr.nPage = nTruncate;
            pWal->hdr.szPage = (u16)((szPage&0xff00) | (szPage>>16));
            testcase( szPage<=32768 );
            testcase( szPage>=65536 );
            aFrameCksum[0] = pWal->hdr.aFrameCksum[0];
            aFrameCksum[1] = pWal->hdr.aFrameCksum[1];
          }
        }
        pWal->apWiData[iPg] = aShare;
        nHdr = (iPg==0 ? WALINDEX_HDR_SIZE : 0);
        nHdr32 = nHdr / sizeof(u32);
#ifndef SQLITE_SAFER_WALINDEX_RECOVERY
        /* Memcpy() should work fine here, on all reasonable implementations.
        ** Technically, memcpy() might change the destination to some
        ** intermediate value before setting to the final value, and that might
        ** cause a concurrent reader to malfunction.  Memcpy() is allowed to
        ** do that, according to the spec, but no memcpy() implementation that
        ** we know of actually does that, which is why we say that memcpy()
        ** is safe for this.  Memcpy() is certainly a lot faster.
        */
        memcpy(&aShare[nHdr32], &aPrivate[nHdr32], WALINDEX_PGSZ-nHdr);
#else
        /* In the event that some platform is found for which memcpy()
        ** changes the destination to some intermediate value before
        ** setting the final value, this alternative copy routine is
        ** provided.
        */
        {
          int i;
          for(i=nHdr32; i<WALINDEX_PGSZ/sizeof(u32); i++){
            if( aShare[i]!=aPrivate[i] ){
              /* Atomic memory operations are not required here because if
              ** the value needs to be changed, that means it is not being
              ** accessed concurrently. */
              aShare[i] = aPrivate[i];
            }
          }
        }
#endif
        if( iFrame<=iLast ) break;
      }
  
      sqlite3_free(aFrame);
    }else if( pbZero ){
      *pbZero = 1;
    }
  }

  pWal->hdr.aFrameCksum[0] = aFrameCksum[0];
  pWal->hdr.aFrameCksum[1] = aFrameCksum[1];

  return rc;
}

static int walOpenWal2(Wal *pWal){
  int rc = SQLITE_OK;
  if( !isOpen(pWal->apWalFd[1]) ){
    int f = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_WAL);
    rc = sqlite3OsOpen(pWal->pVfs, pWal->zWalName2, pWal->apWalFd[1], f, &f);
  }
  return rc;
}

static int walTruncateWal2(Wal *pWal){
  int bIs;
  int rc;
  assert( !isOpen(pWal->apWalFd[1]) );
  rc = sqlite3OsAccess(pWal->pVfs, pWal->zWalName2, SQLITE_ACCESS_EXISTS, &bIs);
  if( rc==SQLITE_OK && bIs ){
    rc = walOpenWal2(pWal);
    if( rc==SQLITE_OK ){
      rc = sqlite3OsTruncate(pWal->apWalFd[1], 0);
      sqlite3OsClose(pWal->apWalFd[1]);
    }
  }
  return rc;
}

/*
** Recover the wal-index by reading the write-ahead log file. 
**
** This routine first tries to establish an exclusive lock on the
** wal-index to prevent other threads/processes from doing anything
** with the WAL or wal-index while recovery is running.  The
** WAL_RECOVER_LOCK is also held so that other threads will know
** that this thread is running recovery.  If unable to establish
** the necessary locks, this routine returns SQLITE_BUSY.
*/
static int walIndexRecover(Wal *pWal){
  int rc;                         /* Return Code */
  i64 nSize;                      /* Size of log file */
  u32 aFrameCksum[2] = {0, 0};
  int iLock;                      /* Lock offset to lock for checkpoint */
  u32 nCkpt1 = 0xFFFFFFFF;
  u32 nCkpt2 = 0xFFFFFFFF;
  int bZero = 0;
  WalIndexHdr hdr;

  /* Obtain an exclusive lock on all byte in the locking range not already
  ** locked by the caller. The caller is guaranteed to have locked the
  ** WAL_WRITE_LOCK byte, and may have also locked the WAL_CKPT_LOCK byte.
  ** If successful, the same bytes that are locked here are concurrent before
  ** this function returns.
  */
  assert( pWal->ckptLock==1 || pWal->ckptLock==0 );
  assert( WAL_ALL_BUT_WRITE==WAL_WRITE_LOCK+1 );
  assert( WAL_CKPT_LOCK==WAL_ALL_BUT_WRITE );
  assert( pWal->writeLock );
  iLock = WAL_ALL_BUT_WRITE + pWal->ckptLock;
  rc = walLockExclusive(pWal, iLock, WAL_READ_LOCK(0)-iLock);
  if( rc==SQLITE_OK ){
    rc = walLockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
    if( rc!=SQLITE_OK ){
      walUnlockExclusive(pWal, iLock, WAL_READ_LOCK(0)-iLock);
    }
  }
  if( rc ){
    return rc;
  }

  WALTRACE(("WAL%p: recovery begin...\n", pWal));

  memset(&pWal->hdr, 0, sizeof(WalIndexHdr));

  /* Recover the *-wal file. If a valid version-1 header is recovered
  ** from it, do not open the *-wal2 file. Even if it exists.
  rc = sqlite3OsFileSize(pWal->pWalFd, &nSize);
  if( rc!=SQLITE_OK ){
    goto recovery_error;
  **
  ** Otherwise, if the *-wal2 file exists or if the "wal2" flag was 
  ** specified when sqlite3WalOpen() was called, open and recover
  }

  ** the *-wal2 file. Except, if the *-wal file was zero bytes in size,
  if( nSize>WAL_HDRSIZE ){
    u8 aBuf[WAL_HDRSIZE];         /* Buffer to load WAL header into */
    u8 *aFrame = 0;               /* Malloc'd buffer to load entire frame */
    int szFrame;                  /* Number of bytes in buffer aFrame[] */
  ** truncate the *-wal2 to zero bytes in size.
    u8 *aData;                    /* Pointer to data part of aFrame buffer */
    int iFrame;                   /* Index of last frame read */
    i64 iOffset;                  /* Next offset to read from log file */
    int szPage;                   /* Page size according to the log */
    u32 magic;                    /* Magic value read from WAL header */
    u32 version;                  /* Magic value read from WAL header */
  **
  ** After this block has run, if the *-wal2 file is open the system
  ** starts up in VERSION2 mode. In this case pWal->hdr contains the 
  ** wal-index header considering only *-wal2. Stack variable hdr
  ** contains the wal-index header considering only *-wal. The hash 
    int isValid;                  /* True if this frame is valid */

  ** tables are populated for both.  
    /* Read in the WAL header. */
    rc = sqlite3OsRead(pWal->pWalFd, aBuf, WAL_HDRSIZE, 0);
    if( rc!=SQLITE_OK ){
      goto recovery_error;
    }

  **
    /* If the database page size is not a power of two, or is greater than
    ** SQLITE_MAX_PAGE_SIZE, conclude that the WAL file contains no valid 
    ** data. Similarly, if the 'magic' value is invalid, ignore the whole
    ** WAL file.
    */
  ** Or, if the *-wal2 file is not open, start up in VERSION1 mode.
  ** pWal->hdr is already populated.
  */
    magic = sqlite3Get4byte(&aBuf[0]);
    szPage = sqlite3Get4byte(&aBuf[8]);
    if( (magic&0xFFFFFFFE)!=WAL_MAGIC 
     || szPage&(szPage-1) 
     || szPage>SQLITE_MAX_PAGE_SIZE 
     || szPage<512 
    ){
      goto finished;
    }
    pWal->hdr.bigEndCksum = (u8)(magic&0x00000001);
    pWal->szPage = szPage;
  rc = walIndexRecoverOne(pWal, 0, &nCkpt1, &bZero);
    pWal->nCkpt = sqlite3Get4byte(&aBuf[12]);
    memcpy(&pWal->hdr.aSalt, &aBuf[16], 8);

  assert( pWal->hdr.iVersion==0 
      || pWal->hdr.iVersion==WAL_VERSION1 
    /* Verify that the WAL header checksum is correct */
    walChecksumBytes(pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN, 
        aBuf, WAL_HDRSIZE-2*4, 0, pWal->hdr.aFrameCksum
    );
      || pWal->hdr.iVersion==WAL_VERSION2 
  );
    if( pWal->hdr.aFrameCksum[0]!=sqlite3Get4byte(&aBuf[24])
     || pWal->hdr.aFrameCksum[1]!=sqlite3Get4byte(&aBuf[28])
    ){
      goto finished;
    }

  if( rc==SQLITE_OK && bZero ){
    /* Verify that the version number on the WAL format is one that
    ** are able to understand */
    version = sqlite3Get4byte(&aBuf[4]);
    if( version!=WAL_MAX_VERSION ){
      rc = SQLITE_CANTOPEN_BKPT;
    rc = walTruncateWal2(pWal);
      goto finished;
    }

  }
  if( rc==SQLITE_OK && pWal->hdr.iVersion!=WAL_VERSION1 ){
    /* Malloc a buffer to read frames into. */
    szFrame = szPage + WAL_FRAME_HDRSIZE;
    aFrame = (u8 *)sqlite3_malloc64(szFrame);
    if( !aFrame ){
    int bOpen = 1;
    sqlite3_vfs *pVfs = pWal->pVfs;
    if( pWal->hdr.iVersion==0 && pWal->bWal2==0 ){
      rc = SQLITE_NOMEM_BKPT;
      goto recovery_error;
    }
    aData = &aFrame[WAL_FRAME_HDRSIZE];

      rc = sqlite3OsAccess(pVfs, pWal->zWalName2, SQLITE_ACCESS_EXISTS, &bOpen);
    /* Read all frames from the log file. */
    iFrame = 0;
    for(iOffset=WAL_HDRSIZE; (iOffset+szFrame)<=nSize; iOffset+=szFrame){
      u32 pgno;                   /* Database page number for frame */
      u32 nTruncate;              /* dbsize field from frame header */

    }
      /* Read and decode the next log frame. */
      iFrame++;
      rc = sqlite3OsRead(pWal->pWalFd, aFrame, szFrame, iOffset);
      if( rc!=SQLITE_OK ) break;
    if( rc==SQLITE_OK && bOpen ){
      isValid = walDecodeFrame(pWal, &pgno, &nTruncate, aData, aFrame);
      if( !isValid ) break;
      rc = walIndexAppend(pWal, iFrame, pgno);
      if( rc!=SQLITE_OK ) break;
      rc = walOpenWal2(pWal);
      if( rc==SQLITE_OK ){

      /* If nTruncate is non-zero, this is a commit record. */
      if( nTruncate ){
        pWal->hdr.mxFrame = iFrame;
        pWal->hdr.nPage = nTruncate;
        hdr = pWal->hdr;
        rc = walIndexRecoverOne(pWal, 1, &nCkpt2, 0);
        pWal->hdr.szPage = (u16)((szPage&0xff00) | (szPage>>16));
        testcase( szPage<=32768 );
        testcase( szPage>=65536 );
        aFrameCksum[0] = pWal->hdr.aFrameCksum[0];
        aFrameCksum[1] = pWal->hdr.aFrameCksum[1];
      }
    }

  }
    sqlite3_free(aFrame);
  }


finished:
  if( rc==SQLITE_OK ){
    volatile WalCkptInfo *pInfo;
    int i;
    pWal->hdr.aFrameCksum[0] = aFrameCksum[0];
    pWal->hdr.aFrameCksum[1] = aFrameCksum[1];

    if( isOpen(pWal->apWalFd[1]) ){
      /* The case where *-wal2 may follow *-wal */
      if( nCkpt2<=0x0F && nCkpt2==nCkpt1+1 ){
        if( pWal->hdr.mxFrame
         && sqlite3Get4byte((u8*)(&pWal->hdr.aSalt[0]))==hdr.aFrameCksum[0]
         && sqlite3Get4byte((u8*)(&pWal->hdr.aSalt[1]))==hdr.aFrameCksum[1]
        ){
          walidxSetFile(&pWal->hdr, 1);
          walidxSetMxFrame(&pWal->hdr, 1, pWal->hdr.mxFrame);
          walidxSetMxFrame(&pWal->hdr, 0, hdr.mxFrame);
        }else{
          pWal->hdr = hdr;
        }
      }else

      /* When *-wal may follow *-wal2 */
      if( (nCkpt2==0x0F && nCkpt1==0) || (nCkpt2<0x0F && nCkpt2==nCkpt1-1) ){
        if( hdr.mxFrame
         && sqlite3Get4byte((u8*)(&hdr.aSalt[0]))==pWal->hdr.aFrameCksum[0]
         && sqlite3Get4byte((u8*)(&hdr.aSalt[1]))==pWal->hdr.aFrameCksum[1]
        ){
          SWAP(WalIndexHdr, pWal->hdr, hdr);
          walidxSetMxFrame(&pWal->hdr, 1, hdr.mxFrame);
        }else{
          walidxSetFile(&pWal->hdr, 1);
          walidxSetMxFrame(&pWal->hdr, 1, pWal->hdr.mxFrame);
          walidxSetMxFrame(&pWal->hdr, 0, 0);
        }
      }else

      /* Fallback */
      if( nCkpt1<=nCkpt2 ){
        pWal->hdr = hdr;
      }else{
        walidxSetFile(&pWal->hdr, 1);
        walidxSetMxFrame(&pWal->hdr, 1, pWal->hdr.mxFrame);
        walidxSetMxFrame(&pWal->hdr, 0, 0);
      }
      pWal->hdr.iVersion = WAL_VERSION2;
    }else{
      pWal->hdr.iVersion = WAL_VERSION1;
    }

    walIndexWriteHdr(pWal);

    /* Reset the checkpoint-header. This is safe because this thread is 
    ** currently holding locks that exclude all other readers, writers and
    ** checkpointers.
    ** currently holding locks that exclude all other writers and 
    ** checkpointers. Then set the values of read-mark slots 1 through N.
    */
    pInfo = walCkptInfo(pWal);
    pInfo->nBackfill = 0;
    pInfo->nBackfillAttempted = pWal->hdr.mxFrame;
    pInfo->aReadMark[0] = 0;
    for(i=1; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED;
    if( pWal->hdr.mxFrame ) pInfo->aReadMark[1] = pWal->hdr.mxFrame;
    memset((void*)pInfo, 0, sizeof(WalCkptInfo));
    if( 0==isWalMode2(pWal) ){
      int i;
      pInfo->nBackfillAttempted = pWal->hdr.mxFrame;
      pInfo->aReadMark[0] = 0;
      for(i=1; i<WAL_NREADER; i++){
        rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1);
        if( rc==SQLITE_OK ){
          if( i==1 && pWal->hdr.mxFrame ){
            pInfo->aReadMark[i] = pWal->hdr.mxFrame;
          }else{
            pInfo->aReadMark[i] = READMARK_NOT_USED;
          }
          walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
        }else if( rc!=SQLITE_BUSY ){
          break;
        }
      }
    }

    /* If more than one frame was recovered from the log file, report an
    ** event via sqlite3_log(). This is to help with identifying performance
    ** problems caused by applications routinely shutting down without
    ** checkpointing the log file.
    ** checkpointing the log file.  */
    */
    if( pWal->hdr.nPage ){
      if( isWalMode2(pWal) ){
      sqlite3_log(SQLITE_NOTICE_RECOVER_WAL,
          "recovered %d frames from WAL file %s",
          pWal->hdr.mxFrame, pWal->zWalName
      );
        sqlite3_log(SQLITE_NOTICE_RECOVER_WAL,
            "recovered (%d,%d) frames from WAL files %s[2] (wal2 mode)",
            walidxGetMxFrame(&pWal->hdr, 0), walidxGetMxFrame(&pWal->hdr, 1), 
            pWal->zWalName
        );
      }else{
        sqlite3_log(SQLITE_NOTICE_RECOVER_WAL,
            "recovered %d frames from WAL file %s",
            pWal->hdr.mxFrame, pWal->zWalName
        );
      }
    }
  }

recovery_error:
  WALTRACE(("WAL%p: recovery %s\n", pWal, rc ? "failed" : "ok"));
  walUnlockExclusive(pWal, iLock, WAL_READ_LOCK(0)-iLock);
  walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
  return rc;
}

/*
** Close an open wal-index.
** Close an open wal-index and wal files.
*/
static void walIndexClose(Wal *pWal, int isDelete){
  if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE || pWal->bShmUnreliable ){
    int i;
    for(i=0; i<pWal->nWiData; i++){
      sqlite3_free((void *)pWal->apWiData[i]);
      pWal->apWiData[i] = 0;
    }
  }
  if( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE ){
    sqlite3OsShmUnmap(pWal->pDbFd, isDelete);
  }
  sqlite3OsClose(pWal->apWalFd[0]);
  sqlite3OsClose(pWal->apWalFd[1]);
}

/* 
** Open a connection to the WAL file zWalName. The database file must 
** already be opened on connection pDbFd. The buffer that zWalName points
** to must remain valid for the lifetime of the returned Wal* handle.
**
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
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
1986
1987
1988
1989
1990
1991
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
2017
2018
2019
2020
2021
2022

2023
2024
2025
2026
2027
2028

2029
2030
2031

2032
2033
2034
2035
2036
2037
2038
2039
2040
2041

2042
2043

2044
2045
2046
2047
2048
2049
2050

2051
2052
2053
2054
2055
2056
2057







+





+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
-







+



-
+





-
+
+

-
+






+
+

-
+

-
+






-







*/
int sqlite3WalOpen(
  sqlite3_vfs *pVfs,              /* vfs module to open wal and wal-index */
  sqlite3_file *pDbFd,            /* The open database file */
  const char *zWalName,           /* Name of the WAL file */
  int bNoShm,                     /* True to run in heap-memory mode */
  i64 mxWalSize,                  /* Truncate WAL to this size on reset */
  int bWal2,                      /* True to open in wal2 mode */
  Wal **ppWal                     /* OUT: Allocated Wal handle */
){
  int rc;                         /* Return Code */
  Wal *pRet;                      /* Object to allocate and return */
  int flags;                      /* Flags passed to OsOpen() */
  int nByte;                      /* Bytes of space to allocate */

  assert( zWalName && zWalName[0] );
  assert( pDbFd );

  /* Verify the values of various constants.  Any changes to the values
  ** of these constants would result in an incompatible on-disk format
  ** for the -shm file.  Any change that causes one of these asserts to
  ** fail is a backward compatibility problem, even if the change otherwise
  ** works.
  **
  ** This table also serves as a helpful cross-reference when trying to
  ** interpret hex dumps of the -shm file.
  */
  assert(    48 ==  sizeof(WalIndexHdr)  );
  assert(    40 ==  sizeof(WalCkptInfo)  );
  assert(   120 ==  WALINDEX_LOCK_OFFSET );
  assert(   136 ==  WALINDEX_HDR_SIZE    );
  assert(  4096 ==  HASHTABLE_NPAGE      );
  assert(  4062 ==  HASHTABLE_NPAGE_ONE  );
  assert(  8192 ==  HASHTABLE_NSLOT      );
  assert(   383 ==  HASHTABLE_HASH_1     );
  assert( 32768 ==  WALINDEX_PGSZ        );
  assert(     8 ==  SQLITE_SHM_NLOCK     );
  assert(     5 ==  WAL_NREADER          );
  assert(    24 ==  WAL_FRAME_HDRSIZE    );
  assert(    32 ==  WAL_HDRSIZE          );
  assert(   120 ==  WALINDEX_LOCK_OFFSET + WAL_WRITE_LOCK   );
  assert(   121 ==  WALINDEX_LOCK_OFFSET + WAL_CKPT_LOCK    );
  assert(   122 ==  WALINDEX_LOCK_OFFSET + WAL_RECOVER_LOCK );
  assert(   123 ==  WALINDEX_LOCK_OFFSET + WAL_READ_LOCK(0) );
  assert(   124 ==  WALINDEX_LOCK_OFFSET + WAL_READ_LOCK(1) );
  assert(   125 ==  WALINDEX_LOCK_OFFSET + WAL_READ_LOCK(2) );
  assert(   126 ==  WALINDEX_LOCK_OFFSET + WAL_READ_LOCK(3) );
  assert(   127 ==  WALINDEX_LOCK_OFFSET + WAL_READ_LOCK(4) );

  /* In the amalgamation, the os_unix.c and os_win.c source files come before
  ** this source file.  Verify that the #defines of the locking byte offsets
  ** in os_unix.c and os_win.c agree with the WALINDEX_LOCK_OFFSET value.
  ** For that matter, if the lock offset ever changes from its initial design
  ** value of 120, we need to know that so there is an assert() to check it.
  */
  assert( 120==WALINDEX_LOCK_OFFSET );
  assert( 136==WALINDEX_HDR_SIZE );
#ifdef WIN_SHM_BASE
  assert( WIN_SHM_BASE==WALINDEX_LOCK_OFFSET );
#endif
#ifdef UNIX_SHM_BASE
  assert( UNIX_SHM_BASE==WALINDEX_LOCK_OFFSET );
#endif

  nByte = sizeof(Wal) + pVfs->szOsFile*2;

  /* Allocate an instance of struct Wal to return. */
  *ppWal = 0;
  pRet = (Wal*)sqlite3MallocZero(sizeof(Wal) + pVfs->szOsFile);
  pRet = (Wal*)sqlite3MallocZero(nByte);
  if( !pRet ){
    return SQLITE_NOMEM_BKPT;
  }

  pRet->pVfs = pVfs;
  pRet->pWalFd = (sqlite3_file *)&pRet[1];
  pRet->apWalFd[0] = (sqlite3_file*)((char*)pRet+sizeof(Wal));
  pRet->apWalFd[1] = (sqlite3_file*)((char*)pRet+sizeof(Wal)+pVfs->szOsFile);
  pRet->pDbFd = pDbFd;
  pRet->readLock = -1;
  pRet->readLock = WAL_LOCK_NONE;
  pRet->mxWalSize = mxWalSize;
  pRet->zWalName = zWalName;
  pRet->syncHeader = 1;
  pRet->padToSectorBoundary = 1;
  pRet->exclusiveMode = (bNoShm ? WAL_HEAPMEMORY_MODE: WAL_NORMAL_MODE);
  sqlite3FastPrngInit(&pRet->sPrng);
  pRet->bWal2 = bWal2;
  pRet->zWalName2 = &zWalName[sqlite3Strlen30(zWalName)+1];

  /* Open file handle on the write-ahead log file. */
  /* Open a file handle on the first write-ahead log file. */
  flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_WAL);
  rc = sqlite3OsOpen(pVfs, zWalName, pRet->pWalFd, flags, &flags);
  rc = sqlite3OsOpen(pVfs, zWalName, pRet->apWalFd[0], flags, &flags);
  if( rc==SQLITE_OK && flags&SQLITE_OPEN_READONLY ){
    pRet->readOnly = WAL_RDONLY;
  }

  if( rc!=SQLITE_OK ){
    walIndexClose(pRet, 0);
    sqlite3OsClose(pRet->pWalFd);
    sqlite3_free(pRet);
  }else{
    int iDC = sqlite3OsDeviceCharacteristics(pDbFd);
    if( iDC & SQLITE_IOCAP_SEQUENTIAL ){ pRet->syncHeader = 0; }
    if( iDC & SQLITE_IOCAP_POWERSAFE_OVERWRITE ){
      pRet->padToSectorBoundary = 0;
    }
1598
1599
1600
1601
1602
1603
1604
1605

1606
1607
1608
1609
1610
1611



1612
1613
1614
1615
1616






1617
1618
1619
1620

1621

1622
1623




1624
1625
1626
1627

1628
1629
1630









1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653


1654
1655
1656
1657
1658
1659
1660

1661





1662
1663
1664





1665
1666
1667
1668
1669


1670
1671
1672
1673
1674
1675
1676
1677
1678





1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689



















































































1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707






1708
1709
1710
1711
1712
1713
1714
2253
2254
2255
2256
2257
2258
2259

2260
2261
2262
2263



2264
2265
2266
2267
2268
2269
2270

2271
2272
2273
2274
2275
2276
2277
2278
2279

2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293



2294
2295
2296
2297
2298
2299
2300
2301
2302
2303

2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323

2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339



2340
2341
2342
2343
2344
2345
2346
2347


2348
2349
2350
2351
2352
2353





2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
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
2481
2482
2483







-
+



-
-
-
+
+
+




-
+
+
+
+
+
+



-
+

+


+
+
+
+




+
-
-
-
+
+
+
+
+
+
+
+
+

-




















-
+
+







+

+
+
+
+
+
-
-
-
+
+
+
+
+



-
-
+
+




-
-
-
-
-
+
+
+
+
+











+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


















+
+
+
+
+
+







*/
static void walIteratorFree(WalIterator *p){
  sqlite3_free(p);
}

/*
** Construct a WalInterator object that can be used to loop over all 
** pages in the WAL following frame nBackfill in ascending order. Frames
** pages in wal file iWal following frame nBackfill in ascending order. Frames
** nBackfill or earlier may be included - excluding them is an optimization
** only. The caller must hold the checkpoint lock.
**
** On success, make *pp point to the newly allocated WalInterator object
** return SQLITE_OK. Otherwise, return an error code. If this routine
** returns an error, the value of *pp is undefined.
** On success, make *pp point to the newly allocated WalIterator object
** and return SQLITE_OK. Otherwise, return an error code. If this routine
** returns an error, the final value of *pp is undefined.
**
** The calling routine should invoke walIteratorFree() to destroy the
** WalIterator object when it has finished with it.
*/
static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){
static int walIteratorInit(
  Wal *pWal, 
  int iWal, 
  u32 nBackfill, 
  WalIterator **pp
){
  WalIterator *p;                 /* Return value */
  int nSegment;                   /* Number of segments to merge */
  u32 iLast;                      /* Last frame in log */
  int nByte;                      /* Number of bytes to allocate */
  sqlite3_int64 nByte;            /* Number of bytes to allocate */
  int i;                          /* Iterator variable */
  int iLastSeg;                   /* Last hash table to iterate though */
  ht_slot *aTmp;                  /* Temp space used by merge-sort */
  int rc = SQLITE_OK;             /* Return Code */
  int iMode = isWalMode2(pWal) ? 2 : 1;

  assert( isWalMode2(pWal) || iWal==0 );
  assert( 0==isWalMode2(pWal) || nBackfill==0 );

  /* This routine only runs while holding the checkpoint lock. And
  ** it only runs if there is actually content in the log (mxFrame>0).
  */
  iLast = walidxGetMxFrame(&pWal->hdr, iWal);
  assert( pWal->ckptLock && pWal->hdr.mxFrame>0 );
  iLast = pWal->hdr.mxFrame;

  assert( pWal->ckptLock && iLast>0 );

  if( iMode==2 ){
    iLastSeg = walFramePage2(iWal, iLast);
  }else{
    iLastSeg = walFramePage(iLast);
  }
  nSegment = 1 + (iLastSeg/iMode);

  /* Allocate space for the WalIterator object. */
  nSegment = walFramePage(iLast) + 1;
  nByte = sizeof(WalIterator) 
        + (nSegment-1)*sizeof(struct WalSegment)
        + iLast*sizeof(ht_slot);
  p = (WalIterator *)sqlite3_malloc64(nByte);
  if( !p ){
    return SQLITE_NOMEM_BKPT;
  }
  memset(p, 0, nByte);
  p->nSegment = nSegment;

  /* Allocate temporary space used by the merge-sort routine. This block
  ** of memory will be freed before this function returns.
  */
  aTmp = (ht_slot *)sqlite3_malloc64(
      sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast)
  );
  if( !aTmp ){
    rc = SQLITE_NOMEM_BKPT;
  }

  for(i=walFramePage(nBackfill+1); rc==SQLITE_OK && i<nSegment; i++){
  i = iMode==2 ? iWal : walFramePage(nBackfill+1);
  for(; rc==SQLITE_OK && i<=iLastSeg; i+=iMode){
    WalHashLoc sLoc;

    rc = walHashGet(pWal, i, &sLoc);
    if( rc==SQLITE_OK ){
      int j;                      /* Counter variable */
      int nEntry;                 /* Number of entries in this segment */
      ht_slot *aIndex;            /* Sorted index for this segment */
      u32 iZero;

      if( iMode==2 ){
        walExternalDecode(sLoc.iZero+1, &iZero);
        iZero--;
        assert( iZero==0 || i>=2 );
      }else{
      sLoc.aPgno++;
      if( (i+1)==nSegment ){
        nEntry = (int)(iLast - sLoc.iZero);
        iZero = sLoc.iZero;
      }

      if( i==iLastSeg ){
        nEntry = (int)(iLast - iZero);
      }else{
        nEntry = (int)((u32*)sLoc.aHash - (u32*)sLoc.aPgno);
      }
      aIndex = &((ht_slot *)&p->aSegment[p->nSegment])[sLoc.iZero];
      sLoc.iZero++;
      aIndex = &((ht_slot *)&p->aSegment[p->nSegment])[iZero];
      iZero++;
  
      for(j=0; j<nEntry; j++){
        aIndex[j] = (ht_slot)j;
      }
      walMergesort((u32 *)sLoc.aPgno, aTmp, aIndex, &nEntry);
      p->aSegment[i].iZero = sLoc.iZero;
      p->aSegment[i].nEntry = nEntry;
      p->aSegment[i].aIndex = aIndex;
      p->aSegment[i].aPgno = (u32 *)sLoc.aPgno;
      walMergesort((u32*)sLoc.aPgno, aTmp, aIndex, &nEntry);
      p->aSegment[i/iMode].iZero = iZero;
      p->aSegment[i/iMode].nEntry = nEntry;
      p->aSegment[i/iMode].aIndex = aIndex;
      p->aSegment[i/iMode].aPgno = (u32*)sLoc.aPgno;
    }
  }
  sqlite3_free(aTmp);

  if( rc!=SQLITE_OK ){
    walIteratorFree(p);
    p = 0;
  }
  *pp = p;
  return rc;
}

#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
/*
** Attempt to enable blocking locks. Blocking locks are enabled only if (a)
** they are supported by the VFS, and (b) the database handle is configured 
** with a busy-timeout. Return 1 if blocking locks are successfully enabled, 
** or 0 otherwise.
*/
static int walEnableBlocking(Wal *pWal){
  int res = 0;
  if( pWal->db ){
    int tmout = pWal->db->busyTimeout;
    if( tmout ){
      int rc;
      rc = sqlite3OsFileControl(
          pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout
      );
      res = (rc==SQLITE_OK);
    }
  }
  return res;
}

/*
** Disable blocking locks.
*/
static void walDisableBlocking(Wal *pWal){
  int tmout = 0;
  sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout);
}

/*
** If parameter bLock is true, attempt to enable blocking locks, take
** the WRITER lock, and then disable blocking locks. If blocking locks
** cannot be enabled, no attempt to obtain the WRITER lock is made. Return 
** an SQLite error code if an error occurs, or SQLITE_OK otherwise. It is not
** an error if blocking locks can not be enabled.
**
** If the bLock parameter is false and the WRITER lock is held, release it.
*/
int sqlite3WalWriteLock(Wal *pWal, int bLock){
  int rc = SQLITE_OK;
  assert( pWal->readLock<0 || bLock==0 );
  if( bLock ){
    assert( pWal->db );
    if( walEnableBlocking(pWal) ){
      rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1);
      if( rc==SQLITE_OK ){
        pWal->writeLock = 1;
      }
      walDisableBlocking(pWal);
    }
  }else if( pWal->writeLock ){
    walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
    pWal->writeLock = 0;
  }
  return rc;
}

/*
** Set the database handle used to determine if blocking locks are required.
*/
void sqlite3WalDb(Wal *pWal, sqlite3 *db){
  pWal->db = db;
}

/*
** Take an exclusive WRITE lock. Blocking if so configured.
*/
static int walLockWriter(Wal *pWal){
  int rc;
  walEnableBlocking(pWal);
  rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1);
  walDisableBlocking(pWal);
  return rc;
}
#else
# define walEnableBlocking(x) 0
# define walDisableBlocking(x)
# define walLockWriter(pWal) walLockExclusive((pWal), WAL_WRITE_LOCK, 1)
# define sqlite3WalDb(pWal, db)
#endif   /* ifdef SQLITE_ENABLE_SETLK_TIMEOUT */


/*
** Attempt to obtain the exclusive WAL lock defined by parameters lockIdx and
** n. If the attempt fails and parameter xBusy is not NULL, then it is a
** busy-handler function. Invoke it and retry the lock until either the
** lock is successfully obtained or the busy-handler returns 0.
*/
static int walBusyLock(
  Wal *pWal,                      /* WAL connection */
  int (*xBusy)(void*),            /* Function to call when busy */
  void *pBusyArg,                 /* Context argument for xBusyHandler */
  int lockIdx,                    /* Offset of first byte to lock */
  int n                           /* Number of bytes to lock */
){
  int rc;
  do {
    rc = walLockExclusive(pWal, lockIdx, n);
  }while( xBusy && rc==SQLITE_BUSY && xBusy(pBusyArg) );
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
  if( rc==SQLITE_BUSY_TIMEOUT ){
    walDisableBlocking(pWal);
    rc = SQLITE_BUSY;
  }
#endif
  return rc;
}

/*
** The cache of the wal-index header must be valid to call this function.
** Return the page-size in bytes used by the database.
*/
1733
1734
1735
1736
1737
1738
1739

1740
1741
1742
1743
1744
1745

1746
1747
1748
1749
1750






























































1751
1752
1753
1754
1755
1756
1757
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514

2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589







+





-
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







** new wal-index header. It should be passed a pseudo-random value (i.e. 
** one obtained from sqlite3_randomness()).
*/
static void walRestartHdr(Wal *pWal, u32 salt1){
  volatile WalCkptInfo *pInfo = walCkptInfo(pWal);
  int i;                          /* Loop counter */
  u32 *aSalt = pWal->hdr.aSalt;   /* Big-endian salt values */
  assert( isWalMode2(pWal)==0 );
  pWal->nCkpt++;
  pWal->hdr.mxFrame = 0;
  sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0]));
  memcpy(&pWal->hdr.aSalt[1], &salt1, 4);
  walIndexWriteHdr(pWal);
  pInfo->nBackfill = 0;
  AtomicStore(&pInfo->nBackfill, 0);
  pInfo->nBackfillAttempted = 0;
  pInfo->aReadMark[1] = 0;
  for(i=2; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED;
  assert( pInfo->aReadMark[0]==0 );
}

/*
** This function is used in wal2 mode.
**
** This function is called when writer pWal is just about to start 
** writing out frames. Parameter iApp is the current wal file. The "other" wal
** file (wal file !iApp) has been fully checkpointed. This function returns
** SQLITE_OK if there are no readers preventing the writer from switching to
** the other wal file. Or SQLITE_BUSY if there are.
*/
static int wal2RestartOk(Wal *pWal, int iApp){
  /* The other wal file (wal file !iApp) can be overwritten if there
  ** are no readers reading from it - no "full" or "partial" locks.
  ** Technically speaking it is not possible for any reader to hold
  ** a "part" lock, as this would have prevented the file from being
  ** checkpointed. But checking anyway doesn't hurt. The following
  ** is equivalent to:
  **
  **   if( iApp==0 ) eLock = WAL_LOCK_PART1_FULL2;
  **   if( iApp==1 ) eLock = WAL_LOCK_PART1;
  */
  int eLock = 1 + (iApp==0);

  assert( WAL_LOCK_PART1==1 );
  assert( WAL_LOCK_PART1_FULL2==2 );
  assert( WAL_LOCK_PART2_FULL1==3 );
  assert( WAL_LOCK_PART2==4 );

  assert( iApp!=0 || eLock==WAL_LOCK_PART1_FULL2 );
  assert( iApp!=1 || eLock==WAL_LOCK_PART1 );

  return walLockExclusive(pWal, WAL_READ_LOCK(eLock), 3);
}
static void wal2RestartFinished(Wal *pWal, int iApp){
  walUnlockExclusive(pWal, WAL_READ_LOCK(1 + (iApp==0)), 3);
}

/*
** This function is used in wal2 mode.
**
** This function is called when a checkpointer wishes to checkpoint wal
** file iCkpt. It takes the required lock and, if successful, returns
** SQLITE_OK. Otherwise, an SQLite error code (e.g. SQLITE_BUSY). If this
** function returns SQLITE_OK, it is the responsibility of the caller
** to invoke wal2CheckpointFinished() to release the lock.
*/
static int wal2CheckpointOk(Wal *pWal, int iCkpt){
  int eLock = 1 + (iCkpt*2);

  assert( WAL_LOCK_PART1==1 );
  assert( WAL_LOCK_PART1_FULL2==2 );
  assert( WAL_LOCK_PART2_FULL1==3 );
  assert( WAL_LOCK_PART2==4 );

  assert( iCkpt!=0 || eLock==WAL_LOCK_PART1 );
  assert( iCkpt!=1 || eLock==WAL_LOCK_PART2_FULL1 );

  return walLockExclusive(pWal, WAL_READ_LOCK(eLock), 2);
}
static void wal2CheckpointFinished(Wal *pWal, int iCkpt){
  walUnlockExclusive(pWal, WAL_READ_LOCK(1 + (iCkpt*2)), 2);
}

/*
** Copy as much content as we can from the WAL back into the database file
** in response to an sqlite3_wal_checkpoint() request or the equivalent.
**
** The amount of information copies from WAL to database might be limited
** by active readers.  This routine will never overwrite a database page
1794
1795
1796
1797
1798
1799
1800


1801

1802
1803
1804
1805

1806












1807
1808
1809
1810
1811
1812
1813
1814
1815




1816

1817
1818
1819



1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843


















1844
1845
1846



1847
1848
1849
1850
1851
1852



1853
1854

1855
1856
1857
1858


1859
1860
1861

1862
1863
1864
1865

1866
1867









1868
1869
1870
1871




1872
1873
1874
1875

1876
1877




1878
1879
1880
1881

1882
1883
1884



1885
1886

1887
1888
1889
1890
1891
1892

1893
1894
1895
1896




1897
1898
1899

1900
1901
1902
1903
1904
1905
1906
1907








1908
1909

1910


1911
1912
1913
1914
1915
1916
1917

1918
1919
1920
1921
1922
1923
1924
1925

1926
1927
1928
1929
1930
1931
1932
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641

2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658




2659
2660
2661
2662
2663
2664



2665
2666
2667
























2668
2669
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
2704

2705

2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720




2721
2722
2723
2724
2725
2726
2727
2728
2729


2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745

2746
2747
2748
2749
2750
2751
2752
2753
2754



2755
2756
2757
2758
2759
2760
2761
2762








2763
2764
2765
2766
2767
2768
2769
2770

2771
2772

2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789

2790
2791
2792
2793
2794
2795
2796
2797







+
+

+




+
-
+
+
+
+
+
+
+
+
+
+
+
+





-
-
-
-
+
+
+
+

+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+
+



-
-
-
+
+
+


+


-
-
+
+


-
+
-



+


+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+




+
-
-
+
+
+
+




+



+
+
+

-
+






+

-
-
-
+
+
+
+



+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-

+
-
+
+







+







-
+







  WalIterator *pIter = 0;         /* Wal iterator context */
  u32 iDbpage = 0;                /* Next database page to write */
  u32 iFrame = 0;                 /* Wal frame containing data for iDbpage */
  u32 mxSafeFrame;                /* Max frame that can be backfilled */
  u32 mxPage;                     /* Max database page to write */
  int i;                          /* Loop counter */
  volatile WalCkptInfo *pInfo;    /* The checkpoint status information */
  int bWal2 = isWalMode2(pWal);   /* True for wal2 connections */
  int iCkpt = bWal2 ? !walidxGetFile(&pWal->hdr) : 0;

  mxSafeFrame = walidxGetMxFrame(&pWal->hdr, iCkpt);
  szPage = walPagesize(pWal);
  testcase( szPage<=32768 );
  testcase( szPage>=65536 );
  pInfo = walCkptInfo(pWal);
  if( (bWal2==1 && pInfo->nBackfill==0 && mxSafeFrame) 
  if( pInfo->nBackfill<pWal->hdr.mxFrame ){
   || (bWal2==0 && pInfo->nBackfill<mxSafeFrame)
  ){
    sqlite3_file *pWalFd = pWal->apWalFd[iCkpt];
    mxPage = pWal->hdr.nPage;

    /* If this is a wal2 system, check for a reader holding a lock 
    ** preventing this checkpoint operation. If one is found, return
    ** early.  */
    if( bWal2 ){
      rc = wal2CheckpointOk(pWal, iCkpt);
      if( rc!=SQLITE_OK ) return rc;
    }

    /* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked
    ** in the SQLITE_CHECKPOINT_PASSIVE mode. */
    assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 );

    /* Compute in mxSafeFrame the index of the last frame of the WAL that is
    ** safe to write into the database.  Frames beyond mxSafeFrame might
    ** overwrite database pages that are in use by active readers and thus
    ** cannot be backfilled from the WAL.
    /* If this is a wal system (not wal2), compute in mxSafeFrame the index 
    ** of the last frame of the WAL that is safe to write into the database.
    ** Frames beyond mxSafeFrame might overwrite database pages that are in 
    ** use by active readers and thus cannot be backfilled from the WAL.
    */
    if( bWal2==0 ){
    mxSafeFrame = pWal->hdr.mxFrame;
    mxPage = pWal->hdr.nPage;
    for(i=1; i<WAL_NREADER; i++){
      mxSafeFrame = pWal->hdr.mxFrame;
      mxPage = pWal->hdr.nPage;
      for(i=1; i<WAL_NREADER; i++){
      /* Thread-sanitizer reports that the following is an unsafe read,
      ** as some other thread may be in the process of updating the value
      ** of the aReadMark[] slot. The assumption here is that if that is
      ** happening, the other client may only be increasing the value,
      ** not decreasing it. So assuming either that either the "old" or
      ** "new" version of the value is read, and not some arbitrary value
      ** that would never be written by a real client, things are still 
      ** safe.  */
      u32 y = pInfo->aReadMark[i];
      if( mxSafeFrame>y ){
        assert( y<=pWal->hdr.mxFrame );
        rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1);
        if( rc==SQLITE_OK ){
          pInfo->aReadMark[i] = (i==1 ? mxSafeFrame : READMARK_NOT_USED);
          walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
        }else if( rc==SQLITE_BUSY ){
          mxSafeFrame = y;
          xBusy = 0;
        }else{
          goto walcheckpoint_out;
        }
      }
    }

        u32 y = AtomicLoad(pInfo->aReadMark+i);
        if( mxSafeFrame>y ){
          assert( y<=pWal->hdr.mxFrame );
          rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1);
          if( rc==SQLITE_OK ){
            u32 iMark = (i==1 ? mxSafeFrame : READMARK_NOT_USED);
            AtomicStore(pInfo->aReadMark+i, iMark);
            walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
          }else if( rc==SQLITE_BUSY ){
            mxSafeFrame = y;
            xBusy = 0;
          }else{
            goto walcheckpoint_out;
          }
        }
      }
    }

    /* Allocate the iterator */
    if( pInfo->nBackfill<mxSafeFrame ){
      rc = walIteratorInit(pWal, pInfo->nBackfill, &pIter);
    if( bWal2 || pInfo->nBackfill<mxSafeFrame ){
      assert( bWal2==0 || pInfo->nBackfill==0 );
      rc = walIteratorInit(pWal, iCkpt, pInfo->nBackfill, &pIter);
      assert( rc==SQLITE_OK || pIter==0 );
    }

    if( pIter
     && (rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(0),1))==SQLITE_OK
    ){
    if( pIter && (bWal2 
     || (rc = walBusyLock(pWal, xBusy, pBusyArg,WAL_READ_LOCK(0),1))==SQLITE_OK
    )){
      u32 nBackfill = pInfo->nBackfill;

      assert( bWal2==0 || nBackfill==0 );
      pInfo->nBackfillAttempted = mxSafeFrame;

      /* Sync the WAL to disk */
      rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags));
      /* Sync the wal file being checkpointed to disk */
      rc = sqlite3OsSync(pWalFd, CKPT_SYNC_FLAGS(sync_flags));

      /* If the database may grow as a result of this checkpoint, hint
      ** about the eventual size of the db file to the VFS layer.
      ** about the eventual size of the db file to the VFS layer.  */
      */
      if( rc==SQLITE_OK ){
        i64 nReq = ((i64)mxPage * szPage);
        i64 nSize;                    /* Current size of database file */
        sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_CKPT_START, 0);
        rc = sqlite3OsFileSize(pWal->pDbFd, &nSize);
        if( rc==SQLITE_OK && nSize<nReq ){
          i64 mx = pWal->hdr.mxFrame + (bWal2?walidxGetMxFrame(&pWal->hdr,1):0);
          if( (nSize+65536+mx*szPage)<nReq ){
            /* If the size of the final database is larger than the current
            ** database plus the amount of data in the wal file, plus the
            ** maximum size of the pending-byte page (65536 bytes), then 
            ** must be corruption somewhere.  Or in the case of wal2 mode,
            ** plus the amount of data in both wal files. */
            rc = SQLITE_CORRUPT_BKPT;
          }else{
          sqlite3OsFileControlHint(pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq);
        }
      }

            sqlite3OsFileControlHint(pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT,&nReq);
          }
        }
      }

      /* Iterate through the contents of the WAL, copying data to the db file */
      while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
        i64 iOffset;

        assert( walFramePgno(pWal, iFrame)==iDbpage );
        if( db->u1.isInterrupted ){
        assert( bWal2==1 || walFramePgno(pWal, iFrame)==iDbpage );
        assert( bWal2==0 || walFramePgno2(pWal, iCkpt, iFrame)==iDbpage );

        if( AtomicLoad(&db->u1.isInterrupted) ){
          rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT;
          break;
        }
        if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){
          assert( bWal2==0 || iDbpage>mxPage );
          continue;
        }
        iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE;
        WALTRACE(("WAL%p: checkpoint frame %d of wal %d to db page %d\n",
              pWal, (int)iFrame, iCkpt, (int)iDbpage
        ));
        /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */
        rc = sqlite3OsRead(pWal->pWalFd, zBuf, szPage, iOffset);
        rc = sqlite3OsRead(pWalFd, zBuf, szPage, iOffset);
        if( rc!=SQLITE_OK ) break;
        iOffset = (iDbpage-1)*(i64)szPage;
        testcase( IS_BIG_INT(iOffset) );
        rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset);
        if( rc!=SQLITE_OK ) break;
      }
      sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_CKPT_DONE, 0);

      /* If work was actually accomplished... */
      if( rc==SQLITE_OK ){
        if( mxSafeFrame==walIndexHdr(pWal)->mxFrame ){
      /* If work was actually accomplished, truncate the db file, sync the wal
      ** file and set WalCkptInfo.nBackfill to indicate so. */
      if( rc==SQLITE_OK && (bWal2 || mxSafeFrame==walIndexHdr(pWal)->mxFrame) ){
        if( !bWal2 ){
          i64 szDb = pWal->hdr.nPage*(i64)szPage;
          testcase( IS_BIG_INT(szDb) );
          rc = sqlite3OsTruncate(pWal->pDbFd, szDb);
        }
          if( rc==SQLITE_OK ){
            rc = sqlite3OsSync(pWal->pDbFd, CKPT_SYNC_FLAGS(sync_flags));
          }
        }
        if( rc==SQLITE_OK ){
          pInfo->nBackfill = mxSafeFrame;
        }
      }
        if( rc==SQLITE_OK ){
          rc = sqlite3OsSync(pWal->pDbFd, CKPT_SYNC_FLAGS(sync_flags));
        }
      }
      if( rc==SQLITE_OK ){
        AtomicStore(&pInfo->nBackfill, (bWal2 ? 1 : mxSafeFrame));
      }


      /* Release the reader lock held while backfilling */
      if( bWal2==0 ){
      walUnlockExclusive(pWal, WAL_READ_LOCK(0), 1);
        walUnlockExclusive(pWal, WAL_READ_LOCK(0), 1);
      }
    }

    if( rc==SQLITE_BUSY ){
      /* Reset the return code so as not to report a checkpoint failure
      ** just because there are active readers.  */
      rc = SQLITE_OK;
    }
    if( bWal2 ) wal2CheckpointFinished(pWal, iCkpt);
  }

  /* If this is an SQLITE_CHECKPOINT_RESTART or TRUNCATE operation, and the
  ** entire wal file has been copied into the database file, then block 
  ** until all readers have finished using the wal file. This ensures that 
  ** the next process to write to the database restarts the wal file.
  */
  if( rc==SQLITE_OK && eMode!=SQLITE_CHECKPOINT_PASSIVE ){
  if( bWal2==0 && rc==SQLITE_OK && eMode!=SQLITE_CHECKPOINT_PASSIVE ){
    assert( pWal->writeLock );
    if( pInfo->nBackfill<pWal->hdr.mxFrame ){
      rc = SQLITE_BUSY;
    }else if( eMode>=SQLITE_CHECKPOINT_RESTART ){
      u32 salt1;
      sqlite3FastRandomness(&pWal->sPrng, 4, &salt1);
      assert( pInfo->nBackfill==pWal->hdr.mxFrame );
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
1984
1985
1986
1987
1988
1989
1990
1991
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
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031

























2032








2033
2034
2035
2036
2037

2038
2039
2040
2041
2042
2043
2044
2808
2809
2810
2811
2812
2813
2814

2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832










2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
























2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912

2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923







-
+
















+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
















+












+



+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+

-



+







          ** writer clients should see that the entire log file has been
          ** checkpointed and behave accordingly. This seems unsafe though,
          ** as it would leave the system in a state where the contents of
          ** the wal-index header do not match the contents of the 
          ** file-system. To avoid this, update the wal-index header to
          ** indicate that the log file contains zero valid frames.  */
          walRestartHdr(pWal, salt1);
          rc = sqlite3OsTruncate(pWal->pWalFd, 0);
          rc = sqlite3OsTruncate(pWal->apWalFd[0], 0);
        }
        walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
      }
    }
  }

 walcheckpoint_out:
  walIteratorFree(pIter);
  return rc;
}

/*
** If the WAL file is currently larger than nMax bytes in size, truncate
** it to exactly nMax bytes. If an error occurs while doing so, ignore it.
*/
static void walLimitSize(Wal *pWal, i64 nMax){
  if( isWalMode2(pWal)==0 ){
  i64 sz;
  int rx;
  sqlite3BeginBenignMalloc();
  rx = sqlite3OsFileSize(pWal->pWalFd, &sz);
  if( rx==SQLITE_OK && (sz > nMax ) ){
    rx = sqlite3OsTruncate(pWal->pWalFd, nMax);
  }
  sqlite3EndBenignMalloc();
  if( rx ){
    sqlite3_log(rx, "cannot limit WAL size: %s", pWal->zWalName);
    i64 sz;
    int rx;
    sqlite3BeginBenignMalloc();
    rx = sqlite3OsFileSize(pWal->apWalFd[0], &sz);
    if( rx==SQLITE_OK && (sz > nMax ) ){
      rx = sqlite3OsTruncate(pWal->apWalFd[0], nMax);
    }
    sqlite3EndBenignMalloc();
    if( rx ){
      sqlite3_log(rx, "cannot limit WAL size: %s", pWal->zWalName);
    }
  }
}

/*
** Close a connection to a log file.
*/
int sqlite3WalClose(
  Wal *pWal,                      /* Wal to close */
  sqlite3 *db,                    /* For interrupt flag */
  int sync_flags,                 /* Flags to pass to OsSync() (or 0) */
  int nBuf,
  u8 *zBuf                        /* Buffer of at least nBuf bytes */
){
  int rc = SQLITE_OK;
  if( pWal ){
    int isDelete = 0;             /* True to unlink wal and wal-index files */
    pWal->bClosing = 1;

    /* If an EXCLUSIVE lock can be obtained on the database file (using the
    ** ordinary, rollback-mode locking methods, this guarantees that the
    ** connection associated with this log file is the only connection to
    ** the database. In this case checkpoint the database and unlink both
    ** the wal and wal-index files.
    **
    ** The EXCLUSIVE lock is not released before returning.
    */
    if( zBuf!=0
     && SQLITE_OK==(rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE))
    ){
      int i;
      if( pWal->exclusiveMode==WAL_NORMAL_MODE ){
        pWal->exclusiveMode = WAL_EXCLUSIVE_MODE;
      }
      for(i=0; rc==SQLITE_OK && i<2; i++){
      rc = sqlite3WalCheckpoint(pWal, db, 
          SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0
      );
      if( rc==SQLITE_OK ){
        int bPersist = -1;
        sqlite3OsFileControlHint(
            pWal->pDbFd, SQLITE_FCNTL_PERSIST_WAL, &bPersist
        );
        if( bPersist!=1 ){
          /* Try to delete the WAL file if the checkpoint completed and
          ** fsyned (rc==SQLITE_OK) and if we are not in persistent-wal
          ** mode (!bPersist) */
          isDelete = 1;
        }else if( pWal->mxWalSize>=0 ){
          /* Try to truncate the WAL file to zero bytes if the checkpoint
          ** completed and fsynced (rc==SQLITE_OK) and we are in persistent
          ** WAL mode (bPersist) and if the PRAGMA journal_size_limit is a
          ** non-negative value (pWal->mxWalSize>=0).  Note that we truncate
          ** to zero bytes as truncating to the journal_size_limit might
          ** leave a corrupt WAL file on disk. */
          walLimitSize(pWal, 0);
        }
      }
    }
        rc = sqlite3WalCheckpoint(pWal, db, 
            SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0
        );
        if( rc==SQLITE_OK ){
          int bPersist = -1;
          sqlite3OsFileControlHint(
              pWal->pDbFd, SQLITE_FCNTL_PERSIST_WAL, &bPersist
          );
          if( bPersist!=1 ){
            /* Try to delete the WAL file if the checkpoint completed and
            ** fsyned (rc==SQLITE_OK) and if we are not in persistent-wal
            ** mode (!bPersist) */
            isDelete = 1;
          }else if( pWal->mxWalSize>=0 ){
            /* Try to truncate the WAL file to zero bytes if the checkpoint
            ** completed and fsynced (rc==SQLITE_OK) and we are in persistent
            ** WAL mode (bPersist) and if the PRAGMA journal_size_limit is a
            ** non-negative value (pWal->mxWalSize>=0).  Note that we truncate
            ** to zero bytes as truncating to the journal_size_limit might
            ** leave a corrupt WAL file on disk. */
            walLimitSize(pWal, 0);
          }
        }

        if( isWalMode2(pWal)==0 ) break;

        walCkptInfo(pWal)->nBackfill = 0;
        walidxSetFile(&pWal->hdr, !walidxGetFile(&pWal->hdr));
        pWal->writeLock = 1;
        walIndexWriteHdr(pWal);
        pWal->writeLock = 0;
      }
    }

    walIndexClose(pWal, isDelete);
    sqlite3OsClose(pWal->pWalFd);
    if( isDelete ){
      sqlite3BeginBenignMalloc();
      sqlite3OsDelete(pWal->pVfs, pWal->zWalName, 0);
      sqlite3OsDelete(pWal->pVfs, pWal->zWalName2, 0);
      sqlite3EndBenignMalloc();
    }
    WALTRACE(("WAL%p: closed\n", pWal));
    sqlite3_free((void *)pWal->apWiData);
    sqlite3_free(pWal);
  }
  return rc;
2100
2101
2102
2103
2104
2105
2106
2107

2108
2109
2110
2111
2112
2113
2114
2979
2980
2981
2982
2983
2984
2985

2986
2987
2988
2989
2990
2991
2992
2993







-
+







** If and only if the read is consistent and the header is different from
** pWal->hdr, then pWal->hdr is updated to the content of the new header
** and *pChanged is set to 1.
**
** If the checksum cannot be verified return non-zero. If the header
** is read successfully and the checksum verified, return zero.
*/
static int walIndexTryHdr(Wal *pWal, int *pChanged){
static SQLITE_NO_TSAN int walIndexTryHdr(Wal *pWal, int *pChanged){
  WalIndexHdr h1;                 /* Copy of the header content */

  if( walIndexLoadHdr(pWal, &h1) ){
    return 1;
  }

  if( memcmp(&pWal->hdr, &h1, sizeof(WalIndexHdr)) ){
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195


2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210


















2211
2212
2213
2214
2215
2216
2217
2218



2219
2220
2221
2222
2223
2224
2225
3061
3062
3063
3064
3065
3066
3067

3068
3069
3070
3071
3072
3073
3074
3075















3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100

3101
3102
3103
3104
3105
3106
3107
3108
3109
3110







-






+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
+
+
+







  ** being modified by another thread or process.
  */
  badHdr = (page0 ? walIndexTryHdr(pWal, pChanged) : 1);

  /* If the first attempt failed, it might have been due to a race
  ** with a writer.  So get a WRITE lock and try again.
  */
  assert( badHdr==0 || pWal->writeLock==0 );
  if( badHdr ){
    if( pWal->bShmUnreliable==0 && (pWal->readOnly & WAL_SHM_RDONLY) ){
      if( SQLITE_OK==(rc = walLockShared(pWal, WAL_WRITE_LOCK)) ){
        walUnlockShared(pWal, WAL_WRITE_LOCK);
        rc = SQLITE_READONLY_RECOVERY;
      }
    }else{
      int bWriteLock = pWal->writeLock;
    }else if( SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) ){
      pWal->writeLock = 1;
      if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
        badHdr = walIndexTryHdr(pWal, pChanged);
        if( badHdr ){
          /* If the wal-index header is still malformed even while holding
          ** a WRITE lock, it can only mean that the header is corrupted and
          ** needs to be reconstructed.  So run recovery to do exactly that.
          */
          rc = walIndexRecover(pWal);
          *pChanged = 1;
        }
      }
      pWal->writeLock = 0;
      walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
      if( bWriteLock || SQLITE_OK==(rc = walLockWriter(pWal)) ){
        pWal->writeLock = 1;
        if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
          badHdr = walIndexTryHdr(pWal, pChanged);
          if( badHdr ){
            /* If the wal-index header is still malformed even while holding
            ** a WRITE lock, it can only mean that the header is corrupted and
            ** needs to be reconstructed.  So run recovery to do exactly that.
            */
            rc = walIndexRecover(pWal);
            *pChanged = 1;
          }
        }
        if( bWriteLock==0 ){
          pWal->writeLock = 0;
          walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
        }
      }
    }
  }

  /* If the header is read successfully, check the version number to make
  ** sure the wal-index was not constructed with some future format that
  ** this version of SQLite cannot understand.
  */
  if( badHdr==0 && pWal->hdr.iVersion!=WALINDEX_MAX_VERSION ){
  if( badHdr==0 
   && pWal->hdr.iVersion!=WAL_VERSION1 && pWal->hdr.iVersion!=WAL_VERSION2
  ){
    rc = SQLITE_CANTOPEN_BKPT;
  }
  if( pWal->bShmUnreliable ){
    if( rc!=SQLITE_OK ){
      walIndexClose(pWal, 0);
      pWal->bShmUnreliable = 0;
      assert( pWal->nWiData>0 && pWal->apWiData[0]==0 );
2303
2304
2305
2306
2307
2308
2309
2310

2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327

2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344

2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356


2357

2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371

2372
2373
2374
2375
2376
2377
2378
2379

2380
2381
2382
2383
2384
2385
2386
3188
3189
3190
3191
3192
3193
3194

3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211

3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228

3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243

3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257

3258
3259
3260
3261
3262
3263
3264
3265

3266
3267
3268
3269
3270
3271
3272
3273







-
+
















-
+
















-
+












+
+
-
+













-
+







-
+







  **
  ** Once sqlite3OsShmMap() has been called for an sqlite3_file and has
  ** returned any SQLITE_READONLY value, it must return only SQLITE_READONLY
  ** or SQLITE_READONLY_CANTINIT or some error for all subsequent invocations,
  ** even if some external agent does a "chmod" to make the shared-memory
  ** writable by us, until sqlite3OsShmUnmap() has been called.
  ** This is a requirement on the VFS implementation.
   */
  */
  rc = sqlite3OsShmMap(pWal->pDbFd, 0, WALINDEX_PGSZ, 0, &pDummy);
  assert( rc!=SQLITE_OK ); /* SQLITE_OK not possible for read-only connection */
  if( rc!=SQLITE_READONLY_CANTINIT ){
    rc = (rc==SQLITE_READONLY ? WAL_RETRY : rc);
    goto begin_unreliable_shm_out;
  }

  /* We reach this point only if the real shared-memory is still unreliable.
  ** Assume the in-memory WAL-index substitute is correct and load it
  ** into pWal->hdr.
  */
  memcpy(&pWal->hdr, (void*)walIndexHdr(pWal), sizeof(WalIndexHdr));

  /* Make sure some writer hasn't come in and changed the WAL file out
  ** from under us, then disconnected, while we were not looking.
  */
  rc = sqlite3OsFileSize(pWal->pWalFd, &szWal);
  rc = sqlite3OsFileSize(pWal->apWalFd[0], &szWal);
  if( rc!=SQLITE_OK ){
    goto begin_unreliable_shm_out;
  }
  if( szWal<WAL_HDRSIZE ){
    /* If the wal file is too small to contain a wal-header and the
    ** wal-index header has mxFrame==0, then it must be safe to proceed
    ** reading the database file only. However, the page cache cannot
    ** be trusted, as a read/write connection may have connected, written
    ** the db, run a checkpoint, truncated the wal file and disconnected
    ** since this client's last read transaction.  */
    *pChanged = 1;
    rc = (pWal->hdr.mxFrame==0 ? SQLITE_OK : WAL_RETRY);
    goto begin_unreliable_shm_out;
  }

  /* Check the salt keys at the start of the wal file still match. */
  rc = sqlite3OsRead(pWal->pWalFd, aBuf, WAL_HDRSIZE, 0);
  rc = sqlite3OsRead(pWal->apWalFd[0], aBuf, WAL_HDRSIZE, 0);
  if( rc!=SQLITE_OK ){
    goto begin_unreliable_shm_out;
  }
  if( memcmp(&pWal->hdr.aSalt, &aBuf[16], 8) ){
    /* Some writer has wrapped the WAL file while we were not looking.
    ** Return WAL_RETRY which will cause the in-memory WAL-index to be
    ** rebuilt. */
    rc = WAL_RETRY;
    goto begin_unreliable_shm_out;
  }

  /* Allocate a buffer to read frames into */
  assert( (pWal->szPage & (pWal->szPage-1))==0 );
  assert( pWal->szPage>=512 && pWal->szPage<=65536 );
  szFrame = pWal->hdr.szPage + WAL_FRAME_HDRSIZE;
  szFrame = pWal->szPage + WAL_FRAME_HDRSIZE;
  aFrame = (u8 *)sqlite3_malloc64(szFrame);
  if( aFrame==0 ){
    rc = SQLITE_NOMEM_BKPT;
    goto begin_unreliable_shm_out;
  }
  aData = &aFrame[WAL_FRAME_HDRSIZE];

  /* Check to see if a complete transaction has been appended to the
  ** wal file since the heap-memory wal-index was created. If so, the
  ** heap-memory wal-index is discarded and WAL_RETRY returned to
  ** the caller.  */
  aSaveCksum[0] = pWal->hdr.aFrameCksum[0];
  aSaveCksum[1] = pWal->hdr.aFrameCksum[1];
  for(iOffset=walFrameOffset(pWal->hdr.mxFrame+1, pWal->hdr.szPage); 
  for(iOffset=walFrameOffset(pWal->hdr.mxFrame+1, pWal->szPage); 
      iOffset+szFrame<=szWal; 
      iOffset+=szFrame
  ){
    u32 pgno;                   /* Database page number for frame */
    u32 nTruncate;              /* dbsize field from frame header */

    /* Read and decode the next log frame. */
    rc = sqlite3OsRead(pWal->pWalFd, aFrame, szFrame, iOffset);
    rc = sqlite3OsRead(pWal->apWalFd[0], aFrame, szFrame, iOffset);
    if( rc!=SQLITE_OK ) break;
    if( !walDecodeFrame(pWal, &pgno, &nTruncate, aData, aFrame) ) break;

    /* If nTruncate is non-zero, then a complete transaction has been
    ** appended to this wal file. Set rc to WAL_RETRY and break out of
    ** the loop.  */
    if( nTruncate ){
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467

2468
2469
2470
2471
2472
2473
2474
3341
3342
3343
3344
3345
3346
3347



3348

3349

3350
3351
3352
3353
3354
3355
3356
3357







-
-
-

-

-
+







** checkpoint process do as much work as possible.  This routine might
** update values of the aReadMark[] array in the header, but if it does
** so it takes care to hold an exclusive lock on the corresponding
** WAL_READ_LOCK() while changing values.
*/
static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
  volatile WalCkptInfo *pInfo;    /* Checkpoint information in wal-index */
  u32 mxReadMark;                 /* Largest aReadMark[] value */
  int mxI;                        /* Index of largest aReadMark[] value */
  int i;                          /* Loop counter */
  int rc = SQLITE_OK;             /* Return code  */
  u32 mxFrame;                    /* Wal frame to lock to */

  assert( pWal->readLock<0 );     /* Not currently locked */
  assert( pWal->readLock==WAL_LOCK_NONE );     /* Not currently locked */

  /* useWal may only be set for read/write connections */
  assert( (pWal->readOnly & WAL_SHM_RDONLY)==0 || useWal==0 );

  /* Take steps to avoid spinning forever if there is a protocol error.
  **
  ** Circumstances that cause a RETRY should only last for the briefest
2533
2534
2535
2536
2537
2538
2539
































2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663






























































































































2664
2665
2666
2667
2668
2669
2670
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454




























































































































3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
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
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







      return walBeginShmUnreliable(pWal, pChanged);
    }
  }

  assert( pWal->nWiData>0 );
  assert( pWal->apWiData[0]!=0 );
  pInfo = walCkptInfo(pWal);
  if( isWalMode2(pWal) ){
    /* This connection needs a "part" lock on the current wal file and, 
    ** unless pInfo->nBackfill is set to indicate that it has already been
    ** checkpointed, a "full" lock on the other wal file.  */
    int iWal = walidxGetFile(&pWal->hdr);
    int nBackfill = pInfo->nBackfill || walidxGetMxFrame(&pWal->hdr, !iWal)==0;
    int eLock = 1 + (iWal*2) + (nBackfill==iWal);

    assert( nBackfill==0 || nBackfill==1 );
    assert( iWal==0 || iWal==1 );
    assert( iWal!=0 || nBackfill!=1 || eLock==WAL_LOCK_PART1 );
    assert( iWal!=0 || nBackfill!=0 || eLock==WAL_LOCK_PART1_FULL2 );
    assert( iWal!=1 || nBackfill!=1 || eLock==WAL_LOCK_PART2 );
    assert( iWal!=1 || nBackfill!=0 || eLock==WAL_LOCK_PART2_FULL1 );

    rc = walLockShared(pWal, WAL_READ_LOCK(eLock));
    if( rc!=SQLITE_OK ){
      return (rc==SQLITE_BUSY ? WAL_RETRY : rc);
    }
    walShmBarrier(pWal);
    if( memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) ){
      walUnlockShared(pWal, WAL_READ_LOCK(eLock));
      return WAL_RETRY;
    }else{
      pWal->readLock = eLock;
    }
    assert( pWal->minFrame==0 && walFramePage(pWal->minFrame)==0 );
  }else{
    u32 mxReadMark;               /* Largest aReadMark[] value */
    int mxI;                      /* Index of largest aReadMark[] value */
    int i;                        /* Loop counter */
    u32 mxFrame;                  /* Wal frame to lock to */
  if( !useWal && pInfo->nBackfill==pWal->hdr.mxFrame
#ifdef SQLITE_ENABLE_SNAPSHOT
   && (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0)
#endif
  ){
    /* The WAL has been completely backfilled (or it is empty).
    ** and can be safely ignored.
    */
    rc = walLockShared(pWal, WAL_READ_LOCK(0));
    walShmBarrier(pWal);
    if( rc==SQLITE_OK ){
      if( memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) ){
        /* It is not safe to allow the reader to continue here if frames
        ** may have been appended to the log before READ_LOCK(0) was obtained.
        ** When holding READ_LOCK(0), the reader ignores the entire log file,
        ** which implies that the database file contains a trustworthy
        ** snapshot. Since holding READ_LOCK(0) prevents a checkpoint from
        ** happening, this is usually correct.
        **
        ** However, if frames have been appended to the log (or if the log 
        ** is wrapped and written for that matter) before the READ_LOCK(0)
        ** is obtained, that is not necessarily true. A checkpointer may
        ** have started to backfill the appended frames but crashed before
        ** it finished. Leaving a corrupt image in the database file.
        */
        walUnlockShared(pWal, WAL_READ_LOCK(0));
        return WAL_RETRY;
      }
      pWal->readLock = 0;
      return SQLITE_OK;
    }else if( rc!=SQLITE_BUSY ){
      return rc;
    }
  }

  /* If we get this far, it means that the reader will want to use
  ** the WAL to get at content from recent commits.  The job now is
  ** to select one of the aReadMark[] entries that is closest to
  ** but not exceeding pWal->hdr.mxFrame and lock that entry.
  */
  mxReadMark = 0;
  mxI = 0;
  mxFrame = pWal->hdr.mxFrame;
#ifdef SQLITE_ENABLE_SNAPSHOT
  if( pWal->pSnapshot && pWal->pSnapshot->mxFrame<mxFrame ){
    mxFrame = pWal->pSnapshot->mxFrame;
  }
#endif
  for(i=1; i<WAL_NREADER; i++){
    u32 thisMark = AtomicLoad(pInfo->aReadMark+i);
    if( mxReadMark<=thisMark && thisMark<=mxFrame ){
      assert( thisMark!=READMARK_NOT_USED );
      mxReadMark = thisMark;
      mxI = i;
    }
  }
  if( (pWal->readOnly & WAL_SHM_RDONLY)==0
   && (mxReadMark<mxFrame || mxI==0)
  ){
    for(i=1; i<WAL_NREADER; i++){
      rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1);
      if( rc==SQLITE_OK ){
        mxReadMark = AtomicStore(pInfo->aReadMark+i,mxFrame);
        mxI = i;
        walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
        break;
      }else if( rc!=SQLITE_BUSY ){
        return rc;
      }
    }
  }
  if( mxI==0 ){
    assert( rc==SQLITE_BUSY || (pWal->readOnly & WAL_SHM_RDONLY)!=0 );
    return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTINIT;
  }

  rc = walLockShared(pWal, WAL_READ_LOCK(mxI));
  if( rc ){
    return rc==SQLITE_BUSY ? WAL_RETRY : rc;
  }
  /* Now that the read-lock has been obtained, check that neither the
  ** value in the aReadMark[] array or the contents of the wal-index
  ** header have changed.
  **
  ** It is necessary to check that the wal-index header did not change
  ** between the time it was read and when the shared-lock was obtained
  ** on WAL_READ_LOCK(mxI) was obtained to account for the possibility
  ** that the log file may have been wrapped by a writer, or that frames
  ** that occur later in the log than pWal->hdr.mxFrame may have been
  ** copied into the database by a checkpointer. If either of these things
  ** happened, then reading the database with the current value of
  ** pWal->hdr.mxFrame risks reading a corrupted snapshot. So, retry
  ** instead.
  **
  ** Before checking that the live wal-index header has not changed
  ** since it was read, set Wal.minFrame to the first frame in the wal
  ** file that has not yet been checkpointed. This client will not need
  ** to read any frames earlier than minFrame from the wal file - they
  ** can be safely read directly from the database file.
  **
  ** Because a ShmBarrier() call is made between taking the copy of 
  ** nBackfill and checking that the wal-header in shared-memory still
  ** matches the one cached in pWal->hdr, it is guaranteed that the 
  ** checkpointer that set nBackfill was not working with a wal-index
  ** header newer than that cached in pWal->hdr. If it were, that could
  ** cause a problem. The checkpointer could omit to checkpoint
  ** a version of page X that lies before pWal->minFrame (call that version
  ** A) on the basis that there is a newer version (version B) of the same
  ** page later in the wal file. But if version B happens to like past
  ** frame pWal->hdr.mxFrame - then the client would incorrectly assume
  ** that it can read version A from the database file. However, since
  ** we can guarantee that the checkpointer that set nBackfill could not
  ** see any pages past pWal->hdr.mxFrame, this problem does not come up.
  */
  pWal->minFrame = AtomicLoad(&pInfo->nBackfill)+1;
  walShmBarrier(pWal);
  if( AtomicLoad(pInfo->aReadMark+mxI)!=mxReadMark
   || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr))
  ){
    walUnlockShared(pWal, WAL_READ_LOCK(mxI));
    return WAL_RETRY;
  }else{
    assert( mxReadMark<=pWal->hdr.mxFrame );
    pWal->readLock = (i16)mxI;
    if( !useWal && pInfo->nBackfill==pWal->hdr.mxFrame
  #ifdef SQLITE_ENABLE_SNAPSHOT
     && (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0)
  #endif
    ){
      /* The WAL has been completely backfilled (or it is empty).
      ** and can be safely ignored.
      */
      rc = walLockShared(pWal, WAL_READ_LOCK(0));
      walShmBarrier(pWal);
      if( rc==SQLITE_OK ){
        if( memcmp((void *)walIndexHdr(pWal), &pWal->hdr,sizeof(WalIndexHdr)) ){
          /* It is not safe to allow the reader to continue here if frames
          ** may have been appended to the log before READ_LOCK(0) was obtained.
          ** When holding READ_LOCK(0), the reader ignores the entire log file,
          ** which implies that the database file contains a trustworthy
          ** snapshot. Since holding READ_LOCK(0) prevents a checkpoint from
          ** happening, this is usually correct.
          **
          ** However, if frames have been appended to the log (or if the log 
          ** is wrapped and written for that matter) before the READ_LOCK(0)
          ** is obtained, that is not necessarily true. A checkpointer may
          ** have started to backfill the appended frames but crashed before
          ** it finished. Leaving a corrupt image in the database file.
          */
          walUnlockShared(pWal, WAL_READ_LOCK(0));
          return WAL_RETRY;
        }
        pWal->readLock = 0;
        return SQLITE_OK;
      }else if( rc!=SQLITE_BUSY ){
        return rc;
      }
    }
  
    /* If we get this far, it means that the reader will want to use
    ** the WAL to get at content from recent commits.  The job now is
    ** to select one of the aReadMark[] entries that is closest to
    ** but not exceeding pWal->hdr.mxFrame and lock that entry.
    */
    mxReadMark = 0;
    mxI = 0;
    mxFrame = pWal->hdr.mxFrame;
  #ifdef SQLITE_ENABLE_SNAPSHOT
    if( pWal->pSnapshot && pWal->pSnapshot->mxFrame<mxFrame ){
      mxFrame = pWal->pSnapshot->mxFrame;
    }
  #endif
    for(i=1; i<WAL_NREADER; i++){
      u32 thisMark = AtomicLoad(pInfo->aReadMark+i);
      if( mxReadMark<=thisMark && thisMark<=mxFrame ){
        assert( thisMark!=READMARK_NOT_USED );
        mxReadMark = thisMark;
        mxI = i;
      }
    }
    if( (pWal->readOnly & WAL_SHM_RDONLY)==0
     && (mxReadMark<mxFrame || mxI==0)
    ){
      for(i=1; i<WAL_NREADER; i++){
        rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1);
        if( rc==SQLITE_OK ){
          AtomicStore(pInfo->aReadMark+i,mxFrame);
          mxReadMark = mxFrame;
          mxI = i;
          walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
          break;
        }else if( rc!=SQLITE_BUSY ){
          return rc;
        }
      }
    }
    if( mxI==0 ){
      assert( rc==SQLITE_BUSY || (pWal->readOnly & WAL_SHM_RDONLY)!=0 );
      return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTINIT;
    }
  
    rc = walLockShared(pWal, WAL_READ_LOCK(mxI));
    if( rc ){
      return rc==SQLITE_BUSY ? WAL_RETRY : rc;
    }
    /* Now that the read-lock has been obtained, check that neither the
    ** value in the aReadMark[] array or the contents of the wal-index
    ** header have changed.
    **
    ** It is necessary to check that the wal-index header did not change
    ** between the time it was read and when the shared-lock was obtained
    ** on WAL_READ_LOCK(mxI) was obtained to account for the possibility
    ** that the log file may have been wrapped by a writer, or that frames
    ** that occur later in the log than pWal->hdr.mxFrame may have been
    ** copied into the database by a checkpointer. If either of these things
    ** happened, then reading the database with the current value of
    ** pWal->hdr.mxFrame risks reading a corrupted snapshot. So, retry
    ** instead.
    **
    ** Before checking that the live wal-index header has not changed
    ** since it was read, set Wal.minFrame to the first frame in the wal
    ** file that has not yet been checkpointed. This client will not need
    ** to read any frames earlier than minFrame from the wal file - they
    ** can be safely read directly from the database file.
    **
    ** Because a ShmBarrier() call is made between taking the copy of 
    ** nBackfill and checking that the wal-header in shared-memory still
    ** matches the one cached in pWal->hdr, it is guaranteed that the 
    ** checkpointer that set nBackfill was not working with a wal-index
    ** header newer than that cached in pWal->hdr. If it were, that could
    ** cause a problem. The checkpointer could omit to checkpoint
    ** a version of page X that lies before pWal->minFrame (call that version
    ** A) on the basis that there is a newer version (version B) of the same
    ** page later in the wal file. But if version B happens to like past
    ** frame pWal->hdr.mxFrame - then the client would incorrectly assume
    ** that it can read version A from the database file. However, since
    ** we can guarantee that the checkpointer that set nBackfill could not
    ** see any pages past pWal->hdr.mxFrame, this problem does not come up.
    */
    pWal->minFrame = AtomicLoad(&pInfo->nBackfill)+1;
    walShmBarrier(pWal);
    if( AtomicLoad(pInfo->aReadMark+mxI)!=mxReadMark
     || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr))
    ){
      walUnlockShared(pWal, WAL_READ_LOCK(mxI));
      return WAL_RETRY;
    }else{
      assert( mxReadMark<=pWal->hdr.mxFrame );
      pWal->readLock = (i16)mxI;
    }
  }
  return rc;
}

#ifdef SQLITE_ENABLE_SNAPSHOT
/*
** Attempt to reduce the value of the WalCkptInfo.nBackfillAttempted 
2684
2685
2686
2687
2688
2689
2690



2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706

2707
2708
2709
2710
2711
2712
2713

2714

2715
2716
2717
2718
2719

2720
2721
2722
2723
2724
2725
2726
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







+
+
+















-
+







+
-
+




-
+







** SQLITE_OK is returned if successful, or an SQLite error code if an
** error occurs. It is not an error if nBackfillAttempted cannot be
** decreased at all.
*/
int sqlite3WalSnapshotRecover(Wal *pWal){
  int rc;

  /* Snapshots may not be used with wal2 mode databases. */
  if( isWalMode2(pWal) ) return SQLITE_ERROR;

  assert( pWal->readLock>=0 );
  rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
  if( rc==SQLITE_OK ){
    volatile WalCkptInfo *pInfo = walCkptInfo(pWal);
    int szPage = (int)pWal->szPage;
    i64 szDb;                   /* Size of db file in bytes */

    rc = sqlite3OsFileSize(pWal->pDbFd, &szDb);
    if( rc==SQLITE_OK ){
      void *pBuf1 = sqlite3_malloc(szPage);
      void *pBuf2 = sqlite3_malloc(szPage);
      if( pBuf1==0 || pBuf2==0 ){
        rc = SQLITE_NOMEM;
      }else{
        u32 i = pInfo->nBackfillAttempted;
        for(i=pInfo->nBackfillAttempted; i>pInfo->nBackfill; i--){
        for(i=pInfo->nBackfillAttempted; i>AtomicLoad(&pInfo->nBackfill); i--){
          WalHashLoc sLoc;          /* Hash table location */
          u32 pgno;                 /* Page number in db file */
          i64 iDbOff;               /* Offset of db file entry */
          i64 iWalOff;              /* Offset of wal file entry */

          rc = walHashGet(pWal, walFramePage(i), &sLoc);
          if( rc!=SQLITE_OK ) break;
          assert( i - sLoc.iZero - 1 >=0 );
          pgno = sLoc.aPgno[i-sLoc.iZero];
          pgno = sLoc.aPgno[i-sLoc.iZero-1];
          iDbOff = (i64)(pgno-1) * szPage;

          if( iDbOff+szPage<=szDb ){
            iWalOff = walFrameOffset(i, szPage) + WAL_FRAME_HDRSIZE;
            rc = sqlite3OsRead(pWal->pWalFd, pBuf1, szPage, iWalOff);
            rc = sqlite3OsRead(pWal->apWalFd[0], pBuf1, szPage, iWalOff);

            if( rc==SQLITE_OK ){
              rc = sqlite3OsRead(pWal->pDbFd, pBuf2, szPage, iDbOff);
            }

            if( rc!=SQLITE_OK || 0==memcmp(pBuf1, pBuf2, szPage) ){
              break;
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764







2765
2766




















2767
2768
2769
2770
2771
2772
2773
2774
2775
2776




2777
2778
2779
2780
2781
2782
2783
3675
3676
3677
3678
3679
3680
3681

3682
3683
3684
3685
3686
3687
3688
3689
3690
3691


3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732







-



+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










+
+
+
+







** transaction, then *pChanged is set to 1 before returning.  The
** Pager layer will use this to know that its cache is stale and
** needs to be flushed.
*/
int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
  int rc;                         /* Return code */
  int cnt = 0;                    /* Number of TryBeginRead attempts */

#ifdef SQLITE_ENABLE_SNAPSHOT
  int bChanged = 0;
  WalIndexHdr *pSnapshot = pWal->pSnapshot;
#endif

  assert( pWal->ckptLock==0 );

#ifdef SQLITE_ENABLE_SNAPSHOT
  if( pSnapshot ){
    if( isWalMode2(pWal) ) return SQLITE_ERROR;
  if( pSnapshot && memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){
    bChanged = 1;
    if( memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){
      bChanged = 1;
    }

    /* It is possible that there is a checkpointer thread running 
    ** concurrent with this code. If this is the case, it may be that the
    ** checkpointer has already determined that it will checkpoint 
    ** snapshot X, where X is later in the wal file than pSnapshot, but 
    ** has not yet set the pInfo->nBackfillAttempted variable to indicate 
    ** its intent. To avoid the race condition this leads to, ensure that
    ** there is no checkpointer process by taking a shared CKPT lock 
    ** before checking pInfo->nBackfillAttempted.  */
    (void)walEnableBlocking(pWal);
    rc = walLockShared(pWal, WAL_CKPT_LOCK);
    walDisableBlocking(pWal);

    if( rc!=SQLITE_OK ){
      return rc;
    }
    pWal->ckptLock = 1;
  }
#endif

  do{
    rc = walTryBeginRead(pWal, pChanged, 0, ++cnt);
  }while( rc==WAL_RETRY );
  testcase( (rc&0xff)==SQLITE_BUSY );
  testcase( (rc&0xff)==SQLITE_IOERR );
  testcase( rc==SQLITE_PROTOCOL );
  testcase( rc==SQLITE_OK );
  
  if( rc==SQLITE_OK && pWal->hdr.iVersion==WAL_VERSION2 ){
    rc = walOpenWal2(pWal);
  }

  pWal->nPriorFrame = pWal->hdr.mxFrame;
#ifdef SQLITE_ENABLE_SNAPSHOT
  if( rc==SQLITE_OK ){
    if( pSnapshot && memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){
      /* At this point the client has a lock on an aReadMark[] slot holding
      ** a value equal to or smaller than pSnapshot->mxFrame, but pWal->hdr
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829















2830





2831

2832
2833

2834
2835
2836
2837
2838
2839
2840
2841







2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852

2853
2854

2855




















































































2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870



2871
2872
2873
2874
2875
2876
2877




2878
2879

2880
2881









2882
2883
2884
2885











2886
2887
2888
2889

2890
2891
2892





2893
2894
2895
2896
2897
2898
2899
2900
2901







2902
2903
2904


2905
2906
2907
2908
2909
2910
2911
2912
2913

2914
2915
2916
2917
2918
2919
2920
2921
2922


2923
2924
2925
2926
2927

2928
2929
2930
2931
2932



2933
2934
2935


2936
2937

2938
2939
2940
2941
2942
2943

2944




2945
2946
2947
2948
2949
2950
2951
3742
3743
3744
3745
3746
3747
3748






























3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769

3770


3771


3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794

3795
3796

3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
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
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
3899
3900
3901



3902


3903
3904
3905
3906
3907

3908


3909
3910
3911
3912
3913
3914
3915
3916
3917




3918
3919
3920
3921
3922
3923
3924
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
3962

3963

3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
-
+
-
-
+
-
-






+
+
+
+
+
+
+










-
+

-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+















+
+
+

-
-
-

-
-
+
+
+
+

-
+
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+




+
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
+
+
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-

-
-
+
+
-
-
-
-
-
+
-
-
-
-
-
+
+
+
-
-
-
+
+
-
-
+
-




-
+
-
+
+
+
+







      **         checkpoint need not have completed for this to cause problems.
      */
      volatile WalCkptInfo *pInfo = walCkptInfo(pWal);

      assert( pWal->readLock>0 || pWal->hdr.mxFrame==0 );
      assert( pInfo->aReadMark[pWal->readLock]<=pSnapshot->mxFrame );

      /* It is possible that there is a checkpointer thread running 
      ** concurrent with this code. If this is the case, it may be that the
      ** checkpointer has already determined that it will checkpoint 
      ** snapshot X, where X is later in the wal file than pSnapshot, but 
      ** has not yet set the pInfo->nBackfillAttempted variable to indicate 
      ** its intent. To avoid the race condition this leads to, ensure that
      ** there is no checkpointer process by taking a shared CKPT lock 
      ** before checking pInfo->nBackfillAttempted.  
      **
      ** TODO: Does the aReadMark[] lock prevent a checkpointer from doing
      **       this already?
      */
      rc = walLockShared(pWal, WAL_CKPT_LOCK);

      if( rc==SQLITE_OK ){
        /* Check that the wal file has not been wrapped. Assuming that it has
        ** not, also check that no checkpointer has attempted to checkpoint any
        ** frames beyond pSnapshot->mxFrame. If either of these conditions are
        ** true, return SQLITE_ERROR_SNAPSHOT. Otherwise, overwrite pWal->hdr
        ** with *pSnapshot and set *pChanged as appropriate for opening the
        ** snapshot.  */
        if( !memcmp(pSnapshot->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt))
         && pSnapshot->mxFrame>=pInfo->nBackfillAttempted
        ){
          assert( pWal->readLock>0 );
          memcpy(&pWal->hdr, pSnapshot, sizeof(WalIndexHdr));
          *pChanged = bChanged;
        }else{
          rc = SQLITE_ERROR_SNAPSHOT;
        }
      /* Check that the wal file has not been wrapped. Assuming that it has
      ** not, also check that no checkpointer has attempted to checkpoint any
      ** frames beyond pSnapshot->mxFrame. If either of these conditions are
      ** true, return SQLITE_ERROR_SNAPSHOT. Otherwise, overwrite pWal->hdr
      ** with *pSnapshot and set *pChanged as appropriate for opening the
      ** snapshot.  */
      if( !memcmp(pSnapshot->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt))
       && pSnapshot->mxFrame>=pInfo->nBackfillAttempted
      ){
        assert( pWal->readLock>0 );
        memcpy(&pWal->hdr, pSnapshot, sizeof(WalIndexHdr));
        *pChanged = bChanged;
      }else{
        rc = SQLITE_ERROR_SNAPSHOT;
      }

      /* A client using a non-current snapshot may not ignore any frames
      ** from the start of the wal file. This is because, for a system
      ** where (minFrame < iSnapshot < maxFrame), a checkpointer may
      ** have omitted to checkpoint a frame earlier than minFrame in 
      ** the file because there exists a frame after iSnapshot that
        /* Release the shared CKPT lock obtained above. */
      ** is the same database page.  */
        walUnlockShared(pWal, WAL_CKPT_LOCK);
        pWal->minFrame = 1;
      pWal->minFrame = 1;
      }


      if( rc!=SQLITE_OK ){
        sqlite3WalEndReadTransaction(pWal);
      }
    }
  }

  /* Release the shared CKPT lock obtained above. */
  if( pWal->ckptLock ){
    assert( pSnapshot );
    walUnlockShared(pWal, WAL_CKPT_LOCK);
    pWal->ckptLock = 0;
  }
#endif
  return rc;
}

/*
** Finish with a read transaction.  All this does is release the
** read-lock.
*/
void sqlite3WalEndReadTransaction(Wal *pWal){
  sqlite3WalEndWriteTransaction(pWal);
  if( pWal->readLock>=0 ){
  if( pWal->readLock!=WAL_LOCK_NONE ){
    walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock));
    pWal->readLock = -1;
    pWal->readLock = WAL_LOCK_NONE;
  }
}

/* Search hash table iHash for an entry matching page number
** pgno. Each call to this function searches a single hash table
** (each hash table indexes up to HASHTABLE_NPAGE frames).
**
** This code might run concurrently to the code in walIndexAppend()
** that adds entries to the wal-index (and possibly to this hash 
** table). This means the value just read from the hash 
** slot (aHash[iKey]) may have been added before or after the 
** current read transaction was opened. Values added after the
** read transaction was opened may have been written incorrectly -
** i.e. these slots may contain garbage data. However, we assume
** that any slots written before the current read transaction was
** opened remain unmodified.
**
** For the reasons above, the if(...) condition featured in the inner
** loop of the following block is more stringent that would be required 
** if we had exclusive access to the hash-table:
**
**   (aPgno[iFrame]==pgno): 
**     This condition filters out normal hash-table collisions.
**
**   (iFrame<=iLast): 
**     This condition filters out entries that were added to the hash
**     table after the current read-transaction had started.
*/
static int walSearchHash(
  Wal *pWal, 
  u32 iLast,
  int iHash, 
  Pgno pgno, 
  u32 *piRead
){
  WalHashLoc sLoc;                /* Hash table location */
  int iKey;                       /* Hash slot index */
  int nCollide;                   /* Number of hash collisions remaining */
  int rc;                         /* Error code */

  rc = walHashGet(pWal, iHash, &sLoc);
  if( rc!=SQLITE_OK ){
    return rc;
  }
  nCollide = HASHTABLE_NSLOT;
  for(iKey=walHash(pgno); sLoc.aHash[iKey]; iKey=walNextHash(iKey)){
    u32 iFrame = sLoc.aHash[iKey] + sLoc.iZero;
    if( iFrame<=iLast 
     && iFrame>=pWal->minFrame 
     && sLoc.aPgno[sLoc.aHash[iKey]-1]==pgno 
    ){
      assert( iFrame>*piRead || CORRUPT_DB );
      *piRead = iFrame;
    }
    if( (nCollide--)==0 ){
      return SQLITE_CORRUPT_BKPT;
    }
  }

  return SQLITE_OK;
}

static int walSearchWal(
  Wal *pWal, 
  int iWal, 
  Pgno pgno, 
  u32 *piRead
){
  int rc = SQLITE_OK;
  int bWal2 = isWalMode2(pWal);
  u32 iLast = walidxGetMxFrame(&pWal->hdr, iWal);
  if( iLast ){
    int iHash;
    int iMinHash = walFramePage(pWal->minFrame);
    u32 iExternal = bWal2 ? walExternalEncode(iWal, iLast) : iLast;
    assert( bWal2==0 || pWal->minFrame==0 );
    for(iHash=walFramePage(iExternal); 
        iHash>=iMinHash && *piRead==0; 
        iHash-=(1+bWal2)
    ){
      rc = walSearchHash(pWal, iExternal, iHash, pgno, piRead);
      if( rc!=SQLITE_OK ) break;
    }
  }
  return rc;
}

/*
** Search the wal file for page pgno. If found, set *piRead to the frame that
** contains the page. Otherwise, if pgno is not in the wal file, set *piRead
** to zero.
**
** Return SQLITE_OK if successful, or an error code if an error occurs. If an
** error does occur, the final value of *piRead is undefined.
*/
int sqlite3WalFindFrame(
  Wal *pWal,                      /* WAL handle */
  Pgno pgno,                      /* Database page number to read data for */
  u32 *piRead                     /* OUT: Frame number (or zero) */
){
  int bWal2 = isWalMode2(pWal);
  int iApp = walidxGetFile(&pWal->hdr);
  int rc = SQLITE_OK;
  u32 iRead = 0;                  /* If !=0, WAL frame to return data from */
  u32 iLast = pWal->hdr.mxFrame;  /* Last page in WAL for this reader */
  int iHash;                      /* Used to loop through N hash tables */
  int iMinHash;

  /* This routine is only be called from within a read transaction. */
  assert( pWal->readLock>=0 || pWal->lockError );
  /* This routine is only be called from within a read transaction. Or,
  ** sometimes, as part of a rollback that occurs after an error reaquiring
  ** a read-lock in walRestartLog().  */
  assert( pWal->readLock!=WAL_LOCK_NONE || pWal->writeLock );

  /* If the "last page" field of the wal-index header snapshot is 0, then
  /* If this is a regular wal system, then iApp must be set to 0 (there is
  ** no data will be read from the wal under any circumstances. Return early
  ** in this case as an optimization.  Likewise, if pWal->readLock==0, 
  ** only one wal file, after all). Or, if this is a wal2 system and the
  ** write-lock is not held, the client must have a partial-wal lock on wal 
  ** file iApp. This is not always true if the write-lock is held and this
  ** function is being called after WalLockForCommit() as part of committing
  ** a CONCURRENT transaction.  */
#ifdef SQLITE_DEBUG
  if( bWal2 ){
    if( pWal->writeLock==0 ){
      int l = pWal->readLock;
  ** then the WAL is ignored by the reader so return early, as if the 
  ** WAL were empty.
  */
  if( iLast==0 || (pWal->readLock==0 && pWal->bShmUnreliable==0) ){
      assert( iApp==1 || l==WAL_LOCK_PART1 || l==WAL_LOCK_PART1_FULL2 );
      assert( iApp==0 || l==WAL_LOCK_PART2 || l==WAL_LOCK_PART2_FULL1 );
    }
  }else{
    assert( iApp==0 );
  }
#endif

  /* Return early if read-lock 0 is held. */
  if( (pWal->readLock==0 && pWal->bShmUnreliable==0) ){
    assert( !bWal2 );
    *piRead = 0;
    return SQLITE_OK;
  }

  /* Search the wal file that the client holds a partial lock on first. */
  /* Each iteration of the following for() loop searches one
  ** hash table (each hash table indexes up to HASHTABLE_NPAGE frames).
  **
  rc = walSearchWal(pWal, iApp, pgno, &iRead);

  /* If the requested page was not found, no error has occured, and 
  ** the client holds a full-wal lock on the other wal file, search it
  ** too.  */
  ** This code might run concurrently to the code in walIndexAppend()
  ** that adds entries to the wal-index (and possibly to this hash 
  ** table). This means the value just read from the hash 
  ** slot (aHash[iKey]) may have been added before or after the 
  ** current read transaction was opened. Values added after the
  ** read transaction was opened may have been written incorrectly -
  ** i.e. these slots may contain garbage data. However, we assume
  ** that any slots written before the current read transaction was
  ** opened remain unmodified.
  if( rc==SQLITE_OK && bWal2 && iRead==0 && (
        pWal->readLock==WAL_LOCK_PART1_FULL2 
     || pWal->readLock==WAL_LOCK_PART2_FULL1
#ifndef SQLITE_OMIT_CONCURRENT
     || (pWal->readLock==WAL_LOCK_PART1 && iApp==1)
     || (pWal->readLock==WAL_LOCK_PART2 && iApp==0)
#endif
  **
  ** For the reasons above, the if(...) condition featured in the inner
  ** loop of the following block is more stringent that would be required 
  )){
    rc = walSearchWal(pWal, !iApp, pgno, &iRead);
  ** if we had exclusive access to the hash-table:
  **
  **   (aPgno[iFrame]==pgno): 
  **     This condition filters out normal hash-table collisions.
  **
  **   (iFrame<=iLast): 
  **     This condition filters out entries that were added to the hash
  **     table after the current read-transaction had started.
  */
  }
  iMinHash = walFramePage(pWal->minFrame);
  for(iHash=walFramePage(iLast); iHash>=iMinHash; iHash--){
    WalHashLoc sLoc;              /* Hash table location */
    int iKey;                     /* Hash slot index */
    int nCollide;                 /* Number of hash collisions remaining */
    int rc;                       /* Error code */

    rc = walHashGet(pWal, iHash, &sLoc);
    if( rc!=SQLITE_OK ){
#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
  if( iRead ){ 
      return rc;
    }
    nCollide = HASHTABLE_NSLOT;
    for(iKey=walHash(pgno); sLoc.aHash[iKey]; iKey=walNextHash(iKey)){
      u32 iFrame = sLoc.aHash[iKey] + sLoc.iZero;
    u32 iFrame;
      if( iFrame<=iLast && iFrame>=pWal->minFrame
       && sLoc.aPgno[sLoc.aHash[iKey]]==pgno ){
        assert( iFrame>iRead || CORRUPT_DB );
        iRead = iFrame;
      }
    int iWal = walExternalDecode(iRead, &iFrame);
    WALTRACE(("WAL%p: page %d @ frame %d wal %d\n",pWal,(int)pgno,iFrame,iWal));
  }else{
      if( (nCollide--)==0 ){
        return SQLITE_CORRUPT_BKPT;
      }
    WALTRACE(("WAL%p: page %d not found\n", pWal, (int)pgno));
  }
    }
    if( iRead ) break;
#endif
  }

#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
  /* If expensive assert() statements are available, do a linear search
  ** of the wal-index file content. Make sure the results agree with the
  ** result obtained using the hash indexes above.  */
  ** result obtained using the hash indexes above.  
  {
  **
  ** TODO: This is broken for wal2.
  */
  if( rc==SQLITE_OK ){
    u32 iRead2 = 0;
    u32 iTest;
    assert( pWal->bShmUnreliable || pWal->minFrame>0 );
    for(iTest=iLast; iTest>=pWal->minFrame && iTest>0; iTest--){
      if( walFramePgno(pWal, iTest)==pgno ){
        iRead2 = iTest;
        break;
2962
2963
2964
2965
2966
2967
2968
2969

2970
2971
2972
2973


2974


2975
2976
2977
2978










2979
2980
2981

2982
2983
2984
2985
2986
2987
2988

2989
2990
2991
2992
2993
2994
2995
3985
3986
3987
3988
3989
3990
3991

3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017

4018
4019
4020
4021
4022
4023
4024

4025
4026
4027
4028
4029
4030
4031
4032







-
+




+
+

+
+




+
+
+
+
+
+
+
+
+
+


-
+






-
+







/*
** Read the contents of frame iRead from the wal file into buffer pOut
** (which is nOut bytes in size). Return SQLITE_OK if successful, or an
** error code otherwise.
*/
int sqlite3WalReadFrame(
  Wal *pWal,                      /* WAL handle */
  u32 iRead,                      /* Frame to read */
  u32 iExternal,                  /* Frame to read */
  int nOut,                       /* Size of buffer pOut in bytes */
  u8 *pOut                        /* Buffer to write page data to */
){
  int sz;
  int iWal = 0;
  u32 iRead;
  i64 iOffset;

  /* Figure out the page size */
  sz = pWal->hdr.szPage;
  sz = (sz&0xfe00) + ((sz&0x0001)<<16);
  testcase( sz<=32768 );
  testcase( sz>=65536 );

  if( isWalMode2(pWal) ){
    /* Figure out which of the two wal files, and the frame within, that 
    ** iExternal refers to.  */
    iWal = walExternalDecode(iExternal, &iRead);
  }else{
    iRead = iExternal;
  }

  WALTRACE(("WAL%p: reading frame %d wal %d\n", pWal, iRead, iWal));
  iOffset = walFrameOffset(iRead, sz) + WAL_FRAME_HDRSIZE;
  /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL */
  return sqlite3OsRead(pWal->pWalFd, pOut, (nOut>sz ? sz : nOut), iOffset);
  return sqlite3OsRead(pWal->apWalFd[iWal], pOut, (nOut>sz?sz:nOut), iOffset);
}

/* 
** Return the size of the database in pages (or zero, if unknown).
*/
Pgno sqlite3WalDbsize(Wal *pWal){
  if( pWal && ALWAYS(pWal->readLock>=0) ){
  if( pWal && ALWAYS(pWal->readLock!=WAL_LOCK_NONE) ){
    return pWal->hdr.nPage;
  }
  return 0;
}

/*
** Take the WRITER lock on the WAL file. Return SQLITE_OK if successful,
3031
3032
3033
3034
3035
3036
3037












3038

3039
3040
3041
3042
3043
3044
3045
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086

4087
4088
4089
4090
4091
4092
4093
4094







+
+
+
+
+
+
+
+
+
+
+
+
-
+







** the read transaction was started, then it is not possible for this
** thread to write as doing so would cause a fork.  So this routine
** returns SQLITE_BUSY in that case and no write transaction is started.
**
** There can only be a single writer active at a time.
*/
int sqlite3WalBeginWriteTransaction(Wal *pWal){
  int rc;

#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
  /* If the write-lock is already held, then it was obtained before the
  ** read-transaction was even opened, making this call a no-op.
  ** Return early. */
  if( pWal->writeLock ){
    assert( !memcmp(&pWal->hdr,(void *)walIndexHdr(pWal),sizeof(WalIndexHdr)) );
    return SQLITE_OK;
  }
#endif
  
  int rc = walWriteLock(pWal);
  rc = walWriteLock(pWal);
  if( rc==SQLITE_OK ){
    /* If another connection has written to the database file since the
    ** time the read transaction on this connection was started, then
    ** the write is disallowed. Release the WRITER lock and return
    ** SQLITE_BUSY_SNAPSHOT in this case.  */
    if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){
      walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
3057
3058
3059
3060
3061
3062
3063

3064
3065
3066
3067
3068
3069
3070
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120







+







**
** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
*/
static int walUpgradeReadlock(Wal *pWal){
  int cnt;
  int rc;
  assert( pWal->writeLock && pWal->readLock==0 );
  assert( isWalMode2(pWal)==0 );
  walUnlockShared(pWal, WAL_READ_LOCK(0));
  pWal->readLock = -1;
  cnt = 0;
  do{
    int notUsed;
    rc = walTryBeginRead(pWal, &notUsed, 1, ++cnt);
  }while( rc==WAL_RETRY );
3103
3104
3105
3106
3107
3108
3109
3110

3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
4153
4154
4155
4156
4157
4158
4159

4160
4161
4162
4163

4164
4165
4166
4167
4168
4169
4170







-
+



-







** lock cannot be obtained. Or, if the WRITER lock can be obtained but there
** are conflicts with a committed transaction, SQLITE_BUSY_SNAPSHOT. Finally,
** if an error (i.e. an OOM condition or IO error), an SQLite error code
** is returned.
*/
int sqlite3WalLockForCommit(
  Wal *pWal, 
  PgHdr *pPage1, 
  PgHdr *pPg1, 
  Bitvec *pAllRead, 
  Pgno *piConflict
){
  Pager *pPager = pPage1->pPager;
  int rc = walWriteLock(pWal);

  /* If the database has been modified since this transaction was started,
  ** check if it is still possible to commit. The transaction can be 
  ** committed if:
  **
  **   a) None of the pages in pList have been modified since the 
3130
3131
3132
3133
3134
3135
3136

3137

3138
3139
3140
3141
3142
3143
3144
3145














































3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197



























































3198
3199
3200
3201
3202
3203
3204
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188








4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235



















































4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301







+

+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    if( walIndexLoadHdr(pWal, &head) ){
      /* This branch is taken if the wal-index header is corrupted. This 
      ** occurs if some other writer has crashed while committing a 
      ** transaction to this database since the current concurrent transaction
      ** was opened.  */
      rc = SQLITE_BUSY_SNAPSHOT;
    }else if( memcmp(&pWal->hdr, (void*)&head, sizeof(WalIndexHdr))!=0 ){
      int bWal2 = isWalMode2(pWal);
      int iHash;
      int nLoop = 1+(bWal2 && walidxGetFile(&head)!=walidxGetFile(&pWal->hdr));
      int iLastHash = walFramePage(head.mxFrame);
      u32 iFirst = pWal->hdr.mxFrame+1;     /* First wal frame to check */
      if( memcmp(pWal->hdr.aSalt, (u32*)head.aSalt, sizeof(u32)*2) ){
        assert( pWal->readLock==0 );
        iFirst = 1;
      }
      for(iHash=walFramePage(iFirst); iHash<=iLastHash; iHash++){
        WalHashLoc sLoc;
      int iLoop;

      if( pPg1==0 ){
        /* If pPg1==0, then the current transaction modified the database
        ** schema. This means it conflicts with all other transactions. */
        *piConflict = 1;
        rc = SQLITE_BUSY_SNAPSHOT;
      }

      assert( nLoop==1 || nLoop==2 );
      for(iLoop=0; rc==SQLITE_OK && iLoop<nLoop; iLoop++){
        u32 iFirst;               /* First (external) wal frame to check */
        u32 iLastHash;            /* Last hash to check this loop */
        u32 mxFrame;              /* Last (external) wal frame to check */

        if( bWal2==0 ){
          assert( iLoop==0 );
          /* Special case for wal mode. If this concurrent transaction was
          ** opened after the entire wal file had been checkpointed, and
          ** another connection has since wrapped the wal file, then we wish to
          ** iterate through every frame in the new wal file - not just those
          ** that follow the current value of pWal->hdr.mxFrame (which will be
          ** set to the size of the old, now overwritten, wal file). This
          ** doesn't come up in wal2 mode, as in wal2 mode the client always
          ** has a PART lock on one of the wal files, preventing it from being
          ** checkpointed or overwritten. */
          iFirst = pWal->hdr.mxFrame+1;
          if( memcmp(pWal->hdr.aSalt, (u32*)head.aSalt, sizeof(u32)*2) ){
            assert( pWal->readLock==0 );
            iFirst = 1;
          }
          mxFrame = head.mxFrame;
        }else{
          int iA = walidxGetFile(&pWal->hdr);
          if( iLoop==0 ){
            iFirst = walExternalEncode(iA, 1+walidxGetMxFrame(&pWal->hdr, iA));
            mxFrame = walExternalEncode(iA, walidxGetMxFrame(&head, iA));
          }else{
            iFirst = walExternalEncode(!iA, 1);
            mxFrame = walExternalEncode(!iA, walidxGetMxFrame(&head, !iA));
          }
        }
        iLastHash = walFramePage(mxFrame);

        for(iHash=walFramePage(iFirst); iHash<=iLastHash; iHash += (1+bWal2)){
          WalHashLoc sLoc;

        rc = walHashGet(pWal, iHash, &sLoc);
        if( rc==SQLITE_OK ){
          u32 i, iMin, iMax;
          assert( head.mxFrame>=sLoc.iZero );
          iMin = (sLoc.iZero >= iFirst) ? 1 : (iFirst - sLoc.iZero);
          iMax = (iHash==0) ? HASHTABLE_NPAGE_ONE : HASHTABLE_NPAGE;
          if( iMax>(head.mxFrame-sLoc.iZero) ) iMax = (head.mxFrame-sLoc.iZero);
          for(i=iMin; rc==SQLITE_OK && i<=iMax; i++){
            PgHdr *pPg;
            if( sLoc.aPgno[i]==1 ){
              /* Check that the schema cookie has not been modified. If
              ** it has not, the commit can proceed. */
              u8 aNew[4];
              u8 *aOld = &((u8*)pPage1->pData)[40];
              int sz;
              i64 iOffset;
              sz = pWal->hdr.szPage;
              sz = (sz&0xfe00) + ((sz&0x0001)<<16);
              iOffset = walFrameOffset(i+sLoc.iZero, sz) + WAL_FRAME_HDRSIZE+40;
              rc = sqlite3OsRead(pWal->pWalFd, aNew, sizeof(aNew), iOffset);
              if( rc==SQLITE_OK && memcmp(aOld, aNew, sizeof(aNew)) ){
                rc = SQLITE_BUSY_SNAPSHOT;
              }
            }else if( sqlite3BitvecTestNotNull(pAllRead, sLoc.aPgno[i]) ){
              *piConflict = sLoc.aPgno[i];
              rc = SQLITE_BUSY_SNAPSHOT;
            }else if( (pPg = sqlite3PagerLookup(pPager, sLoc.aPgno[i])) ){
              /* Page aPgno[i], which is present in the pager cache, has been
              ** modified since the current CONCURRENT transaction was started.
              ** However it was not read by the current transaction, so is not
              ** a conflict. There are two possibilities: (a) the page was
              ** allocated at the of the file by the current transaction or 
              ** (b) was present in the cache at the start of the transaction.
              **
              ** For case (a), do nothing. This page will be moved within the
              ** database file by the commit code to avoid the conflict. The
              ** call to PagerUnref() is to release the reference grabbed by
              ** the sqlite3PagerLookup() above.  
              **
              ** In case (b), drop the page from the cache - otherwise
              ** following the snapshot upgrade the cache would be inconsistent
              ** with the database as stored on disk. */
              if( sqlite3PagerIswriteable(pPg) ){
                sqlite3PagerUnref(pPg);
              }else{
                sqlite3PcacheDrop(pPg);
              }
            }
          }
        }
        if( rc!=SQLITE_OK ) break;
          rc = walHashGet(pWal, iHash, &sLoc);
          if( rc==SQLITE_OK ){
            u32 i, iMin, iMax;
            assert( mxFrame>=sLoc.iZero );
            iMin = (sLoc.iZero >= iFirst) ? 1 : (iFirst - sLoc.iZero);
            iMax = (iHash==0) ? HASHTABLE_NPAGE_ONE : HASHTABLE_NPAGE;
            if( iMax>(mxFrame-sLoc.iZero) ) iMax = (mxFrame-sLoc.iZero);
            for(i=iMin; rc==SQLITE_OK && i<=iMax; i++){
              PgHdr *pPg;
              if( sLoc.aPgno[i-1]==1 ){
                /* Check that the schema cookie has not been modified. If
                ** it has not, the commit can proceed. */
                u8 aNew[4];
                u8 *aOld = &((u8*)pPg1->pData)[40];
                int sz;
                i64 iOff;
                u32 iFrame = sLoc.iZero + i;
                int iWal = 0;
                if( bWal2 ){
                  iWal = walExternalDecode(iFrame, &iFrame);
                }
                sz = pWal->hdr.szPage;
                sz = (sz&0xfe00) + ((sz&0x0001)<<16);
                iOff = walFrameOffset(iFrame, sz) + WAL_FRAME_HDRSIZE + 40;
                rc = sqlite3OsRead(pWal->apWalFd[iWal],aNew,sizeof(aNew),iOff);
                if( rc==SQLITE_OK && memcmp(aOld, aNew, sizeof(aNew)) ){
                  rc = SQLITE_BUSY_SNAPSHOT;
                }
              }else if( sqlite3BitvecTestNotNull(pAllRead, sLoc.aPgno[i-1]) ){
                *piConflict = sLoc.aPgno[i-1];
                rc = SQLITE_BUSY_SNAPSHOT;
              }else
              if( (pPg = sqlite3PagerLookup(pPg1->pPager, sLoc.aPgno[i-1])) ){
                /* Page aPgno[i], which is present in the pager cache, has been
                ** modified since the current CONCURRENT transaction was
                ** started.  However it was not read by the current
                ** transaction, so is not a conflict. There are two
                ** possibilities: (a) the page was allocated at the of the file
                ** by the current transaction or (b) was present in the cache
                ** at the start of the transaction.
                **
                ** For case (a), do nothing. This page will be moved within the
                ** database file by the commit code to avoid the conflict. The
                ** call to PagerUnref() is to release the reference grabbed by
                ** the sqlite3PagerLookup() above.  
                **
                ** In case (b), drop the page from the cache - otherwise
                ** following the snapshot upgrade the cache would be
                ** inconsistent with the database as stored on disk. */
                if( sqlite3PagerIswriteable(pPg) ){
                  sqlite3PagerUnref(pPg);
                }else{
                  sqlite3PcacheDrop(pPg);
                }
              }
            }
          }
          if( rc!=SQLITE_OK ) break;
        }
      }
    }
  }

  pWal->nPriorFrame = pWal->hdr.mxFrame;
  return rc;
}
3215
3216
3217
3218
3219
3220
3221


3222


3223
3224
3225
3226
3227
3228

3229
3230
3231
3232
3233
3234
3235
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







+
+

+
+






+







** (even if the CONCURRENT transaction ran against an older snapshot).
**
** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
*/
int sqlite3WalUpgradeSnapshot(Wal *pWal){
  int rc = SQLITE_OK;
  assert( pWal->writeLock );

  assert( pWal->szPage==pWal->hdr.szPage );
  memcpy(&pWal->hdr, (void*)walIndexHdr(pWal), sizeof(WalIndexHdr));
  assert( pWal->szPage==pWal->hdr.szPage || pWal->szPage==0 );
  pWal->szPage = pWal->hdr.szPage;

  /* If this client has its read-lock on slot aReadmark[0] and the entire
  ** wal has not been checkpointed, switch it to a different slot. Otherwise
  ** any reads performed between now and committing the transaction will
  ** read from the old snapshot - not the one just upgraded to.  */
  if( pWal->readLock==0 && pWal->hdr.mxFrame!=walCkptInfo(pWal)->nBackfill ){
    assert( isWalMode2(pWal)==0 );
    rc = walUpgradeReadlock(pWal);
  }
  return rc;
}
#endif   /* SQLITE_OMIT_CONCURRENT */

/*
3254
3255
3256
3257
3258
3259
3260
3261






3262
3263


3264

3265
3266



3267
3268
3269
3270

3271
















3272
3273
3274
3275










3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286




3287
3288




3289
3290

3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301


3302

3303
3304
3305

3306
3307
3308
3309
3310
3311
3312
3313
3314
3315


3316
3317

3318

3319
3320

3321
3322
3323
3324
3325
3326

3327
3328
3329
3330


3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345




3346
3347
3348

3349
3350
3351
3352
3353












3354


























3355
3356
3357
3358
3359
3360
3361
4356
4357
4358
4359
4360
4361
4362

4363
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
4394
4395
4396
4397
4398
4399




4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424


4425
4426
4427
4428
4429

4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443

4444
4445
4446

4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462

4463
4464

4465
4466
4467
4468
4469
4470

4471
4472
4473


4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486




4487
4488
4489
4490
4491
4492

4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510

4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543







-
+
+
+
+
+
+


+
+
-
+

-
+
+
+




+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+











+
+
+
+
-
-
+
+
+
+

-
+











+
+
-
+


-
+










+
+


+
-
+

-
+





-
+


-
-
+
+











-
-
-
-
+
+
+
+


-
+





+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







** to the WAL since the start of the transaction. If the callback returns
** other than SQLITE_OK, it is not invoked again and the error code is
** returned to the caller.
**
** Otherwise, if the callback function does not return an error, this
** function returns SQLITE_OK.
*/
int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx){
int sqlite3WalUndo(
  Wal *pWal, 
  int (*xUndo)(void *, Pgno), 
  void *pUndoCtx,
  int bConcurrent                 /* True if this is a CONCURRENT transaction */
){
  int rc = SQLITE_OK;
  if( pWal->writeLock ){
    int iWal = walidxGetFile(&pWal->hdr);
    Pgno iMax = walidxGetMxFrame(&pWal->hdr, iWal);
    Pgno iMax = pWal->hdr.mxFrame;
    Pgno iNew;
    Pgno iFrame;
  

    assert( isWalMode2(pWal) || iWal==0 );

    /* Restore the clients cache of the wal-index header to the state it
    ** was in before the client began writing to the database. 
    */
    memcpy(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr));
    iNew = walidxGetMxFrame(&pWal->hdr, walidxGetFile(&pWal->hdr));

    /* BEGIN CONCURRENT transactions are different, as the header just
    ** memcpy()d into pWal->hdr may not be the same as the current header 
    ** when the transaction was started. Instead, pWal->hdr now contains
    ** the header written by the most recent successful COMMIT. Because
    ** Wal.writeLock is set, if this is a BEGIN CONCURRENT transaction,
    ** the rollback must be taking place because an error occurred during
    ** a COMMIT.
    **
    ** The code below is still valid. All frames between (iNew+1) and iMax 
    ** must have been written by this transaction before the error occurred.
    ** The exception is in wal2 mode - if the current wal file at the time
    ** of the last COMMIT is not wal file iWal, then the error must have
    ** occurred in WalLockForCommit(), before any pages were written
    ** to the database file. In this case return early.  */
#ifndef SQLITE_OMIT_CONCURRENT
    if( bConcurrent ){
    for(iFrame=pWal->hdr.mxFrame+1; 
        ALWAYS(rc==SQLITE_OK) && iFrame<=iMax; 
        iFrame++
    ){
      pWal->hdr.aCksum[0]++;
    }
    if( walidxGetFile(&pWal->hdr)!=iWal ){
      assert( bConcurrent && isWalMode2(pWal) );
      return SQLITE_OK;
    }
#endif
    assert( walidxGetFile(&pWal->hdr)==iWal );

    for(iFrame=iNew+1; ALWAYS(rc==SQLITE_OK) && iFrame<=iMax; iFrame++){
      /* This call cannot fail. Unless the page for which the page number
      ** is passed as the second argument is (a) in the cache and 
      ** (b) has an outstanding reference, then xUndo is either a no-op
      ** (if (a) is false) or simply expels the page from the cache (if (b)
      ** is false).
      **
      ** If the upper layer is doing a rollback, it is guaranteed that there
      ** are no outstanding references to any page other than page 1. And
      ** page 1 is never written to the log until the transaction is
      ** committed. As a result, the call to xUndo may not fail.
      */
      Pgno pgno;
      if( isWalMode2(pWal) ){
        pgno = walFramePgno2(pWal, iWal, iFrame);
      }else{
      assert( walFramePgno(pWal, iFrame)!=1 );
      rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame));
        pgno = walFramePgno(pWal, iFrame);
      }
      assert( pgno!=1 );
      rc = xUndo(pUndoCtx, pgno);
    }
    if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal);
    if( iMax!=iNew ) walCleanupHash(pWal);
  }
  return rc;
}

/* 
** Argument aWalData must point to an array of WAL_SAVEPOINT_NDATA u32 
** values. This function populates the array with values required to 
** "rollback" the write position of the WAL handle back to the current 
** point in the event of a savepoint rollback (via WalSavepointUndo()).
*/
void sqlite3WalSavepoint(Wal *pWal, u32 *aWalData){
  int iWal = walidxGetFile(&pWal->hdr);
  assert( isWalMode2(pWal) || iWal==0 );
  aWalData[0] = pWal->hdr.mxFrame;
  aWalData[0] = walidxGetMxFrame(&pWal->hdr, iWal);
  aWalData[1] = pWal->hdr.aFrameCksum[0];
  aWalData[2] = pWal->hdr.aFrameCksum[1];
  aWalData[3] = pWal->nCkpt;
  aWalData[3] = isWalMode2(pWal) ? iWal : pWal->nCkpt;
}

/* 
** Move the write position of the WAL back to the point identified by
** the values in the aWalData[] array. aWalData must point to an array
** of WAL_SAVEPOINT_NDATA u32 values that has been previously populated
** by a call to WalSavepoint().
*/
int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData){
  int rc = SQLITE_OK;
  int iWal = walidxGetFile(&pWal->hdr);
  int iCmp = isWalMode2(pWal) ? iWal : pWal->nCkpt;

  assert( pWal->writeLock || aWalData[0]==pWal->hdr.mxFrame );
  assert( isWalMode2(pWal) || iWal==0 );
  assert( aWalData[3]!=pWal->nCkpt || aWalData[0]<=pWal->hdr.mxFrame );
  assert( aWalData[3]!=iCmp || aWalData[0]<=walidxGetMxFrame(&pWal->hdr,iWal) );

  if( aWalData[3]!=pWal->nCkpt ){
  if( aWalData[3]!=iCmp ){
    /* This savepoint was opened immediately after the write-transaction
    ** was started. Right after that, the writer decided to wrap around
    ** to the start of the log. Update the savepoint values to match.
    */
    aWalData[0] = 0;
    aWalData[3] = pWal->nCkpt;
    aWalData[3] = iCmp;
  }

  if( aWalData[0]<pWal->hdr.mxFrame ){
    pWal->hdr.mxFrame = aWalData[0];
  if( aWalData[0]<walidxGetMxFrame(&pWal->hdr, iWal) ){
    walidxSetMxFrame(&pWal->hdr, iWal, aWalData[0]);
    pWal->hdr.aFrameCksum[0] = aWalData[1];
    pWal->hdr.aFrameCksum[1] = aWalData[2];
    walCleanupHash(pWal);
  }

  return rc;
}

/*
** This function is called just before writing a set of frames to the log
** file (see sqlite3WalFrames()). It checks to see if, instead of appending
** to the current log file, it is possible to overwrite the start of the
** existing log file with the new frames (i.e. "reset" the log). If so,
** it sets pWal->hdr.mxFrame to 0. Otherwise, pWal->hdr.mxFrame is left
** unchanged.
** to the current log file, it is possible and desirable to switch to the
** other log file and write the new transaction to the start of it.
** If so, the wal-index header is updated accordingly - both in heap memory
** and in the *-shm file.
**
** SQLITE_OK is returned if no error is encountered (regardless of whether
** or not pWal->hdr.mxFrame is modified). An SQLite error code is returned
** or not the wal-index header is modified). An SQLite error code is returned
** if an error occurs.
*/
static int walRestartLog(Wal *pWal){
  int rc = SQLITE_OK;

  if( isWalMode2(pWal) ){
    int iApp = walidxGetFile(&pWal->hdr);
    int nWalSize = WAL_DEFAULT_WALSIZE;
    if( pWal->mxWalSize>0 ){
      nWalSize = (pWal->mxWalSize-WAL_HDRSIZE+pWal->szPage+WAL_FRAME_HDRSIZE-1) 
        / (pWal->szPage+WAL_FRAME_HDRSIZE);
      nWalSize = MAX(nWalSize, 1);
    }

    assert( 1==WAL_LOCK_PART1 );
    assert( 4==WAL_LOCK_PART2 );
    assert( 1+(iApp*3)==WAL_LOCK_PART1 || 1+(iApp*3)==WAL_LOCK_PART2 );
  if( pWal->readLock==0 ){
    if( pWal->readLock==1+(iApp*3)
     && walidxGetMxFrame(&pWal->hdr, iApp)>=nWalSize 
    ){
      volatile WalCkptInfo *pInfo = walCkptInfo(pWal);
      u32 mxFrame = walidxGetMxFrame(&pWal->hdr, !iApp);
      if( mxFrame==0 || pInfo->nBackfill ){
        rc = wal2RestartOk(pWal, iApp);
        if( rc==SQLITE_OK ){
          int iNew = !iApp;
          pWal->nCkpt++;
          walidxSetFile(&pWal->hdr, iNew);
          walidxSetMxFrame(&pWal->hdr, iNew, 0);
          sqlite3Put4byte((u8*)&pWal->hdr.aSalt[0], pWal->hdr.aFrameCksum[0]);
          sqlite3Put4byte((u8*)&pWal->hdr.aSalt[1], pWal->hdr.aFrameCksum[1]);
          walIndexWriteHdr(pWal);
          pInfo->nBackfill = 0;
          wal2RestartFinished(pWal, iApp);
          walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock));
          pWal->readLock = iNew ? WAL_LOCK_PART2_FULL1 : WAL_LOCK_PART1_FULL2;
          rc = walLockShared(pWal, WAL_READ_LOCK(pWal->readLock));
        }else if( rc==SQLITE_BUSY ){
          rc = SQLITE_OK;
        }
      }
    }
  }else if( pWal->readLock==0 ){
    volatile WalCkptInfo *pInfo = walCkptInfo(pWal);
    assert( pInfo->nBackfill==pWal->hdr.mxFrame );
    if( pInfo->nBackfill>0 ){
      u32 salt1;
      sqlite3FastRandomness(&pWal->sPrng, 4, &salt1);
      rc = walLockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
      if( rc==SQLITE_OK ){
3382
3383
3384
3385
3386
3387
3388

3389
3390
3391
3392
3393
3394
3395
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578







+







    ** only - never from the wal file. This means that if a writer holding
    ** a lock on aReadmark[0] were to commit a transaction but not close the
    ** read-transaction, subsequent read operations would read directly from
    ** the database file - ignoring the new pages just appended
    ** to the wal file. */
    rc = walUpgradeReadlock(pWal);
  }

  return rc;
}

/*
** Information about the current state of the WAL file and where
** the next fsync should occur - passed from sqlite3WalFrames() into
** walWriteToLog().
3440
3441
3442
3443
3444
3445
3446

3447

3448
3449










3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470

3471
3472
3473
3474

3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490

3491
3492
3493
3494
3495
3496
3497
3498

3499
3500
3501
3502
3503
3504
3505

3506
3507
3508
3509
3510
3511
3512
4623
4624
4625
4626
4627
4628
4629
4630

4631


4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642

4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659

4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681

4682
4683
4684
4685
4686
4687
4688
4689

4690
4691
4692
4693
4694
4695
4696

4697
4698
4699
4700
4701
4702
4703
4704







+
-
+
-
-
+
+
+
+
+
+
+
+
+
+

-

















-

+




+















-
+







-
+






-
+







  PgHdr *pPage,               /* The page of the frame to be written */
  int nTruncate,              /* The commit flag.  Usually 0.  >0 for commit */
  sqlite3_int64 iOffset       /* Byte offset at which to write */
){
  int rc;                         /* Result code from subfunctions */
  void *pData;                    /* Data actually written */
  u8 aFrame[WAL_FRAME_HDRSIZE];   /* Buffer to assemble frame-header in */

#if defined(SQLITE_HAS_CODEC)
#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
  if( (pData = sqlite3PagerCodec(pPage))==0 ) return SQLITE_NOMEM_BKPT;
#else
  { 
    int iWal = walidxGetFile(&p->pWal->hdr);
    int iFrame = 1 + (iOffset / (WAL_FRAME_HDRSIZE + p->pWal->szPage));
    assert( p->pWal->apWalFd[iWal]==p->pFd );
    WALTRACE(("WAL%p: page %d written to frame %d of wal %d\n",
          p->pWal, (int)pPage->pgno, iFrame, iWal
    ));
  }
#endif

  pData = pPage->pData;
#endif
  walEncodeFrame(p->pWal, pPage->pgno, nTruncate, pData, aFrame);
  rc = walWriteToLog(p, aFrame, sizeof(aFrame), iOffset);
  if( rc ) return rc;
  /* Write the page data */
  rc = walWriteToLog(p, pData, p->szPage, iOffset+sizeof(aFrame));
  return rc;
}

/*
** This function is called as part of committing a transaction within which
** one or more frames have been overwritten. It updates the checksums for
** all frames written to the wal file by the current transaction starting
** with the earliest to have been overwritten.
**
** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
*/
static int walRewriteChecksums(Wal *pWal, u32 iLast){
  const int szPage = pWal->szPage;/* Database page size */
  int rc = SQLITE_OK;             /* Return code */
  const int szPage = pWal->szPage;/* Database page size */
  u8 *aBuf;                       /* Buffer to load data from wal file into */
  u8 aFrame[WAL_FRAME_HDRSIZE];   /* Buffer to assemble frame-headers in */
  u32 iRead;                      /* Next frame to read from wal file */
  i64 iCksumOff;
  sqlite3_file *pWalFd = pWal->apWalFd[walidxGetFile(&pWal->hdr)];

  aBuf = sqlite3_malloc(szPage + WAL_FRAME_HDRSIZE);
  if( aBuf==0 ) return SQLITE_NOMEM_BKPT;

  /* Find the checksum values to use as input for the recalculating the
  ** first checksum. If the first frame is frame 1 (implying that the current
  ** transaction restarted the wal file), these values must be read from the
  ** wal-file header. Otherwise, read them from the frame header of the
  ** previous frame.  */
  assert( pWal->iReCksum>0 );
  if( pWal->iReCksum==1 ){
    iCksumOff = 24;
  }else{
    iCksumOff = walFrameOffset(pWal->iReCksum-1, szPage) + 16;
  }
  rc = sqlite3OsRead(pWal->pWalFd, aBuf, sizeof(u32)*2, iCksumOff);
  rc = sqlite3OsRead(pWalFd, aBuf, sizeof(u32)*2, iCksumOff);
  pWal->hdr.aFrameCksum[0] = sqlite3Get4byte(aBuf);
  pWal->hdr.aFrameCksum[1] = sqlite3Get4byte(&aBuf[sizeof(u32)]);

  iRead = pWal->iReCksum;
  pWal->iReCksum = 0;
  for(; rc==SQLITE_OK && iRead<=iLast; iRead++){
    i64 iOff = walFrameOffset(iRead, szPage);
    rc = sqlite3OsRead(pWal->pWalFd, aBuf, szPage+WAL_FRAME_HDRSIZE, iOff);
    rc = sqlite3OsRead(pWalFd, aBuf, szPage+WAL_FRAME_HDRSIZE, iOff);
    if( rc==SQLITE_OK ){
      u32 iPgno, nDbSize;
      iPgno = sqlite3Get4byte(aBuf);
      nDbSize = sqlite3Get4byte(&aBuf[4]);

      walEncodeFrame(pWal, iPgno, nDbSize, &aBuf[WAL_FRAME_HDRSIZE], aFrame);
      rc = sqlite3OsWrite(pWal->pWalFd, aFrame, sizeof(aFrame), iOff);
      rc = sqlite3OsWrite(pWalFd, aFrame, sizeof(aFrame), iOff);
    }
  }

  sqlite3_free(aBuf);
  return rc;
}

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
3569
3570
3571
3572

3573












3574

3575
3576
3577
3578
3579
3580

3581
3582
3583
3584
3585
3586
3587

3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601

3602
3603
3604
3605
3606
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
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736







4737
4738
4739

4740
4741
4742
4743
4744
4745

4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756

4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770

4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784

4785

4786
4787
4788
4789

4790
4791
4792
4793
4794
4795
4796

4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810

4811
4812
4813
4814
4815
4816
4817
4818

4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835

4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846



4847


4848
4849
4850
4851
4852
4853
4854
4855







+
+








-
-
-
-
-
-
-


+
-
+





-
+







+
+
+
-
+
+
+
+
+
+
+
+

+




-
+

+
+
+
+
+
+
+
+
+
+
+
+
-
+
-




-
+






-
+













-
+







-
+
















-
+

+
+
+






-
-
-

-
-
+







  PgHdr *pLast = 0;               /* Last frame in list */
  int nExtra = 0;                 /* Number of extra copies of last page */
  int szFrame;                    /* The size of a single frame */
  i64 iOffset;                    /* Next byte to write in WAL file */
  WalWriter w;                    /* The writer */
  u32 iFirst = 0;                 /* First frame that may be overwritten */
  WalIndexHdr *pLive;             /* Pointer to shared header */
  int iApp;
  int bWal2 = isWalMode2(pWal);

  assert( pList );
  assert( pWal->writeLock );

  /* If this frame set completes a transaction, then nTruncate>0.  If
  ** nTruncate==0 then this frame set does not complete the transaction. */
  assert( (isCommit!=0)==(nTruncate!=0) );

#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
  { int cnt; for(cnt=0, p=pList; p; p=p->pDirty, cnt++){}
    WALTRACE(("WAL%p: frame write begin. %d frames. mxFrame=%d. %s\n",
              pWal, cnt, pWal->hdr.mxFrame, isCommit ? "Commit" : "Spill"));
  }
#endif

  pLive = (WalIndexHdr*)walIndexHdr(pWal);
  if( memcmp(&pWal->hdr, (void *)pLive, sizeof(WalIndexHdr))!=0 ){
    /* if( isWalMode2(pWal)==0 ) */
    iFirst = pLive->mxFrame+1;
    iFirst = walidxGetMxFrame(pLive, walidxGetFile(pLive))+1;
  }

  /* See if it is possible to write these frames into the start of the
  ** log file, instead of appending to it at pWal->hdr.mxFrame.
  */
  if( SQLITE_OK!=(rc = walRestartLog(pWal)) ){
  else if( SQLITE_OK!=(rc = walRestartLog(pWal)) ){
    return rc;
  }

  /* If this is the first frame written into the log, write the WAL
  ** header to the start of the WAL file. See comments at the top of
  ** this source file for a description of the WAL header format.
  */
  iApp = walidxGetFile(&pWal->hdr);
  iFrame = walidxGetMxFrame(&pWal->hdr, iApp);
  assert( iApp==0 || bWal2 );
  iFrame = pWal->hdr.mxFrame;

#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
  { int cnt; for(cnt=0, p=pList; p; p=p->pDirty, cnt++){}
    WALTRACE(("WAL%p: frame write begin. %d frames. iWal=%d. mxFrame=%d. %s\n",
              pWal, cnt, iApp, iFrame, isCommit ? "Commit" : "Spill"));
  }
#endif

  if( iFrame==0 ){
    u32 iCkpt = 0;
    u8 aWalHdr[WAL_HDRSIZE];      /* Buffer to assemble wal-header in */
    u32 aCksum[2];                /* Checksum for wal-header */

    sqlite3Put4byte(&aWalHdr[0], (WAL_MAGIC | SQLITE_BIGENDIAN));
    sqlite3Put4byte(&aWalHdr[4], WAL_MAX_VERSION);
    sqlite3Put4byte(&aWalHdr[4], pWal->hdr.iVersion);
    sqlite3Put4byte(&aWalHdr[8], szPage);
    if( bWal2 ){
      if( walidxGetMxFrame(&pWal->hdr, !iApp)>0 ){
        u8 aPrev[4];
        rc = sqlite3OsRead(pWal->apWalFd[!iApp], aPrev, 4, 12);
        if( rc!=SQLITE_OK ){
          return rc;
        }
        iCkpt = (sqlite3Get4byte(aPrev) + 1) & 0x0F;
      }
    }else{
      iCkpt = pWal->nCkpt;
    }
    sqlite3Put4byte(&aWalHdr[12], pWal->nCkpt);
    sqlite3Put4byte(&aWalHdr[12], iCkpt);
    if( pWal->nCkpt==0 ) sqlite3FastRandomness(&pWal->sPrng, 8, pWal->hdr.aSalt);
    memcpy(&aWalHdr[16], pWal->hdr.aSalt, 8);
    walChecksumBytes(1, aWalHdr, WAL_HDRSIZE-2*4, 0, aCksum);
    sqlite3Put4byte(&aWalHdr[24], aCksum[0]);
    sqlite3Put4byte(&aWalHdr[28], aCksum[1]);
    

    pWal->szPage = szPage;
    pWal->hdr.bigEndCksum = SQLITE_BIGENDIAN;
    pWal->hdr.aFrameCksum[0] = aCksum[0];
    pWal->hdr.aFrameCksum[1] = aCksum[1];
    pWal->truncateOnCommit = 1;

    rc = sqlite3OsWrite(pWal->pWalFd, aWalHdr, sizeof(aWalHdr), 0);
    rc = sqlite3OsWrite(pWal->apWalFd[iApp], aWalHdr, sizeof(aWalHdr), 0);
    WALTRACE(("WAL%p: wal-header write %s\n", pWal, rc ? "failed" : "ok"));
    if( rc!=SQLITE_OK ){
      return rc;
    }

    /* Sync the header (unless SQLITE_IOCAP_SEQUENTIAL is true or unless
    ** all syncing is turned off by PRAGMA synchronous=OFF).  Otherwise
    ** an out-of-order write following a WAL restart could result in
    ** database corruption.  See the ticket:
    **
    **     https://sqlite.org/src/info/ff5be73dee
    */
    if( pWal->syncHeader ){
      rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags));
      rc = sqlite3OsSync(pWal->apWalFd[iApp], CKPT_SYNC_FLAGS(sync_flags));
      if( rc ) return rc;
    }
  }
  assert( (int)pWal->szPage==szPage );

  /* Setup information needed to write frames into the WAL */
  w.pWal = pWal;
  w.pFd = pWal->pWalFd;
  w.pFd = pWal->apWalFd[iApp];
  w.iSyncPoint = 0;
  w.syncFlags = sync_flags;
  w.szPage = szPage;
  iOffset = walFrameOffset(iFrame+1, szPage);
  szFrame = szPage + WAL_FRAME_HDRSIZE;

  /* Write all frames into the log file exactly once */
  for(p=pList; p; p=p->pDirty){
    int nDbSize;   /* 0 normally.  Positive == commit flag */

    /* Check if this page has already been written into the wal file by
    ** the current transaction. If so, overwrite the existing frame and
    ** set Wal.writeLock to WAL_WRITELOCK_RECKSUM - indicating that 
    ** checksums must be recomputed when the transaction is committed.  */
    if( iFirst && (p->pDirty || isCommit==0) ){
      u32 iWrite = 0;
      VVA_ONLY(rc =) sqlite3WalFindFrame(pWal, p->pgno, &iWrite);
      VVA_ONLY(rc =) walSearchWal(pWal, iApp, p->pgno, &iWrite);
      assert( rc==SQLITE_OK || iWrite==0 );
      if( iWrite && bWal2 ){
        walExternalDecode(iWrite, &iWrite);
      }
      if( iWrite>=iFirst ){
        i64 iOff = walFrameOffset(iWrite, szPage) + WAL_FRAME_HDRSIZE;
        void *pData;
        if( pWal->iReCksum==0 || iWrite<pWal->iReCksum ){
          pWal->iReCksum = iWrite;
        }
#if defined(SQLITE_HAS_CODEC)
        if( (pData = sqlite3PagerCodec(p))==0 ) return SQLITE_NOMEM;
#else
        pData = p->pData;
#endif
        rc = sqlite3OsWrite(pWal->pWalFd, pData, szPage, iOff);
        rc = sqlite3OsWrite(pWal->apWalFd[iApp], pData, szPage, iOff);
        if( rc ) return rc;
        p->flags &= ~PGHDR_WAL_APPEND;
        continue;
      }
    }

    iFrame++;
3673
3674
3675
3676
3677
3678
3679
3680

3681
3682
3683
3684
3685
3686
3687
3688

3689
3690
3691
3692
3693
3694
3695
4882
4883
4884
4885
4886
4887
4888

4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905







-
+








+







  ** boundary is crossed.  Only the part of the WAL prior to the last
  ** sector boundary is synced; the part of the last frame that extends
  ** past the sector boundary is written after the sync.
  */
  if( isCommit && WAL_SYNC_FLAGS(sync_flags)!=0 ){
    int bSync = 1;
    if( pWal->padToSectorBoundary ){
      int sectorSize = sqlite3SectorSize(pWal->pWalFd);
      int sectorSize = sqlite3SectorSize(w.pFd);
      w.iSyncPoint = ((iOffset+sectorSize-1)/sectorSize)*sectorSize;
      bSync = (w.iSyncPoint==iOffset);
      testcase( bSync );
      while( iOffset<w.iSyncPoint ){
        rc = walWriteOneFrame(&w, pLast, nTruncate, iOffset);
        if( rc ) return rc;
        iOffset += szFrame;
        nExtra++;
        assert( pLast!=0 );
      }
    }
    if( bSync ){
      assert( rc==SQLITE_OK );
      rc = sqlite3OsSync(w.pFd, WAL_SYNC_FLAGS(sync_flags));
    }
  }
3708
3709
3710
3711
3712
3713
3714
3715

3716
3717
3718
3719

3720

3721
3722
3723
3724

3725
3726
3727
3728
3729
3730
3731
3732

3733
3734
3735
3736
3737
3738
3739









3740


3741
3742
3743
3744
3745
3746
3747
4918
4919
4920
4921
4922
4923
4924

4925
4926
4927
4928

4929
4930
4931
4932
4933
4934

4935
4936
4937
4938
4939
4940
4941
4942

4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959

4960
4961
4962
4963
4964
4965
4966
4967
4968







-
+



-
+

+



-
+







-
+







+
+
+
+
+
+
+
+
+
-
+
+







  }

  /* Append data to the wal-index. It is not necessary to lock the 
  ** wal-index to do this as the SQLITE_SHM_WRITE lock held on the wal-index
  ** guarantees that there are no other writers, and no data that may
  ** be in use by existing readers is being overwritten.
  */
  iFrame = pWal->hdr.mxFrame;
  iFrame = walidxGetMxFrame(&pWal->hdr, iApp);
  for(p=pList; p && rc==SQLITE_OK; p=p->pDirty){
    if( (p->flags & PGHDR_WAL_APPEND)==0 ) continue;
    iFrame++;
    rc = walIndexAppend(pWal, iFrame, p->pgno);
    rc = walIndexAppend(pWal, iApp, iFrame, p->pgno);
  }
  assert( pLast!=0 || nExtra==0 );
  while( rc==SQLITE_OK && nExtra>0 ){
    iFrame++;
    nExtra--;
    rc = walIndexAppend(pWal, iFrame, pLast->pgno);
    rc = walIndexAppend(pWal, iApp, iFrame, pLast->pgno);
  }

  if( rc==SQLITE_OK ){
    /* Update the private copy of the header. */
    pWal->hdr.szPage = (u16)((szPage&0xff00) | (szPage>>16));
    testcase( szPage<=32768 );
    testcase( szPage>=65536 );
    pWal->hdr.mxFrame = iFrame;
    walidxSetMxFrame(&pWal->hdr, iApp, iFrame);
    if( isCommit ){
      pWal->hdr.iChange++;
      pWal->hdr.nPage = nTruncate;
    }
    /* If this is a commit, update the wal-index header too. */
    if( isCommit ){
      walIndexWriteHdr(pWal);
      if( bWal2 ){
        int iOther = !walidxGetFile(&pWal->hdr);
        if( walidxGetMxFrame(&pWal->hdr, iOther) 
            && !walCkptInfo(pWal)->nBackfill 
        ){
          pWal->iCallback = walidxGetMxFrame(&pWal->hdr, 0);
          pWal->iCallback += walidxGetMxFrame(&pWal->hdr, 1);
        }
      }else{
      pWal->iCallback = iFrame;
        pWal->iCallback = iFrame;
      }
    }
  }

  WALTRACE(("WAL%p: frame write %s\n", pWal, rc ? "failed" : "ok"));
  return rc;
}

3778
3779
3780
3781
3782
3783
3784





3785
3786

3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797










3798
3799

3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820






















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
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
5024




















5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058

5059
5060
5061
5062
5063
5064
5065
5066
5067
5068


5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085

5086
5087
5088
5089
5090
5091

5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105


5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119







+
+
+
+
+

-
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+

+







-
+
+
+







-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+





-
+
+
+
+
+


+
+
+



+
-
-
+
+
+

+
+
+







  /* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked
  ** in the SQLITE_CHECKPOINT_PASSIVE mode. */
  assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 );

  if( pWal->readOnly ) return SQLITE_READONLY;
  WALTRACE(("WAL%p: checkpoint begins\n", pWal));

  /* Enable blocking locks, if possible. If blocking locks are successfully
  ** enabled, set xBusy2=0 so that the busy-handler is never invoked. */
  sqlite3WalDb(pWal, db);
  (void)walEnableBlocking(pWal);

  /* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive 
  ** "checkpoint" lock on the database file. */
  ** "checkpoint" lock on the database file.
  rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
  if( rc ){
    /* EVIDENCE-OF: R-10421-19736 If any other process is running a
    ** checkpoint operation at the same time, the lock cannot be obtained and
    ** SQLITE_BUSY is returned.
    ** EVIDENCE-OF: R-53820-33897 Even if there is a busy-handler configured,
    ** it will not be invoked in this case.
    */
    testcase( rc==SQLITE_BUSY );
    testcase( xBusy!=0 );
    return rc;
  ** EVIDENCE-OF: R-10421-19736 If any other process is running a
  ** checkpoint operation at the same time, the lock cannot be obtained and
  ** SQLITE_BUSY is returned.
  ** EVIDENCE-OF: R-53820-33897 Even if there is a busy-handler configured,
  ** it will not be invoked in this case.
  */
  rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
  testcase( rc==SQLITE_BUSY );
  testcase( rc!=SQLITE_OK && xBusy2!=0 );
  if( rc==SQLITE_OK ){
  }
  pWal->ckptLock = 1;
    pWal->ckptLock = 1;

  /* IMPLEMENTATION-OF: R-59782-36818 The SQLITE_CHECKPOINT_FULL, RESTART and
  ** TRUNCATE modes also obtain the exclusive "writer" lock on the database
  ** file.
  **
  ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained
  ** immediately, and a busy-handler is configured, it is invoked and the
  ** writer lock retried until either the busy-handler returns 0 or the
  ** lock is successfully obtained.
  */
  if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){
    rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_WRITE_LOCK, 1);
    if( rc==SQLITE_OK ){
      pWal->writeLock = 1;
    }else if( rc==SQLITE_BUSY ){
      eMode2 = SQLITE_CHECKPOINT_PASSIVE;
      xBusy2 = 0;
      rc = SQLITE_OK;
    }
  }

    /* IMPLEMENTATION-OF: R-59782-36818 The SQLITE_CHECKPOINT_FULL, RESTART and
    ** TRUNCATE modes also obtain the exclusive "writer" lock on the database
    ** file.
    **
    ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained
    ** immediately, and a busy-handler is configured, it is invoked and the
    ** writer lock retried until either the busy-handler returns 0 or the
    ** lock is successfully obtained.
    */
    if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){
      rc = walBusyLock(pWal, xBusy2, pBusyArg, WAL_WRITE_LOCK, 1);
      if( rc==SQLITE_OK ){
        pWal->writeLock = 1;
      }else if( rc==SQLITE_BUSY ){
        eMode2 = SQLITE_CHECKPOINT_PASSIVE;
        xBusy2 = 0;
        rc = SQLITE_OK;
      }
    }
  }


  /* Read the wal-index header. */
  if( rc==SQLITE_OK ){
    walDisableBlocking(pWal);
    rc = walIndexReadHdr(pWal, &isChanged);
    (void)walEnableBlocking(pWal);
    if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){
      sqlite3OsUnfetch(pWal->pDbFd, 0, 0);
    }
  }

  /* Copy data from the log to the database file. */
  if( rc==SQLITE_OK ){
    if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
    if( (walPagesize(pWal)!=nBuf) 
     && ((pWal->hdr.mxFrame2 & 0x7FFFFFFF) || pWal->hdr.mxFrame)
    ){
      rc = SQLITE_CORRUPT_BKPT;
    }else{
      rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags, zBuf);
    }

    /* If no error occurred, set the output variables. */
    if( rc==SQLITE_OK || rc==SQLITE_BUSY ){
      if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame;
      if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill);
      if( pnLog ){
        *pnLog = walidxGetMxFrame(&pWal->hdr,0)+walidxGetMxFrame(&pWal->hdr,1);
      }
      if( pnCkpt ){
        if( isWalMode2(pWal) ){
          if( (int)(walCkptInfo(pWal)->nBackfill) ){
            *pnCkpt = walidxGetMxFrame(&pWal->hdr, !walidxGetFile(&pWal->hdr));
          }else{
            *pnCkpt = 0;
          }
        }else{
          *pnCkpt = walCkptInfo(pWal)->nBackfill;
        }
      }
    }
  }

  if( isChanged ){
  if( isChanged && pWal->bClosing==0 ){
    /* If a new wal-index header was loaded before the checkpoint was 
    ** performed, then the pager-cache associated with pWal is now
    ** out of date. So zero the cached wal-index header to ensure that
    ** next time the pager opens a snapshot on this database it knows that
    ** the cache needs to be reset.
    */
    **
    ** Except, do not do this if the wal is being closed. In this case
    ** the caller needs the wal-index header to check if the database is
    ** in wal2 mode and the "other" wal file also needs to be checkpointed.
    ** Besides, the pager cache will not be used again in this case. */
    memset(&pWal->hdr, 0, sizeof(WalIndexHdr));
  }

  walDisableBlocking(pWal);
  sqlite3WalDb(pWal, 0);

  /* Release the locks. */
  sqlite3WalEndWriteTransaction(pWal);
  if( pWal->ckptLock ){
  walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1);
  pWal->ckptLock = 0;
    walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1);
    pWal->ckptLock = 0;
  }
  WALTRACE(("WAL%p: checkpoint %s\n", pWal, rc ? "failed" : "ok"));
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
  if( rc==SQLITE_BUSY_TIMEOUT ) rc = SQLITE_BUSY;
#endif
  return (rc==SQLITE_OK && eMode!=eMode2 ? SQLITE_BUSY : rc);
}

/* Return the value to pass to a sqlite3_wal_hook callback, the
** number of frames in the WAL at the point of the last commit since
** sqlite3WalCallback() was called.  If no commits have occurred since
** the last call, then return 0.
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
3923
3924
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165


5166
5167
5168
5169

5170
5171

5172
5173
5174
5175
5176
5177
5178
5179
5180







+









-
-
+
+


-
+

-
+
+







** If op is negative, then do a dry-run of the op==1 case but do
** not actually change anything. The pager uses this to see if it
** should acquire the database exclusive lock prior to invoking
** the op==1 case.
*/
int sqlite3WalExclusiveMode(Wal *pWal, int op){
  int rc;

  assert( pWal->writeLock==0 );
  assert( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE || op==-1 );

  /* pWal->readLock is usually set, but might be -1 if there was a 
  ** prior error while attempting to acquire are read-lock. This cannot 
  ** happen if the connection is actually in exclusive mode (as no xShmLock
  ** locks are taken in this case). Nor should the pager attempt to
  ** upgrade to exclusive-mode following such an error.
  */
  assert( pWal->readLock>=0 || pWal->lockError );
  assert( pWal->readLock>=0 || (op<=0 && pWal->exclusiveMode==0) );
  assert( pWal->readLock!=WAL_LOCK_NONE || pWal->lockError );
  assert( pWal->readLock!=WAL_LOCK_NONE || (op<=0 && pWal->exclusiveMode==0) );

  if( op==0 ){
    if( pWal->exclusiveMode!=WAL_NORMAL_MODE ){
    if( pWal->exclusiveMode ){
      pWal->exclusiveMode = WAL_NORMAL_MODE;
      if( walLockShared(pWal, WAL_READ_LOCK(pWal->readLock))!=SQLITE_OK ){
      rc = walLockShared(pWal, WAL_READ_LOCK(pWal->readLock));
      if( rc!=SQLITE_OK ){
        pWal->exclusiveMode = WAL_EXCLUSIVE_MODE;
      }
      rc = pWal->exclusiveMode==WAL_NORMAL_MODE;
    }else{
      /* Already in locking_mode=NORMAL */
      rc = 0;
    }
3948
3949
3950
3951
3952
3953
3954



3955
3956
3957
3958

3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975




3976
3977
3978
3979
3980
3981
3982
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216

5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233

5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244







+
+
+



-
+
















-
+
+
+
+







** every other subsystem, so the WAL module can put whatever it needs
** in the object.
*/
int sqlite3WalSnapshotGet(Wal *pWal, sqlite3_snapshot **ppSnapshot){
  int rc = SQLITE_OK;
  WalIndexHdr *pRet;
  static const u32 aZero[4] = { 0, 0, 0, 0 };

  /* Snapshots may not be used with wal2 mode databases. */
  if( isWalMode2(pWal) ) return SQLITE_ERROR;

  assert( pWal->readLock>=0 && pWal->writeLock==0 );

  if( memcmp(&pWal->hdr.aFrameCksum[0],aZero,16)==0 ){
  if( memcmp(&pWal->hdr.aFrameCksum[0],aZero,8)==0 ){
    *ppSnapshot = 0;
    return SQLITE_ERROR;
  }
  pRet = (WalIndexHdr*)sqlite3_malloc(sizeof(WalIndexHdr));
  if( pRet==0 ){
    rc = SQLITE_NOMEM_BKPT;
  }else{
    memcpy(pRet, &pWal->hdr, sizeof(WalIndexHdr));
    *ppSnapshot = (sqlite3_snapshot*)pRet;
  }

  return rc;
}

/* Try to open on pSnapshot when the next read-transaction starts
*/
void sqlite3WalSnapshotOpen(Wal *pWal, sqlite3_snapshot *pSnapshot){
void sqlite3WalSnapshotOpen(
  Wal *pWal, 
  sqlite3_snapshot *pSnapshot
){
  pWal->pSnapshot = (WalIndexHdr*)pSnapshot;
}

/* 
** Return a +ve value if snapshot p1 is newer than p2. A -ve value if
** p1 is older than p2 and zero if p1 and p2 are the same snapshot.
*/
4002
4003
4004
4005
4006
4007
4008




4009
4010
4011
4012
4013
4014
4015
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281







+
+
+
+







** If the snapshot is not available, SQLITE_ERROR is returned. Or, if
** the CHECKPOINTER lock cannot be obtained, SQLITE_BUSY. If any error
** occurs (any value other than SQLITE_OK is returned), the CHECKPOINTER
** lock is released before returning.
*/
int sqlite3WalSnapshotCheck(Wal *pWal, sqlite3_snapshot *pSnapshot){
  int rc;

  /* Snapshots may not be used with wal2 mode databases. */
  if( isWalMode2(pWal) ) return SQLITE_ERROR;

  rc = walLockShared(pWal, WAL_CKPT_LOCK);
  if( rc==SQLITE_OK ){
    WalIndexHdr *pNew = (WalIndexHdr*)pSnapshot;
    if( memcmp(pNew->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt))
     || pNew->mxFrame<walCkptInfo(pWal)->nBackfillAttempted
    ){
      rc = SQLITE_ERROR_SNAPSHOT;
4042
4043
4044
4045
4046
4047
4048
4049

4050
4051
4052
4053
4054
4055
4056
4057
4058
4059

4060
4061
4062
4063








4064
5308
5309
5310
5311
5312
5313
5314

5315
5316
5317
5318
5319
5320
5321
5322
5323

5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338







-
+








-

+




+
+
+
+
+
+
+
+

  return (pWal ? pWal->szPage : 0);
}
#endif

/* Return the sqlite3_file object for the WAL file
*/
sqlite3_file *sqlite3WalFile(Wal *pWal){
  return pWal->pWalFd;
  return pWal->apWalFd[0];
}

/* 
** Return the values required by sqlite3_wal_info().
*/
int sqlite3WalInfo(Wal *pWal, u32 *pnPrior, u32 *pnFrame){
  int rc = SQLITE_OK;
  if( pWal ){
    *pnFrame = pWal->hdr.mxFrame;
    *pnPrior = pWal->nPriorFrame;
    *pnFrame = walidxGetMxFrame(&pWal->hdr, walidxGetFile(&pWal->hdr));
  }
  return rc;
}

/* 
** Return the journal mode used by this Wal object.
*/
int sqlite3WalJournalMode(Wal *pWal){
  assert( pWal );
  return (isWalMode2(pWal) ? PAGER_JOURNALMODE_WAL2 : PAGER_JOURNALMODE_WAL);
}

#endif /* #ifndef SQLITE_OMIT_WAL */

Changes to src/wal.h.

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
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







-
+







-
+










+










-
+







/* Macros for extracting appropriate sync flags for either transaction
** commits (WAL_SYNC_FLAGS(X)) or for checkpoint ops (CKPT_SYNC_FLAGS(X)):
*/
#define WAL_SYNC_FLAGS(X)   ((X)&0x03)
#define CKPT_SYNC_FLAGS(X)  (((X)>>2)&0x03)

#ifdef SQLITE_OMIT_WAL
# define sqlite3WalOpen(x,y,z)                   0
# define sqlite3WalOpen(w,x,y,z)                 0
# define sqlite3WalLimit(x,y)
# define sqlite3WalClose(v,w,x,y,z)              0
# define sqlite3WalBeginReadTransaction(y,z)     0
# define sqlite3WalEndReadTransaction(z)
# define sqlite3WalDbsize(y)                     0
# define sqlite3WalBeginWriteTransaction(y)      0
# define sqlite3WalEndWriteTransaction(x)        0
# define sqlite3WalUndo(x,y,z)                   0
# define sqlite3WalUndo(w,x,y,z)                 0
# define sqlite3WalSavepoint(y,z)
# define sqlite3WalSavepointUndo(y,z)            0
# define sqlite3WalFrames(u,v,w,x,y,z)           0
# define sqlite3WalCheckpoint(q,r,s,t,u,v,w,x,y,z) 0
# define sqlite3WalCallback(z)                   0
# define sqlite3WalExclusiveMode(y,z)            0
# define sqlite3WalHeapMemory(z)                 0
# define sqlite3WalFramesize(z)                  0
# define sqlite3WalFindFrame(x,y,z)              0
# define sqlite3WalFile(x)                       0
# define sqlite3WalJournalMode(x)                0
#else

#define WAL_SAVEPOINT_NDATA 4

/* Connection to a write-ahead log (WAL) file. 
** There is one object of this type for each pager. 
*/
typedef struct Wal Wal;

/* Open and close a connection to a write-ahead log. */
int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *, int, i64, Wal**);
int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *,int,i64,int,Wal**);
int sqlite3WalClose(Wal *pWal, sqlite3*, int sync_flags, int, u8 *);

/* Set the limiting size of a WAL file. */
void sqlite3WalLimit(Wal*, i64);

/* Used by readers to open (lock) and close (unlock) a snapshot.  A 
** snapshot is like a read-transaction.  It is the state of the database
79
80
81
82
83
84
85
86

87
88
89
90
91
92
93
80
81
82
83
84
85
86

87
88
89
90
91
92
93
94







-
+







Pgno sqlite3WalDbsize(Wal *pWal);

/* Obtain or release the WRITER lock. */
int sqlite3WalBeginWriteTransaction(Wal *pWal);
int sqlite3WalEndWriteTransaction(Wal *pWal);

/* Undo any frames written (but not committed) to the log */
int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx);
int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx, int);

/* Return an integer that records the current (uncommitted) write
** position in the WAL */
void sqlite3WalSavepoint(Wal *pWal, u32 *aWalData);

/* Move the write position of the WAL back to iFrame.  Called in
** response to a ROLLBACK TO command. */
150
151
152
153
154
155
156











157
158
159
160
161
162
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174







+
+
+
+
+
+
+
+
+
+
+






** stored in each frame (i.e. the db page-size when the WAL was created).
*/
int sqlite3WalFramesize(Wal *pWal);
#endif

/* Return the sqlite3_file object for the WAL file */
sqlite3_file *sqlite3WalFile(Wal *pWal);

/* Return the journal mode (WAL or WAL2) used by this Wal object. */
int sqlite3WalJournalMode(Wal *pWal);

#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
int sqlite3WalWriteLock(Wal *pWal, int bLock);
void sqlite3WalDb(Wal *pWal, sqlite3 *db);
#endif

/* sqlite3_wal_info() data */
int sqlite3WalInfo(Wal *pWal, u32 *pnPrior, u32 *pnFrame);

/* sqlite3_wal_info() data */
int sqlite3WalInfo(Wal *pWal, u32 *pnPrior, u32 *pnFrame);

#endif /* ifndef SQLITE_OMIT_WAL */
#endif /* SQLITE_WAL_H */

Changes to src/walker.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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







** an SQL statement.
*/
#include "sqliteInt.h"
#include <stdlib.h>
#include <string.h>


#if !defined(SQLITE_OMIT_WINDOWFUNC)
/*
** Walk all expressions linked into the list of Window objects passed
** as the second argument.
*/
static int walkWindowList(Walker *pWalker, Window *pList, int bOneOnly){
  Window *pWin;
  for(pWin=pList; pWin; pWin=pWin->pNextWin){
    int rc;
    rc = sqlite3WalkExprList(pWalker, pWin->pOrderBy);
    if( rc ) return WRC_Abort;
    rc = sqlite3WalkExprList(pWalker, pWin->pPartition);
    if( rc ) return WRC_Abort;
    rc = sqlite3WalkExpr(pWalker, pWin->pFilter);
    if( rc ) return WRC_Abort;
    rc = sqlite3WalkExpr(pWalker, pWin->pStart);
    if( rc ) return WRC_Abort;
    rc = sqlite3WalkExpr(pWalker, pWin->pEnd);
    if( rc ) return WRC_Abort;
    if( bOneOnly ) break;
  }
  return WRC_Continue;
}
#endif

/*
** Walk an expression tree.  Invoke the callback once for each node
** of the expression, while descending.  (In other words, the callback
** is invoked before visiting children.)
**
** The return value from the callback should be one of the WRC_*
** constants to specify how to proceed with the walk.
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
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







-
-
+
+

+


+
-
+

+
-
-
-
+
+
+

-
+
-
-
-
-
-
+
+

+







  int rc;
  testcase( ExprHasProperty(pExpr, EP_TokenOnly) );
  testcase( ExprHasProperty(pExpr, EP_Reduced) );
  while(1){
    rc = pWalker->xExprCallback(pWalker, pExpr);
    if( rc ) return rc & WRC_Abort;
    if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){
      if( pExpr->pLeft && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
       assert( pExpr->x.pList==0 || pExpr->pRight==0 );
      assert( pExpr->x.pList==0 || pExpr->pRight==0 );
      if( pExpr->pLeft && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
      if( pExpr->pRight ){
        assert( !ExprHasProperty(pExpr, EP_WinFunc) );
        pExpr = pExpr->pRight;
        continue;
      }else if( ExprUseXSelect(pExpr) ){
      }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
        assert( !ExprHasProperty(pExpr, EP_WinFunc) );
        if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort;
      }else{
      }else if( pExpr->x.pList ){
        if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
      }
        if( pExpr->x.pList ){
          if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
        }
#ifndef SQLITE_OMIT_WINDOWFUNC
      if( ExprHasProperty(pExpr, EP_WinFunc) ){
        if( ExprHasProperty(pExpr, EP_WinFunc) ){
        Window *pWin = pExpr->y.pWin;
        if( sqlite3WalkExprList(pWalker, pWin->pPartition) ) return WRC_Abort;
        if( sqlite3WalkExprList(pWalker, pWin->pOrderBy) ) return WRC_Abort;
        if( sqlite3WalkExpr(pWalker, pWin->pFilter) ) return WRC_Abort;
      }
          if( walkWindowList(pWalker, pExpr->y.pWin, 1) ) return WRC_Abort;
        }
#endif
      }
    }
    break;
  }
  return WRC_Continue;
}
int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){
  return pExpr ? walkExpr(pWalker,pExpr) : WRC_Continue;
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
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







+
+
+
+
+
+
+
+
+
+














+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+













-
+


-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+



-
+







  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)
  if( p->pWinDefn ){
    Parse *pParse;
    if( pWalker->xSelectCallback2==sqlite3WalkWinDefnDummyCallback
     || ((pParse = pWalker->pParse)!=0 && IN_RENAME_OBJECT)
#ifndef SQLITE_OMIT_CTE
     || pWalker->xSelectCallback2==sqlite3SelectPopWith
#endif
    ){
      /* The following may return WRC_Abort if there are unresolvable
      ** symbols (e.g. a table that does not exist) in a window definition. */
      int rc = walkWindowList(pWalker, p->pWinDefn, 0);
      return rc;
    }
  }
#endif
  return WRC_Continue;
}

/*
** Walk the parse trees associated with all subqueries in the
** FROM clause of SELECT statement p.  Do not invoke the select
** callback on p, but do invoke it on each FROM clause subquery
** and on any subqueries further down in the tree.  Return 
** WRC_Abort or WRC_Continue;
*/
int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
  SrcList *pSrc;
  int i;
  struct SrcList_item *pItem;
  SrcItem *pItem;

  pSrc = p->pSrc;
  assert( pSrc!=0 );
  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;
  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
161
162
163
164
165
166
167





































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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
    if( pWalker->xSelectCallback2 ){
      pWalker->xSelectCallback2(pWalker, p);
    }
    p = p->pPrior;
  }while( p!=0 );
  return WRC_Continue;
}

/* Increase the walkerDepth when entering a subquery, and
** descrease when leaving the subquery.
*/
int sqlite3WalkerDepthIncrease(Walker *pWalker, Select *pSelect){
  UNUSED_PARAMETER(pSelect);
  pWalker->walkerDepth++;
  return WRC_Continue;
}
void sqlite3WalkerDepthDecrease(Walker *pWalker, Select *pSelect){
  UNUSED_PARAMETER(pSelect);
  pWalker->walkerDepth--;
}


/*
** No-op routine for the parse-tree walker.
**
** When this routine is the Walker.xExprCallback then expression trees
** are walked without any actions being taken at each node.  Presumably,
** when this routine is used for Walker.xExprCallback then 
** Walker.xSelectCallback is set to do something useful for every 
** subquery in the parser tree.
*/
int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
  UNUSED_PARAMETER2(NotUsed, NotUsed2);
  return WRC_Continue;
}

/*
** No-op routine for the parse-tree walker for SELECT statements.
** subquery in the parser tree.
*/
int sqlite3SelectWalkNoop(Walker *NotUsed, Select *NotUsed2){
  UNUSED_PARAMETER2(NotUsed, NotUsed2);
  return WRC_Continue;
}

Changes to src/where.c.

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
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







-
-
+
+
+
+
+
+
+
+




-
-
-
-
-
-

















+
-
-
+
+
+
+
+


-
+







**
** This object is not an API and can be changed from one release to the
** next.  As long as allocateIndexInfo() and sqlite3_vtab_collation()
** agree on the structure, all will be well.
*/
typedef struct HiddenIndexInfo HiddenIndexInfo;
struct HiddenIndexInfo {
  WhereClause *pWC;   /* The Where clause being analyzed */
  Parse *pParse;      /* The parsing context */
  WhereClause *pWC;        /* The Where clause being analyzed */
  Parse *pParse;           /* The parsing context */
  int eDistinct;           /* Value to return from sqlite3_vtab_distinct() */
  u32 mIn;                 /* Mask of terms that are <col> IN (...) */
  u32 mHandleIn;           /* Terms that vtab will handle as <col> IN (...) */
  sqlite3_value *aRhs[1];  /* RHS values for constraints. MUST BE LAST
                           ** because extra space is allocated to hold up
                           ** to nTerm such values */
};

/* Forward declaration of methods */
static int whereLoopResize(sqlite3*, WhereLoop*, int);

/* Test variable that can be set to enable WHERE tracing */
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
/***/ int sqlite3WhereTrace = 0;
#endif


/*
** Return the estimated number of output rows from a WHERE clause
*/
LogEst sqlite3WhereOutputRowCount(WhereInfo *pWInfo){
  return pWInfo->nRowOut;
}

/*
** Return one of the WHERE_DISTINCT_xxxxx values to indicate how this
** WHERE clause returns outputs for DISTINCT processing.
*/
int sqlite3WhereIsDistinct(WhereInfo *pWInfo){
  return pWInfo->eDistinct;
}

/*
** Return the number of ORDER BY terms that are satisfied by the
** Return TRUE if the WHERE clause returns rows in ORDER BY order.
** Return FALSE if the output needs to be sorted.
** WHERE clause.  A return of 0 means that the output must be
** completely sorted.  A return equal to the number of ORDER BY
** terms means that no sorting is needed at all.  A return that
** is positive but less than the number of ORDER BY terms means that
** block sorting is required.
*/
int sqlite3WhereIsOrdered(WhereInfo *pWInfo){
  return pWInfo->nOBSat;
  return pWInfo->nOBSat<0 ? 0 : pWInfo->nOBSat;
}

/*
** In the ORDER BY LIMIT optimization, if the inner-most loop is known
** to emit rows in increasing order, and if the last row emitted by the
** inner-most loop did not fit within the sorter, then we can skip all
** subsequent rows for the current iteration of the inner loop (because they
94
95
96
97
98
99
100























101




102
103
104
105
106
107
108
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+







  if( !pWInfo->bOrderedInnerLoop ){
    /* The ORDER BY LIMIT optimization does not apply.  Jump to the 
    ** continuation of the inner-most loop. */
    return pWInfo->iContinue;
  }
  pInner = &pWInfo->a[pWInfo->nLevel-1];
  assert( pInner->addrNxt!=0 );
  return pInner->pRJ ? pWInfo->iContinue : pInner->addrNxt;
}

/*
** While generating code for the min/max optimization, after handling
** the aggregate-step call to min() or max(), check to see if any
** additional looping is required.  If the output order is such that
** we are certain that the correct answer has already been found, then
** code an OP_Goto to by pass subsequent processing.
**
** Any extra OP_Goto that is coded here is an optimization.  The
** correct answer should be obtained regardless.  This OP_Goto just
** makes the answer appear faster.
*/
void sqlite3WhereMinMaxOptEarlyOut(Vdbe *v, WhereInfo *pWInfo){
  WhereLevel *pInner;
  int i;
  if( !pWInfo->bOrderedInnerLoop ) return;
  if( pWInfo->nOBSat==0 ) return;
  for(i=pWInfo->nLevel-1; i>=0; i--){
    pInner = &pWInfo->a[i];
    if( (pInner->pWLoop->wsFlags & WHERE_COLUMN_IN)!=0 ){
      sqlite3VdbeGoto(v, pInner->addrNxt);
  return pInner->addrNxt;
      return;
    }
  }
  sqlite3VdbeGoto(v, pWInfo->iBreak);
}

/*
** Return the VDBE address or label to jump to in order to continue
** immediately with the next row of a WHERE clause.
*/
int sqlite3WhereContinueLabel(WhereInfo *pWInfo){
116
117
118
119
120
121
122
123

124
125
126
127
128
129
130
146
147
148
149
150
151
152

153
154
155
156
157
158
159
160







-
+







*/
int sqlite3WhereBreakLabel(WhereInfo *pWInfo){
  return pWInfo->iBreak;
}

/*
** Return ONEPASS_OFF (0) if an UPDATE or DELETE statement is unable to
** operate directly on the rowis returned by a WHERE clause.  Return
** operate directly on the rowids returned by a WHERE clause.  Return
** ONEPASS_SINGLE (1) if the statement can operation directly because only
** a single row is to be changed.  Return ONEPASS_MULTI (2) if the one-pass
** optimization can be used on multiple 
**
** If the ONEPASS optimization is used (if this routine returns true)
** then also write the indices of open cursors used by ONEPASS
** into aiCur[0] and aiCur[1].  iaCur[0] gets the cursor of the data
142
143
144
145
146
147
148








149
150
151
152
153
154
155
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193







+
+
+
+
+
+
+
+







    sqlite3DebugPrintf("%s cursors: %d %d\n",
         pWInfo->eOnePass==ONEPASS_SINGLE ? "ONEPASS_SINGLE" : "ONEPASS_MULTI",
         aiCur[0], aiCur[1]);
  }
#endif
  return pWInfo->eOnePass;
}

/*
** Return TRUE if the WHERE loop uses the OP_DeferredSeek opcode to move
** the data cursor to the row selected by the index cursor.
*/
int sqlite3WhereUsesDeferredSeek(WhereInfo *pWInfo){
  return pWInfo->bDeferredSeek;
}

/*
** Move the content of pSrc into pDest
*/
static void whereOrMove(WhereOrSet *pDest, WhereOrSet *pSrc){
  pDest->n = pSrc->n;
  memcpy(pDest->a, pSrc->a, pDest->n*sizeof(pDest->a[0]));
198
199
200
201
202
203
204





205

206
207
208
209
210
211
























212
213
214
215
216
217
218
219
220
221
222
223
224












225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244

245
246

247
248

249
250
251
252

253
254
255
256

257
258
259
260
261
262
263
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







+
+
+
+
+
-
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+













+
+
+
+
+
+
+
+
+
+
+
+




















+


+

-
+



-
+



-
+







/*
** Return the bitmask for the given cursor number.  Return 0 if
** iCursor is not in the set.
*/
Bitmask sqlite3WhereGetMask(WhereMaskSet *pMaskSet, int iCursor){
  int i;
  assert( pMaskSet->n<=(int)sizeof(Bitmask)*8 );
  assert( pMaskSet->n>0 || pMaskSet->ix[0]<0 );
  assert( iCursor>=-1 );
  if( pMaskSet->ix[0]==iCursor ){
    return 1;
  }
  for(i=0; i<pMaskSet->n; i++){
  for(i=1; i<pMaskSet->n; i++){
    if( pMaskSet->ix[i]==iCursor ){
      return MASKBIT(i);
    }
  }
  return 0;
}

/* Allocate memory that is automatically freed when pWInfo is freed.
*/
void *sqlite3WhereMalloc(WhereInfo *pWInfo, u64 nByte){
  WhereMemBlock *pBlock;
  pBlock = sqlite3DbMallocRawNN(pWInfo->pParse->db, nByte+sizeof(*pBlock));
  if( pBlock ){
    pBlock->pNext = pWInfo->pMemToFree;
    pBlock->sz = nByte;
    pWInfo->pMemToFree = pBlock;
    pBlock++;
  }
  return (void*)pBlock;
}
void *sqlite3WhereRealloc(WhereInfo *pWInfo, void *pOld, u64 nByte){
  void *pNew = sqlite3WhereMalloc(pWInfo, nByte);
  if( pNew && pOld ){
    WhereMemBlock *pOldBlk = (WhereMemBlock*)pOld;
    pOldBlk--;
    assert( pOldBlk->sz<nByte );
    memcpy(pNew, pOld, pOldBlk->sz);
  }
  return pNew;
}

/*
** Create a new mask for cursor iCursor.
**
** There is one cursor per table in the FROM clause.  The number of
** tables in the FROM clause is limited by a test early in the
** sqlite3WhereBegin() routine.  So we know that the pMaskSet->ix[]
** array will never overflow.
*/
static void createMask(WhereMaskSet *pMaskSet, int iCursor){
  assert( pMaskSet->n < ArraySize(pMaskSet->ix) );
  pMaskSet->ix[pMaskSet->n++] = iCursor;
}

/*
** If the right-hand branch of the expression is a TK_COLUMN, then return
** a pointer to the right-hand branch.  Otherwise, return NULL.
*/
static Expr *whereRightSubexprIsColumn(Expr *p){
  p = sqlite3ExprSkipCollateAndLikely(p->pRight);
  if( ALWAYS(p!=0) && p->op==TK_COLUMN && !ExprHasProperty(p, EP_FixedCol) ){
    return p;
  }
  return 0;
}

/*
** Advance to the next WhereTerm that matches according to the criteria
** established when the pScan object was initialized by whereScanInit().
** Return NULL if there are no more matching WhereTerms.
*/
static WhereTerm *whereScanNext(WhereScan *pScan){
  int iCur;            /* The cursor on the LHS of the term */
  i16 iColumn;         /* The column on the LHS of the term.  -1 for IPK */
  Expr *pX;            /* An expression being tested */
  WhereClause *pWC;    /* Shorthand for pScan->pWC */
  WhereTerm *pTerm;    /* The term being tested */
  int k = pScan->k;    /* Where to start scanning */

  assert( pScan->iEquiv<=pScan->nEquiv );
  pWC = pScan->pWC;
  while(1){
    iColumn = pScan->aiColumn[pScan->iEquiv-1];
    iCur = pScan->aiCur[pScan->iEquiv-1];
    assert( pWC!=0 );
    assert( iCur>=0 );
    do{
      for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){
        assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 || pTerm->leftCursor<0 );
        if( pTerm->leftCursor==iCur
         && pTerm->u.leftColumn==iColumn
         && pTerm->u.x.leftColumn==iColumn
         && (iColumn!=XN_EXPR
             || sqlite3ExprCompareSkip(pTerm->pExpr->pLeft,
                                       pScan->pIdxExpr,iCur)==0)
         && (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin))
         && (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_OuterON))
        ){
          if( (pTerm->eOperator & WO_EQUIV)!=0
           && pScan->nEquiv<ArraySize(pScan->aiCur)
           && (pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight))->op==TK_COLUMN
           && (pX = whereRightSubexprIsColumn(pTerm->pExpr))!=0
          ){
            int j;
            for(j=0; j<pScan->nEquiv; j++){
              if( pScan->aiCur[j]==pX->iTable
               && pScan->aiColumn[j]==pX->iColumn ){
                  break;
              }
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
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







-
+
-






-
+
+








+
+
+
+
+
+
+
+
+
+
+
+














+
+
+
+
+
+
+
+
+
+
+







              CollSeq *pColl;
              Parse *pParse = pWC->pWInfo->pParse;
              pX = pTerm->pExpr;
              if( !sqlite3IndexAffinityOk(pX, pScan->idxaff) ){
                continue;
              }
              assert(pX->pLeft);
              pColl = sqlite3BinaryCompareCollSeq(pParse,
              pColl = sqlite3ExprCompareCollSeq(pParse, pX);
                                                  pX->pLeft, pX->pRight);
              if( pColl==0 ) pColl = pParse->db->pDfltColl;
              if( sqlite3StrICmp(pColl->zName, pScan->zCollName) ){
                continue;
              }
            }
            if( (pTerm->eOperator & (WO_EQ|WO_IS))!=0
             && (pX = pTerm->pExpr->pRight)->op==TK_COLUMN
             && (pX = pTerm->pExpr->pRight, ALWAYS(pX!=0))
             && pX->op==TK_COLUMN
             && pX->iTable==pScan->aiCur[0]
             && pX->iColumn==pScan->aiColumn[0]
            ){
              testcase( pTerm->eOperator & WO_IS );
              continue;
            }
            pScan->pWC = pWC;
            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 );
    if( pScan->iEquiv>=pScan->nEquiv ) break;
    pWC = pScan->pOrigWC;
    k = 0;
    pScan->iEquiv++;
  }
  return 0;
}

/*
** This is whereScanInit() for the case of an index on an expression.
** It is factored out into a separate tail-recursion subroutine so that
** the normal whereScanInit() routine, which is a high-runner, does not
** need to push registers onto the stack as part of its prologue.
*/
static SQLITE_NOINLINE WhereTerm *whereScanInitIndexExpr(WhereScan *pScan){
  pScan->idxaff = sqlite3ExprAffinity(pScan->pIdxExpr);
  return whereScanNext(pScan);
}

/*
** Initialize a WHERE clause scanner object.  Return a pointer to the
** first match.  Return NULL if there are no matches.
**
** The scanner will be searching the WHERE clause pWC.  It will look
** for terms of the form "X <op> <expr>" where X is column iColumn of table
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
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







+
+
+
+
+



-
-
-
-
+




+
+
+
+
+




-
-
-

-
-







  Index *pIdx             /* Must be compatible with this index */
){
  pScan->pOrigWC = pWC;
  pScan->pWC = pWC;
  pScan->pIdxExpr = 0;
  pScan->idxaff = 0;
  pScan->zCollName = 0;
  pScan->opMask = opMask;
  pScan->k = 0;
  pScan->aiCur[0] = iCur;
  pScan->nEquiv = 1;
  pScan->iEquiv = 1;
  if( pIdx ){
    int j = iColumn;
    iColumn = pIdx->aiColumn[j];
    if( iColumn==XN_EXPR ){
      pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr;
      pScan->zCollName = pIdx->azColl[j];
    }else if( iColumn==pIdx->pTable->iPKey ){
    if( iColumn==pIdx->pTable->iPKey ){
      iColumn = XN_ROWID;
    }else if( iColumn>=0 ){
      pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity;
      pScan->zCollName = pIdx->azColl[j];
    }else if( iColumn==XN_EXPR ){
      pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr;
      pScan->zCollName = pIdx->azColl[j];
      pScan->aiColumn[0] = XN_EXPR;
      return whereScanInitIndexExpr(pScan);
    }
  }else if( iColumn==XN_EXPR ){
    return 0;
  }
  pScan->opMask = opMask;
  pScan->k = 0;
  pScan->aiCur[0] = iCur;
  pScan->aiColumn[0] = iColumn;
  pScan->nEquiv = 1;
  pScan->iEquiv = 1;
  return whereScanNext(pScan);
}

/*
** Search for a term in the WHERE clause that is of the form "X <op> <expr>"
** where X is a reference to the iColumn of table iCur or of index pIdx
** if pIdx!=0 and <op> is one of the WO_xx operator codes specified by
432
433
434
435
436
437
438
439
440



441
442
443
444
445
446
447
538
539
540
541
542
543
544


545
546
547
548
549
550
551
552
553
554







-
-
+
+
+







  Index *pIdx,                    /* Index to match column of */
  int iCol                        /* Column of index to match */
){
  int i;
  const char *zColl = pIdx->azColl[iCol];

  for(i=0; i<pList->nExpr; i++){
    Expr *p = sqlite3ExprSkipCollate(pList->a[i].pExpr);
    if( p->op==TK_COLUMN
    Expr *p = sqlite3ExprSkipCollateAndLikely(pList->a[i].pExpr);
    if( ALWAYS(p!=0)
     && (p->op==TK_COLUMN || p->op==TK_AGG_COLUMN)
     && p->iColumn==pIdx->aiColumn[iCol]
     && p->iTable==iBase
    ){
      CollSeq *pColl = sqlite3ExprNNCollSeq(pParse, pList->a[i].pExpr);
      if( 0==sqlite3StrICmp(pColl->zName, zColl) ){
        return i;
      }
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
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







-
-
+
+
+
+

















+







  pTab = pTabList->a[0].pTab;

  /* 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 = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr);
    if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1;
    Expr *p = sqlite3ExprSkipCollateAndLikely(pDistinct->a[i].pExpr);
    if( NEVER(p==0) ) continue;
    if( p->op!=TK_COLUMN && p->op!=TK_AGG_COLUMN ) continue;
    if( p->iTable==iBase && p->iColumn<0 ) return 1;
  }

  /* Loop through all indices on the table, checking each to see if it makes
  ** the DISTINCT qualifier redundant. It does so if:
  **
  **   1. The index is itself UNIQUE, and
  **
  **   2. All of the columns in the index are either part of the pDistinct
  **      list, or else the WHERE clause contains a term of the form "col=X",
  **      where X is a constant value. The collation sequences of the
  **      comparison and select-list expressions must match those of the index.
  **
  **   3. All of those index columns for which the WHERE clause does not
  **      contain a "col=X" term are subject to a NOT NULL constraint.
  */
  for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
    if( !IsUniqueIndex(pIdx) ) continue;
    if( pIdx->pPartIdxWhere ) continue;
    for(i=0; i<pIdx->nKeyCol; i++){
      if( 0==sqlite3WhereFindTerm(pWC, iBase, i, ~(Bitmask)0, WO_EQ, pIdx) ){
        if( findIndexCol(pParse, pDistinct, iBase, pIdx, i)<0 ) break;
        if( indexColumnNotNull(pIdx, i)==0 ) break;
      }
    }
    if( i==pIdx->nKeyCol ){
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
638
639
640
641
642
643
644



645
646
647
648

649

650
651

652
653
654
655
656

657
658

659
660


661
662
663
664
665
666
667
668


669

















































670
671
672
673
674

675
676
677
678



679
680
681
682
683
684
685
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
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







-
-
-
-
+
+
+
+






-
+












+

-
-
-
-
-
+
+
+
+
-

-


+











-
+

-
+

+
-
+




-
+
+








-
+

-
+













-
-
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








-
-
-
+
+
+




+
-
+
-
-
+

-
-
-
-
+


+
-
-
+
+








+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
+

-
-
-
+
+
+







/*
** Convert OP_Column opcodes to OP_Copy in previously generated code.
**
** This routine runs over generated VDBE code and translates OP_Column
** opcodes into OP_Copy when the table is being accessed via co-routine 
** instead of via table lookup.
**
** If the bIncrRowid parameter is 0, then any OP_Rowid instructions on
** cursor iTabCur are transformed into OP_Null. Or, if bIncrRowid is non-zero,
** then each OP_Rowid is transformed into an instruction to increment the
** value stored in its output register.
** If the iAutoidxCur is not zero, then any OP_Rowid instructions on
** cursor iTabCur are transformed into OP_Sequence opcode for the
** iAutoidxCur cursor, in order to generate unique rowids for the
** automatic index being generated.
*/
static void translateColumnToCopy(
  Parse *pParse,      /* Parsing context */
  int iStart,         /* Translate from this opcode to the end */
  int iTabCur,        /* OP_Column/OP_Rowid references to this table */
  int iRegister,      /* The first column is in this register */
  int bIncrRowid      /* If non-zero, transform OP_rowid to OP_AddImm(1) */
  int iAutoidxCur     /* If non-zero, cursor of autoindex being generated */
){
  Vdbe *v = pParse->pVdbe;
  VdbeOp *pOp = sqlite3VdbeGetOp(v, iStart);
  int iEnd = sqlite3VdbeCurrentAddr(v);
  if( pParse->db->mallocFailed ) return;
  for(; iStart<iEnd; iStart++, pOp++){
    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;
      pOp->p5 = 2;  /* Cause the MEM_Subtype flag to be cleared */
    }else if( pOp->opcode==OP_Rowid ){
      if( bIncrRowid ){
        /* Increment the value stored in the P2 operand of the OP_Rowid. */
        pOp->opcode = OP_AddImm;
        pOp->p1 = pOp->p2;
        pOp->p2 = 1;
      pOp->opcode = OP_Sequence;
      pOp->p1 = iAutoidxCur;
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
      if( iAutoidxCur==0 ){
      }else{
        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
** SQLITE_TEST or SQLITE_DEBUG are defined, then these routines
** are no-ops.
*/
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(WHERETRACE_ENABLED)
static void TRACE_IDX_INPUTS(sqlite3_index_info *p){
static void whereTraceIndexInfoInputs(sqlite3_index_info *p){
  int i;
  if( !sqlite3WhereTrace ) return;
  if( (sqlite3WhereTrace & 0x10)==0 ) return;
  for(i=0; i<p->nConstraint; i++){
    sqlite3DebugPrintf(
    sqlite3DebugPrintf("  constraint[%d]: col=%d termid=%d op=%d usabled=%d\n",
       "  constraint[%d]: col=%d termid=%d op=%d usabled=%d collseq=%s\n",
       i,
       p->aConstraint[i].iColumn,
       p->aConstraint[i].iTermOffset,
       p->aConstraint[i].op,
       p->aConstraint[i].usable);
       p->aConstraint[i].usable,
       sqlite3_vtab_collation(p,i));
  }
  for(i=0; i<p->nOrderBy; i++){
    sqlite3DebugPrintf("  orderby[%d]: col=%d desc=%d\n",
       i,
       p->aOrderBy[i].iColumn,
       p->aOrderBy[i].desc);
  }
}
static void TRACE_IDX_OUTPUTS(sqlite3_index_info *p){
static void whereTraceIndexInfoOutputs(sqlite3_index_info *p){
  int i;
  if( !sqlite3WhereTrace ) return;
  if( (sqlite3WhereTrace & 0x10)==0 ) return;
  for(i=0; i<p->nConstraint; i++){
    sqlite3DebugPrintf("  usage[%d]: argvIdx=%d omit=%d\n",
       i,
       p->aConstraintUsage[i].argvIndex,
       p->aConstraintUsage[i].omit);
  }
  sqlite3DebugPrintf("  idxNum=%d\n", p->idxNum);
  sqlite3DebugPrintf("  idxStr=%s\n", p->idxStr);
  sqlite3DebugPrintf("  orderByConsumed=%d\n", p->orderByConsumed);
  sqlite3DebugPrintf("  estimatedCost=%g\n", p->estimatedCost);
  sqlite3DebugPrintf("  estimatedRows=%lld\n", p->estimatedRows);
}
#else
#define TRACE_IDX_INPUTS(A)
#define TRACE_IDX_OUTPUTS(A)
#define whereTraceIndexInfoInputs(A)
#define whereTraceIndexInfoOutputs(A)
#endif

/*
** We know that pSrc is an operand of an outer join.  Return true if
** pTerm is a constraint that is compatible with that join.
**
** pTerm must be EP_OuterON if pSrc is the right operand of an
** outer join.  pTerm can be either EP_OuterON or EP_InnerON if pSrc
** is the left operand of a RIGHT join.
**
** See https://sqlite.org/forum/forumpost/206d99a16dd9212f
** for an example of a WHERE clause constraints that may not be used on
** the right table of a RIGHT JOIN because the constraint implies a
** not-NULL condition on the left table of the RIGHT JOIN.
*/
static int constraintCompatibleWithOuterJoin(
  const WhereTerm *pTerm,       /* WHERE clause term to check */
  const SrcItem *pSrc           /* Table we are trying to access */
){
  assert( (pSrc->fg.jointype&(JT_LEFT|JT_LTORJ|JT_RIGHT))!=0 ); /* By caller */
  testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_LEFT );
  testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_LTORJ );
  testcase( ExprHasProperty(pTerm->pExpr, EP_OuterON) )
  testcase( ExprHasProperty(pTerm->pExpr, EP_InnerON) );
  if( !ExprHasProperty(pTerm->pExpr, EP_OuterON|EP_InnerON)
   || pTerm->pExpr->w.iJoin != pSrc->iCursor
  ){
    return 0;
  }
  if( (pSrc->fg.jointype & (JT_LEFT|JT_RIGHT))!=0
   && ExprHasProperty(pTerm->pExpr, EP_InnerON)
  ){
    return 0;
  }
  return 1;
}
 


#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
/*
** Return TRUE if the WHERE clause term pTerm is of a form where it
** could be used with an index to access pSrc, assuming an appropriate
** index existed.
*/
static int termCanDriveIndex(
  WhereTerm *pTerm,              /* WHERE clause term to check */
  struct SrcList_item *pSrc,     /* Table we are trying to access */
  Bitmask notReady               /* Tables in outer loops of the join */
  const WhereTerm *pTerm,        /* WHERE clause term to check */
  const SrcItem *pSrc,           /* Table we are trying to access */
  const Bitmask notReady         /* Tables in outer loops of the join */
){
  char aff;
  if( pTerm->leftCursor!=pSrc->iCursor ) return 0;
  if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) return 0;
  assert( (pSrc->fg.jointype & JT_RIGHT)==0 );
  if( (pSrc->fg.jointype & JT_LEFT) 
  if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0
   && !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
   && (pTerm->eOperator & WO_IS)
   && !constraintCompatibleWithOuterJoin(pTerm,pSrc)
  ){
    /* Cannot use an IS term from the WHERE clause as an index driver for
    ** the RHS of a LEFT JOIN. Such a term can only be used if it is from
    ** the ON clause.  */
    return 0;
    return 0;  /* See https://sqlite.org/forum/forumpost/51e6959f61 */
  }
  if( (pTerm->prereqRight & notReady)!=0 ) return 0;
  assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
  if( pTerm->u.leftColumn<0 ) return 0;
  aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity;
  if( pTerm->u.x.leftColumn<0 ) return 0;
  aff = pSrc->pTab->aCol[pTerm->u.x.leftColumn].affinity;
  if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0;
  testcase( pTerm->pExpr->op==TK_IS );
  return 1;
}
#endif


#ifndef SQLITE_OMIT_AUTOMATIC_INDEX

#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
/*
** Argument pIdx represents an automatic index that the current statement
** will create and populate. Add an OP_Explain with text of the form:
**
**     CREATE AUTOMATIC INDEX ON <table>(<cols>) [WHERE <expr>]
**
** This is only required if sqlite3_stmt_scanstatus() is enabled, to
** associate an SQLITE_SCANSTAT_NCYCLE and SQLITE_SCANSTAT_NLOOP
** values with. In order to avoid breaking legacy code and test cases, 
** the OP_Explain is not added if this is an EXPLAIN QUERY PLAN command.
*/
static void explainAutomaticIndex(
  Parse *pParse,
  Index *pIdx,                    /* Automatic index to explain */
  int bPartial,                   /* True if pIdx is a partial index */
  int *pAddrExplain               /* OUT: Address of OP_Explain */
){
  if( pParse->explain!=2 ){
    Table *pTab = pIdx->pTable;
    const char *zSep = "";
    char *zText = 0;
    int ii = 0;
    sqlite3_str *pStr = sqlite3_str_new(pParse->db);
    sqlite3_str_appendf(pStr,"CREATE AUTOMATIC INDEX ON %s(", pTab->zName);
    assert( pIdx->nColumn>1 );
    assert( pIdx->aiColumn[pIdx->nColumn-1]==XN_ROWID );
    for(ii=0; ii<(pIdx->nColumn-1); ii++){
      const char *zName = 0;
      int iCol = pIdx->aiColumn[ii];

      zName = pTab->aCol[iCol].zCnName;
      sqlite3_str_appendf(pStr, "%s%s", zSep, zName);
      zSep = ", ";
    }
    zText = sqlite3_str_finish(pStr);
    if( zText==0 ){
      sqlite3OomFault(pParse->db);
    }else{
      *pAddrExplain = sqlite3VdbeExplain(
          pParse, 0, "%s)%s", zText, (bPartial ? " WHERE <expr>" : "")
      );
      sqlite3_free(zText);
    }
  }
}
#else
# define explainAutomaticIndex(a,b,c,d)
#endif

/*
** Generate code to construct the Index object for an automatic index
** and to set up the WhereLevel object pLevel so that the code generator
** makes use of the automatic index.
*/
static void constructAutomaticIndex(
static SQLITE_NOINLINE void constructAutomaticIndex(
  Parse *pParse,              /* The parsing context */
  WhereClause *pWC,           /* The WHERE clause */
  struct SrcList_item *pSrc,  /* The FROM clause term to get the next index */
  Bitmask notReady,           /* Mask of cursors that are not available */
  const WhereClause *pWC,     /* The WHERE clause */
  const SrcItem *pSrc,        /* The FROM clause term to get the next index */
  const Bitmask notReady,     /* Mask of cursors that are not available */
  WhereLevel *pLevel          /* Write new index here */
){
  int nKeyCol;                /* Number of columns in the constructed index */
  WhereTerm *pTerm;           /* A single term of the WHERE clause */
  WhereTerm *pWCEnd;          /* End of pWC->a[] */
  Index *pIdx;                /* Object describing the transient index */
  Vdbe *v;                    /* Prepared statement under construction */
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
891
892
893
894
895
896
897

898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919

920


921


922
923



924
925
926
927
928
929


930
931
932
933
934
935
936
937
938
939

940
941
942
943
944
945
946
947
948
949
950
951

952
953
954
955
956
957
958
959







-
+


+
+
+
















-
+
-
-
+
-
-
+
+
-
-
-
+
+
+



-
-
+
+
+
+
+





-
+











-
+







  WhereLoop *pLoop;           /* The Loop object */
  char *zNotUsed;             /* Extra space on the end of pIdx */
  Bitmask idxCols;            /* Bitmap of columns used for indexing */
  Bitmask extraCols;          /* Bitmap of additional columns */
  u8 sentWarning = 0;         /* True if a warnning has been issued */
  Expr *pPartial = 0;         /* Partial Index Expression */
  int iContinue = 0;          /* Jump here to skip excluded rows */
  struct SrcList_item *pTabItem;  /* FROM clause term being indexed */
  SrcItem *pTabItem;          /* FROM clause term being indexed */
  int addrCounter = 0;        /* Address where integer counter is initialized */
  int regBase;                /* Array of registers where record is assembled */
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
  int addrExp = 0;            /* Address of OP_Explain */
#endif

  /* Generate code to skip over the creation and initialization of the
  ** transient index on 2nd and subsequent iterations of the loop. */
  v = pParse->pVdbe;
  assert( v!=0 );
  addrInit = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);

  /* Count the number of columns that will be added to the index
  ** and used to match WHERE clause constraints */
  nKeyCol = 0;
  pTable = pSrc->pTab;
  pWCEnd = &pWC->a[pWC->nTerm];
  pLoop = pLevel->pWLoop;
  idxCols = 0;
  for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
    Expr *pExpr = pTerm->pExpr;
    assert( !ExprHasProperty(pExpr, EP_FromJoin)    /* prereq always non-zero */
    /* Make the automatic index a partial index if there are terms in the
         || pExpr->iRightJoinTable!=pSrc->iCursor   /*   for the right-hand   */
         || pLoop->prereq!=0 );                     /*   table of a LEFT JOIN */
    ** WHERE clause (or the ON clause of a LEFT join) that constrain which
    if( pLoop->prereq==0
     && (pTerm->wtFlags & TERM_VIRTUAL)==0
    ** rows of the target table (pSrc) that can be used. */
    if( (pTerm->wtFlags & TERM_VIRTUAL)==0
     && !ExprHasProperty(pExpr, EP_FromJoin)
     && sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor) ){
      pPartial = sqlite3ExprAnd(pParse->db, pPartial,
     && sqlite3ExprIsTableConstraint(pExpr, pSrc)
    ){
      pPartial = sqlite3ExprAnd(pParse, pPartial,
                                sqlite3ExprDup(pParse->db, pExpr, 0));
    }
    if( termCanDriveIndex(pTerm, pSrc, notReady) ){
      int iCol = pTerm->u.leftColumn;
      Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol);
      int iCol;
      Bitmask cMask;
      assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
      iCol = pTerm->u.x.leftColumn;
      cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol);
      testcase( iCol==BMS );
      testcase( iCol==BMS-1 );
      if( !sentWarning ){
        sqlite3_log(SQLITE_WARNING_AUTOINDEX,
            "automatic index on %s(%s)", pTable->zName,
            pTable->aCol[iCol].zName);
            pTable->aCol[iCol].zCnName);
        sentWarning = 1;
      }
      if( (idxCols & cMask)==0 ){
        if( whereLoopResize(pParse->db, pLoop, nKeyCol+1) ){
          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
777
778
779
780
781
782
783
784
785





786
787
788
789
790
791
792



793
794
795
796
797
798
799
979
980
981
982
983
984
985


986
987
988
989
990
991
992
993
994
995


996
997
998
999
1000
1001
1002
1003
1004
1005







-
-
+
+
+
+
+





-
-
+
+
+







  pLoop->u.btree.pIndex = pIdx;
  pIdx->zName = "auto-index";
  pIdx->pTable = pTable;
  n = 0;
  idxCols = 0;
  for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
    if( termCanDriveIndex(pTerm, pSrc, notReady) ){
      int iCol = pTerm->u.leftColumn;
      Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol);
      int iCol;
      Bitmask cMask;
      assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
      iCol = pTerm->u.x.leftColumn;
      cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol);
      testcase( iCol==BMS-1 );
      testcase( iCol==BMS );
      if( (idxCols & cMask)==0 ){
        Expr *pX = pTerm->pExpr;
        idxCols |= cMask;
        pIdx->aiColumn[n] = pTerm->u.leftColumn;
        pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
        pIdx->aiColumn[n] = pTerm->u.x.leftColumn;
        pColl = sqlite3ExprCompareCollSeq(pParse, pX);
        assert( pColl!=0 || pParse->nErr>0 ); /* TH3 collate01.800 */
        pIdx->azColl[n] = pColl ? pColl->zName : sqlite3StrBINARY;
        n++;
      }
    }
  }
  assert( (u32)n==pLoop->u.btree.nEq );

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

900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945

946
947
948
949
950
951
952



953
954
955
956


957
958
959
960
961
962
963
964
965
966
967

968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983

984
985
986






987
988
989
990
991
992
993
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
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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







+





+
+
+
+














-
+







+
+
+
+
+






+

-
+

+


-
-
+
+





+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+


-
+


-
+
-




+








+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+

+









+
+
-
+
+
+
+
+
+
+

+











+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+







-
+
+




-
-
-
-
-
-

-
+


-
-
-
-
-
+
+
+
-
-


+
+


-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+


-
+
+
+
+
+
+







    }
  }
  assert( n==nKeyCol );
  pIdx->aiColumn[n] = XN_ROWID;
  pIdx->azColl[n] = sqlite3StrBINARY;

  /* Create the automatic index */
  explainAutomaticIndex(pParse, pIdx, pPartial!=0, &addrExp);
  assert( pLevel->iIdxCur>=0 );
  pLevel->iIdxCur = pParse->nTab++;
  sqlite3VdbeAddOp2(v, OP_OpenAutoindex, pLevel->iIdxCur, nKeyCol+1);
  sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
  VdbeComment((v, "for %s", pTable->zName));
  if( OptimizationEnabled(pParse->db, SQLITE_BloomFilter) ){
    pLevel->regFilter = ++pParse->nMem;
    sqlite3VdbeAddOp2(v, OP_Blob, 10000, pLevel->regFilter);
  }

  /* Fill the automatic index with content */
  pTabItem = &pWC->pWInfo->pTabList->a[pLevel->iFrom];
  if( pTabItem->fg.viaCoroutine ){
    int regYield = pTabItem->regReturn;
    addrCounter = sqlite3VdbeAddOp2(v, OP_Integer, 0, 0);
    sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub);
    addrTop =  sqlite3VdbeAddOp1(v, OP_Yield, regYield);
    VdbeCoverage(v);
    VdbeComment((v, "next row of %s", pTabItem->pTab->zName));
  }else{
    addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur); VdbeCoverage(v);
  }
  if( pPartial ){
    iContinue = sqlite3VdbeMakeLabel(v);
    iContinue = sqlite3VdbeMakeLabel(pParse);
    sqlite3ExprIfFalse(pParse, pPartial, iContinue, SQLITE_JUMPIFNULL);
    pLoop->wsFlags |= WHERE_PARTIALIDX;
  }
  regRecord = sqlite3GetTempReg(pParse);
  regBase = sqlite3GenerateIndexKey(
      pParse, pIdx, pLevel->iTabCur, regRecord, 0, 0, 0, 0
  );
  if( pLevel->regFilter ){
    sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0,
                         regBase, pLoop->u.btree.nEq);
  }
  sqlite3VdbeScanStatusCounters(v, addrExp, addrExp, sqlite3VdbeCurrentAddr(v));
  sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord);
  sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
  if( pPartial ) sqlite3VdbeResolveLabel(v, iContinue);
  if( pTabItem->fg.viaCoroutine ){
    sqlite3VdbeChangeP2(v, addrCounter, regBase+n);
    testcase( pParse->db->mallocFailed );
    assert( pLevel->iIdxCur>0 );
    translateColumnToCopy(pParse, addrTop, pLevel->iTabCur,
                          pTabItem->regResult, 1);
                          pTabItem->regResult, pLevel->iIdxCur);
    sqlite3VdbeGoto(v, addrTop);
    pTabItem->fg.viaCoroutine = 0;
  }else{
    sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v);
  }
  sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX);
    sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX);
  }
  sqlite3VdbeJumpHere(v, addrTop);
  sqlite3ReleaseTempReg(pParse, regRecord);
  
  /* Jump here when skipping the initialization */
  sqlite3VdbeJumpHere(v, addrInit);
  sqlite3VdbeScanStatusRange(v, addrExp, addrExp, -1);

end_auto_index_create:
  sqlite3ExprDelete(pParse->db, pPartial);
}
#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */

/*
** Generate bytecode that will initialize a Bloom filter that is appropriate
** for pLevel.
**
** If there are inner loops within pLevel that have the WHERE_BLOOMFILTER
** flag set, initialize a Bloomfilter for them as well.  Except don't do
** this recursive initialization if the SQLITE_BloomPulldown optimization has
** been turned off.
**
** When the Bloom filter is initialized, the WHERE_BLOOMFILTER flag is cleared
** from the loop, but the regFilter value is set to a register that implements
** the Bloom filter.  When regFilter is positive, the
** sqlite3WhereCodeOneLoopStart() will generate code to test the Bloom filter
** and skip the subsequence B-Tree seek if the Bloom filter indicates that
** no matching rows exist.
**
** This routine may only be called if it has previously been determined that
** the loop would benefit from a Bloom filter, and the WHERE_BLOOMFILTER bit
** is set.
*/
static SQLITE_NOINLINE void sqlite3ConstructBloomFilter(
  WhereInfo *pWInfo,    /* The WHERE clause */
  int iLevel,           /* Index in pWInfo->a[] that is pLevel */
  WhereLevel *pLevel,   /* Make a Bloom filter for this FROM term */
  Bitmask notReady      /* Loops that are not ready */
){
  int addrOnce;                        /* Address of opening OP_Once */
  int addrTop;                         /* Address of OP_Rewind */
  int addrCont;                        /* Jump here to skip a row */
  const WhereTerm *pTerm;              /* For looping over WHERE clause terms */
  const WhereTerm *pWCEnd;             /* Last WHERE clause term */
  Parse *pParse = pWInfo->pParse;      /* Parsing context */
  Vdbe *v = pParse->pVdbe;             /* VDBE under construction */
  WhereLoop *pLoop = pLevel->pWLoop;   /* The loop being coded */
  int iCur;                            /* Cursor for table getting the filter */

  assert( pLoop!=0 );
  assert( v!=0 );
  assert( pLoop->wsFlags & WHERE_BLOOMFILTER );

  addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
  do{
    const SrcItem *pItem;
    const Table *pTab;
    u64 sz;
    sqlite3WhereExplainBloomFilter(pParse, pWInfo, pLevel);
    addrCont = sqlite3VdbeMakeLabel(pParse);
    iCur = pLevel->iTabCur;
    pLevel->regFilter = ++pParse->nMem;

    /* The Bloom filter is a Blob held in a register.  Initialize it
    ** to zero-filled blob of at least 80K bits, but maybe more if the
    ** estimated size of the table is larger.  We could actually
    ** measure the size of the table at run-time using OP_Count with
    ** P3==1 and use that value to initialize the blob.  But that makes
    ** testing complicated.  By basing the blob size on the value in the
    ** sqlite_stat1 table, testing is much easier.
    */
    pItem = &pWInfo->pTabList->a[pLevel->iFrom];
    assert( pItem!=0 );
    pTab = pItem->pTab;
    assert( pTab!=0 );
    sz = sqlite3LogEstToInt(pTab->nRowLogEst);
    if( sz<10000 ){
      sz = 10000;
    }else if( sz>10000000 ){
      sz = 10000000;
    }
    sqlite3VdbeAddOp2(v, OP_Blob, (int)sz, pLevel->regFilter);

    addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v);
    pWCEnd = &pWInfo->sWC.a[pWInfo->sWC.nTerm];
    for(pTerm=pWInfo->sWC.a; pTerm<pWCEnd; pTerm++){
      Expr *pExpr = pTerm->pExpr;
      if( (pTerm->wtFlags & TERM_VIRTUAL)==0
       && sqlite3ExprIsTableConstraint(pExpr, pItem)
      ){
        sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL);
      }
    }
    if( pLoop->wsFlags & WHERE_IPK ){
      int r1 = sqlite3GetTempReg(pParse);
      sqlite3VdbeAddOp2(v, OP_Rowid, iCur, r1);
      sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0, r1, 1);
      sqlite3ReleaseTempReg(pParse, r1);
    }else{
      Index *pIdx = pLoop->u.btree.pIndex;
      int n = pLoop->u.btree.nEq;
      int r1 = sqlite3GetTempRange(pParse, n);
      int jj;
      for(jj=0; jj<n; jj++){
        int iCol = pIdx->aiColumn[jj];
        assert( pIdx->pTable==pItem->pTab );
        sqlite3ExprCodeGetColumnOfTable(v, pIdx->pTable, iCur, iCol,r1+jj);
      }
      sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0, r1, n);
      sqlite3ReleaseTempRange(pParse, r1, n);
    }
    sqlite3VdbeResolveLabel(v, addrCont);
    sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1);
    VdbeCoverage(v);
    sqlite3VdbeJumpHere(v, addrTop);
    pLoop->wsFlags &= ~WHERE_BLOOMFILTER;
    if( OptimizationDisabled(pParse->db, SQLITE_BloomPulldown) ) break;
    while( ++iLevel < pWInfo->nLevel ){
      const SrcItem *pTabItem;
      pLevel = &pWInfo->a[iLevel];
      pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
      if( pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ) ) continue;
      pLoop = pLevel->pWLoop;
      if( NEVER(pLoop==0) ) continue;
      if( pLoop->prereq & notReady ) continue;
      if( (pLoop->wsFlags & (WHERE_BLOOMFILTER|WHERE_COLUMN_IN))
                 ==WHERE_BLOOMFILTER
      ){
        /* This is a candidate for bloom-filter pull-down (early evaluation).
        ** The test that WHERE_COLUMN_IN is omitted is important, as we are
        ** not able to do early evaluation of bloom filters that make use of
        ** the IN operator */
        break;
      }
    }
  }while( iLevel < pWInfo->nLevel );
  sqlite3VdbeJumpHere(v, addrOnce);
}


#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Allocate and populate an sqlite3_index_info structure. It is the 
** responsibility of the caller to eventually release the structure
** by passing the pointer returned by this function to sqlite3_free().
** by passing the pointer returned by this function to freeIndexInfo().
*/
static sqlite3_index_info *allocateIndexInfo(
  Parse *pParse,                  /* The parsing context */
  WhereInfo *pWInfo,              /* The WHERE clause */
  WhereClause *pWC,               /* The WHERE clause being analyzed */
  Bitmask mUnusable,              /* Ignore terms with these prereqs */
  struct SrcList_item *pSrc,      /* The FROM clause term that is the vtab */
  SrcItem *pSrc,                  /* The FROM clause term that is the vtab */
  ExprList *pOrderBy,             /* The ORDER BY clause */
  u16 *pmNoOmit                   /* Mask of terms not to omit */
){
  int i, j;
  int nTerm;
  Parse *pParse = pWInfo->pParse;
  struct sqlite3_index_constraint *pIdxCons;
  struct sqlite3_index_orderby *pIdxOrderBy;
  struct sqlite3_index_constraint_usage *pUsage;
  struct HiddenIndexInfo *pHidden;
  WhereTerm *pTerm;
  int nOrderBy;
  sqlite3_index_info *pIdxInfo;
  u16 mNoOmit = 0;
  const Table *pTab;
  int eDistinct = 0;
  ExprList *pOrderBy = pWInfo->pOrderBy;

  /* Count the number of possible WHERE clause constraints referring
  ** to this virtual table */
 
  assert( pSrc!=0 );
  pTab = pSrc->pTab;
  assert( pTab!=0 );
  assert( IsVirtual(pTab) );

  /* Find all WHERE clause constraints referring to this virtual table.
  ** Mark each term with the TERM_OK flag.  Set nTerm to the number of
  ** terms found.
  */
  for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
    pTerm->wtFlags &= ~TERM_OK;
    if( pTerm->leftCursor != pSrc->iCursor ) continue;
    if( pTerm->prereqRight & mUnusable ) continue;
    assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
    testcase( pTerm->eOperator & WO_IN );
    testcase( pTerm->eOperator & WO_ISNULL );
    testcase( pTerm->eOperator & WO_IS );
    testcase( pTerm->eOperator & WO_ALL );
    if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue;
    if( pTerm->wtFlags & TERM_VNULL ) continue;

    assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
    assert( pTerm->u.leftColumn>=(-1) );
    assert( pTerm->u.x.leftColumn>=XN_ROWID );
    assert( pTerm->u.x.leftColumn<pTab->nCol );
    if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0
     && !constraintCompatibleWithOuterJoin(pTerm,pSrc)
    ){
      continue;
    }
    nTerm++;
    pTerm->wtFlags |= TERM_OK;
  }

  /* If the ORDER BY clause contains only columns in the current 
  ** virtual table then allocate space for the aOrderBy part of
  ** the sqlite3_index_info structure.
  */
  nOrderBy = 0;
  if( pOrderBy ){
    int n = pOrderBy->nExpr;
    for(i=0; i<n; i++){
      Expr *pExpr = pOrderBy->a[i].pExpr;
      Expr *pE2;

      /* Skip over constant terms in the ORDER BY clause */
      if( sqlite3ExprIsConstant(pExpr) ){
        continue;
      }

      /* Virtual tables are unable to deal with NULLS FIRST */
      if( pOrderBy->a[i].fg.sortFlags & KEYINFO_ORDER_BIGNULL ) break;

      /* First case - a direct column references without a COLLATE operator */
      if( pExpr->op==TK_COLUMN && pExpr->iTable==pSrc->iCursor ){
        assert( pExpr->iColumn>=XN_ROWID && pExpr->iColumn<pTab->nCol );
        continue;
      }

      /* 2nd case - a column reference with a COLLATE operator.  Only match
      ** of the COLLATE operator matches the collation of the column. */
      if( pExpr->op!=TK_COLUMN || pExpr->iTable!=pSrc->iCursor ) break;
    }
    if( i==n){
      if( pExpr->op==TK_COLLATE
       && (pE2 = pExpr->pLeft)->op==TK_COLUMN
       && pE2->iTable==pSrc->iCursor
      ){
        const char *zColl;  /* The collating sequence name */
        assert( !ExprHasProperty(pExpr, EP_IntValue) );
        assert( pExpr->u.zToken!=0 );
        assert( pE2->iColumn>=XN_ROWID && pE2->iColumn<pTab->nCol );
        pExpr->iColumn = pE2->iColumn;
        if( pE2->iColumn<0 ) continue;  /* Collseq does not matter for rowid */
        zColl = sqlite3ColumnColl(&pTab->aCol[pE2->iColumn]);
        if( zColl==0 ) zColl = sqlite3StrBINARY;
        if( sqlite3_stricmp(pExpr->u.zToken, zColl)==0 ) continue;
      }

      /* No matches cause a break out of the loop */
      break;
    }
    if( i==n ){
      nOrderBy = n;
      if( (pWInfo->wctrlFlags & WHERE_DISTINCTBY) ){
        eDistinct = 2 + ((pWInfo->wctrlFlags & WHERE_SORTBYGROUP)!=0);
      }else if( pWInfo->wctrlFlags & WHERE_GROUPBY ){
        eDistinct = 1;
      }
    }
  }

  /* Allocate the sqlite3_index_info structure
  */
  pIdxInfo = sqlite3DbMallocZero(pParse->db, sizeof(*pIdxInfo)
                           + (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm
                           + sizeof(*pIdxOrderBy)*nOrderBy + sizeof(*pHidden) );
                           + sizeof(*pIdxOrderBy)*nOrderBy + sizeof(*pHidden)
                           + sizeof(sqlite3_value*)*nTerm );
  if( pIdxInfo==0 ){
    sqlite3ErrorMsg(pParse, "out of memory");
    return 0;
  }

  /* Initialize the structure.  The sqlite3_index_info structure contains
  ** many fields that are declared "const" to prevent xBestIndex from
  ** changing them.  We have to do some funky casting in order to
  ** initialize those fields.
  */
  pHidden = (struct HiddenIndexInfo*)&pIdxInfo[1];
  pIdxCons = (struct sqlite3_index_constraint*)&pHidden[1];
  pIdxCons = (struct sqlite3_index_constraint*)&pHidden->aRhs[nTerm];
  pIdxOrderBy = (struct sqlite3_index_orderby*)&pIdxCons[nTerm];
  pUsage = (struct sqlite3_index_constraint_usage*)&pIdxOrderBy[nOrderBy];
  *(int*)&pIdxInfo->nConstraint = nTerm;
  *(int*)&pIdxInfo->nOrderBy = nOrderBy;
  *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint = pIdxCons;
  *(struct sqlite3_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy;
  *(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage =
  pIdxInfo->aConstraint = pIdxCons;
  pIdxInfo->aOrderBy = pIdxOrderBy;
  pIdxInfo->aConstraintUsage = pUsage;
                                                                   pUsage;

  pHidden->pWC = pWC;
  pHidden->pParse = pParse;
  pHidden->eDistinct = eDistinct;
  pHidden->mIn = 0;
  for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
    u16 op;
    if( pTerm->leftCursor != pSrc->iCursor ) continue;
    if( pTerm->prereqRight & mUnusable ) continue;
    assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
    testcase( pTerm->eOperator & WO_IN );
    testcase( pTerm->eOperator & WO_IS );
    testcase( pTerm->eOperator & WO_ISNULL );
    testcase( pTerm->eOperator & WO_ALL );
    if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue;
    if( pTerm->wtFlags & TERM_VNULL ) continue;
    if( (pTerm->wtFlags & TERM_OK)==0 ) continue;
    if( (pSrc->fg.jointype & JT_LEFT)!=0
     && !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
     && (pTerm->eOperator & (WO_IS|WO_ISNULL))
    ){
      /* An "IS" term in the WHERE clause where the virtual table is the rhs
      ** of a LEFT JOIN. Do not pass this term to the virtual table
      ** implementation, as this can lead to incorrect results from SQL such
      ** as:
      **
      **   "LEFT JOIN vtab WHERE vtab.col IS NULL"  */
      testcase( pTerm->eOperator & WO_ISNULL );
      testcase( pTerm->eOperator & WO_IS );
      continue;
    }
    assert( pTerm->u.leftColumn>=(-1) );
    pIdxCons[j].iColumn = pTerm->u.leftColumn;
    pIdxCons[j].iColumn = pTerm->u.x.leftColumn;
    pIdxCons[j].iTermOffset = i;
    op = pTerm->eOperator & WO_ALL;
    if( op==WO_IN ) op = WO_EQ;
    if( op==WO_IN ){
      if( (pTerm->wtFlags & TERM_SLICE)==0 ){
        pHidden->mIn |= SMASKBIT32(j);
      }
      op = WO_EQ;
    }
    if( op==WO_AUX ){
      pIdxCons[j].op = pTerm->eMatchOp;
    }else if( op & (WO_ISNULL|WO_IS) ){
      if( op==WO_ISNULL ){
        pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_ISNULL;
      }else{
        pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_IS;
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
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
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440







+
-
+







+
+
-
+

+
+
+
+
-
-
+
+
+

+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







      assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
      assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
      assert( pTerm->eOperator&(WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_AUX) );

      if( op & (WO_LT|WO_LE|WO_GT|WO_GE)
       && sqlite3ExprIsVector(pTerm->pExpr->pRight) 
      ){
        testcase( j!=i );
        if( i<16 ) mNoOmit |= (1 << i);
        if( j<16 ) mNoOmit |= (1 << j);
        if( op==WO_LT ) pIdxCons[j].op = WO_LE;
        if( op==WO_GT ) pIdxCons[j].op = WO_GE;
      }
    }

    j++;
  }
  assert( j==nTerm );
  pIdxInfo->nConstraint = j;
  for(i=0; i<nOrderBy; i++){
  for(i=j=0; i<nOrderBy; i++){
    Expr *pExpr = pOrderBy->a[i].pExpr;
    if( sqlite3ExprIsConstant(pExpr) ) continue;
    assert( pExpr->op==TK_COLUMN
         || (pExpr->op==TK_COLLATE && pExpr->pLeft->op==TK_COLUMN
              && pExpr->iColumn==pExpr->pLeft->iColumn) );
    pIdxOrderBy[i].iColumn = pExpr->iColumn;
    pIdxOrderBy[i].desc = pOrderBy->a[i].sortOrder;
    pIdxOrderBy[j].iColumn = pExpr->iColumn;
    pIdxOrderBy[j].desc = pOrderBy->a[i].fg.sortFlags & KEYINFO_ORDER_DESC;
    j++;
  }
  pIdxInfo->nOrderBy = j;

  *pmNoOmit = mNoOmit;
  return pIdxInfo;
}

/*
** Free an sqlite3_index_info structure allocated by allocateIndexInfo()
** and possibly modified by xBestIndex methods.
*/
static void freeIndexInfo(sqlite3 *db, sqlite3_index_info *pIdxInfo){
  HiddenIndexInfo *pHidden;
  int i;
  assert( pIdxInfo!=0 );
  pHidden = (HiddenIndexInfo*)&pIdxInfo[1];
  assert( pHidden->pParse!=0 );
  assert( pHidden->pParse->db==db );
  for(i=0; i<pIdxInfo->nConstraint; i++){
    sqlite3ValueFree(pHidden->aRhs[i]); /* IMP: R-14553-25174 */
    pHidden->aRhs[i] = 0;
  }
  sqlite3DbFree(db, pIdxInfo);
}

/*
** The table object reference passed as the second argument to this function
** must represent a virtual table. This function invokes the xBestIndex()
** method of the virtual table with the sqlite3_index_info object that
** comes in as the 3rd argument to this function.
**
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
1448
1449
1450
1451
1452
1453
1454

1455
1456
1457
1458

1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475

1476
1477
1478
1479
1480
1481
1482
1483







-
+
+

+
-
+
















-
+







** caller to eventually free p->idxStr if p->needToFreeIdxStr indicates
** that this is required.
*/
static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
  sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab;
  int rc;

  TRACE_IDX_INPUTS(p);
  whereTraceIndexInfoInputs(p);
  pParse->db->nSchemaLock++;
  rc = pVtab->pModule->xBestIndex(pVtab, p);
  pParse->db->nSchemaLock--;
  TRACE_IDX_OUTPUTS(p);
  whereTraceIndexInfoOutputs(p);

  if( rc!=SQLITE_OK && rc!=SQLITE_CONSTRAINT ){
    if( rc==SQLITE_NOMEM ){
      sqlite3OomFault(pParse->db);
    }else if( !pVtab->zErrMsg ){
      sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc));
    }else{
      sqlite3ErrorMsg(pParse, "%s", pVtab->zErrMsg);
    }
  }
  sqlite3_free(pVtab->zErrMsg);
  pVtab->zErrMsg = 0;
  return rc;
}
#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */

#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
/*
** Estimate the location of a particular key among all keys in an
** index.  Store the results in aStat as follows:
**
**    aStat[0]      Est. number of rows less than pRec
**    aStat[1]      Est. number of rows equal to pRec
**
1096
1097
1098
1099
1100
1101
1102
1103

1104
1105
1106
1107
1108
1109
1110
1505
1506
1507
1508
1509
1510
1511

1512
1513
1514
1515
1516
1517
1518
1519







-
+







  tRowcnt iLower = 0;         /* anLt[] + anEq[] of largest sample pRec is > */

#ifndef SQLITE_DEBUG
  UNUSED_PARAMETER( pParse );
#endif
  assert( pRec!=0 );
  assert( pIdx->nSample>0 );
  assert( pRec->nField>0 && pRec->nField<=pIdx->nSampleCol );
  assert( pRec->nField>0 );

  /* Do a binary search to find the first sample greater than or equal
  ** to pRec. If pRec contains a single field, the set of samples to search
  ** is simply the aSample[] array. If the samples in aSample[] contain more
  ** than one fields, all fields following the first are ignored.
  **
  ** If pRec contains N fields, where N is more than one, then as well as the
1142
1143
1144
1145
1146
1147
1148
1149

1150
1151
1152
1153
1154
1155
1156
1551
1552
1553
1554
1555
1556
1557

1558
1559
1560
1561
1562
1563
1564
1565







-
+







  ** equal to the previous sample in the array. For example, in the above, 
  ** sample 2 is the first sample of a block of N samples, so at first it 
  ** appears that it should be 1 field in size. However, that would make it 
  ** smaller than sample 1, so the binary search would not work. As a result, 
  ** it is extended to two fields. The duplicates that this creates do not 
  ** cause any problems.
  */
  nField = pRec->nField;
  nField = MIN(pRec->nField, pIdx->nSample);
  iCol = 0;
  iSample = pIdx->nSample * nField;
  do{
    int iSamp;                    /* Index in aSample[] of test sample */
    int n;                        /* Number of fields in test sample */

    iTest = (iMin+iSample)/2;
1230
1231
1232
1233
1234
1235
1236
1237

1238
1239
1240
1241
1242
1243
1244
1639
1640
1641
1642
1643
1644
1645

1646
1647
1648
1649
1650
1651
1652
1653







-
+







    aStat[1] = aSample[i].anEq[iCol];
  }else{
    /* At this point, the (iCol+1) field prefix of aSample[i] is the first 
    ** sample that is greater than pRec. Or, if i==pIdx->nSample then pRec
    ** is larger than all samples in the array. */
    tRowcnt iUpper, iGap;
    if( i>=pIdx->nSample ){
      iUpper = sqlite3LogEstToInt(pIdx->aiRowLogEst[0]);
      iUpper = pIdx->nRowEst0;
    }else{
      iUpper = aSample[i].anLt[iCol];
    }

    if( iLower>=iUpper ){
      iGap = 0;
    }else{
1253
1254
1255
1256
1257
1258
1259
1260

1261
1262
1263
1264
1265
1266
1267
1662
1663
1664
1665
1666
1667
1668

1669
1670
1671
1672
1673
1674
1675
1676







-
+







    aStat[1] = pIdx->aAvgEq[nField-1];
  }

  /* Restore the pRec->nField value before returning.  */
  pRec->nField = nField;
  return i;
}
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
#endif /* SQLITE_ENABLE_STAT4 */

/*
** If it is not NULL, pTerm is a term that provides an upper or lower
** bound on a range scan. Without considering pTerm, it is estimated 
** that the scan will visit nNew rows. This function returns the number
** estimated to be visited after taking pTerm into account.
**
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
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







-
+








+





-
+







      nRet -= 20;        assert( 20==sqlite3LogEst(4) );
    }
  }
  return nRet;
}


#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
/*
** Return the affinity for a single column of an index.
*/
char sqlite3IndexColumnAffinity(sqlite3 *db, Index *pIdx, int iCol){
  assert( iCol>=0 && iCol<pIdx->nColumn );
  if( !pIdx->zColAff ){
    if( sqlite3IndexAffinityStr(db, pIdx)==0 ) return SQLITE_AFF_BLOB;
  }
  assert( pIdx->zColAff[iCol]!=0 );
  return pIdx->zColAff[iCol];
}
#endif


#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
/* 
** This function is called to estimate the number of rows visited by a
** range-scan on a skip-scan index. For example:
**
**   CREATE INDEX i1 ON t1(a, b, c);
**   SELECT * FROM t1 WHERE a=? AND c BETWEEN ? AND ?;
**
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
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







-
+













-
+







    ** method (assume that the scan visits 1/64 of the rows) for estimating
    ** the number of rows visited. Otherwise, estimate the number of rows
    ** using the method described in the header comment for this function. */
    if( nDiff!=1 || pUpper==0 || pLower==0 ){
      int nAdjust = (sqlite3LogEst(p->nSample) - sqlite3LogEst(nDiff));
      pLoop->nOut -= nAdjust;
      *pbDone = 1;
      WHERETRACE(0x10, ("range skip-scan regions: %u..%u  adjust=%d est=%d\n",
      WHERETRACE(0x20, ("range skip-scan regions: %u..%u  adjust=%d est=%d\n",
                           nLower, nUpper, nAdjust*-1, pLoop->nOut));
    }

  }else{
    assert( *pbDone==0 );
  }

  sqlite3ValueFree(p1);
  sqlite3ValueFree(p2);
  sqlite3ValueFree(pVal);

  return rc;
}
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
#endif /* SQLITE_ENABLE_STAT4 */

/*
** This function is used to estimate the number of rows that will be visited
** by scanning an index for a range of values. The range may have an upper
** bound, a lower bound, or both. The WHERE clause terms that set the upper
** and lower bounds are represented by pLower and pUpper respectively. For
** example, assuming that index p is on t1(a):
1452
1453
1454
1455
1456
1457
1458
1459

1460
1461
1462
1463
1464


1465
1466
1467
1468
1469
1470
1471
1862
1863
1864
1865
1866
1867
1868

1869
1870
1871
1872


1873
1874
1875
1876
1877
1878
1879
1880
1881







-
+



-
-
+
+







  WhereTerm *pUpper,   /* Upper bound on the range. ex: "x<455" Might be NULL */
  WhereLoop *pLoop     /* Modify the .nOut and maybe .rRun fields */
){
  int rc = SQLITE_OK;
  int nOut = pLoop->nOut;
  LogEst nNew;

#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
  Index *p = pLoop->u.btree.pIndex;
  int nEq = pLoop->u.btree.nEq;

  if( p->nSample>0 && nEq<p->nSampleCol
   && OptimizationEnabled(pParse->db, SQLITE_Stat34)
  if( p->nSample>0 && ALWAYS(nEq<p->nSampleCol)
   && OptimizationEnabled(pParse->db, SQLITE_Stat4)
  ){
    if( nEq==pBuilder->nRecValid ){
      UnpackedRecord *pRec = pBuilder->pRec;
      tRowcnt a[2];
      int nBtm = pLoop->u.btree.nBtm;
      int nTop = pLoop->u.btree.nTop;

1555
1556
1557
1558
1559
1560
1561
1562

1563
1564
1565
1566
1567
1568
1569
1570

1571
1572
1573
1574
1575
1576
1577
1965
1966
1967
1968
1969
1970
1971

1972
1973
1974
1975
1976
1977
1978
1979

1980
1981
1982
1983
1984
1985
1986
1987







-
+







-
+







      pBuilder->pRec = pRec;
      if( rc==SQLITE_OK ){
        if( iUpper>iLower ){
          nNew = sqlite3LogEst(iUpper - iLower);
          /* TUNING:  If both iUpper and iLower are derived from the same
          ** sample, then assume they are 4x more selective.  This brings
          ** the estimated selectivity more in line with what it would be
          ** if estimated without the use of STAT3/4 tables. */
          ** if estimated without the use of STAT4 tables. */
          if( iLwrIdx==iUprIdx ) nNew -= 20;  assert( 20==sqlite3LogEst(4) );
        }else{
          nNew = 10;        assert( 10==sqlite3LogEst(2) );
        }
        if( nNew<nOut ){
          nOut = nNew;
        }
        WHERETRACE(0x10, ("STAT4 range scan: %u..%u  est=%d\n",
        WHERETRACE(0x20, ("STAT4 range scan: %u..%u  est=%d\n",
                           (u32)iLower, (u32)iUpper, nOut));
      }
    }else{
      int bDone = 0;
      rc = whereRangeSkipScanEst(pParse, pLower, pUpper, pLoop, &bDone);
      if( bDone ) return rc;
    }
1596
1597
1598
1599
1600
1601
1602
1603

1604
1605
1606
1607
1608
1609
1610
1611

1612
1613
1614
1615
1616

1617
1618
1619
1620
1621
1622
1623
2006
2007
2008
2009
2010
2011
2012

2013
2014
2015
2016
2017
2018
2019
2020

2021
2022
2023
2024
2025

2026
2027
2028
2029
2030
2031
2032
2033







-
+







-
+




-
+







  }

  nOut -= (pLower!=0) + (pUpper!=0);
  if( nNew<10 ) nNew = 10;
  if( nNew<nOut ) nOut = nNew;
#if defined(WHERETRACE_ENABLED)
  if( pLoop->nOut>nOut ){
    WHERETRACE(0x10,("Range scan lowers nOut from %d to %d\n",
    WHERETRACE(0x20,("Range scan lowers nOut from %d to %d\n",
                    pLoop->nOut, nOut));
  }
#endif
  pLoop->nOut = (LogEst)nOut;
  return rc;
}

#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
/*
** Estimate the number of rows that will be returned based on
** an equality constraint x=VALUE and where that VALUE occurs in
** the histogram data.  This only works when x is the left-most
** column of an index and sqlite_stat3 histogram data is available
** column of an index and sqlite_stat4 histogram data is available
** for that index.  When pExpr==NULL that means the constraint is
** "x IS NULL" instead of "x=VALUE".
**
** Write the estimated row count into *pnRow and return SQLITE_OK. 
** If unable to make an estimate, leave *pnRow unchanged and return
** non-zero.
**
1661
1662
1663
1664
1665
1666
1667
1668

1669
1670
1671
1672
1673
1674

1675
1676

1677
1678
1679
1680
1681
1682
1683
2071
2072
2073
2074
2075
2076
2077

2078
2079
2080
2081
2082
2083

2084
2085

2086
2087
2088
2089
2090
2091
2092
2093







-
+





-
+

-
+







  rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, 1, nEq-1, &bOk);
  pBuilder->pRec = pRec;
  if( rc!=SQLITE_OK ) return rc;
  if( bOk==0 ) return SQLITE_NOTFOUND;
  pBuilder->nRecValid = nEq;

  whereKeyStats(pParse, p, pRec, 0, a);
  WHERETRACE(0x10,("equality scan regions %s(%d): %d\n",
  WHERETRACE(0x20,("equality scan regions %s(%d): %d\n",
                   p->zName, nEq-1, (int)a[1]));
  *pnRow = a[1];
  
  return rc;
}
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
#endif /* SQLITE_ENABLE_STAT4 */

#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
/*
** Estimate the number of rows that will be returned based on
** an IN constraint where the right-hand side of the IN operator
** is a list of values.  Example:
**
**        WHERE x IN (1,2,3,4)
**
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

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
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
2199
2200

2201
2202
2203
2204
2205
2206
2207
2208







-
+




-
+






-
+



-
+

-
+


-
+
+

+

-
+

-
+





-
-
-
+
+
+
+
+
+
+
+
+
-
-
+
-
-
+
+
+

+












-
+








-
+


-
+







    nRowEst += nEst;
    pBuilder->nRecValid = nRecValid;
  }

  if( rc==SQLITE_OK ){
    if( nRowEst > nRow0 ) nRowEst = nRow0;
    *pnRow = nRowEst;
    WHERETRACE(0x10,("IN row estimate: est=%d\n", nRowEst));
    WHERETRACE(0x20,("IN row estimate: est=%d\n", nRowEst));
  }
  assert( pBuilder->nRecValid==nRecValid );
  return rc;
}
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
#endif /* SQLITE_ENABLE_STAT4 */


#ifdef WHERETRACE_ENABLED
/*
** Print the content of a WhereTerm object
*/
static void whereTermPrint(WhereTerm *pTerm, int iTerm){
void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm){
  if( pTerm==0 ){
    sqlite3DebugPrintf("TERM-%-3d NULL\n", iTerm);
  }else{
    char zType[4];
    char zType[8];
    char zLeft[50];
    memcpy(zType, "...", 4);
    memcpy(zType, "....", 5);
    if( pTerm->wtFlags & TERM_VIRTUAL ) zType[0] = 'V';
    if( pTerm->eOperator & WO_EQUIV  ) zType[1] = 'E';
    if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) zType[2] = 'L';
    if( ExprHasProperty(pTerm->pExpr, EP_OuterON) ) zType[2] = 'L';
    if( pTerm->wtFlags & TERM_CODED  ) zType[3] = 'C';
    if( pTerm->eOperator & WO_SINGLE ){
      assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
      sqlite3_snprintf(sizeof(zLeft),zLeft,"left={%d:%d}",
                       pTerm->leftCursor, pTerm->u.leftColumn);
                       pTerm->leftCursor, pTerm->u.x.leftColumn);
    }else if( (pTerm->eOperator & WO_OR)!=0 && pTerm->u.pOrInfo!=0 ){
      sqlite3_snprintf(sizeof(zLeft),zLeft,"indexable=0x%lld", 
      sqlite3_snprintf(sizeof(zLeft),zLeft,"indexable=0x%llx", 
                       pTerm->u.pOrInfo->indexable);
    }else{
      sqlite3_snprintf(sizeof(zLeft),zLeft,"left=%d", pTerm->leftCursor);
    }
    sqlite3DebugPrintf(
       "TERM-%-3d %p %s %-12s prob=%-3d op=0x%03x wtFlags=0x%04x",
       iTerm, pTerm, zType, zLeft, pTerm->truthProb,
       pTerm->eOperator, pTerm->wtFlags);
       "TERM-%-3d %p %s %-12s op=%03x wtFlags=%04x",
       iTerm, pTerm, zType, zLeft, pTerm->eOperator, pTerm->wtFlags);
    /* The 0x10000 .wheretrace flag causes extra information to be
    ** shown about each Term */
    if( sqlite3WhereTrace & 0x10000 ){
      sqlite3DebugPrintf(" prob=%-3d prereq=%llx,%llx",
        pTerm->truthProb, (u64)pTerm->prereqAll, (u64)pTerm->prereqRight);
    }
    if( (pTerm->eOperator & (WO_OR|WO_AND))==0 && pTerm->u.x.iField ){
    if( pTerm->iField ){
      sqlite3DebugPrintf(" iField=%d\n", pTerm->iField);
      sqlite3DebugPrintf(" iField=%d", pTerm->u.x.iField);
    }else{
      sqlite3DebugPrintf("\n");
    }
    if( pTerm->iParent>=0 ){
      sqlite3DebugPrintf(" iParent=%d", pTerm->iParent);
    }
    sqlite3DebugPrintf("\n");
    sqlite3TreeViewExpr(0, pTerm->pExpr, 0);
  }
}
#endif

#ifdef WHERETRACE_ENABLED
/*
** Show the complete content of a WhereClause
*/
void sqlite3WhereClausePrint(WhereClause *pWC){
  int i;
  for(i=0; i<pWC->nTerm; i++){
    whereTermPrint(&pWC->a[i], i);
    sqlite3WhereTermPrint(&pWC->a[i], i);
  }
}
#endif

#ifdef WHERETRACE_ENABLED
/*
** Print a WhereLoop object for debugging purposes
*/
static void whereLoopPrint(WhereLoop *p, WhereClause *pWC){
void sqlite3WhereLoopPrint(WhereLoop *p, WhereClause *pWC){
  WhereInfo *pWInfo = pWC->pWInfo;
  int nb = 1+(pWInfo->pTabList->nSrc+3)/4;
  struct SrcList_item *pItem = pWInfo->pTabList->a + p->iTab;
  SrcItem *pItem = pWInfo->pTabList->a + p->iTab;
  Table *pTab = pItem->pTab;
  Bitmask mAll = (((Bitmask)1)<<(nb*4)) - 1;
  sqlite3DebugPrintf("%c%2d.%0*llx.%0*llx", p->cId,
                     p->iTab, nb, p->maskSelf, nb, p->prereq & mAll);
  sqlite3DebugPrintf(" %12s",
                     pItem->zAlias ? pItem->zAlias : pTab->zName);
  if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){
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
2216
2217
2218
2219
2220
2221
2222

2223
2224
2225
2226
2227
2228
2229
2230
2231

2232
2233

2234
2235
2236

2237
2238
2239

2240
2241
2242
2243
2244
2245
2246
2247







-
+








-
+

-
+


-
+


-
+







      sqlite3DebugPrintf(".%-16s %2d", zName, p->u.btree.nEq);
    }else{
      sqlite3DebugPrintf("%20s","");
    }
  }else{
    char *z;
    if( p->u.vtab.idxStr ){
      z = sqlite3_mprintf("(%d,\"%s\",%x)",
      z = sqlite3_mprintf("(%d,\"%s\",%#x)",
                p->u.vtab.idxNum, p->u.vtab.idxStr, p->u.vtab.omitMask);
    }else{
      z = sqlite3_mprintf("(%d,%x)", p->u.vtab.idxNum, p->u.vtab.omitMask);
    }
    sqlite3DebugPrintf(" %-19s", z);
    sqlite3_free(z);
  }
  if( p->wsFlags & WHERE_SKIPSCAN ){
    sqlite3DebugPrintf(" f %05x %d-%d", p->wsFlags, p->nLTerm,p->nSkip);
    sqlite3DebugPrintf(" f %06x %d-%d", p->wsFlags, p->nLTerm,p->nSkip);
  }else{
    sqlite3DebugPrintf(" f %05x N %d", p->wsFlags, p->nLTerm);
    sqlite3DebugPrintf(" f %06x N %d", p->wsFlags, p->nLTerm);
  }
  sqlite3DebugPrintf(" cost %d,%d,%d\n", p->rSetup, p->rRun, p->nOut);
  if( p->nLTerm && (sqlite3WhereTrace & 0x100)!=0 ){
  if( p->nLTerm && (sqlite3WhereTrace & 0x4000)!=0 ){
    int i;
    for(i=0; i<p->nLTerm; i++){
      whereTermPrint(p->aLTerm[i], i);
      sqlite3WhereTermPrint(p->aLTerm[i], i);
    }
  }
}
#endif

/*
** Convert bulk memory into a valid WhereLoop that can be passed
1849
1850
1851
1852
1853
1854
1855
1856


1857
1858
1859





1860
1861


1862
1863
1864
1865
1866
1867
1868
2268
2269
2270
2271
2272
2273
2274

2275
2276
2277
2278

2279
2280
2281
2282
2283
2284

2285
2286
2287
2288
2289
2290
2291
2292
2293







-
+
+


-
+
+
+
+
+

-
+
+







      sqlite3DbFreeNN(db, p->u.btree.pIndex);
      p->u.btree.pIndex = 0;
    }
  }
}

/*
** Deallocate internal memory used by a WhereLoop object
** Deallocate internal memory used by a WhereLoop object.  Leave the
** object in an initialized state, as if it had been newly allocated.
*/
static void whereLoopClear(sqlite3 *db, WhereLoop *p){
  if( p->aLTerm!=p->aLTermSpace ) sqlite3DbFreeNN(db, p->aLTerm);
  if( p->aLTerm!=p->aLTermSpace ){
    sqlite3DbFreeNN(db, p->aLTerm);
    p->aLTerm = p->aLTermSpace;
    p->nLSlot = ArraySize(p->aLTermSpace);
  }
  whereLoopClearUnion(db, p);
  whereLoopInit(p);
  p->nLTerm = 0;
  p->wsFlags = 0;
}

/*
** Increase the memory allocation for pLoop->aLTerm[] to be at least n.
*/
static int whereLoopResize(sqlite3 *db, WhereLoop *p, int n){
  WhereTerm **paNew;
1878
1879
1880
1881
1882
1883
1884

1885
1886



1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902

1903
1904

1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918

1919
1920
1921
1922
1923
1924





1925

1926
1927
1928
1929
1930
1931


1932
1933
1934
1935
1936
1937
1938
2303
2304
2305
2306
2307
2308
2309
2310


2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331

2332
2333
2334
2335
2336
2337
2338

2339






2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351

2352
2353
2354
2355
2356
2357

2358
2359
2360
2361
2362
2363
2364
2365
2366







+
-
-
+
+
+
















+

-
+






-

-
-
-
-
-
-
+






+
+
+
+
+
-
+





-
+
+







}

/*
** Transfer content from the second pLoop into the first.
*/
static int whereLoopXfer(sqlite3 *db, WhereLoop *pTo, WhereLoop *pFrom){
  whereLoopClearUnion(db, pTo);
  if( pFrom->nLTerm > pTo->nLSlot
  if( whereLoopResize(db, pTo, pFrom->nLTerm) ){
    memset(&pTo->u, 0, sizeof(pTo->u));
   && whereLoopResize(db, pTo, pFrom->nLTerm)
  ){
    memset(pTo, 0, WHERE_LOOP_XFER_SZ);
    return SQLITE_NOMEM_BKPT;
  }
  memcpy(pTo, pFrom, WHERE_LOOP_XFER_SZ);
  memcpy(pTo->aLTerm, pFrom->aLTerm, pTo->nLTerm*sizeof(pTo->aLTerm[0]));
  if( pFrom->wsFlags & WHERE_VIRTUALTABLE ){
    pFrom->u.vtab.needFree = 0;
  }else if( (pFrom->wsFlags & WHERE_AUTO_INDEX)!=0 ){
    pFrom->u.btree.pIndex = 0;
  }
  return SQLITE_OK;
}

/*
** Delete a WhereLoop object
*/
static void whereLoopDelete(sqlite3 *db, WhereLoop *p){
  assert( db!=0 );
  whereLoopClear(db, p);
  sqlite3DbFreeNN(db, p);
  sqlite3DbNNFreeNN(db, p);
}

/*
** Free a WhereInfo structure
*/
static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
  int i;
  assert( pWInfo!=0 );
  for(i=0; i<pWInfo->nLevel; i++){
    WhereLevel *pLevel = &pWInfo->a[i];
    if( pLevel->pWLoop && (pLevel->pWLoop->wsFlags & WHERE_IN_ABLE) ){
      sqlite3DbFree(db, pLevel->u.in.aInLoop);
    }
  }
  assert( db!=0 );
  sqlite3WhereClauseClear(&pWInfo->sWC);
  while( pWInfo->pLoops ){
    WhereLoop *p = pWInfo->pLoops;
    pWInfo->pLoops = p->pNextLoop;
    whereLoopDelete(db, p);
  }
  while( pWInfo->pMemToFree ){
    WhereMemBlock *pNext = pWInfo->pMemToFree->pNext;
    sqlite3DbNNFreeNN(db, pWInfo->pMemToFree);
    pWInfo->pMemToFree = pNext;
  }
  sqlite3DbFreeNN(db, pWInfo);
  sqlite3DbNNFreeNN(db, pWInfo);
}

/*
** Return TRUE if all of the following are true:
**
**   (1)  X has the same or lower cost that Y
**   (1)  X has the same or lower cost, or returns the same or fewer rows, 
**        than Y.
**   (2)  X uses fewer WHERE clause terms than Y
**   (3)  Every WHERE clause term used by X is also used by Y
**   (4)  X skips at least as many columns as Y
**   (5)  If X is a covering index, than Y is too
**
** Conditions (2) and (3) mean that X is a "proper subset" of Y.
** If X is a proper subset of Y then Y is a better choice and ought
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
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998





1999
2000
2001
2002
2003
2004
2005





2006
2007
2008
2009
2010
2011
2012
2375
2376
2377
2378
2379
2380
2381
2382
2383




2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398


2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420



2421
2422
2423
2424
2425
2426
2427
2428
2429



2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441







+

-
-
-
-















-
-
+
+




















-
-
-
+
+
+
+
+




-
-
-
+
+
+
+
+







  const WhereLoop *pX,       /* First WhereLoop to compare */
  const WhereLoop *pY        /* Compare against this WhereLoop */
){
  int i, j;
  if( pX->nLTerm-pX->nSkip >= pY->nLTerm-pY->nSkip ){
    return 0; /* X is not a subset of Y */
  }
  if( pX->rRun>pY->rRun && pX->nOut>pY->nOut ) return 0;
  if( pY->nSkip > pX->nSkip ) return 0;
  if( pX->rRun >= pY->rRun ){
    if( pX->rRun > pY->rRun ) return 0;    /* X costs more than Y */
    if( pX->nOut > pY->nOut ) return 0;    /* X costs more than Y */
  }
  for(i=pX->nLTerm-1; i>=0; i--){
    if( pX->aLTerm[i]==0 ) continue;
    for(j=pY->nLTerm-1; j>=0; j--){
      if( pY->aLTerm[j]==pX->aLTerm[i] ) break;
    }
    if( j<0 ) return 0;  /* X not a subset of Y since term X[i] not used by Y */
  }
  if( (pX->wsFlags&WHERE_IDX_ONLY)!=0 
   && (pY->wsFlags&WHERE_IDX_ONLY)==0 ){
    return 0;  /* Constraint (5) */
  }
  return 1;  /* All conditions meet */
}

/*
** Try to adjust the cost of WhereLoop pTemplate upwards or downwards so
** that:
** Try to adjust the cost and number of output rows of WhereLoop pTemplate
** upwards or downwards so that:
**
**   (1) pTemplate costs less than any other WhereLoops that are a proper
**       subset of pTemplate
**
**   (2) pTemplate costs more than any other WhereLoops for which pTemplate
**       is a proper subset.
**
** To say "WhereLoop X is a proper subset of Y" means that X uses fewer
** WHERE clause terms than Y and that every WHERE clause term used by X is
** also used by Y.
*/
static void whereLoopAdjustCost(const WhereLoop *p, WhereLoop *pTemplate){
  if( (pTemplate->wsFlags & WHERE_INDEXED)==0 ) return;
  for(; p; p=p->pNextLoop){
    if( p->iTab!=pTemplate->iTab ) continue;
    if( (p->wsFlags & WHERE_INDEXED)==0 ) continue;
    if( whereLoopCheaperProperSubset(p, pTemplate) ){
      /* Adjust pTemplate cost downward so that it is cheaper than its 
      ** subset p. */
      WHERETRACE(0x80,("subset cost adjustment %d,%d to %d,%d\n",
                       pTemplate->rRun, pTemplate->nOut, p->rRun, p->nOut-1));
      pTemplate->rRun = p->rRun;
      pTemplate->nOut = p->nOut - 1;
                       pTemplate->rRun, pTemplate->nOut, 
                       MIN(p->rRun, pTemplate->rRun),
                       MIN(p->nOut - 1, pTemplate->nOut)));
      pTemplate->rRun = MIN(p->rRun, pTemplate->rRun);
      pTemplate->nOut = MIN(p->nOut - 1, pTemplate->nOut);
    }else if( whereLoopCheaperProperSubset(pTemplate, p) ){
      /* Adjust pTemplate cost upward so that it is costlier than p since
      ** pTemplate is a proper subset of p */
      WHERETRACE(0x80,("subset cost adjustment %d,%d to %d,%d\n",
                       pTemplate->rRun, pTemplate->nOut, p->rRun, p->nOut+1));
      pTemplate->rRun = p->rRun;
      pTemplate->nOut = p->nOut + 1;
                       pTemplate->rRun, pTemplate->nOut, 
                       MAX(p->rRun, pTemplate->rRun),
                       MAX(p->nOut + 1, pTemplate->nOut)));
      pTemplate->rRun = MAX(p->rRun, pTemplate->rRun);
      pTemplate->nOut = MAX(p->nOut + 1, pTemplate->nOut);
    }
  }
}

/*
** Search the list of WhereLoops in *ppPrev looking for one that can be
** replaced by pTemplate.
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
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570

2571
2572
2573
2574
2575
2576
2577
2578
2579

2580
2581
2582
2583
2584
2585
2586
2587

2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603

2604
2605
2606
2607
2608

2609
2610
2611
2612
2613
2614
2615
2616







+
+















-
+








-








-
+















-
+




-
+







  /* Stop the search once we hit the query planner search limit */
  if( pBuilder->iPlanLimit==0 ){
    WHERETRACE(0xffffffff,("=== query planner search limit reached ===\n"));
    if( pBuilder->pOrSet ) pBuilder->pOrSet->n = 0;
    return SQLITE_DONE;
  }
  pBuilder->iPlanLimit--;

  whereLoopAdjustCost(pWInfo->pLoops, pTemplate);

  /* If pBuilder->pOrSet is defined, then only keep track of the costs
  ** and prereqs.
  */
  if( pBuilder->pOrSet!=0 ){
    if( pTemplate->nLTerm ){
#if WHERETRACE_ENABLED
      u16 n = pBuilder->pOrSet->n;
      int x =
#endif
      whereOrInsert(pBuilder->pOrSet, pTemplate->prereq, pTemplate->rRun,
                                    pTemplate->nOut);
#if WHERETRACE_ENABLED /* 0x8 */
      if( sqlite3WhereTrace & 0x8 ){
        sqlite3DebugPrintf(x?"   or-%d:  ":"   or-X:  ", n);
        whereLoopPrint(pTemplate, pBuilder->pWC);
        sqlite3WhereLoopPrint(pTemplate, pBuilder->pWC);
      }
#endif
    }
    return SQLITE_OK;
  }

  /* Look for an existing WhereLoop to replace with pTemplate
  */
  whereLoopAdjustCost(pWInfo->pLoops, pTemplate);
  ppPrev = whereLoopFindLesser(&pWInfo->pLoops, pTemplate);

  if( ppPrev==0 ){
    /* There already exists a WhereLoop on the list that is better
    ** than pTemplate, so just ignore pTemplate */
#if WHERETRACE_ENABLED /* 0x8 */
    if( sqlite3WhereTrace & 0x8 ){
      sqlite3DebugPrintf("   skip: ");
      whereLoopPrint(pTemplate, pBuilder->pWC);
      sqlite3WhereLoopPrint(pTemplate, pBuilder->pWC);
    }
#endif
    return SQLITE_OK;  
  }else{
    p = *ppPrev;
  }

  /* If we reach this point it means that either p[] should be overwritten
  ** with pTemplate[] if p[] exists, or if p==NULL then allocate a new
  ** WhereLoop and insert it.
  */
#if WHERETRACE_ENABLED /* 0x8 */
  if( sqlite3WhereTrace & 0x8 ){
    if( p!=0 ){
      sqlite3DebugPrintf("replace: ");
      whereLoopPrint(p, pBuilder->pWC);
      sqlite3WhereLoopPrint(p, pBuilder->pWC);
      sqlite3DebugPrintf("   with: ");
    }else{
      sqlite3DebugPrintf("    add: ");
    }
    whereLoopPrint(pTemplate, pBuilder->pWC);
    sqlite3WhereLoopPrint(pTemplate, pBuilder->pWC);
  }
#endif
  if( p==0 ){
    /* Allocate a new WhereLoop to add to the end of the list */
    *ppPrev = p = sqlite3DbMallocRawNN(db, sizeof(WhereLoop));
    if( p==0 ) return SQLITE_NOMEM_BKPT;
    whereLoopInit(p);
2196
2197
2198
2199
2200
2201
2202
2203

2204
2205
2206
2207
2208
2209
2210
2211
2212

2213
2214
2215
2216
2217
2218
2219
2626
2627
2628
2629
2630
2631
2632

2633
2634
2635
2636
2637
2638
2639
2640
2641

2642
2643
2644
2645
2646
2647
2648
2649







-
+








-
+







      if( ppTail==0 ) break;
      pToDel = *ppTail;
      if( pToDel==0 ) break;
      *ppTail = pToDel->pNextLoop;
#if WHERETRACE_ENABLED /* 0x8 */
      if( sqlite3WhereTrace & 0x8 ){
        sqlite3DebugPrintf(" delete: ");
        whereLoopPrint(pToDel, pBuilder->pWC);
        sqlite3WhereLoopPrint(pToDel, pBuilder->pWC);
      }
#endif
      whereLoopDelete(db, pToDel);
    }
  }
  rc = whereLoopXfer(db, p, pTemplate);
  if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){
    Index *pIndex = p->u.btree.pIndex;
    if( pIndex && pIndex->tnum==0 ){
    if( pIndex && pIndex->idxType==SQLITE_IDXTYPE_IPK ){
      p->u.btree.pIndex = 0;
    }
  }
  return rc;
}

/*
2248
2249
2250
2251
2252
2253
2254
2255

2256
2257
2258
2259
2260



2261
2262

2263
2264
2265
2266
2267
2268
2269


















2270
2271
2272
2273
2274
2275
2276
2277
2278



2279

2280
2281
2282
2283
2284
2285
2286




2287
2288
2289
2290
2291



2292
2293
2294
2295
2296
2297
2298
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
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726

2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737

2738
2739
2740
2741
2742
2743
2744
2745

2746
2747
2748
2749
2750
2751
2752
2753
2754
2755







-
+



-
-
+
+
+

-
+







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








-
+
+
+

+






-
+
+
+
+




-
+
+
+







static void whereLoopOutputAdjust(
  WhereClause *pWC,      /* The WHERE clause */
  WhereLoop *pLoop,      /* The loop to adjust downward */
  LogEst nRow            /* Number of rows in the entire table */
){
  WhereTerm *pTerm, *pX;
  Bitmask notAllowed = ~(pLoop->prereq|pLoop->maskSelf);
  int i, j, k;
  int i, j;
  LogEst iReduce = 0;    /* pLoop->nOut should not exceed nRow-iReduce */

  assert( (pLoop->wsFlags & WHERE_AUTO_INDEX)==0 );
  for(i=pWC->nTerm, pTerm=pWC->a; i>0; i--, pTerm++){
    if( (pTerm->wtFlags & TERM_VIRTUAL)!=0 ) break;
  for(i=pWC->nBase, pTerm=pWC->a; i>0; i--, pTerm++){
    assert( pTerm!=0 );
    if( (pTerm->prereqAll & notAllowed)!=0 ) continue;
    if( (pTerm->prereqAll & pLoop->maskSelf)==0 ) continue;
    if( (pTerm->prereqAll & notAllowed)!=0 ) continue;
    if( (pTerm->wtFlags & TERM_VIRTUAL)!=0 ) continue;
    for(j=pLoop->nLTerm-1; j>=0; j--){
      pX = pLoop->aLTerm[j];
      if( pX==0 ) continue;
      if( pX==pTerm ) break;
      if( pX->iParent>=0 && (&pWC->a[pX->iParent])==pTerm ) break;
    }
    if( j<0 ){
      sqlite3ProgressCheck(pWC->pWInfo->pParse);
      if( pLoop->maskSelf==pTerm->prereqAll ){
        /* If there are extra terms in the WHERE clause not used by an index
        ** that depend only on the table being scanned, and that will tend to
        ** cause many rows to be omitted, then mark that table as
        ** "self-culling".
        **
        ** 2022-03-24:  Self-culling only applies if either the extra terms
        ** are straight comparison operators that are non-true with NULL
        ** operand, or if the loop is not an OUTER JOIN.
        */
        if( (pTerm->eOperator & 0x3f)!=0
         || (pWC->pWInfo->pTabList->a[pLoop->iTab].fg.jointype
                  & (JT_LEFT|JT_LTORJ))==0
        ){
          pLoop->wsFlags |= WHERE_SELFCULL;
        }
      }
      if( pTerm->truthProb<=0 ){
        /* If a truth probability is specified using the likelihood() hints,
        ** then use the probability provided by the application. */
        pLoop->nOut += pTerm->truthProb;
      }else{
        /* In the absence of explicit truth probabilities, use heuristics to
        ** guess a reasonable truth probability. */
        pLoop->nOut--;
        if( pTerm->eOperator&(WO_EQ|WO_IS) ){
        if( (pTerm->eOperator&(WO_EQ|WO_IS))!=0
         && (pTerm->wtFlags & TERM_HIGHTRUTH)==0  /* tag-20200224-1 */
        ){
          Expr *pRight = pTerm->pExpr->pRight;
          int k = 0;
          testcase( pTerm->pExpr->op==TK_IS );
          if( sqlite3ExprIsInteger(pRight, &k) && k>=(-1) && k<=1 ){
            k = 10;
          }else{
            k = 20;
          }
          if( iReduce<k ) iReduce = k;
          if( iReduce<k ){
            pTerm->wtFlags |= TERM_HEURTRUTH;
            iReduce = k;
          }
        }
      }
    }
  }
  if( pLoop->nOut > nRow-iReduce )  pLoop->nOut = nRow - iReduce;
  if( pLoop->nOut > nRow-iReduce ){
    pLoop->nOut = nRow - iReduce;
  }
}

/* 
** Term pTerm is a vector range comparison operation. The first comparison
** in the vector can be optimized using column nEq of the index. This
** function returns the total number of vector elements that can be used
** as part of the range comparison.
2321
2322
2323
2324
2325
2326
2327



2328
2329
2330



2331
2332
2333
2334
2335
2336
2337
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787



2788
2789
2790
2791
2792
2793
2794
2795
2796
2797







+
+
+
-
-
-
+
+
+







  nCmp = MIN(nCmp, (pIdx->nColumn - nEq));
  for(i=1; i<nCmp; i++){
    /* Test if comparison i of pTerm is compatible with column (i+nEq) 
    ** of the index. If not, exit the loop.  */
    char aff;                     /* Comparison affinity */
    char idxaff = 0;              /* Indexed columns affinity */
    CollSeq *pColl;               /* Comparison collation sequence */
    Expr *pLhs, *pRhs;

    assert( ExprUseXList(pTerm->pExpr->pLeft) );
    Expr *pLhs = pTerm->pExpr->pLeft->x.pList->a[i].pExpr;
    Expr *pRhs = pTerm->pExpr->pRight;
    if( pRhs->flags & EP_xIsSelect ){
    pLhs = pTerm->pExpr->pLeft->x.pList->a[i].pExpr;
    pRhs = pTerm->pExpr->pRight;
    if( ExprUseXSelect(pRhs) ){
      pRhs = pRhs->x.pSelect->pEList->a[i].pExpr;
    }else{
      pRhs = pRhs->x.pList->a[i].pExpr;
    }

    /* Check that the LHS of the comparison is a column reference to
    ** the right column of the right source table. And that the sort
2372
2373
2374
2375
2376
2377
2378
2379
2380


2381
2382
2383
2384

2385
2386
2387
2388
2389
2390
2391
2832
2833
2834
2835
2836
2837
2838


2839
2840
2841
2842
2843

2844
2845
2846
2847
2848
2849
2850
2851







-
-
+
+



-
+







** index pIndex. Try to match one more.
**
** When this function is called, pBuilder->pNew->nOut contains the 
** number of rows expected to be visited by filtering using the nEq 
** terms only. If it is modified, this value is restored before this 
** function returns.
**
** If pProbe->tnum==0, that means pIndex is a fake index used for the
** INTEGER PRIMARY KEY.
** If pProbe->idxType==SQLITE_IDXTYPE_IPK, that means pIndex is 
** a fake index used for the INTEGER PRIMARY KEY.
*/
static int whereLoopAddBtreeIndex(
  WhereLoopBuilder *pBuilder,     /* The WhereLoop factory */
  struct SrcList_item *pSrc,      /* FROM clause term being analyzed */
  SrcItem *pSrc,                  /* FROM clause term being analyzed */
  Index *pProbe,                  /* An index on pSrc */
  LogEst nInMul                   /* log(Number of iterations due to IN) */
){
  WhereInfo *pWInfo = pBuilder->pWInfo;  /* WHERE analyse context */
  Parse *pParse = pWInfo->pParse;        /* Parsing context */
  sqlite3 *db = pParse->db;       /* Database connection malloc context */
  WhereLoop *pNew;                /* Template WhereLoop under construction */
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411







2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423


2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443

2444
2445
2446
2447
2448
2449
2450
2451
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
2481
2482
2483
2484
2485
2486
2487
2488

2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508


2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526


2527
2528
2529
2530
2531



2532
2533
2534



2535






2536
2537
2538
2539




2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557

2558
2559




2560
2561
2562
2563
2564





2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586




















2587
2588
2589
2590
2591




2592
2593
2594
2595
2596
2597
2598
2599
2600
2601

2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615

2616
2617
2618
2619
2620
2621



2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635





















2636
2637
2638
2639
2640
2641
2642
2862
2863
2864
2865
2866
2867
2868



2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908

2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922





2923
2924
2925
2926
2927

2928

2929
2930

2931
2932
2933
2934
2935
2936
2937
2938

2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953

2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969


2970


2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989

2990
2991
2992
2993
2994


2995
2996
2997
2998


2999
3000
3001

3002
3003
3004
3005
3006
3007
3008
3009


3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038





3039
3040
3041
3042
3043






















3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063





3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076

3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090

3091
3092
3093
3094



3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139







-
-
-
+
+
+
+
+
+
+












+
+



















-
+













-
-
-
-
-
+
+



-

-
+

-
+






+
-
+
+
+
+











-
+















-
-

-
-
+
+

















-
+
+



-
-
+
+
+

-
-
+
+
+
-
+
+
+
+
+
+


-
-
+
+
+
+


















+


+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+









-
+













-
+



-
-
-
+
+
+














+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  LogEst saved_nOut;              /* Original value of pNew->nOut */
  int rc = SQLITE_OK;             /* Return code */
  LogEst rSize;                   /* Number of rows in the table */
  LogEst rLogSize;                /* Logarithm of table size */
  WhereTerm *pTop = 0, *pBtm = 0; /* Top and bottom range constraints */

  pNew = pBuilder->pNew;
  if( db->mallocFailed ) return SQLITE_NOMEM_BKPT;
  WHERETRACE(0x800, ("BEGIN %s.addBtreeIdx(%s), nEq=%d\n",
                     pProbe->pTable->zName,pProbe->zName, pNew->u.btree.nEq));
  assert( db->mallocFailed==0 || pParse->nErr>0 );
  if( pParse->nErr ){
    return pParse->rc;
  }
  WHERETRACE(0x800, ("BEGIN %s.addBtreeIdx(%s), nEq=%d, nSkip=%d, rRun=%d\n",
                     pProbe->pTable->zName,pProbe->zName,
                     pNew->u.btree.nEq, pNew->nSkip, pNew->rRun));

  assert( (pNew->wsFlags & WHERE_VIRTUALTABLE)==0 );
  assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 );
  if( pNew->wsFlags & WHERE_BTM_LIMIT ){
    opMask = WO_LT|WO_LE;
  }else{
    assert( pNew->u.btree.nBtm==0 );
    opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE|WO_ISNULL|WO_IS;
  }
  if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);

  assert( pNew->u.btree.nEq<pProbe->nColumn );
  assert( pNew->u.btree.nEq<pProbe->nKeyCol
       || pProbe->idxType!=SQLITE_IDXTYPE_PRIMARYKEY );

  saved_nEq = pNew->u.btree.nEq;
  saved_nBtm = pNew->u.btree.nBtm;
  saved_nTop = pNew->u.btree.nTop;
  saved_nSkip = pNew->nSkip;
  saved_nLTerm = pNew->nLTerm;
  saved_wsFlags = pNew->wsFlags;
  saved_prereq = pNew->prereq;
  saved_nOut = pNew->nOut;
  pTerm = whereScanInit(&scan, pBuilder->pWC, pSrc->iCursor, saved_nEq,
                        opMask, pProbe);
  pNew->rSetup = 0;
  rSize = pProbe->aiRowLogEst[0];
  rLogSize = estLog(rSize);
  for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){
    u16 eOp = pTerm->eOperator;   /* Shorthand for pTerm->eOperator */
    LogEst rCostIdx;
    LogEst nOutUnadjusted;        /* nOut before IN() and WHERE adjustments */
    int nIn = 0;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
    int nRecValid = pBuilder->nRecValid;
#endif
    if( (eOp==WO_ISNULL || (pTerm->wtFlags&TERM_VNULL)!=0)
     && indexColumnNotNull(pProbe, saved_nEq)
    ){
      continue; /* ignore IS [NOT] NULL constraints on NOT NULL columns */
    }
    if( pTerm->prereqRight & pNew->maskSelf ) continue;

    /* Do not allow the upper bound of a LIKE optimization range constraint
    ** to mix with a lower range bound from some other source */
    if( pTerm->wtFlags & TERM_LIKEOPT && pTerm->eOperator==WO_LT ) continue;

    /* Do not allow constraints from the WHERE clause to be used by the
    ** right table of a LEFT JOIN.  Only constraints in the ON clause are
    ** allowed */
    if( (pSrc->fg.jointype & JT_LEFT)!=0
     && !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
    if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0
     && !constraintCompatibleWithOuterJoin(pTerm,pSrc)
    ){
      continue;
    }

    if( IsUniqueIndex(pProbe) && saved_nEq==pProbe->nKeyCol-1 ){
      pBuilder->bldFlags |= SQLITE_BLDF_UNIQUE;
      pBuilder->bldFlags1 |= SQLITE_BLDF1_UNIQUE;
    }else{
      pBuilder->bldFlags |= SQLITE_BLDF_INDEXED;
      pBuilder->bldFlags1 |= SQLITE_BLDF1_INDEXED;
    }
    pNew->wsFlags = saved_wsFlags;
    pNew->u.btree.nEq = saved_nEq;
    pNew->u.btree.nBtm = saved_nBtm;
    pNew->u.btree.nTop = saved_nTop;
    pNew->nLTerm = saved_nLTerm;
    if( pNew->nLTerm>=pNew->nLSlot
    if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */
     && whereLoopResize(db, pNew, pNew->nLTerm+1)
    ){
       break; /* OOM while trying to enlarge the pNew->aLTerm array */
    }
    pNew->aLTerm[pNew->nLTerm++] = pTerm;
    pNew->prereq = (saved_prereq | pTerm->prereqRight) & ~pNew->maskSelf;

    assert( nInMul==0
        || (pNew->wsFlags & WHERE_COLUMN_NULL)!=0 
        || (pNew->wsFlags & WHERE_COLUMN_IN)!=0 
        || (pNew->wsFlags & WHERE_SKIPSCAN)!=0 
    );

    if( eOp & WO_IN ){
      Expr *pExpr = pTerm->pExpr;
      if( ExprHasProperty(pExpr, EP_xIsSelect) ){
      if( ExprUseXSelect(pExpr) ){
        /* "x IN (SELECT ...)":  TUNING: the SELECT returns 25 rows */
        int i;
        nIn = 46;  assert( 46==sqlite3LogEst(25) );

        /* The expression may actually be of the form (x, y) IN (SELECT...).
        ** In this case there is a separate term for each of (x) and (y).
        ** However, the nIn multiplier should only be applied once, not once
        ** for each such term. The following loop checks that pTerm is the
        ** first such term in use, and sets nIn back to 0 if it is not. */
        for(i=0; i<pNew->nLTerm-1; i++){
          if( pNew->aLTerm[i] && pNew->aLTerm[i]->pExpr==pExpr ) nIn = 0;
        }
      }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
        /* "x IN (value, value, ...)" */
        nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
        assert( nIn>0 );  /* RHS always has 2 or more terms...  The parser
                          ** changes "x IN (?)" into "x=?". */
      }
      if( pProbe->hasStat1 ){
        LogEst M, logK, safetyMargin;
      if( pProbe->hasStat1 && rLogSize>=10 ){
        LogEst M, logK, x;
        /* Let:
        **   N = the total number of rows in the table
        **   K = the number of entries on the RHS of the IN operator
        **   M = the number of rows in the table that match terms to the 
        **       to the left in the same index.  If the IN operator is on
        **       the left-most index column, M==N.
        **
        ** Given the definitions above, it is better to omit the IN operator
        ** from the index lookup and instead do a scan of the M elements,
        ** testing each scanned row against the IN operator separately, if:
        **
        **        M*log(K) < K*log(N)
        **
        ** Our estimates for M, K, and N might be inaccurate, so we build in
        ** a safety margin of 2 (LogEst: 10) that favors using the IN operator
        ** with the index, as using an index has better worst-case behavior.
        ** If we do not have real sqlite_stat1 data, always prefer to use
        ** the index.
        ** the index.  Do not bother with this optimization on very small
        ** tables (less than 2 rows) as it is pointless in that case.
        */
        M = pProbe->aiRowLogEst[saved_nEq];
        logK = estLog(nIn);
        safetyMargin = 10;  /* TUNING: extra weight for indexed IN */
        if( M + logK + safetyMargin < nIn + rLogSize ){
        /* TUNING      v-----  10 to bias toward indexed IN */
        x = M + logK + 10 - (nIn + rLogSize);
        if( x>=0 ){
          WHERETRACE(0x40,
            ("Scan preferred over IN operator on column %d of \"%s\" (%d<%d)\n",
             saved_nEq, pProbe->zName, M+logK+10, nIn+rLogSize));
            ("IN operator (N=%d M=%d logK=%d nIn=%d rLogSize=%d x=%d) "
             "prefers indexed lookup\n",
             saved_nEq, M, logK, nIn, rLogSize, x));
          continue;
        }else if( nInMul<2 && OptimizationEnabled(db, SQLITE_SeekScan) ){
          WHERETRACE(0x40,
            ("IN operator (N=%d M=%d logK=%d nIn=%d rLogSize=%d x=%d"
             " nInMul=%d) prefers skip-scan\n",
             saved_nEq, M, logK, nIn, rLogSize, x, nInMul));
          pNew->wsFlags |= WHERE_IN_SEEKSCAN;
        }else{
          WHERETRACE(0x40,
            ("IN operator preferred on column %d of \"%s\" (%d>=%d)\n",
             saved_nEq, pProbe->zName, M+logK+10, nIn+rLogSize));
            ("IN operator (N=%d M=%d logK=%d nIn=%d rLogSize=%d x=%d"
             " nInMul=%d) prefers normal scan\n",
             saved_nEq, M, logK, nIn, rLogSize, x, nInMul));
          continue;
        }
      }
      pNew->wsFlags |= WHERE_COLUMN_IN;
    }else if( eOp & (WO_EQ|WO_IS) ){
      int iCol = pProbe->aiColumn[saved_nEq];
      pNew->wsFlags |= WHERE_COLUMN_EQ;
      assert( saved_nEq==pNew->u.btree.nEq );
      if( iCol==XN_ROWID 
       || (iCol>=0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1)
      ){
        if( iCol==XN_ROWID || pProbe->uniqNotNull 
         || (pProbe->nKeyCol==1 && pProbe->onError && eOp==WO_EQ) 
        ){
          pNew->wsFlags |= WHERE_ONEROW;
        }else{
          pNew->wsFlags |= WHERE_UNQ_WANTED;
        }
      }
      if( scan.iEquiv>1 ) pNew->wsFlags |= WHERE_TRANSCONS;
    }else if( eOp & WO_ISNULL ){
      pNew->wsFlags |= WHERE_COLUMN_NULL;
    }else{
      int nVecLen = whereRangeVectorLen(
          pParse, pSrc->iCursor, pProbe, saved_nEq, pTerm
      );
    }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(
      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 = nVecLen;
          pParse, pSrc->iCursor, pProbe, saved_nEq, pTerm
      );
      pBtm = pTerm;
      pTop = 0;
      if( pTerm->wtFlags & TERM_LIKEOPT ){
        /* Range contraints that come from the LIKE optimization are
        ** always used in pairs. */
        pTop = &pTerm[1];
        assert( (pTop-(pTerm->pWC->a))<pTerm->pWC->nTerm );
        assert( pTop->wtFlags & TERM_LIKEOPT );
        assert( pTop->eOperator==WO_LT );
        if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */
        pNew->aLTerm[pNew->nLTerm++] = pTop;
        pNew->wsFlags |= WHERE_TOP_LIMIT;
        pNew->u.btree.nTop = 1;
      }
    }else{
      assert( eOp & (WO_LT|WO_LE) );
      testcase( eOp & WO_LT );
      testcase( eOp & WO_LE );
      pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_TOP_LIMIT;
      pNew->u.btree.nTop = whereRangeVectorLen(
        pBtm = pTerm;
        pTop = 0;
        if( pTerm->wtFlags & TERM_LIKEOPT ){
          /* Range constraints that come from the LIKE optimization are
          ** always used in pairs. */
          pTop = &pTerm[1];
          assert( (pTop-(pTerm->pWC->a))<pTerm->pWC->nTerm );
          assert( pTop->wtFlags & TERM_LIKEOPT );
          assert( pTop->eOperator==WO_LT );
          if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */
          pNew->aLTerm[pNew->nLTerm++] = pTop;
          pNew->wsFlags |= WHERE_TOP_LIMIT;
          pNew->u.btree.nTop = 1;
        }
      }else{
        assert( eOp & (WO_LT|WO_LE) );
        testcase( eOp & WO_LT );
        testcase( eOp & WO_LE );
        pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_TOP_LIMIT;
        pNew->u.btree.nTop = nVecLen;
          pParse, pSrc->iCursor, pProbe, saved_nEq, pTerm
      );
      pTop = pTerm;
      pBtm = (pNew->wsFlags & WHERE_BTM_LIMIT)!=0 ?
                     pNew->aLTerm[pNew->nLTerm-2] : 0;
        pTop = pTerm;
        pBtm = (pNew->wsFlags & WHERE_BTM_LIMIT)!=0 ?
                       pNew->aLTerm[pNew->nLTerm-2] : 0;
      }
    }

    /* At this point pNew->nOut is set to the number of rows expected to
    ** be visited by the index scan before considering term pTerm, or the
    ** values of nIn and nInMul. In other words, assuming that all 
    ** "x IN(...)" terms are replaced with "x = ?". This block updates
    ** the value of pNew->nOut to account for pTerm (but not nIn/nInMul).  */
    assert( pNew->nOut==saved_nOut );
    if( pNew->wsFlags & WHERE_COLUMN_RANGE ){
      /* Adjust nOut using stat3/stat4 data. Or, if there is no stat3/stat4
      /* Adjust nOut using stat4 data. Or, if there is no stat4
      ** data, using some other estimate.  */
      whereRangeScanEst(pParse, pBuilder, pBtm, pTop, pNew);
    }else{
      int nEq = ++pNew->u.btree.nEq;
      assert( eOp & (WO_ISNULL|WO_EQ|WO_IN|WO_IS) );

      assert( pNew->nOut==saved_nOut );
      if( pTerm->truthProb<=0 && pProbe->aiColumn[saved_nEq]>=0 ){
        assert( (eOp & WO_IN) || nIn==0 );
        testcase( eOp & WO_IN );
        pNew->nOut += pTerm->truthProb;
        pNew->nOut -= nIn;
      }else{
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
        tRowcnt nOut = 0;
        if( nInMul==0 
         && pProbe->nSample 
         && pNew->u.btree.nEq<=pProbe->nSampleCol
         && ((eOp & WO_IN)==0 || !ExprHasProperty(pTerm->pExpr, EP_xIsSelect))
         && OptimizationEnabled(db, SQLITE_Stat34)
         && ALWAYS(pNew->u.btree.nEq<=pProbe->nSampleCol)
         && ((eOp & WO_IN)==0 || ExprUseXList(pTerm->pExpr))
         && OptimizationEnabled(db, SQLITE_Stat4)
        ){
          Expr *pExpr = pTerm->pExpr;
          if( (eOp & (WO_EQ|WO_ISNULL|WO_IS))!=0 ){
            testcase( eOp & WO_EQ );
            testcase( eOp & WO_IS );
            testcase( eOp & WO_ISNULL );
            rc = whereEqualScanEst(pParse, pBuilder, pExpr->pRight, &nOut);
          }else{
            rc = whereInScanEst(pParse, pBuilder, pExpr->x.pList, &nOut);
          }
          if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
          if( rc!=SQLITE_OK ) break;          /* Jump out of the pTerm loop */
          if( nOut ){
            pNew->nOut = sqlite3LogEst(nOut);
            if( nEq==1
             /* TUNING: Mark terms as "low selectivity" if they seem likely
             ** to be true for half or more of the rows in the table.
             ** See tag-202002240-1 */
             && pNew->nOut+10 > pProbe->aiRowLogEst[0]
            ){
#if WHERETRACE_ENABLED /* 0x01 */
              if( sqlite3WhereTrace & 0x20 ){
                sqlite3DebugPrintf(
                   "STAT4 determines term has low selectivity:\n");
                sqlite3WhereTermPrint(pTerm, 999);
              }
#endif
              pTerm->wtFlags |= TERM_HIGHTRUTH;
              if( pTerm->wtFlags & TERM_HEURTRUTH ){
                /* If the term has previously been used with an assumption of
                ** higher selectivity, then set the flag to rerun the
                ** loop computations. */
                pBuilder->bldFlags2 |= SQLITE_BLDF2_2NDPASS;
              }
            }
            if( pNew->nOut>saved_nOut ) pNew->nOut = saved_nOut;
            pNew->nOut -= nIn;
          }
        }
        if( nOut==0 )
#endif
        {
2651
2652
2653
2654
2655
2656
2657








2658


2659
2660

2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678


2679



2680
2681
2682
2683

2684
2685
2686
2687
2688
2689
2690
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162

3163
3164
3165

3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193

3194
3195
3196
3197
3198
3199
3200
3201







+
+
+
+
+
+
+
+
-
+
+

-
+


















+
+

+
+
+



-
+







      }
    }

    /* Set rCostIdx to the cost of visiting selected rows in index. Add
    ** it to pNew->rRun, which is currently set to the cost of the index
    ** seek only. Then, if this is a non-covering index, add the cost of
    ** visiting the rows in the main table.  */
    assert( pSrc->pTab->szTabRow>0 );
    if( pProbe->idxType==SQLITE_IDXTYPE_IPK ){
      /* The pProbe->szIdxRow is low for an IPK table since the interior
      ** pages are small.  Thuse szIdxRow gives a good estimate of seek cost.
      ** But the leaf pages are full-size, so pProbe->szIdxRow would badly
      ** under-estimate the scanning cost. */
      rCostIdx = pNew->nOut + 16;
    }else{
    rCostIdx = pNew->nOut + 1 + (15*pProbe->szIdxRow)/pSrc->pTab->szTabRow;
      rCostIdx = pNew->nOut + 1 + (15*pProbe->szIdxRow)/pSrc->pTab->szTabRow;
    }
    pNew->rRun = sqlite3LogEstAdd(rLogSize, rCostIdx);
    if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){
    if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK|WHERE_EXPRIDX))==0 ){
      pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut + 16);
    }
    ApplyCostMultiplier(pNew->rRun, pProbe->pTable->costMult);

    nOutUnadjusted = pNew->nOut;
    pNew->rRun += nInMul + nIn;
    pNew->nOut += nInMul + nIn;
    whereLoopOutputAdjust(pBuilder->pWC, pNew, rSize);
    rc = whereLoopInsert(pBuilder, pNew);

    if( pNew->wsFlags & WHERE_COLUMN_RANGE ){
      pNew->nOut = saved_nOut;
    }else{
      pNew->nOut = nOutUnadjusted;
    }

    if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
     && pNew->u.btree.nEq<pProbe->nColumn
     && (pNew->u.btree.nEq<pProbe->nKeyCol ||
           pProbe->idxType!=SQLITE_IDXTYPE_PRIMARYKEY)
    ){
      if( pNew->u.btree.nEq>3 ){
        sqlite3ProgressCheck(pParse);
      }
      whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn);
    }
    pNew->nOut = saved_nOut;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
    pBuilder->nRecValid = nRecValid;
#endif
  }
  pNew->prereq = saved_prereq;
  pNew->u.btree.nEq = saved_nEq;
  pNew->u.btree.nBtm = saved_nBtm;
  pNew->u.btree.nTop = saved_nTop;
2702
2703
2704
2705
2706
2707
2708

2709

2710
2711
2712
2713
2714
2715
2716
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229







+

+







  ** contains fewer than 2^17 rows we assume otherwise in other parts of
  ** the code). And, even if it is not, it should not be too much slower. 
  ** On the other hand, the extra seeks could end up being significantly
  ** more expensive.  */
  assert( 42==sqlite3LogEst(18) );
  if( saved_nEq==saved_nSkip
   && saved_nEq+1<pProbe->nKeyCol
   && saved_nEq==pNew->nLTerm
   && pProbe->noSkipScan==0
   && pProbe->hasStat1!=0
   && OptimizationEnabled(db, SQLITE_SkipScan)
   && pProbe->aiRowLogEst[saved_nEq+1]>=42  /* TUNING: Minimum for skip-scan */
   && (rc = whereLoopResize(db, pNew, pNew->nLTerm+1))==SQLITE_OK
  ){
    LogEst nIter;
    pNew->u.btree.nEq++;
    pNew->nSkip++;
2749
2750
2751
2752
2753
2754
2755
2756


2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
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
3262
3263
3264
3265
3266
3267
3268

3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290

3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301

3302
3303

3304
3305
3306
3307
3308
3309



3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470







-
+
+




















-
+
+
+
+
+
+


+
+
+
-
+

-
+




+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  ExprList *pOB;
  ExprList *aColExpr;
  int ii, jj;

  if( pIndex->bUnordered ) return 0;
  if( (pOB = pBuilder->pWInfo->pOrderBy)==0 ) return 0;
  for(ii=0; ii<pOB->nExpr; ii++){
    Expr *pExpr = sqlite3ExprSkipCollate(pOB->a[ii].pExpr);
    Expr *pExpr = sqlite3ExprSkipCollateAndLikely(pOB->a[ii].pExpr);
    if( NEVER(pExpr==0) ) continue;
    if( pExpr->op==TK_COLUMN && pExpr->iTable==iCursor ){
      if( pExpr->iColumn<0 ) return 1;
      for(jj=0; jj<pIndex->nKeyCol; jj++){
        if( pExpr->iColumn==pIndex->aiColumn[jj] ) return 1;
      }
    }else if( (aColExpr = pIndex->aColExpr)!=0 ){
      for(jj=0; jj<pIndex->nKeyCol; jj++){
        if( pIndex->aiColumn[jj]!=XN_EXPR ) continue;
        if( sqlite3ExprCompareSkip(pExpr,aColExpr->a[jj].pExpr,iCursor)==0 ){
          return 1;
        }
      }
    }
  }
  return 0;
}

/* Check to see if a partial index with pPartIndexWhere can be used
** in the current query.  Return true if it can be and false if not.
*/
static int whereUsablePartialIndex(int iTab, WhereClause *pWC, Expr *pWhere){
static int whereUsablePartialIndex(
  int iTab,             /* The table for which we want an index */
  u8 jointype,          /* The JT_* flags on the join */
  WhereClause *pWC,     /* The WHERE clause of the query */
  Expr *pWhere          /* The WHERE clause from the partial index */
){
  int i;
  WhereTerm *pTerm;
  Parse *pParse;

  if( jointype & JT_LTORJ ) return 0;
  Parse *pParse = pWC->pWInfo->pParse;
  pParse = pWC->pWInfo->pParse;
  while( pWhere->op==TK_AND ){
    if( !whereUsablePartialIndex(iTab,pWC,pWhere->pLeft) ) return 0;
    if( !whereUsablePartialIndex(iTab,jointype,pWC,pWhere->pLeft) ) return 0;
    pWhere = pWhere->pRight;
  }
  if( pParse->db->flags & SQLITE_EnableQPSG ) pParse = 0;
  for(i=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
    Expr *pExpr;
    Expr *pExpr = pTerm->pExpr;
    if( (!ExprHasProperty(pExpr, EP_FromJoin) || pExpr->iRightJoinTable==iTab)
     && sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, iTab) 
    pExpr = pTerm->pExpr;
    if( (!ExprHasProperty(pExpr, EP_OuterON) || pExpr->w.iJoin==iTab)
     && ((jointype & JT_OUTER)==0 || ExprHasProperty(pExpr, EP_OuterON))
     && sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, iTab)
     && (pTerm->wtFlags & TERM_VNULL)==0
    ){
      return 1;
    }
  }
  return 0;
}

/*
** pIdx is an index containing expressions.  Check it see if any of the
** expressions in the index match the pExpr expression.
*/
static int exprIsCoveredByIndex(
  const Expr *pExpr,
  const Index *pIdx,
  int iTabCur
){
  int i;
  for(i=0; i<pIdx->nColumn; i++){
    if( pIdx->aiColumn[i]==XN_EXPR
     && sqlite3ExprCompare(0, pExpr, pIdx->aColExpr->a[i].pExpr, iTabCur)==0
    ){
      return 1;
    }
  }
  return 0;
}

/*
** Structure passed to the whereIsCoveringIndex Walker callback.
*/
typedef struct CoveringIndexCheck CoveringIndexCheck;
struct CoveringIndexCheck {
  Index *pIdx;       /* The index */
  int iTabCur;       /* Cursor number for the corresponding table */
  u8 bExpr;          /* Uses an indexed expression */
  u8 bUnidx;         /* Uses an unindexed column not within an indexed expr */
};

/*
** Information passed in is pWalk->u.pCovIdxCk.  Call it pCk.
**
** If the Expr node references the table with cursor pCk->iTabCur, then
** make sure that column is covered by the index pCk->pIdx.  We know that
** all columns less than 63 (really BMS-1) are covered, so we don't need
** to check them.  But we do need to check any column at 63 or greater.
**
** If the index does not cover the column, then set pWalk->eCode to 
** non-zero and return WRC_Abort to stop the search.
**
** If this node does not disprove that the index can be a covering index,
** then just return WRC_Continue, to continue the search.
**
** If pCk->pIdx contains indexed expressions and one of those expressions
** matches pExpr, then prune the search.
*/
static int whereIsCoveringIndexWalkCallback(Walker *pWalk, Expr *pExpr){
  int i;                    /* Loop counter */
  const Index *pIdx;        /* The index of interest */
  const i16 *aiColumn;      /* Columns contained in the index */
  u16 nColumn;              /* Number of columns in the index */
  CoveringIndexCheck *pCk;  /* Info about this search */

  pCk = pWalk->u.pCovIdxCk;
  pIdx = pCk->pIdx;
  if( (pExpr->op==TK_COLUMN || pExpr->op==TK_AGG_COLUMN) ){
    /* if( pExpr->iColumn<(BMS-1) && pIdx->bHasExpr==0 ) return WRC_Continue;*/
    if( pExpr->iTable!=pCk->iTabCur ) return WRC_Continue;
    pIdx = pWalk->u.pCovIdxCk->pIdx;
    aiColumn = pIdx->aiColumn;
    nColumn = pIdx->nColumn;
    for(i=0; i<nColumn; i++){
      if( aiColumn[i]==pExpr->iColumn ) return WRC_Continue;
    }
    pCk->bUnidx = 1;
    return WRC_Abort;
  }else if( pIdx->bHasExpr
         && exprIsCoveredByIndex(pExpr, pIdx, pWalk->u.pCovIdxCk->iTabCur) ){
    pCk->bExpr = 1;
    return WRC_Prune;
  }
  return WRC_Continue;
}


/*
** pIdx is an index that covers all of the low-number columns used by
** pWInfo->pSelect (columns from 0 through 62) or an index that has
** expressions terms.  Hence, we cannot determine whether or not it is
** a covering index by using the colUsed bitmasks.  We have to do a search
** to see if the index is covering.  This routine does that search.
**
** The return value is one of these:
**
**      0                The index is definitely not a covering index
**
**      WHERE_IDX_ONLY   The index is definitely a covering index
**
**      WHERE_EXPRIDX    The index is likely a covering index, but it is
**                       difficult to determine precisely because of the
**                       expressions that are indexed.  Score it as a
**                       covering index, but still keep the main table open
**                       just in case we need it.
**
** This routine is an optimization.  It is always safe to return zero.
** But returning one of the other two values when zero should have been
** returned can lead to incorrect bytecode and assertion faults.
*/
static SQLITE_NOINLINE u32 whereIsCoveringIndex(
  WhereInfo *pWInfo,     /* The WHERE clause context */
  Index *pIdx,           /* Index that is being tested */
  int iTabCur            /* Cursor for the table being indexed */
){
  int i, rc;
  struct CoveringIndexCheck ck;
  Walker w;
  if( pWInfo->pSelect==0 ){
    /* We don't have access to the full query, so we cannot check to see
    ** if pIdx is covering.  Assume it is not. */
    return 0;
  }
  if( pIdx->bHasExpr==0 ){
    for(i=0; i<pIdx->nColumn; i++){
      if( pIdx->aiColumn[i]>=BMS-1 ) break;
    }
    if( i>=pIdx->nColumn ){
      /* pIdx does not index any columns greater than 62, but we know from
      ** colMask that columns greater than 62 are used, so this is not a
      ** covering index */
      return 0;
    }
  }
  ck.pIdx = pIdx;
  ck.iTabCur = iTabCur;
  ck.bExpr = 0;
  ck.bUnidx = 0;
  memset(&w, 0, sizeof(w));
  w.xExprCallback = whereIsCoveringIndexWalkCallback;
  w.xSelectCallback = sqlite3SelectWalkNoop;
  w.u.pCovIdxCk = &ck;
  sqlite3WalkSelect(&w, pWInfo->pSelect);
  if( ck.bUnidx ){
    rc = 0;
  }else if( ck.bExpr ){
    rc = WHERE_EXPRIDX;
  }else{
    rc = WHERE_IDX_ONLY;
  }
  return rc;
}

/*
** Add all WhereLoop objects for a single table of the join where the table
** is identified by pBuilder->pNew->iTab.  That table is guaranteed to be
** a b-tree table, not a virtual table.
**
** The costs (WhereLoop.rRun) of the b-tree loops added by this function
2836
2837
2838
2839
2840
2841
2842
2843

2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861


2862
2863

2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879


2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896

2897
2898

2899
2900
2901
2902

2903
2904

2905
2906

2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924

2925
2926
2927


2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948

2949
2950
2951



2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967

2968
2969
2970

2971
2972
2973
2974
2975
2976















2977




2978
2979
2980
2981
2982
2983
2984
2985
2986
2987

2988
2989
2990




























2991
2992
2993
2994
2995
2996

2997
2998
2999
3000
3001
3002
3003
3504
3505
3506
3507
3508
3509
3510

3511
3512
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
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594

3595
3596
3597

3598
3599
3600
3601
3602
3603
3604
3605
3606
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
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678

3679
3680
3681
3682

3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724







-
+





-











-
+
+

-
+















-
+
+











-




-
+

-
+




+


+


+

















-
+


-
+
+




















-
+


-
+
+
+
















+


-
+





-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+








-

+


-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






+







){
  WhereInfo *pWInfo;          /* WHERE analysis context */
  Index *pProbe;              /* An index we are evaluating */
  Index sPk;                  /* A fake index object for the primary key */
  LogEst aiRowEstPk[2];       /* The aiRowLogEst[] value for the sPk index */
  i16 aiColumnPk = -1;        /* The aColumn[] value for the sPk index */
  SrcList *pTabList;          /* The FROM clause */
  struct SrcList_item *pSrc;  /* The FROM clause btree term to add */
  SrcItem *pSrc;              /* The FROM clause btree term to add */
  WhereLoop *pNew;            /* Template WhereLoop object */
  int rc = SQLITE_OK;         /* Return code */
  int iSortIdx = 1;           /* Index number */
  int b;                      /* A boolean value */
  LogEst rSize;               /* number of rows in the table */
  LogEst rLogSize;            /* Logarithm of the number of rows in the table */
  WhereClause *pWC;           /* The parsed WHERE clause */
  Table *pTab;                /* Table being queried */
  
  pNew = pBuilder->pNew;
  pWInfo = pBuilder->pWInfo;
  pTabList = pWInfo->pTabList;
  pSrc = pTabList->a + pNew->iTab;
  pTab = pSrc->pTab;
  pWC = pBuilder->pWC;
  assert( !IsVirtual(pSrc->pTab) );

  if( pSrc->pIBIndex ){
  if( pSrc->fg.isIndexedBy ){
    assert( pSrc->fg.isCte==0 );
    /* An INDEXED BY clause specifies a particular index to use */
    pProbe = pSrc->pIBIndex;
    pProbe = pSrc->u2.pIBIndex;
  }else if( !HasRowid(pTab) ){
    pProbe = pTab->pIndex;
  }else{
    /* There is no INDEXED BY clause.  Create a fake Index object in local
    ** variable sPk to represent the rowid primary key index.  Make this
    ** fake index the first in a chain of Index objects with all of the real
    ** indices to follow */
    Index *pFirst;                  /* First of real indices on the table */
    memset(&sPk, 0, sizeof(Index));
    sPk.nKeyCol = 1;
    sPk.nColumn = 1;
    sPk.aiColumn = &aiColumnPk;
    sPk.aiRowLogEst = aiRowEstPk;
    sPk.onError = OE_Replace;
    sPk.pTable = pTab;
    sPk.szIdxRow = pTab->szTabRow;
    sPk.szIdxRow = 3;  /* TUNING: Interior rows of IPK table are very small */
    sPk.idxType = SQLITE_IDXTYPE_IPK;
    aiRowEstPk[0] = pTab->nRowLogEst;
    aiRowEstPk[1] = 0;
    pFirst = pSrc->pTab->pIndex;
    if( pSrc->fg.notIndexed==0 ){
      /* The real indices of the table are only considered if the
      ** NOT INDEXED qualifier is omitted from the FROM clause */
      sPk.pNext = pFirst;
    }
    pProbe = &sPk;
  }
  rSize = pTab->nRowLogEst;
  rLogSize = estLog(rSize);

#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
  /* Automatic indexes */
  if( !pBuilder->pOrSet      /* Not part of an OR optimization */
   && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0
   && (pWInfo->wctrlFlags & (WHERE_RIGHT_JOIN|WHERE_OR_SUBCLAUSE))==0
   && (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0
   && pSrc->pIBIndex==0      /* Has no INDEXED BY clause */
   && !pSrc->fg.isIndexedBy  /* Has no INDEXED BY clause */
   && !pSrc->fg.notIndexed   /* Has no NOT INDEXED clause */
   && HasRowid(pTab)         /* Not WITHOUT ROWID table. (FIXME: Why not?) */
   && !pSrc->fg.isCorrelated /* Not a correlated subquery */
   && !pSrc->fg.isRecursive  /* Not a recursive common table expression. */
   && (pSrc->fg.jointype & JT_RIGHT)==0 /* Not the right tab of a RIGHT JOIN */
  ){
    /* Generate auto-index WhereLoops */
    LogEst rLogSize;         /* Logarithm of the number of rows in the table */
    WhereTerm *pTerm;
    WhereTerm *pWCEnd = pWC->a + pWC->nTerm;
    rLogSize = estLog(rSize);
    for(pTerm=pWC->a; rc==SQLITE_OK && pTerm<pWCEnd; pTerm++){
      if( pTerm->prereqRight & pNew->maskSelf ) continue;
      if( termCanDriveIndex(pTerm, pSrc, 0) ){
        pNew->u.btree.nEq = 1;
        pNew->nSkip = 0;
        pNew->u.btree.pIndex = 0;
        pNew->nLTerm = 1;
        pNew->aLTerm[0] = pTerm;
        /* TUNING: One-time cost for computing the automatic index is
        ** estimated to be X*N*log2(N) where N is the number of rows in
        ** the table being indexed and where X is 7 (LogEst=28) for normal
        ** tables or 0.5 (LogEst=-10) for views and subqueries.  The value
        ** of X is smaller for views and subqueries so that the query planner
        ** will be more aggressive about generating automatic indexes for
        ** those objects, since there is no opportunity to add schema
        ** indexes on subqueries and views. */
        pNew->rSetup = rLogSize + rSize;
        if( pTab->pSelect==0 && (pTab->tabFlags & TF_Ephemeral)==0 ){
        if( !IsView(pTab) && (pTab->tabFlags & TF_Ephemeral)==0 ){
          pNew->rSetup += 28;
        }else{
          pNew->rSetup -= 10;
          pNew->rSetup -= 25;  /* Greatly reduced setup cost for auto indexes
                               ** on ephemeral materializations of views */
        }
        ApplyCostMultiplier(pNew->rSetup, pTab->costMult);
        if( pNew->rSetup<0 ) pNew->rSetup = 0;
        /* TUNING: Each index lookup yields 20 rows in the table.  This
        ** is more than the usual guess of 10 rows, since we have no way
        ** of knowing how selective the index will ultimately be.  It would
        ** not be unreasonable to make this value much larger. */
        pNew->nOut = 43;  assert( 43==sqlite3LogEst(20) );
        pNew->rRun = sqlite3LogEstAdd(rLogSize,pNew->nOut);
        pNew->wsFlags = WHERE_AUTO_INDEX;
        pNew->prereq = mPrereq | pTerm->prereqRight;
        rc = whereLoopInsert(pBuilder, pNew);
      }
    }
  }
#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */

  /* Loop over all indices. If there was an INDEXED BY clause, then only 
  ** consider index pProbe.  */
  for(; rc==SQLITE_OK && pProbe; 
      pProbe=(pSrc->pIBIndex ? 0 : pProbe->pNext), iSortIdx++
      pProbe=(pSrc->fg.isIndexedBy ? 0 : pProbe->pNext), iSortIdx++
  ){
    if( pProbe->pPartIdxWhere!=0
     && !whereUsablePartialIndex(pSrc->iCursor, pWC, pProbe->pPartIdxWhere) ){
     && !whereUsablePartialIndex(pSrc->iCursor, pSrc->fg.jointype, pWC,
                                 pProbe->pPartIdxWhere)
    ){
      testcase( pNew->iTab!=pSrc->iCursor );  /* See ticket [98d973b8f5] */
      continue;  /* Partial index inappropriate for this query */
    }
    if( pProbe->bNoQuery ) continue;
    rSize = pProbe->aiRowLogEst[0];
    pNew->u.btree.nEq = 0;
    pNew->u.btree.nBtm = 0;
    pNew->u.btree.nTop = 0;
    pNew->nSkip = 0;
    pNew->nLTerm = 0;
    pNew->iSortIdx = 0;
    pNew->rSetup = 0;
    pNew->prereq = mPrereq;
    pNew->nOut = rSize;
    pNew->u.btree.pIndex = pProbe;
    b = indexMightHelpWithOrderBy(pBuilder, pProbe, pSrc->iCursor);

    /* The ONEPASS_DESIRED flags never occurs together with ORDER BY */
    assert( (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || b==0 );
    if( pProbe->tnum<=0 ){
    if( pProbe->idxType==SQLITE_IDXTYPE_IPK ){
      /* Integer primary key index */
      pNew->wsFlags = WHERE_IPK;

      /* Full table scan */
      pNew->iSortIdx = b ? iSortIdx : 0;
      /* TUNING: Cost of full table scan is (N*3.0). */
      /* TUNING: Cost of full table scan is 3.0*N.  The 3.0 factor is an
      ** extra cost designed to discourage the use of full table scans,
      ** since index lookups have better worst-case performance if our
      ** stat guesses are wrong.  Reduce the 3.0 penalty slightly
      ** (to 2.75) if we have valid STAT4 information for the table.
      ** At 2.75, a full table scan is preferred over using an index on
      ** a column with just two distinct values where each value has about
      ** an equal number of appearances.  Without STAT4 data, we still want
      ** to use an index in that case, since the constraint might be for
      ** the scarcer of the two values, and in that case an index lookup is
      ** better.
      */
#ifdef SQLITE_ENABLE_STAT4
      pNew->rRun = rSize + 16 - 2*((pTab->tabFlags & TF_HasStat4)!=0);
#else
      pNew->rRun = rSize + 16;
#endif
      if( IsView(pTab) || (pTab->tabFlags & TF_Ephemeral)!=0 ){
        pNew->wsFlags |= WHERE_VIEWSCAN;
      }
      ApplyCostMultiplier(pNew->rRun, pTab->costMult);
      whereLoopOutputAdjust(pWC, pNew, rSize);
      rc = whereLoopInsert(pBuilder, pNew);
      pNew->nOut = rSize;
      if( rc ) break;
    }else{
      Bitmask m;
      if( pProbe->isCovering ){
        pNew->wsFlags = WHERE_IDX_ONLY | WHERE_INDEXED;
        m = 0;
        pNew->wsFlags = WHERE_IDX_ONLY | WHERE_INDEXED;
      }else{
        m = pSrc->colUsed & pProbe->colNotIdxed;
        pNew->wsFlags = (m==0) ? (WHERE_IDX_ONLY|WHERE_INDEXED) : WHERE_INDEXED;
        pNew->wsFlags = WHERE_INDEXED;
        if( m==TOPBIT || (pProbe->bHasExpr && !pProbe->bHasVCol && m!=0) ){
          u32 isCov = whereIsCoveringIndex(pWInfo, pProbe, pSrc->iCursor);
          if( isCov==0 ){
            WHERETRACE(0x200,
               ("-> %s is not a covering index"
                " according to whereIsCoveringIndex()\n", pProbe->zName));
            assert( m!=0 );
          }else{
            m = 0;
            pNew->wsFlags |= isCov;
            if( isCov & WHERE_IDX_ONLY ){
              WHERETRACE(0x200,
                 ("-> %s is a covering expression index"
                  " according to whereIsCoveringIndex()\n", pProbe->zName));
            }else{
              assert( isCov==WHERE_EXPRIDX );
              WHERETRACE(0x200,
                 ("-> %s might be a covering expression index"
                  " according to whereIsCoveringIndex()\n", pProbe->zName));
            }
          }
        }else if( m==0 ){
          WHERETRACE(0x200,
             ("-> %s a covering index according to bitmasks\n",
             pProbe->zName, m==0 ? "is" : "is not"));
          pNew->wsFlags = WHERE_IDX_ONLY | WHERE_INDEXED;
        }
      }

      /* Full scan via index */
      if( b
       || !HasRowid(pTab)
       || pProbe->pPartIdxWhere!=0
       || pSrc->fg.isIndexedBy
       || ( m==0
         && pProbe->bUnordered==0
         && (pProbe->szIdxRow<pTab->szTabRow)
         && (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
         && sqlite3GlobalConfig.bUseCis
         && OptimizationEnabled(pWInfo->pParse->db, SQLITE_CoverIdxScan)
          )
3033
3034
3035
3036
3037
3038
3039






3040


3041
3042
3043
3044
3045
3046

3047
3048

3049
3050
3051
3052
3053
3054
3055

3056
3057
3058
3059
3060
3061
3062
3063
3064









3065
3066
3067
3068
3069
3070
3071
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766

3767
3768
3769
3770
3771
3772
3773

3774
3775

3776
3777
3778
3779
3780
3781
3782

3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808







+
+
+
+
+
+
-
+
+





-
+

-
+






-
+









+
+
+
+
+
+
+
+
+







            }
          }
          
          pNew->rRun = sqlite3LogEstAdd(pNew->rRun, nLookup);
        }
        ApplyCostMultiplier(pNew->rRun, pTab->costMult);
        whereLoopOutputAdjust(pWC, pNew, rSize);
        if( (pSrc->fg.jointype & JT_RIGHT)!=0 && pProbe->aColExpr ){
          /* Do not do an SCAN of a index-on-expression in a RIGHT JOIN
          ** because the cursor used to access the index might not be
          ** positioned to the correct row during the right-join no-match
          ** loop. */
        }else{
        rc = whereLoopInsert(pBuilder, pNew);
          rc = whereLoopInsert(pBuilder, pNew);
        }
        pNew->nOut = rSize;
        if( rc ) break;
      }
    }

    pBuilder->bldFlags = 0;
    pBuilder->bldFlags1 = 0;
    rc = whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, 0);
    if( pBuilder->bldFlags==SQLITE_BLDF_INDEXED ){
    if( pBuilder->bldFlags1==SQLITE_BLDF1_INDEXED ){
      /* If a non-unique index is used, or if a prefix of the key for
      ** unique index is used (making the index functionally non-unique)
      ** then the sqlite_stat1 data becomes important for scoring the
      ** plan */
      pTab->tabFlags |= TF_StatsUsed;
    }
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
    sqlite3Stat4ProbeFree(pBuilder->pRec);
    pBuilder->nRecValid = 0;
    pBuilder->pRec = 0;
#endif
  }
  return rc;
}

#ifndef SQLITE_OMIT_VIRTUALTABLE

/*
** Return true if pTerm is a virtual table LIMIT or OFFSET term.
*/
static int isLimitTerm(WhereTerm *pTerm){
  assert( pTerm->eOperator==WO_AUX || pTerm->eMatchOp==0 );
  return pTerm->eMatchOp>=SQLITE_INDEX_CONSTRAINT_LIMIT 
      && pTerm->eMatchOp<=SQLITE_INDEX_CONSTRAINT_OFFSET;
}

/*
** Argument pIdxInfo is already populated with all constraints that may
** be used by the virtual table identified by pBuilder->pNew->iTab. This
** function marks a subset of those constraints usable, invokes the
** xBestIndex method and adds the returned plan to pBuilder.
**
3086
3087
3088
3089
3090
3091
3092
3093


3094
3095

3096
3097
3098
3099
3100
3101
3102
3103

3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117

3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132

3133
3134
3135
3136
3137
3138
3139
3140
3141
3142

3143
3144
3145
3146
3147
3148
3149
3150
3151


3152
3153
3154
3155
3156
3157
3158
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
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
3899







-
+
+


+







-
+














+















+









-
+







-
-
+
+







static int whereLoopAddVirtualOne(
  WhereLoopBuilder *pBuilder,
  Bitmask mPrereq,                /* Mask of tables that must be used. */
  Bitmask mUsable,                /* Mask of usable tables */
  u16 mExclude,                   /* Exclude terms using these operators */
  sqlite3_index_info *pIdxInfo,   /* Populated object for xBestIndex */
  u16 mNoOmit,                    /* Do not omit these constraints */
  int *pbIn                       /* OUT: True if plan uses an IN(...) op */
  int *pbIn,                      /* OUT: True if plan uses an IN(...) op */
  int *pbRetryLimit               /* OUT: Retry without LIMIT/OFFSET */
){
  WhereClause *pWC = pBuilder->pWC;
  HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1];
  struct sqlite3_index_constraint *pIdxCons;
  struct sqlite3_index_constraint_usage *pUsage = pIdxInfo->aConstraintUsage;
  int i;
  int mxTerm;
  int rc = SQLITE_OK;
  WhereLoop *pNew = pBuilder->pNew;
  Parse *pParse = pBuilder->pWInfo->pParse;
  struct SrcList_item *pSrc = &pBuilder->pWInfo->pTabList->a[pNew->iTab];
  SrcItem *pSrc = &pBuilder->pWInfo->pTabList->a[pNew->iTab];
  int nConstraint = pIdxInfo->nConstraint;

  assert( (mUsable & mPrereq)==mPrereq );
  *pbIn = 0;
  pNew->prereq = mPrereq;

  /* Set the usable flag on the subset of constraints identified by 
  ** arguments mUsable and mExclude. */
  pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
  for(i=0; i<nConstraint; i++, pIdxCons++){
    WhereTerm *pTerm = &pWC->a[pIdxCons->iTermOffset];
    pIdxCons->usable = 0;
    if( (pTerm->prereqRight & mUsable)==pTerm->prereqRight 
     && (pTerm->eOperator & mExclude)==0
     && (pbRetryLimit || !isLimitTerm(pTerm))
    ){
      pIdxCons->usable = 1;
    }
  }

  /* Initialize the output fields of the sqlite3_index_info structure */
  memset(pUsage, 0, sizeof(pUsage[0])*nConstraint);
  assert( pIdxInfo->needToFreeIdxStr==0 );
  pIdxInfo->idxStr = 0;
  pIdxInfo->idxNum = 0;
  pIdxInfo->orderByConsumed = 0;
  pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2;
  pIdxInfo->estimatedRows = 25;
  pIdxInfo->idxFlags = 0;
  pIdxInfo->colUsed = (sqlite3_int64)pSrc->colUsed;
  pHidden->mHandleIn = 0;

  /* Invoke the virtual table xBestIndex() method */
  rc = vtabBestIndex(pParse, pSrc->pTab, pIdxInfo);
  if( rc ){
    if( rc==SQLITE_CONSTRAINT ){
      /* If the xBestIndex method returns SQLITE_CONSTRAINT, that means
      ** that the particular combination of parameters provided is unusable.
      ** Make no entries in the loop table.
      */
      WHERETRACE(0xffff, ("  ^^^^--- non-viable plan rejected!\n"));
      WHERETRACE(0xffffffff, ("  ^^^^--- non-viable plan rejected!\n"));
      return SQLITE_OK;
    }
    return rc;
  }

  mxTerm = -1;
  assert( pNew->nLSlot>=nConstraint );
  for(i=0; i<nConstraint; i++) pNew->aLTerm[i] = 0;
  pNew->u.vtab.omitMask = 0;
  memset(pNew->aLTerm, 0, sizeof(pNew->aLTerm[0])*nConstraint );
  memset(&pNew->u.vtab, 0, sizeof(pNew->u.vtab));
  pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
  for(i=0; i<nConstraint; i++, pIdxCons++){
    int iTerm;
    if( (iTerm = pUsage[i].argvIndex - 1)>=0 ){
      WhereTerm *pTerm;
      int j = pIdxCons->iTermOffset;
      if( iTerm>=nConstraint
3171
3172
3173
3174
3175
3176
3177



3178
3179











3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191


















3192
3193
3194
3195
3196
3197
3198
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921


3922
3923
3924
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
3962
3963
3964
3965
3966







+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+









-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







      pTerm = &pWC->a[j];
      pNew->prereq |= pTerm->prereqRight;
      assert( iTerm<pNew->nLSlot );
      pNew->aLTerm[iTerm] = pTerm;
      if( iTerm>mxTerm ) mxTerm = iTerm;
      testcase( iTerm==15 );
      testcase( iTerm==16 );
      if( pUsage[i].omit ){
        if( i<16 && ((1<<i)&mNoOmit)==0 ){
          testcase( i!=iTerm );
      if( iTerm<16 && pUsage[i].omit ) pNew->u.vtab.omitMask |= 1<<iTerm;
      if( (pTerm->eOperator & WO_IN)!=0 ){
          pNew->u.vtab.omitMask |= 1<<iTerm;
        }else{
          testcase( i!=iTerm );
        }
        if( pTerm->eMatchOp==SQLITE_INDEX_CONSTRAINT_OFFSET ){
          pNew->u.vtab.bOmitOffset = 1;
        }
      }
      if( SMASKBIT32(i) & pHidden->mHandleIn ){ 
        pNew->u.vtab.mHandleIn |= MASKBIT32(iTerm);
      }else if( (pTerm->eOperator & WO_IN)!=0 ){
        /* A virtual table that is constrained by an IN clause may not
        ** consume the ORDER BY clause because (1) the order of IN terms
        ** is not necessarily related to the order of output terms and
        ** (2) Multiple outputs from a single IN value will not merge
        ** together.  */
        pIdxInfo->orderByConsumed = 0;
        pIdxInfo->idxFlags &= ~SQLITE_INDEX_SCAN_UNIQUE;
        *pbIn = 1; assert( (mExclude & WO_IN)==0 );
      }
    }
  }
  pNew->u.vtab.omitMask &= ~mNoOmit;

      assert( pbRetryLimit || !isLimitTerm(pTerm) );
      if( isLimitTerm(pTerm) && *pbIn ){
        /* If there is an IN(...) term handled as an == (separate call to
        ** xFilter for each value on the RHS of the IN) and a LIMIT or
        ** OFFSET term handled as well, the plan is unusable. Set output
        ** variable *pbRetryLimit to true to tell the caller to retry with
        ** LIMIT and OFFSET disabled. */
        if( pIdxInfo->needToFreeIdxStr ){
          sqlite3_free(pIdxInfo->idxStr);
          pIdxInfo->idxStr = 0;
          pIdxInfo->needToFreeIdxStr = 0;
        }
        *pbRetryLimit = 1;
        return SQLITE_OK;
      }
    }
  }

  pNew->nLTerm = mxTerm+1;
  for(i=0; i<=mxTerm; i++){
    if( pNew->aLTerm[i]==0 ){
      /* The non-zero argvIdx values must be contiguous.  Raise an
      ** error if they are not */
      sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName);
3219
3220
3221
3222
3223
3224
3225
3226

3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238













3239
3240
3241
3242
3243
3244
3245
3246
3247
3248

3249
3250
3251
3252
3253
3254



























































































3255
3256
3257
3258
3259
3260
3261
3987
3988
3989
3990
3991
3992
3993

3994
3995
3996
3997
3998
3999
4000
4001





4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023

4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
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
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128







-
+







-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+









-
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    pNew->wsFlags &= ~WHERE_ONEROW;
  }
  rc = whereLoopInsert(pBuilder, pNew);
  if( pNew->u.vtab.needFree ){
    sqlite3_free(pNew->u.vtab.idxStr);
    pNew->u.vtab.needFree = 0;
  }
  WHERETRACE(0xffff, ("  bIn=%d prereqIn=%04llx prereqOut=%04llx\n",
  WHERETRACE(0xffffffff, ("  bIn=%d prereqIn=%04llx prereqOut=%04llx\n",
                      *pbIn, (sqlite3_uint64)mPrereq,
                      (sqlite3_uint64)(pNew->prereq & ~mPrereq)));

  return rc;
}

/*
** If this function is invoked from within an xBestIndex() callback, it
** returns a pointer to a buffer containing the name of the collation
** sequence associated with element iCons of the sqlite3_index_info.aConstraint
** array. Or, if iCons is out of range or there is no active xBestIndex
** call, return NULL.
** Return the collating sequence for a constraint passed into xBestIndex.
**
** pIdxInfo must be an sqlite3_index_info structure passed into xBestIndex.
** This routine depends on there being a HiddenIndexInfo structure immediately
** following the sqlite3_index_info structure.
**
** Return a pointer to the collation name:
**
**    1. If there is an explicit COLLATE operator on the constaint, return it.
**
**    2. Else, if the column has an alternative collation, return that.
**
**    3. Otherwise, return "BINARY".
*/
const char *sqlite3_vtab_collation(sqlite3_index_info *pIdxInfo, int iCons){
  HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1];
  const char *zRet = 0;
  if( iCons>=0 && iCons<pIdxInfo->nConstraint ){
    CollSeq *pC = 0;
    int iTerm = pIdxInfo->aConstraint[iCons].iTermOffset;
    Expr *pX = pHidden->pWC->a[iTerm].pExpr;
    if( pX->pLeft ){
      pC = sqlite3BinaryCompareCollSeq(pHidden->pParse, pX->pLeft, pX->pRight);
      pC = sqlite3ExprCompareCollSeq(pHidden->pParse, pX);
    }
    zRet = (pC ? pC->zName : sqlite3StrBINARY);
  }
  return zRet;
}

/*
** Return true if constraint iCons is really an IN(...) constraint, or
** false otherwise. If iCons is an IN(...) constraint, set (if bHandle!=0)
** or clear (if bHandle==0) the flag to handle it using an iterator.
*/
int sqlite3_vtab_in(sqlite3_index_info *pIdxInfo, int iCons, int bHandle){
  HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1];
  u32 m = SMASKBIT32(iCons);
  if( m & pHidden->mIn ){
    if( bHandle==0 ){ 
      pHidden->mHandleIn &= ~m;
    }else if( bHandle>0 ){
      pHidden->mHandleIn |= m;
    }
    return 1;
  }
  return 0;
}

/*
** This interface is callable from within the xBestIndex callback only.
**
** If possible, set (*ppVal) to point to an object containing the value 
** on the right-hand-side of constraint iCons.
*/
int sqlite3_vtab_rhs_value(
  sqlite3_index_info *pIdxInfo,   /* Copy of first argument to xBestIndex */
  int iCons,                      /* Constraint for which RHS is wanted */
  sqlite3_value **ppVal           /* Write value extracted here */
){
  HiddenIndexInfo *pH = (HiddenIndexInfo*)&pIdxInfo[1];
  sqlite3_value *pVal = 0;
  int rc = SQLITE_OK;
  if( iCons<0 || iCons>=pIdxInfo->nConstraint ){
    rc = SQLITE_MISUSE; /* EV: R-30545-25046 */
  }else{
    if( pH->aRhs[iCons]==0 ){
      WhereTerm *pTerm = &pH->pWC->a[pIdxInfo->aConstraint[iCons].iTermOffset];
      rc = sqlite3ValueFromExpr(
          pH->pParse->db, pTerm->pExpr->pRight, ENC(pH->pParse->db),
          SQLITE_AFF_BLOB, &pH->aRhs[iCons]
      );
      testcase( rc!=SQLITE_OK );
    }
    pVal = pH->aRhs[iCons];
  }
  *ppVal = pVal;

  if( rc==SQLITE_OK && pVal==0 ){  /* IMP: R-19933-32160 */
    rc = SQLITE_NOTFOUND;          /* IMP: R-36424-56542 */
  }

  return rc;
}

/*
** Return true if ORDER BY clause may be handled as DISTINCT.
*/
int sqlite3_vtab_distinct(sqlite3_index_info *pIdxInfo){
  HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1];
  assert( pHidden->eDistinct>=0 && pHidden->eDistinct<=3 );
  return pHidden->eDistinct;
}

#if (defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)) \
    && !defined(SQLITE_OMIT_VIRTUALTABLE)
/*
** Cause the prepared statement that is associated with a call to
** xBestIndex to potentially use all schemas.  If the statement being
** prepared is read-only, then just start read transactions on all
** schemas.  But if this is a write operation, start writes on all
** schemas.
**
** This is used by the (built-in) sqlite_dbpage virtual table.
*/
void sqlite3VtabUsesAllSchemas(sqlite3_index_info *pIdxInfo){
  HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1];
  Parse *pParse = pHidden->pParse;
  int nDb = pParse->db->nDb;
  int i;
  for(i=0; i<nDb; i++){
    sqlite3CodeVerifySchema(pParse, i);
  }
  if( DbMaskNonZero(pParse->writeMask) ){
    for(i=0; i<nDb; i++){
      sqlite3BeginWriteOperation(pParse, 0, i);
    }
  }
}
#endif

/*
** Add all WhereLoop objects for a table of the join identified by
** pBuilder->pNew->iTab.  That table is guaranteed to be a virtual table.
**
** If there are no LEFT or CROSS JOIN joins in the query, both mPrereq and
** mUnusable are set to 0. Otherwise, mPrereq is a mask of all FROM clause
** entries that occur before the virtual table in the FROM clause and are
3282
3283
3284
3285
3286
3287
3288
3289

3290
3291
3292
3293
3294
3295

3296
3297
3298
3299
3300
3301
3302
3303
3304

3305
3306
3307
3308
3309
3310
3311
3312
3313

3314
3315
3316
3317
3318
3319
3320
3321











3322
3323
3324
3325
3326
3327





3328
3329
3330
3331
3332
3333
3334
3335
3336

3337
3338

3339
3340
3341
3342
3343
3344
3345
4149
4150
4151
4152
4153
4154
4155

4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171

4172

4173
4174
4175
4176
4177
4178
4179

4180
4181
4182
4183
4184
4185



4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197





4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210

4211
4212

4213
4214
4215
4216
4217
4218
4219
4220







-
+






+








-
+
-







-
+





-
-
-
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+








-
+

-
+







  Bitmask mPrereq,             /* Tables that must be scanned before this one */
  Bitmask mUnusable            /* Tables that must be scanned after this one */
){
  int rc = SQLITE_OK;          /* Return code */
  WhereInfo *pWInfo;           /* WHERE analysis context */
  Parse *pParse;               /* The parsing context */
  WhereClause *pWC;            /* The WHERE clause */
  struct SrcList_item *pSrc;   /* The FROM clause term to search */
  SrcItem *pSrc;               /* The FROM clause term to search */
  sqlite3_index_info *p;       /* Object to pass to xBestIndex() */
  int nConstraint;             /* Number of constraints in p */
  int bIn;                     /* True if plan uses IN(...) operator */
  WhereLoop *pNew;
  Bitmask mBest;               /* Tables used by best possible plan */
  u16 mNoOmit;
  int bRetry = 0;              /* True to retry with LIMIT/OFFSET disabled */

  assert( (mPrereq & mUnusable)==0 );
  pWInfo = pBuilder->pWInfo;
  pParse = pWInfo->pParse;
  pWC = pBuilder->pWC;
  pNew = pBuilder->pNew;
  pSrc = &pWInfo->pTabList->a[pNew->iTab];
  assert( IsVirtual(pSrc->pTab) );
  p = allocateIndexInfo(pParse, pWC, mUnusable, pSrc, pBuilder->pOrderBy, 
  p = allocateIndexInfo(pWInfo, pWC, mUnusable, pSrc, &mNoOmit);
      &mNoOmit);
  if( p==0 ) return SQLITE_NOMEM_BKPT;
  pNew->rSetup = 0;
  pNew->wsFlags = WHERE_VIRTUALTABLE;
  pNew->nLTerm = 0;
  pNew->u.vtab.needFree = 0;
  nConstraint = p->nConstraint;
  if( whereLoopResize(pParse->db, pNew, nConstraint) ){
    sqlite3DbFree(pParse->db, p);
    freeIndexInfo(pParse->db, p);
    return SQLITE_NOMEM_BKPT;
  }

  /* First call xBestIndex() with all constraints usable. */
  WHERETRACE(0x800, ("BEGIN %s.addVirtual()\n", pSrc->pTab->zName));
  WHERETRACE(0x40, ("  VirtualOne: all usable\n"));
  rc = whereLoopAddVirtualOne(pBuilder, mPrereq, ALLBITS, 0, p, mNoOmit, &bIn);

  WHERETRACE(0x800, ("  VirtualOne: all usable\n"));
  rc = whereLoopAddVirtualOne(
      pBuilder, mPrereq, ALLBITS, 0, p, mNoOmit, &bIn, &bRetry
  );
  if( bRetry ){
    assert( rc==SQLITE_OK );
    rc = whereLoopAddVirtualOne(
        pBuilder, mPrereq, ALLBITS, 0, p, mNoOmit, &bIn, 0
    );
  }

  /* If the call to xBestIndex() with all terms enabled produced a plan
  ** that does not require any source tables (IOW: a plan with mBest==0),
  ** then there is no point in making any further calls to xBestIndex() 
  ** since they will all return the same result (if the xBestIndex()
  ** implementation is sane). */
  if( rc==SQLITE_OK && (mBest = (pNew->prereq & ~mPrereq))!=0 ){
  ** that does not require any source tables (IOW: a plan with mBest==0)
  ** and does not use an IN(...) operator, then there is no point in making 
  ** any further calls to xBestIndex() since they will all return the same
  ** result (if the xBestIndex() implementation is sane). */
  if( rc==SQLITE_OK && ((mBest = (pNew->prereq & ~mPrereq))!=0 || bIn) ){
    int seenZero = 0;             /* True if a plan with no prereqs seen */
    int seenZeroNoIN = 0;         /* Plan with no prereqs and no IN(...) seen */
    Bitmask mPrev = 0;
    Bitmask mBestNoIn = 0;

    /* If the plan produced by the earlier call uses an IN(...) term, call
    ** xBestIndex again, this time with IN(...) terms disabled. */
    if( bIn ){
      WHERETRACE(0x40, ("  VirtualOne: all usable w/o IN\n"));
      WHERETRACE(0x800, ("  VirtualOne: all usable w/o IN\n"));
      rc = whereLoopAddVirtualOne(
          pBuilder, mPrereq, ALLBITS, WO_IN, p, mNoOmit, &bIn);
          pBuilder, mPrereq, ALLBITS, WO_IN, p, mNoOmit, &bIn, 0);
      assert( bIn==0 );
      mBestNoIn = pNew->prereq & ~mPrereq;
      if( mBestNoIn==0 ){
        seenZero = 1;
        seenZeroNoIN = 1;
      }
    }
3355
3356
3357
3358
3359
3360
3361
3362

3363
3364
3365

3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376

3377
3378

3379
3380
3381
3382
3383
3384
3385
3386

3387
3388

3389
3390
3391
3392
3393

3394
3395
3396
3397
3398
3399
3400
4230
4231
4232
4233
4234
4235
4236

4237
4238
4239

4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250

4251
4252

4253
4254
4255
4256
4257
4258
4259
4260

4261
4262

4263
4264
4265
4266
4267

4268
4269
4270
4271
4272
4273
4274
4275







-
+


-
+










-
+

-
+







-
+

-
+




-
+







            pWC->a[p->aConstraint[i].iTermOffset].prereqRight & ~mPrereq
        );
        if( mThis>mPrev && mThis<mNext ) mNext = mThis;
      }
      mPrev = mNext;
      if( mNext==ALLBITS ) break;
      if( mNext==mBest || mNext==mBestNoIn ) continue;
      WHERETRACE(0x40, ("  VirtualOne: mPrev=%04llx mNext=%04llx\n",
      WHERETRACE(0x800, ("  VirtualOne: mPrev=%04llx mNext=%04llx\n",
                       (sqlite3_uint64)mPrev, (sqlite3_uint64)mNext));
      rc = whereLoopAddVirtualOne(
          pBuilder, mPrereq, mNext|mPrereq, 0, p, mNoOmit, &bIn);
          pBuilder, mPrereq, mNext|mPrereq, 0, p, mNoOmit, &bIn, 0);
      if( pNew->prereq==mPrereq ){
        seenZero = 1;
        if( bIn==0 ) seenZeroNoIN = 1;
      }
    }

    /* If the calls to xBestIndex() in the above loop did not find a plan
    ** that requires no source tables at all (i.e. one guaranteed to be
    ** usable), make a call here with all source tables disabled */
    if( rc==SQLITE_OK && seenZero==0 ){
      WHERETRACE(0x40, ("  VirtualOne: all disabled\n"));
      WHERETRACE(0x800, ("  VirtualOne: all disabled\n"));
      rc = whereLoopAddVirtualOne(
          pBuilder, mPrereq, mPrereq, 0, p, mNoOmit, &bIn);
          pBuilder, mPrereq, mPrereq, 0, p, mNoOmit, &bIn, 0);
      if( bIn==0 ) seenZeroNoIN = 1;
    }

    /* If the calls to xBestIndex() have so far failed to find a plan
    ** that requires no source tables at all and does not use an IN(...)
    ** operator, make a final call to obtain one here.  */
    if( rc==SQLITE_OK && seenZeroNoIN==0 ){
      WHERETRACE(0x40, ("  VirtualOne: all disabled and w/o IN\n"));
      WHERETRACE(0x800, ("  VirtualOne: all disabled and w/o IN\n"));
      rc = whereLoopAddVirtualOne(
          pBuilder, mPrereq, mPrereq, WO_IN, p, mNoOmit, &bIn);
          pBuilder, mPrereq, mPrereq, WO_IN, p, mNoOmit, &bIn, 0);
    }
  }

  if( p->needToFreeIdxStr ) sqlite3_free(p->idxStr);
  sqlite3DbFreeNN(pParse->db, p);
  freeIndexInfo(pParse->db, p);
  WHERETRACE(0x800, ("END %s.addVirtual(), rc=%d\n", pSrc->pTab->zName, rc));
  return rc;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */

/*
** Add WhereLoop entries to handle OR terms.  This works for either
3410
3411
3412
3413
3414
3415
3416
3417

3418
3419
3420
3421
3422
3423
3424



3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440

3441
3442
3443
3444
3445
3446
3447
3448

3449
3450
3451
3452
3453
3454
3455
3456

3457
3458

3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472

3473

3474
3475
3476
3477
3478
3479
3480
4285
4286
4287
4288
4289
4290
4291

4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
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







-
+







+
+
+












-


-
+








+







-
+

-
+














+
-
+







  WhereLoop *pNew;
  WhereTerm *pTerm, *pWCEnd;
  int rc = SQLITE_OK;
  int iCur;
  WhereClause tempWC;
  WhereLoopBuilder sSubBuild;
  WhereOrSet sSum, sCur;
  struct SrcList_item *pItem;
  SrcItem *pItem;
  
  pWC = pBuilder->pWC;
  pWCEnd = pWC->a + pWC->nTerm;
  pNew = pBuilder->pNew;
  memset(&sSum, 0, sizeof(sSum));
  pItem = pWInfo->pTabList->a + pNew->iTab;
  iCur = pItem->iCursor;

  /* The multi-index OR optimization does not work for RIGHT and FULL JOIN */
  if( pItem->fg.jointype & JT_RIGHT ) return SQLITE_OK;

  for(pTerm=pWC->a; pTerm<pWCEnd && rc==SQLITE_OK; pTerm++){
    if( (pTerm->eOperator & WO_OR)!=0
     && (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0 
    ){
      WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc;
      WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm];
      WhereTerm *pOrTerm;
      int once = 1;
      int i, j;
    
      sSubBuild = *pBuilder;
      sSubBuild.pOrderBy = 0;
      sSubBuild.pOrSet = &sCur;

      WHERETRACE(0x200, ("Begin processing OR-clause %p\n", pTerm));
      WHERETRACE(0x400, ("Begin processing OR-clause %p\n", pTerm));
      for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
        if( (pOrTerm->eOperator & WO_AND)!=0 ){
          sSubBuild.pWC = &pOrTerm->u.pAndInfo->wc;
        }else if( pOrTerm->leftCursor==iCur ){
          tempWC.pWInfo = pWC->pWInfo;
          tempWC.pOuter = pWC;
          tempWC.op = TK_AND;
          tempWC.nTerm = 1;
          tempWC.nBase = 1;
          tempWC.a = pOrTerm;
          sSubBuild.pWC = &tempWC;
        }else{
          continue;
        }
        sCur.n = 0;
#ifdef WHERETRACE_ENABLED
        WHERETRACE(0x200, ("OR-term %d of %p has %d subterms:\n", 
        WHERETRACE(0x400, ("OR-term %d of %p has %d subterms:\n", 
                   (int)(pOrTerm-pOrWC->a), pTerm, sSubBuild.pWC->nTerm));
        if( sqlite3WhereTrace & 0x400 ){
        if( sqlite3WhereTrace & 0x20000 ){
          sqlite3WhereClausePrint(sSubBuild.pWC);
        }
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
        if( IsVirtual(pItem->pTab) ){
          rc = whereLoopAddVirtual(&sSubBuild, mPrereq, mUnusable);
        }else
#endif
        {
          rc = whereLoopAddBtree(&sSubBuild, mPrereq);
        }
        if( rc==SQLITE_OK ){
          rc = whereLoopAddOr(&sSubBuild, mPrereq, mUnusable);
        }
        testcase( rc==SQLITE_NOMEM && sCur.n>0 );
        assert( rc==SQLITE_OK || sCur.n==0 );
        testcase( rc==SQLITE_DONE );
        if( sCur.n==0 ){
          sSum.n = 0;
          break;
        }else if( once ){
          whereOrMove(&sSum, &sCur);
          once = 0;
        }else{
3510
3511
3512
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
4389
4390
4391
4392
4393
4394
4395

4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410


4411
4412
4413
4414
4415
4416
4417

4418
4419
4420
4421

4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435




4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453

4454
4455

4456
4457

4458
4459
4460
4461
4462
4463
4464
4465







-
+














-
-
+
+


+
+

-
+



-
+
+
+
+
+
+
+






+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-


-
+

-
+







        ** the planner may elect to "OR" together a full-table scan and an
        ** index lookup. And other similarly odd results.  */
        pNew->rRun = sSum.a[i].rRun + 1;
        pNew->nOut = sSum.a[i].nOut;
        pNew->prereq = sSum.a[i].prereq;
        rc = whereLoopInsert(pBuilder, pNew);
      }
      WHERETRACE(0x200, ("End processing OR-clause %p\n", pTerm));
      WHERETRACE(0x400, ("End processing OR-clause %p\n", pTerm));
    }
  }
  return rc;
}

/*
** Add all WhereLoop objects for all tables 
*/
static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
  WhereInfo *pWInfo = pBuilder->pWInfo;
  Bitmask mPrereq = 0;
  Bitmask mPrior = 0;
  int iTab;
  SrcList *pTabList = pWInfo->pTabList;
  struct SrcList_item *pItem;
  struct SrcList_item *pEnd = &pTabList->a[pWInfo->nLevel];
  SrcItem *pItem;
  SrcItem *pEnd = &pTabList->a[pWInfo->nLevel];
  sqlite3 *db = pWInfo->pParse->db;
  int rc = SQLITE_OK;
  int bFirstPastRJ = 0;
  int hasRightJoin = 0;
  WhereLoop *pNew;
  u8 priorJointype = 0;


  /* Loop over the tables in the join, from left to right */
  pNew = pBuilder->pNew;
  whereLoopInit(pNew);

  /* Verify that pNew has already been initialized */
  assert( pNew->nLTerm==0 );
  assert( pNew->wsFlags==0 );
  assert( pNew->nLSlot>=ArraySize(pNew->aLTermSpace) );
  assert( pNew->aLTerm!=0 );

  pBuilder->iPlanLimit = SQLITE_QUERY_PLANNER_LIMIT;
  for(iTab=0, pItem=pTabList->a; pItem<pEnd; iTab++, pItem++){
    Bitmask mUnusable = 0;
    pNew->iTab = iTab;
    pBuilder->iPlanLimit += SQLITE_QUERY_PLANNER_LIMIT_INCR;
    pNew->maskSelf = sqlite3WhereGetMask(&pWInfo->sMaskSet, pItem->iCursor);
    if( bFirstPastRJ 
    if( ((pItem->fg.jointype|priorJointype) & (JT_LEFT|JT_CROSS))!=0 ){
      /* This condition is true when pItem is the FROM clause term on the
      ** right-hand-side of a LEFT or CROSS JOIN.  */
      mPrereq = mPrior;
     || (pItem->fg.jointype & (JT_OUTER|JT_CROSS|JT_LTORJ))!=0
    ){
      /* Add prerequisites to prevent reordering of FROM clause terms
      ** across CROSS joins and outer joins.  The bFirstPastRJ boolean
      ** prevents the right operand of a RIGHT JOIN from being swapped with
      ** other elements even further to the right.
      **
      ** The JT_LTORJ case and the hasRightJoin flag work together to
      ** prevent FROM-clause terms from moving from the right side of
      ** a LEFT JOIN over to the left side of that join if the LEFT JOIN
      ** is itself on the left side of a RIGHT JOIN.
      */
      if( pItem->fg.jointype & JT_LTORJ ) hasRightJoin = 1;
      mPrereq |= mPrior;
      bFirstPastRJ = (pItem->fg.jointype & JT_RIGHT)!=0;
    }else if( !hasRightJoin ){
      mPrereq = 0;
    }
    priorJointype = pItem->fg.jointype;
#ifndef SQLITE_OMIT_VIRTUALTABLE
    if( IsVirtual(pItem->pTab) ){
      struct SrcList_item *p;
      SrcItem *p;
      for(p=&pItem[1]; p<pEnd; p++){
        if( mUnusable || (p->fg.jointype & (JT_LEFT|JT_CROSS)) ){
        if( mUnusable || (p->fg.jointype & (JT_OUTER|JT_CROSS)) ){
          mUnusable |= sqlite3WhereGetMask(&pWInfo->sMaskSet, p->iCursor);
        }
      }
      rc = whereLoopAddVirtual(pBuilder, mPrereq, mUnusable);
    }else
#endif /* SQLITE_OMIT_VIRTUALTABLE */
    {
3664
3665
3666
3667
3668
3669
3670

3671


3672
3673
3674
3675
3676
3677
3678
3679
3680
3681





3682
3683
3684


3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696



3697
3698
3699
3700
3701
3702
3703
3704
3705


3706
3707
3708
3709
3710
3711





3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731




3732


3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750




3751
3752
3753
3754
3755
3756


3757

3758


3759
3760
3761
3762
3763
3764
3765
4564
4565
4566
4567
4568
4569
4570
4571

4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582

4583
4584
4585
4586
4587
4588


4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600


4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611

4612
4613
4614
4615
4616
4617


4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646

4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665

4666
4667
4668
4669
4670
4671
4672
4673
4674

4675
4676
4677
4678

4679
4680
4681
4682
4683
4684
4685
4686
4687







+
-
+
+









-
+
+
+
+
+

-
-
+
+










-
-
+
+
+








-
+
+




-
-
+
+
+
+
+




















+
+
+
+
-
+
+

















-
+
+
+
+





-
+
+

+
-
+
+







  testcase( nOrderBy==BMS-1 );
  if( nOrderBy>BMS-1 ) return 0;  /* Cannot optimize overly large ORDER BYs */
  isOrderDistinct = 1;
  obDone = MASKBIT(nOrderBy)-1;
  orderDistinctMask = 0;
  ready = 0;
  eqOpMask = WO_EQ | WO_IS | WO_ISNULL;
  if( wctrlFlags & (WHERE_ORDERBY_LIMIT|WHERE_ORDERBY_MAX|WHERE_ORDERBY_MIN) ){
  if( wctrlFlags & WHERE_ORDERBY_LIMIT ) eqOpMask |= WO_IN;
    eqOpMask |= WO_IN;
  }
  for(iLoop=0; isOrderDistinct && obSat<obDone && iLoop<=nLoop; iLoop++){
    if( iLoop>0 ) ready |= pLoop->maskSelf;
    if( iLoop<nLoop ){
      pLoop = pPath->aLoop[iLoop];
      if( wctrlFlags & WHERE_ORDERBY_LIMIT ) continue;
    }else{
      pLoop = pLast;
    }
    if( pLoop->wsFlags & WHERE_VIRTUALTABLE ){
      if( pLoop->u.vtab.isOrdered ) obSat = obDone;
      if( pLoop->u.vtab.isOrdered 
       && ((wctrlFlags&(WHERE_DISTINCTBY|WHERE_SORTBYGROUP))!=WHERE_DISTINCTBY)
      ){
        obSat = obDone;
      }
      break;
    }else{
      pLoop->u.btree.nIdxCol = 0;
    }else if( wctrlFlags & WHERE_DISTINCTBY ){
      pLoop->u.btree.nDistinctCol = 0;
    }
    iCur = pWInfo->pTabList->a[pLoop->iTab].iCursor;

    /* Mark off any ORDER BY term X that is a column in the table of
    ** the current loop for which there is term in the WHERE
    ** 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 = sqlite3ExprSkipCollate(pOrderBy->a[i].pExpr);
      if( pOBExpr->op!=TK_COLUMN ) continue;
      pOBExpr = sqlite3ExprSkipCollateAndLikely(pOrderBy->a[i].pExpr);
      if( NEVER(pOBExpr==0) ) continue;
      if( pOBExpr->op!=TK_COLUMN && pOBExpr->op!=TK_AGG_COLUMN ) continue;
      if( pOBExpr->iTable!=iCur ) continue;
      pTerm = sqlite3WhereFindTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn,
                       ~ready, eqOpMask, 0);
      if( pTerm==0 ) continue;
      if( pTerm->eOperator==WO_IN ){
        /* IN terms are only valid for sorting in the ORDER BY LIMIT 
        ** optimization, and then only if they are actually used
        ** by the query plan */
        assert( wctrlFlags & WHERE_ORDERBY_LIMIT );
        assert( wctrlFlags & 
               (WHERE_ORDERBY_LIMIT|WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX) );
        for(j=0; j<pLoop->nLTerm && pTerm!=pLoop->aLTerm[j]; j++){}
        if( j>=pLoop->nLTerm ) continue;
      }
      if( (pTerm->eOperator&(WO_EQ|WO_IS))!=0 && pOBExpr->iColumn>=0 ){
        if( sqlite3ExprCollSeqMatch(pWInfo->pParse, 
                  pOrderBy->a[i].pExpr, pTerm->pExpr)==0 ){
        Parse *pParse = pWInfo->pParse;
        CollSeq *pColl1 = sqlite3ExprNNCollSeq(pParse, pOrderBy->a[i].pExpr);
        CollSeq *pColl2 = sqlite3ExprCompareCollSeq(pParse, pTerm->pExpr);
        assert( pColl1 );
        if( pColl2==0 || sqlite3StrICmp(pColl1->zName, pColl2->zName) ){
          continue;
        }
        testcase( pTerm->pExpr->op==TK_IS );
      }
      obSat |= MASKBIT(i);
    }

    if( (pLoop->wsFlags & WHERE_ONEROW)==0 ){
      if( pLoop->wsFlags & WHERE_IPK ){
        pIndex = 0;
        nKeyCol = 0;
        nColumn = 1;
      }else if( (pIndex = pLoop->u.btree.pIndex)==0 || pIndex->bUnordered ){
        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);
        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.
      */
      rev = revSet = 0;
      distinctColumns = 0;
      for(j=0; j<nColumn; j++){
        u8 bOnce = 1; /* True to run the ORDER BY search loop */

        assert( j>=pLoop->u.btree.nEq 
            || (pLoop->aLTerm[j]==0)==(j<pLoop->nSkip)
        );
        if( j<pLoop->u.btree.nEq && j>=pLoop->nSkip ){
          u16 eOp = pLoop->aLTerm[j]->eOperator;

          /* Skip over == and IS and ISNULL terms.  (Also skip IN terms when
          ** doing WHERE_ORDERBY_LIMIT processing). 
          ** doing WHERE_ORDERBY_LIMIT processing).  Except, IS and ISNULL
          ** terms imply that the index is not UNIQUE NOT NULL in which case
          ** the loop need to be marked as not order-distinct because it can
          ** have repeated NULL rows.
          **
          ** If the current term is a column of an ((?,?) IN (SELECT...)) 
          ** expression for which the SELECT returns more than one column,
          ** check that it is the only column used by this loop. Otherwise,
          ** if it is one of two or more, none of the columns can be
          ** considered to match an ORDER BY term.  */
          ** considered to match an ORDER BY term.
          */
          if( (eOp & eqOpMask)!=0 ){
            if( eOp & (WO_ISNULL|WO_IS) ){
            if( eOp & WO_ISNULL ){
              testcase( eOp & WO_ISNULL );
              testcase( eOp & WO_IS );
              testcase( isOrderDistinct );
              isOrderDistinct = 0;
            }
            continue;  
          }else if( ALWAYS(eOp & WO_IN) ){
            /* ALWAYS() justification: eOp is an equality operator due to the
            ** j<pLoop->u.btree.nEq constraint above.  Any equality other
3777
3778
3779
3780
3781
3782
3783
3784

3785
3786
3787
3788
3789
3790
3791
3792

3793
3794
3795
3796
3797
3798
3799
3800











3801
3802
3803
3804
3805
3806
3807
3808

3809
3810

3811
3812
3813

3814
3815
3816
3817
3818


3819
3820
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
4699
4700
4701
4702
4703
4704
4705

4706
4707
4708
4709
4710
4711
4712
4713

4714
4715







4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733

4734
4735
4736
4737
4738
4739

4740
4741
4742
4743


4744
4745
4746
4747
4748
4749
4750
4751
4752
4753

4754
4755
4756
4757
4758
4759
4760
4761
4762

4763
4764
4765
4766
4767
4768

4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786







-
+







-
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+







-
+


+


-
+



-
-
+
+







+
-
+
+







-
+
+
+
+
+

-
+



+
+
+
+
+
+
+







        }

        /* Get the column number in the table (iColumn) and sort order
        ** (revIdx) for the j-th column of the index.
        */
        if( pIndex ){
          iColumn = pIndex->aiColumn[j];
          revIdx = pIndex->aSortOrder[j];
          revIdx = pIndex->aSortOrder[j] & KEYINFO_ORDER_DESC;
          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 = sqlite3ExprSkipCollate(pOrderBy->a[i].pExpr);
          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) ){
            Expr *pIxExpr = pIndex->aColExpr->a[j].pExpr;
            if( sqlite3ExprCompareSkip(pOBExpr, pIxExpr, iCur) ){
              continue;
            }
          }
          if( iColumn!=XN_ROWID ){
            pColl = sqlite3ExprNNCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
            if( sqlite3StrICmp(pColl->zName, pIndex->azColl[j])!=0 ) continue;
          }
          if( wctrlFlags & WHERE_DISTINCTBY ){
          pLoop->u.btree.nIdxCol = j+1;
            pLoop->u.btree.nDistinctCol = j+1;
          }
          isMatch = 1;
          break;
        }
        if( isMatch && (wctrlFlags & WHERE_GROUPBY)==0 ){
          /* Make sure the sort order is compatible in an ORDER BY clause.
          ** Sort order is irrelevant for a GROUP BY clause. */
          if( revSet ){
            if( (rev ^ revIdx)!=pOrderBy->a[i].sortOrder ) isMatch = 0;
            if( (rev ^ revIdx) 
                           != (pOrderBy->a[i].fg.sortFlags&KEYINFO_ORDER_DESC)
            ){
              isMatch = 0;
            }
          }else{
            rev = revIdx ^ pOrderBy->a[i].sortOrder;
            rev = revIdx ^ (pOrderBy->a[i].fg.sortFlags & KEYINFO_ORDER_DESC);
            if( rev ) *pRevMask |= MASKBIT(iLoop);
            revSet = 1;
          }
        }
        if( isMatch && (pOrderBy->a[i].fg.sortFlags & KEYINFO_ORDER_BIGNULL) ){
          if( j==pLoop->u.btree.nEq ){
            pLoop->wsFlags |= WHERE_BIGNULL_SORT;
          }else{
            isMatch = 0;
          }
        }
        if( isMatch ){
          if( iColumn==XN_ROWID ){
            testcase( distinctColumns==0 );
            distinctColumns = 1;
          }
          obSat |= MASKBIT(i);
3874
3875
3876
3877
3878
3879
3880
3881

3882
3883
3884
3885
3886
3887
3888
4814
4815
4816
4817
4818
4819
4820

4821
4822
4823
4824
4825
4826
4827
4828







-
+







        }
      }
    }
  } /* End the loop over all WhereLoops from outer-most down to inner-most */
  if( obSat==obDone ) return (i8)nOrderBy;
  if( !isOrderDistinct ){
    for(i=nOrderBy-1; i>0; i--){
      Bitmask m = MASKBIT(i) - 1;
      Bitmask m = ALWAYS(i<BMS) ? MASKBIT(i) - 1 : 0;
      if( (obSat&m)==m ) return i;
    }
    return 0;
  }
  return -1;
}

3907
3908
3909
3910
3911
3912
3913
3914

3915
3916
3917
3918
3919
3920
3921
4847
4848
4849
4850
4851
4852
4853

4854
4855
4856
4857
4858
4859
4860
4861







-
+







**
** then
**
**   SELECT * FROM t1 GROUP BY x,y ORDER BY x,y;   -- IsSorted()==1
**   SELECT * FROM t1 GROUP BY y,x ORDER BY y,x;   -- IsSorted()==0
*/
int sqlite3WhereIsSorted(WhereInfo *pWInfo){
  assert( pWInfo->wctrlFlags & WHERE_GROUPBY );
  assert( pWInfo->wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY) );
  assert( pWInfo->wctrlFlags & WHERE_SORTBYGROUP );
  return pWInfo->sorted;
}

#ifdef WHERETRACE_ENABLED
/* For debugging use only: */
static const char *wherePathName(WherePath *pPath, int nLoop, WhereLoop *pLast){
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
3962
3963
















3964
3965
3966
3967
3968
3969
3970
4870
4871
4872
4873
4874
4875
4876




4877
4878
4879
4880
4881

4882
4883
4884

4885
4886
4887
4888
4889
4890

4891
4892







4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914



4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937







-
-
-
-
+
+
+
+

-
+


-
+





-
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








/*
** Return the cost of sorting nRow rows, assuming that the keys have 
** nOrderby columns and that the first nSorted columns are already in
** order.
*/
static LogEst whereSortingCost(
  WhereInfo *pWInfo,
  LogEst nRow,
  int nOrderBy,
  int nSorted
  WhereInfo *pWInfo, /* Query planning context */
  LogEst nRow,       /* Estimated number of rows to sort */
  int nOrderBy,      /* Number of ORDER BY clause terms */
  int nSorted        /* Number of initial ORDER BY terms naturally in order */
){
  /* TUNING: Estimated cost of a full external sort, where N is 
  /* Estimated cost of a full external sort, where N is 
  ** the number of rows to sort is:
  **
  **   cost = (3.0 * N * log(N)).
  **   cost = (K * N * log(N)).
  ** 
  ** Or, if the order-by clause has X terms but only the last Y 
  ** terms are out of order, then block-sorting will reduce the 
  ** sorting cost to:
  **
  **   cost = (3.0 * N * log(N)) * (Y/X)
  **   cost = (K * N * log(N)) * (Y/X)
  **
  ** The (Y/X) term is implemented using stack variable rScale
  ** below.  */
  LogEst rScale, rSortCost;
  assert( nOrderBy>0 && 66==sqlite3LogEst(100) );
  rScale = sqlite3LogEst((nOrderBy-nSorted)*100/nOrderBy) - 66;
  rSortCost = nRow + rScale + 16;

  ** The constant K is at least 2.0 but will be larger if there are a
  ** large number of columns to be sorted, as the sorting time is
  ** proportional to the amount of content to be sorted.  The algorithm
  ** does not currently distinguish between fat columns (BLOBs and TEXTs) 
  ** and skinny columns (INTs).  It just uses the number of columns as 
  ** an approximation for the row width.
  **
  ** And extra factor of 2.0 or 3.0 is added to the sorting cost if the sort
  ** is built using OP_IdxInsert and OP_Sort rather than with OP_SorterInsert.
  */
  LogEst rSortCost, nCol;
  assert( pWInfo->pSelect!=0 );
  assert( pWInfo->pSelect->pEList!=0 );
  /* TUNING: sorting cost proportional to the number of output columns: */
  nCol = sqlite3LogEst((pWInfo->pSelect->pEList->nExpr+59)/30);
  rSortCost = nRow + nCol;
  if( nSorted>0 ){
    /* Scale the result by (Y/X) */
    rSortCost += sqlite3LogEst((nOrderBy-nSorted)*100/nOrderBy) - 66;
  }

  /* Multiple by log(M) where M is the number of output rows.
  ** Use the LIMIT for M if it is smaller */
  if( (pWInfo->wctrlFlags & WHERE_USE_LIMIT)!=0 && pWInfo->iLimit<nRow ){
    nRow = pWInfo->iLimit;
  ** Use the LIMIT for M if it is smaller.  Or if this sort is for
  ** a DISTINCT operator, M will be the number of distinct output
  ** rows, so fudge it downwards a bit.
  */
  if( (pWInfo->wctrlFlags & WHERE_USE_LIMIT)!=0 ){
    rSortCost += 10;       /* TUNING: Extra 2.0x if using LIMIT */
    if( nSorted!=0 ){
      rSortCost += 6;      /* TUNING: Extra 1.5x if also using partial sort */
    }
    if( pWInfo->iLimit<nRow ){
      nRow = pWInfo->iLimit;
    }
  }else if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT) ){
    /* TUNING: In the sort for a DISTINCT operator, assume that the DISTINCT
    ** reduces the number of output rows by a factor of 2 */
    if( nRow>10 ){ nRow -= 10;  assert( 10==sqlite3LogEst(2) ); }
  }
  rSortCost += estLog(nRow);
  return rSortCost;
}

/*
** Given the list of WhereLoop objects at pWInfo->pLoops, this routine
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4945
4946
4947
4948
4949
4950
4951

4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969

4970
4971
4972
4973
4974
4975
4976







-


















-







** Return SQLITE_OK on success or SQLITE_NOMEM of a memory allocation
** error occurs.
*/
static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
  int mxChoice;             /* Maximum number of simultaneous paths tracked */
  int nLoop;                /* Number of terms in the join */
  Parse *pParse;            /* Parsing context */
  sqlite3 *db;              /* The database connection */
  int iLoop;                /* Loop counter over the terms of the join */
  int ii, jj;               /* Loop counters */
  int mxI = 0;              /* Index of next entry to replace */
  int nOrderBy;             /* Number of ORDER BY clause terms */
  LogEst mxCost = 0;        /* Maximum cost of a set of paths */
  LogEst mxUnsorted = 0;    /* Maximum unsorted cost of a set of path */
  int nTo, nFrom;           /* Number of valid entries in aTo[] and aFrom[] */
  WherePath *aFrom;         /* All nFrom paths at the previous level */
  WherePath *aTo;           /* The nTo best paths at the current level */
  WherePath *pFrom;         /* An element of aFrom[] that we are working on */
  WherePath *pTo;           /* An element of aTo[] that we are working on */
  WhereLoop *pWLoop;        /* One of the WhereLoop objects */
  WhereLoop **pX;           /* Used to divy up the pSpace memory */
  LogEst *aSortCost = 0;    /* Sorting and partial sorting costs */
  char *pSpace;             /* Temporary memory used by this routine */
  int nSpace;               /* Bytes of space allocated at pSpace */

  pParse = pWInfo->pParse;
  db = pParse->db;
  nLoop = pWInfo->nLevel;
  /* TUNING: For simple queries, only the best path is tracked.
  ** For 2-way joins, the 5 best paths are followed.
  ** For joins of 3 or more tables, track the 10 best paths */
  mxChoice = (nLoop<=1) ? 1 : (nLoop==2 ? 5 : 10);
  assert( nLoop<=pWInfo->pTabList->nSrc );
  WHERETRACE(0x002, ("---- begin solver.  (nRowEst=%d)\n", nRowEst));
4020
4021
4022
4023
4024
4025
4026
4027

4028
4029
4030
4031
4032
4033
4034
4985
4986
4987
4988
4989
4990
4991

4992
4993
4994
4995
4996
4997
4998
4999







-
+







  }else{
    nOrderBy = pWInfo->pOrderBy->nExpr;
  }

  /* Allocate and initialize space for aTo, aFrom and aSortCost[] */
  nSpace = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2;
  nSpace += sizeof(LogEst) * nOrderBy;
  pSpace = sqlite3DbMallocRawNN(db, nSpace);
  pSpace = sqlite3StackAllocRawNN(pParse->db, nSpace);
  if( pSpace==0 ) return SQLITE_NOMEM_BKPT;
  aTo = (WherePath*)pSpace;
  aFrom = aTo+mxChoice;
  memset(aFrom, 0, sizeof(aFrom[0]));
  pX = (WhereLoop**)(aFrom+mxChoice);
  for(ii=mxChoice*2, pFrom=aTo; ii>0; ii--, pFrom++, pX += nLoop){
    pFrom->aLoop = pX;
4070
4071
4072
4073
4074
4075
4076
4077

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
4107
4108
4109
4110
4111

4112
4113
4114
4115

4116
4117
4118
4119
4120
4121
4122
4123
4124







4125
4126
4127
4128
4129
4130
4131
5035
5036
5037
5038
5039
5040
5041

5042
5043

5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077

5078
5079
5080
5081

5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105







-
+

-
+


















+

+












-
+



-
+









+
+
+
+
+
+
+







  for(iLoop=0; iLoop<nLoop; iLoop++){
    nTo = 0;
    for(ii=0, pFrom=aFrom; ii<nFrom; ii++, pFrom++){
      for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){
        LogEst nOut;                      /* Rows visited by (pFrom+pWLoop) */
        LogEst rCost;                     /* Cost of path (pFrom+pWLoop) */
        LogEst rUnsorted;                 /* Unsorted cost of (pFrom+pWLoop) */
        i8 isOrdered = pFrom->isOrdered;  /* isOrdered for (pFrom+pWLoop) */
        i8 isOrdered;                     /* isOrdered for (pFrom+pWLoop) */
        Bitmask maskNew;                  /* Mask of src visited by (..) */
        Bitmask revMask = 0;              /* Mask of rev-order loops for (..) */
        Bitmask revMask;                  /* Mask of rev-order loops for (..) */

        if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue;
        if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue;
        if( (pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 && pFrom->nRow<3 ){
          /* Do not use an automatic index if the this loop is expected
          ** to run less than 1.25 times.  It is tempting to also exclude
          ** automatic index usage on an outer loop, but sometimes an automatic
          ** index is useful in the outer loop of a correlated subquery. */
          assert( 10==sqlite3LogEst(2) );
          continue;
        }

        /* At this point, pWLoop is a candidate to be the next loop. 
        ** Compute its cost */
        rUnsorted = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
        rUnsorted = sqlite3LogEstAdd(rUnsorted, pFrom->rUnsorted);
        nOut = pFrom->nRow + pWLoop->nOut;
        maskNew = pFrom->maskLoop | pWLoop->maskSelf;
        isOrdered = pFrom->isOrdered;
        if( isOrdered<0 ){
          revMask = 0;
          isOrdered = wherePathSatisfiesOrderBy(pWInfo,
                       pWInfo->pOrderBy, pFrom, pWInfo->wctrlFlags,
                       iLoop, pWLoop, &revMask);
        }else{
          revMask = pFrom->revLoop;
        }
        if( isOrdered>=0 && isOrdered<nOrderBy ){
          if( aSortCost[isOrdered]==0 ){
            aSortCost[isOrdered] = whereSortingCost(
                pWInfo, nRowEst, nOrderBy, isOrdered
            );
          }
          /* TUNING:  Add a small extra penalty (5) to sorting as an
          /* TUNING:  Add a small extra penalty (3) to sorting as an
          ** extra encouragment to the query planner to select a plan
          ** where the rows emerge in the correct order without any sorting
          ** required. */
          rCost = sqlite3LogEstAdd(rUnsorted, aSortCost[isOrdered]) + 5;
          rCost = sqlite3LogEstAdd(rUnsorted, aSortCost[isOrdered]) + 3;

          WHERETRACE(0x002,
              ("---- sort cost=%-3d (%d/%d) increases cost %3d to %-3d\n",
               aSortCost[isOrdered], (nOrderBy-isOrdered), nOrderBy, 
               rUnsorted, rCost));
        }else{
          rCost = rUnsorted;
          rUnsorted -= 2;  /* TUNING:  Slight bias in favor of no-sort plans */
        }

        /* TUNING:  A full-scan of a VIEW or subquery in the outer loop
        ** is not so bad. */
        if( iLoop==0 && (pWLoop->wsFlags & WHERE_VIEWSCAN)!=0 ){
          rCost += -10;
          nOut += -30;
        }

        /* Check to see if pWLoop should be added to the set of
        ** mxChoice best-so-far paths.
        **
        ** First look for an existing path among best-so-far paths
        ** that covers the same set of loops and has the same isOrdered
        ** setting as the current path candidate.
4269
4270
4271
4272
4273
4274
4275
4276

4277
4278
4279
4280
4281
4282
4283
5243
5244
5245
5246
5247
5248
5249

5250
5251
5252
5253
5254
5255
5256
5257







-
+







    aTo = aFrom;
    aFrom = pFrom;
    nFrom = nTo;
  }

  if( nFrom==0 ){
    sqlite3ErrorMsg(pParse, "no query solution");
    sqlite3DbFreeNN(db, pSpace);
    sqlite3StackFreeNN(pParse->db, pSpace);
    return SQLITE_ERROR;
  }
  
  /* Find the lowest cost path.  pFrom will be left pointing to that path */
  pFrom = aFrom;
  for(ii=1; ii<nFrom; ii++){
    if( pFrom->rCost>aFrom[ii].rCost ) pFrom = &aFrom[ii];
4300
4301
4302
4303
4304
4305
4306

4307
4308
4309
4310
4311
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
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286

5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317







+





-



















+
+
+
+
+







                 WHERE_DISTINCTBY, nLoop-1, pFrom->aLoop[nLoop-1], &notUsed);
    if( rc==pWInfo->pResultSet->nExpr ){
      pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
    }
  }
  pWInfo->bOrderedInnerLoop = 0;
  if( pWInfo->pOrderBy ){
    pWInfo->nOBSat = pFrom->isOrdered;
    if( pWInfo->wctrlFlags & WHERE_DISTINCTBY ){
      if( pFrom->isOrdered==pWInfo->pOrderBy->nExpr ){
        pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
      }
    }else{
      pWInfo->nOBSat = pFrom->isOrdered;
      pWInfo->revMask = pFrom->revLoop;
      if( pWInfo->nOBSat<=0 ){
        pWInfo->nOBSat = 0;
        if( nLoop>0 ){
          u32 wsFlags = pFrom->aLoop[nLoop-1]->wsFlags;
          if( (wsFlags & WHERE_ONEROW)==0 
           && (wsFlags&(WHERE_IPK|WHERE_COLUMN_IN))!=(WHERE_IPK|WHERE_COLUMN_IN)
          ){
            Bitmask m = 0;
            int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom,
                      WHERE_ORDERBY_LIMIT, nLoop-1, pFrom->aLoop[nLoop-1], &m);
            testcase( wsFlags & WHERE_IPK );
            testcase( wsFlags & WHERE_COLUMN_IN );
            if( rc==pWInfo->pOrderBy->nExpr ){
              pWInfo->bOrderedInnerLoop = 1;
              pWInfo->revMask = m;
            }
          }
        }
      }else if( nLoop
            && pWInfo->nOBSat==1
            && (pWInfo->wctrlFlags & (WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX))!=0
            ){
        pWInfo->bOrderedInnerLoop = 1;
      }
    }
    if( (pWInfo->wctrlFlags & WHERE_SORTBYGROUP)
        && pWInfo->nOBSat==pWInfo->pOrderBy->nExpr && nLoop>0
    ){
      Bitmask revMask = 0;
      int nOrder = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, 
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

4371
4372
4373
4374
4375
4376
4377

4378
4379
4380
4381
4382
4383
4384
4385





4386
4387
4388
4389
4390
4391


4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410


4411
4412
4413
4414
4415
4416
4417
5325
5326
5327
5328
5329
5330
5331

5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348

5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364

5365
5366
5367
5368
5369
5370
5371
5372
5373
5374

5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394

5395
5396
5397
5398
5399
5400
5401
5402
5403







-
+
















-
+







+







-
+
+
+
+
+





-
+
+


















-
+
+







    }
  }


  pWInfo->nRowOut = pFrom->nRow;

  /* Free temporary memory and return success */
  sqlite3DbFreeNN(db, pSpace);
  sqlite3StackFreeNN(pParse->db, pSpace);
  return SQLITE_OK;
}

/*
** Most queries use only a single table (they are not joins) and have
** simple == constraints against indexed fields.  This routine attempts
** to plan those simple cases using much less ceremony than the
** general-purpose query planner, and thereby yield faster sqlite3_prepare()
** times for the common case.
**
** Return non-zero on success, if this query can be handled by this
** no-frills query planner.  Return zero if this query needs the 
** general-purpose query planner.
*/
static int whereShortCut(WhereLoopBuilder *pBuilder){
  WhereInfo *pWInfo;
  struct SrcList_item *pItem;
  SrcItem *pItem;
  WhereClause *pWC;
  WhereTerm *pTerm;
  WhereLoop *pLoop;
  int iCur;
  int j;
  Table *pTab;
  Index *pIdx;
  WhereScan scan;

  pWInfo = pBuilder->pWInfo;
  if( pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE ) return 0;
  assert( pWInfo->pTabList->nSrc>=1 );
  pItem = pWInfo->pTabList->a;
  pTab = pItem->pTab;
  if( IsVirtual(pTab) ) return 0;
  if( pItem->fg.isIndexedBy ) return 0;
  if( pItem->fg.isIndexedBy || pItem->fg.notIndexed ){
    testcase( pItem->fg.isIndexedBy );
    testcase( pItem->fg.notIndexed );
    return 0;
  }
  iCur = pItem->iCursor;
  pWC = &pWInfo->sWC;
  pLoop = pBuilder->pNew;
  pLoop->wsFlags = 0;
  pLoop->nSkip = 0;
  pTerm = sqlite3WhereFindTerm(pWC, iCur, -1, 0, WO_EQ|WO_IS, 0);
  pTerm = whereScanInit(&scan, pWC, iCur, -1, WO_EQ|WO_IS, 0);
  while( pTerm && pTerm->prereqRight ) pTerm = whereScanNext(&scan);
  if( pTerm ){
    testcase( pTerm->eOperator & WO_IS );
    pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_IPK|WHERE_ONEROW;
    pLoop->aLTerm[0] = pTerm;
    pLoop->nLTerm = 1;
    pLoop->u.btree.nEq = 1;
    /* TUNING: Cost of a rowid lookup is 10 */
    pLoop->rRun = 33;  /* 33==sqlite3LogEst(10) */
  }else{
    for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
      int opMask;
      assert( pLoop->aLTermSpace==pLoop->aLTerm );
      if( !IsUniqueIndex(pIdx)
       || pIdx->pPartIdxWhere!=0 
       || pIdx->nKeyCol>ArraySize(pLoop->aLTermSpace) 
      ) continue;
      opMask = pIdx->uniqNotNull ? (WO_EQ|WO_IS) : WO_EQ;
      for(j=0; j<pIdx->nKeyCol; j++){
        pTerm = sqlite3WhereFindTerm(pWC, iCur, j, 0, opMask, pIdx);
        pTerm = whereScanInit(&scan, pWC, iCur, j, opMask, pIdx);
        while( pTerm && pTerm->prereqRight ) pTerm = whereScanNext(&scan);
        if( pTerm==0 ) break;
        testcase( pTerm->eOperator & WO_IS );
        pLoop->aLTerm[j] = pTerm;
      }
      if( j!=pIdx->nKeyCol ) continue;
      pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_ONEROW|WHERE_INDEXED;
      if( pIdx->isCovering || (pItem->colUsed & pIdx->colNotIdxed)==0 ){
4432
4433
4434
4435
4436
4437
4438

4439
4440





4441
4442
4443
4444
4445
4446
4447
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439







+


+
+
+
+
+







    pLoop->maskSelf = 1; /* sqlite3WhereGetMask(&pWInfo->sMaskSet, iCur); */
    pWInfo->a[0].iTabCur = iCur;
    pWInfo->nRowOut = 1;
    if( pWInfo->pOrderBy ) pWInfo->nOBSat =  pWInfo->pOrderBy->nExpr;
    if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){
      pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
    }
    if( scan.iEquiv>1 ) pLoop->wsFlags |= WHERE_TRANSCONS;
#ifdef SQLITE_DEBUG
    pLoop->cId = '0';
#endif
#ifdef WHERETRACE_ENABLED
    if( sqlite3WhereTrace & 0x02 ){
      sqlite3DebugPrintf("whereShortCut() used to compute solution\n");
    }
#endif
    return 1;
  }
  return 0;
}

/*
4465
4466
4467
4468
4469
4470
4471



















































































































































































































































4472
4473
4474
4475
4476
4477
4478
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  memset(&w, 0, sizeof(w));
  w.eCode = 1;
  w.xExprCallback = exprNodeIsDeterministic;
  w.xSelectCallback = sqlite3SelectWalkFail;
  sqlite3WalkExpr(&w, p);
  return w.eCode;
}

  
#ifdef WHERETRACE_ENABLED
/*
** Display all WhereLoops in pWInfo
*/
static void showAllWhereLoops(WhereInfo *pWInfo, WhereClause *pWC){
  if( sqlite3WhereTrace ){    /* Display all of the WhereLoop objects */
    WhereLoop *p;
    int i;
    static const char zLabel[] = "0123456789abcdefghijklmnopqrstuvwyxz"
                                           "ABCDEFGHIJKLMNOPQRSTUVWYXZ";
    for(p=pWInfo->pLoops, i=0; p; p=p->pNextLoop, i++){
      p->cId = zLabel[i%(sizeof(zLabel)-1)];
      sqlite3WhereLoopPrint(p, pWC);
    }
  }
}
# define WHERETRACE_ALL_LOOPS(W,C) showAllWhereLoops(W,C)
#else
# define WHERETRACE_ALL_LOOPS(W,C)
#endif

/* Attempt to omit tables from a join that do not affect the result.
** For a table to not affect the result, the following must be true:
**
**   1) The query must not be an aggregate.
**   2) The table must be the RHS of a LEFT JOIN.
**   3) Either the query must be DISTINCT, or else the ON or USING clause
**      must contain a constraint that limits the scan of the table to 
**      at most a single row.
**   4) The table must not be referenced by any part of the query apart
**      from its own USING or ON clause.
**
** For example, given:
**
**     CREATE TABLE t1(ipk INTEGER PRIMARY KEY, v1);
**     CREATE TABLE t2(ipk INTEGER PRIMARY KEY, v2);
**     CREATE TABLE t3(ipk INTEGER PRIMARY KEY, v3);
**
** then table t2 can be omitted from the following:
**
**     SELECT v1, v3 FROM t1 
**       LEFT JOIN t2 ON (t1.ipk=t2.ipk)
**       LEFT JOIN t3 ON (t1.ipk=t3.ipk)
**
** or from:
**
**     SELECT DISTINCT v1, v3 FROM t1 
**       LEFT JOIN t2
**       LEFT JOIN t3 ON (t1.ipk=t3.ipk)
*/
static SQLITE_NOINLINE Bitmask whereOmitNoopJoin(
  WhereInfo *pWInfo,
  Bitmask notReady
){
  int i;
  Bitmask tabUsed;

  /* Preconditions checked by the caller */
  assert( pWInfo->nLevel>=2 );
  assert( OptimizationEnabled(pWInfo->pParse->db, SQLITE_OmitNoopJoin) );

  /* These two preconditions checked by the caller combine to guarantee
  ** condition (1) of the header comment */
  assert( pWInfo->pResultSet!=0 );
  assert( 0==(pWInfo->wctrlFlags & WHERE_AGG_DISTINCT) );

  tabUsed = sqlite3WhereExprListUsage(&pWInfo->sMaskSet, pWInfo->pResultSet);
  if( pWInfo->pOrderBy ){
    tabUsed |= sqlite3WhereExprListUsage(&pWInfo->sMaskSet, pWInfo->pOrderBy);
  }
  for(i=pWInfo->nLevel-1; i>=1; i--){
    WhereTerm *pTerm, *pEnd;
    SrcItem *pItem;
    WhereLoop *pLoop;
    pLoop = pWInfo->a[i].pWLoop;
    pItem = &pWInfo->pTabList->a[pLoop->iTab];
    if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))!=JT_LEFT ) continue;
    if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT)==0
     && (pLoop->wsFlags & WHERE_ONEROW)==0
    ){
      continue;
    }
    if( (tabUsed & pLoop->maskSelf)!=0 ) continue;
    pEnd = pWInfo->sWC.a + pWInfo->sWC.nTerm;
    for(pTerm=pWInfo->sWC.a; pTerm<pEnd; pTerm++){
      if( (pTerm->prereqAll & pLoop->maskSelf)!=0 ){
        if( !ExprHasProperty(pTerm->pExpr, EP_OuterON)
         || pTerm->pExpr->w.iJoin!=pItem->iCursor
        ){
          break;
        }
      }
    }
    if( pTerm<pEnd ) continue;
    WHERETRACE(0xffffffff, ("-> drop loop %c not used\n", pLoop->cId));
    notReady &= ~pLoop->maskSelf;
    for(pTerm=pWInfo->sWC.a; pTerm<pEnd; pTerm++){
      if( (pTerm->prereqAll & pLoop->maskSelf)!=0 ){
        pTerm->wtFlags |= TERM_CODED;
      }
    }
    if( i!=pWInfo->nLevel-1 ){
      int nByte = (pWInfo->nLevel-1-i) * sizeof(WhereLevel);
      memmove(&pWInfo->a[i], &pWInfo->a[i+1], nByte);
    }
    pWInfo->nLevel--;
    assert( pWInfo->nLevel>0 );
  }
  return notReady;
}

/*
** Check to see if there are any SEARCH loops that might benefit from
** using a Bloom filter.  Consider a Bloom filter if:
**
**   (1)  The SEARCH happens more than N times where N is the number
**        of rows in the table that is being considered for the Bloom
**        filter.
**   (2)  Some searches are expected to find zero rows.  (This is determined
**        by the WHERE_SELFCULL flag on the term.)
**   (3)  Bloom-filter processing is not disabled.  (Checked by the
**        caller.)
**   (4)  The size of the table being searched is known by ANALYZE.
**
** This block of code merely checks to see if a Bloom filter would be
** appropriate, and if so sets the WHERE_BLOOMFILTER flag on the
** WhereLoop.  The implementation of the Bloom filter comes further
** down where the code for each WhereLoop is generated.
*/
static SQLITE_NOINLINE void whereCheckIfBloomFilterIsUseful(
  const WhereInfo *pWInfo
){
  int i;
  LogEst nSearch;

  assert( pWInfo->nLevel>=2 );
  assert( OptimizationEnabled(pWInfo->pParse->db, SQLITE_BloomFilter) );
  nSearch = pWInfo->a[0].pWLoop->nOut;
  for(i=1; i<pWInfo->nLevel; i++){
    WhereLoop *pLoop = pWInfo->a[i].pWLoop;
    const unsigned int reqFlags = (WHERE_SELFCULL|WHERE_COLUMN_EQ);
    if( (pLoop->wsFlags & reqFlags)==reqFlags
     /* vvvvvv--- Always the case if WHERE_COLUMN_EQ is defined */
     && ALWAYS((pLoop->wsFlags & (WHERE_IPK|WHERE_INDEXED))!=0)
    ){
      SrcItem *pItem = &pWInfo->pTabList->a[pLoop->iTab];
      Table *pTab = pItem->pTab;
      pTab->tabFlags |= TF_StatsUsed;
      if( nSearch > pTab->nRowLogEst
       && (pTab->tabFlags & TF_HasStat1)!=0
      ){
        testcase( pItem->fg.jointype & JT_LEFT );
        pLoop->wsFlags |= WHERE_BLOOMFILTER;
        pLoop->wsFlags &= ~WHERE_IDX_ONLY;
        WHERETRACE(0xffffffff, (
           "-> use Bloom-filter on loop %c because there are ~%.1e "
           "lookups into %s which has only ~%.1e rows\n",
           pLoop->cId, (double)sqlite3LogEstToInt(nSearch), pTab->zName,
           (double)sqlite3LogEstToInt(pTab->nRowLogEst)));
      }
    }
    nSearch += pLoop->nOut;
  }
}

/*
** This is an sqlite3ParserAddCleanup() callback that is invoked to
** free the Parse->pIdxEpr list when the Parse object is destroyed.
*/
static void whereIndexedExprCleanup(sqlite3 *db, void *pObject){
  Parse *pParse = (Parse*)pObject;
  while( pParse->pIdxEpr!=0 ){
    IndexedExpr *p = pParse->pIdxEpr;
    pParse->pIdxEpr = p->pIENext;
    sqlite3ExprDelete(db, p->pExpr);
    sqlite3DbFreeNN(db, p);
  }
}

/*
** The index pIdx is used by a query and contains one or more expressions.
** In other words pIdx is an index on an expression.  iIdxCur is the cursor
** number for the index and iDataCur is the cursor number for the corresponding
** table.
**
** This routine adds IndexedExpr entries to the Parse->pIdxEpr field for
** each of the expressions in the index so that the expression code generator
** will know to replace occurrences of the indexed expression with
** references to the corresponding column of the index.
*/
static SQLITE_NOINLINE void whereAddIndexedExpr(
  Parse *pParse,     /* Add IndexedExpr entries to pParse->pIdxEpr */
  Index *pIdx,       /* The index-on-expression that contains the expressions */
  int iIdxCur,       /* Cursor number for pIdx */
  SrcItem *pTabItem  /* The FROM clause entry for the table */
){
  int i;
  IndexedExpr *p;
  Table *pTab;
  assert( pIdx->bHasExpr );
  pTab = pIdx->pTable;
  for(i=0; i<pIdx->nColumn; i++){
    Expr *pExpr;
    int j = pIdx->aiColumn[i];
    int bMaybeNullRow;
    if( j==XN_EXPR ){
      pExpr = pIdx->aColExpr->a[i].pExpr;
      testcase( pTabItem->fg.jointype & JT_LEFT );
      testcase( pTabItem->fg.jointype & JT_RIGHT );
      testcase( pTabItem->fg.jointype & JT_LTORJ );
      bMaybeNullRow = (pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0;
    }else if( j>=0 && (pTab->aCol[j].colFlags & COLFLAG_VIRTUAL)!=0 ){
      pExpr = sqlite3ColumnExpr(pTab, &pTab->aCol[j]);
      bMaybeNullRow = 0;
    }else{
      continue;
    }
    if( sqlite3ExprIsConstant(pExpr) ) continue;
    p = sqlite3DbMallocRaw(pParse->db,  sizeof(IndexedExpr));
    if( p==0 ) break;
    p->pIENext = pParse->pIdxEpr;
#ifdef WHERETRACE_ENABLED
    if( sqlite3WhereTrace & 0x200 ){
      sqlite3DebugPrintf("New pParse->pIdxEpr term {%d,%d}\n", iIdxCur, i);
      if( sqlite3WhereTrace & 0x5000 ) sqlite3ShowExpr(pExpr);
    }
#endif
    p->pExpr = sqlite3ExprDup(pParse->db, pExpr, 0);
    p->iDataCur = pTabItem->iCursor;
    p->iIdxCur = iIdxCur;
    p->iIdxCol = i;
    p->bMaybeNullRow = bMaybeNullRow;
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
    p->zIdxName = pIdx->zName;
#endif
    pParse->pIdxEpr = p;
    if( p->pIENext==0 ){
      sqlite3ParserAddCleanup(pParse, whereIndexedExprCleanup, pParse);
    }
  }
}

/*
** Generate the beginning of the loop used for WHERE clause processing.
** The return value is a pointer to an opaque structure that contains
** information needed to terminate the loop.  Later, the calling routine
** should invoke sqlite3WhereEnd() with the return value of this function
** in order to complete the WHERE clause processing.
4560
4561
4562
4563
4564
4565
4566

4567
4568
4569
4570
4571
4572
4573
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809







+







*/
WhereInfo *sqlite3WhereBegin(
  Parse *pParse,          /* The parser context */
  SrcList *pTabList,      /* FROM clause: A list of all tables to be scanned */
  Expr *pWhere,           /* The WHERE clause */
  ExprList *pOrderBy,     /* An ORDER BY (or GROUP BY) clause, or NULL */
  ExprList *pResultSet,   /* Query result set.  Req'd for DISTINCT */
  Select *pSelect,        /* The entire SELECT statement */
  u16 wctrlFlags,         /* The WHERE_* flags defined in sqliteInt.h */
  int iAuxArg             /* If WHERE_OR_SUBCLAUSE is set, index cursor number
                          ** If WHERE_USE_LIMIT, then the limit amount */
){
  int nByteWInfo;            /* Num. bytes allocated for WhereInfo struct */
  int nTabList;              /* Number of elements in pTabList */
  WhereInfo *pWInfo;         /* Will become the return value of this function */
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
5830
5831
5832
5833
5834
5835
5836







5837
5838
5839
5840
5841
5842
5843







-
-
-
-
-
-
-







  /* Variable initialization */
  db = pParse->db;
  memset(&sWLB, 0, sizeof(sWLB));

  /* An ORDER/GROUP BY clause of more than 63 terms cannot be optimized */
  testcase( pOrderBy && pOrderBy->nExpr==BMS-1 );
  if( pOrderBy && pOrderBy->nExpr>=BMS ) pOrderBy = 0;
  sWLB.pOrderBy = pOrderBy;

  /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via
  ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */
  if( OptimizationDisabled(db, SQLITE_DistinctOpt) ){
    wctrlFlags &= ~WHERE_WANT_DISTINCT;
  }

  /* The number of tables in the FROM clause is limited by the number of
  ** bits in a Bitmask 
  */
  testcase( pTabList->nSrc==BMS );
  if( pTabList->nSrc>BMS ){
    sqlite3ErrorMsg(pParse, "at most %d tables in a join", BMS);
4625
4626
4627
4628
4629
4630
4631
4632

4633
4634
4635
4636
4637
4638
4639
4640
4641

4642

4643
4644
4645
4646

4647
4648
4649

4650
4651
4652
4653
4654




4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675



4676
4677
4678
4679
4680
4681
4682
5854
5855
5856
5857
5858
5859
5860

5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876

5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902

5903
5904
5905
5906
5907
5908
5909

5910
5911
5912
5913
5914
5915
5916
5917
5918
5919







-
+









+

+



-
+



+





+
+
+
+












-







-
+
+
+







  /* Allocate and initialize the WhereInfo structure that will become the
  ** return value. A single allocation is used to store the WhereInfo
  ** struct, the contents of WhereInfo.a[], the WhereClause structure
  ** and the WhereMaskSet structure. Since WhereClause contains an 8-byte
  ** field (type Bitmask) it must be aligned on an 8-byte boundary on
  ** some architectures. Hence the ROUND8() below.
  */
  nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel));
  nByteWInfo = ROUND8P(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel));
  pWInfo = sqlite3DbMallocRawNN(db, nByteWInfo + sizeof(WhereLoop));
  if( db->mallocFailed ){
    sqlite3DbFree(db, pWInfo);
    pWInfo = 0;
    goto whereBeginError;
  }
  pWInfo->pParse = pParse;
  pWInfo->pTabList = pTabList;
  pWInfo->pOrderBy = pOrderBy;
#if WHERETRACE_ENABLED
  pWInfo->pWhere = pWhere;
#endif
  pWInfo->pResultSet = pResultSet;
  pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1;
  pWInfo->nLevel = nTabList;
  pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(v);
  pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(pParse);
  pWInfo->wctrlFlags = wctrlFlags;
  pWInfo->iLimit = iAuxArg;
  pWInfo->savedNQueryLoop = pParse->nQueryLoop;
  pWInfo->pSelect = pSelect;
  memset(&pWInfo->nOBSat, 0, 
         offsetof(WhereInfo,sWC) - offsetof(WhereInfo,nOBSat));
  memset(&pWInfo->a[0], 0, sizeof(WhereLoop)+nTabList*sizeof(WhereLevel));
  assert( pWInfo->eOnePass==ONEPASS_OFF );  /* ONEPASS defaults to OFF */
  pMaskSet = &pWInfo->sMaskSet;
  pMaskSet->n = 0;
  pMaskSet->ix[0] = -99; /* Initialize ix[0] to a value that can never be
                         ** a valid cursor number, to avoid an initial
                         ** test for pMaskSet->n==0 in sqlite3WhereGetMask() */
  sWLB.pWInfo = pWInfo;
  sWLB.pWC = &pWInfo->sWC;
  sWLB.pNew = (WhereLoop*)(((char*)pWInfo)+nByteWInfo);
  assert( EIGHT_BYTE_ALIGNMENT(sWLB.pNew) );
  whereLoopInit(sWLB.pNew);
#ifdef SQLITE_DEBUG
  sWLB.pNew->cId = '*';
#endif

  /* Split the WHERE clause into separate subexpressions where each
  ** subexpression is separated by an AND operator.
  */
  initMaskSet(pMaskSet);
  sqlite3WhereClauseInit(&pWInfo->sWC, pWInfo);
  sqlite3WhereSplit(&pWInfo->sWC, pWhere, TK_AND);
    
  /* Special case: No FROM clause
  */
  if( nTabList==0 ){
    if( pOrderBy ) pWInfo->nOBSat = pOrderBy->nExpr;
    if( wctrlFlags & WHERE_WANT_DISTINCT ){
    if( (wctrlFlags & WHERE_WANT_DISTINCT)!=0
     && OptimizationEnabled(db, SQLITE_DistinctOpt)
    ){
      pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
    }
    ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW"));
  }else{
    /* Assign a bit from the bitmask to every term in the FROM clause.
    **
    ** The N-th term of the FROM clause is assigned a bitmask of 1<<N.
4706
4707
4708
4709
4710
4711
4712



4713

4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726

4727
4728
4729
4730
4731
4732
4733
4734
4735





4736

4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748

4749
4750
4751
4752
4753









4754
4755
4756





4757
4758
4759
4760
4761
4762
4763
4764










4765
4766




4767
4768
4769
4770

4771
4772

4773


4774
4775

4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787

4788
4789

4790
4791
4792
4793
4794
4795
4796
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952

5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965

5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980

5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992

5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007



6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018


6019
6020
6021
6022
6023
6024
6025
6026
6027
6028


6029
6030
6031
6032




6033


6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051

6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062







+
+
+
-
+












-
+









+
+
+
+
+
-
+











-
+





+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+






-
-
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
-
-
-
-
+
-
-
+

+
+


+











-
+


+







      }
    }
  #endif
  }
  
  /* Analyze all of the subexpressions. */
  sqlite3WhereExprAnalyze(pTabList, &pWInfo->sWC);
  if( pSelect && pSelect->pLimit ){
    sqlite3WhereAddLimit(&pWInfo->sWC, pSelect);
  }
  if( db->mallocFailed ) goto whereBeginError;
  if( pParse->nErr ) goto whereBeginError;

  /* Special case: WHERE terms that do not refer to any tables in the join
  ** (constant expressions). Evaluate each such term, and jump over all the
  ** generated code if the result is not true.  
  **
  ** Do not do this if the expression contains non-deterministic functions
  ** that are not within a sub-select. This is not strictly required, but
  ** preserves SQLite's legacy behaviour in the following two cases:
  **
  **   FROM ... WHERE random()>0;           -- eval random() once per row
  **   FROM ... WHERE (SELECT random())>0;  -- eval random() once overall
  */
  for(ii=0; ii<sWLB.pWC->nTerm; ii++){
  for(ii=0; ii<sWLB.pWC->nBase; ii++){
    WhereTerm *pT = &sWLB.pWC->a[ii];
    if( pT->wtFlags & TERM_VIRTUAL ) continue;
    if( pT->prereqAll==0 && (nTabList==0 || exprIsDeterministic(pT->pExpr)) ){
      sqlite3ExprIfFalse(pParse, pT->pExpr, pWInfo->iBreak, SQLITE_JUMPIFNULL);
      pT->wtFlags |= TERM_CODED;
    }
  }

  if( wctrlFlags & WHERE_WANT_DISTINCT ){
    if( OptimizationDisabled(db, SQLITE_DistinctOpt) ){
      /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via
      ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */
      wctrlFlags &= ~WHERE_WANT_DISTINCT;
      pWInfo->wctrlFlags &= ~WHERE_WANT_DISTINCT;
    if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){
    }else if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){
      /* The DISTINCT marking is pointless.  Ignore it. */
      pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
    }else if( pOrderBy==0 ){
      /* Try to ORDER BY the result set to make distinct processing easier */
      pWInfo->wctrlFlags |= WHERE_DISTINCTBY;
      pWInfo->pOrderBy = pResultSet;
    }
  }

  /* Construct the WhereLoop objects */
#if defined(WHERETRACE_ENABLED)
  if( sqlite3WhereTrace & 0xffff ){
  if( sqlite3WhereTrace & 0xffffffff ){
    sqlite3DebugPrintf("*** Optimizer Start *** (wctrlFlags: 0x%x",wctrlFlags);
    if( wctrlFlags & WHERE_USE_LIMIT ){
      sqlite3DebugPrintf(", limit: %d", iAuxArg);
    }
    sqlite3DebugPrintf(")\n");
    if( sqlite3WhereTrace & 0x8000 ){
      Select sSelect;
      memset(&sSelect, 0, sizeof(sSelect));
      sSelect.selFlags = SF_WhereBegin;
      sSelect.pSrc = pTabList;
      sSelect.pWhere = pWhere;
      sSelect.pOrderBy = pOrderBy;
      sSelect.pEList = pResultSet;
      sqlite3TreeViewSelect(0, &sSelect, 0);
  }
  if( sqlite3WhereTrace & 0x100 ){ /* Display all terms of the WHERE clause */
    sqlite3WhereClausePrint(sWLB.pWC);
    }
    if( sqlite3WhereTrace & 0x4000 ){ /* Display all WHERE clause terms */
      sqlite3DebugPrintf("---- WHERE clause at start of analysis:\n");
      sqlite3WhereClausePrint(sWLB.pWC);
    }
  }
#endif

  if( nTabList!=1 || whereShortCut(&sWLB)==0 ){
    rc = whereLoopAddAll(&sWLB);
    if( rc ) goto whereBeginError;
  
#ifdef WHERETRACE_ENABLED

#ifdef SQLITE_ENABLE_STAT4
    /* If one or more WhereTerm.truthProb values were used in estimating
    ** loop parameters, but then those truthProb values were subsequently
    ** changed based on STAT4 information while computing subsequent loops,
    ** then we need to rerun the whole loop building process so that all
    ** loops will be built using the revised truthProb values. */
    if( sWLB.bldFlags2 & SQLITE_BLDF2_2NDPASS ){
      WHERETRACE_ALL_LOOPS(pWInfo, sWLB.pWC);
      WHERETRACE(0xffffffff, 
    if( sqlite3WhereTrace ){    /* Display all of the WhereLoop objects */
      WhereLoop *p;
           ("**** Redo all loop computations due to"
            " TERM_HIGHTRUTH changes ****\n"));
      while( pWInfo->pLoops ){
        WhereLoop *p = pWInfo->pLoops;
      int i;
      static const char zLabel[] = "0123456789abcdefghijklmnopqrstuvwyxz"
                                             "ABCDEFGHIJKLMNOPQRSTUVWYXZ";
      for(p=pWInfo->pLoops, i=0; p; p=p->pNextLoop, i++){
        pWInfo->pLoops = p->pNextLoop;
        p->cId = zLabel[i%(sizeof(zLabel)-1)];
        whereLoopPrint(p, sWLB.pWC);
        whereLoopDelete(db, p);
      }
      rc = whereLoopAddAll(&sWLB);
      if( rc ) goto whereBeginError;
    }
#endif
    WHERETRACE_ALL_LOOPS(pWInfo, sWLB.pWC);
  
    wherePathSolver(pWInfo, 0);
    if( db->mallocFailed ) goto whereBeginError;
    if( pWInfo->pOrderBy ){
       wherePathSolver(pWInfo, pWInfo->nRowOut+1);
       if( db->mallocFailed ) goto whereBeginError;
    }
  }
  if( pWInfo->pOrderBy==0 && (db->flags & SQLITE_ReverseOrder)!=0 ){
     pWInfo->revMask = ALLBITS;
  }
  if( pParse->nErr || NEVER(db->mallocFailed) ){
  if( pParse->nErr ){
    goto whereBeginError;
  }
  assert( db->mallocFailed==0 );
#ifdef WHERETRACE_ENABLED
  if( sqlite3WhereTrace ){
    sqlite3DebugPrintf("---- Solution nRow=%d", pWInfo->nRowOut);
    if( pWInfo->nOBSat>0 ){
      sqlite3DebugPrintf(" ORDERBY=%d,0x%llx", pWInfo->nOBSat, pWInfo->revMask);
    }
    switch( pWInfo->eDistinct ){
4805
4806
4807
4808
4809
4810
4811
4812

4813
4814
4815
4816
4817
4818


4819
4820
4821
4822
4823
4824
4825






4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848


4849
4850
4851
4852
4853



4854
4855

4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867





4868
4869
4870
4871
4872
4873


4874
4875
4876



4877
4878
4879

4880
4881



4882
4883
4884

4885
4886
4887
4888
4889
4890
4891
4892
4893
4894


4895
4896
4897
4898
4899
4900
4901
6071
6072
6073
6074
6075
6076
6077

6078
6079
6080
6081
6082


6083
6084
6085






6086
6087
6088
6089
6090
6091



















6092
6093
6094

6095
6096
6097
6098



6099
6100
6101


6102












6103
6104
6105
6106
6107






6108
6109



6110
6111
6112



6113


6114
6115
6116



6117










6118
6119
6120
6121
6122
6123
6124
6125
6126







-
+




-
-
+
+

-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-



-
+
+


-
-
-
+
+
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
+
+
-
-
-
+
+
+
-
-
-
+
-
-
+
+
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
+
+







      case WHERE_DISTINCT_UNORDERED: {
        sqlite3DebugPrintf("  DISTINCT=unordered");
        break;
      }
    }
    sqlite3DebugPrintf("\n");
    for(ii=0; ii<pWInfo->nLevel; ii++){
      whereLoopPrint(pWInfo->a[ii].pWLoop, sWLB.pWC);
      sqlite3WhereLoopPrint(pWInfo->a[ii].pWLoop, sWLB.pWC);
    }
  }
#endif

  /* Attempt to omit tables from the join that do not affect the result.
  ** For a table to not affect the result, the following must be true:
  /* Attempt to omit tables from a join that do not affect the result.
  ** See the comment on whereOmitNoopJoin() for further information.
  **
  **   1) The query must not be an aggregate.
  **   2) The table must be the RHS of a LEFT JOIN.
  **   3) Either the query must be DISTINCT, or else the ON or USING clause
  **      must contain a constraint that limits the scan of the table to 
  **      at most a single row.
  **   4) The table must not be referenced by any part of the query apart
  ** This query optimization is factored out into a separate "no-inline"
  ** procedure to keep the sqlite3WhereBegin() procedure from becoming
  ** too large.  If sqlite3WhereBegin() becomes too large, that prevents
  ** some C-compiler optimizers from in-lining the 
  ** sqlite3WhereCodeOneLoopStart() procedure, and it is important to
  ** in-line sqlite3WhereCodeOneLoopStart() for performance reasons.
  **      from its own USING or ON clause.
  **
  ** For example, given:
  **
  **     CREATE TABLE t1(ipk INTEGER PRIMARY KEY, v1);
  **     CREATE TABLE t2(ipk INTEGER PRIMARY KEY, v2);
  **     CREATE TABLE t3(ipk INTEGER PRIMARY KEY, v3);
  **
  ** then table t2 can be omitted from the following:
  **
  **     SELECT v1, v3 FROM t1 
  **       LEFT JOIN t2 USING (t1.ipk=t2.ipk)
  **       LEFT JOIN t3 USING (t1.ipk=t3.ipk)
  **
  ** or from:
  **
  **     SELECT DISTINCT v1, v3 FROM t1 
  **       LEFT JOIN t2
  **       LEFT JOIN t3 USING (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 ){
    notReady = whereOmitNoopJoin(pWInfo, notReady);
    nTabList = pWInfo->nLevel;
    assert( nTabList>0 );
      tabUsed |= sqlite3WhereExprListUsage(pMaskSet, sWLB.pOrderBy);
    }
  }
    for(i=pWInfo->nLevel-1; i>=1; i--){
      WhereTerm *pTerm, *pEnd;
      struct SrcList_item *pItem;
      pLoop = pWInfo->a[i].pWLoop;
      pItem = &pWInfo->pTabList->a[pLoop->iTab];
      if( (pItem->fg.jointype & JT_LEFT)==0 ) continue;
      if( (wctrlFlags & WHERE_WANT_DISTINCT)==0
       && (pLoop->wsFlags & WHERE_ONEROW)==0
      ){
        continue;
      }
      if( (tabUsed & pLoop->maskSelf)!=0 ) continue;

  /* Check to see if there are any SEARCH loops that might benefit from
  ** using a Bloom filter.
  */
  if( pWInfo->nLevel>=2
      pEnd = sWLB.pWC->a + sWLB.pWC->nTerm;
      for(pTerm=sWLB.pWC->a; pTerm<pEnd; pTerm++){
        if( (pTerm->prereqAll & pLoop->maskSelf)!=0 ){
          if( !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
           || pTerm->pExpr->iRightJoinTable!=pItem->iCursor
          ){
   && OptimizationEnabled(db, SQLITE_BloomFilter)
  ){
            break;
          }
        }
    whereCheckIfBloomFilterIsUseful(pWInfo);
  }

      }
      if( pTerm<pEnd ) continue;
      WHERETRACE(0xffff, ("-> drop loop %c not used\n", pLoop->cId));
#if defined(WHERETRACE_ENABLED)
      notReady &= ~pLoop->maskSelf;
      for(pTerm=sWLB.pWC->a; pTerm<pEnd; pTerm++){
  if( sqlite3WhereTrace & 0x4000 ){ /* Display all terms of the WHERE clause */
    sqlite3DebugPrintf("---- WHERE clause at end of analysis:\n");
    sqlite3WhereClausePrint(sWLB.pWC);
        if( (pTerm->prereqAll & pLoop->maskSelf)!=0 ){
          pTerm->wtFlags |= TERM_CODED;
        }
  }
      }
      if( i!=pWInfo->nLevel-1 ){
        int nByte = (pWInfo->nLevel-1-i) * sizeof(WhereLevel);
        memmove(&pWInfo->a[i], &pWInfo->a[i+1], nByte);
      }
      pWInfo->nLevel--;
      nTabList--;
    }
  }
  WHERETRACE(0xffff,("*** Optimizer Finished ***\n"));
  WHERETRACE(0xffffffff,("*** Optimizer Finished ***\n"));
#endif
  pWInfo->pParse->nQueryLoop += pWInfo->nRowOut;

  /* If the caller is an UPDATE or DELETE statement that is requesting
  ** to use a one-pass algorithm, determine if this is appropriate.
  **
  ** A one-pass approach can be used if the caller has requested one
  ** and either (a) the scan visits at most one row or (b) each
4913
4914
4915
4916
4917
4918
4919

4920
4921
4922

4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941

4942
4943
4944
4945
4946
4947

4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960




4961
4962
4963
4964
4965
4966
4967
4968
4969
4970








4971
4972
4973
4974
4975
4976
4977
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147

6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166

6167
6168
6169
6170
6171
6172

6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184


6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197

6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212







+


-
+


















-
+





-
+











-
-
+
+
+
+









-
+
+
+
+
+
+
+
+







  ** use a one-pass approach, and this is not set accurately for scans
  ** that use the OR optimization.
  */
  assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 );
  if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 ){
    int wsFlags = pWInfo->a[0].pWLoop->wsFlags;
    int bOnerow = (wsFlags & WHERE_ONEROW)!=0;
    assert( !(wsFlags & WHERE_VIRTUALTABLE) || IsVirtual(pTabList->a[0].pTab) );
    if( bOnerow || (
        0!=(wctrlFlags & WHERE_ONEPASS_MULTIROW)
     && 0==(wsFlags & WHERE_VIRTUALTABLE)
     && !IsVirtual(pTabList->a[0].pTab)
     && (0==(wsFlags & WHERE_MULTI_OR) || (wctrlFlags & WHERE_DUPLICATES_OK))
    )){
      pWInfo->eOnePass = bOnerow ? ONEPASS_SINGLE : ONEPASS_MULTI;
      if( HasRowid(pTabList->a[0].pTab) && (wsFlags & WHERE_IDX_ONLY) ){
        if( wctrlFlags & WHERE_ONEPASS_MULTIROW ){
          bFordelete = OPFLAG_FORDELETE;
        }
        pWInfo->a[0].pWLoop->wsFlags = (wsFlags & ~WHERE_IDX_ONLY);
      }
    }
  }

  /* Open all tables in the pTabList and any indices selected for
  ** searching those tables.
  */
  for(ii=0, pLevel=pWInfo->a; ii<nTabList; ii++, pLevel++){
    Table *pTab;     /* Table to open */
    int iDb;         /* Index of database containing table/index */
    struct SrcList_item *pTabItem;
    SrcItem *pTabItem;

    pTabItem = &pTabList->a[pLevel->iFrom];
    pTab = pTabItem->pTab;
    iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
    pLoop = pLevel->pWLoop;
    if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ){
    if( (pTab->tabFlags & TF_Ephemeral)!=0 || IsView(pTab) ){
      /* Do nothing */
    }else
#ifndef SQLITE_OMIT_VIRTUALTABLE
    if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ){
      const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
      int iCur = pTabItem->iCursor;
      sqlite3VdbeAddOp4(v, OP_VOpen, iCur, 0, 0, pVTab, P4_VTAB);
    }else if( IsVirtual(pTab) ){
      /* noop */
    }else
#endif
    if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
         && (wctrlFlags & WHERE_OR_SUBCLAUSE)==0 ){
    if( ((pLoop->wsFlags & WHERE_IDX_ONLY)==0
         && (wctrlFlags & WHERE_OR_SUBCLAUSE)==0)
     || (pTabItem->fg.jointype & (JT_LTORJ|JT_RIGHT))!=0
    ){
      int op = OP_OpenRead;
      if( pWInfo->eOnePass!=ONEPASS_OFF ){
        op = OP_OpenWrite;
        pWInfo->aiCurOnePass[0] = pTabItem->iCursor;
      };
      sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, op);
      assert( pTabItem->iCursor==pLevel->iTabCur );
      testcase( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol==BMS-1 );
      testcase( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol==BMS );
      if( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol<BMS && HasRowid(pTab) ){
      if( pWInfo->eOnePass==ONEPASS_OFF 
       && pTab->nCol<BMS
       && (pTab->tabFlags & (TF_HasGenerated|TF_WithoutRowid))==0
       && (pLoop->wsFlags & (WHERE_AUTO_INDEX|WHERE_BLOOMFILTER))==0
      ){
        /* If we know that only a prefix of the record will be used,
        ** it is advantageous to reduce the "column count" field in
        ** the P4 operand of the OP_OpenRead/Write opcode. */
        Bitmask b = pTabItem->colUsed;
        int n = 0;
        for(; b; b=b>>1, n++){}
        sqlite3VdbeChangeP4(v, -1, SQLITE_INT_TO_PTR(n), P4_INT32);
        assert( n<=pTab->nCol );
      }
#ifdef SQLITE_ENABLE_CURSOR_HINTS
5013
5014
5015
5016
5017
5018
5019


5020


5021

5022
5023
5024
5025
5026
5027
5028


5029
5030
5031
5032

5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052































5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063


5064
5065












5066
5067
5068
5069






5070
5071
5072
5073
5074
5075
5076
5077

5078
5079
5080
5081
5082
5083
5084
5085

5086
5087
5088
5089
5090
5091
5092
6248
6249
6250
6251
6252
6253
6254
6255
6256

6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272

6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352



6353
6354
6355
6356
6357
6358
6359
6360

6361
6362
6363
6364

6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381







+
+
-
+
+

+







+
+



-
+




















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+











+
+


+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
+
+
+
+
+
+


-




-
+








+







        op = OP_OpenWrite;
        pWInfo->aiCurOnePass[1] = iIndexCur;
      }else if( iAuxArg && (wctrlFlags & WHERE_OR_SUBCLAUSE)!=0 ){
        iIndexCur = iAuxArg;
        op = OP_ReopenIdx;
      }else{
        iIndexCur = pParse->nTab++;
        if( pIx->bHasExpr && OptimizationEnabled(db, SQLITE_IndexedExpr) ){
          whereAddIndexedExpr(pParse, pIx, iIndexCur, pTabItem);
      }
        }
      }
      pLevel->iIdxCur = iIndexCur;
      assert( pIx!=0 );
      assert( pIx->pSchema==pTab->pSchema );
      assert( iIndexCur>=0 );
      if( op ){
        sqlite3VdbeAddOp3(v, op, iIndexCur, pIx->tnum, iDb);
        sqlite3VdbeSetP4KeyInfo(pParse, pIx);
        if( (pLoop->wsFlags & WHERE_CONSTRAINT)!=0
         && (pLoop->wsFlags & (WHERE_COLUMN_RANGE|WHERE_SKIPSCAN))==0
         && (pLoop->wsFlags & WHERE_BIGNULL_SORT)==0
         && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0
         && (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)==0
         && pWInfo->eDistinct!=WHERE_DISTINCT_ORDERED
        ){
          sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ); /* Hint to COMDB2 */
          sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ);
        }
        VdbeComment((v, "%s", pIx->zName));
#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
        {
          u64 colUsed = 0;
          int ii, jj;
          for(ii=0; ii<pIx->nColumn; ii++){
            jj = pIx->aiColumn[ii];
            if( jj<0 ) continue;
            if( jj>63 ) jj = 63;
            if( (pTabItem->colUsed & MASKBIT(jj))==0 ) continue;
            colUsed |= ((u64)1)<<(ii<63 ? ii : 63);
          }
          sqlite3VdbeAddOp4Dup8(v, OP_ColumnsUsed, iIndexCur, 0, 0,
                                (u8*)&colUsed, P4_INT64);
        }
#endif /* SQLITE_ENABLE_COLUMN_USED_MASK */
      }
    }
    if( iDb>=0 ) sqlite3CodeVerifySchema(pParse, iDb);
    if( (pTabItem->fg.jointype & JT_RIGHT)!=0
     && (pLevel->pRJ = sqlite3WhereMalloc(pWInfo, sizeof(WhereRightJoin)))!=0
    ){
      WhereRightJoin *pRJ = pLevel->pRJ;
      pRJ->iMatch = pParse->nTab++;
      pRJ->regBloom = ++pParse->nMem;
      sqlite3VdbeAddOp2(v, OP_Blob, 65536, pRJ->regBloom);
      pRJ->regReturn = ++pParse->nMem;
      sqlite3VdbeAddOp2(v, OP_Null, 0, pRJ->regReturn);
      assert( pTab==pTabItem->pTab );
      if( HasRowid(pTab) ){
        KeyInfo *pInfo;
        sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRJ->iMatch, 1);
        pInfo = sqlite3KeyInfoAlloc(pParse->db, 1, 0);
        if( pInfo ){
          pInfo->aColl[0] = 0;
          pInfo->aSortFlags[0] = 0;
          sqlite3VdbeAppendP4(v, pInfo, P4_KEYINFO);
        }
      }else{
        Index *pPk = sqlite3PrimaryKeyIndex(pTab);
        sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRJ->iMatch, pPk->nKeyCol);
        sqlite3VdbeSetP4KeyInfo(pParse, pPk);
      }
      pLoop->wsFlags &= ~WHERE_IDX_ONLY;
      /* The nature of RIGHT JOIN processing is such that it messes up
      ** the output order.  So omit any ORDER BY/GROUP BY elimination
      ** optimizations.  We need to do an actual sort for RIGHT JOIN. */
      pWInfo->nOBSat = 0;
      pWInfo->eDistinct = WHERE_DISTINCT_UNORDERED;
    }
  }
  pWInfo->iTop = sqlite3VdbeCurrentAddr(v);
  if( db->mallocFailed ) goto whereBeginError;

  /* Generate the code to do the search.  Each iteration of the for
  ** loop below generates code for a single nested loop of the VM
  ** program.
  */
  for(ii=0; ii<nTabList; ii++){
    int addrExplain;
    int wsFlags;
    SrcItem *pSrc;
    if( pParse->nErr ) goto whereBeginError;
    pLevel = &pWInfo->a[ii];
    wsFlags = pLevel->pWLoop->wsFlags;
    pSrc = &pTabList->a[pLevel->iFrom];
    if( pSrc->fg.isMaterialized ){
      if( pSrc->fg.isCorrelated ){
        sqlite3VdbeAddOp2(v, OP_Gosub, pSrc->regReturn, pSrc->addrFillSub);
      }else{
        int iOnce = sqlite3VdbeAddOp0(v, OP_Once);  VdbeCoverage(v);
        sqlite3VdbeAddOp2(v, OP_Gosub, pSrc->regReturn, pSrc->addrFillSub);
        sqlite3VdbeJumpHere(v, iOnce);
      }
    }
    if( (wsFlags & (WHERE_AUTO_INDEX|WHERE_BLOOMFILTER))!=0 ){
      if( (wsFlags & WHERE_AUTO_INDEX)!=0 ){
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
    if( (pLevel->pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 ){
      constructAutomaticIndex(pParse, &pWInfo->sWC,
                &pTabList->a[pLevel->iFrom], notReady, pLevel);
        constructAutomaticIndex(pParse, &pWInfo->sWC,
                  &pTabList->a[pLevel->iFrom], notReady, pLevel);
#endif
      }else{
        sqlite3ConstructBloomFilter(pWInfo, ii, pLevel, notReady);
      }
      if( db->mallocFailed ) goto whereBeginError;
    }
#endif
    addrExplain = sqlite3WhereExplainOneScan(
        pParse, pTabList, pLevel, wctrlFlags
    );
    pLevel->addrBody = sqlite3VdbeCurrentAddr(v);
    notReady = sqlite3WhereCodeOneLoopStart(pWInfo, ii, notReady);
    notReady = sqlite3WhereCodeOneLoopStart(pParse,v,pWInfo,ii,pLevel,notReady);
    pWInfo->iContinue = pLevel->addrCont;
    if( (wsFlags&WHERE_MULTI_OR)==0 && (wctrlFlags&WHERE_OR_SUBCLAUSE)==0 ){
      sqlite3WhereAddScanStatus(v, pTabList, pLevel, addrExplain);
    }
  }

  /* Done. */
  VdbeModuleComment((v, "Begin WHERE-core"));
  pWInfo->iEndWhere = sqlite3VdbeCurrentAddr(v);
  return pWInfo;

  /* Jump here if malloc fails */
whereBeginError:
  if( pWInfo ){
    pParse->nQueryLoop = pWInfo->savedNQueryLoop;
    whereInfoFree(db, pWInfo);
5110
5111
5112
5113
5114
5115
5116




















5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128


5129
5130
5131
5132
5133
5134
5135











5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146

5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163

5164
5165
5166
5167
5168
5169





5170
5171
5172
5173

5174
5175
5176

5177
5178
5179
5180


5181
5182
5183


5184
5185
5186
5187
5188

























5189
5190
5191
5192
5193
5194
5195
5196
5197
5198




5199
5200
5201
5202
5203
5204
5205
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+












+
+







+
+
+
+
+
+
+
+
+
+
+










-
+
















-
+






+
+
+
+
+



-
+


-
+




+
+



+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










+
+
+
+







    VdbeOp *pOp
  ){
    if( (db->flags & SQLITE_VdbeAddopTrace)==0 ) return;
    sqlite3VdbePrintOp(0, pc, pOp);
  }
#endif

#ifdef SQLITE_DEBUG
/*
** Return true if cursor iCur is opened by instruction k of the
** bytecode.  Used inside of assert() only.
*/
static int cursorIsOpen(Vdbe *v, int iCur, int k){
  while( k>=0 ){
    VdbeOp *pOp = sqlite3VdbeGetOp(v,k--);
    if( pOp->p1!=iCur ) continue;
    if( pOp->opcode==OP_Close ) return 0;
    if( pOp->opcode==OP_OpenRead ) return 1;
    if( pOp->opcode==OP_OpenWrite ) return 1;
    if( pOp->opcode==OP_OpenDup ) return 1;
    if( pOp->opcode==OP_OpenAutoindex ) return 1;
    if( pOp->opcode==OP_OpenEphemeral ) return 1;
  }
  return 0;
}
#endif /* SQLITE_DEBUG */

/*
** Generate the end of the WHERE loop.  See comments on 
** sqlite3WhereBegin() for additional information.
*/
void sqlite3WhereEnd(WhereInfo *pWInfo){
  Parse *pParse = pWInfo->pParse;
  Vdbe *v = pParse->pVdbe;
  int i;
  WhereLevel *pLevel;
  WhereLoop *pLoop;
  SrcList *pTabList = pWInfo->pTabList;
  sqlite3 *db = pParse->db;
  int iEnd = sqlite3VdbeCurrentAddr(v);
  int nRJ = 0;

  /* Generate loop termination code.
  */
  VdbeModuleComment((v, "End WHERE-core"));
  for(i=pWInfo->nLevel-1; i>=0; i--){
    int addr;
    pLevel = &pWInfo->a[i];
    if( pLevel->pRJ ){
      /* Terminate the subroutine that forms the interior of the loop of
      ** the RIGHT JOIN table */
      WhereRightJoin *pRJ = pLevel->pRJ;
      sqlite3VdbeResolveLabel(v, pLevel->addrCont);
      pLevel->addrCont = 0;
      pRJ->endSubrtn = sqlite3VdbeCurrentAddr(v);
      sqlite3VdbeAddOp3(v, OP_Return, pRJ->regReturn, pRJ->addrSubrtn, 1);
      VdbeCoverage(v);
      nRJ++;
    }
    pLoop = pLevel->pWLoop;
    if( pLevel->op!=OP_Noop ){
#ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT
      int addrSeek = 0;
      Index *pIdx;
      int n;
      if( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED
       && i==pWInfo->nLevel-1  /* Ticket [ef9318757b152e3] 2017-10-21 */
       && (pLoop->wsFlags & WHERE_INDEXED)!=0
       && (pIdx = pLoop->u.btree.pIndex)->hasStat1
       && (n = pLoop->u.btree.nIdxCol)>0
       && (n = pLoop->u.btree.nDistinctCol)>0
       && pIdx->aiRowLogEst[n]>=36
      ){
        int r1 = pParse->nMem+1;
        int j, op;
        for(j=0; j<n; j++){
          sqlite3VdbeAddOp3(v, OP_Column, pLevel->iIdxCur, j, r1+j);
        }
        pParse->nMem += n+1;
        op = pLevel->op==OP_Prev ? OP_SeekLT : OP_SeekGT;
        addrSeek = sqlite3VdbeAddOp4Int(v, op, pLevel->iIdxCur, 0, r1, n);
        VdbeCoverageIf(v, op==OP_SeekLT);
        VdbeCoverageIf(v, op==OP_SeekGT);
        sqlite3VdbeAddOp2(v, OP_Goto, 1, pLevel->p2);
      }
#endif /* SQLITE_DISABLE_SKIPAHEAD_DISTINCT */
      /* The common case: Advance to the next row */
      sqlite3VdbeResolveLabel(v, pLevel->addrCont);
      if( pLevel->addrCont ) sqlite3VdbeResolveLabel(v, pLevel->addrCont);
      sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3);
      sqlite3VdbeChangeP5(v, pLevel->p5);
      VdbeCoverage(v);
      VdbeCoverageIf(v, pLevel->op==OP_Next);
      VdbeCoverageIf(v, pLevel->op==OP_Prev);
      VdbeCoverageIf(v, pLevel->op==OP_VNext);
      if( pLevel->regBignull ){
        sqlite3VdbeResolveLabel(v, pLevel->addrBignull);
        sqlite3VdbeAddOp2(v, OP_DecrJumpZero, pLevel->regBignull, pLevel->p2-1);
        VdbeCoverage(v);
      }
#ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT
      if( addrSeek ) sqlite3VdbeJumpHere(v, addrSeek);
#endif
    }else{
    }else if( pLevel->addrCont ){
      sqlite3VdbeResolveLabel(v, pLevel->addrCont);
    }
    if( pLoop->wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){
    if( (pLoop->wsFlags & WHERE_IN_ABLE)!=0 && pLevel->u.in.nIn>0 ){
      struct InLoop *pIn;
      int j;
      sqlite3VdbeResolveLabel(v, pLevel->addrNxt);
      for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){
        assert( sqlite3VdbeGetOp(v, pIn->addrInTop+1)->opcode==OP_IsNull
                 || pParse->db->mallocFailed );
        sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
        if( pIn->eEndLoopOp!=OP_Noop ){
          if( pIn->nPrefix ){
            int bEarlyOut = 
                (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0
            assert( pLoop->wsFlags & WHERE_IN_EARLYOUT );
            sqlite3VdbeAddOp4Int(v, OP_IfNoHope, pLevel->iIdxCur,
                              sqlite3VdbeCurrentAddr(v)+2,
                              pIn->iBase, pIn->nPrefix);
            VdbeCoverage(v);
                 && (pLoop->wsFlags & WHERE_IN_EARLYOUT)!=0;
            if( pLevel->iLeftJoin ){
              /* For LEFT JOIN queries, cursor pIn->iCur may not have been
              ** opened yet. This occurs for WHERE clauses such as
              ** "a = ? AND b IN (...)", where the index is on (a, b). If
              ** the RHS of the (a=?) is NULL, then the "b IN (...)" may
              ** never have been coded, but the body of the loop run to
              ** return the null-row. So, if the cursor is not open yet,
              ** jump over the OP_Next or OP_Prev instruction about to
              ** be coded.  */
              sqlite3VdbeAddOp2(v, OP_IfNotOpen, pIn->iCur, 
                  sqlite3VdbeCurrentAddr(v) + 2 + bEarlyOut);
              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);
        }
        sqlite3VdbeJumpHere(v, pIn->addrInTop-1);
      }
    }
    sqlite3VdbeResolveLabel(v, pLevel->addrBrk);
    if( pLevel->pRJ ){
      sqlite3VdbeAddOp3(v, OP_Return, pLevel->pRJ->regReturn, 0, 1);
      VdbeCoverage(v);
    }
    if( pLevel->addrSkip ){
      sqlite3VdbeGoto(v, pLevel->addrSkip);
      VdbeComment((v, "next skip-scan on %s", pLoop->u.btree.pIndex->zName));
      sqlite3VdbeJumpHere(v, pLevel->addrSkip);
      sqlite3VdbeJumpHere(v, pLevel->addrSkip-2);
    }
#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
5214
5215
5216
5217
5218
5219
5220
5221

5222






5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244

5245
5246

5247
5248
5249









5250
5251
5252
5253
5254
5255
5256
6569
6570
6571
6572
6573
6574
6575

6576
6577
6578
6579
6580
6581
6582
6583
6584
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594
6595
6596





6597
6598
6599

6600
6601

6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621







-
+

+
+
+
+
+
+













-
-
-
-
-



-
+

-
+



+
+
+
+
+
+
+
+
+







      addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v);
      assert( (ws & WHERE_IDX_ONLY)==0 || (ws & WHERE_INDEXED)!=0 );
      if( (ws & WHERE_IDX_ONLY)==0 ){
        assert( pLevel->iTabCur==pTabList->a[pLevel->iFrom].iCursor );
        sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iTabCur);
      }
      if( (ws & WHERE_INDEXED) 
       || ((ws & WHERE_MULTI_OR) && pLevel->u.pCovidx) 
       || ((ws & WHERE_MULTI_OR) && pLevel->u.pCoveringIdx) 
      ){
        if( ws & WHERE_MULTI_OR ){
          Index *pIx = pLevel->u.pCoveringIdx;
          int iDb = sqlite3SchemaToIndex(db, pIx->pSchema);
          sqlite3VdbeAddOp3(v, OP_ReopenIdx, pLevel->iIdxCur, pIx->tnum, iDb);
          sqlite3VdbeSetP4KeyInfo(pParse, pIx);
        }
        sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur);
      }
      if( pLevel->op==OP_Return ){
        sqlite3VdbeAddOp2(v, OP_Gosub, pLevel->p1, pLevel->addrFirst);
      }else{
        sqlite3VdbeGoto(v, pLevel->addrFirst);
      }
      sqlite3VdbeJumpHere(v, addr);
    }
    VdbeModuleComment((v, "End WHERE-loop%d: %s", i,
                     pWInfo->pTabList->a[pLevel->iFrom].pTab->zName));
  }

  /* The "break" point is here, just past the end of the outer loop.
  ** Set it.
  */
  sqlite3VdbeResolveLabel(v, pWInfo->iBreak);

  assert( pWInfo->nLevel<=pTabList->nSrc );
  for(i=0, pLevel=pWInfo->a; i<pWInfo->nLevel; i++, pLevel++){
    int k, last;
    VdbeOp *pOp;
    VdbeOp *pOp, *pLastOp;
    Index *pIdx = 0;
    struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
    SrcItem *pTabItem = &pTabList->a[pLevel->iFrom];
    Table *pTab = pTabItem->pTab;
    assert( pTab!=0 );
    pLoop = pLevel->pWLoop;

    /* Do RIGHT JOIN processing.  Generate code that will output the
    ** unmatched rows of the right operand of the RIGHT JOIN with
    ** all of the columns of the left operand set to NULL.
    */
    if( pLevel->pRJ ){
      sqlite3WhereRightJoinLoop(pWInfo, i, pLevel);
      continue;
    }

    /* For a co-routine, change all OP_Column references to the table of
    ** the co-routine into OP_Copy of result contained in a register.
    ** OP_Rowid becomes OP_Null.
    */
    if( pTabItem->fg.viaCoroutine ){
      testcase( pParse->db->mallocFailed );
5269
5270
5271
5272
5273
5274
5275
5276

5277
5278
5279
5280
5281

5282
5283






















5284
5285
5286
5287





5288
5289

5290
5291
5292





5293
5294
5295
5296
5297
5298





5299
5300
5301
5302



5303
5304

5305
5306
5307
5308
5309
5310
5311
















5312
5313
5314
5315
5316
5317
5318
5319
5320




5321
5322
5323
5324
5325
5326





5327
5328
5329
5330

5331
5332
6634
6635
6636
6637
6638
6639
6640

6641
6642
6643

6644
6645
6646


6647
6648
6649
6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
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



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
6735
6736
6737
6738
6739
6740
6741
6742
6743
6744
6745
6746
6747
6748
6749
6750
6751
6752
6753
6754
6755







-
+


-


+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




+
+
+
+
+


+
-
-
-
+
+
+
+
+






+
+
+
+
+




+
+
+

-
+




-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








-
+
+
+
+






+
+
+
+
+




+


    ** directly.  This loop scans all that code looking for opcodes
    ** that reference the table and converts them into opcodes that
    ** reference the index.
    */
    if( pLoop->wsFlags & (WHERE_INDEXED|WHERE_IDX_ONLY) ){
      pIdx = pLoop->u.btree.pIndex;
    }else if( pLoop->wsFlags & WHERE_MULTI_OR ){
      pIdx = pLevel->u.pCovidx;
      pIdx = pLevel->u.pCoveringIdx;
    }
    if( pIdx
     && (pWInfo->eOnePass==ONEPASS_OFF || !HasRowid(pIdx->pTable))
     && !db->mallocFailed
    ){
      if( pWInfo->eOnePass==ONEPASS_OFF || !HasRowid(pIdx->pTable) ){
      last = sqlite3VdbeCurrentAddr(v);
      k = pLevel->addrBody;
        last = iEnd;
      }else{
        last = pWInfo->iEndWhere;
      }
      if( pIdx->bHasExpr ){
        IndexedExpr *p = pParse->pIdxEpr;
        while( p ){
          if( p->iIdxCur==pLevel->iIdxCur ){
#ifdef WHERETRACE_ENABLED
            if( sqlite3WhereTrace & 0x200 ){
              sqlite3DebugPrintf("Disable pParse->pIdxEpr term {%d,%d}\n",
                                  p->iIdxCur, p->iIdxCol);
              if( sqlite3WhereTrace & 0x5000 ) sqlite3ShowExpr(p->pExpr);
            }
#endif
            p->iDataCur = -1;
            p->iIdxCur = -1;
          }
          p = p->pIENext;
        }
      }
      k = pLevel->addrBody + 1;
#ifdef SQLITE_DEBUG
      if( db->flags & SQLITE_VdbeAddopTrace ){
        printf("TRANSLATE opcodes in range %d..%d\n", k, last-1);
      }
      /* Proof that the "+1" on the k value above is safe */
      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);
      for(; k<last; k++, pOp++){
        if( pOp->p1!=pLevel->iTabCur ) continue;
        if( pOp->opcode==OP_Column
      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
        ){
          int x = pOp->p2;
          assert( pIdx->pTable==pTab );
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
          if( pOp->opcode==OP_Offset ){
            /* Do not need to translate the column number */
          }else
#endif
          if( !HasRowid(pTab) ){
            Index *pPk = sqlite3PrimaryKeyIndex(pTab);
            x = pPk->aiColumn[x];
            assert( x>=0 );
          }else{
            testcase( x!=sqlite3StorageColumnToTable(pTab,x) );
            x = sqlite3StorageColumnToTable(pTab,x);
          }
          x = sqlite3ColumnOfIndex(pIdx, x);
          x = sqlite3TableColumnToIndex(pIdx, x);
          if( x>=0 ){
            pOp->p2 = x;
            pOp->p1 = pLevel->iIdxCur;
            OpcodeRewriteTrace(db, k, pOp);
          }
          assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || x>=0 
              || pWInfo->eOnePass );
          }else{
            /* Unable to translate the table reference into an index
            ** reference.  Verify that this is harmless - that the
            ** table being referenced really is open.
            */
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
            assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
                 || cursorIsOpen(v,pOp->p1,k)
                 || pOp->opcode==OP_Offset
            );
#else
            assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
                 || cursorIsOpen(v,pOp->p1,k)
            );
#endif
          }
        }else if( pOp->opcode==OP_Rowid ){
          pOp->p1 = pLevel->iIdxCur;
          pOp->opcode = OP_IdxRowid;
          OpcodeRewriteTrace(db, k, pOp);
        }else if( pOp->opcode==OP_IfNullRow ){
          pOp->p1 = pLevel->iIdxCur;
          OpcodeRewriteTrace(db, k, pOp);
        }
      }
#ifdef SQLITE_DEBUG
        k++;
#endif
      }while( (++pOp)<pLastOp );
#ifdef SQLITE_DEBUG
      if( db->flags & SQLITE_VdbeAddopTrace ) printf("TRANSLATE complete\n");
#endif
    }
  }

  /* The "break" point is here, just past the end of the outer loop.
  ** Set it.
  */
  sqlite3VdbeResolveLabel(v, pWInfo->iBreak);

  /* Final cleanup
  */
  pParse->nQueryLoop = pWInfo->savedNQueryLoop;
  whereInfoFree(db, pWInfo);
  pParse->withinRJSubrtn -= nRJ;
  return;
}

Changes to src/whereInt.h.

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
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







+
+

-
-
-
-
-
-
-
-
-
-
-
-
-















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







**
*************************************************************************
**
** This file contains structure and macro definitions for the query
** planner logic in "where.c".  These definitions are broken out into
** a separate source file for easier editing.
*/
#ifndef SQLITE_WHEREINT_H
#define SQLITE_WHEREINT_H

/*
** Trace output macros
*/
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
/***/ extern int sqlite3WhereTrace;
#endif
#if defined(SQLITE_DEBUG) \
    && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE))
# define WHERETRACE(K,X)  if(sqlite3WhereTrace&(K)) sqlite3DebugPrintf X
# define WHERETRACE_ENABLED 1
#else
# define WHERETRACE(K,X)
#endif

/* Forward references
*/
typedef struct WhereClause WhereClause;
typedef struct WhereMaskSet WhereMaskSet;
typedef struct WhereOrInfo WhereOrInfo;
typedef struct WhereAndInfo WhereAndInfo;
typedef struct WhereLevel WhereLevel;
typedef struct WhereLoop WhereLoop;
typedef struct WherePath WherePath;
typedef struct WhereTerm WhereTerm;
typedef struct WhereLoopBuilder WhereLoopBuilder;
typedef struct WhereScan WhereScan;
typedef struct WhereOrCost WhereOrCost;
typedef struct WhereOrSet WhereOrSet;
typedef struct WhereMemBlock WhereMemBlock;
typedef struct WhereRightJoin WhereRightJoin;

/*
** This object is a header on a block of allocated memory that will be
** automatically freed when its WInfo oject is destructed.
*/
struct WhereMemBlock {
  WhereMemBlock *pNext;      /* Next block in the chain */
  u64 sz;                    /* Bytes of space */
};

/*
** Extra information attached to a WhereLevel that is a RIGHT JOIN.
*/
struct WhereRightJoin {
  int iMatch;          /* Cursor used to determine prior matched rows */
  int regBloom;        /* Bloom filter for iRJMatch */
  int regReturn;       /* Return register for the interior subroutine */
  int addrSubrtn;      /* Starting address for the interior subroutine */
  int endSubrtn;       /* The last opcode in the interior subroutine */
};

/*
** This object contains information needed to implement a single nested
** loop in WHERE clause.
**
** Contrast this object with WhereLoop.  This object describes the
** implementation of the loop.  WhereLoop describes the algorithm.
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
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







+
+




+
+


-
+











-
+







  int iIdxCur;          /* The VDBE cursor used to access pIdx */
  int addrBrk;          /* Jump here to break out of the loop */
  int addrNxt;          /* Jump here to start the next IN combination */
  int addrSkip;         /* Jump here for next iteration of skip-scan */
  int addrCont;         /* Jump here to continue with the next loop cycle */
  int addrFirst;        /* First instruction of interior of the loop */
  int addrBody;         /* Beginning of the body of this loop */
  int regBignull;       /* big-null flag reg. True if a NULL-scan is needed */
  int addrBignull;      /* Jump here for next part of big-null scan */
#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
  u32 iLikeRepCntr;     /* LIKE range processing counter register (times 2) */
  int addrLikeRep;      /* LIKE range processing address */
#endif
  int regFilter;        /* Bloom filter */
  WhereRightJoin *pRJ;  /* Extra information for RIGHT JOIN */
  u8 iFrom;             /* Which entry in the FROM clause */
  u8 op, p3, p5;        /* Opcode, P3 & P5 of the opcode that ends the loop */
  int p1, p2;           /* Operands of the opcode used to ends the loop */
  int p1, p2;           /* Operands of the opcode used to end the loop */
  union {               /* Information that depends on pWLoop->wsFlags */
    struct {
      int nIn;              /* Number of entries in aInLoop[] */
      struct InLoop {
        int iCur;              /* The VDBE cursor used by this IN operator */
        int addrInTop;         /* Top of the IN loop */
        int iBase;             /* Base register of multi-key index record */
        int nPrefix;           /* Number of prior entires in the key */
        u8 eEndLoopOp;         /* IN Loop terminator. OP_Next or OP_Prev */
      } *aInLoop;           /* Information about each nested IN operator */
    } in;                 /* Used when pWLoop->wsFlags&WHERE_IN_ABLE */
    Index *pCovidx;       /* Possible covering index for WHERE_MULTI_OR */
    Index *pCoveringIdx;  /* Possible covering index for WHERE_MULTI_OR */
  } u;
  struct WhereLoop *pWLoop;  /* The selected WhereLoop object */
  Bitmask notReady;          /* FROM entries not usable at this level */
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
  int addrVisit;        /* Address at which row is visited */
#endif
};
122
123
124
125
126
127
128
129

130
131
132
133
134


135
136
137

138
139
140
141
142
143
144
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







-
+




-
+
+



+







  LogEst rRun;          /* Cost of running each loop */
  LogEst nOut;          /* Estimated number of output rows */
  union {
    struct {               /* Information for internal btree tables */
      u16 nEq;               /* Number of equality constraints */
      u16 nBtm;              /* Size of BTM vector */
      u16 nTop;              /* Size of TOP vector */
      u16 nIdxCol;           /* Index column used for ORDER BY */
      u16 nDistinctCol;      /* Index columns used to sort for DISTINCT */
      Index *pIndex;         /* Index used, or NULL */
    } btree;
    struct {               /* Information for virtual tables */
      int idxNum;            /* Index number */
      u8 needFree;           /* True if sqlite3_free(idxStr) is needed */
      u32 needFree : 1;      /* True if sqlite3_free(idxStr) is needed */
      u32 bOmitOffset : 1;   /* True to let virtual table handle offset */
      i8 isOrdered;          /* True if satisfies ORDER BY */
      u16 omitMask;          /* Terms that may be omitted */
      char *idxStr;          /* Index identifier string */
      u32 mHandleIn;         /* Terms to handle as IN(...) instead of == */
    } vtab;
  } u;
  u32 wsFlags;          /* WHERE_* flags describing the plan */
  u16 nLTerm;           /* Number of entries in aLTerm[] */
  u16 nSkip;            /* Number of NULL aLTerm[] entries */
  /**** whereLoopXfer() copies fields above ***********************/
# define WHERE_LOOP_XFER_SZ offsetof(WhereLoop,nLSlot)
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
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







-

+
-
+
+
+










-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
+
-
-
-
-
-
-
-
+
+
+
+

+
+
+
+
+
+
+










+
+

+
-
+
-
-
-







  LogEst truthProb;       /* Probability of truth for this expression */
  u16 wtFlags;            /* TERM_xxx bit flags.  See below */
  u16 eOperator;          /* A WO_xx value describing <op> */
  u8 nChild;              /* Number of children that must disable us */
  u8 eMatchOp;            /* Op for vtab MATCH/LIKE/GLOB/REGEXP terms */
  int iParent;            /* Disable pWC->a[iParent] when this term disabled */
  int leftCursor;         /* Cursor number of X in "X <op> <expr>" */
  int iField;             /* Field in (?,?,?) IN (SELECT...) vector */
  union {
    struct {
    int leftColumn;         /* Column number of X in "X <op> <expr>" */
      int leftColumn;         /* Column number of X in "X <op> <expr>" */
      int iField;             /* Field in (?,?,?) IN (SELECT...) vector */
    } x;                    /* Opcode other than OP_OR or OP_AND */
    WhereOrInfo *pOrInfo;   /* Extra information if (eOperator & WO_OR)!=0 */
    WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
  } u;
  Bitmask prereqRight;    /* Bitmask of tables used by pExpr->pRight */
  Bitmask prereqAll;      /* Bitmask of tables referenced by pExpr */
};

/*
** Allowed values of WhereTerm.wtFlags
*/
#define TERM_DYNAMIC    0x01   /* Need to call sqlite3ExprDelete(db, pExpr) */
#define TERM_VIRTUAL    0x02   /* Added by the optimizer.  Do not code */
#define TERM_CODED      0x04   /* This term is already coded */
#define TERM_COPIED     0x08   /* Has a child */
#define TERM_ORINFO     0x10   /* Need to free the WhereTerm.u.pOrInfo object */
#define TERM_ANDINFO    0x20   /* Need to free the WhereTerm.u.pAndInfo obj */
#define TERM_OR_OK      0x40   /* Used during OR-clause processing */
#define TERM_DYNAMIC    0x0001 /* Need to call sqlite3ExprDelete(db, pExpr) */
#define TERM_VIRTUAL    0x0002 /* Added by the optimizer.  Do not code */
#define TERM_CODED      0x0004 /* This term is already coded */
#define TERM_COPIED     0x0008 /* Has a child */
#define TERM_ORINFO     0x0010 /* Need to free the WhereTerm.u.pOrInfo object */
#define TERM_ANDINFO    0x0020 /* Need to free the WhereTerm.u.pAndInfo obj */
#define TERM_OK         0x0040 /* Used during OR-clause processing */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#  define TERM_VNULL    0x80   /* Manufactured x>NULL or x<=NULL term */
#define TERM_VNULL      0x0080 /* Manufactured x>NULL or x<=NULL term */
#else
#  define TERM_VNULL    0x00   /* Disabled if not using stat3 */
#endif
#define TERM_LIKEOPT    0x100  /* Virtual terms from the LIKE optimization */
#define TERM_LIKECOND   0x200  /* Conditionally this LIKE operator term */
#define TERM_LIKE       0x400  /* The original LIKE operator */
#define TERM_IS         0x800  /* Term.pExpr is an IS operator */
#define TERM_LIKEOPT    0x0100 /* Virtual terms from the LIKE optimization */
#define TERM_LIKECOND   0x0200 /* Conditionally this LIKE operator term */
#define TERM_LIKE       0x0400 /* The original LIKE operator */
#define TERM_IS         0x0800 /* Term.pExpr is an IS operator */
#define TERM_VARSELECT  0x1000 /* Term.pExpr contains a correlated sub-query */
#define TERM_HEURTRUTH  0x2000 /* Heuristic truthProb used */
#ifdef SQLITE_ENABLE_STAT4
#  define TERM_HIGHTRUTH  0x4000 /* Term excludes few rows */
#else
#  define TERM_HIGHTRUTH  0      /* Only used with STAT4 */
#endif
#define TERM_SLICE      0x8000 /* One slice of a row-value/vector comparison */

/*
** An instance of the WhereScan object is used as an iterator for locating
** terms in the WHERE clause that are useful to the query planner.
*/
struct WhereScan {
  WhereClause *pOrigWC;      /* Original, innermost WhereClause */
  WhereClause *pWC;          /* WhereClause currently being scanned */
  const char *zCollName;     /* Required collating sequence, if not NULL */
  Expr *pIdxExpr;            /* Search for this index expression */
  int k;                     /* Resume scanning at this->pWC->a[this->k] */
  u32 opMask;                /* Acceptable operators */
  char idxaff;               /* Must match this affinity, if zCollName!=NULL */
  unsigned char iEquiv;      /* Current slot in aiCur[] and aiColumn[] */
  unsigned char nEquiv;      /* Number of entries in aEquiv[] */
  unsigned char nEquiv;      /* Number of entries in aiCur[] and aiColumn[] */
  unsigned char iEquiv;      /* Next unused slot in aEquiv[] */
  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 */
};

/*
** An instance of the following structure holds all information about a
** WHERE clause.  Mostly this is a container for one or more WhereTerms.
321
322
323
324
325
326
327

328
329
330
331
332
333
334
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357







+







struct WhereClause {
  WhereInfo *pWInfo;       /* WHERE clause processing context */
  WhereClause *pOuter;     /* Outer conjunction */
  u8 op;                   /* Split operator.  TK_AND or TK_OR */
  u8 hasOr;                /* True if any a[].eOperator is WO_OR */
  int nTerm;               /* Number of terms */
  int nSlot;               /* Number of entries in a[] */
  int nBase;               /* Number of terms through the last non-Virtual */
  WhereTerm *a;            /* Each a[] describes a term of the WHERE cluase */
#if defined(SQLITE_SMALL_STACK)
  WhereTerm aStatic[1];    /* Initial static space for a[] */
#else
  WhereTerm aStatic[8];    /* Initial static space for a[] */
#endif
};
351
352
353
354
355
356
357
358

359
360
361
362
363
364
365
374
375
376
377
378
379
380

381
382
383
384
385
386
387
388







-
+







};

/*
** An instance of the following structure keeps track of a mapping
** between VDBE cursor numbers and bits of the bitmasks in WhereTerm.
**
** The VDBE cursor numbers are small integers contained in 
** SrcList_item.iCursor and Expr.iTable fields.  For any given WHERE 
** SrcItem.iCursor and Expr.iTable fields.  For any given WHERE 
** clause, the cursor numbers might not begin with 0 and they might
** contain gaps in the numbering sequence.  But we want to make maximum
** use of the bits in our bitmasks.  This structure provides a mapping
** from the sparse cursor numbers into consecutive integers beginning
** with 0.
**
** If WhereMaskSet.ix[A]==B it means that The A-th bit of a Bitmask
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
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







-
-
-
-
-







-


-
+



-
+
+




-
-
+
+
+
+







*/
struct WhereMaskSet {
  int bVarSelect;               /* Used by sqlite3WhereExprUsage() */
  int n;                        /* Number of assigned cursor values */
  int ix[BMS];                  /* Cursor assigned to each bit */
};

/*
** Initialize a WhereMaskSet object
*/
#define initMaskSet(P)  (P)->n=0

/*
** This object is a convenience wrapper holding all information needed
** to construct WhereLoop objects for a particular query.
*/
struct WhereLoopBuilder {
  WhereInfo *pWInfo;        /* Information about this WHERE */
  WhereClause *pWC;         /* WHERE clause terms */
  ExprList *pOrderBy;       /* ORDER BY clause */
  WhereLoop *pNew;          /* Template WhereLoop */
  WhereOrSet *pOrSet;       /* Record best loops here, if not NULL */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
  UnpackedRecord *pRec;     /* Probe for stat4 (if required) */
  int nRecValid;            /* Number of valid fields currently in pRec */
#endif
  unsigned int bldFlags;    /* SQLITE_BLDF_* flags */
  unsigned char bldFlags1;  /* First set of SQLITE_BLDF_* flags */
  unsigned char bldFlags2;  /* Second set of SQLITE_BLDF_* flags */
  unsigned int iPlanLimit;  /* Search limiter */
};

/* Allowed values for WhereLoopBuider.bldFlags */
#define SQLITE_BLDF_INDEXED  0x0001   /* An index is used */
#define SQLITE_BLDF_UNIQUE   0x0002   /* All keys of a UNIQUE index used */
#define SQLITE_BLDF1_INDEXED  0x0001   /* An index is used */
#define SQLITE_BLDF1_UNIQUE   0x0002   /* All keys of a UNIQUE index used */

#define SQLITE_BLDF2_2NDPASS  0x0004   /* Second builder pass needed */

/* The WhereLoopBuilder.iPlanLimit is used to limit the number of
** index+constraint combinations the query planner will consider for a
** particular query.  If this parameter is unlimited, then certain
** pathological queries can spend excess time in the sqlite3WhereBegin()
** routine.  The limit is high enough that is should not impact real-world
** queries.
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
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







+

+
-
+





+


-

-

+
+
-
+
+
+

+

+

-













+
+









+
+









+
+
+
+
+


+












+
+


+

+
+
+
+
+






+




-
+







** planner.
*/
struct WhereInfo {
  Parse *pParse;            /* Parsing and code generating context */
  SrcList *pTabList;        /* List of tables in the join */
  ExprList *pOrderBy;       /* The ORDER BY clause or NULL */
  ExprList *pResultSet;     /* Result set of the query */
#if WHERETRACE_ENABLED
  Expr *pWhere;             /* The complete WHERE clause */
#endif
  LogEst iLimit;            /* LIMIT if wctrlFlags has WHERE_USE_LIMIT */
  Select *pSelect;          /* The entire SELECT statement containing WHERE */
  int aiCurOnePass[2];      /* OP_OpenWrite cursors for the ONEPASS opt */
  int iContinue;            /* Jump here to continue with next record */
  int iBreak;               /* Jump here to break out of the loop */
  int savedNQueryLoop;      /* pParse->nQueryLoop outside the WHERE loop */
  u16 wctrlFlags;           /* Flags originally passed to sqlite3WhereBegin() */
  LogEst iLimit;            /* LIMIT if wctrlFlags has WHERE_USE_LIMIT */
  u8 nLevel;                /* Number of nested loop */
  i8 nOBSat;                /* Number of ORDER BY terms satisfied by indices */
  u8 sorted;                /* True if really sorted (not just grouped) */
  u8 eOnePass;              /* ONEPASS_OFF, or _SINGLE, or _MULTI */
  u8 untestedTerms;         /* Not all WHERE terms resolved by outer loop */
  u8 eDistinct;             /* One of the WHERE_DISTINCT_* values */
  unsigned bDeferredSeek :1;   /* Uses OP_DeferredSeek */
  unsigned untestedTerms :1;   /* Not all WHERE terms resolved by outer loop */
  u8 bOrderedInnerLoop;     /* True if only the inner-most loop is ordered */
  unsigned bOrderedInnerLoop:1;/* True if only the inner-most loop is ordered */
  unsigned sorted :1;          /* True if really sorted (not just grouped) */
  LogEst nRowOut;           /* Estimated number of output rows */
  int iTop;                 /* The very beginning of the WHERE loop */
  int iEndWhere;            /* End of the WHERE clause itself */
  WhereLoop *pLoops;        /* List of all WhereLoop objects */
  WhereMemBlock *pMemToFree;/* Memory to free when this object destroyed */
  Bitmask revMask;          /* Mask of ORDER BY terms that need reversing */
  LogEst nRowOut;           /* Estimated number of output rows */
  WhereClause sWC;          /* Decomposition of the WHERE clause */
  WhereMaskSet sMaskSet;    /* Map cursor numbers to bitmasks */
  WhereLevel a[1];          /* Information about each nest loop in WHERE */
};

/*
** Private interfaces - callable only by other where.c routines.
**
** where.c:
*/
Bitmask sqlite3WhereGetMask(WhereMaskSet*,int);
#ifdef WHERETRACE_ENABLED
void sqlite3WhereClausePrint(WhereClause *pWC);
void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm);
void sqlite3WhereLoopPrint(WhereLoop *p, WhereClause *pWC);
#endif
WhereTerm *sqlite3WhereFindTerm(
  WhereClause *pWC,     /* The WHERE clause to be searched */
  int iCur,             /* Cursor number of LHS */
  int iColumn,          /* Column number of LHS */
  Bitmask notReady,     /* RHS must not overlap with this mask */
  u32 op,               /* Mask of WO_xx values describing operator */
  Index *pIdx           /* Must be compatible with this index, if not NULL */
);
void *sqlite3WhereMalloc(WhereInfo *pWInfo, u64 nByte);
void *sqlite3WhereRealloc(WhereInfo *pWInfo, void *pOld, u64 nByte);

/* wherecode.c: */
#ifndef SQLITE_OMIT_EXPLAIN
int sqlite3WhereExplainOneScan(
  Parse *pParse,                  /* Parse context */
  SrcList *pTabList,              /* Table list this loop refers to */
  WhereLevel *pLevel,             /* Scan to write OP_Explain opcode for */
  u16 wctrlFlags                  /* Flags passed to sqlite3WhereBegin() */
);
int sqlite3WhereExplainBloomFilter(
  const Parse *pParse,            /* Parse context */
  const WhereInfo *pWInfo,        /* WHERE clause */
  const WhereLevel *pLevel        /* Bloom filter on this level */
);
#else
# define sqlite3WhereExplainOneScan(u,v,w,x) 0
# define sqlite3WhereExplainBloomFilter(u,v,w) 0
#endif /* SQLITE_OMIT_EXPLAIN */
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
void sqlite3WhereAddScanStatus(
  Vdbe *v,                        /* Vdbe to add scanstatus entry to */
  SrcList *pSrclist,              /* FROM clause pLvl reads data from */
  WhereLevel *pLvl,               /* Level to add scanstatus() entry for */
  int addrExplain                 /* Address of OP_Explain (or 0) */
);
#else
# define sqlite3WhereAddScanStatus(a, b, c, d) ((void)d)
#endif
Bitmask sqlite3WhereCodeOneLoopStart(
  Parse *pParse,       /* Parsing context */
  Vdbe *v,             /* Prepared statement under construction */
  WhereInfo *pWInfo,   /* Complete information about the WHERE clause */
  int iLevel,          /* Which level of pWInfo->a[] should be coded */
  WhereLevel *pLevel,  /* The current level pointer */
  Bitmask notReady     /* Which tables are currently available */
);
SQLITE_NOINLINE void sqlite3WhereRightJoinLoop(
  WhereInfo *pWInfo,
  int iLevel,
  WhereLevel *pLevel
);

/* whereexpr.c: */
void sqlite3WhereClauseInit(WhereClause*,WhereInfo*);
void sqlite3WhereClauseClear(WhereClause*);
void sqlite3WhereSplit(WhereClause*,Expr*,u8);
void sqlite3WhereAddLimit(WhereClause*, Select*);
Bitmask sqlite3WhereExprUsage(WhereMaskSet*, Expr*);
Bitmask sqlite3WhereExprUsageNN(WhereMaskSet*, Expr*);
Bitmask sqlite3WhereExprListUsage(WhereMaskSet*, ExprList*);
void sqlite3WhereExprAnalyze(SrcList*, WhereClause*);
void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereClause*);
void sqlite3WhereTabFuncArgs(Parse*, SrcItem*, WhereClause*);





/*
** Bitmasks for the operators on WhereTerm objects.  These are all
548
549
550
551
552
553
554

555
556

557
558
559
560
561
562
563
593
594
595
596
597
598
599
600
601

602
603
604
605
606
607
608
609







+

-
+







#define WO_AUX    0x0040       /* Op useful to virtual tables only */
#define WO_IS     0x0080
#define WO_ISNULL 0x0100
#define WO_OR     0x0200       /* Two or more OR-connected terms */
#define WO_AND    0x0400       /* Two or more AND-connected terms */
#define WO_EQUIV  0x0800       /* Of the form A==B, both columns */
#define WO_NOOP   0x1000       /* This term does not restrict search space */
#define WO_ROWVAL 0x2000       /* A row-value term */

#define WO_ALL    0x1fff       /* Mask of all possible WO_* values */
#define WO_ALL    0x3fff       /* Mask of all possible WO_* values */
#define WO_SINGLE 0x01ff       /* Mask of all non-compound WO_* values */

/*
** These are definitions of bits in the WhereLoop.wsFlags field.
** The particular combination of bits in each WhereLoop help to
** determine the algorithm that WhereLoop represents.
*/
577
578
579
580
581
582
583










623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639







+
+
+
+
+
+
+
+
+
+
#define WHERE_ONEROW       0x00001000  /* Selects no more than one row */
#define WHERE_MULTI_OR     0x00002000  /* OR using multiple indices */
#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 */
#define WHERE_BLOOMFILTER  0x00400000  /* Consider using a Bloom-filter */
#define WHERE_SELFCULL     0x00800000  /* nOut reduced by extra WHERE terms */
#define WHERE_OMIT_OFFSET  0x01000000  /* Set offset counter to zero */
#define WHERE_VIEWSCAN     0x02000000  /* A full-scan of a VIEW or subquery */
#define WHERE_EXPRIDX      0x04000000  /* Uses an index-on-expressions */

#endif /* !defined(SQLITE_WHEREINT_H) */

Changes to src/wherecode.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







-
+







/*
** Return the name of the i-th column of the pIdx index.
*/
static const char *explainIndexColumnName(Index *pIdx, int i){
  i = pIdx->aiColumn[i];
  if( i==XN_EXPR ) return "<expr>";
  if( i==XN_ROWID ) return "rowid";
  return pIdx->pTable->aCol[i].zName;
  return pIdx->pTable->aCol[i].zCnName;
}

/*
** This routine is a helper for explainIndexRange() below
**
** pStr holds the text of an expression that we are building up one term
** at a time.  This routine adds a new term to the end of the expression.
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
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







-
+


















-
-
-
-
-
-
-
+
-
-
+
-







  u16 wctrlFlags                  /* Flags passed to sqlite3WhereBegin() */
){
  int ret = 0;
#if !defined(SQLITE_DEBUG) && !defined(SQLITE_ENABLE_STMT_SCANSTATUS)
  if( sqlite3ParseToplevel(pParse)->explain==2 )
#endif
  {
    struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom];
    SrcItem *pItem = &pTabList->a[pLevel->iFrom];
    Vdbe *v = pParse->pVdbe;      /* VM being constructed */
    sqlite3 *db = pParse->db;     /* Database handle */
    int isSearch;                 /* True for a SEARCH. False for SCAN. */
    WhereLoop *pLoop;             /* The controlling WhereLoop object */
    u32 flags;                    /* Flags that describe this loop */
    char *zMsg;                   /* Text to add to EQP output */
    StrAccum str;                 /* EQP output string */
    char zBuf[100];               /* Initial space for EQP output string */

    pLoop = pLevel->pWLoop;
    flags = pLoop->wsFlags;
    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) );
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
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







+
+
+
+
+
+
-
+
+
+

-
+

+
-
+

-
+


-
+

-
+
-







+
+
+









+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




















+
+
+
-
+



+




+
+
+
+
+
+
+
+
+







      }
      if( zFmt ){
        sqlite3_str_append(&str, " USING ", 7);
        sqlite3_str_appendf(&str, zFmt, pIdx->zName);
        explainIndexRange(&str, pLoop);
      }
    }else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){
      char cRangeOp;
#if 0  /* Better output, but breaks many tests */
      const Table *pTab = pItem->pTab;
      const char *zRowid = pTab->iPKey>=0 ? pTab->aCol[pTab->iPKey].zCnName:
                              "rowid";
#else
      const char *zRangeOp;
      const char *zRowid = "rowid";
#endif
      sqlite3_str_appendf(&str, " USING INTEGER PRIMARY KEY (%s", zRowid);
      if( flags&(WHERE_COLUMN_EQ|WHERE_COLUMN_IN) ){
        zRangeOp = "=";
        cRangeOp = '=';
      }else if( (flags&WHERE_BOTH_LIMIT)==WHERE_BOTH_LIMIT ){
        sqlite3_str_appendf(&str, ">? AND %s", zRowid);
        zRangeOp = ">? AND rowid<";
        cRangeOp = '<';
      }else if( flags&WHERE_BTM_LIMIT ){
        zRangeOp = ">";
        cRangeOp = '>';
      }else{
        assert( flags&WHERE_TOP_LIMIT);
        zRangeOp = "<";
        cRangeOp = '<';
      }
      sqlite3_str_appendf(&str, 
      sqlite3_str_appendf(&str, "%c?)", cRangeOp);
          " USING INTEGER PRIMARY KEY (rowid%s?)",zRangeOp);
    }
#ifndef SQLITE_OMIT_VIRTUALTABLE
    else if( (flags & WHERE_VIRTUALTABLE)!=0 ){
      sqlite3_str_appendf(&str, " VIRTUAL TABLE INDEX %d:%s",
                  pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr);
    }
#endif
    if( pItem->fg.jointype & JT_LEFT ){
      sqlite3_str_appendf(&str, " LEFT-JOIN");
    }
#ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS
    if( pLoop->nOut>=10 ){
      sqlite3_str_appendf(&str, " (~%llu rows)",
             sqlite3LogEstToInt(pLoop->nOut));
    }else{
      sqlite3_str_append(&str, " (~1 row)", 9);
    }
#endif
    zMsg = sqlite3StrAccumFinish(&str);
    sqlite3ExplainBreakpoint("",zMsg);
    ret = sqlite3VdbeAddOp4(v, OP_Explain, sqlite3VdbeCurrentAddr(v),
                            pParse->addrExplain, 0, zMsg,P4_DYNAMIC);
  }
  return ret;
}

/*
** Add a single OP_Explain opcode that describes a Bloom filter.
**
** Or if not processing EXPLAIN QUERY PLAN and not in a SQLITE_DEBUG and/or
** SQLITE_ENABLE_STMT_SCANSTATUS build, then OP_Explain opcodes are not
** required and this routine is a no-op.
**
** If an OP_Explain opcode is added to the VM, its address is returned.
** Otherwise, if no OP_Explain is coded, zero is returned.
*/
int sqlite3WhereExplainBloomFilter(
  const Parse *pParse,               /* Parse context */
  const WhereInfo *pWInfo,           /* WHERE clause */
  const WhereLevel *pLevel           /* Bloom filter on this level */
){
  int ret = 0;
  SrcItem *pItem = &pWInfo->pTabList->a[pLevel->iFrom];
  Vdbe *v = pParse->pVdbe;      /* VM being constructed */
  sqlite3 *db = pParse->db;     /* Database handle */
  char *zMsg;                   /* Text to add to EQP output */
  int i;                        /* Loop counter */
  WhereLoop *pLoop;             /* The where loop */
  StrAccum str;                 /* EQP output string */
  char zBuf[100];               /* Initial space for EQP output string */

  sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH);
  str.printfFlags = SQLITE_PRINTF_INTERNAL;
  sqlite3_str_appendf(&str, "BLOOM FILTER ON %S (", pItem);
  pLoop = pLevel->pWLoop;
  if( pLoop->wsFlags & WHERE_IPK ){
    const Table *pTab = pItem->pTab;
    if( pTab->iPKey>=0 ){
      sqlite3_str_appendf(&str, "%s=?", pTab->aCol[pTab->iPKey].zCnName);
    }else{
      sqlite3_str_appendf(&str, "rowid=?");
    }
  }else{
    for(i=pLoop->nSkip; i<pLoop->u.btree.nEq; i++){
      const char *z = explainIndexColumnName(pLoop->u.btree.pIndex, i);
      if( i>pLoop->nSkip ) sqlite3_str_append(&str, " AND ", 5);
      sqlite3_str_appendf(&str, "%s=?", z);
    }
  }
  sqlite3_str_append(&str, ")", 1);
  zMsg = sqlite3StrAccumFinish(&str);
  ret = sqlite3VdbeAddOp4(v, OP_Explain, sqlite3VdbeCurrentAddr(v),
                          pParse->addrExplain, 0, zMsg,P4_DYNAMIC);

  sqlite3VdbeScanStatus(v, sqlite3VdbeCurrentAddr(v)-1, 0, 0, 0, 0);
  return ret;
}
#endif /* SQLITE_OMIT_EXPLAIN */

#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
/*
** Configure the VM passed as the first argument with an
** sqlite3_stmt_scanstatus() entry corresponding to the scan used to 
** implement level pLvl. Argument pSrclist is a pointer to the FROM 
** clause that the scan reads data from.
**
** If argument addrExplain is not 0, it must be the address of an 
** OP_Explain instruction that describes the same loop.
*/
void sqlite3WhereAddScanStatus(
  Vdbe *v,                        /* Vdbe to add scanstatus entry to */
  SrcList *pSrclist,              /* FROM clause pLvl reads data from */
  WhereLevel *pLvl,               /* Level to add scanstatus() entry for */
  int addrExplain                 /* Address of OP_Explain (or 0) */
){
  const char *zObj = 0;
  WhereLoop *pLoop = pLvl->pWLoop;
  int wsFlags = pLoop->wsFlags;
  int viaCoroutine = 0;

  if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0  &&  pLoop->u.btree.pIndex!=0 ){
  if( (wsFlags & WHERE_VIRTUALTABLE)==0  &&  pLoop->u.btree.pIndex!=0 ){
    zObj = pLoop->u.btree.pIndex->zName;
  }else{
    zObj = pSrclist->a[pLvl->iFrom].zName;
    viaCoroutine = pSrclist->a[pLvl->iFrom].fg.viaCoroutine;
  }
  sqlite3VdbeScanStatus(
      v, addrExplain, pLvl->addrBody, pLvl->addrVisit, pLoop->nOut, zObj
  );

  if( viaCoroutine==0 ){
    if( (wsFlags & (WHERE_MULTI_OR|WHERE_AUTO_INDEX))==0 ){
      sqlite3VdbeScanStatusRange(v, addrExplain, -1, pLvl->iTabCur);
    }
    if( wsFlags & WHERE_INDEXED ){
      sqlite3VdbeScanStatusRange(v, addrExplain, -1, pLvl->iIdxCur);
    }
  }
}
#endif


/*
** Disable a term in the WHERE clause.  Except, do not disable the term
** if it controls a LEFT OUTER JOIN and it did not originate in the ON
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
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







-
+







+
+
+
+
+
+













-
-
-
+
+
+












-
-
+
+

+
-
+




-
+







** a conditional such that is only evaluated on the second pass of a
** LIKE-optimization loop, when scanning BLOBs instead of strings.
*/
static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
  int nLoop = 0;
  assert( pTerm!=0 );
  while( (pTerm->wtFlags & TERM_CODED)==0
      && (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin))
      && (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_OuterON))
      && (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 & 0x4001)==0x4001 ){
      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++;
  }
}

/*
** Code an OP_Affinity opcode to apply the column affinity string zAff
** to the n registers starting at base. 
**
** As an optimization, SQLITE_AFF_BLOB entries (which are no-ops) at the
** beginning and end of zAff are ignored.  If all entries in zAff are
** SQLITE_AFF_BLOB, then no code gets generated.
** As an optimization, SQLITE_AFF_BLOB and SQLITE_AFF_NONE entries (which
** are no-ops) at the beginning and end of zAff are ignored.  If all entries
** in zAff are SQLITE_AFF_BLOB or SQLITE_AFF_NONE, then no code gets generated.
**
** This routine makes its own copy of zAff so that the caller is free
** to modify zAff after this routine returns.
*/
static void codeApplyAffinity(Parse *pParse, int base, int n, char *zAff){
  Vdbe *v = pParse->pVdbe;
  if( zAff==0 ){
    assert( pParse->db->mallocFailed );
    return;
  }
  assert( v!=0 );

  /* Adjust base and n to skip over SQLITE_AFF_BLOB entries at the beginning
  ** and end of the affinity string.
  /* Adjust base and n to skip over SQLITE_AFF_BLOB and SQLITE_AFF_NONE
  ** entries at the beginning and end of the affinity string.
  */
  assert( SQLITE_AFF_NONE<SQLITE_AFF_BLOB );
  while( n>0 && zAff[0]==SQLITE_AFF_BLOB ){
  while( n>0 && zAff[0]<=SQLITE_AFF_BLOB ){
    n--;
    base++;
    zAff++;
  }
  while( n>1 && zAff[n-1]==SQLITE_AFF_BLOB ){
  while( n>1 && zAff[n-1]<=SQLITE_AFF_BLOB ){
    n--;
  }

  /* Code the OP_Affinity opcode if there is anything left to do. */
  if( n>0 ){
    sqlite3VdbeAddOp4(v, OP_Affinity, base, n, 0, zAff, n);
  }
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
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







+
-
+

-
-
+
+





+
+
+
+
+


+
+
-
+







static Expr *removeUnindexableInClauseTerms(
  Parse *pParse,        /* The parsing context */
  int iEq,              /* Look at loop terms starting here */
  WhereLoop *pLoop,     /* The current loop */
  Expr *pX              /* The IN expression to be reduced */
){
  sqlite3 *db = pParse->db;
  Expr *pNew;
  Expr *pNew = sqlite3ExprDup(db, pX, 0);
  pNew = sqlite3ExprDup(db, pX, 0);
  if( db->mallocFailed==0 ){
    ExprList *pOrigRhs = pNew->x.pSelect->pEList;  /* Original unmodified RHS */
    ExprList *pOrigLhs = pNew->pLeft->x.pList;     /* Original unmodified LHS */
    ExprList *pOrigRhs;         /* Original unmodified RHS */
    ExprList *pOrigLhs;         /* Original unmodified LHS */
    ExprList *pRhs = 0;         /* New RHS after modifications */
    ExprList *pLhs = 0;         /* New LHS after mods */
    int i;                      /* Loop counter */
    Select *pSelect;            /* Pointer to the SELECT on the RHS */

    assert( ExprUseXSelect(pNew) );
    pOrigRhs = pNew->x.pSelect->pEList;
    assert( pNew->pLeft!=0 );
    assert( ExprUseXList(pNew->pLeft) );
    pOrigLhs = pNew->pLeft->x.pList;
    for(i=iEq; i<pLoop->nLTerm; i++){
      if( pLoop->aLTerm[i]->pExpr==pX ){
        int iField;
        assert( (pLoop->aLTerm[i]->eOperator & (WO_OR|WO_AND))==0 );
        int iField = pLoop->aLTerm[i]->iField - 1;
        iField = pLoop->aLTerm[i]->u.x.iField - 1;
        if( pOrigRhs->a[iField].pExpr==0 ) continue; /* Duplicate PK column */
        pRhs = sqlite3ExprListAppend(pParse, pRhs, pOrigRhs->a[iField].pExpr);
        pOrigRhs->a[iField].pExpr = 0;
        assert( pOrigLhs->a[iField].pExpr!=0 );
        pLhs = sqlite3ExprListAppend(pParse, pLhs, pOrigLhs->a[iField].pExpr);
        pOrigLhs->a[iField].pExpr = 0;
      }
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
618
619
620
621
622
623
624
625


626
627
628
629
630


631
632








633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650

651
652
653

654
655
656
657

658
659
660
661
662
663
664
665
666
667


668
669
670
671
672
673
674
675
676
677

678
679
680
681
682
683
684
685
686

687
688
689

690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725

726
727
728
729
730
731
732
733
734
735







+
-
-
+
+

+
+
-
-
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+






-



-

+


-
+
+
+
+





+
-
-
+
+








-









-
+


-









+
+
+
+
+
+
+
+






+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+







      }
    }
    for(i=iEq;i<pLoop->nLTerm; i++){
      assert( pLoop->aLTerm[i]!=0 );
      if( pLoop->aLTerm[i]->pExpr==pX ) nEq++;
    }

    iTab = 0;
    if( (pX->flags & EP_xIsSelect)==0 || pX->x.pSelect->pEList->nExpr==1 ){
      eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0);
    if( !ExprUseXSelect(pX) || pX->x.pSelect->pEList->nExpr==1 ){
      eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0, &iTab);
    }else{
      Expr *pExpr = pTerm->pExpr;
      if( pExpr->iTable==0 || !ExprHasProperty(pExpr, EP_Subrtn) ){
      sqlite3 *db = pParse->db;
      pX = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX);
        sqlite3 *db = pParse->db;
        pX = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX);

      if( !db->mallocFailed ){
        aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq);
        eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap);
        pTerm->pExpr->iTable = pX->iTable;
      }
      sqlite3ExprDelete(db, pX);
      pX = pTerm->pExpr;
        if( !db->mallocFailed ){
          aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq);
          eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap,&iTab);
          pExpr->iTable = iTab;
        }
        sqlite3ExprDelete(db, pX);
      }else{
        int n = sqlite3ExprVectorSize(pX->pLeft);
        aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*MAX(nEq,n));
        eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap, &iTab);
      }
      pX = pExpr;
    }

    if( eType==IN_INDEX_INDEX_DESC ){
      testcase( bRev );
      bRev = !bRev;
    }
    iTab = pX->iTable;
    sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
    VdbeCoverageIf(v, bRev);
    VdbeCoverageIf(v, !bRev);
    assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );

    assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
    pLoop->wsFlags |= WHERE_IN_ABLE;
    if( pLevel->u.in.nIn==0 ){
      pLevel->addrNxt = sqlite3VdbeMakeLabel(v);
      pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse);
    }
    if( iEq>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0 ){
      pLoop->wsFlags |= WHERE_IN_EARLYOUT;
    }

    i = pLevel->u.in.nIn;
    pLevel->u.in.nIn += nEq;
    pLevel->u.in.aInLoop =
       sqlite3WhereRealloc(pTerm->pWC->pWInfo,
       sqlite3DbReallocOrFree(pParse->db, pLevel->u.in.aInLoop,
                              sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn);
                           pLevel->u.in.aInLoop,
                           sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn);
    pIn = pLevel->u.in.aInLoop;
    if( pIn ){
      int iMap = 0;               /* Index in aiMap[] */
      pIn += i;
      for(i=iEq;i<pLoop->nLTerm; i++){
        if( pLoop->aLTerm[i]->pExpr==pX ){
          int iOut = iReg + i - iEq;
          if( eType==IN_INDEX_ROWID ){
            testcase( nEq>1 );  /* Happens with a UNIQUE index on ROWID */
            pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iOut);
          }else{
            int iCol = aiMap ? aiMap[iMap++] : 0;
            pIn->addrInTop = sqlite3VdbeAddOp3(v,OP_Column,iTab, iCol, iOut);
          }
          sqlite3VdbeAddOp1(v, OP_IsNull, iOut); VdbeCoverage(v);
          if( i==iEq ){
            pIn->iCur = iTab;
            pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next;
            if( iEq>0 && (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 ){
            if( iEq>0 ){
              pIn->iBase = iReg - i;
              pIn->nPrefix = i;
              pLoop->wsFlags |= WHERE_IN_EARLYOUT;
            }else{
              pIn->nPrefix = 0;
            }
          }else{
            pIn->eEndLoopOp = OP_Noop;
          }
          pIn++;
        }
      }
      testcase( iEq>0
                && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0
                && (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 );
      if( iEq>0 
       && (pLoop->wsFlags & (WHERE_IN_SEEKSCAN|WHERE_VIRTUALTABLE))==0
      ){
        sqlite3VdbeAddOp3(v, OP_SeekHit, pLevel->iIdxCur, 0, iEq);
      }
    }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.
**
692
693
694
695
696
697
698

699
700
701
702
703

704
705
706
707
708
709
710
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827







+





+







  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);
    assert( pLevel->addrSkip==0 );
    pLevel->addrSkip = sqlite3VdbeAddOp4Int(v, (bRev?OP_SeekLT:OP_SeekGT),
                            iIdxCur, 0, regBase, nSkip);
    VdbeCoverageIf(v, bRev==0);
    VdbeCoverageIf(v, bRev!=0);
    sqlite3VdbeJumpHere(v, j);
    for(j=0; j<nSkip; j++){
      sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, j, regBase+j);
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
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







-
+


+
+
+














-
+
+







    testcase( pTerm->wtFlags & TERM_VIRTUAL );
    r1 = codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, regBase+j);
    if( r1!=regBase+j ){
      if( nReg==1 ){
        sqlite3ReleaseTempReg(pParse, regBase);
        regBase = r1;
      }else{
        sqlite3VdbeAddOp2(v, OP_SCopy, r1, regBase+j);
        sqlite3VdbeAddOp2(v, OP_Copy, r1, regBase+j);
      }
    }
  }
  for(j=nSkip; j<nEq; j++){
    pTerm = pLoop->aLTerm[j];
    if( pTerm->eOperator & WO_IN ){
      if( pTerm->pExpr->flags & EP_xIsSelect ){
        /* No affinity ever needs to be (or should be) applied to a value
        ** from the RHS of an "? IN (SELECT ...)" expression. The 
        ** sqlite3FindInIndex() routine has already ensured that the 
        ** affinity of the comparison has been applied to the value.  */
        if( zAff ) zAff[j] = SQLITE_AFF_BLOB;
      }
    }else if( (pTerm->eOperator & WO_ISNULL)==0 ){
      Expr *pRight = pTerm->pExpr->pRight;
      if( (pTerm->wtFlags & TERM_IS)==0 && sqlite3ExprCanBeNull(pRight) ){
        sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk);
        VdbeCoverage(v);
      }
      if( zAff ){
      if( pParse->nErr==0 ){
        assert( 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;
        }
      }
783
784
785
786
787
788
789
790

791
792
793
794
795
796
797
904
905
906
907
908
909
910

911
912
913
914
915
916
917
918







-
+







  Vdbe *v,                /* prepared statement under construction */
  WhereLevel *pLevel,     /* The loop that contains the LIKE operator */
  WhereTerm *pTerm        /* The upper or lower bound just coded */
){
  if( pTerm->wtFlags & TERM_LIKEOPT ){
    VdbeOp *pOp;
    assert( pLevel->iLikeRepCntr>0 );
    pOp = sqlite3VdbeGetOp(v, -1);
    pOp = sqlite3VdbeGetLastOp(v);
    assert( pOp!=0 );
    assert( pOp->opcode==OP_String8 
            || pTerm->pWC->pWInfo->pParse->db->mallocFailed );
    pOp->p3 = (int)(pLevel->iLikeRepCntr>>1);  /* Register holding counter */
    pOp->p5 = (u8)(pLevel->iLikeRepCntr&1);    /* ASC or DESC */
  }
}
818
819
820
821
822
823
824
825

826
827
828
829
830
831
832
939
940
941
942
943
944
945

946
947
948
949
950
951
952
953







-
+







** accessed through the index.  If it cannot, then set pWalker->eCode to 1.
*/
static int codeCursorHintCheckExpr(Walker *pWalker, Expr *pExpr){
  struct CCurHint *pHint = pWalker->u.pCCurHint;
  assert( pHint->pIdx!=0 );
  if( pExpr->op==TK_COLUMN
   && pExpr->iTable==pHint->iTabCur
   && sqlite3ColumnOfIndex(pHint->pIdx, pExpr->iColumn)<0
   && sqlite3TableColumnToIndex(pHint->pIdx, pExpr->iColumn)<0
  ){
    pWalker->eCode = 1;
  }
  return WRC_Continue;
}

/*
886
887
888
889
890
891
892
893

894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913

914
915
916
917
918
919
920
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







-
+



















-
+







    if( pExpr->iTable!=pHint->iTabCur ){
      int reg = ++pWalker->pParse->nMem;   /* Register for column value */
      sqlite3ExprCode(pWalker->pParse, pExpr, reg);
      pExpr->op = TK_REGISTER;
      pExpr->iTable = reg;
    }else if( pHint->pIdx!=0 ){
      pExpr->iTable = pHint->iIdxCur;
      pExpr->iColumn = sqlite3ColumnOfIndex(pHint->pIdx, pExpr->iColumn);
      pExpr->iColumn = sqlite3TableColumnToIndex(pHint->pIdx, pExpr->iColumn);
      assert( pExpr->iColumn>=0 );
    }
  }else if( pExpr->op==TK_AGG_FUNCTION ){
    /* An aggregate function in the WHERE clause of a query means this must
    ** be a correlated sub-query, and expression pExpr is an aggregate from
    ** the parent context. Do not walk the function arguments in this case.
    **
    ** todo: It should be possible to replace this node with a TK_REGISTER
    ** expression, as the result of the expression must be stored in a 
    ** register at this point. The same holds for TK_AGG_COLUMN nodes. */
    rc = WRC_Prune;
  }
  return rc;
}

/*
** Insert an OP_CursorHint instruction if it is appropriate to do so.
*/
static void codeCursorHint(
  struct SrcList_item *pTabItem,  /* FROM clause item */
  SrcItem *pTabItem,  /* FROM clause item */
  WhereInfo *pWInfo,    /* The where clause */
  WhereLevel *pLevel,   /* Which loop to provide hints for */
  WhereTerm *pEndRange  /* Hint this end-of-scan boundary term if not NULL */
){
  Parse *pParse = pWInfo->pParse;
  sqlite3 *db = pParse->db;
  Vdbe *v = pParse->pVdbe;
933
934
935
936
937
938
939
940

941
942
943
944
945
946
947
1054
1055
1056
1057
1058
1059
1060

1061
1062
1063
1064
1065
1066
1067
1068







-
+







  sHint.iTabCur = iCur;
  sHint.iIdxCur = pLevel->iIdxCur;
  sHint.pIdx = pLoop->u.btree.pIndex;
  memset(&sWalker, 0, sizeof(sWalker));
  sWalker.pParse = pParse;
  sWalker.u.pCCurHint = &sHint;
  pWC = &pWInfo->sWC;
  for(i=0; i<pWC->nTerm; i++){
  for(i=0; i<pWC->nBase; i++){
    pTerm = &pWC->a[i];
    if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
    if( pTerm->prereqAll & pLevel->notReady ) continue;

    /* Any terms specified as part of the ON(...) clause for any LEFT 
    ** JOIN for which the current table is not the rhs are omitted
    ** from the cursor-hint. 
962
963
964
965
966
967
968
969
970


971
972
973
974
975
976
977
978

979
980
981
982
983
984
985
1083
1084
1085
1086
1087
1088
1089


1090
1091
1092
1093
1094
1095
1096
1097
1098

1099
1100
1101
1102
1103
1104
1105
1106







-
-
+
+







-
+







    **
    **   WHERE 1 = (t2.c IS NULL)
    **
    ** are also excluded. See codeCursorHintIsOrFunction() for details.
    */
    if( pTabItem->fg.jointype & JT_LEFT ){
      Expr *pExpr = pTerm->pExpr;
      if( !ExprHasProperty(pExpr, EP_FromJoin) 
       || pExpr->iRightJoinTable!=pTabItem->iCursor
      if( !ExprHasProperty(pExpr, EP_OuterON) 
       || pExpr->w.iJoin!=pTabItem->iCursor
      ){
        sWalker.eCode = 0;
        sWalker.xExprCallback = codeCursorHintIsOrFunction;
        sqlite3WalkExpr(&sWalker, pTerm->pExpr);
        if( sWalker.eCode ) continue;
      }
    }else{
      if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) continue;
      if( ExprHasProperty(pTerm->pExpr, EP_OuterON) ) continue;
    }

    /* All terms in pWLoop->aLTerm[] except pEndRange are used to initialize
    ** the cursor.  These terms are not needed as hints for a pure range
    ** scan (that has no == terms) so omit them. */
    if( pLoop->u.btree.nEq==0 && pTerm!=pEndRange ){
      for(j=0; j<pLoop->nLTerm && pLoop->aLTerm[j]!=pTerm; j++){}
995
996
997
998
999
1000
1001
1002

1003
1004
1005
1006
1007
1008
1009
1116
1117
1118
1119
1120
1121
1122

1123
1124
1125
1126
1127
1128
1129
1130







-
+







      sWalker.eCode = 0;
      sWalker.xExprCallback = codeCursorHintCheckExpr;
      sqlite3WalkExpr(&sWalker, pTerm->pExpr);
      if( sWalker.eCode ) continue;
    }

    /* If we survive all prior tests, that means this term is worth hinting */
    pExpr = sqlite3ExprAnd(db, pExpr, sqlite3ExprDup(db, pTerm->pExpr, 0));
    pExpr = sqlite3ExprAnd(pParse, pExpr, sqlite3ExprDup(db, pTerm->pExpr, 0));
  }
  if( pExpr!=0 ){
    sWalker.xExprCallback = codeCursorHintFixExpr;
    sqlite3WalkExpr(&sWalker, pExpr);
    sqlite3VdbeAddOp4(v, OP_CursorHint, 
                      (sHint.pIdx ? sHint.iIdxCur : sHint.iTabCur), 0, 0,
                      (const char*)pExpr, P4_EXPR);
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
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
1318
1319




1320
1321
1322
1323
1324
1325
1326
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
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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
1430
1431
1432
1433

1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447


1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478


1479
1480
1481
1482
1483
1484
1485

1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497


1498
1499
1500





1501
1502
1503





1504
1505
1506
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
1546








+
+

-
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+













+

-
+




-
+



+

-
+
+
+
+



















-
+

+
+
-
+





+
+
-
+






-
+




-
-
-
+
+
+
+
+
+

-
-
-
-
+
+
+
+
+
+
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
+




+
+
+
+
+
+
-
+
-
-
+
+
+
+
+
+

-
-
+
+
-
-
-
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








+
+


+





-

-



-

-
-
+








-
-


-





-
-

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+











-
-
+
+





-
+










-
+
+
+
+




















-








+
+
+
+
+
+
-
-
+
+
+



+
+
+
+
+
+
+
+
+









+
+
+



+
-
-
+
+



+
+
-
+
+
+
+



+




-
-
+
+
+
-
-
-
-
-
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+

-
+
+

-
-
-
+
+
+
+
+
+
+
+
+
+
+
+



-
+
+
+


+
-
-
-
-
+
+
+
+







** a rowid value just read from cursor iIdxCur, open on index pIdx. This
** function generates code to do a deferred seek of cursor iCur to the 
** rowid stored in register iRowid.
**
** Normally, this is just:
**
**   OP_DeferredSeek $iCur $iRowid
**
** Which causes a seek on $iCur to the row with rowid $iRowid.
**
** However, if the scan currently being coded is a branch of an OR-loop and
** the statement currently being coded is a SELECT, then P3 of OP_DeferredSeek
** the statement currently being coded is a SELECT, then additional information
** is set to iIdxCur and P4 is set to point to an array of integers
** containing one entry for each column of the table cursor iCur is open 
** on. For each table column, if the column is the i'th column of the 
** index, then the corresponding array entry is set to (i+1). If the column
** does not appear in the index at all, the array entry is set to 0.
** is added that might allow OP_Column to omit the seek and instead do its
** lookup on the index, thus avoiding an expensive seek operation.  To
** enable this optimization, the P3 of OP_DeferredSeek is set to iIdxCur
** and P4 is set to an array of integers containing one entry for each column
** in the table.  For each table column, if the column is the i'th
** column of the index, then the corresponding array entry is set to (i+1).
** If the column does not appear in the index at all, the array entry is set
** to 0.  The OP_Column opcode can check this array to see if the column it
** wants is in the index and if it is, it will substitute the index cursor
** and column number and continue with those new values, rather than seeking
** the table cursor.
*/
static void codeDeferredSeek(
  WhereInfo *pWInfo,              /* Where clause context */
  Index *pIdx,                    /* Index scan is using */
  int iCur,                       /* Cursor for IPK b-tree */
  int iIdxCur                     /* Index cursor */
){
  Parse *pParse = pWInfo->pParse; /* Parse context */
  Vdbe *v = pParse->pVdbe;        /* Vdbe to generate code within */

  assert( iIdxCur>0 );
  assert( pIdx->aiColumn[pIdx->nColumn-1]==-1 );
  
  pWInfo->bDeferredSeek = 1;
  sqlite3VdbeAddOp3(v, OP_DeferredSeek, iIdxCur, 0, iCur);
  if( (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)
  if( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))
   && DbMaskAllZero(sqlite3ParseToplevel(pParse)->writeMask)
  ){
    int i;
    Table *pTab = pIdx->pTable;
    int *ai = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*(pTab->nCol+1));
    u32 *ai = (u32*)sqlite3DbMallocZero(pParse->db, sizeof(u32)*(pTab->nCol+1));
    if( ai ){
      ai[0] = pTab->nCol;
      for(i=0; i<pIdx->nColumn-1; i++){
        int x1, x2;
        assert( pIdx->aiColumn[i]<pTab->nCol );
        if( pIdx->aiColumn[i]>=0 ) ai[pIdx->aiColumn[i]+1] = i+1;
        x1 = pIdx->aiColumn[i];
        x2 = sqlite3TableColumnToStorage(pTab, x1);
        testcase( x1!=x2 );
        if( x1>=0 ) ai[x2+1] = i+1;
      }
      sqlite3VdbeChangeP4(v, -1, (char*)ai, P4_INTARRAY);
    }
  }
}

/*
** If the expression passed as the second argument is a vector, generate
** code to write the first nReg elements of the vector into an array
** of registers starting with iReg.
**
** If the expression is not a vector, then nReg must be passed 1. In
** this case, generate code to evaluate the expression and leave the
** result in register iReg.
*/
static void codeExprOrVector(Parse *pParse, Expr *p, int iReg, int nReg){
  assert( nReg>0 );
  if( p && sqlite3ExprIsVector(p) ){
#ifndef SQLITE_OMIT_SUBQUERY
    if( (p->flags & EP_xIsSelect) ){
    if( ExprUseXSelect(p) ){
      Vdbe *v = pParse->pVdbe;
      int iSelect;
      assert( p->op==TK_SELECT );
      int iSelect = sqlite3CodeSubselect(pParse, p, 0, 0);
      iSelect = sqlite3CodeSubselect(pParse, p);
      sqlite3VdbeAddOp3(v, OP_Copy, iSelect, iReg, nReg-1);
    }else
#endif
    {
      int i;
      const ExprList *pList;
      assert( ExprUseXList(p) );
      ExprList *pList = p->x.pList;
      pList = p->x.pList;
      assert( nReg<=pList->nExpr );
      for(i=0; i<nReg; i++){
        sqlite3ExprCode(pParse, pList->a[i].pExpr, iReg+i);
      }
    }
  }else{
    assert( nReg==1 );
    assert( nReg==1 || pParse->nErr );
    sqlite3ExprCode(pParse, p, iReg);
  }
}

/* An instance of the IdxExprTrans object carries information about a
** mapping from an expression on table columns into a column in an index
** down through the Walker.
/*
** The pTruth expression is always true because it is the WHERE clause
** a partial index that is driving a query loop.  Look through all of the
** WHERE clause terms on the query, and if any of those terms must be
** true because pTruth is true, then mark those WHERE clause terms as
** coded.
*/
typedef struct IdxExprTrans {
  Expr *pIdxExpr;    /* The index expression */
  int iTabCur;       /* The cursor of the corresponding table */
  int iIdxCur;       /* The cursor for the index */
static void whereApplyPartialIndexConstraints(
  Expr *pTruth,
  int iTabCur,
  WhereClause *pWC
){
  int i;
  int iIdxCol;       /* The column for the index */
} IdxExprTrans;

  WhereTerm *pTerm;
  while( pTruth->op==TK_AND ){
    whereApplyPartialIndexConstraints(pTruth->pLeft, iTabCur, pWC);
    pTruth = pTruth->pRight;
  }
/* The walker node callback used to transform matching expressions into
** a reference to an index column for an index on an expression.
**
** If pExpr matches, then transform it into a reference to the index column
** that contains the value of pExpr.
*/
static int whereIndexExprTransNode(Walker *p, Expr *pExpr){
  IdxExprTrans *pX = p->u.pIdxTrans;
  if( sqlite3ExprCompare(0, pExpr, pX->pIdxExpr, pX->iTabCur)==0 ){
    pExpr->op = TK_COLUMN;
  for(i=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
    Expr *pExpr;
    if( pTerm->wtFlags & TERM_CODED ) continue;
    pExpr = pTerm->pExpr;
    if( sqlite3ExprCompare(0, pExpr, pTruth, iTabCur)==0 ){
      pTerm->wtFlags |= TERM_CODED;
    pExpr->iTable = pX->iIdxCur;
    pExpr->iColumn = pX->iIdxCol;
    pExpr->y.pTab = 0;
    return WRC_Prune;
  }else{
    return WRC_Continue;
    }
  }
}

/*
** This routine is called right after An OP_Filter has been generated and
** before the corresponding index search has been performed.  This routine
** checks to see if there are additional Bloom filters in inner loops that
** can be checked prior to doing the index lookup.  If there are available
** inner-loop Bloom filters, then evaluate those filters now, before the
** index lookup.  The idea is that a Bloom filter check is way faster than
** For an indexes on expression X, locate every instance of expression X
** an index lookup, and the Bloom filter might return false, meaning that
** in pExpr and change that subexpression into a reference to the appropriate
** column of the index.
** the index lookup can be skipped.
**
** We know that an inner loop uses a Bloom filter because it has the
** WhereLevel.regFilter set.  If an inner-loop Bloom filter is checked,
** then clear the WhereLevel.regFilter value to prevent the Bloom filter
** from being checked a second time when the inner loop is evaluated.
*/
static void whereIndexExprTrans(
  Index *pIdx,      /* The Index */
static SQLITE_NOINLINE void filterPullDown(
  Parse *pParse,       /* Parsing context */
  int iTabCur,      /* Cursor of the table that is being indexed */
  int iIdxCur,      /* Cursor of the index itself */
  WhereInfo *pWInfo /* Transform expressions in this WHERE clause */
  WhereInfo *pWInfo,   /* Complete information about the WHERE clause */
  int iLevel,          /* Which level of pWInfo->a[] should be coded */
  int addrNxt,         /* Jump here to bypass inner loops */
  Bitmask notReady     /* Loops that are not ready */
){
  int iIdxCol;               /* Column number of the index */
  ExprList *aColExpr;        /* Expressions that are indexed */
  Walker w;
  IdxExprTrans x;
  aColExpr = pIdx->aColExpr;
  if( aColExpr==0 ) return;  /* Not an index on expressions */
  memset(&w, 0, sizeof(w));
  w.xExprCallback = whereIndexExprTransNode;
  w.u.pIdxTrans = &x;
  x.iTabCur = iTabCur;
  x.iIdxCur = iIdxCur;
  while( ++iLevel < pWInfo->nLevel ){
    WhereLevel *pLevel = &pWInfo->a[iLevel];
    WhereLoop *pLoop = pLevel->pWLoop;
    if( pLevel->regFilter==0 ) continue;
    if( pLevel->pWLoop->nSkip ) continue;
    /*         ,--- Because sqlite3ConstructBloomFilter() has will not have set
    **  vvvvv--'    pLevel->regFilter if this were true. */
    if( NEVER(pLoop->prereq & notReady) ) continue;
    assert( pLevel->addrBrk==0 );
    pLevel->addrBrk = addrNxt;
    if( pLoop->wsFlags & WHERE_IPK ){
      WhereTerm *pTerm = pLoop->aLTerm[0];
  for(iIdxCol=0; iIdxCol<aColExpr->nExpr; iIdxCol++){
    if( pIdx->aiColumn[iIdxCol]!=XN_EXPR ) continue;
    assert( aColExpr->a[iIdxCol].pExpr!=0 );
      int regRowid;
      assert( pTerm!=0 );
    x.iIdxCol = iIdxCol;
    x.pIdxExpr = aColExpr->a[iIdxCol].pExpr;
    sqlite3WalkExpr(&w, pWInfo->pWhere);
    sqlite3WalkExprList(&w, pWInfo->pOrderBy);
    sqlite3WalkExprList(&w, pWInfo->pResultSet);
      assert( pTerm->pExpr!=0 );
      testcase( pTerm->wtFlags & TERM_VIRTUAL );
      regRowid = sqlite3GetTempReg(pParse);
      regRowid = codeEqualityTerm(pParse, pTerm, pLevel, 0, 0, regRowid);
      sqlite3VdbeAddOp2(pParse->pVdbe, OP_MustBeInt, regRowid, addrNxt);
      VdbeCoverage(pParse->pVdbe);
      sqlite3VdbeAddOp4Int(pParse->pVdbe, OP_Filter, pLevel->regFilter,
                           addrNxt, regRowid, 1);
      VdbeCoverage(pParse->pVdbe);
    }else{
      u16 nEq = pLoop->u.btree.nEq;
      int r1;
      char *zStartAff;

      assert( pLoop->wsFlags & WHERE_INDEXED );
      assert( (pLoop->wsFlags & WHERE_COLUMN_IN)==0 );
      r1 = codeAllEqualityTerms(pParse,pLevel,0,0,&zStartAff);
      codeApplyAffinity(pParse, r1, nEq, zStartAff);
      sqlite3DbFree(pParse->db, zStartAff);
      sqlite3VdbeAddOp4Int(pParse->pVdbe, OP_Filter, pLevel->regFilter,
                           addrNxt, r1, nEq);
      VdbeCoverage(pParse->pVdbe);
    }
    pLevel->regFilter = 0;
    pLevel->addrBrk = 0;
  }
}

/*
** Generate code for the start of the iLevel-th loop in the WHERE clause
** implementation described by pWInfo.
*/
Bitmask sqlite3WhereCodeOneLoopStart(
  Parse *pParse,       /* Parsing context */
  Vdbe *v,             /* Prepared statement under construction */
  WhereInfo *pWInfo,   /* Complete information about the WHERE clause */
  int iLevel,          /* Which level of pWInfo->a[] should be coded */
  WhereLevel *pLevel,  /* The current level pointer */
  Bitmask notReady     /* Which tables are currently available */
){
  int j, k;            /* Loop counters */
  int iCur;            /* The VDBE cursor for the table */
  int addrNxt;         /* Where to jump to continue with the next IN case */
  int omitTable;       /* True if we use the index only */
  int bRev;            /* True if we need to scan in reverse order */
  WhereLevel *pLevel;  /* The where level to be coded */
  WhereLoop *pLoop;    /* The WhereLoop object being coded */
  WhereClause *pWC;    /* Decomposition of the entire WHERE clause */
  WhereTerm *pTerm;               /* A WHERE clause term */
  Parse *pParse;                  /* Parsing context */
  sqlite3 *db;                    /* Database connection */
  Vdbe *v;                        /* The prepared stmt under constructions */
  struct SrcList_item *pTabItem;  /* FROM clause term being coded */
  SrcItem *pTabItem;              /* FROM clause term being coded */
  int addrBrk;                    /* Jump here to break out of the loop */
  int addrHalt;                   /* addrBrk for the outermost loop */
  int addrCont;                   /* Jump here to continue with next cycle */
  int iRowidReg = 0;        /* Rowid is stored in this register, if not zero */
  int iReleaseReg = 0;      /* Temp register to free before returning */
  Index *pIdx = 0;          /* Index used by loop (if any) */
  int iLoop;                /* Iteration of constraint generator loop */

  pParse = pWInfo->pParse;
  v = pParse->pVdbe;
  pWC = &pWInfo->sWC;
  db = pParse->db;
  pLevel = &pWInfo->a[iLevel];
  pLoop = pLevel->pWLoop;
  pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
  iCur = pTabItem->iCursor;
  pLevel->notReady = notReady & ~sqlite3WhereGetMask(&pWInfo->sMaskSet, iCur);
  bRev = (pWInfo->revMask>>iLevel)&1;
  omitTable = (pLoop->wsFlags & WHERE_IDX_ONLY)!=0 
           && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0;
  VdbeModuleComment((v, "Begin WHERE-loop%d: %s",iLevel,pTabItem->pTab->zName));
#if WHERETRACE_ENABLED /* 0x4001 */
  if( sqlite3WhereTrace & 0x1 ){
    sqlite3DebugPrintf("Coding level %d of %d:  notReady=%llx  iFrom=%d\n",
       iLevel, pWInfo->nLevel, (u64)notReady, pLevel->iFrom);
    if( sqlite3WhereTrace & 0x1000 ){
      sqlite3WhereLoopPrint(pLoop, pWC);
    }
  }
  if( (sqlite3WhereTrace & 0x4001)==0x4001 ){
    if( iLevel==0 ){
      sqlite3DebugPrintf("WHERE clause being coded:\n");
      sqlite3TreeViewExpr(0, pWInfo->pWhere, 0);
    }
    sqlite3DebugPrintf("All WHERE-clause terms before coding:\n");
    sqlite3WhereClausePrint(pWC);
  }
#endif

  /* Create labels for the "break" and "continue" instructions
  ** for the current loop.  Jump to addrBrk to break out of a loop.
  ** Jump to cont to go immediately to the next iteration of the
  ** loop.
  **
  ** When there is an IN operator, we also have a "addrNxt" label that
  ** means to continue with the next IN value combination.  When
  ** there are no IN operators in the constraints, the "addrNxt" label
  ** is the same as "addrBrk".
  */
  addrBrk = pLevel->addrBrk = pLevel->addrNxt = sqlite3VdbeMakeLabel(v);
  addrCont = pLevel->addrCont = sqlite3VdbeMakeLabel(v);
  addrBrk = pLevel->addrBrk = pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse);
  addrCont = pLevel->addrCont = sqlite3VdbeMakeLabel(pParse);

  /* If this is the right table of a LEFT OUTER JOIN, allocate and
  ** initialize a memory cell that records if this table matches any
  ** row of the left table of the join.
  */
  assert( (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)
  assert( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))
       || pLevel->iFrom>0 || (pTabItem[0].fg.jointype & JT_LEFT)==0
  );
  if( pLevel->iFrom>0 && (pTabItem[0].fg.jointype & JT_LEFT)!=0 ){
    pLevel->iLeftJoin = ++pParse->nMem;
    sqlite3VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin);
    VdbeComment((v, "init LEFT JOIN no-match flag"));
  }

  /* Compute a safe address to jump to if we discover that the table for
  ** this loop is empty and can never contribute content. */
  for(j=iLevel; j>0 && pWInfo->a[j].iLeftJoin==0; j--){}
  for(j=iLevel; j>0; j--){
    if( pWInfo->a[j].iLeftJoin ) break;
    if( pWInfo->a[j].pRJ ) break;
  }
  addrHalt = pWInfo->a[j].addrBrk;

  /* Special case of a FROM clause subquery implemented as a co-routine */
  if( pTabItem->fg.viaCoroutine ){
    int regYield = pTabItem->regReturn;
    sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub);
    pLevel->p2 =  sqlite3VdbeAddOp2(v, OP_Yield, regYield, addrBrk);
    VdbeCoverage(v);
    VdbeComment((v, "next row of %s", pTabItem->pTab->zName));
    pLevel->op = OP_Goto;
  }else

#ifndef SQLITE_OMIT_VIRTUALTABLE
  if(  (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ){
    /* Case 1:  The table is a virtual-table.  Use the VFilter and VNext
    **          to access the data.
    */
    int iReg;   /* P3 Value for OP_VFilter */
    int addrNotFound;
    int nConstraint = pLoop->nLTerm;
    int iIn;    /* Counter for IN constraints */

    iReg = sqlite3GetTempRange(pParse, nConstraint+2);
    addrNotFound = pLevel->addrBrk;
    for(j=0; j<nConstraint; j++){
      int iTarget = iReg+j+2;
      pTerm = pLoop->aLTerm[j];
      if( NEVER(pTerm==0) ) continue;
      if( pTerm->eOperator & WO_IN ){
        if( SMASKBIT32(j) & pLoop->u.vtab.mHandleIn ){
          int iTab = pParse->nTab++;
          int iCache = ++pParse->nMem;
          sqlite3CodeRhsOfIN(pParse, pTerm->pExpr, iTab);
          sqlite3VdbeAddOp3(v, OP_VInitIn, iTab, iTarget, iCache);
        }else{
        codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget);
        addrNotFound = pLevel->addrNxt;
          codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget);
          addrNotFound = pLevel->addrNxt;
        }
      }else{
        Expr *pRight = pTerm->pExpr->pRight;
        codeExprOrVector(pParse, pRight, iTarget, 1);
        if( pTerm->eMatchOp==SQLITE_INDEX_CONSTRAINT_OFFSET
         && pLoop->u.vtab.bOmitOffset
        ){
          assert( pTerm->eOperator==WO_AUX );
          assert( pWInfo->pSelect!=0 );
          assert( pWInfo->pSelect->iOffset>0 );
          sqlite3VdbeAddOp2(v, OP_Integer, 0, pWInfo->pSelect->iOffset);
          VdbeComment((v,"Zero OFFSET counter"));
        }
      }
    }
    sqlite3VdbeAddOp2(v, OP_Integer, pLoop->u.vtab.idxNum, iReg);
    sqlite3VdbeAddOp2(v, OP_Integer, nConstraint, iReg+1);
    sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg,
                      pLoop->u.vtab.idxStr,
                      pLoop->u.vtab.needFree ? P4_DYNAMIC : P4_STATIC);
    VdbeCoverage(v);
    pLoop->u.vtab.needFree = 0;
    /* An OOM inside of AddOp4(OP_VFilter) instruction above might have freed
    ** the u.vtab.idxStr.  NULL it out to prevent a use-after-free */
    if( db->mallocFailed ) pLoop->u.vtab.idxStr = 0;
    pLevel->p1 = iCur;
    pLevel->op = pWInfo->eOnePass ? OP_Noop : OP_VNext;
    pLevel->p2 = sqlite3VdbeCurrentAddr(v);
    assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
    iIn = pLevel->u.in.nIn;
    for(j=nConstraint-1; j>=0; j--){

    for(j=0; j<nConstraint; j++){
      pTerm = pLoop->aLTerm[j];
      if( j<16 && (pLoop->u.vtab.omitMask>>j)&1 ){
        disableTerm(pLevel, pTerm);
        continue;
      }
      }else if( (pTerm->eOperator & WO_IN)!=0 ){
      if( (pTerm->eOperator & WO_IN)!=0
       && (SMASKBIT32(j) & pLoop->u.vtab.mHandleIn)==0
       && !db->mallocFailed
      ){
        Expr *pCompare;  /* The comparison operator */
        Expr *pRight;    /* RHS of the comparison */
        VdbeOp *pOp;     /* Opcode to access the value of the IN constraint */
        int iIn;         /* IN loop corresponding to the j-th constraint */

        /* Reload the constraint value into reg[iReg+j+2].  The same value
        ** was loaded into the same register prior to the OP_VFilter, but
        ** the xFilter implementation might have changed the datatype or
        ** encoding of the value in the register, so it *must* be reloaded. */
        assert( pLevel->u.in.aInLoop!=0 || db->mallocFailed );
        ** encoding of the value in the register, so it *must* be reloaded.
        */
        for(iIn=0; ALWAYS(iIn<pLevel->u.in.nIn); iIn++){
        if( !db->mallocFailed ){
          assert( iIn>0 );
          pOp = sqlite3VdbeGetOp(v, pLevel->u.in.aInLoop[--iIn].addrInTop);
          assert( pOp->opcode==OP_Column || pOp->opcode==OP_Rowid );
          assert( pOp->opcode!=OP_Column || pOp->p3==iReg+j+2 );
          pOp = sqlite3VdbeGetOp(v, pLevel->u.in.aInLoop[iIn].addrInTop);
          if( (pOp->opcode==OP_Column && pOp->p3==iReg+j+2)
           || (pOp->opcode==OP_Rowid && pOp->p2==iReg+j+2)
          assert( pOp->opcode!=OP_Rowid || pOp->p2==iReg+j+2 );
          testcase( pOp->opcode==OP_Rowid );
          sqlite3VdbeAddOp3(v, pOp->opcode, pOp->p1, pOp->p2, pOp->p3);
        }

          ){
            testcase( pOp->opcode==OP_Rowid );
            sqlite3VdbeAddOp3(v, pOp->opcode, pOp->p1, pOp->p2, pOp->p3);
            break;
          }
        }

        /* Generate code that will continue to the next row if 
        ** the IN constraint is not satisfied */
        ** the IN constraint is not satisfied
        */
        pCompare = sqlite3PExpr(pParse, TK_EQ, 0, 0);
        assert( pCompare!=0 || db->mallocFailed );
        if( pCompare ){
          pCompare->pLeft = pTerm->pExpr->pLeft;
        if( !db->mallocFailed ){
          int iFld = pTerm->u.x.iField;
          Expr *pLeft = pTerm->pExpr->pLeft;
          assert( pLeft!=0 );
          if( iFld>0 ){
            assert( pLeft->op==TK_VECTOR );
            assert( ExprUseXList(pLeft) );
            assert( iFld<=pLeft->x.pList->nExpr );
            pCompare->pLeft = pLeft->x.pList->a[iFld-1].pExpr;
          }else{
            pCompare->pLeft = pLeft;
          }
          pCompare->pRight = pRight = sqlite3Expr(db, TK_REGISTER, 0);
          if( pRight ){
            pRight->iTable = iReg+j+2;
            sqlite3ExprIfFalse(pParse, pCompare, pLevel->addrCont, 0);
            sqlite3ExprIfFalse(
                pParse, pCompare, pLevel->addrCont, SQLITE_JUMPIFNULL
            );
          }
          pCompare->pLeft = 0;
        }
          sqlite3ExprDelete(db, pCompare);
        }
      }
    }
        sqlite3ExprDelete(db, pCompare);
      }
    }

    /* These registers need to be preserved in case there is an IN operator
    ** loop.  So we could deallocate the registers here (and potentially
    ** reuse them later) if (pLoop->wsFlags & WHERE_IN_ABLE)==0.  But it seems
    ** simpler and safer to simply not reuse the registers.
    **
    **    sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2);
    */
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
1555
1556
1557
1558
1559
1560
1561

1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587

1588
1589
1590
1591
1592
1593
1594







-





+
+
+
+
+
+
+
+













-







    **          we reference multiple rows using a "rowid IN (...)"
    **          construct.
    */
    assert( pLoop->u.btree.nEq==1 );
    pTerm = pLoop->aLTerm[0];
    assert( pTerm!=0 );
    assert( pTerm->pExpr!=0 );
    assert( omitTable==0 );
    testcase( pTerm->wtFlags & TERM_VIRTUAL );
    iReleaseReg = ++pParse->nMem;
    iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, bRev, iReleaseReg);
    if( iRowidReg!=iReleaseReg ) sqlite3ReleaseTempReg(pParse, iReleaseReg);
    addrNxt = pLevel->addrNxt;
    if( pLevel->regFilter ){
      sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt);
      VdbeCoverage(v);
      sqlite3VdbeAddOp4Int(v, OP_Filter, pLevel->regFilter, addrNxt,
                           iRowidReg, 1);
      VdbeCoverage(v);
      filterPullDown(pParse, pWInfo, iLevel, addrNxt, notReady);
    }
    sqlite3VdbeAddOp3(v, OP_SeekRowid, iCur, addrNxt, iRowidReg);
    VdbeCoverage(v);
    pLevel->op = OP_Noop;
  }else if( (pLoop->wsFlags & WHERE_IPK)!=0
         && (pLoop->wsFlags & WHERE_COLUMN_RANGE)!=0
  ){
    /* Case 3:  We have an inequality comparison against the ROWID field.
    */
    int testOp = OP_Noop;
    int start;
    int memEndValue = 0;
    WhereTerm *pStart, *pEnd;

    assert( omitTable==0 );
    j = 0;
    pStart = pEnd = 0;
    if( pLoop->wsFlags & WHERE_BTM_LIMIT ) pStart = pLoop->aLTerm[j++];
    if( pLoop->wsFlags & WHERE_TOP_LIMIT ) pEnd = pLoop->aLTerm[j++];
    assert( pStart!=0 || pEnd!=0 );
    if( bRev ){
      pTerm = pStart;
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
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758




















1759
1760
1761
1762
1763
1764
1765







+
+
+





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







    int iIdxCur;                 /* The VDBE cursor for the index */
    int nExtraReg = 0;           /* Number of extra registers needed */
    int op;                      /* Instruction opcode */
    char *zStartAff;             /* Affinity for start of range constraint */
    char *zEndAff = 0;           /* Affinity for end of range constraint */
    u8 bSeekPastNull = 0;        /* True to seek past initial nulls */
    u8 bStopAtNull = 0;          /* Add condition to terminate at NULLs */
    int omitTable;               /* True if we use the index only */
    int regBignull = 0;          /* big-null flag register */
    int addrSeekScan = 0;        /* Opcode of the OP_SeekScan, if any */

    pIdx = pLoop->u.btree.pIndex;
    iIdxCur = pLevel->iIdxCur;
    assert( nEq>=pLoop->nSkip );

    /* If this loop satisfies a sort order (pOrderBy) request that 
    ** was passed to this function to implement a "SELECT min(x) ..." 
    ** query, then the caller will only allow the loop to run for
    ** a single iteration. This means that the first row returned
    ** should not have a NULL value stored in 'x'. If column 'x' is
    ** the first one after the nEq equality constraints in the index,
    ** this requires some special handling.
    */
    assert( pWInfo->pOrderBy==0
         || pWInfo->pOrderBy->nExpr==1
         || (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)==0 );
    if( (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)!=0
     && pWInfo->nOBSat>0
     && (pIdx->nKeyCol>nEq)
    ){
      assert( pLoop->nSkip==0 );
      bSeekPastNull = 1;
      nExtraReg = 1;
    }

    /* Find any inequality constraint terms for the start and end 
    ** of the range. 
    */
    j = nEq;
    if( pLoop->wsFlags & WHERE_BTM_LIMIT ){
      pRangeStart = pLoop->aLTerm[j++];
      nExtraReg = MAX(nExtraReg, pLoop->u.btree.nBtm);
1582
1583
1584
1585
1586
1587
1588






















1589
1590
1591
1592
1593
1594

1595
1596
1597
1598
1599
1600






1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612

1613
1614
1615
1616
1617
1618
1619
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+
-
-




+
+
+
+
+
+











-
+







        j = pIdx->aiColumn[nEq];
        if( (j>=0 && pIdx->pTable->aCol[j].notNull==0) || j==XN_EXPR ){
          bSeekPastNull = 1;
        }
      }
    }
    assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 );

    /* If the WHERE_BIGNULL_SORT flag is set, then index column nEq uses
    ** a non-default "big-null" sort (either ASC NULLS LAST or DESC NULLS 
    ** FIRST). In both cases separate ordered scans are made of those
    ** index entries for which the column is null and for those for which
    ** it is not. For an ASC sort, the non-NULL entries are scanned first.
    ** For DESC, NULL entries are scanned first.
    */
    if( (pLoop->wsFlags & (WHERE_TOP_LIMIT|WHERE_BTM_LIMIT))==0
     && (pLoop->wsFlags & WHERE_BIGNULL_SORT)!=0
    ){
      assert( bSeekPastNull==0 && nExtraReg==0 && nBtm==0 && nTop==0 );
      assert( pRangeEnd==0 && pRangeStart==0 );
      testcase( pLoop->nSkip>0 );
      nExtraReg = 1;
      bSeekPastNull = 1;
      pLevel->regBignull = regBignull = ++pParse->nMem;
      if( pLevel->iLeftJoin ){
        sqlite3VdbeAddOp2(v, OP_Integer, 0, regBignull);
      }
      pLevel->addrBignull = sqlite3VdbeMakeLabel(pParse);
    }

    /* If we are doing a reverse order scan on an ascending index, or
    ** a forward order scan on a descending index, interchange the 
    ** start and end terms (pRangeStart and pRangeEnd).
    */
    if( (nEq<pIdx->nKeyCol && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC))
    if( (nEq<pIdx->nColumn && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC)) ){
     || (bRev && pIdx->nKeyCol==nEq)
    ){
      SWAP(WhereTerm *, pRangeEnd, pRangeStart);
      SWAP(u8, bSeekPastNull, bStopAtNull);
      SWAP(u8, nBtm, nTop);
    }

    if( iLevel>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)!=0 ){
      /* In case OP_SeekScan is used, ensure that the index cursor does not
      ** point to a valid row for the first iteration of this loop. */
      sqlite3VdbeAddOp1(v, OP_NullRow, iIdxCur);
    }

    /* Generate code to evaluate all constraint terms using == or IN
    ** and store the values of those terms in an array of registers
    ** starting at regBase.
    */
    codeCursorHint(pTabItem, pWInfo, pLevel, pRangeEnd);
    regBase = codeAllEqualityTerms(pParse,pLevel,bRev,nExtraReg,&zStartAff);
    assert( zStartAff==0 || sqlite3Strlen30(zStartAff)>=nEq );
    if( zStartAff && nTop ){
      zEndAff = sqlite3DbStrDup(db, &zStartAff[nEq]);
    }
    addrNxt = pLevel->addrNxt;
    addrNxt = (regBignull ? pLevel->addrBignull : pLevel->addrNxt);

    testcase( pRangeStart && (pRangeStart->eOperator & WO_LE)!=0 );
    testcase( pRangeStart && (pRangeStart->eOperator & WO_GE)!=0 );
    testcase( pRangeEnd && (pRangeEnd->eOperator & WO_LE)!=0 );
    testcase( pRangeEnd && (pRangeEnd->eOperator & WO_GE)!=0 );
    startEq = !pRangeStart || pRangeStart->eOperator & (WO_LE|WO_GE);
    endEq =   !pRangeEnd || pRangeEnd->eOperator & (WO_LE|WO_GE);
1639
1640
1641
1642
1643
1644
1645

1646

1647
1648


1649

1650
1651
1652
1653
1654
1655
1656
1657
1658



1659







1660
1661



















1662
1663
1664
1665
1666
1667
1668
1669

















1670
1671
1672
1673
1674
1675

1676
1677










1678
1679
1680
1681
1682
1683
1684
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884

1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895


1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
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







+

+

-
+
+

+







-
-
+
+
+

+
+
+
+
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






+


+
+
+
+
+
+
+
+
+
+







      if( sqlite3ExprIsVector(pRight)==0 ){
        disableTerm(pLevel, pRangeStart);
      }else{
        startEq = 1;
      }
      bSeekPastNull = 0;
    }else if( bSeekPastNull ){
      startEq = 0;
      sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
      start_constraints = 1;
      nConstraint++;
      startEq = 0;
    }else if( regBignull ){
      sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
      start_constraints = 1;
      nConstraint++;
    }
    codeApplyAffinity(pParse, regBase, nConstraint - bSeekPastNull, zStartAff);
    if( pLoop->nSkip>0 && nConstraint==pLoop->nSkip ){
      /* The skip-scan logic inside the call to codeAllEqualityConstraints()
      ** above has already left the cursor sitting on the correct row,
      ** so no further seeking is needed */
    }else{
      if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){
        sqlite3VdbeAddOp1(v, OP_SeekHit, iIdxCur);
      if( regBignull ){
        sqlite3VdbeAddOp2(v, OP_Integer, 1, regBignull);
        VdbeComment((v, "NULL-scan pass ctr"));
      }
      if( pLevel->regFilter ){
        sqlite3VdbeAddOp4Int(v, OP_Filter, pLevel->regFilter, addrNxt,
                             regBase, nEq);
        VdbeCoverage(v);
        filterPullDown(pParse, pWInfo, iLevel, addrNxt, notReady);
      }

      op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
      assert( op!=0 );
      if( (pLoop->wsFlags & WHERE_IN_SEEKSCAN)!=0 && op==OP_SeekGE ){
        assert( regBignull==0 );
        /* TUNING:  The OP_SeekScan opcode seeks to reduce the number
        ** of expensive seek operations by replacing a single seek with
        ** 1 or more step operations.  The question is, how many steps
        ** should we try before giving up and going with a seek.  The cost
        ** of a seek is proportional to the logarithm of the of the number
        ** of entries in the tree, so basing the number of steps to try
        ** on the estimated number of rows in the btree seems like a good
        ** guess. */
        addrSeekScan = sqlite3VdbeAddOp1(v, OP_SeekScan, 
                                         (pIdx->aiRowLogEst[0]+9)/10);
        if( pRangeStart ){
          sqlite3VdbeChangeP5(v, 1);
          sqlite3VdbeChangeP2(v, addrSeekScan, sqlite3VdbeCurrentAddr(v)+1);
          addrSeekScan = 0;
        }
        VdbeCoverage(v);
      }
      sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
      VdbeCoverage(v);
      VdbeCoverageIf(v, op==OP_Rewind);  testcase( op==OP_Rewind );
      VdbeCoverageIf(v, op==OP_Last);    testcase( op==OP_Last );
      VdbeCoverageIf(v, op==OP_SeekGT);  testcase( op==OP_SeekGT );
      VdbeCoverageIf(v, op==OP_SeekGE);  testcase( op==OP_SeekGE );
      VdbeCoverageIf(v, op==OP_SeekLE);  testcase( op==OP_SeekLE );
      VdbeCoverageIf(v, op==OP_SeekLT);  testcase( op==OP_SeekLT );

      assert( bSeekPastNull==0 || bStopAtNull==0 );
      if( regBignull ){
        assert( bSeekPastNull==1 || bStopAtNull==1 );
        assert( bSeekPastNull==!bStopAtNull );
        assert( bStopAtNull==startEq );
        sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+2);
        op = aStartOp[(nConstraint>1)*4 + 2 + bRev];
        sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, 
                             nConstraint-startEq);
        VdbeCoverage(v);
        VdbeCoverageIf(v, op==OP_Rewind);  testcase( op==OP_Rewind );
        VdbeCoverageIf(v, op==OP_Last);    testcase( op==OP_Last );
        VdbeCoverageIf(v, op==OP_SeekGE);  testcase( op==OP_SeekGE );
        VdbeCoverageIf(v, op==OP_SeekLE);  testcase( op==OP_SeekLE );
        assert( op==OP_Rewind || op==OP_Last || op==OP_SeekGE || op==OP_SeekLE);
      }
    }

    /* Load the value for the inequality constraint at the end of the
    ** range (if any).
    */
    nConstraint = nEq;
    assert( pLevel->p2==0 );
    if( pRangeEnd ){
      Expr *pRight = pRangeEnd->pExpr->pRight;
      if( addrSeekScan ){
        /* For a seek-scan that has a range on the lowest term of the index,
        ** we have to make the top of the loop be code that sets the end
        ** condition of the range.  Otherwise, the OP_SeekScan might jump
        ** over that initialization, leaving the range-end value set to the
        ** range-start value, resulting in a wrong answer.
        ** See ticket 5981a8c041a3c2f3 (2021-11-02).
        */
        pLevel->p2 = sqlite3VdbeCurrentAddr(v);
      }
      codeExprOrVector(pParse, pRight, regBase+nEq, nTop);
      whereLikeOptimizationStringFixup(v, pLevel, pRangeEnd);
      if( (pRangeEnd->wtFlags & TERM_VNULL)==0
       && sqlite3ExprCanBeNull(pRight)
      ){
        sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
        VdbeCoverage(v);
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
1744

1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755







1756
1757
1758
1759
1760
1761
1762
1763
1764












1765
1766
1767
1768
1769
1770
1771
1988
1989
1990
1991
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
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038



2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050










2051

2052
2053
2054
2055

2056
2057
2058
2059
2060
2061
2062





2063
2064
2065
2066
2067
2068
2069









2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088







+
-
-
+
+
+


-
-
+
+


-
+



+
+
+
+
+
+






+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+



+
+



-
-
-
-
-
-
-
-
-
-
+
-




-
+






-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+








      if( sqlite3ExprIsVector(pRight)==0 ){
        disableTerm(pLevel, pRangeEnd);
      }else{
        endEq = 1;
      }
    }else if( bStopAtNull ){
      if( regBignull==0 ){
      sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
      endEq = 0;
        sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
        endEq = 0;
      }
      nConstraint++;
    }
    sqlite3DbFree(db, zStartAff);
    sqlite3DbFree(db, zEndAff);
    if( zStartAff ) sqlite3DbNNFreeNN(db, zStartAff);
    if( zEndAff ) sqlite3DbNNFreeNN(db, zEndAff);

    /* Top of the loop body */
    pLevel->p2 = sqlite3VdbeCurrentAddr(v);
    if( pLevel->p2==0 ) pLevel->p2 = sqlite3VdbeCurrentAddr(v);

    /* Check if the index cursor is past the end of the range. */
    if( nConstraint ){
      if( regBignull ){
        /* Except, skip the end-of-range check while doing the NULL-scan */
        sqlite3VdbeAddOp2(v, OP_IfNot, regBignull, sqlite3VdbeCurrentAddr(v)+3);
        VdbeComment((v, "If NULL-scan 2nd pass"));
        VdbeCoverage(v);
      }
      op = aEndOp[bRev*2 + endEq];
      sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
      testcase( op==OP_IdxGT );  VdbeCoverageIf(v, op==OP_IdxGT );
      testcase( op==OP_IdxGE );  VdbeCoverageIf(v, op==OP_IdxGE );
      testcase( op==OP_IdxLT );  VdbeCoverageIf(v, op==OP_IdxLT );
      testcase( op==OP_IdxLE );  VdbeCoverageIf(v, op==OP_IdxLE );
      if( addrSeekScan ) sqlite3VdbeJumpHere(v, addrSeekScan);
    }
    if( regBignull ){
      /* During a NULL-scan, check to see if we have reached the end of
      ** the NULLs */
      assert( bSeekPastNull==!bStopAtNull );
      assert( bSeekPastNull+bStopAtNull==1 );
      assert( nConstraint+bSeekPastNull>0 );
      sqlite3VdbeAddOp2(v, OP_If, regBignull, sqlite3VdbeCurrentAddr(v)+2);
      VdbeComment((v, "If NULL-scan 1st pass"));
      VdbeCoverage(v);
      op = aEndOp[bRev*2 + bSeekPastNull];
      sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase,
                           nConstraint+bSeekPastNull);
      testcase( op==OP_IdxGT );  VdbeCoverageIf(v, op==OP_IdxGT );
      testcase( op==OP_IdxGE );  VdbeCoverageIf(v, op==OP_IdxGE );
      testcase( op==OP_IdxLT );  VdbeCoverageIf(v, op==OP_IdxLT );
      testcase( op==OP_IdxLE );  VdbeCoverageIf(v, op==OP_IdxLE );

    if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){
      sqlite3VdbeAddOp2(v, OP_SeekHit, iIdxCur, 1);
    }

    if( (pLoop->wsFlags & WHERE_IN_EARLYOUT)!=0 ){
      sqlite3VdbeAddOp3(v, OP_SeekHit, iIdxCur, nEq, nEq);
    }

    /* Seek the table cursor, if required */
    omitTable = (pLoop->wsFlags & WHERE_IDX_ONLY)!=0 
           && (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))==0;
    if( omitTable ){
      /* pIdx is a covering index.  No need to access the main table. */
    }else if( HasRowid(pIdx->pTable) ){
      if( (pWInfo->wctrlFlags & WHERE_SEEK_TABLE) || (
          (pWInfo->wctrlFlags & WHERE_SEEK_UNIQ_TABLE) 
       && (pWInfo->eOnePass==ONEPASS_SINGLE)
      )){
        iRowidReg = ++pParse->nMem;
        sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg);
        sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowidReg);
        VdbeCoverage(v);
      }else{
        codeDeferredSeek(pWInfo, pIdx, iCur, iIdxCur);
      codeDeferredSeek(pWInfo, pIdx, iCur, iIdxCur);
      }
    }else if( iCur!=iIdxCur ){
      Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);
      iRowidReg = sqlite3GetTempRange(pParse, pPk->nKeyCol);
      for(j=0; j<pPk->nKeyCol; j++){
        k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[j]);
        k = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[j]);
        sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, iRowidReg+j);
      }
      sqlite3VdbeAddOp4Int(v, OP_NotFound, iCur, addrCont,
                           iRowidReg, pPk->nKeyCol); VdbeCoverage(v);
    }

    /* If pIdx is an index on one or more expressions, then look through
    ** all the expressions in pWInfo and try to transform matching expressions
    ** into reference to index columns.
    **
    ** Do not do this for the RHS of a LEFT JOIN. This is because the 
    if( pLevel->iLeftJoin==0 ){
      /* If a partial index is driving the loop, try to eliminate WHERE clause
      ** terms from the query that must be true due to the WHERE clause of
      ** the partial index.
      **
      ** 2019-11-02 ticket 623eff57e76d45f6: This optimization does not work
      ** for a LEFT JOIN.
    ** expression may be evaluated after OP_NullRow has been executed on
    ** the cursor. In this case it is important to do the full evaluation,
    ** as the result of the expression may not be NULL, even if all table
    ** column values are.  https://www.sqlite.org/src/info/7fa8049685b50b5a
    */
    if( pLevel->iLeftJoin==0 ){
      whereIndexExprTrans(pIdx, iCur, iIdxCur, pWInfo);
    }

      */
      if( pIdx->pPartIdxWhere ){
        whereApplyPartialIndexConstraints(pIdx->pPartIdxWhere, iCur, pWC);
      }
    }else{
      testcase( pIdx->pPartIdxWhere );
      /* The following assert() is not a requirement, merely an observation:
      ** The OR-optimization doesn't work for the right hand table of
      ** a LEFT JOIN: */
      assert( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))==0 );
    }
  
    /* Record the instruction used to terminate the loop. */
    if( pLoop->wsFlags & WHERE_ONEROW ){
      pLevel->op = OP_Noop;
    }else if( bRev ){
      pLevel->op = OP_Prev;
    }else{
      pLevel->op = OP_Next;
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
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







-
+



-

















-
+

-
+







    SrcList *pOrTab;       /* Shortened table list or OR-clause generation */
    Index *pCov = 0;             /* Potential covering index (or NULL) */
    int iCovCur = pParse->nTab++;  /* Cursor used for index scans (if any) */

    int regReturn = ++pParse->nMem;           /* Register used with OP_Gosub */
    int regRowset = 0;                        /* Register for RowSet object */
    int regRowid = 0;                         /* Register holding rowid */
    int iLoopBody = sqlite3VdbeMakeLabel(v);  /* Start of loop body */
    int iLoopBody = sqlite3VdbeMakeLabel(pParse);/* Start of loop body */
    int iRetInit;                             /* Address of regReturn init */
    int untestedTerms = 0;             /* Some terms not completely tested */
    int ii;                            /* Loop counter */
    u16 wctrlFlags;                    /* Flags for sub-WHERE clause */
    Expr *pAndExpr = 0;                /* An ".. AND (...)" expression */
    Table *pTab = pTabItem->pTab;

    pTerm = pLoop->aLTerm[0];
    assert( pTerm!=0 );
    assert( pTerm->eOperator & WO_OR );
    assert( (pTerm->wtFlags & TERM_ORINFO)!=0 );
    pOrWc = &pTerm->u.pOrInfo->wc;
    pLevel->op = OP_Return;
    pLevel->p1 = regReturn;

    /* Set up a new SrcList in pOrTab containing the table being scanned
    ** by this loop in the a[0] slot and all notReady tables in a[1..] slots.
    ** This becomes the SrcList in the recursive call to sqlite3WhereBegin().
    */
    if( pWInfo->nLevel>1 ){
      int nNotReady;                 /* The number of notReady tables */
      struct SrcList_item *origSrc;     /* Original list of tables */
      SrcItem *origSrc;              /* Original list of tables */
      nNotReady = pWInfo->nLevel - iLevel - 1;
      pOrTab = sqlite3StackAllocRaw(db,
      pOrTab = sqlite3DbMallocRawNN(db,
                            sizeof(*pOrTab)+ nNotReady*sizeof(pOrTab->a[0]));
      if( pOrTab==0 ) return notReady;
      pOrTab->nAlloc = (u8)(nNotReady + 1);
      pOrTab->nSrc = pOrTab->nAlloc;
      memcpy(pOrTab->a, pTabItem, sizeof(*pTabItem));
      origSrc = pWInfo->pTabList->a;
      for(k=1; k<=nNotReady; k++){
1894
1895
1896
1897
1898
1899
1900
1901

1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912














1913
1914
1915
1916
1917
1918
1919
1920

1921



1922
1923

1924
1925

1926
1927





1928

1929
1930
1931
1932
1933
1934
1935
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
2210
2211
2212
2213
2214
2215
2216

2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251

2252
2253
2254
2255

2256
2257

2258
2259
2260
2261
2262
2263
2264
2265

2266
2267
2268
2269
2270
2271
2272
2273

2274
2275
2276
2277
2278
2279
2280
2281



2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295




2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306







-
+











+
+
+
+
+
+
+
+
+
+
+
+
+
+








+
-
+
+
+

-
+

-
+


+
+
+
+
+
-
+







-






+

-
-
-
+
+
+
+
+
+
+
+





+
-
-
-
-
+
+
+
+







        sqlite3VdbeSetP4KeyInfo(pParse, pPk);
      }
      regRowid = ++pParse->nMem;
    }
    iRetInit = sqlite3VdbeAddOp2(v, OP_Integer, 0, regReturn);

    /* If the original WHERE clause is z of the form:  (x1 OR x2 OR ...) AND y
    ** Then for every term xN, evaluate as the subexpression: xN AND z
    ** Then for every term xN, evaluate as the subexpression: xN AND y
    ** That way, terms in y that are factored into the disjunction will
    ** be picked up by the recursive calls to sqlite3WhereBegin() below.
    **
    ** Actually, each subexpression is converted to "xN AND w" where w is
    ** the "interesting" terms of z - terms that did not originate in the
    ** ON or USING clause of a LEFT JOIN, and terms that are usable as 
    ** indices.
    **
    ** This optimization also only applies if the (x1 OR x2 OR ...) term
    ** is not contained in the ON clause of a LEFT JOIN.
    ** See ticket http://www.sqlite.org/src/info/f2369304e4
    **
    ** 2022-02-04:  Do not push down slices of a row-value comparison.
    ** In other words, "w" or "y" may not be a slice of a vector.  Otherwise,
    ** the initialization of the right-hand operand of the vector comparison
    ** might not occur, or might occur only in an OR branch that is not
    ** taken.  dbsqlfuzz 80a9fade844b4fb43564efc972bcb2c68270f5d1.
    **
    ** 2022-03-03:  Do not push down expressions that involve subqueries.
    ** The subquery might get coded as a subroutine.  Any table-references
    ** in the subquery might be resolved to index-references for the index on
    ** the OR branch in which the subroutine is coded.  But if the subroutine
    ** is invoked from a different OR branch that uses a different index, such
    ** index-references will not work.  tag-20220303a
    ** https://sqlite.org/forum/forumpost/36937b197273d403
    */
    if( pWC->nTerm>1 ){
      int iTerm;
      for(iTerm=0; iTerm<pWC->nTerm; iTerm++){
        Expr *pExpr = pWC->a[iTerm].pExpr;
        if( &pWC->a[iTerm] == pTerm ) continue;
        testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL );
        testcase( pWC->a[iTerm].wtFlags & TERM_CODED );
        testcase( pWC->a[iTerm].wtFlags & TERM_SLICE );
        if( (pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_CODED))!=0 ) continue;
        if( (pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_CODED|TERM_SLICE))!=0 ){
          continue;
        }
        if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue;
        testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO );
        if( ExprHasProperty(pExpr, EP_Subquery) ) continue;  /* tag-20220303a */
        pExpr = sqlite3ExprDup(db, pExpr, 0);
        pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr);
        pAndExpr = sqlite3ExprAnd(pParse, pAndExpr, pExpr);
      }
      if( pAndExpr ){
        /* The extra 0x10000 bit on the opcode is masked off and does not
        ** become part of the new Expr.op.  However, it does make the
        ** op==TK_AND comparison inside of sqlite3PExpr() false, and this
        ** prevents sqlite3PExpr() from applying the AND short-circuit 
        ** optimization, which we do not want here. */
        pAndExpr = sqlite3PExpr(pParse, TK_AND|TKFLG_DONTFOLD, 0, pAndExpr);
        pAndExpr = sqlite3PExpr(pParse, TK_AND|0x10000, 0, pAndExpr);
      }
    }

    /* Run a separate WHERE clause for each term of the OR clause.  After
    ** eliminating duplicates from other WHERE clauses, the action for each
    ** sub-WHERE clause is to to invoke the main loop body as a subroutine.
    */
    wctrlFlags =  WHERE_OR_SUBCLAUSE | (pWInfo->wctrlFlags & WHERE_SEEK_TABLE);
    ExplainQueryPlan((pParse, 1, "MULTI-INDEX OR"));
    for(ii=0; ii<pOrWc->nTerm; ii++){
      WhereTerm *pOrTerm = &pOrWc->a[ii];
      if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
        WhereInfo *pSubWInfo;           /* Info for single OR-term scan */
        Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */
        Expr *pDelete;                  /* Local copy of OR clause term */
        int jmp1 = 0;                   /* Address of jump operation */
        assert( (pTabItem[0].fg.jointype & JT_LEFT)==0 
             || ExprHasProperty(pOrExpr, EP_FromJoin) 
        );
        testcase( (pTabItem[0].fg.jointype & JT_LEFT)!=0
               && !ExprHasProperty(pOrExpr, EP_OuterON)
        ); /* See TH3 vtab25.400 and ticket 614b25314c766238 */
        pDelete = pOrExpr = sqlite3ExprDup(db, pOrExpr, 0);
        if( db->mallocFailed ){
          sqlite3ExprDelete(db, pDelete);
          continue;
        }
        if( pAndExpr ){
          pAndExpr->pLeft = pOrExpr;
          pOrExpr = pAndExpr;
        }
        /* Loop through table entries that match term pOrTerm. */
        ExplainQueryPlan((pParse, 1, "INDEX %d", ii+1));
        WHERETRACE(0xffff, ("Subplan for OR-clause:\n"));
        pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
                                      wctrlFlags, iCovCur);
        assert( pSubWInfo || pParse->nErr || db->mallocFailed );
        WHERETRACE(0xffffffff, ("Subplan for OR-clause:\n"));
        pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0, 0,
                                      WHERE_OR_SUBCLAUSE, iCovCur);
        assert( pSubWInfo || pParse->nErr );
        if( pSubWInfo ){
          WhereLoop *pSubLoop;
          int addrExplain = sqlite3WhereExplainOneScan(
              pParse, pOrTab, &pSubWInfo->a[0], 0
          );
          sqlite3WhereAddScanStatus(v, pOrTab, &pSubWInfo->a[0], addrExplain);

1978
1979
1980
1981
1982
1983
1984
1985

1986
1987
1988
1989
1990
1991
1992
2322
2323
2324
2325
2326
2327
2328

2329
2330
2331
2332
2333
2334
2335
2336







-
+







              int iPk;
              int r;

              /* Read the PK into an array of temp registers. */
              r = sqlite3GetTempRange(pParse, nPk);
              for(iPk=0; iPk<nPk; iPk++){
                int iCol = pPk->aiColumn[iPk];
                sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol, r+iPk);
                sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol,r+iPk);
              }

              /* Check if the temp table already contains this key. If so,
              ** the row has already been included in the result set and
              ** can be ignored (by jumping past the Gosub below). Otherwise,
              ** insert the key into the temp table and proceed with processing
              ** the row.
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
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410

2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428

2429
2430
2431
2432
2433
2434
2435
2436







+
+
+



+

+



+
+
+
-
+









+
+
+
+
+
+
+
+
-
+







           && (HasRowid(pTab) || !IsPrimaryKeyIndex(pSubLoop->u.btree.pIndex))
          ){
            assert( pSubWInfo->a[0].iIdxCur==iCovCur );
            pCov = pSubLoop->u.btree.pIndex;
          }else{
            pCov = 0;
          }
          if( sqlite3WhereUsesDeferredSeek(pSubWInfo) ){
            pWInfo->bDeferredSeek = 1;
          }

          /* Finish the loop through table entries that match term pOrTerm. */
          sqlite3WhereEnd(pSubWInfo);
          ExplainQueryPlanPop(pParse);
        }
        sqlite3ExprDelete(db, pDelete);
      }
    }
    ExplainQueryPlanPop(pParse);
    assert( pLevel->pWLoop==pLoop );
    assert( (pLoop->wsFlags & WHERE_MULTI_OR)!=0 );
    assert( (pLoop->wsFlags & WHERE_IN_ABLE)==0 );
    pLevel->u.pCovidx = pCov;
    pLevel->u.pCoveringIdx = pCov;
    if( pCov ) pLevel->iIdxCur = iCovCur;
    if( pAndExpr ){
      pAndExpr->pLeft = 0;
      sqlite3ExprDelete(db, pAndExpr);
    }
    sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v));
    sqlite3VdbeGoto(v, pLevel->addrBrk);
    sqlite3VdbeResolveLabel(v, iLoopBody);

    /* Set the P2 operand of the OP_Return opcode that will end the current
    ** loop to point to this spot, which is the top of the next containing
    ** loop.  The byte-code formatter will use that P2 value as a hint to
    ** indent everything in between the this point and the final OP_Return.
    ** See tag-20220407a in vdbe.c and shell.c */
    assert( pLevel->op==OP_Return );
    pLevel->p2 = sqlite3VdbeCurrentAddr(v);

    if( pWInfo->nLevel>1 ) sqlite3StackFree(db, pOrTab);
    if( pWInfo->nLevel>1 ){ sqlite3DbFreeNN(db, pOrTab); }
    if( !untestedTerms ) disableTerm(pLevel, pTerm);
  }else
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */

  {
    /* Case 6:  There is no usable index.  We must do a complete
    **          scan of the entire table.
2124
2125
2126
2127
2128
2129
2130






2131
2132
2133
2134










2135
2136
2137
2138
2139
2140
2141
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496




2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513







+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+







        testcase( pWInfo->untestedTerms==0
            && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)!=0 );
        pWInfo->untestedTerms = 1;
        continue;
      }
      pE = pTerm->pExpr;
      assert( pE!=0 );
      if( pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT) ){
        if( !ExprHasProperty(pE,EP_OuterON|EP_InnerON) ){
          /* Defer processing WHERE clause constraints until after outer
          ** join processing.  tag-20220513a */
          continue;
        }else if( (pTabItem->fg.jointype & JT_LEFT)==JT_LEFT
      if( (pTabItem->fg.jointype&JT_LEFT) && !ExprHasProperty(pE,EP_FromJoin) ){
        continue;
      }
      
               && !ExprHasProperty(pE,EP_OuterON) ){
          continue;
        }else{
          Bitmask m = sqlite3WhereGetMask(&pWInfo->sMaskSet, pE->w.iJoin);
          if( m & pLevel->notReady ){
            /* An ON clause that is not ripe */
            continue;
          }
        }
      }
      if( iLoop==1 && !sqlite3ExprCoveredByIndex(pE, pLevel->iTabCur, pIdx) ){
        iNext = 2;
        continue;
      }
      if( iLoop<3 && (pTerm->wtFlags & TERM_VARSELECT) ){
        if( iNext==0 ) iNext = 3;
        continue;
2149
2150
2151
2152
2153
2154
2155


2156
2157
2158
2159
2160

2161
2162
2163
2164




2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181

2182
2183
2184
2185
2186
2187
2188

2189






2190

2191

2192

2193
2194
2195
2196
2197

2198
2199
2200
2201
2202
2203
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


























































































2521
2522
2523
2524
2525
2526
2527
2528
2529
2530

2531
2532

2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557

2558
2559
2560
2561
2562
2563
2564

2565
2566
2567
2568
2569
2570
2571
2572

2573
2574
2575

2576
2577
2578
2579
2580

2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667

2668
2669
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
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785







+
+

-


-
+




+
+
+
+
















-
+






-
+

+
+
+
+
+
+
-
+

+
-
+




-
+











+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+









+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+







+






+
+
+
+
+
+
+
+
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
        ** that compares BLOBs. */
#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
        continue;
#else
        u32 x = pLevel->iLikeRepCntr;
        if( x>0 ){
          skipLikeAddr = sqlite3VdbeAddOp1(v, (x&1)?OP_IfNot:OP_If,(int)(x>>1));
          VdbeCoverageIf(v, (x&1)==1);
          VdbeCoverageIf(v, (x&1)==0);
        }
        VdbeCoverage(v);
#endif
      }
#ifdef WHERETRACE_ENABLED /* 0xffff */
#ifdef WHERETRACE_ENABLED /* 0xffffffff */
      if( sqlite3WhereTrace ){
        VdbeNoopComment((v, "WhereTerm[%d] (%p) priority=%d",
                         pWC->nTerm-j, pTerm, iLoop));
      }
      if( sqlite3WhereTrace & 0x4000 ){
        sqlite3DebugPrintf("Coding auxiliary constraint:\n");
        sqlite3WhereTermPrint(pTerm, pWC->nTerm-j);
      }
#endif
      sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL);
      if( skipLikeAddr ) sqlite3VdbeJumpHere(v, skipLikeAddr);
      pTerm->wtFlags |= TERM_CODED;
    }
    iLoop = iNext;
  }while( iLoop>0 );

  /* Insert code to test for implied constraints based on transitivity
  ** of the "==" operator.
  **
  ** Example: If the WHERE clause contains "t1.a=t2.b" and "t2.b=123"
  ** and we are coding the t1 loop and the t2 loop has not yet coded,
  ** then we cannot use the "t1.a=t2.b" constraint, but we can code
  ** the implied "t1.a=123" constraint.
  */
  for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
  for(pTerm=pWC->a, j=pWC->nBase; j>0; j--, pTerm++){
    Expr *pE, sEAlt;
    WhereTerm *pAlt;
    if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
    if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) continue;
    if( (pTerm->eOperator & WO_EQUIV)==0 ) continue;
    if( pTerm->leftCursor!=iCur ) continue;
    if( pLevel->iLeftJoin ) continue;
    if( pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT) ) continue;
    pE = pTerm->pExpr;
#ifdef WHERETRACE_ENABLED /* 0x4001 */
    if( (sqlite3WhereTrace & 0x4001)==0x4001 ){
      sqlite3DebugPrintf("Coding transitive constraint:\n");
      sqlite3WhereTermPrint(pTerm, pWC->nTerm-j);
    }
#endif
    assert( !ExprHasProperty(pE, EP_FromJoin) );
    assert( !ExprHasProperty(pE, EP_OuterON) );
    assert( (pTerm->prereqRight & pLevel->notReady)!=0 );
    assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
    pAlt = sqlite3WhereFindTerm(pWC, iCur, pTerm->u.leftColumn, notReady,
    pAlt = sqlite3WhereFindTerm(pWC, iCur, pTerm->u.x.leftColumn, notReady,
                    WO_EQ|WO_IN|WO_IS, 0);
    if( pAlt==0 ) continue;
    if( pAlt->wtFlags & (TERM_CODED) ) continue;
    if( (pAlt->eOperator & WO_IN) 
     && (pAlt->pExpr->flags & EP_xIsSelect)
     && ExprUseXSelect(pAlt->pExpr)
     && (pAlt->pExpr->x.pSelect->pEList->nExpr>1)
    ){
      continue;
    }
    testcase( pAlt->eOperator & WO_EQ );
    testcase( pAlt->eOperator & WO_IS );
    testcase( pAlt->eOperator & WO_IN );
    VdbeModuleComment((v, "begin transitive constraint"));
    sEAlt = *pAlt->pExpr;
    sEAlt.pLeft = pE->pLeft;
    sqlite3ExprIfFalse(pParse, &sEAlt, addrCont, SQLITE_JUMPIFNULL);
    pAlt->wtFlags |= TERM_CODED;
  }

  /* For a RIGHT OUTER JOIN, record the fact that the current row has
  ** been matched at least once.
  */
  if( pLevel->pRJ ){
    Table *pTab;
    int nPk;
    int r;
    int jmp1 = 0;
    WhereRightJoin *pRJ = pLevel->pRJ;

    /* pTab is the right-hand table of the RIGHT JOIN.  Generate code that
    ** will record that the current row of that table has been matched at
    ** least once.  This is accomplished by storing the PK for the row in
    ** both the iMatch index and the regBloom Bloom filter.
    */
    pTab = pWInfo->pTabList->a[pLevel->iFrom].pTab;
    if( HasRowid(pTab) ){
      r = sqlite3GetTempRange(pParse, 2);
      sqlite3ExprCodeGetColumnOfTable(v, pTab, pLevel->iTabCur, -1, r+1);
      nPk = 1;
    }else{
      int iPk;
      Index *pPk = sqlite3PrimaryKeyIndex(pTab);
      nPk = pPk->nKeyCol;
      r = sqlite3GetTempRange(pParse, nPk+1);
      for(iPk=0; iPk<nPk; iPk++){
        int iCol = pPk->aiColumn[iPk];
        sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol,r+1+iPk);
      }
    }
    jmp1 = sqlite3VdbeAddOp4Int(v, OP_Found, pRJ->iMatch, 0, r+1, nPk);
    VdbeCoverage(v);
    VdbeComment((v, "match against %s", pTab->zName));
    sqlite3VdbeAddOp3(v, OP_MakeRecord, r+1, nPk, r);
    sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pRJ->iMatch, r, r+1, nPk);
    sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pRJ->regBloom, 0, r+1, nPk);
    sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
    sqlite3VdbeJumpHere(v, jmp1);
    sqlite3ReleaseTempRange(pParse, r, nPk+1);
  }

  /* For a LEFT OUTER JOIN, generate code that will record the fact that
  ** at least one row of the right table has matched the left table.  
  */
  if( pLevel->iLeftJoin ){
    pLevel->addrFirst = sqlite3VdbeCurrentAddr(v);
    sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin);
    VdbeComment((v, "record LEFT JOIN hit"));
    if( pLevel->pRJ==0 ){
      goto code_outer_join_constraints; /* WHERE clause constraints */
    }
  }

  if( pLevel->pRJ ){
    /* Create a subroutine used to process all interior loops and code
    ** of the RIGHT JOIN.  During normal operation, the subroutine will
    ** be in-line with the rest of the code.  But at the end, a separate
    ** loop will run that invokes this subroutine for unmatched rows
    ** of pTab, with all tables to left begin set to NULL.
    */
    WhereRightJoin *pRJ = pLevel->pRJ;
    sqlite3VdbeAddOp2(v, OP_BeginSubrtn, 0, pRJ->regReturn);
    pRJ->addrSubrtn = sqlite3VdbeCurrentAddr(v);
    assert( pParse->withinRJSubrtn < 255 );
    pParse->withinRJSubrtn++;

    /* WHERE clause constraints must be deferred until after outer join
    ** row elimination has completed, since WHERE clause constraints apply
    ** to the results of the OUTER JOIN.  The following loop generates the
    ** appropriate WHERE clause constraint checks.  tag-20220513a.
    */
  code_outer_join_constraints:
    for(pTerm=pWC->a, j=0; j<pWC->nTerm; j++, pTerm++){
    for(pTerm=pWC->a, j=0; j<pWC->nBase; j++, pTerm++){
      testcase( pTerm->wtFlags & TERM_VIRTUAL );
      testcase( pTerm->wtFlags & TERM_CODED );
      if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
      if( (pTerm->prereqAll & pLevel->notReady)!=0 ){
        assert( pWInfo->untestedTerms );
        continue;
      }
      if( pTabItem->fg.jointype & JT_LTORJ ) continue;
      assert( pTerm->pExpr );
      sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL);
      pTerm->wtFlags |= TERM_CODED;
    }
  }

#if WHERETRACE_ENABLED /* 0x4001 */
  if( sqlite3WhereTrace & 0x4000 ){
    sqlite3DebugPrintf("All WHERE-clause terms after coding level %d:\n",
                       iLevel);
    sqlite3WhereClausePrint(pWC);
  }
  if( sqlite3WhereTrace & 0x1 ){
    sqlite3DebugPrintf("End Coding level %d:  notReady=%llx\n",
       iLevel, (u64)pLevel->notReady);
  }
#endif
  return pLevel->notReady;
}

/*
** Generate the code for the loop that finds all non-matched terms
** for a RIGHT JOIN.
*/
SQLITE_NOINLINE void sqlite3WhereRightJoinLoop(
  WhereInfo *pWInfo,
  int iLevel,
  WhereLevel *pLevel
){
  Parse *pParse = pWInfo->pParse;
  Vdbe *v = pParse->pVdbe;
  WhereRightJoin *pRJ = pLevel->pRJ;
  Expr *pSubWhere = 0;
  WhereClause *pWC = &pWInfo->sWC;
  WhereInfo *pSubWInfo;
  WhereLoop *pLoop = pLevel->pWLoop;
  SrcItem *pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
  SrcList sFrom;
  Bitmask mAll = 0;
  int k;

  ExplainQueryPlan((pParse, 1, "RIGHT-JOIN %s", pTabItem->pTab->zName));
  sqlite3VdbeNoJumpsOutsideSubrtn(v, pRJ->addrSubrtn, pRJ->endSubrtn,
                                  pRJ->regReturn);
  for(k=0; k<iLevel; k++){
    int iIdxCur;
    mAll |= pWInfo->a[k].pWLoop->maskSelf;
    sqlite3VdbeAddOp1(v, OP_NullRow, pWInfo->a[k].iTabCur);
    iIdxCur = pWInfo->a[k].iIdxCur;
    if( iIdxCur ){
      sqlite3VdbeAddOp1(v, OP_NullRow, iIdxCur);
    }
  }
  if( (pTabItem->fg.jointype & JT_LTORJ)==0 ){
    mAll |= pLoop->maskSelf;
    for(k=0; k<pWC->nTerm; k++){
      WhereTerm *pTerm = &pWC->a[k];
      if( (pTerm->wtFlags & (TERM_VIRTUAL|TERM_SLICE))!=0
       && pTerm->eOperator!=WO_ROWVAL
      ){
        break;
      }
      if( pTerm->prereqAll & ~mAll ) continue;
      if( ExprHasProperty(pTerm->pExpr, EP_OuterON|EP_InnerON) ) continue;
      pSubWhere = sqlite3ExprAnd(pParse, pSubWhere,
                                 sqlite3ExprDup(pParse->db, pTerm->pExpr, 0));
    }
  }
  sFrom.nSrc = 1;
  sFrom.nAlloc = 1;
  memcpy(&sFrom.a[0], pTabItem, sizeof(SrcItem));
  sFrom.a[0].fg.jointype = 0;
  assert( pParse->withinRJSubrtn < 100 );
  pParse->withinRJSubrtn++;
  pSubWInfo = sqlite3WhereBegin(pParse, &sFrom, pSubWhere, 0, 0, 0,
                                WHERE_RIGHT_JOIN, 0);
  if( pSubWInfo ){
    int iCur = pLevel->iTabCur;
    int r = ++pParse->nMem;
    int nPk;
    int jmp;
    int addrCont = sqlite3WhereContinueLabel(pSubWInfo);
    Table *pTab = pTabItem->pTab;
    if( HasRowid(pTab) ){
      sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, -1, r);
      nPk = 1;
    }else{
      int iPk;
      Index *pPk = sqlite3PrimaryKeyIndex(pTab);
      nPk = pPk->nKeyCol;
      pParse->nMem += nPk - 1;
      for(iPk=0; iPk<nPk; iPk++){
        int iCol = pPk->aiColumn[iPk];
        sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol,r+iPk);
      }
    }
    jmp = sqlite3VdbeAddOp4Int(v, OP_Filter, pRJ->regBloom, 0, r, nPk);
    VdbeCoverage(v);
    sqlite3VdbeAddOp4Int(v, OP_Found, pRJ->iMatch, addrCont, r, nPk);
    VdbeCoverage(v);
    sqlite3VdbeJumpHere(v, jmp);
    sqlite3VdbeAddOp2(v, OP_Gosub, pRJ->regReturn, pRJ->addrSubrtn);
    sqlite3WhereEnd(pSubWInfo);
  }
  sqlite3ExprDelete(pParse->db, pSubWhere);
  ExplainQueryPlanPop(pParse);
  assert( pParse->withinRJSubrtn>0 );
  pParse->withinRJSubrtn--;
}

Changes to src/whereexpr.c.

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
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







-
+








-
-
-
-
+


+





-
+







static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){
  WhereTerm *pTerm;
  int idx;
  testcase( wtFlags & TERM_VIRTUAL );
  if( pWC->nTerm>=pWC->nSlot ){
    WhereTerm *pOld = pWC->a;
    sqlite3 *db = pWC->pWInfo->pParse->db;
    pWC->a = sqlite3DbMallocRawNN(db, sizeof(pWC->a[0])*pWC->nSlot*2 );
    pWC->a = sqlite3WhereMalloc(pWC->pWInfo, sizeof(pWC->a[0])*pWC->nSlot*2 );
    if( pWC->a==0 ){
      if( wtFlags & TERM_DYNAMIC ){
        sqlite3ExprDelete(db, p);
      }
      pWC->a = pOld;
      return 0;
    }
    memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm);
    if( pOld!=pWC->aStatic ){
      sqlite3DbFree(db, pOld);
    }
    pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
    pWC->nSlot = pWC->nSlot*2;
  }
  pTerm = &pWC->a[idx = pWC->nTerm++];
  if( (wtFlags & TERM_VIRTUAL)==0 ) pWC->nBase = pWC->nTerm;
  if( p && ExprHasProperty(p, EP_Unlikely) ){
    pTerm->truthProb = sqlite3LogEst(p->iTable) - 270;
  }else{
    pTerm->truthProb = 1;
  }
  pTerm->pExpr = sqlite3ExprSkipCollate(p);
  pTerm->pExpr = sqlite3ExprSkipCollateAndLikely(p);
  pTerm->wtFlags = wtFlags;
  pTerm->pWC = pWC;
  pTerm->iParent = -1;
  memset(&pTerm->eOperator, 0,
         sizeof(WhereTerm) - offsetof(WhereTerm,eOperator));
  return idx;
}
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
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







-
-
-
-
-
-
-
-

-
+
-
-
+
-
-
-
-
-
-
-
-
+
+
-
-
-
-
+
+
+
-










+







  assert( TK_GE==TK_EQ+4 );
  return op==TK_IN || (op>=TK_EQ && op<=TK_GE) || op==TK_ISNULL || op==TK_IS;
}

/*
** Commute a comparison operator.  Expressions of the form "X op Y"
** are converted into "Y op X".
**
** If left/right precedence rules come into play when determining the
** collating sequence, then COLLATE operators are adjusted to ensure
** that the collating sequence does not change.  For example:
** "Y collate NOCASE op X" becomes "X op Y" because any collation sequence on
** the left hand side of a comparison overrides any collation sequence 
** attached to the right. For the same reason the EP_Collate flag
** is not commuted.
*/
static void exprCommute(Parse *pParse, Expr *pExpr){
static u16 exprCommute(Parse *pParse, Expr *pExpr){
  u16 expRight = (pExpr->pRight->flags & EP_Collate);
  u16 expLeft = (pExpr->pLeft->flags & EP_Collate);
  if( pExpr->pLeft->op==TK_VECTOR
  assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN );
  if( expRight==expLeft ){
    /* Either X and Y both have COLLATE operator or neither do */
    if( expRight ){
      /* Both X and Y have COLLATE operators.  Make sure X is always
      ** used by clearing the EP_Collate flag from Y. */
      pExpr->pRight->flags &= ~EP_Collate;
    }else if( sqlite3ExprCollSeq(pParse, pExpr->pLeft)!=0 ){
   || pExpr->pRight->op==TK_VECTOR
   || sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pRight) !=
      /* Neither X nor Y have COLLATE operators, but X has a non-default
      ** collating sequence.  So add the EP_Collate marker on X to cause
      ** it to be searched first. */
      pExpr->pLeft->flags |= EP_Collate;
      sqlite3BinaryCompareCollSeq(pParse, pExpr->pRight, pExpr->pLeft)
  ){
    pExpr->flags ^= EP_Commuted;
    }
  }
  SWAP(Expr*,pExpr->pRight,pExpr->pLeft);
  if( pExpr->op>=TK_GT ){
    assert( TK_LT==TK_GT+2 );
    assert( TK_GE==TK_LE+2 );
    assert( TK_GT>TK_EQ );
    assert( TK_GT<TK_LE );
    assert( pExpr->op>=TK_GT && pExpr->op<=TK_GE );
    pExpr->op = ((pExpr->op-TK_GT)^2)+TK_GT;
  }
  return 0;
}

/*
** Translate from TK_xx operator to WO_xx bitmask.
*/
static u16 operatorMask(int op){
  u16 c;
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
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







+















+
-
+








  if( !sqlite3IsLikeFunction(db, pExpr, pnoCase, (char*)wc) ){
    return 0;
  }
#ifdef SQLITE_EBCDIC
  if( *pnoCase ) return 0;
#endif
  assert( ExprUseXList(pExpr) );
  pList = pExpr->x.pList;
  pLeft = pList->a[1].pExpr;

  pRight = sqlite3ExprSkipCollate(pList->a[0].pExpr);
  op = pRight->op;
  if( op==TK_VARIABLE && (db->flags & SQLITE_EnableQPSG)==0 ){
    Vdbe *pReprepare = pParse->pReprepare;
    int iCol = pRight->iColumn;
    pVal = sqlite3VdbeGetBoundValue(pReprepare, iCol, SQLITE_AFF_BLOB);
    if( pVal && sqlite3_value_type(pVal)==SQLITE_TEXT ){
      z = sqlite3_value_text(pVal);
    }
    sqlite3VdbeSetVarmask(pParse->pVdbe, iCol);
    assert( pRight->op==TK_VARIABLE || pRight->op==TK_REGISTER );
  }else if( op==TK_STRING ){
    assert( !ExprHasProperty(pRight, EP_IntValue) );
    z = (u8*)pRight->u.zToken;
     z = (u8*)pRight->u.zToken;
  }
  if( z ){

    /* Count the number of prefix characters prior to the first wildcard */
    cnt = 0;
    while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){
      cnt++;
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
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







+
+
-
+






+

-
-
-
+
+
+
-
-
-
+

+
+
-
+
-
-
-
+
+
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+













+







      /* A "complete" match if the pattern ends with "*" or "%" */
      *pisComplete = c==wc[0] && z[cnt+1]==0;

      /* Get the pattern prefix.  Remove all escapes from the prefix. */
      pPrefix = sqlite3Expr(db, TK_STRING, (char*)z);
      if( pPrefix ){
        int iFrom, iTo;
        char *zNew;
        assert( !ExprHasProperty(pPrefix, EP_IntValue) );
        char *zNew = pPrefix->u.zToken;
        zNew = pPrefix->u.zToken;
        zNew[cnt] = 0;
        for(iFrom=iTo=0; iFrom<cnt; iFrom++){
          if( zNew[iFrom]==wc[3] ) iFrom++;
          zNew[iTo++] = zNew[iFrom];
        }
        zNew[iTo] = 0;
        assert( iTo>0 );

        /* If the RHS begins with a digit or a minus sign, then the LHS must be
        ** an ordinary column (not a virtual table column) with TEXT affinity.
        ** Otherwise the LHS might be numeric and "lhs >= rhs" would be false
        /* If the LHS is not an ordinary column with TEXT affinity, then the
        ** pattern prefix boundaries (both the start and end boundaries) must
        ** not look like a number.  Otherwise the pattern might be treated as
        ** even though "lhs LIKE rhs" is true.  But if the RHS does not start
        ** with a digit or '-', then "lhs LIKE rhs" will always be false if
        ** the LHS is numeric and so the optimization still works.
        ** a number, which will invalidate the LIKE optimization.
        **
        ** Getting this right has been a persistent source of bugs in the
        ** LIKE optimization.  See, for example:
        ** 2018-09-10 ticket c94369cae9b561b1f996d0054bfab11389f9d033
        **    2018-09-10 https://sqlite.org/src/info/c94369cae9b561b1
        ** The RHS pattern must not be '/%' because the termination condition
        ** will then become "x<'0'" and if the affinity is numeric, will then
        ** be converted into "x<0", which is incorrect.
        **    2019-05-02 https://sqlite.org/src/info/b043a54c3de54b28
        **    2019-06-10 https://sqlite.org/src/info/fd76310a5e843e07
        **    2019-06-14 https://sqlite.org/src/info/ce8717f0885af975
        **    2019-09-03 https://sqlite.org/src/info/0f0428096f17252a
        */
        if( sqlite3Isdigit(zNew[0])
         || zNew[0]=='-'
         || (zNew[0]+1=='0' && iTo==1)
        ){
          if( pLeft->op!=TK_COLUMN 
           || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT 
           || IsVirtual(pLeft->y.pTab)  /* Value might be numeric */
          ){
        if( pLeft->op!=TK_COLUMN 
         || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT 
         || (ALWAYS( ExprUseYTab(pLeft) )
             && ALWAYS(pLeft->y.pTab)
             && IsVirtual(pLeft->y.pTab))  /* Might be numeric */
        ){
          int isNum;
          double rDummy;
          isNum = sqlite3AtoF(zNew, &rDummy, iTo, SQLITE_UTF8);
          if( isNum<=0 ){
            if( iTo==1 && zNew[0]=='-' ){
              isNum = +1;
            }else{
              zNew[iTo-1]++;
              isNum = sqlite3AtoF(zNew, &rDummy, iTo, SQLITE_UTF8);
              zNew[iTo-1]--;
            }
          }
          if( isNum>0 ){
            sqlite3ExprDelete(db, pPrefix);
            sqlite3ValueFree(pVal);
            return 0;
          }
        }
      }
      *ppPrefix = pPrefix;

      /* If the RHS pattern is a bound parameter, make arrangements to
      ** reprepare the statement when that parameter is rebound */
      if( op==TK_VARIABLE ){
        Vdbe *v = pParse->pVdbe;
        sqlite3VdbeSetVarmask(v, pRight->iColumn);
        assert( !ExprHasProperty(pRight, EP_IntValue) );
        if( *pisComplete && pRight->u.zToken[1] ){
          /* If the rhs of the LIKE expression is a variable, and the current
          ** value of the variable means there is no need to invoke the LIKE
          ** function, then no OP_Variable will be added to the program.
          ** This causes problems for the sqlite3_bind_parameter_name()
          ** API. To work around them, add a dummy OP_Variable here.
          */ 
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
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







+













-
+
+

+




















-
+
+
+







+















-
+
+


+
+
-
+



















-
-
-
+
+
+







      { "like",   SQLITE_INDEX_CONSTRAINT_LIKE },
      { "regexp", SQLITE_INDEX_CONSTRAINT_REGEXP }
    };
    ExprList *pList;
    Expr *pCol;                     /* Column reference */
    int i;

    assert( ExprUseXList(pExpr) );
    pList = pExpr->x.pList;
    if( pList==0 || pList->nExpr!=2 ){
      return 0;
    }

    /* Built-in operators MATCH, GLOB, LIKE, and REGEXP attach to a
    ** virtual table on their second argument, which is the same as
    ** the left-hand side operand in their in-fix form.
    **
    **       vtab_column MATCH expression
    **       MATCH(expression,vtab_column)
    */
    pCol = pList->a[1].pExpr;
    if( pCol->op==TK_COLUMN && IsVirtual(pCol->y.pTab) ){
    assert( pCol->op!=TK_COLUMN || (ExprUseYTab(pCol) && pCol->y.pTab!=0) );
    if( ExprIsVtab(pCol) ){
      for(i=0; i<ArraySize(aOp); i++){
        assert( !ExprHasProperty(pExpr, EP_IntValue) );
        if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){
          *peOp2 = aOp[i].eOp2;
          *ppRight = pList->a[0].pExpr;
          *ppLeft = pCol;
          return 1;
        }
      }
    }

    /* We can also match against the first column of overloaded
    ** functions where xFindFunction returns a value of at least
    ** SQLITE_INDEX_CONSTRAINT_FUNCTION.
    **
    **      OVERLOADED(vtab_column,expression)
    **
    ** Historically, xFindFunction expected to see lower-case function
    ** names.  But for this use case, xFindFunction is expected to deal
    ** with function names in an arbitrary case.
    */
    pCol = pList->a[0].pExpr;
    if( pCol->op==TK_COLUMN && IsVirtual(pCol->y.pTab) ){
    assert( pCol->op!=TK_COLUMN || ExprUseYTab(pCol) );
    assert( pCol->op!=TK_COLUMN || (ExprUseYTab(pCol) && pCol->y.pTab!=0) );
    if( ExprIsVtab(pCol) ){
      sqlite3_vtab *pVtab;
      sqlite3_module *pMod;
      void (*xNotUsed)(sqlite3_context*,int,sqlite3_value**);
      void *pNotUsed;
      pVtab = sqlite3GetVTable(db, pCol->y.pTab)->pVtab;
      assert( pVtab!=0 );
      assert( pVtab->pModule!=0 );
      assert( !ExprHasProperty(pExpr, EP_IntValue) );
      pMod = (sqlite3_module *)pVtab->pModule;
      if( pMod->xFindFunction!=0 ){
        i = pMod->xFindFunction(pVtab,2, pExpr->u.zToken, &xNotUsed, &pNotUsed);
        if( i>=SQLITE_INDEX_CONSTRAINT_FUNCTION ){
          *peOp2 = i;
          *ppRight = pList->a[1].pExpr;
          *ppLeft = pCol;
          return 1;
        }
      }
    }
  }else if( pExpr->op==TK_NE || pExpr->op==TK_ISNOT || pExpr->op==TK_NOTNULL ){
    int res = 0;
    Expr *pLeft = pExpr->pLeft;
    Expr *pRight = pExpr->pRight;
    if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->y.pTab) ){
    assert( pLeft->op!=TK_COLUMN || (ExprUseYTab(pLeft) && pLeft->y.pTab!=0) );
    if( ExprIsVtab(pLeft) ){
      res++;
    }
    assert( pRight==0 || pRight->op!=TK_COLUMN
            || (ExprUseYTab(pRight) && pRight->y.pTab!=0) );
    if( pRight && pRight->op==TK_COLUMN && IsVirtual(pRight->y.pTab) ){
    if( pRight && ExprIsVtab(pRight) ){
      res++;
      SWAP(Expr*, pLeft, pRight);
    }
    *ppLeft = pLeft;
    *ppRight = pRight;
    if( pExpr->op==TK_NE ) *peOp2 = SQLITE_INDEX_CONSTRAINT_NE;
    if( pExpr->op==TK_ISNOT ) *peOp2 = SQLITE_INDEX_CONSTRAINT_ISNOT;
    if( pExpr->op==TK_NOTNULL ) *peOp2 = SQLITE_INDEX_CONSTRAINT_ISNOTNULL;
    return res;
  }
  return 0;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */

/*
** If the pBase expression originated in the ON or USING clause of
** a join, then transfer the appropriate markings over to derived.
*/
static void transferJoinMarkings(Expr *pDerived, Expr *pBase){
  if( pDerived ){
    pDerived->flags |= pBase->flags & EP_FromJoin;
    pDerived->iRightJoinTable = pBase->iRightJoinTable;
  if( pDerived && ExprHasProperty(pBase, EP_OuterON|EP_InnerON) ){
    pDerived->flags |= pBase->flags & (EP_OuterON|EP_InnerON);
    pDerived->w.iJoin = pBase->w.iJoin;
  }
}

/*
** Mark term iChild as being a child of term iParent
*/
static void markTermAsChild(WhereClause *pWC, int iChild, int iParent){
508
509
510
511
512
513
514

515
516
517
518
519
520
521
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531







+







){
  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;
676
677
678
679
680
681
682

683
684
685
686
687
688
689
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700







+







        WhereClause *pAndWC;
        WhereTerm *pAndTerm;
        int j;
        Bitmask b = 0;
        pOrTerm->u.pAndInfo = pAndInfo;
        pOrTerm->wtFlags |= TERM_ANDINFO;
        pOrTerm->eOperator = WO_AND;
        pOrTerm->leftCursor = -1;
        pAndWC = &pAndInfo->wc;
        memset(pAndWC->aStatic, 0, sizeof(pAndWC->aStatic));
        sqlite3WhereClauseInit(pAndWC, pWC->pWInfo);
        sqlite3WhereSplit(pAndWC, pOrTerm->pExpr, TK_AND);
        sqlite3WhereExprAnalyze(pSrc, pAndWC);
        pAndWC->pOuter = pWC;
        if( !db->mallocFailed ){
718
719
720
721
722
723
724
725
726



727
728
729
730
731
732
733
734
735
736
729
730
731
732
733
734
735


736
737
738
739


740
741
742
743
744
745
746







-
-
+
+
+

-
-







  }

  /*
  ** Record the set of tables that satisfy case 3.  The set might be
  ** empty.
  */
  pOrInfo->indexable = indexable;
  if( indexable ){
    pTerm->eOperator = WO_OR;
  pTerm->eOperator = WO_OR;
  pTerm->leftCursor = -1;
  if( indexable ){
    pWC->hasOr = 1;
  }else{
    pTerm->eOperator = WO_OR;
  }

  /* For a two-way OR, attempt to implementation case 2.
  */
  if( indexable && pOrWc->nTerm==2 ){
    int iOne = 0;
    WhereTerm *pOne;
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
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







-
+

















+
-
+



















+

-
-
+
+














-
+
















-
+

+

-
+










-
+




-
+







    ** and column is found but leave okToChngToIN false if not found.
    */
    for(j=0; j<2 && !okToChngToIN; j++){
      Expr *pLeft = 0;
      pOrTerm = pOrWc->a;
      for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){
        assert( pOrTerm->eOperator & WO_EQ );
        pOrTerm->wtFlags &= ~TERM_OR_OK;
        pOrTerm->wtFlags &= ~TERM_OK;
        if( pOrTerm->leftCursor==iCursor ){
          /* This is the 2-bit case and we are on the second iteration and
          ** current term is from the first iteration.  So skip this term. */
          assert( j==1 );
          continue;
        }
        if( (chngToIN & sqlite3WhereGetMask(&pWInfo->sMaskSet,
                                            pOrTerm->leftCursor))==0 ){
          /* This term must be of the form t1.a==t2.b where t2 is in the
          ** chngToIN set but t1 is not.  This term will be either preceded
          ** or follwed by an inverted copy (t2.b==t1.a).  Skip this term 
          ** and use its inversion. */
          testcase( pOrTerm->wtFlags & TERM_COPIED );
          testcase( pOrTerm->wtFlags & TERM_VIRTUAL );
          assert( pOrTerm->wtFlags & (TERM_COPIED|TERM_VIRTUAL) );
          continue;
        }
        assert( (pOrTerm->eOperator & (WO_OR|WO_AND))==0 );
        iColumn = pOrTerm->u.leftColumn;
        iColumn = pOrTerm->u.x.leftColumn;
        iCursor = pOrTerm->leftCursor;
        pLeft = pOrTerm->pExpr->pLeft;
        break;
      }
      if( i<0 ){
        /* No candidate table+column was found.  This can only occur
        ** on the second iteration */
        assert( j==1 );
        assert( IsPowerOfTwo(chngToIN) );
        assert( chngToIN==sqlite3WhereGetMask(&pWInfo->sMaskSet, iCursor) );
        break;
      }
      testcase( j==1 );

      /* We have found a candidate table and column.  Check to see if that
      ** table and column is common to every term in the OR clause */
      okToChngToIN = 1;
      for(; i>=0 && okToChngToIN; i--, pOrTerm++){
        assert( pOrTerm->eOperator & WO_EQ );
        assert( (pOrTerm->eOperator & (WO_OR|WO_AND))==0 );
        if( pOrTerm->leftCursor!=iCursor ){
          pOrTerm->wtFlags &= ~TERM_OR_OK;
        }else if( pOrTerm->u.leftColumn!=iColumn || (iColumn==XN_EXPR 
          pOrTerm->wtFlags &= ~TERM_OK;
        }else if( pOrTerm->u.x.leftColumn!=iColumn || (iColumn==XN_EXPR 
               && sqlite3ExprCompare(pParse, pOrTerm->pExpr->pLeft, pLeft, -1)
        )){
          okToChngToIN = 0;
        }else{
          int affLeft, affRight;
          /* If the right-hand side is also a column, then the affinities
          ** of both right and left sides must be such that no type
          ** conversions are required on the right.  (Ticket #2249)
          */
          affRight = sqlite3ExprAffinity(pOrTerm->pExpr->pRight);
          affLeft = sqlite3ExprAffinity(pOrTerm->pExpr->pLeft);
          if( affRight!=0 && affRight!=affLeft ){
            okToChngToIN = 0;
          }else{
            pOrTerm->wtFlags |= TERM_OR_OK;
            pOrTerm->wtFlags |= TERM_OK;
          }
        }
      }
    }

    /* At this point, okToChngToIN is true if original pTerm satisfies
    ** case 1.  In that case, construct a new virtual term that is 
    ** pTerm converted into an IN operator.
    */
    if( okToChngToIN ){
      Expr *pDup;            /* A transient duplicate expression */
      ExprList *pList = 0;   /* The RHS of the IN operator */
      Expr *pLeft = 0;       /* The LHS of the IN operator */
      Expr *pNew;            /* The complete IN operator */

      for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){
        if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue;
        if( (pOrTerm->wtFlags & TERM_OK)==0 ) continue;
        assert( pOrTerm->eOperator & WO_EQ );
        assert( (pOrTerm->eOperator & (WO_OR|WO_AND))==0 );
        assert( pOrTerm->leftCursor==iCursor );
        assert( pOrTerm->u.leftColumn==iColumn );
        assert( pOrTerm->u.x.leftColumn==iColumn );
        pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0);
        pList = sqlite3ExprListAppend(pWInfo->pParse, pList, pDup);
        pLeft = pOrTerm->pExpr->pLeft;
      }
      assert( pLeft!=0 );
      pDup = sqlite3ExprDup(db, pLeft, 0);
      pNew = sqlite3PExpr(pParse, TK_IN, pDup, 0);
      if( pNew ){
        int idxNew;
        transferJoinMarkings(pNew, pExpr);
        assert( !ExprHasProperty(pNew, EP_xIsSelect) );
        assert( ExprUseXList(pNew) );
        pNew->x.pList = pList;
        idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);
        testcase( idxNew==0 );
        exprAnalyze(pSrc, pWC, idxNew);
        /* pTerm = &pWC->a[idxTerm]; // would be needed if pTerm where used again */
        /* pTerm = &pWC->a[idxTerm]; // would be needed if pTerm where reused */
        markTermAsChild(pWC, idxNew, idxTerm);
      }else{
        sqlite3ExprListDelete(db, pList);
      }
    }
  }
}
898
899
900
901
902
903
904
905

906
907
908
909
910
911
912
913

914
915
916
917
918
919
920
911
912
913
914
915
916
917

918
919
920
921
922
923
924
925

926
927
928
929
930
931
932
933







-
+







-
+







** returned when it should not be, then incorrect answers might result.
*/
static int termIsEquivalence(Parse *pParse, Expr *pExpr){
  char aff1, aff2;
  CollSeq *pColl;
  if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0;
  if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0;
  if( ExprHasProperty(pExpr, EP_FromJoin) ) return 0;
  if( ExprHasProperty(pExpr, EP_OuterON) ) return 0;
  aff1 = sqlite3ExprAffinity(pExpr->pLeft);
  aff2 = sqlite3ExprAffinity(pExpr->pRight);
  if( aff1!=aff2
   && (!sqlite3IsNumericAffinity(aff1) || !sqlite3IsNumericAffinity(aff2))
  ){
    return 0;
  }
  pColl = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pRight);
  pColl = sqlite3ExprCompareCollSeq(pParse, pExpr);
  if( sqlite3IsBinary(pColl) ) return 1;
  return sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight);
}

/*
** Recursively walk the expressions of a SELECT statement and generate
** a bitmask indicating which tables are used in that expression
929
930
931
932
933
934
935

936


937
938
939
940
941
942
943
942
943
944
945
946
947
948
949

950
951
952
953
954
955
956
957
958







+
-
+
+







    mask |= sqlite3WhereExprListUsage(pMaskSet, pS->pOrderBy);
    mask |= sqlite3WhereExprUsage(pMaskSet, pS->pWhere);
    mask |= sqlite3WhereExprUsage(pMaskSet, pS->pHaving);
    if( ALWAYS(pSrc!=0) ){
      int i;
      for(i=0; i<pSrc->nSrc; i++){
        mask |= exprSelectUsage(pMaskSet, pSrc->a[i].pSelect);
        if( pSrc->a[i].fg.isUsing==0 ){
        mask |= sqlite3WhereExprUsage(pMaskSet, pSrc->a[i].pOn);
          mask |= sqlite3WhereExprUsage(pMaskSet, pSrc->a[i].u3.pOn);
        }
        if( pSrc->a[i].fg.isTabFunc ){
          mask |= sqlite3WhereExprListUsage(pMaskSet, pSrc->a[i].u1.pFuncArg);
        }
      }
    }
    pS = pS->pPrior;
  }
968
969
970
971
972
973
974

975
976
977
978
979
980
981
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997







+







  int iCur;
  for(i=0; mPrereq>1; i++, mPrereq>>=1){}
  iCur = pFrom->a[i].iCursor;
  for(pIdx=pFrom->a[i].pTab->pIndex; pIdx; pIdx=pIdx->pNext){
    if( pIdx->aColExpr==0 ) continue;
    for(i=0; i<pIdx->nKeyCol; i++){
      if( pIdx->aiColumn[i]!=XN_EXPR ) continue;
      assert( pIdx->bHasExpr );
      if( sqlite3ExprCompareSkip(pExpr, pIdx->aColExpr->a[i].pExpr, iCur)==0 ){
        aiCurCol[0] = iCur;
        aiCurCol[1] = XN_EXPR;
        return 1;
      }
    }
  }
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
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







+

+











+







  /* If this expression is a vector to the left or right of a 
  ** inequality constraint (>, <, >= or <=), perform the processing 
  ** on the first element of the vector.  */
  assert( TK_GT+1==TK_LE && TK_GT+2==TK_LT && TK_GT+3==TK_GE );
  assert( TK_IS<TK_GE && TK_ISNULL<TK_GE && TK_IN<TK_GE );
  assert( op<=TK_GE );
  if( pExpr->op==TK_VECTOR && (op>=TK_GT && ALWAYS(op<=TK_GE)) ){
    assert( ExprUseXList(pExpr) );
    pExpr = pExpr->x.pList->a[0].pExpr;

  }

  if( pExpr->op==TK_COLUMN ){
    aiCurCol[0] = pExpr->iTable;
    aiCurCol[1] = pExpr->iColumn;
    return 1;
  }
  if( mPrereq==0 ) return 0;                 /* No table references */
  if( (mPrereq&(mPrereq-1))!=0 ) return 0;   /* Refs more than one table */
  return exprMightBeIndexed2(pFrom,mPrereq,aiCurCol,pExpr);
}


/*
** The input to this routine is an WhereTerm structure with only the
** "pExpr" field filled in.  The job of this routine is to analyze the
** subexpression and populate all the other fields of the WhereTerm
** structure.
**
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
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







+



+

+





-
+




-
-
+


+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+












-
+


+
-
+




+
-
+





+




-
+







  sqlite3 *db = pParse->db;        /* Database connection */
  unsigned char eOp2 = 0;          /* op2 value for LIKE/REGEXP/GLOB */
  int nLeft;                       /* Number of elements on left side vector */

  if( db->mallocFailed ){
    return;
  }
  assert( pWC->nTerm > idxTerm );
  pTerm = &pWC->a[idxTerm];
  pMaskSet = &pWInfo->sMaskSet;
  pExpr = pTerm->pExpr;
  assert( pExpr!=0 ); /* Because malloc() has not failed */
  assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE );
  pMaskSet->bVarSelect = 0;
  prereqLeft = sqlite3WhereExprUsage(pMaskSet, pExpr->pLeft);
  op = pExpr->op;
  if( op==TK_IN ){
    assert( pExpr->pRight==0 );
    if( sqlite3ExprCheckIN(pParse, pExpr) ) return;
    if( ExprHasProperty(pExpr, EP_xIsSelect) ){
    if( ExprUseXSelect(pExpr) ){
      pTerm->prereqRight = exprSelectUsage(pMaskSet, pExpr->x.pSelect);
    }else{
      pTerm->prereqRight = sqlite3WhereExprListUsage(pMaskSet, pExpr->x.pList);
    }
  }else if( op==TK_ISNULL ){
    pTerm->prereqRight = 0;
    prereqAll = prereqLeft | pTerm->prereqRight;
  }else{
    pTerm->prereqRight = sqlite3WhereExprUsage(pMaskSet, pExpr->pRight);
    if( pExpr->pLeft==0
     || ExprHasProperty(pExpr, EP_xIsSelect|EP_IfNullRow)
     || pExpr->x.pList!=0
    ){
      prereqAll = sqlite3WhereExprUsageNN(pMaskSet, pExpr);
    }else{
      prereqAll = prereqLeft | pTerm->prereqRight;
  }
  pMaskSet->bVarSelect = 0;
  prereqAll = sqlite3WhereExprUsageNN(pMaskSet, pExpr);
  if( pMaskSet->bVarSelect ) pTerm->wtFlags |= TERM_VARSELECT;
  if( ExprHasProperty(pExpr, EP_FromJoin) ){
    Bitmask x = sqlite3WhereGetMask(pMaskSet, pExpr->iRightJoinTable);
    prereqAll |= x;
    extraRight = x-1;  /* ON clause terms may not be used with an index
                       ** on left table of a LEFT JOIN.  Ticket #3015 */
    if( (prereqAll>>1)>=x ){
      sqlite3ErrorMsg(pParse, "ON clause references tables to its right");
      return;
    }
  }
  if( pMaskSet->bVarSelect ) pTerm->wtFlags |= TERM_VARSELECT;

#ifdef SQLITE_DEBUG
  if( prereqAll!=sqlite3WhereExprUsageNN(pMaskSet, pExpr) ){
    printf("\n*** Incorrect prereqAll computed for:\n");
    sqlite3TreeViewExpr(0,pExpr,0);
    assert( 0 );
  }
#endif

  if( ExprHasProperty(pExpr, EP_OuterON|EP_InnerON) ){
    Bitmask x = sqlite3WhereGetMask(pMaskSet, pExpr->w.iJoin);
    if( ExprHasProperty(pExpr, EP_OuterON) ){
      prereqAll |= x;
      extraRight = x-1;  /* ON clause terms may not be used with an index
                         ** on left table of a LEFT JOIN.  Ticket #3015 */
      if( (prereqAll>>1)>=x ){
        sqlite3ErrorMsg(pParse, "ON clause references tables to its right");
        return;
      }
    }else if( (prereqAll>>1)>=x ){
      /* The ON clause of an INNER JOIN references a table to its right.
      ** Most other SQL database engines raise an error.  But SQLite versions
      ** 3.0 through 3.38 just put the ON clause constraint into the WHERE
      ** clause and carried on.   Beginning with 3.39, raise an error only
      ** if there is a RIGHT or FULL JOIN in the query.  This makes SQLite
      ** more like other systems, and also preserves legacy. */
      if( ALWAYS(pSrc->nSrc>0) && (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){
        sqlite3ErrorMsg(pParse, "ON clause references tables to its right");
        return;
      }
      ExprClearProperty(pExpr, EP_InnerON);
    }
  }
  pTerm->prereqAll = prereqAll;
  pTerm->leftCursor = -1;
  pTerm->iParent = -1;
  pTerm->eOperator = 0;
  if( allowedOp(op) ){
    int aiCurCol[2];
    Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft);
    Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight);
    u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV;

    if( pTerm->iField>0 ){
    if( pTerm->u.x.iField>0 ){
      assert( op==TK_IN );
      assert( pLeft->op==TK_VECTOR );
      assert( ExprUseXList(pLeft) );
      pLeft = pLeft->x.pList->a[pTerm->iField-1].pExpr;
      pLeft = pLeft->x.pList->a[pTerm->u.x.iField-1].pExpr;
    }

    if( exprMightBeIndexed(pSrc, prereqLeft, aiCurCol, pLeft, op) ){
      pTerm->leftCursor = aiCurCol[0];
      assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
      pTerm->u.leftColumn = aiCurCol[1];
      pTerm->u.x.leftColumn = aiCurCol[1];
      pTerm->eOperator = operatorMask(op) & opMask;
    }
    if( op==TK_IS ) pTerm->wtFlags |= TERM_IS;
    if( pRight 
     && exprMightBeIndexed(pSrc, pTerm->prereqRight, aiCurCol, pRight, op)
     && !ExprHasProperty(pRight, EP_FixedCol)
    ){
      WhereTerm *pNew;
      Expr *pDup;
      u16 eExtraOp = 0;        /* Extra bits for pNew->eOperator */
      assert( pTerm->iField==0 );
      assert( pTerm->u.x.iField==0 );
      if( pTerm->leftCursor>=0 ){
        int idxNew;
        pDup = sqlite3ExprDup(db, pExpr, 0);
        if( db->mallocFailed ){
          sqlite3ExprDelete(db, pDup);
          return;
        }
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
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







-
+

+
-
+




+
+
+
+
+
+
+
+
+
+
+




















-
+


+
+







          pTerm->eOperator |= WO_EQUIV;
          eExtraOp = WO_EQUIV;
        }
      }else{
        pDup = pExpr;
        pNew = pTerm;
      }
      exprCommute(pParse, pDup);
      pNew->wtFlags |= exprCommute(pParse, pDup);
      pNew->leftCursor = aiCurCol[0];
      assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
      pNew->u.leftColumn = aiCurCol[1];
      pNew->u.x.leftColumn = aiCurCol[1];
      testcase( (prereqLeft | extraRight) != prereqLeft );
      pNew->prereqRight = prereqLeft | extraRight;
      pNew->prereqAll = prereqAll;
      pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask;
    }else 
    if( op==TK_ISNULL
     && !ExprHasProperty(pExpr,EP_OuterON)
     && 0==sqlite3ExprCanBeNull(pLeft)
    ){
      assert( !ExprHasProperty(pExpr, EP_IntValue) );
      pExpr->op = TK_TRUEFALSE;
      pExpr->u.zToken = "false";
      ExprSetProperty(pExpr, EP_IsFalse);
      pTerm->prereqAll = 0;
      pTerm->eOperator = 0;
    }
  }

#ifndef SQLITE_OMIT_BETWEEN_OPTIMIZATION
  /* If a term is the BETWEEN operator, create two new virtual terms
  ** that define the range that the BETWEEN implements.  For example:
  **
  **      a BETWEEN b AND c
  **
  ** is converted into:
  **
  **      (a BETWEEN b AND c) AND (a>=b) AND (a<=c)
  **
  ** The two new terms are added onto the end of the WhereClause object.
  ** The new terms are "dynamic" and are children of the original BETWEEN
  ** term.  That means that if the BETWEEN term is coded, the children are
  ** skipped.  Or, if the children are satisfied by an index, the original
  ** BETWEEN term is skipped.
  */
  else if( pExpr->op==TK_BETWEEN && pWC->op==TK_AND ){
    ExprList *pList = pExpr->x.pList;
    ExprList *pList;
    int i;
    static const u8 ops[] = {TK_GE, TK_LE};
    assert( ExprUseXList(pExpr) );
    pList = pExpr->x.pList;
    assert( pList!=0 );
    assert( pList->nExpr==2 );
    for(i=0; i<2; i++){
      Expr *pNewExpr;
      int idxNew;
      pNewExpr = sqlite3PExpr(pParse, ops[i], 
                             sqlite3ExprDup(db, pExpr->pLeft, 0),
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
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
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+















+
-
+











+


+
+
+







  */
  else if( pExpr->op==TK_OR ){
    assert( pWC->op==TK_AND );
    exprAnalyzeOrTerm(pSrc, pWC, idxTerm);
    pTerm = &pWC->a[idxTerm];
  }
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
  /* The form "x IS NOT NULL" can sometimes be evaluated more efficiently
  ** as "x>NULL" if x is not an INTEGER PRIMARY KEY.  So construct a
  ** virtual term of that form.
  **
  ** The virtual term must be tagged with TERM_VNULL.
  */
  else if( pExpr->op==TK_NOTNULL ){
    if( pExpr->pLeft->op==TK_COLUMN
     && pExpr->pLeft->iColumn>=0
     && !ExprHasProperty(pExpr, EP_OuterON)
    ){
      Expr *pNewExpr;
      Expr *pLeft = pExpr->pLeft;
      int idxNew;
      WhereTerm *pNewTerm;
  
      pNewExpr = sqlite3PExpr(pParse, TK_GT,
                              sqlite3ExprDup(db, pLeft, 0),
                              sqlite3ExprAlloc(db, TK_NULL, 0, 0));
  
      idxNew = whereClauseInsert(pWC, pNewExpr,
                                TERM_VIRTUAL|TERM_DYNAMIC|TERM_VNULL);
      if( idxNew ){
        pNewTerm = &pWC->a[idxNew];
        pNewTerm->prereqRight = 0;
        pNewTerm->leftCursor = pLeft->iTable;
        pNewTerm->u.x.leftColumn = pLeft->iColumn;
        pNewTerm->eOperator = WO_GT;
        markTermAsChild(pWC, idxNew, idxTerm);
        pTerm = &pWC->a[idxTerm];
        pTerm->wtFlags |= TERM_COPIED;
        pNewTerm->prereqAll = pTerm->prereqAll;
      }
    }
  }


#ifndef SQLITE_OMIT_LIKE_OPTIMIZATION
  /* Add constraints to reduce the search space on a LIKE or GLOB
  ** operator.
  **
  ** A like pattern of the form "x LIKE 'aBc%'" is changed into constraints
  **
  **          x>='ABC' AND x<'abd' AND x LIKE 'aBc%'
  **
  ** The last character of the prefix "abc" is incremented to form the
  ** termination condition "abd".  If case is not significant (the default
  ** for LIKE) then the lower-bound is made all uppercase and the upper-
  ** bound is made all lowercase so that the bounds also work when comparing
  ** BLOBs.
  */
  else if( pExpr->op==TK_FUNCTION
  if( pWC->op==TK_AND 
   && pWC->op==TK_AND
   && isLikeOrGlob(pParse, pExpr, &pStr1, &isComplete, &noCase)
  ){
    Expr *pLeft;       /* LHS of LIKE/GLOB operator */
    Expr *pStr2;       /* Copy of pStr1 - RHS of LIKE/GLOB operator */
    Expr *pNewExpr1;
    Expr *pNewExpr2;
    int idxNew1;
    int idxNew2;
    const char *zCollSeqName;     /* Name of collating sequence */
    const u16 wtFlags = TERM_LIKEOPT | TERM_VIRTUAL | TERM_DYNAMIC;

    assert( ExprUseXList(pExpr) );
    pLeft = pExpr->x.pList->a[1].pExpr;
    pStr2 = sqlite3ExprDup(db, pStr1, 0);
    assert( pStr1==0 || !ExprHasProperty(pStr1, EP_IntValue) );
    assert( pStr2==0 || !ExprHasProperty(pStr2, EP_IntValue) );
 

    /* Convert the lower bound to upper-case and the upper bound to
    ** lower-case (upper-case is less than lower-case in ASCII) so that
    ** the range constraints also work for BLOBs
    */
    if( noCase && !pParse->db->mallocFailed ){
      int i;
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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
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
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460

1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474


1475
1476
1477
1478
1479
1480
1481
1482
1483

1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496




























































































1497
1498
1499
1500
1501
1502
1503







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+











-
+













-
-
+
+
+






-
+












-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







    pTerm = &pWC->a[idxTerm];
    if( isComplete ){
      markTermAsChild(pWC, idxNew1, idxTerm);
      markTermAsChild(pWC, idxNew2, idxTerm);
    }
  }
#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */

  /* If there is a vector == or IS term - e.g. "(a, b) == (?, ?)" - create
  ** new terms for each component comparison - "a = ?" and "b = ?".  The
  ** new terms completely replace the original vector comparison, which is
  ** no longer used.
  **
  ** This is only required if at least one side of the comparison operation
  ** is not a sub-select.
  **
  ** tag-20220128a
  */
  if( (pExpr->op==TK_EQ || pExpr->op==TK_IS)
   && (nLeft = sqlite3ExprVectorSize(pExpr->pLeft))>1
   && sqlite3ExprVectorSize(pExpr->pRight)==nLeft
   && ( (pExpr->pLeft->flags & EP_xIsSelect)==0 
     || (pExpr->pRight->flags & EP_xIsSelect)==0)
   && pWC->op==TK_AND
  ){
    int i;
    for(i=0; i<nLeft; i++){
      int idxNew;
      Expr *pNew;
      Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i, nLeft);
      Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i, nLeft);

      pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight);
      transferJoinMarkings(pNew, pExpr);
      idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC|TERM_SLICE);
      exprAnalyze(pSrc, pWC, idxNew);
    }
    pTerm = &pWC->a[idxTerm];
    pTerm->wtFlags |= TERM_CODED|TERM_VIRTUAL;  /* Disable the original */
    pTerm->eOperator = WO_ROWVAL;
  }

  /* If there is a vector IN term - e.g. "(a, b) IN (SELECT ...)" - create
  ** a virtual term for each vector component. The expression object
  ** used by each such virtual term is pExpr (the full vector IN(...) 
  ** expression). The WhereTerm.u.x.iField variable identifies the index within
  ** the vector on the LHS that the virtual term represents.
  **
  ** This only works if the RHS is a simple SELECT (not a compound) that does
  ** not use window functions.
  */
  else if( pExpr->op==TK_IN
   && pTerm->u.x.iField==0
   && pExpr->pLeft->op==TK_VECTOR
   && ALWAYS( ExprUseXSelect(pExpr) )
   && pExpr->x.pSelect->pPrior==0
#ifndef SQLITE_OMIT_WINDOWFUNC
   && pExpr->x.pSelect->pWin==0
#endif
   && pWC->op==TK_AND
  ){
    int i;
    for(i=0; i<sqlite3ExprVectorSize(pExpr->pLeft); i++){
      int idxNew;
      idxNew = whereClauseInsert(pWC, pExpr, TERM_VIRTUAL|TERM_SLICE);
      pWC->a[idxNew].u.x.iField = i+1;
      exprAnalyze(pSrc, pWC, idxNew);
      markTermAsChild(pWC, idxNew, idxTerm);
    }
  }

#ifndef SQLITE_OMIT_VIRTUALTABLE
  /* Add a WO_AUX auxiliary term to the constraint set if the
  ** current expression is of the form "column OP expr" where OP
  ** is an operator that gets passed into virtual tables but which is
  ** not normally optimized for ordinary tables.  In other words, OP
  ** is one of MATCH, LIKE, GLOB, REGEXP, !=, IS, IS NOT, or NOT NULL.
  ** This information is used by the xBestIndex methods of
  ** virtual tables.  The native query optimizer does not attempt
  ** to do anything with MATCH functions.
  */
  if( pWC->op==TK_AND ){
  else if( pWC->op==TK_AND ){
    Expr *pRight = 0, *pLeft = 0;
    int res = isAuxiliaryVtabOperator(db, pExpr, &eOp2, &pLeft, &pRight);
    while( res-- > 0 ){
      int idxNew;
      WhereTerm *pNewTerm;
      Bitmask prereqColumn, prereqExpr;

      prereqExpr = sqlite3WhereExprUsage(pMaskSet, pRight);
      prereqColumn = sqlite3WhereExprUsage(pMaskSet, pLeft);
      if( (prereqExpr & prereqColumn)==0 ){
        Expr *pNewExpr;
        pNewExpr = sqlite3PExpr(pParse, TK_MATCH, 
            0, sqlite3ExprDup(db, pRight, 0));
        if( ExprHasProperty(pExpr, EP_FromJoin) && pNewExpr ){
          ExprSetProperty(pNewExpr, EP_FromJoin);
        if( ExprHasProperty(pExpr, EP_OuterON) && pNewExpr ){
          ExprSetProperty(pNewExpr, EP_OuterON);
          pNewExpr->w.iJoin = pExpr->w.iJoin;
        }
        idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
        testcase( idxNew==0 );
        pNewTerm = &pWC->a[idxNew];
        pNewTerm->prereqRight = prereqExpr;
        pNewTerm->leftCursor = pLeft->iTable;
        pNewTerm->u.leftColumn = pLeft->iColumn;
        pNewTerm->u.x.leftColumn = pLeft->iColumn;
        pNewTerm->eOperator = WO_AUX;
        pNewTerm->eMatchOp = eOp2;
        markTermAsChild(pWC, idxNew, idxTerm);
        pTerm = &pWC->a[idxTerm];
        pTerm->wtFlags |= TERM_COPIED;
        pNewTerm->prereqAll = pTerm->prereqAll;
      }
      SWAP(Expr*, pLeft, pRight);
    }
  }
#endif /* SQLITE_OMIT_VIRTUALTABLE */

  /* If there is a vector == or IS term - e.g. "(a, b) == (?, ?)" - create
  ** new terms for each component comparison - "a = ?" and "b = ?".  The
  ** new terms completely replace the original vector comparison, which is
  ** no longer used.
  **
  ** This is only required if at least one side of the comparison operation
  ** is not a sub-select.  */
  if( pWC->op==TK_AND 
  && (pExpr->op==TK_EQ || pExpr->op==TK_IS)
  && (nLeft = sqlite3ExprVectorSize(pExpr->pLeft))>1
  && sqlite3ExprVectorSize(pExpr->pRight)==nLeft
  && ( (pExpr->pLeft->flags & EP_xIsSelect)==0 
    || (pExpr->pRight->flags & EP_xIsSelect)==0)
  ){
    int i;
    for(i=0; i<nLeft; i++){
      int idxNew;
      Expr *pNew;
      Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i);
      Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i);

      pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight);
      transferJoinMarkings(pNew, pExpr);
      idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC);
      exprAnalyze(pSrc, pWC, idxNew);
    }
    pTerm = &pWC->a[idxTerm];
    pTerm->wtFlags |= TERM_CODED|TERM_VIRTUAL;  /* Disable the original */
    pTerm->eOperator = 0;
  }

  /* If there is a vector IN term - e.g. "(a, b) IN (SELECT ...)" - create
  ** a virtual term for each vector component. The expression object
  ** used by each such virtual term is pExpr (the full vector IN(...) 
  ** expression). The WhereTerm.iField variable identifies the index within
  ** the vector on the LHS that the virtual term represents.
  **
  ** This only works if the RHS is a simple SELECT, not a compound
  */
  if( pWC->op==TK_AND && pExpr->op==TK_IN && pTerm->iField==0
   && pExpr->pLeft->op==TK_VECTOR
   && pExpr->x.pSelect->pPrior==0
  ){
    int i;
    for(i=0; i<sqlite3ExprVectorSize(pExpr->pLeft); i++){
      int idxNew;
      idxNew = whereClauseInsert(pWC, pExpr, TERM_VIRTUAL);
      pWC->a[idxNew].iField = i+1;
      exprAnalyze(pSrc, pWC, idxNew);
      markTermAsChild(pWC, idxNew, idxTerm);
    }
  }

#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  /* When sqlite_stat3 histogram data is available an operator of 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.
  **
  ** Note that the virtual term must be tagged with TERM_VNULL.
  */
  if( pExpr->op==TK_NOTNULL
   && pExpr->pLeft->op==TK_COLUMN
   && pExpr->pLeft->iColumn>=0
   && !ExprHasProperty(pExpr, EP_FromJoin)
   && OptimizationEnabled(db, SQLITE_Stat34)
  ){
    Expr *pNewExpr;
    Expr *pLeft = pExpr->pLeft;
    int idxNew;
    WhereTerm *pNewTerm;

    pNewExpr = sqlite3PExpr(pParse, TK_GT,
                            sqlite3ExprDup(db, pLeft, 0),
                            sqlite3ExprAlloc(db, TK_NULL, 0, 0));

    idxNew = whereClauseInsert(pWC, pNewExpr,
                              TERM_VIRTUAL|TERM_DYNAMIC|TERM_VNULL);
    if( idxNew ){
      pNewTerm = &pWC->a[idxNew];
      pNewTerm->prereqRight = 0;
      pNewTerm->leftCursor = pLeft->iTable;
      pNewTerm->u.leftColumn = pLeft->iColumn;
      pNewTerm->eOperator = WO_GT;
      markTermAsChild(pWC, idxNew, idxTerm);
      pTerm = &pWC->a[idxTerm];
      pTerm->wtFlags |= TERM_COPIED;
      pNewTerm->prereqAll = pTerm->prereqAll;
    }
  }
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */

  /* Prevent ON clause terms of a LEFT JOIN from being used to drive
  ** an index for tables to the left of the join.
  */
  testcase( pTerm!=&pWC->a[idxTerm] );
  pTerm = &pWC->a[idxTerm];
  pTerm->prereqRight |= extraRight;
}
1441
1442
1443
1444
1445
1446
1447
1448

1449

1450
1451
1452
1453
1454
1455
1456
1457


















































































































1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469

1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482

1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493

























1494


1495
1496
1497
1498
1499
1500
1501
1502


























1503

1504



1505






















1506
1507
1508
1509
1510
1511
1512
1513
1514
1515

1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
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
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
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675


1676
1677











1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
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
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772




1773








1774
1775
1776
1777
1778
1779
1780







-
+

+








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+












+










-
-

+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
-
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
-
-
-
+
-
-
-
-
-
-
-
-







** does is make slot[] entries point to substructure within pExpr.
**
** In the previous sentence and in the diagram, "slot[]" refers to
** the WhereClause.a[] array.  The slot[] array grows as needed to contain
** all terms of the WHERE clause.
*/
void sqlite3WhereSplit(WhereClause *pWC, Expr *pExpr, u8 op){
  Expr *pE2 = sqlite3ExprSkipCollate(pExpr);
  Expr *pE2 = sqlite3ExprSkipCollateAndLikely(pExpr);
  pWC->op = op;
  assert( pE2!=0 || pExpr==0 );
  if( pE2==0 ) return;
  if( pE2->op!=op ){
    whereClauseInsert(pWC, pExpr, 0);
  }else{
    sqlite3WhereSplit(pWC, pE2->pLeft, op);
    sqlite3WhereSplit(pWC, pE2->pRight, op);
  }
}

/*
** Add either a LIMIT (if eMatchOp==SQLITE_INDEX_CONSTRAINT_LIMIT) or 
** OFFSET (if eMatchOp==SQLITE_INDEX_CONSTRAINT_OFFSET) term to the 
** where-clause passed as the first argument. The value for the term
** is found in register iReg.
**
** In the common case where the value is a simple integer 
** (example: "LIMIT 5 OFFSET 10") then the expression codes as a
** TK_INTEGER so that it will be available to sqlite3_vtab_rhs_value().
** If not, then it codes as a TK_REGISTER expression.
*/
static void whereAddLimitExpr(
  WhereClause *pWC,   /* Add the constraint to this WHERE clause */
  int iReg,           /* Register that will hold value of the limit/offset */
  Expr *pExpr,        /* Expression that defines the limit/offset */
  int iCsr,           /* Cursor to which the constraint applies */
  int eMatchOp        /* SQLITE_INDEX_CONSTRAINT_LIMIT or _OFFSET */
){
  Parse *pParse = pWC->pWInfo->pParse;
  sqlite3 *db = pParse->db;
  Expr *pNew;
  int iVal = 0;

  if( sqlite3ExprIsInteger(pExpr, &iVal) && iVal>=0 ){
    Expr *pVal = sqlite3Expr(db, TK_INTEGER, 0);
    if( pVal==0 ) return;
    ExprSetProperty(pVal, EP_IntValue);
    pVal->u.iValue = iVal;
    pNew = sqlite3PExpr(pParse, TK_MATCH, 0, pVal);
  }else{
    Expr *pVal = sqlite3Expr(db, TK_REGISTER, 0);
    if( pVal==0 ) return;
    pVal->iTable = iReg;
    pNew = sqlite3PExpr(pParse, TK_MATCH, 0, pVal);
  }
  if( pNew ){
    WhereTerm *pTerm;
    int idx;
    idx = whereClauseInsert(pWC, pNew, TERM_DYNAMIC|TERM_VIRTUAL);
    pTerm = &pWC->a[idx];
    pTerm->leftCursor = iCsr;
    pTerm->eOperator = WO_AUX;
    pTerm->eMatchOp = eMatchOp;
  }
}

/*
** Possibly add terms corresponding to the LIMIT and OFFSET clauses of the
** SELECT statement passed as the second argument. These terms are only
** added if:
**
**   1. The SELECT statement has a LIMIT clause, and
**   2. The SELECT statement is not an aggregate or DISTINCT query, and
**   3. The SELECT statement has exactly one object in its from clause, and
**      that object is a virtual table, and
**   4. There are no terms in the WHERE clause that will not be passed
**      to the virtual table xBestIndex method.
**   5. The ORDER BY clause, if any, will be made available to the xBestIndex
**      method.
**
** LIMIT and OFFSET terms are ignored by most of the planner code. They
** exist only so that they may be passed to the xBestIndex method of the
** single virtual table in the FROM clause of the SELECT.
*/
void SQLITE_NOINLINE sqlite3WhereAddLimit(WhereClause *pWC, Select *p){
  assert( p!=0 && p->pLimit!=0 );                 /* 1 -- checked by caller */
  if( p->pGroupBy==0
   && (p->selFlags & (SF_Distinct|SF_Aggregate))==0             /* 2 */
   && (p->pSrc->nSrc==1 && IsVirtual(p->pSrc->a[0].pTab))       /* 3 */
  ){
    ExprList *pOrderBy = p->pOrderBy;
    int iCsr = p->pSrc->a[0].iCursor;
    int ii;

    /* Check condition (4). Return early if it is not met. */
    for(ii=0; ii<pWC->nTerm; ii++){
      if( pWC->a[ii].wtFlags & TERM_CODED ){
        /* This term is a vector operation that has been decomposed into
        ** other, subsequent terms.  It can be ignored. See tag-20220128a */
        assert( pWC->a[ii].wtFlags & TERM_VIRTUAL );
        assert( pWC->a[ii].eOperator==WO_ROWVAL );
        continue;
      }
      if( pWC->a[ii].nChild ){
        /* If this term has child terms, then they are also part of the
        ** pWC->a[] array. So this term can be ignored, as a LIMIT clause
        ** will only be added if each of the child terms passes the 
        ** (leftCursor==iCsr) test below.  */
        continue;
      }
      if( pWC->a[ii].leftCursor!=iCsr ) return;
    }

    /* Check condition (5). Return early if it is not met. */
    if( pOrderBy ){
      for(ii=0; ii<pOrderBy->nExpr; ii++){
        Expr *pExpr = pOrderBy->a[ii].pExpr;
        if( pExpr->op!=TK_COLUMN ) return;
        if( pExpr->iTable!=iCsr ) return;
        if( pOrderBy->a[ii].fg.sortFlags & KEYINFO_ORDER_BIGNULL ) return;
      }
    }

    /* All conditions are met. Add the terms to the where-clause object. */
    assert( p->pLimit->op==TK_LIMIT );
    whereAddLimitExpr(pWC, p->iLimit, p->pLimit->pLeft,
                      iCsr, SQLITE_INDEX_CONSTRAINT_LIMIT);
    if( p->iOffset>0 ){
      whereAddLimitExpr(pWC, p->iOffset, p->pLimit->pRight,
                        iCsr, SQLITE_INDEX_CONSTRAINT_OFFSET);
    }
  }
}

/*
** Initialize a preallocated WhereClause structure.
*/
void sqlite3WhereClauseInit(
  WhereClause *pWC,        /* The WhereClause to be initialized */
  WhereInfo *pWInfo        /* The WHERE processing context */
){
  pWC->pWInfo = pWInfo;
  pWC->hasOr = 0;
  pWC->pOuter = 0;
  pWC->nTerm = 0;
  pWC->nBase = 0;
  pWC->nSlot = ArraySize(pWC->aStatic);
  pWC->a = pWC->aStatic;
}

/*
** Deallocate a WhereClause structure.  The WhereClause structure
** itself is not freed.  This routine is the inverse of
** sqlite3WhereClauseInit().
*/
void sqlite3WhereClauseClear(WhereClause *pWC){
  int i;
  WhereTerm *a;
  sqlite3 *db = pWC->pWInfo->pParse->db;
  assert( pWC->nTerm>=pWC->nBase );
  for(i=pWC->nTerm-1, a=pWC->a; i>=0; i--, a++){
    if( a->wtFlags & TERM_DYNAMIC ){
      sqlite3ExprDelete(db, a->pExpr);
    }
    if( a->wtFlags & TERM_ORINFO ){
      whereOrInfoDelete(db, a->u.pOrInfo);
    }else if( a->wtFlags & TERM_ANDINFO ){
      whereAndInfoDelete(db, a->u.pAndInfo);
    }
  }
  if( pWC->a!=pWC->aStatic ){
  if( pWC->nTerm>0 ){
    WhereTerm *a = pWC->a;
    WhereTerm *aLast = &pWC->a[pWC->nTerm-1];
#ifdef SQLITE_DEBUG
    int i;
    /* Verify that every term past pWC->nBase is virtual */
    for(i=pWC->nBase; i<pWC->nTerm; i++){
      assert( (pWC->a[i].wtFlags & TERM_VIRTUAL)!=0 );
    }
#endif
    while(1){
      assert( a->eMatchOp==0 || a->eOperator==WO_AUX );
      if( a->wtFlags & TERM_DYNAMIC ){
        sqlite3ExprDelete(db, a->pExpr);
      }
      if( a->wtFlags & (TERM_ORINFO|TERM_ANDINFO) ){
        if( a->wtFlags & TERM_ORINFO ){
          assert( (a->wtFlags & TERM_ANDINFO)==0 );
          whereOrInfoDelete(db, a->u.pOrInfo);
        }else{
          assert( (a->wtFlags & TERM_ANDINFO)!=0 );
          whereAndInfoDelete(db, a->u.pAndInfo);
        }
      }
      if( a==aLast ) break;
    sqlite3DbFree(db, pWC->a);
      a++;
    }
  }
}


/*
** These routines walk (recursively) an expression tree and generate
** a bitmask indicating which tables are used in that expression
** tree.
**
** sqlite3WhereExprUsage(MaskSet, Expr) ->
**
**       Return a Bitmask of all tables referenced by Expr.  Expr can be
**       be NULL, in which case 0 is returned.
**
** sqlite3WhereExprUsageNN(MaskSet, Expr) ->
**
**       Same as sqlite3WhereExprUsage() except that Expr must not be
**       NULL.  The "NN" suffix on the name stands for "Not Null".
**
** sqlite3WhereExprListUsage(MaskSet, ExprList) ->
**
**       Return a Bitmask of all tables referenced by every expression
**       in the expression list ExprList.  ExprList can be NULL, in which
**       case 0 is returned.
**
** sqlite3WhereExprUsageFull(MaskSet, ExprList) ->
**
**       Internal use only.  Called only by sqlite3WhereExprUsageNN() for
**       complex expressions that require pushing register values onto
**       the stack.  Many calls to sqlite3WhereExprUsageNN() do not need
**       the more complex analysis done by this routine.  Hence, the
**       computations done by this routine are broken out into a separate
**       "no-inline" function to avoid the stack push overhead in the
**       common case where it is not needed.
*/
static SQLITE_NOINLINE Bitmask sqlite3WhereExprUsageFull(
Bitmask sqlite3WhereExprUsageNN(WhereMaskSet *pMaskSet, Expr *p){
  WhereMaskSet *pMaskSet,
  Expr *p
){
  Bitmask mask;
  mask = (p->op==TK_IF_NULL_ROW) ? sqlite3WhereGetMask(pMaskSet, p->iTable) : 0;
  if( p->pLeft ) mask |= sqlite3WhereExprUsageNN(pMaskSet, p->pLeft);
  if( p->pRight ){
    mask |= sqlite3WhereExprUsageNN(pMaskSet, p->pRight);
    assert( p->x.pList==0 );
  }else if( ExprUseXSelect(p) ){
    if( ExprHasProperty(p, EP_VarSelect) ) pMaskSet->bVarSelect = 1;
    mask |= exprSelectUsage(pMaskSet, p->x.pSelect);
  }else if( p->x.pList ){
    mask |= sqlite3WhereExprListUsage(pMaskSet, p->x.pList);
  }
#ifndef SQLITE_OMIT_WINDOWFUNC
  if( (p->op==TK_FUNCTION || p->op==TK_AGG_FUNCTION) && ExprUseYWin(p) ){
    assert( p->y.pWin!=0 );
    mask |= sqlite3WhereExprListUsage(pMaskSet, p->y.pWin->pPartition);
    mask |= sqlite3WhereExprListUsage(pMaskSet, p->y.pWin->pOrderBy);
    mask |= sqlite3WhereExprUsage(pMaskSet, p->y.pWin->pFilter);
  }
#endif
  return mask;
}
Bitmask sqlite3WhereExprUsageNN(WhereMaskSet *pMaskSet, Expr *p){
  if( p->op==TK_COLUMN && !ExprHasProperty(p, EP_FixedCol) ){
    return sqlite3WhereGetMask(pMaskSet, p->iTable);
  }else if( ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
    assert( p->op!=TK_IF_NULL_ROW );
    return 0;
  }
  mask = (p->op==TK_IF_NULL_ROW) ? sqlite3WhereGetMask(pMaskSet, p->iTable) : 0;
  if( p->pLeft ) mask |= sqlite3WhereExprUsageNN(pMaskSet, p->pLeft);
  if( p->pRight ){
    mask |= sqlite3WhereExprUsageNN(pMaskSet, p->pRight);
  return sqlite3WhereExprUsageFull(pMaskSet, p);
    assert( p->x.pList==0 );
  }else if( ExprHasProperty(p, EP_xIsSelect) ){
    if( ExprHasProperty(p, EP_VarSelect) ) pMaskSet->bVarSelect = 1;
    mask |= exprSelectUsage(pMaskSet, p->x.pSelect);
  }else if( p->x.pList ){
    mask |= sqlite3WhereExprListUsage(pMaskSet, p->x.pList);
  }
  return mask;
}
Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){
  return p ? sqlite3WhereExprUsageNN(pMaskSet,p) : 0;
}
Bitmask sqlite3WhereExprListUsage(WhereMaskSet *pMaskSet, ExprList *pList){
  int i;
  Bitmask mask = 0;
1560
1561
1562
1563
1564
1565
1566
1567

1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581

1582
1583
1584
1585
1586
1587
1588
1589
1590
1591

1592

1593
1594
1595






1596
1597
1598
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







-
+














+










+

+



+
+
+
+
+
+



** new WHERE clause terms.  
**
** Each function argument translates into an equality constraint against
** a HIDDEN column in the table.
*/
void sqlite3WhereTabFuncArgs(
  Parse *pParse,                    /* Parsing context */
  struct SrcList_item *pItem,       /* The FROM clause term to process */
  SrcItem *pItem,                   /* The FROM clause term to process */
  WhereClause *pWC                  /* Xfer function arguments to here */
){
  Table *pTab;
  int j, k;
  ExprList *pArgs;
  Expr *pColRef;
  Expr *pTerm;
  if( pItem->fg.isTabFunc==0 ) return;
  pTab = pItem->pTab;
  assert( pTab!=0 );
  pArgs = pItem->u1.pFuncArg;
  if( pArgs==0 ) return;
  for(j=k=0; j<pArgs->nExpr; j++){
    Expr *pRhs;
    u32 joinType;
    while( k<pTab->nCol && (pTab->aCol[k].colFlags & COLFLAG_HIDDEN)==0 ){k++;}
    if( k>=pTab->nCol ){
      sqlite3ErrorMsg(pParse, "too many arguments on %s() - max %d",
                      pTab->zName, j);
      return;
    }
    pColRef = sqlite3ExprAlloc(pParse->db, TK_COLUMN, 0, 0);
    if( pColRef==0 ) return;
    pColRef->iTable = pItem->iCursor;
    pColRef->iColumn = k++;
    assert( ExprUseYTab(pColRef) );
    pColRef->y.pTab = pTab;
    pItem->colUsed |= sqlite3ExprColUsed(pColRef);
    pRhs = sqlite3PExpr(pParse, TK_UPLUS, 
        sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0);
    pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, pRhs);
    if( pItem->fg.jointype & (JT_LEFT|JT_LTORJ) ){
      joinType = EP_OuterON;
    }else{
      joinType = EP_InnerON;
    }
    sqlite3SetJoinExpr(pTerm, pItem->iCursor, joinType);
    whereClauseInsert(pWC, pTerm, TERM_DYNAMIC);
  }
}

Changes to src/window.c.

194
195
196
197
198
199
200


























































































201
202
203
204
205
206
207
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







      p->nValue++;
      p->nStep = 0;
    }
    sqlite3_result_int64(pCtx, p->nValue);
  }
}

/*
** Implementation of built-in window function nth_value(). This
** implementation is used in "slow mode" only - when the EXCLUDE clause
** is not set to the default value "NO OTHERS".
*/
struct NthValueCtx {
  i64 nStep;
  sqlite3_value *pValue;
};
static void nth_valueStepFunc(
  sqlite3_context *pCtx, 
  int nArg,
  sqlite3_value **apArg
){
  struct NthValueCtx *p;
  p = (struct NthValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p));
  if( p ){
    i64 iVal;
    switch( sqlite3_value_numeric_type(apArg[1]) ){
      case SQLITE_INTEGER:
        iVal = sqlite3_value_int64(apArg[1]);
        break;
      case SQLITE_FLOAT: {
        double fVal = sqlite3_value_double(apArg[1]);
        if( ((i64)fVal)!=fVal ) goto error_out;
        iVal = (i64)fVal;
        break;
      }
      default:
        goto error_out;
    }
    if( iVal<=0 ) goto error_out;

    p->nStep++;
    if( iVal==p->nStep ){
      p->pValue = sqlite3_value_dup(apArg[0]);
      if( !p->pValue ){
        sqlite3_result_error_nomem(pCtx);
      }
    }
  }
  UNUSED_PARAMETER(nArg);
  UNUSED_PARAMETER(apArg);
  return;

 error_out:
  sqlite3_result_error(
      pCtx, "second argument to nth_value must be a positive integer", -1
  );
}
static void nth_valueFinalizeFunc(sqlite3_context *pCtx){
  struct NthValueCtx *p;
  p = (struct NthValueCtx*)sqlite3_aggregate_context(pCtx, 0);
  if( p && p->pValue ){
    sqlite3_result_value(pCtx, p->pValue);
    sqlite3_value_free(p->pValue);
    p->pValue = 0;
  }
}
#define nth_valueInvFunc noopStepFunc
#define nth_valueValueFunc noopValueFunc

static void first_valueStepFunc(
  sqlite3_context *pCtx, 
  int nArg,
  sqlite3_value **apArg
){
  struct NthValueCtx *p;
  p = (struct NthValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p));
  if( p && p->pValue==0 ){
    p->pValue = sqlite3_value_dup(apArg[0]);
    if( !p->pValue ){
      sqlite3_result_error_nomem(pCtx);
    }
  }
  UNUSED_PARAMETER(nArg);
  UNUSED_PARAMETER(apArg);
}
static void first_valueFinalizeFunc(sqlite3_context *pCtx){
  struct NthValueCtx *p;
  p = (struct NthValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p));
  if( p && p->pValue ){
    sqlite3_result_value(pCtx, p->pValue);
    sqlite3_value_free(p->pValue);
    p->pValue = 0;
  }
}
#define first_valueInvFunc noopStepFunc
#define first_valueValueFunc noopValueFunc

/*
** Implementation of built-in window function rank(). Assumes that
** the window frame has been set to:
**
**   RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW 
*/
static void rankStepFunc(
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
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







-
+







-
-
+
+


-
+
-
-
+
-
-
-
-
+
-
+
+
+
+
+
+
+
+
+
+





+

-
+




-


+





-
+







-
-
+
+


-
+
-
-
+
-
-
+
+
+
+
+
+
+
+
+
+
+



-
-
+
+




+














-
+







-
+




-






-
+

+
+
+
+
+
+
+
+
+
+
+







-
+



-
+











+







  }
}

/*
** Implementation of built-in window function percent_rank(). Assumes that
** the window frame has been set to:
**
**   RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW 
**   GROUPS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
*/
static void percent_rankStepFunc(
  sqlite3_context *pCtx, 
  int nArg,
  sqlite3_value **apArg
){
  struct CallCount *p;
  UNUSED_PARAMETER(nArg); assert( nArg==1 );

  UNUSED_PARAMETER(nArg); assert( nArg==0 );
  UNUSED_PARAMETER(apArg);
  p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p));
  if( p ){
    if( p->nTotal==0 ){
    p->nTotal++;
      p->nTotal = sqlite3_value_int64(apArg[0]);
    }
  }
    p->nStep++;
    if( p->nValue==0 ){
      p->nValue = p->nStep;
    }
}
  }
static void percent_rankInvFunc(
  sqlite3_context *pCtx, 
  int nArg,
  sqlite3_value **apArg
){
  struct CallCount *p;
  UNUSED_PARAMETER(nArg); assert( nArg==0 );
  UNUSED_PARAMETER(apArg);
  p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p));
  p->nStep++;
}
static void percent_rankValueFunc(sqlite3_context *pCtx){
  struct CallCount *p;
  p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p));
  if( p ){
    p->nValue = p->nStep;
    if( p->nTotal>1 ){
      double r = (double)(p->nValue-1) / (double)(p->nTotal-1);
      double r = (double)p->nValue / (double)(p->nTotal-1);
      sqlite3_result_double(pCtx, r);
    }else{
      sqlite3_result_double(pCtx, 0.0);
    }
    p->nValue = 0;
  }
}
#define percent_rankFinalizeFunc percent_rankValueFunc

/*
** Implementation of built-in window function cume_dist(). Assumes that
** the window frame has been set to:
**
**   RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW 
**   GROUPS BETWEEN 1 FOLLOWING AND UNBOUNDED FOLLOWING
*/
static void cume_distStepFunc(
  sqlite3_context *pCtx, 
  int nArg,
  sqlite3_value **apArg
){
  struct CallCount *p;
  assert( nArg==1 ); UNUSED_PARAMETER(nArg);

  UNUSED_PARAMETER(nArg); assert( nArg==0 );
  UNUSED_PARAMETER(apArg);
  p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p));
  if( p ){
    if( p->nTotal==0 ){
    p->nTotal++;
      p->nTotal = sqlite3_value_int64(apArg[0]);
    }
  }
    p->nStep++;
  }
}
static void cume_distInvFunc(
  sqlite3_context *pCtx, 
  int nArg,
  sqlite3_value **apArg
){
  struct CallCount *p;
  UNUSED_PARAMETER(nArg); assert( nArg==0 );
  UNUSED_PARAMETER(apArg);
  p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p));
  p->nStep++;
}
static void cume_distValueFunc(sqlite3_context *pCtx){
  struct CallCount *p;
  p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p));
  if( p && p->nTotal ){
  p = (struct CallCount*)sqlite3_aggregate_context(pCtx, 0);
  if( p ){
    double r = (double)(p->nStep) / (double)(p->nTotal);
    sqlite3_result_double(pCtx, r);
  }
}
#define cume_distFinalizeFunc cume_distValueFunc

/*
** Context object for ntile() window function.
*/
struct NtileCtx {
  i64 nTotal;                     /* Total rows in partition */
  i64 nParam;                     /* Parameter passed to ntile(N) */
  i64 iRow;                       /* Current row */
};

/*
** Implementation of ntile(). This assumes that the window frame has
** been coerced to:
**
**   ROWS UNBOUNDED PRECEDING AND CURRENT ROW
**   ROWS CURRENT ROW AND UNBOUNDED FOLLOWING
*/
static void ntileStepFunc(
  sqlite3_context *pCtx, 
  int nArg,
  sqlite3_value **apArg
){
  struct NtileCtx *p;
  assert( nArg==2 ); UNUSED_PARAMETER(nArg);
  assert( nArg==1 ); UNUSED_PARAMETER(nArg);
  p = (struct NtileCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p));
  if( p ){
    if( p->nTotal==0 ){
      p->nParam = sqlite3_value_int64(apArg[0]);
      p->nTotal = sqlite3_value_int64(apArg[1]);
      if( p->nParam<=0 ){
        sqlite3_result_error(
            pCtx, "argument of ntile must be a positive integer", -1
        );
      }
    }
    p->iRow++;
    p->nTotal++;
  }
}
static void ntileInvFunc(
  sqlite3_context *pCtx, 
  int nArg,
  sqlite3_value **apArg
){
  struct NtileCtx *p;
  assert( nArg==1 ); UNUSED_PARAMETER(nArg);
  UNUSED_PARAMETER(apArg);
  p = (struct NtileCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p));
  p->iRow++;
}
static void ntileValueFunc(sqlite3_context *pCtx){
  struct NtileCtx *p;
  p = (struct NtileCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p));
  if( p && p->nParam>0 ){
    int nSize = (p->nTotal / p->nParam);
    if( nSize==0 ){
      sqlite3_result_int64(pCtx, p->iRow);
      sqlite3_result_int64(pCtx, p->iRow+1);
    }else{
      i64 nLarge = p->nTotal - p->nParam*nSize;
      i64 iSmall = nLarge*(nSize+1);
      i64 iRow = p->iRow-1;
      i64 iRow = p->iRow;

      assert( (nLarge*(nSize+1) + (p->nParam-nLarge)*nSize)==p->nTotal );

      if( iRow<iSmall ){
        sqlite3_result_int64(pCtx, 1 + iRow/(nSize+1));
      }else{
        sqlite3_result_int64(pCtx, 1 + nLarge + (iRow-iSmall)/nSize);
      }
    }
  }
}
#define ntileFinalizeFunc ntileValueFunc

/*
** Context object for last_value() window function.
*/
struct LastValueCtx {
  sqlite3_value *pVal;
  int nVal;
402
403
404
405
406
407
408
409

410
411
412
413
414
415
416
518
519
520
521
522
523
524

525
526
527
528
529
530
531
532







-
+







      sqlite3_value_free(p->pVal);
      p->pVal = 0;
    }
  }
}
static void last_valueValueFunc(sqlite3_context *pCtx){
  struct LastValueCtx *p;
  p = (struct LastValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p));
  p = (struct LastValueCtx*)sqlite3_aggregate_context(pCtx, 0);
  if( p && p->pVal ){
    sqlite3_result_value(pCtx, p->pVal);
  }
}
static void last_valueFinalizeFunc(sqlite3_context *pCtx){
  struct LastValueCtx *p;
  p = (struct LastValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p));
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
577
578
579
580
581
582
583

584
585
586
587
588
589
590
591

592
593
594
595
596
597
598
599
600

601
602
603
604
605
606
607
608
609
610
611
612
613
614



615
616
617
618


619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647







-
+







-
+








-
+













-
-
-
+
+
+

-
-
+
+









+
+
+
+
+
+
+
+
+
+
+







  assert(0);                 /*NO_TEST*/
}                            /*NO_TEST*/
static void noopValueFunc(sqlite3_context *p){ UNUSED_PARAMETER(p); /*no-op*/ }

/* Window functions that use all window interfaces: xStep, xFinal,
** xValue, and xInverse */
#define WINDOWFUNCALL(name,nArg,extra) {                                   \
  nArg, (SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0,                      \
  nArg, (SQLITE_FUNC_BUILTIN|SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0,  \
  name ## StepFunc, name ## FinalizeFunc, name ## ValueFunc,               \
  name ## InvFunc, name ## Name, {0}                                       \
}

/* Window functions that are implemented using bytecode and thus have
** no-op routines for their methods */
#define WINDOWFUNCNOOP(name,nArg,extra) {                                  \
  nArg, (SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0,                      \
  nArg, (SQLITE_FUNC_BUILTIN|SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0,  \
  noopStepFunc, noopValueFunc, noopValueFunc,                              \
  noopStepFunc, name ## Name, {0}                                          \
}

/* Window functions that use all window interfaces: xStep, the
** same routine for xFinalize and xValue and which never call
** xInverse. */
#define WINDOWFUNCX(name,nArg,extra) {                                     \
  nArg, (SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0,                      \
  nArg, (SQLITE_FUNC_BUILTIN|SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0,  \
  name ## StepFunc, name ## ValueFunc, name ## ValueFunc,                  \
  noopStepFunc, name ## Name, {0}                                          \
}


/*
** Register those built-in window functions that are not also aggregates.
*/
void sqlite3WindowFunctions(void){
  static FuncDef aWindowFuncs[] = {
    WINDOWFUNCX(row_number, 0, 0),
    WINDOWFUNCX(dense_rank, 0, 0),
    WINDOWFUNCX(rank, 0, 0),
    WINDOWFUNCX(percent_rank, 0, SQLITE_FUNC_WINDOW_SIZE),
    WINDOWFUNCX(cume_dist, 0, SQLITE_FUNC_WINDOW_SIZE),
    WINDOWFUNCX(ntile, 1, SQLITE_FUNC_WINDOW_SIZE),
    WINDOWFUNCALL(percent_rank, 0, 0),
    WINDOWFUNCALL(cume_dist, 0, 0),
    WINDOWFUNCALL(ntile, 1, 0),
    WINDOWFUNCALL(last_value, 1, 0),
    WINDOWFUNCNOOP(nth_value, 2, 0),
    WINDOWFUNCNOOP(first_value, 1, 0),
    WINDOWFUNCALL(nth_value, 2, 0),
    WINDOWFUNCALL(first_value, 1, 0),
    WINDOWFUNCNOOP(lead, 1, 0),
    WINDOWFUNCNOOP(lead, 2, 0),
    WINDOWFUNCNOOP(lead, 3, 0),
    WINDOWFUNCNOOP(lag, 1, 0),
    WINDOWFUNCNOOP(lag, 2, 0),
    WINDOWFUNCNOOP(lag, 3, 0),
  };
  sqlite3InsertBuiltinFuncs(aWindowFuncs, ArraySize(aWindowFuncs));
}

static Window *windowFind(Parse *pParse, Window *pList, const char *zName){
  Window *p;
  for(p=pList; p; p=p->pNextWin){
    if( sqlite3StrICmp(p->zName, zName)==0 ) break;
  }
  if( p==0 ){
    sqlite3ErrorMsg(pParse, "no such window: %s", zName);
  }
  return p;
}

/*
** This function is called immediately after resolving the function name
** for a window function within a SELECT statement. Argument pList is a
** linked list of WINDOW definitions for the current SELECT statement.
** Argument pFunc is the function definition just resolved and pWin
** is the Window object representing the associated OVER clause. This
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
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
755
756
757
758
759







-
-
+
+
-
-
-
-
+
-
-
-






-
+
+
+
+

+
+
+
+
+
+
+
+






-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+











+











+
+







*/
void sqlite3WindowUpdate(
  Parse *pParse, 
  Window *pList,                  /* List of named windows for this SELECT */
  Window *pWin,                   /* Window frame to update */
  FuncDef *pFunc                  /* Window function definition */
){
  if( pWin->zName && pWin->eType==0 ){
    Window *p;
  if( pWin->zName && pWin->eFrmType==0 ){
    Window *p = windowFind(pParse, pList, pWin->zName);
    for(p=pList; p; p=p->pNextWin){
      if( sqlite3StrICmp(p->zName, pWin->zName)==0 ) break;
    }
    if( p==0 ){
    if( p==0 ) return;
      sqlite3ErrorMsg(pParse, "no such window: %s", pWin->zName);
      return;
    }
    pWin->pPartition = sqlite3ExprListDup(pParse->db, p->pPartition, 0);
    pWin->pOrderBy = sqlite3ExprListDup(pParse->db, p->pOrderBy, 0);
    pWin->pStart = sqlite3ExprDup(pParse->db, p->pStart, 0);
    pWin->pEnd = sqlite3ExprDup(pParse->db, p->pEnd, 0);
    pWin->eStart = p->eStart;
    pWin->eEnd = p->eEnd;
    pWin->eType = p->eType;
    pWin->eFrmType = p->eFrmType;
    pWin->eExclude = p->eExclude;
  }else{
    sqlite3WindowChain(pParse, pWin, pList);
  }
  if( (pWin->eFrmType==TK_RANGE)
   && (pWin->pStart || pWin->pEnd) 
   && (pWin->pOrderBy==0 || pWin->pOrderBy->nExpr!=1)
  ){
    sqlite3ErrorMsg(pParse, 
      "RANGE with offset PRECEDING/FOLLOWING requires one ORDER BY expression"
    );
  }else
  if( pFunc->funcFlags & SQLITE_FUNC_WINDOW ){
    sqlite3 *db = pParse->db;
    if( pWin->pFilter ){
      sqlite3ErrorMsg(pParse, 
          "FILTER clause may only be used with aggregate window functions"
      );
    }else
    if( pFunc->zName==row_numberName || pFunc->zName==ntileName ){
      sqlite3ExprDelete(db, pWin->pStart);
      sqlite3ExprDelete(db, pWin->pEnd);
      pWin->pStart = pWin->pEnd = 0;
      pWin->eType = TK_ROWS;
      pWin->eStart = TK_UNBOUNDED;
      pWin->eEnd = TK_CURRENT;
    }else

    if( pFunc->zName==dense_rankName || pFunc->zName==rankName
    }else{
      struct WindowUpdate {
        const char *zFunc;
        int eFrmType;
        int eStart;
        int eEnd;
      } aUp[] = {
        { row_numberName,   TK_ROWS,   TK_UNBOUNDED, TK_CURRENT }, 
        { dense_rankName,   TK_RANGE,  TK_UNBOUNDED, TK_CURRENT }, 
        { rankName,         TK_RANGE,  TK_UNBOUNDED, TK_CURRENT }, 
        { percent_rankName, TK_GROUPS, TK_CURRENT,   TK_UNBOUNDED }, 
        { cume_distName,    TK_GROUPS, TK_FOLLOWING, TK_UNBOUNDED }, 
        { ntileName,        TK_ROWS,   TK_CURRENT,   TK_UNBOUNDED }, 
        { leadName,         TK_ROWS,   TK_UNBOUNDED, TK_UNBOUNDED }, 
        { lagName,          TK_ROWS,   TK_UNBOUNDED, TK_CURRENT }, 
      };
      int i;
      for(i=0; i<ArraySize(aUp); i++){
        if( pFunc->zName==aUp[i].zFunc ){
     || pFunc->zName==percent_rankName || pFunc->zName==cume_distName
    ){
      sqlite3ExprDelete(db, pWin->pStart);
      sqlite3ExprDelete(db, pWin->pEnd);
      pWin->pStart = pWin->pEnd = 0;
      pWin->eType = TK_RANGE;
      pWin->eStart = TK_UNBOUNDED;
      pWin->eEnd = TK_CURRENT;
    }
  }
  pWin->pFunc = pFunc;
          sqlite3ExprDelete(db, pWin->pStart);
          sqlite3ExprDelete(db, pWin->pEnd);
          pWin->pEnd = pWin->pStart = 0;
          pWin->eFrmType = aUp[i].eFrmType;
          pWin->eStart = aUp[i].eStart;
          pWin->eEnd = aUp[i].eEnd;
          pWin->eExclude = 0;
          if( pWin->eStart==TK_FOLLOWING ){
            pWin->pStart = sqlite3Expr(db, TK_INTEGER, "1");
          }
          break;
        }
      }
    }
  }
  pWin->pWFunc = pFunc;
}

/*
** Context object passed through sqlite3WalkExprList() to
** selectWindowRewriteExprCb() by selectWindowRewriteEList().
*/
typedef struct WindowRewrite WindowRewrite;
struct WindowRewrite {
  Window *pWin;
  SrcList *pSrc;
  ExprList *pSub;
  Table *pTab;
  Select *pSubSelect;             /* Current sub-select, if any */
};

/*
** Callback function used by selectWindowRewriteEList(). If necessary,
** this function appends to the output expression-list and updates 
** expression (*ppExpr) in place.
*/
static int selectWindowRewriteExprCb(Walker *pWalker, Expr *pExpr){
  struct WindowRewrite *p = pWalker->u.pRewrite;
  Parse *pParse = pWalker->pParse;
  assert( p!=0 );
  assert( p->pWin!=0 );

  /* If this function is being called from within a scalar sub-select
  ** that used by the SELECT statement being processed, only process
  ** TK_COLUMN expressions that refer to it (the outer SELECT). Do
  ** not process aggregates or window functions at all, as they belong
  ** to the scalar sub-select.  */
  if( p->pSubSelect ){
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
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







-
+



+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+

+







-
+

+
+

-
+







        for(pWin=p->pWin; pWin; pWin=pWin->pNextWin){
          if( pExpr->y.pWin==pWin ){
            assert( pWin->pOwner==pExpr );
            return WRC_Prune;
          }
        }
      }
      /* Fall through.  */
      /* 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;
          }
        }
      }
      if( iCol<0 ){
      Expr *pDup = sqlite3ExprDup(pParse->db, pExpr, 0);
      p->pSub = sqlite3ExprListAppend(pParse, p->pSub, pDup);
        Expr *pDup = sqlite3ExprDup(pParse->db, pExpr, 0);
        if( pDup && pDup->op==TK_AGG_FUNCTION ) pDup->op = TK_FUNCTION;
        p->pSub = sqlite3ExprListAppend(pParse, p->pSub, pDup);
      }
      if( p->pSub ){
        int f = pExpr->flags & EP_Collate;
        assert( ExprHasProperty(pExpr, EP_Static)==0 );
        ExprSetProperty(pExpr, EP_Static);
        sqlite3ExprDelete(pParse->db, pExpr);
        ExprClearProperty(pExpr, EP_Static);
        memset(pExpr, 0, sizeof(Expr));

        pExpr->op = TK_COLUMN;
        pExpr->iColumn = p->pSub->nExpr-1;
        pExpr->iColumn = (iCol<0 ? p->pSub->nExpr-1: iCol);
        pExpr->iTable = p->pWin->iEphCsr;
        pExpr->y.pTab = p->pTab;
        pExpr->flags = f;
      }

      if( pParse->db->mallocFailed ) return WRC_Abort;
      break;
    }

    default: /* no-op */
      break;
  }

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
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
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
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958

959
960
961
962
963
964
965
966
967
968
969
970
971
972
973

974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002



1003
1004
1005
1006
1007
1008
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







+





+






+


















-
+
+





+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










-
+
+
+
+
+










-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





+
+




-
-
-
+
+
+
+
+




+






+

-
-
+
+





-
-
+
+






+
+
+
+
+
+
-
-
+
+
+
+
+
+

















-
+






+
+
+
-
-
+
+
+
+

+

+

+
-
+
+
+
+
+
+


+
-
-
-
+
+
+
+
+
+
+
+

-
-




-
-
+
+
+
+
+
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+






+






+







** appending the new one.
*/
static void selectWindowRewriteEList(
  Parse *pParse, 
  Window *pWin,
  SrcList *pSrc,
  ExprList *pEList,               /* Rewrite expressions in this list */
  Table *pTab,
  ExprList **ppSub                /* IN/OUT: Sub-select expression-list */
){
  Walker sWalker;
  WindowRewrite sRewrite;

  assert( pWin!=0 );
  memset(&sWalker, 0, sizeof(Walker));
  memset(&sRewrite, 0, sizeof(WindowRewrite));

  sRewrite.pSub = *ppSub;
  sRewrite.pWin = pWin;
  sRewrite.pSrc = pSrc;
  sRewrite.pTab = pTab;

  sWalker.pParse = pParse;
  sWalker.xExprCallback = selectWindowRewriteExprCb;
  sWalker.xSelectCallback = selectWindowRewriteSelectCb;
  sWalker.u.pRewrite = &sRewrite;

  (void)sqlite3WalkExprList(&sWalker, pEList);

  *ppSub = sRewrite.pSub;
}

/*
** Append a copy of each expression in expression-list pAppend to
** expression list pList. Return a pointer to the result list.
*/
static ExprList *exprListAppendList(
  Parse *pParse,          /* Parsing context */
  ExprList *pList,        /* List to which to append. Might be NULL */
  ExprList *pAppend       /* List of values to append. Might be NULL */
  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);
      if( db->mallocFailed ){
        sqlite3ExprDelete(db, pDup);
        break;
      }
      if( bIntToNull ){
        int iDummy;
        Expr *pSub;
        pSub = sqlite3ExprSkipCollateAndLikely(pDup);
        if( sqlite3ExprIsInteger(pSub, &iDummy) ){
          pSub->op = TK_NULL;
          pSub->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse);
          pSub->u.zToken = 0;
        }
      }
      pList = sqlite3ExprListAppend(pParse, pList, pDup);
      if( pList ) pList->a[nInit+i].sortOrder = pAppend->a[i].sortOrder;
      if( pList ) pList->a[nInit+i].fg.sortFlags = pAppend->a[i].fg.sortFlags;
    }
  }
  return pList;
}

/*
** When rewriting a query, if the new subquery in the FROM clause
** contains TK_AGG_FUNCTION nodes that refer to an outer query,
** then we have to increase the Expr->op2 values of those nodes
** due to the extra subquery layer that was added.
**
** See also the incrAggDepth() routine in resolve.c
*/
static int sqlite3WindowExtraAggFuncDepth(Walker *pWalker, Expr *pExpr){
  if( pExpr->op==TK_AGG_FUNCTION
   && pExpr->op2>=pWalker->walkerDepth
  ){
    pExpr->op2++;
  }
  return WRC_Continue;
}

static int disallowAggregatesInOrderByCb(Walker *pWalker, Expr *pExpr){
  if( pExpr->op==TK_AGG_FUNCTION && pExpr->pAggInfo==0 ){
    assert( !ExprHasProperty(pExpr, EP_IntValue) );
     sqlite3ErrorMsg(pWalker->pParse,
         "misuse of aggregate: %s()", pExpr->u.zToken);
  }
  return WRC_Continue;
}

/*
** If the SELECT statement passed as the second argument does not invoke
** any SQL window functions, this function is a no-op. Otherwise, it 
** rewrites the SELECT statement so that window function xStep functions
** are invoked in the correct order as described under "SELECT REWRITING"
** at the top of this file.
*/
int sqlite3WindowRewrite(Parse *pParse, Select *p){
  int rc = SQLITE_OK;
  if( p->pWin && p->pPrior==0 ){
  if( p->pWin
   && p->pPrior==0
   && ALWAYS((p->selFlags & SF_WinRewrite)==0)
   && ALWAYS(!IN_RENAME_OBJECT)
  ){
    Vdbe *v = sqlite3GetVdbe(pParse);
    sqlite3 *db = pParse->db;
    Select *pSub = 0;             /* The subquery */
    SrcList *pSrc = p->pSrc;
    Expr *pWhere = p->pWhere;
    ExprList *pGroupBy = p->pGroupBy;
    Expr *pHaving = p->pHaving;
    ExprList *pSort = 0;

    ExprList *pSublist = 0;       /* Expression list for sub-query */
    Window *pMWin = p->pWin;      /* Master window object */
    Window *pMWin = p->pWin;      /* Main window object */
    Window *pWin;                 /* Window object iterator */
    Table *pTab;
    Walker w;

    u32 selFlags = p->selFlags;

    pTab = sqlite3DbMallocZero(db, sizeof(Table));
    if( pTab==0 ){
      return sqlite3ErrorToParser(db, SQLITE_NOMEM);
    }
    sqlite3AggInfoPersistWalkerInit(&w, pParse);
    sqlite3WalkSelect(&w, p);
    if( (p->selFlags & SF_Aggregate)==0 ){
      w.xExprCallback = disallowAggregatesInOrderByCb;
      w.xSelectCallback = 0;
      sqlite3WalkExprList(&w, p->pOrderBy);
    }

    p->pSrc = 0;
    p->pWhere = 0;
    p->pGroupBy = 0;
    p->pHaving = 0;
    p->selFlags &= ~SF_Aggregate;
    p->selFlags |= SF_WinRewrite;

    /* Create the ORDER BY clause for the sub-select. This is the concatenation
    ** of the window PARTITION and ORDER BY clauses. Then, if this makes it
    ** redundant, remove the ORDER BY from the parent SELECT.  */
    pSort = sqlite3ExprListDup(db, pMWin->pPartition, 0);
    pSort = exprListAppendList(pParse, pSort, pMWin->pOrderBy);
    if( pSort && p->pOrderBy ){
    pSort = exprListAppendList(pParse, 0, pMWin->pPartition, 1);
    pSort = exprListAppendList(pParse, pSort, pMWin->pOrderBy, 1);
    if( pSort && p->pOrderBy && p->pOrderBy->nExpr<=pSort->nExpr ){
      int nSave = pSort->nExpr;
      pSort->nExpr = p->pOrderBy->nExpr;
      if( sqlite3ExprListCompare(pSort, p->pOrderBy, -1)==0 ){
        sqlite3ExprListDelete(db, p->pOrderBy);
        p->pOrderBy = 0;
      }
      pSort->nExpr = nSave;
    }

    /* Assign a cursor number for the ephemeral table used to buffer rows.
    ** The OpenEphemeral instruction is coded later, after it is known how
    ** many columns the table will have.  */
    pMWin->iEphCsr = pParse->nTab++;
    pParse->nTab += 3;

    selectWindowRewriteEList(pParse, pMWin, pSrc, p->pEList, &pSublist);
    selectWindowRewriteEList(pParse, pMWin, pSrc, p->pOrderBy, &pSublist);
    selectWindowRewriteEList(pParse, pMWin, pSrc, p->pEList, pTab, &pSublist);
    selectWindowRewriteEList(pParse, pMWin, pSrc, p->pOrderBy, pTab, &pSublist);
    pMWin->nBufferCol = (pSublist ? pSublist->nExpr : 0);

    /* Append the PARTITION BY and ORDER BY expressions to the to the 
    ** sub-select expression list. They are required to figure out where 
    ** boundaries for partitions and sets of peer rows lie.  */
    pSublist = exprListAppendList(pParse, pSublist, pMWin->pPartition);
    pSublist = exprListAppendList(pParse, pSublist, pMWin->pOrderBy);
    pSublist = exprListAppendList(pParse, pSublist, pMWin->pPartition, 0);
    pSublist = exprListAppendList(pParse, pSublist, pMWin->pOrderBy, 0);

    /* Append the arguments passed to each window function to the
    ** sub-select expression list. Also allocate two registers for each
    ** window function - one for the accumulator, another for interim
    ** results.  */
    for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
      ExprList *pArgs;
      assert( ExprUseXList(pWin->pOwner) );
      assert( pWin->pWFunc!=0 );
      pArgs = pWin->pOwner->x.pList;
      if( pWin->pWFunc->funcFlags & SQLITE_FUNC_SUBTYPE ){
        selectWindowRewriteEList(pParse, pMWin, pSrc, pArgs, pTab, &pSublist);
      pWin->iArgCol = (pSublist ? pSublist->nExpr : 0);
      pSublist = exprListAppendList(pParse, pSublist, pWin->pOwner->x.pList);
        pWin->iArgCol = (pSublist ? pSublist->nExpr : 0);
        pWin->bExprArgs = 1;
      }else{
        pWin->iArgCol = (pSublist ? pSublist->nExpr : 0);
        pSublist = exprListAppendList(pParse, pSublist, pArgs, 0);
      }
      if( pWin->pFilter ){
        Expr *pFilter = sqlite3ExprDup(db, pWin->pFilter, 0);
        pSublist = sqlite3ExprListAppend(pParse, pSublist, pFilter);
      }
      pWin->regAccum = ++pParse->nMem;
      pWin->regResult = ++pParse->nMem;
      sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum);
    }

    /* If there is no ORDER BY or PARTITION BY clause, and the window
    ** function accepts zero arguments, and there are no other columns
    ** selected (e.g. "SELECT row_number() OVER () FROM t1"), it is possible
    ** that pSublist is still NULL here. Add a constant expression here to 
    ** keep everything legal in this case. 
    */
    if( pSublist==0 ){
      pSublist = sqlite3ExprListAppend(pParse, 0, 
          sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[0], 0)
        sqlite3Expr(db, TK_INTEGER, "0")
      );
    }

    pSub = sqlite3SelectNew(
        pParse, pSublist, pSrc, pWhere, pGroupBy, pHaving, pSort, 0, 0
    );
    TREETRACE(0x40,pParse,pSub,
       ("New window-function subquery in FROM clause of (%u/%p)\n",
       p->selId, p));
    p->pSrc = sqlite3SrcListAppend(db, 0, 0, 0);
    assert( p->pSrc || db->mallocFailed );
    p->pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
    assert( pSub!=0 || p->pSrc==0 ); /* Due to db->mallocFailed test inside
                                     ** of sqlite3DbMallocRawNN() called from
                                     ** sqlite3SrcListAppend() */
    if( p->pSrc ){
      Table *pTab2;
      p->pSrc->a[0].pSelect = pSub;
      p->pSrc->a[0].fg.isCorrelated = 1;
      sqlite3SrcListAssignCursors(pParse, p->pSrc);
      pSub->selFlags |= SF_Expanded|SF_OrderByReqd;
      if( sqlite3ExpandSubquery(pParse, &p->pSrc->a[0]) ){
      pTab2 = sqlite3ResultSetOfSelect(pParse, pSub, SQLITE_AFF_NONE);
      pSub->selFlags |= (selFlags & SF_Aggregate);
      if( pTab2==0 ){
        /* Might actually be some other kind of error, but in that case
        ** pParse->nErr will be set, so if SQLITE_NOMEM is set, we will get
        ** the correct error message regardless. */
        rc = SQLITE_NOMEM;
      }else{
        memcpy(pTab, pTab2, sizeof(Table));
        pSub->selFlags |= SF_Expanded;
        p->selFlags &= ~SF_Aggregate;
        sqlite3SelectPrep(pParse, pSub, 0);
        pTab->tabFlags |= TF_Ephemeral;
        p->pSrc->a[0].pTab = pTab;
        pTab = pTab2;
        memset(&w, 0, sizeof(w));
        w.xExprCallback = sqlite3WindowExtraAggFuncDepth;
        w.xSelectCallback = sqlite3WalkerDepthIncrease;
        w.xSelectCallback2 = sqlite3WalkerDepthDecrease;
        sqlite3WalkSelect(&w, pSub);
      }

      sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pMWin->iEphCsr, pSublist->nExpr);
    }else{
      sqlite3SelectDelete(db, pSub);
    }
    if( db->mallocFailed ) rc = SQLITE_NOMEM;
  }


    /* Defer deleting the temporary table pTab because if an error occurred,
    ** there could still be references to that table embedded in the
    ** result-set or ORDER BY clause of the SELECT statement p.  */
    sqlite3ParserAddCleanup(pParse, sqlite3DbFree, pTab);
  }

  assert( rc==SQLITE_OK || pParse->nErr!=0 );
  return rc;
}

/*
** Unlink the Window object from the Select to which it is attached,
** if it is attached.
*/
void sqlite3WindowUnlinkFromSelect(Window *p){
  if( p->ppThis ){
    *p->ppThis = p->pNextWin;
    if( p->pNextWin ) p->pNextWin->ppThis = p->ppThis;
    p->ppThis = 0;
  }
}

/*
** Free the Window object passed as the second argument.
*/
void sqlite3WindowDelete(sqlite3 *db, Window *p){
  if( p ){
    sqlite3WindowUnlinkFromSelect(p);
    sqlite3ExprDelete(db, p->pFilter);
    sqlite3ExprListDelete(db, p->pPartition);
    sqlite3ExprListDelete(db, p->pOrderBy);
    sqlite3ExprDelete(db, p->pEnd);
    sqlite3ExprDelete(db, p->pStart);
    sqlite3DbFree(db, p->zName);
    sqlite3DbFree(db, p->zBase);
    sqlite3DbFree(db, p);
  }
}

/*
** Free the linked list of Window objects starting at the second argument.
*/
877
878
879
880
881
882
883

884
885
886
887
888
889
890
891
892
893
894
895

896
897
898
899


900
901

902
903
904

905
906
907
908
909
910
911
912
913


914
915
916

917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938

939
940
941
942
943
944

945
946





947
948
949
950
951
952
953
954
955































































956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972







973

974
975
976
977
978
979
980























981
982



983
984
985









986
987

988
989
990
991











992
993
994
995
996
997
998
999
1000
1001



1002
1003
1004
1005
1006










1007
1008
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
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
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
1318
1319

1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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
1430
1431
1432
1433
1434


1435
1436
1437
1438
1439



1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450

1451
1452
1453
1454
1455
1456

1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475

1476
1477
1478
1479

1480
1481
1482
1483

1484
1485
1486

1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498




1499
1500
1501
1502
1503
1504
1505
1506
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
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
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638







+











-
+



-
+
+


+


-
+







-
-
+
+
-
-
-
+
-
-



















-
+





-
+


+
+
+
+
+









+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+

-
-
+
+
+
+
+
+
+
+
+


+


-
-
+
+
+
+
+
+
+
+
+
+
+









-
+
+
+


-
-
-
+
+
+
+
+
+
+
+
+
+

-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+








+
+
+
-
-
+
+



-
-
-
+
+
+








-






-





+
+
+
+
+
+








-
+



-
+
+
+

-
+


-
+

+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+

+
-
-
+
+

+
+
+










+
+
-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







** value should be a non-negative integer.  If the value is not a
** constant, change it to NULL.  The fact that it is then a non-negative
** integer will be caught later.  But it is important not to leave
** variable values in the expression tree.
*/
static Expr *sqlite3WindowOffsetExpr(Parse *pParse, Expr *pExpr){
  if( 0==sqlite3ExprIsConstant(pExpr) ){
    if( IN_RENAME_OBJECT ) sqlite3RenameExprUnmap(pParse, pExpr);
    sqlite3ExprDelete(pParse->db, pExpr);
    pExpr = sqlite3ExprAlloc(pParse->db, TK_NULL, 0, 0);
  }
  return pExpr;
}

/*
** Allocate and return a new Window object describing a Window Definition.
*/
Window *sqlite3WindowAlloc(
  Parse *pParse,    /* Parsing context */
  int eType,        /* Frame type. TK_RANGE or TK_ROWS */
  int eType,        /* Frame type. TK_RANGE, TK_ROWS, TK_GROUPS, or 0 */
  int eStart,       /* Start type: CURRENT, PRECEDING, FOLLOWING, UNBOUNDED */
  Expr *pStart,     /* Start window size if TK_PRECEDING or FOLLOWING */
  int eEnd,         /* End type: CURRENT, FOLLOWING, TK_UNBOUNDED, PRECEDING */
  Expr *pEnd        /* End window size if TK_FOLLOWING or PRECEDING */
  Expr *pEnd,       /* End window size if TK_FOLLOWING or PRECEDING */
  u8 eExclude       /* EXCLUDE clause */
){
  Window *pWin = 0;
  int bImplicitFrame = 0;

  /* Parser assures the following: */
  assert( eType==TK_RANGE || eType==TK_ROWS );
  assert( eType==0 || eType==TK_RANGE || eType==TK_ROWS || eType==TK_GROUPS );
  assert( eStart==TK_CURRENT || eStart==TK_PRECEDING
           || eStart==TK_UNBOUNDED || eStart==TK_FOLLOWING );
  assert( eEnd==TK_CURRENT || eEnd==TK_FOLLOWING
           || eEnd==TK_UNBOUNDED || eEnd==TK_PRECEDING );
  assert( (eStart==TK_PRECEDING || eStart==TK_FOLLOWING)==(pStart!=0) );
  assert( (eEnd==TK_FOLLOWING || eEnd==TK_PRECEDING)==(pEnd!=0) );


  /* If a frame is declared "RANGE" (not "ROWS"), then it may not use
  if( eType==0 ){
    bImplicitFrame = 1;
  ** either "<expr> PRECEDING" or "<expr> FOLLOWING".
  */
  if( eType==TK_RANGE && (pStart!=0 || pEnd!=0) ){
    eType = TK_RANGE;
    sqlite3ErrorMsg(pParse, "RANGE must use only UNBOUNDED or CURRENT ROW");
    goto windowAllocErr;
  }

  /* Additionally, the
  ** starting boundary type may not occur earlier in the following list than
  ** the ending boundary type:
  **
  **   UNBOUNDED PRECEDING
  **   <expr> PRECEDING
  **   CURRENT ROW
  **   <expr> FOLLOWING
  **   UNBOUNDED FOLLOWING
  **
  ** The parser ensures that "UNBOUNDED PRECEDING" cannot be used as an ending
  ** boundary, and than "UNBOUNDED FOLLOWING" cannot be used as a starting
  ** frame boundary.
  */
  if( (eStart==TK_CURRENT && eEnd==TK_PRECEDING)
   || (eStart==TK_FOLLOWING && (eEnd==TK_PRECEDING || eEnd==TK_CURRENT))
  ){
    sqlite3ErrorMsg(pParse, "unsupported frame delimiter for ROWS");
    sqlite3ErrorMsg(pParse, "unsupported frame specification");
    goto windowAllocErr;
  }

  pWin = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window));
  if( pWin==0 ) goto windowAllocErr;
  pWin->eType = eType;
  pWin->eFrmType = eType;
  pWin->eStart = eStart;
  pWin->eEnd = eEnd;
  if( eExclude==0 && OptimizationDisabled(pParse->db, SQLITE_WindowFunc) ){
    eExclude = TK_NO;
  }
  pWin->eExclude = eExclude;
  pWin->bImplicitFrame = bImplicitFrame;
  pWin->pEnd = sqlite3WindowOffsetExpr(pParse, pEnd);
  pWin->pStart = sqlite3WindowOffsetExpr(pParse, pStart);
  return pWin;

windowAllocErr:
  sqlite3ExprDelete(pParse->db, pEnd);
  sqlite3ExprDelete(pParse->db, pStart);
  return 0;
}

/*
** Attach PARTITION and ORDER BY clauses pPartition and pOrderBy to window
** pWin. Also, if parameter pBase is not NULL, set pWin->zBase to the
** equivalent nul-terminated string.
*/
Window *sqlite3WindowAssemble(
  Parse *pParse, 
  Window *pWin, 
  ExprList *pPartition, 
  ExprList *pOrderBy, 
  Token *pBase
){
  if( pWin ){
    pWin->pPartition = pPartition;
    pWin->pOrderBy = pOrderBy;
    if( pBase ){
      pWin->zBase = sqlite3DbStrNDup(pParse->db, pBase->z, pBase->n);
    }
  }else{
    sqlite3ExprListDelete(pParse->db, pPartition);
    sqlite3ExprListDelete(pParse->db, pOrderBy);
  }
  return pWin;
}

/*
** Window *pWin has just been created from a WINDOW clause. Tokne pBase
** is the base window. Earlier windows from the same WINDOW clause are
** stored in the linked list starting at pWin->pNextWin. This function
** either updates *pWin according to the base specification, or else
** leaves an error in pParse.
*/
void sqlite3WindowChain(Parse *pParse, Window *pWin, Window *pList){
  if( pWin->zBase ){
    sqlite3 *db = pParse->db;
    Window *pExist = windowFind(pParse, pList, pWin->zBase);
    if( pExist ){
      const char *zErr = 0;
      /* Check for errors */
      if( pWin->pPartition ){
        zErr = "PARTITION clause";
      }else if( pExist->pOrderBy && pWin->pOrderBy ){
        zErr = "ORDER BY clause";
      }else if( pExist->bImplicitFrame==0 ){
        zErr = "frame specification";
      }
      if( zErr ){
        sqlite3ErrorMsg(pParse, 
            "cannot override %s of window: %s", zErr, pWin->zBase
        );
      }else{
        pWin->pPartition = sqlite3ExprListDup(db, pExist->pPartition, 0);
        if( pExist->pOrderBy ){
          assert( pWin->pOrderBy==0 );
          pWin->pOrderBy = sqlite3ExprListDup(db, pExist->pOrderBy, 0);
        }
        sqlite3DbFree(db, pWin->zBase);
        pWin->zBase = 0;
      }
    }
  }
}

/*
** Attach window object pWin to expression p.
*/
void sqlite3WindowAttach(Parse *pParse, Expr *p, Window *pWin){
  if( p ){
    assert( p->op==TK_FUNCTION );
    /* This routine is only called for the parser.  If pWin was not
    ** allocated due to an OOM, then the parser would fail before ever
    ** invoking this routine */
    if( ALWAYS(pWin) ){
      p->y.pWin = pWin;
      ExprSetProperty(p, EP_WinFunc);
      pWin->pOwner = p;
      if( p->flags & EP_Distinct ){
        sqlite3ErrorMsg(pParse,
           "DISTINCT is not supported for window functions");
    assert( pWin );
    p->y.pWin = pWin;
    ExprSetProperty(p, EP_WinFunc);
    pWin->pOwner = p;
    if( (p->flags & EP_Distinct) && pWin->eFrmType!=TK_FILTER ){
      sqlite3ErrorMsg(pParse,
          "DISTINCT is not supported for window functions"
      }
      );
    }
  }else{
    sqlite3WindowDelete(pParse->db, pWin);
  }
}

/*
** Possibly link window pWin into the list at pSel->pWin (window functions
** to be processed as part of SELECT statement pSel). The window is linked
** in if either (a) there are no other windows already linked to this
** SELECT, or (b) the windows already linked use a compatible window frame.
*/
void sqlite3WindowLink(Select *pSel, Window *pWin){
  if( pSel ){
    if( 0==pSel->pWin || 0==sqlite3WindowCompare(0, pSel->pWin, pWin, 0) ){
      pWin->pNextWin = pSel->pWin;
      if( pSel->pWin ){
        pSel->pWin->ppThis = &pWin->pNextWin;
      }
      pSel->pWin = pWin;
      pWin->ppThis = &pSel->pWin;
    }else{
      if( sqlite3ExprListCompare(pWin->pPartition, pSel->pWin->pPartition,-1) ){
        pSel->selFlags |= SF_MultiPart;
      }
    }
  }
}

/*
** Return 0 if the two window objects are identical, or non-zero otherwise.
** Identical window objects can be processed in a single scan.
** Return 0 if the two window objects are identical, 1 if they are
** different, or 2 if it cannot be determined if the objects are identical
** or not. Identical window objects can be processed in a single scan.
*/
int sqlite3WindowCompare(Parse *pParse, Window *p1, Window *p2){
  if( p1->eType!=p2->eType ) return 1;
int sqlite3WindowCompare(
  const Parse *pParse,
  const Window *p1,
  const Window *p2,
  int bFilter
){
  int res;
  if( NEVER(p1==0) || NEVER(p2==0) ) return 1;
  if( p1->eFrmType!=p2->eFrmType ) return 1;
  if( p1->eStart!=p2->eStart ) return 1;
  if( p1->eEnd!=p2->eEnd ) return 1;
  if( p1->eExclude!=p2->eExclude ) return 1;
  if( sqlite3ExprCompare(pParse, p1->pStart, p2->pStart, -1) ) return 1;
  if( sqlite3ExprCompare(pParse, p1->pEnd, p2->pEnd, -1) ) return 1;
  if( sqlite3ExprListCompare(p1->pPartition, p2->pPartition, -1) ) return 1;
  if( sqlite3ExprListCompare(p1->pOrderBy, p2->pOrderBy, -1) ) return 1;
  if( (res = sqlite3ExprListCompare(p1->pPartition, p2->pPartition, -1)) ){
    return res;
  }
  if( (res = sqlite3ExprListCompare(p1->pOrderBy, p2->pOrderBy, -1)) ){
    return res;
  }
  if( bFilter ){
    if( (res = sqlite3ExprCompare(pParse, p1->pFilter, p2->pFilter, -1)) ){
      return res;
    }
  }
  return 0;
}


/*
** This is called by code in select.c before it calls sqlite3WhereBegin()
** to begin iterating through the sub-query results. It is used to allocate
** and initialize registers and cursors used by sqlite3WindowCodeStep().
*/
void sqlite3WindowCodeInit(Parse *pParse, Window *pMWin){
void sqlite3WindowCodeInit(Parse *pParse, Select *pSelect){
  int nEphExpr = pSelect->pSrc->a[0].pSelect->pEList->nExpr;
  Window *pMWin = pSelect->pWin;
  Window *pWin;
  Vdbe *v = sqlite3GetVdbe(pParse);
  int nPart = (pMWin->pPartition ? pMWin->pPartition->nExpr : 0);
  nPart += (pMWin->pOrderBy ? pMWin->pOrderBy->nExpr : 0);
  if( nPart ){

  sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pMWin->iEphCsr, nEphExpr);
  sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+1, pMWin->iEphCsr);
  sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+2, pMWin->iEphCsr);
  sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+3, pMWin->iEphCsr);

  /* Allocate registers to use for PARTITION BY values, if any. Initialize
  ** said registers to NULL.  */
  if( pMWin->pPartition ){
    int nExpr = pMWin->pPartition->nExpr;
    pMWin->regPart = pParse->nMem+1;
    pParse->nMem += nPart;
    sqlite3VdbeAddOp3(v, OP_Null, 0, pMWin->regPart, pMWin->regPart+nPart-1);
    pParse->nMem += nExpr;
    sqlite3VdbeAddOp3(v, OP_Null, 0, pMWin->regPart, pMWin->regPart+nExpr-1);
  }

  pMWin->regOne = ++pParse->nMem;
  sqlite3VdbeAddOp2(v, OP_Integer, 1, pMWin->regOne);

  if( pMWin->eExclude ){
    pMWin->regStartRowid = ++pParse->nMem;
    pMWin->regEndRowid = ++pParse->nMem;
    pMWin->csrApp = pParse->nTab++;
    sqlite3VdbeAddOp2(v, OP_Integer, 1, pMWin->regStartRowid);
    sqlite3VdbeAddOp2(v, OP_Integer, 0, pMWin->regEndRowid);
    sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->csrApp, pMWin->iEphCsr);
    return;
  }

  for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
    FuncDef *p = pWin->pFunc;
    FuncDef *p = pWin->pWFunc;
    if( (p->funcFlags & SQLITE_FUNC_MINMAX) && pWin->eStart!=TK_UNBOUNDED ){
      /* The inline versions of min() and max() require a single ephemeral
      ** table and 3 registers. The registers are used as follows:
      **
      **   regApp+0: slot to copy min()/max() argument to for MakeRecord
      **   regApp+1: integer value used to ensure keys are unique
      **   regApp+2: output of MakeRecord
      */
      ExprList *pList;
      KeyInfo *pKeyInfo;
      assert( ExprUseXList(pWin->pOwner) );
      ExprList *pList = pWin->pOwner->x.pList;
      KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pList, 0, 0);
      pList = pWin->pOwner->x.pList;
      pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pList, 0, 0);
      pWin->csrApp = pParse->nTab++;
      pWin->regApp = pParse->nMem+1;
      pParse->nMem += 3;
      if( pKeyInfo && pWin->pFunc->zName[1]=='i' ){
        assert( pKeyInfo->aSortOrder[0]==0 );
        pKeyInfo->aSortOrder[0] = 1;
      if( pKeyInfo && pWin->pWFunc->zName[1]=='i' ){
        assert( pKeyInfo->aSortFlags[0]==0 );
        pKeyInfo->aSortFlags[0] = KEYINFO_ORDER_DESC;
      }
      sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pWin->csrApp, 2);
      sqlite3VdbeAppendP4(v, pKeyInfo, P4_KEYINFO);
      sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp+1);
    }
    else if( p->zName==nth_valueName || p->zName==first_valueName ){
      /* Allocate two registers at pWin->regApp. These will be used to
      ** store the start and end index of the current frame.  */
      assert( pMWin->iEphCsr );
      pWin->regApp = pParse->nMem+1;
      pWin->csrApp = pParse->nTab++;
      pParse->nMem += 2;
      sqlite3VdbeAddOp2(v, OP_OpenDup, pWin->csrApp, pMWin->iEphCsr);
    }
    else if( p->zName==leadName || p->zName==lagName ){
      assert( pMWin->iEphCsr );
      pWin->csrApp = pParse->nTab++;
      sqlite3VdbeAddOp2(v, OP_OpenDup, pWin->csrApp, pMWin->iEphCsr);
    }
  }
}

#define WINDOW_STARTING_INT  0
#define WINDOW_ENDING_INT    1
#define WINDOW_NTH_VALUE_INT 2
#define WINDOW_STARTING_NUM  3
#define WINDOW_ENDING_NUM    4

/*
** A "PRECEDING <expr>" (eCond==0) or "FOLLOWING <expr>" (eCond==1) or the
** value of the second argument to nth_value() (eCond==2) has just been
** evaluated and the result left in register reg. This function generates VM
** code to check that the value is a non-negative integer and throws an
** exception if it is not.
*/
static void windowCheckIntValue(Parse *pParse, int reg, int eCond){
static void windowCheckValue(Parse *pParse, int reg, int eCond){
  static const char *azErr[] = {
    "frame starting offset must be a non-negative integer",
    "frame ending offset must be a non-negative integer",
    "second argument to nth_value must be a positive integer"
    "second argument to nth_value must be a positive integer",
    "frame starting offset must be a non-negative number",
    "frame ending offset must be a non-negative number",
  };
  static int aOp[] = { OP_Ge, OP_Ge, OP_Gt };
  static int aOp[] = { OP_Ge, OP_Ge, OP_Gt, OP_Ge, OP_Ge };
  Vdbe *v = sqlite3GetVdbe(pParse);
  int regZero = sqlite3GetTempReg(pParse);
  assert( eCond==0 || eCond==1 || eCond==2 );
  assert( eCond>=0 && eCond<ArraySize(azErr) );
  sqlite3VdbeAddOp2(v, OP_Integer, 0, regZero);
  if( eCond>=WINDOW_STARTING_NUM ){
    int regString = sqlite3GetTempReg(pParse);
    sqlite3VdbeAddOp4(v, OP_String8, 0, regString, 0, "", P4_STATIC);
    sqlite3VdbeAddOp3(v, OP_Ge, regString, sqlite3VdbeCurrentAddr(v)+2, reg);
    sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC|SQLITE_JUMPIFNULL);
    VdbeCoverage(v);
    assert( eCond==3 || eCond==4 );
    VdbeCoverageIf(v, eCond==3);
    VdbeCoverageIf(v, eCond==4);
  }else{
  sqlite3VdbeAddOp2(v, OP_MustBeInt, reg, sqlite3VdbeCurrentAddr(v)+2);
  VdbeCoverageIf(v, eCond==0);
  VdbeCoverageIf(v, eCond==1);
  VdbeCoverageIf(v, eCond==2);
    sqlite3VdbeAddOp2(v, OP_MustBeInt, reg, sqlite3VdbeCurrentAddr(v)+2);
    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);
  VdbeCoverageNeverNullIf(v, eCond==1);
  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);
  sqlite3VdbeAppendP4(v, (void*)azErr[eCond], P4_STATIC);
  sqlite3ReleaseTempReg(pParse, regZero);
}

/*
** Return the number of arguments passed to the window-function associated
** with the object passed as the only argument to this function.
*/
static int windowArgCount(Window *pWin){
  const ExprList *pList;
  assert( ExprUseXList(pWin->pOwner) );
  ExprList *pList = pWin->pOwner->x.pList;
  pList = pWin->pOwner->x.pList;
  return (pList ? pList->nExpr : 0);
}

typedef struct WindowCodeArg WindowCodeArg;
typedef struct WindowCsrAndReg WindowCsrAndReg;

/*
** See comments above struct WindowCodeArg.
*/
struct WindowCsrAndReg {
  int csr;                        /* Cursor number */
  int reg;                        /* First in array of peer values */
};

/*
** A single instance of this structure is allocated on the stack by 
** sqlite3WindowCodeStep() and a pointer to it passed to the various helper
** routines. This is to reduce the number of arguments required by each
** helper function.
**
** regArg:
**   Each window function requires an accumulator register (just as an
**   ordinary aggregate function does). This variable is set to the first
**   in an array of accumulator registers - one for each window function
**   in the WindowCodeArg.pMWin list.
**
** eDelete:
**   The window functions implementation sometimes caches the input rows
**   that it processes in a temporary table. If it is not zero, this
**   variable indicates when rows may be removed from the temp table (in
**   order to reduce memory requirements - it would always be safe just
**   to leave them there). Possible values for eDelete are:
**
**      WINDOW_RETURN_ROW:
**        An input row can be discarded after it is returned to the caller.
**
**      WINDOW_AGGINVERSE:
**        An input row can be discarded after the window functions xInverse()
**        callbacks have been invoked in it.
**
**      WINDOW_AGGSTEP:
**        An input row can be discarded after the window functions xStep()
**        callbacks have been invoked in it.
**
** start,current,end
**   Consider a window-frame similar to the following:
**
**     (ORDER BY a, b GROUPS BETWEEN 2 PRECEDING AND 2 FOLLOWING)
**
**   The windows functions implmentation caches the input rows in a temp
**   table, sorted by "a, b" (it actually populates the cache lazily, and
**   aggressively removes rows once they are no longer required, but that's
**   a mere detail). It keeps three cursors open on the temp table. One
**   (current) that points to the next row to return to the query engine
**   once its window function values have been calculated. Another (end)
**   points to the next row to call the xStep() method of each window function
**   on (so that it is 2 groups ahead of current). And a third (start) that
**   points to the next row to call the xInverse() method of each window
**   function on.
**
**   Each cursor (start, current and end) consists of a VDBE cursor
**   (WindowCsrAndReg.csr) and an array of registers (starting at
**   WindowCodeArg.reg) that always contains a copy of the peer values 
**   read from the corresponding cursor.
**
**   Depending on the window-frame in question, all three cursors may not
**   be required. In this case both WindowCodeArg.csr and reg are set to
**   0.
*/
struct WindowCodeArg {
  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;
};

/*
** Generate VM code to read the window frames peer values from cursor csr into
** an array of registers starting at reg.
*/
static void windowReadPeerValues(
  WindowCodeArg *p,
  int csr,
  int reg
){
  Window *pMWin = p->pMWin;
  ExprList *pOrderBy = pMWin->pOrderBy;
  if( pOrderBy ){
    Vdbe *v = sqlite3GetVdbe(p->pParse);
    ExprList *pPart = pMWin->pPartition;
    int iColOff = pMWin->nBufferCol + (pPart ? pPart->nExpr : 0);
    int i;
    for(i=0; i<pOrderBy->nExpr; i++){
      sqlite3VdbeAddOp3(v, OP_Column, csr, iColOff+i, reg+i);
    }
  }
}

/*
** Generate VM code to invoke either xStep() (if bInverse is 0) or 
** xInverse (if bInverse is non-zero) for each window function in the 
** linked list starting at pMWin. Or, for built-in window functions
** that do not use the standard function API, generate the required
** inline VM code.
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
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
1318
1319

1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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
1430
1431
1432
1433
1434
1435
1436
1437


1438
1439

1440

1441
1442
1443
1444
1445



1446
1447
1448
1449
1450





1451
1452
1453
1454
1455
1456
1457
1458
1459
1460



1461
1462
1463

1464
1465


1466
1467

1468
1469
1470
1471
1472
1473
1474
1475


1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486


1487
1488
1489
1490
1491
1492
1493
1494
1495
1496







1497
1498
1499


1500
1501
1502
1503




1504
1505
1506
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





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
1574
1575
1576
1577



1578
1579

1580
1581
1582
1583
1584






1585
1586

1587
1588
1589
1590
1591
1592
1593
1594




1595
1596
1597
1598


1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619


1620
1621
1622
1623
1624
1625



1626
1627
1628
1629
1630
1631
1632
1633
1634
1635







1636
1637
1638
1639
1640

1641
1642
1643

1644
1645
1646
1647
1648

1649
1650

1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662

1663
1664

1665
1666
1667
1668
1669
1670
1671


1672
1673
1674

1675
1676
1677
1678
1679
1680
1681
1682
1683

1684
1685
1686





1687
1688

1689
1690
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


1744
1745





1746
1747
1748
1749

1750
1751
1752
1753
1754

1755
1756
1757
1758

1759
1760
1761
1762
1763
1764
1765
1766


1767
1768
1769
1770
1771
1772
1773
1774
1775

1776
1777
1778
1779
1780
1781
1782
1783
1784
1785

1786
1787
1788
1789
1790
1791
1792
1793
1794



















1795
1796
1797



1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824


1825
1826
1827
1828
1829
1830
1831
1832
1833











1834
1835
1836
1837
1838




1839
1840
1841
1842
1843
1844
1845
1846
1847
1848

1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859

1860
1861

1862
1863


1864

1865


1866

1867
1868
1869
1870
1871
1872
1873
1874


1875
1876
1877
1878
1879
1880
1881



1882
1883
1884


1885
1886

1887
1888


1889
1890
1891
1892

1893
1894

1895
1896

1897
1898
1899
1900
1901
1902
1903


1904
1905
1906


1907
1908
1909
1910
1911
1912

1913
1914
1915
1916
1917
1918
1919
1920
1921
1922










1923
1924
1925
1926



1927
1928
1929

1930
1931

1932
1933
1934
1935
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
1984
1985
1986
1987
1988
1989
1990
1991
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
2017
2018
2019





2020
2021
2022
2023
2024
2025
2026


2027
2028
2029

2030
2031
2032
2033
2034
2035
2036


2037
2038


2039
2040
2041

2042
2043
2044
2045
2046
2047

2048
2049
2050
2051

2052
2053
2054
2055
2056



2057
2058
2059
2060

2061
2062


2063
2064
2065

2066

2067
2068

2069
2070
2071



2072
2073
2074
2075
2076
2077
2078
2079
2080
2081

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
1646
1647
1648
1649
1650
1651
1652

1653
1654
1655
1656

1657

1658
1659
1660
1661
1662

1663
1664

1665
1666
1667
1668



1669
1670
1671
1672
1673
1674
1675
1676








1677
1678
1679


1680







1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701


1702
1703
1704
1705
1706

1707




1708
1709
1710
1711


1712
1713



1714
1715



1716
1717





1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745

1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763


1764
1765
1766
1767
1768

1769
1770
1771
1772
1773
1774
1775
1776


1777
1778
1779
1780
1781
1782
1783
1784



1785
1786
1787
1788



1789
1790
1791
1792
1793
1794

1795


1796
1797
1798
1799
1800
1801
1802



1803
1804
1805
1806
1807


1808
1809
1810











1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833

1834



1835
1836
1837
1838
1839


1840










1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860









1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876



1877
1878
1879
1880
1881
1882
1883




1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895


1896



1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913

1914


































1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
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
1984
1985
1986
1987
1988
1989
1990
1991
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
2017
2018



2019
2020
2021



2022


2023
2024


2025








2026
2027











2028
2029










2030
2031
2032
2033
2034
2035
2036



2037
2038




2039
2040
2041
2042









2043









2044
2045
2046

2047







2048
2049
2050
2051
2052
2053
2054


2055




2056
2057
2058
2059
2060
2061
2062
2063



2064
2065
2066
2067


2068
2069
2070
2071




2072
2073
2074
2075
2076

2077





2078








2079

2080
2081
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
2164
2165
2166
2167
2168
2169



2170
2171


2172
2173
2174
2175
2176
2177

2178

2179





2180




2181








2182
2183









2184










2185









2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
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
2234

2235








2236
2237







2238
2239
2240



2241
2242

2243
2244


2245
2246




2247


2248


2249



2250



2251
2252



2253
2254






2255










2256
2257
2258
2259
2260
2261
2262
2263
2264
2265




2266
2267
2268



2269


2270













2271
2272

2273

2274






2275
2276
2277
2278

2279






2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297


2298




2299
2300





2301
2302
2303
2304
2305


























2306
2307










2308



2309
2310



2311





2312
2313
2314
2315
2316







2317
2318



2319







2320
2321


2322
2323
2324


2325






2326




2327





2328
2329
2330




2331


2332
2333


2334
2335

2336
2337

2338



2339
2340
2341










2342





2343
2344
2345


2346
2347
2348
2349

2350


2351



2352

2353
2354
2355
2356
2357





2358
2359
2360
2361
2362
2363



2364

2365

2366


2367



2368







2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383

2384
2385
2386

2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406







-
+



-
+
-

+



-
+

-
+
+

+
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
+
+
+
-
-
+
-
-
-
-
-
-
-
+
+
+
+
+
















-
-
+
+



-
+
-
-
-
-



+
-
-
+
+
-
-
-
+
+
-
-
-


-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+





-
+

+
+
+






+
+
+
+
+
+
+
-
-
+
+



-
+
+
+




+
-
-
+
+






-
-
-

+

+
-
-
-
+
+
+



-
+
-
-
+






-
-
-
+
+
+
+

-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+
-
-
-
+
+
+
+
+
-
-

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+


+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-

-
-
-
+
+















-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-














-
+
+


+
-
+
-
-
-
-
-
+
+
+

-
-
-
-
+
+
+
+
+







-
-
-
+
+
+
-
-
-
+
-
-
+
+
-
-
+
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-

+
+
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
+
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
-
-
+
+
+
+
-
-
-
-
+
+
+
+
+
-

-
-
-
-
-
+
-
-
-
-
-
-
-
-

-
+
+

-
+
+
+
+
+

-
+
-
-
-
-
-
-
-
-
-
-

+
+
+

-
+
-
-
-
-
-
+
+
+
+
+
+

-
+

-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-

-
+
+
+

-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
+
-
-
-
+


-
-
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
-
-
-
-
-
+
+
-
-
-
+
-
-
-
-
-
-
-
-
-
+
-
-
-
+
+
+
+
+
-
-
+
-
-
-
-
-
-
+
-
-
+
-
-
-
-
+
+
-
-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
-
-
-
-
-
+
-
-
-
-
-
-
-
+
+
-
-
-
-
+
+
+
+
+
+

-
-
-
+
+
-
-
+
+
+
+
+

-

-
+
-
-
-
-
-
+
-
-
-
-
+
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-

-
+
-
-
+
-
-
+
+
-
+

+
+
-
+
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
+
+
+
-
-
-
+
+
-

+
-
-
+
+
-
-
-
-
+
-
-
+
-
-
+
-
-
-

-
-
-
+
+
-
-
-
+
+
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
-
-
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+

-

-
+
-
-
-
-
-
-
+
+
+
+
-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
-
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+
+
-
-
-
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
+
+
-
-
-
+
-
-
-
-
-
-
-
+
+
-
-
+
+

-
-
+
-
-
-
-
-
-
+
-
-
-
-
+
-
-
-
-
-
+
+
+
-
-
-
-
+
-
-
+
+
-
-

+
-
+

-
+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
+
+

-
-
+
+
+

-
+
-
-
+
-
-
-
+
-


+
+
+
-
-
-
-
-
+
+
+
+
+
+
-
-
-
+
-

-
+
-
-
+
-
-
-
+
-
-
-
-
-
-
-
+












+

-
+


-
+


+
+
+
+
+
+



+







** Or, if csr is less than zero, then the array of registers at reg is
** already populated with all columns from the current row of the sub-query.
**
** If argument regPartSize is non-zero, then it is a register containing the
** number of rows in the current partition.
*/
static void windowAggStep(
  Parse *pParse, 
  WindowCodeArg *p,
  Window *pMWin,                  /* Linked list of window functions */
  int csr,                        /* Read arguments from this cursor */
  int bInverse,                   /* True to invoke xInverse instead of xStep */
  int reg,                        /* Array of registers */
  int reg                         /* Array of registers */
  int regPartSize                 /* Register containing size of partition */
){
  Parse *pParse = p->pParse;
  Vdbe *v = sqlite3GetVdbe(pParse);
  Window *pWin;
  for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
    int flags = pWin->pFunc->funcFlags;
    FuncDef *pFunc = pWin->pWFunc;
    int regArg;
    int nArg = windowArgCount(pWin);
    int nArg = pWin->bExprArgs ? 0 : windowArgCount(pWin);
    int i;

    assert( bInverse==0 || pWin->eStart!=TK_UNBOUNDED );
    if( csr>=0 ){
      int i;
      for(i=0; i<nArg; i++){

    /* All OVER clauses in the same window function aggregate step must
    ** be the same. */
    assert( pWin==pMWin || sqlite3WindowCompare(pParse,pWin,pMWin,0)!=1 );

    for(i=0; i<nArg; i++){
      if( i!=1 || pFunc->zName!=nth_valueName ){
        sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+i, reg+i);
      }
      regArg = reg;
      if( flags & SQLITE_FUNC_WINDOW_SIZE ){
        if( nArg==0 ){
          regArg = regPartSize;
        }else{
          sqlite3VdbeAddOp2(v, OP_SCopy, regPartSize, reg+nArg);
        }
      }else{
        sqlite3VdbeAddOp3(v, OP_Column, pMWin->iEphCsr, pWin->iArgCol+i, reg+i);
      }
        nArg++;
      }
    }
    }else{
      assert( !(flags & SQLITE_FUNC_WINDOW_SIZE) );
      regArg = reg + pWin->iArgCol;
    }

    if( (pWin->pFunc->funcFlags & SQLITE_FUNC_MINMAX) 
      && pWin->eStart!=TK_UNBOUNDED 
    regArg = reg;

    if( pMWin->regStartRowid==0
     && (pFunc->funcFlags & SQLITE_FUNC_MINMAX) 
     && (pWin->eStart!=TK_UNBOUNDED)
    ){
      int addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regArg);
      VdbeCoverage(v);
      if( bInverse==0 ){
        sqlite3VdbeAddOp2(v, OP_AddImm, pWin->regApp+1, 1);
        sqlite3VdbeAddOp2(v, OP_SCopy, regArg, pWin->regApp);
        sqlite3VdbeAddOp3(v, OP_MakeRecord, pWin->regApp, 2, pWin->regApp+2);
        sqlite3VdbeAddOp2(v, OP_IdxInsert, pWin->csrApp, pWin->regApp+2);
      }else{
        sqlite3VdbeAddOp4Int(v, OP_SeekGE, pWin->csrApp, 0, regArg, 1);
        VdbeCoverageNeverTaken(v);
        sqlite3VdbeAddOp1(v, OP_Delete, pWin->csrApp);
        sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
      }
      sqlite3VdbeJumpHere(v, addrIsNull);
    }else if( pWin->regApp ){
      assert( pWin->pFunc->zName==nth_valueName
           || pWin->pFunc->zName==first_valueName
      assert( pFunc->zName==nth_valueName
           || pFunc->zName==first_valueName
      );
      assert( bInverse==0 || bInverse==1 );
      sqlite3VdbeAddOp2(v, OP_AddImm, pWin->regApp+1-bInverse, 1);
    }else if( pWin->pFunc->zName==leadName
    }else if( pFunc->xSFunc!=noopStepFunc ){
           || pWin->pFunc->zName==lagName
    ){
      /* no-op */
    }else{
      int addrIf = 0;
      if( pWin->pFilter ){
        int regTmp;
        assert( ExprUseXList(pWin->pOwner) );
        assert( nArg==0 || nArg==pWin->pOwner->x.pList->nExpr );
        assert( nArg || pWin->pOwner->x.pList==0 );
        assert( pWin->bExprArgs || !nArg ||nArg==pWin->pOwner->x.pList->nExpr );
        assert( pWin->bExprArgs || nArg  ||pWin->pOwner->x.pList==0 );
        if( csr>0 ){
          regTmp = sqlite3GetTempReg(pParse);
          sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+nArg,regTmp);
        regTmp = sqlite3GetTempReg(pParse);
        sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+nArg,regTmp);
        }else{
          regTmp = regArg + nArg;
        }
        addrIf = sqlite3VdbeAddOp3(v, OP_IfNot, regTmp, 0, 1);
        VdbeCoverage(v);
        if( csr>0 ){
          sqlite3ReleaseTempReg(pParse, regTmp);
        }
      }
      if( pWin->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){
        sqlite3ReleaseTempReg(pParse, regTmp);
      }
      
      if( pWin->bExprArgs ){
        int iOp = sqlite3VdbeCurrentAddr(v);
        int iEnd;

        assert( ExprUseXList(pWin->pOwner) );
        nArg = pWin->pOwner->x.pList->nExpr;
        regArg = sqlite3GetTempRange(pParse, nArg);
        sqlite3ExprCodeExprList(pParse, pWin->pOwner->x.pList, regArg, 0, 0);

        for(iEnd=sqlite3VdbeCurrentAddr(v); iOp<iEnd; iOp++){
          VdbeOp *pOp = sqlite3VdbeGetOp(v, iOp);
          if( pOp->opcode==OP_Column && pOp->p1==pMWin->iEphCsr ){
            pOp->p1 = csr;
          }
        }
      }
      if( pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){
        CollSeq *pColl;
        assert( nArg>0 );
        assert( ExprUseXList(pWin->pOwner) );
        pColl = sqlite3ExprNNCollSeq(pParse, pWin->pOwner->x.pList->a[0].pExpr);
        sqlite3VdbeAddOp4(v, OP_CollSeq, 0,0,0, (const char*)pColl, P4_COLLSEQ);
      }
      sqlite3VdbeAddOp3(v, bInverse? OP_AggInverse : OP_AggStep, 
                        bInverse, regArg, pWin->regAccum);
      sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF);
      sqlite3VdbeAppendP4(v, pFunc, P4_FUNCDEF);
      sqlite3VdbeChangeP5(v, (u8)nArg);
      if( pWin->bExprArgs ){
        sqlite3ReleaseTempRange(pParse, regArg, nArg);
      }
      if( addrIf ) sqlite3VdbeJumpHere(v, addrIf);
    }
  }
}

/*
** Values that may be passed as the second argument to windowCodeOp().
*/
#define WINDOW_RETURN_ROW 1
#define WINDOW_AGGINVERSE 2
#define WINDOW_AGGSTEP    3

/*
** Generate VM code to invoke either xValue() (bFinal==0) or xFinalize()
** (bFinal==1) for each window function in the linked list starting at
** Generate VM code to invoke either xValue() (bFin==0) or xFinalize()
** (bFin==1) for each window function in the linked list starting at
** pMWin. Or, for built-in window-functions that do not use the standard
** API, generate the equivalent VM code.
*/
static void windowAggFinal(Parse *pParse, Window *pMWin, int bFinal){
static void windowAggFinal(WindowCodeArg *p, int bFin){
  Parse *pParse = p->pParse;
  Window *pMWin = p->pMWin;
  Vdbe *v = sqlite3GetVdbe(pParse);
  Window *pWin;

  for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
    if( pMWin->regStartRowid==0
    if( (pWin->pFunc->funcFlags & SQLITE_FUNC_MINMAX) 
     && pWin->eStart!=TK_UNBOUNDED 
     && (pWin->pWFunc->funcFlags & SQLITE_FUNC_MINMAX) 
     && (pWin->eStart!=TK_UNBOUNDED)
    ){
      sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult);
      sqlite3VdbeAddOp1(v, OP_Last, pWin->csrApp);
      VdbeCoverage(v);
      sqlite3VdbeAddOp3(v, OP_Column, pWin->csrApp, 0, pWin->regResult);
      sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
      if( bFinal ){
        sqlite3VdbeAddOp1(v, OP_ResetSorter, pWin->csrApp);
      }
    }else if( pWin->regApp ){
      assert( pMWin->regStartRowid==0 );
    }else{
      int nArg = windowArgCount(pWin);
      if( bFinal ){
        sqlite3VdbeAddOp2(v, OP_AggFinal, pWin->regAccum, windowArgCount(pWin));
        sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF);
      if( bFin ){
        sqlite3VdbeAddOp2(v, OP_AggFinal, pWin->regAccum, nArg);
        sqlite3VdbeAppendP4(v, pWin->pWFunc, P4_FUNCDEF);
        sqlite3VdbeAddOp2(v, OP_Copy, pWin->regAccum, pWin->regResult);
        sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum);
      }else{
        sqlite3VdbeAddOp3(v, OP_AggValue, pWin->regAccum, windowArgCount(pWin),
        sqlite3VdbeAddOp3(v, OP_AggValue,pWin->regAccum,nArg,pWin->regResult);
                             pWin->regResult);
        sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF);
        sqlite3VdbeAppendP4(v, pWin->pWFunc, P4_FUNCDEF);
      }
    }
  }
}

/*
** This function generates VM code to invoke the sub-routine at address
** lblFlushPart once for each partition with the entire partition cached in
** the Window.iEphCsr temp table.
** Generate code to calculate the current values of all window functions in the
** p->pMWin list by doing a full scan of the current window frame. Store the
** results in the Window.regResult registers, ready to return the upper
** layer.
*/
static void windowPartitionCache(
  Parse *pParse,
static void windowFullScan(WindowCodeArg *p){
  Window *pWin;
  Parse *pParse = p->pParse;
  Select *p,                      /* The rewritten SELECT statement */
  WhereInfo *pWInfo,              /* WhereInfo to call WhereEnd() on */
  int regFlushPart,               /* Register to use with Gosub lblFlushPart */
  int lblFlushPart,               /* Subroutine to Gosub to */
  int *pRegSize                   /* OUT: Register containing partition size */
){
  Window *pMWin = p->pWin;
  Vdbe *v = sqlite3GetVdbe(pParse);
  int iSubCsr = p->pSrc->a[0].iCursor;
  int nSub = p->pSrc->a[0].pTab->nCol;
  int k;
  Window *pMWin = p->pMWin;
  Vdbe *v = p->pVdbe;

  int regCRowid = 0;              /* Current rowid value */
  int regCPeer = 0;               /* Current peer values */
  int regRowid = 0;               /* AggStep rowid value */
  int regPeer = 0;                /* AggStep peer values */

  int nPeer;
  int lblNext;
  int lblBrk;
  int addrNext;
  int csr;

  VdbeModuleComment((v, "windowFullScan begin"));

  assert( pMWin!=0 );
  csr = pMWin->csrApp;
  nPeer = (pMWin->pOrderBy ? pMWin->pOrderBy->nExpr : 0);

  lblNext = sqlite3VdbeMakeLabel(pParse);
  lblBrk = sqlite3VdbeMakeLabel(pParse);

  int reg = pParse->nMem+1;
  regCRowid = sqlite3GetTempReg(pParse);
  int regRecord = reg+nSub;
  int regRowid = regRecord+1;

  regRowid = sqlite3GetTempReg(pParse);
  if( nPeer ){
    regCPeer = sqlite3GetTempRange(pParse, nPeer);
    regPeer = sqlite3GetTempRange(pParse, nPeer);
  }
  *pRegSize = regRowid;
  pParse->nMem += nSub + 2;

  /* Load the column values for the row returned by the sub-select
  ** into an array of registers starting at reg. */
  for(k=0; k<nSub; k++){
    sqlite3VdbeAddOp3(v, OP_Column, iSubCsr, k, reg+k);
  }
  sqlite3VdbeAddOp3(v, OP_MakeRecord, reg, nSub, regRecord);

  /* Check if this is the start of a new partition. If so, call the
  ** flush_partition sub-routine.  */
  if( pMWin->pPartition ){
  sqlite3VdbeAddOp2(v, OP_Rowid, pMWin->iEphCsr, regCRowid);
  windowReadPeerValues(p, pMWin->iEphCsr, regCPeer);

  for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
    sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum);
  }

  sqlite3VdbeAddOp3(v, OP_SeekGE, csr, lblBrk, pMWin->regStartRowid);
  VdbeCoverage(v);
  addrNext = sqlite3VdbeCurrentAddr(v);
  sqlite3VdbeAddOp2(v, OP_Rowid, csr, regRowid);
  sqlite3VdbeAddOp3(v, OP_Gt, pMWin->regEndRowid, lblBrk, regRowid);
  VdbeCoverageNeverNull(v);

  if( pMWin->eExclude==TK_CURRENT ){
    sqlite3VdbeAddOp3(v, OP_Eq, regCRowid, lblNext, regRowid);
    VdbeCoverageNeverNull(v);
  }else if( pMWin->eExclude!=TK_NO ){
    int addr;
    int addrEq = 0;
    ExprList *pPart = pMWin->pPartition;
    int nPart = pPart->nExpr;
    int regNewPart = reg + pMWin->nBufferCol;
    KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pPart, 0, 0);

    addr = sqlite3VdbeAddOp3(v, OP_Compare, regNewPart, pMWin->regPart,nPart);
    sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO);
    sqlite3VdbeAddOp3(v, OP_Jump, addr+2, addr+4, addr+2);
    VdbeCoverageEqNe(v);
    KeyInfo *pKeyInfo = 0;

    if( pMWin->pOrderBy ){
      pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pMWin->pOrderBy, 0, 0);
    }
    if( pMWin->eExclude==TK_TIES ){
      addrEq = sqlite3VdbeAddOp3(v, OP_Eq, regCRowid, 0, regRowid);
      VdbeCoverageNeverNull(v);
    }
    if( pKeyInfo ){
      windowReadPeerValues(p, csr, regPeer);
      sqlite3VdbeAddOp3(v, OP_Compare, regPeer, regCPeer, nPeer);
      sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO);
      addr = sqlite3VdbeCurrentAddr(v)+1;
      sqlite3VdbeAddOp3(v, OP_Jump, addr, lblNext, addr);
      VdbeCoverageEqNe(v);
    sqlite3VdbeAddOp3(v, OP_Copy, regNewPart, pMWin->regPart, nPart-1);
    sqlite3VdbeAddOp2(v, OP_Gosub, regFlushPart, lblFlushPart);
    VdbeComment((v, "call flush_partition"));
    }else{
      sqlite3VdbeAddOp2(v, OP_Goto, 0, lblNext);
    }
    if( addrEq ) sqlite3VdbeJumpHere(v, addrEq);
  }

  windowAggStep(p, pMWin, csr, 0, p->regArg);
  /* Buffer the current row in the ephemeral table. */
  sqlite3VdbeAddOp2(v, OP_NewRowid, pMWin->iEphCsr, regRowid);
  sqlite3VdbeAddOp3(v, OP_Insert, pMWin->iEphCsr, regRecord, regRowid);


  sqlite3VdbeResolveLabel(v, lblNext);
  sqlite3VdbeAddOp2(v, OP_Next, csr, addrNext);
  VdbeCoverage(v);
  sqlite3VdbeJumpHere(v, addrNext-1);
  sqlite3VdbeJumpHere(v, addrNext+1);
  sqlite3ReleaseTempReg(pParse, regRowid);
  sqlite3ReleaseTempReg(pParse, regCRowid);
  if( nPeer ){
    sqlite3ReleaseTempRange(pParse, regPeer, nPeer);
    sqlite3ReleaseTempRange(pParse, regCPeer, nPeer);
  }
  /* End of the input loop */
  sqlite3WhereEnd(pWInfo);

  /* Invoke "flush_partition" to deal with the final (or only) partition */
  sqlite3VdbeAddOp2(v, OP_Gosub, regFlushPart, lblFlushPart);
  VdbeComment((v, "call flush_partition"));
  windowAggFinal(p, 1);
  VdbeModuleComment((v, "windowFullScan end"));
}

/*
** Invoke the sub-routine at regGosub (generated by code in select.c) to
** return the current row of Window.iEphCsr. If all window functions are
** aggregate window functions that use the standard API, a single
** OP_Gosub instruction is all that this routine generates. Extra VM code
** for per-row processing is only generated for the following built-in window
** functions:
**
**   nth_value()
**   first_value()
**   lag()
**   lead()
*/
static void windowReturnOneRow(
static void windowReturnOneRow(WindowCodeArg *p){
  Parse *pParse,
  Window *pMWin,
  int regGosub,
  int addrGosub
){
  Vdbe *v = sqlite3GetVdbe(pParse);
  Window *pWin;
  for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
    FuncDef *pFunc = pWin->pFunc;
    if( pFunc->zName==nth_valueName
     || pFunc->zName==first_valueName
    ){
      int csr = pWin->csrApp;
      int lbl = sqlite3VdbeMakeLabel(v);
      int tmpReg = sqlite3GetTempReg(pParse);
      sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult);

      if( pFunc->zName==nth_valueName ){
        sqlite3VdbeAddOp3(v, OP_Column, pMWin->iEphCsr, pWin->iArgCol+1,tmpReg);
        windowCheckIntValue(pParse, tmpReg, 2);
      }else{
        sqlite3VdbeAddOp2(v, OP_Integer, 1, tmpReg);
      }
      sqlite3VdbeAddOp3(v, OP_Add, tmpReg, pWin->regApp, tmpReg);
      sqlite3VdbeAddOp3(v, OP_Gt, pWin->regApp+1, lbl, tmpReg);
      VdbeCoverageNeverNull(v);
      sqlite3VdbeAddOp3(v, OP_SeekRowid, csr, 0, tmpReg);
      VdbeCoverageNeverTaken(v);
      sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol, pWin->regResult);
      sqlite3VdbeResolveLabel(v, lbl);
      sqlite3ReleaseTempReg(pParse, tmpReg);
    }
    else if( pFunc->zName==leadName || pFunc->zName==lagName ){
      int nArg = pWin->pOwner->x.pList->nExpr;
  Window *pMWin = p->pMWin;
  Vdbe *v = p->pVdbe;

  if( pMWin->regStartRowid ){
    windowFullScan(p);
  }else{
    Parse *pParse = p->pParse;
    Window *pWin;

    for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
      FuncDef *pFunc = pWin->pWFunc;
      assert( ExprUseXList(pWin->pOwner) );
      if( pFunc->zName==nth_valueName
       || pFunc->zName==first_valueName
      ){
        int csr = pWin->csrApp;
        int lbl = sqlite3VdbeMakeLabel(pParse);
        int tmpReg = sqlite3GetTempReg(pParse);
        sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult);
  
        if( pFunc->zName==nth_valueName ){
          sqlite3VdbeAddOp3(v, OP_Column,pMWin->iEphCsr,pWin->iArgCol+1,tmpReg);
          windowCheckValue(pParse, tmpReg, 2);
        }else{
          sqlite3VdbeAddOp2(v, OP_Integer, 1, tmpReg);
        }
        sqlite3VdbeAddOp3(v, OP_Add, tmpReg, pWin->regApp, tmpReg);
        sqlite3VdbeAddOp3(v, OP_Gt, pWin->regApp+1, lbl, tmpReg);
        VdbeCoverageNeverNull(v);
        sqlite3VdbeAddOp3(v, OP_SeekRowid, csr, 0, tmpReg);
        VdbeCoverageNeverTaken(v);
        sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol, pWin->regResult);
        sqlite3VdbeResolveLabel(v, lbl);
        sqlite3ReleaseTempReg(pParse, tmpReg);
      }
      else if( pFunc->zName==leadName || pFunc->zName==lagName ){
        int nArg = pWin->pOwner->x.pList->nExpr;
      int iEph = pMWin->iEphCsr;
      int csr = pWin->csrApp;
      int lbl = sqlite3VdbeMakeLabel(v);
      int tmpReg = sqlite3GetTempReg(pParse);

      if( nArg<3 ){
        sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult);
      }else{
        sqlite3VdbeAddOp3(v, OP_Column, iEph, pWin->iArgCol+2, pWin->regResult);
      }
      sqlite3VdbeAddOp2(v, OP_Rowid, iEph, tmpReg);
      if( nArg<2 ){
        int val = (pFunc->zName==leadName ? 1 : -1);
        sqlite3VdbeAddOp2(v, OP_AddImm, tmpReg, val);
      }else{
        int op = (pFunc->zName==leadName ? OP_Add : OP_Subtract);
        int tmpReg2 = sqlite3GetTempReg(pParse);
        sqlite3VdbeAddOp3(v, OP_Column, iEph, pWin->iArgCol+1, tmpReg2);
        sqlite3VdbeAddOp3(v, op, tmpReg2, tmpReg, tmpReg);
        sqlite3ReleaseTempReg(pParse, tmpReg2);
      }

      sqlite3VdbeAddOp3(v, OP_SeekRowid, csr, lbl, tmpReg);
      VdbeCoverage(v);
      sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol, pWin->regResult);
      sqlite3VdbeResolveLabel(v, lbl);
      sqlite3ReleaseTempReg(pParse, tmpReg);
    }
  }
        int csr = pWin->csrApp;
        int lbl = sqlite3VdbeMakeLabel(pParse);
        int tmpReg = sqlite3GetTempReg(pParse);
        int iEph = pMWin->iEphCsr;
  
        if( nArg<3 ){
          sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult);
        }else{
          sqlite3VdbeAddOp3(v, OP_Column, iEph,pWin->iArgCol+2,pWin->regResult);
        }
        sqlite3VdbeAddOp2(v, OP_Rowid, iEph, tmpReg);
        if( nArg<2 ){
          int val = (pFunc->zName==leadName ? 1 : -1);
          sqlite3VdbeAddOp2(v, OP_AddImm, tmpReg, val);
        }else{
          int op = (pFunc->zName==leadName ? OP_Add : OP_Subtract);
          int tmpReg2 = sqlite3GetTempReg(pParse);
          sqlite3VdbeAddOp3(v, OP_Column, iEph, pWin->iArgCol+1, tmpReg2);
          sqlite3VdbeAddOp3(v, op, tmpReg2, tmpReg, tmpReg);
          sqlite3ReleaseTempReg(pParse, tmpReg2);
        }
  
        sqlite3VdbeAddOp3(v, OP_SeekRowid, csr, lbl, tmpReg);
        VdbeCoverage(v);
        sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol, pWin->regResult);
        sqlite3VdbeResolveLabel(v, lbl);
        sqlite3ReleaseTempReg(pParse, tmpReg);
      }
    }
  sqlite3VdbeAddOp2(v, OP_Gosub, regGosub, addrGosub);
}
  }

/*
** Invoke the code generated by windowReturnOneRow() and, optionally, the
** xInverse() function for each window function, for one or more rows
** from the Window.iEphCsr temp table. This routine generates VM code
** similar to:
**
**   while( regCtr>0 ){
**     regCtr--;
**     windowReturnOneRow()
**     if( bInverse ){
**       AggInverse
**     }
**     Next (Window.iEphCsr)
**   }
*/
static void windowReturnRows(
  Parse *pParse,
  Window *pMWin,                  /* List of window functions */
  int regCtr,                     /* Register containing number of rows */
  int regGosub,                   /* Register for Gosub addrGosub */
  int addrGosub,                  /* Address of sub-routine for ReturnOneRow */
  int regInvArg,                  /* Array of registers for xInverse args */
  int regInvSize                  /* Register containing size of partition */
){
  int addr;
  Vdbe *v = sqlite3GetVdbe(pParse);
  windowAggFinal(pParse, pMWin, 0);
  addr = sqlite3VdbeAddOp3(v, OP_IfPos, regCtr, sqlite3VdbeCurrentAddr(v)+2 ,1);
  VdbeCoverage(v);
  sqlite3VdbeAddOp2(v, OP_Goto, 0, 0);
  sqlite3VdbeAddOp2(v, OP_Gosub, p->regGosub, p->addrGosub);
  windowReturnOneRow(pParse, pMWin, regGosub, addrGosub);
  if( regInvArg ){
    windowAggStep(pParse, pMWin, pMWin->iEphCsr, 1, regInvArg, regInvSize);
  }
  sqlite3VdbeAddOp2(v, OP_Next, pMWin->iEphCsr, addr);
  VdbeCoverage(v);
  sqlite3VdbeJumpHere(v, addr+1);   /* The OP_Goto */
}

/*
** Generate code to set the accumulator register for each window function
** in the linked list passed as the second argument to NULL. And perform
** any equivalent initialization required by any built-in window functions
** in the list.
*/
static int windowInitAccum(Parse *pParse, Window *pMWin){
  Vdbe *v = sqlite3GetVdbe(pParse);
  int regArg;
  int nArg = 0;
  Window *pWin;
  for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
    FuncDef *pFunc = pWin->pFunc;
    FuncDef *pFunc = pWin->pWFunc;
    assert( pWin->regAccum );
    sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum);
    nArg = MAX(nArg, windowArgCount(pWin));
    if( pMWin->regStartRowid==0 ){
    if( pFunc->zName==nth_valueName
      if( pFunc->zName==nth_valueName || pFunc->zName==first_valueName ){
     || pFunc->zName==first_valueName
    ){
      sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp);
      sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp+1);
    }
        sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp);
        sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp+1);
      }

    if( (pFunc->funcFlags & SQLITE_FUNC_MINMAX) && pWin->csrApp ){
      assert( pWin->eStart!=TK_UNBOUNDED );
      sqlite3VdbeAddOp1(v, OP_ResetSorter, pWin->csrApp);
      sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp+1);
      if( (pFunc->funcFlags & SQLITE_FUNC_MINMAX) && pWin->csrApp ){
        assert( pWin->eStart!=TK_UNBOUNDED );
        sqlite3VdbeAddOp1(v, OP_ResetSorter, pWin->csrApp);
        sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp+1);
      }
    }
  }
  regArg = pParse->nMem+1;
  pParse->nMem += nArg;
  return regArg;
}


/*
** This function does the work of sqlite3WindowCodeStep() for all "ROWS"
/* 
** Return true if the current frame should be cached in the ephemeral table,
** even if there are no xInverse() calls required.
** window frame types except for "BETWEEN UNBOUNDED PRECEDING AND CURRENT
** ROW". Pseudo-code for each follows.
**
*/
** ROWS BETWEEN <expr1> PRECEDING AND <expr2> FOLLOWING
**
static int windowCacheFrame(Window *pMWin){
  Window *pWin;
**     ...
**       if( new partition ){
  if( pMWin->regStartRowid ) return 1;
**         Gosub flush_partition
**       }
**       Insert (record in eph-table)
**     sqlite3WhereEnd()
**     Gosub flush_partition
**  
**   flush_partition:
**     Once {
  for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
    FuncDef *pFunc = pWin->pWFunc;
**       OpenDup (iEphCsr -> csrStart)
**       OpenDup (iEphCsr -> csrEnd)
**     }
**     regStart = <expr1>                // PRECEDING expression
**     regEnd = <expr2>                  // FOLLOWING expression
**     if( regStart<0 || regEnd<0 ){ error! }
**     Rewind (csr,csrStart,csrEnd)      // if EOF goto flush_partition_done
**       Next(csrEnd)                    // if EOF skip Aggstep
**       Aggstep (csrEnd)
**       if( (regEnd--)<=0 ){
**         AggFinal (xValue)
    if( (pFunc->zName==nth_valueName)
     || (pFunc->zName==first_valueName)
**         Gosub addrGosub
**         Next(csr)                // if EOF goto flush_partition_done
**         if( (regStart--)<=0 ){
**           AggInverse (csrStart)
**           Next(csrStart)
**         }
**       }
**   flush_partition_done:
**     ResetSorter (csr)
**     Return
     || (pFunc->zName==leadName)
     || (pFunc->zName==lagName)
    ){
      return 1;
    }
  }
  return 0;
**
** ROWS BETWEEN <expr> PRECEDING    AND CURRENT ROW
** ROWS BETWEEN CURRENT ROW         AND <expr> FOLLOWING
}

** ROWS BETWEEN UNBOUNDED PRECEDING AND <expr> FOLLOWING
**
**   These are similar to the above. For "CURRENT ROW", intialize the
**   register to 0. For "UNBOUNDED PRECEDING" to infinity.
/*
** regOld and regNew are each the first register in an array of size
** pOrderBy->nExpr. This function generates code to compare the two
** arrays of registers using the collation sequences and other comparison
**
** ROWS BETWEEN <expr> PRECEDING    AND UNBOUNDED FOLLOWING
** ROWS BETWEEN CURRENT ROW         AND UNBOUNDED FOLLOWING
**
**     Rewind (csr,csrStart,csrEnd)    // if EOF goto flush_partition_done
**     while( 1 ){
**       Next(csrEnd)                  // Exit while(1) at EOF
**       Aggstep (csrEnd)
**     }
** parameters specified by pOrderBy. 
**     while( 1 ){
**       AggFinal (xValue)
**       Gosub addrGosub
**       Next(csr)                     // if EOF goto flush_partition_done
**       if( (regStart--)<=0 ){
**         AggInverse (csrStart)
**         Next(csrStart)
**       }
**     }
**
** If the two arrays are not equal, the contents of regNew is copied to 
** regOld and control falls through. Otherwise, if the contents of the arrays
**   For the "CURRENT ROW AND UNBOUNDED FOLLOWING" case, the final if() 
** are equal, an OP_Goto is executed. The address of the OP_Goto is returned.
**   condition is always true (as if regStart were initialized to 0).
**
** RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
** 
**   This is the only RANGE case handled by this routine. It modifies the
**   second while( 1 ) loop in "ROWS BETWEEN CURRENT ... UNBOUNDED..." to
**   be:
*/
static void windowIfNewPeer(
  Parse *pParse,
  ExprList *pOrderBy,
  int regNew,                     /* First in array of new values */
  int regOld,                     /* First in array of old values */
  int addr                        /* Jump here */
**
**     while( 1 ){
){
**       AggFinal (xValue)
**       while( 1 ){
**         regPeer++
**         Gosub addrGosub
  Vdbe *v = sqlite3GetVdbe(pParse);
  if( pOrderBy ){
    int nVal = pOrderBy->nExpr;
    KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pOrderBy, 0, 0);
    sqlite3VdbeAddOp3(v, OP_Compare, regOld, regNew, nVal);
    sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO);
    sqlite3VdbeAddOp3(v, OP_Jump, 
      sqlite3VdbeCurrentAddr(v)+1, addr, sqlite3VdbeCurrentAddr(v)+1
**         Next(csr)                     // if EOF goto flush_partition_done
**         if( new peer ) break;
**       }
    );
    VdbeCoverageEqNe(v);
    sqlite3VdbeAddOp3(v, OP_Copy, regNew, regOld, nVal-1);
  }else{
**       while( (regPeer--)>0 ){
**         AggInverse (csrStart)
    sqlite3VdbeAddOp2(v, OP_Goto, 0, addr);
  }
}

**         Next(csrStart)
**       }
**     }
**
/*
** This function is called as part of generating VM programs for RANGE
** offset PRECEDING/FOLLOWING frame boundaries. Assuming "ASC" order for
** the ORDER BY term in the window, and that argument op is OP_Ge, it generates
** code equivalent to:
** ROWS BETWEEN <expr> FOLLOWING    AND <expr> FOLLOWING
**
**   regEnd = regEnd - regStart
**   Rewind (csr,csrStart,csrEnd)   // if EOF goto flush_partition_done
**     Aggstep (csrEnd)
**     Next(csrEnd)                 // if EOF fall-through
**     if( (regEnd--)<=0 ){
**   if( csr1.peerVal + regVal >= csr2.peerVal ) goto lbl;
**       if( (regStart--)<=0 ){
**         AggFinal (xValue)
**         Gosub addrGosub
**         Next(csr)              // if EOF goto flush_partition_done
**       }
**       AggInverse (csrStart)
**       Next (csrStart)
**     }
**
** ROWS BETWEEN <expr> PRECEDING    AND <expr> PRECEDING
** The value of parameter op may also be OP_Gt or OP_Le. In these cases the
** operator in the above pseudo-code is replaced with ">" or "<=", respectively.
**
**   Replace the bit after "Rewind" in the above with:
** If the sort-order for the ORDER BY term in the window is DESC, then the
** comparison is reversed. Instead of adding regVal to csr1.peerVal, it is
** 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( (regEnd--)<=0 ){
**   if( csr1.peerVal - regVal <= csr2.peerVal ) goto lbl;
**       AggStep (csrEnd)
**       Next (csrEnd)
**     }
**     AggFinal (xValue)
**     Gosub addrGosub
**     Next(csr)                  // if EOF goto flush_partition_done
**     if( (regStart--)<=0 ){
**       AggInverse (csr2)
**       Next (csr2)
**     }
**
** A special type of arithmetic is used such that if csr1.peerVal is not
** a numeric type (real or integer), then the result of the addition
** or subtraction is a a copy of csr1.peerVal.
*/
static void windowCodeRowExprStep(
static void windowCodeRangeTest(
  Parse *pParse, 
  Select *p,
  WhereInfo *pWInfo,
  int regGosub, 
  int addrGosub
  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 */
){
  Window *pMWin = p->pWin;
  Parse *pParse = p->pParse;
  Vdbe *v = sqlite3GetVdbe(pParse);
  int regFlushPart;               /* Register for "Gosub flush_partition" */
  int lblFlushPart;               /* Label for "Gosub flush_partition" */
  int lblFlushDone;               /* Label for "Gosub flush_partition_done" */

  int regArg;
  int addr;
  int csrStart = pParse->nTab++;
  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 csrEnd = pParse->nTab++;
  int regStart;                    /* Value of <expr> PRECEDING */
  int regEnd;                      /* Value of <expr> FOLLOWING */
  int addrGoto;
  int arith = OP_Add;                       /* OP_Add or OP_Subtract */
  int addrGe;                               /* Jump destination */
  int addrTop;
  int addrIfPos1 = 0;
  int addrIfPos2 = 0;
  int regSize = 0;

  assert( pMWin->eStart==TK_PRECEDING 
       || pMWin->eStart==TK_CURRENT 
       || pMWin->eStart==TK_FOLLOWING 
       || pMWin->eStart==TK_UNBOUNDED 
  );
  assert( pMWin->eEnd==TK_FOLLOWING 
       || pMWin->eEnd==TK_CURRENT 
       || pMWin->eEnd==TK_UNBOUNDED 
       || pMWin->eEnd==TK_PRECEDING 
  );

  /* Allocate register and label for the "flush_partition" sub-routine. */
  regFlushPart = ++pParse->nMem;
  lblFlushPart = sqlite3VdbeMakeLabel(v);
  lblFlushDone = sqlite3VdbeMakeLabel(v);

  int addrDone = sqlite3VdbeMakeLabel(pParse);   /* Address past OP_Ge */
  CollSeq *pColl;
  regStart = ++pParse->nMem;
  regEnd = ++pParse->nMem;

  windowPartitionCache(pParse, p, pWInfo, regFlushPart, lblFlushPart, &regSize);

  addrGoto = sqlite3VdbeAddOp0(v, OP_Goto);
  /* Read the peer-value from each cursor into a register */
  windowReadPeerValues(p, csr1, reg1);
  windowReadPeerValues(p, csr2, reg2);

  /* Start of "flush_partition" */
  sqlite3VdbeResolveLabel(v, lblFlushPart);
  sqlite3VdbeAddOp2(v, OP_Once, 0, sqlite3VdbeCurrentAddr(v)+3);
  VdbeCoverage(v);
  VdbeComment((v, "Flush_partition subroutine"));
  sqlite3VdbeAddOp2(v, OP_OpenDup, csrStart, pMWin->iEphCsr);
  sqlite3VdbeAddOp2(v, OP_OpenDup, csrEnd, pMWin->iEphCsr);

  /* If either regStart or regEnd are not non-negative integers, throw 
  assert( op==OP_Ge || op==OP_Gt || op==OP_Le );
  assert( pOrderBy && pOrderBy->nExpr==1 );
  if( pOrderBy->a[0].fg.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;
  ** an exception.  */
  if( pMWin->pStart ){
    sqlite3ExprCode(pParse, pMWin->pStart, regStart);
    windowCheckIntValue(pParse, regStart, 0);
  }
    }
  if( pMWin->pEnd ){
    sqlite3ExprCode(pParse, pMWin->pEnd, regEnd);
    windowCheckIntValue(pParse, regEnd, 1);
    arith = OP_Subtract;
  }

  /* If this is "ROWS <expr1> FOLLOWING AND ROWS <expr2> FOLLOWING", do:
  **
  **   if( regEnd<regStart ){
  VdbeModuleComment((v, "CodeRangeTest: if( R%d %s R%d %s R%d ) goto lbl",
  **     // The frame always consists of 0 rows
  **     regStart = regSize;
      reg1, (arith==OP_Add ? "+" : "-"), regVal,
  **   }
  **   regEnd = regEnd - regStart;
  */
  if( pMWin->pEnd && pMWin->eStart==TK_FOLLOWING ){
    assert( pMWin->pStart!=0 );
    assert( pMWin->eEnd==TK_FOLLOWING );
    sqlite3VdbeAddOp3(v, OP_Ge, regStart, sqlite3VdbeCurrentAddr(v)+2, regEnd);
    VdbeCoverageNeverNull(v);
    sqlite3VdbeAddOp2(v, OP_Copy, regSize, regStart);
    sqlite3VdbeAddOp3(v, OP_Subtract, regStart, regEnd, regEnd);
  }

      ((op==OP_Ge) ? ">=" : (op==OP_Le) ? "<=" : (op==OP_Gt) ? ">" : "<"), reg2
  if( pMWin->pStart && pMWin->eEnd==TK_PRECEDING ){
    assert( pMWin->pEnd!=0 );
  ));
    assert( pMWin->eStart==TK_PRECEDING );
    sqlite3VdbeAddOp3(v, OP_Le, regStart, sqlite3VdbeCurrentAddr(v)+3, regEnd);
    VdbeCoverageNeverNull(v);
    sqlite3VdbeAddOp2(v, OP_Copy, regSize, regStart);
    sqlite3VdbeAddOp2(v, OP_Copy, regSize, regEnd);
  }


  /* If the BIGNULL flag is set for the ORDER BY, then it is required to 
  /* Initialize the accumulator register for each window function to NULL */
  regArg = windowInitAccum(pParse, pMWin);

  ** consider NULL values to be larger than all other values, instead of 
  sqlite3VdbeAddOp2(v, OP_Rewind, pMWin->iEphCsr, lblFlushDone);
  VdbeCoverage(v);
  sqlite3VdbeAddOp2(v, OP_Rewind, csrStart, lblFlushDone);
  VdbeCoverageNeverTaken(v);
  sqlite3VdbeChangeP5(v, 1);
  sqlite3VdbeAddOp2(v, OP_Rewind, csrEnd, lblFlushDone);
  VdbeCoverageNeverTaken(v);
  sqlite3VdbeChangeP5(v, 1);

  ** the usual smaller. The VDBE opcodes OP_Ge and so on do not handle this
  /* Invoke AggStep function for each window function using the row that
  ** csrEnd currently points to. Or, if csrEnd is already at EOF,
  ** do nothing.  */
  ** (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:
  **
  addrTop = sqlite3VdbeCurrentAddr(v);
  if( pMWin->eEnd==TK_PRECEDING ){
  **   if( reg1 IS NULL ){
    addrIfPos1 = sqlite3VdbeAddOp3(v, OP_IfPos, regEnd, 0 , 1);
    VdbeCoverage(v);
  }
  sqlite3VdbeAddOp2(v, OP_Next, csrEnd, sqlite3VdbeCurrentAddr(v)+2);
  VdbeCoverage(v);
  addr = sqlite3VdbeAddOp0(v, OP_Goto);
  **     if( op==OP_Ge ) goto lbl;
  windowAggStep(pParse, pMWin, csrEnd, 0, regArg, regSize);
  if( pMWin->eEnd==TK_UNBOUNDED ){
  **     if( op==OP_Gt && reg2 IS NOT NULL ) goto lbl;
    sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop);
    sqlite3VdbeJumpHere(v, addr);
    addrTop = sqlite3VdbeCurrentAddr(v);
  }else{
  **     if( op==OP_Le && reg2 IS NULL ) goto lbl;
  **   }else if( reg2 IS NULL ){
    sqlite3VdbeJumpHere(v, addr);
    if( pMWin->eEnd==TK_PRECEDING ){
  **     if( op==OP_Le ) goto lbl;
      sqlite3VdbeJumpHere(v, addrIfPos1);
    }
  }

  if( pMWin->eEnd==TK_FOLLOWING ){
    addrIfPos1 = sqlite3VdbeAddOp3(v, OP_IfPos, regEnd, 0 , 1);
  **   }
  **
  ** Additionally, if either reg1 or reg2 are NULL but the jump to lbl is 
  ** not taken, control jumps over the comparison operator coded below this
  ** block.  */
  if( pOrderBy->a[0].fg.sortFlags & KEYINFO_ORDER_BIGNULL ){
    /* This block runs if reg1 contains a NULL. */
    int addr = sqlite3VdbeAddOp1(v, OP_NotNull, reg1); VdbeCoverage(v);
    switch( op ){
      case OP_Ge: 
    VdbeCoverage(v);
  }
  if( pMWin->eStart==TK_FOLLOWING ){
    addrIfPos2 = sqlite3VdbeAddOp3(v, OP_IfPos, regStart, 0 , 1);
    VdbeCoverage(v);
  }
  windowAggFinal(pParse, pMWin, 0);
  windowReturnOneRow(pParse, pMWin, regGosub, addrGosub);
  sqlite3VdbeAddOp2(v, OP_Next, pMWin->iEphCsr, sqlite3VdbeCurrentAddr(v)+2);
  VdbeCoverage(v);
  sqlite3VdbeAddOp2(v, OP_Goto, 0, lblFlushDone);
        sqlite3VdbeAddOp2(v, OP_Goto, 0, lbl); 
  if( pMWin->eStart==TK_FOLLOWING ){
    sqlite3VdbeJumpHere(v, addrIfPos2);
  }

        break;
  if( pMWin->eStart==TK_CURRENT 
   || pMWin->eStart==TK_PRECEDING 
   || pMWin->eStart==TK_FOLLOWING 
  ){
    int lblSkipInverse = sqlite3VdbeMakeLabel(v);;
      case OP_Gt: 
    if( pMWin->eStart==TK_PRECEDING ){
      sqlite3VdbeAddOp3(v, OP_IfPos, regStart, lblSkipInverse, 1);
      VdbeCoverage(v);
    }
    if( pMWin->eStart==TK_FOLLOWING ){
      sqlite3VdbeAddOp2(v, OP_Next, csrStart, sqlite3VdbeCurrentAddr(v)+2);
      VdbeCoverage(v);
        sqlite3VdbeAddOp2(v, OP_NotNull, reg2, lbl); 
        VdbeCoverage(v); 
      sqlite3VdbeAddOp2(v, OP_Goto, 0, lblSkipInverse);
    }else{
      sqlite3VdbeAddOp2(v, OP_Next, csrStart, sqlite3VdbeCurrentAddr(v)+1);
      VdbeCoverageAlwaysTaken(v);
        break;
      case OP_Le: 
        sqlite3VdbeAddOp2(v, OP_IsNull, reg2, lbl); 
        VdbeCoverage(v); 
        break;
      default: assert( op==OP_Lt ); /* no-op */ break;
    }
    windowAggStep(pParse, pMWin, csrStart, 1, regArg, regSize);
    sqlite3VdbeResolveLabel(v, lblSkipInverse);
  }
    sqlite3VdbeAddOp2(v, OP_Goto, 0, addrDone);

  if( pMWin->eEnd==TK_FOLLOWING ){
    sqlite3VdbeJumpHere(v, addrIfPos1);
    /* This block runs if reg1 is not NULL, but reg2 is. */
    sqlite3VdbeJumpHere(v, addr);
    sqlite3VdbeAddOp2(v, OP_IsNull, reg2,
                      (op==OP_Gt || op==OP_Ge) ? addrDone : lbl);
    VdbeCoverage(v);
  }
  sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop);

  /* flush_partition_done: */
  /* Register reg1 currently contains csr1.peerVal (the peer-value from csr1).
  sqlite3VdbeResolveLabel(v, lblFlushDone);
  sqlite3VdbeAddOp1(v, OP_ResetSorter, pMWin->iEphCsr);
  sqlite3VdbeAddOp1(v, OP_Return, regFlushPart);
  VdbeComment((v, "end flush_partition subroutine"));

  ** This block adds (or subtracts for DESC) the numeric value in regVal
  /* Jump to here to skip over flush_partition */
  sqlite3VdbeJumpHere(v, addrGoto);
}

  ** from it. Or, if reg1 is not numeric (it is a NULL, a text value or a blob),
/*
** This function does the work of sqlite3WindowCodeStep() for cases that
** would normally be handled by windowCodeDefaultStep() when there are
** one or more built-in window-functions that require the entire partition
** to be cached in a temp table before any rows can be returned. Additionally.
** "RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING" is always handled by
** this function.
**
  ** then leave reg1 as it is. In pseudo-code, this is implemented as:
  **
** Pseudo-code corresponding to the VM code generated by this function
** for each type of window follows.
**
** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
**
**   flush_partition:
**     Once {
**       OpenDup (iEphCsr -> csrLead)
**     }
  **   if( reg1>='' ) goto addrGe;
**     Integer ctr 0
**     foreach row (csrLead){
**       if( new peer ){
**         AggFinal (xValue)
**         for(i=0; i<ctr; i++){
**           Gosub addrGosub
**           Next iEphCsr
**         }
**         Integer ctr 0
**       }
  **   reg1 = reg1 +/- regVal
**       AggStep (csrLead)
**       Incr ctr
**     }
**
**     AggFinal (xFinalize)
**     for(i=0; i<ctr; i++){
**       Gosub addrGosub
**       Next iEphCsr
**     }
  **   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);
**
**     ResetSorter (csr)
**     Return
  pColl = sqlite3ExprNNCollSeq(pParse, pOrderBy->a[0].pExpr);
  sqlite3VdbeAppendP4(v, (void*)pColl, P4_COLLSEQ);
  sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
**
** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
**
**   As above, except that the "if( new peer )" branch is always taken.
**
** RANGE BETWEEN CURRENT ROW AND CURRENT ROW 
**
**   As above, except that each of the for() loops becomes:
**
**         for(i=0; i<ctr; i++){
**           Gosub addrGosub
**           AggInverse (iEphCsr)
**           Next iEphCsr
**         }
**
** RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
**
**   flush_partition:
**     Once {
**       OpenDup (iEphCsr -> csrLead)
**     }
**     foreach row (csrLead) {
**       AggStep (csrLead)
**     }
**     foreach row (iEphCsr) {
**       Gosub addrGosub
**     }
  sqlite3VdbeResolveLabel(v, addrDone);

** 
** RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
**
**   flush_partition:
**     Once {
**       OpenDup (iEphCsr -> csrLead)
**     }
**     foreach row (csrLead){
**       AggStep (csrLead)
  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);
  sqlite3ReleaseTempReg(pParse, reg2);

  VdbeModuleComment((v, "CodeRangeTest: end"));
}

**     }
**     Rewind (csrLead)
**     Integer ctr 0
**     foreach row (csrLead){
**       if( new peer ){
/*
** Helper function for sqlite3WindowCodeStep(). Each call to this function
** generates VM code for a single RETURN_ROW, AGGSTEP or AGGINVERSE 
** operation. Refer to the header comment for sqlite3WindowCodeStep() for
**         AggFinal (xValue)
**         for(i=0; i<ctr; i++){
**           Gosub addrGosub
**           AggInverse (iEphCsr)
**           Next iEphCsr
**         }
**         Integer ctr 0
**       }
**       Incr ctr
**     }
** details.
**
**     AggFinal (xFinalize)
**     for(i=0; i<ctr; i++){
**       Gosub addrGosub
**       Next iEphCsr
**     }
**
**     ResetSorter (csr)
**     Return
*/
static void windowCodeCacheStep(
static int windowCodeOp(
  Parse *pParse, 
  Select *p,
 WindowCodeArg *p,                /* Context object */
  WhereInfo *pWInfo,
  int regGosub, 
 int op,                          /* WINDOW_RETURN_ROW, AGGSTEP or AGGINVERSE */
 int regCountdown,                /* Register for OP_IfPos countdown */
  int addrGosub
 int jumpOnEof                    /* Jump here if stepped cursor reaches EOF */
){
  int csr, reg;
  Parse *pParse = p->pParse;
  Window *pMWin = p->pWin;
  Window *pMWin = p->pMWin;
  Vdbe *v = sqlite3GetVdbe(pParse);
  int k;
  int addr;
  ExprList *pPart = pMWin->pPartition;
  ExprList *pOrderBy = pMWin->pOrderBy;
  int nPeer = pOrderBy ? pOrderBy->nExpr : 0;
  int regNewPeer;

  int ret = 0;
  Vdbe *v = p->pVdbe;
  int addrGoto;                   /* Address of Goto used to jump flush_par.. */
  int addrNext;                   /* Jump here for next iteration of loop */
  int regFlushPart;
  int lblFlushPart;
  int csrLead;
  int regCtr;
  int regArg;                     /* Register array to martial function args */
  int addrContinue = 0;
  int bPeer = (pMWin->eFrmType!=TK_ROWS);

  int regSize;
  int lblEmpty;
  int bReverse = pMWin->pOrderBy && pMWin->eStart==TK_CURRENT 
  int lblDone = sqlite3VdbeMakeLabel(pParse);
  int addrNextRange = 0;
          && pMWin->eEnd==TK_UNBOUNDED;

  /* Special case - WINDOW_AGGINVERSE is always a no-op if the frame
  assert( (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_CURRENT) 
       || (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_UNBOUNDED) 
  ** starts with UNBOUNDED PRECEDING. */
  if( op==WINDOW_AGGINVERSE && pMWin->eStart==TK_UNBOUNDED ){
       || (pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_CURRENT) 
       || (pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_UNBOUNDED) 
  );

    assert( regCountdown==0 && jumpOnEof==0 );
  lblEmpty = sqlite3VdbeMakeLabel(v);
  regNewPeer = pParse->nMem+1;
    return 0;
  pParse->nMem += nPeer;

  }
  /* Allocate register and label for the "flush_partition" sub-routine. */
  regFlushPart = ++pParse->nMem;
  lblFlushPart = sqlite3VdbeMakeLabel(v);

  csrLead = pParse->nTab++;
  regCtr = ++pParse->nMem;

  if( regCountdown>0 ){
    if( pMWin->eFrmType==TK_RANGE ){
  windowPartitionCache(pParse, p, pWInfo, regFlushPart, lblFlushPart, &regSize);
  addrGoto = sqlite3VdbeAddOp0(v, OP_Goto);

      addrNextRange = sqlite3VdbeCurrentAddr(v);
      assert( op==WINDOW_AGGINVERSE || op==WINDOW_AGGSTEP );
  /* Start of "flush_partition" */
  sqlite3VdbeResolveLabel(v, lblFlushPart);
  sqlite3VdbeAddOp2(v, OP_Once, 0, sqlite3VdbeCurrentAddr(v)+2);
  VdbeCoverage(v);
  sqlite3VdbeAddOp2(v, OP_OpenDup, csrLead, pMWin->iEphCsr);

      if( op==WINDOW_AGGINVERSE ){
  /* Initialize the accumulator register for each window function to NULL */
  regArg = windowInitAccum(pParse, pMWin);

  sqlite3VdbeAddOp2(v, OP_Integer, 0, regCtr);
  sqlite3VdbeAddOp2(v, OP_Rewind, csrLead, lblEmpty);
  VdbeCoverage(v);
  sqlite3VdbeAddOp2(v, OP_Rewind, pMWin->iEphCsr, lblEmpty);
  VdbeCoverageNeverTaken(v);

  if( bReverse ){
        if( pMWin->eStart==TK_FOLLOWING ){
          windowCodeRangeTest(
              p, OP_Le, p->current.csr, regCountdown, p->start.csr, lblDone
          );
        }else{
          windowCodeRangeTest(
              p, OP_Ge, p->start.csr, regCountdown, p->current.csr, lblDone
          );
        }
      }else{
    int addr2 = sqlite3VdbeCurrentAddr(v);
    windowAggStep(pParse, pMWin, csrLead, 0, regArg, regSize);
    sqlite3VdbeAddOp2(v, OP_Next, csrLead, addr2);
    VdbeCoverage(v);
        windowCodeRangeTest(
            p, OP_Gt, p->end.csr, regCountdown, p->current.csr, lblDone
        );
    sqlite3VdbeAddOp2(v, OP_Rewind, csrLead, lblEmpty);
    VdbeCoverageNeverTaken(v);
  }
      }
  addrNext = sqlite3VdbeCurrentAddr(v);

    }else{
  if( pOrderBy && (pMWin->eEnd==TK_CURRENT || pMWin->eStart==TK_CURRENT) ){
    int bCurrent = (pMWin->eStart==TK_CURRENT);
    int addrJump = 0;             /* Address of OP_Jump below */
    if( pMWin->eType==TK_RANGE ){
      int iOff = pMWin->nBufferCol + (pPart ? pPart->nExpr : 0);
      int regPeer = pMWin->regPart + (pPart ? pPart->nExpr : 0);
      KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pOrderBy, 0, 0);
      for(k=0; k<nPeer; k++){
        sqlite3VdbeAddOp3(v, OP_Column, csrLead, iOff+k, regNewPeer+k);
      }
      addr = sqlite3VdbeAddOp3(v, OP_Compare, regNewPeer, regPeer, nPeer);
      sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO);
      addrJump = sqlite3VdbeAddOp3(v, OP_Jump, addr+2, 0, addr+2);
      sqlite3VdbeAddOp3(v, OP_IfPos, regCountdown, lblDone, 1);
      VdbeCoverage(v);
      sqlite3VdbeAddOp3(v, OP_Copy, regNewPeer, regPeer, nPeer-1);
    }

  }
    windowReturnRows(pParse, pMWin, regCtr, regGosub, addrGosub, 
        (bCurrent ? regArg : 0), (bCurrent ? regSize : 0)
    );
    if( addrJump ) sqlite3VdbeJumpHere(v, addrJump);
  }


  if( op==WINDOW_RETURN_ROW && pMWin->regStartRowid==0 ){
    windowAggFinal(p, 0);
  }
  if( bReverse==0 ){
  addrContinue = sqlite3VdbeCurrentAddr(v);
    windowAggStep(pParse, pMWin, csrLead, 0, regArg, regSize);
  }
  sqlite3VdbeAddOp2(v, OP_AddImm, regCtr, 1);
  sqlite3VdbeAddOp2(v, OP_Next, csrLead, addrNext);
  VdbeCoverage(v);


  /* If this is a (RANGE BETWEEN a FOLLOWING AND b FOLLOWING) or
  ** (RANGE BETWEEN b PRECEDING AND a PRECEDING) frame, ensure the 
  ** start cursor does not advance past the end cursor within the 
  ** temporary table. It otherwise might, if (a>b). Also ensure that,
  ** if the input cursor is still finding new rows, that the end
  ** cursor does not go past it to EOF. */
  if( pMWin->eStart==pMWin->eEnd && regCountdown
   && pMWin->eFrmType==TK_RANGE
  ){
    int regRowid1 = sqlite3GetTempReg(pParse);
    int regRowid2 = sqlite3GetTempReg(pParse);
    if( op==WINDOW_AGGINVERSE ){
      sqlite3VdbeAddOp2(v, OP_Rowid, p->start.csr, regRowid1);
      sqlite3VdbeAddOp2(v, OP_Rowid, p->end.csr, regRowid2);
      sqlite3VdbeAddOp3(v, OP_Ge, regRowid2, lblDone, regRowid1);
      VdbeCoverage(v);
    }else if( p->regRowid ){
  windowReturnRows(pParse, pMWin, regCtr, regGosub, addrGosub, 0, 0);

      sqlite3VdbeAddOp2(v, OP_Rowid, p->end.csr, regRowid1);
  sqlite3VdbeResolveLabel(v, lblEmpty);
  sqlite3VdbeAddOp1(v, OP_ResetSorter, pMWin->iEphCsr);
  sqlite3VdbeAddOp1(v, OP_Return, regFlushPart);

      sqlite3VdbeAddOp3(v, OP_Ge, p->regRowid, lblDone, regRowid1);
      VdbeCoverageNeverNull(v);
  /* Jump to here to skip over flush_partition */
  sqlite3VdbeJumpHere(v, addrGoto);
}


    }
    sqlite3ReleaseTempReg(pParse, regRowid1);
    sqlite3ReleaseTempReg(pParse, regRowid2);
    assert( pMWin->eStart==TK_PRECEDING || pMWin->eStart==TK_FOLLOWING );
  }
/*
** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
**
**   ...
**     if( new partition ){
**       AggFinal (xFinalize)
**       Gosub addrGosub
**       ResetSorter eph-table
**     }
**     else if( new peer ){
**       AggFinal (xValue)
**       Gosub addrGosub
**       ResetSorter eph-table
**     }
**     AggStep
**     Insert (record into eph-table)
**   sqlite3WhereEnd()
**   AggFinal (xFinalize)
**   Gosub addrGosub
**
** RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
**
**   As above, except take no action for a "new peer". Invoke
**   the sub-routine once only for each partition.
**
** RANGE BETWEEN CURRENT ROW AND CURRENT ROW

  switch( op ){
**
**   As above, except that the "new peer" condition is handled in the
**   same way as "new partition" (so there is no "else if" block).
**
** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
** 
**   As above, except assume every row is a "new peer".
*/
static void windowCodeDefaultStep(
  Parse *pParse, 
    case WINDOW_RETURN_ROW:
  Select *p,
  WhereInfo *pWInfo,
  int regGosub, 
      csr = p->current.csr;
      reg = p->current.reg;
  int addrGosub
){
  Window *pMWin = p->pWin;
      windowReturnOneRow(p);
  Vdbe *v = sqlite3GetVdbe(pParse);
  int k;
  int iSubCsr = p->pSrc->a[0].iCursor;
  int nSub = p->pSrc->a[0].pTab->nCol;
  int reg = pParse->nMem+1;
      break;

    case WINDOW_AGGINVERSE:
      csr = p->start.csr;
      reg = p->start.reg;
  int regRecord = reg+nSub;
  int regRowid = regRecord+1;
  int addr;
  ExprList *pPart = pMWin->pPartition;
  ExprList *pOrderBy = pMWin->pOrderBy;

  assert( pMWin->eType==TK_RANGE 
      if( pMWin->regStartRowid ){
        assert( pMWin->regEndRowid );
      || (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_CURRENT)
  );

        sqlite3VdbeAddOp2(v, OP_AddImm, pMWin->regStartRowid, 1);
  assert( (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_CURRENT)
       || (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_UNBOUNDED)
       || (pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_CURRENT)
       || (pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_UNBOUNDED && !pOrderBy)
  );

  if( pMWin->eEnd==TK_UNBOUNDED ){
      }else{
        windowAggStep(p, pMWin, csr, 1, p->regArg);
    pOrderBy = 0;
  }
      }
      break;

  pParse->nMem += nSub + 2;

    default:
  /* Load the individual column values of the row returned by
  ** the sub-select into an array of registers. */
  for(k=0; k<nSub; k++){
    sqlite3VdbeAddOp3(v, OP_Column, iSubCsr, k, reg+k);
  }

      assert( op==WINDOW_AGGSTEP );
  /* Check if this is the start of a new partition or peer group. */
  if( pPart || pOrderBy ){
    int nPart = (pPart ? pPart->nExpr : 0);
    int addrGoto = 0;
      csr = p->end.csr;
    int addrJump = 0;
    int nPeer = (pOrderBy ? pOrderBy->nExpr : 0);

    if( pPart ){
      int regNewPart = reg + pMWin->nBufferCol;
      reg = p->end.reg;
      if( pMWin->regStartRowid ){
        assert( pMWin->regEndRowid );
      KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pPart, 0, 0);
      addr = sqlite3VdbeAddOp3(v, OP_Compare, regNewPart, pMWin->regPart,nPart);
      sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO);
      addrJump = sqlite3VdbeAddOp3(v, OP_Jump, addr+2, 0, addr+2);
        sqlite3VdbeAddOp2(v, OP_AddImm, pMWin->regEndRowid, 1);
      VdbeCoverageEqNe(v);
      windowAggFinal(pParse, pMWin, 1);
      }else{
        windowAggStep(p, pMWin, csr, 0, p->regArg);
      if( pOrderBy ){
        addrGoto = sqlite3VdbeAddOp0(v, OP_Goto);
      }
      break;
    }
  }

    if( pOrderBy ){
  if( op==p->eDelete ){
      int regNewPeer = reg + pMWin->nBufferCol + nPart;
      int regPeer = pMWin->regPart + nPart;

    sqlite3VdbeAddOp1(v, OP_Delete, csr);
    sqlite3VdbeChangeP5(v, OPFLAG_SAVEPOSITION);
  }
      if( addrJump ) sqlite3VdbeJumpHere(v, addrJump);
      if( pMWin->eType==TK_RANGE ){
        KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pOrderBy, 0, 0);
        addr = sqlite3VdbeAddOp3(v, OP_Compare, regNewPeer, regPeer, nPeer);
        sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO);
        addrJump = sqlite3VdbeAddOp3(v, OP_Jump, addr+2, 0, addr+2);
        VdbeCoverage(v);
      }else{
        addrJump = 0;
      }

      windowAggFinal(pParse, pMWin, pMWin->eStart==TK_CURRENT);
      if( addrGoto ) sqlite3VdbeJumpHere(v, addrGoto);
    }

    sqlite3VdbeAddOp2(v, OP_Rewind, pMWin->iEphCsr,sqlite3VdbeCurrentAddr(v)+3);
  if( jumpOnEof ){
    sqlite3VdbeAddOp2(v, OP_Next, csr, sqlite3VdbeCurrentAddr(v)+2);
    VdbeCoverage(v);
    sqlite3VdbeAddOp2(v, OP_Gosub, regGosub, addrGosub);
    sqlite3VdbeAddOp2(v, OP_Next, pMWin->iEphCsr, sqlite3VdbeCurrentAddr(v)-1);
    ret = sqlite3VdbeAddOp0(v, OP_Goto);
  }else{
    sqlite3VdbeAddOp2(v, OP_Next, csr, sqlite3VdbeCurrentAddr(v)+1+bPeer);
    VdbeCoverage(v);

    if( bPeer ){
    sqlite3VdbeAddOp1(v, OP_ResetSorter, pMWin->iEphCsr);
    sqlite3VdbeAddOp3(
      sqlite3VdbeAddOp2(v, OP_Goto, 0, lblDone);
        v, OP_Copy, reg+pMWin->nBufferCol, pMWin->regPart, nPart+nPeer-1
    );

    }
    if( addrJump ) sqlite3VdbeJumpHere(v, addrJump);
  }

  if( bPeer ){
    int nReg = (pMWin->pOrderBy ? pMWin->pOrderBy->nExpr : 0);
    int regTmp = (nReg ? sqlite3GetTempRange(pParse, nReg) : 0);
  /* Invoke step function for window functions */
  windowAggStep(pParse, pMWin, -1, 0, reg, 0);

  /* Buffer the current row in the ephemeral table. */
  if( pMWin->nBufferCol>0 ){
    windowReadPeerValues(p, csr, regTmp);
    windowIfNewPeer(pParse, pMWin->pOrderBy, regTmp, reg, addrContinue);
    sqlite3ReleaseTempRange(pParse, regTmp, nReg);
  }

  if( addrNextRange ){
    sqlite3VdbeAddOp3(v, OP_MakeRecord, reg, pMWin->nBufferCol, regRecord);
  }else{
    sqlite3VdbeAddOp2(v, OP_Blob, 0, regRecord);
    sqlite3VdbeAddOp2(v, OP_Goto, 0, addrNextRange);
    sqlite3VdbeAppendP4(v, (void*)"", 0);
  }
  sqlite3VdbeAddOp2(v, OP_NewRowid, pMWin->iEphCsr, regRowid);
  sqlite3VdbeResolveLabel(v, lblDone);
  sqlite3VdbeAddOp3(v, OP_Insert, pMWin->iEphCsr, regRecord, regRowid);

  return ret;
  /* End the database scan loop. */
  sqlite3WhereEnd(pWInfo);

}
  windowAggFinal(pParse, pMWin, 1);
  sqlite3VdbeAddOp2(v, OP_Rewind, pMWin->iEphCsr,sqlite3VdbeCurrentAddr(v)+3);
  VdbeCoverage(v);
  sqlite3VdbeAddOp2(v, OP_Gosub, regGosub, addrGosub);
  sqlite3VdbeAddOp2(v, OP_Next, pMWin->iEphCsr, sqlite3VdbeCurrentAddr(v)-1);
  VdbeCoverage(v);
}


/*
** Allocate and return a duplicate of the Window object indicated by the
** third argument. Set the Window.pOwner field of the new object to
** pOwner.
*/
Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p){
  Window *pNew = 0;
  if( ALWAYS(p) ){
    pNew = sqlite3DbMallocZero(db, sizeof(Window));
    if( pNew ){
      pNew->zName = sqlite3DbStrDup(db, p->zName);
      pNew->zBase = sqlite3DbStrDup(db, p->zBase);
      pNew->pFilter = sqlite3ExprDup(db, p->pFilter, 0);
      pNew->pFunc = p->pFunc;
      pNew->pWFunc = p->pWFunc;
      pNew->pPartition = sqlite3ExprListDup(db, p->pPartition, 0);
      pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, 0);
      pNew->eType = p->eType;
      pNew->eFrmType = p->eFrmType;
      pNew->eEnd = p->eEnd;
      pNew->eStart = p->eStart;
      pNew->eExclude = p->eExclude;
      pNew->regResult = p->regResult;
      pNew->regAccum = p->regAccum;
      pNew->iArgCol = p->iArgCol;
      pNew->iEphCsr = p->iEphCsr;
      pNew->bExprArgs = p->bExprArgs;
      pNew->pStart = sqlite3ExprDup(db, p->pStart, 0);
      pNew->pEnd = sqlite3ExprDup(db, p->pEnd, 0);
      pNew->pOwner = pOwner;
      pNew->bImplicitFrame = p->bImplicitFrame;
    }
  }
  return pNew;
}

/*
** Return a copy of the linked list of Window objects passed as the
2160
2161
2162
2163
2164
2165
2166




















2167
2168
2169
2170
2171
2172
2173











































































































































































































































































































































2174
2175
2176
2177
2178
2179
2180
2181
2182












































2183
2184
2185
2186










2187
2188
2189
2190





2191
2192

2193
2194

2195
2196
2197
2198
2199

2200
2201
2202














2203
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
2234
2235
2236
2237
2238











2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251






























































































































2252
2253
2254
2255
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445



2446
2447
2448
2449
2450
2451
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
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
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
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
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
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830



2831
2832
2833
2834
2835
2836
2837
2838
2839
2840




2841
2842
2843
2844
2845


2846


2847





2848



2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862




2863
2864
2865
2866
2867
2868
2869
2870








2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901











2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942





2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959







2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970













2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+









+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
-
-
+
-
-
+
-
-
-
-
-
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




    *pp = sqlite3WindowDup(db, 0, pWin);
    if( *pp==0 ) break;
    pp = &((*pp)->pNextWin);
  }

  return pRet;
}

/*
** Return true if it can be determined at compile time that expression 
** pExpr evaluates to a value that, when cast to an integer, is greater 
** than zero. False otherwise.
**
** If an OOM error occurs, this function sets the Parse.db.mallocFailed 
** flag and returns zero.
*/
static int windowExprGtZero(Parse *pParse, Expr *pExpr){
  int ret = 0;
  sqlite3 *db = pParse->db;
  sqlite3_value *pVal = 0;
  sqlite3ValueFromExpr(db, pExpr, db->enc, SQLITE_AFF_NUMERIC, &pVal);
  if( pVal && sqlite3_value_int(pVal)>0 ){
    ret = 1;
  }
  sqlite3ValueFree(pVal);
  return ret;
}

/*
** sqlite3WhereBegin() has already been called for the SELECT statement 
** passed as the second argument when this function is invoked. It generates
** code to populate the Window.regResult register for each window function and
** invoke the sub-routine at instruction addrGosub once for each row.
** This function calls sqlite3WhereEnd() before returning. 
** code to populate the Window.regResult register for each window function 
** and invoke the sub-routine at instruction addrGosub once for each row.
** sqlite3WhereEnd() is always called before returning. 
**
** This function handles several different types of window frames, which
** require slightly different processing. The following pseudo code is
** used to implement window frames of the form:
**
**   ROWS BETWEEN <expr1> PRECEDING AND <expr2> FOLLOWING
**
** Other window frame types use variants of the following:
**
**     ... loop started by sqlite3WhereBegin() ...
**       if( new partition ){
**         Gosub flush
**       }
**       Insert new row into eph table.
**       
**       if( first row of partition ){
**         // Rewind three cursors, all open on the eph table.
**         Rewind(csrEnd);
**         Rewind(csrStart);
**         Rewind(csrCurrent);
**       
**         regEnd = <expr2>          // FOLLOWING expression
**         regStart = <expr1>        // PRECEDING expression
**       }else{
**         // First time this branch is taken, the eph table contains two 
**         // rows. The first row in the partition, which all three cursors
**         // currently point to, and the following row.
**         AGGSTEP
**         if( (regEnd--)<=0 ){
**           RETURN_ROW
**           if( (regStart--)<=0 ){
**             AGGINVERSE
**           }
**         }
**       }
**     }
**     flush:
**       AGGSTEP
**       while( 1 ){
**         RETURN ROW
**         if( csrCurrent is EOF ) break;
**         if( (regStart--)<=0 ){
**           AggInverse(csrStart)
**           Next(csrStart)
**         }
**       }
**
** The pseudo-code above uses the following shorthand:
**
**   AGGSTEP:    invoke the aggregate xStep() function for each window function
**               with arguments read from the current row of cursor csrEnd, then
**               step cursor csrEnd forward one row (i.e. sqlite3BtreeNext()).
**
**   RETURN_ROW: return a row to the caller based on the contents of the 
**               current row of csrCurrent and the current state of all 
**               aggregates. Then step cursor csrCurrent forward one row.
**
**   AGGINVERSE: invoke the aggregate xInverse() function for each window 
**               functions with arguments read from the current row of cursor
**               csrStart. Then step csrStart forward one row.
**
** There are two other ROWS window frames that are handled significantly
** differently from the above - "BETWEEN <expr> PRECEDING AND <expr> PRECEDING"
** and "BETWEEN <expr> FOLLOWING AND <expr> FOLLOWING". These are special 
** cases because they change the order in which the three cursors (csrStart,
** csrCurrent and csrEnd) iterate through the ephemeral table. Cases that
** use UNBOUNDED or CURRENT ROW are much simpler variations on one of these
** three.
**
**   ROWS BETWEEN <expr1> PRECEDING AND <expr2> PRECEDING
**
**     ... loop started by sqlite3WhereBegin() ...
**       if( new partition ){
**         Gosub flush
**       }
**       Insert new row into eph table.
**       if( first row of partition ){
**         Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent)
**         regEnd = <expr2>
**         regStart = <expr1>
**       }else{
**         if( (regEnd--)<=0 ){
**           AGGSTEP
**         }
**         RETURN_ROW
**         if( (regStart--)<=0 ){
**           AGGINVERSE
**         }
**       }
**     }
**     flush:
**       if( (regEnd--)<=0 ){
**         AGGSTEP
**       }
**       RETURN_ROW
**
**
**   ROWS BETWEEN <expr1> FOLLOWING AND <expr2> FOLLOWING
**
**     ... loop started by sqlite3WhereBegin() ...
**     if( new partition ){
**       Gosub flush
**     }
**     Insert new row into eph table.
**     if( first row of partition ){
**       Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent)
**       regEnd = <expr2>
**       regStart = regEnd - <expr1>
**     }else{
**       AGGSTEP
**       if( (regEnd--)<=0 ){
**         RETURN_ROW
**       }
**       if( (regStart--)<=0 ){
**         AGGINVERSE
**       }
**     }
**   }
**   flush:
**     AGGSTEP
**     while( 1 ){
**       if( (regEnd--)<=0 ){
**         RETURN_ROW
**         if( eof ) break;
**       }
**       if( (regStart--)<=0 ){
**         AGGINVERSE
**         if( eof ) break
**       }
**     }
**     while( !eof csrCurrent ){
**       RETURN_ROW
**     }
**
** For the most part, the patterns above are adapted to support UNBOUNDED by
** assuming that it is equivalent to "infinity PRECEDING/FOLLOWING" and
** CURRENT ROW by assuming that it is equivilent to "0 PRECEDING/FOLLOWING".
** This is optimized of course - branches that will never be taken and
** conditions that are always true are omitted from the VM code. The only
** exceptional case is:
**
**   ROWS BETWEEN <expr1> FOLLOWING AND UNBOUNDED FOLLOWING
**
**     ... loop started by sqlite3WhereBegin() ...
**     if( new partition ){
**       Gosub flush
**     }
**     Insert new row into eph table.
**     if( first row of partition ){
**       Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent)
**       regStart = <expr1>
**     }else{
**       AGGSTEP
**     }
**   }
**   flush:
**     AGGSTEP
**     while( 1 ){
**       if( (regStart--)<=0 ){
**         AGGINVERSE
**         if( eof ) break
**       }
**       RETURN_ROW
**     }
**     while( !eof csrCurrent ){
**       RETURN_ROW
**     }
**
** Also requiring special handling are the cases:
**
**   ROWS BETWEEN <expr1> PRECEDING AND <expr2> PRECEDING
**   ROWS BETWEEN <expr1> FOLLOWING AND <expr2> FOLLOWING
**
** when (expr1 < expr2). This is detected at runtime, not by this function.
** To handle this case, the pseudo-code programs depicted above are modified
** slightly to be:
**
**     ... loop started by sqlite3WhereBegin() ...
**     if( new partition ){
**       Gosub flush
**     }
**     Insert new row into eph table.
**     if( first row of partition ){
**       Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent)
**       regEnd = <expr2>
**       regStart = <expr1>
**       if( regEnd < regStart ){
**         RETURN_ROW
**         delete eph table contents
**         continue
**       }
**     ...
**
** The new "continue" statement in the above jumps to the next iteration
** of the outer loop - the one started by sqlite3WhereBegin().
**
** The various GROUPS cases are implemented using the same patterns as
** ROWS. The VM code is modified slightly so that:
**
**   1. The else branch in the main loop is only taken if the row just
**      added to the ephemeral table is the start of a new group. In
**      other words, it becomes:
**
**         ... loop started by sqlite3WhereBegin() ...
**         if( new partition ){
**           Gosub flush
**         }
**         Insert new row into eph table.
**         if( first row of partition ){
**           Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent)
**           regEnd = <expr2>
**           regStart = <expr1>
**         }else if( new group ){
**           ... 
**         }
**       }
**
**   2. Instead of processing a single row, each RETURN_ROW, AGGSTEP or 
**      AGGINVERSE step processes the current row of the relevant cursor and
**      all subsequent rows belonging to the same group.
**
** RANGE window frames are a little different again. As for GROUPS, the 
** main loop runs once per group only. And RETURN_ROW, AGGSTEP and AGGINVERSE
** deal in groups instead of rows. As for ROWS and GROUPS, there are three
** basic cases:
**
**   RANGE BETWEEN <expr1> PRECEDING AND <expr2> FOLLOWING
**
**     ... loop started by sqlite3WhereBegin() ...
**       if( new partition ){
**         Gosub flush
**       }
**       Insert new row into eph table.
**       if( first row of partition ){
**         Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent)
**         regEnd = <expr2>
**         regStart = <expr1>
**       }else{
**         AGGSTEP
**         while( (csrCurrent.key + regEnd) < csrEnd.key ){
**           RETURN_ROW
**           while( csrStart.key + regStart) < csrCurrent.key ){
**             AGGINVERSE
**           }
**         }
**       }
**     }
**     flush:
**       AGGSTEP
**       while( 1 ){
**         RETURN ROW
**         if( csrCurrent is EOF ) break;
**           while( csrStart.key + regStart) < csrCurrent.key ){
**             AGGINVERSE
**           }
**         }
**       }
**
** In the above notation, "csr.key" means the current value of the ORDER BY 
** expression (there is only ever 1 for a RANGE that uses an <expr> FOLLOWING
** or <expr PRECEDING) read from cursor csr.
**
**   RANGE BETWEEN <expr1> PRECEDING AND <expr2> PRECEDING
**
**     ... loop started by sqlite3WhereBegin() ...
**       if( new partition ){
**         Gosub flush
**       }
**       Insert new row into eph table.
**       if( first row of partition ){
**         Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent)
**         regEnd = <expr2>
**         regStart = <expr1>
**       }else{
**         while( (csrEnd.key + regEnd) <= csrCurrent.key ){
**           AGGSTEP
**         }
**         while( (csrStart.key + regStart) < csrCurrent.key ){
**           AGGINVERSE
**         }
**         RETURN_ROW
**       }
**     }
**     flush:
**       while( (csrEnd.key + regEnd) <= csrCurrent.key ){
**         AGGSTEP
**       }
**       while( (csrStart.key + regStart) < csrCurrent.key ){
**         AGGINVERSE
**       }
**       RETURN_ROW
**
**   RANGE BETWEEN <expr1> FOLLOWING AND <expr2> FOLLOWING
**
**     ... loop started by sqlite3WhereBegin() ...
**       if( new partition ){
**         Gosub flush
**       }
**       Insert new row into eph table.
**       if( first row of partition ){
**         Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent)
**         regEnd = <expr2>
**         regStart = <expr1>
**       }else{
**         AGGSTEP
**         while( (csrCurrent.key + regEnd) < csrEnd.key ){
**           while( (csrCurrent.key + regStart) > csrStart.key ){
**             AGGINVERSE
**           }
**           RETURN_ROW
**         }
**       }
**     }
**     flush:
**       AGGSTEP
**       while( 1 ){
**         while( (csrCurrent.key + regStart) > csrStart.key ){
**           AGGINVERSE
**           if( eof ) break "while( 1 )" loop.
**         }
**         RETURN_ROW
**       }
**       while( !eof csrCurrent ){
**         RETURN_ROW
**       }
**
** The text above leaves out many details. Refer to the code and comments
** below for a more complete picture.
*/
void sqlite3WindowCodeStep(
  Parse *pParse,                  /* Parse context */
  Select *p,                      /* Rewritten SELECT statement */
  WhereInfo *pWInfo,              /* Context returned by sqlite3WhereBegin() */
  int regGosub,                   /* Register for OP_Gosub */
  int addrGosub                   /* OP_Gosub here to return each row */
){
  Window *pMWin = p->pWin;
  ExprList *pOrderBy = pMWin->pOrderBy;
  Vdbe *v = sqlite3GetVdbe(pParse);
  int csrWrite;                   /* Cursor used to write to eph. table */
  int csrInput = p->pSrc->a[0].iCursor;     /* Cursor of sub-select */
  int nInput = p->pSrc->a[0].pTab->nCol;    /* Number of cols returned by sub */
  int iInput;                               /* To iterate through sub cols */
  int addrNe;                     /* Address of OP_Ne */
  int addrGosubFlush = 0;         /* Address of OP_Gosub to flush: */
  int addrInteger = 0;            /* Address of OP_Integer */
  int addrEmpty;                  /* Address of OP_Rewind in flush: */
  int regNew;                     /* Array of registers holding new input row */
  int regRecord;                  /* regNew array in record form */
  int regNewPeer = 0;             /* Peer values for new row (part of regNew) */
  int regPeer = 0;                /* Peer values for current row */
  int regFlushPart = 0;           /* Register for "Gosub flush_partition" */
  WindowCodeArg s;                /* Context object for sub-routines */
  int lblWhereEnd;                /* Label just before sqlite3WhereEnd() code */
  int regStart = 0;               /* Value of <expr> PRECEDING */
  int regEnd = 0;                 /* Value of <expr> FOLLOWING */

  assert( pMWin->eStart==TK_PRECEDING || pMWin->eStart==TK_CURRENT 
       || pMWin->eStart==TK_FOLLOWING || pMWin->eStart==TK_UNBOUNDED 
  );
  assert( pMWin->eEnd==TK_FOLLOWING || pMWin->eEnd==TK_CURRENT 
       || pMWin->eEnd==TK_UNBOUNDED || pMWin->eEnd==TK_PRECEDING 
  );
  assert( pMWin->eExclude==0 || pMWin->eExclude==TK_CURRENT
       || pMWin->eExclude==TK_GROUP || pMWin->eExclude==TK_TIES
       || pMWin->eExclude==TK_NO
  );

  lblWhereEnd = sqlite3VdbeMakeLabel(pParse);

  /* Fill in the context object */
  memset(&s, 0, sizeof(WindowCodeArg));
  s.pParse = pParse;
  s.pMWin = pMWin;
  s.pVdbe = v;
  s.regGosub = regGosub;
  s.addrGosub = addrGosub;
  s.current.csr = pMWin->iEphCsr;
  csrWrite = s.current.csr+1;
  s.start.csr = s.current.csr+2;
  s.end.csr = s.current.csr+3;

  /* There are three different functions that may be used to do the work
  ** of this one, depending on the window frame and the specific built-in
  ** window functions used (if any).
  /* Figure out when rows may be deleted from the ephemeral table. There
  ** are four options - they may never be deleted (eDelete==0), they may 
  ** be deleted as soon as they are no longer part of the window frame
  ** (eDelete==WINDOW_AGGINVERSE), they may be deleted as after the row 
  ** has been returned to the caller (WINDOW_RETURN_ROW), or they may
  ** be deleted after they enter the frame (WINDOW_AGGSTEP). */
  switch( pMWin->eStart ){
    case TK_FOLLOWING:
      if( pMWin->eFrmType!=TK_RANGE
       && windowExprGtZero(pParse, pMWin->pStart)
  **
  ** windowCodeRowExprStep() handles all "ROWS" window frames, except for:
  **
  **   ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
      ){
        s.eDelete = WINDOW_RETURN_ROW;
      }
      break;
    case TK_UNBOUNDED:
  **
  ** The exception is because windowCodeRowExprStep() implements all window
      if( windowCacheFrame(pMWin)==0 ){
  ** frame types by caching the entire partition in a temp table, and
  ** "ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW" is easy enough to
        if( pMWin->eEnd==TK_PRECEDING ){
  ** implement without such a cache.
  **
  ** windowCodeCacheStep() is used for:
  **
  **   RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
          if( pMWin->eFrmType!=TK_RANGE
  **
  ** It is also used for anything not handled by windowCodeRowExprStep() 
  ** that invokes a built-in window function that requires the entire 
           && windowExprGtZero(pParse, pMWin->pEnd)
          ){
            s.eDelete = WINDOW_AGGSTEP;
          }
        }else{
          s.eDelete = WINDOW_RETURN_ROW;
        }
      }
      break;
    default:
      s.eDelete = WINDOW_AGGINVERSE;
      break;
  }

  ** partition to be cached in a temp table before any rows are returned
  ** (e.g. nth_value() or percent_rank()).
  **
  ** Finally, assuming there is no built-in window function that requires
  /* Allocate registers for the array of values from the sub-query, the
  ** samve values in record form, and the rowid used to insert said record
  ** into the ephemeral table.  */
  regNew = pParse->nMem+1;
  pParse->nMem += nInput;
  regRecord = ++pParse->nMem;
  s.regRowid = ++pParse->nMem;

  ** the partition to be cached, windowCodeDefaultStep() is used for:
  **
  **   RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW 
  **   RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
  **   RANGE BETWEEN CURRENT ROW AND CURRENT ROW 
  **   ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
  **
  ** windowCodeDefaultStep() is the only one of the three functions that
  /* 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;
  }
  if( pMWin->eEnd==TK_PRECEDING || pMWin->eEnd==TK_FOLLOWING ){
    regEnd = ++pParse->nMem;
  }

  /* If this is not a "ROWS BETWEEN ..." frame, then allocate arrays of
  ** registers to store copies of the ORDER BY expressions (peer values) 
  ** for the main loop, and for each cursor (start, current and end). */
  if( pMWin->eFrmType!=TK_ROWS ){
    int nPeer = (pOrderBy ? pOrderBy->nExpr : 0);
    regNewPeer = regNew + pMWin->nBufferCol;
    if( pMWin->pPartition ) regNewPeer += pMWin->pPartition->nExpr;
    regPeer = pParse->nMem+1;       pParse->nMem += nPeer;
    s.start.reg = pParse->nMem+1;   pParse->nMem += nPeer;
    s.current.reg = pParse->nMem+1; pParse->nMem += nPeer;
    s.end.reg = pParse->nMem+1;     pParse->nMem += nPeer;
  }

  /* Load the column values for the row returned by the sub-select
  ** into an array of registers starting at regNew. Assemble them into
  ** a record in register regRecord. */
  for(iInput=0; iInput<nInput; iInput++){
    sqlite3VdbeAddOp3(v, OP_Column, csrInput, iInput, regNew+iInput);
  }
  sqlite3VdbeAddOp3(v, OP_MakeRecord, regNew, nInput, regRecord);

  ** does not cache each partition in a temp table before beginning to
  ** return rows.
  */
  if( pMWin->eType==TK_ROWS 
   && (pMWin->eStart!=TK_UNBOUNDED||pMWin->eEnd!=TK_CURRENT||!pMWin->pOrderBy)
  ){
    VdbeModuleComment((pParse->pVdbe, "Begin RowExprStep()"));
    windowCodeRowExprStep(pParse, p, pWInfo, regGosub, addrGosub);
  }else{
    Window *pWin;
    int bCache = 0;               /* True to use CacheStep() */
  /* An input row has just been read into an array of registers starting
  ** at regNew. If the window has a PARTITION clause, this block generates 
  ** VM code to check if the input row is the start of a new partition.
  ** If so, it does an OP_Gosub to an address to be filled in later. The
  ** address of the OP_Gosub is stored in local variable addrGosubFlush. */
  if( pMWin->pPartition ){
    int addr;
    ExprList *pPart = pMWin->pPartition;
    int nPart = pPart->nExpr;
    int regNewPart = regNew + pMWin->nBufferCol;
    KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pPart, 0, 0);

    regFlushPart = ++pParse->nMem;
    addr = sqlite3VdbeAddOp3(v, OP_Compare, regNewPart, pMWin->regPart, nPart);
    sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO);
    sqlite3VdbeAddOp3(v, OP_Jump, addr+2, addr+4, addr+2);
    VdbeCoverageEqNe(v);
    addrGosubFlush = sqlite3VdbeAddOp1(v, OP_Gosub, regFlushPart);
    VdbeComment((v, "call flush_partition"));
    sqlite3VdbeAddOp3(v, OP_Copy, regNewPart, pMWin->regPart, nPart-1);
  }

  /* Insert the new row into the ephemeral table */
  sqlite3VdbeAddOp2(v, OP_NewRowid, csrWrite, s.regRowid);
  sqlite3VdbeAddOp3(v, OP_Insert, csrWrite, regRecord, s.regRowid);
  addrNe = sqlite3VdbeAddOp3(v, OP_Ne, pMWin->regOne, 0, s.regRowid);
  VdbeCoverageNeverNull(v);

  /* This block is run for the first row of each partition */
  s.regArg = windowInitAccum(pParse, pMWin);

  if( regStart ){
    sqlite3ExprCode(pParse, pMWin->pStart, regStart);
    windowCheckValue(pParse, regStart, 0 + (pMWin->eFrmType==TK_RANGE?3:0));
  }
  if( regEnd ){
    sqlite3ExprCode(pParse, pMWin->pEnd, regEnd);
    windowCheckValue(pParse, regEnd, 1 + (pMWin->eFrmType==TK_RANGE?3:0));
  }

  if( pMWin->eFrmType!=TK_RANGE && pMWin->eStart==pMWin->eEnd && regStart ){
    if( pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_UNBOUNDED ){
      bCache = 1;
    }else{
      for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
        FuncDef *pFunc = pWin->pFunc;
    int op = ((pMWin->eStart==TK_FOLLOWING) ? OP_Ge : OP_Le);
    int addrGe = sqlite3VdbeAddOp3(v, op, regStart, 0, regEnd);
    VdbeCoverageNeverNullIf(v, op==OP_Ge); /* NeverNull because bound <expr> */
    VdbeCoverageNeverNullIf(v, op==OP_Le); /*   values previously checked */
    windowAggFinal(&s, 0);
    sqlite3VdbeAddOp1(v, OP_Rewind, s.current.csr);
    windowReturnOneRow(&s);
    sqlite3VdbeAddOp1(v, OP_ResetSorter, s.current.csr);
    sqlite3VdbeAddOp2(v, OP_Goto, 0, lblWhereEnd);
    sqlite3VdbeJumpHere(v, addrGe);
  }
  if( pMWin->eStart==TK_FOLLOWING && pMWin->eFrmType!=TK_RANGE && regEnd ){
    assert( pMWin->eEnd==TK_FOLLOWING );
    sqlite3VdbeAddOp3(v, OP_Subtract, regStart, regEnd, regStart);
  }

  if( pMWin->eStart!=TK_UNBOUNDED ){
        if( (pFunc->funcFlags & SQLITE_FUNC_WINDOW_SIZE)
         || (pFunc->zName==nth_valueName)
         || (pFunc->zName==first_valueName)
         || (pFunc->zName==leadName)
         || (pFunc->zName==lagName)
        ){
          bCache = 1;
    sqlite3VdbeAddOp1(v, OP_Rewind, s.start.csr);
  }
  sqlite3VdbeAddOp1(v, OP_Rewind, s.current.csr);
  sqlite3VdbeAddOp1(v, OP_Rewind, s.end.csr);
  if( regPeer && pOrderBy ){
    sqlite3VdbeAddOp3(v, OP_Copy, regNewPeer, regPeer, pOrderBy->nExpr-1);
    sqlite3VdbeAddOp3(v, OP_Copy, regPeer, s.start.reg, pOrderBy->nExpr-1);
    sqlite3VdbeAddOp3(v, OP_Copy, regPeer, s.current.reg, pOrderBy->nExpr-1);
    sqlite3VdbeAddOp3(v, OP_Copy, regPeer, s.end.reg, pOrderBy->nExpr-1);
  }

          break;
        }
      }
    }

    /* Otherwise, call windowCodeDefaultStep().  */
    if( bCache ){
      VdbeModuleComment((pParse->pVdbe, "Begin CacheStep()"));
      windowCodeCacheStep(pParse, p, pWInfo, regGosub, addrGosub);
    }else{
      VdbeModuleComment((pParse->pVdbe, "Begin DefaultStep()"));
      windowCodeDefaultStep(pParse, p, pWInfo, regGosub, addrGosub);
    }
  sqlite3VdbeAddOp2(v, OP_Goto, 0, lblWhereEnd);

  sqlite3VdbeJumpHere(v, addrNe);

  /* Beginning of the block executed for the second and subsequent rows. */
  if( regPeer ){
    windowIfNewPeer(pParse, pOrderBy, regNewPeer, regPeer, lblWhereEnd);
  }
  if( pMWin->eStart==TK_FOLLOWING ){
    windowCodeOp(&s, WINDOW_AGGSTEP, 0, 0);
    if( pMWin->eEnd!=TK_UNBOUNDED ){
      if( pMWin->eFrmType==TK_RANGE ){
        int lbl = sqlite3VdbeMakeLabel(pParse);
        int addrNext = sqlite3VdbeCurrentAddr(v);
        windowCodeRangeTest(&s, OP_Ge, s.current.csr, regEnd, s.end.csr, lbl);
        windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0);
        windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 0);
        sqlite3VdbeAddOp2(v, OP_Goto, 0, addrNext);
        sqlite3VdbeResolveLabel(v, lbl);
      }else{
        windowCodeOp(&s, WINDOW_RETURN_ROW, regEnd, 0);
        windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0);
      }
    }
  }else
  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);
    if( !bRPS ) windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0);
  }else{
    int addr = 0;
    windowCodeOp(&s, WINDOW_AGGSTEP, 0, 0);
    if( pMWin->eEnd!=TK_UNBOUNDED ){
      if( pMWin->eFrmType==TK_RANGE ){
        int lbl = 0;
        addr = sqlite3VdbeCurrentAddr(v);
        if( regEnd ){
          lbl = sqlite3VdbeMakeLabel(pParse);
          windowCodeRangeTest(&s, OP_Ge, s.current.csr, regEnd, s.end.csr, lbl);
        }
        windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 0);
        windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0);
        if( regEnd ){
          sqlite3VdbeAddOp2(v, OP_Goto, 0, addr);
          sqlite3VdbeResolveLabel(v, lbl);
        }
      }else{
        if( regEnd ){
          addr = sqlite3VdbeAddOp3(v, OP_IfPos, regEnd, 0, 1);
          VdbeCoverage(v);
        }
        windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 0);
        windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0);
        if( regEnd ) sqlite3VdbeJumpHere(v, addr);
      }
    }
  }

  /* End of the main input loop */
  sqlite3VdbeResolveLabel(v, lblWhereEnd);
  sqlite3WhereEnd(pWInfo);

  /* 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);
  }else if( pMWin->eStart==TK_FOLLOWING ){
    int addrStart;
    int addrBreak1;
    int addrBreak2;
    int addrBreak3;
    windowCodeOp(&s, WINDOW_AGGSTEP, 0, 0);
    if( pMWin->eFrmType==TK_RANGE ){
      addrStart = sqlite3VdbeCurrentAddr(v);
      addrBreak2 = windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 1);
      addrBreak1 = windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 1);
    }else
    if( pMWin->eEnd==TK_UNBOUNDED ){
      addrStart = sqlite3VdbeCurrentAddr(v);
      addrBreak1 = windowCodeOp(&s, WINDOW_RETURN_ROW, regStart, 1);
      addrBreak2 = windowCodeOp(&s, WINDOW_AGGINVERSE, 0, 1);
    }else{
      assert( pMWin->eEnd==TK_FOLLOWING );
      addrStart = sqlite3VdbeCurrentAddr(v);
      addrBreak1 = windowCodeOp(&s, WINDOW_RETURN_ROW, regEnd, 1);
      addrBreak2 = windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 1);
    }
    sqlite3VdbeAddOp2(v, OP_Goto, 0, addrStart);
    sqlite3VdbeJumpHere(v, addrBreak2);
    addrStart = sqlite3VdbeCurrentAddr(v);
    addrBreak3 = windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 1);
    sqlite3VdbeAddOp2(v, OP_Goto, 0, addrStart);
    sqlite3VdbeJumpHere(v, addrBreak1);
    sqlite3VdbeJumpHere(v, addrBreak3);
  }else{
    int addrBreak;
    int addrStart;
    windowCodeOp(&s, WINDOW_AGGSTEP, 0, 0);
    addrStart = sqlite3VdbeCurrentAddr(v);
    addrBreak = windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 1);
    windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0);
    sqlite3VdbeAddOp2(v, OP_Goto, 0, addrStart);
    sqlite3VdbeJumpHere(v, addrBreak);
  }
  sqlite3VdbeJumpHere(v, addrEmpty);

  sqlite3VdbeAddOp1(v, OP_ResetSorter, s.current.csr);
  if( pMWin->pPartition ){
    if( pMWin->regStartRowid ){
      sqlite3VdbeAddOp2(v, OP_Integer, 1, pMWin->regStartRowid);
      sqlite3VdbeAddOp2(v, OP_Integer, 0, pMWin->regEndRowid);
    }
    sqlite3VdbeChangeP1(v, addrInteger, sqlite3VdbeCurrentAddr(v));
    sqlite3VdbeAddOp1(v, OP_Return, regFlushPart);
  }
}

#endif /* SQLITE_OMIT_WINDOWFUNC */

Changes to test/affinity2.test.

10
11
12
13
14
15
16

17
18
19
20
21
22
23
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24







+







#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is type affinity in comparison operations.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix affinity2

do_execsql_test affinity2-100 {
  CREATE TABLE t1(
    xi INTEGER,
    xr REAL,
    xb BLOB,
    xn NUMERIC,
53
54
55
56
57
58
59
60










































































61
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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

do_execsql_test affinity2-220 {
  SELECT rowid, xn==xt, xn==xb, xn==+xt FROM t1 ORDER BY rowid;
} {1 1 1 1 2 1 1 1 3 1 1 1}

do_execsql_test affinity2-300 {
  SELECT rowid, xt==+xi, xt==xi, xt==xb FROM t1 ORDER BY rowid;
} {1 1 1 0 2 1 1 1 3 0 1 1}

#-------------------------------------------------------------------------
do_execsql_test 400 {
  CREATE TABLE ttt(c0, c1);
  CREATE INDEX ii ON ttt(CAST(c0 AS NUMERIC)); 
  INSERT INTO ttt VALUES('abc', '-1');
}
do_execsql_test 410 {
  SELECT * FROM ttt WHERE CAST(c0 AS NUMERIC) > c1 GROUP BY rowid; 
} {abc -1}
do_execsql_test 420 {
  SELECT * FROM ttt INDEXED BY ii WHERE CAST(c0 AS NUMERIC) > c1 GROUP BY rowid;
} {abc -1}

do_execsql_test 430 {
  CREATE TABLE t3(a, b, c INTEGER);
  CREATE INDEX t3ac ON t3(a, c-1);
  INSERT INTO t3 VALUES(1, 1, 1);
  INSERT INTO t3 VALUES(2, 1, 0);
  INSERT INTO t3 VALUES(3, 1, 1);
  INSERT INTO t3 VALUES(4, 1, 0);
  INSERT INTO t3 VALUES(5, 1, 1);
}
do_execsql_test 440 {
  SELECT * FROM t3 WHERE c='0' ORDER BY a;
} {2 1 0 4 1 0}

# 2019-08-22 ticket https://sqlite.org/src/info/d99f1ffe836c591ac57f
# False positive in sqlite3ExprNeedsNoAffinityChange()
#
do_execsql_test 500 {
  DROP TABLE IF EXISTS t0;
  CREATE TABLE t0(c0 TEXT UNIQUE, c1);
  INSERT INTO t0(c0) VALUES (-1);
  SELECT quote(- x'ce'), quote(t0.c0), quote(- x'ce' >= t0.c0) FROM t0;
} {0 '-1' 1}
do_execsql_test 501 {
  SELECT * FROM t0 WHERE - x'ce' >= t0.c0;
} {-1 {}}
do_execsql_test 502 {
  SELECT quote(+-+x'ce'), quote(t0.c0), quote(+-+x'ce' >= t0.c0) FROM t0;
} {0 '-1' 1}
do_execsql_test 503 {
  SELECT * FROM t0 WHERE +-+x'ce' >= t0.c0;
} {-1 {}}
do_execsql_test 504 {
  SELECT quote(- 'ce'), quote(t0.c0), quote(- 'ce' >= t0.c0) FROM t0;
} {0 '-1' 1}
do_execsql_test 505 {
  SELECT * FROM t0 WHERE - 'ce' >= t0.c0;
} {-1 {}}
do_execsql_test 506 {
  SELECT quote(+-+'ce'), quote(t0.c0), quote(+-+'ce' >= t0.c0) FROM t0;
} {0 '-1' 1}
do_execsql_test 507 {
  SELECT * FROM t0 WHERE +-+'ce' >= t0.c0;
} {-1 {}}
 
# 2019-08-30 ticket https://www.sqlite.org/src/info/40812aea1fde9594
#
# Due to some differences in floating point computations, these tests do not
# work under valgrind.
#
if {![info exists ::G(valgrind)]} {
  do_execsql_test 600 {
    DROP TABLE IF EXISTS t0;
    CREATE TABLE t0(c0 REAL UNIQUE);
    INSERT INTO t0(c0) VALUES (3175546974276630385);
    SELECT 3175546974276630385 < c0 FROM t0;
  } {1}
  do_execsql_test 601 {
    SELECT 1 FROM t0 WHERE 3175546974276630385 < c0;
  } {1}
}

finish_test

Changes to test/affinity3.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
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







+
+
+
+
+





+
+
+
+
+
+
+
+









+
+
+
+



+
+
+
+
+
+




+
+
+



+
+
+
+
+
+







  CREATE TABLE apr (id INT PRIMARY KEY, apr REAL);
  
  CREATE VIEW v1 AS
  SELECT c.id, i.apr
  FROM customer c
  LEFT JOIN apr i ON i.id=c.id;
  
  CREATE VIEW v1rj AS
  SELECT c.id, i.apr
  FROM apr i
  RIGHT JOIN customer c ON i.id=c.id;
  
  CREATE VIEW v2 AS
  SELECT c.id, v1.apr
  FROM customer c
  LEFT JOIN v1 ON v1.id=c.id;
  
  CREATE VIEW v2rj AS
  SELECT c.id, v1.apr
  FROM v1 RIGHT JOIN customer c ON v1.id=c.id;
  
  CREATE VIEW v2rjrj AS
  SELECT c.id, v1rj.apr
  FROM v1rj RIGHT JOIN customer c ON v1rj.id=c.id;
  
  INSERT INTO customer (id) VALUES (1);
  INSERT INTO apr (id, apr) VALUES (1, 12);
  INSERT INTO customer (id) VALUES (2);
  INSERT INTO apr (id, apr) VALUES (2, 12.01);
}
do_execsql_test affinity3-110 {
  PRAGMA automatic_index=ON;
  SELECT id, (apr / 100), typeof(apr) apr_type  FROM v1;
} {1 0.12 real 2 0.1201 real}
do_execsql_test affinity3-111 {
  PRAGMA automatic_index=ON;
  SELECT id, (apr / 100), typeof(apr) apr_type  FROM v1rj;
} {1 0.12 real 2 0.1201 real}
do_execsql_test affinity3-120 {
  SELECT id, (apr / 100), typeof(apr) apr_type  FROM v2;
} {1 0.12 real 2 0.1201 real}
do_execsql_test affinity3-121 {
  SELECT id, (apr / 100), typeof(apr) apr_type  FROM v2rj;
} {1 0.12 real 2 0.1201 real}
do_execsql_test affinity3-122 {
  SELECT id, (apr / 100), typeof(apr) apr_type  FROM v2rjrj;
} {1 0.12 real 2 0.1201 real}
do_execsql_test affinity3-130 {
  PRAGMA automatic_index=OFF;
  SELECT id, (apr / 100), typeof(apr) apr_type  FROM v1;
} {1 0.12 real 2 0.1201 real}
do_execsql_test affinity3-131 {
  SELECT id, (apr / 100), typeof(apr) apr_type  FROM v1rj;
} {1 0.12 real 2 0.1201 real}
do_execsql_test affinity3-140 {
  SELECT id, (apr / 100), typeof(apr) apr_type  FROM v2;
} {1 0.12 real 2 0.1201 real}
do_execsql_test affinity3-141 {
  SELECT id, (apr / 100), typeof(apr) apr_type  FROM v2rj;
} {1 0.12 real 2 0.1201 real}
do_execsql_test affinity3-142 {
  SELECT id, (apr / 100), typeof(apr) apr_type  FROM v2rjrj;
} {1 0.12 real 2 0.1201 real}

# Ticket https://www.sqlite.org/src/info/7ffd1ca1d2ad4ecf  (2017-01-16)
# Incorrect affinity when using automatic indexes 
#
do_execsql_test affinity3-200 {
  CREATE TABLE map_integer (id INT, name);
  INSERT INTO map_integer VALUES(1,'a');
71
72
73
74
75
76
77
78

79
80
81

82
83
84
85
86

87
88
89

90
91
103
104
105
106
107
108
109

110
111
112

113
114
115
116
117

118
119
120

121
122
123







-
+


-
+




-
+


-
+


      UNION SELECT * FROM map_text;
  CREATE TABLE mzed AS SELECT * FROM idmap;
}

do_execsql_test affinity3-210 {
  PRAGMA automatic_index=ON;
  SELECT * FROM data JOIN idmap USING(id);
} {1 abc a 4 xyz e}
} {4 xyz e}
do_execsql_test affinity3-220 {
  SELECT * FROM data JOIN mzed USING(id);
} {1 abc a 4 xyz e}
} {4 xyz e}

do_execsql_test affinity3-250 {
  PRAGMA automatic_index=OFF;
  SELECT * FROM data JOIN idmap USING(id);
} {1 abc a 4 xyz e}
} {4 xyz e}
do_execsql_test affinity3-260 {
  SELECT * FROM data JOIN mzed USING(id);
} {1 abc a 4 xyz e}
} {4 xyz e}

finish_test

Changes to test/aggnested.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

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
-
+


















+







# 2012 August 23
# 2012-08-23
#
# 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 file implements tests for processing aggregate queries with 
# subqueries in which the subqueries hold the aggregate functions
# or in which the subqueries are themselves aggregate queries
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix aggnested

do_test aggnested-1.1 {
  db eval {
    CREATE TABLE t1(a1 INTEGER);
    INSERT INTO t1 VALUES(1), (2), (3);
    CREATE TABLE t2(b1 INTEGER);
    INSERT INTO t2 VALUES(4), (5);
132
133
134
135
136
137
138











139
140
141
142
143
144
145
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







+
+
+
+
+
+
+
+
+
+
+







     (SELECT sum(value2==xyz) FROM t2)
    FROM
     (SELECT curr.value1 as xyz
        FROM t1 AS curr LEFT JOIN t1 AS other
       GROUP BY curr.id1);
  }
} {1 1}
do_test aggnested-3.1-rj {
  db eval {
    SELECT
     (SELECT sum(value2==xyz) FROM t2)
    FROM
     (SELECT curr.value1 as xyz
        FROM t1 AS other RIGHT JOIN t1 AS curr
       GROUP BY curr.id1);
  }
} {1 1}

do_test aggnested-3.2 {
  db eval {
    DROP TABLE IF EXISTS t1;
    DROP TABLE IF EXISTS t2;
    CREATE TABLE t1 (
      id1 INTEGER,
      value1 INTEGER,
228
229
230
231
232
233
234
235
236






















































































































237
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







-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

do_test aggnested-3.16 {
  db eval {
    SELECT max(value1), (SELECT sum(value2=value1) FROM t2)
      FROM t1
     GROUP BY id1;
  }
} {12 2 34 4}
 


# 2019-08-31
# Problem found by dbsqlfuzz
#
do_execsql_test aggnested-4.1 {
  DROP TABLE IF EXISTS aa;
  DROP TABLE IF EXISTS bb;
  CREATE TABLE aa(x INT);  INSERT INTO aa(x) VALUES(123);
  CREATE TABLE bb(y INT);  INSERT INTO bb(y) VALUES(456);
  SELECT (SELECT sum(x+(SELECT y)) FROM bb) FROM aa;
} {579}
do_execsql_test aggnested-4.2 {
  SELECT (SELECT sum(x+y) FROM bb) FROM aa;
} {579}
do_execsql_test aggnested-4.3 {
  DROP TABLE IF EXISTS tx;
  DROP TABLE IF EXISTS ty;
  CREATE TABLE tx(x INT);
  INSERT INTO tx VALUES(1),(2),(3),(4),(5);
  CREATE TABLE ty(y INT);
  INSERT INTO ty VALUES(91),(92),(93);
  SELECT min((SELECT count(y) FROM ty)) FROM tx;
} {3}
do_execsql_test aggnested-4.4 {
  SELECT max((SELECT a FROM (SELECT count(*) AS a FROM ty) AS s)) FROM tx;
} {3}

#--------------------------------------------------------------------------
#
reset_db
do_execsql_test 5.0 {
  CREATE TABLE x1(a, b);
  INSERT INTO x1 VALUES(1, 2);
  CREATE TABLE x2(x);
  INSERT INTO x2 VALUES(NULL), (NULL), (NULL);
}

# At one point, aggregate "total()" in the query below was being processed
# as part of the outer SELECT, not as part of the sub-select with no FROM
# clause.
do_execsql_test 5.1 {
  SELECT ( SELECT total( (SELECT b FROM x1) ) ) FROM x2;
} {2.0 2.0 2.0}

do_execsql_test 5.2 {
  SELECT ( SELECT total( (SELECT 2 FROM x1) ) ) FROM x2;
} {2.0 2.0 2.0}

do_execsql_test 5.3 {
  CREATE TABLE t1(a);
  CREATE TABLE t2(b);
}

do_execsql_test 5.4 {
  SELECT(
    SELECT max(b) LIMIT (
      SELECT total( (SELECT a FROM t1) )
    )
  )
  FROM t2;
} {{}}

do_execsql_test 5.5 {
  CREATE TABLE a(b);
  WITH c AS(SELECT a)
    SELECT(SELECT(SELECT group_concat(b, b)
          LIMIT(SELECT 0.100000 *
            AVG(DISTINCT(SELECT 0 FROM a ORDER BY b, b, b))))
        FROM a GROUP BY b,
        b, b) FROM a EXCEPT SELECT b FROM a ORDER BY b,
    b, b;
}

#-------------------------------------------------------------------------
# dbsqlfuzz a779227f721a834df95f4f42d0c31550a1f8b8a2 
#
reset_db
do_execsql_test 6.0 {
  CREATE TABLE t1(a);
  CREATE TABLE t2(b);

  INSERT INTO t1 VALUES('x');
  INSERT INTO t2 VALUES(1);
}

do_execsql_test 6.1.1 {
  SELECT ( 
    SELECT t2.b FROM (SELECT t2.b AS c FROM t1) GROUP BY 1 HAVING t2.b
  )
  FROM t2 GROUP BY 'constant_string';
} {1}
do_execsql_test 6.1.2 {
  SELECT ( 
    SELECT c FROM (SELECT t2.b AS c FROM t1) GROUP BY c HAVING t2.b
  )
  FROM t2 GROUP BY 'constant_string';
} {1}

do_execsql_test 6.2.0 {
  UPDATE t2 SET b=0
}
do_execsql_test 6.2.1 {
  SELECT ( 
    SELECT t2.b FROM (SELECT t2.b AS c FROM t1) GROUP BY 1 HAVING t2.b
  )
  FROM t2 GROUP BY 'constant_string';
} {{}}
do_execsql_test 6.2.2 {
  SELECT ( 
    SELECT c FROM (SELECT t2.b AS c FROM t1) GROUP BY c HAVING t2.b
  )
  FROM t2 GROUP BY 'constant_string';
} {{}}



 

finish_test

Changes to test/alter.test.

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
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







-
+












-
+







  }
} {1 18 2 9}

#--------------------------------------------------------------------------
# alter-9.X - Special test: Make sure the sqlite_rename_column() and
# rename_table() functions do not crash when handed bad input.
#
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db
do_test alter-9.1 {
  execsql {SELECT SQLITE_RENAME_COLUMN(0,0,0,0,0,0,0,0,0)}
} {{}}
foreach {tn sql} {
    1 { SELECT SQLITE_RENAME_TABLE(0,0,0,0,0,0,0) }
    2 { SELECT SQLITE_RENAME_TABLE(10,20,30,40,50,60,70) }
    3 { SELECT SQLITE_RENAME_TABLE('foo','foo','foo','foo','foo','foo','foo') }
} {
  do_test alter-9.2.$tn {
    catch { execsql $sql }
  } 1
}
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db

# If the INTERNAL_FUNCTIONS test-control is disabled (which is the default),
# then the sqlite_rename_table() SQL function is not accessible to ordinary SQL.
#
do_catchsql_test alter-9.3 {
  SELECT sqlite_rename_table(0,0,0,0,0,0,0);
} {1 {no such function: sqlite_rename_table}}
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
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







+
















-







  }
} {t3102a_rename t3102b_rename t3102c}

# Ticket #3651
do_test alter-14.1 {
  catchsql {
    CREATE TABLE t3651(a UNIQUE);
    INSERT INTO t3651 VALUES(5);
    ALTER TABLE t3651 ADD COLUMN b UNIQUE;
  }
} {1 {Cannot add a UNIQUE column}}
do_test alter-14.2 {
  catchsql {
    ALTER TABLE t3651 ADD COLUMN b PRIMARY KEY;
  }
} {1 {Cannot add a PRIMARY KEY column}}


#-------------------------------------------------------------------------
# Test that it is not possible to use ALTER TABLE on any system table.
#
set system_table_list {1 sqlite_master}
catchsql ANALYZE
ifcapable analyze { lappend system_table_list 2 sqlite_stat1 }
ifcapable stat3   { lappend system_table_list 3 sqlite_stat3 }
ifcapable stat4   { lappend system_table_list 4 sqlite_stat4 }

foreach {tn tbl} $system_table_list {
  do_test alter-15.$tn.1 {
    catchsql "ALTER TABLE $tbl RENAME TO xyz"
  } [list 1 "table $tbl may not be altered"]

898
899
900
901
902
903
904
905
































906
898
899
900
901
902
903
904
905
906
907
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
935
936
937
938








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

      DELETE FROM t2 WHERE id = OLD.a;
    END;
    ALTER TABLE t1 RENAME TO t3;
    UPDATE t3 SET b='peach' WHERE a=2;
    SELECT * FROM t2 ORDER BY 1;
  } {1 1.0 2.0 3 1.5 3.5}
}

# 2021-03-08 dbsqlfuzz 3f0a7245b69cd08617d7d7781ebaedb0fe765a93
reset_db
do_catchsql_test alter-18.1 {
  CREATE TABLE t1(a,b,c);
  CREATE TABLE log(a INTEGER PRIMARY KEY,b,c);
  CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
    INSERT INTO logx(a,b,c) VALUES(new.a,new.b,new.c)
    ON CONFLICT(a) DO UPDATE SET c=excluded.c, b=new.b;
  END;
  ALTER TABLE log RENAME COLUMN a TO x;
} {1 {error in trigger tr1: no such table: main.logx}}

# 2021-10-13 dbsqlfuzz e89174cbfad2d904f06b5e24df0a22510b6a1c1e
reset_db
do_execsql_test alter-19.1 {
  CREATE TABLE t1(x);
  CREATE TABLE t2(c);
  CREATE TRIGGER r1 AFTER INSERT ON t2 BEGIN
    UPDATE t2 SET (c)=(
       EXISTS(SELECT 1 WHERE (WITH cte1(a) AS (SELECT 1 FROM t1 WHERE (SELECT 1 WHERE (WITH cte2(b) AS (VALUES(1))SELECT b FROM cte2)))SELECT a FROM cte1))
    );
  END;
  ALTER TABLE t2 RENAME TO t3;
} {}
do_execsql_test alter-19.2 {
  SELECT name FROM sqlite_schema WHERE sql LIKE '%t2%';
} {}
do_execsql_test alter-19.3 {
  SELECT name FROM sqlite_schema WHERE sql LIKE '%t3%' ORDER BY name;
} {r1 t3}


finish_test

Changes to test/alter3.test.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
9
10
11
12
13
14
15


16
17
18
19
20
21
22







-
-







#
#*************************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is testing that SQLite can handle a subtle 
# file format change that may be used in the future to implement
# "ALTER TABLE ... ADD COLUMN".
#
# $Id: alter3.test,v 1.11 2008/03/19 00:21:31 drh Exp $
#

set testdir [file dirname $argv0]

source $testdir/tester.tcl

# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
ifcapable !altertable {
50
51
52
53
54
55
56

57
58
59
60
61
62
63
64
65
48
49
50
51
52
53
54
55
56

57
58
59
60
61
62
63







+

-







# This procedure returns the value of the file-format in file 'test.db'.
# 
proc get_file_format {{fname test.db}} {
  return [hexio_get_int [hexio_read $fname 44 4]]
}

do_test alter3-1.1 {
  sqlite3_db_config db LEGACY_FILE_FORMAT 1
  execsql {
    PRAGMA legacy_file_format=ON;
    CREATE TABLE abc(a, b, c);
    SELECT sql FROM sqlite_master;
  }
} {{CREATE TABLE abc(a, b, c)}}
do_test alter3-1.2 {
  execsql {ALTER TABLE abc ADD d INTEGER;}
  execsql {
112
113
114
115
116
117
118

119
120
121
122
123
124
125
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124







+







    DROP TABLE t3; 
  }
} {}

do_test alter3-2.1 {
  execsql {
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES(1,2);
  }
  catchsql {
    ALTER TABLE t1 ADD c PRIMARY KEY;
  }
} {1 {Cannot add a PRIMARY KEY column}}
do_test alter3-2.2 {
  catchsql {
194
195
196
197
198
199
200

201
202
203
204
205
206
207
208
209
193
194
195
196
197
198
199
200
201

202
203
204
205
206
207
208







+

-







  } {11}
}

do_test alter3-4.1 {
  db close
  forcedelete test.db
  set ::DB [sqlite3 db test.db]
  sqlite3_db_config db LEGACY_FILE_FORMAT 1
  execsql {
    PRAGMA legacy_file_format=ON;
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES(1, 100);
    INSERT INTO t1 VALUES(2, 300);
    SELECT * FROM t1;
  }
} {1 100 2 300}
do_test alter3-4.1 {
389
390
391
392
393
394
395
396















































397
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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  list 
} {}
do_test alter3-8.2 {
  execsql {
    SELECT sql FROM sqlite_master WHERE name = 't4';
  }
} [list $::sql]

# 2021-07-20:  Add support for detecting CHECK and NOT NULL constraint
# violations in ALTER TABLE ADD COLUMN
#
reset_db
do_execsql_test alter3-9.1 {
  CREATE TABLE t1(a,b);
  INSERT INTO t1 VALUES(1, 2), ('null!',NULL), (3,4);
} {}
do_catchsql_test alter3-9.2 {
  ALTER TABLE t1 ADD COLUMN c CHECK(a!=1);
} {1 {CHECK constraint failed}}
do_catchsql_test alter3-9.3 {
  ALTER TABLE t1 ADD COLUMN c CHECK(a!=3);
} {1 {CHECK constraint failed}}
do_catchsql_test alter3-9.4 {
  ALTER TABLE t1 ADD COLUMN c CHECK(a!=2);
} {0 {}}
do_catchsql_test alter3-9.5 {
  ALTER TABLE t1 ADD COLUMN d AS (b+1) NOT NULL;
} {1 {NOT NULL constraint failed}}
do_catchsql_test alter3-9.6 {
  ALTER TABLE t1 ADD COLUMN d AS (b+1) NOT NULL CHECK(a!=1);
} {1 {CHECK constraint failed}}
do_catchsql_test alter3-9.7 {
  ALTER TABLE t1 ADD COLUMN d AS (b+1) NOT NULL CHECK(a!=3);
} {1 {NOT NULL constraint failed}}

do_execsql_test alter3-9.10 {
  CREATE TEMP TABLE t0(m,n);
  INSERT INTO t0 VALUES(1, 2), ('null!',NULL), (3,4);
  ATTACH ':memory:' AS aux1;
  CREATE TABLE aux1.t2(x,y);
  INSERT INTO t2 VALUES(1, 2), ('null!',NULL), (3,4);
} {}
do_catchsql_test alter3-9.11 {
  ALTER TABLE t0 ADD COLUMN xtra1 AS (n+1) NOT NULL CHECK(m!=1);
} {1 {CHECK constraint failed}}
do_catchsql_test alter3-9.12 {
  ALTER TABLE t0 ADD COLUMN xtra1 AS (n+1) NOT NULL CHECK(m!=3);
} {1 {NOT NULL constraint failed}}
do_catchsql_test alter3-9.13 {
  ALTER TABLE t2 ADD COLUMN xtra1 AS (y+1) NOT NULL CHECK(x!=1);
} {1 {CHECK constraint failed}}
do_catchsql_test alter3-9.14 {
  ALTER TABLE t2 ADD COLUMN xtra1 AS (y+1) NOT NULL CHECK(x!=3);
} {1 {NOT NULL constraint failed}}

finish_test

Changes to test/alter4.test.

119
120
121
122
123
124
125

126
127
128
129
130
131
132
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133







+







    DROP TABLE t3; 
  }
} {}

do_test alter4-2.1 {
  execsql {
    CREATE TABLE temp.t1(a, b);
    INSERT INTO t1 VALUES(1,2);
  }
  catchsql {
    ALTER TABLE t1 ADD c PRIMARY KEY;
  }
} {1 {Cannot add a PRIMARY KEY column}}
do_test alter4-2.2 {
  catchsql {
313
314
315
316
317
318
319
320

321
322

323
324
325
326
327

328
329

330
331
332
333
334
335
336
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);
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
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







+

-












+







# does not corrupt DESC indexes.
#
# Ticket https://www.sqlite.org/src/tktview/f68bf68513a1c
#
do_test alter4-10.1 {
  db close
  sqlite3 db :memory:
  sqlite3_db_config db LEGACY_FILE_FORMAT 1
  db eval {
    PRAGMA legacy_file_format=on;
    CREATE TABLE t1(a,b,c);
    CREATE INDEX t1a ON t1(a DESC);
    INSERT INTO t1 VALUES(1,2,3);
    INSERT INTO t1 VALUES(2,3,4);
    ALTER TABLE t1 ADD COLUMN d;
    PRAGMA integrity_check;
  }
} {ok}

reset_db
do_execsql_test alter4-11.0 {
  CREATE TABLE t1(c INTEGER PRIMARY KEY, d);
  INSERT INTO t1(c,d) VALUES(1,2);
  PRAGMA foreign_keys = on;
  ALTER TABLE t1 ADD COLUMN e;
}

do_execsql_test alter4-11.1 {
  ALTER TABLE t1 ADD COLUMN f REFERENCES t1;
}

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
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







+












+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



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_ALTER_TABLE main t2 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.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
9
10
11
12
13
14
15


16
17
18
19
20
21
22







-
-







#
#*************************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is testing that SQLite can handle a subtle 
# file format change that may be used in the future to implement
# "ALTER TABLE ... RENAME COLUMN ... TO".
#
# $Id: alter4.test,v 1.1 2009/02/02 18:03:22 drh Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix altercol

# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
ifcapable !altertable {
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
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







-
+

+







+

+




-
+


+

+







  DROP TRIGGER tr1;
  CREATE INDEX x1i ON x1(i);
  SELECT sql FROM sqlite_master WHERE name='x1i';
} {{CREATE INDEX x1i ON x1(i)}}

sqlite3_db_config db DEFENSIVE 0
do_execsql_test 13.1.4 {
  PRAGMA writable_schema = 1;
  PRAGMA writable_schema = ON;
  UPDATE sqlite_master SET sql = 'CREATE INDEX x1i ON x1(j)' WHERE name='x1i';
  PRAGMA writable_schema = OFF;
} {}

do_catchsql_test 13.1.5 {
  ALTER TABLE x1 RENAME COLUMN t TO ttt;
} {1 {error in index x1i: no such column: j}}

do_execsql_test 13.1.6 {
  PRAGMA writable_schema = ON;
  UPDATE sqlite_master SET sql = '' WHERE name='x1i';
  PRAGMA writable_schema = OFF;
} {}

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 {
  PRAGMA writable_schema = ON;
  DELETE FROM sqlite_master WHERE name = 'x1i';
  PRAGMA writable_schema = OFF;
}

do_execsql_test 13.2.0 {
  CREATE TABLE data(x UNIQUE, y, z);
}
foreach {tn trigger error} {
  1 {
614
615
616
617
618
619
620
621

622
623
624
625
626
627
628
617
618
619
620
621
622
623

624
625
626
627
628
629
630
631







-
+







    ALTER TABLE x1 RENAME COLUMN t TO ttt;
  } "1 {error in trigger tr1: $error}"
}

#-------------------------------------------------------------------------
# Passing invalid parameters directly to sqlite_rename_column().
#
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db
do_execsql_test 14.1 {
  CREATE TABLE ddd(sql, type, object, db, tbl, icol, znew, bquote);
  INSERT INTO ddd VALUES(
      'CREATE TABLE x1(i INTEGER, t TEXT)',
      'table', 'x1', 'main', 'x1', -1, 'zzz', 0
  ), (
      'CREATE TABLE x1(i INTEGER, t TEXT)',
637
638
639
640
641
642
643
644

645
646
647
648
649
650
651
640
641
642
643
644
645
646

647
648
649
650
651
652
653
654







-
+







} {}

do_execsql_test 14.2 {
  SELECT 
  sqlite_rename_column(sql, type, object, db, tbl, icol, znew, bquote, 0)
  FROM ddd;
} {{} {} {} {}}
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db

# If the INTERNAL_FUNCTIONS test-control is disabled (which is the default)
# then the sqlite_rename_table() SQL function is not accessible to
# ordinary SQL.
#
do_catchsql_test 14.3 {
  SELECT sqlite_rename_column(0,0,0,0,0,0,0,0,0);
774
775
776
777
778
779
780

781
782





















































































































































783
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
900
901
902
903
904
905
906
907
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







+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

do_execsql_test 19.1 {
  ALTER TABLE t1 RENAME a TO f;
  SELECT sql FROM sqlite_master WHERE name = 'v2';
} {
  {CREATE VIEW v2(e) AS SELECT coalesce(t2.c,t1.f) FROM t1, t2 WHERE t1.b=t2.d}
}

# 2019-01-08: https://www.sqlite.org/src/tktview/bc8d94f0fbd633fd9a051e3


#
# ALTER TABLE RENAME COLUMN does not work for tables that have redundant
# UNIQUE constraints.
#
sqlite3 db :memory:
do_execsql_test 20.100 {
  CREATE TABLE t1(aaa,b,c,UNIQUE(aaA),PRIMARY KEY(aAa),UNIQUE(aAA));
  ALTER TABLE t1 RENAME aaa TO bbb;
  SELECT sql FROM sqlite_master WHERE name='t1';
} {{CREATE TABLE t1(bbb,b,c,UNIQUE(bbb),PRIMARY KEY(bbb),UNIQUE(bbb))}}
do_execsql_test 20.105 {
  DROP TABLE t1;
  CREATE TABLE t1(aaa,b,c,UNIQUE(aaA),PRIMARY KEY(aAa),UNIQUE(aAA))WITHOUT ROWID;
  ALTER TABLE t1 RENAME aaa TO bbb;
  SELECT sql FROM sqlite_master WHERE name='t1';
} {{CREATE TABLE t1(bbb,b,c,UNIQUE(bbb),PRIMARY KEY(bbb),UNIQUE(bbb))WITHOUT ROWID}}
do_execsql_test 20.110 {
  DROP TABLE t1;
  CREATE TABLE t1(aa UNIQUE,bb UNIQUE,cc UNIQUE,UNIQUE(aA),PRIMARY KEY(bB),UNIQUE(cC));
  ALTER TABLE t1 RENAME aa TO xx;
  ALTER TABLE t1 RENAME bb TO yy;
  ALTER TABLE t1 RENAME cc TO zz;
  SELECT sql FROM sqlite_master WHERE name='t1';
} {{CREATE TABLE t1(xx UNIQUE,yy UNIQUE,zz UNIQUE,UNIQUE(xx),PRIMARY KEY(yy),UNIQUE(zz))}}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 21.0 {
  CREATE TABLE t1(a, b, c NOT NULL);
  CREATE TRIGGER tr1 AFTER INSERT ON t1 WHEN new.c IS NOT NULL BEGIN
    SELECT c NOT NULL FROM t1;
  END;
}

do_execsql_test 21.1 {
  ALTER TABLE t1 RENAME c TO d;
}

do_execsql_test 21.2 {
  SELECT sql FROM sqlite_schema WHERE name IS 'tr1'
} {{CREATE TRIGGER tr1 AFTER INSERT ON t1 WHEN new.d IS NOT NULL BEGIN
    SELECT d NOT NULL FROM t1;
  END}
}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 22.0 {
  CREATE TABLE t1(a, b);
  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
sqlite3_db_config db SQLITE_DBCONFIG_DQS_DDL 1
sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1
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)}}

# 2022-02-04
# Do not complain about syntax errors in the schema if
# in PRAGMA writable_schema=ON mode.
#
reset_db
do_execsql_test 23.0 {
  CREATE TABLE t1(a INT, b REAL, c TEXT, d BLOB, e ANY);
  CREATE INDEX t1abx ON t1(a, b, a+b) WHERE c IS NOT NULL;
  CREATE VIEW t2 AS SELECT a+10, b*5.0, xyz FROM t1; -- unknown column "xyz"
  CREATE TABLE schema_copy(name TEXT, sql TEXT);
  INSERT INTO schema_copy(name,sql) SELECT name, sql FROM sqlite_schema WHERE sql IS NOT NULL;
} {}
do_catchsql_test 23.1 {
  ALTER TABLE t1 RENAME COLUMN e TO eeee;
} {1 {error in view t2: no such column: xyz}}
do_execsql_test 23.2 {
  SELECT name, sql FROM sqlite_master
    EXCEPT SELECT name, sql FROM schema_copy;
} {}
do_execsql_test 23.3 {
  BEGIN;
  PRAGMA writable_schema=ON;
  ALTER TABLE t1 RENAME COLUMN e TO eeee;
  PRAGMA writable_schema=OFF;
  SELECT name FROM sqlite_master
     WHERE (name, sql) NOT IN (SELECT name, sql FROM schema_copy);
  ROLLBACK;
} {t1}
do_execsql_test 23.10 {
  DROP VIEW t2;
  CREATE TRIGGER r3 AFTER INSERT ON t1 BEGIN
    INSERT INTO t3(x,y) VALUES(new.a, new.b);
    INSERT INTO t4(p) VALUES(new.c);    -- no such table "t4"
  END;
  DELETE FROM schema_copy;
  INSERT INTO schema_copy(name,sql) SELECT name, sql FROM sqlite_schema WHERE sql IS NOT NULL;
} {}
do_catchsql_test 23.11 {
  ALTER TABLE t1 RENAME COLUMN e TO eeee;
} {1 {error in trigger r3: no such table: main.t3}}
do_execsql_test 23.12 {
  SELECT name, sql FROM sqlite_master
    EXCEPT SELECT name, sql FROM schema_copy;
} {}
do_execsql_test 23.13 {
  BEGIN;
  PRAGMA writable_schema=ON;
  ALTER TABLE t1 RENAME COLUMN e TO eeee;
  PRAGMA writable_schema=OFF;
  SELECT name FROM sqlite_master
     WHERE (name, sql) NOT IN (SELECT name, sql FROM schema_copy);
  ROLLBACK;
} {t1}
do_execsql_test 23.20 {
  CREATE TABLE t4(id INTEGER PRIMARY KEY, c1 INT, c2 INT);
  CREATE VIEW t4v1 AS SELECT id, c1, c99 FROM t4;
  DELETE FROM schema_copy;
  INSERT INTO schema_copy SELECT name, sql FROM sqlite_schema;
  BEGIN;
  PRAGMA writable_schema=ON;
  ALTER TABLE t4 RENAME to t4new;
  SELECT name FROM sqlite_schema WHERE (name,sql) NOT IN (SELECT * FROM schema_copy);
  ROLLBACK;
} {t4new}

finish_test

Added test/altercorrupt.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019-01-11
#
# 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
set testprefix altercorrupt

# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
ifcapable !altertable {
  finish_test
  return
}

database_may_be_corrupt

#--------------------------------------------------------------------------
reset_db
do_test 1.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
.open --hexdb
| size 24576 pagesize 4096 filename crash-685346d89b5e5f.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 06   .....@  ........
|     32: 00 00 63 00 00 05 f0 00 00 00 00 04 10 00 00 04   ..c.............
|     48: 00 00 00 00 00 00 0f f0 00 00 00 01 00 00 00 00   ................
|     64: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|     96: 00 00 00 00 0d 0f f8 00 05 0e cf 00 0f 79 0f d3   .............y..
|    112: 0f 2e 0e f3 0e cf 00 00 00 00 00 00 00 00 00 00   ................
|   3776: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 22   ................
|   3792: 05 06 17 11 11 01 31 74 61 62 6c 65 74 34 74 34   ......1tablet4t4
|   3808: 06 43 52 45 41 54 45 20 54 41 42 4c 45 20 74 34   .CREATE TABLE t4
|   3824: 28 7a 29 39 04 06 17 11 11 01 5f 74 61 62 6c 65   (z)9......_table
|   3840: 74 33 74 33 05 43 52 45 41 54 45 20 54 41 42 4c   t3t3.CREATE TABL
|   3856: 45 20 74 33 28 78 20 49 4e 54 45 47 45 52 20 50   E t3(x INTEGER P
|   3872: 52 49 4d 41 52 59 20 4b 45 59 2c 20 79 29 49 03   RIMARY KEY, y)I.
|   3888: 06 17 11 11 01 7f 74 61 62 6c 65 74 32 74 32 04   ......tablet2t2.
|   3904: 43 52 45 41 54 45 20 54 41 42 4c 45 20 74 32 28   CREATE TABLE t2(
|   3920: 61 2c 62 2c 63 20 50 52 49 4d 41 52 59 20 4b 45   a,b,c PRIMARY KE
|   3936: 59 2c 20 64 2c 20 65 2c 20 66 29 20 57 49 54 48   Y, d, e, f) WITH
|   3952: 4f 55 54 20 52 4f 57 49 44 58 03 07 17 11 11 01   OUT ROWIDX......
|   3968: 81 1b 74 61 62 6c 65 74 31 74 31 02 43 52 45 41   ..tablet1t1.CREA
|   3984: 54 45 20 54 41 42 4c 45 20 74 31 28 61 2c 62 2c   TE TABLE t1(a,b,
|   4000: 63 20 41 53 20 28 2d 62 29 20 56 49 52 54 55 41   c AS (-b) VIRTUA
|   4016: 4c 2c 64 20 43 48 45 43 4b 28 64 3e 35 29 2c 65   L,d CHECK(d>5),e
|   4032: 20 55 4e 49 51 55 45 2c 20 66 20 41 53 20 28 2b    UNIQUE, f AS (+
|   4048: 62 29 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 0a 0f 93 00 0f f6 0f eb 0f e0 0f d5   ................
|     16: 0f ca 0f 8f 0f b4 0f a9 0f 9e 0f 93 00 00 00 00   ................
|   3984: 00 00 00 09 0a 05 01 01 01 01 0a 64 6e 14 09 09   ...........dn...
|   4000: 05 01 01 01 01 09 5a 6d 12 09 08 05 01 01 01 01   ......Zm........
|   4016: 08 50 6c 10 09 07 05 01 01 01 01 07 46 6b 0e 09   .Pl.........Fk..
|   4032: 06 05 01 01 01 01 06 3c 6a 0c 09 05 05 01 01 01   .......<j.......
|   4048: 01 05 32 69 0a 09 04 05 01 01 01 01 04 28 68 08   ..2i.........(h.
|   4064: 09 03 05 01 01 01 01 03 1e 67 06 09 02 05 01 01   .........g......
|   4080: 01 01 02 14 66 04 08 01 05 09 01 01 01 0a 65 02   ....f.........e.
| page 3 offset 8192
|      0: 0a 00 00 00 0a 0f c5 00 0f fb 0f f5 0f ef 0f e9   ................
|     16: 0f e3 0f dd 0f d7 0f d1 0f cb 0f c5 00 00 00 00   ................
|   4032: 00 00 00 00 00 05 03 01 01 14 0a 05 03 01 01 12   ................
|   4048: 09 05 03 01 01 10 08 05 03 01 01 0e 07 05 03 01   ................
|   4064: 01 0c 06 05 03 01 01 0a 05 05 03 01 01 08 04 05   ................
|   4080: 03 01 01 06 03 05 03 01 01 04 02 04 03 01 09 02   ................
| page 4 offset 12288
|      0: 0a 00 00 00 0a 0f 75 00 0f 75 0f 83 0f 91 0f 9f   ......u..u......
|     16: 0f ad 0f bb 0f 00 00 00 00 00 00 00 00 00 00 00   ................
|   3952: 00 00 00 00 00 0d 07 01 01 01 01 01 01 9c 0a 64   ...............d
|   3968: 6e 14 64 0d 07 02 01 01 01 01 01 a6 09 5a 6d 12   n.d..........Zm.
|   3984: 5a 0d 07 01 01 01 01 01 01 b0 08 50 6c 10 50 0d   Z..........Pl.P.
|   4000: 07 01 01 01 01 01 01 ba 07 46 6b 0e 46 0d 07 01   .........Fk.F...
|   4016: 01 01 01 01 01 c4 06 3c 6a 0c 3c 0d 07 01 01 01   .......<j.<.....
|   4032: 01 01 01 ce 05 32 69 0a 32 0d 07 01 01 01 01 01   .....2i.2.......
|   4048: 01 d8 04 28 68 08 28 0d 07 01 01 01 01 01 01 e2   ...(h.(.........
|   4064: 03 1e 67 06 1e 0d 07 01 01 01 01 01 01 ec 02 14   ..g.............
|   4080: 66 04 14 0c 07 01 09 01 01 01 01 f6 0a 65 02 0a   f............e..
| page 5 offset 16384
|      0: 0d 00 00 00 03 0f e9 00 0f e9 0f fb 0f f6 00 00   ................
|     16: 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   4064: 00 00 00 00 00 00 00 00 00 03 ff ff ff ff ff ff   ................
|   4080: ff ff 9c 03 00 00 03 64 03 00 00 03 01 03 00 00   .......d........
| page 6 offset 20480
|      0: 0d 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00   ................
| end crash-685346d89b5e5f.db
}]} {}

do_catchsql_test 1.1 {
  ALTER TABLE t2 DROP COLUMN e;
  ALTER TABLE t1 DROP COLUMN f;
} {1 {database disk image is malformed}}


#--------------------------------------------------------------------------
reset_db
do_test 2.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
.open --hexdb
| size 24576 pagesize 4096 filename crash-0572db8f391431.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 06   .....@  ........
|     32: 00 00 63 00 10 05 f0 00 00 00 00 04 10 00 00 04   ..c.............
|     48: 00 00 00 00 00 00 0f f0 00 00 00 00 00 00 00 00   ................
|     96: 00 00 00 00 0d 0f f8 00 05 0e cf 00 0f 79 0f d3   .............y..
|    112: 0f 2e 0e f3 0e cf 00 00 00 00 00 00 00 00 00 00   ................
|   3776: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 22   ................
|   3792: 05 06 17 11 11 01 31 74 61 62 6c 65 74 34 74 34   ......1tablet4t4
|   3808: 06 43 52 45 41 54 45 20 54 41 42 4c 45 20 74 34   .CREATE TABLE t4
|   3824: 28 7a 29 39 04 06 17 11 11 01 5f 74 61 62 6c 65   (z)9......_table
|   3840: 74 33 74 33 05 43 52 45 41 54 45 20 54 41 42 4c   t3t3.CREATE TABL
|   3856: 45 20 74 33 28 78 20 49 4e 54 55 47 45 52 20 50   E t3(x INTUGER P
|   3872: 52 49 4d 41 52 59 20 4b 45 59 2c 20 79 29 49 03   RIMARY KEY, y)I.
|   3888: 06 17 11 11 01 7f 74 61 62 6c 65 74 32 74 32 04   ......tablet2t2.
|   3904: 43 52 45 41 54 45 20 54 41 42 4c 45 20 74 32 28   CREATE TABLE t2(
|   3920: 61 2c 62 2c 63 20 50 52 49 4d 41 52 59 20 4b 45   a,b,c PRIMARY KE
|   3936: 59 2c 20 64 2c 20 65 2c 20 66 29 20 57 49 54 48   Y, d, e, f) WITH
|   3952: 4f 55 54 20 52 4f 57 49 44 58 05 07 17 11 11 01   OUT ROWIDX......
|   3968: 81 1b 74 61 62 6c 65 74 31 74 31 02 43 52 45 41   ..tablet1t1.CREA
|   3984: 54 45 20 54 41 42 4c 45 20 74 31 28 61 2c 62 2c   TE TABLE t1(a,b,
|   4000: 63 20 41 53 20 28 2d 62 29 20 56 49 52 54 55 41   c AS (-b) VIRTUA
|   4016: 4c 2c 64 20 43 48 45 43 4b 28 64 3e 35 29 2c 65   L,d CHECK(d>5),e
|   4032: 20 55 4e 49 51 55 45 2c 20 66 20 41 53 20 28 2b    UNIQUE, f AS (+
|   4048: 62 29 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 84 31 03 01 00 00 08 00 00 00 00   _t1_1.1.........
| page 2 offset 4096
|      0: 0d 00 00 00 0a 0f 93 00 0f f6 0f eb 0f e0 0f d5   ................
|     16: 0f ca 0f 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   3984: 00 00 00 09 0a 05 01 01 01 01 0a 64 6e 14 09 09   ...........dn...
|   4000: 05 01 01 01 01 09 5a 6d 12 09 08 05 01 00 f1 01   ......Zm........
|   4016: 08 50 6c 10 09 07 05 01 01 01 01 07 46 6b 0e 09   .Pl.........Fk..
|   4032: 06 05 01 00 f1 01 06 3c 6a 0c 09 05 05 01 01 01   .......<j.......
|   4048: 01 05 32 69 0a 09 04 05 01 01 01 01 04 28 68 08   ..2i.........(h.
|   4064: 57 03 05 01 01 01 01 03 1e 67 06 09 02 05 01 01   W........g......
|   4080: 01 01 02 14 66 04 08 01 05 09 01 01 01 0a 65 02   ....f.........e.
| page 3 offset 8192
|      0: 09 ff ff ff fa 0f c5 00 0f fb 0f f5 0f ef 0f e9   ................
|     16: 0f e3 0f dd 0f d7 00 00 00 00 00 00 00 00 00 00   ................
|   4032: 00 00 00 00 00 05 03 01 01 14 0a 05 03 01 01 12   ................
|   4048: 09 05 03 01 01 10 08 05 03 01 01 0e 07 05 03 01   ................
|   4064: 01 0c 06 05 03 01 01 0a 05 05 03 01 01 08 04 05   ................
|   4080: 03 01 01 06 03 05 03 01 01 04 02 04 03 01 09 02   ................
| page 4 offset 12288
|      0: 0a 00 00 00 0a 0f 75 00 0f 75 0f 83 0f 91 0f 9f   ......u..u......
|     16: 0f ad 0f bb 0f 00 00 00 00 00 01 00 00 00 00 00   ................
|   3952: 00 00 00 00 00 0d 07 01 01 01 01 01 01 9c 0a 64   ...............d
|   3968: 6e 14 64 0d 07 02 01 01 01 01 01 a6 09 5a 6d 12   n.d..........Zm.
|   3984: 5a 0d 07 01 01 01 01 d4 01 b0 08 50 6c 10 50 0d   Z..........Pl.P.
|   4000: 07 01 01 01 01 01 01 ba 07 46 6b 0e 46 0d 07 00   .........Fk.F...
|   4016: 01 01 01 01 01 c4 06 3c 6a 0c 3c 0d 07 01 01 01   .......<j.<.....
|   4032: 01 01 01 ce 05 32 69 0a 32 0d 07 01 01 01 01 01   .....2i.2.......
|   4048: 01 d8 04 28 68 08 28 0d 07 01 01 01 01 01 01 e2   ...(h.(.........
|   4064: 03 1e 67 06 1e 0d 07 01 01 01 01 01 01 ec 02 14   ..g.............
|   4080: 66 04 14 0c 07 01 09 01 01 00 f1 f6 0a 65 02 0a   f............e..
| page 5 offset 16384
|      0: 0d 00 00 00 03 0f e9 00 0f e9 0f fb 0f f6 00 00   ................
|   4064: 00 00 00 00 00 00 00 00 00 03 ff ff ff ff ff ff   ................
|   4080: ff ff 9c 03 00 00 03 64 03 00 01 03 01 03 00 00   .......d........
| page 6 offset 20480
|      0: 0d 00 10 00 00 10 01 00 00 00 00 00 00 00 00 00   ................
| end crash-0572db8f391431.db
}]} {}

do_catchsql_test 2.1 {
  ALTER TABLE t1 DROP COLUMN a;
} {1 {database disk image is malformed}}

finish_test

Added test/alterdropcol.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2021 February 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.
#
#*************************************************************************
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix alterdropcol

# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
ifcapable !altertable {
  finish_test
  return
}

do_execsql_test 1.0 {
  CREATE TABLE t1(a, b, c);
  CREATE VIEW v1 AS SELECT * FROM t1;

  CREATE TABLE t2(x INTEGER PRIMARY KEY, y, z UNIQUE);
  CREATE INDEX t2y ON t2(y);

  CREATE TABLE t3(q, r, s);
  CREATE INDEX t3rs ON t3(r+s);
}

do_catchsql_test 1.1 {
  ALTER TABLE nosuch DROP COLUMN z;
} {1 {no such table: nosuch}}

do_catchsql_test 1.2 {
  ALTER TABLE v1 DROP COLUMN c;
} {1 {cannot drop column from view "v1"}}

ifcapable fts5 {
  do_execsql_test 1.3.1 {
    CREATE VIRTUAL TABLE ft1 USING fts5(one, two);
  }
  do_catchsql_test 1.3.2 {
    ALTER TABLE ft1 DROP COLUMN two;
  } {1 {cannot drop column from virtual table "ft1"}}
}

do_catchsql_test 1.4 {
  ALTER TABLE sqlite_schema DROP COLUMN sql;
} {1 {table sqlite_master may not be altered}}

do_catchsql_test 1.5 {
  ALTER TABLE t1 DROP COLUMN d;
} {1 {no such column: "d"}}

do_execsql_test 1.6.1 {
  ALTER TABLE t1 DROP COLUMN b;
}
do_execsql_test 1.6.2 {
  SELECT sql FROM sqlite_schema WHERE name = 't1'
} {{CREATE TABLE t1(a, c)}}

do_execsql_test 1.7.1 {
  ALTER TABLE t1 DROP COLUMN c;
}
do_execsql_test 1.7.2 {
  SELECT sql FROM sqlite_schema WHERE name = 't1'
} {{CREATE TABLE t1(a)}}

do_catchsql_test 1.7.3 {
  ALTER TABLE t1 DROP COLUMN a;
} {1 {cannot drop column "a": no other columns exist}}


do_catchsql_test 1.8 {
  ALTER TABLE t2 DROP COLUMN z
} {1 {cannot drop UNIQUE column: "z"}}

do_catchsql_test 1.9 {
  ALTER TABLE t2 DROP COLUMN x
} {1 {cannot drop PRIMARY KEY column: "x"}}

do_catchsql_test 1.10 {
  ALTER TABLE t2 DROP COLUMN y
} {1 {error in index t2y after drop column: no such column: y}}

do_catchsql_test 1.11 {
  ALTER TABLE t3 DROP COLUMN s
} {1 {error in index t3rs after drop column: no such column: s}}

#-------------------------------------------------------------------------

foreach {tn wo} {
  1 {}
  2 {WITHOUT ROWID}
} { eval [string map [list %TN% $tn %WO% $wo] {

  reset_db
  do_execsql_test 2.%TN%.0 {
    CREATE TABLE t1(x, y INTEGER PRIMARY KEY, z) %WO% ;
    INSERT INTO t1 VALUES(1, 2, 3);
    INSERT INTO t1 VALUES(4, 5, 6);
    INSERT INTO t1 VALUES(7, 8, 9);
  }
  
  do_execsql_test 2.%TN%.1 {
    ALTER TABLE t1 DROP COLUMN x;
    SELECT * FROM t1;
  } {
    2 3  5 6  8 9
  }
  do_execsql_test 2.%TN%.2 {
    ALTER TABLE t1 DROP COLUMN z;
    SELECT * FROM t1;
  } {
    2 5 8
  }
}]}

#-------------------------------------------------------------------------
reset_db

do_execsql_test 3.0 {
  CREATE TABLE t12(a, b, c, CHECK(c>10));
  CREATE TABLE t13(a, b, c CHECK(c>10));
}
do_catchsql_test 3.1 {
  ALTER TABLE t12 DROP COLUMN c;
} {1 {error in table t12 after drop column: no such column: c}}

do_catchsql_test 3.2 {
  ALTER TABLE t13 DROP COLUMN c;
} {0 {}}

#-------------------------------------------------------------------------
# Test that generated columns can be dropped. And that other columns from
# tables that contain generated columns can be dropped.
#
foreach {tn wo vs} {
  1 ""              ""
  2 ""              VIRTUAL
  3 ""              STORED
  4 "WITHOUT ROWID" STORED
  5 "WITHOUT ROWID" VIRTUAL
} {
  reset_db

  do_execsql_test 4.$tn.0 "
    CREATE TABLE 'my table'(a, b PRIMARY KEY, c AS (a+b) $vs, d) $wo
  "
  do_execsql_test 4.$tn.1 {
    INSERT INTO "my table"(a, b, d) VALUES(1, 2, 'hello');
    INSERT INTO "my table"(a, b, d) VALUES(3, 4, 'world');

    SELECT * FROM "my table"
  } {
    1 2 3 hello
    3 4 7 world
  }

  do_execsql_test 4.$tn.2 {
    ALTER TABLE "my table" DROP COLUMN c;
  }
  do_execsql_test 4.$tn.3 {
    SELECT * FROM "my table"
  } {
    1 2 hello
    3 4 world
  }
  
  do_execsql_test 4.$tn.4 "
    CREATE TABLE x1(a, b, c PRIMARY KEY, d AS (b+c) $vs, e) $wo
  "
  do_execsql_test 4.$tn.5 {
    INSERT INTO x1(a, b, c, e) VALUES(1, 2, 3, 4);
    INSERT INTO x1(a, b, c, e) VALUES(5, 6, 7, 8);
    INSERT INTO x1(a, b, c, e) VALUES(9, 10, 11, 12);
    SELECT * FROM x1;
  } {
    1 2 3 5 4
    5 6 7 13 8
    9 10 11 21 12
  }

  do_execsql_test 4.$tn.6 {
    ALTER TABLE x1 DROP COLUMN a
  }
  do_execsql_test 4.$tn.7 {
    SELECT * FROM x1
  } {
    2 3 5 4
    6 7 13 8
    10 11 21 12
  }
  do_execsql_test 4.$tn.8 {
    ALTER TABLE x1 DROP COLUMN e
  }
  do_execsql_test 4.$tn.9 {
    SELECT * FROM x1
  } {
    2 3 5
    6 7 13
    10 11 21
  }
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 5.0 {
  CREATE TABLE p1(a PRIMARY KEY, b UNIQUE);
  CREATE TABLE c1(x, y, z REFERENCES p1(c));
  CREATE TABLE c2(x, y, z, w REFERENCES p1(b));
}
do_execsql_test 5.1 {
  ALTER TABLE c1 DROP COLUMN z;
  ALTER TABLE c2 DROP COLUMN z;
  SELECT sql FROM sqlite_schema WHERE name IN ('c1', 'c2');
} {
  {CREATE TABLE c1(x, y)} 
  {CREATE TABLE c2(x, y, w REFERENCES p1(b))}
}

do_execsql_test 5.2.1 {
  CREATE VIEW v1 AS SELECT d, e FROM p1
}
do_catchsql_test 5.2.2 {
  ALTER TABLE c1 DROP COLUMN x
} {1 {error in view v1: no such column: d}}
do_execsql_test 5.3.1 {
  DROP VIEW v1;
  CREATE VIEW v1 AS SELECT x, y FROM c1;
}
do_catchsql_test 5.3.2 {
  ALTER TABLE c1 DROP COLUMN x
} {1 {error in view v1 after drop column: no such column: x}}

do_execsql_test 5.4.1 {
  CREATE TRIGGER tr AFTER INSERT ON c1 BEGIN
    INSERT INTO p1 VALUES(new.y, new.xyz);
  END;
}
do_catchsql_test 5.4.2 {
  ALTER TABLE c1 DROP COLUMN y
} {1 {error in trigger tr: no such column: new.xyz}}
do_execsql_test 5.5.1 {
  DROP TRIGGER tr;
  CREATE TRIGGER tr AFTER INSERT ON c1 BEGIN
    INSERT INTO p1 VALUES(new.y, new.z);
  END;
}
do_catchsql_test 5.5.2 {
  ALTER TABLE c1 DROP COLUMN y
} {1 {error in trigger tr: no such column: new.z}}

# 2021-03-06 dbsqlfuzz crash-419aa525df93db6e463772c686ac6da27b46da9e
reset_db
do_catchsql_test 6.0 {
  CREATE TABLE t1(a,b,c);
  CREATE TABLE t2(x,y,z);
  PRAGMA writable_schema=ON;
  UPDATE sqlite_schema SET sql='CREATE INDEX t1b ON t1(b)' WHERE name='t2';
  PRAGMA writable_schema=OFF;
  ALTER TABLE t2 DROP COLUMN z;
} {1 {database disk image is malformed}}
reset_db
do_catchsql_test 6.1 {
  CREATE TABLE t1(a,b,c);
  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

Added test/alterdropcol2.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2021 February 19
#
# 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
set testprefix alterdropcol2

# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
ifcapable !altertable {
  finish_test
  return
}

# EVIDENCE-OF: R-58318-35349 The DROP COLUMN syntax is used to remove an
# existing column from a table.
do_execsql_test 1.0 {
  CREATE TABLE t1(c, b, a, PRIMARY KEY(b, a)) WITHOUT ROWID;
  INSERT INTO t1 VALUES(1, 2, 3), (4, 5, 6);
}
do_execsql_test 1.1 {
  ALTER TABLE t1 DROP c;
}

# EVIDENCE-OF: The DROP COLUMN command removes the named column from the table,
# and also rewrites the entire table to purge the data associated with that
# column.  
do_execsql_test 1.2.1 {
  SELECT * FROM t1;
} {2 3   5 6}

do_execsql_test 1.2.2 {
  SELECT sql FROM sqlite_schema;
} {
  {CREATE TABLE t1(b, a, PRIMARY KEY(b, a)) WITHOUT ROWID}
}

proc do_atdc_error_test {tn schema atdc error} {
  reset_db
  execsql $schema
  uplevel [list do_catchsql_test $tn $atdc [list 1 [string trim $error]]]
}

#-------------------------------------------------------------------------
# Test cases 2.* attempt to verify the following:
#
# EVIDENCE-OF: R-24098-10282 The DROP COLUMN command only works if the column
# is not referenced by any other parts of the schema and is not a PRIMARY KEY
# and does not have a UNIQUE constraint.
#

# EVIDENCE-OF: R-52436-31752 The column is a PRIMARY KEY or part of one.
#
do_atdc_error_test 2.1.1 {
  CREATE TABLE x1(a PRIMARY KEY, b, c);
} { 
  ALTER TABLE x1 DROP COLUMN a 
} {
  cannot drop PRIMARY KEY column: "a"
}
do_atdc_error_test 2.1.2 {
  CREATE TABLE x1(a,b,c,d,e, PRIMARY KEY(b,c,d));
} { 
  ALTER TABLE x1 DROP COLUMN c
} {
  cannot drop PRIMARY KEY column: "c"
}

# EVIDENCE-OF: R-43412-16016 The column has a UNIQUE constraint.
#
do_atdc_error_test 2.2.1 {
  CREATE TABLE x1(a PRIMARY KEY, b, c UNIQUE);
} { 
  ALTER TABLE x1 DROP COLUMN c 
} {
  cannot drop UNIQUE column: "c"
}
do_atdc_error_test 2.2.2 {
  CREATE TABLE x1(a PRIMARY KEY, b, c, UNIQUE(b, c));
} { 
  ALTER TABLE x1 DROP COLUMN c 
} {
  error in table x1 after drop column: no such column: c
}

# EVIDENCE-OF: R-46731-08965 The column is indexed.
#
do_atdc_error_test 2.3.1 {
  CREATE TABLE 'one two'('x y', 'z 1', 'a b');
  CREATE INDEX idx ON 'one two'('z 1');
} { 
  ALTER TABLE 'one two' DROP COLUMN 'z 1' 
} {
  error in index idx after drop column: no such column: z 1
}
do_atdc_error_test 2.3.2 {
  CREATE TABLE x1(a, b, c);
  CREATE INDEX idx ON x1(a);
} { 
  ALTER TABLE x1 DROP COLUMN a;
} {
  error in index idx after drop column: no such column: a
}

# EVIDENCE-OF: R-46731-08965 The column is indexed.
#
do_atdc_error_test 2.4.1 {
  CREATE TABLE x1234(a, b, c PRIMARY KEY) WITHOUT ROWID;
  CREATE INDEX i1 ON x1234(b) WHERE ((a+5) % 10)==0;
} { 
  ALTER TABLE x1234 DROP a
} {
  error in index i1 after drop column: no such column: a
}

# EVIDENCE-OF: R-47838-03249 The column is named in a table or column
# CHECK constraint not associated with the column being dropped.
#
do_atdc_error_test 2.5.1 {
  CREATE TABLE x1234(a, b, c PRIMARY KEY, CHECK(((a+5)%10)!=0)) WITHOUT ROWID;
} { 
  ALTER TABLE x1234 DROP a
} {
  error in table x1234 after drop column: no such column: a
}

# EVIDENCE-OF: R-55640-01652 The column is used in a foreign key constraint.
#
do_atdc_error_test 2.6.1 {
  CREATE TABLE p1(x, y UNIQUE);
  CREATE TABLE c1(u, v, FOREIGN KEY (v) REFERENCES p1(y))
} { 
  ALTER TABLE c1 DROP v
} {
  error in table c1 after drop column: unknown column "v" in foreign key definition
}

# EVIDENCE-OF: R-20795-39479 The column is used in the expression of a 
# generated column.
do_atdc_error_test 2.7.1 {
  CREATE TABLE c1(u, v, w AS (u+v));
} { 
  ALTER TABLE c1 DROP v
} {
  error in table c1 after drop column: no such column: v
}
do_atdc_error_test 2.7.2 {
  CREATE TABLE c1(u, v, w AS (u+v) STORED);
} { 
  ALTER TABLE c1 DROP u
} {
  error in table c1 after drop column: no such column: u
}

# EVIDENCE-OF: R-01515-49025 The column appears in a trigger or view.
#
do_atdc_error_test 2.8.1 {
  CREATE TABLE log(l);
  CREATE TABLE c1(u, v, w);
  CREATE TRIGGER tr1 AFTER INSERT ON c1 BEGIN
    INSERT INTO log VALUES(new.w);
  END;
} { 
  ALTER TABLE c1 DROP w
} {
  error in trigger tr1 after drop column: no such column: new.w
}
do_atdc_error_test 2.8.2 {
  CREATE TABLE c1(u, v, w);
  CREATE VIEW v1 AS SELECT u, v, w FROM c1;
} { 
  ALTER TABLE c1 DROP w
} {
  error in view v1 after drop column: no such column: w
}
do_atdc_error_test 2.8.3 {
  CREATE TABLE c1(u, v, w);
  CREATE VIEW v1 AS SELECT * FROM c1 WHERE w IS NOT NULL;
} { 
  ALTER TABLE c1 DROP w
} {
  error in view v1 after drop column: no such column: w
}

#-------------------------------------------------------------------------
# Verify that a column that is part of a CHECK constraint may be dropped
# if the CHECK constraint was specified as part of the column definition.
#

# STALE-EVIDENCE: R-60924-11170 However, the column being deleted can be used in a
# column CHECK constraint because the column CHECK constraint is dropped
# together with the column itself.
do_execsql_test 3.0 {
  CREATE TABLE yyy(q, w, e CHECK (e > 0), r);
  INSERT INTO yyy VALUES(1,1,1,1), (2,2,2,2);

  CREATE TABLE zzz(q, w, e, r, CHECK (e > 0));
  INSERT INTO zzz VALUES(1,1,1,1), (2,2,2,2);
}
do_catchsql_test 3.1.1 {
  INSERT INTO yyy VALUES(0,0,0,0);
} {1 {CHECK constraint failed: e > 0}}
do_catchsql_test 3.1.2 {
  INSERT INTO yyy VALUES(0,0,0,0);
} {1 {CHECK constraint failed: e > 0}}

do_execsql_test 3.2.1 {
  ALTER TABLE yyy DROP e;
}
do_catchsql_test 3.2.2 {
  ALTER TABLE zzz DROP e;
} {1 {error in table zzz after drop column: no such column: e}}

finish_test

Added test/alterfault.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2021 November 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.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix alterfault

# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
ifcapable !altertable {
  finish_test
  return
}

do_execsql_test 1.0 {
  CREATE TABLE t1(a);                 
}
faultsim_save_and_close

do_faultsim_test 1.1 -faults oom* -prep {
  faultsim_restore_and_reopen
} -body {
  execsql {
    ALTER TABLE t1 ADD COLUMN b CHECK (a!=1)
  }
} -test {
  faultsim_test_result {0 {}}
}



finish_test

Changes to test/alterlegacy.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







-
+


















-
+







}

# Legacy behavior is to corrupt the schema in this case, as the table name in
# the CHECK constraint is incorrect after "t1" is renamed. This version is
# slightly different - it rejects the change and rolls back the transaction.
do_catchsql_test 1.2 {
  ALTER TABLE t1 RENAME TO t1new;
} {1 {no such column: t1.a}}
} {1 {error in table t1new after rename: no such column: t1.a}}

do_execsql_test 1.3 {
  CREATE TABLE t3(c, d);
  ALTER TABLE t3 RENAME TO t3new;
  DROP TABLE t3new;
}

do_execsql_test 1.4 {
  SELECT sql FROM sqlite_master
} {
  {CREATE TABLE t1(a, b, CHECK(t1.a != t1.b))}
  {CREATE TABLE t2(a, b)}
  {CREATE INDEX t2expr ON t2(a) WHERE t2.b>0}
}


do_catchsql_test 1.3 {
  ALTER TABLE t2 RENAME TO t2new;
} {1 {no such column: t2.b}}
} {1 {error in index t2expr after rename: no such column: t2.b}}
do_execsql_test 1.4 {
  SELECT sql FROM sqlite_master
} {
  {CREATE TABLE t1(a, b, CHECK(t1.a != t1.b))}
  {CREATE TABLE t2(a, b)}
  {CREATE INDEX t2expr ON t2(a) WHERE t2.b>0}
}

Changes to test/altermalloc2.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
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







+
+
+
+
+








-
+


















-
+

















-
+







  return
}

do_execsql_test 1.0 {
  CREATE TABLE t1(abcd, efgh);
}
faultsim_save_and_close

set ::TMPDBERROR [list 1 \
  {unable to open a temporary database file for storing temporary tables}
]


do_faultsim_test 1 -prep {
  faultsim_restore_and_reopen
} -body {
  execsql {
    ALTER TABLE t1 RENAME abcd TO dcba
  }
} -test {
  faultsim_test_result {0 {}}
  faultsim_test_result {0 {}} $::TMPDBERROR
}

catch {db close}
forcedelete test.db
sqlite3 db test.db
do_execsql_test 2.0 {
  PRAGMA encoding = 'utf-16';
  CREATE TABLE t1(abcd, efgh);
}
faultsim_save_and_close

do_faultsim_test 2 -prep {
  faultsim_restore_and_reopen
} -body {
  execsql {
    ALTER TABLE t1 RENAME abcd TO dcba
  }
} -test {
  faultsim_test_result {0 {}}
  faultsim_test_result {0 {}} $::TMPDBERROR
}


reset_db
do_execsql_test 3.0 {
  CREATE TABLE t1(abcd, efgh);
  CREATE VIEW v1 AS SELECT * FROM t1 WHERE abcd>efgh;
}
faultsim_save_and_close

do_faultsim_test 3 -prep {
  faultsim_restore_and_reopen
} -body {
  execsql {
    ALTER TABLE t1 RENAME abcd TO dcba
  }
} -test {
  faultsim_test_result {0 {}}
  faultsim_test_result {0 {}} $::TMPDBERROR
}

reset_db
do_execsql_test 4.0 {
  CREATE TABLE rr(a, b);
  CREATE VIEW vv AS SELECT * FROM rr;

91
92
93
94
95
96
97
98






















99
100
101
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







-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



  faultsim_restore_and_reopen
  execsql { SELECT * FROM sqlite_master }
} -body {
  execsql {
    ALTER TABLE rr RENAME a TO c;
  }
} -test {
  faultsim_test_result {0 {}} 
  faultsim_test_result {0 {}} $::TMPDBERROR
}

reset_db
do_execsql_test 5.0 {
  CREATE TABLE rr(a, b);
  CREATE VIEW vv AS SELECT * FROM (
    WITH abc(d, e) AS (SELECT * FROM rr)
    SELECT * FROM abc
  );
} {}

faultsim_save_and_close
do_faultsim_test 5 -faults oom-* -prep {
  faultsim_restore_and_reopen
  execsql { SELECT * FROM sqlite_master }
} -body {
  execsql {
    ALTER TABLE rr RENAME TO c;
  }
} -test {
  faultsim_test_result {0 {}} $::TMPDBERROR
}

finish_test

Added test/altermalloc3.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2021 February 18
#
# 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/malloc_common.tcl
set testprefix altermalloc3

# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
ifcapable !altertable {
  finish_test
  return
}


set ::TMPDBERROR [list 1 \
  {unable to open a temporary database file for storing temporary tables}
]

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 {}} $::TMPDBERROR
}


#-------------------------------------------------------------------------
# dbsqlfuzz e3dd84cda3848016a6a6024c7249d09bc2ef2615
#
reset_db
do_execsql_test 2.0 {
  CREATE TABLE t2(k,v);
  CREATE TRIGGER r2 AFTER INSERT ON t2 BEGIN
    UPDATE t2 SET (k,v)= (
       (WITH cte1(a) AS ( SELECT 1 FROM ( SELECT * FROM t2 ) )
       SELECT a FROM cte1
    ), 1);
  END;

  CREATE TRIGGER r1 AFTER INSERT ON t2 BEGIN
    UPDATE t2 SET k=1 FROM t2 AS one, t2 AS two NATURAL JOIN t2 AS three 
    WHERE one.k=two.v;
  END;
}

faultsim_save_and_close
faultsim_restore_and_reopen

do_execsql_test 2.1 {
  ALTER TABLE t2 RENAME TO t2x;
}

do_faultsim_test 2.2 -prep {
  faultsim_restore_and_reopen
  db eval { SELECT * FROM sqlite_master } 
} -body {
  execsql {
    ALTER TABLE t2 RENAME TO t2x;
  }
} -test {
  faultsim_test_result {0 {}} $::TMPDBERROR
}

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
112
113
114
115
116
117
118
119
120
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 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

# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
ifcapable !altertable {
  finish_test
  return
}


sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db
sqlite3_db_config db SQLITE_DBCONFIG_DQS_DDL 1
sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1

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
sqlite3_db_config db SQLITE_DBCONFIG_DQS_DDL 1
sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1
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.

236
237
238
239
240
241
242
243

244
245
246
247
248
249

250
251
252
253
254
255
256
236
237
238
239
240
241
242

243
244
245
246
247
248

249
250
251
252
253
254
255
256







-
+





-
+







    ), (
        'main', 'CREATE TABLE x1(i INTEGER, t TEXT)', NULL, 'eee', 0
    ), (
        'main', NULL, 'ddd', 'eee', 0
    );
  } {}
  
  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1
  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db
  do_execsql_test 7.2 {
    SELECT 
    sqlite_rename_table(db, 0, 0, sql, zOld, zNew, bTemp)
    FROM ddd;
  } {{} {} {}}
  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0
  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db
}

#-------------------------------------------------------------------------
#
reset_db
forcedelete test.db2
do_execsql_test 8.1 {
501
502
503
504
505
506
507


508


























































































































































































































































































































































































































































































509
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984







+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  SELECT * FROM x;
} {x x x}

do_execsql_test 15.5 {
  SELECT sql FROM sqlite_master WHERE name = 'y';
} {{CREATE VIEW y AS SELECT f2 AS f1 FROM x}}

#-------------------------------------------------------------------------
# Test that it is not possible to rename a shadow table in DEFENSIVE mode.

#
ifcapable fts3 {
  proc vtab_command {method args} {
    switch -- $method {
      xConnect {
        if {[info exists ::vtab_connect_sql]} {
          execsql $::vtab_connect_sql
        }
        return "CREATE TABLE t1(a, b, c)"
      }

      xBestIndex {
        set clist [lindex $args 0]
        if {[llength $clist]!=1} { error "unexpected constraint list" }
        catch { array unset C }
        array set C [lindex $clist 0]
        if {$C(usable)} {
          return "omit 0 cost 0 rows 1 idxnum 555 idxstr eq!"
        } else {
          return "cost 1000000 rows 0 idxnum 0 idxstr scan..."
        }
      }
    }

    return {}
  }

  register_tcl_module db

  sqlite3_db_config db DEFENSIVE 1

  do_execsql_test 16.0 {
    CREATE VIRTUAL TABLE y1 USING fts3;
    VACUUM;
  }

  do_catchsql_test 16.10 {
    INSERT INTO y1_segments VALUES(1, X'1234567890');
  } {1 {table y1_segments may not be modified}}

  do_catchsql_test 16.20 {
    DROP TABLE y1_segments;
  } {1 {table y1_segments may not be dropped}}

  do_catchsql_test 16.20 {
    ALTER TABLE y1_segments RENAME TO abc;
  } {1 {table y1_segments may not be altered}}
  sqlite3_db_config db DEFENSIVE 0
  do_catchsql_test 16.22 {
    ALTER TABLE y1_segments RENAME TO abc;
  } {0 {}}
  sqlite3_db_config db DEFENSIVE 1
  do_catchsql_test 16.23 {
    CREATE TABLE y1_segments AS SELECT * FROM abc;
  } {1 {object name reserved for internal use: y1_segments}}
  do_catchsql_test 16.24 {
    CREATE VIEW y1_segments AS SELECT * FROM abc;
  } {1 {object name reserved for internal use: y1_segments}}
  sqlite3_db_config db DEFENSIVE 0
  do_catchsql_test 16.25 {
    ALTER TABLE abc RENAME TO y1_segments;
  } {0 {}}
  sqlite3_db_config db DEFENSIVE 1

  do_execsql_test 16.30 {
    ALTER TABLE y1 RENAME TO z1;
  }

  do_execsql_test 16.40 {
    SELECT * FROM z1_segments;
  }
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 17.0 {
  CREATE TABLE sqlite1234 (id integer);
  ALTER TABLE sqlite1234 RENAME TO User;
  SELECT name, sql FROM sqlite_master WHERE sql IS NOT NULL;
} {
  User {CREATE TABLE "User" (id integer)}
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 18.1.0 {
  CREATE TABLE t0 (c0 INTEGER, PRIMARY KEY(c0)) WITHOUT ROWID;
}
do_execsql_test 18.1.1 {
  ALTER TABLE t0 RENAME COLUMN c0 TO c1;
}
do_execsql_test 18.1.2 {
  SELECT sql FROM sqlite_master;
} {{CREATE TABLE t0 (c1 INTEGER, PRIMARY KEY(c1)) WITHOUT ROWID}}

reset_db
do_execsql_test 18.2.0 {
  CREATE TABLE t0 (c0 INTEGER, PRIMARY KEY(c0));
}
do_execsql_test 18.2.1 {
  ALTER TABLE t0 RENAME COLUMN c0 TO c1;
}
do_execsql_test 18.2.2 {
  SELECT sql FROM sqlite_master;
} {{CREATE TABLE t0 (c1 INTEGER, PRIMARY KEY(c1))}}

# 2020-02-23 ticket f50af3e8a565776b
reset_db
do_execsql_test 19.100 {
  CREATE TABLE t1(x);
  CREATE VIEW t2 AS SELECT 1 FROM t1, (t1 AS a0, t1);
  ALTER TABLE t1 RENAME TO t3;
  SELECT sql FROM sqlite_master;
} {{CREATE TABLE "t3"(x)} {CREATE VIEW t2 AS SELECT 1 FROM "t3", ("t3" AS a0, "t3")}}
do_execsql_test 19.110 {
  INSERT INTO t3(x) VALUES(123);
  SELECT * FROM t2;
} {1}
do_execsql_test 19.120 {
  INSERT INTO t3(x) VALUES('xyz');
  SELECT * FROM t2;
} {1 1 1 1 1 1 1 1}

# Ticket 4722bdab08cb14
reset_db
do_execsql_test 20.0 {
  CREATE TABLE a(a);
  CREATE VIEW b AS SELECT(SELECT *FROM c JOIN a USING(d, a, a, a) JOIN a) IN();
}
do_execsql_test 20.1 {
  ALTER TABLE a RENAME a TO e;
} {}

reset_db
do_execsql_test 21.0 {
  CREATE TABLE a(b);
  CREATE VIEW c AS 
      SELECT NULL INTERSECT 
      SELECT NULL ORDER BY
      likelihood(NULL, (d, (SELECT c)));
} {}
do_catchsql_test 21.1 {
  SELECT likelihood(NULL, (d, (SELECT c)));
} {1 {second argument to likelihood() must be a constant between 0.0 and 1.0}}
do_catchsql_test 21.2 {
  SELECT * FROM c;
} {1 {1st ORDER BY term does not match any column in the result set}}

do_catchsql_test 21.3 {
  ALTER TABLE a RENAME TO e;
} {1 {error in view c: 1st ORDER BY term does not match any column in the result set}}

# After forum thread https://sqlite.org/forum/forumpost/ddbe1c7efa
# Ensure that PRAGMA schema_version=N causes a full schema reload.
#
reset_db
do_execsql_test 22.0 {
  CREATE TABLE t1(a INT, b TEXT NOT NULL);
  INSERT INTO t1 VALUES(1,2),('a','b');
  BEGIN;
  PRAGMA writable_schema=ON;
  UPDATE sqlite_schema SET sql='CREATE TABLE t1(a INT, b TEXT)' WHERE name LIKE 't1';
  PRAGMA schema_version=1234;
  COMMIT;
  PRAGMA integrity_check;
} {ok}
do_execsql_test 22.1 {
  ALTER TABLE t1 ADD COLUMN c INT DEFAULT 78;
  SELECT * FROM t1;
} {1 2 78 a b 78}

#-------------------------------------------------------------------------
reset_db
db collate compare64 compare64

do_execsql_test 23.1 {
  CREATE TABLE gigo(a text);
  CREATE TABLE idx(x text COLLATE compare64);
  CREATE VIEW v1 AS SELECT * FROM idx WHERE x='abc';
}
db close
sqlite3 db test.db

do_execsql_test 23.2 {
  alter table gigo rename to ggiiggoo;
  alter table idx rename to idx2;
}

do_execsql_test 23.3 {
  SELECT sql FROM sqlite_master;
} {
  {CREATE TABLE "ggiiggoo"(a text)} 
  {CREATE TABLE "idx2"(x text COLLATE compare64)}
  {CREATE VIEW v1 AS SELECT * FROM "idx2" WHERE x='abc'}
}

do_execsql_test 23.4 {
  ALTER TABLE idx2 RENAME x TO y;
  SELECT sql FROM sqlite_master;
} {
  {CREATE TABLE "ggiiggoo"(a text)} 
  {CREATE TABLE "idx2"(y text COLLATE compare64)}
  {CREATE VIEW v1 AS SELECT * FROM "idx2" WHERE y='abc'}
}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 24.1.0 {
  CREATE TABLE t1(a, b);
  CREATE TRIGGER AFTER INSERT ON t1 BEGIN
    INSERT INTO nosuchtable VALUES(new.a) ON CONFLICT(a) DO NOTHING;
  END;
}
do_catchsql_test 24.1.1 {
  ALTER TABLE t1 RENAME TO t2;
} {1 {error in trigger AFTER: no such table: main.nosuchtable}}

reset_db
do_execsql_test 24.2.0 {
  CREATE TABLE t1(a, b);
  CREATE TRIGGER AFTER INSERT ON t1 BEGIN
    INSERT INTO v1 VALUES(new.a) ON CONFLICT(a) DO NOTHING;
  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}}

#--------------------------------------------------------------------------
#
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}

#-------------------------------------------------------------------------
reset_db

do_execsql_test 27.1 {

 create table t_sa (
 c_muyat INTEGER NOT NULL,
 c_d4u TEXT 
 );

 create table t2 ( abc );

 CREATE TRIGGER trig AFTER DELETE ON t_sa
   BEGIN
   DELETE FROM t_sa WHERE (
       SELECT 123 FROM t2
       WINDOW oamat7fzf AS ( PARTITION BY t_sa.c_d4u )
   );
   END;
}

do_execsql_test 27.2 {
  alter table t_sa rename column c_muyat to c_dg;
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 29.1 {
  CREATE TABLE t1(a, b, c);
  INSERT INTO t1 VALUES('a', 'b', 'c');

  CREATE VIEW v0 AS
    WITH p AS ( SELECT 1 FROM t1 ),
         g AS ( SELECT 1 FROM p, t1 )
    SELECT 1 FROM g;
}

do_execsql_test 29.2 {
  SELECT * FROM v0
} 1

do_execsql_test 29.2 {
  ALTER TABLE t1 RENAME TO t2
} 

do_execsql_test 29.3 {
  SELECT sql FROM sqlite_schema WHERE name='v0'
} {{CREATE VIEW v0 AS
    WITH p AS ( SELECT 1 FROM "t2" ),
         g AS ( SELECT 1 FROM p, "t2" )
    SELECT 1 FROM g}}

do_execsql_test 29.4 {
  CREATE VIEW v2 AS
    WITH p AS ( SELECT 1 FROM t2 ),
         g AS ( SELECT 1 FROM (
           WITH i AS (SELECT 1 FROM p, t2)
           SELECT * FROM i
         )
    )
    SELECT 1 FROM g;
}

do_execsql_test 29.4 {
    SELECT * FROM v2;
} 1

do_execsql_test 29.5 {
  ALTER TABLE t2 RENAME TO t3;
} 

do_execsql_test 29.5 {
  SELECT sql FROM sqlite_schema WHERE name='v2'
} {{CREATE VIEW v2 AS
    WITH p AS ( SELECT 1 FROM "t3" ),
         g AS ( SELECT 1 FROM (
           WITH i AS (SELECT 1 FROM p, "t3")
           SELECT * FROM i
         )
    )
    SELECT 1 FROM g}}


#-------------------------------------------------------------------------
reset_db
do_execsql_test 28.1 {
  CREATE TABLE t1(a);
  CREATE TABLE t2(b,c);
  CREATE TABLE t4(b,c);
  INSERT INTO t2 VALUES(1,2),(1,3),(2,5);
  INSERT INTO t4 VALUES(1,2),(1,3),(2,5);

  CREATE VIEW v3 AS 
    WITH RECURSIVE t3(x,y,z) AS (
        SELECT b,c,NULL FROM t4
        UNION
        SELECT x,y,NULL FROM t3, t2
    )
  SELECT * FROM t3 AS xyz;
}

do_execsql_test 28.2 {
  SELECT * FROM v3
} {
  1 2 {} 1 3 {} 2 5 {}
}

do_execsql_test 28.3 {
  ALTER TABLE t1 RENAME a TO a2; -- fails in v3
} 

do_execsql_test 28.4 {
  ALTER TABLE t2 RENAME TO t5;
} 

do_execsql_test 28.5 {
  SELECT sql FROM sqlite_schema WHERE name='v3'
} {{CREATE VIEW v3 AS 
    WITH RECURSIVE t3(x,y,z) AS (
        SELECT b,c,NULL FROM t4
        UNION
        SELECT x,y,NULL FROM t3, "t5"
    )
  SELECT * FROM t3 AS xyz}}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 30.0 {
  CREATE TABLE t1(a,b,c,d,e,f);
  CREATE TABLE t2(a,b,c);
  CREATE INDEX t1abc ON t1(a,b,c+d+e);
  CREATE VIEW v1(x,y) AS 
    SELECT t1.b,t2.b FROM t1,t2 WHERE t1.a=t2.a 
      GROUP BY 1 HAVING t2.c NOT NULL LIMIT 10;
  CREATE TRIGGER r1 AFTER INSERT ON t1 WHEN 'no' NOT NULL BEGIN
    INSERT INTO t2(a,a,b,c) VALUES(new.b,new.a,new.c-7);
    WITH c1(x) AS (
      VALUES(0) 
        UNION ALL 
      SELECT current_time+x FROM c1 WHERE x 
        UNION ALL 
      SELECT 1+x FROM c1 WHERE x<1
    ), c2(x) AS (VALUES(0),(1))
    SELECT * FROM c1 AS x1, c2 AS x2, (
      SELECT x+1 FROM c1 WHERE x IS NOT TRUE 
        UNION ALL 
      SELECT 1+x FROM c1 WHERE 1<x
    ) AS x3, c2 x5;
  END;
}

do_execsql_test 30.1 {
  ALTER TABLE t1 RENAME TO t1x;
}

do_execsql_test 30.2 {
  SELECT sql FROM sqlite_schema ORDER BY rowid
} {
  {CREATE TABLE "t1x"(a,b,c,d,e,f)} 
  {CREATE TABLE t2(a,b,c)}
  {CREATE INDEX t1abc ON "t1x"(a,b,c+d+e)}
  {CREATE VIEW v1(x,y) AS 
    SELECT "t1x".b,t2.b FROM "t1x",t2 WHERE "t1x".a=t2.a 
      GROUP BY 1 HAVING t2.c NOT NULL LIMIT 10}
  {CREATE TRIGGER r1 AFTER INSERT ON "t1x" WHEN 'no' NOT NULL BEGIN
    INSERT INTO t2(a,a,b,c) VALUES(new.b,new.a,new.c-7);
    WITH c1(x) AS (
      VALUES(0) 
        UNION ALL 
      SELECT current_time+x FROM c1 WHERE x 
        UNION ALL 
      SELECT 1+x FROM c1 WHERE x<1
    ), c2(x) AS (VALUES(0),(1))
    SELECT * FROM c1 AS x1, c2 AS x2, (
      SELECT x+1 FROM c1 WHERE x IS NOT TRUE 
        UNION ALL 
      SELECT 1+x FROM c1 WHERE 1<x
    ) AS x3, c2 x5;
  END}
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 31.0 {
  CREATE TABLE t1(q);
  CREATE VIEW vvv AS WITH x AS (WITH y AS (SELECT * FROM x) SELECT 1) SELECT 1;
}

do_execsql_test 31.1 {
  SELECT * FROM vvv;
} {1}

do_execsql_test 31.2 {
  ALTER TABLE t1 RENAME TO t1x;
}

do_execsql_test 31.3 {
  ALTER TABLE t1x RENAME q TO x;
}

# 2021-07-02 OSSFuzz https://oss-fuzz.com/testcase-detail/5517690440646656
# Bad assert() statement
#
reset_db
do_catchsql_test 32.0 {
  CREATE TABLE t1(x);
  CREATE TRIGGER r1 BEFORE INSERT ON t1 BEGIN 
    UPDATE t1 SET x=x FROM (SELECT*);
  END;
  ALTER TABLE t1 RENAME TO x;
} {1 {error in trigger r1: no tables specified}}

finish_test

Changes to test/altertab2.test.

138
139
140
141
142
143
144


























































































































































































































145
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


  do_execsql_test 3.$tn.4 {
    ALTER TABLE log_entry RENAME col1 TO newname;
    SELECT sql FROM sqlite_master;
  } $expect
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 4.0 {
  CREATE TABLE t1(a,b,c,d,e,f);
  CREATE TRIGGER r1 AFTER INSERT ON t1 WHEN new.a NOT NULL BEGIN
    UPDATE t1 SET (c,d)=(a,b);
  END;
}

do_execsql_test 4.1 {
  ALTER TABLE t1 RENAME TO t1x;
  SELECT sql FROM sqlite_master WHERE type = 'trigger';
} {
{CREATE TRIGGER r1 AFTER INSERT ON "t1x" WHEN new.a NOT NULL BEGIN
    UPDATE "t1x" SET (c,d)=(a,b);
  END}
}

do_execsql_test 4.2 {
  ALTER TABLE t1x RENAME a TO aaa;
  SELECT sql FROM sqlite_master WHERE type = 'trigger';
} {
{CREATE TRIGGER r1 AFTER INSERT ON "t1x" WHEN new.aaa NOT NULL BEGIN
    UPDATE "t1x" SET (c,d)=(aaa,b);
  END}
}

do_execsql_test 4.3 {
  ALTER TABLE t1x RENAME d TO ddd;
  SELECT sql FROM sqlite_master WHERE type = 'trigger';
} {
{CREATE TRIGGER r1 AFTER INSERT ON "t1x" WHEN new.aaa NOT NULL BEGIN
    UPDATE "t1x" SET (c,ddd)=(aaa,b);
  END}
}

#-------------------------------------------------------------------------
ifcapable windowfunc {
do_execsql_test 5.0 {
  CREATE TABLE t2(a);
  CREATE TRIGGER r2 AFTER INSERT ON t2 WHEN new.a NOT NULL BEGIN
    SELECT a, sum(a) OVER w1 FROM t2
      WINDOW w1 AS (
        PARTITION BY a ORDER BY a 
        ROWS BETWEEN 2 PRECEDING AND 3 FOLLOWING
      ),
      w2 AS (
        PARTITION BY a
        ORDER BY rowid ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
      );
  END;
} {}

do_execsql_test 5.0.1 {
  INSERT INTO t2 VALUES(1);
} {}

do_execsql_test 5.1 {
  ALTER TABLE t2 RENAME TO t2x;
  SELECT sql FROM sqlite_master WHERE name = 'r2';
} {
  {CREATE TRIGGER r2 AFTER INSERT ON "t2x" WHEN new.a NOT NULL BEGIN
    SELECT a, sum(a) OVER w1 FROM "t2x"
      WINDOW w1 AS (
        PARTITION BY a ORDER BY a 
        ROWS BETWEEN 2 PRECEDING AND 3 FOLLOWING
      ),
      w2 AS (
        PARTITION BY a
        ORDER BY rowid ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
      );
  END}
}

do_execsql_test 5.2 {
  ALTER TABLE t2x RENAME a TO aaaa;
  SELECT sql FROM sqlite_master WHERE name = 'r2';
} {
  {CREATE TRIGGER r2 AFTER INSERT ON "t2x" WHEN new.aaaa NOT NULL BEGIN
    SELECT aaaa, sum(aaaa) OVER w1 FROM "t2x"
      WINDOW w1 AS (
        PARTITION BY aaaa ORDER BY aaaa 
        ROWS BETWEEN 2 PRECEDING AND 3 FOLLOWING
      ),
      w2 AS (
        PARTITION BY aaaa
        ORDER BY rowid ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
      );
  END}
}

do_execsql_test 5.3 {
  INSERT INTO t2x VALUES(1);
} {}
} ;# windowfunc

#-------------------------------------------------------------------------

do_execsql_test 6.0 {
  CREATE TABLE t3(a,b,c,d);
  CREATE TRIGGER r3 AFTER INSERT ON t3 WHEN new.a NOT NULL BEGIN
    SELECT a,b,c FROM t3 EXCEPT SELECT a,b,c FROM t3 ORDER BY a;
    SELECT rowid, * FROM t3;
  END;
} {}

do_execsql_test 6.1 {
  ALTER TABLE t3 RENAME TO t3x;
  SELECT sql FROM sqlite_master WHERE name = 'r3';
} {
  {CREATE TRIGGER r3 AFTER INSERT ON "t3x" WHEN new.a NOT NULL BEGIN
    SELECT a,b,c FROM "t3x" EXCEPT SELECT a,b,c FROM "t3x" ORDER BY a;
    SELECT rowid, * FROM "t3x";
  END}
}

do_execsql_test 6.2 {
  ALTER TABLE t3x RENAME a TO abcd;
  SELECT sql FROM sqlite_master WHERE name = 'r3';
} {
  {CREATE TRIGGER r3 AFTER INSERT ON "t3x" WHEN new.abcd NOT NULL BEGIN
    SELECT abcd,b,c FROM "t3x" EXCEPT SELECT abcd,b,c FROM "t3x" ORDER BY abcd;
    SELECT rowid, * FROM "t3x";
  END}
}

#-------------------------------------------------------------------------
reset_db

do_execsql_test 7.0 {
  CREATE TABLE t1(a,b,c,d,e,f);
  INSERT INTO t1 VALUES(1,2,3,4,5,6);
  CREATE TABLE t2(x,y,z);
}

do_execsql_test 7.1 {
  SELECT a,b,c FROM t1 UNION SELECT d,e,f FROM t1 ORDER BY b,c;
} {1 2 3 4 5 6}

do_execsql_test 7.2 {
  CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
    INSERT INTO t2
    SELECT a,b,c FROM t1 UNION SELECT d,e,f FROM t1 ORDER BY b,c;
  END;
  INSERT INTO t1 VALUES(2,3,4,5,6,7);
  SELECT * FROM t2;
} {1 2 3  2 3 4  4 5 6  5 6 7}

do_execsql_test 7.3 {
  ALTER TABLE t1 RENAME TO xyzzy;
  SELECT sql FROM sqlite_master WHERE name='r1'
} {
  {CREATE TRIGGER r1 AFTER INSERT ON "xyzzy" BEGIN
    INSERT INTO t2
    SELECT a,b,c FROM "xyzzy" UNION SELECT d,e,f FROM "xyzzy" ORDER BY b,c;
  END}
}

do_execsql_test 7.3 {
  ALTER TABLE xyzzy RENAME c TO ccc;
  SELECT sql FROM sqlite_master WHERE name='r1'
} {
  {CREATE TRIGGER r1 AFTER INSERT ON "xyzzy" BEGIN
    INSERT INTO t2
    SELECT a,b,ccc FROM "xyzzy" UNION SELECT d,e,f FROM "xyzzy" ORDER BY b,ccc;
  END}
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 8.0 {
  CREATE TABLE t1(a, b, c); 
  CREATE TABLE t2(a, b, c); 
  CREATE TABLE t3(d, e, f);
  CREATE VIEW v1 AS SELECT * FROM t1;
  CREATE TRIGGER tr AFTER INSERT ON t3 BEGIN
    UPDATE t2 SET a = new.d;
    SELECT a, b, c FROM v1;
  END;
}

do_execsql_test 8.1 {
  INSERT INTO t3 VALUES(1, 2, 3);
}

# The following ALTER TABLE fails as if column "t1.a" is renamed the "a"
# in the "SELECT a, b, c FROM v1" within the trigger can no longer be
# resolved. But at one point there was a bug allowing the ALTER TABLE
# succeed. Which meant the subsequent INSERT statement would fail.
do_catchsql_test 8.2 {
  ALTER TABLE t1 RENAME a TO aaa;
} {1 {error in trigger tr after rename: no such column: a}}
do_execsql_test 8.3 {
  INSERT INTO t3 VALUES(4, 5, 6);
}

do_execsql_test 8.4 {
  CREATE TABLE t4(a, b);
  CREATE VIEW v4 AS SELECT * FROM t4 WHERE (a=1 AND 0) OR b=2;
}

# Branches of an expression tree that are optimized out by the AND 
# optimization are renamed.
#
do_execsql_test 8.5 {
  ALTER TABLE t4 RENAME a TO c;
  SELECT sql FROM sqlite_master WHERE name = 'v4'
} {{CREATE VIEW v4 AS SELECT * FROM t4 WHERE (c=1 AND 0) OR b=2}}

# 2019-06-10 https://www.sqlite.org/src/info/533010b8cacebe82
reset_db
do_catchsql_test 8.6 {
  CREATE TABLE t0(c0);
  CREATE INDEX i0 ON t0(likelihood(1,2) AND 0);
  ALTER TABLE t0 RENAME TO t1;
  SELECT sql FROM sqlite_master WHERE name='i0';
} {1 {error in index i0: second argument to likelihood() must be a constant between 0.0 and 1.0}}

finish_test

Added test/altertab3.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
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019 January 23
#
# 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
set testprefix altertab3

# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
ifcapable !altertable {
  finish_test
  return
}

ifcapable windowfunc {
do_execsql_test 1.0 {
  CREATE TABLE t1(a, b);
  CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
    SELECT sum(b) OVER w FROM t1 WINDOW w AS (ORDER BY a);
  END;
}

do_execsql_test 1.1 {
  ALTER TABLE t1 RENAME a TO aaa;
}

do_execsql_test 1.2 {
  SELECT sql FROM sqlite_master WHERE name='tr1'
} {{CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
    SELECT sum(b) OVER w FROM t1 WINDOW w AS (ORDER BY aaa);
  END}}

do_execsql_test 1.3 {
  INSERT INTO t1 VALUES(1, 2);
}
} ;# windowfunc

#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.0 {
  CREATE TABLE t1(a,b,c);
  CREATE TABLE t2(a,b,c);
  CREATE TRIGGER r1 AFTER INSERT ON t1 WHEN new.a NOT NULL BEGIN
    SELECT a,b, a name FROM t1 
      INTERSECT 
    SELECT a,b,c FROM t1 WHERE b>='d' ORDER BY name;
    SELECT new.c;
  END;
}

do_execsql_test 2.1 {
  ALTER TABLE t1 RENAME TO t1x;
  SELECT sql FROM sqlite_master WHERE name = 'r1';
} {{CREATE TRIGGER r1 AFTER INSERT ON "t1x" WHEN new.a NOT NULL BEGIN
    SELECT a,b, a name FROM "t1x" 
      INTERSECT 
    SELECT a,b,c FROM "t1x" WHERE b>='d' ORDER BY name;
    SELECT new.c;
  END}}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 3.0 {
  CREATE TABLE t1(a, b, c, d);
  CREATE VIEW v1 AS SELECT * FROM t1 WHERE a=1 OR (b IN ());
}

do_execsql_test 3.1 {
  ALTER TABLE t1 RENAME b TO bbb;
}

do_execsql_test 3.2 {
  SELECT sql FROM sqlite_master WHERE name = 'v1'
} {{CREATE VIEW v1 AS SELECT * FROM t1 WHERE a=1 OR (b IN ())}}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 4.0 {
  CREATE TABLE t1(a, b);
  CREATE TABLE t3(e, f);
  CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
    INSERT INTO t2 VALUES(new.a, new.b);
  END;
}

do_catchsql_test 4.1.2 {
  BEGIN;
    ALTER TABLE t3 RENAME TO t4;
} {1 {error in trigger tr1: no such table: main.t2}}
do_execsql_test 4.1.2 {
  COMMIT;
}
do_execsql_test 4.1.3 {
  SELECT type, name, tbl_name, sql 
  FROM sqlite_master WHERE type='table' AND name!='t1';
} {table t3 t3 {CREATE TABLE t3(e, f)}}


do_catchsql_test 4.2.1 {
  BEGIN;
    ALTER TABLE t3 RENAME e TO eee;
} {1 {error in trigger tr1: no such table: main.t2}}
do_execsql_test 4.2.2 {
  COMMIT;
}
do_execsql_test 4.2.3 {
  SELECT type, name, tbl_name, sql 
  FROM sqlite_master WHERE type='table' AND name!='t1';
} {table t3 t3 {CREATE TABLE t3(e, f)}}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 5.0 {
  CREATE TABLE t1 (
      c1 integer, c2, PRIMARY KEY(c1 collate rtrim),
      UNIQUE(c2)
  )
}
do_execsql_test 5.1 {
  ALTER TABLE t1 RENAME c1 TO c3;
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 6.0 {
  CREATE TEMPORARY TABLE Table0 (
    Col0 INTEGER, 
    PRIMARY KEY(Col0 COLLATE RTRIM), 
    FOREIGN KEY (Col0) REFERENCES Table0
  );
}

do_execsql_test 6.1 {
  ALTER TABLE Table0 RENAME Col0 TO Col0;
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 7.1.0 {
  CREATE TABLE t1(a,b,c);
  CREATE TRIGGER AFTER INSERT ON t1 BEGIN
    SELECT a, rank() OVER w1 FROM t1
    WINDOW w1 AS (PARTITION BY b, percent_rank() OVER w1);
  END;
}

do_execsql_test 7.1.2 {
  ALTER TABLE t1 RENAME TO t1x;
  SELECT sql FROM sqlite_master;
} {
  {CREATE TABLE "t1x"(a,b,c)}
  {CREATE TRIGGER AFTER INSERT ON "t1x" BEGIN
    SELECT a, rank() OVER w1 FROM "t1x"
    WINDOW w1 AS (PARTITION BY b, percent_rank() OVER w1);
  END}
}

do_execsql_test 7.2.1 {
  DROP TRIGGER after;
  CREATE TRIGGER AFTER INSERT ON t1x BEGIN
    SELECT a, rank() OVER w1 FROM t1x
    WINDOW w1 AS (PARTITION BY b, percent_rank() OVER w1 ORDER BY d);
  END;
}

do_catchsql_test 7.2.2 {
  ALTER TABLE t1x RENAME TO t1;
} {1 {error in trigger AFTER: no such column: d}}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 8.0 {
  CREATE TABLE t0(c0);
  CREATE INDEX i0 ON t0('1' IN ());
}
do_execsql_test 8.1 {
  ALTER TABLE t0 RENAME TO t1;
  SELECT sql FROM sqlite_master;
} {
  {CREATE TABLE "t1"(c0)}
  {CREATE INDEX i0 ON "t1"('1' IN ())}
}
do_execsql_test 8.2.1 {
  CREATE TABLE t2 (c0);
  CREATE INDEX i2 ON t2((LIKELIHOOD(c0, 100) IN ()));
  ALTER TABLE t2 RENAME COLUMN c0 TO c1;
}
do_execsql_test 8.2.2 {
  SELECT sql FROM sqlite_master WHERE tbl_name = 't2';
} {
  {CREATE TABLE t2 (c1)} 
  {CREATE INDEX i2 ON t2((LIKELIHOOD(c0, 100) IN ()))}
}
do_test 8.2.3 {
  sqlite3 db2 test.db
  db2 eval { INSERT INTO t2 VALUES (1), (2), (3) }
  db close
} {}
db2 close

#-------------------------------------------------------------------------
reset_db
do_execsql_test 9.1 {
  CREATE TABLE t1(a,b,c);
  CREATE TRIGGER AFTER INSERT ON t1 WHEN new.a NOT NULL BEGIN
    SELECT true WHERE (SELECT a, b FROM (t1)) IN ();
  END;
}
do_execsql_test 9.2 {
  ALTER TABLE t1 RENAME TO t1x;
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 10.1 {
  CREATE TABLE t1(a, b, c);
  CREATE TABLE t2(a, b, c);
  CREATE VIEW v1 AS SELECT * FROM t1 WHERE (
    SELECT t1.a FROM t1, t2
  ) IN () OR t1.a=5;
}

do_execsql_test 10.2 {
  ALTER TABLE t2 RENAME TO t3;
  SELECT sql FROM sqlite_master WHERE name='v1';
} {
  {CREATE VIEW v1 AS SELECT * FROM t1 WHERE (
    SELECT t1.a FROM t1, t2
  ) IN () OR t1.a=5}
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 11.1 {
  CREATE TABLE t1(
      a,b,c,d,e,f,g,h,j,jj,jjb,k,aa,bb,cc,dd,ee DEFAULT 3.14,
      ff DEFAULT('hiccup'),Wg NOD NULL DEFAULT(false)
  );

  CREATE TRIGGER b AFTER INSERT ON t1 WHEN new.a BEGIN
    SELECT a, sum() w3 FROM t1 
    WINDOW b AS (ORDER BY NOT EXISTS(SELECT 1 FROM abc));
  END;
}

do_catchsql_test 11.2 {
  ALTER TABLE t1 RENAME TO t1x;
} {1 {error in trigger b: no such table: main.abc}}

do_execsql_test 11.3 {
  DROP TRIGGER b;
  CREATE TRIGGER b AFTER INSERT ON t1 WHEN new.a BEGIN
    SELECT a, sum() w3 FROM t1 
    WINDOW b AS (ORDER BY NOT EXISTS(SELECT 1 FROM t1));
  END;
} {}

do_execsql_test 11.4 {
  ALTER TABLE t1 RENAME TO t1x;
  SELECT sql FROM sqlite_master WHERE name = 'b';
} {
{CREATE TRIGGER b AFTER INSERT ON "t1x" WHEN new.a BEGIN
    SELECT a, sum() w3 FROM "t1x" 
    WINDOW b AS (ORDER BY NOT EXISTS(SELECT 1 FROM "t1x"));
  END}
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 12.1 {
CREATE TABLE t1(a,b,c,d,e,f,g,h,j,jj,Zjj,k,aQ,bb,cc,dd,ee DEFAULT 3.14,
ff DEFAULT('hiccup'),gg NOD NULL DEFAULT(false));
CREATE TRIGGER AFTER INSERT ON t1 WHEN new.a NOT NULL BEGIN

SELECT b () OVER , dense_rank() OVER d, d () OVER w1
FROM t1
WINDOW
w1 AS
( w1 ORDER BY d
ROWS BETWEEN 2 NOT IN(SELECT a, sum(d) w2,max(d)OVER FROM t1
WINDOW
w1 AS
(PARTITION BY d
ROWS BETWEEN '' PRECEDING AND false FOLLOWING),
d AS
(PARTITION BY b ORDER BY d
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
) PRECEDING AND 1 FOLLOWING),
w2 AS
(PARTITION BY b ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW),
w3 AS
(PARTITION BY b ORDER BY d
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
;
SELECT a, sum(d) w2,max(d)OVER FROM t1
WINDOW
w1 AS
(PARTITION BY d
ROWS BETWEEN '' PRECEDING AND false FOLLOWING),
d AS
(PARTITION BY b ORDER BY d
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
;

END;
}

do_execsql_test 12.2 {
  ALTER TABLE t1 RENAME TO t1x;
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 13.1 {
  CREATE TABLE t1(a);
  CREATE TRIGGER r1 INSERT ON t1 BEGIN
    SELECT a(*) OVER (ORDER BY (SELECT 1)) FROM t1;
  END;
}

do_execsql_test 13.2 {
  ALTER TABLE t1 RENAME TO t1x;
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 14.1 {
  CREATE TABLE t1(a);
  CREATE TABLE t2(b);
  CREATE TRIGGER AFTER INSERT ON t1 BEGIN
    SELECT sum() FILTER (WHERE (SELECT sum() FILTER (WHERE 0)) AND a);
  END;
}

do_catchsql_test 14.2 {
  ALTER TABLE t1 RENAME TO t1x;
} {1 {error in trigger AFTER: no such column: a}}

#-------------------------------------------------------------------------
reset_db

do_execsql_test 16.1 {
  CREATE TABLE t1(x);
  CREATE TRIGGER AFTER INSERT ON t1 BEGIN
    SELECT (WITH t2 AS (WITH t3 AS (SELECT true)
          SELECT * FROM t3 ORDER BY true COLLATE nocase)
        SELECT 11);

    WITH t4 AS (SELECT * FROM t1) SELECT 33;
  END;
}
do_execsql_test 16.2 {
  ALTER TABLE t1 RENAME TO t1x;
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 17.1 {
  CREATE TABLE t1(a,b,c);
  CREATE TRIGGER AFTER INSERT ON t1 WHEN new.a NOT NULL BEGIN
    SELECT a () FILTER (WHERE a>0) FROM t1;
  END;
}

do_execsql_test 17.2 {
  ALTER TABLE t1 RENAME TO t1x;
  ALTER TABLE t1x RENAME a TO aaa;
  SELECT sql FROM sqlite_master WHERE type='trigger';
} {
{CREATE TRIGGER AFTER INSERT ON "t1x" WHEN new.aaa NOT NULL BEGIN
    SELECT a () FILTER (WHERE aaa>0) FROM "t1x";
  END}
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 18.1 {
  CREATE TABLE t1(a,b);
  CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
    SELECT a, b FROM t1
    INTERSECT SELECT b,a FROM t1
    ORDER BY b IN (
        SELECT a UNION SELECT b
        FROM t1
        ORDER BY b COLLATE nocase
        )
    ;
  END;
}

do_catchsql_test 18.2 {
    SELECT a, b FROM t1
    INTERSECT 
    SELECT b,a FROM t1
    ORDER BY b IN (
        SELECT a UNION SELECT b
        FROM t1
        ORDER BY b COLLATE nocase
        );
} {1 {1st ORDER BY term does not match any column in the result set}}

do_catchsql_test 18.3 {
  ALTER TABLE t1 RENAME TO t1x;
} {1 {error in trigger r1: 1st ORDER BY term does not match any column in the result set}}

#-------------------------------------------------------------------------
reset_db 
do_execsql_test 19.0 {
  CREATE TABLE a(a,h CONSTRAINT a UNIQUE ON CONFLICT FAIL,CONSTRAINT a);
}

foreach {tn v res} {
  1 {
    CREATE VIEW q AS SELECT 123
    
      WINDOW x AS (
        RANGE BETWEEN UNBOUNDED PRECEDING AND INDEXED() OVER(
          PARTITION BY ( WITH x AS(VALUES(col1)) VALUES(453) )
        )
      FOLLOWING
    ) 
  } {1 {error in view q: no such column: col1}}

  2 {
    CREATE VIEW q AS SELECT
    CAST(CAST(CAST(CAST(CAST(CAST(CAST(CAST(CAST(CAST(CAST(RIGHT
    AS)AS)AS)AS)AS)AS)AS)AS)AS)AS)AS)WINDOW x AS(RANGE BETWEEN UNBOUNDED
    PRECEDING AND INDEXED(*)OVER(PARTITION BY
    CROSS,CROSS,NATURAL,sqlite_master(*)OVER a,(WITH a AS(VALUES(LEFT)UNION
    VALUES(LEFT)UNION VALUES(LEFT)UNION VALUES(LEFT)UNION VALUES(LEFT)UNION
    VALUES(LEFT)UNION VALUES(LEFT))VALUES(LEFT))IN
    STORED,LEFT,LEFT,LEFT,LEFT,LEFT,LEFT)*LEFT FOLLOWING)ORDER BY
    LEFT,LEFT,LEFT,LEFT,LEFT,LEFT,LEFT,LEFT,LEFT,LEFT,LEFT LIMIT
    LEFT,INDEXED(*)OVER(PARTITION BY
    CROSS,CROSS,CROSS,LEFT,INDEXED(*)OVER(PARTITION BY
    CROSS,CROSS,CROSS),INDEXED(*)OVER(PARTITION BY
    LEFT,LEFT,LEFT,LEFT,LEFT,LEFT,LEFT,LEFT,LEFT,LEFT,LEFT),
    LEFT,LEFT,INNER,CROSS,CROSS,CROSS,INNER,NATURAL ORDER BY
    OUTER,NATURAL,NATURAL,NATURAL,NATURAL,NATURAL,NATURAL,NATURAL,INNER,
    INNER,INNER NULLS LAST GROUPS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED
    FOLLOWING); 
  } {1 {error in view q: no such column: LEFT}}

  3 {
    CREATE VIEW q AS SELECT 99 WINDOW x AS (RANGE BETWEEN UNBOUNDED PRECEDING
    AND count(*)OVER(PARTITION BY (WITH a AS(VALUES(2),(x3))VALUES(0)))
    FOLLOWING)ORDER BY x2,sum(1)OVER(PARTITION BY avg(5)OVER(PARTITION BY x1));
  } {1 {error in view q: no such column: x3}}
} {
  do_execsql_test 19.$tn.1 "
    DROP VIEW IF EXISTS q;
    $v
  " {}

  do_catchsql_test 19.$tn.2 {
    ALTER TABLE a RENAME TO g;
  } $res
}

# Verify that the "if( pParse->nErr ) return WRC_Abort" at the top of the
# renameUnmapSelectCb() routine in alter.c (2019-12-04) is really required.
#
sqlite3 db :memory:
do_catchsql_test 20.10 {
  CREATE TABLE s(a, b, c);
  CREATE INDEX k ON s( (WITH s AS( SELECT * ) VALUES(2) ) IN () );
  ALTER TABLE s RENAME a TO a2;
} {1 {error in index k: no tables specified}}

#------------------------------------------------------------------------
#
reset_db
do_execsql_test 21.1 {
  CREATE TABLE s(col);
  CREATE VIEW v AS SELECT ( 
    WITH x(a) AS(SELECT * FROM s) VALUES(RIGHT) 
  ) IN() ; 
  CREATE TABLE a(a);
  ALTER TABLE a RENAME a TO b;
}

#------------------------------------------------------------------------
#
reset_db
do_execsql_test 22.1 {
  CREATE TABLE t1(a);
  CREATE VIEW v2(b) AS SELECT * FROM v2;
}

do_catchsql_test 22.2 {
  ALTER TABLE t1 RENAME TO t4;
} {1 {error in view v2: view v2 is circularly defined}}

do_execsql_test 22.3 {
  DROP VIEW v2;
  CREATE VIEW v2(b) AS WITH t3 AS (SELECT b FROM v2) SELECT * FROM t3;
}

do_catchsql_test 22.4 {
  ALTER TABLE t1 RENAME TO t4;
} {1 {error in view v2: view v2 is circularly defined}}

do_execsql_test 22.5 {
  DROP VIEW v2;
  CREATE VIEW v2(b) AS WITH t3 AS (SELECT b FROM v2) VALUES(1);
}

do_catchsql_test 22.6 {
  ALTER TABLE t1 RENAME TO t4;
} {0 {}}

#------------------------------------------------------------------------
#
reset_db
do_execsql_test 23.1 {
  CREATE TABLE t1(x);
  CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
    UPDATE t1 SET (c,d)=((SELECT 1 FROM t1 JOIN t2 ON b=x),1);
  END;
}

do_catchsql_test 23.2 {
  ALTER TABLE t1 RENAME TO t1x;
} {1 {error in trigger r1: no such table: main.t2}}

#------------------------------------------------------------------------
#
reset_db
do_execsql_test 23.1 {
  CREATE TABLE v0 (a);
  CREATE VIEW v2 (v3) AS 
    WITH x1 AS (SELECT * FROM v2) 
    SELECT v3 AS x, v3 AS y FROM v2; 
}

do_catchsql_test 23.2 {
  SELECT * FROM v2
} {1 {view v2 is circularly defined}}

db close
sqlite3 db test.db

do_catchsql_test 23.3 {
  ALTER TABLE v0 RENAME TO t3 ;
} {1 {error in view v2: view v2 is circularly defined}}

#------------------------------------------------------------------------
#
reset_db
do_execsql_test 24.1 {
  CREATE TABLE v0 (v1); 
  CREATE TABLE v2 (v3 INTEGER UNIQUE ON CONFLICT ABORT); 
  CREATE TRIGGER x AFTER INSERT ON v2 WHEN ( 
      ( SELECT v1 AS PROMO_REVENUE FROM v2 JOIN v0 USING ( VALUE ) ) AND 0 ) 
  BEGIN 
    DELETE FROM v2; 
  END; 
}
do_catchsql_test 24.2 {
  ALTER TABLE v0 RENAME TO x ;
} {1 {error in trigger x: cannot join using column VALUE - column not present in both tables}}

do_execsql_test 24.3 {
  DROP TRIGGER x;
  CREATE TRIGGER x AFTER INSERT ON v2 WHEN (
    0 AND (SELECT rowid FROM v0)
  ) BEGIN
    DELETE FROM v2;
  END;
}

do_execsql_test 24.4 {
  ALTER TABLE v0 RENAME TO xyz;
  SELECT sql FROM sqlite_master WHERE type='trigger'
} {{CREATE TRIGGER x AFTER INSERT ON v2 WHEN (
    0 AND (SELECT rowid FROM "xyz")
  ) BEGIN
    DELETE FROM v2;
  END}}

#------------------------------------------------------------------------
#
reset_db
do_execsql_test 25.1 {
  CREATE TABLE t1(a, b, c);
  CREATE TABLE t2(a, b, c);
  CREATE TRIGGER ttt AFTER INSERT ON t1 BEGIN
    UPDATE t1 SET a=t2.a FROM t2 WHERE t1.a=t2.a; 
  END;
}
#do_execsql_test 25.2 {
#  ALTER TABLE t2 RENAME COLUMN a TO aaa;
#}

#------------------------------------------------------------------------
#
reset_db
do_execsql_test 26.1 {
  CREATE TABLE t1(x);

  CREATE TABLE t3(y);
  CREATE TABLE t4(z);

  CREATE TRIGGER tr1 INSERT ON t3 BEGIN
    UPDATE t3 SET y=z FROM (SELECT z FROM t4);
  END;

  CREATE TRIGGER tr2 INSERT ON t3 BEGIN
    UPDATE t3 SET y=abc FROM (SELECT x AS abc FROM t1);
  END;
}

do_execsql_test 26.2 {
  ALTER TABLE t1 RENAME TO t2;
}

do_execsql_test 26.3 {
  ALTER TABLE t2 RENAME x TO xx;
}

do_execsql_test 26.4 {
  SELECT sql FROM sqlite_schema WHERE name='tr2'
} {
{CREATE TRIGGER tr2 INSERT ON t3 BEGIN
    UPDATE t3 SET y=abc FROM (SELECT xx AS abc FROM "t2");
  END}
}

# 2020-11-02 OSSFuzz 
#
reset_db
do_execsql_test 26.5 {
  CREATE TABLE t1(xx);
  CREATE TRIGGER xx INSERT ON t1 BEGIN
     UPDATE t1 SET xx=xx FROM(SELECT xx);
  END;
} {}
do_catchsql_test 26.6 {
  ALTER TABLE t1 RENAME TO t2;
} {1 {error in trigger xx: no such column: xx}}


#-------------------------------------------------------------------------
reset_db

do_execsql_test 27.1 {
  CREATE TABLE t1(a, b AS ((WITH w1 (xyz) AS  ( SELECT t1.b FROM t1 )  SELECT 123) IN ()), c);
}

do_execsql_test 27.2 {
  ALTER TABLE t1 DROP COLUMN c;
  SELECT sql FROM sqlite_schema WHERE name = 't1';
} {
  {CREATE TABLE t1(a, b AS ((WITH w1 (xyz) AS  ( SELECT t1.b FROM t1 )  SELECT 123) IN ()))}
}

do_execsql_test 27.3 {
  CREATE TABLE t0(c0 , c1 AS (CASE TRUE   NOT IN () WHEN NULL   THEN CASE + 0xa     ISNULL  WHEN NOT + 0x9     THEN t0.c1  ELSE CURRENT_TIME   LIKE CAST (t0.c1 REGEXP '-([1-9]\d*.\d*|0\.\d*[1-9]\d*)'ESCAPE (c1) COLLATE BINARY  BETWEEN c1  AND c1   NOT IN (WITH t4 (c0) AS  (WITH t3 (c0) AS NOT MATERIALIZED  (WITH RECURSIVE t2 (c0) AS  (WITH RECURSIVE t1 AS  (VALUES (x'717171ff71717171' )  )  SELECT DISTINCT t0.c0  FROM t0 NOT INDEXED  WHERE t0.c0 =t0.c0 GROUP BY 0x9      )  SELECT DISTINCT t0.c0  FROM t0 NOT INDEXED  WHERE t0.c0 =t0.c1   )  SELECT DISTINCT t0.c0  FROM t0 NOT INDEXED  WHERE t0.c0 =t0.c0 GROUP BY typeof(0x9   )    )  SELECT DISTINCT t0.c0  FROM t0 NOT INDEXED  WHERE t0.c0 =t0.c0 GROUP BY typeof(typeof(0x9    )  )    ) IN t0   BETWEEN typeof(typeof(typeof(hex(*) FILTER (WHERE + x'5ccd1e68'   )  )  )  )  AND 1   >0xa      AS BLOB (+4.4E4 , -0xe  ) )  END  <> c1  IN ()  END  ) VIRTUAL   , c35 PRIMARY KEY   ,  c60 , c64 NUMERIC (-6.8 , -0xE  )  ) WITHOUT ROWID ;
} {}

do_execsql_test 27.4 {
  ALTER TABLE t0 DROP COLUMN c60;
} {}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 28.1 {
  CREATE TABLE t1(a,b,c,d);
  CREATE TRIGGER AFTER INSERT ON t1 BEGIN
    UPDATE t1 SET (c,d)=(a,b);
  END;
  ALTER TABLE t1 RENAME TO t2;
}

do_execsql_test 28.2 {
  SELECT sql FROM sqlite_schema WHERE type='trigger'
} {{CREATE TRIGGER AFTER INSERT ON "t2" BEGIN
    UPDATE "t2" SET (c,d)=(a,b);
  END}}


#-------------------------------------------------------------------------
reset_db
do_execsql_test 29.1 {
  CREATE TABLE t1(x, y);
  CREATE TRIGGER Trigger1 DELETE ON t1 
  BEGIN 
    SELECT t1.*, t1.x FROM t1 ORDER BY t1.x;
  END;
}


do_execsql_test 29.2 {
  ALTER TABLE t1 RENAME x TO z;
}

do_execsql_test 29.3 {
  ALTER TABLE t1 RENAME TO t2;
}

do_execsql_test 29.4 {
  CREATE TRIGGER tr2 AFTER DELETE ON t2 BEGIN
    SELECT z, y FROM (
      SELECT t2.* FROM t2
    );
  END;
}

do_execsql_test 29.5 {
  DELETE FROM t2
}

do_execsql_test 29.6 {
  ALTER TABLE t2 RENAME TO t3;
}

do_execsql_test 29.7 {
  SELECT sql FROM sqlite_schema WHERE type='trigger'
} {
  {CREATE TRIGGER Trigger1 DELETE ON "t3" 
  BEGIN 
    SELECT "t3".*, "t3".z FROM "t3" ORDER BY "t3".z;
  END}
  {CREATE TRIGGER tr2 AFTER DELETE ON "t3" BEGIN
    SELECT z, y FROM (
      SELECT "t3".* FROM "t3"
    );
  END}
}

finish_test

Added test/altertrig.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022 May 27
#
# 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
set testprefix altertrig

# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
ifcapable !altertable {
  finish_test
  return
}

proc collapse_whitespace {in} {
  regsub -all {[ \t\n]+} [string trim $in] { }
}

proc do_whitespace_sql_test {tn sql res} {
  set got [execsql $sql]
  set wgot [list]
  set wres [list]
  foreach g $got { lappend wgot [collapse_whitespace $g] }
  foreach r $res { lappend wres [collapse_whitespace $r] }

  uplevel [list do_test $tn [list set {} $wgot] $wres]
}

do_execsql_test 1.0 {
  CREATE TABLE t1(x);
  CREATE TABLE t2(y);
  CREATE TABLE t3(z);
  CREATE TABLE t4(a);

  CREATE TRIGGER r1 INSERT ON t1 BEGIN 
    UPDATE t1 SET d='xyz' FROM t2, t3; 
  END;
}

do_whitespace_sql_test 1.1 {
  ALTER TABLE t3 RENAME TO t5;
  SELECT sql FROM sqlite_schema WHERE type='trigger';
} {{
  CREATE TRIGGER r1 INSERT ON t1 BEGIN 
    UPDATE t1 SET d='xyz' FROM t2, "t5"; 
  END
}}

do_execsql_test 1.2 {
  DROP TRIGGER r1;
  CREATE TRIGGER r1 INSERT ON t1 BEGIN 
    UPDATE t1 SET d='xyz' FROM t2, (SELECT * FROM t5); 
  END;
}

do_whitespace_sql_test 1.3 {
  ALTER TABLE t5 RENAME TO t3;
  SELECT sql FROM sqlite_schema WHERE type='trigger';
} {{
  CREATE TRIGGER r1 INSERT ON t1 BEGIN 
    UPDATE t1 SET d='xyz' FROM t2, (SELECT * FROM "t3"); 
  END
}}

foreach {tn alter update final} {
  1 {
    ALTER TABLE t3 RENAME TO t10
  } {
    UPDATE t1 SET d='xyz' FROM t2, (SELECT * FROM t3)
  } {
    UPDATE t1 SET d='xyz' FROM t2, (SELECT * FROM "t10")
  }

  2 {
    ALTER TABLE t3 RENAME TO t10
  } {
    UPDATE t1 SET a='xyz' FROM t3, (SELECT * FROM (SELECT e FROM t3))
  } {
    UPDATE t1 SET a='xyz' FROM "t10", (SELECT * FROM (SELECT e FROM "t10"))
  }

  3 {
    ALTER TABLE t3 RENAME e TO abc
  } {
    UPDATE t1 SET a='xyz' FROM t3, (SELECT * FROM (SELECT e FROM t3))
  } {
    UPDATE t1 SET a='xyz' FROM t3, (SELECT * FROM (SELECT abc FROM t3))
  }

  4 {
    ALTER TABLE t2 RENAME c TO abc
  } {
    UPDATE t1 SET a='xyz' FROM t3, (SELECT 1 FROM t2 WHERE c)
  } {
    UPDATE t1 SET a='xyz' FROM t3, (SELECT 1 FROM t2 WHERE abc)
  }

  5 {
    ALTER TABLE t2 RENAME c TO abc
  } {
    UPDATE t1 SET a=t2.c FROM t2
  } {
    UPDATE t1 SET a=t2.abc FROM t2
  }

  6 {
    ALTER TABLE t2 RENAME c TO abc
  } {
    UPDATE t1 SET a=t2.c FROM t2, t3
  } {
    UPDATE t1 SET a=t2.abc FROM t2, t3
  }

  7 {
    ALTER TABLE t4 RENAME e TO abc
  } {
    UPDATE t1 SET a=1 FROM t3 NATURAL JOIN t4 WHERE t4.e=a
  } {
    UPDATE t1 SET a=1 FROM t3 NATURAL JOIN t4 WHERE t4.abc=a
  }

  8 {
    ALTER TABLE t4 RENAME TO abc
  } {
    UPDATE t1 SET a=1 FROM t3 NATURAL JOIN t4 WHERE t4.e=a
  } {
    UPDATE t1 SET a=1 FROM t3 NATURAL JOIN "abc" WHERE "abc".e=a
  }
 
} {
  reset_db
  do_execsql_test 2.$tn.1 {
    CREATE TABLE t1(a,b);
    CREATE TABLE t2(c,d);
    CREATE TABLE t3(e,f);
    CREATE TABLE t4(e,f);
  }
  do_execsql_test 2.$tn.2 "
    CREATE TRIGGER r1 INSERT ON t1 BEGIN 
      $update;
    END
  "
  do_execsql_test 2.$tn.3 $alter

  do_whitespace_sql_test 2.$tn.4 {
    SELECT sqL FROM sqlite_schema WHERE type='trigger'
  } "{
    CREATE TRIGGER r1 INSERT ON t1 BEGIN 
      $final;
    END
  }"
}

finish_test

Changes to test/analyze.test.

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
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







-
+

















-
+
-

-
-
-
+
+
+
-
+









-
+

-
-
-
+
+
+
-
+









-
+

-
-
-
+
+
+
-
+







  sqlite3 db test.db
  execsql {
    SELECT * FROM t4 WHERE x=1234;
  }
} {}

# Verify that DROP TABLE and DROP INDEX remove entries from the 
# sqlite_stat1, sqlite_stat3 and sqlite_stat4 tables.
# sqlite_stat1 and sqlite_stat4 tables.
#
do_test analyze-5.0 {
  execsql {
    DELETE FROM t3;
    DELETE FROM t4;
    INSERT INTO t3 VALUES(1,2,3,4);
    INSERT INTO t3 VALUES(5,6,7,8);
    INSERT INTO t3 SELECT a+8, b+8, c+8, d+8 FROM t3;
    INSERT INTO t3 SELECT a+16, b+16, c+16, d+16 FROM t3;
    INSERT INTO t3 SELECT a+32, b+32, c+32, d+32 FROM t3;
    INSERT INTO t3 SELECT a+64, b+64, c+64, d+64 FROM t3;
    INSERT INTO t4 SELECT a, b, c FROM t3;
    ANALYZE;
    SELECT DISTINCT idx FROM sqlite_stat1 ORDER BY 1;
    SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1;
  }
} {t3i1 t3i2 t3i3 t4i1 t4i2 t3 t4}
ifcapable stat4||stat3 {
ifcapable stat4 {
  ifcapable stat4 {set stat sqlite_stat4} else {set stat sqlite_stat3}
  do_test analyze-5.1 {
    execsql "
      SELECT DISTINCT idx FROM $stat ORDER BY 1;
      SELECT DISTINCT tbl FROM $stat ORDER BY 1;
    execsql {
      SELECT DISTINCT idx FROM sqlite_stat4 ORDER BY 1;
      SELECT DISTINCT tbl FROM sqlite_stat4 ORDER BY 1;
    "
    }
  } {t3i1 t3i2 t3i3 t4i1 t4i2 t3 t4}
}
do_test analyze-5.2 {
  execsql {
    DROP INDEX t3i2;
    SELECT DISTINCT idx FROM sqlite_stat1 ORDER BY 1;
    SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1;
  }
} {t3i1 t3i3 t4i1 t4i2 t3 t4}
ifcapable stat4||stat3 {
ifcapable stat4 {
  do_test analyze-5.3 {
    execsql "
      SELECT DISTINCT idx FROM $stat ORDER BY 1;
      SELECT DISTINCT tbl FROM $stat ORDER BY 1;
    execsql {
      SELECT DISTINCT idx FROM sqlite_stat4 ORDER BY 1;
      SELECT DISTINCT tbl FROM sqlite_stat4 ORDER BY 1;
    "
    }
  } {t3i1 t3i3 t4i1 t4i2 t3 t4}
}
do_test analyze-5.4 {
  execsql {
    DROP TABLE t3;
    SELECT DISTINCT idx FROM sqlite_stat1 ORDER BY 1;
    SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1;
  }
} {t4i1 t4i2 t4}
ifcapable stat4||stat3 {
ifcapable stat4 {
  do_test analyze-5.5 {
    execsql "
      SELECT DISTINCT idx FROM $stat ORDER BY 1;
      SELECT DISTINCT tbl FROM $stat ORDER BY 1;
    execsql {
      SELECT DISTINCT idx FROM sqlite_stat4 ORDER BY 1;
      SELECT DISTINCT tbl FROM sqlite_stat4 ORDER BY 1;
    "
    }
  } {t4i1 t4i2 t4}
}

# This test corrupts the database file so it must be the last test
# in the series.
#
do_test analyze-5.99 {

Changes to test/analyze3.test.

14
15
16
17
18
19
20
21











22
23
24
25
26
27
28
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







-
+
+
+
+
+
+
+
+
+
+
+







# instead of literal constant arguments.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix analyze3

ifcapable !stat4&&!stat3 {
ifcapable !stat4 {
  finish_test
  return
}

# This test cannot be run with the sqlite3_prepare() permutation, as it
# tests that stat4 data can be used to influence the plans of queries
# based on bound variable values. And this is not possible when using
# sqlite3_prepare() - as queries cannot be internally re-prepared after
# binding values are available.
if {[permutation]=="prepare"} {
  finish_test
  return
}

#----------------------------------------------------------------------
# Test Organization:
#
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
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







-
-
+
-
-
-













-
+


-
+









-
+




-
+




-
+




-
+




-
+







    execsql { INSERT INTO t1 VALUES($i+100, $i) }
  }
  execsql {
    COMMIT;
    ANALYZE;
  }

  ifcapable stat4 {
    execsql { SELECT count(*)>0 FROM sqlite_stat4; }
  execsql { SELECT count(*)>0 FROM sqlite_stat4; }
  } else {
    execsql { SELECT count(*)>0 FROM sqlite_stat3; }
  }
} {1}

do_execsql_test analyze3-1.1.x {
  SELECT count(*) FROM t1 WHERE x>200 AND x<300;
  SELECT count(*) FROM t1 WHERE x>0 AND x<1100;
} {99 1000}

# 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]
197
198
199
200
201
202
203
204

205
206
207

208
209
210
211
212
213
214
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]
249
250
251
252
253
254
255
256

257
258
259

260
261
262
263
264
265
266
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]
304
305
306
307
308
309
310
311

312
313
314

315
316
317
318
319
320
321
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
694
695
696
697
698
699
700
701

702
703
704
705

706
707
708
709
710
711
712
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.

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
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







+
+
+
+
+
+



















-
+







# statistics.
#
# Also include test cases for collating sequences on indices.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
ifcapable !altertable {
  finish_test
  return
}

do_test analyze4-1.0 {
  db eval {
    CREATE TABLE t1(a,b);
    CREATE INDEX t1a ON t1(a);
    CREATE INDEX t1b ON t1(b);
    INSERT INTO t1 VALUES(1,NULL);
    INSERT INTO t1 SELECT a+1, b FROM t1;
    INSERT INTO t1 SELECT a+2, b FROM t1;
    INSERT INTO t1 SELECT a+4, b FROM t1;
    INSERT INTO t1 SELECT a+8, b FROM t1;
    INSERT INTO t1 SELECT a+16, b FROM t1;
    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/analyze5.test.

13
14
15
16
17
18
19
20

21
22
23
24
25
26
27
13
14
15
16
17
18
19

20
21
22
23
24
25
26
27







-
+







# in this file is the use of the sqlite_stat4 histogram data on tables
# with many repeated values and only a few distinct values.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable !stat4&&!stat3 {
ifcapable !stat4 {
  finish_test
  return
}

set testprefix analyze5

proc eqp {sql {db db}} {
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
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







-
-
-
-
+
+
+
-
-
-
-
-




-
-
-
-
-
+
+
+
+
-
-
-
-
-

-
-
-
-
+
+
+
-
-
-
-
-







    CREATE INDEX t1v ON t1(v);  -- mixed case text
    CREATE INDEX t1w ON t1(w);  -- integers 0, 1, 2 and a few NULLs
    CREATE INDEX t1x ON t1(x);  -- integers 1, 2, 3 and many NULLs
    CREATE INDEX t1y ON t1(y);  -- integers 0 and very few 1s
    CREATE INDEX t1z ON t1(z);  -- integers 0, 1, 2, and 3
    ANALYZE;
  }
  ifcapable stat4 {
    db eval {
      SELECT DISTINCT lindex(test_decode(sample),0) 
        FROM sqlite_stat4 WHERE idx='t1u' ORDER BY nlt;
  db eval {
    SELECT DISTINCT lindex(test_decode(sample),0) 
      FROM sqlite_stat4 WHERE idx='t1u' ORDER BY nlt;
    }
  } else {
    db eval {
      SELECT sample FROM sqlite_stat3 WHERE idx='t1u' ORDER BY nlt;
    }
  }
} {alpha bravo charlie delta}

do_test analyze5-1.1 {
  ifcapable stat4 {
    db eval {
      SELECT DISTINCT lower(lindex(test_decode(sample), 0)) 
        FROM sqlite_stat4 WHERE idx='t1v' ORDER BY 1
    }
  db eval {
    SELECT DISTINCT lower(lindex(test_decode(sample), 0)) 
      FROM sqlite_stat4 WHERE idx='t1v' ORDER BY 1
  }
  } else {
    db eval {
      SELECT lower(sample) FROM sqlite_stat3 WHERE idx='t1v' ORDER BY 1
    }
  }
} {alpha bravo charlie delta}
ifcapable stat4 {
  do_test analyze5-1.2 {
    db eval {SELECT idx, count(*) FROM sqlite_stat4 GROUP BY 1 ORDER BY 1}
  } {t1t 8 t1u 8 t1v 8 t1w 8 t1x 8 t1y 9 t1z 8}
do_test analyze5-1.2 {
  db eval {SELECT idx, count(*) FROM sqlite_stat4 GROUP BY 1 ORDER BY 1}
} {t1t 8 t1u 8 t1v 8 t1w 8 t1x 8 t1y 9 t1z 8}
} else {
  do_test analyze5-1.2 {
    db eval {SELECT idx, count(*) FROM sqlite_stat3 GROUP BY 1 ORDER BY 1}
  } {t1t 4 t1u 4 t1v 4 t1w 4 t1x 4 t1y 2 t1z 4}
}

# Verify that range queries generate the correct row count estimates
#
foreach {testid where index rows} {
    1  {z>=0 AND z<=0}       t1z  400
    2  {z>=1 AND z<=1}       t1z  300
    3  {z>=2 AND z<=2}       t1z  175

Changes to test/analyze6.test.

13
14
15
16
17
18
19
20

21
22
23
24
25
26
27
13
14
15
16
17
18
19

20
21
22
23
24
25
26
27







-
+







# in this file a corner-case query planner optimization involving the
# join order of two tables of different sizes.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable !stat4&&!stat3 {
ifcapable !stat4 {
  finish_test
  return
}

set testprefix analyze6

proc eqp {sql {db db}} {
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=?)*/}
ifcapable stat4||stat3 {
} {/*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 && !stat3} {
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.

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
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












-
+





-
+







# 2011 August 13
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file implements tests for SQLite library.  The focus of the tests
# in this file is testing the capabilities of sqlite_stat3.
# in this file is testing the capabilities of sqlite_stat4.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable !stat4&&!stat3 {
ifcapable !stat4 {
  finish_test
  return
}

set testprefix analyze8

proc eqp {sql {db db}} {
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.

395
396
397
398
399
400
401
402

403
404
405
406
407
408
409
395
396
397
398
399
400
401

402
403
404
405
406
407
408
409







-
+







  CREATE INDEX i2 ON t1(e);
}
do_test 9.2 {
  execsql BEGIN;
  for {set i 0} {$i < 100} {incr i} {
    execsql "INSERT INTO t1 VALUES('x', 'y', 'z', $i, [expr $i/2])"
  }
  for {set i 0} {$i < 20} {incr i} {
  for {set i 0} {$i < 21} {incr i} {
    execsql "INSERT INTO t1 VALUES('x', 'y', 'z', 101, $i)"
  }
  for {set i 102} {$i < 200} {incr i} {
    execsql "INSERT INTO t1 VALUES('x', 'y', 'z', $i, [expr $i/2])"
  }
  execsql COMMIT
  execsql ANALYZE
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

Deleted test/analyzeA.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


























































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# 2013 August 3
#
# 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 contains automated tests used to verify that the current build
# (which must be either ENABLE_STAT3 or ENABLE_STAT4) works with both stat3
# and stat4 data.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix analyzeA

ifcapable !stat4&&!stat3 {
  finish_test
  return
}

# Populate the stat3 table according to the current contents of the db
#
proc populate_stat3 {{bDropTable 1}} {
  # Open a second connection on database "test.db" and run ANALYZE. If this
  # is an ENABLE_STAT3 build, this is all that is required to create and
  # populate the sqlite_stat3 table. 
  # 
  sqlite3 db2 test.db
  execsql { ANALYZE }

  # Now, if this is an ENABLE_STAT4 build, create and populate the 
  # sqlite_stat3 table based on the stat4 data gathered by the ANALYZE
  # above. Then drop the sqlite_stat4 table.
  #
  ifcapable stat4 {
    db2 func lindex lindex
    execsql {
      PRAGMA writable_schema = on;
      CREATE TABLE sqlite_stat3(tbl,idx,neq,nlt,ndlt,sample);
      INSERT INTO sqlite_stat3 
      SELECT DISTINCT tbl, idx, 
        lindex(neq,0), lindex(nlt,0), lindex(ndlt,0), test_extract(sample, 0)
      FROM sqlite_stat4;
    } db2
    if {$bDropTable} { execsql {DROP TABLE sqlite_stat4} db2 }
    execsql { PRAGMA writable_schema = off }
  }

  # Modify the database schema cookie to ensure that the other connection
  # reloads the schema.
  #
  execsql {
    CREATE TABLE obscure_tbl_nm(x);
    DROP TABLE obscure_tbl_nm;
  } db2
  db2 close
}

# Populate the stat4 table according to the current contents of the db
#
proc populate_stat4 {{bDropTable 1}} {
  sqlite3 db2 test.db
  execsql { ANALYZE }

  ifcapable stat3 {
    execsql {
      PRAGMA writable_schema = on;
      CREATE TABLE sqlite_stat4(tbl,idx,neq,nlt,ndlt,sample);
      INSERT INTO sqlite_stat4 
      SELECT tbl, idx, neq, nlt, ndlt, sqlite_record(sample) 
      FROM sqlite_stat3;
    } db2
    if {$bDropTable} { execsql {DROP TABLE sqlite_stat3} db2 }
    execsql { PRAGMA writable_schema = off }
  }
 
  # Modify the database schema cookie to ensure that the other connection
  # reloads the schema.
  #
  execsql {
    CREATE TABLE obscure_tbl_nm(x);
    DROP TABLE obscure_tbl_nm;
  } db2
  db2 close
}

# Populate the stat4 table according to the current contents of the db.
# Leave deceptive data in the stat3 table. This data should be ignored
# in favour of that from the stat4 table.
#
proc populate_both {} {
  ifcapable stat4 { populate_stat3 0 }
  ifcapable stat3 { populate_stat4 0 }

  sqlite3 db2 test.db
  execsql {
    PRAGMA writable_schema = on;
    UPDATE sqlite_stat3 SET idx = 
      CASE idx WHEN 't1b' THEN 't1c' ELSE 't1b'
    END;
    PRAGMA writable_schema = off;
    CREATE TABLE obscure_tbl_nm(x);
    DROP TABLE obscure_tbl_nm;
  } db2
  db2 close
}

foreach {tn analyze_cmd} {
  1 populate_stat4 
  2 populate_stat3
  3 populate_both
} {
  reset_db
  do_test 1.$tn.1 {
    execsql { CREATE TABLE t1(a INTEGER PRIMARY KEY, b INT, c INT) }
    for {set i 0} {$i < 100} {incr i} {
      set c [expr int(pow(1.1,$i)/100)]
      set b [expr 125 - int(pow(1.1,99-$i))/100]
      execsql {INSERT INTO t1 VALUES($i, $b, $c)}
    }
  } {}

  execsql { CREATE INDEX t1b ON t1(b) }
  execsql { CREATE INDEX t1c ON t1(c) }
  $analyze_cmd

  do_execsql_test 1.$tn.2.1 { SELECT count(*) FROM t1 WHERE b=31 } 1
  do_execsql_test 1.$tn.2.2 { SELECT count(*) FROM t1 WHERE c=0  } 49
  do_execsql_test 1.$tn.2.3 { SELECT count(*) FROM t1 WHERE b=125  } 49
  do_execsql_test 1.$tn.2.4 { SELECT count(*) FROM t1 WHERE c=16  } 1

  do_eqp_test 1.$tn.2.5 {
    SELECT * FROM t1 WHERE b = 31 AND c = 0;
  } {SEARCH TABLE t1 USING INDEX t1b (b=?)}
  do_eqp_test 1.$tn.2.6 {
    SELECT * FROM t1 WHERE b = 125 AND c = 16;
  } {SEARCH TABLE t1 USING INDEX t1c (c=?)}

  do_execsql_test 1.$tn.3.1 { 
    SELECT count(*) FROM t1 WHERE b BETWEEN 0 AND 50
  } {6}
  do_execsql_test 1.$tn.3.2 { 
    SELECT count(*) FROM t1 WHERE c BETWEEN 0 AND 50
  } {90}
  do_execsql_test 1.$tn.3.3 { 
    SELECT count(*) FROM t1 WHERE b BETWEEN 75 AND 125
  } {90}
  do_execsql_test 1.$tn.3.4 { 
    SELECT count(*) FROM t1 WHERE c BETWEEN 75 AND 125
  } {6}

  do_eqp_test 1.$tn.3.5 {
    SELECT * FROM t1 WHERE b BETWEEN 0 AND 50 AND c BETWEEN 0 AND 50
  } {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}

  do_eqp_test 1.$tn.3.6 {
    SELECT * FROM t1 WHERE b BETWEEN 75 AND 125 AND c BETWEEN 75 AND 125
  } {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}

  do_eqp_test 1.$tn.3.7 {
    SELECT * FROM t1 WHERE b BETWEEN +0 AND +50 AND c BETWEEN +0 AND +50
  } {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}

  do_eqp_test 1.$tn.3.8 {
    SELECT * FROM t1
     WHERE b BETWEEN cast('0' AS int) AND cast('50.0' AS real)
       AND c BETWEEN cast('0' AS numeric) AND cast('50.0' AS real)
  } {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}

  do_eqp_test 1.$tn.3.9 {
    SELECT * FROM t1 WHERE b BETWEEN +75 AND +125 AND c BETWEEN +75 AND +125
  } {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}

  do_eqp_test 1.$tn.3.10 {
    SELECT * FROM t1
     WHERE b BETWEEN cast('75' AS int) AND cast('125.0' AS real)
       AND c BETWEEN cast('75' AS numeric) AND cast('125.0' AS real)
  } {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}
}

finish_test

Deleted test/analyzeB.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
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
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










































































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# 2013 August 3
#
# 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 contains automated tests used to verify that the sqlite_stat3
# functionality is working. The tests in this file are based on a subset
# of the sqlite_stat4 tests in analyze9.test.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix analyzeB

ifcapable !stat3 {
  finish_test
  return
}

do_execsql_test 1.0 {
  CREATE TABLE t1(a TEXT, b TEXT); 
  INSERT INTO t1 VALUES('(0)', '(0)');
  INSERT INTO t1 VALUES('(1)', '(1)');
  INSERT INTO t1 VALUES('(2)', '(2)');
  INSERT INTO t1 VALUES('(3)', '(3)');
  INSERT INTO t1 VALUES('(4)', '(4)');
  CREATE INDEX i1 ON t1(a, b);
} {}


do_execsql_test 1.1 {
  ANALYZE;
} {}

do_execsql_test 1.2 {
  SELECT tbl,idx,nEq,nLt,nDLt,quote(sample) FROM sqlite_stat3;
} {
  t1 i1 1 0 0 '(0)'
  t1 i1 1 1 1 '(1)'
  t1 i1 1 2 2 '(2)'
  t1 i1 1 3 3 '(3)'
  t1 i1 1 4 4 '(4)'
}

if {[permutation] != "utf16"} {
  do_execsql_test 1.3 {
    SELECT tbl,idx,nEq,nLt,nDLt,quote(sample) FROM sqlite_stat3;
  } {
    t1 i1 1 0 0 '(0)'
    t1 i1 1 1 1 '(1)'
    t1 i1 1 2 2 '(2)'
    t1 i1 1 3 3 '(3)'
    t1 i1 1 4 4 '(4)'
  }
}


#-------------------------------------------------------------------------
# This is really just to test SQL user function "test_decode".
#
reset_db
do_execsql_test 2.1 {
  CREATE TABLE t1(a, b, c);
  INSERT INTO t1(a) VALUES('some text');
  INSERT INTO t1(a) VALUES(14);
  INSERT INTO t1(a) VALUES(NULL);
  INSERT INTO t1(a) VALUES(22.0);
  INSERT INTO t1(a) VALUES(x'656667');
  CREATE INDEX i1 ON t1(a, b, c);
  ANALYZE;
  SELECT quote(sample) FROM sqlite_stat3;
} {
  NULL 14 22.0 {'some text'} X'656667' 
}

#-------------------------------------------------------------------------
# 
reset_db
do_execsql_test 3.1 {
  CREATE TABLE t2(a, b);
  CREATE INDEX i2 ON t2(a, b);
  BEGIN;
}

do_test 3.2 {
  for {set i 0} {$i < 1000} {incr i} {
    set a [expr $i / 10]
    set b [expr int(rand() * 15.0)]
    execsql { INSERT INTO t2 VALUES($a, $b) }
  }
  execsql COMMIT
} {}

db func lindex lindex

# Each value of "a" occurs exactly 10 times in the table.
#
do_execsql_test 3.3.1 {
  SELECT count(*) FROM t2 GROUP BY a;
} [lrange [string repeat "10 " 100] 0 99]

# The first element in the "nEq" list of all samples should therefore be 10.
#
do_execsql_test 3.3.2 {
  ANALYZE;
  SELECT nEq FROM sqlite_stat3;
} [lrange [string repeat "10 " 100] 0 23]

#-------------------------------------------------------------------------
# 
do_execsql_test 3.4 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
  INSERT INTO t1 VALUES(1, 1, 'one-a');
  INSERT INTO t1 VALUES(11, 1, 'one-b');
  INSERT INTO t1 VALUES(21, 1, 'one-c');
  INSERT INTO t1 VALUES(31, 1, 'one-d');
  INSERT INTO t1 VALUES(41, 1, 'one-e');
  INSERT INTO t1 VALUES(51, 1, 'one-f');
  INSERT INTO t1 VALUES(61, 1, 'one-g');
  INSERT INTO t1 VALUES(71, 1, 'one-h');
  INSERT INTO t1 VALUES(81, 1, 'one-i');
  INSERT INTO t1 VALUES(91, 1, 'one-j');
  INSERT INTO t1 SELECT a+1,2,'two' || substr(c,4) FROM t1;
  INSERT INTO t1 SELECT a+2,3,'three'||substr(c,4) FROM t1 WHERE c GLOB 'one-*';
  INSERT INTO t1 SELECT a+3,4,'four'||substr(c,4) FROM t1 WHERE c GLOB 'one-*';
  INSERT INTO t1 SELECT a+4,5,'five'||substr(c,4) FROM t1 WHERE c GLOB 'one-*';
  INSERT INTO t1 SELECT a+5,6,'six'||substr(c,4) FROM t1 WHERE c GLOB 'one-*';	
  CREATE INDEX t1b ON t1(b);
  ANALYZE;
  SELECT c FROM t1 WHERE b=3 AND a BETWEEN 30 AND 60;
} {three-d three-e three-f}


#-------------------------------------------------------------------------
# These tests verify that the sample selection for stat3 appears to be 
# working as designed.
#

reset_db
db func lindex lindex
db func lrange lrange

do_execsql_test 4.0 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a, b, c);
  CREATE INDEX i1 ON t1(c, b, a);
}


proc insert_filler_rows_n {iStart args} {
  set A(-ncopy) 1
  set A(-nval) 1

  foreach {k v} $args {
    if {[info exists A($k)]==0} { error "no such option: $k" }
    set A($k) $v
  }
  if {[llength $args] % 2} {
    error "option requires an argument: [lindex $args end]"
  }

  for {set i 0} {$i < $A(-nval)} {incr i} {
    set iVal [expr $iStart+$i]
    for {set j 0} {$j < $A(-ncopy)} {incr j} {
      execsql { INSERT INTO t1 VALUES($iVal, $iVal, $iVal) }
    }
  }
}

do_test 4.1 {
  execsql { BEGIN }
  insert_filler_rows_n  0  -ncopy 10 -nval 19
  insert_filler_rows_n 20  -ncopy  1 -nval 100

  execsql {
    INSERT INTO t1(c, b, a) VALUES(200, 1, 'a');
    INSERT INTO t1(c, b, a) VALUES(200, 1, 'b');
    INSERT INTO t1(c, b, a) VALUES(200, 1, 'c');

    INSERT INTO t1(c, b, a) VALUES(200, 2, 'e');
    INSERT INTO t1(c, b, a) VALUES(200, 2, 'f');

    INSERT INTO t1(c, b, a) VALUES(201, 3, 'g');
    INSERT INTO t1(c, b, a) VALUES(201, 4, 'h');

    ANALYZE;
    SELECT count(*) FROM sqlite_stat3;
    SELECT count(*) FROM t1;
  }
} {24 297}

do_execsql_test 4.2 {
  SELECT neq, nlt, ndlt, sample FROM sqlite_stat3 ORDER BY rowid LIMIT 16;
} {
  10 0 0 0
  10 10 1 1
  10 20 2 2
  10 30 3 3
  10 40 4 4
  10 50 5 5
  10 60 6 6
  10 70 7 7
  10 80 8 8
  10 90 9 9
  10 100 10 10
  10 110 11 11
  10 120 12 12
  10 130 13 13
  10 140 14 14
  10 150 15 15
}

do_execsql_test 4.3 {
  SELECT neq, nlt, ndlt, sample FROM sqlite_stat3
  ORDER BY rowid DESC LIMIT 2;
} {
  2 295 120 201
  5 290 119 200
}

do_execsql_test 4.4 { SELECT count(DISTINCT c) FROM t1 WHERE c<201 } 120
do_execsql_test 4.5 { SELECT count(DISTINCT c) FROM t1 WHERE c<200 } 119

reset_db
do_test 4.7 {
  execsql { 
    BEGIN;
    CREATE TABLE t1(o,t INTEGER PRIMARY KEY);
    CREATE INDEX i1 ON t1(o);
  }
  for {set i 0} {$i<10000} {incr i [expr (($i<1000)?1:10)]} {
    execsql { INSERT INTO t1 VALUES('x', $i) }
  }
  execsql {
    COMMIT;
    ANALYZE;
    SELECT count(*) FROM sqlite_stat3;
  }
} {1}
do_execsql_test 4.8 {
  SELECT sample FROM sqlite_stat3;
} {x}


#-------------------------------------------------------------------------
# The following would cause a crash at one point.
#
reset_db
do_execsql_test 5.1 {
  PRAGMA encoding = 'utf-16';
  CREATE TABLE t0(v);
  ANALYZE;
}

#-------------------------------------------------------------------------
# This was also crashing (corrupt sqlite_stat3 table).
#
reset_db
do_execsql_test 6.1 {
  CREATE TABLE t1(a, b);
  CREATE INDEX i1 ON t1(a);
  CREATE INDEX i2 ON t1(b);
  INSERT INTO t1 VALUES(1, 1);
  INSERT INTO t1 VALUES(2, 2);
  INSERT INTO t1 VALUES(3, 3);
  INSERT INTO t1 VALUES(4, 4);
  INSERT INTO t1 VALUES(5, 5);
  ANALYZE;
  PRAGMA writable_schema = 1;
  CREATE TEMP TABLE x1 AS
    SELECT tbl,idx,neq,nlt,ndlt,sample FROM sqlite_stat3
    ORDER BY (rowid%5), rowid;
  DELETE FROM sqlite_stat3;
  INSERT INTO sqlite_stat3 SELECT * FROM x1;
  PRAGMA writable_schema = 0;
  ANALYZE sqlite_master;
}
do_execsql_test 6.2 {
  SELECT * FROM t1 WHERE a = 'abc';
}

#-------------------------------------------------------------------------
# The following tests experiment with adding corrupted records to the
# 'sample' column of the sqlite_stat3 table.
#
reset_db
sqlite3_db_config_lookaside db 0 0 0

do_execsql_test 7.1 {
  CREATE TABLE t1(a, b);
  CREATE INDEX i1 ON t1(a, b);
  INSERT INTO t1 VALUES(1, 1);
  INSERT INTO t1 VALUES(2, 2);
  INSERT INTO t1 VALUES(3, 3);
  INSERT INTO t1 VALUES(4, 4);
  INSERT INTO t1 VALUES(5, 5);
  ANALYZE;
  UPDATE sqlite_stat3 SET sample = X'' WHERE rowid = 1;
  ANALYZE sqlite_master;
}

do_execsql_test 7.2 {
  UPDATE sqlite_stat3 SET sample = X'FFFF';
  ANALYZE sqlite_master;
  SELECT * FROM t1 WHERE a = 1;
} {1 1}

do_execsql_test 7.3 {
  ANALYZE;
  UPDATE sqlite_stat3 SET neq = '0 0 0';
  ANALYZE sqlite_master;
  SELECT * FROM t1 WHERE a = 1;
} {1 1}

do_execsql_test 7.4 {
  ANALYZE;
  UPDATE sqlite_stat3 SET ndlt = '0 0 0';
  ANALYZE sqlite_master;
  SELECT * FROM t1 WHERE a = 3;
} {3 3}

do_execsql_test 7.5 {
  ANALYZE;
  UPDATE sqlite_stat3 SET nlt = '0 0 0';
  ANALYZE sqlite_master;
  SELECT * FROM t1 WHERE a = 5;
} {5 5}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 8.1 {
  CREATE TABLE t1(x TEXT);
  CREATE INDEX i1 ON t1(x);
  INSERT INTO t1 VALUES('1');
  INSERT INTO t1 VALUES('2');
  INSERT INTO t1 VALUES('3');
  INSERT INTO t1 VALUES('4');
  ANALYZE;
}
do_execsql_test 8.2 {
  SELECT * FROM t1 WHERE x = 3;
} {3}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 9.1 {
  CREATE TABLE t1(a, b, c, d, e);
  CREATE INDEX i1 ON t1(a, b, c, d);
  CREATE INDEX i2 ON t1(e);
}
do_test 9.2 {
  execsql BEGIN;
  for {set i 0} {$i < 100} {incr i} {
    execsql "INSERT INTO t1 VALUES('x', 'y', 'z', $i, [expr $i/2])"
  }
  for {set i 0} {$i < 20} {incr i} {
    execsql "INSERT INTO t1 VALUES('x', 'y', 'z', 101, $i)"
  }
  for {set i 102} {$i < 200} {incr i} {
    execsql "INSERT INTO t1 VALUES('x', 'y', 'z', $i, [expr $i/2])"
  }
  execsql COMMIT
  execsql ANALYZE
} {}

do_eqp_test 9.3.1 {
  SELECT * FROM t1 WHERE a='x' AND b='y' AND c='z' AND d=101 AND e=5;
} {/t1 USING INDEX i1/}
do_eqp_test 9.3.2 {
  SELECT * FROM t1 WHERE a='x' AND b='y' AND c='z' AND d=99 AND e=5;
} {/t1 USING INDEX i1/}

set value_d [expr 101]
do_eqp_test 9.4.1 {
  SELECT * FROM t1 WHERE a='x' AND b='y' AND c='z' AND d=$value_d AND e=5
} {/t1 USING INDEX i1/}
set value_d [expr 99]
do_eqp_test 9.4.2 {
  SELECT * FROM t1 WHERE a='x' AND b='y' AND c='z' AND d=$value_d AND e=5
} {/t1 USING INDEX i1/}

#-------------------------------------------------------------------------
# Check that the planner takes stat3 data into account when considering
# "IS NULL" and "IS NOT NULL" constraints.
#
do_execsql_test 10.1.1 {
  DROP TABLE IF EXISTS t3;
  CREATE TABLE t3(a, b);
  CREATE INDEX t3a ON t3(a);
  CREATE INDEX t3b ON t3(b);
}
do_test 10.1.2 {
  for {set i 1} {$i < 100} {incr i} {
    if {$i>90} { set a $i } else { set a NULL }
    set b [expr $i % 5]
    execsql "INSERT INTO t3 VALUES($a, $b)"
  }
  execsql ANALYZE
} {}
do_eqp_test 10.1.3 {
  SELECT * FROM t3 WHERE a IS NULL AND b = 2
} {/t3 USING INDEX t3b/}
do_eqp_test 10.1.4 {
  SELECT * FROM t3 WHERE a IS NOT NULL AND b = 2
} {/t3 USING INDEX t3a/}

#-------------------------------------------------------------------------
# Check that stat3 data is used correctly with non-default collation
# sequences.
#
foreach {tn schema} {
  1 {
    CREATE TABLE t4(a COLLATE nocase, b);
    CREATE INDEX t4a ON t4(a);
    CREATE INDEX t4b ON t4(b);
  }
  2 {
    CREATE TABLE t4(a, b);
    CREATE INDEX t4a ON t4(a COLLATE nocase);
    CREATE INDEX t4b ON t4(b);
  }
} {
  drop_all_tables
  do_test 11.$tn.1 { execsql $schema } {}

  do_test 11.$tn.2 {
    for {set i 0} {$i < 100} {incr i} {
      if { ($i % 10)==0 } { set a ABC } else { set a DEF }
      set b [expr $i % 5]
        execsql { INSERT INTO t4 VALUES($a, $b) }
    }
    execsql ANALYZE
  } {}

  do_eqp_test 11.$tn.3 {
    SELECT * FROM t4 WHERE a = 'def' AND b = 3;
  } {/t4 USING INDEX t4b/}

  if {$tn==1} {
    set sql "SELECT * FROM t4 WHERE a = 'abc' AND b = 3;"
    do_eqp_test 11.$tn.4 $sql {/t4 USING INDEX t4a/}
  } else {

    set sql "SELECT * FROM t4 WHERE a = 'abc' COLLATE nocase AND b = 3;"
    do_eqp_test 11.$tn.5 $sql {/t4 USING INDEX t4a/}

    set sql "SELECT * FROM t4 WHERE a COLLATE nocase = 'abc' AND b = 3;"
    do_eqp_test 11.$tn.6 $sql {/t4 USING INDEX t4a/}
  }
}

#-------------------------------------------------------------------------
# Test that nothing untoward happens if the stat3 table contains entries
# for indexes that do not exist. Or NULL values in the idx column.
# Or NULL values in any of the other columns.
#
drop_all_tables
do_execsql_test 15.1 {
  CREATE TABLE x1(a, b, UNIQUE(a, b));
  INSERT INTO x1 VALUES(1, 2);
  INSERT INTO x1 VALUES(3, 4);
  INSERT INTO x1 VALUES(5, 6);
  ANALYZE;
  INSERT INTO sqlite_stat3 VALUES(NULL, NULL, NULL, NULL, NULL, NULL);
}
db close
sqlite3 db test.db
do_execsql_test 15.2 { SELECT * FROM x1 } {1 2 3 4 5 6}

do_execsql_test 15.3 {
  INSERT INTO sqlite_stat3 VALUES(42, 42, 42, 42, 42, 42);
}
db close
sqlite3 db test.db
do_execsql_test 15.4 { SELECT * FROM x1 } {1 2 3 4 5 6}

do_execsql_test 15.5 {
  UPDATE sqlite_stat1 SET stat = NULL;
}
db close
sqlite3 db test.db
do_execsql_test 15.6 { SELECT * FROM x1 } {1 2 3 4 5 6}

do_execsql_test 15.7 {
  ANALYZE;
  UPDATE sqlite_stat1 SET tbl = 'no such tbl';
}
db close
sqlite3 db test.db
do_execsql_test 15.8 { SELECT * FROM x1 } {1 2 3 4 5 6}

do_execsql_test 15.9 {
  ANALYZE;
  UPDATE sqlite_stat3 SET neq = NULL, nlt=NULL, ndlt=NULL;
}
db close
sqlite3 db test.db
do_execsql_test 15.10 { SELECT * FROM x1 } {1 2 3 4 5 6}

# This is just for coverage....
do_execsql_test 15.11 {
  ANALYZE;
  UPDATE sqlite_stat1 SET stat = stat || ' unordered';
}
db close
sqlite3 db test.db
do_execsql_test 15.12 { SELECT * FROM x1 } {1 2 3 4 5 6}

#-------------------------------------------------------------------------
# Test that allocations used for sqlite_stat3 samples are included in
# the quantity returned by SQLITE_DBSTATUS_SCHEMA_USED.
#
set one [string repeat x 1000]
set two [string repeat x 2000]
do_test 16.1 {
  reset_db
  execsql {
    CREATE TABLE t1(a, UNIQUE(a));
    INSERT INTO t1 VALUES($one);
    ANALYZE;
  }
  set nByte [lindex [sqlite3_db_status db SCHEMA_USED 0] 1]

  reset_db
  execsql {
    CREATE TABLE t1(a, UNIQUE(a));
    INSERT INTO t1 VALUES($two);
    ANALYZE;
  }
  set nByte2 [lindex [sqlite3_db_status db SCHEMA_USED 0] 1]

  expr {$nByte2 > $nByte+950 && $nByte2 < $nByte+1050}
} {1}

#-------------------------------------------------------------------------
# Test that stat3 data may be used with partial indexes.
#
do_test 17.1 {
  reset_db
  execsql {
    CREATE TABLE t1(a, b, c, d);
    CREATE INDEX i1 ON t1(a, b) WHERE d IS NOT NULL;
    INSERT INTO t1 VALUES(-1, -1, -1, NULL);
    INSERT INTO t1 SELECT 2*a,2*b,2*c,d FROM t1;
    INSERT INTO t1 SELECT 2*a,2*b,2*c,d FROM t1;
    INSERT INTO t1 SELECT 2*a,2*b,2*c,d FROM t1;
    INSERT INTO t1 SELECT 2*a,2*b,2*c,d FROM t1;
    INSERT INTO t1 SELECT 2*a,2*b,2*c,d FROM t1;
    INSERT INTO t1 SELECT 2*a,2*b,2*c,d FROM t1;
  }

  for {set i 0} {$i < 32} {incr i} {
    execsql { INSERT INTO t1 VALUES($i%2, $b, $i/2, 'abc') }
  }
  execsql {ANALYZE main.t1}
} {}

do_catchsql_test 17.1.2 {
  ANALYZE temp.t1;
} {1 {no such table: temp.t1}}

do_eqp_test 17.2 {
  SELECT * FROM t1 WHERE d IS NOT NULL AND a=0;
} {/USING INDEX i1/}
do_eqp_test 17.3 {
  SELECT * FROM t1 WHERE d IS NOT NULL AND a=0;
} {/USING INDEX i1/}

do_execsql_test 17.4 {
  CREATE INDEX i2 ON t1(c) WHERE d IS NOT NULL;
  ANALYZE main.i2;
}
do_eqp_test 17.5 {
  SELECT * FROM t1 WHERE d IS NOT NULL AND a=0;
} {/USING INDEX i1/}
do_eqp_test 17.6 {
  SELECT * FROM t1 WHERE d IS NOT NULL AND a=0 AND b=0 AND c=10;
} {/USING INDEX i2/}

#-------------------------------------------------------------------------
#
do_test 18.1 {
  reset_db
  execsql {
    CREATE TABLE t1(a, b);
    CREATE INDEX i1 ON t1(a, b);
  }
  for {set i 0} {$i < 9} {incr i} {
    execsql {
      INSERT INTO t1 VALUES($i, 0);
      INSERT INTO t1 VALUES($i, 0);
      INSERT INTO t1 VALUES($i, 0);
      INSERT INTO t1 VALUES($i, 0);
      INSERT INTO t1 VALUES($i, 0);
      INSERT INTO t1 VALUES($i, 0);
      INSERT INTO t1 VALUES($i, 0);
      INSERT INTO t1 VALUES($i, 0);
      INSERT INTO t1 VALUES($i, 0);
      INSERT INTO t1 VALUES($i, 0);
      INSERT INTO t1 VALUES($i, 0);
      INSERT INTO t1 VALUES($i, 0);
      INSERT INTO t1 VALUES($i, 0);
      INSERT INTO t1 VALUES($i, 0);
      INSERT INTO t1 VALUES($i, 0);
    }
  }
  execsql ANALYZE
  execsql { SELECT count(*) FROM sqlite_stat3 }
} {9}

#-------------------------------------------------------------------------
# For coverage.
#
ifcapable view {
  do_test 19.1 {
    reset_db 
    execsql {
      CREATE TABLE t1(x, y);
      CREATE INDEX i1 ON t1(x, y);
      CREATE VIEW v1 AS SELECT * FROM t1;
      ANALYZE;
    }
  } {}
}
ifcapable auth {
  proc authproc {op args} {
    if {$op == "SQLITE_ANALYZE"} { return "SQLITE_DENY" }
    return "SQLITE_OK"
  }
  do_test 19.2 {
    reset_db 
    db auth authproc
    execsql {
      CREATE TABLE t1(x, y);
      CREATE VIEW v1 AS SELECT * FROM t1;
    }
    catchsql ANALYZE
  } {1 {not authorized}}
}

#-------------------------------------------------------------------------
#
reset_db
proc r {args} { expr rand() }
db func r r
db func lrange lrange
do_test 20.1 {
  execsql {
    CREATE TABLE t1(a,b,c,d);
    CREATE INDEX i1 ON t1(a,b,c,d);
  }
  for {set i 0} {$i < 16} {incr i} {
    execsql {
      INSERT INTO t1 VALUES($i, r(), r(), r());
      INSERT INTO t1 VALUES($i, $i,  r(), r());
      INSERT INTO t1 VALUES($i, $i,  $i,  r());
      INSERT INTO t1 VALUES($i, $i,  $i,  $i);
      INSERT INTO t1 VALUES($i, $i,  $i,  $i);
      INSERT INTO t1 VALUES($i, $i,  $i,  r());
      INSERT INTO t1 VALUES($i, $i,  r(), r());
      INSERT INTO t1 VALUES($i, r(), r(), r());
    }
  }
} {}
do_execsql_test 20.2 { ANALYZE }
for {set i 0} {$i<16} {incr i} {
    set val $i
    do_execsql_test 20.3.$i {
      SELECT count(*) FROM sqlite_stat3 WHERE sample=$val
    } {1}
}

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.
127
128
129
130
131
132
133














134
135
136
137
138
139
140
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+







  ANALYZE sqlite_master;
  SELECT count(a) FROM t1;
} {6}
do_execsql_test 4.3 {
  EXPLAIN QUERY PLAN
  SELECT count(a) FROM t1;
} {/.*INDEX t1ca.*/}

# 2019-08-15.
# Ticket https://www.sqlite.org/src/tktview/e4598ecbdd18bd82945f602901
# The sz=N parameter in the sqlite_stat1 table needs to have a value of
# 2 or more to avoid a division by zero in the query planner.
#
do_execsql_test 4.4 {
  DROP TABLE IF EXISTS t44;
  CREATE TABLE t44(a PRIMARY KEY);
  INSERT INTO sqlite_stat1 VALUES('t44',null,'sz=0');
  ANALYZE sqlite_master;
  SELECT 0 FROM t44 WHERE a IN(1,2,3);
} {}



# The sz=NNN parameter works even if there is other extraneous text
# in the sqlite_stat1.stat column.
#
do_execsql_test 5.0 {
  DELETE FROM sqlite_stat1;

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 }

Added test/analyzeG.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2020-02-23
#
# 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.
#
#***********************************************************************
# Tests for functionality related to ANALYZE.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable !stat4 {
  finish_test
  return
}
set testprefix analyzeG

#-------------------------------------------------------------------------
# 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;
  CREATE TABLE t1(a, x);
  CREATE TABLE t2(b, y);
  WITH s(i) AS (
    SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<100
  )
  INSERT INTO t1 SELECT (i%50), NULL FROM s;
  WITH s(i) AS (
    SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<100
  )
  INSERT INTO t2 SELECT (CASE WHEN i<95 THEN 44 ELSE i END), NULL FROM s;
}

# 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_eqp_test 1.1.1 {
  SELECT * FROM t1, t2 WHERE a=44 AND b=44;
} {

}
do_eqp_test 1.1.2 {
  SELECT * FROM t2, t1 WHERE a=44 AND b=44 
} {
  QUERY PLAN
  |--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_eqp_test 1.3.1 {
  SELECT * FROM t1, t2 WHERE a=44 AND b=44;
} {
  QUERY PLAN
  |--SCAN t1
  `--SCAN t2
}
do_eqp_test 1.3.2 {
  SELECT * FROM t2, t1 WHERE a=44 AND b=44 
} {
  QUERY PLAN
  |--SCAN t1
  `--SCAN t2
}


finish_test

Changes to test/atof1.test.

15
16
17
18
19
20
21




22
23
24
25
26
27
28
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32







+
+
+
+







set testdir [file dirname $argv0]
source $testdir/tester.tcl

if {$::longdouble_size<=8} {
  finish_test
  return
}
if {$::tcl_platform(machine)!="x86_64"} {
  finish_test
  return
}

expr srand(1)
for {set i 1} {$i<20000} {incr i} {
  set pow [expr {int((rand()-0.5)*100)}]
  set x [expr {pow((rand()-0.5)*2*rand(),$pow)}]
  set xf [format %.32e $x]

51
52
53
54
55
56
57
58




59





















60
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








+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

      puts [format {QUOTE: %16s %s} {} [db eval {SELECT quote($x)}]]
      db eval {SELECT CAST(quote($x) AS real) c} {}
      puts "OUT:   $b [format %.32e $c]"
    }
    set y
  } {1}
}

# 2020-01-08 ticket 9eda2697f5cc1aba
# When running sqlite3AtoF() on a blob with an odd number of bytes using
# UTF16, ignore the last byte so that the string has an integer number of
# UTF16 code points.

#
reset_db
do_execsql_test atof1-2.10 {
  PRAGMA encoding = 'UTF16be';
  CREATE TABLE t1(a, b);
  INSERT INTO t1(rowid,a) VALUES (1,x'00'),(2,3);
  SELECT substr(a,',') is true FROM t1 ORDER BY rowid;
} {0 1}
do_execsql_test atof1-2.20 {
  SELECT substr(a,',') is true FROM t1 ORDER BY rowid DESC;
} {1 0}
do_execsql_test atof1-2.30 {
  CREATE INDEX i1 ON t1(a);
  SELECT count(*) FROM t1 WHERE substr(a,',');
} {1}
# 2020-08-27 OSSFuzz find related to the above.
do_execsql_test atof1-2.40 {
  SELECT randomblob(0) - 1;
} {-1}


finish_test

Changes to test/atrc.c.

71
72
73
74
75
76
77
78

79
80
81
82
83
84
85
71
72
73
74
75
76
77

78
79
80
81
82
83
84
85







-
+







  sqlite3_str *pUndo        /* Append SQL to undo the rename here */
){
  sqlite3_stmt *pStmt;
  int rc;
  int cnt = 0;

  rc = sqlite3_prepare_v2(db,
         "SELECT name FROM sqlite_master WHERE type='table'"
         "SELECT name FROM sqlite_schema WHERE type='table'"
         " AND name NOT LIKE 'sqlite_%';",
         -1, &pStmt, 0);
  if( rc ) return rc;
  while( sqlite3_step(pStmt)==SQLITE_ROW ){
    const char *zTab = (const char*)sqlite3_column_text(pStmt, 0);
    char *zNewTab;
    char zPrefix[2];

Changes to test/attach.test.

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
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







-
+
-
-
+
-








-
+
-
-
+
-







  }
} {1 {database db5 is already in use}}
do_test attach-1.14 {
  catchsql {
    ATTACH 'test.db' as db9;
  }
} {1 {database db9 is already in use}}
do_test attach-1.15 {
do_catchsql_test attach-1.15 {
  catchsql {
    ATTACH 'test.db' as main;
  ATTACH 'test.db' as main;
  }
} {1 {database main is already in use}}
ifcapable tempdb {
  do_test attach-1.16 {
    catchsql {
      ATTACH 'test.db' as temp;
    }
  } {1 {database temp is already in use}}
}
do_test attach-1.17 {
do_catchsql_test attach-1.17 {
  catchsql {
    ATTACH 'test.db' as MAIN;
  ATTACH 'test.db' as MAIN;
  }
} {1 {database MAIN is already in use}}
do_test attach-1.18 {
  catchsql {
    ATTACH 'test.db' as db10;
    ATTACH 'test.db' as db11;
  }
} {0 {}}
226
227
228
229
230
231
232

233
234
235
236
237
238
239
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236







+







  }
} {1 {no such database: db12}}
do_test attach-1.26 {
  catchsql {
    DETACH main;
  }
} {1 {cannot detach database main}}


ifcapable tempdb {
  do_test attach-1.27 {
    catchsql {
      DETACH Temp;
    }
  } {1 {cannot detach database Temp}}
908
909
910
911
912
913
914
915















916
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  CREATE TABLE db2.Table2(col1 INTEGER, col2 INTEGER, col3 INTEGER, col4);
  CREATE UNIQUE INDEX db2.idx_col1_unique ON Table2 (col1);
  CREATE UNIQUE INDEX db2.idx_col23_unique ON Table2 (col2, col3);
  CREATE INDEX db2.idx_col2 ON Table2 (col2);
  INSERT INTO Table2 VALUES(1,2,3,4);
  PRAGMA integrity_check;
} {ok}

# 2021-03-10 Forum post https://sqlite.org/forum/forumpost/a006d86f72
#
reset_db
do_test attach-13.1 {
  sqlite3 db :memory:
  db eval {CREATE TABLE base(x);}
  for {set i 0} {$i<$SQLITE_MAX_ATTACHED} {incr i} {
    db eval "ATTACH ':memory:' AS a$i"
  }
  set m "a[expr {$SQLITE_MAX_ATTACHED-1}]"
  db eval "CREATE TABLE $m.t1(a INTEGER PRIMARY KEY, b);"
  db eval "CREATE TABLE $m.t2(a INTEGER PRIMARY KEY, b);"
  db eval {SELECT a FROM t1 WHERE b IN (SELECT a FROM t2);}
} {}

finish_test

Changes to test/attach2.test.

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







+







# and related functionality.
#
# $Id: attach2.test,v 1.38 2007/12/13 21:54:11 drh Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix attach2

ifcapable !attach {
  finish_test
  return
}

# Ticket #354
383
384
385
386
387
388
389
390



























































391
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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

do_test attach2-6.3 {
  catchsql {
    DETACH aux;
  }
} {0 {}}

db close

ifcapable utf16 {
  forcedelete test.db2      ;# utf-16
  forcedelete test.db3      ;# utf-16
  forcedelete test.db4      ;# utf-8
  
  sqlite3 db2 test.db2 
  do_execsql_test -db db2 1.1 {
    PRAGMA encoding = 'utf16';
    CREATE TABLE t2(x);
    INSERT INTO t2 VALUES('text2');
  }
  db2 close
  
  sqlite3 db3 test.db3 
  do_execsql_test -db db3 1.2 {
    PRAGMA encoding = 'utf16';
    CREATE TABLE t3(x);
    INSERT INTO t3 VALUES('text3');
  }
  db3 close
  
  sqlite3 db4 test.db4 
  do_execsql_test -db db4 1.3 {
    PRAGMA encoding = 'utf8';
    CREATE TABLE t4(x);
    INSERT INTO t4 VALUES('text4');
  }
  db4 close
  
  reset_db
  do_execsql_test 2.1 {
    PRAGMA encoding = 'utf16';
    ATTACH 'test.db2' AS aux;
    SELECT * FROM t2;
  } {text2}
  
  reset_db
  do_execsql_test 2.2 {
    ATTACH 'test.db4' AS aux;
    SELECT * FROM t4;
  } {text4}
  
  db close
  sqlite3 db test.db2
  do_execsql_test 2.3 {
    ATTACH 'test.db3' AS aux;
    SELECT * FROM t3;
    SELECT * FROM t2;
  } {text3 text2}
  
  db close
  sqlite3 db test.db2
  do_catchsql_test 2.4 {
    ATTACH 'test.db4' AS aux;
  } {1 {attached databases must use the same text encoding as main database}}
  
  db close
}

finish_test

Changes to test/attach4.test.

110
111
112
113
114
115
116



















117
118
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


    lappend L $name [execsql "SELECT x FROM $name.tbl"]
  }
  set L
} $files

db close
foreach {name f} $files { forcedelete $f }

#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.0 {
  ATTACH DATABASE '' AS aux;
  CREATE TABLE IF NOT EXISTS aux.t1(a, b);
  CREATE TEMPORARY TRIGGER tr1 DELETE ON t1 BEGIN 
    DELETE FROM t1; 
  END;
  CREATE TABLE temp.t1(a, b);
}

do_execsql_test 2.1 {
  DETACH DATABASE aux;
}

do_execsql_test 2.2 {
  DROP TRIGGER tr1;
}

finish_test

Changes to test/attachmalloc.test.

57
58
59
60
61
62
63

64
65
66
67
68
69
70
71
72
73
74
75












76
77
57
58
59
60
61
62
63
64












65
66
67
68
69
70
71
72
73
74
75
76
77
78







+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+


  }
  db2 close
} -sqlbody {
  CREATE TABLE t1(d, e, f);
  ATTACH 'test2.db' AS db1;
}

ifcapable shared_cache {
set enable_shared_cache [sqlite3_enable_shared_cache 1]
sqlite3 dbaux test3.db
dbaux eval {SELECT * FROM sqlite_master}
do_malloc_test attachmalloc-3 -sqlbody {
  SELECT * FROM sqlite_master;
  ATTACH 'test3.db' AS three;
} -cleanup {
  db eval { DETACH three }
}
dbaux close
sqlite3_enable_shared_cache $enable_shared_cache

  set enable_shared_cache [sqlite3_enable_shared_cache 1]
  sqlite3 dbaux test3.db
  dbaux eval {SELECT * FROM sqlite_master}
  do_malloc_test attachmalloc-3 -sqlbody {
    SELECT * FROM sqlite_master;
    ATTACH 'test3.db' AS three;
  } -cleanup {
    db eval { DETACH three }
  }
  dbaux close
  sqlite3_enable_shared_cache $enable_shared_cache
}

finish_test

Changes to test/auth.test.

1387
1388
1389
1390
1391
1392
1393
1394

1395
1396














1397
1398
1399
1400
1401
1402
1403
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







-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+







      set ::authargs [list $arg1 $arg2 $arg3 $arg4]
      return SQLITE_DENY
    }
    return SQLITE_OK
  }
  catchsql {DROP INDEX i2}
} {1 {not authorized}}
do_test auth-1.206 {
do_test auth-1.205a {
  set ::authargs
} {i2 t2 main {}}
db eval {
  ATTACH ':memory:' as di205;
  CREATE TABLE di205.t1(x);
  CREATE INDEX di205.t1x ON t1(x);
}
do_catchsql_test auth-1.205b {
  DROP INDEX di205.t1x;
} {1 {not authorized}}
db eval {
  DETACH di205;
}
do_test auth-1.206 {
  set ::authargs
} {t1x t1 di205 {}}
do_test auth-1.207 {
  execsql {SELECT name FROM sqlite_master}
} {t2 i2}
do_test auth-1.208 {
  proc auth {code arg1 arg2 arg3 arg4 args} {
    if {$code=="SQLITE_DELETE" && $arg1=="sqlite_master"} {
      return SQLITE_IGNORE
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
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
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







+
+
+
+
+
+
+
+
+



















+
+
+
+
+
+
+
+
+
+
















-



+
+
+
+
+
+
+
+
+
+
+
+
+







  do_test auth-1.301 {
    set x [execsql {SELECT sql FROM sqlite_master WHERE name='t5'}]
    regexp new_col_1 $x
  } {1}
  do_test auth-1.302 {
    set authargs
  } {main t5 {} {}}
  db eval BEGIN
  set authargs {}
  do_execsql_test auth-1.302-drop-1 {
    ALTER TABLE t5 DROP COLUMN new_col_1;
  } {}
  db eval ROLLBACK
  do_test auth-1.302-drop-2 {
    set authargs
  } {main t5 new_col_1 {}}
  do_test auth-1.303 {
    proc auth {code arg1 arg2 arg3 arg4 args} {
      if {$code=="SQLITE_ALTER_TABLE"} {
        set ::authargs [list $arg1 $arg2 $arg3 $arg4]
        return SQLITE_IGNORE
      }
      return SQLITE_OK
    }
    catchsql {
      ALTER TABLE t5 ADD COLUMN new_col_2;
    }
  } {0 {}}
  do_test auth-1.304 {
    set x [execsql {SELECT sql FROM sqlite_master WHERE name='t5'}]
    regexp new_col_2 $x
  } {0}
  do_test auth-1.305 {
    set authargs
  } {main t5 {} {}}
  db eval BEGIN
  set authargs {}
  do_execsql_test auth-1.305-drop-1 {
     ALTER TABLE t5 DROP COLUMN new_col_1;
     SELECT 1 FROM sqlite_schema WHERE name='t5' AND sql LIKE '%new_col_1%';
  } {1}
  db eval ROLLBACK
  do_test auth-1.305-drop-2 {
    set authargs
  } {main t5 new_col_1 {}}
  do_test auth-1.306 {
    proc auth {code arg1 arg2 arg3 arg4 args} {
      if {$code=="SQLITE_ALTER_TABLE"} {
        set ::authargs [list $arg1 $arg2 $arg3 $arg4]
        return SQLITE_DENY
      }
      return SQLITE_OK
    }
    catchsql {
      ALTER TABLE t5 ADD COLUMN new_col_3
    }
  } {1 {not authorized}}
  do_test auth-1.307 {
    set x [execsql {SELECT sql FROM temp.sqlite_master WHERE type='t5'}]
    regexp new_col_3 $x
  } {0}

  do_test auth-1.308 {
    set authargs
  } {main t5 {} {}}
  db eval BEGIN
  set authargs {}
  do_catchsql_test auth-1.308-drop-1 {
    ALTER TABLE t5 DROP COLUMN new_col_1;
  } {1 {not authorized}}
  do_execsql_test auth-1.308-drop-2 {
    SELECT 1 FROM sqlite_schema WHERE name='t5' AND sql LIKE '%new_col_1%';
  } {1}
  do_test auth-1.308-drop-3 {
    set authargs
  } {main t5 new_col_1 {}}
  db eval ROLLBACK

  execsql {DROP TABLE t5}
} ;# ifcapable altertable

ifcapable {cte} {
  do_test auth-1.310 {
    proc auth {code arg1 arg2 arg3 arg4 args} {
      if {$code=="SQLITE_RECURSIVE"} {
2141
2142
2143
2144
2145
2146
2147
2148

2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166

2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184

2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196

2197
2198
2199

2200
2201
2202
2203













2204
2205
2206
2207
2208
2209
2210
2186
2187
2188
2189
2190
2191
2192

2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
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
2234
2235
2236
2237
2238
2239
2240

2241
2242
2243

2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268







-
+

















-
+

















-
+











-
+


-
+




+
+
+
+
+
+
+
+
+
+
+
+
+







#    MAIN: CREATE TABLE t4(a,b,c);
#    MAIN: CREATE INDEX t4i1 ON t4(a);
#    MAIN: CREATE INDEX t4i2 ON t4(b,a,c);
#    MAIN: CREATE TABLE sqlite_stat1(tbl,idx,stat);
#    MAIN: CREATE TABLE t1(a,b);
#
ifcapable altertable&&vtab {
  do_test 1.350 {
  do_test auth-1.350 {
    proc auth {code arg1 arg2 arg3 arg4 args} {
      if {$code=="SQLITE_ALTER_TABLE"} {
        set ::authargs [list $arg1 $arg2 $arg3 $arg4]
        return SQLITE_OK
      }
      return SQLITE_OK
    }
    catchsql {
      ALTER TABLE t1 RENAME COLUMN b TO bcdefg;
    }
  } {0 {}}
  do_execsql_test auth-1.351 {
    SELECT name FROM pragma_table_info('t1') ORDER BY cid;
  } {a bcdefg}
  do_test auth-1.352 {
    set authargs
  } {main t1 {} {}}
  do_test 1.353 {
  do_test auth-1.353 {
    proc auth {code arg1 arg2 arg3 arg4 args} {
      if {$code=="SQLITE_ALTER_TABLE"} {
        set ::authargs [list $arg1 $arg2 $arg3 $arg4]
        return SQLITE_IGNORE
      }
      return SQLITE_OK
    }
    catchsql {
      ALTER TABLE t1 RENAME COLUMN bcdefg TO b;
    }
  } {0 {}}
  do_execsql_test auth-1.354 {
    SELECT name FROM pragma_table_info('t1') ORDER BY cid;
  } {a bcdefg}
  do_test auth-1.355 {
    set authargs
  } {main t1 {} {}}
  do_test 1.356 {
  do_test auth-1.356 {
    proc auth {code arg1 arg2 arg3 arg4 args} {
      if {$code=="SQLITE_ALTER_TABLE"} {
        set ::authargs [list $arg1 $arg2 $arg3 $arg4]
        return SQLITE_DENY
      }
      return SQLITE_OK
    }
    catchsql {
      ALTER TABLE t1 RENAME COLUMN bcdefg TO b;
    }
  } {1 {not authorized}}
  do_execsql_test auth-1.356 {
  do_execsql_test auth-1.357 {
    SELECT name FROM pragma_table_info('t1') ORDER BY cid;
  } {a bcdefg}
  do_test auth-1.357 {
  do_test auth-1.358 {
    set authargs
  } {main t1 {} {}}
}

# 2022-12-28
# The sqlite3_declare_vtab() call that occurs during pragma_table_list
# should not cause an authentication failure.
#
do_test auth-1.359 {
  proc auth {code arg1 arg2 arg3 arg4 args} {
    if {$code=="SQLITE_UPDATE"} {
      return SQLITE_DENY
    }
    return SQLITE_OK
  }
  catchsql {SELECT * FROM pragma_table_list WHERE name='xyzzy';}
} {0 {}}

do_test auth-2.1 {
  proc auth {code arg1 arg2 arg3 arg4 args} {
    if {$code=="SQLITE_READ" && $arg1=="t3" && $arg2=="x"} {
      return SQLITE_DENY
    }
    return SQLITE_OK
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456

2457
2458
2459
2460
2461
2462
2463
2464
2504
2505
2506
2507
2508
2509
2510




2511

2512
2513
2514
2515
2516
2517
2518







-
-
-
-
+
-







        DROP TABLE v1chng;
      }
    }
  }
  ifcapable stat4 {
    set stat4 "sqlite_stat4 "
  } else {
    ifcapable stat3 {
      set stat4 "sqlite_stat3 "
    } else {
      set stat4 ""
    set stat4 ""
    }
  }
  do_test auth-5.2 {
    execsql {
      SELECT name FROM (
        SELECT * FROM sqlite_master UNION ALL SELECT * FROM temp.sqlite_master)
      WHERE type='table'
      ORDER BY name

Changes to test/auth3.test.

111
112
113
114
115
116
117

118
119
120
121
122
123
124
125
126
127
128
129
130














131
132
111
112
113
114
115
116
117
118













119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134







+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+


  set sqlite_search_count
} {1}

# 2016-07-28.  A problem report from a private client complaining about
# an authorizer failure during an ALTER TABLE.  The solution (I think) is
# to disable the authorizer during schema parsing.
#
ifcapable altertable {
proc auth {code args} {
  if {$code=="SQLITE_READ" && [regexp {DoNotRead} $args]} {
    return SQLITE_DENY
  }
  return SQLITE_OK
}
do_execsql_test auth3-3.0 {
  CREATE TEMPORARY TABLE TempTable (
      key TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE,
      value TEXT NOT NULL ON CONFLICT FAIL);
  ALTER TABLE TempTable RENAME TO DoNotRead;
  SELECT name FROM temp.sqlite_master;
} {DoNotRead sqlite_autoindex_DoNotRead_1}
  proc auth {code args} {
    if {$code=="SQLITE_READ" && [regexp {DoNotRead} $args]} {
      return SQLITE_DENY
    }
    return SQLITE_OK
  }
  do_execsql_test auth3-3.0 {
    CREATE TEMPORARY TABLE TempTable (
        key TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE,
        value TEXT NOT NULL ON CONFLICT FAIL);
    ALTER TABLE TempTable RENAME TO DoNotRead;
    SELECT name FROM temp.sqlite_master;
  } {DoNotRead sqlite_autoindex_DoNotRead_1}
}

finish_test

Changes to test/autoinc.test.

12
13
14
15
16
17
18

19
20
21
22
23
24
25
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26







+







# focus of this script is testing the AUTOINCREMENT features.
#
# $Id: autoinc.test,v 1.14 2009/06/23 20:28:54 drh Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix autoinc

# If the library is not compiled with autoincrement support then
# skip all tests in this file.
#
ifcapable {!autoinc} {
  finish_test
  return
851
852
853
854
855
856
857
858























859
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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  set res [catch {db eval {
    INSERT INTO t1(b) VALUES('two'),('three'),('four');
    INSERT INTO t1(b) VALUES('five');
    PRAGMA integrity_check;
  }} msg]
  lappend res $msg
} {0 ok}

#--------------------------------------------------------------------------
reset_db
do_execsql_test 13.0 {
  CREATE TABLE t1(i INTEGER PRIMARY KEY AUTOINCREMENT, j);
  CREATE TABLE t2(i INTEGER PRIMARY KEY AUTOINCREMENT, j);
  CREATE TABLE t3(i INTEGER PRIMARY KEY AUTOINCREMENT, j);

  INSERT INTO t1 VALUES(NULL, 1);
  INSERT INTO t2 VALUES(NULL, 2);
  INSERT INTO t3 VALUES(NULL, 3);

  SELECT name FROM sqlite_sequence;
} {t1 t2 t3}

do_execsql_test 13.1 {
  UPDATE sqlite_sequence SET name=NULL WHERE name='t2';
  INSERT INTO t3 VALUES(NULL, 4);
  DELETE FROM t3;
  INSERT INTO t3 VALUES(NULL, 5);
  SELECT * FROM t3;
} {3 5}


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=?)
  `--LIST SUBQUERY
     `--SCAN TABLE t502
  |--SEARCH t501 USING INTEGER PRIMARY KEY (rowid=?)
  `--LIST SUBQUERY xxxxxx
     `--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
  `--CORRELATED LIST SUBQUERY
     `--SEARCH TABLE t502 USING AUTOMATIC COVERING INDEX (y=?)
  |--SCAN t501
  `--CORRELATED LIST SUBQUERY xxxxxx
     `--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=?)
  `--CORRELATED LIST SUBQUERY
     `--SCAN TABLE t502
  |--SEARCH t501 USING INTEGER PRIMARY KEY (rowid=?)
  `--CORRELATED LIST SUBQUERY xxxxxx
     `--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<?)
  |  `--CORRELATED SCALAR SUBQUERY
  |     `--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=?)
  |--MATERIALIZE y
  |  |--SCAN s
  |  |--SEARCH prev USING INDEX sqlite_autoindex_flock_owner_1 (flock_no=? AND owner_change_date<?)
  |  `--CORRELATED SCALAR SUBQUERY xxxxxx
  |     `--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=?) LEFT-JOIN
}


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.
538
539
540
541
542
543
544
545
546


















547
548
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







-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


  INSERT INTO t11 VALUES(NULL);
  INSERT INTO t12 VALUES('notnull');
}
do_execsql_test autoindex1-1020 {
  SELECT count(*) FROM t11 LEFT JOIN t12 WHERE t12.y IS t11.w;
} 0



# 2022-04-25
# https://sqlite.org/forum/forumpost/0d3200f4f3bcd3a3
#
reset_db
do_execsql_test autoindex-1100 {
  CREATE TABLE t1(a INT, b INT);
  CREATE TABLE t2(c INT, d INT);
  CREATE TABLE t3(e TEXT, f TEXT);
  INSERT INTO t1 VALUES(1, 1);
  INSERT INTO t2 VALUES(1, 2);
  INSERT INTO t3 VALUES('abc', 'def');
} {}
do_execsql_test autoindex-1110 {
  SELECT * FROM t1, t2 LEFT JOIN t3 ON (t2.d=1) WHERE t2.c = +t1.a;
} {1 1 1 2 {} {}}
do_execsql_test autoindex-1120 {
  SELECT * FROM t1 LEFT JOIN t2 ON (t2.c=+t1.a) LEFT JOIN t3 ON (t2.d IS NULL);
} {1 1 1 2 {} {}}

finish_test

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/autoindex4.test.

28
29
30
31
32
33
34



35
36
37



38
39
40



41
42
43
44
45
46
47
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







+
+
+



+
+
+



+
+
+







do_execsql_test autoindex4-1.1 {
  SELECT *, '|' FROM t1, t2 WHERE a=234 AND x=555;
} {}

do_execsql_test autoindex4-1.2 {
  SELECT *, '|' FROM t1 LEFT JOIN t2 ON a=234 AND x=555;
} {123 abc {} {} | 234 def {} {} | 234 ghi {} {} | 345 jkl {} {} |}
do_execsql_test autoindex4-1.2-rj {
  SELECT t1.*, t2.*, '|' FROM t2 RIGHT JOIN t1 ON a=234 AND x=555;
} {123 abc {} {} | 234 def {} {} | 234 ghi {} {} | 345 jkl {} {} |}
do_execsql_test autoindex4-1.3 {
  SELECT *, '|' FROM t1 LEFT JOIN t2 ON x=555 WHERE a=234;
} {234 def {} {} | 234 ghi {} {} |}
do_execsql_test autoindex4-1.3-rj {
  SELECT t1.*, t2.*, '|' FROM t2 RIGHT JOIN t1 ON x=555 WHERE a=234;
} {234 def {} {} | 234 ghi {} {} |}
do_execsql_test autoindex4-1.4 {
  SELECT *, '|' FROM t1 LEFT JOIN t2 WHERE a=234 AND x=555;
} {}
do_execsql_test autoindex4-1.4-rj {
  SELECT t1.*, t2.*, '|' FROM t2 RIGHT JOIN t1 WHERE a=234 AND x=555;
} {}


do_execsql_test autoindex4-2.0 {
  CREATE TABLE t3(e,f);
  INSERT INTO t3 VALUES(123,654),(555,444),(234,987);

  SELECT (SELECT count(*) FROM t1, t2 WHERE a=e AND x=f), e, f, '|'
65
66
67
68
69
70
71








72
73
74
75
76
77
78
79
80





































































































81
82
83
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







+
+
+
+
+
+
+
+









+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



    FROM Items
      LEFT JOIN A ON (A.Name = Items.ItemName and Items.ItemName = 'dummy')
      LEFT JOIN B ON (B.Name = Items.ItemName)
    WHERE Items.Name = 'Parent'
    ORDER BY Items.ItemName;
} {Item1 Item2}
do_execsql_test autoindex4-3.1 {
  SELECT Items.ItemName
    FROM A
      RIGHT JOIN Items ON (A.Name = Items.ItemName and Items.ItemName = 'dummy')
      LEFT JOIN B ON (B.Name = Items.ItemName)
    WHERE Items.Name = 'Parent'
    ORDER BY Items.ItemName;
} {Item1 Item2}
do_execsql_test autoindex4-3.10 {
  CREATE INDEX Items_x1 ON Items(ItemName,Name) WHERE ItemName = 'dummy';
  
  SELECT Items.ItemName
    FROM Items
      LEFT JOIN A ON (A.Name = Items.ItemName and Items.ItemName = 'dummy')
      LEFT JOIN B ON (B.Name = Items.ItemName)
    WHERE Items.Name = 'Parent'
    ORDER BY Items.ItemName;
} {Item1 Item2}
do_execsql_test autoindex4-3.11 {
  SELECT Items.ItemName
    FROM A
      RIGHT JOIN Items ON (A.Name = Items.ItemName and Items.ItemName = 'dummy')
      LEFT JOIN B ON (B.Name = Items.ItemName)
    WHERE Items.Name = 'Parent'
    ORDER BY Items.ItemName;
} {Item1 Item2}

# 2021-11-30 - Enhancement to help the automatic index mechanism to
# create a partial index more often.
#
unset -nocomplain id data1 data2 jointype onclause whereclause answer
foreach {id data1 data2 jointype onclause whereclause answer} {
  1
  VALUES(1,2),(3,4)
  VALUES(1,2),(3,4)
  {LEFT JOIN}
  a=x
  {y=4 OR y IS NULL}
  {3 4 3 4}

  2
  VALUES(1,2),(3,4)
  VALUES(1,2),(3,4)
  {LEFT JOIN}
  {a=x AND y=4}
  {coalesce(y,4)==4}
  {1 2 {} {} 3 4 3 4}

  3
  VALUES(1,2),(3,4)
  VALUES(1,2),(3,4)
  {JOIN}
  {a=x}
  {y=4 OR y IS NULL}
  {3 4 3 4}

  4
  VALUES(1,2),(3,4)
  VALUES(1,2),(3,4)
  {JOIN}
  {a=x AND y=4}
  {coalesce(y,4)==4}
  {3 4 3 4}

  5
  VALUES(1,2),(3,4),(NULL,4)
  VALUES(1,2),(3,4)
  {LEFT JOIN}
  a=x
  {y=4 OR y IS NULL}
  {3 4 3 4 {} 4 {} {}}

  6
  VALUES(1,2),(3,4)
  VALUES(1,2),(3,4),(NULL,4)
  {LEFT JOIN}
  {a=x AND y=4}
  {coalesce(y,4)==4}
  {1 2 {} {} 3 4 3 4}

  7
  VALUES(1,2),(3,4),(NULL,4)
  VALUES(1,2),(3,4),(NULL,4)
  {JOIN}
  {a=x}
  {y=4 OR y IS NULL}
  {3 4 3 4}

  8
  VALUES(1,2),(3,4)
  VALUES(1,2),(3,4)
  {JOIN}
  {a=x AND y=4}
  {coalesce(y,4)==4}
  {3 4 3 4}
} {
  do_test autoindex4-4.$id.0 {
    db eval {
       DROP TABLE IF EXISTS t1;
       CREATE TABLE t1(a INT, b INT);
       DROP TABLE IF EXISTS t2;
       CREATE TABLE t2(x INT, y INT);
    }
    db eval "INSERT INTO t1(a,b) $data1;"
    db eval "INSERT INTO t2(x,y) $data2;"
  } {}
  set sql "SELECT * FROM t1 $jointype t2 ON $onclause WHERE $whereclause"
  # puts "sql = $sql"
  do_test autoindex4-4.$id.1 {
    db eval {PRAGMA automatic_index=ON;}
    db eval $sql
  } $answer
  do_test autoindex4-4.$id.2 {
    db eval {PRAGMA automatic_index=OFF;}
    db eval $sql
  } $answer
}




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
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







-
+




















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





+







  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}

# At one point the following was returning "no such column: rowid". This
# was incorrect - "rowid" matches against the rowid of table t1 in this
# query.
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
    )
  );
} {0 9}

# 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:
do_execsql_test 3.0 {
  -- This is the original test case reported on the mailing list
  CREATE TABLE artists (
    id integer NOT NULL PRIMARY KEY AUTOINCREMENT,
    name varchar(255)
  );
162
163
164
165
166
167
168


169
170
171
172
173
174
175
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196







+
+







          WHERE (name = 'Al')
        ) AS 't1'
        WHERE (x = 1)
      ))
      AND (albums.id IN (1, 2)))
  ));
} {1 Ar}
} ;# windowfunc

# The remaining test cases were discovered (by Dan) during trouble-shooting
sqlite3 db :memory:
do_execsql_test 3.1 {
  CREATE TABLE t1 (a); INSERT INTO t1 (a) VALUES (104);
  CREATE TABLE t2 (b); INSERT INTO t2 (b) VALUES (104);
  CREATE TABLE t3 (c); INSERT INTO t3 (c) VALUES (104);
  CREATE TABLE t4 (d); INSERT INTO t4 (d) VALUES (104);

Changes to test/autovacuum.test.

1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11

12
13

14
15
16
17
18
19
20











-
+

-







# 2001 September 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 the SELECT statement.
# focus of this file is testing the autovacuum feature.
#
# $Id: autovacuum.test,v 1.29 2009/04/06 17:50:03 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# If this build of the library does not support auto-vacuum, omit this
# whole file.
ifcapable {!autovacuum || !pragma} {

Added test/autovacuum2.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2021-10-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 the sqlite3_autovacuum_pages() interface
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# If this build of the library does not support auto-vacuum, omit this
# whole file.
ifcapable {!autovacuum || !pragma} {
  finish_test
  return
}

# Demonstrate basic sqlite3_autovacuum_pages functionality
#
do_execsql_test autovacuum2-1.0 {
  PRAGMA page_size=1024;
  PRAGMA auto_vacuum=FULL;
  CREATE TABLE t1(x);
  VACUUM;
  INSERT INTO t1(x) VALUES(zeroblob(10000));
  PRAGMA page_count;
} {12}
proc autovac_page_callback {schema filesize freesize pagesize} {
  global autovac_callback_data
  lappend autovac_callback_data $schema $filesize $freesize $pagesize
  return [expr {$freesize/2}]
}
sqlite3_autovacuum_pages db autovac_page_callback
set autovac_callback_data {}
do_execsql_test autovacuum2-1.1 {
  BEGIN;
  DELETE FROM t1;
  PRAGMA freelist_count;
  PRAGMA page_count;
} {9 12}
do_execsql_test autovacuum2-1.2 {
  COMMIT;
} {}
do_test autovacuum2-1.3 {
  set autovac_callback_data
} {main 12 9 1024}
do_execsql_test autovacuum2-1.4 {
  PRAGMA freelist_count;
  PRAGMA page_count;
} {5 8}
do_execsql_test autovacuum2-1.5 {
  PRAGMA integrity_check;
} {ok}

# Disable the autovacuum-pages callback.  Then do any transaction.
# The database should shrink to minimal size
#
sqlite3_autovacuum_pages db
do_execsql_test autovacuum2-1.10 {
  CREATE TABLE t2(x);
  PRAGMA freelist_count;
} {0}

# Rig the autovacuum-pages callback to always return zero.  No
# autovacuum will happen.
#
proc autovac_page_callback_off {schema filesize freesize pagesize} {
  return 0
}
sqlite3_autovacuum_pages db autovac_page_callback_off
do_execsql_test autovacuum2-1.20 {
  BEGIN;
  INSERT INTO t1(x) VALUES(zeroblob(10000));
  DELETE FROM t1;
  PRAGMA freelist_count;
  COMMIT;
  PRAGMA freelist_count;
} {9 9}

finish_test

Added test/avfs.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2021-03-06
#
# 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 tests for the appendvfs extension.
#
# Tests performed:
# avfs-1.0. Test that an appendvfs DB can be added to an empty (ZLF) file.
# avfs-1.1. Test that the DB can be read with correct content upon reopen.
# avfs-1.2. Test that an appendvfs DB can be added to a simple text file.
# avfs-1.3. Test that the DB can be read with correct content upon reopen.
# avfs-1.4. Test that appended DB is aligned to default page boundary.
# avfs-2.1. Test that the simple text file retains its initial text.
# avfs-3.1. Test that the appendvfs can grow and shrink, remaining intact.
# avfs-3.2. Test that appendvfs is intact after grow/shrink/close/reopen.
# avfs-3.3. Test that appendvfs can grow by many pages and be written.
# avfs-3.4. Test that grown appendvfs can be reopened and appear intact.
# avfs-3.5. Test that much grown appendvfs can shrink and reopen intact.
# avfs-4.1. Test shell's ability to append to a non-appendvfs file.
# avfs-4.2. Test shell's ability to append to empty or nonexistent file.
# avfs-4.3. Test shell's ability to reopen and alter an appendvfs file.
# avfs-5.1. Test appendvfs refusal to open too-tiny DB appended onto ZLF.
# avfs-5.2. Test appendvfs refusal to open too-tiny DB appended on other.
# ...
# (more to come)

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set ::testprefix avfs

# Do not attempt this test if SQLITE_OMIT_VIRTUALTABLE is defined. 
#
ifcapable !vtab {
  finish_test
  return
}

set CLI [test_find_cli]
db close
# forcedelete test.db

load_static_extension db appendvfs

set ::fa avfs.adb
set ::fza avfs.sdb
forcedelete $::fa $::fza
set ::result {}

proc shellDoesAr {} {
  set shdo "sh_app1.sql"
  forcedelete $shdo
  set fd [open $shdo w]
  puts $fd ".help\n.q"
  close $fd
  set res [catchcmd "-batch -cmd \".read $shdo\""]
  return [regexp {^.archive} [lindex $res 1]]
}

set ::vf "&vfs=apndvfs"

# Return file offset of appendvfs portion of a file, or {} if none such.
proc fosAvfs {fname} {
  if {[file size $fname] < 25} {
    return {}
  }
  if {[catch {set fd [open $fname rb]}]} {
    return {}
  }
  seek $fd -25 end
  set am [read $fd 17]
  set ao [read $fd 8]
  close $fd
  if {$am ne "Start-Of-SQLite3-"} {
    return {}
  }
  binary scan $ao "W" rvo
  return $rvo
}

do_test 1.0 {
  set results {}
  set out [open $::fza wb]
  close $out
  sqlite3 adb "file:$::fza?mode=rwc$::vf" -uri 1
  adb eval {
    PRAGMA page_size=1024;
    PRAGMA cache_size=10;
    CREATE TABLE t1(a TEXT);
    INSERT INTO t1 VALUES ('dog'),('cat');
    SELECT group_concat(a) as pets FROM (SELECT a FROM t1 ORDER BY a);
  } { lappend results $pets }
  adb close
  lappend results [fosAvfs $fza]
  set ::result [join $results " | "]
} {cat,dog | 0}

do_test 1.1 {
  set results {}
  sqlite3 adb "file:$::fza?mode=rw$::vf" -uri 1
  adb eval {
    SELECT group_concat(a) as pets FROM (SELECT a FROM t1 ORDER BY a DESC);
  } { lappend results $pets }
  adb close
  set ::result [join $results " | "]
} {dog,cat}

do_test 1.2 {
  set results {}
  set out [open $::fa wb]
  set ::tlo { "Just some text," "and more text," "ending at 3 lines." }
  puts $out [join $::tlo "\n"]
  close $out
  set adbSz [file size $::fa]
  sqlite3 adb "file:$::fa?mode=rwc$::vf" -uri 1
  adb eval {
    PRAGMA auto_vacuum = 0;
    PRAGMA page_size=512;
    PRAGMA cache_size=0;
    CREATE TABLE t1(a TEXT);
    INSERT INTO t1 VALUES ('dog'),('cat'),('pig');
    SELECT group_concat(a) as pets FROM (SELECT a FROM t1 ORDER BY a);
  } { lappend results $pets }
  adb close
  set adaSz [file size $::fa]
  lappend results "Bytes before/after $adbSz/$adaSz"
  set ::result [join $results " | "]
} {cat,dog,pig | Bytes before/after 50/5145}

do_test 1.3 {
  set results {}
  sqlite3 adb "file:$::fa?mode=rw$::vf" -uri 1
  adb eval {
    SELECT group_concat(a) as pets FROM (SELECT a FROM t1 ORDER BY a DESC);
  } { lappend results $pets }
  adb close
  set ::result [join $results " | "]
} {pig,dog,cat}

do_test 1.4 {
  set ::result [fosAvfs $fa]
} {4096}

do_test 2.1 {
  set in [open $::fa r]
  set tli {}
  for {set i [llength $::tlo]} {$i > 0} {incr i -1} {
    lappend tli [gets $in]
  }
  close $in
  if { [join $tli ":"] ne [join $::tlo ":"] } {
    set ::result "Appendee changed."
  } else {
    set ::result "Appendee intact."
  }
} {Appendee intact.}

# Set of repeatable random integers for a couple tests.
set ::nrint 50000
proc rint {v} {
  return [::tcl::mathfunc::int [expr $v * 100000]]
}
array set ::randints [list 0 [rint [::tcl::mathfunc::srand 0]]]
for {set i 1} {$i < $::nrint} {incr i} {
  set ::randints($i) [rint [::tcl::mathfunc::rand]]
}

do_test 3.1 {
  set results {}
  sqlite3 adb "file:$::fa?mode=rw$::vf" -uri 1
  adb eval {
    DROP TABLE t1;
    PRAGMA cache_size=10;
    CREATE TABLE ri (i INTEGER);
    BEGIN;
  }
  for {set i 0} {$i < $::nrint} {incr i} {
    set r $::randints($i)
    set s $::randints([incr i])
    set t $::randints([incr i])
    set u $::randints([incr i])
    set v $::randints([incr i])
    adb eval {
      INSERT INTO ri VALUES ($r),($s),($t),($u),($v)
    }
  }
  adb eval {
    COMMIT;
    SELECT integrity_check as ic FROM pragma_integrity_check();
  } { lappend results $ic }
  set adbSz [file size $::fa]
  set qr {}
  adb eval {
    SELECT count(*) as ic FROM ri;
    DELETE FROM ri WHERE (i % 50) <> 25;
    SELECT integrity_check as ic FROM pragma_integrity_check();
    VACUUM;
    SELECT integrity_check as ic FROM pragma_integrity_check();
    SELECT count(*) as ic FROM ri;
  } { lappend qr $ic }
  adb close
  set adaSz [file size $::fa]
  set adba [expr ($adbSz + 0.1)/$adaSz]
  # lappend results $adba
  set results [concat $results [lrange $qr 0 2]]
  lappend results [expr {$adba > 10.0}]
  set ::result [join $results " | "]
} "ok | $::nrint | ok | ok | 1"

do_test 3.2 {
  set results {}
  sqlite3 adb "file:$::fa?mode=rw$::vf" -uri 1
  adb eval {
    SELECT integrity_check as ic FROM pragma_integrity_check();
  } { lappend results $ic }
  adb close
  set ::result [join $results " | "]
} {ok}

# avfs-3.3. Test that appendvfs can grow by many pages and be written.
do_test 3.3 {
  set results {}
  sqlite3 adb "file:$::fa?mode=rw$::vf" -uri 1
  set npages 300
  adb eval { BEGIN }
  while {$npages > 0} {
    adb eval { INSERT INTO ri VALUES (randomblob(1500)) }
    incr npages -1
  }
  adb eval { COMMIT }
  adb eval {
    SELECT integrity_check as ic FROM pragma_integrity_check();
  } { lappend results $ic }
  adb close
  set adaSzr [expr [file size $::fa] / 300.0 / 1500 ]
  set okSzr [expr $adaSzr > 1.0 && $adaSzr < 1.3 ]
  lappend results $okSzr
  set ::result [join $results " | "]
} {ok | 1}

# avfs-3.4. Test that grown appendvfs can be reopened and appear intact.
do_test 3.4 {
  set results {}
  sqlite3 adb "file:$::fa?mode=rw$::vf" -uri 1
  adb eval {
    SELECT integrity_check as ic FROM pragma_integrity_check();
  } { lappend results $ic }
  adb close
  set ::result $ic
} {ok}

# avfs-3.5. Test that much grown appendvfs can shrink and reopen intact.
do_test 3.5 {
  set results {}
  set adbsz [file size $::fa]
  sqlite3 adb "file:$::fa?mode=rw$::vf" -uri 1
  adb eval {
    DELETE FROM ri WHERE rowid % 8 <> 0;
    SELECT integrity_check as ic FROM pragma_integrity_check();
    VACUUM;
    SELECT integrity_check as ic FROM pragma_integrity_check();
  } { lappend results $ic }
  adb close
  set adasz [file size $::fa]
  lappend results [expr {$adbsz/$adasz > 5}]
  sqlite3 adb "file:$::fa?mode=rw$::vf" -uri 1
  adb eval {
    SELECT integrity_check as ic FROM pragma_integrity_check();
  } { lappend results $ic }
  adb close
  set ::result [join $results " | "]
} {ok | ok | 1 | ok}

set ::cliDoesAr [shellDoesAr]

do_test 4.1 {
  set shdo "sh_app1.sql"
  set shod "sh_app1.adb"
  forcedelete $shdo $shod
  set ofd [open $shdo w]
  if {$::cliDoesAr} {
    puts $ofd ".ar -c"
  } else {
    puts $ofd "pragma page_size=512;"
    puts $ofd "create table sqlar (a);"
  }
  puts $ofd ".tables"
  puts $ofd ".q"
  close $ofd
  set ofd [open $shod wb]
  puts $ofd "Some text."
  close $ofd
  set res [catchcmd "-append -batch -init $shdo $shod" ""]
  lappend res [fosAvfs $shod]
  forcedelete $shdo $shod
  set ::result [join $res " | "]
} {0 | sqlar | 4096}

do_test 4.2 {
  set shdo "sh_app1.sql"
  set shod "sh_app1.adb"
  forcedelete $shdo $shod
  set ofd [open $shdo w]
  if {$::cliDoesAr} {
    puts $ofd ".ar -c"
  } else {
    puts $ofd "pragma page_size=512;"
    puts $ofd "create table sqlar (a);"
  }
  puts $ofd ".tables"
  puts $ofd ".q"
  close $ofd
  set ofd [open $shod wb]
  close $ofd
  set res [catchcmd "-append -batch -init $shdo $shod" ""]
  lappend res [fosAvfs $shod]
  forcedelete $shdo ; # Leave $shod for next test.
  set ::result [join $res " | "]
} {0 | sqlar | 0}

do_test 4.3 {
  set shdo "sh_app1.sql"
  set shod "sh_app1.adb" ; # Same as test 4.2, reusing ADB.
  forcedelete $shdo
  set ofd [open $shdo w]
  if {$::cliDoesAr} {
    puts $ofd ".ar -u $shdo"
    puts $ofd "select count(*) from sqlar where name = '$shdo';"
  } else {
    puts $ofd "insert into sqlar values (1);"
    puts $ofd "select count(*) from sqlar;"
  }
  puts $ofd ".q"
  close $ofd
  set res [catchcmd "-append -batch -init $shdo $shod" ""]
  sqlite3 adb "file:$shod?mode=rw$::vf" -uri 1
  adb eval {
    SELECT count(*) as n FROM sqlar
  } { lappend res $n }
  adb close
  forcedelete $shdo $shod;
  set ::result [join $res " | "]
} {0 | 1 | 1}

do_test 5.1 {
  set fake "faketiny.sdb"
  forcedelete $fake
  set ofd [open $fake wb]
  puts -nonewline $ofd "SQLite format 3"
  puts -nonewline $ofd [binary format "c" 0]
  puts -nonewline $ofd "Start-Of-SQLite3-"
  puts -nonewline $ofd [binary format "W" 0]
  close $ofd
  if {[catch {sqlite3 adb "file:$fake?mode=rw$::vf" -uri 1}]} {
    set res "Open failed."
  } else {
    adb close
    set res "Opened when should not."
  }
  forcedelete $fake
  set ::result $res
} {Open failed.}

do_test 5.2 {
  set fake "faketiny.sdb"
  forcedelete $fake
  set ofd [open $fake wb]
  set fakeAppendee "Dog ate my homework.\n"
  puts -nonewline $ofd $fakeAppendee
  puts -nonewline $ofd "SQLite format 3"
  puts -nonewline $ofd [binary format "c" 0]
  puts -nonewline $ofd "Start-Of-SQLite3-"
  puts -nonewline $ofd [binary format "W" [string length $fakeAppendee]]
  close $ofd
  if {[catch {sqlite3 adb "file:$fake?mode=rw$::vf" -uri 1}]} {
    set res "Open failed."
  } else {
    adb close
    set res "Opened when should not."
  }
  forcedelete $fake
  set ::result $res
} {Open failed.}

forcedelete $::fa $::fza

unset -nocomplain ::fa ::fza ::tlo ::result ::randints ::nrint ::cliDoesAr

finish_test

Changes to test/backup.test.

964
965
966
967
968
969
970









971
972
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981







+
+
+
+
+
+
+
+
+



  do_test backup-10.$tn.6 {
    B finish
  } {SQLITE_OK}

  db2 close
}

# 2021-01-31 https://sqlite.org/forum/forumpost/8b39fbf3e7
#
do_test backup-11.1 {
  sqlite3 db1 :memory:
  sqlite3 db2 :memory:
  sqlite3_backup B db1 main db2 temp
  B finish
} {SQLITE_OK}

finish_test

Changes to test/backup2.test.

140
141
142
143
144
145
146
147

148
149
150
151
152
153
154

155

156
157
158
159
160
161
162
140
141
142
143
144
145
146

147
148
149
150
151
152
153
154
155

156
157
158
159
160
161
162
163







-
+







+
-
+







} {1 {wrong # args: should be "db backup ?DATABASE? FILENAME"}}

# Try to restore from an unreadable file.
#
if {$tcl_platform(platform)=="windows"} {
  set msg {cannot open source database: unable to open database file}
} elseif {[string match *BSD $tcl_platform(os)]} {
  set msg {restore failed: file is not a database}
  set msg {}
} else {
  set msg {cannot open source database: disk I/O error}
}
do_test backup2-10 {
  forcedelete bu3.db
  file mkdir bu3.db
  set rc [catch {db restore temp bu3.db} res]
  if {[string match *BSD $tcl_platform(os)]} { set res "" }
  lappend rc $res
  list $rc $res
} [list 1 $msg]

# Try to restore from something that is not a database file.
#
do_test backup2-11 {
  set rc [catch {db restore temp bu2.db} res]
  lappend rc $res

Changes to test/badutf2.test.

94
95
96
97
98
99
100





101
102
103
104
105
106







107
108
109
110
111
112
113
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_test badutf2-3.1.$i {
      set sql "SELECT hex('$hstr') AS x;"
      set res [ sqlite3_exec db $sql ]
      lindex [ lindex $res 1] 1
    } $uval
  }

  # Tcl 8.7 and later do automatic bad-utf8 correction for
  # characters 0x80 thru 0x9f so test case 5 does not work here.
  if {$i==5 && $tcl_version>=8.7} {
     # no-op
  } else {
  do_test badutf2-4.1.$i {
    sqlite3_reset $S
    sqlite3_bind_text $S 1 $xstr $len
    sqlite3_step $S
    utf8_to_ustr2 [ sqlite3_column_text $S 0 ]
  } $ustr
    do_test badutf2-4.1.$i {
      sqlite3_reset $S
      sqlite3_bind_text $S 1 $xstr $len
      sqlite3_step $S
      utf8_to_ustr2 [ sqlite3_column_text $S 0 ]
    } $ustr
  }

  ifcapable debug {
    do_test badutf2-5.1.$i {
      utf8_to_utf8 $uval
    } $u2u
  }

Added test/basexx1.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022 November 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.
#
#***********************************************************************
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix basexx

if {[catch {load_static_extension db basexx} error]} {
  puts "Skipping basexx tests, hit load error: $error"
  finish_test; return
}

# Empty blobs encode to empty strings.
do_execsql_test 100 {
  SELECT base64(x'')||base85(x'');
} {{}}

# Empty strings decode to empty blobs.
do_execsql_test 101 {
  SELECT hex(x'01'||base64('')||base85('')||x'02');
} {0102}

# Basic base64 encoding
do_execsql_test 102 {
  SELECT base64(x'000102030405');
  SELECT base64(x'0001020304');
  SELECT base64(x'00010203');
} {{AAECAwQF
} {AAECAwQ=
} {AAECAw==
}}

# Basic base64 decoding with pad chars
do_execsql_test 103 {
  SELECT hex(base64('AAECAwQF'));
  SELECT hex(base64('AAECAwQ='));
  SELECT hex(base64('AAECAw=='));
} {000102030405 0001020304 00010203}

# Basic base64 decoding without pad chars and with whitespace
do_execsql_test 104 {
  SELECT hex(base64(' AAECAwQF '));
  SELECT hex(base64(' AAECAwQ'));
  SELECT hex(base64('AAECAw '));
} {000102030405 0001020304 00010203}

# Basic base85 encoding
do_execsql_test 105 {
  SELECT base85(x'000102030405');
  SELECT base85(x'0001020304');
  SELECT base85(x'00010203');
} {{##/2,#2/
} {##/2,#*
} {##/2,
}}

# Basic base85 decoding with and without whitespace
do_execsql_test 106 {
  SELECT hex(base85('##/2,#2/'));
  SELECT hex(base85('##/2,#*'));
  SELECT hex(base85('##/2,'));
  SELECT hex(base85(' ##/2,#2/ '));
  SELECT hex(base85(' ##/2,#*'));
  SELECT hex(base85('##/2, '));
} {000102030405 0001020304 00010203 000102030405 0001020304 00010203}

# Round-trip some random blobs.
do_execsql_test 107 {
  CREATE TEMP TABLE rb( len int, b blob ) STRICT;
  INSERT INTO rb(len) VALUES (1),(2),(3),(4),(5),(150),(151),(152),(153),(1054);
  UPDATE rb SET b = randomblob(len);
  SELECT len, base64(base64(b))=b, base85(base85(b))=b
  FROM rb ORDER BY len;
} {1 1 1 2 1 1 3 1 1 4 1 1 5 1 1 150 1 1 151 1 1 152 1 1 153 1 1 1054 1 1}

# Same round-trip but with space or junk prepended and/or appended or not.
do_execsql_test 108 {
  CREATE TEMP TABLE junk(j text, rank int);
  INSERT INTO junk VALUES ('',0),(' ',1),('~',2);
  SELECT len, base64(j.j||base64(b)||j.j)=b, base85(j.j||base85(b)||j.j)=b
  FROM rb r, junk j WHERE j.rank=(r.len+r.len/25)%3 ORDER BY len;
} {1 1 1 2 1 1 3 1 1 4 1 1 5 1 1 150 1 1 151 1 1 152 1 1 153 1 1 1054 1 1}

# Exercise the fail-on-too-large result feature.

set inLimit [sqlite3_limit db SQLITE_LIMIT_LENGTH -1]
sqlite3_limit db SQLITE_LIMIT_LENGTH 1300

do_catchsql_test 109 {
  SELECT len, base64(b) FROM rb WHERE len>200;
} {1 {blob expanded to base64 too big}}

do_catchsql_test 110 {
  SELECT len, base85(b) FROM rb WHERE len>200;
} {1 {blob expanded to base85 too big}}

do_catchsql_test 111 {
  SELECT length(base85(b))=1335 FROM rb WHERE len=1054;
} {1 {blob expanded to base85 too big}}

sqlite3_limit db SQLITE_LIMIT_LENGTH $inLimit

# Exercise is_base85(t)

do_execsql_test 112 {
  SELECT is_base85(' '||base85(x'123456')||char(10)),
  is_base85('#$%&*+,-./0123456789:;<=>?@'
   ||'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
   ||'[\]^_`'
   ||'abcdefghijklmnopqrstuvwxyz'),
  is_base85('!'), is_base85('"'), is_base85(''''), is_base85('('),
  is_base85(')'), is_base85(char(123)), is_base85('|'), is_base85(char(125)),
  is_base85('~'), is_base85(char(127));
} {1 1 0 0 0 0 0 0 0 0 0 0}

do_execsql_test 113 {
  SELECT is_base85(NULL) IS NULL;
} {1}

do_catchsql_test 114 {
  SELECT is_base85(1);
} {1 {is_base85 accepts only text or NULL}}

do_catchsql_test 115 {
  SELECT is_base85(1.1);
} {1 {is_base85 accepts only text or NULL}}

do_catchsql_test 116 {
  SELECT is_base85(x'00');
} {1 {is_base85 accepts only text or NULL}}

# Round-trip many bigger random blobs.

do_execsql_test 117 {
  CREATE TABLE bs(b blob, num);
  INSERT INTO bs SELECT randomblob(4000 + n%3), n 
   FROM ( 
     WITH RECURSIVE seq(n) AS (
      VALUES(1) UNION ALL SELECT n+1
      FROM seq WHERE n<100
     ) SELECT n FROM seq);
  SELECT num FROM bs WHERE base64(base64(b))!=b;
  SELECT num FROM bs WHERE base85(base85(b))!=b;
} {}

finish_test

Changes to test/bestindex1.test.

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
42







-
+
+
+
+







proc vtab_command {method args} {
  switch -- $method {
    xConnect {
      return "CREATE TABLE t1(a, b, c)"
    }

    xBestIndex {
      set clist [lindex $args 0]
      set hdl [lindex $args 0]
      set clist [$hdl constraints]
      set orderby [$hdl orderby]
      
      if {[llength $clist]!=1} { error "unexpected constraint list" }
      catch { array unset C }
      array set C [lindex $clist 0]
      if {$C(usable)} {
        return "omit 0 cost 0 rows 1 idxnum 555 idxstr eq!"
      } else {
        return "cost 1000000 rows 0 idxnum 0 idxstr scan..."
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
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







-
+



-
+




















+
+
+
+



-








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:
#
#   "omit" - Implement filtering. Set the omit flag.
#   "use"  - Implement filtering. Use the constraint, but do not set omit.
#   "use2" - Do not implement filtering. Use the constraint anyway.
#
#   
proc t1_vtab {mode method args} {
  switch -- $method {
    xConnect {
      return "CREATE TABLE t1(a, b)"
    }

    xBestIndex {
      set hdl [lindex $args 0]
      set clist [$hdl constraints]
      set orderby [$hdl orderby]

      set SQL_FILTER {SELECT * FROM t1x WHERE a='%1%'}
      set SQL_SCAN   {SELECT * FROM t1x}

      set clist [lindex $args 0]
      set idx 0
      for {set idx 0} {$idx < [llength $clist]} {incr idx} {
        array unset C
        array set C [lindex $clist $idx]
        if {$C(column)==0 && $C(op)=="eq" && $C(usable)} {
          switch -- $mode {
            "omit" {
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
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







-
+




-
+




-
+








  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)]
}
173
174
175
176
177
178
179
180




181
182
183
184
185
186
187
179
180
181
182
183
184
185

186
187
188
189
190
191
192
193
194
195
196







-
+
+
+
+








  switch -- $method {
    xConnect {
      return "CREATE TABLE t1($G(cols))"
    }

    xBestIndex {
      set clist [lindex $args 0]
      set hdl [lindex $args 0]
      set clist [$hdl constraints]
      set orderby [$hdl orderby]
      
      #puts $clist
      set W [list]
      set U [list]

      set i 0
      for {set idx 0} {$idx < [llength $clist]} {incr idx} {
        array set c [lindex $clist $idx]
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







+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

} {
  1 0 ValueA 1 0 ValueA
  2 0 ValueA 2 0 ValueA
  3 0 ValueB 3 0 ValueB
  4 0 ValueB 4 0 ValueB
}

#-------------------------------------------------------------------------
# If there is an IN(..) condition in the WHERE clause of a query on a
# virtual table, the xBestIndex method is first invoked with the IN(...)
# represented by a "usable" SQLITE_INDEX_CONSTRAINT_EQ constraint. If
# the virtual table elects to use the IN(...) constraint, then the 
# xBestIndex method is invoked again, this time with the IN(...) marked
# as "not usable". Depending on the relative costs of the two plans as
# defined by the virtual table implementation, and the cardinality of the
# IN(...) operator, SQLite chooses the most efficient plan. 

#
# At one point the second invocation of xBestIndex() was only being made
# for join queries. The following tests check that this problem has been
# fixed.
#
proc vtab_command {method args} {
  switch -- $method {
    xConnect {
      return "CREATE TABLE t1(a, b, c, d)"
    }

    xBestIndex {
      set hdl [lindex $args 0]
      set clist [$hdl constraints]
      set orderby [$hdl orderby]
      
      lappend ::bestindex_calls $clist
      set ret "cost 1000000 idxnum 555"
      for {set i 0} {$i < [llength $clist]} {incr i} {
        array set C [lindex $clist $i]
        if {$C(usable)} { 
          lappend ret use $i 
        }
      }
      return $ret
    }
  }
  return {}
}

do_execsql_test 4.0 {
  CREATE VIRTUAL TABLE x1 USING tcl(vtab_command);
} {}

do_test 4.1 {
  set ::bestindex_calls [list]
  execsql {
    SELECT * FROM x1 WHERE a=? AND b BETWEEN ? AND ? AND c IN (1, 2, 3, 4);
  }
  set ::bestindex_calls
} [list \
    [list {op eq column 0 usable 1} \
          {op eq column 2 usable 1} \
          {op ge column 1 usable 1} \
          {op le column 1 usable 1} \
    ] \
    [list {op eq column 0 usable 1} \
          {op eq column 2 usable 0} \
          {op ge column 1 usable 1} \
          {op le column 1 usable 1}
    ]
]

do_catchsql_test 5.0 {
  SELECT * FROM tcl('abc');
} {1 {wrong number of arguments}}

finish_test

Changes to test/bestindex2.test.

43
44
45
46
47
48
49


50


51
52
53
54
55
56
57
43
44
45
46
47
48
49
50
51

52
53
54
55
56
57
58
59
60







+
+
-
+
+







#  
proc vtab_cmd {tbl cols method args} {
  switch -- $method {
    xConnect {
      return "CREATE TABLE $tbl ([join $cols ,])"
    }
    xBestIndex {
      set hdl [lindex $args 0]
      set clist [$hdl constraints]
      foreach {clist orderby mask} $args {}
      set orderby [$hdl orderby]
      set mask [$hdl mask]

      set cons [list]
      set used [list]

      for {set i 0} {$i < [llength $clist]} {incr i} {
        array unset C
        array set C [lindex $clist $i]
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
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







-
+



-
+



-
+





-
-
+
+






-
-
-
+
+
+






-
-
-
+
+
+










-
-
-
-
+
+
+
+



  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.

30
31
32
33
34
35
36


37


38
39
40
41
42
43
44
30
31
32
33
34
35
36
37
38

39
40
41
42
43
44
45
46
47







+
+
-
+
+







proc vtab_cmd {bOmit method args} {
  switch -- $method {
    xConnect {
      return "CREATE TABLE t1(a, b, c)"
    }

    xBestIndex {
      set hdl [lindex $args 0]
      set clist [$hdl constraints]
      foreach {clist orderby mask} $args {}
      set orderby [$hdl orderby]
      set mask [$hdl mask]

      set ret [list]
      set use use
      if {$bOmit} {set use omit}

      for {set i 0} {$i < [llength $clist]} {incr i} {
        array unset C
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
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







-
+



-
+






+
-
-
+
+
+







+
-
-
+
+
+








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 TABLE t1 VIRTUAL TABLE INDEX 0:b EQ ?
     |  `--SCAN t1 VIRTUAL TABLE INDEX 0:a EQ ?
     `--INDEX 2
        `--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 TABLE t1 VIRTUAL TABLE INDEX 0:b EQ ?
     |  `--SCAN t1 VIRTUAL TABLE INDEX 0:a LIKE ?
     `--INDEX 2
        `--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');
146
147
148
149
150
151
152

153
154



155
156
157
158
159
160
161
153
154
155
156
157
158
159
160


161
162
163
164
165
166
167
168
169
170







+
-
-
+
+
+







  }

  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 TABLE t2 USING INDEX t2y (y=?)
       |  `--SEARCH t2 USING INDEX t2x (x>? AND x<?)
       `--INDEX 2
          `--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.

44
45
46
47
48
49
50


51


52
53
54
55
56
57
58
44
45
46
47
48
49
50
51
52

53
54
55
56
57
58
59
60
61







+
+
-
+
+







proc vtab_cmd {param method args} {
  switch -- $method {
    xConnect {
      return "CREATE TABLE t1(id TEXT, host TEXT, class TEXT)"
    }

    xBestIndex {
      set hdl [lindex $args 0]
      set clist [$hdl constraints]
      foreach {clist orderby mask} $args {}
      set orderby [$hdl orderby]
      set mask [$hdl mask]

      set ret [list]

      set use use


      for {set i 0} {$i < [llength $clist]} {incr i} {
131
132
133
134
135
136
137
138





139
140
141
142
143
144
145
134
135
136
137
138
139
140

141
142
143
144
145
146
147
148
149
150
151
152







-
+
+
+
+
+







proc vtab_command {method args} {
  switch -- $method {
    xConnect {
      return "CREATE TABLE t1(a, b, c, d HIDDEN)"
    }

    xBestIndex {
      set clist [lindex $args 0]
      set hdl [lindex $args 0]
      set clist [$hdl constraints]
      set orderby [$hdl orderby]
      set mask [$hdl mask]
      
      if {[llength $clist]!=1} { error "unexpected constraint list" }
      catch { array unset C }
      array set C [lindex $clist 0]
      if {$C(usable)} {
        return [list omit 0 idxnum 555 rows 10 cost 100]
      }
      return [list cost 100000000]
155
156
157
158
159
160
161
162
163


164
165
166
167
168
169
170
171


172
173
174
175
162
163
164
165
166
167
168


169
170
171
172
173
174
175
176


177
178
179
180
181
182







-
-
+
+






-
-
+
+




  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/bestindex5.test.

10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
10
11
12
13
14
15
16

17
18
19
20
21
22
23
24







-
+







#***********************************************************************
# Test the virtual table interface. In particular the xBestIndex
# method.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix bestindex4
set testprefix bestindex5

ifcapable !vtab {
  finish_test
  return
}

#-------------------------------------------------------------------------
40
41
42
43
44
45
46


47


48
49
50
51
52
53
54
40
41
42
43
44
45
46
47
48

49
50
51
52
53
54
55
56
57







+
+
-
+
+








  switch -- $method {
    xConnect {
      return "CREATE TABLE t1(a, b, c)"
    }

    xBestIndex {
      set hdl [lindex $args 0]
      set clist [$hdl constraints]
      foreach {clist orderby mask} $args {}
      set orderby [$hdl orderby]
      set mask [$hdl mask]

      set cost 1000000.0
      set ret [list]
      set str [list]

      set v 0
      for {set i 0} {$i < [llength $clist]} {incr i} {

Changes to test/bestindex6.test.

24
25
26
27
28
29
30
31





32
33
34
35
36
37
38
24
25
26
27
28
29
30

31
32
33
34
35
36
37
38
39
40
41
42







-
+
+
+
+
+







proc vtab_command {src method args} {
  switch -- $method {
    xConnect {
      return [db one {SELECT sql FROM sqlite_master where name = $src}]
    }

    xBestIndex {
      set clist [lindex $args 0]
      set hdl [lindex $args 0]
      set clist [$hdl constraints]
      set orderby [$hdl orderby]
      set mask [$hdl mask]

      set wlist 1

      set iCons 0
      set ret [list]
      foreach cons $clist {
        catch { array unset C }
        array set C $cons

Added test/bestindex7.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2020-01-29
#
# 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
set testprefix bestindex7

ifcapable !vtab {
  finish_test
  return
}

register_tcl_module db

proc vtab_command {src method args} {
  switch -- $method {
    xConnect {
      return "CREATE TABLE xxx(a)"
    }

    xBestIndex {
      set hdl [lindex $args 0]
      set clist [$hdl constraints]
      set orderby [$hdl orderby]
      set mask [$hdl mask]
      
      set iCons 0
      set ret [list]
      foreach cons $clist {
        catch { array unset C }
        array set C $cons
        if {$C(usable)} {
          lappend ret use $iCons
        }
        incr iCons
      }
      return $ret
    }

    xFilter {
      return [list sql "SELECT rowid, x FROM $src"]
    }

  }

  return {}
}

do_execsql_test 1.0 {
  CREATE TABLE t1(x);
  INSERT INTO t1 VALUES(0), (2);
  CREATE VIRTUAL TABLE vt1 USING tcl(vtab_command t1);
}

do_execsql_test 1.1 { select * from vt1 } {0 2}
do_execsql_test 1.2 { select * from vt1 WHERE a=0 } {0}
do_execsql_test 1.3 { select * from vt1 WHERE a=1 } {}
do_execsql_test 1.4 { select * from vt1 WHERE a=1 OR a=0} {0}

do_execsql_test 1.5 {
  UPDATE t1 SET x=NULL WHERE x=2;
}

do_execsql_test 1.6 { select * from vt1 } {0 {}}
do_execsql_test 1.7 { select * from vt1 WHERE a=0 } {0}
do_execsql_test 1.8 { select * from vt1 WHERE a=1 } {}
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

Added test/bestindex8.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2020-01-29
#
# 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
set testprefix bestindex8

ifcapable !vtab {
  finish_test
  return
}

register_tcl_module db

proc vtab_command {src method args} {
  switch -- $method {
    xConnect {
      return "CREATE TABLE xxx(a, b)"
    }

    xBestIndex {
      set hdl [lindex $args 0]
      set clist [$hdl constraints]
      set orderby [$hdl orderby]
      lappend ::lBestIndexDistinct [$hdl distinct]

      #puts "ORDERBY: $orderby" 
      set iCons 0
      set ret [list]
      foreach cons $clist {
        catch { array unset C }
        array set C $cons
        if {$C(usable)} {
          lappend ret use $iCons
        }
        incr iCons
      }
      if {$orderby=="{column 0 desc 0} {column 1 desc 0}"
       || $orderby=="{column 0 desc 0}"
      } {
        lappend ret orderby 1
        lappend ret idxnum 1
        set ::lOrderByConsumed 1
      }
      return $ret
    }

    xFilter {
      set idxnum [lindex $args 0]
      if {$idxnum} {
        return [list sql "SELECT rowid, a, b FROM $src order by 2, 3"]
      }
      return [list sql "SELECT rowid, a, b FROM $src"]
    }

  }

  return {}
}

do_execsql_test 1.0 {
  CREATE TABLE t1(a, b);
  CREATE INDEX i1 ON t1(a, b);
  INSERT INTO t1 VALUES('a', 'b'), ('c', 'd');
  INSERT INTO t1 VALUES('a', 'b'), ('c', 'd');
  CREATE VIRTUAL TABLE vt1 USING tcl(vtab_command t1);

  CREATE TABLE t0(c0);
  INSERT INTO t0(c0) VALUES (1), (0);
}

foreach {tn sql bDistinct idxinsert bConsumed res} {
  1 "SELECT a, b FROM vt1"                              0 0 0 {a b c d a b c d}
  2 "SELECT DISTINCT a, b FROM vt1"                     2 1 1 {a b c d}
  3 "SELECT DISTINCT a FROM vt1"                        2 1 1 {a c}
  4 "SELECT DISTINCT b FROM vt1"                        2 1 0 {b d}
  5 "SELECT DISTINCT b FROM vt1 ORDER BY a"             0 1 1 {b d}
  6 "SELECT DISTINCT t0.c0 FROM vt1, t0 ORDER BY vt1.a" 0 1 1 {1 0}
  7 "SELECT DISTINCT a, b FROM vt1 ORDER BY a, b"       3 0 1 {a b c d}
  8 "SELECT DISTINCT a, b FROM vt1 ORDER BY a"          0 1 1 {a b c d}
  9 "SELECT DISTINCT a FROM vt1 ORDER BY a, b"          0 1 1 {a c}

 10 "SELECT DISTINCT a, b FROM vt1 WHERE b='b'"         2 1 1 {a b}
 11 "SELECT DISTINCT a, b FROM vt1 WHERE +b='b'"        2 1 1 {a b}
} {
  set ::lBestIndexDistinct ""
  set ::lOrderByConsumed 0
  do_execsql_test 1.$tn.1 $sql $res
  do_test 1.$tn.2 {
    set ::lBestIndexDistinct
  } $bDistinct
  do_test 1.$tn.3 {
    expr {[lsearch [execsql "explain $sql"] IdxInsert]>=0}
  } $idxinsert
  do_test 1.$tn.4 {
    set ::lOrderByConsumed
  } $bConsumed
}

#-------------------------------------------------------------------------
reset_db
register_tcl_module db

proc vtab_command {src method args} {
  switch -- $method {
    xConnect {
      return "CREATE TABLE xxx(a, b)"
    }

    xBestIndex {
      set hdl [lindex $args 0]
      set ret [list]

      set iCons 0
      foreach cons [$hdl constraints] {
        array set C $cons
        if {($C(op)=="limit" || $C(op)=="offset") && $C(usable)} {
          lappend ret use $iCons
        }
        incr iCons
      }

      return $ret
    }

    xFilter {
      lappend ::lFilterArgs [lindex $args 2]
      return [list sql "SELECT rowid, a, b FROM $src"]
    }

  }

  return {}
}

do_execsql_test 2.0 {
  CREATE TABLE t1(a, b);
  CREATE INDEX i1 ON t1(a, b);
  CREATE VIRTUAL TABLE vt1 USING tcl(vtab_command t1);
}

do_test 2.1 {
  set ::lFilterArgs [list]
  execsql { SELECT * FROM vt1 LIMIT 10 }
  set ::lFilterArgs
} {10}

do_test 2.2 {
  set ::lFilterArgs [list]
  execsql { SELECT * FROM vt1 LIMIT 5 OFFSET 50 }
  set ::lFilterArgs
} {{5 50}}

do_test 2.3 {
  set ::lFilterArgs [list]
  execsql { SELECT * FROM vt1 ORDER BY a, b LIMIT 1 OFFSET 1 }
  set ::lFilterArgs
} {{1 1}}

do_test 2.4 {
  set ::lFilterArgs [list]
  execsql { SELECT * FROM vt1 ORDER BY a, +b LIMIT 1 OFFSET 1 }
  set ::lFilterArgs
} {{}}

#-------------------------------------------------------------------------
reset_db
register_tcl_module db

proc vtab_command {src method args} {
  switch -- $method {
    xConnect {
      return "CREATE TABLE xxx(a, b)"
    }

    xBestIndex {
      set hdl [lindex $args 0]
      set lCons [$hdl constraints]

      set ret [list]
      for {set i 0} {$i < [llength $lCons]} {incr i} {
        array set C [lindex $lCons $i]
        if {$C(usable)} {
          lappend ret use $i
          $hdl in $i 1
        }
      }
      return $ret
    }

    xFilter {
      set lArg [lindex $args 2]
      lappend ::lFilterArg {*}$lArg
      return [list sql "SELECT rowid, a, b FROM $src"]
    }

  }

  return {}
}

do_execsql_test 3.0 {
  CREATE TABLE t1(a, b);
  CREATE INDEX i1 ON t1(a, b);
  CREATE VIRTUAL TABLE vt1 USING tcl(vtab_command t1);
}

foreach {tn sql lfa} {
  1 "SELECT * FROM vt1 WHERE b IN (10, 20, 30)" {{10 20 30}}
  2 "SELECT * FROM vt1 WHERE b IN ('abc', 'def')" {{abc def}}
  3 "SELECT * FROM vt1 WHERE a IS NULL AND b IN ('abc', 'def')" {{} {abc def}}
  4 "SELECT * FROM vt1 WHERE a IN (1,2,3) AND b IN ('abc', 'def')" 
     {{1 2 3} {abc def}}

  5 "SELECT * FROM vt1 
     WHERE a IN (SELECT 1 UNION SELECT 2) AND b IN ('abc', 'def')"
     {{1 2} {abc def}}

  6 "SELECT * FROM vt1 
     WHERE b IN ('abc', 'def') AND a IN (SELECT 1 UNION SELECT 2)"
     {{abc def} {1 2}}
} {
  do_test 3.$tn {
    set ::lFilterArg [list]
    execsql $sql
    set ::lFilterArg
  } $lfa
}

#explain_i { SELECT * FROM vt1 WHERE b IN (10, 20, 30) }

#-------------------------------------------------------------------------
reset_db
register_tcl_module db

proc vtab_command {src method args} {
  switch -- $method {
    xConnect {
      return "CREATE TABLE xxx(a, b, c)"
    }

    xBestIndex {
      set hdl [lindex $args 0]
      set lCons [$hdl constraints]

      set ret [list]
      for {set i 0} {$i < [llength $lCons]} {incr i} {
        lappend ::lBestIndexRhs [$hdl rhs_value $i -]
      }
      return $ret
    }

    xFilter {
      return [list sql "SELECT rowid, a, b, c FROM $src"]
    }

  }

  return {}
}

do_execsql_test 4.0 {
  CREATE TABLE t1(a, b, c);
  CREATE VIRTUAL TABLE vt1 USING tcl(vtab_command t1);
}

foreach {tn sql lbir} {
  1 "SELECT * FROM vt1 WHERE b = 10" {10}
  2 "SELECT * FROM vt1 WHERE a = 'abc' AND b < 30" {abc 30}
  3 "SELECT * FROM vt1 WHERE a = 'abc' AND b < 30+2" {abc -}
  4 "SELECT * FROM vt1 WHERE a IN (1,2,3) AND b < 30+2" {- -}
  5 "SELECT * FROM vt1 WHERE a IS 111 AND b < 30+2" {111 -}
} {
  do_test 4.$tn {
    set ::lBestIndexRhs [list]
    execsql $sql
    set ::lBestIndexRhs
  } $lbir
}

#-------------------------------------------------------------------------
reset_db
db cache size 0
register_tcl_module db

set ::vtab_handle_in 1
proc vtab_command {src method args} {
  switch -- $method {
    xConnect {
      return "CREATE TABLE xxx(a, b, c)"
    }

    xBestIndex {
      set lCols [list a b c]

      set hdl [lindex $args 0]
      set lCons [$hdl constraints]
      set lOrder [$hdl order]

      set L ""
      set O ""
      set W [list]
      set a 0
      for {set i 0} {$i < [llength $lCons]} {incr i} {
        array set C [lindex $lCons $i]
        if {$C(usable)} {
          if { $C(op)=="eq" } {
            set bIn 0
            if {$::vtab_handle_in} { set bIn [$hdl in $i 1] }
            if {$bIn} {
              lappend W "[lindex $lCols $C(column)] IN (%I$a%)"
            } else {
              lappend W "[lindex $lCols $C(column)] = %$a%"
            }
            lappend ret omit $i
          }
          if { $C(op)=="limit"  } { set L " LIMIT %$a%"  ; lappend ret use $i }
          if { $C(op)=="offset" } { set O " OFFSET %$a%" ; lappend ret use $i }
          incr a
        }
      }

      set order ""
      set selectlist "rowid, a, b, c"
      if {[llength $lOrder]} {
        array set sl [list]
        set lO [list]
        foreach s $lOrder {
          array set C $s
          set ad ""
          if {$C(desc)} { set ad " DESC" }
          lappend lO "[lindex $lCols $C(column)]$ad"
          set sl($C(column)) 1
        }
        if {[$hdl distinct]==2} {
          set selectlist "DISTINCT 0"
          foreach i {0 1 2} {
            if {[info exists sl($i)]} {
              append selectlist ", [lindex $lCols $i]"
            } else {
              append selectlist ", 0"
            }
          }
        } else {
          set order " ORDER BY [join $lO ,]"
        }
      }

      set where ""
      if {[llength $W]} { set where " WHERE [join $W { AND }]" }
      set sql "SELECT $selectlist FROM $src$where$order$L$O"

      lappend ret idxStr $sql
      return $ret
    }

    xFilter {
      foreach {idxnum idxstr lArg} $args {}
      set ii 0
      set sql $idxstr
      foreach a $lArg {
        set sql [string map [list %$ii% $a] $sql]
        set sql [string map [list %I$ii% [join $a ,]] $sql]
        incr ii
      }
      lappend ::lFilterSql $sql

      if {[regexp {OFFSET (.*)$} $sql -> off]} {
        set real_sql "
          WITH c(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM c WHERE i<$off )
          SELECT 0,0,0,0 FROM c
          UNION ALL SELECT * FROM (
            $sql
          )
        "
      } else {
        set real_sql $sql
      }

      return [list sql $real_sql]
    }

  }

  return {}
}

do_execsql_test 5.0 {
  CREATE TABLE t1(a, b, c);
  CREATE VIRTUAL TABLE vt1 USING tcl(vtab_command t1);
  INSERT INTO t1 VALUES(1, 2, 3);
  INSERT INTO t1 VALUES(2, 3, 4);
  INSERT INTO t1 VALUES(3, 4, 5);
  INSERT INTO t1 VALUES(1, 5, 6);
  INSERT INTO t1 VALUES(2, 6, 7);
  INSERT INTO t1 VALUES(3, 7, 8);
  INSERT INTO t1 VALUES(1, 8, 9);
  INSERT INTO t1 VALUES(2, 9, 0);
}

proc do_vtab_test {tn sql vtsql {res {}}} {
  set ::lFilterSql [list]
  uplevel [list do_execsql_test $tn.1 $sql $res]
  uplevel [list do_test $tn.2 {set ::lFilterSql} [list {*}$vtsql]]
}

do_vtab_test 5.1.1 {
  SELECT DISTINCT a FROM vt1
} {
  {SELECT DISTINCT 0, a, 0, 0 FROM t1}
} {1 2 3}

do_vtab_test 5.1.2 {
  SELECT DISTINCT a FROM vt1 ORDER BY a
} {
  {SELECT rowid, a, b, c FROM t1 ORDER BY a}
} {1 2 3}

do_vtab_test 5.1.3 {
  SELECT DISTINCT a FROM vt1 WHERE c IN (4,5,6,7,8)
} {
  {SELECT DISTINCT 0, a, 0, 0 FROM t1 WHERE c IN (4,5,6,7,8)}
} {2 3 1}

set ::vtab_handle_in 0
do_vtab_test 5.1.4 {
  SELECT  DISTINCT a FROM vt1 WHERE c IN (4,5,6,7,8)
} {
  {SELECT DISTINCT 0, a, 0, 0 FROM t1 WHERE c = 4}
  {SELECT DISTINCT 0, a, 0, 0 FROM t1 WHERE c = 5}
  {SELECT DISTINCT 0, a, 0, 0 FROM t1 WHERE c = 6}
  {SELECT DISTINCT 0, a, 0, 0 FROM t1 WHERE c = 7}
  {SELECT DISTINCT 0, a, 0, 0 FROM t1 WHERE c = 8}
} {2 3 1}

set ::vtab_handle_in 1
do_vtab_test 5.1.5a {
  SELECT a, b, c FROM vt1 WHERE c IN (4,5,6,7,8) LIMIT 2 OFFSET 2
} {
  {SELECT rowid, a, b, c FROM t1 WHERE c IN (4,5,6,7,8) LIMIT 2 OFFSET 2}
} {1 5 6 2 6 7}

set ::vtab_handle_in 0
do_vtab_test 5.1.5b {
  SELECT a, b, c FROM vt1 WHERE c IN (4,5,6,7,8) LIMIT 2 OFFSET 2
} {
  {SELECT rowid, a, b, c FROM t1 WHERE c = 4}
  {SELECT rowid, a, b, c FROM t1 WHERE c = 5}
  {SELECT rowid, a, b, c FROM t1 WHERE c = 6}
  {SELECT rowid, a, b, c FROM t1 WHERE c = 7}
} {1 5 6 2 6 7}
set ::vtab_handle_in 1

finish_test

Added test/bestindex9.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2020-01-29
#
# 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
set testprefix bestindex9

ifcapable !vtab {
  finish_test
  return
}


proc vtab_command {method args} {
  switch -- $method {
    xConnect {
      return $::create_table
    }

    xBestIndex {
      set hdl [lindex $args 0]
      set ::vtab_orderby [$hdl orderby]
      set ::vtab_distinct [$hdl distinct]

      return [list orderby 1]
    }

    xFilter {
      return ""
    }
  }

  return {}
}

proc do_bestindex9_test {tn create select orderby distinct} {
  forcedelete test.db2
  sqlite3 dbtest test.db2
  register_tcl_module dbtest

  set ::create_table $create
  dbtest eval { CREATE VIRTUAL TABLE t1 USING tcl(vtab_command); }
  dbtest eval $select

  do_test $tn.orderby [list set {} $::vtab_orderby] $orderby
  do_test $tn.distinct [list set {} $::vtab_distinct] $distinct

  dbtest close
}

#-------------------------------------------------------------------------
#
do_bestindex9_test 1.0 {
  CREATE TABLE x(k1, k2, v1, PRIMARY KEY(k1, k2))
} {
  SELECT DISTINCT k1, k2 FROM t1 
} {{column 0 desc 0} {column 1 desc 0}} 2

do_bestindex9_test 1.1 {
  CREATE TABLE x(k1, k2, v1, PRIMARY KEY(k1, k2)) WITHOUT ROWID
} {
  SELECT DISTINCT k1, k2 FROM t1 
} {} 0

do_bestindex9_test 1.2 {
  CREATE TABLE x(k1 NOT NULL, k2 NOT NULL, v1, PRIMARY KEY(k1, k2))
} {
  SELECT DISTINCT k1, k2 FROM t1 
} {} 0

#-------------------------------------------------------------------------
#
do_bestindex9_test 2 {
  CREATE TABLE x(c1, c2, c3);
} {
  SELECT DISTINCT c1 FROM t1 ORDER BY c1
} {{column 0 desc 0}} 3

#-------------------------------------------------------------------------
#
do_bestindex9_test 3 {
  CREATE TABLE x(c1, c2, c3);
} {
  SELECT DISTINCT c1 FROM t1 GROUP BY c1
} {{column 0 desc 0}} 1

do_bestindex9_test 4 {
  CREATE TABLE x(c1, c2, c3);
} {
  CREATE TABLE t2(balls);
  SELECT DISTINCT c1 FROM t1, t2
} {{column 0 desc 0}} 2


finish_test




Added test/bestindexA.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2020-01-29
#
# 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
set testprefix bestindexA

ifcapable !vtab {
  finish_test
  return
}


proc vtab_command {method args} {
  switch -- $method {
    xConnect {
      return "CREATE TABLE x(a, b, c)"
    }

    xBestIndex {
      set hdl [lindex $args 0]
      set clist [$hdl constraints]
      foreach c $clist {
        array set C $c
        lappend ::vtab_constraints [list $C(op) $C(column)]
      }
      return [list]
    }

    xFilter {
      return ""
    }

    xFindFunction {
      foreach {nArg name} $args {}
      if {$nArg==2 && $name=="even"} { 
        return 152 
      }
      return 0
    }

  }

  return {}
}

register_tcl_module db
do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE t1 USING tcl(vtab_command);
}

proc do_xbestindex_test {tn sql res} {
  set script [subst {
    execsql "$sql"
    set ::vtab_constraints
  }]

  uplevel [list do_test $tn $script [list {*}$res]]
  set ::vtab_constraints [list]
}

do_xbestindex_test 1.1 {
  SELECT * FROM t1 WHERE a=?
} {
  {eq 0}
}

do_xbestindex_test 1.2 {
  SELECT * FROM t1 WHERE a=? LIMIT 10
} {
  {eq 0}
  {limit 0}
}

do_xbestindex_test 1.3 {
  SELECT * FROM t1 WHERE a=? AND (b+1)=? LIMIT 10
} {
  {eq 0}
}

proc error_function {args} { error "not a function!" }
db function even error_function

do_xbestindex_test 1.4 {
  SELECT * FROM t1 WHERE even(a, ?)
} {
  {152 0}
}

do_xbestindex_test 1.5 {
  SELECT * FROM t1 WHERE b=10 AND even(a, ?)
} {
  {eq 1}
  {152 0}
}

do_xbestindex_test 1.6 {
  SELECT * FROM t1 WHERE b=10 LIMIT 10
} {
  {eq 1}
  {limit 0}
}

do_xbestindex_test 1.7 {
  SELECT * FROM t1 WHERE even(b,?) LIMIT 10
} {
  {152 1}
  {limit 0}
}

do_xbestindex_test 1.8 {
  SELECT * FROM t1 WHERE b!=? LIMIT 10
} {
  {ne 1}
  {limit 0}
}

do_xbestindex_test 1.9 {
  SELECT * FROM t1 WHERE ?=a LIMIT 10
} {
  {eq 0}
  {limit 0}
}


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 {
115
116
117
118
119
120
121





122
















123
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







+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

} {4 2 25 27 sort t1 i1zyx}
do_test between-1.5.3 {
  queryplan {
    SELECT * FROM t1 WHERE 26 BETWEEN y AND +z ORDER BY +w
  }
} {4 2 25 27 sort t1 *}

#-------------------------------------------------------------------------
reset_db
do_execsql_test between-2.0 {
  CREATE TABLE t1(x TEXT, y TEXT COLLATE nocase);
  INSERT INTO t1 VALUES('0', 'abc');

}

foreach {tn expr res} {
  1 "x                BETWEEN 1 AND '5'" 0
  2 "x COLLATE binary BETWEEN 1 AND '5'" 0
  3 "x COLLATE nocase BETWEEN 1 AND '5'" 0

  4 "y                  BETWEEN 'A' AND 'B'" 1
  5 "y COLLATE nocase   BETWEEN 'A' AND 'B'" 1
  6 "y COLLATE binary   BETWEEN 'A' AND 'B'" 0
  7 "(y COLLATE binary) BETWEEN 'A' AND 'B'" 0
} {
  set sql "SELECT $expr FROM t1"
  do_execsql_test between-2.1.$tn $sql $res
}

finish_test

Changes to test/bigmmap.test.

48
49
50
51
52
53
54
55





56
57
58
59
60
61
62
48
49
50
51
52
53
54

55
56
57
58
59
60
61
62
63
64
65
66







-
+
+
+
+
+







  PRAGMA page_size = 4096;
  CREATE TABLE t0(a INTEGER PRIMARY KEY, b, c, UNIQUE(b, c));
  WITH  s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 100 )
  INSERT INTO t0 SELECT i, 't0', randomblob(800) FROM s;
}

for {set i 1} {$i < 8} {incr i} {
  fake_big_file [expr $i*1024] [get_pwd]/test.db
  if {[catch {fake_big_file [expr $i*1024] [get_pwd]/test.db}]} {
    puts "Cannot create ${i}MB sparse file"
    finish_test
    return
  }
  hexio_write test.db 28 [format %.8x [expr ($i*1024*1024*1024/4096) - 5]]

  do_execsql_test 1.$i "
    CREATE TABLE t$i (a INTEGER PRIMARY KEY, b, c, UNIQUE(b, c));
    WITH  s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 100 )
      INSERT INTO t$i SELECT i, 't$i', randomblob(800) FROM s;
  "
90
91
92
93
94
95
96
97
98
99



100
101
102
103
104
94
95
96
97
98
99
100



101
102
103
104
105
106
107
108







-
-
-
+
+
+





    
    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
      `--CORRELATED SCALAR SUBQUERY
         `--SEARCH TABLE t$t AS i USING INTEGER PRIMARY KEY (rowid=?)
      |--SCAN o USING COVERING INDEX sqlite_autoindex_t${t}_1
      `--CORRELATED SCALAR SUBQUERY xxxxxx
         `--SEARCH i USING INTEGER PRIMARY KEY (rowid=?)
    "]
  }
}

finish_test

Changes to test/bigsort.test.

19
20
21
22
23
24
25



26
27
28
29




30
31
32
33
34
35
36
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







+
+
+




+
+
+
+







# cache-size and page-size was larger than 2^31. Causing an infinite 
# loop if the product was also an integer multiple of 2^32, or 
# inefficiency otherwise.
#
# This test causes thrashing on machines with smaller amounts of
# memory.  Make sure the host has at least 8GB available before running
# this test.
#
# Update: https://sqlite.org/src/info/7c96a56 adds assert() statements
# that make this test too slow to run with SQLITE_DEBUG builds.
#
if {[catch {exec free | grep Mem:} out] || [lindex $out 1]<8000000} {
  finish_test
  return
}
ifcapable debug {
  finish_test
  return
}

do_execsql_test 1.0 {
  PRAGMA page_size = 1024;
  CREATE TABLE t1(a, b);
  BEGIN;
  WITH data(x,y) AS (

Added test/bind2.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022 Feb 10
#
# 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
set testprefix bind2


# Test that using bind_value() on a REAL sqlite3_value that was stored
# as an INTEGER works properly.
#
#   1.1: An IntReal value read from a table,
#   1.2: IntReal values obtained via the sqlite3_preupdate_old|new() 
#        interfaces.
# 
do_execsql_test 1.0 { 
  CREATE TABLE t1(a REAL);
  INSERT INTO t1 VALUES(42.0);
  SELECT * FROM t1;
} {42.0}

do_test 1.1 {
  set stmt [sqlite3_prepare db "SELECT ?" -1 tail]
  sqlite3_bind_value_from_select $stmt 1 "SELECT a FROM t1"
  sqlite3_step $stmt
  sqlite3_column_text $stmt 0
} {42.0}
sqlite3_finalize $stmt

ifcapable !preupdate {
  finish_test
  return
}

proc preup {args} {
  set stmt [sqlite3_prepare db "SELECT ?" -1 tail]
  sqlite3_bind_value_from_preupdate $stmt 1 old 0
  sqlite3_step $stmt
  lappend ::reslist [sqlite3_column_text $stmt 0]
  sqlite3_reset $stmt
  sqlite3_bind_value_from_preupdate $stmt 1 new 0
  sqlite3_step $stmt
  lappend ::reslist [sqlite3_column_text $stmt 0]
  sqlite3_finalize $stmt
}
db preupdate hook preup

do_test 1.2 {
  set ::reslist [list]
  execsql { UPDATE t1 SET a=43; }
  set ::reslist
} {42.0 43.0}

finish_test

Added test/bloom1.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022 October 06
#
# 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.
#
#***********************************************************************
#
# Tests for queries that use bloom filters

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/malloc_common.tcl

set testprefix bloom1

# Tests 1.*  verify that the bloom filter code correctly handles the
# case where the RHS of an (<ipk-column> = ?) expression must be coerced
# to an integer before the comparison made.
#
do_execsql_test 1.0 {
  CREATE TABLE t1(a, b);
  CREATE TABLE t2(c INTEGER PRIMARY KEY, d);
}

do_execsql_test 1.1 {
  INSERT INTO t1 VALUES('hello', 'world');
  INSERT INTO t2 VALUES(14, 'fourteen');
}

do_execsql_test 1.2 {
  ANALYZE sqlite_schema;
  INSERT INTO sqlite_stat1 VALUES('t2','idx1','6 6');
  ANALYZE sqlite_schema;
}

do_execsql_test 1.3 {
  SELECT 'affinity!' FROM t1 CROSS JOIN t2 WHERE t2.c = '14';
} {affinity!}


reset_db
do_execsql_test 1.4 {
  CREATE TABLE t1(a, b TEXT);
  CREATE TABLE t2(c INTEGER PRIMARY KEY, d);
  CREATE TABLE t3(e INTEGER PRIMARY KEY, f);

  ANALYZE sqlite_schema;
  INSERT INTO sqlite_stat1 VALUES('t1','idx1','600 6');
  INSERT INTO sqlite_stat1 VALUES('t2','idx1','6 6');
  INSERT INTO sqlite_stat1 VALUES('t3','idx2','6 6');
  ANALYZE sqlite_schema;

  INSERT INTO t1 VALUES(1, '123');
  INSERT INTO t2 VALUES(123, 'one');
  INSERT INTO t3 VALUES(123, 'two');
}

do_execsql_test 1.5 {
  SELECT 'result' FROM t1, t2, t3 
  WHERE t2.c=t1.b AND t2.d!='silly'
    AND t3.e=t1.b AND t3.f!='silly'
} {result}

finish_test

Changes to test/btree01.test.

124
125
126
127
128
129
130
























131
132
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


      INSERT INTO t1(a,b) SELECT i, zeroblob(6500) FROM c;
      UPDATE t1 SET b=zeroblob(4000);
      UPDATE t1 SET b=zeroblob(65000) WHERE a=$::i;
      PRAGMA integrity_check;
    }
  } {ok}
}

# 2022-03-06 OSSFuzz issue 45329
# An assertion fault due to the failure to clear a flag in an optimization
# committed last night.
#
# When the stay-on-last page optimization of sqlite3BtreeIndexMoveto() is
# invoked, it needs to clear the BTCF_ValidOvfl flag.
#
db close
sqlite3 db :memory:
do_execsql_test btree01-2.1 {
  PRAGMA page_size=1024;
  CREATE TABLE t1(a INT PRIMARY KEY, b BLOB, c INT) WITHOUT ROWID;
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100)
    INSERT INTO t1(a,b,c) SELECT x*2, zeroblob(100), x FROM c;
  UPDATE t1 SET b=zeroblob(1000) WHERE a=198;
  CREATE TABLE t2(x INTEGER PRIMARY KEY, y INT);
  INSERT INTO t2(y) VALUES(198),(187),(100);
  SELECT y, c FROM t2 LEFT JOIN t1 ON y=a ORDER BY x;
} {198 99 187 {} 100 50}
do_execsql_test btree01-2.2 {
  SELECT y, c FROM t1 RIGHT JOIN t2 ON y=a ORDER BY x;
} {198 99 187 {} 100 50}


finish_test

Changes to test/btree02.test.

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
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







-
+







+
+
+
+
+
+



+

-
+
-





-
+

+



+




-
+


set testdir [file dirname $argv0]
source $testdir/tester.tcl

load_static_extension db eval
do_execsql_test btree02-100 {
  CREATE TABLE t1(a TEXT, ax INTEGER, b INT, PRIMARY KEY(a,ax)) WITHOUT ROWID;
  WITH RECURSIVE c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<10)
    INSERT INTO t1(a,ax,b) SELECT printf('%02x',i), random(), i FROM c;
    INSERT INTO t1(a,ax,b) SELECT printf('%02x',i+160), random(), i FROM c;
  CREATE INDEX t1a ON t1(a);
  CREATE TABLE t2(x,y);
  CREATE TABLE t3(cnt);
  WITH RECURSIVE c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<4)
    INSERT INTO t3(cnt) SELECT i FROM c;
  SELECT count(*) FROM t1;
} {10}

proc showt1 {} {
  puts -nonewline "t1: "
  puts [db eval {SELECT printf('(%s,%s)',quote(a),quote(b)) FROM t1}]
}

do_test btree02-110 {
  db eval BEGIN
  set i 0
  # showt1
  db eval {SELECT a, ax, b, cnt FROM t1 CROSS JOIN t3 WHERE b IS NOT NULL} {
    if {$a==""} {set a 0}
    if {$a==""} continue
    if {$b==""} {set b 0}    
    db eval {INSERT INTO t2(x,y) VALUES($b,$cnt)}
    # puts "a,b,cnt = ($a,$b,$cnt)"
    incr i
    if {$i%2==1} {
      set bx [expr {$b+1000}]
      # puts "INSERT ($a),$bx"
      #  puts "INSERT ($a),$bx"
      db eval {INSERT INTO t1(a,ax,b) VALUES(printf('(%s)',$a),random(),$bx)}
      # showt1
    } else {
      # puts "DELETE a=$a"
      db eval {DELETE FROM t1 WHERE a=$a}
      # showt1
    }
    db eval {COMMIT; BEGIN}
  }  
  db one {COMMIT; SELECT count(*) FROM t1;}
} {27}
} {10}

finish_test

Changes to test/btreefault.test.

49
50
51
52
53
54
55

















































56
57
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


} -body {
  execsql { PRAGMA incremental_vacuum = 10 }
} -test {
  sqlite3_finalize $::STMT
  faultsim_test_result {0 {}} 
  faultsim_integrity_check
}

#-------------------------------------------------------------------------
# dbsqlfuzz crash-6ef3cd3b18ccc5de86120950a0498641acd90a33.txt
#
reset_db

do_execsql_test 2.0 {
  CREATE TABLE t1(i INTEGER PRIMARY KEY, a, b);
  CREATE INDEX i1 ON t1(b);
  CREATE TABLE t2(x, y);
}

do_execsql_test 2.1 {
  INSERT INTO t1 VALUES(25, 25, 25);
  INSERT INTO t2 VALUES(25, 'a'), (25, 'b'), (25, 'c');
}

faultsim_save
do_test 2.2 {
  set res [list]
  db eval {
    SELECT x, y FROM t1 CROSS JOIN t2 WHERE t2.x=t1.i AND +t1.i=25 ORDER BY b
  } {
    lappend res $x $y
    if {$y=="b"} {
      db eval { DELETE FROM t1 WHERE i=25 }
    }
  }
  set res
} {25 a 25 b}

do_faultsim_test 2 -faults oom-t* -prep {
  faultsim_restore_and_reopen
  db eval {SELECT * FROM sqlite_master}
} -body {
  set ::myres [list]
  db eval {
    SELECT x, y FROM t1 CROSS JOIN t2 WHERE t2.x=t1.i AND +t1.i=25 ORDER BY b
  } {
    lappend ::myres $x $y
    if {$y=="b"} {
      db eval { DELETE FROM t1 WHERE i=25 }
    }
  }
  set ::myres
} -test {
  faultsim_test_result {0 {25 a 25 b}} 
}


finish_test

Added test/busy2.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2020 June 30
#
# 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 test the busy handler
#
# TESTRUNNER: slow


set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
set testprefix busy2

do_multiclient_test tn {
  do_test 1.$tn.0 {
    sql2 {
      CREATE TABLE t1(a, b);
      PRAGMA journal_mode = wal;
      INSERT INTO t1 VALUES('A', 'B');
    }
  } {wal}

  do_test 1.$tn.1 {
    code1 { db timeout 1000 }
    sql1 { SELECT * FROM t1 }
  } {A B}

  do_test 1.$tn.2 {
    sql2 {
      BEGIN;
        INSERT INTO t1 VALUES('C', 'D');
    }
  } {}

  do_test 1.$tn.3 {
    set us [lindex [time { catch { sql1 { BEGIN EXCLUSIVE } } }] 0]
    expr {$us>950000 && $us<1500000}
  } {1}

  do_test 1.$tn.4 {
    sql2 {
      COMMIT
    }
  } {}
}

#-------------------------------------------------------------------------

do_multiclient_test tn {
  # Make the db a WAL mode db. And add a table and a row to it. Then open
  # a second connection within process 1. Process 1 now has connections
  # [db] and [db1.2], process 2 has connection [db2] only.
  #
  # Configure all connections to use a 1000 ms timeout.
  #
  do_test 2.$tn.0 {
    code1 {
      sqlite3 db1.2 test.db
    }
    sql1 {
      PRAGMA auto_vacuum = off;
      PRAGMA journal_mode = wal;
      CREATE TABLE t1(a, b);
      INSERT INTO t1 VALUES(1, 2);
    }
    code2 {
      db2 timeout 1000
    }
    code1 {
      db1.2 timeout 1000
      db    timeout 1000
      db1.2 eval {SELECT * FROM t1}
    }
  } {1 2}

  # Take a read lock with [db] in process 1.
  #
  do_test 2.$tn.1 {
    sql1 {
      BEGIN;
        SELECT * FROM t1;
    }
  } {1 2}

  # Insert a row using [db2] in process 2. Then try a passive checkpoint.
  # It fails to checkpoint the final frame (due to the readlock taken by
  # [db]), and returns in less than 250ms.
  do_test 2.$tn.2 {
    sql2 { INSERT INTO t1 VALUES(3, 4) }
    set us [lindex [time {
      set res [code2 { db2 eval { PRAGMA wal_checkpoint } }]
    }] 0]
    list [expr $us < 250000] $res
  } {1 {0 4 3}}

  # Now try a FULL checkpoint with [db2]. It returns SQLITE_BUSY. And takes
  # over 950ms to do so.
  do_test 2.$tn.3 {
    set us [lindex [time {
      set res [code2 { db2 eval { PRAGMA wal_checkpoint = FULL } }]
    }] 0]
    list [expr $us > 950000] $res
  } {1 {1 4 3}}

  # Passive checkpoint with [db1.2] (process 1). No SQLITE_BUSY, returns
  # in under 250ms.
  do_test 2.$tn.4 {
    set us [lindex [time {
      set res [code1 { db1.2 eval { PRAGMA wal_checkpoint } }]
    }] 0]
    list [expr $us < 250000] $res
  } {1 {0 4 3}}

  # Full checkpoint with [db1.2] (process 1). SQLITE_BUSY returned in
  # a bit over 950ms.
  do_test 2.$tn.5 {
    set us [lindex [time {
      set res [code1 { db1.2 eval { PRAGMA wal_checkpoint = FULL } }]
    }] 0]
    list [expr $us > 950000] $res
  } {1 {1 4 3}}

  code1 {
    db1.2 close
  }
}

#-------------------------------------------------------------------------
# Check that even if the busy-handler fails (returns zero) within a
# call to sqlite3_prepare() (or _v2(), or _v3()), it is still invoked
# the next time an SQLITE_BUSY is encountered.
#
do_multiclient_test tn {
  code1 {
    set ::busy_called 0
    proc busy {args} {
      if {$::busy_called} { return 1 }
      set ::busy_called 1
      return 0
    }
    db busy busy
  }

  do_test 3.$tn.1 {
    sql2 {
      CREATE TABLE t1(x);
      BEGIN EXCLUSIVE;
        INSERT INTO t1 VALUES('x');
    }
  } {}

  do_test 3.$tn.2 {
    set ::busy_called 0
    list [catch { sql1 { SELECT * FROM t1 } } msg] $::busy_called
  } {1 1}

  do_test 3.$tn.3 {
    set ::busy_called 0
    list [catch { sql1 { SELECT * FROM t1 } } msg] $::busy_called
  } {1 1}

}

finish_test

Changes to test/capi2.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
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







-
+





-
+




















-
+







  sqlite3_data_count $VM
} {2}
do_test capi2-1.4 {
  get_row_values $VM
} {t1 1}
do_test capi2-1.5 {
  get_column_names $VM
} {name rowid text INTEGER}
} {name rowid TEXT INTEGER}
do_test capi2-1.6 {
  sqlite3_step $VM 
} {SQLITE_DONE}
do_test capi2-1.7 {
  list [sqlite3_column_count $VM] [get_row_values $VM] [get_column_names $VM]
} {2 {} {name rowid text INTEGER}}
} {2 {} {name rowid TEXT INTEGER}}

# This used to be SQLITE_MISUSE.  But now we automatically reset prepared
# statements.
ifcapable autoreset {
  do_test capi2-1.8 {
    sqlite3_step $VM
  } {SQLITE_ROW}
} else {
  do_test capi2-1.8 {
    sqlite3_step $VM
  } {SQLITE_MISUSE}
}

# Update: In v2, once SQLITE_MISUSE is returned the statement handle cannot
# be interrogated for more information. However in v3, since the column
# count, names and types are determined at compile time, these are still
# accessible after an SQLITE_MISUSE error.
do_test capi2-1.9 {
  sqlite3_reset $VM
  list [sqlite3_column_count $VM] [get_row_values $VM] [get_column_names $VM]
} {2 {} {name rowid text INTEGER}}
} {2 {} {name rowid TEXT INTEGER}}
do_test capi2-1.10 {
  sqlite3_data_count $VM
} {0}

do_test capi2-1.11 {
  sqlite3_finalize $VM
} {SQLITE_OK}
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
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







-
+





-
+














-
+







    -- A comment at the end
  }
do_test capi2-2.2 {
  set r [sqlite3_step $VM]
  lappend r [sqlite3_column_count $VM] \
            [get_row_values $VM] \
            [get_column_names $VM]
} {SQLITE_ROW 2 {t1 1} {name rowid text INTEGER}}
} {SQLITE_ROW 2 {t1 1} {name rowid TEXT INTEGER}}
do_test capi2-2.3 {
  set r [sqlite3_step $VM]
  lappend r [sqlite3_column_count $VM] \
            [get_row_values $VM] \
            [get_column_names $VM]
} {SQLITE_DONE 2 {} {name rowid text INTEGER}}
} {SQLITE_DONE 2 {} {name rowid TEXT INTEGER}}
do_test capi2-2.4 {
  sqlite3_finalize $VM
} {SQLITE_OK}
do_test capi2-2.5 {
  set VM [sqlite3_prepare $DB $SQL -1 SQL]
  set SQL
} {
    -- A comment at the end
  }
do_test capi2-2.6 {
  set r [sqlite3_step $VM]
  lappend r [sqlite3_column_count $VM] \
            [get_row_values $VM] \
            [get_column_names $VM]
} {SQLITE_DONE 2 {} {name rowid text INTEGER}}
} {SQLITE_DONE 2 {} {name rowid TEXT INTEGER}}
do_test capi2-2.7 {
  sqlite3_finalize $VM
} {SQLITE_OK}
do_test capi2-2.8 {
  set VM [sqlite3_prepare $DB $SQL -1 SQL]
  list $SQL $VM
} {{} {}}

Changes to test/capi3c.test.

1265
1266
1267
1268
1269
1270
1271

1272
1273
1274
1275
1276
1277
1278
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279







+







  do_test capi3c-21.2 {
    sqlite3_extended_errcode $DB
  } {SQLITE_INTERRUPT}
  do_test capi3c-21.3 {
    sqlite3_finalize $STMT
  } {SQLITE_INTERRUPT}
  do_test capi3c-21.4 {
    db progress
    set STMT [sqlite3_prepare $DB {SELECT * FROM t3} -1 TAIL]
    db progress 5 "expr 1"
    sqlite3_step $STMT
  } {SQLITE_ERROR}
  do_test capi3c-21.5 {
    sqlite3_errcode $DB
  } {SQLITE_ERROR}

Changes to test/capi3d.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
121


















































































122
123
124
125
126
127
128
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







-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+













-
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  do_test $testname [format {
    set DB [sqlite3_connection_pointer db]
    set STMT [sqlite3_prepare $DB {%s} -1 TAIL]
    set rc [sqlite3_stmt_readonly $STMT]
    sqlite3_finalize $STMT
    set rc
  } $sql] $truth
}


  # EVIDENCE-OF: R-61212-30018 If prepared statement X is an EXPLAIN or
  # EXPLAIN QUERY PLAN statement, then sqlite3_stmt_readonly(X) returns
  # the same value as if the EXPLAIN or EXPLAIN QUERY PLAN prefix were
  # omitted.
  #
  do_test $testname.explain [format {
    set DB [sqlite3_connection_pointer db]
    set STMT [sqlite3_prepare $DB {EXPLAIN %s} -1 TAIL]
    set rc [sqlite3_stmt_readonly $STMT]
    sqlite3_finalize $STMT
    set rc
  } $sql] $truth
  do_test $testname.eqp [format {
    set DB [sqlite3_connection_pointer db]
    set STMT [sqlite3_prepare $DB {EXPLAIN QUERY PLAN %s} -1 TAIL]
    set rc [sqlite3_stmt_readonly $STMT]
    sqlite3_finalize $STMT
    set rc
  } $sql] $truth
}

# EVIDENCE-OF: R-23332-64992 The sqlite3_stmt_readonly(X) interface
# returns true (non-zero) if and only if the prepared statement X makes
# no direct changes to the content of the database file.
#
test_is_readonly capi3d-2.1 {SELECT * FROM sqlite_master} 1
test_is_readonly capi3d-2.2 {CREATE TABLE t1(x)} 0
db eval {CREATE TABLE t1(x)}
test_is_readonly capi3d-2.3 {INSERT INTO t1 VALUES(5)} 0
test_is_readonly capi3d-2.4 {UPDATE t1 SET x=x+1 WHERE x<0} 0
test_is_readonly capi3d-2.5 {SELECT * FROM t1} 1
ifcapable wal {
  test_is_readonly capi3d-2.6 {PRAGMA journal_mode=WAL} 0
  test_is_readonly capi3d-2.7 {PRAGMA wal_checkpoint} 0
}
test_is_readonly capi3d-2.8 {PRAGMA application_id=1234} 0
test_is_readonly capi3d-2.9 {VACUUM} 0
test_is_readonly capi3d-2.10 {PRAGMA integrity_check} 1
do_test capi3-2.99 {
do_test capi3-2.49 {
  sqlite3_stmt_readonly 0
} 1


# EVIDENCE-OF: R-04929-09147 This routine returns false if there is any
# possibility that the statement might change the database file.
#
# EVIDENCE-OF: R-13288-53765 A false return does not guarantee that the
# statement will change the database file.
#
# EVIDENCE-OF: R-22182-18548 For example, an UPDATE statement might have
# a WHERE clause that makes it a no-op, but the sqlite3_stmt_readonly()
# result would still be false.
#
# EVIDENCE-OF: R-50998-48593 Similarly, a CREATE TABLE IF NOT EXISTS
# statement is a read-only no-op if the table already exists, but
# sqlite3_stmt_readonly() still returns false for such a statement.
#
db eval {
  CREATE TABLE t2(a,b,c);
  INSERT INTO t2 VALUES(1,2,3);
}
test_is_readonly capi3d-2.11 {UPDATE t2 SET a=a+1 WHERE false} 0
test_is_readonly capi3d-2.12 {CREATE TABLE IF NOT EXISTS t2(x,y)} 0


# EVIDENCE-OF: R-37014-01401 The ATTACH and DETACH statements also cause
# sqlite3_stmt_readonly() to return true since, while those statements
# change the configuration of a database connection, they do not make
# changes to the content of the database files on disk.
#
test_is_readonly capi3d-2.13 {ATTACH ':memory:' AS mem1} 1
db eval {ATTACH ':memory:' AS mem1}
test_is_readonly capi3d-2.14 {DETACH mem1} 1
db eval {DETACH mem1}

# EVIDENCE-OF: R-07474-04783 Transaction control statements such as
# BEGIN, COMMIT, ROLLBACK, SAVEPOINT, and RELEASE cause
# sqlite3_stmt_readonly() to return true, since the statements
# themselves do not actually modify the database but rather they control
# the timing of when other statements modify the database.
#
test_is_readonly capi3d-2.15 {BEGIN} 1
test_is_readonly capi3d-2.16 {COMMIT} 1
test_is_readonly capi3d-2.17 {SAVEPOINT one} 1
test_is_readonly capi3d-2.18 {RELEASE one} 1

# EVIDENCE-OF: R-36961-63052 The sqlite3_stmt_readonly() interface
# returns true for BEGIN since BEGIN merely sets internal flags, but the
# BEGIN IMMEDIATE and BEGIN EXCLUSIVE commands do touch the database and
# so sqlite3_stmt_readonly() returns false for those commands.
#
test_is_readonly capi3d-2.19 {BEGIN IMMEDIATE} 0
test_is_readonly capi3d-2.20 {BEGIN EXCLUSIVE} 0

# EVIDENCE-OF: R-21769-42523 For example, if an application defines a
# function "eval()" that calls sqlite3_exec(), then the following SQL
# statement would change the database file through side-effects: SELECT
# eval('DELETE FROM t1') FROM t2; But because the SELECT statement does
# not change the database file directly, sqlite3_stmt_readonly() would
# still return true.
#
proc evalsql {sql} {db eval $sql}
db func eval evalsql
test_is_readonly capi3d-2.21 {SELECT eval('DELETE FROM t1') FROM t2} 1

# Tests for the is-explain interface.
#
proc test_is_explain {testname sql truth} {
  do_test $testname [format {
    set DB [sqlite3_connection_pointer db]
    set STMT [sqlite3_prepare $DB {%s} -1 TAIL]
    set rc [sqlite3_stmt_isexplain $STMT]
    sqlite3_finalize $STMT
    set rc
  } $sql] $truth
}

test_is_explain capi3d-2.51 {SELECT * FROM sqlite_master} 0
test_is_explain capi3d-2.52 { explain SELECT * FROM sqlite_master} 1
test_is_explain capi3d-2.53 {  Explain Query Plan select * FROM sqlite_master} 2
do_test capi3-2.99 {
  sqlite3_stmt_isexplain 0
} 0

# Tests for sqlite3_stmt_busy
#
do_test capi3d-3.1 {
  db eval {INSERT INTO t1 VALUES(6); INSERT INTO t1 VALUES(7);}
  set STMT [sqlite3_prepare db {SELECT * FROM t1} -1 TAIL]
  sqlite3_stmt_busy $STMT
} {0}

Added test/carray01.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2020-11-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 tests for CARRAY extension
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix carray01

ifcapable !vtab {
  finish_test
  return
}
load_static_extension db carray

# Parameter $stmt must be a prepared statement created using
# the sqlite3_prepare_v2 command and with parameters fully bound.
# This routine simply runs the statement, gathers the result, and
# returns a list containing the result.
#
# If the optional second argument is true, then the stmt is finalized
# after it is run.
#
proc run_stmt {stmt} {
  set r {}
  while {[sqlite3_step $stmt]=="SQLITE_ROW"} {
    for {set i 0} {$i<[sqlite3_data_count $stmt]} {incr i} {
      lappend r [sqlite3_column_text $stmt $i]
    }
  }
  sqlite3_reset $stmt
  return $r
}

do_test 100 {
  set STMT [sqlite3_prepare_v2 db {SELECT 5 IN carray(?3)} -1]
  sqlite3_carray_bind $STMT 3 1 2 3 4 5 6 7
  run_stmt $STMT
} {1}
do_test 101 {
  sqlite3_carray_bind -static $STMT 3 1 2 3 4 5 6 7
  run_stmt $STMT
} {1}
do_test 102 {
  set STMT2 [sqlite3_prepare_v2 db {
       SELECT DISTINCT typeof(value) FROM carray(?3)} -1]
  sqlite3_carray_bind $STMT2 3 1 2 3 4 5 6 7
  run_stmt $STMT2
} {integer}
do_test 110 {
  sqlite3_carray_bind $STMT 3 1 2 3 4 6 7
  run_stmt $STMT
} {0}
do_test 120 {
  sqlite3_carray_bind -int64 $STMT 3 1 2 3 4 5 6 7
  run_stmt $STMT
} {1}
do_test 120b {
  sqlite3_carray_bind -int64 $STMT2 3 1 2 3 4 5 6 7
  run_stmt $STMT2
} {integer}
do_test 121 {
  sqlite3_carray_bind -int64 -transient $STMT 3 1 2 3 4 5 6 7
  run_stmt $STMT
} {1}
do_test 122 {
  sqlite3_carray_bind -int64 -static $STMT 3 1 2 3 4 5 6 7
  run_stmt $STMT
} {1}
do_test 123 {
  sqlite3_carray_bind -int32 -transient $STMT 3 1 2 3 4 5 6 7
  run_stmt $STMT
} {1}
do_test 124 {
  sqlite3_carray_bind -int32 -static $STMT 3 1 2 3 4 5 6 7
  run_stmt $STMT
} {1}
do_test 125 {
  sqlite3_carray_bind -int32 $STMT 3 1 2 3 4 5 6 7
  run_stmt $STMT
} {1}
do_test 130 {
  sqlite3_carray_bind -int64 $STMT 3 1 2 3 4 6 7
  run_stmt $STMT
} {0}
do_test 131 {
  sqlite3_carray_bind -int64 -transient $STMT 3 1 2 3 4 6 7
  run_stmt $STMT
} {0}
do_test 131 {
  sqlite3_carray_bind -int64 -static $STMT 3 1 2 3 4 6 7
  run_stmt $STMT
} {0}
do_test 140 {
  sqlite3_carray_bind -double $STMT 3 1 2 3 4 5 6 7
  run_stmt $STMT
} {1}
do_test 141 {
  sqlite3_carray_bind -double -transient $STMT 3 1 2 3 4 5 6 7
  run_stmt $STMT
} {1}
do_test 142 {
  sqlite3_carray_bind -double -static $STMT 3 1 2 3 4 5 6 7
  run_stmt $STMT
} {1}
do_test 143 {
  sqlite3_carray_bind -double $STMT2 3 1 2 3 4 5 6 7
  run_stmt $STMT2
} {real}
do_test 150 {
  sqlite3_carray_bind -double $STMT 3 1 2 3 4 6 7
  run_stmt $STMT
} {0}
do_test 160 {
  sqlite3_carray_bind -double $STMT 3 1 2 3 4 5 6 7
  run_stmt $STMT
} {1}
do_test 170 {
  sqlite3_carray_bind -text -static $STMT 3 1 2 3 4 6 7
  run_stmt $STMT
} {0}
do_test 171 {
  sqlite3_carray_bind -text -static $STMT2 3 1 2 3 4 6 7
  run_stmt $STMT2
} {text}
do_test 180 {
  sqlite3_carray_bind -text -transient $STMT 3 1 2 3 4 5 6 7
  run_stmt $STMT
} {0}
do_test 190 {
  sqlite3_carray_bind -blob -static $STMT 3 1 2 3 4 5 6 7
  run_stmt $STMT
} {0}
do_test 191 {
  sqlite3_carray_bind -blob -static $STMT2 3 1 2 3 4 5 6 7
  run_stmt $STMT2
} {blob}
do_test 200 {
  sqlite3_carray_bind -blob -transient $STMT 3 1 2 3 4 5 6 7
  run_stmt $STMT
} {0}
do_test 300 {
  sqlite3_carray_bind $STMT 3
  run_stmt $STMT
} {0}

sqlite3_finalize $STMT
sqlite3_finalize $STMT2

finish_test

Changes to test/cast.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
215
216
217
218
219
220
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







-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+







do_test cast-1.51 {
  execsql {SELECT CAST('123.5abc' AS numeric)}
} 123.5
do_test cast-1.53 {
  execsql {SELECT CAST('123.5abc' AS integer)}
} 123

do_test case-1.60 {
do_test cast-1.60 {
  execsql {SELECT CAST(null AS REAL)}
} {{}}
do_test case-1.61 {
do_test cast-1.61 {
  execsql {SELECT typeof(CAST(null AS REAL))}
} {null}
do_test case-1.62 {
do_test cast-1.62 {
  execsql {SELECT CAST(1 AS REAL)}
} {1.0}
do_test case-1.63 {
do_test cast-1.63 {
  execsql {SELECT typeof(CAST(1 AS REAL))}
} {real}
do_test case-1.64 {
do_test cast-1.64 {
  execsql {SELECT CAST('1' AS REAL)}
} {1.0}
do_test case-1.65 {
do_test cast-1.65 {
  execsql {SELECT typeof(CAST('1' AS REAL))}
} {real}
do_test case-1.66 {
do_test cast-1.66 {
  execsql {SELECT CAST('abc' AS REAL)}
} {0.0}
do_test case-1.67 {
do_test cast-1.67 {
  execsql {SELECT typeof(CAST('abc' AS REAL))}
} {real}
do_test case-1.68 {
do_test cast-1.68 {
  execsql {SELECT CAST(x'31' AS REAL)}
} {1.0}
do_test case-1.69 {
do_test cast-1.69 {
  execsql {SELECT typeof(CAST(x'31' AS REAL))}
} {real}


# Ticket #1662.  Ignore leading spaces in numbers when casting.
#
do_test cast-2.1 {
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







-
+







      execsql {
        SELECT CAST(CAST(x'39323233333732303336383534373734383030' AS real)
                    AS integer)
      }
    } 9223372036854774784
  }
}
do_test case-3.31 {
do_test cast-3.31 {
  execsql {SELECT CAST(NULL AS numeric)}
} {{}}

# Test to see if it is possible to trick SQLite into reading past 
# the end of a blob when converting it to a number.
do_test cast-3.32.1 {
  set blob "1234567890"
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
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







-
+


+
-
+





-
+










+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

} {-9223372036854775808 -9223372036854775808 -9223372036854775808}

# EVIDENCE-OF: R-33990-33527 When casting to INTEGER, if the text looks
# like a floating point value with an exponent, the exponent will be
# ignored because it is no part of the integer prefix.
# EVIDENCE-OF: R-24225-46995 For example, "(CAST '123e+5' AS INTEGER)"
# results in 123, not in 12300000.
do_execsql_test case-5.3 {
do_execsql_test cast-5.3 {
  SELECT CAST('123e+5' AS INTEGER);
  SELECT CAST('123e+5' AS NUMERIC);
  SELECT CAST('123e+5' AS REAL);
} {123 12300000.0}
} {123 12300000 12300000.0}


# The following does not have anything to do with the CAST operator,
# but it does deal with affinity transformations.
#
do_execsql_test case-6.1 {
do_execsql_test cast-6.1 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a NUMERIC);
  INSERT INTO t1 VALUES
     ('9000000000000000001'),
     ('9000000000000000001 '),
     (' 9000000000000000001'),
     (' 9000000000000000001 ');
  SELECT * FROM t1;
} {9000000000000000001 9000000000000000001 9000000000000000001 9000000000000000001}

# 2019-06-07
# https://www.sqlite.org/src/info/4c2d7639f076aa7c
do_execsql_test cast-7.1 {
  SELECT CAST('-' AS NUMERIC);
} {0}
do_execsql_test cast-7.2 {
  SELECT CAST('-0' AS NUMERIC);
} {0}
do_execsql_test cast-7.3 {
  SELECT CAST('+' AS NUMERIC);
} {0}
do_execsql_test cast-7.4 {
  SELECT CAST('/' AS NUMERIC);
} {0}

# 2019-06-07
# https://www.sqlite.org/src/info/e8bedb2a184001bb
do_execsql_test cast-7.10 {
  SELECT '' - 2851427734582196970;
} {-2851427734582196970}
do_execsql_test cast-7.11 {
  SELECT 0 - 2851427734582196970;
} {-2851427734582196970}
do_execsql_test cast-7.12 {
  SELECT '' - 1;
} {-1}

# 2019-06-10
# https://www.sqlite.org/src/info/dd6bffbfb6e61db9
#
# EVIDENCE-OF: R-55084-10555 Casting a TEXT or BLOB value into NUMERIC
# yields either an INTEGER or a REAL result.
#
do_execsql_test cast-7.20 {
  DROP TABLE IF EXISTS t0;
  CREATE TABLE t0 (c0 TEXT);
  INSERT INTO t0(c0) VALUES ('1.0');
  SELECT CAST(c0 AS NUMERIC) FROM t0;
} {1}

# 2019-06-10
# https://sqlite.org/src/info/27de823723a41df45af3
#
do_execsql_test cast-7.30 {
  SELECT -'.';
} 0
do_execsql_test cast-7.31 {
  SELECT '.'+0;
} 0
do_execsql_test cast-7.32 {
  SELECT CAST('.' AS numeric);
} 0
do_execsql_test cast-7.33 {
  SELECT -CAST('.' AS numeric);
} 0

# 2019-06-12
# https://www.sqlite.org/src/info/674385aeba91c774
#
do_execsql_test cast-7.40 {
  SELECT CAST('-0.0' AS numeric);
} 0
do_execsql_test cast-7.41 {
  SELECT CAST('0.0' AS numeric);
} 0
do_execsql_test cast-7.42 {
  SELECT CAST('+0.0' AS numeric);
} 0
do_execsql_test cast-7.43 {
  SELECT CAST('-1.0' AS numeric);
} -1

ifcapable utf16 {
  reset_db
  execsql { PRAGMA encoding='utf16' }

  do_execsql_test cast-8.1 {
    SELECT quote(X'310032003300')==quote(substr(X'310032003300', 1))
  } 1
  do_execsql_test cast-8.2 {
    SELECT CAST(X'310032003300' AS TEXT)
         ==CAST(substr(X'310032003300', 1) AS TEXT)
  } 1
}

reset_db
do_execsql_test cast-9.0 {
  CREATE TABLE t0(c0);
  INSERT INTO t0(c0) VALUES (0);
  CREATE VIEW v1(c0, c1) AS 
    SELECT CAST(0.0 AS NUMERIC), COUNT(*) OVER () FROM t0;
  SELECT v1.c0 FROM v1, t0 WHERE v1.c0=0; 
} {0.0}

# Set the 2022-12-10 "reopen" of ticket [https://sqlite.org/src/tktview/57c47526c3]
#
do_execsql_test cast-9.1 {
  CREATE TABLE dual(dummy TEXT);
  INSERT INTO dual VALUES('X');
  SELECT CAST(4 AS NUMERIC);
} {4}
do_execsql_test cast-9.2 {
  SELECT CAST(4.0 AS NUMERIC);
} {4.0}
do_execsql_test cast-9.3 {
  SELECT CAST(4.5 AS NUMERIC);
} {4.5}
do_execsql_test cast-9.4 {
  SELECT x, typeof(x) FROM (SELECT CAST(4 AS NUMERIC) AS x) JOIN dual;
} {4 integer}
do_execsql_test cast-9.5 {
  SELECT x, typeof(x) FROM dual CROSS JOIN (SELECT CAST(4 AS NUMERIC) AS x);
} {4 integer}
do_execsql_test cast-9.10 {
  SELECT x, typeof(x) FROM (SELECT CAST(4.0 AS NUMERIC) AS x) JOIN dual;
} {4.0 real}
do_execsql_test cast-9.11 {
  SELECT x, typeof(x) FROM dual CROSS JOIN (SELECT CAST(4.0 AS NUMERIC) AS x);
} {4.0 real}
do_execsql_test cast-9.12 {
  SELECT x, typeof(x) FROM (SELECT CAST(4.5 AS NUMERIC) AS x) JOIN dual;
} {4.5 real}
do_execsql_test cast-9.13 {
  SELECT x, typeof(x) FROM dual CROSS JOIN (SELECT CAST(4.5 AS NUMERIC) AS x);
} {4.5 real}

# 2022-12-15 dbsqlfuzz c9ee6f9a0a8b8fefb02cf69de2a8b67ca39525c8
#
# Added a new SQLITE_AFF_FLEXNUM that does not try to convert int to real or
# real to int.
#
do_execsql_test cast-10.1 {
  VALUES(CAST(44 AS REAL)),(55);
} {44.0 55}
do_execsql_test cast-10.2 {
  SELECT CAST(44 AS REAL) AS 'm' UNION ALL SELECT 55;
} {44.0 55}
do_execsql_test cast-10.3 {
  SELECT * FROM (VALUES(CAST(44 AS REAL)),(55));
} {44.0 55}
do_execsql_test cast-10.4 {
  SELECT * FROM (SELECT CAST(44 AS REAL) AS 'm' UNION ALL SELECT 55);
} {44.0 55}
do_execsql_test cast-10.5 {
  SELECT * FROM dual CROSS JOIN (VALUES(CAST(44 AS REAL)),(55));
} {X 44.0 X 55}
do_execsql_test cast-10.6 {
  SELECT * FROM dual CROSS JOIN (SELECT CAST(44 AS REAL) AS 'm'
                                 UNION ALL SELECT 55);
} {X 44.0 X 55}
do_execsql_test cast-10.7 {
  DROP VIEW v1;
  CREATE VIEW v1 AS SELECT CAST(44 AS REAL) AS 'm' UNION ALL SELECT 55;
  SELECT name, type FROM pragma_table_info('v1');
} {m NUM}
do_execsql_test cast-10.8 {
  CREATE VIEW v2 AS VALUES(CAST(44 AS REAL)),(55);
  SELECT type FROM pragma_table_info('v2');
} {NUM}
do_execsql_test cast-10.9 {
  SELECT * FROM v1;
} {44.0 55}
do_execsql_test cast-10.10 {
  SELECT * FROM v2;
} {44.0 55}

finish_test

Added test/changes.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2021 June 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.
#
#***********************************************************************
#
# Tests for the sqlite3_changes() and sqlite3_total_changes() APIs.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix changes

# To test that the change-counters do not suffer from 32-bit signed integer 
# rollover, add the following line to the array of test cases below. The
# test will take will over an hour to run.
#
#   7 (1<<31)+10 ""
#

foreach {tn nRow wor} {
  1 50 ""
  2 50 "WITHOUT ROWID"

  3 5000 ""
  4 5000 "WITHOUT ROWID"

  5 50000 ""
  6 50000 "WITHOUT ROWID"
} {
  reset_db
  set nBig [expr $nRow]
  
  do_execsql_test 1.$tn.0 "
    PRAGMA journal_mode = off;
    CREATE TABLE t1(x INTEGER PRIMARY KEY) $wor;
  " {off}
  
  do_execsql_test 1.$tn.1 {
    WITH s(i) AS (
      SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i < $nBig
    )
    INSERT INTO t1 SELECT i FROM s;
  }
  
  do_test 1.$tn.2 {
    db changes
  } [expr $nBig]
  
  do_test 1.$tn.3 {
    db total_changes
  } [expr $nBig]
  
  do_execsql_test 1.$tn.4 {
    INSERT INTO t1 VALUES(-1)
  }
  
  do_test 1.$tn.5 {
    db changes
  } [expr 1]
  
  do_test 1.$tn.6 {
    db total_changes
  } [expr {$nBig+1}]
  
  do_execsql_test 1.$tn.7a {
    SELECT count(*) FROM t1
  } [expr {$nBig+1}]
  
  do_execsql_test 1.$tn.7 {
    DELETE FROM t1
  }
  
  do_test 1.$tn.8 {
    db changes
  } [expr {$nBig+1}]
  
  do_test 1.$tn.9 {
    db total_changes
  } [expr {2*($nBig+1)}]
}

finish_test


Added test/changes2.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022 June 6
#
# 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
set testprefix changes2

do_execsql_test 1.0 {
  CREATE TABLE some_table ( 
    id INTEGER NOT NULL, value VARCHAR(40) NOT NULL, PRIMARY KEY (id)
  );
  INSERT INTO some_table (id, value) VALUES (1, 'v1');
} {}

set ::stmt [sqlite3_prepare_v2 db {
  UPDATE some_table SET value='v2' WHERE id=1 RETURNING id
} -1 dummy]

do_test 1.1 {
  list [sqlite3_step $::stmt] [db changes]
} {SQLITE_ROW 1}

do_test 1.2 {
  list [sqlite3_step $::stmt] [db changes]
} {SQLITE_DONE 1}

sqlite3_reset $::stmt

do_execsql_test 1.2 {
  DROP TABLE some_table;
  CREATE TABLE some_table ( 
    id INTEGER NOT NULL, value VARCHAR(40) NOT NULL, PRIMARY KEY (id)
  );
  INSERT INTO some_table (id, value) VALUES (1, 'v1');
} {}

do_test 1.3 {
  list [sqlite3_step $::stmt] [db changes]
} {SQLITE_ROW 1}

do_test 1.4 {
  list [sqlite3_step $::stmt] [db changes]
} {SQLITE_DONE 1}

sqlite3_finalize $::stmt

#-------------------------------------------------------------------------
reset_db

do_execsql_test 2.0 {
  CREATE TABLE t1(a, b);
  CREATE TABLE log(t);
} {}

set ::stmt [sqlite3_prepare_v2 db {
  INSERT INTO log VALUES(changes() || ' changes')
} -1 dummy]

do_execsql_test 2.1 {
  INSERT INTO t1 VALUES (1, 'v1'), (2, 'v2');
} {}

do_test 2.2 {
  list [sqlite3_step $::stmt] [sqlite3_reset $::stmt]
} {SQLITE_DONE SQLITE_OK}

do_execsql_test 2.3 {
  CREATE TABLE t3(x);
}

do_execsql_test 2.2 {
  INSERT INTO t1 VALUES (3, 'v1'), (4, 'v2');
} {}

do_test 2.3 {
  list [sqlite3_step $::stmt] [sqlite3_reset $::stmt]
} {SQLITE_DONE SQLITE_OK}

sqlite3_finalize $::stmt

do_execsql_test 2.4 {
  SELECT * FROM log;
} {{2 changes} {2 changes}}

finish_test

Changes to test/check.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
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













-










+
+



















-
+









-
+







# 2005 November 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.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing CHECK constraints
#
# $Id: check.test,v 1.13 2009/06/05 17:09:12 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set ::testprefix check

# Only run these tests if the build includes support for CHECK constraints
ifcapable !check {
  finish_test
  return
}
sqlite3_db_config db SQLITE_DBCONFIG_DQS_DDL 1
sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1

do_test check-1.1 {
  execsql {
    CREATE TABLE t1(
      x INTEGER CHECK( x<5 ),
      y REAL CHECK( y>x )
    );
  }
} {}
do_test check-1.2 {
  execsql {
    INSERT INTO t1 VALUES(3,4);
    SELECT * FROM t1;
  }  
} {3 4.0}
do_test check-1.3 {
  catchsql {
    INSERT INTO t1 VALUES(6,7);
  }
} {1 {CHECK constraint failed: t1}}
} {1 {CHECK constraint failed: x<5}}
do_test check-1.4 {
  execsql {
    SELECT * FROM t1;
  }  
} {3 4.0}
do_test check-1.5 {
  catchsql {
    INSERT INTO t1 VALUES(4,3);
  }
} {1 {CHECK constraint failed: t1}}
} {1 {CHECK constraint failed: y>x}}
do_test check-1.6 {
  execsql {
    SELECT * FROM t1;
  }  
} {3 4.0}
do_test check-1.7 {
  catchsql {
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
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







-
+









-
+


















+





+
+
+
+
+
+










+
+












+



+
+
+
+
+
+
+





-
+



















-
+




















+







    SELECT * FROM t1;
  }
} {2 4.0}
do_test check-1.12 {
  catchsql {
    UPDATE t1 SET x=7 WHERE x==2
  }
} {1 {CHECK constraint failed: t1}}
} {1 {CHECK constraint failed: x<5}}
do_test check-1.13 {
  execsql {
    SELECT * FROM t1;
  }
} {2 4.0}
do_test check-1.14 {
  catchsql {
    UPDATE t1 SET x=5 WHERE x==2
  }
} {1 {CHECK constraint failed: t1}}
} {1 {CHECK constraint failed: x<5}}
do_test check-1.15 {
  execsql {
    SELECT * FROM t1;
  }
} {2 4.0}
do_test check-1.16 {
  catchsql {
    UPDATE t1 SET x=4, y=11 WHERE x==2
  }
} {0 {}}
do_test check-1.17 {
  execsql {
    SELECT * FROM t1;
  }
} {4 11.0}

do_test check-2.1 {
  execsql {
    PRAGMA writable_schema = 1;
    CREATE TABLE t2(
      x INTEGER CONSTRAINT one CHECK( typeof(coalesce(x,0))=="integer" ),
      y REAL CONSTRAINT two CHECK( typeof(coalesce(y,0.1))=='real' ),
      z TEXT CONSTRAINT three CHECK( typeof(coalesce(z,''))=='text' )
    );
    CREATE TABLE t2n(
      x INTEGER CONSTRAINT one CHECK( typeof(coalesce(x,0))=="integer" ),
      y NUMERIC CONSTRAINT two CHECK( typeof(coalesce(y,0.1))=='real' ),
      z TEXT CONSTRAINT three CHECK( typeof(coalesce(z,''))=='text' )
    );
    PRAGMA writable_schema = 0;
  }
} {}
do_test check-2.2 {
  execsql {
    INSERT INTO t2 VALUES(1,2.2,'three');
    SELECT * FROM t2;
  }
} {1 2.2 three}
db close
sqlite3 db test.db
sqlite3_db_config db SQLITE_DBCONFIG_DQS_DDL 1
sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1
do_test check-2.3 {
  execsql {
    INSERT INTO t2 VALUES(NULL, NULL, NULL);
    SELECT * FROM t2;
  }
} {1 2.2 three {} {} {}}
do_test check-2.4 {
  catchsql {
    INSERT INTO t2 VALUES(1.1, NULL, NULL);
  }
} {1 {CHECK constraint failed: one}}
do_test check-2.5 {
  # The 5 gets automatically promoted to 5.0 because the column type is REAL
  catchsql {
    INSERT INTO t2 VALUES(NULL, 5, NULL);
  }
} {0 {}}
do_test check-2.5b {
  # This time the column type is NUMERIC, so not automatic promption to REAL
  # occurs and the constraint fails.
  catchsql {
    INSERT INTO t2n VALUES(NULL, 5, NULL);
  }
} {1 {CHECK constraint failed: two}}
do_test check-2.6 {
  catchsql {
    INSERT INTO t2 VALUES(NULL, NULL, 3.14159);
  }
} {1 {CHECK constraint failed: three}}
} {0 {}}

# Undocumented behavior:  The CONSTRAINT name clause can follow a constraint.
# Such a clause is ignored.  But the parser must accept it for backwards
# compatibility.
#
do_test check-2.10 {
  execsql {
    CREATE TABLE t2b(
      x INTEGER CHECK( typeof(coalesce(x,0))=='integer' ) CONSTRAINT one,
      y TEXT PRIMARY KEY constraint two,
      z INTEGER,
      UNIQUE(x,z) constraint three
    );
  }
} {}
do_test check-2.11 {
  catchsql {
    INSERT INTO t2b VALUES('xyzzy','hi',5);
  }
} {1 {CHECK constraint failed: t2b}}
} {1 {CHECK constraint failed: typeof(coalesce(x,0))=='integer'}}
do_test check-2.12 {
  execsql {
    CREATE TABLE t2c(
      x INTEGER CONSTRAINT x_one CONSTRAINT x_two
          CHECK( typeof(coalesce(x,0))=='integer' )
          CONSTRAINT x_two CONSTRAINT x_three,
      y INTEGER, z INTEGER,
      CONSTRAINT u_one UNIQUE(x,y,z) CONSTRAINT u_two
    );
  }
} {}
do_test check-2.13 {
  catchsql {
    INSERT INTO t2c VALUES('xyzzy',7,8);
  }
} {1 {CHECK constraint failed: x_two}}
do_test check-2.cleanup {
  execsql {
    DROP TABLE IF EXISTS t2b;
    DROP TABLE IF EXISTS t2c;
    DROP TABLE IF EXISTS t2n;
  }
} {}

ifcapable subquery {
  do_test check-3.1 {
    catchsql {
      CREATE TABLE t3(
252
253
254
255
256
257
258
259

260
261
262
263
264
265
266
271
272
273
274
275
276
277

278
279
280
281
282
283
284
285







-
+







    SELECT * FROM t3;
  }
} {1 2 3}
do_test check-3.9 {
  catchsql {
    INSERT INTO t3 VALUES(111,222,333);
  }
} {1 {CHECK constraint failed: t3}}
} {1 {CHECK constraint failed: t3.x<25}}

do_test check-4.1 {
  execsql {
    CREATE TABLE t4(x, y,
      CHECK (
           x+y==11
        OR x*y==12
294
295
296
297
298
299
300
301




302
303
304
305
306
307
308
313
314
315
316
317
318
319

320
321
322
323
324
325
326
327
328
329
330







-
+
+
+
+







    SELECT * FROM t4
  }
} {12 -22}
do_test check-4.6 {
  catchsql {
    UPDATE t4 SET x=0, y=1;
  }
} {1 {CHECK constraint failed: t4}}
} {1 {CHECK constraint failed: x+y==11
        OR x*y==12
        OR x/y BETWEEN 5 AND 8
        OR -x==y+10}}
do_test check-4.7 {
  execsql {
    SELECT * FROM t4;
  }
} {12 -22}
do_test check-4.8 {
  execsql {
316
317
318
319
320
321
322
323




324
325
326
327
328
329
330
338
339
340
341
342
343
344

345
346
347
348
349
350
351
352
353
354
355







-
+
+
+
+







  PRAGMA ignore_check_constraints=OFF;
  PRAGMA integrity_check;
} {{CHECK constraint failed in t4}}
do_test check-4.9 {
  catchsql {
    UPDATE t4 SET x=0, y=2;
  }
} {1 {CHECK constraint failed: t4}}
} {1 {CHECK constraint failed: x+y==11
        OR x*y==12
        OR x/y BETWEEN 5 AND 8
        OR -x==y+10}}
ifcapable vacuum {
  do_test check_4.10 {
    catchsql {
      VACUUM
    }
  } {0 {}}
}
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
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







-
+











-
+


















-
+







    SELECT * FROM t1;
  }
} {4 11.0 2 20.0}
do_test check-6.5 {
  catchsql {
    UPDATE OR FAIL t1 SET x=7-x, y=y+1;
  }
} {1 {CHECK constraint failed: t1}}
} {1 {CHECK constraint failed: x<5}}
do_test check-6.6 {
  execsql {
    SELECT * FROM t1;
  }
} {3 12.0 2 20.0}
do_test check-6.7 {
  catchsql {
    BEGIN;
    INSERT INTO t1 VALUES(1,30.0);
    INSERT OR ROLLBACK INTO t1 VALUES(8,40.0);
  }
} {1 {CHECK constraint failed: t1}}
} {1 {CHECK constraint failed: x<5}}
do_test check-6.8 {
  catchsql {
    COMMIT;
  }
} {1 {cannot commit - no transaction is active}}
do_test check-6.9 {
  execsql {
    SELECT * FROM t1
  }
} {3 12.0 2 20.0}

do_test check-6.11 {
  execsql {SELECT * FROM t1}
} {3 12.0 2 20.0}
do_test check-6.12 {
  catchsql {
    REPLACE INTO t1 VALUES(6,7);
  }
} {1 {CHECK constraint failed: t1}}
} {1 {CHECK constraint failed: x<5}}
do_test check-6.13 {
  execsql {SELECT * FROM t1}
} {3 12.0 2 20.0}
do_test check-6.14 {
  catchsql {
    INSERT OR IGNORE INTO t1 VALUES(6,7);
  }
422
423
424
425
426
427
428
429

430
431
432
433
434

435
436
437
438
439
440
441
447
448
449
450
451
452
453

454
455
456
457
458

459
460
461
462
463
464
465
466







-
+




-
+







# If a connection opens a database that contains a CHECK constraint that
# uses an unknown UDF, the schema should not be considered malformed.
# Attempting to modify the table should fail (since the CHECK constraint
# cannot be tested).
#
reset_db
proc myfunc {x} {expr $x < 10}
db func myfunc myfunc
db func myfunc -deterministic myfunc

do_execsql_test  7.1 { CREATE TABLE t6(a CHECK (myfunc(a))) }
do_execsql_test  7.2 { INSERT INTO t6 VALUES(9)  }
do_catchsql_test 7.3 { INSERT INTO t6 VALUES(11) } \
          {1 {CHECK constraint failed: t6}}
          {1 {CHECK constraint failed: myfunc(a)}}

do_test 7.4 {
  sqlite3 db2 test.db
  execsql { SELECT * FROM t6 } db2 
} {9}

do_test 7.5 {
450
451
452
453
454
455
456
457

458
459
460
461
462
463
464
475
476
477
478
479
480
481

482
483
484
485
486
487
488
489







-
+







  db2 func myfunc myfunc
  execsql { INSERT INTO t6 VALUES(8) } db2
} {}

do_test 7.8 {
  db2 func myfunc myfunc
  catchsql { INSERT INTO t6 VALUES(12) } db2
} {1 {CHECK constraint failed: t6}}
} {1 {CHECK constraint failed: myfunc(a)}}

# 2013-08-02:  Silently ignore database name qualifiers in CHECK constraints.
#
do_execsql_test 8.1 {
  CREATE TABLE t810(a, CHECK( main.t810.a>0 ));
  CREATE TABLE t811(b, CHECK( xyzzy.t811.b BETWEEN 5 AND 10 ));
} {}
488
489
490
491
492
493
494
495






























































































496
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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

forcedelete test.db
sqlite3 db test.db
do_execsql_test 10.1 {
  CREATE TABLE t1(x);
  CREATE VIEW v1(y) AS SELECT x FROM t1;
  PRAGMA integrity_check;
} {ok}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 11.0 {
  CREATE TABLE t1 (Col0 CHECK(1 COLLATE BINARY BETWEEN 1 AND 1) ) ;
}
do_execsql_test 11.1 {
  INSERT INTO t1 VALUES (NULL);
}
do_execsql_test 11.2 {
  INSERT  INTO t1 VALUES (NULL);
}

do_execsql_test 11.3 {
  CREATE TABLE t2(b, a CHECK(
      CASE 'abc' COLLATE nocase WHEN a THEN 1 ELSE 0 END)
  );
}
do_execsql_test 11.4 {
  INSERT INTO t2(a) VALUES('abc');
}
do_execsql_test 11.5 {
  INSERT INTO t2(b, a) VALUES(1, 'abc'||'');
}
do_execsql_test 11.6 {
  INSERT INTO t2(b, a) VALUES(2, 'abc');
}

# 2019-12-24 ticket b383b90278186263
#
reset_db
do_execsql_test 12.10 {
  CREATE TABLE t1(a TEXT, CHECK(a=+a));
  INSERT INTO t1(a) VALUES(NULL),('xyz'),(5),(x'303132'),(4.75);
  SELECT quote(a) FROM t1 ORDER BY rowid;
} {NULL 'xyz' '5' X'303132' '4.75'}
do_execsql_test 12.20 {
  DROP TABLE t1;
  CREATE TABLE t1(a TEXT, CHECK(a<>+a));
  INSERT INTO t1(a) VALUES(NULL);
} {}
do_catchsql_test 12.21 {
  INSERT INTO t1(a) VALUES('xyz');
} {1 {CHECK constraint failed: a<>+a}}
do_catchsql_test 12.22 {
  INSERT INTO t1(a) VALUES(123);
} {1 {CHECK constraint failed: a<>+a}}
do_execsql_test 12.30 {
  DROP TABLE t1;
  CREATE TABLE t1(a TEXT, CHECK(NOT(a=+a)));
  INSERT INTO t1(a) VALUES(NULL);
} {}
do_catchsql_test 12.31 {
  INSERT INTO t1(a) VALUES('xyz');
} {1 {CHECK constraint failed: NOT(a=+a)}}
do_catchsql_test 12.32 {
  INSERT INTO t1(a) VALUES(123);
} {1 {CHECK constraint failed: NOT(a=+a)}}
do_execsql_test 12.40 {
  DROP TABLE t1;
  CREATE TABLE t1(a TEXT, CHECK(NOT(a<>+a)));
  INSERT INTO t1(a) VALUES(NULL),('xyz'),(5),(x'303132'),(4.75);
  SELECT quote(a) FROM t1 ORDER BY rowid;
} {NULL 'xyz' '5' X'303132' '4.75'}
do_execsql_test 12.50 {
  DROP TABLE t1;
  CREATE TABLE t1(a TEXT, CHECK(a BETWEEN 0 AND +a));
  INSERT INTO t1(a) VALUES(NULL),('xyz'),(5),(x'303132'),(4.75);
  SELECT quote(a) FROM t1 ORDER BY rowid;
} {NULL 'xyz' '5' X'303132' '4.75'}
do_execsql_test 12.60 {
  DROP TABLE t1;
  CREATE TABLE t1(a TEXT, CHECK(a NOT BETWEEN 0 AND +a));
  INSERT INTO t1(a) VALUES(NULL);
  SELECT quote(a) FROM t1 ORDER BY rowid;
} {NULL}
do_catchsql_test 12.61 {
  INSERT INTO t1(a) VALUES(456);
} {1 {CHECK constraint failed: a NOT BETWEEN 0 AND +a}}
do_execsql_test 12.70 {
  DROP TABLE t1;
  CREATE TABLE t1(a TEXT, CHECK(a BETWEEN +a AND 999999));
  INSERT INTO t1(a) VALUES(NULL),(5);
  SELECT quote(a) FROM t1 ORDER BY rowid;
} {NULL '5'}
do_execsql_test 12.80 {
  DROP TABLE t1;
  CREATE TABLE t1(a TEXT, CHECK(a NOT BETWEEN +a AND 999999));
  INSERT INTO t1(a) VALUES(NULL);
  SELECT quote(a) FROM t1 ORDER BY rowid;
} {NULL}
do_catchsql_test 12.81 {
  INSERT INTO t1(a) VALUES(456);
} {1 {CHECK constraint failed: a NOT BETWEEN +a AND 999999}}

finish_test

Added test/checkfault.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019 July 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 contains fault-injection test cases for the 
# sqlite3_db_cacheflush API.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix cffault
source $testdir/malloc_common.tcl

do_execsql_test 1.0 {
  CREATE TABLE t1 (Col0 CHECK(1 COLLATE BINARY BETWEEN 1 AND 1) ) ;
  CREATE TABLE t2(b, a CHECK(
      CASE 'abc' COLLATE nocase WHEN a THEN 1 ELSE 0 END)
  );
}

do_faultsim_test 1.1 -faults oom* -body {
  execsql { INSERT INTO t1 VALUES ('ABCDEFG') }
} -test {
  faultsim_test_result {0 {}}
}

do_faultsim_test 1.2 -faults oom* -body {
  execsql { INSERT INTO t2(a) VALUES('abc') }
} -test {
  faultsim_test_result {0 {}}
}


finish_test

Added test/chunksize.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019 June 5
#
# 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
set testprefix chunksize

if {$::tcl_platform(platform)!="unix"} {
  finish_test
  return
}

foreach {tn jrnlmode} {
  1 delete
  2 wal
} {
  reset_db
  file_control_chunksize_test db main 32768
  do_execsql_test $tn.0 " PRAGMA journal_mode = $jrnlmode " $jrnlmode
  do_execsql_test $tn.1 {
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES(1, 2);
  }

  execsql { PRAGMA wal_checkpoint }

  do_test $tn.2 {
    file size test.db
  } 32768
}

finish_test

Changes to test/close.test.

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







+
+
+
+
+
+
+


    sqlite3_prepare $DB "SELECT * FROM sqlite_master" -1 dummy
  } msg] $msg
} {1 {(21) bad parameter or other API misuse}}

do_test 1.4.4 {
  sqlite3_finalize $STMT
} {SQLITE_OK}

do_test 1.5 {
  set DB [sqlite3_open test.db]
  sqlite3_blob_open $DB main t1 x 2 0 BLOB
  sqlite3_close_v2 $DB
  sqlite3_blob_close $BLOB
} {}

finish_test

Changes to test/collate1.test.

334
335
336
337
338
339
340

341
342
343
344
345
346
347
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348







+







} {1 2}



#-------------------------------------------------------------------------
# Fix problems with handling collation sequences named '"""'.
#
sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1
do_execsql_test 6.1 {
  SELECT """""""";
} {\"\"\"}

do_catchsql_test 6.2 {
  CREATE TABLE x1(a);
  SELECT a FROM x1 ORDER BY a COLLATE """""""";
396
397
398
399
400
401
402


403














































404
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







+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

    ORDER BY 1 COLLATE nocase COLLATE nocase COLLATE nocase COLLATE binary;
} {DEF abc}
do_execsql_test 7.2 {
   SELECT 'abc' UNION ALL SELECT 'DEF'
    ORDER BY 1 COLLATE binary COLLATE binary COLLATE binary COLLATE nocase;
} {abc DEF}

# 2019-06-14
# https://sqlite.org/src/info/f1580ba1b574e9e9

#
do_execsql_test 8.0 {
  SELECT ' ' > char(20) COLLATE rtrim;
} 0
do_execsql_test 8.1 {
  SELECT '' < char(20) COLLATE rtrim;
} 1
do_execsql_test 8.2 {
  DROP TABLE IF EXISTS t0;
  CREATE TABLE t0(c0 COLLATE RTRIM, c1 BLOB UNIQUE,
                  PRIMARY KEY (c0, c1)) WITHOUT ROWID;
  INSERT INTO t0 VALUES (123, 3), (' ', 1), ('	', 2), ('', 4);
  SELECT * FROM t0 WHERE c1 = 1;
} {{ } 1}

# 2019-10-09
# ALWAYS() macro fails following OOM
# Problem detected by dbsqlfuzz.
#
do_execsql_test 9.0 {
  CREATE TABLE t1(a, b);
  CREATE TABLE t2(c, d);
}

do_faultsim_test 9.1 -faults oom* -body {
  execsql {
    SELECT * FROM (
        SELECT b COLLATE nocase IN (SELECT c FROM t2) FROM t1
    );
  }
} -test {
  faultsim_test_result {0 {}}
}

# 2020-01-03 dbsqlfuzz find
#
reset_db
do_catchsql_test 10.0 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY,b);
  INSERT INTO t1 VALUES(0,NULL);
  CREATE TABLE t2(x UNIQUE);
  CREATE VIEW v1a(z,y) AS SELECT x COLLATE x FROM t2;
  SELECT a,b,z,y,'' FROM t1 JOIN v1a ON b IS NOT FALSE;
} {1 {no such collation sequence: x}}


finish_test

Changes to test/collate2.test.

680
681
682
683
684
685
686
687

688
689

690
691
692













693
694
695






696
697
698
699
700
701
702
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







-
+

-
+


-
+
+
+
+
+
+
+
+
+
+
+
+
+



+
+
+
+
+
+







  }
} {aa aA Aa AA}
do_test collate2-5.3 {
  execsql {
    SELECT collate2t1.b FROM collate2t2 NATURAL JOIN collate2t1;
  }
} {aa}
do_test collate2-5.4 {
do_test collate2-5.4.1 {
  execsql {
    SELECT collate2t2.b FROM collate2t1 LEFT OUTER JOIN collate2t2 USING (b) order by collate2t1.oid;
    SELECT collate2t2.b FROM collate2t1 LEFT JOIN collate2t2 USING (b) order by collate2t1.oid;
  }
} {{} aa {} {} {} aa {} {} {} aa {} {} {} aa {} {} {}}
do_test collate2-5.5 {
do_test collate2-5.4.2 {
  execsql {
    SELECT collate2t2.b FROM collate2t2 RIGHT JOIN collate2t1 ON collate2t1.b=collate2t2.b
     ORDER BY collate2t1.oid;
  }
} {{} aa {} {} {} aa {} {} {} aa {} {} {} aa {} {} {}}
do_test collate2-5.4.3 {
  execsql {
    SELECT collate2t2.b FROM collate2t1 LEFT JOIN collate2t2 ON collate2t2.b=collate2t1.b
     ORDER BY collate2t1.oid;
  }
} {{} aa {} {} {} {} {} {} {} {} {} {} {} {} {} {} {}}
do_test collate2-5.5.1 {
  execsql {
    SELECT collate2t1.b, collate2t2.b FROM collate2t2 LEFT OUTER JOIN collate2t1 USING (b);
  }
} {aa aa}
do_test collate2-5.5.2 {
  execsql {
    SELECT collate2t1.b, collate2t2.b
      FROM collate2t1 RIGHT JOIN collate2t2 ON collate2t2.b=collate2t1.b
  }
} {aa aa}

do_execsql_test 6.1 {
  CREATE TABLE t1(x);
  INSERT INTO t1 VALUES('b');
  INSERT INTO t1 VALUES('B');
}

Changes to test/collate5.test.

15
16
17
18
19
20
21


22
23
24
25
26
27
28

29
30
31
32
33
34
35
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38







+
+







+







# GROUP BY clauses that use user-defined collation sequences.
#
# $Id: collate5.test,v 1.7 2008/09/16 11:58:20 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

set testprefix collate5


#
# Tests are organised as follows:
# collate5-1.* - DISTINCT
# collate5-2.* - Compound SELECT
# collate5-3.* - ORDER BY on compound SELECT
# collate5-4.* - GROUP BY
# collate5-5.* - Collation sequence cases

# Create the collation sequence 'TEXT', purely for asthetic reasons. The
# test cases in this script could just as easily use BINARY.
db collate TEXT [list string compare]

# Mimic the SQLite 2 collation type NUMERIC.
db collate numeric numeric_collate
284
285
286
287
288
289
290
291

































292
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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  }
} {/[aA] 1(.0)? 2 [bB] 2 1 [bB] 3 1/}
do_test collate5-4.3 {
  execsql {
    DROP TABLE collate5t1;
  }
} {}

#-------------------------------------------------------------------------
reset_db

do_execsql_test 5.0 {
  CREATE TABLE t1(a, b COLLATE nocase);
  CREATE TABLE t2(c, d);
  INSERT INTO t2 VALUES(1, 'bbb');
}
do_execsql_test 5.1 {
  SELECT * FROM (
      SELECT a, b FROM t1 UNION ALL SELECT c, d FROM t2
  ) WHERE b='BbB';
} {1 bbb}

reset_db
do_execsql_test 5.2 {
  CREATE TABLE t1(a,b,c COLLATE NOCASE);
  INSERT INTO t1 VALUES(NULL,'C','c');
  CREATE VIEW v2 AS
    SELECT a,b,c FROM t1 INTERSECT SELECT a,b,b FROM t1
    WHERE 'eT"3qRkL+oJMJjQ9z0'>=b
    ORDER BY a,b,c;
}

do_execsql_test 5.3 {
  SELECT * FROM v2;
} { {} C c }

do_execsql_test 5.4 {
  SELECT * FROM v2 WHERE c='c';
} { {} C c }


finish_test

Changes to test/colname.test.

395
396
397
398
399
400
401






402
403
404
405
406
407
408
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414







+
+
+
+
+
+







} {Bbb 123}
ifcapable vtab {
  do_execsql_test colname-9.320 {
    CREATE TABLE t2 AS SELECT BBb FROM (SELECT aaa AS Bbb FROM t1);
    SELECT name FROM pragma_table_info('t2');
  } {Bbb}
}
do_execsql_test colname-9.330 { -- added 2019-08-10 to invalidate
  DROP TABLE IF EXISTS t1;      -- a couple assert()s that were
  CREATE TABLE t1(a);           -- added by ticket 3b44500725
  INSERT INTO t1 VALUES(17),(2),(99),(-3),(7);
  SELECT (SELECT avg(a) UNION SELECT min(a) OVER()) FROM t1;
} {17}

# Issue detected by OSSFuzz on 2017-12-24 (Christmas Eve)
# caused by check-in https://sqlite.org/src/info/6b2ff26c25
#
# Prior to being fixed, the following CREATE TABLE was dereferencing
# a NULL pointer and segfaulting.
#

Added test/columncount.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2021 February 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 the sqlite3_column_count() API.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix columncount

# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
ifcapable !altertable {
  finish_test
  return
}

proc do_ccsql_test {tn sql res} {

  uplevel [list do_test $tn [subst -nocommands {
    set stmt [sqlite3_prepare_v2 db {$sql} -1 dummy]
    set res [sqlite3_column_count [set stmt]]
    while {[sqlite3_step [set stmt]]=="SQLITE_ROW"} {
      for {set i 0} {[set i] < [sqlite3_data_count [set stmt]]} {incr i} {
        lappend res [sqlite3_column_text [set stmt] [set i]]
      }
    }
  
    set rc [sqlite3_finalize [set stmt]]
    if {[set rc]!="SQLITE_OK"} {
      error [sqlite3_errmsg db]
    }

    set res
  }] [list {*}$res]]

}

do_execsql_test 1.0 {
  CREATE TABLE t1(x, y, z);
  INSERT INTO t1 VALUES('a', 'b', 'c');
}

do_ccsql_test 1.1 { SELECT * FROM t1 }      {3    a b c}
do_ccsql_test 1.2 { CREATE TABLE t2(a, b) } {0}

do_ccsql_test 1.3 { ALTER TABLE t2 RENAME TO t3 } {0}
do_ccsql_test 1.4 { ALTER TABLE t3 RENAME b TO ccc } {0}
do_ccsql_test 1.5 { ALTER TABLE t3 ADD COLUMN d } {0}

do_ccsql_test 1.6 { DROP TABLE t3 } {0}



finish_test

Added test/concfault2.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2018 Dec 28
#
# 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 contains fault injection tests designed to test the concurrent
# transactions feature.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/malloc_common.tcl
set testprefix concfault2

ifcapable !concurrent {
  finish_test
  return
}

do_execsql_test 1.0 {
  PRAGMA auto_vacuum = 0;
  PRAGMA journal_mode = wal2;
  CREATE TABLE t1(a PRIMARY KEY, b);
  CREATE TABLE t2(a PRIMARY KEY, b);
  INSERT INTO t1 VALUES(randomblob(1000), randomblob(100));
  INSERT INTO t1 SELECT randomblob(1000), randomblob(1000) FROM t1;
  INSERT INTO t1 SELECT randomblob(1000), randomblob(1000) FROM t1;
  INSERT INTO t1 SELECT randomblob(1000), randomblob(1000) FROM t1;
  INSERT INTO t1 SELECT randomblob(1000), randomblob(1000) FROM t1;
  DELETE FROM t1 WHERE rowid%2;
} {wal2}

do_test 1.1 {
  list [expr [file size test.db-wal]>75000] [file size test.db-shm]
} {1 32768}

faultsim_save_and_close

do_faultsim_test 1 -prep {
  faultsim_restore_and_reopen
  execsql {
    SELECT * FROM t1;
    BEGIN CONCURRENT;
      INSERT INTO t2 VALUES(1, 2);
  }
  sqlite3 db2 test.db
  execsql {
    PRAGMA journal_size_limit = 10000;
    INSERT INTO t1 VALUES(randomblob(1000), randomblob(1000));
  } db2
  db2 close
} -body {
  execsql { COMMIT }
} -test {
  faultsim_test_result {0 {}} 
  catchsql { ROLLBACK }
  set res [catchsql { SELECT count(*) FROM t1 }]
  if {$res!="0 9"} { error "expected {0 9} got {$res}" }
  faultsim_integrity_check
}

finish_test

Changes to test/concurrent.test.

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
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







+









+
-
+
+

+
+
+
+
-
+
+
+




-
+







  sqlite3_finalize $stmt
  catchsql ROLLBACK
}

#-------------------------------------------------------------------------
# CONCURRENT transactions may not modify the db schema.
#
sqlite3 db2 test.db
foreach {tn sql} {
  1 { CREATE TABLE xx(a, b) }
  2 { DROP TABLE t1 }
  3 { CREATE INDEX i1 ON t1(a) }
  4 { CREATE VIEW v1 AS SELECT * FROM t1 }
} {
  do_catchsql_test 1.7.0.$tn.1 "
    BEGIN CONCURRENT;
    $sql
  " {0 {}}
  " {1 {cannot modify database schema within CONCURRENT transaction}}

  db2 eval {INSERT INTO t1 DEFAULT VALUES}

  do_catchsql_test 1.7.0.$tn.2 {
    COMMIT
  } {1 {database is locked}}

  do_execsql_test 1.7.0.$tn.2 {
  do_execsql_test 1.7.0.$tn.2 ROLLBACK

  do_execsql_test 1.7.0.$tn.3 {
    SELECT sql FROM sqlite_master;
    SELECT sql FROM sqlite_temp_master;
  } {{CREATE TABLE t1(a, b)}}

  do_execsql_test 1.7.0.$tn.3 COMMIT
  #do_execsql_test 1.7.0.$tn.3 COMMIT
}

# Except the temp db schema.
foreach {tn sql} {
  1 { CREATE TEMP TABLE xx(a, b) }
  2 { DROP TABLE xx }
  3 { CREATE TEMP TABLE yy(a, b) }

Changes to test/concurrent2.test.

18
19
20
21
22
23
24




25
26
27
28
29
30
31
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35







+
+
+
+







source $testdir/wal_common.tcl
set ::testprefix concurrent2

ifcapable !concurrent {
  finish_test
  return
}

do_test 0.1 {
  llength [sqlite3_wal_info db main]
} {2}

do_multiclient_test tn {

  do_test 1.$tn.1 {
    sql1 {
      PRAGMA journal_mode = wal;
      CREATE TABLE t1(x);

Changes to test/concurrent3.test.

222
223
224
225
226
227
228



229
230
231
222
223
224
225
226
227
228
229
230
231
232
233
234







+
+
+



    $db close 
  }
  # foreach k [lsort [array names used]] {
  #   puts "$k: $stats($k,0) committed, $stats($k,1) rolled back"
  # }
}

catch { db close }
sqlite3_shutdown
test_sqlite3_log


finish_test

Added test/concurrent8.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2020 July 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.
#
#***********************************************************************
#


set testdir [file dirname $argv0]
source $testdir/tester.tcl
set ::testprefix concurrent8

source $testdir/lock_common.tcl

ifcapable !concurrent {
  finish_test
  return
}

do_multiclient_test tn {

  do_test 1.$tn.0 {
    sql1 {
      CREATE TABLE t1(x, y);
      PRAGMA journal_mode = wal;
    }
  } {wal}

  do_test 1.$tn.1 {
    sql1 {
      BEGIN CONCURRENT;
        INSERT INTO t1 VALUES(1, 1);
    }
  } {}

  do_test 1.$tn.2 {
    sql2 {
      CREATE TABLE t2(a, b);
    }
  } {}

  do_test 1.$tn.3 {
    list [catch { sql1 { COMMIT } } msg] $msg
  } {1 {database is locked}}

  do_test 1.$tn.4 {
    code1 { db errorcode }
  } {517}  ;# SQLITE_BUSY_SNAPSHOT

  do_test 1.$tn.5 {
    sql1 {
      ROLLBACK;
      BEGIN CONCURRENT;
        CREATE TABLE t3(a, b);
      COMMIT;
    }
  } {}

  do_test 1.$tn.6 {
    set nPg [sql1 {PRAGMA page_count}]
    sql1 "BEGIN CONCURRENT"
    for {set i 0} {$i<250} {incr i} {
      sql1 "CREATE TABLE z$i (a, b, c)"
    }
    sql1 "COMMIT"
    set nPg2 [sql1 {PRAGMA page_count}]
    expr $nPg2>$nPg
  } {1}

  do_test 1.$tn.7 {
    sql2 { PRAGMA integrity_check }
  } {ok}

  do_test 1.$tn.8 {
    sql1 {
      BEGIN CONCURRENT;
        CREATE TABLE t4(a, b);
    }
    sql2 {
      INSERT INTO t1 VALUES(2, 2);
    }
    list [catch { sql1 COMMIT } msg] $msg
  } {1 {database is locked}}
  sql1 ROLLBACK

  do_test 1.$tn.9 {
    sql1 {
      BEGIN CONCURRENT;
        CREATE TEMP TABLE t5(a, b);
        INSERT INTO t2 VALUES('x', 'x');
    }
    sql2 {
      INSERT INTO t1 VALUES(3, 3);
      CREATE TEMP TABLE t1(x, y);
    }
    sql1 COMMIT 
  } {}
}



finish_test


Added test/concurrent9.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2023 January 12
#
# 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 concurrent9

do_execsql_test 1.0 {
  CREATE TABLE t1(x);
  INSERT INTO t1 VALUES(1), (2);
  CREATE TABLE t2(y);
  INSERT INTO t2 VALUES('a'), ('b');
  PRAGMA journal_mode = wal;
} {wal}

db close

#-------------------------------------------------------------------------
# Fix a problem that may occur if a BEGIN CONCURRENT transaction is 
# started when the wal file is completely empty and committed after
# it has been initialized by some other connection.
#
sqlite3 db  test.db
sqlite3 db2 test.db

do_execsql_test -db db  1.1 {
  BEGIN CONCURRENT;
    INSERT INTO t2 VALUES('c');
}

do_execsql_test -db db2  1.2 {
  INSERT INTO t1 VALUES(3);
}

do_execsql_test -db db  1.3 {
  COMMIT;
}

do_execsql_test -db db2  1.4 {
  SELECT * FROM t1;
  SELECT * FROM t2;
} {1 2 3 a b c}

finish_test

Changes to test/conflict.test.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
9
10
11
12
13
14
15

16
17
18
19
20
21
22







-







#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for the conflict resolution extension
# to SQLite.
#
# $Id: conflict.test,v 1.32 2009/04/30 09:10:38 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable !conflict {
  finish_test
  return
810
811
812
813
814
815
816
817

818
819
820
821
822
823
824
825
826
827
































































828
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







-
+










+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

    CREATE TABLE t13(a CHECK(a!=2));
    BEGIN;
    REPLACE INTO t13 VALUES(1);
  }
  catchsql {
    REPLACE INTO t13 VALUES(2);
  }
} {1 {CHECK constraint failed: t13}}
} {1 {CHECK constraint failed: a!=2}}
verify_ex_errcode conflict-13.1b SQLITE_CONSTRAINT_CHECK
do_test conflict-13.2 {
  execsql {
    REPLACE INTO t13 VALUES(3);
    COMMIT;
    SELECT * FROM t13;
  }
} {1 3}


# Ticket https://www.sqlite.org/src/tktview/e6f1f2e34dceeb1ed61531c7e9
# Verify that it is not possible to sneak a NULL value into a NOT NULL
# column using REPLACE.
#
do_catchsql_test conflict-14.1 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(x NOT NULL DEFAULT NULL);
  REPLACE INTO t1 DEFAULT VALUES;
} {1 {NOT NULL constraint failed: t1.x}}

# 2019-12-15 gramfuzz1 find
# Three UNIQUE constraints, where the third would is a duplicate except
# that it adds ON CONFLICT REPLACE.  Verify that the indexes end up
# sorted in the correct order (REPLACE last) so that constraint processing
# works correctly.
#
reset_db
do_execsql_test conflict-15.10 {
  CREATE TABLE t1(
    x PRIMARY KEY,
    UNIQUE(x,x),
    UNIQUE(x,x) ON CONFLICT REPLACE
  );
  INSERT INTO t1(x) VALUES(1);
  SELECT * FROM t1;
} {1}
do_catchsql_test conflict-15.20 {
  INSERT INTO t1(x) VALUES(1);
} {1 {UNIQUE constraint failed: t1.x}}
do_execsql_test conflict-15.30 {
  SELECT * FROM t1;
} {1}

# 2023-01-16 https://sqlite.org/forum/forumpost/aa580a5af38a58e3
# The parser accepts an ON CONFLICT clause on table CHECK constraints
# but not on column CHECK constraints.  But the CHECK constraint is
# ignored.  It has been like this since version 3.0.0.
#
# There might be applications and/or databases in the wild that have
# table CHECK constraints with ON CONFLICT clauses.  In as much as this
# is a harmless quirk, we continue to support it in order to avoid
# breaking those legacy applications and databases.
#
reset_db
do_catchsql_test conflict-16.1 {
  -- ON CONFLICT clauses are not allowed on column CHECK constraints
  CREATE TABLE t1(a INT CHECK( a!=5 ) ON CONFLICT ignore);
} {1 {near "ON": syntax error}}
do_execsql_test conflict-16.2 {
  -- ON CONFLICT is allowed on table CHECK constraints
  CREATE TABLE t1(a INT, CHECK( a!=5 ) ON CONFLICT ignore);
} {}
do_catchsql_test conflict-16.3 {
  -- The ON CONFLICT clause is in-op
  INSERT INTO t1(a) VALUES(4),(5),(6);
} {1 {CHECK constraint failed: a!=5}}
do_execsql_test conflict-16.4 {
  SELECT a FROM t1 ORDER BY a;
} {}
do_execsql_test conflict-16.5 {
  INSERT OR IGNORE INTO t1(a) VALUES(4),(5),(6);
  SELECT a FROM t1 ORDER BY a;
} {4 6}

finish_test

Changes to test/conflict2.test.

807
808
809
810
811
812
813
814

815
816
817
818
819
820
821
807
808
809
810
811
812
813

814
815
816
817
818
819
820
821







-
+







    CREATE TABLE t13(a PRIMARY KEY CHECK(a!=2)) WITHOUT rowid;
    BEGIN;
    REPLACE INTO t13 VALUES(1);
  }
  catchsql {
    REPLACE INTO t13 VALUES(2);
  }
} {1 {CHECK constraint failed: t13}}
} {1 {CHECK constraint failed: a!=2}}
verify_ex_errcode conflict2-13.1b SQLITE_CONSTRAINT_CHECK
do_test conflict2-13.2 {
  execsql {
    REPLACE INTO t13 VALUES(3);
    COMMIT;
    SELECT * FROM t13;
  }

Changes to test/conflict3.test.

362
363
364
365
366
367
368



































































369
370
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


do_execsql_test 12.2 {
  REPLACE INTO t2 VALUES(NULL, '112'), (111, '111B');
}
do_execsql_test 12.3 {
  SELECT * FROM t2;
} {111 111B 112 112}

#-------------------------------------------------------------------------
ifcapable trigger {
  reset_db
  do_execsql_test 13.1.0 {
    PRAGMA recursive_triggers = true;
    CREATE TABLE t0 (c0 UNIQUE, c1 UNIQUE);
    CREATE TRIGGER tr0 AFTER DELETE ON t0 BEGIN 
      DELETE FROM t0; 
    END;

    INSERT INTO t0 VALUES(1, NULL);
    INSERT INTO t0 VALUES(0, NULL);
  }

  do_catchsql_test 13.1.1 {
    UPDATE OR REPLACE t0 SET c1 = 1;
  } {1 {constraint failed}}

  integrity_check 13.1.2

  do_execsql_test 13.1.3 {
    SELECT * FROM t0
  } {1 {} 0 {}}

  do_execsql_test 13.2.0 {
    CREATE TABLE t2 (a PRIMARY KEY, b UNIQUE, c UNIQUE) WITHOUT ROWID;
    CREATE TRIGGER tr3 AFTER DELETE ON t2 BEGIN 
      DELETE FROM t2; 
    END;

    INSERT INTO t2 VALUES(1, 1, 1);
    INSERT INTO t2 VALUES(2, 2, 2);
  }

  do_catchsql_test 13.2.1 {
    UPDATE OR REPLACE t2 SET c = 0;
  } {1 {constraint failed}}

  integrity_check 13.2.2

  do_execsql_test 13.2.3 {
    SELECT * FROM t2
  } {1 1 1 2 2 2}

  do_execsql_test 13.3.0 {
    CREATE TABLE t1(a, b);
    CREATE TABLE log(x);
    CREATE INDEX i1 ON t1(a);
    INSERT INTO t1 VALUES(1, 2);

    CREATE TRIGGER tb BEFORE UPDATE ON t1 BEGIN
      DELETE FROM t1;
    END;
    CREATE TRIGGER ta AFTER UPDATE ON t1 BEGIN
      INSERT INTO log VALUES('fired!');
    END;

    UPDATE t1 SET b=3;
  }

  do_execsql_test 13.3.1 {
    SELECT * FROM t1;
  } {}
  do_execsql_test 13.3.2 {
    SELECT * FROM log;
  } {}
}

finish_test

Changes to test/corrupt2.test.

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
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







+
+
-
+
-
-
-
-
+
+


















-
+
-
-
-
-
+
+







  set f [open corrupt.db RDWR]
  fconfigure $f -encoding binary
  seek $f 101 start
  puts -nonewline $f "\xFF\xFF"
  close $f

  sqlite3 db2 corrupt.db
  # Note: This test is no longer meaningful due to the deferred computation
  # of MemPage.nFree 
  catchsql "
  catchsql {PRAGMA quick_check} db2
    $::presql
    SELECT * FROM sqlite_master;
  " db2
} {1 {database disk image is malformed}}
} {0 {{*** in database main ***
Page 1: free space corruption}}}

do_test corrupt2-1.5 {
  db2 close

  # Corrupt the free-block list on page 1.
  forcedelete corrupt.db
  forcedelete corrupt.db-journal
  forcecopy test.db corrupt.db
  set f [open corrupt.db RDWR]
  fconfigure $f -encoding binary
  seek $f 101 start
  puts -nonewline $f "\x00\xC8"
  seek $f 200 start
  puts -nonewline $f "\x00\x00"
  puts -nonewline $f "\x10\x00"
  close $f

  sqlite3 db2 corrupt.db
  catchsql "
  catchsql {PRAGMA quick_check} db2
    $::presql
    SELECT * FROM sqlite_master;
  " db2
} {1 {database disk image is malformed}}
} {0 {{*** in database main ***
Page 1: free space corruption}}}
db2 close

# Corrupt a database by having 2 indices of the same name:
do_test corrupt2-2.1 {

  forcedelete corrupt.db
  forcedelete corrupt.db-journal

Changes to test/corrupt3.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_test corrupt3-1.9 {
  db close
  hexio_write test.db 2044 [hexio_render_int32 4]
  sqlite3 db test.db
  catchsql {
    SELECT substr(x,1,10) FROM t1
  }
} [list 0 0123456789]
} [list 1 {database disk image is malformed}]
do_test corrupt3-1.10 {
  catchsql {
    PRAGMA integrity_check
  }
} {0 {{*** in database main ***
On tree page 2 cell 0: invalid page number 4
Page 3 is never used}}}

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
148
149








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  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

if {![info exists ::G(perm:presql)]} {
  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/corruptA.test.

43
44
45
46
47
48
49
50

51
52
53
54
55
56
57
43
44
45
46
47
48
49

50
51
52
53
54
55
56
57







-
+







# Corrupt the file header in various ways and make sure the corruption
# is detected when opening the database file.
#
db close
forcecopy test.db test.db-template

set unreadable_version 02
ifcapable wal { set unreadable_version 03 }
ifcapable wal { set unreadable_version 04 }
do_test corruptA-2.1 {
  forcecopy test.db-template test.db
  hexio_write test.db 19 $unreadable_version   ;# the read format number
  sqlite3 db test.db
  catchsql {SELECT * FROM t1}  
} {1 {file is not a database}}
 

Changes to test/corruptC.test.

30
31
32
33
34
35
36

37
38
39
40
41
42
43
44
45
46
30
31
32
33
34
35
36
37
38
39

40
41
42
43
44
45
46







+


-







# These tests deal with corrupt database files
#
database_may_be_corrupt

# Construct a compact, dense database for testing.
#
do_test corruptC-1.1 {
  sqlite3_db_config db LEGACY_FILE_FORMAT 1
  execsql {
    PRAGMA auto_vacuum = 0;
    PRAGMA legacy_file_format=1;
    BEGIN;
    CREATE TABLE t1(x,y);
    INSERT INTO t1 VALUES(1,1);
    INSERT OR IGNORE INTO t1 SELECT x*2,y FROM t1;
    INSERT OR IGNORE INTO t1 SELECT x*3,y FROM t1;
    INSERT OR IGNORE INTO t1 SELECT x*5,y FROM t1;
    INSERT OR IGNORE INTO t1 SELECT x*7,y FROM t1;
93
94
95
96
97
98
99
100


101
102
103
104
105
106
107
93
94
95
96
97
98
99

100
101
102
103
104
105
106
107
108







-
+
+







  forcecopy test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 2053 [format %02x 0x04]

  sqlite3 db test.db
  catchsql {PRAGMA integrity_check}
} {1 {database disk image is malformed}}
} {0 {{*** in database main ***
Page 3: free space corruption}}}

# test that a corrupt content offset size is handled (seed 5649)
#
# Update 2016-12-27:  As of check-in [0b86fbca66] "In sqlite3BtreeInsert() when
# replacing a re-existing row, try to overwrite the cell directly rather than
# deallocate and reallocate the cell" on 2016-12-09, this test case no longer
# detects the offset size problem during the UPDATE.  We have to run a subsequent

Changes to test/corruptD.test.

107
108
109
110
111
112
113
114
115



116
117
118
119
120
121
122
107
108
109
110
111
112
113


114
115
116
117
118
119
120
121
122
123







-
-
+
+
+







#-------------------------------------------------------------------------
# The following tests, corruptD-1.1.*, focus on the page header field
# containing the offset of the first free block in a page. 
#
do_test corruptD-1.1.1 {
  incr_change_counter
  hexio_write test.db [expr 1024+1] FFFF
  catchsql { SELECT * FROM t1 ORDER BY rowid }
} {1 {database disk image is malformed}}
  catchsql { PRAGMA quick_check }
} {0 {{*** in database main ***
Page 2: free space corruption}}}
do_test corruptD-1.1.2 {
  incr_change_counter
  hexio_write test.db [expr 1024+1] [hexio_render_int32 1021]
  catchsql { SELECT * FROM t1 ORDER BY rowid }
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------

Changes to test/corruptE.test.

32
33
34
35
36
37
38

39
40
41
42
43
44
45
46
47
48
32
33
34
35
36
37
38
39
40
41

42
43
44
45
46
47
48







+


-







  finish_test
  return
}

# Construct a compact, dense database for testing.
#
do_test corruptE-1.1 {
  sqlite3_db_config db LEGACY_FILE_FORMAT 1
  execsql {
    PRAGMA auto_vacuum = 0;
    PRAGMA legacy_file_format=1;
    BEGIN;
    CREATE TABLE t1(x,y);
    INSERT INTO t1 VALUES(1,1);
    INSERT OR IGNORE INTO t1 SELECT x*2,y FROM t1;
    INSERT OR IGNORE INTO t1 SELECT x*3,y FROM t1;
    INSERT OR IGNORE INTO t1 SELECT x*5,y FROM t1;
    INSERT OR IGNORE INTO t1 SELECT x*7,y FROM t1;

Changes to test/corruptK.test.

64
65
66
67
68
69
70





71
72
73

74
75
76
77
78
79
80
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86







+
+
+
+
+



+







  seek $fd 30
  puts -nonewline $fd "\x18"
  close $fd
} {}
do_execsql_test 1.3 {
  INSERT INTO t1 VALUES(randomblob(20));
}

# This test no longer functions due to the deferred computation of
# MemPage.nFree.
#
if 0 {
do_catchsql_test 1.4 {
  INSERT INTO t1 VALUES(randomblob(90));
} {1 {database disk image is malformed}}
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.1 {
  PRAGMA page_size=1024;
  PRAGMA auto_vacuum=0;
  CREATE TABLE t1(x);

Added test/corruptL.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
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019-01-11
#
# 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
set testprefix corruptL

database_may_be_corrupt

#-------------------------------------------------------------------------
reset_db
do_test 1.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 356352 pagesize 4096 filename crash-acaae0347204ae.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 d0 00 00 00   .....@  ........
|     32: 40 00 ea 00 00 00 00 00 00 40 00 00 00 40 00 00   @........@...@..
|     96: 00 00 00 00 0d 00 00 00 04 0e 9c 00 0f ad 0f 4f   ...............O
|    112: 0e fc 0e 9c 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   3728: 00 00 00 00 00 00 00 00 00 00 00 00 5e 04 07 17   ............^...
|   3744: 1f 1f 01 81 0b 74 61 62 6c 65 74 31 5f 70 61 72   .....tablet1_par
|   3760: 65 6e 74 74 31 5f 70 61 72 65 6e 74 04 43 52 45   entt1_parent.CRE
|   3776: 41 54 45 20 54 41 42 4c 45 20 22 74 31 5f 70 61   ATE TABLE .t1_pa
|   3792: 72 65 6e 74 22 28 6e 6f 64 65 6e 6f 20 49 4e 54   rent.(nodeno INT
|   3808: 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59   EGER PRIMARY KEY
|   3824: 2c 70 61 72 65 6e 74 6e 6f 64 65 29 51 03 06 17   ,parentnode)Q...
|   3840: 1b 1b 01 7b 74 61 62 6c 65 74 31 5f 6e 6f 64 65   ....tablet1_node
|   3856: 74 31 5f 6e 6f 64 65 03 43 52 45 41 54 45 20 54   t1_node.CREATE T
|   3872: 41 42 4c 45 20 22 74 31 5f 6e 6f 64 65 22 28 6e   ABLE .t1_node.(n
|   3888: 6f 64 65 6e 6f 20 49 4e 54 45 47 45 52 20 50 52   odeno INTEGER PR
|   3904: 49 4d 41 52 59 20 4b 45 59 2c 64 61 74 61 29 5c   IMARY KEY,data).
|   3920: 02 07 17 1d 1d 01 81 0b 74 61 62 6c 65 74 31 5f   ........tablet1_
|   3936: 72 6f 77 69 64 74 31 5f 72 6f 77 69 64 02 43 52   rowidt1_rowid.CR
|   3952: 45 41 54 45 20 54 41 42 4c 45 20 22 74 31 5f 72   EATE TABLE .t1_r
|   3968: 6f 77 69 64 22 28 72 6f 77 69 64 20 49 4e 54 45   owid.(rowid INTE
|   3984: 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c   GER PRIMARY KEY,
|   4000: 6e 6f 64 65 6e 6f 2c 61 30 2c 61 31 29 51 01 07   nodeno,a0,a1)Q..
|   4016: 17 11 11 08 81 0f 74 61 62 6c 65 74 31 74 31 43   ......tablet1t1C
|   4032: 52 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41   REATE VIRTUAL TA
|   4048: 42 4c 45 20 74 31 20 55 53 49 4e 47 20 72 74 72   BLE t1 USING rtr
|   4064: 65 65 28 69 64 2c 78 30 20 50 52 49 4d 41 52 59   ee(id,x0 PRIMARY
|   4080: 20 4b 45 59 2c 70 61 72 65 6e 74 6e 6f 64 65 29    KEY,parentnode)
| page 2 offset 4096
|      0: 51 03 06 17 1b 1b 01 7b 74 61 62 6c 65 74 31 5f   Q.......tablet1_
|     16: 6e 6f 64 65 74 31 5f 6e 6f 64 65 03 43 52 45 41   nodet1_node.CREA
|     32: 54 45 20 54 41 42 4c 45 20 22 74 31 5f 6e 6f 64   TE TABLE .t1_nod
|     48: 65 22 28 6e 6f 64 65 6e 6f 20 49 4e 54 45 47 45   e.(nodeno INTEGE
|     64: 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 64 61   R PRIMARY KEY,da
|     80: 74 61 29 5c 02 07 17 1d 1d 01 81 0b 74 61 62 6c   ta).........tabl
|     96: 65 74 31 5f 72 6f 77 69 64 74 31 5f 72 6f 77 69   et1_rowidt1_rowi
|    112: 64 02 43 52 45 41 54 45 20 54 41 42 4c 45 00 00   d.CREATE TABLE..
|    128: 01 0a 02 00 00 00 01 0e 0d 00 00 00 00 24 0e 0d   .............$..
|    144: 0c 1a 06 85 50 46 60 27 70 08 00 00 00 00 00 00   ....PF`'p.......
|   3824: 00 00 00 00 00 00 00 0d 0e 05 00 09 1d 00 74 6f   ..............to
|   3840: 79 20 68 61 6c 66 10 0d 05 00 09 23 00 62 6f 74   y half.....#.bot
|   3856: 74 6f 6d 20 68 61 6c 66 0f 0c 05 00 09 21 00 72   tom half.....!.r
|   3872: 69 67 68 74 20 68 61 6c 66 0e 0b 05 00 09 1f 00   ight half.......
|   3888: 6c 65 66 74 20 43 15 f6 e6 f6 46 50 34 35 24 54   left C....FP45$T
|   3904: 15 44 52 05 44 14 24 c4 52 02 27 43 15 f6 e6 f6   .DR.D.$.R.'C....
|   3920: 46 52 22 8e 6f 64 65 6e 6f 20 49 4e 54 45 47 45   FR..odeno INTEGE
|   3936: 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 64 61   R PRIMARY KEY,da
|   3952: 74 61 29 5c 02 07 17 1d 1d 01 81 0b 74 61 62 6c   ta).........tabl
|   3968: 65 74 31 5f 72 6f 74 74 6f 6d 20 65 64 67 65 0f   et1_rottom edge.
|   3984: 07 05 00 09 21 00 72 69 67 68 74 20 65 64 67 65   ....!.right edge
|   4000: 0e 06 05 00 09 1f 00 6c 65 66 74 20 65 64 67 65   .......left edge
|   4016: 0b 05 05 00 09 19 00 63 65 6e 74 65 72 17 04 05   .......center...
|   4032: 00 09 31 00 75 70 70 65 72 2d 72 69 67 68 74 20   ..1.upper-right 
|   4048: 63 6f 72 6e 65 72 17 03 05 00 09 31 00 6c 6f 77   corner.....1.low
|   4064: 65 72 2d 72 69 67 68 74 20 63 6f 72 6e 65 72 16   er-right corner.
|   4080: 02 05 00 09 2f 00 75 70 70 65 72 2d 6c 65 66 74   ..../.upper-left
| page 3 offset 8192
|      0: 20 63 6f 72 6e 65 72 16 01 05 00 09 2f 01 8c 6f    corner...../..o
|     16: 77 65 72 2d 6c 53 51 4c 69 74 65 20 66 6f 72 6d   wer-lSQLite form
|     32: 61 74 20 33 00 10 00 01 01 00 40 20 20 00 00 00   at 3......@  ...
|     48: 00 00 00 00 2f 00 00 0d eb 13 00 00 00 03 00 00   ..../...........
|     64: 00 04 00 00 00 00 00 00 00 06 00 00 00 01 00 00   ................
|     80: 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00   ................
| page 6 offset 20480
|    128: 00 00 00 00 00 00 00 00 97 3d 04 ae 7c 01 00 00   .........=..|...
|    624: 00 00 00 00 00 00 21 97 3d 04 ae 7c 01 00 00 00   ......!.=..|....
|   1120: 00 00 00 00 00 20 97 3d 04 ae 7c 01 00 00 00 00   ..... .=..|.....
|   1616: 00 00 00 00 1f 97 3d 04 ae 7c 01 00 00 00 00 00   ......=..|......
|   2112: 00 00 00 1e 97 3d 04 ae 7c 01 00 00 00 00 00 00   .....=..|.......
|   2608: 00 00 1d 97 d3 d0 4a e7 c0 00 00 00 00 00 00 00   ......J.........
|   3088: 00 00 00 00 00 00 00 00 00 00 00 00 01 f3 00 00   ................
|   3600: 23 97 3d 04 ae 7c 01 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 26   ...............&
| page 8 offset 28672
|      0: 0d 00 00 00 01 04 30 00 04 30 00 00 00 00 00 00   ......0..0......
|   1072: 97 4d 1e 14 00 ae 7c 00 00 00 00 00 00 00 00 00   .M....|.........
|   1088: 00 00 00 00 00 00 01 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 03   ................
| page 10 offset 36864
|      0: 0d 00 00 00 01 04 30 00 04 30 00 00 00 00 00 00   ......0..0......
|   1072: 9a ee c1 80 fd 78 1f ce 1b ae eb b4 00 00 00 00   .....x..........
|   1088: 13 20 ff 20 00 70 00 00 00 60 50 00 00 00 11 e0   . . .p...`P.....
|   1104: 00 00 00 70 00 00 00 60 50 05 35 14 c6 97 46 52   ...p...`P.5...FR
|   1120: 06 66 f7 26 d6 17 42 03 30 01 00 00 10 10 04 02   .f.&..B.0.......
|   1136: 02 00 00 00 00 00 00 00 00 40 00 00 00 00 00 00   .........@......
|   1152: 00 00 00 00 00 40 00 00 00 40 00 00 00 00 00 00   .....@...@......
|   4080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05   ................
| page 12 offset 45056
|      0: 0d 00 00 00 01 04 30 00 04 30 e1 b4 30 97 4d 46   ......0..0..0.MF
|     16: 14 00 ae 7c 00 00 00 00 00 00 00 03 00 00 43 00   ...|..........C.
| page 47 offset 188416
|   2512: 00 00 00 00 00 00 00 00 be 00 00 00 00 00 00 00   ................
| page 87 offset 352256
|   2512: 00 00 00 00 00 00 00 00 aa 00 00 00 00 00 00 00   ................
| end crash-acaae0347204ae.db
}]} {}

do_catchsql_test 1.1 {
  PRAGMA cell_size_check = off;
  DROP INDEX t1x1;
} {1 {database disk image is malformed}}

do_catchsql_test 1.2 {
  SELECT sum(s+length(b)) FROM t1 WHERE a IN (110,10,150) AND q IS NULL;
} {1 {database disk image is malformed}}

do_catchsql_test 1.3 {
  REINDEX t1;
} {1 {database disk image is malformed}}

do_catchsql_test 1.4 {
  PRAGMA integrity_check
} {1 {database disk image is malformed}}


#-------------------------------------------------------------------------
reset_db
do_test 2.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 20480 pagesize 4096 filename crash.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 05   .....@  ........
|     32: 00 00 00 00 00 00 00 00 00 00 00 05 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 00 00 00 05 0e 55 00 0f 74 0f 3c   ..........U..t.<
|    112: 0e f9 0e d1 0e 55 00 00 00 00 00 00 00 00 00 00   .....U..........
|   3664: 00 00 00 00 00 7a 05 07 15 11 11 08 81 63 76 69   .....z.......cvi
|   3680: 65 77 76 31 76 31 43 52 45 41 54 45 20 56 49 45   ewv1v1CREATE VIE
|   3696: 57 20 76 31 28 78 2c 79 29 20 41 53 0a 53 45 4c   W v1(x,y) AS.SEL
|   3712: 45 43 54 20 74 31 2e 62 2c 74 32 2e 62 20 46 52   ECT t1.b,t2.b FR
|   3728: 4f 4d 20 74 31 2c 74 32 20 57 48 45 52 45 20 74   OM t1,t2 WHERE t
|   3744: 31 2e 61 3d 74 32 2e 61 20 47 52 4f 55 50 20 42   1.a=t2.a GROUP B
|   3760: 59 20 31 20 48 41 56 49 4e 47 20 74 32 2e 63 20   Y 1 HAVING t2.c 
|   3776: 4e 4f 54 20 4e 55 4c 4c 0a 4c 49 4d 49 54 20 31   NOT NULL.LIMIT 1
|   3792: 30 26 04 06 17 11 11 01 39 74 61 62 6c 65 74 32   0&......9tablet2
|   3808: 74 32 05 43 52 45 41 54 45 20 54 41 42 4c 45 20   t2.CREATE TABLE 
|   3824: 74 32 28 61 2c 62 2c 63 29 41 03 06 17 15 11 01   t2(a,b,c)A......
|   3840: 6b 69 6e 64 65 78 74 31 78 31 74 31 04 43 52 45   kindext1x1t1.CRE
|   3856: 41 54 45 20 49 4e 44 45 58 20 73 31 78 31 20 4f   ATE INDEX s1x1 O
|   3872: 4e 20 74 31 28 64 29 20 57 48 45 52 45 20 65 65   N t1(d) WHERE ee
|   3888: 20 49 53 20 4e 4f 54 20 4e 55 4c 4c 36 02 06 17    IS NOT NULL6...
|   3904: 17 11 01 53 69 6e 64 65 78 74 31 61 62 63 74 31   ...Sindext1abct1
|   3920: 03 43 52 45 41 54 45 20 49 4e 44 45 58 20 74 31   .CREATE INDEX t1
|   3936: 61 62 63 20 4f 4e 20 74 31 28 61 2c 62 2c 63 2b   abc ON t1(a,b,c+
|   3952: 64 2b 65 29 81 09 01 07 17 11 11 01 81 7d 74 61   d+e)..........ta
|   3968: 62 6c 65 74 31 74 31 02 43 52 45 41 54 45 20 54   blet1t1.CREATE T
|   3984: 41 42 4c 45 20 74 31 28 61 2c 62 2c 63 2c 64 2c   ABLE t1(a,b,c,d,
|   4000: 65 2c 66 2c 67 2c 68 2c 6a 2c 6a 6a 2c 6a 6a 6a   e,f,g,h,j,jj,jjj
|   4016: 2c 6b 2c 61 61 2c 62 62 2c 63 63 2c 64 64 2c 65   ,k,aa,bb,cc,dd,e
|   4032: 65 20 44 45 46 41 55 4c 54 20 33 2e 31 34 2c 0a   e DEFAULT 3.14,.
|   4048: 66 66 20 44 45 46 41 55 4c 54 28 27 68 69 63 63   ff DEFAULT('hicc
|   4064: 75 70 27 29 2c 67 67 20 4e 4f 54 20 4e 55 4c 4c   up'),gg NOT NULL
|   4080: 20 44 45 46 41 55 4c 54 28 66 61 6c 73 65 29 29    DEFAULT(false))
| page 2 offset 4096
|      0: 0d 00 00 00 0a 0e 7b 00 0f dc 0f b6 0f 8f 0f 68   ...............h
|     16: 0f 41 0f 1a 0e f3 0e cb 0e a3 0e 7b 00 00 00 00   .A..............
|   3696: 00 00 00 00 00 00 00 00 00 00 00 26 0a 14 01 01   ...........&....
|   3712: 02 08 00 00 00 00 00 00 00 00 00 00 00 00 07 19   ................
|   3728: 08 09 5a 00 b4 40 09 1e b8 51 eb 85 1f 68 69 63   ..Z..@...Q...hic
|   3744: 63 75 70 26 09 14 01 01 02 08 00 00 00 00 00 00   cup&............
|   3760: 00 00 00 00 00 00 07 19 08 08 50 00 a0 40 09 1e   ..........P..@..
|   3776: b8 51 eb 85 1f 68 69 63 63 75 70 26 08 14 01 01   .Q...hiccup&....
|   3792: 02 08 00 00 00 00 00 00 00 00 00 00 00 00 07 19   ................
|   3808: 08 07 46 00 8c 40 09 1e b8 51 eb 85 1f 68 69 63   ..F..@...Q...hic
|   3824: 63 75 70 25 07 14 01 01 01 08 00 00 00 00 00 00   cup%............
|   3840: 00 00 00 00 00 00 07 b9 08 06 3c 78 40 09 1e b8   ..........<x@...
|   3856: 51 eb 85 1f 68 69 63 63 75 70 25 06 14 01 00 01   Q...hiccup%.....
|   3872: 08 00 00 00 00 00 00 00 00 00 00 00 00 07 19 08   ................
|   3888: 05 32 64 40 09 1e b8 51 eb 85 1f 68 69 63 63 75   .2d@...Q...hiccu
|   3904: 70 25 05 14 01 01 01 08 00 00 00 00 00 00 00 00   p%..............
|   3920: 00 00 00 00 07 19 08 04 28 50 40 09 1e b8 51 eb   ........(P@...Q.
|   3936: 85 1f 68 69 63 63 75 70 25 04 14 01 01 01 08 00   ..hiccup%.......
|   3952: 00 00 00 00 00 00 00 00 00 00 00 07 19 08 03 1e   ................
|   3968: 3c 40 09 1e b8 51 eb 85 1f 68 69 63 63 75 70 25   <@...Q...hiccup%
|   3984: 03 14 01 01 01 08 00 00 00 00 00 00 00 00 00 00   ................
|   4000: 00 00 07 19 08 02 14 28 40 09 1e b8 51 eb 85 1f   .......(@...Q...
|   4016: 68 69 63 63 75 70 24 02 14 09 01 01 08 00 00 00   hiccup$.........
|   4032: 00 00 00 00 00 00 00 00 00 07 19 08 0a 14 40 09   ..............@.
|   4048: 1e b8 51 eb 85 1f 68 69 63 63 75 70 22 01 14 08   ..Q...hiccup....
|   4064: 08 08 07 ff ff ff ff ff ff 00 00 00 00 00 00 07   ................
|   4080: 19 08 40 09 1e b8 51 eb 85 1f 68 69 63 63 75 70   ..@...Q...hiccup
| page 3 offset 8192
|      0: 0a 00 00 00 0a 0f aa 00 0f fa 0f f2 0f e9 0f e0   ................
|     16: 0f d7 0f ce 0f c5 0f bc 0e b3 0f aa 00 00 00 00   ................
|   4000: 00 00 00 00 00 00 00 00 00 00 08 05 01 01 00 01   ................
|   4016: 09 5a 0a 08 05 01 01 00 01 08 50 09 08 05 01 01   .Z........P.....
|   4032: 00 01 07 46 08 08 05 01 01 00 01 06 3c 07 08 05   ...F........<...
|   4048: 01 01 00 01 05 32 06 08 05 01 01 00 01 04 28 05   .....2........(.
|   4064: 08 05 01 01 00 01 03 1e 04 08 05 01 01 00 01 02   ................
|   4080: 14 03 07 05 09 01 00 01 0a 02 05 05 08 08 00 09   ................
| page 4 offset 12288
|      0: 0a 00 00 00 0a 0f cf 00 0f fc 0f f7 0f f2 0f ed   ................
|     16: 0f e8 0f e3 0f de 0f d9 0f d4 0f cf 00 00 00 00   ................
|   4032: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04   ................
|   4048: 03 08 01 0a 04 03 08 01 09 04 03 08 01 08 04 03   ................
|   4064: 08 01 07 04 03 08 01 06 04 03 08 01 05 04 03 08   ................
|   4080: 01 04 04 03 08 01 13 04 03 08 01 02 03 03 08 09   ................
| page 5 offset 16384
|      0: 0d 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00   ................
| end crash.txt.db
}]} {}

do_execsql_test 2.1 {
  PRAGMA writable_schema=ON; -- bypass improved sqlite_master consistency checking
  INSERT INTO t1(b) VALUES(X'a0fee3669f9fddefc5cba913e4225d4b6ce2b04f26b87fad3ee6f9b7d90a1ea62a169bf41e5d32707a6ca5c3d05e4bde05c9d89eaaa8c50e74333d2e9fcd7dfe95528a3a016aac1102d825c5cd70cf99d8a88e0ea7f798d4334386518b7ad359beb168b93aba059a2a3bd93112d65b44c12b9904ea786b204d80531cdf0504bf9b203dbe927061974caf7b9f30cbc3397b61f802e732012a6663d41c3607d6f1c0dbcfd489adac05ca500c0b04439d894cd93a840159225ef73b627e178b9f84b3ffe66cf22a963a8368813ff7961fc47f573211ccec95e0220dcbb3bf429f4a50ba54d7a53784ac51bfef346e6ac8ae0d0e7c3175946e62ba2b');
}

do_catchsql_test 2.2 {
  SELECT b,c FROM t1 ORDER BY a;
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 3.0 {
  CREATE TABLE t1(a, b, c, d INTEGER PRIMARY KEY);
  CREATE TABLE t2(a, b, c, d INTEGER PRIMARY KEY);

  INSERT INTO t1(a, b, c, d) VALUES (1, 2, 3, 100), (4, 5, 6, 101);
  INSERT INTO t2(a, b, c, d) VALUES (1, 100, 3, 1000), (4, 101, 6, 1001);

  CREATE INDEX t1a ON t1(a);
  CREATE INDEX t2a ON t2(a, b, c);

  PRAGMA writable_schema = 1;
  UPDATE sqlite_master SET sql = 'CREATE INDEX t2a ON t2(a)' WHERE name='t2a';
}

db close
sqlite3 db test.db

do_catchsql_test 3.1 {
  INSERT INTO t1 SELECT * FROM t2;
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
reset_db
do_test 4.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 4096 pagesize 512 filename crash-6b48ba69806134.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: 02 00 01 01 00 40 20 20 00 ff ff ff ff 00 00 07   .....@  ........
|     32: 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 04   ................
|     48: 00 00 00 00 00 00 00 05 00 eb 00 01 00 00 00 00   ................
|     80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0c   ................
|     96: 00 2e 2c 50 0d 00 00 00 06 01 06 00 01 da 01 b0   ..,P............
|    112: 05 56 01 86 01 2a 01 06 00 00 00 00 00 00 00 00   .V...*..........
|    128: 00 ff 00 00 ff ff ff e1 00 00 00 00 00 00 00 00   ................
|    144: 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00   ................
|    160: 00 00 00 00 00 00 00 00 f2 00 00 00 00 00 00 00   ................
|    176: 00 00 f9 ff ff ff ff ff ff ff 00 00 00 00 00 fb   ................
|    208: 00 00 00 00 00 00 00 00 1e 00 00 00 fe 00 00 00   ................
|    224: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ca 00   ................
|    256: 00 00 00 00 ef ff 22 07 06 17 11 11 01 31 74 61   .............1ta
|    272: 62 6c 65 74 38 38 74 04 43 52 45 41 54 45 20 54   blet88t.CREATE T
|    288: 41 42 4c 45 20 74 34 28 87 29 2a 06 06 17 13 11   ABLE t4(.)*.....
|    304: 01 3f 69 4f 64 65 78 74 33 78 74 33 05 43 52 45   .?iOdext3xt3.CRE
|    320: 41 54 45 20 49 6e 44 45 58 20 74 33 78 20 4f 4e   ATE InDEX t3x ON
|    336: 20 74 33 28 78 29 2e 04 06 17 15 11 01 45 69 6e    t3(x).......Ein
|    352: 64 65 2e 74 32 63 64 74 3d 05 43 52 45 41 54 45   de.t2cdt=.CREATE
|    368: 20 49 4e 44 45 58 20 74 32 63 64 20 4f 4e 20 74    INDEX t2cd ON t
|    384: 32 28 0a 0c 44 29 28 05 06 17 11 11 01 3d 74 61   2(..D)(......=ta
|    400: 62 6c 65 d4 33 74 33 04 43 52 45 41 54 45 20 54   ble.3t3.CREATE T
|    416: 41 42 4c 45 20 74 33 28 63 2c 78 2c 65 2c 66 29   ABLE t3(c,x,e,f)
|    432: 28 02 06 17 11 11 01 3d 74 61 62 6c 65 74 32 74   (......=tablet2t
|    448: 32 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 74   2.CREATE TABLE t
|    464: 32 28 63 2c 64 2c 65 2c 66 29 24 01 06 17 11 11   2(c,d,e,f)$.....
|    480: 01 35 74 60 62 6c 65 74 31 74 31 02 43 52 45 41   .5t`blet1t1.CREA
|    496: 54 45 20 54 41 42 4c 45 20 74 30 28 61 2c 62 29   TE TABLE t0(a,b)
| page 2 offset 512
|      0: 0d 00 ff 11 04 01 cf 00 01 fa 01 f3 01 de 01 cf   ................
|     32: 00 00 08 00 00 00 00 00 00 00 00 00 00 00 00 13   ................
|     48: 00 00 00 00 00 00 00 00 00 00 00 01 00 20 00 00   ............. ..
|     64: 00 00 00 00 00 00 f8 ff ff ff 00 00 00 00 00 00   ................
|    160: 01 64 00 00 00 00 00 80 ff ff ff 00 00 00 00 00   .d..............
|    176: 00 00 00 00 00 00 00 00 1f 00 00 00 00 00 00 03   ................
|    192: 00 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00   ..@.............
|    288: 00 00 00 00 00 00 ff ff ff e9 00 00 00 00 00 00   ................
|    336: 01 00 00 ff ff 00 00 00 00 00 00 00 00 00 00 00   ................
|    368: 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ...............
|    384: 00 de ff 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|    464: 00 00 00 00 00 13 76 65 6e 65 69 67 68 74 13 03   ......veneight..
|    480: 03 40 07 07 14 00 54 45 20 49 4e 44 45 58 20 74   .@....TE INDEX t
|    496: 32 63 64 20 4f 4e 20 74 32 28 0a 0c 44 09 01 02   2cd ON t2(..D...
| page 3 offset 1024
|      0: 0d 00 00 00 48 01 54 00 01 f7 01 ec 01 c5 01 aa   ....H.T.........
|     16: 30 34 28 87 29 2a 06 06 17 13 11 01 3f 69 4f 64   04(.)*......?iOd
|     32: 65 79 74 33 78 74 33 6d 6d 6d 6d 6d 6d 7d 6d 6d   eyt3xt3mmmmmm.mm
|     48: 6d 41 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d   mAmmmmmmmmmmmmmm
|     64: 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 66 6d 6d 6d 6d   mmmmmmmmmmmfmmmm
|     80: 6d 4e 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d   mNmmmmmmmmmmmmmm
|     96: 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d   mmmmmmmmmmmmmmmm
|    112: 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d 6d   mmmmmmmmmmmmmmmm
|    128: 6d 6d 6d 6d 6d 00 00 00 00 00 00 00 00 00 00 00   mmmmm...........
|    160: 80 00 00 00 00 00 00 03 00 00 00 ff e4 00 00 00   ................
|    208: 00 00 00 00 00 00 00 00 00 00 00 00 00 c5 00 00   ................
|    240: 14 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00   ................
|    256: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0f ec   ................
|    304: 00 00 00 00 19 08 05 17 17 17 17 65 69 67 68 74   ...........eight
|    320: 65 69 67 68 74 73 65 00 00 00 00 00 00 00 00 00   eightse.........
|    336: 00 00 00 00 19 08 05 17 17 17 17 65 69 67 68 74   ...........eight
|    352: 65 69 67 68 74 73 65 01 65 6e 00 00 00 10 25 07   eightse.en....%.
|    368: 07 6e 25 07 07 07 40 18 00 00 00 00 00 00 40 18   .n%...@.......@.
|    384: 00 00 00 00 00 00 40 14 00 00 00 00 00 00 40 14   ......@.......@.
|    400: 00 00 00 00 00 00 09 06 05 01 01 01 01 04 04 03   ................
|    416: 03 07 05 05 01 01 09 09 02 02 19 04 05 17 17 17   ................
|    432: 17 10 65 76 65 6e 65 69 67 68 74 65 69 67 68 74   ..eveneighteight
|    448: 73 65 76 65 6e 25 03 05 07 07 07 07 40 14 00 00   seven%......@...
|    464: 00 00 00 00 40 18 00 00 00 00 00 00 40 18 00 00   ....@.......@...
|    480: 00 00 00 00 40 14 00 00 00 00 e8 f6 09 02 00 00   ....@...........
|    496: 00 00 00 00 00 00 00 00 00 00 64 00 00 00 00 02   ..........d.....
| page 4 offset 1536
|      0: 0d 00 00 00 00 02 00 00 00 00 00 00 00 00 00 fa   ................
|     16: 1f a1 07 00 00 00 00 00 01 00 00 00 00 00 00 00   ................
|     32: 00 00 00 00 00 00 00 00 00 00 00 00 00 73 69 6d   .............sim
|     48: 70 6c 65 00 00 00 00 00 00 00 00 00 00 00 00 00   ple.............
|     80: 00 00 00 00 00 10 00 00 00 00 00 00 01 00 00 00   ................
|     96: 00 00 00 00 00 00 00 00 00 00 00 00 00 fe ff ff   ................
|    112: ff 00 00 00 00 00 00 00 00 00 00 00 4a 00 00 00   ............J...
|    144: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00   ................
|    176: e5 ff ff ff 00 00 00 00 00 00 00 00 00 00 00 00   ................
|    208: 00 00 00 00 00 00 00 00 00 00 36 36 00 00 00 00   ..........66....
|    240: 00 00 00 6c 00 00 00 00 00 00 00 00 00 00 00 00   ...l............
|    256: 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|    320: 00 00 00 00 00 00 00 00 01 00 00 02 00 80 00 00   ................
|    336: 00 00 00 00 00 19 08 05 17 17 17 17 65 69 67 68   ............eigh
|    352: 74 65 69 67 68 74 73 65 76 65 6e 73 65 76 65 6e   teightsevenseven
|    368: 25 07 05 07 07 07 07 40 18 00 00 00 00 00 00 40   %......@.......@
|    384: 18 00 20 00 00 00 40 00 14 00 00 00 00 00 00 40   .. ...@........@
|    400: 14 00 00 00 00 00 1c 09 06 05 01 01 01 01 04 04   ................
|    416: 03 03 07 05 05 01 01 00 00 00 00 00 00 00 00 00   ................
|    448: 74 73 65 76 65 6e 00 80 ff ff 00 00 00 00 00 aa   tseven..........
|    464: 00 9e 00 00 00 00 00 00 00 00 00 00 00 70 6f 72   .............por
|    480: 74 65 72 00 00 00 00 00 00 00 00 00 00 00 00 00   ter.............
|    496: 00 00 00 00 00 00 29 00 00 00 00 00 00 00 00 00   ......).........
| page 5 offset 2048
|      0: 0a 00 00 00 08 01 96 00 01 fa 01 c5 01 f2 01 bc   ................
|     16: 01 dc 01 a6 01 96 01 cc 00 00 00 00 00 00 00 00   ................
|    112: 00 00 00 09 00 00 00 00 01 00 00 00 00 00 00 00   ................
|    160: 74 72 69 67 62 ff ff ff ff fc 00 00 00 00 00 00   trigb...........
|    240: 00 00 00 00 00 00 00 00 00 00 ff 00 00 00 00 00   ................
|    256: e5 ff ff ff 00 00 54 00 00 00 00 00 00 00 00 00   ......T.........
|    304: 00 00 00 00 00 00 09 00 00 00 00 00 00 00 00 00   ................
|    400: 00 00 00 00 00 09 00 00 00 00 01 00 00 00 00 00   ................
|    448: 00 00 74 72 69 67 62 ff ff ff ff fc 00 00 07 05   ..trigb.........
|    464: 05 01 01 09 09 02 02 19 04 05 17 17 17 17 10 65   ...............e
|    480: 76 65 6e 65 69 67 68 74 65 40 18 00 00 00 00 01   veneighte@......
|    496: 02 03 07 04 01 01 01 03 04 02 05 04 09 01 ff fd   ................
| end crash-6b48ba69806134.db
}]} {}

set res {1 {database disk image is malformed}}
ifcapable oversize_cell_check {
  set res {1 {no such table: t3}}
}
do_catchsql_test 4.1 {
  PRAGMA writable_schema=ON; -- bypass improved sqlite_master consistency checking
  INSERT INTO t3 SELECT * FROM t2;
} $res

#-------------------------------------------------------------------------
reset_db
do_test 5.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 192512 pagesize 4096 filename crash-9ae5502296c949.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 2f   .....@  ......./
|     32: 00 00 00 1b 00 00 00 13 00 00 00 03 00 00 00 04   ................
|     48: 00 00 00 00 00 00 00 06 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   ................
|     96: 00 00 00 00 0d 00 00 00 04 0e e2 00 0f 96 0f 44   ...............D
|    112: 0f 10 0e e2 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   3808: 00 00 2c 04 06 17 15 11 01 41 69 6e 64 65 78 74   ..,......Aindext
|   3824: 31 78 32 74 31 06 43 52 45 41 54 45 20 49 4e 44   1x2t1.CREATE IND
|   3840: 45 58 20 74 31 78 32 20 4f 4e 20 74 31 28 62 29   EX t1x2 ON t1(b)
|   3856: 32 03 06 17 15 11 01 4d 69 6e 64 65 78 74 31 78   2......Mindext1x
|   3872: 31 74 31 05 43 52 45 41 54 45 20 49 4e 44 45 58   1t1.CREATE INDEX
|   3888: 20 74 31 78 31 20 4f 4e 20 74 31 28 67 2b 68 2c    t1x1 ON t1(g+h,
|   3904: 6a 2c 6b 29 50 02 06 17 2b 2b 01 59 74 61 62 6c   j,k)P...++.Ytabl
|   3920: 65 73 71 6c 69 74 65 5f 73 65 71 75 65 6e 63 65   esqlite_sequence
|   3936: 73 71 6c 69 74 65 5f 73 65 71 75 65 6e 63 65 04   sqlite_sequence.
|   3952: 43 52 45 41 54 45 20 54 41 42 4c 45 20 73 71 6c   CREATE TABLE sql
|   3968: 69 74 65 5f 73 65 71 75 65 6e 63 65 28 6e 61 6d   ite_sequence(nam
|   3984: 65 2c 73 65 71 29 68 01 07 17 11 11 01 81 3b 74   e,seq)h.......;t
|   4000: 61 62 6c 65 74 31 74 31 03 43 52 45 41 54 45 20   ablet1t1.CREATE 
|   4016: 54 41 42 4c 45 20 74 31 28 61 20 49 4e 54 45 47   TABLE t1(a INTEG
|   4032: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 20 41   ER PRIMARY KEY A
|   4048: 55 54 4f 49 4e 43 52 45 4d 45 4e 54 2c 0a 62 2c   UTOINCREMENT,.b,
|   4064: 63 2c 64 2c 65 2c 66 2c 67 2c 68 2c 6a 2c 6b 2c   c,d,e,f,g,h,j,k,
|   4080: 6c 2c 6d 2c 6e 2c 6f 2c 70 2c 71 2c 72 2c 73 29   l,m,n,o,p,q,r,s)
| page 2 offset 4096
|      0: 01 00 00 00 00 01 00 00 00 00 01 00 00 00 00 01   ................
|     16: 00 00 00 00 02 10 00 00 00 05 00 00 00 03 02 00   ................
|     32: 00 00 00 05 00 00 00 03 02 00 00 00 00 05 00 00   ................
|     48: 00 03 02 00 00 00 00 05 00 00 00 03 02 00 00 00   ................
|     64: 00 05 00 00 00 03 02 00 00 00 00 05 00 00 00 03   ................
|     80: 02 00 00 00 00 05 00 00 00 03 02 00 00 00 00 05   ................
|     96: 00 00 00 03 02 00 00 00 00 05 00 00 00 03 05 00   ................
|    112: 00 00 03 03 00 00 00 23 02 00 00 00 00 03 00 00   .......#........
|    128: 00 23 02 00 00 00 00 03 00 00 00 23 02 00 00 00   .#.........#....
|    144: 00 03 00 00 00 23 02 00 00 00 00 03 00 00 00 23   .....#.........#
|    160: 05 00 00 00 06 05 00 00 00 06 02 00 00 00 00 03   ................
|    176: 00 00 00 06 02 00 00 00 00 03 00 00 00 24 02 00   .............$..
|    192: 00 00 00 03 00 00 00 24 02 00 00 00 00 03 00 00   .......$........
|    208: 00 24 02 00 00 00 00 02 00 00 00 00 03 00 00 00   .$..............
|    224: 24 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   $...............
| page 3 offset 8192
|      0: 05 00 00 00 09 0f d0 00 00 00 00 19 0f fb 0f f6   ................
|     16: 0f f1 0f ec 0f e7 0f e2 0f dc 0f d6 0f d0 0f a0   ................
|     32: 0f a0 0f a0 0f a0 0f a0 0f a0 0f a0 0f a0 0f a0   ................
|   1072: 00 97 4c 0a 14 00 ae 7c 00 00 00 00 00 00 00 00   ..L....|........
|   1088: 00 00 00 00 00 00 00 09 00 00 00 00 00 00 00 00   ................
|   4000: 0f ac 00 06 00 00 00 00 00 30 00 00 00 00 00 00   .........0......
|   4048: 00 00 00 16 81 2a 00 00 00 14 81 16 00 00 00 12   .....*..........
|   4064: 81 02 00 00 00 10 6e 00 00 00 0e 5a 00 00 00 0c   ......n....Z....
|   4080: 46 00 00 00 0a 32 00 00 00 08 1e 00 00 00 18 0a   F....2..........
| page 4 offset 12288
|      0: 0d 00 00 00 01 0f f7 00 0f f7 00 00 00 00 00 00   ................
|   4080: 00 00 00 00 00 00 00 07 01 03 11 02 74 31 00 be   ............t1..
| page 5 offset 16384
|      0: 0a 0f 7c 00 0a 0f 74 00 0f f9 0f eb 0f dd 0f cf   ..|...t.........
|     16: 0f c1 0f b3 0f a4 0f 94 0f 84 0f 74 0f 74 0f 74   ...........t.t.t
|     32: 0f 74 0f 74 0f 74 0f 74 0f 74 0f 74 0f 74 00 00   .t.t.t.t.t.t.t..
|   3952: 00 00 00 00 07 05 00 00 00 02 00 be 0f 8c 00 08   ................
|   3968: 00 00 00 00 07 05 00 00 00 02 00 aa 0f 9c 00 08   ................
|   3984: 00 00 00 00 07 05 00 00 00 02 00 96 0f ac 00 08   ................
|   4000: 00 00 00 00 07 05 00 00 00 02 00 82 0f ba 00 07   ................
|   4016: 00 00 00 06 05 00 00 00 01 6e 0f c8 00 07 00 00   .........n......
|   4032: 00 06 05 00 00 00 01 5a 0f d6 00 07 00 00 00 06   .......Z........
|   4048: 05 00 00 00 01 46 0f e4 00 07 00 00 00 06 05 00   .....F..........
|   4064: 00 00 01 32 0f f2 00 07 00 00 00 06 05 00 00 00   ...2............
|   4080: 01 1e 00 00 00 07 00 00 00 06 05 00 00 00 01 0a   ................
| page 6 offset 20480
|      0: 02 00 00 00 01 0e 0d 00 00 00 00 24 0e 0d 0c 1a   ...........$....
|     16: 06 55 04 66 02 77 00 88 00 00 00 00 00 00 00 00   .U.f.w..........
|    128: 00 00 00 00 00 00 00 00 97 3d 04 ae 7c 01 00 00   .........=..|...
|    624: 00 00 00 00 00 00 21 97 3d 04 ae 7c 01 00 00 00   ......!.=..|....
|   1120: 00 00 00 00 00 20 97 3d 04 ae 7c 01 00 00 00 00   ..... .=..|.....
|   1616: 00 00 00 00 1f 97 3d 04 ae 7c 01 00 00 00 00 00   ......=..|......
|   2112: 00 00 00 1e 97 3d 04 ae 7c 01 00 00 00 00 00 00   .....=..|.......
|   2608: 00 00 1d 97 3d 04 ae 7c 01 00 00 00 00 00 00 00   ....=..|........
|   3088: 00 00 00 00 00 00 00 00 00 00 00 00 01 f3 00 00   ................
|   3600: 23 97 3d 04 ae 7c 01 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 26   ...............&
| page 8 offset 28672
|      0: 0d 00 00 00 01 04 30 00 04 30 00 00 00 00 00 00   ......0..0......
|   1072: 97 4d 1e 14 00 ae 7c 00 00 00 00 00 00 00 00 00   .M....|.........
|   1088: 00 00 00 00 00 00 01 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 03   ................
| page 10 offset 36864
|    256: 0d 00 00 00 01 04 30 00 04 30 00 00 00 00 00 00   ......0..0......
|   1072: 97 4d 32 14 00 ae 7c 00 00 00 00 00 00 00 00 00   .M2...|.........
|   1088: 00 00 00 00 00 00 01 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 12 offset 45056
|      0: 0d 00 00 00 01 04 30 00 04 30 00 00 00 00 00 00   ......0..0......
|   1072: 97 4d 46 14 00 ae 7c 00 00 00 00 00 00 00 00 00   .MF...|.........
|   1088: 00 00 00 00 00 00 01 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 07   ................
| page 14 offset 53248
|      0: 0d 00 00 00 01 04 30 00 04 30 00 00 00 00 00 00   ......0..0......
|   1072: 97 4d 5a 14 00 ae 7c 00 00 00 00 00 00 00 00 00   .MZ...|.........
|   1088: 00 00 00 00 00 00 01 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 09   ................
| page 16 offset 61440
|      0: 0d 00 00 00 01 04 30 00 04 30 00 00 00 00 00 00   ......0..0......
|   1072: 97 4d 6e 14 00 ae 7c 00 00 00 00 00 00 00 00 00   .Mn...|.........
|   1088: 00 00 00 00 00 00 01 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 0b   ................
| page 18 offset 69632
|      0: 0d 00 00 00 01 04 2f 00 04 2f 00 00 00 00 00 00   ....../../......
|   1056: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 97   ................
|   1072: 4d 81 02 14 00 ae 7c 00 00 00 00 00 00 00 00 00   M.....|.........
|   1088: 00 00 00 00 00 00 01 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 0d   ................
| page 20 offset 77824
|      0: 0d 00 00 00 01 04 2f 00 04 2f 00 00 00 00 00 00   ....../../......
|   1056: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 97   ................
|   1072: 4d 81 16 14 00 ae 7c 00 00 00 00 00 00 00 00 00   M.....|.........
|   1088: 00 00 00 00 00 00 01 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 0f   ................
| page 22 offset 86016
|      0: 0d 00 00 00 01 04 2f 00 04 2f 00 00 00 00 00 00   ....../../......
|   1056: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 97   ................
|   1072: 4d 81 2a 14 00 ae 7c 00 00 00 00 00 00 00 00 00   M.*...|.........
|   1088: 00 00 00 00 00 00 01 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 11   ................
| page 24 offset 94208
|      0: 0d 00 00 00 01 04 31 00 04 31 00 00 00 00 00 00   ......1..1......
|   1072: 00 97 4c 0a 14 00 ae 7c 00 00 00 00 00 00 00 00   ..L....|........
|   1088: 00 00 00 00 00 00 00 09 00 00 00 00 00 00 00 00   ................
| page 25 offset 98304
|      0: 0d 00 00 00 01 04 2f 00 04 2f 00 00 00 00 00 00   ....../../......
|   1056: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 97   ................
|   1072: 4d 81 3e 14 00 ae 7c 00 00 00 00 00 00 00 00 00   M.>...|.........
|   1088: 00 00 00 00 00 00 01 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 13   ................
| page 26 offset 102400
|   2512: 00 00 00 00 00 00 00 0a 00 00 00 00 00 00 00 00   ................
| page 27 offset 106496
|      0: 00 00 00 00 00 00 00 12 00 00 00 07 00 00 00 1d   ................
|     16: 00 00 00 09 00 00 00 1f 00 00 00 0b 00 00 00 21   ...............!
|     32: 00 00 00 0d 00 00 00 25 00 00 00 0f 00 00 00 19   .......%........
|     48: 00 00 00 11 00 00 00 29 00 00 00 13 00 00 00 2b   .......).......+
|     64: 00 00 00 15 00 00 00 2d 00 00 00 2e 00 00 00 17   .......-........
| page 28 offset 110592
|   2512: 00 00 00 00 00 00 00 1e 00 00 00 00 00 00 00 00   ................
| page 30 offset 118784
|   2512: 00 00 00 00 00 00 00 32 00 00 00 00 00 00 00 00   .......2........
| page 32 offset 126976
|   2512: 00 00 00 00 00 00 00 46 00 00 00 00 00 00 00 00   .......F........
| page 34 offset 135168
|   2512: 00 00 00 00 00 00 00 5a 00 00 00 00 00 00 00 00   .......Z........
| page 35 offset 139264
|      0: 0a 08 44 00 05 02 77 00 0e 11 0a 33 06 55 02 77   ..D...w....3.U.w
|     16: 04 66 00 88 00 88 00 88 00 00 00 00 00 00 00 00   .f..............
|    128: 00 00 00 00 00 00 00 00 04 66 01 ef 00 00 00 00   .........f......
|    624: 00 00 00 00 00 00 00 97 3d 04 ae 7c 01 00 00 00   ........=..|....
|   1120: 00 00 00 00 00 20 97 3d 04 ae 7c 01 00 00 00 00   ..... .=..|.....
|   1616: 00 00 00 00 22 97 3d 04 ae 7c 01 00 00 00 00 00   ......=..|......
|   2112: 00 00 00 1e 0c 22 01 ef 00 00 00 00 00 00 00 00   ................
|   2608: 00 00 00 97 3d 04 ae 7c 01 00 00 00 00 00 00 00   ....=..|........
|   3104: 00 1c 00 00 01 ef 00 00 00 00 00 00 00 00 00 00   ................
|   3600: 00 97 3d 04 ae 7c 01 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 1a   ................
| page 36 offset 143360
|      0: 0a 08 44 00 04 02 77 00 06 55 02 77 04 66 0e 11   ..D...w..U.w.f..
|     16: 00 88 00 88 00 88 0e 11 00 00 00 00 00 00 00 00   ................
|    128: 00 00 00 00 00 00 00 00 04 76 01 ef 00 00 00 00   .........v......
|    624: 00 00 00 00 00 00 00 97 3e 04 ae 7c 02 00 00 00   ........>..|....
|   1120: 00 00 00 00 00 2a 97 3e 04 ae 7c 02 00 00 00 00   .....*.>..|.....
|   1616: 00 00 00 00 2c 97 3e 04 ae 7c 02 00 00 00 00 00   ....,.>..|......
|   2112: 00 00 00 28 00 00 05 cd 00 00 00 00 00 00 00 00   ...(............
|   3600: 00 97 3e 04 ae 7c 02 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 2f   .............../
| page 38 offset 151552
|   2512: 00 00 00 00 00 00 00 6e 00 00 00 00 00 00 00 00   .......n........
| page 40 offset 159744
|   2512: 00 00 00 00 00 00 00 00 82 00 00 00 00 00 00 00   ................
| page 42 offset 167936
|   2512: 00 00 00 00 00 00 00 00 96 00 00 00 00 00 00 00   ................
| page 44 offset 176128
|   2512: 00 00 00 00 00 00 00 00 aa 00 00 00 00 00 00 00   ................
| page 47 offset 188416
|   2512: 00 00 00 00 00 00 00 00 be 00 00 00 00 00 00 00   ................
| end crash-9ae5502296c949.db
}]} {}

do_catchsql_test 5.1 {
  INSERT INTO t1(b) VALUES(zeroblob(40000));
} {1 {database disk image is malformed}}

do_catchsql_test 5.2 {
  DROP INDEX t1x2;
} {0 {}}

do_catchsql_test 5.3 {
  INSERT INTO t1(b) VALUES(zeroblob(40000));
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
reset_db
do_test 6.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 20480 pagesize 4096 filename crash-d260f001fa015c.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 ff ff f0 00 00 00 02 00 00 00 04   ................
|     48: 00 00 00 00 00 00 00 64 00 00 00 01 00 00 00 00   .......d........
|     96: 00 00 00 00 0d 0f f8 00 04 0e ce 00 0f 4c 0f d3   .............L..
|    112: 0e fa 0e ce 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   3776: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2a 04   ..............*.
|   3792: 06 17 13 11 01 3f 69 6e 64 65 78 74 31 62 74 31   .....?indext1bt1
|   3808: 05 43 52 45 41 54 45 20 49 4e 44 45 58 20 74 31   .CREATE INDEX t1
|   3824: 62 20 4f 4e 20 74 31 28 62 29 50 03 06 17 2b 2b   b ON t1(b)P...++
|   3840: 01 59 74 61 62 6c 65 73 71 6c 69 74 65 5f 73 65   .Ytablesqlite_se
|   3856: 71 75 65 6e 63 65 73 71 6c 69 74 65 5f 73 65 71   quencesqlite_seq
|   3872: 75 65 6e 63 65 04 43 52 45 41 54 45 20 54 41 42   uence.CREATE TAB
|   3888: 4c 45 20 73 71 6c 69 74 65 5f 73 65 71 75 65 6e   LE sqlite_sequen
|   3904: 63 65 28 6e 61 6d 65 2c 73 65 71 29 81 04 01 07   ce(name,seq)....
|   3920: 17 11 11 01 81 73 74 61 62 6c 65 74 31 74 31 02   .....stablet1t1.
|   3936: 43 52 45 41 54 45 20 54 41 42 4c 45 20 74 31 28   CREATE TABLE t1(
|   3952: 61 20 52 45 41 4c 20 4e 4f 54 20 4e 55 4c 4c 20   a REAL NOT NULL 
|   3968: 44 45 46 41 55 4c 54 28 32 35 2b 33 32 29 2c 62   DEFAULT(25+32),b
|   3984: 20 46 4c 4f 41 54 2c 63 20 44 4f 55 42 4c 45 20    FLOAT,c DOUBLE 
|   4000: 55 4e 49 51 55 45 2c 0a 64 20 43 4c 4f 42 2c 65   UNIQUE,.d CLOB,e
|   4016: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59    INTEGER PRIMARY
|   4032: 20 4b 45 59 20 41 55 54 4f 49 4e 43 52 45 4d 45    KEY AUTOINCREME
|   4048: 4e 54 29 23 02 06 17 37 11 01 00 69 6e 64 65 78   NT)#...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 05 00 00 00 08 00 00 00 00   _t1_1t1.........
| page 2 offset 4096
|      0: 0d 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00   ................
| page 3 offset 8192
|      0: 0a 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00   ................
| 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: 0a 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00   ................
| end crash-d260f001fa015c.db
}]} {}

do_catchsql_test 6.1 {
  BEGIN;
    INSERT INTO t1(b) VALUES(1);
    INSERT INTO t1(b) VALUES(2);
  COMMIT;
} {1 {malformed database schema (t1b) - invalid rootpage}}

#-------------------------------------------------------------------------
reset_db
do_test 7.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 20480 pagesize 4096 filename crash-8391315d75edff.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 00 05 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 00 00 00 05 0e 55 00 0f 74 0f 3c   ..........U..t.<
|    112: 0e f9 0e d1 0e 55 00 00 00 00 00 00 00 00 00 00   .....U..........
|   3664: 00 00 00 00 00 7a 05 07 15 11 11 08 81 63 76 69   .....z.......cvi
|   3680: 65 77 76 31 76 31 43 52 45 41 54 45 20 56 49 45   ewv1v1CREATE VIE
|   3696: 57 20 76 31 28 78 2c 69 29 20 41 53 0a 53 45 4c   W v1(x,i) AS.SEL
|   3712: 45 43 54 20 74 31 2e 62 2c 74 32 2e 62 20 46 52   ECT t1.b,t2.b FR
|   3728: 4f 4d 20 74 31 2c 74 32 20 57 48 45 52 45 20 74   OM t1,t2 WHERE t
|   3744: 31 2e 61 3d 74 32 2e 61 20 47 52 4f 55 50 20 42   1.a=t2.a GROUP B
|   3760: 59 20 31 20 48 41 56 49 4e 47 20 74 32 2e 63 20   Y 1 HAVING t2.c 
|   3776: 4e 4f 54 20 4e 55 4c 4c 0a 4c 49 4d 49 54 20 31   NOT NULL.LIMIT 1
|   3792: 30 26 04 06 17 11 11 01 39 74 61 62 6c 65 74 32   0&......9tablet2
|   3808: 74 32 05 43 52 45 41 54 45 20 54 41 42 4c 45 20   t2.CREATE TABLE 
|   3824: 74 32 28 61 2c 62 2c 63 29 41 03 06 17 15 11 01   t2(a,b,c)A......
|   3840: 6b 69 6e 64 65 78 74 31 78 31 74 31 03 43 52 45   kindext1x1t1.CRE
|   3856: 41 54 45 20 49 4e 44 45 58 20 74 31 78 31 20 4f   ATE INDEX t1x1 O
|   3872: 4e 20 74 31 28 64 29 20 57 48 45 52 45 20 65 65   N t1(d) WHERE ee
|   3888: 20 49 53 20 4e 4f 54 20 4e 55 4c 4c 36 02 06 17    IS NOT NULL6...
|   3904: 17 11 01 53 69 6e 64 65 78 74 31 61 62 63 74 31   ...Sindext1abct1
|   3920: 03 43 52 45 41 54 45 20 49 4e 44 45 58 20 74 31   .CREATE INDEX t1
|   3936: 61 62 63 20 4f 4e 20 74 31 28 61 2c 62 2c 63 2b   abc ON t1(a,b,c+
|   3952: 64 2b 65 29 81 09 01 07 17 11 11 01 81 7d 74 61   d+e)..........ta
|   3968: 62 6c 65 74 31 74 31 02 43 52 45 41 54 45 20 54   blet1t1.CREATE T
|   3984: 41 42 4c 45 20 74 31 28 61 2c 62 2c 63 2c 64 2c   ABLE t1(a,b,c,d,
|   4000: 65 2c 66 2c 67 2c 68 2c 6a 2c 6a 6a 2c 6a 6a 6a   e,f,g,h,j,jj,jjj
|   4016: 2c 6b 2c 61 61 2c 62 69 8c 63 63 2c 64 64 2c 65   ,k,aa,bi.cc,dd,e
|   4032: 65 20 44 45 46 41 55 4c 54 20 33 2e 31 34 2c 0a   e DEFAULT 3.14,.
|   4048: 66 66 20 44 45 46 41 55 4c 54 28 27 68 69 63 63   ff DEFAULT('hicc
|   4064: 75 70 27 29 2c 67 67 20 4e 4f 54 20 4e 55 4c 4c   up'),gg NOT NULL
|   4080: 20 44 45 46 41 55 4c 54 28 66 61 6c 73 65 29 29    DEFAULT(false))
| page 2 offset 4096
|      0: 0d 00 00 00 0a 0e 7b 00 0f dc 0f b6 0f 8f 0f 68   ...............h
|     16: 0f 41 0f 1a 0e f3 0e cb 0e a3 0e 22 00 00 00 00   .A..............
|   3696: 00 00 00 00 00 00 00 00 00 00 00 26 0a 14 01 01   ...........&....
|   3712: 02 08 00 00 00 00 00 00 00 00 00 00 00 00 07 19   ................
|   3728: 08 09 5a 00 b4 40 09 1e b8 51 eb 95 1f 68 69 63   ..Z..@...Q...hic
|   3744: 63 75 70 26 09 14 01 01 02 08 00 00 00 00 00 00   cup&............
|   3760: 00 00 00 00 00 00 07 19 08 08 50 00 a0 40 09 1e   ..........P..@..
|   3776: b8 51 eb 85 1f 68 69 63 63 74 70 26 08 14 01 01   .Q...hicctp&....
|   3792: 03 08 00 00 00 00 00 00 00 00 00 00 00 00 07 19   ................
|   3808: 08 07 46 00 8c 40 09 1e b8 51 eb 85 1f 68 69 63   ..F..@...Q...hic
|   3824: 63 75 70 25 07 14 01 01 01 08 00 00 00 00 00 00   cup%............
|   3840: 00 00 00 00 00 10 07 19 08 06 3c 78 40 09 1e b8   ..........<x@...
|   3856: 51 eb 85 1f 68 69 63 63 75 70 25 06 14 01 01 01   Q...hiccup%.....
|   3872: 08 00 00 00 00 00 00 00 00 00 00 00 00 07 19 08   ................
|   3888: 05 32 64 40 09 1e b8 51 eb 85 1f 68 69 63 63 75   .2d@...Q...hiccu
|   3904: 70 25 05 14 01 01 01 08 00 00 00 00 00 00 00 00   p%..............
|   3920: 00 00 00 00 07 19 08 04 28 50 40 09 1e b8 51 eb   ........(P@...Q.
|   3936: 85 1f 68 69 63 63 75 70 25 04 14 01 00 f1 08 00   ..hiccup%.......
|   3952: 00 00 00 00 00 00 00 00 00 00 00 07 19 08 03 1e   ................
|   3968: 3c 40 09 1e b8 51 eb 85 1f 68 69 63 63 75 70 25   <@...Q...hiccup%
|   3984: 03 14 01 01 01 08 00 00 00 00 00 00 00 00 00 00   ................
|   4000: 00 00 07 19 08 02 14 28 40 09 1e b8 51 eb 85 1f   .......(@...Q...
|   4016: 68 69 63 63 75 70 24 02 14 09 01 01 08 00 00 00   hiccup$.........
|   4032: 00 00 00 00 00 00 00 00 00 07 19 08 0a 14 40 09   ..............@.
|   4048: 1e b8 51 eb 85 1f 68 69 63 63 75 70 22 01 14 08   ..Q...hiccup....
|   4064: 08 08 08 00 00 00 00 00 00 00 00 00 00 00 00 07   ................
|   4080: 19 08 40 09 1e b8 51 eb 85 1f 68 69 63 63 75 70   ..@...Q...hiccup
| page 3 offset 8192
|      0: 0a 00 00 00 0a 0f aa 00 0f fa 0f f2 0f e9 0f e0   ................
|     16: 0f d7 0f ce 0f c5 0f bc 0f b3 0f aa 00 00 00 00   ................
|   4000: 00 00 00 00 00 00 00 00 00 00 08 05 01 01 00 01   ................
|   4016: 09 5a 0a d8 05 01 01 00 01 08 50 09 08 05 01 01   .Z........P.....
|   4032: 00 01 07 46 08 08 05 01 01 00 01 06 3c 07 08 05   ...F........<...
|   4048: 01 01 00 01 05 32 06 08 05 01 01 00 01 04 28 05   .....2........(.
|   4064: 08 05 01 02 60 01 03 1e 04 08 05 01 01 00 01 02   ....`...........
|   4080: 14 03 07 05 09 01 00 01 0a 02 05 05 08 08 00 09   ................
| page 4 offset 12288
|      0: 0a 00 00 00 0a 0f cf 00 0f fc 0f f7 0f f2 0f ed   ................
|     16: 0f e8 0f e3 0f de 0f d9 0f d4 0f cf 00 00 00 00   ................
|   4032: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04   ................
|   4048: 03 08 01 0a 04 03 08 01 09 04 03 08 01 08 04 03   ................
|   4064: 08 01 07 04 03 08 01 06 04 03 08 01 05 04 03 08   ................
|   4080: 01 04 04 03 08 01 03 04 03 08 01 02 03 03 08 09   ................
| page 5 offset 16384
|      0: 0d 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00   ................
| end crash-8391315d75edff.db
}]} {}

do_catchsql_test 7.1 {
  SELECT * FROM sqlite_master;
} {1 {malformed database schema (t1x1) - invalid rootpage}}

#-------------------------------------------------------------------------
reset_db
do_test 8.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 2048 pagesize 512 filename a.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: 02 00 01 01 00 40 20 20 ff ff 00 0c 00 00 00 07   .....@  ........
|     32: 0b 00 00 00 00 00 00 00 00 00 00 08 9c 00 00 04   ................
|     48: 00 00 00 e0 09 00 00 01 00 00 00 01 00 00 00 00   ................
|     64: 00 00 00 00 f2 ff 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 0c   ................
|     96: 00 2e 2c 50 0d 00 00 00 06 01 06 00 01 da 01 b0   ..,P............
|    112: 05 56 01 86 01 2a 01 06 00 00 00 00 00 06 00 00   .V...*..........
|    128: 00 ff 00 00 ff ff ff e1 00 00 00 00 00 00 00 00   ................
|    144: 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00   ................
|    160: 00 00 00 00 00 00 00 00 f2 00 00 00 00 00 00 00   ................
|    176: 00 00 f9 ff ff ff ff ff ff ff 00 00 00 5f 00 fb   ............._..
|    192: 00 00 00 00 00 00 00 00 00 e1 ff 00 00 00 00 00   ................
|    208: 00 00 10 00 00 00 00 00 1e 00 00 00 fe 00 00 00   ................
|    224: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ca 00   ................
|    240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 35   ...............5
|    256: 00 00 00 00 ef ff 22 07 06 17 11 11 01 30 39 38   .............098
|    272: 62 6c 65 74 38 38 74 04 43 52 45 41 54 45 20 54   blet88t.CREATE T
|    288: 41 42 4c 45 20 74 34 28 87 29 2a 06 06 17 13 11   ABLE t4(.)*.....
|    304: 01 3f 69 4f 64 65 78 74 33 78 74 40 05 43 52 45   .?iOdext3xt@.CRE
|    320: 41 54 45 20 49 6e 44 45 58 20 74 33 78 20 4f 4e   ATE InDEX t3x ON
|    336: 20 74 33 28 78 29 2e 04 06 17 15 11 01 45 69 6e    t3(x).......Ein
|    352: 00 04 00 00 34 63 64 74 3d 05 43 52 45 41 54 45   ....4cdt=.CREATE
|    368: 20 49 4e 44 45 58 20 63 74 64 32 20 4f 4e 20 74    INDEX ctd2 ON t
|    384: 32 28 0a 0c 44 29 28 05 06 17 11 11 01 3d 74 6c   2(..D)(......=tl
|    400: 62 61 d4 65 33 74 33 04 43 52 45 41 54 45 20 54   ba.e3t3.CREATE T
|    416: 41 42 4c 45 20 74 33 28 63 2c 78 2c 65 2c 66 29   ABLE t3(c,x,e,f)
|    432: 28 02 06 17 11 11 01 3d 74 61 62 6c 65 74 32 74   (......=tablet2t
|    448: 32 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 74   2.CREATE TABLE t
|    464: 32 28 63 2c 64 2c 65 2c 66 29 24 01 06 17 11 11   2(c,d,e,f)$.....
|    480: 01 35 74 60 62 6c 65 74 31 74 31 02 43 52 45 41   .5t`blet1t1.CREA
|    496: 54 45 20 54 41 42 4c 45 20 74 30 28 61 2c 62 29   TE TABLE t0(a,b)
| page 2 offset 512
|      0: 0d 00 ff 11 04 01 cf 80 01 fa 01 09 00 de 01 cf   ................
|     16: 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00   ................
|     32: 00 00 08 00 00 00 00 00 00 11 00 00 00 00 00 13   ................
|     48: 00 00 00 00 00 00 00 00 00 00 00 01 00 e0 ff ff   ................
|     64: ff d2 ff ff ff 00 f8 ff ff ff 00 00 00 00 00 00   ................
|     80: 00 ff ff 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|     96: 00 00 00 00 ff de 00 00 00 00 00 00 00 00 00 00   ................
|    112: 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00   .............@..
|    128: 2a 00 00 00 00 00 00 00 00 f7 00 00 00 00 00 00   *...............
|    144: 00 00 00 00 00 21 00 00 00 00 00 00 00 00 00 00   .....!..........
|    160: 01 64 00 00 00 00 04 80 ff ff ff 00 00 00 00 00   .d..............
|    176: 00 00 00 00 00 00 00 00 1f 00 00 00 00 00 00 00   ................
|    192: 00 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00   ..@.............
|    208: b5 00 00 00 00 00 00 40 00 00 00 00 00 00 00 00   .......@........
|    224: 00 00 00 f6 00 ee ff ff ff 00 00 00 00 00 00 00   ................
|    272: f2 00 00 00 00 00 00 00 00 00 f9 ff ff ff ff ff   ................
|    288: ff ff 00 00 00 5f 00 fb 00 00 00 00 00 00 00 00   ....._..........
|    320: 1e 00 00 00 fe 00 00 00 00 00 00 00 00 00 00 00   ................
|    336: 00 00 00 00 00 00 ca 00 00 00 00 00 00 00 ff ec   ................
|    352: 00 00 00 00 00 00 00 32 00 00 00 00 ef ff 22 07   .......2........
|    368: 06 17 11 11 01 30 74 61 62 6c 65 74 38 38 74 04   .....0tablet88t.
|    384: 43 52 45 41 54 45 20 54 41 42 4c 45 20 8c cb d7   CREATE TABLE ...
|    400: 78 d6 d5 f9 f9 17 13 11 01 3f 69 4f 64 65 78 74   x........?iOdext
|    416: 33 78 74 33 05 43 52 45 41 54 45 26 49 6e 44 45   3xt3.CREATE&InDE
|    432: 58 20 74 33 78 00 00 00 00 00 00 00 00 00 00 00   X t3x...........
|    464: 00 00 00 00 00 13 76 65 6e 65 69 67 68 74 13 03   ......veneight..
|    480: 03 40 07 07 15 00 54 45 20 49 4e 44 45 58 20 74   .@....TE INDEX t
|    496: 31 63 64 20 4f 4e 20 74 ce d7 f5 f0 44 09 01 02   1cd ON t....D...
| page 3 offset 1024
|      0: 0d 00 00 00 48 01 54 00 01 f6 e2 ec 01 c5 01 aa   ....H.T.........
|     16: 30 34 28 87 29 32 06 f5 16 13 11 01 8e 61 24 64   04(.)2.......a$d
|     32: 65 78 74 37 78 1f 33 6d 6d 6d 6d 6d 00 00 04 06   ext7x.3mmmmm....
|     48: 6d 41 6d 6d 6e 6d 6d 00 00 02 00 6d 6d 6d 6d 6d   mAmmnmm....mmmmm
|     64: 15 11 01 45 45 45 45 45 45 45 45 45 45 45 45 45   ...EEEEEEEEEEEEE
|     80: 45 45 45 45 45 45 45 45 45 45 45 00 45 63 74 64   EEEEEEEEEEE.Ectd
|     96: 34 20 4f 4e 20 61 62 6c 5d 74 38 38 74 04 43 52   4 ON abl]t88t.CR
|    112: 45 41 54 45 20 54 41 42 4c 45 20 74 34 28 87 29   EATE TABLE t4(.)
|    128: 2a 06 06 13 13 01 00 00 00 4f 64 6e 78 74 33 44   *........Odnxt3D
|    144: 74 13 05 43 52 45 41 54 45 20 49 6e 44 45 00 00   t..CREATE InDE..
|    160: 00 00 00 00 00 00 00 f9 ff ff ff ff ff ff ff 00   ................
|    176: 00 00 5f 00 fb 00 00 2d 00 00 00 00 00 00 00 00   .._....-........
|    192: 00 00 00 00 00 00 00 00 00 00 00 00 00 1e 00 00   ................
|    208: 00 fe 00 00 00 00 17 15 11 01 45 69 6e 64 65 2e   ..........Einde.
|    224: 5b 38 63 64 74 3d 05 43 52 45 41 54 45 20 49 4e   [8cdt=.CREATE IN
|    240: 44 45 58 20 63 20 64 32 20 4f 4e 20 74 32 28 0a   DEX c d2 ON t2(.
|    256: 0c 44 32 05 00 10 00 00 11 11 3d 74 6c 62 61 d4   .D2.......=tlba.
|    272: 65 33 74 33 04 43 52 45 41 54 45 20 54 41 42 4c   e3t3.CREATE TABL
|    288: 45 20 74 36 ff ff 7f ff 43 52 45 41 54 45 20 49   E t6....CREATE I
|    304: 73 71 6c 69 74 65 5f 73 65 71 75 65 6e 63 65 28   sqlite_sequence(
|    320: 0a 0c 44 29 28 05 06 17 11 11 01 3d 74 6c 62 61   ..D)(......=tlba
|    336: 20 00 00 00 33 04 43 52 45 41 54 45 20 54 41 42    ...3.CREATE TAB
|    352: 4c 45 20 74 33 28 63 2c 78 2c 65 2c 66 29 28 02   LE t3(c,x,e,f)(.
|    368: 06 00 00 7f ff 40 41 54 45 20 49 6e 44 45 58 20   .....@ATE InDEX 
|    384: 74 33 78 20 4f 4e 20 74 31 28 78 29 2e 04 06 17   t3x ON t1(x)....
|    400: 15 11 01 45 69 6e 64 65 2e 74 34 63 64 74 3d 05   ...Einde.t4cdt=.
|    416: 00 00 00 00 00 00 00 00 00 00 00 4d 00 00 00 00   ...........M....
|    432: 01 00 00 00 00 00 00 05 00 00 10 00 00 00 00 00   ................
|    448: 00 01 00 00 00 00 01 00 00 00 00 07 40 14 00 00   ............@...
|    464: 00 00 21 00 40 18 00 00 00 00 00 00 40 1c 00 00   ..!.@.......@...
|    480: 00 00 ff ff ff 00 00 00 5f 00 fb 00 00 2d 00 00   ........_....-..
|    496: 00 00 00 1e 00 00 00 fe 00 00 64 00 00 ff fb 02   ..........d.....
| page 4 offset 1536
|      0: 0d 00 39 00 00 02 00 00 00 00 00 00 00 00 00 00   ..9.............
| end a.db
}]} {}

set res {1 {database disk image is malformed}}
ifcapable oversize_cell_check {
  set res {1 {no such table: t3}}
}
do_catchsql_test 8.1 {
  PRAGMA writable_schema=ON; -- bypass improved sqlite_master consistency checking
  INSERT INTO t3 SELECT * FROM t2;
} $res

#-------------------------------------------------------------------------
reset_db
do_test 9.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 8192 pagesize 4096 filename crash-ab10597e4e1c32.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 01 0f d6 00 0f d6 00 00   ................
|   4048: 00 00 00 00 00 00 28 01 06 17 11 11 01 3d 74 61   ......(......=ta
|   4064: 62 6c 65 74 31 74 31 02 43 52 45 41 54 45 20 54   blet1t1.CREATE T
|   4080: 41 42 4c 45 20 74 31 28 61 2c 62 2c 63 2c 64 29   ABLE t1(a,b,c,d)
| page 2 offset 4096
|      0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
| end crash-ab10597e4e1c32.db
}]} {}

do_execsql_test 9.1 {
  SAVEPOINT one;
}
do_catchsql_test 9.3 {
  INSERT INTO t1(b,c) VALUES(5,6);
} {1 {database disk image is malformed}}
do_execsql_test 9.3 {
  ROLLBACK TO one;
}

#-------------------------------------------------------------------------
reset_db
do_test 10.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 180224 pagesize 4096 filename crash-41390d95d613b6.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 04 0e e2 00 0f 96 0f 44   ...............D
|    112: 0f 10 0e e2 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   3808: 00 00 2c 14 06 17 15 11 01 41 69 6e 64 65 78 74   ..,......Aindext
|   3824: 41 78 33 74 31 06 43 52 45 41 54 45 20 49 4e 44   Ax3t1.CREATE IND
|   3840: 45 58 20 74 31 78 32 20 4f 4e 20 74 31 28 62 29   EX t1x2 ON t1(b)
|   3856: 32 03 06 17 15 11 01 4d 69 6e 64 65 78 74 31 88   2......Mindext1.
|   3872: 31 74 31 05 43 52 45 41 54 45 20 49 4e 44 45 58   1t1.CREATE INDEX
|   3888: 20 74 31 78 31 20 4f 4e 20 74 31 28 67 2b 68 2c    t1x1 ON t1(g+h,
|   3904: 6a 2d 6b 29 50 02 06 17 2b 2b 01 59 74 61 62 6c   j-k)P...++.Ytabl
|   3920: 65 73 71 6c 69 74 65 5e 73 65 71 74 65 6e 63 65   esqlite^seqtence
|   3936: 73 71 6c 69 74 65 5f 73 65 71 75 65 6e 63 65 04   sqlite_sequence.
|   3952: 43 52 45 41 54 45 20 54 41 42 4c 45 20 73 71 6c   CREATE TABLE sql
|   3968: 69 74 65 5f 73 65 71 75 65 6e 63 65 28 6e 61 6d   ite_sequence(nam
|   3984: 65 2c 73 65 71 29 68 00 07 17 11 11 01 81 3b 74   e,seq)h.......;t
|   4000: 61 62 6c 65 74 31 74 31 03 43 52 45 41 54 45 20   ablet1t1.CREATE 
|   4016: 54 41 42 4c 45 20 74 31 28 61 20 49 4e 54 45 47   TABLE t1(a INTEG
|   4032: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 20 41   ER PRIMARY KEY A
|   4048: 55 54 4f 49 4e 43 52 45 4d 45 4e 54 2c 0a 62 2c   UTOINCREMENT,.b,
|   4064: 63 2c 64 2c 65 2c 66 2c 67 2c 68 2c 6a 2c 6b 2c   c,d,e,f,g,h,j,k,
|   4080: 6c 2c 6d 2c 6e 2c 6f 2c 70 2c 71 2c 72 2c 73 29   l,m,n,o,p,q,r,s)
| page 2 offset 4096
|      0: 01 00 00 00 00 01 00 00 10 00 01 00 00 00 00 01   ................
|     16: 00 00 00 00 02 00 0f f0 00 15 00 00 00 03 02 00   ................
|     32: 00 00 d9 05 00 00 00 03 02 00 00 00 00 05 00 00   ................
|     48: 10 03 02 00 00 00 00 05 00 00 00 03 02 00 00 00   ................
|     64: 00 05 00 00 00 02 62 00 00 00 00 05 00 00 00 03   ......b.........
|     80: 02 00 00 00 00 05 00 00 00 03 02 00 00 00 00 05   ................
|     96: 00 00 00 03 02 00 00 00 00 05 00 00 00 03 05 00   ................
|    112: 00 00 03 03 01 00 00 23 02 00 00 4f 00 02 00 00   .......#...O....
|    128: 10 25 02 00 00 00 00 03 00 00 00 23 02 00 00 00   .%.........#....
|    144: 00 03 00 00 00 23 02 00 00 00 00 03 00 00 00 23   .....#.........#
|    160: 05 00 08 90 06 05 00 00 00 06 01 ff 00 00 00 03   ................
|    176: 00 00 00 06 02 00 00 00 00 02 ff 00 00 00 00 00   ................
| page 3 offset 8192
|      0: 05 00 00 00 09 0f d0 00 00 00 00 19 0f fb 0f f6   ................
|     16: 0f f1 10 ec ec e7 0f e2 0f dc 0f d6 0f 00 00 00   ................
|   1072: 00 97 4c 0a 24 00 ae 00 00 00 00 00 00 00 00 00   ..L.$...........
|   4048: 00 00 00 16 83 39 ff ff ff 14 81 16 00 00 00 12   .....9..........
|   4064: 81 02 00 00 00 10 6e 00 00 00 0e 5a 00 00 00 0c   ......n....Z....
|   4080: 46 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   F...............
| page 4 offset 12288
|   1072: 97 4d 32 14 00 ae 00 00 00 00 00 00 00 00 00 00   .M2.............
|   4080: 00 00 00 00 00 00 00 07 01 03 11 02 74 31 00 bd   ............t1..
| page 5 offset 16384
|      0: fa 0f 7c 00 0a 0f 74 00 0f f9 0f eb 0f dd 0f cf   ..|...t.........
|     16: 0f c1 0f b3 0f a4 0e 94 0f 84 0f 74 0f 74 0f 74   ...........t.t.t
|     32: 0f 74 0f 64 0f 00 00 00 00 00 00 00 00 00 00 00   .t.d............
|   3952: 00 00 00 00 07 05 00 00 00 02 00 be 0f 8c 10 07   ................
|   3968: ff ff 00 00 07 05 00 00 00 02 00 aa 0f 9b f0 08   ................
|   3984: c8 00 00 00 37 06 00 00 00 01 00 96 0f ac 00 08   ....7...........
|   4000: 00 00 00 b3 07 15 00 10 00 02 00 82 0f ba 00 07   ................
|   4016: 00 00 00 06 05 00 00 00 01 6e 0f c8 00 07 00 00   .........n......
|   4032: 00 06 05 00 00 00 01 5a 03 f6 00 07 00 00 00 06   .......Z........
|   4048: 05 00 00 00 01 46 0f e4 00 07 00 00 10 06 05 00   .....F..........
|   4064: 00 00 01 32 10 02 00 07 00 00 00 07 05 00 00 00   ...2............
|   4080: 01 1d ff ff ff 07 10 00 00 06 05 00 00 00 01 0a   ................
| page 6 offset 20480
|    624: 00 00 00 00 00 21 97 00 00 00 00 00 00 00 00 00   .....!..........
|   1120: 00 00 00 00 00 24 57 3e 00 00 00 00 00 00 00 00   .....$W>........
|   1616: 00 00 00 00 1f 97 00 00 00 00 00 00 00 00 00 00   ................
|   2112: 00 00 00 1e 97 3d 00 00 00 00 00 00 00 00 00 00   .....=..........
|   2608: 00 1d 97 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
| page 8 offset 28672
|   1184: 00 00 00 00 00 00 00 00 00 97 4d 1e 13 ff ae 7c   ..........M....|
|   4080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90   ................
| page 9 offset 32768
|    256: 0d 01 c0 00 01 04 30 00 04 30 00 00 00 00 00 00   ......0..0......
| page 10 offset 36864
|      0: 0d 00 22 00 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 12 offset 45056
|      0: 0d 00 00 00 01 04 30 00 00 00 00 00 00 00 00 00   ......0.........
| page 14 offset 53248
|      0: 0d 00 00 00 01 04 30 00 04 30 00 00 00 00 00 00   ......0..0......
|   1072: 96 4d 5a 14 00 00 00 00 00 00 00 00 00 00 00 00   .MZ.............
| page 16 offset 61440
|      0: 0d 00 00 00 01 04 30 00 04 30 00 00 00 00 00 00   ......0..0......
|   1072: 97 4d 6e 14 00 ae 7b ff ff ff ff 00 00 00 00 00   .Mn.............
| page 18 offset 69632
|   1056: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 97   ................
|   1072: 4d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   M...............
|   4080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0d   ................
| page 20 offset 77824
|   1056: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 97   ................
|   1072: 4d 81 16 14 00 ae 00 00 00 00 00 00 00 00 00 00   M...............
|   4080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0f   ................
| page 22 offset 86016
|      0: 0d 00 00 00 01 04 2f 00 04 2f 01 00 00 00 00 00   ....../../......
|   1056: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 97   ................
|   1072: 4d 81 2a 14 00 00 00 00 00 00 00 00 00 00 00 00   M.*.............
| page 24 offset 94208
|   1072: 00 97 4c 0a 14 00 ae 7c 00 00 00 00 00 00 00 00   ..L....|........
| page 25 offset 98304
|   1056: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 97   ................
|   1072: 4d 81 3e 14 00 ae 7c 00 00 18 ff 00 00 00 00 00   M.>...|.........
| page 27 offset 106496
|      0: 00 00 00 00 00 00 00 12 00 00 00 07 00 00 00 1d   ................
|     16: 00 00 00 09 00 00 00 1f 00 00 00 0b 00 00 00 21   ...............!
|     32: 00 00 00 0d 00 10 00 25 00 00 00 0f 00 00 00 27   .......%.......'
|     48: 00 00 00 11 00 00 00 00 00 00 00 00 00 00 00 00   ................
| page 32 offset 126976
|   2512: 00 00 00 00 00 00 00 45 21 00 00 00 00 00 00 00   .......E!.......
| page 35 offset 139264
|      0: 00 0a 08 44 00 05 02 77 00 0e 11 0a 92 00 00 00   ...D...w........
|   1120: 00 00 00 00 00 20 97 00 00 00 00 00 00 00 00 00   ..... ..........
|   1616: 00 00 00 00 22 00 00 00 00 00 00 00 00 00 00 00   ................
|   2608: 00 00 00 97 3d 04 00 00 00 00 00 00 00 00 00 00   ....=...........
|   3104: 00 1c 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   3600: 00 97 3d 04 ae 7c 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 1a   ................
| page 36 offset 143360
|      0: 0a 08 44 00 04 02 00 00 00 00 00 00 00 00 00 00   ..D.............
|   1120: 00 00 00 00 00 2a 97 3e 04 00 00 00 00 00 00 00   .....*.>........
|   1616: 00 00 00 00 2c 97 3e 00 00 00 00 00 00 00 00 00   ....,.>.........
|   2112: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 38   ...............8
|   2128: 00 00 05 cd 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   3600: 00 97 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
| page 38 offset 151552
|   2464: 00 00 00 00 00 00 00 00 00 6e 00 00 00 00 00 00   .........n......
| page 40 offset 159744
|   2512: 00 00 00 00 00 00 00 00 82 00 00 00 00 00 00 00   ................
| page 42 offset 167936
|   2512: 00 00 00 00 00 00 00 96 00 00 00 00 00 00 00 00   ................
| page 44 offset 176128
|   2512: 00 00 00 00 00 00 00 00 aa 00 00 00 00 00 00 00   ................
| end crash-41390d95d613b6.db
}]} {}

do_catchsql_test 10.1 {
  PRAGMA writable_schema=ON; -- bypass improved sqlite_master consistency checking
  SELECT * FROM t1 WHERE a<='2019-05-09' ORDER BY a DESC;
} {1 {database disk image is malformed}}


#-------------------------------------------------------------------------
reset_db
do_test 11.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 595 pagesize 512 filename x.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: 02 00 00 01 00 40 20 20 00 01 00 0c 00 00 00 07   .....@  ........
|     32: 00 00 00 05 07 a1 1f fa 00 00 00 08 00 00 00 04   ................
|     48: 00 00 01 00 00 49 00 00 00 00 00 05 00 00 00 00   .....I..........
|     80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1c   ................
|     96: 00 2e 2c 50 0d 00 00 00 06 01 06 00 01 da 01 b0   ..,P............
|    112: 01 56 01 86 01 2a 01 06 00 00 62 00 00 00 00 00   .V...*....b.....
|    128: 00 ed e2 78 74 64 33 ff 43 52 45 41 54 45 20 49   ...xtd3.CREATE I
|    144: 4e 44 45 58 20 74 33 78 20 4f 4e 20 74 33 28 38   NDEX t3x ON t3(8
|    160: 29 2e 04 06 17 15 11 01 45 69 6e 64 65 68 74 32   ).......Eindeht2
|    176: 63 64 74 31 e5 43 52 45 41 54 45 20 49 4e 44 45   cdt1.CREATE INDE
|    192: 58 20 74 32 63 c4 20 4f 4e 20 74 32 28 63 2c 64   X t2c. ON t2(c,d
|    208: 29 28 05 06 17 01 11 11 3d 74 61 6c 36 74 62 74   )(......=tal6tbt
|    224: 65 32 04 43 52 45 41 54 45 20 54 41 42 4c 45 20   e2.CREATE TABLE 
|    240: 74 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00   t...............
|    256: 00 00 00 00 00 00 22 07 06 17 11 11 01 30 e8 03   .............0..
|    272: 62 6c 65 74 34 74 35 02 43 52 45 41 54 45 20 54   blet4t5.CREATE T
|    288: 41 42 4c 45 20 74 34 28 94 29 2a 06 06 17 13 11   ABLE t4(.)*.....
|    304: 01 3f 69 33 74 6e 65 78 78 74 64 33 ff 43 52 45   .?i3tnexxtd3.CRE
|    320: 41 54 45 20 49 4e 44 45 58 20 74 33 78 20 4f 4e   ATE INDEX t3x ON
|    336: 20 74 31 28 38 29 2e 04 06 17 15 11 01 45 69 6e    t1(8).......Ein
|    352: 64 65 68 74 32 63 64 74 31 e5 43 52 45 41 54 45   deht2cdt1.CREATE
|    368: 20 49 4e 44 45 58 20 74 32 63 c4 20 4f 4e 20 74    INDEX t2c. ON t
|    384: 32 28 63 2c 64 29 28 05 06 17 01 11 11 3d 74 61   2(c,d)(......=ta
|    400: 6c 32 74 62 74 65 32 04 43 52 45 41 54 45 20 54   l2tbte2.CREATE T
|    416: 41 42 4c 45 20 74 33 28 63 2c 78 2c 65 2c 66 29   ABLE t3(c,x,e,f)
|    432: 28 02 06 17 11 11 01 3d 74 61 9e 93 65 74 32 74   (......=ta..et2t
|    448: 32 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 74   2.CREATE TABLE t
|    464: 32 28 63 2c 64 2c 65 2c 66 29 24 01 06 17 11 11   2(c,d,e,f)$.....
|    480: 01 35 55 61 62 6c 88 74 31 74 31 02 43 52 45 41   .5Uabl.t1t1.CREA
|    496: 54 45 20 54 41 42 4c 45 20 74 31 28 61 2c 62 29   TE TABLE t1(a,b)
| page 2 offset 512
|      0: 0d 00 00 00 0d 25 00 01 cf 00 01 fa 01 f3 01 de   .....%..........
|     16: 01 00 00 00 fd 00 00 0d 00 00 00 00 45 20 54 41   ............E TA
|     32: 42 4c 45 20 74 34 28 94 29 2a 06 06 17 13 11 01   BLE t4(.)*......
|     48: 3f 69 33 74 6e 65 78 78 74 64 33 ff 43 52 45 a0   ?i3tnexxtd3.CRE.
|     64: a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 74 13 11 01   ............t...
|     80: 49 45 74 00 00 00 00 00 00 00 00 00 00 00 00 00   IEt.............
| end x.db
}]} {}

do_catchsql_test 11.1 {
  PRAGMA writable_schema=ON; -- bypass improved sqlite_master consistency checking
  DELETE FROM t3 WHERE x IN (SELECT x FROM t4);
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
reset_db
do_test 12.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 12288 pagesize 4096 filename crash-e6d070858a3a85.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 8f 00 0f bf 0f 8f   ................
|   3968: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2e   ................
|   3984: 02 06 17 15 11 01 45 69 6e 64 65 78 74 31 63 62   ......Eindext1cb
|   4000: 74 31 03 43 52 45 41 54 45 20 49 4e 44 45 58 20   t1.CREATE INDEX 
|   4016: 74 31 63 62 20 4f 4e 20 74 31 28 63 2c 62 29 3f   t1cb ON t1(c,b)?
|   4032: 01 06 17 11 11 01 6b 74 61 62 6c 65 74 31 74 31   ......ktablet1t1
|   4048: 02 43 52 45 41 54 45 20 54 41 42 4c 45 20 74 31   .CREATE TABLE t1
|   4064: 28 61 20 49 4e 54 2c 20 62 20 49 4e 54 2c 20 43   (a INT, b INT, C
|   4080: 20 49 4e 54 20 44 45 46 41 55 4c 54 20 31 36 29    INT DEFAULT 16)
| page 2 offset 4096
|      0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   4000: 00 00 00 00 00 00 00 00 07 0b 04 01 01 01 63 63   ..............cc
|   4016: 11 05 0a 04 00 00 01 11 05 09 04 08 08 01 0f 05   ................
|   4032: 08 04 00 00 01 01 56 07 04 01 08 01 07 10 07 06   ......V.........
|   4048: 14 01 01 01 06 08 10 06 05 04 f5 00 01 05 10 07   ................
|   4064: 04 04 01 01 01 04 03 10 06 03 04 01 09 01 03 10   ................
|   4080: 06 02 04 01 00 01 02 10 06 01 04 09 01 01 02 10   ................
| page 3 offset 8192
|      0: 0a 00 00 00 0b 0f b0 00 0f f9 0f f2 0f eb 0f e4   ................
|     16: 0f dd 0f d6 0f 9f 0f c7 0f be 00 00 00 00 00 00   ................
|   4016: 07 04 01 01 01 11 e2 0b 06 04 91 00 01 11 0a 07   ................
|   4032: 04 01 01 01 10 08 06 07 04 01 01 01 10 04 04 06   ................
|   4048: 04 01 01 09 10 02 06 04 01 0a 01 10 00 00 00 00   ................
| end crash-e6d070858a3a85.db
}]} {}

do_catchsql_test 12.1 {
  SELECT CAST((SELECT b FROM t1 WHERE 16=c) AS int) FROM t1 WHERE 16=c;
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
reset_db
do_test 13.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 8192 pagesize 4096 filename crash-81dd2952aef34f.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 02   .....@  ........
|     32: 00 00 00 00 00 00 00 00 00 00 00 01 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 00 00 00 01 0f c4 00 0f c4 00 00   ................
|   4032: 00 00 00 00 3a 11 06 17 11 11 01 61 74 61 62 6c   ....:......atabl
|   4048: 65 74 31 74 31 02 43 52 45 41 54 45 20 54 41 42   et1t1.CREATE TAB
|   4064: 4c 45 20 74 31 28 61 20 49 4e 54 45 47 45 52 20   LE t1(a INTEGER 
|   4080: 50 52 49 4d 41 52 59 20 4b 45 59 2c 62 2c 63 29   PRIMARY KEY,b,c)
| page 2 offset 4096
|      0: 0d 07 70 00 02 0f eb 00 0f fa 00 00 00 00 00 00   ..p.............
|   4064: 00 00 00 00 00 00 00 00 00 00 00 05 bf ff ff ff   ................
|   4080: ff ff ff ff ff 04 00 01 00 02 04 01 00 00 00 00   ................
| end crash-81dd2952aef34f.db
}]} {}

do_catchsql_test 13.1 {
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x-2019 FROM c WHERE x<2)
    INSERT INTO t1(b,c) SELECT last_insert_rowid(), x FROM c;
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
reset_db
do_test 14.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 512 pagesize 65536 filename clusterfuzz-testcase-minimized-sqlite3_dbfuzz2_fuzzer-4806406219825152
| 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: 00 01 02 01 00 40 20 20 00 63 2e 78 00 00 00 07   .....@  .c.x....
|     32: 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 04   ................
|     48: 00 00 00 00 00 00 01 00 35 05 43 00 04 00 00 00   ........5.C.....
|     80: 00 00 00 00 00 00 00 00 08 00 00 00 00 00 00 0c   ................
|     96: 00 2e 2c 50 0d 00 00 00 03 00 00 00 01 da 01 b0   ..,P............
|    112: 01 56 01 86 01 2a 01 02 00 00 00 00 00 00 00 1c   .V...*..........
|    128: 00 38 80 b2 e6 0e 00 00 00 00 00 00 00 00 00 10   .8..............
|    144: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01   ................
|    160: 00 00 00 00 00 00 00 00 00 00 00 00 45 20 54 41   ............E TA
|    256: 00 00 00 00 00 00 22 07 06 17 11 11 01 35 74 61   .............5ta
|    272: 62 6c 00 10 00 00 34 07 43 52 54 45 20 54 41 42   bl....4.CRTE TAB
|    288: 4c 45 20 74 33 28 63 2e 78 2c 65 2c 66 15 28 3a   LE t3(c.x,e,f.(:
|    304: 06 17 11 11 01 65 78 8c cc 87 85 35 05 43 72 45   .....ex....5.CrE
|    320: 41 54 48 20 49 4e 44 45 58 20 74 33 78 20 4f 4e   ATH INDEX t3x ON
|    336: 20 74 33 28 78 39 2e 04 06 17 15 11 01 45 69 6e    t3(x9.......Ein
|    352: 64 65 78 74 32 63 64 74 32 05 43 52 45 41 54 45   dext2cdt2.CREATE
|    368: 20 49 4e 44 45 58 20 74 32 63 64 20 4f 4e 20 74    INDEX t2cd ON t
|    384: 32 28 63 2a 44 29 28 05 fa e8 ee ed 01 3d 74 63   2(c*D)(......=tc
|    400: 62 6c 65 74 33 74 33 07 43 52 45 41 54 45 20 54   blet3t3.CREATE T
|    416: 41 42 4c 45 20 74 33 28 63 2e 78 2c 65 2c 66 15   ABLE t3(c.x,e,f.
|    432: 28 3a 06 17 11 11 01 3d 74 61 62 6c 65 74 32 74   (:.....=tablet2t
|    448: 32 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 74   2.CREATE TABLE t
|    464: 32 28 63 2c 64 2c 65 2c 66 29 24 01 06 17 11 11   2(c,d,e,f)$.....
|    480: 01 35 74 61 62 6c 65 74 31 74 31 02 43 52 45 41   .5tablet1t1.CREA
|    496: 54 45 20 54 41 42 4c 45 20 74 31 28 61 2c 63 29   TE TABLE t1(a,c)
| end clusterfuzz-testcase-minimized-sqlite3_dbfuzz2_fuzzer-4806406219825152
}]} {}

extra_schema_checks 0
do_catchsql_test 14.1 {
  PRAGMA integrity_check;
} {1 {database disk image is malformed}}

# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
ifcapable altertable {
  do_catchsql_test 14.2 {
    ALTER TABLE t1 RENAME TO alkjalkjdfiiiwuer987lkjwer82mx97sf98788s9789s; 
  } {1 {database disk image is malformed}}
}
extra_schema_checks 1

#-------------------------------------------------------------------------
reset_db
do_test 15.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 28672 pagesize 4096 filename crash-3afa1ca9e9c1bd.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   ................
|     48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00   ................
|     96: 00 00 00 00 0d 00 00 00 06 0e 88 00 0f b8 0f 6d   ...............m
|    112: 0f 3a 0f 0b 0e d5 0e 88 01 00 00 00 00 00 00 00   .:..............
|   3712: 00 00 00 00 00 00 00 00 4b 06 06 17 25 25 01 5b   ........K...%%.[
|   3728: 74 61 62 6c 65 73 71 6c 69 74 65 5f 73 74 61 74   tablesqlite_stat
|   3744: 31 73 71 6c 69 74 65 5f 73 74 61 74 31 07 43 52   1sqlite_stat1.CR
|   3760: 45 41 54 45 20 54 41 42 4c 45 20 73 71 6c 69 74   EATE TABLE sqlit
|   3776: 65 5f 73 74 61 74 31 28 74 62 6c 2c 69 64 78 2c   e_stat1(tbl,idx,
|   3792: 73 74 61 74 29 34 05 06 17 13 11 01 53 69 6e 64   stat)4......Sind
|   3808: 65 78 63 31 63 63 31 06 43 52 45 41 54 45 20 55   exc1cc1.CREATE U
|   3824: 4e 49 51 55 45 20 49 4e 44 45 58 20 63 31 63 20   NIQUE INDEX c1c 
|   3840: 4f 4e 20 63 31 28 63 2c 20 62 29 2d 04 06 17 13   ON c1(c, b)-....
|   3856: 11 01 45 69 6e 64 65 78 63 31 64 63 31 05 43 52   ..Eindexc1dc1.CR
|   3872: 45 41 54 45 20 49 4e 44 45 58 20 63 31 64 20 4f   EATE INDEX c1d O
|   3888: 4e 20 63 31 28 64 2c 20 62 29 31 03 06 17 13 11   N c1(d, b)1.....
|   3904: 01 4d 69 6e 64 65 78 62 31 63 62 31 05 43 52 45   .Mindexb1cb1.CRE
|   3920: 41 54 45 20 55 4e 49 51 55 45 20 49 4e 44 45 58   ATE UNIQUE INDEX
|   3936: 20 62 31 63 20 4f 4e 20 62 31 28 63 29 49 02 06    b1c ON b1(c)I..
|   3952: 17 11 11 0f 7f 74 61 62 6c 65 63 31 63 31 03 43   .....tablec1c1.C
|   3968: 52 45 41 54 45 20 54 41 42 4c 45 20 63 31 28 61   REATE TABLE c1(a
|   3984: 20 49 4e 54 20 50 52 49 4d 41 52 59 20 4b 45 59    INT PRIMARY KEY
|   4000: 2c 20 62 2c 20 63 2c 20 64 29 20 57 49 54 48 4f   , b, c, d) WITHO
|   4016: 55 54 20 52 4f 57 49 44 46 01 06 17 11 11 01 79   UT ROWIDF......y
|   4032: 74 61 62 6c 65 62 31 62 31 02 43 52 45 41 54 45   tableb1b1.CREATE
|   4048: 20 54 41 42 4c 45 20 62 31 28 61 20 49 4e 54 20    TABLE b1(a INT 
|   4064: 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 62 2c 20   PRIMARY KEY, b, 
|   4080: 63 29 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44   c) WITHOUT ROWID
| page 2 offset 4096
|      0: 0a 00 00 00 07 0f ca 00 0f fa 0f f2 0f ea 0f e2   ................
|     16: 0f da 00 00 00 01 00 00 00 00 00 00 00 00 00 00   ................
|   4032: 00 00 00 00 00 00 00 00 00 00 07 04 01 0f 01 06   ................
|   4048: 67 07 07 04 01 0f 01 06 66 06 07 04 01 0f 01 05   g.......f.......
|   4064: 65 05 07 04 01 0f 01 04 64 04 07 04 01 0f 01 03   e.......d.......
|   4080: 63 03 07 04 01 0f 01 02 62 0f 05 04 09 0f 09 61   c.......b......a
| page 3 offset 8192
|      0: 0a 00 00 00 07 0f bd 00 0f f9 0f ef 0f e5 0f db   ................
|     16: 0f d1 0f c7 0f bd 00 00 00 00 01 00 00 00 00 00   ................
|   4016: 00 00 00 00 00 00 00 00 00 00 00 00 00 09 05 01   ................
|   4032: 0f 01 01 07 61 07 07 09 05 01 0f 01 01 06 61 06   ....a.........a.
|   4048: 06 09 05 01 0f 01 01 05 61 05 05 09 05 01 0f 01   ........a.......
|   4064: 01 04 61 04 04 09 05 01 0f 01 01 03 61 03 03 09   ..a.........a...
|   4080: 05 01 0f 01 01 02 61 0f 02 06 05 09 0f 09 09 61   ......a........a
| page 4 offset 12288
|      0: 0a 00 00 00 07 0f d8 00 0f fc 0f f0 0f ea 0f e4   ................
|     16: 0f de 0f d8 0f f6 00 00 00 00 00 00 00 00 00 00   ................
|   4048: 00 00 00 00 00 00 00 00 05 03 01 01 07 07 05 03   ................
|   4064: 01 01 06 06 05 03 01 01 05 05 05 03 01 01 04 04   ................
|   4080: 05 03 01 01 03 03 05 03 01 01 0f 02 03 03 09 09   ................
| page 5 offset 16384
|      0: 0a 00 00 00 07 0f ca 00 0f fa 0f f2 0f ea 0f 00   ................
|   4032: 00 00 00 00 00 00 00 00 00 00 07 04 01 0f 01 07   ................
|   4048: 61 07 07 04 01 0f 01 06 61 06 07 04 01 0f 01 05   a.......a.......
|   4064: 61 05 07 04 01 1f 01 04 61 04 07 04 01 0f 01 03   a.......a.......
|   4080: 61 03 07 04 01 0f 01 02 61 02 05 04 09 0f 09 61   a.......a......a
| page 6 offset 20480
|      0: 0a 00 00 00 07 0f ca 00 0f fa 0f ea 0f e2 00 00   ................
|   4032: 00 00 00 00 00 00 00 00 00 00 07 04 01 0f 01 07   ................
|   4048: 61 07 07 04 01 0f 01 06 61 06 07 04 01 0f 01 05   a.......a.......
|   4064: 61 05 07 04 01 0f 01 04 61 04 07 04 01 0f 01 03   a.......a.......
|   4080: 61 03 07 04 01 0f 01 0f 61 02 05 04 09 0f 09 61   a.......a......a
| page 7 offset 24576
|      0: 0d 00 00 00 05 0f 1c 00 0f f0 0f e0 0f d3 0f c5   ................
|     16: 0f b8 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   4016: 00 00 00 00 00 00 00 00 0b 05 04 11 11 13 62 31   ..............b1
|   4032: 62 31 37 20 31 0c 04 04 11 13 13 62 31 62 31 63   b17 1......b1b1c
|   4048: 37 20 31 0b 03 04 11 11 13 63 31 63 31 37 20 31   7 1......c1c17 1
|   4064: 0e 02 04 11 13 07 63 31 63 31 64 37 20 31 20 31   ......c1c1d7 1 1
|   4080: 0e 01 04 11 13 17 63 31 63 31 63 37 20 31 00 00   ......c1c1c7 1..
| end crash-3afa1ca9e9c1bd.db
}]} {}

extra_schema_checks 0
do_execsql_test 15.1 {
  PRAGMA cell_size_check = 0;
  UPDATE c1 SET c= NOT EXISTS(SELECT 1 FROM c1 ORDER BY (SELECT 1 FROM c1 ORDER BY a)) +10 WHERE d BETWEEN 4 AND 7;
} {}
extra_schema_checks 1

#-------------------------------------------------------------------------
reset_db
do_execsql_test 16.0 {
  CREATE TABLE t1(w, x, y, z, UNIQUE(w, x), UNIQUE(y, z));
  INSERT INTO t1 VALUES(1, 1, 1, 1);

  CREATE TABLE t1idx(x, y, i INTEGER, PRIMARY KEY(x)) WITHOUT ROWID;
  INSERT INTO t1idx VALUES(10, NULL, 5);

  PRAGMA writable_schema = 1;
  UPDATE sqlite_master SET rootpage = (
    SELECT rootpage FROM sqlite_master WHERE name='t1idx'
  ) WHERE type = 'index';
}

extra_schema_checks 0
db close
sqlite3 db test.db
extra_schema_checks 1

do_catchsql_test 16.1 {
  PRAGMA writable_schema = ON;
  INSERT INTO t1(rowid, w, x, y, z) VALUES(5, 10, 11, 10, NULL);
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
# Test that corruption is reported from within a checkpoint if the 
# expected final size of the database (according to the last commit
# frame in the wal file) is greater than the combined initial sizes 
# of the database and wal file.
#
if {[wal_is_capable]} {
  reset_db
  do_execsql_test 17.0 {
    CREATE TABLE t1(o INTEGER PRIMARY KEY, t UNIQUE);
    INSERT INTO t1(t) VALUES(randomblob(123));
    INSERT INTO t1(t) SELECT randomblob(123) FROM t1;
    INSERT INTO t1(t) SELECT randomblob(123) FROM t1;
    INSERT INTO t1(t) SELECT randomblob(123) FROM t1;
    INSERT INTO t1(t) SELECT randomblob(123) FROM t1;
    INSERT INTO t1(t) SELECT randomblob(123) FROM t1;
    INSERT INTO t1(t) SELECT randomblob(123) FROM t1;
    INSERT INTO t1(t) SELECT randomblob(123) FROM t1;
    INSERT INTO t1(t) SELECT randomblob(123) FROM t1;
    INSERT INTO t1(t) SELECT randomblob(123) FROM t1;
  
    PRAGMA journal_mode = wal;
    INSERT INTO t1 VALUES(-1, 'b');
  } {wal}
  
  do_test 17.1 {
    set fd [open test.db r+]
    chan truncate $fd 2048
    file size test.db
  } {2048}
  
  do_catchsql_test 17.2 {
    PRAGMA wal_checkpoint
  } {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

#-------------------------------------------------------------------------
reset_db
do_test 19.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
.open --hexdb
| size 20480 pagesize 4096 filename crash-f022eb0ce64d27.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 00 02 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 0e d2 00 0f 08 0f d3   ................
|    112: 0f ae 0e d2 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   3792: 00 00 34 04 06 17 0f 11 01 57 69 6e 64 65 78 61   ..4......Windexa
|   3808: 74 31 05 43 52 45 41 54 45 20 55 4e 49 51 55 45   t1.CREATE UNIQUE
|   3824: 20 49 4e 44 45 58 20 61 20 4f 4e 20 74 31 28 61    INDEX a ON t1(a
|   3840: 2c 20 30 20 7c 20 61 29 81 23 01 07 17 11 11 01   , 0 | a).#......
|   3856: 82 31 74 61 62 6c 65 74 31 74 31 02 43 52 45 41   .1tablet1t1.CREA
|   3872: 54 45 20 54 41 42 4c 45 20 74 31 28 0a 20 20 20   TE TABLE t1(.   
|   3888: 20 67 63 62 20 41 53 20 28 62 2a 31 29 2c 0a 20    gcb AS (b*1),. 
|   3904: 20 20 20 61 20 49 34 54 45 47 45 52 20 50 52 49      a I4TEGER PRI
|   3920: 4d 41 52 59 20 4b 45 59 2c 0a 20 20 20 20 67 63   MARY KEY,.    gc
|   3936: 63 20 41 53 20 28 74 32 2b 30 29 2c 0a 20 20 20   c AS (t2+0),.   
|   3952: 20 62 20 55 4e 49 51 55 45 2c 0a 20 20 20 20 67    b UNIQUE,.    g
|   3968: 63 61 20 41 53 20 28 31 2a 61 2b 30 29 2c 0a 20   ca AS (1*a+0),. 
|   3984: 20 20 20 74 32 20 55 4e 49 51 55 45 0a 20 20 29      t2 UNIQUE.  )
|   4000: 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 23 03    WITHOUT ROWID#.
|   4016: 06 17 37 11 01 00 69 6e 64 65 78 73 71 6c 69 74   ..7...indexsqlit
|   4032: 65 5f 61 75 74 6f 69 6e 64 65 78 5f 74 31 5f 33   e_autoindex_t1_3
|   4048: 74 31 02 23 02 06 17 37 11 01 00 69 6e 64 65 78   t1.#...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 32 74 31 02 00 00 00 08 00 00 00 00   _t1_2t1.........
| page 2 offset 4096
|      0: 0a 00 00 00 05 0f d8 00 0f f8 0f f8 9f e8 0f e0   ................
|     16: 0f d8 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   4048: 00 00 00 00 00 00 00 00 07 04 01 02 00 0f 13 88   ................
|   4064: 07 04 01 02 00 0e 0f a0 07 04 01 02 00 0d 0b b8   ................
|   4080: 07 04 01 02 00 0c 07 d0 07 04 01 02 00 0b 03 e8   ................
| page 5 offset 16384
|      0: 0a 00 00 00 05 0f e2 00 0f fa 0f f4 0f ee 0f e8   ................
|     16: 0f e2 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   4064: 00 00 05 03 01 01 0f 0f 05 03 01 01 0e 0e 05 03   ................
|   4080: 01 01 0d 0d 05 03 01 01 0c 0c 05 03 01 01 0b 0b   ................
| end crash-f022eb0ce64d27.db
}]} {}

do_execsql_test 19.1 {
  PRAGMA writable_schema=ON;
}
do_catchsql_test 19.2 {
  UPDATE t1 SET a=1;
} {1 {database disk image is malformed}}

reset_db
do_execsql_test 19.3 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT, c INTEGER, d TEXT);
  CREATE INDEX i1 ON t1((NULL));
  INSERT INTO t1 VALUES(1, NULL, 1, 'text value');
  PRAGMA writable_schema = on;
  UPDATE sqlite_schema SET 
      sql = 'CREATE INDEX i1 ON t1(b, c, d)', 
      tbl_name = 't1', 
      type='index' 
  WHERE name='i1';
}
db close
sqlite3 db test.db
do_catchsql_test 19.4 {
  PRAGMA integrity_check;
} {1 {database disk image is malformed}}

finish_test

Added test/corruptM.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019-08-12
#
# 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.
#
#***********************************************************************
#
# Check to ensure that the type, name, and tbl_name fields of the
# sqlite_master table are validated and errors are reported if they
# are inconsistent with the sql.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix corruptM

# These tests deal with corrupt database files
#
database_may_be_corrupt

proc open_db2_and_catchsql {sql} {
  set rc [catch { sqlite3 db2 test.db } msg]
  if {$rc} {
    return [list $rc $msg]
  }
  set res [catchsql $sql db2]
  db2 close
  set res
}

db close
forcedelete test.db
sqlite3 db test.db
do_execsql_test corruptM-100 {
  CREATE TABLE t1(a,b,c);
  INSERT INTO t1 VALUES(111,222,333);
  CREATE INDEX i1 ON t1(b);
  CREATE VIEW v2 AS SELECT 15,22;
  CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN SELECT 5; END;
  SELECT type, name, tbl_name, '|' FROM sqlite_master;
} {table t1 t1 | index i1 t1 | view v2 v2 | trigger r1 t1 |}
do_execsql_test corruptM-101 {
  PRAGMA writable_schema=on;
  UPDATE sqlite_master SET tbl_name=NULL WHERE name='t1';
  SELECT type, name, tbl_name, '|' FROM sqlite_master;
} {table t1 {} | index i1 t1 | view v2 v2 | trigger r1 t1 |}
do_test corruptM-102 {
  open_db2_and_catchsql {
    PRAGMA quick_check;
  }
} {1 {malformed database schema (t1)}}

do_execsql_test corruptM-110 {
  UPDATE sqlite_master SET tbl_name='tx' WHERE name='t1';
  SELECT type, name, tbl_name, '|' FROM sqlite_master;
} {table t1 tx | index i1 t1 | view v2 v2 | trigger r1 t1 |}
do_test corruptM-111 {
  open_db2_and_catchsql {
    PRAGMA quick_check;
  }
} {1 {malformed database schema (t1)}}
do_execsql_test corruptM-112 {
  UPDATE sqlite_master SET tbl_name='t1', type='tabl' WHERE name='t1';
  SELECT type, name, tbl_name, '|' FROM sqlite_master;
} {tabl t1 t1 | index i1 t1 | view v2 v2 | trigger r1 t1 |}
do_test corruptM-113 {
  open_db2_and_catchsql {
    PRAGMA quick_check;
  }
} {1 {malformed database schema (t1)}}
do_execsql_test corruptM-114 {
  UPDATE sqlite_master SET tbl_name='t9',type='table',name='t9'WHERE name='t1';
  SELECT type, name, tbl_name, '|' FROM sqlite_master;
} {table t9 t9 | index i1 t1 | view v2 v2 | trigger r1 t1 |}
do_test corruptM-114 {
  open_db2_and_catchsql {
    PRAGMA quick_check;
  }
} {1 {malformed database schema (t9)}}

do_execsql_test corruptM-120 {
  UPDATE sqlite_master SET name='t1',tbl_name='T1' WHERE name='t9';
  SELECT type, name, tbl_name, '|' FROM sqlite_master;
} {table t1 T1 | index i1 t1 | view v2 v2 | trigger r1 t1 |}
do_test corruptM-121 {
  open_db2_and_catchsql {
    PRAGMA quick_check;
    SELECT * FROM t1, v2;
  } 
} {0 {ok 111 222 333 15 22}}

do_execsql_test corruptM-130 {
  UPDATE sqlite_master SET type='view' WHERE name='t1';
  SELECT type, name, tbl_name, '|' FROM sqlite_master;
} {view t1 T1 | index i1 t1 | view v2 v2 | trigger r1 t1 |}
do_test corruptM-131 {
  open_db2_and_catchsql {
    PRAGMA quick_check;
    SELECT * FROM t1, v2;
  }
} {1 {malformed database schema (t1)}}

do_execsql_test corruptM-140 {
  UPDATE sqlite_master SET type='table', tbl_name='t1' WHERE name='t1';
  UPDATE sqlite_master SET tbl_name='tx' WHERE name='i1';
  SELECT type, name, tbl_name, '|' FROM sqlite_master;
} {table t1 t1 | index i1 tx | view v2 v2 | trigger r1 t1 |}
do_test corruptM-141 {
  open_db2_and_catchsql {
    PRAGMA quick_check;
    SELECT * FROM t1, v2;
  }
} {1 {malformed database schema (i1)}}

do_execsql_test corruptM-150 {
  UPDATE sqlite_master SET type='table', tbl_name='t1' WHERE name='i1';
  SELECT type, name, tbl_name, '|' FROM sqlite_master;
} {table t1 t1 | table i1 t1 | view v2 v2 | trigger r1 t1 |}
do_test corruptM-151 {
  open_db2_and_catchsql {
    PRAGMA quick_check;
    SELECT * FROM t1, v2;
  }
} {1 {malformed database schema (i1)}}

do_execsql_test corruptM-160 {
  UPDATE sqlite_master SET type='view', tbl_name='t1' WHERE name='i1';
  SELECT type, name, tbl_name, '|' FROM sqlite_master;
} {table t1 t1 | view i1 t1 | view v2 v2 | trigger r1 t1 |}
do_test corruptM-161 {
  open_db2_and_catchsql {
    PRAGMA quick_check;
    SELECT * FROM t1, v2;
  }
} {1 {malformed database schema (i1)}}

do_execsql_test corruptM-170 {
  UPDATE sqlite_master SET type='index', tbl_name='t1' WHERE name='i1';
  UPDATE sqlite_master SET type='table', tbl_name='v2' WHERE name='v2';
  SELECT type, name, tbl_name, '|' FROM sqlite_master;
} {table t1 t1 | index i1 t1 | table v2 v2 | trigger r1 t1 |}
do_test corruptM-171 {
  open_db2_and_catchsql {
    PRAGMA quick_check;
    SELECT * FROM t1, v2;
  }
} {1 {malformed database schema (v2)}}

do_execsql_test corruptM-180 {
  UPDATE sqlite_master SET type='view',name='v3',tbl_name='v3' WHERE name='v2';
  SELECT type, name, tbl_name, '|' FROM sqlite_master;
} {table t1 t1 | index i1 t1 | view v3 v3 | trigger r1 t1 |}
do_test corruptM-181 {
  open_db2_and_catchsql {
    PRAGMA quick_check;
    SELECT * FROM t1, v2;
  }
} {1 {malformed database schema (v3)}}

do_execsql_test corruptM-190 {
  UPDATE sqlite_master SET type='view',name='v2',tbl_name='v2' WHERE name='v3';
  UPDATE sqlite_master SET type='view' WHERE name='r1';
  SELECT type, name, tbl_name, '|' FROM sqlite_master;
} {table t1 t1 | index i1 t1 | view v2 v2 | view r1 t1 |}
do_test corruptM-191 {
  open_db2_and_catchsql {
    PRAGMA quick_check;
    SELECT * FROM t1, v2;
  }
} {1 {malformed database schema (r1)}}
do_execsql_test corruptM-192 {
  UPDATE sqlite_master SET type='trigger',tbl_name='v2' WHERE name='r1';
  SELECT type, name, tbl_name, '|' FROM sqlite_master;
} {table t1 t1 | index i1 t1 | view v2 v2 | trigger r1 v2 |}
do_test corruptM-193 {
  open_db2_and_catchsql {
    PRAGMA quick_check;
    SELECT * FROM t1, v2;
  }
} {1 {malformed database schema (r1)}}

finish_test

Added test/corruptN.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2020-12-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.
#
#***********************************************************************
#
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix corruptN

# These tests deal with corrupt database files
#
database_may_be_corrupt

reset_db
do_test 1.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
.open --hexdb
| size 4096 pagesize 512 filename sql024239.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: 02 00 01 01 00 40 20 20 00 00 00 0c 00 00 00 07   .....@  ........
|     32: 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 04   ................
|     48: 00 00 00 00 89 00 00 04 00 10 00 01 0a 00 00 01   ................
|     80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0c   ................
|     96: 00 2e 2c 50 0d 00 00 00 06 01 06 00 01 da 01 b0   ..,P............
|    112: 01 56 01 86 01 2a 01 06 00 00 00 00 00 00 00 00   .V...*..........
|    256: 00 00 00 00 00 00 22 07 06 17 11 11 01 31 74 61   .............1ta
|    272: 62 6c 65 74 34 74 34 07 43 52 45 41 54 45 20 54   blet4t4.CREATE T
|    288: 41 42 4c 45 20 74 34 28 78 29 2a 06 06 17 13 11   ABLE t4(x)*.....
|    304: 01 3f 69 6e 64 65 78 74 33 78 74 33 05 43 52 45   .?indext3xt3.CRE
|    320: 41 54 45 20 49 4e 44 45 58 20 74 33 78 20 4f 4e   ATE INDEX t3x ON
|    336: 20 74 33 28 78 29 2e 04 06 17 15 11 01 45 69 6e    t3(x).......Ein
|    352: 64 65 78 74 32 63 64 74 32 05 43 52 45 41 54 45   dext2cdt2.CREATE
|    368: 20 49 4e 44 45 58 20 74 32 63 64 20 4f 4e 20 74    INDEX t2cd ON t
|    384: 32 28 63 2c 64 29 28 05 06 17 11 11 01 3d 74 61   2(c,d)(......=ta
|    400: 62 6c 65 74 33 74 33 07 43 52 45 41 54 45 20 54   blet3t3.CREATE T
|    416: 41 42 4c 45 20 74 33 28 63 2c 78 2c 65 2c 66 29   ABLE t3(c,x,e,f)
|    432: 28 02 06 17 11 11 01 3d 74 61 62 6c 65 74 32 74   (......=tablet2t
|    448: 32 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 74   2.CREATE TABLE t
|    464: 32 28 63 2c 64 2c 65 2c 66 29 24 01 06 17 11 11   2(c,d,e,f)$.....
|    480: 01 35 74 61 62 6c 65 74 31 74 31 02 43 52 45 41   .5tablet1t1.CREA
|    496: 54 45 20 54 41 42 4c 45 20 74 31 28 61 2c 62 29   TE TABLE t1(a,b)
| page 2 offset 512
|      0: 0d 00 00 00 04 01 41 00 01 fa 01 f3 01 de 01 cf   ......A.........
|    160: 00 00 20 00 00 00 00 00 00 00 00 00 00 00 00 00   .. .............
|    448: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0d   ................
|    464: 04 03 17 17 73 65 76 65 6e 65 69 67 68 74 13 03   ....seveneight..
|    480: 03 07 07 40 14 00 00 00 00 00 00 40 18 00 00 00   ...@.......@....
|    496: 00 00 00 05 02 03 01 01 03 04 04 01 03 09 01 02   ................
| page 3 offset 1024
|      0: 0d 00 00 00 08 01 54 00 01 f7 01 ec 01 c5 01 aa   ......T.........
|     16: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|    112: 00 00 dd 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|    336: 00 00 00 00 19 08 05 17 17 17 17 65 69 67 68 74   ...........eight
|    352: 65 69 67 68 74 73 65 76 65 6e 73 65 76 65 6e 25   eightsevenseven%
|    368: 07 05 07 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|    432: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08   ................
|    480: 00 00 0f 04 17 17 01 65 69 67 68 74 65 69 67 68   .......eighteigh
|    496: 74 08 15 04 07 07 01 40 18 00 00 00 00 00 00 40   t......@.......@
| page 4 offset 1536
|      0: 18 00 00 00 00 00 00 07 07 04 01 01 01 04 04 06   ................
|     16: 07 04 01 01 01 02 02 05 0f 04 17 17 01 73 6d 76   .............smv
|     32: 65 6e 65 69 67 68 74 04 15 04 07 07 01 40 14 00   eneight......@..
| page 5 offset 2048
|      0: 0a 00 00 00 08 01 96 00 01 fa 01 c4 01 f2 01 bc   ................
|     16: 01 dc 01 e1 01 96 01 cc 00 00 00 00 00 00 00 00   ................
|    160: 00 00 00 00 00 00 32 00 00 00 00 00 00 00 00 00   ......2.........
|    368: 00 00 00 08 00 00 00 00 00 00 00 00 00 00 00 00   ................
|    400: 00 00 00 00 00 00 0f 04 17 17 01 85 69 67 68 74   ............ight
|    416: 65 69 67 68 74 08 15 04 07 07 01 40 18 00 00 00   eight......@....
|    432: 00 00 00 40 18 00 00 00 00 00 00 07 07 04 01 01   ...@............
|    448: 01 04 04 06 07 04 01 01 01 02 02 05 0f 04 17 17   ................
|    464: 01 73 6d 76 65 6e 65 69 67 68 74 04 15 04 07 07   .smveneight.....
|    480: 01 40 14 00 00 00 00 00 00 40 18 00 00 00 00 00   .@.......@......
|    496: 00 03 07 04 01 01 01 03 04 02 05 04 03 01 09 02   ................
| page 6 offset 2560
|      0: 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|     16: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00   ................
|    304: 00 00 00 26 00 00 00 00 00 00 00 00 00 00 00 00   ...&............
| page 7 offset 3072
|      0: 0d 00 00 00 08 01 c2 00 01 fb 01 f6 01 f1 01 ec   ................
|     16: 01 e0 01 d4 01 cb 01 c2 00 00 00 00 00 00 00 00   ................
|    128: 00 00 00 00 00 00 00 00 00 00 00 00 00 20 00 04   ............. ..
|    384: 00 00 00 00 00 00 00 00 00 07 08 02 17 65 69 fc   .............ei.
|    400: 68 74 07 07 02 17 65 69 67 68 74 0a fb fd f8 bf   ht....eight.....
|    416: e7 ff ff ff 00 00 00 0a 05 02 07 40 18 00 00 00   ...........@....
|    432: 00 00 00 03 04 02 01 04 03 03 02 01 04 03 02 01   ................
|    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
}]} {}

reset_db
if {![info exists ::G(perm:presql)]} {
  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 4.2 {
    PRAGMA writable_schema = 1;
    REPLACE INTO x1 VALUES(5, 2, 3);
  } {0 {}}

}

#-------------------------------------------------------------------------

reset_db

ifcapable json1&&vtab {
  db func strreplace strreplace
  proc strreplace {orig a b} {
    string map [list $a $b] $orig
  }

  do_execsql_test 5.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';
  }

  # Do not run this tests if there is any presql (SQL run from within
  # the [sqlite3] command) configured. In this case the schema is parsed
  # before the "PRAGMA writable_schema" command is executed and the 
  # script throws and exception.
  if {[info exists ::G(perm:presql)]==0 || $::G(perm:presql)==""} {
    db close
    sqlite3 db test.db

    do_execsql_test 5.1 {
      PRAGMA writable_schema = 1;
      SELECT * FROM t1
    }
  }
}; # ifcapable json1&&vtab

#-------------------------------------------------------------------------
reset_db

do_execsql_test 6.0 {
  PRAGMA auto_vacuum = 0;
  PRAGMA page_size=1024;
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
  INSERT INTO t1(b) VALUES(zeroblob(300)),(zeroblob(300)),(zeroblob(300)),(zeroblob(300));
  CREATE TABLE t2(a);
  CREATE TRIGGER t1tr BEFORE UPDATE ON t1 BEGIN DELETE FROM t2; END;
  PRAGMA writable_schema=ON;
  UPDATE sqlite_schema SET rootpage=3 WHERE rowid=2;
  PRAGMA writable_schema=RESET;
  INSERT INTO t2 VALUES('active'),('boomer'),('atom'),('atomic'),
         ('alpha channel backup abandon test aback boomer atom alpha active');
}
do_catchsql_test 6.1 {
  UPDATE t1 SET b=zeroblob(299);
} {1 {database disk image is malformed}}

reset_db
do_execsql_test 6.2 {
  -- Make "t1" a large table. Large enough that the children of the root
  -- node are interior nodes.
  PRAGMA page_size = 1024;
  PRAGMA auto_vacuum = 0;
  CREATE TABLE t1(x);
  WITH s(i) AS (
    SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<500
  )
  INSERT INTO t1 SELECT zeroblob(300) FROM s;
  
  CREATE TABLE t2(y);
  CREATE TRIGGER tr BEFORE UPDATE ON t1 BEGIN
    DELETE FROM t2;
  END;
  
  -- Set the root of table t2 to 137 - the leftmost child of the root of t1.
  PRAGMA writable_schema = ON;
  UPDATE sqlite_schema SET rootpage = 137 WHERE name='t2';
  PRAGMA writable_schema = RESET;
}
  
do_catchsql_test 6.3 {
  -- Run an UPDATE on t1 that will hit a child of page 136. Have the trigger
  -- clear page 136 and its children. Assert fails.
  UPDATE t1 SET x='hello world' WHERE rowid=1;
} {1 {database disk image is malformed}}

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
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 TABLE t5 USING INDEX t5c (c=?)
  |  `--SEARCH TABLE t5 USING INDEX t5d (d=?)
  |  |  `--SEARCH t5 USING INDEX t5b (b=?)
  |  |--INDEX 2
  |  |  `--SEARCH t5 USING INDEX t5c (c=?)
  |  `--INDEX 3
  |     `--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 TABLE t3 USING INDEX t3i2 (c=?)
  |  |  `--SEARCH t3 USING INDEX t3i1 (b>? AND b<?)
  |  `--INDEX 2
  |     `--SEARCH t3 USING INDEX t3i2 (c=?)
  `--USE TEMP B-TREE FOR ORDER BY
}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 7.1 {
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
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







+
-
-
+
+
+








-
+



-
+







do_eqp_test 7.2 {
  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 TABLE t1 USING INDEX t1b (b=?)
  |  |  `--SEARCH t1 USING INDEX t1b (b>? AND b<?)
  |  `--INDEX 2
  |     `--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,
191
192
193
194
195
196
197
198
199
200



201
202
203
204
205
206
207
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(
219
220
221
222
223
224
225
226

227
228
229

230
231
232
233
234
235
236
226
227
228
229
230
231
232

233
234
235

236
237
238
239
240
241
242
243







-
+


-
+







    CREATE INDEX i2 ON t1(a,b,c,d,e,f,g,h,i,j);
  }
} {}

set L [list a=? b=? c=? d=? e=? f=? g=? h=? i=? j=?]
foreach {tn nTerm nRow} {
  1   1 10
  2   2  9
  2   2 10
  3   3  8
  4   4  7
  5   5  6
  5   5  7
  6   6  5
  7   7  5
  8   8  5
  9   9  5
  10 10  5
} {
  set w [join [lrange $L 0 [expr $nTerm-1]] " AND "]
260
261
262
263
264
265
266
267

268
269
270
271

272
273
274
275

276
277
278
279

280
281
282
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.

122
123
124
125
126
127
128
129
130
131






132
133
134
135
136
137
138
122
123
124
125
126
127
128



129
130
131
132
133
134
135
136
137
138
139
140
141







-
-
-
+
+
+
+
+
+







} {1 {DISTINCT aggregates must have exactly one argument}}
do_test count-2.7 {
  uses_op_count {SELECT count(*)+1 FROM t2}
} {0}
do_test count-2.8 {
  uses_op_count {SELECT count(*) FROM t2 WHERE a IS NOT NULL}
} {0}
do_test count-2.9 {
  catchsql {SELECT count(*) FROM t2 HAVING count(*)>1}
} {1 {a GROUP BY clause is required before HAVING}}
do_execsql_test count-2.9a {
  SELECT count(*) FROM t2 HAVING count(*)>1;
} {}
do_execsql_test count-2.9b {
  SELECT count(*) FROM t2 HAVING count(*)<10;
} {0}
do_test count-2.10 {
  uses_op_count {SELECT count(*) FROM (SELECT 1)}
} {0}
do_test count-2.11 {
  execsql { CREATE VIEW v1 AS SELECT 1 AS a }
  uses_op_count {SELECT count(*) FROM v1}
} {0}
191
192
193
194
195
196
197
198

















































199
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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  SELECT count(*) FROM t5;
} {1}

do_catchsql_test count-6.1 {
  CREATE TABLE t6(x);
  SELECT count(DISTINCT) FROM t6 GROUP BY x;
} {1 {DISTINCT aggregates must have exactly one argument}}

# 2020-05-08.
# The count() optimization should honor the NOT INDEXED clause
#
reset_db
do_execsql_test count-7.1 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b INT, c VARCHAR(1000));
  CREATE INDEX t1b ON t1(b);
  INSERT INTO t1(a,b,c) values(1,2,'count.test cases for NOT INDEXED');
  ANALYZE;
  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 t1 USING COVERING INDEX t1b
}
do_eqp_test count-7.3 {
  SELECT count(1) FROM t1 NOT INDEXED
} {
  QUERY PLAN
  `--SCAN t1
}
do_eqp_test count-7.3 {
  SELECT count(*) FROM t1;
} {
  QUERY PLAN
  `--SCAN t1 USING COVERING INDEX t1b
}
do_eqp_test count-7.4 {
  SELECT count(*) FROM t1 NOT INDEXED
} {
  QUERY PLAN
  `--SCAN t1
}

do_execsql_test count-8.0 {
  CREATE TABLE t7(a INT,b TEXT,c BLOB,d REAL);
  CREATE TABLE t8(a INT,b TEXT,c BLOB,d REAL);
  CREATE INDEX t8a ON t8(a);
}
do_catchsql_test count-8.1 {
  SELECT * FROM t8 WHERE (a, b) IN (
      SELECT count(t8.b), count(*) FROM t7 AS ra0 ORDER BY count(*)
  ) AND t8.b=0; 
} {1 {misuse of aggregate: count()}}


finish_test

Changes to test/countofview.test.

35
36
37
38
39
40
41













42
43
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56







+
+
+
+
+
+
+
+
+
+
+
+
+


} {1}

do_execsql_test 1.3 {
  select count(*) from (
    select c from t2 union all select f from t3
  )
} {3}

# 2019-05-15
do_execsql_test 2.0 {
  CREATE TABLE t1(x);
  INSERT INTO t1 VALUES(1),(99),('abc');
  CREATE VIEW v1(x,y) AS SELECT x,1 FROM t1 UNION ALL SELECT x,2 FROM t1;
  SELECT count(*) FROM v1 WHERE x<>1;
} {4}
do_execsql_test 2.1 {
  SELECT count(*) FROM v1 GROUP BY y;
} {3 3}



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/crash5.test.

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
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







-
+







-
+

















+
+
+
+
+
+
+
+
+
+
+
+
+
+














-
-
+
+
+

+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Only run these tests if memory debugging is turned on.
#
ifcapable !crashtest||!memorymanage {
   puts "Skipping crash5 tests: not compiled with -DSQLITE_MEMDEBUG..."
   puts "Skipping crash5 tests: not compiled with -DSQLITE_ENABLE_MEMORY_MANAGEMENT..."
   finish_test
   return
}

db close

for {set ii 0} {$ii < 10} {incr ii} {
  for {set jj 50} {$jj < 100} {incr jj} {
  for {set jj 1} {$jj < 100} {incr jj} {

    # Set up the database so that it is an auto-vacuum database 
    # containing a single table (root page 3) with a single row. 
    # The row has an overflow page (page 4).
    forcedelete test.db test.db-journal
    sqlite3 db test.db
    set c [string repeat 3 1500]
    db eval {
      pragma auto_vacuum = 1;
      CREATE TABLE t1(a, b, c);
      INSERT INTO t1 VALUES('1111111111', '2222222222', $c);
    }
    db close

    do_test crash5-$ii.$jj.1 {
      crashsql -delay 1 -file test.db-journal -seed $ii -tclbody [join [list \
        [list set iFail $jj] {
        proc get_pwd {} {
          if {$::tcl_platform(platform) eq "windows"} {
            if {[info exists ::env(ComSpec)]} {
              set comSpec $::env(ComSpec)
            } else {
              # NOTE: Hard-code the typical default value.
              set comSpec {C:\Windows\system32\cmd.exe}
            }
            return [string map [list \\ /] \
              [string trim [exec -- $comSpec /c echo %CD%]]]
          } else {
            return [pwd]
          }
        }
        sqlite3_crashparams 0 [file join [get_pwd] test.db-journal]
      
        # Begin a transaction and evaluate a "CREATE INDEX" statement
        # with the iFail'th malloc() set to fail. This operation will
        # have to move the current contents of page 4 (the overflow
        # page) to make room for the new root page. The bug is that
        # if malloc() fails at a particular point in sqlite3PagerMovepage(),
        # sqlite mistakenly thinks that the page being moved (page 4) has 
        # been safely synced into the journal. If the page is written
        # to later in the transaction, it may be written out to the database
        # before the relevant part of the journal has been synced.
        #
        db eval BEGIN
        sqlite3_memdebug_fail $iFail -repeat 0
        catch {db eval { CREATE UNIQUE INDEX i1 ON t1(a); }} msg
        # puts "$n $msg ac=[sqlite3_get_autocommit db]"
        set rc [catch {db eval { CREATE UNIQUE INDEX i1 ON t1(a); }} msg]
#       puts "$msg ac=[sqlite3_get_autocommit db] iFail=$iFail"
#       puts "fail=[sqlite3_memdebug_fail -1]"
      
        if {$rc} {
        # If the transaction is still active (it may not be if the malloc()
        # failure occurred in the OS layer), write to the database. Make sure
        # page 4 is among those written.
        #
        if {![sqlite3_get_autocommit db]} {
          db eval {
            DELETE FROM t1;  -- This will put page 4 on the free list.
            INSERT INTO t1 VALUES('111111111', '2222222222', '33333333');
            INSERT INTO t1 SELECT * FROM t1;                     -- 2
            INSERT INTO t1 SELECT * FROM t1;                     -- 4
            INSERT INTO t1 SELECT * FROM t1;                     -- 8
            INSERT INTO t1 SELECT * FROM t1;                     -- 16
            INSERT INTO t1 SELECT * FROM t1;                     -- 32
            INSERT INTO t1 SELECT * FROM t1 WHERE rowid%2;       -- 48
          }
        }
        
        # If the right malloc() failed during the 'CREATE INDEX' above and
        # the transaction was not rolled back, then the sqlite cache now 
        # has a dirty page 4 that it incorrectly believes is already safely
        # in the synced part of the journal file. When 
        # sqlite3_release_memory() is called sqlite tries to free memory
        # by writing page 4 out to the db file. If it crashes later on,
        # before syncing the journal... Corruption!
        #
        sqlite3_crashparams 1 [file join [get_pwd] test.db-journal]
        sqlite3_release_memory 8092
          # If the transaction is still active (it may not be if the malloc()
          # failure occurred in the OS layer), write to the database. Make sure
          # page 4 is among those written.
          #
          if {![sqlite3_get_autocommit db]} {
            db eval {
              DELETE FROM t1;  -- This will put page 4 on the free list.
              INSERT INTO t1 VALUES('111111111', '2222222222', '33333333');
              INSERT INTO t1 SELECT * FROM t1;                     -- 2
              INSERT INTO t1 SELECT * FROM t1;                     -- 4
              INSERT INTO t1 SELECT * FROM t1;                     -- 8
              INSERT INTO t1 SELECT * FROM t1;                     -- 16
              INSERT INTO t1 SELECT * FROM t1;                     -- 32
              INSERT INTO t1 SELECT * FROM t1 WHERE rowid%2;       -- 48
            }
          }
          
          # If the right malloc() failed during the 'CREATE INDEX' above and
          # the transaction was not rolled back, then the sqlite cache now 
          # has a dirty page 4 that it incorrectly believes is already safely
          # in the synced part of the journal file. When 
          # sqlite3_release_memory() is called sqlite tries to free memory
          # by writing page 4 out to the db file. If it crashes later on,
          # before syncing the journal... Corruption!
          #
          sqlite3_crashparams 1 [file join [get_pwd] test.db-journal]
          sqlite3_release_memory 8092
        }
      }]] {}
      expr 1
    } {1}
  
    sqlite3 db test.db
    do_test crash5-$ii.$jj.2 {
      db eval {pragma integrity_check}

Changes to test/createtab.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 that it is OK to create new tables
# and indices while creating existing tables and indices.
#
# $Id: createtab.test,v 1.3 2007/09/12 17:01:45 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable autovacuum {
  set upperBound 2
} else {
138
139
140
141
142
143
144
145










146
137
138
139
140
141
142
143

144
145
146
147
148
149
150
151
152
153
154







-
+
+
+
+
+
+
+
+
+
+

    execsql {
      SELECT name FROM sqlite_master WHERE type='table' ORDER BY 1
    }
  } {t1 t2 t3 t4}
  integrity_check createtab-$av.40

}
  

# 2019-03-31 Ensure that a proper error is returned for an index
# with too many columns.
#
do_test createtab-3.1 {
  db eval {DROP TABLE IF EXISTS t1;}
  set sql "CREATE TABLE t1(x,UNIQUE(x[string repeat ,x 100000]))"
  catchsql $sql
} {1 {too many columns in index}}
  
finish_test

Changes to test/cse.test.

14
15
16
17
18
19
20

21
22
23
24
25
26
27
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28







+







# common subexpression eliminations.
#
# $Id: cse.test,v 1.6 2008/08/04 03:51:24 danielk1977 Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix cse

do_test cse-1.1 {
  execsql {
    CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d, e, f);
    INSERT INTO t1 VALUES(1,11,12,13,14,15);
    INSERT INTO t1 VALUES(2,21,22,23,24,25);
  }
152
153
154
155
156
157
158
159







































160
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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  }
  set sql "SELECT [join $colset ,] FROM t2"
  do_test cse-2.2.$i {
    # explain $::sql
    execsql $::sql
  } $answer
}

#-------------------------------------------------------------------------
# Ticket fd1bda016d1a
#
reset_db
do_execsql_test 3.0 {
  CREATE TABLE t1(a TEXT, b);
  INSERT INTO t1 VALUES('hello', 0);
  INSERT INTO t1 VALUES('world', 0);

  CREATE TABLE t2(x TEXT);
  INSERT INTO t2 VALUES('hello');
  INSERT INTO t2 VALUES('world');

  CREATE TABLE t3(y);
  INSERT INTO t3 VALUES(1000);
} {}

do_execsql_test 3.1 {
  SELECT 1000 = y FROM t3
} {1}

do_execsql_test 3.2 {
  SELECT 1000 IN (SELECT x FROM t2), 1000 = y FROM t3
} {0 1}

do_execsql_test 3.3 {
  SELECT 0 IN (SELECT a), (SELECT a LIMIT 0) FROM t1 
} {0 {} 0 {}}

do_execsql_test 3.4 {
  SELECT 0 IN (SELECT a) FROM t1 WHERE a = 'hello' OR (SELECT a LIMIT 0);
} {0}

do_execsql_test 3.5 {
  CREATE TABLE v0(v1 VARCHAR0);
  INSERT INTO v0 VALUES(2), (3);
  SELECT 0 IN(SELECT v1) FROM v0 WHERE v1 = 2 OR(SELECT v1 LIMIT 0);
} {0}

finish_test

Changes to test/csv01.test.

209
210
211
212
213
214
215






























































216
217
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


# Problem with single-column CSV support reported on the mailing list
# by Trent W. Buck.
#
do_execsql_test 4.4 {
  CREATE VIRTUAL TABLE temp.trent USING csv(data='1');
  SELECT * FROM trent;
} {1}

# 2018-12-26
# Bug report on the mailing list
#
forcedelete csv01.csv
set fd [open csv01.csv wb]
puts $fd "a,b,c,d\r\n1,2,3,4\r\none,two,three,four\r\n5,6,7,8"
close $fd
do_execsql_test 5.1 {
  CREATE VIRTUAL TABLE t5_1 USING csv(filename='csv01.csv');
  SELECT name FROM temp.pragma_table_info('t5_1');
} {c0 c1 c2 c3}
do_execsql_test 5.2 {
  SELECT *, '|' FROM t5_1;
} {a b c d | 1 2 3 4 | one two three four | 5 6 7 8 |}
do_execsql_test 5.3 {
  DROP TABLE t5_1;
  CREATE VIRTUAL TABLE t5_1 USING csv(filename='csv01.csv', header);
  SELECT name FROM temp.pragma_table_info('t5_1');
} {a b c d}
do_execsql_test 5.4 {
  SELECT *, '|' FROM t5_1;
} {1 2 3 4 | one two three four | 5 6 7 8 |}

#-------------------------------------------------------------------------

proc randomtext {n} {
  string range [db one {SELECT hex(randomblob($n))}] 1 $n
}

for {set ii 0} {$ii < 200} {incr ii} {
  reset_db
  load_static_extension db csv
  set fd [open csv.data w]
  puts $fd "a,b"
  puts $fd "[randomtext $ii],abcd"
  close $fd
  do_execsql_test 6.$ii.1 {
    CREATE VIRTUAL TABLE abc USING csv(filename='csv.data', header=true);
  }
  do_execsql_test 6.$ii.2 {
    SELECT count(*) FROM abc
  } 1
}

for {set ii 0} {$ii < 20} {incr ii} {
  reset_db
  load_static_extension db csv
  set T [randomtext $ii]
  set fd [open csv.data w]
  puts $fd "a,b"
  puts -nonewline $fd "abcd,$T"
  close $fd
  do_execsql_test 7.$ii.1 {
    CREATE VIRTUAL TABLE abc USING csv(filename='csv.data', header=true);
  }
  breakpoint
  do_execsql_test 7.$ii.2 {
    SELECT * FROM abc
  } [list abcd $T]
}


finish_test

Changes to test/ctime.test.

77
78
79
80
81
82
83

84
85
86
87
88
89
90
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91







+







      SELECT sqlite_compileoption_used($opt)
    } $res
  }
}

# SQLITE_THREADSAFE should pretty much always be defined
# one way or the other, and it must have a value of 0 or 1.
sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1
do_test ctime-1.4.1 {
  catchsql {
    SELECT sqlite_compileoption_used('SQLITE_THREADSAFE');
  }
} {0 1}
do_test ctime-1.4.2 {
  catchsql {

Changes to test/cursorhint.test.

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
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







-
+












-
+







     SELECT * FROM t1 CROSS JOIN t2 WHERE a=x
  }
} {{EQ(r[1],c0)}}
do_test 1.2 {
  p5_of_opcode db OpenRead {
     SELECT * FROM t1 CROSS JOIN t2 WHERE a=x
  }
} {00 00}
} {0 0}

# Do the same test the other way around.
#
do_test 2.1 {
  p4_of_opcode db CursorHint {
     SELECT * FROM t2 CROSS JOIN t1 WHERE a=x
  }
} {{EQ(c0,r[1])}}
do_test 2.2 {
  p5_of_opcode db OpenRead {
     SELECT * FROM t2 CROSS JOIN t1 WHERE a=x
  }
} {00 00}
} {0 0}

# Various expressions captured by CursorHint
#
do_test 3.1 {
  p4_of_opcode db CursorHint {
    SELECT * FROM t1 WHERE a=15 AND c=22 AND rowid!=98
  }
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
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







-
+














-
+







    SELECT * FROM t1 WHERE b>11 ORDER BY b DESC;
  }
} {GT(c0,11)}
do_test 4.2 {
  p5_of_opcode db OpenRead {
    SELECT * FROM t1 WHERE b>11;
  }
} {02 00}
} {2 0}
do_test 4.3asc {
  p4_of_opcode db CursorHint {
    SELECT c FROM t1 WHERE b<11 ORDER BY b ASC;
  }
} {LT(c0,11)}
do_test 4.3desc {
  p4_of_opcode db CursorHint {
    SELECT c FROM t1 WHERE b<11 ORDER BY b DESC;
  }
} {}
do_test 4.4 {
  p5_of_opcode db OpenRead {
    SELECT c FROM t1 WHERE b<11;
  }
} {00}
} {0}

do_test 4.5asc {
  p4_of_opcode db CursorHint {
    SELECT c FROM t1 WHERE b>=10 AND b<=20 ORDER BY b ASC;
  }
} {LE(c0,20)}
do_test 4.5desc {

Changes to test/date.test.

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
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







-
-
-
+
+
+
+
+

-
-
-
-
+
+
-

-
-
-
-
+

+
+
+
-
+
-
-
-
-
+
+
-
-
-
+
-
-
-
-
+
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
+
+
-
-
-
-
-
+
-
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
-
+
-
-
-
-
-

-
-
-
-
-
-
-
-
+
+
-
-
-
+
+
-
-
-
+
-
-
-
-
+
+
+
+
-
-
-
-
-
+
+
-
-
+
-
-
-
-
+
+
+
+
-
-
+
-
-
-
-
-

+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
-
-
-
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
-
+







datetest 5.10 {datetime('1994-04-16 14:00:00 Z')} {1994-04-16 14:00:00}
datetest 5.11 {datetime('1994-04-16 14:00:00z    ')} {1994-04-16 14:00:00}
datetest 5.12 {datetime('1994-04-16 14:00:00     z    ')} {1994-04-16 14:00:00}
datetest 5.13 {datetime('1994-04-16 14:00:00Zulu')} NULL
datetest 5.14 {datetime('1994-04-16 14:00:00Z +05:00')} NULL
datetest 5.15 {datetime('1994-04-16 14:00:00 +05:00 Z')} NULL

# localtime->utc and utc->localtime conversions.  These tests only work
# if the localtime is in the US Eastern Time (the time in Charlotte, NC
# and in New York.)
# localtime->utc and utc->localtime conversions.
#
# Use SQLITE_TESTCTRL_LOCALTIME_FAULT=2 to set an alternative localtime_r()
# implementation that is not locale-dependent.  This testing localtime_r()
# operates as follows:
#
# On non-Vista Windows platform, '2006-03-31' is treated incorrectly as being
# in DST giving a 4 hour offset instead of 5.  In 2007, DST was extended to 
# start three weeks earlier (second Sunday in March) and end one week
# later (first Sunday in November).  Older Windows systems apply this
#     (1)  Localtime is 30 minutes earlier than (west of) UTC on
#          even days (counting from 1970-01-01)
# new rule incorrectly to dates prior to 2007.
#
# It might be argued that this is masking a problem on non-Vista Windows
# platform.  A ticket has already been opened for this issue 
# (http://www.sqlite.org/cvstrac/tktview?tn=2322).  This is just to prevent
# more confusion/reports of the issue.
#     (2)  Localtime is 30 minutes later than (east of) UTC on odd days.
#
#     (3)  The function fails for the specific date/time value
#          of 2000-05-29 14:16:00 in order to test the ability of
#          SQLite to deal with localtime_r() failures.

#
# $tzoffset_old should be 5 if DST is working correctly.
set tzoffset_old [db one {
  SELECT CAST(24*(julianday('2006-03-31') -
                  julianday('2006-03-31','localtime'))+0.5
proc local_to_utc {tn utc local} {
  do_execsql_test date-$tn "SELECT datetime('$utc','localtime')" [list $local]
              AS INT)
}]

}
# $tzoffset_new should be 4 if DST is working correctly.
set tzoffset_new [db one {
  SELECT CAST(24*(julianday('2007-03-31') -
                  julianday('2007-03-31','localtime'))+0.5
proc utc_to_local {tn local utc} {
              AS INT)
}]

  do_execsql_test date-$tn "SELECT datetime('$local','utc')" [list $utc]
}
# Warn about possibly broken Windows DST implementations.
if {$::tcl_platform(platform)=="windows" && $tzoffset_new==4 && $tzoffset_old==4} {
  puts "******************************************************************"
  puts "N.B.:  The DST support provided by your current O/S seems to be"
  puts "suspect in that it is reporting incorrect DST values for dates"
  puts "prior to 2007.  This is the known case for most (all?) non-Vista"
  puts "Windows versions.  Please see ticket #2322 for more information."
  puts "******************************************************************"
}


sqlite3_test_control SQLITE_TESTCTRL_LOCALTIME_FAULT 2
if {$tzoffset_new==4} {
  datetest 6.1 {datetime('2000-10-29 05:59:00','localtime')}\
      {2000-10-29 01:59:00}
local_to_utc 6.1  {2000-10-29 12:00:00} {2000-10-29 12:30:00}
utc_to_local 6.2  {2000-10-29 12:30:00} {2000-10-29 12:00:00}
  datetest 6.1.1 {datetime('2006-10-29 05:59:00','localtime')}\
      {2006-10-29 01:59:00}
  datetest 6.1.2 {datetime('2007-11-04 05:59:00','localtime')}\
      {2007-11-04 01:59:00}

local_to_utc 6.3  {2000-10-30 12:00:00} {2000-10-30 11:30:00}
  # If the new and old DST rules seem to be working correctly...
  if {$tzoffset_new==4 && $tzoffset_old==5} {
    datetest 6.2 {datetime('2000-10-29 06:00:00','localtime')}\
        {2000-10-29 01:00:00}
utc_to_local 6.4  {2000-10-30 11:30:00} {2000-10-30 12:00:00}
    datetest 6.2.1 {datetime('2006-10-29 06:00:00','localtime')}\
        {2006-10-29 01:00:00}
  }

  datetest 6.2.2 {datetime('2007-11-04 06:00:00','localtime')}\
      {2007-11-04 01:00:00}

local_to_utc 6.5  {2000-10-28 23:59:59} {2000-10-28 23:29:59}
  # If the new and old DST rules seem to be working correctly...
  if {$tzoffset_new==4 && $tzoffset_old==5} {
    datetest 6.3 {datetime('2000-04-02 06:59:00','localtime')}\
        {2000-04-02 01:59:00}
local_to_utc 6.6  {2000-10-29 00:00:00} {2000-10-29 00:30:00}
    datetest 6.3.1 {datetime('2006-04-02 06:59:00','localtime')}\
        {2006-04-02 01:59:00}
  }
  datetest 6.3.2 {datetime('2007-03-11 07:00:00','localtime')}\
      {2007-03-11 03:00:00}

  datetest 6.4 {datetime('2000-04-02 07:00:00','localtime')}\
      {2000-04-02 03:00:00}
  datetest 6.4.1 {datetime('2006-04-02 07:00:00','localtime')}\
      {2006-04-02 03:00:00}
  datetest 6.4.2 {datetime('2007-03-11 07:00:00','localtime')}\
      {2007-03-11 03:00:00}
      
  datetest 6.5 {datetime('2000-10-29 01:59:00','utc')} {2000-10-29 05:59:00}
# The previous two cases establish that no such localtime as
# 2000-10-29 00:10:00 exists.  Verify that we get a reasonable
  datetest 6.5.1 {datetime('2006-10-29 01:59:00','utc')} {2006-10-29 05:59:00}
  datetest 6.5.2 {datetime('2007-11-04 01:59:00','utc')} {2007-11-04 05:59:00}

# answer if we try to convert this non-existant localtime to utc?
#
  # If the new and old DST rules seem to be working correctly...
  if {$tzoffset_new==4 && $tzoffset_old==5} {
    datetest 6.6 {datetime('2000-10-29 02:00:00','utc')} {2000-10-29 07:00:00}
utc_to_local 6.7  {2000-10-29 00:10:00} {2000-10-28 23:40:00}
    datetest 6.6.1 {datetime('2006-10-29 02:00:00','utc')} {2006-10-29 07:00:00}
  }
  datetest 6.6.2 {datetime('2007-11-04 02:00:00','utc')} {2007-11-04 07:00:00}


local_to_utc 6.8  {2022-02-10 23:59:59} {2022-02-11 00:29:59}
local_to_utc 6.9  {2022-02-11 00:00:00} {2022-02-10 23:30:00}
local_to_utc 6.10 {2022-02-10 23:45:00} {2022-02-11 00:15:00}
  # If the new and old DST rules seem to be working correctly...
  if {$tzoffset_new==4 && $tzoffset_old==5} {
    datetest 6.7 {datetime('2000-04-02 01:59:00','utc')} {2000-04-02 06:59:00}
    datetest 6.7.1 {datetime('2006-04-02 01:59:00','utc')} {2006-04-02 06:59:00}
  }
local_to_utc 6.11 {2022-02-11 00:45:00} {2022-02-11 00:15:00}

  datetest 6.7.2 {datetime('2007-03-11 01:59:00','utc')} {2007-03-11 06:59:00}

# The previous two cases show that two different UTC values give
  datetest 6.8 {datetime('2000-04-02 02:00:00','utc')} {2000-04-02 06:00:00}
  datetest 6.8.1 {datetime('2006-04-02 02:00:00','utc')} {2006-04-02 06:00:00}
  datetest 6.8.2 {datetime('2007-03-11 02:00:00','utc')} {2007-03-11 06:00:00}

# the same localtime of 2022-02-11 00:15:00.  When converting from
# that localtime back to UTC, we should get one or the other of
# the two UTC values.
#
  # The 'utc' modifier is a no-op if the LHS is known to already be in UTC
  datetest 6.9.1 {datetime('2015-12-23 12:00:00','utc')} {2015-12-23 17:00:00}
utc_to_local 6.12 {2022-02-11 00:15:00} {2022-02-11 00:45:00}
  datetest 6.9.2 {datetime('2015-12-23 12:00:00z','utc')} {2015-12-23 12:00:00}
  datetest 6.9.3 {datetime('2015-12-23 12:00:00-03:00','utc')} \
         {2015-12-23 15:00:00}
  datetest 6.9.4 {datetime('2015-12-23 12:00:00','utc','utc','utc')} \
         {2015-12-23 17:00:00}

# If localtime_r() fails, the datetime() SQL function should raise an error

#
  datetest 6.10 {datetime('2000-01-01 12:00:00','localtime')} \
      {2000-01-01 07:00:00}
  datetest 6.11 {datetime('1969-01-01 12:00:00','localtime')} \
      {1969-01-01 07:00:00}
  datetest 6.12 {datetime('2039-01-01 12:00:00','localtime')} \
      {2039-01-01 07:00:00}
  datetest 6.13 {datetime('2000-07-01 12:00:00','localtime')} \
      {2000-07-01 08:00:00}
  datetest 6.14 {datetime('1969-07-01 12:00:00','localtime')} \
      {1969-07-01 07:00:00}
  datetest 6.15 {datetime('2039-07-01 12:00:00','localtime')} \
      {2039-07-01 07:00:00}
  set sqlite_current_time \
do_catchsql_test date-6.20 {
     [db eval {SELECT strftime('%s','2000-07-01 12:34:56')}]
  datetest 6.16 {datetime('now','localtime')} {2000-07-01 08:34:56}
  SELECT datetime('2000-05-29 14:16:00','localtime');
  datetest 6.17 {datetime('now','localtimex')} NULL
  datetest 6.18 {datetime('now','localtim')} NULL
  set sqlite_current_time 0
}

} {1 {local time unavailable}}

# Modifiers work for dates that are way out of band for localtime_r()
#
# These two are a bit of a scam. They are added to ensure that 100% of
# the date.c file is covered by testing, even when the time-zone
# is not -0400 (the condition for running of the block of tests above).
#
datetest 6.19 {datetime('2039-07-01 12:00:00','localtime',null)} NULL
local_to_utc 6.21 {1800-10-29 12:00:00} {1800-10-29 12:30:00}
utc_to_local 6.22 {1800-10-29 12:30:00} {1800-10-29 12:00:00}
local_to_utc 6.23 {3000-10-30 12:00:00} {3000-10-30 11:30:00}
utc_to_local 6.24 {3000-10-30 11:30:00} {3000-10-30 12:00:00}

# Restore the use of the OS localtime_r() before going on...
datetest 6.20 {datetime('2039-07-01 12:00:00','utc',null)} NULL
sqlite3_test_control SQLITE_TESTCTRL_LOCALTIME_FAULT 0

# Date-time functions that contain NULL arguments return a NULL
# result.
#
datetest 7.1 {datetime(null)} NULL
datetest 7.2 {datetime('now',null)} NULL
datetest 7.3 {datetime('now','localtime',null)} NULL
603
604
605
606
607
608
609


610


611
612
535
536
537
538
539
540
541
542
543

544
545
546
547







+
+
-
+
+


datetest 17.2 {datetime(2457828)} {2017-03-15 12:00:00}
datetest 17.3 {datetime(2457828,'start of day')} {2017-03-15 00:00:00}
datetest 17.4 {datetime(2457828,'start of month')} {2017-03-01 00:00:00}
datetest 17.5 {datetime(2457828,'start of year')} {2017-01-01 00:00:00}
datetest 17.6 {datetime(37,'start of year')} NULL
datetest 17.7 {datetime(38,'start of year')} {-4712-01-01 00:00:00}

# 2022-03-04 https://sqlite.org/forum/forumpost/2ffbaa2c3fd7fb82
# The 'localtime' modifier should preserve fractional seconds.

#
datetest 18.1 {strftime('%f',1.234,'unixepoch','localtime')} {01.234}

finish_test

Changes to test/date2.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
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







-
+





-
+
+
+
+
+
+
+
+








-
+












-
+








do_execsql_test date2-100 {
  CREATE TABLE t1(x, y, CHECK( date(x) BETWEEN '2017-07-01' AND '2017-07-31' ));
  INSERT INTO t1(x,y) VALUES('2017-07-20','one');
} {}
do_catchsql_test date2-110 {
  INSERT INTO t1(x,y) VALUES('now','two');
} {1 {non-deterministic function in index expression or CHECK constraint}}
} {1 {non-deterministic use of date() in a CHECK constraint}}
do_execsql_test date2-120 {
  SELECT * FROM t1;
} {2017-07-20 one}
do_catchsql_test date2-130 {
  INSERT INTO t1(x,y) VALUES('2017-08-01','two');
} {1 {CHECK constraint failed: t1}}
} {1 {CHECK constraint failed: date(x) BETWEEN '2017-07-01' AND '2017-07-31'}}

# 2021-03-16 Forum post https://sqlite.org/forum/forumpost/464afd4086
do_catchsql_test date2-140 {
  DROP TABLE t1;
  CREATE TABLE t1(x, y, z AS (date()));
  INSERT INTO t1(x,y) VALUES(1,2);
} {1 {non-deterministic use of date() in a generated column}}

do_execsql_test date2-200 {
  CREATE TABLE t2(x,y);
  INSERT INTO t2(x,y) VALUES(1, '2017-07-20'), (2, 'xyzzy');
  CREATE INDEX t2y ON t2(date(y));
}
do_catchsql_test date2-210 {
  INSERT INTO t2(x,y) VALUES(3, 'now');
} {1 {non-deterministic function in index expression or CHECK constraint}}
} {1 {non-deterministic use of date() in an index}}
do_execsql_test date2-220 {
  SELECT x, y FROM t2 ORDER BY x;
} {1 2017-07-20 2 xyzzy}

do_execsql_test date2-300 {
  CREATE TABLE t3(a INTEGER PRIMARY KEY,b);
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<1000)
    INSERT INTO t3(a,b) SELECT x, julianday('2017-07-01')+x FROM c;
  UPDATE t3 SET b='now' WHERE a=500;
}
do_catchsql_test date2-310 {
  CREATE INDEX t3b1 ON t3(datetime(b));
} {1 {non-deterministic function in index expression or CHECK constraint}}
} {1 {non-deterministic use of datetime() in an index}}
do_catchsql_test date2-320 {
  CREATE INDEX t3b1 ON t3(datetime(b)) WHERE typeof(b)='real';
} {0 {}}
do_execsql_test date2-330 {
  EXPLAIN QUERY PLAN
  SELECT a FROM t3
   WHERE typeof(b)='real'
80
81
82
83
84
85
86
87

88
89
90
91
92
93
94
95

96
97
98
99
100
101
102
87
88
89
90
91
92
93

94
95
96
97
98
99
100
101

102
103
104
105
106
107
108
109







-
+







-
+







  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<1000)
    INSERT INTO t4(a,b) SELECT x, julianday('2017-07-01')+x FROM c;
  UPDATE t4 SET b='now' WHERE a=500;
}
do_catchsql_test date2-410 {
  CREATE INDEX t4b1 ON t4(b)
    WHERE date(b) BETWEEN '2017-06-01' AND '2017-08-31';
} {1 {non-deterministic function in index expression or CHECK constraint}}
} {1 {non-deterministic use of date() in an index}}
do_execsql_test date2-420 {
  DELETE FROM t4 WHERE a=500;
  CREATE INDEX t4b1 ON t4(b)
    WHERE date(b) BETWEEN '2017-06-01' AND '2017-08-31';
}
do_catchsql_test date2-430 {
  INSERT INTO t4(a,b) VALUES(9999,'now');
} {1 {non-deterministic function in index expression or CHECK constraint}}
} {1 {non-deterministic use of date() in an index}}

do_execsql_test date2-500 {
  CREATE TABLE mods(x);
  INSERT INTO mods(x) VALUES
    ('+10 days'),
    ('-10 days'),
    ('+10 hours'),
117
118
119
120
121
122
123
124

125
126
127

128

129


















130
131














132




133
134
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







-
+


-
+

+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+


  CREATE TABLE t5(y,m);
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<5)
    INSERT INTO t5(y,m) SELECT julianday('2017-07-01')+c.x, mods.x FROM c, mods;
  CREATE INDEX t5x1 on t5(y) WHERE datetime(y,m) IS NOT NULL;
}
do_catchsql_test date2-510 {
  INSERT INTO t5(y,m) VALUES('2017-07-20','localtime');
} {1 {non-deterministic function in index expression or CHECK constraint}}
} {1 {non-deterministic use of datetime() in an index}}
do_catchsql_test date2-520 {
  INSERT INTO t5(y,m) VALUES('2017-07-20','utc');
} {1 {non-deterministic function in index expression or CHECK constraint}}
} {1 {non-deterministic use of datetime() in an index}}

# 2019-10-30 Ticket 830277d9db6c3ba1

#
do_catchsql_test date2-600 {
  CREATE TABLE t600(a REAL CHECK( a<julianday('now') ));
  INSERT INTO t600(a) VALUES(1.0);
} {1 {non-deterministic use of julianday() in a CHECK constraint}}
do_catchsql_test date2-601 {
  CREATE TABLE t601(a REAL, b TEXT, CHECK( a<julianday(b) ));
  INSERT INTO t601(a,b) VALUES(1.0, '1970-01-01');
} {0 {}}
do_catchsql_test date2-602 {
  INSERT INTO t601(a,b) VALUES(1e100, '1970-01-01');
} {1 {CHECK constraint failed: a<julianday(b)}}
do_catchsql_test date2-603 {
  INSERT INTO t601(a,b) VALUES(10, 'now');
} {1 {non-deterministic use of julianday() in a CHECK constraint}}
do_catchsql_test date2-604 {
  INSERT INTO t600(a) VALUES(julianday('now')+10);
} {1 {non-deterministic use of julianday() in a CHECK constraint}}

  

do_catchsql_test date2-610 {
  CREATE TABLE t610(a,b);
  CREATE INDEX t610x1 ON t610(julianday('now')+b);
  INSERT INTO t610(a,b) VALUES(123,456);
} {1 {non-deterministic use of julianday() in an index}}
do_catchsql_test date2-611 {
  CREATE TABLE t611(a,b);
  CREATE INDEX t611x1 ON t611(julianday(a)+b);
  INSERT INTO t611(a,b) VALUES('1970-01-01',10.0);
} {0 {}}
do_catchsql_test date2-612 {
  INSERT INTO t611(a,b) VALUES('now',10.0);
} {1 {non-deterministic use of julianday() in an index}}

do_catchsql_test date3-620 {
  CREATE TABLE t620(a, b AS (a+julianday('now')));
  INSERT INTO t620 VALUES(10);
} {1 {non-deterministic use of julianday() in a generated column}}

finish_test

Added test/date3.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022-01-27
#
# 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 date and time functions.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Skip this whole file if date and time functions are omitted
# at compile-time
#
ifcapable {!datetime} {
  finish_test
  return
}

proc datetest {tnum expr result} {
  do_test date3-$tnum [subst {
    execsql "SELECT coalesce($expr,'NULL')"
  }] [list $result]
}
set tcl_precision 15

# EVIDENCE-OF: R-45708-63005 unixepoch(time-value, modifier, modifier,
# ...)
#
datetest 1.1 {unixepoch('1970-01-01')} {0}
datetest 1.2 {unixepoch('1969-12-31 23:59:59')} {-1}
datetest 1.3 {unixepoch('2106-02-07 06:28:15')} {4294967295}
datetest 1.4 {unixepoch('2106-02-07 06:28:16')} {4294967296}
datetest 1.5 {unixepoch('9999-12-31 23:59:59')} {253402300799}
datetest 1.6 {unixepoch('0000-01-01 00:00:00')} {-62167219200}

# EVIDENCE-OF: R-30877-63179 The unixepoch() function returns a unix
# timestamp - the number of seconds since 1970-01-01 00:00:00 UTC.
#
for {set i 1} {$i<=100} {incr i} {
  set x [expr {int(rand()*0xfffffffff)-0xffffffff}]
  datetest 1.7.$i "unixepoch($x,'unixepoch')==$x" {1}
}

# EVIDENCE-OF: R-62992-54137 The unixepoch() always returns an integer,
# even if the input time-value has millisecond precision.
#
datetest 1.8 {unixepoch('2022-01-27 12:59:28.052')} {1643288368}

# EVIDENCE-OF: R-05412-24332 If the time-value is numeric (the
# DDDDDDDDDD format) then the 'auto' modifier causes the time-value to
# interpreted as either a julian day number or a unix timestamp,
# depending on its magnitude.
#
# EVIDENCE-OF: R-56763-40111 If the value is between 0.0 and
# 5373484.499999, then it is interpreted as a julian day number
# (corresponding to dates between -4713-11-24 12:00:00 and 9999-12-31
# 23:59:59, inclusive).
#
# EVIDENCE-OF: R-07289-49223 For numeric values outside of the range of
# valid julian day numbers, but within the range of -210866760000 to
# 253402300799, the 'auto' modifier causes the value to be interpreted
# as a unix timestamp.
#
# EVIDENCE-OF: R-20795-34947 Other numeric values are out of range and
# cause a NULL return.
#
foreach {tn jd date} {
  2.1  0.0              {-4713-11-24 12:00:00}
  2.2  5373484.4999999  {9999-12-31 23:59:59}
  2.3  2440587.5        {1970-01-01 00:00:00}
  2.4  2440587.49998843 {1969-12-31 23:59:59}
  2.5  2440615.7475463  {1970-01-29 05:56:28}

  2.10 -1               {1969-12-31 23:59:59}
  2.11 5373485          {1970-03-04 04:38:05}
  2.12 -210866760000    {-4713-11-24 12:00:00}
  2.13 253402300799     {9999-12-31 23:59:59}

  2.20 -210866760001    {NULL}
  2.21 253402300800     {NULL}
} {
  datetest $tn "datetime($jd,'auto')" $date
}

# EVIDENCE-OF: R-38886-35357 The 'auto' modifier is a no-op for text
# time-values.
#
datetest 2.30 {date('2022-01-29','auto')==date('2022-01-29')} {1}

# EVIDENCE-OF: R-53132-26856 The 'auto' modifier can be used to work
# with date/time values even in cases where it is not known if the
# julian day number or unix timestamp formats are in use.
#
do_execsql_test date3-2.40 {
  WITH tx(timeval,datetime) AS (
     VALUES('2022-01-27 13:15:44','2022-01-27 13:15:44'),
           (2459607.05260275,'2022-01-27 13:15:44'),
           (1643289344,'2022-01-27 13:15:44')
  )
  SELECT datetime(timeval,'auto') == datetime FROM tx;
} {1 1 1}

# EVIDENCE-OF: R-49255-55373 The "unixepoch" modifier (11) only works if
# it immediately follows a time value in the DDDDDDDDDD format.
#
# EVIDENCE-OF: R-23075-39245 This modifier causes the DDDDDDDDDD to be
# interpreted not as a Julian day number as it normally would be, but as
# Unix Time - the number of seconds since 1970.
#
datetest 3.1 {datetime(2459607.05,'+1 hour','unixepoch')} {NULL}
datetest 3.2 {datetime(2459607.05,'unixepoch','+1 hour')} {1970-01-29 12:13:27}

# EVIDENCE-OF: R-21150-52363 The "julianday" modifier must immediately
# follow the initial time-value which must be of the form DDDDDDDDD.
#
# EVIDENCE-OF: R-31176-64601 Any other use of the 'julianday' modifier
# is an error and causes the function to return NULL.
#
# EVIDENCE-OF: R-32483-36353 The 'julianday' modifier forces the
# time-value number to be interpreted as a julian-day number.
#
# EVIDENCE-OF: R-25859-20124 The only difference is that adding
# 'julianday' forces the DDDDDDDDD time-value format, and causes a NULL
# to be returned if any other time-value format is used.
#
datetest 4.1 {datetime(2459607,'julianday')}           {2022-01-27 12:00:00}
datetest 4.2 {datetime(2459607,'+1 hour','julianday')} {NULL}
datetest 4.3 {datetime('2022-01-27','julianday')}      {NULL}



# EVIDENCE-OF: R-33431-18865 Unix timestamps for the first 63 days of
# 1970 will be interpreted as julian day numbers.
#
do_execsql_test date3-5.0 {
  WITH inc(x) AS (VALUES(-10) UNION ALL SELECT x+1 FROM inc WHERE x<100)
  SELECT count(*) FROM inc
  WHERE datetime('1970-01-01',format('%+d days',x))
     <> datetime(unixepoch('1970-01-01',format('%+d days',x)),'auto');
} {63}

finish_test

Added test/dbdata.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019-04-11
#
# 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 the sqlite_dbpage virtual table.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix dbdata

ifcapable !vtab||!compound {
  finish_test
  return
}
if { [catch { db enable_load_extension 1 }]
  || [catch { db eval { SELECT load_extension('../dbdata') } }] 
} {
  finish_test
  return
}

do_execsql_test 1.0 {
  CREATE TABLE T1(a, b);
  INSERT INTO t1(rowid, a ,b) VALUES(5, 'v', 'five');
  INSERT INTO t1(rowid, a, b) VALUES(10, 'x', 'ten');
}

do_execsql_test 1.1 {
  SELECT pgno, cell, field, quote(value) FROM sqlite_dbdata WHERE pgno=2;
} {
  2 0 -1 5 
  2 0  0 'v' 
  2 0  1 'five' 
  2 1 -1 10 
  2 1  0 'x' 
  2 1  1 'ten'
}

breakpoint
do_execsql_test 1.2 {
  SELECT pgno, cell, field, quote(value) FROM sqlite_dbdata;
} {
  1 0 -1 1 
  1 0 0 'table' 
  1 0 1 'T1' 
  1 0 2 'T1' 
  1 0 3 2 
  1 0 4 {'CREATE TABLE T1(a, b)'}
  2 0 -1 5 
  2 0  0 'v' 
  2 0  1 'five' 
  2 1 -1 10 
  2 1  0 'x' 
  2 1  1 'ten'
}

set big [string repeat big 2000]
do_execsql_test 1.3 {
  INSERT INTO t1 VALUES(NULL, $big);
  SELECT value FROM sqlite_dbdata WHERE pgno=2 AND cell=2 AND field=1;
} $big

do_execsql_test 1.4 {
  DELETE FROM t1;
  INSERT INTO t1 VALUES(NULL, randomblob(5050));
}
do_test 1.5 {
  execsql {
    SELECT quote(value) FROM sqlite_dbdata WHERE pgno=2 AND cell=0 AND field=1;
  }
} [db one {SELECT quote(b) FROM t1}]

#-------------------------------------------------------------------------
reset_db
db enable_load_extension 1
db eval { SELECT load_extension('../dbdata') }

do_execsql_test 2.0 {
  CREATE TABLE t1(a);
  CREATE INDEX i1 ON t1(a);
  WITH s(i) AS (
    SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<10
  )
  INSERT INTO t1 SELECT randomblob(900) FROM s;
}

do_execsql_test 2.1 {
  SELECT * FROM sqlite_dbptr WHERE pgno=2;
} {
  2 25   2 6   2 7   2 9   2 11   2 13   2 15   2 17   2 19   2 21
}

do_execsql_test 2.2 {
  SELECT * FROM sqlite_dbptr WHERE pgno=3;
} {
  3 24   3 23
}

do_execsql_test 2.3 {
  SELECT * FROM sqlite_dbptr
} {
  2 25   2 6   2 7   2 9   2 11   2 13   2 15   2 17   2 19   2 21
  3 24   3 23
}


finish_test

Changes to test/dbfuzz001.test.

164
165
166
167
168
169
170





171
172









173
174
175
176
177
178
179
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







+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+







    |    432: 01 ec 01 c5 01 0d 43 00 00 48 01 54 00 01 f7 01   ......C..H.T....
    |    448: ec 01 c5 01 0d 42 00 00 48 01 54 00 01 f7 01 ec   .....B..H.T.....
    |    464: 01 c5 01 0d 41 00 00 48 01 54 00 01 f7 01 ec 01   ....A..H.T......
    |    480: c5 01 0d 40 00 00 48 01 54 00 01 f7 01 ec 01 c5   ...@..H.T.......
    |    496: 01 0d 3f 00 00 48 01 54 00 01 f7 01 ec 01 c5 01   ..?..H.T........
    | end c4.db
  }]
} {}

ifcapable !oversize_cell_check {
  # Non SQLITE_ENABLE_OVERSIZE_CELL_CHECK builds:
  do_test dbfuzz001-101a {
  db eval {PRAGMA integrity_check}
} {/Fragmentation of 384 bytes reported as 0 on page 8/}
    db eval {PRAGMA writable_schema=on; PRAGMA integrity_check}
  } {/Fragmentation of 384 bytes reported as 0 on page 8/}
} else {
  # SQLITE_ENABLE_OVERSIZE_CELL_CHECK builds:
  do_catchsql_test dbfuzz001-101b {
    PRAGMA writable_schema=on; 
    PRAGMA integrity_check;
  } {1 {database disk image is malformed}}
}

# The DELETE query below deletes the very last cell from page 8.
# Prior to a certain fix to sqlite3BtreeDelete() and because of the
# corruption to the freeblock list on page 8, this would fail to
# cause a rebalance operation, which would leave the btree in a weird
# state that would lead to segfaults and or assertion faults.
#
266
267
268
269
270
271
272
273

274
275
276
277
278
279
280
278
279
280
281
282
283
284

285
286
287
288
289
290
291
292







-
+







    |    496: 07 40 18 00 04 02 01 04 03 03 02 01 04 03 02 02   .@..............
    | end x/c03.db
  }]
  catchsql {INSERT INTO t3 SELECT * FROM t2;}
} {1 {database disk image is malformed}}


do_test dbfuzz001-110 {
do_test dbfuzz001-310 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 3584 pagesize 512 filename x/c02.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: 02 00 01 01 00 40 20 20 00 00 00 0c 00 00 00 07   .....@  ........
|     32: 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 04   ................
289
290
291
292
293
294
295
296

297
298
299
300
301
302
303
301
302
303
304
305
306
307

308
309
310
311
312
313
314
315







-
+







|    320: 41 54 45 20 49 4e 44 45 58 20 74 33 78 20 4f 4e   ATE INDEX t3x ON
|    336: 20 74 33 28 78 29 2e 04 06 17 15 11 01 45 69 6e    t3(x).......Ein
|    352: 64 65 78 74 32 63 64 74 32 05 43 52 45 41 54 45   dext2cdt2.CREATE
|    368: 20 49 4e 44 45 58 20 74 32 63 64 20 4f 4e 20 74    INDEX t2cd ON t
|    384: 32 28 63 2c 64 29 28 05 06 17 11 11 01 3d 74 61   2(c,d)(......=ta
|    400: 62 6c 65 74 33 74 33 07 43 52 45 41 54 45 20 54   blet3t3.CREATE T
|    416: 41 42 4c 45 20 74 33 28 63 2c 78 2c 65 2c 66 29   ABLE t3(c,x,e,f)
|    432: 28 02 06 17 11 11 01 3d 74 61 74 65 6c 03 62 74   (......=tatel.bt
|    432: 28 02 06 17 11 11 01 3d 74 61 62 6c 65 74 32 74   (......=tablet2t
|    448: 32 32 43 52 45 41 54 45 20 54 41 42 4c 45 20 74   22CREATE TABLE t
|    464: 32 28 63 2c 64 2c 65 2c 66 29 24 01 06 17 11 11   2(c,d,e,f)$.....
|    480: 01 35 74 61 62 6c 65 74 31 74 31 02 43 52 45 41   .5tablet1t1.CREA
|    496: 54 45 20 54 41 42 4c 45 20 74 31 28 61 2c 62 29   TE TABLE t1(a,b)
| page 2 offset 512
|      0: 0d 00 00 00 04 01 cf 00 01 fa 01 f3 01 de 01 cf   ................
|    160: 00 00 20 00 00 00 00 00 00 00 00 00 00 00 00 00   .. .............
343
344
345
346
347
348
349
350
351
352
353











354
355
355
356
357
358
359
360
361




362
363
364
365
366
367
368
369
370
371
372
373
374







-
-
-
-
+
+
+
+
+
+
+
+
+
+
+


|     16: 01 e0 01 d4 01 cb 01 c2 00 00 00 00 00 00 00 00   ................
|    448: 00 00 07 08 02 17 65 69 67 68 74 07 07 02 17 65   ......eight....e
|    464: 69 67 68 74 0a 06 02 07 40 18 00 00 00 00 00 00   ight....@.......
|    480: 0a 05 02 07 40 18 00 00 00 00 00 00 03 04 02 01   ....@...........
|    496: 04 03 03 02 01 04 03 02 02 01 02 03 01 02 01 02   ................
| end x/c02.db
  }]
  execsql {
    DELETE FROM t3 WHERE x IN (SELECT x FROM t4);
  }
} {}
} {}

extra_schema_checks 0
do_catchsql_test dbfuzz001-320 {
  PRAGMA integrity_check;
} {1 {database disk image is malformed}}

do_catchsql_test dbfuzz001-330 {
  DELETE FROM t3 WHERE x IN (SELECT x FROM t4);
} {1 {database disk image is malformed}}
extra_schema_checks 1

finish_test

Changes to test/dbfuzz2.c.

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























































27
28
29
30
31
32
33

34

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222

223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260

261
262

263



264
265
266
267
268
269
270
271
272
273
274
275
276


277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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







-
+
-










+
+
+
+







-
+













+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+









+
+














+
+
+
+
+
+
+
+
+
+
+
+
+





+
+
-
+
+
+
+
+















+
+
+
+
+
+
+
+
+
+
+
+
+





-
+

-

-
-
-





+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+

-
+

-
+
-



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
**
** Any of these tables can be virtual tables, for example FTS or RTree tables.
**
** To run this test:
**
**     mkdir dir
**     cp dbfuzz2-seed*.db dir
**     clang-6.0 -I. -g -O1 -fsanitize=fuzzer \
**     clang-6.0 -I. -g -O1 -fsanitize=fuzzer -DTHREADSAFE=0 \
**       -DTHREADSAFE=0 -DSQLITE_ENABLE_DESERIALIZE \
**       -DSQLITE_ENABLE_DBSTAT_VTAB dbfuzz2.c sqlite3.c -ldl
**     ./a.out dir
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#include <stdint.h>
#ifndef _WIN32
#include <sys/time.h>
#include <sys/resource.h>
#endif
#include "sqlite3.h"

/*
** This is the is the SQL that is run against the database.
*/
static const char *azSql[] = {
  "PRAGMA integrity_check;",
  "SELECT * FROM sqlite_master;",
  "SELECT * FROM sqlite_schema;",
  "SELECT sum(length(name)) FROM dbstat;",
  "UPDATE t1 SET b=a, a=b WHERE a<b;",
  "ALTER TABLE t1 RENAME TO alkjalkjdfiiiwuer987lkjwer82mx97sf98788s9789s;",
  "INSERT INTO t3 SELECT * FROM t2;",
  "DELETE FROM t3 WHERE x IN (SELECT x FROM t4);",
  "REINDEX;",
  "DROP TABLE t3;",
  "VACUUM;",
};

/* Output verbosity level.  0 means complete silence */
int eVerbosity = 0;

/* True to activate PRAGMA vdbe_debug=on */
static int bVdbeDebug = 0;

/* Maximum size of the in-memory database file */
static sqlite3_int64 szMax = 104857600;

/* Progress handler callback data */
static int nCb = 0;                  /* Number of callbacks seen so far */
static int mxCb = 250000;            /* Maximum allowed callbacks */

/***** Copy/paste from ext/misc/memtrace.c ***************************/
/* The original memory allocation routines */
static sqlite3_mem_methods memtraceBase;
static FILE *memtraceOut;

/* Methods that trace memory allocations */
static void *memtraceMalloc(int n){
  if( memtraceOut ){
    fprintf(memtraceOut, "MEMTRACE: allocate %d bytes\n", 
            memtraceBase.xRoundup(n));
  }
  return memtraceBase.xMalloc(n);
}
static void memtraceFree(void *p){
  if( p==0 ) return;
  if( memtraceOut ){
    fprintf(memtraceOut, "MEMTRACE: free %d bytes\n", memtraceBase.xSize(p));
  }
  memtraceBase.xFree(p);
}
static void *memtraceRealloc(void *p, int n){
  if( p==0 ) return memtraceMalloc(n);
  if( n==0 ){
    memtraceFree(p);
    return 0;
  }
  if( memtraceOut ){
    fprintf(memtraceOut, "MEMTRACE: resize %d -> %d bytes\n",
            memtraceBase.xSize(p), memtraceBase.xRoundup(n));
  }
  return memtraceBase.xRealloc(p, n);
}
static int memtraceSize(void *p){
  return memtraceBase.xSize(p);
}
static int memtraceRoundup(int n){
  return memtraceBase.xRoundup(n);
}
static int memtraceInit(void *p){
  return memtraceBase.xInit(p);
}
static void memtraceShutdown(void *p){
  memtraceBase.xShutdown(p);
}

/* The substitute memory allocator */
static sqlite3_mem_methods ersaztMethods = {
  memtraceMalloc,
  memtraceFree,
  memtraceRealloc,
  memtraceSize,
  memtraceRoundup,
  memtraceInit,
  memtraceShutdown
};

/* Begin tracing memory allocations to out. */
int sqlite3MemTraceActivate(FILE *out){
  int rc = SQLITE_OK;
  if( memtraceBase.xMalloc==0 ){
    rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memtraceBase);
    if( rc==SQLITE_OK ){
      rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &ersaztMethods);
    }
  }
  memtraceOut = out;
  return rc;
}

/* Deactivate memory tracing */
int sqlite3MemTraceDeactivate(void){
  int rc = SQLITE_OK;
  if( memtraceBase.xMalloc!=0 ){
    rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memtraceBase);
    if( rc==SQLITE_OK ){
      memset(&memtraceBase, 0, sizeof(memtraceBase));
    }
  }
  memtraceOut = 0;
  return rc;
}
/***** End copy/paste from ext/misc/memtrace.c ***************************/

/*
** Progress handler callback
**
** Count the number of callbacks and cause an abort once the limit is
** reached.
*/
static int progress_handler(void *pNotUsed){
  nCb++;
  if( nCb<mxCb ) return 0;
  if( eVerbosity>=1 ){
    printf("-- Progress limit of %d reached\n", mxCb);
  }
  return 1;
}

/* libFuzzer invokes this routine with fuzzed database files (in aData).
** This routine run SQLite against the malformed database to see if it
** can provoke a failure or malfunction.
*/
int LLVMFuzzerTestOneInput(const uint8_t *aData, size_t nByte){
  unsigned char *a;
  sqlite3 *db;
  int rc;
  int i;
  sqlite3_int64 x;
  char *zErr = 0;

  if( eVerbosity>=1 ){
    printf("************** nByte=%d ***************\n", (int)nByte);
    fflush(stdout);
  }
  if( sqlite3_initialize() ) return 0;
  rc = sqlite3_open(0, &db);
  if( rc ) return 1;
  a = sqlite3_malloc64(nByte+1);
  if( a==0 ) return 1;
  memcpy(a, aData, nByte);
  sqlite3_deserialize(db, "main", a, nByte, nByte,
        SQLITE_DESERIALIZE_RESIZEABLE |
        SQLITE_DESERIALIZE_FREEONCLOSE);
  x = szMax;
#ifdef SQLITE_FCNTL_SIZE_LIMIT
  sqlite3_file_control(db, "main", SQLITE_FCNTL_SIZE_LIMIT, &x);
#endif
  if( bVdbeDebug ){
    sqlite3_exec(db, "PRAGMA vdbe_debug=ON", 0, 0, 0);
  }
  if( mxCb>0 ){
    sqlite3_progress_handler(db, 10, progress_handler, 0);
  }
#ifdef SQLITE_TESTCTRL_PRNG_SEED
  sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SEED, 1, db);
#endif
  for(i=0; i<sizeof(azSql)/sizeof(azSql[0]); i++){
    if( eVerbosity>=1 ){
      printf("%s\n", azSql[i]);
      fflush(stdout);
    }
    zErr = 0;
    nCb = 0;
    sqlite3_exec(db, azSql[i], 0, 0, 0);
    rc = sqlite3_exec(db, azSql[i], 0, 0, &zErr);
    if( rc && eVerbosity>=1 ){
      printf("-- rc=%d zErr=%s\n", rc, zErr);
    }
    sqlite3_free(zErr);
  }
  rc = sqlite3_close(db);
  if( rc!=SQLITE_OK ){
    fprintf(stdout, "sqlite3_close() returns %d\n", rc);
  }
  if( sqlite3_memory_used()!=0 ){
    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);
  }
  return 0;
}

/*
** Return the number of "v" characters in a string.  Return 0 if there
** are any characters in the string other than "v".
*/
static int numberOfVChar(const char *z){
  int N = 0;
  while( z[0] && z[0]=='v' ){
    z++;
    N++;
  }
  return z[0]==0 ? N : 0;
}

/* libFuzzer invokes this routine once when the executable starts, to
** process the command-line arguments.
*/
int LLVMFuzzerInitialize(int *pArgc, char ***pArgv){
  int i, j;
  int i, j, n;
  int argc = *pArgc;
  char **newArgv;
  char **argv = *pArgv;
  newArgv = malloc( sizeof(char*)*(argc+1) );
  if( newArgv==0 ) return 0;
  newArgv[0] = argv[0];
  for(i=j=1; i<argc; i++){
    char *z = argv[i];
    if( z[0]=='-' ){
      z++;
      if( z[0]=='-' ) z++;
      if( z[0]=='v' && (n = numberOfVChar(z))>0 ){
        eVerbosity += n;
        continue;
      }
      if( strcmp(z,"vdbe-debug")==0 ){
        bVdbeDebug = 1;
        continue;
      }
      if( strcmp(z,"v")==0 ){
        eVerbosity++;
      if( strcmp(z,"limit")==0 ){
        if( i+1==argc ){
          fprintf(stderr, "missing argument to %s\n", argv[i]);
          exit(1);
        }
        mxCb = strtol(argv[++i], 0, 0);
        continue;
      }
      if( strcmp(z,"memtrace")==0 ){
        sqlite3MemTraceActivate(stdout);
        continue;
      }
      if( strcmp(z,"max-db-size")==0 ){
        if( i+1==argc ){
          fprintf(stderr, "missing argument to %s\n", argv[i]);
          exit(1);
        }
        szMax = strtol(argv[++i], 0, 0);
        continue;
      }
      if( strcmp(z, "lookaside")==0 ){
        int sz, nSlot;
        if( i+2>=argc ){
          fprintf(stderr, 
             "--lookaside requires two arguments: slot-size num-slots\n");
          exit(1);
        }
        sz = atoi(argv[++i]);
        nSlot = atoi(argv[++i]);
        sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, nSlot);
        continue;
      }
#ifndef _WIN32
      if( strcmp(z,"max-stack")==0
       || strcmp(z,"max-data")==0
       || strcmp(z,"max-as")==0
      ){
        struct rlimit x,y;
        int resource = RLIMIT_STACK;
        char *zType = "RLIMIT_STACK";
        if( i+1==argc ){
          fprintf(stderr, "missing argument to %s\n", argv[i]);
          exit(1);
        }
        if( z[4]=='d' ){
          resource = RLIMIT_DATA;
          zType = "RLIMIT_DATA";
        }
        if( z[4]=='a' ){
          resource = RLIMIT_AS;
          zType = "RLIMIT_AS";
        }
        memset(&x,0,sizeof(x));
        getrlimit(resource, &x);
        y.rlim_cur = atoi(argv[++i]);
        y.rlim_max = x.rlim_cur;
        setrlimit(resource, &y);
        memset(&y,0,sizeof(y));
        getrlimit(resource, &y);
        printf("%s changed from %d to %d\n", 
               zType, (int)x.rlim_cur, (int)y.rlim_cur);
        continue;
      }
#endif /* _WIN32 */
    }
    newArgv[j++] = argv[i];
    argv[j++] = argv[i];
  }
  newArgv[j] = 0;
  argv[j] = 0;
  *pArgv = newArgv;
  *pArgc = j;
  return 0;
}

#ifdef STANDALONE
/*
** Read an entire file into memory.  Space to hold the file comes
** from malloc().
*/
static unsigned char *readFile(const char *zName, int *pnByte){
  FILE *in = fopen(zName, "rb");
  long nIn;
  size_t nRead;
  unsigned char *pBuf;
  if( in==0 ) return 0;
  fseek(in, 0, SEEK_END);
  nIn = ftell(in);
  rewind(in);
  pBuf = malloc( nIn+1 );
  if( pBuf==0 ){ fclose(in); return 0; }
  nRead = fread(pBuf, nIn, 1, in);
  fclose(in);
  if( nRead!=1 ){
    free(pBuf);
    return 0;
  }
  pBuf[nIn] = 0;
  if( pnByte ) *pnByte = nIn;
  return pBuf;
}
#endif /* STANDALONE */

#ifdef STANDALONE
int main(int argc, char **argv){
  int i;
  LLVMFuzzerInitialize(&argc, &argv);
  for(i=1; i<argc; i++){
    unsigned char *pIn;
    int nIn;
    pIn = readFile(argv[i], &nIn);
    if( pIn ){
      LLVMFuzzerTestOneInput((const uint8_t*)pIn, (size_t)nIn);
      free(pIn);
    }
  }
#ifdef RUSAGE_SELF
  if( eVerbosity>0 ){
    struct rusage x;
    printf("SQLite %s\n", sqlite3_sourceid());
    memset(&x, 0, sizeof(x));
    if( getrusage(RUSAGE_SELF, &x)==0 ){
      printf("Maximum RSS = %ld KB\n", x.ru_maxrss);
    }
  }
#endif
  return 0;
}
#endif /*STANDALONE*/

Changes to test/dbpage.test.

97
98
99
100
101
102
103






104
105
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111







+
+
+
+
+
+


do_execsql_test 260 {
  UPDATE sqlite_dbpage SET data=(SELECT x FROM saved_content)
   WHERE pgno=2 AND schema='aux1';
} {}
do_catchsql_test 270 {
  PRAGMA aux1.integrity_check;
} {0 ok}

db close
sqlite3 db :memory:
do_execsql_test 300 {
  SELECT * FROM sqlite_temp_schema, sqlite_dbpage;
} {}

finish_test

Added test/dbpagefault.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022 July 06
#
# 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
source $testdir/malloc_common.tcl

if {[permutation] == "inmemory_journal"} {
  finish_test
  return
}

ifcapable !vtab {
  finish_test
  return
}

set testprefix dbpagefault

faultsim_save_and_close
do_faultsim_test 1 -prep {
  faultsim_restore_and_reopen
  execsql { ATTACH 'test.db2' AS aux; }
} -body {
  execsql { 
    CREATE VIRTUAL TABLE t1 USING sqlite_dbpage();
  }
} -test {
  execsql { PRAGMA journal_mode = off }
  faultsim_test_result {0 {}} 
}

do_faultsim_test 2 -prep {
  sqlite3 db "xyz.db" -vfs memdb
  execsql { ATTACH 'test.db2' AS aux; }
} -body {
  execsql { 
    CREATE VIRTUAL TABLE t1 USING sqlite_dbpage();
    INSERT INTO t1 DEFAULT VALUES;
  }
} -test {
  execsql { PRAGMA journal_mode = off }
  faultsim_test_result {1 {no such schema}}  {1 {SQL logic error}}
}

reset_db
do_execsql_test 3.0 {
  CREATE TABLE x1(z, b);
  CREATE TRIGGER BEFORE INSERT ON x1 BEGIN
    DELETE FROM sqlite_dbpage WHERE pgno=100;
    UPDATE sqlite_dbpage SET data=null WHERE pgno=100;
  END;
}

# This test case no longer works, as it is no longer possible to use
# virtual table sqlite_dbpage from within a trigger.
#
do_execsql_test 3.1 {
  PRAGMA trusted_schema = 1;
}
do_catchsql_test 3.2 {
  PRAGMA trusted_schema = 1;
  INSERT INTO x1 DEFAULT VALUES;
} {1 {unsafe use of virtual table "sqlite_dbpage"}}
#do_faultsim_test 3 -prep {
#  catch { db close }
#  sqlite3 db test.db
#  execsql { PRAGMA trusted_schema = 1 }
#} -body {
#  execsql { INSERT INTO x1 DEFAULT VALUES; }
#} -test {
#  faultsim_test_result {0 {}}
#}


finish_test


Changes to test/dbstatus.test.

59
60
61
62
63
64
65
66

67
68
69
70
71
72
73
59
60
61
62
63
64
65

66
67
68
69
70
71
72
73







-
+








proc lookaside {db} {
  expr { $::lookaside_buffer_size *
    [lindex [sqlite3_db_status $db SQLITE_DBSTATUS_LOOKASIDE_USED 0] 1]
  }
}

ifcapable stat4||stat3 {
ifcapable stat4 {
  set STAT3 1
} else {
  set STAT3 0
}

#---------------------------------------------------------------------------
# Run the dbstatus-2 and dbstatus-3 tests with several of different

Added test/decimal.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2017 December 9
#
# 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
set testprefix decimal

if {[catch {load_static_extension db decimal} error]} {
  puts "Skipping decimal tests, hit load error: $error"
  finish_test; return
}

do_execsql_test 1000 {
  SELECT decimal(1);
} {1}
do_execsql_test 1010 {
  SELECT decimal(1.0);
} {1.0}
do_execsql_test 1020 {
  SELECT decimal(0001.0);
} {1.0}
do_execsql_test 1030 {
  SELECT decimal(+0001.0);
} {1.0}
do_execsql_test 1040 {
  SELECT decimal(-0001.0);
} {-1.0}
do_execsql_test 1050 {
  SELECT decimal(1.0e72);
} {1000000000000000000000000000000000000000000000000000000000000000000000000}
#   123456789 123456789 123456789 123456789 123456789 123456789 123456789 123
do_execsql_test 1060 {
  SELECT decimal(1.0e-72);
} {0.0000000000000000000000000000000000000000000000000000000000000000000000010}
#    123456789 123456789 123456789 123456789 123456789 123456789 123456789 123
do_execsql_test 1070 {
  SELECT decimal(-123e-4);
} {-0.0123}
do_execsql_test 1080 {
  SELECT decimal(+123e+4);
} {1230000.0}


do_execsql_test 2000 {
  CREATE TABLE t1(seq INTEGER PRIMARY KEY, val TEXT);
  INSERT INTO t1 VALUES
    (1, '-9999e99'),
    (2, '-9998.000e+99'),
    (3, '-9999.0'),
    (4, '-1'),
    (5, '-9999e-20'),
    (6, '0'),
    (7, '1e-30'),
    (8, '1e-29'),
    (9, '1'),
    (10,'1.00000000000000001'),
    (11,'+1.00001'),
    (12,'99e+99');
  SELECT *, '|'
    FROM t1 AS a, t1 AS b
   WHERE a.seq<b.seq
     AND decimal_cmp(a.val,b.val)>=0;
} {}
do_execsql_test 2010 {
  SELECT *, '|'
    FROM t1 AS a, t1 AS b
   WHERE a.seq<>b.seq
     AND decimal_cmp(a.val,b.val)==0;
} {}
do_execsql_test 2020 {
  SELECT *, '|'
    FROM t1 AS a, t1 AS b
   WHERE a.seq>b.seq
     AND decimal_cmp(a.val,b.val)<=0;
} {}
do_execsql_test 2030 {
  SELECT seq FROM t1 ORDER BY val COLLATE decimal;
} {1 2 3 4 5 6 7 8 9 10 11 12}
do_execsql_test 2040 {
  SELECT seq FROM t1 ORDER BY val COLLATE decimal DESC;
} {12 11 10 9 8 7 6 5 4 3 2 1}

do_execsql_test 3000 {
  CREATE TABLE t3(seq INTEGER PRIMARY KEY, val TEXT);
  WITH RECURSIVE c(x) AS (VALUES(1) UNION SELECT x+1 FROM c WHERE x<10)
    INSERT INTO t3(seq, val) SELECT x, x FROM c;
  WITH RECURSIVE c(x) AS (VALUES(1) UNION SELECT x+1 FROM c WHERE x<5)
    INSERT INTO t3(seq, val) SELECT x+10, x*1000 FROM c;
  SELECT decimal(val) FROM t3 ORDER BY seq;
} {1 2 3 4 5 6 7 8 9 10 1000 2000 3000 4000 5000}
do_execsql_test 3020 {
  SELECT decimal_add(val,'0.5') FROM t3 WHERE seq>5 ORDER BY seq
} {6.5 7.5 8.5 9.5 10.5 1000.5 2000.5 3000.5 4000.5 5000.5}
do_execsql_test 3030 {
  SELECT decimal_add(val,'-10') FROM t3 ORDER BY seq;
} {-9 -8 -7 -6 -5 -4 -3 -2 -1 0 990 1990 2990 3990 4990}

do_execsql_test 4000 {
  SELECT decimal_sum(val) FROM t3;
} {15055}
do_execsql_test 4010 {
  SELECT decimal_sum(decimal_add(val,val||'e+10')) FROM t3;
} {150550000015055}
do_execsql_test 4010 {
  SELECT decimal_sum(decimal_add(val||'e+20',decimal_add(val,val||'e-20')))
    FROM t3;
} {1505500000000000000015055.00000000000000015055}

do_execsql_test 5000 {
  WITH RECURSIVE c(x,y,z) AS (
    VALUES(0,'1','1')
    UNION ALL
    SELECT x+1, decimal_mul(y,'2'), decimal_mul(z,'0.5')
      FROM c WHERE x<32
  )
  SELECT count(*) FROM c WHERE decimal_mul(y,z)='1';
} {33}

do_execsql_test 5100 {
  SELECT decimal_mul('1234.00','2.00');
} {2468.00}
do_execsql_test 5101 {
  SELECT decimal_mul('1234.00','2.0000');
} {2468.00}
do_execsql_test 5102 {
  SELECT decimal_mul('1234.0000','2.000');
} {2468.000}
do_execsql_test 5103 {
  SELECT decimal_mul('1234.0000','2');
} {2468}

if {[catch {load_static_extension db ieee754} error]} {
  puts "Skipping ieee754 tests, hit load error: $error"
  finish_test; return
}

do_execsql_test 6000 {
  CREATE TABLE pow2(x INTEGER PRIMARY KEY, v TEXT);
  WITH RECURSIVE c(x,v) AS (
    VALUES(0,'1')
    UNION ALL
    SELECT x+1, decimal_mul(v,'2') FROM c WHERE x+1<=971
  ) INSERT INTO pow2(x,v) SELECT x, v FROM c;
  WITH RECURSIVE c(x,v) AS (
    VALUES(-1,'0.5')
    UNION ALL
    SELECT x-1, decimal_mul(v,'0.5') FROM c WHERE x-1>=-1075
  ) INSERT INTO pow2(x,v) SELECT x, v FROM c;
} {}
do_execsql_test 6010 {
  WITH c(n) AS (SELECT ieee754_from_blob(x'0000000000000001'))
SELECT decimal_mul(ieee754_mantissa(c.n),pow2.v)
  FROM pow2, c WHERE pow2.x=ieee754_exponent(c.n);
} {0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004940656458412465441765687928682213723650598026143247644255856825006755072702087518652998363616359923797965646954457177309266567103559397963987747960107818781263007131903114045278458171678489821036887186360569987307230500063874091535649843873124733972731696151400317153853980741262385655911710266585566867681870395603106249319452715914924553293054565444011274801297099995419319894090804165633245247571478690147267801593552386115501348035264934720193790268107107491703332226844753335720832431936092382893458368060106011506169809753078342277318329247904982524730776375927247874656084778203734469699533647017972677717585125660551199131504891101451037862738167250955837389733598993664809941164205702637090279242767544565229087538682506419718265533447265625}
do_execsql_test 6020 {
  WITH c(n) AS (SELECT ieee754_from_blob(x'7fefffffffffffff'))
SELECT decimal_mul(ieee754_mantissa(c.n),pow2.v)
  FROM pow2, c WHERE pow2.x=ieee754_exponent(c.n);
} {179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368}

do_execsql_test 6100 {
  SELECT ieee754(ieee754_from_blob(x'0000000000000001'));
} {ieee754(1,-1074)}
do_execsql_test 6110 {
  SELECT ieee754(ieee754_from_blob(x'7fefffffffffffff'));
} {ieee754(9007199254740991,971)}
do_execsql_test 6120 {
  SELECT printf('%.8e',ieee754_from_blob(x'0000000000000001'));
} {4.94065646e-324}
do_execsql_test 6130 {
  SELECT printf('%.8e',ieee754_from_blob(x'ffefffffffffffff'));
} {-1.79769313e+308}




finish_test

Changes to test/default.test.

123
124
125
126
127
128
129









130
131
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140







+
+
+
+
+
+
+
+
+


} {1 {default value of column [b] is not constant}}
do_catchsql_test default-4.3 {
  CREATE TABLE t2(a TEXT, b TEXT DEFAULT(abs(:xyz)));
} {1 {default value of column [b] is not constant}}
do_catchsql_test default-4.4 {
  CREATE TABLE t2(a TEXT, b TEXT DEFAULT(98+coalesce(5,:xyz)));
} {1 {default value of column [b] is not constant}}

# 2020-03-09 out-of-bounds memory access discovered by "Eternal Sakura"
# and reported to chromium.
#
reset_db
do_catchsql_test default-5.1 {
  CREATE TABLE t1 (a,b DEFAULT(random() NOTNULL IN (RAISE(IGNORE),2,3)));
  INSERT INTO t1(a) VALUES(1);
} {1 {RAISE() may only be used within a trigger-program}}

finish_test

Changes to test/delete4.test.

55
56
57
58
59
60
61
62

63
64
65
66
67

68
69








70
71
72
73
74
75
76
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







-
+





+

-
+
+
+
+
+
+
+
+







  SELECT x FROM t1;
} {1 3 5 7}


#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 3.1 {
do_execsql_test 3.0.1 {
  CREATE TABLE t1(a, b, PRIMARY KEY(a, b)) WITHOUT ROWID;
  INSERT INTO t1 VALUES(1, 2);
  INSERT INTO t1 VALUES(2, 4);
  INSERT INTO t1 VALUES(1, 5);
  DELETE FROM t1 WHERE a=1;
  SELECT printf('(%d)',changes());
  SELECT * FROM t1;
} {2 4}
} {(2) 2 4}
do_execsql_test 3.0.2 {
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100)
     INSERT INTO t1(a,b) SELECT x, x+1 FROM c;
  SELECT printf('(%d)',changes());
  DELETE FROM t1;
  SELECT printf('(%d)',changes());
} {(100) (101)}

#-------------------------------------------------------------------------
# DELETE statement that uses the OR optimization
#
reset_db
do_execsql_test 3.1 {
  CREATE TABLE t1(i INTEGER PRIMARY KEY, a, b);
178
179
180
181
182
183
184
185





186









































































187
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








+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

do_execsql_test 6.1 {
  DROP TABLE IF EXISTS t2;
  CREATE TABLE t2(x INT);
  INSERT INTO t2(x) VALUES(1),(2),(3),(4),(5);
  DELETE FROM t2 WHERE EXISTS(SELECT 1 FROM t2 AS v WHERE v.x=t2.x+1);
  SELECT x FROM t2;
} {5}

#-------------------------------------------------------------------------
# Test the effect of failing to find a table row based on an index key
# within a DELETE. Either because the db is corrupt, or a trigger on another
# row already deleted the entry, or because a BEFORE trigger on the current
# row has already deleted it.

#
do_execsql_test 7.1.0 {
  CREATE TABLE t3(id INT PRIMARY KEY, a, b) WITHOUT ROWID;
  CREATE INDEX t3a ON t3(a);
  CREATE INDEX t3b ON t3(b);

  INSERT INTO t3 VALUES(1, 1, 1);
  INSERT INTO t3 VALUES(2, 2, 2);
  INSERT INTO t3 VALUES(3, 3, 3);
  INSERT INTO t3 VALUES(4, 4, 1);
}
do_execsql_test 7.1.1 {
  DELETE FROM t3 WHERE a=4 OR b=1;
}
do_execsql_test 7.1.2 {
  SELECT * FROM t3;
} { 2 2 2   3 3 3 }

do_execsql_test 7.2.0 {
  CREATE TABLE t4(a PRIMARY KEY, b) WITHOUT ROWID;
  CREATE INDEX t4i ON t4(b);
  INSERT INTO t4 VALUES(1, 'hello');
  INSERT INTO t4 VALUES(2, 'world');

  CREATE TABLE t5(a PRIMARY KEY, b) WITHOUT ROWID;
  CREATE INDEX t5i ON t5(b);
  INSERT INTO t5 VALUES(1, 'hello');
  INSERT INTO t5 VALUES(3, 'world');

  PRAGMA writable_schema = 1;
  UPDATE sqlite_master SET rootpage = (
    SELECT rootpage FROM sqlite_master WHERE name = 't5'
  ) WHERE name = 't4';
}

db close
sqlite3 db test.db
do_execsql_test 7.2.1 {
  DELETE FROM t4 WHERE b='world'
}
reset_db

do_execsql_test 7.3.0 {
  CREATE TABLE t3(id INT PRIMARY KEY, a, b) WITHOUT ROWID;
  INSERT INTO t3 VALUES(1, 2, 3);
  INSERT INTO t3 VALUES(4, 5, 6);
  INSERT INTO t3 VALUES(7, 8, 9);
  CREATE TRIGGER t3t BEFORE DELETE ON t3 BEGIN
    DELETE FROM t3 WHERE id=old.id+3;
  END;
}

do_execsql_test 7.3.1 {
  DELETE FROM t3 WHERE a IN(2, 5, 8);
  SELECT * FROM t3;
} {}

do_execsql_test 7.3.2 {
  DROP TRIGGER t3t;
  INSERT INTO t3 VALUES(1, 2, 3);
  INSERT INTO t3 VALUES(4, 5, 6);
  INSERT INTO t3 VALUES(7, 8, 9);
  CREATE TRIGGER t3t BEFORE DELETE ON t3 BEGIN
    DELETE FROM t3 WHERE id=old.id;
  END;
}

do_execsql_test 7.3.3 {
  DELETE FROM t3 WHERE a IN(2, 5, 8);
  SELECT * FROM t3;
} {}


finish_test

Changes to test/descidx1.test.

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







-
+
+







source $testdir/tester.tcl

# Do not use a codec for tests in this file, as the database file is
# manipulated directly using tcl scripts (using the [hexio_write] command).
#
do_not_use_codec

db eval {PRAGMA legacy_file_format=OFF}
#db eval {PRAGMA legacy_file_format=OFF}
sqlite3_db_config db LEGACY_FILE_FORMAT 0

# This procedure sets the value of the file-format in file 'test.db'
# to $newval. Also, the schema cookie is incremented.
# 
proc set_file_format {newval} {
  hexio_write test.db 44 [hexio_render_int32 $newval]
  set schemacookie [hexio_get_int [hexio_read test.db 40 4]]
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
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







-
+






-
+



-
-
+
+


















-
-
+
+



















+

-









# the get_file_format command.
#
ifcapable legacyformat {
  do_test descidx1-6.1 {
    db close
    forcedelete test.db test.db-journal
    sqlite3 db test.db
    execsql {PRAGMA legacy_file_format}
    sqlite3_db_config db LEGACY_FILE_FORMAT
  } {1}
} else {
  do_test descidx1-6.1 {
    db close
    forcedelete test.db test.db-journal
    sqlite3 db test.db
    execsql {PRAGMA legacy_file_format}
    sqlite3_db_config db LEGACY_FILE_FORMAT
  } {0}
}
do_test descidx1-6.2 {
  execsql {PRAGMA legacy_file_format=YES}
  execsql {PRAGMA legacy_file_format}
  sqlite3_db_config db LEGACY_FILE_FORMAT 1
  sqlite3_db_config db LEGACY_FILE_FORMAT
} {1}
do_test descidx1-6.3 {
  execsql {
    CREATE TABLE t1(a,b,c);
  }
  get_file_format
} {1}
ifcapable vacuum {
  # Verify that the file format is preserved across a vacuum.
  do_test descidx1-6.3.1 {
    execsql {VACUUM}
    get_file_format
  } {1}
}
do_test descidx1-6.4 {
  db close
  forcedelete test.db test.db-journal
  sqlite3 db test.db
  execsql {PRAGMA legacy_file_format=NO}
  execsql {PRAGMA legacy_file_format}
  sqlite3_db_config db LEGACY_FILE_FORMAT 0
  sqlite3_db_config db LEGACY_FILE_FORMAT
} {0}
do_test descidx1-6.5 {
  execsql {
    CREATE TABLE t1(a,b,c);
    CREATE INDEX i1 ON t1(a ASC, b DESC, c ASC);
    INSERT INTO t1 VALUES(1,2,3);
    INSERT INTO t1 VALUES(1,1,0);
    INSERT INTO t1 VALUES(1,2,1);
    INSERT INTO t1 VALUES(1,3,4);
  }
  get_file_format
} {4}
ifcapable vacuum {
  # Verify that the file format is preserved across a vacuum.
  do_test descidx1-6.6 {
    execsql {VACUUM}
    get_file_format
  } {4}
  do_test descidx1-6.7 {
    sqlite3_db_config db LEGACY_FILE_FORMAT 1
    execsql {
      PRAGMA legacy_file_format=ON;
      VACUUM;
    }
    get_file_format
  } {4}
} 



finish_test

Changes to test/descidx2.test.

19
20
21
22
23
24
25
26


27
28
29
30
31
32
33
19
20
21
22
23
24
25

26
27
28
29
30
31
32
33
34







-
+
+








# Do not use a codec for tests in this file, as the database file is
# manipulated directly using tcl scripts (using the [hexio_write] command).
#
do_not_use_codec


db eval {PRAGMA legacy_file_format=OFF}
#db eval {PRAGMA legacy_file_format=OFF}
sqlite3_db_config db LEGACY_FILE_FORMAT 0

# This procedure sets the value of the file-format in file 'test.db'
# to $newval. Also, the schema cookie is incremented.
# 
proc set_file_format {newval} {
  hexio_write test.db 44 [hexio_render_int32 $newval]
  set schemacookie [hexio_get_int [hexio_read test.db 40 4]]

Changes to test/descidx3.test.

22
23
24
25
26
27
28
29


30
31
32
33
34
35
36
22
23
24
25
26
27
28

29
30
31
32
33
34
35
36
37







-
+
+







#
do_not_use_codec

ifcapable !bloblit {
  finish_test
  return
}
db eval {PRAGMA legacy_file_format=OFF}
#db eval {PRAGMA legacy_file_format=OFF}
sqlite3_db_config db LEGACY_FILE_FORMAT 0

# This procedure sets the value of the file-format in file 'test.db'
# to $newval. Also, the schema cookie is incremented.
# 
proc set_file_format {newval} {
  hexio_write test.db 44 [hexio_render_int32 $newval]
  set schemacookie [hexio_get_int [hexio_read test.db 40 4]]

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
46
47
48
49
50
51
52
53
54
55


56
57
58
59
60
61
62
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







-
+


-
+

-















-
-
+
+







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} {
  uplevel [list do_test $tn [list is_distinct_noop $sql] 0]
}

proc do_temptables_test {tn sql temptables} {
  uplevel [list do_test $tn [subst -novar {
    set ret ""
    db eval "EXPLAIN [set sql]" {
      if {$opcode == "OpenEphemeral" || $opcode == "SorterOpen"} { 
        if {$p5 != "08" && $p5!="00"} { error "p5 = $p5" }
        if {$p5 == "08"} {
        if {$p5!=8 && $p5!=0} { error "p5 = $p5" }
        if {$p5==8} {
          lappend ret hash
        } else {
          lappend ret btree
        }
      }
    }
    set ret
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} {
263
264
265
266
267
268
269
270


271

















































































272
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








+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

    FROM sqlite_master;
} {jjj}
do_execsql_test 6.2 {
  CREATE TABLE nnn(x);
  SELECT (SELECT 'mmm' UNION SELECT DISTINCT max(name) ORDER BY 1) 
    FROM sqlite_master;
} {mmm}

#-------------------------------------------------------------------------
# Ticket [9c944882]

#
reset_db
do_execsql_test 7.0 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY);
  CREATE TABLE t3(a INTEGER PRIMARY KEY);

  CREATE TABLE t4(x);
  CREATE TABLE t5(y);
  
  INSERT INTO t5 VALUES(1), (2), (2);
  INSERT INTO t1 VALUES(2);
  INSERT INTO t3 VALUES(2);
  INSERT INTO t4 VALUES(2);
}

do_execsql_test 7.1 {
  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}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 9.0 {
  CREATE TABLE t1(a, b);
  INSERT INTO t1 VALUES('a', 'a');
  INSERT INTO t1 VALUES('a', 'b');
  INSERT INTO t1 VALUES('a', 'c');

  INSERT INTO t1 VALUES('b', 'a');
  INSERT INTO t1 VALUES('b', 'b');
  INSERT INTO t1 VALUES('b', 'c');

  INSERT INTO t1 VALUES('a', 'a');
  INSERT INTO t1 VALUES('b', 'b');

  INSERT INTO t1 VALUES('A', 'A');
  INSERT INTO t1 VALUES('B', 'B');
}

foreach {tn idx} {
  1 { }
  2 { CREATE INDEX i1 ON t1(a, b); }
  3 { CREATE INDEX i1 ON t1(b, a); }
  4 { CREATE INDEX i1 ON t1(a COLLATE nocase, b COLLATE nocase); }
  5 { CREATE INDEX i1 ON t1(b COLLATE nocase, a COLLATE nocase); }
} {

  execsql { DROP INDEX IF EXISTS i1 }
  execsql $idx
  
  do_execsql_test 9.$tn.1 {
    SELECT DISTINCT a, b FROM t1 ORDER BY a, b
  } {
    A A  B B
    a a  a b  a c
    b a  b b  b c
  }

  do_execsql_test 9.$tn.1 {
    SELECT DISTINCT a COLLATE nocase, b COLLATE nocase FROM t1 
    ORDER BY a COLLATE nocase, b COLLATE nocase
  } {
    a a  a b  a c
    b a  b b  b c
  }
}


finish_test

Changes to test/distinct2.test.

225
226
227
228
229
230
231







































































232
233
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


  CREATE TABLE t2(x PRIMARY KEY);
  INSERT INTO t2 VALUES('yes');
  SELECT DISTINCT a FROM t1, t2 WHERE x=b;
  ANALYZE;
  SELECT DISTINCT a FROM t1, t2 WHERE x=b;
} {1 1}

#-------------------------------------------------------------------------
reset_db

do_execsql_test 2000 {
  CREATE TABLE t0 (c0, c1, c2, PRIMARY KEY (c0, c1));
  CREATE TABLE t1 (c2);
  INSERT INTO t0(c2) VALUES (0),(1),(3),(4),(5),(6),(7),(8),(9),(10),(11);
  INSERT INTO t0(c1) VALUES ('a');
  INSERT INTO t1(c2) VALUES (0);
}
do_execsql_test 2010 {
  SELECT DISTINCT t0.c0, t1._rowid_, t0.c1 FROM t1 CROSS JOIN t0 ORDER BY t0.c0;
} {{} 1 {} {} 1 a}
do_execsql_test 1.2 {
  ANALYZE;
}
do_execsql_test 2020 {
  SELECT DISTINCT t0.c0, t1._rowid_, t0.c1 FROM t1 CROSS JOIN t0 ORDER BY t0.c0;
} {{} 1 {} {} 1 a}


do_execsql_test 2030 {
  CREATE TABLE t2(a, b, c);
  CREATE INDEX t2ab ON t2(a, b);
  
  WITH c(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM c WHERE i<64)
    INSERT INTO t2 SELECT 'one', i%2, 'one' FROM c;

  WITH c(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM c WHERE i<64)
    INSERT INTO t2 SELECT 'two', i%2, 'two' FROM c;

  CREATE TABLE t3(x INTEGER PRIMARY KEY);
  INSERT INTO t3 VALUES(1);

  ANALYZE;
}
do_execsql_test 2040 {
  SELECT DISTINCT a, b, x FROM t3 CROSS JOIN t2 ORDER BY a, +b; 
} {
  one 0 1
  one 1 1
  two 0 1
  two 1 1
}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 3000 {
  CREATE TABLE t0 (c0, c1 NOT NULL DEFAULT 1, c2, PRIMARY KEY (c0, c1));
  INSERT INTO t0(c2) VALUES (NULL), (NULL), (NULL), (NULL), (NULL), (NULL), (NULL), (NULL), (NULL), (NULL), (NULL);
  INSERT INTO t0(c2) VALUES('a');
}

do_execsql_test 3010 {
  SELECT DISTINCT * FROM t0 WHERE NULL IS t0.c0;
} {
  {} 1 {}
  {} 1 a
}

do_execsql_test 3020 {
  ANALYZE;
}

do_execsql_test 3030 {
  SELECT DISTINCT * FROM t0 WHERE NULL IS c0;
} {
  {} 1 {}
  {} 1 a
}

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_blobbytes.test.

9
10
11
12
13
14
15





16
17
18
19
20
21
22
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27







+
+
+
+
+







#
#***********************************************************************
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix e_blobbytes

ifcapable !incrblob {
  finish_test
  return
}

do_execsql_test 1.0 {
  CREATE TABLE q1(r INTEGER PRIMARY KEY, s TEXT);
  WITH d(a, b) AS (
    SELECT 0, '' 
      UNION ALL
    SELECT a+1, b||'.' FROM d WHERE a<10000

Changes to test/e_blobclose.test.

9
10
11
12
13
14
15





16
17
18
19
20
21
22
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27







+
+
+
+
+







#
#***********************************************************************
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix e_blobclose

ifcapable !incrblob {
  finish_test
  return
}

set dots [string repeat . 40]
do_execsql_test 1.0 {
  CREATE TABLE x1(a INTEGER PRIMARY KEY, b DOTS);
  INSERT INTO x1 VALUES(-1, $dots);
  INSERT INTO x1 VALUES(-10, $dots);
  INSERT INTO x1 VALUES(-100, $dots);

Changes to test/e_blobopen.test.

9
10
11
12
13
14
15





16
17
18
19
20
21
22
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27







+
+
+
+
+







#
#***********************************************************************
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix e_blobopen

ifcapable !incrblob {
  finish_test
  return
}

forcedelete test.db2

do_execsql_test 1.0 {
  ATTACH 'test.db2' AS aux;

  CREATE TABLE main.t1(a INTEGER PRIMARY KEY, b TEXT, c BLOB);

Changes to test/e_blobwrite.test.

9
10
11
12
13
14
15





16
17
18
19
20
21
22
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27







+
+
+
+
+







#
#***********************************************************************
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix e_blobwrite

ifcapable !incrblob {
  finish_test
  return
}

#--------------------------------------------------------------------------
# EVIDENCE-OF: R-62898-22698 This function is used to write data into an
# open BLOB handle from a caller-supplied buffer. N bytes of data are
# copied from the buffer Z into the open BLOB, starting at offset
# iOffset.
#

Changes to test/e_changes.test.

21
22
23
24
25
26
27
28
29
30
31




32
33
34
35
36
37
38
21
22
23
24
25
26
27




28
29
30
31
32
33
34
35
36
37
38







-
-
-
-
+
+
+
+







  uplevel [list \
    do_test $tn "concat \[execsql {$sql}\] \[db changes\]" $res
  ]
}


#--------------------------------------------------------------------------
# EVIDENCE-OF: R-15996-49369 This function returns the number of rows
# modified, inserted or deleted by the most recently completed INSERT,
# UPDATE or DELETE statement on the database connection specified by the
# only parameter.
# EVIDENCE-OF: R-58361-29089 The changes() function returns the number
# of database rows that were changed or inserted or deleted by the most
# recently completed INSERT, DELETE, or UPDATE statement, exclusive of
# statements in lower-level triggers.
#
do_execsql_test 1.0 {
  CREATE TABLE t1(a, b);
  CREATE TABLE t2(x, y, PRIMARY KEY(x, y)) WITHOUT ROWID;
  CREATE INDEX i1 ON t1(a);
  CREATE INDEX i2 ON t2(y);
}
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
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







-
+














+
-
+
+







  do_test 1.$tn.11 { db changes } 0
  do_changes_test 1.$tn.12 COMMIT 0

}


#--------------------------------------------------------------------------
# EVIDENCE-OF: R-44877-05564 Executing any other type of SQL statement
# X-EVIDENCE-OF: R-44877-05564 Executing any other type of SQL statement
# does not modify the value returned by this function.
#
reset_db
do_changes_test 2.1 { CREATE TABLE t1(x)          } 0
do_changes_test 2.2 { 
  WITH d(y) AS (SELECT 1 UNION ALL SELECT y+1 FROM d WHERE y<47)
  INSERT INTO t1 SELECT y FROM d;
} 47

# The statement above set changes() to 47. Check that none of the following
# modify this.
do_changes_test 2.3 { SELECT count(x) FROM t1 } {47 47}
do_changes_test 2.4 { DROP TABLE t1               } 47
do_changes_test 2.5 { CREATE TABLE t1(x)          } 47
ifcapable altertable {
do_changes_test 2.6 { ALTER TABLE t1 ADD COLUMN b } 47
  do_changes_test 2.6 { ALTER TABLE t1 ADD COLUMN b } 47
}


#--------------------------------------------------------------------------
# EVIDENCE-OF: R-53938-27527 Only changes made directly by the INSERT,
# UPDATE or DELETE statement are considered - auxiliary changes caused
# by triggers, foreign key actions or REPLACE constraint resolution are
# not counted.

Changes to test/e_createtable.test.

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
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







+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+







+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
















+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+






+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+







do_createtable_tests 1.2.2 {
  1    "CREATE TABLE main.abc(a, b, c)"          {}
  2    "CREATE TABLE temp.helloworld(x)"         {}
  3    {CREATE TABLE auxa."t 1"(x, y)}           {}
  4    {CREATE TABLE auxb.xyz(z)}                {}
}
drop_all_tables
if {[permutation]!="maindbname"} {
do_createtable_tests 1.3 -tclquery {
  unset -nocomplain X
  array set X [table_list]
  list $X(main) $X(temp) $X(auxa) $X(auxb)
} {
  1    "CREATE TABLE main.abc(a, b, c)"  {abc {} {} {}}
  2    "CREATE TABLE main.t1(a, b, c)"   {{abc t1} {} {} {}}
  3    "CREATE TABLE temp.tmp(a, b, c)"  {{abc t1} tmp {} {}}
  4    "CREATE TABLE auxb.tbl(x, y)"     {{abc t1} tmp {} tbl}
  5    "CREATE TABLE auxb.t1(k, v)"      {{abc t1} tmp {} {t1 tbl}}
  6    "CREATE TABLE auxa.next(c, d)"    {{abc t1} tmp next {t1 tbl}}
  do_createtable_tests 1.3 -tclquery {
    unset -nocomplain X
    array set X [table_list]
    list $X(main) $X(temp) $X(auxa) $X(auxb)
  } {
    1    "CREATE TABLE main.abc(a, b, c)"  {abc {} {} {}}
    2    "CREATE TABLE main.t1(a, b, c)"   {{abc t1} {} {} {}}
    3    "CREATE TABLE temp.tmp(a, b, c)"  {{abc t1} tmp {} {}}
    4    "CREATE TABLE auxb.tbl(x, y)"     {{abc t1} tmp {} tbl}
    5    "CREATE TABLE auxb.t1(k, v)"      {{abc t1} tmp {} {t1 tbl}}
    6    "CREATE TABLE auxa.next(c, d)"    {{abc t1} tmp next {t1 tbl}}
  }
}

# EVIDENCE-OF: R-18895-27365 If the "TEMP" or "TEMPORARY" keyword occurs
# between the "CREATE" and "TABLE" then the new table is created in the
# temp database.
#
drop_all_tables
if {[permutation]!="maindbname"} {
do_createtable_tests 1.4 -tclquery {
  unset -nocomplain X
  array set X [table_list]
  list $X(main) $X(temp) $X(auxa) $X(auxb)
} {
  1    "CREATE TEMP TABLE t1(a, b)"      {{} t1 {} {}}
  2    "CREATE TEMPORARY TABLE t2(a, b)" {{} {t1 t2} {} {}}
  do_createtable_tests 1.4 -tclquery {
    unset -nocomplain X
    array set X [table_list]
    list $X(main) $X(temp) $X(auxa) $X(auxb)
  } {
    1    "CREATE TEMP TABLE t1(a, b)"      {{} t1 {} {}}
    2    "CREATE TEMPORARY TABLE t2(a, b)" {{} {t1 t2} {} {}}
  }
}

# EVIDENCE-OF: R-23976-43329 It is an error to specify both a
# schema-name and the TEMP or TEMPORARY keyword, unless the schema-name
# is "temp".
#
drop_all_tables
do_createtable_tests 1.5.1 -error {
  temporary table name must be unqualified
} {
  1    "CREATE TEMP TABLE main.t1(a, b)"        {}
  2    "CREATE TEMPORARY TABLE auxa.t2(a, b)"   {}
  3    "CREATE TEMP TABLE auxb.t3(a, b)"        {}
  4    "CREATE TEMPORARY TABLE main.xxx(x)"     {}
}
drop_all_tables
if {[permutation]!="maindbname"} {
do_createtable_tests 1.5.2 -tclquery {
  unset -nocomplain X
  array set X [table_list]
  list $X(main) $X(temp) $X(auxa) $X(auxb)
} {
  1    "CREATE TEMP TABLE temp.t1(a, b)"        {{} t1 {} {}}
  2    "CREATE TEMPORARY TABLE temp.t2(a, b)"   {{} {t1 t2} {} {}}
  3    "CREATE TEMP TABLE TEMP.t3(a, b)"        {{} {t1 t2 t3} {} {}}
  4    "CREATE TEMPORARY TABLE TEMP.xxx(x)"     {{} {t1 t2 t3 xxx} {} {}}
  do_createtable_tests 1.5.2 -tclquery {
    unset -nocomplain X
    array set X [table_list]
    list $X(main) $X(temp) $X(auxa) $X(auxb)
  } {
    1    "CREATE TEMP TABLE temp.t1(a, b)"        {{} t1 {} {}}
    2    "CREATE TEMPORARY TABLE temp.t2(a, b)"   {{} {t1 t2} {} {}}
    3    "CREATE TEMP TABLE TEMP.t3(a, b)"        {{} {t1 t2 t3} {} {}}
    4    "CREATE TEMPORARY TABLE TEMP.xxx(x)"     {{} {t1 t2 t3 xxx} {} {}}
  }
}

# EVIDENCE-OF: R-31997-24564 If no schema name is specified and the TEMP
# keyword is not present then the table is created in the main database.
#
drop_all_tables
if {[permutation]!="maindbname"} {
do_createtable_tests 1.6 -tclquery {
  unset -nocomplain X
  array set X [table_list]
  list $X(main) $X(temp) $X(auxa) $X(auxb)
} {
  1    "CREATE TABLE t1(a, b)"   {t1 {} {} {}}
  2    "CREATE TABLE t2(a, b)"   {{t1 t2} {} {} {}}
  3    "CREATE TABLE t3(a, b)"   {{t1 t2 t3} {} {} {}}
  4    "CREATE TABLE xxx(x)"     {{t1 t2 t3 xxx} {} {} {}}
  do_createtable_tests 1.6 -tclquery {
    unset -nocomplain X
    array set X [table_list]
    list $X(main) $X(temp) $X(auxa) $X(auxb)
  } {
    1    "CREATE TABLE t1(a, b)"   {t1 {} {} {}}
    2    "CREATE TABLE t2(a, b)"   {{t1 t2} {} {} {}}
    3    "CREATE TABLE t3(a, b)"   {{t1 t2 t3} {} {} {}}
    4    "CREATE TABLE xxx(x)"     {{t1 t2 t3 xxx} {} {} {}}
  }
}

drop_all_tables
do_execsql_test e_createtable-1.7.0 {
  CREATE TABLE t1(x, y);
  CREATE INDEX i1 ON t1(x);
  CREATE VIEW  v1 AS SELECT * FROM t1;
481
482
483
484
485
486
487
488

489
490
491

492
493
494
495
496
497
498
489
490
491
492
493
494
495

496
497
498

499
500
501
502
503
504
505
506







-
+


-
+







#   table/index/view of the same name does fail. 1.7.2.* tests that creating
#   a table with the same name as a table/index/view in a different database
#   is Ok.
#
do_createtable_tests 1.7.1 -error { %s } {
  1    "CREATE TABLE t1(a, b)"   {{table t1 already exists}}
  2    "CREATE TABLE i1(a, b)"   {{there is already an index named i1}}
  3    "CREATE TABLE v1(a, b)"   {{table v1 already exists}}
  3    "CREATE TABLE v1(a, b)"   {{view v1 already exists}}
  4    "CREATE TABLE auxa.tbl1(a, b)"   {{table tbl1 already exists}}
  5    "CREATE TABLE auxa.idx1(a, b)"   {{there is already an index named idx1}}
  6    "CREATE TABLE auxa.view1(a, b)"  {{table view1 already exists}}
  6    "CREATE TABLE auxa.view1(a, b)"  {{view view1 already exists}}
}
do_createtable_tests 1.7.2 {
  1    "CREATE TABLE auxa.t1(a, b)"   {}
  2    "CREATE TABLE auxa.i1(a, b)"   {}
  3    "CREATE TABLE auxa.v1(a, b)"   {}
  4    "CREATE TABLE tbl1(a, b)"      {}
  5    "CREATE TABLE idx1(a, b)"      {}
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269




1270
1271
1272
1273
1274
1275
1276
1268
1269
1270
1271
1272
1273
1274



1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285







-
-
-
+
+
+
+







  11   "INSERT INTO t2 VALUES('brambles', NULL)"     {}
  12   "INSERT INTO t2 VALUES(X'ABCDEF', NULL)"      {}

  13   "INSERT INTO t2 VALUES(NULL, NULL)"           {}
  14   "INSERT INTO t2 VALUES(NULL, NULL)"           {}
}

# EVIDENCE-OF: R-35113-43214 Unless the column is an INTEGER PRIMARY KEY
# or the table is a WITHOUT ROWID table or the column is declared NOT
# NULL, SQLite allows NULL values in a PRIMARY KEY column.
# EVIDENCE-OF: R-40010-16873 Unless the column is an INTEGER PRIMARY KEY
# or the table is a WITHOUT ROWID table or a STRICT table or the column
# is declared NOT NULL, SQLite allows NULL values in a PRIMARY KEY
# column.
#
#     If the column is an integer primary key, attempting to insert a NULL
#     into the column triggers the auto-increment behavior. Attempting
#     to use UPDATE to set an ipk column to a NULL value is an error.
#
do_createtable_tests 4.5.1 {
  1    "SELECT count(*) FROM t1 WHERE x IS NULL"                   3
1292
1293
1294
1295
1296
1297
1298








1299
1300
1301
1302
1303
1304
1305
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322







+
+
+
+
+
+
+
+







  CREATE TABLE t4(s, u INT PRIMARY KEY, v) WITHOUT ROWID;
  INSERT INTO t4 VALUES(1, NULL, 2);
} {1 {NOT NULL constraint failed: t4.u}}
do_catchsql_test 4.5.5 {
  CREATE TABLE t5(s, u INT PRIMARY KEY NOT NULL, v);
  INSERT INTO t5 VALUES(1, NULL, 2);
} {1 {NOT NULL constraint failed: t5.u}}
do_catchsql_test 4.5.6 {
  CREATE TABLE t6(s INT, u INT PRIMARY KEY, v INT) STRICT;
  INSERT INTO t6 VALUES(1, NULL, 2);
} {1 {NOT NULL constraint failed: t6.u}}
do_catchsql_test 4.5.7 {
  CREATE TABLE t7(s INT, u INT PRIMARY KEY NOT NULL, v INT) STRICT;
  INSERT INTO t7 VALUES(1, NULL, 2);
} {1 {NOT NULL constraint failed: t7.u}}

# EVIDENCE-OF: R-00227-21080 A UNIQUE constraint is similar to a PRIMARY
# KEY constraint, except that a single table may have any number of
# UNIQUE constraints.
#
drop_all_tables
do_createtable_tests 4.6 {
1381
1382
1383
1384
1385
1386
1387
1388

1389
1390
1391

1392
1393
1394

1395
1396
1397
1398
1399
1400
1401
1398
1399
1400
1401
1402
1403
1404

1405
1406
1407

1408
1409
1410

1411
1412
1413
1414
1415
1416
1417
1418







-
+


-
+


-
+







#
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 
1421
1422
1423
1424
1425
1426
1427
1428
1429


1430
1431
1432


1433
1434
1435


1436
1437
1438


1439
1440
1441


1442
1443
1444
1445
1446
1447
1448
1438
1439
1440
1441
1442
1443
1444


1445
1446
1447


1448
1449
1450


1451
1452
1453


1454
1455
1456


1457
1458
1459
1460
1461
1462
1463
1464
1465







-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+







  CREATE TABLE t2(a, b, CHECK( a||b ));
  INSERT INTO x2 VALUES(1, 'xx');
  INSERT INTO x2 VALUES(1, 'yy');
  INSERT INTO t2 SELECT * FROM x2;
}

do_createtable_tests 4.11 -error {CHECK constraint failed: %s} {
  1a    "INSERT INTO x1 VALUES('one', 0)"       {x1}
  1b    "INSERT INTO t1 VALUES('one', -4.0)"    {t1}
  1a    "INSERT INTO x1 VALUES('one', 0)"       {b>0}
  1b    "INSERT INTO t1 VALUES('one', -4.0)"    {b>0}

  2a    "INSERT INTO x2 VALUES('abc', 1)"       {x2}
  2b    "INSERT INTO t2 VALUES('abc', 1)"       {t2}
  2a    "INSERT INTO x2 VALUES('abc', 1)"       {a||b}
  2b    "INSERT INTO t2 VALUES('abc', 1)"       {a||b}

  3a    "INSERT INTO x2 VALUES(0, 'abc')"       {x2}
  3b    "INSERT INTO t2 VALUES(0, 'abc')"       {t2}
  3a    "INSERT INTO x2 VALUES(0, 'abc')"       {a||b}
  3b    "INSERT INTO t2 VALUES(0, 'abc')"       {a||b}

  4a    "UPDATE t1 SET b=-1 WHERE rowid=1"      {t1}
  4b    "UPDATE x1 SET b=-1 WHERE rowid=1"      {x1}
  4a    "UPDATE t1 SET b=-1 WHERE rowid=1"      {b>0}
  4b    "UPDATE x1 SET b=-1 WHERE rowid=1"      {b>0}

  4a    "UPDATE x2 SET a='' WHERE rowid=1"      {x2}
  4b    "UPDATE t2 SET a='' WHERE rowid=1"      {t2}
  4a    "UPDATE x2 SET a='' WHERE rowid=1"      {a||b}
  4b    "UPDATE t2 SET a='' WHERE rowid=1"      {a||b}
}

# EVIDENCE-OF: R-34109-39108 If the CHECK expression evaluates to NULL,
# or any other non-zero value, it is not a constraint violation.
#
do_createtable_tests 4.12 {
  1a    "INSERT INTO x1 VALUES('one', NULL)"    {}
1627
1628
1629
1630
1631
1632
1633
1634

1635
1636
1637
1638
1639
1640
1641
1644
1645
1646
1647
1648
1649
1650

1651
1652
1653
1654
1655
1656
1657
1658







-
+







  CREATE TABLE t4(a, b CHECK (b!=10));
  INSERT INTO t4 VALUES(1, 2);
  INSERT INTO t4 VALUES(3, 4);
}
do_execsql_test  4.18.2 { BEGIN; INSERT INTO t4 VALUES(5, 6) }
do_catchsql_test 4.18.3 { 
  INSERT INTO t4 SELECT a+4, b+4 FROM t4
} {1 {CHECK constraint failed: t4}}
} {1 {CHECK constraint failed: b!=10}}
do_test e_createtable-4.18.4 { sqlite3_get_autocommit db } 0
do_execsql_test 4.18.5 { SELECT * FROM t4 } {1 2 3 4 5 6}

# EVIDENCE-OF: R-19114-56113 Different constraints within the same table
# may have different default conflict resolution algorithms.
#
do_execsql_test 4.19.0 {

Changes to test/e_droptrigger.test.

123
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
137
138







-
-
+
+







    droptrigger_reopen_db
    execsql $droptrigger
    execsql " INSERT INTO $tbl VALUES('1', '2') "
    set ::triggers_fired
  } $after
}

# EVIDENCE-OF: R-50239-29811 Once removed, the trigger definition is no
# longer present in the sqlite_master (or sqlite_temp_master) table and
# EVIDENCE-OF: R-04950-25529 Once removed, the trigger definition is no
# longer present in the sqlite_schema (or sqlite_temp_schema) table and
# is not fired by any subsequent INSERT, UPDATE or DELETE statements.
#
#   Test cases e_droptrigger-1.* test the first part of this statement
#   (that dropped triggers do not appear in the schema table), and tests
#   droptrigger-2.* test that dropped triggers are not fired by INSERT
#   statements. The following tests verify that they are not fired by
#   UPDATE or DELETE statements.

Changes to test/e_dropview.test.

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
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







-
+





-
+





-
+





-
+

-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+







#
set databasedata [list_all_data]

do_execsql_test  3.1.0 { SELECT * FROM temp.v1 } {{a temp} {b temp}}
do_execsql_test  3.1.1 { DROP VIEW temp.v1 } {}
do_catchsql_test 3.1.2 { SELECT * FROM temp.v1 } {1 {no such table: temp.v1}}
do_test          3.1.3 { list_all_views } {main.v1 main.v2 aux.v1 aux.v2 aux.v3}
do_test          3.1.4 { list_all_data  } $databasedata
do_test          3.1.4 { string compare [list_all_data] $databasedata } 0

do_execsql_test  3.2.0 { SELECT * FROM v1 } {{a main} {b main}}
do_execsql_test  3.2.1 { DROP VIEW v1 } {}
do_catchsql_test 3.2.2 { SELECT * FROM main.v1 } {1 {no such table: main.v1}}
do_test          3.2.3 { list_all_views } {main.v2 aux.v1 aux.v2 aux.v3}
do_test          3.2.4 { list_all_data  } $databasedata
do_test          3.2.4 { string compare [list_all_data] $databasedata } 0

do_execsql_test  3.3.0 { SELECT * FROM v2 } {{a main} {b main}}
do_execsql_test  3.3.1 { DROP VIEW v2 } {}
do_catchsql_test 3.3.2 { SELECT * FROM main.v2 } {1 {no such table: main.v2}}
do_test          3.3.3 { list_all_views } {aux.v1 aux.v2 aux.v3}
do_test          3.3.4 { list_all_data  } $databasedata
do_test          3.3.4 { string compare [list_all_data] $databasedata } 0

do_execsql_test  3.4.0 { SELECT * FROM v1 } {{a aux} {b aux}}
do_execsql_test  3.4.1 { DROP VIEW v1 } {}
do_catchsql_test 3.4.2 { SELECT * FROM v1 } {1 {no such table: v1}}
do_test          3.4.3 { list_all_views } {aux.v2 aux.v3}
do_test          3.4.4 { list_all_data  } $databasedata
do_test          3.4.4 { string compare [list_all_data] $databasedata } 0

do_execsql_test  3.4.0 { SELECT * FROM aux.v2 } {{a aux} {b aux}}
do_execsql_test  3.4.1 { DROP VIEW aux.v2 } {}
do_catchsql_test 3.4.2 { SELECT * FROM aux.v2 } {1 {no such table: aux.v2}}
do_test          3.4.3 { list_all_views } {aux.v3}
do_test          3.4.4 { list_all_data  } $databasedata
do_execsql_test  3.5.0 { SELECT * FROM aux.v2 } {{a aux} {b aux}}
do_execsql_test  3.5.1 { DROP VIEW aux.v2 } {}
do_catchsql_test 3.5.2 { SELECT * FROM aux.v2 } {1 {no such table: aux.v2}}
do_test          3.5.3 { list_all_views } {aux.v3}
do_test          3.5.4 { string compare [list_all_data] $databasedata } 0

do_execsql_test  3.5.0 { SELECT * FROM v3 } {{a aux} {b aux}}
do_execsql_test  3.5.1 { DROP VIEW v3 } {}
do_catchsql_test 3.5.2 { SELECT * FROM v3 } {1 {no such table: v3}}
do_test          3.5.3 { list_all_views } {}
do_test          3.5.4 { list_all_data  } $databasedata
do_execsql_test  3.6.0 { SELECT * FROM v3 } {{a aux} {b aux}}
do_execsql_test  3.6.1 { DROP VIEW v3 } {}
do_catchsql_test 3.6.2 { SELECT * FROM v3 } {1 {no such table: v3}}
do_test          3.6.3 { list_all_views } {}
do_test          3.6.4 { string compare [list_all_data] $databasedata } 0

# EVIDENCE-OF: R-25558-37487 If the specified view cannot be found and
# the IF EXISTS clause is not present, it is an error.
#
do_dropview_tests 4 -repair {
  dropview_reopen_db 
} -errorformat {
175
176
177
178
179
180
181
182

183
184
185
186



187
188
189
190
191
192
175
176
177
178
179
180
181

182
183



184
185
186
187
188
189
190
191
192







-
+

-
-
-
+
+
+






# an IF EXISTS clause is present in the DROP VIEW statement, then the
# statement is a no-op.
#
do_dropview_tests 5 -repair {
  dropview_reopen_db
} -tclquery {
  list_all_views
  expr {[list_all_views] == "main.v1 main.v2 temp.v1 aux.v1 aux.v2 aux.v3"}
  #expr {[list_all_views] == "main.v1 main.v2 temp.v1 aux.v1 aux.v2 aux.v3"}
} {
  1    "DROP VIEW IF EXISTS xx"       1
  2    "DROP VIEW IF EXISTS main.xx"  1
  3    "DROP VIEW IF EXISTS temp.v2"  1
  1    "DROP VIEW IF EXISTS xx" "main.v1 main.v2 temp.v1 aux.v1 aux.v2 aux.v3"
  2    "DROP VIEW IF EXISTS main.xx" "main.v1 main.v2 temp.v1 aux.v1 aux.v2 aux.v3"
  3    "DROP VIEW IF EXISTS temp.v2" "main.v1 main.v2 temp.v1 aux.v1 aux.v2 aux.v3"
}




finish_test

Changes to test/e_expr.test.

80
81
82
83
84
85
86
87

88
89
90
91
92

93
94
95
96
97
98
99
80
81
82
83
84
85
86

87
88
89
90
91

92
93
94
95
96
97
98
99







-
+




-
+







db func regexp -argcount 2 regexfunc

#-------------------------------------------------------------------------
# Test cases e_expr-1.* attempt to verify that all binary operators listed
# in the documentation exist and that the relative precedences of the
# operators are also as the documentation suggests.
#
# EVIDENCE-OF: R-15514-65163 SQLite understands the following binary
# X-EVIDENCE-OF: R-15514-65163 SQLite understands the following binary
# operators, in order from highest to lowest precedence: || * / % + -
# << >> & | < <= > >= = == != <> IS IS
# NOT IN LIKE GLOB MATCH REGEXP AND OR
#
# EVIDENCE-OF: R-38759-38789 Operators IS and IS NOT have the same
# X-EVIDENCE-OF: R-38759-38789 Operators IS and IS NOT have the same
# precedence as =.
#

unset -nocomplain untested
foreach op1 $oplist {
  foreach op2 $oplist {
    set untested($op1,$op2) 1
176
177
178
179
180
181
182
183

184
185
186
187
188
189
190
176
177
178
179
180
181
182

183
184
185
186
187
188
189
190







-
+







  SELECT 0 == 0 < 2,   (0 == 0) < 2,   0 == (0 < 2)
} {0 1 0}

#-------------------------------------------------------------------------
# Check that the four unary prefix operators mentioned in the 
# documentation exist.
#
# EVIDENCE-OF: R-13958-53419 Supported unary prefix operators are these:
# X-EVIDENCE-OF: R-13958-53419 Supported unary prefix operators are these:
# - + ~ NOT
#
do_execsql_test e_expr-2.1 { SELECT -   10   } {-10}
do_execsql_test e_expr-2.2 { SELECT +   10   } {10}
do_execsql_test e_expr-2.3 { SELECT ~   10   } {-11}
do_execsql_test e_expr-2.4 { SELECT NOT 10   } {0}

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
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







-
-
+
+
+








-
-
-
-
-
-
-
+
+
+
+







  
  do_execsql_test e_expr-5.$tn "SELECT $a || $b" [list "${as}${bs}"]
}

#-------------------------------------------------------------------------
# Test the % operator.
#
# EVIDENCE-OF: R-04223-04352 The operator % outputs the integer value of
# its left operand modulo its right operand.
# EVIDENCE-OF: R-53431-59159 The % operator casts both of its operands
# to type INTEGER and then computes the remainder after dividing the
# left integer by the right integer.
#
do_execsql_test e_expr-6.1 {SELECT  72%5}  {2}
do_execsql_test e_expr-6.2 {SELECT  72%-5} {2}
do_execsql_test e_expr-6.3 {SELECT -72%-5} {-2}
do_execsql_test e_expr-6.4 {SELECT -72%5}  {-2}
do_execsql_test e_expr-6.5 {SELECT 72.35%5} {2.0}

#-------------------------------------------------------------------------
# Test that the results of all binary operators are either numeric or 
# NULL, except for the || operator, which may evaluate to either a text
# value or NULL.
#
# EVIDENCE-OF: R-20665-17792 The result of any binary operator is either
# a numeric value or NULL, except for the || concatenation operator
# which always evaluates to either NULL or a text value.
# EVIDENCE-OF: R-15904-00746 The result of any binary operator is either
# a numeric value or NULL, except for the || concatenation operator, and
# the -> and ->> extract operators which evaluate to either
# NULL or a text value.
#
set literals {
  1 'abc'        2 'hexadecimal'       3 ''
  4 123          5 -123                6 0
  7 123.4        8 0.0                 9 -123.4
 10 X'ABCDEF'   11 X''                12 X'0000'
 13     NULL
363
364
365
366
367
368
369
370

371
372
373
374
375
376
377
361
362
363
364
365
366
367

368
369
370
371
372
373
374
375







-
+







  string compare [reverse_str $zLeft] [reverse_str $zRight]
}
db collate reverse reverse_collate

# EVIDENCE-OF: R-59577-33471 The COLLATE operator is a unary postfix
# operator that assigns a collating sequence to an expression.
#
# EVIDENCE-OF: R-36231-30731 The COLLATE operator has a higher
# X-EVIDENCE-OF: R-36231-30731 The COLLATE operator has a higher
# precedence (binds more tightly) than any binary operator and any unary
# prefix operator except "~".
#
do_execsql_test e_expr-9.1 { SELECT  'abcd' < 'bbbb'    COLLATE reverse } 0
do_execsql_test e_expr-9.2 { SELECT ('abcd' < 'bbbb')   COLLATE reverse } 1
do_execsql_test e_expr-9.3 { SELECT  'abcd' <= 'bbbb'   COLLATE reverse } 0
do_execsql_test e_expr-9.4 { SELECT ('abcd' <= 'bbbb')  COLLATE reverse } 1
855
856
857
858
859
860
861
862

863
864
865
866
867
868
869
853
854
855
856
857
858
859

860
861
862
863
864
865
866
867







-
+







  do_test e_expr-13.1.$tn {
    set ::xcount 0
    set a [execsql "SELECT $expr"]
    list $::xcount $a
  } [list $nEval $res]
}

# EVIDENCE-OF: R-05155-34454 The precedence of the BETWEEN operator is
# X-EVIDENCE-OF: R-05155-34454 The precedence of the BETWEEN operator is
# the same as the precedence as operators == and != and LIKE and groups
# left to right.
# 
# Therefore, BETWEEN groups more tightly than operator "AND", but less
# so than "<".
#
do_execsql_test e_expr-13.2.1  { SELECT 1 == 10 BETWEEN 0 AND 2   }  1
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022












1023
1024
1025
1026
1027
1028
1029
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







-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+







do_test         e_expr-15.1.4 { set likeargs } {def abc X}
db close
sqlite3 db test.db

# EVIDENCE-OF: R-22868-25880 The LIKE operator can be made case
# sensitive using the case_sensitive_like pragma.
#
do_execsql_test e_expr-16.1.1 { SELECT 'abcxyz' LIKE 'ABC%' } 1
do_execsql_test e_expr-16.1.2 { PRAGMA case_sensitive_like = 1 } {}
do_execsql_test e_expr-16.1.3 { SELECT 'abcxyz' LIKE 'ABC%' } 0
do_execsql_test e_expr-16.1.4 { SELECT 'ABCxyz' LIKE 'ABC%' } 1
do_execsql_test e_expr-16.1.5 { PRAGMA case_sensitive_like = 0 } {}
do_execsql_test e_expr-16.1.6 { SELECT 'abcxyz' LIKE 'ABC%' } 1
do_execsql_test e_expr-16.1.7 { SELECT 'ABCxyz' LIKE 'ABC%' } 1
do_execsql_test e_expr-16.1.1  { SELECT 'abcxyz' LIKE 'ABC%' } 1
do_execsql_test e_expr-16.1.1b { SELECT 'abc%xyz' LIKE 'ABC\%x%' ESCAPE '\' } 1
do_execsql_test e_expr-16.1.2  { PRAGMA case_sensitive_like = 1 } {}
do_execsql_test e_expr-16.1.3  { SELECT 'abcxyz' LIKE 'ABC%' } 0
do_execsql_test e_expr-16.1.3b { SELECT 'abc%xyz' LIKE 'ABC\%X%' ESCAPE '\' } 0
do_execsql_test e_expr-16.1.4  { SELECT 'ABCxyz' LIKE 'ABC%' } 1
do_execsql_test e_expr-16.1.4b { SELECT 'ABC%xyz' LIKE 'ABC\%x%' ESCAPE '\' } 1
do_execsql_test e_expr-16.1.5  { PRAGMA case_sensitive_like = 0 } {}
do_execsql_test e_expr-16.1.6  { SELECT 'abcxyz' LIKE 'ABC%' } 1
do_execsql_test e_expr-16.1.6b { SELECT 'abc%xyz' LIKE 'ABC\%X%' ESCAPE '\' } 1
do_execsql_test e_expr-16.1.7  { SELECT 'ABCxyz' LIKE 'ABC%' } 1
do_execsql_test e_expr-16.1.7b { SELECT 'ABC%xyz' LIKE 'ABC\%X%' ESCAPE '\' } 1

# EVIDENCE-OF: R-52087-12043 The GLOB operator is similar to LIKE but
# uses the Unix file globbing syntax for its wildcards.
#
# EVIDENCE-OF: R-09813-17279 Also, GLOB is case sensitive, unlike LIKE.
#
do_execsql_test e_expr-17.1.1 { SELECT 'abcxyz' GLOB 'abc%' } 0
1130
1131
1132
1133
1134
1135
1136
1137

1138
1139
1140
1141
1142
1143
1144
1133
1134
1135
1136
1137
1138
1139

1140
1141
1142
1143
1144
1145
1146
1147







-
+







do_execsql_test e_expr-19.2.3 { SELECT 'X' NOT MATCH 'Y' } 0
do_test         e_expr-19.2.4 { set matchargs } {Y X}
sqlite3 db test.db

#-------------------------------------------------------------------------
# Test cases for the testable statements related to the CASE expression.
#
# EVIDENCE-OF: R-15199-61389 There are two basic forms of the CASE
# EVIDENCE-OF: R-57495-24088 There are two fundamental forms of the CASE
# expression: those with a base expression and those without.
#
do_execsql_test e_expr-20.1 {
  SELECT CASE WHEN 1 THEN 'true' WHEN 0 THEN 'false' ELSE 'else' END;
} {true}
do_execsql_test e_expr-20.2 {
  SELECT CASE 0 WHEN 1 THEN 'true' WHEN 0 THEN 'false' ELSE 'else' END;
1226
1227
1228
1229
1230
1231
1232
1233
1234


1235
1236
1237


1238
1239
1240
1241
1242
1243
1244
1229
1230
1231
1232
1233
1234
1235


1236
1237
1238


1239
1240
1241
1242
1243
1244
1245
1246
1247







-
-
+
+

-
-
+
+







} {null}
db nullvalue {}

# EVIDENCE-OF: R-13943-13592 A NULL result is considered untrue when
# evaluating WHEN terms.
#
do_execsql_test e_expr-21.4.1 {
  SELECT CASE WHEN NULL THEN 'A' WHEN 1 THEN 'B' END
} {B}
  SELECT CASE WHEN NULL THEN 'A' WHEN 1 THEN 'B' END, iif(NULL,8,99);
} {B 99}
do_execsql_test e_expr-21.4.2 {
  SELECT CASE WHEN 0 THEN 'A' WHEN NULL THEN 'B' ELSE 'C' END
} {C}
  SELECT CASE WHEN 0 THEN 'A' WHEN NULL THEN 'B' ELSE 'C' END, iif(0,8,99);
} {C 99}

# EVIDENCE-OF: R-38620-19499 In a CASE with a base expression, the base
# expression is evaluated just once and the result is compared against
# the evaluation of each WHEN expression from left to right.
#
# Note: This test case tests the "evaluated just once" part of the above
# statement. Tests associated with the next two statements test that the
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645











1646
1647
1648
1649
1650
1651
























1652
1653
1654
1655
1656
1657
1658
1638
1639
1640
1641
1642
1643
1644




1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692







-
-
-
-
+
+
+
+
+
+
+
+
+
+
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  CAST(-9223372036854775809.0 AS INT)
} integer -9223372036854775808
do_expr_test e_expr-31.2.4 { 
  CAST(9223372036854775809.0 AS INT)
} integer 9223372036854775807


# EVIDENCE-OF: R-09295-61337 Casting a TEXT or BLOB value into NUMERIC
# first does a forced conversion into REAL but then further converts the
# result into INTEGER if and only if the conversion from REAL to INTEGER
# is lossless and reversible.
# EVIDENCE-OF: R-55084-10555 Casting a TEXT or BLOB value into NUMERIC
# yields either an INTEGER or a REAL result.
#
# EVIDENCE-OF: R-48945-04866 If the input text looks like an integer
# (there is no decimal point nor exponent) and the value is small enough
# to fit in a 64-bit signed integer, then the result will be INTEGER.
#
# EVIDENCE-OF: R-47045-23194 Input text that looks like floating point
# (there is a decimal point and/or an exponent) and the text describes a
# value that can be losslessly converted back and forth between IEEE 754
# 64-bit float and a 51-bit signed integer, then the result is INTEGER.
#
do_expr_test e_expr-32.1.1 { CAST('45'   AS NUMERIC)  } integer 45
do_expr_test e_expr-32.1.2 { CAST('45.0' AS NUMERIC)  } integer 45
do_expr_test e_expr-32.1.3 { CAST('45.2' AS NUMERIC)  } real 45.2
do_expr_test e_expr-32.1.4 { CAST('11abc' AS NUMERIC) } integer 11
do_expr_test e_expr-32.1.5 { CAST('11.1abc' AS NUMERIC) } real 11.1
do_expr_test e_expr-32.1.6 {CAST( '9.223372036e14' AS NUMERIC)} integer  922337203600000
do_expr_test e_expr-32.1.7 {CAST('-9.223372036e14' AS NUMERIC)} integer -922337203600000
do_test e_expr-32.1.8 {
  set expr {CAST( '9.223372036e15' AS NUMERIC)}
  db eval "SELECT typeof($expr) AS type, printf('%.5e',$expr) AS value"  break;
  list $type $value
} {real 9.22337e+15}
do_test e_expr-32.1.9 {
  set expr {CAST('-9.223372036e15' AS NUMERIC)}
  db eval "SELECT typeof($expr) AS type, printf('%.5e',$expr) AS value"  break;
  list $type $value
} {real -9.22337e+15}

# EVIDENCE-OF: R-50300-26941 Any text input that describes a value
# outside the range of a 64-bit signed integer yields a REAL result.
#
do_expr_test e_expr-32.1.20 { CAST('9223372036854775807' AS numeric) } \
   integer 9223372036854775807
do_expr_test e_expr-32.1.21 { CAST('9223372036854775808' AS numeric) } \
   real 9.22337203685478e+18
do_expr_test e_expr-32.1.22 { CAST('-9223372036854775808' AS numeric) } \
   integer -9223372036854775808
do_expr_test e_expr-32.1.23 { CAST('-9223372036854775809' AS numeric) } \
   real -9.22337203685478e+18

# EVIDENCE-OF: R-30347-18702 Casting a REAL or INTEGER value to NUMERIC
# is a no-op, even if a real value could be losslessly converted to an
# integer.
#
do_expr_test e_expr-32.2.1 { CAST(13.0 AS NUMERIC) } real 13.0
do_expr_test e_expr-32.2.2 { CAST(13.5 AS NUMERIC) } real 13.5
1692
1693
1694
1695
1696
1697
1698
1699

1700
1701
1702
1703
1704
1705
1706


1707
1708
1709
1710
1711
1712
1713
1726
1727
1728
1729
1730
1731
1732

1733
1734
1735
1736
1737
1738


1739
1740
1741
1742
1743
1744
1745
1746
1747







-
+





-
-
+
+







  SELECT typeof(CAST(x AS NUMERIC)), CAST(x AS NUMERIC)||'' FROM t1;
} [list \
 integer 9000000000000000001 \
 integer 9000000000000000001 \
 integer 9000000000000000001 \
 integer 9000000000000000001 \
 integer 9000000000000000001 \
 integer 9000000000000000001 \
 real 9.0e+18 \
 integer 9223372036854775807 \
 integer 9223372036854775807 \
 integer 9223372036854775807 \
 real 9.22337203685478e+18 \
 real 9.22337203685478e+18 \
 integer 9223372036854775807 \
 integer 9223372036854775807 \
 real 9.22337203685478e+18 \
 real 9.22337203685478e+18 \
 integer -5 \
 integer -5 \
]

# EVIDENCE-OF: R-64550-29191 Note that the result from casting any
# non-BLOB value into a BLOB and the result from casting any BLOB value
# into a non-BLOB value may be different depending on whether the
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1910
1911
1912
1913
1914
1915
1916



1917
1918
1919
1920
1921
1922
1923







-
-
-







} {
  do_catchsql_test e_expr-35.2.$tn $sql $M
}

# EVIDENCE-OF: R-18318-14995 The value of a subquery expression is the
# first row of the result from the enclosed SELECT statement.
#
# EVIDENCE-OF: R-15900-52156 In other words, an implied "LIMIT 1" is
# added to the subquery, overriding an explicitly coded LIMIT.
#
do_execsql_test e_expr-36.3.1 {
  CREATE TABLE t4(x, y);
  INSERT INTO t4 VALUES(1, 'one');
  INSERT INTO t4 VALUES(2, 'two');
  INSERT INTO t4 VALUES(3, 'three');
} {}

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
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


1984
1985
1986
1987
1988







-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+





-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+



  do_expr_test e_expr-36.4.$tn $expr null {}
}

# EVIDENCE-OF: R-62477-06476 For example, the values NULL, 0.0, 0,
# 'english' and '0' are all considered to be false.
#
do_execsql_test e_expr-37.1 {
   SELECT CASE WHEN NULL THEN 'true' ELSE 'false' END;
} {false}
   SELECT CASE WHEN NULL THEN 'true' ELSE 'false' END, iif(NULL,'true','false');
} {false false}
do_execsql_test e_expr-37.2 {
   SELECT CASE WHEN 0.0 THEN 'true' ELSE 'false' END;
} {false}
   SELECT CASE WHEN 0.0 THEN 'true' ELSE 'false' END, iif(0.0,'true','false');
} {false false}
do_execsql_test e_expr-37.3 {
   SELECT CASE WHEN 0 THEN 'true' ELSE 'false' END;
} {false}
   SELECT CASE WHEN 0 THEN 'true' ELSE 'false' END, iif(0,'true','false');
} {false false}
do_execsql_test e_expr-37.4 {
   SELECT CASE WHEN 'engligh' THEN 'true' ELSE 'false' END;
} {false}
   SELECT CASE WHEN 'engligh' THEN 'true' ELSE 'false' END, iif('engligh','true','false');
} {false false}
do_execsql_test e_expr-37.5 {
   SELECT CASE WHEN '0' THEN 'true' ELSE 'false' END;
} {false}
   SELECT CASE WHEN '0' THEN 'true' ELSE 'false' END, iif('0','true','false');
} {false false}

# EVIDENCE-OF: R-55532-10108 Values 1, 1.0, 0.1, -0.1 and '1english' are
# considered to be true.
#
do_execsql_test e_expr-37.6 {
   SELECT CASE WHEN 1 THEN 'true' ELSE 'false' END;
} {true}
   SELECT CASE WHEN 1 THEN 'true' ELSE 'false' END, iif(1,'true','false');
} {true true}
do_execsql_test e_expr-37.7 {
   SELECT CASE WHEN 1.0 THEN 'true' ELSE 'false' END;
} {true}
   SELECT CASE WHEN 1.0 THEN 'true' ELSE 'false' END, iif(1.0,'true','false');
} {true true}
do_execsql_test e_expr-37.8 {
   SELECT CASE WHEN 0.1 THEN 'true' ELSE 'false' END;
} {true}
   SELECT CASE WHEN 0.1 THEN 'true' ELSE 'false' END, iif(0.1,'true','false');
} {true true}
do_execsql_test e_expr-37.9 {
   SELECT CASE WHEN -0.1 THEN 'true' ELSE 'false' END;
} {true}
   SELECT CASE WHEN -0.1 THEN 'true' ELSE 'false' END, iif(-0.1,'true','false');
} {true true}
do_execsql_test e_expr-37.10 {
   SELECT CASE WHEN '1english' THEN 'true' ELSE 'false' END;
} {true}
   SELECT CASE WHEN '1english' THEN 'true' ELSE 'false' END, iif('1engl','true','false');
} {true true}


finish_test

Changes to test/e_fkey.test.

44
45
46
47
48
49
50
51

52
53

54
55
56
57
58
59
60
44
45
46
47
48
49
50

51
52

53
54
55
56
57
58
59
60







-
+

-
+







}

###########################################################################
### SECTION 2: Enabling Foreign Key Support
###########################################################################

#-------------------------------------------------------------------------
# EVIDENCE-OF: R-33710-56344 In order to use foreign key constraints in
# EVIDENCE-OF: R-37672-59189 In order to use foreign key constraints in
# SQLite, the library must be compiled with neither
# SQLITE_OMIT_FOREIGN_KEY or SQLITE_OMIT_TRIGGER defined.
# SQLITE_OMIT_FOREIGN_KEY nor SQLITE_OMIT_TRIGGER defined.
#
ifcapable trigger&&foreignkey {
  do_test e_fkey-1 {
    execsql {
      PRAGMA foreign_keys = ON;
      CREATE TABLE p(i PRIMARY KEY);
      CREATE TABLE c(j REFERENCES p ON UPDATE CASCADE);
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
###########################################################################

#-------------------------------------------------------------------------
2051
2052
2053
2054
2055
2056
2057
2058

2059
2060

2061
2062
2063
2064
2065
2066
2067
2051
2052
2053
2054
2055
2056
2057

2058
2059

2060
2061
2062
2063
2064
2065
2066
2067







-
+

-
+







do_test e_fkey-44.5 {
  execsql { SELECT quote(c) FROM cB }
} {NULL}

#-------------------------------------------------------------------------
# Test SET DEFAULT actions.
#
# EVIDENCE-OF: R-43054-54832 The "SET DEFAULT" actions are similar to
# EVIDENCE-OF: R-55814-22637 The "SET DEFAULT" actions are similar to
# "SET NULL", except that each of the child key columns is set to
# contain the columns default value instead of NULL.
# contain the column's default value instead of NULL.
#
drop_all_tables
do_test e_fkey-45.1 {
  execsql {
    CREATE TABLE pA(x PRIMARY KEY);
    CREATE TABLE cA(c DEFAULT X'0000' REFERENCES pA ON DELETE SET DEFAULT);
    CREATE TABLE cB(c DEFAULT X'9999' REFERENCES pA ON UPDATE SET DEFAULT);
2503
2504
2505
2506
2507
2508
2509
2510

2511
2512
2513
2514
2515

2516
2517
2518




2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532


2533
2534

2535
2536
2537
2538
2539
2540
2541
2503
2504
2505
2506
2507
2508
2509

2510
2511
2512
2513
2514
2515
2516



2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532


2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544







-
+





+
-
-
-
+
+
+
+












-
-
+
+


+







# clause, unless the default value of the new column is NULL. Attempting
# to do so returns an error.
#
proc test_efkey_6 {tn zAlter isError} {
  drop_all_tables 

  do_test e_fkey-56.$tn.1 "
    execsql { CREATE TABLE tbl(a, b) }
    execsql { CREATE TABLE tbl(a, b); INSERT INTO tbl VALUES(1, 2); }
    [list catchsql $zAlter]
  " [lindex {{0 {}} {1 {Cannot add a REFERENCES column with non-NULL default value}}} $isError]

}

ifcapable altertable {
test_efkey_6 1 "ALTER TABLE tbl ADD COLUMN c REFERENCES xx" 0
test_efkey_6 2 "ALTER TABLE tbl ADD COLUMN c DEFAULT NULL REFERENCES xx" 0
test_efkey_6 3 "ALTER TABLE tbl ADD COLUMN c DEFAULT 0 REFERENCES xx" 1
  test_efkey_6 1 "ALTER TABLE tbl ADD COLUMN c REFERENCES xx" 0
  test_efkey_6 2 "ALTER TABLE tbl ADD COLUMN c DEFAULT NULL REFERENCES xx" 0
  test_efkey_6 3 "ALTER TABLE tbl ADD COLUMN c DEFAULT 0 REFERENCES xx" 1
}

#-------------------------------------------------------------------------
# Test that ALTER TABLE adjusts REFERENCES clauses when the parent table
# is RENAMED.
#
# EVIDENCE-OF: R-47080-02069 If an "ALTER TABLE ... RENAME TO" command
# is used to rename a table that is the parent table of one or more
# foreign key constraints, the definitions of the foreign key
# constraints are modified to refer to the parent table by its new name
#
# Test that these adjustments are visible in the sqlite_master table.
#
# EVIDENCE-OF: R-63827-54774 The text of the child CREATE TABLE
# statement or statements stored in the sqlite_master table are modified
# EVIDENCE-OF: R-43040-62530 The text of the child CREATE TABLE
# statement or statements stored in the sqlite_schema table are modified
# to reflect the new parent table name.
#
ifcapable altertable {
do_test e_fkey-56.1 {
  drop_all_tables
  execsql {
    CREATE TABLE 'p 1 "parent one"'(a REFERENCES 'p 1 "parent one"', b, PRIMARY KEY(b));

    CREATE TABLE c1(c, d REFERENCES 'p 1 "parent one"' ON UPDATE CASCADE);
    CREATE TABLE c2(e, f, FOREIGN KEY(f) REFERENCES 'p 1 "parent one"' ON UPDATE CASCADE);
2565
2566
2567
2568
2569
2570
2571

2572
2573
2574
2575
2576
2577
2578
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582







+







  execsql { SELECT sql FROM sqlite_master WHERE type = 'table'}
} [list                                                                     \
  {CREATE TABLE "p"(a REFERENCES "p", b, PRIMARY KEY(b))}                   \
  {CREATE TABLE c1(c, d REFERENCES "p" ON UPDATE CASCADE)}                  \
  {CREATE TABLE c2(e, f, FOREIGN KEY(f) REFERENCES "p" ON UPDATE CASCADE)}  \
  {CREATE TABLE c3(e, 'f col 2', FOREIGN KEY('f col 2') REFERENCES "p" ON UPDATE CASCADE)} \
]
}

#-------------------------------------------------------------------------
# Check that a DROP TABLE does an implicit DELETE FROM. Which does not
# cause any triggers to fire, but does fire foreign key actions.
#
# EVIDENCE-OF: R-14208-23986 If foreign key constraints are enabled when
# it is prepared, the DROP TABLE command performs an implicit DELETE to
2765
2766
2767
2768
2769
2770
2771

2772
2773
2774

2775
2776
2777
2778
2779
2780
2781
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778

2779
2780
2781
2782
2783
2784
2785
2786







+


-
+







#      default value.
#   2. Modifying foreign key definitions when a parent table is RENAMEd.
#   3. Running an implicit DELETE FROM command as part of DROP TABLE.
#
# EVIDENCE-OF: R-54142-41346 The properties of the DROP TABLE and ALTER
# TABLE commands described above only apply if foreign keys are enabled.
#
ifcapable altertable {
do_test e_fkey-61.1.1 {
  drop_all_tables
  execsql { CREATE TABLE t1(a, b) }
  execsql { CREATE TABLE t1(a, b) ; INSERT INTO t1 VALUES(1, 2) }
  catchsql { ALTER TABLE t1 ADD COLUMN c DEFAULT 'xxx' REFERENCES t2 }
} {1 {Cannot add a REFERENCES column with non-NULL default value}}
do_test e_fkey-61.1.2 {
  execsql { PRAGMA foreign_keys = OFF }
  execsql { ALTER TABLE t1 ADD COLUMN c DEFAULT 'xxx' REFERENCES t2 }
  execsql { SELECT sql FROM sqlite_master WHERE name = 't1' }
} {{CREATE TABLE t1(a, b, c DEFAULT 'xxx' REFERENCES t2)}}
2826
2827
2828
2829
2830
2831
2832

2833
2834
2835
2836
2837
2838
2839
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845







+







    DROP TABLE p;
    SELECT * FROM c;
  }
} {x}
do_test e_fkey-61.3.3 {
  execsql { PRAGMA foreign_keys = ON }
} {}
}

###########################################################################
### SECTION 6: Limits and Unsupported Features
###########################################################################

#-------------------------------------------------------------------------
# Test that MATCH clauses are parsed, but SQLite treats every foreign key

Changes to test/e_select.test.

92
93
94
95
96
97
98
99

100
101
102
103
104
105
106
92
93
94
95
96
97
98

99
100
101
102
103
104
105
106







-
+







  SELECT count(*) FROM t1 %JOIN% t2 USING (a)
} {3}
do_join_test e_select-0.1.3 {
  SELECT count(*) FROM t1 %JOIN% t2
} {9}
do_catchsql_test e_select-0.1.4 {
  SELECT count(*) FROM t1, t2 ON (t1.a=t2.a) USING (a)
} {1 {cannot have both ON and USING clauses in the same join}}
} {1 {near "USING": syntax error}}
do_catchsql_test e_select-0.1.5 {
  SELECT count(*) FROM t1, t2 USING (a) ON (t1.a=t2.a)
} {1 {near "ON": syntax error}}

# -- syntax diagram select-core
#
#   0: SELECT ...
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
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







-
+







-
+
-







-
+
-


















-
+







-
+
-








-
+







  2002.1  "SELECT ALL 1, 2, 3 GROUP BY 2 HAVING count(*)=1" {1 2 3}
  2002.2  "SELECT ALL 1, 2, 3 GROUP BY 2 HAVING count(*)>1" {}

  0101.1  "SELECT count(*), max(a) FROM t1 GROUP BY b" {1 a 1 c 1 b}
  0102.1  "SELECT count(*), max(a) FROM t1 GROUP BY b HAVING count(*)=1" {
    1 a 1 c 1 b
  }
  0102.2  "SELECT count(*), max(a) FROM t1 GROUP BY b HAVING count(*)=2" { }
  0102.2  "SELECT count(*), max(a) FROM t1 GROUP BY b HAVING count(*)=2" {}

  1101.1  "SELECT DISTINCT count(*), max(a) FROM t1 GROUP BY b" {1 a 1 c 1 b}
  1102.1  "SELECT DISTINCT count(*), max(a) FROM t1 
           GROUP BY b HAVING count(*)=1" {
    1 a 1 c 1 b
  }
  1102.2  "SELECT DISTINCT count(*), max(a) FROM t1 
           GROUP BY b HAVING count(*)=2" { 
           GROUP BY b HAVING count(*)=2" {}
  }

  2101.1  "SELECT ALL count(*), max(a) FROM t1 GROUP BY b" {1 a 1 c 1 b}
  2102.1  "SELECT ALL count(*), max(a) FROM t1 
           GROUP BY b HAVING count(*)=1" {
    1 a 1 c 1 b
  }
  2102.2  "SELECT ALL count(*), max(a) FROM t1 
           GROUP BY b HAVING count(*)=2" { 
           GROUP BY b HAVING count(*)=2" {}
  }

  0011.1  "SELECT 1, 2, 3 WHERE 1 GROUP BY 2" {1 2 3}
  0012.1  "SELECT 1, 2, 3 WHERE 0 GROUP BY 2 HAVING count(*)=1" {}
  0012.2  "SELECT 1, 2, 3 WHERE 0 GROUP BY 2 HAVING count(*)>1" {}

  1011.1  "SELECT DISTINCT 1, 2, 3 WHERE 0 GROUP BY 2" {}
  1012.1  "SELECT DISTINCT 1, 2, 3 WHERE 1 GROUP BY 2 HAVING count(*)=1" 
          {1 2 3}
  1012.2  "SELECT DISTINCT 1, 2, 3 WHERE NULL GROUP BY 2 HAVING count(*)>1" {}

  2011.1  "SELECT ALL 1, 2, 3 WHERE 1 GROUP BY 2" {1 2 3}
  2012.1  "SELECT ALL 1, 2, 3 WHERE 0 GROUP BY 2 HAVING count(*)=1" {}
  2012.2  "SELECT ALL 1, 2, 3 WHERE 'abc' GROUP BY 2 HAVING count(*)>1" {}

  0111.1  "SELECT count(*), max(a) FROM t1 WHERE a='a' GROUP BY b" {1 a}
  0112.1  "SELECT count(*), max(a) FROM t1 
           WHERE a='c' GROUP BY b HAVING count(*)=1" {1 c}
  0112.2  "SELECT count(*), max(a) FROM t1 
           WHERE 0 GROUP BY b HAVING count(*)=2" { }
           WHERE 0 GROUP BY b HAVING count(*)=2" {}
  1111.1  "SELECT DISTINCT count(*), max(a) FROM t1 WHERE a<'c' GROUP BY b" 
          {1 a 1 b}
  1112.1  "SELECT DISTINCT count(*), max(a) FROM t1 WHERE a>'a'
           GROUP BY b HAVING count(*)=1" {
    1 c 1 b
  }
  1112.2  "SELECT DISTINCT count(*), max(a) FROM t1 WHERE 0
           GROUP BY b HAVING count(*)=2" { 
           GROUP BY b HAVING count(*)=2" {}
  }

  2111.1  "SELECT ALL count(*), max(a) FROM t1 WHERE b>'one' GROUP BY b" 
          {1 c 1 b}
  2112.1  "SELECT ALL count(*), max(a) FROM t1 WHERE a!='b'
           GROUP BY b HAVING count(*)=1" {
    1 a 1 c
  }
  2112.2  "SELECT ALL count(*), max(a) FROM t1 
           WHERE 0 GROUP BY b HAVING count(*)=2" { }
           WHERE 0 GROUP BY b HAVING count(*)=2" {}
}


# -- syntax diagram result-column
#
do_select_tests e_select-0.3 {
  1  "SELECT * FROM t1" {a one b two c three}
617
618
619
620
621
622
623

624

625
626
627
628


629
630
631
632
633
634
635
614
615
616
617
618
619
620
621

622
623
624


625
626
627
628
629
630
631
632
633







+
-
+


-
-
+
+







     {aa cc cc bb DD dd}
  4b { SELECT * FROM (SELECT a COLLATE nocase, b FROM t6) AS x
       %JOIN% t5 ON (x.a=t5.a) } 
     {aa cc AA cc bb DD BB dd}
} {
  do_join_test e_select-1.7.$tn $select $res
}

# EVIDENCE-OF: R-42531-52874 If the join-operator is a "LEFT JOIN" or
# EVIDENCE-OF: R-24610-05866 If the join-operator is a "LEFT JOIN" or
# "LEFT OUTER JOIN", then after the ON or USING filtering clauses have
# been applied, an extra row is added to the output for each row in the
# original left-hand input dataset that corresponds to no rows at all in
# the composite dataset (if any).
# original left-hand input dataset that does not match any row in the
# right-hand dataset.
#
do_execsql_test e_select-1.8.0 {
  CREATE TABLE t7(a, b, c);
  CREATE TABLE t8(a, d, e);

  INSERT INTO t7 VALUES('x', 'ex',  24);
  INSERT INTO t7 VALUES('y', 'why', 25);
1003
1004
1005
1006
1007
1008
1009
1010

1011
1012

1013
1014
1015



1016
1017
1018
1019
1020
1021
1022
1001
1002
1003
1004
1005
1006
1007

1008
1009
1010
1011



1012
1013
1014
1015
1016
1017
1018
1019
1020
1021







-
+


+
-
-
-
+
+
+







  CREATE TABLE b3(a COLLATE nocase, b COLLATE binary);
  INSERT INTO b3 VALUES('abc', 'abc');
  INSERT INTO b3 VALUES('aBC', 'aBC');
  INSERT INTO b3 VALUES('Def', 'Def');
  INSERT INTO b3 VALUES('dEF', 'dEF');
} {}

# EVIDENCE-OF: R-07284-35990 If the SELECT statement is an aggregate
# EVIDENCE-OF: R-40855-36147 If the SELECT statement is an aggregate
# query with a GROUP BY clause, then each of the expressions specified
# as part of the GROUP BY clause is evaluated for each row of the
# dataset according to the processing rules stated below for ORDER BY
# dataset. Each row is then assigned to a "group" based on the results;
# rows for which the results of evaluating the GROUP BY expressions are
# the same get assigned to the same group.
# expressions. Each row is then assigned to a "group" based on the
# results; rows for which the results of evaluating the GROUP BY
# expressions are the same get assigned to the same group.
#
#   These tests also show that the following is not untrue:
#
# EVIDENCE-OF: R-25883-55063 The expressions in the GROUP BY clause do
# not have to be expressions that appear in the result.
#
do_select_tests e_select-4.9 {

Changes to test/e_totalchanges.test.

28
29
30
31
32
33
34
35
36
37



38
39
40
41
42
43
44
45
28
29
30
31
32
33
34



35
36
37

38
39
40
41
42
43
44







-
-
-
+
+
+
-







  CREATE INDEX t1_b ON t1(b);
  CREATE TABLE t2(x, y, PRIMARY KEY(x, y)) WITHOUT ROWID;
  CREATE INDEX t2_y ON t2(y);
}


#--------------------------------------------------------------------------
# EVIDENCE-OF: R-65438-26258 This function returns the total number of
# rows inserted, modified or deleted by all INSERT, UPDATE or DELETE
# statements completed since the database connection was opened,
# EVIDENCE-OF: R-38914-26427 The total_changes() function returns the
# number of row changes caused by INSERT, UPDATE or DELETE statements
# since the current database connection was opened.
# including those executed as part of trigger programs.
#
#   1.1.*: different types of I/U/D statements,
#   1.2.*: trigger programs.
#
do_tc_test 1.1.1 {
  INSERT INTO t1 VALUES(1, 2);
  INSERT INTO t1 VALUES(3, 4);
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
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







+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  UPDATE t1 SET b='c';               -- 1 + 1 + 2
  DELETE FROM t1;                    -- 1 + 1 + 1
} {9}

#--------------------------------------------------------------------------
# EVIDENCE-OF: R-61766-15253 Executing any other type of SQL statement
# does not affect the value returned by sqlite3_total_changes().
ifcapable altertable {
do_tc_test 2.1 {
  INSERT INTO t1 VALUES(1, 2), (3, 4);
  INSERT INTO t2 VALUES(1, 2), (3, 4);
} {15}
do_tc_test 2.2 {
  SELECT count(*) FROM t1;
} {2 15}
do_tc_test 2.3 {
  CREATE TABLE t4(a, b);
  ALTER TABLE t4 ADD COLUMN c;
  CREATE INDEX i4 ON t4(c);
  ALTER TABLE t4 RENAME TO t5;
  ANALYZE;
  BEGIN;
  DROP TABLE t2;
  ROLLBACK;
  VACUUM;
} {15}
  do_tc_test 2.1 {
    INSERT INTO t1 VALUES(1, 2), (3, 4);
    INSERT INTO t2 VALUES(1, 2), (3, 4);
  } {15}
  do_tc_test 2.2 {
    SELECT count(*) FROM t1;
  } {2 15}
  do_tc_test 2.3 {
    CREATE TABLE t4(a, b);
    ALTER TABLE t4 ADD COLUMN c;
    CREATE INDEX i4 ON t4(c);
    ALTER TABLE t4 RENAME TO t5;
    ANALYZE;
    BEGIN;
    DROP TABLE t2;
    ROLLBACK;
    VACUUM;
  } {15}
}


#--------------------------------------------------------------------------
# EVIDENCE-OF: R-36043-10590 Changes made as part of foreign key
# actions are included in the count, but those made as part of REPLACE
# constraint resolution are not.
#

Changes to test/e_uri.test.

21
22
23
24
25
26
27

28
29
30
31
32
33
34
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35







+







  testvfs tvfs 
  tvfs filter xOpen
  tvfs script parse_uri_open_cb

  set ::uri_open [list]
  set DB [sqlite3_open_v2 $uri {
    SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_WAL
    SQLITE_OPEN_EXRESCODE
  } tvfs]
  set fileName [sqlite3_db_filename $DB main]
  sqlite3_close $DB
  forcedelete $fileName
  tvfs delete
  tvfs2 delete

353
354
355
356
357
358
359

360
361
362
363
364
365
366
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368







+







  2    {file:test.db?cache=shared}     {not an error}
  3    {file:test.db?cache=yes}        {no such cache mode: yes}
  4    {file:test.db?cache=}           {no such cache mode: }
" {
  do_test 10.$tn { open_uri_error $uri } $error
}

ifcapable shared_cache {
# EVIDENCE-OF: R-23027-03515 Setting it to "shared" is equivalent to
# setting the SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed
# to sqlite3_open_v2().
#
# EVIDENCE-OF: R-49793-28525 Setting the cache parameter to "private" is
# equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
#
425
426
427
428
429
430
431

432
433
434
435
436
437
438
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441







+








  do_test 11.$tn { sqlite3_errmsg $DB } $RES($isshared)

  sqlite3_close $DB
  db close
}
sqlite3_enable_shared_cache $orig
}  ;#  End ifcapable shared_chache

# EVIDENCE-OF: R-63472-46769 Specifying an unknown parameter in the
# query component of a URI is not an error.
#
do_filepath_test 12.1 {
  parse_uri file://localhost/test.db?an=unknown&parameter=is&ok=
} {/test.db {an unknown parameter is ok {}}}

Changes to test/e_vacuum.test.

186
187
188
189
190
191
192
193
194


195
196
197
198
199
200
201
186
187
188
189
190
191
192


193
194
195
196
197
198
199
200
201







-
-
+
+







      execsql { PRAGMA auto_vacuum = FULL }
      execsql VACUUM
      execsql { PRAGMA page_size ; PRAGMA auto_vacuum }
    } {2048 1}
  }
}
  
# EVIDENCE-OF: R-55119-57913 By default, VACUUM only works only on the
# main database.
# EVIDENCE-OF: R-40347-36128 By default, VACUUM operates on the main
# database.
forcedelete test.db2
create_db { PRAGMA auto_vacuum = NONE }
do_execsql_test e_vacuum-2.1.1 {
  ATTACH 'test.db2' AS aux;
  PRAGMA aux.page_size = 1024;
  CREATE TABLE aux.t3 AS SELECT * FROM t1;
  DELETE FROM t3;
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
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







+
+













+













+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+







# entries in any tables that do not have an explicit INTEGER PRIMARY
# KEY.
#
#   Tests e_vacuum-3.1.1 - 3.1.2 demonstrate that rowids can change when
#   a database is VACUUMed. Tests e_vacuum-3.1.3 - 3.1.4 show that adding
#   an INTEGER PRIMARY KEY column to a table stops this from happening.
#
#   Update 2019-01-07:  Rowids are now preserved by VACUUM.
#
do_execsql_test e_vacuum-3.1.1 {
  CREATE TABLE t4(x);
  INSERT INTO t4(x) VALUES('x');
  INSERT INTO t4(x) VALUES('y');
  INSERT INTO t4(x) VALUES('z');
  DELETE FROM t4 WHERE x = 'y';
  SELECT rowid, x FROM t4;
} {1 x 3 z}
do_execsql_test e_vacuum-3.1.2 {
  VACUUM;
  SELECT rowid, x FROM t4;
} {1 x 2 z}

# Rowids are preserved if an INTEGER PRIMARY KEY is used
do_execsql_test e_vacuum-3.1.3 {
  CREATE TABLE t5(x, y INTEGER PRIMARY KEY);
  INSERT INTO t5(x) VALUES('x');
  INSERT INTO t5(x) VALUES('y');
  INSERT INTO t5(x) VALUES('z');
  DELETE FROM t5 WHERE x = 'y';
  SELECT rowid, x FROM t5;
} {1 x 3 z}
do_execsql_test e_vacuum-3.1.4 {
  VACUUM;
  SELECT rowid, x FROM t5;
} {1 x 3 z}

# Rowid is preserved for VACUUM INTO
do_execsql_test e_vacuum-3.1.5 {
  DROP TABLE t5;
  CREATE TABLE t5(x);
  INSERT INTO t5(x) VALUES('x');
  INSERT INTO t5(x) VALUES('y');
  INSERT INTO t5(x) VALUES('z');
  DELETE FROM t5 WHERE x = 'y';
  SELECT rowid, x FROM t5;
} {1 x 3 z}
forcedelete test2.db
do_execsql_test e_vacuum-3.1.6 {
  VACUUM INTO 'test2.db';
  ATTACH 'test2.db' AS aux1;
  SELECT rowid, x FROM aux1.t5;
  DETACH aux1;
} {1 x 3 z}

# Rowids are not renumbered if the table being vacuumed
# has indexes.
do_execsql_test e_vacuum-3.1.7 {
  DROP TABLE t5;
  CREATE TABLE t5(x,y,z);
  INSERT INTO t5(x) VALUES('x');
  INSERT INTO t5(x) VALUES('y');
  INSERT INTO t5(x) VALUES('z');
  UPDATE t5 SET y=x, z=random();
  DELETE FROM t5 WHERE x = 'y';
  CREATE INDEX t5x ON t5(x);
  CREATE UNIQUE INDEX t5y ON t5(y);
  CREATE INDEX t5zxy ON t5(z,x,y);
  SELECT rowid, x FROM t5;
} {1 x 3 z}
do_execsql_test e_vacuum-3.1.8 {
  VACUUM;
  SELECT rowid, x FROM t5;
} {1 x 3 z}

# EVIDENCE-OF: R-49563-33883 A VACUUM will fail if there is an open
# transaction, or if there are one or more active SQL statements when it
# is run.
# EVIDENCE-OF: R-12218-18073 A VACUUM will fail if there is an open
# transaction on the database connection that is attempting to run the
# VACUUM.
#
do_execsql_test  e_vacuum-3.2.1.1 { BEGIN } {}
do_catchsql_test e_vacuum-3.2.1.2 { 
  VACUUM 
} {1 {cannot VACUUM from within a transaction}}
do_execsql_test  e_vacuum-3.2.1.3 { COMMIT } {}
do_execsql_test  e_vacuum-3.2.1.4 { VACUUM } {}

Changes to test/e_wal.test.

11
12
13
14
15
16
17

18
19
20
21
22
23
24
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25







+







#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix e_wal

db close
forcedelete test.db-shm 
testvfs oldvfs -iversion 1


# EVIDENCE-OF: R-58297-14483 WAL databases can be created, read, and
# written even if shared memory is unavailable as long as the
# locking_mode is set to EXCLUSIVE before the first attempted access.
#

Changes to test/enc.test.

164
165
166
167
168
169
170
















































































171
172
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


} {}
do_test enc-11.2 {
  set cp200 "\u00C8"
  execsql {
    SELECT count(*) FROM ab WHERE a = $::cp200;
  }
} {2}

#-------------------------------------------------------------------------
reset_db
forcedelete test.db2
forcedelete test.db3

do_execsql_test enc-12.0 {
  PRAGMA encoding = 'utf-8';
  CREATE TABLE t1(a, b, c);
  INSERT INTO t1 VALUES('a', 'b', 'c');
  ATTACH 'test.db3' AS aux;
  CREATE TABLE aux.t3(x, y, z);
  INSERT INTO t3 VALUES('xxx', 'yyy', 'zzz');
  PRAGMA encoding;
} {UTF-8}

do_test enc-12.1 {
  sqlite3 db2 test.db2
  db2 eval {
    PRAGMA encoding = 'UTF-16le';
    CREATE TABLE t2(d, e, f);
    INSERT INTO t2 VALUES('d', 'e', 'f');
    PRAGMA encoding;
  }
} {UTF-16le}

do_test enc-12.2 {
  db2 backup test.db
  db2 close
} {}

do_catchsql_test enc-12.3 {
  SELECT * FROM t2;
} {1 {attached databases must use the same text encoding as main database}}

db close
sqlite3 db test.db3
do_execsql_test enc-12.4 {
  SELECT * FROM t3;
  PRAGMA encoding = 'UTF-16le';
  SELECT * FROM t3;
} {xxx yyy zzz xxx yyy zzz}

db close
sqlite3 db test.db3
breakpoint
do_execsql_test enc-12.5 {
  PRAGMA encoding = 'UTF-16le';
  PRAGMA encoding;
} {UTF-8}

reset_db
do_execsql_test enc-12.6 {
  PRAGMA encoding = 'UTF-8';
  CREATE TEMP TABLE t1(a, b, c);
  INSERT INTO t1 VALUES('xxx', 'yyy', 'zzz');
}
do_test enc-12.7 {
  sqlite3 db2 test.db2
  db2 backup test.db
  db2 close
  db eval {
    SELECT * FROM t1;
  }
} {xxx yyy zzz}
do_catchsql_test enc-12.8 {
  SELECT * FROM t2;
  SELECT * FROM t1;
} {1 {attached databases must use the same text encoding as main database}}

db close
sqlite3 db test.db
do_execsql_test enc-12.9 {
  CREATE TEMP TABLE t1(a, b, c);
  INSERT INTO t1 VALUES('xxx', 'yyy', 'zzz');
}
do_execsql_test enc-12.10 {
  SELECT * FROM t2;
  SELECT * FROM t1;
} {d e f xxx yyy zzz}

finish_test

Changes to test/enc2.test.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
9
10
11
12
13
14
15

16
17
18
19
20
21
22







-







#
#***********************************************************************
# This file implements regression tests for SQLite library.  The focus of
# this file is testing the SQLite routines used for converting between the
# various suported unicode encodings (UTF-8, UTF-16, UTF-16le and
# UTF-16be).
#
# $Id: enc2.test,v 1.29 2007/10/09 08:29:32 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# If UTF16 support is disabled, ignore the tests in this file
#
ifcapable {!utf16} {
547
548
549
550
551
552
553
554













555
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567








+
+
+
+
+
+
+
+
+
+
+
+
+

  }
  db close
  sqlite3 db test.db
  db eval {
    SELECT name FROM sqlite_master
  }
} {t1 t2}

# 2020-01-15 ticket a08879a4a476eea9
# Do not allow a database connection encoding change unless *all*
# attached databases are empty.
#
reset_db
do_execsql_test enc2-11.10 {
  PRAGMA encoding=UTF8;
  CREATE TEMP TABLE t1(x);
  INSERT INTO t1 VALUES('this is a test');
  PRAGMA encoding=UTF16;
  SELECT * FROM t1;
} {{this is a test}}

finish_test

Changes to test/enc3.test.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
9
10
11
12
13
14
15

16
17
18
19
20
21
22







-







#
#***********************************************************************
# This file implements regression tests for SQLite library. 
#
# The focus of this file is testing of the proper handling of conversions
# to the native text representation.
#
# $Id: enc3.test,v 1.8 2008/01/22 01:48:09 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable {utf16} {
  do_test enc3-1.1 {
    execsql {

Changes to test/eqp.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
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
41
42
43
44
45
46
47
48



49
50
51
52
53
54
55
56
57

58
59
60


61
62
63
64
65
66
67
68

69
70
71
72
73
74

75
76
77
78
79
80
81

82
83
84
85
86
87

88
89
90
91
92

93
94
95
96
97
98

99
100
101
102
103
104
105
106
107


108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125

126
127
128
129
130
131


132
133
134
135

136
137
138

139
140
141
142
143



144
145
146
147
148

149
150
151

152
153
154
155
156



157
158
159
160
161
162

163
164
165

166
167
168
169
170



171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188

189
190
191
192
193
194
195

196
197
198
199
200
201

202
203
204
205
206


207
208
209
210
211
212


213
214
215
216
217
218
219


220
221
222
223
224
225

226
227
228
229

230
231
232
233

234
235
236
237
238

239
240
241
242
243
244
245
246
247
248
249
250



251
252
253
254
255
256
257
258



259
260
261
262
263
264
265
266



267
268
269
270
271
272
273
274
275



276
277
278
279
280
281
282
283
284


285
286
287

288
289
290
291
292
293
294
295
296
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 TABLE t1 USING INDEX i2 (b=?)
  `--SCAN TABLE t2
  |  |  `--SEARCH t1 USING INDEX i1 (a=?)
  |  `--INDEX 2
  |     `--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 TABLE t1 USING INDEX i2 (b=?)
     |  `--SEARCH t1 USING INDEX i1 (a=?)
     `--INDEX 2
        `--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
  |--CO-ROUTINE (subquery-xxxxxx)
  |  `--SCAN CONSTANT ROW
  |--MATERIALIZE xxxxxx
  |--SCAN (subquery-xxxxxx)
  `--SCAN t3
}
do_eqp_test 1.7.2 {
  SELECT * FROM t3 JOIN (SELECT 1) AS v1
} {
  QUERY PLAN
  |--CO-ROUTINE v1
  |  `--SCAN CONSTANT ROW
  |--SCAN SUBQUERY xxxxxx
  `--SCAN TABLE t3
  |--SCAN v1
  `--SCAN t3
}
do_eqp_test 1.7.3 {
  SELECT * FROM t3 AS xx JOIN (SELECT 1) AS yy
} {
  QUERY PLAN
  |--CO-ROUTINE 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
  |--CO-ROUTINE (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 (subquery-xxxxxx)
  `--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
  |--CO-ROUTINE 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
  |--CO-ROUTINE 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
  |--CO-ROUTINE 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
  `--SCALAR SUBQUERY
     `--SCAN TABLE t1 AS sub
  |--SCAN t1
  `--SCALAR SUBQUERY xxxxxx
     `--SCAN sub
}
do_eqp_test 3.1.2 {
  SELECT * FROM t1 WHERE (SELECT x FROM t1 AS sub);
} {
  QUERY PLAN
  |--SCAN TABLE t1
  `--SCALAR SUBQUERY
     `--SCAN TABLE t1 AS sub
  |--SCAN t1
  `--SCALAR SUBQUERY xxxxxx
     `--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
  `--SCALAR SUBQUERY
     |--SCAN TABLE t1 AS sub
  |--SCAN t1
  `--SCALAR SUBQUERY xxxxxx
     |--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
  `--SCALAR SUBQUERY
     `--SCAN TABLE t2 USING COVERING INDEX t2i1
  |--SCAN t1
  `--SCALAR SUBQUERY xxxxxx
     `--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
  |--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
  |--CO-ROUTINE 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
  `--LIST SUBQUERY
     `--SCAN TABLE t2
  |--SCAN t1
  `--LIST SUBQUERY xxxxxx
     `--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
  `--CORRELATED LIST SUBQUERY
     `--SCAN TABLE t2
  |--SCAN t1
  `--CORRELATED LIST SUBQUERY xxxxxx
     `--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
  `--CORRELATED SCALAR SUBQUERY
     `--SCAN TABLE t2
  |--SCAN t1
  `--CORRELATED SCALAR SUBQUERY xxxxxx
     `--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 
639
640
641
642
643
644
645
646
647


648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668

669
670
671
672
673

674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692

693
694
695
696
697

698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713

714
715
716
717
718

719
720
721
722
723

724
725
726
727
728

729
730
731
732
733

734
735
736
737
738

739
740
741
742
743

744
745
746
747
748
749
750
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 {
806
807
808
809
810
811
812
813
814


815
816
817


818
819
820
821
822



823
824
825
826
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
  |--CO-ROUTINE thread
  |  |--SCAN x USING INDEX forumthread
  |  |--USING ROWID SEARCH ON TABLE private FOR IN-OPERATOR
  |  |--CORRELATED SCALAR SUBQUERY
  |  |  |--SEARCH TABLE forumpost USING COVERING INDEX forumthread (froot=?)
  |  |--CORRELATED SCALAR SUBQUERY xxxxxx
  |  |  |--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

Changes to test/eval.test.

77
78
79
80
81
82
83
84

85
86
87
77
78
79
80
81
82
83

84
85
86
87







-
+



  execsql {
    INSERT INTO t2 SELECT x, x+1 FROM t1 WHERE x<5;
    SELECT x, test_eval('UPDATE t2 SET y=y+100 WHERE x='||x), y FROM t2;
  }
} {1 {} 102 2 {} 103 3 {} 104 4 {} 105}

do_test eval-4.1 {
  execsql { SELECT test_eval('SELECT "abcdefghij"') }
  execsql { SELECT test_eval('SELECT ''abcdefghij''') }
} {abcdefghij}

finish_test

Changes to test/exclusive.test.

506
507
508
509
510
511
512
























513
514
515
516
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




  sqlite3 db test.db
} {}

do_execsql_test exclusive-6.5 {
  PRAGMA locking_mode = EXCLUSIVE;
  SELECT * FROM sqlite_master;
} {exclusive}

# 2019-12-26 ticket fb3b3024ea238d5c
if {[permutation]!="journaltest"} {
  # The custom VFS used by the "journaltest" permutation cannot open the
  # shared-memory file. So, while it is able to switch the db file to
  # journal_mode=WAL when locking_mode=EXCLUSIVE, it can no longer access
  # it once the locking_mode is changed back to NORMAL.
  do_test exclusive-7.1 {
    db close
    forcedelete test.db test.db-journal test.db-wal
    sqlite3 db test.db
    # The following sequence of pragmas would trigger an assert()
    # associated with Pager.changeCountDone inside of assert_pager_state(),
    # prior to the fix.
    db eval {
      PRAGMA locking_mode = EXCLUSIVE;
      PRAGMA journal_mode = WAL;
      PRAGMA locking_mode = NORMAL;
      PRAGMA user_version;
      PRAGMA journal_mode = DELETE;
    }
  } {exclusive wal normal 0 delete}
}
 

} ;# atomic_batch_write==0

finish_test

Changes to test/expr.test.

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
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







+

+

+

+


+
+


+
+


+
+


+
+

+

+

+

+


+
+


+
+


+
+


+
+







test_expr expr-1.109 {i1=0} {1/0} {{}}

if {[working_64bit_int]} {
  test_expr expr-1.110 {i1=0} {-9223372036854775807/-1} 9223372036854775807
}

test_expr expr-1.111 {i1=NULL, i2=8} {i1 IS i2} 0
test_expr expr-1.111b {i1=NULL, i2=8} {i1 IS NOT DISTINCT FROM i2} 0
test_expr expr-1.112 {i1=NULL, i2=NULL} {i1 IS i2} 1
test_expr expr-1.112b {i1=NULL, i2=NULL} {i1 IS NOT DISTINCT FROM i2} 1
test_expr expr-1.113 {i1=6, i2=NULL} {i1 IS i2} 0
test_expr expr-1.113b {i1=6, i2=NULL} {i1 IS NOT DISTINCT FROM i2} 0
test_expr expr-1.114 {i1=6, i2=6} {i1 IS i2} 1
test_expr expr-1.114b {i1=6, i2=6} {i1 IS NOT DISTINCT FROM i2} 1
test_expr expr-1.115 {i1=NULL, i2=8} \
  {CASE WHEN i1 IS i2 THEN 'yes' ELSE 'no' END} no
test_expr expr-1.115b {i1=NULL, i2=8} \
  {CASE WHEN i1 IS NOT DISTINCT FROM i2 THEN 'yes' ELSE 'no' END} no
test_expr expr-1.116 {i1=NULL, i2=NULL} \
  {CASE WHEN i1 IS i2 THEN 'yes' ELSE 'no' END} yes
test_expr expr-1.116b {i1=NULL, i2=NULL} \
  {CASE WHEN i1 IS NOT DISTINCT FROM i2 THEN 'yes' ELSE 'no' END} yes
test_expr expr-1.117 {i1=6, i2=NULL} \
  {CASE WHEN i1 IS i2 THEN 'yes' ELSE 'no' END} no
test_expr expr-1.117b {i1=6, i2=NULL} \
  {CASE WHEN i1 IS NOT DISTINCT FROM i2 THEN 'yes' ELSE 'no' END} no
test_expr expr-1.118 {i1=8, i2=8} \
  {CASE WHEN i1 IS i2 THEN 'yes' ELSE 'no' END} yes
test_expr expr-1.118b {i1=8, i2=8} \
  {CASE WHEN i1 IS NOT DISTINCT FROM i2 THEN 'yes' ELSE 'no' END} yes
test_expr expr-1.119 {i1=NULL, i2=8} {i1 IS NOT i2} 1
test_expr expr-1.119b {i1=NULL, i2=8} {i1 IS DISTINCT FROM i2} 1
test_expr expr-1.120 {i1=NULL, i2=NULL} {i1 IS NOT i2} 0
test_expr expr-1.120b {i1=NULL, i2=NULL} {i1 IS DISTINCT FROM i2} 0
test_expr expr-1.121 {i1=6, i2=NULL} {i1 IS NOT i2} 1
test_expr expr-1.121b {i1=6, i2=NULL} {i1 IS DISTINCT FROM i2} 1
test_expr expr-1.122 {i1=6, i2=6} {i1 IS NOT i2} 0
test_expr expr-1.122b {i1=6, i2=6} {i1 IS DISTINCT FROM i2} 0
test_expr expr-1.123 {i1=NULL, i2=8} \
  {CASE WHEN i1 IS NOT i2 THEN 'yes' ELSE 'no' END} yes
test_expr expr-1.123b {i1=NULL, i2=8} \
  {CASE WHEN i1 IS DISTINCT FROM i2 THEN 'yes' ELSE 'no' END} yes
test_expr expr-1.124 {i1=NULL, i2=NULL} \
  {CASE WHEN i1 IS NOT i2 THEN 'yes' ELSE 'no' END} no
test_expr expr-1.124b {i1=NULL, i2=NULL} \
  {CASE WHEN i1 IS DISTINCT FROM i2 THEN 'yes' ELSE 'no' END} no
test_expr expr-1.125 {i1=6, i2=NULL} \
  {CASE WHEN i1 IS NOT i2 THEN 'yes' ELSE 'no' END} yes
test_expr expr-1.125b {i1=6, i2=NULL} \
  {CASE WHEN i1 IS DISTINCT FROM i2 THEN 'yes' ELSE 'no' END} yes
test_expr expr-1.126 {i1=8, i2=8} \
  {CASE WHEN i1 IS NOT i2 THEN 'yes' ELSE 'no' END} no
test_expr expr-1.126b {i1=8, i2=8} \
  {CASE WHEN i1 IS DISTINCT FROM i2 THEN 'yes' ELSE 'no' END} no

do_catchsql_test expr-1.127 {
  SELECT 1 IS #1;
} {1 {near "#1": syntax error}}

ifcapable floatingpoint {if {[working_64bit_int]} {
  test_expr expr-1.200\
966
967
968
969
970
971
972

973
974
975
976
977
978
979
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004







+







} {9.22337203685478e+18}
do_realnum_test expr-13.7 {
  execsql {
    SELECT '9223372036854775807.0'+0
  }
} {9.22337203685478e+18}

sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1
do_execsql_test expr-13.8 {
  SELECT "" <= '';
} {1}
do_execsql_test expr-13.9 {
  SELECT '' <= "";
} {1}

1031
1032
1033
1034
1035
1036
1037
1038




















1039
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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  } {0}

  do_execsql_test expr-15.$tn.6 {
    SELECT sum(CASE WHEN x THEN 0 ELSE 1 END) FROM t1
     WHERE x
  } {0}
}

reset_db
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db
do_execsql_test expr-16.1 {
  CREATE TABLE t1(a,b,c);
  CREATE TABLE dual(dummy);
  INSERT INTO dual VALUES('X');
} {}
do_execsql_test expr-16.100 {
  SELECT implies_nonnull_row( (b=1 AND 0)>(b=3 AND 0),a)
  FROM dual LEFT JOIN t1;
} {0}
do_execsql_test expr-16.101 {
  SELECT implies_nonnull_row( (b=1 AND 0)>(b=3 AND a=4),a)
  FROM dual LEFT JOIN t1;
} {1}
do_execsql_test expr-16.102 {
  SELECT implies_nonnull_row( (b=1 AND a=2)>(b=3 AND a=4),a)
  FROM dual LEFT JOIN t1;
} {1}

finish_test

Added test/expr2.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019 May 20
#
# 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 expressions.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix expr2

do_execsql_test 1.0 {
  CREATE TABLE t0(c0);
  INSERT INTO t0(c0) VALUES ('val');
}

do_execsql_test 1.1 {
  SELECT * FROM t0 WHERE (
      ( (0 IS NOT FALSE) OR NOT (0 IS FALSE OR (t0.c0 = 1)) ) IS 0
  )
} {val}

do_execsql_test 1.2.1 {
  SELECT 
      ( (0 IS NOT FALSE) OR NOT (0 IS FALSE OR (t0.c0 = 1)) ) IS 0
  FROM t0 
} {1}

do_execsql_test 1.2.2 {
  SELECT 
      ( (0 IS NOT FALSE) OR NOT (0 IS 0 OR (t0.c0 = 1)) ) IS 0
  FROM t0 
} {1}

do_execsql_test 1.3 {
  SELECT ( (0 IS NOT FALSE) OR NOT (0 IS FALSE OR (t0.c0 = 1)) ) FROM t0 
} {0}

do_execsql_test 1.4.1 {
  SELECT (0 IS NOT FALSE) FROM t0 
} {0}
do_execsql_test 1.4.2 {
  SELECT NOT (0 IS FALSE OR (t0.c0 = 1)) FROM t0 
} {0}


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
36
37
38
39
40
41
42
43
44
45
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 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 {}}
}

do_faultsim_test 2 -faults oom* -prep {
  faultsim_restore_and_reopen
} -body {
  execsql {
    SELECT hex ( unhex('ABCDEF') );
  }
} -test {
  faultsim_test_result {0 ABCDEF}
}


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/fallocate.test.

66
67
68
69
70
71
72









73
74
75
76
77
78
79
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88







+
+
+
+
+
+
+
+
+







    hexio_get_int [hexio_read test.db-journal 16 4]
  } else {
    set {} 1024
  }
} {1024}
do_test fallocate-1.8 { execsql { COMMIT } } {}

do_test fallocate-1.8 {
  set nPg [db one {PRAGMA page_count}]
  set nFile [expr [file size test.db] / 1024]
  list [expr $nPg<100] [expr $nFile>100]
} {1 1}

do_execsql_test fallocate-1.9 {
  PRAGMA max_page_count = 100;
} {100}

#-------------------------------------------------------------------------
# The following tests - fallocate-2.* - test that things work in WAL
# mode as well.
#
set skipwaltests [expr {
  [permutation]=="journaltest" || [permutation]=="inmemory_journal"

Added test/filter1.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2018 May 8
#
# 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 filter1

ifcapable !windowfunc {
  finish_test
  return
}

do_execsql_test 1.0 {
  CREATE TABLE t1(a);
  CREATE INDEX i1 ON t1(a);
  INSERT INTO t1 VALUES(1), (2), (3), (4), (5), (6), (7), (8), (9);
}

do_execsql_test 1.1 { SELECT sum(a) FROM t1; } 45
do_execsql_test 1.2 { SELECT sum(a) FILTER( WHERE a<5 ) FROM t1; } 10

do_execsql_test 1.3 { 
  SELECT sum(a) FILTER( WHERE a>9 ),
         sum(a) FILTER( WHERE a>8 ),
         sum(a) FILTER( WHERE a>7 ),
         sum(a) FILTER( WHERE a>6 ),
         sum(a) FILTER( WHERE a>5 ),
         sum(a) FILTER( WHERE a>4 ),
         sum(a) FILTER( WHERE a>3 ),
         sum(a) FILTER( WHERE a>2 ),
         sum(a) FILTER( WHERE a>1 ),
         sum(a) FILTER( WHERE a>0 )
  FROM t1;
} {{} 9 17 24 30 35 39 42 44 45}

do_execsql_test 1.4 {
  SELECT max(a) FILTER (WHERE (a % 2)==0) FROM t1
} {8}

do_execsql_test 1.5 {
  SELECT min(a) FILTER (WHERE a>4) FROM t1
} {5}

do_execsql_test 1.6 {
  SELECT count(*) FILTER (WHERE a!=5) FROM t1
} {8}

do_execsql_test 1.7 {
  SELECT min(a) FILTER (WHERE a>3) FROM t1 GROUP BY (a%2) ORDER BY 1;
} {4 5}

do_execsql_test 1.8 {
  CREATE VIEW vv AS 
  SELECT sum(a) FILTER( WHERE a>9 ),
         sum(a) FILTER( WHERE a>8 ),
         sum(a) FILTER( WHERE a>7 ),
         sum(a) FILTER( WHERE a>6 ),
         sum(a) FILTER( WHERE a>5 ),
         sum(a) FILTER( WHERE a>4 ),
         sum(a) FILTER( WHERE a>3 ),
         sum(a) FILTER( WHERE a>2 ),
         sum(a) FILTER( WHERE a>1 ),
         sum(a) FILTER( WHERE a>0 )
  FROM t1;
  SELECT * FROM vv;
} {{} 9 17 24 30 35 39 42 44 45}


#-------------------------------------------------------------------------
# Test some errors:
#
#   .1 FILTER on a non-aggregate function,
#   .2 Window function in FILTER clause,
#   .3 Aggregate function in FILTER clause,
#
reset_db
do_execsql_test 2.0 {
  CREATE TABLE t1(a);
  INSERT INTO t1 VALUES(1), (2), (3), (4), (5), (6), (7), (8), (9);
}

do_catchsql_test 2.1 {
  SELECT upper(a) FILTER (WHERE a=1) FROM t1
} {1 {FILTER may not be used with non-aggregate upper()}}

do_catchsql_test 2.2 {
  SELECT sum(a) FILTER (WHERE 1 - max(a) OVER () > 0) FROM t1
} {1 {misuse of window function max()}}

do_catchsql_test 2.3 {
  SELECT sum(a) FILTER (WHERE 1 - count(a)) FROM t1
} {1 {misuse of aggregate function count()}}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 3.0 {
  CREATE TABLE t1(a,b);
  INSERT INTO t1 VALUES(1, 1);
}
do_execsql_test 3.1 {
  SELECT b, max(a) FILTER (WHERE b='x') FROM t1;
} {1 {}}

do_execsql_test 3.2 {
  CREATE TABLE t2(a, b, c);
  INSERT INTO t2 VALUES(1, 2, 3);
  INSERT INTO t2 VALUES(1, 3, 4);
  INSERT INTO t2 VALUES(2, 5, 6);
  INSERT INTO t2 VALUES(2, 7, 8);
}
do_execsql_test 3.3 {
  SELECT a, c, max(b) FILTER (WHERE c='x') FROM t2 GROUP BY a;
} {1 3 {} 2 6 {}}

do_execsql_test 3.4 {
  DELETE FROM t2;
  INSERT INTO t2 VALUES(1, 5, 'x');
  INSERT INTO t2 VALUES(1, 2, 3);
  INSERT INTO t2 VALUES(1, 4, 'x');
  INSERT INTO t2 VALUES(2, 5, 6);
  INSERT INTO t2 VALUES(2, 7, 8);
}
do_execsql_test 3.5 {
  SELECT a, c, max(b) FILTER (WHERE c='x') FROM t2 GROUP BY a;
} {1 x 5 2 6 {}}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 4.0 {
  CREATE TABLE t1(a, b, c);
  INSERT INTO t1 VALUES('a', 0, 5);
  INSERT INTO t1 VALUES('a', 1, 10);
  INSERT INTO t1 VALUES('a', 0, 15);

  INSERT INTO t1 VALUES('b', 0, 5);
  INSERT INTO t1 VALUES('b', 1, 1000);
  INSERT INTO t1 VALUES('b', 0, 5);

  INSERT INTO t1 VALUES('c', 0, 1);
  INSERT INTO t1 VALUES('c', 1, 2);
  INSERT INTO t1 VALUES('c', 0, 3);
}

do_execsql_test 4.1 {
  SELECT avg(c) FILTER (WHERE b!=1) AS h FROM t1 GROUP BY a ORDER BY h;
} {2.0 5.0 10.0}
do_execsql_test 4.2 {
  SELECT avg(c) FILTER (WHERE b!=1) AS h FROM t1 GROUP BY a ORDER BY (h+1.0);
} {2.0 5.0 10.0}
do_execsql_test 4.3 {
  SELECT a, avg(c) FILTER (WHERE b!=1) AS h FROM t1 GROUP BY a ORDER BY avg(c);
} {c 2.0 a 10.0 b 5.0}
do_execsql_test 4.4 {
  SELECT a, avg(c) FILTER (WHERE b!=1) FROM t1 GROUP BY a ORDER BY 2
} {c 2.0 b 5.0 a 10.0}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 5.0 {
  CREATE TABLE t1(a, b);
  INSERT INTO t1 VALUES(1, 2);
  INSERT INTO t1 VALUES(1, 3);
}

do_execsql_test 5.1 {
  SELECT count(*) FILTER (WHERE b>2) FROM (SELECT * FROM t1) 
} {1}

do_execsql_test 5.2 {
  SELECT count(*) FILTER (WHERE b>2) OVER () FROM (SELECT * FROM t1) 
} {1 1}

do_execsql_test 5.3 {
  SELECT count(*) FILTER (WHERE b>2) OVER (ORDER BY b) FROM (SELECT * FROM t1) 
} {0 1}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 6.0 {
  CREATE TABLE t1(a,b);
  INSERT INTO t1 VALUES(1,1);
  INSERT INTO t1 VALUES(2,2);
  CREATE TABLE t2(x,y);
  INSERT INTO t2 VALUES(1,1);
}

do_execsql_test 6.1 {
  SELECT (SELECT COUNT(a) FILTER(WHERE x) FROM t2) FROM t1;
} {1 1}
do_execsql_test 6.2 {
  SELECT (SELECT COUNT(a+x) FROM t2) FROM t1;
} {1 1}
do_execsql_test 6.3 {
  SELECT (SELECT COUNT(a) FROM t2) FROM t1;
} {2}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 7.0 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
  INSERT INTO t1 VALUES(321, 100000);
  INSERT INTO t1 VALUES(111, 110000);
  INSERT INTO t1 VALUES(444, 120000);
  INSERT INTO t1 VALUES(222, 130000);
}

do_execsql_test 7.1 {
  SELECT max(a), max(a) FILTER (WHERE b<12345), b FROM t1;
} {
  444 {} 120000
}



finish_test

Added test/filter2.tcl.





































































































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2018 May 19
#
# 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.
#
#***********************************************************************
#

source [file join [file dirname $argv0] pg_common.tcl]

#=========================================================================


start_test filter2 "2019 July 2"

ifcapable !windowfunc

execsql_test 1.0 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b INTEGER);
  INSERT INTO t1 VALUES
   (1, 7), (2, 3), (3, 5), (4, 30), (5, 26), (6, 23), (7, 27),
   (8, 3), (9, 17), (10, 26), (11, 33), (12, 25), (13, NULL), (14, 47),
   (15, 36), (16, 13), (17, 45), (18, 31), (19, 11), (20, 36), (21, 37),
   (22, 21), (23, 22), (24, 14), (25, 16), (26, 3), (27, 7), (28, 29),
   (29, 50), (30, 38), (31, 3), (32, 36), (33, 12), (34, 4), (35, 46),
   (36, 3), (37, 48), (38, 23), (39, NULL), (40, 24), (41, 5), (42, 46),
   (43, 11), (44, NULL), (45, 18), (46, 25), (47, 15), (48, 18), (49, 23);
}

execsql_test 1.1 { SELECT sum(b) FROM t1 }

execsql_test 1.2 { SELECT sum(b) FILTER (WHERE a<10) FROM t1 }

execsql_test 1.3 { SELECT count(DISTINCT b) FROM t1 }

execsql_test 1.4 { SELECT count(DISTINCT b) FILTER (WHERE a!=19) FROM t1 }

execsql_test 1.5 { 
  SELECT min(b) FILTER (WHERE a>19),
         min(b) FILTER (WHERE a>0),
         max(a+b) FILTER (WHERE a>19),
         max(b+a) FILTER (WHERE a BETWEEN 10 AND 40)
  FROM t1;
}

execsql_test 1.6 { 
  SELECT min(b),
         min(b),
         max(a+b),
         max(b+a)
  FROM t1
  GROUP BY (a%10)
  ORDER BY 1, 2, 3, 4;
}

execsql_test 1.7 { 
  SELECT min(b) FILTER (WHERE a>19),
         min(b) FILTER (WHERE a>0),
         max(a+b) FILTER (WHERE a>19),
         max(b+a) FILTER (WHERE a BETWEEN 10 AND 40)
  FROM t1
  GROUP BY (a%10)
  ORDER BY 1, 2, 3, 4;
}

execsql_test 1.8 { 
  SELECT sum(a+b) FILTER (WHERE a=NULL) FROM t1
}

execsql_test 1.9 {
  SELECT (a%5) FROM t1 GROUP BY (a%5) 
  HAVING sum(b) FILTER (WHERE b<20) > 34
  ORDER BY 1
}

execsql_test 1.10 {
  SELECT (a%5), sum(b) FILTER (WHERE b<20) AS bbb
  FROM t1
  GROUP BY (a%5) HAVING sum(b) FILTER (WHERE b<20) >34
  ORDER BY 1
}

execsql_test 1.11 {
  SELECT (a%5), sum(b) FILTER (WHERE b<20) AS bbb
  FROM t1
  GROUP BY (a%5) HAVING sum(b) FILTER (WHERE b<20) >34
  ORDER BY 2
}

execsql_test 1.12 {
  SELECT (a%5), 
    sum(b) FILTER (WHERE b<20) AS bbb,
    count(distinct b) FILTER (WHERE b<20 OR a=13) AS ccc
  FROM t1 GROUP BY (a%5)
  ORDER BY 2
}

execsql_test 1.13 {
  SELECT 
    string_agg(CAST(b AS TEXT), '_') FILTER (WHERE b%2!=0),
    string_agg(CAST(b AS TEXT), '_') FILTER (WHERE b%2!=1),
    count(*) FILTER (WHERE b%2!=0),
    count(*) FILTER (WHERE b%2!=1)
  FROM t1;
}

execsql_float_test 1.14 {
  SELECT 
    avg(b) FILTER (WHERE b>a),
    avg(b) FILTER (WHERE b<a)
  FROM t1 GROUP BY (a%2) ORDER BY 1,2;
}

execsql_test 1.15 {
  SELECT 
    a/5,
    sum(b) FILTER (WHERE a%5=0),
    sum(b) FILTER (WHERE a%5=1),
    sum(b) FILTER (WHERE a%5=2),
    sum(b) FILTER (WHERE a%5=3),
    sum(b) FILTER (WHERE a%5=4)
  FROM t1 GROUP BY (a/5) ORDER BY 1;
}

finish_test


Added test/filter2.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019 July 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.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#

####################################################
# DO NOT EDIT! THIS FILE IS AUTOMATICALLY GENERATED!
####################################################

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix filter2

ifcapable !windowfunc { finish_test ; return }
do_execsql_test 1.0 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b INTEGER);
  INSERT INTO t1 VALUES
   (1, 7), (2, 3), (3, 5), (4, 30), (5, 26), (6, 23), (7, 27),
   (8, 3), (9, 17), (10, 26), (11, 33), (12, 25), (13, NULL), (14, 47),
   (15, 36), (16, 13), (17, 45), (18, 31), (19, 11), (20, 36), (21, 37),
   (22, 21), (23, 22), (24, 14), (25, 16), (26, 3), (27, 7), (28, 29),
   (29, 50), (30, 38), (31, 3), (32, 36), (33, 12), (34, 4), (35, 46),
   (36, 3), (37, 48), (38, 23), (39, NULL), (40, 24), (41, 5), (42, 46),
   (43, 11), (44, NULL), (45, 18), (46, 25), (47, 15), (48, 18), (49, 23);
} {}

do_execsql_test 1.1 {
  SELECT sum(b) FROM t1
} {1041}

do_execsql_test 1.2 {
  SELECT sum(b) FILTER (WHERE a<10) FROM t1
} {141}

do_execsql_test 1.3 {
  SELECT count(DISTINCT b) FROM t1
} {31}

do_execsql_test 1.4 {
  SELECT count(DISTINCT b) FILTER (WHERE a!=19) FROM t1
} {31}

do_execsql_test 1.5 {
  SELECT min(b) FILTER (WHERE a>19),
         min(b) FILTER (WHERE a>0),
         max(a+b) FILTER (WHERE a>19),
         max(b+a) FILTER (WHERE a BETWEEN 10 AND 40)
  FROM t1;
} {3 3 88 85}

do_execsql_test 1.6 {
  SELECT min(b),
         min(b),
         max(a+b),
         max(b+a)
  FROM t1
  GROUP BY (a%10)
  ORDER BY 1, 2, 3, 4;
} {3 3 58 58   3 3 66 66   3 3 71 71   3 3 88 88   4 4 61 61   5 5 54 54
  7 7 85 85   11 11 79 79   16 16 81 81   24 24 68 68}

do_execsql_test 1.7 {
  SELECT min(b) FILTER (WHERE a>19),
         min(b) FILTER (WHERE a>0),
         max(a+b) FILTER (WHERE a>19),
         max(b+a) FILTER (WHERE a BETWEEN 10 AND 40)
  FROM t1
  GROUP BY (a%10)
  ORDER BY 1, 2, 3, 4;
} {3 3 58 58   3 3 71 39   4 4 38 61   7 7 85 85   11 5 54 45   16 16 81 81
  18 3 66 61   21 3 88 68   23 11 79 79   24 24 68 68}

do_execsql_test 1.8 {
  SELECT sum(a+b) FILTER (WHERE a=NULL) FROM t1
} {{}}

do_execsql_test 1.9 {
  SELECT (a%5) FROM t1 GROUP BY (a%5) 
  HAVING sum(b) FILTER (WHERE b<20) > 34
  ORDER BY 1
} {3   4}

do_execsql_test 1.10 {
  SELECT (a%5), sum(b) FILTER (WHERE b<20) AS bbb
  FROM t1
  GROUP BY (a%5) HAVING sum(b) FILTER (WHERE b<20) >34
  ORDER BY 1
} {3 49   4 46}

do_execsql_test 1.11 {
  SELECT (a%5), sum(b) FILTER (WHERE b<20) AS bbb
  FROM t1
  GROUP BY (a%5) HAVING sum(b) FILTER (WHERE b<20) >34
  ORDER BY 2
} {4 46   3 49}

do_execsql_test 1.12 {
  SELECT (a%5), 
    sum(b) FILTER (WHERE b<20) AS bbb,
    count(distinct b) FILTER (WHERE b<20 OR a=13) AS ccc
  FROM t1 GROUP BY (a%5)
  ORDER BY 2
} {2 25 3   0 34 2   1 34 4   4 46 4   3 49 5}

do_execsql_test 1.13 {
  SELECT 
    group_concat(CAST(b AS TEXT), '_') FILTER (WHERE b%2!=0),
    group_concat(CAST(b AS TEXT), '_') FILTER (WHERE b%2!=1),
    count(*) FILTER (WHERE b%2!=0),
    count(*) FILTER (WHERE b%2!=1)
  FROM t1;
} {7_3_5_23_27_3_17_33_25_47_13_45_31_11_37_21_3_7_29_3_3_23_5_11_25_15_23 30_26_26_36_36_22_14_16_50_38_36_12_4_46_48_24_46_18_18 27 19}


do_test 1.14 {
  set myres {}
  foreach r [db eval {SELECT 
    avg(b) FILTER (WHERE b>a),
    avg(b) FILTER (WHERE b<a)
  FROM t1 GROUP BY (a%2) ORDER BY 1,2;}] {
    lappend myres [format %.4f [set r]]
  }
  set res2 {30.8333 13.7273 31.4167 13.0000}
  set i 0
  foreach r [set myres] r2 [set res2] {
    if {[set r]<([set r2]-0.0001) || [set r]>([set r2]+0.0001)} {
      error "list element [set i] does not match: got=[set r] expected=[set r2]"
    }
    incr i
  }
  set {} {}
} {}

do_execsql_test 1.15 {
  SELECT 
    a/5,
    sum(b) FILTER (WHERE a%5=0),
    sum(b) FILTER (WHERE a%5=1),
    sum(b) FILTER (WHERE a%5=2),
    sum(b) FILTER (WHERE a%5=3),
    sum(b) FILTER (WHERE a%5=4)
  FROM t1 GROUP BY (a/5) ORDER BY 1;
} {0 {} 7 3 5 30   1 26 23 27 3 17   2 26 33 25 {} 47   3 36 13 45 31 11
  4 36 37 21 22 14   5 16 3 7 29 50   6 38 3 36 12 4   7 46 3 48 23 {}
  8 24 5 46 11 {}   9 18 25 15 18 23}

finish_test

Added test/filterfault.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2018 May 8
#
# 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 filterfault

ifcapable !windowfunc {
  finish_test
  return
}

do_execsql_test 1.0 {
  CREATE TABLE t1(a, b, c, d);
  INSERT INTO t1 VALUES(1, 2, 3, 4);
  INSERT INTO t1 VALUES(5, 6, 7, 8);
  INSERT INTO t1 VALUES(9, 10, 11, 12);
}
faultsim_save_and_close

do_faultsim_test 1 -faults oom-t* -prep {
  faultsim_restore_and_reopen
} -body {
  execsql {
    SELECT sum(a) FILTER (WHERE b<5),
           count() FILTER (WHERE d!=c) 
      FROM t1 GROUP BY c ORDER BY 1;
  }
} -test {
  faultsim_test_result {0 {{} 1 {} 1 1 1}}
}


finish_test

Changes to test/fkey1.test.

218
219
220
221
222
223
224

















































225
226
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


} {1 {foreign key mismatch - "c1" referencing "p1"}}

do_execsql_test 6.2 {
  CREATE UNIQUE INDEX p1x2 ON p1(x);
  INSERT INTO c1 VALUES(1);
} {}

# 2021-07-03 https://sqlite.org/forum/forumpost/a6b0c05277
# 2021-07-07 https://sqlite.org/forum/forumpost/79c9e4797d
# Failure to allocate enough registers in the VDBE for a
# PRAGMA foreign_key_check when the foreign key has more
# columns than the table.
#
reset_db
do_execsql_test 7.1 {
  PRAGMA foreign_keys=OFF;
  CREATE TABLE t1(a,b,c,FOREIGN KEY(a,a,a,a,a,a,a,a,a,a,a,a,a,a) REFERENCES t0);
  INSERT INTO t1 VALUES(1,2,3);
  PRAGMA foreign_key_check;
} {t1 1 t0 0}
do_execsql_test 7.2 {
  DROP TABLE t1;
  CREATE TABLE t1(a,b,c AS(1),d, FOREIGN KEY(c,d,b,a,b,d,b,c) REFERENCES t0);
  PRAGMA foreign_key_check;
} {}

# 2021-12-31 forum https://sqlite.org/forum/forumpost/24bd1fef7e9323ef
# Memory leak caused by sqlite3NestedParse() running on a corrupt system
# table.  Discovered by Jingzhou Fu.
#
reset_db
do_execsql_test 8.1 {
  PRAGMA writable_schema=ON;
  PRAGMA foreign_keys = ON;
  CREATE TABLE sqlite_stat1 (tbl INTEGER PRIMARY KEY DESC, idx UNIQUE DEFAULT NULL) WITHOUT ROWID;
  PRAGMA writable_schema=OFF;
  CREATE TABLE sqlsim4(stat PRIMARY KEY);;
  CREATE TABLE t1(sqlsim7 REFERENCES sqlite_stat1 ON DELETE CASCADE);
  DROP table "sqlsim4";
} {}
# 2022-01-01 dbsqlfuzz 1c57440219f6f0aedf5e8f72a8ddd75f15aea381
# Follow-up case to the above.  Assertion is not true if the schema
# is corrupt.
reset_db
database_may_be_corrupt
do_execsql_test 8.2 {
  CREATE TABLE t1(a REFERENCES sqlite_stat1 ON DELETE CASCADE);
  CREATE TABLE t2(a TEXT PRIMARY KEY);
  PRAGMA writable_schema=ON;
  CREATE TABLE sqlite_stat1(tbl INTEGER PRIMARY KEY DESC, idx UNIQUE DEFAULT NULL) WITHOUT ROWID;
  UPDATE sqlite_schema SET name='sqlite_autoindex_sqlite_stat1_1' WHERE name='sqlite_autoindex_sqlite_stat1_2';
  PRAGMA writable_schema=RESET;
} {}
do_catchsql_test 8.3 {
  REINDEX;
} {1 {database disk image is malformed}}

finish_test

Changes to test/fkey2.test.

413
414
415
416
417
418
419
420

421
422
423
424
425
426
427

428
429
430
431
432
433
434
413
414
415
416
417
418
419

420
421
422
423
424
425
426

427
428
429
430
431
432
433
434







-
+






-
+







    INSERT INTO ab VALUES(1, 'b');
    INSERT INTO cd VALUES(1, 'd');
    INSERT INTO ef VALUES(1, 'e');
  }
} {}
do_test fkey2-3.1.3 {
  catchsql { UPDATE ab SET a = 5 }
} {1 {CHECK constraint failed: ef}}
} {1 {CHECK constraint failed: e!=5}}
do_test fkey2-3.1.4 {
  execsql { SELECT * FROM ab }
} {1 b}
do_test fkey2-3.1.4 {
  execsql BEGIN;
  catchsql { UPDATE ab SET a = 5 }
} {1 {CHECK constraint failed: ef}}
} {1 {CHECK constraint failed: e!=5}}
do_test fkey2-3.1.5 {
  execsql COMMIT;
  execsql { SELECT * FROM ab; SELECT * FROM cd; SELECT * FROM ef }
} {1 b 1 d 1 e}

do_test fkey2-3.2.1 {
  execsql BEGIN;
951
952
953
954
955
956
957

958
959
960
961
962
963
964
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965







+







drop_all_tables
ifcapable altertable {
  do_test fkey2-14.1.1 {
    # Adding a column with a REFERENCES clause is not supported.
    execsql { 
      CREATE TABLE t1(a PRIMARY KEY);
      CREATE TABLE t2(a, b);
      INSERT INTO t2 VALUES(1,2);
    }
    catchsql { ALTER TABLE t2 ADD COLUMN c REFERENCES t1 }
  } {0 {}}
  do_test fkey2-14.1.2 {
    catchsql { ALTER TABLE t2 ADD COLUMN d DEFAULT NULL REFERENCES t1 }
  } {0 {}}
  do_test fkey2-14.1.3 {
983
984
985
986
987
988
989
990

991
992
993
994
995
996
997
998
999
1000

1001
1002
1003
1004
1005
1006
1007
984
985
986
987
988
989
990

991
992
993
994
995
996
997
998
999
1000

1001
1002
1003
1004
1005
1006
1007
1008







-
+









-
+







  # Test the sqlite_rename_parent() function directly.
  #
  proc test_rename_parent {zCreate zOld zNew} {
    db eval {SELECT sqlite_rename_table(
        'main', 'table', 't1', $zCreate, $zOld, $zNew, 0
    )}
  }
  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1
  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db
  do_test fkey2-14.2.1.1 {
    test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3
  } {{CREATE TABLE t1(a REFERENCES "t3")}}
  do_test fkey2-14.2.1.2 {
    test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t4 t3
  } {{CREATE TABLE t1(a REFERENCES t2)}}
  do_test fkey2-14.2.1.3 {
    test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3
  } {{CREATE TABLE t1(a REFERENCES "t3")}}
  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0
  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db
  
  # Test ALTER TABLE RENAME TABLE a bit.
  #
  do_test fkey2-14.2.2.1 {
    drop_all_tables
    execsql {
      CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1);
1042
1043
1044
1045
1046
1047
1048

1049
1050
1051
1052
1053
1054
1055
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057







+







  #
  drop_all_tables
  do_test fkey2-14.1tmp.1 {
    # Adding a column with a REFERENCES clause is not supported.
    execsql { 
      CREATE TEMP TABLE t1(a PRIMARY KEY);
      CREATE TEMP TABLE t2(a, b);
      INSERT INTO temp.t2 VALUES(1,2);
    }
    catchsql { ALTER TABLE t2 ADD COLUMN c REFERENCES t1 }
  } {0 {}}
  do_test fkey2-14.1tmp.2 {
    catchsql { ALTER TABLE t2 ADD COLUMN d DEFAULT NULL REFERENCES t1 }
  } {0 {}}
  do_test fkey2-14.1tmp.3 {
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
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







-
+









-
+







      PRAGMA foreign_keys = off;
      ALTER TABLE t2 ADD COLUMN h DEFAULT 'text' REFERENCES t1;
      PRAGMA foreign_keys = on;
      SELECT sql FROM temp.sqlite_master WHERE name='t2';
    }
  } {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}}

  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1
  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db
  do_test fkey2-14.2tmp.1.1 {
    test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3
  } {{CREATE TABLE t1(a REFERENCES "t3")}}
  do_test fkey2-14.2tmp.1.2 {
    test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t4 t3
  } {{CREATE TABLE t1(a REFERENCES t2)}}
  do_test fkey2-14.2tmp.1.3 {
    test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3
  } {{CREATE TABLE t1(a REFERENCES "t3")}}
  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0
  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db
  
  # Test ALTER TABLE RENAME TABLE a bit.
  #
  do_test fkey2-14.2tmp.2.1 {
    drop_all_tables
    execsql {
      CREATE TEMP TABLE t1(a PRIMARY KEY, b REFERENCES t1);
1126
1127
1128
1129
1130
1131
1132

1133
1134
1135
1136
1137
1138
1139
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142







+







  drop_all_tables
  do_test fkey2-14.1aux.1 {
    # Adding a column with a REFERENCES clause is not supported.
    execsql { 
      ATTACH ':memory:' AS aux;
      CREATE TABLE aux.t1(a PRIMARY KEY);
      CREATE TABLE aux.t2(a, b);
      INSERT INTO aux.t2(a,b) VALUES(1,2);
    }
    catchsql { ALTER TABLE t2 ADD COLUMN c REFERENCES t1 }
  } {0 {}}
  do_test fkey2-14.1aux.2 {
    catchsql { ALTER TABLE t2 ADD COLUMN d DEFAULT NULL REFERENCES t1 }
  } {0 {}}
  do_test fkey2-14.1aux.3 {
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
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







-
+









-
+







      PRAGMA foreign_keys = off;
      ALTER TABLE t2 ADD COLUMN h DEFAULT 'text' REFERENCES t1;
      PRAGMA foreign_keys = on;
      SELECT sql FROM aux.sqlite_master WHERE name='t2';
    }
  } {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}}

  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1
  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db
  do_test fkey2-14.2aux.1.1 {
    test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3
  } {{CREATE TABLE t1(a REFERENCES "t3")}}
  do_test fkey2-14.2aux.1.2 {
    test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t4 t3
  } {{CREATE TABLE t1(a REFERENCES t2)}}
  do_test fkey2-14.2aux.1.3 {
    test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3
  } {{CREATE TABLE t1(a REFERENCES "t3")}}
  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0
  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db
  
  # Test ALTER TABLE RENAME TABLE a bit.
  #
  do_test fkey2-14.2aux.2.1 {
    drop_all_tables
    execsql {
      CREATE TABLE aux.t1(a PRIMARY KEY, b REFERENCES t1);

Changes to test/fkey5.test.

11
12
13
14
15
16
17
18

19
20
21


22
23
24
25
26
27
28
11
12
13
14
15
16
17

18
19


20
21
22
23
24
25
26
27
28







-
+

-
-
+
+







# This file implements regression tests for SQLite library.
#
# This file tests the PRAGMA foreign_key_check command.
#
# EVIDENCE-OF: R-15402-03103 PRAGMA schema.foreign_key_check; PRAGMA
# schema.foreign_key_check(table-name);
#
# EVIDENCE-OF: R-23918-17301 The foreign_key_check pragma checks the
# EVIDENCE-OF: R-41653-15278 The foreign_key_check pragma checks the
# database, or the table called "table-name", for foreign key
# constraints that are violated and returns one row of output for each
# violation.
# constraints that are violated. The foreign_key_check pragma returns
# one row output for each foreign key violation.

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix fkey5

ifcapable {!foreignkey} {
  finish_test
425
426
427
428
429
430
431
432



























































433
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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

do_execsql_test 11.0 {
  CREATE TABLE tt(y);
  CREATE TABLE c11(x REFERENCES tt(y));
}
do_catchsql_test 11.1 {
  PRAGMA foreign_key_check;
} {1 {foreign key mismatch - "c11" referencing "tt"}}

# 2020-07-03 Bug in foreign_key_check discovered while working on the
# forum reports that pragma_foreign_key_check does not accept an argument:
# If two separate schemas seem to reference one another, that causes
# problems for foreign_key_check.
#
reset_db
do_execsql_test 12.0 {
  ATTACH ':memory:' as aux;
  CREATE TABLE aux.t1(a INTEGER PRIMARY KEY, b TEXT REFERENCES t2);
  CREATE TABLE main.t2(x TEXT PRIMARY KEY, y INT);
  INSERT INTO main.t2 VALUES('abc',11),('def',22),('xyz',99);
  INSERT INTO aux.t1 VALUES(5,'abc'),(7,'xyz'),(9,'oops');
  PRAGMA foreign_key_check=t1;
} {t1 5 t2 0 t1 7 t2 0 t1 9 t2 0}
do_execsql_test 12.1 {
  CREATE TABLE aux.t2(x TEXT PRIMARY KEY, y INT);
  INSERT INTO aux.t2 VALUES('abc',11),('def',22),('xyz',99);
  PRAGMA foreign_key_check=t1;
} {t1 9 t2 0}

# 2020-07-03: the pragma_foreign_key_check virtual table should
# accept arguments for the table name and/or schema name.
#
ifcapable vtab {
  do_execsql_test 13.0 {
    SELECT *, 'x' FROM pragma_foreign_key_check('t1');
  } {t1 9 t2 0 x}
  do_catchsql_test 13.1 {
    SELECT *, 'x' FROM pragma_foreign_key_check('t1','main');
  } {1 {no such table: main.t1}}
  do_execsql_test 13.2 {
    SELECT *, 'x' FROM pragma_foreign_key_check('t1','aux');
  } {t1 9 t2 0 x}
}

ifcapable vtab {
  reset_db
    do_execsql_test 13.10 {
      PRAGMA foreign_keys=OFF;
      CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT REFERENCES t2);
      CREATE TABLE t2(x TEXT PRIMARY KEY, y INT);
      CREATE TABLE t3(w TEXT, z INT REFERENCES t1);
      INSERT INTO t2 VALUES('abc',11),('def',22),('xyz',99);
      INSERT INTO t1 VALUES(5,'abc'),(7,'xyz'),(9,'oops');
      INSERT INTO t3 VALUES(11,7),(22,19);
    } {}
  do_execsql_test 13.11 {
    SELECT x.*, '|'
      FROM sqlite_schema, pragma_foreign_key_check(name) AS x
      WHERE type='table'
      ORDER BY x."table";
  } {t1 9 t2 0 | t3 2 t1 0 |}
  do_execsql_test 13.12 {
    SELECT *, '|'
      FROM pragma_foreign_key_check AS x
      ORDER BY x."table";
  } {t1 9 t2 0 | t3 2 t1 0 |}
}

finish_test

Changes to test/fkey7.test.

78
79
80
81
82
83
84




































85
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

    INSERT INTO c4 VALUES(1), (2), (3);

    ANALYZE;
    INSERT INTO p4(id) VALUES(4);
  }
}


do_execsql_test 4.0 {
  PRAGMA foreign_keys = true;
  CREATE TABLE parent(
    p PRIMARY KEY
  );
  CREATE TABLE child(
    c UNIQUE REFERENCES parent(p)
  );
}

do_catchsql_test 4.1 {
  INSERT OR FAIL INTO child VALUES(123), (123);
} {1 {FOREIGN KEY constraint failed}}

do_execsql_test 4.2 {
  SELECT * FROM child;
} {}

do_execsql_test 4.3 {
  PRAGMA foreign_key_check;
} {}

do_catchsql_test 4.4 {
  INSERT INTO parent VALUES(123);
  INSERT OR FAIL INTO child VALUES(123), (123);
} {1 {UNIQUE constraint failed: child.c}}

do_execsql_test 4.5 {
  SELECT * FROM child;
} {123}

do_execsql_test 4.6 {
  PRAGMA foreign_key_check;
} {}

finish_test

Changes to test/fkey8.test.

159
160
161
162
163
164
165






















































































166
167
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


    INSERT OR REPLACE INTO p3 VALUES(2, 'three');
  END;
}

do_catchsql_test 2.3.1 {
  DELETE FROM p3 WHERE a=1
} {1 {FOREIGN KEY constraint failed}}


do_execsql_test 3.0 {
  PRAGMA foreign_keys=ON;
  CREATE TABLE t2(
    a PRIMARY KEY, b, c, d, e,
      FOREIGN KEY(b, c) REFERENCES t2(d, e)
  ) WITHOUT ROWID;
  CREATE UNIQUE INDEX idx ON t2(d, e);

  INSERT INTO t2 VALUES(1, 'one', 'one', 'one', 'one'); -- row is parent of self
  INSERT INTO t2 VALUES(2, 'one', 'one', 'one', NULL);  -- parent is row 1
}

do_catchsql_test 3.1 {
  DELETE FROM t2 WHERE a=1;
} {1 {FOREIGN KEY constraint failed}}

do_execsql_test 4.0 {
  CREATE TABLE t1 (
      c1 PRIMARY KEY,
      c2 NUMERIC,
      FOREIGN KEY(c1) REFERENCES t1(c2)
      ) WITHOUT ROWID ;
  CREATE INDEX t1c1 ON t1(c1);
  CREATE UNIQUE INDEX t1c1unique ON t1(c2);
}
do_catchsql_test 4.1 {
  INSERT OR REPLACE INTO t1 VALUES(10000, 20000);
} {1 {FOREIGN KEY constraint failed}}
do_execsql_test 4.2 {
  INSERT OR REPLACE INTO t1 VALUES(20000, 20000);
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 5.0 {
  PRAGMA foreign_keys = true;
  CREATE TABLE parent(
    p TEXT PRIMARY KEY
  );
  CREATE TABLE child(
    c INTEGER UNIQUE, 
    FOREIGN KEY(c) REFERENCES parent(p) DEFERRABLE INITIALLY DEFERRED
  );
  BEGIN;
    INSERT INTO child VALUES(123);
    INSERT INTO parent VALUES('123');
  COMMIT;
}
do_execsql_test 5.1 {
  PRAGMA integrity_check;
} {ok}

do_execsql_test 5.2 {
  INSERT INTO parent VALUES(1200);
  BEGIN;
    INSERT INTO child VALUES(456);
    UPDATE parent SET p = '456' WHERE p=1200;
  COMMIT;
}
do_execsql_test 5.3 {
  PRAGMA integrity_check;
} {ok}

#-------------------------------------------------------------------------
reset_db
forcedelete test.db2
do_execsql_test 6.1 {
  PRAGMA foreign_keys = on;
  CREATE TABLE c1(b);
  INSERT INTO c1 VALUES(123);
}

do_execsql_test 6.2 {
  ATTACH 'test.db2' AS aux;
  CREATE TABLE aux.p1(a INTEGER PRIMARY KEY);
  CREATE TABLE aux.c1(b REFERENCES p1(a) ON DELETE RESTRICT);

  INSERT INTO aux.p1 VALUES(123);
}

do_execsql_test 6.3 {
  DELETE FROM aux.p1 WHERE a=123;
}


finish_test

Changes to test/fordelete.test.

44
45
46
47
48
49
50
51

52
53
54
55
56
57
58
44
45
46
47
48
49
50

51
52
53
54
55
56
57
58







-
+







    if {$R(opcode)=="OpenWrite"} {
      set root $R(p2)
      set csr $R(p1)
      if {[info exists T($root)]} { set M($csr) $T($root) }

      set obj $T($root)
      set O($obj) ""
      if {"0x$R(p5)" & 0x08} { 
      if {$R(p5) & 0x08} { 
        set O($obj) *
      } else {
        set O($obj) ""
      }
    }
  }

Changes to test/format4.test.

13
14
15
16
17
18
19
20


21
22
23
24
25
26
27
13
14
15
16
17
18
19

20
21
22
23
24
25
26
27
28







-
+
+







# This file implements tests to verify that the new serial_type
# values of 8 (integer 0) and 9 (integer 1) work correctly.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

db eval {PRAGMA legacy_file_format=OFF}
#db eval {PRAGMA legacy_file_format=OFF}
sqlite3_db_config db LEGACY_FILE_FORMAT 0

# The size of the database depends on whether or not autovacuum
# is enabled.
#
ifcapable autovacuum {
  if {[db one {PRAGMA auto_vacuum}]} {
    set small 3072

Changes to test/fts3_common.tcl.

39
40
41
42
43
44
45




46
47
48
49
50
51
52
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56







+
+
+
+







#     Todo.
#
#   fts3_doclist TBL TERM WHERE
#     Todo.
#
#
#

ifcapable fts3 {
  sqlite3_fts3_may_be_corrupt 0 
}

#-------------------------------------------------------------------------
# USAGE: fts3_build_db_1 SWITCHES N
#
# Build a sample FTS table in the database opened by database connection 
# [db]. The name of the new table is "t1".
#

Changes to test/fts3aa.test.

246
247
248
249
250
251
252











253
254
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265







+
+
+
+
+
+
+
+
+
+
+


do_execsql_test 9.1 {
  CREATE VIRTUAL TABLE t9 USING fts4(a, "", '---');
}
do_execsql_test 9.2 {
  CREATE VIRTUAL TABLE t10 USING fts3(<, b, c);
}

do_execsql_test 10.0 {
  CREATE VIRTUAL TABLE z1 USING fts3;
  INSERT INTO z1 VALUES('one two three'),('four one five'),('six two five');
  CREATE TRIGGER z1r1 AFTER DELETE ON z1_content BEGIN
    DELETE FROM z1;
  END;
}
do_catchsql_test 10.1 {
  DELETE FROM z1;
} {1 {SQL logic error}}

expand_all_sql db
finish_test

Changes to test/fts3aj.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
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








-
-

















-
+




-
-
-
+
+
+







# 2007 February 6
#
# The author disclaims copyright to this source code.
#
#*************************************************************************
# This file implements regression tests for SQLite library.  This
# tests creating fts3 tables in an attached database.
#
# $Id: fts3aj.test,v 1.1 2007/08/20 17:38:42 shess Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# If SQLITE_ENABLE_FTS3 is defined, omit this file.
ifcapable !fts3 {
  finish_test
  return
}

# Clean up anything left over from a previous pass.
forcedelete test2.db
forcedelete test2.db-journal
sqlite3 db2 test2.db

db eval {
  CREATE VIRTUAL TABLE t3 USING fts3(content);
  INSERT INTO t3 (rowid, content) VALUES(1, "hello world");
  INSERT INTO t3 (rowid, content) VALUES(1, 'hello world');
}

db2 eval {
  CREATE VIRTUAL TABLE t1 USING fts3(content);
  INSERT INTO t1 (rowid, content) VALUES(1, "hello world");
  INSERT INTO t1 (rowid, content) VALUES(2, "hello there");
  INSERT INTO t1 (rowid, content) VALUES(3, "cruel world");
  INSERT INTO t1 (rowid, content) VALUES(1, 'hello world');
  INSERT INTO t1 (rowid, content) VALUES(2, 'hello there');
  INSERT INTO t1 (rowid, content) VALUES(3, 'cruel world');
}

# This has always worked because the t1_* tables used by fts3 will be
# the defaults.
do_test fts3aj-1.1 {
  execsql {
    ATTACH DATABASE 'test2.db' AS two;
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
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







-
-
-
+
+
+















-
-
+
+











# 'two'.  It appears to work fine because the tables end up being the
# defaults, but obviously is badly broken if you hope to use things
# other than in the exact same ATTACH setup.
do_test fts3aj-1.2 {
  execsql {
    ATTACH DATABASE 'test2.db' AS two;
    CREATE VIRTUAL TABLE two.t2 USING fts3(content);
    INSERT INTO t2 (rowid, content) VALUES(1, "hello world");
    INSERT INTO t2 (rowid, content) VALUES(2, "hello there");
    INSERT INTO t2 (rowid, content) VALUES(3, "cruel world");
    INSERT INTO t2 (rowid, content) VALUES(1, 'hello world');
    INSERT INTO t2 (rowid, content) VALUES(2, 'hello there');
    INSERT INTO t2 (rowid, content) VALUES(3, 'cruel world');
    SELECT rowid FROM t2 WHERE t2 MATCH 'hello';
    DETACH DATABASE two;
  }
} {1 2}
catch {db eval {DETACH DATABASE two}}

# In older code, this broke because the fts3 code attempted to create
# t3_* tables in database 'main', but they already existed.  Normally
# this wouldn't happen without t3 itself existing, in which case the
# fts3 code would never be called in the first place.
do_test fts3aj-1.3 {
  execsql {
    ATTACH DATABASE 'test2.db' AS two;

    CREATE VIRTUAL TABLE two.t3 USING fts3(content);
    INSERT INTO two.t3 (rowid, content) VALUES(2, "hello there");
    INSERT INTO two.t3 (rowid, content) VALUES(3, "cruel world");
    INSERT INTO two.t3 (rowid, content) VALUES(2, 'hello there');
    INSERT INTO two.t3 (rowid, content) VALUES(3, 'cruel world');
    SELECT rowid FROM two.t3 WHERE t3 MATCH 'hello';

    DETACH DATABASE two;
  } db2
} {2}
catch {db eval {DETACH DATABASE two}}

catch {db2 close}
forcedelete test2.db

finish_test

Changes to test/fts3ak.test.

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
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







-
-
-
+
+
+






-
-
+
+










-
-
+
+










-
-
+
+

















-
-
+
+









-
+










-
+







ifcapable !fts3 {
  finish_test
  return
}

db eval {
  CREATE VIRTUAL TABLE t1 USING fts3(content);
  INSERT INTO t1 (rowid, content) VALUES(1, "hello world");
  INSERT INTO t1 (rowid, content) VALUES(2, "hello there");
  INSERT INTO t1 (rowid, content) VALUES(3, "cruel world");
  INSERT INTO t1 (rowid, content) VALUES(1, 'hello world');
  INSERT INTO t1 (rowid, content) VALUES(2, 'hello there');
  INSERT INTO t1 (rowid, content) VALUES(3, 'cruel world');
}

# Test that possibly-buffered inserts went through after commit.
do_test fts3ak-1.1 {
  execsql {
    BEGIN TRANSACTION;
    INSERT INTO t1 (rowid, content) VALUES(4, "false world");
    INSERT INTO t1 (rowid, content) VALUES(5, "false door");
    INSERT INTO t1 (rowid, content) VALUES(4, 'false world');
    INSERT INTO t1 (rowid, content) VALUES(5, 'false door');
    COMMIT TRANSACTION;
    SELECT rowid FROM t1 WHERE t1 MATCH 'world';
  }
} {1 3 4}

# Test that buffered inserts are seen by selects in the same
# transaction.
do_test fts3ak-1.2 {
  execsql {
    BEGIN TRANSACTION;
    INSERT INTO t1 (rowid, content) VALUES(6, "another world");
    INSERT INTO t1 (rowid, content) VALUES(7, "another test");
    INSERT INTO t1 (rowid, content) VALUES(6, 'another world');
    INSERT INTO t1 (rowid, content) VALUES(7, 'another test');
    SELECT rowid FROM t1 WHERE t1 MATCH 'world';
    COMMIT TRANSACTION;
  }
} {1 3 4 6}

# Test that buffered inserts are seen within a transaction.  This is
# really the same test as 1.2.
do_test fts3ak-1.3 {
  execsql {
    BEGIN TRANSACTION;
    INSERT INTO t1 (rowid, content) VALUES(8, "second world");
    INSERT INTO t1 (rowid, content) VALUES(9, "second sight");
    INSERT INTO t1 (rowid, content) VALUES(8, 'second world');
    INSERT INTO t1 (rowid, content) VALUES(9, 'second sight');
    SELECT rowid FROM t1 WHERE t1 MATCH 'world';
    ROLLBACK TRANSACTION;
  }
} {1 3 4 6 8}

# Double-check that the previous result doesn't persist past the
# rollback!
do_test fts3ak-1.4 {
  execsql {
    SELECT rowid FROM t1 WHERE t1 MATCH 'world';
  }
} {1 3 4 6}

# Test it all together.
do_test fts3ak-1.5 {
  execsql {
    BEGIN TRANSACTION;
    INSERT INTO t1 (rowid, content) VALUES(10, "second world");
    INSERT INTO t1 (rowid, content) VALUES(11, "second sight");
    INSERT INTO t1 (rowid, content) VALUES(10, 'second world');
    INSERT INTO t1 (rowid, content) VALUES(11, 'second sight');
    ROLLBACK TRANSACTION;
    SELECT rowid FROM t1 WHERE t1 MATCH 'world';
  }
} {1 3 4 6}

# Test that the obvious case works.
do_test fts3ak-1.6 {
  execsql {
    BEGIN;
    INSERT INTO t1 (rowid, content) VALUES(12, "third world");
    INSERT INTO t1 (rowid, content) VALUES(12, 'third world');
    COMMIT;
    SELECT rowid FROM t1 WHERE t1 MATCH 'third';
  }
} {12}

# This is exactly the same as the previous test, except that older
# code loses the INSERT due to an SQLITE_SCHEMA error.
do_test fts3ak-1.7 {
  execsql {
    BEGIN;
    INSERT INTO t1 (rowid, content) VALUES(13, "third dimension");
    INSERT INTO t1 (rowid, content) VALUES(13, 'third dimension');
    CREATE TABLE x (c);
    COMMIT;
    SELECT rowid FROM t1 WHERE t1 MATCH 'dimension';
  }
} {13}

finish_test

Changes to test/fts3atoken.test.

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
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







+
+
+
+




+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
















+







    INSERT INTO t1(content) VALUES('There was movement at the station');
    INSERT INTO t1(content) VALUES('For the word has passed around');
    INSERT INTO t1(content) VALUES('That the colt from ol regret had got');
    SELECT content FROM t1 WHERE content MATCH 'movement'
  }
} {{There was movement at the station}}

unset -nocomplain simple blah2name simplename
set simplename "simple"
set blah2name "blah2"
set simple [db one {SELECT fts3_tokenizer('simple')}]
sqlite3_db_config db SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 0
do_catchsql_test 1.6 {
  SELECT fts3_tokenizer('blah', fts3_tokenizer('simple')) IS NULL;
} {1 {fts3tokenize disabled}}
do_test fts3atoken-1.7 {
  execsql {
    SELECT fts3_tokenizer('blah2', $simple) IS NULL;

  }
} {1}

# With ENABLE_FTS3_TOKENIZER off, the fts3_tokenzer(1) function
# returns NULL unless the first parameter is a bound parameter.
# If the first parameter is a bound parameter, then fts3_tokenizer(1)
# returns the actual pointer value as a BLOB.
#
do_test fts3atoken-1.8 {
  execsql {
    SELECT fts3_tokenizer($blah2name) == fts3_tokenizer($simplename),
           typeof(fts3_tokenizer($blah2name)),
           typeof(fts3_tokenizer('blah2')),
           typeof(fts3_tokenizer($simplename)),
           typeof(fts3_tokenizer('simple'));
  }
} {1 blob null blob null}

# With ENABLE_FTS3_TOKENIZER on, fts3_tokenizer() always returns
# the BLOB pointer, regardless the parameter
#
sqlite3_db_config db SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1
do_test fts3atoken-1.9 {
  execsql {
    SELECT fts3_tokenizer('blah2') == fts3_tokenizer('simple'),
           typeof(fts3_tokenizer($blah2name)),
           typeof(fts3_tokenizer('blah2')),
           typeof(fts3_tokenizer($simplename)),
           typeof(fts3_tokenizer('simple'));
  }
} {1 blob blob blob blob}

# 2019-12-31:  The fts3_tokenizer() function can never be invoked from
# within a trigger or view.
#
do_catchsql_test fts3atoken-1.10 {
  CREATE VIEW v110(x) AS
      SELECT fts3_tokenizer('tok110', fts3_tokenizer('simple')) IS NULL;
} {0 {}}
do_catchsql_test fts3atoken-1.11 {
  SELECT * FROM v110;
} {1 {unsafe use of fts3_tokenizer()}}
do_catchsql_test fts3atoken-1.12 {
  CREATE TABLE t110(a,b);
  CREATE TRIGGER r110 AFTER INSERT ON t110 BEGIN
      SELECT fts3_tokenizer('tok110', fts3_tokenizer('simple')) IS NULL;
  END;
} {0 {}}
do_catchsql_test fts3atoken-1.13 {
  INSERT INTO t110(a,b) VALUES(1,2);
} {1 {unsafe use of fts3_tokenizer()}}
do_catchsql_test fts3atoken-1.14 {
  SELECT * FROM t110;
} {0 {}}

#--------------------------------------------------------------------------
# Test cases fts3atoken-2.* test error cases in the scalar function based
# API for getting and setting tokenizers.
#
do_test fts3atoken-2.1 {
  catchsql {
    SELECT fts3_tokenizer('nosuchtokenizer');
  }
} {1 {unknown tokenizer: nosuchtokenizer}}

#--------------------------------------------------------------------------
# Test cases fts3atoken-3.* test the three built-in tokenizers with a
# simple input string via the built-in test function. This is as much
# to test the test function as the tokenizer implementations.
#
sqlite3_db_config db SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1
do_test fts3atoken-3.1 {
  execsql {
    SELECT fts3_tokenizer_test('simple', 'I don''t see how');
  }
} {{0 i I 1 don don 2 t t 3 see see 4 how how}}
do_test fts3atoken-3.2 {
  execsql {

Changes to test/fts3auto.test.

566
567
568
569
570
571
572







573
574
575
576
577
578
579
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586







+
+
+
+
+
+
+







  do_fts3query_test 4.$tn.3.5 -deferred five t1 {one NEAR/3 five}

  do_fts3query_test 4.$tn.4.1 -deferred fi* t1 {on* AND fi*}
  do_fts3query_test 4.$tn.4.2 -deferred fi* t1 {on* NEAR fi*}
  do_fts3query_test 4.$tn.4.3 -deferred fi* t1 {on* NEAR/1 fi*}
  do_fts3query_test 4.$tn.4.4 -deferred fi* t1 {on* NEAR/2 fi*}
  do_fts3query_test 4.$tn.4.5 -deferred fi* t1 {on* NEAR/3 fi*}

  ifcapable fts4_deferred {
    db eval {UPDATE t1_stat SET value=x'' WHERE id=0}
    do_catchsql_test 4.$tn.4.6 {
      SELECT docid FROM t1 WHERE t1 MATCH 'on* NEAR/3 fi*'
    } {1 {database disk image is malformed}}
  }
}

#--------------------------------------------------------------------------
# The following test cases - fts3auto-5.* - focus on using prefix indexes.
#
set chunkconfig [fts3_configure_incr_load 1 1]
foreach {tn create pending} {

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/fts3aux2.test.

136
137
138
139
140
141
142
























143
144
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


do_execsql_test 1.4.6 {
  SELECT term, col, documents, occurrences, languageid 
  FROM terms WHERE term>='e' AND term<'seven' AND languageid=2
} {
  eight * 1 1 2    eight 1 1 1 2 
  five * 1 1 2     five 0 1 1 2 
}

#-------------------------------------------------------------------------
do_execsql_test 2.0 {
  CREATE VIRTUAL TABLE ft USING fts3();
  INSERT INTO ft VALUES('a_234567890123456789');
  INSERT INTO ft VALUES('b_234567890123456789');
  INSERT INTO ft VALUES('c_234567890123456789');
  CREATE VIRTUAL TABLE t2 USING fts4aux(ft);
}

do_execsql_test 2.1 {
  SELECT term FROM t2 WHERE term=X'625f323334353637383930313233343536373839';
}

do_execsql_test 2.2 {
  SELECT term FROM t2 WHERE term<X'625f003334353637383930313233343536373839';
} {
  234567890123456789 234567890123456789 a a b b
}

do_execsql_test 2.3 {
  SELECT term FROM t2 WHERE term=X'625f003334353637383930313233343536373839';
}


finish_test

Changes to test/fts3corrupt.test.

161
162
163
164
165
166
167

































































168
169
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


do_test 5.2.1 { sqlite3_extended_errcode db } SQLITE_CORRUPT_VTAB
do_catchsql_test 5.3 {
  UPDATE t1_stat SET value = NULL;
  SELECT matchinfo(t1, 'nxa') FROM t1 WHERE t1 MATCH 't*';
} {1 {database disk image is malformed}}
do_test 5.3.1 { sqlite3_extended_errcode db } SQLITE_CORRUPT_VTAB

# 2019-11-18 https://bugs.chromium.org/p/chromium/issues/detail?id=1025467
# bug1
db close
sqlite3 db :memory:
do_catchsql_test 6.10 {
  CREATE VIRTUAL TABLE f using fts3(a,b);
  CREATE TABLE f_stat(id INTEGER PRIMARY KEY, value BLOB);
  INSERT INTO f_segdir VALUES (2000, 0,0,0, '16', '');
  INSERT INTO f_segdir VALUES (1999, 0,0,0, '0 18',
                               x'000131030102000103323334050101010200');
  INSERT INTO f_segments (blockid) values (16);
  INSERT INTO f_segments values (0, x'');
  INSERT INTO f_stat VALUES (1,x'cf0f01');
  INSERT INTO f(f) VALUES ('merge=1');
} {1 {database disk image is malformed}}

# 2020-03-02 https://bugs.chromium.org/p/chromium/issues/detail?id=1057441
# The ticket complains of use of an uninitialized value. That part is harmless.
# The only reason to fix this is the failure to detect a subtly corrupt
# inverted index.
#
reset_db
do_catchsql_test 7.10 {
  CREATE VIRTUAL TABLE f USING fts3(a,b);
  INSERT INTO f_segdir VALUES (0,0,1,0,'0 0',x'01010101020101');
  SELECT  matchinfo( f , 'pcx')  FROM f WHERE b MATCH x'c533';
} {1 {database disk image is malformed}}

reset_db
sqlite3_fts3_may_be_corrupt 1
do_execsql_test 8.1 {
  CREATE VIRTUAL TABLE f USING fts3(a);
  INSERT INTO f(f) VALUES('nodesize=24');
  BEGIN;
    INSERT INTO f VALUES('abcdefghijklmnopqrstuvwxyz0123456789');
    INSERT INTO f VALUES('abcdefghijklmnopqrstuvwxyz0123456789');
    INSERT INTO f VALUES('abcdefghijklmnopqrstuvwxyz0123456789');

    INSERT INTO f VALUES('abcdefghijklmnopqrstuvwxyz012345678X');
    INSERT INTO f VALUES('abcdefghijklmnopqrstuvwxyz012345678X');
    INSERT INTO f VALUES('abcdefghijklmnopqrstuvwxyz012345678X');
  COMMIT;
  BEGIN;
    INSERT INTO f VALUES('abcdefghijklmnopqrstuvwxyz0123456789');
    INSERT INTO f VALUES('abcdefghijklmnopqrstuvwxyz0123456789');
    INSERT INTO f VALUES('abcdefghijklmnopqrstuvwxyz0123456789');

    INSERT INTO f VALUES('abcdefghijklmnopqrstuvwxyz012345678X');
    INSERT INTO f VALUES('abcdefghijklmnopqrstuvwxyz012345678X');
    INSERT INTO f VALUES('abcdefghijklmnopqrstuvwxyz012345678X');
  COMMIT;

  SELECT count(*) FROM f_segments;
} {4}

do_execsql_test 8.2 {
  UPDATE f_segments SET block = (
    SELECT block FROM f_segments WHERE blockid=1
  ) WHERE blockid=2
}

do_catchsql_test 8.3 {
  INSERT INTO f(f) VALUES('merge=2,2');
} {1 {database disk image is malformed}}
sqlite3_fts3_may_be_corrupt 0

finish_test

Changes to test/fts3corrupt2.test.

12
13
14
15
16
17
18

19
20
21
22
23
24
25
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26







+







set testdir [file dirname $argv0]
source $testdir/tester.tcl

# If SQLITE_ENABLE_FTS3 is not defined, omit this file.
ifcapable !fts3 { finish_test ; return }

set ::testprefix fts3corrupt2
sqlite3_fts3_may_be_corrupt 1

set data [list]
lappend data {*}{
   "amxtvoo adqwroyhz auq aithtir avniqnuynvf axp ahibayfynig agbicpm"
   "ajdtebs anteaxr aieynenwmd awpl alo akxcrwow aoxftge aoqvgul"
   "amcfvdr auz apu aebelm ahuxyz aqc asyafdb agulvhvqu"
   "apepwfyz azkhdvkw aenyelxzbk aslnitbyet aycdsdcpgr aqzzdbc agfi axnypydou"
98
99
100
101
102
103
104
105
106
107
108
109
110
111
99
100
101
102
103
104
105

106
107
108
109
110
111







-






        catchsql { SELECT * FROM t2 WHERE t2 MATCH 'a*' }
        set {} {}
      } {}
    }
    execsql { UPDATE t2_segdir SET root = $blob WHERE rowid = $rowid }
  }
}






finish_test

Changes to test/fts3corrupt4.test.

12
13
14
15
16
17
18

19
20
21
22
23
24
25




26
27
28
29
30
31
32
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







+







+
+
+
+







# focus of this script is testing the FTS3 module.
#
# $Id: fts3aa.test,v 1.1 2007/08/20 17:38:42 shess Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/fts3_common.tcl
set testprefix fts3corrupt4

# If SQLITE_ENABLE_FTS3 is defined, omit this file.
ifcapable !fts3 {
  finish_test
  return
}

sqlite3_fts3_may_be_corrupt 1
database_may_be_corrupt
extra_schema_checks 0

do_execsql_test 1.0 {
  BEGIN;
    CREATE VIRTUAL TABLE ft USING fts3;
    INSERT INTO ft VALUES('aback');
    INSERT INTO ft VALUES('abaft');
    INSERT INTO ft VALUES('abandon');
140
141
142
143
144
145
146


























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































147
148
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
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
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
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
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
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
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
1984
1985
1986
1987
1988
1989
1990
1991
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
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
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
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
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
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
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
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
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
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
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
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
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
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
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
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
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
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
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
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
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
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
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
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
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
4360
4361
4362
4363
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
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
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
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
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
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
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
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
6457
6458
6459
6460
6461
6462
6463
6464
6465
6466
6467
6468
6469
6470
6471
6472
6473
6474
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485
6486
6487
6488
6489
6490
6491
6492
6493
6494
6495
6496
6497
6498
6499
6500
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516
6517
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561
6562
6563
6564
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583
6584
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621
6622
6623
6624
6625
6626
6627
6628
6629
6630
6631
6632
6633
6634
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
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
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
6735
6736
6737
6738
6739
6740
6741
6742
6743
6744
6745
6746
6747
6748
6749
6750
6751
6752
6753
6754
6755
6756
6757
6758
6759
6760
6761
6762
6763
6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774
6775
6776
6777
6778
6779
6780
6781
6782
6783
6784
6785
6786
6787
6788
6789
6790
6791
6792
6793
6794
6795
6796
6797
6798
6799
6800
6801
6802
6803
6804
6805
6806
6807
6808
6809
6810
6811
6812
6813
6814
6815
6816
6817
6818
6819
6820
6821
6822
6823
6824
6825
6826
6827
6828
6829
6830
6831
6832
6833
6834
6835
6836
6837
6838
6839
6840
6841
6842
6843
6844
6845
6846
6847
6848
6849
6850
6851
6852
6853
6854
6855
6856
6857
6858
6859
6860
6861
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
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
6903
6904
6905
6906
6907
6908
6909
6910
6911
6912
6913
6914
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
6943
6944
6945
6946
6947
6948
6949
6950
6951
6952
6953
6954
6955
6956
6957
6958
6959
6960
6961
6962
6963
6964
6965
6966
6967
6968
6969
6970
6971
6972
6973
6974
6975
6976
6977
6978
6979
6980
6981
6982
6983
6984
6985
6986
6987
6988
6989
6990
6991
6992
6993
6994
6995
6996
6997
6998
6999
7000
7001
7002
7003
7004
7005
7006
7007
7008
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
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
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
7097
7098
7099
7100
7101
7102
7103
7104
7105
7106
7107
7108
7109
7110
7111
7112
7113
7114
7115
7116
7117
7118
7119
7120
7121
7122
7123
7124
7125
7126
7127
7128
7129
7130
7131
7132
7133
7134
7135
7136
7137
7138
7139
7140
7141
7142
7143
7144
7145
7146
7147
7148
7149
7150
7151
7152
7153
7154
7155
7156
7157
7158
7159
7160
7161
7162
7163
7164
7165
7166
7167
7168
7169
7170
7171
7172
7173
7174
7175
7176
7177
7178
7179
7180
7181
7182
7183
7184
7185
7186
7187
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
7236
7237
7238
7239
7240
7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261
7262
7263
7264
7265
7266
7267
7268
7269
7270
7271
7272
7273
7274
7275
7276
7277
7278
7279
7280
7281
7282
7283
7284
7285
7286
7287
7288
7289
7290
7291
7292
7293
7294
7295
7296
7297
7298
7299
7300
7301
7302
7303
7304
7305
7306
7307
7308
7309
7310
7311
7312
7313
7314
7315
7316
7317
7318
7319
7320
7321
7322
7323
7324
7325
7326
7327
7328
7329
7330
7331
7332
7333
7334
7335
7336
7337
7338
7339
7340
7341
7342
7343
7344
7345
7346
7347
7348
7349
7350
7351
7352
7353
7354
7355
7356
7357
7358
7359
7360
7361
7362
7363
7364
7365
7366
7367
7368
7369
7370
7371
7372
7373
7374
7375
7376
7377
7378
7379
7380
7381
7382
7383
7384
7385
7386
7387
7388
7389
7390
7391
7392
7393
7394
7395
7396
7397
7398
7399
7400
7401
7402
7403
7404
7405
7406
7407
7408
7409
7410
7411
7412
7413
7414
7415
7416
7417
7418
7419
7420
7421
7422
7423
7424
7425
7426
7427
7428
7429
7430
7431
7432
7433
7434
7435
7436
7437
7438
7439
7440
7441
7442
7443
7444
7445
7446
7447
7448
7449
7450
7451
7452
7453
7454
7455
7456
7457
7458
7459
7460
7461
7462
7463
7464
7465
7466
7467
7468
7469
7470
7471
7472
7473
7474
7475
7476
7477
7478
7479
7480
7481
7482
7483
7484
7485
7486
7487
7488
7489
7490
7491
7492
7493
7494
7495
7496
7497
7498
7499
7500
7501
7502
7503
7504
7505
7506
7507
7508
7509
7510
7511
7512
7513
7514
7515
7516
7517
7518
7519
7520
7521
7522
7523
7524
7525
7526
7527
7528
7529
7530
7531
7532
7533
7534
7535
7536
7537
7538
7539
7540
7541
7542
7543
7544
7545
7546
7547
7548
7549
7550
7551
7552
7553
7554
7555
7556
7557
7558
7559
7560
7561
7562
7563
7564
7565
7566
7567
7568
7569
7570
7571
7572
7573
7574
7575
7576
7577
7578
7579
7580
7581
7582
7583
7584
7585
7586
7587
7588
7589
7590
7591
7592
7593
7594
7595
7596
7597
7598
7599
7600
7601
7602
7603
7604
7605
7606
7607
7608
7609
7610
7611
7612
7613
7614
7615
7616
7617
7618
7619
7620
7621
7622
7623
7624
7625
7626
7627
7628
7629
7630
7631
7632
7633
7634
7635
7636
7637
7638
7639
7640
7641
7642
7643
7644
7645
7646
7647
7648
7649
7650
7651
7652
7653
7654
7655
7656
7657
7658
7659
7660
7661
7662
7663
7664
7665
7666
7667







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


  UPDATE ft_segdir 
  SET root = blob('0101056162633132FFFFFFFF070236030132030136');
}

do_catchsql_test 3.1 {
  SELECT * FROM ft WHERE ft MATCH 'abc20'
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 4.0 {
  CREATE VIRTUAL TABLE t1 USING fts3();
  INSERT INTO t1 VALUES('one two three');
  UPDATE t1_segdir SET start_block = 1;
}

do_catchsql_test 4.1 { 
  SELECT * FROM t1 WHERE t1 MATCH 'one'; 
} {1 {database disk image is malformed}}
do_catchsql_test 4.2 { 
  SELECT * FROM t1 WHERE t1 MATCH 'two'; 
} {1 {database disk image is malformed}}
do_catchsql_test 4.3 { 
  SELECT * FROM t1 WHERE t1 MATCH 'three'; 
} {1 {database disk image is malformed}}
do_execsql_test 4.4 {
  INSERT INTO t1(t1) VALUES('optimize');
}

#-------------------------------------------------------------------------
reset_db
do_test 5.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 24576 pagesize 4096 filename c15.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 04 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 0e f9 00 06 0d ec 00 0f cd 0f 69   ...............i
|    112: 0f 01 0e 10 0e c6 0d ec 00 00 00 00 00 00 00 00   ................
|   3552: 00 00 00 00 00 00 00 00 00 00 00 00 22 06 06 17   ................
|   3568: 11 11 01 31 74 61 62 6c 65 74 32 74 32 06 43 52   ...1tablet2t2.CR
|   3584: 45 41 54 45 20 54 41 42 4c 45 20 74 32 28 78 29   EATE TABLE t2(x)
|   3600: 81 33 04 07 17 1f 1f 01 82 35 74 61 62 6c 65 74   .3.......5tablet
|   3616: 31 5f 73 65 67 64 69 72 74 31 5f 73 65 67 64 69   1_segdirt1_segdi
|   3632: 72 04 43 52 45 41 54 45 20 54 41 42 4c 45 20 27   r.CREATE TABLE '
|   3648: 74 31 5f 73 65 67 64 69 72 27 28 6c 65 76 65 6c   t1_segdir'(level
|   3664: 20 49 4e 54 45 47 45 52 2c 69 64 78 20 49 4e 54    INTEGER,idx INT
|   3680: 45 47 45 52 2c 73 74 61 72 74 5f 62 6c 6f 63 6b   EGER,start_block
|   3696: 20 49 4e 54 45 47 45 52 2c 6c 65 61 76 65 73 5f    INTEGER,leaves_
|   3712: 65 6e 64 5f 62 6c 6f 63 6b 20 49 4e 54 45 47 45   end_block INTEGE
|   3728: 52 2c 65 6e 64 5f 62 6c 6f 63 6b 20 49 4e 54 45   R,end_block INTE
|   3744: 47 45 52 2c 72 6f 6f 74 20 42 4c 4f 42 2c 50 52   GER,root BLOB,PR
|   3760: 49 4d 41 52 59 20 4b 45 59 28 6c 65 76 65 6c 2c   IMARY KEY(level,
|   3776: 20 69 64 78 29 29 31 05 06 17 45 1f 01 00 69 6e    idx))1...E...in
|   3792: 64 65 78 73 71 6c 69 74 65 5f 61 75 74 6f 69 6e   dexsqlite_autoin
|   3808: 64 65 79 5f 74 31 5f 73 65 67 64 69 72 5f 31 74   dey_t1_segdir_1t
|   3824: 31 5f 73 65 67 64 69 72 05 00 00 00 08 00 00 00   1_segdir........
|   3840: 00 66 03 07 17 23 23 01 81 13 74 61 62 6c 65 74   .f...##...tablet
|   3856: 31 5f 73 65 67 6d 65 6e 74 73 74 31 5f 73 65 67   1_segmentst1_seg
|   3872: 6d 65 6e 74 73 03 43 52 45 41 54 45 20 54 41 42   ments.CREATE TAB
|   3888: 4c 45 20 27 74 31 5f 73 65 67 6d 65 6e 74 73 27   LE 't1_segments'
|   3904: 28 62 6c 6f 63 6b 69 64 20 49 4e 54 45 47 45 52   (blockid INTEGER
|   3920: 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 62 6c    PRIMARY KEY, bl
|   3936: 6f 63 6b 20 42 4c 4f 42 29 62 02 07 17 21 21 01   ock BLOB)b...!!.
|   3952: 81 0f 74 61 62 6c 65 74 31 5f 63 6f 6e 74 65 6e   ..tablet1_conten
|   3968: 74 74 31 5f 63 6f 6e 74 65 6e 74 02 43 52 45 41   tt1_content.CREA
|   3984: 54 45 20 54 41 42 4c 45 20 27 74 31 5f 63 6f 6e   TE TABLE 't1_con
|   4000: 74 65 6e 74 27 28 64 6f 63 69 64 20 49 4e 54 45   tent'(docid INTE
|   4016: 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c   GER PRIMARY KEY,
|   4032: 20 27 63 30 63 6f 6e 74 65 6e 74 27 29 31 01 06    'c0content')1..
|   4048: 17 11 11 08 51 74 61 62 6c 65 74 31 74 31 43 52   ....Qtablet1t1CR
|   4064: 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 42   EATE VIRTUAL TAB
|   4080: 4c 45 20 74 31 20 55 53 49 4e 47 20 66 74 73 33   LE t1 USING fts3
| page 2 offset 4096
|      0: 0d 00 00 00 03 0f e0 00 0f f6 0f ec 0f e0 00 00   ................
|   4064: 0a 03 03 00 1b 61 62 61 6e 64 6f 6e 08 02 03 00   .....abandon....
|   4080: 17 61 62 61 66 74 08 01 03 00 17 61 62 61 63 6b   .abaft.....aback
| page 3 offset 8192
|      0: 0d 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00   ................
| page 4 offset 12288
|      0: 0d 00 00 00 01 0f d6 00 0f d6 00 00 00 00 00 00   ................
|   4048: 00 00 00 00 00 00 28 01 07 08 08 08 08 15 46 30   ......(.......F0
|   4064: 20 32 39 00 05 61 62 61 63 6b 03 01 02 00 03 02    29..aback......
|   4080: 66 74 03 02 02 00 03 04 6e 64 6f 60 30 30 20 00   ft......ndo`00 .
| page 5 offset 16384
|      0: a0 00 00 00 10 ff b0 00 ff fb 00 00 00 00 00 00   ................
|   4080: 00 00 00 00 00 00 00 00 00 00 00 04 04 08 08 09   ................
| page 6 offset 20480
|      0: 0d 00 00 00 05 0f b8 00 0f f4 0f e9 0f d6 0f c7   ................
|     16: 0f b8 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28 64   ..'t1_content'(d
|     32: 6f 63 69 64 20 49 4e 54 45 47 45 52 20 50 52 49   ocid INTEGER PRI
|     48: 4d 41 52 59 20 4b 45 59 2c 20 27 63 30 63 6f 6e   MARY KEY, 'c0con
|     64: 74 65 6e 74 27 29 31 01 06 17 11 11 08 51 74 61   tent')1......Qta
|     80: 62 6c 65 74 31 74 31 43 52 45 41 54 45 20 56 49   blet1t1CREATE VI
|     96: 52 54 55 41 4c 20 54 41 42 4c 45 20 74 31 20 55   RTUAL TABLE t1 U
|    112: 53 49 4e 47 20 66 74 73 33 0d 00 00 00 03 0f e0   SING fts3.......
|    128: 00 0f f6 0f ec 0f e0 00 00 00 00 00 00 00 00 00   ................
|   4016: 00 00 00 00 00 00 00 00 0d 05 02 23 61 75 74 6f   ...........#auto
|   4032: 6d 65 72 67 65 3d 35 0d 04 02 23 6d 65 72 67 65   merge=5...#merge
|   4048: 3d 31 30 30 2c 38 11 03 02 2b 69 6e 74 65 67 72   =100,8...+integr
|   4064: 69 74 79 2d 63 68 65 63 6b 09 02 02 1b 72 65 62   ity-check....reb
|   4080: 75 69 6c 64 0a 01 02 1d 6f 70 74 69 6d 69 7a 65   uild....optimize
| end c15.db
}]} {}

do_catchsql_test 5.1 {
  SELECT * FROM t1 WHERE t1 MATCH 'abandon';
} {1 {malformed database schema (sqlite_autoindey_t1_segdir_1) - orphan index}}


#-------------------------------------------------------------------------
reset_db
database_may_be_corrupt
do_execsql_test 6.0 {
  CREATE VIRTUAL TABLE Table0 USING fts3();
  INSERT INTO Table0_segdir VALUES(1,NULL,1,NULL,NULL,NULL);
}

do_catchsql_test 6.1 {
  SELECT * FROM Table0 WHERE Table0 MATCH 'a';
} {0 {}}

do_catchsql_test 6.2 {
  INSERT INTO Table0(Table0) VALUES('optimize');
} {0 {}}

#-------------------------------------------------------------------------
reset_db
do_test 7.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 32768 pagesize 4096 filename crash-04bb6e7c811ce9.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   ................
|     48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00   ................
|     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 50 52 49 4d 41 52 59 20 4b   NTEGER PRIMARY 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 31 2c 32 27 29   (a,prefix='1,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 63 0e 1f 00 00 00 00 00 00 00 00   .....c..........
|   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 67 42 06   r sint occaecgB.
|   3712: 37 57 06 96 46 17 46 17 42 06 e6 f6 e2 07 07 26   7W..F.F.B......&
|   3728: f6 96 46 56 e7 42 c2 a0 60 30 05 b6 36 96 c6 c7   ..FV.B..`0..6...
|   3744: 56 d2 06 46 f6 c6 f7 26 52 06 57 52 06 67 56 7c   V..F...&R.WR.gV|
|   3760: 65 3f 04 20 6e 75 6c 6c 61 20 70 61 72 69 61 74   e?. 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 72 12 29   psum dolor sir.)
|   4064: 0d 65 74 2c 20 63 6f 6e 73 65 63 74 65 74 75 72   .et, consectetur
|   4080: 20 61 64 69 70 69 73 63 69 6e 67 20 65 6c 69 74    adipiscing elit
| page 3 offset 8192
|      0: 0d 00 00 00 00 10 30 00 10 17 50 30 80 20 00 00   ......0...P0. ..
|     16: 27 46 50 30 20 50 00 00 27 56 c0 30 30 a0 00 10   'FP0 P..'V.00...
|     32: 17 40 90 20 70 00 10 20 00 10 30 00 00 27 66 50   .@. p.. ..0..'fP
|     48: 60 30 60 00 20 a0 00 10 16 f0 30 50 90 08 20 a0   `0`. .....0P.. .
|     64: 20 80 20 80 80 81 78 40 20 40 03 02 03 23 53 10    . ...x@ @...#S.
|     80: 00 16 11 30 10 60 40 00 10 c0 00 10 40 00 00 00   ...0.`@.....@...
|     96: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 78 24   ..............x$
|    112: 41 71 83 37 10 27 97 60 10 40 00 00 16 41 10 10   Aq.7.'.`.@...A..
|    128: 40 00 10 30 90 00 30 20 50 00 10 30 00 20 70 00   @..0..0 P..0. p.
|    144: 00 16 51 b0 10 90 00 10 40 70 00 10 30 80 00 10   ..Q.....@p..0...
|    160: 50 30 00 10 b0 00 10 40 00 10 20 00 10 b0 00 00   P0.....@.. .....
|    176: 16 60 30 60 50 00 00 16 90 f0 10 30 00 10 60 00   .`0`P......0..`.
|    192: 30 40 40 40 00 30 30 90 00 00 16 c0 c0 10 20 00   0@@@.00....... .
|    208: 10 80 00 10 b0 00 50 c0 00 00 16 d0 90 20 b0 00   ......P...... ..
|    224: 10 50 00 50 80 00 00 16 e0 c0 30 80 00 10 20 00   .P.P......0... .
|    240: 20 60 00 10 60 00 00 16 f0 60 70 40 00 10 60 00    `..`....`p@..`.
|    256: 00 17 00 60 60 70 00 10 70 00 00 17 10 60 30 70   ...``p..p....`0p
|    272: 00 50 50 00 00 17 20 30 50 70 00 00 17 30 c0 10   .PP... 0Pp...0..
|    288: 50 00 10 20 00 50 30 00 10 20 00 00 17 40 30 20   P.. .P0.. ...@0 
|    304: 50 00 00 17 50 a0 20 70 00 10 20 a0 00 10 30 00   P...P. p.. ...0.
|    320: 00 17 60 70 30 60 00 20 90 30 08 52 60 10 80 80   ..`p0`. .0.R`...
|    336: 80 80 81 78 a3 e3 02 03 63 63 50 00 26 16 40 30   ...x....ccP.&.@0
|    352: 30 40 00 20 86 97 06 97 36 36 96 e6 70 30 10 80   0@. ....66..p0..
|    368: 00 10 56 c6 97 17 56 10 30 20 c0 00 50 26 97 00   ..V...V.0 ..P&..
|    384: 30 40 40 00 10 36 d6 57 40 30 10 60 00 10 36 e6   0@@..6.W@0.`..6.
|    400: 96 d0 30 80 90 00 10 37 57 46 50 30 50 30 00 00   ..0....7WFP0P0..
|    416: 66 36 96 c6 c7 56 d0 30 60 20 00 10 66 f6 d6 d6   f6...V.0` ..f...
|    432: f6 46 f0 30 40 70 00 20 96 e7 36 56 37 46 57 47   .F.0@p. ..6V7FWG
|    448: 57 20 30 10 70 00 50 47 17 56 17 40 30 40 80 00   W 0.p.PG.V.@0@..
|    464: 10 47 56 c7 06 10 30 80 40 00 20 77 06 96 46 17   .GV...0.@. w..F.
|    480: 46 17 40 30 70 50 00 00 86 46 57 36 57 27 56 e7   F.@0pP...FW6W'V.
|    496: 40 30 80 70 00 10 16 f0 30 20 30 00 20 36 c6 f7   @0.p....0 0. 6..
|    512: 20 60 10 40 00 40 50 00 50 16 50 60 20 a0 00 40    `.@.@P.P.P` ..@
|    528: 30 00 10 37 56 97 30 30 50 20 00 00 26 56 10 30   0..7V.00P ..&V.0
|    544: 40 60 00 10 66 97 57 36 d6 f6 40 30 20 40 00 10   @`..f.W6..@0 @..
|    560: 36 c6 97 40 30 10 90 00 15 35 14 c6 97 46 52 06   6..@0....5...FR.
|    576: 66 f7 26 d6 17 42 03 30 01 00 00 10 10 04 02 02   f.&..B.0........
|    592: 00 00 00 00 00 00 00 00 70 00 00 00 00 00 00 00   ........p.......
|    608: 00 00 00 00 60 00 00 00 40 00 00 00 00 00 00 00   ....`...@.......
| 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 00 00 91 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 30 03 03 00 01 01 73 06   l......n0.....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 01 70 00 03 01 80 00 05 03 00 01   ......p.........
|   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 64 03 03 04 00 02   .>0 665..ad.....
|   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 75 72 03 01   .....nsectetur..
|   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 00 00   ................
|   4080: 00 00 00 00 00 00 00 07 00 03 00 14 08 45 b5 03   .............E..
| page 8 offset 28672
|      0: 6f ee cd e1 f1 ee 1a ca be ed ee ec de ac f1 cb   o...............
|     16: f1 ee 1a ce de ee f1 ee 0a cc de ed ae 90 87 88   ................
|     32: ec 5e dc ec fc 11 72 32 75 0a da be ec ed eb de   .^....r2u.......
|     48: ce c1 aa e0 ae ec 1f c1 ee 99 c2 aa e0 a9 ad 15   ................
|     64: 0e ec ab ef 1e e0 48 ad 15 04 24 80 00 00 00 00   ......H...$.....
|     80: 00 00 00 00 e0 00 00 00 04 2c 80 00 10 42 4e c1   .........,...BN.
|     96: 20 4b 45 59 2c 6e 6f 64 65 6e 6f 2c 61 30 29 46    KEY,nodeno,a0)F
|    112: 02 06 17 11 11 08 7b 74 61 62 6c 65 74 31 74 31   .......tablet1t1
|    128: 43 52 45 41 54 e1 ec eb ea eb eb ac ee ce be de   CREAT...........
|    144: ee f1 ee 1a ca ba de 47 80 30 00 14 90 47 70 30   .......G.0...Gp0
|    160: 00 11 60 47 60 30 00 15 f0 47 50 30 00 10 f0 47   ..`G`0...GP0...G
|    176: 40 30 00 11 f0 47 45 20 30 00 11 d0 45 10 30 00   @0...GE 0...E.0.
|    192: 12 10 45 00 30 00 14 e0 44 f0 30 00 11 e0 44 e0   ..E.0...D.0...D.
|    208: 30 00 12 a0 44 d0 30 00 15 e0 44 c0 30 00 10 40   0...D.0...D.0..@
|    224: 44 b0 30 00 15 10 44 a0 30 00 14 c0 44 90 30 00   D.0...D.0...D.0.
|    240: 16 20 44 80 30 00 52 45 41 54 45 20 54 41 42 4c   . D.0.REATE TABL
|    256: 45 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28 69   E 't1_content'(i
|    272: 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52   d INTEGER PRIMAR
|    288: 59 20 4b 45 59 2c 20 63 30 29 69 03 07 17 19 19   Y KEY, c0)i.....
|    304: 01 81 2d 74 61 62 6c 65 74 31 5f 69 64 78 74 31   ..-tablet1_idxt1
|    320: 5f 69 64 78 03 43 52 45 41 54 45 20 54 41 42 4c   _idx.CREATE TABL
|    336: 45 20 27 70 31 5f 69 64 78 03 6e 69 6d 03 03 03   E 'p1_idx.nim...
|    352: 00 01 03 73 73 65 03 05 0b 00 02 01 74 03 08 0b   ...sse......t...
|    368: 00 01 01 74 03 02 09 00 01 01 75 03 06 04 00 01   ...t......u.....
|    384: 01 78 03 04 05 00 02 07 63 65 70 74 65 75 72 03   .x......cepteur.
|    400: 07 02 00 02 0a 65 72 63 69 74 61 74 69 6f 6e 03   .....ercitation.
|    416: 03 09 00 00 06 66 75 67 69 61 74 03 06 05 00 00   .....fugiat.....
|    432: 02 69 64 03 08 0a 00 01 01 6e 07 05 06 04 00 03   .id......n......
|    448: 03 00 02 08 63 69 64 69 64 75 6e 74 03 02 06 00   ....cididunt....
|    464: 01 04 70 73 75 6d 03 01 03 00 01 04 72 75 72 65   ..psum......rure
|    480: 03 05 04 00 00 06 6c 61 62 6f 72 65 03 02 08 00   ......labore....
|    496: 05 02 69 73 03 03 0b 00 05 02 75 6d 03 08 0c 00   ..is......um....
|    512: 01 04 6f 72 65 6d 03 01 02 00 00 05 6d 61 67 6e   ..orem......magn
|    528: 61 03 02 0b 00 01 04 69 6e 69 6d 03 03 05 00 01   a......inim.....
|    544: 05 6f 6c 6c 69 74 03 08 08 00 00 04 6e 69 73 69   .ollit......nisi
|    560: 03 04 02 00 01 02 6f 6e 03 07 06 00 02 05 73 74   ......on......st
|    576: 72 75 64 03 03 08 00 01 04 75 6c 6c 61 03 06 06   rud......ulla...
|    592: 00 00 08 6f 63 63 61 65 63 61 74 03 07 04 00 01   ...occaecat.....
|    608: 06 66 66 69 63 69 61 03 08 06 00 00 08 70 61 72   .fficia......par
|    624: 69 61 74 75 72 03 06 07 00 01 07 72 6f ed ce de   iatur......ro...
|    640: 69 64 65 6e 74 03 07 07 00 00 03 71 75 69 03 08   ident......qui..
|    656: 05 00 03 01 73 03 03 07 00 00 0d 72 65 70 72 65   ....s......repre
|    672: 68 65 6e 64 65 72 69 74 03 05 07 00 00 03 73 65   henderit......se
|    688: 64 03 02 02 00 01 03 69 6e 74 03 07 03 00 02 01   d......int......
|    704: 74 03 01 05 00 01 03 75 6e 74 03 08 02 00 00 06   t......unt......
|    720: 74 65 6d 70 6f 72 03 02 05 00 00 07 75 6c 6c 61   tempor......ulla
|    736: 6d 63 6f 03 03 0a 00 01 01 74 09 02 07 00 01 02   mco......t......
|    752: 00 01 03 00 00 05 76 65 6c 69 74 03 05 0a 00 02   ......velit.....
|    768: 04 6e 69 61 6d 03 03 06 00 01 08 6f 6c 75 70 74   .niam......olupt
|    784: 61 74 65 03 05 09 00 0a 00 00 00 03 0f eb 00 0f   ate.............
|    800: fb 0f f3 0f eb 00 00 00 00 00 00 00 00 00 00 00   ................
| end crash-04bb6e7c811ce9.db
}]} {}

do_catchsql_test 7.1 {
  SELECT matchinfo(t1,'y') FROM t1 WHERE t1 MATCH 'e*';
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
reset_db
do_test 8.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 28672 pagesize 4096 filename crash-7948058d822acb.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   ................
|     48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00   ................
|     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 50 52 49 4d 41 52 59 20 4b   NTEGER PRIMARY 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 31 2c 32 27 29   (a,prefix='1,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 63 0e 1f 00 00 00 00 00 00 00 00   .....c..........
|   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 67 42 06   r sint occaecgB.
|   3712: 37 57 06 96 46 17 46 17 42 06 e6 f6 e2 07 07 26   7W..F.F.B......&
|   3728: f6 96 46 56 e7 42 c2 a0 60 30 05 b6 36 96 c6 c7   ..FV.B..`0..6...
|   3744: 56 d2 06 46 f6 c6 f7 26 52 06 57 52 06 67 56 7c   V..F...&R.WR.gV|
|   3760: 65 3f 04 20 6e 75 6c 6c 61 20 70 61 72 69 61 74   e?. 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 7c 69 71 75 69 70 20 65 78 20 65    ut a|iquip 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 6c 69 74    adipiscing elit
| page 3 offset 8192
|      0: 0d 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00   ................
| 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 00 00 91 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 30 03 03 00 01 01 73 06   l......n0.....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 00 80 00 15 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 64 03 03 04 00 02   .>0 665..ad.....
|   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 75 72 03 01   .....nsectetur..
|   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 40 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 00 00   ................
|   4080: 00 00 00 00 00 00 00 07 00 03 00 14 08 45 b5 03   .............E..
| end crash-7948058d822acb.db
}]} {}

do_catchsql_test 8.1 {
  SELECT matchinfo(t1,'x') FROM t1 WHERE t1 MATCH 'e*';
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
reset_db
do_test 9.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 28672 pagesize 4096 filename crash-e1c6cbfdf643e9.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 02 00 00 00 01 00 00 00 07 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 0e b1 00 06 0d a4 00 0f 8d 0f 21   ...............!
|    112: 0e b9 0d c8 0e 7e 0d a4 0d a4 00 00 00 00 00 00   .....~..........
|   3488: 00 00 00 00 22 07 06 17 11 11 01 31 74 61 62 6c   ...........1tabl
|   3504: 65 74 32 74 32 07 43 52 45 41 54 45 20 54 41 42   et2t2.CREATE TAB
|   3520: 4c 45 20 74 32 28 78 29 81 33 05 07 17 1f 1f 01   LE t2(x).3......
|   3536: 82 35 74 61 62 6c 65 74 31 5f 73 65 67 64 69 72   .5tablet1_segdir
|   3552: 74 31 5f 73 65 67 64 69 72 05 43 52 45 41 54 45   t1_segdir.CREATE
|   3568: 20 54 41 42 4c 45 20 27 74 31 5f 73 65 67 64 69    TABLE 't1_segdi
|   3584: 72 27 28 6c 65 76 65 6c 20 49 4e 54 45 47 45 52   r'(level INTEGER
|   3600: 2c 69 64 78 20 49 4e 54 45 47 45 52 2c 73 74 61   ,idx INTEGER,sta
|   3616: 72 74 5f 62 6c 6f 63 6b 20 49 4e 54 45 47 45 52   rt_block INTEGER
|   3632: 2c 6c 65 61 76 65 73 5f 65 6e 64 5f 62 6c 6f 63   ,leaves_end_bloc
|   3648: 6b 20 49 4e 54 45 47 45 52 2c 65 6e 64 5f 62 6c   k INTEGER,end_bl
|   3664: 6f 63 6b 20 49 4e 54 45 47 45 52 2c 72 6f 6f 74   ock INTEGER,root
|   3680: 20 42 4c 4f 42 2c 50 52 49 4d 41 52 59 20 4b 45    BLOB,PRIMARY KE
|   3696: 59 28 6c 65 76 65 6c 2c 20 69 64 78 29 29 31 06   Y(level, idx))1.
|   3712: 06 17 45 1f 01 00 69 6e 64 65 78 73 71 6c 69 74   ..E...indexsqlit
|   3728: 65 5f 61 75 74 6f 69 6e 64 65 78 5f 74 31 5f 73   e_autoindex_t1_s
|   3744: 65 67 64 69 72 5f 31 74 31 5f 73 65 67 64 69 72   egdir_1t1_segdir
|   3760: 06 0f c7 00 08 00 00 00 00 66 04 07 17 23 23 01   .........f...##.
|   3776: 81 13 74 61 62 6c 65 74 31 5f 73 65 67 6d 65 6e   ..tablet1_segmen
|   3792: 74 73 74 31 5f 73 65 67 6d 65 6e 74 73 04 43 52   tst1_segments.CR
|   3808: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 73   EATE TABLE 't1_s
|   3824: 65 67 6d 65 6e 74 73 27 28 62 6c 6f 63 6b 69 64   egments'(blockid
|   3840: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59    INTEGER PRIMARY
|   3856: 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42    KEY, block BLOB
|   3872: 29 6a 03 07 17 21 21 01 81 1f 74 61 62 6c 65 74   )j...!!...tablet
|   3888: 31 5f 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74   1_contentt1_cont
|   3904: 65 6e 74 03 43 52 45 41 54 45 20 54 41 42 4c 45   ent.CREATE TABLE
|   3920: 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28 64 6f    't1_content'(do
|   3936: 63 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d   cid INTEGER PRIM
|   3952: 41 52 59 20 4b 45 59 2c 20 27 63 30 61 27 2c 20   ARY KEY, 'c0a', 
|   3968: 27 63 31 62 27 2c 20 27 63 32 63 27 29 38 02 06   'c1b', 'c2c')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 33   LE t1 USING fts3
|   4032: 28 61 2c 62 2c 63 29 00 00 00 39 00 00 00 00 00   (a,b,c)...9.....
| page 3 offset 8192
|      0: 0d 00 00 00 25 0b 48 00 0f d8 0f af 0f 86 0f 74   ....%.H........t
|     16: 0f 61 0f 4e 0f 2f 0f 0f 0e ef 0e d7 0e be 0e a5   .a.N./..........
|     32: 0e 8d 0e 74 0e 5b 0e 40 0e 24 0e 08 0d ef 0d d5   ...t.[.@.$......
|     48: 0d bb 0d a0 0d 84 0d 68 0d 4f 0d 35 0d 1b 0c fb   .......h.O.5....
|     64: 0c da 0c b9 0c 99 0c 78 0c 57 0c 3e 0c 24 0c 0a   .......x.W.>.$..
|     80: 0b 48 00 00 00 00 00 00 00 00 00 00 00 00 00 00   .H..............
|   2880: 00 00 00 00 00 00 00 00 81 3f 25 06 00 82 7f 00   .........?%.....
|   2896: 00 43 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e   .COMPILER=gcc-5.
|   2912: 34 2e 30 20 32 30 31 36 30 36 30 39 20 44 45 42   4.0 20160609 DEB
|   2928: 55 47 20 45 4e 41 42 4c 45 20 44 42 53 54 41 54   UG ENABLE DBSTAT
|   2944: 20 56 54 41 42 20 45 4e 41 42 4c 45 20 46 54 53    VTAB ENABLE FTS
|   2960: 34 20 45 4e 41 42 4c 45 20 46 54 53 35 20 45 4e   4 ENABLE FTS5 EN
|   2976: 41 42 4c 45 20 47 45 4f 50 4f 4c 59 20 45 4e 41   ABLE GEOPOLY ENA
|   2992: 42 4c 45 20 4a 53 4f 4e 31 20 45 4e 41 42 4c 45   BLE JSON1 ENABLE
|   3008: 20 4d 45 4d 53 59 53 35 20 45 4e 41 42 4c 45 20    MEMSYS5 ENABLE 
|   3024: 52 54 52 45 45 20 4d 41 58 20 4d 45 4d 4f 52 59   RTREE MAX MEMORY
|   3040: 3d 35 30 30 30 30 30 30 30 20 4f 4d 49 54 20 4c   =50000000 OMIT L
|   3056: 4f 41 44 20 45 58 54 45 4e 53 49 4f 4e 20 54 48   OAD EXTENSION TH
|   3072: 52 45 41 44 53 41 46 45 3d 30 18 24 05 00 25 0f   READSAFE=0.$..%.
|   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 22   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 4f 4d   0XRTRIM.!..3..OM
|   3168: 49 54 20 4c 4f 41 44 20 35 58 54 45 4e 53 49 4f   IT LOAD 5XTENSIO
|   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 53 49   MIT LOAD EXTENSI
|   3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17   ONXNOCASE....3..
|   3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53   OMIT LOAD EXTENS
|   3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19   IONXRTRIM....3..
|   3264: 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30   MAX MEMORY=50000
|   3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f   000XBINARY....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 33   0000XNOCASE....3
|   3328: 0f 17 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30   ..MAX 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 58 4e 4f 43 41 53 45 17   LE RTREEXNOCASE.
|   3408: 19 05 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52   ...%..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 53 35 58 52 54 52 49 4d 18 15 05 00 25   MSYS5XRTRIM....%
|   3520: 0f 19 45 4e 41 42 4c 45 20 4a 53 4f 4e 31 58 42   ..ENABLE 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 31 58 4e 4f 43 41 53 45 17   LE JSON1XNOCASE.
|   3568: 13 05 00 25 1f 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 4e 41 42 4c   NARY....)..ENABL
|   3632: 45 20 47 45 4f 50 4f 4c 59 58 4e 4f 43 41 53 45   E GEOPOLYXNOCASE
|   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 19 45 4e 41 42 4c 45 20 46 54 53 35 58 42 49   ..ENABLE FTS5XBI
|   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 58 4e 4f 43 41 53 45 16 0d 05   E FTS5XNOCASE...
|   3728: 00 23 0f 17 44 4e 41 42 4c 45 20 46 54 53 35 58   .#..DNABLE FTS5X
|   3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42   RTRIM....#..ENAB
|   3760: 4c 45 20 46 54 53 34 58 42 49 4e 41 52 59 17 0b   LE FTS4XBINARY..
|   3776: 05 00 23 0f 19 45 4e 41 42 4c 45 20 46 54 53 34   ..#..ENABLE FTS4
|   3792: 58 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 45 4e   XNOCASE....#..EN
|   3808: 41 42 4c 45 20 46 54 53 34 58 52 54 52 49 4d 1e   ABLE FTS4XRTRIM.
|   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 3d 67   ...C..COMPILER=g
|   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 43   9XNOCASE&...C..C
|   4064: 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e   OMPILER=gcc-5.4.
|   4080: 30 20 32 30 31 36 30 36 30 39 58 52 54 52 49 4d   0 20160609XRTRIM
| 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 02 0b a0 00 0c ad 0b a0 00 00 00 00   ................
|   2976: 82 0a 02 08 08 09 08 08 17 84 06 30 20 32 35 33   ...........0 253
|   2992: 00 01 30 04 25 06 1b 00 00 08 32 30 31 36 30 36   ..0.%.....201606
|   3008: 30 39 03 25 07 00 00 01 34 03 25 05 00 00 01 35   09.%....4.%....5
|   3024: 03 25 04 00 01 07 30 30 30 30 30 30 30 03 25 1a   .%....0000000.%.
|   3040: 00 00 08 63 6f 6d 70 69 6c 65 72 03 25 02 00 00   ...compiler.%...
|   3056: 06 64 62 73 74 61 74 03 25 0a 00 01 04 65 62 75   .dbstat.%....ebu
|   3072: 67 03 25 08 00 00 06 65 6e 61 62 6c 65 09 25 09   g.%....enable.%.
|   3088: 05 04 04 04 04 04 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3104: 6e 03 25 1d 00 00 04 66 74 73 34 03 25 0d 00 03   n.%....fts4.%...
|   3120: 01 35 03 25 0f 00 00 03 67 63 63 03 25 03 00 01   .5.%....gcc.%...
|   3136: 06 65 6f 70 6f 6c 79 03 25 11 00 00 05 6a 73 6f   .eopoly.%....jso
|   3152: 6e 31 03 25 13 00 00 04 6c 6f 61 64 03 25 1c 00   n1.%....load.%..
|   3168: 00 03 6d 61 78 03 25 18 00 01 05 65 6d 6f 72 79   ..max.%....emory
|   3184: 03 25 19 00 03 04 73 79 73 35 03 25 15 00 00 04   .%....sys5.%....
|   3200: 6f 6d 69 74 03 25 1b 00 00 05 72 74 72 65 65 03   omit.%....rtree.
|   3216: 25 17 00 00 0a 74 68 72 65 61 64 73 61 66 65 03   %....threadsafe.
|   3232: 25 1e 00 00 04 76 74 61 62 03 25 0b 00 86 50 01   %....vtab.%...P.
|   3248: 08 08 08 08 08 17 8d 12 30 20 38 33 35 00 01 30   ........0 835..0
|   3264: 12 01 06 00 01 06 00 01 06 00 1f 03 00 01 03 00   ................
|   3280: 01 03 00 00 08 32 30 31 36 30 36 30 39 09 01 07   .....20160609...
|   3296: 00 01 07 00 01 07 00 00 01 34 09 01 05 00 01 05   .........4......
|   3312: 00 01 05 00 00 01 35 09 01 04 00 01 04 00 01 04   ......5.........
|   3328: 00 01 07 30 30 30 30 30 30 30 09 1c 04 00 01 04   ...0000000......
|   3344: 00 01 04 00 00 06 62 69 6e 61 72 79 3c 03 01 02   ......binary<...
|   3360: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3376: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
|   3392: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03   ................
|   3408: 01 02 02 00 03 01 02 02 00 00 08 63 6f 6d 70 69   ...........compi
|   3424: 6c 65 72 09 01 02 00 01 02 00 01 02 00 00 06 64   ler............d
|   3440: 62 73 74 61 74 09 07 03 00 01 03 00 01 03 00 01   bstat...........
|   3456: 04 65 62 75 67 09 04 02 00 01 02 00 01 02 00 00   .ebug...........
|   3472: 06 65 6e 61 62 6c 65 3f 07 02 00 01 02 00 01 02   .enable?........
|   3488: 00 01 02 00 01 02 00 01 02 00 01 02 00 01 02 00   ................
|   3504: 01 02 00 01 02 00 01 02 00 01 02 00 01 01 00 01   ................
|   3520: 02 00 01 02 00 01 02 00 01 02 00 01 02 00 01 02   ................
|   3536: 00 01 02 00 01 02 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3552: 6e 09 1f 04 00 01 04 00 01 04 00 00 04 66 74 73   n............fts
|   3568: 34 09 0a 03 00 01 03 00 01 03 00 03 01 35 09 0d   4............5..
|   3584: 03 00 01 03 00 01 03 00 00 03 67 63 63 09 01 03   ..........gcc...
|   3600: 00 01 03 00 01 03 00 01 06 65 6f 70 6f 6c 79 09   .........eopoly.
|   3616: 10 03 00 01 03 00 01 03 00 00 05 6a 73 6f 6e 31   ...........json1
|   3632: 09 13 03 00 01 03 00 01 03 00 00 04 6c 6f 61 64   ............load
|   3648: 09 1f 03 00 01 03 00 01 03 00 00 03 6d 61 78 09   ............max.
|   3664: 1c 02 00 01 02 00 01 02 00 01 05 65 6d 6f 72 79   ...........emory
|   3680: 09 1c 03 00 01 03 00 01 03 00 03 04 73 79 73 35   ............sys5
|   3696: 09 16 03 00 01 03 00 01 03 00 00 06 6e 6f 63 61   ............noca
|   3712: 73 65 3c 02 01 02 02 00 03 01 02 02 00 03 01 02   se<.............
|   3728: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3744: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
|   3760: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 00   ................
|   3776: 04 6f 6d 69 74 09 1f 02 00 01 02 00 01 02 00 00   .omit...........
|   3792: 05 72 74 72 65 65 09 19 03 00 01 03 00 01 03 00   .rtree..........
|   3808: 03 02 69 6d 3c 01 01 02 02 00 03 01 02 02 00 03   ..im<...........
|   3824: 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01   ................
|   3840: 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02   ................
|   3856: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3872: 00 00 0a 74 68 72 65 61 64 73 61 66 65 09 22 02   ...threadsafe...
|   3888: 00 01 02 00 0a 12 00 00 04 76 74 61 62 09 07 04   .........vtab...
|   3904: 00 01 04 00 01 04 00 00 01 78 b4 01 01 01 01 02   .........x......
|   3920: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   3936: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   3952: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   3968: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   3984: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4000: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   4016: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   4032: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   4048: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   4064: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4080: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
| page 6 offset 20480
|      0: 0a 00 00 00 02 0f f5 00 0f fb 0f f5 00 00 00 00   ................
|   4080: 00 00 00 00 00 05 04 08 09 01 02 04 04 08 08 09   ................
| page 7 offset 24576
|      0: 0d 00 00 00 05 0f b8 00 0f f4 0f e9 0f d6 0f c7   ................
|     16: 0f b8 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   4016: 00 00 00 00 00 00 00 00 0d 05 02 23 61 75 74 6f   ...........#auto
|   4032: 6d 65 72 67 65 3d 35 0d 04 02 23 6d 65 72 67 65   merge=5...#merge
|   4048: 3d 31 30 30 2c 38 11 03 02 2b 69 6e 74 65 67 72   =100,8...+integr
|   4064: 69 74 79 2d 63 68 65 63 6b 09 02 02 1b 72 65 62   ity-check....reb
|   4080: 75 69 6c 64 0a 01 02 1d 6f 70 74 69 6d 69 7a 65   uild....optimize
| end crash-e1c6cbfdf643e9.db
}]} {}

do_execsql_test 9.1 {
  SELECT count(*) FROM t1 WHERE t1 MATCH '"json1 enable"';
} {1}

#-------------------------------------------------------------------------
reset_db
do_test 10.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 28672 pagesize 4096 filename crash-c3a971f0061039.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 02 00 00 00 01 00 00 00 07 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 0e b1 00 06 0d a4 00 0f 8d 0f 21   ...............!
|    112: 0e b9 0d c8 0e 7e 0d a4 0d a4 00 00 00 00 00 00   .....~..........
|   3488: 00 00 00 00 22 07 06 17 11 11 01 31 74 61 62 6c   ...........1tabl
|   3504: 65 74 32 74 32 07 43 52 45 41 54 45 20 54 41 42   et2t2.CREATE TAB
|   3520: 4c 45 20 74 32 28 78 29 81 33 05 07 17 1f 1f 01   LE t2(x).3......
|   3536: 82 35 74 61 62 6c 65 74 31 5f 73 65 67 64 69 72   .5tablet1_segdir
|   3552: 74 31 5f 73 65 67 64 69 72 05 43 52 45 41 54 45   t1_segdir.CREATE
|   3568: 20 54 41 42 4c 45 20 27 74 31 5f 73 65 67 64 69    TABLE 't1_segdi
|   3584: 72 27 28 6c 65 76 65 6c 20 49 4e 54 45 47 45 52   r'(level INTEGER
|   3600: 2c 69 64 78 20 49 4e 54 45 47 45 52 2c 73 74 61   ,idx INTEGER,sta
|   3616: 72 74 5f 62 6c 6f 63 6b 20 49 4e 54 45 47 45 52   rt_block INTEGER
|   3632: 2c 6c 65 61 76 65 73 5f 65 6e 64 5f 62 6c 6f 63   ,leaves_end_bloc
|   3648: 6b 20 49 4e 54 45 47 45 52 2c 65 6e 64 5f 62 6c   k INTEGER,end_bl
|   3664: 6f 63 6b 20 49 4e 54 45 47 45 52 2c 72 6f 6f 74   ock INTEGER,root
|   3680: 20 42 4c 4f 42 2c 50 52 49 4d 41 52 59 20 4b 45    BLOB,PRIMARY KE
|   3696: 59 28 6c 65 76 65 6c 2c 20 69 64 78 29 29 31 06   Y(level, idx))1.
|   3712: 06 17 45 1f 01 00 69 6e 64 65 78 73 71 6c 69 74   ..E...indexsqlit
|   3728: 65 5f 61 75 74 6f 69 6e 64 65 78 5f 74 31 5f 73   e_autoindex_t1_s
|   3744: 65 67 64 69 72 5f 31 74 31 5f 73 65 67 64 69 72   egdir_1t1_segdir
|   3760: 06 0f c7 00 08 00 00 00 00 66 04 07 17 23 23 01   .........f...##.
|   3776: 81 13 74 61 62 6c 65 74 31 5f 73 65 67 6d 65 6e   ..tablet1_segmen
|   3792: 74 73 74 31 5f 73 65 67 6d 65 6e 74 73 04 43 52   tst1_segments.CR
|   3808: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 73   EATE TABLE 't1_s
|   3824: 65 67 6d 65 6e 74 73 27 28 62 6c 6f 63 6b 69 64   egments'(blockid
|   3840: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59    INTEGER PRIMARY
|   3856: 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42    KEY, block BLOB
|   3872: 29 6a 03 07 17 21 21 01 81 1f 74 61 62 6c 65 74   )j...!!...tablet
|   3888: 31 5f 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74   1_contentt1_cont
|   3904: 65 6e 74 03 43 52 45 41 54 45 20 54 41 42 4c 45   ent.CREATE TABLE
|   3920: 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28 64 6f    't1_content'(do
|   3936: 63 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d   cid INTEGER PRIM
|   3952: 41 52 59 30 4b 45 59 2c 20 27 63 30 61 27 2c 20   ARY0KEY, 'c0a', 
|   3968: 27 63 31 62 27 2c 20 27 63 32 63 27 29 38 02 06   'c1b', 'c2c')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 33   LE t1 USING fts3
|   4032: 28 61 2c 62 2c 63 29 00 00 00 39 00 00 00 00 00   (a,b,c)...9.....
| page 3 offset 8192
|      0: 0d 00 00 00 25 0b 48 00 0f d8 0f af 0f 86 0f 74   ....%.H........t
|     16: 0f 61 0f 4e 0f 2f 0f 0f 0e ef 0e d7 0e be 0e a5   .a.N./..........
|     32: 0e 8d 0e 74 0e 5b 0e 40 0e 24 0e 08 0d ef 0d d5   ...t.[.@.$......
|     48: 0d bb 0d a0 0d 84 0d 68 0d 4f 0d 35 0d 1b 0c fb   .......h.O.5....
|     64: 0c da 0c b9 0c 99 0c 78 0c 57 0c 3e 0c 24 0c 0a   .......x.W.>.$..
|     80: 0b 48 00 00 00 00 00 00 00 00 00 00 00 00 00 00   .H..............
|   2880: 00 00 00 00 00 00 00 00 81 3f 25 06 00 82 7f 00   .........?%.....
|   2896: 00 43 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e   .COMPILER=gcc-5.
|   2912: 34 2e 30 20 32 30 31 36 30 36 30 39 20 44 45 42   4.0 20160609 DEB
|   2928: 55 47 20 45 4e 41 42 4c 45 20 44 42 53 54 41 54   UG ENABLE DBSTAT
|   2944: 20 56 54 41 42 20 45 4e 41 42 4c 45 20 46 54 53    VTAB ENABLE FTS
|   2960: 34 20 45 4e 41 42 4c 45 20 46 54 53 35 20 45 4e   4 ENABLE FTS5 EN
|   2976: 41 42 4c 45 20 47 45 4f 50 4f 4c 59 20 45 4e 41   ABLE GEOPOLY ENA
|   2992: 42 4c 45 20 4a 53 4f 4e 31 20 45 4e 41 42 4c 45   BLE JSON1 ENABLE
|   3008: 20 4d 45 4d 53 59 53 35 20 45 4e 41 42 4c 45 1f    MEMSYS5 ENABLE.
|   3024: 52 54 52 45 45 20 4d 41 58 20 4d 45 4d 4f 52 59   RTREE MAX MEMORY
|   3040: 3d 35 30 30 30 30 30 30 30 20 4f 4d 49 54 20 4c   =50000000 OMIT L
|   3056: 4f 41 44 20 45 58 54 45 4e 53 49 4f 4e 20 54 48   OAD EXTENSION TH
|   3072: 52 45 41 44 53 41 46 45 3d 30 18 24 05 00 25 0f   READSAFE=0.$..%.
|   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 22   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 4f 4d   0XRTRIM.!..3..OM
|   3168: 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49 4f   IT LOAD EXTENSIO
|   3184: 4e 58 43 49 4e 41 52 59 1f 20 05 00 33 0f 19 4f   NXCINARY. ..3..O
|   3200: 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49   MIT LOAD EXTENSI
|   3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17   ONXNOCASE....3..
|   3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53   OMIT LOAD EXTENS
|   3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19   IONXRTRIM....3..
|   3264: 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30   MAX MEMORY=50000
|   3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f   000XBINARY....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 33   0000XNOCASE....3
|   3328: 0f 17 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30   ..MAX 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 58 4e 4f 43 41 53 45 17   LE RTREEXNOCASE.
|   3408: 19 05 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52   ...%..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 53 35 58 52 54 52 49 4d 18 15 09 00 25   MSYS5XRTRIM....%
|   3520: 0f 19 45 4e 41 42 4c 45 20 4a 53 4f 4e 31 58 42   ..ENABLE 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 31 58 4e 4f 43 41 53 45 17   LE JSON1XNOCASE.
|   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 4e 41 42 4c   NARY....)..ENABL
|   3632: 45 20 47 45 4f 50 4f 4c 59 58 4e 4f 43 41 53 45   E GEOPOLYXNOCASE
|   3648: 19 10 05 00 29 0f 17 45 4e 41 42 4c 46 20 47 45   ....)..ENABLF GE
|   3664: 4f 50 4f 4c 59 58 52 54 52 49 4d 17 0f 05 00 23   OPOLYXRTRIM....#
|   3680: 0f 19 45 4e 41 42 4c 45 20 46 54 53 35 58 42 49   ..ENABLE FTS5XBI
|   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 58 4e 4f 43 41 53 45 16 0d 05   E FTS5XNOCASE...
|   3728: 00 23 0f 17 45 4e 41 42 4c 45 20 46 54 53 35 58   .#..ENABLE FTS5X
|   3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42   RTRIM....#..ENAB
|   3760: 4c 45 20 46 54 53 34 58 42 49 4e 41 52 59 17 0b   LE FTS4XBINARY..
|   3776: 05 00 23 0f 19 45 4e 41 42 4c 45 20 46 54 53 34   ..#..ENABLE FTS4
|   3792: 58 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 45 4e   XNOCASE....#..EN
|   3808: 41 42 4c 45 20 46 54 53 34 58 52 54 52 49 4d 1e   ABLE FTS4XRTRIM.
|   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 3d 67   ...C..COMPILER=g
|   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 43   9XNOCASE&...C..C
|   4064: 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e   OMPILER=gcc-5.4.
|   4080: 30 20 32 30 31 36 30 36 30 39 58 52 54 52 49 4d   0 20160609XRTRIM
| 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 02 0b a0 00 0c ad 0b a0 00 00 00 00   ................
|   2976: 82 0a 02 08 08 09 08 08 17 84 06 30 20 32 35 33   ...........0 253
|   2992: 00 01 30 04 25 06 1b 00 00 08 32 30 31 36 30 36   ..0.%.....201606
|   3008: 30 39 03 25 07 00 00 01 34 03 25 05 00 00 01 35   09.%....4.%....5
|   3024: 03 25 04 00 01 07 30 30 30 30 30 30 30 03 25 1a   .%....0000000.%.
|   3040: 00 00 08 63 6f 6d 70 69 6c 65 72 03 25 02 00 00   ...compiler.%...
|   3056: 06 64 62 73 74 61 74 03 25 0a 00 01 04 65 62 75   .dbstat.%....ebu
|   3072: 67 03 25 08 00 00 06 65 6e 61 62 6c 65 09 25 09   g.%....enable.%.
|   3088: 05 04 04 04 04 04 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3104: 6e 03 25 1d 00 00 04 66 74 73 34 03 25 0d 00 03   n.%....fts4.%...
|   3120: 01 35 03 25 0f 00 00 03 67 63 63 03 25 03 00 01   .5.%....gcc.%...
|   3136: 06 65 6f 70 6f 6c 79 03 25 11 00 00 05 6a 73 6f   .eopoly.%....jso
|   3152: 6e 31 03 25 13 00 00 04 6c 6f 61 64 03 25 1c 00   n1.%....load.%..
|   3168: 00 03 6d 61 78 03 25 18 00 01 05 65 6d 6f 72 79   ..max.%....emory
|   3184: 03 25 19 00 03 04 73 79 73 35 03 25 15 00 00 04   .%....sys5.%....
|   3200: 6f 6d 69 74 03 25 1b 00 00 05 72 74 72 65 65 03   omit.%....rtree.
|   3216: 25 17 00 00 0a 74 68 72 65 61 64 73 61 66 65 03   %....threadsafe.
|   3232: 25 1e 00 00 04 76 74 61 62 03 25 0b 00 86 50 01   %....vtab.%...P.
|   3248: 08 08 08 08 09 17 8d 12 30 20 38 33 35 00 01 30   ........0 835..0
|   3264: 12 01 06 00 01 06 00 01 06 00 1f 03 00 01 03 00   ................
|   3280: 01 03 00 00 08 32 30 31 36 30 36 30 39 09 01 07   .....20160609...
|   3296: 00 01 07 00 01 07 00 00 01 34 09 01 05 00 01 05   .........4......
|   3312: 00 01 05 00 00 01 35 09 01 04 00 01 04 00 01 04   ......5.........
|   3328: 00 01 07 30 30 30 30 30 30 30 09 1c 04 00 01 04   ...0000000......
|   3344: 00 01 04 00 00 06 62 69 6e 61 72 79 3c 03 01 02   ......binary<...
|   3360: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3376: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
|   3392: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03   ................
|   3408: 01 02 02 00 03 01 02 02 00 00 08 63 6f 6d 70 69   ...........compi
|   3424: 6c 65 72 09 01 02 00 01 02 00 01 02 00 00 06 64   ler............d
|   3440: 62 73 74 61 74 09 07 03 00 01 03 00 01 03 00 01   bstat...........
|   3456: 04 65 62 75 67 09 04 02 00 01 02 00 01 02 00 00   .ebug...........
|   3472: 06 65 6e 61 62 6c 65 3f 07 02 00 01 02 00 01 02   .enable?........
|   3488: 00 01 02 00 01 02 00 01 02 00 01 02 00 01 02 00   ................
|   3504: 01 02 00 01 02 00 01 02 00 01 02 00 01 02 00 01   ................
|   3520: 02 00 01 02 00 01 02 00 01 02 00 01 02 00 01 02   ................
|   3536: 00 01 02 00 01 02 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3552: 6e 09 1f 04 00 01 04 00 01 04 00 00 04 66 74 73   n............fts
|   3568: 34 09 0a 03 00 01 03 00 01 03 00 03 01 35 09 0d   4............5..
|   3584: 03 00 01 03 00 01 03 00 00 03 67 63 63 09 01 03   ..........gcc...
|   3600: 00 01 03 00 01 03 00 01 06 65 6f 70 6f 6c 79 09   .........eopoly.
|   3616: 10 03 00 01 03 00 01 03 00 00 05 6a 73 6f 6e 31   ...........json1
|   3632: 09 13 03 00 01 03 00 01 03 00 00 04 6c 6f 61 64   ............load
|   3648: 09 1f 03 00 01 03 00 01 03 00 00 03 6d 61 78 09   ............max.
|   3664: 1c 02 00 01 02 00 01 02 00 01 05 65 6d 6f 72 79   ...........emory
|   3680: 09 1c 03 00 01 03 00 01 03 00 03 04 73 79 73 35   ............sys5
|   3696: 09 16 03 00 01 03 00 01 03 00 00 06 6e 6f 63 61   ............noca
|   3712: 73 65 3c 02 01 02 02 00 03 01 02 02 00 03 01 02   se<.............
|   3728: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3744: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
|   3760: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 00   ................
|   3776: 04 6f 6d 69 74 09 1f 02 00 01 02 00 01 02 00 00   .omit...........
|   3792: 05 72 74 72 65 65 09 19 03 00 01 03 00 01 03 00   .rtree..........
|   3808: 03 02 69 6d 3c 01 01 02 02 00 03 01 02 02 00 03   ..im<...........
|   3824: 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01   ................
|   3840: 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02   ................
|   3856: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3872: 00 00 0a 74 68 72 65 61 64 73 61 66 65 09 22 02   ...threadsafe...
|   3888: 00 01 02 00 02 02 00 00 04 76 74 61 62 09 07 04   .........vtab...
|   3904: 00 01 04 00 01 04 00 00 01 78 b4 01 01 01 01 02   .........x......
|   3920: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   3936: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   3952: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   3968: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   3984: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4000: 10 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   4016: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   4032: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   4048: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   4064: 02 00 01 01 02 02 00 01 01 01 02 00 01 01 01 02   ................
|   4080: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
| page 6 offset 20480
|      0: 0a 00 00 00 02 0f f5 00 0f fb 0f f5 00 00 00 00   ................
|   4080: 00 00 00 00 00 05 04 08 09 01 02 04 04 08 08 09   ................
| page 7 offset 24576
|      0: 0d 00 00 00 05 0f b8 00 0f f4 0f e9 0f d6 0f c7   ................
|     16: 0f b8 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   4016: 00 00 00 00 00 00 00 00 0d 05 02 23 61 75 74 6f   ...........#auto
|   4032: 6d 65 72 67 65 3d 35 0d 04 02 23 6d 65 72 67 65   merge=5...#merge
|   4048: 3d 31 30 30 2c 38 11 03 02 2b 69 6e 74 65 67 72   =100,8...+integr
|   4064: 69 74 79 2d 63 68 65 63 6b 09 02 02 1b 72 65 62   ity-check....reb
|   4080: 75 69 6c 64 0a 01 02 1d 6f 70 74 69 6d 69 7a 65   uild....optimize
| end crash-c3a971f0061039.db
}]} {}

do_catchsql_test 10.1 {
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100)
    INSERT OR IGNORE INTO t1(a,c) SELECT x,null FROM c
    UNION ALL SELECT 180-x,printf('[%,d]',x*-5844627) FROM c;
} {0 {}}

do_catchsql_test 10.3 {
  INSERT INTO t1(t1) VALUES('optimize');
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
reset_db
do_test 11.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 28672 pagesize 4096 filename crash-843cb8447eaf14.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 02 00 00 00 01 00 00 00 07 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 0e b1 00 06 0d a4 00 0f 8d 0f 21   ...............!
|    112: 0e b9 0d c8 0e 7e 0d a4 0d a4 00 00 00 00 00 00   .....~..........
|   3488: 00 00 00 00 22 07 06 17 11 11 01 31 74 61 62 6c   ...........1tabl
|   3504: 65 74 32 74 32 07 43 52 45 41 54 45 20 54 41 42   et2t2.CREATE TAB
|   3520: 4c 45 20 74 32 28 78 29 81 33 05 07 17 1f 1f 01   LE t2(x).3......
|   3536: 82 35 74 61 62 6c 65 74 31 5f 73 65 67 64 69 72   .5tablet1_segdir
|   3552: 74 31 5f 73 65 67 64 69 72 05 43 52 45 41 54 45   t1_segdir.CREATE
|   3568: 20 54 41 42 4c 45 20 27 74 31 5f 73 65 67 64 69    TABLE 't1_segdi
|   3584: 72 27 28 6c 65 76 65 6c 20 49 4e 54 45 47 45 52   r'(level INTEGER
|   3600: 2c 69 64 78 20 49 4e 54 45 47 45 52 2c 73 74 61   ,idx INTEGER,sta
|   3616: 72 74 5f 62 6c 6f 63 6b 20 49 4e 54 45 47 45 52   rt_block INTEGER
|   3632: 2c 6c 65 61 76 65 73 5f 65 6e 64 5f 62 6c 6f 63   ,leaves_end_bloc
|   3648: 6b 20 49 4e 54 45 47 45 52 2c 65 6e 64 5f 62 6c   k INTEGER,end_bl
|   3664: 6f 63 6b 20 49 4e 54 45 47 45 52 2c 72 6f 6f 74   ock INTEGER,root
|   3680: 20 42 4c 4f 42 2c 50 52 49 4d 41 52 59 20 4b 45    BLOB,PRIMARY KE
|   3696: 59 28 6c 65 76 65 6c 2c 20 69 64 78 29 29 31 06   Y(level, idx))1.
|   3712: 06 17 45 1f 01 00 69 6e 64 65 78 73 71 6c 69 74   ..E...indexsqlit
|   3728: 65 5f 61 75 74 6f 69 6e 64 65 78 5f 74 31 5f 73   e_autoindex_t1_s
|   3744: 65 67 64 69 72 5f 31 74 31 5f 73 65 67 64 69 72   egdir_1t1_segdir
|   3760: 06 0f c7 00 08 00 00 00 00 66 04 07 17 23 23 01   .........f...##.
|   3776: 81 13 74 61 62 6c 65 74 31 5f 73 65 67 6d 65 6e   ..tablet1_segmen
|   3792: 74 73 74 31 5f 73 65 67 6d 65 6e 74 73 04 43 52   tst1_segments.CR
|   3808: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 73   EATE TABLE 't1_s
|   3824: 65 67 6d 65 6e 74 73 27 28 62 6c 6f 63 6b 69 64   egments'(blockid
|   3840: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59    INTEGER PRIMARY
|   3856: 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42    KEY, block BLOB
|   3872: 29 6a 03 07 17 21 21 01 81 1f 74 61 62 6c 65 74   )j...!!...tablet
|   3888: 31 5f 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74   1_contentt1_cont
|   3904: 65 6e 74 03 43 52 45 41 54 45 20 54 41 42 4c 45   ent.CREATE TABLE
|   3920: 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28 64 6f    't1_content'(do
|   3936: 63 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d   cid INTEGER PRIM
|   3952: 41 52 59 20 4b 45 59 2c 20 27 63 30 61 27 2c 20   ARY KEY, 'c0a', 
|   3968: 27 63 31 62 27 2c 20 27 63 32 63 27 29 38 02 06   'c1b', 'c2c')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 33   LE t1 USING fts3
|   4032: 28 61 2c 62 2c 63 29 00 00 00 39 00 00 00 00 00   (a,b,c)...9.....
| page 3 offset 8192
|      0: 0d 00 00 00 25 0b 48 00 0f d8 0f af 0f 86 0f 74   ....%.H........t
|     16: 0f 61 0f 4e 0f 2f 0f 0f 0e ef 0e d7 0e be 0e a5   .a.N./..........
|     32: 0e 8d 0e 74 0e 5b 0e 40 0e 24 0e 08 0d ef 0d d4   ...t.[.@.$......
|     48: dd bb 0d a0 0d 84 0d 68 0d 4f 0d 35 0d 1b 0c fb   .......h.O.5....
|     64: 0c da 0c b9 35 99 0c 78 0c 57 0c 3e 0c 24 0c 0a   ....5..x.W.>.$..
|     80: 0b 48 00 00 00 00 00 00 00 00 00 00 00 00 00 00   .H..............
|   2880: 00 00 00 00 00 00 00 00 81 3f 25 06 00 82 7f 00   .........?%.....
|   2896: 00 43 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e   .COMPILER=gcc-5.
|   2912: 34 2e 30 20 32 30 31 36 30 36 30 39 20 44 45 42   4.0 20160609 DEB
|   2928: 55 47 20 45 4e 41 42 4c 45 20 44 42 53 54 41 54   UG ENABLE DBSTAT
|   2944: 20 56 54 41 42 20 45 4e 41 42 4c 45 20 46 54 53    VTAB ENABLE FTS
|   2960: 34 20 45 4e 41 42 4c 45 20 46 54 53 35 20 45 4e   4 ENABLE FTS5 EN
|   2976: 41 42 4c 45 20 47 45 4f 50 4f 4c 59 20 45 4e 41   ABLE GEOPOLY ENA
|   2992: 42 4c 45 20 4a 53 4f 4e 31 20 45 4e 41 42 4c 45   BLE JSON1 ENABLE
|   3008: 20 4d 45 4d 53 59 53 35 20 45 4e 41 42 4c 45 20    MEMSYS5 ENABLE 
|   3024: 52 54 52 45 45 20 4d 41 58 20 4d 45 4d 4f 52 59   RTREE MAX MEMORY
|   3040: 3d 35 30 30 30 30 30 30 30 20 4f 4d 49 54 20 4c   =50000000 OMIT L
|   3056: 4f 41 44 20 45 58 54 45 4e 53 49 4f 4e 20 54 48   OAD EXTENSION TH
|   3072: 52 45 41 44 53 41 46 45 3d 30 18 24 05 00 25 0f   READSAFE=0.$..%.
|   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 22   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 4f 4d   0XRTRIM.!..3..OM
|   3168: 49 54 20 4c 4f 41 44 20 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 53 49   MIT LOAD EXTENSI
|   3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17   ONXNOCASE....3..
|   3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53   OMIT LOAD EXTENS
|   3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19   IONXRTRIM....3..
|   3264: 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30   MAX MEMORY=50000
|   3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f   000XBINARY....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 33   0000XNOCASE....3
|   3328: 0f 17 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30   ..MAX 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 58 4e 4f 43 41 53 45 17   LE RTREEXNOCASE.
|   3408: 19 05 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52   ...%..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 53 35 58 52 54 52 49 4d 18 15 05 00 25   MSYS5XRTRIM....%
|   3520: 0f 19 45 4e 41 42 4c 45 20 4a 53 4f 4e 31 58 42   ..ENABLE 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 31 58 4e 4f 43 41 53 45 17   LE JSON1XNOCASE.
|   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 4e 41 42 4c   NARY....)..ENABL
|   3632: 45 20 47 45 4f 50 4f 4c 59 58 4e 4f 43 41 53 45   E GEOPOLYXNOCASE
|   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 19 45 4e 41 42 4c 45 20 46 54 53 35 58 42 49   ..ENABLE FTS5XBI
|   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 58 4e 4f 43 41 53 45 16 0d 05   E FTS5XNOCASE...
|   3728: 00 23 0f 17 45 4e 41 42 4c 45 20 46 54 53 35 58   .#..ENABLE FTS5X
|   3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42   RTRIM....#..ENAB
|   3760: 4c 45 20 46 54 53 34 58 42 49 4e 41 52 59 17 0b   LE FTS4XBINARY..
|   3776: 05 00 23 0f 19 45 4e 41 42 4c 45 20 46 54 53 34   ..#..ENABLE FTS4
|   3792: 58 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 45 4e   XNOCASE....#..EN
|   3808: 41 42 4c 45 20 46 54 53 34 58 52 54 52 49 4d 1e   ABLE FTS4XRTRIM.
|   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 3d 67   ...C..COMPILER=g
|   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 43   9XNOCASE&...C..C
|   4064: 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e   OMPILER=gcc-5.4.
|   4080: 30 20 32 30 31 36 30 36 30 39 58 52 54 52 49 4d   0 20160609XRTRIM
| 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 02 0b a0 00 0c ad 0b a0 00 00 00 00   ................
|   2976: 82 0a 02 08 08 09 08 08 17 84 06 30 20 32 35 33   ...........0 253
|   2992: 00 01 30 04 25 06 1b 00 00 08 32 30 31 36 30 36   ..0.%.....201606
|   3008: 30 39 03 25 07 00 00 01 34 03 25 05 00 00 01 35   09.%....4.%....5
|   3024: 03 25 04 00 01 07 30 30 30 30 30 30 30 03 25 1a   .%....0000000.%.
|   3040: 00 00 08 63 6f 6d 70 69 6c 65 72 03 25 02 00 00   ...compiler.%...
|   3056: 06 64 62 73 74 61 74 03 25 0a 00 01 04 65 62 75   .dbstat.%....ebu
|   3072: 67 03 25 08 00 00 06 65 6e 61 62 6c 65 09 25 09   g.%....enable.%.
|   3088: 05 04 04 04 04 04 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3104: 6e 03 25 1d 00 00 04 66 74 73 34 03 25 0d 00 03   n.%....fts4.%...
|   3120: 01 35 03 25 0f 00 00 03 67 63 63 03 25 03 00 01   .5.%....gcc.%...
|   3136: 06 65 6f 70 6f 6c 79 03 25 11 00 00 05 6a 73 6f   .eopoly.%....jso
|   3152: 6e 31 03 25 13 00 00 04 6c 6f 61 64 03 25 1c 00   n1.%....load.%..
|   3168: 00 03 6d 61 78 03 25 18 00 01 05 65 6d 6f 72 79   ..max.%....emory
|   3184: 03 25 19 00 03 04 73 79 73 35 03 25 15 00 00 04   .%....sys5.%....
|   3200: 6f 6d 69 74 03 25 1b 00 00 05 72 74 72 65 65 03   omit.%....rtree.
|   3216: 25 17 00 00 0a 74 68 72 65 61 64 73 61 66 65 03   %....threadsafe.
|   3232: 25 1e 00 00 04 76 74 61 62 03 25 0b 00 86 50 01   %....vtab.%...P.
|   3248: 08 08 08 08 08 17 8d 12 30 20 38 33 35 00 01 30   ........0 835..0
|   3264: 12 01 06 00 01 06 00 01 06 00 1f 03 00 01 03 00   ................
|   3280: 01 03 00 00 08 32 30 31 36 30 36 30 39 09 01 07   .....20160609...
|   3296: 00 01 07 00 01 07 00 00 01 34 09 01 05 00 01 05   .........4......
|   3312: 00 01 05 00 00 01 35 09 01 04 00 01 04 00 01 04   ......5.........
|   3328: 00 01 07 30 30 30 30 30 30 30 09 1c 04 00 01 04   ...0000000......
|   3344: 00 01 04 00 00 06 62 69 6e 61 72 79 3c 03 01 02   ......binary<...
|   3360: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3376: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
|   3392: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03   ................
|   3408: 01 02 02 00 03 01 02 02 00 00 08 63 6f 6d 70 69   ...........compi
|   3424: 6c 65 72 09 01 02 00 01 02 00 01 02 00 00 06 64   ler............d
|   3440: 62 73 74 61 74 09 07 03 00 01 03 00 01 03 00 01   bstat...........
|   3456: 04 65 62 75 67 09 04 02 00 01 02 00 01 02 00 00   .ebug...........
|   3472: 06 65 6e 61 62 6c 65 3f 07 02 00 01 02 00 01 02   .enable?........
|   3488: 00 01 02 00 01 02 00 01 02 00 01 02 00 01 02 00   ................
|   3504: 01 02 00 01 02 00 01 02 00 01 02 00 01 01 00 01   ................
|   3520: 02 00 01 02 00 01 02 00 01 02 00 01 02 00 01 02   ................
|   3536: 00 01 02 00 01 02 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3552: 6e 09 1f 04 00 01 04 00 01 04 00 00 04 66 74 73   n............fts
|   3568: 34 09 0a 03 00 01 03 00 01 03 00 03 01 35 09 0d   4............5..
|   3584: 03 00 01 03 00 01 03 00 00 03 67 63 63 09 01 03   ..........gcc...
|   3600: 00 01 03 00 01 03 00 01 06 65 6f 70 6f 6c 79 09   .........eopoly.
|   3616: 10 03 00 01 03 00 01 03 00 00 05 6a 73 6f 6e 31   ...........json1
|   3632: 09 13 03 00 01 03 00 01 03 00 00 04 6c 6f 61 64   ............load
|   3648: 09 1f 03 00 01 03 00 01 03 00 00 03 6d 61 78 09   ............max.
|   3664: 1c 02 00 01 02 00 01 02 00 01 05 65 6d 6f 72 79   ...........emory
|   3680: 09 1c 03 00 01 03 00 01 03 00 03 04 73 79 73 35   ............sys5
|   3696: 09 16 03 00 01 03 00 01 03 00 00 06 6e 6f 63 61   ............noca
|   3712: 73 65 3c 02 01 02 02 00 03 01 02 02 00 03 01 02   se<.............
|   3728: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3744: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
|   3760: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 00   ................
|   3776: 04 6f 6d 69 74 09 1f 02 00 01 02 00 01 02 00 00   .omit...........
|   3792: 05 72 74 72 65 65 09 19 03 00 01 03 00 01 03 00   .rtree..........
|   3808: 03 02 69 6d 3c 01 01 02 02 00 03 01 02 02 00 03   ..im<...........
|   3824: 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01   ................
|   3840: 02 02 00 03 01 02 02 00 03 01 a2 02 00 03 01 02   ................
|   3856: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3872: 00 00 0a 74 68 72 65 61 64 73 61 66 65 09 22 02   ...threadsafe...
|   3888: 00 01 02 00 01 02 00 00 04 76 74 61 62 09 07 04   .........vtab...
|   3904: 00 01 04 00 01 04 00 00 01 78 b4 01 01 01 01 02   .........x......
|   3920: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   3936: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   3952: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   3968: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   3984: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4000: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   4016: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   4032: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   4048: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   4064: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4080: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
| page 6 offset 20480
|      0: 0a 00 00 00 02 0f f5 00 0f fb 0f f5 00 00 00 00   ................
|   4080: 00 00 00 00 00 05 04 08 09 01 02 04 04 08 08 09   ................
| page 7 offset 24576
|      0: 0d 00 00 00 05 0f b8 00 0f f4 0f e9 0f d6 0f c7   ................
|     16: 0f b8 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   4016: 00 00 00 00 00 00 00 00 0d 05 02 23 61 75 74 6f   ...........#auto
|   4032: 6d 65 72 67 65 3d 35 0d 04 02 23 6d 65 72 67 65   merge=5...#merge
|   4048: 3d 31 30 30 2c 38 11 03 02 2b 69 6e 74 65 67 72   =100,8...+integr
|   4064: 69 74 79 2d 63 68 65 63 6b 09 02 02 1b 72 65 62   ity-check....reb
|   4080: 75 69 6c 64 0a 01 02 1d 6f 70 74 69 6d 69 7a 65   uild....optimize
| end crash-843cb8447eaf14.db
}]} {}

do_catchsql_test 11.1 {
  SELECT rowid, quote(matchinfo(t1,'pcxybs')) FROM t1 WHERE t1 MATCH 'e*'
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
reset_db
do_test 12.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 28672 pagesize 4096 filename c81b.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 01 00 00 00 07   .....@  ........
|     32: 00 00 00 02 00 00 00 01 00 00 00 01 00 00 00 04   ................
|     48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00   ................
|     80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01   ................
|     96: 00 2e 30 38 0d 0e b1 00 06 0d a4 00 0f 8d 0f 21   ..08...........!
|    112: 0e b9 0d c8 0e 7e 0d a4 0d a4 00 00 00 00 00 00   .....~..........
|   3488: 00 00 00 00 22 07 06 17 11 11 01 31 74 61 62 6c   ...........1tabl
|   3504: 65 74 32 74 32 07 43 52 45 41 54 45 20 54 41 42   et2t2.CREATE TAB
|   3520: 4c 45 20 74 32 28 78 29 81 33 05 07 17 1f 1f 01   LE t2(x).3......
|   3536: 82 35 74 61 62 6c 65 74 31 5f 73 65 67 64 69 72   .5tablet1_segdir
|   3552: 74 31 5f 73 65 67 64 69 72 05 43 52 45 41 54 45   t1_segdir.CREATE
|   3568: 20 54 41 42 4c 45 20 27 74 31 5f 73 65 67 64 69    TABLE 't1_segdi
|   3584: 72 27 28 6c 65 76 65 6c 20 49 4e 54 45 47 45 52   r'(level INTEGER
|   3600: 2c 69 64 78 20 49 4e 54 45 47 45 52 2c 73 74 61   ,idx INTEGER,sta
|   3616: 72 74 5f 62 6c 6f 63 6b 20 49 4e 54 45 47 45 52   rt_block INTEGER
|   3632: 2c 6c 65 61 76 65 73 5f 65 6e 64 5f 62 6c 6f 63   ,leaves_end_bloc
|   3648: 6b 20 49 4e 54 45 47 45 52 2c 65 6e 64 5f 62 6c   k INTEGER,end_bl
|   3664: 6f 63 6b 20 49 4e 54 45 47 45 62 2c 72 6f 6f 74   ock INTEGEb,root
|   3680: 20 42 4c 4f 42 2c 50 52 49 4d 41 52 59 20 4b 45    BLOB,PRIMARY KE
|   3696: 59 28 6c 65 76 65 6c 2c 20 69 64 78 29 29 31 06   Y(level, idx))1.
|   3712: 06 17 45 1f 01 00 69 6e 64 65 78 73 71 6c 69 74   ..E...indexsqlit
|   3728: 65 5f 61 75 74 6f 69 6e 64 65 78 5f 74 31 5f 73   e_autoindex_t1_s
|   3744: 65 67 64 69 72 5f 31 74 31 5f 73 65 67 64 69 72   egdir_1t1_segdir
|   3760: 06 0f c7 00 08 00 00 00 00 66 04 07 17 23 23 01   .........f...##.
|   3776: 81 13 74 61 62 6c 65 74 31 5f 73 65 67 6d 65 6e   ..tablet1_segmen
|   3792: 74 73 74 31 5f 73 65 67 6d 65 6e 74 73 04 43 52   tst1_segments.CR
|   3808: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 73   EATE TABLE 't1_s
|   3824: 65 67 6d 65 6e 74 73 27 28 62 6c 6f 63 6b 69 64   egments'(blockid
|   3840: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59    INTEGER PRIMARY
|   3856: 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42    KEY, block BLOB
|   3872: 29 6a 03 07 17 21 21 01 81 1f 74 61 62 6c 65 74   )j...!!...tablet
|   3888: 31 5f 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74   1_contentt1_cont
|   3904: 65 6e 74 03 43 52 45 41 54 45 20 54 41 42 4c 45   ent.CREATE TABLE
|   3920: 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28 64 6f    't1_content'(do
|   3936: 63 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d   cid INTEGER PRIM
|   3952: 41 52 59 20 4b 45 59 2c 20 27 63 30 61 27 2c 20   ARY KEY, 'c0a', 
|   3968: 27 63 31 62 27 2c 20 27 63 32 63 27 29 38 02 06   'c1b', 'c2c')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 33   LE t1 USING fts3
|   4032: 28 61 2c 62 2c 63 29 00 00 00 39 00 00 00 00 00   (a,b,c)...9.....
| page 3 offset 8192
|      0: 0d 00 00 00 25 0b 48 00 0f d8 0f af 0f 86 0f 74   ....%.H........t
|     16: 0f 61 0f 4e 0f 2f 0f 0f 0e ef 0e d7 0e be 0e a5   .a.N./..........
|     32: 0e 8d 0e 74 0e 5b 0e 40 0e 24 0e 08 0d ef 0d d5   ...t.[.@.$......
|     48: 0d bb 0d a0 0d 84 0d 68 0d 4f 0d 35 0d 1b 0c fb   .......h.O.5....
|     64: 0c da 0c b9 0c 99 0c 78 0c 57 0c 3e 0c 24 0c 0a   .......x.W.>.$..
|     80: 0b 48 00 00 00 00 00 00 00 00 00 00 00 00 00 00   .H..............
|   2880: 00 00 00 00 00 00 00 00 81 3f 25 06 00 82 7f 00   .........?%.....
|   2896: 00 43 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e   .COMPILER=gcc-5.
|   2912: 34 2e 30 20 32 30 31 36 30 36 30 39 20 44 45 42   4.0 20160609 DEB
|   2928: 55 47 20 45 4e 41 42 4c 45 20 44 42 53 54 41 54   UG ENABLE DBSTAT
|   2944: 20 56 54 41 42 20 45 4e 41 42 4c 45 20 46 54 53    VTAB ENABLE FTS
|   2960: 34 20 45 4e 41 42 4c 45 20 46 54 53 35 20 45 4e   4 ENABLE FTS5 EN
|   2976: 41 42 4c 45 20 47 45 4f 50 4f 4c 59 20 46 4e 41   ABLE GEOPOLY FNA
|   2992: 42 4c 45 20 4a 53 4f 4e 31 20 45 4e 41 42 4c 45   BLE JSON1 ENABLE
|   3008: 20 4d 45 4d 53 59 53 35 20 45 4e 41 42 4c 45 20    MEMSYS5 ENABLE 
|   3024: 52 54 52 45 45 20 4d 41 58 20 4d 45 4d 4f 52 59   RTREE MAX MEMORY
|   3040: 3d 35 30 30 30 30 30 30 30 20 4f 4d 49 54 20 4c   =50000000 OMIT L
|   3056: 4f 41 44 20 45 58 54 45 4e 53 49 4f 4e 20 54 48   OAD EXTENSION TH
|   3072: 52 45 41 44 53 41 46 45 3d 30 18 24 05 00 0f 25   READSAFE=0.$...%
|   3088: 19 58 54 48 52 45 41 44 53 41 46 45 3d 30 42 49   .XTHREADSAFE=0BI
|   3104: 4e 41 52 59 18 23 05 00 0f 25 19 58 54 48 52 45   NARY.#...%.XTHRE
|   3120: 41 44 53 41 46 45 3d 30 4e 4f 43 41 53 45 17 22   ADSAFE=0NOCASE..
|   3136: 05 00 0f 25 17 58 54 48 52 45 41 44 53 41 46 45   ...%.XTHREADSAFE
|   3152: 3d 30 52 54 52 49 4d 1f 21 05 00 0f 33 19 58 4f   =0RTRIM.!...3.XO
|   3168: 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49   MIT LOAD EXTENSI
|   3184: 4f 4e 42 49 4e 41 52 59 1f 20 05 00 0f 33 19 58   ONBINARY. ...3.X
|   3200: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53   OMIT LOAD EXTENS
|   3216: 49 4f 4e 4e 4f 43 41 53 45 1e 1f 05 00 0f 33 17   IONNOCASE.....3.
|   3232: 58 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e   XOMIT LOAD EXTEN
|   3248: 53 49 4f 4e 52 54 52 49 4d 1f 1e 05 00 0f 33 19   SIONRTRIM.....3.
|   3264: 58 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30   XMAX MEMORY=5000
|   3280: 30 30 30 30 42 49 4e 41 52 59 1f 1d 05 00 0f 33   0000BINARY.....3
|   3296: 19 58 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30   .XMAX MEMORY=500
|   3312: 30 30 30 30 30 4e 4f 43 41 53 45 1e 1c 05 00 0f   00000NOCASE.....
|   3328: 33 17 58 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30   3.XMAX MEMORY=50
|   3344: 30 30 30 30 30 30 52 54 52 49 4d 18 1b 05 00 0f   000000RTRIM.....
|   3360: 25 19 58 45 4e 41 42 4c 45 20 52 54 52 45 45 42   %.XENABLE RTREEB
|   3376: 49 4e 41 52 59 18 1a 05 00 0f 25 19 58 45 4e 41   INARY.....%.XENA
|   3392: 42 4c 45 20 52 54 52 45 45 4e 4f 43 41 53 45 17   BLE RTREENOCASE.
|   3408: 19 05 00 0f 25 17 58 45 4e 41 42 4c 45 20 52 54   ....%.XENABLE RT
|   3424: 52 45 45 52 54 52 49 4d 1a 18 05 00 0f 29 19 58   REERTRIM.....).X
|   3440: 45 4e 41 42 4c 45 20 4d 45 4d 53 59 53 35 42 49   ENABLE MEMSYS5BI
|   3456: 4e 41 52 59 1a 17 05 00 0f 29 19 58 45 4e 41 42   NARY.....).XENAB
|   3472: 4c 45 20 4d 45 4d 53 59 53 35 4e 4f 43 41 53 45   LE MEMSYS5NOCASE
|   3488: 19 16 05 00 0f 29 17 58 45 4e 41 42 4c 45 20 4d   .....).XENABLE M
|   3504: 45 4d 53 59 53 35 52 54 52 49 4d 18 15 05 00 0f   EMSYS5RTRIM.....
|   3520: 25 19 58 45 4e 41 42 4c 45 20 4a 53 4f 4e 31 42   %.XENABLE JSON1B
|   3536: 49 4e 41 52 59 18 14 05 00 0f 25 19 58 45 4e 41   INARY.....%.XENA
|   3552: 42 4c 45 20 4a 53 4f 4e 31 4e 4f 43 41 53 45 17   BLE JSON1NOCASE.
|   3568: 13 05 00 0f 25 17 58 45 4e 41 42 4c 45 20 4a 53   ....%.XENABLE JS
|   3584: 4f 4e 31 52 54 52 49 4d 1a 12 05 00 0f 29 19 58   ON1RTRIM.....).X
|   3600: 45 4e 41 42 4c 45 20 47 45 4f 50 4f 4c 59 42 49   ENABLE GEOPOLYBI
|   3616: 4e 41 52 59 1a 11 05 00 0f 29 19 58 45 4e 41 1e   NARY.....).XENA.
|   3632: 4c 45 20 47 45 4f 50 4f 4c 59 4e 4f 43 41 53 45   LE GEOPOLYNOCASE
|   3648: 19 10 05 00 0f 29 17 58 45 4e 41 42 4c 45 20 47   .....).XENABLE G
|   3664: 45 4f 50 4f 4c 59 52 54 52 49 4d 17 0f 05 00 0f   EOPOLYRTRIM.....
|   3680: 23 19 58 45 4e 41 42 4c 45 20 46 54 53 35 42 49   #.XENABLE FTS5BI
|   3696: 4e 41 52 59 17 0e 05 00 0f 23 19 58 55 4e 41 42   NARY.....#.XUNAB
|   3712: 4c 45 20 46 54 53 35 4e 4f 43 41 53 45 16 0d 05   LE FTS5NOCASE...
|   3728: 00 0f 23 17 58 45 4e 41 42 4c 45 20 46 54 53 35   ..#.XENABLE FTS5
|   3744: 52 54 52 49 4d 17 0c 05 00 0f 23 19 58 45 4e 41   RTRIM.....#.XENA
|   3760: 42 4c 45 20 46 54 53 34 42 49 4e 41 52 59 17 0b   BLE FTS4BINARY..
|   3776: 05 00 0f 23 19 58 45 4e 41 42 4c 45 20 46 54 53   ...#.XENABLE FTS
|   3792: 35 4e 4f 43 40 53 45 16 0a 05 00 0f 23 17 58 45   5NOC@SE.....#.XE
|   3808: 4e 41 42 4c 45 20 46 54 53 34 52 54 52 49 4d 1e   NABLE FTS4RTRIM.
|   3824: 09 05 00 0f 31 19 58 45 4e 41 42 4c 35 20 44 42   ....1.XENABL5 DB
|   3840: 53 54 41 54 20 56 54 41 42 42 49 4e 41 52 59 1e   STAT VTABBINARY.
|   3856: 08 05 00 0f 31 19 58 45 4e 41 42 4c 45 20 44 42   ....1.XENABLE DB
|   3872: 53 54 41 54 20 56 54 41 42 4e 4f 43 41 53 45 1d   STAT VTABNOCASE.
|   3888: 07 05 00 0f 31 17 58 45 4e 41 42 4c 45 20 44 42   ....1.XENABLE DB
|   3904: 53 54 41 54 20 56 54 41 42 52 54 52 49 4d 11 06   STAT VTABRTRIM..
|   3920: 05 00 0f 17 19 58 44 45 42 55 47 42 49 4e 41 52   .....XDEBUGBINAR
|   3936: 59 11 05 05 00 0f 17 19 58 44 45 42 55 47 4e 4f   Y.......XDEBUGNO
|   3952: 43 41 53 45 10 04 05 00 0f 17 17 58 44 45 42 55   CASE.......XDEBU
|   3968: 47 52 54 52 49 4d 27 03 05 00 0f 43 19 58 43 4f   GRTRIM'....C.XCO
|   3984: 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e 30   MPILER=gcc-5.4.0
|   4000: 20 32 30 31 36 30 36 30 39 42 49 4e 41 52 59 27    20160609BINARY'
|   4016: 02 05 00 0f 43 19 58 43 4f 4d 50 49 4c 45 52 3d   ....C.XCOMPILER=
|   4032: 67 63 63 2d 35 2e 34 2e 30 20 32 30 31 36 30 36   gcc-5.4.0 201606
|   4048: 30 39 4e 4f 43 41 53 45 26 01 05 00 0f 43 17 58   09NOCASE&....C.X
|   4064: 43 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34   COMPILER=gcc-5.4
|   4080: 2e 30 20 32 30 31 36 30 36 30 39 52 54 52 49 4d   .0 20160609RTRIM
| 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 03 07 bb 00 0c ad 0b a0 07 bb 00 00   ................
|   1968: 00 00 00 00 00 00 00 00 00 00 00 87 62 03 08 08   ............b...
|   1984: 01 08 08 17 8f 34 02 30 20 39 38 30 00 01 30 1e   .....4.0 980..0.
|   2000: 01 01 01 06 00 01 01 01 06 00 01 01 01 06 00 1f   ................
|   2016: 01 01 03 00 01 01 01 03 00 01 01 01 03 00 00 08   ................
|   2032: 32 30 31 36 30 36 30 39 0f 01 01 01 07 00 01 01   20160609........
|   2048: 01 07 00 01 01 01 07 00 00 01 34 0f 01 01 01 05   ..........4.....
|   2064: 00 01 01 01 05 00 01 01 01 05 00 00 01 35 0f 01   .............5..
|   2080: 01 01 04 00 01 01 01 04 00 01 01 01 04 00 01 07   ................
|   2096: 30 30 30 30 30 30 30 0f 1c 01 01 04 00 01 01 01   0000000.........
|   2112: 04 00 01 01 01 04 00 00 06 62 69 6e 61 72 79 3c   .........binary<
|   2128: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03   ................
|   2144: 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01   ................
|   2160: 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02   ................
|   2176: 02 00 03 01 02 02 00 03 01 02 02 00 00 08 63 6f   ..............co
|   2192: 6d 70 69 6c 65 72 0f 01 01 01 02 00 01 01 01 02   mpiler..........
|   2208: 00 01 01 01 02 00 00 06 64 62 73 74 61 74 0f 07   ........dbstat..
|   2224: 01 01 03 00 01 01 01 03 00 01 01 01 03 00 01 04   ................
|   2240: 65 62 75 67 0f 04 01 01 02 00 01 01 01 02 00 01   ebug............
|   2256: 01 01 02 00 00 03 65 6e 61 05 11 01 01 02 00 03   ......ena.......
|   2272: 03 62 6c 35 05 09 01 01 02 00 05 01 65 5a 07 01   .bl5........eZ..
|   2288: 01 02 00 01 01 01 02 00 02 01 01 02 00 01 01 01   ................
|   2304: 02 00 01 01 01 02 00 01 01 01 02 00 02 01 01 02   ................
|   2320: 00 01 01 01 02 00 02 01 01 02 00 01 01 01 02 00   ................
|   2336: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   2352: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   2368: 01 02 00 01 01 01 02 00 01 08 78 74 65 6e 73 69   ..........xtensi
|   2384: 6f 6e 0f 1f 01 01 04 00 01 01 01 04 00 01 01 01   on..............
|   2400: 04 00 00 04 66 74 73 34 0a 0a 01 01 03 00 02 01   ....fts4........
|   2416: 01 03 00 03 01 35 14 0b 01 01 03 00 02 01 01 03   .....5..........
|   2432: 00 01 01 01 03 00 01 01 01 03 00 00 03 67 63 63   .............gcc
|   2448: 0f 01 01 01 03 00 01 01 01 03 00 01 01 01 03 00   ................
|   2464: 01 06 65 6f 70 6f 6c 79 0f 10 01 01 03 00 01 01   ..eopoly........
|   2480: 01 04 00 01 01 01 03 00 00 05 6a 73 6f 6e 31 0f   ..........json1.
|   2496: 13 01 01 03 00 01 01 01 03 00 01 01 01 03 00 00   ................
|   2512: 02 6c 65 05 11 01 01 03 00 01 03 6f 61 64 0f 1f   .le........oad..
|   2528: 01 01 03 00 01 01 01 03 00 01 01 01 03 00 00 03   ................
|   2544: 6d 61 78 0f 1c 01 01 02 00 01 01 01 02 00 01 01   max.............
|   2560: 01 02 00 01 05 65 6d 6f 72 79 0f 1c 01 01 03 00   .....emory......
|   2576: 01 01 01 03 00 01 01 01 03 00 03 04 73 79 73 35   ............sys5
|   2592: 0f 16 01 01 03 00 01 01 01 03 00 01 01 01 03 00   ................
|   2608: 00 03 6e 6f 63 05 0b 01 02 02 00 03 03 61 73 65   ..noc........ase
|   2624: 37 02 01 02 02 00 03 01 02 02 00 03 01 02 02 00   7...............
|   2640: 06 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03   ................
|   2656: 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01   ................
|   2672: 02 02 00 03 01 02 02 00 00 04 6f 6d 69 74 0f 1f   ..........omit..
|   2688: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 00 05   ................
|   2704: 72 74 72 65 65 0f 19 01 01 03 00 01 01 01 03 00   rtree...........
|   2720: 01 01 01 03 00 03 02 69 6d 3c 01 01 02 02 00 03   .......im<......
|   2736: 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01   ................
|   2752: 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02   ................
|   2768: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   2784: 00 03 01 02 02 00 00 02 73 65 05 0b 01 02 03 00   ........se......
|   2800: 00 0a 74 68 72 65 61 64 73 61 66 65 0f 22 01 01   ..threadsafe....
|   2816: 02 00 01 01 01 02 00 01 01 01 02 00 00 06 75 6e   ..............un
|   2832: 61 62 6c 65 05 0e 01 01 02 00 00 04 76 74 61 62   able........vtab
|   2848: 0f 07 01 01 04 00 01 01 01 04 00 01 01 01 04 00   ................
|   2864: 00 01 78 6c 01 02 00 01 02 00 01 02 00 01 02 00   ..xl............
|   2880: 01 02 00 01 02 00 01 02 00 01 02 00 01 02 00 01   ................
|   2896: 02 00 01 02 00 01 02 00 01 02 00 01 02 00 01 02   ................
|   2912: 00 01 02 00 01 02 00 01 02 00 01 02 00 01 02 00   ................
|   2928: 01 02 00 01 02 00 01 02 00 01 02 00 01 02 00 01   ................
|   2944: 02 00 01 02 00 01 02 00 01 02 00 01 02 00 01 02   ................
|   2960: 00 01 02 00 01 02 00 01 02 00 01 02 00 01 02 00   ................
|   2976: 82 0a 02 08 08 09 08 08 17 84 06 30 20 32 35 33   ...........0 253
|   2992: 00 01 30 04 25 06 1b 00 00 08 32 30 31 36 30 36   ..0.%.....201606
|   3008: 30 39 03 25 07 00 00 01 34 03 25 05 00 00 01 35   09.%....4.%....5
|   3024: 03 25 04 00 01 07 30 30 30 30 30 30 30 03 25 1a   .%....0000000.%.
|   3040: 00 00 08 63 6f 6d 70 69 6c 65 72 03 25 02 00 00   ...compiler.%...
|   3056: 06 64 62 73 74 61 74 03 25 0a 00 01 04 65 62 75   .dbstat.%....ebu
|   3072: 67 03 25 08 00 00 06 65 6e 61 62 6c 65 09 25 09   g.%....enable.%.
|   3088: 05 04 04 04 04 04 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3104: 6e 03 25 1d 00 00 04 66 74 73 34 03 25 0d 00 03   n.%....fts4.%...
|   3120: 11 35 03 25 0f 00 00 03 67 63 63 03 25 03 00 01   .5.%....gcc.%...
|   3136: 06 65 6f 70 6f 6c 79 03 25 11 00 00 05 6a 73 6f   .eopoly.%....jso
|   3152: 6e 31 03 25 13 00 00 04 6c 6f 61 64 03 25 1c 00   n1.%....load.%..
|   3168: 00 03 6d 61 78 03 25 18 00 01 05 65 6d 6f 72 79   ..max.%....emory
|   3184: 03 25 19 00 03 04 73 79 73 35 03 25 15 00 00 04   .%....sys5.%....
|   3200: 6f 6d 69 74 03 25 1b 00 00 05 72 74 72 65 65 03   omit.%....rtree.
|   3216: 25 17 00 00 0a 74 68 72 65 61 64 73 61 66 65 03   %....threadsafe.
|   3232: 25 1e 00 00 04 76 74 61 62 03 25 0b 00 86 50 01   %....vtab.%...P.
|   3248: 08 08 08 08 08 17 8d 12 30 20 38 33 35 00 01 30   ........0 835..0
|   3264: 12 00 f6 00 01 06 00 01 06 00 1f 03 00 01 03 00   ................
|   3280: 01 03 00 00 08 32 30 31 36 30 36 30 39 09 01 07   .....20160609...
|   3296: 00 01 07 00 01 07 00 00 01 34 09 01 05 00 01 05   .........4......
|   3312: 00 01 05 00 00 01 35 09 01 04 00 01 04 00 01 04   ......5.........
|   3328: 00 01 07 30 30 30 30 30 30 30 09 1c 04 00 01 04   ...0000000......
|   3344: 00 01 04 00 00 06 62 69 6e 61 72 79 3c 03 01 02   ......binary<...
|   3360: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3376: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
|   3392: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03   ................
|   3408: 01 02 02 00 03 01 02 02 00 00 08 63 6f 6d 70 69   ...........compi
|   3424: 6c 65 72 09 01 02 00 01 02 00 01 02 00 00 06 64   ler............d
|   3440: 62 73 74 61 74 09 07 03 00 01 03 00 01 03 00 01   bstat...........
|   3456: 04 65 62 75 67 09 04 02 00 01 02 00 01 02 00 00   .ebug...........
|   3472: 06 65 6e 61 62 6c 65 3f 07 02 00 01 02 00 01 01   .enable?........
|   3488: 00 01 02 00 01 02 00 01 02 00 01 02 00 01 02 00   ................
|   3504: 01 02 00 01 02 00 01 02 00 01 02 00 01 02 10 01   ................
|   3520: 02 00 01 02 00 01 02 00 01 02 00 01 02 00 01 02   ................
|   3536: 00 01 02 00 01 02 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3552: 6e 09 1f 04 00 01 04 00 01 04 00 00 04 66 74 73   n............fts
|   3568: 34 09 0a 03 00 01 03 00 01 03 00 03 01 35 09 0d   4............5..
|   3584: 03 00 01 03 00 01 03 00 00 03 67 63 63 09 01 03   ..........gcc...
|   3600: 00 01 03 00 01 03 00 01 06 65 6f 70 6f 6c 79 09   .........eopoly.
|   3616: 10 03 00 01 03 00 01 03 00 00 05 6a 73 6f 6e 31   ...........json1
|   3632: 09 13 03 00 01 03 00 01 03 00 00 04 6c 6f 61 64   ............load
|   3648: 09 1f 03 00 01 03 00 01 03 00 00 03 6d 61 78 09   ............max.
|   3664: 1c 02 00 01 02 00 01 02 00 01 05 65 6d 6f 72 79   ...........emory
|   3680: 09 1c 03 00 01 03 00 01 03 00 03 04 73 79 73 35   ............sys5
|   3696: 09 16 03 00 01 03 00 01 03 00 00 06 6e 6f 63 61   ............noca
|   3712: 73 65 3c 02 01 02 02 00 03 01 02 02 00 03 01 02   se<.............
|   3728: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3744: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
|   3760: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 00   ................
|   3776: 04 6f 6d 69 74 09 1f 02 00 01 02 00 01 02 00 00   .omit...........
|   3792: 05 72 74 72 65 65 09 19 03 00 01 03 00 01 03 00   .rtree..........
|   3808: 03 02 69 6d 3c 01 01 02 02 00 03 01 02 02 00 03   ..im<...........
|   3824: 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01   ................
|   3840: 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02   ................
|   3856: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3872: 00 00 0a 74 68 72 65 61 64 73 61 66 65 09 22 02   ...threadsafe...
|   3888: 00 01 02 00 02 02 00 00 04 76 74 61 62 09 07 04   .........vtab...
|   3904: 00 01 04 00 01 04 00 00 01 78 b4 01 01 01 01 02   .........x......
|   3920: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   3936: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   3952: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   3968: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   3984: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4000: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   4016: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   4032: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   4048: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   4064: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4080: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
| page 6 offset 20480
|      0: 0a 00 00 00 03 0f ee 00 0f fb 0f f5 0f ee 00 00   ................
|   4064: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 06 04   ................
|   4080: 08 01 01 02 03 05 04 08 09 01 02 04 04 08 08 09   ................
| page 7 offset 24576
|      0: 0d 00 00 00 05 0f b8 00 0f f4 0f e9 0f d6 0f c7   ................
|     16: 0f b8 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   4016: 00 00 00 00 00 00 00 00 0d 05 02 23 61 75 74 6f   ...........#auto
|   4032: 6d 65 72 67 65 3d 35 0c f4 02 23 6d 65 72 67 65   merge=5...#merge
|   4048: 3d 31 30 30 2c 38 11 03 02 2b 69 6e 74 65 67 72   =100,8...+integr
|   4064: 69 74 79 2d 63 68 65 63 6b 09 02 02 1b 72 65 62   ity-check....reb
|   4080: 75 69 6c 64 0a 01 02 1d 6f 70 74 69 6d 69 7a 65   uild....optimize
| end c81b.db
}]} {}

do_catchsql_test 12.1 {
  SELECT rowid, quote(matchinfo(t1,'pcxybspcxybs')) 
  FROM t1 WHERE t1 MATCH 'e*e*'
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
reset_db
do_test 13.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 28672 pagesize 4096 filename crash-c666cfde112dee.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 02 00 00 00 01 00 00 00 07 00 00 00 04   ................
|     48: 00 00 00 00 00 00 00 07 00 00 00 01 00 00 00 00   ................
|     96: 00 00 00 00 0d 0e b1 00 06 0d a4 00 0f 8d 0f 21   ...............!
|    112: 0e b9 0d c8 0e 7e 0d a4 0d a4 00 00 00 00 00 00   .....~..........
|   3488: 00 00 00 00 22 07 06 17 11 11 01 31 74 61 62 6c   ...........1tabl
|   3504: 65 74 32 74 32 07 43 52 45 41 54 45 20 54 41 42   et2t2.CREATE TAB
|   3520: 4c 45 20 74 32 28 78 29 81 33 05 07 17 1f 1f 01   LE t2(x).3......
|   3536: 82 35 74 61 62 6c 65 74 31 5f 73 65 67 64 69 72   .5tablet1_segdir
|   3552: 74 31 5f 73 65 67 64 69 72 05 43 52 45 41 54 45   t1_segdir.CREATE
|   3568: 20 54 41 42 4c 45 20 27 74 31 5f 73 65 67 64 69    TABLE 't1_segdi
|   3584: 72 27 28 6c 65 76 65 6c 20 49 4e 54 45 47 45 52   r'(level INTEGER
|   3600: 2c 69 64 78 20 49 4e 54 45 47 45 52 2c 73 74 61   ,idx INTEGER,sta
|   3616: 72 74 5f 62 6c 6f 63 6b 20 49 4e 54 45 47 45 52   rt_block INTEGER
|   3632: 2c 6c 65 61 76 65 73 5f 65 6e 64 5f 62 6c 6f 63   ,leaves_end_bloc
|   3648: 6b 20 49 4e 54 45 47 45 52 2c 65 6e 64 5f 62 6c   k INTEGER,end_bl
|   3664: 6f 63 6b 20 49 4e 54 45 47 45 62 2c 72 6f 6f 74   ock INTEGEb,root
|   3680: 20 42 4c 4f 42 2c 50 52 49 4d 41 52 59 20 4b 45    BLOB,PRIMARY KE
|   3696: 59 28 6c 65 76 65 6c 2c 20 69 64 78 29 29 31 06   Y(level, idx))1.
|   3712: 06 17 45 1f 01 00 69 6e 64 65 78 73 71 6c 69 74   ..E...indexsqlit
|   3728: 65 5f 61 75 74 6f 69 6e 64 65 78 5f 74 31 5f 73   e_autoindex_t1_s
|   3744: 65 67 64 69 72 5f 31 74 31 5f 73 65 67 64 69 72   egdir_1t1_segdir
|   3760: 06 0f c7 00 08 00 00 00 00 66 04 07 17 23 23 01   .........f...##.
|   3776: 81 13 74 61 62 6c 65 74 31 5f 73 65 67 6d 65 6e   ..tablet1_segmen
|   3792: 74 73 74 31 5f 73 65 67 6d 65 6e 74 73 04 43 52   tst1_segments.CR
|   3808: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 73   EATE TABLE 't1_s
|   3824: 65 67 6d 65 6e 74 73 27 28 62 6c 6f 63 6b 69 64   egments'(blockid
|   3840: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59    INTEGER PRIMARY
|   3856: 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42    KEY, block BLOB
|   3872: 29 6a 03 07 17 21 21 01 81 1f 74 61 62 6c 65 74   )j...!!...tablet
|   3888: 31 5f 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74   1_contentt1_cont
|   3904: 65 6e 74 03 43 52 45 41 54 45 20 54 41 42 4c 45   ent.CREATE TABLE
|   3920: 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28 64 6f    't1_content'(do
|   3936: 63 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d   cid INTEGER PRIM
|   3952: 41 52 59 20 4b 45 59 2c 20 27 63 30 61 27 2c 20   ARY KEY, 'c0a', 
|   3968: 27 63 31 62 27 2c 20 27 63 32 63 27 29 38 02 06   'c1b', 'c2c')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 33   LE t1 USING fts3
|   4032: 28 61 2c 62 2c 63 29 00 00 00 39 00 00 00 00 00   (a,b,c)...9.....
| page 3 offset 8192
|      0: 0d 00 00 00 25 0b 48 00 0f d8 0f af 0f 86 0f 74   ....%.H........t
|     16: 0f 61 0f 4e 0f 2f 0f 0f 0e ef 0e d7 0e be 0e a5   .a.N./..........
|     32: 0e 8d 0e 74 0e 5b 0e 40 0e 24 0e 08 0d ef 0d d5   ...t.[.@.$......
|     48: 0d bb 0d a0 0d 84 0d 68 0d 4f 0d 35 0d 1b 0c fb   .......h.O.5....
|     64: 0c da 0c b9 0c 99 0c 78 0c 57 0c 3e 0c 24 0c 0a   .......x.W.>.$..
|     80: 0b 48 00 00 00 00 00 00 00 00 00 00 00 00 00 00   .H..............
|   2880: 00 00 00 00 00 00 00 00 81 3f 25 06 00 82 7f 00   .........?%.....
|   2896: 00 43 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e   .COMPILER=gcc-5.
|   2912: 34 23 00 20 32 30 31 36 30 36 30 39 20 44 45 42   4#. 20160609 DEB
|   2928: 55 47 20 45 4e 41 42 4c 45 20 44 42 53 54 41 54   UG ENABLE DBSTAT
|   2944: 20 56 54 41 42 20 45 4e 41 42 4c 45 20 46 54 53    VTAB ENABLE FTS
|   2960: 34 20 45 4e 41 42 4c 45 20 46 54 53 35 20 45 4e   4 ENABLE FTS5 EN
|   2976: 41 42 4c 45 20 47 45 4f 50 4f 4c 59 20 45 4e 41   ABLE GEOPOLY ENA
|   2992: 42 4c 45 20 4a 53 4f 4e 31 20 45 4e 41 42 4c 45   BLE JSON1 ENABLE
|   3008: 20 4d 45 4d 53 59 53 35 20 45 4e 41 42 4c 45 20    MEMSYS5 ENABLE 
|   3024: 52 54 52 45 45 20 4d 41 58 20 4d 45 4d 4f 52 59   RTREE MAX MEMORY
|   3040: 3d 35 30 30 30 30 30 30 30 20 4f 4d 49 54 20 4c   =50000000 OMIT L
|   3056: 4f 41 44 20 45 58 54 45 4e 53 49 4f 4e 20 54 48   OAD EXTENSION TH
|   3072: 52 45 41 44 53 41 46 45 3d 30 18 24 05 00 25 0f   READSAFE=0.$..%.
|   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 22   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 4f 4d   0XRTRIM.!..3..OM
|   3168: 49 54 20 4c 4f 41 44 20 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 53 49   MIT LOAD EXTENSI
|   3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17   ONXNOCASE....3..
|   3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53   OMIT LOAD EXTENS
|   3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19   IONXRTRIM....3..
|   3264: 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30   MAX MEMORY=50000
|   3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f   000XBINARY....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 33   0000XNOCASE....3
|   3328: 0f 17 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30   ..MAX MEMORY=500
|   3344: 30 30 30 30 30 58 52 54 53 49 4d 18 1b 05 00 25   00000XRTSIM....%
|   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 58 4e 4f 43 41 53 45 17   LE RTREEXNOCASE.
|   3408: 19 05 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52   ...%..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 53 35 58 52 54 52 49 4d 18 15 05 00 25   MSYS5XRTRIM....%
|   3520: 0f 19 45 4e 41 42 4c 45 20 4a 53 4f 4e 31 58 42   ..ENABLE 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 31 58 4e 4f 43 41 53 45 17   LE JSON1XNOCASE.
|   3568: 13 05 00 25 0f 17 45 4e 41 52 4c 45 20 4a 53 4f   ...%..ENARLE 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 4e 41 1e 4c   NARY....)..ENA.L
|   3632: 45 20 47 45 4f 50 4f 4c 59 58 4e 4f 43 41 53 45   E GEOPOLYXNOCASE
|   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 19 45 4e 41 42 4c 45 20 46 54 53 35 58 42 49   ..ENABLE FTS5XBI
|   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 58 4e 4f 43 41 53 45 16 0d 05   E FTS5XNOCASE...
|   3728: 00 23 0f 17 45 4e 41 42 4c 45 20 46 54 59 e5 58   .#..ENABLE FTY.X
|   3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42   RTRIM....#..ENAB
|   3760: 4c 45 20 46 54 53 34 58 42 49 4e 41 52 59 17 0b   LE FTS4XBINARY..
|   3776: 05 00 23 0f 19 45 4e 41 42 4c 45 20 46 54 53 35   ..#..ENABLE FTS5
|   3792: 58 4e 4f 43 40 53 45 16 0a 05 00 23 0f 17 45 4e   XNOC@SE....#..EN
|   3808: 41 42 4c 45 20 46 54 53 34 58 52 54 52 49 4d 1e   ABLE FTS4XRTRIM.
|   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 3d 67   ...C..COMPILER=g
|   4032: 63 63 2d 35 2e 34 2f 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 43   9XNOCASE&...C..C
|   4064: 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e   OMPILER=gcc-5.4.
|   4080: 30 20 32 30 31 36 30 36 30 39 58 52 54 52 49 4d   0 20160609XRTRIM
| 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 02 0b a0 00 0c ad 0b a0 00 00 00 00   ................
|   2976: 82 0a 02 08 08 09 08 08 17 84 06 30 20 32 35 33   ...........0 253
|   2992: 00 01 30 04 25 06 1b 00 00 08 32 30 31 36 30 36   ..0.%.....201606
|   3008: 30 39 03 25 07 00 00 01 34 03 25 05 00 00 01 35   09.%....4.%....5
|   3024: 03 25 04 00 01 07 30 30 30 30 30 30 30 03 25 1a   .%....0000000.%.
|   3040: 00 00 08 63 6f 6d 70 69 6c 65 72 03 25 02 00 00   ...compiler.%...
|   3056: 06 64 62 73 74 61 74 03 25 0a 00 01 04 65 62 75   .dbstat.%....ebu
|   3072: 67 03 25 08 00 00 06 65 6e 61 62 6c 65 09 25 09   g.%....enable.%.
|   3088: 05 04 04 04 04 04 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3104: 6e 03 25 1d 00 00 04 66 74 73 34 03 25 0d 00 03   n.%....fts4.%...
|   3120: 01 35 03 25 0f 00 00 03 67 63 63 03 25 03 00 01   .5.%....gcc.%...
|   3136: 06 65 6f 70 6f 6c 79 03 25 11 00 00 05 6a 73 6f   .eopoly.%....jso
|   3152: 6e 31 03 25 13 41 00 04 6c 6f 61 64 03 25 1c 00   n1.%.A..load.%..
|   3168: 00 03 6d 61 78 03 25 18 00 01 05 65 6d 6f 72 79   ..max.%....emory
|   3184: 03 25 19 00 03 04 73 79 73 35 03 25 15 00 00 04   .%....sys5.%....
|   3200: 6f 6d 69 74 03 25 1b 00 00 05 72 74 72 65 65 03   omit.%....rtree.
|   3216: 25 17 00 00 0a 74 68 72 65 61 64 73 61 66 65 03   %....threadsafe.
|   3232: 25 1e 00 00 04 76 74 61 62 03 25 0b 00 86 50 01   %....vtab.%...P.
|   3248: 08 08 08 08 08 17 8d 12 30 20 38 33 35 00 01 30   ........0 835..0
|   3264: 12 01 06 00 01 06 00 01 06 00 1f 03 00 01 03 00   ................
|   3280: 01 03 00 00 08 32 30 31 36 30 36 30 39 09 01 07   .....20160609...
|   3296: 00 01 07 00 01 07 00 00 01 34 09 01 05 00 01 05   .........4......
|   3312: 00 01 05 00 00 01 35 09 01 04 00 01 04 00 01 04   ......5.........
|   3328: 00 01 07 30 30 30 30 30 30 30 09 1c 04 00 01 04   ...0000000......
|   3344: 00 01 04 00 00 06 62 69 6e 61 72 79 3c 03 02 02   ......binary<...
|   3360: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3376: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
|   3392: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03   ................
|   3408: 01 02 02 00 03 01 02 02 00 00 08 63 6f 6d 70 69   ...........compi
|   3424: 6c 65 72 09 01 02 00 01 02 00 01 02 00 00 06 64   ler............d
|   3440: 62 73 74 61 74 09 f2 03 00 01 03 00 01 03 00 01   bstat...........
|   3456: 04 65 62 75 67 09 04 02 00 01 02 00 01 02 00 00   .ebug...........
|   3472: 06 65 6e 61 62 6c 65 3f 07 02 00 01 02 00 01 02   .enable?........
|   3488: 00 01 02 00 01 02 00 01 02 00 01 02 00 57 02 00   .............W..
|   3504: 01 02 00 01 01 00 01 02 00 01 02 00 01 02 10 01   ................
|   3520: 02 00 01 02 00 01 02 00 01 02 00 01 02 00 01 02   ................
|   3536: 00 01 02 00 01 02 00 01 08 78 74 64 6e 73 69 6f   .........xtdnsio
|   3552: 6e 09 1f 04 00 01 04 00 01 03 00 00 04 66 74 73   n............fts
|   3568: 34 09 0a 03 00 01 03 00 01 03 00 03 01 35 09 0d   4............5..
|   3584: 03 00 01 03 00 01 03 00 00 03 57 63 63 09 01 03   ..........Wcc...
|   3600: 00 01 03 00 01 03 00 01 06 65 6f 70 6f 6c 79 09   .........eopoly.
|   3616: 10 03 00 01 03 00 01 03 00 00 05 6a 73 6f 6e 31   ...........json1
|   3632: 09 13 03 00 01 03 00 01 03 00 00 04 6c 6f 61 64   ............load
|   3648: 09 1f 03 00 01 03 00 01 03 00 00 03 6d 61 78 09   ............max.
|   3664: 1c 02 00 01 02 00 01 02 00 01 05 65 6d 6f 72 79   ...........emory
|   3680: 09 1c 03 00 01 03 00 01 03 00 03 04 73 79 73 35   ............sys5
|   3696: 09 16 03 00 01 03 00 01 03 00 00 06 6e 6f 63 61   ............noca
|   3712: 73 65 3c 02 01 02 02 00 03 01 02 02 00 03 01 02   se<.............
|   3728: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3744: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
|   3760: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 00   ................
|   3776: 04 6f 6d 69 74 09 1f 02 00 01 02 00 01 02 00 00   .omit...........
|   3792: 05 72 74 72 65 65 09 19 03 00 01 03 00 01 03 00   .rtree..........
|   3808: 03 02 69 6d 3c 01 01 02 02 00 03 01 02 02 00 03   ..im<...........
|   3824: 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01   ................
|   3840: 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02   ................
|   3856: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3872: 00 00 0a 74 68 72 65 61 64 73 61 66 65 09 22 02   ...threadsafe...
|   3888: 00 01 02 00 02 02 00 00 04 76 74 61 62 09 07 04   .........vtab...
|   3904: 00 01 04 00 01 04 00 00 01 78 b4 01 01 01 01 02   .........x......
|   3920: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   3936: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   3952: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   3968: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   3984: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4000: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   4016: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   4032: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   4048: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   4064: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4080: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
| page 6 offset 20480
|      0: 0a 00 00 00 02 0f f5 00 0f fb 0f f5 00 00 00 00   ................
|   4080: 00 00 00 00 00 05 04 08 09 01 02 04 04 08 08 09   ................
| page 7 offset 24576
|      0: 0d 00 00 00 05 0f b8 00 0f f4 0f e9 0f d6 0f c7   ................
|     16: 0f b8 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   4016: 00 00 00 00 00 00 00 00 0d 05 02 23 61 75 74 6f   ...........#auto
|   4032: 6d 65 72 67 65 3d 35 0d 04 02 23 6d 65 72 67 65   merge=5...#merge
|   4048: 3d 31 30 30 2c 38 11 03 02 2b 69 6e 74 65 67 72   =100,8...+integr
|   4064: 69 74 79 2d 63 68 65 63 6b 09 02 02 1b 72 65 62   ity-check....reb
|   4080: 75 69 6c 64 0a 01 02 1d 6f 70 74 69 6d 69 7a 65   uild....optimize
| end crash-c666cfde112dee.db
}]} {}

do_catchsql_test 13.1 {
  SELECT quote(matchinfo(t1,'pcxybs'))==0 FROM t1 WHERE b MATCH 'e*';
} {0 {}}

#-------------------------------------------------------------------------
reset_db
do_test 14.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 28672 pagesize 4096 filename crash-f7b636a855e1d2.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   ................
|     48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00   ................
|     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 25 04 43 52 45 41 54 45 20 54   _segdi%.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 50 52 49 4d 41 52 59 20 4b   NTEGER PRIMARY 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 31 2c 32 27 29   (a,prefix='1,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 63 0e 1f 00 00 00 00 00 00 00 00   .....c..........
|   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 01 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 43 05 04 00 81 09 44 75 69 73 20 61 75   ur.C.....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 14 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 6c 69 74    adipiscing elit
| page 3 offset 8192
|      0: 0d 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00   ................
| 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 01 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 13 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 04 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: 03 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 08 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 64 03 03 04 00 02   .>0 665..ad.....
|   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 75 72 03 01   .....nsectetur..
|   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 73 03 08 0b 00 01 01 74   se......s......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 00 00   ................
|   4080: 00 00 00 00 00 00 00 07 00 03 00 14 08 45 b5 03   .............E..
| end crash-f7b636a855e1d2.db
}]} {}

do_execsql_test 14.1 {
  PRAGMA writable_schema = 1;
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<10)
    INSERT INTO t1(a) SELECT randomblob(3000) FROM c;
}

do_catchsql_test 14.2 {
  INSERT INTO t1(t1) VALUES('optimize');
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 15.0 {
  CREATE VIRTUAL TABLE t1 USING fts3(a, content="");
  INSERT INTO t1_segdir VALUES(0,0,0,0,'0 665',X'000261640303040002086970697363696e670301080001056c6971756103020c00050269700304040001036d65740301060001036e6a6d03080900010375746503050300000663696c6c756d0306020001066f6d6d6f646f0304070002096e736563746574757203010700050471756174030408000104756c7061030804000207706964617461740307050000086465736572756e740308070001016f0302030002036c6f720601040004050005016506020a00040300010375697303050200000265610304060001066975736d6f640302040001036c69740301090001036e696d13030300010373736503050b0002017403080b0001017403020900010175030604000101780304050002076365707465757203070100020a65726369746174696f6e030309000006667567696174030605000002696403080a0001016e070506040003030002086369646964756e740302060001047073756d030103000104727572650305040000066c61626f7265030208000502697303030b000502756d03080c0001046f72656d0301020000056d61676e6103020b000104696e696d0303050001056f6c6c69740308080000046e6973690304020001026f6e0307060002057374727564030308000104756c6c610306060000086f636361656361740307040001066666696369610308060000087061726961747572030607000107726f6964656e740307070000037175690308050003017303030700000d726570726568656e6465726974030507000003736564030202000103696e7403070300020174030105000103756e7403080200000674656d706f72030205000007756c6c616d636f03030a0001017409020700010200010300000576656c697403050a0002046e69616d0303060001086f6c75707461746503050900');
}

do_execsql_test 15.1 {
  SELECT quote(matchinfo(t1, t1 ))==0 FROM t1 WHERE t1 MATCH 'e*';
} {0 0 0 0 0 0}

#-------------------------------------------------------------------------
reset_db
do_test 16.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 28672 pagesize 4096 filename crash-de7e8cb026385a.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   ................
|     48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00   ................
|     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 af 54 45 47 45 52 20 50 52 49 4d   (id I.TEGER 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 50 52 49 4d 41 52 59 20 4b   NTEGER PRIMARY 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 31 2c 32 27 29   (a,prefix='1,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 63 0e 1f 00 00 00 00 00 00 00 00   .....c..........
|   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 21 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 74 65 2b 04 03 00 5d 6e 69 73 69   it este+...]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 51 6c 69   dolore magna Qli
|   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 e5 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 6c 69 74    adipiscing elit
| page 3 offset 8192
|      0: 0d 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00   ................
| 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 12 08   .....o..........
|   3152: 08 08 17 84 02 04 00 30 20 32 35 31 00 01 61 23   .......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 13 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 10 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 64 03 03 04 00 02   .>0 665..ad.....
|   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 75 72 03 01   .....nsectetur..
|   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 7e 74 03 02 06 00 01 04 70 73   cididu~t......ps
|   3776: 75 6d 03 01 03 00 01 03 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 03 a4 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 00 00   ................
|   4080: 00 00 00 00 00 00 00 07 00 03 00 14 08 45 b5 03   .............E..
| end crash-de7e8cb026385a.db
}]} {}

do_catchsql_test 16.1 {
  INSERT INTO t1(t1) VALUES('optimize');
} {0 {}}

#-------------------------------------------------------------------------
reset_db
do_test 17.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
.open --hexdb
| size 28672 pagesize 4096 filename crash-f15972acf5bc1c.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 02 00 00 00 01 00 00 00 07 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 0e b1 00 06 0d a4 00 0f 8d 0f 21   ...............!
|    112: 0e b9 0d c8 0e 7e 0d a4 0d a4 00 00 00 00 00 00   .....~..........
|   3488: 00 00 00 00 22 07 06 17 11 11 01 31 74 61 62 6c   ...........1tabl
|   3504: 65 74 32 74 32 07 43 52 45 41 54 45 20 54 41 42   et2t2.CREATE TAB
|   3520: 4c 45 20 74 32 28 78 29 81 33 05 07 17 1f 1f 01   LE t2(x).3......
|   3536: 82 35 74 61 62 6c 65 74 31 5f 73 65 67 64 69 72   .5tablet1_segdir
|   3552: 74 31 5f 73 65 67 64 69 72 05 43 52 45 41 54 45   t1_segdir.CREATE
|   3568: 20 54 41 42 4c 45 20 27 74 31 5f 73 65 67 64 69    TABLE 't1_segdi
|   3584: 72 27 28 6c 65 76 65 6c 20 49 4e 54 45 47 45 52   r'(level INTEGER
|   3600: 2c 69 64 78 20 49 4e 54 45 47 45 52 2c 73 74 61   ,idx INTEGER,sta
|   3616: 72 74 5f 62 6c 6f 63 6b 20 49 4e 54 45 47 45 52   rt_block INTEGER
|   3632: 2c 6c 65 61 76 65 73 5f 65 6e 64 5f 62 6c 6f 63   ,leaves_end_bloc
|   3648: 6b 20 49 4e 54 45 47 45 52 2c 65 6e 64 5f 62 6c   k INTEGER,end_bl
|   3664: 6f 63 6b 20 49 4e 54 45 47 45 52 2c 72 6f 6f 74   ock INTEGER,root
|   3680: 20 42 4c 4f 42 2c 50 52 49 4d 41 52 59 20 4b 45    BLOB,PRIMARY KE
|   3696: 59 28 6c 65 76 65 6c 2c 20 69 64 78 29 29 31 06   Y(level, idx))1.
|   3712: 06 17 45 1f 01 00 69 6e 64 65 78 73 71 6c 69 74   ..E...indexsqlit
|   3728: 65 5f 61 75 74 6f 69 6e 64 65 78 5f 74 31 5f 73   e_autoindex_t1_s
|   3744: 65 67 64 69 72 5f 31 74 31 5f 73 65 67 64 69 72   egdir_1t1_segdir
|   3760: 06 0f c7 00 08 00 00 00 00 66 04 07 17 23 23 01   .........f...##.
|   3776: 81 13 74 61 62 6c 65 74 31 5f 73 65 67 6d 65 6e   ..tablet1_segmen
|   3792: 74 73 74 31 5f 73 65 67 6d 65 6e 74 73 04 43 52   tst1_segments.CR
|   3808: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 73   EATE TABLE 't1_s
|   3824: 65 67 6d 65 6e 74 73 27 28 62 6c 6f 63 6b 69 64   egments'(blockid
|   3840: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59    INTEGER PRIMARY
|   3856: 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42    KEY, block BLOB
|   3872: 29 6a 03 07 17 21 21 01 81 1f 74 61 62 6c 65 74   )j...!!...tablet
|   3888: 31 5f 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74   1_contentt1_cont
|   3904: 65 6e 74 03 43 52 45 41 54 45 20 54 41 42 4c 45   ent.CREATE TABLE
|   3920: 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28 64 6f    't1_content'(do
|   3936: 63 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d   cid INTEGER PRIM
|   3952: 41 52 59 20 4b 45 59 2c 20 27 63 30 61 27 2c 20   ARY KEY, 'c0a', 
|   3968: 27 63 31 62 27 2c 20 27 63 32 63 27 29 38 02 06   'c1b', 'c2c')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 33   LE t1 USING fts3
|   4032: 28 61 2c 62 2c 63 29 00 00 00 39 00 00 00 00 00   (a,b,c)...9.....
| page 3 offset 8192
|      0: 0d 00 00 00 25 0b 48 00 0f d8 0f af 0f 86 0f 74   ....%.H........t
|     16: 0f 61 0f 4e 0f 2f 0f 0f 0e ef 0e d7 0e be 0e a5   .a.N./..........
|     32: 0e 8d 0e 74 0e 5b 0e 40 0e 24 0e 08 0d ef 0d d5   ...t.[.@.$......
|     48: 0d bb 0d a0 0d 84 03 28 0d 4f 0d 35 0d 1b 0c fb   .......(.O.5....
|     64: 0c da 0c b9 0c 99 0c 78 0c 57 0c 3e 0c 24 0c 0a   .......x.W.>.$..
|     80: 0b 48 00 00 00 00 00 00 00 00 00 00 00 00 00 00   .H..............
|   2880: 00 00 00 00 00 00 00 00 81 3f 25 06 00 72 7f 00   .........?%..r..
|   2896: 00 43 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e   .COMPILER=gcc-5.
|   2912: 34 2e 30 20 32 30 31 36 30 36 30 39 20 44 45 42   4.0 20160609 DEB
|   2928: 55 47 20 45 4e 41 42 4c 45 20 44 42 53 54 41 54   UG ENABLE DBSTAT
|   2944: 20 56 54 41 42 20 45 4e 41 42 4c 45 20 46 54 53    VTAB ENABLE FTS
|   2960: 34 20 45 4e 41 42 4c 45 20 46 54 53 35 20 45 4e   4 ENABLE FTS5 EN
|   2976: 41 42 4c 45 20 47 45 4f 50 4f 4c 59 20 45 4e 41   ABLE GEOPOLY ENA
|   2992: 42 4c 45 20 4a 53 4f 4e 31 20 45 4e 41 42 4c 45   BLE JSON1 ENABLE
|   3008: 20 4d 45 4d 53 59 53 35 20 45 4e 41 42 4c 45 20    MEMSYS5 ENABLE 
|   3024: 52 54 52 45 45 20 4d 41 58 20 4d 45 4d 4f 52 59   RTREE MAX MEMORY
|   3040: 3d 35 30 30 30 30 30 30 30 20 4f 4d 49 54 20 4c   =50000000 OMIT L
|   3056: 4f 41 43 20 45 58 54 45 4e 53 49 4f 4e 20 54 48   OAC EXTENSION TH
|   3072: 52 45 41 44 53 41 46 45 3d 30 18 24 05 00 25 0f   READSAFE=0.$..%.
|   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 22   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 4f 4d   0XRTRIM.!..3..OM
|   3168: 49 54 20 4c 4f 41 44 20 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 53 49   MIT LOAD EXTENSI
|   3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17   ONXNOCASE....3..
|   3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53   OMIT LOAD EXTENS
|   3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19   IONXRTRIM....3..
|   3264: 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30   MAX MEMORY=50000
|   3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f   000XBINARY....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 33   0000XNOCASE....3
|   3328: 0f 17 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30   ..MAX 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 58 4e 4f 43 41 53 45 17   LE RTREEXNOCASE.
|   3408: 19 05 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52   ...%..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 53 35 58 52 54 52 49 4d 18 14 05 00 25   MSYS5XRTRIM....%
|   3520: 0f 19 45 4e 41 42 4c 45 20 4a 53 4f 4e 31 58 42   ..ENABLE 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 31 58 4e 4f 43 41 53 45 17   LE JSON1XNOCASE.
|   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 4e 41 42 4c   NARY....)..ENABL
|   3632: 45 20 47 45 4f 50 4f 4c 59 58 4e 4f 43 41 53 45   E GEOPOLYXNOCASE
|   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 19 45 4e 41 42 4c 45 20 46 54 53 35 58 42 49   ..ENABLE FTS5XBI
|   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 58 4e 4f 43 41 53 45 16 0d 05   E FTS5XNOCASE...
|   3728: 00 23 0f 17 45 4e 41 42 4c 45 20 46 54 53 35 58   .#..ENABLE FTS5X
|   3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42   RTRIM....#..ENAB
|   3760: 4c 45 20 46 54 53 34 58 42 49 4e 41 52 59 17 0b   LE FTS4XBINARY..
|   3776: 05 00 23 0f 19 45 4e 41 42 4c 45 20 46 54 53 34   ..#..ENABLE FTS4
|   3792: 58 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 45 4e   XNOCASE....#..EN
|   3808: 41 42 4c 45 20 46 54 53 34 58 52 54 52 49 4d 1e   ABLE FTS4XRTRIM.
|   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 0e 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 3d 67   ...C..COMPILER=g
|   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 43   9XNOCASE&...C..C
|   4064: 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e   OMPILER=gcc-5.4.
|   4080: 30 20 32 30 31 36 30 36 30 39 58 52 54 52 49 4d   0 20160609XRTRIM
| 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 02 0b a0 00 0c ad 0b a0 00 00 00 00   ................
|   2976: 82 0a 02 08 08 09 08 08 17 84 06 30 20 32 35 33   ...........0 253
|   2992: 00 01 30 04 25 06 1b 00 00 08 32 30 31 36 30 36   ..0.%.....201606
|   3008: 30 39 03 25 07 00 00 01 34 03 25 05 00 00 01 35   09.%....4.%....5
|   3024: 03 25 04 00 01 07 30 30 30 30 30 30 30 03 25 1a   .%....0000000.%.
|   3040: 00 00 08 63 6f 6d 70 69 6c 65 72 03 25 02 00 00   ...compiler.%...
|   3056: 06 64 62 73 74 61 74 03 25 0a 00 01 04 65 62 75   .dbstat.%....ebu
|   3072: 67 03 25 08 00 00 06 65 6e 61 62 6c 65 09 25 09   g.%....enable.%.
|   3088: 05 04 04 04 04 04 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3104: 6e 03 25 1d 00 00 04 66 74 73 34 03 25 0d 00 03   n.%....fts4.%...
|   3120: 01 35 03 25 0f 00 00 03 67 63 63 03 25 03 00 01   .5.%....gcc.%...
|   3136: 06 65 6f 70 6f 6c 79 03 25 11 00 00 05 6a 73 6f   .eopoly.%....jso
|   3152: 6e 31 03 25 13 00 00 04 6c 6f 61 64 03 25 1c 00   n1.%....load.%..
|   3168: 00 03 6d 61 78 03 25 18 00 01 05 65 6d 6f 72 79   ..max.%....emory
|   3184: 03 25 19 00 03 04 73 79 73 4d 03 25 15 00 00 04   .%....sysM.%....
|   3200: 6f 6d 69 74 03 25 1b 00 00 05 72 74 72 65 65 03   omit.%....rtree.
|   3216: 25 17 00 00 0a 74 68 72 65 61 64 73 61 66 65 03   %....threadsafe.
|   3232: 25 0e 00 00 04 76 74 61 62 03 25 0b 00 86 50 01   %....vtab.%...P.
|   3248: 08 08 08 08 08 17 8d 12 30 20 38 33 35 00 01 30   ........0 835..0
|   3264: 12 01 06 00 01 06 00 01 06 00 1f 03 00 01 03 00   ................
|   3280: 01 03 00 00 08 32 30 31 36 30 36 30 39 09 01 07   .....20160609...
|   3296: 00 01 07 00 01 07 00 00 01 34 09 01 05 00 01 05   .........4......
|   3312: 00 01 05 00 00 01 35 09 01 04 00 01 04 00 01 04   ......5.........
|   3328: 00 01 07 30 30 30 30 30 30 30 09 1c 04 00 01 04   ...0000000......
|   3344: 00 01 04 00 00 06 62 69 6e 61 72 79 3c 03 01 02   ......binary<...
|   3360: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3376: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
|   3392: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03   ................
|   3408: 01 02 02 00 03 01 02 02 00 00 08 63 6f 6d 70 69   ...........compi
|   3424: 6c 65 72 09 01 02 00 01 02 00 01 02 00 00 06 64   ler............d
|   3440: 62 73 74 61 74 09 07 03 00 01 03 00 01 03 00 01   bstat...........
|   3456: 04 65 62 75 67 09 04 02 00 01 02 00 01 02 00 00   .ebug...........
|   3472: 06 65 6e 61 62 6c 65 3f 07 02 00 01 02 00 01 02   .enable?........
|   3488: 00 01 02 00 01 02 00 01 02 00 01 02 00 01 02 00   ................
|   3504: 01 02 00 01 02 00 01 02 00 01 02 00 01 02 00 01   ................
|   3520: 02 00 01 02 00 01 02 00 01 02 00 01 02 00 01 02   ................
|   3536: 00 01 02 00 01 02 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3552: 6e 09 1f 04 00 01 04 00 01 04 00 00 04 66 74 73   n............fts
|   3568: 34 09 0a 03 00 01 03 00 01 03 00 03 01 35 09 0d   4............5..
|   3584: 03 00 01 03 00 01 03 00 00 03 67 63 63 09 01 03   ..........gcc...
|   3600: 00 01 03 00 01 03 00 01 06 65 6f 70 6f 6c 79 09   .........eopoly.
|   3616: 10 03 00 01 03 00 01 03 00 00 05 6a 73 6f 6e 31   ...........json1
|   3632: 09 13 03 00 01 03 00 01 03 00 00 04 6c 6f 61 64   ............load
|   3648: 09 1f 03 00 01 03 00 01 03 00 00 03 6d 61 78 09   ............max.
|   3664: 1c 02 00 01 02 00 01 02 00 01 05 65 6d 6f 72 79   ...........emory
|   3680: 09 1c 03 00 01 03 00 01 03 00 03 04 73 79 73 35   ............sys5
|   3696: 09 16 03 00 01 03 00 01 03 00 00 06 6e 6f 63 61   ............noca
|   3712: 73 65 3c 02 01 02 02 00 03 01 02 02 00 03 01 02   se<.............
|   3728: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3744: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
|   3760: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 00   ................
|   3776: 04 6f 6d 69 74 09 1f 02 00 01 02 00 01 02 00 00   .omit...........
|   3792: 05 72 74 72 65 65 09 19 03 00 01 03 00 01 03 00   .rtree..........
|   3808: 03 02 69 6d 3c 01 01 02 02 00 03 01 02 02 00 03   ..im<...........
|   3824: 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01   ................
|   3840: 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02   ................
|   3856: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3872: 00 00 0a 74 68 72 65 61 64 73 61 66 65 09 22 02   ...threadsafe...
|   3888: 00 01 02 00 01 02 00 00 04 76 74 61 62 09 07 04   .........vtab...
|   3904: 00 01 04 00 01 04 00 00 01 78 b4 01 01 01 01 02   .........x......
|   3920: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   3936: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   3952: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   3968: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   3984: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4000: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   4016: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   4032: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   4048: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   4064: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4080: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
| page 6 offset 20480
|      0: 0a 00 00 00 02 0f f5 00 0f fb 0f f5 00 00 00 00   ................
|   4080: 00 00 00 00 00 05 04 08 09 01 02 04 04 08 08 09   ................
| page 7 offset 24576
|      0: 0d 00 00 00 05 0f b8 00 0f f4 0f e9 10 d6 0f c7   ................
|     16: 0f b8 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   4016: 00 00 00 00 00 00 00 00 0d 05 02 23 61 75 74 6f   ...........#auto
|   4032: 6d 65 72 67 65 3d 35 0d 04 02 23 6d 65 72 67 65   merge=5...#merge
|   4048: 3d 31 30 30 2c 38 11 03 02 2b 69 6e 74 65 67 72   =100,8...+integr
|   4064: 69 74 79 2d 63 68 65 63 6b 09 02 02 1b 72 65 62   ity-check....reb
|   4080: 75 69 6c 64 0a 01 02 1d 6f 70 74 69 6d 69 7a 65   uild....optimize
| end crash-f15972acf5bc1c.db
}]} {}

do_execsql_test 17.1 {
  BEGIN;
    INSERT INTO t1(t1) SELECT x FROM t2;
    UPDATE t1 SET b=quote(zeroblob(200)) WHERE a MATCH 'thread*';
}

do_catchsql_test 17.2 {
  DROP TABLE IF EXISTS t1;
} {1 {SQL logic error}}

do_execsql_test 17.3 {
  INSERT INTO t1(t1) VALUES('optimize');
}

do_catchsql_test 17.4 {
  DROP TABLE IF EXISTS t1;
} {1 {SQL logic error}}

#-------------------------------------------------------------------------
reset_db
do_test 18.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 32768 pagesize 4096 filename crash-4ce32d0608aff1.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 02 00 00 00 01 00 00 00 07 00 00 00 04   ................
|     48: 00 00 00 00 00 00 00 07 00 00 00 01 00 00 00 00   ................
|     96: 00 00 00 00 0d 0e b1 00 06 0d a4 00 0f 8d 0f 21   ...............!
|    112: 0e b9 0d c8 0e 7e 0d a4 0d a4 00 00 00 00 00 00   .....~..........
|   3488: 00 00 00 00 22 07 06 17 11 11 01 31 74 61 62 6c   ...........1tabl
|   3504: 65 74 32 74 32 07 43 52 45 41 54 45 20 54 41 42   et2t2.CREATE TAB
|   3520: 4c 45 20 74 32 28 78 29 81 33 05 07 17 1f 1f 01   LE t2(x).3......
|   3536: 82 35 74 61 62 6c 65 74 31 5f 73 65 67 64 69 72   .5tablet1_segdir
|   3552: 74 31 5f 73 65 67 64 69 72 05 43 52 45 41 54 45   t1_segdir.CREATE
|   3568: 20 54 41 42 4c 45 20 27 74 31 5f 73 65 67 64 69    TABLE 't1_segdi
|   3584: 72 27 28 6c 65 76 65 6c 20 49 4e 54 45 47 45 52   r'(level INTEGER
|   3600: 2c 69 64 78 20 49 4e 54 45 47 45 52 2c 73 74 61   ,idx INTEGER,sta
|   3616: 72 74 5f 62 6c 6f 63 6b 20 49 4e 54 45 47 45 52   rt_block INTEGER
|   3632: 2c 6c 65 61 76 65 73 5f 65 6e 64 5f 62 6c 6f 63   ,leaves_end_bloc
|   3648: 6b 20 49 4e 54 45 47 45 52 2c 65 6e 64 5f 62 6c   k INTEGER,end_bl
|   3664: 6f 63 6b 20 49 4e 54 45 47 45 62 2c 72 6f 6f 74   ock INTEGEb,root
|   3680: 20 42 4c 4f 42 2c 50 52 49 4d 41 52 59 20 4b 45    BLOB,PRIMARY KE
|   3696: 59 28 6c 65 76 65 6c 2c 20 69 64 78 29 29 31 06   Y(level, idx))1.
|   3712: 06 17 45 1f 01 00 69 6e 64 65 78 73 71 6c 69 74   ..E...indexsqlit
|   3728: 65 5f 61 75 74 6f 69 6e 64 65 78 5f 74 31 5f 73   e_autoindex_t1_s
|   3744: 65 67 64 69 72 5f 31 74 31 5f 73 65 67 64 69 72   egdir_1t1_segdir
|   3760: 06 0f c7 00 08 00 00 00 00 66 04 07 17 23 23 01   .........f...##.
|   3776: 81 13 74 61 62 6c 65 74 31 5f 73 65 67 6d 65 6e   ..tablet1_segmen
|   3792: 74 73 74 31 5f 73 65 67 6d 65 6e 74 73 04 43 52   tst1_segments.CR
|   3808: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 73   EATE TABLE 't1_s
|   3824: 65 67 6d 65 6e 74 73 27 28 62 6c 6f 63 6b 69 64   egments'(blockid
|   3840: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59    INTEGER PRIMARY
|   3856: 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42    KEY, block BLOB
|   3872: 29 6a 03 07 17 21 21 01 81 1f 74 61 62 6c 65 74   )j...!!...tablet
|   3888: 31 5f 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74   1_contentt1_cont
|   3904: 65 6e 74 03 43 52 45 41 54 45 20 54 41 42 4c 45   ent.CREATE TABLE
|   3920: 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28 64 6f    't1_content'(do
|   3936: 63 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d   cid INTEGER PRIM
|   3952: 41 52 59 20 4b 45 59 2c 20 27 63 30 61 27 2c 20   ARY KEY, 'c0a', 
|   3968: 27 63 31 62 27 2c 20 27 63 32 63 27 29 38 02 06   'c1b', 'c2c')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 33   LE t1 USING fts3
|   4032: 28 61 2c 62 2c 63 29 00 00 00 39 00 00 00 00 00   (a,b,c)...9.....
| page 3 offset 8192
|      0: 0d 00 00 00 25 0b 48 00 0f d8 0f af 0f 86 0f 74   ....%.H........t
|     16: 0f 61 0f 4e 0f 2f 0f 0f 0e ef 0e d7 0e be 0e a5   .a.N./..........
|     32: 0e 8d 0e 74 0e 5b 0e 40 0e 24 0e 08 0d ef 0d d5   ...t.[.@.$......
|     48: 0d bb 0d a0 0d 84 0d 68 0d 4f 0d 35 0d 1b 0c fb   .......h.O.5....
|     64: 0c da 0c b9 0c 99 0c 78 0c 57 0c 3e 0c 24 0c 0a   .......x.W.>.$..
|     80: 0b 48 00 00 00 00 00 00 00 00 00 00 00 00 00 00   .H..............
|   2880: 00 00 00 00 00 00 00 00 81 3f 25 06 00 82 7f 00   .........?%.....
|   2896: 00 43 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e   .COMPILER=gcc-5.
|   2912: 34 23 00 20 32 30 31 36 30 36 30 39 20 44 45 42   4#. 20160609 DEB
|   2928: 55 47 20 45 4e 41 42 4c 45 20 44 42 53 54 41 54   UG ENABLE DBSTAT
|   2944: 20 56 54 41 42 20 45 4e 41 42 4c 45 20 46 54 53    VTAB ENABLE FTS
|   2960: 34 20 45 4e 41 42 4c 45 20 46 54 53 35 20 45 4e   4 ENABLE FTS5 EN
|   2976: 41 42 4c 45 20 47 45 4f 50 4f 4c 59 20 45 4e 41   ABLE GEOPOLY ENA
|   2992: 42 4c 45 20 4a 53 4f 4e 31 20 45 4e 41 42 4c 45   BLE JSON1 ENABLE
|   3008: 20 4d 45 4d 53 59 53 35 20 45 4e 41 42 4c 45 20    MEMSYS5 ENABLE 
|   3024: 52 54 52 45 45 20 4d 41 58 20 4d 45 4d 4f 52 59   RTREE MAX MEMORY
|   3040: 3d 35 30 30 30 30 30 30 30 20 4f 4d 49 54 20 4c   =50000000 OMIT L
|   3056: 4f 41 44 20 45 58 54 45 4e 53 49 4f 4e 20 54 48   OAD EXTENSION TH
|   3072: 52 45 41 44 53 41 46 45 3d 30 18 24 05 00 25 0f   READSAFE=0.$..%.
|   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 22   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 4f 4d   0XRTRIM.!..3..OM
|   3168: 49 54 20 4c 4f 41 44 20 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 53 49   MIT LOAD EXTENSI
|   3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17   ONXNOCASE....3..
|   3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53   OMIT LOAD EXTENS
|   3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19   IONXRTRIM....3..
|   3264: 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30   MAX MEMORY=50000
|   3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f   000XBINARY....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 33   0000XNOCASE....3
|   3328: 0f 17 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30   ..MAX MEMORY=500
|   3344: 30 30 30 30 30 58 52 54 53 49 4d 18 1b 05 00 25   00000XRTSIM....%
|   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 58 4e 4f 43 41 53 45 17   LE RTREEXNOCASE.
|   3408: 19 05 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52   ...%..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 53 35 58 52 54 52 49 4d 18 15 05 00 25   MSYS5XRTRIM....%
|   3520: 0f 19 45 4e 41 42 4c 45 20 4a 53 4f 4e 31 58 42   ..ENABLE 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 31 58 4e 4f 43 41 53 45 17   LE JSON1XNOCASE.
|   3568: 13 05 00 25 0f 17 45 4e 41 52 4c 45 20 4a 53 4f   ...%..ENARLE 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 4e 41 1e 4c   NARY....)..ENA.L
|   3632: 45 20 47 45 4f 50 4f 4c 59 58 4e 4f 43 41 53 45   E GEOPOLYXNOCASE
|   3648: 19 10 05 00 29 0f 17 45 4e 41 42 4c 45 20 47 55   ....)..ENABLE GU
|   3664: 4f 50 4f 4c 59 58 52 54 52 49 4d 17 0f 05 00 23   OPOLYXRTRIM....#
|   3680: 0f 19 45 4e 41 42 4c 45 20 46 54 53 35 58 42 49   ..ENABLE FTS5XBI
|   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 58 4e 4f 43 41 53 45 16 0d 05   E FTS5XNOCASE...
|   3728: 00 23 0f 17 45 4e 41 42 4c 45 20 46 54 59 e5 58   .#..ENABLE FTY.X
|   3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42   RTRIM....#..ENAB
|   3760: 4c 45 20 46 54 53 34 58 42 49 4e 41 52 59 17 0b   LE FTS4XBINARY..
|   3776: 05 00 23 0f 19 45 4e 41 42 4c 45 20 46 54 53 35   ..#..ENABLE FTS5
|   3792: 58 4e 4f 43 40 53 45 16 0a 05 00 23 0f 17 45 4e   XNOC@SE....#..EN
|   3808: 41 42 4c 45 20 46 54 53 34 58 52 54 52 49 4d 1e   ABLE FTS4XRTRIM.
|   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 3d 67   ...C..COMPILER=g
|   4032: 63 63 25 75 2e 34 2f 30 20 32 30 31 36 30 36 30   cc%u.4/0 2016060
|   4048: 39 58 4e 4f 43 41 53 45 26 01 05 00 43 0f 17 43   9XNOCASE&...C..C
|   4064: 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e   OMPILER=gcc-5.4.
|   4080: 30 20 32 30 31 36 30 36 30 39 58 52 54 52 49 4d   0 20160609XRTRIM
| 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 02 0b a0 00 0c ad 0b a0 00 00 00 00   ................
|   2976: 82 0a 02 08 08 09 08 08 17 84 06 30 20 32 35 33   ...........0 253
|   2992: 00 01 30 04 25 06 1b 00 00 08 32 30 31 36 30 36   ..0.%.....201606
|   3008: 30 39 03 25 07 00 00 01 34 03 25 05 00 00 01 35   09.%....4.%....5
|   3024: 03 25 04 00 01 07 30 30 30 30 30 30 30 03 25 1a   .%....0000000.%.
|   3040: 00 00 08 63 6f 6d 70 69 6c 65 72 03 25 02 00 00   ...compiler.%...
|   3056: 06 64 62 73 74 61 74 03 25 0a 00 01 04 65 62 75   .dbstat.%....ebu
|   3072: 67 03 25 08 00 00 06 65 6e 61 62 6c 65 09 25 09   g.%....enable.%.
|   3088: 05 04 04 04 04 04 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3104: 6e 03 25 1d 00 00 04 66 74 73 34 03 25 0d 00 03   n.%....fts4.%...
|   3120: 01 35 03 25 0f 00 00 03 67 63 63 03 25 03 00 01   .5.%....gcc.%...
|   3136: 06 65 6f 70 6f 6c 79 03 25 11 00 00 05 6a 73 6f   .eopoly.%....jso
|   3152: 6e 31 03 25 13 41 00 04 6c 6f 61 64 03 25 1c 00   n1.%.A..load.%..
|   3168: 00 03 6d 61 78 03 25 18 00 01 05 65 6d 6f 72 79   ..max.%....emory
|   3184: 03 25 19 00 03 04 73 79 73 35 03 25 15 00 00 04   .%....sys5.%....
|   3200: 6f 6d 69 74 03 25 1b 00 00 05 72 74 72 65 65 03   omit.%....rtree.
|   3216: 25 17 00 00 0a 74 68 72 65 61 64 73 61 56 65 03   %....threadsaVe.
|   3232: 25 1e 00 00 04 76 74 61 62 03 25 0b 00 86 50 01   %....vtab.%...P.
|   3248: 08 08 08 08 08 17 8d 12 30 20 38 33 35 00 01 30   ........0 835..0
|   3264: 12 01 06 00 01 06 00 01 06 00 1f 03 00 01 03 00   ................
|   3280: 01 03 00 00 08 32 30 31 36 30 36 30 39 09 01 07   .....20160609...
|   3296: 00 01 07 00 01 07 00 00 01 34 09 01 05 00 01 05   .........4......
|   3312: 00 01 05 00 00 01 35 09 01 04 00 01 04 00 01 04   ......5.........
|   3328: 00 01 07 30 30 30 30 30 30 30 09 1c 04 00 01 04   ...0000000......
|   3344: 00 01 04 00 00 06 62 69 6e 61 72 79 3c 03 02 02   ......binary<...
|   3360: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3376: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
|   3392: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03   ................
|   3408: 01 02 02 00 03 01 02 02 00 00 08 63 6f 6d 70 69   ...........compi
|   3424: 6c 65 72 09 01 02 00 01 02 00 01 02 00 00 06 64   ler............d
|   3440: 62 73 74 61 74 09 f2 03 00 01 03 00 01 03 00 01   bstat...........
|   3456: 04 65 62 75 67 09 04 02 00 01 02 00 01 02 00 00   .ebug...........
|   3472: 06 65 6e 61 62 6c 65 3f 07 02 00 01 02 00 01 02   .enable?........
|   3488: 00 01 02 00 01 02 00 01 02 00 01 02 00 57 02 00   .............W..
|   3504: 01 02 00 01 01 00 01 02 00 11 02 00 01 02 10 01   ................
|   3520: 02 00 01 02 00 01 02 00 01 02 00 01 02 00 01 02   ................
|   3536: 00 01 02 00 01 02 00 01 08 78 74 64 6e 73 69 6f   .........xtdnsio
|   3552: 6e 09 1f 04 00 01 04 00 01 03 00 00 04 66 74 73   n............fts
|   3568: 34 09 0a 03 00 01 03 00 01 03 00 03 01 35 09 0d   4............5..
|   3584: 03 00 01 03 00 01 03 00 00 03 57 63 63 09 01 03   ..........Wcc...
|   3600: 00 01 03 00 01 03 00 01 06 65 6f 70 6f 6c 79 09   .........eopoly.
|   3616: 10 03 00 01 03 00 01 03 00 00 05 6a 73 6f 6e 31   ...........json1
|   3632: 09 13 03 00 01 03 00 01 03 00 00 04 6c 6f 61 64   ............load
|   3648: 09 1f 03 00 01 03 00 01 03 00 00 03 6d 61 78 09   ............max.
|   3664: 1c 02 00 01 02 00 01 02 00 01 05 65 6d 6f 72 79   ...........emory
|   3680: 09 1c 03 00 01 03 00 01 03 00 03 04 73 79 73 35   ............sys5
|   3696: 09 16 03 00 01 03 00 01 03 00 00 06 6e 6f 63 61   ............noca
|   3712: 73 65 3c 02 01 02 02 00 03 01 02 02 00 03 01 02   se<.............
|   3728: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3744: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
|   3760: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 00   ................
|   3776: 04 6f 6d 69 74 09 1f 02 00 01 02 00 01 02 00 00   .omit...........
|   3792: 05 72 74 72 65 65 09 19 03 00 01 03 00 01 03 00   .rtree..........
|   3808: 03 02 69 6d 3c 01 01 02 02 00 03 01 02 02 00 03   ..im<...........
|   3824: 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01   ................
|   3840: 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02   ................
|   3856: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3872: 00 00 0a 74 68 72 65 61 64 73 61 66 65 09 22 02   ...threadsafe...
|   3888: 00 01 02 00 02 02 00 00 04 76 74 61 62 09 07 04   .........vtab...
|   3904: 00 01 04 00 01 04 00 00 01 78 b4 01 01 01 01 02   .........x......
|   3920: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   3936: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   3952: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   3968: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   3984: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4000: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   4016: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   4032: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   4048: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   4064: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4080: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
| page 6 offset 20480
|      0: 0a 00 00 00 02 0f f5 00 0f fb 0f f5 00 00 00 00   ................
|   4080: 00 00 00 00 00 05 04 08 09 01 02 04 04 08 08 09   ................
| page 7 offset 24576
|      0: 0d 00 00 00 05 0f b8 00 0f f4 0f e9 0f d6 0f c7   ................
|     16: 0f b8 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   4064: 00 00 00 00 00 0d 05 02 23 61 75 74 6f 6d 65 72   ........#automer
|   4080: 67 65 3d 35 0d 04 02 23 6d 65 72 67 65 3d 31 30   ge=5...#merge=10
| page 8 offset 28672
|      0: 30 2c 38 11 03 02 2b 69 6e 74 65 67 72 69 74 79   0,8...+integrity
|     16: 2d 63 68 65 63 6b 09 02 02 1b 72 65 62 75 69 6c   -check....rebuil
|     32: 64 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 00 00 00   d....optimize...
| end crash-4ce32d0608aff1.db
}]} {}

do_catchsql_test 18.1 {
  SELECT quote(matchinfo(t1,'pcxybs'))==0 FROM t1 WHERE b MATCH 'e*';
} {0 {}}

#-------------------------------------------------------------------------
reset_db
do_test 19.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 28672 pagesize 4096 filename crash-526ea445f41c02.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 02 00 00 00 01 00 00 00 07 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 0e b1 00 06 0d a4 00 0f 8d 0f 21   ...............!
|    112: 0e b9 0d c8 0e 7e 0d a4 00 00 00 00 00 00 00 00   .....~..........
|   3488: 00 00 00 00 22 07 06 17 11 11 01 31 74 61 62 6c   ...........1tabl
|   3504: 65 74 32 74 32 07 43 52 45 41 54 45 20 54 41 42   et2t2.CREATE TAB
|   3520: 4c 45 20 74 32 28 78 29 81 33 05 07 17 1f 1f 01   LE t2(x).3......
|   3536: 82 35 74 61 62 6c 65 74 31 5f 73 65 67 64 69 72   .5tablet1_segdir
|   3552: 74 31 5f 73 65 67 64 69 72 05 43 52 45 41 54 45   t1_segdir.CREATE
|   3568: 20 54 41 42 4c 45 20 27 74 31 5f 73 65 67 64 69    TABLE 't1_segdi
|   3584: 72 27 28 6c 65 76 65 6c 20 49 4e 54 45 47 45 52   r'(level INTEGER
|   3600: 2c 69 64 78 20 49 4e 54 45 47 45 52 2c 73 74 61   ,idx INTEGER,sta
|   3616: 72 74 5f 62 6c 6f 63 6b 20 49 4e 54 45 47 45 52   rt_block INTEGER
|   3632: 2c 6c 65 61 76 65 73 5f 65 6e 64 5f 62 6c 6f 63   ,leaves_end_bloc
|   3648: 6b 20 49 4e 54 45 47 45 52 2c 65 6e 64 5f 62 6c   k INTEGER,end_bl
|   3664: 6f 63 6b 20 49 4e 54 45 47 45 52 2c 72 6f 6f 74   ock INTEGER,root
|   3680: 20 42 4c 4f 42 2c 50 52 49 4d 41 52 59 20 4b 45    BLOB,PRIMARY KE
|   3696: 59 28 6c 65 76 65 6c 2c 20 69 64 78 29 29 31 06   Y(level, idx))1.
|   3712: 06 17 45 1f 01 00 69 6e 64 65 78 73 71 6c 69 74   ..E...indexsqlit
|   3728: 65 5f 61 75 74 6f 69 6e 64 65 78 5f 74 31 5f 73   e_autoindex_t1_s
|   3744: 65 67 64 69 72 5f 31 74 31 5f 73 65 67 64 69 72   egdir_1t1_segdir
|   3760: 06 0f c7 00 08 00 00 00 00 66 04 07 17 23 23 01   .........f...##.
|   3776: 81 13 74 61 62 6c 65 74 31 5f 73 65 67 6d 65 6e   ..tablet1_segmen
|   3792: 74 73 74 31 5f 73 65 67 6d 65 6e 74 73 04 43 52   tst1_segments.CR
|   3808: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 73   EATE TABLE 't1_s
|   3824: 65 67 6d 65 6e 74 73 27 28 62 6c 6f 63 6b 69 64   egments'(blockid
|   3840: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59    INTEGER PRIMARY
|   3856: 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42    KEY, block BLOB
|   3872: 29 6a 03 07 17 21 21 01 81 1f 74 61 62 6c 65 74   )j...!!...tablet
|   3888: 31 5f 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74   1_contentt1_cont
|   3904: 65 6e 74 03 43 52 45 41 54 45 20 54 41 42 4c 45   ent.CREATE TABLE
|   3920: 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28 64 6f    't1_content'(do
|   3936: 63 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d   cid INTEGER PRIM
|   3952: 41 52 59 20 4b 45 59 2c 20 27 63 30 61 27 2c 20   ARY KEY, 'c0a', 
|   3968: 27 63 31 62 27 2c 20 27 63 32 63 27 29 38 02 06   'c1b', 'c2c')8..
|   3984: 17 11 11 08 5f 74 61 62 6c 65 74 31 74 41 43 52   ...._tablet1tACR
|   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 33   LE t1 USING fts3
|   4032: 28 61 2c 62 2c 63 29 00 00 00 39 00 00 00 00 00   (a,b,c)...9.....
| page 3 offset 8192
|      0: 0d 00 00 00 25 0b 48 00 0f d8 0f af 0f 86 0f 74   ....%.H........t
|     16: 0f 61 0f 4e 0f 2f 0f 0f 0e ef 0e d7 0e be 0e a5   .a.N./..........
|     32: 0e 8d 0e 74 0e 5b 0e 40 0e 24 0e 08 0d ef 0d d5   ...t.[.@.$......
|     48: 0d bb 0d a0 0d 84 0d 68 0d 4f 0d 35 0d 1b 0c fb   .......h.O.5....
|     64: 0c da 0c b9 0c 99 0c 78 0c 57 0c 3e 0c 24 0c 0a   .......x.W.>.$..
|     80: 0b 48 00 00 00 00 00 00 00 00 00 00 00 00 00 00   .H..............
|   2880: 00 00 00 00 00 00 00 00 81 3f 25 06 00 82 7f 00   .........?%.....
|   2896: 00 43 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2f   .COMPILER=gcc-5/
|   2912: 34 2e 30 20 32 30 31 36 30 36 30 39 20 44 45 42   4.0 20160609 DEB
|   2928: 55 47 20 45 4e 41 42 4c 45 20 44 42 53 54 41 54   UG ENABLE DBSTAT
|   2944: 20 56 54 41 42 20 45 4e 41 42 4c 45 20 46 54 53    VTAB ENABLE FTS
|   2960: 34 20 45 4e 41 42 4c 45 20 46 54 53 35 20 45 4e   4 ENABLE FTS5 EN
|   2976: 41 42 4c 45 20 47 45 4f 50 4f 4c 59 20 45 4e 41   ABLE GEOPOLY ENA
|   2992: 42 4c 45 20 4a 53 4f 4e 31 20 45 4e 41 42 4c 45   BLE JSON1 ENABLE
|   3008: 20 4d 45 4d 53 59 53 35 20 45 4e 41 42 4c 45 20    MEMSYS5 ENABLE 
|   3024: 52 54 52 45 45 20 4d 41 58 20 4d 45 4d 4f 52 59   RTREE MAX MEMORY
|   3040: 3d 35 30 30 30 30 30 30 30 20 4f 4d 49 54 20 4c   =50000000 OMIT L
|   3056: 4f 41 44 20 45 58 54 45 4e 53 49 4f 4e 20 54 48   OAD EXTENSION TH
|   3072: 52 45 41 44 53 41 46 45 3d 30 18 24 05 00 25 0f   READSAFE=0.$..%.
|   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 22   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 4f 4d   0XRTRIM.!..3..OM
|   3168: 49 54 20 4c 4f 41 44 20 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 53 49   MIT LOAD EXTENSI
|   3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17   ONXNOCASE....3..
|   3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53   OMIT LOAD EXTENS
|   3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19   IONXRTRIM....3..
|   3264: 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30   MAX MEMORY=50000
|   3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f   000XBINARY....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 33   0000XNOCASE....3
|   3328: 0f 17 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30   ..MAX 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 58 4e 4f 43 41 53 45 17   LE RTREEXNOCASE.
|   3408: 19 05 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52   ...%..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 53 35 58 52 54 52 49 4d 18 15 05 00 25   MSYS5XRTRIM....%
|   3520: 0f 19 45 4e 41 42 4c 45 20 4a 53 4f 4e 31 58 42   ..ENABLE 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 31 58 4e 4f 43 41 53 45 17   LE JSON1XNOCASE.
|   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 4e 41 42 4c   NARY....)..ENABL
|   3632: 45 20 47 45 4f 50 4f 4c 59 58 4e 4f 43 41 53 45   E GEOPOLYXNOCASE
|   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 19 45 4e 41 42 4c 45 20 46 54 53 35 58 42 49   ..ENABLE FTS5XBI
|   3696: 4f 41 52 59 17 0e 05 00 23 0f 19 45 4e 41 42 4c   OARY....#..ENABL
|   3712: 45 20 46 54 53 35 58 4e 4f 43 41 53 45 16 0d 05   E FTS5XNOCASE...
|   3728: 00 23 0f 17 45 4e 41 42 4c 45 20 46 54 53 35 58   .#..ENABLE FTS5X
|   3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42   RTRIM....#..ENAB
|   3760: 4c 45 20 46 54 53 34 58 42 49 4e 41 52 59 17 0b   LE FTS4XBINARY..
|   3776: 05 00 23 0f 19 45 4e 41 42 4d f5 20 46 54 53 34   ..#..ENABM. FTS4
|   3792: 58 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 45 4e   XNOCASE....#..EN
|   3808: 41 52 4c 45 20 46 54 53 34 58 52 54 52 49 4d 1e   ARLE FTS4XRTRIM.
|   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 04 00 43 0f 19 43 4f 4d 50 49 4c 45 52 3d 67   ...C..COMPILER=g
|   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 43   9XNOCASE&...C..C
|   4064: 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e   OMPILER=gcc-5.4.
|   4080: 30 20 32 30 31 36 30 36 30 39 58 52 54 52 49 4d   0 20160609XRTRIM
| page 4 offset 12288
|      0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
| page 5 offset 16384
|      0: 0d 00 00 00 02 0b a0 00 0c ad 0b a0 00 00 00 00   ................
|   2976: 82 0a 02 08 08 09 08 08 17 84 06 30 20 32 35 33   ...........0 253
|   2992: 00 01 30 04 25 06 1b 00 00 08 32 30 31 36 30 36   ..0.%.....201606
|   3008: 30 39 03 25 07 00 00 01 34 03 25 05 00 00 01 35   09.%....4.%....5
|   3024: 03 25 04 00 01 07 30 30 30 30 30 30 30 03 25 1a   .%....0000000.%.
|   3040: 00 00 08 63 6f 6d 70 69 6c 65 72 03 25 02 00 00   ...compiler.%...
|   3056: 06 64 62 73 74 61 74 03 25 0a 00 01 04 65 62 75   .dbstat.%....ebu
|   3072: 67 03 25 08 00 00 06 65 6e 61 62 6c 65 09 25 09   g.%....enable.%.
|   3088: 05 04 04 04 04 04 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3104: 6e 03 25 1d 00 00 04 66 74 73 34 03 25 0d 00 03   n.%....fts4.%...
|   3120: 01 35 03 25 0f 00 00 03 67 63 63 03 25 03 00 01   .5.%....gcc.%...
|   3136: 06 65 6f 70 6f 6c 79 03 25 11 00 00 05 6a 73 6f   .eopoly.%....jso
|   3152: 6e 31 03 25 13 00 00 04 6c 6f 61 64 03 25 1c 00   n1.%....load.%..
|   3168: 00 03 6d 61 78 03 25 18 00 01 05 65 6d 6f 72 79   ..max.%....emory
|   3184: 03 25 19 00 03 04 73 79 73 35 03 25 15 00 00 04   .%....sys5.%....
|   3200: 6f 6d 69 74 03 25 1b 00 00 05 72 74 72 65 65 03   omit.%....rtree.
|   3216: 25 17 00 00 0a 74 68 72 65 61 64 73 61 66 65 03   %....threadsafe.
|   3232: 25 1e 00 00 04 76 74 61 62 03 25 0b 00 86 50 01   %....vtab.%...P.
|   3248: 08 08 08 08 08 17 8d 12 30 20 38 33 35 00 01 30   ........0 835..0
|   3264: 12 01 06 00 01 06 00 01 06 00 1f 03 00 01 03 00   ................
|   3280: 01 03 00 00 08 32 30 31 36 30 36 30 39 09 01 07   .....20160609...
|   3296: 00 01 07 00 01 07 00 00 01 34 09 01 05 00 01 05   .........4......
|   3312: 00 01 05 00 00 01 35 09 01 04 00 01 04 00 01 04   ......5.........
|   3328: 00 01 07 30 30 30 30 30 30 30 09 1c 04 00 01 04   ...0000000......
|   3344: 00 01 04 00 00 06 62 69 6e 61 72 79 3c 03 01 02   ......binary<...
|   3360: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3376: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
|   3392: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03   ................
|   3408: 01 02 02 00 03 01 02 02 00 00 08 63 6f 6d 70 69   ...........compi
|   3424: 6c 65 72 09 01 02 00 01 02 00 01 02 00 00 06 64   ler............d
|   3440: 62 73 74 61 74 09 07 03 00 01 03 00 01 03 00 01   bstat...........
|   3456: 04 65 62 75 67 09 04 02 00 01 02 00 01 02 00 00   .ebug...........
|   3472: 06 65 6e 61 62 6c 65 3f 07 02 00 01 02 00 01 02   .enable?........
|   3488: 00 01 02 00 01 02 00 01 02 00 01 02 00 01 02 00   ................
|   3504: 01 02 00 01 02 00 01 02 00 01 02 00 01 02 00 01   ................
|   3520: 02 00 01 02 00 01 02 00 01 02 00 01 02 00 01 02   ................
|   3536: 00 01 02 00 01 02 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3552: 6e 09 1f 04 00 01 04 00 01 04 00 00 04 66 74 73   n............fts
|   3568: 34 09 0a 03 00 01 03 00 01 03 00 03 01 35 09 0d   4............5..
|   3584: 03 00 01 03 00 01 03 00 00 03 67 63 63 09 01 03   ..........gcc...
|   3600: 00 01 03 00 01 03 00 01 06 65 6f 70 6f 6c 79 09   .........eopoly.
|   3616: 10 03 00 01 03 00 01 03 00 00 05 6a 73 6f 6e 31   ...........json1
|   3632: 09 13 03 00 01 03 00 01 03 00 00 04 6c 6f 61 64   ............load
|   3648: 09 1f 03 00 01 03 00 01 03 00 00 03 6d 61 78 09   ............max.
|   3664: 1c 02 00 01 02 00 01 02 00 01 05 65 6d 6f 72 79   ...........emory
|   3680: 09 1c 03 00 01 03 00 01 03 00 03 04 73 79 73 35   ............sys5
|   3696: 09 16 03 00 01 03 00 01 03 00 00 06 6e 6f 63 61   ............noca
|   3712: 73 65 3c 02 01 02 02 00 03 01 02 02 00 03 01 02   se<.............
|   3728: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3744: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
|   3760: 03 01 02 02 00 13 01 02 02 00 03 01 02 02 00 00   ................
|   3776: 04 6f 6d 69 74 09 1f 02 00 01 12 00 01 02 00 00   .omit...........
|   3792: 05 72 74 72 65 65 09 19 03 00 01 81 00 01 03 00   .rtree..........
|   3808: 03 02 69 6d 3c 01 01 02 02 00 03 01 02 02 00 03   ..im<...........
|   3824: 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01   ................
|   3840: 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02   ................
|   3856: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3872: 00 00 0a 74 68 72 65 61 64 73 61 66 65 09 22 02   ...threadsafe...
|   3888: 00 01 02 00 01 02 00 00 04 76 74 61 62 09 07 04   .........vtab...
|   3904: 00 01 04 00 01 04 00 00 01 78 b4 01 01 01 01 02   .........x......
|   3920: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   3936: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   3952: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   3968: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   3984: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4000: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   4016: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   4032: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   4048: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   4064: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4080: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
| page 6 offset 20480
|      0: 0a 00 00 00 02 0f f5 00 0f fb 0f f5 00 00 00 00   ................
|   4080: 00 00 00 00 00 05 04 08 09 01 02 04 04 08 08 09   ................
| page 7 offset 24576
|      0: 0d 00 00 00 05 0f b8 00 0f f4 0f e9 0f d6 0f c7   ................
|     16: 0f b8 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   4016: 00 00 00 00 00 00 00 00 0d 05 02 23 61 75 74 6f   ...........#auto
|   4032: 6d 65 72 67 65 3d 35 0d 04 02 23 6d 65 72 67 65   merge=5...#merge
|   4048: 3d 31 30 30 2c 38 11 03 02 2b 69 6e 74 65 67 72   =100,8...+integr
|   4064: 69 74 79 2d 63 68 65 63 6b 09 02 02 1b 72 65 62   ity-check....reb
|   4080: 75 69 6c 64 0a 01 02 1d 6f 70 74 69 6d 69 7a 65   uild....optimize
| end crash-526ea445f41c02.db
}]} {}

do_catchsql_test 19.1 {
  PRAGMA writable_schema = 1;
  SELECT rowid,a,c,snippet(t1,85101090932165,-1,10) FROM t1 WHERE a MATCH 'rtree';
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
reset_db
do_test 20.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
.open --hexdb
| size 28672 pagesize 4096 filename crash-afecd03c862e58.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 01 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 30 4b 45 59 2c 20 73 69 7a 65   RIMARY0KEY, 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 25 04 43 52 45 41 54 45 20 54   _segdi%.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 4d 54 45 47 45 52 2c 65 6e 64 5f 62 6c 6f 63   IMTEGER,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 50 52 49 4d 41 52 59 20 4b   NTEGER PRIMARY 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 31 2c 32 27 29   (a,prefix='1,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 63 0e 1f 00 00 00 00 00 00 00 00   .....c..........
|   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 68 20 6f 66 66 69 63 69 61 20 64   pa quh 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 01 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 43 05 04 00 81 09 44 75 69 73 20 61 75   ur.C.....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 14 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 63 20 6d 69 6e 69 6d 20 76 65 6e 69 61   m ac 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 6c 69 74    adipiscing elit
| page 3 offset 8192
|      0: 0d 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00   ................
| 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 01 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 13 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: 03 05 00 00 02 72 bc 03 03 0a 00 01 01 74 09 02   .....r.......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 02 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 f0 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 08 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 21 36 36 35 00 02 61 64 03 03 04 00 02   .>0!665..ad.....
|   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 75 72 03 01   .....nsectetur..
|   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 41 72 65 68 65 6e 64 65 72 69   ....reArehenderi
|   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 70 6c 75 70 74 61 74 65 03 05 09 00   ....pluptate....
| 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 0a 98 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 00 00 00 00 00 00 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 00 00   ................
|   4080: 00 00 00 00 00 00 00 07 00 03 00 14 08 45 b5 03   .............E..
| end crash-afecd03c862e58.db
}]} {}

do_execsql_test 20.1 {
  PRAGMA writable_schema = 1;
  BEGIN;
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<10)
    INSERT INTO t1(a) SELECT randomblob(3000) FROM c;
}

do_execsql_test 20.2 {
  INSERT INTO t1(t1) VALUES('optimize');
} 

#-------------------------------------------------------------------------
reset_db
do_test 21.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 28672 pagesize 4096 filename crash-18cc014e42e828.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 02 00 00 00 01 00 00 00 07 00 00 00 04   ................
|     96: 00 00 00 00 0d 0e b1 00 06 0d a4 00 0f 8d 0f 21   ...............!
|    112: 0e b9 0d c8 0e 7e 0d a4 00 00 00 00 00 00 00 00   .....~..........
|   3488: 00 00 00 00 22 07 06 17 11 11 01 31 74 61 62 6c   ...........1tabl
|   3504: 66 74 32 74 32 07 43 52 45 41 54 45 20 54 41 42   ft2t2.CREATE TAB
|   3520: 4c 45 20 74 32 28 78 29 81 33 05 07 17 1f 1f 01   LE t2(x).3......
|   3536: 82 35 74 61 62 6c 65 74 31 5f 73 75 67 64 69 72   .5tablet1_sugdir
|   3552: 74 31 5f 73 65 67 64 69 72 05 43 52 45 41 54 45   t1_segdir.CREATE
|   3568: 20 54 41 42 4c 45 20 27 74 31 5f 73 65 67 64 69    TABLE 't1_segdi
|   3584: 72 27 28 6c 65 76 65 6c 20 49 4e 54 45 47 45 52   r'(level INTEGER
|   3600: 2c 69 64 78 20 49 4e 54 45 47 45 52 2c 73 74 61   ,idx INTEGER,sta
|   3616: 72 74 5f 62 6c 6f 63 6b 20 49 4e 54 46 47 45 52   rt_block INTFGER
|   3632: 2c 6c 65 61 76 65 73 5f 65 6e 64 5f 62 6c 6f 63   ,leaves_end_bloc
|   3648: 6b 20 49 4e 54 45 47 45 52 2c 65 6e 64 5f 62 6c   k INTEGER,end_bl
|   3664: 6f 63 6b 20 49 4e 54 45 47 45 62 2c 72 6f 6f 74   ock INTEGEb,root
|   3680: 20 42 4c 4f 42 2c 50 52 49 4d 41 52 59 20 4b 45    BLOB,PRIMARY KE
|   3696: 59 28 6c 65 76 65 6c 2c 20 69 64 78 29 29 31 06   Y(level, idx))1.
|   3712: 06 17 45 1f 01 00 69 6e 64 65 78 73 71 6c 69 74   ..E...indexsqlit
|   3728: 65 5f 61 75 74 6f 69 6e 64 65 78 5f 74 31 5f 73   e_autoindex_t1_s
|   3744: 65 67 64 69 72 5f 31 74 31 5f 73 65 67 64 69 72   egdir_1t1_segdir
|   3760: 06 0f c7 00 08 00 00 00 00 66 04 07 17 23 23 01   .........f...##.
|   3776: 81 13 74 61 62 6c 65 74 31 5f 73 65 67 6d 65 6e   ..tablet1_segmen
|   3792: 74 73 74 31 5f 73 65 67 6d 65 6e 74 73 04 43 52   tst1_segments.CR
|   3808: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 73   EATE TABLE 't1_s
|   3824: 65 67 6d 65 6e 74 73 27 28 62 6c 6f 63 6b 69 64   egments'(blockid
|   3840: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59    INTEGER PRIMARY
|   3856: 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42    KEY, block BLOB
|   3872: 29 6a 03 07 17 21 21 01 81 1f 74 61 62 6c 65 74   )j...!!...tablet
|   3888: 31 5f 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74   1_contentt1_cont
|   3904: 65 6e 74 03 43 52 45 41 54 45 20 54 41 42 4c 45   ent.CREATE TABLE
|   3920: 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28 64 6f    't1_content'(do
|   3936: 63 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d   cid INTEGER PRIM
|   3952: 41 52 59 20 4b 45 59 2c 20 27 63 30 61 27 2c 20   ARY KEY, 'c0a', 
|   3968: 27 63 31 62 27 2c 20 27 63 32 63 27 29 38 02 06   'c1b', 'c2c')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 33   LE t1 USING fts3
|   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 25 0b 48 00 0f d8 0f af 0f 86 0f 74   ....%.H........t
|     16: 0f 61 0f 4e 0f 2f 0f 0f 0e ef 0e d7 0e be 0e a5   .a.N./..........
|     32: 0e 8d 0e 74 0e 5b 0e 40 0e 24 0e 08 0d ef 0d d5   ...t.[.@.$......
|     48: 0d bb 0d a0 0d 84 0d 68 0d 4e 0d 35 0d 1b 0c fb   .......h.N.5....
|     64: 0c da 0c b9 0c 99 0c 78 0c 57 0c 3e 0c 24 00 00   .......x.W.>.$..
|   2880: 00 00 00 00 00 00 00 00 81 3f 25 06 00 82 7f 00   .........?%.....
|   2896: 00 43 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e   .COMPILER=gcc-5.
|   2912: 34 23 00 20 32 30 31 36 30 36 30 39 20 44 45 42   4#. 20160609 DEB
|   2928: 55 47 20 45 4e 41 42 4c 45 20 44 42 53 54 41 54   UG ENABLE DBSTAT
|   2944: 20 56 54 41 42 20 45 4e 41 42 4c 45 20 46 43 53    VTAB ENABLE FCS
|   2960: 34 20 45 4e 41 42 4c 45 20 46 54 53 35 20 45 4e   4 ENABLE FTS5 EN
|   2976: 41 42 4c 45 20 47 45 4f 50 4f 4c 59 20 45 4e 41   ABLE GEOPOLY ENA
|   2992: 42 4c 45 20 4a 53 4f 4e 31 20 45 4e 41 42 4c 45   BLE JSON1 ENABLE
|   3008: 20 4d 45 4d 53 59 53 35 20 45 4e 41 42 4c 45 20    MEMSYS5 ENABLE 
|   3024: 52 54 52 45 45 20 4d 41 58 20 4d 45 4d 4f 52 59   RTREE MAX MEMORY
|   3040: 3d 35 30 30 30 30 30 30 30 20 4f 4d 49 54 20 4c   =50000000 OMIT L
|   3056: 4f 41 44 20 45 58 54 45 4e 53 49 4f 4e 20 54 48   OAD EXTENSION TH
|   3072: 52 45 41 44 53 41 46 45 3d 30 18 24 05 00 25 0f   READSAFE=0.$..%.
|   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 22   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 20 21 05 00 33 0f 19 4f 4d   0XRTRIM !..3..OM
|   3168: 49 54 20 4c 4f 41 44 20 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 53 49   MIT LOAD EXTENSI
|   3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17   ONXNOCASE....3..
|   3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53   OMIT LOAD EXTENS
|   3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19   IONXRTRIM....3..
|   3264: 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30   MAX MEMORY=50000
|   3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f   000XBINARY....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 33   0000XNOCASE....3
|   3328: 0f 17 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30   ..MAX 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 58 4e 4f 43 41 53 45 17   LE RTREEXNOCASE.
|   3408: 19 05 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52   ...%..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 53 35 58 52 54 52 49 4d 18 15 05 00 25   MSYS5XRTRIM....%
|   3520: 0f 19 45 4e 41 42 4c 45 20 4a 53 4f 4e 31 58 42   ..ENABLE 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 31 58 4e 4f 43 41 53 45 17   LE JSON1XNOCASE.
|   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 39   NABLE GEOPOLYXB9
|   3616: 4e 41 52 59 1a 11 05 00 29 0f 19 45 4e 41 1e 4c   NARY....)..ENA.L
|   3632: 45 20 47 45 4f 50 4f 4c 59 58 4e 4f 43 41 53 45   E GEOPOLYXNOCASE
|   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 19 45 4e 41 42 4c 45 20 46 54 53 35 58 42 49   ..ENABLE FTS5XBI
|   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 58 4e 4f 43 41 53 45 16 0d 05   E FTS5XNOCASE...
|   3728: 00 23 0f 16 45 4e 41 42 4c 45 20 46 54 53 35 58   .#..ENABLE FTS5X
|   3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42   RTRIM....#..ENAB
|   3760: 4c 45 20 46 54 53 34 58 42 48 4e 41 52 59 17 0b   LE FTS4XBHNARY..
|   3776: 05 00 23 0e 19 45 4e 41 42 4c 45 20 46 54 53 35   ..#..ENABLE FTS5
|   3792: 58 4e 4f 43 40 53 45 16 0a 05 00 23 0f 17 45 4e   XNOC@SE....#..EN
|   3808: 41 42 4c 45 20 46 54 53 34 58 52 2e 52 49 4d 1e   ABLE FTS4XR.RIM.
|   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 da 41 52 59 27   20160609XBI.ARY'
|   4016: 02 05 00 43 0f 19 43 4f 4d 50 49 4c 45 52 3d 67   ...C..COMPILER=g
|   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 43   9XNOCASE&...C..C
|   4064: 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 00 00 00 00   OMPILER=gcc-....
| page 5 offset 16384
|      0: 0d 00 00 00 02 0b a0 00 0c ad 0b a0 00 00 00 00   ................
|   2976: 82 0a 02 08 08 09 08 08 17 84 06 30 20 32 35 33   ...........0 253
|   2992: 00 01 30 04 25 06 1b 00 00 08 32 30 31 36 30 36   ..0.%.....201606
|   3008: 30 3a 03 25 07 00 00 01 34 03 25 05 00 00 01 35   0:.%....4.%....5
|   3024: 03 25 04 00 01 07 30 30 30 30 30 30 30 03 25 1a   .%....0000000.%.
|   3040: 00 00 08 63 6f 6d 70 69 6c 65 72 03 25 02 00 00   ...compiler.%...
|   3056: 06 64 62 73 74 61 74 03 25 0a 00 01 04 65 62 75   .dbstat.%....ebu
|   3072: 67 03 25 08 00 00 06 65 6e 61 62 6c 65 09 25 09   g.%....enable.%.
|   3088: 05 04 04 04 04 04 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3104: 6e 03 25 1d 00 00 04 66 74 73 34 03 25 0d 00 03   n.%....fts4.%...
|   3120: 01 35 03 25 0f 00 00 03 57 63 63 03 25 03 00 01   .5.%....Wcc.%...
|   3136: 06 65 6f 70 6f 6c 79 03 25 11 00 00 05 6a 73 6f   .eopoly.%....jso
|   3152: 6e 31 03 25 13 00 00 04 6c 6f 61 64 03 25 1c 00   n1.%....load.%..
|   3168: 00 03 6d 61 78 03 25 18 00 01 05 65 6d 6f 72 79   ..max.%....emory
|   3184: 03 25 19 00 03 04 73 79 73 35 03 25 15 00 00 04   .%....sys5.%....
|   3200: 6f 6d 69 74 03 25 1b 00 00 05 72 74 72 65 65 03   omit.%....rtree.
|   3216: 25 17 00 00 0a 74 68 72 65 64 64 73 61 66 65 03   %....threddsafe.
|   3232: 25 1e 00 00 04 76 74 61 62 03 25 0b 00 86 50 01   %....vtab.%...P.
|   3248: 08 08 08 08 08 17 8d 12 30 20 38 33 35 00 01 30   ........0 835..0
|   3264: 12 01 06 00 01 06 00 01 06 00 1f 03 00 01 03 00   ................
|   3280: 01 03 00 00 08 32 30 31 36 30 36 30 39 09 01 07   .....20160609...
|   3296: 00 01 07 00 01 07 00 00 01 34 09 01 05 00 01 05   .........4......
|   3312: 00 01 05 00 00 01 35 09 01 04 00 01 04 00 01 04   ......5.........
|   3328: 00 01 07 30 30 30 30 30 30 30 09 1c 04 00 01 04   ...0000000......
|   3344: 00 01 04 00 00 06 62 69 6e 61 72 79 3c 03 01 02   ......binary<...
|   3360: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3376: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
|   3392: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03   ................
|   3408: 01 02 02 00 03 01 02 02 00 00 08 63 6f 6d 70 69   ...........compi
|   3424: 6c 65 72 09 01 02 00 01 02 00 01 02 00 00 06 64   ler............d
|   3440: 62 73 74 61 74 09 07 03 00 01 03 00 01 03 00 01   bstat...........
|   3456: 04 65 62 75 67 09 04 02 00 01 02 00 01 02 00 00   .ebug...........
|   3472: 06 65 6e 61 62 6c 65 3f 07 02 00 01 02 00 01 12   .enable?........
|   3488: 00 01 02 00 01 02 00 01 02 00 01 02 0e 97 02 00   ................
|   3504: 01 02 00 01 cb 00 01 02 00 01 02 00 01 02 10 01   ................
|   3520: 02 00 01 02 00 01 02 01 01 02 00 01 02 00 01 02   ................
|   3536: 00 01 02 00 01 02 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3552: 6e 09 1f 04 00 01 04 00 01 04 00 00 04 66 74 73   n............fts
|   3568: 34 09 0a 03 00 01 03 00 01 03 00 03 01 35 09 0d   4............5..
|   3584: 03 00 01 03 00 01 03 00 00 03 67 63 63 09 01 03   ..........gcc...
|   3600: 00 01 03 00 01 03 00 01 06 65 6f 70 6f 6c 79 09   .........eopoly.
|   3616: 10 03 00 01 03 00 01 03 00 00 05 6a 73 6f 6e 31   ...........json1
|   3632: 09 13 03 00 01 03 00 01 03 00 00 04 6c 6f 61 64   ............load
|   3648: 09 1f 03 00 01 03 00 01 03 00 00 03 6d 61 78 09   ............max.
|   3664: 1c 02 00 01 02 00 01 02 00 01 05 65 6d 6f 72 79   ...........emory
|   3680: 09 1c 03 00 01 03 00 01 03 00 03 04 73 79 73 35   ............sys5
|   3696: 09 16 03 00 01 03 00 01 03 00 00 06 6e 6f 63 61   ............noca
|   3712: 73 65 3c 02 01 02 02 00 03 01 02 02 00 03 01 02   se<.............
|   3728: 02 00 03 01 02 02 00 03 01 02 02 00 ab 01 02 02   ................
|   3744: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
|   3760: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 00   ................
|   3776: 04 6f 6d 69 74 09 1f 12 00 01 02 00 01 02 00 00   .omit...........
|   3792: 05 72 74 72 65 65 09 19 03 00 01 03 00 01 03 00   .rtree..........
|   3808: 03 02 69 6d 3c 01 01 02 02 00 03 01 02 02 00 03   ..im<...........
|   3824: 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01   ................
|   3840: 02 02 00 03 01 02 01 f0 03 01 02 02 00 03 01 02   ................
|   3856: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3872: 00 00 0a 74 68 72 65 61 64 73 61 66 65 09 22 02   ...threadsafe...
|   3888: 00 01 02 00 02 02 00 00 04 76 74 61 62 09 07 04   .........vtab...
|   3904: 00 01 04 00 01 04 00 00 01 78 b4 01 01 01 08 a2   .........x......
|   3920: 00 01 01 01 02 00 01 01 01 02 00 02 01 01 02 00   ................
|   3936: 01 01 01 01 ff f1 01 01 02 00 01 01 01 02 00 01   ................
|   3952: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   3968: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   3984: 02 00 01 01 01 02 00 01 01 01 02 01 01 01 01 02   ................
|   4000: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   4016: 01 01 01 02 00 01 01 01 02 00 01 01 01 03 00 01   ................
|   4032: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   4048: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   4064: 02 00 01 01 01 02 00 01 02 01 02 00 01 01 01 02   ................
|   4080: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
| page 6 offset 20480
|      0: 0a 00 00 00 02 0f f5 00 0f fb 0f f5 00 00 00 00   ................
|   4080: 00 00 00 00 00 05 04 08 09 01 02 04 04 08 08 09   ................
| page 7 offset 24576
|      0: 0d 00 00 00 05 0f b8 00 00 00 00 00 00 00 00 00   ................
|   4016: 00 00 00 00 00 00 00 00 0d 05 02 23 61 75 74 6f   ...........#auto
|   4032: 6d 65 72 67 65 3d 35 0d 04 02 23 6d 65 72 67 65   merge=5...#merge
|   4048: 3d 31 30 30 2c 38 11 03 02 2b 69 6e 74 65 67 72   =100,8...+integr
|   4064: 69 74 79 2d 63 68 65 63 6b 09 02 02 1b 72 65 62   ity-check....reb
|   4080: 75 69 6c 64 0a 01 02 1d 00 00 00 00 00 00 00 00   uild............
| end crash-18cc014e42e828.db
}]} {}

do_catchsql_test 21.1 {
  PRAGMA writable_schema = 1;
  SELECT offsets(t1) FROM t1 WHERE t1 MATCH 'R*';
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
reset_db
do_test 22.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 28672 pagesize 4096 filename crash-b794c89d922ac9.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 02 00 00 00 01 00 00 00 07 00 00 00 00   ................
|     96: 00 00 00 00 0d 0e b1 00 06 0d a4 00 0f 8d 0f 21   ...............!
|    112: 0e b9 0d c8 0e 7e 0d a4 00 00 00 00 00 00 00 00   .....~..........
|   3488: 00 00 00 00 22 07 06 17 11 11 01 31 74 61 62 6c   ...........1tabl
|   3504: 65 74 32 74 32 07 43 52 45 41 54 45 20 54 41 42   et2t2.CREATE TAB
|   3520: 4c 45 20 74 32 28 78 29 81 33 05 07 17 1f 1f 01   LE t2(x).3......
|   3536: 82 35 74 61 61 6c 65 74 31 5f 73 65 67 64 69 72   .5taalet1_segdir
|   3552: 74 31 5f 73 65 67 64 69 72 05 43 52 45 41 54 45   t1_segdir.CREATE
|   3568: 20 54 41 42 4c 45 20 27 74 31 5f 73 65 67 64 69    TABLE 't1_segdi
|   3584: 72 27 28 6c 65 76 65 6c 20 49 4e 54 45 47 45 52   r'(level INTEGER
|   3600: 2c 69 64 78 20 49 4e 54 45 47 45 52 2c 73 74 61   ,idx INTEGER,sta
|   3616: 72 74 5f 62 6c 6f 63 6b 20 49 4e 54 45 47 45 52   rt_block INTEGER
|   3632: 2c 6c 65 61 76 65 73 5f 65 6e 64 5f 62 6c 6f 63   ,leaves_end_bloc
|   3648: 6b 20 49 4e 54 45 47 45 52 2c 65 6e 64 5f 62 6c   k INTEGER,end_bl
|   3664: 6f 63 6b 20 49 4e 54 45 47 45 52 2c 72 6f 6f 74   ock INTEGER,root
|   3680: 20 42 4c 4f 42 2c 50 52 49 4d 41 52 59 20 4b 45    BLOB,PRIMARY KE
|   3696: 59 28 6c 65 76 65 6c 2c 20 69 64 78 29 29 31 06   Y(level, idx))1.
|   3712: 06 17 45 1f 01 00 69 6e 64 65 78 73 71 6c 69 74   ..E...indexsqlit
|   3728: 65 5f 61 75 74 6f 69 6e 64 65 78 5f 74 31 5f 73   e_autoindex_t1_s
|   3744: 65 67 64 69 72 5f 31 74 31 5f 73 65 67 64 69 72   egdir_1t1_segdir
|   3760: 06 0f c7 00 08 00 00 00 00 66 04 07 17 23 23 01   .........f...##.
|   3776: 81 13 74 61 62 6c 65 74 31 5f 73 65 67 6d 65 6e   ..tablet1_segmen
|   3792: 74 73 74 31 5f 73 65 67 6d 65 6e 74 73 04 43 52   tst1_segments.CR
|   3808: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 73   EATE TABLE 't1_s
|   3824: 65 67 6d 65 6e 74 73 27 28 62 6c 6f 63 6b 69 64   egments'(blockid
|   3840: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59    INTEGER PRIMARY
|   3856: 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42    KEY, block BLOB
|   3872: 29 6a 03 07 17 21 21 01 81 1f 74 61 62 6c 65 74   )j...!!...tablet
|   3888: 31 5f 63 6f 6e 84 65 6e 74 74 31 5f 63 6f 6e 74   1_con.entt1_cont
|   3904: 65 6e 74 03 43 52 45 41 54 45 20 54 41 42 4c 45   ent.CREATE TABLE
|   3920: 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28 64 6f    't1_content'(do
|   3936: 63 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d   cid INTEGER PRIM
|   3952: 41 52 59 20 4b 45 59 2c 20 27 63 30 61 27 2c 20   ARY KEY, 'c0a', 
|   3968: 27 63 31 62 27 2c 20 27 63 32 63 27 29 38 02 06   'c1b', 'c2c')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 33   LE t1 USING fts3
|   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 25 0b 48 00 0f d8 0f af 0f 86 0f 74   ....%.H........t
|     16: 0f 61 0f 4e 0f 2f 0f 0f 0e ef 0e d7 0e be 0e a5   .a.N./..........
|     32: 0e 8d 0e 74 0e 5b 0e 40 0e 24 0e 08 0d ef 0d d5   ...t.[.@.$......
|     48: 0d bb 0d a0 0d 84 0d 68 0d 4f 0d 35 0d 1b 0c fb   .......h.O.5....
|     64: 0c da 0c b9 0c 99 0c 78 0c 57 0c 3e 0c 24 0c 0a   .......x.W.>.$..
|     80: 0b 48 00 00 00 00 00 00 00 00 00 00 00 00 00 00   .H..............
|   2880: 00 00 00 00 00 00 00 00 81 3f 25 06 00 82 7f 00   .........?%.....
|   2896: 00 43 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e   .COMPILER=gcc-5.
|   2912: 34 2e 30 20 32 30 31 36 30 36 30 39 20 44 45 42   4.0 20160609 DEB
|   2928: 55 47 20 45 4e 41 42 4c 45 20 44 42 53 54 41 54   UG ENABLE DBSTAT
|   2944: 20 56 54 41 42 20 45 4e 41 42 4c 45 20 46 54 53    VTAB ENABLE FTS
|   2960: 34 20 45 4e 41 42 4c 45 20 46 54 53 35 20 45 4e   4 ENABLE FTS5 EN
|   2976: 41 42 4c 45 20 47 45 4f 50 4f 4c 59 20 45 4e 41   ABLE GEOPOLY ENA
|   2992: 42 4c 45 20 4a 53 4f 4e 31 20 45 4e 41 42 4c 45   BLE JSON1 ENABLE
|   3008: 20 4d 45 4d 53 49 53 35 20 45 4e 41 42 4c 45 20    MEMSIS5 ENABLE 
|   3024: 52 54 52 45 45 20 4d 41 58 20 4d 45 4d 4f 52 59   RTREE MAX MEMORY
|   3040: 3d 35 30 30 30 30 30 30 30 20 4f 4d 49 54 20 4c   =50000000 OMIT L
|   3056: 4f 41 44 20 45 58 54 45 4e 53 49 4f 4e 20 54 48   OAD EXTENSION TH
|   3072: 52 45 41 44 53 41 46 45 3d 30 18 24 05 00 26 0f   READSAFE=0.$..&.
|   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 22   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 4f 4d   0XRTRIM.!..3..OM
|   3168: 49 54 20 4c 4f 41 44 20 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 53 49   MIT LOAD EXTENSI
|   3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17   ONXNOCASE....3..
|   3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53   OMIT LOAD EXTENS
|   3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19   IONXRTRIM....3..
|   3264: 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30   MAX MEMORY=50000
|   3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f   000XBINARY....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 33   0000XNOCASE....3
|   3328: 0f 17 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30   ..MAX 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 55 20 52 54 52 45 45 58 4e 4f 43 41 53 45 17   LU RTREEXNOCASE.
|   3408: 19 05 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52   ...%..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 53 35 58 52 54 52 49 4d 18 15 05 00 25   MSYS5XRTRIM....%
|   3520: 0f 19 45 4e 41 42 4c 45 20 4a 53 4f 4e 31 58 42   ..ENABLE 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 31 58 4e 4f 43 41 53 45 17   LE JSON1XNOCASE.
|   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 4e 41 42 4c   NARY....)..ENABL
|   3632: 45 20 47 45 4f 50 4f 4c 59 58 4e 4f 43 41 53 45   E GEOPOLYXNOCASE
|   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 19 45 4e 41 42 4c 45 20 46 54 53 35 58 42 49   ..ENABLE FTS5XBI
|   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 58 4e 4f 43 41 53 45 16 0d 05   E FTS5XNOCASE...
|   3728: 00 23 0f 17 45 4e 41 42 4c 45 20 46 54 53 35 58   .#..ENABLE FTS5X
|   3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42   RTRIM....#..ENAB
|   3760: 4c 45 19 46 54 53 34 58 42 49 4e 41 52 59 17 0b   LE.FTS4XBINARY..
|   3776: 05 00 23 0f 19 45 4e 41 42 4e f5 20 46 54 53 34   ..#..ENABN. FTS4
|   3792: 58 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 45 4e   XNOCASE....#..EN
|   3808: 41 42 4c 45 20 46 54 53 34 58 52 54 52 49 4d 1e   ABLE FTS4XRTRIM.
|   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 41 53   ...1..ENABLE DAS
|   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 ab 17 44 45 42 55 47   CASE.......DEBUG
|   3968: 48 52 54 52 49 4d 27 03 05 00 43 0f 19 43 4f 4d   HRTRIM'...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 43 49 4e 41 52 59 27   20160609XCINARY'
|   4016: 02 04 00 43 0f 19 43 4f 4d 50 49 4c 45 52 3d 67   ...C..COMPILER=g
|   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 43   9XNOCASE&...C..C
|   4064: 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e   OMPILER=gcc-5.4.
|   4080: 30 20 32 30 31 36 30 36 30 39 58 52 54 52 49 4d   0 20160609XRTRIM
| page 4 offset 12288
|      0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
| page 5 offset 16384
|      0: 0d 00 00 00 02 0b a0 00 0c ad 0b a0 00 00 00 00   ................
|   2976: 82 0a 02 08 08 09 08 08 17 84 06 30 20 32 35 33   ...........0 253
|   2992: 00 01 30 04 25 06 1b 00 00 08 32 30 31 36 30 36   ..0.%.....201606
|   3008: 30 39 03 25 07 00 00 01 34 03 25 05 00 00 01 35   09.%....4.%....5
|   3024: 03 25 04 00 01 07 30 30 30 30 30 30 30 03 25 1a   .%....0000000.%.
|   3040: 00 00 08 63 6f 6d 70 69 6c 65 72 03 25 02 00 00   ...compiler.%...
|   3056: 06 64 62 73 74 61 74 03 25 0a 00 01 04 65 62 75   .dbstat.%....ebu
|   3072: 67 03 25 08 00 00 06 65 6e 61 62 6c 65 09 25 09   g.%....enable.%.
|   3088: 05 04 04 04 04 04 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3104: 6e 03 25 1d 00 00 04 66 74 73 34 03 25 0d 00 03   n.%....fts4.%...
|   3120: 01 35 03 25 0f 00 00 03 67 63 63 03 25 03 00 01   .5.%....gcc.%...
|   3136: 06 65 6f 70 6f 6c 79 03 25 11 00 00 05 6a 73 6f   .eopoly.%....jso
|   3152: 6e 31 03 25 13 00 00 04 6c 6f 61 64 03 25 1c 00   n1.%....load.%..
|   3168: 00 03 6d 61 78 03 25 18 00 01 05 65 6d 6f 72 79   ..max.%....emory
|   3184: 03 25 19 00 03 04 73 79 73 35 03 25 15 00 00 04   .%....sys5.%....
|   3200: 6f 6d 69 74 03 25 1b 00 00 05 72 74 72 65 65 03   omit.%....rtree.
|   3216: 25 17 00 00 0a 74 68 72 65 61 64 73 61 66 65 03   %....threadsafe.
|   3232: 25 1e 00 00 04 76 74 61 62 03 25 0b 00 86 50 01   %....vtab.%...P.
|   3248: 08 08 08 08 08 17 8d 12 30 20 38 33 35 00 01 30   ........0 835..0
|   3264: 12 01 06 00 01 06 00 01 06 00 1f 03 00 01 03 00   ................
|   3280: 01 03 00 00 08 32 30 31 36 30 36 30 39 09 01 07   .....20160609...
|   3296: 00 01 07 00 01 07 00 00 01 34 09 01 05 00 01 05   .........4......
|   3312: 00 01 05 00 00 01 35 09 01 04 00 01 04 00 01 04   ......5.........
|   3328: 00 01 07 30 30 30 30 30 30 30 09 1c 04 00 01 04   ...0000000......
|   3344: 00 01 04 00 00 06 62 69 6e 61 72 79 3c 03 01 02   ......binary<...
|   3360: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3376: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
|   3392: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03   ................
|   3408: 01 02 02 00 03 01 02 02 00 00 08 63 6f 6d 70 69   ...........compi
|   3424: 6c 65 72 09 01 02 00 01 02 00 01 02 00 00 06 64   ler............d
|   3440: 62 73 74 61 74 09 07 03 00 01 03 00 01 03 00 01   bstat...........
|   3456: 04 65 62 75 67 09 04 02 00 01 02 00 01 02 00 00   .ebug...........
|   3472: 06 65 6e 61 62 6c 65 3f 07 02 00 01 02 00 01 02   .enable?........
|   3488: 00 01 02 00 01 02 00 01 02 00 01 02 00 01 02 00   ................
|   3504: 01 02 00 01 02 00 01 02 00 01 02 00 01 02 00 01   ................
|   3520: 02 00 01 02 00 01 02 00 01 02 00 01 02 00 01 02   ................
|   3536: 00 01 02 00 01 02 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3552: 6e 09 1f 04 00 01 04 00 01 04 00 00 04 66 74 73   n............fts
|   3568: 34 09 0a 03 d4 01 02 ff 01 03 00 03 01 35 09 0d   4............5..
|   3584: 03 00 01 03 00 01 03 00 00 03 67 64 d3 09 01 03   ..........gd....
|   3600: 00 01 03 00 01 03 00 01 06 65 6f 70 6f 6c 79 09   .........eopoly.
|   3616: 10 03 00 01 03 00 01 03 00 00 05 6a 73 6f 6e 31   ...........json1
|   3632: 19 13 03 00 01 03 00 01 03 00 00 04 6c 6f 61 64   ............load
|   3648: 09 1f 03 00 01 03 00 01 03 00 00 03 6d 61 78 09   ............max.
|   3664: 1c 02 00 01 02 00 01 02 00 01 05 65 6d 6f 72 79   ...........emory
|   3680: 09 1c 03 00 01 03 00 01 03 00 03 04 73 79 73 35   ............sys5
|   3696: 09 16 03 00 01 03 00 01 03 00 00 06 6e 6f 63 61   ............noca
|   3712: 73 65 3c 02 01 02 02 00 03 01 02 02 00 03 01 02   se<.............
|   3728: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3744: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
|   3760: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 00   ................
|   3776: 04 6f 6d 69 74 09 1f 02 00 01 12 00 01 02 00 00   .omit...........
|   3792: 05 72 74 72 65 65 09 19 03 00 01 07 80 00 f3 00   .rtree..........
|   3808: 03 02 69 6d 3c 01 01 02 02 00 03 01 02 02 00 03   ..im<...........
|   3824: 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01   ................
|   3840: 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02   ................
|   3856: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3872: 00 00 0a 74 68 72 65 61 64 73 61 66 65 09 22 02   ...threadsafe...
|   3888: 00 01 02 00 01 02 00 00 04 76 74 61 62 09 07 04   .........vtab...
|   3904: 00 01 04 00 01 04 00 00 01 78 b4 01 01 01 01 02   .........x......
|   3920: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   3936: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   3952: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   3968: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   3984: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4000: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   4016: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   4032: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   4048: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   4064: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4080: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
| page 6 offset 20480
|      0: 0a 00 00 00 02 0f f5 00 0f fb 0f f5 00 00 00 00   ................
|   4080: 00 00 00 00 00 05 04 08 09 01 02 04 04 08 08 09   ................
| page 7 offset 24576
|      0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   4016: 00 00 00 00 00 00 00 00 0d 05 02 23 61 75 74 6f   ...........#auto
|   4032: 6d 65 72 67 65 3d 35 0d 04 02 23 6d 65 72 67 65   merge=5...#merge
|   4048: 3d 31 30 30 2c 38 11 03 02 2b 69 6e 74 65 67 72   =100,8...+integr
|   4064: 69 74 79 2d 63 68 65 63 6b 09 02 02 1b 72 65 62   ity-check....reb
| end crash-b794c89d922ac9.db
}]} {}

do_catchsql_test 22.1 {
  PRAGMA writable_schema = 1;
  SELECT snippet(t1,'', '', '--',-1,01)==0
    FROM t1 WHERE a MATCH 'rtree OR json1rtree OR json1';
} {0 {0 0 0 0 0 0 0}}

#-------------------------------------------------------------------------
reset_db
do_test 23.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
.open --hexdb
| size 28672 pagesize 4096 filename crash-670b15f2955a36.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 02 10 00 00 01 00 00 00 07 00 00 00 00   ................
|     96: 00 00 00 00 0d 0e b1 00 06 0d a4 00 0f 8d 0f 21   ...............!
|    112: 0e b9 0d c8 0e 7e 0d a4 00 00 00 00 00 00 00 00   .....~..........
|   3488: 00 00 00 00 22 07 06 17 11 11 01 31 74 61 62 6c   ...........1tabl
|   3504: 65 74 32 74 32 07 43 52 45 41 54 45 20 54 41 42   et2t2.CREATE TAB
|   3520: 4c 45 20 74 32 28 78 29 81 33 05 07 17 1f 1f 01   LE t2(x).3......
|   3536: 82 35 74 61 62 6c 65 74 31 5f 73 65 67 64 69 72   .5tablet1_segdir
|   3552: 74 31 5f 73 65 67 64 69 72 05 43 52 45 41 54 45   t1_segdir.CREATE
|   3568: 20 54 41 42 4c 45 20 27 74 31 5f 73 65 67 64 69    TABLE 't1_segdi
|   3584: 72 27 28 6c 65 76 65 6c 20 49 4e 54 45 47 45 52   r'(level INTEGER
|   3600: 2c 69 64 78 20 49 4e 54 45 47 45 52 2c 73 74 61   ,idx INTEGER,sta
|   3616: 72 74 5f 62 6c 6f 63 6b 20 49 4e 54 45 47 45 52   rt_block INTEGER
|   3632: 2c 6c 65 61 76 65 73 5f 65 6e 64 5f 62 6c 6f 63   ,leaves_end_bloc
|   3648: 6b 20 49 4e 54 45 47 45 52 2c 65 6e 64 5f 62 6c   k INTEGER,end_bl
|   3664: 6f 63 6b 20 49 4e 54 45 47 45 52 2c 72 6f 6f 74   ock INTEGER,root
|   3680: 20 42 4c 4f 42 2c 50 52 49 4d 41 52 59 20 4b 45    BLOB,PRIMARY KE
|   3696: 59 28 6c 65 76 65 6c 2c 20 69 64 78 29 29 31 06   Y(level, idx))1.
|   3712: 06 17 45 1f 01 00 69 6e 64 65 78 73 71 6c 69 74   ..E...indexsqlit
|   3728: 65 5f 61 75 74 6f 69 6e 64 65 78 5f 74 31 5f 73   e_autoindex_t1_s
|   3744: 65 67 64 69 72 5f 31 74 31 5f 73 65 67 64 69 72   egdir_1t1_segdir
|   3760: 06 0f c7 00 08 00 00 00 00 66 04 07 17 23 23 01   .........f...##.
|   3776: 81 13 74 61 62 6c 75 74 31 5f 73 65 67 6d 65 6e   ..tablut1_segmen
|   3792: 74 73 74 31 5f 73 65 67 6d 65 6e 74 73 04 43 52   tst1_segments.CR
|   3808: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 73   EATE TABLE 't1_s
|   3824: 65 67 6d 65 6e 74 73 27 28 62 6c 6f 63 6b 69 64   egments'(blockid
|   3840: 20 49 4e 54 45 47 45 42 20 50 52 49 4d 41 52 59    INTEGEB PRIMARY
|   3856: 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42    KEY, block BLOB
|   3872: 29 6a 03 07 17 21 21 01 81 1f 74 61 62 6c 65 74   )j...!!...tablet
|   3888: 31 5f 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74   1_contentt1_cont
|   3904: 65 6e 74 03 43 52 45 41 54 45 20 54 41 42 4c 45   ent.CREATE TABLE
|   3920: 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28 64 6f    't1_content'(do
|   3936: 63 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d   cid INTEGER PRIM
|   3952: 41 52 59 20 4b 45 59 2c 20 27 63 30 61 27 2c 20   ARY KEY, 'c0a', 
|   3968: 27 63 31 62 27 2c 20 27 63 32 63 27 29 38 02 06   'c1b', 'c2c')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 33   LE t1 USING fts3
|   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 25 0b 48 01 0f d8 00 2f 0f 86 0f 74   ....%.H..../...t
|     16: 0f 61 0f 4e 0f 2f 0f 0f 0e ef 0e d7 0e be 0e a5   .a.N./..........
|     32: 0e 8d 0e 74 0e 5a fe 40 0e 24 0e 08 0d ef 0d d5   ...t.Z.@.$......
|     48: 0d bb 0d a0 0d 84 0d 68 0d 4f 81 35 0d 1b 0c fb   .......h.O.5....
|     64: 0c da 0c b9 0c 99 0c 78 0c 57 0c 3e 00 00 00 00   .......x.W.>....
|   2880: 00 00 00 00 00 00 00 00 81 3f 25 06 00 82 7f 10   .........?%.....
|   2896: 00 43 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e   .COMPILER=gcc-5.
|   2912: 34 2e 30 20 32 30 31 36 30 36 30 39 20 44 45 42   4.0 20160609 DEB
|   2928: 55 47 20 45 4e 41 42 4c 45 20 44 42 53 54 41 54   UG ENABLE DBSTAT
|   2944: 20 56 54 41 42 20 45 4e 41 42 4c 45 20 46 54 53    VTAB ENABLE FTS
|   2960: 34 20 45 4e 41 42 4c 45 20 46 54 53 35 20 45 4e   4 ENABLE FTS5 EN
|   2976: 41 42 4c 45 20 47 45 4f 50 4f 4c 59 20 45 4e 41   ABLE GEOPOLY ENA
|   2992: 42 4c 45 20 4a 53 4f 4e 31 20 45 4e 41 42 4c 45   BLE JSON1 ENABLE
|   3008: 20 4d 45 4d 53 59 53 35 20 45 4e 41 42 4c 45 20    MEMSYS5 ENABLE 
|   3024: 52 54 52 45 45 20 4d 41 58 20 4d 45 4d 4f 52 59   RTREE MAX MEMORY
|   3040: 3d 35 30 30 30 30 30 30 30 20 4f 4d 49 54 20 4c   =50000000 OMIT L
|   3056: 4f 41 44 20 45 58 54 45 4e 53 49 4f 4e 20 54 48   OAD EXTENSION TH
|   3072: 52 45 41 44 53 41 46 45 3d 30 18 24 05 00 35 0f   READSAFE=0.$..5.
|   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 55 00 25 0f 19 54 48 52 45 41   NARY.#U.%..THREA
|   3120: 44 53 41 46 45 3d 30 58 4e 4f 43 41 53 45 17 22   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 4f 4d   0XRTRIM.!..3..OM
|   3168: 49 54 20 4c 4f 41 44 20 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 53 49   MIT LOAD EXTENSI
|   3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17   ONXNOCASE....3..
|   3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53   OMIT LOAD EXTENS
|   3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19   IONXRTRIM....3..
|   3264: 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30   MAX MEMORY=50000
|   3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f   000XBINARY....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 33   0000XNOCASE....3
|   3328: 0f 17 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30   ..MAX 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 44 20 52 54 52 45 45 58 42   ..ENABLD 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 58 4e 4f 43 41 53 45 17   LE RTREEXNOCASE.
|   3408: 19 05 00 24 0f 17 45 4e 40 42 4c 45 20 52 54 52   ...$..EN@BLE 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 4d 41 42 4c   NARY....)..EMABL
|   3472: 45 20 4d 45 4d 53 59 53 35 58 4e 4f 43 41 4c 45   E MEMSYS5XNOCALE
|   3488: 19 16 05 00 29 0f 17 45 4e 41 42 4c 45 20 4d 45   ....)..ENABLE ME
|   3504: 4e 53 59 53 35 58 52 54 52 49 4d 18 15 05 00 25   NSYS5XRTRIM....%
|   3520: 0f 19 45 4e 41 42 4c 45 20 4a 53 4f 4e 31 58 42   ..ENABLE 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 31 58 4e 4f 43 41 53 45 17   LE JSON1XNOCASE.
|   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 5f b9 4d 1a 12 05 00 29 0f 19 45   N1XRT_.M....)..E
|   3600: 4e 41 42 4c 45 20 47 45 4f 50 31 4c 59 58 42 49   NABLE GEOP1LYXBI
|   3616: 4e 41 52 58 1a 11 05 00 29 0f 19 45 4e 41 42 4c   NARX....)..ENABL
|   3632: 45 20 47 45 4f 50 4f 4c 59 58 4e 4f 43 41 53 45   E GEOPOLYXNOCASE
|   3648: 19 10 05 00 29 0f 17 45 4e 41 42 4c 45 20 57 45   ....)..ENABLE WE
|   3664: 4f 50 4f 4c 59 48 52 54 52 49 4d 17 0f 05 00 23   OPOLYHRTRIM....#
|   3680: 0f 19 45 4e 41 42 4c 45 20 46 54 53 35 58 42 49   ..ENABLE FTS5XBI
|   3696: 4e 41 53 59 17 0e 05 00 23 0f 19 45 4e 40 42 4b   NASY....#..EN@BK
|   3712: 45 20 46 54 53 35 58 4e 4f 43 41 53 45 16 0d 05   E FTS5XNOCASE...
|   3728: 00 23 0f 17 45 4e 41 42 4c 45 20 46 54 53 35 58   .#..ENABLE FTS5X
|   3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42   RTRIM....#..ENAB
|   3760: 4c 45 20 46 54 94 34 58 42 49 4e 41 52 59 17 0b   LE FT.4XBINARY..
|   3776: 05 00 23 0f 19 45 4e 41 42 4c 43 70 46 54 53 34   ..#..ENABLCpFTS4
|   3792: 58 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 45 4e   XNOCASE....#..EN
|   3808: 41 42 4c 45 20 46 54 53 34 58 52 54 52 49 4d 1e   ABLE FTS4XRTRIM.
|   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 32 53   ...1..ENABLE D2S
|   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 0b 27 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 03 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 35 52 3d 67   ...C..COMPIL5R=g
|   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 02 43   9XNOCASE&...C..C
|   4064: 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e   OMPILER=gcc-5.4.
|   4080: 30 20 32 30 31 36 30 36 30 39 58 00 00 00 00 00   0 20160609X.....
| page 5 offset 16384
|      0: 0d 00 00 00 02 0b a0 00 0c ad 0b a0 00 00 00 00   ................
|   2976: 82 0a 02 08 08 09 08 08 17 84 06 30 20 32 35 33   ...........0 253
|   2992: 00 01 30 04 25 06 1b 00 00 08 32 30 31 36 30 36   ..0.%.....201606
|   3008: 30 39 03 25 07 00 00 01 34 03 25 05 00 00 01 35   09.%....4.%....5
|   3024: 03 25 04 00 01 07 30 30 30 30 30 30 30 08 55 1a   .%....0000000.U.
|   3040: 00 00 08 63 6f 6d 70 69 6c 65 72 03 25 02 00 00   ...compiler.%...
|   3056: 06 64 62 73 74 61 74 03 25 0a 00 01 04 65 61 75   .dbstat.%....eau
|   3072: 67 03 25 08 00 00 06 65 6e 61 62 6c 65 09 25 09   g.%....enable.%.
|   3088: 05 04 04 04 04 04 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3104: 6e 03 25 1d 00 00 04 66 74 73 34 03 25 0d 00 03   n.%....fts4.%...
|   3120: 01 35 03 25 0f 00 00 0c 97 63 63 03 25 03 00 01   .5.%.....cc.%...
|   3136: 06 65 6f 70 6f 6c 7a 03 25 11 00 00 05 6a 73 6f   .eopolz.%....jso
|   3152: 6e 31 03 25 13 00 00 04 6c 6f 61 64 03 25 1c 00   n1.%....load.%..
|   3168: 00 03 6d 61 78 03 25 18 00 01 05 65 6d 6f 72 79   ..max.%....emory
|   3184: 03 25 3d f0 03 04 73 79 73 35 03 25 15 00 00 04   .%=...sys5.%....
|   3200: 6f 6d 69 74 03 25 1b 00 00 05 72 74 72 65 65 03   omit.%....rtree.
|   3216: 25 17 00 00 0a 74 68 72 65 61 64 73 61 66 65 03   %....threadsafe.
|   3232: 25 1e 00 00 04 76 74 61 62 03 25 0b 00 86 50 01   %....vtab.%...P.
|   3248: 08 08 08 09 08 17 8d 12 30 20 38 33 37 e3 aa e0   ........0 837...
|   3264: 12 d1 06 00 01 06 00 01 06 00 1f 03 00 01 03 00   ................
|   3280: 01 03 00 00 08 32 30 31 36 30 36 30 49 09 01 07   .....2016060I...
|   3296: 00 01 07 00 01 07 00 00 01 34 09 01 05 00 01 05   .........4......
|   3312: 00 01 05 00 00 01 35 09 01 04 00 01 04 00 01 04   ......5.........
|   3328: 00 01 07 30 30 30 30 30 30 30 09 1c 04 00 01 04   ...0000000......
|   3344: 00 01 04 00 00 06 62 69 6e 61 72 79 3c 03 01 02   ......binary<...
|   3360: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3376: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
|   3392: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03   ................
|   3408: 01 02 02 00 03 01 02 02 00 00 08 63 6f 6d 70 69   ...........compi
|   3424: 6c 65 72 09 01 02 00 01 02 00 01 02 00 00 06 64   ler............d
|   3440: 62 73 74 61 74 09 07 03 00 01 03 00 01 03 00 01   bstat...........
|   3456: 04 65 62 75 67 09 04 01 f0 01 02 00 01 02 00 00   .ebug...........
|   3472: 06 65 6e 61 62 6c 65 3f 07 02 00 01 02 00 01 02   .enable?........
|   3488: 00 01 02 00 01 02 00 01 02 00 01 02 00 01 02 00   ................
|   3504: 01 02 00 01 02 00 01 02 00 01 02 00 01 02 00 01   ................
|   3520: 02 00 01 02 00 01 02 00 01 02 00 01 02 00 01 02   ................
|   3536: 00 01 02 00 01 02 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3552: 6e 09 1f 04 00 01 04 00 01 04 00 00 04 66 74 73   n............fts
|   3568: 34 09 0a 03 f3 01 03 00 01 03 00 19 01 35 09 0d   4............5..
|   3584: 03 00 01 03 00 01 03 00 00 03 67 63 63 09 01 03   ..........gcc...
|   3600: 00 01 03 00 01 03 00 01 06 65 6f 70 6f 6c 79 09   .........eopoly.
|   3616: 10 03 00 01 03 00 01 03 00 00 05 6a 73 6f 6e 31   ...........json1
|   3632: 09 13 03 00 01 03 00 00 f3 00 00 04 6c 6f 61 64   ............load
|   3648: 09 1f 03 00 01 03 00 01 03 00 00 03 6d 61 78 09   ............max.
|   3664: 1c 02 00 01 02 00 01 02 00 01 05 65 6d 6f 72 79   ...........emory
|   3680: 09 1c 03 00 01 03 00 01 03 00 03 04 73 79 73 35   ............sys5
|   3696: 09 16 03 00 01 03 00 01 03 00 00 06 6e 6f 63 61   ............noca
|   3712: 73 65 3c 02 01 02 02 00 03 01 02 02 00 03 01 02   se<.............
|   3728: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3744: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
|   3760: 03 01 02 02 00 03 01 02 02 00 46 01 02 02 00 00   ..........F.....
|   3776: 04 6f 6d 69 74 09 1f 02 00 01 02 00 01 02 00 00   .omit...........
|   3792: 05 72 74 72 64 65 09 19 03 00 01 03 00 01 03 00   .rtrde..........
|   3808: 03 02 69 6d 3c 01 01 02 02 00 03 01 02 02 00 03   ..im<...........
|   3824: 01 02 02 00 03 01 02 01 ff 03 01 02 02 00 03 01   ................
|   3840: 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02   ................
|   3856: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3872: 00 00 0a 74 68 72 65 61 64 73 61 66 65 09 22 02   ...threadsafe...
|   3888: 00 01 02 00 01 02 00 00 04 76 74 61 62 09 07 04   .........vtab...
|   3904: 00 01 04 00 01 04 00 00 01 78 b4 01 01 01 01 02   .........x......
|   3920: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   3936: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   3952: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   3968: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   3984: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4000: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   4016: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   4032: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   4048: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   4064: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 02 02   ................
|   4080: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
| page 6 offset 20480
|      0: 0a 00 00 00 02 0f f5 00 0f fb 0f f5 00 00 00 00   ................
|   4080: 00 00 00 00 00 05 04 08 09 01 02 04 04 08 09 09   ................
| page 7 offset 24576
|      0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   4016: 00 00 00 00 00 00 00 00 0d 05 02 23 61 75 74 6f   ...........#auto
|   4032: 6d 65 71 97 65 3d 35 0d 04 02 23 6d 65 72 67 65   meq.e=5...#merge
|   4048: 3d 31 30 30 2c 38 11 03 02 2b 69 6e 74 65 67 72   =100,8...+integr
|   4064: 69 74 79 00 00 00 00 00 00 00 00 00 00 00 00 00   ity.............
| end crash-670b15f2955a36.db
}]} {}

do_catchsql_test 23.1 {
  PRAGMA writable_schema = 1;
  SELECT 'FyzLy'FROM t1 WHERE t1 MATCH 'j';
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
reset_db
do_test 24.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
.open --hexdb
| size 28672 pagesize 4096 filename crash-369d042958c29b.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 03 10 00 00 00 00   .....@  ........
|     96: 00 00 00 00 0d 0e b1 00 06 0d a4 00 0f 8d 0f 21   ...............!
|    112: 0e b9 0d c8 0e 7e 0d a4 00 00 00 00 00 00 00 00   .....~..........
|   3488: 00 00 00 00 22 07 06 17 11 11 01 31 74 61 62 6c   ...........1tabl
|   3504: 65 74 32 74 32 07 43 52 45 41 54 45 20 54 41 42   et2t2.CREATE TAB
|   3520: 4c 45 20 74 32 28 78 29 81 33 05 07 17 1f 1f 01   LE t2(x).3......
|   3536: 82 35 74 61 62 6c 65 74 31 5f 73 65 67 64 69 72   .5tablet1_segdir
|   3552: 74 31 5f 73 65 67 64 69 72 05 43 52 45 41 54 45   t1_segdir.CREATE
|   3568: 20 54 41 42 4c 45 20 27 74 31 5f 73 65 67 64 69    TABLE 't1_segdi
|   3584: 72 27 28 6c 65 76 65 6c 20 49 4e 54 45 47 45 52   r'(level INTEGER
|   3600: 2c 69 64 78 20 49 4e 54 45 47 45 52 2c 73 74 61   ,idx INTEGER,sta
|   3616: 72 74 5f 62 6c 6f 63 6b 20 49 4e 54 45 47 45 52   rt_block INTEGER
|   3632: 2c 6c 65 61 76 65 73 5f 65 6e 64 5f 62 6c 6f 63   ,leaves_end_bloc
|   3648: 6b 20 49 4e 54 45 47 45 52 2c 65 6e 64 5f 62 6c   k INTEGER,end_bl
|   3664: 6f 63 6b 20 49 4e 54 45 47 45 52 2c 72 6f 6f 74   ock INTEGER,root
|   3680: 20 42 4c 4f 42 2c 50 52 49 4d 41 52 59 20 4b 45    BLOB,PRIMARY KE
|   3696: 59 28 6c 65 76 65 6c 2c 20 69 64 78 29 29 31 06   Y(level, idx))1.
|   3712: 06 17 45 1f 01 00 69 6e 64 65 78 73 71 6c 69 74   ..E...indexsqlit
|   3728: 65 5f 61 75 74 6f 69 6e 64 65 78 5f 74 31 5f 73   e_autoindex_t1_s
|   3744: 65 67 64 69 72 5f 31 74 31 5f 73 65 67 64 69 72   egdir_1t1_segdir
|   3760: 06 0f c7 00 08 00 10 00 00 66 04 07 17 23 23 01   .........f...##.
|   3776: 81 13 74 61 62 6c 65 74 31 5f 73 65 67 6d 65 6e   ..tablet1_segmen
|   3792: 64 73 74 31 5f 73 65 67 6d 65 6e 74 73 04 43 52   dst1_segments.CR
|   3808: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 73   EATE TABLE 't1_s
|   3824: 65 67 6d 65 6e 74 73 27 28 62 6c 6f 63 6b 69 64   egments'(blockid
|   3840: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59    INTEGER PRIMARY
|   3856: 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42    KEY, block BLOB
|   3872: 29 6a 03 07 17 21 21 01 81 1f 74 61 62 6c 65 74   )j...!!...tablet
|   3888: 31 4f 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74   1Ocontentt1_cont
|   3904: 65 6e 74 03 43 52 45 41 54 45 20 54 41 42 4c 45   ent.CREATE TABLE
|   3920: 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28 64 6f    't1_content'(do
|   3936: 63 69 64 20 49 4e 54 45 47 45 52 20 50 52 39 4d   cid INTEGER PR9M
|   3952: 41 52 59 20 4b 45 59 2c 20 27 63 30 61 27 2c 20   ARY KEY, 'c0a', 
|   3968: 27 63 31 62 27 2c 20 27 63 32 63 27 29 38 02 06   'c1b', 'c2c')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 33   LE t1 USING fts3
|   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 26 0b 48 0e 0f d8 0f af 0f 86 0f 74   ....&.H........t
|     16: 0f 61 0f 4e 0f 2f 0f 0f 0e ef 0e d7 0e be 0e a5   .a.N./..........
|     32: 0e 8d 0e 74 0e 5b 0e 40 0e 24 0e 08 0d ef 0d d5   ...t.[.@.$......
|     48: 0d bb 0d a0 0e 94 03 28 0d 4f 0d 35 0d 1b 05 0b   .......(.O.5....
|     64: 0c da 0c b9 0c 99 0c 78 0c 57 0c 3e 0c 24 0c 0a   .......x.W.>.$..
|   2880: 00 00 00 00 00 00 00 00 81 3f 25 06 00 72 7f 00   .........?%..r..
|   2896: 00 43 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e   .COMPILER=gcc-5.
|   2912: 34 2e 30 20 32 30 31 36 30 36 30 39 20 44 55 42   4.0 20160609 DUB
|   2928: 55 47 20 45 4e 41 e4 7c 45 20 44 42 53 54 41 54   UG ENA.|E DBSTAT
|   2944: e4 d1 54 41 42 20 45 4e 41 42 4c 45 20 46 54 53   ..TAB ENABLE FTS
|   2960: 34 20 45 4e 41 42 4c 45 20 46 54 53 35 20 45 4e   4 ENABLE FTS5 EN
|   2976: 41 42 4c 45 20 47 45 4f 50 4f 4c 59 20 45 4e 41   ABLE GEOPOLY ENA
|   2992: 42 4c 45 20 4a 53 4f 4e 31 20 45 4e 41 42 4c 45   BLE JSON1 ENABLE
|   3008: 20 4d 45 4d 53 59 53 35 20 45 4e 41 42 4c 45 20    MEMSYS5 ENABLE 
|   3024: 42 54 52 45 45 20 4d 41 58 20 4d 45 4d 4f 52 59   BTREE MAX MEMORY
|   3040: 3d 35 30 30 30 30 30 30 30 20 4f 4c 49 54 20 4c   =50000000 OLIT L
|   3056: 4f 41 43 20 45 58 54 45 4e 53 49 4f 4e 21 54 48   OAC EXTENSION!TH
|   3072: 52 45 41 44 53 41 46 45 3d 30 18 24 05 00 25 0f   READSAFE=0.$..%.
|   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 4b 75 3d 30 58 4d 4f 43 41 53 45 17 22   DSAKu=0XMOCASE..
|   3136: 05 00 25 0f 17 54 48 52 45 41 44 53 41 46 46 3d   ..%..THREADSAFF=
|   3152: 30 58 52 54 52 49 4d 1f 21 05 00 33 0f 19 4f 4d   0XRTRIM.!..3..OM
|   3168: 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 52 49 4f   IT LOAD EXTENRIO
|   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 53 49   MIT LOAD EXTENSI
|   3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17   ONXNOCASE....3..
|   3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53   OMIT LOAD EXTENS
|   3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19   IONXRTRIM....3..
|   3264: 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30   MAX MEMORY=50000
|   3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f   000XBINARY....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 33   0000XNOCASE....3
|   3328: 0f 17 4d 42 b8 20 4d 45 4d 4f 52 59 3d 35 30 30   ..MB. 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 0d a5 0f 19 45 4e 41 42   INARY.......ENAB
|   3392: 4c 45 20 52 54 52 45 45 58 4e 4f 43 41 53 45 17   LE RTREEXNOCASE.
|   3408: 19 1c 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52   ...%..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 53 35 58 52 54 52 49 4d 18 14 05 01 25   MSYS5XRTRIM....%
|   3520: 0f 19 45 4e 12 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 09 d9 45 4e 41 42   INARY....%..ENAB
|   3552: 4c 45 20 4a 53 4f 3e 31 58 4e 4f 43 41 53 45 17   LE JSO>1XNOCASE.
|   3568: 13 05 00 25 0f 17 45 4e 40 42 4c 45 20 4a 53 4f   ...%..EN@BLE JSO
|   3584: 4e 31 58 52 54 52 49 4d 1a 12 05 82 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 c9 29 e8 19 46 4e 41 42 4c   NARY....)..FNABL
|   3632: 48 c0 47 45 4f 50 4f 4c 59 58 4e 74 43 41 53 45   H.GEOPOLYXNtCASE
|   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 19 45 4e 41 42 4c 45 30 46 54 53 35 58 42 49   ..ENABLE0FTS5XBI
|   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 58 4e 4f 43 41 53 45 16 0e 05   E FTS5XNOCASE...
|   3728: 00 23 0f 17 45 4e 41 42 4c 45 20 46 54 53 35 58   .#..ENABLE FTS5X
|   3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42   RTRIM....#..ENAB
|   3760: 4c 45 20 46 54 53 34 58 42 49 4e 41 52 59 17 0b   LE FTS4XBINARY..
|   3776: 05 00 23 0f 19 45 4e 41 42 4c 45 20 46 54 53 34   ..#..ENABLE FTS4
|   3792: 58 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 45 4e   XNOCASE....#..EN
|   3808: 41 42 4c 45 20 46 54 53 34 58 52 54 52 49 4d 1e   ABLE FTS4XRTRIM.
|   3824: 09 05 00 31 0f 19 45 4e 42 42 4c 45 20 44 42 53   ...1..ENBBLE 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 4a 4d 11 06   TAT VTABXRTRJM..
|   3920: 05 f0 17 0f 19 44 45 42 55 47 58 42 49 4e 41 52   .....DEBUGXBINAR
|   3936: 59 11 05 05 00 17 0e 19 44 45 42 55 47 58 4e 4f   Y.......DEBUGXNO
|   3952: 43 41 53 45 10 04 05 00 17 0f 16 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 3d 67   ...C..COMPILER=g
|   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 06 00 43 0f 17 43   9XNOCASE&...C..C
|   4064: 4f 4d 50 49 4b 45 52 3d 67 63 63 2d 35 2e 34 2e   OMPIKER=gcc-5.4.
|   4080: 30 20 32 30 31 36 30 36 40 39 58 29 54 52 49 4d   0 201606@9X)TRIM
| page 4 offset 12288
|      0: 0d 00 10 00 00 10 00 00 00 00 00 00 00 01 00 00   ................
| page 5 offset 16384
|      0: 0d 00 00 00 02 0b a0 00 0c ad 0b a0 00 00 00 00   ................
|   2976: 82 0a 02 08 08 09 08 08 17 84 06 30 20 32 35 33   ...........0 253
|   2992: 00 01 30 04 25 06 1b 00 00 08 32 30 31 36 30 36   ..0.%.....201606
|   3008: 30 39 03 25 07 00 00 01 34 03 25 05 00 00 01 35   09.%....4.%....5
|   3024: 03 25 04 00 01 07 30 30 30 30 30 30 30 03 25 1a   .%....0000000.%.
|   3040: 00 00 08 63 6f 6d 70 69 6c 65 72 03 25 02 00 00   ...compiler.%...
|   3056: 06 64 62 73 74 61 74 03 25 0a 00 01 04 65 62 75   .dbstat.%....ebu
|   3072: 67 03 25 08 00 00 06 65 6e 61 62 6c 65 09 25 09   g.%....enable.%.
|   3088: 05 04 04 04 04 04 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3104: 6e 03 25 1d 00 00 04 66 74 73 34 03 25 0d 00 03   n.%....fts4.%...
|   3120: 01 35 03 25 0f 00 00 03 67 63 63 03 25 03 00 01   .5.%....gcc.%...
|   3136: 06 65 6f 70 6f 6c 79 03 25 11 00 00 05 6a 73 6f   .eopoly.%....jso
|   3152: 6e 31 03 25 13 00 00 04 6c 6f 61 64 03 25 1c 00   n1.%....load.%..
|   3168: 00 03 6d 61 78 03 25 18 00 01 05 65 6e 6f 72 79   ..max.%....enory
|   3184: 03 25 19 00 03 04 ce 79 73 4d 03 25 15 00 00 04   .%.....ysM.%....
|   3200: 6f 6d 69 74 03 25 1b 00 00 05 72 74 72 65 65 03   omit.%....rtree.
|   3216: 25 17 00 00 0a 74 68 72 65 61 64 73 61 66 65 03   %....threadsafe.
|   3232: 25 0e 00 00 04 76 74 61 62 03 25 0b 00 86 50 01   %....vtab.%...P.
|   3248: 08 08 08 08 08 17 8d 12 30 20 38 33 35 00 01 30   ........0 835..0
|   3264: 12 01 06 00 01 06 00 01 06 00 1f 03 00 01 03 09   ................
|   3280: 51 03 00 00 08 32 30 31 36 30 36 30 39 09 01 07   Q....20160609...
|   3296: 00 01 07 00 01 07 00 00 01 34 09 01 05 00 01 05   .........4......
|   3312: 00 01 05 00 00 01 35 09 01 04 00 01 04 00 01 04   ......5.........
|   3328: 00 01 07 30 30 30 30 30 30 30 09 1c 04 00 01 04   ...0000000......
|   3344: 00 01 04 00 00 06 62 69 6e 61 72 79 3c 03 01 02   ......binary<...
|   3360: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3376: 00 03 01 02 02 00 02 f1 02 02 00 03 01 02 02 00   ................
|   3392: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03   ................
|   3408: 01 02 02 00 03 01 02 02 00 00 08 63 6f 6d 70 69   ...........compi
|   3424: 6c 65 72 09 01 02 00 01 02 00 01 02 00 00 06 67   ler............g
|   3440: d2 73 74 61 74 09 07 03 00 01 03 00 01 03 00 01   .stat...........
|   3456: 04 65 62 75 67 09 04 02 00 01 02 00 01 02 00 00   .ebug...........
|   3472: 06 65 6e 6f 82 6c 65 3f 07 02 00 01 02 00 01 02   .eno.le?........
|   3488: b0 01 02 00 01 02 00 11 02 00 01 02 00 01 02 00   ................
|   3504: 01 02 00 01 02 00 01 02 00 01 a6 00 01 02 00 01   ................
|   3520: 02 05 51 02 00 01 02 00 01 02 00 01 02 00 01 02   ..Q.............
|   3536: 00 01 02 00 01 02 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3552: 6e 09 1f 04 00 01 04 00 00 04 00 00 04 66 74 73   n............fts
|   3568: 34 09 0a 03 00 01 03 00 01 03 00 03 01 35 09 0d   4............5..
|   3584: 03 00 01 03 00 01 03 00 00 03 67 63 63 09 01 03   ..........gcc...
|   3600: 00 01 03 00 01 03 00 01 06 65 6f 70 73 6c 79 09   .........eopsly.
|   3616: 10 03 00 01 03 00 01 03 00 00 05 6a 73 6f 6e 31   ...........json1
|   3632: 09 13 03 00 01 03 00 01 03 00 00 04 6c 6f 61 64   ............load
|   3648: 09 1f 03 00 01 03 00 01 03 00 00 03 6d 61 78 09   ............max.
|   3664: 1c 02 00 01 02 00 01 02 00 01 05 65 6d 6f 72 79   ...........emory
|   3680: 09 1c 03 00 01 03 00 01 03 00 03 04 73 79 73 35   ............sys5
|   3696: 09 16 03 00 01 03 00 01 03 00 00 06 6e 6f 63 61   ............noca
|   3712: 73 65 3c 02 01 02 02 00 03 01 12 02 00 03 01 02   se<.............
|   3728: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3744: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
|   3760: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 00   ................
|   3776: 04 6f 6d 69 74 09 1f 02 00 01 02 00 01 02 00 00   .omit...........
|   3792: 05 72 74 72 65 65 09 19 03 00 01 03 00 01 03 00   .rtree..........
|   3808: 03 02 69 6d 3c 01 01 02 02 00 03 01 02 02 00 03   ..im<...........
|   3824: 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01   ................
|   3840: 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02   ................
|   3856: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3872: 00 00 0a 74 68 72 65 61 64 73 61 66 65 09 22 02   ...threadsafe...
|   3888: 00 01 02 00 01 02 00 00 04 76 74 61 62 09 07 04   .........vtab...
|   3904: 00 01 04 00 01 03 ff ff 01 78 b4 01 01 01 01 02   .........x......
|   3920: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   3936: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   3952: 01 01 02 00 01 01 01 07 30 01 01 01 02 00 01 01   ........0.......
|   3968: 01 02 00 11 01 01 02 00 01 01 01 02 00 11 01 01   ................
|   3984: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4000: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   4016: 01 01 01 01 ff 01 01 01 02 00 01 01 01 02 00 01   ................
|   4032: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   4048: 01 02 00 01 01 09 c2 00 01 01 01 02 00 01 01 01   ................
|   4064: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4080: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
| page 6 offset 20480
|      0: 0a 00 00 00 02 0f f5 00 0f fb 0f f5 00 00 00 00   ................
|   4080: 00 00 00 00 00 05 04 08 09 01 02 04 04 08 08 09   ................
| page 7 offset 24576
|      0: 0d 00 00 00 05 0f b8 00 0e f4 0f e9 10 d6 0f c7   ................
|   4016: 00 00 00 00 00 00 00 00 0d 05 02 23 61 75 74 6f   ...........#auto
|   4032: 6d 65 72 67 65 3d 35 0d 04 02 23 6d 65 72 67 65   merge=5...#merge
|   4048: 3d 31 00 00 00 00 00 00 00 00 00 00 00 00 00 00   =1..............
| end crash-369d042958c29b.db
}]} {}

do_catchsql_test 24.1 {
  PRAGMA writable_schema = 1;
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT '4hE'+x FROM c WHERE x<72)
    INSERT INTO t1(a) SELECT randomblob(2829) FROM c;
} {1 {database disk image is malformed}}

do_catchsql_test 24.2 {
  UPDATE t1 SET b=quote((true) ) WHERE t1 MATCH 'h';
} {0 {}}

do_catchsql_test 24.3 {
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT 3+x FROM c WHERE x<72)
    INSERT INTO t1(a) SELECT randomblob(2829) FROM c;
} {1 {database disk image is malformed}}

do_catchsql_test 24.4 {
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT null<<x FROM c WHERE x<72)
    INSERT INTO t1(a) SELECT randomblob(2829) FROM c;
} {0 {}}

do_catchsql_test 24.5 {
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT 3+x FROM c WHERE x<72)
    INSERT INTO t1(a) SELECT randomblob(2829) FROM c;
} {1 {database disk image is malformed}}

do_catchsql_test 24.7 {
  INSERT INTO t1(t1) SELECT x FROM t2;
} {0 {}}

#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
reset_db
do_test 25.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
.open --hexdb
| size 28672 pagesize 4096 filename crash-dde9e76ed8ab2d.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 03 10 00 00 00 00   .....@  ........
|     96: 00 00 00 00 0d 0e b1 00 06 0d a4 00 0f 8d 0f 21   ...............!
|    112: 0e b9 0d c8 0e 7e 0d a4 00 00 00 00 00 00 00 00   .....~..........
|   3488: 00 00 00 00 22 07 06 17 11 11 01 31 74 61 62 6c   ...........1tabl
|   3504: 65 74 32 74 32 07 43 52 45 41 54 45 20 54 41 42   et2t2.CREATE TAB
|   3520: 4c 45 20 74 32 28 78 29 81 33 05 07 17 1f 1f 01   LE t2(x).3......
|   3536: 82 35 74 61 62 6c 65 74 31 5f 73 65 67 64 69 72   .5tablet1_segdir
|   3552: 74 31 5f 73 65 67 64 69 72 05 43 52 45 41 54 45   t1_segdir.CREATE
|   3568: 20 54 41 42 4c 45 20 27 74 31 5f 73 65 67 64 69    TABLE 't1_segdi
|   3584: 72 27 28 6c 65 76 65 6c 20 49 4e 54 45 47 45 52   r'(level INTEGER
|   3600: 2c 69 64 78 20 49 4e 54 45 47 45 52 2c 73 74 61   ,idx INTEGER,sta
|   3616: 72 74 5f 62 6c 6f 63 6b 20 49 4e 54 45 47 45 52   rt_block INTEGER
|   3632: 2c 6c 65 61 76 65 73 5f 65 6e 64 5f 62 6c 6f 63   ,leaves_end_bloc
|   3648: 6b 20 49 4e 54 45 47 45 52 2c 65 6e 64 5f 62 6c   k INTEGER,end_bl
|   3664: 6f 63 6b 20 49 4e 54 45 47 45 52 2c 72 6f 6f 74   ock INTEGER,root
|   3680: 20 42 4c 4f 42 2c 50 52 49 4d 41 52 59 20 4b 45    BLOB,PRIMARY KE
|   3696: 59 28 6c 65 76 65 6c 2c 20 69 64 78 29 29 31 06   Y(level, idx))1.
|   3712: 06 17 45 1f 01 00 69 6e 64 65 78 73 71 6c 69 74   ..E...indexsqlit
|   3728: 65 5f 61 75 74 6f 69 6e 64 65 78 5f 74 31 5f 73   e_autoindex_t1_s
|   3744: 65 67 64 69 72 5f 31 74 31 5f 73 65 67 64 69 72   egdir_1t1_segdir
|   3760: 06 0f c7 00 08 00 00 00 00 66 04 07 17 23 23 01   .........f...##.
|   3776: 81 13 74 61 62 6c 65 74 31 5f 73 65 67 6d 65 6e   ..tablet1_segmen
|   3792: 64 73 74 31 5f 73 65 67 6d 65 6e 74 73 04 43 52   dst1_segments.CR
|   3808: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 73   EATE TABLE 't1_s
|   3824: 65 67 6d 65 6e 74 73 27 28 62 6c 6f 63 6b 69 64   egments'(blockid
|   3840: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59    INTEGER PRIMARY
|   3856: 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42    KEY, block BLOB
|   3872: 29 6a 03 07 17 21 21 01 81 1f 74 61 62 6c 65 74   )j...!!...tablet
|   3888: 31 5f 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74   1_contentt1_cont
|   3904: 65 6e 74 03 43 52 45 41 54 45 20 54 41 42 4c 45   ent.CREATE TABLE
|   3920: 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28 64 6f    't1_content'(do
|   3936: 63 69 64 20 49 4e 54 45 47 45 52 20 50 52 39 4d   cid INTEGER PR9M
|   3952: 41 52 59 20 4b 45 59 2c 20 27 63 30 61 27 2c 20   ARY KEY, 'c0a', 
|   3968: 27 63 31 62 27 2c 20 27 63 32 63 27 29 38 02 06   'c1b', 'c2c')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 33   LE t1 USING fts3
|   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 26 0b 48 0e 0f d8 0f af 0f 86 0f 74   ....&.H........t
|     16: 0f 61 0f 4e 0f 2f 0f 0f 0e ef 0e d7 0e be 0e a5   .a.N./..........
|     32: 0e 8d 0e 74 0e 5b 0e 40 0e 24 0e 08 0d ef 0d d5   ...t.[.@.$......
|     48: 0d bb 0d a0 0e 94 03 28 0d 4f 0d 35 0d 1b 05 0b   .......(.O.5....
|     64: 0c da 0c b9 0c 99 0c 78 0c 57 0c 3e 0c 24 0c 0a   .......x.W.>.$..
|   2880: 00 00 00 00 00 00 00 00 81 3f 25 06 00 72 7f 00   .........?%..r..
|   2896: 00 43 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e   .COMPILER=gcc-5.
|   2912: 34 2e 30 20 32 30 31 36 30 36 30 39 20 44 55 42   4.0 20160609 DUB
|   2928: 55 47 20 45 4e 41 e4 7c 45 20 44 42 53 54 41 54   UG ENA.|E DBSTAT
|   2944: e4 46 54 41 42 20 45 4e 41 42 4c 45 20 46 54 53   .FTAB ENABLE FTS
|   2960: 34 20 45 4e 41 42 4c 45 20 46 54 53 35 20 45 4e   4 ENABLE FTS5 EN
|   2976: 41 42 4c 45 20 47 45 4f 50 4f 4c 59 20 45 4e 41   ABLE GEOPOLY ENA
|   2992: 42 4c 45 20 4a 53 4f 4e 31 20 45 4e 41 42 4c 45   BLE JSON1 ENABLE
|   3008: 20 4d 45 4d 53 59 53 35 20 45 4e 41 42 4c 45 20    MEMSYS5 ENABLE 
|   3024: 42 54 52 45 45 20 4d 41 58 20 4d 45 4d 4f 52 59   BTREE MAX MEMORY
|   3040: 3d 35 30 30 30 30 30 30 30 20 4f 4c 49 54 20 4c   =50000000 OLIT L
|   3056: 4f 41 43 20 45 58 54 45 4e 53 49 4f 4e 21 54 48   OAC EXTENSION!TH
|   3072: 52 45 41 44 53 41 46 45 3d 30 18 24 05 00 25 0f   READSAFE=0.$..%.
|   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 4b 75 3d 30 58 4d 4f 43 41 53 45 17 22   DSAKu=0XMOCASE..
|   3136: 05 00 25 0f 17 54 48 52 45 41 44 53 41 46 46 3d   ..%..THREADSAFF=
|   3152: 30 58 52 54 52 49 4d 1f 21 05 00 33 0f 19 4f 4d   0XRTRIM.!..3..OM
|   3168: 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 52 49 4f   IT LOAD EXTENRIO
|   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 53 49   MIT LOAD EXTENSI
|   3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17   ONXNOCASE....3..
|   3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53   OMIT LOAD EXTENS
|   3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19   IONXRTRIM....3..
|   3264: 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30   MAX MEMORY=50000
|   3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f   000XBINARY....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 33   0000XNOCASE....3
|   3328: 0f 17 4d 42 b8 20 4d 45 4d 4f 52 59 3d 35 30 30   ..MB. 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 0d a5 0f 19 45 4e 41 42   INARY.......ENAB
|   3392: 4c 45 20 52 54 52 45 45 58 4e 4f 43 41 53 45 17   LE RTREEXNOCASE.
|   3408: 19 1c 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52   ...%..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 53 35 58 52 54 52 49 4d 18 14 05 01 25   MSYS5XRTRIM....%
|   3520: 0f 19 45 4e 12 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 09 d9 45 4e 41 42   INARY....%..ENAB
|   3552: 4c 45 20 4a 53 4f 3e 31 58 4e 4f 43 41 53 45 17   LE JSO>1XNOCASE.
|   3568: 13 05 00 25 0f 17 45 4e 40 42 4c 45 20 4a 53 4f   ...%..EN@BLE JSO
|   3584: 4e 31 58 52 54 52 49 4d 1a 12 05 82 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 c9 29 e8 19 46 4e 41 42 4c   NARY....)..FNABL
|   3632: 48 c0 47 45 4f 50 4f 4c 59 58 4e 74 43 41 53 45   H.GEOPOLYXNtCASE
|   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 19 45 4e 41 42 4c 45 30 46 54 53 35 58 42 49   ..ENABLE0FTS5XBI
|   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 58 4e 4f 43 41 53 45 16 0e 05   E FTS5XNOCASE...
|   3728: 00 23 0f 17 45 4e 41 42 4c 45 20 46 54 53 35 58   .#..ENABLE FTS5X
|   3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42   RTRIM....#..ENAB
|   3760: 4c 45 20 46 54 53 34 58 42 49 4e 41 52 59 17 0b   LE FTS4XBINARY..
|   3776: 05 00 23 0f 19 45 4e 41 42 4c 45 20 46 54 53 34   ..#..ENABLE FTS4
|   3792: 58 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 45 4e   XNOCASE....#..EN
|   3808: 41 42 4c 45 20 46 54 53 34 58 52 54 52 49 4d 1e   ABLE FTS4XRTRIM.
|   3824: 09 05 00 31 0f 19 45 4e 42 42 4c 45 20 44 42 53   ...1..ENBBLE 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 4a 4d 11 06   TAT VTABXRTRJM..
|   3920: 05 f0 17 0f 19 44 45 42 55 47 58 42 49 4e 41 52   .....DEBUGXBINAR
|   3936: 59 11 05 05 00 17 0e 19 44 45 42 55 47 58 4e 4f   Y.......DEBUGXNO
|   3952: 43 41 53 45 10 04 05 00 17 0f 16 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 3d 67   ...C..COMPILER=g
|   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 06 00 43 0f 17 43   9XNOCASE&...C..C
|   4064: 4f 4d 50 49 4b 45 52 3d 67 63 63 2d 35 2e 34 2e   OMPIKER=gcc-5.4.
|   4080: 30 20 32 30 31 36 30 36 40 39 58 29 54 52 49 4d   0 201606@9X)TRIM
| page 4 offset 12288
|      0: 0d 00 10 00 00 10 00 00 00 00 00 00 00 01 00 00   ................
| page 5 offset 16384
|      0: 0d 00 00 00 02 0b a0 00 0c ad 0b a0 00 00 00 00   ................
|   2976: 82 0a 02 08 08 09 08 08 17 84 06 30 20 32 35 33   ...........0 253
|   2992: 00 01 30 04 25 06 1b 00 00 08 32 30 31 36 30 36   ..0.%.....201606
|   3008: 30 39 03 25 07 00 00 01 34 03 25 05 00 00 01 35   09.%....4.%....5
|   3024: 03 25 04 00 01 07 30 30 30 30 30 30 30 03 25 1a   .%....0000000.%.
|   3040: 00 00 08 63 6f 6d 70 69 6c 65 72 03 25 02 00 00   ...compiler.%...
|   3056: 06 64 62 73 74 61 74 03 25 0a 00 01 04 65 62 75   .dbstat.%....ebu
|   3072: 67 03 25 08 00 00 06 65 6e 61 62 6c 65 09 25 09   g.%....enable.%.
|   3088: 05 04 04 04 04 04 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3104: 6e 03 25 1d 00 00 04 66 74 73 34 03 25 0d 00 03   n.%....fts4.%...
|   3120: 01 35 03 25 0f 00 00 03 67 63 63 03 25 03 00 01   .5.%....gcc.%...
|   3136: 06 65 6f 70 6f 6c 79 03 25 11 00 00 05 6a 73 6f   .eopoly.%....jso
|   3152: 6e 31 03 25 13 00 00 04 6c 6f 61 64 03 25 1c 00   n1.%....load.%..
|   3168: 00 03 6d 61 78 03 25 18 00 01 05 65 6e 6f 72 79   ..max.%....enory
|   3184: 03 25 19 00 03 04 ce 79 73 4d 03 25 15 00 00 04   .%.....ysM.%....
|   3200: 6f 6d 69 74 03 25 1b 00 00 05 72 74 72 65 65 03   omit.%....rtree.
|   3216: 25 17 00 00 0a 74 68 72 65 61 64 73 61 66 65 03   %....threadsafe.
|   3232: 25 0e 00 00 04 76 74 61 62 03 25 0b 00 86 50 01   %....vtab.%...P.
|   3248: 08 08 08 08 08 17 8d 12 30 20 38 33 35 00 01 30   ........0 835..0
|   3264: 12 01 06 00 01 06 00 01 06 00 1f 03 00 01 03 09   ................
|   3280: 51 03 00 00 08 32 30 31 36 30 36 30 39 09 01 07   Q....20160609...
|   3296: 00 01 07 00 01 07 00 00 01 34 09 01 05 00 01 05   .........4......
|   3312: 00 01 05 00 00 01 35 09 01 04 00 01 04 00 01 04   ......5.........
|   3328: 00 01 07 30 30 30 30 30 30 30 09 1c 04 00 01 04   ...0000000......
|   3344: 00 01 04 00 00 06 62 69 6e 61 72 79 3c 03 01 02   ......binary<...
|   3360: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3376: 00 03 01 02 02 00 02 f1 02 02 00 03 01 02 02 00   ................
|   3392: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03   ................
|   3408: 01 02 02 00 03 01 02 02 00 00 08 63 6f 6d 70 69   ...........compi
|   3424: 6c 65 72 09 01 02 00 01 02 00 01 02 00 00 06 67   ler............g
|   3440: d2 73 74 61 74 09 07 03 00 01 03 00 01 03 00 01   .stat...........
|   3456: 04 65 62 75 67 09 04 02 00 01 02 00 01 02 00 00   .ebug...........
|   3472: 06 65 6e 6f 82 6c 65 3f 07 02 00 01 02 00 01 02   .eno.le?........
|   3488: b0 01 02 00 01 02 00 11 02 00 01 02 00 01 02 00   ................
|   3504: 01 02 00 01 02 00 01 02 00 01 a6 00 01 02 00 01   ................
|   3520: 02 05 51 02 00 01 02 00 01 02 00 01 02 00 01 02   ..Q.............
|   3536: 00 01 02 00 01 02 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3552: 6e 09 1f 04 00 01 04 00 00 04 00 00 04 66 74 73   n............fts
|   3568: 34 09 0a 03 00 01 03 00 01 03 00 03 01 35 09 0d   4............5..
|   3584: 03 00 01 03 00 01 03 00 00 03 67 63 63 09 01 03   ..........gcc...
|   3600: 00 01 03 00 01 03 00 01 06 65 6f 70 73 6c 79 09   .........eopsly.
|   3616: 10 03 00 01 03 00 01 03 00 00 05 6a 73 6f 6e 31   ...........json1
|   3632: 09 13 03 00 01 03 00 01 03 00 00 04 6c 6f 61 64   ............load
|   3648: 09 1f 03 00 01 03 00 01 03 00 00 03 6d 61 78 09   ............max.
|   3664: 1c 02 00 01 02 00 01 02 00 01 05 65 6d 6f 72 79   ...........emory
|   3680: 09 1c 03 00 01 03 00 01 03 00 03 04 73 79 73 35   ............sys5
|   3696: 09 16 03 00 01 03 00 01 03 00 00 06 6e 6f 63 61   ............noca
|   3712: 73 65 3c 02 01 02 02 00 03 01 12 02 00 03 01 02   se<.............
|   3728: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3744: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
|   3760: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 00   ................
|   3776: 0e 9f 6d 69 74 09 1f 02 00 01 02 00 01 02 00 00   ..mit...........
|   3792: 05 72 74 72 65 65 09 19 03 00 01 03 00 01 03 00   .rtree..........
|   3808: 03 02 69 6d 3c 01 01 02 02 00 03 01 02 02 00 03   ..im<...........
|   3824: 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01   ................
|   3840: 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02   ................
|   3856: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3872: 00 00 0a 74 68 72 65 61 64 73 61 66 65 09 22 02   ...threadsafe...
|   3888: 00 01 02 00 01 02 00 00 04 76 74 61 62 09 07 04   .........vtab...
|   3904: 00 01 04 00 01 04 00 00 01 78 b4 01 01 01 01 02   .........x......
|   3920: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   3936: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   3952: 01 01 02 00 01 01 01 07 30 01 01 01 02 00 01 01   ........0.......
|   3968: 01 02 00 11 01 01 02 00 01 01 01 02 00 11 01 01   ................
|   3984: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4000: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   4016: 01 01 01 01 ff 01 01 01 02 00 01 01 01 02 00 01   ................
|   4032: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   4048: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   4064: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4080: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
| page 6 offset 20480
|      0: 0a 00 00 00 02 0f f5 00 0f fb 0f f5 00 00 00 00   ................
|   4080: 00 00 00 00 00 05 04 08 09 01 02 04 04 08 08 09   ................
| page 7 offset 24576
|      0: 0d 00 00 00 05 0f b8 00 0e f4 0f e9 10 d6 0f c7   ................
|   4016: 00 00 00 00 00 00 00 00 0d 05 02 23 61 75 74 6f   ...........#auto
|   4032: 6d 65 72 67 65 3d 35 0d 04 02 23 6d 65 72 67 65   merge=5...#merge
|   4048: 3d 31 00 00 00 00 00 00 00 00 00 00 00 00 00 00   =1..............
| end crash-dde9e76ed8ab2d.db
}]} {}

do_catchsql_test 25.1 {
  PRAGMA writable_schema = 1;
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x%1 FROM c WHERE x<599237)
    INSERT INTO t1( a ) SELECT randomblob(3000) FROM t2 ;
} {0 {}}

do_catchsql_test 25.2 {
  UPDATE t1 SET b=quote((true) ) WHERE t1 MATCH 'h*';
} {0 {}}

do_catchsql_test 25.3 {
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x +x FROM c WHERE 72<x)
    INSERT INTO t1(a) SELECT randomblob(2829) FROM c;
} {0 {}}

do_catchsql_test 25.4 {
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x%1 FROM c WHERE 599237<x)
    INSERT INTO t1(a) SELECT randomblob(3000) FROM t2 ;
} {0 {}}

do_catchsql_test 25.5 {
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x%1 FROM c WHERE x<599237)
    INSERT INTO t1( a ) SELECT randomblob(3000) FROM t2 ;
} {0 {}}

do_catchsql_test 25.6 {
  INSERT INTO t1(t1) SELECT x FROM t2;
  INSERT INTO t1(t1) SELECT x FROM t2;
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
reset_db
do_test 26.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
.open --hexdb
| size 28672 pagesize 4096 filename crash-26682721375870.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 0e b1 00 06 0d a4 00 0f 8d 0f 21   ...............!
|    112: 0e b9 0d c8 0e 7e 0d a4 00 00 00 00 00 00 00 00   .....~..........
|   3488: 00 00 00 00 22 07 06 17 11 11 01 31 74 61 62 6c   ...........1tabl
|   3504: 65 74 32 74 32 07 43 52 45 41 54 45 20 54 41 42   et2t2.CREATE TAB
|   3520: 4c 45 20 74 32 28 78 29 81 33 05 07 17 1f 1f 01   LE t2(x).3......
|   3536: 82 35 74 61 62 6c 65 74 31 5f 73 65 67 64 69 72   .5tablet1_segdir
|   3552: 74 31 5f 73 65 67 64 69 72 05 43 52 45 41 54 45   t1_segdir.CREATE
|   3568: 20 54 41 42 4c 45 20 27 74 31 5f 73 65 67 64 69    TABLE 't1_segdi
|   3584: 72 27 28 6c 65 76 65 6c 20 49 4e 54 45 47 45 51   r'(level INTEGEQ
|   3600: 2c 69 64 78 20 49 4e 54 45 47 45 52 2c 73 74 61   ,idx INTEGER,sta
|   3616: 72 74 5f 62 6c 6f 63 6b 20 49 4e 54 45 47 45 52   rt_block INTEGER
|   3632: 2c 6c 65 61 76 65 73 5f 65 6e 64 5f 62 6c 6f 63   ,leaves_end_bloc
|   3648: 6b 20 49 4e 54 45 47 45 52 2c 65 6e 64 5f 62 6c   k INTEGER,end_bl
|   3664: 6f 63 6b 20 49 4e 54 45 47 45 62 2c 72 6f 6f 74   ock INTEGEb,root
|   3680: 20 42 4c 4f 42 2c 50 52 49 4d 41 52 59 20 4b 45    BLOB,PRIMARY KE
|   3696: 59 28 6c 65 76 65 6c 2c 20 69 64 78 29 29 31 06   Y(level, idx))1.
|   3712: 06 17 45 1f 01 00 69 6e 64 65 78 73 71 6c 69 74   ..E...indexsqlit
|   3728: 65 5f 61 75 74 6f 69 6e 64 65 78 5f 74 31 5f 73   e_autoindex_t1_s
|   3744: 65 67 64 69 72 5f 31 74 31 5f 73 65 67 64 69 72   egdir_1t1_segdir
|   3760: 06 0f c7 00 08 00 00 00 00 66 04 07 17 23 23 01   .........f...##.
|   3776: 81 13 74 61 62 6c 65 74 31 5f 73 65 66 6d 65 6e   ..tablet1_sefmen
|   3792: 74 73 74 31 5f 73 65 67 6d 65 6e 74 73 04 43 52   tst1_segments.CR
|   3808: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 73   EATE TABLE 't1_s
|   3824: 65 67 6d 65 6e 74 73 27 28 62 6c 6f 63 6b 69 64   egments'(blockid
|   3840: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59    INTEGER PRIMARY
|   3856: 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42    KEY, block BLOB
|   3872: 29 6a 03 07 17 21 21 01 81 1f 74 61 62 6c 65 74   )j...!!...tablet
|   3888: 31 5f 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74   1_contentt1_cont
|   3904: 65 6e 74 03 43 52 45 41 54 45 20 54 41 42 4c 45   ent.CREATE TABLE
|   3920: 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28 64 6f    't1_content'(do
|   3936: 63 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d   cid INTEGER PRIM
|   3952: 41 52 59 20 4b 45 59 2c 20 27 63 30 61 27 2c 20   ARY KEY, 'c0a', 
|   3968: 27 63 31 62 27 2c 20 27 63 32 63 27 29 38 02 06   'c1b', 'c2c')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 33   LE t1 USING fts3
|   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 25 0b 48 00 0f d8 0f af 0f 86 0f 74   ....%.H........t
|     16: 0f 61 0f 4e 0f 2f 0f 0f 0e ef 0e d7 0e be 0e a5   .a.N./..........
|     32: 0e 8d 0e 74 0e 5b 0e 40 0e 24 0e 08 0d ef 00 00   ...t.[.@.$......
|   2880: 00 00 00 00 00 00 00 00 81 3f 25 06 00 82 7f 00   .........?%.....
|   2896: 00 43 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e   .COMPILER=gcc-5.
|   2912: 34 23 00 20 32 2f 31 36 30 36 30 39 20 44 45 42   4#. 2/160609 DEB
|   2928: 55 47 20 45 4e 41 42 4c 45 20 44 42 53 54 41 54   UG ENABLE DBSTAT
|   2944: 20 56 54 41 42 20 45 4e 41 42 4c 45 20 46 54 53    VTAB ENABLE FTS
|   2960: 34 20 45 4e 41 42 4c 45 20 46 54 53 35 20 45 4e   4 ENABLE FTS5 EN
|   2976: 41 42 4c 45 20 47 45 4f 50 4f 4c 59 20 45 4e 41   ABLE GEOPOLY ENA
|   2992: 42 4c 45 20 4a 53 4f 4e 31 20 45 4e 41 42 4c 45   BLE JSON1 ENABLE
|   3008: 20 4d 45 4d 53 59 53 35 20 45 4e 41 42 4c 45 20    MEMSYS5 ENABLE 
|   3024: 52 54 52 45 45 20 4d 41 58 20 4d 45 4d 4f 52 59   RTREE MAX MEMORY
|   3040: 3d 35 30 30 30 30 30 30 30 20 4f 4d 49 54 20 4c   =50000000 OMIT L
|   3056: 4f 41 44 20 45 58 54 45 4e 53 59 4f 4e 20 54 48   OAD EXTENSYON TH
|   3072: 52 45 41 44 53 41 46 45 3d 30 18 24 05 00 25 0f   READSAFE=0.$..%.
|   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 22   DSAFE=0XNOCASE..
|   3136: 05 00 25 0f 17 54 38 52 45 41 44 53 41 46 45 3d   ..%..T8READSAFE=
|   3152: 30 58 52 54 52 49 4d 1f 21 05 00 33 0f 19 4f 4d   0XRTRIM.!..3..OM
|   3168: 49 54 20 4c 4f 41 44 20 45 58 54 45 fc 53 49 4f   IT LOAD EXTE.SIO
|   3184: 4e 68 42 49 4e 4a c2 59 1f 20 05 00 33 0f 19 4f   NhBINJ.Y. ..3..O
|   3200: 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49   MIT LOAD EXTENSI
|   3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17   ONXNOCASE....3..
|   3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53   OMIT LOAD EXTENS
|   3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19   IONXRTRIM....3..
|   3264: 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 2f 30 30   MAX MEMORY=50/00
|   3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f   000XBINARY....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 48 4e 4f 43 41 53 45 1e 1c 05 00 33   0000HNOCASE....3
|   3328: 0f 17 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30   ..MAX 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 58 4e 4f 53 41 53 45 17   LE RTREEXNOSASE.
|   3408: 19 05 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52   ...%..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 53 35 58 52 54 52 49 4d 18 15 05 00 25   MSYS5XRTRIM....%
|   3520: 0f 19 45 4e 41 42 4c 45 20 4a 53 4f 4e 31 58 42   ..ENABLE JSON1XB
|   3536: 49 4e 41 52 59 18 14 05 00 25 0f 19 45 4e 42 42   INARY....%..ENBB
|   3552: 4d 45 20 4a 53 4f 4e 31 58 4e 4f 43 41 53 45 17   ME JSON1XNOCASE.
|   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 4e 41 1e 4c   NARY....)..ENA.L
|   3632: 45 20 47 45 4f 50 4f 4c 59 58 4e 4f 43 41 53 45   E GEOPOLYXNOCASE
|   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 62 54 52 49 4d 17 0f 05 00 23   OPOLYXbTRIM....#
|   3680: 0f 19 45 4e 41 42 4c 45 20 46 54 53 35 58 42 49   ..ENABLE FTS5XBI
|   3696: 4e 41 52 59 17 0e 05 00 23 0f 19 45 4e 41 42 4c   NARY....#..ENABL
|   3712: 45 20 46 54 fc 35 58 4e 4f 43 41 53 45 16 0d 05   E FT.5XNOCASE...
|   3728: 00 23 0f 17 45 4e 41 42 4c 45 20 46 54 53 35 58   .#..ENABLE FTS5X
|   3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42   RTRIM....#..ENAB
|   3760: 4c 45 20 46 54 53 34 58 42 49 4e 41 52 59 17 0b   LE FTS4XBINARY..
|   3776: 05 00 23 0f 19 45 4e 41 42 4c 45 20 46 54 53 35   ..#..ENABLE FTS5
|   3792: 58 4e 4f 43 40 53 45 16 0a 05 00 23 0f 17 45 4e   XNOC@SE....#..EN
|   3808: 41 42 4c 45 20 56 54 53 34 58 52 54 52 49 4d 1e   ABLE VTS4XRTRIM.
|   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 b3 58 1e   TAT VTABXBINA.X.
|   3856: 08 05 00 31 0f 19 45 4e 40 42 4c 45 20 44 42 53   ...1..EN@BLE 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 45 42 53   ...1..ENABLE EBS
|   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 4b 19 4e 41 52 59 27   20160609XK.NARY'
|   4016: 02 05 00 43 0f 19 43 4f 4d 50 49 4c 45 52 3d 67   ...C..COMPILER=g
|   4032: 63 63 2d 35 2e 34 2e 30 20 32 30 31 36 30 36 30   cc-5.4.0 2016060
| page 5 offset 16384
|      0: 0d 00 00 00 02 0b a0 00 0c ad 0b a0 00 00 00 00   ................
|   2976: 82 0a 02 08 08 09 08 08 17 84 06 30 20 32 34 33   ...........0 243
|   2992: 00 01 30 04 25 06 1b 00 00 08 32 30 31 36 30 36   ..0.%.....201606
|   3008: 30 39 03 25 07 00 00 01 34 03 25 05 00 00 01 35   09.%....4.%....5
|   3024: 03 25 04 00 01 07 30 30 30 30 30 30 30 03 25 1a   .%....0000000.%.
|   3040: 00 00 08 63 6f 6d 70 69 6c 65 72 03 25 02 00 00   ...compiler.%...
|   3056: 06 64 62 73 74 51 74 03 25 0a 00 01 04 65 62 75   .dbstQt.%....ebu
|   3072: 67 03 25 08 00 00 06 65 6e 61 62 6c 65 09 25 09   g.%....enable.%.
|   3088: 05 04 04 04 04 04 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3104: 6e 03 25 1d 00 00 04 66 74 73 34 03 25 0d 00 03   n.%....fts4.%...
|   3120: 01 35 03 25 0f 00 00 03 67 63 63 03 25 03 00 01   .5.%....gcc.%...
|   3136: 06 65 6f 70 6f 6c 79 03 25 11 00 00 05 6a 73 6f   .eopoly.%....jso
|   3152: 6e 31 03 25 13 00 00 04 6c 6f 61 64 03 25 1c 00   n1.%....load.%..
|   3168: 00 03 6d 61 78 03 25 18 00 01 05 65 6d 6f 72 79   ..max.%....emory
|   3184: 03 25 19 00 03 04 73 79 73 35 03 25 15 00 00 04   .%....sys5.%....
|   3200: 6f 6d 69 74 03 25 1b 00 00 05 72 74 72 65 65 03   omit.%....rtree.
|   3216: 25 17 00 00 0a 74 68 72 65 61 64 73 61 66 65 03   %....threadsafe.
|   3232: 25 1e 00 00 04 76 74 61 62 03 25 0b 00 86 50 01   %....vtab.%...P.
|   3248: 08 08 08 08 08 17 8d 12 30 20 38 33 35 00 01 30   ........0 835..0
|   3264: 12 01 06 00 01 06 00 01 06 00 1e f3 00 01 03 00   ................
|   3280: 01 03 00 00 08 32 30 31 36 30 36 30 39 09 01 07   .....20160609...
|   3296: 00 01 07 00 01 07 00 00 01 34 09 01 05 00 01 05   .........4......
|   3312: 00 01 05 00 00 01 35 09 01 04 00 01 04 00 01 04   ......5.........
|   3328: 00 01 07 30 30 30 30 2f 30 30 09 1c 04 00 01 04   ...0000/00......
|   3344: 00 01 04 00 00 06 62 69 6e 61 72 79 3c 03 01 02   ......binary<...
|   3360: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3376: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
|   3392: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03   ................
|   3408: 01 02 02 00 03 01 02 02 00 00 08 63 6f 6d 70 69   ...........compi
|   3424: 6c 65 72 09 01 02 00 01 02 00 01 02 00 00 06 64   ler............d
|   3440: 62 73 74 61 74 09 07 03 00 01 03 00 01 03 00 01   bstat...........
|   3456: 04 65 62 75 67 09 04 02 00 01 02 00 01 02 00 00   .ebug...........
|   3472: 06 65 6e 61 62 6c 65 3f 07 02 00 01 02 00 01 02   .enable?........
|   3488: 00 01 02 00 01 02 00 01 01 f0 01 02 00 57 02 00   .............W..
|   3504: 01 02 00 01 02 00 01 02 00 01 02 00 01 02 10 01   ................
|   3520: 02 00 01 02 00 01 02 00 01 02 00 01 02 00 01 02   ................
|   3536: 00 00 02 00 01 02 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3552: 6e 09 1f 04 00 01 04 00 01 04 00 00 04 66 74 73   n............fts
|   3568: 34 09 0a 03 00 01 03 00 01 03 00 03 01 35 09 0d   4............5..
|   3584: 03 00 01 03 00 a9 03 00 00 03 67 63 63 09 01 03   ..........gcc...
|   3600: 00 01 03 00 01 03 00 01 06 65 6f 70 6f 6c 79 09   .........eopoly.
|   3616: 10 03 00 01 03 00 01 03 00 00 05 6a 73 6f 6e 31   ...........json1
|   3632: 09 13 03 00 01 03 00 01 03 00 00 04 6c 6f 61 64   ............load
|   3648: 09 1f 03 00 01 03 00 01 03 00 00 03 6d 61 78 09   ............max.
|   3664: 1c 02 0b 31 02 00 01 02 00 01 05 65 6d 6f 72 79   ...1.......emory
|   3680: 09 1c 03 00 01 03 00 01 03 00 03 04 73 79 73 35   ............sys5
|   3696: 09 16 03 00 01 03 00 01 03 00 00 06 6e 6f 63 61   ............noca
|   3712: 73 65 3c 02 01 02 02 00 03 01 02 02 00 03 01 02   se<.............
|   3728: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3744: 00 03 01 02 02 00 f3 01 02 02 00 03 01 02 02 00   ................
|   3760: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 00   ................
|   3776: 04 6f 6d 69 74 09 1f 02 00 01 02 00 01 02 00 00   .omit...........
|   3792: 05 72 74 72 65 65 09 19 03 00 01 03 00 01 03 00   .rtree..........
|   3808: 03 02 69 6d 3c 01 01 02 02 00 03 01 02 02 00 03   ..im<...........
|   3824: 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01   ................
|   3840: 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02   ................
|   3856: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3872: 00 00 0a 74 68 72 65 61 64 63 61 66 65 09 22 02   ...threadcafe...
|   3888: 00 01 02 00 02 02 00 00 04 76 74 61 62 09 07 04   .........vtab...
|   3904: 00 01 04 00 01 04 00 00 01 78 b4 01 01 01 01 02   .........x......
|   3920: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   3936: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   3952: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   3968: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   3984: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4000: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   4016: 01 01 01 02 00 01 01 01 02 00 01 00 01 02 00 01   ................
|   4032: 01 01 02 00 01 01 00 e2 00 01 01 01 02 00 01 01   ................
|   4048: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   4064: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4080: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
| page 6 offset 20480
|      0: 0a 00 00 00 02 0f f5 00 0f fb 0f f5 00 00 00 00   ................
|   4080: 00 00 00 00 00 05 04 08 09 01 02 04 04 08 08 09   ................
| page 7 offset 24576
|      0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   4016: 00 00 00 00 00 00 00 00 0d 05 02 23 61 00 00 00   ...........#a...
| end crash-26682721375870.db
}]} {}

do_execsql_test 26.1 {
  PRAGMA writable_schema = 1;
  SELECT count(*) FROM (
    SELECT t1, (t1) FROM t1 WHERE b MATCH 'x'
  )
} 34

#-------------------------------------------------------------------------
reset_db
do_test 27.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
.open --hexdb
| size 28672 pagesize 4096 filename crash-23ddd777a03bfd.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 0e b1 00 06 0d a4 00 0f 8d 0f 21   ...............!
|    112: 0e b9 0d c8 0e 7e 0d a4 00 00 00 00 00 00 00 00   .....~..........
|   3488: 00 00 00 00 22 07 06 17 11 11 01 31 74 61 62 6c   ...........1tabl
|   3504: 65 74 32 74 32 07 43 52 45 41 54 45 20 54 41 42   et2t2.CREATE TAB
|   3520: 4c 45 20 74 32 28 78 29 81 33 05 07 17 1f 1f 01   LE t2(x).3......
|   3536: 82 35 74 61 62 6c 65 74 31 5f 73 65 67 64 69 72   .5tablet1_segdir
|   3552: 74 31 5f 73 65 67 64 69 72 05 43 52 45 41 54 45   t1_segdir.CREATE
|   3568: 20 54 41 42 4c 45 20 27 74 31 5f 73 65 67 64 69    TABLE 't1_segdi
|   3584: 72 27 28 6c 65 76 65 6c 20 49 4e 54 45 47 45 52   r'(level INTEGER
|   3600: 2c 69 64 78 20 49 4e 54 45 47 45 52 2c 73 74 61   ,idx INTEGER,sta
|   3616: 72 74 5f 62 6c 6f 63 6b 20 49 4e 54 45 47 45 52   rt_block INTEGER
|   3632: 2c 6c 65 61 76 65 73 5f 65 6e 64 5f 62 6c 6f 63   ,leaves_end_bloc
|   3648: 6b 20 49 4e 54 45 47 45 52 2c 65 6e 64 5f 62 6c   k INTEGER,end_bl
|   3664: 6f 63 6b 20 49 4e 54 45 47 45 52 2c 72 6f 6f 74   ock INTEGER,root
|   3680: 20 42 4c 4f 42 2c 50 52 49 4d 41 52 59 20 4b 45    BLOB,PRIMARY KE
|   3696: 59 28 6c 65 76 65 6c 2c 20 69 64 78 29 29 31 06   Y(level, idx))1.
|   3712: 06 17 45 1f 01 00 69 6e 64 65 78 73 71 6c 69 74   ..E...indexsqlit
|   3728: 65 5f 61 75 74 6f 69 6e 64 65 78 5f 74 31 5f 73   e_autoindex_t1_s
|   3744: 65 67 64 69 72 5f 31 74 31 5f 73 65 67 64 69 72   egdir_1t1_segdir
|   3760: 06 0f c7 00 08 00 00 00 00 66 04 07 17 23 23 01   .........f...##.
|   3776: 81 13 74 61 62 6c 65 74 31 5f 73 65 67 6d 65 6e   ..tablet1_segmen
|   3792: 64 73 74 31 5f 73 65 67 6d 65 6e 73 73 04 43 52   dst1_segmenss.CR
|   3808: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 73   EATE TABLE 't1_s
|   3824: 65 67 6d 65 6e 74 73 27 28 62 6c 6f 63 6b 69 64   egments'(blockid
|   3840: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 4e 72 59    INTEGER PRIMNrY
|   3856: 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42    KEY, block BLOB
|   3872: 29 6a 03 07 17 21 21 01 81 1f 74 61 62 6c 65 74   )j...!!...tablet
|   3888: 31 5f 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74   1_contentt1_cont
|   3904: 65 6e 74 04 43 52 45 41 54 45 20 54 41 42 4c 45   ent.CREATE TABLE
|   3920: 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28 64 6f    't1_content'(do
|   3936: 63 69 64 20 49 4e 54 45 47 45 52 20 50 52 39 4d   cid INTEGER PR9M
|   3952: 41 52 59 20 4b 45 59 2c 20 27 63 30 61 27 2c 20   ARY KEY, 'c0a', 
|   3968: 27 63 31 62 27 2c 20 27 63 32 63 27 29 38 02 06   'c1b', 'c2c')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 33   LE t1 USING fts3
|   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 26 0b 48 0e 0f d8 0f af 0f 86 0f 74   ....&.H........t
|     16: 0f 61 0f 4e 0f 2f 0f 0f 0e ef 0e 00 00 00 00 00   .a.N./..........
|   2880: 00 00 00 00 00 00 00 00 81 3f 25 06 00 72 7f 00   .........?%..r..
|   2896: 00 43 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e   .COMPILER=gcc-5.
|   2912: 34 2e 30 20 32 30 31 36 30 36 30 39 20 44 55 42   4.0 20160609 DUB
|   2928: 55 47 20 45 4e 41 e4 7c 45 20 44 42 53 54 41 54   UG ENA.|E DBSTAT
|   2944: e4 46 54 41 42 20 45 4e 41 42 4c 45 20 46 54 53   .FTAB ENABLE FTS
|   2960: 34 20 45 4e 41 42 4c 45 20 46 54 53 35 20 45 4e   4 ENABLE FTS5 EN
|   2976: 41 42 4c 45 20 47 45 4f 50 4f 4c 59 20 45 4e 41   ABLE GEOPOLY ENA
|   2992: 42 4c 45 20 4a 53 4f 4e 31 20 45 4e 41 42 4c 45   BLE JSON1 ENABLE
|   3008: 20 4d 45 4d 53 59 53 35 20 45 4e 41 42 4c 45 20    MEMSYS5 ENABLE 
|   3024: 42 54 52 45 45 20 4d 41 58 20 4d 45 4d 4f 52 59   BTREE MAX MEMORY
|   3040: 3d 35 30 30 30 30 30 30 30 20 4f 4c 49 54 20 4c   =50000000 OLIT L
|   3056: 4f 41 43 20 45 58 54 45 4e 53 49 4f 4e 21 54 48   OAC EXTENSION!TH
|   3072: 52 45 41 44 53 41 46 45 3d 30 18 24 05 00 25 0f   READSAFE=0.$..%.
|   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 4b 75 3d 30 58 4d 4f 43 41 53 45 17 22   DSAKu=0XMOCASE..
|   3136: 05 00 25 0f 17 54 48 52 45 41 44 53 41 46 46 3d   ..%..THREADSAFF=
|   3152: 30 58 52 54 52 49 4d 1f 21 05 00 33 0f 19 4f 4d   0XRTRIM.!..3..OM
|   3168: 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 52 49 4f   IT LOAD EXTENRIO
|   3184: 4e 58 42 49 4e 41 52 59 0f 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 43 49   MIT LOAD EXTENCI
|   3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17   ONXNOCASE....3..
|   3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53   OMIT LOAD EXTENS
|   3248: 49 4f 4e 58 52 5d 12 49 4d 1f 1e 05 00 33 0f 19   IONXR].IM....3..
|   3264: 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30   MAX MEMORY=50000
|   3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f   000XBINARY....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 4f 4f 43 41 53 45 1e 1c 05 00 33   0000XOOCASE....3
|   3328: 0f 17 4d 41 b8 20 4d 45 4d 4f 52 59 3d 35 30 3c   ..MA. MEMORY=50<
|   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 0d a5 0f 19 45 4e 41 42   INARY.......ENAB
|   3392: 4c 45 20 52 54 52 45 45 58 4e 4f 43 41 53 45 17   LE RTREEXNOCASE.
|   3408: 19 1c 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52   ...%..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 53 59 1a 17 05 00 29 0f 19 45 4e 41 42 4c   NASY....)..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 53 35 58 52 54 52 49 4d 18 14 05 01 25   MSYS5XRTRIM....%
|   3520: 0f 19 45 4e 12 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 09 d9 45 4e 41 42   INARY....%..ENAB
|   3552: 4c 45 20 4a 53 4f 3e 31 58 4e 4f 43 41 53 45 17   LE JSO>1XNOCASE.
|   3568: 13 05 00 25 0f 17 45 4e 40 42 4c 45 20 4a 53 4f   ...%..EN@BLE JSO
|   3584: 4e 31 58 52 54 52 49 4d 1a 12 05 82 29 0f 19 45   N1XRTRIM....)..E
|   3600: 4e 41 42 4c 45 20 47 45 4f 50 4f 4d 59 58 42 49   NABLE GEOPOMYXBI
|   3616: 4e 41 52 59 1a 11 05 c9 29 e8 19 46 4e 41 42 4c   NARY....)..FNABL
|   3632: 48 c0 47 45 4f 50 4f 4c 59 58 4e 74 43 41 53 45   H.GEOPOLYXNtCASE
|   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 19 45 4e 41 42 4c 45 30 46 54 53 35 58 42 49   ..ENABLE0FTS5XBI
|   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 58 4e 4f 4a e1 53 45 16 0e 05   E FTS5XNOJ.SE...
|   3728: 00 23 0f 17 45 4e 41 42 4c 45 20 46 54 53 35 58   .#..ENABLE FTS5X
|   3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42   RTRIM....#..ENAB
|   3760: 4c 45 20 46 54 53 34 58 42 49 4e 41 52 59 17 0b   LE FTS4XBINARY..
|   3776: 05 00 23 0f 19 45 4e 41 42 4c 45 20 46 54 53 34   ..#..ENABLE FTS4
|   3792: 58 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 55 4e   XNOCASE....#..UN
|   3808: 41 42 4c 45 20 46 54 53 34 58 52 54 52 49 4d 1e   ABLE FTS4XRTRIM.
|   3824: 09 05 00 31 0f 19 45 4e 42 42 4c 45 20 44 42 53   ...1..ENBBLE 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 4a 4d 11 06   TAT VTABXRTRJM..
|   3920: 05 f0 17 0f 29 44 45 42 55 47 58 42 49 4e 41 52   ....)DEBUGXBINAR
|   3936: 59 11 05 05 00 17 0e 19 44 45 42 55 47 58 4e 4f   Y.......DEBUGXNO
|   3952: 43 41 53 45 10 04 05 00 17 0f 16 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 3d 67   ...C..COMPILER=g
|   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 06 00 43 0f 17 43   9XNOCASE&...C..C
|   4064: 4f 4d 50 49 4b 45 52 3d 67 63 63 2d 35 2e 34 2e   OMPIKER=gcc-5.4.
|   4080: 30 20 32 30 31 36 30 36 40 39 58 29 54 52 49 4d   0 201606@9X)TRIM
| page 4 offset 12288
|      0: 0d 00 10 00 00 10 00 00 00 00 00 00 00 00 00 00   ................
|     16: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
| page 5 offset 16384
|      0: 0d 00 00 00 02 0b a0 00 0c ad 0b a0 00 00 00 00   ................
|   2976: 82 0a 02 08 08 09 08 08 17 84 06 30 20 32 35 33   ...........0 253
|   2992: 00 01 30 04 25 06 1b 00 00 08 32 30 31 36 30 36   ..0.%.....201606
|   3008: 30 39 03 25 07 00 00 01 34 03 25 05 00 00 01 35   09.%....4.%....5
|   3024: 03 25 04 00 01 07 30 30 30 30 30 30 30 03 25 1a   .%....0000000.%.
|   3040: 00 00 08 63 6f 6d 70 69 6c 65 72 03 25 02 00 00   ...compiler.%...
|   3056: 06 64 62 73 74 61 74 03 25 0a 00 01 04 65 62 75   .dbstat.%....ebu
|   3072: 67 03 25 08 00 00 06 65 6e 61 62 7c 65 09 25 09   g.%....enab|e.%.
|   3088: 05 04 04 04 04 04 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3104: 6e 03 25 1d 00 00 04 66 74 73 34 03 25 0d 00 03   n.%....fts4.%...
|   3120: 01 35 03 25 0f 00 00 03 67 63 63 03 25 03 00 01   .5.%....gcc.%...
|   3136: 06 65 6f 70 6f 6c 79 03 25 11 00 00 05 6a 73 6f   .eopoly.%....jso
|   3152: 6e 31 03 25 13 00 00 04 6c 6f 61 64 03 25 1c 00   n1.%....load.%..
|   3168: 00 03 6d 61 78 03 25 18 00 01 05 65 6e 6f 72 79   ..max.%....enory
|   3184: 03 25 19 00 03 04 ce 79 73 4d 03 25 15 00 00 04   .%.....ysM.%....
|   3200: 6f 6d 69 74 03 25 1b 00 00 05 72 74 72 65 65 03   omit.%....rtree.
|   3216: 25 17 00 00 0a 74 68 72 65 61 64 73 61 66 65 03   %....threadsafe.
|   3232: 25 0e 00 00 04 76 74 61 62 03 25 0b 00 86 50 01   %....vtab.%...P.
|   3248: 08 08 08 08 08 17 8d 12 30 20 38 33 35 00 01 30   ........0 835..0
|   3264: 12 01 06 00 01 06 00 01 06 00 1f 03 00 01 03 00   ................
|   3280: 01 03 00 00 08 32 30 31 36 30 36 30 39 09 01 07   .....20160609...
|   3296: 00 01 07 00 01 07 00 00 01 34 09 01 05 00 01 05   .........4......
|   3312: 00 01 05 00 00 01 35 09 01 04 00 01 04 00 01 04   ......5.........
|   3328: 00 01 07 30 30 30 30 30 30 30 09 1c 04 00 01 04   ...0000000......
|   3344: 00 01 04 00 00 06 62 69 6e 61 72 79 3c 03 01 02   ......binary<...
|   3360: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3376: 00 03 01 02 02 00 02 f1 02 02 00 03 01 02 02 00   ................
|   3392: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03   ................
|   3408: 01 01 f2 00 03 01 02 02 00 00 08 63 6f 6d 70 69   ...........compi
|   3424: 6c 65 72 09 01 02 00 01 02 00 01 02 00 00 06 67   ler............g
|   3440: d2 73 74 61 74 09 07 03 00 01 03 00 01 03 00 01   .stat...........
|   3456: 04 65 62 75 67 09 04 02 00 01 02 00 01 02 00 00   .ebug...........
|   3472: 06 65 6e 6f 82 6c 65 3f 07 02 00 01 02 00 01 02   .eno.le?........
|   3488: b0 01 02 00 01 02 00 11 0a f0 01 02 00 01 02 00   ................
|   3504: 01 02 00 01 02 00 01 02 00 01 a6 00 01 02 00 02   ................
|   3520: 02 05 51 02 00 01 02 00 01 02 00 01 02 00 01 02   ..Q.............
|   3536: 00 01 02 00 01 02 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3552: 6e 09 1f 04 00 01 04 00 00 04 00 00 04 66 74 73   n............fts
|   3568: 34 09 0a 03 00 01 03 00 01 03 00 03 01 35 09 0d   4............5..
|   3584: 03 00 01 03 00 01 03 00 00 03 67 63 63 09 01 03   ..........gcc...
|   3600: 00 01 03 00 01 03 00 01 06 65 6f 70 73 6c 79 09   .........eopsly.
|   3616: 10 03 00 01 03 00 01 03 00 00 05 6a 73 6f 6e 31   ...........json1
|   3632: 09 13 03 00 01 03 00 01 03 00 00 04 6c 6f 61 64   ............load
|   3648: 09 1f 03 00 01 03 00 01 03 00 00 03 6d 61 78 09   ............max.
|   3664: 1c 02 00 01 02 00 01 02 00 01 05 65 6d 6f 72 79   ...........emory
|   3680: 09 1c 03 00 01 03 00 01 03 00 03 04 73 79 73 35   ............sys5
|   3696: 09 16 03 00 01 03 00 01 03 00 00 06 6e 6f 63 61   ............noca
|   3712: 73 65 3c 02 01 02 02 00 03 01 12 02 00 03 01 02   se<.............
|   3728: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3744: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
|   3760: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 00   ................
|   3776: 04 6f 6d 69 74 09 1f 02 00 01 02 00 01 02 00 00   .omit...........
|   3792: 05 72 74 72 65 65 09 19 03 00 01 03 00 01 03 00   .rtree..........
|   3808: 03 02 69 6d 3c 01 01 02 02 00 03 01 02 02 00 03   ..im<...........
|   3824: 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01   ................
|   3840: 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02   ................
|   3856: 02 00 03 01 02 02 01 e3 01 02 02 00 03 01 02 02   ................
|   3872: 00 00 0a 74 68 72 65 61 64 73 61 66 65 09 22 02   ...threadsafe...
|   3888: 00 01 02 00 01 02 00 00 04 76 74 61 62 09 07 04   .........vtab...
|   3904: 00 01 04 00 01 04 00 00 01 78 b4 01 01 01 01 02   .........x......
|   3920: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   3936: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   3952: 01 01 01 f0 01 01 01 07 30 01 01 01 02 00 01 01   ........0.......
|   3968: 01 02 00 ea 01 01 02 00 01 01 01 02 00 11 01 01   ................
|   3984: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4000: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   4016: 01 01 01 01 ff 01 01 01 02 00 01 01 01 02 00 01   ................
|   4032: 01 01 02 00 01 11 01 02 00 01 01 01 02 00 01 01   ................
|   4048: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   4064: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4080: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
| page 6 offset 20480
|      0: 0a 00 00 00 02 0f f5 00 0f fb 0f f5 01 00 00 00   ................
|   4080: 00 00 00 00 00 05 04 08 09 01 02 04 04 08 08 09   ................
| page 7 offset 24576
|      0: 0d 00 00 00 05 0f b8 00 0e f4 0f e9 10 d6 0f c7   ................
|   4016: 00 00 00 00 00 00 00 00 0f 85 02 23 61 75 74 6f   ...........#auto
|   4032: 6d 65 72 67 65 3d 35 0d 04 02 23 6d 65 72 67 65   merge=5...#merge
|   4048: 3d 31 00 00 00 00 00 00 00 00 00 00 00 00 00 00   =1..............
| end crash-23ddd777a03bfd.db
}]} {}

do_catchsql_test 27.2 {
  PRAGMA writable_schema = 1;
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x GLOB 2.16770 FROM x)
    INSERT INTO t1(a) SELECT randomblob(3000) FROM t2 ;
} {1 {database disk image is malformed}}
do_catchsql_test 27.3 {
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT 3+x FROM c WHERE x<2.653)
    INSERT INTO t1(a) SELECT randomblob(-current_time) FROM c;
} {1 {database disk image is malformed}}
do_catchsql_test 27.4 {
  UPDATE t1 SET b=quote((true) ) WHERE t1 MATCH 'h*h*';
} {0 {}}
do_catchsql_test 27.5 {
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT 3+x FROM c WHERE x<2.653)
    INSERT INTO t1(a) SELECT randomblob(-current_time) FROM c;
} {1 {database disk image is malformed}}
do_catchsql_test 27.5 {
  INSERT INTO t1(t1) SELECT x FROM t2;
} {1 {database disk image is malformed}}
do_catchsql_test 27.6 {
  INSERT INTO t1(t1) SELECT x FROM t2;
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
reset_db
do_test 28.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
.open --hexdb
| size 28672 pagesize 4096 filename crash-159ac1ca51ed55.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 0e b1 00 06 0d a4 00 0f 8d 0f 21   ...............!
|    112: 0e b9 0d c8 0e 7e 0d a4 00 00 00 00 00 00 00 00   .....~..........
|   3488: 00 00 00 00 22 07 06 17 11 11 01 31 74 61 62 6c   ...........1tabl
|   3504: 65 74 32 74 32 07 43 52 45 41 54 45 20 54 41 42   et2t2.CREATE TAB
|   3520: 4c 45 20 74 32 28 78 29 81 33 05 07 17 1f 1f 01   LE t2(x).3......
|   3536: 82 35 74 61 62 6c 65 74 31 5f 73 65 67 64 69 72   .5tablet1_segdir
|   3552: 74 31 5f 73 65 67 64 69 72 05 43 52 45 41 54 45   t1_segdir.CREATE
|   3568: 20 54 41 42 4c 45 20 27 74 31 5f 73 65 67 64 69    TABLE 't1_segdi
|   3584: 72 27 28 6c 65 76 65 6c 20 49 4e 54 45 47 45 52   r'(level INTEGER
|   3600: 2c 69 64 78 20 49 4e 54 45 47 45 52 2c 73 74 61   ,idx INTEGER,sta
|   3616: 72 74 5f 62 6c 6f 63 6b 20 49 4e 54 45 47 45 52   rt_block INTEGER
|   3632: 2c 6c 65 61 76 65 73 5f 65 6e 64 5f 62 6c 6f 63   ,leaves_end_bloc
|   3648: 6b 20 49 4e 54 45 47 45 52 2c 65 6e 64 5f 62 6c   k INTEGER,end_bl
|   3664: 6f 63 6b 20 49 4e 54 45 47 45 52 2c 72 6f 6f 74   ock INTEGER,root
|   3680: 20 42 4c 4f 42 2c 50 52 49 4d 41 52 59 20 4b 45    BLOB,PRIMARY KE
|   3696: 59 28 6c 65 76 65 6c 2c 20 69 64 78 29 29 31 06   Y(level, idx))1.
|   3712: 06 17 45 1f 01 00 69 6e 64 65 78 73 71 6c 69 74   ..E...indexsqlit
|   3728: 65 5f 61 75 74 6f 69 6e 64 65 78 5f 74 31 5f 73   e_autoindex_t1_s
|   3744: 65 67 64 69 72 5f 31 74 31 5f 73 65 67 64 69 72   egdir_1t1_segdir
|   3760: 06 0f c7 00 08 00 10 00 00 66 04 07 17 23 23 01   .........f...##.
|   3776: 81 13 74 61 62 6c 65 74 31 5f 73 65 67 6d 65 6e   ..tablet1_segmen
|   3792: 64 73 74 31 5f 73 65 67 6d 65 6e 74 73 04 43 52   dst1_segments.CR
|   3808: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 73   EATE TABLE 't1_s
|   3824: 65 67 6d 65 6e 74 73 27 28 62 6c 6f 63 6b 69 64   egments'(blockid
|   3840: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59    INTEGER PRIMARY
|   3856: 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42    KEY, block BLOB
|   3872: 29 6a 03 07 17 21 21 01 81 1f 74 61 62 6c 65 74   )j...!!...tablet
|   3888: 31 4f 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74   1Ocontentt1_cont
|   3904: 65 6e 74 03 43 52 45 41 54 45 20 54 41 42 4c 45   ent.CREATE TABLE
|   3920: 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28 64 6f    't1_content'(do
|   3936: 63 69 64 20 49 4e 54 45 43 a5 52 20 50 52 39 4d   cid INTEC.R PR9M
|   3952: 41 52 59 20 4b 45 59 2c 20 27 63 30 61 27 2c 20   ARY KEY, 'c0a', 
|   3968: 27 63 31 62 27 2c 20 27 63 32 63 27 29 38 02 06   'c1b', 'c2c')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 33   LE t1 USING fts3
|   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 26 0b 48 00 00 00 00 00 00 00 00 00   ....&.H.........
|   2880: 00 00 00 00 00 00 00 00 81 3f 25 06 00 72 7f 00   .........?%..r..
|   2896: 00 43 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e   .COMPILER=gcc-5.
|   2912: 34 2e 30 20 32 30 31 36 30 36 30 39 20 44 55 42   4.0 20160609 DUB
|   2928: 55 47 20 45 4e 41 e4 7c 45 20 44 42 53 54 41 54   UG ENA.|E DBSTAT
|   2944: e4 46 54 41 42 20 45 4e 41 42 4c 45 20 46 54 53   .FTAB ENABLE FTS
|   2960: 34 20 45 4e 41 42 4c 45 20 46 54 53 35 20 45 4e   4 ENABLE FTS5 EN
|   2976: 41 42 1f 45 20 47 45 4f 50 4f 4c 59 20 45 4e 41   AB.E GEOPOLY ENA
|   2992: 42 4c 45 20 4a 53 4f 4e 31 20 45 4e 41 42 4c 45   BLE JSON1 ENABLE
|   3008: 20 4d 45 4d 53 59 53 35 20 45 4e 41 42 4c 45 20    MEMSYS5 ENABLE 
|   3024: 42 54 52 45 45 20 4d 41 58 20 4d 45 4d 4f 52 59   BTREE MAX MEMORY
|   3040: 3d 35 30 30 30 30 30 30 30 20 4f 4c 49 54 20 4c   =50000000 OLIT L
|   3056: 4f 41 43 20 45 58 54 45 4e 53 49 4f 4e 21 54 48   OAC EXTENSION!TH
|   3072: 52 45 41 44 53 41 46 45 3d 2f 18 24 05 00 25 0f   READSAFE=/.$..%.
|   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 4b 75 3d 30 58 4d 4f 43 41 53 45 17 22   DSAKu=0XMOCASE..
|   3136: 05 00 25 0f 17 54 48 52 45 41 44 53 41 46 46 3d   ..%..THREADSAFF=
|   3152: 30 58 52 54 52 49 4d 1f 21 05 00 33 0f 19 4f 4d   0XRTRIM.!..3..OM
|   3168: 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 52 49 4f   IT LOAD EXTENRIO
|   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 53 49   MIT LOAD EXTENSI
|   3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17   ONXNOCASE....3..
|   3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53   OMIT LOAD EXTENS
|   3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19   IONXRTRIM....3..
|   3264: 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30   MAX MEMORY=50000
|   3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f   000XBINARY....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 33   0000XNOCASE....3
|   3328: 0f 17 4d 42 b8 20 4d 45 4d 4f 52 59 3d 35 30 30   ..MB. MEMORY=500
|   3344: 30 30 30 30 30 58 52 54 52 4a 4d 18 1b 05 00 25   00000XRTRJM....%
|   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 0d a5 0f 19 45 4e 41 42   INARY.......ENAB
|   3392: 4c 45 20 52 54 52 45 45 58 4e 4f 43 41 53 45 17   LE RTREEXNOCASE.
|   3408: 19 1c 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52   ...%..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 53 35 58 52 54 52 49 4d 18 14 05 01 25   MSYS5XRTRIM....%
|   3520: 0f 19 45 4e 12 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 09 d9 45 4e 41 42   INARY....%..ENAB
|   3552: 4c 45 20 4a 53 4f 3e 31 58 4e 4f 43 41 53 45 17   LE JSO>1XNOCASE.
|   3568: 13 05 00 25 0f 17 44 4e 40 42 4c 45 20 4a 53 4f   ...%..DN@BLE JSO
|   3584: 4e 31 58 52 54 52 49 4d 1a 12 05 82 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 c9 29 e8 19 46 4e 41 42 4c   NARY....)..FNABL
|   3632: 48 c0 47 45 4f 50 4f 4c 59 58 4e 74 43 41 53 45   H.GEOPOLYXNtCASE
|   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 19 45 4e 41 42 4c 45 30 46 54 53 35 58 42 49   ..ENABLE0FTS5XBI
|   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 58 4e 4f 43 41 53 45 16 0e 05   E FTS5XNOCASE...
|   3728: 00 23 0f 17 45 4e 41 42 4c 45 20 46 54 53 35 58   .#..ENABLE FTS5X
|   3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42   RTRIM....#..ENAB
|   3760: 4c 45 20 46 54 53 34 58 42 49 4e 41 52 59 17 0b   LE FTS4XBINARY..
|   3776: 04 ff 23 0f 19 45 4e 41 42 4c 45 20 46 54 53 34   ..#..ENABLE FTS4
|   3792: 58 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 45 4e   XNOCASE....#..EN
|   3808: 41 42 4c 45 20 46 54 53 34 58 52 54 52 49 4d 1e   ABLE FTS4XRTRIM.
|   3824: 09 05 00 31 0f 19 45 4e 42 42 4c 45 20 44 42 53   ...1..ENBBLE 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 4a 4d 11 06   TAT VTABXRTRJM..
|   3920: 05 f0 17 0f 19 44 45 42 55 47 58 42 49 4e 41 52   .....DEBUGXBINAR
|   3936: 59 11 05 09 b0 17 0e 19 44 45 42 55 47 58 4e 4f   Y.......DEBUGXNO
|   3952: 43 41 53 45 10 04 05 00 17 0f 16 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 4d 67   ...C..COMPILERMg
|   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 06 00 43 0f 17 43   9XNOCASE&...C..C
|   4064: 4f 4d 50 49 4b 45 52 3d 67 63 63 2d 35 2e 34 2e   OMPIKER=gcc-5.4.
|   4080: 30 20 32 30 31 36 30 36 40 39 58 29 54 52 49 4d   0 201606@9X)TRIM
| page 4 offset 12288
|      0: 0d 00 10 00 00 10 00 00 00 00 00 00 00 00 00 00   ................
| page 5 offset 16384
|      0: 0d 00 00 00 02 0b a0 00 00 00 00 00 00 00 00 00   ................
|   2976: 82 0a 02 08 08 09 08 08 17 84 06 30 20 32 35 33   ...........0 253
|   2992: 00 01 30 04 25 06 1b 00 00 08 32 30 31 36 30 36   ..0.%.....201606
|   3008: 30 39 03 25 07 00 00 01 34 03 25 05 00 00 01 35   09.%....4.%....5
|   3024: 03 25 04 00 4d 07 30 30 30 30 30 30 30 03 25 1a   .%..M.0000000.%.
|   3040: 00 00 08 63 6f 6d 70 69 6c 65 72 03 25 02 00 00   ...compiler.%...
|   3056: 06 64 62 73 74 61 74 03 25 0a 00 01 04 65 62 75   .dbstat.%....ebu
|   3072: 67 03 25 08 00 00 06 65 6e 61 62 6c 65 09 25 09   g.%....enable.%.
|   3088: 05 04 04 04 04 04 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3104: 6e 03 25 1d 00 00 04 66 74 73 34 03 25 0d 00 03   n.%....fts4.%...
|   3120: 01 35 03 25 0f 00 00 03 67 63 63 03 25 03 00 01   .5.%....gcc.%...
|   3136: 06 65 6f 70 6f 6c 79 03 25 10 ff ff f5 6a 73 6f   .eopoly.%....jso
|   3152: 6e 31 03 25 13 00 00 04 6c 6f 61 64 03 25 1c 00   n1.%....load.%..
|   3168: 00 03 6d 71 78 03 25 18 00 01 05 65 6e 6f 72 79   ..mqx.%....enory
|   3184: 03 25 19 00 03 04 ce 79 73 4d 03 25 15 00 00 04   .%.....ysM.%....
|   3200: 6f 6d 69 74 03 25 1b 00 00 05 72 74 72 65 65 03   omit.%....rtree.
|   3216: 25 17 00 00 0a 7f 08 72 65 61 64 73 61 66 65 03   %......readsafe.
|   3232: 25 0e 00 00 04 76 75 61 62 03 25 0b 00 86 50 01   %....vuab.%...P.
|   3248: 08 08 08 08 08 17 8d 12 30 20 38 33 35 00 01 30   ........0 835..0
|   3264: 12 01 06 00 01 06 00 01 06 00 1f 03 00 01 03 09   ................
|   3280: 51 03 00 00 09 32 30 31 36 30 36 30 39 09 01 07   Q....20160609...
|   3296: 00 01 07 00 01 07 00 00 01 34 09 01 05 00 01 05   .........4......
|   3312: 00 01 05 00 00 01 35 09 01 04 00 01 03 ff 01 04   ......5.........
|   3328: 00 01 07 30 30 30 30 30 30 30 09 1c 04 00 01 04   ...0000000......
|   3344: 00 01 04 00 00 06 62 69 6e 61 72 79 3c 03 01 02   ......binary<...
|   3360: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3376: 00 03 01 02 02 00 02 f1 02 02 00 03 01 02 02 00   ................
|   3392: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03   ................
|   3408: 01 02 02 00 03 01 02 02 00 00 08 63 6f 6d 70 69   ...........compi
|   3424: 6c 65 72 09 01 02 00 01 02 00 01 02 00 00 06 67   ler............g
|   3440: d2 73 74 61 74 09 07 03 00 01 03 00 01 03 00 01   .stat...........
|   3456: 04 65 62 75 67 09 04 02 00 01 02 00 01 02 00 00   .ebug...........
|   3472: 06 65 6e 6f 82 6c 65 3f 07 02 00 01 02 00 01 02   .eno.le?........
|   3488: b0 01 02 00 00 f2 00 11 02 00 01 02 00 01 02 00   ................
|   3504: 01 02 00 01 02 00 01 02 00 01 a6 00 01 02 00 01   ................
|   3520: 02 05 51 02 00 01 02 00 01 02 00 01 02 00 01 02   ..Q.............
|   3536: 00 01 02 00 01 02 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3552: 6e 09 1f 04 00 01 04 00 00 04 00 00 04 66 74 73   n............fts
|   3568: 34 09 0a 03 00 01 03 00 01 03 00 03 01 35 09 0d   4............5..
|   3584: 03 00 01 03 00 01 03 00 00 03 67 63 63 09 01 03   ..........gcc...
|   3600: 00 01 03 00 01 03 00 01 06 65 6f 70 73 6c 79 09   .........eopsly.
|   3616: 10 03 00 01 03 00 01 03 00 00 05 6a 73 6f 6e 31   ...........json1
|   3632: 09 13 03 00 01 03 00 01 03 00 00 04 6c 6f 61 64   ............load
|   3648: 09 1f 03 00 01 03 00 01 03 00 00 03 6d 61 78 09   ............max.
|   3664: 1c 02 00 01 02 00 01 02 00 01 05 65 6d 6f 72 79   ...........emory
|   3680: 09 1c 03 00 01 03 00 01 03 00 03 04 73 79 73 35   ............sys5
|   3696: 09 16 03 00 01 03 00 01 03 00 00 06 6e 6f 63 61   ............noca
|   3712: 73 65 3c 02 01 02 02 00 03 01 12 02 00 03 01 02   se<.............
|   3728: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3744: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
|   3760: 0f 71 02 02 00 03 01 02 02 00 03 6f 02 02 00 00   .q.........o....
|   3776: 04 6f 6d 69 74 09 1f 02 00 01 02 00 01 02 00 00   .omit...........
|   3792: 05 72 74 72 65 65 09 19 03 00 01 03 00 01 03 00   .rtree..........
|   3808: 03 02 69 6d 3c 01 01 02 02 00 03 01 02 02 00 03   ..im<...........
|   3824: 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01   ................
|   3840: 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02   ................
|   3856: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3872: 00 00 0a 74 68 72 65 61 64 73 61 66 65 09 22 02   ...threadsafe...
|   3888: 00 01 02 00 01 02 00 00 04 76 74 61 62 09 07 04   .........vtab...
|   3904: 00 01 04 00 01 04 00 00 01 78 b4 01 01 01 01 02   .........x......
|   3920: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   3936: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   3952: 01 01 02 00 01 01 01 07 30 01 01 01 02 00 01 01   ........0.......
|   3968: 01 02 00 11 01 01 02 00 01 01 01 02 00 11 01 01   ................
|   3984: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4000: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   4016: 01 01 01 01 ff 01 01 01 02 00 01 01 01 02 00 01   ................
|   4032: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   4048: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   4064: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4080: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
| page 6 offset 20480
|      0: 0a 00 00 00 02 0f f5 00 00 00 00 00 00 00 00 00   ................
|   4080: 00 00 00 00 00 05 04 08 09 01 02 04 04 08 08 09   ................
| page 7 offset 24576
|      0: 0d 00 00 00 05 0f b8 00 0e f4 0f e9 10 d6 0f c7   ................
|   4016: 00 00 00 00 00 00 00 00 0d 05 02 23 61 75 74 6f   ...........#auto
|   4032: 6d 65 72 67 65 3d 35 0d 04 02 23 6d 65 72 67 65   merge=5...#merge
|   4048: 3d 31 00 00 00 00 00 00 00 00 00 00 00 00 00 00   =1..............
| end crash-159ac1ca51ed55.db
}]} {}

do_catchsql_test 28.1 {
  PRAGMA writable_schema = 1;
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT 3+x FROM c WHERE x<72)
    INSERT INTO t1(a) SELECT randomblob(2829) FROM c;
} {1 {database disk image is malformed}}

do_catchsql_test 28.2 {
  UPDATE t1 SET b=quote((true) ) WHERE t1 MATCH 'h';
} {0 {}}

do_catchsql_test 28.3 {
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT 3+x FROM c WHERE x<72)
    INSERT INTO t1(a) SELECT randomblob(2829) FROM c;
} {1 {database disk image is malformed}}

do_catchsql_test 28.4 {
  WITH c(x) AS (VALUES(1) UNION ALL SELECT 3<<x FROM c WHERE x<72)
    INSERT INTO t1(a) SELECT randomblob(2829) FROM c;
} {0 {}}

do_catchsql_test 28.5 {
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT 3+x FROM c WHERE x<72)
    INSERT INTO t1(a) SELECT randomblob(2829) FROM c;
} {1 {database disk image is malformed}}

do_catchsql_test 28.6 {
  WITH c(x) AS (VALUES(1) UNION ALL SELECT 3<<x FROM c WHERE x<72)
    INSERT INTO t1(a) SELECT randomblob(2829) FROM c;
} {0 {}}

do_catchsql_test 28.7 {
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+3 FROM c WHERE x<72)
    INSERT INTO t1(a) SELECT randomblob(2829) FROM c;
} {1 {database disk image is malformed}}

do_catchsql_test 28.8 {
  INSERT INTO t1(t1) SELECT x FROM t2;
} {0 {}}

#-------------------------------------------------------------------------
#
reset_db
do_test 29.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
.open --hexdb
| size 28672 pagesize 4096 filename crash-53f41622dd3bf6.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 0e b1 00 06 0d a4 00 0f 8d 0f 21   ...............!
|    112: 0e b9 0d c8 0e 7e 0d a4 00 00 00 00 00 00 00 00   .....~..........
|   3488: 00 00 00 00 22 07 06 17 11 11 01 31 74 61 62 6c   ...........1tabl
|   3504: 65 74 32 74 32 07 43 52 45 41 54 45 20 54 41 42   et2t2.CREATE TAB
|   3520: 4c 45 20 74 32 28 78 29 81 33 05 07 17 1f 1f 01   LE t2(x).3......
|   3536: 82 35 74 61 62 6c 65 74 31 5f 73 65 67 54 69 72   .5tablet1_segTir
|   3552: 74 31 5f 73 65 67 64 69 72 05 43 52 45 41 54 45   t1_segdir.CREATE
|   3568: 20 54 41 42 4c 45 20 27 74 31 5f 73 65 67 64 69    TABLE 't1_segdi
|   3584: 72 27 28 6c 65 76 65 6c 20 49 4e 54 45 47 45 52   r'(level INTEGER
|   3600: 2c 69 64 78 20 49 4d 54 45 47 45 52 2c 73 74 61   ,idx IMTEGER,sta
|   3616: 72 74 5f 62 6c 6f 63 6b 20 49 4e 54 45 47 45 52   rt_block INTEGER
|   3632: 2c 6c 65 61 76 65 73 5f 65 6e 64 5f 62 6c 6f 63   ,leaves_end_bloc
|   3648: 6b 20 49 4e 54 45 47 45 52 2c 65 6e 64 5f 62 6c   k INTEGER,end_bl
|   3664: 6f 63 6b 20 49 4e 54 45 47 45 52 2c 72 6f 6f 74   ock INTEGER,root
|   3680: 20 42 4c 4f 42 2c 50 52 49 4d 41 52 59 20 4b 45    BLOB,PRIMARY KE
|   3696: 59 28 6c 65 76 65 6c 2c 20 69 64 78 29 29 31 06   Y(level, idx))1.
|   3712: 06 17 45 1f 01 00 69 6e 64 65 78 73 71 6c 69 74   ..E...indexsqlit
|   3728: 65 5f 61 75 74 6f 69 6e 64 65 78 5f 74 31 5f 73   e_autoindex_t1_s
|   3744: 65 67 64 69 72 5f 31 74 31 5f 73 65 67 64 69 72   egdir_1t1_segdir
|   3760: 06 0f c7 00 08 00 00 00 00 66 04 07 17 23 23 01   .........f...##.
|   3776: 81 13 74 61 62 6c 65 74 31 5f 73 65 67 6d 65 6e   ..tablet1_segmen
|   3792: 74 73 74 31 5f 73 65 67 6d 65 6e 74 73 04 43 52   tst1_segments.CR
|   3808: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 73   EATE TABLE 't1_s
|   3824: 65 67 6d 65 6e 74 73 27 28 62 6c 6f 63 6b 69 64   egments'(blockid
|   3840: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59    INTEGER PRIMARY
|   3856: 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42    KEY, block BLOB
|   3872: 29 6a 03 07 17 21 21 01 81 1f 74 61 62 6c 65 74   )j...!!...tablet
|   3888: 31 5f 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74   1_contentt1_cont
|   3904: 65 6e 74 03 43 52 45 41 54 45 20 54 41 42 4c 45   ent.CREATE TABLE
|   3920: 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28 64 6f    't1_content'(do
|   3936: 63 69 64 20 49 4e 54 45 47 45 52 20 50 52 39 4d   cid INTEGER PR9M
|   3952: 41 52 59 20 4b 45 59 2c 20 27 63 30 61 27 2c 20   ARY KEY, 'c0a', 
|   3968: 27 63 31 62 27 2c 20 27 63 32 63 27 29 38 12 06   'c1b', 'c2c')8..
|   3984: 17 11 11 08 5f 74 61 6b 3c 65 74 31 74 31 43 52   ...._tak<et1t1CR
|   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 33   LE t1 USING fts3
|   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 25 0b 48 00 0f d8 0f af 0f 86 0f 74   ....%.H........t
|     16: 0f 61 0f 4e 0f 2f 0f 0f 0e ef 0e d7 0e be 0e a5   .a.N./..........
|     32: 0e 8d 0e 74 0e 5b 0e 40 0e 24 0e 08 0d ef 0d d5   ...t.[.@.$......
|     48: 0d bb 0d a0 0d 84 03 28 0d 4f 0d 35 0d 1b 0c fb   .......(.O.5....
|     64: 0c da 0c b9 0c 99 0c 78 0c 57 0c 3e 0c 24 0c 0a   .......x.W.>.$..
|     80: 0b 48 00 00 00 00 00 00 00 00 00 00 00 00 00 00   .H..............
|   2880: 00 00 00 00 00 00 00 00 81 3f 25 06 00 72 7f 00   .........?%..r..
|   2896: 00 43 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e   .COMPILER=gcc-5.
|   2912: 34 2e 30 20 32 30 31 36 30 36 30 39 21 44 45 42   4.0 20160609!DEB
|   2928: 55 47 20 45 4e 41 42 4c 45 20 44 42 53 54 41 54   UG ENABLE DBSTAT
|   2944: 20 56 54 41 42 20 45 4e 41 42 4c 46 20 46 54 53    VTAB ENABLF FTS
|   2960: 34 20 45 4e 41 42 4c 45 20 46 54 53 35 20 45 4e   4 ENABLE FTS5 EN
|   2976: 41 42 4c 45 20 47 45 4f 50 4f 4c 59 20 45 4e 41   ABLE GEOPOLY ENA
|   2992: 42 4c 55 20 4a 53 4f 4e 31 20 45 4e 41 42 4c 45   BLU JSON1 ENABLE
|   3008: 20 4d 45 4d 53 59 53 35 20 45 4e 41 42 4c 45 20    MEMSYS5 ENABLE 
|   3024: 52 54 52 45 45 56 4d 41 58 20 4d 45 4d 4f 52 59   RTREEVMAX MEMORY
|   3040: 3d 35 30 30 30 30 30 30 30 20 4f 4d 49 54 20 4c   =50000000 OMIT L
|   3056: 4f 42 43 20 45 58 54 45 4e 53 49 4f 4e 20 54 48   OBC EXTENSION TH
|   3072: 52 45 41 44 53 41 46 45 3d 40 18 24 05 00 25 0f   READSAFE=@.$..%.
|   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 31 58 4e 4f 43 41 53 45 17 22   DSAFE=1XNOCASE..
|   3136: 05 00 25 0f 17 54 48 52 45 41 44 43 41 46 45 3d   ..%..THREADCAFE=
|   3152: 30 58 52 54 52 49 4d 1f 21 05 00 33 0f 19 4f 4d   0XRTRIM.!..3..OM
|   3168: 49 54 20 4c 4f 41 44 20 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 53 48   MIT LOAD EXTENSH
|   3216: cf 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17   .NXNOCASE....3..
|   3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53   OMIT LOAD EXTENS
|   3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19   IONXRTRIM....3..
|   3264: 4d 41 58 20 4d 45 4d 4f 52 59 2d 35 30 30 30 30   MAX MEMORY-50000
|   3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f   000XBINARY....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 33   0000XNOCASE....3
|   3328: 0f 17 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30   ..MAX 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 49 18 1a 05 0d a5 0f 19 45 4e 41 42   INARI.......ENAB
|   3392: 4c 45 20 52 54 52 45 45 58 4e 4f be 31 53 45 17   LE RTREEXNO.1SE.
|   3408: 19 05 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 51   ...%..ENABLE RTQ
|   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 53 37 f8 52 54 52 49 4d 18 14 05 00 25   MSYS7.RTRIM....%
|   3520: 0f 19 45 4e 41 42 4c 45 20 4a 53 4f 4e 31 58 42   ..ENABLE 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 3e 31 58 4e 4f 43 41 53 45 17   LE JSO>1XNOCASE.
|   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 4e 41 42 4c   NARY....)..ENABL
|   3632: 48 c0 47 45 4f 50 4f 4c 40 58 4e 4f 43 41 53 45   H.GEOPOL@XNOCASE
|   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 51 49 4d 17 0f 05 00 23   OPOLYXRTQIM....#
|   3680: 0f 19 45 4e 41 42 4c 45 20 46 54 53 35 58 42 49   ..ENABLE FTS5XBI
|   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 58 4e 4f 43 41 53 45 16 0d 05   E FTS5XNOCASE...
|   3728: 00 23 0f 17 45 4e 41 42 4c 45 20 46 54 53 35 58   .#..ENABLE FTS5X
|   3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42   RTRIM....#..ENAB
|   3760: 4c 45 20 46 54 53 34 58 42 49 4d 41 52 59 17 0b   LE FTS4XBIMARY..
|   3776: 05 00 23 0f 19 45 4e 31 42 4c 45 20 46 1a 53 34   ..#..EN1BLE F.S4
|   3792: 58 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 45 4e   XNOCASE....#..EN
|   3808: 41 42 4c 45 20 46 54 53 34 58 52 54 52 49 4d 1e   ABLE FTS4XRTRIM.
|   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 96 54 20 56 54 41 42 58 52 54 52 49 4d 11 06   T.T VTABXRTRIM..
|   3920: 05 00 17 0f 1e e4 45 42 55 47 58 42 49 4e 41 52   ......EBUGXBINAR
|   3936: 59 11 05 05 00 17 0e 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 01 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 3d 67   ...C..COMPILER=g
|   4032: 63 63 2d 35 2e 34 2e 30 40 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 43   9XNOCASE&...C..C
|   4064: 4f 4d 4f 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e   OMOILER=gcc-5.4.
|   4080: 30 20 32 30 31 36 30 36 30 39 58 52 54 52 49 4d   0 20160609XRTRIM
| page 4 offset 12288
|      0: 0d 00 00 01 00 10 00 00 00 00 00 00 00 00 00 00   ................
| page 5 offset 16384
|      0: 0d 00 00 00 02 0b a0 00 0c ad 0b a0 00 00 00 00   ................
|   2976: 82 0a 02 08 08 09 08 08 17 84 06 30 20 32 35 33   ...........0 253
|   2992: 00 01 30 04 25 06 1b 00 00 08 32 30 31 36 30 36   ..0.%.....201606
|   3008: 30 39 03 25 07 00 00 01 34 03 25 05 00 00 01 35   09.%....4.%....5
|   3024: 03 25 04 00 01 07 30 30 30 30 30 30 30 03 25 1a   .%....0000000.%.
|   3040: 00 00 08 63 6f 6d 70 69 6c 65 72 03 25 02 00 00   ...compiler.%...
|   3056: 06 64 62 73 74 61 74 03 25 0a 00 01 04 65 62 75   .dbstat.%....ebu
|   3072: 67 03 25 08 00 00 06 65 6e 61 62 6c 65 09 25 09   g.%....enable.%.
|   3088: 05 04 04 04 04 04 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3104: 6e 03 25 1d 00 00 04 66 74 73 34 03 25 0d 00 03   n.%....fts4.%...
|   3120: 01 35 03 25 0f 00 00 03 67 63 63 03 25 03 00 01   .5.%....gcc.%...
|   3136: 06 65 6f 70 6f 6c 79 03 25 11 00 00 05 6a 73 6f   .eopoly.%....jso
|   3152: 6e 31 03 25 13 00 00 04 6c 6f 61 64 03 25 1c 00   n1.%....load.%..
|   3168: 00 03 6d 61 78 03 25 18 00 01 05 65 6d 6f 72 79   ..max.%....emory
|   3184: 03 25 19 00 03 04 73 79 73 4d 03 25 15 00 00 04   .%....sysM.%....
|   3200: 6e 6d 69 74 03 25 1b 00 00 05 72 74 72 65 65 03   nmit.%....rtree.
|   3216: 25 17 00 00 0a 74 68 72 65 61 64 73 61 66 65 03   %....threadsafe.
|   3232: 25 0e 00 00 04 76 74 61 62 03 25 0b 00 86 50 01   %....vtab.%...P.
|   3248: 08 08 08 08 08 17 8d 12 30 20 38 33 35 00 01 30   ........0 835..0
|   3264: 12 01 06 00 01 06 00 01 06 00 1f 03 00 01 03 00   ................
|   3280: 01 03 00 00 08 32 30 31 36 30 36 30 39 09 01 bd   .....20160609...
|   3296: 00 01 07 00 01 07 00 00 01 34 09 01 05 00 01 05   .........4......
|   3312: 00 01 06 00 00 01 35 09 01 04 00 01 04 00 02 04   ......5.........
|   3328: 00 01 07 30 30 e6 30 30 30 30 09 1c 04 00 01 04   ...00.0000......
|   3344: 00 01 04 00 00 06 62 69 6e 61 72 79 3c 03 01 02   ......binary<...
|   3360: 02 00 03 01 02 02 00 04 01 02 02 10 03 01 02 02   ................
|   3376: 00 0f 71 02 12 00 03 01 02 02 00 03 01 65 02 00   ..q..........e..
|   3392: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03   ................
|   3408: 01 0d a2 00 03 01 02 02 00 00 08 63 3b 6d 70 69   ...........c;mpi
|   3424: 6c 65 72 09 01 02 00 01 02 00 01 02 00 00 06 64   ler............d
|   3440: 62 73 74 61 74 09 07 03 00 01 03 00 01 03 00 01   bstat...........
|   3456: 04 65 62 75 67 09 04 02 00 01 02 00 01 02 00 00   .ebug...........
|   3472: 06 65 6e 61 62 6c 65 3f 07 02 00 01 02 00 01 02   .enable?........
|   3488: 00 01 02 00 01 02 00 01 01 f0 01 02 00 01 02 00   ................
|   3504: 01 02 00 01 02 00 01 02 00 01 02 00 01 02 00 01   ................
|   3520: 02 00 01 02 00 01 02 00 01 02 00 01 02 00 01 02   ................
|   3536: 00 01 02 00 01 02 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3552: 6e 09 1f 04 00 01 04 00 01 04 00 00 04 66 74 73   n............fts
|   3568: 34 09 0a 03 00 01 03 00 01 03 00 03 01 35 09 0d   4............5..
|   3584: 03 00 01 03 00 01 03 00 00 03 67 63 63 09 01 03   ..........gcc...
|   3600: 00 01 03 00 01 03 00 01 06 65 6f 70 6f 6c 79 09   .........eopoly.
|   3616: 10 03 00 01 03 00 01 03 00 00 05 6a 73 6f 6e 31   ...........json1
|   3632: 09 13 03 00 01 03 00 01 03 00 00 04 6c 6f 61 64   ............load
|   3648: 09 1f 03 00 01 03 00 01 03 00 00 03 6d 61 78 09   ............max.
|   3664: 1c 02 00 01 02 00 01 02 00 01 05 65 6d 6f 72 79   ...........emory
|   3680: 09 1c 03 00 01 03 00 01 03 00 03 04 73 79 73 35   ............sys5
|   3696: 09 16 03 00 01 03 00 01 03 00 00 06 6e 6f 63 61   ............noca
|   3712: 73 65 3c 02 01 02 02 00 03 01 02 02 00 03 01 02   se<.............
|   3728: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3744: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 01 f0   ................
|   3760: 03 01 02 02 05 93 01 02 02 00 03 01 02 02 00 00   ................
|   3776: 04 6f 6d 69 74 09 1f 02 00 01 02 00 01 02 00 00   .omit...........
|   3792: 05 72 8a 72 65 65 09 19 03 00 01 03 00 11 03 00   .r.ree..........
|   3808: 03 02 69 6d 3c 01 01 02 02 00 03 01 02 02 00 03   ..im<...........
|   3824: 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01   ................
|   3840: 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02   ................
|   3856: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3872: 00 00 0a 74 68 72 65 61 64 73 61 66 65 09 22 02   ...threadsafe...
|   3888: 00 01 02 00 01 02 00 00 04 76 75 61 62 09 07 04   .........vuab...
|   3904: 00 01 04 00 01 04 00 00 61 78 b4 01 01 01 01 02   ........ax......
|   3920: 00 01 01 01 02 00 00 f1 01 02 00 01 01 01 02 00   ................
|   3936: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   3952: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   3968: 01 02 00 01 01 01 01 ff 01 01 01 02 00 01 01 01   ................
|   3984: 02 00 01 01 01 02 00 01 01 01 02 09 01 01 01 02   ................
|   4000: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   4016: 01 01 01 02 00 01 02 01 02 00 01 01 01 02 00 01   ................
|   4032: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   4048: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   4064: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4080: 00 01 01 11 02 00 01 01 01 02 00 01 01 01 02 00   ................
| page 6 offset 20480
|      0: 0a 00 00 00 02 0f f5 00 0f fb 1f f5 00 00 00 00   ................
|   4080: 00 00 00 00 00 05 04 08 09 01 02 04 04 08 08 09   ................
| page 7 offset 24576
|      0: 0d 00 00 00 05 0f b8 00 0f f4 0f e9 10 d6 0f c7   ................
|   4016: 00 00 00 00 00 00 00 00 0d 05 02 23 61 75 74 6f   ...........#auto
|   4032: 6d 65 72 67 65 3d 35 0d 04 02 23 6d 65 72 67 65   merge=5...#merge
|   4048: 3d 31 00 00 00 00 00 00 00 00 00 00 00 00 00 00   =1..............
| end crash-53f41622dd3bf6.db
}]} {}

do_catchsql_test 29.1 {
  PRAGMA writable_schema = 1;
  INSERT INTO t1(a) SELECT X'819192E578DE3F';
  UPDATE t1 SET b=quote(zeroblob(current_date)) WHERE t1 MATCH 't*';
  INSERT INTO t1(b) VALUES(x'78');
  INSERT INTO t1(t1) SELECT x FROM t2;
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
#
reset_db
do_test 30.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 28672 pagesize 4096 filename crash-e6e3857edf9b26.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 0e b1 00 06 0d a4 00 0f 8d 0f 21   ...............!
|    112: 0e b9 0d c8 0e 7e 0d a4 00 00 00 00 00 00 00 00   .....~..........
|   3488: 00 00 00 00 22 07 06 17 11 11 01 31 74 61 62 6c   ...........1tabl
|   3504: 65 74 32 74 32 07 43 52 45 41 54 45 20 54 41 42   et2t2.CREATE TAB
|   3520: 4c 45 20 74 32 28 78 29 81 33 05 07 17 1f 1f 01   LE t2(x).3......
|   3536: 82 35 74 61 62 6c 65 74 31 5f 73 65 67 64 69 72   .5tablet1_segdir
|   3552: 74 31 5f 73 65 67 64 69 72 05 43 52 45 41 54 45   t1_segdir.CREATE
|   3568: 20 54 41 42 4c 45 20 27 74 31 5f 73 65 67 64 69    TABLE 't1_segdi
|   3584: 72 27 28 6c 65 76 65 6c 20 49 4e 54 45 47 45 52   r'(level INTEGER
|   3600: 2c 69 64 78 20 49 4e 54 45 47 45 52 2c 73 74 61   ,idx INTEGER,sta
|   3616: 72 74 5f 62 6c 6f 63 6b 20 49 4e 54 45 47 45 52   rt_block INTEGER
|   3632: 2c 6c 65 61 76 65 73 5f 65 6e 64 5f 62 6c 6f 63   ,leaves_end_bloc
|   3648: 6b 20 49 4e 54 45 47 45 52 2c 65 6e 64 5f 62 6c   k INTEGER,end_bl
|   3664: 6f 63 6b 20 49 4e 54 45 47 45 62 2c 72 6f 6f 74   ock INTEGEb,root
|   3680: 20 42 4c 4f 42 2c 50 52 49 4d 41 52 59 20 4b 45    BLOB,PRIMARY KE
|   3696: 59 28 6c 65 76 65 6c 2c 20 69 64 78 29 29 31 06   Y(level, idx))1.
|   3712: 06 17 45 1f 01 00 69 6e 64 65 78 73 71 6c 69 74   ..E...indexsqlit
|   3728: 65 5f 61 75 74 6f 69 6e 64 65 78 5f 74 31 5f 73   e_autoindex_t1_s
|   3744: 65 67 64 69 72 5f 31 74 31 5f 73 65 67 64 69 72   egdir_1t1_segdir
|   3760: 06 0f c7 00 08 00 00 00 00 66 04 07 17 23 23 01   .........f...##.
|   3776: 81 13 74 61 62 6c 65 74 31 5f 73 65 67 6d 65 6e   ..tablet1_segmen
|   3792: 74 73 74 31 5f 73 65 67 6d 65 6e 74 73 04 43 52   tst1_segments.CR
|   3808: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 73   EATE TABLE 't1_s
|   3824: 65 67 6d 65 6e 74 73 27 28 62 6c 6f 63 6b 69 64   egments'(blockid
|   3840: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59    INTEGER PRIMARY
|   3856: 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42    KEY, block BLOB
|   3872: 29 6a 03 07 17 21 21 01 81 1f 74 61 62 6c 65 74   )j...!!...tablet
|   3888: 31 5f 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74   1_contentt1_cont
|   3904: 65 6e 74 03 43 52 45 41 54 45 20 54 41 42 4c 45   ent.CREATE TABLE
|   3920: 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28 64 6f    't1_content'(do
|   3936: 63 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d   cid INTEGER PRIM
|   3952: 41 52 59 20 4b 45 59 2c 20 27 63 30 61 27 2c 20   ARY KEY, 'c0a', 
|   3968: 27 63 31 62 27 2c 20 27 63 32 63 27 29 38 02 06   'c1b', 'c2c')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 33   LE t1 USING fts3
|   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 25 0b 48 00 0f d8 0f af 0f 86 0f 74   ....%.H........t
|     16: 0f 61 0f 4e 0f 2f 0f 0f 0e ef 0e d7 0e be 0e a5   .a.N./..........
|     32: 0e 8d 0e 74 0e 5b 0e 40 0e 24 0e 08 0d ef 00 00   ...t.[.@.$......
|   2880: 00 00 00 00 00 00 00 00 81 3f 25 06 00 82 7e f0   .........?%...~.
|   2896: 00 43 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e   .COMPILER=gcc-5.
|   2912: 34 23 00 20 32 30 31 36 30 36 30 39 20 44 45 42   4#. 20160609 DEB
|   2928: 55 47 20 45 4e 41 42 4c 45 20 44 42 53 54 41 54   UG ENABLE DBSTAT
|   2944: 20 56 54 41 42 20 45 4e 42 92 4c 45 20 46 54 53    VTAB ENB.LE FTS
|   2960: 34 20 45 4e 41 42 4c 45 20 46 54 53 35 20 45 4e   4 ENABLE FTS5 EN
|   2976: 41 42 4c 45 20 47 45 4f 50 4f 4c 59 20 45 4e 41   ABLE GEOPOLY ENA
|   2992: 42 4c 45 1f 4a 53 4f 4e 31 20 45 4e 41 42 4c 49   BLE.JSON1 ENABLI
|   3008: 00 4d 45 4d 53 59 53 35 20 45 4e 41 42 4c 45 20   .MEMSYS5 ENABLE 
|   3024: 52 54 52 45 45 20 4d 41 58 20 4d 45 4d 4f 52 59   RTREE MAX MEMORY
|   3040: 3d 35 30 30 30 30 30 30 30 20 4f 4d 49 54 20 4c   =50000000 OMIT L
|   3056: 4f 41 44 20 45 58 54 45 4e 53 49 4f 4e 20 54 48   OAD EXTENSION TH
|   3072: 52 45 41 44 53 41 46 45 3d 30 18 24 05 00 25 0f   READSAFE=0.$..%.
|   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 88 4e 4f 43 41 53 45 17 22   DSAFE=0.NOCASE..
|   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 4f 4d   0XRTRIM.!..3..OM
|   3168: 49 54 20 4c 4f 41 44 20 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 53 49   MIT LOAD EXTENSI
|   3216: 4f 4e 58 4e 4f 43 41 53 45 1e 20 05 00 33 0f 17   ONXNOCASE. ..3..
|   3232: 4f 4d 49 54 20 4c 4f 41 54 20 45 58 54 45 4e 53   OMIT LOAT EXTENS
|   3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 04 00 33 0f 19   IONXRTRIM....3..
|   3264: 82 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30   .AX MEMORY=50000
|   3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f   000XBINARY....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 33   0000XNOCASE....3
|   3328: 0f 17 4d 41 58 20 4d 45 4d fa 52 59 3d 35 30 20   ..MAX MEM.RY=50 
|   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 53 52 45 45 58 42   ..ENABLE RSREEXB
|   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 58 4e 4f 53 41 53 45 17   LE RTREEXNOSASE.
|   3408: 19 05 00 25 0f 17 45 4e 42 42 4c 45 20 52 54 52   ...%..ENBBLE 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 5a 53 35 58 42 49   NABLE MEMSZS5XBI
|   3456: 4e 41 52 59 1a 17 05 00 29 0f 19 45 4e 41 42 3c   NARY....)..ENAB<
|   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 53 35 58 52 54 52 49 4d 18 15 05 00 25   MSYS5XRTRIM....%
|   3520: 0f 19 45 4e 41 42 4c 45 20 4a 53 4f 4e 31 58 42   ..ENABLE 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 31 58 4e 4f 43 41 53 45 17   LE JSON1XNOCASE.
|   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 31 42 4c 45 20 47 45 4e 50 4f 4c 59 58 42 49   N1BLE GENPOLYXBI
|   3616: 4e 41 52 59 1a 11 05 00 29 0f 19 45 4e f2 1e 4c   NARY....)..EN..L
|   3632: 45 20 47 45 4f 50 4f 4c 59 58 4e 4f 43 41 53 45   E GEOPOLYXNOCASE
|   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 19 45 4e 41 42 4c 45 20 46 54 53 35 58 42 49   ..ENABLE FTS5XBI
|   3696: 4e 41 52 59 17 0e 05 00 23 0f 19 45 4e 41 42 3c   NARY....#..ENAB<
|   3712: 45 20 46 54 53 35 58 4e 4f 43 41 53 45 16 0d 05   E FTS5XNOCASE...
|   3728: 00 23 0f 17 45 4e 41 42 4c 45 20 46 54 53 35 58   .#..ENABLE FTS5X
|   3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42   RTRIM....#..ENAB
|   3760: 4c 45 20 46 54 53 34 58 42 49 4e 41 52 59 17 0b   LE FTS4XBINARY..
|   3776: 05 00 23 0f 19 45 4e 41 43 4c 45 20 46 54 53 35   ..#..ENACLE FTS5
|   3792: 58 4e 4f 43 40 53 45 16 0a 05 00 23 0f 17 45 4e   XNOC@SE....#..EN
|   3808: 41 42 4c 45 20 46 54 53 34 58 52 54 52 49 4d 1e   ABLE FTS4XRTRIM.
|   3824: 09 05 00 31 0f 19 45 4e 41 42 4c 45 20 44 42 53   ...1..ENABLE DBS
|   3840: 54 41 55 20 56 54 41 42 58 42 49 4e 41 52 59 1e   TAU 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 62 49 4d 11 06   TAT VTABXRTbIM..
|   3920: 05 00 17 0f 19 44 45 42 54 47 58 42 49 4e 41 52   .....DEBTGXBINAR
|   3936: 59 11 05 05 00 17 0f 19 54 45 42 55 47 58 4e 4f   Y.......TEBUGXNO
|   3952: 43 41 53 45 10 04 05 00 17 0f 17 44 45 42 55 47   CASE.......DEBUG
|   3968: 68 52 54 52 49 4d 27 03 05 00 43 0f 19 43 4f 4d   hRTRIM'...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 3d 67   ...C..COMPILER=g
|   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 4f 4f 43 41 53 45 26 01 05 00 43 0f 17 43   9XOOCASE&...C..C
|   4064: 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e   OMPILER=gcc-5.4.
|   4080: 30 20 32 30 31 36 30 36 30 39 58 52 54 52 49 4d   0 20160609XRTRIM
| page 4 offset 12288
|      0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
| page 5 offset 16384
|      0: 0d 00 00 00 02 0b a0 00 0c ad 0b a0 00 00 00 00   ................
|   2976: 82 0a 02 08 08 09 08 08 17 84 06 30 20 32 35 33   ...........0 253
|   2992: 00 01 30 04 25 06 1b 00 00 08 32 30 31 36 30 36   ..0.%.....201606
|   3008: 30 39 03 25 07 00 00 01 34 03 25 05 00 00 01 35   09.%....4.%....5
|   3024: 03 25 04 00 01 07 30 30 30 30 30 30 30 03 25 1a   .%....0000000.%.
|   3040: 00 00 08 63 6f 6d 70 69 6c 65 72 03 25 02 00 00   ...compiler.%...
|   3056: 06 64 62 73 74 61 74 03 25 0a 00 01 04 65 62 75   .dbstat.%....ebu
|   3072: 67 03 25 08 00 00 06 65 6e 61 62 6c 65 09 25 09   g.%....enable.%.
|   3088: 05 04 04 04 04 04 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3104: 6e 03 25 1d 00 00 04 66 74 73 34 03 25 0d 00 03   n.%....fts4.%...
|   3120: 01 35 03 25 0f 00 00 03 67 63 63 03 25 03 00 01   .5.%....gcc.%...
|   3136: 06 65 6f 70 6f 6c 79 03 25 11 00 00 05 6a 73 6f   .eopoly.%....jso
|   3152: 6e 31 03 25 14 00 e8 04 6c 6f 61 64 03 25 1c 00   n1.%....load.%..
|   3168: 00 03 6d 61 78 03 25 18 00 01 05 65 6d 6f 72 79   ..max.%....emory
|   3184: 03 25 19 00 03 04 73 79 73 35 03 25 15 00 00 04   .%....sys5.%....
|   3200: 6f 6d 69 74 03 25 1b 00 00 05 72 74 72 65 65 03   omit.%....rtree.
|   3216: 25 17 00 00 0a 74 68 72 65 61 64 73 61 66 65 03   %....threadsafe.
|   3232: 25 1e 00 00 04 76 74 61 62 03 25 0b 00 86 50 01   %....vtab.%...P.
|   3248: 08 08 08 08 08 17 8d 12 30 20 38 33 35 00 01 30   ........0 835..0
|   3264: 12 01 06 00 01 06 00 01 06 00 1f 03 00 01 03 00   ................
|   3280: 01 03 00 00 08 32 30 31 36 30 36 30 39 09 01 07   .....20160609...
|   3296: 00 01 07 00 01 07 00 00 01 34 09 01 05 00 01 05   .........4......
|   3312: 00 01 05 00 00 01 35 09 01 04 00 01 04 00 01 04   ......5.........
|   3328: 00 01 07 30 30 30 30 30 30 30 09 1c 04 00 01 04   ...0000000......
|   3344: 00 01 04 00 00 06 62 69 6e 61 72 79 3c 03 01 02   ......binary<...
|   3360: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3376: 00 03 01 02 f2 00 03 01 02 02 00 03 01 02 02 00   ................
|   3392: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03   ................
|   3408: 01 02 02 00 03 01 02 02 00 00 08 63 6f 6d 70 69   ...........compi
|   3424: 6c 65 72 09 01 02 00 01 02 00 01 02 00 00 06 64   ler............d
|   3440: 62 73 74 61 74 09 07 03 00 01 03 00 01 03 00 01   bstat...........
|   3456: 04 65 62 75 67 09 04 02 00 01 02 00 01 02 00 00   .ebug...........
|   3472: 06 65 6e 60 62 6c 65 3f 07 02 00 01 02 00 01 01   .en`ble?........
|   3488: ff f1 b1 00 00 02 3f 01 01 f0 f1 02 00 57 02 00   ......?......W..
|   3504: 01 02 00 01 02 00 01 02 00 01 02 00 01 02 10 01   ................
|   3520: 02 00 01 02 00 01 02 00 01 02 01 01 02 00 01 02   ................
|   3536: 00 01 02 00 00 f2 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3552: 6e 09 1f 04 00 01 04 00 01 04 00 00 04 66 74 73   n............fts
|   3568: 34 09 0a 03 00 01 03 00 01 03 00 03 01 35 09 0d   4............5..
|   3584: 03 00 01 03 00 01 03 00 00 03 67 63 63 09 01 03   ..........gcc...
|   3600: 00 01 03 00 01 03 00 01 06 65 6f 70 6f 6c 79 09   .........eopoly.
|   3616: 10 03 00 01 03 00 01 03 00 00 b3 6a 73 6f 6e 31   ...........json1
|   3632: 09 13 03 00 01 03 00 01 03 00 00 04 6c 6f 61 64   ............load
|   3648: 09 1f 03 00 01 03 00 01 03 00 00 03 6d 61 78 09   ............max.
|   3664: 1c 02 00 01 02 00 01 02 00 01 05 65 6d 6f 72 79   ...........emory
|   3680: 09 1c 03 00 01 03 00 01 03 00 03 04 73 79 73 35   ............sys5
|   3696: 09 16 03 00 01 03 00 01 03 cc 00 06 6e 6f 63 61   ............noca
|   3712: 73 65 3c 02 01 02 02 00 03 01 02 02 00 03 01 02   se<.............
|   3728: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3744: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
|   3760: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 00   ................
|   3776: 04 6f 6d 69 74 09 1f 02 00 01 02 00 01 02 00 00   .omit...........
|   3792: 05 72 74 62 65 65 09 19 03 00 01 03 00 01 03 00   .rtbee..........
|   3808: 03 02 69 6d 3c 01 01 02 02 00 03 01 02 02 00 03   ..im<...........
|   3824: 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01   ................
|   3840: 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02   ................
|   3856: 02 00 03 01 02 02 00 03 01 02 01 00 03 01 02 02   ................
|   3872: 00 00 0a 74 68 72 65 61 64 73 61 66 65 09 22 02   ...threadsafe...
|   3888: 00 01 02 00 02 02 00 00 04 76 74 61 62 09 07 04   .........vtab...
|   3904: 00 01 03 00 01 04 00 00 01 78 b4 01 01 01 01 02   .........x......
|   3920: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   3936: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   3952: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   3968: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   3984: 02 01 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4000: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   4016: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   4032: 01 01 02 00 01 01 01 da 00 01 01 01 02 00 01 01   ................
|   4048: 01 02 00 01 01 01 01 ff ff 01 01 02 00 01 01 01   ................
|   4064: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4080: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
| page 6 offset 20480
|      0: 0a 00 00 00 02 0f f5 00 0f fb 0f f5 01 00 00 00   ................
|   4080: 00 00 00 00 00 05 04 08 09 01 02 04 04 08 08 09   ................
| page 7 offset 24576
|      0: 01 6f 00 00 00 00 00 00 00 00 00 00 00 00 00 00   .o..............
| end crash-e6e3857edf9b26.db
}]} {}

do_execsql_test 30.1 {
  UPDATE t1 SET b=a;
}

do_catchsql_test 30.2 {
  SELECT (matchinfo(null)) FROM t1 WHERE t1 MATCH 'ee*e*e*e*e*e*e*Re*e*e*e**' 
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 31.0 {
CREATE VIRTUAL TABLE t1 USING fts3(a,b,c);
INSERT INTO t1_segdir VALUES(0,0,0,0,'0 592',X'00016dcb048ce6fbd3b2d68bfebf0101020200808080808080808020010202008080808080808080100102020080808080808080800801020200808080808080808004010202008080808080808080020102020080808080808080800101020200808080808080804001020200808080808080802001020200808080808080801001020200808080808080800801020200808080808080800401020200808080808080800201020200808080808080800101020200808080808080400102020080808080808020010202008080808080801001020200808080808080080102020080808080808004010202008080808080800201020200808080808080010102020080808080804001020200808080808020010202008080808080100102020080808080800801020200808080808004010202008080808080020102020080808080800101020200808080804001020200808080802001020200808080801001020200808080800801020200808080800401020200808080800201020200808080800101020200808080400102020080808020010202008080801001020200808080080102020080808004010202008080800201020200808080010102020080804001020200808020010202008080100102020080800801020200808004010202008080020102020080800101020200804001020200802001020200801001020200800801020200800401020200800201020200800101020200400102020020010202001001020200080102020004010202000201020200010102020001010202008080808080808080800101020200');
INSERT INTO t1_segdir VALUES(0,1,0,0,'0 18',X'00026d6d0d8ee6fbd3b2d68bfe7f01020200');
}

do_catchsql_test 31.1 {
  SELECT (matchinfo(t1, c ) ) FROM t1 WHERE t1 MATCH 'M*M*M*M*';
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
#
reset_db
do_test 32.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
.open --hexdb
| size 24576 pagesize 4096 filename crash-74fdbc96edbc04.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 0e b1 00 06 0d a4 00 0f 8d 0f 21   ...............!
|    112: 0e b9 0d c8 0e 7e 0d a4 00 00 00 00 00 00 00 00   .....~..........
|   3488: 00 00 00 00 22 07 06 17 11 11 01 31 74 61 62 6c   ...........1tabl
|   3504: 65 74 32 74 32 07 43 52 45 41 54 45 20 54 41 42   et2t2.CREATE TAB
|   3520: 4c 45 20 74 32 28 78 29 81 33 05 07 17 1f 1f 01   LE t2(x).3......
|   3536: 82 35 74 61 62 6c 65 74 31 5f 73 65 67 64 69 72   .5tablet1_segdir
|   3552: 74 31 5f 73 65 67 64 69 72 05 43 52 45 41 54 45   t1_segdir.CREATE
|   3568: 20 54 41 42 4c 45 20 27 74 31 5f 73 65 67 64 69    TABLE 't1_segdi
|   3584: 72 27 28 6c 65 76 65 6c 20 49 4e 54 45 47 45 52   r'(level INTEGER
|   3600: 2c 69 64 78 20 49 4e 54 45 47 44 52 2c 73 74 61   ,idx INTEGDR,sta
|   3616: 72 74 5f 62 6c 6f 63 6b 20 49 4e 54 45 47 45 52   rt_block INTEGER
|   3632: 2c 6c 65 61 76 65 73 5f 65 6e 64 5f 62 6c 6f 63   ,leaves_end_bloc
|   3648: 6b 20 49 4e 54 45 47 45 52 2c 65 6e 64 5f 62 6c   k INTEGER,end_bl
|   3664: 6f 63 6b 20 49 4e 54 45 47 45 52 2c 72 6f 6f 74   ock INTEGER,root
|   3680: 20 42 4c 4f 42 2c 50 52 49 4d 41 52 59 20 4b 45    BLOB,PRIMARY KE
|   3696: 59 28 6c 65 76 65 6c 2c 20 69 64 78 29 29 31 06   Y(level, idx))1.
|   3712: 06 17 45 1f 01 00 6a 6e 64 65 78 73 71 6c 69 74   ..E...jndexsqlit
|   3728: 65 5f 61 75 74 6f 69 6e 64 65 78 5f 74 31 5f 73   e_autoindex_t1_s
|   3744: 65 67 64 69 72 5f 31 74 31 5f 73 65 67 64 69 72   egdir_1t1_segdir
|   3760: 06 0f c7 00 08 00 00 00 00 66 04 07 17 23 23 01   .........f...##.
|   3776: 81 13 74 61 62 6c 65 74 31 5f 73 65 67 6d 65 6e   ..tablet1_segmen
|   3792: 74 73 74 31 5f 73 65 67 6d 65 6e 74 73 03 43 52   tst1_segments.CR
|   3808: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 73   EATE TABLE 't1_s
|   3824: 65 67 6d 65 6e 74 73 27 28 62 6c 6f 63 6b 69 64   egments'(blockid
|   3840: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 5a    INTEGER PRIMARZ
|   3856: 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42    KEY, block BLOB
|   3872: 29 6a 03 07 17 21 21 01 81 1f 74 61 62 6c 65 74   )j...!!...tablet
|   3888: 31 5f 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74   1_contentt1_cont
|   3904: 65 6e 74 03 43 52 45 41 54 45 20 54 41 42 4c 45   ent.CREATE TABLE
|   3920: 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28 64 6f    't1_content'(do
|   3936: 63 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d   cid INTEGER PRIM
|   3952: 41 52 59 20 4b 45 59 2c 20 27 63 30 61 27 2c 20   ARY KEY, 'c0a', 
|   3968: 27 63 31 62 27 2c 20 27 63 32 63 27 29 38 02 06   'c1b', 'c2c')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 33   LE t1 USING fts3
|   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 25 0b 48 00 0f d8 0f af 0f 86 0f 74   ....%.H........t
|     16: 0f 61 0f 4e 0f 2f 0f 0f 0e ef 0e d7 0e be 0e a5   .a.N./..........
|     32: 0e 8d 0e 74 0e 5b 0e 40 0e 24 0e 08 0d ef 0d d5   ...t.[.@.$......
|     48: 0d bb 0d a0 0d 84 0d 68 0d 50 0d 35 0d 1b 0c fb   .......h.P.5....
|     64: 0c da 0c b8 fc 99 0c 78 0c 57 0c 3e 0c 24 0c 0a   .......x.W.>.$..
|     80: 0b 48 00 00 00 00 00 00 00 00 00 00 00 00 00 00   .H..............
|   2880: 00 00 00 00 00 00 00 00 81 3f 25 06 00 82 7f 00   .........?%.....
|   2896: 00 43 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e   .COMPILER=gcc-5.
|   2912: 34 2e 30 20 32 30 31 36 30 36 30 39 20 44 45 42   4.0 20160609 DEB
|   2928: 55 47 20 45 4e 41 42 4c 45 20 44 42 53 54 7e 54   UG ENABLE DBST~T
|   2944: 20 56 54 41 42 20 45 4e 41 42 4c 45 20 46 54 53    VTAB ENABLE FTS
|   2960: 44 20 45 4e 41 42 4c 45 20 46 54 53 35 20 45 4e   D ENABLE FTS5 EN
|   2976: 41 42 4c 45 20 47 45 4f 50 4f 4c 59 20 45 4e 41   ABLE GEOPOLY ENA
|   2992: 42 4c 45 20 4a 53 4f 4e 31 20 45 4e 41 42 4c 45   BLE JSON1 ENABLE
|   3008: 20 4d 45 4d 53 59 53 35 20 45 4e 41 42 4c 45 20    MEMSYS5 ENABLE 
|   3024: 52 54 52 45 45 20 4d 41 58 20 4d 45 4d 4f 52 59   RTREE MAX MEMORY
|   3040: 3d 35 30 30 30 30 30 30 30 20 4f 4d 49 54 20 4c   =50000000 OMIT L
|   3056: 4f 41 44 20 45 58 54 45 4e 53 49 4f 4e 20 54 48   OAD EXTENSION TH
|   3072: 52 45 41 44 53 41 46 45 3d 30 18 24 05 00 25 0f   READSAFE=0.$..%.
|   3088: 19 54 48 52 45 41 44 54 41 46 45 3d 30 58 42 49   .THREADTAFE=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 bd 4e 4f 43 41 53 45 17 22   DSAFE=0.NOCASE..
|   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 4f 4d   0XRTRIM.!..3..OM
|   3168: 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49 4e   IT LOAD EXTENSIN
|   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 53 49   MIT LOAD EXTENSI
|   3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17   ONXNOCASE....3..
|   3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53   OMIT LOAD EXTENS
|   3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19   IONXRTRIM....3..
|   3264: 4d 41 58 1f 4d 45 4d 4f 52 59 3d 35 30 30 30 30   MAX.MEMORY=50000
|   3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f   000XBINARY....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 33   0000XNOCASE....3
|   3328: 0f 17 4d 41 58 20 4d 44 4d 4f 52 59 3d 35 30 30   ..MAX MDMORY=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 55 20 52 54 52 45 45 58 4e 4f 43 41 53 45 17   LU RTREEXNOCASE.
|   3408: 19 05 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52   ...%..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 3f 43 41 53 45   E MEMSYS5XN?CASE
|   3488: 19 16 05 00 29 0f 17 45 4e a1 42 4c 45 20 4d 45   ....)..EN.BLE ME
|   3504: 4d 53 59 53 35 58 52 54 52 49 4d 18 15 05 00 25   MSYS5XRTRIM....%
|   3520: 0f 19 45 4e 41 42 4c 45 20 4a 53 4f 4e 31 58 42   ..ENABLE 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 31 58 4e 4f 43 41 53 45 17   LE JSON1XNOCASE.
|   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 5f 4c 59 58 42 49   NABLE GEOP_LYXBI
|   3616: 4e 41 52 59 1a 11 05 00 29 0f 19 45 4e 41 42 4c   NARY....)..ENABL
|   3632: 45 20 47 45 4f 50 4f 4c 59 58 4b bf 43 41 53 45   E GEOPOLYXK.CASE
|   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 19 45 4e 41 42 4c 55 20 46 54 53 35 58 42 49   ..ENABLU FTS5XBI
|   3696: 4e 4b a2 59 17 0e 05 00 23 0f 19 45 4e 41 42 4c   NK.Y....#..ENABL
|   3712: 45 20 46 54 52 35 58 4e 4f 43 41 53 45 16 0d 05   E FTR5XNOCASE...
|   3728: 00 23 0f 17 45 4e 41 42 4c 45 20 46 54 53 35 58   .#..ENABLE FTS5X
|   3744: 52 54 52 49 4d 17 0b 05 00 23 0f 19 45 4e 41 42   RTRIM....#..ENAB
|   3760: 4c 45 20 46 54 53 34 58 42 49 4e 41 52 59 17 0b   LE FTS4XBINARY..
|   3776: 05 00 23 0f 19 45 4e 41 42 4c 45 20 46 54 53 34   ..#..ENABLE FTS4
|   3792: 58 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 45 4e   XNOCASE....#..EN
|   3808: 41 42 4c 45 20 46 54 53 34 58 52 54 52 49 4d 1e   ABLE FTS4XRTRIM.
|   3824: 09 05 07 e1 0f 19 45 4e 41 42 4c 45 20 44 42 53   ......ENABLE DBS
|   3840: 54 41 54 20 56 54 41 42 58 42 49 4e 41 52 59 1e   TAT VTABXBINARY.
|   3856: 18 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 41 18 4e 4f 43 41 53 45 1d   TAT VTAA.NOCASE.
|   3888: 07 05 00 31 0f 17 45 4e 41 42 4c 45 20 44 32 53   ...1..ENABLE D2S
|   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 00 00 00 00 00 00   Y.......DE......
| page 5 offset 16384
|      0: 0d 00 00 00 02 0b a0 00 0c ad 0b a0 01 00 00 00   ................
|   2976: 82 0a 02 08 08 09 08 08 17 84 06 30 20 32 35 33   ...........0 253
|   2992: 00 01 30 04 25 06 1b 00 00 08 32 30 31 36 30 36   ..0.%.....201606
|   3008: 30 38 03 25 07 00 00 01 34 03 25 05 00 00 01 35   08.%....4.%....5
|   3024: 03 25 13 00 01 07 30 30 30 30 30 30 30 03 25 1a   .%....0000000.%.
|   3040: 00 00 08 63 6f 6d 70 69 6c 65 72 03 25 02 00 00   ...compiler.%...
|   3056: 06 64 62 73 74 61 74 03 25 0a 00 01 04 65 62 75   .dbstat.%....ebu
|   3072: 67 03 25 08 00 00 06 65 6e 61 62 6c 65 09 25 09   g.%....enable.%.
|   3088: 05 04 04 04 04 04 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3104: 6e 03 25 1d 00 00 04 66 74 73 34 03 25 0d 00 03   n.%....fts4.%...
|   3120: 01 35 03 25 0f 00 00 03 67 63 63 03 25 03 00 01   .5.%....gcc.%...
|   3136: 06 65 6f 70 6f 6c 79 03 25 11 00 00 05 6a 73 6f   .eopoly.%....jso
|   3152: 6e 31 03 25 13 00 00 04 6c 6f 61 64 03 25 1c 00   n1.%....load.%..
|   3168: 00 03 6d 62 78 03 25 18 00 01 05 65 6d 6f 72 79   ..mbx.%....emory
|   3184: 03 25 19 00 03 04 73 c8 73 35 03 25 15 00 00 04   .%....s.s5.%....
|   3200: 6f 6d 69 74 03 25 1b 00 00 05 72 74 72 65 65 03   omit.%....rtree.
|   3216: 25 17 00 00 0a 74 68 72 65 61 64 73 61 66 65 03   %....threadsafe.
|   3232: 25 1e 00 00 04 76 74 61 62 03 25 0b 00 86 50 01   %....vtab.%...P.
|   3248: 08 08 08 08 08 17 8d 12 30 20 38 33 35 00 01 30   ........0 835..0
|   3264: 12 01 06 00 01 06 00 01 06 00 1f 03 00 01 03 00   ................
|   3280: 01 03 00 00 08 32 30 31 36 30 36 30 39 09 01 07   .....20160609...
|   3296: 00 01 07 00 01 07 00 00 01 34 09 01 05 00 01 05   .........4......
|   3312: 00 01 05 00 00 01 35 09 01 04 00 01 04 00 02 04   ......5.........
|   3328: 00 01 07 30 2f 30 30 30 30 30 09 1c 04 00 01 04   ...0/00000......
|   3344: 00 01 04 00 00 06 62 69 6e 61 72 79 3c 03 01 02   ......binary<...
|   3360: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3376: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
|   3392: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03   ................
|   3408: 01 02 02 00 03 01 02 02 00 00 08 63 6f 6d 70 69   ...........compi
|   3424: 6c 65 72 09 01 02 00 01 02 00 01 02 00 00 06 64   ler............d
|   3440: 62 73 74 61 74 09 07 03 00 01 03 00 01 03 00 01   bstat...........
|   3456: 04 65 62 75 67 09 04 02 00 01 02 00 01 02 00 00   .ebug...........
|   3472: 06 65 6e 61 6c 2c 65 3f 07 02 00 01 02 00 01 02   .enal,e?........
|   3488: 00 01 02 00 01 02 00 01 02 00 01 02 00 01 02 00   ................
|   3504: 01 02 00 01 02 00 01 02 00 01 01 ff f1 02 00 01   ................
|   3520: 02 00 01 02 00 01 02 00 f1 02 00 01 02 00 01 4f   ...............O
|   3536: 00 01 02 00 01 02 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3552: 6e 09 1f 04 00 01 04 00 01 04 00 00 04 66 74 73   n............fts
|   3568: 34 09 0a 03 00 01 03 00 00 f3 00 03 01 35 09 0d   4............5..
|   3584: 03 00 01 04 00 01 03 00 00 03 67 63 63 09 01 03   ..........gcc...
|   3600: 00 01 03 00 01 03 00 01 06 65 6f 70 6f 6c 79 09   .........eopoly.
|   3616: 10 03 00 01 03 00 01 03 00 00 05 6a 73 6f 6e 31   ...........json1
|   3632: 09 13 03 00 01 02 ff 01 03 00 00 04 6c 6f 61 63   ............loac
|   3648: 09 1f 03 00 01 03 00 01 03 00 00 03 6d 61 78 09   ............max.
|   3664: 1c 02 00 01 02 00 01 02 00 01 05 64 6d 6f 72 79   ...........dmory
|   3680: 09 1c 03 00 01 03 00 01 03 00 03 04 73 79 73 35   ............sys5
|   3696: 09 16 02 f0 01 03 00 01 03 00 00 06 6e 6f 63 61   ............noca
|   3712: 73 65 3c 02 01 02 02 00 03 01 02 02 00 03 01 02   se<.............
|   3728: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3744: 00 03 01 02 02 00 03 01 02 02 00 4b 01 02 02 00   ...........K....
|   3760: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 00   ................
|   3776: 04 6f 6d 69 74 09 1f 02 00 01 02 00 01 02 00 00   .omit...........
|   3792: 05 72 74 72 65 65 09 19 03 00 01 03 00 01 03 00   .rtree..........
|   3808: 03 02 69 6d 3c 01 01 02 02 00 03 01 02 02 00 03   ..im<...........
|   3824: 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01   ................
|   3840: 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02   ................
|   3856: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3872: 00 00 0a 74 68 72 65 61 64 73 61 66 65 09 22 02   ...threadsafe...
|   3888: 00 01 02 00 01 02 00 00 04 76 74 61 62 09 07 04   .........vtab...
|   3904: 00 01 04 00 01 04 00 00 01 78 b4 01 01 01 01 02   .........x......
|   3920: 00 01 f4 01 02 00 01 02 01 02 00 01 01 01 02 ff   ................
|   3936: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   3952: 01 01 02 ae 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   3968: 01 12 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   3984: 12 00 01 01 01 02 01 01 01 01 02 00 01 01 01 02   ................
|   4000: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   4016: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   4032: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   4048: 01 02 00 01 01 01 02 00 01 76 01 02 00 01 01 01   .........v......
|   4064: 02 00 01 01 01 02 01 01 01 01 02 00 01 01 01 02   ................
|   4080: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
| page 6 offset 20480
|      0: 0a 00 00 00 02 0f f5 00 0f fb 0f f5 00 00 00 00   ................
|   4080: 00 00 00 00 00 05 04 08 09 01 02 04 04 08 08 09   ................
| end crash-74fdbc96edbc04.db
}]} {}

do_catchsql_test 32.1 {
  UPDATE t1 SET b=quote(zeroblob(6.51158946e+5)) WHERE a MATCH '*t*';
} {1 {database disk image is malformed}}

#do_catchsql_test 32.2 {
#  UPDATE t1 SET b=((- '' )) WHERE a MATCH '0*t';
#} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
#
ifcapable icu {
  reset_db
  do_catchsql_test 33.0 {
    CREATE VIRTUAL TABLE f USING fts3(a,b,tokenize=icu);
    CREATE TABLE 'f_docsize'(docid INTEGER PRIMARY KEY, size BLOB);
    CREATE TABLE 'f_stat'(id INTEGER PRIMARY KEY, value BLOB);
    INSERT INTO f VALUES (1, '1234');
    INSERT INTO f_stat VALUES (1,x'0000000165656565db6569746565c5c52bc5c5c53e3a003bc502ffffffffc5c5c53e3a003bc502fffffffffb8b2afbfb6565f0740100650000000165656565db6569746565c5c52bc5c5c53e3a003bc502ffffffffc5c5c53e3a003b8b00c5c5c5c5c5bfc5');
    INSERT INTO f(f) VALUES ('merge=198,49');
  } {1 {database disk image is malformed}}
}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 34.0 {
  CREATE VIRTUAL TABLE f USING fts3(a,b);
  INSERT INTO f VALUES (1, '1234');
  INSERT INTO f_segdir VALUES (1,255,0,0,'1 255',x'00');
  UPDATE f_segdir SET level = 0 WHERE level IN (
    SELECT level FROM f_segdir LIMIT 1 OFFSET 1
  );
  INSERT INTO f_segdir VALUES (255,249,0,121,'0 0',x'00');
  INSERT INTO f_content VALUES (255,0,x'ff');
  INSERT INTO f_segdir VALUES (1,255,16,0,'1 255',x'00');
}

do_catchsql_test 34.1 {
  UPDATE f SET b = x'00' WHERE b IN (SELECT b FROM f LIMIT 1 OFFSET 0);
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 35.0 {
  CREATE VIRTUAL TABLE f USING fts3(a,b);
  INSERT INTO f_segdir VALUES (1,255,0,0,'1 255',x'0001ff000001ff000001ff000001ff000001ff00c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5bec5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5');
}

do_catchsql_test 35.1 {
  INSERT INTO f(f) VALUES ('integrity-check');
} {1 {database disk image is malformed}}

reset_db
do_catchsql_test 36.0 {
  CREATE VIRTUAL TABLE f USING fts3(a,tokenize=porter);
  CREATE TABLE 'f_stat'(id INTEGER PRIMARY KEY, value BLOB);
  INSERT INTO f VALUES (1);
  INSERT INTO f_stat VALUES (1,x'00000000000101010119013d00ffff0400fa83717b71a69297979701f63d010101010101010101010101190000000000000000fa83717b71a601f63d01010101010101010101010119013d00ffffff0400fa83717b71a69297979701f63d010101010101010101010101190000000000000000fa83717b71a69201f63d010101f63d01010101010101010101010119013d00ffffff0400fa83717b71a6929797010101010101010101010119013d00ffff01f63d01010101010101010101010119013d00ffffff0400fa83717b71a69297979701f63d00fa03ffffffa69297979701f63d010101000000000101010101197e9797976567656565ffa63535354e');
  INSERT INTO f(f) VALUES ('merge=53,216');
} {0 {}}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 36.0 {
  CREATE VIRTUAL TABLE f USING fts3(a,b);
  CREATE TABLE 'f_stat'(id INTEGER PRIMARY KEY, value BLOB);
  INSERT INTO f_stat VALUES (1,x'11014101000101c5c5014b010164c5014b010101c50101c5c5010201010101014101000101c5c5014b010101c5014b010101c50101c5c501010100c50101c5c5010101010101e40201010101014101000201010101014101000101010201010101014101000101c5c503b5fefefe3afeffffc5c5c5c50101010101010201010101014101adadadadadadadadadadadad91adadadadadadadad0101c50101c5c501f9ffffffffffffffff0001010102010101010140f5000101c5c5014b010101c50101c5c501010101e6010201010101014101000101c5c5014b010101c50101c5c5010101114b0101c5c50101010a0101020101e60101');
}

do_catchsql_test 36.1 {
  INSERT INTO f(f) VALUES ('merge=59,59');
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 37.0 {
  CREATE VIRTUAL TABLE f USING fts3(a,b);
  INSERT INTO f_segdir VALUES (28,0,0,0,'0 0',x'00');
  INSERT INTO f_segdir VALUES (0,241,0,0,'0 0',x'0001000030310000f1');
}

do_catchsql_test 37.1 {
  INSERT INTO f VALUES (0,x'00');
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
#
reset_db
do_test 38.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
.open --hexdb
| size 24576 pagesize 4096 filename crash-1cc4f8a70485ce.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 0e b1 00 06 0d a4 00 0f 8d 0f 21   ...............!
|    112: 0e b9 0d c8 0e 7e 0d a4 00 00 00 00 00 00 00 00   .....~..........
|   3488: 00 00 00 00 22 07 06 17 11 11 01 31 74 61 62 6c   ...........1tabl
|   3504: 65 74 32 74 32 07 43 52 45 41 54 45 20 54 41 42   et2t2.CREATE TAB
|   3520: 4c 45 20 74 32 28 78 29 81 33 05 07 17 1f 1f 01   LE t2(x).3......
|   3536: 82 35 74 61 62 6c 65 74 31 5f 73 65 67 64 69 72   .5tablet1_segdir
|   3552: 74 31 5f 73 65 67 64 69 72 05 43 52 45 41 54 45   t1_segdir.CREATE
|   3568: 20 54 41 42 4c 45 20 27 74 31 5f 73 65 67 64 69    TABLE 't1_segdi
|   3584: 72 27 28 6c 65 76 65 6c 20 49 4e 54 45 47 45 52   r'(level INTEGER
|   3600: 2c 69 64 78 20 49 4e 54 45 47 45 52 2c 73 74 61   ,idx INTEGER,sta
|   3616: 72 74 5f 62 6c 6f 63 6b 20 49 4e 54 45 47 45 52   rt_block INTEGER
|   3632: 2c 6c 65 61 76 65 73 5f 65 6e 64 5f 62 6c 6f 63   ,leaves_end_bloc
|   3648: 6b 20 49 4e 54 45 47 45 52 2c 65 6e 64 5f 62 6c   k INTEGER,end_bl
|   3664: 6f 63 6b 20 49 4e 54 45 47 45 62 2c 72 6f 6f 74   ock INTEGEb,root
|   3680: 20 42 4c 4f 42 2c 50 52 49 4d 41 52 59 20 4b 45    BLOB,PRIMARY KE
|   3696: 59 28 6c 65 76 65 6c 2c 20 69 64 78 29 29 31 06   Y(level, idx))1.
|   3712: 06 17 45 1f 01 00 69 6e 64 65 78 73 71 6c 69 74   ..E...indexsqlit
|   3728: 65 5f 61 75 74 6f 69 6e 64 65 78 5f 74 31 5f 73   e_autoindex_t1_s
|   3744: 65 67 64 69 72 5f 31 74 31 5f 73 65 67 64 69 72   egdir_1t1_segdir
|   3760: 06 0f c7 00 08 00 00 00 00 66 04 07 17 23 23 01   .........f...##.
|   3776: 81 13 74 61 62 6c 65 74 31 5f 73 65 67 6d 65 6e   ..tablet1_segmen
|   3792: 74 73 74 31 5f 73 65 67 6d 65 6e 74 73 04 43 52   tst1_segments.CR
|   3808: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 73   EATE TABLE 't1_s
|   3824: 65 67 6d 65 6e 74 73 27 28 62 6c 6f 63 6b 69 64   egments'(blockid
|   3840: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59    INTEGER PRIMARY
|   3856: 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42    KEY, block BLOB
|   3872: 29 6a 03 07 17 21 21 01 81 1f 74 61 62 6c 65 74   )j...!!...tablet
|   3888: 31 5f 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74   1_contentt1_cont
|   3904: 65 6e 74 03 43 52 45 41 54 45 20 54 41 42 4c 45   ent.CREATE TABLE
|   3920: 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28 64 6f    't1_content'(do
|   3936: 63 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d   cid INTEGER PRIM
|   3952: 41 52 59 20 4b 45 59 2c 20 27 63 30 61 27 2c 20   ARY KEY, 'c0a', 
|   3968: 27 63 31 62 27 2c 20 27 63 32 63 27 29 38 02 06   'c1b', 'c2c')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 33   LE t1 USING fts3
|   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 25 0b 48 00 0f d8 0f af 0f 86 0f 74   ....%.H........t
|     16: 0f 61 0f 4e 0f 2f 0f 0f 0e ef 0e d7 0e be 0e a5   .a.N./..........
|     32: 0e 8d 0e 74 0e 5b 0e 40 0e 24 0e 08 0d ef 00 00   ...t.[.@.$......
|   2880: 00 00 00 00 00 00 00 00 81 3f 25 06 00 82 7e f0   .........?%...~.
|   2896: 00 43 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e   .COMPILER=gcc-5.
|   2912: 34 23 00 20 42 30 31 36 2f 36 30 39 20 44 45 42   4#. B016/609 DEB
|   2928: 55 47 20 45 4e 41 42 4c 45 20 44 42 53 54 41 54   UG ENABLE DBSTAT
|   2944: 20 56 54 41 42 20 45 4e 42 92 4c 45 20 46 54 53    VTAB ENB.LE FTS
|   2960: 34 20 45 4e 41 42 4c 45 20 46 54 53 35 20 45 4e   4 ENABLE FTS5 EN
|   2976: 41 42 4c 45 20 47 45 4f 50 4f 4c 59 20 45 4e 41   ABLE GEOPOLY ENA
|   2992: 42 5c 45 1f 4a 53 4f 4e 31 20 45 4e 41 42 4c 45   B.E.JSON1 ENABLE
|   3008: 20 4d 45 4d 53 59 53 35 20 45 4e 41 42 4c 45 20    MEMSYS5 ENABLE 
|   3024: 52 54 52 45 45 20 4d 41 58 20 4d 45 4d 4f 52 59   RTREE MAX MEMORY
|   3040: 3d 35 30 30 30 30 30 30 30 20 4f 4d 49 54 20 4c   =50000000 OMIT L
|   3056: 4f 41 44 20 45 58 54 45 4e 53 49 4f 4e 20 54 48   OAD EXTENSION TH
|   3072: 52 45 41 44 53 41 46 45 3d 30 18 24 05 00 25 0f   READSAFE=0.$..%.
|   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 88 4e 4f 43 41 53 45 17 22   DSAFE=0.NOCASE..
|   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 4f 4d   0XRTRIM.!..3..OM
|   3168: 49 54 20 4c 4f 41 44 20 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 53 49   MIT LOAD EXTENSI
|   3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17   ONXNOCASE....3..
|   3232: 4f 4d 49 54 20 4c 4f 41 54 20 45 58 54 45 4e 53   OMIT LOAT EXTENS
|   3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 04 00 33 0f 19   IONXRTRIM....3..
|   3264: 82 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30   .AX MEMORY=50000
|   3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f   000XBINARY....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 33   0000XNOCASE....3
|   3328: 0f 17 4d 41 58 20 4d 45 4d fa 52 59 3d 35 30 20   ..MAX MEM.RY=50 
|   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 58 4e 4f 43 41 53 45 17   LE RTREEXNOCASE.
|   3408: 19 05 00 25 0f 17 45 4e 42 42 4c 45 20 52 54 52   ...%..ENBBLE 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 3c   NARY....)..ENAB<
|   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 53 35 58 52 54 52 49 4d 18 15 05 00 25   MSYS5XRTRIM....%
|   3520: 0f 19 45 4e 41 42 4c 45 20 4a 53 4f 4e 31 58 42   ..ENABLE 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 31 58 4e 4f 43 41 53 45 17   LE JSON1XNOCASE.
|   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 95 12 05 00 29 0f 19 45   N1XRTRIM....)..E
|   3600: 4e 31 42 4c 45 20 47 45 4e 50 4f 4c 59 58 42 49   N1BLE GENPOLYXBI
|   3616: 4e 41 52 59 1a 11 05 00 29 0f 19 45 3e f2 1e 4c   NARY....)..E>..L
|   3632: 45 20 47 45 4f 50 4f 4c 59 58 4e 4f 43 41 53 45   E GEOPOLYXNOCASE
|   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 19 45 4e 41 42 4c 45 20 46 54 53 35 58 42 49   ..ENABLE FTS5XBI
|   3696: 4e 41 52 59 17 0e 05 00 23 0f 19 45 4e 41 42 3c   NARY....#..ENAB<
|   3712: 45 20 46 54 53 35 58 4e 4f 43 41 53 45 16 0d 05   E FTS5XNOCASE...
|   3728: 00 23 0f 17 45 4e 41 42 4c 45 20 46 54 53 35 58   .#..ENABLE FTS5X
|   3744: 5d 24 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42   ]$RIM....#..ENAB
|   3760: 4c 45 20 46 54 53 34 58 42 49 4e 41 52 59 17 0b   LE FTS4XBINARY..
|   3776: 05 00 23 0f 19 45 4e 41 42 4c 45 20 46 54 53 35   ..#..ENABLE FTS5
|   3792: 58 4e 4f 43 40 53 45 16 0a 05 00 23 0f 17 45 4e   XNOC@SE....#..EN
|   3808: 41 42 4c 45 20 46 54 53 34 58 52 54 52 49 4d 1e   ABLE FTS4XRTRIM.
|   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 4b 45 20 44 42 53   ...1..ENABKE DBS
|   3904: 54 41 54 20 56 53 41 42 58 52 54 62 49 4d 11 06   TAT VSABXRTbIM..
|   3920: 05 00 17 0f 19 44 45 42 54 47 58 42 49 4e 41 52   .....DEBTGXBINAR
|   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: 68 52 54 52 49 4d 27 03 05 00 43 0f 19 43 4f 4d   hRTRIM'...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 3d 67   ...C..COMPILER=g
|   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 4f 4f 43 41 53 45 26 01 05 00 43 0f 17 43   9XOOCASE&...C..C
|   4064: 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e   OMPILER=gcc-5.4.
|   4080: 30 20 32 30 31 36 30 36 30 39 58 52 54 52 49 4d   0 20160609XRTRIM
| page 4 offset 12288
|      0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
| page 5 offset 16384
|      0: 0d 00 00 00 02 0b a0 00 0c ad 0b a0 00 00 00 00   ................
|   2976: 82 0a 02 08 08 09 08 08 17 84 06 30 20 32 35 33   ...........0 253
|   2992: 00 01 30 04 25 06 1b 00 00 08 32 30 31 36 8c 36   ..0.%.....2016.6
|   3008: 30 39 03 25 07 00 00 01 34 03 25 05 00 00 01 35   09.%....4.%....5
|   3024: 03 25 04 00 01 07 30 30 30 30 30 30 30 03 25 1a   .%....0000000.%.
|   3040: 00 00 08 63 6f 5d 70 69 6c 65 72 03 25 02 00 00   ...co]piler.%...
|   3056: 06 64 62 73 74 61 74 03 25 0a 00 01 04 65 62 75   .dbstat.%....ebu
|   3072: 67 03 25 08 00 00 06 65 6e 61 62 6c 65 09 25 09   g.%....enable.%.
|   3088: 05 04 04 04 04 04 00 01 08 78 74 65 7e 73 69 6f   .........xte~sio
|   3104: 6e 03 25 1d 00 00 04 66 74 73 34 03 25 0d 00 03   n.%....fts4.%...
|   3120: 01 35 03 25 0f 00 00 03 67 63 63 03 25 03 00 01   .5.%....gcc.%...
|   3136: 06 65 6f 70 7f 6c 79 03 25 11 00 00 05 6a 73 6f   .eop.ly.%....jso
|   3152: 6e 31 03 25 14 00 e8 04 6c 6f 61 64 03 25 1c 00   n1.%....load.%..
|   3168: 00 03 6d 61 78 03 25 18 00 01 05 65 6d 6f 72 79   ..max.%....emory
|   3184: 03 25 19 00 03 04 73 79 73 35 03 25 15 00 00 04   .%....sys5.%....
|   3200: 6f 6d 69 74 03 25 1b 00 00 05 72 74 72 65 65 03   omit.%....rtree.
|   3216: 25 17 00 00 0a 74 68 72 65 61 64 73 61 66 65 03   %....threadsafe.
|   3232: 25 1e 00 00 04 76 74 61 62 03 25 0b 00 86 50 01   %....vtab.%...P.
|   3248: 08 08 08 08 08 17 8d 12 30 20 38 33 35 00 01 30   ........0 835..0
|   3264: 12 01 06 00 01 06 00 01 06 00 1f 03 00 01 03 00   ................
|   3280: 01 03 00 00 08 32 30 31 36 30 36 30 39 09 01 07   .....20160609...
|   3296: 00 01 07 00 01 07 00 00 01 34 09 01 05 00 01 05   .........4......
|   3312: 00 01 05 00 00 01 35 09 01 04 00 01 04 00 01 04   ......5.........
|   3328: 00 01 07 30 30 30 30 30 30 30 09 1c 04 00 01 04   ...0000000......
|   3344: 00 01 04 00 00 06 62 69 6e 61 72 79 3c 03 01 02   ......binary<...
|   3360: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3376: 00 03 01 02 c2 00 03 01 02 02 00 03 01 04 82 00   ................
|   3392: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03   ................
|   3408: 01 02 02 00 03 01 02 02 00 00 08 63 6f 6d 70 69   ...........compi
|   3424: 6c 65 72 09 01 02 00 01 02 00 01 02 00 00 06 64   ler............d
|   3440: 62 73 74 61 74 09 07 03 00 01 03 00 01 03 00 01   bstat...........
|   3456: 04 65 62 75 67 09 04 02 00 01 02 00 01 02 00 00   .ebug...........
|   3472: 06 65 6e 60 62 6c 65 3f 07 02 00 01 02 92 e1 a4   .en`ble?........
|   3488: ff fc a2 8c 95 b2 3f 01 01 f0 f1 02 00 57 02 00   ......?......W..
|   3504: 01 02 00 01 02 00 01 02 00 01 02 00 01 02 10 01   ................
|   3520: 02 00 01 02 00 01 02 00 01 02 01 01 02 00 01 02   ................
|   3536: 00 01 02 00 00 f2 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3552: 6e 09 1f 04 00 01 04 00 01 04 00 00 04 66 74 73   n............fts
|   3568: 34 09 0a 03 00 01 03 00 01 03 00 03 01 35 09 0d   4............5..
|   3584: 03 00 01 03 00 01 03 00 00 03 67 63 63 09 01 03   ..........gcc...
|   3600: 00 01 03 00 01 03 00 01 06 65 5f 70 6f 6c 79 09   .........e_poly.
|   3616: 10 03 00 01 03 00 01 03 00 00 b3 6a 73 6f 6e 31   ...........json1
|   3632: 09 13 03 00 01 03 00 01 03 00 00 04 6c 6f 61 64   ............load
|   3648: 09 1f 03 00 01 03 00 01 03 00 00 03 6d 61 78 09   ............max.
|   3664: 1c 02 00 01 02 00 01 02 00 01 05 65 6d 6f 72 79   ...........emory
|   3680: 09 1c 03 00 01 03 00 01 03 00 03 04 73 79 73 35   ............sys5
|   3696: 09 16 03 00 01 03 00 01 03 cc 00 06 6e 6f 63 61   ............noca
|   3712: 73 65 3c 02 01 02 02 00 03 01 02 02 00 03 01 02   se<.............
|   3728: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3744: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
|   3760: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 00   ................
|   3776: 04 6f 6d 69 74 09 1f 02 00 01 02 00 01 02 00 00   .omit...........
|   3792: 05 72 74 62 65 65 09 19 03 00 01 03 00 01 03 00   .rtbee..........
|   3808: 03 02 69 6d 3c 01 01 02 02 00 03 01 02 02 00 03   ..im<...........
|   3824: 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01   ................
|   3840: 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02   ................
|   3856: 02 00 03 01 02 02 00 03 01 02 01 00 03 01 02 02   ................
|   3872: 00 00 0a 74 68 72 65 61 64 73 61 66 65 09 22 02   ...threadsafe...
|   3888: 00 01 02 00 02 02 00 00 04 76 74 61 62 09 07 04   .........vtab...
|   3904: 00 01 03 00 01 04 00 00 01 78 b4 01 01 01 01 02   .........x......
|   3920: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   3936: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   3952: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   3968: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   3984: 02 01 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4000: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   4016: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   4032: 01 01 02 00 01 01 01 da 00 00 f1 01 02 00 01 01   ................
|   4048: 01 02 00 01 01 01 01 ff ff 01 01 02 00 01 01 01   ................
|   4064: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4080: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
| page 6 offset 20480
|      0: 0a 00 00 00 02 0f f5 00 0f fb 0f f5 01 00 00 00   ................
|   4080: 00 00 00 00 00 05 04 08 09 01 02 04 04 08 08 09   ................
| end crash-1cc4f8a70485ce.db
}]} {}

do_execsql_test 38.1 {
  UPDATE t1 SET b=a;
}

do_catchsql_test 38.2 {
  SELECT b FROM t1 WHERE a MATCH 'e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*'
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
reset_db
set saved $sqlite_fts3_enable_parentheses
set sqlite_fts3_enable_parentheses 1
do_execsql_test 39.0 {
  CREATE VIRTUAL TABLE t0 USING fts3(
    col0 INTEGER PRIMARY KEY,
    col1 VARCHAR(8),
    col2 BINARY,
    col3 BINARY
  );
  INSERT INTO t0_content VALUES(1,1,'1234','aaaa','bbbb');
  INSERT INTO t0_segdir VALUES(0,0,0,0,'0 42',X'000131030782000103323334050101010200000461616161050101020200000462626262050101030200');
}

do_test 39.1 {
  catch {
    db eval { SELECT rowid FROM t0 WHERE t0 MATCH '1 NEAR 1' }
  }
} 0

do_test 39.2 {
  catch {
    db eval {
  SELECT matchinfo(t0,'yxy') FROM t0 WHERE t0 MATCH x'2b0a312b0a312a312a2a0b5d0a0b0b0a312a0a0b0b0a312a0b310a392a0b0a27312a2a0b5d0a312a0b310a31315d0b310a312a316d2a0b313b15bceaa50a312a0b0a27312a2a0b5d0a312a0b310a312b0b2a310a312a0b2a0b2a0b2e5d0a0bff313336e34a2a312a0b0a3c310b0a0b4b4b0b4b2a4bec40322b2a0b310a0a312a0a0a0a0a0a0a0a0a0b310a312a2a2a0b5d0a0b0b0a312a0b310a312a0b0a4e4541530b310a5df5ced70a0a0a0a0a4f520a0a0a0a0a0a0a312a0b0a4e4541520b310a5d616161610a0a0a0a4f520a0a0a0a0a0a312b0a312a312a0a0a0a0a0a0a004a0b0a310b220a0b0a310a4a22310a0b0a7e6fe0e0e030e0e0e0e0e01176e02000e0e0e0e0e01131320226310a0b0a310a4a22310a0b0a310a766f8b8b4ee0e0300ae0090909090909090909090909090909090909090909090909090909090909090947aaaa540b09090909090909090909090909090909090909090909090909090909090909fae0e0f2f22164e0e0f273e07fefefef7d6dfafafafa6d6d6d6d';
    }
  }
} 0
set sqlite_fts3_enable_parentheses $saved

#-------------------------------------------------------------------------
reset_db
set saved $sqlite_fts3_enable_parentheses
set sqlite_fts3_enable_parentheses 1

do_execsql_test 40.1 {

  CREATE VIRTUAL TABLE t0 USING fts3(col0 INTEGER PRIMARY KEY, col1, col2 ,col3 );
  INSERT INTO t0_segdir VALUES(0,0,0,0,'0 42',
      X'0001310301020001033233340500010102000004616161bc050101020200000462626262050101030200'
  );
}

do_execsql_test 40.2 {
  SELECT 0==matchinfo(t0,'sx') FROM t0 WHERE t0 MATCH '1* 2 3 4 5 6 OR 1';
} 0

set sqlite_fts3_enable_parentheses $saved

#-------------------------------------------------------------------------
reset_db
do_execsql_test 41.1 {
  CREATE VIRTUAL TABLE t1 USING fts3(a,b,c);
  INSERT INTO t1_segdir VALUES(0,0,0,0,'0 835',X'000130120106000106000106001f030001030001030000083230313630363039090107000107000107000001340901050001050001050000013509010400010400010400010730303030303030091c0400010400010400000662696e6172793c0301020200030102020003010202000301020200030102020003010202000301020200030102020003010202000301020200030102020003010202000008636f3870696c657209010200010200010200000664627374617409070300010300010300010465627567090402000102000102000006656e61626c653f07020001020001020001020001020001020001020001020001020001030001010002020001020001020001020001120001020001020001020001020001020001087874656e73696f6e091f0400010400010400000466747334090a0300010300010400030135090d03000103000103000003676363090103000103000103000106656f706f6c790910030001030001030000056a736f6e310913030001030001030000046c6f6164091f030001030001030000036d6178091c02000102000102000105656d6f7279091c03000103000103000304737973350916030001030001030000066e6f636173653c02010202000301020200030102020003010202000301020200030102020003010202000301020200030102020003010202000301020200030102020000046f6d6974091f020001020001020000057274726565091903000103000103000302696d3c010102020003010202000301020200030102020003010202000301020200030102020003010202000301020200030102020003010202000301020200000a746872656164736166650922020001020001020000047674616209070400010400010400000178b401010101020001010102000101010200010101020001010102000101010200010101020001010102000101010200010101020001010102000101010200010101020001010102000101010200010101020001010102000101010200010101020001010102000101010200010101020001010102000101010200010101020001010102000101010200010101020001010102000101010200010101020001010102000101010200010101020001010102000101010200');
}

do_execsql_test 41.2 {
  SELECT offsets(t1) FROM t1 WHERE t1 MATCH 'rtree ner "json1^enable"';
}

#-------------------------------------------------------------------------
do_execsql_test 42.1 {
  CREATE VIRTUAL TABLE f USING fts3(a, b);
}
do_execsql_test 42.2 {
  INSERT INTO f_segdir VALUES(0,2,1111,0,0,X'00');
  INSERT INTO f_segdir VALUES(0,3,0   ,0,0,X'00013003010200');
}
do_execsql_test 42.3 {
  INSERT INTO f(f) VALUES ('merge=107,2');
}

#-------------------------------------------------------------------------
reset_db
set saved $sqlite_fts3_enable_parentheses
set sqlite_fts3_enable_parentheses 1
do_execsql_test 43.1 {
  CREATE VIRTUAL TABLE def USING fts3(xyz);
  INSERT INTO def_segdir VALUES(0,0,0,0,0, X'0001310301c9000103323334050d81');
} {}

do_execsql_test 43.2 {
  SELECT rowid FROM def WHERE def MATCH '1 NEAR 1'
} {1}

set sqlite_fts3_enable_parentheses $saved

#-------------------------------------------------------------------------
reset_db
do_execsql_test 44.1 {
  CREATE VIRTUAL TABLE t0 USING fts3(col0 INTEGER PRIMARY KEY,col1 VARCHAR(8),col2 BINARY,col3 BINARY);
  INSERT INTO t0_content VALUES(0,NULL,NULL,NULL,NULL);
  INSERT INTO t0_segdir VALUES(0,0,0,0,'0 42',X'00013103010200010332333405010201ba00000461616161050101020200000462626262050101030200');
}

do_execsql_test 44.2 {
  SELECT matchinfo(t0, t0) IS NULL FROM t0 WHERE t0 MATCH '1*'
} {0}

#-------------------------------------------------------------------------
#
reset_db
do_test 45.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
.open --hexdb
| size 24576 pagesize 4096 filename crash-65c98512cc9e49.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 06   .....@  ........
|     96: 00 00 00 00 0d 0e fc 00 06 0d bc 00 0f ca 0f 6c   ...............l
|    112: 0f 04 0e 13 0e c9 0d bc 00 00 00 00 00 00 00 00   ................
|   3504: 00 00 00 00 00 00 00 00 00 00 00 00 55 06 07 17   ............U...
|   3520: 1b 1b 01 81 01 74 61 62 6c 65 78 31 5f 73 74 61   .....tablex1_sta
|   3536: 74 78 31 5f 73 74 61 74 06 43 52 45 41 54 45 20   tx1_stat.CREATE 
|   3552: 54 41 42 4c 45 20 27 78 31 5f 73 74 61 74 27 28   TABLE 'x1_stat'(
|   3568: 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41   id INTEGER PRIMA
|   3584: 52 59 20 4b 45 59 2c 20 76 61 6c 75 65 20 42 4c   RY KEY, value BL
|   3600: 41 82 29 81 33 04 07 17 1f 1f 01 82 35 74 61 62   A.).3.......5tab
|   3616: 6c 65 78 31 5f 73 65 67 64 69 72 78 31 5f 73 65   lex1_segdirx1_se
|   3632: 67 64 69 72 04 43 52 45 41 54 45 20 54 41 42 4c   gdir.CREATE TABL
|   3648: 45 20 27 78 31 5f 73 65 67 64 69 72 27 28 6c 65   E 'x1_segdir'(le
|   3664: 76 65 6c 20 49 4e 54 45 47 45 52 2c 69 64 78 20   vel INTEGER,idx 
|   3680: 49 4e 54 45 47 45 52 2c 73 74 61 72 74 5f 62 6c   INTEGER,start_bl
|   3696: 6f 63 6b 20 49 4e 54 45 47 45 52 2c 6c 65 61 76   ock INTEGER,leav
|   3712: 65 73 5f 65 6e 64 5f 62 6c 6f 63 6b 20 49 4e 54   es_end_block INT
|   3728: 45 47 45 52 2c 65 6e 64 5f 62 6c 6f 63 6b 20 49   EGER,end_block I
|   3744: 4e 54 45 47 45 52 2c 72 6f 6f 74 20 42 4c 4f 42   NTEGER,root BLOB
|   3760: 2c 50 52 49 4d 41 52 59 20 4b 45 59 28 6c 65 76   ,PRIMARY KEY(lev
|   3776: 65 6c 2c 20 69 64 78 29 29 31 05 06 17 45 1f 01   el, idx))1...E..
|   3792: 00 69 6e 64 65 78 73 71 6c 69 74 65 5f 61 75 74   .indexsqlite_aut
|   3808: 6f 69 6e 64 65 78 5f 78 31 5f 73 65 67 64 69 72   oindex_x1_segdir
|   3824: 5f 31 78 31 5f 73 65 67 64 69 72 05 00 00 00 08   _1x1_segdir.....
|   3840: 60 00 00 00 66 03 07 17 23 23 01 81 13 74 61 62   `...f...##...tab
|   3856: 6c 65 78 31 5f 73 65 67 6d 65 6e 74 73 78 31 5f   lex1_segmentsx1_
|   3872: 73 65 67 6d 65 6e 74 73 03 43 52 45 41 54 45 20   segments.CREATE 
|   3888: 54 41 42 4c 45 20 27 78 31 5f 73 65 67 6d 65 6e   TABLE 'x1_segmen
|   3904: 74 73 27 28 62 6c 6f 63 6b 69 64 20 49 4e 54 45   ts'(blockid INTE
|   3920: 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c   GER PRIMARY KEY,
|   3936: 20 62 6c 6f 63 6b 20 42 4c 4f 42 29 5c 02 07 17    block BLOB)....
|   3952: 21 21 01 81 03 74 61 62 6c 65 78 31 5f 63 6f 6e   !!...tablex1_con
|   3968: 74 65 6e 74 78 31 5f 63 6f 6e 74 65 6e 74 02 43   tentx1_content.C
|   3984: 52 45 41 54 45 20 54 41 42 4c 45 20 27 78 31 5f   REATE TABLE 'x1_
|   4000: 63 6f 6e 74 65 6e 74 27 28 64 6f 63 69 64 20 49   content'(docid I
|   4016: 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b   NTEGER PRIMARY K
|   4032: 45 59 2c 20 27 63 30 78 27 29 34 01 06 17 11 11   EY, 'c0x')4.....
|   4048: 08 57 74 61 62 6c 65 78 31 78 31 43 52 45 41 54   .Wtablex1x1CREAT
|   4064: 45 20 56 49 52 54 55 41 4c 20 54 41 42 4c 45 20   E VIRTUAL TABLE 
|   4080: 78 31 20 55 53 49 4e 47 20 66 74 73 33 28 78 29   x1 USING fts3(x)
| page 2 offset 4096
|      0: 0d 00 00 00 11 0f 77 f0 0f f8 0f f0 0f e8 0f e0   ......w.........
|     16: 0f d8 0f d0 0f c8 0f c0 00 00 00 00 00 00 00 00   ................
|   3952: 00 00 00 00 00 00 00 00 06 11 03 00 13 77 78 79   .............wxy
|   3968: 06 10 03 00 13 74 75 76 06 0f 03 00 13 71 33 73   .....tuv.....q3s
|   3984: 06 0e 03 00 13 6e 6f 70 06 0d 03 00 13 6b 6c 6d   .....nop.....klm
|   4000: 06 0c 03 04 c3 68 69 6a 06 0b 03 00 13 65 66 67   .....hij.....efg
|   4016: 06 0a 03 00 13 62 63 64 06 09 03 00 13 79 7a 61   .....bcd.....yza
|   4032: 06 08 03 00 13 76 77 78 06 07 03 00 13 73 74 75   .....vwx.....stu
|   4048: 06 06 03 00 13 70 71 72 06 05 03 00 13 6d 6e 6f   .....pqr.....mno
|   4064: 06 03 03 00 13 6a 6b 6c 06 03 03 00 13 67 68 69   .....jkl.....ghi
|   4080: 06 02 02 00 03 64 65 66 06 01 03 00 13 61 52 63   .....def.....aRc
| page 3 offset 8192
|      0: 0d 00 00 00 03 0f a7 00 0f b5 0f a7 0f fa 01 00   ................
|   4000: 00 00 00 00 00 00 00 0c 02 03 00 1e 00 03 6b 6c   ..............kl
|   4016: 6d 03 0d 02 00 43 01 04 00 81 0a 00 03 61 62 63   m....C.......abc
|   4032: 03 0b 32 00 00 03 62 63 64 03 0a 02 00 00 03 64   ..2...bcd......d
|   4048: 69 26 03 02 02 00 00 03 65 66 67 03 0b 02 00 00   i&......efg.....
|   4064: 03 67 68 69 03 03 02 00 00 03 68 69 6a 03 0c 02   .ghi......hij...
|   4080: 00 00 03 6a 6a 2c 03 04 02 00 03 81 00 03 00 00   ...jj,..........
| page 4 offset 12288
|      0: 0d 0f 3a 00 05 0f 25 00 0f 9e 0f 88 0f 43 0f 25   ..:...%......C.%
|     16: 0f 72 00 00 00 00 00 00 00 00 00 00 00 00 00 00   .r..............
|   3856: 00 00 00 00 00 00 00 00 00 56 01 08 08 13 1e 03   .........V......
|   3872: 30 20 39 00 03 13 05 07 08 08 18 08 13 1e 30 20   0 9...........0 
|   3888: 39 00 03 77 78 79 03 11 02 00 0f 6c 00 09 01 08   9..wxy.....l....
|   3904: 08 15 54 27 04 07 09 01 08 08 15 42 02 30 20 33   ..T'.......B.0 3
|   3920: 36 00 03 6e 6f 70 03 0e 02 00 00 03 71 72 73 03   6..nop......qrs.
|   3936: 0f 02 00 00 03 74 75 76 03 10 02 00 0f cf b1 06   .....tuv........
|   3952: 01 08 14 06 07 01 08 09 01 1b 14 02 02 31 32 38   .............128
|   3968: 20 2d 37 32 10 01 01 6b 14 03 07 09 09 08 08 15    -72...k........
|   3984: 1e 30 20 33 36 00 03 79 7a 61 03 09 02 00 2f 02   .0 36..yza..../.
|   4000: 07 09 08 08 08 15 54 30 20 33 36 00 03 6d 6e 6f   ......T0 36..mno
|   4016: 03 05 02 00 00 03 70 71 72 03 06 02 00 00 03 73   ......pqr......s
|   4032: 74 75 03 07 02 00 00 03 76 77 78 03 08 02 00 00   tu......vwx.....
|   4048: 00 00 4a 08 08 08 15 54 30 20 33 36 00 03 61 62   ..J....T0 36..ab
|   4064: 63 03 01 02 00 00 03 64 65 66 03 02 02 00 00 03   c......def......
|   4080: 67 68 69 03 03 67 00 00 03 6a 6b 6c 03 04 02 00   ghi..g...jkl....
| page 5 offset 16384
|      0: 0a 0f e7 00 05 0f da 00 0f e1 0f fa 0f f4 0f ed   ................
|     16: 0f da 0f 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   4048: 00 00 00 00 00 00 00 1a 01 03 06 04 01 08 01 02   ................
|   4064: 06 05 04 08 08 01 05 00 00 00 06 01 03 06 04 09   ................
|   4080: 02 01 02 04 05 04 09 09 01 03 05 04 09 08 01 02   ................
| page 6 offset 20480
|      0: 0d 00 10 00 01 0f f9 00 0f f9 00 00 00 00 00 00   ................
|   4080: 00 00 00 00 00 00 00 00 00 05 01 03 00 10 01 03   ................
| end crash-65c98512cc9e49.db
}]} {}

do_catchsql_test 45.2 {
  INSERT INTO x1(x1) VALUES( 'merge=1' )
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
reset_db
set saved $sqlite_fts3_enable_parentheses
set sqlite_fts3_enable_parentheses 1
do_execsql_test 46.1 {
  CREATE VIRTUAL TABLE t0 USING fts3(a INTEGER PRIMARY KEY,b,c,d);
  INSERT INTO t0_segdir VALUES(0,0,0,0,'0 42',X'0001310301c9000103323334050d8000f200000461616161050101020200000462626262050101030200');
} {}

do_catchsql_test 46.2 {
  SELECT * FROM t0
    WHERE t0 MATCH x'2b0a312b0a312a312a2a0b5d0a0b0b0a312a0a0b0b0a312a0b310a392a0b0a27312a2a0b5d0a312a0b310a31315d0b310a312a316d2a0b313b15bceaa50a312a0b0a27312a2a0b5d0a312a0b310a312b0b2a310a312a0b2a0b2a0b2e5d0a0bff313336e34a2a312a0b0a3c310b0a0b4b4b0b4b2a4bec40322b2a0b310a0a312a0a0a0a0a0a0a0a0a0b310a312a2a2a0b5d0a0b0b0a312a0b310a312a0b0a4e4541530b310a5df5ced70a0a0a0a0a4f520a0a0a0a0a0a0a312a0b0a4e4541520b310a5d616161610a0a0a0a4f520a0a0a0a0a0a312b0a312a312a0a0a0a0a0a0a004a0b0a310b220a0b0a310a4a22310a0b0a7e6fe0e0e030e0e0e0e0e01176e02000e0e0e0e0e01131320226310a0b0a310a4a22310a0b0a310a766f8b8b4ee0e0300ae0090909090909090909090909090909090909090909090909090909090909090947aaaa540b09090909090909090909090909090909090909090909090909090909090909fae0e0f2f22164e0e0f273e07fefefef7d6dfafafafa6d6d6d6d';
} {1 {database disk image is malformed}}

set sqlite_fts3_enable_parentheses $saved
extra_schema_checks 1

#-------------------------------------------------------------------------
reset_db
do_execsql_test 47.1 {
  CREATE VIRTUAL TABLE t1 USING fts3(a,b,c);
}
do_execsql_test 47.2 {
  INSERT INTO t1_segdir VALUES(0,0,0,0,0,X'000130120106000106000106001f030001030001030000083230313630363039090107000107000107000001340901050001050001050000013509010400010400010400010730303030303030091c0400010400010400000662696e6172793c0301020200030102020003010202000301020200030102020003010202000301020200030102020003010202000301020200030102020003010202000008636f6d70696c657209010200010200010200000664627374617409070300010300010300010465627567090402000102000102000006656e61626c653f07020001020001020001020001020001020001020001020001020001020001020001020001010001020001020001020001020001020001020001020001020001087874656e73696f6e091f0400010400010400000466747334090a0300010300010300030135090d03000103000103000003676363090103000103000103000106656f706f6c790910030001030001030000056a736f6e310913030001030001030000046c6f6164091f030001030001030000036d6178091c02000102000102000105656d6f7279091c03000103000103000304737973350916030001030001030000066e6f636173653c02010202000301020200030102020003010202000301020200030102020003010202000301020200030102020003010202000301020200030102020000046f6d6974091f020001020001020000057274726565091903000103000103000302696d3c01010202000301020200030102020003010202000301020200030102020003010202000301a202000301020200030102020003010202000301020200000a746872656164736166650922020001020001020000047674616209070400010400010400000178b401010101020001010102000101010200010101020001010102000101010200010101020001010102000101010200010101020001010102000101010200010101020001010102000101010200010101020001010102000101010200010101020001010102000101010200010101020001010102000101010200010101020001010102000101010200010101020001010102000101010200010101020001010102000101010200010101020001010102000101010200');
  INSERT INTO t1_segdir VALUES(0,1,0,0,0,X'0001300425061b000008323031363036303903250700000134032505000001350325040001073030303030303003251a000008636f6d70696c657203250200000664627374617403250a00010465627567032508000006656e61626c650925090504040404040001087874656e73696f6e03251d0000046674733403250d0003013503250f000003676363032503000106656f706f6c790325110000056a736f6e310325130000046c6f616403251c0000036d6178032518000105656d6f7279032519000304737973350325150000046f6d697403251b000005727472656503251700000a7468726561647361666503251e0000047674616333250b00');
}

do_catchsql_test 47.3 {
  SELECT matchinfo(t1) FROM t1 WHERE t1 MATCH '"json1 enable"';
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
#
reset_db
do_test 48.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
.open --hexdb
| size 20480 pagesize 4096 filename sql038051.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 00   .....@  ........
|     96: 00 00 00 00 0d 0e fc 00 05 0e 13 00 0f ca 0f 6c   ...............l
|    112: 0f 04 0e 13 0e c9 00 00 00 00 00 00 00 00 00 00   ................
|   3600: 00 00 00 81 33 04 07 17 1f 1f 01 82 35 74 61 62   ....3.......5tab
|   3616: 6c 65 78 31 5f 73 65 67 64 69 72 78 31 5f 73 65   lex1_segdirx1_se
|   3632: 67 64 69 72 04 43 52 45 41 54 45 20 54 41 42 4c   gdir.CREATE TABL
|   3648: 45 20 27 78 31 5f 73 65 67 64 69 72 27 28 6c 65   E 'x1_segdir'(le
|   3664: 76 65 6c 20 49 4e 54 45 47 45 52 2c 69 64 78 20   vel INTEGER,idx 
|   3680: 49 4e 54 45 47 45 52 2c 73 74 61 72 74 5f 62 6c   INTEGER,start_bl
|   3696: 6f 63 6b 20 49 4e 54 45 47 45 52 2c 6c 65 61 76   ock INTEGER,leav
|   3712: 65 73 5f 65 6e 64 5f 62 6c 6f 63 6b 20 49 4e 54   es_end_block INT
|   3728: 45 47 45 52 2c 65 6e 64 5f 62 6c 6f 63 6b 20 49   EGER,end_block I
|   3744: 4e 54 45 47 45 52 2c 72 6f 6f 74 20 42 4c 4f 42   NTEGER,root BLOB
|   3760: 2c 50 52 49 4d 41 52 59 20 4b 45 59 28 6c 65 76   ,PRIMARY KEY(lev
|   3776: 65 6c 2c 20 69 64 78 29 29 31 05 06 17 45 1f 01   el, idx))1...E..
|   3792: 00 69 6e 64 65 78 73 71 6c 69 74 65 5f 61 75 74   .indexsqlite_aut
|   3808: 6f 69 6e 64 65 78 5f 78 31 5f 73 65 67 64 69 72   oindex_x1_segdir
|   3824: 5f 31 78 31 5f 73 65 67 64 69 72 05 00 00 00 08   _1x1_segdir.....
|   3840: 00 00 00 00 66 03 07 17 23 23 01 81 13 74 61 62   ....f...##...tab
|   3856: 6c 65 78 31 5f 73 65 67 6d 65 6e 74 73 78 31 5f   lex1_segmentsx1_
|   3872: 73 65 67 6d 65 6e 74 73 03 43 52 45 41 54 45 20   segments.CREATE 
|   3888: 54 41 42 4c 45 20 27 78 31 5f 73 65 67 6d 65 6e   TABLE 'x1_segmen
|   3904: 74 73 27 28 62 6c 6f 63 6b 69 64 20 49 4e 54 45   ts'(blockid INTE
|   3920: 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c   GER PRIMARY KEY,
|   3936: 20 62 6c 6f 63 6b 20 42 4c 4f 42 29 5c 02 07 17    block BLOB)....
|   3952: 21 21 01 81 03 74 61 62 6c 65 78 31 5f 63 6f 6e   !!...tablex1_con
|   3968: 74 65 6e 74 78 31 5f 63 6f 6e 74 65 6e 74 02 43   tentx1_content.C
|   3984: 52 45 41 54 45 20 54 41 42 4c 45 20 27 78 31 5f   REATE TABLE 'x1_
|   4000: 63 6f 6e 74 65 6e 74 27 28 64 6f 63 69 64 20 49   content'(docid I
|   4016: 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b   NTEGER PRIMARY K
|   4032: 45 59 2c 20 27 63 30 78 27 29 34 01 06 17 11 11   EY, 'c0x')4.....
|   4048: 08 57 74 61 62 6c 65 78 31 78 31 43 52 45 41 54   .Wtablex1x1CREAT
|   4064: 45 20 56 49 52 54 55 41 4c 20 54 41 42 4c 45 20   E VIRTUAL TABLE 
|   4080: 78 31 20 55 53 49 4e 47 20 66 74 73 33 28 78 29   x1 USING fts3(x)
| page 2 offset 4096
|      0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   3920: 00 00 00 2e 04 03 00 63 62 72 61 69 6e 73 74 65   .......cbrainste
|   3936: 6d 20 62 72 61 69 6e 73 74 65 6d 73 20 62 72 61   m brainstems bra
|   3952: 69 6e 73 74 6f 72 6d 20 62 72 61 69 6e 73 74 6f   instorm brainsto
|   3968: 72 6d 73 2b 03 03 00 5d 62 72 61 69 6e 20 62 72   rms+...]brain br
|   3984: 61 69 6e 63 68 69 6c 64 20 62 72 61 69 6e 65 64   ainchild brained
|   4000: 20 62 72 61 69 6e 69 6e 67 20 62 72 61 69 6e 73    braining brains
|   4016: 26 02 03 00 53 62 72 61 67 73 20 62 72 61 69 64   &...Sbrags braid
|   4032: 20 62 72 61 69 64 65 64 20 62 72 61 69 64 69 6e    braided braidin
|   4048: 67 20 62 72 61 69 64 73 26 01 03 00 53 62 72 61   g braids&...Sbra
|   4064: 65 73 20 62 72 61 67 20 62 72 61 67 67 65 64 20   es brag bragged 
|   4080: 62 72 61 c3 67 65 72 20 62 72 61 67 67 69 6e 67   bra.ger bragging
| page 3 offset 8192
|      0: 0d 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00   ................
| page 4 offset 12288
|      0: 0d 00 00 00 04 0f 20 00 0f c8 0f 90 0f 54 0f 20   ...... ......T. 
|   3872: 32 04 07 08 01 08 08 15 58 03 30 20 33 38 00 09   2.......X.0 38..
|   3888: 62 72 61 69 6e 73 74 65 6d 03 04 02 00 09 01 73   brainstem......s
|   3904: 03 04 03 00 07 03 6f 72 6d 03 04 04 00 0a 01 73   ......orm......s
|   3920: 03 04 05 00 3a 03 07 08 01 08 08 15 68 02 30 20   ....:.......h.0 
|   3936: 34 36 00 05 62 72 61 69 6e 03 03 02 00 05 05 63   46..brain......c
|   3952: 68 69 6c 64 03 03 03 00 05 02 65 64 03 03 04 00   hild......ed....
|   3968: 05 03 69 6e 67 03 03 05 00 05 01 73 03 03 06 00   ..ing......s....
|   3984: 36 02 07 08 09 08 08 15 62 30 20 34 33 00 05 62   6.......b0 43..b
|   4000: 72 61 67 73 03 02 02 00 03 02 69 64 03 02 03 00   rags......id....
|   4016: 05 02 65 64 03 02 04 00 05 03 69 6e 67 03 02 05   ..ed......ing...
|   4032: 00 05 01 73 03 02 06 00 36 01 07 08 08 08 08 15   ...s....6.......
|   4048: 62 30 20 34 33 00 05 62 72 61 65 73 03 01 02 00   b0 43..braes....
|   4064: 03 01 68 03 01 03 00 04 03 67 65 74 03 01 04 00   ..h......get....
|   4080: 06 01 72 03 01 05 00 05 03 69 6e 67 03 01 06 00   ..r......ing....
| page 5 offset 16384
|      0: 0a 00 00 00 04 0f e7 00 0f fb 0f f5 0f ee 0f e7   ................
|   4064: 00 00 00 00 00 00 00 06 04 08 01 01 03 04 06 04   ................
|   4080: 08 01 01 02 03 05 04 08 09 01 02 04 04 08 08 09   ................
| 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}

#-------------------------------------------------------------------------
#
reset_db
do_test 50.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
.open --hexdb
| size 28672 pagesize 4096 filename crash-14ab65782c9c45.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 02 00 00 00 01 00 00 00 00 00 00 00 00   ................
|     96: 00 00 00 00 0d 0e b1 00 06 0d a4 00 0f 8d 0f 21   ...............!
|    112: 0e b9 0d c8 0e 7e 0d a4 00 00 00 00 00 00 00 00   .....~..........
|   3488: 00 00 00 00 22 07 06 17 11 11 01 31 74 61 62 6c   ...........1tabl
|   3504: 65 74 32 74 32 07 43 52 45 41 54 45 20 54 41 42   et2t2.CREATE TAB
|   3520: 4c 45 20 74 32 28 78 29 81 33 05 07 17 1f 1f 01   LE t2(x).3......
|   3536: 82 35 74 61 62 6c 65 74 31 5f 73 65 67 64 69 72   .5tablet1_segdir
|   3552: 74 31 5f 73 65 67 64 69 72 05 43 52 45 41 54 45   t1_segdir.CREATE
|   3568: 20 54 41 42 4c 45 20 27 74 31 5f 73 65 67 64 69    TABLE 't1_segdi
|   3584: 72 27 28 6c 65 76 65 6c 20 49 4e 54 45 47 45 52   r'(level INTEGER
|   3600: 2c 69 64 78 20 49 4e 54 45 47 45 52 2c 73 74 61   ,idx INTEGER,sta
|   3616: 72 74 5f 62 6c 6f 63 6b 20 49 4e 54 45 47 45 52   rt_block INTEGER
|   3632: 2c 6c 65 61 76 65 73 5f 65 6e 64 5f 62 6c 6f 63   ,leaves_end_bloc
|   3648: 6b 20 49 4e 54 45 47 45 52 2c 65 6e 64 5f 62 6c   k INTEGER,end_bl
|   3664: 6f 63 6b 20 49 4e 54 45 47 45 52 2c 72 6f 6f 74   ock INTEGER,root
|   3680: 20 42 4c 4f 42 2c 50 52 49 4d 41 52 59 20 4b 45    BLOB,PRIMARY KE
|   3696: 59 28 6c 65 76 65 6c 2c 20 69 64 78 29 29 31 06   Y(level, idx))1.
|   3712: 06 17 45 1f 01 00 69 6e 64 65 78 73 71 6c 69 74   ..E...indexsqlit
|   3728: 65 5f 61 75 74 6f 69 6e 64 65 78 5f 74 31 5f 73   e_autoindex_t1_s
|   3744: 65 67 64 69 72 5f 31 74 31 5f 73 65 68 64 69 72   egdir_1t1_sehdir
|   3760: 06 0f c7 00 08 00 00 00 00 66 04 07 17 23 23 01   .........f...##.
|   3776: 81 13 74 61 62 6c 65 74 31 5f 73 65 67 6d 65 6e   ..tablet1_segmen
|   3792: 74 73 74 31 5f 73 65 67 6d 65 6e 74 73 04 43 52   tst1_segments.CR
|   3808: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 73   EATE TABLE 't1_s
|   3824: 65 67 6d 65 6e 74 73 27 28 62 6c 6f 63 6b 69 64   egments'(blockid
|   3840: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59    INTEGER PRIMARY
|   3856: 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42    KEY, block BLOB
|   3872: 29 6a 03 07 17 21 21 01 81 1f 74 61 62 6c 65 74   )j...!!...tablet
|   3888: 31 5f 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74   1_contentt1_cont
|   3904: 65 6e 74 03 43 52 45 41 54 45 20 54 41 42 4c 45   ent.CREATE TABLE
|   3920: 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28 64 6f    't1_content'(do
|   3936: 63 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d   cid INTEGER PRIM
|   3952: 41 52 59 20 4b 45 59 2c 20 27 63 30 61 27 2c 20   ARY KEY, 'c0a', 
|   3968: 27 62 31 62 27 2c 20 27 63 32 63 27 29 38 02 06   'b1b', 'c2c')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 33   LE t1 USING fts3
|   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 25 0b 48 00 0f d8 0f af 0f 86 0f 74   ....%.H........t
|     16: 0f 61 0f 4e 0f 2f 0f 0f 0e ef 0e d7 0e be 0e a5   .a.N./..........
|     32: 0e 8d 0e 74 0e 5b 0e 40 0e 24 0e 08 0d ef 0d d5   ...t.[.@.$......
|     48: 0d bb 0d a0 0d 84 0d 00 00 00 00 00 00 00 00 00   ................
|   2880: 00 00 00 00 00 00 00 00 81 f9 25 06 00 82 7f 00   ..........%.....
|   2896: 00 43 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e   .COMPILER=gcc-5.
|   2912: 34 2e 30 20 32 30 31 36 30 36 30 39 20 44 45 42   4.0 20160609 DEB
|   2928: 55 47 20 45 4e 41 42 4c 45 20 44 42 53 54 41 54   UG ENABLE DBSTAT
|   2944: 20 56 54 41 42 20 45 4e 41 42 4c 45 20 46 54 53    VTAB ENABLE FTS
|   2960: 34 20 45 4e 41 42 4c 45 20 46 54 53 35 20 45 4e   4 ENABLE FTS5 EN
|   2976: 41 42 4c 45 20 47 45 4f 50 4f 4c 59 20 45 4e 41   ABLE GEOPOLY ENA
|   2992: 42 4c 45 20 4a 53 4f 4e 31 20 45 4e 41 42 4c 45   BLE JSON1 ENABLE
|   3008: 20 4d 45 4d 53 59 53 35 20 45 4e 41 42 4c 45 20    MEMSYS5 ENABLE 
|   3024: 52 54 52 45 45 20 4d 41 58 20 4d 45 4d 4f 52 59   RTREE MAX MEMORY
|   3040: 3d 37 a0 30 30 30 30 f2 30 20 4f 4d 49 54 20 4c   =7.0000.0 OMIT L
|   3056: 4f 41 44 20 45 58 54 45 4e 53 49 4f 4e 20 54 48   OAD EXTENSION TH
|   3072: 52 45 41 44 53 41 46 45 3d 30 18 24 05 00 25 0f   READSAFE=0.$..%.
|   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 22   DSAFE=0XNOCASE..
|   3136: 05 00 25 0f 17 54 48 52 45 41 54 53 41 46 45 3d   ..%..THREATSAFE=
|   3152: 30 58 52 54 52 49 4d 1f 21 05 00 33 0f 19 4f 4d   0XRTRIM.!..3..OM
|   3168: 49 54 20 5c 4f 41 44 20 45 58 54 45 4e 53 49 4f   IT .OAD 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 53 49   MIT LOAD EXTENSI
|   3216: 4f 4e 58 4e 4f 43 41 53 46 1e 1f 05 00 33 0f 17   ONXNOCASF....3..
|   3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53   OMIT LOAD EXTENS
|   3248: 49 4f 4e 58 52 44 52 49 4d 1f 1e 05 00 33 0f 19   IONXRDRIM....3..
|   3264: 4d 41 68 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30   MAh MEMORY=50000
|   3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f   000XBINARY....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 33   0000XNOCASE....3
|   3328: 0f 16 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30   ..MAX 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 58 4e 4f 43 41 53 45 17   LE RTREEXNOCASE.
|   3408: 19 05 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52   ...%..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 43 53 59 53 35 58 42 49   NABLE MECSYS5XBI
|   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 53 35 58 52 54 52 49 4d 18 15 05 00 25   MSYS5XRTRIM....%
|   3520: 0f 19 45 4e 41 42 4c 45 20 4a 53 4f 4e 31 58 42   ..ENABLE 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 31 58 4e 4f 43 41 53 45 17   LE JSON1XNOCASE.
|   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 4e 41 42 4c   NARY....)..ENABL
|   3632: 45 20 47 45 4f 50 4f 4c 59 58 4e 4f 43 41 53 45   E GEOPOLYXNOCASE
|   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 19 45 4e 41 42 4c 45 20 46 54 53 35 58 42 49   ..ENABLE FTS5XBI
|   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 58 4e 4f 43 41 53 45 16 0d 05   E FTS5XNOCASE...
|   3728: 00 23 0f 17 45 4e 41 42 4c 45 20 46 54 53 35 58   .#..ENABLE FTS5X
|   3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42   RTRIM....#..ENAB
|   3760: 4c 45 20 46 54 53 34 58 42 49 4e 41 52 59 17 0b   LE FTS4XBINARY..
|   3776: 05 00 23 0f 19 45 4e 41 42 4c 45 20 46 54 53 34   ..#..ENABLE FTS4
|   3792: 58 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 45 4e   XNOCASE....#..EN
|   3808: 41 42 4c 46 20 46 54 53 34 58 52 54 52 49 4d 1e   ABLF FTS4XRTRIM.
|   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: 55 41 54 20 56 54 41 42 58 4e 4f 43 41 53 45 1d   UAT 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 3d 67   ...C..COMPILER=g
|   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 00 00 00 00 00 00 00 00   9XNOCASE........
| page 5 offset 16384
|      0: 0d 00 00 00 02 0b a0 00 0c ad 0b a0 00 00 00 00   ................
|   2976: 82 0a 02 08 08 09 08 08 17 84 06 30 20 32 35 33   ...........0 253
|   2992: 00 01 30 04 25 06 1b 00 00 08 32 30 31 36 30 36   ..0.%.....201606
|   3008: 30 39 03 25 07 00 00 01 34 03 25 05 00 00 01 35   09.%....4.%....5
|   3024: 03 25 04 00 01 07 30 30 30 30 30 30 30 03 25 1a   .%....0000000.%.
|   3040: 00 00 08 63 6f 6d 70 69 6c 65 72 03 25 02 00 00   ...compiler.%...
|   3056: 06 64 62 73 74 61 74 03 25 0a 00 01 04 65 62 75   .dbstat.%....ebu
|   3072: 67 03 25 08 00 00 06 65 6e 61 62 6c 65 09 25 09   g.%....enable.%.
|   3088: 05 04 04 04 04 04 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3104: 6e 03 25 1d 00 00 04 66 74 73 34 03 25 0d 00 03   n.%....fts4.%...
|   3120: 01 35 03 25 0f 00 00 03 67 63 63 03 25 03 00 01   .5.%....gcc.%...
|   3136: 06 65 6f 70 6f 6c 79 03 25 11 00 00 05 6a 73 6f   .eopoly.%....jso
|   3152: 6e 31 03 25 13 00 00 04 6c 6f 61 64 03 25 1c 00   n1.%....load.%..
|   3168: 00 03 6d 61 78 03 25 18 00 01 05 65 6d 6f 72 79   ..max.%....emory
|   3184: 03 25 19 00 03 04 73 79 73 35 03 25 15 00 00 04   .%....sys5.%....
|   3200: 6f 6d 69 74 03 25 1b 00 00 05 72 74 72 65 65 03   omit.%....rtree.
|   3216: 25 17 00 00 0a 74 68 72 65 61 64 73 61 66 65 03   %....threadsafe.
|   3232: 25 1e 00 00 04 76 74 61 62 03 25 0b 00 86 50 01   %....vtab.%...P.
|   3248: 08 08 08 08 08 17 8d 12 30 20 38 33 35 00 01 30   ........0 835..0
|   3264: 12 01 06 00 01 06 00 01 06 00 1f 03 00 01 03 00   ................
|   3280: 01 03 00 00 08 32 30 31 36 30 36 30 39 09 01 07   .....20160609...
|   3296: 00 01 07 00 01 07 00 00 01 34 09 01 05 00 01 05   .........4......
|   3312: 00 01 05 00 00 01 35 09 01 04 00 01 04 00 01 04   ......5.........
|   3328: 00 01 07 30 30 30 30 30 30 30 09 1c 04 00 01 04   ...0000000......
|   3344: 00 01 04 00 00 06 62 69 6e 61 72 79 3c 03 01 02   ......binary<...
|   3360: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3376: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
|   3392: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03   ................
|   3408: 01 02 02 00 03 01 02 02 00 00 08 63 6f 38 70 69   ...........co8pi
|   3424: 6c 65 72 09 01 02 00 01 02 00 01 02 00 00 06 64   ler............d
|   3440: 52 73 74 61 74 09 07 03 00 01 03 00 01 03 00 01   Rstat...........
|   3456: 04 65 62 75 67 09 04 02 00 01 02 00 01 02 00 00   .ebug...........
|   3472: 06 65 6e 61 62 6c 65 3f 07 02 00 01 02 00 01 01   .enable?........
|   3488: ff f1 02 00 01 02 00 01 02 00 01 02 00 01 02 00   ................
|   3504: 01 02 00 01 03 00 01 01 00 02 02 00 01 02 00 01   ................
|   3520: 02 00 01 02 00 01 12 00 01 02 00 01 02 00 01 02   ................
|   3536: 00 01 02 00 01 02 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3552: 6e 09 1f 04 00 01 04 00 01 04 00 00 04 66 74 73   n............fts
|   3568: 34 09 0a 03 00 01 03 00 01 04 00 03 01 35 09 0d   4............5..
|   3584: 03 00 01 03 00 01 03 00 00 03 67 63 63 09 01 03   ..........gcc...
|   3600: 00 01 03 0b 01 13 00 01 06 65 6f 70 6f 6c 79 09   .........eopoly.
|   3616: 10 03 00 01 03 00 01 03 00 00 05 6a 83 6f 6e 31   ...........j.on1
|   3632: 09 13 03 00 01 03 00 01 03 00 00 04 6c 6f 61 64   ............load
|   3648: 09 1f 03 00 01 03 00 01 03 00 00 03 6d 61 78 09   ............max.
|   3664: 1c 02 00 01 02 00 01 02 00 01 05 65 6d 6f 72 79   ...........emory
|   3680: 09 1c 03 00 01 03 00 01 03 00 03 04 73 79 73 35   ............sys5
|   3696: 09 16 03 00 01 03 00 01 03 00 00 06 6e 6f 63 61   ............noca
|   3712: 73 65 3c 02 01 02 02 00 03 01 02 02 00 03 01 02   se<.............
|   3728: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3744: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
|   3760: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 00   ................
|   3776: 04 6f 6d 69 74 09 1f 02 00 01 02 00 01 02 00 00   .omit...........
|   3792: 05 72 74 72 65 65 09 19 03 00 01 03 00 01 03 00   .rtree..........
|   3808: 03 02 69 6d 3c 01 01 02 02 00 03 01 02 02 00 03   ..im<...........
|   3824: 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01   ................
|   3840: 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02   ................
|   3856: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3872: 00 00 0a 74 68 72 65 61 64 73 61 66 65 09 22 02   ...threadsafe...
|   3888: 00 01 02 00 01 02 00 00 04 76 74 61 62 09 07 04   .........vtab...
|   3904: 00 01 04 00 01 04 00 00 01 78 b4 01 01 01 01 02   .........x......
|   3920: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   3936: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   3952: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   3968: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   3984: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4000: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   4016: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   4032: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   4048: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   4064: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4080: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
| page 6 offset 20480
|      0: 0a 00 00 00 02 0f f5 00 0f fb 0f f5 00 00 00 00   ................
|   4080: 00 00 00 00 00 05 04 08 09 01 02 04 04 08 08 09   ................
| page 7 offset 24576
|      0: 0d 00 00 00 05 0f b8 00 0f f4 0f 00 00 00 00 00   ................
|   4016: 00 00 00 00 00 00 00 00 0d 05 02 23 61 75 74 6f   ...........#auto
|   4032: 6d 65 72 67 65 3d 35 0d 04 02 23 6d 65 72 67 65   merge=5...#merge
|   4048: 3d 31 30 30 2c 38 11 03 02 2b 69 6e 74 65 67 72   =100,8...+integr
|   4064: 69 74 79 2d 63 68 65 63 6b 09 02 02 00 00 00 00   ity-check.......
| end crash-14ab65782c9c45.db
}]} {}

do_execsql_test 50.1 {
  SELECT NULL FROM t1 WHERE t1 MATCH '"^enable"'
} {
  {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {}
}

#-------------------------------------------------------------------------
#
reset_db
do_test 51.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
.open --hexdb
| size 28672 pagesize 4096 filename crash-11cf359576eb28.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 02 00 00 00 01 00 00 00 07 00 00 00 04   ................
|     96: 00 00 00 00 0d 0e b1 00 06 0d a4 00 0f 8d 0f 21   ...............!
|    112: 0e b9 0d c8 0e 7e 0d a4 0d a4 00 00 00 00 00 00   .....~..........
|   3488: 00 00 00 00 22 07 06 17 11 11 01 31 74 61 62 6c   ...........1tabl
|   3504: 65 74 32 74 32 07 43 52 45 41 54 45 20 54 41 42   et2t2.CREATE TAB
|   3520: 4c 45 20 74 32 28 78 29 81 33 05 07 17 1f 1f 01   LE t2(x).3......
|   3536: 82 35 74 61 62 6c 65 74 31 5f 73 65 67 64 69 72   .5tablet1_segdir
|   3552: 74 31 5f 73 65 67 64 69 72 05 43 52 45 41 54 45   t1_segdir.CREATE
|   3568: 20 54 41 42 4c 45 20 27 74 31 5f 73 65 67 64 69    TABLE 't1_segdi
|   3584: 72 27 28 6c 65 76 65 6c 20 49 4e 54 45 47 45 52   r'(level INTEGER
|   3600: 2c 69 64 78 20 49 4e 54 45 47 45 52 2c 73 74 61   ,idx INTEGER,sta
|   3616: 72 74 5f 62 6c 6f 63 6b 20 49 4e 54 45 47 45 52   rt_block INTEGER
|   3632: 2c 6c 65 61 76 65 73 5f 65 6e 64 5f 62 6c 6f 63   ,leaves_end_bloc
|   3648: 6b 20 49 4e 54 45 47 45 52 2c 65 6e 64 5f 62 6c   k INTEGER,end_bl
|   3664: 6f 63 6b 20 49 4e 54 45 47 45 52 2c 72 6f 6f 74   ock INTEGER,root
|   3680: 20 42 4c 4f 42 2c 50 52 49 4d 41 52 59 20 4b 45    BLOB,PRIMARY KE
|   3696: 59 28 6c 65 76 65 6c 2c 20 69 64 78 29 29 31 06   Y(level, idx))1.
|   3712: 06 17 45 1f 01 00 69 6e 64 65 78 73 71 6c 69 74   ..E...indexsqlit
|   3728: 65 5f 61 75 74 6f 69 6e 64 65 78 5f 74 31 5f 73   e_autoindex_t1_s
|   3744: 65 67 64 69 72 5f 31 74 31 5f 73 65 67 64 69 72   egdir_1t1_segdir
|   3760: 06 0f c7 00 08 00 00 00 00 66 04 07 17 23 23 01   .........f...##.
|   3776: 81 13 74 61 62 6c 65 74 31 5f 73 65 67 6d 65 6e   ..tablet1_segmen
|   3792: 74 73 74 31 5f 73 65 67 6d 65 6e 74 73 04 43 52   tst1_segments.CR
|   3808: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 73   EATE TABLE 't1_s
|   3824: 65 67 6d 65 6e 74 73 27 28 62 6c 6f 63 6b 69 64   egments'(blockid
|   3840: 20 49 4e 54 45 47 45 52 20 50 51 49 4d 41 52 59    INTEGER PQIMARY
|   3856: 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42    KEY, block BLOB
|   3872: 29 6a 03 07 17 21 21 01 81 1f 74 61 62 6c 65 74   )j...!!...tablet
|   3888: 31 5f 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74   1_contentt1_cont
|   3904: 65 6e 74 03 43 52 45 41 54 45 20 54 41 42 4c 45   ent.CREATE TABLE
|   3920: 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28 64 6f    't1_content'(do
|   3936: 63 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d   cid INTEGER PRIM
|   3952: 41 52 59 20 4b 45 59 2c 20 27 63 30 61 27 2c 20   ARY KEY, 'c0a', 
|   3968: 27 63 31 62 27 2c 20 27 63 32 63 27 29 38 02 06   'c1b', 'c2c')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 33   LE t1 USING fts3
|   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 25 0b 48 00 0f d8 0f af 0f 86 0f 74   ....%.H........t
|     16: 0f 61 0f 4e 0f 2f 0f 0f 0e ef 0e d7 0e be 0e a5   .a.N./..........
|     32: 0e 8d 0e 74 0e 5b 0e 40 0e 24 0e 08 0d ef 0d d5   ...t.[.@.$......
|     48: 0d bb 0d a0 0d 84 0d 68 0d 4f 0d 35 0d 1b 0c fb   .......h.O.5....
|     64: 0c da 0c b9 0c 99 0c 78 0c 57 0c 3e 0c 24 0c 0a   .......x.W.>.$..
|     80: 0b 48 00 00 00 00 00 00 00 00 00 00 00 00 00 00   .H..............
|   2880: 00 00 00 00 00 00 00 00 81 3f 25 06 00 82 7f 00   .........?%.....
|   2896: 00 43 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e   .COMPILER=gcc-5.
|   2912: 34 2e 30 20 32 30 31 36 30 36 30 39 20 44 45 42   4.0 20160609 DEB
|   2928: 55 47 20 45 4e 41 42 4c 45 20 44 42 53 54 41 54   UG ENABLE DBSTAT
|   2944: 20 56 54 41 42 20 45 4e 41 42 4c 45 20 46 54 53    VTAB ENABLE FTS
|   2960: 34 20 45 4e 41 42 4c 45 20 46 54 53 35 20 45 4e   4 ENABLE FTS5 EN
|   2976: 41 42 4c 45 20 47 45 4f 59 0f 4c 59 20 45 4e 41   ABLE GEOY.LY ENA
|   2992: 42 4c 45 20 4a 53 4f 4e 31 20 45 4e 41 42 4c 45   BLE JSON1 ENABLE
|   3008: 20 4d 45 4d 53 59 53 35 20 45 4e 41 42 4c 45 20    MEMSYS5 ENABLE 
|   3024: 52 54 52 45 45 20 4d 41 58 20 4d 45 4d 4f 52 59   RTREE MAX MEMORY
|   3040: 3d 35 30 30 30 30 30 30 30 20 4f 4d 49 54 20 4d   =50000000 OMIT M
|   3056: 4f 41 44 20 45 58 54 45 4e 53 49 4f 4e 20 54 48   OAD EXTENSION TH
|   3072: 52 45 41 44 53 41 46 45 3d 30 18 24 05 00 25 0f   READSAFE=0.$..%.
|   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 22   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 4f 4d   0XRTRIM.!..3..OM
|   3168: 49 54 20 4c 4f 41 44 20 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 53 49   MIT LOAD EXTENSI
|   3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17   ONXNOCASE....3..
|   3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53   OMIT LOAD EXTENS
|   3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19   IONXRTRIM....3..
|   3264: 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30   MAX MEMORY=50000
|   3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f   000XBINARY....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 33   0000XNOCASE....3
|   3328: 0f 17 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30   ..MAX 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 58 4e 4f 43 41 53 45 17   LE RTREEXNOCASE.
|   3408: 19 05 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52   ...%..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 53 35 58 52 54 52 49 4d 18 15 05 00 25   MSYS5XRTRIM....%
|   3520: 0f 19 45 4e 41 42 4c 45 20 4a 53 4f 4e 31 58 42   ..ENABLE 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 31 58 4e 4f 43 41 53 45 17   LE JSON1XNOCASE.
|   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 4e 41 42 4c   NARY....)..ENABL
|   3632: 45 20 47 45 4f 50 4f 4c 59 58 4e 4f 43 41 53 45   E GEOPOLYXNOCASE
|   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 19 45 4e 41 42 4c 45 20 46 54 53 35 58 42 49   ..ENABLE FTS5XBI
|   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 58 4e 4f 43 41 53 45 16 0d 05   E FTS5XNOCASE...
|   3728: 00 23 0f 17 45 4e 41 42 4c 45 20 46 54 53 35 58   .#..ENABLE FTS5X
|   3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42   RTRIM....#..ENAB
|   3760: 4c 45 20 46 54 53 34 58 42 49 4e 41 52 59 17 0b   LE FTS4XBINARY..
|   3776: 05 00 23 0f 19 45 4e 41 42 4c 45 20 46 54 53 34   ..#..ENABLE FTS4
|   3792: 58 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 45 4e   XNOCASE....#..EN
|   3808: 41 42 4c 45 20 46 54 53 34 58 52 54 52 49 4d 1e   ABLE FTS4XRTRIM.
|   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 10 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 3d 67   ...C..COMPILER=g
|   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 43   9XNOCASE&...C..C
|   4064: 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e   OMPILER=gcc-5.4.
|   4080: 30 20 32 30 31 36 30 36 30 39 58 52 54 52 49 4d   0 20160609XRTRIM
| 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 02 0b a0 00 0c ad 0b a0 00 00 00 00   ................
|   2976: 82 0a 02 08 08 09 08 08 17 84 06 30 20 32 35 33   ...........0 253
|   2992: 00 01 30 04 25 06 1b 00 00 08 32 30 31 36 30 36   ..0.%.....201606
|   3008: 30 39 03 25 07 00 00 01 34 03 25 05 00 00 01 35   09.%....4.%....5
|   3024: 03 25 04 00 01 07 30 30 30 30 30 30 30 03 25 1a   .%....0000000.%.
|   3040: 00 00 08 63 6f 6d 70 69 6c 65 72 03 25 02 00 00   ...compiler.%...
|   3056: 06 64 62 73 74 61 74 03 25 0a 00 01 04 65 62 75   .dbstat.%....ebu
|   3072: 67 03 25 08 00 00 06 65 6e 61 62 6c 65 09 25 09   g.%....enable.%.
|   3088: 05 04 04 04 04 04 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3104: 6e 03 25 1d 00 00 04 66 74 73 34 03 25 0d 00 03   n.%....fts4.%...
|   3120: 01 35 03 25 0f 00 00 03 67 63 63 03 25 03 00 01   .5.%....gcc.%...
|   3136: 06 65 6f 70 6f 6c 79 03 25 11 00 00 05 6a 73 6f   .eopoly.%....jso
|   3152: 6e 31 03 25 13 00 00 04 6c 6f 61 64 03 25 1c 00   n1.%....load.%..
|   3168: 00 03 6d 61 78 03 25 18 00 01 05 65 6d 6f 72 79   ..max.%....emory
|   3184: 03 25 19 00 03 04 73 79 73 35 03 25 15 00 00 04   .%....sys5.%....
|   3200: 6f 6d 69 74 03 25 1b 00 00 05 72 74 72 65 65 03   omit.%....rtree.
|   3216: 25 17 00 00 0a 74 68 72 65 61 64 73 61 66 65 03   %....threadsafe.
|   3232: 25 1e 00 00 04 76 74 61 62 03 25 0b 00 86 50 01   %....vtab.%...P.
|   3248: 08 08 08 08 08 17 8d 12 30 20 38 33 35 00 01 30   ........0 835..0
|   3264: 12 01 06 00 01 06 00 01 06 00 1f 03 00 01 03 00   ................
|   3280: 01 03 00 00 08 32 30 31 36 30 36 30 39 09 01 07   .....20160609...
|   3296: 00 01 07 00 01 07 00 00 01 34 09 01 05 00 01 05   .........4......
|   3312: 00 01 05 00 00 01 35 09 01 04 00 01 04 00 01 04   ......5.........
|   3328: 00 01 07 30 30 30 30 30 30 30 09 1c 04 00 01 04   ...0000000......
|   3344: 00 01 04 00 00 06 62 69 6e 61 72 79 3c 03 01 02   ......binary<...
|   3360: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3376: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 5f   ..............._
|   3392: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03   ................
|   3408: 01 02 02 00 03 01 02 02 00 00 08 63 6f 6d 70 69   ...........compi
|   3424: 6c 65 72 09 01 02 00 01 02 00 01 02 00 00 06 64   ler............d
|   3440: 62 73 74 61 74 09 07 03 00 01 03 00 01 03 00 01   bstat...........
|   3456: 04 65 62 75 67 09 04 02 00 01 02 00 01 02 00 00   .ebug...........
|   3472: 06 65 6e 61 62 6c 65 3f 07 02 00 01 02 00 01 02   .enable?........
|   3488: 00 01 02 00 01 02 00 01 02 00 01 02 00 01 02 00   ................
|   3504: 01 02 00 01 02 00 01 02 00 01 02 00 01 02 00 01   ................
|   3520: 02 00 01 01 00 01 02 00 01 02 00 01 02 00 01 02   ................
|   3536: 00 01 02 00 01 02 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
|   3552: 6e 09 1f 04 00 01 04 00 01 04 00 00 04 66 74 73   n............fts
|   3568: 34 09 0a 03 00 01 03 00 01 03 00 03 01 35 09 0d   4............5..
|   3584: 03 00 01 03 00 01 03 00 00 03 67 63 63 09 01 03   ..........gcc...
|   3600: 00 01 03 00 01 03 00 01 06 65 6f 70 6f 6c 79 09   .........eopoly.
|   3616: 10 03 00 01 03 00 01 03 00 00 05 6a 73 6f 6e 31   ...........json1
|   3632: 09 13 03 00 01 03 00 01 03 00 00 04 6c 6f 61 64   ............load
|   3648: 09 1f 03 00 01 03 00 01 03 00 00 03 6d 61 78 09   ............max.
|   3664: 1c 02 00 01 02 00 01 02 00 01 05 65 6d 6f 72 79   ...........emory
|   3680: 09 1c 03 00 01 03 00 01 03 00 03 04 73 79 73 35   ............sys5
|   3696: 09 16 03 00 01 03 00 01 03 00 00 06 6e 6f 63 61   ............noca
|   3712: 73 65 3c 02 01 02 02 00 03 01 02 02 00 03 01 02   se<.............
|   3728: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3744: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
|   3760: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 00   ................
|   3776: 04 6f 6d 69 74 09 1f 02 00 01 02 00 01 02 00 00   .omit...........
|   3792: 05 72 74 72 65 65 09 19 03 00 01 03 00 01 03 00   .rtree..........
|   3808: 03 02 69 6d 3c 01 01 02 02 00 03 01 02 02 00 03   ..im<...........
|   3824: 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01   ................
|   3840: 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02   ................
|   3856: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
|   3872: 00 00 0a 74 68 72 65 61 64 73 61 66 65 09 22 02   ...threadsafe...
|   3888: 00 01 02 00 01 02 00 00 04 76 74 61 62 09 07 04   .........vtab...
|   3904: 00 01 04 00 01 04 00 00 01 78 b4 01 01 01 01 02   .........x......
|   3920: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   3936: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   3952: 01 01 03 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   3968: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   3984: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4000: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
|   4016: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
|   4032: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
|   4048: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
|   4064: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
|   4080: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
| page 6 offset 20480
|      0: 0a 00 00 00 02 0f f5 00 0f fb 0f f5 00 00 00 00   ................
|   4080: 00 00 00 00 00 05 04 08 09 01 02 04 04 08 08 09   ................
| page 7 offset 24576
|      0: 0d 00 00 00 05 0f b8 00 0f f4 0f e9 0f d6 00 00   ................
|   4016: 00 00 00 00 00 00 00 00 0d 05 02 23 61 75 74 6f   ...........#auto
|   4032: 6d 65 72 67 65 3d 35 0d 04 02 23 6d 65 72 67 65   merge=5...#merge
|   4048: 3d 31 30 30 2c 38 11 03 02 2b 69 6e 74 65 67 72   =100,8...+integr
|   4064: 69 74 79 2d 63 68 65 63 6b 09 02 02 1b 72 65 62   ity-check....reb
|   4080: 75 69 6c 64 0a 01 02 1d 6f 70 74 69 6d 69 7a 65   uild....optimize
| end crash-11cf359576eb28.db
}]} {}

set saved $sqlite_fts3_enable_parentheses
set sqlite_fts3_enable_parentheses 1
do_catchsql_test 51.1 {
  SELECT 'xyzzy',offsets(t1) FROM t1 WHERE t1 MATCH 'rtree OR json1''rtree NEAR "json1 enable"';
} {1 {database disk image is malformed}}
set sqlite_fts3_enable_parentheses $saved

#-------------------------------------------------------------------------
#
set saved $sqlite_fts3_enable_parentheses
set sqlite_fts3_enable_parentheses 1
reset_db
do_test 52.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
.open --hexdb
| size 28672 pagesize 4096 filename crash-fd33f4b1c8348b.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 92 00 00 00 07   .....@  ........
|     32: 00 00 00 00 00 00 00 00 00 00 00 07 00 00 00 04   ................
|     96: 00 00 00 00 0d 0e ef 00 08 0d 13 00 0f bd 0f 5f   ..............._
|    112: 0e f7 0e 06 0e bc 0d a4 0d 4d 0d 13 00 00 00 00   .........M......
|   3344: 00 00 00 38 08 06 17 11 11 08 5f 74 61 62 6c 65   ...8......_table
|   3360: 74 32 74 32 43 52 45 41 54 45 20 56 49 52 54 55   t2t2CREATE VIRTU
|   3376: 41 4c 20 54 41 42 4c 45 20 74 32 20 55 53 49 4e   AL TABLE t2 USIN
|   3392: 47 20 66 74 73 34 61 75 78 28 74 31 29 55 07 07   G fts4aux(t1)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 64 45 47 45 52 2c 73 74 61 72 74   dx INdEGER,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 50 52 49 4d 41 52 59 20 4b   NTEGER PRIMARY 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 e6 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 31 2c 32 27 29   (a,prefix='1,2')
| page 2 offset 4096
|      0: 0d 00 00 00 08 0e 22 00 0f c4 0f 00 00 00 00 00   ................
|   3616: 00 00 42 08 04 00 81 09 73 75 6e 74 20 69 6e 20   ..B.....sunt in 
|   3632: 63 75 6c 70 61 20 71 75 69 20 6f 66 66 69 63 69   culpa qui offici
|   3648: 61 20 64 65 73 65 72 75 6e 74 20 6d 6f 6c 6c 69   a deserunt molli
|   3664: 74 20 61 6e 69 6d 20 69 64 20 65 73 74 20 7c 61   t anim id est |a
|   3680: 62 6f 72 75 6d 2e 32 07 03 00 6b 45 78 63 65 70   borum.2...kExcep
|   3696: 74 65 75 72 20 73 69 6e 74 20 6f 63 63 61 65 63   teur sint occaec
|   3712: 61 74 20 63 75 70 69 64 61 74 61 74 20 6e 6f 6e   at cupidatat non
|   3728: 20 70 72 6f 69 64 65 6e 74 2c 29 06 03 00 59 63    proident,)...Yc
|   3744: 69 6c 6c 75 6d 20 64 6f 6c 6f 72 65 20 65 20 66   illum dolore e f
|   3760: 75 67 69 61 74 20 6e 75 6c 6c 61 20 70 61 72 69   ugiat nulla pari
|   3776: 61 74 75 72 2e 42 05 04 00 81 09 44 75 69 73 20   atur.B.....Duis 
|   3792: 61 75 74 65 20 69 72 75 72 65 20 64 6f 6c 6f 72   aute irure dolor
|   3808: 20 69 6e 20 72 65 60 72 65 68 65 6e 64 65 72 69    in re`rehenderi
|   3824: 74 20 69 6e 20 76 70 6c 75 70 74 61 74 65 20 76   t in vpluptate v
|   3840: 65 6c 69 72 c0 65 73 73 65 29 04 03 00 59 6e 69   elir.esse)...Yni
|   3856: 73 6a 20 75 74 20 61 6c 69 71 75 69 70 20 65 20   sj ut aliquip e 
|   3872: 65 20 63 6f 6d 6d 6f 64 6f 20 63 6f 6e 73 65 71   e commodo conseq
|   3888: 75 61 74 2e 46 03 04 00 29 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 7a 71 74 69 6f 6e 20 75 6c 6c   exercizqtion 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: 72 63 75 6d 20 64 6f 6c 6f 72 20 73 69 74 20 61   rcum dolor sit a
|   4064: 6d 65 74 2c 20 63 6f 6e 78 65 63 74 65 64 75 72   met, conxectedur
|   4080: 20 61 64 69 70 69 73 00 00 00 00 00 00 00 00 00    adipis.........
| page 4 offset 12288
|      0: 0d 00 00 00 03 0a c1 00 0d 61 0c 54 0a c1 00 00   .........a.T....
|   2752: 00 83 10 03 08 02 08 08 08 17 86 0e 08 00 30 20   ..............0 
|   2768: 33 38 35 00 02 61 64 06 01 08 00 02 04 00 01 01   385..ad.........
|   2784: 6c 06 02 0c 00 02 04 00 01 01 6d 03 01 06 10 01   l.........m.....
|   2800: 01 6e 03 08 09 00 01 01 75 03 05 03 00 00 02 63   .n......u......c
|   2816: 69 03 06 02 00 01 01 6f 07 01 07 00 03 07 03 00   i......o........
|   2832: 01 01 75 06 75 05 00 01 04 00 00 02 64 65 03 08   ..u.u.......de..
|   2848: 07 00 01 01 6f 0d 01 04 00 01 03 09 00 03 05 00   ....o...........
|   2864: 01 03 00 01 01 75 03 05 02 00 00 02 65 69 03 02   .....u......ei..
|   2880: 04 00 01 01 6c 03 01 44 00 01 01 6e 03 03 03 00   ....l..D...n....
|   2896: 01 01 73 06 05 0b 00 03 0b 00 01 01 74 03 02 09   ..s.........t...
|   2912: 00 01 01 78 06 03 09 00 04 02 00 00 02 66 75 03   ...x.........fu.
|   2928: 06 05 00 00 02 69 64 03 08 0a 00 01 01 6e 0a 02   .....id......n..
|   2944: 06 00 03 06 04 00 03 03 00 01 01 70 03 01 03 00   ...........p....
|   2960: 01 01 72 03 05 04 00 00 02 6c 61 09 02 08 00 01   ..r......la.....
|   2976: 0b 00 05 0c 00 01 01 6f 03 01 02 00 00 02 6d 61   .......o......ma
|   2992: 03 02 0b 00 01 01 69 03 03 05 00 01 01 6f 03 08   ......i......o..
|   3008: 08 00 00 02 6e 69 03 04 02 00 01 01 6f 06 03 08   ....ni......o...
|   3024: 00 04 06 00 01 01 75 03 06 06 00 00 02 6f 63 03   ......u......oc.
|   3040: 07 04 00 01 01 66 03 08 06 00 00 02 70 61 03 06   .....f......pa..
|   3056: 07 00 01 11 72 03 07 07 00 00 02 71 75 06 03 07   ....r......qu...
|   3072: 00 05 05 00 00 02 72 65 03 05 07 00 00 02 73 65   ......re......se
|   3088: 03 02 02 00 01 01 69 06 01 05 00 06 03 00 01 01   ......i.........
|   3104: 75 03 08 02 00 00 02 74 65 03 02 05 00 00 02 75   u......te......u
|   3120: 6c 13 03 0a 00 01 01 74 09 02 07 00 01 02 00 01   l......t........
|   3136: 02 ff ff 02 76 65 06 03 06 00 02 0a 00 01 01 6f   ....ve.........o
|   3152: 03 05 09 00 82 0a 02 08 02 08 08 08 17 84 02 04   ................
|   3168: 00 30 20 32 35 31 00 01 61 13 01 06 04 00 01 0c   .0 251..a.......
|   3184: 00 01 04 00 01 04 00 01 03 00 03 09 00 00 01 63   ...............c
|   3200: 10 01 07 00 03 07 03 00 02 02 00 01 05 00 01 04   ................
|   3216: 00 00 01 64 11 01 04 00 01 03 09 00 03 02 05 00   ...d............
|   3232: 01 03 00 02 07 00 00 01 65 1b 01 09 00 01 04 07   ........e.......
|   3248: 00 01 03 08 00 01 05 03 00 01 1c eb 01 04 00 01   ................
|   3264: 0e 80 01 0b 00 00 01 66 03 06 05 00 00 01 69 0f   .......f......i.
|   3280: 01 03 00 01 06 0b 23 04 04 04 00 03 03 09 00 00   ......#.........
|   3296: 01 6c 0c 01 02 00 01 08 00 01 0b 00 05 0c 00 00   .l..............
|   3312: 01 6d 09 02 0b 00 01 05 00 05 08 00 00 01 6e 0c   .m............n.
|   3328: 03 08 00 01 02 00 02 06 00 01 06 00 00 01 6f 06   ..............o.
|   3344: 07 04 00 01 06 00 00 01 70 06 06 07 00 01 07 00   ........p.......
|   3360: 00 01 71 06 03 07 00 05 05 00 00 01 72 03 05 07   ..q.........r...
|   3376: 00 00 02 73 0c 01 05 00 01 02 00 05 03 00 01 02   ...s............
|   3392: 00 00 01 74 03 02 05 00 00 01 75 0a 02 07 00 01   ...t......u.....
|   3408: 02 0a 00 01 03 00 00 01 76 07 03 06 00 02 09 03   ........v.......
|   3424: 00 85 1c 01 08 08 08 08 08 17 8a 2a 30 20 36 35   ...........*0 65
|   3440: 35 00 02 61 64 03 03 04 00 02 08 69 70 69 73 63   5..ad......ipisc
|   3456: 69 6e 67 03 01 08 00 01 05 6c 69 71 75 61 03 02   ing......liqua..
|   3472: 0c 00 05 02 69 70 03 04 04 00 01 03 6d 65 74 03   ....ip......met.
|   3488: 01 06 00 01 03 6e 69 6d 03 08 09 00 01 03 75 74   .....nim......ut
|   3504: 65 03 05 03 00 00 06 63 69 6c 6c 75 6d 03 06 02   e......cillum...
|   3520: 00 01 06 6f 6d 6d 6f 64 6f 03 04 07 00 02 09 6e   ...ommodo......n
|   3536: 73 65 63 74 65 74 75 72 03 01 07 00 05 04 71 75   sectetur......qu
|   3552: 61 73 03 04 08 00 01 04 75 6c 70 61 03 08 04 00   as......ulpa....
|   3568: 02 07 70 69 64 61 74 61 74 03 07 05 00 00 08 64   ..pidatat......d
|   3584: 65 73 65 72 75 6e 74 03 08 07 00 01 01 6f 03 09   eserunt......o..
|   3600: b3 00 02 03 6c 6f 72 06 01 04 00 04 05 00 05 01   ....lor.........
|   3616: 65 06 02 0a 00 04 03 00 01 03 75 69 73 03 05 02   e.........uis...
|   3632: 00 00 01 65 07 04 05 03 00 02 04 00 01 06 69 75   ...e..........iu
|   3648: 73 6d 6f 64 03 02 04 00 01 03 6c 69 74 03 01 09   smod......lit...
|   3664: 00 01 03 6e 69 6d 03 03 03 00 01 03 73 73 65 03   ...nim......sse.
|   3680: 05 0b 00 02 01 74 03 08 0b 00 01 01 74 03 02 09   .....t......t...
|   3696: 00 01 08 78 63 65 70 64 65 75 72 03 07 02 00 02   ...xcepdeur.....
|   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 6c f3 01 03 00 01 04 72 75 72 65 03 05 04 00   ul......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 15 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 01 ff ff f0   t......sed......
|   4000: b9 6e 74 03 07 03 00 02 01 74 03 01 05 00 01 03   .nt......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 00 00 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 00 00 01 00 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 0d fa 04 02 03 00 0e 0b 04 00 00 00 00 00   ................
| page 7 offset 24576
|   4080: 00 00 00 00 00 00 00 07 00 03 00 00 00 00 00 00   ................
| end crash-fd33f4b1c8348b.db
}]} {}

do_catchsql_test 52.1 {
  SELECT * FROM t1, t2;
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
#
reset_db
do_test 53.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
.open --hexdb
| size 8192 pagesize 1024 filename crash-7bc.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: 04 00 01 01 00 40 20 20 00 00 00 00 00 00 00 08   .....@  ........
|     32: 00 00 00 00 00 00 00 00 00 00 00 06 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 02 f3 00 07 01 51 00 03 c8 03 63   ..........Q....c
|    112: 02 fb 02 0a 02 c0 01 a8 01 51 00 00 00 00 00 00   .........Q......
|    336: 00 55 07 07 17 1b 1b 01 81 01 74 61 62 6c 65 74   .U........tablet
|    352: 31 5f 73 74 61 74 74 31 5f 73 74 61 74 07 43 52   1_statt1_stat.CR
|    368: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 73   EATE TABLE 't1_s
|    384: 74 61 74 27 28 69 64 20 49 4e 54 45 47 45 52 20   tat'(id INTEGER 
|    400: 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 76 61 6c   PRIMARY KEY, val
|    416: 75 65 20 42 4c 4f 42 29 60 06 07 17 21 21 01 81   ue BLOB)`...!!..
|    432: 0b 74 61 62 6c 65 74 31 5f 64 6f 63 73 69 7a 65   .tablet1_docsize
|    448: 74 31 5f 64 6f 63 73 69 7a 65 06 43 52 45 41 54   t1_docsize.CREAT
|    464: 45 20 54 41 42 4c 45 20 27 74 31 5f 64 6f 63 73   E TABLE 't1_docs
|    480: 69 7a 65 27 28 64 6f 63 69 64 20 49 4e 54 45 47   ize'(docid INTEG
|    496: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20   ER PRIMARY KEY, 
|    512: 73 69 7a 65 20 42 4c 4f 42 29 81 33 04 07 17 1f   size BLOB).3....
|    528: 1f 01 82 35 74 61 62 6c 65 74 31 5f 73 65 67 64   ...5tablet1_segd
|    544: 69 72 74 31 5f 73 65 67 64 69 72 04 43 52 45 41   irt1_segdir.CREA
|    560: 54 45 20 54 41 42 4c 45 20 27 74 31 5f 73 65 67   TE TABLE 't1_seg
|    576: 64 69 72 27 28 6c 65 76 65 6c 20 49 4e 54 45 47   dir'(level INTEG
|    592: 45 52 2c 69 64 78 20 49 4e 54 45 47 45 52 2c 73   ER,idx INTEGER,s
|    608: 74 61 72 74 5f 62 6c 6f 63 6b 20 49 4e 54 45 47   tart_block INTEG
|    624: 45 52 2c 6c 65 61 76 65 73 5f 65 6e 64 5f 62 6c   ER,leaves_end_bl
|    640: 6f 63 6b 20 49 4e 54 45 47 45 52 2c 65 6e 64 5f   ock INTEGER,end_
|    656: 62 6c 6f 63 6b 20 49 4e 54 45 47 45 52 2c 72 6f   block INTEGER,ro
|    672: 6f 74 20 42 4c 4f 42 2c 50 52 49 4d 41 52 59 20   ot BLOB,PRIMARY 
|    688: 4b 45 59 28 6c 65 76 65 6c 2c 20 69 64 78 29 29   KEY(level, idx))
|    704: 31 05 06 17 45 1f 01 00 69 6e 64 65 78 73 71 6c   1...E...indexsql
|    720: 69 74 65 5f 61 75 74 6f 69 6e 64 65 78 5f 74 31   ite_autoindex_t1
|    736: 5f 73 65 67 64 69 72 5f 31 74 31 5f 73 65 67 64   _segdir_1t1_segd
|    752: 69 72 05 00 00 00 08 00 00 00 00 66 03 07 17 23   ir.........f...#
|    768: 23 01 81 13 74 61 62 6c 65 74 31 5f 73 65 67 6d   #...tablet1_segm
|    784: 65 6e 74 73 74 31 5f 73 65 67 6d 65 6e 74 73 03   entst1_segments.
|    800: 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 31   CREATE TABLE 't1
|    816: 5f 73 65 67 6d 65 6e 74 73 27 28 62 6c 6f 63 6b   _segments'(block
|    832: 69 64 20 49 4e 53 45 47 45 52 20 50 52 49 4d 41   id INSEGER PRIMA
|    848: 52 59 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c   RY KEY, block BL
|    864: 4f 42 29 63 02 07 17 21 21 01 81 11 74 61 62 6c   OB)c...!!...tabl
|    880: 65 74 31 5f 63 6f 6e 74 65 6e 74 74 31 5f 63 6f   et1_contentt1_co
|    896: 6e 74 65 6e 74 02 43 52 45 41 54 45 20 54 41 42   ntent.CREATE TAB
|    912: 4c 45 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28   LE 't1_content'(
|    928: 64 6f 63 69 64 20 49 4e 54 45 47 45 52 20 50 52   docid INTEGER PR
|    944: 49 4d 41 52 59 20 4b 45 59 2c 20 27 63 30 30 27   IMARY KEY, 'c00'
|    960: 2c 20 27 63 31 62 27 29 36 01 06 17 11 11 08 5b   , 'c1b')6......[
|    976: 74 61 62 6c 65 74 31 74 31 43 52 45 41 54 45 20   tablet1t1CREATE 
|    992: 56 49 52 54 55 41 4c 20 54 41 42 4c 45 20 74 31   VIRTUAL TABLE t1
|   1008: 20 55 53 49 4e 47 20 66 74 73 34 28 30 2c 62 29    USING fts4(0,b)
| page 2 offset 1024
|      0: 0d 00 00 00 03 00 0f 00 00 23 00 16 00 0f 00 05   .........#......
|     16: 03 04 00 08 0f 61 0b 02 04 00 08 1b 41 54 45 20   .....a......ATE 
|     32: 32 3a 50 87 5a 01 05 00 08 8f 37 66 30 30 30 30   2:P.Z.....7f0000
|     48: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|     64: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|     80: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|     96: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    112: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    128: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    144: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    160: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    176: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    192: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    208: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    224: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    240: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    256: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    272: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    288: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    304: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    320: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    336: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    352: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    368: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    384: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    400: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    416: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    432: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    448: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    464: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    480: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    496: 30 40 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0@00000000000000
|    512: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    528: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    544: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    560: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    576: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    592: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    608: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    624: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    640: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    656: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    672: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    688: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    704: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    720: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    736: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    752: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    768: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    784: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    800: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    816: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    832: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    848: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    864: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    880: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    896: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    912: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    928: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    944: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    960: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    976: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    992: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|   1008: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
| page 3 offset 2048
|      0: 0d 00 00 00 02 03 86 00 03 f4 03 86 00 00 00 00   ................
|    896: 00 00 00 00 00 00 87 62 02 04 00 8f 48 00 d5 07   .......b....H...
|    912: 66 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   f000000000000000
|    928: 30 30 30 30 3a 30 30 30 30 30 30 30 30 30 30 30   0000:00000000000
|    944: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    960: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    976: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    992: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|   1008: 00 00 00 08 0a 01 03 00 1a 00 01 30 03 01 02 00   ...........0....
| page 4 offset 3072
|      0: 0d 00 00 00 03 03 9e 00 03 ed 03 bc 03 9e 00 00   ................
|    912: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1c 03   ................
|    928: 07 08 01 08 08 15 2c 02 30 20 31 36 00 01 30 03   ......,.0 16..0.
|    944: 03 02 00 00 01 61 05 03 01 01 02 00 2f 02 07 08   .....a....../...
|    960: 09 08 08 15 54 30 20 33 36 00 01 30 03 02 02 00   ....T0 36..0....
|    976: 00 01 32 05 02 01 01 03 00 00 03 61 74 65 05 02   ..2........ate..
|    992: 01 01 02 00 00 01 70 05 02 01 01 04 00 11 01 07   ......p.........
|   1008: 08 08 09 01 17 14 02 32 20 39 39 37 01 01 01 66   .......2 997...f
| page 5 offset 4096
|      0: 0a 00 00 00 03 03 ee 00 03 fb 03 f5 03 ee 00 00   ................
|    992: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 06 04   ................
|   1008: 08 01 01 02 03 05 04 08 09 01 02 04 04 08 08 09   ................
| page 6 offset 5120
|      0: 0d 00 00 00 03 03 eb 00 00 00 00 00 00 00 00 00   ................
|    992: 00 00 00 00 00 00 00 00 00 00 00 05 03 03 00 10   ................
|   1008: 01 01 05 02 03 00 10 01 03 05 01 03 00 10 01 01   ................
| page 7 offset 6144
|      0: 0d 00 00 00 01 03 f6 00 03 f6 00 00 00 00 00 00   ................
|   1008: 00 00 00 00 00 00 08 00 03 00 16 03 08 c5 e0 07   ................
| page 8 offset 7168
|      0: 00 00 00 00 30 30 30 30 30 30 30 30 30 30 30 30   ....000000000000
|     16: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|     32: 30 30 30 30 30 30 30 30 30 30 30 30 30 bc 30 30   0000000000000.00
|     48: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|     64: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|     80: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|     96: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    112: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    128: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    144: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    160: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    176: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    192: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 c0 30   00000000000000.0
|    208: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    224: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    240: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    256: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    272: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    288: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    304: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    320: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    336: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    352: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    368: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    384: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    400: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    416: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    432: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    448: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    464: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    480: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    496: 30 30 30 30 30 30 30 30 30 30 30 40 30 30 30 30   00000000000@0000
|    512: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    528: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    544: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    560: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    576: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    592: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    608: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    624: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    640: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    656: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    672: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    688: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    704: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    720: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    736: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    752: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    768: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    784: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    800: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    816: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    832: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    848: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    864: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    880: 30 30 30 30 30 30 30 30 30 05 01 00 00 00 00 00   000000000.......
| end crash-7bc.txt.db
}]} {}

do_execsql_test 53.1 {
  SELECT*FROM t1 WHERE t1 MATCH'ATE"0"OR"2D:P"""ATE"0"OR"2:P"""';
} {0 {ATE 2:P}}
set sqlite_fts3_enable_parentheses $saved

#-------------------------------------------------------------------------
#
reset_db
do_test 54.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
.open --hexdb
| size 8192 pagesize 1024 filename crash-365.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: 04 00 01 01 00 40 20 20 00 00 00 00 00 00 00 08   .....@  ........
|     32: 00 00 00 00 00 00 00 00 00 00 00 06 00 00 00 04   ................
|     96: 00 00 00 00 0d 02 f3 00 07 01 51 00 03 c8 03 63   ..........Q....c
|    112: 02 fb 02 0a 02 c0 01 a8 01 51 00 00 00 00 00 00   .........Q......
|    336: 00 55 07 07 17 1b 1b 01 81 01 74 61 62 6c 65 74   .U........tablet
|    352: 31 5f 73 74 61 74 74 31 5f 73 74 61 74 07 43 52   1_statt1_stat.CR
|    368: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 73   EATE TABLE 't1_s
|    384: 74 61 74 27 28 69 64 20 49 4e 54 45 47 45 52 20   tat'(id INTEGER 
|    400: 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 76 61 6c   PRIMARY KEY, val
|    416: 75 65 20 42 4c 4f 42 29 60 06 07 17 21 21 01 81   ue BLOB)`...!!..
|    432: 0b 74 61 62 6c 65 74 31 5f 64 6f 63 73 69 7a 65   .tablet1_docsize
|    448: 74 31 5f 64 6f 63 73 69 7a 65 06 43 52 45 41 54   t1_docsize.CREAT
|    464: 45 20 54 41 42 4c 45 20 27 74 31 5f 64 6f 63 73   E TABLE 't1_docs
|    480: 69 7a 65 27 28 64 6f 63 69 64 20 49 4e 54 45 47   ize'(docid INTEG
|    496: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20   ER PRIMARY KEY, 
|    512: 73 69 7a 65 20 42 4c 4f 42 29 81 33 04 07 17 1f   size BLOB).3....
|    528: 1f 01 82 35 74 61 62 6c 65 74 31 5f 73 65 67 64   ...5tablet1_segd
|    544: 69 72 74 31 5f 73 65 67 64 69 72 04 43 52 45 41   irt1_segdir.CREA
|    560: 54 45 20 54 41 42 4c 45 20 27 74 31 5f 73 65 67   TE TABLE 't1_seg
|    576: 64 69 72 27 28 6c 65 76 65 6c 20 49 4e 54 45 47   dir'(level INTEG
|    592: 45 52 2c 69 64 78 20 49 4e 54 45 47 45 52 2c 73   ER,idx INTEGER,s
|    608: 74 61 72 74 5f 62 6c 6f 63 6b 20 49 4e 54 45 47   tart_block INTEG
|    624: 45 52 2c 6c 65 61 76 65 73 5f 65 6e 64 5f 62 6c   ER,leaves_end_bl
|    640: 6f 63 6b 20 49 4e 54 45 47 45 52 2c 65 6e 64 5f   ock INTEGER,end_
|    656: 62 6c 6f 63 6b 20 49 4e 54 45 47 45 52 2c 72 6f   block INTEGER,ro
|    672: 6f 74 20 42 4c 4f 42 2c 50 52 49 4d 41 52 59 20   ot BLOB,PRIMARY 
|    688: 4b 45 59 28 6c 65 76 65 6c 2c 20 69 64 78 29 29   KEY(level, idx))
|    704: 31 05 06 17 45 1f 01 00 69 6e 64 65 78 73 71 6c   1...E...indexsql
|    720: 69 74 65 5f 61 75 74 6f 69 6e 64 65 78 5f 74 31   ite_autoindex_t1
|    736: 5f 73 65 67 64 69 72 5f 31 74 31 5f 73 65 67 64   _segdir_1t1_segd
|    752: 69 72 05 00 00 00 08 00 00 00 00 66 03 07 17 23   ir.........f...#
|    768: 23 01 81 13 74 61 62 6c 65 74 31 5f 73 65 67 6d   #...tablet1_segm
|    784: 65 6e 74 73 74 31 5f 73 65 67 6d 65 6e 74 73 03   entst1_segments.
|    800: 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 31   CREATE TABLE 't1
|    816: 5f 73 65 67 6d 65 6e 74 73 27 28 62 6c 6f 63 6b   _segments'(block
|    832: 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41   id INTEGER PRIMA
|    848: 52 59 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c   RY KEY, block BL
|    864: 4f 42 29 63 02 07 17 21 21 01 81 11 74 61 62 6c   OB)c...!!...tabl
|    880: 65 74 31 5f 63 6f 6e 74 65 6e 74 74 31 5f 63 6f   et1_contentt1_co
|    896: 6e 74 65 6e 74 02 43 52 45 41 54 45 20 54 41 42   ntent.CREATE TAB
|    912: 4c 45 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28   LE 't1_content'(
|    928: 64 6f 63 69 64 20 49 4e 54 45 47 45 52 20 50 52   docid INTEGER PR
|    944: 49 4d 41 52 59 20 4b 45 59 2c 20 27 63 30 30 27   IMARY KEY, 'c00'
|    960: 2c 20 27 63 31 62 27 29 36 01 06 17 11 11 08 5b   , 'c1b')6......[
|    976: 74 61 62 6c 65 74 31 74 31 43 52 45 41 54 45 20   tablet1t1CREATE 
|    992: 56 49 52 54 55 41 4c 20 54 41 42 4c 45 20 74 31   VIRTUAL TABLE t1
|   1008: 20 55 53 49 4e 47 20 66 74 73 34 28 30 2c 62 29    USING fts4(0,b)
| page 2 offset 1024
|      0: 0d 00 00 00 03 00 0f 00 00 23 00 16 00 0f 00 05   .........#......
|     16: 03 04 00 08 0f 61 0b 02 04 00 08 1b 41 54 45 20   .....a......ATE 
|     32: 32 3a 50 87 5a 01 05 00 08 8f 37 66 30 30 30 30   2:P.Z.....7f0000
|     48: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|     64: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|     80: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|     96: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    112: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    128: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    144: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    160: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    176: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    192: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    208: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    224: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    240: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    256: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    272: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    288: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    304: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    320: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    336: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    352: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    368: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    384: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    400: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    416: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    432: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    448: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    464: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    480: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    496: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    512: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    528: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    544: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    560: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    576: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    592: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    608: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    624: 30 30 30 30 30 30 30 30 30 30 1b 30 30 30 30 30   0000000000.00000
|    640: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    656: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    672: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    688: 30 30 30 30 30 30 30 30 2f 30 30 30 30 30 30 30   00000000/0000000
|    704: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    720: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    736: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    752: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    768: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    784: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    800: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    816: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    832: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    848: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    864: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    880: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    896: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    912: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    928: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    944: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    960: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    976: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    992: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|   1008: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
| page 3 offset 2048
|      0: 0d 00 00 00 02 03 86 00 03 f4 03 86 00 00 00 00   ................
|    896: 00 00 00 00 00 00 87 62 02 04 00 8f 48 00 d5 07   .......b....H...
|    912: 66 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   f000000000000000
|    928: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    944: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    960: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    976: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    992: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|   1008: 00 00 00 08 0a 01 03 00 1a 00 01 30 03 01 02 00   ...........0....
| page 4 offset 3072
|      0: 0d 00 00 00 03 03 9e 00 03 ed 03 bc 03 9e 00 01   ................
|    912: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1c 03   ................
|    928: 07 08 01 08 08 15 2c 02 30 20 31 36 00 01 30 03   ......,.0 16..0.
|    944: 03 02 00 00 01 61 05 03 01 01 02 00 2f 02 07 08   .....a....../...
|    960: 09 08 08 15 54 30 20 33 36 00 01 30 03 02 02 00   ....T0 36..0....
|    976: 00 01 32 05 02 01 01 03 00 00 03 61 74 65 05 02   ..2........ate..
|    992: 01 01 02 00 00 01 70 05 02 01 01 04 00 11 01 07   ......p.........
|   1008: 08 08 09 01 17 14 02 32 20 39 39 37 01 01 01 66   .......2 997...f
| page 5 offset 4096
|      0: 0a 00 00 00 03 03 ee 00 03 fb 03 f5 03 ee 00 00   ................
|    992: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 06 04   ................
|   1008: 08 01 01 02 03 05 04 08 09 01 02 04 04 08 08 09   ................
| page 6 offset 5120
|      0: 0d 00 00 00 03 03 eb 00 03 f9 03 f2 00 00 00 00   ................
|    992: 00 00 00 00 00 00 00 00 00 00 00 05 03 03 00 10   ................
|   1008: 01 01 05 02 03 00 10 01 03 05 01 03 00 10 01 01   ................
| page 7 offset 6144
|      0: 0d 00 00 00 01 03 f6 00 03 f6 00 00 00 00 00 00   ................
|   1008: 00 00 00 00 00 00 08 00 03 00 16 03 03 05 e0 07   ................
| page 8 offset 7168
|      0: 00 00 00 00 30 30 30 30 30 30 30 30 30 30 30 30   ....000000000000
|     16: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|     32: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|     48: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|     64: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|     80: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|     96: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    112: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    128: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    144: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    160: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    176: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    192: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    208: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    224: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    240: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    256: 30 30 30 30 30 2f 30 30 30 30 30 30 30 30 30 30   00000/0000000000
|    272: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    288: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    304: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    320: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    336: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    352: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    368: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    384: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    400: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    416: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    432: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    448: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    464: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    480: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    496: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    512: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    528: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    544: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    560: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    576: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    592: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    608: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    624: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    640: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    656: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    672: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    688: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    704: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    720: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    736: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    752: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    768: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    784: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    800: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    816: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    832: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    848: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    864: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30   0000000000000000
|    880: 30 30 30 30 30 30 30 30 30 05 01 01 01 02 00 00   000000000.......
| end crash-365.txt.db
}]} {}

do_execsql_test 54.1 {
  SELECT rowid, quote(matchinfo(t1,'pcxybspcxybs')) FROM t1 WHERE t1 MATCH'ATE"0"OR"2:P"""';
}

finish_test

Added test/fts3corrupt5.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019 May 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.
#
#*************************************************************************
#
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/fts3_common.tcl
set testprefix fts3corrupt5

# If SQLITE_ENABLE_FTS3 is defined, omit this file.
ifcapable !fts3 {
  finish_test
  return
}

sqlite3_fts3_may_be_corrupt 1

do_execsql_test 1.0 {
  BEGIN;
    CREATE VIRTUAL TABLE ft USING fts3(a, b, c);
    INSERT INTO ft VALUES('one', 'one', 'one');
  COMMIT;
}

do_execsql_test 1.1 {
  SELECT * FROM ft WHERE ft MATCH 'b:one'
} {one one one}

do_execsql_test 1.2 {
  SELECT quote(root) FROM ft_segdir;
} {X'00036F6E6509010201010201020200'}

breakpoint
foreach {tn val q bCorrupt} {
  1 X'00036F6E650901'                   'b:one'  1
  2 X'00036F6E6509010201010201FFFFFF'   'c:one'  1
  3 X'00036F6E6501'                     'b:one'  1
  4 X'00036F6E650101'                   'b:one'  1
  5 X'00036F6E650100'                   'b:one'  0
} {
  do_execsql_test 1.3.$tn.1 "UPDATE ft_segdir SET root = $val"

  set res {0 {}}
  if {$bCorrupt} { set res {1 {database disk image is malformed}}}
  do_catchsql_test 1.3.$tn.2 {
    SELECT * FROM ft WHERE ft MATCH $q
  } $res
}

finish_test

Added test/fts3corrupt6.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2020 June 8
#
# 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 script is testing the FTS3 module.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/fts3_common.tcl
set testprefix fts3corrupt6

# If SQLITE_ENABLE_FTS3 is defined, omit this file.
ifcapable !fts3 {
  finish_test
  return
}

set ::saved_sqlite_fts3_enable_parentheses $::sqlite_fts3_enable_parentheses
set sqlite_fts3_enable_parentheses 1
sqlite3_fts3_may_be_corrupt 1
database_may_be_corrupt

do_execsql_test 1.0 {
  BEGIN TRANSACTION;
  CREATE TABLE t_content(col0 INTEGER);
  PRAGMA writable_schema=ON;
  CREATE VIRTUAL TABLE t0 USING fts3(col0 INTEGER PRIMARY KEY,col1 VARCHAR(8),col2 BINARY,col3 BINARY);
  INSERT INTO t0_content VALUES(0,NULL,NULL,NULL,NULL);
  INSERT INTO t0_segdir VALUES(0,0,0,0,'0 42',X'000131030102000103323334050101010200000461616161050101020200000462626262050101030200');
  COMMIT;
}

do_execsql_test 1.1 {
  SELECT 0+matchinfo(t0,'yxyyxy') FROM t0 WHERE t0 MATCH CAST( x'2b0a312b0a312a312a2a0b5d0a0b0b0a312a0a0b0b0a312a0b310a392a0b0a27312a2a0b5d0a312a0b310a31315d0b310a312a316d2a0b313b15bceaa50a312a0b0a27312a2a0b5d0a312a0b310a312b0b2a310a312a0b2a0b2a0b2e5d0a0bff313336e34a2a312a0b0a3c310b0a0b4b4b0b4b2a4bec40322b2a0b310a0a312a0a0a0a0a0a0a0a0a0b310a312a2a2a0b5d0a0b0b0a312a0b310a312a0b0a4e4541530b310a5df5ced70a0a0a0a0a4f520a0a0a0a0a0a0a312a0b0a4e4541520b310a5d616161610a0a0a0a4f520a0a0a0a0a0a312b0a312a312a0a0a0a0a0a0a004a0b0a310b220a0b0a310a4a22310a0b0a7e6fe0e0e030e0e0e0e0e01176e02000e0e0e0e0e01131320226310a0b0a310a4a22310a0b0a310a766f8b8b4ee0e0300ae0090909090909090909090909090909090909090909090909090909090909090947aaaa540b09090909090909090909090909090909090909090909090909090909090909fae0e0f2f22164e0e0f273e07fefefef7d6dfafafafa6d6d6d6d' AS TEXT);
} {0}

do_execsql_test 1.2 {
  CREATE VIRTUAL TABLE t1 USING fts3(col0 INTEGER PRIMARY KEY,col1 VARCHAR(8),col2 BINARY,col3 BINARY);
  INSERT INTO t1_content VALUES(0,NULL,NULL,NULL,NULL);
  INSERT INTO t1_segdir VALUES(0,0,0,0,'0 42',X'000131030102000103323334050101010200000461616161050101020200000462626262050101030200');
}

do_execsql_test 1.3 {
  SELECT 42+matchinfo(t1,'yxyyxy')  FROM t1 WHERE t1 MATCH  x'2b0a312b0a312a312a2a0b5d0a0b0b0a312a0a0b0b0a312a0b310a392a0b0a27312a2a0b5d0a312a0b310a31315d0b310a312a316d2a0b313b15bceaa50a312a0b0a27312a2a0b5d0a312a0b310a312b0b2a310a312a0b2a0b2a0b2e5d0a0bff313336e34a2a312a0b0a3c310b0a0b4b4b0b4b2a4bec40322b2a0b310a0a312a0a0a0a0a0a0a0a0a0b310a312a2a2a0b5d0a0b0b0a312a0b310a312a0b0a4e4541530b310a5df5ced70a0a0a0a0a4f520a0a0a0a0a0a0a312a0b0a4e4541520b310a5d616161610a0a0a0a4f520a0a0a0a0a0a312b0a312a312a0a0a0a0a0a0a004a0b0a310b220a0b0a310a4a22310a0b0a7e6fe0e0e030e0e0e0e0e01176e02000e0e0e0e0e01131320226310a0b0a310a4a22310a0b0a310a766f8b8b4ee0e0300ae0090909090909090909090909090909090909090909090909090909090909090947aaaa540b09090909090909090909090909090909090909090909090909090909090909fae0e0f2f22164e0e0f273e07fefefef7d6dfafafafa6d6d6d6d';
} {42}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.0 {
  CREATE VIRTUAL TABLE t0 USING fts3(a);
  INSERT INTO t0_segdir VALUES(0,0,0,0,'0 42',X'000131030782000103323334050100fff200010461616161050101020200000462626262050101030200');
}
do_execsql_test 2.1 {
  SELECT count(*) FROM t0 WHERE t0 MATCH '(1 NEAR 1) AND (aaaa OR 1)';
} 1

#-------------------------------------------------------------------------
reset_db
breakpoint
do_catchsql_test 3.0 {
  CREATE VIRTUAL TABLE main.Table0 USING fts3();
  INSERT INTO Table0 VALUES (1), (printf('%8.1280000X') ), (1), (printf('%8.1280000X') ), (1)  ;
  INSERT INTO Table0 VALUES (0), (printf('%8.1280000X%8.1280000X') ), (1), (printf('%1280000.1280000X%#1280000.1280000E%8.1280000X') ), (1)  ;
  INSERT INTO Table0 VALUES (1)  ;
  UPDATE Table0_segdir SET start_block = 1;
  INSERT INTO Table0 VALUES (1)  ;
  INSERT INTO Table0(Table0) VALUES('merge=6,8');
} {1 {database disk image is malformed}}

set sqlite_fts3_enable_parentheses $saved_sqlite_fts3_enable_parentheses
finish_test

Changes to test/fts3cov.test.

93
94
95
96
97
98
99
100

101
102
103
104
105
106
107
108

109
110
111
112
113
114
115
93
94
95
96
97
98
99

100
101
102
103
104
105
106
107

108
109
110
111
112
113
114
115







-
+







-
+







do_test fts3cov-2.2 {
  set root [db one {SELECT root FROM t1_segdir}]
  read_fts3varint [string range $root 1 end] left_child
  execsql { DELETE FROM t1_segments WHERE blockid = $left_child }
} {}
do_error_test fts3cov-2.3 {
  SELECT * FROM t1 WHERE t1 MATCH 'c*'
} {SQL logic error}
} {database disk image is malformed}

# Test the "replaced with NULL" case:
do_test fts3cov-2.4 {
  execsql { INSERT INTO t1_segments VALUES($left_child, NULL) }
} {}
do_error_test fts3cov-2.5 {
  SELECT * FROM t1 WHERE t1 MATCH 'cloud'
} {SQL logic error}
} {database disk image is malformed}

#--------------------------------------------------------------------------
# The following tests are to test the effects of OOM errors while storing
# terms in the pending-hash table. Specifically, while creating doclist
# blobs to store in the table. More specifically, to test OOM errors while
# appending column numbers to doclists. For example, if a doclist consists
# of:

Changes to test/fts3defer2.test.

156
157
158
159
160
161
162




























163
164
165
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



} {
  sqlite3_db_config db DEFENSIVE 0
  execsql $sql
  do_execsql_test 2.4.$tn {
    SELECT docid, mit(matchinfo(t3, 'pcxnal')) FROM t3 WHERE t3 MATCH '"a b c"';
  } {1 {1 1 1 4 4 11 912 6} 3 {1 1 1 4 4 11 912 6}}
}

do_execsql_test 2.5 {
  INSERT INTO t3(t3) VALUES('rebuild');
}
do_execsql_test 2.6 {
  SELECT rowid, length(offsets(t3)) FROM t3 WHERE t3 MATCH '(a NEAR a)';
} {11 228929}
do_execsql_test 2.7 {
  SELECT rowid, length(offsets(t3)) FROM t3 WHERE t3 MATCH '(a NEAR b NEAR a)';
} {1 23 3 23 11 205}
do_execsql_test 2.8 {
  SELECT rowid, length(offsets(t3)) FROM t3 WHERE t3 MATCH '(a NEAR b)';
} {1 15 3 15 11 106}

do_execsql_test 2.9 {
  SELECT rowid, length(matchinfo(t3)) FROM t3 WHERE t3 MATCH '(a NEAR a)';
} {11 32}
do_execsql_test 2.10 {
  SELECT rowid, length(matchinfo(t3)) FROM t3 WHERE t3 MATCH '(a NEAR b NEAR a)'
} {1 44 3 44 11 44}
do_execsql_test 2.11 {
  SELECT rowid, length(matchinfo(t3)) FROM t3 WHERE t3 MATCH '(a NEAR b)';
} {1 32 3 32 11 32}

do_execsql_test 2.12 {
  SELECT rowid, length(matchinfo(t3)) FROM t3 
  WHERE t3 MATCH '(a NEAR b NEAR a NEAR b NEAR a)'
} {1 68 3 68 11 68}


finish_test

Added test/fts3dropmod.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2021 December 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.  The
# focus of this script is testing the FTS3 module.
#
# $Id: fts3aa.test,v 1.1 2007/08/20 17:38:42 shess Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix fts3dropmod

# If SQLITE_ENABLE_FTS3 is defined, omit this file.
ifcapable !fts3 {
  finish_test
  return
}

sqlite3_drop_modules db fts3
do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE t1 USING fts3(x);
} 
do_catchsql_test 1.1 {
  CREATE VIRTUAL TABLE t2 USING fts4(x);
} {1 {no such module: fts4}}

reset_db
sqlite3_drop_modules db fts4
do_execsql_test 2.0 {
  CREATE VIRTUAL TABLE t1 USING fts4(x);
} 
do_catchsql_test 2.1 {
  CREATE VIRTUAL TABLE t2 USING fts3(x);
} {1 {no such module: fts3}}

finish_test

Changes to test/fts3expr4.test.

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
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







-
+
+
+
+
+
+
+
+
+
+

















-
+











do_icu_expr_test 1.5 {(x OR y)}     {OR {PHRASE 3 0 x} {PHRASE 3 0 y}}
do_icu_expr_test 1.6 { "(x OR y)" } {PHRASE 3 0 ( x or y )}

# In "col:word", if "col" is not the name of a column, the entire thing
# is passed to the tokenizer.
#
do_icu_expr_test 1.7 {a:word} {PHRASE 0 0 word}
do_icu_expr_test 1.8 {d:word} {PHRASE 3 0 d:word}
# do_icu_expr_test 1.8 {d:word} {PHRASE 3 0 d:word}
do_test 1.8 {
  set res [
    db one {SELECT fts3_exprtest('icu en_US', 'd:word', 'a', 'b', 'c')}
  ]
  expr {
    $res=="PHRASE 3 0 d:word" ||
    $res=="AND {AND {PHRASE 3 0 d} {PHRASE 3 0 :}} {PHRASE 3 0 word}"
  }
} 1

set sqlite_fts3_enable_parentheses 0

do_icu_expr_test 2.1 {
  f (e NEAR/2 a)
} {AND {AND {AND {PHRASE 3 0 f} {PHRASE 3 0 (}} {NEAR/2 {PHRASE 3 0 e} {PHRASE 3 0 a}}} {PHRASE 3 0 )}}

#-------------------------------------------------------------------------
#
do_simple_expr_test 3.1 {*lOl* *h4h*} {
  AND {PHRASE 3 0 lol+} {PHRASE 3 0 h4h+}
}

do_icu_expr_test 3.2 {*lOl* *h4h*} {
  AND {AND {AND {PHRASE 3 0 *} {PHRASE 3 0 lol+}} {PHRASE 3 0 *}} {PHRASE 3 0 h4h+}
}

do_simple_expr_test 3.3 { * }    { }
do_simple_expr_test 3.3 { * }    {}
do_simple_expr_test 3.4 { *a }   { PHRASE 3 0 a }
do_simple_expr_test 3.5 { a*b }  { AND {PHRASE 3 0 a+} {PHRASE 3 0 b} }
do_simple_expr_test 3.6 { *a*b } { AND {PHRASE 3 0 a+} {PHRASE 3 0 b} }
do_simple_expr_test 3.7 { *"abc" } { PHRASE 3 0 abc }
do_simple_expr_test 3.8 { "abc"* } { PHRASE 3 0 abc }
do_simple_expr_test 3.8 { "ab*c" } { PHRASE 3 0 ab+ c }

do_icu_expr_test    3.9 { "ab*c" } { PHRASE 3 0 ab+ * c }
do_icu_expr_test    3.10 { ab*c } { AND {PHRASE 3 0 ab+} {PHRASE 3 0 c}}

finish_test

Changes to test/fts3expr5.test.

17
18
19
20
21
22
23




24
25
26
27
28
29
30
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34







+
+
+
+







set testprefix fts3expr5

# If SQLITE_ENABLE_FTS3 is defined, omit this file.
ifcapable !fts3 {
  finish_test
  return
}

proc test_fts3expr {expr} {
  db one {SELECT fts3_exprtest('simple', $expr, 'a', 'b', 'c')}
}

#-------------------------------------------------------------------------
# Various forms of empty phrase expressions.
#
do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE t0 USING fts3(x);
  SELECT rowid FROM t0 WHERE x MATCH '';
40
41
42
43
44
45
46
47














48
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66








+
+
+
+
+
+
+
+
+
+
+
+
+
+

} {}
do_execsql_test 1.4 {
  SELECT rowid FROM t0 WHERE x MATCH '"" NOT ""';
} {}
do_execsql_test 1.5 {
  SELECT rowid FROM t0 WHERE x MATCH '""""';
} {}

#-------------------------------------------------------------------------
# Various forms of empty phrase expressions.
#
set sqlite_fts3_enable_parentheses 1
do_test 2.0 {
  test_fts3expr {(a:123)(b:234)()(c:456)}
} {AND {AND {PHRASE 0 0 123} {PHRASE 1 0 234}} {PHRASE 2 0 456}}
do_test 2.1 {
  test_fts3expr {(a:123)(b:234)(c:456)}
} {AND {AND {PHRASE 0 0 123} {PHRASE 1 0 234}} {PHRASE 2 0 456}}
do_test 2.2 {
  list [catch { test_fts3expr {"123" AND ( )} } msg] $msg
} {1 {Error parsing expression}}

finish_test

Added test/fts3f.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2006 September 9
#
# 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 script is testing the FTS3 module.
#
# $Id: fts3aa.test,v 1.1 2007/08/20 17:38:42 shess Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix fts3f

# If SQLITE_ENABLE_FTS3 is defined, omit this file.
ifcapable !fts3 {
  finish_test
  return
}

do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE ft USING fts3(x);
  BEGIN;
    INSERT INTO ft VALUES('a one'), ('b one'), ('c one');
}

do_test 1.1 {
  set ret [list]
  db eval { SELECT docid FROM ft WHERE ft MATCH 'one' } {
    if { $docid==2 } {
      db eval COMMIT
    }
    lappend ret $docid
  }
  set ret
} {1 2 3}

do_execsql_test 1.2 {
  BEGIN;
    INSERT INTO ft VALUES('a one'), ('b one'), ('c one');
}

do_execsql_test 1.3 {
  SELECT docid, optimize(ft) FROM ft WHERE ft MATCH 'one'
} {
  1 {Index optimized} 2 {Index already optimal} 3 {Index already optimal}
  4 {Index already optimal}
  5 {Index already optimal} 6 {Index already optimal}
}

finish_test

Changes to test/fts3fault.test.

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







+
+
+
+







set testdir [file dirname $argv0]
source $testdir/tester.tcl

set ::testprefix fts3fault

# If SQLITE_ENABLE_FTS3 is not defined, omit this file.
ifcapable !fts3 { finish_test ; return }

set ::TMPDBERROR [list 1 \
  {unable to open a temporary database file for storing temporary tables}
]

# Test error handling in the sqlite3Fts3Init() function. This is the 
# function that registers the FTS3 module and various support functions
# with SQLite.
#
do_faultsim_test 1 -body { 
  sqlite3 db test.db 
45
46
47
48
49
50
51
52

53
54
55
56
57
58
59
49
50
51
52
53
54
55

56
57
58
59
60
61
62
63







-
+







    BEGIN;
      INSERT INTO t1 VALUES('registers the FTS3 module');
      INSERT INTO t1 VALUES('various support functions');
  }
} -body {
  execsql { ALTER TABLE t1 RENAME TO t2 }
} -test {
  faultsim_test_result {0 {}} 
  faultsim_test_result {0 {}} $::TMPDBERROR
}

# Test error handling in the special case where a single prefix query 
# matches terms that reside on a large range of leaf nodes.
#
do_test fts3fault-3.0 {
  sqlite3 db test.db
190
191
192
193
194
195
196
197

198
199
200
201
202
203
204
194
195
196
197
198
199
200

201
202
203
204
205
206
207
208







-
+








do_faultsim_test 8.2 -faults oom-t* -prep { 
  faultsim_restore_and_reopen
  db func mit mit
} -body {
  execsql { SELECT mit(matchinfo(t8, 's')) FROM t8 WHERE t8 MATCH 'a b c' }
} -test {
  faultsim_test_result {0 3}
  faultsim_test_result {0 3} $::TMPDBERROR
}
do_faultsim_test 8.3 -prep { 
  faultsim_restore_and_reopen
  db func mit mit
} -body {
  execsql { SELECT mit(matchinfo(t8, 'a')) FROM t8 WHERE t8 MATCH 'a b c' }
} -test {
235
236
237
238
239
240
241
242
















243
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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

do_faultsim_test 10.1 -prep {
  faultsim_delete_and_reopen
} -body {
  execsql { CREATE VIRTUAL TABLE t1 USING fts4(a, b, languageid=d) }
} -test {
  faultsim_test_result {0 {}}
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 11.0 {
  CREATE VIRTUAL TABLE t1 USING fts3(a, b);
}
faultsim_save_and_close

do_faultsim_test 11 -faults oom* -prep {
  faultsim_restore_and_reopen
} -body {
  execsql { DROP TABLE t1 }
} -test {
  faultsim_test_result {0 {}}
}


finish_test

Changes to test/fts3fault2.test.

211
212
213
214
215
216
217



218
219
220
221
222
223

224
225
226
227
228
229
230
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225

226
227
228
229
230
231
232
233







+
+
+





-
+







  faultsim_restore_and_reopen
} -body {
  execsql { INSERT INTO t8 VALUES('one two three') }
} -test {
  faultsim_test_result {0 {}}
}

set ::TMPDBERROR [list 1 \
  {unable to open a temporary database file for storing temporary tables}
]
do_faultsim_test 8.2 -faults oom* -prep {
  faultsim_restore_and_reopen
} -body {
  execsql { ALTER TABLE t8 RENAME TO t8ii }
} -test {
  faultsim_test_result {0 {}}
  faultsim_test_result {0 {}} $::TMPDBERROR
}

#-------------------------------------------------------------------------
reset_db
set chunkconfig [fts3_configure_incr_load 1 1]
do_execsql_test 9.0 {
  PRAGMA page_size = 512;

Added test/fts3fuzz001.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2012-12-21
#
# 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.
#
#***********************************************************************
#
# Test cases for corrupt database files.

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable !deserialize||!fts3 {
  finish_test
  return
}
database_may_be_corrupt

do_test fts3fuzz001-100 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 24576 pagesize 4096 filename c6.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 06   .....@  ........
|     32: 00 00 00 00 00 00 00 00 00 00 00 05 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 0e f9 00 06 0d ec 00 0f cd 0f 69   ...............i
|    112: 0f 01 0e 10 0e c6 0d ec 00 00 00 00 00 00 00 00   ................
|   3552: 00 00 00 00 00 00 00 00 00 00 00 00 22 06 06 17   ............"...
|   3568: 11 11 01 31 74 61 62 6c 65 74 32 74 32 06 43 52   ...1tablet2t2.CR
|   3584: 45 41 54 45 20 54 41 42 4c 45 20 74 32 28 78 29   EATE TABLE t2(x)
|   3600: 81 33 04 07 17 1f 1f 01 82 35 74 61 62 6c 65 74   .3.......5tablet
|   3616: 31 5f 73 65 67 64 69 72 74 31 5f 73 65 67 64 69   1_segdirt1_segdi
|   3632: 72 04 43 52 45 41 54 45 20 54 41 42 4c 45 20 27   r.CREATE TABLE '
|   3648: 74 31 5f 73 65 67 64 69 72 27 28 6c 65 76 65 6c   t1_segdir'(level
|   3664: 20 49 4e 54 45 47 45 52 2c 69 64 78 20 49 4e 54    INTEGER,idx INT
|   3680: 45 47 45 52 2c 73 74 61 72 74 5f 62 6c 6f 63 6b   EGER,start_block
|   3696: 20 49 4e 54 45 47 45 52 2c 6c 65 61 76 65 73 5f    INTEGER,leaves_
|   3712: 65 6e 64 5f 62 6c 6f 63 6b 20 49 4e 54 45 47 45   end_block INTEGE
|   3728: 52 2c 65 6e 64 5f 62 6c 6f 63 6b 20 49 4e 54 45   R,end_block INTE
|   3744: 47 45 52 2c 72 6f 6f 74 20 42 4c 4f 42 2c 50 52   GER,root BLOB,PR
|   3760: 49 4d 41 52 59 20 4b 45 59 28 6c 65 76 65 6c 2c   IMARY KEY(level,
|   3776: 20 69 64 78 29 29 31 05 06 17 45 1f 01 00 69 6e    idx))1...E...in
|   3792: 64 65 78 73 71 6c 69 74 65 5f 61 75 74 6f 69 6e   dexsqlite_autoin
|   3808: 64 65 78 5f 74 15 f7 36 56 76 46 97 25 f3 17 43   dex_t..6VvF.%..C
|   3824: 15 5f 73 65 67 64 69 72 05 00 00 00 08 00 00 00   ._segdir........
|   3840: 00 66 03 07 17 23 23 01 81 13 74 61 62 6c 65 74   .f...##...tablet
|   3856: 31 5f 73 65 67 6d 65 6e 74 73 74 31 5f 73 65 67   1_segmentst1_seg
|   3872: 6d 65 6e 74 73 03 43 52 45 41 54 45 20 54 41 42   ments.CREATE TAB
|   3888: 4c 45 20 27 74 31 5f 73 65 67 6d 65 6e 74 73 27   LE 't1_segments'
|   3904: 28 62 6c 6f 63 6b 69 64 20 49 4e 54 45 47 45 52   (blockid INTEGER
|   3920: 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 62 6c    PRIMARY KEY, bl
|   3936: 6f 63 6b 20 42 4c 4f 42 29 62 02 07 17 21 21 01   ock BLOB)b...!!.
|   3952: 81 0f 74 61 62 6c 65 74 31 5f 63 6f 6e 74 65 6e   ..tablet1_conten
|   3968: 74 74 31 5f 63 6f 6e 74 65 6e 74 02 43 52 45 41   tt1_content.CREA
|   3984: 54 45 20 54 41 42 4c 45 20 27 74 31 5f 63 6f 6e   TE TABLE 't1_con
|   4000: 74 65 6e 74 27 28 64 6f 63 69 64 20 49 4e 54 45   tent'(docid INTE
|   4016: 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c   GER PRIMARY KEY,
|   4032: 20 27 63 30 63 6f 6e 74 65 6e 74 27 29 31 01 06    'c0content')1..
|   4048: 17 11 11 08 51 74 61 62 6c 65 74 31 74 31 43 52   ....Qtablet1t1CR
|   4064: 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 42   EATE VIRTUAL TAB
|   4080: 4c 45 20 74 31 20 55 53 49 4e 47 20 66 74 73 33   LE t1 USING fts3
| page 2 offset 4096
|      0: 0d 00 00 00 03 0f e0 00 0f f6 0f ec 0f e0 00 00   ................
|   4064: 0a 03 03 00 1b 61 62 61 6e 64 6f 6e 08 02 03 00   .....abandon....
|   4080: 17 61 62 61 66 74 08 01 03 00 17 61 62 61 63 6b   .abaft.....aback
| page 3 offset 8192
|      0: 0d 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00   ................
| page 4 offset 12288
|      0: 0d 00 00 00 01 0f d6 00 0f 00 00 00 00 00 00 00   ................
|   4048: 00 00 00 00 00 00 28 01 07 08 08 08 08 15 46 30   ......(.......F0
|   4064: 20 32 39 00 05 61 62 61 63 6b 03 01 02 00 03 02    29..aback......
|   4080: 66 74 03 02 02 00 03 04 6e 64 6f 6e 03 03 02 00   ft......ndon....
| page 5 offset 16384
|      0: 0a 00 00 00 01 0f fb 00 0f fb 00 00 00 00 00 00   ................
|   4080: 00 00 00 00 00 00 00 00 00 00 00 04 04 08 08 09   ................
| page 6 offset 20480
|      0: 0d 00 00 00 05 0f b8 00 0f f4 0f e9 0f d6 0f c7   ................
|     16: 0f b8 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   4016: 00 00 00 00 00 00 00 00 0d 05 02 23 61 75 74 6f   ...........#auto
|   4032: 6d 65 72 67 65 3d 35 0d 04 02 23 6d 65 72 67 65   merge=5...#merge
|   4048: 3d 31 30 30 2c 38 11 03 02 2b 69 6e 74 65 67 72   =100,8...+integr
|   4064: 69 74 79 3d 63 68 65 63 6b 09 02 02 1b 72 65 62   ity=check....reb
|   4080: 75 69 6c 64 0a 01 02 1d 6f 70 74 69 6d 69 7a 65   uild....optimize
| end c6.db
  }]
  catchsql {
    PRAGMA writable_schema=on; -- disable schema corruption detection
    INSERT INTO t1(t1) SELECT x FROM t2;
  }
} {1 {database disk image is malformed}}
do_test fts3fuzz001-110 {
  catchsql {
    INSERT INTO t1(t1) VALUES('integrity-check');
  }
} {1 {database disk image is malformed}}
do_test fts3fuzz001-120 {
  catchsql {
    INSERT INTO t1(t1) VALUES('optimize');
  }
} {1 {database disk image is malformed}}
do_test fts3fuzz001-121 {
  catchsql {
    INSERT INTO t1(t1) VALUES('integrity-check');
  }
} {1 {database disk image is malformed}}


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=?) LEFT-JOIN
}

finish_test

Added test/fts3matchinfo2.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2020-05-14
#
# 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 the FTS3 module. The focus
# of this file is tables created with the "matchinfo=fts3" option.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# If SQLITE_ENABLE_FTS3 is not defined, omit this file.
ifcapable !fts3 { finish_test ; return }

set sqlite_fts3_enable_parentheses 1

# Crash case found by cyg0810 at gmail.com 2020-05-14.  Reported to
# chromium (which is not vulnerable) who kindly referred it to us.
#
do_execsql_test 1.0 {
  CREATE TABLE t_content(col0 INTEGER);
  CREATE VIRTUAL TABLE t0 USING fts3(col0 INTEGER PRIMARY KEY,col1 VARCHAR(8),col2 BINARY,col3 BINARY);
  INSERT INTO t0 VALUES (1, '1234','aaaa','bbbb');
  SELECT hex(matchinfo(t0,'yxy'))  FROM t0 WHERE t0 MATCH  x'2b0a312b0a312a312a2a0b5d0a0b0b0a312a0a0b0b0a312a0b310a392a0b0a27312a2a0b5d0a312a0b310a31315d0b310a312a316d2a0b313b15bceaa50a312a0b0a27312a2a0b5d0a312a0b310a312b0b2a310a312a0b2a0b2a0b2e5d0a0bff313336e34a2a312a0b0a3c310b0a0b4b4b0b4b2a4bec40322b2a0b310a0a312a0a0a0a0a0a0a0a0a0b310a312a2a2a0b5d0a0b0b0a312a0b310a312a0b0a4e4541530b310a5df5ced70a0a0a0a0a4f520a0a0a0a0a0a0a312a0b0a4e4541520b310a5d616161610a0a0a0a4f520a0a0a0a0a0a312b0a312a312a0a0a0a0a0a0a004a0b0a310b220a0b0a310a4a22310a0b0a7e6fe0e0e030e0e0e0e0e01176e02000e0e0e0e0e01131320226310a0b0a310a4a22310a0b0a310a766f8b8b4ee0e0300ae0090909090909090909090909090909090909090909090909090909090909090947aaaa540b09090909090909090909090909090909090909090909090909090909090909fae0e0f2f22164e0e0f273e07fefefef7d6dfafafafa6d6d6d6d';
} {/000000.*0000000/}


set sqlite_fts3_enable_parentheses 0
finish_test

Changes to test/fts3misc.test.

222
223
224
225
226
227
228
































































































229
230
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


    INSERT INTO t6 SELECT 'x x x x x x x x x x x' FROM s;
  COMMIT;
}
do_execsql_test 6.1 {
  SELECT rowid FROM t6 WHERE t6 MATCH 'b OR "x a"'
} {50001 50002 50003 50004}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 7.0 {
  CREATE VIRTUAL TABLE vt0 USING fts3(c0);
  INSERT INTO vt0 VALUES (x'00');
}
do_execsql_test 7.1 {
  INSERT INTO vt0(vt0) VALUES('integrity-check');
}

#-------------------------------------------------------------------------
# Ticket [8a6fa2bb].
#
reset_db
do_execsql_test 7.0.1 {
  CREATE VIRTUAL TABLE vt0 USING fts4(c0, order=DESC);
  INSERT INTO vt0(c0) VALUES (0), (0);
}
do_execsql_test 7.0.2 {
  INSERT INTO vt0(vt0) VALUES('integrity-check');
}
reset_db
do_execsql_test 7.1.1 {
  CREATE VIRTUAL TABLE vt0 USING fts4(c0, order=ASC);
  INSERT INTO vt0(c0) VALUES (0), (0);
}
do_execsql_test 7.1.2 {
  INSERT INTO vt0(vt0) VALUES('integrity-check');
}
do_execsql_test 7.2.1 {
  CREATE VIRTUAL TABLE ft USING fts4(c0, c1, order=DESC, prefix=1);
  INSERT INTO ft VALUES('a b c d', 'hello world');
  INSERT INTO ft VALUES('negative', 'positive');
  INSERT INTO ft VALUES('hello world', 'a b c d');
}
do_execsql_test 7.2.2 {
  INSERT INTO vt0(vt0) VALUES('integrity-check');
}

#-------------------------------------------------------------------------
# Ticket [745f1abc].
#
reset_db
do_execsql_test 8.1 {
  CREATE VIRTUAL TABLE vt0 USING fts4(c0, prefix=1);
}
do_execsql_test 8.2 {
  BEGIN;
    INSERT INTO vt0 VALUES (0);
    INSERT INTO vt0(vt0) VALUES('optimize');
  COMMIT;
}
do_execsql_test 8.3 {
  INSERT INTO vt0(vt0) VALUES('integrity-check');
}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 9.0 {
  CREATE VIRTUAL TABLE t1 using fts4(mailcontent);
  insert into t1(rowid, mailcontent) values
      (-4764623217061966105, 'we are going to upgrade'),
      (8324454597464624651, 'we are going to upgrade');
}

do_execsql_test 9.1 {
  INSERT INTO t1(t1) VALUES('integrity-check');
}

do_execsql_test 9.2 {
  SELECT rowid FROM t1 WHERE t1 MATCH 'upgrade';
} {
  -4764623217061966105 8324454597464624651
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 10.0 {
  CREATE VIRTUAL TABLE f USING fts3(a,b);
  CREATE TABLE 'f_stat'(id INTEGER PRIMARY KEY, value BLOB);
  INSERT INTO f_stat VALUES (1,x'3b3b3b3b3b3b3b28ffffffffffffffffff1807f9073481f1d43bc93b3b3b3b3b3b3b3b3b3b18073b3b3b3b3b3b3b9b003b');
} {}

do_catchsql_test 10.1 {
  INSERT INTO f(f) VALUES ('merge=69,59');
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
do_execsql_test 11.0 {
  CREATE VIRTUAL TABLE xyz USING fts3();
}
do_execsql_test 11.1 {
  SELECT * FROM xyz WHERE xyz MATCH 'a NEAR/4294836224 a';
}

finish_test

Changes to test/fts3offsets.test.

113
114
115
116
117
118
119












120
121
122
123
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135







+
+
+
+
+
+
+
+
+
+
+
+




  6 {(A) x}
  5 {(A) (B) (C)}
  4 {(A) (B) (C) x x x x x x x B}
  3 {(A) x x x x x x x x x C}
  2 {(A) x x x x x x x x x x x B} 
  1 {(A) (B) (C)}
}

do_execsql_test 1.5.0 {
  CREATE VIRTUAL TABLE x1 USING fts3(x);
  INSERT INTO x1 VALUES('A A A');
  INSERT INTO x1 VALUES('A A A');
}
do_execsql_test 1.5.1 {
  SELECT offsets(x1) FROM x1 WHERE x1 MATCH 'a OR b AND c NEAR d'
} {
  {0 0 0 1 0 0 2 1 0 0 4 1} 
  {0 0 0 1 0 0 2 1 0 0 4 1}
}


set sqlite_fts3_enable_parentheses 0
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/fts3snippet.test.

551
552
553
554
555
556
557





558
559

























560
561
562
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







+
+
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



  set x35 [string trim [string repeat "x " 35]]
  execsql "INSERT INTO t4 VALUES('$x35 E $x35 F $x35 G $x35');"
  llength [db one {
    SELECT snippet(t4, '', '', '', 0, 64) FROM t4 WHERE t4 MATCH 'E'
  }]
} {64}

do_test 4.3 {
  llength [db one {
    SELECT snippet(t4, '', '', '', 0, 150) FROM t4 WHERE t4 MATCH 'E'
  }]
} {64}


#-------------------------------------------------------------------------
# Request a snippet from a query with more than 64 phrases.
#
do_execsql_test 5.0 {
  CREATE VIRTUAL TABLE t5 USING fts3(x);
  INSERT INTO t5 VALUES('a1 a2 a3');
  INSERT INTO t5 VALUES('a4 a5 a6');
  INSERT INTO t5 VALUES('a70 a71 a72');
}

do_execsql_test 5.1 {
  SELECT snippet(t5, '[', ']') FROM t5 WHERE t5 MATCH 
  'a1 OR a2 OR a3 OR a4 OR a5 OR a6 OR a7 OR a8 OR a9 OR a10 OR ' ||
  'a11 OR a12 OR a13 OR a14 OR a15 OR a16 OR a17 OR a18 OR a19 OR a10 OR ' ||
  'a21 OR a22 OR a23 OR a24 OR a25 OR a26 OR a27 OR a28 OR a29 OR a20 OR ' ||
  'a31 OR a32 OR a33 OR a34 OR a35 OR a36 OR a37 OR a38 OR a39 OR a30 OR ' ||
  'a41 OR a42 OR a43 OR a44 OR a45 OR a46 OR a47 OR a48 OR a49 OR a40 OR ' ||
  'a51 OR a52 OR a53 OR a54 OR a55 OR a56 OR a57 OR a58 OR a59 OR a50 OR ' ||
  'a61 OR a62 OR a63 OR a64 OR a65 OR a66 OR a67 OR a68 OR a69 OR a60 OR ' ||
  'a71 OR a72 OR a73 OR a74 OR a75 OR a76 OR a77 OR a78 OR a79 OR a70'
} {
  {[a1] [a2] [a3]}
  {[a4] [a5] [a6]}
  {[a70] [a71] [a72]}
}

set sqlite_fts3_enable_parentheses 0
finish_test

Added test/fts3snippet2.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2020-05-14
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#*************************************************************************
#
# The tests in this file test the FTS3 auxillary functions offsets(), 
# snippet() and matchinfo() work. At time of writing, running this file 
# provides full coverage of fts3_snippet.c.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix fts3snippet

# If SQLITE_ENABLE_FTS3 is not defined, omit this file.
ifcapable !fts3 { finish_test ; return }
source $testdir/fts3_common.tcl

set sqlite_fts3_enable_parentheses 1
#-------------------------------------------------------------------------
# Request a snippet from a query with more than 64 phrases.
#
reset_db
do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE f USING fts3(b);
  INSERT INTO f VALUES ( x'746e6e6d64612e082a011065616e656d655a616c702a2f65732e0f42014001380230018218');
}

do_execsql_test 1.1 {
  SELECT  length(snippet(f))>0  FROM f WHERE b MATCH x'1065616e656d655a616c702a2f65732e0f42014001380230018218021001081e0a3d746e6e6d64612e082a010f42014001380230018218021001081e0a3d746e6e6d64612e082a011065616e656d655a616c702a2f65732e0f42014001380230018218021001081e0a3d746e6e6d64612e082a011065616e656d655a616c702a2f65732e0f42014001380230018218021001081e0a3d746e6e6d64612e082a011065616e656d655a616c702a2f0a3d746e6e6d64612e082a011065616e656d655a616c702a2f65732e0f42014001018218021001081e0a3d746e6e6d64612e082a011065616e656d655a616c702a018218021001081e0a3d746e6e6d64612e082a011065616e656d655a616c2a2f65732e0f42014001380230018218021001081e0a3d746e6e6d64612e082a011065616e656d655a616c702a2f65732e0f42014001380230018218021001081e0a3d746e6e6d64612e082a011065616e656d655a616c702a2f65732e0f42014001380230018218021001081e0a3d746e6e6d64612e082a011065616e656d655a616c702a2f65732e0f42014001380230018218021001081e0a3d746e6e6d64612e0f42';
} {1}

reset_db
do_execsql_test 2.0 {
  CREATE VIRTUAL TABLE t0 USING fts3(col0 INTEGER PRIMARY KEY,col1 VARCHAR(8),col2 BINARY,col3 BINARY);
  INSERT INTO t0 VALUES (1, '1234','aaaa','bbbb');
  SELECT snippet(t0)  FROM t0 WHERE t0 MATCH x'0a4d4d4d4d320a4f52d70a310a310a4e4541520a0a31f6ce0a4f520a0a310a310a310a4f520a75fc2a242424' ;
} {<b>1</b>}

reset_db
do_execsql_test 2.1 {
  CREATE VIRTUAL TABLE t0 USING fts3(
      col0 INTEGER PRIMARY KEY,col1 VARCHAR(8),col2 BINARY,col3 BINARY
  );
  INSERT INTO t0 VALUES ('one', '1234','aaaa','bbbb');
}
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/fts3varint.test.

106
107
108
109
110
111
112


113
114


115
116


117
118
106
107
108
109
110
111
112
113
114


115
116
117

118
119
120
121







+
+
-
-
+
+

-
+
+


    576460752303423487 576460752303423488 576460752303423489 }
do_fts3_varint_test 2.60 { 
    1152921504606846975 1152921504606846976 1152921504606846977 }
do_fts3_varint_test 2.61 { 
    2305843009213693951 2305843009213693952 2305843009213693953 }
do_fts3_varint_test 2.62 { 
    4611686018427387903 4611686018427387904 4611686018427387905 }

if {![catch {fts3_test_varint 18446744073709551615}]} {
do_fts3_varint_test 2.63 { 
    9223372036854775807 9223372036854775808 9223372036854775809 }
  do_fts3_varint_test 2.63 { 
      9223372036854775807 9223372036854775808 9223372036854775809 }

do_fts3_varint_test 3.0 { 18446744073709551615 -18446744073709551615 }
  do_fts3_varint_test 3.0 { 18446744073709551615 -18446744073709551615 }
}

finish_test

Changes to test/fts4aa.test.

186
187
188
189
190
191
192






























































193
194
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


set ii 0
foreach {q r} [array get fts4aa_res] {
  incr ii
  do_test fts4aa-4.$ii {
    db eval {SELECT docid FROM t1 WHERE words MATCH $::q ORDER BY docid}
  } $r
}

# 2019-11-16 https://bugs.chromium.org/p/chromium/issues/detail?id=1025472
#
db close
sqlite3 db :memory:
do_execsql_test fts4aa-5.10 {
  CREATE VIRTUAL TABLE t1 USING fts4(a, b, c, d, e,f,g,h,i,j,k,l,m,n,o,p,q,r);
  INSERT INTO t1 VALUES('X Y', '2', '3', '4', '5', '6', '7', '8', '9', '0',
                        'a','b','c','d','e','f','g','h');
  UPDATE t1_docsize SET size=x'88' WHERE docid=1;
} {}
do_catchsql_test fts4aa-5.20 {
  SELECT quote(matchinfo(t1, 'l')) FROM t1 WHERE t1 MATCH 'X Y';
} {1 {database disk image is malformed}}
do_execsql_test fts4aa-5.30 {
  DROP TABLE t1;
  CREATE VIRTUAL TABLE t1 USING fts4(a,b,c,d);
  INSERT INTO t1 VALUES('one two','three four','five six','seven eight');
} {}
do_catchsql_test fts4aa-5.40 {
  UPDATE t1_stat SET value=x'01010101' WHERE id=0;
  SELECT quote(matchinfo(t1,'a')) FROM t1 WHERE t1 MATCH 'one two';
} {1 {database disk image is malformed}}
do_catchsql_test fts4aa-5.50 {
  UPDATE t1_stat SET value=x'010101' WHERE id=0;
  SELECT quote(matchinfo(t1,'a')) FROM t1 WHERE t1 MATCH 'one two';
} {1 {database disk image is malformed}}
do_catchsql_test fts4aa-5.60 {
  UPDATE t1_stat SET value=x'01' WHERE id=0;
  SELECT quote(matchinfo(t1,'a')) FROM t1 WHERE t1 MATCH 'one two';
} {1 {database disk image is malformed}}
do_catchsql_test fts4aa-5.70 {
  UPDATE t1_stat SET value=x'' WHERE id=0;
  SELECT quote(matchinfo(t1,'a')) FROM t1 WHERE t1 MATCH 'one two';
} {1 {database disk image is malformed}}

# 2019-11-18 https://bugs.chromium.org/p/chromium/issues/detail?id=1025467
db close
sqlite3 db :memory:
if {$tcl_platform(byteOrder)=="littleEndian"} {
  set res {X'0200000000000000000000000E0000000E00000001000000010000000100000001000000'}
} else {
  set res {X'0000000200000000000000000000000E0000000E00000001000000010000000100000001'}
}
do_catchsql_test fts4aa-6.10 {
  CREATE VIRTUAL TABLE f USING fts4();
  INSERT INTO f_segdir VALUES (77,91,0,0,'255 77',x'0001308000004d5c4ddddddd4d4d7b4d4d4d614d8019ff4d05000001204d4d2e4d6e4d4d4d4b4d6c4d004d4d4d4d4d4d3d000000004d5d4d4d645d4d004d4d4d4d4d4d4d4d4d454d6910004d05ffff054d646c4d004d5d4d4d4d4d3d000000004d4d4d4d4d4d4d4d4d4d4d69624d4d4d04004d4d4d4d4d604d4ce1404d554d45');
  INSERT INTO f_segdir VALUES (77,108,0,0,'255 77',x'0001310000fa64004d4d4d3c5d4d654d4d4d614d8000ff4d05000001204d4d2e4d6e4d4d4dff4d4d4d4d4d4d00104d4d4d4d000000004d4d4d0400311d4d4d4d4d4d4d4d4d4d684d6910004d05ffff054d4d6c4d004d4d4d4d4d4d3d000000004d4d4d4d644d4d4d4d4d4d69624d4d4d03ed4d4d4d4d4d604d4ce1404d550080');
  INSERT INTO f_stat VALUES (0,x'80808080100000000064004d4d4d3c4d4d654d4d4d614d8000ff4df6ff1a00204d4d2e4d6e4d4d4d104d4d4d4d4d4d00104d4d4d4d4d4d69574d4d4d000031044d4d4d3e4d4d4c4d05004d6910');
  SELECT quote(matchinfo(f,'pnax')) from f where f match '0 1';
} {1 {database disk image is malformed}}

# 2019-11-18 Detect infinite loop in fts3SelectLeaf()
db close
sqlite3 db :memory:
do_catchsql_test fts4aa-7.10 {
  CREATE VIRTUAL TABLE f USING fts4();
  INSERT INTO f_segdir VALUES (63,60,60,60,'60 60',x'3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c483c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c20003c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c283c3c3c3c3c3c3c3c3c3c3c223c3c3c3c3c3c3c3c3c');
  INSERT INTO f_segments VALUES (60,x'3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c5a3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c2a3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c5e3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c803c3c3c3c3c3c233c3c3c3c1c3c3c3c3c3c3c3c3c3c3c3c1b3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c273c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c1a3c3c3c3c3c3c000200003c3c3c3c3c3c3c3c3c3c3c3c3c383c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d898d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d3c3c3c3c3c3c3c3c3c3cba3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c1c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c00023c3c3c3c3c3c383c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3cbc3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c2c3c3c3c403c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c16161616161616163c3c3c3c3c3c3c3c3c3c3c3c3c583c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c2b3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c1c013c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c20003c3c3c3c3c3c3c3c3c3c3c800000003c3c3c3c3c3c3c2c3c3c3c3c3c3c353c08080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808f4080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808083c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c323c3c3c3c3c3c3c3c3c3c3c4f3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3cfcfcfcfcfcfcfcfcfcfcfc10fcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfd02fcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfc03e8fcfcfcfc3c3c3c3c3c3c8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c553c3c3c3c3c3c3c3c3c3c3c3c3c573c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c000000803c3c4dd5d5a6d52cf3d5d5d5d5d5d5d5d5d5d5d5d5d5d53c3c3c3c3f3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c2d3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c013c3c3c3c00643c3c3c3ce93c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c263c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c363c3c3c3c3c3c3c3c3c3c3c3c3c3c543c3c3c3c3c3c3c3c3c3c273c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c330000003c3c3c3c3c3c3c3c3c3c3c3c3c3c4d3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c000010003c3c3c3c3c3c413c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c1c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c403c3c3c3c3c3c3c3c3c3c3c3cec0000fa3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c2d3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c4c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c5e3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c1b3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c593c3c3c3c3c3c243c3c373c3c3c3c3cff3c3c3c3c3c3c3c3c3c3c3c3c3c000080003c3c3c3c3c3c3c3c3c3c353c3c3c3c3c3d3c3c3c3c3c3c3c3c3c3c3c3c4d3c3c3c3c3c3c3c3c3c3c3c3c3c40003c3c3c3c3c293c3c3c3c3c3c3c3c3c3d3c3c3c3c3c3c3c3c353c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c4f3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3f3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3cff7f3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c2d3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3ca43c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3cbf3c3c3c3c3c3c3c3c3c008000003c3c3c3c3c3c3c3c343c3c373c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c593c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c');
  SELECT * from f where f match '0';
} {1 {database disk image is malformed}}


finish_test

Changes to test/fts4content.test.

629
630
631
632
633
634
635




































636
637
638
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



# Test cases 11.*
# 
reset_db

do_catchsql_test 11.1 {
  CREATE VIRTUAL TABLE x1 USING fts4(content=x1);
} {1 {vtable constructor called recursively: x1}}

#---------------------------------------------------------------------------
# Check that an fts4 table cannot be its own content table.
#
reset_db
breakpoint
do_execsql_test 12.1.1 {
  CREATE VIRTUAL TABLE t1 USING fts4(a, content=t1 );
  INSERT INTO t1(rowid, a) VALUES(1, 'abc');
}
do_catchsql_test 12.1.2 { 
  SELECT * FROM t1; 
} {1 {SQL logic error}}
do_catchsql_test 12.1.3 { 
  SELECT * FROM t1('abc'); 
} {1 {SQL logic error}}
do_catchsql_test 12.1.4 { 
  SELECT count(*) FROM t1;
} {1 {SQL logic error}}

reset_db
do_execsql_test 12.2.1 {
  CREATE VIRTUAL TABLE t1 USING fts4(a, content=t2 );
  CREATE VIRTUAL TABLE t2 USING fts4(a, content=t1 );
  INSERT INTO t1(rowid, a) VALUES(1, 'abc');
}
do_catchsql_test 12.2.2 { 
  SELECT * FROM t1; 
} {1 {SQL logic error}}
do_catchsql_test 12.2.3 { 
  SELECT * FROM t1('abc'); 
} {1 {SQL logic error}}
do_catchsql_test 12.2.4 { 
  SELECT count(*) FROM t1;
} {1 {SQL logic error}}



finish_test

Changes to test/fts4langid.test.

485
486
487
488
489
490
491















492
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  } {1 2 5}

  do_execsql_test 5.4.$lid.5 {
    SELECT count(*) FROM t6_segdir;
    SELECT count(*) FROM t6_segments;
  } {1 2}
}

reset_db
do_execsql_test 6.0 {
  CREATE VIRTUAL TABLE vt0 USING fts4(c0, languageid="lid");
  INSERT INTO vt0 VALUES ('a'), ('b');
  BEGIN;
    UPDATE vt0 SET lid = 1 WHERE lid=0;
}
do_execsql_test 6.1 {
  INSERT INTO vt0(vt0) VALUES('integrity-check');
}
do_execsql_test 6.2 {
  COMMIT;
  INSERT INTO vt0(vt0) VALUES('integrity-check');
}
finish_test

Changes to test/fts4merge.test.

322
323
324
325
326
327
328
329
















330
331
332
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







-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



    expr { ([db total_changes] - $x)>1 }
  } {0}
  do_test 7.5 {
    set x [db total_changes]
    execsql { INSERT INTO t1(t1) VALUES('merge=200,10') }
    expr { ([db total_changes] - $x)>1 }
  } {0}

}

#-------------------------------------------------------------------------
# Test cases 8.* - ticket [bf1aab89].
#
set testprefix fts4merge
reset_db
do_execsql_test 8.0 {
  CREATE VIRTUAL TABLE t1 USING fts4(a, order=DESC);
  INSERT INTO t1(a) VALUES (0);
  INSERT INTO t1(a) VALUES (0);
  UPDATE t1 SET a = NULL;
} 

do_execsql_test 8.1 {
  INSERT INTO t1(t1) VALUES('merge=1,4');
}

finish_test

Changes to test/fts4merge4.test.

12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
12
13
14
15
16
17
18

19
20
21
22
23
24
25
26







-
+







#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/fts3_common.tcl
set ::testprefix fts4merge4

ifcapable !fts3 {
ifcapable !fts3||!shared_cache {
  finish_test
  return
}

set ::enable_shared_cache [sqlite3_enable_shared_cache 1]

do_execsql_test 1.1 { CREATE VIRTUAL TABLE t1 USING fts4 }

Added test/fts4merge5.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019 October 02
#
# 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 script is testing the FTS4 module.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix fts4merge5

# If SQLITE_ENABLE_FTS3 is defined, omit this file.
ifcapable !fts3 {
  finish_test
  return
}

source $testdir/genesis.tcl

do_execsql_test 1.1 { 
  CREATE TABLE t1(docid, words);
}
fts_kjv_genesis

do_execsql_test 1.2 {
  CREATE VIRTUAL TABLE x1 USING fts3; 
  INSERT INTO x1(x1) VALUES('nodesize=64');
  INSERT INTO x1(x1) VALUES('maxpending=64');
}

do_execsql_test 1.3 {
  INSERT INTO x1(docid, content) SELECT * FROM t1;
}

for {set tn 1} {1} {incr tn} {
  set tc1 [db total_changes]
  do_execsql_test 1.4.$tn.1 {
    INSERT INTO x1(x1) VALUES('merge=1,2');
  }
  set tc2 [db total_changes]

  if {($tc2 - $tc1)<2} break

  do_execsql_test 1.4.$tn.1 {
    INSERT INTO x1(x1) VALUES('integrity-check');
  }
}



finish_test

Added test/fts4min.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2020 February 27
#
# 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/fts3_common.tcl
set ::testprefix fts4min

# If SQLITE_ENABLE_FTS3 is defined, omit this file.
ifcapable !fts3 {
  finish_test
  return
}

#------------------------------------------------------------------
do_execsql_test 0.0 {
  CREATE TABLE t1(a NOT NULL, b);
  CREATE INDEX i1 ON t1(a);
}

do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE ft USING fts3(c);
  INSERT INTO ft(docid, c) VALUES(22, 'hello world');
  INSERT INTO ft(docid, c) VALUES(44, 'hello world');
  INSERT INTO ft(docid, c) VALUES(11, 'hello world');
}

do_eqp_test 1.1.1 {
  SELECT max(rowid) FROM ft
} {VIRTUAL TABLE INDEX 0:DESC}

do_eqp_test 1.1.2 {
  SELECT min(rowid) FROM ft
} {VIRTUAL TABLE INDEX 0:ASC}

do_execsql_test 1.2.1 {
  SELECT max(rowid) FROM ft
} {44}

do_execsql_test 1.2.2 {
  SELECT min(rowid) FROM ft
} {11}

finish_test

Changes to test/fts4noti.test.

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
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







-
+




















-
+







# Check that if an indexed column name is a prefix of a notindexed column
# name, the column is still correctly tokenized. This was a problem at one
# point.
do_execsql_test 6.1.1 {
  CREATE VIRTUAL TABLE t1 USING fts4(
    poiCategory, poiCategoryId, notindexed=poiCategoryId
  );
  INSERT INTO t1(poiCategory, poiCategoryId) values ("Restaurant", 6021);
  INSERT INTO t1(poiCategory, poiCategoryId) values ('Restaurant', 6021);
}

do_execsql_test 6.1.2 {
  SELECT * FROM t1 WHERE t1 MATCH 'restaurant';
} { Restaurant 6021 }
do_execsql_test 6.1.3 {
  SELECT * FROM t1 WHERE t1 MATCH 're*';
} { Restaurant 6021 }
do_execsql_test 6.1.4 {
  SELECT * FROM t1 WHERE t1 MATCH '6021';
} {}
do_execsql_test 6.1.5 {
  SELECT * FROM t1 WHERE t1 MATCH '60*';
} {}

do_execsql_test 6.2.1 {
  DROP TABLE t1;
  CREATE VIRTUAL TABLE t1 USING fts4(
    poiCategory, poiCategoryId, notindexed=poiCategory
  );
  INSERT INTO t1(poiCategory, poiCategoryId) values ("Restaurant", 6021);
  INSERT INTO t1(poiCategory, poiCategoryId) values ('Restaurant', 6021);
}

do_execsql_test 6.2.2 {
  SELECT * FROM t1 WHERE t1 MATCH 'restaurant';
} {}
do_execsql_test 6.2.3 {
  SELECT * FROM t1 WHERE t1 MATCH 're*';

Added test/fts4record.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019 September 18
#
# 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 script is testing the FTS4 module.
#
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/fts3_common.tcl
set testprefix fts4record

# If SQLITE_ENABLE_FTS3 is defined, omit this file.
ifcapable !fts3 {
  finish_test
  return
}

sqlite3_fts3_may_be_corrupt 1

do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE t1 USING fts4(x);
  INSERT INTO t1 VALUES('terma terma terma termb');
}

do_execsql_test 1.1 {
  SELECT quote(root) FROM t1_segdir
} {
  X'00057465726D6105010203030004016203010500'
}

proc make_record_wrapper {args} { make_fts3record $args }
db func record make_record_wrapper

do_execsql_test 1.2 {
  select quote( 
    record(0,    5, 'terma', 5, 1, 2, 3, 3, 0, 
              4, 1, 'b'    , 3, 1, 5, 0
  ) );
} {
  X'00057465726D6105010203030004016203010500'
}

do_execsql_test 1.3.1 {
  UPDATE t1_segdir SET root = 
    record(0,    5, 'terma', 5, 1, 2, 3, 3, 0, 
              4, 1, 'b'    , 3, 1, 5, 
              1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
              1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
              1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0
          );
}

do_catchsql_test 1.3.2 {
  SELECT snippet(t1) FROM t1 WHERE t1 MATCH 'term*'
} {1 {database disk image is malformed}}

do_execsql_test 1.4.1 {
  UPDATE t1_segdir SET root = 
    record(0,    5, 'terma', 5, 1, 2, 3, 3, 0, 
              4, 1, 'b'    , 4, 1, 5, 
              256, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
              1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
              1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0
          );
}

do_catchsql_test 1.4.2 {
  SELECT snippet(t1) FROM t1 WHERE t1 MATCH 'term*'
} {1 {database disk image is malformed}}

do_execsql_test 1.4.3 {
  SELECT quote(root) FROM t1_segdir
} {
  X'00057465726D610501020303000401620401058002010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010100'
}

do_execsql_test 1.5.1 {
  UPDATE t1_segdir SET root = 
    record(0,    5, 'terma', 5, 1, 2, 3, 3, 0, 
              4, 1, 'b'    , 4, 1, 5, 
              256, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
              1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
              1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0
          );
}

do_catchsql_test 1.4.2 {
  SELECT snippet(t1) FROM t1 WHERE t1 MATCH 'term*'
} {1 {database disk image is malformed}}

do_execsql_test 1.4.3 {
  SELECT quote(root) FROM t1_segdir
} {
  X'00057465726D610501020303000401620401058002010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010100'
}


do_execsql_test 1.5.1 {
  UPDATE t1_segdir SET root = 
  X'00057465726D61050102030300040162040105FF00010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010100'
}

do_catchsql_test 1.5.2 {
  SELECT snippet(t1) FROM t1 WHERE t1 MATCH 'term*'
} {1 {database disk image is malformed}}

do_catchsql_test 1.5.3 {
  INSERT INTO t1(t1) VALUES('integrity-check');
} {1 {database disk image is malformed}}

finish_test

Added test/fts4rename.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019 April 30
#
# 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/fts3_common.tcl
set ::testprefix fts4rename

# If SQLITE_ENABLE_FTS3 is defined, omit this file.
ifcapable !fts3 {
  finish_test
  return
}

do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE temp.t1 USING fts3(a);
  BEGIN;
  CREATE TABLE t2(x);
} {}

do_catchsql_test 1.1 {
  ALTER TABLE t1_content RENAME c0a TO docid;
} {1 {error in table t1_content after rename: duplicate column name: docid}}

do_catchsql_test 1.2 {
  UPDATE t1 SET Col0 = 1 ;
} {1 {no such column: Col0}}

do_catchsql_test 1.3 {
  ROLLBACK;
  DROP TABLE t1;
} {0 {}}

finish_test

Changes to test/fts4umlaut.test.

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







-
+








ifcapable !fts3 {
  finish_test
  return
}

do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE t1 USING fts5(x);
  CREATE VIRTUAL TABLE t1 USING fts4(x, tokenize=unicode61);
  CREATE VIRTUAL TABLE t2 USING fts4(
      x, 
      tokenize=unicode61 "remove_diacritics=2"
  );
}

foreach {tn q res1 res2} {
45
46
47
48
49
50
51
52

53
54
55
56
57

58
59
60
61
62
63
64
65
45
46
47
48
49
50
51

52
53
54
55
56

57
58
59
60
61
62
63
64








-
+




-
+







-
  } $res1
  do_execsql_test 1.$tn.2 {
    DELETE FROM t1;
    INSERT INTO t1(rowid, x) VALUES (1, $q);
    SELECT count(*) FROM t1 WHERE t1 MATCH 'Ha Noi'
  } $res1

  do_execsql_test 1.$tn.2 {
  do_execsql_test 1.$tn.3 {
    DELETE FROM t2;
    INSERT INTO t2(rowid, x) VALUES (1, 'Ha Noi');
    SELECT count(*) FROM t2 WHERE t2 MATCH $q
  } $res2
  do_execsql_test 1.$tn.2 {
  do_execsql_test 1.$tn.4 {
    DELETE FROM t2;
    INSERT INTO t2(rowid, x) VALUES (1, $q);
    SELECT count(*) FROM t2 WHERE t2 MATCH 'Ha Noi'
  } $res2
}

finish_test

Changes to test/fts4unicode.test.

562
563
564
565
566
567
568


















569
570
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


  CREATE VIRTUAL TABLE ft1 USING fts3tokenize(
    "unicode61", "tokenchars=@.", "separators=1234567890"
  );
  SELECT token FROM ft1 WHERE input = 'berlin@street123sydney.road';
} {
  berlin@street sydney.road
}

# Test for embedded nul characters in fts4 unicode index.
#
do_execsql_test 12.0 {
  CREATE VIRTUAL TABLE t12 USING fts4(tokenize=unicode61);
  INSERT INTO t12 VALUES('abc' || char(0) || 'def');
  SELECT hex(CAST(content AS blob)) FROM t12;
} {61626300646566}
do_execsql_test 12.1 {
  INSERT INTO t12(t12) VALUES('integrity-check');
} {}
do_execsql_test 12.2 { 
  CREATE VIRTUAL TABLE t12aux USING fts4aux(t12);
  SELECT * FROM t12aux;
} {abc * 1 1 abc 0 1 1}
do_execsql_test 12.3 { 
  SELECT hex(CAST(content AS blob)) FROM t12 WHERE t12 MATCH 'abc'
} {61626300646566}

finish_test

Added test/fts4upfrom.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2020 February 24
#
# 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 script is testing UPDATE statements with FROM clauses
# against FTS4 tables.
#
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix fts4upfrom

# If SQLITE_ENABLE_FTS3 is defined, omit this file.
ifcapable !fts3 {
  finish_test
  return
}

foreach {tn create_table} {
  0 { CREATE VIRTUAL TABLE ft USING fts5(a, b, c) }
  1 { CREATE VIRTUAL TABLE ft USING fts3(a, b, c) }
  2 { CREATE TABLE ft(a, b, c) }
  3 { 
    CREATE TABLE real(a, b, c);
    CREATE INDEX i1 ON real(a);
    CREATE VIEW ft AS SELECT rowid, a, b, c FROM real;
    CREATE TRIGGER tr1 INSTEAD OF INSERT ON ft BEGIN
      INSERT INTO real(rowid, a, b, c) VALUES(new.rowid, new.a, new.b, new.c);
    END;
    CREATE TRIGGER tr2 INSTEAD OF UPDATE ON ft BEGIN
      UPDATE real SET rowid=new.rowid, a=new.a, b=new.b, c=new.c 
      WHERE rowid=old.rowid;
    END;
  }
} {
  if {$tn==0} { ifcapable !fts5 { continue } }
  catchsql { DROP VIEW IF EXISTS changes }
  catchsql { DROP TABLE IF EXISTS ft }
  catchsql { DROP VIEW IF EXISTS ft }
  execsql $create_table

  do_execsql_test 1.$tn.0 {
    INSERT INTO ft(a, b, c) VALUES('a', NULL, 'apple');
    INSERT INTO ft(a, b, c) VALUES('b', NULL, 'banana');
    INSERT INTO ft(a, b, c) VALUES('c', NULL, 'cherry');
    INSERT INTO ft(a, b, c) VALUES('d', NULL, 'damson plum');
  }
  
  do_execsql_test 1.$tn.1 {
    SELECT a, b, c FROM ft ORDER BY rowid;
  } {
    a {} apple
    b {} banana
    c {} cherry
    d {} {damson plum}
  }
  
  do_execsql_test 1.$tn.2 {
    UPDATE ft SET b=o.c FROM ft AS o WHERE (ft.a == char(unicode(o.a)+1))
  }
  
  do_execsql_test 1.$tn.3 {
    SELECT a, b, c FROM ft ORDER BY rowid;
  } {
    a {} apple
    b apple banana
    c banana cherry
    d cherry {damson plum}
  }

  do_catchsql_test 1.$tn.4 {
    UPDATE ft SET c=v FROM changes WHERE a=k;
  } {1 {no such table: changes}}

  do_execsql_test 1.$tn.5 {
    create view changes(k, v) AS 
      VALUES( 'd', 'dewberry' ) UNION ALL
      VALUES( 'c', 'clementine' ) UNION ALL
      VALUES( 'b', 'blueberry' ) UNION ALL
      VALUES( 'a', 'apricot' ) 
    ;
  }

  do_execsql_test 1.$tn.6 {
    UPDATE ft SET c=v FROM changes WHERE a=k;
  }

  do_execsql_test 1.$tn.7 {
    SELECT rowid, a, b, c FROM ft ORDER BY rowid;
  } {
    1 a {} apricot
    2 b apple blueberry
    3 c banana clementine
    4 d cherry dewberry
  }

  do_execsql_test 1.$tn.8 "
    WITH x1(o, n) AS (
        VALUES(1, 11) UNION ALL
        VALUES(2, 12) UNION ALL
        VALUES(3, 13) UNION ALL
        VALUES(4, 14)
    )
    SELECT ft.rowid, a, b, c, o, n FROM ft, x1 WHERE ft.rowid = o;
  " {
    1 a {} apricot 1 11
    2 b apple blueberry 2 12
    3 c banana clementine 3 13
    4 d cherry dewberry 4 14
  }

  set ROWID rowid
  if {$tn==1} { set ROWID docid }
  do_execsql_test 1.$tn.9 "
    WITH x1(o, n) AS (
        VALUES(1, 11) UNION ALL
        VALUES(2, 12) UNION ALL
        VALUES(3, 13) UNION ALL
        VALUES(4, 14)
    )
    UPDATE ft SET $ROWID = n FROM x1 WHERE ft.rowid = o;
    SELECT rowid, a, b, c FROM ft ORDER BY rowid;
  " {
    11 a {} apricot
    12 b apple blueberry
    13 c banana clementine
    14 d cherry dewberry
  }
}

finish_test

Changes to test/func.test.

311
312
313
314
315
316
317



318
319
320
321
322
323
324
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327







+
+
+







  } {99999999999995.0}
  do_test func-4.37 {
    execsql {SELECT round(9999999999999.55,1);}
  } {9999999999999.6}
  do_test func-4.38 {
    execsql {SELECT round(9999999999999.556,2);}
  } {9999999999999.56}
  do_test func-4.39 {
    string tolower [db eval {SELECT round(1e500), round(-1e500);}]
  } {inf -inf}
}

# Test the upper() and lower() functions
#
do_test func-5.1 {
  execsql {SELECT upper(t1) FROM tbl1}
} {THIS PROGRAM IS FREE SOFTWARE}
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
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







-
+




-
+




-
+




-
+




-
+




-
+







do_test func-21.2 {
  catchsql {
    SELECT replace(1,2,3,4);
  }
} {1 {wrong number of arguments to function replace()}}
do_test func-21.3 {
  execsql {
    SELECT typeof(replace("This is the main test string", NULL, "ALT"));
    SELECT typeof(replace('This is the main test string', NULL, 'ALT'));
  }
} {null}
do_test func-21.4 {
  execsql {
    SELECT typeof(replace(NULL, "main", "ALT"));
    SELECT typeof(replace(NULL, 'main', 'ALT'));
  }
} {null}
do_test func-21.5 {
  execsql {
    SELECT typeof(replace("This is the main test string", "main", NULL));
    SELECT typeof(replace('This is the main test string', 'main', NULL));
  }
} {null}
do_test func-21.6 {
  execsql {
    SELECT replace("This is the main test string", "main", "ALT");
    SELECT replace('This is the main test string', 'main', 'ALT');
  }
} {{This is the ALT test string}}
do_test func-21.7 {
  execsql {
    SELECT replace("This is the main test string", "main", "larger-main");
    SELECT replace('This is the main test string', 'main', 'larger-main');
  }
} {{This is the larger-main test string}}
do_test func-21.8 {
  execsql {
    SELECT replace("aaaaaaa", "a", "0123456789");
    SELECT replace('aaaaaaa', 'a', '0123456789');
  }
} {0123456789012345678901234567890123456789012345678901234567890123456789}

ifcapable tclvar {
  do_test func-21.9 {
    # Attempt to exploit a buffer-overflow that at one time existed 
    # in the REPLACE function. 
1103
1104
1105
1106
1107
1108
1109







1110
1111
1112
1113
1114
1115
1116
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126







+
+
+
+
+
+
+







} {null}
do_test func-22.21 {
  execsql {SELECT typeof(trim(NULL,'xyz'));}
} {null}
do_test func-22.22 {
  execsql {SELECT typeof(trim('hello',NULL));}
} {null}

# 2021-06-15 - infinite loop due to unsigned character counter
# overflow, reported by Zimuzo Ezeozue
#
do_execsql_test func-22.23 {
  SELECT trim('xyzzy',x'c0808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080');
} {xyzzy}

# This is to test the deprecated sqlite3_aggregate_count() API.
#
ifcapable deprecated {
  do_test func-23.1 {
    sqlite3_create_aggregate db
    execsql {
1301
1302
1303
1304
1305
1306
1307
1308

1309
1310
1311
1312
1313
1314
1315
1311
1312
1313
1314
1315
1316
1317

1318
1319
1320
1321
1322
1323
1324
1325







-
+







# the content of their argument.
#
do_test func-29.1 {
  db eval {
    CREATE TABLE t29(id INTEGER PRIMARY KEY, x, y);
    INSERT INTO t29 VALUES(1, 2, 3), (2, NULL, 4), (3, 4.5, 5);
    INSERT INTO t29 VALUES(4, randomblob(1000000), 6);
    INSERT INTO t29 VALUES(5, "hello", 7);
    INSERT INTO t29 VALUES(5, 'hello', 7);
  }
  db close
  sqlite3 db test.db
  sqlite3_db_status db CACHE_MISS 1
  db eval {SELECT typeof(x), length(x), typeof(y) FROM t29 ORDER BY id}
} {integer 1 integer null {} integer real 3 integer blob 1000000 integer text 5 integer}
do_test func-29.2 {
1387
1388
1389
1390
1391
1392
1393

























































































































1394
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

}

# Test char().
#
do_execsql_test func-31.1 { 
  SELECT char(), length(char()), typeof(char()) 
} {{} 0 text}

# sqlite3_value_frombind()
#
do_execsql_test func-32.100 {
  SELECT test_frombind(1,2,3,4);
} {0}
do_execsql_test func-32.110 {
  SELECT test_frombind(1,2,?,4);
} {4}
do_execsql_test func-32.120 {
  SELECT test_frombind(1,(?),4,?+7);
} {2}
do_execsql_test func-32.130 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a,b,c,e,f);
  INSERT INTO t1 VALUES(1,2.5,'xyz',x'e0c1b2a3',null);
  SELECT test_frombind(a,b,c,e,f,$xyz) FROM t1;
} {32}
do_execsql_test func-32.140 {
  SELECT test_frombind(a,b,c,e,f,$xyz+f) FROM t1;
} {0}
do_execsql_test func-32.150 {
  SELECT test_frombind(x.a,y.b,x.c,:123,y.e,x.f,$xyz+y.f) FROM t1 x, t1 y;
} {8}

# 2019-08-15
# Direct-only functions.
#
proc testdirectonly {x} {return [expr {$x*2}]}
do_test func-33.1 {
  db func testdirectonly -directonly testdirectonly
  db eval {SELECT testdirectonly(15)}
} {30}
do_catchsql_test func-33.2 {
  CREATE VIEW v33(y) AS SELECT testdirectonly(15);
  SELECT * FROM v33;
} {1 {unsafe use of testdirectonly()}}
do_execsql_test func-33.3 {
  SELECT * FROM (SELECT testdirectonly(15)) AS v33;
} {30}
do_execsql_test func-33.4 {
  WITH c(x) AS (SELECT testdirectonly(15))
  SELECT * FROM c;
} {30}
do_catchsql_test func-33.5 {
  WITH c(x) AS (SELECT * FROM v33)
  SELECT * FROM c;
} {1 {unsafe use of testdirectonly()}}
do_execsql_test func-33.10 {
  CREATE TABLE t33a(a,b);
  CREATE TABLE t33b(x,y);
  CREATE TRIGGER r1 AFTER INSERT ON t33a BEGIN
    INSERT INTO t33b(x,y) VALUES(testdirectonly(new.a),new.b);
  END;
} {}
do_catchsql_test func-33.11 {
  INSERT INTO t33a VALUES(1,2);
} {1 {unsafe use of testdirectonly()}}

ifcapable altertable {
do_execsql_test func-33.20 {
  ALTER TABLE t33a RENAME COLUMN a TO aaa;
  SELECT sql FROM sqlite_master WHERE name='r1';
} {{CREATE TRIGGER r1 AFTER INSERT ON t33a BEGIN
    INSERT INTO t33b(x,y) VALUES(testdirectonly(new.aaa),new.b);
  END}}
}

# 2020-01-09 Yongheng fuzzer find
# The bug is in the register-validity debug logic, not in the SQLite core
# and as such it only impacts debug builds.  Release builds work fine.
#
reset_db
do_execsql_test func-34.10 {
  CREATE TABLE t1(a INT CHECK(
     datetime( 0, 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,a)
   )
  );
  INSERT INTO t1(a) VALUES(1),(2);
  SELECT * FROM t1;
} {1 2}

# 2020-03-11 COALESCE() should short-circuit
# See also ticket 3c9eadd2a6ba0aa5
# Both issues stem from the fact that functions that could
# throw exceptions were being factored out into initialization
# code.  The fix was to put those function calls inside of
# OP_Once instead.
#
reset_db
do_execsql_test func-35.100 {
  CREATE TABLE t1(x);
  SELECT coalesce(x, abs(-9223372036854775808)) FROM t1;
} {}
do_execsql_test func-35.110 {
  SELECT coalesce(x, 'xyz' LIKE printf('%.1000000c','y')) FROM t1;
} {}
do_execsql_test func-35.200 {
  CREATE TABLE t0(c0 CHECK(ABS(-9223372036854775808)));
  PRAGMA integrity_check;
} {ok}

# 2021-01-07:  The -> and ->> operators.
#
proc ptr1 {a b} { return "$a->$b" }
db func -> ptr1
proc ptr2 {a b} { return "$a->>$b" }
db func ->> ptr2
do_execsql_test func-36.100 {
  SELECT 123 -> 456
} {123->456}
do_execsql_test func-36.110 {
  SELECT 123 ->> 456
} {123->>456}



finish_test

Changes to test/func3.test.

149
150
151
152
153
154
155













156
157
158
159
160
161
162
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







+
+
+
+
+
+
+
+
+
+
+
+
+







# the code generator optimizes away so that it consumes no CPU cycles at
# run-time (that is, during calls to sqlite3_step()).
#
do_test func3-5.39 {
  db eval {EXPLAIN SELECT unlikely(min(1.0+'2.0',4*11))}
} [db eval {EXPLAIN SELECT min(1.0+'2.0',4*11)}]

# Unlikely() does not preserve the affinity of X.
# ticket https://www.sqlite.org/src/tktview/0c620df60b
#
do_execsql_test func3-5.40 {
  SELECT likely(CAST(1 AS INT))=='1';
} 0
do_execsql_test func3-5.41 {
  SELECT unlikely(CAST(1 AS INT))=='1';
} 0
do_execsql_test func3-5.41 {
  SELECT likelihood(CAST(1 AS INT),0.5)=='1';
} 0


# EVIDENCE-OF: R-23735-03107 The likely(X) function returns the argument
# X unchanged.
#
do_execsql_test func3-5.50 {
  SELECT likely(9223372036854775807);
} {9223372036854775807}
180
181
182
183
184
185
186








187
188
189
190
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211







+
+
+
+
+
+
+
+




# code generator optimizes away so that it consumes no CPU cycles at
# run-time (that is, during calls to sqlite3_step()).
#
do_test func3-5.59 {
  db eval {EXPLAIN SELECT likely(min(1.0+'2.0',4*11))}
} [db eval {EXPLAIN SELECT min(1.0+'2.0',4*11)}]


# Test the outcome of specifying NULL xStep and xFinal pointers (normally
# used to delete any existing function) and a non-NULL xDestroy when there 
# is no existing function to destroy.
#
do_test func3-6.0 {
  sqlite3_create_function_v2 db nofunc 1 utf8
} {}



finish_test

Changes to test/func4.test.

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
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







-
+




-
+




-
+




-
+




-
+




-
+









-
+









-
+




-
+




-
+




-
+




-
+




-
+









-
+





-
+


-
-
+
+











-
+




-
+




-
+




-
+




-
+




-
+







      x INTEGER CHECK(tointeger(x) IS NOT NULL)
    );
  } {}
  do_test func4-3.2 {
    catchsql {
      INSERT INTO t1 (x) VALUES (NULL);
    }
  } {1 {CHECK constraint failed: t1}}
  } {1 {CHECK constraint failed: tointeger(x) IS NOT NULL}}
  do_test func4-3.3 {
    catchsql {
      INSERT INTO t1 (x) VALUES (NULL);
    }
  } {1 {CHECK constraint failed: t1}}
  } {1 {CHECK constraint failed: tointeger(x) IS NOT NULL}}
  do_test func4-3.4 {
    catchsql {
      INSERT INTO t1 (x) VALUES ('');
    }
  } {1 {CHECK constraint failed: t1}}
  } {1 {CHECK constraint failed: tointeger(x) IS NOT NULL}}
  do_test func4-3.5 {
    catchsql {
      INSERT INTO t1 (x) VALUES ('bad');
    }
  } {1 {CHECK constraint failed: t1}}
  } {1 {CHECK constraint failed: tointeger(x) IS NOT NULL}}
  do_test func4-3.6 {
    catchsql {
      INSERT INTO t1 (x) VALUES ('1234bad');
    }
  } {1 {CHECK constraint failed: t1}}
  } {1 {CHECK constraint failed: tointeger(x) IS NOT NULL}}
  do_test func4-3.7 {
    catchsql {
      INSERT INTO t1 (x) VALUES ('1234.56bad');
    }
  } {1 {CHECK constraint failed: t1}}
  } {1 {CHECK constraint failed: tointeger(x) IS NOT NULL}}
  do_test func4-3.8 {
    catchsql {
      INSERT INTO t1 (x) VALUES (1234);
    }
  } {0 {}}
  do_test func4-3.9 {
    catchsql {
      INSERT INTO t1 (x) VALUES (1234.56);
    }
  } {1 {CHECK constraint failed: t1}}
  } {1 {CHECK constraint failed: tointeger(x) IS NOT NULL}}
  do_test func4-3.10 {
    catchsql {
      INSERT INTO t1 (x) VALUES ('1234');
    }
  } {0 {}}
  do_test func4-3.11 {
    catchsql {
      INSERT INTO t1 (x) VALUES ('1234.56');
    }
  } {1 {CHECK constraint failed: t1}}
  } {1 {CHECK constraint failed: tointeger(x) IS NOT NULL}}
  do_test func4-3.12 {
    catchsql {
      INSERT INTO t1 (x) VALUES (ZEROBLOB(4));
    }
  } {1 {CHECK constraint failed: t1}}
  } {1 {CHECK constraint failed: tointeger(x) IS NOT NULL}}
  do_test func4-3.13 {
    catchsql {
      INSERT INTO t1 (x) VALUES (X'');
    }
  } {1 {CHECK constraint failed: t1}}
  } {1 {CHECK constraint failed: tointeger(x) IS NOT NULL}}
  do_test func4-3.14 {
    catchsql {
      INSERT INTO t1 (x) VALUES (X'1234');
    }
  } {1 {CHECK constraint failed: t1}}
  } {1 {CHECK constraint failed: tointeger(x) IS NOT NULL}}
  do_test func4-3.15 {
    catchsql {
      INSERT INTO t1 (x) VALUES (X'12345678');
    }
  } {1 {CHECK constraint failed: t1}}
  } {1 {CHECK constraint failed: tointeger(x) IS NOT NULL}}
  do_test func4-3.16 {
    catchsql {
      INSERT INTO t1 (x) VALUES ('1234.00');
    }
  } {1 {CHECK constraint failed: t1}}
  } {0 {}}
  do_test func4-3.17 {
    catchsql {
      INSERT INTO t1 (x) VALUES (1234.00);
    }
  } {0 {}}
  do_test func4-3.18 {
    catchsql {
      INSERT INTO t1 (x) VALUES ('-9223372036854775809');
    }
  } {1 {CHECK constraint failed: t1}}
  } {0 {}}
  if {$highPrecision(1)} {
    do_test func4-3.19 {
      catchsql {
        INSERT INTO t1 (x) VALUES (9223372036854775808);
      }
    } {1 {CHECK constraint failed: t1}}
    } {1 {CHECK constraint failed: tointeger(x) IS NOT NULL}}
  }
  do_execsql_test func4-3.20 {
    SELECT x FROM t1 ORDER BY x;
  } {1234 1234 1234}
    SELECT x FROM t1 WHERE x>0 ORDER BY x;
  } {1234 1234 1234 1234}

  ifcapable floatingpoint {
    do_execsql_test func4-4.1 {
      CREATE TABLE t2(
        x REAL CHECK(toreal(x) IS NOT NULL)
      );
    } {}
    do_test func4-4.2 {
      catchsql {
        INSERT INTO t2 (x) VALUES (NULL);
      }
    } {1 {CHECK constraint failed: t2}}
    } {1 {CHECK constraint failed: toreal(x) IS NOT NULL}}
    do_test func4-4.3 {
      catchsql {
        INSERT INTO t2 (x) VALUES (NULL);
      }
    } {1 {CHECK constraint failed: t2}}
    } {1 {CHECK constraint failed: toreal(x) IS NOT NULL}}
    do_test func4-4.4 {
      catchsql {
        INSERT INTO t2 (x) VALUES ('');
      }
    } {1 {CHECK constraint failed: t2}}
    } {1 {CHECK constraint failed: toreal(x) IS NOT NULL}}
    do_test func4-4.5 {
      catchsql {
        INSERT INTO t2 (x) VALUES ('bad');
      }
    } {1 {CHECK constraint failed: t2}}
    } {1 {CHECK constraint failed: toreal(x) IS NOT NULL}}
    do_test func4-4.6 {
      catchsql {
        INSERT INTO t2 (x) VALUES ('1234bad');
      }
    } {1 {CHECK constraint failed: t2}}
    } {1 {CHECK constraint failed: toreal(x) IS NOT NULL}}
    do_test func4-4.7 {
      catchsql {
        INSERT INTO t2 (x) VALUES ('1234.56bad');
      }
    } {1 {CHECK constraint failed: t2}}
    } {1 {CHECK constraint failed: toreal(x) IS NOT NULL}}
    do_test func4-4.8 {
      catchsql {
        INSERT INTO t2 (x) VALUES (1234);
      }
    } {0 {}}
    do_test func4-4.9 {
      catchsql {
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
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







-
+




-
+




-
+




-
+







        INSERT INTO t2 (x) VALUES ('1234.56');
      }
    } {0 {}}
    do_test func4-4.12 {
      catchsql {
        INSERT INTO t2 (x) VALUES (ZEROBLOB(4));
      }
    } {1 {CHECK constraint failed: t2}}
    } {1 {CHECK constraint failed: toreal(x) IS NOT NULL}}
    do_test func4-4.13 {
      catchsql {
        INSERT INTO t2 (x) VALUES (X'');
      }
    } {1 {CHECK constraint failed: t2}}
    } {1 {CHECK constraint failed: toreal(x) IS NOT NULL}}
    do_test func4-4.14 {
      catchsql {
        INSERT INTO t2 (x) VALUES (X'1234');
      }
    } {1 {CHECK constraint failed: t2}}
    } {1 {CHECK constraint failed: toreal(x) IS NOT NULL}}
    do_test func4-4.15 {
      catchsql {
        INSERT INTO t2 (x) VALUES (X'12345678');
      }
    } {1 {CHECK constraint failed: t2}}
    } {1 {CHECK constraint failed: toreal(x) IS NOT NULL}}
    do_execsql_test func4-4.16 {
      SELECT x FROM t2 ORDER BY x;
    } {1234.0 1234.0 1234.56 1234.56}
  }
}

ifcapable floatingpoint {

Changes to test/func5.test.

49
50
51
52
53
54
55

56
57
58

59
60
61
62
63
49
50
51
52
53
54
55
56
57
58

59
60
61
62
63
64







+


-
+





} {1 2 3 4 5 6 7 8}
sqlite3_create_function db
do_execsql_test func5-2.2 {
  SELECT x, y FROM t2
   WHERE x+counter1('hello')=counter1('hello')+x
   ORDER BY +x;
} {}
set cvalue [db one {SELECT counter2('hello')+1}]
do_execsql_test func5-2.3 {
  SELECT x, y FROM t2
   WHERE x+counter2('hello')=counter2('hello')+x
   WHERE x+counter2('hello')=$cvalue+x
   ORDER BY +x;
} {1 2 3 4 5 6 7 8}


finish_test

Changes to test/func6.test.

166
167
168
169
170
171
172









173
174
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183







+
+
+
+
+
+
+
+
+


  ORDER BY b
} [concat $z100 $z100 $z100]

# Test offsets in WITHOUT ROWID table t2.
do_execsql_test func6-200 {
  SELECT offrec( sqlite_offset(y), x, y ) FROM t2 ORDER BY x
} $z100

# 2022-03-14 dbsqlfuzz 474499f3977d95fdf2dbcd99c50be1d0082e4c92
reset_db
do_execsql_test func6-300 {
  CREATE TABLE t2(a INT, b INT PRIMARY KEY) WITHOUT ROWID;
  CREATE INDEX x3 ON t2(b);
  CREATE TABLE t1(a INT PRIMARY KEY, b TEXT);
  SELECT * FROM t1 WHERE a IN (SELECT sqlite_offset(b) FROM t2);
} {}

finish_test

Added test/func7.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2020-12-07
#
# 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.
#
#*************************************************************************
#
# Test cases for SQL functions based off the standard math library
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable !mathlib {
  finish_test
  return
}

do_execsql_test func7-100 {
  SELECT ceil(99.9), ceiling(-99.01), floor(17), floor(-17.99);
} {100.0 -99.0 17 -18.0}
do_execsql_test func7-110 {
  SELECT quote(ceil(NULL)), ceil('-99.99');
} {NULL -99.0}
do_execsql_test func7-200 {
  SELECT round(ln(5),2), log(100.0), log(100), log(2,'256');
} {1.61 2.0 2.0 8.0}
do_execsql_test func7-210 {
  SELECT ln(-5), log(-5,100.0);
} {{} {}}

# Test cases derived from PostgreSQL documentation
#
do_execsql_test func7-pg-100 {
  SELECT abs(-17.4)
} {17.4}
do_execsql_test func7-pg-110 {
  SELECT ceil(42.2)
} {43.0}
do_execsql_test func7-pg-120 {
  SELECT ceil(-42.2)
} {-42.0}
do_execsql_test func7-pg-130 {
  SELECT round(exp(1.0),7)
} {2.7182818}
do_execsql_test func7-pg-140 {
  SELECT floor(42.8)
} {42.0}
do_execsql_test func7-pg-150 {
  SELECT floor(-42.8)
} {-43.0}
do_execsql_test func7-pg-160 {
  SELECT round(ln(2.0),7)
} {0.6931472}
do_execsql_test func7-pg-170 {
  SELECT log(100.0)
} {2.0}
do_execsql_test func7-pg-180 {
  SELECT log10(1000.0)
} {3.0}
do_execsql_test func7-pg-181 {
  SELECT format('%.30f', log10(100.0) );
} {2.000000000000000000000000000000}
do_execsql_test func7-pg-182 {
  SELECT format('%.30f', ln(exp(2.0)) );
} {2.000000000000000000000000000000}
do_execsql_test func7-pg-190 {
  SELECT log(2.0, 64.0)
} {6.0}
do_execsql_test func7-pg-200 {
   SELECT mod(9,4);
} {1.0}
do_execsql_test func7-pg-210 {
   SELECT round(pi(),7);
} {3.1415927}
do_execsql_test func7-pg-220 {
   SELECT power(9,3);
} {729.0}
do_execsql_test func7-pg-230 {
   SELECT round(radians(45.0),7);
} {0.7853982}
do_execsql_test func7-pg-240 {
   SELECT round(42.4);
} {42.0}
do_execsql_test func7-pg-250 {
   SELECT round(42.4382,2);
} {42.44}
do_execsql_test func7-pg-260 {
   SELECT sign(-8.4);
} {-1}
do_execsql_test func7-pg-270 {
   SELECT round( sqrt(2), 7);
} {1.4142136}
do_execsql_test func7-pg-280 {
   SELECT trunc(42.8), trunc(-42.8);
} {42.0 -42.0}
do_execsql_test func7-pg-300 {
   SELECT acos(1);
} {0.0}
do_execsql_test func7-pg-301 {
   SELECT degrees(acos(0.5));
} {60.0}
do_execsql_test func7-pg-310 {
   SELECT round( asin(1), 7);
} {1.5707963}
do_execsql_test func7-pg-311 {
   SELECT degrees( asin(0.5) );
} {30.0}
do_execsql_test func7-pg-320 {
   SELECT round( atan(1), 7);
} {0.7853982}
do_execsql_test func7-pg-321 {
   SELECT degrees( atan(1) );
} {45.0}
do_execsql_test func7-pg-330 {
   SELECT round( atan2(1,0), 7);
} {1.5707963}
do_execsql_test func7-pg-331 {
   SELECT degrees( atan2(1,0) );
} {90.0}
do_execsql_test func7-pg-400 {
   SELECT cos(0);
} {1.0}
do_execsql_test func7-pg-401 {
   SELECT cos( radians(60.0) );
} {0.5}
do_execsql_test func7-pg-400 {
   SELECT cos(0);
} {1.0}
do_execsql_test func7-pg-410 {
   SELECT round( sin(1), 7);
} {0.841471}
do_execsql_test func7-pg-411 {
   SELECT sin( radians(30) );
} {0.5}
do_execsql_test func7-pg-420 {
   SELECT round( tan(1), 7);
} {1.5574077}
do_execsql_test func7-pg-421 {
   SELECT tan( radians(45) );
} {1.0}
do_execsql_test func7-pg-500 {
   SELECT round( sinh(1), 7);
} {1.1752012}
do_execsql_test func7-pg-510 {
   SELECT round( cosh(0), 7);
} {1.0}
do_execsql_test func7-pg-520 {
   SELECT round( tanh(1), 7);
} {0.7615942}
do_execsql_test func7-pg-530 {
   SELECT round( asinh(1), 7);
} {0.8813736}
do_execsql_test func7-pg-540 {
   SELECT round( acosh(1), 7);
} {0.0}
do_execsql_test func7-pg-550 {
   SELECT round( atanh(0.5), 7);
} {0.5493061}

# Test cases derived from MySQL documentation
#
do_execsql_test func7-mysql-100 {
   SELECT acos(1);
} {0.0}
do_execsql_test func7-mysql-110 {
   SELECT acos(1.0001);
} {{}}
do_execsql_test func7-mysql-120 {
   SELECT round( acos(0.0), 7);
} {1.5707963}
do_execsql_test func7-mysql-130 {
   SELECT round( asin(0.2), 7);
} {0.2013579}
do_execsql_test func7-mysql-140 {
   SELECT asin('foo');
} {{}}  ;# Note: MySQL returns 0 here, not NULL.
         # SQLite deliberately returns NULL.
         # SQLServer and Oracle throw an error.
do_execsql_test func7-mysql-150 {
   SELECT round( atan(2), 7), round( atan(-2), 7);
} {1.1071487 -1.1071487}
do_execsql_test func7-mysql-160 {
   SELECT round( atan2(-2,2), 7), round( atan2(pi(),0), 7);
} {-0.7853982 1.5707963}
do_execsql_test func7-mysql-170 {
   SELECT ceiling(1.23), ceiling(-1.23);
} {2.0 -1.0}
do_execsql_test func7-mysql-180 {
   SELECT cos(pi());
} {-1.0}
do_execsql_test func7-mysql-190 {
   SELECT degrees(pi()), degrees(pi()/2);
} {180.0 90.0}
do_execsql_test func7-mysql-190 {
   SELECT round( exp(2), 7), round( exp(-2), 7), exp(0);
} {7.3890561 0.1353353 1.0}
do_execsql_test func7-mysql-200 {
   SELECT floor(1.23), floor(-1.23);
} {1.0 -2.0}
do_execsql_test func7-mysql-210 {
   SELECT round(ln(2),7), quote(ln(-2));
} {0.6931472 NULL}
#do_execsql_test func7-mysql-220 {
#   SELECT round(log(2),7), log(-2);
#} {0.6931472 NULL}
# log() means natural logarithm in MySQL
do_execsql_test func7-mysql-230 {
   SELECT log(2,65536), log(10,100), quote(log(1,100)), quote(log(0,100));
} {16.0 2.0 NULL NULL}
do_execsql_test func7-mysql-240 {
   SELECT log2(65536), quote(log2(-100)), quote(log2(0));
} {16.0 NULL NULL}
do_execsql_test func7-mysql-250 {
   SELECT round(log10(2),7), log10(100), quote(log10(-100));
} {0.30103 2.0 NULL}
do_execsql_test func7-mysql-260 {
   SELECT mod(234,10), 253%7, mod(29,9), 29%9;
} {4.0 1 2.0 2}
do_execsql_test func7-mysql-270 {
   SELECT mod(34.5,3);
} {1.5}
do_execsql_test func7-mysql-280 {
   SELECT pow(2,2), pow(2,-2);
} {4.0 0.25}
do_execsql_test func7-mysql-281 {
   SELECT power(2,2), power(2,-2);
} {4.0 0.25}
do_execsql_test func7-mysql-290 {
   SELECT round(radians(90),7);
} {1.5707963}
do_execsql_test func7-mysql-300 {
   SELECT sign(-32), sign(0), sign(234);
} {-1 0 1}
do_execsql_test func7-mysql-310 {
   SELECT sin(pi()) BETWEEN -1.0e-15 AND 1.0e-15;
} {1}
do_execsql_test func7-mysql-320 {
   SELECT sqrt(4), round(sqrt(20),7), quote(sqrt(-16));
} {2.0 4.472136 NULL}
do_execsql_test func7-mysql-330 {
   SELECT tan(pi()) BETWEEN -1.0e-15 AND 1.0e-15;
} {1}
do_execsql_test func7-mysql-331 {
   SELECT round(tan(pi()+1),7);
} {1.5574077}


finish_test

Changes to test/fuzz-oss1.test.

325
326
327
328
329
330
331


332
333
334
335
336
337
338
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340







+
+







}

# Taken from the gnome-shell project
#
db close
forcedelete test.db
sqlite3 db test.db
sqlite3_db_config db SQLITE_DBCONFIG_DQS_DDL 1
sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1
do_test fuzz-oss1-gnomeshell {
  db eval {
CREATE TABLE Resource (ID INTEGER NOT NULL PRIMARY KEY, Uri TEXT NOT
NULL, UNIQUE (Uri));
CREATE VIRTUAL TABLE fts USING fts4;
CREATE TABLE "mfo:Action" (ID INTEGER NOT NULL PRIMARY KEY);
CREATE TABLE "mfo:Enclosure" (ID INTEGER NOT NULL PRIMARY KEY,

Changes to test/fuzz.test.

368
369
370
371
372
373
374
375

376
377
378
379
368
369
370
371
372
373
374

375
376
377
378
379







-
+




integrity_check fuzz-7.3.integrity
do_test         fuzz-7.4 {execsql COMMIT} {}
integrity_check fuzz-7.5.integrity

#----------------------------------------------------------------
# Many CREATE and DROP TABLE statements:
#
set E [list table duplicate {no such col} {ambiguous column name} {use DROP}]
set E [list table view duplicate {no such col} {ambiguous column name} {use DROP}]
do_fuzzy_test fuzz-8.1 -template {[CreateOrDropTableOrView]} -errorlist $E

close $::log
finish_test

Changes to test/fuzz_common.tcl.

359
360
361
362
363
364
365

366
367
368
369
370
371
372
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373







+







  set ::fuzzyopts(-repeats) $::REPEATS
  array set ::fuzzyopts $args

  lappend ::fuzzyopts(-errorlist) {parser stack overflow} 
  lappend ::fuzzyopts(-errorlist) {ORDER BY}
  lappend ::fuzzyopts(-errorlist) {GROUP BY}
  lappend ::fuzzyopts(-errorlist) {datatype mismatch}
  lappend ::fuzzyopts(-errorlist) {non-deterministic functions prohibited}

  for {set ii 0} {$ii < $::fuzzyopts(-repeats)} {incr ii} {
    do_test ${testname}.$ii {
      set ::sql [subst $::fuzzyopts(-template)]
      puts $::log $::sql
      flush $::log
      set rc [catch {execsql $::sql} msg]

Changes to test/fuzzcheck.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22
1
2
3
4
5
6
7
8
9
10
11
12
13

14

15
16
17
18
19
20
21













-
+
-







/*
** 2015-05-25
**
** 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 is a utility program designed to aid running regressions tests on
** the SQLite library using data from an external fuzzer, such as American
** the SQLite library using data from external fuzzers.
** Fuzzy Lop (AFL) (http://lcamtuf.coredump.cx/afl/).
**
** This program reads content from an SQLite database file with the following
** schema:
**
**     CREATE TABLE db(
**       dbid INTEGER PRIMARY KEY, -- database id
**       dbcontent BLOB            -- database disk file image
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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






+

+









-
-
-
-
+
+
+
-











-
-
-
-
+
+
+
+







** tables.  Then do "./fuzzcheck new.db" to run the tests.
**
** DEBUGGING HINTS:
**
** If fuzzcheck does crash, it can be run in the debugger and the content
** of the global variable g.zTextName[] will identify the specific XSQL and
** DB values that were running when the crash occurred.
**
** DBSQLFUZZ: (Added 2020-02-25)
**
** The dbsqlfuzz fuzzer includes both a database file and SQL to run against
** that database in its input.  This utility can now process dbsqlfuzz
** input files.  Load such files using the "--load-dbsql FILE ..." command-line
** option.
**
** Dbsqlfuzz inputs are ordinary text.  The first part of the file is text
** that describes the content of the database (using a lot of hexadecimal),
** then there is a divider line followed by the SQL to run against the
** database.  Because they are ordinary text, dbsqlfuzz inputs are stored
** in the XSQL table, as if they were ordinary SQL inputs.  The isDbSql()
** function can look at a text string and determine whether or not it is
** a valid dbsqlfuzz input.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#include <assert.h>
#include "sqlite3.h"
#include "sqlite3recover.h"
#define ISSPACE(X) isspace((unsigned char)(X))
#define ISDIGIT(X) isdigit((unsigned char)(X))


#ifdef __unix__
# include <signal.h>
# include <unistd.h>
#endif

#ifdef SQLITE_OSS_FUZZ
# include <stddef.h>
# if !defined(_MSC_VER)
#  include <stdint.h>
#include <stddef.h>
#if !defined(_MSC_VER)
# include <stdint.h>
# endif
#endif

#if defined(_MSC_VER)
typedef unsigned char uint8_t;
#endif

/*
** Files in the virtual file system.
*/
typedef struct VFile VFile;
struct VFile {
  char *zFilename;        /* Filename.  NULL for delete-on-close. From malloc() */
  int sz;                 /* Size of the file in bytes */
  int nRef;               /* Number of references to this file */
  unsigned char *a;       /* Content of the file.  From malloc() */
  char *zFilename;      /* Filename.  NULL for delete-on-close. From malloc() */
  int sz;               /* Size of the file in bytes */
  int nRef;             /* Number of references to this file */
  unsigned char *a;     /* Content of the file.  From malloc() */
};
typedef struct VHandle VHandle;
struct VHandle {
  sqlite3_file base;      /* Base class.  Must be first */
  VFile *pVFile;          /* The underlying file */
};

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
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







+






+


+
+
+
+
+
+






+
+
-
+
-
-
-
+
-








-
+


-
-
-
+
+
+
+
+
+
+
+
+
+
+
+







#define MX_FILE_SZ 10000000

/*
** All global variables are gathered into the "g" singleton.
*/
static struct GlobalVars {
  const char *zArgv0;              /* Name of program */
  const char *zDbFile;             /* Name of database file */
  VFile aFile[MX_FILE];            /* The virtual filesystem */
  int nDb;                         /* Number of template databases */
  Blob *pFirstDb;                  /* Content of first template database */
  int nSql;                        /* Number of SQL scripts */
  Blob *pFirstSql;                 /* First SQL script */
  unsigned int uRandom;            /* Seed for the SQLite PRNG */
  unsigned int nInvariant;         /* Number of invariant checks run */
  char zTestName[100];             /* Name of current test */
} g;

/*
** Include the external vt02.c module.
*/
extern int sqlite3_vt02_init(sqlite3*,char***,void*);


/*
** Print an error message and quit.
*/
static void fatalError(const char *zFormat, ...){
  va_list ap;
  fprintf(stderr, "%s", g.zArgv0);
  if( g.zDbFile ) fprintf(stderr, " %s", g.zDbFile);
  if( g.zTestName[0] ){
  if( g.zTestName[0] ) fprintf(stderr, " (%s)", g.zTestName);
    fprintf(stderr, "%s (%s): ", g.zArgv0, g.zTestName);
  }else{
    fprintf(stderr, "%s: ", g.zArgv0);
  fprintf(stderr, ": ");
  }
  va_start(ap, zFormat);
  vfprintf(stderr, zFormat, ap);
  va_end(ap);
  fprintf(stderr, "\n");
  exit(1);
}

/*
** Timeout handler
** signal handler
*/
#ifdef __unix__
static void timeoutHandler(int NotUsed){
  (void)NotUsed;
  fatalError("timeout\n");
static void signalHandler(int signum){
  const char *zSig;
  if( signum==SIGABRT ){
    zSig = "abort";
  }else if( signum==SIGALRM ){
    zSig = "timeout";
  }else if( signum==SIGSEGV ){
    zSig = "segfault";
  }else{
    zSig = "signal";
  }
  fatalError(zSig);
}
#endif

/*
** Set the an alarm to go off after N seconds.  Disable the alarm
** if N==0
*/
193
194
195
196
197
198
199
200

201
202
203
204
205
206
207
223
224
225
226
227
228
229

230
231
232
233
234
235
236
237







-
+







static int progressHandler(void *pVdbeLimitFlag){
  if( *(int*)pVdbeLimitFlag ) fatalError("too many VDBE cycles");
  return 1;
}
#endif

/*
** Reallocate memory.  Show and error and quit if unable.
** Reallocate memory.  Show an error and quit if unable.
*/
static void *safe_realloc(void *pOld, int szNew){
  void *pNew = realloc(pOld, szNew<=0 ? 1 : szNew);
  if( pNew==0 ) fatalError("unable to realloc for %d bytes", szNew);
  return pNew;
}

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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+











+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+








-
+

+
-
+







  pNew->nRef = 0;
  pNew->sz = sz;
  pNew->a = safe_realloc(0, sz);
  if( sz>0 ) memcpy(pNew->a, pData, sz);
  return pNew;
}

/* Return true if the line is all zeros */
static int allZero(unsigned char *aLine){
  int i;
  for(i=0; i<16 && aLine[i]==0; i++){}
  return i==16;
}

/*
** Render a database and query as text that can be input into
** the CLI.
*/
static void renderDbSqlForCLI(
  FILE *out,             /* Write to this file */
  const char *zFile,     /* Name of the database file */
  unsigned char *aDb,    /* Database content */
  int nDb,               /* Number of bytes in aDb[] */
  unsigned char *zSql,   /* SQL content */
  int nSql               /* Bytes of SQL */
){
  fprintf(out, ".print ******* %s *******\n", zFile);
  if( nDb>100 ){
    int i, j;                   /* Loop counters */
    int pgsz;                   /* Size of each page */
    int lastPage = 0;           /* Last page number shown */
    int iPage;                  /* Current page number */
    unsigned char *aLine;       /* Single line to display */
    unsigned char buf[16];      /* Fake line */
    unsigned char bShow[256];   /* Characters ok to display */

    memset(bShow, '.', sizeof(bShow));
    for(i=' '; i<='~'; i++){
      if( i!='{' && i!='}' && i!='"' && i!='\\' ) bShow[i] = i;
    }
    pgsz = (aDb[16]<<8) | aDb[17];
    if( pgsz==0 ) pgsz = 65536;
    if( pgsz<512 || (pgsz&(pgsz-1))!=0 ) pgsz = 4096;
    fprintf(out,".open --hexdb\n");
    fprintf(out,"| size %d pagesize %d filename %s\n",nDb,pgsz,zFile);
    for(i=0; i<nDb; i += 16){
      if( i+16>nDb ){
        memset(buf, 0, sizeof(buf));
        memcpy(buf, aDb+i, nDb-i);
        aLine = buf;
      }else{
        aLine = aDb + i;
      }
      if( allZero(aLine) ) continue;
      iPage = i/pgsz + 1;
      if( lastPage!=iPage ){
        fprintf(out,"| page %d offset %d\n", iPage, (iPage-1)*pgsz);
        lastPage = iPage;
      }
      fprintf(out,"|  %5d:", i-(iPage-1)*pgsz);
      for(j=0; j<16; j++) fprintf(out," %02x", aLine[j]);
      fprintf(out,"   ");
      for(j=0; j<16; j++){
        unsigned char c = (unsigned char)aLine[j];
        fputc( bShow[c], stdout);
      }
      fputc('\n', stdout);
    }
    fprintf(out,"| end %s\n", zFile);
  }else{
    fprintf(out,".open :memory:\n");
  }
  fprintf(out,".testctrl prng_seed 1 db\n");
  fprintf(out,".testctrl internal_functions\n");
  fprintf(out,"%.*s", nSql, zSql);
  if( nSql>0 && zSql[nSql-1]!='\n' ) fprintf(out, "\n");
}

/*
** Read the complete content of a file into memory.  Add a 0x00 terminator
** and return a pointer to the result.
**
** The file content is held in memory obtained from sqlite_malloc64() which
** should be freed by the caller.
*/
static char *readFile(const char *zFilename, long *sz){
  FILE *in;
  long nIn;
  unsigned char *pBuf;

  *sz = 0;
  if( zFilename==0 ) return 0;
  in = fopen(zFilename, "rb");
  if( in==0 ) return 0;
  fseek(in, 0, SEEK_END);
  *sz = nIn = ftell(in);
  rewind(in);
  pBuf = sqlite3_malloc64( nIn+1 );
  if( pBuf && 1==fread(pBuf, nIn, 1, in) ){
    pBuf[nIn] = 0;
    fclose(in);
    return (char*)pBuf;
  }  
  sqlite3_free(pBuf);
  *sz = 0;
  fclose(in);
  return 0;
}


/*
** Implementation of the "readfile(X)" SQL function.  The entire content
** of the file named X is read and returned as a BLOB.  NULL is returned
** if the file does not exist or is unreadable.
*/
static void readfileFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  long nIn;
  void *pBuf;
  const char *zName = (const char*)sqlite3_value_text(argv[0]);

  if( zName==0 ) return;
  pBuf = readFile(zName, &nIn);
  if( pBuf ){
    sqlite3_result_blob(context, pBuf, nIn, sqlite3_free);
  }
}

/*
** Implementation of the "readtextfile(X)" SQL function.  The text content
** of the file named X through the end of the file or to the first \000
** character, whichever comes first, is read and returned as TEXT.  NULL
** is returned if the file does not exist or is unreadable.
*/
static void readtextfileFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const char *zName;
  FILE *in;
  long nIn;
  void *pBuf;
  char *pBuf;

  zName = (const char*)sqlite3_value_text(argv[0]);
  if( zName==0 ) return;
  in = fopen(zName, "rb");
  if( in==0 ) return;
  fseek(in, 0, SEEK_END);
  nIn = ftell(in);
  rewind(in);
  pBuf = sqlite3_malloc64( nIn );
  pBuf = sqlite3_malloc64( nIn+1 );
  if( pBuf && 1==fread(pBuf, nIn, 1, in) ){
    pBuf[nIn] = 0;
    sqlite3_result_blob(context, pBuf, nIn, sqlite3_free);
    sqlite3_result_text(context, pBuf, -1, sqlite3_free);
  }else{
    sqlite3_free(pBuf);
  }
  fclose(in);
}

/*
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
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343







-
-
+
+
+
+
+
+
















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  while( p ){
    pNext = p->pNext;
    free(p);
    p = pNext;
  }
}


/* Return the current wall-clock time */
/* Return the current wall-clock time
**
** The number of milliseconds since the julian epoch.
** 1907-01-01 00:00:00  ->  210866716800000
** 2021-01-01 00:00:00  ->  212476176000000
*/
static sqlite3_int64 timeOfDay(void){
  static sqlite3_vfs *clockVfs = 0;
  sqlite3_int64 t;
  if( clockVfs==0 ){
    clockVfs = sqlite3_vfs_find(0);
    if( clockVfs==0 ) return 0;
  }
  if( clockVfs->iVersion>=1 && clockVfs->xCurrentTimeInt64!=0 ){
    clockVfs->xCurrentTimeInt64(clockVfs, &t);
  }else{
    double r;
    clockVfs->xCurrentTime(clockVfs, &r);
    t = (sqlite3_int64)(r*86400000.0);
  }
  return t;
}

/***************************************************************************
** Code to process combined database+SQL scripts generated by the
** dbsqlfuzz fuzzer.
*/

/* An instance of the following object is passed by pointer as the
** client data to various callbacks.
*/
typedef struct FuzzCtx {
  sqlite3 *db;               /* The database connection */
  sqlite3_int64 iCutoffTime; /* Stop processing at this time. */
  sqlite3_int64 iLastCb;     /* Time recorded for previous progress callback */
  sqlite3_int64 mxInterval;  /* Longest interval between two progress calls */
  unsigned nCb;              /* Number of progress callbacks */
  unsigned mxCb;             /* Maximum number of progress callbacks allowed */
  unsigned execCnt;          /* Number of calls to the sqlite3_exec callback */
  int timeoutHit;            /* True when reaching a timeout */
} FuzzCtx;

/* Verbosity level for the dbsqlfuzz test runner */
static int eVerbosity = 0;

/* True to activate PRAGMA vdbe_debug=on */
static int bVdbeDebug = 0;

/* Timeout for each fuzzing attempt, in milliseconds */
static int giTimeout = 10000;   /* Defaults to 10 seconds */

/* Maximum number of progress handler callbacks */
static unsigned int mxProgressCb = 2000;

/* Maximum string length in SQLite */
static int lengthLimit = 1000000;

/* Maximum expression depth */
static int depthLimit = 500;

/* Limit on the amount of heap memory that can be used */
static sqlite3_int64 heapLimit = 100000000;

/* Maximum byte-code program length in SQLite */
static int vdbeOpLimit = 25000;

/* Maximum size of the in-memory database */
static sqlite3_int64 maxDbSize = 104857600;
/* OOM simulation parameters */
static unsigned int oomCounter = 0;    /* Simulate OOM when equals 1 */
static unsigned int oomRepeat = 0;     /* Number of OOMs in a row */
static void*(*defaultMalloc)(int) = 0; /* The low-level malloc routine */

/* Enable recovery */
static int bNoRecover = 0;

/* This routine is called when a simulated OOM occurs.  It is broken
** out as a separate routine to make it easy to set a breakpoint on
** the OOM
*/
void oomFault(void){
  if( eVerbosity ){
    printf("Simulated OOM fault\n");
  }
  if( oomRepeat>0 ){
    oomRepeat--;
  }else{
    oomCounter--;
  }
}

/* This routine is a replacement malloc() that is used to simulate
** Out-Of-Memory (OOM) errors for testing purposes.
*/
static void *oomMalloc(int nByte){
  if( oomCounter ){
    if( oomCounter==1 ){
      oomFault();
      return 0;
    }else{
      oomCounter--;
    }
  }
  return defaultMalloc(nByte);
}

/* Register the OOM simulator.  This must occur before any memory
** allocations */
static void registerOomSimulator(void){
  sqlite3_mem_methods mem;
  sqlite3_shutdown();
  sqlite3_config(SQLITE_CONFIG_GETMALLOC, &mem);
  defaultMalloc = mem.xMalloc;
  mem.xMalloc = oomMalloc;
  sqlite3_config(SQLITE_CONFIG_MALLOC, &mem);
}

/* Turn off any pending OOM simulation */
static void disableOom(void){
  oomCounter = 0;
  oomRepeat = 0;
}

/*
** Translate a single byte of Hex into an integer.
** This routine only works if h really is a valid hexadecimal
** character:  0..9a..fA..F
*/
static unsigned char hexToInt(unsigned int h){
#ifdef SQLITE_EBCDIC
  h += 9*(1&~(h>>4));   /* EBCDIC */
#else
  h += 9*(1&(h>>6));    /* ASCII */
#endif
  return h & 0xf;
}

/*
** The first character of buffer zIn[0..nIn-1] is a '['.  This routine
** checked to see if the buffer holds "[NNNN]" or "[+NNNN]" and if it
** does it makes corresponding changes to the *pK value and *pI value
** and returns true.  If the input buffer does not match the patterns,
** no changes are made to either *pK or *pI and this routine returns false.
*/
static int isOffset(
  const unsigned char *zIn,  /* Text input */
  int nIn,                   /* Bytes of input */
  unsigned int *pK,          /* half-byte cursor to adjust */
  unsigned int *pI           /* Input index to adjust */
){
  int i;
  unsigned int k = 0;
  unsigned char c;
  for(i=1; i<nIn && (c = zIn[i])!=']'; i++){
    if( !isxdigit(c) ) return 0;
    k = k*16 + hexToInt(c);
  }
  if( i==nIn ) return 0;
  *pK = 2*k;
  *pI += i;
  return 1;
}

/*
** Decode the text starting at zIn into a binary database file.
** The maximum length of zIn is nIn bytes.  Store the binary database
** file in space obtained from sqlite3_malloc().
**
** Return the number of bytes of zIn consumed.  Or return -1 if there
** is an error.  One potential error is that the recipe specifies a
** database file larger than MX_FILE_SZ bytes.
**
** Abort on an OOM.
*/
static int decodeDatabase(
  const unsigned char *zIn,      /* Input text to be decoded */
  int nIn,                       /* Bytes of input text */
  unsigned char **paDecode,      /* OUT: decoded database file */
  int *pnDecode                  /* OUT: Size of decoded database */
){
  unsigned char *a, *aNew;       /* Database under construction */
  int mx = 0;                    /* Current size of the database */
  sqlite3_uint64 nAlloc = 4096;  /* Space allocated in a[] */
  unsigned int i;                /* Next byte of zIn[] to read */
  unsigned int j;                /* Temporary integer */
  unsigned int k;                /* half-byte cursor index for output */
  unsigned int n;                /* Number of bytes of input */
  unsigned char b = 0;
  if( nIn<4 ) return -1;
  n = (unsigned int)nIn;
  a = sqlite3_malloc64( nAlloc );
  if( a==0 ){
    fprintf(stderr, "Out of memory!\n");
    exit(1);
  }
  memset(a, 0, (size_t)nAlloc);
  for(i=k=0; i<n; i++){
    unsigned char c = (unsigned char)zIn[i];
    if( isxdigit(c) ){
      k++;
      if( k & 1 ){
        b = hexToInt(c)*16;
      }else{
        b += hexToInt(c);
        j = k/2 - 1;
        if( j>=nAlloc ){
          sqlite3_uint64 newSize;
          if( nAlloc==MX_FILE_SZ || j>=MX_FILE_SZ ){
            if( eVerbosity ){
              fprintf(stderr, "Input database too big: max %d bytes\n",
                      MX_FILE_SZ);
            }
            sqlite3_free(a);
            return -1;
          }
          newSize = nAlloc*2;
          if( newSize<=j ){
            newSize = (j+4096)&~4095;
          }
          if( newSize>MX_FILE_SZ ){
            if( j>=MX_FILE_SZ ){
              sqlite3_free(a);
              return -1;
            }
            newSize = MX_FILE_SZ;
          }
          aNew = sqlite3_realloc64( a, newSize );
          if( aNew==0 ){
            sqlite3_free(a);
            return -1;
          }
          a = aNew;
          assert( newSize > nAlloc );
          memset(a+nAlloc, 0, (size_t)(newSize - nAlloc));
          nAlloc = newSize;
        }
        if( j>=(unsigned)mx ){
          mx = (j + 4095)&~4095;
          if( mx>MX_FILE_SZ ) mx = MX_FILE_SZ;
        }
        assert( j<nAlloc );
        a[j] = b;
      }
    }else if( zIn[i]=='[' && i<n-3 && isOffset(zIn+i, nIn-i, &k, &i) ){
      continue;
   }else if( zIn[i]=='\n' && i<n-4 && memcmp(zIn+i,"\n--\n",4)==0 ){
      i += 4;
      break;
    }
  }
  *pnDecode = mx;
  *paDecode = a;
  return i;
}

/*
** Progress handler callback.
**
** The argument is the cutoff-time after which all processing should
** stop.  So return non-zero if the cut-off time is exceeded.
*/
static int progress_handler(void *pClientData) {
  FuzzCtx *p = (FuzzCtx*)pClientData;
  sqlite3_int64 iNow = timeOfDay();
  int rc = iNow>=p->iCutoffTime;
  sqlite3_int64 iDiff = iNow - p->iLastCb;
  /* printf("time-remaining: %lld\n", p->iCutoffTime - iNow); */
  if( iDiff > p->mxInterval ) p->mxInterval = iDiff;
  p->nCb++;
  if( rc==0 && p->mxCb>0 && p->mxCb<=p->nCb ) rc = 1;
  if( rc && !p->timeoutHit && eVerbosity>=2 ){
    printf("Timeout on progress callback %d\n", p->nCb);
    fflush(stdout);
    p->timeoutHit = 1;
  }
  return rc;
}

/*
** Flag bits set by block_troublesome_sql()
*/
#define BTS_SELECT      0x000001
#define BTS_NONSELECT   0x000002
#define BTS_BADFUNC     0x000004
#define BTS_BADPRAGMA   0x000008  /* Sticky for rest of the script */

/*
** Disallow debugging pragmas such as "PRAGMA vdbe_debug" and
** "PRAGMA parser_trace" since they can dramatically increase the
** amount of output without actually testing anything useful.
**
** Also block ATTACH if attaching a file from the filesystem.
*/
static int block_troublesome_sql(
  void *pClientData,
  int eCode,
  const char *zArg1,
  const char *zArg2,
  const char *zArg3,
  const char *zArg4
){
  unsigned int *pBtsFlags = (unsigned int*)pClientData;

  (void)zArg3;
  (void)zArg4;
  switch( eCode ){
    case SQLITE_PRAGMA: {
      if( sqlite3_stricmp("busy_timeout",zArg1)==0
       && (zArg2==0 || strtoll(zArg2,0,0)>100 || strtoll(zArg2,0,10)>100)
      ){
        return SQLITE_DENY;
      }else if( sqlite3_stricmp("hard_heap_limit", zArg1)==0
              || sqlite3_stricmp("reverse_unordered_selects", zArg1)==0
      ){
        /* BTS_BADPRAGMA is sticky.  A hard_heap_limit or
        ** revert_unordered_selects should inhibit all future attempts
        ** at verifying query invariants */
        *pBtsFlags |= BTS_BADPRAGMA;
      }else if( eVerbosity==0 ){
        if( sqlite3_strnicmp("vdbe_", zArg1, 5)==0
         || sqlite3_stricmp("parser_trace", zArg1)==0
         || sqlite3_stricmp("temp_store_directory", zArg1)==0
        ){
         return SQLITE_DENY;
        }
      }else if( sqlite3_stricmp("oom",zArg1)==0
              && zArg2!=0 && zArg2[0]!=0 ){
        oomCounter = atoi(zArg2);
      }
      *pBtsFlags |= BTS_NONSELECT;
      break;
    }
    case SQLITE_ATTACH: {
      /* Deny the ATTACH if it is attaching anything other than an in-memory
      ** database. */
      *pBtsFlags |= BTS_NONSELECT;
      if( zArg1==0 ) return SQLITE_DENY;
      if( strcmp(zArg1,":memory:")==0 ) return SQLITE_OK;
      if( sqlite3_strglob("file:*[?]vfs=memdb", zArg1)==0
       && sqlite3_strglob("file:*[^/a-zA-Z0-9_.]*[?]vfs=memdb", zArg1)!=0
      ){
        return SQLITE_OK;
      }
      return SQLITE_DENY;
    }
    case SQLITE_SELECT: {
      *pBtsFlags |= BTS_SELECT;
      break;
    }
    case SQLITE_FUNCTION: {
      static const char *azBadFuncs[] = {
        "avg",
        "count",
        "cume_dist",
        "current_date",
        "current_time",
        "current_timestamp",
        "date",
        "datetime",
        "decimal_sum",
        "dense_rank",
        "first_value",
        "geopoly_group_bbox",
        "group_concat",
        "implies_nonnull_row",
        "json_group_array",
        "json_group_object",
        "julianday",
        "lag",
        "last_value",
        "lead",
        "max",
        "min",
        "nth_value",
        "ntile",
        "percent_rank",
        "random",
        "randomblob",
        "rank",
        "row_number",
        "sqlite_offset",
        "strftime",
        "sum",
        "time",
        "total",
        "unixepoch",
      };
      int first, last;
      first = 0;
      last = sizeof(azBadFuncs)/sizeof(azBadFuncs[0]) - 1;
      do{
        int mid = (first+last)/2;
        int c = sqlite3_stricmp(azBadFuncs[mid], zArg2);
        if( c<0 ){
          first = mid+1;
        }else if( c>0 ){
          last = mid-1;
        }else{
          *pBtsFlags |= BTS_BADFUNC;
          break;
        }
      }while( first<=last );
      break;
    }
    case SQLITE_READ: {
      /* Benign */
      break;
    }
    default: {
      *pBtsFlags |= BTS_NONSELECT;
    }
  }
  return SQLITE_OK;
}

/* Implementation found in fuzzinvariant.c */
extern int fuzz_invariant(
  sqlite3 *db,            /* The database connection */
  sqlite3_stmt *pStmt,    /* Test statement stopped on an SQLITE_ROW */
  int iCnt,               /* Invariant sequence number, starting at 0 */
  int iRow,               /* The row number for pStmt */
  int nRow,               /* Total number of output rows */
  int *pbCorrupt,         /* IN/OUT: Flag indicating a corrupt database file */
  int eVerbosity          /* How much debugging output */
);

/* Implementation of sqlite_dbdata and sqlite_dbptr */
extern int sqlite3_dbdata_init(sqlite3*,const char**,void*);


/*
** This function is used as a callback by the recover extension. Simply
** print the supplied SQL statement to stdout.
*/
static int recoverSqlCb(void *pCtx, const char *zSql){
  if( eVerbosity>=2 ){
    printf("%s\n", zSql);
  }
  return SQLITE_OK;
}

/*
** This function is called to recover data from the database.
*/
static int recoverDatabase(sqlite3 *db){
  int rc;                                 /* Return code from this routine */
  const char *zLAF = "lost_and_found";    /* Name of "lost_and_found" table */
  int bFreelist = 1;                      /* True to scan the freelist */
  int bRowids = 1;                        /* True to restore ROWID values */
  sqlite3_recover *p;                     /* The recovery object */

  p = sqlite3_recover_init_sql(db, "main", recoverSqlCb, 0);
  sqlite3_recover_config(p, SQLITE_RECOVER_LOST_AND_FOUND, (void*)zLAF);
  sqlite3_recover_config(p, SQLITE_RECOVER_ROWIDS, (void*)&bRowids);
  sqlite3_recover_config(p, SQLITE_RECOVER_FREELIST_CORRUPT,(void*)&bFreelist);
  sqlite3_recover_run(p);
  if( sqlite3_recover_errcode(p)!=SQLITE_OK ){
    const char *zErr = sqlite3_recover_errmsg(p);
    int errCode = sqlite3_recover_errcode(p);
    if( eVerbosity>0 ){
      printf("recovery error: %s (%d)\n", zErr, errCode);
    }
  }
  rc = sqlite3_recover_finish(p);
  if( eVerbosity>0 && rc ){
     printf("recovery returns error code %d\n", rc);
  }
  return rc;
}

/*
** Run the SQL text
*/
static int runDbSql(sqlite3 *db, const char *zSql, unsigned int *pBtsFlags){
  int rc;
  sqlite3_stmt *pStmt;
  int bCorrupt = 0;
  while( isspace(zSql[0]&0x7f) ) zSql++;
  if( zSql[0]==0 ) return SQLITE_OK;
  if( eVerbosity>=4 ){
    printf("RUNNING-SQL: [%s]\n", zSql);
    fflush(stdout);
  }
  (*pBtsFlags) &= ~BTS_BADPRAGMA;
  rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
  if( rc==SQLITE_OK ){
    int nRow = 0;
    while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
      nRow++;
      if( eVerbosity>=4 ){
        int j;
        for(j=0; j<sqlite3_column_count(pStmt); j++){
          if( j ) printf(",");
          switch( sqlite3_column_type(pStmt, j) ){
            case SQLITE_NULL: {
              printf("NULL");
              break;
            }
            case SQLITE_INTEGER:
            case SQLITE_FLOAT: {
              printf("%s", sqlite3_column_text(pStmt, j));
              break;
            }
            case SQLITE_BLOB: {
              int n = sqlite3_column_bytes(pStmt, j);
              int i;
              const unsigned char *a;
              a = (const unsigned char*)sqlite3_column_blob(pStmt, j);
              printf("x'");
              for(i=0; i<n; i++){
                printf("%02x", a[i]);
              }
              printf("'");
              break;
            }
            case SQLITE_TEXT: {
              int n = sqlite3_column_bytes(pStmt, j);
              int i;
              const unsigned char *a;
              a = (const unsigned char*)sqlite3_column_blob(pStmt, j);
              printf("'");
              for(i=0; i<n; i++){
                if( a[i]=='\'' ){
                  printf("''");
                }else{
                  putchar(a[i]);
                }
              }
              printf("'");
              break;
            }
          } /* End switch() */
        } /* End for() */
        printf("\n");
        fflush(stdout);
      } /* End if( eVerbosity>=5 ) */
    } /* End while( SQLITE_ROW */
    if( rc==SQLITE_DONE ){
      if( (*pBtsFlags)==BTS_SELECT
       && !sqlite3_stmt_isexplain(pStmt)
       && nRow>0
      ){
        int iRow = 0;
        sqlite3_reset(pStmt);
        while( sqlite3_step(pStmt)==SQLITE_ROW ){
          int iCnt = 0;
          iRow++;
          for(iCnt=0; iCnt<99999; iCnt++){
            rc = fuzz_invariant(db, pStmt, iCnt, iRow, nRow,
                                &bCorrupt, eVerbosity);
            if( rc==SQLITE_DONE ) break;
            if( rc!=SQLITE_ERROR ) g.nInvariant++;
            if( eVerbosity>0 ){
              if( rc==SQLITE_OK ){
                printf("invariant-check: ok\n");
              }else if( rc==SQLITE_CORRUPT ){
                printf("invariant-check: failed due to database corruption\n");
              }
            }
          }
        }          
      }
    }else if( eVerbosity>=4 ){
      printf("SQL-ERROR: (%d) %s\n", rc, sqlite3_errmsg(db));
      fflush(stdout);
    }
  }else if( eVerbosity>=4 ){
    printf("SQL-ERROR (%d): %s\n", rc, sqlite3_errmsg(db));
    fflush(stdout);    
  } /* End if( SQLITE_OK ) */
  return sqlite3_finalize(pStmt);
}

/* Invoke this routine to run a single test case */
int runCombinedDbSqlInput(
  const uint8_t *aData,      /* Combined DB+SQL content */
  size_t nByte,              /* Size of aData in bytes */
  int iTimeout,              /* Use this timeout */
  int bScript,               /* If true, just render CLI output */
  int iSqlId                 /* SQL identifier */
){
  int rc;                    /* SQLite API return value */
  int iSql;                  /* Index in aData[] of start of SQL */
  unsigned char *aDb = 0;    /* Decoded database content */
  int nDb = 0;               /* Size of the decoded database */
  int i;                     /* Loop counter */
  int j;                     /* Start of current SQL statement */
  char *zSql = 0;            /* SQL text to run */
  int nSql;                  /* Bytes of SQL text */
  FuzzCtx cx;                /* Fuzzing context */
  unsigned int btsFlags = 0; /* Parsing flags */

  if( nByte<10 ) return 0;
  if( sqlite3_initialize() ) return 0;
  if( sqlite3_memory_used()!=0 ){
    int nAlloc = 0;
    int nNotUsed = 0;
    sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &nAlloc, &nNotUsed, 0);
    fprintf(stderr,"memory leak prior to test start:"
                   " %lld bytes in %d allocations\n",
            sqlite3_memory_used(), nAlloc);
    exit(1);
  }
  memset(&cx, 0, sizeof(cx));
  iSql = decodeDatabase((unsigned char*)aData, (int)nByte, &aDb, &nDb);
  if( iSql<0 ) return 0;
  nSql = (int)(nByte - iSql);
  if( bScript ){
    char zName[100];
    sqlite3_snprintf(sizeof(zName),zName,"dbsql%06d.db",iSqlId);
    renderDbSqlForCLI(stdout, zName, aDb, nDb,
                      (unsigned char*)(aData+iSql), nSql);
    sqlite3_free(aDb);
    return 0;
  }
  if( eVerbosity>=3 ){
    printf(
      "****** %d-byte input, %d-byte database, %d-byte script "
      "******\n", (int)nByte, nDb, nSql);
    fflush(stdout);
  }
  rc = sqlite3_open(0, &cx.db);
  if( rc ){
    sqlite3_free(aDb);
    return 1;
  }
  if( bVdbeDebug ){
    sqlite3_exec(cx.db, "PRAGMA vdbe_debug=ON", 0, 0, 0);
  }

  /* Invoke the progress handler frequently to check to see if we
  ** are taking too long.  The progress handler will return true
  ** (which will block further processing) if more than giTimeout seconds have
  ** elapsed since the start of the test.
  */
  cx.iLastCb = timeOfDay();
  cx.iCutoffTime = cx.iLastCb + (iTimeout<giTimeout ? iTimeout : giTimeout);
  cx.mxCb = mxProgressCb;
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  sqlite3_progress_handler(cx.db, 10, progress_handler, (void*)&cx);
#endif

  /* Set a limit on the maximum size of a prepared statement, and the
  ** maximum length of a string or blob */
  if( vdbeOpLimit>0 ){
    sqlite3_limit(cx.db, SQLITE_LIMIT_VDBE_OP, vdbeOpLimit);
  }
  if( lengthLimit>0 ){
    sqlite3_limit(cx.db, SQLITE_LIMIT_LENGTH, lengthLimit);
  }
  if( depthLimit>0 ){
    sqlite3_limit(cx.db, SQLITE_LIMIT_EXPR_DEPTH, depthLimit);
  }
  sqlite3_limit(cx.db, SQLITE_LIMIT_LIKE_PATTERN_LENGTH, 100);
  sqlite3_hard_heap_limit64(heapLimit);

  if( nDb>=20 && aDb[18]==2 && aDb[19]==2 ){
    aDb[18] = aDb[19] = 1;
  }
  rc = sqlite3_deserialize(cx.db, "main", aDb, nDb, nDb,
          SQLITE_DESERIALIZE_RESIZEABLE |
          SQLITE_DESERIALIZE_FREEONCLOSE);
  if( rc ){
    fprintf(stderr, "sqlite3_deserialize() failed with %d\n", rc);
    goto testrun_finished;
  }
  if( maxDbSize>0 ){
    sqlite3_int64 x = maxDbSize;
    sqlite3_file_control(cx.db, "main", SQLITE_FCNTL_SIZE_LIMIT, &x);
  }

  /* For high debugging levels, turn on debug mode */
  if( eVerbosity>=5 ){
    sqlite3_exec(cx.db, "PRAGMA vdbe_debug=ON;", 0, 0, 0);
  }

  /* 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, &btsFlags);

  /* Add the vt02 virtual table */
  sqlite3_vt02_init(cx.db, 0, 0);

  /* Add support for sqlite_dbdata and sqlite_dbptr virtual tables used
  ** by the recovery API */
  sqlite3_dbdata_init(cx.db, 0, 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

  /* Run recovery on the initial database, just to make sure recovery
  ** works. */
  if( !bNoRecover ){
    recoverDatabase(cx.db);
  }

  zSql = sqlite3_malloc( nSql + 1 );
  if( zSql==0 ){
    fprintf(stderr, "Out of memory!\n");
  }else{
    memcpy(zSql, aData+iSql, nSql);
    zSql[nSql] = 0;
    for(i=j=0; zSql[i]; i++){
      if( zSql[i]==';' ){
        char cSaved = zSql[i+1];
        zSql[i+1] = 0;
        if( sqlite3_complete(zSql+j) ){
          rc = runDbSql(cx.db, zSql+j, &btsFlags);
          j = i+1;
        }
        zSql[i+1] = cSaved;
        if( rc==SQLITE_INTERRUPT || progress_handler(&cx) ){
          goto testrun_finished;
        }
      }
    }
    if( j<i ){
      runDbSql(cx.db, zSql+j, &btsFlags);
    }
  }
testrun_finished:
  sqlite3_free(zSql);
  rc = sqlite3_close(cx.db);
  if( rc!=SQLITE_OK ){
    fprintf(stdout, "sqlite3_close() returns %d\n", rc);
  }
  if( eVerbosity>=2 && !bScript ){
    fprintf(stdout, "Peak memory usages: %f MB\n",
       sqlite3_memory_highwater(1) / 1000000.0);
  }
  if( sqlite3_memory_used()!=0 ){
    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
***************************************************************************/

/* Look at a SQL text and try to determine if it begins with a database
** description, such as would be found in a dbsqlfuzz test case.  Return
** true if this does appear to be a dbsqlfuzz test case and false otherwise.
*/
static int isDbSql(unsigned char *a, int n){
  unsigned char buf[12];
  int i;
  if( n>4 && memcmp(a,"\n--\n",4)==0 ) return 1;
  while( n>0 && isspace(a[0]) ){ a++; n--; }
  for(i=0; n>0 && i<8; n--, a++){
    if( isxdigit(a[0]) ) buf[i++] = a[0];
  }
  if( i==8 && memcmp(buf,"53514c69",8)==0 ) return 1;
  return 0;
}

/* Implementation of the isdbsql(TEXT) SQL function.
*/
static void isDbSqlFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  int n = sqlite3_value_bytes(argv[0]);
  unsigned char *a = (unsigned char*)sqlite3_value_blob(argv[0]);
  sqlite3_result_int(context, a!=0 && n>0 && isDbSql(a,n));
}

/* Methods for the VHandle object
*/
static int inmemClose(sqlite3_file *pFile){
  VHandle *p = (VHandle*)pFile;
  VFile *pVFile = p->pVFile;
  pVFile->nRef--;
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
1629
1630
1631
1632
1633
1634
1635

1636
1637
1638

1639
1640
1641
1642
1643
1644
1645

1646
1647
1648
1649
1650
1651
1652

1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664







-
+

+
-
+






-
+






-
+
+
+
+
+







/*
** Rebuild the database file.
**
**    (1)  Remove duplicate entries
**    (2)  Put all entries in order
**    (3)  Vacuum
*/
static void rebuild_database(sqlite3 *db){
static void rebuild_database(sqlite3 *db, int dbSqlOnly){
  int rc;
  char *zSql;
  rc = sqlite3_exec(db, 
  zSql = sqlite3_mprintf(
     "BEGIN;\n"
     "CREATE TEMP TABLE dbx AS SELECT DISTINCT dbcontent FROM db;\n"
     "DELETE FROM db;\n"
     "INSERT INTO db(dbid, dbcontent) "
        " SELECT NULL, dbcontent FROM dbx ORDER BY 2;\n"
     "DROP TABLE dbx;\n"
     "CREATE TEMP TABLE sx AS SELECT DISTINCT sqltext FROM xsql;\n"
     "CREATE TEMP TABLE sx AS SELECT DISTINCT sqltext FROM xsql %s;\n"
     "DELETE FROM xsql;\n"
     "INSERT INTO xsql(sqlid,sqltext) "
        " SELECT NULL, sqltext FROM sx ORDER BY 2;\n"
     "DROP TABLE sx;\n"
     "COMMIT;\n"
     "PRAGMA page_size=1024;\n"
     "VACUUM;\n", 0, 0, 0);
     "VACUUM;\n",
     dbSqlOnly ? " WHERE isdbsql(sqltext)" : ""
  );
  rc = sqlite3_exec(db, zSql, 0, 0, 0);
  sqlite3_free(zSql);
  if( rc ) fatalError("cannot rebuild: %s", sqlite3_errmsg(db));
}

/*
** Return the value of a hexadecimal digit.  Return -1 if the input
** is not a hex digit.
*/
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
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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
















+
+


-
-
+
+
+
+



+





+
+
+

-
+

+















+






+
+
+











-
-
+
+









+
+
+

+
+



-
+
+
+







      v *= aMult[i].iMult;
      break;
    }
  }
  if( v>0x7fffffff ) fatalError("parameter too large - max 2147483648");
  return (int)(isNeg? -v : v);
}

/*
** Return the number of "v" characters in a string.  Return 0 if there
** are any characters in the string other than "v".
*/
static int numberOfVChar(const char *z){
  int N = 0;
  while( z[0] && z[0]=='v' ){
    z++;
    N++;
  }
  return z[0]==0 ? N : 0;
}

/*
** Print sketchy documentation for this utility program
*/
static void showHelp(void){
  printf("Usage: %s [options] SOURCE-DB ?ARGS...?\n", g.zArgv0);
  printf(
"Read databases and SQL scripts from SOURCE-DB and execute each script against\n"
"each database, checking for crashes and memory leaks.\n"
"Options:\n"
"  --cell-size-check    Set the PRAGMA cell_size_check=ON\n"
"  --dbid N             Use only the database where dbid=N\n"
"  --export-db DIR      Write databases to files(s) in DIR. Works with --dbid\n"
"  --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-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"
"  --no-recover         Do not run recovery on dbsqlfuzz databases\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"
"  --result-trace       Show the results of each SQL command\n"
"  --script             Output CLI script instead of running tests\n"
"  --skip N             Skip the first N test cases\n"
"  --spinner            Use a spinner to show progress\n"
"  --sqlid N            Use only SQL where sqlid=N\n"
"  --timeout N          Abort if any single test needs more than N seconds\n"
"  --timeout N          Maximum time for any one test in N millseconds\n"
"  -v|--verbose         Increased output.  Repeat for more output.\n"
"  --vdbe-debug         Activate VDBE debugging.\n"
  );
}

int main(int argc, char **argv){
  sqlite3_int64 iBegin;        /* Start time of this program */
  int quietFlag = 0;           /* True if --quiet or -q */
  int verboseFlag = 0;         /* True if --verbose or -v */
  char *zInsSql = 0;           /* SQL statement for --load-db or --load-sql */
  int iFirstInsArg = 0;        /* First argv[] for --load-db or --load-sql */
  sqlite3 *db = 0;             /* The open database connection */
  sqlite3_stmt *pStmt;         /* A prepared statement */
  int rc;                      /* Result code from SQLite interface calls */
  Blob *pSql;                  /* For looping over SQL scripts */
  Blob *pDb;                   /* For looping over template databases */
  int i;                       /* Loop index for the argv[] loop */
  int dbSqlOnly = 0;           /* Only use scripts that are dbsqlfuzz */
  int onlySqlid = -1;          /* --sqlid */
  int onlyDbid = -1;           /* --dbid */
  int nativeFlag = 0;          /* --native-vfs */
  int rebuildFlag = 0;         /* --rebuild */
  int vdbeLimitFlag = 0;       /* --limit-vdbe */
  int infoFlag = 0;            /* --info */
  int nSkip = 0;               /* --skip */
  int bScript = 0;             /* --script */
  int bSpinner = 0;            /* True for --spinner */
  int timeoutTest = 0;         /* undocumented --timeout-test flag */
  int runFlags = 0;            /* Flags sent to runSql() */
  char *zMsg = 0;              /* Add this message */
  int nSrcDb = 0;              /* Number of source databases */
  char **azSrcDb = 0;          /* Array of source database names */
  int iSrcDb;                  /* Loop over all source databases */
  int nTest = 0;               /* Total number of tests performed */
  char *zDbName = "";          /* Appreviated name of a source database */
  const char *zFailCode = 0;   /* Value of the TEST_FAILURE env variable */
  int cellSzCkFlag = 0;        /* --cell-size-check */
  int sqlFuzz = 0;             /* True for SQL fuzz. False for DB fuzz */
  int iTimeout = 120;          /* Default 120-second timeout */
  int nMem = 0;                /* Memory limit */
  int iTimeout = 120000;       /* Default 120-second timeout */
  int nMem = 0;                /* Memory limit override */
  int nMemThisDb = 0;          /* Memory limit set by the CONFIG table */
  char *zExpDb = 0;            /* Write Databases to files in this directory */
  char *zExpSql = 0;           /* Write SQL to files in this directory */
  void *pHeap = 0;             /* Heap for use by SQLite */
  int ossFuzz = 0;             /* enable OSS-FUZZ testing */
  int ossFuzzThisDb = 0;       /* ossFuzz value for this particular database */
  int nativeMalloc = 0;        /* Turn off MEMSYS3/5 and lookaside if true */
  sqlite3_vfs *pDfltVfs;       /* The default VFS */
  int openFlags4Data;          /* Flags for sqlite3_open_v2() */
  int bTimer = 0;              /* Show elapse time for each test */
  int nV;                      /* How much to increase verbosity with -vvvv */
  sqlite3_int64 tmStart;       /* Start of each test */

  sqlite3_config(SQLITE_CONFIG_URI,1);
  registerOomSimulator();
  sqlite3_initialize();
  iBegin = timeOfDay();
#ifdef __unix__
  signal(SIGALRM, timeoutHandler);
  signal(SIGALRM, signalHandler);
  signal(SIGSEGV, signalHandler);
  signal(SIGABRT, signalHandler);
#endif
  g.zArgv0 = argv[0];
  openFlags4Data = SQLITE_OPEN_READONLY;
  zFailCode = getenv("TEST_FAILURE");
  pDfltVfs = sqlite3_vfs_find(0);
  inmemVfsRegister(1);
  for(i=1; i<argc; i++){
891
892
893
894
895
896
897
898

899
900
901
902
903
904
905
906
907
908
909
910
911
912
913









914
915
916
917
918
919
920
921
922


923
924
925
926
927
928
929
930
931








932
933
934
935
936
937
938
939
940
941
942



943
944
945
946
947
948
949
950
951
952
953

954
955
956
957
958
959
960













961
962
963
964
965
966
967
968
969
970
971
972
973
974
975



976

977
978

979

























980
981
982
983
984
985
986
1845
1846
1847
1848
1849
1850
1851

1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862





1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873

1874
1875
1876
1877
1878

1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
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
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998







-
+










-
-
-
-
-
+
+
+
+
+
+
+
+
+


-





-
+
+









+
+
+
+
+
+
+
+











+
+
+











+







+
+
+
+
+
+
+
+
+
+
+
+
+















+
+
+
-
+


+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







        if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
        onlyDbid = integerValue(argv[++i]);
      }else
      if( strcmp(z,"export-db")==0 ){
        if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
        zExpDb = argv[++i];
      }else
      if( strcmp(z,"export-sql")==0 ){
      if( strcmp(z,"export-sql")==0 || strcmp(z,"export-dbsql")==0 ){
        if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
        zExpSql = argv[++i];
      }else
      if( strcmp(z,"help")==0 ){
        showHelp();
        return 0;
      }else
      if( strcmp(z,"info")==0 ){
        infoFlag = 1;
      }else
      if( strcmp(z,"limit-mem")==0 ){
#if !defined(SQLITE_ENABLE_MEMSYS3) && !defined(SQLITE_ENABLE_MEMSYS5)
        fatalError("the %s option requires -DSQLITE_ENABLE_MEMSYS5 or _MEMSYS3",
                   argv[i]);
#else
      if( strcmp(z,"limit-depth")==0 ){
        if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
        depthLimit = integerValue(argv[++i]);
      }else
      if( strcmp(z,"limit-heap")==0 ){
        if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
        heapLimit = integerValue(argv[++i]);
      }else
      if( strcmp(z,"limit-mem")==0 ){
        if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
        nMem = integerValue(argv[++i]);
#endif
      }else
      if( strcmp(z,"limit-vdbe")==0 ){
        vdbeLimitFlag = 1;
      }else
      if( strcmp(z,"load-sql")==0 ){
        zInsSql = "INSERT INTO xsql(sqltext)VALUES(CAST(readfile(?1) AS text))";
        zInsSql = "INSERT INTO xsql(sqltext)"
                  "VALUES(CAST(readtextfile(?1) AS text))";
        iFirstInsArg = i+1;
        openFlags4Data = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
        break;
      }else
      if( strcmp(z,"load-db")==0 ){
        zInsSql = "INSERT INTO db(dbcontent) VALUES(readfile(?1))";
        iFirstInsArg = i+1;
        openFlags4Data = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
        break;
      }else
      if( strcmp(z,"load-dbsql")==0 ){
        zInsSql = "INSERT INTO xsql(sqltext)"
                  "VALUES(readfile(?1))";
        iFirstInsArg = i+1;
        openFlags4Data = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
        dbSqlOnly = 1;
        break;
      }else
      if( strcmp(z,"m")==0 ){
        if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
        zMsg = argv[++i];
        openFlags4Data = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
      }else
      if( strcmp(z,"native-malloc")==0 ){
        nativeMalloc = 1;
      }else
      if( strcmp(z,"native-vfs")==0 ){
        nativeFlag = 1;
      }else
      if( strcmp(z,"no-recover")==0 ){
        bNoRecover = 1;
      }else
      if( strcmp(z,"oss-fuzz")==0 ){
        ossFuzz = 1;
      }else
      if( strcmp(z,"prng-seed")==0 ){
        if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
        g.uRandom = atoi(argv[++i]);
      }else
      if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
        quietFlag = 1;
        verboseFlag = 0;
        eVerbosity = 0;
      }else
      if( strcmp(z,"rebuild")==0 ){
        rebuildFlag = 1;
        openFlags4Data = SQLITE_OPEN_READWRITE;
      }else
      if( strcmp(z,"result-trace")==0 ){
        runFlags |= SQL_OUTPUT;
      }else
      if( strcmp(z,"script")==0 ){
        bScript = 1;
      }else
      if( strcmp(z,"skip")==0 ){
        if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
        nSkip = atoi(argv[++i]);
      }else
      if( strcmp(z,"spinner")==0 ){
        bSpinner = 1;
      }else
      if( strcmp(z,"timer")==0 ){
        bTimer = 1;
      }else
      if( strcmp(z,"sqlid")==0 ){
        if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
        onlySqlid = integerValue(argv[++i]);
      }else
      if( strcmp(z,"timeout")==0 ){
        if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
        iTimeout = integerValue(argv[++i]);
      }else
      if( strcmp(z,"timeout-test")==0 ){
        timeoutTest = 1;
#ifndef __unix__
        fatalError("timeout is not available on non-unix systems");
#endif
      }else
      if( strcmp(z,"vdbe-debug")==0 ){
        bVdbeDebug = 1;
      }else
      if( strcmp(z,"verbose")==0 || strcmp(z,"v")==0 ){
      if( strcmp(z,"verbose")==0 ){
        quietFlag = 0;
        verboseFlag++;
        eVerbosity++;
        if( verboseFlag>1 ) runFlags |= SQL_TRACE;
      }else
      if( (nV = numberOfVChar(z))>=1 ){
        quietFlag = 0;
        verboseFlag += nV;
        eVerbosity += nV;
        if( verboseFlag>1 ) runFlags |= SQL_TRACE;
      }else
      if( strcmp(z,"version")==0 ){
        int ii;
        const char *zz;
        printf("SQLite %s %s\n", sqlite3_libversion(), sqlite3_sourceid());
        for(ii=0; (zz = sqlite3_compileoption_get(ii))!=0; ii++){
          printf("%s\n", zz);
        }
        return 0;
      }else
      if( strcmp(z,"is-dbsql")==0 ){
        i++;
        for(i++; i<argc; i++){
          long nData;
          char *aData = readFile(argv[i], &nData);
          printf("%d %s\n", isDbSql((unsigned char*)aData,nData), argv[i]);
          sqlite3_free(aData);
        }
        exit(0);
      }else
      {
        fatalError("unknown option: %s", argv[i]);
      }
    }else{
      nSrcDb++;
      azSrcDb = safe_realloc(azSrcDb, nSrcDb*sizeof(azSrcDb[0]));
995
996
997
998
999
1000
1001



1002
1003



1004



1005
1006



1007
1008
1009
1010
1011
1012
1013
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025


2026
2027
2028
2029
2030
2031
2032
2033
2034
2035







+
+
+


+
+
+

+
+
+
-
-
+
+
+







    if( zInsSql ){
      fatalError("cannot import into more than one database");
    }
  }

  /* Process each source database separately */
  for(iSrcDb=0; iSrcDb<nSrcDb; iSrcDb++){
    char *zRawData = 0;
    long nRawData = 0;
    g.zDbFile = azSrcDb[iSrcDb];
    rc = sqlite3_open_v2(azSrcDb[iSrcDb], &db,
                         openFlags4Data, pDfltVfs->zName);
    if( rc==SQLITE_OK ){
      rc = sqlite3_exec(db, "SELECT count(*) FROM sqlite_schema", 0, 0, 0);
    }
    if( rc ){
      sqlite3_close(db);
      zRawData = readFile(azSrcDb[iSrcDb], &nRawData);
      if( zRawData==0 ){
      fatalError("cannot open source database %s - %s",
      azSrcDb[iSrcDb], sqlite3_errmsg(db));
        fatalError("input file \"%s\" is not recognized\n", azSrcDb[iSrcDb]);
      }
      sqlite3_open(":memory:", &db);
    }

    /* Print the description, if there is one */
    if( infoFlag ){
      int n;
      zDbName = azSrcDb[iSrcDb];
      i = (int)strlen(zDbName) - 1;
1034
1035
1036
1037
1038
1039
1040

1041
1042
1043
1044
1045
1046
1047
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070







+







       && (n = sqlite3_column_int(pStmt,0))>0
      ){
        printf(" - %d scripts", n);
      }
      sqlite3_finalize(pStmt);
      printf("\n");
      sqlite3_close(db);
      sqlite3_free(zRawData);
      continue;
    }

    rc = sqlite3_exec(db,
       "CREATE TABLE IF NOT EXISTS db(\n"
       "  dbid INTEGER PRIMARY KEY, -- database id\n"
       "  dbcontent BLOB            -- database disk file image\n"
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
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

2164
2165
2166
2167
2168
2169
2170
2171







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

















-
+
-
-
-
-


-








+
+
+
+






+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+





-
+







    if( zMsg ){
      char *zSql;
      zSql = sqlite3_mprintf(
               "DELETE FROM readme; INSERT INTO readme(msg) VALUES(%Q)", zMsg);
      rc = sqlite3_exec(db, zSql, 0, 0, 0);
      sqlite3_free(zSql);
      if( rc ) fatalError("cannot change description: %s", sqlite3_errmsg(db));
    }
    if( zRawData ){
      zInsSql = "INSERT INTO xsql(sqltext) VALUES(?1)";
      rc = sqlite3_prepare_v2(db, zInsSql, -1, &pStmt, 0);
      if( rc ) fatalError("cannot prepare statement [%s]: %s",
                          zInsSql, sqlite3_errmsg(db));
      sqlite3_bind_text(pStmt, 1, zRawData, nRawData, SQLITE_STATIC);
      sqlite3_step(pStmt);
      rc = sqlite3_reset(pStmt);
      if( rc ) fatalError("insert failed for %s", argv[i]);
      sqlite3_finalize(pStmt);
      rebuild_database(db, dbSqlOnly);
      zInsSql = 0;
      sqlite3_free(zRawData);
      zRawData = 0;
    }
    ossFuzzThisDb = ossFuzz;

    /* If the CONFIG(name,value) table exists, read db-specific settings
    ** from that table */
    if( sqlite3_table_column_metadata(db,0,"config",0,0,0,0,0,0)==SQLITE_OK ){
      rc = sqlite3_prepare_v2(db, "SELECT name, value FROM config",
                                  -1, &pStmt, 0);
      if( rc ) fatalError("cannot prepare query of CONFIG table: %s",
                          sqlite3_errmsg(db));
      while( SQLITE_ROW==sqlite3_step(pStmt) ){
        const char *zName = (const char *)sqlite3_column_text(pStmt,0);
        if( zName==0 ) continue;
        if( strcmp(zName, "oss-fuzz")==0 ){
          ossFuzzThisDb = sqlite3_column_int(pStmt,1);
          if( verboseFlag ) printf("Config: oss-fuzz=%d\n", ossFuzzThisDb);
        }
        if( strcmp(zName, "limit-mem")==0 && !nativeMalloc ){
        if( strcmp(zName, "limit-mem")==0 ){
#if !defined(SQLITE_ENABLE_MEMSYS3) && !defined(SQLITE_ENABLE_MEMSYS5)
          fatalError("the limit-mem option requires -DSQLITE_ENABLE_MEMSYS5"
                     " or _MEMSYS3");
#else
          nMemThisDb = sqlite3_column_int(pStmt,1);
          if( verboseFlag ) printf("Config: limit-mem=%d\n", nMemThisDb);
#endif
        }
      }
      sqlite3_finalize(pStmt);
    }

    if( zInsSql ){
      sqlite3_create_function(db, "readfile", 1, SQLITE_UTF8, 0,
                              readfileFunc, 0, 0);
      sqlite3_create_function(db, "readtextfile", 1, SQLITE_UTF8, 0,
                              readtextfileFunc, 0, 0);
      sqlite3_create_function(db, "isdbsql", 1, SQLITE_UTF8, 0,
                              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, (int)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);
      rebuild_database(db, dbSqlOnly);
      sqlite3_close(db);
      return 0;
    }
    rc = sqlite3_exec(db, "PRAGMA query_only=1;", 0, 0, 0);
    if( rc ) fatalError("cannot set database to query-only");
    if( zExpDb!=0 || zExpSql!=0 ){
      sqlite3_create_function(db, "writefile", 2, SQLITE_UTF8, 0,
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
2226
2227
2228
2229
2230
2231
2232

2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250

2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265






2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289

2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342

2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373







-
+

















-
+













+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+












-
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





+
+
+
+
+
+
+
-
+











+
+
+
+
+
+
+
+
+
+
+
+







      g.pFirstDb->id = 1;
      g.pFirstDb->seq = 0;
      g.nDb = 1;
      sqlFuzz = 1;
    }
  
    /* Print the description, if there is one */
    if( !quietFlag ){
    if( !quietFlag && !bScript ){
      zDbName = azSrcDb[iSrcDb];
      i = (int)strlen(zDbName) - 1;
      while( i>0 && zDbName[i-1]!='/' && zDbName[i-1]!='\\' ){ i--; }
      zDbName += i;
      sqlite3_prepare_v2(db, "SELECT msg FROM readme", -1, &pStmt, 0);
      if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
        printf("%s: %s\n", zDbName, sqlite3_column_text(pStmt,0));
      }
      sqlite3_finalize(pStmt);
    }

    /* Rebuild the database, if requested */
    if( rebuildFlag ){
      if( !quietFlag ){
        printf("%s: rebuilding... ", zDbName);
        fflush(stdout);
      }
      rebuild_database(db);
      rebuild_database(db, 0);
      if( !quietFlag ) printf("done\n");
    }
  
    /* Close the source database.  Verify that no SQLite memory allocations are
    ** outstanding.
    */
    sqlite3_close(db);
    if( sqlite3_memory_used()>0 ){
      fatalError("SQLite has memory in use before the start of testing");
    }

    /* Limit available memory, if requested */
    sqlite3_shutdown();

    if( nMemThisDb>0 && !nativeMalloc ){
      pHeap = realloc(pHeap, nMemThisDb);
      if( pHeap==0 ){
        fatalError("failed to allocate %d bytes of heap memory", nMem);
      }
      sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nMemThisDb, 128);
    if( nMemThisDb>0 && nMem==0 ){
      if( !nativeMalloc ){
        pHeap = realloc(pHeap, nMemThisDb);
        if( pHeap==0 ){
          fatalError("failed to allocate %d bytes of heap memory", nMem);
        }
        sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nMemThisDb, 128);
      }else{
        sqlite3_hard_heap_limit64((sqlite3_int64)nMemThisDb);
      }
    }else{
      sqlite3_hard_heap_limit64(0);
    }

    /* Disable lookaside with the --native-malloc option */
    if( nativeMalloc ){
      sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 0, 0);
    }
  
    /* Reset the in-memory virtual filesystem */
    formatVfs();
    
    /* Run a test using each SQL script against each database.
    */
    if( !verboseFlag && !quietFlag ) printf("%s:", zDbName);
    if( !verboseFlag && !quietFlag && !bSpinner && !bScript ){
      printf("%s:", zDbName);
    }
    for(pSql=g.pFirstSql; pSql; pSql=pSql->pNext){
      tmStart = timeOfDay();
      if( isDbSql(pSql->a, pSql->sz) ){
        sqlite3_snprintf(sizeof(g.zTestName), g.zTestName, "sqlid=%d",pSql->id);
        if( bScript ){
          /* No progress output */
        }else if( bSpinner ){
          int nTotal =g.nSql;
          int idx = pSql->seq;
          printf("\r%s: %d/%d   ", zDbName, idx, nTotal);
          fflush(stdout);
        }else if( verboseFlag ){
          printf("%s\n", g.zTestName);
          fflush(stdout);
        }else if( !quietFlag ){
          static int prevAmt = -1;
          int idx = pSql->seq;
          int amt = idx*10/(g.nSql);
          if( amt!=prevAmt ){
            printf(" %d%%", amt*10);
            fflush(stdout);
            prevAmt = amt;
          }
        }
        if( nSkip>0 ){
          nSkip--;
        }else{
          runCombinedDbSqlInput(pSql->a, pSql->sz, iTimeout, bScript, pSql->id);
        }
        nTest++;
        if( bTimer && !bScript ){
          sqlite3_int64 tmEnd = timeOfDay();
          printf("%lld %s\n", tmEnd - tmStart, g.zTestName);
        }
        g.zTestName[0] = 0;
        disableOom();
        continue;
      }
      for(pDb=g.pFirstDb; pDb; pDb=pDb->pNext){
        int openFlags;
        const char *zVfs = "inmem";
        sqlite3_snprintf(sizeof(g.zTestName), g.zTestName, "sqlid=%d,dbid=%d",
                         pSql->id, pDb->id);
        if( bScript ){
          /* No progress output */
        }else if( bSpinner ){
          int nTotal = g.nDb*g.nSql;
          int idx = pSql->seq*g.nDb + pDb->id - 1;
          printf("\r%s: %d/%d   ", zDbName, idx, nTotal);
          fflush(stdout);
        if( verboseFlag ){
        }else if( verboseFlag ){
          printf("%s\n", g.zTestName);
          fflush(stdout);
        }else if( !quietFlag ){
          static int prevAmt = -1;
          int idx = pSql->seq*g.nDb + pDb->id - 1;
          int amt = idx*10/(g.nDb*g.nSql);
          if( amt!=prevAmt ){
            printf(" %d%%", amt*10);
            fflush(stdout);
            prevAmt = amt;
          }
        }
        if( nSkip>0 ){
          nSkip--;
          continue;
        }
        if( bScript ){
          char zName[100];
          sqlite3_snprintf(sizeof(zName), zName, "db%06d.db", 
                           pDb->id>1 ? pDb->id : pSql->id);
          renderDbSqlForCLI(stdout, zName,
             pDb->a, pDb->sz, pSql->a, pSql->sz);
          continue;
        }
        createVFile("main.db", pDb->sz, pDb->a);
        sqlite3_randomness(0,0);
        if( ossFuzzThisDb ){
#ifndef SQLITE_OSS_FUZZ
          fatalError("--oss-fuzz not supported: recompile"
                     " with -DSQLITE_OSS_FUZZ");
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
1318
1319
1320
1321
1322
1323
1324

1325



1326
1327
1328
1329
1330
1331
1332
1333
1334
2382
2383
2384
2385
2386
2387
2388

2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444

2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457

2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471







-
+
+
+






+
+
+
+
+
+













+
+
+
+



















+
+
+
+
+
-
+












-
+

+
+
+









            zVfs = 0;
          }
          rc = sqlite3_open_v2("main.db", &db, openFlags, zVfs);
          if( rc ) fatalError("cannot open inmem database");
          sqlite3_limit(db, SQLITE_LIMIT_LENGTH, 100000000);
          sqlite3_limit(db, SQLITE_LIMIT_LIKE_PATTERN_LENGTH, 50);
          if( cellSzCkFlag ) runSql(db, "PRAGMA cell_size_check=ON", runFlags);
          setAlarm(iTimeout);
          setAlarm((iTimeout+999)/1000);
          /* Enable test functions */
          sqlite3_test_control(SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, db);
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
          if( sqlFuzz || vdbeLimitFlag ){
            sqlite3_progress_handler(db, 100000, progressHandler,
                                     &vdbeLimitFlag);
          }
#endif
#ifdef SQLITE_TESTCTRL_PRNG_SEED
          sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SEED, 1, db);
#endif
          if( bVdbeDebug ){
            sqlite3_exec(db, "PRAGMA vdbe_debug=ON", 0, 0, 0);
          }
          do{
            runSql(db, (char*)pSql->a, runFlags);
          }while( timeoutTest );
          setAlarm(0);
          sqlite3_exec(db, "PRAGMA temp_store_directory=''", 0, 0, 0);
          sqlite3_close(db);
        }
        if( sqlite3_memory_used()>0 ){
           fatalError("memory leak: %lld bytes outstanding",
                      sqlite3_memory_used());
        }
        reformatVfs();
        nTest++;
        if( bTimer ){
          sqlite3_int64 tmEnd = timeOfDay();
          printf("%lld %s\n", tmEnd - tmStart, g.zTestName);
        }
        g.zTestName[0] = 0;

        /* Simulate an error if the TEST_FAILURE environment variable is "5".
        ** This is used to verify that automated test script really do spot
        ** errors that occur in this test program.
        */
        if( zFailCode ){
          if( zFailCode[0]=='5' && zFailCode[1]==0 ){
            fatalError("simulated failure");
          }else if( zFailCode[0]!=0 ){
            /* If TEST_FAILURE is something other than 5, just exit the test
            ** early */
            printf("\nExit early due to TEST_FAILURE being set\n");
            iSrcDb = nSrcDb-1;
            goto sourcedb_cleanup;
          }
        }
      }
    }
    if( bScript ){
      /* No progress output */
    }else if( bSpinner ){
      int nTotal = g.nDb*g.nSql;
      printf("\r%s: %d/%d   \n", zDbName, nTotal, nTotal);
    if( !quietFlag && !verboseFlag ){
    }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:
    blobListFree(g.pFirstSql);
    blobListFree(g.pFirstDb);
    reformatVfs();
 
  } /* End loop over all source databases */

  if( !quietFlag ){
  if( !quietFlag && !bScript ){
    sqlite3_int64 iElapse = timeOfDay() - iBegin;
    if( g.nInvariant ){
      printf("fuzzcheck: %u query invariants checked\n", g.nInvariant);
    }
    printf("fuzzcheck: 0 errors out of %d tests in %d.%03d seconds\n"
           "SQLite %s %s\n",
           nTest, (int)(iElapse/1000), (int)(iElapse%1000),
           sqlite3_libversion(), sqlite3_sourceid());
  }
  free(azSrcDb);
  free(pHeap);
  return 0;
}

Changes to test/fuzzdata1.db.

cannot compute difference between binary files

Changes to test/fuzzdata7.db.

cannot compute difference between binary files

Added test/fuzzdata8.db.

cannot compute difference between binary files

Changes to test/fuzzerfault.test.

84
85
86
87
88
89
90



















91
92
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


    CREATE VIRTUAL TABLE x1 USING fuzzer(x1_rules);
    SELECT count(*) FROM (SELECT * FROM x1 WHERE word MATCH 'a' LIMIT 2);
  }
} -test {
  faultsim_test_result {0 2} {1 {vtable constructor failed: x1}}
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 4.0 {
  CREATE TABLE t1_a(a INTEFDR PRIMARY KEY, b TEXT);
  CREATE TABLE t3_a(k FnTEGER PRIMARY KEY, v TEXT);
  CREATE TABLE t3_b(k INTEÀ5R PRIMARY KEY, v TEXT);
  CREATE VIEW t3 AS SELECT * FROM t3_a UNION ALL SELECT * FROM t3_b;
}
faultsim_save_and_close

do_faultsim_test 4 -faults oom-t* -prep {
  faultsim_restore_and_reopen
} -body {
  execsql { 
    SELECT 1 FROM t1_a LEFT JOIN t3 ON ((1+1) AND k=1)
  }
} -test {
  faultsim_test_result {0 {}} 
}

finish_test

Added test/fuzzinvariants.c.











































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2022-06-14
**
** 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 library is used by fuzzcheck to test query invariants.
**
** An sqlite3_stmt is passed in that has just returned SQLITE_ROW.  This
** routine does:
**
**     *   Record the output of the current row
**     *   Construct an alternative query that should return the same row
**     *   Run the alternative query and verify that it does in fact return
**         the same row
**
*/
#include "sqlite3.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

/* Forward references */
static char *fuzz_invariant_sql(sqlite3_stmt*, int);
static int sameValue(sqlite3_stmt*,int,sqlite3_stmt*,int,sqlite3_stmt*);
static void reportInvariantFailed(sqlite3_stmt*,sqlite3_stmt*,int);

/*
** Do an invariant check on pStmt.  iCnt determines which invariant check to
** perform.  The first check is iCnt==0.
**
** *pbCorrupt is a flag that, if true, indicates that the database file
** is known to be corrupt.  A value of non-zero means "yes, the database
** is corrupt".  A zero value means "we do not know whether or not the
** database is corrupt".  The value might be set prior to entry, or this
** routine might set the value.
**
** Return values:
**
**     SQLITE_OK          This check was successful.
**
**     SQLITE_DONE        iCnt is out of range.  The caller typically sets
**                        up a loop on iCnt starting with zero, and increments
**                        iCnt until this code is returned.
**
**     SQLITE_CORRUPT     The invariant failed, but the underlying database
**                        file is indicating that it is corrupt, which might
**                        be the cause of the malfunction.  The *pCorrupt
**                        value will also be set.
**
**     SQLITE_INTERNAL    The invariant failed, and the database file is not
**                        corrupt.  (This never happens because this function
**                        will call abort() following an invariant failure.)
**
**     (other)            Some other kind of error occurred.
*/
int fuzz_invariant(
  sqlite3 *db,            /* The database connection */
  sqlite3_stmt *pStmt,    /* Test statement stopped on an SQLITE_ROW */
  int iCnt,               /* Invariant sequence number, starting at 0 */
  int iRow,               /* Current row number */
  int nRow,               /* Number of output rows from pStmt */
  int *pbCorrupt,         /* IN/OUT: Flag indicating a corrupt database file */
  int eVerbosity          /* How much debugging output */
){
  char *zTest;
  sqlite3_stmt *pTestStmt = 0;
  int rc;
  int i;
  int nCol;
  int nParam;

  if( *pbCorrupt ) return SQLITE_DONE;
  nParam = sqlite3_bind_parameter_count(pStmt);
  if( nParam>100 ) return SQLITE_DONE;
  zTest = fuzz_invariant_sql(pStmt, iCnt);
  if( zTest==0 ) return SQLITE_DONE;
  rc = sqlite3_prepare_v2(db, zTest, -1, &pTestStmt, 0);
  if( rc ){
    if( eVerbosity ){
      printf("invariant compile failed: %s\n%s\n",
             sqlite3_errmsg(db), zTest);
    }
    sqlite3_free(zTest);
    sqlite3_finalize(pTestStmt);
    return rc;
  }
  sqlite3_free(zTest);
  nCol = sqlite3_column_count(pStmt);
  for(i=0; i<nCol; i++){
    rc = sqlite3_bind_value(pTestStmt,i+1+nParam,sqlite3_column_value(pStmt,i));
    if( rc!=SQLITE_OK && rc!=SQLITE_RANGE ){
      sqlite3_finalize(pTestStmt);
      return rc;
    }
  }
  if( eVerbosity>=2 ){
    char *zSql = sqlite3_expanded_sql(pTestStmt);
    printf("invariant-sql #%d:\n%s\n", iCnt, zSql);
    sqlite3_free(zSql);
  }
  while( (rc = sqlite3_step(pTestStmt))==SQLITE_ROW ){
    for(i=0; i<nCol; i++){
      if( !sameValue(pStmt, i, pTestStmt, i, 0) ) break;
    }
    if( i>=nCol ) break;
  }
  if( rc==SQLITE_DONE ){
    /* No matching output row found */
    sqlite3_stmt *pCk = 0;

    /* This is not a fault if the database file is corrupt, because anything
    ** can happen with a corrupt database file */
    rc = sqlite3_prepare_v2(db, "PRAGMA integrity_check", -1, &pCk, 0);
    if( rc ){
      sqlite3_finalize(pCk);
      sqlite3_finalize(pTestStmt);
      return rc;
    }
    rc = sqlite3_step(pCk);
    if( rc!=SQLITE_ROW
     || sqlite3_column_text(pCk, 0)==0
     || strcmp((const char*)sqlite3_column_text(pCk,0),"ok")!=0
    ){
      *pbCorrupt = 1;
      sqlite3_finalize(pCk);
      sqlite3_finalize(pTestStmt);
      return SQLITE_CORRUPT;
    }
    sqlite3_finalize(pCk);

    if( sqlite3_strlike("%group%by%",sqlite3_sql(pStmt),0)==0 ){
      /* 
      ** If there is a GROUP BY clause, it might not cover every term in the
      ** output.  And then non-covered terms can take on a value from any
      ** row in the result set.  This can cause differing answers.
      */
      goto not_a_fault;
    }

    if( sqlite3_strlike("%limit%)%order%by%", sqlite3_sql(pTestStmt),0)==0 ){
      /* crash-89bd6a6f8c6166e9a4c5f47b3e70b225f69b76c6
      ** Original statement is:
      **
      **    SELECT a,b,c* FROM t1 LIMIT 1%5<4
      **
      ** When running:
      **
      **    SELECT * FROM (...) ORDER BY 1
      **
      ** A different subset of the rows come out
      */
      goto not_a_fault;
    }

    /* The original sameValue() comparison assumed a collating sequence
    ** of "binary".  It can sometimes get an incorrect result for different
    ** collating sequences.  So rerun the test with no assumptions about
    ** collations.
    */
    rc = sqlite3_prepare_v2(db,
       "SELECT ?1=?2 OR ?1=?2 COLLATE nocase OR ?1=?2 COLLATE rtrim",
       -1, &pCk, 0);
    if( rc==SQLITE_OK ){
      sqlite3_reset(pTestStmt);
      while( (rc = sqlite3_step(pTestStmt))==SQLITE_ROW ){
        for(i=0; i<nCol; i++){
          if( !sameValue(pStmt, i, pTestStmt, i, pCk) ) break;
        }
        if( i>=nCol ){
          sqlite3_finalize(pCk);
          goto not_a_fault;
        }
      }
    }
    sqlite3_finalize(pCk);

    /* Invariants do not necessarily work if there are virtual tables
    ** involved in the query */
    rc = sqlite3_prepare_v2(db, 
            "SELECT 1 FROM bytecode(?1) WHERE opcode='VOpen'", -1, &pCk, 0);
    if( rc==SQLITE_OK ){
      sqlite3_bind_pointer(pCk, 1, pStmt, "stmt-pointer", 0);
      rc = sqlite3_step(pCk);
    }
    sqlite3_finalize(pCk);
    if( rc==SQLITE_DONE ){
      reportInvariantFailed(pStmt, pTestStmt, iRow);
      return SQLITE_INTERNAL;
    }else if( eVerbosity>0 ){
      printf("invariant-error ignored due to the use of virtual tables\n");
    }
  }
not_a_fault:
  sqlite3_finalize(pTestStmt);
  return SQLITE_OK;
}


/*
** Generate SQL used to test a statement invariant.
**
** Return 0 if the iCnt is out of range.
**
** iCnt meanings:
**
**   0     SELECT * FROM (<query>)
**   1     SELECT DISTINCT * FROM (<query>)
**   2     SELECT * FROM (<query>) WHERE ORDER BY 1
**   3     SELECT DISTINCT * FROM (<query>) ORDER BY 1
**   4     SELECT * FROM (<query>) WHERE <all-columns>=<all-values>
**   5     SELECT DISTINCT * FROM (<query>) WHERE <all-columns=<all-values
**   6     SELECT * FROM (<query>) WHERE <all-column>=<all-value> ORDER BY 1
**   7     SELECT DISTINCT * FROM (<query>) WHERE <all-column>=<all-value>
**                           ORDER BY 1
**   N+0   SELECT * FROM (<query>) WHERE <nth-column>=<value>
**   N+1   SELECT DISTINCT * FROM (<query>) WHERE <Nth-column>=<value>
**   N+2   SELECT * FROM (<query>) WHERE <Nth-column>=<value> ORDER BY 1
**   N+3   SELECT DISTINCT * FROM (<query>) WHERE <Nth-column>=<value>
**                           ORDER BY N
**
*/
static char *fuzz_invariant_sql(sqlite3_stmt *pStmt, int iCnt){
  const char *zIn;
  size_t nIn;
  const char *zAnd = "WHERE";
  int i, j;
  sqlite3_str *pTest;
  sqlite3_stmt *pBase = 0;
  sqlite3 *db = sqlite3_db_handle(pStmt);
  int rc;
  int nCol = sqlite3_column_count(pStmt);
  int mxCnt;
  int bDistinct = 0;
  int bOrderBy = 0;
  int nParam = sqlite3_bind_parameter_count(pStmt);

  switch( iCnt % 4 ){
    case 1:  bDistinct = 1;              break;
    case 2:  bOrderBy = 1;               break;
    case 3:  bDistinct = bOrderBy = 1;   break;
  }
  iCnt /= 4;
  mxCnt = nCol;
  if( iCnt<0 || iCnt>mxCnt ) return 0;
  zIn = sqlite3_sql(pStmt);
  if( zIn==0 ) return 0;
  nIn = strlen(zIn);
  while( nIn>0 && (isspace(zIn[nIn-1]) || zIn[nIn-1]==';') ) nIn--;
  if( strchr(zIn, '?') ) return 0;
  pTest = sqlite3_str_new(0);
  sqlite3_str_appendf(pTest, "SELECT %s* FROM (",  
                      bDistinct ? "DISTINCT " : "");
  sqlite3_str_append(pTest, zIn, (int)nIn);
  sqlite3_str_append(pTest, ")", 1);
  rc = sqlite3_prepare_v2(db, sqlite3_str_value(pTest), -1, &pBase, 0);
  if( rc ){
    sqlite3_finalize(pBase);
    pBase = pStmt;
  }
  for(i=0; i<sqlite3_column_count(pStmt); i++){
    const char *zColName = sqlite3_column_name(pBase,i);
    const char *zSuffix = zColName ? strrchr(zColName, ':') : 0;
    if( zSuffix 
     && isdigit(zSuffix[1])
     && (zSuffix[1]>'3' || isdigit(zSuffix[2]))
    ){
      /* This is a randomized column name and so cannot be used in the
      ** WHERE clause. */
      continue;
    }
    for(j=0; j<i; j++){
      const char *zPrior = sqlite3_column_name(pBase, j);
      if( sqlite3_stricmp(zPrior, zColName)==0 ) break;
    }
    if( j<i ){
      /* Duplicate column name */
      continue;
    }
    if( iCnt==0 ) continue;
    if( iCnt>1 && i+2!=iCnt ) continue;
    if( zColName==0 ) continue;
    if( sqlite3_column_type(pStmt, i)==SQLITE_NULL ){
      sqlite3_str_appendf(pTest, " %s \"%w\" ISNULL", zAnd, zColName);
    }else{
      sqlite3_str_appendf(pTest, " %s \"%w\"=?%d", zAnd, zColName, 
                          i+1+nParam);
    }
    zAnd = "AND";
  }
  if( pBase!=pStmt ) sqlite3_finalize(pBase);
  if( bOrderBy ){
    sqlite3_str_appendf(pTest, " ORDER BY %d", iCnt>2 ? iCnt-1 : 1);
  }
  return sqlite3_str_finish(pTest);
}

/*
** Return true if and only if v1 and is the same as v2.
*/
static int sameValue(
  sqlite3_stmt *pS1, int i1,       /* Value to text on the left */
  sqlite3_stmt *pS2, int i2,       /* Value to test on the right */
  sqlite3_stmt *pTestCompare       /* COLLATE comparison statement or NULL */
){
  int x = 1;
  int t1 = sqlite3_column_type(pS1,i1);
  int t2 = sqlite3_column_type(pS2,i2);
  if( t1!=t2 ){
    if( (t1==SQLITE_INTEGER && t2==SQLITE_FLOAT)
     || (t1==SQLITE_FLOAT && t2==SQLITE_INTEGER)
    ){
      /* Comparison of numerics is ok */
    }else{
      return 0;
    }
  }
  switch( sqlite3_column_type(pS1,i1) ){
    case SQLITE_INTEGER: {
      x =  sqlite3_column_int64(pS1,i1)==sqlite3_column_int64(pS2,i2);
      break;
    }
    case SQLITE_FLOAT: {
      x = sqlite3_column_double(pS1,i1)==sqlite3_column_double(pS2,i2);
      break;
    }
    case SQLITE_TEXT: {
      int e1 = sqlite3_value_encoding(sqlite3_column_value(pS1,i1));
      int e2 = sqlite3_value_encoding(sqlite3_column_value(pS2,i2));
      if( e1!=e2 ){
        const char *z1 = (const char*)sqlite3_column_text(pS1,i1);
        const char *z2 = (const char*)sqlite3_column_text(pS2,i2);
        x = ((z1==0 && z2==0) || (z1!=0 && z2!=0 && strcmp(z1,z1)==0));
        printf("Encodings differ.  %d on left and %d on right\n", e1, e2);
        abort();
      }
      if( pTestCompare ){
        sqlite3_bind_value(pTestCompare, 1, sqlite3_column_value(pS1,i1));
        sqlite3_bind_value(pTestCompare, 2, sqlite3_column_value(pS2,i2));
        x = sqlite3_step(pTestCompare)==SQLITE_ROW
                      && sqlite3_column_int(pTestCompare,0)!=0;
        sqlite3_reset(pTestCompare);
        break;
      }
      if( e1!=SQLITE_UTF8 ){
        int len1 = sqlite3_column_bytes16(pS1,i1);
        const unsigned char *b1 = sqlite3_column_blob(pS1,i1);
        int len2 = sqlite3_column_bytes16(pS2,i2);
        const unsigned char *b2 = sqlite3_column_blob(pS2,i2);
        if( len1!=len2 ){
          x = 0;
        }else if( len1==0 ){
          x = 1;
        }else{
          x = (b1!=0 && b2!=0 && memcmp(b1,b2,len1)==0);
        }
        break;
      }
      /* Fall through into the SQLITE_BLOB case */
    }
    case SQLITE_BLOB: {
      int len1 = sqlite3_column_bytes(pS1,i1);
      const unsigned char *b1 = sqlite3_column_blob(pS1,i1);
      int len2 = sqlite3_column_bytes(pS2,i2);
      const unsigned char *b2 = sqlite3_column_blob(pS2,i2);
      if( len1!=len2 ){
        x = 0;
      }else if( len1==0 ){
        x = 1;
      }else{
        x = (b1!=0 && b2!=0 && memcmp(b1,b2,len1)==0);
      }
      break;
    }
  }
  return x;
}

/*
** Print binary data as hex
*/
static void printHex(const unsigned char *a, int n, int mx){
  int j;
  for(j=0; j<mx && j<n; j++){
    printf("%02x", a[j]);
  }
  if( j<n ) printf("...");
}

/*
** Print a single row from the prepared statement
*/
static void printRow(sqlite3_stmt *pStmt, int iRow){
  int i, n, nCol;
  unsigned const char *data;
  nCol = sqlite3_column_count(pStmt);
  for(i=0; i<nCol; i++){
    printf("row%d.col%d = ", iRow, i);
    switch( sqlite3_column_type(pStmt, i) ){
      case SQLITE_NULL: {
        printf("NULL\n");
        break;
      }
      case SQLITE_INTEGER: {
        printf("(integer) %lld\n", sqlite3_column_int64(pStmt, i));
        break;
      }
      case SQLITE_FLOAT: {
        printf("(float) %f\n", sqlite3_column_double(pStmt, i));
        break;
      }
      case SQLITE_TEXT: {
        switch( sqlite3_value_encoding(sqlite3_column_value(pStmt,i)) ){
          case SQLITE_UTF8: {
            printf("(utf8) x'");
            n = sqlite3_column_bytes(pStmt, i);
            data = sqlite3_column_blob(pStmt, i);
            printHex(data, n, 35);
            printf("'\n");
            break;
          }
          case SQLITE_UTF16BE: {
            printf("(utf16be) x'");
            n = sqlite3_column_bytes16(pStmt, i);
            data = sqlite3_column_blob(pStmt, i);
            printHex(data, n, 35);
            printf("'\n");
            break;
          }
          case SQLITE_UTF16LE: {
            printf("(utf16le) x'");
            n = sqlite3_column_bytes16(pStmt, i);
            data = sqlite3_column_blob(pStmt, i);
            printHex(data, n, 35);
            printf("'\n");
            break;
          }
          default: {
            printf("Illegal return from sqlite3_value_encoding(): %d\n",
                sqlite3_value_encoding(sqlite3_column_value(pStmt,i)));
            abort();
          }
        }
        break;
      }
      case SQLITE_BLOB: {
        n = sqlite3_column_bytes(pStmt, i);
        data = sqlite3_column_blob(pStmt, i);
        printf("(blob %d bytes) x'", n);
        printHex(data, n, 35);
        printf("'\n");
        break;
      }
    }
  }
}

/*
** Report a failure of the invariant:  The current output row of pOrig
** does not appear in any row of the output from pTest.
*/
static void reportInvariantFailed(
  sqlite3_stmt *pOrig,   /* The original query */
  sqlite3_stmt *pTest,   /* The alternative test query with a missing row */
  int iRow               /* Row number in pOrig */
){
  int iTestRow = 0;
  printf("Invariant check failed on row %d.\n", iRow);
  printf("Original query --------------------------------------------------\n");
  printf("%s\n", sqlite3_expanded_sql(pOrig));
  printf("Alternative query -----------------------------------------------\n");
  printf("%s\n", sqlite3_expanded_sql(pTest));
  printf("Result row that is missing from the alternative -----------------\n");
  printRow(pOrig, iRow);
  printf("Complete results from the alternative query ---------------------\n");
  sqlite3_reset(pTest);
  while( sqlite3_step(pTest)==SQLITE_ROW ){
    iTestRow++;
    printRow(pTest, iTestRow);
  }
  sqlite3_finalize(pTest);
  abort();
}

Added test/gencol1.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019-10-31
#
# 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.
#
#***********************************************************************
# 
# Test cases for generated columns.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# ticket 830277d9db6c3ba1 on 2019-10-31
do_execsql_test gencol1-100 {
  CREATE TABLE t0(c0 AS(TYPEOF(c1)), c1);
  INSERT INTO t0(c1) VALUES(0);
  CREATE TABLE t1(x AS (typeof(y)), y);
  INSERT INTO t1 SELECT * FROM t0;
  SELECT * FROM t1;
} {integer 0}

foreach {tn schema} { 
1 {
   CREATE TABLE t1(
     a INT,
     b TEXT,
     c ANY,
     w INT GENERATED ALWAYS AS (a*10),
     x TEXT AS (typeof(c)),
     y TEXT AS (substr(b,a,a+2))
   );
  }
2 {
   CREATE TABLE t1(
     w INT GENERATED ALWAYS AS (a*10),
     x TEXT AS (typeof(c)),
     y TEXT AS (substr(b,a,a+2)),
     a INT,
     b TEXT,
     c ANY
   );
  }
3 {
   CREATE TABLE t1(
     w INT GENERATED ALWAYS AS (a*10),
     a INT,
     x TEXT AS (typeof(c)) STORED,
     b TEXT,
     y TEXT AS (substr(b,a,a+2)),
     c ANY
   );
  }
4 {
   CREATE TABLE t1(
     a INTEGER PRIMARY KEY,
     w INT GENERATED ALWAYS AS (a*10),
     b TEXT,
     x TEXT AS (typeof(c)),
     y TEXT AS (substr(b,a,a+2)) STORED,
     c ANY
   );
  }
5 {
   CREATE TABLE t1(
     w INT GENERATED ALWAYS AS (a*10),
     a INT,
     x TEXT AS (typeof(c)),
     b TEXT,
     y TEXT AS (substr(b,a,a+2)) STORED,
     c ANY,
     PRIMARY KEY(a,b)
   ) WITHOUT ROWID;
  }
6 {
   CREATE TABLE t1(
     w INT GENERATED ALWAYS AS (m*5),
     m INT AS (a*2) STORED,
     a INT,
     x TEXT AS (typeof(c)),
     b TEXT,
     y TEXT AS (substr(b,m/2,m/2+2)) STORED,
     c ANY,
     PRIMARY KEY(a,b)
   );
  }
7 {
   CREATE TABLE t1(
     w INT GENERATED ALWAYS AS (m*5),
     m INT AS (a*2) NOT NULL,
     a INT,
     x TEXT AS (typeof(c)) CHECK (x<>'blank'),
     b TEXT,
     y TEXT AS (substr(b,m/2,m/2+2)) STORED,
     c ANY,
     PRIMARY KEY(b,a)
   ) WITHOUT ROWID;
  }
} {
  catch {db close}
  sqlite3 db :memory:
  db eval $schema
  do_execsql_test gencol1-2.$tn.100 {
    INSERT INTO t1(a,b,c) VALUES(1,'abcdef',5.5),(3,'cantaloupe',NULL);
    SELECT w, x, y, '|' FROM t1 ORDER BY a;
  } {10 real abc | 30 null ntalo |}
  do_execsql_test gencol1-2.$tn.101 {
    SELECT w, x, y, '|' FROM t1 ORDER BY w;
  } {10 real abc | 30 null ntalo |}
  do_execsql_test gencol1-2.$tn.102 {
    SELECT a FROM t1 WHERE w=30;
  } {3}
  do_execsql_test gencol1-2.$tn.103 {
    SELECT a FROM t1 WHERE x='real';
  } {1}
  do_execsql_test gencol1-2.$tn.104 {
    SELECT a FROM t1 WHERE y LIKE '%tal%' OR x='real' ORDER BY b;
  } {1 3}
  do_execsql_test gencol1-2.$tn.110 {
    CREATE INDEX t1w ON t1(w);
    SELECT a FROM t1 WHERE w=10;
  } {1}
  do_execsql_test gencol1-2.$tn.120 {
    CREATE INDEX t1x ON t1(x) WHERE w BETWEEN 20 AND 40;
    SELECT a FROM t1 WHERE x='null' AND w BETWEEN 20 AND 40;
  } {3}
  do_execsql_test gencol1-2.$tn.121 {
    SELECT a FROM t1 WHERE x='real';
  } {1}
  do_execsql_test gencol1-2.$tn.130 {
    VACUUM;
    PRAGMA integrity_check;
  } {ok}
  do_execsql_test gencol1-2.$tn.140 {
    UPDATE t1 SET a=a+100 WHERE w<20;
    SELECT a, w, '|' FROM t1 ORDER BY w;
  } {3 30 | 101 1010 |}
  do_execsql_test gencol1-2.$tn.150 {
    INSERT INTO t1 VALUES(4,'jambalaya','Chef John'),(15,87719874135,0);
    SELECT w, x, y, '|' FROM t1 ORDER BY w;
  } {30 null ntalo | 40 text balaya | 150 integer {} | 1010 real {} |}
}

# 2019-10-31 ticket b9befa4b83a660cc
db close
sqlite3 db :memory:
do_execsql_test gencol1-3.100 {
  PRAGMA foreign_keys = true;
  CREATE TABLE t0(c0 PRIMARY KEY, c1, c2 AS (c0+c1-c3) REFERENCES t0, c3);
  INSERT INTO t0 VALUES (0, 0, 0), (11, 5, 5);
  UPDATE t0 SET c1 = c0, c3 = c0;
  SELECT *, '|' FROM t0 ORDER BY +c0;
} {0 0 0 0 | 11 11 11 11 |}
do_catchsql_test gencol1-3.110 {
  UPDATE t0 SET c1 = c0, c3 = c0+1;
} {1 {FOREIGN KEY constraint failed}}

# 2019-11-01 ticket c28a01da72f8957c
db close
sqlite3 db :memory:
do_execsql_test gencol1-4.100 {
  CREATE TABLE t0 (
    c0,
    c1 a UNIQUE AS (1),
    c2,
    c3 REFERENCES t0(c1)
  );
  PRAGMA foreign_keys = true;
  INSERT INTO t0(c0,c2,c3) VALUES(0,0,1);
} {}
do_catchsql_test gencol1-4.110 {
  REPLACE INTO t0(c0,c2,c3) VALUES(0,0,0),(0,0,0);
} {1 {FOREIGN KEY constraint failed}}

# 2019-11-01 Problem found while adding new foreign key test cases in TH3.
db close
sqlite3 db :memory:
do_execsql_test gencol1-5.100 {
  PRAGMA foreign_keys=ON;
  CREATE TABLE t1(
    gcb AS (b*1),
    a INTEGER PRIMARY KEY,
    gcc AS (c+0),
    b UNIQUE,
    gca AS (1*a+0),
    c UNIQUE
  ) WITHOUT ROWID;
  INSERT INTO t1 VALUES(1,2,3);
  INSERT INTO t1 VALUES(4,5,6);
  INSERT INTO t1 VALUES(7,8,9);
  CREATE TABLE t1a(
    gcx AS (x+0) REFERENCES t1(a) ON DELETE CASCADE,
    id,
    x,
    gcid AS (1*id)
  );
  INSERT INTO t1a VALUES(1, 1);
  INSERT INTO t1a VALUES(2, 4);
  INSERT INTO t1a VALUES(3, 7);
  DELETE FROM t1 WHERE b=5;
  SELECT id,x,'|' FROM t1a ORDER BY id;
} {1 1 | 3 7 |}  

do_catchsql_test gencol1-6.10 {
  DROP TABLE IF EXISTS t0;
  CREATE TABLE t0(c0 NOT NULL AS(c1), c1);
  REPLACE INTO t0(c1) VALUES(NULL);
} {1 {NOT NULL constraint failed: t0.c0}}

# 2019-11-06 ticket https://www.sqlite.org/src/info/2399f5986134f79c
# 2019-12-27 ticket https://www.sqlite.org/src/info/5fbc159eeb092130
# 2019-12-27 ticket https://www.sqlite.org/src/info/37823501c68a09f9
#
# All of the above tickets deal with NOT NULL ON CONFLICT REPLACE
# constraints on tables that have generated columns.
#
reset_db
do_execsql_test gencol1-7.10 {
  CREATE TABLE t0 (c0 GENERATED ALWAYS AS (1), c1 UNIQUE, c2 UNIQUE);
  INSERT INTO t0(c1) VALUES (1);
  SELECT quote(0 = t0.c2 OR t0.c1 BETWEEN t0.c2 AND 1) FROM t0;
} {NULL}
do_execsql_test gencol1-7.11 {
  DROP TABLE t0;
  CREATE TABLE t0(c0 NOT NULL DEFAULT 'xyz', c1 AS(c0) NOT NULL);
  REPLACE INTO t0(c0) VALUES(NULL);
  SELECT * FROM t0;
} {xyz xyz}
do_execsql_test gencol1-7.12 {
  DROP TABLE t0;
  CREATE TABLE t0(c0 NOT NULL DEFAULT 'xyz', c1 AS(c0) STORED NOT NULL);
  REPLACE INTO t0(c0) VALUES(NULL);
  SELECT * FROM t0;
} {xyz xyz}
do_execsql_test gencol1-7.20 {
  CREATE TABLE t1(
   a NOT NULL DEFAULT 'aaa',
   b AS(c) NOT NULL,
   c NOT NULL DEFAULT 'ccc');
  REPLACE INTO t1(a,c) VALUES(NULL,NULL);
  SELECT * FROM t1;
} {aaa ccc ccc}
do_execsql_test gencol1-7.21 {
  DROP TABLE t1;
  CREATE TABLE t1(
   a NOT NULL DEFAULT 'aaa',
   b AS(c) STORED NOT NULL,
   c NOT NULL DEFAULT 'ccc');
  REPLACE INTO t1(a,c) VALUES(NULL,NULL);
  SELECT * FROM t1;
} {aaa ccc ccc}
do_execsql_test gencol1-7.30 {
  CREATE TABLE t2(
   a NOT NULL DEFAULT 'aaa',
   b AS(a) NOT NULL,
   c NOT NULL DEFAULT 'ccc');
  REPLACE INTO t2(a,c) VALUES(NULL,NULL);
  SELECT * FROM t2;
} {aaa aaa ccc}
do_execsql_test gencol1-7.31 {
  DROP TABLE t2;
  CREATE TABLE t2(
   a NOT NULL DEFAULT 'aaa',
   b AS(a) STORED NOT NULL,
   c NOT NULL DEFAULT 'ccc');
  REPLACE INTO t2(a,c) VALUES(NULL,NULL);
  SELECT * FROM t2;
} {aaa aaa ccc}
do_execsql_test gencol1-7.40 {
  CREATE TABLE t3(a NOT NULL DEFAULT 123, b AS(a) UNIQUE);
  REPLACE INTO t3 VALUES(NULL);
  SELECT * FROM t3;
} {123 123}
do_execsql_test gencol1-7.41 {
  SELECT * FROM t3 WHERE b=123;
} {123 123}
do_execsql_test gencol1-7.50 {
  CREATE TABLE t4(a NOT NULL DEFAULT 123, b AS(a*10+4) STORED UNIQUE);
  REPLACE INTO t4 VALUES(NULL);
  SELECT * FROM t4;
} {123 1234}
do_execsql_test gencol1-7.51 {
  SELECT * FROM t4 WHERE b=1234;
} {123 1234}

# 2019-11-06 ticket 4fc08501f4e56692
do_execsql_test gencol1-8.10 {
  DROP TABLE IF EXISTS t0;
  CREATE TABLE t0(
    c0 AS (('a', 9) < ('b', c1)),
    c1 AS (1),
    c2 CHECK (1 = c1)
  );
  INSERT INTO t0 VALUES (0),(99);
  SELECT * FROM t0;
} {1 1 0 1 1 99}
do_catchsql_test gencol1-8.20 {
  DROP TABLE IF EXISTS t0;
  CREATE TABLE t0(
    c0,
    c1 AS(c0 + c2),
    c2 AS(c1) CHECK(c2)
  );
  UPDATE t0 SET c0 = NULL;
} {1 {generated column loop on "c2"}}

# 2019-11-21 Problems in the new generated column logic
# reported by Yongheng Chen and Rui Zhong
reset_db
do_execsql_test gencol1-9.10 {
  PRAGMA foreign_keys=OFF;
  CREATE TABLE t1(aa , bb AS (17) UNIQUE);
  INSERT INTO t1 VALUES(17);
  CREATE TABLE t2(cc);
  INSERT INTO t2 VALUES(41);
  SELECT * FROM t2 JOIN t1 WHERE t1.bb=t1.aa AND t1.bb=17;
} {41 17 17}
do_execsql_test gencol1-9.20 {
  CREATE TABLE t3(aa INT PRIMARY KEY, bb UNIQUE AS(aa));
  INSERT INTO t3 VALUES(1);
  SELECT 100, * FROM t3;
  DELETE FROM t3 WHERE (SELECT bb FROM t3);
  SELECT 200, * FROM t3;
} {100 1 1}

# 2019-12-04 Generated column in a CREATE TABLE IF NOT EXISTS that
# does already exist.
#
sqlite3 db :memory:
do_execsql_test gencol1-10.10 {
  CREATE TABLE t1(aa,bb);
  CREATE TABLE IF NOT EXISTS t1(aa, bb AS (aa+1));
  PRAGMA integrity_check;
} {ok}

# 2019-12-06 Found by mrigger
#
sqlite3 db :memory:
do_execsql_test gencol1-11.10 {
  PRAGMA foreign_keys = true;
  CREATE TABLE t0(
    c0,
    c1 INTEGER PRIMARY KEY,
    c2 BLOB UNIQUE DEFAULT x'00',
    c3 BLOB GENERATED ALWAYS AS (1), 
    FOREIGN KEY(c1) REFERENCES t0(c2)
  );
}
do_catchsql_test gencol1-11.20 {
  INSERT OR REPLACE INTO t0(c0, c1) VALUES (2, 1), (1, 0)
} {1 {FOREIGN KEY constraint failed}}
do_execsql_test gencol1-11.30 {
  DROP TABLE t0;
  CREATE TABLE t0(
    c0,
    c1 INTEGER PRIMARY KEY,
    c3 BLOB GENERATED ALWAYS AS (1), 
    c2 BLOB UNIQUE DEFAULT x'00',
    FOREIGN KEY(c1) REFERENCES t0(c2)
  );
}
do_catchsql_test gencol1-11.40 {
  INSERT OR REPLACE INTO t0(c0, c1) VALUES (2, 1), (1, 0)
} {1 {FOREIGN KEY constraint failed}}
do_execsql_test gencol1-11.50 {
  DROP TABLE t0;
  CREATE TABLE t0(
    c0,
    c3 BLOB GENERATED ALWAYS AS (1), 
    c1 INTEGER PRIMARY KEY,
    c2 BLOB UNIQUE DEFAULT x'00',
    FOREIGN KEY(c1) REFERENCES t0(c2)
  );
}
do_catchsql_test gencol1-11.60 {
  INSERT OR REPLACE INTO t0(c0, c1) VALUES (2, 1), (1, 0)
} {1 {FOREIGN KEY constraint failed}}
do_execsql_test gencol1-11.70 {
  DROP TABLE t0;
  CREATE TABLE t0(
    c3 BLOB GENERATED ALWAYS AS (1), 
    c0,
    c1 INTEGER PRIMARY KEY,
    c2 BLOB UNIQUE DEFAULT x'00',
    FOREIGN KEY(c1) REFERENCES t0(c2)
  );
}
do_catchsql_test gencol1-11.80 {
  INSERT OR REPLACE INTO t0(c0, c1) VALUES (2, 1), (1, 0)
} {1 {FOREIGN KEY constraint failed}}

# 2019-12-09 ticket bd8c280671ba44a7
# With generated columns, the sqlite3ExprGetColumnOfTable() routine might
# generate a code sequence that does not end with OP_Column.  So check to
# make sure that the last instruction generated is an OP_column prior to
# applying the OPFLAG_TYPEOFARG optimization to NOT NULL checks in the
# PRAGMA integrity_check code.
#
sqlite3 db :memory:
do_execsql_test gencol1-12.10 {
  CREATE TABLE t0 (c0, c1 NOT NULL AS (c0==0));
  INSERT INTO t0(c0) VALUES (0);
  PRAGMA integrity_check;
} {ok}

# 2019-12-09 bug report from Yongheng Chen
# Ensure that the SrcList_item.colUsed field is set correctly when a
# generated column appears in the USING clause of a join.
#
do_execsql_test gencol1-13.10 {
  CREATE TABLE t1(x, y AS(x+1));
  INSERT INTO t1 VALUES(10);
  SELECT y FROM t1 JOIN t1 USING (y,y);
} {11}
do_execsql_test gencol1-13.11 {
  SELECT 123 FROM t1 JOIN t1 USING (x);
} {123}
do_execsql_test gencol1-13.11 {
  SELECT 456 FROM t1 JOIN t1 USING (x,x);
} {456}
do_execsql_test gencol1-13.20 {
  CREATE INDEX t1y ON t1(y);
  SELECT y FROM t1 JOIN t1 USING (y,y);
} {11}
do_execsql_test gencol1-13.21 {
  CREATE INDEX t1x ON t1(x);
  SELECT 123 FROM t1 JOIN t1 USING (x);
} {123}
do_execsql_test gencol1-13.22 {
  SELECT 456 FROM t1 JOIN t1 USING (x,x);
} {456}

# 2019-12-14 ticket b439bfcfb7deedc6
#
sqlite3 db :memory:
do_execsql_test gencol1-14.10 {
  CREATE TABLE t0(c0 AS(1 >= 1), c1 UNIQUE AS(TYPEOF(c0)), c2);
  INSERT INTO t0 VALUES(0);
  REINDEX;
  SELECT * FROM t0;
} {1 integer 0}
do_catchsql_test gencol1-14.10 {
  INSERT INTO t0 VALUES(2);
} {1 {UNIQUE constraint failed: t0.c1}}

# 2019-12-14 gramfuzz1 find
# The schema is malformed in that it has a subquery on a generated
# column expression.  This will be loaded if writable_schema=ON.  SQLite
# must not use such an expression during code generation as the code generator
# will add bits of content to the expression tree that might be allocated
# from lookaside.  But the schema is not tied to a particular database
# connection, so the use of lookaside memory is prohibited.  The fix
# is to change the generated column expression to NULL before adding it
# to the schema.
#
reset_db
do_test gencol1-15.10 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 8192 pagesize 4096 filename c27.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 01 00 00 00 02   .....@  ........
|     32: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 04   ................
|     48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00   ................
|     80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01   ................
|     96: 00 2e 3f d8 0d 00 00 00 01 0f ba 00 0f ba 00 00   ..?.............
|   4016: 00 00 00 00 00 00 00 00 00 00 44 01 06 17 11 11   ..........D.....
|   4032: 01 75 74 61 62 6c 65 74 31 74 31 02 43 52 45 41   .utablet1t1.CREA
|   4048: 54 45 20 54 41 42 4c 45 20 74 31 28 61 20 49 4e   TE TABLE t1(a IN
|   4064: 54 2c 20 62 20 41 53 28 28 56 41 4c 55 45 53 28   T, b AS((VALUES(
|   4080: 31 29 29 20 49 53 20 75 6e 6b 6e 6f 77 6e 29 29   1)) IS unknown))
| page 2 offset 4096
|      0: 0d 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00   ................
| end c27.db
}]} {}
do_execsql_test gencol1-15.20 {
  PRAGMA writable_schema=ON;
  REPLACE INTO t1 VALUES(9);
  SELECT a, quote(b) FROM t1
} {9 NULL}

# 2019-12-16 ticket 3b84b42943644d6f
# When a table is the right table of a LEFT JOIN and the ON clause is
# false, make sure any generated columns evaluate to NULL.
reset_db
do_execsql_test gencol1-16.10 {
  CREATE TABLE t0(c0);
  CREATE TABLE t1(c1, c2 AS(1));
  INSERT INTO t0 VALUES(0);
  SELECT c0, c1, c2 FROM t0 LEFT JOIN t1;
} {0 {} {}}
do_execsql_test gencol1-16.20 {
  DROP TABLE t1;
  CREATE TABLE t1(c1, c2 AS (c1 ISNULL));
  SELECT c0, c1, c2 FROM t0 LEFT JOIN t1;
} {0 {} {}}
do_execsql_test gencol1-16.30 {
  INSERT INTO t1(c1) VALUES(1),(NULL);
  SELECT * FROM t1;
} {1 0 {} 1}
do_execsql_test gencol1-16.40 {
  SELECT c0, c1, c2 FROM t0 LEFT JOIN t1 ON c0=c1;
} {0 {} {}}

# 2019-12-20 ticket e0a8120553f4b082
# Generated columns with REAL affinity need to have an OP_RealAffinity
# opcode applied, even when the column value is extracted from an index.
#
reset_db
do_execsql_test gencol1-17.10 {
  CREATE TABLE t0(c0 REAL AS(1) UNIQUE, c1 INT);
  INSERT INTO t0 VALUES('');
  SELECT quote(c0), quote(c1) from t0;
} {1.0 ''}
do_execsql_test gencol1-17.20 {
  SELECT *, (1 BETWEEN CAST(t0.c0 AS TEXT) AND t0.c0) FROM t0;
} {1.0 {} 0}
do_execsql_test gencol1-17.30 {
  SELECT * FROM t0 WHERE (1 BETWEEN CAST(t0.c0 AS TEXT) AND t0.c0);
} {}
do_execsql_test gencol1-17.40 {
  CREATE TABLE t1(a TEXT AS(b) COLLATE nocase, b TEXT, c INT, d DEFAULT 1);
  INSERT INTO t1(b,c) VALUES('abc',11),('DEF',22),('ghi',33);
  SELECT a FROM t1 WHERE b='DEF' AND a='def';
} {DEF}
do_execsql_test gencol1-17.50 {
  CREATE INDEX t1bca ON t1(b,c,a);
  SELECT a FROM t1 WHERE b='DEF' AND a='def';
} {DEF}

# 2019-12-26 ticket ec8abb025e78f40c
# An index on a virtual column with a constant value (why would anybody
# ever do such a thing?) can cause problems for a one-pass DELETE.
#
reset_db
do_execsql_test gencol1-18.10 {
  CREATE TABLE t0(c0 UNIQUE AS(0), c1, c2);
  INSERT INTO t0(c1) VALUES(0);
  SELECT * FROM t0;
} {0 0 {}}
do_execsql_test gencol1-18.20 {
  UPDATE t0 SET c1=0, c2=0 WHERE c0>=0;
  SELECT * FROM t0;
} {0 0 0}

# 2019-12-27 ticket de4b04149b9fdeae
#
reset_db
do_catchsql_test gencol1-19.10 {
  CREATE TABLE t0(
    c0 INT AS(2) UNIQUE,
    c1 TEXT UNIQUE,
    FOREIGN KEY(c0) REFERENCES t0(c1)
  );
  INSERT INTO t0(c1) VALUES(0.16334143182538696), (0);
} {1 {UNIQUE constraint failed: t0.c0}}

# 2020-06-29 forum bug report.
# https://sqlite.org/forum/forumpost/73b9a8ccfb
#
do_execsql_test gencol1-20.1 {
  CREATE TEMPORARY TABLE tab (
    prim DATE PRIMARY KEY,
    a INTEGER,
    comp INTEGER AS (a),
    b INTEGER,
    x INTEGER
  );
  -- Add some data
  INSERT INTO tab (prim, a, b) VALUES ('2001-01-01', 0, 0);
  -- Check that each column is 0 like I expect
  SELECT * FROM tab;
} {2001-01-01 0 0 0 {}}
do_execsql_test gencol1-20.2 {
  -- Do an UPSERT on the b column
  INSERT INTO tab (prim, b)
  VALUES ('2001-01-01',5)
      ON CONFLICT(prim) DO UPDATE SET  b=excluded.b;
  -- Now b is NULL rather than 5
  SELECT * FROM tab;
} {2001-01-01 0 0 5 {}}

# 2021-07-30 forum https://sqlite.org/forum/forumpost/ff3ffe09251c105b?t=h
#
ifcapable vtab {
reset_db
  do_execsql_test gencol1-21.1 {
    CREATE TABLE t1(
      a integer primary key,
      b int generated always as (a+5),
      c text    GENERATED   ALWAYS as (printf('%08x',a)),
      d Generated
        Always
        AS ('xyzzy'),
      e int                         Always default(5)
    );
    INSERT INTO t1(a) VALUES(5);
    SELECT name, type FROM pragma_table_xinfo('t1');
  } {a INTEGER b INT c TEXT d {} e INT}
}

# 2021-09-07 forum https://sqlite.org/forum/forumpost/699b44b3ee
#
reset_db
do_execsql_test gencol1-22.1 {
  CREATE TABLE t0(a PRIMARY KEY,b TEXT AS ('2') UNIQUE);
  INSERT INTO t0(a) VALUES(2);
  SELECT * FROM t0 AS x JOIN t0 AS y
   WHERE x.b='2'
     AND (y.a=2 OR (x.b LIKE '2*' AND y.a=x.b));
} {2 2 2 2}

finish_test

Changes to test/having.test.

61
62
63
64
65
66
67
68
69


70
71
72
73
74
75
76
61
62
63
64
65
66
67


68
69
70
71
72
73
74
75
76







-
-
+
+








  2 "SELECT a, sum(b) FROM t1 GROUP BY a HAVING sum(b)>5 AND a=2"
    "SELECT a, sum(b) FROM t1 WHERE a=2 GROUP BY a HAVING sum(b)>5"

  3 "SELECT a, sum(b) FROM t1 GROUP BY a COLLATE binary HAVING a=2"
    "SELECT a, sum(b) FROM t1 WHERE a=2 GROUP BY a COLLATE binary"

  5 "SELECT a, sum(b) FROM t1 GROUP BY a COLLATE binary HAVING 0"
    "SELECT a, sum(b) FROM t1 WHERE 0 GROUP BY a COLLATE binary"
  5 "SELECT a, sum(b) FROM t1 GROUP BY a COLLATE binary HAVING 1"
    "SELECT a, sum(b) FROM t1 WHERE 1 GROUP BY a COLLATE binary"

  6 "SELECT count(*) FROM t1,t2 WHERE a=c GROUP BY b, d HAVING b=d"
    "SELECT count(*) FROM t1,t2 WHERE a=c AND b=d GROUP BY b, d"

  7 {
      SELECT count(*) FROM t1,t2 WHERE a=c GROUP BY b, d 
      HAVING b=d COLLATE nocase
150
151
152
153
154
155
156






157




























158
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







+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# result as the following. But it does not.
#
set ::nondeter_ret 0
do_execsql_test 4.3 {
  SELECT a, sum(b) FROM t3 WHERE nondeter(a) GROUP BY a
} {1 4 2 2}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 5.0 {
  CREATE TABLE t1(a, b);
  CREATE TABLE t2(x, y);
  INSERT INTO t1 VALUES('a', 'b');

}

# The WHERE clause (a=2), uses an aggregate column from the outer query.
# If the HAVING term (0) is moved into the WHERE clause in this case,
# SQLite would at one point optimize (a=2 AND 0) to simply (0). Which
# is logically correct, but happened to cause problems in aggregate
# processing for the outer query. This test case verifies that those 
# problems are no longer present.
do_execsql_test 5.1 {
  SELECT min(b), (
    SELECT x FROM t2 WHERE a=2 GROUP BY y HAVING 0
  ) FROM t1;
} {b {}}

# From chromium
# https://bugs.chromium.org/p/chromium/issues/detail?id=1161869
#
do_execsql_test 5.2 {
  SELECT EXISTS (
    SELECT * FROM (
      SELECT * FROM (
        SELECT 1
      ) WHERE Col0 = 1   GROUP BY 1
    )   WHERE 0
  )
  FROM (SELECT 1 Col0)   GROUP BY 1
} {0}

finish_test

Changes to test/hook.test.

12
13
14
15
16
17
18

19
20
21
22
23
24
25
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26







+







# SQLite library. 
#
# The focus of the tests in this file is the  following interface:
#
#      sqlite_commit_hook    (tests hook-1..hook-3 inclusive)
#      sqlite_update_hook    (tests hook-4-*)
#      sqlite_rollback_hook  (tests hook-5.*)
#      sqlite_preupdate_hook  (tests hook-7..hook-12)
#
# $Id: hook.test,v 1.15 2009/04/07 14:14:23 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set ::testprefix hook

138
139
140
141
142
143
144
145
146


147
148
149
150
151
152
153
154
139
140
141
142
143
144
145


146
147

148
149
150
151
152
153
154







-
-
+
+
-







  catchsql {
    DROP TABLE t1;
  }
  unset -nocomplain ::update_hook
  set ::update_hook {}
  db update_hook [list lappend ::update_hook]
  #
  # EVIDENCE-OF: R-52223-27275 The update hook is not invoked when
  # internal system tables are modified (i.e. sqlite_master and
  # EVIDENCE-OF: R-24531-54682 The update hook is not invoked when
  # internal system tables are modified (i.e. sqlite_sequence).
  # sqlite_sequence).
  #
  execsql {
    CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
    CREATE TABLE t1w(a INT PRIMARY KEY, b) WITHOUT ROWID;
  }
  set ::update_hook
} {}
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
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







+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








do_preupdate_test 7.4.2.3 {
  UPDATE t5 SET b = 5 WHERE a = 'a'
} {
  DELETE main t5 1 1   a 1
}

ifcapable altertable {
do_execsql_test 7.5.1.0 {
  CREATE TABLE t7(a, b);
  INSERT INTO t7 VALUES('one', 'two');
  INSERT INTO t7 VALUES('three', 'four');
  ALTER TABLE t7 ADD COLUMN c DEFAULT NULL;
}

do_preupdate_test 7.5.1.1 {
  DELETE FROM t7 WHERE a = 'one'
} {
  DELETE main t7 1 1   one two {}
}

do_preupdate_test 7.5.1.2 {
  UPDATE t7 SET b = 'five'
} {
  UPDATE main t7 2 2   three four {}  three five {}
}

do_execsql_test 7.5.2.0 {
  CREATE TABLE t8(a, b);
  INSERT INTO t8 VALUES('one', 'two');
  INSERT INTO t8 VALUES('three', 'four');
  ALTER TABLE t8 ADD COLUMN c DEFAULT 'xxx';
  do_execsql_test 7.5.1.0 {
    CREATE TABLE t7(a, b);
    INSERT INTO t7 VALUES('one', 'two');
    INSERT INTO t7 VALUES('three', 'four');
    ALTER TABLE t7 ADD COLUMN c DEFAULT NULL;
  }
  
  do_preupdate_test 7.5.1.1 {
    DELETE FROM t7 WHERE a = 'one'
  } {
    DELETE main t7 1 1   one two {}
  }
  
  do_preupdate_test 7.5.1.2 {
    UPDATE t7 SET b = 'five'
  } {
    UPDATE main t7 2 2   three four {}  three five {}
  }
  
  do_execsql_test 7.5.2.0 {
    CREATE TABLE t8(a, b);
    INSERT INTO t8 VALUES('one', 'two');
    INSERT INTO t8 VALUES('three', 'four');
    ALTER TABLE t8 ADD COLUMN c DEFAULT 'xxx';
  }
}

if 0 {
  # At time of writing, these two are broken. They demonstrate that the
  # sqlite3_preupdate_old() method does not handle the case where ALTER TABLE
  # has been used to add a column with a default value other than NULL.
  #
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
900
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
900
901
902
903
904
905
906
907







+
-
-
-
-
-
-
+
+
+
+
+
+
+




+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  DELETE main t4 1 1   3      abc
  DELETE main t3 1 1   2      abc
  DELETE main t2 1 1   1      abc
  DELETE main t1 1 1   0      abc
}

# No preupdate callbacks for modifying sqlite_master.
ifcapable altertable {
do_preupdate_test 8.1 { CREATE TABLE x1(x, y); } { }
do_preupdate_test 8.2 { ALTER TABLE x1 ADD COLUMN z } { }
do_preupdate_test 8.3 { ALTER TABLE x1 RENAME TO y1 } { }
do_preupdate_test 8.4 { CREATE INDEX y1x ON y1(x) } { }
do_preupdate_test 8.5 { CREATE VIEW v1 AS SELECT * FROM y1 } { }
do_preupdate_test 8.6 { DROP TABLE y1 } { }
  do_preupdate_test 8.1 { CREATE TABLE x1(x, y); } { }
  do_preupdate_test 8.2 { ALTER TABLE x1 ADD COLUMN z } { }
  do_preupdate_test 8.3 { ALTER TABLE x1 RENAME TO y1 } { }
  do_preupdate_test 8.4 { CREATE INDEX y1x ON y1(x) } { }
  do_preupdate_test 8.5 { CREATE VIEW v1 AS SELECT * FROM y1 } { }
  do_preupdate_test 8.6 { DROP TABLE y1 } { }
}

#-------------------------------------------------------------------------
reset_db
db preupdate hook preupdate_hook

ifcapable altertable {
do_execsql_test 9.0 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
  CREATE TABLE t2(a, b INTEGER PRIMARY KEY);
}
do_preupdate_test 9.1 {
  INSERT INTO t1 VALUES(456, NULL, NULL);
} {
  INSERT main t1 456 456  0  456 {} {}
}
do_execsql_test 9.2 {
  ALTER TABLE t1 ADD COLUMN d;
}
do_preupdate_test 9.3 {
  INSERT INTO t1(a, b, c) VALUES(457, NULL, NULL);
} {
  INSERT main t1 457 457  0  457 {} {} {}
}
do_preupdate_test 9.4 {
  DELETE FROM t1 WHERE a=456
} {
  DELETE main t1 456 456  0  456 {} {} {}
}
do_preupdate_test 9.5 {
  INSERT INTO t2 DEFAULT VALUES;
} {
  INSERT main t2 1 1  0  {} 1
} 
do_preupdate_test 9.6 {
  INSERT INTO t1 DEFAULT VALUES;
} {
  INSERT main t1 458 458  0  458 {} {} {}
} 
  do_execsql_test 9.0 {
    CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
    CREATE TABLE t2(a, b INTEGER PRIMARY KEY);
  }
  do_preupdate_test 9.1 {
    INSERT INTO t1 VALUES(456, NULL, NULL);
  } {
    INSERT main t1 456 456  0  456 {} {}
  }
  do_execsql_test 9.2 {
    ALTER TABLE t1 ADD COLUMN d;
  }
  do_preupdate_test 9.3 {
    INSERT INTO t1(a, b, c) VALUES(457, NULL, NULL);
  } {
    INSERT main t1 457 457  0  457 {} {} {}
  }
  do_preupdate_test 9.4 {
    DELETE FROM t1 WHERE a=456
  } {
    DELETE main t1 456 456  0  456 {} {} {}
  }
  do_preupdate_test 9.5 {
    INSERT INTO t2 DEFAULT VALUES;
  } {
    INSERT main t2 1 1  0  {} 1
  } 
  do_preupdate_test 9.6 {
    INSERT INTO t1 DEFAULT VALUES;
  } {
    INSERT main t1 458 458  0  458 {} {} {}
  } 
}


do_execsql_test 10.0 {
  CREATE TABLE t3(a, b INTEGER PRIMARY KEY);
}
do_preupdate_test 10.1 {
  INSERT INTO t3 DEFAULT VALUES
953
954
955
956
957
958
959



960























































961
960
961
962
963
964
965
966
967
968
969

970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025







+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

    preupdate {DELETE main sqlite_stat1 1 1}
    preupdate {DELETE main sqlite_stat1 2 2}
    preupdate {INSERT main sqlite_stat1 1 1}
    preupdate {INSERT main sqlite_stat1 2 2}
  }]
}

#-------------------------------------------------------------------------
# Test that the pre-update hook is fired for INSERT statements that use
# the xfer optimization on without rowid tables.

#
reset_db
do_execsql_test 12.1 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
  CREATE TABLE t2(a INTEGER PRIMARY KEY, b) WITHOUT ROWID;

  INSERT INTO t1 VALUES(1, 2);
  INSERT INTO t1 VALUES(3, 4);
  INSERT INTO t2 VALUES(5, 6);
  INSERT INTO t2 VALUES(7, 8);

  CREATE TABLE t3 (a INTEGER PRIMARY KEY, b) WITHOUT ROWID;
}

db preupdate hook preupdate_cb
db update_hook update_cb

proc preupdate_cb {args} { lappend ::res "preupdate" $args }
proc update_cb {args} { lappend ::res "update" $args }

set ::res [list]
do_test 12.2 {
  execsql VACUUM
  set ::res
} {}

do_test 12.3 {
  set ::res [list]
  execsql { INSERT INTO t3 SELECT a, b FROM t2 }
  set ::res
} {preupdate {INSERT main t3 0 0} preupdate {INSERT main t3 0 0}}

do_test 12.4 {
  execsql { DELETE FROM t3 }
  set ::res [list]
  execsql { INSERT INTO t3 SELECT * FROM t2 }
  set ::res
} {preupdate {INSERT main t3 0 0} preupdate {INSERT main t3 0 0}}

do_execsql_test 12.5 {
  CREATE TABLE t4(a COLLATE nocase PRIMARY KEY, b) WITHOUT ROWID;
  INSERT INTO t4 VALUES('abc', 1);
  INSERT INTO t4 VALUES('DEF', 2);
}

set ::res [list]
do_test 12.6 {
  execsql VACUUM
  set ::res
} {}

do_catchsql_test 12.6 {
  INSERT INTO t4 VALUES('def', 3);
} {1 {UNIQUE constraint failed: t4.a}}

finish_test

Changes to test/icu.test.

141
142
143
144
145
146
147


















148
149
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


  do_catchsql_test icu-5.5 {SELECT 'abc' REGEXP }   {1 {incomplete input}}
  do_catchsql_test icu-5.6 {SELECT 'abc' REGEXP, 1} {1 {near ",": syntax error}}
 
  do_malloc_test icu-6.10 -sqlbody {
    SELECT upper(char(0xfb04,0xdf,0xfb04,0xe8,0xfb04));
  }
}

# 2020-03-19
# The ESCAPE clause on LIKE takes precedence over wildcards
#
do_execsql_test idu-6.0 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(id INTEGER PRIMARY KEY, x TEXT);
  INSERT INTO t1 VALUES
    (1,'abcde'),
    (2,'abc_'),
    (3,'abc__'),
    (4,'abc%'),
    (5,'abc%%');
  SELECT id FROM t1 WHERE x LIKE 'abc%%' ESCAPE '%';
} {4}
do_execsql_test icu-6.1 {
  SELECT id FROM t1 WHERE x LIKE 'abc__' ESCAPE '_';
} {2}

finish_test

Changes to test/ieee754.test.

19
20
21
22
23
24
25
26
27


28
29
30
31
32
33
34
19
20
21
22
23
24
25


26
27
28
29
30
31
32
33
34







-
-
+
+








foreach {id float rep} {
   1       1.0                            1,0
   2       2.0                            2,0
   3       0.5                            1,-1
   4       1.5                            3,-1
   5       0.0                            0,-1075
   6       4.9406564584124654e-324        4503599627370497,-1075
   7       2.2250738585072009e-308        9007199254740991,-1075
   6       4.9406564584124654e-324        1,-1074
   7       2.2250738585072009e-308        4503599627370495,-1074
   8       2.2250738585072014e-308        1,-1022
} {
  do_test ieee754-100-$id-1 {
    db eval "SELECT ieee754($float);"
  } "ieee754($rep)"
  do_test ieee754-100-$id-2 {
    db eval "SELECT ieee754($rep)==$float;"

Changes to test/in.test.

277
278
279
280
281
282
283
284

285
286
287
288
289


290
291
292
293
294
295
296
277
278
279
280
281
282
283

284
285
286
287
288

289
290
291
292
293
294
295
296
297







-
+




-
+
+







    SELECT * FROM ta LEFT JOIN tb ON (ta.b=tb.b) WHERE ta.a IN ();
  }
} {}
do_test in-7.8.2 {
  db status step
} {0}

do_test in-8.1 {
do_test in-8.3 {
  execsql {
    SELECT b FROM t1 WHERE a IN ('hello','there')
  }
} {world}
do_test in-8.2 {
do_test in-8.4 {
  sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1
  execsql {
    SELECT b FROM t1 WHERE a IN ("hello",'there')
  }
} {world}

# Test constructs of the form:  expr IN tablename
#
328
329
330
331
332
333
334
335

336
337
338
339
340
341
342
329
330
331
332
333
334
335

336
337
338
339
340
341
342
343







-
+







    SELECT * FROM t5;
  }
} {111}
do_test in-10.2 {
  catchsql {
    INSERT INTO t5 VALUES(4);
  }
} {1 {CHECK constraint failed: t5}}
} {1 {CHECK constraint failed: a IN (111,222,333)}}

# Ticket #1821
#
# Type affinity applied to the right-hand side of an IN operator.
#
do_test in-11.1 {
  execsql {
646
647
648
649
650
651
652
653



























































































































































654
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
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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

do_execsql_test in-14.0 {
  CREATE TABLE c1(a);
  INSERT INTO c1 VALUES(1), (2), (4), (3);
}
do_execsql_test in-14.1 {
  SELECT * FROM c1 WHERE a IN (SELECT a FROM c1) ORDER BY 1
} {1 2 3 4}

# 2019-02-20 Ticket https://www.sqlite.org/src/tktview/df46dfb631f75694fbb97033b69
#
do_execsql_test in-15.0 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE IF NOT EXISTS t1(id INTEGER PRIMARY KEY);
  INSERT INTO t1 VALUES(1);
  SELECT a.id FROM t1 AS a JOIN t1 AS b ON a.id=b.id WHERE a.id IN (1,2,3);
} {1}
do_execsql_test in-15.1 {
  DROP TABLE IF EXISTS t2;
  CREATE TABLE t2(a INTEGER PRIMARY KEY,b);
  INSERT INTO t2 VALUES(1,11);
  INSERT INTO t2 VALUES(2,22);
  INSERT INTO t2 VALUES(3,33);
  SELECT b, a IN (3,4,5) FROM t2 ORDER BY b;
} {11 0 22 0 33 1}
do_execsql_test in-15.2 {
  DROP TABLE IF EXISTS t3;
  CREATE TABLE t3(x INTEGER PRIMARY KEY);
  INSERT INTO t3 VALUES(8);
  SELECT CASE WHEN x NOT IN (5,6,7) THEN 'yes' ELSE 'no' END FROM t3;
  SELECT CASE WHEN x NOT IN (NULL,6,7) THEN 'yes' ELSE 'no' END FROM t3;
} {yes no}
do_execsql_test in-15.3 {
  SELECT CASE WHEN x NOT IN (5,6,7) OR x=0 THEN 'yes' ELSE 'no' END FROM t3;
  SELECT CASE WHEN x NOT IN (NULL,6,7) OR x=0 THEN 'yes' ELSE 'no' END FROM t3;
} {yes no}
do_execsql_test in-15.4 {
  DROP TABLE IF EXISTS t4;
  CREATE TABLE t4(a INTEGER PRIMARY KEY, b INT);
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<20)
    INSERT INTO t4(a,b) SELECT x, x+100 FROM c;
  SELECT b FROM t4 WHERE a IN (3,null,8) ORDER BY +b;
} {103 108}
do_execsql_test in-15.5 {
  SELECT b FROM t4 WHERE a NOT IN (3,null,8);
} {}
do_execsql_test in-15.6 {
  DROP TABLE IF EXISTS t5;
  DROP TABLE IF EXISTS t6;
  CREATE TABLE t5(id INTEGER PRIMARY KEY, name TEXT);
  CREATE TABLE t6(id INTEGER PRIMARY KEY, name TEXT, t5_id INT);
  INSERT INTO t5 VALUES(1,'Alice'),(2,'Emma');
  INSERT INTO t6 VALUES(1,'Bob',1),(2,'Cindy',1),(3,'Dave',2);
  SELECT a.*
    FROM t5 AS 'a' JOIN t5 AS 'b' ON b.id=a.id
   WHERE b.id IN (
          SELECT t6.t5_id
            FROM t6
           WHERE name='Bob'
             AND t6.t5_id IS NOT NULL
             AND t6.id IN (
                  SELECT id
                    FROM (SELECT t6.id, count(*) AS x
                            FROM t6
                           WHERE name='Bob'
                         ) AS 't'
                   WHERE x=1
                 )
             AND t6.id IN (1,id)
         );
} {1 Alice}

#-------------------------------------------------------------------------
reset_db
do_execsql_test in-16.0 {
  CREATE TABLE x1(a, b);
  INSERT INTO x1(a) VALUES(1), (2), (3), (4), (5), (6);
  CREATE INDEX x1i ON x1(a, b);
}

do_execsql_test in-16.1 {
  SELECT * FROM x1 
  WHERE a IN (SELECT a FROM x1 WHERE (a%2)==0) 
  ORDER BY a DESC, b;
} {6 {} 4 {} 2 {}}

do_execsql_test in-16.2 {
  SELECT * FROM x1 
  WHERE a IN (SELECT a FROM x1 WHERE (a%7)==0) 
  ORDER BY a DESC, b;
} {}

# 2019-06-11
# https://www.sqlite.org/src/info/57353f8243c637c0
#
do_execsql_test in-17.1 {
  SELECT 1 IN ('1');
} 0
do_execsql_test in-17.2 {
  SELECT 1 IN ('1' COLLATE nocase);
} 0
do_execsql_test in-17.3 {
  SELECT 1 IN (CAST('1' AS text));
} 0
do_execsql_test in-17.4 {
  SELECT 1 IN (CAST('1' AS text) COLLATE nocase);
} 0

# 2019-08-27 ticket https://sqlite.org/src/info/dbaf8a6820be1ece
# 
do_execsql_test in-18.1 {
  DROP TABLE IF EXISTS t0;
  CREATE TABLE t0(c0 INT UNIQUE);
  INSERT INTO t0(c0) VALUES (1);
  SELECT * FROM t0 WHERE '1' IN (t0.c0);
} {}

# 2019-09-02 ticket https://www.sqlite.org/src/info/2841e99d104c6436
# For the IN_INDEX_NOOP optimization, apply REAL affinity to the LHS
# values prior to comparison if the RHS has REAL affinity.
#
# Also ticket https://sqlite.org/src/info/29f635e0af71234b
#
do_execsql_test in-19.10 {
  DROP TABLE IF EXISTS t0;
  CREATE TABLE t0(c0 REAL UNIQUE);
  INSERT INTO t0(c0) VALUES(2.0625E00);
  SELECT 1 FROM t0 WHERE c0 IN ('2.0625');
} {1}
do_execsql_test in-19.20 {
  SELECT c0 IN ('2.0625') FROM t0;
} {1}
do_execsql_test in-19.21 {
  SELECT c0 = ('2.0625') FROM t0;
} {1}
do_execsql_test in-19.22 {
  SELECT c0 = ('0.20625e+01') FROM t0;
} {1}
do_execsql_test in-19.30 {
  SELECT c0 IN ('2.0625',2,3) FROM t0;
} {1}
do_execsql_test in-19.40 {
  DROP TABLE t0;
  CREATE TABLE t0(c0 TEXT, c1 REAL, c2, PRIMARY KEY(c2, c0, c1));
  CREATE INDEX i0 ON t0(c1 IN (c0));
  INSERT INTO t0(c0, c2) VALUES (0, NULL) ON CONFLICT(c2, c1, c0) DO NOTHING;
  PRAGMA integrity_check;
} {ok}

# Ticket f3ff1472887
#
do_execsql_test in-20.1 {
  SELECT (1 IN (2 IS TRUE));
} {1}

# Forum post: https://sqlite.org/forum/forumpost/5782619992.
#
reset_db
do_execsql_test in-21.1 {
  CREATE TABLE t0(c0);
  SELECT COUNT(*) FROM t0 ORDER BY (t0.c0 IN ());
} {0}


finish_test

Changes to test/in4.test.

9
10
11
12
13
14
15

16
17
18
19
20
21
22
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23







+







#
#***********************************************************************
#
# $Id: in4.test,v 1.4 2009/06/05 17:09:12 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix in4

do_test in4-1.1 {
  execsql {
    CREATE TABLE t1(a, b);
    CREATE INDEX i1 ON t1(a);
  }
} {}
222
223
224
225
226
227
228



229
230
231
232




233
234
235
236
237
238
239
223
224
225
226
227
228
229
230
231
232




233
234
235
236
237
238
239
240
241
242
243







+
+
+
-
-
-
-
+
+
+
+







do_execsql_test in4-3.42 {
  EXPLAIN
  SELECT * FROM t3 WHERE x IN (10,11);
} {/OpenEphemeral/}
do_execsql_test in4-3.43 {
  SELECT * FROM t3 WHERE x IN (10);
} {10 10 10}

# This test would verify that the "X IN (Y)" -> "X==Y" optimization
# was working.  But we have now taken that optimization out.
do_execsql_test in4-3.44 {
  EXPLAIN
  SELECT * FROM t3 WHERE x IN (10);
} {~/OpenEphemeral/}
#do_execsql_test in4-3.44 {
#  EXPLAIN
#  SELECT * FROM t3 WHERE x IN (10);
#} {~/OpenEphemeral/}
do_execsql_test in4-3.45 {
  SELECT * FROM t3 WHERE x NOT IN (10,11,99999);
} {1 1 1}
do_execsql_test in4-3.46 {
  EXPLAIN
  SELECT * FROM t3 WHERE x NOT IN (10,11,99999);
} {/OpenEphemeral/}
322
323
324
325
326
327
328
329

330
331
332
333
334
335
336
337







338











































































































































































339
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







-
+








+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  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/}
} {~/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/}

reset_db
do_execsql_test 7.0 {
  CREATE TABLE t1(a, b, c);
  CREATE TABLE t2(d, e);
  CREATE INDEX t1bc ON t1(c, b);
  INSERT INTO t2(e) VALUES(1);
  INSERT INTO t1 VALUES(NULL, NULL, NULL);

}

do_execsql_test 7.1 {
  SELECT * FROM t2 LEFT JOIN t1 ON c = d AND b IN (10,10,10);
} {{} 1 {} {} {}}

ifcapable rtree {
  reset_db
  do_execsql_test 7.2 {
    CREATE VIRTUAL TABLE t1 USING rtree(a, b, c);
    CREATE TABLE t2(d INTEGER, e INT);
    INSERT INTO t2(e) VALUES(1);
  }

  do_execsql_test 7.3 {
    SELECT * FROM t2 LEFT JOIN t1 ON c IN (d) AND b IN (10,10,10);
  } {{} 1 {} {} {}}
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 8.0 {
  CREATE TABLE t1(x INTEGER PRIMARY KEY, y);
  CREATE UNIQUE INDEX t1y ON t1(y);
  INSERT INTO t1 VALUES(111, 'AAA'),(222, 'BBB'),(333, 'CCC');
  CREATE TABLE t2(z);
  INSERT INTO t2 VALUES('BBB'),('AAA');
  ANALYZE sqlite_schema;
  INSERT INTO sqlite_stat1 VALUES('t1', 't1y','100 1');
}

db close
sqlite3 db test.db

do_execsql_test 8.1 {
  SELECT t1.x FROM t2 CROSS JOIN t1 WHERE t2.z = t1.y;
} {222 111}

do_execsql_test 8.2 {
  SELECT t1.x FROM t2 CROSS JOIN t1 WHERE t2.z = t1.y AND +t1.x IN (111, 222);
} {222 111}

do_execsql_test 8.3 {
  SELECT t1.x FROM t2 CROSS JOIN t1 WHERE t2.z = t1.y AND t1.x IN (111, 222);
} {222 111}

# 2021-06-02 forum post https://sqlite.org/forum/forumpost/b4fcb8a598
# OP_SeekScan changes from check-in 4a43430fd23f8835 on 2020-09-30 causes
# performance regression.
#
reset_db
do_execsql_test 9.0 {
  CREATE TABLE node(node_id INTEGER PRIMARY KEY);
  CREATE TABLE edge(node_from INT, node_to INT);
  CREATE TABLE sub_nodes(node_id INTEGER PRIMARY KEY);
  CREATE INDEX edge_from_to ON edge(node_from,node_to);
  CREATE INDEX edge_to_from ON edge(node_to,node_from);
  ANALYZE;
  DELETE FROM sqlite_stat1;
  INSERT INTO sqlite_stat1 VALUES
    ('sub_nodes',NULL,'1000000'),
    ('edge','edge_to_from','20000000 2 2'),
    ('edge','edge_from_to','20000000 2 2'),
    ('node',NULL,'10000000');
  ANALYZE sqlite_schema;
} {}
do_eqp_test 9.1 {
SELECT count(*) FROM edge
 WHERE node_from IN sub_nodes AND node_to IN sub_nodes;
} {
  QUERY PLAN
  |--SEARCH edge USING COVERING INDEX edge_to_from (node_to=?)
  |--USING ROWID SEARCH ON TABLE sub_nodes FOR IN-OPERATOR
  `--USING ROWID SEARCH ON TABLE sub_nodes FOR IN-OPERATOR
}
# ^^^^^ the key to the above is that the index should only use a single
#       term (node_to=?), not two terms (node_to=? AND node_from=).

# dbsqlfuzz case
#
reset_db
do_execsql_test 10.0 {
  CREATE TABLE t1(a,b,c,d,PRIMARY KEY(a,b,c)) WITHOUT ROWID;
  INSERT INTO t1(a,b,c,d) VALUES
    (0,-2,2,3),
    (0,2,3,4),
    (0,5,8,10),
    (1,7,11,13);
  ANALYZE sqlite_schema;
  INSERT INTO sqlite_stat1 VALUES('t1','t1','10 3 2 1');
  ANALYZE sqlite_schema;
  PRAGMA reverse_unordered_selects(1);
  SELECT d FROM t1 WHERE 0=a AND b IN (-17,-4,-3,1,5,25,7798);
} {10}

# 2021-06-13 dbsqlfuzz e41762333a4d6e90a49e628f488d0873b2dba4c5
# The opcode that preceeds OP_SeekScan is usually OP_IdxGT, but can
# sometimes be OP_IdxGE
#
reset_db
do_execsql_test 11.0 {
  CREATE TABLE t1(a TEXT, b INT, c INT, d INT);
  INSERT INTO t1 VALUES('abc',123,4,5);
  INSERT INTO t1 VALUES('xyz',1,'abcdefxyz',99);
  CREATE INDEX t1abc ON t1(b,b,c);
  ANALYZE sqlite_schema;
  INSERT INTO sqlite_stat1 VALUES('t1','t1abc','10000 5 00 2003 10');
  ANALYZE sqlite_schema;
} {}
do_execsql_test 11.1 {
  SELECT * FROM t1
   WHERE b IN (345, (SELECT 1 FROM t1 
                      WHERE b IN (345 NOT GLOB 510)
                        AND c GLOB 'abc*xyz'))
     AND c BETWEEN 'abc' AND 'xyz';
} {xyz 1 abcdefxyz 99}
do_execsql_test 11.2 {
  EXPLAIN SELECT * FROM t1
   WHERE b IN (345, (SELECT 1 FROM t1 
                      WHERE b IN (345 NOT GLOB 510)
                        AND c GLOB 'abc*xyz'))
     AND c BETWEEN 'abc' AND 'xyz';
} {/ SeekScan /}

# 2021-06-25 ticket 6dcbfd11cf666e21
# Another problem with OP_SeekScan
#
reset_db
do_execsql_test 12.0 {
  CREATE TABLE t1(a,b,c);
  CREATE INDEX t1abc ON t1(a,b,c);
  CREATE INDEX t1bca on t1(b,c,a);
  INSERT INTO t1 VALUES(56,1119,1115);
  INSERT INTO t1 VALUES(57,1147,1137);
  INSERT INTO t1 VALUES(100,1050,1023);
  INSERT INTO t1 VALUES(101,1050,1023);
  ANALYZE sqlite_schema;
  INSERT INTO sqlite_stat1 VALUES('t1','t1abc','358677 2 2 1');
  INSERT INTO sqlite_stat1 VALUES('t1','t1bca','358677 4 2 1');
  ANALYZE sqlite_schema;
  SELECT * FROM t1 NOT INDEXED
   WHERE (b = 1137 AND c IN (97, 98))
      OR (b = 1119 AND c IN (1115, 1023));
} {56 1119 1115}
do_execsql_test 12.1 {
  SELECT * FROM t1
   WHERE (b = 1137 AND c IN (97, 98))
      OR (b = 1119 AND c IN (1115, 1023));
} {56 1119 1115}

# 2021-11-02 ticket 5981a8c041a3c2f3
# Another OP_SeekScan problem.
#
reset_db
do_execsql_test 13.0 {
  CREATE TABLE t1(id INTEGER PRIMARY KEY, a INT, b INT, c INT);
  INSERT INTO t1 VALUES(10,1,2,5);
  INSERT INTO t1 VALUES(20,1,3,5);
  INSERT INTO t1 VALUES(30,1,2,4);
  INSERT INTO t1 VALUES(40,1,3,4);
  ANALYZE sqlite_master;
  INSERT INTO sqlite_stat1 VALUES('t1','t1x','84000 3 2 1');
  CREATE INDEX t1x ON t1(a,b,c);
  PRAGMA writable_schema=RESET;
  SELECT * FROM t1
   WHERE a=1
     AND b IN (2,3)
     AND c BETWEEN 4 AND 5
   ORDER BY +id;
} {10 1 2 5 20 1 3 5 30 1 2 4 40 1 3 4}

finish_test

Changes to test/in5.test.

244
245
246
247
248
249
250

















251
252
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


  CREATE TABLE t9(a INTEGER PRIMARY KEY);
  INSERT INTO t9 VALUES (44), (45);
}
do_execsql_test 9.1 {
  SELECT * FROM t9 WHERE a IN (44, 45, 44, 45)
} {44 45}

#-------------------------------------------------------------------------
# Test that ticket c7a117190 is fixed.
#
reset_db
do_execsql_test 9.0 {
  CREATE TABLE t0(c0);
  CREATE VIEW v0(c0) AS SELECT LOWER(CAST('1e500' AS TEXT)) FROM t0;
  INSERT INTO t0(c0) VALUES (NULL);
}

do_execsql_test 9.1 {
  SELECT lower('1e500') FROM t0 WHERE rowid NOT IN (0, 0, lower('1e500'));
} {1e500}

do_execsql_test 9.2 {
  SELECT lower('1e500') FROM t0 WHERE rowid != lower('1e500');
} {1e500}

finish_test

Changes to test/in6.test.

73
74
75
76
77
78
79







































80
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  SELECT d, f FROM t1 LEFT JOIN t2 ON (e=d)
  WHERE a=100
    AND b IN (200,201,202,204)
    AND c IN (300,302,301,305)
  ORDER BY +d;
} {1 {} 2 {} 3 {} 4 {} 5 {} 8 {} 9 {}}

# 2020-03-16 ticket 82b588d342d515d1
# Ensure that the IN-early-out optimization works with LEFT JOINs
#
reset_db
do_execsql_test in6-3.100 {
  CREATE TABLE t1(a);
  INSERT INTO t1 VALUES(0);
  CREATE TABLE t2(b, c, d);
  INSERT INTO t2(b,c,d) VALUES(4,5,3),(4,5,4),(4,5,8);
  CREATE INDEX t2bcd ON t2(b, c, d);
  SELECT * FROM t1 LEFT JOIN t2 ON b=NULL AND c=5 AND d IN (2,3,4);
} {0 {} {} {}}
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/incrblob3.test.

9
10
11
12
13
14
15






16
17
18
19
20
21
22
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28







+
+
+
+
+
+







#
#***********************************************************************
#
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix incrblob3

ifcapable !incrblob {
  finish_test
  return
}

sqlite3 db test.db
sqlite3_db_config_lookaside db 0 0 0

do_execsql_test incrblob3-1.1 {
  CREATE TABLE blobs(k INTEGER PRIMARY KEY, v BLOB);
  INSERT INTO blobs VALUES(1, zeroblob(100));
264
265
266
267
268
269
270





































271
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  sqlite3 db test.db 
  sqlite3_db_config_lookaside db 0 0 0
  list [catch {db incrblob blobs v 1} msg] $msg
} {1 {database schema has changed}}
db close
tvfs delete

#-------------------------------------------------------------------------
#
reset_db
forcedelete test.db2
do_execsql_test 8.1 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
  ATTACH 'test.db2' AS aux;
  CREATE TABLE aux.t1(a INTEGER PRIMARY KEY, b);

  INSERT INTO t1 VALUES(4, 'hello');
  INSERT INTO aux.t1 VALUES(4, 'world');
}

do_test 8.2 {
  set ::blob [db incrblob -readonly main t1 b 4]
  read $::blob
} {hello}
close $::blob

do_test 8.3 {
  set ::blob [db incrblob -readonly aux t1 b 4]
  read $::blob
} {world}
close $::blob

do_test 8.4 {
  set ::blob [db incrblob -readonly t1 b 4]
  read $::blob
} {hello}
close $::blob

do_test 8.5 {
  list [catch { db incrblob -readonly nosuchdb t1 b 4 } msg] $msg
} {1 {no such table: nosuchdb.t1}}


db close
finish_test

Changes to test/incrblobfault.test.

9
10
11
12
13
14
15





16
17
18
19
20
21
22
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27







+
+
+
+
+







#
#***********************************************************************
#
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable !incrblob {
  finish_test
  return
}

set testprefix incrblobfault

do_execsql_test 1.0 {
  CREATE TABLE blob(x INTEGER PRIMARY KEY, v BLOB);
  INSERT INTO blob VALUES(1, 'hello world');
  INSERT INTO blob VALUES(2, 'world hello');

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/index.test.

424
425
426
427
428
429
430
431

432
433
434
435
436
437
438
424
425
426
427
428
429
430

431
432
433
434
435
436
437
438







-
+







   );
   INSERT INTO t5 VALUES(1,2,3);
   SELECT * FROM t5;
  }
} {1 2.0 3}
do_test index-13.2 {
  set ::idxlist [execsql {
    SELECT name FROM sqlite_master WHERE type="index" AND tbl_name="t5";
    SELECT name FROM sqlite_master WHERE type='index' AND tbl_name='t5';
  }]
  llength $::idxlist
} {3}
for {set i 0} {$i<[llength $::idxlist]} {incr i} {
  do_test index-13.3.$i {
    catchsql "
      DROP INDEX '[lindex $::idxlist $i]';
734
735
736
737
738
739
740









741


















742
743
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







+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


     CREATE TEMP TABLE t6(x);
     INSERT INTO temp.t6 values(1),(5),(9);
     CREATE INDEX temp.i21 ON t6(x);
     SELECT x FROM t6 ORDER BY x DESC;
  }
} {0 {9 5 1}}

# 2019-05-01 ticket https://www.sqlite.org/src/info/3be1295b264be2fa
do_execsql_test index-22.0 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a, b TEXT);
  CREATE UNIQUE INDEX IF NOT EXISTS x1 ON t1(b==0);
  CREATE INDEX IF NOT EXISTS x2 ON t1(a || 0) WHERE b;
  INSERT INTO t1(a,b) VALUES('a',1),('a',0);
  SELECT a, b, '|' FROM t1;
} {a 1 | a 0 |}
   

# 2019-05-10 ticket https://www.sqlite.org/src/info/ae0f637bddc5290b
do_execsql_test index-23.0 {
  DROP TABLE t1;
  CREATE TABLE t1(a TEXT, b REAL);
  CREATE UNIQUE INDEX t1x1 ON t1(a GLOB b);
  INSERT INTO t1(a,b) VALUES('0.0','1'),('1.0','1');
  SELECT * FROM t1;
  REINDEX;
} {0.0 1.0 1.0 1.0}
do_execsql_test index-23.1 {
  DROP TABLE t1;
  CREATE TABLE t1(a REAL);
  CREATE UNIQUE INDEX index_0 ON t1(TYPEOF(a));
  INSERT OR IGNORE INTO t1(a) VALUES (0.1),(FALSE);
  SELECT * FROM t1;
  REINDEX;
} {0.1}

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 .*/}
ifcapable stat4||stat3 {
} {/(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=?) LEFT-JOIN
}

do_execsql_test index6-8.2 {
  SELECT * FROM t8a LEFT JOIN t8b ON (x = 'value' AND y = a)
} {
  1 one value 1 
  2 two {} {} 
406
407
408
409
410
411
412






















































































































413
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  SELECT 'one', * FROM t2 WHERE x NOT IN (SELECT a FROM t1);
  CREATE INDEX t1a ON t1(a) WHERE b=1;
  SELECT 'two', * FROM t2 WHERE x NOT IN (SELECT a FROM t1);
} {}
do_execsql_test index6-12.2 {
  SELECT x FROM t2 WHERE x IN (SELECT a FROM t1) ORDER BY +x;
} {1 2}

# 2019-05-04
# Ticket https://www.sqlite.org/src/tktview/5c6955204c392ae763a95
# Theorem prover error
#
do_execsql_test index6-13.1 {
  DROP TABLE IF EXISTS t0;
  CREATE TABLE t0(c0);
  CREATE INDEX index_0 ON t0(c0) WHERE c0 NOT NULL;
  INSERT INTO t0(c0) VALUES (NULL);
  SELECT * FROM t0 WHERE c0 OR 1;
} {{}}

# 2019-05-11
# Ticket https://sqlite.org/src/tktview/8025674847
reset_db
do_execsql_test index6-14.1 {
  CREATE TABLE IF NOT EXISTS t0 (c0, c1);
  CREATE INDEX IF NOT EXISTS i0 ON t0(c0, c1) WHERE c0 NOT NULL;
  INSERT INTO t0(c0, c1) VALUES(NULL, 'row');
  SELECT * FROM t0 WHERE t0.c0 IS NOT 1;
} {{} row}

do_execsql_test index6-14.2 {
  SELECT * FROM t0 WHERE CASE c0 WHEN 0 THEN 0 ELSE 1 END;
} {{} row}

# 2019-08-30
# Ticket https://www.sqlite.org/src/info/a6408d42b9f44462
# Ticket https://www.sqlite.org/src/info/fba33c8b1df6a915
# https://sqlite.org/src/info/bac716244fddac1fe841
#
do_execsql_test index6-15.1 {
  DROP TABLE t0;
  CREATE TABLE t0(c0);
  INSERT INTO t0(c0) VALUES (NULL);
  CREATE INDEX i0 ON t0(1) WHERE c0 NOT NULL;
  SELECT 1 FROM t0 WHERE (t0.c0 IS FALSE) IS FALSE;
} {1}
do_execsql_test index6-15.2 {
  SELECT 1 FROM t0 WHERE (t0.c0 IS FALSE) BETWEEN FALSE AND TRUE;
} {1}
do_execsql_test index6-15.3 {
  SELECT 1 FROM t0 WHERE TRUE BETWEEN (t0.c0 IS FALSE) AND TRUE;
} {1}
do_execsql_test index6-15.4 {
  SELECT 1 FROM t0 WHERE FALSE BETWEEN FALSE AND (t0.c0 IS FALSE);
} {1}
do_execsql_test index6-15.5 {
  SELECT 1 FROM t0 WHERE (c0 IS FALSE) IN (FALSE);
} {1}

# 2019-09-03
# Ticket https://sqlite.org/src/info/767a8cbc6d20bd68
do_execsql_test index6-16.1 {
  DROP TABLE t0;
  CREATE TABLE t0(c0 COLLATE NOCASE, c1);
  CREATE INDEX i0 ON t0(0) WHERE c0 >= c1;
  INSERT INTO t0 VALUES('a', 'B');
  SELECT c1 <= c0, c0 >= c1 FROM t0;
} {1 0}
do_execsql_test index6-16.2 {
  SELECT 2 FROM t0 WHERE c0 >= c1;
} {}
do_execsql_test index6-16.3 {
  SELECT 3 FROM t0 WHERE c1 <= c0;
} {3}

# 2019-11-02
# Ticket https://sqlite.org/src/tktview/a9efb42811fa41ee286e8
db close
sqlite3 db :memory:
do_execsql_test index6-17.1 {
  CREATE TABLE t0(c0);
  CREATE INDEX i0 ON t0(0) WHERE c0 GLOB c0;
  INSERT INTO t0 VALUES (0);
  CREATE UNIQUE INDEX i1 ON t0(0);
  PRAGMA integrity_check;
} {ok}
do_execsql_test index6-17.2 {
  CREATE UNIQUE INDEX i2 ON t0(0);
  REPLACE INTO t0 VALUES(0);
  PRAGMA integrity_check;
} {ok}
do_execsql_test index6-17.3 {
  SELECT COUNT(*) FROM t0 WHERE t0.c0 GLOB t0.c0;
} {1}

# 2021-05-29
# Forum https://sqlite.org/forum/forumpost/d813704d7c
reset_db
do_execsql_test index6-18.1 {
  CREATE TABLE t1(a INT, b INT);
  INSERT INTO t1 VALUES(10,10);
  CREATE UNIQUE INDEX t1b ON t1(b) WHERE a>NULL;
  SELECT * FROM t1 WHERE a IS NOT NULL;
} {10 10}

# 2022-06-09
# https://sqlite.org/forum/forumpost/c4676c4956
# Cannot do a scan of a partial index on the left table of a RIGHT JOIN
# since that will cause extra rows to appear in the output during the
# right-join no-match loop.  The following testcase is verify using
# PostgreSQL 14.
#
reset_db
do_execsql_test index6-19.1 {
  CREATE TABLE t1(a INT, b INT);
  INSERT INTO t1(a) VALUES(2);
  CREATE TABLE t2(c INT);
  CREATE INDEX i0 ON t2(c) WHERE c=3;
  CREATE TABLE t3(d INT);
  INSERT INTO t3 VALUES(1);
}
do_execsql_test index6-19.2 {
  SELECT * FROM t2 RIGHT JOIN t3 ON d<>0 LEFT JOIN t1 ON c=3 WHERE t1.a<>0;
} {}

finish_test

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 {
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
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







-
+















-
-
+
+





-
+






-
+






-
+







    CREATE INDEX t1c ON t1(c);
    ANALYZE;
    SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
    PRAGMA integrity_check;
  }
} {t1 {15 1} t1a {10 1} t1b {8 1} t1c {15 1} ok}

# Queries use partial indices as appropriate times.
# Queries use partial indices at appropriate times.
#
do_test index7-2.1 {
  execsql {
    CREATE TABLE t2(a,b PRIMARY KEY) without rowid;
    INSERT INTO t2(a,b) SELECT value, value FROM nums WHERE value<1000;
    UPDATE t2 SET a=NULL WHERE b%5==0;
    CREATE INDEX t2a1 ON t2(a) WHERE a IS NOT NULL;
    SELECT count(*) FROM t2 WHERE a IS NOT NULL;
  }
} {800}
do_test index7-2.2 {
  execsql {
    EXPLAIN QUERY PLAN
    SELECT * FROM t2 WHERE a=5;
  }
} {/.* TABLE t2 USING COVERING INDEX t2a1 .*/}
ifcapable stat4||stat3 {
} {/(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
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355







-
+





+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  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);
  INSERT INTO t6 VALUES(1, 1);
  INSERT INTO t6 VALUES(0, 0);
  SELECT * FROM t6 WHERE y IS TRUE ORDER BY x;
} {1 1}

do_execsql_test index7-7.1 {
  CREATE INDEX i6 ON t6(x) WHERE y IS NOT TRUE;
  SELECT * FROM t6 WHERE y IS TRUE ORDER BY x;
} {1 1}

# 2020-05-27.  tag-20200527-1.
# Incomplete stat1 information on a table with few rows should still use the
# index.
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 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/index9.test.

30
31
32
33
34
35
36

37
38
39
40
41
42
43
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44







+







  uplevel [list do_test $tn [list sqluses $sql] $objects]
}

do_execsql_test 1.0 {
  CREATE TABLE t1(x, y);
  CREATE INDEX t1x ON t1(x) WHERE y=45;
}
unset -nocomplain a
set y [expr 45]
do_sqluses_test 1.1 { SELECT * FROM t1 WHERE x=? AND y=$y } {t1 t1x}
set y [expr 45.1]
do_sqluses_test 1.2 { SELECT * FROM t1 WHERE x=? AND y=$y } {t1}
set y [expr 44]
do_sqluses_test 1.3 { SELECT * FROM t1 WHERE x=? AND y=$y } {t1}
unset -nocomplain y

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.
#
86
87
88
89
90
91
92
93
94
95



96
97
98

99
100
101
102
103
104
105
86
87
88
89
90
91
92



93
94
95
96
97

98
99
100
101
102
103
104
105







-
-
-
+
+
+


-
+







# EVIDENCE-OF: R-15800-25719 If index-name does not exist or cannot be
# used for the query, then the preparation of the SQL statement fails.
#
do_test indexedby-2.4 {
  catchsql { SELECT * FROM t1 INDEXED BY i3 WHERE a = 'one' AND b = 'two'}
} {1 {no such index: i3}}

# EVIDENCE-OF: R-62112-42456 If the query optimizer is unable to use the
# index specified by the INDEX BY clause, then the query will fail with
# an error.
# EVIDENCE-OF: R-05301-32681 If the query optimizer is unable to use the
# index specified by the INDEXED BY clause, then the query will fail
# with an error.
do_test indexedby-2.4.1 {
  catchsql { SELECT b FROM t1 INDEXED BY i1 WHERE b = 'two' }
} {1 {no query solution}}
} {0 {}}

do_test indexedby-2.5 {
  catchsql { SELECT * FROM t1 INDEXED BY i5 WHERE a = 'one' AND b = 'two'}
} {1 {no such index: i5}}
do_test indexedby-2.6 {
  catchsql { SELECT * FROM t1 INDEXED BY WHERE a = 'one' AND b = 'two'}
} {1 {near "WHERE": syntax 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
274
275
276
277
278
279
280
281
282
283
284
285
286
287

288
289
290

291
292
293
294
295
296
297
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







-
+


-
+


-
+




-
+


-
+


-
+


-
+









-
+


-
+


-
+










-
-
+
+





-
-
+
+





-
+




-
+








-
+


-
+








-
+











-
+


-
+









-
+


-
+


-
+


-
+


-
+


-
+





-
+


-
+


-
+


-
+


-
+


-
+

















-
+


-
+







# 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' }
} {1 {no query solution}}
} {0 {}}
do_test indexedby-3.5 {
  catchsql { SELECT * FROM t1 INDEXED BY i2 ORDER BY a }
} {1 {no query solution}}
} {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 }
} {1 {no query solution}}
} {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 t2
  `--SEARCH TABLE t1 USING INDEX i1 (a=?)
  |--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
  }
} {1 {no query solution}}
} {0 {}}
do_test indexedby-4.4 {
  catchsql {
    SELECT * FROM t2 INDEXED BY i3, t1 INDEXED BY i1 WHERE a=c
  }
} {1 {no query solution}}
} {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 }
} {1 {no query solution}}
} {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}
} {1 {no query solution}}
} {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}
} {1 {no query solution}}
} {0 {}}

# Test that bug #3560 is fixed.
#
do_test indexedby-9.1 {
  execsql {
    CREATE TABLE maintable( id integer);
    CREATE TABLE joinme(id_int integer, id_text text);
    CREATE INDEX joinme_id_text_idx on joinme(id_text);
    CREATE INDEX joinme_id_int_idx on joinme(id_int);
  }
} {}
do_test indexedby-9.2 {
  catchsql {
    select * from maintable as m inner join
    joinme as j indexed by joinme_id_text_idx
    on ( m.id  = j.id_int)
  }
} {1 {no query solution}}
} {0 {}}
do_test indexedby-9.3 {
  catchsql { select * from maintable, joinme INDEXED by joinme_id_text_idx }
} {1 {no query solution}}
} {0 {}}

# Make sure we can still create tables, indices, and columns whose name
# is "indexed".
#
do_test indexedby-10.1 {
  execsql {
    CREATE TABLE indexed(x,y);
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.

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
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







+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+










-
+






-
+







} {2 3 5}
do_execsql_test indexexpr1-150eqp {
  EXPLAIN QUERY PLAN
  SELECT rowid FROM t1 WHERE substr(a,b,3) IN ('and','l_t','xyz')
   ORDER BY +rowid;
} {/USING INDEX t1abx/}

ifcapable altertable {
do_execsql_test indexexpr1-160 {
  ALTER TABLE t1 ADD COLUMN d;
  UPDATE t1 SET d=length(a);
  CREATE INDEX t1a2 ON t1(SUBSTR(a, 27, 3)) WHERE d>=29;
  SELECT rowid, b, c FROM t1
   WHERE substr(a,27,3)=='ord' AND d>=29;
} {1 1 1}
do_execsql_test indexexpr1-160eqp {
  EXPLAIN QUERY PLAN
  SELECT rowid, b, c FROM t1
   WHERE substr(a,27,3)=='ord' AND d>=29;
} {/USING INDEX t1a2/}
  do_execsql_test indexexpr1-160 {
    ALTER TABLE t1 ADD COLUMN d;
    UPDATE t1 SET d=length(a);
    CREATE INDEX t1a2 ON t1(SUBSTR(a, 27, 3)) WHERE d>=29;
    SELECT rowid, b, c FROM t1
      WHERE substr(a,27,3)=='ord' AND d>=29;
  } {1 1 1}
  do_execsql_test indexexpr1-160eqp {
    EXPLAIN QUERY PLAN
      SELECT rowid, b, c FROM t1
      WHERE substr(a,27,3)=='ord' AND d>=29;
  } {/USING INDEX t1a2/}
}

# ORDER BY using an indexed expression
#
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),
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
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







+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+








-
+







} {2 3 5}
do_execsql_test indexexpr1-250eqp {
  EXPLAIN QUERY PLAN
  SELECT id FROM t1 WHERE substr(a,b,3) IN ('and','l_t','xyz')
   ORDER BY +id;
} {/USING INDEX t1abx/}

ifcapable altertable {
do_execsql_test indexexpr1-260 {
  ALTER TABLE t1 ADD COLUMN d;
  UPDATE t1 SET d=length(a);
  CREATE INDEX t1a2 ON t1(SUBSTR(a, 27, 3)) WHERE d>=29;
  SELECT id, b, c FROM t1
   WHERE substr(a,27,3)=='ord' AND d>=29;
} {1 1 1}
do_execsql_test indexexpr1-260eqp {
  EXPLAIN QUERY PLAN
  SELECT id, b, c FROM t1
   WHERE substr(a,27,3)=='ord' AND d>=29;
} {/USING INDEX t1a2/}
  do_execsql_test indexexpr1-260 {
    ALTER TABLE t1 ADD COLUMN d;
    UPDATE t1 SET d=length(a);
    CREATE INDEX t1a2 ON t1(SUBSTR(a, 27, 3)) WHERE d>=29;
    SELECT id, b, c FROM t1
      WHERE substr(a,27,3)=='ord' AND d>=29;
  } {1 1 1}
  do_execsql_test indexexpr1-260eqp {
    EXPLAIN QUERY PLAN
      SELECT id, b, c FROM t1
      WHERE substr(a,27,3)=='ord' AND d>=29;
  } {/USING INDEX t1a2/}
}


do_catchsql_test indexexpr1-300 {
  CREATE TABLE t2(a,b,c); INSERT INTO t2 VALUES(1,2,3);
  CREATE INDEX t2x1 ON t2(a,b+random());
} {1 {non-deterministic functions prohibited in index expressions}}
do_catchsql_test indexexpr1-301 {
  CREATE INDEX t2x1 ON t2(julianday('now',a));
} {1 {non-deterministic function in index expression or CHECK constraint}}
} {1 {non-deterministic use of julianday() in an index}}
do_catchsql_test indexexpr1-310 {
  CREATE INDEX t2x2 ON t2(a,b+(SELECT 15));
} {1 {subqueries prohibited in index expressions}}
do_catchsql_test indexexpr1-320 {
  CREATE TABLE e1(x,y,UNIQUE(y,substr(x,1,5)));
} {1 {expressions prohibited in PRIMARY KEY and UNIQUE constraints}}
do_catchsql_test indexexpr1-330 {
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
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







-
+













-
+






-
+



-
+



+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  REPLACE INTO t1500(a,b) VALUES(1,3);  -- formerly caused assertion fault
  SELECT * FROM t1500;
} {1 3}

# 2018-01-03 OSSFuzz discovers another test case for the same problem
# above.
#
do_execsql_test indexexpr-1510 {
do_execsql_test indexexpr1-1510 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a PRIMARY KEY,b UNIQUE);
  REPLACE INTO t1 VALUES(2, 1);
  REPLACE INTO t1 SELECT 6,1;
  CREATE INDEX t1aa ON t1(a-a);
  REPLACE INTO t1 SELECT a, randomblob(a) FROM t1
} {}

# 2018-01-31 https://www.sqlite.org/src/tktview/343634942dd54ab57b702411
# When an index on an expression depends on the string representation of
# a numeric table column, trouble can arise since there are multiple
# string that can map to the same numeric value.  (Ex: 123, 0123, 000123).
#
do_execsql_test indexexpr-1600 {
do_execsql_test indexexpr1-1600 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1 (a INTEGER, b);
  CREATE INDEX idx1 ON t1 (lower(a));
  INSERT INTO t1 VALUES('0001234',3);
  PRAGMA integrity_check;
} {ok}
do_execsql_test indexexpr-1610 {
do_execsql_test indexexpr1-1610 {
  INSERT INTO t1 VALUES('1234',0),('001234',2),('01234',1);
  SELECT b FROM t1 WHERE lower(a)='1234' ORDER BY +b;
} {0 1 2 3}
do_execsql_test indexexpr-1620 {
do_execsql_test indexexpr1-1620 {
  SELECT b FROM t1 WHERE lower(a)='01234' ORDER BY +b;
} {}

# 2019-08-09 https://www.sqlite.org/src/info/9080b6227fabb466
# ExprImpliesExpr theorem prover bug:
# "(NULL IS FALSE) IS FALSE" does not imply "NULL IS NULL"

#
do_execsql_test indexexpr1-1700 {
  DROP TABLE IF EXISTS t0;
  CREATE TABLE t0(c0);
  INSERT INTO t0(c0) VALUES (0);
  CREATE INDEX i0 ON t0(NULL > c0) WHERE (NULL NOT NULL);
  SELECT * FROM t0 WHERE ((NULL IS FALSE) IS FALSE);
} {0}

# 2019-09-02 https://www.sqlite.org/src/tktview/57af00b6642ecd6848
# When the expression of an an index-on-expression references a
# table column of type REAL that is actually holding an MEM_IntReal
# value, be sure to use the REAL value and not the INT value when
# computing the expression.
#
ifcapable like_match_blobs {
  do_execsql_test indexexpr1-1800 {
    DROP TABLE IF EXISTS t0;
    CREATE TABLE t0(c0 REAL, c1 TEXT);
    CREATE INDEX i0 ON t0(+c0, c0);
    INSERT INTO t0(c0) VALUES(0);
    SELECT CAST(+ t0.c0 AS BLOB) LIKE 0 FROM t0; 
  } {0}
  do_execsql_test indexexpr1-1810 {
    SELECT CAST(+ t0.c0 AS BLOB) LIKE '0.0' FROM t0; 
  } {1}
  do_execsql_test indexexpr1-1820 {
    DROP TABLE IF EXISTS t1;
    CREATE TABLE t1(x REAL);
    CREATE INDEX t1x ON t1(x, +x);
    INSERT INTO t1(x) VALUES(2);
    SELECT +x FROM t1 WHERE x=2;
  } {2.0}
}

# 2022-04-30 https://sqlite.org/forum/info/7efabf4b03328e57
# Assertion fault during a DELETE INDEXED BY.
#
reset_db
do_execsql_test indexexpr1-1900 {
  CREATE TABLE t1(x TEXT PRIMARY KEY, y TEXT, z INT);
  INSERT INTO t1(x,y,z) VALUES('alpha','ALPHA',1),('bravo','charlie',1);
  CREATE INDEX i1 ON t1(+y COLLATE NOCASE);
  SELECT * FROM t1;
} {alpha ALPHA 1 bravo charlie 1}
do_execsql_test indexexpr1-1910 {
  DELETE FROM t1 INDEXED BY i1 
   WHERE x IS +y COLLATE NOCASE IN (SELECT z FROM t1)
  RETURNING *;
} {alpha ALPHA 1}
do_execsql_test indexexpr1-1920 {
  SELECT * FROM t1;
} {bravo charlie 1}

# 2022-11-28 Ticket 695a1a53de
# Improved ability to recognize that an index on an expression is a
# covering index.
#
reset_db
do_execsql_test indexexpr1-2000 {
  CREATE TABLE t1(a INT, b TEXT);
  INSERT INTO t1(a,b) VALUES
    (10, '{"one":5,"two":6}'),
    (10, '{"one":50,"two":60}'),
    (10, '{"three":99}'),
    (11, '{"one":100,"two":200}');
  CREATE INDEX t1_one ON t1(a, b->>'one');
  CREATE INDEX t1_two ON t1(a, b->>'two');
}
do_execsql_test indexexpr1-2010 {
  EXPLAIN QUERY PLAN
  SELECT sum(b->>'one') FROM t1 WHERE a=10; /* Query AA */
} {/.* t1_one .*/}
do_execsql_test indexexpr1-2011 {
  SELECT sum(b->>'one') FROM t1 WHERE a=10; /* Query AA */
} {55}
do_execsql_test indexexpr1-2020 {
  EXPLAIN QUERY PLAN
  SELECT sum(b->>'two') FROM t1 WHERE a=10; /* Query BB */
} {/.* t1_two .*/}
do_execsql_test indexexpr1-2021 {
  SELECT sum(b->>'two') FROM t1 WHERE a=10; /* Query BB */
} {66}
do_execsql_test indexexpr1-2030 {
  DROP TABLE t1;
  CREATE TABLE t1(a INT, b TEXT, c INT, d INT);
  INSERT INTO t1(a,b,c,d) VALUES
    (1, '{"x":1}', 12,  3),
    (1, '{"x":2}',  4,  5),
    (1, '{"x":1}',  6, 11),
    (2, '{"x":1}', 22,  3),
    (2, '{"x":2}',  4,  5),
    (3, '{"x":1}',  6,  7);
  CREATE INDEX t1x ON t1(d, a, b->>'x', c);
}
do_execsql_test indexexpr1-2030 {
  SELECT a,
       SUM(1)                              AS t1,
       SUM(CASE WHEN b->>'x'=1 THEN 1 END) AS t2,
       SUM(c)                              AS t3,
       SUM(CASE WHEN b->>'x'=1 THEN c END) AS t4
    FROM t1;
} {1 6 4 54 46}
do_execsql_test indexexpr1-2030 {
  explain query plan
  SELECT a,
       SUM(1)                              AS t1,
       SUM(CASE WHEN b->>'x'=1 THEN 1 END) AS t2,
       SUM(c)                              AS t3,
       SUM(CASE WHEN b->>'x'=1 THEN c END) AS t4
    FROM t1;
} {/.*SCAN t1 USING INDEX t1x.*/}



finish_test

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.
#
245
246
247
248
249
250
251





252

253




















































































































254
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







+
+
+
+
+
-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  CREATE INDEX t5a ON t5( abs(a) );
  CREATE INDEX t5b ON t5( abs(b) );
}
do_execsql_test 5.4 {
  SELECT * FROM t5 WHERE abs(a)=2 or abs(b)=9;
} {2 4 3 9}

#-------------------------------------------------------------------------
do_execsql_test 6.0 {
  CREATE TABLE x1(a INTEGER PRIMARY KEY, b);
  INSERT INTO x1 VALUES
      (1, 123), (2, '123'), (3, '123abc'), (4, 123.0), (5, 1234);

}

do_execsql_test 6.1.1 {
  SELECT a, b FROM x1 WHERE CAST(b AS INTEGER) = 123;
} {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 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 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 {
  CREATE INDEX i0 ON t0(ABS(c0));
} {1 {integer overflow}}
do_execsql_test 7.2 {
  COMMIT;
  SELECT sql FROM sqlite_master WHERE tbl_name = 't0';
  CREATE INDEX i0 ON t0(c0);
} {{CREATE TABLE t0(c0)}}
do_execsql_test 7.3 {
  REINDEX;
} {}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 8.0 {
  CREATE TABLE t0(c0);
  CREATE INDEX i0 ON t0(c0) WHERE c0 NOT NULL;
  INSERT INTO t0(c0) VALUES (NULL);
}

do_execsql_test 8.1.1 {
  SELECT * FROM t0 WHERE ~('' BETWEEN t0.c0 AND TRUE);
} {{}}
do_execsql_test 8.1.2 {
  SELECT ~('' BETWEEN t0.c0 AND TRUE) FROM t0;
} {-1}

foreach {tn expr} {
  1 " 0  ==  (34 BETWEEN c0 AND 33)"
  2 " 1  !=  (34 BETWEEN c0 AND 33)"
  3 "-1   <  (34 BETWEEN c0 AND 33)"
  4 "-1  <=  (34 BETWEEN c0 AND 33)"
  5 " 1   >  (34 BETWEEN c0 AND 33)"
  6 " 1  >=  (34 BETWEEN c0 AND 33)"
  7 " 1   -  (34 BETWEEN c0 AND 33)"
  8 "-1   +  (34 BETWEEN c0 AND 33)"
  9 " 1   |  (34 BETWEEN c0 AND 33)"
 10 " 1  <<  (34 BETWEEN c0 AND 33)"
 11 " 1  >>  (34 BETWEEN c0 AND 33)"
 12 " 1  ||  (34 BETWEEN c0 AND 33)"
} {
  do_execsql_test 8.3.$tn.1 "SELECT * FROM t0 WHERE $expr ORDER BY c0" { {} }
  do_execsql_test 8.3.$tn.2 "SELECT ($expr) IS TRUE FROM t0"           { 1 }
}

do_execsql_test 8.4 {
  CREATE TABLE t1(a, b);
  INSERT INTO t1 VALUES(1, 2), (3, 4);
  CREATE TABLE t2(x, y);
}

foreach {tn expr} {
  1 " 0  ==  (a=0 AND y=1)"
  2 " 1  !=  (a=0 AND y=1)"
  3 "-1  <   (a=0 AND y=1)"
  4 "-1  <=  (a=0 AND y=1)"
  5 " 1   >  (a=0 AND y=1)"
  6 " 1  >=  (a=0 AND y=1)"
  7 " 1   -  (a=0 AND y=1)"
  8 "-1   +  (a=0 AND y=1)"
  9 " 1   |  (a=0 AND y=1)"
  10 "1  <<  (a=0 AND y=1)"
  11 "1  >>  (a=0 AND y=1)"
  12 "1  ||  (a=0 AND y=1)"

  13 " 0  ==  (10 BETWEEN y AND b)"
  14 " 1  !=  (10 BETWEEN y AND b)"
  15 "-1  <   (10 BETWEEN y AND b)"
  16 "-1  <=  (10 BETWEEN y AND b)"
  17 " 1   >  (10 BETWEEN y AND b)"
  18 " 1  >=  (10 BETWEEN y AND b)"
  19 " 1   -  (10 BETWEEN y AND b)"
  20 "-1   +  (10 BETWEEN y AND b)"
  21 " 1   |  (10 BETWEEN y AND b)"
  22 " 1  <<  (10 BETWEEN y AND b)"
  23 " 1  >>  (10 BETWEEN y AND b)"
  24 " 1  ||  (10 BETWEEN y AND b)"

  25 " 1  ||  (10 BETWEEN y AND b)"
} {
  do_execsql_test 8.5.$tn.1 "
    SELECT * FROM t1 LEFT JOIN t2 WHERE $expr
  " {1 2 {} {} 3 4 {} {}}

  do_execsql_test 8.5.$tn.2 "
    SELECT ($expr) IS TRUE FROM t1 LEFT JOIN t2
  " {1 1}
}

finish_test

Changes to test/indexfault.test.

332
333
334
335
336
337
338










339
340
341
342
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352







+
+
+
+
+
+
+
+
+
+




  faultsim_restore_and_reopen
  set ::nReadCall 0
  sqlite3_soft_heap_limit 0
} -body {
  execsql { CREATE INDEX i1 ON t1(x) }
  faultsim_test_result {0 {}} 
}

do_faultsim_test 5 -prep {
  reset_db
} -body {
  execsql { 
 CREATE TABLE reallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallylongname(a PRIMARY KEY) WITHOUT ROWID;
  }
} -test {
  faultsim_test_result {0 {}} 
}

uninstall_custom_faultsim

finish_test

Changes to test/insert.test.

1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
-
+












-







# 2001 September 15
# 2001-09-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 the INSERT statement.
#
# $Id: insert.test,v 1.31 2007/04/05 11:25:59 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Try to insert into a non-existant table.
#
do_test insert-1.1 {
445
446
447
448
449
450
451









452

453













































































































































454
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







+
+
+
+
+
+
+
+
+
-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  CREATE TABLE t13(a INTEGER PRIMARY KEY,b UNIQUE);
  CREATE INDEX t13x1 ON t13(-b=b);
  INSERT INTO t13 VALUES(1,5),(6,2);
  REPLACE INTO t13 SELECT b,0 FROM t13;
  SELECT * FROM t13 ORDER BY +b;
} {2 0 6 2 1 5}

# 2019-01-17.  From the chromium fuzzer.
#
do_execsql_test insert-14.1 {
  DROP TABLE IF EXISTS t14;
  CREATE TABLE t14(x INTEGER PRIMARY KEY);
  INSERT INTO t14 VALUES(CASE WHEN 1 THEN null END);
  SELECT x FROM t14;
} {1}

integrity_check insert-99.0
integrity_check insert-14.2

# 2019-08-12.
#
do_execsql_test insert-15.1 {
  DROP TABLE IF EXISTS t1;
  DROP TABLE IF EXISTS t2;
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT);
  CREATE INDEX i1 ON t1(b);
  CREATE TABLE t2(a, b);
  INSERT INTO t2 VALUES(4, randomblob(31000));
  INSERT INTO t2 VALUES(4, randomblob(32000));
  INSERT INTO t2 VALUES(4, randomblob(33000));
  REPLACE INTO t1 SELECT a, b FROM t2;
  SELECT a, length(b) FROM t1;
} {4 33000}

# 2019-10-16
# ticket https://www.sqlite.org/src/info/a8a4847a2d96f5de
# On a REPLACE INTO, if an AFTER trigger adds back the conflicting
# row, you can end up with the wrong number of rows in an index.
#
db close
sqlite3 db :memory:
do_catchsql_test insert-16.1 {
  PRAGMA recursive_triggers = true;
  CREATE TABLE t0(c0,c1);
  CREATE UNIQUE INDEX i0 ON t0(c0);
  INSERT INTO t0(c0,c1) VALUES(123,1);
  CREATE TRIGGER tr0 AFTER DELETE ON t0
  BEGIN
    INSERT INTO t0 VALUES(123,2);
  END;
  REPLACE INTO t0(c0,c1) VALUES(123,3);
} {1 {UNIQUE constraint failed: t0.c0}}
do_execsql_test insert-16.2 {
  SELECT * FROM t0;
} {123 1}
integrity_check insert-16.3
do_catchsql_test insert-16.4 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
  CREATE INDEX t1b ON t1(b);
  INSERT INTO t1 VALUES(1, 'one');
  CREATE TRIGGER tr3 AFTER DELETE ON t1 BEGIN
    INSERT INTO t1 VALUES(1, 'three');
  END;
  REPLACE INTO t1 VALUES(1, 'two');
} {1 {UNIQUE constraint failed: t1.a}}
integrity_check insert-16.5
do_catchsql_test insert-16.6 {
  PRAGMA foreign_keys = 1;
  CREATE TABLE p1(a, b UNIQUE);
  CREATE TABLE c1(c, d REFERENCES p1(b) ON DELETE CASCADE);
  CREATE TRIGGER tr6 AFTER DELETE ON c1 BEGIN
    INSERT INTO p1 VALUES(4, 1);
  END;
  INSERT INTO p1 VALUES(1, 1);
  INSERT INTO c1 VALUES(2, 1);
  REPLACE INTO p1 VALUES(3, 1);2
} {1 {UNIQUE constraint failed: p1.b}}
integrity_check insert-16.7

# 2019-10-25 ticket c1e19e12046d23fe
do_catchsql_test insert-17.1 {
  PRAGMA temp.recursive_triggers = true;
  DROP TABLE IF EXISTS t0;
  CREATE TABLE t0(aa, bb);
  CREATE UNIQUE INDEX t0bb ON t0(bb);
  CREATE TRIGGER "r17.1" BEFORE DELETE ON t0
    BEGIN INSERT INTO t0(aa,bb) VALUES(99,1);
  END;
  INSERT INTO t0(aa,bb) VALUES(10,20);
  REPLACE INTO t0(aa,bb) VALUES(30,20);
} {1 {UNIQUE constraint failed: t0.rowid}}
integrity_check insert-17.2
do_catchsql_test insert-17.3 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a, b UNIQUE, c UNIQUE);
  INSERT INTO t1(a,b,c) VALUES(1,1,1),(2,2,2),(3,3,3),(4,4,4);
  CREATE TRIGGER "r17.3" AFTER DELETE ON t1 WHEN OLD.c<>3 BEGIN
    INSERT INTO t1(rowid,a,b,c) VALUES(100,100,100,3);
  END;
  REPLACE INTO t1(rowid,a,b,c) VALUES(200,1,2,3);
} {1 {UNIQUE constraint failed: t1.c}}
integrity_check insert-17.4
do_execsql_test insert-17.5 {
  CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
  CREATE UNIQUE INDEX t2b ON t2(b);
  INSERT INTO t2(a,b) VALUES(1,1),(2,2),(3,3),(4,4);
  CREATE TABLE fire(x);
  CREATE TRIGGER t2r1 AFTER DELETE ON t2 BEGIN
    INSERT INTO fire VALUES(old.a);
  END;
  UPDATE OR REPLACE t2 SET a=4, b=3 WHERE a=1;
  SELECT *, 'x' FROM t2 ORDER BY a;
} {2 2 x 4 3 x}
do_execsql_test insert-17.6 {
  SELECT x FROM fire ORDER BY x;
} {3 4}
do_execsql_test insert-17.7 {
  DELETE FROM t2;
  DELETE FROM fire;
  INSERT INTO t2(a,b) VALUES(1,1),(2,2),(3,3),(4,4);
  UPDATE OR REPLACE t2 SET a=1, b=3 WHERE a=1;
  SELECT *, 'x' FROM t2 ORDER BY a;
} {1 3 x 2 2 x 4 4 x}
do_execsql_test insert-17.8 {
  SELECT x FROM fire ORDER BY x;
} {3}
do_execsql_test insert-17.10 {
  CREATE TABLE t3(a INTEGER PRIMARY KEY, b INT, c INT, d INT);
  CREATE UNIQUE INDEX t3bpi ON t3(b) WHERE c<=d;
  CREATE UNIQUE INDEX t3d ON t3(d);
  INSERT INTO t3(a,b,c,d) VALUES(1,1,1,1),(2,1,3,2),(3,4,5,6);
  CREATE TRIGGER t3r1 AFTER DELETE ON t3 BEGIN
    SELECT 'hi';
  END;
  REPLACE INTO t3(a,b,c,d) VALUES(4,4,8,9);
} {}
do_execsql_test insert-17.11 {
  SELECT *, 'x' FROM t3 ORDER BY a;
} {1 1 1 1 x 2 1 3 2 x 4 4 8 9 x}
do_execsql_test insert-17.12 {
  REPLACE INTO t3(a,b,c,d) VALUES(5,1,11,2);
  SELECT *, 'x' FROM t3 ORDER BY a;
} {1 1 1 1 x 4 4 8 9 x 5 1 11 2 x}

do_execsql_test insert-17.13 {
  DELETE FROM t3;
  INSERT INTO t3(a,b,c,d) VALUES(1,1,1,1),(2,1,3,2),(3,4,5,6);
  DROP TRIGGER t3r1;
  CREATE TRIGGER t3r1 AFTER DELETE ON t3 BEGIN
    INSERT INTO t3(b,c,d) VALUES(old.b,old.c,old.d);
  END;
} {}
do_catchsql_test insert-17.14 {
  REPLACE INTO t3(a,b,c,d) VALUES(4,4,8,9);
} {1 {UNIQUE constraint failed: t3.b}}
do_catchsql_test insert-17.15 {
  REPLACE INTO t3(a,b,c,d) VALUES(5,1,11,2);
} {1 {UNIQUE constraint failed: t3.d}}


finish_test

Changes to test/insert4.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20













-







# 2007 January 24
#
# 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 the INSERT transfer optimization.
#
# $Id: insert4.test,v 1.10 2008/01/21 16:22:46 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix insert4

ifcapable !view||!subquery {
  finish_test
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
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







+

-



















-
+







#
proc xferopt_test {testname N} {
  do_test $testname {set ::sqlite3_xferopt_count} $N
}

# Create tables used for testing.
#
sqlite3_db_config db LEGACY_FILE_FORMAT 0
execsql {
  PRAGMA legacy_file_format = 0;
  CREATE TABLE t1(a int, b int, check(b>a));
  CREATE TABLE t2(x int, y int);
  CREATE VIEW v2 AS SELECT y, x FROM t2;
  CREATE TABLE t3(a int, b int);
}

# Ticket #2252.  Make sure the an INSERT from identical tables
# does not violate constraints.
#
do_test insert4-1.1 {
  set sqlite3_xferopt_count 0
  execsql {
    DELETE FROM t1;
    DELETE FROM t2;
    INSERT INTO t2 VALUES(9,1);
  }
  catchsql {
    INSERT INTO t1 SELECT * FROM t2;
  }
} {1 {CHECK constraint failed: t1}}
} {1 {CHECK constraint failed: b>a}}
xferopt_test insert4-1.2 0
do_test insert4-1.3 {
  execsql {
    SELECT * FROM t1;
  }
} {}

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
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







-
+

















-
+







xferopt_test insert4-2.3.2  0
do_test insert4-2.3.3 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 SELECT * FROM t2 LIMIT 1;
    SELECT * FROM t1;
  }
} {1 {CHECK constraint failed: t1}}
} {1 {CHECK constraint failed: b>a}}
xferopt_test insert4-2.3.4 0

# Do not run the transfer optimization if there is a DISTINCT
#
do_test insert4-2.4.1 {
  execsql {
    DELETE FROM t3;
    INSERT INTO t3 SELECT DISTINCT * FROM t2;
    SELECT * FROM t3;
  }
} {9 1 1 9}
xferopt_test insert4-2.4.2 0
do_test insert4-2.4.3 {
  catchsql {
    DELETE FROM t1;
    INSERT INTO t1 SELECT DISTINCT * FROM t2;
  }
} {1 {CHECK constraint failed: t1}}
} {1 {CHECK constraint failed: b>a}}
xferopt_test insert4-2.4.4 0

# The following procedure constructs two tables then tries to transfer
# data from one table to the other.  Checks are made to make sure the
# transfer is successful and that the transfer optimization was used or
# not, as appropriate.
#
312
313
314
315
316
317
318
319

320
321
322
323
324
325
326
327
328

329
330
331
332
333
334
335
311
312
313
314
315
316
317

318
319
320
321
322
323
324
325
326

327
328
329
330
331
332
333
334







-
+








-
+







do_test insert4-6.6 {
  execsql {
    CREATE TABLE t6b(x CHECK( x<>'abc' COLLATE nocase ));
  }
  catchsql {
    INSERT INTO t6b SELECT * FROM t6a;
  }
} {1 {CHECK constraint failed: t6b}}
} {1 {CHECK constraint failed: x<>'abc' COLLATE nocase}}
do_test insert4-6.7 {
  execsql {
    DROP TABLE t6b;
    CREATE TABLE t6b(x CHECK( x COLLATE nocase <>'abc' ));
  }
  catchsql {
    INSERT INTO t6b SELECT * FROM t6a;
  }
} {1 {CHECK constraint failed: t6b}}
} {1 {CHECK constraint failed: x COLLATE nocase <>'abc'}}

# Ticket [6284df89debdfa61db8073e062908af0c9b6118e]
# Disable the xfer optimization if the destination table contains
# a foreign key constraint
#
ifcapable foreignkey {
  do_test insert4-7.1 {
594
595
596
597
598
599
600






601





















602
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







+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

do_test 10.3 {
  execsql { PRAGMA integrity_check }
  set sqlite3_xferopt_count 0
  execsql { INSERT INTO x     SELECT * FROM t8 }
  set sqlite3_xferopt_count
} {1}

do_test 10.4 {
  execsql { PRAGMA integrity_check }
  set sqlite3_xferopt_count 0
  execsql { INSERT INTO x     SELECT * FROM t8  RETURNING * }
  set sqlite3_xferopt_count
} {0}

#-------------------------------------------------------------------------
# xfer transfer between tables where the source has an empty partial index.
#
do_execsql_test 11.0 {
  CREATE TABLE t9(a, b, c);
  CREATE INDEX t9a ON t9(a);
  CREATE INDEX t9b ON t9(b) WHERE c=0;

  INSERT INTO t9 VALUES(1, 1, 1);
  INSERT INTO t9 VALUES(2, 2, 2);
  INSERT INTO t9 VALUES(3, 3, 3);

  CREATE TABLE t10(a, b, c);
  CREATE INDEX t10a ON t10(a);
  CREATE INDEX t10b ON t10(b) WHERE c=0;

  INSERT INTO t10 SELECT * FROM t9;
  SELECT * FROM t10;
  PRAGMA integrity_check;
} {1 1 1  2 2 2  3 3 3  ok}

finish_test

Added test/insertfault.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019-01-26
#
# 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.
#
#***********************************************************************
#
# Test cases for INSERT

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix insertfault

do_execsql_test 1.0 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d DEFAULT true);
  INSERT INTO t1 DEFAULT VALUES;
  SELECT * FROM t1;
} {1 {} {} 1}
faultsim_save_and_close

breakpoint
do_faultsim_test 1 -faults oom* -prep {
  faultsim_restore_and_reopen
  db eval { SELECT * FROM sqlite_master } 
} -body {
  execsql { SELECT * FROM t1 }
} -test {
  faultsim_test_result {0 {1 {} {} 1}}
}


finish_test

Changes to test/instr.test.

252
253
254
255
256
257
258





















259
260
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


  SELECT instr(X'', 'abc')
} 0
do_execsql_test instr-1.64 {
  CREATE TABLE x1(a, b);
  INSERT INTO x1 VALUES(X'', 'abc');
  SELECT instr(a, b) FROM x1;
} 0

# 2019-09-16 ticket https://www.sqlite.org/src/info/587791f92620090e
#
do_execsql_test instr-2.0 {
  DROP TABLE IF EXISTS t0;
  CREATE TABLE t0(c0 PRIMARY KEY, c1);
  INSERT INTO t0(c0) VALUES (x'bb'), (0);
  SELECT COUNT(*) FROM t0 WHERE INSTR(x'aabb', t0.c0) ORDER BY t0.c0, t0.c1;
} {1}
do_execsql_test instr-2.1 {
  SELECT quote(c0) FROM t0 WHERE INSTR(x'aabb', t0.c0) ORDER BY t0.c0, t0.c1;
} {X'BB'}
do_execsql_test instr-2.2 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(x);
  INSERT INTO t1(x) VALUES('text'),(x'bb');
  SELECT quote(x) FROM t1 WHERE instr(x'aabb',x);
} {X'BB'}
do_execsql_test instr-2.3 {
  SELECT quote(x) FROM t1 WHERE x>'zzz' AND instr(x'aabb',x);
} {X'BB'}

finish_test

Changes to test/instrfault.test.

65
66
67
68
69
70
71
72

73
74
75
76
77
78
79
65
66
67
68
69
70
71

72
73
74
75
76
77
78
79







-
+







    faultsim_test_result {0 31}
    sqlite3_finalize $::stmt
  }

  do_faultsim_test 1.$enc.4 -faults oom-t* -prep {
    set ::stmt [sqlite3_prepare_v2 db "SELECT instr(?, ?)" -1 dummy]
    sqlite3_bind_blob $::stmt 1 $::HAYSTACK [string length $::HAYSTACK]
    sqlite3_bind_text $::stmt 2 $::NEEDLE [string length $::NEEDLE]
    sqlite3_bind_blob $::stmt 2 $::NEEDLE [string length $::NEEDLE]
  } -body {
    set rc [sqlite3_step $::stmt]
    if {$rc=="SQLITE_NOMEM"} { error "out of memory" }
    sqlite3_column_int $::stmt 0
  } -test {
    faultsim_test_result {0 31}
    sqlite3_finalize $::stmt

Changes to test/intarray.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







-
+


-
-
-
+
+
+







  set ia4 [sqlite3_intarray_create db ia4]
  db eval {
    SELECT type, name FROM temp.sqlite_master
     ORDER BY name
  }
} {table ia1 table ia2 table ia3 table ia4}

# Verify the inability to DROP and recreate an intarray virtual table.
# Verify the ability to DROP and recreate an intarray virtual table.
do_test intarray-1.1b {
  db eval {DROP TABLE ia1}
  set rc [catch {sqlite3_intarray_create db ia1} msg]
  lappend rc $msg
} {1 SQLITE_MISUSE}
  set rc [catch {sqlite3_intarray_create db ia1} ia1]
  lappend rc $ia1
} {/0 [0-9A-Z]+/} 

do_test intarray-1.2 {
  db eval {
    SELECT b FROM t1 WHERE a IN ia3 ORDER BY a
  }
} {}

Changes to test/interrupt.test.

90
91
92
93
94
95
96
97






98
99
100




101
102



103
104



105
106
107
108
109
110
111
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







-
+
+
+
+
+
+


-
+
+
+
+


+
+
+


+
+
+







} $cksum
ifcapable {vacuum && !default_autovacuum} {
  do_test interrupt-2.4 {
    expr {$::origsize>[file size test.db]}
  } 1
}
ifcapable {explain} {
  do_test interrupt-2.5 {
  do_test interrupt-2.5.1 {
    sqlite3_is_interrupted $DB
  } {0}
  do_test interrupt-2.5.2 {
    unset -nocomplain ::interrupt_count
    set ::interrupt_count 0
    set sql {EXPLAIN SELECT max(a,b), a, b FROM t1}
    execsql $sql
    set rc [catch {db eval $sql {sqlite3_interrupt $DB}} msg]
    set rc [catch {db eval $sql {
      sqlite3_interrupt $DB;
      incr ::interrupt_count [sqlite3_is_interrupted $DB];
    }} msg]
    lappend rc $msg
  } {1 interrupted}
  do_test interrupt-2.5.3 {
    set ::interrupt_count
  } {1}
}
integrity_check interrupt-2.6
do_test interrupt-2.7 {
  sqlite3_is_interrupted $DB
} {0}

# Ticket #594.  If an interrupt occurs in the middle of a transaction
# and that transaction is later rolled back, the internal schema tables do
# not reset.
#
# UPDATE: Interrupting a DML statement in the middle of a transaction now
# causes the transaction to roll back. Leaving the transaction open after

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');

Added test/intreal.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019-05-03
#
# 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.
#
#***********************************************************************
# Tests to exercise the MEM_IntReal representation of Mem objects.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set ::testprefix intreal

sqlite3_create_function db
do_execsql_test 100 {
  SELECT intreal(5);
} {5.0}
do_execsql_test 110 {
  SELECT intreal(5)=5, 6=intreal(6);
} {1 1}
do_execsql_test 120 {
  SELECT intreal(7)=7.0, 8.0=intreal(8);
} {1 1}
do_execsql_test 130 {
  SELECT typeof(intreal(9));
} {real}
do_execsql_test 140 {
  SELECT 'a'||intreal(11)||'z';
} {a11.0z}

do_execsql_test 150 {
  SELECT max(1.0,intreal(2),3.0), max(1,intreal(2),3);
} {3.0 3}
do_execsql_test 160 {
  SELECT max(1.0,intreal(4),3.0), max(1,intreal(4),3);
} {4.0 4.0}
do_execsql_test 170 {
  SELECT max(1.0,intreal(2),intreal(3),4.0),
         max(1,intreal(2),intreal(3),4);
} {4.0 4}
do_execsql_test 180 {
  SELECT max(1.0,intreal(5),intreal(3),4.0),
         max(1,intreal(5),intreal(3),4);
} {5.0 5.0}

#-------------------------------------------------------------------------
do_execsql_test 2.1 {
  CREATE TABLE t2(a REAL);
  INSERT INTO t2 VALUES( 836627109860825358 );
  SELECT substr(a,1,4) FROM t2 WHERE a = CAST(836627109860825358 AS REAL);
} {8.36}

do_execsql_test 2.2 {
  CREATE INDEX i2 ON t2(a);
  SELECT substr(a,1,4) FROM t2 WHERE a = CAST(836627109860825358 AS REAL);
} {8.36}

do_execsql_test 2.3 {
  CREATE TABLE t0 (c0);
  CREATE TABLE t1 (c1 REAL);
  INSERT INTO t1(c1) VALUES (8366271098608253588);
  INSERT INTO t0(c0) VALUES ('a');
}
set D [db one {SELECT c1 FROM t1}]

do_execsql_test 2.4 {
  SELECT * FROM t1 WHERE (t1.c1 = CAST(8366271098608253588 AS REAL));
} $D

do_execsql_test 2.5 {
  SELECT * FROM t0, t1 WHERE (t1.c1 = CAST(8366271098608253588 AS REAL));
} [list a $D]

do_execsql_test 2.6 {
  SELECT * FROM t0, t1 
  WHERE (
        t1.c1 >= CAST(8366271098608253588 AS REAL) 
    AND t1.c1 <= CAST(8366271098608253588 AS REAL)
  );
} [list a $D]

# 2019-07-29 ticket ba2f4585cf495231
#
db close
sqlite3 db :memory:
do_execsql_test 3.0 {
  CREATE TABLE t0 (c0 REAL, c1);
  CREATE UNIQUE INDEX i0 ON t0(c1, 0 | c0);
  INSERT INTO t0(c0) VALUES (4750228396194493326), (0);
  UPDATE OR REPLACE t0 SET c0 = 'a', c1 = '';
  SELECT * FROM t0 ORDER BY t0.c1;
  PRAGMA integrity_check;
} {a {} ok}


reset_db
do_execsql_test 4.0 {
  CREATE TABLE t1(a REAL, b AS ('expr') ); 
}
do_execsql_test 4.1 {
  INSERT INTO t1 VALUES( REPLACE(0, '', 'expr') );
}
do_execsql_test 4.2 {
  INSERT INTO t1 SELECT REPLACE(4, '', 'expr');
}
do_execsql_test 4.3 {
  SELECT typeof(a), a FROM t1;
} {
  real 0.0
  real 4.0
}

finish_test

Changes to test/io.test.

636
637
638
639
640
641
642


643
636
637
638
639
640
641
642
643
644
645







+
+

  # to be flushed. Which is a bug.
  hexio_write test.db [expr 1024 * 5] [string repeat 00 2048]
  do_execsql_test 6.2.$tn.3 { PRAGMA integrity_check } {ok}
  db close
}

sqlite3_simulate_device -char {} -sectorsize 0
unregister_devsim

finish_test

Changes to test/ioerr.test.

330
331
332
333
334
335
336

337
338
339
340
341
342
343
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344







+







  db eval { CREATE TABLE t1(x) }
  db eval { INSERT INTO t1 VALUES(randomblob(1100)); }
} -tclbody {
  db eval { INSERT INTO t1 VALUES(randomblob(2000)); }
}
sqlite3_simulate_device -char {} -sectorsize 0
catch {db close}
unregister_devsim

do_ioerr_test ioerr-13 -ckrefcount true -erc 1 -sqlprep {
  PRAGMA auto_vacuum = incremental;
  CREATE TABLE t1(x);
  CREATE TABLE t2(x);
  INSERT INTO t2 VALUES(randomblob(1500));
  INSERT INTO t2 SELECT randomblob(1500) FROM t2;

Changes to test/istrue.test.

108
109
110
111
112
113
114
115

116
117
118

119
120
121

122
123
124

125
126
127
128
129
130
131
108
109
110
111
112
113
114

115
116
117

118
119
120

121
122
123

124
125
126
127
128
129
130
131







-
+


-
+


-
+


-
+







     e BOOLEAN CHECK(e IS NOT FALSE)
  );
  INSERT INTO t2 VALUES(1,true,false,null,null);
  SELECT * FROM t2;
} {1 1 0 {} {}}
do_catchsql_test istrue-521 {
  INSERT INTO t2 VALUES(2,false,false,null,null);
} {1 {CHECK constraint failed: t2}}
} {1 {CHECK constraint failed: b IS TRUE}}
do_catchsql_test istrue-522 {
  INSERT INTO t2 VALUES(2,true,true,null,null);
} {1 {CHECK constraint failed: t2}}
} {1 {CHECK constraint failed: c IS FALSE}}
do_catchsql_test istrue-523 {
  INSERT INTO t2 VALUES(2,true,false,true,null);
} {1 {CHECK constraint failed: t2}}
} {1 {CHECK constraint failed: d IS NOT TRUE}}
do_catchsql_test istrue-524 {
  INSERT INTO t2 VALUES(2,true,false,null,false);
} {1 {CHECK constraint failed: t2}}
} {1 {CHECK constraint failed: e IS NOT FALSE}}

foreach {tn val} [list 1 NaN 2 -NaN 3 NaN0 4 -NaN0 5 Inf 6 -Inf] {
  do_execsql_test istrue-600.$tn.1 {
    DROP TABLE IF EXISTS t1;
    CREATE TABLE t1(x);
  }
  do_test istrue-600.$tn.2 {
139
140
141
142
143
144
145

146
147
148
149
150
151
152
153
154
155
156
157
158
159
160



























































161
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







+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

    SELECT x IS TRUE FROM t1;
  } [expr {$tn in [list 5 6] ? {1} : {0}}]
  do_execsql_test istrue-600.$tn.4 {
    SELECT x IS FALSE FROM t1;
  } {0}
}

ifcapable altertable {
do_execsql_test istrue-700 {
  CREATE TABLE t7(
    a INTEGER PRIMARY KEY,
    b BOOLEAN DEFAULT false,
    c BOOLEAN DEFAULT true
  );
  INSERT INTO t7(a) VALUES(1);
  INSERT INTO t7(a,b,c) VALUES(2,true,false);
  ALTER TABLE t7 ADD COLUMN d BOOLEAN DEFAULT false;
  ALTER TABLE t7 ADD COLUMN e BOOLEAN DEFAULT true;
  INSERT INTO t7(a,b,c) VALUES(3,true,false);
  INSERT INTO t7 VALUES(4,false,true,true,false);
  SELECT *,'x' FROM t7 ORDER BY a;
} {1 0 1 0 1 x 2 1 0 0 1 x 3 1 0 0 1 x 4 0 1 1 0 x}

  do_execsql_test istrue-700 {
    CREATE TABLE t7(
      a INTEGER PRIMARY KEY,
      b BOOLEAN DEFAULT false,
      c BOOLEAN DEFAULT true
    );
    INSERT INTO t7(a) VALUES(1);
    INSERT INTO t7(a,b,c) VALUES(2,true,false);
    ALTER TABLE t7 ADD COLUMN d BOOLEAN DEFAULT false;
    ALTER TABLE t7 ADD COLUMN e BOOLEAN DEFAULT true;
    INSERT INTO t7(a,b,c) VALUES(3,true,false);
    INSERT INTO t7 VALUES(4,false,true,true,false);
    SELECT *,'x' FROM t7 ORDER BY a;
  } {1 0 1 0 1 x 2 1 0 0 1 x 3 1 0 0 1 x 4 0 1 1 0 x}
}

do_execsql_test istrue-710 {
  SELECT 0.5 IS TRUE COLLATE NOCASE;
  SELECT 0.5 IS TRUE COLLATE RTRIM;
  SELECT 0.5 IS TRUE COLLATE BINARY;

  SELECT 0.5 IS TRUE;
  SELECT 0.5 COLLATE NOCASE IS TRUE;
  SELECT 0.0 IS FALSE;

  SELECT 0.0 IS FALSE COLLATE NOCASE;
  SELECT 0.0 IS FALSE COLLATE RTRIM;
  SELECT 0.0 IS FALSE COLLATE BINARY;
} {1 1 1   1 1 1  1 1 1}

# 2020-06-12 bug report from Chromium
# https://bugs.chromium.org/p/chromium/issues/detail?id=1094247
do_catchsql_test istrue-800 {
  SELECT 9 IN (false.false);
} {1 {no such column: false.false}}
do_execsql_test istrue-810 {
  CREATE TABLE t8(a INT, true INT, false INT, d INT);
  INSERT INTO t8(a,true,false,d) VALUES(5,6,7,8),(4,3,2,1),('a','b','c','d');
  SELECT * FROM t8 ORDER BY false;
} {4 3 2 1 5 6 7 8 a b c d}
do_catchsql_test istrue-820 {
  SELECT 9 IN (false.false) FROM t8;
} {1 {no such column: false.false}}
do_execsql_test istrue-830 {
  CREATE TABLE false(true INT, false INT, x INT CHECK (5 IN (false.false)));
} {}
do_execsql_test istrue-840 {
  INSERT INTO False VALUES(4,5,6);
} {}
do_catchsql_test istrue-841 {
  INSERT INTO False VALUES(5,6,7);
} {1 {CHECK constraint failed: 5 IN (false.false)}}
do_execsql_test istrue-850 {
  SELECT 9 IN (false.false) FROM false;
} {0}
do_execsql_test istrue-851 {
  SELECT 5 IN (false.false) FROM false;
} {1}

finish_test

Changes to test/join.test.

246
247
248
249
250
251
252













253
254
255
256
257
258
259
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







+
+
+
+
+
+
+
+
+
+
+
+
+








do_test join-2.1 {
  execsql {
    SELECT * FROM t1 NATURAL LEFT JOIN t2;
  }
} {1 2 3 4 2 3 4 5 3 4 5 {}}

# EVIDENCE-OF: R-52129-05406 you can say things like "OUTER LEFT NATURAL
# JOIN" which means the same as "NATURAL LEFT OUTER JOIN".
do_test join-2.1b {
  execsql {
    SELECT * FROM t1 OUTER LEFT NATURAL JOIN t2;
  }
} {1 2 3 4 2 3 4 5 3 4 5 {}}
do_test join-2.1c {
  execsql {
    SELECT * FROM t1 NATURAL LEFT OUTER JOIN t2;
  }
} {1 2 3 4 2 3 4 5 3 4 5 {}}

# ticket #3522
do_test join-2.1.1 {
  execsql2 {
    SELECT * FROM t1 NATURAL LEFT JOIN t2;
  }
} {a 1 b 2 c 3 d 4 a 2 b 3 c 4 d 5 a 3 b 4 c 5 d {}}
do_test join-2.1.2 {
268
269
270
271
272
273
274

275
276
277
278






279
280
281
282
283
284
285
286
281
282
283
284
285
286
287
288




289
290
291
292
293
294

295
296
297
298
299
300
301







+
-
-
-
-
+
+
+
+
+
+
-







} {b 2 c 3 d 4 b 3 c 4 d 5 b {} c {} d {}}

do_test join-2.2 {
  execsql {
    SELECT * FROM t2 NATURAL LEFT OUTER JOIN t1;
  }
} {1 2 3 {} 2 3 4 1 3 4 5 2}

do_test join-2.3 {
  catchsql {
    SELECT * FROM t1 NATURAL RIGHT OUTER JOIN t2;
  }
#do_test join-2.3 {
#  catchsql {
#    SELECT * FROM t1 NATURAL RIGHT OUTER JOIN t2;
#  }
#} {1 {RIGHT and FULL OUTER JOINs are not currently supported}}

} {1 {RIGHT and FULL OUTER JOINs are not currently supported}}
do_test join-2.4 {
  execsql {
    SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.d
  }
} {1 2 3 {} {} {} 2 3 4 {} {} {} 3 4 5 1 2 3}
do_test join-2.5 {
  execsql {
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
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







-
+


















+
+
+




-
+




-
+




-
+




-
+




-
+




-
+







    SELECT * FROM t1 NATURAL JOIN t2 USING(b);
  }
} {1 {a NATURAL join may not have an ON or USING clause}}
do_test join-3.3 {
  catchsql {
    SELECT * FROM t1 JOIN t2 ON t1.a=t2.b USING(b);
  }
} {1 {cannot have both ON and USING clauses in the same join}}
} {1 {near "USING": syntax error}}
do_test join-3.4.1 {
  catchsql {
    SELECT * FROM t1 JOIN t2 USING(a);
  }
} {1 {cannot join using column a - column not present in both tables}}
do_test join-3.4.2 {
  catchsql {
    SELECT * FROM t1 JOIN t2 USING(d);
  }
} {1 {cannot join using column d - column not present in both tables}}
do_test join-3.5 {
  catchsql { SELECT * FROM t1 USING(a) }
} {1 {a JOIN clause is required before USING}}
do_test join-3.6 {
  catchsql {
    SELECT * FROM t1 JOIN t2 ON t3.a=t2.b;
  }
} {1 {no such column: t3.a}}

# EVIDENCE-OF: R-47973-48020 you cannot say "INNER OUTER JOIN", because
# that would be contradictory.
do_test join-3.7 {
  catchsql {
    SELECT * FROM t1 INNER OUTER JOIN t2;
  }
} {1 {unknown or unsupported join type: INNER OUTER}}
} {1 {unknown join type: INNER OUTER}}
do_test join-3.8 {
  catchsql {
    SELECT * FROM t1 INNER OUTER CROSS JOIN t2;
  }
} {1 {unknown or unsupported join type: INNER OUTER CROSS}}
} {1 {unknown join type: INNER OUTER CROSS}}
do_test join-3.9 {
  catchsql {
    SELECT * FROM t1 OUTER NATURAL INNER JOIN t2;
  }
} {1 {unknown or unsupported join type: OUTER NATURAL INNER}}
} {1 {unknown join type: OUTER NATURAL INNER}}
do_test join-3.10 {
  catchsql {
    SELECT * FROM t1 LEFT BOGUS JOIN t2;
  }
} {1 {unknown or unsupported join type: LEFT BOGUS}}
} {1 {unknown join type: LEFT BOGUS}}
do_test join-3.11 {
  catchsql {
    SELECT * FROM t1 INNER BOGUS CROSS JOIN t2;
  }
} {1 {unknown or unsupported join type: INNER BOGUS CROSS}}
} {1 {unknown join type: INNER BOGUS CROSS}}
do_test join-3.12 {
  catchsql {
    SELECT * FROM t1 NATURAL AWK SED JOIN t2;
  }
} {1 {unknown or unsupported join type: NATURAL AWK SED}}
} {1 {unknown join type: NATURAL AWK SED}}

do_test join-4.1 {
  execsql {
    BEGIN;
    CREATE TABLE t5(a INTEGER PRIMARY KEY);
    CREATE TABLE t6(a INTEGER);
    INSERT INTO t6 VALUES(NULL);
435
436
437
438
439
440
441

442
443
444
445
446
447
448
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467







+







    usuarios left outer join centros on usuarios.idcentro = centros.id;
  }
} {1 a xxx 2 b xxx 3 c {}}

# A test for ticket #247.
#
do_test join-7.1 {
  sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1
  execsql {
    CREATE TABLE t7 (x, y);
    INSERT INTO t7 VALUES ("pa1", 1);
    INSERT INTO t7 VALUES ("pa2", NULL);
    INSERT INTO t7 VALUES ("pa3", NULL);
    INSERT INTO t7 VALUES ("pa4", 2);
    INSERT INTO t7 VALUES ("pa30", 131);
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
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







+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+







jointest join-12.2 30 {0 1}
jointest join-12.3 63 {0 1}
jointest join-12.4 64 {0 1}
jointest join-12.5 65 {1 {at most 64 tables in a join}}
jointest join-12.6 66 {1 {at most 64 tables in a join}}
jointest join-12.7 127 {1 {at most 64 tables in a join}}
jointest join-12.8 128 {1 {at most 64 tables in a join}}

# As of 2019-01-17, the number of elements in a SrcList is limited
# to 200.  The following tests still run, but the answer is now
# an SQLITE_NOMEM error.
#
jointest join-12.9 1000 {1 {at most 64 tables in a join}}

# If SQLite is built with SQLITE_MEMDEBUG, then the huge number of realloc()
# calls made by the following test cases are too time consuming to run.
# Without SQLITE_MEMDEBUG, realloc() is fast enough that these are not
# a problem.
ifcapable pragma&&compileoption_diags {
  if {[lsearch [db eval {PRAGMA compile_options}] MEMDEBUG]<0} {
    jointest join-12.10 65534 {1 {at most 64 tables in a join}}
    jointest join-12.11 65535 {1 {too many references to "t14": max 65535}}
    jointest join-12.12 65536 {1 {too many references to "t14": max 65535}}
    jointest join-12.13 65537 {1 {too many references to "t14": max 65535}}
# jointest join-12.9 1000 {1 {at most 64 tables in a join}}
#
#  If SQLite is built with SQLITE_MEMDEBUG, then the huge number of realloc()
#  calls made by the following test cases are too time consuming to run.
#  Without SQLITE_MEMDEBUG, realloc() is fast enough that these are not
#  a problem.
#
# ifcapable pragma&&compileoption_diags {
#    if {[lsearch [db eval {PRAGMA compile_options}] MEMDEBUG]<0} {
#     jointest join-12.10 65534 {1 {at most 64 tables in a join}}
#     jointest join-12.11 65535 {1 {too many references to "t14": max 65535}}
#     jointest join-12.12 65536 {1 {too many references to "t14": max 65535}}
#     jointest join-12.13 65537 {1 {too many references to "t14": max 65535}}
  }
}
#   }
# }


#-------------------------------------------------------------------------
# Test a problem with reordering tables following a LEFT JOIN.
#
do_execsql_test join-13.0 {
  CREATE TABLE aa(a);
733
734
735
736
737
738
739



740



























741
742
743
744
745
746
747
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







+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







} {111 555 333}

do_execsql_test join-14.4 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(c PRIMARY KEY, a TEXT(10000), b TEXT(10000));
  SELECT * FROM (SELECT 111) LEFT JOIN (SELECT c+222 FROM t1) GROUP BY 1;
} {111 {}}
do_execsql_test join-14.4b {
  SELECT * FROM (SELECT 111) LEFT JOIN (SELECT c+222 FROM t1);
} {111 {}}
do_execsql_test join-14.5 {
  SELECT * FROM (SELECT 111 AS x UNION ALL SELECT 222)
                LEFT JOIN (SELECT c+333 AS y FROM t1) ON x=y GROUP BY 1;
} {111 {} 222 {}}
do_execsql_test join-14.5b {
  SELECT count(*)
    FROM (SELECT 111 AS x UNION ALL SELECT 222)
         LEFT JOIN (SELECT c+333 AS y FROM t1) ON x=y;
} {2}
do_execsql_test join-14.5c {
  SELECT count(*)
    FROM (SELECT c+333 AS y FROM t1)
         RIGHT JOIN (SELECT 111 AS x UNION ALL SELECT 222) ON x=y;
} {2}
do_execsql_test join-14.6 {
  SELECT * FROM (SELECT 111 AS x UNION ALL SELECT 111)
                LEFT JOIN (SELECT c+333 AS y FROM t1) ON x=y GROUP BY 1;
} {111 {}}
do_execsql_test join-14.7 {
  SELECT * FROM (SELECT 111 AS x UNION ALL SELECT 111 UNION ALL SELECT 222)
                LEFT JOIN (SELECT c+333 AS y FROM t1) ON x=y GROUP BY 1;
} {111 {} 222 {}}
do_execsql_test join-14.8 {
  INSERT INTO t1(c) VALUES(-111);
  SELECT * FROM (SELECT 111 AS x UNION ALL SELECT 111 UNION ALL SELECT 222)
                LEFT JOIN (SELECT c+333 AS y FROM t1) ON x=y GROUP BY 1;
} {111 {} 222 222}
do_execsql_test join-14.9 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(c PRIMARY KEY) WITHOUT ROWID;
  SELECT * FROM (SELECT 111) LEFT JOIN (SELECT c+222 FROM t1) GROUP BY 1;
} {111 {}}

# Verify the fix to ticket 
# https://www.sqlite.org/src/tktview/7fde638e94287d2c948cd9389
802
803
804
805
806
807
808
809

810
811
812
813





814
815
816
817
818
819
820
857
858
859
860
861
862
863

864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880







-
+




+
+
+
+
+







   WHERE CASE WHEN FALSE THEN a=x ELSE 1 END;
} {1 2 {} {} x 3 4 {} {} x}
do_execsql_test join-15.105 {
  SELECT *, 'x'
    FROM t1 LEFT JOIN t2
   WHERE a IN (1,3,x,y);
} {1 2 {} {} x 3 4 {} {} x}
do_execsql_test join-15.106 {
do_execsql_test join-15.106a {
  SELECT *, 'x' 
    FROM t1 LEFT JOIN t2 
   WHERE NOT ( 'x'='y' AND t2.y=1 );
} {1 2 {} {} x 3 4 {} {} x}
do_execsql_test join-15.106b {
  SELECT *, 'x' 
    FROM t1 LEFT JOIN t2 
   WHERE ~ ( 'x'='y' AND t2.y=1 );
} {1 2 {} {} x 3 4 {} {} x}
do_execsql_test join-15.107 {
  SELECT *, 'x' 
    FROM t1 LEFT JOIN t2 
   WHERE t2.y IS NOT 'abc'
} {1 2 {} {} x 3 4 {} {} x}
do_execsql_test join-15.110 {
  DROP TABLE t1;
839
840
841
842
843
844
845
846















































































































































































































































































































847
899
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

          ON x3 IS TRUE AND b4=a3
        JOIN (SELECT x AS x4 FROM t2)
          ON x4<=CASE WHEN x3 THEN CASE WHEN a4 THEN 1 ELSE -1 END ELSE 0 END
        LEFT JOIN (SELECT a AS a5, b AS b5 FROM t1)
          ON x4 IS TRUE AND b5=a4
   ORDER BY a1, a2, a3, a4, a5;
} {1 {} {} {} {} 1 11 {} {} {} 1 12 {} {} {} 1 12 121 {} {} 1 13 {} {} {}}

# 2019-02-05 Ticket https://www.sqlite.org/src/tktview/5948e09b8c415bc45da5c
# Error in join due to the LEFT JOIN strength reduction optimization.
#
do_execsql_test join-16.100 {
  DROP TABLE IF EXISTS t1;
  DROP TABLE IF EXISTS t2;
  CREATE TABLE t1(a INT);
  INSERT INTO t1(a) VALUES(1);
  CREATE TABLE t2(b INT);
  SELECT a, b
    FROM t1 LEFT JOIN t2 ON 0
   WHERE (b IS NOT NULL)=0;
} {1 {}}

# 2019-08-17 ticket https://sqlite.org/src/tktview/6710d2f7a13a299728ab
# Ensure that constants that derive from the right-hand table of a LEFT JOIN
# are never factored out, since they are not really constant.
#
do_execsql_test join-17.100 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(x);
  INSERT INTO t1(x) VALUES(0),(1);
  SELECT * FROM t1 LEFT JOIN (SELECT abs(1) AS y FROM t1) ON x WHERE NOT(y='a');
} {1 1 1 1}
do_execsql_test join-17.110 {
  SELECT * FROM t1 LEFT JOIN (SELECT abs(1)+2 AS y FROM t1) ON x
   WHERE NOT(y='a');
} {1 3 1 3}

#-------------------------------------------------------------------------
reset_db
do_execsql_test join-18.1 {
  CREATE TABLE t0(a);
  CREATE TABLE t1(b);
  CREATE VIEW v0 AS SELECT a FROM t1 LEFT JOIN t0;
  INSERT INTO t1 VALUES (1);
} {}

do_execsql_test join-18.2 {
  SELECT * FROM v0 WHERE NOT(v0.a IS FALSE);
} {{}}

do_execsql_test join-18.3 {
  SELECT * FROM t1 LEFT JOIN t0 WHERE NOT(a IS FALSE);
} {1 {}}

do_execsql_test join-18.4 {
  SELECT NOT(v0.a IS FALSE) FROM v0
} {1}

#-------------------------------------------------------------------------
reset_db
do_execsql_test join-19.0 {
  CREATE TABLE t1(a);
  CREATE TABLE t2(b);
  INSERT INTO t1(a) VALUES(0);
  CREATE VIEW v0(c) AS SELECT t2.b FROM t1 LEFT JOIN t2;
}

do_execsql_test join-19.1 {
  SELECT * FROM v0 WHERE v0.c NOTNULL NOTNULL; 
} {{}}

do_execsql_test join-19.2 {
  SELECT * FROM t1 LEFT JOIN t2
} {0 {}}

do_execsql_test join-19.3 {
  SELECT * FROM t1 LEFT JOIN t2 WHERE (b IS NOT NULL) IS NOT NULL; 
} {0 {}}

do_execsql_test join-19.4 {
  SELECT (b IS NOT NULL) IS NOT NULL FROM t1 LEFT JOIN t2
} {1}

do_execsql_test join-19.5 {
  SELECT * FROM t1 LEFT JOIN t2 WHERE 
    (b IS NOT NULL AND b IS NOT NULL) IS NOT NULL; 
} {0 {}}

# 2019-11-02 ticket 623eff57e76d45f6
# The optimization of exclusing the WHERE expression of a partial index
# from the WHERE clause of the query if the index is used does not work
# of the table of the index is the right-hand table of a LEFT JOIN.
#
db close
sqlite3 db :memory:
do_execsql_test join-20.1 {
  CREATE TABLE t1(c1);
  CREATE TABLE t0(c0);
  INSERT INTO t0(c0) VALUES (0);
  SELECT * FROM t0 LEFT JOIN t1 WHERE NULL IN (c1);
} {}
do_execsql_test join-20.2 {
  CREATE INDEX t1x ON t1(0) WHERE NULL IN (c1);
  SELECT * FROM t0 LEFT JOIN t1 WHERE NULL IN (c1);
} {}

# 2019-11-30 ticket 7f39060a24b47353
# Do not allow a WHERE clause term to qualify a partial index on the
# right table of a LEFT JOIN.
#
do_execsql_test join-21.10 {
  DROP TABLE t0;
  DROP TABLE t1;
  CREATE TABLE t0(aa);
  CREATE TABLE t1(bb);
  INSERT INTO t0(aa) VALUES (1);
  INSERT INTO t1(bb) VALUES (1);
  SELECT 11, * FROM t1 LEFT JOIN t0 WHERE aa ISNULL;
  SELECT 12, * FROM t1 LEFT JOIN t0 WHERE +aa ISNULL;
  SELECT 13, * FROM t1 LEFT JOIN t0 ON aa ISNULL;
  SELECT 14, * FROM t1 LEFT JOIN t0 ON +aa ISNULL;
  CREATE INDEX i0 ON t0(aa) WHERE aa ISNULL;
  SELECT 21, * FROM t1 LEFT JOIN t0 WHERE aa ISNULL;
  SELECT 22, * FROM t1 LEFT JOIN t0 WHERE +aa ISNULL;
  SELECT 23, * FROM t1 LEFT JOIN t0 ON aa ISNULL;
  SELECT 24, * FROM t1 LEFT JOIN t0 ON +aa ISNULL;
} {13 1 {} 14 1 {} 23 1 {} 24 1 {}}

# 2019-12-18 problem with a LEFT JOIN where the RHS is a view.
# Detected by Yongheng and Rui.
# Follows from the optimization attempt of check-in 41c27bc0ff1d3135
# on 2017-04-18
#
reset_db
do_execsql_test join-22.10 {
  CREATE TABLE t0(a, b);
  CREATE INDEX t0a ON t0(a);
  INSERT INTO t0 VALUES(10,10),(10,11),(10,12);
  SELECT DISTINCT c FROM t0 LEFT JOIN (SELECT a+1 AS c FROM t0) ORDER BY c ;
} {11}

# 2019-12-22 ticket 7929c1efb2d67e98
#
reset_db
ifcapable vtab {
do_execsql_test join-23.10 {
  CREATE TABLE t0(c0);
  INSERT INTO t0(c0) VALUES(123);
  CREATE VIEW v0(c0) AS SELECT 0 GROUP BY 1;
  SELECT t0.c0, v0.c0, vt0.name
   FROM v0, t0 LEFT JOIN pragma_table_info('t0') AS vt0
     ON vt0.name LIKE 'c0'
   WHERE v0.c0 == 0;
} {123 0 c0}
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test join-24.1 {
  CREATE TABLE t1(a PRIMARY KEY, x);
  CREATE TABLE t2(b INT);
  CREATE INDEX t1aa ON t1(a, a);

  INSERT INTO t1 VALUES('abc', 'def');
  INSERT INTO t2 VALUES(1);
}

do_execsql_test join-24.2 {
  SELECT * FROM t2 JOIN t1 WHERE a='abc' AND x='def';
} {1 abc def}
do_execsql_test join-24.3 {
  SELECT * FROM t2 JOIN t1 WHERE a='abc' AND x='abc';
} {}

do_execsql_test join-24.2 {
  SELECT * FROM t2 LEFT JOIN t1 ON a=0 WHERE (x='x' OR x IS NULL);
} {1 {} {}}

# 2020-09-30 ticket 66e4b0e271c47145
# The query flattener inserts an "expr AND expr" expression as a substitution
# for the column of a view where that view column is part of an ON expression
# of a LEFT JOIN.
#
reset_db
do_execsql_test join-25.1 {
  CREATE TABLE t0(c0 INT);
  CREATE VIEW v0 AS SELECT (NULL AND 5) as c0 FROM t0;
  INSERT INTO t0(c0) VALUES (NULL);
  SELECT count(*)  FROM v0 LEFT JOIN t0 ON v0.c0;
} {1}

# 2022-04-21 Parser issue detected by dbsqlfuzz
#
reset_db
do_catchsql_test join-26.1 {
  CREATE TABLE t4(a,b);
  CREATE TABLE t5(a,c);
  CREATE TABLE t6(a,d);
  SELECT * FROM t5 JOIN ((t4 JOIN (t5 JOIN t6)) t7);
} {/1 {.*}/}

# 2022-06-09 Invalid subquery flattening caused by
# check-in 3f45007d544e5f78 and detected by dbsqlfuzz
#
reset_db
do_execsql_test join-27.1 {
  CREATE TABLE t1(a INT,b INT,c INT);  INSERT INTO t1 VALUES(NULL,NULL,NULL);
  CREATE TABLE t2(d INT,e INT);        INSERT INTO t2 VALUES(NULL,NULL);
  CREATE INDEX x2 ON t1(c,b);
  CREATE TABLE t3(x INT);              INSERT INTO t3 VALUES(NULL);
}
do_execsql_test join-27.2 {
  WITH t99(b) AS MATERIALIZED (
    SELECT b FROM t2 LEFT JOIN t1 ON c IN (SELECT x FROM t3)
  )
  SELECT 5 FROM t2 JOIN t99 ON b IN (1,2,3);
} {}
do_execsql_test join-27.3 {
  WITH t99(b) AS NOT MATERIALIZED (
    SELECT b FROM t2 LEFT JOIN t1 ON c IN (SELECT x FROM t3)
  )
  SELECT 5 FROM t2 JOIN t99 ON b IN (1,2,3);
} {}
do_execsql_test join-27.4 {
  WITH t99(b) AS (SELECT b FROM t2 LEFT JOIN t1 ON c IN (SELECT x FROM t3))
  SELECT 5 FROM t2 JOIN t99 ON b IN (1,2,3);
} {}
do_execsql_test join-27.5 {
  SELECT 5
    FROM t2 JOIN (
       SELECT b FROM t2 LEFT JOIN t1 ON c IN (SELECT x FROM t3)
    ) AS t99 ON b IN (1,2,3);
} {}

db null NULL
do_execsql_test join-27.6 {
  INSERT INTO t1 VALUES(3,4,NULL);
  INSERT INTO t2 VALUES(1,2);
  WITH t99(b) AS (
    SELECT coalesce(b,3) FROM t2 AS x LEFT JOIN t1 ON c IN (SELECT x FROM t3)
  )
  SELECT d, e, b FROM t2 JOIN t99 ON b IN (1,2,3) ORDER BY +d;
} {NULL NULL 3 NULL NULL 3 1 2 3 1 2 3}
do_execsql_test join-27.7 {
  SELECT d, e, b2
    FROM t2 
         JOIN (SELECT coalesce(b,3) AS b2 FROM t2 AS x LEFT JOIN t1
                ON c IN (SELECT x FROM t3)) AS t99
            ON b2 IN (1,2,3) ORDER BY +d;
} {NULL NULL 3 NULL NULL 3 1 2 3 1 2 3}

do_execsql_test join-27.8 {
  DELETE FROM t1;
  DELETE FROM t2 WHERE d IS NOT NULL;
  DELETE FROM t3;
  SELECT * FROM t2 JOIN (SELECT b FROM t2 LEFT JOIN t1
                       ON c IN (SELECT x FROM t3)) AS t99 ON b IN (1,2,3);
} {}

do_execsql_test join-27.9 {
  DELETE FROM t1;
  DELETE FROM t2;
  DELETE FROM t3;
  INSERT INTO t1 VALUES(4,3,5);
  INSERT INTO t2 VALUES(1,2);
  INSERT INTO t3 VALUES(5);
  SELECT * FROM t2 JOIN (SELECT b FROM t2 LEFT JOIN t1
                       ON c IN (SELECT x FROM t3)) AS t99 ON b IS NULL;
} {}
do_execsql_test join-27.10 {
  WITH t99(b) AS (
    SELECT b FROM t2 AS x LEFT JOIN t1 ON c IN (SELECT x FROM t3)
  )
  SELECT d, e, b FROM t2 JOIN t99 ON b IS NULL;
} {}


# 2022-09-19 https://sqlite.org/forum/forumpost/96b9e5709cf47cda
# Performance regression relative to version 3.38.0 that resulted from
# a new query flattener restriction that was added to fixes the join-27.*
# tests above.  The restriction needed to be removed and the join-27.*
# problem fixed another way.
#
reset_db
do_execsql_test join-28.1 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b INT, c INT);
  CREATE TABLE t2(d INTEGER PRIMARY KEY, e INT);
  CREATE VIEW t3(a,b,c,d,e) AS SELECT * FROM t1 LEFT JOIN t2 ON d=c;
  CREATE TABLE t4(x INT, y INT);
  INSERT INTO t1 VALUES(1,2,3);
  INSERT INTO t2 VALUES(1,5);
  INSERT INTO t4 VALUES(1,4);
  SELECT a, b, y FROM t4 JOIN t3 ON a=x;
} {1 2 4}
do_eqp_test join-28.2 {
  SELECT a, b, y FROM t4 JOIN t3 ON a=x;
} {
  QUERY PLAN
  |--SCAN t4
  `--SEARCH t1 USING INTEGER PRIMARY KEY (rowid=?)
}
# ^^^^^^^ Without the fix (if the query flattening optimization does not
# run) the query plan above would look like this:
#
#   QUERY PLAN
#   |--MATERIALIZE t3
#   |  |--SCAN t1
#   |  `--SEARCH t2 USING INTEGER PRIMARY KEY (rowid=?) LEFT-JOIN
#   |--SCAN t4
#   `--SEARCH t3 USING AUTOMATIC COVERING INDEX (a=?)

finish_test

Changes to test/join2.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
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







+
+
+
+
+
+






+
+
+
+
+
+



















+
+
+







} {1 11 111 1111 3 33 333 {}}
do_test join2-1.6 {
  execsql {
    SELECT * FROM
      t1 NATURAL LEFT OUTER JOIN t2 NATURAL JOIN t3
  }
} {1 11 111 1111}
do_test join2-1.6-rj {
  execsql {
    SELECT * FROM
      t2 NATURAL RIGHT OUTER JOIN t1 NATURAL JOIN t3
  }
} {11 111 1 1111}
ifcapable subquery {
  do_test join2-1.7 {
    execsql {
      SELECT * FROM
        t1 NATURAL LEFT OUTER JOIN (t2 NATURAL JOIN t3)
    }
  } {1 11 111 1111 2 22 {} {} 3 33 {} {}}
  do_test join2-1.7-rj {
    execsql {
      SELECT a, b, c, d FROM
        t2 NATURAL JOIN t3 NATURAL RIGHT JOIN t1
    }
  } {1 11 111 1111 2 22 {} {} 3 33 {} {}}
}

#-------------------------------------------------------------------------
# Check that ticket [25e335f802ddc] has been resolved. It should be an
# error for the ON clause of a LEFT JOIN to refer to a table to its right.
#
do_execsql_test 2.0 {
  CREATE TABLE aa(a);
  CREATE TABLE bb(b);
  CREATE TABLE cc(c);
  INSERT INTO aa VALUES('one');
  INSERT INTO bb VALUES('one');
  INSERT INTO cc VALUES('one');
}

do_catchsql_test 2.1 {
  SELECT * FROM aa LEFT JOIN cc ON (a=b) JOIN bb ON (b=coalesce(c,1));
} {1 {ON clause references tables to its right}}
do_catchsql_test 2.1b {
  SELECT * FROM aa RIGHT JOIN cc ON (a=b) JOIN bb ON (b=coalesce(c,1));
} {1 {ON clause references tables to its right}}
do_catchsql_test 2.2 {
  SELECT * FROM aa JOIN cc ON (a=b) JOIN bb ON (b=c);
} {0 {one one one}}

#-------------------------------------------------------------------------
# Test that a problem causing where.c to overlook opportunities to
# omit unnecessary tables from a LEFT JOIN when UNIQUE, NOT NULL column 
109
110
111
112
113
114
115
116
117


118
119
120
121
122
123
124
125


126
127
128
129
130
131
132
124
125
126
127
128
129
130


131
132
133
134
135
136
137
138


139
140
141
142
143
144
145
146
147







-
-
+
+






-
-
+
+







  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=?) LEFT-JOIN
}

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=?) LEFT-JOIN
}

#-------------------------------------------------------------------------
# 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
172
173
174
175
176
177
178



179
180
181
182
183
184
185
186


187
188
189
190
191
192
193
194
195







-
-
-
+
+
+





-
-
+
+







  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=?) LEFT-JOIN
  `--SEARCH c3 USING INTEGER PRIMARY KEY (rowid=?) LEFT-JOIN
}
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=?) LEFT-JOIN
}

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
219
220
221
222
223
224
225



226
227
228
229
230
231
232
233


234
235
236
237
238
239
240
241
242







-
-
-
+
+
+





-
-
+
+







  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=?) LEFT-JOIN
  `--SEARCH c3 USING INDEX sqlite_autoindex_c3_1 (k=?) LEFT-JOIN
}
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=?) LEFT-JOIN
}

# 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
275
276
277
278
279
280
281


282



























































283
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







-
+



-
+








-
+














+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  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);
  CREATE VIEW test AS
    SELECT *, 'x'
      FROM t1 LEFT JOIN (SELECT * FROM t2, t3) ON (c=b AND x=9)
      WHERE c IS NULL;
  SELECT * FROM test;
} {3 4 {} {} {} x 5 6 {} {} {} x}

#-------------------------------------------------------------------------
# Ticket [dfd66334].

#
reset_db
do_execsql_test 8.0 {
  CREATE TABLE t0(c0);
  CREATE TABLE t1(c0);
}

do_execsql_test 8.1 {
  SELECT * FROM t0 LEFT JOIN t1 
  WHERE (t1.c0 BETWEEN 0 AND 0) > ('' AND t0.c0);
}

#-------------------------------------------------------------------------
# Ticket [45f4bf4eb] reported by Manuel Rigger (2020-04-25)
#
# Follow up error reported by Eric Speckman on the SQLite forum
# https://sqlite.org/forum/info/c49496d24d35bd7c (2020-08-19)
#
reset_db
do_execsql_test 9.0 {
  CREATE TABLE t0(c0 INT);
  CREATE VIEW v0(c0) AS SELECT CAST(t0.c0 AS INTEGER) FROM t0;
  INSERT INTO t0(c0) VALUES (0);
}

do_execsql_test 9.1 {
  SELECT typeof(c0), c0 FROM v0 WHERE c0>='0'
} {integer 0}

do_execsql_test 9.2 {
  SELECT * FROM t0, v0 WHERE v0.c0 >= '0';
} {0 0}

do_execsql_test 9.3 {
  SELECT * FROM t0 LEFT JOIN v0 WHERE v0.c0 >= '0';
} {0 0}

do_execsql_test 9.4 {
  SELECT * FROM t0 LEFT JOIN v0 ON v0.c0 >= '0';
} {0 0}

do_execsql_test 9.5 {
  SELECT * FROM t0 LEFT JOIN v0 ON v0.c0 >= '0' WHERE TRUE 
  UNION SELECT 0,0 WHERE 0; 
} {0 0}

do_execsql_test 9.10 {
  CREATE TABLE t1 (aaa);
  INSERT INTO t1 VALUES(23456);
  CREATE TABLE t2(bbb);
  CREATE VIEW v2(ccc) AS SELECT bbb IS 1234 FROM t2;
  SELECT ccc, ccc IS NULL AS ddd FROM t1 LEFT JOIN v2;
} {{} 1}
optimization_control db query-flattener 0
do_execsql_test 9.11 {
  SELECT ccc, ccc IS NULL AS ddd FROM t1 LEFT JOIN v2;
} {{} 1}


finish_test

Changes to test/join5.test.

236
237
238
239
240
241
242












243
244
245
246
247
248
249
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







+
+
+
+
+
+
+
+
+
+
+
+







  SELECT ifnull(z, '!!!') FROM t3 LEFT JOIN t4 ON (x=y);
} {!!!}

do_execsql_test 6.3.2 {
  CREATE INDEX t4i ON t4(y, ifnull(z, '!!!'));
  SELECT ifnull(z, '!!!') FROM t3 LEFT JOIN t4 ON (x=y);
} {!!!}

# 2019-02-08 https://sqlite.org/src/info/4e8e4857d32d401f
reset_db
do_execsql_test 6.100 {
  CREATE TABLE t1(aa, bb);
  CREATE INDEX t1x1 on t1(abs(aa), abs(bb));
  INSERT INTO t1 VALUES(-2,-3),(+2,-3),(-2,+3),(+2,+3);
  SELECT * FROM (t1) 
   WHERE ((abs(aa)=1 AND 1=2) OR abs(aa)=2)
     AND abs(bb)=3
  ORDER BY +1, +2;
} {-2 -3 -2 3 2 -3 2 3}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 7.0 {
  CREATE TABLE t1(x);
  INSERT INTO t1 VALUES(1);
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
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







-
+

+
-
-
+
+
+



















-
-
+
+
+
+
+
+
+
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


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 TABLE t2 USING INDEX t2xy (x=? AND y=?)
     |  `--SEARCH t2 USING INDEX t2xy (x=? AND y=?) LEFT-JOIN
     `--INDEX 2
        `--SEARCH t2 USING INDEX t2xy (x=? AND y=?) LEFT-JOIN
}

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=?) LEFT-JOIN
} 
do_eqp_test 7.4b {
  SELECT * FROM t3 CROSS JOIN t4 ON (t4.x = t3.x) WHERE (+t4.y = ? OR t4.z = ?);
} {
  QUERY PLAN
  |--SCAN t3
  |--BLOOM FILTER ON t4 (x=?)
  `--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);

  INSERT INTO t1 VALUES (2);

  INSERT INTO t0 VALUES(0, 10);
  INSERT INTO t0 VALUES(1, 10);
  INSERT INTO t0 VALUES(2, 10);
  INSERT INTO t0 VALUES(3, 10);
}

do_execsql_test 8.1 {
  SELECT * FROM t0, t1 
  WHERE (t0.c1 >= 1 OR t0.c1 < 1) AND t0.c0 IN (1, t1.c0) ORDER BY 1;
} {
  1 10 2
  2 10 2
}


# 2022-01-31 dbsqlfuzz 787d9bd73164c6f0c85469e2e48b2aff19af6938
#
reset_db
do_execsql_test 9.1 {
  CREATE TABLE t1(a ,b FLOAT);
  INSERT INTO t1 VALUES(1,1);
  CREATE INDEX t1x1 ON t1(a,b,a,a,a,a,a,a,a,a,a,b);
  ANALYZE sqlite_schema;
  INSERT INTO sqlite_stat1 VALUES('t1','t1x1','648 324 81 81 81 81 81 81 81081 81 81 81');
  ANALYZE sqlite_schema;
  SELECT a FROM (SELECT a FROM t1 NATURAL LEFT JOIN t1) NATURAL LEFT JOIN t1 WHERE (rowid,1)<=(5,0);
} {1}

# 2022-03-02 https://sqlite.org/forum/info/50a1bbe08ce4c29c
# Bloom-filter pulldown is incompatible with skip-scan.
#
reset_db
do_execsql_test 10.1 {
  CREATE TABLE t1(x INT);
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<20)
    INSERT INTO t1(x) SELECT 0 FROM c;
  CREATE INDEX t1x1 ON t1(x BETWEEN 0 AND 10, x);
  ANALYZE;
  DELETE FROM t1;
  INSERT INTO t1 VALUES(0),(0);
  CREATE VIEW v1 AS SELECT * FROM t1 NATURAL JOIN t1 WHERE (x BETWEEN 0 AND 10) OR true;
  CREATE VIEW v2 AS SELECT * FROM v1 NATURAL JOIN v1;
  CREATE VIEW v3 AS SELECT * FROM v2, v1 USING (x) GROUP BY x;
  SELECT x FROM v3; 
} {0}

# 2022-03-24 https://sqlite.org/forum/forumpost/031e262a89b6a9d2
# Bloom-filter on a LEFT JOIN with NULL-based WHERE constraints.
#
reset_db
do_execsql_test 11.1 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b INT);
  CREATE TABLE t2(c INTEGER PRIMARY KEY, d INT);
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<8)
  INSERT INTO t1(a,b) SELECT x, 10*x FROM c;
  INSERT INTO t2(c,d) SELECT b*2, 100*a FROM t1;
  ANALYZE;
  DELETE FROM sqlite_stat1;
  INSERT INTO sqlite_stat1(tbl,idx,stat) VALUES
    ('t1',NULL,150105),('t2',NULL,98747);
  ANALYZE sqlite_schema;
} {}
do_execsql_test 11.2 {
  SELECT count(*) FROM t1 LEFT JOIN t2 ON c=b WHERE d IS NULL;
} {4}
do_execsql_test 11.3 {
  SELECT count(*) FROM t1 LEFT JOIN t2 ON c=b WHERE d=100;
} {1}
do_execsql_test 11.4 {
  SELECT count(*) FROM t1 LEFT JOIN t2 ON c=b WHERE d>=300;
} {2}

# 2022-05-03 https://sqlite.org/forum/forumpost/2482b32700384a0f
# Bloom-filter pull-down does not handle NOT NULL constraints correctly.
#
reset_db
do_execsql_test 12.1 {
  CREATE TABLE t1(a INT, b INT, c INT);
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100)
    INSERT INTO t1(a,b,c) SELECT x, x*1000, x*1000000 FROM c;
  CREATE TABLE t2(b INT, x INT);
  INSERT INTO t2(b,x) SELECT b, a FROM t1 WHERE a%3==0;
  CREATE INDEX t2b ON t2(b);
  CREATE TABLE t3(c INT, y INT);
  INSERT INTO t3(c,y) SELECT c, a FROM t1 WHERE a%4==0;
  CREATE INDEX t3c ON t3(c);
  INSERT INTO t1(a,b,c) VALUES(200, 200000, NULL);
  ANALYZE;
} {}
do_execsql_test 12.2 {
  SELECT * FROM t1 NATURAL JOIN t2 NATURAL JOIN t3 WHERE x>0 AND y>0
  ORDER BY +a;
} {
  12  12000  12000000  12  12
  24  24000  24000000  24  24
  36  36000  36000000  36  36
  48  48000  48000000  48  48
  60  60000  60000000  60  60
  72  72000  72000000  72  72
  84  84000  84000000  84  84
  96  96000  96000000  96  96
}




finish_test

Changes to test/join6.test.

143
144
145
146
147
148
149
















150
151
152
153
154
155
156
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    execsql {
      SELECT * FROM t1 NATURAL JOIN t2 NATURAL JOIN
         (SELECT 5 AS c, 91 AS x, 93 AS z UNION SELECT 6, 99, 95)
    }
  } {1 91 92 3 93 5}
}

do_execsql_test join6-5.1 {
  CREATE TABLE tx(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o PRIMARY KEY) 
  WITHOUT ROWID;
  INSERT INTO tx VALUES(
    1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
  );
} {}
do_execsql_test joint6-5.2 {
  SELECT o FROM tx NATURAL JOIN tx;
} {15}

do_execsql_test join6-5.3 {
  CREATE TABLE ty(a,Ñ,x6,x7,x8,Q,I,v,x1,L,E,x2,x3,x4,x5,s,g PRIMARY KEY,b,c)
  WITHOUT ROWID;
  SELECT a FROM ty NATURAL JOIN ty;
}







Added test/join7.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022-04-09
#
# 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 file implements tests for RIGHT and FULL OUTER JOINs.

set testdir [file dirname $argv0]
source $testdir/tester.tcl

foreach {id schema} {
  1 {
    CREATE TABLE t1(a INT, b INT);
    INSERT INTO t1 VALUES(1,2),(1,3),(1,4);
    CREATE INDEX t1a ON t1(a);
    CREATE TABLE t2(c INT, d INT);
    INSERT INTO t2 VALUES(3,33),(4,44),(5,55);
    CREATE INDEX t2c ON t2(c);
    CREATE VIEW dual(dummy) AS VALUES('x');
  }
  2 {
    CREATE TABLE t1(a INT, b INT);
    INSERT INTO t1 VALUES(1,2),(1,3),(1,4);
    CREATE INDEX t1ab ON t1(a,b);
    CREATE TABLE t2(c INT, d INT);
    INSERT INTO t2 VALUES(3,33),(4,44),(5,55);
    CREATE INDEX t2cd ON t2(c,d);
    CREATE VIEW dual(dummy) AS VALUES('x');
  }
  3 {
    CREATE TABLE t1(a INT, b INT);
    INSERT INTO t1 VALUES(1,2),(1,3),(1,4);
    CREATE INDEX t1a ON t1(a);
    CREATE TABLE t2(c INT, d INT PRIMARY KEY) WITHOUT ROWID;
    INSERT INTO t2 VALUES(3,33),(4,44),(5,55);
    CREATE INDEX t2c ON t2(c);
    CREATE VIEW dual(dummy) AS VALUES('x');
  }
  4 {
    CREATE TABLE t1(a INT, b INT);
    INSERT INTO t1 VALUES(1,2),(1,3),(1,4);
    CREATE TABLE t2(c INTEGER PRIMARY KEY, d INT);
    INSERT INTO t2 VALUES(3,33),(4,44),(5,55);
    CREATE VIEW dual(dummy) AS VALUES('x');
  }
  5 {
    CREATE TABLE t1(a INT, b INT);
    INSERT INTO t1 VALUES(1,2),(1,3),(1,4);
    CREATE TABLE t2(c INT PRIMARY KEY, d INT) WITHOUT ROWID;
    INSERT INTO t2 VALUES(3,33),(4,44),(5,55);
    CREATE VIEW dual(dummy) AS VALUES('x');
  }
  6 {
    CREATE TABLE t1(a INT, b INT);
    INSERT INTO t1 VALUES(1,2),(1,3),(1,4);
    CREATE VIEW t2(c,d) AS VALUES(3,33),(4,44),(5,55);
    CREATE VIEW dual(dummy) AS VALUES('x');
  }
  7 {
    CREATE VIEW t1(a,b) AS VALUES(1,2),(1,3),(1,4);
    CREATE TABLE t2(c INTEGER PRIMARY KEY, d INT);
    INSERT INTO t2 VALUES(3,33),(4,44),(5,55);
    CREATE VIEW dual(dummy) AS VALUES('x');
  }
  8 {
    CREATE TABLE t1(a INT, b INT);
    INSERT INTO t1 VALUES(1,2),(1,3),(1,4);
    CREATE TABLE t2(c INT, d INT);
    INSERT INTO t2 VALUES(3,33),(4,44),(5,55);
    CREATE VIEW dual(dummy) AS VALUES('x');
  }
  9 {
    CREATE TABLE t1(a INT, b INT);
    INSERT INTO t1 VALUES(1,2),(1,3),(1,4);
    CREATE TABLE t2a(c INTEGER PRIMARY KEY, i1 INT);
    CREATE TABLE t2b(i1 INTEGER PRIMARY KEY, d INT);
    CREATE VIEW t2(c,d) AS SELECT c, d FROM t2a NATURAL JOIN t2b;
    INSERT INTO t2a VALUES(3,93),(4,94),(5,95),(6,96),(7,97);
    INSERT INTO t2b VALUES(91,11),(92,22),(93,33),(94,44),(95,55);
    CREATE TABLE dual(dummy TEXT);
    INSERT INTO dual(dummy) VALUES('x');
  }
  10 {
    CREATE TABLE t1(a INT, b INT, PRIMARY KEY(a,b)) WITHOUT ROWID;
    INSERT INTO t1 VALUES(1,2),(1,3),(1,4);
    CREATE TABLE t2a(c INTEGER PRIMARY KEY, i1 INT);
    CREATE TABLE t2b(i1 INTEGER PRIMARY KEY, d INT);
    CREATE VIEW t2(c,d) AS SELECT c, d FROM t2a NATURAL JOIN t2b;
    INSERT INTO t2a VALUES(3,93),(4,94),(5,95),(6,96),(7,97);
    INSERT INTO t2b VALUES(91,11),(92,22),(93,33),(94,44),(95,55);
    CREATE TABLE dual(dummy TEXT);
    INSERT INTO dual(dummy) VALUES('x');
  }
} {
  reset_db
  db nullvalue NULL
  do_execsql_test join7-$id.setup $schema {}

  # Verified against PG-14 for case 1
  do_execsql_test join7-$id.10 {
    SELECT b, d FROM t1 FULL OUTER JOIN t2 ON b=c ORDER BY +b;
  } {
    NULL 55
    2    NULL
    3    33
    4    44
  }

  # Verified against PG-14 for case 1
  do_execsql_test join7-$id.20 {
    SELECT a, c FROM t1 FULL OUTER JOIN t2 ON b=c ORDER BY +b;
  } {
    NULL  5
    1     NULL
    1     3
    1     4
  }

  do_execsql_test join7-$id.30 {
    SELECT * FROM t1 FULL OUTER JOIN t2 ON b=c ORDER BY +b;
  } {
    NULL NULL 5    55
    1    2    NULL NULL
    1    3    3    33
    1    4    4    44
  }
  do_execsql_test join7-$id.31 {
    SELECT t1.*, t2.* FROM t2 FULL OUTER JOIN t1 ON b=c ORDER BY +b;
  } {
    NULL NULL 5    55
    1    2    NULL NULL
    1    3    3    33
    1    4    4    44
  }
  do_execsql_test join7-$id.32 {
    SELECT t1.*, t2.* FROM t2 FULL OUTER JOIN t1 ON b=c
     WHERE b=c
     ORDER BY +b;
  } {
    1    3    3    33
    1    4    4    44
  }
  do_execsql_test join7-$id.33 {
    SELECT t1.*, t2.* FROM t2 FULL OUTER JOIN t1 ON b=c
     WHERE b>0
     ORDER BY +b;
  } {
    1    2    NULL NULL
    1    3    3    33
    1    4    4    44
  }
  do_execsql_test join7-$id.34 {
    SELECT t1.*, t2.* FROM t2 FULL OUTER JOIN t1 ON b=c
     WHERE b>0 OR b IS NULL
     ORDER BY +b;
  } {
    NULL NULL 5    55
    1    2    NULL NULL
    1    3    3    33
    1    4    4    44
  }
  do_execsql_test join7-$id.35 {
    SELECT t1.*, t2.* FROM t2 FULL OUTER JOIN t1 ON b=c AND b>3 AND c>4
     ORDER BY coalesce(b,c,0);
  } {
    1    2    NULL NULL
    NULL NULL 3    33
    1    3    NULL NULL
    NULL NULL 4    44
    1    4    NULL NULL
    NULL NULL 5    55
  }
  do_execsql_test join7-$id.36 {
    SELECT t1.*, t2.* FROM t2 FULL OUTER JOIN t1 ON b=c AND b>3 WHERE c>4
     ORDER BY coalesce(b,c,0);
  } {
    NULL NULL 5    55
  }
  do_execsql_test join7-$id.37 {
    SELECT t1.*, t2.* FROM t2 FULL OUTER JOIN t1 ON b=c WHERE b>3 AND c>4
     ORDER BY coalesce(b,c,0);
  } {
  }
  do_execsql_test join7-$id.38 {
    SELECT t1.*, t2.* FROM t2 FULL OUTER JOIN t1 ON b=c WHERE b>3 OR c>4
     ORDER BY coalesce(b,c,0);
  } {
    1    4    4    44
    NULL NULL 5    55
  }
  do_execsql_test join7-$id.39 {
    SELECT t1.*, t2.* FROM t2 FULL OUTER JOIN t1 ON b=c AND (b>3 OR c>4)
     ORDER BY coalesce(b,c,0);
  } {
    1    2    NULL NULL
    NULL NULL 3    33
    1    3    NULL NULL
    1    4    4    44
    NULL NULL 5    55
  }
  do_execsql_test join7-$id.40 {
    SELECT * FROM t1 RIGHT OUTER JOIN t2 ON b=c ORDER BY +b;
  } {
    NULL NULL 5    55
    1    3    3    33
    1    4    4    44
  }
  do_execsql_test join7-$id.50 {
    SELECT t1.*, t2.* FROM t2 LEFT OUTER JOIN t1 ON b=c ORDER BY +b;
  } {
    NULL NULL 5    55
    1    3    3    33
    1    4    4    44
  }
  do_execsql_test join7-$id.60 {
    SELECT * FROM dual JOIN t1 ON true RIGHT OUTER JOIN t2 ON b=c ORDER BY +b;
  } {
    NULL NULL NULL 5    55
    x    1    3    3    33
    x    1    4    4    44
  }
  do_execsql_test join7-$id.70 {
    SELECT t1.*, t2.* 
      FROM t2 LEFT JOIN (dual JOIN t1 ON true) ON b=c ORDER BY +b;
  } {
    NULL NULL 5    55
    1    3    3    33
    1    4    4    44
  }
  do_execsql_test join7-$id.80 {
    SELECT * FROM dual CROSS JOIN t1 RIGHT OUTER JOIN t2 ON b=c ORDER BY +b;
  } {
    NULL NULL NULL 5    55
    x    1    3    3    33
    x    1    4    4    44
  }
  do_execsql_test join7-$id.81 {
    SELECT dual.*, t1.*, t2.*
      FROM t1 CROSS JOIN dual RIGHT OUTER JOIN t2 ON b=c ORDER BY +b;
  } {
    NULL NULL NULL 5    55
    x    1    3    3    33
    x    1    4    4    44
  }
  do_execsql_test join7-$id.90 {
    SELECT * FROM t1 LEFT OUTER JOIN t2 ON b=c ORDER BY +b;
  } {
    1    2    NULL NULL
    1    3    3    33
    1    4    4    44
  }
  do_execsql_test join7-$id.100 {
    SELECT * FROM t1 FULL OUTER JOIN t2 ON b=c AND a=1 ORDER BY +b;
  } {
    NULL NULL 5    55
    1    2    NULL NULL
    1    3    3    33
    1    4    4    44
  }
  do_execsql_test join7-$id.101 {
    SELECT t1.*, t2.* FROM t2 FULL OUTER JOIN t1 ON b=c AND a=1 ORDER BY +b;
  } {
    NULL NULL 5    55
    1    2    NULL NULL
    1    3    3    33
    1    4    4    44
  }

  # Verified against PG-14 for case 1
  do_execsql_test join7-$id.110 {
    SELECT * FROM t1 FULL OUTER JOIN t2 ON b=c WHERE a=1 ORDER BY +b;
  } {
    1    2    NULL NULL
    1    3    3    33
    1    4    4    44
  }

  do_execsql_test join7-$id.111 {
    SELECT t1.*, t2.* FROM t2 FULL OUTER JOIN t1 ON b=c WHERE a=1 ORDER BY +b;
  } {
    1    2    NULL NULL
    1    3    3    33
    1    4    4    44
  }

  # Verified against PG-14 for case 1
  do_execsql_test join7-$id.115 {
    SELECT * FROM t1 FULL OUTER JOIN t2 ON b=c
     WHERE a=1 OR a IS NULL ORDER BY +b;
  } {
    NULL NULL 5    55
    1    2    NULL NULL
    1    3    3    33
    1    4    4    44
  }

  do_execsql_test join7-$id.116 {
    SELECT t1.*, t2.* FROM t2 FULL OUTER JOIN t1 ON b=c
     WHERE a=1 OR a IS NULL ORDER BY +b;
  } {
    NULL NULL 5    55
    1    2    NULL NULL
    1    3    3    33
    1    4    4    44
  }

  # Verified against PG-14 for case 1:
  do_execsql_test join7-$id.120 {
    SELECT * FROM t1 FULL OUTER JOIN t2 ON b=c WHERE a IS NULL ORDER BY +d;
  } {
    NULL NULL 5    55
  }

  # Verified against PG-14 for case 1:
  do_execsql_test join7-$id.130 {
    SELECT * FROM t1 FULL OUTER JOIN t2 ON b=c AND d<=0 ORDER BY +b, +d;
  } {
    NULL NULL 3    33
    NULL NULL 4    44
    NULL NULL 5    55
    1    2    NULL NULL
    1    3    NULL NULL
    1    4    NULL NULL
  }

  # Verified against PG-14 for case 1:
  do_execsql_test join7-$id.140 {
    SELECT a, b, c, d
      FROM t2 FULL OUTER JOIN t1 ON b=c AND d<=0 ORDER BY +b, +d;
  } {
    NULL NULL 3    33
    NULL NULL 4    44
    NULL NULL 5    55
    1    2    NULL NULL
    1    3    NULL NULL
    1    4    NULL NULL
  }

  do_execsql_test join7-$id.141 {
    SELECT a, b, c, d
      FROM t2 FULL OUTER JOIN t1 ON b=c AND d<=0
     ORDER BY +b, +d LIMIT 2 OFFSET 2
  } {
    NULL NULL 5    55
    1    2    NULL NULL
  }
}  
finish_test

Added test/join8.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
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022-04-12
#
# 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 tests for RIGHT and FULL OUTER JOINs.

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable !vtab {
  finish_test
  return
}

db null NULL
# EVIDENCE-OF: R-33754-02880 you can say "LEFT RIGHT JOIN" which is the
# same as "FULL JOIN".
do_execsql_test join8-10 {
  CREATE TABLE t1(a,b,c);
  CREATE TABLE t2(x,y);
  CREATE INDEX t2x ON t2(x);
  SELECT avg(DISTINCT b) FROM (SELECT * FROM t2 LEFT RIGHT JOIN t1 ON c);
} {NULL}

# Pending optimization opportunity:
# Row-value initialization subroutines must be called from with the
# RIGHT JOIN body subroutine before the first use of any register containing
# the results of that subroutine.  This seems dodgy.  Test case:
#
reset_db
do_execsql_test join8-1000 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT,b,c,d,e,f,g,h,j,k,l,m,n,o,p,q,r,s);
  CREATE INDEX t1x1 ON t1(g+h,j,k);
  CREATE INDEX t1x2 ON t1(b);
  INSERT INTO t1 DEFAULT VALUES;
} {}
do_catchsql_test join8-1010 {
  SELECT a
    FROM (
          SELECT a
            FROM (
                  SELECT a
                    FROM (
                          SELECT a FROM t1 NATURAL LEFT JOIN t1
                           WHERE (b, 2 ) IS ( SELECT 2 IN(2,2),2)
                         )
                    NATURAL LEFT FULL JOIN t1
                   WHERE ( rowid , 1 )<=(CASE 5 WHEN 619 THEN 841 ELSE 3374391096 END,0)
                   ORDER BY a ASC
                 )
            NATURAL LEFT JOIN t1
           WHERE (b, 2 ) IS ( SELECT 3 IN(3,3),3)
         )
    NATURAL LEFT FULL JOIN t1
   WHERE ( rowid , 1 )<=(CASE 5 WHEN 619 THEN 841 ELSE 3374391096 END,0)
   ORDER BY a ASC;
} {0 1}

# Pending issue #2: (now resolved)
# Jump to addrHalt inside the RIGHT JOIN body subroutine bypasses the
# OP_Return, resulting in a subroutine loop.  Test case:
#
reset_db
do_execsql_test join8-2000 {
  CREATE TABLE t1(a int, b int, c int);
  INSERT INTO t1 VALUES(1,2,3),(4,5,6);
  CREATE TABLE t2(d int, e int);
  INSERT INTO t2 VALUES(3,333),(4,444);
  CREATE TABLE t3(f int, g int);
  PRAGMA automatic_index=off;
} {}
do_catchsql_test join8-2010 {
  SELECT * FROM t1 RIGHT JOIN t2 ON c=d JOIN t3 ON f=e;
} {0 {}}

# Demonstrate that nested FULL JOINs and USING clauses work
#
reset_db
load_static_extension db series
do_execsql_test join8-3000 {
  CREATE TABLE t1(id INTEGER PRIMARY KEY, a INT);
  CREATE TABLE t2(id INTEGER PRIMARY KEY, b INT);
  CREATE TABLE t3(id INTEGER PRIMARY KEY, c INT);
  CREATE TABLE t4(id INTEGER PRIMARY KEY, d INT);
  CREATE TABLE t5(id INTEGER PRIMARY KEY, e INT);
  CREATE TABLE t6(id INTEGER PRIMARY KEY, f INT);
  CREATE TABLE t7(id INTEGER PRIMARY KEY, g INT);
  CREATE TABLE t8(id INTEGER PRIMARY KEY, h INT);
  INSERT INTO t1 SELECT value, 1 FROM generate_series(1,256) WHERE value & 1;
  INSERT INTO t2 SELECT value, 1 FROM generate_series(1,256) WHERE value & 2;
  INSERT INTO t3 SELECT value, 1 FROM generate_series(1,256) WHERE value & 4;
  INSERT INTO t4 SELECT value, 1 FROM generate_series(1,256) WHERE value & 8;
  INSERT INTO t5 SELECT value, 1 FROM generate_series(1,256) WHERE value & 16;
  INSERT INTO t6 SELECT value, 1 FROM generate_series(1,256) WHERE value & 32;
  INSERT INTO t7 SELECT value, 1 FROM generate_series(1,256) WHERE value & 64;
  INSERT INTO t8 SELECT value, 1 FROM generate_series(1,256) WHERE value & 128;
  CREATE TABLE t9 AS
    SELECT id, h, g, f, e, d, c, b, a
      FROM t1
      NATURAL FULL JOIN t2
      NATURAL FULL JOIN t3
      NATURAL FULL JOIN t4
      NATURAL FULL JOIN t5
      NATURAL FULL JOIN t6
      NATURAL FULL JOIN t7
      NATURAL FULL JOIN t8;
} {}
do_execsql_test join8-3010 {
  SELECT count(*) FROM t9;
} {255}
do_execsql_test join8-3020 {
  SELECT id, count(*) FROM t9 GROUP BY id HAVING count(*)!=1;
} {}
do_execsql_test join8-3030 {
  UPDATE t9 SET a=0 WHERE a IS NULL;
  UPDATE t9 SET b=0 WHERE b IS NULL;
  UPDATE t9 SET c=0 WHERE c IS NULL;
  UPDATE t9 SET d=0 WHERE d IS NULL;
  UPDATE t9 SET e=0 WHERE e IS NULL;
  UPDATE t9 SET f=0 WHERE f IS NULL;
  UPDATE t9 SET g=0 WHERE g IS NULL;
  UPDATE t9 SET h=0 WHERE h IS NULL;
  SELECT count(*) FROM t9 WHERE id=128*h+64*g+32*f+16*e+8*d+4*c+2*b+a;
} {255}
do_execsql_test join8-3040 {
  SELECT * FROM t9 WHERE id<>128*h+64*g+32*f+16*e+8*d+4*c+2*b+a;
} {}

# 2022-04-21 dbsqlfuzz find
#
reset_db
do_execsql_test join8-4000 {
  CREATE TABLE t1(x INTEGER PRIMARY KEY, a, b);
  INSERT INTO t1 VALUES(1,5555,4);
  CREATE INDEX i1a ON t1(a);
  CREATE INDEX i1b ON t1(b);
  SELECT a FROM t1 NATURAL RIGHT JOIN t1 WHERE a=5555 OR (1,b)==(SELECT 2 IN (2,2),4);
} {5555}

# 2022-04-23 dbsqlfuzz c7ee5500e3abddec3557016de777713b80c790d3
# Escape from the right-join body subroutine via the ORDER BY LIMIT optimization.
#
reset_db
db null -
do_catchsql_test join8-5000 {
  CREATE TABLE t1(x);
  INSERT INTO t1(x) VALUES(NULL),(NULL);
  CREATE TABLE t2(c, d);
  INSERT INTO t2(c,d) SELECT x, x FROM t1;
  CREATE INDEX t2dc ON t2(d, c);
  SELECT (SELECT c FROM sqlite_temp_schema FULL JOIN t2 ON d IN (1,2,3) ORDER BY d) AS x FROM t1;
} {0 {- -}}

# 2022-04-29 dbsqlfuzz 19f1102a70cf966ab249de56d944fc20dbebcfcf
#
reset_db
do_execsql_test join8-6000 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT, c TEXT, d REAL);
  INSERT INTO t1 VALUES(1,'A','aa',2.5);
  SELECT * FROM t1 AS t2 NATURAL RIGHT JOIN t1 AS t3
   WHERE (a,b) IN (SELECT rowid, b FROM t1);
} {1 A aa 2.5}
do_execsql_test join8-6010 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a INT PRIMARY KEY, b TEXT, c TEXT, d INT) WITHOUT ROWID;
  INSERT INTO t1 VALUES(15,'xray','baker',42);
  SELECT value, t1.* FROM json_each('7') NATURAL RIGHT JOIN t1
   WHERE (a,b) IN (SELECT a, b FROM t1);
} {7 15 xray baker 42}
do_execsql_test join8-6020 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a INTEGER PRIMARY KEY,b);
  INSERT INTO t1 VALUES(0,NULL),(1,2);
  SELECT value, t1.* FROM json_each('17') NATURAL RIGHT JOIN t1
   WHERE (a,b) IN (SELECT rowid, b FROM t1);
} {17 1 2}

# Bloom filter usage by RIGHT and FULL JOIN
#
reset_db
do_execsql_test join8-7000 {
CREATE TABLE t1(a INT, b INT, c INT, d INT);
  WITH RECURSIVE c(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c WHERE x<10)
    INSERT INTO t1(a,b,c,d) SELECT x, x+100, x+200, x+300 FROM c;
  CREATE TABLE t2(b INT, x INT);
  INSERT INTO t2(b,x) SELECT b, a FROM t1 WHERE a%2=0;
  CREATE INDEX t2b ON t2(b);
  CREATE TABLE t3(c INT, y INT);
  INSERT INTO t3(c,y) SELECT c, a FROM t1 WHERE a%3=0;
  CREATE INDEX t3c ON t3(c);
  CREATE TABLE t4(d INT, z INT);
  INSERT INTO t4(d,z) SELECT d, a FROM t1 WHERE a%5=0;
  CREATE INDEX t4d ON t4(d);
  INSERT INTO t1(a,b,c,d) VALUES
    (96,NULL,296,396),
    (97,197,NULL,397),
    (98,198,298,NULL),
    (99,NULL,NULL,NULL);
  ANALYZE sqlite_schema;
  INSERT INTO sqlite_stat1 VALUES('t4','t4d','20 1');
  INSERT INTO sqlite_stat1 VALUES('t3','t3c','32 1');
  INSERT INTO sqlite_stat1 VALUES('t2','t2b','48 1');
  INSERT INTO sqlite_stat1 VALUES('t1',NULL,'100');
  ANALYZE sqlite_schema;
} {}
db null -
do_execsql_test join8-7010 {
  WITH t0 AS MATERIALIZED (
    SELECT t1.*, t2.*, t3.*
      FROM t1 INNER JOIN t2 ON t1.b=t2.b AND t2.x>0
        RIGHT JOIN t3 ON t1.c=t3.c AND t3.y>0
  )
  SELECT * FROM t0 FULL JOIN t4 ON t0.a=t4.d AND t4.z>0
   ORDER BY coalesce(t0.a, t0.y+200, t4.d);
} {
  6  106  206  306  106  6  206  6    -   -
  -    -    -    -    -  -  200  0    -   -
  -    -    -    -    -  -  203  3    -   -
  -    -    -    -    -  -  209  9    -   -
  -    -    -    -    -  -    -  -  300   0
  -    -    -    -    -  -    -  -  305   5
  -    -    -    -    -  -    -  -  310  10
}

# EVIDENCE-OF: R-33754-02880 you can say "LEFT RIGHT JOIN" which is the
# same as "FULL JOIN".
do_execsql_test join8-7011 {
  WITH t0 AS MATERIALIZED (
    SELECT t1.*, t2.*, t3.*
      FROM t1 INNER JOIN t2 ON t1.b=t2.b AND t2.x>0
        RIGHT JOIN t3 ON t1.c=t3.c AND t3.y>0
  )
  SELECT * FROM t0 LEFT RIGHT JOIN t4 ON t0.a=t4.d AND t4.z>0
   ORDER BY coalesce(t0.a, t0.y+200, t4.d);
} {
  6  106  206  306  106  6  206  6    -   -
  -    -    -    -    -  -  200  0    -   -
  -    -    -    -    -  -  203  3    -   -
  -    -    -    -    -  -  209  9    -   -
  -    -    -    -    -  -    -  -  300   0
  -    -    -    -    -  -    -  -  305   5
  -    -    -    -    -  -    -  -  310  10
}

do_execsql_test join8-7020 {
  EXPLAIN QUERY PLAN
  WITH t0 AS MATERIALIZED (
    SELECT t1.*, t2.*, t3.*
      FROM t1 INNER JOIN t2 ON t1.b=t2.b AND t2.x>0
        RIGHT JOIN t3 ON t1.c=t3.c AND t3.y>0
  )
  SELECT * FROM t0 FULL JOIN t4 ON t0.a=t4.d AND t4.z>0
   ORDER BY coalesce(t0.a, t0.y+200, t4.d);
} {/.*BLOOM FILTER ON t2.*BLOOM FILTER ON t3.*BLOOM FILTER ON t4.*/}

# 2022-05-12 Difference with PG found (by Dan) while exploring
# https://sqlite.org/forum/forumpost/677a0ab93fcd9ccd
#
reset_db
do_execsql_test join8-8000 {
  CREATE TABLE t1(a INT, b INT);
  CREATE TABLE t2(c INT, d INT);
  CREATE TABLE t3(e INT, f INT);
  INSERT INTO t1 VALUES(1, 2);
  INSERT INTO t2 VALUES(3, 4);
  INSERT INTO t3 VALUES(5, 6);
} {}
do_execsql_test join8-8010 {
  SELECT *
    FROM t3 LEFT JOIN t2 ON true
            JOIN t1 ON (t3.e IS t2.c);
} {}
do_execsql_test join8-8020 {
  SELECT *
    FROM t3 LEFT JOIN t2 ON true
            JOIN t1 ON (t3.e IS NOT DISTINCT FROM t2.c);
} {}

# 2022-05-13 The idea of reusing subquery cursors does not
# work, if the cursors are used both for scanning and lookups.
#
reset_db
db null -
do_execsql_test join8-9000 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT, c TEXT, d REAL);
  INSERT INTO t1 VALUES(1,'E','bb',NULL),(2,NULL,NULL,NULL);
  SELECT * FROM t1 NATURAL RIGHT JOIN t1 AS t2 WHERE (a,b) IN (SELECT a+0, b FROM t1);
} {1 E bb -}

# 2022-05-14 https://sqlite.org/forum/forumpost/c06b10ad7e
#
reset_db
db null -
do_execsql_test join8-10000 {
  CREATE TABLE t1(c0 INT UNIQUE);
  CREATE TABLE t2(c0);
  CREATE TABLE t2i(c0 INT);
  CREATE TABLE t3(c0 INT);
  INSERT INTO t1 VALUES(1);
  INSERT INTO t2 VALUES(2);
  INSERT INTO t2i VALUES(2);
  INSERT INTO t3 VALUES(3);
} {}
do_execsql_test join8-10010 {
  SELECT DISTINCT t1.c0, t3.c0
    FROM t2 NATURAL JOIN t1 RIGHT JOIN t3 ON t1.c0;
} {- 3}
do_execsql_test join8-10020 {
  SELECT t1.c0, t3.c0
    FROM t2 NATURAL JOIN t1 RIGHT JOIN t3 ON t1.c0;
} {- 3}
do_execsql_test join8-10030 {
  SELECT DISTINCT t1.c0, t3.c0
    FROM t2 NATURAL CROSS JOIN t1 RIGHT JOIN t3 ON t1.c0;
} {- 3}
do_execsql_test join8-10040 {
  SELECT t1.c0, t3.c0
    FROM t1 NATURAL CROSS JOIN t2 RIGHT JOIN t3 ON t1.c0;
} {- 3}
do_execsql_test join8-10050 {
  SELECT DISTINCT t1.c0, t3.c0
    FROM t2i NATURAL JOIN t1 RIGHT JOIN t3 ON t1.c0;
} {- 3}
do_execsql_test join8-10060 {
  SELECT DISTINCT +t1.c0, t3.c0
    FROM t2 NATURAL JOIN t1 RIGHT JOIN t3 ON t1.c0;
} {- 3}
do_execsql_test join8-10070 {
  SELECT DISTINCT +t1.c0, t3.c0
    FROM t1 NATURAL CROSS JOIN t2 RIGHT JOIN t3 ON t1.c0;
} {- 3}
do_execsql_test join8-10080 {
  SELECT DISTINCT t1.c0, t3.c0
    FROM t2 NATURAL JOIN t1 RIGHT JOIN t3 ON t1.c0<>0;
} {- 3}

# 2022-05-14
# index-on-expr scan on a RIGHT JOIN
# dbsqlfuzz 39ee60004ff027a9e2846cf76e02cd5ac0953739
#
reset_db
db null -
do_execsql_test join8-11000 {
  CREATE TABLE t1(a);
  CREATE TABLE t2(b);
  INSERT INTO t2 VALUES(0),(1),(2);
  SELECT * FROM t1 RIGHT JOIN t2 ON (a=b) WHERE 99+(b+1)!=99;
} {- 0 - 1 - 2}
do_execsql_test join8-11010 {
  CREATE INDEX t2b ON t2(b+1) WHERE b IS NOT NULL;
  SELECT * FROM t1 RIGHT JOIN t2 ON (a=b) WHERE 99+(b+1)!=99;
} {- 0 - 1 - 2}
do_execsql_test join8-11020 {
  DROP TABLE t1;
  DROP TABLE t2;
  CREATE TABLE t1(a);
  CREATE TABLE t2(b, c, d);
  INSERT INTO t2 VALUES(1, 3, 'not-4');
  SELECT b, d FROM t1 RIGHT JOIN t2 WHERE (b+0)=1 AND d!=4;
} {1 not-4}
do_execsql_test join8-11030 {
  CREATE INDEX i2 ON t2((b+0), d);
  SELECT b, d FROM t1 RIGHT JOIN t2 WHERE (b+0)=1 AND d!=4;
} {1 not-4}
do_execsql_test join8-11040 {
  DROP INDEX i2;
  CREATE INDEX i2 ON t2((b+0), d) WHERE d IS NOT NULL;
  SELECT b, d FROM t1 RIGHT JOIN t2 WHERE (b+0)=1 AND d!=4;
} {1 not-4}

# 2022-05-23
# NATURAL JOIN name resolution is more forgiving with LEFT JOIN
# https://sqlite.org/forum/forumpost/e90a8e6e6f
#
reset_db
db null -
do_execsql_test join8-12000 {
  CREATE TABLE t1(a INT);  INSERT INTO t1 VALUES(0),(1);
  CREATE TABLE t2(a INT);  INSERT INTO t2 VALUES(0),(2);
  CREATE TABLE t3(a INT);  INSERT INTO t3 VALUES(0),(3);
} {}
do_catchsql_test join8-12010 {
  SELECT * FROM t1 RIGHT JOIN t2 ON t2.a<>0 NATURAL RIGHT JOIN t3;
} {1 {ambiguous reference to a in USING()}}
do_catchsql_test join8-12020 {
  SELECT * FROM t1 RIGHT JOIN t2 ON t2.a<>0 NATURAL LEFT JOIN t3;
} {1 {ambiguous reference to a in USING()}}
do_catchsql_test join8-12030 {
  SELECT * FROM t1 LEFT JOIN t2 ON t2.a<>0 NATURAL RIGHT JOIN t3;
} {1 {ambiguous reference to a in USING()}}

# The following query should probably also return the same error as the
# previous three cases.  However, historical versions of SQLite have always
# let it pass.  We will not "fix" this, since to do so might break legacy
# applications.
#
do_catchsql_test join8-12040 {
  SELECT * FROM t1 LEFT JOIN t2 ON t2.a<>0 NATURAL LEFT JOIN t3;
} {0 {0 2 1 2}}

# 2022-05-24
# https://sqlite.org/forum/forumpost/687b0bf563a1d4f1
#
reset_db
do_execsql_test join8-13000 {
  CREATE TABLE t0(t TEXT, u TEXT);  INSERT INTO t0 VALUES('t', 'u');
  CREATE TABLE t1(v TEXT, w TEXT);  INSERT INTO t1 VALUES('v', 'w');
  CREATE TABLE t2(x TEXT, y TEXT);  INSERT INTO t2 VALUES('x', 'y');
  SELECT * FROM t0 JOIN t1 ON (t2.x NOTNULL) LEFT JOIN t2 ON false;
  SELECT * FROM t0 JOIN t1 ON (t2.x NOTNULL) LEFT JOIN t2 ON false
   WHERE t2.y ISNULL;
} {}

# 2022-05-25
# https://sqlite.org/forum/forumpost/5cfe08eed6
#
reset_db
do_execsql_test join8-14000 {
  CREATE TABLE t0(a TEXT, b TEXT, c TEXT);
  CREATE TABLE t1(a TEXT);
  INSERT INTO t1 VALUES('1');
  CREATE VIEW v0 AS SELECT 'xyz' AS d;
  SELECT * FROM v0 RIGHT JOIN t1 ON t1.a<>'' INNER JOIN t0 ON t0.c<>'';
  SELECT * FROM v0 RIGHT JOIN t1 ON t1.a<>'' INNER JOIN t0 ON t0.c<>'' WHERE b ISNULL;
} {}
do_execsql_test join8-14010 {
  CREATE TABLE y0(a INT);
  CREATE TABLE y1(b INT); INSERT INTO y1 VALUES(1), (2);
  CREATE TABLE y2(c INT); INSERT INTO y2 VALUES(3), (4);
} {}
db null -
do_execsql_test join8-14020 {
  SELECT * FROM y0 RIGHT JOIN y1 ON true INNER JOIN y2 ON true WHERE y2.c!=99 AND y2.c!=98;
} {
  - 1 3
  - 1 4
  - 2 3
  - 2 4
}

# 2022-05-30
# https://sqlite.org/forum/forumpost/3902c7b833
#
reset_db
do_execsql_test join8-15000 {
  CREATE TABLE t1(x INT);
  CREATE TABLE t2(y INT);
  CREATE TABLE t3(z INT);
  INSERT INTO t1 VALUES(10);
  INSERT INTO t3 VALUES(20),(30);
}
do_execsql_test join8-15010 {
  SELECT * FROM t1 LEFT JOIN t2 ON true JOIN t3 ON t2.y IS NOT NULL;
} {}
do_execsql_test join8-15020 {
  SELECT * FROM t1 LEFT JOIN t2 ON true JOIN t3 ON t2.y IS NOT NULL
   WHERE (t3.z!=400 AND t3.z!=500 AND t3.z!=600);
} {}
do_execsql_test join8-15100 {
  PRAGMA automatic_index = 0;
  CREATE TABLE t4(x TEXT);
  CREATE TABLE t5(y TEXT);
  CREATE TABLE t6(z TEXT);
  INSERT INTO t4 VALUES('a'), ('b');
  INSERT INTO t5 VALUES('b'), ('c');
  INSERT INTO t6 VALUES('a'), ('d');
} {}
db null -
do_execsql_test join8-15110 {
  SELECT * FROM t4 LEFT JOIN t5 ON x=y LEFT JOIN t6 ON (x=z) ORDER BY +x;
} {a - a b b -}
do_execsql_test join8-15120 {
  SELECT * FROM t4 LEFT JOIN t5 ON x=y LEFT JOIN t6 ON (x=z)
   WHERE t5.y!='x' AND t4.x!='x';
} {b b -}

# 2022-05-31
# https://sqlite.org/forum/forumpost/c2554d560b
reset_db
do_execsql_test join8-16000 {
  CREATE TABLE t1(a TEXT);
  CREATE TABLE t2(b TEXT);
  CREATE TABLE t3(c TEXT);
  INSERT INTO t2(b) VALUES ('x');
  INSERT INTO t3(c) VALUES ('y'), ('z');
} {}
db null -
do_execsql_test join8-16010 {
  SELECT * FROM t1 RIGHT JOIN t2 ON true LEFT JOIN t3 ON a<>'';
} {- x -}
do_execsql_test join8-16020 {
  SELECT * FROM t1 RIGHT JOIN t2 ON true LEFT JOIN t3 ON a<>'' WHERE c IS NULL;
} {- x -}
do_execsql_test join8-16020 {
  SELECT * FROM t1 RIGHT JOIN t2 ON true JOIN t3 ON a<>'' WHERE c IS NULL;
} {}
do_execsql_test join8-16030 {
  SELECT * FROM t1 RIGHT JOIN t2 ON true JOIN t3 ON a<>'';
} {}
do_execsql_test join8-16040 {
  SELECT * FROM t1 RIGHT JOIN t2 ON true LEFT JOIN t3 ON a<>'' WHERE c<>'';
} {}
do_execsql_test join8-16050 {
  SELECT * FROM t1 RIGHT JOIN t2 ON true LEFT JOIN t3 ON a<>'' WHERE c IS NOT NULL;
} {}
do_execsql_test join8-16060 {
  SELECT * FROM t1 RIGHT JOIN t2 ON true JOIN t3 ON a<>'' WHERE c<>'';
} {}
do_execsql_test join8-16070 {
  SELECT * FROM t1 RIGHT JOIN t2 ON true JOIN t3 ON a<>'' WHERE c IS NOT NULL;
} {}

# 2022-06-01
# https://sqlite.org/forum/forumpost/087de2d9ec
#
reset_db
do_execsql_test join8-17000 {
  CREATE TABLE t1(id INTEGER PRIMARY KEY, x INT, y INT);
  CREATE TABLE t2(z INT);
  INSERT INTO t1(id,x,y) VALUES(1, 0, 0);
} {}
db null NULL
do_execsql_test join8-17010 {
  SELECT * FROM t2 RIGHT JOIN t1 ON true;
} {NULL 1 0 0}
do_execsql_test join8-17020 {
  SELECT 99=id AND 0=y AS "truth" FROM t2 RIGHT JOIN t1 ON true;
} {0}
do_execsql_test join8-17030 {
  SELECT (99, 0)==(id, y) AS "truth" FROM t2 RIGHT JOIN t1;
} {0}
do_execsql_test join8-17040 {
  SELECT * FROM t2 RIGHT JOIN t1 WHERE 99=id AND 0=y;
} {}
do_execsql_test join8-17041 {
  SELECT * FROM t2 RIGHT JOIN t1 WHERE 99=+id AND 0=y;
} {}
do_execsql_test join8-17050 {
  SELECT * FROM t2 RIGHT JOIN t1 WHERE (99, 0)==(id,y);
} {}
do_execsql_test join8-17051 {
  SELECT * FROM t2 RIGHT JOIN t1 WHERE (99, 0)==(+id,y);
} {}
do_execsql_test join8-17060 {
  SELECT * FROM t2 RIGHT JOIN t1 WHERE 1=id AND 0=y;
} {NULL 1 0 0}
do_execsql_test join8-17061 {
  SELECT * FROM t2 RIGHT JOIN t1 WHERE 1=+id AND 0=y;
} {NULL 1 0 0}
do_execsql_test join8-17070 {
  SELECT * FROM t2 RIGHT JOIN t1 WHERE (1, 0)==(id,y);
} {NULL 1 0 0}
do_execsql_test join8-17071 {
  SELECT * FROM t2 RIGHT JOIN t1 WHERE (1, 0)==(+id,y);
} {NULL 1 0 0}
do_execsql_test join8-17080 {
  CREATE TABLE t3(a INTEGER PRIMARY KEY, b INT);
  CREATE TABLE t4(x INT, y INT);
  INSERT INTO t3(a,b) VALUES(1, 3);
} {}
do_execsql_test join8-17090 {
  SELECT t3.a FROM t4 RIGHT JOIN t3 ON (x=a) WHERE (b, 4)=(SELECT 3, 4);
} {1}
do_execsql_test join8-17091 {
  SELECT t3.a FROM t4 RIGHT JOIN t3 ON (x=a) WHERE (b, 4) IS (SELECT 3, 4);
} {1}

# 2022-06-06
# https://sqlite.org/forum/forumpost/206d99a16dd9212f
# tag-20191211-001
#
reset_db
do_execsql_test join8-18000 {
  CREATE TABLE t1(a BOOLEAN); INSERT INTO t1 VALUES (false);
  CREATE TABLE t2(x INT);     INSERT INTO t2 VALUES (0);
  SELECT *, x NOTNULL, (x NOTNULL)=a FROM t2 RIGHT JOIN t1 ON true WHERE (x NOTNULL)=a;
} {}
do_execsql_test join8-18010 {
  CREATE INDEX t1a ON t1(a);
  SELECT *, x NOTNULL, (x NOTNULL)=a FROM t2 RIGHT JOIN t1 ON true WHERE (x NOTNULL)=a;
} {}

do_execsql_test join8-18020 {
  CREATE TABLE t3(z);
  INSERT INTO t3 VALUES('t3value');
  SELECT *, x NOTNULL, (x NOTNULL)=a FROM t2 RIGHT JOIN t1 ON true INNER JOIN t3 ON (x NOTNULL)=a;
} {}

ifcapable rtree {
  do_execsql_test join8-18030 {
    CREATE VIRTUAL TABLE rtree1 USING rtree(a, x1, x2);
    INSERT INTO rtree1 VALUES(0, 0, 0);
  }
  do_execsql_test join8-18040 {
    SELECT *, x NOTNULL, (x NOTNULL)=a FROM t2 
      RIGHT JOIN rtree1 ON true INNER JOIN t3 ON (x NOTNULL)=+a;
  } {}
  do_execsql_test join8-18050 {
    SELECT *, x NOTNULL, (x NOTNULL)=a FROM t2 
      RIGHT JOIN rtree1 ON true INNER JOIN t3 ON (x NOTNULL)=a;
  } {}
}


reset_db
do_execsql_test join8-19000 {
  CREATE TABLE t1(a INT);
  CREATE TABLE t2(b INT, c INT);
  CREATE TABLE t3(d INT);

  INSERT INTO t1 VALUES(10);
  INSERT INTO t2 VALUES(50,51);
  INSERT INTO t3 VALUES(299);

  CREATE INDEX t2b ON t2( (b IS NOT NULL) );
}

do_execsql_test join8-19010 {
  SELECT * FROM t1 LEFT JOIN t2 ON true INNER JOIN t3 ON (b IS NOT NULL)=0;
}

# 2022-06-07
# https://sqlite.org/forum/forumpost/323f86cc30
reset_db
do_execsql_test join8-20000 {
  CREATE TABLE t1(x TEXT);
  INSERT INTO t1(x) VALUES('aaa');
  CREATE VIEW v0(y) AS SELECT x FROM t1;
  CREATE TABLE t2(z TEXT);
} {}
db null -
do_execsql_test join8-20010 {
  SELECT * FROM t2 JOIN v0 ON z<>'bbb' RIGHT JOIN t1 ON z<>'ccc';
} {- - aaa}
do_execsql_test join8-20020 {
  SELECT * FROM t2 JOIN v0 ON z<>'bbb' RIGHT JOIN t1 ON z<>'ccc' ORDER BY z;
} {- - aaa}
do_execsql_test join8-20030 {
  SELECT 99 as "m" FROM t2 JOIN v0 ON z<>'bbb' RIGHT JOIN t1 ON z<>'ccc';
} {99}
do_execsql_test join8-20040 {
  SELECT 99 as "m" FROM t2 JOIN v0 ON z<>'bbb' RIGHT JOIN t1 ON z<>'ccc' ORDER BY z;
} {99}
do_execsql_test join8-20050 {
  SELECT count(*)
    FROM (SELECT 99 as "m" FROM t2 JOIN v0 ON z<>'' RIGHT JOIN t1 ON z<>'') AS "t3";
} {1}
do_execsql_test join8-20060 {
  SELECT count(*) 
    FROM (SELECT 99 as "m" FROM t2 JOIN v0 ON z<>'' RIGHT JOIN t1 ON z<>'' ORDER BY z) AS "t3";
} {1}

# 2022-06-10
# https://sqlite.org/forum/forumpost/8e4c352937e82929
#
# Do not allow constant propagation between ON and WHERE clause terms.
# (Updated 2022-06-20) See also https://sqlite.org/forum/forumpost/57bdf2217d
#
reset_db
do_execsql_test join8-21000 {
  CREATE TABLE t1(a INT,b BOOLEAN);
  CREATE TABLE t2(c INT);  INSERT INTO t2 VALUES(NULL);
  CREATE TABLE t3(d INT);
}
do_execsql_test join8-21010 {
  SELECT (b IS TRUE) FROM t1 JOIN t3 ON (b=TRUE) RIGHT JOIN t2 ON TRUE;
} {0}
do_execsql_test join8-22020 {
  SELECT * FROM t1 JOIN t3 ON (b=TRUE) RIGHT JOIN t2 ON TRUE WHERE (b IS TRUE);
} {}
do_execsql_test join8-22030 {
  DROP TABLE t1;
  DROP TABLE t2;
  DROP TABLE t3;
  CREATE TABLE t1(a INT);
  CREATE TABLE t2(b INT);
  CREATE TABLE t3(c INTEGER PRIMARY KEY, d INT);
  CREATE INDEX t3d ON t3(d);
  INSERT INTO t3 VALUES(0, 0);
}
do_catchsql_test join8-22031 {
  SELECT * FROM t1 JOIN t2 ON d>b RIGHT JOIN t3 ON true WHERE +d = 0;
} {1 {ON clause references tables to its right}}
do_catchsql_test join8-22040 {
  SELECT * FROM t1 JOIN t2 ON d>b RIGHT JOIN t3 ON true WHERE d = 0;
} {1 {ON clause references tables to its right}}


# 2022-06-10
# https://sqlite.org/forum/forumpost/51e6959f61
#
# Restrictions on the usage of WHERE clause constraints by joins that are
# involved with a RIGHT JOIN must also be applied to automatic indexes.
#
reset_db
do_execsql_test join8-22000 {
  CREATE TABLE t1(a INT);
  CREATE TABLE t2(b INT);
  CREATE TABLE t3(c TEXT);  INSERT INTO t3 VALUES('x');
  CREATE TABLE t4(d TEXT);  INSERT INTO t4 VALUES('y');
  SELECT 99
    FROM t1
         LEFT JOIN t2 ON true
         RIGHT JOIN t3 ON true
         RIGHT JOIN t4 ON true
   WHERE a=b;
} {}

# 2022-06-13
# https://sqlite.org/forum/forumpost/b40696f501
#
# This optimization that converts "x ISNULL" into "FALSE" when column "x" has a
# NOT NULL constraint is too aggresive if the query contains RIGHT JOIN.
#
reset_db
db null -
do_execsql_test join8-23000 {
  CREATE TABLE t1(a TEXT);
  INSERT INTO t1 VALUES('c');
  CREATE TABLE t2(b TEXT, c TEXT NOT NULL);
  INSERT INTO t2 VALUES('a', 'b');
  CREATE TABLE t3(d TEXT);
  INSERT INTO t3 VALUES('x');
  CREATE TABLE t4(e TEXT);
  INSERT INTO t4 VALUES('y');
}
do_execsql_test join8-23010 {
  SELECT *
    FROM t1
         LEFT JOIN t2 ON TRUE
         JOIN t3 ON c=''
         RIGHT JOIN t4 ON b='';
} {- - - - y}
do_execsql_test join8-23020 {
  SELECT *
    FROM t1
         LEFT JOIN t2 ON TRUE
         JOIN t3 ON c=''
         RIGHT JOIN t4 ON b=''
   WHERE d ISNULL
} {- - - - y}

# 2022-06-14
# dbsqlfuzz 2f3101834d14325a976f601b9267a0fd323d6bbd
#
# When the OP_NullRow opcode creates a new cursor, it must
# set the cursor to no-reuse so that an OP_OpenEphemeral in
# a subroutine does not try to reuse it.
#
reset_db
db null -
do_execsql_test join8-24000 {
  CREATE TABLE t4(b INT, c INT);
  CREATE TABLE t5(a INT, f INT);
  INSERT INTO t5 VALUES(1,2);
  WITH t7(x, y) AS (SELECT 100, 200 FROM t5)
    SELECT * FROM t4 JOIN t7 ON true RIGHT JOIN (SELECT y AS z FROM t7) AS t6 ON (x=z);
} {- - - - 200}

# 2022-06-20
# forum/forumpost/6650cd40b5634f35
#
reset_db
do_execsql_test join8-25000 {
  CREATE TABLE t1(a1 INT);
  CREATE TABLE t2(b2 INT);
  CREATE TABLE t3(c3 INT, d3 INT UNIQUE);
  CREATE TABLE t4(e4 INT, f4 TEXT);
  INSERT INTO t3(c3, d3) VALUES (2, 1);
  INSERT INTO t4(f4) VALUES ('x');
  CREATE INDEX i0 ON t3(c3) WHERE d3 ISNULL;
  ANALYZE main;
}
db null -
do_execsql_test join8-25010 {
  SELECT * FROM t1 LEFT JOIN t2 ON true JOIN t3 ON (b2 IN (a1)) FULL JOIN t4 ON true;
} {- - - - - x}
do_execsql_test join8-25020 {
  SELECT 1 FROM t1 LEFT JOIN t2 ON true JOIN t3 ON (b2 IN (a1)) FULL JOIN t4 ON true;
} {1}

# 2022-07-13
# forum/forumpost/174afeae57
#
reset_db
db null -
do_execsql_test join8-26000 {
  CREATE TABLE t1(a INT);
  CREATE TABLE t2(b INT, c INT);
  CREATE VIEW t3(d) AS SELECT NULL FROM t2 FULL OUTER JOIN t1 ON c=a UNION ALL SELECT b FROM t2;
  INSERT INTO t1(a) VALUES (NULL);
  INSERT INTO t2(b, c) VALUES (99, NULL);
  SELECT DISTINCT b, c, d FROM t2, t3 WHERE b<>0
   UNION SELECT DISTINCT b, c, d FROM t2, t3 WHERE b ISNULL;
} {99 - - 99 - 99}

finish_test

Added test/join9.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022-04-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 file implements tests for RIGHT and FULL OUTER JOINs.

set testdir [file dirname $argv0]
source $testdir/tester.tcl

foreach {id schema} {
  1 {
    CREATE TABLE t3(id INTEGER PRIMARY KEY, w TEXT);
    CREATE TABLE t4(id INTEGER PRIMARY KEY, x TEXT);
    CREATE TABLE t5(id INTEGER PRIMARY KEY, y TEXT);
    CREATE TABLE t6(id INTEGER PRIMARY KEY, z INT);
    CREATE VIEW dual(dummy) AS VALUES('x');
    INSERT INTO t3(id,w) VALUES(2,'two'),(3,'three'),(6,'six'),(7,'seven');
    INSERT INTO t4(id,x) VALUES(2,'alice'),(4,'bob'),(6,'cindy'),(8,'dave');
    INSERT INTO t5(id,y) VALUES(1,'red'),(2,'orange'),(3,'yellow'),(4,'green'),
                               (5,'blue');
    INSERT INTO t6(id,z) VALUES(3,333),(4,444),(5,555),(0,1000),(9,999);
  }
  2 {
    CREATE TABLE t3(id INT PRIMARY KEY, w TEXT) WITHOUT ROWID;
    CREATE TABLE t4(id INT PRIMARY KEY, x TEXT) WITHOUT ROWID;
    CREATE TABLE t5(id INT PRIMARY KEY, y TEXT) WITHOUT ROWID;
    CREATE TABLE t6(id INT PRIMARY KEY, z INT) WITHOUT ROWID;
    CREATE TABLE dual(dummy TEXT);
    INSERT INTO dual(dummy) VALUES('x');
    INSERT INTO t3(id,w) VALUES(2,'two'),(3,'three'),(6,'six'),(7,'seven');
    INSERT INTO t4(id,x) VALUES(2,'alice'),(4,'bob'),(6,'cindy'),(8,'dave');
    INSERT INTO t5(id,y) VALUES(1,'red'),(2,'orange'),(3,'yellow'),(4,'green'),
                               (5,'blue');
    INSERT INTO t6(id,z) VALUES(3,333),(4,444),(5,555),(0,1000),(9,999);
  }
  3 {
    CREATE TABLE t3x(id INTEGER PRIMARY KEY, w TEXT);
    CREATE TABLE t4x(id INTEGER PRIMARY KEY, x TEXT);
    CREATE TABLE t5x(id INTEGER PRIMARY KEY, y TEXT);
    CREATE TABLE t6x(id INTEGER PRIMARY KEY, z INT);
    CREATE VIEW dual(dummy) AS VALUES('x');
    INSERT INTO t3x(id,w) VALUES(2,'two'),(3,'three'),(6,'six'),(7,'seven');
    INSERT INTO t4x(id,x) VALUES(2,'alice'),(4,'bob'),(6,'cindy'),(8,'dave');
    INSERT INTO t5x(id,y) VALUES(1,'red'),(2,'orange'),(3,'yellow'),(4,'green'),
                               (5,'blue');
    INSERT INTO t6x(id,z) VALUES(3,333),(4,444),(5,555),(0,1000),(9,999);
    CREATE VIEW t3 AS SELECT * FROM t3x LIMIT 1000;
    CREATE VIEW t4 AS SELECT * FROM t4x LIMIT 1000;
    CREATE VIEW t5 AS SELECT * FROM t5x LIMIT 1000;
    CREATE VIEW t6 AS SELECT * FROM t6x LIMIT 1000;
  }
  4 {
    CREATE TABLE t3a(id INTEGER PRIMARY KEY, w TEXT);
    CREATE TABLE t3b(id INTEGER PRIMARY KEY, w TEXT);
    CREATE TABLE t4a(id INTEGER PRIMARY KEY, x TEXT);
    CREATE TABLE t4b(id INTEGER PRIMARY KEY, x TEXT);
    CREATE TABLE t5a(id INTEGER PRIMARY KEY, y TEXT);
    CREATE TABLE t5b(id INTEGER PRIMARY KEY, y TEXT);
    CREATE TABLE t6a(id INTEGER PRIMARY KEY, z INT);
    CREATE TABLE t6b(id INTEGER PRIMARY KEY, z INT);
    CREATE VIEW dual(dummy) AS VALUES('x');
    INSERT INTO t3a(id,w) VALUES(2,'two'),(3,'three');
    INSERT INTO t3b(id,w) VALUES(6,'six'),(7,'seven');
    INSERT INTO t4a(id,x) VALUES(2,'alice'),(4,'bob');
    INSERT INTO t4b(id,x) VALUES(6,'cindy'),(8,'dave');
    INSERT INTO t5a(id,y) VALUES(1,'red'),(2,'orange'),(3,'yellow');
    INSERT INTO t5b(id,y) VALUES(4,'green'),(5,'blue');
    INSERT INTO t6a(id,z) VALUES(3,333),(4,444);
    INSERT INTO t6b(id,z) VALUES(5,555),(0,1000),(9,999);
    CREATE VIEW t3 AS SELECT * FROM t3a UNION ALL SELECT * FROM t3b;
    CREATE VIEW t4 AS SELECT * FROM t4a UNION ALL SELECT * FROM t4b;
    CREATE VIEW t5 AS SELECT * FROM t5a UNION ALL SELECT * FROM t5b;
    CREATE VIEW t6 AS SELECT * FROM t6a UNION ALL SELECT * FROM t6b;
  }
  5 {
    CREATE TABLE t3a(id INTEGER PRIMARY KEY, w TEXT) WITHOUT ROWID;
    CREATE TABLE t3b(id INTEGER PRIMARY KEY, w TEXT);
    CREATE TABLE t4a(id INTEGER PRIMARY KEY, x TEXT) WITHOUT ROWID;
    CREATE TABLE t4b(id INTEGER PRIMARY KEY, x TEXT) WITHOUT ROWID;
    CREATE TABLE t5a(id INTEGER PRIMARY KEY, y TEXT);
    CREATE TABLE t5b(id INTEGER PRIMARY KEY, y TEXT) WITHOUT ROWID;
    CREATE TABLE t6a(id INTEGER PRIMARY KEY, z INT);
    CREATE TABLE t6b(id INTEGER PRIMARY KEY, z INT);
    CREATE VIEW dual(dummy) AS VALUES('x');
    INSERT INTO t3a(id,w) VALUES(2,'two'),(3,'three');
    INSERT INTO t3b(id,w) VALUES(6,'six'),(7,'seven');
    INSERT INTO t4a(id,x) VALUES(2,'alice'),(4,'bob');
    INSERT INTO t4b(id,x) VALUES(6,'cindy'),(8,'dave');
    INSERT INTO t5a(id,y) VALUES(1,'red'),(2,'orange'),(3,'yellow');
    INSERT INTO t5b(id,y) VALUES(4,'green'),(5,'blue');
    INSERT INTO t6a(id,z) VALUES(3,333),(4,444);
    INSERT INTO t6b(id,z) VALUES(5,555),(0,1000),(9,999);
    CREATE VIEW t3 AS SELECT * FROM t3a UNION ALL SELECT * FROM t3b;
    CREATE VIEW t4 AS SELECT * FROM t4a UNION ALL SELECT * FROM t4b LIMIT 50;
    CREATE VIEW t5 AS SELECT * FROM t5a UNION ALL SELECT * FROM t5b LIMIT 100;
    CREATE VIEW t6 AS SELECT * FROM t6a UNION ALL SELECT * FROM t6b;
  }
} {
  reset_db
  db nullvalue -
  do_execsql_test join9-$id.setup $schema {}

  # Verifid by PG-14 for case 1
  do_execsql_test join9-$id.100 {
    SELECT *, t4.id, t5.id, t6.id
      FROM t4 NATURAL LEFT JOIN t5 NATURAL LEFT JOIN t6
     ORDER BY 1;
  } {
    2   alice  orange  -    2   2   - 
    4   bob    green   444  4   4   4 
    6   cindy  -       -    6   -   - 
    8   dave   -       -    8   -   - 
  }

  do_execsql_test join9-$id.101 {
    SELECT *, t4.id, t5.id, t6.id
      FROM t4 NATURAL LEFT JOIN t5 NATURAL LEFT JOIN t6
     ORDER BY id;
  } {
    2   alice  orange  -    2   2   - 
    4   bob    green   444  4   4   4 
    6   cindy  -       -    6   -   - 
    8   dave   -       -    8   -   - 
  }
  do_execsql_test join9-$id.102 {
    SELECT *, t4.id, t5.id, t6.id
      FROM t4 LEFT JOIN t5 USING(id) LEFT JOIN t6 USING(id)
     ORDER BY id;
  } {
    2   alice  orange  -    2   2   - 
    4   bob    green   444  4   4   4 
    6   cindy  -       -    6   -   - 
    8   dave   -       -    8   -   - 
  }

  # Verifid by PG-14 using case 1
  do_execsql_test join9-$id.200 {
    SELECT id, x, y, z, t4.id, t5.id, t6.id
      FROM t5 NATURAL RIGHT JOIN t4 NATURAL LEFT JOIN t6
     ORDER BY 1;
  } {
    2   alice  orange  -    2   2   - 
    4   bob    green   444  4   4   4 
    6   cindy  -       -    6   -   - 
    8   dave   -       -    8   -   - 
  }

  do_execsql_test join9-$id.201 {
    SELECT id, x, y, z, t4.id, t5.id, t6.id
      FROM t5 NATURAL RIGHT JOIN t4 NATURAL LEFT JOIN t6
     ORDER BY id;
  } {
    2   alice  orange  -    2   2   - 
    4   bob    green   444  4   4   4 
    6   cindy  -       -    6   -   - 
    8   dave   -       -    8   -   - 
  }

  # Verified by PG-14 using case 1
  do_execsql_test join9-$id.300 {
    SELECT *, t4.id, t5.id, t6.id
      FROM t4 NATURAL RIGHT JOIN t5 NATURAL RIGHT JOIN t6
     ORDER BY 1;
  } {
    0   -    -       1000  -   -   0 
    3   -    yellow  333   -   3   3 
    4   bob  green   444   4   4   4 
    5   -    blue    555   -   5   5 
    9   -    -       999   -   -   9 
  }

  do_execsql_test join9-$id.301 {
    SELECT *, t4.id, t5.id, t6.id
      FROM t4 NATURAL RIGHT JOIN t5 NATURAL RIGHT JOIN t6
     ORDER BY id;
  } {
    0   -    -       1000  -   -   0 
    3   -    yellow  333   -   3   3 
    4   bob  green   444   4   4   4 
    5   -    blue    555   -   5   5 
    9   -    -       999   -   -   9 
  }

  # Verified by PG-14 for case 1
  do_execsql_test join9-$id.400 {
    SELECT *, t4.id, t5.id, t6.id
      FROM t4 NATURAL FULL JOIN t5 NATURAL FULL JOIN t6
     ORDER BY 1;
  } {
    0    -      -       1000  -   -   0 
    1    -      red     -     -   1   - 
    2    alice  orange  -     2   2   - 
    3    -      yellow  333   -   3   3 
    4    bob    green   444   4   4   4 
    5    -      blue    555   -   5   5 
    6    cindy  -       -     6   -   - 
    8    dave   -       -     8   -   - 
    9    -      -       999   -   -   9 
  }

  do_execsql_test join9-$id.401 {
    SELECT *, t4.id, t5.id, t6.id
      FROM t4 NATURAL FULL JOIN t5 NATURAL FULL JOIN t6
     ORDER BY id;
  } {
    0    -      -       1000  -   -   0 
    1    -      red     -     -   1   - 
    2    alice  orange  -     2   2   - 
    3    -      yellow  333   -   3   3 
    4    bob    green   444   4   4   4 
    5    -      blue    555   -   5   5 
    6    cindy  -       -     6   -   - 
    8    dave   -       -     8   -   - 
    9    -      -       999   -   -   9 
  }
  do_execsql_test join9-$id.402 {
    SELECT id, x, y, z, t4.id, t5.id, t6.id
      FROM t4 NATURAL FULL JOIN t6 NATURAL FULL JOIN t5
     ORDER BY id;
  } {
    0    -      -       1000  -   -   0 
    1    -      red     -     -   1   - 
    2    alice  orange  -     2   2   - 
    3    -      yellow  333   -   3   3 
    4    bob    green   444   4   4   4 
    5    -      blue    555   -   5   5 
    6    cindy  -       -     6   -   - 
    8    dave   -       -     8   -   - 
    9    -      -       999   -   -   9 
  }
  do_execsql_test join9-$id.403 {
    SELECT id, x, y, z, t4.id, t5.id, t6.id
      FROM t5 NATURAL FULL JOIN t4 NATURAL FULL JOIN t6
     ORDER BY id;
  } {
    0    -      -       1000  -   -   0 
    1    -      red     -     -   1   - 
    2    alice  orange  -     2   2   - 
    3    -      yellow  333   -   3   3 
    4    bob    green   444   4   4   4 
    5    -      blue    555   -   5   5 
    6    cindy  -       -     6   -   - 
    8    dave   -       -     8   -   - 
    9    -      -       999   -   -   9 
  }
  do_execsql_test join9-$id.404 {
    SELECT id, x, y, z, t4.id, t5.id, t6.id
      FROM t5 NATURAL FULL JOIN t6 NATURAL FULL JOIN t4
     ORDER BY id;
  } {
    0    -      -       1000  -   -   0 
    1    -      red     -     -   1   - 
    2    alice  orange  -     2   2   - 
    3    -      yellow  333   -   3   3 
    4    bob    green   444   4   4   4 
    5    -      blue    555   -   5   5 
    6    cindy  -       -     6   -   - 
    8    dave   -       -     8   -   - 
    9    -      -       999   -   -   9 
  }
  do_execsql_test join9-$id.405 {
    SELECT id, x, y, z, t4.id, t5.id, t6.id
      FROM t6 NATURAL FULL JOIN t4 NATURAL FULL JOIN t5
     ORDER BY id;
  } {
    0    -      -       1000  -   -   0 
    1    -      red     -     -   1   - 
    2    alice  orange  -     2   2   - 
    3    -      yellow  333   -   3   3 
    4    bob    green   444   4   4   4 
    5    -      blue    555   -   5   5 
    6    cindy  -       -     6   -   - 
    8    dave   -       -     8   -   - 
    9    -      -       999   -   -   9 
  }
  do_execsql_test join9-$id.406 {
    SELECT id, x, y, z, t4.id, t5.id, t6.id
      FROM t6 NATURAL FULL JOIN t5 NATURAL FULL JOIN t4
     ORDER BY id;
  } {
    0    -      -       1000  -   -   0 
    1    -      red     -     -   1   - 
    2    alice  orange  -     2   2   - 
    3    -      yellow  333   -   3   3 
    4    bob    green   444   4   4   4 
    5    -      blue    555   -   5   5 
    6    cindy  -       -     6   -   - 
    8    dave   -       -     8   -   - 
    9    -      -       999   -   -   9 
  }

  # Verified by PG-14 using case 1
  do_execsql_test join9-$id.500 {
    SELECT id, w, x, y, z
      FROM t3 FULL JOIN t4 USING(id)
              NATURAL FULL JOIN t5
              FULL JOIN t6 USING(id)
      ORDER BY 1;
  } {
    0   -      -      -       1000
    1   -      -      red     -   
    2   two    alice  orange  -   
    3   three  -      yellow  333 
    4   -      bob    green   444 
    5   -      -      blue    555 
    6   six    cindy  -       -   
    7   seven  -      -       -   
    8   -      dave   -       -   
    9   -      -      -       999 
  }

  # Verified by PG-14 using case 1
  do_execsql_test join9-$id.600 {
    SELECT id, w, x, y, z
       FROM t3 JOIN dual AS d1 ON true
               FULL JOIN t4 USING(id)
               JOIN dual AS d2 ON true
               NATURAL FULL JOIN t5
               JOIN dual AS d3 ON true
               FULL JOIN t6 USING(id)
               CROSS JOIN dual AS d4
      ORDER BY 1;
  } {
    0   -      -      -       1000
    1   -      -      red     -   
    2   two    alice  orange  -   
    3   three  -      yellow  333 
    4   -      bob    green   444 
    5   -      -      blue    555 
    6   six    cindy  -       -   
    7   seven  -      -       -   
    8   -      dave   -       -   
    9   -      -      -       999 
  }

  # Verified by PG-14 using case 1
  do_execsql_test join9-$id.700 {
    SELECT id, w, x, y, z
       FROM t3 JOIN dual AS d1 ON true
               FULL JOIN t4 USING(id)
               JOIN dual AS d2 ON true
               NATURAL FULL JOIN t5
               JOIN dual AS d3 ON true
               FULL JOIN t6 USING(id)
               CROSS JOIN dual AS d4
      WHERE x<>'bob' OR x IS NULL
      ORDER BY 1;
  } {
    0   -      -      -       1000
    1   -      -      red     -   
    2   two    alice  orange  -   
    3   three  -      yellow  333 
    5   -      -      blue    555 
    6   six    cindy  -       -   
    7   seven  -      -       -   
    8   -      dave   -       -   
    9   -      -      -       999 
  }

  # Verified by PG-14 using case 1
  do_execsql_test join9-$id.800 {
    WITH t7(id,a) AS MATERIALIZED (SELECT * FROM t4 WHERE false)
    SELECT *
      FROM t7 
           JOIN t7 AS t7b USING(id)
           FULL JOIN t3 USING(id);
  } {
    2   -  -  two  
    3   -  -  three
    6   -  -  six  
    7   -  -  seven
  }

  # Verified by PG-14
  do_execsql_test join9-$id.900 {
    SELECT *
      FROM (t3 NATURAL FULL JOIN t4)
           NATURAL FULL JOIN
           (t5 NATURAL FULL JOIN t6)
    ORDER BY 1;
  } {
    0   -      -      -       1000
    1   -      -      red     -   
    2   two    alice  orange  -   
    3   three  -      yellow  333 
    4   -      bob    green   444 
    5   -      -      blue    555 
    6   six    cindy  -       -   
    7   seven  -      -       -   
    8   -      dave   -       -   
    9   -      -      -       999 
  }
  do_execsql_test join9-$id.910 {
    SELECT *
      FROM t3 NATURAL FULL JOIN 
           (t4 NATURAL FULL JOIN
            (t5 NATURAL FULL JOIN t6))
    ORDER BY 1;
  } {
    0   -      -      -       1000
    1   -      -      red     -   
    2   two    alice  orange  -   
    3   three  -      yellow  333 
    4   -      bob    green   444 
    5   -      -      blue    555 
    6   six    cindy  -       -   
    7   seven  -      -       -   
    8   -      dave   -       -   
    9   -      -      -       999 
  }
  do_execsql_test join9-$id.920 {
    SELECT *
      FROM t3 FULL JOIN (
                t4 FULL JOIN (
                    t5 FULL JOIN t6 USING (id)
                ) USING(id)
           ) USING(id)
    ORDER BY 1;
  } {
    0   -      -      -       1000
    1   -      -      red     -   
    2   two    alice  orange  -   
    3   three  -      yellow  333 
    4   -      bob    green   444 
    5   -      -      blue    555 
    6   six    cindy  -       -   
    7   seven  -      -       -   
    8   -      dave   -       -   
    9   -      -      -       999 
  }
  do_execsql_test join9-$id.920 {
    SELECT *
      FROM t3 FULL JOIN (
                t4 FULL JOIN (
                    t5 FULL JOIN t6 USING (id)
                ) USING(id)
           ) USING(id)
    ORDER BY 1;
  } {
    0   -      -      -       1000
    1   -      -      red     -   
    2   two    alice  orange  -   
    3   three  -      yellow  333 
    4   -      bob    green   444 
    5   -      -      blue    555 
    6   six    cindy  -       -   
    7   seven  -      -       -   
    8   -      dave   -       -   
    9   -      -      -       999 
  }

  # Verified by PG-14
  do_execsql_test join9-$id.930 {
    SELECT *
      FROM t3 FULL JOIN (
               t4 FULL JOIN (
                   t5 FULL JOIN t6 USING(id)
               ) USING(id)
           ) AS j1 ON j1.id=t3.id
     ORDER BY coalesce(t3.id,j1.id);
  } {
    -   -      0   -      -       1000
    -   -      1   -      red     -   
    2   two    2   alice  orange  -   
    3   three  3   -      yellow  333 
    -   -      4   bob    green   444 
    -   -      5   -      blue    555 
    6   six    6   cindy  -       -   
    7   seven  -   -      -       -   
    -   -      8   dave   -       -   
    -   -      9   -      -       999 
  }

  # Verified by PG-14
  do_execsql_test join9-$id.940 {
    SELECT *
      FROM t3 FULL JOIN (
                t4 RIGHT JOIN (
                    t5 FULL JOIN t6 USING(id)
                ) USING(id)
           ) AS j1 ON j1.id=t3.id
     ORDER BY coalesce(t3.id,j1.id);
  } {
    -   -      0   -      -       1000
    -   -      1   -      red     -   
    2   two    2   alice  orange  -   
    3   three  3   -      yellow  333 
    -   -      4   bob    green   444 
    -   -      5   -      blue    555 
    6   six    -   -      -       -   
    7   seven  -   -      -       -   
    -   -      9   -      -       999 
  }

  # Verified by PG-14
  do_execsql_test join9-$id.950 {
    SELECT *
      FROM t3 FULL JOIN (
                t4 LEFT JOIN (
                    t5 FULL JOIN t6 USING(id)
                ) USING(id)
           ) AS j1 ON j1.id=t3.id
     ORDER BY coalesce(t3.id,j1.id);
  } {
    2   two    2   alice  orange  -  
    3   three  -   -      -       -  
    -   -      4   bob    green   444
    6   six    6   cindy  -       -  
    7   seven  -   -      -       -  
    -   -      8   dave   -       -  
  }

  # Restriction (27) in the query flattener
  # Verified by PG-14
  do_execsql_test join9-$id.1000 {
    WITH t56(id,y,z) AS (SELECT * FROM t5 FULL JOIN t6 USING(id) LIMIT 50)
    SELECT id,x,y,z FROM t4 JOIN t56 USING(id)
    ORDER BY 1;
  } {
    2   alice  orange  -  
    4   bob    green   444
  }

  # Verified by PG-14
  do_execsql_test join9-$id.1010 {
    SELECT id,x,y,z
      FROM t4 INNER JOIN (t5 FULL JOIN t6 USING(id)) USING(id)
     ORDER BY 1;
  } {
    2   alice  orange  -  
    4   bob    green   444
  }

  # Verified by PG-14
  do_execsql_test join9-$id.1020 {
    SELECT id,x,y,z
      FROM t4 FULL JOIN t5 USING(id) INNER JOIN t6 USING(id)
     ORDER BY 1;
  } {
    3   -    yellow  333
    4   bob  green   444
    5   -    blue    555
  }

  # Verified by PG-14
  do_execsql_test join9-$id.1030 {
    WITH t45(id,x,y) AS (SELECT * FROM t4 FULL JOIN t5 USING(id) LIMIT 50)
    SELECT id,x,y,z FROM t45 JOIN t6 USING(id)
    ORDER BY 1;
  } {
    3   -    yellow  333
    4   bob  green   444
    5   -    blue    555
  }

}
finish_test

Added test/joinA.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022-04-18
#
# 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 file implements tests for RIGHT and FULL OUTER JOINs.

set testdir [file dirname $argv0]
source $testdir/tester.tcl

foreach {id schema} {
  1 {
    CREATE TABLE t1(a INT, b INT, c INT, d INT);
    CREATE TABLE t2(c INT, d INT, e INT, f INT);
    CREATE TABLE t3(a INT, b INT, e INT, f INT);
    CREATE TABLE t4(a INT, c INT, d INT, f INT);
    INSERT INTO t1 VALUES(11,21,31,41),(12,22,32,42),(15,25,35,45),(18,28,38,48);
    INSERT INTO t2 VALUES(12,22,32,42),(13,23,33,43),(15,25,35,45),(17,27,37,47);
    INSERT INTO t3 VALUES(14,24,34,44),(15,25,35,45),(16,26,36,46);
    INSERT INTO t4 VALUES(11,21,31,41),(13,23,33,43),(16,26,36,46),(19,29,39,49);
  }
  2 {
    CREATE TABLE t1(a INTEGER PRIMARY KEY, b INT, c INT, d INT);
    CREATE TABLE t2(c INT, d INTEGER PRIMARY KEY, e INT, f INT);
    CREATE TABLE t3(a INT, b INT, e INTEGER PRIMARY KEY, f INT);
    CREATE TABLE t4(a INT, c INT, d INT, f INT PRIMARY KEY) WITHOUT ROWID;
    INSERT INTO t1 VALUES(11,21,31,41),(12,22,32,42),(15,25,35,45),(18,28,38,48);
    INSERT INTO t2 VALUES(12,22,32,42),(13,23,33,43),(15,25,35,45),(17,27,37,47);
    INSERT INTO t3 VALUES(14,24,34,44),(15,25,35,45),(16,26,36,46);
    INSERT INTO t4 VALUES(11,21,31,41),(13,23,33,43),(16,26,36,46),(19,29,39,49);
  }
  3 {
    CREATE TABLE t1a(a INT, b INT, c INT, d INT);
    CREATE TABLE t2a(c INT, d INT, e INT, f INT);
    CREATE TABLE t3a(a INT, b INT, e INT, f INT);
    CREATE TABLE t4a(a INT, c INT, d INT, f INT);
    INSERT INTO t1a VALUES(11,21,31,41),(12,22,32,42);
    INSERT INTO t2a VALUES(12,22,32,42),(13,23,33,43);
    INSERT INTO t3a VALUES(14,24,34,44),(15,25,35,45);
    INSERT INTO t4a VALUES(11,21,31,41),(13,23,33,43);
    CREATE TABLE t1b(a INT, b INT, c INT, d INT);
    CREATE TABLE t2b(c INT, d INT, e INT, f INT);
    CREATE TABLE t3b(a INT, b INT, e INT, f INT);
    CREATE TABLE t4b(a INT, c INT, d INT, f INT);
    INSERT INTO t1b VALUES(15,25,35,45),(18,28,38,48);
    INSERT INTO t2b VALUES(15,25,35,45),(17,27,37,47);
    INSERT INTO t3b VALUES(15,25,35,45),(16,26,36,46);
    INSERT INTO t4b VALUES(16,26,36,46),(19,29,39,49);
    CREATE VIEW t1 AS SELECT * FROM t1a UNION SELECT * FROM t1b;
    CREATE VIEW t2 AS SELECT * FROM t2a UNION SELECT * FROM t2b;
    CREATE VIEW t3 AS SELECT * FROM t3a UNION SELECT * FROM t3b;
    CREATE VIEW t4 AS SELECT * FROM t4a UNION SELECT * FROM t4b;
  }
} {
  reset_db
  db nullvalue -
  do_execsql_test joinA-$id.setup $schema {}

  # Verified by PG-14
  do_execsql_test joinA-$id.100 {
    SELECT a,b,c,d,t2.e,f,t3.e
      FROM t1
           INNER JOIN t2 USING(c,d)
           INNER JOIN t3 USING(a,b,f)
           INNER JOIN t4 USING(a,c,d,f)
    ORDER BY 1 nulls first, 3 nulls first;
  } {}


  # Verified by PG-14
  do_execsql_test joinA-$id.110 {
    SELECT a,b,c,d,t2.e,f,t3.e
      FROM t1
           LEFT JOIN t2 USING(c,d)
           LEFT JOIN t3 USING(a,b,f)
           LEFT JOIN t4 USING(a,c,d,f)
    ORDER BY 1 nulls first, 3 nulls first;
  } {
    11  21  31  41  -  -  -
    12  22  32  42  -  -  -
    15  25  35  45  -  -  -
    18  28  38  48  -  -  -
  }

  # Verified by PG-14
  do_execsql_test joinA-$id.120 {
    SELECT a,b,c,d,t2.e,f,t3.e
      FROM t1
           LEFT JOIN t2 USING(c,d)
           RIGHT JOIN t3 USING(a,b,f)
           LEFT JOIN t4 USING(a,c,d,f)
    ORDER BY 1 nulls first, 3 nulls first;
  } {
    14  24  -  -  -  44  34
    15  25  -  -  -  45  35
    16  26  -  -  -  46  36
  }

  # Verified by PG-14
  do_execsql_test joinA-$id.130 {
    SELECT a,b,c,d,t2.e,f,t3.e
      FROM t1
           RIGHT JOIN t2 USING(c,d)
           LEFT JOIN t3 USING(a,b,f)
           RIGHT JOIN t4 USING(a,c,d,f)
    ORDER BY 1 nulls first, 3 nulls first;
  } {
    11  -  21  31  -  41  -
    13  -  23  33  -  43  -
    16  -  26  36  -  46  -
    19  -  29  39  -  49  -
  }

  # Verified by PG-14
  do_execsql_test joinA-$id.140 {
    SELECT a,b,c,d,t2.e,f,t3.e
      FROM t1
           FULL JOIN t2 USING(c,d)
           LEFT JOIN t3 USING(a,b,f)
           RIGHT JOIN t4 USING(a,c,d,f)
    ORDER BY 1 nulls first, 3 nulls first;
  } {
    11  -  21  31  -  41  -
    13  -  23  33  -  43  -
    16  -  26  36  -  46  -
    19  -  29  39  -  49  -
  }

  # Verified by PG-14
  do_execsql_test joinA-$id.150 {
    SELECT a,b,c,d,t2.e,f,t3.e
      FROM t1
           RIGHT JOIN t2 USING(c,d)
           FULL JOIN t3 USING(a,b,f)
           RIGHT JOIN t4 USING(a,c,d,f)
    ORDER BY 1 nulls first, 3 nulls first;
  } {
    11  -  21  31  -  41  -
    13  -  23  33  -  43  -
    16  -  26  36  -  46  -
    19  -  29  39  -  49  -
  }

  # Verified by PG-14
  do_execsql_test joinA-$id.160 {
    SELECT a,b,c,d,t2.e,f,t3.e
      FROM t1
           RIGHT JOIN t2 USING(c,d)
           LEFT JOIN t3 USING(a,b,f)
           FULL JOIN t4 USING(a,c,d,f)
    ORDER BY 1 nulls first, 3 nulls first;
  } {
    -   -  12  22  32  42  -
    -   -  13  23  33  43  -
    -   -  15  25  35  45  -
    -   -  17  27  37  47  -
    11  -  21  31  -   41  -
    13  -  23  33  -   43  -
    16  -  26  36  -   46  -
    19  -  29  39  -   49  -
  }

  # Verified by PG-14
  do_execsql_test joinA-$id.170 {
    SELECT a,b,c,d,t2.e,f,t3.e
      FROM t1
           LEFT JOIN t2 USING(c,d)
           RIGHT JOIN t3 USING(a,b,f)
           FULL JOIN t4 USING(a,c,d,f)
    ORDER BY 1 nulls first, 3 nulls first;
  } {
    11  -   21  31  -  41  - 
    13  -   23  33  -  43  - 
    14  24  -   -   -  44  34
    15  25  -   -   -  45  35
    16  26  -   -   -  46  36
    16  -   26  36  -  46  - 
    19  -   29  39  -  49  - 
  }

  # Verified by PG-14
  do_execsql_test joinA-$id.200 {
    SELECT a,b,c,d,t2.e,f,t3.e
      FROM t1
           FULL JOIN t2 USING(c,d)
           FULL JOIN t3 USING(a,b,f)
           FULL JOIN t4 USING(a,c,d,f)
    ORDER BY 1 nulls first, 3 nulls first;
  } {
    -   -   12  22  32  42  - 
    -   -   13  23  33  43  - 
    -   -   15  25  35  45  - 
    -   -   17  27  37  47  - 
    11  -   21  31  -   41  - 
    11  21  31  41  -   -   - 
    12  22  32  42  -   -   - 
    13  -   23  33  -   43  - 
    14  24  -   -   -   44  34
    15  25  -   -   -   45  35
    15  25  35  45  -   -   - 
    16  26  -   -   -   46  36
    16  -   26  36  -   46  - 
    18  28  38  48  -   -   - 
    19  -   29  39  -   49  - 
  }
}
finish_test

Added test/joinB.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
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
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
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
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
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
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
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
1984
1985
1986
1987
1988
1989
1990
1991
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
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
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
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
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
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
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
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
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
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
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
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
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
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
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
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
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
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
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
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
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
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
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
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
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
4360
4361
4362
4363
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
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
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
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
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
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
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
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
6457
6458
6459
6460
6461
6462
6463
6464
6465
6466
6467
6468
6469
6470
6471
6472
6473
6474
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485
6486
6487
6488
6489
6490
6491
6492
6493
6494
6495
6496
6497
6498
6499
6500
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516
6517
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561
6562
6563
6564
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583
6584
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621
6622
6623
6624
6625
6626
6627
6628
6629
6630
6631
6632
6633
6634
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
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
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
6735
6736
6737
6738
6739
6740
6741
6742
6743
6744
6745
6746
6747
6748
6749
6750
6751
6752
6753
6754
6755
6756
6757
6758
6759
6760
6761
6762
6763
6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774
6775
6776
6777
6778
6779
6780
6781
6782
6783
6784
6785
6786
6787
6788
6789
6790
6791
6792
6793
6794
6795
6796
6797
6798
6799
6800
6801
6802
6803
6804
6805
6806
6807
6808
6809
6810
6811
6812
6813
6814
6815
6816
6817
6818
6819
6820
6821
6822
6823
6824
6825
6826
6827
6828
6829
6830
6831
6832
6833
6834
6835
6836
6837
6838
6839
6840
6841
6842
6843
6844
6845
6846
6847
6848
6849
6850
6851
6852
6853
6854
6855
6856
6857
6858
6859
6860
6861
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
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
6903
6904
6905
6906
6907
6908
6909
6910
6911
6912
6913
6914
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
6943
6944
6945
6946
6947
6948
6949
6950
6951
6952
6953
6954
6955
6956
6957
6958
6959
6960
6961
6962
6963
6964
6965
6966
6967
6968
6969
6970
6971
6972
6973
6974
6975
6976
6977
6978
6979
6980
6981
6982
6983
6984
6985
6986
6987
6988
6989
6990
6991
6992
6993
6994
6995
6996
6997
6998
6999
7000
7001
7002
7003
7004
7005
7006
7007
7008
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
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
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
7097
7098
7099
7100
7101
7102
7103
7104
7105
7106
7107
7108
7109
7110
7111
7112
7113
7114
7115
7116
7117
7118
7119
7120
7121
7122
7123
7124
7125
7126
7127
7128
7129
7130
7131
7132
7133
7134
7135
7136
7137
7138
7139
7140
7141
7142
7143
7144
7145
7146
7147
7148
7149
7150
7151
7152
7153
7154
7155
7156
7157
7158
7159
7160
7161
7162
7163
7164
7165
7166
7167
7168
7169
7170
7171
7172
7173
7174
7175
7176
7177
7178
7179
7180
7181
7182
7183
7184
7185
7186
7187
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
7236
7237
7238
7239
7240
7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
set testdir [file dirname $argv0]
# 2022-04-19
#
# 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 tests for JOINs.
#
# The test case output is all generated by PostgreSQL 14.  This test module
# was created as follows:
#
#   1.   Run a TCL script (included at the bottom of this file) that
#        generates an input script for "psql" that will run man
#        diverse tests on joins.
#
#   2.   Run the script from step (1) through psql and collect the
#        output.
#
#   3.   Make a few minor global search-and-replace operations to convert
#        the psql output into a form suitable for this test module.
#
#   4.   Add this header, and the script content at the footer.
#
source $testdir/tester.tcl
db nullvalue -
db eval {
  DROP TABLE IF EXISTS t1;
  DROP TABLE IF EXISTS t2;
  DROP TABLE IF EXISTS t3;
  DROP TABLE IF EXISTS t4;
  DROP TABLE IF EXISTS t5;
  CREATE TABLE t1(a INT, b INT, c INT);
  CREATE TABLE t2(a INT, b INT, d INT);
  CREATE TABLE t3(a INT, b INT, e INT);
  CREATE TABLE t4(a INT, b INT, f INT);
  CREATE TABLE t5(a INT, b INT, g INT);
  INSERT INTO t1 VALUES(11,21,31),(12,22,32),(15,25,35),(17,27,37);
  INSERT INTO t2 VALUES(12,22,32),(13,23,33),(15,25,35),(18,28,38),
                       (NULL,NULL,36);
  INSERT INTO t4 VALUES(11,21,31),(13,23,33),(15,25,35),(19,29,39);
  INSERT INTO t3 SELECT * FROM t1 UNION SELECT * FROM t2 UNION SELECT * FROM t4;
  INSERT INTO t5 SELECT * FROM t3 WHERE a>=15;
}
do_execsql_test joinB-1 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
}
do_execsql_test joinB-2 {
  SELECT a, c, d, e, f, g
  FROM t1
  INNER JOIN t2 USING(a,b)
  INNER JOIN t3 USING(a,b)
  INNER JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
}
do_execsql_test joinB-3 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
}
do_execsql_test joinB-4 {
  SELECT a, c, d, e, f, g
  FROM t1
  INNER JOIN (t2 INNER JOIN t3 USING(a)) USING(a)
  INNER JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
}
do_execsql_test joinB-5 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  -  - 19
}
do_execsql_test joinB-6 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  INNER JOIN t2 USING(a,b)
  INNER JOIN t3 USING(a,b)
  INNER JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  -  -  - 39
}
do_execsql_test joinB-7 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  -  - 19
}
do_execsql_test joinB-8 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL INNER JOIN t2
  NATURAL INNER JOIN t3
  NATURAL INNER JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-9 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
}
do_execsql_test joinB-10 {
  SELECT a, c, d, e, f, g
  FROM t1
  INNER JOIN t2 USING(a,b)
  INNER JOIN t3 USING(a,b)
  LEFT JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
}
do_execsql_test joinB-11 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12 12  -  -
  15 15 15 15 15 15
}
do_execsql_test joinB-12 {
  SELECT a, c, d, e, f, g
  FROM t1
  INNER JOIN (t2 INNER JOIN t3 USING(a)) USING(a)
  LEFT JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  12 32 32 32  -  -
  15 35 35 35 35 35
}
do_execsql_test joinB-13 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  -  - 19
}
do_execsql_test joinB-14 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  INNER JOIN t2 USING(a,b)
  INNER JOIN t3 USING(a,b)
  LEFT JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  -  -  - 39
}
do_execsql_test joinB-15 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12 12  -  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  -  - 19
}
do_execsql_test joinB-16 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL INNER JOIN t2
  NATURAL INNER JOIN t3
  NATURAL LEFT JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-17 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  19  -  -  - 19 19
}
do_execsql_test joinB-18 {
  SELECT a, c, d, e, f, g
  FROM t1
  INNER JOIN t2 USING(a,b)
  INNER JOIN t3 USING(a,b)
  RIGHT JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  19  -  -  - 39 39
}
do_execsql_test joinB-19 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11  -  -  - 11  -
  13  -  -  - 13  -
  15 15 15 15 15 15
  19  -  -  - 19 19
}
do_execsql_test joinB-20 {
  SELECT a, c, d, e, f, g
  FROM t1
  INNER JOIN (t2 INNER JOIN t3 USING(a)) USING(a)
  RIGHT JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11  -  -  - 31  -
  13  -  -  - 33  -
  15 35 35 35 35 35
}
do_execsql_test joinB-21 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-22 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  INNER JOIN t2 USING(a,b)
  INNER JOIN t3 USING(a,b)
  RIGHT JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  -  - 39 39
}
do_execsql_test joinB-23 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11  -  -  - 11  -
  13  -  -  - 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-24 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL INNER JOIN t2
  NATURAL INNER JOIN t3
  NATURAL RIGHT JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-25 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  19  -  -  - 19 19
}
do_execsql_test joinB-26 {
  SELECT a, c, d, e, f, g
  FROM t1
  INNER JOIN t2 USING(a,b)
  INNER JOIN t3 USING(a,b)
  FULL JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  19  -  -  - 39 39
}
do_execsql_test joinB-27 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11  -  -  - 11  -
  12 12 12 12  -  -
  13  -  -  - 13  -
  15 15 15 15 15 15
  19  -  -  - 19 19
}
do_execsql_test joinB-28 {
  SELECT a, c, d, e, f, g
  FROM t1
  INNER JOIN (t2 INNER JOIN t3 USING(a)) USING(a)
  FULL JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11  -  -  - 31  -
  12 32 32 32  -  -
  13  -  -  - 33  -
  15 35 35 35 35 35
}
do_execsql_test joinB-29 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-30 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  INNER JOIN t2 USING(a,b)
  INNER JOIN t3 USING(a,b)
  FULL JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  -  - 39 39
}
do_execsql_test joinB-31 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11  -  -  - 11  -
  12 12 12 12  -  -
  13  -  -  - 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-32 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL INNER JOIN t2
  NATURAL INNER JOIN t3
  NATURAL FULL JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-33 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
}
do_execsql_test joinB-34 {
  SELECT a, c, d, e, f, g
  FROM t1
  INNER JOIN t2 USING(a,b)
  LEFT JOIN t3 USING(a,b)
  INNER JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
}
do_execsql_test joinB-35 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
}
do_execsql_test joinB-36 {
  SELECT a, c, d, e, f, g
  FROM t1
  INNER JOIN (t2 LEFT JOIN t3 USING(a)) USING(a)
  INNER JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
}
do_execsql_test joinB-37 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  -  - 19
}
do_execsql_test joinB-38 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  INNER JOIN t2 USING(a,b)
  LEFT JOIN t3 USING(a,b)
  INNER JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  -  -  - 39
}
do_execsql_test joinB-39 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  -  - 19
}
do_execsql_test joinB-40 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL INNER JOIN t2
  NATURAL LEFT JOIN t3
  NATURAL INNER JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-41 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
}
do_execsql_test joinB-42 {
  SELECT a, c, d, e, f, g
  FROM t1
  INNER JOIN t2 USING(a,b)
  LEFT JOIN t3 USING(a,b)
  LEFT JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
}
do_execsql_test joinB-43 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12 12  -  -
  15 15 15 15 15 15
}
do_execsql_test joinB-44 {
  SELECT a, c, d, e, f, g
  FROM t1
  INNER JOIN (t2 LEFT JOIN t3 USING(a)) USING(a)
  LEFT JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  12 32 32 32  -  -
  15 35 35 35 35 35
}
do_execsql_test joinB-45 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  -  - 19
}
do_execsql_test joinB-46 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  INNER JOIN t2 USING(a,b)
  LEFT JOIN t3 USING(a,b)
  LEFT JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  -  -  - 39
}
do_execsql_test joinB-47 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12 12  -  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  -  - 19
}
do_execsql_test joinB-48 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL INNER JOIN t2
  NATURAL LEFT JOIN t3
  NATURAL LEFT JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-49 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  19  -  -  - 19 19
}
do_execsql_test joinB-50 {
  SELECT a, c, d, e, f, g
  FROM t1
  INNER JOIN t2 USING(a,b)
  LEFT JOIN t3 USING(a,b)
  RIGHT JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  19  -  -  - 39 39
}
do_execsql_test joinB-51 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11  -  -  - 11  -
  13  -  -  - 13  -
  15 15 15 15 15 15
  19  -  -  - 19 19
}
do_execsql_test joinB-52 {
  SELECT a, c, d, e, f, g
  FROM t1
  INNER JOIN (t2 LEFT JOIN t3 USING(a)) USING(a)
  RIGHT JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11  -  -  - 31  -
  13  -  -  - 33  -
  15 35 35 35 35 35
}
do_execsql_test joinB-53 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-54 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  INNER JOIN t2 USING(a,b)
  LEFT JOIN t3 USING(a,b)
  RIGHT JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  -  - 39 39
}
do_execsql_test joinB-55 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11  -  -  - 11  -
  13  -  -  - 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-56 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL INNER JOIN t2
  NATURAL LEFT JOIN t3
  NATURAL RIGHT JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-57 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  19  -  -  - 19 19
}
do_execsql_test joinB-58 {
  SELECT a, c, d, e, f, g
  FROM t1
  INNER JOIN t2 USING(a,b)
  LEFT JOIN t3 USING(a,b)
  FULL JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  19  -  -  - 39 39
}
do_execsql_test joinB-59 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11  -  -  - 11  -
  12 12 12 12  -  -
  13  -  -  - 13  -
  15 15 15 15 15 15
  19  -  -  - 19 19
}
do_execsql_test joinB-60 {
  SELECT a, c, d, e, f, g
  FROM t1
  INNER JOIN (t2 LEFT JOIN t3 USING(a)) USING(a)
  FULL JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11  -  -  - 31  -
  12 32 32 32  -  -
  13  -  -  - 33  -
  15 35 35 35 35 35
}
do_execsql_test joinB-61 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-62 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  INNER JOIN t2 USING(a,b)
  LEFT JOIN t3 USING(a,b)
  FULL JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  -  - 39 39
}
do_execsql_test joinB-63 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11  -  -  - 11  -
  12 12 12 12  -  -
  13  -  -  - 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-64 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL INNER JOIN t2
  NATURAL LEFT JOIN t3
  NATURAL FULL JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-65 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  19  -  - 19 19 19
}
do_execsql_test joinB-66 {
  SELECT a, c, d, e, f, g
  FROM t1
  INNER JOIN t2 USING(a,b)
  RIGHT JOIN t3 USING(a,b)
  INNER JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  19  -  - 39 39 39
}
do_execsql_test joinB-67 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11  -  - 11 11  -
  13  -  - 13 13  -
  15 15 15 15 15 15
  19  -  - 19 19 19
}
do_execsql_test joinB-68 {
  SELECT a, c, d, e, f, g
  FROM t1
  INNER JOIN (t2 RIGHT JOIN t3 USING(a)) USING(a)
  INNER JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  - 31 31  -
  15 35 35 35 35 35
}
do_execsql_test joinB-69 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-70 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  INNER JOIN t2 USING(a,b)
  RIGHT JOIN t3 USING(a,b)
  INNER JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  - 39 39 39
}
do_execsql_test joinB-71 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11  -  - 11 11  -
  13  -  - 13 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-72 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL INNER JOIN t2
  NATURAL RIGHT JOIN t3
  NATURAL INNER JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-73 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  - 17  - 17
  18  -  - 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-74 {
  SELECT a, c, d, e, f, g
  FROM t1
  INNER JOIN t2 USING(a,b)
  RIGHT JOIN t3 USING(a,b)
  LEFT JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  17  -  - 37  - 37
  18  -  - 38  - 38
  19  -  - 39 39 39
}
do_execsql_test joinB-75 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11  -  - 11 11  -
  12 12 12 12  -  -
  13  -  - 13 13  -
  15 15 15 15 15 15
  17  -  - 17  - 17
  18  -  - 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-76 {
  SELECT a, c, d, e, f, g
  FROM t1
  INNER JOIN (t2 RIGHT JOIN t3 USING(a)) USING(a)
  LEFT JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  - 31 31  -
  12 32 32 32  -  -
  15 35 35 35 35 35
  17 37  - 37  -  -
}
do_execsql_test joinB-77 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  - 17  - 17
  18  -  - 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-78 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  INNER JOIN t2 USING(a,b)
  RIGHT JOIN t3 USING(a,b)
  LEFT JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  - 37  - 37
  18 28  -  - 38  - 38
  19 29  -  - 39 39 39
}
do_execsql_test joinB-79 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11  -  - 11 11  -
  12 12 12 12  -  -
  13  -  - 13 13  -
  15 15 15 15 15 15
  17  -  - 17  - 17
  18  -  - 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-80 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL INNER JOIN t2
  NATURAL RIGHT JOIN t3
  NATURAL LEFT JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-81 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  19  -  - 19 19 19
}
do_execsql_test joinB-82 {
  SELECT a, c, d, e, f, g
  FROM t1
  INNER JOIN t2 USING(a,b)
  RIGHT JOIN t3 USING(a,b)
  RIGHT JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  19  -  - 39 39 39
}
do_execsql_test joinB-83 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11  -  - 11 11  -
  13  -  - 13 13  -
  15 15 15 15 15 15
  19  -  - 19 19 19
}
do_execsql_test joinB-84 {
  SELECT a, c, d, e, f, g
  FROM t1
  INNER JOIN (t2 RIGHT JOIN t3 USING(a)) USING(a)
  RIGHT JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  - 31 31  -
  13  -  -  - 33  -
  15 35 35 35 35 35
}
do_execsql_test joinB-85 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-86 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  INNER JOIN t2 USING(a,b)
  RIGHT JOIN t3 USING(a,b)
  RIGHT JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  - 39 39 39
}
do_execsql_test joinB-87 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11  -  - 11 11  -
  13  -  - 13 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-88 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL INNER JOIN t2
  NATURAL RIGHT JOIN t3
  NATURAL RIGHT JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-89 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  - 17  - 17
  18  -  - 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-90 {
  SELECT a, c, d, e, f, g
  FROM t1
  INNER JOIN t2 USING(a,b)
  RIGHT JOIN t3 USING(a,b)
  FULL JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  17  -  - 37  - 37
  18  -  - 38  - 38
  19  -  - 39 39 39
}
do_execsql_test joinB-91 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11  -  - 11 11  -
  12 12 12 12  -  -
  13  -  - 13 13  -
  15 15 15 15 15 15
  17  -  - 17  - 17
  18  -  - 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-92 {
  SELECT a, c, d, e, f, g
  FROM t1
  INNER JOIN (t2 RIGHT JOIN t3 USING(a)) USING(a)
  FULL JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  - 31 31  -
  12 32 32 32  -  -
  13  -  -  - 33  -
  15 35 35 35 35 35
  17 37  - 37  -  -
}
do_execsql_test joinB-93 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  - 17  - 17
  18  -  - 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-94 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  INNER JOIN t2 USING(a,b)
  RIGHT JOIN t3 USING(a,b)
  FULL JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  - 37  - 37
  18 28  -  - 38  - 38
  19 29  -  - 39 39 39
}
do_execsql_test joinB-95 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11  -  - 11 11  -
  12 12 12 12  -  -
  13  -  - 13 13  -
  15 15 15 15 15 15
  17  -  - 17  - 17
  18  -  - 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-96 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL INNER JOIN t2
  NATURAL RIGHT JOIN t3
  NATURAL FULL JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-97 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  19  -  - 19 19 19
}
do_execsql_test joinB-98 {
  SELECT a, c, d, e, f, g
  FROM t1
  INNER JOIN t2 USING(a,b)
  FULL JOIN t3 USING(a,b)
  INNER JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  19  -  - 39 39 39
}
do_execsql_test joinB-99 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11  -  - 11 11  -
  13  -  - 13 13  -
  15 15 15 15 15 15
  19  -  - 19 19 19
}
do_execsql_test joinB-100 {
  SELECT a, c, d, e, f, g
  FROM t1
  INNER JOIN (t2 FULL JOIN t3 USING(a)) USING(a)
  INNER JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  - 31 31  -
  15 35 35 35 35 35
}
do_execsql_test joinB-101 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-102 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  INNER JOIN t2 USING(a,b)
  FULL JOIN t3 USING(a,b)
  INNER JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  - 39 39 39
}
do_execsql_test joinB-103 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11  -  - 11 11  -
  13  -  - 13 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-104 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL INNER JOIN t2
  NATURAL FULL JOIN t3
  NATURAL INNER JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-105 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  - 17  - 17
  18  -  - 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-106 {
  SELECT a, c, d, e, f, g
  FROM t1
  INNER JOIN t2 USING(a,b)
  FULL JOIN t3 USING(a,b)
  LEFT JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  17  -  - 37  - 37
  18  -  - 38  - 38
  19  -  - 39 39 39
}
do_execsql_test joinB-107 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11  -  - 11 11  -
  12 12 12 12  -  -
  13  -  - 13 13  -
  15 15 15 15 15 15
  17  -  - 17  - 17
  18  -  - 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-108 {
  SELECT a, c, d, e, f, g
  FROM t1
  INNER JOIN (t2 FULL JOIN t3 USING(a)) USING(a)
  LEFT JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  - 31 31  -
  12 32 32 32  -  -
  15 35 35 35 35 35
  17 37  - 37  -  -
}
do_execsql_test joinB-109 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  - 17  - 17
  18  -  - 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-110 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  INNER JOIN t2 USING(a,b)
  FULL JOIN t3 USING(a,b)
  LEFT JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  - 37  - 37
  18 28  -  - 38  - 38
  19 29  -  - 39 39 39
}
do_execsql_test joinB-111 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11  -  - 11 11  -
  12 12 12 12  -  -
  13  -  - 13 13  -
  15 15 15 15 15 15
  17  -  - 17  - 17
  18  -  - 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-112 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL INNER JOIN t2
  NATURAL FULL JOIN t3
  NATURAL LEFT JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-113 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  19  -  - 19 19 19
}
do_execsql_test joinB-114 {
  SELECT a, c, d, e, f, g
  FROM t1
  INNER JOIN t2 USING(a,b)
  FULL JOIN t3 USING(a,b)
  RIGHT JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  19  -  - 39 39 39
}
do_execsql_test joinB-115 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11  -  - 11 11  -
  13  -  - 13 13  -
  15 15 15 15 15 15
  19  -  - 19 19 19
}
do_execsql_test joinB-116 {
  SELECT a, c, d, e, f, g
  FROM t1
  INNER JOIN (t2 FULL JOIN t3 USING(a)) USING(a)
  RIGHT JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  - 31 31  -
  13  -  -  - 33  -
  15 35 35 35 35 35
}
do_execsql_test joinB-117 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-118 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  INNER JOIN t2 USING(a,b)
  FULL JOIN t3 USING(a,b)
  RIGHT JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  - 39 39 39
}
do_execsql_test joinB-119 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11  -  - 11 11  -
  13  -  - 13 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-120 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL INNER JOIN t2
  NATURAL FULL JOIN t3
  NATURAL RIGHT JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-121 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  - 17  - 17
  18  -  - 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-122 {
  SELECT a, c, d, e, f, g
  FROM t1
  INNER JOIN t2 USING(a,b)
  FULL JOIN t3 USING(a,b)
  FULL JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  17  -  - 37  - 37
  18  -  - 38  - 38
  19  -  - 39 39 39
}
do_execsql_test joinB-123 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11  -  - 11 11  -
  12 12 12 12  -  -
  13  -  - 13 13  -
  15 15 15 15 15 15
  17  -  - 17  - 17
  18  -  - 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-124 {
  SELECT a, c, d, e, f, g
  FROM t1
  INNER JOIN (t2 FULL JOIN t3 USING(a)) USING(a)
  FULL JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  - 31 31  -
  12 32 32 32  -  -
  13  -  -  - 33  -
  15 35 35 35 35 35
  17 37  - 37  -  -
}
do_execsql_test joinB-125 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  - 17  - 17
  18  -  - 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-126 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  INNER JOIN t2 USING(a,b)
  FULL JOIN t3 USING(a,b)
  FULL JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  - 37  - 37
  18 28  -  - 38  - 38
  19 29  -  - 39 39 39
}
do_execsql_test joinB-127 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  INNER JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11  -  - 11 11  -
  12 12 12 12  -  -
  13  -  - 13 13  -
  15 15 15 15 15 15
  17  -  - 17  - 17
  18  -  - 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-128 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL INNER JOIN t2
  NATURAL FULL JOIN t3
  NATURAL FULL JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-129 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
}
do_execsql_test joinB-130 {
  SELECT a, c, d, e, f, g
  FROM t1
  LEFT JOIN t2 USING(a,b)
  INNER JOIN t3 USING(a,b)
  INNER JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
}
do_execsql_test joinB-131 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  15 15 15 15 15 15
}
do_execsql_test joinB-132 {
  SELECT a, c, d, e, f, g
  FROM t1
  LEFT JOIN (t2 INNER JOIN t3 USING(a)) USING(a)
  INNER JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  -  - 31  -
  15 35 35 35 35 35
}
do_execsql_test joinB-133 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  -  - 19
}
do_execsql_test joinB-134 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  LEFT JOIN t2 USING(a,b)
  INNER JOIN t3 USING(a,b)
  INNER JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  -  -  - 39
}
do_execsql_test joinB-135 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  -  - 19
}
do_execsql_test joinB-136 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL LEFT JOIN t2
  NATURAL INNER JOIN t3
  NATURAL INNER JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-137 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
}
do_execsql_test joinB-138 {
  SELECT a, c, d, e, f, g
  FROM t1
  LEFT JOIN t2 USING(a,b)
  INNER JOIN t3 USING(a,b)
  LEFT JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  17 37  - 37  - 37
}
do_execsql_test joinB-139 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17
}
do_execsql_test joinB-140 {
  SELECT a, c, d, e, f, g
  FROM t1
  LEFT JOIN (t2 INNER JOIN t3 USING(a)) USING(a)
  LEFT JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  -  - 31  -
  12 32 32 32  -  -
  15 35 35 35 35 35
  17 37  -  -  -  -
}
do_execsql_test joinB-141 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  -  -  -  - 18
  19  -  -  -  - 19
}
do_execsql_test joinB-142 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  LEFT JOIN t2 USING(a,b)
  INNER JOIN t3 USING(a,b)
  LEFT JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27 37  - 37  - 37
  18 28  -  -  -  - 38
  19 29  -  -  -  - 39
}
do_execsql_test joinB-143 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  -  -  -  - 18
  19  -  -  -  - 19
}
do_execsql_test joinB-144 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL LEFT JOIN t2
  NATURAL INNER JOIN t3
  NATURAL LEFT JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-145 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  19  -  -  - 19 19
}
do_execsql_test joinB-146 {
  SELECT a, c, d, e, f, g
  FROM t1
  LEFT JOIN t2 USING(a,b)
  INNER JOIN t3 USING(a,b)
  RIGHT JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  19  -  -  - 39 39
}
do_execsql_test joinB-147 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  13  -  -  - 13  -
  15 15 15 15 15 15
  19  -  -  - 19 19
}
do_execsql_test joinB-148 {
  SELECT a, c, d, e, f, g
  FROM t1
  LEFT JOIN (t2 INNER JOIN t3 USING(a)) USING(a)
  RIGHT JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  -  - 31  -
  13  -  -  - 33  -
  15 35 35 35 35 35
}
do_execsql_test joinB-149 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-150 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  LEFT JOIN t2 USING(a,b)
  INNER JOIN t3 USING(a,b)
  RIGHT JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  -  - 39 39
}
do_execsql_test joinB-151 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  13  -  -  - 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-152 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL LEFT JOIN t2
  NATURAL INNER JOIN t3
  NATURAL RIGHT JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-153 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
  19  -  -  - 19 19
}
do_execsql_test joinB-154 {
  SELECT a, c, d, e, f, g
  FROM t1
  LEFT JOIN t2 USING(a,b)
  INNER JOIN t3 USING(a,b)
  FULL JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  17 37  - 37  - 37
  19  -  -  - 39 39
}
do_execsql_test joinB-155 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  -  -  - 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  19  -  -  - 19 19
}
do_execsql_test joinB-156 {
  SELECT a, c, d, e, f, g
  FROM t1
  LEFT JOIN (t2 INNER JOIN t3 USING(a)) USING(a)
  FULL JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  -  - 31  -
  12 32 32 32  -  -
  13  -  -  - 33  -
  15 35 35 35 35 35
  17 37  -  -  -  -
}
do_execsql_test joinB-157 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  -  -  -  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-158 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  LEFT JOIN t2 USING(a,b)
  INNER JOIN t3 USING(a,b)
  FULL JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27 37  - 37  - 37
  18 28  -  -  -  - 38
  19 29  -  -  - 39 39
}
do_execsql_test joinB-159 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  -  -  - 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  -  -  -  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-160 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL LEFT JOIN t2
  NATURAL INNER JOIN t3
  NATURAL FULL JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-161 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
}
do_execsql_test joinB-162 {
  SELECT a, c, d, e, f, g
  FROM t1
  LEFT JOIN t2 USING(a,b)
  LEFT JOIN t3 USING(a,b)
  INNER JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
}
do_execsql_test joinB-163 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  15 15 15 15 15 15
}
do_execsql_test joinB-164 {
  SELECT a, c, d, e, f, g
  FROM t1
  LEFT JOIN (t2 LEFT JOIN t3 USING(a)) USING(a)
  INNER JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  -  - 31  -
  15 35 35 35 35 35
}
do_execsql_test joinB-165 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  -  - 19
}
do_execsql_test joinB-166 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  LEFT JOIN t2 USING(a,b)
  LEFT JOIN t3 USING(a,b)
  INNER JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  -  -  - 39
}
do_execsql_test joinB-167 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  -  - 19
}
do_execsql_test joinB-168 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL LEFT JOIN t2
  NATURAL LEFT JOIN t3
  NATURAL INNER JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-169 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
}
do_execsql_test joinB-170 {
  SELECT a, c, d, e, f, g
  FROM t1
  LEFT JOIN t2 USING(a,b)
  LEFT JOIN t3 USING(a,b)
  LEFT JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  17 37  - 37  - 37
}
do_execsql_test joinB-171 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17
}
do_execsql_test joinB-172 {
  SELECT a, c, d, e, f, g
  FROM t1
  LEFT JOIN (t2 LEFT JOIN t3 USING(a)) USING(a)
  LEFT JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  -  - 31  -
  12 32 32 32  -  -
  15 35 35 35 35 35
  17 37  -  -  -  -
}
do_execsql_test joinB-173 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  -  -  -  - 18
  19  -  -  -  - 19
}
do_execsql_test joinB-174 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  LEFT JOIN t2 USING(a,b)
  LEFT JOIN t3 USING(a,b)
  LEFT JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27 37  - 37  - 37
  18 28  -  -  -  - 38
  19 29  -  -  -  - 39
}
do_execsql_test joinB-175 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  -  -  -  - 18
  19  -  -  -  - 19
}
do_execsql_test joinB-176 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL LEFT JOIN t2
  NATURAL LEFT JOIN t3
  NATURAL LEFT JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-177 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  19  -  -  - 19 19
}
do_execsql_test joinB-178 {
  SELECT a, c, d, e, f, g
  FROM t1
  LEFT JOIN t2 USING(a,b)
  LEFT JOIN t3 USING(a,b)
  RIGHT JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  19  -  -  - 39 39
}
do_execsql_test joinB-179 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  13  -  -  - 13  -
  15 15 15 15 15 15
  19  -  -  - 19 19
}
do_execsql_test joinB-180 {
  SELECT a, c, d, e, f, g
  FROM t1
  LEFT JOIN (t2 LEFT JOIN t3 USING(a)) USING(a)
  RIGHT JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  -  - 31  -
  13  -  -  - 33  -
  15 35 35 35 35 35
}
do_execsql_test joinB-181 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-182 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  LEFT JOIN t2 USING(a,b)
  LEFT JOIN t3 USING(a,b)
  RIGHT JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  -  - 39 39
}
do_execsql_test joinB-183 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  13  -  -  - 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-184 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL LEFT JOIN t2
  NATURAL LEFT JOIN t3
  NATURAL RIGHT JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-185 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
  19  -  -  - 19 19
}
do_execsql_test joinB-186 {
  SELECT a, c, d, e, f, g
  FROM t1
  LEFT JOIN t2 USING(a,b)
  LEFT JOIN t3 USING(a,b)
  FULL JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  17 37  - 37  - 37
  19  -  -  - 39 39
}
do_execsql_test joinB-187 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  -  -  - 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  19  -  -  - 19 19
}
do_execsql_test joinB-188 {
  SELECT a, c, d, e, f, g
  FROM t1
  LEFT JOIN (t2 LEFT JOIN t3 USING(a)) USING(a)
  FULL JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  -  - 31  -
  12 32 32 32  -  -
  13  -  -  - 33  -
  15 35 35 35 35 35
  17 37  -  -  -  -
}
do_execsql_test joinB-189 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  -  -  -  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-190 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  LEFT JOIN t2 USING(a,b)
  LEFT JOIN t3 USING(a,b)
  FULL JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27 37  - 37  - 37
  18 28  -  -  -  - 38
  19 29  -  -  - 39 39
}
do_execsql_test joinB-191 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  -  -  - 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  -  -  -  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-192 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL LEFT JOIN t2
  NATURAL LEFT JOIN t3
  NATURAL FULL JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-193 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  19  -  - 19 19 19
}
do_execsql_test joinB-194 {
  SELECT a, c, d, e, f, g
  FROM t1
  LEFT JOIN t2 USING(a,b)
  RIGHT JOIN t3 USING(a,b)
  INNER JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  19  -  - 39 39 39
}
do_execsql_test joinB-195 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  13  -  - 13 13  -
  15 15 15 15 15 15
  19  -  - 19 19 19
}
do_execsql_test joinB-196 {
  SELECT a, c, d, e, f, g
  FROM t1
  LEFT JOIN (t2 RIGHT JOIN t3 USING(a)) USING(a)
  INNER JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  - 31 31  -
  15 35 35 35 35 35
}
do_execsql_test joinB-197 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-198 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  LEFT JOIN t2 USING(a,b)
  RIGHT JOIN t3 USING(a,b)
  INNER JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  - 39 39 39
}
do_execsql_test joinB-199 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  13  -  - 13 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-200 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL LEFT JOIN t2
  NATURAL RIGHT JOIN t3
  NATURAL INNER JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-201 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  -  - 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-202 {
  SELECT a, c, d, e, f, g
  FROM t1
  LEFT JOIN t2 USING(a,b)
  RIGHT JOIN t3 USING(a,b)
  LEFT JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  17 37  - 37  - 37
  18  -  - 38  - 38
  19  -  - 39 39 39
}
do_execsql_test joinB-203 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  -  - 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  -  - 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-204 {
  SELECT a, c, d, e, f, g
  FROM t1
  LEFT JOIN (t2 RIGHT JOIN t3 USING(a)) USING(a)
  LEFT JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  - 31 31  -
  12 32 32 32  -  -
  15 35 35 35 35 35
  17 37  - 37  -  -
}
do_execsql_test joinB-205 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  -  - 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-206 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  LEFT JOIN t2 USING(a,b)
  RIGHT JOIN t3 USING(a,b)
  LEFT JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27 37  - 37  - 37
  18 28  -  - 38  - 38
  19 29  -  - 39 39 39
}
do_execsql_test joinB-207 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  -  - 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  -  - 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-208 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL LEFT JOIN t2
  NATURAL RIGHT JOIN t3
  NATURAL LEFT JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-209 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  19  -  - 19 19 19
}
do_execsql_test joinB-210 {
  SELECT a, c, d, e, f, g
  FROM t1
  LEFT JOIN t2 USING(a,b)
  RIGHT JOIN t3 USING(a,b)
  RIGHT JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  19  -  - 39 39 39
}
do_execsql_test joinB-211 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  13  -  - 13 13  -
  15 15 15 15 15 15
  19  -  - 19 19 19
}
do_execsql_test joinB-212 {
  SELECT a, c, d, e, f, g
  FROM t1
  LEFT JOIN (t2 RIGHT JOIN t3 USING(a)) USING(a)
  RIGHT JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  - 31 31  -
  13  -  -  - 33  -
  15 35 35 35 35 35
}
do_execsql_test joinB-213 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-214 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  LEFT JOIN t2 USING(a,b)
  RIGHT JOIN t3 USING(a,b)
  RIGHT JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  - 39 39 39
}
do_execsql_test joinB-215 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  13  -  - 13 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-216 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL LEFT JOIN t2
  NATURAL RIGHT JOIN t3
  NATURAL RIGHT JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-217 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  -  - 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-218 {
  SELECT a, c, d, e, f, g
  FROM t1
  LEFT JOIN t2 USING(a,b)
  RIGHT JOIN t3 USING(a,b)
  FULL JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  17 37  - 37  - 37
  18  -  - 38  - 38
  19  -  - 39 39 39
}
do_execsql_test joinB-219 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  -  - 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  -  - 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-220 {
  SELECT a, c, d, e, f, g
  FROM t1
  LEFT JOIN (t2 RIGHT JOIN t3 USING(a)) USING(a)
  FULL JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  - 31 31  -
  12 32 32 32  -  -
  13  -  -  - 33  -
  15 35 35 35 35 35
  17 37  - 37  -  -
}
do_execsql_test joinB-221 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  -  - 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-222 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  LEFT JOIN t2 USING(a,b)
  RIGHT JOIN t3 USING(a,b)
  FULL JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27 37  - 37  - 37
  18 28  -  - 38  - 38
  19 29  -  - 39 39 39
}
do_execsql_test joinB-223 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  -  - 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  -  - 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-224 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL LEFT JOIN t2
  NATURAL RIGHT JOIN t3
  NATURAL FULL JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-225 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  19  -  - 19 19 19
}
do_execsql_test joinB-226 {
  SELECT a, c, d, e, f, g
  FROM t1
  LEFT JOIN t2 USING(a,b)
  FULL JOIN t3 USING(a,b)
  INNER JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  19  -  - 39 39 39
}
do_execsql_test joinB-227 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  13  -  - 13 13  -
  15 15 15 15 15 15
  19  -  - 19 19 19
}
do_execsql_test joinB-228 {
  SELECT a, c, d, e, f, g
  FROM t1
  LEFT JOIN (t2 FULL JOIN t3 USING(a)) USING(a)
  INNER JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  - 31 31  -
  15 35 35 35 35 35
}
do_execsql_test joinB-229 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-230 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  LEFT JOIN t2 USING(a,b)
  FULL JOIN t3 USING(a,b)
  INNER JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  - 39 39 39
}
do_execsql_test joinB-231 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  13  -  - 13 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-232 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL LEFT JOIN t2
  NATURAL FULL JOIN t3
  NATURAL INNER JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-233 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  -  - 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-234 {
  SELECT a, c, d, e, f, g
  FROM t1
  LEFT JOIN t2 USING(a,b)
  FULL JOIN t3 USING(a,b)
  LEFT JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  17 37  - 37  - 37
  18  -  - 38  - 38
  19  -  - 39 39 39
}
do_execsql_test joinB-235 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  -  - 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  -  - 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-236 {
  SELECT a, c, d, e, f, g
  FROM t1
  LEFT JOIN (t2 FULL JOIN t3 USING(a)) USING(a)
  LEFT JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  - 31 31  -
  12 32 32 32  -  -
  15 35 35 35 35 35
  17 37  - 37  -  -
}
do_execsql_test joinB-237 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  -  - 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-238 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  LEFT JOIN t2 USING(a,b)
  FULL JOIN t3 USING(a,b)
  LEFT JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27 37  - 37  - 37
  18 28  -  - 38  - 38
  19 29  -  - 39 39 39
}
do_execsql_test joinB-239 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  -  - 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  -  - 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-240 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL LEFT JOIN t2
  NATURAL FULL JOIN t3
  NATURAL LEFT JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-241 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  19  -  - 19 19 19
}
do_execsql_test joinB-242 {
  SELECT a, c, d, e, f, g
  FROM t1
  LEFT JOIN t2 USING(a,b)
  FULL JOIN t3 USING(a,b)
  RIGHT JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  19  -  - 39 39 39
}
do_execsql_test joinB-243 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  13  -  - 13 13  -
  15 15 15 15 15 15
  19  -  - 19 19 19
}
do_execsql_test joinB-244 {
  SELECT a, c, d, e, f, g
  FROM t1
  LEFT JOIN (t2 FULL JOIN t3 USING(a)) USING(a)
  RIGHT JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  - 31 31  -
  13  -  -  - 33  -
  15 35 35 35 35 35
}
do_execsql_test joinB-245 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-246 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  LEFT JOIN t2 USING(a,b)
  FULL JOIN t3 USING(a,b)
  RIGHT JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  - 39 39 39
}
do_execsql_test joinB-247 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  13  -  - 13 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-248 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL LEFT JOIN t2
  NATURAL FULL JOIN t3
  NATURAL RIGHT JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-249 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  -  - 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-250 {
  SELECT a, c, d, e, f, g
  FROM t1
  LEFT JOIN t2 USING(a,b)
  FULL JOIN t3 USING(a,b)
  FULL JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  17 37  - 37  - 37
  18  -  - 38  - 38
  19  -  - 39 39 39
}
do_execsql_test joinB-251 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  -  - 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  -  - 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-252 {
  SELECT a, c, d, e, f, g
  FROM t1
  LEFT JOIN (t2 FULL JOIN t3 USING(a)) USING(a)
  FULL JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  - 31 31  -
  12 32 32 32  -  -
  13  -  -  - 33  -
  15 35 35 35 35 35
  17 37  - 37  -  -
}
do_execsql_test joinB-253 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  -  - 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-254 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  LEFT JOIN t2 USING(a,b)
  FULL JOIN t3 USING(a,b)
  FULL JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27 37  - 37  - 37
  18 28  -  - 38  - 38
  19 29  -  - 39 39 39
}
do_execsql_test joinB-255 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  LEFT JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  -  - 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  -  - 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-256 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL LEFT JOIN t2
  NATURAL FULL JOIN t3
  NATURAL FULL JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-257 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
}
do_execsql_test joinB-258 {
  SELECT a, c, d, e, f, g
  FROM t1
  RIGHT JOIN t2 USING(a,b)
  INNER JOIN t3 USING(a,b)
  INNER JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
}
do_execsql_test joinB-259 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  13  - 13 13 13  -
  15 15 15 15 15 15
}
do_execsql_test joinB-260 {
  SELECT a, c, d, e, f, g
  FROM t1
  RIGHT JOIN (t2 INNER JOIN t3 USING(a)) USING(a)
  INNER JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  13  - 33 33 33  -
  15 35 35 35 35 35
}
do_execsql_test joinB-261 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  -  - 19
}
do_execsql_test joinB-262 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  RIGHT JOIN t2 USING(a,b)
  INNER JOIN t3 USING(a,b)
  INNER JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  -  -  - 39
}
do_execsql_test joinB-263 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  13  - 13 13 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  -  - 19
}
do_execsql_test joinB-264 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL RIGHT JOIN t2
  NATURAL INNER JOIN t3
  NATURAL INNER JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-265 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  18  - 18 18  - 18
}
do_execsql_test joinB-266 {
  SELECT a, c, d, e, f, g
  FROM t1
  RIGHT JOIN t2 USING(a,b)
  INNER JOIN t3 USING(a,b)
  LEFT JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  18  - 38 38  - 38
}
do_execsql_test joinB-267 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  18  - 18 18  - 18
}
do_execsql_test joinB-268 {
  SELECT a, c, d, e, f, g
  FROM t1
  RIGHT JOIN (t2 INNER JOIN t3 USING(a)) USING(a)
  LEFT JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  12 32 32 32  -  -
  13  - 33 33 33  -
  15 35 35 35 35 35
  18  - 38 38  -  -
}
do_execsql_test joinB-269 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  - 18 18  - 18
  19  -  -  -  - 19
}
do_execsql_test joinB-270 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  RIGHT JOIN t2 USING(a,b)
  INNER JOIN t3 USING(a,b)
  LEFT JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  - 38 38  - 38
  19 29  -  -  -  - 39
}
do_execsql_test joinB-271 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  - 18 18  - 18
  19  -  -  -  - 19
}
do_execsql_test joinB-272 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL RIGHT JOIN t2
  NATURAL INNER JOIN t3
  NATURAL LEFT JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-273 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  19  -  -  - 19 19
}
do_execsql_test joinB-274 {
  SELECT a, c, d, e, f, g
  FROM t1
  RIGHT JOIN t2 USING(a,b)
  INNER JOIN t3 USING(a,b)
  RIGHT JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  19  -  -  - 39 39
}
do_execsql_test joinB-275 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11  -  -  - 11  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  19  -  -  - 19 19
}
do_execsql_test joinB-276 {
  SELECT a, c, d, e, f, g
  FROM t1
  RIGHT JOIN (t2 INNER JOIN t3 USING(a)) USING(a)
  RIGHT JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11  -  -  - 31  -
  13  - 33 33 33  -
  15 35 35 35 35 35
}
do_execsql_test joinB-277 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-278 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  RIGHT JOIN t2 USING(a,b)
  INNER JOIN t3 USING(a,b)
  RIGHT JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  -  - 39 39
}
do_execsql_test joinB-279 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11  -  -  - 11  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-280 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL RIGHT JOIN t2
  NATURAL INNER JOIN t3
  NATURAL RIGHT JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-281 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  18  - 18 18  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-282 {
  SELECT a, c, d, e, f, g
  FROM t1
  RIGHT JOIN t2 USING(a,b)
  INNER JOIN t3 USING(a,b)
  FULL JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  18  - 38 38  - 38
  19  -  -  - 39 39
}
do_execsql_test joinB-283 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11  -  -  - 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  18  - 18 18  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-284 {
  SELECT a, c, d, e, f, g
  FROM t1
  RIGHT JOIN (t2 INNER JOIN t3 USING(a)) USING(a)
  FULL JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11  -  -  - 31  -
  12 32 32 32  -  -
  13  - 33 33 33  -
  15 35 35 35 35 35
  18  - 38 38  -  -
}
do_execsql_test joinB-285 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  - 18 18  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-286 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  RIGHT JOIN t2 USING(a,b)
  INNER JOIN t3 USING(a,b)
  FULL JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  - 38 38  - 38
  19 29  -  -  - 39 39
}
do_execsql_test joinB-287 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11  -  -  - 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  - 18 18  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-288 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL RIGHT JOIN t2
  NATURAL INNER JOIN t3
  NATURAL FULL JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-289 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
}
do_execsql_test joinB-290 {
  SELECT a, c, d, e, f, g
  FROM t1
  RIGHT JOIN t2 USING(a,b)
  LEFT JOIN t3 USING(a,b)
  INNER JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
}
do_execsql_test joinB-291 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  13  - 13 13 13  -
  15 15 15 15 15 15
}
do_execsql_test joinB-292 {
  SELECT a, c, d, e, f, g
  FROM t1
  RIGHT JOIN (t2 LEFT JOIN t3 USING(a)) USING(a)
  INNER JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  13  - 33 33 33  -
  15 35 35 35 35 35
}
do_execsql_test joinB-293 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  -  - 19
}
do_execsql_test joinB-294 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  RIGHT JOIN t2 USING(a,b)
  LEFT JOIN t3 USING(a,b)
  INNER JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  -  -  - 39
}
do_execsql_test joinB-295 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  13  - 13 13 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  -  - 19
}
do_execsql_test joinB-296 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL RIGHT JOIN t2
  NATURAL LEFT JOIN t3
  NATURAL INNER JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-297 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  18  - 18 18  - 18
}
do_execsql_test joinB-298 {
  SELECT a, c, d, e, f, g
  FROM t1
  RIGHT JOIN t2 USING(a,b)
  LEFT JOIN t3 USING(a,b)
  LEFT JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  18  - 38 38  - 38
}
do_execsql_test joinB-299 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  18  - 18 18  - 18
}
do_execsql_test joinB-300 {
  SELECT a, c, d, e, f, g
  FROM t1
  RIGHT JOIN (t2 LEFT JOIN t3 USING(a)) USING(a)
  LEFT JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  12 32 32 32  -  -
  13  - 33 33 33  -
  15 35 35 35 35 35
  18  - 38 38  -  -
}
do_execsql_test joinB-301 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  - 18 18  - 18
  19  -  -  -  - 19
}
do_execsql_test joinB-302 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  RIGHT JOIN t2 USING(a,b)
  LEFT JOIN t3 USING(a,b)
  LEFT JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  - 38 38  - 38
  19 29  -  -  -  - 39
}
do_execsql_test joinB-303 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  - 18 18  - 18
  19  -  -  -  - 19
}
do_execsql_test joinB-304 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL RIGHT JOIN t2
  NATURAL LEFT JOIN t3
  NATURAL LEFT JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-305 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  19  -  -  - 19 19
}
do_execsql_test joinB-306 {
  SELECT a, c, d, e, f, g
  FROM t1
  RIGHT JOIN t2 USING(a,b)
  LEFT JOIN t3 USING(a,b)
  RIGHT JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  19  -  -  - 39 39
}
do_execsql_test joinB-307 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11  -  -  - 11  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  19  -  -  - 19 19
}
do_execsql_test joinB-308 {
  SELECT a, c, d, e, f, g
  FROM t1
  RIGHT JOIN (t2 LEFT JOIN t3 USING(a)) USING(a)
  RIGHT JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11  -  -  - 31  -
  13  - 33 33 33  -
  15 35 35 35 35 35
}
do_execsql_test joinB-309 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-310 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  RIGHT JOIN t2 USING(a,b)
  LEFT JOIN t3 USING(a,b)
  RIGHT JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  -  - 39 39
}
do_execsql_test joinB-311 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11  -  -  - 11  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-312 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL RIGHT JOIN t2
  NATURAL LEFT JOIN t3
  NATURAL RIGHT JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-313 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  18  - 18 18  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-314 {
  SELECT a, c, d, e, f, g
  FROM t1
  RIGHT JOIN t2 USING(a,b)
  LEFT JOIN t3 USING(a,b)
  FULL JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  18  - 38 38  - 38
  19  -  -  - 39 39
}
do_execsql_test joinB-315 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11  -  -  - 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  18  - 18 18  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-316 {
  SELECT a, c, d, e, f, g
  FROM t1
  RIGHT JOIN (t2 LEFT JOIN t3 USING(a)) USING(a)
  FULL JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11  -  -  - 31  -
  12 32 32 32  -  -
  13  - 33 33 33  -
  15 35 35 35 35 35
  18  - 38 38  -  -
}
do_execsql_test joinB-317 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  - 18 18  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-318 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  RIGHT JOIN t2 USING(a,b)
  LEFT JOIN t3 USING(a,b)
  FULL JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  - 38 38  - 38
  19 29  -  -  - 39 39
}
do_execsql_test joinB-319 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11  -  -  - 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  - 18 18  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-320 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL RIGHT JOIN t2
  NATURAL LEFT JOIN t3
  NATURAL FULL JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-321 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  19  -  - 19 19 19
}
do_execsql_test joinB-322 {
  SELECT a, c, d, e, f, g
  FROM t1
  RIGHT JOIN t2 USING(a,b)
  RIGHT JOIN t3 USING(a,b)
  INNER JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  19  -  - 39 39 39
}
do_execsql_test joinB-323 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11  -  - 11 11  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  19  -  - 19 19 19
}
do_execsql_test joinB-324 {
  SELECT a, c, d, e, f, g
  FROM t1
  RIGHT JOIN (t2 RIGHT JOIN t3 USING(a)) USING(a)
  INNER JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  - 31 31  -
  13  - 33 33 33  -
  15 35 35 35 35 35
}
do_execsql_test joinB-325 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-326 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  RIGHT JOIN t2 USING(a,b)
  RIGHT JOIN t3 USING(a,b)
  INNER JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  - 39 39 39
}
do_execsql_test joinB-327 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11  -  - 11 11  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-328 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL RIGHT JOIN t2
  NATURAL RIGHT JOIN t3
  NATURAL INNER JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-329 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-330 {
  SELECT a, c, d, e, f, g
  FROM t1
  RIGHT JOIN t2 USING(a,b)
  RIGHT JOIN t3 USING(a,b)
  LEFT JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  17  -  - 37  - 37
  18  - 38 38  - 38
  19  -  - 39 39 39
}
do_execsql_test joinB-331 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11  -  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17  -  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-332 {
  SELECT a, c, d, e, f, g
  FROM t1
  RIGHT JOIN (t2 RIGHT JOIN t3 USING(a)) USING(a)
  LEFT JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  - 31 31  -
  12 32 32 32  -  -
  13  - 33 33 33  -
  15 35 35 35 35 35
  17 37  - 37  -  -
  18  - 38 38  -  -
}
do_execsql_test joinB-333 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-334 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  RIGHT JOIN t2 USING(a,b)
  RIGHT JOIN t3 USING(a,b)
  LEFT JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  - 37  - 37
  18 28  - 38 38  - 38
  19 29  -  - 39 39 39
}
do_execsql_test joinB-335 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11  -  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17  -  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-336 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL RIGHT JOIN t2
  NATURAL RIGHT JOIN t3
  NATURAL LEFT JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-337 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  19  -  - 19 19 19
}
do_execsql_test joinB-338 {
  SELECT a, c, d, e, f, g
  FROM t1
  RIGHT JOIN t2 USING(a,b)
  RIGHT JOIN t3 USING(a,b)
  RIGHT JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  19  -  - 39 39 39
}
do_execsql_test joinB-339 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11  -  - 11 11  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  19  -  - 19 19 19
}
do_execsql_test joinB-340 {
  SELECT a, c, d, e, f, g
  FROM t1
  RIGHT JOIN (t2 RIGHT JOIN t3 USING(a)) USING(a)
  RIGHT JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  - 31 31  -
  13  - 33 33 33  -
  15 35 35 35 35 35
}
do_execsql_test joinB-341 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-342 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  RIGHT JOIN t2 USING(a,b)
  RIGHT JOIN t3 USING(a,b)
  RIGHT JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  - 39 39 39
}
do_execsql_test joinB-343 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11  -  - 11 11  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-344 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL RIGHT JOIN t2
  NATURAL RIGHT JOIN t3
  NATURAL RIGHT JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-345 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-346 {
  SELECT a, c, d, e, f, g
  FROM t1
  RIGHT JOIN t2 USING(a,b)
  RIGHT JOIN t3 USING(a,b)
  FULL JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  17  -  - 37  - 37
  18  - 38 38  - 38
  19  -  - 39 39 39
}
do_execsql_test joinB-347 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11  -  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17  -  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-348 {
  SELECT a, c, d, e, f, g
  FROM t1
  RIGHT JOIN (t2 RIGHT JOIN t3 USING(a)) USING(a)
  FULL JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  - 31 31  -
  12 32 32 32  -  -
  13  - 33 33 33  -
  15 35 35 35 35 35
  17 37  - 37  -  -
  18  - 38 38  -  -
}
do_execsql_test joinB-349 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-350 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  RIGHT JOIN t2 USING(a,b)
  RIGHT JOIN t3 USING(a,b)
  FULL JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  - 37  - 37
  18 28  - 38 38  - 38
  19 29  -  - 39 39 39
}
do_execsql_test joinB-351 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11  -  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17  -  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-352 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL RIGHT JOIN t2
  NATURAL RIGHT JOIN t3
  NATURAL FULL JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-353 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  19  -  - 19 19 19
}
do_execsql_test joinB-354 {
  SELECT a, c, d, e, f, g
  FROM t1
  RIGHT JOIN t2 USING(a,b)
  FULL JOIN t3 USING(a,b)
  INNER JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  19  -  - 39 39 39
}
do_execsql_test joinB-355 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11  -  - 11 11  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  19  -  - 19 19 19
}
do_execsql_test joinB-356 {
  SELECT a, c, d, e, f, g
  FROM t1
  RIGHT JOIN (t2 FULL JOIN t3 USING(a)) USING(a)
  INNER JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  - 31 31  -
  13  - 33 33 33  -
  15 35 35 35 35 35
}
do_execsql_test joinB-357 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-358 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  RIGHT JOIN t2 USING(a,b)
  FULL JOIN t3 USING(a,b)
  INNER JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  - 39 39 39
}
do_execsql_test joinB-359 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11  -  - 11 11  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-360 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL RIGHT JOIN t2
  NATURAL FULL JOIN t3
  NATURAL INNER JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-361 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-362 {
  SELECT a, c, d, e, f, g
  FROM t1
  RIGHT JOIN t2 USING(a,b)
  FULL JOIN t3 USING(a,b)
  LEFT JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  17  -  - 37  - 37
  18  - 38 38  - 38
  19  -  - 39 39 39
}
do_execsql_test joinB-363 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
   -  -  -  -  -  -
  11  -  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17  -  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-364 {
  SELECT a, c, d, e, f, g
  FROM t1
  RIGHT JOIN (t2 FULL JOIN t3 USING(a)) USING(a)
  LEFT JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  - 31 31  -
  12 32 32 32  -  -
  13  - 33 33 33  -
  15 35 35 35 35 35
  17 37  - 37  -  -
  18  - 38 38  -  -
}
do_execsql_test joinB-365 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-366 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  RIGHT JOIN t2 USING(a,b)
  FULL JOIN t3 USING(a,b)
  LEFT JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  - 37  - 37
  18 28  - 38 38  - 38
  19 29  -  - 39 39 39
}
do_execsql_test joinB-367 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
   -  -  -  -  -  -
  11  -  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17  -  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-368 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL RIGHT JOIN t2
  NATURAL FULL JOIN t3
  NATURAL LEFT JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-369 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  19  -  - 19 19 19
}
do_execsql_test joinB-370 {
  SELECT a, c, d, e, f, g
  FROM t1
  RIGHT JOIN t2 USING(a,b)
  FULL JOIN t3 USING(a,b)
  RIGHT JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  19  -  - 39 39 39
}
do_execsql_test joinB-371 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11  -  - 11 11  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  19  -  - 19 19 19
}
do_execsql_test joinB-372 {
  SELECT a, c, d, e, f, g
  FROM t1
  RIGHT JOIN (t2 FULL JOIN t3 USING(a)) USING(a)
  RIGHT JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  - 31 31  -
  13  - 33 33 33  -
  15 35 35 35 35 35
}
do_execsql_test joinB-373 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-374 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  RIGHT JOIN t2 USING(a,b)
  FULL JOIN t3 USING(a,b)
  RIGHT JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  - 39 39 39
}
do_execsql_test joinB-375 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11  -  - 11 11  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-376 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL RIGHT JOIN t2
  NATURAL FULL JOIN t3
  NATURAL RIGHT JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-377 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-378 {
  SELECT a, c, d, e, f, g
  FROM t1
  RIGHT JOIN t2 USING(a,b)
  FULL JOIN t3 USING(a,b)
  FULL JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  17  -  - 37  - 37
  18  - 38 38  - 38
  19  -  - 39 39 39
}
do_execsql_test joinB-379 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
   -  -  -  -  -  -
  11  -  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17  -  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-380 {
  SELECT a, c, d, e, f, g
  FROM t1
  RIGHT JOIN (t2 FULL JOIN t3 USING(a)) USING(a)
  FULL JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  - 31 31  -
  12 32 32 32  -  -
  13  - 33 33 33  -
  15 35 35 35 35 35
  17 37  - 37  -  -
  18  - 38 38  -  -
}
do_execsql_test joinB-381 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-382 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  RIGHT JOIN t2 USING(a,b)
  FULL JOIN t3 USING(a,b)
  FULL JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  - 37  - 37
  18 28  - 38 38  - 38
  19 29  -  - 39 39 39
}
do_execsql_test joinB-383 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  RIGHT JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
   -  -  -  -  -  -
  11  -  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17  -  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-384 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL RIGHT JOIN t2
  NATURAL FULL JOIN t3
  NATURAL FULL JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-385 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
}
do_execsql_test joinB-386 {
  SELECT a, c, d, e, f, g
  FROM t1
  FULL JOIN t2 USING(a,b)
  INNER JOIN t3 USING(a,b)
  INNER JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
}
do_execsql_test joinB-387 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  13  - 13 13 13  -
  15 15 15 15 15 15
}
do_execsql_test joinB-388 {
  SELECT a, c, d, e, f, g
  FROM t1
  FULL JOIN (t2 INNER JOIN t3 USING(a)) USING(a)
  INNER JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  -  - 31  -
  13  - 33 33 33  -
  15 35 35 35 35 35
}
do_execsql_test joinB-389 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  -  - 19
}
do_execsql_test joinB-390 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  FULL JOIN t2 USING(a,b)
  INNER JOIN t3 USING(a,b)
  INNER JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  -  -  - 39
}
do_execsql_test joinB-391 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  -  - 19
}
do_execsql_test joinB-392 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL FULL JOIN t2
  NATURAL INNER JOIN t3
  NATURAL INNER JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-393 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
}
do_execsql_test joinB-394 {
  SELECT a, c, d, e, f, g
  FROM t1
  FULL JOIN t2 USING(a,b)
  INNER JOIN t3 USING(a,b)
  LEFT JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  17 37  - 37  - 37
  18  - 38 38  - 38
}
do_execsql_test joinB-395 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
}
do_execsql_test joinB-396 {
  SELECT a, c, d, e, f, g
  FROM t1
  FULL JOIN (t2 INNER JOIN t3 USING(a)) USING(a)
  LEFT JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  -  - 31  -
  12 32 32 32  -  -
  13  - 33 33 33  -
  15 35 35 35 35 35
  17 37  -  -  -  -
  18  - 38 38  -  -
}
do_execsql_test joinB-397 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  -  -  - 19
}
do_execsql_test joinB-398 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  FULL JOIN t2 USING(a,b)
  INNER JOIN t3 USING(a,b)
  LEFT JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27 37  - 37  - 37
  18 28  - 38 38  - 38
  19 29  -  -  -  - 39
}
do_execsql_test joinB-399 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  -  -  - 19
}
do_execsql_test joinB-400 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL FULL JOIN t2
  NATURAL INNER JOIN t3
  NATURAL LEFT JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-401 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  19  -  -  - 19 19
}
do_execsql_test joinB-402 {
  SELECT a, c, d, e, f, g
  FROM t1
  FULL JOIN t2 USING(a,b)
  INNER JOIN t3 USING(a,b)
  RIGHT JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  19  -  -  - 39 39
}
do_execsql_test joinB-403 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  19  -  -  - 19 19
}
do_execsql_test joinB-404 {
  SELECT a, c, d, e, f, g
  FROM t1
  FULL JOIN (t2 INNER JOIN t3 USING(a)) USING(a)
  RIGHT JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  -  - 31  -
  13  - 33 33 33  -
  15 35 35 35 35 35
}
do_execsql_test joinB-405 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-406 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  FULL JOIN t2 USING(a,b)
  INNER JOIN t3 USING(a,b)
  RIGHT JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  -  - 39 39
}
do_execsql_test joinB-407 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-408 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL FULL JOIN t2
  NATURAL INNER JOIN t3
  NATURAL RIGHT JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-409 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-410 {
  SELECT a, c, d, e, f, g
  FROM t1
  FULL JOIN t2 USING(a,b)
  INNER JOIN t3 USING(a,b)
  FULL JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  17 37  - 37  - 37
  18  - 38 38  - 38
  19  -  -  - 39 39
}
do_execsql_test joinB-411 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-412 {
  SELECT a, c, d, e, f, g
  FROM t1
  FULL JOIN (t2 INNER JOIN t3 USING(a)) USING(a)
  FULL JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  -  - 31  -
  12 32 32 32  -  -
  13  - 33 33 33  -
  15 35 35 35 35 35
  17 37  -  -  -  -
  18  - 38 38  -  -
}
do_execsql_test joinB-413 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-414 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  FULL JOIN t2 USING(a,b)
  INNER JOIN t3 USING(a,b)
  FULL JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27 37  - 37  - 37
  18 28  - 38 38  - 38
  19 29  -  -  - 39 39
}
do_execsql_test joinB-415 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  INNER JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-416 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL FULL JOIN t2
  NATURAL INNER JOIN t3
  NATURAL FULL JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-417 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
}
do_execsql_test joinB-418 {
  SELECT a, c, d, e, f, g
  FROM t1
  FULL JOIN t2 USING(a,b)
  LEFT JOIN t3 USING(a,b)
  INNER JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
}
do_execsql_test joinB-419 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  13  - 13 13 13  -
  15 15 15 15 15 15
}
do_execsql_test joinB-420 {
  SELECT a, c, d, e, f, g
  FROM t1
  FULL JOIN (t2 LEFT JOIN t3 USING(a)) USING(a)
  INNER JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  -  - 31  -
  13  - 33 33 33  -
  15 35 35 35 35 35
}
do_execsql_test joinB-421 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  -  - 19
}
do_execsql_test joinB-422 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  FULL JOIN t2 USING(a,b)
  LEFT JOIN t3 USING(a,b)
  INNER JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  -  -  - 39
}
do_execsql_test joinB-423 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  -  - 19
}
do_execsql_test joinB-424 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL FULL JOIN t2
  NATURAL LEFT JOIN t3
  NATURAL INNER JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-425 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
}
do_execsql_test joinB-426 {
  SELECT a, c, d, e, f, g
  FROM t1
  FULL JOIN t2 USING(a,b)
  LEFT JOIN t3 USING(a,b)
  LEFT JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  17 37  - 37  - 37
  18  - 38 38  - 38
}
do_execsql_test joinB-427 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
}
do_execsql_test joinB-428 {
  SELECT a, c, d, e, f, g
  FROM t1
  FULL JOIN (t2 LEFT JOIN t3 USING(a)) USING(a)
  LEFT JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  -  - 31  -
  12 32 32 32  -  -
  13  - 33 33 33  -
  15 35 35 35 35 35
  17 37  -  -  -  -
  18  - 38 38  -  -
}
do_execsql_test joinB-429 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  -  -  - 19
}
do_execsql_test joinB-430 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  FULL JOIN t2 USING(a,b)
  LEFT JOIN t3 USING(a,b)
  LEFT JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27 37  - 37  - 37
  18 28  - 38 38  - 38
  19 29  -  -  -  - 39
}
do_execsql_test joinB-431 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  -  -  - 19
}
do_execsql_test joinB-432 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL FULL JOIN t2
  NATURAL LEFT JOIN t3
  NATURAL LEFT JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-433 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  19  -  -  - 19 19
}
do_execsql_test joinB-434 {
  SELECT a, c, d, e, f, g
  FROM t1
  FULL JOIN t2 USING(a,b)
  LEFT JOIN t3 USING(a,b)
  RIGHT JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  19  -  -  - 39 39
}
do_execsql_test joinB-435 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  19  -  -  - 19 19
}
do_execsql_test joinB-436 {
  SELECT a, c, d, e, f, g
  FROM t1
  FULL JOIN (t2 LEFT JOIN t3 USING(a)) USING(a)
  RIGHT JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  -  - 31  -
  13  - 33 33 33  -
  15 35 35 35 35 35
}
do_execsql_test joinB-437 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-438 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  FULL JOIN t2 USING(a,b)
  LEFT JOIN t3 USING(a,b)
  RIGHT JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  -  - 39 39
}
do_execsql_test joinB-439 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-440 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL FULL JOIN t2
  NATURAL LEFT JOIN t3
  NATURAL RIGHT JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-441 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-442 {
  SELECT a, c, d, e, f, g
  FROM t1
  FULL JOIN t2 USING(a,b)
  LEFT JOIN t3 USING(a,b)
  FULL JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  17 37  - 37  - 37
  18  - 38 38  - 38
  19  -  -  - 39 39
}
do_execsql_test joinB-443 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-444 {
  SELECT a, c, d, e, f, g
  FROM t1
  FULL JOIN (t2 LEFT JOIN t3 USING(a)) USING(a)
  FULL JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  -  - 31  -
  12 32 32 32  -  -
  13  - 33 33 33  -
  15 35 35 35 35 35
  17 37  -  -  -  -
  18  - 38 38  -  -
}
do_execsql_test joinB-445 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-446 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  FULL JOIN t2 USING(a,b)
  LEFT JOIN t3 USING(a,b)
  FULL JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27 37  - 37  - 37
  18 28  - 38 38  - 38
  19 29  -  -  - 39 39
}
do_execsql_test joinB-447 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  LEFT JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  -  - 19 19
}
do_execsql_test joinB-448 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL FULL JOIN t2
  NATURAL LEFT JOIN t3
  NATURAL FULL JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-449 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  19  -  - 19 19 19
}
do_execsql_test joinB-450 {
  SELECT a, c, d, e, f, g
  FROM t1
  FULL JOIN t2 USING(a,b)
  RIGHT JOIN t3 USING(a,b)
  INNER JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  19  -  - 39 39 39
}
do_execsql_test joinB-451 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  19  -  - 19 19 19
}
do_execsql_test joinB-452 {
  SELECT a, c, d, e, f, g
  FROM t1
  FULL JOIN (t2 RIGHT JOIN t3 USING(a)) USING(a)
  INNER JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  - 31 31  -
  13  - 33 33 33  -
  15 35 35 35 35 35
}
do_execsql_test joinB-453 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-454 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  FULL JOIN t2 USING(a,b)
  RIGHT JOIN t3 USING(a,b)
  INNER JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  - 39 39 39
}
do_execsql_test joinB-455 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-456 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL FULL JOIN t2
  NATURAL RIGHT JOIN t3
  NATURAL INNER JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-457 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-458 {
  SELECT a, c, d, e, f, g
  FROM t1
  FULL JOIN t2 USING(a,b)
  RIGHT JOIN t3 USING(a,b)
  LEFT JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  17 37  - 37  - 37
  18  - 38 38  - 38
  19  -  - 39 39 39
}
do_execsql_test joinB-459 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-460 {
  SELECT a, c, d, e, f, g
  FROM t1
  FULL JOIN (t2 RIGHT JOIN t3 USING(a)) USING(a)
  LEFT JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  - 31 31  -
  12 32 32 32  -  -
  13  - 33 33 33  -
  15 35 35 35 35 35
  17 37  - 37  -  -
  18  - 38 38  -  -
}
do_execsql_test joinB-461 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-462 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  FULL JOIN t2 USING(a,b)
  RIGHT JOIN t3 USING(a,b)
  LEFT JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27 37  - 37  - 37
  18 28  - 38 38  - 38
  19 29  -  - 39 39 39
}
do_execsql_test joinB-463 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-464 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL FULL JOIN t2
  NATURAL RIGHT JOIN t3
  NATURAL LEFT JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-465 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  19  -  - 19 19 19
}
do_execsql_test joinB-466 {
  SELECT a, c, d, e, f, g
  FROM t1
  FULL JOIN t2 USING(a,b)
  RIGHT JOIN t3 USING(a,b)
  RIGHT JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  19  -  - 39 39 39
}
do_execsql_test joinB-467 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  19  -  - 19 19 19
}
do_execsql_test joinB-468 {
  SELECT a, c, d, e, f, g
  FROM t1
  FULL JOIN (t2 RIGHT JOIN t3 USING(a)) USING(a)
  RIGHT JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  - 31 31  -
  13  - 33 33 33  -
  15 35 35 35 35 35
}
do_execsql_test joinB-469 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-470 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  FULL JOIN t2 USING(a,b)
  RIGHT JOIN t3 USING(a,b)
  RIGHT JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  - 39 39 39
}
do_execsql_test joinB-471 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-472 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL FULL JOIN t2
  NATURAL RIGHT JOIN t3
  NATURAL RIGHT JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-473 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-474 {
  SELECT a, c, d, e, f, g
  FROM t1
  FULL JOIN t2 USING(a,b)
  RIGHT JOIN t3 USING(a,b)
  FULL JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  17 37  - 37  - 37
  18  - 38 38  - 38
  19  -  - 39 39 39
}
do_execsql_test joinB-475 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-476 {
  SELECT a, c, d, e, f, g
  FROM t1
  FULL JOIN (t2 RIGHT JOIN t3 USING(a)) USING(a)
  FULL JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  - 31 31  -
  12 32 32 32  -  -
  13  - 33 33 33  -
  15 35 35 35 35 35
  17 37  - 37  -  -
  18  - 38 38  -  -
}
do_execsql_test joinB-477 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-478 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  FULL JOIN t2 USING(a,b)
  RIGHT JOIN t3 USING(a,b)
  FULL JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27 37  - 37  - 37
  18 28  - 38 38  - 38
  19 29  -  - 39 39 39
}
do_execsql_test joinB-479 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  RIGHT JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-480 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL FULL JOIN t2
  NATURAL RIGHT JOIN t3
  NATURAL FULL JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-481 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  19  -  - 19 19 19
}
do_execsql_test joinB-482 {
  SELECT a, c, d, e, f, g
  FROM t1
  FULL JOIN t2 USING(a,b)
  FULL JOIN t3 USING(a,b)
  INNER JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  19  -  - 39 39 39
}
do_execsql_test joinB-483 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  19  -  - 19 19 19
}
do_execsql_test joinB-484 {
  SELECT a, c, d, e, f, g
  FROM t1
  FULL JOIN (t2 FULL JOIN t3 USING(a)) USING(a)
  INNER JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  - 31 31  -
  13  - 33 33 33  -
  15 35 35 35 35 35
}
do_execsql_test joinB-485 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-486 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  FULL JOIN t2 USING(a,b)
  FULL JOIN t3 USING(a,b)
  INNER JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  - 39 39 39
}
do_execsql_test joinB-487 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  INNER JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-488 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL FULL JOIN t2
  NATURAL FULL JOIN t3
  NATURAL INNER JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-489 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-490 {
  SELECT a, c, d, e, f, g
  FROM t1
  FULL JOIN t2 USING(a,b)
  FULL JOIN t3 USING(a,b)
  LEFT JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  17 37  - 37  - 37
  18  - 38 38  - 38
  19  -  - 39 39 39
}
do_execsql_test joinB-491 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-492 {
  SELECT a, c, d, e, f, g
  FROM t1
  FULL JOIN (t2 FULL JOIN t3 USING(a)) USING(a)
  LEFT JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  - 31 31  -
  12 32 32 32  -  -
  13  - 33 33 33  -
  15 35 35 35 35 35
  17 37  - 37  -  -
  18  - 38 38  -  -
}
do_execsql_test joinB-493 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-494 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  FULL JOIN t2 USING(a,b)
  FULL JOIN t3 USING(a,b)
  LEFT JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27 37  - 37  - 37
  18 28  - 38 38  - 38
  19 29  -  - 39 39 39
}
do_execsql_test joinB-495 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  LEFT JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-496 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL FULL JOIN t2
  NATURAL FULL JOIN t3
  NATURAL LEFT JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-497 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  19  -  - 19 19 19
}
do_execsql_test joinB-498 {
  SELECT a, c, d, e, f, g
  FROM t1
  FULL JOIN t2 USING(a,b)
  FULL JOIN t3 USING(a,b)
  RIGHT JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  19  -  - 39 39 39
}
do_execsql_test joinB-499 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  19  -  - 19 19 19
}
do_execsql_test joinB-500 {
  SELECT a, c, d, e, f, g
  FROM t1
  FULL JOIN (t2 FULL JOIN t3 USING(a)) USING(a)
  RIGHT JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  - 31 31  -
  13  - 33 33 33  -
  15 35 35 35 35 35
}
do_execsql_test joinB-501 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-502 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  FULL JOIN t2 USING(a,b)
  FULL JOIN t3 USING(a,b)
  RIGHT JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27  -  -  -  - 37
  18 28  -  -  -  - 38
  19 29  -  - 39 39 39
}
do_execsql_test joinB-503 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  RIGHT JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17  -  -  -  - 17
  18  -  -  -  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-504 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL FULL JOIN t2
  NATURAL FULL JOIN t3
  NATURAL RIGHT JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
do_execsql_test joinB-505 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  INNER JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-506 {
  SELECT a, c, d, e, f, g
  FROM t1
  FULL JOIN t2 USING(a,b)
  FULL JOIN t3 USING(a,b)
  FULL JOIN t4 USING(a,b)
  INNER JOIN t5 USING(a,b)
  WHERE a<>13
  ORDER BY 1 NULLS FIRST;
} {
  15 35 35 35 35 35
  17 37  - 37  - 37
  18  - 38 38  - 38
  19  -  - 39 39 39
}
do_execsql_test joinB-507 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  LEFT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-508 {
  SELECT a, c, d, e, f, g
  FROM t1
  FULL JOIN (t2 FULL JOIN t3 USING(a)) USING(a)
  FULL JOIN (t4 LEFT JOIN t5 USING(a)) USING(a)
  WHERE a<=18
  ORDER BY 1 NULLS FIRST;
} {
  11 31  - 31 31  -
  12 32 32 32  -  -
  13  - 33 33 33  -
  15 35 35 35 35 35
  17 37  - 37  -  -
  18  - 38 38  -  -
}
do_execsql_test joinB-509 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  RIGHT JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-510 {
  SELECT a, b, c, d, e, f, g
  FROM t1
  FULL JOIN t2 USING(a,b)
  FULL JOIN t3 USING(a,b)
  FULL JOIN t4 USING(a,b)
  RIGHT JOIN t5 USING(a,b)
  WHERE d<>33 OR d IS NULL
  ORDER BY 1 NULLS FIRST;
} {
  15 25 35 35 35 35 35
  17 27 37  - 37  - 37
  18 28  - 38 38  - 38
  19 29  -  - 39 39 39
}
do_execsql_test joinB-511 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1
  FULL JOIN t2 USING(a)
  FULL JOIN t3 USING(a)
  FULL JOIN t4 USING(a)
  FULL JOIN t5 USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19
}
do_execsql_test joinB-512 {
  SELECT b, c, d, e, f, g
  FROM t1
  NATURAL FULL JOIN t2
  NATURAL FULL JOIN t3
  NATURAL FULL JOIN t4
  NATURAL FULL JOIN t5
  WHERE b BETWEEN 12 AND 17
  ORDER BY 1 NULLS FIRST;
} {
}
finish_test

##############################################################################
# Here is the original TCL script that generated the psql input file:
#
# 
# puts "
# \\pset border off
# \\pset tuples_only on
# \\pset null -
# 
# DROP TABLE IF EXISTS t1;
# DROP TABLE IF EXISTS t2;
# DROP TABLE IF EXISTS t3;
# DROP TABLE IF EXISTS t4;
# DROP TABLE IF EXISTS t5;
# CREATE TABLE t1(a INT, b INT, c INT);
# CREATE TABLE t2(a INT, b INT, d INT);
# CREATE TABLE t3(a INT, b INT, e INT);
# CREATE TABLE t4(a INT, b INT, f INT);
# CREATE TABLE t5(a INT, b INT, g INT);
# INSERT INTO t1 VALUES(11,21,31),(12,22,32),(15,25,35),(17,27,37);
# INSERT INTO t2 VALUES(12,22,32),(13,23,33),(15,25,35),(18,28,38),(NULL,NULL,36);
# INSERT INTO t4 VALUES(11,21,31),(13,23,33),(15,25,35),(19,29,39);
# INSERT INTO t3 SELECT * FROM t1 UNION SELECT * FROM t2 UNION SELECT * FROM t4;
# INSERT INTO t5 SELECT * FROM t3 WHERE a>=15;
# "
# 
# proc echo {prefix txt} {
#   regsub -all {\n} $txt \n$prefix txt
#   puts "$prefix$txt"
# }
# 
# set n 0
# set k 0
# foreach j1 {INNER LEFT RIGHT FULL} {
#   foreach j2 {INNER LEFT RIGHT FULL} {
#     foreach j3 {INNER LEFT RIGHT FULL} {
#       foreach j4 {INNER LEFT RIGHT FULL} {
# 
# incr n
# incr k
# set q1 ""
# append q1 "SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a\n"
# append q1 "  FROM t1\n"
# append q1 "       $j1 JOIN t2 USING(a)\n"
# append q1 "       $j2 JOIN t3 USING(a)\n"
# append q1 "       $j3 JOIN t4 USING(a)\n"
# append q1 "       $j4 JOIN t5 USING(a)\n"
# append q1 " ORDER BY 1 NULLS FIRST;"
# 
# echo "\\qecho " "do_execsql_test joinB-$n \{"
# echo "\\qecho X  " $q1
# echo "\\qecho " "\} \{"
# puts $q1
# echo "\\qecho " "\}"
# 
# switch [expr {$k%4}] {
#   0 {
#     set q2 ""
#     append q2 "SELECT b, c, d, e, f, g\n"
#     append q2 "  FROM t1\n"
#     append q2 "       NATURAL $j1 JOIN t2\n"
#     append q2 "       NATURAL $j2 JOIN t3\n"
#     append q2 "       NATURAL $j3 JOIN t4\n"
#     append q2 "       NATURAL $j4 JOIN t5\n"
#     append q2 " WHERE b BETWEEN 12 AND 17\n"
#     append q2 " ORDER BY 1 NULLS FIRST;"
#     incr n
#     echo "\\qecho " "do_execsql_test joinB-$n \{"
#     echo "\\qecho X  " $q2
#     echo "\\qecho " "\} \{"
#     puts $q2
#     echo "\\qecho " "\}"
#   }
#   1 {
#     set q2 ""
#     append q2 "SELECT a, c, d, e, f, g\n"
#     append q2 "  FROM t1\n"
#     append q2 "       $j1 JOIN t2 USING(a,b)\n"
#     append q2 "       $j2 JOIN t3 USING(a,b)\n"
#     append q2 "       $j3 JOIN t4 USING(a,b)\n"
#     append q2 "       $j4 JOIN t5 USING(a,b)\n"
#     append q2 " WHERE a<>13\n"
#     append q2 " ORDER BY 1 NULLS FIRST;"
#     incr n
#     echo "\\qecho " "do_execsql_test joinB-$n \{"
#     echo "\\qecho X  " $q2
#     echo "\\qecho " "\} \{"
#     puts $q2
#     echo "\\qecho " "\}"
#   }
#   2 {
#     set q2 ""
#     append q2 "SELECT a, c, d, e, f, g\n"
#     append q2 "  FROM t1\n"
#     append q2 "       $j1 JOIN (t2 $j2 JOIN t3 USING(a)) USING(a)\n"
#     append q2 "       $j3 JOIN (t4 $j4 JOIN t5 USING(a)) USING(a)\n"
#     append q2 " WHERE a<=18\n"
#     append q2 " ORDER BY 1 NULLS FIRST;"
#     incr n
#     echo "\\qecho " "do_execsql_test joinB-$n \{"
#     echo "\\qecho X  " $q2
#     echo "\\qecho " "\} \{"
#     puts $q2
#     echo "\\qecho " "\}"
#   }
#   3 {
#     set q2 ""
#     append q2 "SELECT a, b, c, d, e, f, g\n"
#     append q2 "  FROM t1\n"
#     append q2 "       $j1 JOIN t2 USING(a,b)\n"
#     append q2 "       $j2 JOIN t3 USING(a,b)\n"
#     append q2 "       $j3 JOIN t4 USING(a,b)\n"
#     append q2 "       $j4 JOIN t5 USING(a,b)\n"
#     append q2 " WHERE d<>33 OR d IS NULL\n"
#     append q2 " ORDER BY 1 NULLS FIRST;"
#     incr n
#     echo "\\qecho " "do_execsql_test joinB-$n \{"
#     echo "\\qecho X  " $q2
#     echo "\\qecho " "\} \{"
#     puts $q2
#     echo "\\qecho " "\}"
#   }
# }
# 
#       }
#     }
#   }
# }
##############################################################################

Added test/joinC.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
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
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
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
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
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
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
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
1984
1985
1986
1987
1988
1989
1990
1991
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
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
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
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
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
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
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
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
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
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
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
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
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
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
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
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
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
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
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
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
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
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
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
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
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
4360
4361
4362
4363
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
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
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
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022-04-19
#
# 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 tests for JOINs.
#
# The test case output is all generated by PostgreSQL 14.  This test module
# was created as follows:
#
#   1.   Run a TCL script (included at the bottom of this file) that
#        generates an input script for "psql" that will run man
#        diverse tests on joins.
#
#   2.   Run the script from step (1) through psql and collect the
#        output.
#
#   3.   Make a few minor global search-and-replace operations to convert
#        the psql output into a form suitable for this test module.
#
#   4.   Add this header, and the script content at the footer.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
db nullvalue -
db eval {
  DROP TABLE IF EXISTS t1;
  DROP TABLE IF EXISTS t2;
  DROP TABLE IF EXISTS t3;
  DROP TABLE IF EXISTS t4;
  DROP TABLE IF EXISTS t5;
  CREATE TABLE t1(a INT, b INT, c INT);
  CREATE TABLE t2(a INT, b INT, d INT);
  CREATE TABLE t3(a INT, b INT, e INT);
  CREATE TABLE t4(a INT, b INT, f INT);
  CREATE TABLE t5(a INT, b INT, g INT);
  INSERT INTO t1 VALUES(11,21,31),(12,22,32),(15,25,35),(17,27,37);
  INSERT INTO t2 VALUES(12,22,32),(13,23,33),(15,25,35),(18,28,38),
                       (NULL,NULL,36);
  INSERT INTO t4 VALUES(11,21,31),(13,23,33),(15,25,35),(19,29,39);
  INSERT INTO t3 SELECT * FROM t1 UNION SELECT * FROM t2 UNION SELECT * FROM t4;
  INSERT INTO t5 SELECT * FROM t3 WHERE a>=15;
}
do_execsql_test joinC-1 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 INNER JOIN (
  t3 INNER JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15

}
do_execsql_test joinC-2 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 INNER JOIN (
  t3 INNER JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15

}
do_execsql_test joinC-3 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 INNER JOIN (
  t3 INNER JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15

}
do_execsql_test joinC-4 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 INNER JOIN (
  t3 INNER JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15

}
do_execsql_test joinC-5 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 INNER JOIN (
  t3 LEFT JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12 12  -  -
  15 15 15 15 15 15

}
do_execsql_test joinC-6 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 INNER JOIN (
  t3 LEFT JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12 12  -  -
  15 15 15 15 15 15

}
do_execsql_test joinC-7 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 INNER JOIN (
  t3 LEFT JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12 12  -  -
  15 15 15 15 15 15

}
do_execsql_test joinC-8 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 INNER JOIN (
  t3 LEFT JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12 12  -  -
  15 15 15 15 15 15

}
do_execsql_test joinC-9 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 INNER JOIN (
  t3 RIGHT JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15

}
do_execsql_test joinC-10 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 INNER JOIN (
  t3 RIGHT JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15

}
do_execsql_test joinC-11 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 INNER JOIN (
  t3 RIGHT JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15

}
do_execsql_test joinC-12 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 INNER JOIN (
  t3 RIGHT JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15

}
do_execsql_test joinC-13 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 INNER JOIN (
  t3 FULL JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12 12  -  -
  15 15 15 15 15 15

}
do_execsql_test joinC-14 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 INNER JOIN (
  t3 FULL JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12 12  -  -
  15 15 15 15 15 15

}
do_execsql_test joinC-15 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 INNER JOIN (
  t3 FULL JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12 12  -  -
  15 15 15 15 15 15

}
do_execsql_test joinC-16 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 INNER JOIN (
  t3 FULL JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12 12  -  -
  15 15 15 15 15 15

}
do_execsql_test joinC-17 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 LEFT JOIN (
  t3 INNER JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12  -  -  -
  15 15 15 15 15 15

}
do_execsql_test joinC-18 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 LEFT JOIN (
  t3 INNER JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12  -  -  -
  15 15 15 15 15 15

}
do_execsql_test joinC-19 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 LEFT JOIN (
  t3 INNER JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12  -  -  -
  15 15 15 15 15 15

}
do_execsql_test joinC-20 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 LEFT JOIN (
  t3 INNER JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12  -  -  -
  15 15 15 15 15 15

}
do_execsql_test joinC-21 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 LEFT JOIN (
  t3 LEFT JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12 12  -  -
  15 15 15 15 15 15

}
do_execsql_test joinC-22 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 LEFT JOIN (
  t3 LEFT JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12 12  -  -
  15 15 15 15 15 15

}
do_execsql_test joinC-23 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 LEFT JOIN (
  t3 LEFT JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12 12  -  -
  15 15 15 15 15 15

}
do_execsql_test joinC-24 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 LEFT JOIN (
  t3 LEFT JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12 12  -  -
  15 15 15 15 15 15

}
do_execsql_test joinC-25 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 LEFT JOIN (
  t3 RIGHT JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12  -  -  -
  15 15 15 15 15 15

}
do_execsql_test joinC-26 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 LEFT JOIN (
  t3 RIGHT JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12  -  -  -
  15 15 15 15 15 15

}
do_execsql_test joinC-27 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 LEFT JOIN (
  t3 RIGHT JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12  -  -  -
  15 15 15 15 15 15

}
do_execsql_test joinC-28 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 LEFT JOIN (
  t3 RIGHT JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12  -  -  -
  15 15 15 15 15 15

}
do_execsql_test joinC-29 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 LEFT JOIN (
  t3 FULL JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12 12  -  -
  15 15 15 15 15 15

}
do_execsql_test joinC-30 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 LEFT JOIN (
  t3 FULL JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12 12  -  -
  15 15 15 15 15 15

}
do_execsql_test joinC-31 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 LEFT JOIN (
  t3 FULL JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12 12  -  -
  15 15 15 15 15 15

}
do_execsql_test joinC-32 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 LEFT JOIN (
  t3 FULL JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12 12  -  -
  15 15 15 15 15 15

}
do_execsql_test joinC-33 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 RIGHT JOIN (
  t3 INNER JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15

}
do_execsql_test joinC-34 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 RIGHT JOIN (
  t3 INNER JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  15 15 15 15 15 15

}
do_execsql_test joinC-35 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 RIGHT JOIN (
  t3 INNER JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17

}
do_execsql_test joinC-36 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 RIGHT JOIN (
  t3 INNER JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  15 15 15 15 15 15
  17 17  - 17  - 17

}
do_execsql_test joinC-37 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 RIGHT JOIN (
  t3 LEFT JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11  -  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  -  -

}
do_execsql_test joinC-38 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 RIGHT JOIN (
  t3 LEFT JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  -  -

}
do_execsql_test joinC-39 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 RIGHT JOIN (
  t3 LEFT JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11  -  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17

}
do_execsql_test joinC-40 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 RIGHT JOIN (
  t3 LEFT JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17

}
do_execsql_test joinC-41 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 RIGHT JOIN (
  t3 RIGHT JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15

}
do_execsql_test joinC-42 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 RIGHT JOIN (
  t3 RIGHT JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  15 15 15 15 15 15

}
do_execsql_test joinC-43 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 RIGHT JOIN (
  t3 RIGHT JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17

}
do_execsql_test joinC-44 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 RIGHT JOIN (
  t3 RIGHT JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  15 15 15 15 15 15
  17 17  - 17  - 17

}
do_execsql_test joinC-45 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 RIGHT JOIN (
  t3 FULL JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11  -  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  -  -

}
do_execsql_test joinC-46 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 RIGHT JOIN (
  t3 FULL JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  -  -

}
do_execsql_test joinC-47 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 RIGHT JOIN (
  t3 FULL JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11  -  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17

}
do_execsql_test joinC-48 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 RIGHT JOIN (
  t3 FULL JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17

}
do_execsql_test joinC-49 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 FULL JOIN (
  t3 INNER JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12  -  -  -
  15 15 15 15 15 15

}
do_execsql_test joinC-50 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 FULL JOIN (
  t3 INNER JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12  -  -  -
  15 15 15 15 15 15

}
do_execsql_test joinC-51 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 FULL JOIN (
  t3 INNER JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12  -  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17

}
do_execsql_test joinC-52 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 FULL JOIN (
  t3 INNER JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12  -  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17

}
do_execsql_test joinC-53 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 FULL JOIN (
  t3 LEFT JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11  -  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  -  -

}
do_execsql_test joinC-54 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 FULL JOIN (
  t3 LEFT JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  -  -

}
do_execsql_test joinC-55 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 FULL JOIN (
  t3 LEFT JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11  -  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17

}
do_execsql_test joinC-56 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 FULL JOIN (
  t3 LEFT JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17

}
do_execsql_test joinC-57 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 FULL JOIN (
  t3 RIGHT JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12  -  -  -
  15 15 15 15 15 15

}
do_execsql_test joinC-58 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 FULL JOIN (
  t3 RIGHT JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12  -  -  -
  15 15 15 15 15 15

}
do_execsql_test joinC-59 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 FULL JOIN (
  t3 RIGHT JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12  -  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17

}
do_execsql_test joinC-60 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 FULL JOIN (
  t3 RIGHT JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12  -  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17

}
do_execsql_test joinC-61 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 FULL JOIN (
  t3 FULL JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11  -  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  -  -

}
do_execsql_test joinC-62 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 FULL JOIN (
  t3 FULL JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  -  -

}
do_execsql_test joinC-63 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 FULL JOIN (
  t3 FULL JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11  -  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17

}
do_execsql_test joinC-64 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 INNER JOIN (
  t2 FULL JOIN (
  t3 FULL JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17

}
do_execsql_test joinC-65 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 INNER JOIN (
  t3 INNER JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12  -  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-66 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 INNER JOIN (
  t3 INNER JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12  -  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-67 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 INNER JOIN (
  t3 INNER JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12  -  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-68 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 INNER JOIN (
  t3 INNER JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12  -  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-69 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 INNER JOIN (
  t3 LEFT JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-70 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 INNER JOIN (
  t3 LEFT JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-71 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 INNER JOIN (
  t3 LEFT JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-72 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 INNER JOIN (
  t3 LEFT JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-73 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 INNER JOIN (
  t3 RIGHT JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12  -  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-74 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 INNER JOIN (
  t3 RIGHT JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12  -  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-75 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 INNER JOIN (
  t3 RIGHT JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12  -  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-76 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 INNER JOIN (
  t3 RIGHT JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12  -  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-77 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 INNER JOIN (
  t3 FULL JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-78 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 INNER JOIN (
  t3 FULL JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-79 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 INNER JOIN (
  t3 FULL JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-80 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 INNER JOIN (
  t3 FULL JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-81 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 LEFT JOIN (
  t3 INNER JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-82 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 LEFT JOIN (
  t3 INNER JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-83 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 LEFT JOIN (
  t3 INNER JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-84 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 LEFT JOIN (
  t3 INNER JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-85 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 LEFT JOIN (
  t3 LEFT JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-86 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 LEFT JOIN (
  t3 LEFT JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-87 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 LEFT JOIN (
  t3 LEFT JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-88 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 LEFT JOIN (
  t3 LEFT JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-89 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 LEFT JOIN (
  t3 RIGHT JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-90 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 LEFT JOIN (
  t3 RIGHT JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-91 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 LEFT JOIN (
  t3 RIGHT JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-92 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 LEFT JOIN (
  t3 RIGHT JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-93 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 LEFT JOIN (
  t3 FULL JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-94 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 LEFT JOIN (
  t3 FULL JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-95 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 LEFT JOIN (
  t3 FULL JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-96 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 LEFT JOIN (
  t3 FULL JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-97 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 RIGHT JOIN (
  t3 INNER JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12  -  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-98 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 RIGHT JOIN (
  t3 INNER JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12  -  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-99 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 RIGHT JOIN (
  t3 INNER JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12  -  -  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17

}
do_execsql_test joinC-100 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 RIGHT JOIN (
  t3 INNER JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12  -  -  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17

}
do_execsql_test joinC-101 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 RIGHT JOIN (
  t3 LEFT JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11  -  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  -  -

}
do_execsql_test joinC-102 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 RIGHT JOIN (
  t3 LEFT JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  -  -

}
do_execsql_test joinC-103 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 RIGHT JOIN (
  t3 LEFT JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11  -  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17

}
do_execsql_test joinC-104 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 RIGHT JOIN (
  t3 LEFT JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17

}
do_execsql_test joinC-105 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 RIGHT JOIN (
  t3 RIGHT JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12  -  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-106 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 RIGHT JOIN (
  t3 RIGHT JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12  -  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-107 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 RIGHT JOIN (
  t3 RIGHT JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12  -  -  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17

}
do_execsql_test joinC-108 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 RIGHT JOIN (
  t3 RIGHT JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12  -  -  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17

}
do_execsql_test joinC-109 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 RIGHT JOIN (
  t3 FULL JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11  -  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  -  -

}
do_execsql_test joinC-110 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 RIGHT JOIN (
  t3 FULL JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  -  -

}
do_execsql_test joinC-111 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 RIGHT JOIN (
  t3 FULL JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11  -  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17

}
do_execsql_test joinC-112 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 RIGHT JOIN (
  t3 FULL JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17

}
do_execsql_test joinC-113 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 FULL JOIN (
  t3 INNER JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-114 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 FULL JOIN (
  t3 INNER JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-115 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 FULL JOIN (
  t3 INNER JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12  -  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17

}
do_execsql_test joinC-116 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 FULL JOIN (
  t3 INNER JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12  -  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17

}
do_execsql_test joinC-117 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 FULL JOIN (
  t3 LEFT JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11  -  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  -  -

}
do_execsql_test joinC-118 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 FULL JOIN (
  t3 LEFT JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  -  -

}
do_execsql_test joinC-119 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 FULL JOIN (
  t3 LEFT JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11  -  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17

}
do_execsql_test joinC-120 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 FULL JOIN (
  t3 LEFT JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17

}
do_execsql_test joinC-121 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 FULL JOIN (
  t3 RIGHT JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-122 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 FULL JOIN (
  t3 RIGHT JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-123 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 FULL JOIN (
  t3 RIGHT JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12  -  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17

}
do_execsql_test joinC-124 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 FULL JOIN (
  t3 RIGHT JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12  -  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17

}
do_execsql_test joinC-125 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 FULL JOIN (
  t3 FULL JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11  -  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  -  -

}
do_execsql_test joinC-126 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 FULL JOIN (
  t3 FULL JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  -  -

}
do_execsql_test joinC-127 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 FULL JOIN (
  t3 FULL JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11  -  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17

}
do_execsql_test joinC-128 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 LEFT JOIN (
  t2 FULL JOIN (
  t3 FULL JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12 12 12  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17

}
do_execsql_test joinC-129 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 INNER JOIN (
  t3 INNER JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15

}
do_execsql_test joinC-130 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 INNER JOIN (
  t3 INNER JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  13  - 13 13 13  -
  15 15 15 15 15 15

}
do_execsql_test joinC-131 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 INNER JOIN (
  t3 INNER JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  18  - 18 18  - 18

}
do_execsql_test joinC-132 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 INNER JOIN (
  t3 INNER JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  13  - 13 13 13  -
  15 15 15 15 15 15
  18  - 18 18  - 18

}
do_execsql_test joinC-133 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 INNER JOIN (
  t3 LEFT JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12 12  -  -
  13  - 13 13  -  -
  15 15 15 15 15 15
  18  - 18 18  -  -

}
do_execsql_test joinC-134 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 INNER JOIN (
  t3 LEFT JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  18  - 18 18  -  -

}
do_execsql_test joinC-135 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 INNER JOIN (
  t3 LEFT JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12 12  -  -
  13  - 13 13  -  -
  15 15 15 15 15 15
  18  - 18 18  - 18

}
do_execsql_test joinC-136 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 INNER JOIN (
  t3 LEFT JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  18  - 18 18  - 18

}
do_execsql_test joinC-137 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 INNER JOIN (
  t3 RIGHT JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15

}
do_execsql_test joinC-138 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 INNER JOIN (
  t3 RIGHT JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  13  - 13 13 13  -
  15 15 15 15 15 15

}
do_execsql_test joinC-139 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 INNER JOIN (
  t3 RIGHT JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  18  - 18 18  - 18

}
do_execsql_test joinC-140 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 INNER JOIN (
  t3 RIGHT JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  13  - 13 13 13  -
  15 15 15 15 15 15
  18  - 18 18  - 18

}
do_execsql_test joinC-141 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 INNER JOIN (
  t3 FULL JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12 12  -  -
  13  - 13 13  -  -
  15 15 15 15 15 15
  18  - 18 18  -  -

}
do_execsql_test joinC-142 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 INNER JOIN (
  t3 FULL JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  18  - 18 18  -  -

}
do_execsql_test joinC-143 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 INNER JOIN (
  t3 FULL JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12 12  -  -
  13  - 13 13  -  -
  15 15 15 15 15 15
  18  - 18 18  - 18

}
do_execsql_test joinC-144 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 INNER JOIN (
  t3 FULL JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  18  - 18 18  - 18

}
do_execsql_test joinC-145 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 LEFT JOIN (
  t3 INNER JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  12 12 12  -  -  -
  13  - 13  -  -  -
  15 15 15 15 15 15
  18  - 18  -  -  -

}
do_execsql_test joinC-146 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 LEFT JOIN (
  t3 INNER JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  12 12 12  -  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  18  - 18  -  -  -

}
do_execsql_test joinC-147 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 LEFT JOIN (
  t3 INNER JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  12 12 12  -  -  -
  13  - 13  -  -  -
  15 15 15 15 15 15
  18  - 18 18  - 18

}
do_execsql_test joinC-148 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 LEFT JOIN (
  t3 INNER JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  12 12 12  -  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  18  - 18 18  - 18

}
do_execsql_test joinC-149 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 LEFT JOIN (
  t3 LEFT JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  12 12 12 12  -  -
  13  - 13 13  -  -
  15 15 15 15 15 15
  18  - 18 18  -  -

}
do_execsql_test joinC-150 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 LEFT JOIN (
  t3 LEFT JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  18  - 18 18  -  -

}
do_execsql_test joinC-151 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 LEFT JOIN (
  t3 LEFT JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  12 12 12 12  -  -
  13  - 13 13  -  -
  15 15 15 15 15 15
  18  - 18 18  - 18

}
do_execsql_test joinC-152 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 LEFT JOIN (
  t3 LEFT JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  18  - 18 18  - 18

}
do_execsql_test joinC-153 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 LEFT JOIN (
  t3 RIGHT JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  12 12 12  -  -  -
  13  - 13  -  -  -
  15 15 15 15 15 15
  18  - 18  -  -  -

}
do_execsql_test joinC-154 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 LEFT JOIN (
  t3 RIGHT JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  12 12 12  -  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  18  - 18  -  -  -

}
do_execsql_test joinC-155 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 LEFT JOIN (
  t3 RIGHT JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  12 12 12  -  -  -
  13  - 13  -  -  -
  15 15 15 15 15 15
  18  - 18 18  - 18

}
do_execsql_test joinC-156 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 LEFT JOIN (
  t3 RIGHT JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  12 12 12  -  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  18  - 18 18  - 18

}
do_execsql_test joinC-157 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 LEFT JOIN (
  t3 FULL JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  12 12 12 12  -  -
  13  - 13 13  -  -
  15 15 15 15 15 15
  18  - 18 18  -  -

}
do_execsql_test joinC-158 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 LEFT JOIN (
  t3 FULL JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  18  - 18 18  -  -

}
do_execsql_test joinC-159 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 LEFT JOIN (
  t3 FULL JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  12 12 12 12  -  -
  13  - 13 13  -  -
  15 15 15 15 15 15
  18  - 18 18  - 18

}
do_execsql_test joinC-160 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 LEFT JOIN (
  t3 FULL JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  18  - 18 18  - 18

}
do_execsql_test joinC-161 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 RIGHT JOIN (
  t3 INNER JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  19  -  - 19 19 19

}
do_execsql_test joinC-162 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 RIGHT JOIN (
  t3 INNER JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  19  -  - 19 19 19

}
do_execsql_test joinC-163 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 RIGHT JOIN (
  t3 INNER JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19

}
do_execsql_test joinC-164 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 RIGHT JOIN (
  t3 INNER JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19

}
do_execsql_test joinC-165 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 RIGHT JOIN (
  t3 LEFT JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11  -  -
  12 12 12 12  -  -
  13  - 13 13  -  -
  15 15 15 15 15 15
  17 17  - 17  -  -
  18  - 18 18  -  -
  19  -  - 19 19 19

}
do_execsql_test joinC-166 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 RIGHT JOIN (
  t3 LEFT JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  -  -
  18  - 18 18  -  -
  19  -  - 19 19 19

}
do_execsql_test joinC-167 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 RIGHT JOIN (
  t3 LEFT JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11  -  -
  12 12 12 12  -  -
  13  - 13 13  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19

}
do_execsql_test joinC-168 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 RIGHT JOIN (
  t3 LEFT JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19

}
do_execsql_test joinC-169 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 RIGHT JOIN (
  t3 RIGHT JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  19  -  - 19 19 19

}
do_execsql_test joinC-170 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 RIGHT JOIN (
  t3 RIGHT JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  19  -  - 19 19 19

}
do_execsql_test joinC-171 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 RIGHT JOIN (
  t3 RIGHT JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19

}
do_execsql_test joinC-172 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 RIGHT JOIN (
  t3 RIGHT JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19

}
do_execsql_test joinC-173 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 RIGHT JOIN (
  t3 FULL JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11  -  -
  12 12 12 12  -  -
  13  - 13 13  -  -
  15 15 15 15 15 15
  17 17  - 17  -  -
  18  - 18 18  -  -
  19  -  - 19 19 19

}
do_execsql_test joinC-174 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 RIGHT JOIN (
  t3 FULL JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  -  -
  18  - 18 18  -  -
  19  -  - 19 19 19

}
do_execsql_test joinC-175 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 RIGHT JOIN (
  t3 FULL JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11  -  -
  12 12 12 12  -  -
  13  - 13 13  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19

}
do_execsql_test joinC-176 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 RIGHT JOIN (
  t3 FULL JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19

}
do_execsql_test joinC-177 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 FULL JOIN (
  t3 INNER JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  12 12 12  -  -  -
  13  - 13  -  -  -
  15 15 15 15 15 15
  18  - 18  -  -  -
  19  -  - 19 19 19

}
do_execsql_test joinC-178 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 FULL JOIN (
  t3 INNER JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12  -  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  18  - 18  -  -  -
  19  -  - 19 19 19

}
do_execsql_test joinC-179 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 FULL JOIN (
  t3 INNER JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  12 12 12  -  -  -
  13  - 13  -  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19

}
do_execsql_test joinC-180 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 FULL JOIN (
  t3 INNER JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12  -  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19

}
do_execsql_test joinC-181 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 FULL JOIN (
  t3 LEFT JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
   -  -  -  -  -  -
  11 11  - 11  -  -
  12 12 12 12  -  -
  13  - 13 13  -  -
  15 15 15 15 15 15
  17 17  - 17  -  -
  18  - 18 18  -  -
  19  -  - 19 19 19

}
do_execsql_test joinC-182 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 FULL JOIN (
  t3 LEFT JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  -  -
  18  - 18 18  -  -
  19  -  - 19 19 19

}
do_execsql_test joinC-183 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 FULL JOIN (
  t3 LEFT JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
   -  -  -  -  -  -
  11 11  - 11  -  -
  12 12 12 12  -  -
  13  - 13 13  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19

}
do_execsql_test joinC-184 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 FULL JOIN (
  t3 LEFT JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19

}
do_execsql_test joinC-185 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 FULL JOIN (
  t3 RIGHT JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  12 12 12  -  -  -
  13  - 13  -  -  -
  15 15 15 15 15 15
  18  - 18  -  -  -
  19  -  - 19 19 19

}
do_execsql_test joinC-186 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 FULL JOIN (
  t3 RIGHT JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12  -  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  18  - 18  -  -  -
  19  -  - 19 19 19

}
do_execsql_test joinC-187 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 FULL JOIN (
  t3 RIGHT JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  12 12 12  -  -  -
  13  - 13  -  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19

}
do_execsql_test joinC-188 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 FULL JOIN (
  t3 RIGHT JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12  -  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19

}
do_execsql_test joinC-189 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 FULL JOIN (
  t3 FULL JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
   -  -  -  -  -  -
  11 11  - 11  -  -
  12 12 12 12  -  -
  13  - 13 13  -  -
  15 15 15 15 15 15
  17 17  - 17  -  -
  18  - 18 18  -  -
  19  -  - 19 19 19

}
do_execsql_test joinC-190 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 FULL JOIN (
  t3 FULL JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  -  -
  18  - 18 18  -  -
  19  -  - 19 19 19

}
do_execsql_test joinC-191 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 FULL JOIN (
  t3 FULL JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
   -  -  -  -  -  -
  11 11  - 11  -  -
  12 12 12 12  -  -
  13  - 13 13  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19

}
do_execsql_test joinC-192 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 RIGHT JOIN (
  t2 FULL JOIN (
  t3 FULL JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19

}
do_execsql_test joinC-193 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 INNER JOIN (
  t3 INNER JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12  -  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-194 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 INNER JOIN (
  t3 INNER JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12  -  -  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-195 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 INNER JOIN (
  t3 INNER JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12  -  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  18  - 18 18  - 18

}
do_execsql_test joinC-196 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 INNER JOIN (
  t3 INNER JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12  -  -  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  18  - 18 18  - 18

}
do_execsql_test joinC-197 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 INNER JOIN (
  t3 LEFT JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12 12  -  -
  13  - 13 13  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  18  - 18 18  -  -

}
do_execsql_test joinC-198 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 INNER JOIN (
  t3 LEFT JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  18  - 18 18  -  -

}
do_execsql_test joinC-199 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 INNER JOIN (
  t3 LEFT JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12 12  -  -
  13  - 13 13  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  18  - 18 18  - 18

}
do_execsql_test joinC-200 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 INNER JOIN (
  t3 LEFT JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  18  - 18 18  - 18

}
do_execsql_test joinC-201 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 INNER JOIN (
  t3 RIGHT JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12  -  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-202 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 INNER JOIN (
  t3 RIGHT JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12  -  -  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  -  -  -  -

}
do_execsql_test joinC-203 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 INNER JOIN (
  t3 RIGHT JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12  -  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  18  - 18 18  - 18

}
do_execsql_test joinC-204 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 INNER JOIN (
  t3 RIGHT JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12  -  -  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  18  - 18 18  - 18

}
do_execsql_test joinC-205 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 INNER JOIN (
  t3 FULL JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12 12  -  -
  13  - 13 13  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  18  - 18 18  -  -

}
do_execsql_test joinC-206 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 INNER JOIN (
  t3 FULL JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  18  - 18 18  -  -

}
do_execsql_test joinC-207 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 INNER JOIN (
  t3 FULL JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12 12  -  -
  13  - 13 13  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  18  - 18 18  - 18

}
do_execsql_test joinC-208 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 INNER JOIN (
  t3 FULL JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  18  - 18 18  - 18

}
do_execsql_test joinC-209 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 LEFT JOIN (
  t3 INNER JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  -  -  -  -
  12 12 12  -  -  -
  13  - 13  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  18  - 18  -  -  -

}
do_execsql_test joinC-210 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 LEFT JOIN (
  t3 INNER JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  -  -  -  -
  12 12 12  -  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  18  - 18  -  -  -

}
do_execsql_test joinC-211 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 LEFT JOIN (
  t3 INNER JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  -  -  -  -
  12 12 12  -  -  -
  13  - 13  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  18  - 18 18  - 18

}
do_execsql_test joinC-212 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 LEFT JOIN (
  t3 INNER JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  -  -  -  -
  12 12 12  -  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  18  - 18 18  - 18

}
do_execsql_test joinC-213 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 LEFT JOIN (
  t3 LEFT JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  -  -  -  -
  12 12 12 12  -  -
  13  - 13 13  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  18  - 18 18  -  -

}
do_execsql_test joinC-214 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 LEFT JOIN (
  t3 LEFT JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  -  -  -  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  18  - 18 18  -  -

}
do_execsql_test joinC-215 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 LEFT JOIN (
  t3 LEFT JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  -  -  -  -
  12 12 12 12  -  -
  13  - 13 13  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  18  - 18 18  - 18

}
do_execsql_test joinC-216 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 LEFT JOIN (
  t3 LEFT JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  -  -  -  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  18  - 18 18  - 18

}
do_execsql_test joinC-217 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 LEFT JOIN (
  t3 RIGHT JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  -  -  -  -
  12 12 12  -  -  -
  13  - 13  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  18  - 18  -  -  -

}
do_execsql_test joinC-218 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 LEFT JOIN (
  t3 RIGHT JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  -  -  -  -
  12 12 12  -  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  18  - 18  -  -  -

}
do_execsql_test joinC-219 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 LEFT JOIN (
  t3 RIGHT JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  -  -  -  -
  12 12 12  -  -  -
  13  - 13  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  18  - 18 18  - 18

}
do_execsql_test joinC-220 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 LEFT JOIN (
  t3 RIGHT JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  -  -  -  -
  12 12 12  -  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  18  - 18 18  - 18

}
do_execsql_test joinC-221 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 LEFT JOIN (
  t3 FULL JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  -  -  -  -
  12 12 12 12  -  -
  13  - 13 13  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  18  - 18 18  -  -

}
do_execsql_test joinC-222 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 LEFT JOIN (
  t3 FULL JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  -  -  -  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  18  - 18 18  -  -

}
do_execsql_test joinC-223 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 LEFT JOIN (
  t3 FULL JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  -  -  -  -
  12 12 12 12  -  -
  13  - 13 13  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  18  - 18 18  - 18

}
do_execsql_test joinC-224 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 LEFT JOIN (
  t3 FULL JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  -  -  -  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  18  - 18 18  - 18

}
do_execsql_test joinC-225 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 RIGHT JOIN (
  t3 INNER JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12  -  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  19  -  - 19 19 19

}
do_execsql_test joinC-226 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 RIGHT JOIN (
  t3 INNER JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12  -  -  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  19  -  - 19 19 19

}
do_execsql_test joinC-227 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 RIGHT JOIN (
  t3 INNER JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12  -  -  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19

}
do_execsql_test joinC-228 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 RIGHT JOIN (
  t3 INNER JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12  -  -  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19

}
do_execsql_test joinC-229 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 RIGHT JOIN (
  t3 LEFT JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11  -  -
  12 12 12 12  -  -
  13  - 13 13  -  -
  15 15 15 15 15 15
  17 17  - 17  -  -
  18  - 18 18  -  -
  19  -  - 19 19 19

}
do_execsql_test joinC-230 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 RIGHT JOIN (
  t3 LEFT JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  -  -
  18  - 18 18  -  -
  19  -  - 19 19 19

}
do_execsql_test joinC-231 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 RIGHT JOIN (
  t3 LEFT JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11  -  -
  12 12 12 12  -  -
  13  - 13 13  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19

}
do_execsql_test joinC-232 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 RIGHT JOIN (
  t3 LEFT JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19

}
do_execsql_test joinC-233 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 RIGHT JOIN (
  t3 RIGHT JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12  -  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  19  -  - 19 19 19

}
do_execsql_test joinC-234 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 RIGHT JOIN (
  t3 RIGHT JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12  -  -  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  19  -  - 19 19 19

}
do_execsql_test joinC-235 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 RIGHT JOIN (
  t3 RIGHT JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  -  -  -  -
  12 12  -  -  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19

}
do_execsql_test joinC-236 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 RIGHT JOIN (
  t3 RIGHT JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
  11 11  - 11 11  -
  12 12  -  -  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19

}
do_execsql_test joinC-237 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 RIGHT JOIN (
  t3 FULL JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11  -  -
  12 12 12 12  -  -
  13  - 13 13  -  -
  15 15 15 15 15 15
  17 17  - 17  -  -
  18  - 18 18  -  -
  19  -  - 19 19 19

}
do_execsql_test joinC-238 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 RIGHT JOIN (
  t3 FULL JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  -  -
  18  - 18 18  -  -
  19  -  - 19 19 19

}
do_execsql_test joinC-239 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 RIGHT JOIN (
  t3 FULL JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11  -  -
  12 12 12 12  -  -
  13  - 13 13  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19

}
do_execsql_test joinC-240 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 RIGHT JOIN (
  t3 FULL JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19

}
do_execsql_test joinC-241 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 FULL JOIN (
  t3 INNER JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  -  -  -  -
  12 12 12  -  -  -
  13  - 13  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  18  - 18  -  -  -
  19  -  - 19 19 19

}
do_execsql_test joinC-242 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 FULL JOIN (
  t3 INNER JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12  -  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  18  - 18  -  -  -
  19  -  - 19 19 19

}
do_execsql_test joinC-243 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 FULL JOIN (
  t3 INNER JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  -  -  -  -
  12 12 12  -  -  -
  13  - 13  -  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19

}
do_execsql_test joinC-244 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 FULL JOIN (
  t3 INNER JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12  -  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19

}
do_execsql_test joinC-245 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 FULL JOIN (
  t3 LEFT JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
   -  -  -  -  -  -
  11 11  - 11  -  -
  12 12 12 12  -  -
  13  - 13 13  -  -
  15 15 15 15 15 15
  17 17  - 17  -  -
  18  - 18 18  -  -
  19  -  - 19 19 19

}
do_execsql_test joinC-246 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 FULL JOIN (
  t3 LEFT JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  -  -
  18  - 18 18  -  -
  19  -  - 19 19 19

}
do_execsql_test joinC-247 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 FULL JOIN (
  t3 LEFT JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
   -  -  -  -  -  -
  11 11  - 11  -  -
  12 12 12 12  -  -
  13  - 13 13  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19

}
do_execsql_test joinC-248 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 FULL JOIN (
  t3 LEFT JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19

}
do_execsql_test joinC-249 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 FULL JOIN (
  t3 RIGHT JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  -  -  -  -
  12 12 12  -  -  -
  13  - 13  -  -  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  18  - 18  -  -  -
  19  -  - 19 19 19

}
do_execsql_test joinC-250 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 FULL JOIN (
  t3 RIGHT JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12  -  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  -  -  -  -
  18  - 18  -  -  -
  19  -  - 19 19 19

}
do_execsql_test joinC-251 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 FULL JOIN (
  t3 RIGHT JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  -  -  -  -
  12 12 12  -  -  -
  13  - 13  -  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19

}
do_execsql_test joinC-252 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 FULL JOIN (
  t3 RIGHT JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12  -  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19

}
do_execsql_test joinC-253 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 FULL JOIN (
  t3 FULL JOIN (
  t4 INNER JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
   -  -  -  -  -  -
  11 11  - 11  -  -
  12 12 12 12  -  -
  13  - 13 13  -  -
  15 15 15 15 15 15
  17 17  - 17  -  -
  18  - 18 18  -  -
  19  -  - 19 19 19

}
do_execsql_test joinC-254 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 FULL JOIN (
  t3 FULL JOIN (
  t4 LEFT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  -  -
  18  - 18 18  -  -
  19  -  - 19 19 19

}
do_execsql_test joinC-255 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 FULL JOIN (
  t3 FULL JOIN (
  t4 RIGHT JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
   -  -  -  -  -  -
  11 11  - 11  -  -
  12 12 12 12  -  -
  13  - 13 13  -  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19

}
do_execsql_test joinC-256 {
  SELECT a, t1.a, t2.a, t3.a, t4.a, t5.a
  FROM t1 FULL JOIN (
  t2 FULL JOIN (
  t3 FULL JOIN (
  t4 FULL JOIN t5 USING(a)
  ) USING(a)
  ) USING(a)
  ) USING(a)
  ORDER BY 1 NULLS FIRST;
} {
   -  -  -  -  -  -
   -  -  -  -  -  -
  11 11  - 11 11  -
  12 12 12 12  -  -
  13  - 13 13 13  -
  15 15 15 15 15 15
  17 17  - 17  - 17
  18  - 18 18  - 18
  19  -  - 19 19 19

}
finish_test

Added test/joinD.test.

more than 10,000 changes

Added test/joinE.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022-05-13
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file implements tests for JOINs that use Bloom filters.
#
# The test case output is (mostly) all generated by PostgreSQL 14.  This
# test module was created as follows:
#
#   1.   Run a TCL script (included at the bottom of this file) that
#        generates an input script for "psql" that will run man
#        diverse tests on joins.
#
#   2.   Run the script from step (1) through psql and collect the
#        output.
#
#   3.   Make a few minor global search-and-replace operations to convert
#        the psql output into a form suitable for this test module.
#
#   4.   Add this header, and the script content at the footer.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
db nullvalue -
db eval {
  CREATE TABLE t1(a INT);
  INSERT INTO t1 VALUES(1),(NULL);
  CREATE TABLE t2(b INT);
  INSERT INTO t2 VALUES(2),(NULL);
}
do_execsql_test joinE-1 {
  SELECT a, b
  FROM t1 INNER JOIN t2 ON true
  ORDER BY coalesce(a,b,3);
} {
  1 2
  1 -
  - 2
  - -
}
do_execsql_test joinE-2 {
  SELECT a, b
  FROM t1 INNER JOIN t2 ON true WHERE a IS NULL
  ORDER BY coalesce(a,b,3);
} {
  - 2
  - -
}
do_execsql_test joinE-3 {
  SELECT a, b
  FROM t1 INNER JOIN t2 ON a IS NULL
  ORDER BY coalesce(a,b,3);
} {
  - 2
  - -
}
do_execsql_test joinE-4 {
  SELECT a, b
  FROM t1 INNER JOIN t2 ON true WHERE b IS NULL
  ORDER BY coalesce(a,b,3);
} {
  1 -
  - -
}
do_execsql_test joinE-5 {
  SELECT a, b
  FROM t1 INNER JOIN t2 ON b IS NULL
  ORDER BY coalesce(a,b,3);
} {
  1 -
  - -
}
do_execsql_test joinE-6 {
  SELECT a, b
  FROM t1 LEFT JOIN t2 ON true
  ORDER BY coalesce(a,b,3);
} {
  1 2
  1 -
  - 2
  - -
}
do_execsql_test joinE-7 {
  SELECT a, b
  FROM t1 LEFT JOIN t2 ON true WHERE a IS NULL
  ORDER BY coalesce(a,b,3);
} {
  - 2
  - -
}
do_execsql_test joinE-8 {
  SELECT a, b
  FROM t1 LEFT JOIN t2 ON a IS NULL
  ORDER BY coalesce(a,b,3);
} {
  1 -
  - 2
  - -
}
do_execsql_test joinE-9 {
  SELECT a, b
  FROM t1 LEFT JOIN t2 ON true WHERE b IS NULL
  ORDER BY coalesce(a,b,3);
} {
  1 -
  - -
}
do_execsql_test joinE-10 {
  SELECT a, b
  FROM t1 LEFT JOIN t2 ON b IS NULL
  ORDER BY coalesce(a,b,3);
} {
  1 -
  - -
}
do_execsql_test joinE-11 {
  SELECT a, b
  FROM t1 RIGHT JOIN t2 ON true
  ORDER BY coalesce(a,b,3);
} {
  1 2
  1 -
  - 2
  - -
}
do_execsql_test joinE-12 {
  SELECT a, b
  FROM t1 RIGHT JOIN t2 ON true WHERE a IS NULL
  ORDER BY coalesce(a,b,3);
} {
  - 2
  - -
}
do_execsql_test joinE-13 {
  SELECT a, b
  FROM t1 RIGHT JOIN t2 ON a IS NULL
  ORDER BY coalesce(a,b,3);
} {
  - 2
  - -
}
do_execsql_test joinE-14 {
  SELECT a, b
  FROM t1 RIGHT JOIN t2 ON true WHERE b IS NULL
  ORDER BY coalesce(a,b,3);
} {
  1 -
  - -
}
do_execsql_test joinE-15 {
  SELECT a, b
  FROM t1 RIGHT JOIN t2 ON b IS NULL
  ORDER BY coalesce(a,b,3);
} {
  1 -
  - 2
  - -
}
do_execsql_test joinE-16 {
  SELECT a, b
  FROM t1 FULL JOIN t2 ON true
  ORDER BY coalesce(a,b,3);
} {
  1 2
  1 -
  - 2
  - -
}
do_execsql_test joinE-17 {
  SELECT a, b
  FROM t1 FULL JOIN t2 ON true WHERE a IS NULL
  ORDER BY coalesce(a,b,3);
} {
  - 2
  - -
}

# PG-14 is unable to perform this join.  It says:  FULL JOIN is only
# supported with merge-joinable or hash-joinable join conditions
#   
# do_execsql_test joinE-18 {
#  SELECT a, b
#  FROM t1 FULL JOIN t2 ON a IS NULL
#  ORDER BY coalesce(a,b,3);
# } {
# }

do_execsql_test joinE-19 {
  SELECT a, b
  FROM t1 FULL JOIN t2 ON true WHERE b IS NULL
  ORDER BY coalesce(a,b,3);
} {
  1 -
  - -
}

# PG-14 is unable to perform this join.  It says:  FULL JOIN is only
# supported with merge-joinable or hash-joinable join conditions
#   
# do_execsql_test joinE-20 {
#   SELECT a, b
#   FROM t1 FULL JOIN t2 ON b IS NULL
#   ORDER BY coalesce(a,b,3);
# } {
# }

db eval {
  DELETE FROM t1;
  INSERT INTO t1 VALUES(1);
  DELETE FROM t2;
  INSERT INTO t2 VALUES(NULL);
}

do_execsql_test joinE-21 {
  SELECT a, b
  FROM t1 INNER JOIN t2 ON true
  ORDER BY coalesce(a,b,3);
} {
  1 -
}
do_execsql_test joinE-22 {
  SELECT a, b
  FROM t1 INNER JOIN t2 ON true WHERE a IS NULL
  ORDER BY coalesce(a,b,3);
} {
}
do_execsql_test joinE-23 {
  SELECT a, b
  FROM t1 INNER JOIN t2 ON a IS NULL
  ORDER BY coalesce(a,b,3);
} {
}
do_execsql_test joinE-24 {
  SELECT a, b
  FROM t1 INNER JOIN t2 ON true WHERE b IS NULL
  ORDER BY coalesce(a,b,3);
} {
  1 -
}
do_execsql_test joinE-25 {
  SELECT a, b
  FROM t1 INNER JOIN t2 ON b IS NULL
  ORDER BY coalesce(a,b,3);
} {
  1 -
}
do_execsql_test joinE-26 {
  SELECT a, b
  FROM t1 LEFT JOIN t2 ON true
  ORDER BY coalesce(a,b,3);
} {
  1 -
}
do_execsql_test joinE-27 {
  SELECT a, b
  FROM t1 LEFT JOIN t2 ON true WHERE a IS NULL
  ORDER BY coalesce(a,b,3);
} {
}
do_execsql_test joinE-28 {
  SELECT a, b
  FROM t1 LEFT JOIN t2 ON a IS NULL
  ORDER BY coalesce(a,b,3);
} {
  1 -
}
do_execsql_test joinE-29 {
  SELECT a, b
  FROM t1 LEFT JOIN t2 ON true WHERE b IS NULL
  ORDER BY coalesce(a,b,3);
} {
  1 -
}
do_execsql_test joinE-30 {
  SELECT a, b
  FROM t1 LEFT JOIN t2 ON b IS NULL
  ORDER BY coalesce(a,b,3);
} {
  1 -
}
do_execsql_test joinE-31 {
  SELECT a, b
  FROM t1 RIGHT JOIN t2 ON true
  ORDER BY coalesce(a,b,3);
} {
  1 -
}

do_execsql_test joinE-32 {
  SELECT a, b
  FROM t1 RIGHT JOIN t2 ON true WHERE a IS NULL
  ORDER BY coalesce(a,b,3);
} {
}

do_execsql_test joinE-33 {
  SELECT a, b
  FROM t1 RIGHT JOIN t2 ON a IS NULL
  ORDER BY coalesce(a,b,3);
} {
  - -
}
do_execsql_test joinE-34 {
  SELECT a, b
  FROM t1 RIGHT JOIN t2 ON true WHERE b IS NULL
  ORDER BY coalesce(a,b,3);
} {
  1 -
}
do_execsql_test joinE-35 {
  SELECT a, b
  FROM t1 RIGHT JOIN t2 ON b IS NULL
  ORDER BY coalesce(a,b,3);
} {
  1 -
}
do_execsql_test joinE-36 {
  SELECT a, b
  FROM t1 FULL JOIN t2 ON true
  ORDER BY coalesce(a,b,3);
} {
  1 -
}
do_execsql_test joinE-37 {
  SELECT a, b
  FROM t1 FULL JOIN t2 ON true WHERE a IS NULL
  ORDER BY coalesce(a,b,3);
} {
}

# PG-14 is unable
#
# do_execsql_test joinE-38 {
#   SELECT a, b
#   FROM t1 FULL JOIN t2 ON a IS NULL
#   ORDER BY coalesce(a,b,3);
# } {
# }

do_execsql_test joinE-39 {
  SELECT a, b
  FROM t1 FULL JOIN t2 ON true WHERE b IS NULL
  ORDER BY coalesce(a,b,3);
} {
  1 -
}

# PG-14 is unable
# do_execsql_test joinE-40 {
#   SELECT a, b
#   FROM t1 FULL JOIN t2 ON b IS NULL
#   ORDER BY coalesce(a,b,3);
# } {
# }

finish_test

##############################################################################
# This is the PG-14 test script generator
#
# puts "
# \\pset border off
# \\pset tuples_only on
# \\pset null -
# 
# DROP TABLE IF EXISTS t1;
# DROP TABLE IF EXISTS t2;
# CREATE TABLE t1(a INT);
# INSERT INTO t1 VALUES(1),(NULL);
# CREATE TABLE t2(b INT);
# INSERT INTO t2 VALUES(2),(NULL);
# "
# 
# proc echo {prefix txt} {
#   regsub -all {\n} $txt \n$prefix txt
#   puts "$prefix$txt"
# }
# 
# set n 0
# set k 0
# foreach j1 {INNER LEFT RIGHT FULL} {
#   foreach on1 {
#      true
#      {true WHERE a IS NULL}
#      {a IS NULL}
#      {true WHERE b IS NULL}
#      {b IS NULL}
#   } {
# 
# incr n
# incr k
# set q1 ""
# append q1 "SELECT a, b\n"
# append q1 "  FROM t1 $j1 JOIN t2 ON $on1\n"
# append q1 " ORDER BY coalesce(a,b,3);"
# 
# echo "\\qecho " "do_execsql_test joinE-$n \{"
# echo "\\qecho X  " $q1
# echo "\\qecho " "\} \{"
# puts $q1
# echo "\\qecho " "\}"
# 
#   }
# }
# 
# puts "
# DELETE FROM t1;
# INSERT INTO t1 VALUES(1);
# DELETE FROM t2;
# INSERT INTO t2 VALUES(NULL);
# "
# 
# foreach j1 {INNER LEFT RIGHT FULL} {
#   foreach on1 {
#      true
#      {true WHERE a IS NULL}
#      {a IS NULL}
#      {true WHERE b IS NULL}
#      {b IS NULL}
#   } {
# 
# incr n
# incr k
# set q1 ""
# append q1 "SELECT a, b\n"
# append q1 "  FROM t1 $j1 JOIN t2 ON $on1\n"
# append q1 " ORDER BY coalesce(a,b,3);"
# 
# echo "\\qecho " "do_execsql_test joinE-$n \{"
# echo "\\qecho X  " $q1
# echo "\\qecho " "\} \{"
# puts $q1
# echo "\\qecho " "\}"
# 
#   }
# }

Added test/joinF.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022-05-31
#
# 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 tests for JOINs
#
# The test case output is (mostly) all generated by PostgreSQL 14.  This
# test module was created as follows:
#
#   1.   Run a TCL script (included at the bottom of this file) that
#        generates an input script for "psql" that will run man
#        diverse tests on joins.
#
#   2.   Run the script from step (1) through psql and collect the
#        output.
#
#   3.   Make a few minor global search-and-replace operations to convert
#        the psql output into a form suitable for this test module.
#
#   4.   Add this header, and the script content at the footer.
#
# A few extra tests that were not generated from postgresql output are
# added at the end.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
db nullvalue -
db eval {
  CREATE TABLE t1(x INT);
  CREATE TABLE t2(y INT);
  CREATE TABLE t3(z INT);
  CREATE TABLE t4(w INT);
  INSERT INTO t1 VALUES(10);
  INSERT INTO t3 VALUES(20),(30);
  INSERT INTO t4 VALUES(50);
}
do_execsql_test joinF-1 {
  SELECT *
  FROM t1 INNER JOIN t2 ON true
  INNER JOIN t3 ON t2.y IS NOT NULL
  INNER JOIN t4 ON true
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
}
do_execsql_test joinF-2 {
  SELECT *
  FROM t1 INNER JOIN t2 ON true
  INNER JOIN t3 ON t2.y IS NOT NULL
  INNER JOIN t4 ON true
  WHERE (t3.z!=400 AND t3.z!=500 AND t3.z!=600)
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
}
do_execsql_test joinF-3 {
  SELECT *
  FROM t1 INNER JOIN t2 ON true
  INNER JOIN t3 ON t2.y IS NOT NULL
  LEFT JOIN t4 ON true
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
}
do_execsql_test joinF-4 {
  SELECT *
  FROM t1 INNER JOIN t2 ON true
  INNER JOIN t3 ON t2.y IS NOT NULL
  LEFT JOIN t4 ON true
  WHERE (t3.z!=400 AND t3.z!=500 AND t3.z!=600)
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
}
do_execsql_test joinF-5 {
  SELECT *
  FROM t1 INNER JOIN t2 ON true
  INNER JOIN t3 ON t2.y IS NOT NULL
  RIGHT JOIN t4 ON true
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
  - - - 50
}
do_execsql_test joinF-6 {
  SELECT *
  FROM t1 INNER JOIN t2 ON true
  INNER JOIN t3 ON t2.y IS NOT NULL
  RIGHT JOIN t4 ON true
  WHERE (t3.z!=400 AND t3.z!=500 AND t3.z!=600)
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
}
do_execsql_test joinF-7 {
  SELECT *
  FROM t1 INNER JOIN t2 ON true
  LEFT JOIN t3 ON t2.y IS NOT NULL
  INNER JOIN t4 ON true
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
}
do_execsql_test joinF-8 {
  SELECT *
  FROM t1 INNER JOIN t2 ON true
  LEFT JOIN t3 ON t2.y IS NOT NULL
  INNER JOIN t4 ON true
  WHERE (t3.z!=400 AND t3.z!=500 AND t3.z!=600)
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
}
do_execsql_test joinF-9 {
  SELECT *
  FROM t1 INNER JOIN t2 ON true
  LEFT JOIN t3 ON t2.y IS NOT NULL
  LEFT JOIN t4 ON true
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
}
do_execsql_test joinF-10 {
  SELECT *
  FROM t1 INNER JOIN t2 ON true
  LEFT JOIN t3 ON t2.y IS NOT NULL
  LEFT JOIN t4 ON true
  WHERE (t3.z!=400 AND t3.z!=500 AND t3.z!=600)
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
}
do_execsql_test joinF-11 {
  SELECT *
  FROM t1 INNER JOIN t2 ON true
  LEFT JOIN t3 ON t2.y IS NOT NULL
  RIGHT JOIN t4 ON true
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
  - - - 50
}
do_execsql_test joinF-12 {
  SELECT *
  FROM t1 INNER JOIN t2 ON true
  LEFT JOIN t3 ON t2.y IS NOT NULL
  RIGHT JOIN t4 ON true
  WHERE (t3.z!=400 AND t3.z!=500 AND t3.z!=600)
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
}
do_execsql_test joinF-13 {
  SELECT *
  FROM t1 INNER JOIN t2 ON true
  RIGHT JOIN t3 ON t2.y IS NOT NULL
  INNER JOIN t4 ON true
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
  - - 20 50
  - - 30 50
}
do_execsql_test joinF-14 {
  SELECT *
  FROM t1 INNER JOIN t2 ON true
  RIGHT JOIN t3 ON t2.y IS NOT NULL
  INNER JOIN t4 ON true
  WHERE (t3.z!=400 AND t3.z!=500 AND t3.z!=600)
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
  - - 20 50
  - - 30 50
}
do_execsql_test joinF-15 {
  SELECT *
  FROM t1 INNER JOIN t2 ON true
  RIGHT JOIN t3 ON t2.y IS NOT NULL
  LEFT JOIN t4 ON true
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
  - - 20 50
  - - 30 50
}
do_execsql_test joinF-16 {
  SELECT *
  FROM t1 INNER JOIN t2 ON true
  RIGHT JOIN t3 ON t2.y IS NOT NULL
  LEFT JOIN t4 ON true
  WHERE (t3.z!=400 AND t3.z!=500 AND t3.z!=600)
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
  - - 20 50
  - - 30 50
}
do_execsql_test joinF-17 {
  SELECT *
  FROM t1 INNER JOIN t2 ON true
  RIGHT JOIN t3 ON t2.y IS NOT NULL
  RIGHT JOIN t4 ON true
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
  - - 20 50
  - - 30 50
}
do_execsql_test joinF-18 {
  SELECT *
  FROM t1 INNER JOIN t2 ON true
  RIGHT JOIN t3 ON t2.y IS NOT NULL
  RIGHT JOIN t4 ON true
  WHERE (t3.z!=400 AND t3.z!=500 AND t3.z!=600)
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
  - - 20 50
  - - 30 50
}
do_execsql_test joinF-19 {
  SELECT *
  FROM t1 LEFT JOIN t2 ON true
  INNER JOIN t3 ON t2.y IS NOT NULL
  INNER JOIN t4 ON true
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
}
do_execsql_test joinF-20 {
  SELECT *
  FROM t1 LEFT JOIN t2 ON true
  INNER JOIN t3 ON t2.y IS NOT NULL
  INNER JOIN t4 ON true
  WHERE (t3.z!=400 AND t3.z!=500 AND t3.z!=600)
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
}
do_execsql_test joinF-21 {
  SELECT *
  FROM t1 LEFT JOIN t2 ON true
  INNER JOIN t3 ON t2.y IS NOT NULL
  LEFT JOIN t4 ON true
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
}
do_execsql_test joinF-22 {
  SELECT *
  FROM t1 LEFT JOIN t2 ON true
  INNER JOIN t3 ON t2.y IS NOT NULL
  LEFT JOIN t4 ON true
  WHERE (t3.z!=400 AND t3.z!=500 AND t3.z!=600)
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
}
do_execsql_test joinF-23 {
  SELECT *
  FROM t1 LEFT JOIN t2 ON true
  INNER JOIN t3 ON t2.y IS NOT NULL
  RIGHT JOIN t4 ON true
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
  - - - 50
}
do_execsql_test joinF-24 {
  SELECT *
  FROM t1 LEFT JOIN t2 ON true
  INNER JOIN t3 ON t2.y IS NOT NULL
  RIGHT JOIN t4 ON true
  WHERE (t3.z!=400 AND t3.z!=500 AND t3.z!=600)
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
}
do_execsql_test joinF-25 {
  SELECT *
  FROM t1 LEFT JOIN t2 ON true
  LEFT JOIN t3 ON t2.y IS NOT NULL
  INNER JOIN t4 ON true
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
  10 - - 50
}
do_execsql_test joinF-26 {
  SELECT *
  FROM t1 LEFT JOIN t2 ON true
  LEFT JOIN t3 ON t2.y IS NOT NULL
  INNER JOIN t4 ON true
  WHERE (t3.z!=400 AND t3.z!=500 AND t3.z!=600)
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
}
do_execsql_test joinF-27 {
  SELECT *
  FROM t1 LEFT JOIN t2 ON true
  LEFT JOIN t3 ON t2.y IS NOT NULL
  LEFT JOIN t4 ON true
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
  10 - - 50
}
do_execsql_test joinF-28 {
  SELECT *
  FROM t1 LEFT JOIN t2 ON true
  LEFT JOIN t3 ON t2.y IS NOT NULL
  LEFT JOIN t4 ON true
  WHERE (t3.z!=400 AND t3.z!=500 AND t3.z!=600)
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
}
do_execsql_test joinF-29 {
  SELECT *
  FROM t1 LEFT JOIN t2 ON true
  LEFT JOIN t3 ON t2.y IS NOT NULL
  RIGHT JOIN t4 ON true
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
  10 - - 50
}
do_execsql_test joinF-30 {
  SELECT *
  FROM t1 LEFT JOIN t2 ON true
  LEFT JOIN t3 ON t2.y IS NOT NULL
  RIGHT JOIN t4 ON true
  WHERE (t3.z!=400 AND t3.z!=500 AND t3.z!=600)
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
}
do_execsql_test joinF-31 {
  SELECT *
  FROM t1 LEFT JOIN t2 ON true
  RIGHT JOIN t3 ON t2.y IS NOT NULL
  INNER JOIN t4 ON true
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
  - - 20 50
  - - 30 50
}
do_execsql_test joinF-32 {
  SELECT *
  FROM t1 LEFT JOIN t2 ON true
  RIGHT JOIN t3 ON t2.y IS NOT NULL
  INNER JOIN t4 ON true
  WHERE (t3.z!=400 AND t3.z!=500 AND t3.z!=600)
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
  - - 20 50
  - - 30 50
}
do_execsql_test joinF-33 {
  SELECT *
  FROM t1 LEFT JOIN t2 ON true
  RIGHT JOIN t3 ON t2.y IS NOT NULL
  LEFT JOIN t4 ON true
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
  - - 20 50
  - - 30 50
}
do_execsql_test joinF-34 {
  SELECT *
  FROM t1 LEFT JOIN t2 ON true
  RIGHT JOIN t3 ON t2.y IS NOT NULL
  LEFT JOIN t4 ON true
  WHERE (t3.z!=400 AND t3.z!=500 AND t3.z!=600)
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
  - - 20 50
  - - 30 50
}
do_execsql_test joinF-35 {
  SELECT *
  FROM t1 LEFT JOIN t2 ON true
  RIGHT JOIN t3 ON t2.y IS NOT NULL
  RIGHT JOIN t4 ON true
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
  - - 20 50
  - - 30 50
}
do_execsql_test joinF-36 {
  SELECT *
  FROM t1 LEFT JOIN t2 ON true
  RIGHT JOIN t3 ON t2.y IS NOT NULL
  RIGHT JOIN t4 ON true
  WHERE (t3.z!=400 AND t3.z!=500 AND t3.z!=600)
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
  - - 20 50
  - - 30 50
}
do_execsql_test joinF-37 {
  SELECT *
  FROM t1 RIGHT JOIN t2 ON true
  INNER JOIN t3 ON t2.y IS NOT NULL
  INNER JOIN t4 ON true
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
}
do_execsql_test joinF-38 {
  SELECT *
  FROM t1 RIGHT JOIN t2 ON true
  INNER JOIN t3 ON t2.y IS NOT NULL
  INNER JOIN t4 ON true
  WHERE (t3.z!=400 AND t3.z!=500 AND t3.z!=600)
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
}
do_execsql_test joinF-39 {
  SELECT *
  FROM t1 RIGHT JOIN t2 ON true
  INNER JOIN t3 ON t2.y IS NOT NULL
  LEFT JOIN t4 ON true
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
}
do_execsql_test joinF-40 {
  SELECT *
  FROM t1 RIGHT JOIN t2 ON true
  INNER JOIN t3 ON t2.y IS NOT NULL
  LEFT JOIN t4 ON true
  WHERE (t3.z!=400 AND t3.z!=500 AND t3.z!=600)
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
}
do_execsql_test joinF-41 {
  SELECT *
  FROM t1 RIGHT JOIN t2 ON true
  INNER JOIN t3 ON t2.y IS NOT NULL
  RIGHT JOIN t4 ON true
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
  - - - 50
}
do_execsql_test joinF-42 {
  SELECT *
  FROM t1 RIGHT JOIN t2 ON true
  INNER JOIN t3 ON t2.y IS NOT NULL
  RIGHT JOIN t4 ON true
  WHERE (t3.z!=400 AND t3.z!=500 AND t3.z!=600)
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
}
do_execsql_test joinF-43 {
  SELECT *
  FROM t1 RIGHT JOIN t2 ON true
  LEFT JOIN t3 ON t2.y IS NOT NULL
  INNER JOIN t4 ON true
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
}
do_execsql_test joinF-44 {
  SELECT *
  FROM t1 RIGHT JOIN t2 ON true
  LEFT JOIN t3 ON t2.y IS NOT NULL
  INNER JOIN t4 ON true
  WHERE (t3.z!=400 AND t3.z!=500 AND t3.z!=600)
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
}
do_execsql_test joinF-45 {
  SELECT *
  FROM t1 RIGHT JOIN t2 ON true
  LEFT JOIN t3 ON t2.y IS NOT NULL
  LEFT JOIN t4 ON true
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
}
do_execsql_test joinF-46 {
  SELECT *
  FROM t1 RIGHT JOIN t2 ON true
  LEFT JOIN t3 ON t2.y IS NOT NULL
  LEFT JOIN t4 ON true
  WHERE (t3.z!=400 AND t3.z!=500 AND t3.z!=600)
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
}
do_execsql_test joinF-47 {
  SELECT *
  FROM t1 RIGHT JOIN t2 ON true
  LEFT JOIN t3 ON t2.y IS NOT NULL
  RIGHT JOIN t4 ON true
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
  - - - 50
}
do_execsql_test joinF-48 {
  SELECT *
  FROM t1 RIGHT JOIN t2 ON true
  LEFT JOIN t3 ON t2.y IS NOT NULL
  RIGHT JOIN t4 ON true
  WHERE (t3.z!=400 AND t3.z!=500 AND t3.z!=600)
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
}
do_execsql_test joinF-49 {
  SELECT *
  FROM t1 RIGHT JOIN t2 ON true
  RIGHT JOIN t3 ON t2.y IS NOT NULL
  INNER JOIN t4 ON true
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
  - - 20 50
  - - 30 50
}
do_execsql_test joinF-50 {
  SELECT *
  FROM t1 RIGHT JOIN t2 ON true
  RIGHT JOIN t3 ON t2.y IS NOT NULL
  INNER JOIN t4 ON true
  WHERE (t3.z!=400 AND t3.z!=500 AND t3.z!=600)
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
  - - 20 50
  - - 30 50
}
do_execsql_test joinF-51 {
  SELECT *
  FROM t1 RIGHT JOIN t2 ON true
  RIGHT JOIN t3 ON t2.y IS NOT NULL
  LEFT JOIN t4 ON true
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
  - - 20 50
  - - 30 50
}
do_execsql_test joinF-52 {
  SELECT *
  FROM t1 RIGHT JOIN t2 ON true
  RIGHT JOIN t3 ON t2.y IS NOT NULL
  LEFT JOIN t4 ON true
  WHERE (t3.z!=400 AND t3.z!=500 AND t3.z!=600)
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
  - - 20 50
  - - 30 50
}
do_execsql_test joinF-53 {
  SELECT *
  FROM t1 RIGHT JOIN t2 ON true
  RIGHT JOIN t3 ON t2.y IS NOT NULL
  RIGHT JOIN t4 ON true
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
  - - 20 50
  - - 30 50
}
do_execsql_test joinF-54 {
  SELECT *
  FROM t1 RIGHT JOIN t2 ON true
  RIGHT JOIN t3 ON t2.y IS NOT NULL
  RIGHT JOIN t4 ON true
  WHERE (t3.z!=400 AND t3.z!=500 AND t3.z!=600)
  ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);
} {
  - - 20 50
  - - 30 50
}
finish_test

############################################################################
# This is the TCL script used to generate the psql script that generated
# the data above.
#
# puts "
# \\pset border off
# \\pset tuples_only on
# \\pset null -
# 
# DROP TABLE IF EXISTS t1;
# DROP TABLE IF EXISTS t2;
# DROP TABLE IF EXISTS t3;
# DROP TABLE IF EXISTS t4;
# CREATE TABLE t1(x INT);
# CREATE TABLE t2(y INT);
# CREATE TABLE t3(z INT);
# CREATE TABLE t4(w INT);
# INSERT INTO t1 VALUES(10);
# INSERT INTO t3 VALUES(20),(30);
# INSERT INTO t4 VALUES(50);
# "
# 
# proc echo {prefix txt} {
#   regsub -all {\n} $txt \n$prefix txt
#   puts "$prefix$txt"
# }
# 
# set n 0
# foreach j1 {INNER LEFT RIGHT} {
#   foreach j2 {INNER LEFT RIGHT} {
#     foreach j3 {INNER LEFT RIGHT} {
# 
# incr n
# set q1 ""
# append q1 "SELECT *\n"
# append q1 "  FROM t1 $j1 JOIN t2 ON true\n"
# append q1 "          $j2 JOIN t3 ON t2.y IS NOT NULL\n"
# append q1 "          $j3 JOIN t4 ON true\n"
# append q1 " ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);"
# 
# echo "\\qecho " "do_execsql_test joinF-$n \{"
# echo "\\qecho X  " $q1
# echo "\\qecho " "\} \{"
# puts $q1
# echo "\\qecho " "\}"
# 
# incr n
# set q1 ""
# append q1 "SELECT *\n"
# append q1 "  FROM t1 $j1 JOIN t2 ON true\n"
# append q1 "          $j2 JOIN t3 ON t2.y IS NOT NULL\n"
# append q1 "          $j3 JOIN t4 ON true\n"
# append q1 " WHERE (t3.z!=400 AND t3.z!=500 AND t3.z!=600)\n"
# append q1 " ORDER BY coalesce(t1.x,t2.y,t3.z,t4.w,0);"
# 
# echo "\\qecho " "do_execsql_test joinF-$n \{"
# echo "\\qecho X  " $q1
# echo "\\qecho " "\} \{"
# puts $q1
# echo "\\qecho " "\}"
# 
#     }
#   }
# }
#

Added test/joinH.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022 May 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 joinH

do_execsql_test 1.0 {
  CREATE TABLE t1(a INT);
  CREATE TABLE t2(b INT);
  INSERT INTO t2(b) VALUES(NULL);
}

db nullvalue NULL

do_execsql_test 1.1 {
  SELECT DISTINCT a FROM t1 FULL JOIN t2 ON true WHERE (b ISNULL);
} {NULL}
do_execsql_test 1.2 {
  SELECT a FROM t1 FULL JOIN t2 ON true;
} {NULL}
do_execsql_test 1.3 {
  SELECT a FROM t1 FULL JOIN t2 ON true WHERE (b ISNULL);
} {NULL}
do_execsql_test 1.4 {
  SELECT DISTINCT a FROM t1 FULL JOIN t2 ON true;
} {NULL}

#-----------------------------------------------------------

reset_db
do_execsql_test 2.0 {
  CREATE TABLE r3(x);
  CREATE TABLE r4(y INTEGER PRIMARY KEY);
  INSERT INTO r4 VALUES(55);
}

do_execsql_test 2.1 {
  SELECT 'value!' FROM r3 FULL JOIN r4 ON (y=x);
} {value!}

do_execsql_test 2.2 {
  SELECT 'value!' FROM r3 FULL JOIN r4 ON (y=x) WHERE +y=55;
} {value!}

#-----------------------------------------------------------
reset_db
do_execsql_test 3.1 {
  CREATE TABLE t0 (c0);
  CREATE TABLE t1 (c0);
  CREATE TABLE t2 (c0 , c1 , c2 , UNIQUE (c0), UNIQUE (c2 DESC));
  INSERT INTO t2 VALUES ('x', 'y', 'z');
  ANALYZE;
  CREATE VIEW v0(c0) AS SELECT FALSE;
}

do_catchsql_test 3.2 {
  SELECT * FROM t0 LEFT OUTER JOIN t1 ON v0.c0 INNER JOIN v0 INNER JOIN t2 ON (t2.c2 NOT NULL); 
} {1 {ON clause references tables to its right}}

#-------------------------------------------------------------

reset_db
do_execsql_test 4.1 {
  CREATE TABLE t1(a,b,c,d,e,f,g,h,PRIMARY KEY(a,b,c)) WITHOUT ROWID;
  CREATE TABLE t2(i, j);
  INSERT INTO t2 VALUES(10, 20);
}

do_execsql_test 4.2 {
  SELECT (d IS NULL) FROM t1 RIGHT JOIN t2 ON (j=33);
} {1}

do_execsql_test 4.3 {
  CREATE INDEX i1 ON t1( (d IS NULL), d );
}

do_execsql_test 4.4 {
  SELECT (d IS NULL) FROM t1 RIGHT JOIN t2 ON (j=33);
} {1}


finish_test

Changes to test/journal3.test.

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
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







+
+
+
+





-
+











-
+







   1 00644
   2 00666
   3 00600
   4 00755
  } {
    db close
    #set effective [format %.5o [expr $permissions & ~$umask]]
    set res "/[regsub {^00} $permissions {0.}]/"
    if {$tcl_version>=8.7} {
       regsub {^00} $permissions {0o} permissions
    }
    set effective $permissions
    do_test journal3-1.2.$tn.1 {
      catch { forcedelete test.db-journal }
      file attributes test.db -permissions $permissions
      file attributes test.db -permissions
    } $permissions
    } $res
    do_test journal3-1.2.$tn.2 { file exists test.db-journal } {0}
    do_test journal3-1.2.$tn.3 {
      sqlite3 db test.db
      execsql { 
        BEGIN;
          INSERT INTO tx DEFAULT VALUES;
      }
      file exists test.db-journal
    } {1}
    do_test journal3-1.2.$tn.4 {
      file attr test.db-journal -perm
    } $effective
    } $res
    do_execsql_test journal3-1.2.$tn.5 { ROLLBACK } {}
  }


}

finish_test

Changes to test/jrnlmode.test.

61
62
63
64
65
66
67
68










69
70
71
72
73
74
75
61
62
63
64
65
66
67

68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84







-
+
+
+
+
+
+
+
+
+
+







do_test jrnlmode-1.2 {
  execsql {
    PRAGMA journal_mode;
    PRAGMA main.journal_mode;
    PRAGMA temp.journal_mode;
  } 
} [list persist persist [temp_journal_mode persist]]
do_test jrnlmode-1.4 {
do_test jrnlmode-1.4a {
  # When defensive is on, unable to set journal_mode to OFF
  sqlite3_db_config db DEFENSIVE 1
  execsql {
    PRAGMA journal_mode = off;
  } 
} {persist}
do_test jrnlmode-1.4b {
  # When defensive is on, unable to set journal_mode to OFF
  sqlite3_db_config db DEFENSIVE 0
  execsql {
    PRAGMA journal_mode = off;
  } 
} {off}
do_test jrnlmode-1.5 {
  execsql {
    PRAGMA journal_mode;

Changes to test/json101.test.

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
11
12
13
14
15
16
17





18
19
20
21
22
23
24







-
-
-
-
-







# This file implements tests for JSON SQL functions extension to the
# SQLite library.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable !json1 {
  finish_test
  return
}

do_execsql_test json101-1.1.00 {
  SELECT json_array(1,2.5,null,'hello');
} {[1,2.5,null,"hello"]}
do_execsql_test json101-1.1.01 {
  SELECT json_array(1,'{"abc":2.5,"def":null,"ghi":hello}',99);
  -- the second term goes in as a string:
} {[1,"{\\"abc\\":2.5,\\"def\\":null,\\"ghi\\":hello}",99]}
827
828
829
830
831
832
833
834


























































835
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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

} {a 1 integer 1 2 {} {$.a} {$} b 2 integer 2 4 {} {$.b} {$}}
do_execsql_test json-15.120 {
  SELECT * FROM (JSON_EACH('{"a":1, "b":2}'));
} {a 1 integer 1 2 {} {$.a} {$} b 2 integer 2 4 {} {$.b} {$}}
do_execsql_test json-15.130 {
  SELECT xyz.* FROM (JSON_EACH('{"a":1, "b":2}')) AS xyz;
} {a 1 integer 1 2 {} {$.a} {$} b 2 integer 2 4 {} {$.b} {$}}

# 2019-11-10
# Mailing list bug report on the handling of surrogate pairs
# in JSON.
#
do_execsql_test json-16.10 {
  SELECT length(json_extract('"abc\uD834\uDD1Exyz"','$'));
} {7}
do_execsql_test json-16.20 {
  SELECT length(json_extract('"\uD834\uDD1E"','$'));
} {1}
do_execsql_test json-16.30 {
  SELECT unicode(json_extract('"\uD834\uDD1E"','$'));
} {119070}

# 2022-01-30 dbsqlfuzz 4678cf825d27f87c9b8343720121e12cf944b71a
do_execsql_test json-17.1 {
  DROP TABLE IF EXISTS t1;
  DROP TABLE IF EXISTS t2;
  CREATE TABLE t1(a,b,c);
  CREATE TABLE t2(d);
  SELECT * FROM t1 LEFT JOIN t2 ON (SELECT b FROM json_each ORDER BY 1);
} {}

# 2022-04-04 forum post https://sqlite.org/forum/forumpost/c082aeab43
do_execsql_test json-18.1 {
  SELECT json_valid('{"":5}');
} {1}
do_execsql_test json-18.2 {
  SELECT json_extract('{"":5}', '$.""');
} {5}
do_execsql_test json-18.3 {
  SELECT json_extract('[3,{"a":4,"":[5,{"hi":6},7]},8]', '$[1].""[1].hi');
} {6}
do_execsql_test json-18.4 {
  SELECT json_extract('[3,{"a":4,"":[5,{"hi":6},7]},8]', '$[1].""[1]."hi"');
} {6}
do_catchsql_test json-18.5 {
  SELECT json_extract('{"":8}', '$.');
} {1 {JSON path error near ''}}

# 2022-08-29 https://sqlite.org/forum/forumpost/9b9e4716c0d7bbd1
# This is not a problem specifically with JSON functions.  It is
# a problem with transaction control.  But the json() function makes
# the problem more easily accessible, so it is tested here.
#
do_execsql_test json-19.1 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(x);
} {}
do_catchsql_test json-19.2 {
  BEGIN;
  INSERT INTO t1 VALUES(0), (json('not-valid-json'));
} {1 {malformed JSON}}
do_execsql_test json-19.3 {
  COMMIT;
  SELECT * FROM t1;
} {}

finish_test

Changes to test/json102.test.

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
14
15
16
17
18
19
20





21
22
23
24
25
26
27







-
-
-
-
-







# This file contains tests automatically generated from the json1
# documentation.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable !json1 {
  finish_test
  return
}

do_execsql_test json102-100 {
  SELECT json_object('ex','[52,3.14159]');
} {{{"ex":"[52,3.14159]"}}}
do_execsql_test json102-110 {
  SELECT json_object('ex',json('[52,3.14159]'));
} {{{"ex":[52,3.14159]}}}
do_execsql_test json102-120 {
332
333
334
335
336
337
338
339
























































340
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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


# All control characters are escaped
#
do_execsql_test json102-1501 {
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<0x1f)
  SELECT sum(json_valid(json_quote('a'||char(x)||'z'))) FROM c ORDER BY x;
} {31}

# 2022-01-10 tests for -> and ->> operators
#
reset_db
do_execsql_test json102-1600 {
  CREATE TABLE t1(id INTEGER PRIMARY KEY, x JSON);
  INSERT INTO t1(id,x) VALUES
   (1, '{"a":null}'),
   (2, '{"a":123}'),
   (3, '{"a":4.5}'),
   (4, '{"a":"six"}'),
   (5, '{"a":[7,8]}'),
   (6, '{"a":{"b":9}}'),
   (7, '{"b":999}');
  SELECT
    id,
    x->'a' AS '->',
    CASE WHEN subtype(x->'a') THEN 'json' ELSE typeof(x->'a') END AS 'type',
    x->>'a' AS '->>',
    CASE WHEN subtype(x->>'a') THEN 'json' ELSE typeof(x->>'a') END AS 'type',
    json_extract(x,'$.a') AS 'json_extract',
    CASE WHEN subtype(json_extract(x,'$.a'))
         THEN 'json' ELSE typeof(json_extract(x,'$.a')) END AS 'type'
    FROM t1 ORDER BY id;
} [list \
  1 null      json {}        null     {}        null          \
  2 123       json 123       integer  123       integer       \
  3 4.5       json 4.5       real     4.5       real          \
  4 {"six"}   json six       text     six       text          \
  5 {[7,8]}   json {[7,8]}   text     {[7,8]}   json          \
  6 {{"b":9}} json {{"b":9}} text     {{"b":9}} json          \
  7 {}        null {}        null     {}        null
]
do_execsql_test json102-1610 {
  DELETE FROM t1;
  INSERT INTO t1(x) VALUES('[null,123,4.5,"six",[7,8],{"b":9}]');
  WITH c(y) AS (VALUES(0),(1),(2),(3),(4),(5),(6))
  SELECT
    y,
    x->y AS '->',
    CASE WHEN subtype(x->y) THEN 'json' ELSE typeof(x->y) END AS 'type',
    x->>y AS '->>',
    CASE WHEN subtype(x->>y) THEN 'json' ELSE typeof(x->>y) END AS 'type',
    json_extract(x,format('$[%d]',y)) AS 'json_extract',
    CASE WHEN subtype(json_extract(x,format('$[%d]',y)))
      THEN 'json' ELSE typeof(json_extract(x,format('$[%d]',y))) END AS 'type'
  FROM c, t1 ORDER BY y;    
} [list \
  0 null      json {}        null    {}        null       \
  1 123       json 123       integer 123       integer    \
  2 4.5       json 4.5       real    4.5       real       \
  3 {"six"}   json six       text    six       text       \
  4 {[7,8]}   json {[7,8]}   text    {[7,8]}   json       \
  5 {{"b":9}} json {{"b":9}} text    {{"b":9}} json       \
  6 {}        null {}        null    {}        null
]

finish_test

Changes to test/json103.test.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
10
11
12
13
14
15
16





17
18
19
20
21
22
23







-
-
-
-
-







#***********************************************************************
# This file implements tests for JSON aggregate SQL functions
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable !json1 {
  finish_test
  return
}

do_execsql_test json103-100 {
  CREATE TABLE t1(a,b,c);
  WITH RECURSIVE c(x) AS (VALUES(1) UNION SELECT x+1 FROM c WHERE x<100)
  INSERT INTO t1(a,b,c) SELECT x, x%3, printf('n%d',x)  FROM c;
  UPDATE t1 SET a='orange' WHERE rowid=39;
  UPDATE t1 SET a=32.5 WHERE rowid=31;
  UPDATE t1 SET a=x'303132' WHERE rowid=29;

Changes to test/json104.test.

9
10
11
12
13
14
15
16

17
18
19
20
21
22
23
24
25
26
27
9
10
11
12
13
14
15

16




17
18
19
20
21
22
23







-
+
-
-
-
-







#
#***********************************************************************
# This file implements tests for json_patch(A,B) SQL function.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

set testprefix json104
ifcapable !json1 {
  finish_test
  return
}

# This is the example from pages 2 and 3 of RFC-7396
do_execsql_test json104-100 {
  SELECT json_patch('{
       "a": "b",
       "c": {
         "d": "e",
120
121
122
123
124
125
126



127
























128
129
130
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







+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



} {{{"e":null,"a":1}}}
do_execsql_test json104-313 {
  SELECT json_patch('[1,2]','{"a":"b","c":null}');
} {{{"a":"b"}}}
do_execsql_test json104-314 {
  SELECT json_patch('{}','{"a":{"bb":{"ccc":null}}}');
} {{{"a":{"bb":{}}}}}
do_execsql_test json104-320 {
  SELECT json_patch('{"x":{"one":1}}','{"x":{"two":2},"x":"three"}');
} {{{"x":"three"}}}

#-------------------------------------------------------------------------

do_execsql_test 401 {
  CREATE TABLE obj(x);
  INSERT INTO obj VALUES('{"a":1,"b":2}');
  SELECT * FROM obj;
} {{{"a":1,"b":2}}}
do_execsql_test 402 {
  UPDATE obj SET x = json_insert(x, '$.c', 3);
  SELECT * FROM obj;
} {{{"a":1,"b":2,"c":3}}}
do_execsql_test 403 {
  SELECT json_extract(x, '$.b') FROM obj;
  SELECT json_extract(x, '$."b"') FROM obj;
} {2 2}
do_execsql_test 404 {
  UPDATE obj SET x = json_set(x, '$."b"', 555);
  SELECT json_extract(x, '$.b') FROM obj;
  SELECT json_extract(x, '$."b"') FROM obj;
} {555 555}
do_execsql_test 405 {
  UPDATE obj SET x = json_set(x, '$."d"', 4);
  SELECT json_extract(x, '$."d"') FROM obj;
} {4}


finish_test

Added test/json105.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019-11-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 tests for "[#]" extension to json-path
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix json104

# This is the example from pages 2 and 3 of RFC-7396
db eval {
  CREATE TABLE t1(j);
  INSERT INTO t1(j) VALUES('{"a":1,"b":[1,[2,3],4],"c":99}');
}
proc json_extract_test {testnum path result} {
  do_execsql_test json105-1.$testnum "SELECT quote(json_extract(j,$path)) FROM t1" $result
}
json_extract_test 10 {'$.b[#]'}   NULL
json_extract_test 20 {'$.b[#-1]'} 4
json_extract_test 30 {'$.b[#-2]'} {'[2,3]'}
json_extract_test 31 {'$.b[#-02]'} {'[2,3]'}
json_extract_test 40 {'$.b[#-3]'} 1
json_extract_test 50 {'$.b[#-4]'} NULL
json_extract_test 60 {'$.b[#-2][#-1]'} 3
json_extract_test 70 {'$.b[0]','$.b[#-1]'} {'[1,4]'}

json_extract_test 100 {'$.a[#-1]'} NULL
json_extract_test 110 {'$.b[#-000001]'} 4

proc json_remove_test {testnum path result} {
  do_execsql_test json105-2.$testnum "SELECT quote(json_remove(j,$path)) FROM t1" $result
}
json_remove_test 10 {'$.b[#]'}    {'{"a":1,"b":[1,[2,3],4],"c":99}'}
json_remove_test 20 {'$.b[#-0]'}  {'{"a":1,"b":[1,[2,3],4],"c":99}'}
json_remove_test 30 {'$.b[#-1]'}  {'{"a":1,"b":[1,[2,3]],"c":99}'}
json_remove_test 40 {'$.b[#-2]'}  {'{"a":1,"b":[1,4],"c":99}'}
json_remove_test 50 {'$.b[#-3]'}  {'{"a":1,"b":[[2,3],4],"c":99}'}
json_remove_test 60 {'$.b[#-4]'}  {'{"a":1,"b":[1,[2,3],4],"c":99}'}
json_remove_test 70 {'$.b[#-2][#-1]'}  {'{"a":1,"b":[1,[2],4],"c":99}'}

json_remove_test 100 {'$.b[0]','$.b[#-1]'} {'{"a":1,"b":[[2,3]],"c":99}'}
json_remove_test 110 {'$.b[#-1]','$.b[0]'} {'{"a":1,"b":[[2,3]],"c":99}'}
json_remove_test 120 {'$.b[#-1]','$.b[#-2]'} {'{"a":1,"b":[[2,3]],"c":99}'}
json_remove_test 130 {'$.b[#-1]','$.b[#-1]'} {'{"a":1,"b":[1],"c":99}'}
json_remove_test 140 {'$.b[#-2]','$.b[#-1]'} {'{"a":1,"b":[1],"c":99}'}

proc json_insert_test {testnum x result} {
  do_execsql_test json105-3.$testnum "SELECT quote(json_insert(j,$x)) FROM t1" $result
}
json_insert_test 10 {'$.b[#]','AAA'} {'{"a":1,"b":[1,[2,3],4,"AAA"],"c":99}'}
json_insert_test 20 {'$.b[1][#]','AAA'} {'{"a":1,"b":[1,[2,3,"AAA"],4],"c":99}'}
json_insert_test 30 {'$.b[1][#]','AAA','$.b[#]','BBB'} \
     {'{"a":1,"b":[1,[2,3,"AAA"],4,"BBB"],"c":99}'}
json_insert_test 40 {'$.b[#]','AAA','$.b[#]','BBB'} \
     {'{"a":1,"b":[1,[2,3],4,"AAA","BBB"],"c":99}'}

proc json_set_test {testnum x result} {
  do_execsql_test json105-4.$testnum "SELECT quote(json_set(j,$x)) FROM t1" $result
}
json_set_test 10 {'$.b[#]','AAA'} {'{"a":1,"b":[1,[2,3],4,"AAA"],"c":99}'}
json_set_test 20 {'$.b[1][#]','AAA'} {'{"a":1,"b":[1,[2,3,"AAA"],4],"c":99}'}
json_set_test 30 {'$.b[1][#]','AAA','$.b[#]','BBB'} \
     {'{"a":1,"b":[1,[2,3,"AAA"],4,"BBB"],"c":99}'}
json_set_test 40 {'$.b[#]','AAA','$.b[#]','BBB'} \
     {'{"a":1,"b":[1,[2,3],4,"AAA","BBB"],"c":99}'}
json_set_test 50 {'$.b[#-1]','AAA'} {'{"a":1,"b":[1,[2,3],"AAA"],"c":99}'}
json_set_test 60 {'$.b[1][#-1]','AAA'} {'{"a":1,"b":[1,[2,"AAA"],4],"c":99}'}
json_set_test 70 {'$.b[1][#-1]','AAA','$.b[#-1]','BBB'} \
     {'{"a":1,"b":[1,[2,"AAA"],"BBB"],"c":99}'}
json_set_test 80 {'$.b[#-1]','AAA','$.b[#-1]','BBB'} \
     {'{"a":1,"b":[1,[2,3],"BBB"],"c":99}'}

proc json_replace_test {testnum x result} {
  do_execsql_test json105-5.$testnum "SELECT quote(json_replace(j,$x)) FROM t1" $result
}
json_replace_test 10 {'$.b[#]','AAA'} {'{"a":1,"b":[1,[2,3],4],"c":99}'}
json_replace_test 20 {'$.b[1][#]','AAA'} {'{"a":1,"b":[1,[2,3],4],"c":99}'}
json_replace_test 30 {'$.b[1][#]','AAA','$.b[#]','BBB'} \
     {'{"a":1,"b":[1,[2,3],4],"c":99}'}
json_replace_test 40 {'$.b[#]','AAA','$.b[#]','BBB'} \
     {'{"a":1,"b":[1,[2,3],4],"c":99}'}
json_replace_test 50 {'$.b[#-1]','AAA'} {'{"a":1,"b":[1,[2,3],"AAA"],"c":99}'}
json_replace_test 60 {'$.b[1][#-1]','AAA'} {'{"a":1,"b":[1,[2,"AAA"],4],"c":99}'}
json_replace_test 70 {'$.b[1][#-1]','AAA','$.b[#-1]','BBB'} \
     {'{"a":1,"b":[1,[2,"AAA"],"BBB"],"c":99}'}
json_replace_test 80 {'$.b[#-1]','AAA','$.b[#-1]','BBB'} \
     {'{"a":1,"b":[1,[2,3],"BBB"],"c":99}'}

do_catchsql_test json105-6.10 {
  SELECT json_extract(j, '$.b[#-]') FROM t1;
} {1 {JSON path error near '[#-]'}}
do_catchsql_test json105-6.20 {
  SELECT json_extract(j, '$.b[#9]') FROM t1;
} {1 {JSON path error near '[#9]'}}
do_catchsql_test json105-6.30 {
  SELECT json_extract(j, '$.b[#+2]') FROM t1;
} {1 {JSON path error near '[#+2]'}}
do_catchsql_test json105-6.40 {
  SELECT json_extract(j, '$.b[#-1') FROM t1;
} {1 {JSON path error near '[#-1'}}
do_catchsql_test json105-6.50 {
  SELECT json_extract(j, '$.b[#-1x]') FROM t1;
} {1 {JSON path error near '[#-1x]'}}

finish_test

Changes to test/kvtest.c.

903
904
905
906
907
908
909
910

911
912
913
914
915
916
917
903
904
905
906
907
908
909

910
911
912
913
914
915
916
917







-
+







      continue;
    }
    fatalError("unknown option: \"%s\"", argv[i]);
  }
  if( eType==PATH_DB ){
    /* Recover any prior crashes prior to starting the timer */
    sqlite3_open(zDb, &db);
    sqlite3_exec(db, "SELECT rowid FROM sqlite_master LIMIT 1", 0, 0, 0);
    sqlite3_exec(db, "SELECT rowid FROM sqlite_schema LIMIT 1", 0, 0, 0);
    sqlite3_close(db);
    db = 0;
  }
  tmStart = timeOfDay();
  if( eType==PATH_DB ){
    char *zSql;
    rc = sqlite3_open(zDb, &db);

Changes to test/like.test.

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







+







# in particular the optimizations that occur to help those operators
# run faster.
#
# $Id: like.test,v 1.13 2009/06/07 23:45:11 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix like

# Create some sample data to work with.
#
do_test like-1.0 {
  execsql {
    CREATE TABLE t1(x TEXT);
  }
163
164
165
166
167
168
169
170
171


172
173
174


175
176

177
178
179
180
181
182
183
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.
721
722
723
724
725
726
727
728

729
730
731
732
733
734
735
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 {}}
1031
1032
1033
1034
1035
1036
1037

1038
1039


1040
1041
1042
1043
1044
1045

1046
1047


1048
1049
1050
1051
1052
1053
1054
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.
#
1090
1091
1092
1093
1094
1095
1096
1097










































1098
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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  SELECT y FROM t15 WHERE x LIKE '/%bc%' ESCAPE '/';
} {22}
do_execsql_test like-15.121 {
  EXPLAIN QUERY PLAN
  SELECT y FROM t15 WHERE x LIKE '/%bc%' ESCAPE '/';
} {/SEARCH/}
}

#-------------------------------------------------------------------------
# Tests for ticket [b1d8c79314].
#
reset_db
do_execsql_test 16.0 {
  CREATE TABLE t1(a INTEGER COLLATE NOCASE);
  CREATE INDEX i1 ON t1(a);
  INSERT INTO t1 VALUES(' 1x');
  INSERT INTO t1 VALUES(' 1-');
}
do_execsql_test 16.1 {
  SELECT * FROM t1 WHERE a LIKE ' 1%';
} {{ 1x} { 1-}}
do_execsql_test 16.2 {
  SELECT * FROM t1 WHERE a LIKE ' 1-';
} {{ 1-}}

# 2020-03-19
# The ESCAPE clause on LIKE takes precedence over wildcards
#
do_execsql_test 17.0 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(id INTEGER PRIMARY KEY, x TEXT);
  INSERT INTO t1 VALUES
    (1,'abcde'),
    (2,'abc_'),
    (3,'abc__'),
    (4,'abc%'),
    (5,'abc%%');
  SELECT id FROM t1 WHERE x LIKE 'abc%%' ESCAPE '%';
} {4}
do_execsql_test 17.1 {
  SELECT id FROM t1 WHERE x LIKE 'abc__' ESCAPE '_';
} {2}

# 2021-02-15 ticket c0aeea67d58ae0fd
#
do_execsql_test 17.1 {
  SELECT 'x' LIKE '%' ESCAPE '_';
} {1}


finish_test

Changes to test/like2.test.

1001
1002
1003
1004
1005
1006
1007








1008
1009
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017







+
+
+
+
+
+
+
+


do_test like-2.126.2 {
  db eval "SELECT x FROM t2 WHERE y LIKE '~%'"
} {126}
do_test like-2.126.3 {
  db eval "SELECT x FROM t3 WHERE y LIKE 'abc~%'"
} {126}


do_test like-3.1 {
  db eval "SELECT '\u01C0' LIKE '%\x80'"
} {0}
do_test like-3.2 {
  db eval "SELECT '\u0080' LIKE '%\x80'"
} {1}


finish_test

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
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







-
+









-
+









-
+








-
+











-
+








-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



  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);
  CREATE INDEX t5c_0 ON t5c(c0 COLLATE NOCASE);
  INSERT INTO t5c(rowid, c0) VALUES (99,'+/');
  SELECT * FROM t5c WHERE (c0 LIKE '+/');
} {+/}

# 2019-05-08
# Yet another case for the above from Manuel Rigger.
#
do_execsql_test like3-5.400 {
  DROP TABLE IF EXISTS t0;
  CREATE TABLE t0(c0 INT UNIQUE COLLATE NOCASE);
  INSERT INTO t0(c0) VALUES ('./');
  SELECT * FROM t0 WHERE t0.c0 LIKE './';
} {./}

# 2019-06-14
# Ticket https://www.sqlite.org/src/info/ce8717f0885af975
do_execsql_test like3-5.410 {
  DROP TABLE IF EXISTS t0;
  CREATE TABLE t0(c0 INT UNIQUE COLLATE NOCASE);
  INSERT INTO t0(c0) VALUES ('.1%');
  SELECT * FROM t0 WHERE t0.c0 LIKE '.1%';
} {.1%}

# 2019-09-03
# Ticket https://www.sqlite.org/src/info/0f0428096f
do_execsql_test like3-5.420 {
  DROP TABLE IF EXISTS t0;
  CREATE TABLE t0(c0 UNIQUE);
  INSERT INTO t0(c0) VALUES(-1);
  SELECT * FROM t0 WHERE t0.c0 GLOB '-*';
} {-1}
do_execsql_test like3-5.421 {
  SELECT t0.c0 GLOB '-*' FROM t0;
} {1}



# 2019-02-27
# Verify that the LIKE optimization works with an ESCAPE clause when
# using PRAGMA case_sensitive_like=ON.
#
ifcapable !icu {
do_execsql_test like3-6.100 {
  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 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 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 t2 USING INDEX t2path (path>? AND path<?)
}
do_eqp_test like3-6.220 {
  SELECT * FROM t2 WHERE path LIKE 'a%' ESCAPE '\';
} {
  QUERY PLAN
  `--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 t2 USING INDEX t2path2 (path>? AND path<?)
}
do_eqp_test like3-6.240 {
  SELECT * FROM t2 WHERE path LIKE 'a%' ESCAPE '\';
} {
  QUERY PLAN
  `--SEARCH t2 USING INDEX t2path2 (path>? AND path<?)
}
}

finish_test

Changes to test/limit.test.

637
638
639
640
641
642
643























644
645
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


do_execsql_test limit-14.6 {
  SELECT 123 LIMIT -1 OFFSET 0
} {123}
do_execsql_test limit-14.7 {
  SELECT 123 LIMIT -1 OFFSET 1
} {}

# 2021-03-05 dbsqlfuzz crash-d811039c9f44f2d43199d5889fcf4085ef6221b9
#
reset_db
do_execsql_test limit-15.1 {
  CREATE TABLE t1(a PRIMARY KEY, b TEXT);
  CREATE TABLE t4(c PRIMARY KEY, d);
  CREATE TABLE t5(e PRIMARY KEY, f);
  CREATE TABLE t6(g, h);
  CREATE TABLE t3_a(k, v);
  CREATE TABLE t3_b(k, v);
  CREATE VIEW t3 AS SELECT * FROM t3_a UNION ALL SELECT * FROM t3_b;
  INSERT INTO t5(e,f) VALUES(500000,'orange');
  INSERT INTO t4(c,d) VALUES(300000,'blue'),(400,'green'),(8000,'grey');
  INSERT INTO t1(a,b) VALUES(300000,'purple');
  INSERT INTO t3_a VALUES(300000,'yellow'),(500,'pink'),(8000,'red');
  INSERT INTO t6 default values;
  SELECT (
      SELECT 100000 FROM
          (SELECT 200000 FROM t6 WHERE a = ( SELECT 300000 FROM t3 WHERE a ) ),
          (SELECT 400000 FROM t5 WHERE e=500000),
          (SELECT 600000 FROM t4 WHERE c=a)
  ) FROM t1;
} {100000}

finish_test

Changes to test/lock_common.tcl.

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
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







-
+





-
-
+


-

+
+
+
+







# This file contains code used by several different test scripts. The
# code in this file allows testfixture to control another process (or
# processes) to test locking.
#

proc do_multiclient_test {varname script} {

  foreach code [list {
  foreach {tn code} [list 1 {
    if {[info exists ::G(valgrind)]} { db close ; continue }
    set ::code2_chan [launch_testfixture]
    set ::code3_chan [launch_testfixture]
    proc code2 {tcl} { testfixture $::code2_chan $tcl }
    proc code3 {tcl} { testfixture $::code3_chan $tcl }
    set tn 1
  } {
  } 2 {
    proc code2 {tcl} { uplevel #0 $tcl }
    proc code3 {tcl} { uplevel #0 $tcl }
    set tn 2
  }] {
    # Do not run multi-process tests with the unix-excl VFS.
    #
    if {$tn==1 && [permutation]=="unix-excl"} continue

    faultsim_delete_and_reopen

    proc code1 {tcl} { uplevel #0 $tcl }
  
    # Open connections [db2] and [db3]. Depending on which iteration this
    # is, the connections may be created in this interpreter, or in 
    # interpreters running in other OS processes. As such, the [db2] and [db3]

Changes to test/mallocA.test.

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
92
93
94
95
96
97
98


















99
100
101
102
103
104
105







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







  faultsim_test_result [list 0 2]
}
do_faultsim_test 6.2 -faults oom* -body {
  execsql { SELECT rowid FROM t1 WHERE a='abc' AND b<'y' }
} -test {
  faultsim_test_result [list 0 {1 2}]
}
ifcapable stat3 {
  do_test 6.3-prep {
    execsql {
      PRAGMA writable_schema = 1;
      CREATE TABLE sqlite_stat4 AS 
      SELECT tbl, idx, neq, nlt, ndlt, sqlite_record(sample) AS sample 
      FROM sqlite_stat3;
    }
  } {}
  do_faultsim_test 6.3 -faults oom* -body {
    execsql { 
      ANALYZE sqlite_master;
      SELECT rowid FROM t1 WHERE a='abc' AND b<'y';
    }
  } -test {
    faultsim_test_result [list 0 {1 2}]
  }
}

do_execsql_test 7.0 {
  PRAGMA cache_size = 5;
}
do_faultsim_test 7 -faults oom-trans* -prep {
} -body {
  execsql {

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/malloc_common.tcl.

660
661
662
663
664
665
666

667
668
669
670
671
672
673
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674







+







  set cksumsql "SELECT md5sum([join [concat rowid $V(*)] ,]) FROM $tbl"

  # Calculate the initial table checksum.
  set cksum1 [db one $cksumsql]

  if {$::DO_MALLOC_TEST } {
    set answers [list {1 {out of memory}} {0 {}}]
    lappend answers [list 1 {unable to open a temporary database file for storing temporary tables}]
    if {$::DO_MALLOC_TEST==1} {
      set modes {100000 persistent}
    } else {
      set modes {1 transient}
    }
  } else {
    set answers [list {0 {}}]

Changes to test/malloctraceviewer.tcl.

43
44
45
46
47
48
49
50

51
52
53
54
55
56
57
43
44
45
46
47
48
49

50
51
52
53
54
55
56
57







-
+







proc populate_text_widget {db} {
  $::O(text) configure -state normal
  set id [lindex [$::O(tree) selection] 0]
  set frame [lindex $id end]

  set line [$db one {SELECT line FROM frame WHERE frame = $frame}]
  if {$line ne ""} {
    foreach {file line} [split $line :] {}
    regexp {^([^:]*):([0-9]*)} $line -> file line
    set content [$db one "SELECT content FROM file WHERE name = '$file'"]
    $::O(text) delete 0.0 end

    set iLine 1
    foreach L [split $content "\n"] {
      if {$iLine == $line} {
        $::O(text) insert end "$L\n" highlight

Changes to test/memdb1.test.

67
68
69
70
71
72
73

























74
75
76
77
78
79
80
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  DROP TABLE t2;
  PRAGMA page_count;
} {116}
do_execsql_test 140 {
  VACUUM;
  PRAGMA page_count;
} {2}

do_test 150 {
  catch {db deserialize -unknown 1 $db1} msg
  set msg
} {unknown option: -unknown}
do_test 151 {
  db deserialize -readonly 1 $db1
  db eval {SELECT * FROM t1}
} {1 2}
do_test 152 {
  catchsql {INSERT INTO t1 VALUES(3,4);}
} {1 {attempt to write a readonly database}}

breakpoint
do_test 160 {
  db deserialize -maxsize 32768 $db1
  db eval {SELECT * FROM t1}
} {1 2}
do_test 161 {
  db eval {INSERT INTO t1 VALUES(3,4); SELECT * FROM t1}
} {1 2 3 4}
do_test 162 {
  catchsql {INSERT INTO t1 VALUES(5,randomblob(100000))}
} {1 {database or disk is full}}


# Build a largish on-disk database and serialize it.  Verify that the
# serialization works.
#
db close
forcedelete test.db
sqlite3 db test.db
128
129
130
131
132
133
134










135
136
137
138
139
140
141
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]
150
151
152
153
154
155
156
157

158
159
160
161
162








































































163
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







-
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

do_test 600 {
  set rc [catch {db deserialize} msg]
  lappend rc $msg
} {1 {wrong # args: should be "db deserialize ?DATABASE? VALUE"}}
do_test 610 {
  set rc [catch {db deserialize a b c} msg]
  lappend rc $msg
} {1 {wrong # args: should be "db deserialize ?DATABASE? VALUE"}}
} {1 {unknown option: a}}
do_test 620 {
  set rc [catch {db serialize a b} msg]
  lappend rc $msg
} {1 {wrong # args: should be "db serialize ?DATABASE?"}}

# 2021-07-19 https://sqlite.org/forum/forumpost/e1cbb5f450b98aa6
# The TEMP database cannot participate in serialization or
# deserialization.
#
reset_db
do_test 650 {
  db eval {
    CREATE TEMP TABLE t0(a);
    CREATE TABLE t1(x);
    WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<1000)
    INSERT INTO t1(x) SELECT random() FROM c;
  }
  set rc [catch {db deserialize temp [db serialize main]} err]
  lappend rc err
} {1 err}

#-------------------------------------------------------------------------
ifcapable vtab {
  reset_db
  do_execsql_test 700 {
    CREATE TABLE t1(a, b);
    PRAGMA schema_version = 0;
  }
  do_test 710 {
    set ser [db serialize main]
    db close
    sqlite3 db
    db deserialize main $ser
    catchsql {
      CREATE VIRTUAL TABLE t1 USING rtree(id, a, b, c, d);
    }
  } {1 {table t1 already exists}}
}


#-------------------------------------------------------------------------
# dbsqlfuzz  0a13dfb474d4f2f11a48a2ea57075c96fb456dd7
#
if {[wal_is_capable]} {
  reset_db
  do_execsql_test 800 {
    PRAGMA auto_vacuum = 0;
    PRAGMA page_size = 8192;
    PRAGMA journal_mode = wal;
    CREATE TABLE t1(x, y);
    INSERT INTO t1 VALUES(1, 2);
    CREATE TABLE t2(x, y);
  } {wal}
  db close
  
  set fd [open test.db]
  fconfigure $fd -translation binary -encoding binary
  set data [read $fd [expr 20*1024]]
  
  sqlite3 db ""
  db deserialize $data
  
  do_execsql_test 810 {
    PRAGMA locking_mode = exclusive;
    SELECT * FROM t1
  } {exclusive 1 2}
  
  do_execsql_test 820 {
    INSERT INTO t1 VALUES(3, 4);
    SELECT * FROM t1;
  } {1 2 3 4}
  
  do_catchsql_test 830 {
    PRAGMA wal_checkpoint;
  } {1 {database disk image is malformed}}
}

finish_test

Added test/memdb2.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022-12-05
#
# 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 the "memdb" VFS
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix memdb2
do_not_use_codec

ifcapable !deserialize {
  finish_test
  return
}

db close

#-------------------------------------------------------------------------
# Test that when using a memdb database, it is not possible to upgrade
# to an EXCLUSIVE lock if some other client is holding SHARED.
#
foreach {tn fname} {
    1   file:/test.db?vfs=memdb
    2   file:\\test.db?vfs=memdb
} {
  if {$tn==2} breakpoint
  sqlite3 db  $fname -uri 1
  sqlite3 db2 $fname -uri 1

  
  do_execsql_test 1.$tn.1 {
    CREATE TABLE t1(x, y);
    INSERT INTO t1 VALUES(1, 2);
  }
  
  do_execsql_test -db db2 1.$tn.2 {
    BEGIN;
      SELECT * FROM t1;
  } {1 2}
  
  do_execsql_test 1.$tn.3 {
    BEGIN;
      INSERT INTO t1 VALUES(3, 4);
  }
  
  do_catchsql_test 1.$tn.4 {
    COMMIT
  } {1 {database is locked}}
  
  do_execsql_test -db db2 1.$tn.5 {
      SELECT * FROM t1;
    END;
  } {1 2}
  
  do_execsql_test 1.$tn.6 {
    COMMIT
  } {}
  
  do_execsql_test -db db2 1.$tn.7 {
    SELECT * FROM t1
  } {1 2 3 4}
  
  db close
  db2 close
}

finish_test

Added test/memjournal.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2021 May 24
#
# 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.
#
#***********************************************************************
# Tests focused on the in-memory journal.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/malloc_common.tcl
set testprefix memjournal


do_execsql_test 1.0 {
  PRAGMA journal_mode = memory;
  CREATE TABLE t1(a);
} {memory}

set nRow [expr 1]

do_execsql_test 1.1 {
  BEGIN;
    INSERT INTO t1 VALUES( randomblob(500) );
} {}

do_test 1.2 {
  for {set i 1} {$i <= 500} {incr i} {
    execsql {
      SAVEPOINT one;
      UPDATE t1 SET a=randomblob(500);
    }
    execsql { SAVEPOINT abc } 
    execsql { UPDATE t1 SET a=randomblob(500) WHERE rowid<=$i AND 0 }
    execsql { RELEASE abc }
  } 
} {}

do_execsql_test 1.3 {
  COMMIT;
}

finish_test

Added test/memjournal2.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022 Jan 01
#
# 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.
#
#***********************************************************************
# Tests focused on the in-memory journal.
#
# TESTRUNNER: slow

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/malloc_common.tcl
set testprefix memjournal2

do_execsql_test 1.0 {
  PRAGMA journal_mode = memory;
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b UNIQUE);
} {memory}

set nRow [expr 2000]

do_execsql_test 1.1 {
  BEGIN;
    WITH s(i) AS (
      SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<$nRow
    )
    INSERT INTO t1 SELECT NULL, randomblob(700) FROM s;
}

for {set jj 200} {$jj <= 300} {incr jj} {
  do_execsql_test 1.2.$jj.1 {
    SAVEPOINT one; 
      UPDATE t1 SET b=randomblob(700) WHERE a<=$jj;
  }
  do_execsql_test 1.2.$jj.2 {
      SAVEPOINT two;
        UPDATE t1 SET b=randomblob(700) WHERE a==1;
      ROLLBACK TO two;
      RELEASE two;
  }
  do_execsql_test 1.2.$jj.3 {
      SAVEPOINT two;
        UPDATE t1 SET b=randomblob(700) WHERE a==1;
      ROLLBACK TO two;
      RELEASE two;
  }

  do_execsql_test 1.2.$jj.4 {
    PRAGMA integrity_check;
    ROLLBACK TO one;
    RELEASE one;
  } {ok}
} 


finish_test


Changes to test/memsubsys1.test.

170
171
172
173
174
175
176
177

178
179
180
181
182
183
184
170
171
172
173
174
175
176

177
178
179
180
181
182
183
184







-
+







  expr {$pg_used>=45 && $pg_used<=50}
} 1
do_test memsubsys1-4.4 {
  set pg_ovfl [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 2]
} 0
do_test memsubsys1-4.5 {
  set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2]
  expr {$maxreq<7000}
  expr {$maxreq<9000}
} 1

db close
sqlite3_shutdown
sqlite3_config_memstatus 1
sqlite3_config_lookaside 100 500
sqlite3_config serialized

Added test/merge1.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2021-12-29
#
# 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.
#
#***********************************************************************
#
# Testing the compound-SELECT merge algorithm to ensure that it works
# when it tries to balance the merge tree.

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix merge1

ifcapable !vtab {
  finish_test
  return
}

load_static_extension db series


optimization_control db all on
do_execsql_test 100 {
  WITH data(v) AS (
    SELECT value FROM generate_series(1,35,3)
    UNION ALL
    SELECT value FROM generate_series(10,30,4)
    UNION ALL
    SELECT value FROM generate_series(20,50,5)
    UNION ALL
    SELECT value FROM generate_series(30,60,6)
    UNION ALL
    SELECT value FROM generate_series(1,50,7)
    UNION ALL
    SELECT value FROM generate_series(10,80,8)
  )
  SELECT v FROM data ORDER BY v;
} {1 1 4 7 8 10 10 10 13 14 15 16 18 18 19 20 22 22 22 25 25 26 26 28 29 30 30 30 31 34 34 35 36 36 40 42 42 43 45 48 50 50 50 54 58 60 66 74}
do_eqp_test 101 {
  WITH data(v) AS (
    SELECT value FROM generate_series(1,35,3)
    UNION ALL
    SELECT value FROM generate_series(10,30,4)
    UNION ALL
    SELECT value FROM generate_series(20,50,5)
    UNION ALL
    SELECT value FROM generate_series(30,60,6)
    UNION ALL
    SELECT value FROM generate_series(1,50,7)
    UNION ALL
    SELECT value FROM generate_series(10,80,8)
  )
  SELECT v FROM data ORDER BY v;
} {
  QUERY PLAN
  `--MERGE (UNION ALL)
     |--LEFT
     |  `--MERGE (UNION ALL)
     |     |--LEFT
     |     |  `--MERGE (UNION ALL)
     |     |     |--LEFT
     |     |     |  `--SCAN generate_series VIRTUAL TABLE INDEX 23:
     |     |     `--RIGHT
     |     |        `--SCAN generate_series VIRTUAL TABLE INDEX 23:
     |     `--RIGHT
     |        `--SCAN generate_series VIRTUAL TABLE INDEX 23:
     `--RIGHT
        `--MERGE (UNION ALL)
           |--LEFT
           |  `--MERGE (UNION ALL)
           |     |--LEFT
           |     |  `--SCAN generate_series VIRTUAL TABLE INDEX 23:
           |     `--RIGHT
           |        `--SCAN generate_series VIRTUAL TABLE INDEX 23:
           `--RIGHT
              `--SCAN generate_series VIRTUAL TABLE INDEX 23:
}

# Same test with the blanced-merge optimization
# disabled.  Should give the exact same answer.
#
optimization_control db balanced-merge off
db cache flush
do_execsql_test 110 {
  WITH data(v) AS (
    SELECT value FROM generate_series(1,35,3)
    UNION ALL
    SELECT value FROM generate_series(10,30,4)
    UNION ALL
    SELECT value FROM generate_series(20,50,5)
    UNION ALL
    SELECT value FROM generate_series(30,60,6)
    UNION ALL
    SELECT value FROM generate_series(1,50,7)
    UNION ALL
    SELECT value FROM generate_series(10,80,8)
  )
  SELECT v FROM data ORDER BY v;
} {1 1 4 7 8 10 10 10 13 14 15 16 18 18 19 20 22 22 22 25 25 26 26 28 29 30 30 30 31 34 34 35 36 36 40 42 42 43 45 48 50 50 50 54 58 60 66 74}
do_eqp_test 111 {
  WITH data(v) AS (
    SELECT value FROM generate_series(1,35,3)
    UNION ALL
    SELECT value FROM generate_series(10,30,4)
    UNION ALL
    SELECT value FROM generate_series(20,50,5)
    UNION ALL
    SELECT value FROM generate_series(30,60,6)
    UNION ALL
    SELECT value FROM generate_series(1,50,7)
    UNION ALL
    SELECT value FROM generate_series(10,80,8)
  )
  SELECT v FROM data ORDER BY v;
} {
  QUERY PLAN
  `--MERGE (UNION ALL)
     |--LEFT
     |  `--MERGE (UNION ALL)
     |     |--LEFT
     |     |  `--MERGE (UNION ALL)
     |     |     |--LEFT
     |     |     |  `--MERGE (UNION ALL)
     |     |     |     |--LEFT
     |     |     |     |  `--MERGE (UNION ALL)
     |     |     |     |     |--LEFT
     |     |     |     |     |  `--SCAN generate_series VIRTUAL TABLE INDEX 23:
     |     |     |     |     `--RIGHT
     |     |     |     |        `--SCAN generate_series VIRTUAL TABLE INDEX 23:
     |     |     |     `--RIGHT
     |     |     |        `--SCAN generate_series VIRTUAL TABLE INDEX 23:
     |     |     `--RIGHT
     |     |        `--SCAN generate_series VIRTUAL TABLE INDEX 23:
     |     `--RIGHT
     |        `--SCAN generate_series VIRTUAL TABLE INDEX 23:
     `--RIGHT
        `--SCAN generate_series VIRTUAL TABLE INDEX 23:
}

finish_test

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.
637
638
639
640
641
642
643

644










645
646
642
643
644
645
646
647
648
649

650
651
652
653
654
655
656
657
658
659
660
661







+
-
+
+
+
+
+
+
+
+
+
+


  SELECT min(a) FROM t14 WHERE b='2' AND a>'50';
} {100}
do_execsql_test 14.2 {
  CREATE INDEX t14ba ON t14(b,a);
  SELECT min(a) FROM t14 WHERE b='2' AND a>'50';
} {100}

# 2021-08-21.  https://sqlite.org/forum/forumpost/cfcb4b461d

# 
reset_db
do_execsql_test 15.1 {
  CREATE TABLE t1(a);
  CREATE TABLE t2(b);
  CREATE TABLE t3(c);
  INSERT INTO t1 VALUES(0);
  INSERT INTO t2 VALUES(5);
  SELECT MIN((SELECT b FROM t2 UNION SELECT x FROM (SELECT x FROM (SELECT 1 AS x WHERE t1.a=1) UNION ALL SELECT c FROM t3))) FROM t1;
} {5}

finish_test

Changes to test/minmax2.test.

17
18
19
20
21
22
23

24
25
26
27
28
29
30
31
32
17
18
19
20
21
22
23
24
25

26
27
28
29
30
31
32







+

-







#
# $Id: minmax2.test,v 1.2 2008/01/05 17:39:30 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_test minmax2-1.0 {
  sqlite3_db_config db LEGACY_FILE_FORMAT 0
  execsql {
    PRAGMA legacy_file_format=0;
    BEGIN;
    CREATE TABLE t1(x, y);
    INSERT INTO t1 VALUES(1,1);
    INSERT INTO t1 VALUES(2,2);
    INSERT INTO t1 VALUES(3,2);
    INSERT INTO t1 VALUES(4,3);
    INSERT INTO t1 VALUES(5,3);
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/minmax4.test.

15
16
17
18
19
20
21

22
23
24
25
26
27
28
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29







+







#
# Demonstration that the value returned for p is on the same row as 
# the maximum q.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix minmax4

ifcapable !compound {
  finish_test
  return
}

do_test minmax4-1.1 {
144
145
146
147
148
149
150










151
152










































































153
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







+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

} {1 2 1 4 4 2 3 3 5 5}
do_test minmax4-2.7 {
  db eval {
    SELECT a, min(b), b, min(c), c FROM t2 GROUP BY a ORDER BY a;
  }
} {1 1 {} 2 2 2 3 3 5 5}

#-------------------------------------------------------------------------
foreach {tn sql} {
  1 { CREATE INDEX i1 ON t1(a) }
  2 { CREATE INDEX i1 ON t1(a DESC) }
  3 { }
} {
  reset_db
  do_execsql_test 3.$tn.0 {
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES(NULL, 1);


  }
  execsql $sql
  do_execsql_test 3.$tn.1 {
    SELECT min(a), b FROM t1;
  } {{} 1}
  do_execsql_test 3.$tn.2 {
    SELECT min(a), b FROM t1 WHERE a<50;
  } {{} {}}
  do_execsql_test 3.$tn.3 {
    INSERT INTO t1 VALUES(2, 2);
  }
  do_execsql_test 3.$tn.4 {
    SELECT min(a), b FROM t1;
  } {2 2}
  do_execsql_test 3.$tn.5 {
    SELECT min(a), b FROM t1 WHERE a<50;
  } {2 2}
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 4.0 {
  CREATE TABLE t0 (c0, c1);
  CREATE INDEX i0 ON t0(c1, c1 + 1 DESC);
  INSERT INTO t0(c0) VALUES (1);
}
do_execsql_test 4.1 {
  SELECT MIN(t0.c1), t0.c0 FROM t0 WHERE t0.c1 ISNULL; 
} {{} 1}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 5.0 {
  CREATE TABLE t1 (a, b);
  INSERT INTO t1 VALUES(123, NULL);
  CREATE INDEX i1 ON t1(a, b DESC);
}
do_execsql_test 5.1 {
  SELECT MIN(a) FROM t1 WHERE a=123;
} {123}

#-------------------------------------------------------------------------
# Tests for ticket f8a7060ece.
#
reset_db
do_execsql_test 6.1.0 {
  CREATE TABLE t1(a, b, c);
  INSERT INTO t1 VALUES(NULL, 1, 'x');
  CREATE INDEX i1 ON t1(a);
}
do_execsql_test 6.1.1 {
  SELECT min(a), b, c FROM t1 WHERE c='x';
} {{} 1 x}
do_execsql_test 6.1.2 {
  INSERT INTO t1 VALUES(1,    2, 'y');
} {}
do_execsql_test 6.1.3 {
  SELECT min(a), b, c FROM t1 WHERE c='x';
} {{} 1 x}

do_execsql_test 6.2.0 {
  CREATE TABLE t0(c0 UNIQUE, c1);
  INSERT INTO t0(c1) VALUES (0);
  INSERT INTO t0(c0) VALUES (0);
  CREATE VIEW v0(c0, c1) AS 
      SELECT t0.c1, t0.c0 FROM t0 WHERE CAST(t0.rowid AS INT) = 1;
}
do_execsql_test 6.2.1 {
  SELECT c0, c1 FROM v0;
} {0 {}}
do_execsql_test 6.2.2 {
  SELECT v0.c0, MIN(v0.c1) FROM v0;
} {0 {}}

finish_test

Changes to test/misc1.test.

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
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







-
+

+
+
+





-
+









-
+



-
+







  SELECT * FROM t19;
} {1 2 3}
do_execsql_test misc1-19.2 {
  CREATE TABLE t19b AS SELECT 4 AS '', 5 AS '',  6 AS '';
  SELECT * FROM t19b;
} {4 5 6}

# 2015-05-20:  CREATE TABLE AS should not store INT value is a TEXT
# 2015-05-20:  CREATE TABLE AS should not store INT value in a TEXT
# column.
#
# 2022-12-14:  Change:  The column is not TEXT if the AS SELECT is
# a compound with different types on each arm.
#
do_execsql_test misc1-19.3 {
  CREATE TABLE t19c(x TEXT);
  CREATE TABLE t19d AS SELECT * FROM t19c UNION ALL SELECT 1234;
  SELECT x, typeof(x) FROM t19d;
} {1234 text}
} {1234 integer}

# 2014-05-16:  Tests for the SQLITE_TESTCTRL_FAULT_INSTALL feature.
#
unset -nocomplain fault_callbacks
set fault_callbacks {}
proc fault_callback {n} {
  lappend ::fault_callbacks $n
  return 0
}
do_test misc1-19.1 {
do_test misc1-19.11 {
  sqlite3_test_control_fault_install fault_callback
  set fault_callbacks
} {0}
do_test misc1-19.2 {
do_test misc1-19.12 {
  sqlite3_test_control_fault_install
  set fault_callbacks
} {0}

# 2015-01-26:  Valgrind-detected over-read.
# Reported on sqlite-users@sqlite.org by Michal Zalewski.  Found by afl-fuzz
# presumably.
648
649
650
651
652
653
654
655

656
657
658
659
660
661
662
651
652
653
654
655
656
657

658
659
660
661
662
663
664
665







-
+







} {1 {near "#0": syntax error}}
do_catchsql_test misc1-21.2 {
  VALUES(0,0x0MATCH#0;
} {1 {near ";": syntax error}}

# 2015-04-15
do_execsql_test misc1-22.1 {
  SELECT ""+3 FROM (SELECT ""+5);
  SELECT ''+3 FROM (SELECT ''+5);
} {3}

# 2015-04-19: NULL pointer dereference on a corrupt schema
#
db close
sqlite3 db :memory:
sqlite3_db_config db DEFENSIVE 0
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
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







+
+
+
+
+
+
+
-
+















+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  CREATE TABLE abc(a, b, c);
  SELECT randomblob(min(max(coalesce(EXISTS (SELECT 1 FROM ( SELECT (SELECT 2147483647) NOT IN (SELECT 2147483649 UNION ALL SELECT DISTINCT -1) IN (SELECT 2147483649), 'fault', (SELECT ALL -1 INTERSECT SELECT 'experiments') IN (SELECT ALL 56.1 ORDER BY 'experiments' DESC) FROM (SELECT DISTINCT 2147483648, 'hardware' UNION ALL SELECT -2147483648, 'experiments' ORDER BY 2147483648 LIMIT 1 OFFSET 123456789.1234567899) GROUP BY (SELECT ALL 0 INTERSECT SELECT 'in') IN (SELECT DISTINCT 'experiments' ORDER BY zeroblob(1000) LIMIT 56.1 OFFSET -456) HAVING EXISTS (SELECT 'fault' EXCEPT    SELECT DISTINCT 56.1) UNION SELECT 'The', 'The', 2147483649 UNION ALL SELECT DISTINCT 'hardware', 'first', 'experiments' ORDER BY 'hardware' LIMIT 123456789.1234567899 OFFSET -2147483647)) NOT IN (SELECT (SELECT DISTINCT (SELECT 'The') FROM abc ORDER BY EXISTS (SELECT -1 INTERSECT SELECT ALL NULL) ASC) IN (SELECT DISTINCT EXISTS (SELECT ALL 123456789.1234567899 ORDER BY 1 ASC, NULL DESC) FROM sqlite_master INTERSECT SELECT 456)), (SELECT ALL 'injection' UNION ALL SELECT ALL (SELECT DISTINCT 'first' UNION     SELECT DISTINCT 'The') FROM (SELECT 456, 'in', 2147483649))),1), 500)), 'first', EXISTS (SELECT DISTINCT 456 FROM abc ORDER BY 'experiments' DESC) FROM abc;
} {}

# 2017-12-29
#
# The following behaviors (duplicate column names on an INSERT or UPDATE)
# are undocumented.  <<---  Not so.  There is a long-standing requirement
# in lang_update.in to say that when the columns to be updated appear more
# than once in an UPDATE statement that only the rightmost expression is used.
# See e_update-1.6.* for the tests.  This is unfortunate, since omitting
# that requirement would greatly simplify the fix to the problem identified
# by forum post https://sqlite.org/forum/info/16ca0e9f32c38567
#
# are undocumented.  These tests are added to ensure that historical behavior
# These tests are added to ensure that historical behavior
# does not change accidentally.
#
# For duplication columns on an INSERT, the first value is used.
# For duplication columns on an UPDATE, the last value is used.
#
do_execsql_test misc1-27.0 {
  CREATE TABLE dup1(a,b,c);
  INSERT INTO dup1(a,b,c,a,b,c) VALUES(1,2,3,4,5,6);
  SELECT a,b,c FROM dup1;
} {1 2 3}
do_execsql_test misc1-27.1 {
  UPDATE dup1 SET a=7, b=8, c=9, a=10, b=11, c=12;
  SELECT a,b,c FROM dup1;
} {10 11 12}

# 2018-12-20

#
# The Cursor.seekOp debugging value set incorrectly
# in OP_NotExists.
#
sqlite3 db :memory:
do_execsql_test misc1-28.0 {
  CREATE TABLE t1(x);
  CREATE UNIQUE INDEX t1x ON t1(x) WHERE x=1;
  INSERT OR ABORT INTO t1 DEFAULT VALUES;
  UPDATE OR REPLACE t1 SET x = 1;
  PRAGMA integrity_check;
  SELECT * FROM t1;
} {ok 1}

finish_test

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.

223
224
225
226
227
228
229



230
231
232
233
234
235
236
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239







+
+
+







    register_echo_module [sqlite3_connection_pointer db]
    execsql {
      CREATE VIRTUAL TABLE t1 USING echo(abc);
      SELECT a FROM t1 WHERE a = 1 ORDER BY b;
    }
  } {1}
  set sqlite_where_trace 0
  do_catchsql_test misc7-10.1 {
    INSERT INTO t1(a,b,c) VALUES(12345,2,3) ON CONFLICT(a) DO NOTHING;
  } {1 {UPSERT not implemented for virtual table "t1"}}

  # Specify an ORDER BY clause that cannot be indexed.
  do_test misc7-11 {
    execsql {
      SELECT t1.a, t2.a FROM t1, t1 AS t2 ORDER BY 2 LIMIT 1;
    }
  } {1 1}
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
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
448
449
450
451
452
453
454
455

456
457
458
459
460

461
462
463
464
465
466
467
451
452
453
454
455
456
457

458
459
460
461
462
463
464
465
466
467
468
469
470
471







-
+





+







    
    do_test misc7-17.4 {
      db close
      sqlite3 db test.db
      catchsql {
        SELECT count(*) FROM t3;
      } 
    } {1 {database disk image is malformed}}
    } {1 {malformed database schema (t3) - invalid rootpage}}
  }
}

# Ticket #2470
#
reset_db
do_test misc7-18.1 {
  execsql {
    CREATE TABLE table_1 (col_10);
    CREATE TABLE table_2 (
      col_1, col_2, col_3, col_4, col_5,
      col_6, col_7, col_8, col_9, col_10
    );

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 {
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







-
-
-
+
+
+




do_execsql_test misc8-4.1 {
  PRAGMA database_list;
} {/0 main .* 2 aux2/}
dbconfig_maindbname_icecube db
do_execsql_test misc8-4.2 {
  SELECT name FROM icecube.sqlite_master;
} {t1}
do_execsql_test misc8-4.3 {
  PRAGMA database_list;
} {/0 icecube .* 2 aux2/}
do_test misc8-4.3 {
  regexp {0 icecube .* 2 aux2} [db eval {PRAGMA database_list}] 
} 1



finish_test

Changes to test/mmap1.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
22







-
+







#    May you share freely, never taking more than you give.
#
#***********************************************************************
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable !mmap {
ifcapable !mmap||!incrblob {
  finish_test
  return
}
source $testdir/lock_common.tcl
set testprefix mmap1

proc nRead {db} {

Changes to test/multiplex.test.

178
179
180
181
182
183
184





185
186
187
188
189
190
191
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196







+
+
+
+
+







    INSERT INTO t1 VALUES(2, randomblob(1100));
  }
} {}
do_test multiplex-2.1.3 { file size [multiplex_name test.x 0] } {4096}
do_test multiplex-2.1.4 {
  execsql { INSERT INTO t1 VALUES(3, randomblob(1100)) }
} {}
do_execsql_test multiplex-2.1.5 {
  PRAGMA multiplex_enabled;
  PRAGMA multiplex_filecount;
  PRAGMA multiplex_chunksize;
} {1 1 2147418112}

do_test multiplex-2.2.1 {
  execsql { INSERT INTO t1 VALUES(3, randomblob(1100)) }
} {}
do_test multiplex-2.2.3 { file size [multiplex_name test.x 0] } {6144}

do_test multiplex-2.3.1 {
263
264
265
266
267
268
269












270
271
272
273
274
275
276
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







+
+
+
+
+
+
+
+
+
+
+
+








do_test multiplex-2.5.8 {
  db eval {SELECT a,length(b) FROM t1 WHERE a=4}
} {4 4000}

do_test multiplex-2.5.9 { file size [multiplex_name test.x 0] } [list $g_chunk_size]
do_test multiplex-2.5.10 { file size [multiplex_name test.x 1] } [list $g_chunk_size]
do_execsql_test multiplex-2.5.11 {
  PRAGMA multiplex_enabled;
  PRAGMA multiplex_filecount;
  PRAGMA multiplex_chunksize;
} {1 3 65536}
sqlite3 db test.x
do_execsql_test multiplex-2.5.12 {
  PRAGMA multiplex_filecount;
  PRAGMA multiplex_chunksize;
} {3 65536}



do_test multiplex-2.5.99 {
  db close
  sqlite3_multiplex_shutdown
} {SQLITE_OK}


Changes to test/multiplex3.test.

78
79
80
81
82
83
84


85
86
87
88
89
90
91
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93







+
+







}

do_test 1.0 { setup_and_save_db } {}
do_faultsim_test 1 -prep {
  multiplex_restore_db
  sqlite3 db file:test.db?8_3_names=1
  sqlite3_multiplex_control db main chunk_size [expr 256*1024]
  execsql { PRAGMA journal_mode = truncate }
  execsql { PRAGMA synchronous = off }
} -body {
  execsql {
    UPDATE t1 SET a=randomblob(12), b=randomblob(1500) WHERE (rowid%32)=0
  }
} -test {
  faultsim_test_result {0 {}}
  if {$testrc!=0} {

Changes to test/mutex1.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







-
+







    incr var(total) $value
  }
}

#-------------------------------------------------------------------------
# Tests mutex1-1.* test that sqlite3_config() returns SQLITE_MISUSE if
# is called at the wrong time. And that the first time sqlite3_initialize
# is called it obtains the 'static_master' mutex 3 times and a recursive
# is called it obtains the 'static_main' mutex 3 times and a recursive
# mutex (sqlite3Config.pInitMutex) twice. Subsequent calls are no-ops
# that do not require any mutexes.
#
do_test mutex1-1.0 {
  install_mutex_counters 1
} {SQLITE_MISUSE}

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
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







-
+










-
+
















-
+





-
+








do_test mutex1-1.6 {
  sqlite3_initialize
} {SQLITE_OK}

do_test mutex1-1.7 {
  mutex_counters counters
  # list $counters(total) $counters(static_master)
  # list $counters(total) $counters(static_main)
  expr {$counters(total)>0}
} {1}

do_test mutex1-1.8 {
  clear_mutex_counters
  sqlite3_initialize
} {SQLITE_OK}

do_test mutex1-1.9 {
  mutex_counters counters
  list $counters(total) $counters(static_master)
  list $counters(total) $counters(static_main)
} {0 0}

#-------------------------------------------------------------------------
# Tests mutex1-2.* test the three thread-safety related modes that
# can be selected using sqlite3_config:
#
#   * Serialized mode,
#   * Multi-threaded mode,
#   * Single-threaded mode.
#
ifcapable threadsafe1&&shared_cache {
  set enable_shared_cache [sqlite3_enable_shared_cache 1]
  foreach {mode mutexes} {
    singlethread {}
    multithread  {
      fast static_app1 static_app2 static_app3
      static_lru static_master static_mem static_open
      static_lru static_main static_mem static_open
      static_prng static_pmem static_vfs1 static_vfs2
      static_vfs3
    }
    serialized  {
      fast recursive static_app1 static_app2
      static_app3 static_lru static_master static_mem
      static_app3 static_lru static_main static_mem
      static_open static_prng static_pmem static_vfs1
      static_vfs2 static_vfs3
    }
  } {

    do_test mutex1.2.$mode.1 {
      catch {db close}

Changes to test/normalize.test.

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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  0x2
  {0 {SELECT x FROM t1 WHERE x=?;}}

  760
  {SELECT x FROM t1 WHERE x IN ([x] IS NOT NULL, NULL, 1, 'a', "b", x'00');}
  0x2
  {0 {SELECT x FROM t1 WHERE x IN(x IS NOT NULL,?,?,?,b,?);}}

  800
  {ATTACH "normalize800.db" AS somefile;}
  0x2
  {0 {ATTACH"normalize800.db"AS somefile;}}

  810
  {ATTACH DATABASE "normalize810.db" AS somefile;}
  0x2
  {0 {ATTACH DATABASE"normalize810.db"AS somefile;}}

  900
  {INSERT INTO t1 (x) VALUES("sl1"), (1), ("sl2"), ('i');}
  0x2
  {0 {INSERT INTO t1(x)VALUES(?),(?),(?),(?);}}

  910
  {UPDATE t1 SET x = "sl1" WHERE x IN (1, "sl2", 'i');}
  0x2
  {0 {UPDATE t1 SET x=?WHERE x IN(?,?,?);}}

  920
  {UPDATE t1 SET x = "y" WHERE x IN (1, "sl1", 'i');}
  0x2
  {0 {UPDATE t1 SET x=y WHERE x IN(?,?,?);}}

  930
  {DELETE FROM t1 WHERE x IN (1, "sl1", 'i');}
  0x2
  {0 {DELETE FROM t1 WHERE x IN(?,?,?);}}
} {
  do_test $tnum {
    set code [catch {
      set STMT [sqlite3_prepare_v3 $DB $sql -1 $flags TAIL]
      sqlite3_normalized_sql $STMT
    } res]
    if {[info exists STMT]} {

Changes to test/notify3.test.

104
105
106
107
108
109
110
111
112


113
114
115
116
117
118
119
104
105
106
107
108
109
110


111
112
113
114
115
116
117
118
119







-
-
+
+







    db2_loaded
    enable_extended_errors
    result
    error1 error2
  } "
    0   0 0 0   $err     SQLITE_LOCKED               SQLITE_LOCKED_SHAREDCACHE
    1   0 0 1   $err     SQLITE_LOCKED_SHAREDCACHE   SQLITE_LOCKED_SHAREDCACHE
    2   0 1 0   $err     SQLITE_LOCKED               SQLITE_LOCKED_SHAREDCACHE
    3   0 1 1   $err     SQLITE_LOCKED_SHAREDCACHE   SQLITE_LOCKED_SHAREDCACHE
    2   0 1 0   $noerr   SQLITE_OK                   SQLITE_OK
    3   0 1 1   $noerr   SQLITE_OK                   SQLITE_OK
    4   1 0 0   $err     SQLITE_LOCKED               SQLITE_LOCKED_SHAREDCACHE
    5   1 0 1   $err     SQLITE_LOCKED_SHAREDCACHE   SQLITE_LOCKED_SHAREDCACHE
    6   1 1 0   $noerr   SQLITE_OK                   SQLITE_OK
    7   1 1 1   $noerr   SQLITE_OK                   SQLITE_OK
  " {
  
    do_test notify3-2.$tn.1 {

Added test/notnull2.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2021 February 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 optimizations associated with "IS NULL"
# and "IS NOT NULL" operators on columns with NOT NULL constraints.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix notnull2

do_execsql_test 1.0 {
  CREATE TABLE t1(a, b);
  CREATE TABLE t2(c, d NOT NULL);

  WITH x(i) AS (
    SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<1000
  )
  INSERT INTO t1 SELECT i, i FROM x;
  INSERT INTO t2 SELECT * FROM t1;
}

proc do_vmstep_test {tn sql nstep {res {}}} {
  uplevel [list do_execsql_test $tn.0 $sql $res]

  set vmstep [db status vmstep]
  if {[string range $nstep 0 0]=="+"} {
    set body "if {$vmstep<$nstep} {
      error \"got $vmstep, expected more than [string range $nstep 1 end]\"
    }"
  } else {
    set body "if {$vmstep>$nstep} {
      error \"got $vmstep, expected less than $nstep\"
    }"
  }

  # set name "$tn.vmstep=$vmstep,expect=$nstep"
  set name "$tn.1"
  uplevel [list do_test $name $body {}]
}

do_vmstep_test 1.1.1 {
  SELECT * FROM t1 LEFT JOIN t2 WHERE a=c AND d IS NULL;
} 100 {}
do_vmstep_test 1.1.2 {
  SELECT * FROM t1 LEFT JOIN t2 WHERE a=c AND c IS NULL;
} +1000 {}

do_vmstep_test 1.2.1 {
  SELECT * FROM ( SELECT * FROM t2 ) WHERE d IS NULL
} 100 {}
do_vmstep_test 1.2.2 {
  SELECT * FROM ( SELECT * FROM t2 ) WHERE c IS NULL
} +1000 {}

do_vmstep_test 1.3.1 {
  SELECT * FROM t2 WHERE d IS NULL
} 100 {}
do_vmstep_test 1.3.2 {
  SELECT * FROM t2 WHERE c IS NULL
} +1000 {}

do_vmstep_test 1.4.1 {
  SELECT (d IS NOT NULL) FROM t2 WHERE 0==( d IS NOT NULL )
} 100 {}
do_vmstep_test 1.4.2 {
  SELECT * FROM t2 WHERE 0==( c IS NOT NULL )
} +1000 {}

do_vmstep_test 1.5.1 {
  SELECT count(*) FROM t2 WHERE EXISTS(
    SELECT t2.d IS NULL FROM t1 WHERE t1.a=450
  )
} 10000 {1000}
do_vmstep_test 1.5.2 {
  SELECT count(*) FROM t2 WHERE EXISTS(
    SELECT t2.c IS NULL FROM t1 WHERE t1.a=450
  )
} +100000 {1000}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.0 {
  CREATE TABLE T1(a INTEGER PRIMARY KEY, b);
  CREATE TABLE T3(k, v);
}

do_execsql_test 2.1 {
  SELECT * FROM (SELECT a, b FROM t1) LEFT JOIN t3 ON a IS NULL;
}



#-------------------------------------------------------------------------
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}

# 2021-07-22 https://sqlite.org/forum/forumpost/2078b7edd2
#
reset_db
do_execsql_test 4.0 {
  SELECT *, '/'
  FROM (
      SELECT NULL val FROM (SELECT 1)
      UNION ALL
      SELECT 'missing' FROM (SELECT 1)
  ) a
  LEFT JOIN (SELECT 1)
      ON a.val IS NULL;
} {{} 1 / missing {} /}
do_execsql_test 4.1 {
  CREATE TABLE t1(a INT);
  INSERT INTO t1(a) VALUES(1);
  CREATE TABLE t2(b INT);
  SELECT * FROM (SELECT 3 AS c FROM t1) AS t3 LEFT JOIN t2 ON c IS NULL;
} {3 {}}

finish_test

Added test/notnullfault.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2021 February 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 optimizations associated with "IS NULL"
# and "IS NOT NULL" operators on columns with NOT NULL constraints.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix notnullfault

do_execsql_test 1.0 {
  CREATE TABLE t1(a, b);
  CREATE TABLE t2(c, d NOT NULL);
}
faultsim_save_and_close

do_faultsim_test 1 -prep {
  faultsim_restore_and_reopen
} -body {
  execsql {
    SELECT * FROM t2 WHERE d NOT NULL
  }
} -test {
  faultsim_test_result {0 {}}
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.0 {
  CREATE TABLE t1(a, b, c); 
  CREATE TABLE t2(a, b, c, PRIMARY KEY(a, b, c)) WITHOUT ROWID;
}
faultsim_save_and_close

do_faultsim_test 2.1 -faults oom-t* -prep {
  faultsim_restore_and_reopen
} -body {
  execsql {
    SELECT dense_rank() OVER win FROM t2
    WINDOW win AS (ORDER BY c IS NULL)
  }
} -test {
  faultsim_test_result {0 {}}
}

finish_test

Changes to test/null.test.

292
293
294
295
296
297
298







299
300
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307







+
+
+
+
+
+
+


  SELECT * FROM t5 WHERE a = 1 AND b IS NULL;
} {1 {} one 1 {} i}

do_execsql_test null-9.3 {
  SELECT * FROM t5 WHERE a IS NULL AND b = 'x';
} {{} x two {} x ii}

# 2020-09-30 ticket 5c4e7aa793943803
reset_db
do_execsql_test null-10.1 {
  CREATE TABLE t0(c0 PRIMARY KEY DESC);
  INSERT INTO t0(c0) VALUES (0);
  SELECT * FROM t0 WHERE t0.c0 > NULL;
} {}

finish_test

Added test/nulls1.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019 August 10
#
# 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 nulls1

do_execsql_test 1.0 {
  DROP TABLE IF EXISTS t3;
  CREATE TABLE t3(a INTEGER);
  INSERT INTO t3 VALUES(NULL), (10), (30), (20), (NULL);
} {}

for {set a 0} {$a < 3} {incr a} {
  foreach {tn limit} {
    1 ""
    2 "LIMIT 10"
  } {
    do_execsql_test 1.$a.$tn.1 "
      SELECT a FROM t3 ORDER BY a nULLS FIRST $limit
    " {{}   {}   10   20   30}
    
    do_execsql_test 1.$a.$tn.2 "
      SELECT a FROM t3 ORDER BY a nULLS LAST $limit
    " {10   20   30   {}   {}}
    
    do_execsql_test 1.$a.$tn.3 "
      SELECT a FROM t3 ORDER BY a DESC nULLS FIRST $limit
    " {{}   {}   30   20   10}
    
    do_execsql_test 1.$a.$tn.4 "
      SELECT a FROM t3 ORDER BY a DESC nULLS LAST $limit
    " {30   20   10   {}   {}}
  }

  switch $a {
    0 {
      execsql { CREATE INDEX i1 ON t3(a) }
    }
    1 {
      execsql { DROP INDEX i1 ; CREATE INDEX i1 ON t3(a DESC) }
    }
  }
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.0 {
  CREATE TABLE t2(a, b, c);
  CREATE INDEX i2 ON t2(a, b);
  INSERT INTO t2 VALUES(1, 1, 1);
  INSERT INTO t2 VALUES(1, NULL, 2);
  INSERT INTO t2 VALUES(1, NULL, 3);
  INSERT INTO t2 VALUES(1, 4, 4);
}

do_execsql_test 2.1 {
  SELECT * FROM t2 WHERE a=1 ORDER BY b NULLS LAST
} {
  1 1 1    1 4 4   1 {} 2   1 {} 3
}

do_execsql_test 2.2 {
  SELECT * FROM t2 WHERE a=1 ORDER BY b DESC NULLS FIRST
} {
  1 {} 3
  1 {} 2     
  1 4 4     
  1 1 1
}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 3.0 {
  CREATE TABLE t1(a, b, c, d, UNIQUE (b));
}
foreach {tn sql err}  {
  1 { CREATE INDEX i1 ON t1(a ASC NULLS LAST) }           LAST
  2 { CREATE INDEX i1 ON t1(a ASC NULLS FIRST) }          FIRST
  3 { CREATE INDEX i1 ON t1(a, b ASC NULLS LAST) }        LAST
  4 { CREATE INDEX i1 ON t1(a, b ASC NULLS FIRST) }       FIRST
  5 { CREATE INDEX i1 ON t1(a DESC NULLS LAST) }          LAST
  6 { CREATE INDEX i1 ON t1(a DESC NULLS FIRST) }         FIRST
  7 { CREATE INDEX i1 ON t1(a, b DESC NULLS LAST) }       LAST
  8 { CREATE INDEX i1 ON t1(a, b DESC NULLS FIRST) }      FIRST
  9  { CREATE TABLE t2(a, b, PRIMARY KEY(a DESC, b NULLS FIRST)) } FIRST
  10 { CREATE TABLE t2(a, b, UNIQUE(a DESC NULLS FIRST, b)) }      FIRST
  11 { INSERT INTO t1 VALUES(1, 2, 3, 4)
          ON CONFLICT (b DESC NULLS LAST) DO UPDATE SET a = a+1 } LAST
  12 {
    CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
      INSERT INTO t1 VALUES(1, 2, 3, 4)
      ON CONFLICT (b DESC NULLS FIRST) DO UPDATE SET a = a+1;
    END
  } FIRST
} {
  do_catchsql_test 3.1.$tn $sql "1 {unsupported use of NULLS $err}"
}

do_execsql_test 3.2 {
  CREATE TABLE first(nulls, last);
  INSERT INTO first(last, nulls) VALUES(100,200), (300,400), (200,300);
  SELECT * FROM first ORDER BY nulls;
} {
  200 100
  300 200
  400 300
}

#-------------------------------------------------------------------------
#
ifcapable vtab {
  register_echo_module db
  do_execsql_test 4.0 {
    CREATE TABLE tx(a INTEGER PRIMARY KEY, b, c);
    CREATE INDEX i1 ON tx(b);
    INSERT INTO tx VALUES(1, 1, 1);
    INSERT INTO tx VALUES(2, NULL, 2);
    INSERT INTO tx VALUES(3, 3, 3);
    INSERT INTO tx VALUES(4, NULL, 4);
    INSERT INTO tx VALUES(5, 5, 5);
    CREATE VIRTUAL TABLE te USING echo(tx);
  }

  do_execsql_test 4.1 {
    SELECT * FROM tx ORDER BY b NULLS FIRST;
  } {2 {} 2  4 {} 4  1 1 1  3 3 3  5 5 5}
  do_execsql_test 4.2 {
    SELECT * FROM te ORDER BY b NULLS FIRST;
  } {2 {} 2  4 {} 4  1 1 1  3 3 3  5 5 5}

  do_execsql_test 4.3 {
    SELECT * FROM tx ORDER BY b NULLS LAST;
  } {1 1 1  3 3 3  5 5 5  2 {} 2  4 {} 4}
  do_execsql_test 4.4 {
    SELECT * FROM te ORDER BY b NULLS LAST;
  } {1 1 1  3 3 3  5 5 5  2 {} 2  4 {} 4}
}

#-------------------------------------------------------------------------
#
do_execsql_test 5.0 {
  CREATE TABLE t4(a, b, c);
  INSERT INTO t4 VALUES(1, 1, 11);
  INSERT INTO t4 VALUES(1, 2, 12);
  INSERT INTO t4 VALUES(1, NULL, 1);

  INSERT INTO t4 VALUES(2, NULL, 1);
  INSERT INTO t4 VALUES(2, 2, 12);
  INSERT INTO t4 VALUES(2, 1, 11);

  INSERT INTO t4 VALUES(3, NULL, 1);
  INSERT INTO t4 VALUES(3, 2, 12);
  INSERT INTO t4 VALUES(3, NULL, 3);
}

do_execsql_test 5.1 {
  SELECT * FROM t4 WHERE a IN (1, 2, 3) ORDER BY a, b NULLS LAST
} {
  1 1 11   1 2 12   1 {} 1   
  2 1 11   2 2 12   2 {} 1 
  3 2 12   3 {} 1   3 {} 3
}
do_execsql_test 5.2 {
  CREATE INDEX t4ab ON t4(a, b);
  SELECT * FROM t4 WHERE a IN (1, 2, 3) ORDER BY a, b NULLS LAST
} {
  1 1 11   1 2 12   1 {} 1   
  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 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 t4 USING INDEX t4ab (a=?)
}

#-------------------------------------------------------------------------
#
do_execsql_test 6.0 {
  CREATE TABLE t5(a, b, c);
  WITH s(i) AS (
    VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<200
  ) 
  INSERT INTO t5 SELECT i%2, CASE WHEN (i%10)==0 THEN NULL ELSE i END, i FROM s;
}

set res1 [db eval { SELECT a,b FROM t5 WHERE a=1 ORDER BY b NULLS LAST, c }]
set res2 [db eval { 
  SELECT a,b FROM t5 WHERE a=1 ORDER BY b DESC NULLS FIRST, c DESC 
}]

do_execsql_test 6.1.1 {
  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 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 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);

  SELECT * FROM t71 WHERE a=1 AND b=2 ORDER BY c NULLS LAST;
  SELECT * FROM t71 WHERE a=1 AND b=2 ORDER BY c DESC NULLS FIRST;

  SELECT * FROM t71 ORDER BY a NULLS LAST;
  SELECT * FROM t71 ORDER BY a DESC NULLS FIRST;
}

# 2019-12-18 gramfuzz1 find
# NULLS LAST not allows on an INTEGER PRIMARY KEY.
#
do_catchsql_test 8.0 {
  CREATE TABLE t80(a, b INTEGER, PRIMARY KEY(b NULLS LAST)) WITHOUT ROWID;
} {1 {unsupported use of NULLS LAST}}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 9.0 {
  CREATE TABLE v0 (c1, c2, c3);
  CREATE INDEX v3 ON v0 (c1, c2, c3);
}
do_execsql_test 9.1 {
  ANALYZE sqlite_master;
  INSERT INTO sqlite_stat1 VALUES('v0','v3','648 324 81');
  ANALYZE sqlite_master;
}

do_execsql_test 9.2 {
  INSERT INTO v0 VALUES
      (1, 10, 'b'),
      (1, 10, 'd'),
      (1, 10, NULL),
      (2, 10, 'a'),
      (2, 10, NULL),
      (1, 10, 'c'),
      (2, 10, 'b'),
      (1, 10, 'a'),
      (1, 10, NULL),
      (2, 10, NULL),
      (2, 10, 'd'),
      (2, 10, 'c');
}

do_execsql_test 9.3 {
  SELECT c1, c2, ifnull(c3, 'NULL') FROM v0 
  WHERE c2=10 ORDER BY c1, c3 NULLS LAST
} {
  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 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 {
  CREATE TABLE t1(x);
  INSERT INTO t1(x) VALUES('X');
  CREATE TABLE t2(c, d);
  CREATE INDEX t2dc ON t2(d, c);
  SELECT c FROM t1 LEFT JOIN t2 ON d=NULL ORDER BY d, c NULLS LAST;
} {{}}
do_execsql_test 10.20 {
  INSERT INTO t2(c,d) VALUES(5,'X'),(6,'Y'),(7,'Z'),(3,'A'),(4,'B');
  SELECT c FROM t1 LEFT JOIN t2 ON d=x ORDER BY d, c NULLS LAST;
} {5}
do_execsql_test 10.30 {
  UPDATE t2 SET d='X';
  UPDATE t2 SET c=NULL WHERE c=6;
  SELECT c FROM t1 LEFT JOIN t2 ON d=x ORDER BY d NULLS FIRST, c NULLS FIRST;
} {{} 3 4 5 7}
do_execsql_test 10.40 {
  SELECT c FROM t1 LEFT JOIN t2 ON d=x ORDER BY d NULLS LAST, c NULLS LAST;
} {3 4 5 7 {}}
do_execsql_test 10.41 {
  SELECT c FROM t1 LEFT JOIN t2 ON d=x ORDER BY c NULLS LAST;
} {3 4 5 7 {}}
do_execsql_test 10.42 {
  SELECT c FROM t1 LEFT JOIN t2 ON d=x ORDER BY +d NULLS LAST, +c NULLS LAST;
} {3 4 5 7 {}}
do_execsql_test 10.50 {
  INSERT INTO t1(x) VALUES(NULL),('Y');
  SELECT x, c, d, '|' FROM t1 LEFT JOIN t2 ON d=x
   ORDER BY d NULLS LAST, c NULLS LAST;
} {X 3 X | X 4 X | X 5 X | X 7 X | X {} X | {} {} {} | Y {} {} |}
do_execsql_test 10.51 {
  SELECT x, c, d, '|' FROM t1 LEFT JOIN t2 ON d=x
   ORDER BY +d NULLS LAST, +c NULLS LAST;
} {X 3 X | X 4 X | X 5 X | X 7 X | X {} X | {} {} {} | Y {} {} |}





finish_test

Changes to test/offset1.test.

152
153
154
155
156
157
158


159








































160
161
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







+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


do_execsql_test offset1-1.4.9 {
  SELECT a, b FROM t1
  UNION ALL
  SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
  LIMIT 9 OFFSET 1;
} {2 b 3 c 4 d 5 e 6 w 7 x 8 y 9 z}

# 2022-08-04
# https://sqlite.org/forum/forumpost/6b5e9188f0657616

#
do_execsql_test offset1-2.0 {
  CREATE TABLE employees (
    id integer primary key,
    name text,
    city text,
    department text,
    salary integer
  );
  INSERT INTO employees VALUES
    (11,'Diane','London','hr',70),
    (12,'Bob','London','hr',78),
    (21,'Emma','London','it',84),
    (22,'Grace','Berlin','it',90),
    (23,'Henry','London','it',104),
    (24,'Irene','Berlin','it',104),
    (25,'Frank','Berlin','it',120),
    (31,'Cindy','Berlin','sales',96),
    (32,'Dave','London','sales',96),
    (33,'Alice','Berlin','sales',100);
  CREATE VIEW v AS
    SELECT * FROM (
      SELECT * FROM employees 
       WHERE salary < 100
       ORDER BY salary desc)
     UNION ALL 
     SELECT * FROM (
       SELECT * FROM employees
       WHERE salary >= 100
       ORDER BY salary asc);
} {}
do_execsql_test offset1-2.1 {
  SELECT * FROM v LIMIT 5 OFFSET 2;
} {
  22  Grace  Berlin  it      90
  21  Emma   London  it      84
  12  Bob    London  hr      78
  11  Diane  London  hr      70
  33  Alice  Berlin  sales   100
}

finish_test

Changes to test/optfuzz-db01.c.

941
942
943
944
945
946
947
948
941
942
943
944
945
946
947








-
  41, 32, 85, 78, 73, 79, 78, 32, 65, 76, 76, 32, 83, 69, 76, 69, 67, 84, 32,
 120, 43, 49, 32, 70, 82, 79, 77, 32, 99, 48, 32, 87, 72, 69, 82, 69, 32,120,
  60, 57, 41, 10, 32, 32, 83, 69, 76, 69, 67, 84, 32,120, 44, 32, 98, 44, 32,
  99, 44, 32,100, 44, 32,101, 32, 70, 82, 79, 77, 32, 99, 48, 32, 74, 79, 73,
  78, 32,116, 49, 32, 79, 78, 32, 40,116, 49, 46, 97, 61, 53, 48, 45, 99, 48,
  46,120, 41,
};

Changes to test/optfuzz.c.

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
22
23
24
25
26
27
28

29
30
31
32
33
34
35







-







** is printed and the program returns non-zero.
*/

/* Include the SQLite amalgamation, after making appropriate #defines.
*/
#define SQLITE_THREADSAFE 0
#define SQLITE_OMIT_LOAD_EXTENSION 1
#define SQLITE_ENABLE_DESERIALIZE 1
#include "sqlite3.c"

/* Content of the read-only test database */
#include "optfuzz-db01.c"

/*
** Prepare a single SQL statement.  Panic if anything goes wrong

Changes to test/orderby1.test.

39
40
41
42
43
44
45

46
47
48
49
50
51
52
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53







+







    INSERT INTO track VALUES
        (NULL, 1, 1, 'one-a'),
        (NULL, 2, 2, 'two-b'),
        (NULL, 3, 3, 'three-c'),
        (NULL, 1, 3, 'one-c'),
        (NULL, 2, 1, 'two-a'),
        (NULL, 3, 1, 'three-a');
    ANALYZE;
    COMMIT;
  }
} {}
do_test 1.1a {
  db eval {
    SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn
  }
176
177
178
179
180
181
182

183
184
185
186
187
188
189
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191







+







    INSERT INTO track VALUES
        (1,  1, 'one-a'),
        (20, 2, 'two-b'),
        (3,  3, 'three-c'),
        (1,  3, 'one-c'),
        (20, 1, 'two-a'),
        (3,  1, 'three-a');
    ANALYZE;
    COMMIT;
  }
} {}
do_test 2.1a {
  db eval {
    SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn
  }
323
324
325
326
327
328
329

330
331
332
333
334
335
336
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339







+







    INSERT INTO track VALUES
        (NULL, 1, 1, 'one-a'),
        (NULL, 2, 2, 'two-b'),
        (NULL, 3, 3, 'three-c'),
        (NULL, 1, 3, 'one-c'),
        (NULL, 2, 1, 'two-a'),
        (NULL, 3, 1, 'three-a');
    ANALYZE;
    COMMIT;
  }
} {}
do_test 3.1a {
  db eval {
    SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title, tn DESC
  }
512
513
514
515
516
517
518
519

520
521
522
523
524
525
526
515
516
517
518
519
520
521

522
523
524
525
526
527
528
529







-
+







  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
  )
554
555
556
557
558
559
560



561

562
557
558
559
560
561
562
563
564
565
566
567
568
569







+
+
+

+

do_execsql_test 10.0 {
  CREATE TABLE t10(a,b);
  INSERT INTO t10 VALUES(1,2),(8,9),(3,4),(5,4),(0,7);
  CREATE INDEX t10b ON t10(b);
  SELECT b, rowid, '^' FROM t10 ORDER BY b, a LIMIT 4;
} {2 1 ^ 4 3 ^ 4 4 ^ 7 5 ^}

do_catchsql_test 11.0 {
  VALUES(2) EXCEPT SELECT '' ORDER BY abc
} {1 {1st ORDER BY term does not match any column in the result set}}


finish_test

Changes to test/orderby5.test.

122
123
124
125
126
127
128

























































129
130
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


  DROP TABLE t3;
  CREATE TABLE t3(a INTEGER PRIMARY KEY, b, c, d, e, f) WITHOUT rowid;
  CREATE INDEX t3bcde ON t3(b, c, d, e);
  EXPLAIN QUERY PLAN
  SELECT a FROM t3 WHERE b=2 AND c=3 ORDER BY d DESC, e DESC, b, c, a DESC;
} {~/B-TREE/}

#-------------------------------------------------------------------------
do_execsql_test 4.1.0 {
  CREATE TABLE t4(b COLLATE nocase);
  INSERT INTO t4 VALUES('abc');
  INSERT INTO t4 VALUES('ABC');
  INSERT INTO t4 VALUES('aBC');
}
do_execsql_test 4.1.1 {
  SELECT * FROM t4 ORDER BY b COLLATE binary
} {ABC aBC abc}
do_execsql_test 4.1.2 {
  SELECT * FROM t4 WHERE b='abc' ORDER BY b COLLATE binary
} {ABC aBC abc}

do_execsql_test 4.2.1 {
  CREATE TABLE Records(typeID INTEGER, key TEXT COLLATE nocase, value TEXT);
  CREATE INDEX RecordsIndex ON Records(typeID, key, value);
}
do_execsql_test 4.2.2 {
  explain query plan
  SELECT typeID, key, value FROM Records 
  WHERE typeID = 2 AND key = 'x' 
  ORDER BY key, value;
} {~/TEMP B-TREE/}
do_execsql_test 4.2.3 {
  explain query plan
  SELECT typeID, key, value FROM Records 
  WHERE typeID = 2 AND (key = 'x' COLLATE binary)
  ORDER BY key, value;
} {~/TEMP B-TREE/}
do_execsql_test 4.2.4 {
  explain query plan
  SELECT typeID, key, value FROM Records 
  WHERE typeID = 2 
  ORDER BY key, value;
} {~/TEMP B-TREE/}

db collate hello [list string match]
do_execsql_test 4.3.1 {
  CREATE TABLE t5(a INTEGER PRIMARY KEY, b COLLATE hello, c, d);
}
db close
sqlite3 db test.db
do_catchsql_test 4.3.2 {
  SELECT a FROM t5 WHERE b='def' ORDER BY b;
} {1 {no such collation sequence: hello}}

# 2020-02-13 ticket 41c1456a6e61c0e7
do_execsql_test 4.4.0 {
  DROP TABLE t1;
  CREATE TABLE t1(a);
  DROP TABLE t2;
  CREATE TABLE t2(b INTEGER PRIMARY KEY, c INT);
  SELECT DISTINCT *
    FROM t1 LEFT JOIN t2 ON b=c AND b=(SELECT a FROM t1)
   WHERE c>10;
} {}

finish_test

Added test/orderbyA.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019-09-21
#
# 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.
#
# Specifically, it tests cases where the expressions in a GROUP BY 
# clause are the same as those in the ORDER BY clause.
# 

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set ::testprefix orderbyA

proc do_sortcount_test {tn sql cnt res} {
  set eqp [execsql "EXPLAIN QUERY PLAN $sql"]
  set rcnt [regexp -all {USE TEMP} $eqp]
  uplevel [list do_test         $tn.1 [list set {} $rcnt] $cnt]
  uplevel [list do_execsql_test $tn.2 $sql $res]
}

do_execsql_test 1.0 {
  CREATE TABLE t1(a, b, c);
  INSERT INTO t1 VALUES('one',   1, 11);
  INSERT INTO t1 VALUES('three', 7, 11);
  INSERT INTO t1 VALUES('one',   2, 11);
  INSERT INTO t1 VALUES('one',   3, 11);
  INSERT INTO t1 VALUES('two',   4, 11);
  INSERT INTO t1 VALUES('two',   6, 11);
  INSERT INTO t1 VALUES('three', 8, 11);
  INSERT INTO t1 VALUES('two',   5, 11);
  INSERT INTO t1 VALUES('three', 9, 11);
}

foreach {tn idx} {
  1 {}
  2 {CREATE INDEX i1 ON t1(a)}
  3 {CREATE INDEX i1 ON t1(a DESC)}
} {
  execsql { DROP INDEX IF EXISTS i1 }
  execsql $idx

  # $match is the number of temp-table sorts we expect if the GROUP BY
  # can use the same sort order as the ORDER BY. $nomatch is the number
  # of expected sorts if the GROUP BY and ORDER BY are not compatible.
  set match   1
  set nomatch 2
  if {$tn>=2} {
    set match   0
    set nomatch 1
  }

  do_sortcount_test 1.$tn.1.1 {
    SELECT a, sum(b) FROM t1 GROUP BY a ORDER BY a
  } $match {one 6 three 24 two 15}
  do_sortcount_test 1.$tn.1.2 {
    SELECT a, sum(b) FROM t1 GROUP BY a ORDER BY a DESC
  } $match {two 15 three 24 one 6}
  
  do_sortcount_test 1.$tn.2.1 {
    SELECT a, sum(b) FROM t1 GROUP BY a ORDER BY a||''
  } $nomatch {one 6 three 24 two 15}
  do_sortcount_test 1.$tn.2.2 {
    SELECT a, sum(b) FROM t1 GROUP BY a ORDER BY a||'' DESC
  } $nomatch {two 15 three 24 one 6}
  
  do_sortcount_test 1.$tn.3.1 {
    SELECT a, sum(b) FROM t1 GROUP BY a ORDER BY a NULLS LAST
  } $nomatch {one 6 three 24 two 15}
  do_sortcount_test 1.$tn.3.2 {
    SELECT a, sum(b) FROM t1 GROUP BY a ORDER BY a DESC NULLS FIRST
  } $nomatch {two 15 three 24 one 6}
}

#-------------------------------------------------------------------------
do_execsql_test 2.0 {
  CREATE TABLE t2(a, b, c);
  INSERT INTO t2 VALUES(1, 'one', 1);
  INSERT INTO t2 VALUES(1, 'two', 2);
  INSERT INTO t2 VALUES(1, 'one', 3);
  INSERT INTO t2 VALUES(1, 'two', 4);
  INSERT INTO t2 VALUES(1, 'one', 5);
  INSERT INTO t2 VALUES(1, 'two', 6);

  INSERT INTO t2 VALUES(2, 'one', 7);
  INSERT INTO t2 VALUES(2, 'two', 8);
  INSERT INTO t2 VALUES(2, 'one', 9);
  INSERT INTO t2 VALUES(2, 'two', 10);
  INSERT INTO t2 VALUES(2, 'one', 11);
  INSERT INTO t2 VALUES(2, 'two', 12);

  INSERT INTO t2 VALUES(NULL, 'one', 13);
  INSERT INTO t2 VALUES(NULL, 'two', 14);
  INSERT INTO t2 VALUES(NULL, 'one', 15);
  INSERT INTO t2 VALUES(NULL, 'two', 16);
  INSERT INTO t2 VALUES(NULL, 'one', 17);
  INSERT INTO t2 VALUES(NULL, 'two', 18);
}

foreach {tn idx} {
  1 {}

  2 { CREATE INDEX i2 ON t2(a, b)           }
  3 { CREATE INDEX i2 ON t2(a DESC, b DESC) }

  4 { CREATE INDEX i2 ON t2(a, b DESC)      }
  5 { CREATE INDEX i2 ON t2(a DESC, b)      }
} {
  execsql { DROP INDEX IF EXISTS i2 }
  execsql $idx


  set nSort [expr ($tn==2 || $tn==3) ? 0 : 1]
  do_sortcount_test 2.$tn.1.1 {
    SELECT a, b, sum(c) FROM t2 GROUP BY a, b ORDER BY a, b;
  } $nSort {{} one 45  {} two 48  1 one 9  1 two 12  2 one 27  2 two 30}
  do_sortcount_test 2.$tn.1.2 {
    SELECT a, b, sum(c) FROM t2 GROUP BY a, b ORDER BY a DESC, b DESC;
  } $nSort {2 two 30  2 one 27  1 two 12  1 one 9  {} two 48  {} one 45}

  set nSort [expr ($tn==4 || $tn==5) ? 0 : 1]
  do_sortcount_test 2.$tn.2.1 {
    SELECT a, b, sum(c) FROM t2 GROUP BY a, b ORDER BY a, b DESC;
  } $nSort { {} two 48  {} one 45  1 two 12  1 one 9  2 two 30 2 one 27 }
  do_sortcount_test 2.$tn.2.2 {
    SELECT a, b, sum(c) FROM t2 GROUP BY a, b ORDER BY a DESC, b;
  } $nSort { 2 one 27  2 two 30  1 one 9  1 two 12  {} one 45 {} two 48 }

  # ORDER BY can never piggyback on the GROUP BY sort if it uses 
  # non-standard NULLS behaviour.
  set nSort [expr $tn==1 ? 2 : 1]
  do_sortcount_test 2.$tn.3.1 {
    SELECT a, b, sum(c) FROM t2 GROUP BY a, b ORDER BY a, b DESC NULLS FIRST;
  } $nSort { {} two 48  {} one 45  1 two 12  1 one 9  2 two 30 2 one 27 }
  do_sortcount_test 2.$tn.3.2 {
    SELECT a, b, sum(c) FROM t2 GROUP BY a, b ORDER BY a DESC, b NULLS LAST;
  } $nSort { 2 one 27  2 two 30  1 one 9  1 two 12  {} one 45 {} two 48 }
}


finish_test

Changes to test/oserror.test.

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
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







+
+
+


-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+
+
+







#
# The xOpen() method of the unix VFS calls getcwd() as well as open().
# Although this does not appear to be documented in the man page, on OSX
# a call to getcwd() may fail if there are no free file descriptors. So
# an error may be reported for either open() or getcwd() here.
#
if {![clang_sanitize_address]} {
  unset -nocomplain rc
  unset -nocomplain nOpen
  set nOpen 20000
  do_test 1.1.1 {
    set ::log [list]
    list [catch {
      for {set i 0} {$i < 20000} {incr i} { sqlite3 dbh_$i test.db -readonly 1 }
    } msg] $msg
  } {1 {unable to open database file}}
    set ::rc [catch {
      for {set i 0} {$i < $::nOpen} {incr i} { sqlite3 dbh_$i test.db -readonly 1 }
    } msg]
    if {$::rc==0} {
      # Some system (ex: Debian) are able to create 20000+ file descriptiors
      # such systems will not fail here
      set x ok
    } elseif {$::rc==1 && $msg=="unable to open database file"} {
      set x ok
    } else {
      set x [list $::rc $msg]
    }
  } {ok}
  do_test 1.1.2 {
    catch { for {set i 0} {$i < 20000} {incr i} { dbh_$i close } }
  } {1}
  do_re_test 1.1.3 { 
    lindex $::log 0 
  } {^os_unix.c:\d+: \(\d+\) (open|getcwd)\(.*test.db\) - }
    catch { for {set i 0} {$i < $::nOpen} {incr i} { dbh_$i close } }
  } $::rc
  if {$rc} {
    do_re_test 1.1.3 { 
      lindex $::log 0 
    } {^os_unix.c:\d+: \(\d+\) (open|getcwd)\(.*test.db\) - }
  }
}


# Test a failure in open() due to the path being a directory.
#
do_test 1.2.1 {
  file mkdir dir.db

Changes to test/ossfuzz.c.

150
151
152
153
154
155
156








157
158
159
160
161
162
163
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171







+
+
+
+
+
+
+
+







  cx.iCutoffTime = cx.iLastCb + 10000;  /* Now + 10 seconds */
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  sqlite3_progress_handler(cx.db, 10, progress_handler, (void*)&cx);
#endif

  /* Set a limit on the maximum size of a prepared statement */
  sqlite3_limit(cx.db, SQLITE_LIMIT_VDBE_OP, 25000);

  /* Limit total memory available to SQLite to 20MB */
  sqlite3_hard_heap_limit64(20000000);

  /* Set a limit on the maximum length of a string or BLOB.  Without this
  ** limit, fuzzers will invoke randomblob(N) for a large N, and the process
  ** will timeout trying to generate the huge blob */
  sqlite3_limit(cx.db, SQLITE_LIMIT_LENGTH, 50000);

  /* Bit 1 of the selector enables foreign key constraints */
  sqlite3_db_config(cx.db, SQLITE_DBCONFIG_ENABLE_FKEY, uSelector&1, &rc);
  uSelector >>= 1;

  /* Do not allow debugging pragma statements that might cause excess output */
  sqlite3_set_authorizer(cx.db, block_debug_pragmas, 0);

Changes to test/pager1.test.

17
18
19
20
21
22
23




24
25
26
27
28
29
30
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34







+
+
+
+







source $testdir/wal_common.tcl
set testprefix pager1

if {[atomic_batch_write test.db]} {
  finish_test
  return
}
ifcapable !incrblob {
  finish_test
  return
}

# Do not use a codec for tests in this file, as the database file is
# manipulated directly using tcl scripts (using the [hexio_write] command).
#
do_not_use_codec

#
272
273
274
275
276
277
278
279

280
281
282
283
284
285
286
276
277
278
279
280
281
282

283
284
285
286
287
288
289
290







-
+







    INSERT INTO t1 VALUES(1, randomblob(1500));
    INSERT INTO t1 VALUES(2, randomblob(1500));
    INSERT INTO t1 VALUES(3, randomblob(1500));
    SELECT * FROM counter;
} {3 0}
do_catchsql_test pager1-3.1.3 {
    INSERT INTO t1 SELECT a+3, randomblob(1500) FROM t1
} {1 {CHECK constraint failed: counter}}
} {1 {CHECK constraint failed: i<5}}
do_execsql_test pager1-3.4 { SELECT * FROM counter } {3 0}
do_execsql_test pager1-3.5 { SELECT a FROM t1 } {1 2 3}
do_execsql_test pager1-3.6 { COMMIT } {}

foreach {tn sql tcl} {
  7  { PRAGMA synchronous = NORMAL ; PRAGMA temp_store = 0 } {
    testvfs tv -default 1
1760
1761
1762
1763
1764
1765
1766






1767
1768
1769
1770
1771
1772
1773
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783







+
+
+
+
+
+








db close
tv delete

#-------------------------------------------------------------------------
# Test specal "PRAGMA journal_mode=OFF" test cases.
#
# Do not run these tests for SQLITE_ENABLE_ZIPVFS builds. Such builds
# cause the pager to enter the error state if a statement transaction
# cannot be rolled back due to a prior "PRAGMA journal_mode=OFF". Which
# causes these tests to fail.
#
if {[info commands zip_register]==""} {
faultsim_delete_and_reopen
do_execsql_test pager1-14.1.1 {
  PRAGMA journal_mode = OFF;
  CREATE TABLE t1(a, b);
  BEGIN;
    INSERT INTO t1 VALUES(1, 2);
  COMMIT;
1784
1785
1786
1787
1788
1789
1790


1791
1792

1793
1794
1795
1796
1797
1798
1799
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812







+
+


+







do_catchsql_test pager1-14.1.4 {
  BEGIN;
    INSERT INTO t1(rowid, a, b) SELECT a+3, b, b FROM t1;
    INSERT INTO t1(rowid, a, b) SELECT a+3, b, b FROM t1;
} {1 {UNIQUE constraint failed: t1.rowid}}
do_execsql_test pager1-14.1.5 {
  COMMIT;
}
do_execsql_test pager1-14.1.6 {
  SELECT * FROM t1;
} {1 2 2 2}
}

#-------------------------------------------------------------------------
# Test opening and closing the pager sub-system with different values
# for the sqlite3_vfs.szOsFile variable.
#
faultsim_delete_and_reopen
do_execsql_test pager1-15.0 {
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
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







+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







db2 close
do_test pager1-18.4 {
  hexio_write test.db [expr ($pgno-1)*1024] 90000000
  sqlite3 db2 test.db
  catchsql { SELECT length(x||'') FROM t2 } db2
} {1 {database disk image is malformed}}
db2 close
extra_schema_checks 0
ifcapable altertable {
do_test pager1-18.5 {
  sqlite3 db ""
  sqlite3_db_config db DEFENSIVE 0
  execsql {
    CREATE TABLE t1(a, b);
    CREATE TABLE t2(a, b);
    PRAGMA writable_schema = 1;
    UPDATE sqlite_master SET rootpage=5 WHERE tbl_name = 't1';
    PRAGMA writable_schema = 0;
    ALTER TABLE t1 RENAME TO x1;
  }
  catchsql { SELECT * FROM x1 }
} {1 {database disk image is malformed}}
db close
  do_test pager1-18.5 {
    sqlite3 db ""
      sqlite3_db_config db DEFENSIVE 0
      execsql {
        CREATE TABLE t1(a, b);
        CREATE TABLE t2(a, b);
        PRAGMA writable_schema = 1;
        UPDATE sqlite_master SET rootpage=5 WHERE tbl_name = 't1';
        PRAGMA writable_schema = 0;
        ALTER TABLE t1 RENAME TO x1;
      }
    catchsql { SELECT * FROM x1 }
  } {1 {database disk image is malformed}}
  db close
}
extra_schema_checks 1

do_test pager1-18.6 {
  faultsim_delete_and_reopen
  db func a_string a_string
  execsql {
    PRAGMA page_size = 1024;
    CREATE TABLE t1(x);
2903
2904
2905
2906
2907
2908
2909
2910




























2911
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  sqlite3_db_status db CACHE_MISS 1
} {0 3 0}

do_test 43.3 {
  db eval { SELECT * FROM t3 }
  sqlite3_db_status db CACHE_MISS 0
} {0 1 0}

# 2022-03-01 Forum post https://sqlite.org/forum/forumpost/3b9e894312
# Ensure that max_page_count gets adjusted upward, if needed, on a
# ROLLBACK.
#
db close
sqlite3 db :memory:
do_execsql_test 44.1 {
  PRAGMA page_size=4096;
  PRAGMA auto_vacuum=FULL;
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b ANY);
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<50)
  INSERT INTO t1(a,b) SELECT x, zeroblob(1000) FROM c;
  CREATE TABLE t2 AS SELECT * FROM t1;
  PRAGMA page_count;
} {31}
do_execsql_test 44.2 {
  BEGIN;
  DROP TABLE t2;
  PRAGMA incremental_vacuum=50;
  PRAGMA page_count;
  PRAGMA max_page_count=2;
} {16 16}
do_execsql_test 44.3 {
  ROLLBACK;
  PRAGMA page_count;
  PRAGMA max_page_count;
} {31 31}

finish_test

Added test/pendingrace.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2023 January 31
#
# 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
set testprefix pendingrace

# This test file tests that a race condition surrounding hot-journal
# rollback that once existed has been resolved. The problem was that
# if, when attempting to upgrade from a SHARED to EXCLUSIVE lock in
# order to roll back a hot journal, a connection failed to take the
# lock, the file-descriptor was left holding a PENDING lock for 
# a very short amount of time. In a multi-threaded deployment, this
# could allow a second connection to read the database without rolling
# back the hot journal.
#

testvfs tvfs 
db close
sqlite3 db test.db -vfs tvfs

# Create a 20 page database using connection [db]. Connection [db] uses
# Tcl VFS wrapper "tvfs", but it is configured to do straight pass-through
# for now.
#
do_execsql_test 1.0 {
  PRAGMA cache_size = 5;
  CREATE TABLE t1(a, b);
  CREATE INDEX i1 ON t1(a, b);
  WITH s(i) AS (
    SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<10
  )
  INSERT INTO t1 SELECT hex(randomblob(100)), hex(randomblob(100)) FROM s;
  PRAGMA page_count;
} {20}

# Simulate a crash in another process. This leaves the db with a hot-journal.
# Without the journal the db is corrupt.
#
sqlite3 db2 test.db
do_execsql_test -db db2 1.1 {
  PRAGMA cache_size = 5;
  BEGIN;
    UPDATE t1 SET b=hex(randomblob(100));
}
db_save
db2 close
proc my_db_restore {} {
  forcecopy sv_test.db-journal test.db-journal

  set fd1 [open sv_test.db r]
  fconfigure $fd1 -encoding binary -translation binary
  set data [read $fd1]
  close $fd1

  set fd1 [open test.db w]
  fconfigure $fd1 -encoding binary -translation binary
  puts -nonewline $fd1 $data
  close $fd1
}
my_db_restore
do_test 1.2 {
  file exists test.db-journal
} {1}

# Set up connection [db2] to use Tcl VFS wrapper [tvfs2]. Which is configured
# so that the first call to xUnlock() fails. And then all VFS calls thereafter
# fail as well.
#
testvfs tvfs2
tvfs2 filter xUnlock
tvfs2 script xUnlock
set ::seen_unlock 0
proc xUnlock {args} {
  if {$::seen_unlock==0} {
    set ::seen_unlock 1
    tvfs2 ioerr 1 1
    tvfs2 filter {xLock xUnlock}
  }
  return ""
}
sqlite3 db2 test.db -vfs tvfs2

# Configure [tvfs] (used by [db]) so that within the first call to xAccess,
# [db2] attempts to read the db. This causes [db2] to fail to upgrade to
# EXCLUSIVE, leaving it with a PENDING lock. Which it holds on to, 
# as the xUnlock() and all subsequent VFS calls fail.
#
tvfs filter xAccess
tvfs script xAccess
set ::seen_access 0
proc xAccess {args} {
  if {$::seen_access==0} {
    set ::seen_access 1
    catch { db2 eval { SELECT count(*)+0 FROM t1 } }
    breakpoint
  }
  return ""
}

# Run an integrity check using [db].
do_catchsql_test 1.3 {
  PRAGMA integrity_check
} {1 {database is locked}}

db close
db2 close
tvfs delete
tvfs2 delete

finish_test



Changes to test/permutations.test.

86
87
88
89
90
91
92


93
94
95
96
97
98
99
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101







+
+







#
set alltests [list]
foreach f [glob $testdir/*.test] { lappend alltests [file tail $f] }
foreach f [glob -nocomplain            \
    $testdir/../ext/rtree/*.test       \
    $testdir/../ext/fts5/test/*.test   \
    $testdir/../ext/lsm1/test/*.test   \
    $testdir/../ext/recover/*.test     \
    $testdir/../ext/rbu/*.test         \
] {
  lappend alltests $f 
}
foreach f [glob -nocomplain $testdir/../ext/session/*.test] { 
  lappend alltests $f 
}

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
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







+


+


+
+
+
+
+





+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+







  vtab_err.test walslow.test walcrash.test walcrash3.test
  walthread.test rtree3.test indexfault.test securedel2.test
  sort3.test sort4.test fts4growth.test fts4growth2.test
  bigsort.test walprotocol.test mmap4.test fuzzer2.test
  walcrash2.test e_fkey.test backup.test

  fts4merge.test fts4merge2.test fts4merge4.test fts4check.test
  fts4merge5.test
  fts3cov.test fts3snippet.test fts3corrupt2.test fts3an.test
  fts3defer.test fts4langid.test fts3sort.test fts5unicode.test
  recovercorrupt.test

  rtree4.test
  sessionbig.test

  writecrash.test view3.test 
  fts5dlidx.test fts5ac.test fts4merge3.test fts5prefix.test
  sessionB.test
}]
if {[info exists ::env(QUICKTEST_INCLUDE)]} {
  set allquicktests [concat $allquicktests $::env(QUICKTEST_INCLUDE)]
}
if {[info exists ::env(QUICKTEST_OMIT)]} {
  # If environment variable QUICKTEST_OMIT is set, it is a comma-separated
  # list of regular expressions to match against test file names in
  # the "allquicktests" set. Any matches are excluded. Only the filename
  # is matched, not any directory component of the path.
  set all [list]
  foreach a $allquicktests {
    set bIn 1
  foreach x [split $::env(QUICKTEST_OMIT) ,] {
    regsub -all \\y$x\\y $allquicktests {} allquicktests
  }
    foreach x [split $::env(QUICKTEST_OMIT) ,] {
      if {[regexp $x [file tail $a]]} {
        set bIn 0
        break
      }
    }
    if {$bIn} {
      lappend all $a
    }
  }
  set allquicktests $all
}

# If the TEST_FAILURE environment variable is set, it means that we what to
# deliberately provoke test failures in order to test the test infrastructure.
# Only the main.test module is needed for this.
#
if {[info exists ::env(TEST_FAILURE)]} {
162
163
164
165
166
167
168
169







170
171
172
173
174
175
176
186
187
188
189
190
191
192

193
194
195
196
197
198
199
200
201
202
203
204
205
206







-
+
+
+
+
+
+
+








test_suite "veryquick" -prefix "" -description {
  "Very" quick test suite. Runs in minutes on a workstation.
  This test suite is the same as the "quick" tests, except that some files
  that test malloc and IO errors are omitted.
} -files [
  test_set $allquicktests -exclude *malloc* *ioerr* *fault* *bigfile* *_err* \
      *fts5corrupt* *fts5big* *fts5aj*
      *fts5corrupt* *fts5big* *fts5aj* *rbucrash*
]

test_suite "shell" -prefix "" -description {
  Run tests of the command-line shell
} -files [
  test_set [glob $testdir/shell*.test]
]

test_suite "extraquick" -prefix "" -description {
  "Extra" quick test suite. Runs in a few minutes on a workstation.
  This test suite is the same as the "veryquick" tests, except that
  slower tests are omitted.
} -files [
189
190
191
192
193
194
195

196

197
198
199
200
201
202
203
219
220
221
222
223
224
225
226

227
228
229
230
231
232
233
234







+
-
+







]

test_suite "valgrind" -prefix "" -description {
  Run the "veryquick" test suite with a couple of multi-process tests (that
  fail under valgrind) omitted.
} -files [
  test_set $allquicktests -exclude *malloc* *ioerr* *fault* *_err* wal.test \
              shell2.test shell6.test shell7.test \
              shell*.test crash8.test atof1.test selectG.test \
              crash8.test atof1.test selectG.test \
              tkt-fc62af4523.test numindex1.test corruptK.test
] -initialize {
  set ::G(valgrind) 1
} -shutdown {
  unset -nocomplain ::G(valgrind)
}

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
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







+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+













-
-
+
+







# Define the coverage related test suites:
#
#   coverage-wal
#
test_suite "coverage-wal" -description {
  Coverage tests for file wal.c.
} -files {
wal2big.test wal2recover.test wal2rewrite.test
wal2simple.test wal2snapshot.test wal2.test
  wal.test       wal2.test     wal3.test       walmode.test    
  walbak.test    walhook.test  walcrash2.test  walcksum.test
  walfault.test  walbig.test   walnoshm.test
  wal5.test
wal3.test wal4.test wal5.test
wal64k.test wal6.test wal7.test wal8.test wal9.test
walbak.test walbig.test walblock.test walcksum.test 
walfault.test walhook.test walmode.test walnoshm.test
waloverwrite.test walpersist.test walprotocol2.test
walprotocol.test walro2.test walrofault.test walro.test
walshared.test walslow.test wal.test
wal2savepoint.test wal2lock.test wal2recover2.test

  wal2concurrent.test
  concurrent.test concurrent2.test concurrent3.test
  concurrent4.test concurrent5.test concurrent6.test
  concurrent7.test
  concfault.test concfault2.test

  walvfs.test walfault2.test nockpt.test
  snapshot2.test snapshot3.test snapshot4.test
  snapshot_fault.test snapshot.test snapshot_up.test
  walcrash2.test walcrash3.test walcrash4.test walcrash.test
  wal2fault.test
} 

test_suite "coverage-pager" -description {
  Coverage tests for file pager.c.
} -files {
  pager1.test    pager2.test  pagerfault.test  pagerfault2.test
  walfault.test  walbak.test  journal2.test    tkt-9d68c883.test
} 

test_suite "coverage-analyze" -description {
  Coverage tests for file analyze.c.
} -files {
  analyze3.test analyze4.test analyze5.test analyze6.test
  analyze7.test analyze8.test analyze9.test analyzeA.test
  analyze.test analyzeB.test mallocA.test
  analyze7.test analyze8.test analyze9.test
  analyze.test mallocA.test
} 

test_suite "coverage-sorter" -description {
  Coverage tests for file vdbesort.c.
} -files {
  sort.test sortfault.test
} 
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
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







+
+
+
+
+
+
+
+
+
+










-
+







  Run some tests using the "test_onefile.c" demo
} -initialize {
  set ::G(perm:sqlite3_args) [list -vfs fs]
} -files {
  conflict.test  insert.test   insert2.test  insert3.test
  rollback.test  select1.test  select2.test  select3.test
}

# Run some tests using the "unix-excl" VFS.
#
test_suite "unix-excl" -description {
  Run some tests using the "unix-excl" VFS
} -initialize {
  set ::G(perm:sqlite3_args) [list -vfs unix-excl]
} -files {
  shmlock.test
}

# Run some tests using UTF-16 databases.
#
test_suite "utf16" -description {
  Run tests using UTF-16 databases
} -presql {
  pragma encoding = 'UTF-16'
} -files {
    alter.test alter3.test
    analyze.test analyze3.test analyze4.test analyze5.test analyze6.test
    analyze7.test analyze8.test analyze9.test analyzeA.test analyzeB.test
    analyze7.test analyze8.test analyze9.test
    auth.test bind.test blob.test capi2.test capi3.test collate1.test
    collate2.test collate3.test collate4.test collate5.test collate6.test
    conflict.test date.test delete.test expr.test fkey1.test func.test
    hook.test index.test insert2.test insert.test interrupt.test in.test
    intpkey.test ioerr.test join2.test join.test lastinsert.test
    laststmtchanges.test limit.test lock2.test lock.test main.test 
    memdb.test minmax.test misc1.test misc2.test misc3.test notnull.test
739
740
741
742
743
744
745
746

747
748
749
750
751
752
753
798
799
800
801
802
803
804

805
806
807
808
809
810
811
812







-
+







  e_fts3.test fts3cov.test fts3malloc.test fts3rnd.test
  fts3snippet.test mmapfault.test sessionfault.test sessionfault2.test

  # Exclude test scripts that use tcl IO to access journal files or count
  # the number of fsync() calls.
  pager.test exclusive.test jrnlmode.test sync.test misc1.test 
  journal1.test conflict.test crash8.test tkt3457.test io.test
  journal3.test 8_3_names.test
  journal3.test 8_3_names.test shmlock.test

  pager1.test async4.test corrupt.test filefmt.test pager2.test
  corrupt5.test corruptA.test pageropt.test

  # Exclude stmt.test, which expects sub-journals to use temporary files.
  stmt.test symlink.test

763
764
765
766
767
768
769


770
771
772
773
774
775
776
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837







+
+







  
  # This test assumes a journal file is created on disk.
  delete_db.test
  
  # This test depends on a successful recovery from the pager error 
  # state. Which is not possible with an in-memory journal
  fts5fault1.test

  recoverpgsz.test
}]

ifcapable mem3 {
  test_suite "memsys3" -description {
    Run tests using the allocator in mem3.c.
  } -files [test_set $::allquicktests -exclude {
    autovacuum.test           delete3.test              manydb.test
953
954
955
956
957
958
959
960


961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977

















978
979
980
981
982
983
984
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







-
+
+

















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







} -shutdown {
  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
  delete_db.test shmlock.test chunksize.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
  } -shutdown {
    unregister_demovfs
  } -files {
    insert.test   insert2.test  insert3.test rollback.test 
    select1.test  select2.test  select3.test
  }
}

test_suite "wal" -description {
  Run tests with journal_mode=WAL
} -initialize {
  set ::G(savepoint6_iterations) 100
} -shutdown {
  unset -nocomplain ::G(savepoint6_iterations)
} -files {
  savepoint.test     savepoint2.test     savepoint6.test
  trans.test         avtrans.test

  fts3aa.test  fts3ab.test  fts3ac.test  fts3ad.test
  fts3ae.test  fts3af.test  fts3ag.test  fts3ah.test
  fts3ai.test  fts3aj.test  fts3ak.test  fts3al.test
  fts3am.test  fts3an.test  fts3ao.test  fts3b.test
  fts3c.test   fts3d.test   fts3e.test   fts3query.test 
}

test_suite "wal2" -description {
  Run tests with journal_mode=WAL2
} -initialize {
  set ::G(savepoint6_iterations) 100
} -shutdown {
  unset -nocomplain ::G(savepoint6_iterations)
} -files {
  savepoint.test     savepoint2.test     savepoint6.test
  trans.test         avtrans.test
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
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







-
+





-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+







] -dbconfig {
  set ::sqlite3session_streams 1
}

test_suite "rbu" -description {
  RBU tests.
} -files [
  test_set [glob -nocomplain $::testdir/../ext/rbu/*.test] -exclude rbu.test
  test_set [glob -nocomplain $::testdir/../ext/rbu/*.test] 
]

test_suite "no_optimization" -description {
  Run test scripts with optimizations disabled using the
  sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS) interface.
} -files {
  where.test where2.test where3.test where4.test where5.test
  where6.test where7.test where8.test where9.test
  whereA.test whereB.test wherelimit.test
  select1.test select2.test select3.test select4.test select5.test
  select7.test select8.test selectA.test selectC.test
} -dbconfig {
} -files [
  test_set \
    [glob -nocomplain $::testdir/window*.test]                       \
    where.test where2.test where3.test where4.test where5.test       \
    where6.test where7.test where8.test where9.test                  \
    whereA.test whereB.test wherelimit.test                          \
    select1.test select2.test select3.test select4.test select5.test \
    select7.test select8.test selectA.test selectC.test              \
    -exclude windowpushd.test
] -dbconfig {
  optimization_control $::dbhandle all 0
}

test_suite "prepare" -description {
  Run tests with the db connection using sqlite3_prepare() instead of _v2().
} -dbconfig {
  $::dbhandle version -use-legacy-prepare 1
1058
1059
1060
1061
1062
1063
1064










1065
1066
1067
1068
1069
1070
1071
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163







+
+
+
+
+
+
+
+
+
+







} -shutdown {
  catch {db close}
  sqlite3_shutdown
  sqlite3_config_sorterref -1
  sqlite3_initialize
  autoinstall_test_functions
}

test_suite "maindbname" -prefix "" -description {
  Run the "veryquick" test suite with SQLITE_DBCONFIG_MAINDBNAME used to
  set the name of database 0 to "icecube".
} -files [
  test_set $allquicktests -exclude *malloc* *ioerr* *fault* *bigfile* *_err* \
      *fts5corrupt* *fts5big* *fts5aj*
] -dbconfig {
  dbconfig_maindbname_icecube $::dbhandle
}

# End of tests
#############################################################################

# run_tests NAME OPTIONS
#
# where available options are:  
1088
1089
1090
1091
1092
1093
1094
1095
1096








1097











1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
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







-
-
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+


-








  set ::G(perm:name)         $name
  set ::G(perm:prefix)       $options(-prefix)
  set ::G(isquick)           1
  set ::G(perm:dbconfig)     $options(-dbconfig)
  set ::G(perm:presql)       $options(-presql)

  foreach file [lsort $options(-files)] {
    uplevel $options(-initialize)
  set filelist [lsort $options(-files)]
  if {[info exists ::env(TCLTEST_PART)]} {
    regexp {^([0-9]*)/([0-9]*)$} $::env(TCLTEST_PART) -> A B
    set nFile [expr {([llength $filelist]+$B-1)/$B}]
    set filelist [lrange $filelist [expr ($A-1)*$nFile] [expr $A*$nFile-1]]
  }

  foreach file $filelist {
    if {[file tail $file] == $file} { set file [file join $::testdir $file] }

    if {[info exists ::env(SQLITE_TEST_PATTERN_LIST)]} {
      set ok 0
      foreach p $::env(SQLITE_TEST_PATTERN_LIST) {
        set p [string map {% *} $p]
        if {[string match $p [file tail $file]]} {set ok 1 ; break}
      }
      if {!$ok} continue
    }

    uplevel $options(-initialize)
    slave_test_file $file
    uplevel $options(-shutdown)

    unset -nocomplain ::G(perm:sqlite3_args)
  }

  unset ::G(perm:name)
  unset ::G(perm:prefix)
  unset ::G(perm:dbconfig)
  unset ::G(perm:presql)
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
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







+




















-
+



+


      # See if the first argument is a named test-suite.
      #
      set suite [file tail [lindex $argv 0]]
      if {[info exists ::testspec($suite)]} {
        set S $::testspec($suite)
        set i 1
      } else {
        set suite default
        set S [list]
        set i 0
      }

      set extra ""
      if {$i < [llength $argv] && [string range [lindex $argv $i] 0 0]!="-" } {
        set files [list]
        for {} {$i < [llength $argv]} {incr i} {
          set pattern [string map {% *} [lindex $argv $i]]
          if {[string range $pattern 0 0]=="-"} break
          foreach f $::alltests {
            set tail [file tail $f]
            if {[lsearch $files $f]<0 && [string match $pattern $tail]} {
              lappend files $f
            }
          }
        }
        set extra [list -files $files]
      }

      eval run_tests $suite $S $extra
      eval [list run_tests $suite] $S $extra
    }
  }
  main $argv
  set argv {}
  finish_test
}

Changes to test/pg_common.tcl.

14
15
16
17
18
19
20


21
22
23
24
25
26
27
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29







+
+







package require Pgtcl

set db [pg_connect -conninfo "dbname=postgres user=postgres password=postgres"]
sqlite3 sqlite ""

proc execsql {sql} {

  set sql [string map {{WITHOUT ROWID} {}} $sql]

  set lSql [list]
  set frag ""
  while {[string length $sql]>0} {
    set i [string first ";" $sql]
    if {$i>=0} {
      append frag [string range $sql 0 $i]
      set sql [string range $sql $i+1 end]
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
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







+




+

-
-
+
+
+
+
+

+
-
-
-
+
+
+
+
+
+










+
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+







  }
  if {$frag != ""} {
    lappend lSql $frag
  }
  #puts $lSql

  set ret ""
  set nChar 0
  foreach stmt $lSql {
    set res [pg_exec $::db $stmt]
    set err [pg_result $res -error]
    if {$err!=""} { error $err }

    for {set i 0} {$i < [pg_result $res -numTuples]} {incr i} {
      if {$i==0} {
        set ret [pg_result $res -getTuple 0]
      set t [pg_result $res -getTuple $i]
      set nNew [string length $t]
      if {$nChar>0 && ($nChar+$nNew+3)>75} {
        append ret "\n  "
        set nChar 0
      } else {
        if {$nChar>0} {
        append ret "   [pg_result $res -getTuple $i]"
      }
      # lappend ret {*}[pg_result $res -getTuple $i]
          append ret "   "
          incr nChar 3
        }
      }
      incr nChar $nNew
      append ret $t
    }
    pg_result $res -clear
  }

  set ret
}

proc execsql_test {tn sql} {
  set res [execsql $sql]
  set sql [string map {string_agg group_concat} $sql]
  # set sql [string map [list {NULLS FIRST} {}] $sql]
  # set sql [string map [list {NULLS LAST} {}] $sql]
  puts $::fd "do_execsql_test $tn {"
  puts $::fd "  [string trim $sql]"
  puts $::fd "} {$res}"
  puts $::fd ""
}

proc errorsql_test {tn sql} {
  set rc [catch {execsql $sql} msg]
  if {$rc==0} {
    error "errorsql_test SQL did not cause an error!"
  }
  set msg [lindex [split [string trim $msg] "\n"] 0]
  puts $::fd "# PG says $msg"
  set sql [string map {string_agg group_concat} $sql]
  puts $::fd "do_test $tn { catch { execsql {"
  puts $::fd "  [string trim $sql]"
  puts $::fd "} } } 1"
  puts $::fd ""
}

# Same as [execsql_test], except coerce all results to floating point values
# with two decimal points.
#
proc execsql_float_test {tn sql} {
  set F "%.4f"
  set T 0.0001
84
85
86
87
88
89
90

91
92
93
94

95
96
97
98
99
100
101
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130







+




+







puts $::fd [subst -nocommands {
do_test $tn {
  set myres {}
  foreach r [db eval {$sql}] {
    lappend myres [format $F [set r]]
  }
  set res2 {$res2}
  set i 0
  foreach r [set myres] r2 [set res2] {
    if {[set r]<([set r2]-$T) || [set r]>([set r2]+$T)} {
      error "list element [set i] does not match: got=[set r] expected=[set r2]"
    }
    incr i
  }
  set {} {}
} {}
}]
}

proc start_test {name date} {

Changes to test/pragma.test.

247
248
249
250
251
252
253

























254
255
256
257
258
259
260
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







} {0}
do_test pragma-1.14.4 {
  execsql {
    PRAGMA synchronous=10;
    PRAGMA synchronous;
  }
} {2}

do_execsql_test 1.15.1 {
  PRAGMA default_cache_size = 0;
}
do_execsql_test 1.15.2 {
  PRAGMA default_cache_size;
} $DFLT_CACHE_SZ
do_execsql_test 1.15.3 {
  PRAGMA default_cache_size = -500;
}
do_execsql_test 1.15.4 {
  PRAGMA default_cache_size;
} 500
do_execsql_test 1.15.3 {
  PRAGMA default_cache_size = 500;
}
do_execsql_test 1.15.4 {
  PRAGMA default_cache_size;
} 500
db close
hexio_write test.db 48 FFFFFF00
sqlite3 db test.db
do_execsql_test 1.15.4 {
  PRAGMA default_cache_size;
} 256
} ;# ifcapable pager_pragmas

# Test turning "flag" pragmas on and off.
#
ifcapable debug {
  # Pragma "vdbe_listing" is only available if compiled with SQLITE_DEBUG
  #
358
359
360
361
362
363
364
365
366
367





368
369




370
371
372
373
374
375
376
383
384
385
386
387
388
389



390
391
392
393
394


395
396
397
398
399
400
401
402
403
404
405







-
-
-
+
+
+
+
+
-
-
+
+
+
+







      }
    } {{row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2}}
    do_test pragma-3.5 {
      execsql {
        PRAGMA integrity_check=4
      }
    } {{row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2} {row 1 missing from index i2}}
    do_test pragma-3.6 {
      execsql {
        PRAGMA integrity_check=xyz
    do_catchsql_test pragma-3.6 {
      PRAGMA integrity_check=xyz
    } {1 {no such table: xyz}}
    do_catchsql_test pragma-3.6b {
      PRAGMA integrity_check=t2
      }
    } {{row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2}}
    } {0 {{row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2}}}
    do_catchsql_test pragma-3.6c {
      PRAGMA integrity_check=sqlite_schema
    } {0 ok}
    do_test pragma-3.7 {
      execsql {
        PRAGMA integrity_check=0
      }
    } {{row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2}}
  
    # Add additional corruption by appending unused pages to the end of
394
395
396
397
398
399
400
401

402
403
404
405
406
407
408
409






410
411
412
413
414
415
416
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







-
+








+
+
+
+
+
+







    } {ok}
    do_test pragma-3.8.1 {
      execsql {PRAGMA quick_check}
    } {ok}
    do_test pragma-3.8.2 {
      execsql {PRAGMA QUICK_CHECK}
    } {ok}
    do_test pragma-3.9 {
    do_test pragma-3.9a {
      execsql {
        ATTACH 'testerr.db' AS t2;
        PRAGMA integrity_check
      }
    } {{*** in database t2 ***
Page 4 is never used
Page 5 is never used
Page 6 is never used} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2}}
    do_execsql_test pragma-3.9b {
      PRAGMA t2.integrity_check=t2;
    } {{row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2}}
    do_execsql_test pragma-3.9c {
      PRAGMA t2.integrity_check=sqlite_schema;
    } {ok}
    do_test pragma-3.10 {
      execsql {
        PRAGMA integrity_check=1
      }
    } {{*** in database t2 ***
Page 4 is never used}}
    do_test pragma-3.11 {
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
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
638
639
640
641
642
643







+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+









-
+














+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    db eval {PRAGMA integrity_check}
  } {ok}
}

# Verify that PRAGMA integrity_check catches UNIQUE and NOT NULL
# constraint violations.
#
ifcapable altertable {
sqlite3_db_config db DEFENSIVE 0
do_execsql_test pragma-3.20 {
  CREATE TABLE t1(a,b);
  CREATE INDEX t1a ON t1(a);
  INSERT INTO t1 VALUES(1,1),(2,2),(3,3),(2,4),(NULL,5),(NULL,6);
  PRAGMA writable_schema=ON;
  UPDATE sqlite_master SET sql='CREATE UNIQUE INDEX t1a ON t1(a)'
   WHERE name='t1a';
  UPDATE sqlite_master SET sql='CREATE TABLE t1(a NOT NULL,b)'
   WHERE name='t1';
  PRAGMA writable_schema=OFF;
  ALTER TABLE t1 RENAME TO t1x;
  PRAGMA integrity_check;
} {{non-unique entry in index t1a} {NULL value in t1x.a} {non-unique entry in index t1a} {NULL value in t1x.a}}
do_execsql_test pragma-3.21 {
  PRAGMA integrity_check(3);
} {{non-unique entry in index t1a} {NULL value in t1x.a} {non-unique entry in index t1a}}
do_execsql_test pragma-3.22 {
  PRAGMA integrity_check(2);
} {{non-unique entry in index t1a} {NULL value in t1x.a}}
do_execsql_test pragma-3.23 {
  PRAGMA integrity_check(1);
} {{non-unique entry in index t1a}}
  sqlite3_db_config db DEFENSIVE 0
    do_execsql_test pragma-3.20 {
      CREATE TABLE t1(a,b);
      CREATE INDEX t1a ON t1(a);
      INSERT INTO t1 VALUES(1,1),(2,2),(3,3),(2,4),(NULL,5),(NULL,6);
      PRAGMA writable_schema=ON;
      UPDATE sqlite_master SET sql='CREATE UNIQUE INDEX t1a ON t1(a)'
        WHERE name='t1a';
      UPDATE sqlite_master SET sql='CREATE TABLE t1(a NOT NULL,b)'
        WHERE name='t1';
      PRAGMA writable_schema=OFF;
      ALTER TABLE t1 RENAME TO t1x;
      PRAGMA integrity_check;
    } {{non-unique entry in index t1a} {NULL value in t1x.a} {non-unique entry in index t1a} {NULL value in t1x.a}}
  do_execsql_test pragma-3.21 {
    PRAGMA integrity_check(3);
  } {{non-unique entry in index t1a} {NULL value in t1x.a} {non-unique entry in index t1a}}
  do_execsql_test pragma-3.22 {
    PRAGMA integrity_check(2);
  } {{non-unique entry in index t1a} {NULL value in t1x.a}}
  do_execsql_test pragma-3.23 {
    PRAGMA integrity_check(1);
  } {{non-unique entry in index t1a}}
}

# PRAGMA integrity check (or more specifically the sqlite3BtreeCount()
# interface) used to leave index cursors in an inconsistent state
# which could result in an assertion fault in sqlite3BtreeKey()
# called from saveCursorPosition() if content is removed from the
# index while the integrity_check is still running.  This test verifies
# that problem has been fixed.
#
do_test pragma-3.30 {
  db close
  catch { db close }
  delete_file test.db
  sqlite3 db test.db
  db eval {
    CREATE TABLE t1(a,b,c);
    WITH RECURSIVE
      c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<100)
    INSERT INTO t1(a,b,c) SELECT i, printf('xyz%08x',i), 2000-i FROM c;
    CREATE INDEX t1a ON t1(a);
    CREATE INDEX t1bc ON t1(b,c);
  }
  db eval {PRAGMA integrity_check} {
     db eval {DELETE FROM t1}
  }
} {}

# The values stored in indexes must be byte-for-byte identical to the
# values stored in tables.
#
reset_db
do_execsql_test pragma-3.40 {
  CREATE TABLE t1(
    a INTEGER PRIMARY KEY,
    b TEXT COLLATE nocase,
    c INT COLLATE nocase,
    d TEXT
  );
  INSERT INTO t1(a,b,c,d) VALUES
    (1, 'one','one','one'),
    (2, 'two','two','two'),
    (3, 'three','three','three'),
    (4, 'four','four','four'),
    (5, 'five','five','five');
  CREATE INDEX t1bcd ON t1(b,c,d);
  CREATE TABLE t2(
    a INTEGER PRIMARY KEY,
    b TEXT COLLATE nocase,
    c INT COLLATE nocase,
    d TEXT
  );
  INSERT INTO t2(a,b,c,d) VALUES
    (1, 'one','one','one'),
    (2, 'two','two','TWO'),
    (3, 'three','THREE','three'),
    (4, 'FOUR','four','four'),
    (5, 'FIVE','FIVE','five');
  CREATE INDEX t2bcd ON t2(b,c,d);
  CREATE TEMP TABLE saved_schema AS SELECT name, rootpage FROM sqlite_schema;
  PRAGMA writable_schema=ON;
  UPDATE sqlite_schema
     SET rootpage=(SELECT rootpage FROM saved_schema WHERE name='t2bcd')
   WHERE name='t1bcd';
  UPDATE sqlite_schema
     SET rootpage=(SELECT rootpage FROM saved_schema WHERE name='t1bcd')
   WHERE name='t2bcd';
  PRAGMA Writable_schema=RESET;
  SELECT integrity_check AS x FROM pragma_integrity_check ORDER BY 1;
} {
  {row 2 missing from index t1bcd}
  {row 2 missing from index t2bcd}
  {row 3 values differ from index t1bcd}
  {row 3 values differ from index t2bcd}
  {row 4 values differ from index t1bcd}
  {row 4 values differ from index t2bcd}
  {row 5 values differ from index t1bcd}
  {row 5 values differ from index t2bcd}
}
db eval {DROP TABLE t2}

# Test modifying the cache_size of an attached database.
ifcapable pager_pragmas&&attach {
do_test pragma-4.1 {
  execsql {
    ATTACH 'test2.db' AS aux;
    pragma aux.cache_size;
776
777
778
779
780
781
782
783

784
785
786
787
788
789
790
866
867
868
869
870
871
872

873
874
875
876
877
878
879
880







-
+







    );
  }
  capture_pragma db out {PRAGMA table_info(test_table)}
  db eval {SELECT cid, "name", type, "notnull", dflt_value, pk FROM out
            ORDER BY cid}
} [concat \
  {0 one INT 1 -1 0} \
  {1 two text 0 {} 0} \
  {1 two TEXT 0 {} 0} \
  {2 three {VARCHAR(45, 65)} 0 'abcde' 0} \
  {3 four REAL 0 X'abcdef' 0} \
  {4 five {} 0 CURRENT_TIME 0} \
]
do_test pragma-6.8 {
  execsql {
    CREATE TABLE t68(a,b,c,PRIMARY KEY(a,b,a,c));
863
864
865
866
867
868
869

870

871
872

873
874
875




876
877


878
879
880
881
882
883
884
885
953
954
955
956
957
958
959
960

961


962



963
964
965
966


967
968

969
970
971
972
973
974
975







+
-
+
-
-
+
-
-
-
+
+
+
+
-
-
+
+
-







  }
} {}
do_test pragma-8.1.2 {
  execsql2 {
    PRAGMA schema_version;
  }
} {schema_version 105}
sqlite3_db_config db DEFENSIVE 1
do_test pragma-8.1.3 {
do_execsql_test pragma-8.1.3 {
  execsql {
    PRAGMA schema_version = 106;
  PRAGMA schema_version = 106;
  }
} {}
do_test pragma-8.1.4 {
  PRAGMA schema_version;
} 105
sqlite3_db_config db DEFENSIVE 0
do_execsql_test pragma-8.1.4 {
  execsql {
    PRAGMA schema_version;
  PRAGMA schema_version = 106;
  PRAGMA schema_version;
  }
} 106

# Check that creating a table modifies the schema-version (this is really
# to verify that the value being read is in fact the schema version).
do_test pragma-8.1.5 {
  execsql {
    CREATE TABLE t4(a, b, c);
1830
1831
1832
1833
1834
1835
1836

1837
1838
1839
1840

1841
1842
1843
1844
1845
1846
1847
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930

1931
1932
1933
1934
1935
1936
1937
1938







+



-
+







sqlite3 db2 test.db
do_test 23.1 {
  db eval {
    CREATE TABLE t1(a INTEGER PRIMARY KEY,b,c,d);
    CREATE INDEX i1 ON t1(b,c);
    CREATE INDEX i2 ON t1(c,d);
    CREATE INDEX i2x ON t1(d COLLATE nocase, c DESC);
    CREATE INDEX i3 ON t1(d,b+c,c);
    CREATE TABLE t2(x INTEGER REFERENCES t1);
  }
  db2 eval {SELECT name FROM sqlite_master}
} {t1 i1 i2 i2x t2}
} {t1 i1 i2 i2x i3 t2}
do_test 23.2a {
  db eval {
    DROP INDEX i2;
    CREATE INDEX i2 ON t1(c,d,b);
  }
  capture_pragma db2 out {PRAGMA index_info(i2)}
  db2 eval {SELECT cid, name, '|' FROM out ORDER BY seqno}
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
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
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994







-
+

-
+


-
-
+
+
+



















+
+
+







} {2 c 0 BINARY 1 | 3 d 0 BINARY 1 | 1 b 0 BINARY 1 | -1 {} 0 BINARY 0 |}

# (The first column of output from PRAGMA index_xinfo is...)
# EVIDENCE-OF: R-00197-14279 The rank of the column within the index. (0
# means left-most. Key columns come before auxiliary columns.)
#
# (The second column of output from PRAGMA index_xinfo is...)
# EVIDENCE-OF: R-40889-06838 The rank of the column within the table
# EVIDENCE-OF: R-06603-49335 The rank of the column within the table
# being indexed, or -1 if the index-column is the rowid of the table
# being indexed.
# being indexed and -2 if the index is on an expression.
#
# (The third column of output from PRAGMA index_xinfo is...)
# EVIDENCE-OF: R-22751-28901 The name of the column being indexed, or
# NULL if the index-column is the rowid of the table being indexed.
# EVIDENCE-OF: R-40641-22898 The name of the column being indexed, or
# NULL if the index-column is the rowid of the table being indexed or an
# expression.
#
# (The fourth column of output from PRAGMA index_xinfo is...)
# EVIDENCE-OF: R-11847-09179 1 if the index-column is sorted in reverse
# (DESC) order by the index and 0 otherwise.
#
# (The fifth column of output from PRAGMA index_xinfo is...)
# EVIDENCE-OF: R-15313-19540 The name for the collating sequence used to
# compare values in the index-column.
#
# (The sixth column of output from PRAGMA index_xinfo is...)
# EVIDENCE-OF: R-14310-64553 1 if the index-column is a key column and 0
# if the index-column is an auxiliary column.
#
do_test 23.2c {
  db2 eval {PRAGMA index_xinfo(i2)}
} {0 2 c 0 BINARY 1 1 3 d 0 BINARY 1 2 1 b 0 BINARY 1 3 -1 {} 0 BINARY 0}
do_test 23.2d {
  db2 eval {PRAGMA index_xinfo(i2x)}
} {0 3 d 0 nocase 1 1 2 c 1 BINARY 1 2 -1 {} 0 BINARY 0}
do_test 23.2e {
  db2 eval {PRAGMA index_xinfo(i3)}
} {0 3 d 0 BINARY 1 1 -2 {} 0 BINARY 1 2 2 c 0 BINARY 1 3 -1 {} 0 BINARY 0}

# EVIDENCE-OF: R-64103-17776 PRAGMA schema.index_list(table-name); This
# pragma returns one row for each index associated with the given table.
#
# (The first column of output from PRAGMA index_list is...)
# EVIDENCE-OF: R-02753-24748 A sequence number assigned to each index
# for internal tracking purposes.
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
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015








2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031







+





+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+







# (The fourth column of output from PRAGMA index_list is...)
# EVIDENCE-OF: R-36609-39554 "c" if the index was created by a CREATE
# INDEX statement, "u" if the index was created by a UNIQUE constraint,
# or "pk" if the index was created by a PRIMARY KEY constraint.
#
do_test 23.3 {
  db eval {
    DROP INDEX IF EXISTS i3;
    CREATE INDEX i3 ON t1(d,b,c);
  }
  capture_pragma db2 out {PRAGMA index_list(t1)}
  db2 eval {SELECT seq, name, "unique", origin, '|' FROM out ORDER BY seq}
} {0 i3 0 c | 1 i2 0 c | 2 i2x 0 c | 3 i1 0 c |}
ifcapable altertable {
do_test 23.4 {
  db eval {
    ALTER TABLE t1 ADD COLUMN e;
  }
  db2 eval {
    PRAGMA table_info(t1);
  }
} {/4 e {} 0 {} 0/}
  do_test 23.4 {
    db eval {
      ALTER TABLE t1 ADD COLUMN e;
    }
    db2 eval {
      PRAGMA table_info(t1);
    }
  } {/4 e {} 0 {} 0/}
}
do_test 23.5 {
  db eval {
    DROP TABLE t2;
    CREATE TABLE t2(x, y INTEGER REFERENCES t1);
  }
  db2 eval {
    PRAGMA foreign_key_list(t2);

Changes to test/pragma3.test.

250
251
252
253
254
255
256





























257
258
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


  } {2 111 222}
  do_test pragma3-430 {
    db2 eval {PRAGMA data_version; SELECT * FROM t1;}
  } {3 111 222}
  db2 close
}
}

#-------------------------------------------------------------------------
# Check that empty write transactions do not cause the return of "PRAGMA
# data_version" to be decremented with journal_mode=PERSIST and
# locking_mode=EXCLUSIVE
#
foreach {tn sql} {
  A {
  }
  B {
    PRAGMA journal_mode = PERSIST;
    PRAGMA locking_mode = EXCLUSIVE;
  }
} {
  reset_db
  execsql $sql

  do_execsql_test pragma3-510$tn {
    CREATE TABLE t1(x, y);
    INSERT INTO t1 VALUES(1, 2);
    PRAGMA data_version;
  } {1}

  do_execsql_test pragma3-520$tn {
    BEGIN EXCLUSIVE;
    COMMIT;
    PRAGMA data_version;
  } {1}
}

finish_test

Changes to test/pragma4.test.

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
40
41
42
43
44
45
46

47
48
49
50
51
52
53







-







 10 "PRAGMA defer_foreign_keys = 1"
 11 "PRAGMA empty_result_callbacks = 1"
 12 "PRAGMA encoding = 'utf-8'"
 13 "PRAGMA foreign_keys = 1"
 14 "PRAGMA full_column_names = 1"
 15 "PRAGMA fullfsync = 1"
 16 "PRAGMA ignore_check_constraints = 1"
 17 "PRAGMA legacy_file_format = 1"
 18 "PRAGMA page_size = 511"
 19 "PRAGMA page_size = 512"
 20 "PRAGMA query_only = false"
 21 "PRAGMA read_uncommitted = true"
 22 "PRAGMA recursive_triggers = false"
 23 "PRAGMA reverse_unordered_selects = false"
 24 "PRAGMA schema_version = 211"
117
118
119
120
121
122
123
124
125









126
127
128
129
130
131
132
116
117
118
119
120
121
122


123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138







-
-
+
+
+
+
+
+
+
+
+







  0 d {} 0 {} 0 1 e {} 0 {} 0 2 f {} 0 {} 0
}
do_test 4.1.4 { 
  sqlite3 db3 test.db
  sqlite3 db2 test.db2
  execsql { DROP TABLE t1 } db3
  execsql { DROP TABLE t2 } db2
} {}
do_execsql_test 4.1.5 { PRAGMA table_info(t1) }
} {}  
if {[permutation]=="prepare"} {
  do_catchsql_test 4.1.5a { 
    PRAGMA table_info(t1) 
  } {1 {database schema has changed}}
}
do_execsql_test 4.1.5 { 
  PRAGMA table_info(t1) 
}
do_execsql_test 4.1.6 { PRAGMA table_info(t2) }

db2 close
db3 close
reset_db
forcedelete test.db2
do_execsql_test 4.2.1 {
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
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







+


















+
+
+







}
do_test 4.3.4 { 
  sqlite3 db3 test.db
  sqlite3 db2 test.db2
  execsql { DROP INDEX i1 } db3
  execsql { DROP INDEX i2 } db2
} {}
if {[permutation]=="prepare"} { catchsql { SELECT * FROM sqlite_master } }
ifcapable vtab {
  do_execsql_test 4.3.5 { SELECT * FROM pragma_index_info('i1') } 
  do_execsql_test 4.3.6 { SELECT * FROM pragma_index_info('i2') } 
}

execsql {SELECT * FROM main.sqlite_master, aux.sqlite_master}
do_execsql_test 4.4.0 {
  CREATE INDEX main.i1 ON t1(b, c);
  CREATE INDEX aux.i2 ON t2(e, f);
}
ifcapable vtab {
  do_execsql_test 4.4.1 { SELECT * FROM pragma_index_list('t1') } {0 i1 0 c 0}
  do_execsql_test 4.4.2 { SELECT * FROM pragma_index_list('t2') } {0 i2 0 c 0}
}
do_test 4.4.3 { 
  execsql { DROP INDEX i1 } db3
  execsql { DROP INDEX i2 } db2
} {}
if {[permutation]=="prepare"} { 
  catchsql { SELECT * FROM sqlite_master, aux.sqlite_master }
}
ifcapable vtab {
  do_execsql_test 4.4.5 { SELECT * FROM pragma_index_list('t1') } {}
  do_execsql_test 4.4.6 { SELECT * FROM pragma_index_list('t2') } {}
}
execsql {SELECT * FROM main.sqlite_master, aux.sqlite_master}

do_execsql_test 4.5.0 {
212
213
214
215
216
217
218



219
220
221
222
223
224
225
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238







+
+
+







    0 0 t2 r d {NO ACTION} {NO ACTION} NONE
  }
}
do_test 4.5.3 { 
  execsql { DROP TABLE c1 } db3
  execsql { DROP TABLE c2 } db2
} {}
if {[permutation]=="prepare"} { 
  catchsql { SELECT * FROM sqlite_master, aux.sqlite_master }
}
ifcapable vtab {
  do_execsql_test 4.5.4 { SELECT * FROM pragma_foreign_key_list('c1') }
  do_execsql_test 4.5.5 { SELECT * FROM pragma_foreign_key_list('c2') } 
}
execsql {SELECT * FROM main.sqlite_master, aux.sqlite_master}

do_execsql_test 4.6.0 {
237
238
239
240
241
242
243
244










245
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268








+
+
+
+
+
+
+
+
+
+

do_test 4.6.3 { 
  execsql { DROP TABLE c2 } db2
} {}
do_execsql_test 4.6.4 { pragma foreign_key_check('c1') } {c1 1 t1 0}
do_catchsql_test 4.6.5 { 
  pragma foreign_key_check('c2') 
} {1 {no such table: c2}}

do_execsql_test 5.0 {
  CREATE TABLE t4(a DEFAULT 'abc' /* comment */, b DEFAULT -1 -- comment
     , c DEFAULT +4.0 /* another comment */
  );
  PRAGMA table_info = t4;
} {
  0 a {} 0 'abc' 0 1 b {} 0 -1 0 2 c {} 0 +4.0 0
}


finish_test

Changes to test/pragma5.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
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













-
+

-
+


















+
+
+
+


+
-
+


+
-
+







# 2017 August 25
#
# 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 file implements tests for the PRAGMA command. Specifically,
# those pragmas enabled at build time by setting:
# those pragmas that are not disabled at build time by setting:
#
#   -DSQLITE_INTROSPECTION_PRAGMAS
#   -DSQLITE_OMIT_INTROSPECTION_PRAGMAS
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix pragma5

if { [catch {db one "SELECT count(*) FROM pragma_function_list"}] } {
  finish_test
  return
}

db function external external

do_execsql_test 1.0 {
  PRAGMA table_info(pragma_function_list)
} {
  0 name {} 0 {} 0 
  1 builtin {} 0 {} 0
  2 type {} 0 {} 0
  3 enc {} 0 {} 0
  4 narg {} 0 {} 0
  5 flags {} 0 {} 0
}
do_execsql_test 1.1 {
  SELECT DISTINCT name, builtin
  SELECT * FROM pragma_function_list WHERE name='upper' AND builtin
    FROM pragma_function_list WHERE name='upper' AND builtin
} {upper 1}
do_execsql_test 1.2 {
  SELECT DISTINCT name, builtin
  SELECT * FROM pragma_function_list WHERE name LIKE 'exter%';
    FROM pragma_function_list WHERE name LIKE 'exter%';
} {external 0}

ifcapable fts5 {
  do_execsql_test 2.0 {
    PRAGMA table_info(pragma_module_list)
  } {
    0 name {} 0 {} 0 

Added test/prefixes.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2018-01-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 prefixes.c extension
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix unionvtab

ifcapable !vtab {
  finish_test
  return
}

load_static_extension db prefixes

foreach {tn zLeft zRight expected} {
  1 abcdxxx abcyy    3
  2 abcdxxx bcyyy    0
  3 abcdxxx ab       2
  4 ab      abcd     2

  5 "xyz\u1234xz" "xyz\u1234xy" 5
  6 "xyz\u1234"   "xyz\u1234xy" 4
  7 "xyz\u1234"   "xyz\u1234"   4
  8 "xyz\u1234xy" "xyz\u1234"   4
  9 "xyz\u1234xy" "xyz\u1233"   3
 10 "xyz\u1234xy" "xyz\u1235"   3
} {
  do_execsql_test 1.$tn { SELECT prefix_length($zLeft, $zRight) } $expected
}


do_execsql_test 2.0 {
  CREATE TABLE t1(k TEXT UNIQUE, v INTEGER);
  INSERT INTO t1 VALUES
    ('aback', 1),
    ('abaft', 2),
    ('abandon', 3),
    ('abandoned', 4),
    ('abandoning', 5),
    ('abandonment', 6),
    ('abandons', 7),
    ('abase', 8),
    ('abased', 9),
    ('abasement', 10),
    ('abasements', 11),
    ('abases', 12),
    ('abash', 13),
    ('abashed', 14),
    ('abashes', 15),
    ('abashing', 16),
    ('abasing', 17),
    ('abate', 18),
    ('abated', 19),
    ('abatement', 20),
    ('abatements', 21);
}

foreach {tn INPUT expected} {
  1 abatementt   abatement
  2 abashet      abash
  3 abandonio    abandon
  4 abasemenu    abase
} {
  do_execsql_test 2.$tn {
    WITH finder(str) AS (
      SELECT (SELECT max(k) FROM t1 WHERE k<=$INPUT)
        UNION ALL
        SELECT (
          SELECT max(k) FROM t1 
          WHERE k<=substr($INPUT, 1, prefix_length(finder.str, $INPUT))
        ) FROM finder WHERE length(finder.str)>0
      )
    SELECT str FROM finder WHERE length(str)==prefix_length(str, $INPUT) LIMIT 1
  } $expected
}

finish_test

Changes to test/printf.test.

534
535
536
537
538
539
540

541
542
543




544
545
546
547
548
549
550
534
535
536
537
538
539
540
541



542
543
544
545
546
547
548
549
550
551
552







+
-
-
-
+
+
+
+







} {abc: 1 1 (0.0) :xyz}
do_test printf-2.1.2.8 {
  sqlite3_mprintf_double {abc: %d %d (%1.1e) :xyz} 1 1 1.0e-20
} {abc: 1 1 (1.0e-20) :xyz}
do_test printf-2.1.2.9 {
  sqlite3_mprintf_double {abc: %d %d (%1.1g) :xyz} 1 1 1.0e-20
} {abc: 1 1 (1e-20) :xyz}
if {$SQLITE_MAX_LENGTH<=[expr 1000*1000*1000]} {
do_test printf-2.1.2.10 {
  sqlite3_mprintf_double {abc: %*.*f}  2000000000 1000000000 1.0e-20
} {abc: }
  do_test printf-2.1.2.10 {
    sqlite3_mprintf_double {abc: %*.*f}  2000000000 1000000000 1.0e-20
  } {}
}
do_test printf-2.1.3.1 {
  sqlite3_mprintf_double {abc: (%*.*f) :xyz} 1 1 1.0
} {abc: (1.0) :xyz}
do_test printf-2.1.3.2 {
  sqlite3_mprintf_double {abc: (%*.*e) :xyz} 1 1 1.0
} {abc: (1.0e+00) :xyz}
do_test printf-2.1.3.3 {
3772
3773
3774
3775
3776
3777
3778
3779







3780
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789








+
+
+
+
+
+
+

    do_test printf-malloc-$::iRepeat.$nTestNum {
      expr {($nFail>0 && $z eq "") || ($nFail==$nBenign && $z eq $zSuccess)}
    } {1}
    if {$nFail == 0} break
    incr nTestNum
  }
}

# 2020-05-23
# ticket 23439ea582241138
#
do_execsql_test printf-16.1 {
  SELECT printf('%.*g',2147483647,0.01);
} {0.01}

finish_test

Changes to test/printf2.test.

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
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







-
+


+
+
+









-
+







-
+





-
+





-
+





-
+





-
+








-
+







#    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 the printf() SQL function.
#
#
# EVIDENCE-OF: R-63057-40065 The printf(FORMAT,...) SQL function works
# EVIDENCE-OF: R-32560-14372 The format(FORMAT,...) SQL function works
# like the sqlite3_mprintf() C-language function and the printf()
# function from the standard C library.
#
# EVIDENCE-OF: R-64900-53159 The printf() SQL function is an alias for
# the format() SQL function.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# EVIDENCE-OF: R-40086-60101 If the FORMAT argument is missing or NULL
# then the result is NULL.
#
do_execsql_test printf2-1.1 {
  SELECT quote(printf()), quote(printf(NULL,1,2,3));
  SELECT quote(format()), quote(format(NULL,1,2,3));
} {NULL NULL}


do_execsql_test printf2-1.2 {
  SELECT printf('hello');
} {hello}
do_execsql_test printf2-1.3 {
  SELECT printf('%d,%d,%d',55,-11,3421);
  SELECT format('%d,%d,%d',55,-11,3421);
} {55,-11,3421}
do_execsql_test printf2-1.4 {
  SELECT printf('%d,%d,%d',55,'-11',3421);
} {55,-11,3421}
do_execsql_test printf2-1.5 {
  SELECT printf('%d,%d,%d,%d',55,'-11',3421);
  SELECT format('%d,%d,%d,%d',55,'-11',3421);
} {55,-11,3421,0}
do_execsql_test printf2-1.6 {
  SELECT printf('%.2f',3.141592653);
} {3.14}
do_execsql_test printf2-1.7 {
  SELECT printf('%.*f',2,3.141592653);
  SELECT format('%.*f',2,3.141592653);
} {3.14}
do_execsql_test printf2-1.8 {
  SELECT printf('%*.*f',5,2,3.141592653);
} {{ 3.14}}
do_execsql_test printf2-1.9 {
  SELECT printf('%d',314159.2653);
  SELECT format('%d',314159.2653);
} {314159}
do_execsql_test printf2-1.10 {
  SELECT printf('%lld',314159.2653);
} {314159}
do_execsql_test printf2-1.11 {
  SELECT printf('%lld%n',314159.2653,'hi');
  SELECT format('%lld%n',314159.2653,'hi');
} {314159}
do_execsql_test printf2-1.12 {
  SELECT printf('%n',0);
} {{}}

# EVIDENCE-OF: R-17002-27534 The %z format is interchangeable with %s.
#
do_execsql_test printf2-1.12 {
  SELECT printf('%.*z',5,'abcdefghijklmnop');
  SELECT format('%.*z',5,'abcdefghijklmnop');
} {abcde}
do_execsql_test printf2-1.13 {
  SELECT printf('%c','abcdefghijklmnop');
} {a}

# EVIDENCE-OF: R-02347-27622 The %n format is silently ignored and does
# not consume an argument.

Changes to test/pushdown.test.

82
83
84
85
86
87
88



89

































90
91
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







+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


    SELECT * FROM u1 WHERE 123=(
      SELECT x FROM u2 WHERE x=a AND f('two')
    ) AND f('three')=123
  }
  set L
} {three}

# 2022-11-25 dbsqlfuzz crash-3a548de406a50e896c1bf7142692d35d339d697f
# Disable the push-down optimization for compound subqueries if any
# arm of the compound has an incompatible affinity.

#
reset_db
do_execsql_test 3.1 {
  CREATE TABLE t0(c0 INT);
  INSERT INTO t0 VALUES(0);
  CREATE TABLE t1_a(a INTEGER PRIMARY KEY, b TEXT);
  INSERT INTO t1_a VALUES(1,'one');
  CREATE TABLE t1_b(c INTEGER PRIMARY KEY, d TEXT);
  INSERT INTO t1_b VALUES(2,'two');
  CREATE VIEW v0 AS SELECT CAST(t0.c0 AS INTEGER) AS c0 FROM t0;
  CREATE VIEW v1(a,b) AS SELECT a, b FROM t1_a UNION ALL SELECT c, 0 FROM t1_b;
  SELECT v1.a, quote(v1.b), t0.c0 AS cd FROM t0 LEFT JOIN v0 ON v0.c0!=0,v1;
} {
  1 'one' 0
  2 0     0
}
do_execsql_test 3.2 {
  SELECT a, quote(b), cd FROM (
    SELECT v1.a, v1.b, t0.c0 AS cd FROM t0 LEFT JOIN v0 ON v0.c0!=0, v1
  ) WHERE a=2 AND b='0' AND cd=0;
} {}
do_execsql_test 3.3 {
  SELECT a, quote(b), cd FROM (
    SELECT v1.a, v1.b, t0.c0 AS cd FROM t0 LEFT JOIN v0 ON v0.c0!=0, v1
  ) WHERE a=1 AND b='one' AND cd=0;
} {1 'one' 0}
do_execsql_test 3.4 {
  SELECT a, quote(b), cd FROM (
    SELECT v1.a, v1.b, t0.c0 AS cd FROM t0 LEFT JOIN v0 ON v0.c0!=0, v1
  ) WHERE a=2 AND b=0 AND cd=0;
} {
  2 0     0
}
  
finish_test

Added test/quickcheck.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2023 January 28
#
# 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
set testprefix quickcheck

do_execsql_test 1.0 {
  CREATE TABLE t1(
    a INTEGER NOT NULL, b INTEGER NOT NULL, c AS (a+1),
    PRIMARY KEY(b, a)
  ) WITHOUT ROWID;

  INSERT INTO t1 VALUES(1, 2);
  INSERT INTO t1 VALUES(3, 4);
}

do_execsql_test 1.1 {
  PRAGMA quick_check
} {
  ok
}

finish_test

Changes to test/quote.test.

12
13
14
15
16
17
18

19
20
21
22
23
24
25
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26







+







# focus of this file is the ability to specify table and column names
# as quoted strings.
#
# $Id: quote.test,v 1.7 2007/04/25 11:32:30 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix quote

# Create a table with a strange name and with strange column names.
#
do_test quote-1.0 {
  catchsql {CREATE TABLE '@abc' ( '#xyz' int, '!pqr' text );}
} {0 {}}

80
81
82
83
84
85
86
87
88


































































































89
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







-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

#
do_test quote-1.6 {
  set r [catch {
    execsql {DROP TABLE '@abc'}
  } msg ]
  lappend r $msg
} {0 {}}
 


#-------------------------------------------------------------------------
# Check that it is not possible to use double-quotes for a string
# constant in a CHECK constraint or CREATE INDEX statement. However, 
# SQLite can load such a schema from disk.
#
reset_db 
sqlite3_db_config db SQLITE_DBCONFIG_DQS_DDL 0
sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1
do_execsql_test 2.0 {
  CREATE TABLE t1(x, y, z);
}
foreach {tn sql errname} {
  1 { CREATE TABLE xyz(a, b, c CHECK (c!="null") ) } null
  2 { CREATE INDEX i2 ON t1(x, y, z||"abc") }        abc
  3 { CREATE INDEX i3 ON t1("w") }                   w
  4 { CREATE INDEX i4 ON t1(x) WHERE z="w" }         w
} {
  do_catchsql_test 2.1.$tn $sql [list 1 "no such column: $errname"]
}

do_execsql_test 2.2 {
  PRAGMA writable_schema = 1;
  CREATE TABLE xyz(a, b, c CHECK (c!="null") );
  CREATE INDEX i2 ON t1(x, y, z||"abc");
  CREATE INDEX i3 ON t1("w"||"");
  CREATE INDEX i4 ON t1(x) WHERE z="w";
}

db close
sqlite3 db test.db

do_execsql_test 2.3.1 {
  INSERT INTO xyz VALUES(1, 2, 3);
}
do_catchsql_test 2.3.2 {
  INSERT INTO xyz VALUES(1, 2, 'null');
} {1 {CHECK constraint failed: c!="null"}}

do_execsql_test 2.4 {
  INSERT INTO t1 VALUES(1, 2, 3);
  INSERT INTO t1 VALUES(4, 5, 'w');
  SELECT * FROM t1 WHERE z='w';
} {4 5 w}
do_execsql_test 2.5 {
  SELECT sql FROM sqlite_master;
} {
  {CREATE TABLE t1(x, y, z)}
  {CREATE TABLE xyz(a, b, c CHECK (c!="null") )}
  {CREATE INDEX i2 ON t1(x, y, z||"abc")}
  {CREATE INDEX i3 ON t1("w"||"")}
  {CREATE INDEX i4 ON t1(x) WHERE z="w"}
}

# 2021-03-13
# ticket 1c24a659e6d7f3a1
ifcapable altertable {
  reset_db
    do_catchsql_test 3.0 {
      CREATE TABLE t1(a,b);
      CREATE INDEX x1 on t1("b");
      ALTER TABLE t1 DROP COLUMN b;
    } {1 {error in index x1 after drop column: no such column: b}}
  do_catchsql_test 3.1 {
    DROP TABLE t1;
    CREATE TABLE t1(a,"b");
    CREATE INDEX x1 on t1("b");
    ALTER TABLE t1 DROP COLUMN b;
  } {1 {error in index x1 after drop column: no such column: b}}
  do_catchsql_test 3.2 {
    DROP TABLE t1;
    CREATE TABLE t1(a,'b');
    CREATE INDEX x1 on t1("b");
    ALTER TABLE t1 DROP COLUMN b;
  } {1 {error in index x1 after drop column: no such column: b}}
  do_catchsql_test 3.3 {
    DROP TABLE t1;
    CREATE TABLE t1(a,"b");
    CREATE INDEX x1 on t1('b');
    ALTER TABLE t1 DROP COLUMN b;
  } {1 {error in index x1 after drop column: no such column: b}}
  do_catchsql_test 3.4 {
    DROP TABLE t1;
    CREATE TABLE t1(a, b, c);
    CREATE INDEX x1 ON t1("a"||"b");
    INSERT INTO t1 VALUES(1,2,3),(1,4,5);
    ALTER TABLE t1 DROP COLUMN b;
  } {1 {error in index x1 after drop column: no such column: b}}
  sqlite3_db_config db SQLITE_DBCONFIG_DQS_DDL 1
  do_catchsql_test 3.5 {
    DROP TABLE t1;
    CREATE TABLE t1(a, b, c);
    CREATE INDEX x1 ON t1("a"||"x");
    INSERT INTO t1 VALUES(1,2,3),(1,4,5);
    ALTER TABLE t1 DROP COLUMN b;
  } {0 {}}
}

finish_test

Changes to test/rdonly.test.

37
38
39
40
41
42
43
44

45
46
47
48
49
50
51
52

53
54
55
56
57
58
59
37
38
39
40
41
42
43

44
45
46
47
48
49
50
51

52
53
54
55
56
57
58
59







-
+







-
+







# returns 1 if the database N of connection D is read-only, 0 if it is
# read/write, or -1 if N is not the name of a database on connection D.
#
do_test rdonly-1.1.1 {
  sqlite3_db_readonly db main
} {0}

# Changes the write version from 1 to 3.  Verify that the database
# Changes the write version from 1 to 4.  Verify that the database
# can be read but not written.
#
do_test rdonly-1.2 {
  db close
  hexio_get_int [hexio_read test.db 18 1]
} 1
do_test rdonly-1.3 {
  hexio_write test.db 18 03
  hexio_write test.db 18 04
  sqlite3 db test.db
  execsql {
    SELECT * FROM t1;
  }
} {1}
do_test rdonly-1.3.1 {
  sqlite3_db_readonly db main
79
80
81
82
83
84
85
86

87
88
89
90
91
92
93
94
95
79
80
81
82
83
84
85

86
87
88
89
90
91
92
93
94
95







-
+










# Now, after connection [db] has loaded the database schema, modify the
# write-version of the file (and the change-counter, so that the 
# write-version is reloaded). This way, SQLite does not discover that
# the database is read-only until after it is locked.
#
set ro_version 02
ifcapable wal { set ro_version 03 }
ifcapable wal { set ro_version 04 }
do_test rdonly-1.6 {
  hexio_write test.db 18 $ro_version     ; # write-version
  hexio_write test.db 24 11223344        ; # change-counter
  catchsql {
    INSERT INTO t1 VALUES(2);
  }
} {1 {attempt to write a readonly database}}

finish_test

Added test/recover.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019 April 23
#
# 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.
#
#***********************************************************************
#
# Test the shell tool ".ar" command.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix recover

ifcapable !vtab {
  finish_test; return
}
set CLI [test_find_cli]

proc compare_result {db1 db2 sql} {
  set r1 [$db1 eval $sql]
  set r2 [$db2 eval $sql]
  if {$r1 != $r2} {
  puts "r1: $r1"
  puts "r2: $r2"
    error "mismatch for $sql"
  }
  return ""
}

proc compare_dbs {db1 db2} {
  compare_result $db1 $db2 "SELECT sql FROM sqlite_master ORDER BY 1"
  foreach tbl [$db1 eval {SELECT name FROM sqlite_master WHERE type='table'}] {
    compare_result $db1 $db2 "SELECT * FROM $tbl"
  }
}

proc recover_with_opts {opts} {
  set cmd ".recover $opts"
  set fd [open [list |$::CLI test.db $cmd]]
  fconfigure $fd -encoding binary
  fconfigure $fd -translation binary
  set sql [read $fd]
  close $fd

  forcedelete test.db2
  sqlite3 db2 test.db2
  execsql $sql db2
  db2 close
}

proc do_recover_test {tn {tsql {}} {res {}}} {
  recover_with_opts ""

  sqlite3 db2 test.db2
  if {$tsql==""} {
    uplevel [list do_test $tn [list compare_dbs db db2] {}]
  } else {
    uplevel [list do_execsql_test -db db2 $tn $tsql $res]
  }
  db2 close
}

set doc {
  hello
  world
}
do_execsql_test 1.1.1 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
  INSERT INTO t1 VALUES(1, 4, X'1234567800');
  INSERT INTO t1 VALUES(2, 'test', 8.1);
  INSERT INTO t1 VALUES(3, $doc, 8.4);
}
do_recover_test 1.1.2

do_execsql_test 1.2.1 "
  DELETE FROM t1;
  INSERT INTO t1 VALUES(13, 'hello\r\nworld', 13);
"
do_recover_test 1.2.2

do_execsql_test 1.3.1 "
  CREATE TABLE t2(i INTEGER PRIMARY KEY AUTOINCREMENT, b, c);
  INSERT INTO t2 VALUES(NULL, 1, 2);
  INSERT INTO t2 VALUES(NULL, 3, 4);
  INSERT INTO t2 VALUES(NULL, 5, 6);
  CREATE TABLE t3(i INTEGER PRIMARY KEY AUTOINCREMENT, b, c);
  INSERT INTO t3 VALUES(NULL, 1, 2);
  INSERT INTO t3 VALUES(NULL, 3, 4);
  INSERT INTO t3 VALUES(NULL, 5, 6);
  DELETE FROM t2;
"
do_recover_test 1.3.2

#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.1.0 {
  PRAGMA auto_vacuum = 0;
  CREATE TABLE t1(a, b, c, PRIMARY KEY(b, c)) WITHOUT ROWID;
  INSERT INTO t1 VALUES(1, 2, 3);
  INSERT INTO t1 VALUES(4, 5, 6);
  INSERT INTO t1 VALUES(7, 8, 9);
}

do_recover_test 2.1.1

do_execsql_test 2.2.0 {
  PRAGMA writable_schema = 1;
  DELETE FROM sqlite_master WHERE name='t1';
}
do_recover_test 2.2.1 {
  SELECT name FROM sqlite_master
} {lost_and_found}

do_execsql_test 2.3.0 {
  CREATE TABLE lost_and_found(a, b, c);
}
do_recover_test 2.3.1 {
  SELECT name FROM sqlite_master
} {lost_and_found lost_and_found_0}

do_execsql_test 2.4.0 {
  CREATE TABLE lost_and_found_0(a, b, c);
}
do_recover_test 2.4.1 {
  SELECT name FROM sqlite_master;
  SELECT * FROM lost_and_found_1;
} {lost_and_found lost_and_found_0 lost_and_found_1
  2 2 3 {} 2 3 1
  2 2 3 {} 5 6 4
  2 2 3 {} 8 9 7
}

#-------------------------------------------------------------------------
reset_db
do_recover_test 3.0

#-------------------------------------------------------------------------
reset_db 
execsql { PRAGMA secure_delete = 0 }
execsql { PRAGMA auto_vacuum = 0 }
do_execsql_test 4.0 {
  CREATE TABLE t1(a, b, c);
  CREATE TABLE t2(d, e, f);
  CREATE TABLE t3(g, h, i);

  INSERT INTO t2 VALUES(1, 2, 3);
  INSERT INTO t2 VALUES('a', 'b', 'c');

  INSERT INTO t3 VALUES('one', 'two', 'three');
  DROP TABLE t1;
  DROP TABLE t2;
}

recover_with_opts ""
sqlite3 db2 test.db2
do_execsql_test -db db2 4.1.1 {
  SELECT name FROM sqlite_schema
} {t3 lost_and_found}
do_execsql_test -db db2 4.1.2 {
  SELECT id, c0, c1, c2 FROM lost_and_found
} {1 1 2 3    2 a b c}
db2 close

recover_with_opts -ignore-freelist
sqlite3 db2 test.db2
do_execsql_test -db db2 4.2.1 {
  SELECT name FROM sqlite_schema
} {t3}
do_execsql_test -db db2 4.2.2 {
  SELECT * FROM t3
} {one two three}
db2 close

finish_test

Changes to test/regexp1.test.

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
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







+
+
+
+
+
+
+
+
+
+
+
+
+




-
+


+
+
+
+
+
+
+
+
+



-
+


+
+
+
+
+
+
+
+
+







    INSERT INTO t1 VALUES(2, 'by man came also the resurrection of the dead.');
    INSERT INTO t1 VALUES(3, 'For as in Adam all die,');
    INSERT INTO t1 VALUES(4, 'even so in Christ shall all be made alive.');

    SELECT x FROM t1 WHERE y REGEXP '^For ' ORDER BY x;
  }
} {1 3}

do_execsql_test regexp1-1.1.2 {
  SELECT regexpi('abc','ABC');
} {1}
do_execsql_test regexp1-1.1.3 {
  SELECT regexpi('ABC','ABC');
} {1}
do_execsql_test regexp1-1.1.4 {
  SELECT regexpi('ABC','abc');
} {1}
do_execsql_test regexp1-1.1.5 {
  SELECT regexpi('ABC.','ABC');
} {0}

do_execsql_test regexp1-1.2 {
  SELECT x FROM t1 WHERE y REGEXP 'by|in' ORDER BY x;
} {1 2 3 4}
do_execsql_test regexp1-1.3 {
do_execsql_test regexp1-1.3.1 {
  SELECT x FROM t1 WHERE y REGEXP 'by|Christ' ORDER BY x;
} {1 2 4}
do_execsql_test regexp1-1.3.2 {
  SELECT x FROM t1 WHERE regexp('by|christ',y) ORDER BY x;
} {1 2}
do_execsql_test regexp1-1.3.3 {
  SELECT x FROM t1 WHERE regexpi('by|christ',y) ORDER BY x;
} {1 2 4}
do_execsql_test regexp1-1.3.4 {
  SELECT x FROM t1 WHERE regexpi('BY|CHRIST',y) ORDER BY x;
} {1 2 4}
do_execsql_test regexp1-1.4 {
  SELECT x FROM t1 WHERE y REGEXP 'shal+ al+' ORDER BY x;
} {4}
do_execsql_test regexp1-1.5 {
do_execsql_test regexp1-1.5.1 {
  SELECT x FROM t1 WHERE y REGEXP 'shall x*y*z*all' ORDER BY x;
} {4}
do_execsql_test regexp1-1.5.2 {
  SELECT x FROM t1 WHERE regexp('shall x*y*z*all',y) ORDER BY x;
} {4}
do_execsql_test regexp1-1.5.3 {
  SELECT x FROM t1 WHERE regexp('SHALL x*y*z*all',y) ORDER BY x;
} {}
do_execsql_test regexp1-1.5.4 {
  SELECT x FROM t1 WHERE regexpi('SHALL x*y*z*all',y) ORDER BY x;
} {4}
do_execsql_test regexp1-1.6 {
  SELECT x FROM t1 WHERE y REGEXP 'shallx?y? ?z?all' ORDER BY x;
} {4}
do_execsql_test regexp1-1.7 {
  SELECT x FROM t1 WHERE y REGEXP 'r{2}' ORDER BY x;
} {2}
do_execsql_test regexp1-1.8 {
203
204
205
206
207
208
209
210





























































































211
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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  SELECT 'abc$¢€xyz' REGEXP '^abc[\u0024][\u00a2][\u20ac]xyz$',
         'abc$¢€xyz' REGEXP '^abc[\u0024\u00A2\u20AC]{3}xyz$',
         'abc$¢€xyz' REGEXP '^abc[\x24][\xa2\u20ac]+xyz$'
} {1 1 1}
do_execsql_test regexp1-2.22 {
  SELECT 'abc$¢€xyz' REGEXP '^abc[^\u0025-X][^ -\u007f][^\u20ab]xyz$'
} {1}

# 2022-07-03
# https://sqlite.org/forum/forumpost/96692f8ba5
# The REGEXP extension mishandles the prefix search optimization when
# the prefix contains 3-byte UTF8 characters.
#
reset_db
load_static_extension db regexp
do_execsql_test regexp1-3.1 {
  CREATE TABLE t1(id INTEGER PRIMARY KEY, a TEXT);
  INSERT INTO t1(id, a) VALUES(1, '日本語');
  SELECT a, hex(a), length(a) FROM t1;
} {日本語 E697A5E69CACE8AA9E 3}
do_execsql_test regexp1-3.2 {
  SELECT * FROM t1 WHERE a='日本語';
} {1 日本語}
do_execsql_test regexp1-3.3 {
  SELECT * FROM t1 WHERE a LIKE '日本語';
} {1 日本語}
do_execsql_test regexp1-3.4 {
  SELECT * FROM t1 wHERE a REGEXP '日本語';
} {1 日本語}

# 2022-07-03
# https://sqlite.org/forum/forumpost/96692f8ba5  Issue #2
# The '$' token in REGEXP contained within other elements.
#
do_execsql_test regexp1-4.1 {SELECT 'xab' REGEXP 'a(b$|cd)';} {1}
do_execsql_test regexp1-4.1b {SELECT 'xab' REGEXP '(b$|cd)';} {1}
do_execsql_test regexp1-4.2 {SELECT 'xaby' REGEXP 'a(b$|cd)';} {0}
do_execsql_test regexp1-4.3 {SELECT 'xacd' REGEXP 'a(b$|cd)';} {1}
do_execsql_test regexp1-4.4 {SELECT 'xacdy' REGEXP 'a(b$|cd)';} {1}
do_execsql_test regexp1-4.5 {SELECT 'xab' REGEXP 'a(cd|b$)';} {1}
do_execsql_test regexp1-4.6 {SELECT 'xaby' REGEXP 'a(cd|b$)';} {0}
do_execsql_test regexp1-4.7 {SELECT 'xacd' REGEXP 'a(cd|b$)';} {1}
do_execsql_test regexp1-4.8 {SELECT 'xacdy' REGEXP 'a(cd|b$)';} {1}
do_execsql_test regexp1-4.9 {SELECT 'xab' REGEXP 'a(cd|b$|e)';} {1}
do_execsql_test regexp1-4.10 {SELECT 'xaby' REGEXP 'a(cd|b$|e)';} {0}
do_execsql_test regexp1-4.11 {SELECT 'xacd' REGEXP 'a(cd|b$|e)';} {1}
do_execsql_test regexp1-4.12 {SELECT 'xacdy' REGEXP 'a(cd|b$|e)';} {1}

# 2022-07-18
# https://sqlite.org/forum/forumpost/57cbaf1d0e
# Incorrect bytecode for {M,N} when M is zero.
#
do_execsql_test regexp1-5.1 {SELECT 'fooX' REGEXP '^[a-z][a-z0-9]{0,30}$';} {0}
do_execsql_test regexp1-5.2 {SELECT 'fooX' REGEXP '^[a-z][a-z0-9]{0,30}X$';} {1}
do_execsql_test regexp1-5.3 {SELECT 'fooX' REGEXP '^[a-z][a-z0-9]{0,2}X$';} {1}
do_execsql_test regexp1-5.4 {SELECT 'foooX' REGEXP '^[a-z][a-z0-9]{0,2}X$';} {0}
do_execsql_test regexp1-5.5 {SELECT 'foooX' REGEXP '^[a-z][a-z0-9]{0,3}X$';} {1}

# 2022-07-18
# https://sqlite.org/forum/forumpost/18f87fdcdf
# Allow "^" to occur inside of "(..)"
#
do_execsql_test regexp1-6.1 {SELECT 'foo' REGEXP '[a-z]';} {1}
do_execsql_test regexp1-6.2 {SELECT 'foo' REGEXP '^[a-z]+$';} {1}
do_execsql_test regexp1-6.3 {SELECT 'foo' REGEXP '^([a-z]+)$';} {1}
do_execsql_test regexp1-6.4 {SELECT 'foo' REGEXP '(^[a-z]+)$';} {1}
do_execsql_test regexp1-6.5 {SELECT 'foo' REGEXP '(^[a-z]+$)';} {1}
do_execsql_test regexp1-6.6 {SELECT 'abc' REGEXP '(^abc|def)';} {1}
do_execsql_test regexp1-6.7 {SELECT 'xabc' REGEXP '(^abc|def)';} {0}
do_execsql_test regexp1-6.8 {SELECT 'def' REGEXP '(^abc|def)';} {1}
do_execsql_test regexp1-6.9 {SELECT 'xdef' REGEXP '(^abc|def)';} {1}

# 2022-11-17
# https://sqlite.org/forum/forumpost/3ffe058b04
#
do_execsql_test regexp1-7.1 {
  SELECT char(0x61,0x7ff,0x62) REGEXP char(0x7ff);
} 1
do_execsql_test regexp1-7.2 {
  SELECT char(0x61,0x800,0x62) REGEXP char(0x800);
} 1
do_execsql_test regexp1-7.3 {
  SELECT char(0x61,0xabc,0x62) REGEXP char(0xabc);
} 1
do_execsql_test regexp1-7.4 {
  SELECT char(0x61,0xfff,0x62) REGEXP char(0xfff);
} 1
do_execsql_test regexp1-7.5 {
  SELECT char(0x61,0x1000,0x62) REGEXP char(0x1000);
} 1
do_execsql_test regexp1-7.10 {
  SELECT char(0x61,0xffff,0x62) REGEXP char(0xffff);
} 1
do_execsql_test regexp1-7.11 {
  SELECT char(0x61,0x10000,0x62) REGEXP char(0x10000);
} 1
do_execsql_test regexp1-7.12 {
  SELECT char(0x61,0x10ffff,0x62) REGEXP char(0x10ffff);
} 1


finish_test

Changes to test/regexp2.test.

116
117
118
119
120
121
122




















123
124
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


  INSERT INTO t5 VALUES ('^a.*'), ('^b.*'), ('^c.*');
  INSERT INTO t6 VALUES ('eab'), ('abc'), ('bcd'), ('cde'), ('dea');

  DELETE FROM t5;
  SELECT * FROM t6;
} {eab dea}

# 2021-06-04 Forum https://sqlite.org/forum/forumpost/9104f0d9e7
#
do_execsql_test 4.1 {SELECT 'abc' REGEXP '\W'} {0}
do_execsql_test 4.2 {SELECT 'a c' REGEXP '\W'} {1}
do_execsql_test 4.3 {SELECT '   ' REGEXP '\W'} {1}
do_execsql_test 4.4 {SELECT 'abc' REGEXP '\w'} {1}
do_execsql_test 4.5 {SELECT 'a c' REGEXP '\w'} {1}
do_execsql_test 4.6 {SELECT '   ' REGEXP '\w'} {0}
do_execsql_test 4.7 {SELECT 'abc' REGEXP '\D'} {1}
do_execsql_test 4.8 {SELECT 'abc' REGEXP '[^a-z]'} {0}
do_execsql_test 4.9 {SELECT 'a c' REGEXP '[^a-z]'} {1}
do_execsql_test 4.10 {SELECT '   ' REGEXP '[^a-z]'} {1}
do_execsql_test 4.11 {SELECT 'abc' REGEXP '[a-z]'} {1}
do_execsql_test 4.12 {SELECT 'a c' REGEXP '[a-z]'} {1}
do_execsql_test 4.13 {SELECT '   ' REGEXP '[a-z]'} {0}
do_execsql_test 4.14 {SELECT 'abc' REGEXP '[^a-z]{2}'} {0}
do_execsql_test 4.15 {SELECT 'a c' REGEXP '[^a-z]{2}'} {0}
do_execsql_test 4.16 {SELECT '   ' REGEXP '[^a-z]{2}'} {1}
do_execsql_test 4.17 {SELECT 'abc' REGEXP '\W{1,1}'} {0}
do_execsql_test 4.18 {SELECT 'abc' REGEXP '\W{1}'} {0}

finish_test

Changes to test/reindex.test.

11
12
13
14
15
16
17

18
19
20
21
22
23
24
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25







+







# This file implements regression tests for SQLite library.
# This file implements tests for the REINDEX command.
#
# $Id: reindex.test,v 1.4 2008/07/12 14:52:20 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix reindex

# There is nothing to test if REINDEX is disable for this build.
#
ifcapable {!reindex} {
  finish_test
  return
}
163
164
165
166
167
168
169
170

































171
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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

    REINDEX;
  } db2
} {1 {no such collation sequence: c2}}

do_test reindex-3.99 {
  db2 close
} {}

#-------------------------------------------------------------------------
foreach {tn wo} {1 "" 2 "WITHOUT ROWID"} {
  reset_db
  eval [string map [list %without_rowid% $wo] {
    do_execsql_test 4.$tn.0 {
      CREATE TABLE t0 (
        c0 INTEGER PRIMARY KEY DESC, 
        c1 UNIQUE DEFAULT NULL
      ) %without_rowid% ;
      INSERT INTO t0(c0) VALUES (1), (2), (3), (4), (5);
      SELECT c0 FROM t0 WHERE c1 IS NULL ORDER BY 1;
    } {1 2 3 4 5}
    
    do_execsql_test 4.$tn.1 {
      REINDEX;
    }
    
    do_execsql_test 4.$tn.2 {
      SELECT c0 FROM t0 WHERE c1 IS NULL ORDER BY 1;
    } {1 2 3 4 5}

    do_execsql_test 4.$tn.3 {
      SELECT c0 FROM t0 WHERE c1 IS NULL AND c0 IN (1,2,3,4,5);
    } {1 2 3 4 5}

    do_execsql_test 4.$tn.4 {
      PRAGMA integrity_check;
    } {ok}
  }]
}



finish_test

Deleted test/releasetest.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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






















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#!/usr/bin/tclsh
#
# Documentation for this script. This may be output to stderr
# if the script is invoked incorrectly. See the [process_options]
# proc below.
#
set ::USAGE_MESSAGE {
This Tcl script is used to test the various configurations required
before releasing a new version. Supported command line options (all
optional) are:

    --buildonly                        (Just build testfixture - do not run)
    --config   CONFIGNAME              (Run only CONFIGNAME)
    --dryrun                           (Print what would have happened)
    -f|--force                         (Run even if uncommitted changes)
    --info                             (Show diagnostic info)
    --jobs     N                       (Use N processes - default 1)
    --keep                             (Delete no files after each test run)
    --msvc                             (Use MSVC as the compiler)
    --platform PLATFORM                (see below)
    --progress                         (Show progress messages)
    --quick                            (Run "veryquick.test" only)
    --veryquick                        (Run "make smoketest" only)
    --with-tcl=DIR                     (Use TCL build at DIR)

The script determines the default value for --platform using the
$tcl_platform(os) and $tcl_platform(machine) variables.  Supported
platforms are "Linux-x86", "Linux-x86_64", "Darwin-i386",
"Darwin-x86_64", "Windows NT-intel", and "Windows NT-amd64".

Every test begins with a fresh run of the configure script at the top
of the SQLite source tree.
}

# Return a timestamp of the form HH:MM:SS
#
proc now {} {
  return [clock format [clock seconds] -format %H:%M:%S]
}

# Omit comments (text between # and \n) in a long multi-line string.
#
proc strip_comments {in} {
  regsub -all {#[^\n]*\n} $in {} out
  return $out
}

array set ::Configs [strip_comments {
  "Default" {
    -O2
    --disable-amalgamation --disable-shared
    --enable-session
  }
  "Sanitize" {
    CC=clang -fsanitize=undefined
    -DSQLITE_ENABLE_STAT4
    --enable-session
  }
  "Stdcall" {
    -DUSE_STDCALL=1
    -O2
  }
  "Have-Not" {
    # The "Have-Not" configuration sets all possible -UHAVE_feature options
    # in order to verify that the code works even on platforms that lack
    # these support services.
    -DHAVE_FDATASYNC=0
    -DHAVE_GMTIME_R=0
    -DHAVE_ISNAN=0
    -DHAVE_LOCALTIME_R=0
    -DHAVE_LOCALTIME_S=0
    -DHAVE_MALLOC_USABLE_SIZE=0
    -DHAVE_STRCHRNUL=0
    -DHAVE_USLEEP=0
    -DHAVE_UTIME=0
  }
  "Unlock-Notify" {
    -O2
    -DSQLITE_ENABLE_UNLOCK_NOTIFY
    -DSQLITE_THREADSAFE
    -DSQLITE_TCL_DEFAULT_FULLMUTEX=1
  }
  "User-Auth" {
    -O2
    -DSQLITE_USER_AUTHENTICATION=1
  }
  "Secure-Delete" {
    -O2
    -DSQLITE_SECURE_DELETE=1
    -DSQLITE_SOUNDEX=1
  }
  "Update-Delete-Limit" {
    -O2
    -DSQLITE_DEFAULT_FILE_FORMAT=4
    -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1
    -DSQLITE_ENABLE_STMT_SCANSTATUS
    -DSQLITE_LIKE_DOESNT_MATCH_BLOBS
    -DSQLITE_ENABLE_CURSOR_HINTS
    --enable-json1
  }
  "Check-Symbols" {
    -DSQLITE_MEMDEBUG=1
    -DSQLITE_ENABLE_FTS3_PARENTHESIS=1
    -DSQLITE_ENABLE_FTS3=1
    -DSQLITE_ENABLE_RTREE=1
    -DSQLITE_ENABLE_MEMSYS5=1
    -DSQLITE_ENABLE_MEMSYS3=1
    -DSQLITE_ENABLE_COLUMN_METADATA=1
    -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1
    -DSQLITE_SECURE_DELETE=1
    -DSQLITE_SOUNDEX=1
    -DSQLITE_ENABLE_ATOMIC_WRITE=1
    -DSQLITE_ENABLE_MEMORY_MANAGEMENT=1
    -DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1
    -DSQLITE_ENABLE_STAT4
    -DSQLITE_ENABLE_STMT_SCANSTATUS
    --enable-json1 --enable-fts5 --enable-session
  }
  "Debug-One" {
    --disable-shared
    -O2 -funsigned-char
    -DSQLITE_DEBUG=1
    -DSQLITE_MEMDEBUG=1
    -DSQLITE_MUTEX_NOOP=1
    -DSQLITE_TCL_DEFAULT_FULLMUTEX=1
    -DSQLITE_ENABLE_FTS3=1
    -DSQLITE_ENABLE_RTREE=1
    -DSQLITE_ENABLE_MEMSYS5=1
    -DSQLITE_ENABLE_COLUMN_METADATA=1
    -DSQLITE_ENABLE_STAT4
    -DSQLITE_ENABLE_HIDDEN_COLUMNS
    -DSQLITE_MAX_ATTACHED=125
    -DSQLITE_MUTATION_TEST
    --enable-fts5 --enable-json1
  }
  "Fast-One" {
    -O6
    -DSQLITE_ENABLE_FTS4=1
    -DSQLITE_ENABLE_RTREE=1
    -DSQLITE_ENABLE_STAT4
    -DSQLITE_ENABLE_RBU
    -DSQLITE_MAX_ATTACHED=125
    -DLONGDOUBLE_TYPE=double
    --enable-session
  }
  "Device-One" {
    -O2
    -DSQLITE_DEBUG=1
    -DSQLITE_DEFAULT_AUTOVACUUM=1
    -DSQLITE_DEFAULT_CACHE_SIZE=64
    -DSQLITE_DEFAULT_PAGE_SIZE=1024
    -DSQLITE_DEFAULT_TEMP_CACHE_SIZE=32
    -DSQLITE_DISABLE_LFS=1
    -DSQLITE_ENABLE_ATOMIC_WRITE=1
    -DSQLITE_ENABLE_IOTRACE=1
    -DSQLITE_ENABLE_MEMORY_MANAGEMENT=1
    -DSQLITE_MAX_PAGE_SIZE=4096
    -DSQLITE_OMIT_LOAD_EXTENSION=1
    -DSQLITE_OMIT_PROGRESS_CALLBACK=1
    -DSQLITE_OMIT_VIRTUALTABLE=1
    -DSQLITE_ENABLE_HIDDEN_COLUMNS
    -DSQLITE_TEMP_STORE=3
    --enable-json1
  }
  "Device-Two" {
    -DSQLITE_4_BYTE_ALIGNED_MALLOC=1
    -DSQLITE_DEFAULT_AUTOVACUUM=1
    -DSQLITE_DEFAULT_CACHE_SIZE=1000
    -DSQLITE_DEFAULT_LOCKING_MODE=0
    -DSQLITE_DEFAULT_PAGE_SIZE=1024
    -DSQLITE_DEFAULT_TEMP_CACHE_SIZE=1000
    -DSQLITE_DISABLE_LFS=1
    -DSQLITE_ENABLE_FTS3=1
    -DSQLITE_ENABLE_MEMORY_MANAGEMENT=1
    -DSQLITE_ENABLE_RTREE=1
    -DSQLITE_MAX_COMPOUND_SELECT=50
    -DSQLITE_MAX_PAGE_SIZE=32768
    -DSQLITE_OMIT_TRACE=1
    -DSQLITE_TEMP_STORE=3
    -DSQLITE_THREADSAFE=2
    -DSQLITE_ENABLE_DESERIALIZE=1
    --enable-json1 --enable-fts5 --enable-session
  }
  "Locking-Style" {
    -O2
    -DSQLITE_ENABLE_LOCKING_STYLE=1
  }
  "Apple" {
    -Os
    -DHAVE_GMTIME_R=1
    -DHAVE_ISNAN=1
    -DHAVE_LOCALTIME_R=1
    -DHAVE_PREAD=1
    -DHAVE_PWRITE=1
    -DHAVE_USLEEP=1
    -DHAVE_USLEEP=1
    -DHAVE_UTIME=1
    -DSQLITE_DEFAULT_CACHE_SIZE=1000
    -DSQLITE_DEFAULT_CKPTFULLFSYNC=1
    -DSQLITE_DEFAULT_MEMSTATUS=1
    -DSQLITE_DEFAULT_PAGE_SIZE=1024
    -DSQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS=1
    -DSQLITE_ENABLE_API_ARMOR=1
    -DSQLITE_ENABLE_AUTO_PROFILE=1
    -DSQLITE_ENABLE_FLOCKTIMEOUT=1
    -DSQLITE_ENABLE_FTS3=1
    -DSQLITE_ENABLE_FTS3_PARENTHESIS=1
    -DSQLITE_ENABLE_FTS3_TOKENIZER=1
    if:os=="Darwin" -DSQLITE_ENABLE_LOCKING_STYLE=1
    -DSQLITE_ENABLE_PERSIST_WAL=1
    -DSQLITE_ENABLE_PURGEABLE_PCACHE=1
    -DSQLITE_ENABLE_RTREE=1
    -DSQLITE_ENABLE_SNAPSHOT=1
    # -DSQLITE_ENABLE_SQLLOG=1
    -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1
    -DSQLITE_MAX_LENGTH=2147483645
    -DSQLITE_MAX_VARIABLE_NUMBER=500000
    # -DSQLITE_MEMDEBUG=1
    -DSQLITE_NO_SYNC=1
    -DSQLITE_OMIT_AUTORESET=1
    -DSQLITE_OMIT_LOAD_EXTENSION=1
    -DSQLITE_PREFER_PROXY_LOCKING=1
    -DSQLITE_SERIES_CONSTRAINT_VERIFY=1
    -DSQLITE_THREADSAFE=2
    -DSQLITE_USE_URI=1
    -DSQLITE_WRITE_WALFRAME_PREBUFFERED=1
    -DUSE_GUARDED_FD=1
    -DUSE_PREAD=1
    --enable-json1 --enable-fts5
  }
  "Extra-Robustness" {
    -DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1
    -DSQLITE_MAX_ATTACHED=62
  }
  "Devkit" {
    -DSQLITE_DEFAULT_FILE_FORMAT=4
    -DSQLITE_MAX_ATTACHED=30
    -DSQLITE_ENABLE_COLUMN_METADATA
    -DSQLITE_ENABLE_FTS4
    -DSQLITE_ENABLE_FTS5
    -DSQLITE_ENABLE_FTS4_PARENTHESIS
    -DSQLITE_DISABLE_FTS4_DEFERRED
    -DSQLITE_ENABLE_RTREE
    --enable-json1 --enable-fts5
  }
  "No-lookaside" {
    -DSQLITE_TEST_REALLOC_STRESS=1
    -DSQLITE_OMIT_LOOKASIDE=1
    -DHAVE_USLEEP=1
  }
  "Valgrind" {
    -DSQLITE_ENABLE_STAT4
    -DSQLITE_ENABLE_FTS4
    -DSQLITE_ENABLE_RTREE
    -DSQLITE_ENABLE_HIDDEN_COLUMNS
    --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.
  #
  Fail0 {-O0}
  Fail2 {-O0}
  Fail3 {-O0}
  Fail4 {-O0}
  FuzzFail1 {-O0}
  FuzzFail2 {-O0}
}]

array set ::Platforms [strip_comments {
  Linux-x86_64 {
    "Check-Symbols"           checksymbols
    "Fast-One"                "fuzztest test"
    "Debug-One"               "mptest test"
    "Have-Not"                test
    "Secure-Delete"           test
    "Unlock-Notify"           "QUICKTEST_INCLUDE=notify2.test test"
    "User-Auth"               tcltest
    "Update-Delete-Limit"     test
    "Extra-Robustness"        test
    "Device-Two"              test
    "No-lookaside"            test
    "Devkit"                  test
    "Apple"                   test
    "Sanitize"                {QUICKTEST_OMIT=func4.test,nan.test test}
    "Device-One"              fulltest
    "Default"                 "threadtest fulltest"
    "Valgrind"                valgrindtest
  }
  Linux-i686 {
    "Devkit"                  test
    "Have-Not"                test
    "Unlock-Notify"           "QUICKTEST_INCLUDE=notify2.test test"
    "Device-One"              test
    "Device-Two"              test
    "Default"                 "threadtest fulltest"
  }
  Darwin-i386 {
    "Locking-Style"           "mptest test"
    "Have-Not"                test
    "Apple"                   "threadtest fulltest"
  }
  Darwin-x86_64 {
    "Locking-Style"           "mptest test"
    "Have-Not"                test
    "Apple"                   "threadtest fulltest"
  }
  "Windows NT-intel" {
    "Stdcall"                 test
    "Have-Not"                test
    "Default"                 "mptest fulltestonly"
  }
  "Windows NT-amd64" {
    "Stdcall"                 test
    "Have-Not"                test
    "Default"                 "mptest fulltestonly"
  }

  # The Failure-Detection platform runs various tests that deliberately
  # fail.  This is used as a test of this script to verify that this script
  # correctly identifies failures.
  #
  Failure-Detection {
    Fail0     "TEST_FAILURE=0 test"
    Sanitize  "TEST_FAILURE=1 test"
    Fail2     "TEST_FAILURE=2 valgrindtest"
    Fail3     "TEST_FAILURE=3 valgrindtest"
    Fail4     "TEST_FAILURE=4 test"
    FuzzFail1 "TEST_FAILURE=5 test"
    FuzzFail2 "TEST_FAILURE=5 valgrindtest"
  }
}]


# End of configuration section.
#########################################################################
#########################################################################

# Configuration verification: Check that each entry in the list of configs
# specified for each platforms exists.
#
foreach {key value} [array get ::Platforms] {
  foreach {v t} $value {
    if {0==[info exists ::Configs($v)]} {
      puts stderr "No such configuration: \"$v\""
      exit -1
    }
  }
}

# Output log.   Disabled for slave interpreters.
#
if {[lindex $argv end]!="--slave"} {
  set LOG [open releasetest-out.txt w]
  proc PUTS {txt} {
    puts $txt
    puts $::LOG $txt
    flush $::LOG
  }
  proc PUTSNNL {txt} {
    puts -nonewline $txt
    puts -nonewline $::LOG $txt
    flush $::LOG
  }
  proc PUTSERR {txt} {
    puts stderr $txt
    puts $::LOG $txt
    flush $::LOG
  }
  puts $LOG "$argv0 $argv"
  set tm0 [clock format [clock seconds] -format {%Y-%m-%d %H:%M:%S} -gmt 1]
  puts $LOG "start-time: $tm0 UTC"
} else {
  proc PUTS {txt} {
    puts $txt
  }
  proc PUTSNNL {txt} {
    puts -nonewline $txt
  }
  proc PUTSERR {txt} {
    puts stderr $txt
  }
}

# Open the file $logfile and look for a report on the number of errors
# and the number of test cases run.  Add these values to the global
# $::NERRCASE and $::NTESTCASE variables.
#
# If any errors occur, then write into $errmsgVar the text of an appropriate
# one-line error message to show on the output.
#
proc count_tests_and_errors {logfile rcVar errmsgVar} {
  if {$::DRYRUN} return
  upvar 1 $rcVar rc $errmsgVar errmsg
  set fd [open $logfile rb]
  set seen 0
  while {![eof $fd]} {
    set line [gets $fd]
    if {[regexp {(\d+) errors out of (\d+) tests} $line all nerr ntest]} {
      incr ::NERRCASE $nerr
      incr ::NTESTCASE $ntest
      set seen 1
      if {$nerr>0} {
        set rc 1
        set errmsg $line
      }
    }
    if {[regexp {runtime error: +(.*)} $line all msg]} {
      # skip over "value is outside range" errors
      if {[regexp {value .* is outside the range of representable} $line]} {
         # noop
      } else {
        incr ::NERRCASE
        if {$rc==0} {
          set rc 1
          set errmsg $msg
        }
      }
    }
    if {[regexp {fatal error +(.*)} $line all msg]} {
      incr ::NERRCASE
      if {$rc==0} {
        set rc 1
        set errmsg $msg
      }
    }
    if {[regexp {ERROR SUMMARY: (\d+) errors.*} $line all cnt] && $cnt>0} {
      incr ::NERRCASE
      if {$rc==0} {
        set rc 1
        set errmsg $all
      }
    }
    if {[regexp {^VERSION: 3\.\d+.\d+} $line]} {
      set v [string range $line 9 end]
      if {$::SQLITE_VERSION eq ""} {
        set ::SQLITE_VERSION $v
      } elseif {$::SQLITE_VERSION ne $v} {
        set rc 1
        set errmsg "version conflict: {$::SQLITE_VERSION} vs. {$v}"
      }
    }
  }
  close $fd
  if {$::BUILDONLY} {
    incr ::NTESTCASE
    if {$rc!=0} {
      set errmsg "Build failed"
    }
  } elseif {!$seen} {
    set rc 1
    set errmsg "Test did not complete"
    if {[file readable core]} {
      append errmsg " - core file exists"
    }
  }
}

#--------------------------------------------------------------------------
# This command is invoked as the [main] routine for scripts run with the
# "--slave" option.
#
# For each test (i.e. "configure && make test" execution), the master
# process spawns a process with the --slave option. It writes two lines
# to the slaves stdin. The first contains a single boolean value - the
# value of ::TRACE to use in the slave script. The second line contains a
# list in the same format as each element of the list passed to the
# [run_all_test_suites] command in the master process.
#
# The slave then runs the "configure && make test" commands specified. It
# exits successfully if the tests passes, or with a non-zero error code
# otherwise.
#
proc run_slave_test {} {
  # Read global vars configuration from stdin.
  set V [gets stdin]
  foreach {::TRACE ::MSVC ::DRYRUN ::KEEPFILES} $V {}

  # Read the test-suite configuration from stdin.
  set T [gets stdin]
  foreach {title dir configOpts testtarget makeOpts cflags opts} $T {}

  # Create and switch to the test directory.
  set normaldir [file normalize $dir]
  set ::env(SQLITE_TMPDIR) $normaldir
  trace_cmd file mkdir $dir
  trace_cmd cd $dir
  catch {file delete core}
  catch {file delete test.log}

  # Run the "./configure && make" commands.
  set rc 0
  set rc [catch [configureCommand $configOpts]]
  if {!$rc} {
    if {[info exists ::env(TCLSH_CMD)]} {
      set savedEnv(TCLSH_CMD) $::env(TCLSH_CMD)
    } else {
      unset -nocomplain savedEnv(TCLSH_CMD)
    }
    set ::env(TCLSH_CMD) [file nativename [info nameofexecutable]]
    set rc [catch [makeCommand $testtarget $makeOpts $cflags $opts]]
    if {[info exists savedEnv(TCLSH_CMD)]} {
      set ::env(TCLSH_CMD) $savedEnv(TCLSH_CMD)
    } else {
      unset -nocomplain ::env(TCLSH_CMD)
    }
  }

  # Clean up lots of extra files if --keep was not specified.
  if {$::KEEPFILES==0} { cleanup $normaldir }

  # Exis successfully if the test passed, or with a non-zero error code
  # otherwise.
  exit $rc
}

# This command is invoked in the master process each time a slave
# file-descriptor is readable.
#
proc slave_fileevent {fd T tm1} {
  global G
  foreach {title dir configOpts testtarget makeOpts cflags opts} $T {}

  if {[eof $fd]} {
    fconfigure $fd -blocking 1
    set rc [catch { close $fd }]

    set errmsg {}
    set logfile [file join $dir test.log]
    if {[file exists $logfile]} {
      count_tests_and_errors [file join $dir test.log] rc errmsg
    } elseif {$rc==0 && !$::DRYRUN} {
      set rc 1
      set errmsg "no test.log file..."
    }

    if {!$::TRACE} {
      set tm2 [clock seconds]
      set hours [expr {($tm2-$tm1)/3600}]
      set minutes [expr {(($tm2-$tm1)/60)%60}]
      set seconds [expr {($tm2-$tm1)%60}]
      set tm [format (%02d:%02d:%02d) $hours $minutes $seconds]

      if {$rc} {
        set status FAIL
        incr ::NERR
      } else {
        set status Ok
      }

      set n [string length $title]
      if {$::PROGRESS_MSGS} {
        PUTS "finished: ${title}[string repeat . [expr {53-$n}]] $status $tm"
      } else {
        PUTS "${title}[string repeat . [expr {63-$n}]] $status $tm"
      }
      if {$errmsg!=""} {PUTS "     $errmsg"}
      flush stdout
    }

    incr G(nJob) -1
  } else {
    set line [gets $fd]
    if {[string trim $line] != ""} {
      puts "Trace   : $title - \"$line\""
    }
  }
}

#--------------------------------------------------------------------------
# The only argument passed to this function is a list of test-suites to
# run. Each "test-suite" is itself a list consisting of the following
# elements:
#
#   * Test title (for display).
#   * The name of the directory to run the test in.
#   * The argument for [configureCommand]
#   * The first argument for [makeCommand]
#   * The second argument for [makeCommand]
#   * The third argument for [makeCommand]
#
proc run_all_test_suites {alltests} {
  global G
  set tests $alltests

  set G(nJob) 0

  while {[llength $tests]>0 || $G(nJob)>0} {
    if {$G(nJob)>=$::JOBS || [llength $tests]==0} {
      vwait G(nJob)
    }

    if {[llength $tests]>0} {
      set T [lindex $tests 0]
      set tests [lrange $tests 1 end]
      foreach {title dir configOpts testtarget makeOpts cflags opts} $T {}
      if {$::PROGRESS_MSGS && !$::TRACE} {
        set n [string length $title]
        PUTS "starting: ${title} at [now]"
        flush stdout
      }

      # Run the job.
      #
      set tm1 [clock seconds]
      incr G(nJob)
      set script [file normalize [info script]]
      set fd [open "|[info nameofexecutable] $script --slave" r+]
      fconfigure $fd -blocking 0
      fileevent $fd readable [list slave_fileevent $fd $T $tm1]
      puts $fd [list $::TRACE $::MSVC $::DRYRUN $::KEEPFILES]
      puts $fd [list {*}$T]
      flush $fd
    }
  }
}

proc add_test_suite {listvar name testtarget config} {
  upvar $listvar alltests

  # Tcl variable $opts is used to build up the value used to set the
  # OPTS Makefile variable. Variable $cflags holds the value for
  # CFLAGS. The makefile will pass OPTS to both gcc and lemon, but
  # CFLAGS is only passed to gcc.
  #
  set makeOpts ""
  set cflags [expr {$::MSVC ? "-Zi" : "-g"}]
  set opts ""
  set title ${name}($testtarget)
  set configOpts $::WITHTCL
  set skip 0

  regsub -all {#[^\n]*\n} $config \n config
  foreach arg $config {
    if {$skip} {
      set skip 0
      continue
    }
    if {[regexp {^-[UD]} $arg]} {
      lappend opts $arg
    } elseif {[regexp {^[A-Z]+=} $arg]} {
      lappend testtarget $arg
    } elseif {[regexp {^if:([a-z]+)(.*)} $arg all key tail]} {
      # Arguments of the form 'if:os=="Linux"' will cause the subsequent
      # argument to be skipped if the $tcl_platform(os) is not "Linux", for
      # example...
      set skip [expr !(\$::tcl_platform($key)$tail)]
    } elseif {[regexp {^--(enable|disable)-} $arg]} {
      if {$::MSVC} {
        if {$arg eq "--disable-amalgamation"} {
          lappend makeOpts USE_AMALGAMATION=0
          continue
        }
        if {$arg eq "--disable-shared"} {
          lappend makeOpts USE_CRT_DLL=0 DYNAMIC_SHELL=0
          continue
        }
        if {$arg eq "--enable-fts5"} {
          lappend opts -DSQLITE_ENABLE_FTS5
          continue
        }
        if {$arg eq "--enable-json1"} {
          lappend opts -DSQLITE_ENABLE_JSON1
          continue
        }
        if {$arg eq "--enable-shared"} {
          lappend makeOpts USE_CRT_DLL=1 DYNAMIC_SHELL=1
          continue
        }
      }
      lappend configOpts $arg
    } else {
      if {$::MSVC} {
        if {$arg eq "-g"} {
          lappend cflags -Zi
          continue
        }
        if {[regexp -- {^-O(\d+)$} $arg all level]} then {
          lappend makeOpts OPTIMIZATIONS=$level
          continue
        }
      }
      lappend cflags $arg
    }
  }

  # Disable sync to make testing faster.
  #
  lappend opts -DSQLITE_NO_SYNC=1

  # Some configurations already set HAVE_USLEEP; in that case, skip it.
  #
  if {[lsearch -regexp $opts {^-DHAVE_USLEEP(?:=|$)}]==-1} {
    lappend opts -DHAVE_USLEEP=1
  }

  # Add the define for this platform.
  #
  if {$::tcl_platform(platform)=="windows"} {
    lappend opts -DSQLITE_OS_WIN=1
  } else {
    lappend opts -DSQLITE_OS_UNIX=1
  }

  # Set the sub-directory to use.
  #
  set dir [string tolower [string map {- _ " " _} $name]]

  # Join option lists into strings, using space as delimiter.
  #
  set makeOpts [join $makeOpts " "]
  set cflags   [join $cflags " "]
  set opts     [join $opts " "]

  lappend alltests [list \
      $title $dir $configOpts $testtarget $makeOpts $cflags $opts]
}

# The following procedure returns the "configure" command to be exectued for
# the current platform, which may be Windows (via MinGW, etc).
#
proc configureCommand {opts} {
  if {$::MSVC} return [list]; # This is not needed for MSVC.
  set result [list trace_cmd exec]
  if {$::tcl_platform(platform)=="windows"} {
    lappend result sh
  }
  lappend result $::SRCDIR/configure --enable-load-extension
  foreach x $opts {lappend result $x}
  lappend result >& test.log
}

# The following procedure returns the "make" command to be executed for the
# specified targets, compiler flags, and options.
#
proc makeCommand { targets makeOpts cflags opts } {
  set result [list trace_cmd exec]
  if {$::MSVC} {
    set nmakeDir [file nativename $::SRCDIR]
    set nmakeFile [file nativename [file join $nmakeDir Makefile.msc]]
    lappend result nmake /f $nmakeFile TOP=$nmakeDir
    set tclDir [file nativename [file normalize \
        [file dirname [file dirname [info nameofexecutable]]]]]
    lappend result "TCLDIR=$tclDir"
    if {[regexp {USE_STDCALL=1} $cflags]} {
      lappend result USE_STDCALL=1
    }
  } else {
    lappend result make
  }
  foreach makeOpt $makeOpts {
    lappend result $makeOpt
  }
  lappend result clean
  foreach target $targets {
    lappend result $target
  }
  lappend result CFLAGS=$cflags OPTS=$opts >>& test.log
}

# The following procedure prints its arguments if ::TRACE is true.
# And it executes the command of its arguments in the calling context
# if ::DRYRUN is false.
#
proc trace_cmd {args} {
  if {$::TRACE} {
    PUTS $args
  }
  set res ""
  if {!$::DRYRUN} {
    set res [uplevel 1 $args]
  }
  return $res
}


# This proc processes the command line options passed to this script.
# Currently the only option supported is "-makefile", default
# "releasetest.mk". Set the ::MAKEFILE variable to the value of this
# option.
#
proc process_options {argv} {
  set ::SRCDIR    [file normalize [file dirname [file dirname $::argv0]]]
  set ::QUICK          0
  set ::MSVC           0
  set ::BUILDONLY      0
  set ::DRYRUN         0
  set ::TRACE          0
  set ::JOBS           1
  set ::PROGRESS_MSGS  0
  set ::WITHTCL        {}
  set ::FORCE          0
  set ::KEEPFILES      0          ;# Keep extra files after test run
  set config {}
  set platform $::tcl_platform(os)-$::tcl_platform(machine)

  for {set i 0} {$i < [llength $argv]} {incr i} {
    set x [lindex $argv $i]
    if {[regexp {^--[a-z]} $x]} {set x [string range $x 1 end]}
    switch -glob -- $x {
      -slave {
        run_slave_test
        exit
      }

      # Undocumented legacy option: --srcdir DIRECTORY
      #
      # DIRECTORY is the root of the SQLite checkout.  This sets the
      # SRCDIR global variable.  But that variable is already set
      # automatically so there really is no reason to have this option.
      #
      -srcdir {
        incr i
        set ::SRCDIR [file normalize [lindex $argv $i]]
      }

      -platform {
        incr i
        set platform [lindex $argv $i]
      }

      -jobs {
        incr i
        set ::JOBS [lindex $argv $i]
      }

      -progress {
        set ::PROGRESS_MSGS 1
      }

      -quick {
        set ::QUICK 1
      }
      -veryquick {
        set ::QUICK 2
      }

      -config {
        incr i
        set config [lindex $argv $i]
      }

      -msvc {
        set ::MSVC 1
      }

      -buildonly {
        set ::BUILDONLY 1
      }

      -dryrun {
        set ::DRYRUN 1
      }

      -force -
      -f {
        set ::FORCE 1
      }

      -trace {
        set ::TRACE 1
      }

      -info {
        PUTS "Command-line Options:"
        PUTS "   --srcdir $::SRCDIR"
        PUTS "   --platform [list $platform]"
        PUTS "   --config [list $config]"
        if {$::QUICK} {
          if {$::QUICK==1} {PUTS "   --quick"}
          if {$::QUICK==2} {PUTS "   --veryquick"}
        }
        if {$::MSVC}      {PUTS "   --msvc"}
        if {$::BUILDONLY} {PUTS "   --buildonly"}
        if {$::DRYRUN}    {PUTS "   --dryrun"}
        if {$::TRACE}     {PUTS "   --trace"}
        PUTS "\nAvailable --platform options:"
        foreach y [lsort [array names ::Platforms]] {
          PUTS "   [list $y]"
        }
        PUTS "\nAvailable --config options:"
        foreach y [lsort [array names ::Configs]] {
          PUTS "   [list $y]"
        }
        exit
      }

      -g {
        lappend ::EXTRACONFIG [lindex $argv $i]
      }

      -keep {
        set ::KEEPFILES 1
      }

      -with-tcl=* {
        set ::WITHTCL -$x
      }

      -D* -
      -O* -
      -enable-* -
      -disable-* -
      *=* {
        lappend ::EXTRACONFIG [lindex $argv $i]
      }

      default {
        PUTSERR ""
        PUTSERR [string trim $::USAGE_MESSAGE]
        exit -1
      }
    }
  }

  if {0==[info exists ::Platforms($platform)]} {
    PUTS "Unknown platform: $platform"
    PUTSNNL "Set the -platform option to "
    set print [list]
    foreach p [array names ::Platforms] {
      lappend print "\"$p\""
    }
    lset print end "or [lindex $print end]"
    PUTS "[join $print {, }]."
    exit
  }

  if {$config!=""} {
    if {[llength $config]==1} {lappend config fulltest}
    set ::CONFIGLIST $config
  } else {
    if {$::JOBS>1} {
      set ::CONFIGLIST {}
      foreach {target zConfig} [lreverse $::Platforms($platform)] {
        append ::CONFIGLIST [format "    %-25s %s\n" \
                               [list $zConfig] [list $target]]
      }
    } else {
      set ::CONFIGLIST $::Platforms($platform)
    }
  }
  PUTS "Running the following test configurations for $platform:"
  PUTS "    [string trim $::CONFIGLIST]"
  PUTSNNL "Flags:"
  if {$::PROGRESS_MSGS} {PUTSNNL " --progress"}
  if {$::DRYRUN} {PUTSNNL " --dryrun"}
  if {$::BUILDONLY} {PUTSNNL " --buildonly"}
  if {$::MSVC} {PUTSNNL " --msvc"}
  switch -- $::QUICK {
     1 {PUTSNNL " --quick"}
     2 {PUTSNNL " --veryquick"}
  }
  if {$::JOBS>1} {PUTSNNL " --jobs $::JOBS"}
  PUTS ""
}

# Check to see if there are uncommitted changes in the SQLite source
# checkout.  Exit if there are.  Except:  Do nothing if the --force
# flag is used.  Also, ignore this test if the fossil binary is
# unavailable, or if the source tree is not a valid fossil checkout.
#
proc check_uncommitted {} {
  if {$::FORCE} return
  set pwd [pwd]
  cd $::SRCDIR
  if {[catch {exec fossil changes} res]==0 && [string trim $res]!=""} {
    puts "ERROR: The check-out contains uncommitted changes:"
    puts $res
    puts "Use the -f or --force options to override"
    exit 1
  }
  cd $pwd
}

# A test run has just finished in directory $dir. This command deletes all
# non-essential files from the directory. Specifically, everything except
#
#   * The "testfixture" and "sqlite3" binaries,
#   * The "test-out.log" and "test.log" log files.
#
proc cleanup {dir} {
  set K(testfixture) 1
  set K(testfixture.exe) 1
  set K(sqlite3) 1
  set K(sqlite3.exe) 1
  set K(test-out.txt) 1
  set K(test.log) 1

  foreach f [glob -nocomplain [file join $dir *]] {
    set tail [file tail $f]
    if {[info exists K($tail)]==0} { 
      file delete -force $f
    }
  }
}


# Main routine.
#
proc main {argv} {

  # Process any command line options.
  set ::EXTRACONFIG {}
  process_options $argv
  if {!$::DRYRUN} check_uncommitted
  PUTS [string repeat * 79]

  set ::NERR 0
  set ::NTEST 0
  set ::NTESTCASE 0
  set ::NERRCASE 0
  set ::SQLITE_VERSION {}
  set STARTTIME [clock seconds]
  foreach {zConfig target} $::CONFIGLIST {
    if {$::MSVC && ($zConfig eq "Sanitize" || "checksymbols" in $target
           || "valgrindtest" in $target)} {
      PUTS "Skipping $zConfig / $target for MSVC..."
      continue
    }
    if {$target ne "checksymbols"} {
      switch -- $::QUICK {
         1 {set target quicktest}
         2 {set target smoketest}
      }
      if {$::BUILDONLY} {
        set target testfixture
        if {$::tcl_platform(platform)=="windows"} {
          append target .exe
        }
      }
    }
    set config_options [concat $::Configs($zConfig) $::EXTRACONFIG]

    incr NTEST
    add_test_suite all $zConfig $target $config_options

    # If the configuration included the SQLITE_DEBUG option, then remove
    # it and run veryquick.test. If it did not include the SQLITE_DEBUG option
    # add it and run veryquick.test.
    if {$target!="checksymbols" && $target!="valgrindtest"
           && $target!="fuzzoomtest" && !$::BUILDONLY && $::QUICK<2} {
      set debug_idx [lsearch -glob $config_options -DSQLITE_DEBUG*]
      set xtarget $target
      regsub -all {fulltest[a-z]*} $xtarget test xtarget
      regsub -all {fuzzoomtest} $xtarget fuzztest xtarget
      if {$debug_idx < 0} {
        incr NTEST
        append config_options " -DSQLITE_DEBUG=1 -DSQLITE_EXTRA_IFNULLROW=1"
        add_test_suite all "${zConfig}_debug" $xtarget $config_options
      } else {
        incr NTEST
        regsub { *-DSQLITE_MEMDEBUG[^ ]* *} $config_options { } config_options
        regsub { *-DSQLITE_DEBUG[^ ]* *} $config_options { } config_options
        add_test_suite all "${zConfig}_ndebug" $xtarget $config_options
      }
    }
  }

  run_all_test_suites $all

  set elapsetime [expr {[clock seconds]-$STARTTIME}]
  set hr [expr {$elapsetime/3600}]
  set min [expr {($elapsetime/60)%60}]
  set sec [expr {$elapsetime%60}]
  set etime [format (%02d:%02d:%02d) $hr $min $sec]
  if {$::JOBS>1} {append etime " $::JOBS cores"}
  if {[catch {exec hostname} HNAME]==0} {append etime " on $HNAME"}
  PUTS [string repeat * 79]
  incr ::NERRCASE $::NERR
  PUTS "$::NERRCASE failures out of $::NTESTCASE tests in $etime"
  if {$::SQLITE_VERSION ne ""} {
    PUTS "SQLite $::SQLITE_VERSION"
  }
}

main $argv

Added test/releasetest_data.tcl.


















































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019 August 01
#
# 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 a program that produces scripts (either shell scripts
# or batch files) to implement a particular test that is part of the SQLite
# release testing procedure. For example, to run veryquick.test with a 
# specified set of -D compiler switches.
#
# A "configuration" is a set of options passed to [./configure] and [make]
# to build the SQLite library in a particular fashion. A "platform" is a
# list of tests; most platforms are named after the hardware/OS platform
# that the tests will be run on as part of the release procedure. Each 
# "test" is a combination of a configuration and a makefile target (e.g.
# "fulltest"). The program may be invoked as follows:
#
set USAGE {
$argv0 script ?-msvc? CONFIGURATION TARGET
    Given a configuration and make target, return a bash (or, if -msvc
    is specified, batch) script to execute the test. The first argument
    passed to the script must be a directory containing SQLite source code.

$argv0 configurations
    List available configurations.

$argv0 platforms
    List available platforms.

$argv0 tests ?-nodebug? PLATFORM
    List tests in a specified platform. If the -nodebug switch is 
    specified, synthetic debug/ndebug configurations are omitted. Each
    test is a combination of a configuration and a makefile target.
}

# Omit comments (text between # and \n) in a long multi-line string.
#
proc strip_comments {in} {
  regsub -all {#[^\n]*\n} $in {} out
  return $out
}

array set ::Configs [strip_comments {
  "Default" {
    -O2
    --disable-amalgamation --disable-shared
    --enable-session
    -DSQLITE_ENABLE_RBU
  }
  "Sanitize" {
    CC=clang -fsanitize=address,undefined
    -DSQLITE_ENABLE_STAT4
    -DCONFIG_SLOWDOWN_FACTOR=5.0
    --enable-debug
    --enable-all
  }
  "Stdcall" {
    -DUSE_STDCALL=1
    -O2
  }
  "Have-Not" {
    # The "Have-Not" configuration sets all possible -UHAVE_feature options
    # in order to verify that the code works even on platforms that lack
    # these support services.
    -DHAVE_FDATASYNC=0
    -DHAVE_GMTIME_R=0
    -DHAVE_ISNAN=0
    -DHAVE_LOCALTIME_R=0
    -DHAVE_LOCALTIME_S=0
    -DHAVE_MALLOC_USABLE_SIZE=0
    -DHAVE_STRCHRNUL=0
    -DHAVE_USLEEP=0
    -DHAVE_UTIME=0
  }
  "Unlock-Notify" {
    -O2
    -DSQLITE_ENABLE_UNLOCK_NOTIFY
    -DSQLITE_THREADSAFE
    -DSQLITE_TCL_DEFAULT_FULLMUTEX=1
  }
  "User-Auth" {
    -O2
    -DSQLITE_USER_AUTHENTICATION=1
  }
  "Secure-Delete" {
    -O2
    -DSQLITE_SECURE_DELETE=1
    -DSQLITE_SOUNDEX=1
  }
  "Update-Delete-Limit" {
    -O2
    -DSQLITE_DEFAULT_FILE_FORMAT=4
    -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1
    -DSQLITE_ENABLE_STMT_SCANSTATUS
    -DSQLITE_LIKE_DOESNT_MATCH_BLOBS
    -DSQLITE_ENABLE_CURSOR_HINTS
  }
  "Check-Symbols" {
    -DSQLITE_MEMDEBUG=1
    -DSQLITE_ENABLE_FTS3_PARENTHESIS=1
    -DSQLITE_ENABLE_FTS3=1
    -DSQLITE_ENABLE_RTREE=1
    -DSQLITE_ENABLE_MEMSYS5=1
    -DSQLITE_ENABLE_MEMSYS3=1
    -DSQLITE_ENABLE_COLUMN_METADATA=1
    -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1
    -DSQLITE_SECURE_DELETE=1
    -DSQLITE_SOUNDEX=1
    -DSQLITE_ENABLE_ATOMIC_WRITE=1
    -DSQLITE_ENABLE_MEMORY_MANAGEMENT=1
    -DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1
    -DSQLITE_ENABLE_STAT4
    -DSQLITE_ENABLE_STMT_SCANSTATUS
    --enable-fts5 --enable-session
  }
  "Debug-One" {
    --disable-shared
    -O2 -funsigned-char
    -DSQLITE_DEBUG=1
    -DSQLITE_MEMDEBUG=1
    -DSQLITE_MUTEX_NOOP=1
    -DSQLITE_TCL_DEFAULT_FULLMUTEX=1
    -DSQLITE_ENABLE_FTS3=1
    -DSQLITE_ENABLE_RTREE=1
    -DSQLITE_ENABLE_MEMSYS5=1
    -DSQLITE_ENABLE_COLUMN_METADATA=1
    -DSQLITE_ENABLE_STAT4
    -DSQLITE_ENABLE_HIDDEN_COLUMNS
    -DSQLITE_MAX_ATTACHED=125
    -DSQLITE_MUTATION_TEST
    --enable-fts5
  }
  "Debug-Two" {
    -DSQLITE_DEFAULT_MEMSTATUS=0
    -DSQLITE_MAX_EXPR_DEPTH=0
    --enable-debug
  }
  "Fast-One" {
    -O6
    -DSQLITE_ENABLE_FTS4=1
    -DSQLITE_ENABLE_RTREE=1
    -DSQLITE_ENABLE_STAT4
    -DSQLITE_ENABLE_RBU
    -DSQLITE_MAX_ATTACHED=125
    -DSQLITE_MAX_MMAP_SIZE=12884901888
    -DSQLITE_ENABLE_SORTER_MMAP=1
    -DLONGDOUBLE_TYPE=double
    --enable-session
  }
  "Device-One" {
    -O2
    -DSQLITE_DEBUG=1
    -DSQLITE_DEFAULT_AUTOVACUUM=1
    -DSQLITE_DEFAULT_CACHE_SIZE=64
    -DSQLITE_DEFAULT_PAGE_SIZE=1024
    -DSQLITE_DEFAULT_TEMP_CACHE_SIZE=32
    -DSQLITE_DISABLE_LFS=1
    -DSQLITE_ENABLE_ATOMIC_WRITE=1
    -DSQLITE_ENABLE_IOTRACE=1
    -DSQLITE_ENABLE_MEMORY_MANAGEMENT=1
    -DSQLITE_MAX_PAGE_SIZE=4096
    -DSQLITE_OMIT_LOAD_EXTENSION=1
    -DSQLITE_OMIT_PROGRESS_CALLBACK=1
    -DSQLITE_OMIT_VIRTUALTABLE=1
    -DSQLITE_ENABLE_HIDDEN_COLUMNS
    -DSQLITE_TEMP_STORE=3
  }
  "Device-Two" {
    -DSQLITE_4_BYTE_ALIGNED_MALLOC=1
    -DSQLITE_DEFAULT_AUTOVACUUM=1
    -DSQLITE_DEFAULT_CACHE_SIZE=1000
    -DSQLITE_DEFAULT_LOCKING_MODE=0
    -DSQLITE_DEFAULT_PAGE_SIZE=1024
    -DSQLITE_DEFAULT_TEMP_CACHE_SIZE=1000
    -DSQLITE_DISABLE_LFS=1
    -DSQLITE_ENABLE_FTS3=1
    -DSQLITE_ENABLE_MEMORY_MANAGEMENT=1
    -DSQLITE_ENABLE_RTREE=1
    -DSQLITE_MAX_COMPOUND_SELECT=50
    -DSQLITE_MAX_PAGE_SIZE=32768
    -DSQLITE_OMIT_TRACE=1
    -DSQLITE_TEMP_STORE=3
    -DSQLITE_THREADSAFE=2
    --enable-fts5 --enable-session
  }
  "Locking-Style" {
    -O2
    -DSQLITE_ENABLE_LOCKING_STYLE=1
  }
  "Apple" {
    -Os
    -DHAVE_GMTIME_R=1
    -DHAVE_ISNAN=1
    -DHAVE_LOCALTIME_R=1
    -DHAVE_PREAD=1
    -DHAVE_PWRITE=1
    -DHAVE_UTIME=1
    -DSQLITE_DEFAULT_CACHE_SIZE=1000
    -DSQLITE_DEFAULT_CKPTFULLFSYNC=1
    -DSQLITE_DEFAULT_MEMSTATUS=1
    -DSQLITE_DEFAULT_PAGE_SIZE=1024
    -DSQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS=1
    -DSQLITE_ENABLE_API_ARMOR=1
    -DSQLITE_ENABLE_AUTO_PROFILE=1
    -DSQLITE_ENABLE_FLOCKTIMEOUT=1
    -DSQLITE_ENABLE_FTS3=1
    -DSQLITE_ENABLE_FTS3_PARENTHESIS=1
    -DSQLITE_ENABLE_FTS3_TOKENIZER=1
    -DSQLITE_ENABLE_PERSIST_WAL=1
    -DSQLITE_ENABLE_PURGEABLE_PCACHE=1
    -DSQLITE_ENABLE_RTREE=1
    -DSQLITE_ENABLE_SNAPSHOT=1
    # -DSQLITE_ENABLE_SQLLOG=1
    -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1
    -DSQLITE_MAX_LENGTH=2147483645
    -DSQLITE_MAX_VARIABLE_NUMBER=500000
    # -DSQLITE_MEMDEBUG=1
    -DSQLITE_NO_SYNC=1
    -DSQLITE_OMIT_AUTORESET=1
    -DSQLITE_OMIT_LOAD_EXTENSION=1
    -DSQLITE_PREFER_PROXY_LOCKING=1
    -DSQLITE_SERIES_CONSTRAINT_VERIFY=1
    -DSQLITE_THREADSAFE=2
    -DSQLITE_USE_URI=1
    -DSQLITE_WRITE_WALFRAME_PREBUFFERED=1
    -DUSE_GUARDED_FD=1
    -DUSE_PREAD=1
    --enable-fts5
  }
  "Extra-Robustness" {
    -DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1
    -DSQLITE_MAX_ATTACHED=62
  }
  "Devkit" {
    -DSQLITE_DEFAULT_FILE_FORMAT=4
    -DSQLITE_MAX_ATTACHED=30
    -DSQLITE_ENABLE_COLUMN_METADATA
    -DSQLITE_ENABLE_FTS4
    -DSQLITE_ENABLE_FTS5
    -DSQLITE_ENABLE_FTS4_PARENTHESIS
    -DSQLITE_DISABLE_FTS4_DEFERRED
    -DSQLITE_ENABLE_RTREE
    --enable-fts5
  }
  "No-lookaside" {
    -DSQLITE_TEST_REALLOC_STRESS=1
    -DSQLITE_OMIT_LOOKASIDE=1
  }
  "Valgrind" {
    -DSQLITE_ENABLE_STAT4
    -DSQLITE_ENABLE_FTS4
    -DSQLITE_ENABLE_RTREE
    -DSQLITE_ENABLE_HIDDEN_COLUMNS
    -DCONFIG_SLOWDOWN_FACTOR=8.0
  }

  "Windows-Memdebug" {
    MEMDEBUG=1
    DEBUG=3
  }
  "Windows-Win32Heap" {
    WIN32HEAP=1
    DEBUG=4
  }

  # 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.
  #
  Fail0     {-O0}
  Fail2     {-O0}
  Fail3     {-O0}
  Fail4     {-O0}
  FuzzFail1 {-O0}
  FuzzFail2 {-O0}
}]
if {$tcl_platform(os)=="Darwin"} {
  lappend Configs(Apple) -DSQLITE_ENABLE_LOCKING_STYLE=1
}

array set ::Platforms [strip_comments {
  Linux-x86_64 {
    "Check-Symbols*"          "" checksymbols
    "Fast-One"                QUICKTEST_INCLUDE=rbu.test "fuzztest test"
    "Debug-One"               "" "mptest test"
    "Debug-Two"               "" test
    "Have-Not"                "" test
    "Secure-Delete"           "" test
    "Unlock-Notify"           QUICKTEST_INCLUDE=notify2.test test
    "User-Auth"               "" tcltest
    "Update-Delete-Limit"     "" test
    "Extra-Robustness"        "" test
    "Device-Two"              "" "threadtest test"
    "No-lookaside"            "" test
    "Devkit"                  "" test
    "Apple"                   "" test
    "Sanitize*"               "" test
    "Device-One"              "" alltest
    "Default"                 "" "threadtest fuzztest alltest"
    "Valgrind*"               "" valgrindtest
  }
  Linux-i686 {
    "Devkit"                  "" test
    "Have-Not"                "" test
    "Unlock-Notify"           QUICKTEST_INCLUDE=notify2.test test
    "Device-One"              "" test
    "Device-Two"              "" test
    "Default"                 "" "threadtest fuzztest alltest"
  }
  Darwin-i386 {
    "Locking-Style"           "" "mptest test"
    "Have-Not"                "" test
    "Apple"                   "" "threadtest fuzztest alltest"
  }
  Darwin-x86_64 {
    "Locking-Style"           "" "mptest test"
    "Have-Not"                "" test
    "Apple"                   "" "threadtest fuzztest alltest"
  }
  Darwin-arm64 {
    "Locking-Style"           "" "mptest test"
    "Have-Not"                "" test
    "Apple"                   "" "threadtest fuzztest alltest"
  }
  "Windows NT-intel" {
    "Stdcall"                 "" test
    "Have-Not"                "" test
    "Windows-Memdebug*"       "" test
    "Windows-Win32Heap*"      "" test
    "Default"                 "" "mptest fulltestonly"
  }
  "Windows NT-amd64" {
    "Stdcall"                 "" test
    "Have-Not"                "" test
    "Windows-Memdebug*"       "" test
    "Windows-Win32Heap*"      "" test
    "Default"                 "" "mptest fulltestonly"
  }

  # The Failure-Detection platform runs various tests that deliberately
  # fail.  This is used as a test of this script to verify that this script
  # correctly identifies failures.
  #
  Failure-Detection {
    Fail0*     "TEST_FAILURE=0" test
    Sanitize*  "TEST_FAILURE=1" test
    Fail2*     "TEST_FAILURE=2" valgrindtest
    Fail3*     "TEST_FAILURE=3" valgrindtest
    Fail4*     "TEST_FAILURE=4" test
    FuzzFail1* "TEST_FAILURE=5" test
    FuzzFail2* "TEST_FAILURE=5" valgrindtest
  }
}]

#--------------------------------------------------------------------------
#--------------------------------------------------------------------------
#--------------------------------------------------------------------------
# End of configuration section.
#--------------------------------------------------------------------------
#--------------------------------------------------------------------------
#--------------------------------------------------------------------------

# Configuration verification: Check that each entry in the list of configs
# specified for each platforms exists.
#
foreach {key value} [array get ::Platforms] {
  foreach {v vars t} $value {
    if {[string range $v end end]=="*"} {
      set v [string range $v 0 end-1]
    }
    if {0==[info exists ::Configs($v)]} {
      puts stderr "No such configuration: \"$v\""
      exit -1
    }
  }
}

proc usage {} {
  global argv0
  puts stderr [subst $::USAGE]
  exit 1
}

proc is_prefix {p str min} {
  set n [string length $p]
  if {$n<$min} { return 0 }
  if {[string range $str 0 [expr $n-1]]!=$p} { return 0 }
  return 1
}

proc main_configurations {} {
  foreach k [lsort [array names ::Configs]] {
    puts $k
  }
}

proc main_platforms {} {
  foreach k [lsort [array names ::Platforms]] {
    puts "\"$k\""
  }
}

proc main_script {args} {
  set bMsvc 0
  set nArg [llength $args]
  if {$nArg==3} {
    if {![is_prefix [lindex $args 0] -msvc 2]} usage
    set bMsvc 1
  } elseif {$nArg<2 || $nArg>3} {
    usage
  }
  set config [lindex $args end-1]
  set target [lindex $args end]

  set opts       [list]                         ;# OPTS value
  set cflags     [expr {$bMsvc ? "-Zi" : "-g"}] ;# CFLAGS value
  set makeOpts   [list]                         ;# Extra args for [make]
  set configOpts [list]                         ;# Extra args for [configure]

  if {$::tcl_platform(platform)=="windows" || $bMsvc} {
    lappend opts -DSQLITE_OS_WIN=1
  } else {
    lappend opts -DSQLITE_OS_UNIX=1
  }

  # Figure out if this is a synthetic ndebug or debug configuration.
  #
  set bRemoveDebug 0
  if {[string match *-ndebug $config]} {
    set bRemoveDebug 1
    set config [string range $config 0 end-7]
  }
  if {[string match *-debug $config]} {
    lappend opts -DSQLITE_DEBUG
    lappend opts -DSQLITE_EXTRA_IFNULLROW
    set config [string range $config 0 end-6]
  }
  regexp {^(.*)-[0-9]+} $config -> config

  # Ensure that the named configuration exists.
  #
  if {![info exists ::Configs($config)]} {
    puts stderr "No such config: $config"
    exit 1
  }

  # Loop through the parameters of the nominated configuration, updating
  # $opts, $cflags, $makeOpts and $configOpts along the way. Rules are as
  # follows:
  #
  #   1. If the parameter begins with a "*", discard it.
  #
  #   2. If $bRemoveDebug is set and the parameter is -DSQLITE_DEBUG or
  #      -DSQLITE_DEBUG=1, discard it
  #
  #   3. If the parameter begins with "-D", add it to $opts.
  #
  #   4. If the parameter begins with "--" add it to $configOpts. Unless
  #      this command is preparing a script for MSVC - then add an 
  #      equivalent to $makeOpts or $opts.
  #
  #   5. If the parameter begins with "-" add it to $cflags. If in MSVC
  #      mode and the parameter is an -O<integer> option, instead add
  #      an OPTIMIZATIONS=<integer> switch to $makeOpts.
  #
  #   6. If none of the above apply, add the parameter to $makeOpts
  #
  foreach param $::Configs($config) {
    if {[string range $param 0 0]=="*"} continue

    if {$bRemoveDebug} {
      if {$param=="-DSQLITE_DEBUG" || $param=="-DSQLITE_DEBUG=1"
       || $param=="-DSQLITE_MEMDEBUG" || $param=="-DSQLITE_MEMDEBUG=1"
       || $param=="--enable-debug"
      } {
        continue
      }
    }

    if {[string range $param 0 1]=="-D"} {
      lappend opts $param
      continue
    }

    if {[string range $param 0 1]=="--"} {
      if {$bMsvc} {
        switch -- $param {
          --disable-amalgamation {
            lappend makeOpts USE_AMALGAMATION=0
          }
          --disable-shared {
            lappend makeOpts USE_CRT_DLL=0 DYNAMIC_SHELL=0
          }
          --enable-fts5 {
            lappend opts -DSQLITE_ENABLE_FTS5
          } 
          --enable-shared {
            lappend makeOpts USE_CRT_DLL=1 DYNAMIC_SHELL=1
          }
          --enable-session {
            lappend opts -DSQLITE_ENABLE_PREUPDATE_HOOK
            lappend opts -DSQLITE_ENABLE_SESSION
          }
          default {
            error "Cannot translate $param for MSVC"
          }
        }
      } else {
        lappend configOpts $param
      }

      continue
    }

    if {[string range $param 0 0]=="-"} {
      if {$bMsvc && [regexp -- {^-O(\d+)$} $param -> level]} {
        lappend makeOpts OPTIMIZATIONS=$level
      } else {
        lappend cflags $param
      }
      continue
    }

    lappend makeOpts $param
  }

  # Some configurations specify -DHAVE_USLEEP=0. For all others, add
  # -DHAVE_USLEEP=1.
  #
  if {[lsearch $opts "-DHAVE_USLEEP=0"]<0} {
    lappend opts -DHAVE_USLEEP=1
  }

  if {$bMsvc==0} {
    puts {set -e}
    puts {}
    puts {if [ "$#" -ne 1 ] ; then}
    puts {  echo "Usage: $0 <sqlite-src-dir>" }
    puts {  exit -1 }
    puts {fi }
    puts {SRCDIR=$1}
    puts {}
    puts "TCL=\"[::tcl::pkgconfig get libdir,install]\""

    puts "\$SRCDIR/configure --with-tcl=\$TCL $configOpts"
    puts {}
    puts {OPTS="      -DSQLITE_NO_SYNC=1"}
    foreach o $opts { 
      puts "OPTS=\"\$OPTS $o\"" 
    }
    puts {}
    puts "CFLAGS=\"$cflags\""
    puts {}
    puts "make $target \"CFLAGS=\$CFLAGS\" \"OPTS=\$OPTS\" $makeOpts"
  } else {

    puts {set SRCDIR=%1}
    set makecmd    "nmake /f %SRCDIR%\\Makefile.msc TOP=%SRCDIR% $target "
    append makecmd "\"CFLAGS=$cflags\" \"OPTS=$opts\" $makeOpts"

    puts "set TMP=%CD%"
    puts $makecmd
  }
}

proc main_tests {args} {
  set bNodebug 0
  set nArg [llength $args]
  if {$nArg==2} {
    if {[is_prefix [lindex $args 0] -nodebug 2]} {
      set bNodebug 1
    } elseif {[is_prefix [lindex $args 0] -debug 2]} {
      set bNodebug 0
    } else usage
  } elseif {$nArg==0 || $nArg>2} {
    usage
  }
  set p [lindex $args end]
  if {![info exists ::Platforms($p)]} {
    puts stderr "No such platform: $p"
    exit 1
  }

  set lTest [list]

  foreach {config vars target} $::Platforms($p) {
    if {[string range $config end end]=="*"} {
      set config [string range $config 0 end-1]
    } elseif {$bNodebug==0} {
      set dtarget test
      if {[lsearch $target fuzztest]<0 && [lsearch $target test]<0} {
        set dtarget tcltest
      }
      if {$vars!=""} { set dtarget "$vars $dtarget" }

      if {[string first SQLITE_DEBUG $::Configs($config)]>=0
       || [string first --enable-debug $::Configs($config)]>=0
      } {
        lappend lTest "$config-ndebug \"$dtarget\""
      } else {
        lappend lTest "$config-debug \"$dtarget\""
      }
    }

    if {[llength $target]==1 && ([string match "*TEST_FAILURE*" $vars] || (
        [lsearch $target "valgrindtest"]<0
     && [lsearch $target "alltest"]<0
     && [lsearch $target "fulltestonly"]<0
     && ![string match Sanitize* $config]
    ))} {
      if {$vars!=""} { set target "$vars $target" }
      lappend lTest "$config \"$target\""
    } else {
      set idir -1
      foreach t $target {
        if {$t=="valgrindtest" || $t=="alltest" || $t=="fulltestonly"
         || [string match Sanitize* $config]
        } {
          if {$vars!=""} { set t "$vars $t" }
          for {set ii 1} {$ii<=4} {incr ii} {
            lappend lTest "$config-[incr idir] \"TCLTEST_PART=$ii/4 $t\""
          }
        } else {
          if {$vars!=""} { set t "$vars $t" }
          lappend lTest "$config-[incr idir] \"$t\""
        }
      }
    }
  }

  foreach l $lTest {
    puts $l
  }

}

if {[llength $argv]==0} { usage }
set cmd [lindex $argv 0]
set n [expr [llength $argv]-1]
if {[string match ${cmd}* configurations] && $n==0} {
  main_configurations 
} elseif {[string match ${cmd}* script]} {
  main_script {*}[lrange $argv 1 end]
} elseif {[string match ${cmd}* platforms] && $n==0} {
  main_platforms
} elseif {[string match ${cmd}* tests]} {
  main_tests {*}[lrange $argv 1 end]
} else {
  usage
}

Changes to test/resetdb.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
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







-
+




-
+







+
+
+
+







  # Thoroughly corrupt the database file by overwriting the first
  # page with randomness.
  sqlite3_db_config db DEFENSIVE 0
  catchsql {
    UPDATE sqlite_dbpage SET data=randomblob(4096) WHERE pgno=1;
    PRAGMA quick_check;
  }
} {1 {unsupported file format}}
} {1 {file is not a database}}
do_test 201 {
  catchsql {
    PRAGMA quick_check;
  } db2
} {1 {unsupported file format}}
} {1 {file is not a database}}

do_test 210 {
  # Reset the database file using SQLITE_DBCONFIG_RESET_DATABASE
  sqlite3_db_config db RESET_DB 1
  db eval VACUUM
  sqlite3_db_config db RESET_DB 0

  # If using sqlite3_prepare() instead of _v2() or _v3(), the block 
  # below raises an SQLITE_SCHEMA error. The following fixes this.
  if {[permutation]=="prepare"} { catchsql "SELECT * FROM sqlite_master" db2 }

  # Verify that the reset took, even on the separate database connection
  catchsql {
     PRAGMA page_count;
     PRAGMA page_size;
     PRAGMA quick_check;
     PRAGMA journal_mode;
  } db2
246
247
248
249
250
251
252
253










































254
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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  sqlite3_db_config db RESET_DB 0
} {0}

do_execsql_test 740 {
  PRAGMA page_count;
  PRAGMA integrity_check;
} {1 ok}

#-------------------------------------------------------------------------
ifcapable utf16 {
  reset_db
  do_execsql_test 800 {
    PRAGMA encoding = 'utf8';
    CREATE TABLE t1(a, b);
    PRAGMA encoding;
  } {UTF-8}
  
  db close
  sqlite3 db test.db

  sqlite3 db2 test.db
  do_execsql_test -db db2 810 {
    CREATE TEMP TABLE t2(x);
    INSERT INTO t2 VALUES('hello world');
    SELECT name FROM sqlite_schema;
  } {t1}
  do_test 820 {
    db eval "PRAGMA encoding = 'utf16'"
    sqlite3_db_config db RESET_DB 1
  } {1}
  do_test 830 {
    db eval VACUUM
    sqlite3_db_config db RESET_DB 0
  } {0}
  do_test 840 {
    string range [db eval {
      CREATE TABLE t1(a, b);
      INSERT INTO t1 VALUES('one', 'two');
      PRAGMA encoding;
    }] 0 5
  } {UTF-16}

  do_test 850 {
    catchsql { SELECT * FROM t1; } db2 
  } {1 {attached databases must use the same text encoding as main database}}
  do_test 860 {
    catchsql { SELECT * FROM t2; } db2 
  } {1 {attached databases must use the same text encoding as main database}}
}

finish_test

Added test/returning1.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2021-01-28
#
# 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 the new RETURNING clause
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix returning1

do_execsql_test 1.0 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY,b,c DEFAULT 'pax');
  INSERT INTO t1(b) VALUES(10),('happy'),(NULL) RETURNING a,b,c;
} {1 10 pax 2 happy pax 3 {} pax}
do_execsql_test 1.1 {
  SELECT * FROM t1;
} {1 10 pax 2 happy pax 3 {} pax}
do_execsql_test 1.2 {
  INSERT INTO t1(b,c) VALUES(5,99) RETURNING b,c,a,rowid;
} {5 99 4 4}
do_execsql_test 1.3 {
  SELECT * FROM t1;
} {1 10 pax 2 happy pax 3 {} pax 4 5 99}
do_execsql_test 1.4 {
  INSERT INTO t1 DEFAULT VALUES RETURNING *;
} {5 {} pax}
do_execsql_test 1.5 {
  SELECT * FROM t1;
} {1 10 pax 2 happy pax 3 {} pax 4 5 99 5 {} pax}
do_execsql_test 1.6 {
  CREATE TABLE t2(x,y,z);
  INSERT INTO t2 VALUES(11,12,13),(21,'b','c'),(31,'b-value',4.75);
}
do_execsql_test 1.7 {
  INSERT INTO t1 SELECT * FROM t2 RETURNING *;
} {11 12 13 21 b c 31 b-value 4.75}
do_execsql_test 1.8 {
  SELECT *, '|' FROM t1;
} {1 10 pax | 2 happy pax | 3 {} pax | 4 5 99 | 5 {} pax | 11 12 13 | 21 b c | 31 b-value 4.75 |}

do_execsql_test 2.1 {
  UPDATE t1 SET c='bellum' WHERE c='pax' RETURNING rowid, b, '|';
} {1 10 | 2 happy | 3 {} | 5 {} |}
do_execsql_test 2.2 {
  SELECT *, '|' FROM t1;
} {1 10 bellum | 2 happy bellum | 3 {} bellum | 4 5 99 | 5 {} bellum | 11 12 13 | 21 b c | 31 b-value 4.75 |}

do_execsql_test 3.1 {
  DELETE FROM t1 WHERE c='bellum' RETURNING rowid, *, '|';
} {1 1 10 bellum | 2 2 happy bellum | 3 3 {} bellum | 5 5 {} bellum |}
do_execsql_test 3.2 {
  SELECT *, '|' FROM t1;
} {4 5 99 | 11 12 13 | 21 b c | 31 b-value 4.75 |}

do_execsql_test 4.1 {
  CREATE TABLE t4(a INT, b INT DEFAULT 1234, c INT DEFAULT -16);
  CREATE UNIQUE INDEX t4a ON t4(a);
  INSERT INTO t4(a,b,c) VALUES(1,2,3);
} {}
do_execsql_test 4.2 {
  INSERT INTO t4(a,b,c) VALUES(1,22,33)
  ON CONFLICT(a) DO UPDATE SET b=44
  RETURNING *;
} {1 44 3}
do_execsql_test 4.3 {
  SELECT * FROM t4;
} {1 44 3}
do_execsql_test 4.4 {
  DELETE FROM t4;
  INSERT INTO t4 VALUES(1,2,3),(4,5,6),(7,8,9);
} {}
do_execsql_test 4.5 {
  INSERT INTO t4(a,b,c) VALUES(2,3,4),(4,5,6),(5,6,7)
  ON CONFLICT(a) DO UPDATE SET b=100
  RETURNING *, '|';
} {2 3 4 | 4 100 6 | 5 6 7 |}

#-------------------------------------------------------------------------
# Test RETURNING on a table with virtual columns.
#
reset_db
do_execsql_test 5.0 {
  CREATE TABLE t1(xyz);
  CREATE TABLE t2(a as (1+1), b);
}

do_execsql_test 5.1 {
  UPDATE t2 SET b='123' WHERE b='abc' RETURNING (SELECT b FROM t1);
} {}

do_execsql_test 5.2 {
  INSERT INTO t2(b) VALUES('abc');
}

do_execsql_test 5.3 {
  UPDATE t2 SET b='123' WHERE b='abc' RETURNING (SELECT b FROM t1);
} {{}}

do_execsql_test 5.4 {
  INSERT INTO t2(b) VALUES('abc');
  INSERT INTO t1(xyz) VALUES(1);
  UPDATE t2 SET b='123' WHERE b='abc' RETURNING b;
} {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}}

# 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}

# RETURNING column names are dequoted.
# https://sqlite.org/forum/forumpost/033daf0b32
#
reset_db
do_test 12.1 {
  db eval {CREATE TABLE t1(x INT, y INT)}
  unset -nocomplain cname
  db eval {INSERT INTO t1(x) VALUES(1) RETURNING "x";} cname {}
  lsort [array names cname]
} {* x}
do_test 12.2 {
  unset -nocomplain cname
  db eval {INSERT INTO t1(x) VALUES(2) RETURNING [x];} cname {}
  lsort [array names cname]
} {* x} 
do_test 12.3 {
  unset -nocomplain cname
  db eval {INSERT INTO t1(x) VALUES(3) RETURNING x AS [xyz];} cname {}
  lsort [array names cname]
} {* xyz}
do_test 12.4 {
  unset -nocomplain cname
  db eval {INSERT INTO t1(x,y) VALUES(4,5) RETURNING "x"+"y";} cname {}
  lsort [array names cname]
} {{"x"+"y"} *}

ifcapable rtree {
#-------------------------------------------------------------------------
# Based on dbsqlfuzz find crash-ffbba524cac354b2a61bfd677cec9d2a4333f49a
reset_db
do_execsql_test 13.0 {
  CREATE VIRTUAL TABLE t1 USING rtree(a, b, c);
  CREATE TABLE t2(x);
}

do_execsql_test 13.1 {
  INSERT INTO t1(a,b,c) VALUES(1,2,3) 
  RETURNING (SELECT b FROM t2);
} {{}}
} ;# end ifcapable rtree

# 2021-12-01 Forum post https://sqlite.org/forum/forumpost/793beaf322
# Need to report foreign key constraint errors prior to RETURNING
#
reset_db
do_execsql_test 14.0 {
  PRAGMA foreign_keys(1);
  CREATE TABLE Parent(id INTEGER PRIMARY KEY);
  CREATE TABLE Child(id INTEGER PRIMARY KEY, parent_id INTEGER REFERENCES Parent(id));
} {}
do_catchsql_test 14.1 {
  INSERT INTO child(parent_id) VALUES(123) RETURNING id;
} {1 {FOREIGN KEY constraint failed}}

# 2021-12-28 Forum post https://sqlite.org/forum/forumpost/e0c7574ab2
# Incorrect affinity for REAL values that can be represented as integers.
#
reset_db
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db
do_execsql_test 15.0 {
  CREATE TABLE t1(x REAL);
  INSERT INTO t1(x) VALUES(5.0) RETURNING x, affinity(x);
} {5.0 real}
do_execsql_test 15.1 {
  UPDATE t1 SET x=x+1 RETURNING x, affinity(x);
} {6.0 real}
do_execsql_test 15.2 {
  DELETE FROM t1 RETURNING x, affinity(x);
} {6.0 real}

# 2022-02-28 Forum post https://sqlite.org/forum/forumpost/595e132f71
# RETURNING with the xfer optimization
#
reset_db
do_execsql_test 16.0 {
  CREATE TABLE t1(a,b,c);
  INSERT INTO t1 VALUES(1,2,3),('a','b','c');
  CREATE TEMP TABLE t2(x,y,z);
  INSERT INTO t2 SELECT * FROM t1 RETURNING *;
} {1 2 3 a b c}
do_execsql_test 16.1 {
  SELECT * FROM t2;
} {1 2 3 a b c}


foreach {tn temp} {
  1 ""
  2 TEMP
} {
  reset_db
  do_execsql_test 17.$tn.0 "
    CREATE $temp TABLE foo (
      fooid INTEGER PRIMARY KEY,
      fooval INTEGER NOT NULL UNIQUE,
      refcnt INTEGER NOT NULL DEFAULT 1
    );
  "
  do_execsql_test 17.$tn.1 {
    INSERT INTO foo (fooval) VALUES (17), (4711), (17)
      ON CONFLICT DO
      UPDATE SET refcnt = refcnt+1
    RETURNING fooid;
  } {
    1 2 1
  }
}

# 2022-01-13 https://sqlite.org/forum/forumpost/d010a26798
#
reset_db
do_execsql_test 17.0 {
  CREATE TABLE bug(id INTEGER PRIMARY KEY NOT NULL, x);
  INSERT INTO bug(id,x) VALUES(20, NULL);
  UPDATE bug SET x=NULL WHERE id = 20 RETURNING quote(x), x IS NULL;
} {NULL 1}

finish_test

Added test/returningfault.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022 January 5
#
# 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/malloc_common.tcl


do_execsql_test 1.0 {
  CREATE TABLE t1 (b);
} {}
faultsim_save_and_close

do_faultsim_test pagerfault-1 -faults oom-t* -prep {
  faultsim_restore_and_reopen
} -body {
  execsql { 
    INSERT INTO t1(b) VALUES(65) RETURNING (
      SELECT * FROM sqlite_temp_schema
    ) AS aaa;
  }
} -test {
  faultsim_test_result {1 {sub-select returns 5 columns - expected 1}}
}


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

Added test/round1.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019-05-24
#
# 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.
#
#***********************************************************************
# Test cases for rounding behavior of floating point values.
#
# TESTRUNNER: slow

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix round1

expr srand(0)
unset -nocomplain iTest
for {set iTest 1} {$iTest<=50000} {incr iTest} {
   set x1 [expr int(rand()*100000)]
   set x2 [expr int(rand()*100000)+1000*int(rand()*10000)]
   set n [expr int(rand()*8)+1]
   set x3 [string range [format %09d $x2] [expr {9-$n}] end]
   set r $x1.$x3
   set ans [string trimright $r 0]
   if {[string match *. $ans]} {set ans ${ans}0}
   do_test $iTest/$n/${r}4=>$ans {
     set x [db one "SELECT round(${r}4,$n)"]
   } $ans
   set x4 [string range [format %09d [expr {$x2+1}]] [expr {9-$n}] end]
   if {[string trim $x3 9]==""} {incr x1}
   set r2 $x1.$x4
   set ans [string trimright $r2 0]
   if {[string match *. $ans]} {set ans ${ans}0}
   do_test $iTest/$n/${r}5=>$ans {
     set x [db one "SELECT round(${r}5,$n)"]
   } $ans
}

finish_test

Changes to test/rowid.test.

14
15
16
17
18
19
20

21
22
23
24
25
26
27
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28







+







#
# EVIDENCE-OF: R-36924-43758 By default, every row in SQLite has a
# special column, usually called the "rowid", that uniquely identifies
# that row within the table.

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix rowid

# Basic ROWID functionality tests.
#
do_test rowid-1.1 {
  execsql {
    CREATE TABLE t1(x int, y int);
    INSERT INTO t1 VALUES(1,2);
655
656
657
658
659
660
661


























662
663
664
665
666
667
668
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







do_test rowid-11.3 {
  execsql {SELECT rowid, a FROM t5 WHERE rowid<'abc'}
} {1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8}
do_test rowid-11.4 {
  execsql {SELECT rowid, a FROM t5 WHERE rowid<='abc'}
} {1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8}

do_test rowid-11.asc.1 {
  execsql {SELECT rowid, a FROM t5 WHERE rowid>'abc' ORDER BY 1 ASC}
} {}
do_test rowid-11.asc.2 {
  execsql {SELECT rowid, a FROM t5 WHERE rowid>='abc' ORDER BY 1 ASC}
} {}
do_test rowid-11.asc.3 {
  execsql {SELECT rowid, a FROM t5 WHERE rowid<'abc' ORDER BY 1 ASC}
} {1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8}
do_test rowid-11.asc.4 {
  execsql {SELECT rowid, a FROM t5 WHERE rowid<='abc' ORDER BY 1 ASC}
} {1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8}

do_test rowid-11.desc.1 {
  execsql {SELECT rowid, a FROM t5 WHERE rowid>'abc' ORDER BY 1 DESC}
} {}
do_test rowid-11.desc.2 {
  execsql {SELECT rowid, a FROM t5 WHERE rowid>='abc' ORDER BY 1 DESC}
} {}
do_test rowid-11.desc.3 {
  execsql {SELECT rowid, a FROM t5 WHERE rowid<'abc' ORDER BY 1 DESC}
} {8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1}
do_test rowid-11.desc.4 {
  execsql {SELECT rowid, a FROM t5 WHERE rowid<='abc' ORDER BY 1 DESC}
} {8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1}

# Test the automatic generation of rowids when the table already contains
# a rowid with the maximum value.
#
# Once the maximum rowid is taken, rowids are normally chosen at
# random.  By by reseting the random number generator, we can cause
# the rowid guessing loop to collide with prior rowids, and test the
# loop out to its limit of 100 iterations.  After 100 collisions, the
714
715
716
717
718
719
720
721







































































722
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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

db function addrow rowid_addrow_func
do_execsql_test rowid-13.1 {
  CREATE TABLE t13(x);
  INSERT INTO t13(rowid,x) VALUES(1234,5);
  SELECT rowid, x, addrow(rowid+1000), '|' FROM t13 LIMIT 3;
  SELECT last_insert_rowid();
} {1234 5 2234 | 2234 4990756 3234 | 3234 10458756 4234 | 4234}

#-------------------------------------------------------------------------
do_execsql_test rowid-14.0 {
  CREATE TABLE t14(x INTEGER PRIMARY KEY);
  INSERT INTO t14(x) VALUES (100);
}
do_execsql_test rowid-14.1 {
  SELECT * FROM t14 WHERE x < 'a' ORDER BY rowid ASC;
} {100}
do_execsql_test rowid-14.2 {
  SELECT * FROM t14 WHERE x < 'a' ORDER BY rowid DESC;
} {100}

do_execsql_test rowid-14.3 {
  DELETE FROM t14;
  SELECT * FROM t14 WHERE x < 'a' ORDER BY rowid ASC;
} {}
do_execsql_test rowid-14.4 {
  SELECT * FROM t14 WHERE x < 'a' ORDER BY rowid DESC;
} {}

reset_db
do_execsql_test rowid-15.0 {
  PRAGMA reverse_unordered_selects=true;
  CREATE TABLE t1 (c0, c1);
  CREATE TABLE t2 (c0 INT UNIQUE);
  INSERT INTO t1(c0, c1) VALUES (0, 0), (0, NULL);
  INSERT INTO t2(c0) VALUES (1);
}

do_execsql_test rowid-15.1 {
  SELECT t2.c0, t1.c1 FROM t1, t2 
  WHERE (t2.rowid <= 'a') OR (t1.c0 <= t2.c0) LIMIT 100
} {1 {} 1 0}

do_execsql_test rowid-15.2 {
  SELECT 1, NULL INTERSECT SELECT * FROM (
      SELECT t2.c0, t1.c1 FROM t1, t2
      WHERE ((t2.rowid <= 'a')) OR (t1.c0 <= t2.c0) ORDER BY 'a' DESC LIMIT 100
  );
} {1 {}}

#-------------------------------------------------------------------------
# Check that an unqualified "rowid" can be used in join queries so long 
# as only one of the source objects has a rowid column.
#
reset_db
do_execsql_test 16.0 {
  CREATE TABLE t1(x);
  CREATE TABLE t2(y PRIMARY KEY) WITHOUT ROWID;
  CREATE VIEW v1 AS SELECT x FROM t1;
  CREATE TABLE t3(z);

  INSERT INTO t1(rowid, x) VALUES(1, 1);
  INSERT INTO t2(y) VALUES(2);
  INSERT INTO t3(rowid, z) VALUES(3, 3);
}

do_execsql_test 16.1 { SELECT rowid FROM t1, t2; } {1}
do_execsql_test 16.2 { SELECT rowid FROM t1, v1; } {1}
do_execsql_test 16.3 { SELECT rowid FROM t3, v1; } {3}
do_execsql_test 16.4 { SELECT rowid FROM t3, (SELECT 123); } {3}

do_execsql_test 16.5 { SELECT rowid FROM t2, t1; } {1}
do_execsql_test 16.6 { SELECT rowid FROM v1, t1; } {1}
do_execsql_test 16.7 { SELECT rowid FROM v1, t3; } {3}
do_execsql_test 16.8 { SELECT rowid FROM (SELECT 123), t3; } {3}

do_catchsql_test 16.5 { SELECT rowid FROM t1, t3; } {1 {no such column: rowid}}



finish_test

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 {
256
257
258
259
260
261
262
263

264
265

266
267












268
269
270
271
272
273
274
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







-
+

-
+


+
+
+
+
+
+
+
+
+
+
+
+







} {1 {row value misused}}

# 2016-10-27: https://www.sqlite.org/src/tktview/fef4bb4bd9185ec8f
# Incorrect result from a LEFT JOIN with a row-value constraint
#
do_execsql_test 12.1 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a,b); INSERT INTO t1 VALUES(1,2);
  CREATE TABLE t1(a INT,b INT); INSERT INTO t1 VALUES(1,2);
  DROP TABLE IF EXISTS t2;
  CREATE TABLE t2(x,y); INSERT INTO t2 VALUES(3,4);
  CREATE TABLE t2(x INT,y INT); INSERT INTO t2 VALUES(3,4);
  SELECT *,'x' FROM t1 LEFT JOIN t2 ON (a,b)=(x,y);
} {1 2 {} {} x}
db null -
do_execsql_test 12.2 {
  SELECT t1.*, t2.* FROM t2 RIGHT JOIN t1 ON (a,b)=(x,y);
} {1 2 - -}
do_execsql_test 12.3 {
  SELECT t1.*, t2.* FROM t1 FULL JOIN t2 ON (a,b)=(x,y)
   ORDER BY coalesce(a,x);
} {
  1 2 - -
  - - 3 4
}
db null {}


foreach {tn sql} {
  0 "SELECT (1,2) AS x WHERE x=3"
  1 "SELECT (1,2) BETWEEN 1 AND 2"
  2 "SELECT 1 BETWEEN (1,2) AND 2"
  3 "SELECT 2 BETWEEN 1 AND (1,2)"
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
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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







-
+
















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

do_execsql_test 19.35 {
  SELECT * FROM t1 WHERE (3,33)>=(a,b) ORDER BY a DESC;
} {3 33 2 22 1 11}
do_execsql_test 19.36 {
  SELECT * FROM t1 WHERE (3,32)>=(a,b) ORDER BY a DESC;
} {2 22 1 11}

# 2018-02-18: Memory leak nexted row-value.  Detected by OSSFuzz.
# 2018-02-18: Memory leak nested row-value.  Detected by OSSFuzz.
#
do_catchsql_test 20.1 {
  SELECT 1 WHERE (2,(2,0)) IS (2,(2,0));
} {0 1}

# 2018-11-03: Ticket https://www.sqlite.org/src/info/1a84668dcfdebaf1
# Assertion fault when doing row-value operations on a primary key
# containing duplicate columns.
#
do_execsql_test 21.0 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a,b,PRIMARY KEY(b,b));
  INSERT INTO t1 VALUES(1,2),(3,4),(5,6);
  SELECT * FROM t1 WHERE (a,b) IN (VALUES(1,2));  
} {1 2}

# 2019-08-09: Multi-column subquery on the RHS of an IN operator.
#
do_execsql_test 22.100 {
  SELECT (SELECT 3,4 UNION SELECT 5,6 ORDER BY 1) IN (SELECT 3,4);
  SELECT (SELECT 3,4 UNION SELECT 5,6 ORDER BY 1) IN (SELECT 5,6);
  SELECT (SELECT 5,6 UNION SELECT 3,4 ORDER BY 1) IN (SELECT 3,4);
  SELECT (SELECT 5,6 UNION SELECT 3,4 ORDER BY 1) IN (SELECT 5,6);
  SELECT (SELECT 3,4 UNION SELECT 5,6 ORDER BY 1 DESC) IN (SELECT 3,4);
  SELECT (SELECT 3,4 UNION SELECT 5,6 ORDER BY 1 DESC) IN (SELECT 5,6);
  SELECT (SELECT 5,6 UNION SELECT 3,4 ORDER BY 1 DESC) IN (SELECT 3,4);
  SELECT (SELECT 5,6 UNION SELECT 3,4 ORDER BY 1 DESC) IN (SELECT 5,6);
} {1 0 1 0 0 1 0 1}

# 2019-10-21 Ticket b47e3627ecaadbde
#
do_execsql_test 23.100 {
  DROP TABLE IF EXISTS t0;
  CREATE TABLE t0(aa COLLATE NOCASE, bb);
  INSERT INTO t0 VALUES('a', 'A');
  SELECT (+bb,1) >= (aa, 1), (aa,1)<=(+bb,1) FROM t0;
  SELECT 2 FROM t0 WHERE (+bb,1) >= (aa,1);
  SELECT 3 FROM t0 WHERE (aa,1) <= (+bb,1);
} {0 1 3}
do_execsql_test 23.110 {
  SELECT (SELECT +bb,1) >= (aa, 1), (aa,1)<=(SELECT +bb,1) FROM t0;
  SELECT 2 FROM t0 WHERE (SELECT +bb,1) >= (aa,1);
  SELECT 3 FROM t0 WHERE (aa,1) <= (SELECT +bb,1);
} {0 1 3}

# 2019-10-22 Ticket 6ef984af8972c2eb
do_execsql_test 24.100 {
  DROP TABLE t0;
  CREATE TABLE t0(c0 TEXT PRIMARY KEY);
  INSERT INTO t0(c0) VALUES ('');
  SELECT (t0.c0, TRUE) > (CAST(0 AS REAL), FALSE) FROM t0;
  SELECT 2 FROM t0 WHERE (t0.c0, TRUE) > (CAST('' AS REAL), FALSE);
} {1 2}

# 2019-10-23 Ticket 135c9da7513e5a97
do_execsql_test 25.10 {
  DROP TABLE t0;
  CREATE TABLE t0(c0 UNIQUE);
  INSERT INTO t0(c0) VALUES('a');
  SELECT (t0.c0, 0) < ('B' COLLATE NOCASE, 0) FROM t0;
  SELECT 2 FROM t0 WHERE (t0.c0, 0) < ('B' COLLATE NOCASE, 0);
} {1 2}
do_execsql_test 25.20 {
  SELECT ('B' COLLATE NOCASE, 0)> (t0.c0, 0) FROM t0;
  SELECT 2 FROM t0 WHERE ('B' COLLATE NOCASE, 0)> (t0.c0, 0);
} {1 2}
do_execsql_test 25.30 {
  SELECT ('B', 0)> (t0.c0 COLLATE nocase, 0) FROM t0;
  SELECT 2 FROM t0 WHERE ('B', 0)> (t0.c0 COLLATE nocase, 0);
} {1 2}
do_execsql_test 25.40 {
  SELECT (t0.c0 COLLATE nocase, 0) < ('B', 0) FROM t0;
  SELECT 2 FROM t0 WHERE (t0.c0 COLLATE nocase, 0) < ('B', 0);
} {1 2}

# 2019-11-04 Ticket 02aa2bd02f97d0f2
# The TK_VECTOR operator messes up sqlite3ExprImpliesNonNull() which
# causes incorrect LEFT JOIN strength reduction.  TK_VECTOR should be
# treated the same as TK_OR.
#
db close
sqlite3 db :memory:
do_execsql_test 26.10 {
  CREATE TABLE t0(c0);
  CREATE TABLE t1(c1);
  INSERT INTO t1(c1) VALUES (0);
  SELECT (c0, x'') != (NULL, 0) FROM t1 LEFT JOIN t0;
} {1}
do_execsql_test 26.20 {
  SELECT 2 FROM t1 LEFT JOIN t0 ON (c0, x'') != (NULL, 0);
} {2}
do_execsql_test 26.21 {
  SELECT 21 FROM t0 RIGHT JOIN t1 ON (c0, x'') != (NULL, 0);
} {21}
do_execsql_test 26.30 {
  SELECT 3 FROM t1 LEFT JOIN t0 WHERE (c0, x'') != (NULL, 0);
} {3}
do_execsql_test 26.31 {
  SELECT 31 FROM t0 RIGHT JOIN t1 WHERE (c0, x'') != (NULL, 0);
} {31}

# 2019-12-30 ticket 892575cdba4e1e36
#
reset_db
do_catchsql_test 27.10 {
  CREATE TABLE t0(c0 CHECK(((0, 0) > (0, c0))));
  INSERT INTO t0(c0) VALUES(0) ON CONFLICT(c0) DO UPDATE SET c0 = 3;
} {1 {ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint}}

# 2021-02-03
# https://bugs.chromium.org/p/chromium/issues/detail?id=1173511
# Faulty assert() statement.
#
reset_db
do_catchsql_test 28.10 {
  CREATE TABLE t0(c0 PRIMARY KEY, c1);
  CREATE TRIGGER trigger0 BEFORE DELETE ON t0 BEGIN
   SELECT (SELECT c0,c1  FROM t0)  FROM t0;
  END ;
  DELETE FROM t0;
} {1 {sub-select returns 2 columns - expected 1}}

# 2021-03-19
# dbsqlfuzz find of a NEVER().
do_catchsql_test 29.1 {
  SELECT (SELECT 1 WHERE ((SELECT 1 WHERE (2,(2,0)) IS (2,(20))),(2,0)) IS (2,(20))) WHERE (2,(2,0)) IS (2 IN(SELECT 1 WHERE (2,(2,2,0)) IS (2,(20))),(20));
} {1 {row value misused}}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 30.0 {
  CREATE TABLE t1(x, y, z);
  CREATE TABLE t2(a, b);

  INSERT INTO t1 VALUES(1000, 2000, 3000);
  INSERT INTO t2 VALUES(NULL, NULL);
}

do_execsql_test 30.1 {
  UPDATE t2 SET (a,b)=(
    SELECT max( t1.x ) OVER( PARTITION BY sum( (SELECT t1.y) ) ), 2
  )
  FROM t1;
} {}

do_execsql_test 30.2 {
  SELECT * FROM t2
} {1000 2}

reset_db
do_execsql_test 30.3 {
  CREATE TABLE t1(x INT PRIMARY KEY, y, z);
  CREATE TABLE t2(a,b,c,d,e,PRIMARY KEY(a,b))WITHOUT ROWID;

  UPDATE t2 SET (d,d,a)=(SELECT EXISTS(SELECT 1 IN(SELECT max( 1 IN(SELECT x ORDER BY 1)) OVER(PARTITION BY sum((SELECT y FROM t1 UNION SELECT x ORDER BY 1)))INTERSECT SELECT EXISTS(SELECT 1 FROM t1 UNION SELECT x ORDER BY 1) ORDER BY 1) ORDERa)|9 AS blob, 2, 3) FROM t1 WHERE x<a;
}

# 2022-01-21 https://sqlite.org/forum/forumpost/ab95010d410a0a55
reset_db
do_execsql_test 31.1 {
  CREATE TABLE a(a1 PRIMARY KEY,a2);
  INSERT INTO a VALUES(1,5);
  CREATE TABLE b(b1 UNIQUE,b2);
  SELECT * FROM a LEFT JOIN b ON b2=NULL AND b2=5 WHERE (b1,substr(b.b1,1,1))==(SELECT 1024,'b');
} {}
do_execsql_test 31.1b {
  SELECT * FROM b RIGHT JOIN a ON b2=NULL AND b2=5 WHERE (b1,substr(b.b1,1,1))==(SELECT 1024,'b');
} {}
do_execsql_test 31.2 {
  CREATE TABLE t1(a);
  INSERT INTO t1 VALUES(0);
  CREATE TABLE t2(b,c,d);
  INSERT INTO t2 VALUES(NULL,123,456);
  SELECT * FROM t1 LEFT JOIN t2 ON b=NULL WHERE (c,d)==(SELECT 123, 456+a);
} {}
do_execsql_test 31.2b {
  SELECT * FROM t2 RIGHT JOIN t1 ON b=NULL WHERE (c,d)==(SELECT 123, 456+a);
} {}

# 2022-02-03 dbsqlfuzz 80a9fade844b4fb43564efc972bcb2c68270f5d1
reset_db
do_execsql_test 32.1 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b INT, c INT);
  CREATE TABLE t2(d INTEGER PRIMARY KEY);
  INSERT INTO t1(a,b,c) VALUES(500,654,456);
  INSERT INTO t1(a,b,c) VALUES(501,655,456);
  INSERT INTO t1(a,b,c) VALUES(502,654,122);
  INSERT INTO t1(a,b,c) VALUES(503,654,221);
  INSERT INTO t1(a,b,c) VALUES(601,654,122);
  INSERT INTO t2(d) VALUES(456);
  INSERT INTO t2(d) VALUES(122);
  SELECT a FROM (
    SELECT t1.a FROM t2, t1 
    WHERE (987, t1.b) = ( SELECT 987, 654 ) AND t2.d=t1.c
  ) AS t3
  WHERE a=1234 OR a<=567;
} {500 502}

# 2022-07-15
# https://sqlite.org/forum/forumpost/3607259d3c
#
reset_db
do_execsql_test 33.1 {
  CREATE TABLE t1(a INT, b INT PRIMARY KEY) WITHOUT ROWID;
  INSERT INTO t1(a, b) VALUES (0, 1),(15,-7),(3,100);
  ANALYZE;
} {}
do_execsql_test 33.2 {
  SELECT * FROM t1 WHERE (b,a) BETWEEN (0,5) AND (99,-2);
} {0 1}
do_execsql_test 33.3 {
  SELECT * FROM t1 WHERE (b,a) BETWEEN (-8,5) AND (0,-2);
} {15 -7}
do_execsql_test 33.3 {
  SELECT * FROM t1 WHERE (b,a) BETWEEN (3,5) AND (100,4);
} {3 100}
do_execsql_test 33.3 {
  SELECT * FROM t1 WHERE (b,a) BETWEEN (3,5) AND (100,2);
} {}
do_execsql_test 33.3 {
  SELECT * FROM t1 WHERE (a,b) BETWEEN (-2,99) AND (1,0);
} {0 1}
do_execsql_test 33.3 {
  SELECT * FROM t1 WHERE (a,b) BETWEEN (14,99) AND (16,0);
} {15 -7}
do_execsql_test 33.3 {
  SELECT * FROM t1 WHERE (a,b) BETWEEN (2,99) AND (4,0);
} {3 100}

finish_test

Changes to test/rowvalue3.test.

209
210
211
212
213
214
215
216


217
218
219
220
209
210
211
212
213
214
215

216
217
218
219
220
221







-
+
+




  DROP TABLE IF EXISTS t1;
  DROP TABLE IF EXISTS t2;
  CREATE TABLE T1(a TEXT);
  INSERT INTO T1(a) VALUES ('aaa');
  CREATE TABLE T2(a TEXT PRIMARY KEY,n INT);
  INSERT INTO T2(a, n) VALUES('aaa',0);
  SELECT * FROM T2
  WHERE (a,n) IN (SELECT T1.a, V.n FROM T1, (SELECT * FROM (SELECT 0 n)) V);
   WHERE (a,n) IN (SELECT T1.a, V.n
                     FROM T1, (SELECT * FROM (SELECT 0 n) T3) V);
} {aaa 0}


finish_test

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=?)
  |--LIST SUBQUERY
  |  `--SCAN TABLE d1
  `--LIST SUBQUERY
     `--SCAN TABLE d1
  |--SEARCH d2 USING INDEX d2ab (a=? AND b=?)
  |--LIST SUBQUERY xxxxxx
  |  `--SCAN d1
  `--LIST SUBQUERY xxxxxx
     `--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/rowvalue5.test.

42
43
44
45
46
47
48
49



50
51
52
53
54
55
56
42
43
44
45
46
47
48

49
50
51
52
53
54
55
56
57
58







-
+
+
+







      set OP(lt) <
      set OP(ge) >=
      set OP(match) MATCH
      set OP(like) LIKE
      set OP(glob) GLOB
      set OP(regexp) REGEXP

      set clist [lindex $args 0]
      set hdl [lindex $args 0]
      set clist [$hdl constraints]

      set ret [list]
      set elist [list]
      set i 0
      foreach c $clist {
        array set C $c
        if {$C(usable)} {
          lappend ret omit $i

Changes to test/rowvalue7.test.

51
52
53
54
55
56
57










58
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68







+
+
+
+
+
+
+
+
+
+

  UPDATE t1 SET (c,d) = (SELECT x,y,z FROM t2 WHERE w=a);
} {1 {2 columns assigned 3 values}}

do_catchsql_test 2.2 {
  UPDATE t1 SET (b,c,d) = (SELECT x,y FROM t2 WHERE w=a);
} {1 {3 columns assigned 2 values}}

# 2019-08-26
# ticket https://www.sqlite.org/src/info/78acc9d40f0786e8
#
do_catchsql_test 3.0 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a,b);
  INSERT INTO t1 VALUES(1,2);
  UPDATE t1 SET (a,a,a,b)=(SELECT 99,100);
} {1 {4 columns assigned 2 values}}

finish_test

Changes to test/rowvalue9.test.

293
294
295
296
297
298
299

300











301


293
294
295
296
297
298
299
300

301
302
303
304
305
306
307
308
309
310
311
312
313
314







+
-
+
+
+
+
+
+
+
+
+
+
+

+
+

do_execsql_test 7.3 {
  SELECT * FROM g2 WHERE (x, y) IN (
    SELECT a, b FROM g1 ORDER BY 1, 2 LIMIT 10
  );
} { 1 4 1 5 }

#-------------------------------------------------------------------------

#
do_execsql_test 8.1 {
  CREATE TABLE t1(a ,b FLOAT);
  CREATE INDEX t1x1 ON t1(a,b,a,a,a,a,a,a,a,a,a,b);
}

do_catchsql_test 8.2 {
  SELECT a FROM t1 NATURAL JOIN t1 WHERE (a,b)> (SELECT 2 IN (SELECT 2,2), 2);
} {1 {sub-select returns 2 columns - expected 1}}


finish_test


Added test/rowvalueA.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2021 July 6
#
# 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 rowvalueA

do_execsql_test 1.0 {
  SELECT (1, 2) IN ( (3, 4), (5, 6), (1, 3) );
} {0}

do_execsql_test 1.1 {
  SELECT (1, 2) IN ( (3, 4), (5, 6), (1, 2) );
} {1}

do_execsql_test 1.2 {
  SELECT (1, 2) IN ( (3, 2) );
} {0}

do_execsql_test 1.3 {
  SELECT (1, 2) IN ( (1, 2) );
} {1}

do_execsql_test 1.4 {
  SELECT (1, 2) IN ( );
} {0}

do_execsql_test 1.5 {
  SELECT (1, 2) NOT IN ( );
} {1}

for {set ii 0} {$ii < 2000} {incr ii} {
  lappend L "($ii, $ii)"
}

do_execsql_test 1.6.1 "
  SELECT (400,400) IN ( [join $L ,] )
" 1

do_execsql_test 1.6.2 "
  SELECT (1500,1500) IN ( [join $L ,] )
" 1

do_execsql_test 1.6.2 "
  SELECT (1500,1499) IN ( [join $L ,] )
" 0

#-------------------------------------------------------------------------

do_catchsql_test 2.0 {
  SELECT (1, 2) IN ( (1, 2), (3, 4, 5), (5, 6) )
} {1 {IN(...) element has 3 terms - expected 2}}

do_catchsql_test 2.1 {
  SELECT (1, 2) IN ( (1, 2), 4, (5, 6) )
} {1 {IN(...) element has 1 term - expected 2}}

do_catchsql_test 2.2 {
  SELECT (1, 2, 3) IN ( (1, 2), (3, 4), (5, 6) )
} {1 {IN(...) element has 2 terms - expected 3}}

do_catchsql_test 2.3 {
  SELECT 2 IN ( (1, 2), (3, 4), (5, 6) )
} {1 {row value misused}}

finish_test

Changes to test/rowvaluefault.test.

63
64
65
66
67
68
69


















70
71
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


do_faultsim_test 6 -faults oom* -body {
  execsql { 
    SELECT fou FROM xyz 
    WHERE (one, two, thr) BETWEEN ('B', 'B', 'B') AND ('C', 'C', 'C') }
} -test {
  faultsim_test_result {0 {2 3}} 
}

do_faultsim_test 7 -faults oom* -body {
  execsql { 
    SELECT fou FROM xyz 
    WHERE (one, two, thr) IN ( ('a','b','c'), ('A','A','A'), (1,2,3) );
  }
} -test {
  faultsim_test_result {0 1}
}

do_faultsim_test 8 -faults oom* -body {
  execsql { 
    SELECT fou FROM xyz 
    WHERE (two, one) IN ( ('a','b','c'), ('A','A','A'), (1,2,3) );
  }
} -test {
  faultsim_test_result {1 {IN(...) element has 3 terms - expected 2}}
}

finish_test

Added test/rowvaluevtab.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2018 October 14
#
# 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
set ::testprefix rowvaluevtab

ifcapable !vtab {
  finish_test
  return
}

register_echo_module db

do_execsql_test 1.0 {
  CREATE TABLE t1(a, b, c);
  CREATE INDEX t1b ON t1(b);
  INSERT INTO t1 VALUES('one', 1, 1);
  INSERT INTO t1 VALUES('two', 1, 2);
  INSERT INTO t1 VALUES('three', 1, 3);
  INSERT INTO t1 VALUES('four', 2, 1);
  INSERT INTO t1 VALUES('five', 2, 2);
  INSERT INTO t1 VALUES('six', 2, 3);
  INSERT INTO t1 VALUES('seven', 3, 1);
  INSERT INTO t1 VALUES('eight', 3, 2);
  INSERT INTO t1 VALUES('nine', 3, 3);

  WITH s(i) AS (
    SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<10000
  ) INSERT INTO t1 SELECT NULL, NULL, NULL FROM s;
  CREATE VIRTUAL TABLE e1 USING echo(t1);
}

proc do_vfilter4_test {tn sql expected} {
  set res [list]
  db eval "explain $sql" {
    if {$opcode=="VFilter"} {
      lappend res $p4
    }
  }
  uplevel [list do_test $tn [list set {} $res] [list {*}$expected]]
}

do_execsql_test 1.1 {
  SELECT a FROM e1 WHERE (b, c) = (2, 2)
} {five}
do_vfilter4_test 1.1f {
  SELECT a FROM e1 WHERE (b, c) = (?, ?)
} {{SELECT rowid, a, b, c FROM 't1' WHERE b = ?}}

do_execsql_test 1.2 {
  SELECT a FROM e1 WHERE (b, c) > (2, 2)
} {six seven eight nine}
do_vfilter4_test 1.2f {
  SELECT a FROM e1 WHERE (b, c) > (2, 2)
} {
  {SELECT rowid, a, b, c FROM 't1' WHERE b >= ?}
}

do_execsql_test 1.3 {
  SELECT a FROM e1 WHERE (b, c) >= (2, 2)
} {five six seven eight nine}
do_vfilter4_test 1.3f {
  SELECT a FROM e1 WHERE (b, c) >= (2, 2)
} {
  {SELECT rowid, a, b, c FROM 't1' WHERE b >= ?}
}

do_execsql_test 1.3 {
  SELECT a FROM e1 WHERE (b, c) BETWEEN (1, 2) AND (2, 3)
} {two three four five six}
do_vfilter4_test 1.3f {
  SELECT a FROM e1 WHERE (b, c) BETWEEN (1, 2) AND (2, 3)
} {
  {SELECT rowid, a, b, c FROM 't1' WHERE b >= ? AND b <= ?}
}

do_execsql_test 1.4 {
  SELECT a FROM e1 WHERE (b, c) IN ( VALUES(2, 2) )
} {five}
do_vfilter4_test 1.4f {
  SELECT a FROM e1 WHERE (b, c) IN ( VALUES(2, 2) )
} {{SELECT rowid, a, b, c FROM 't1' WHERE b = ?}}

finish_test

Changes to test/savepoint.test.

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
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







+
+













+







#
# $Id: savepoint.test,v 1.13 2009/07/18 08:30:45 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/malloc_common.tcl

forcedelete test2.db

#----------------------------------------------------------------------
# The following tests - savepoint-1.* - test that the SAVEPOINT, RELEASE
# and ROLLBACK TO comands are correctly parsed, and that the auto-commit
# flag is correctly set and unset as a result.
#
do_test savepoint-1.1 {
  wal_set_journal_mode
  execsql {
    SAVEPOINT sp1;
    RELEASE sp1;
  }
} {}
wal_check_journal_mode savepoint-1.1
do_test savepoint-1.2 {
  execsql {
    SAVEPOINT sp1;
    ROLLBACK TO sp1;
  }
} {}
do_test savepoint-1.3 {
801
802
803
804
805
806
807

808

809
810
811
812
813
814
815
804
805
806
807
808
809
810
811

812
813
814
815
816
817
818
819







+
-
+







    CREATE TABLE t3(a, b, UNIQUE(a, b));
    ROLLBACK TO one;
  }
} {}
integrity_check savepoint-11.7
do_test savepoint-11.8 {
  execsql { ROLLBACK }
  db close
  execsql { PRAGMA wal_checkpoint }
  sqlite3 db test.db
  file size test.db
} {8192}

do_test savepoint-11.9 {
  execsql {
    DROP TABLE IF EXISTS t1;
    DROP TABLE IF EXISTS t2;

Changes to test/savepoint6.test.

11
12
13
14
15
16
17




18
19
20
21
22
23
24
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28







+
+
+
+







#
# $Id: savepoint6.test,v 1.4 2009/06/05 17:09:12 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

proc sql {zSql} {
  if {0 && $::debug_op} {
    puts stderr "$zSql ;"
    flush stderr
  }
  uplevel db eval [list $zSql]
  #puts stderr "$zSql ;"
}

set DATABASE_SCHEMA {
    PRAGMA auto_vacuum = incremental;
    CREATE TABLE t1(x, y);
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
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







+





+

















+















+












+







#   rollback  NAME
#   release   NAME
#
#   insert_rows XVALUES
#   delete_rows XVALUES
#
proc savepoint {zName} {
  if {$::debug_op} { puts stderr "savepoint $zName" ; flush stderr }
  catch { sql "SAVEPOINT $zName" }
  lappend ::lSavepoint [list $zName [array get ::aEntry]]
}

proc rollback {zName} {
  if {$::debug_op} { puts stderr "rollback $zName" ; flush stderr }
  catch { sql "ROLLBACK TO $zName" }
  for {set i [expr {[llength $::lSavepoint]-1}]} {$i>=0} {incr i -1} {
    set zSavepoint [lindex $::lSavepoint $i 0]
    if {$zSavepoint eq $zName} {
      unset -nocomplain ::aEntry
      array set ::aEntry [lindex $::lSavepoint $i 1]


      if {$i+1 < [llength $::lSavepoint]} {
        set ::lSavepoint [lreplace $::lSavepoint [expr $i+1] end]
      }
      break
    }
  }
}

proc release {zName} {
  if {$::debug_op} { puts stderr "release $zName" ; flush stderr }
  catch { sql "RELEASE $zName" }
  for {set i [expr {[llength $::lSavepoint]-1}]} {$i>=0} {incr i -1} {
    set zSavepoint [lindex $::lSavepoint $i 0]
    if {$zSavepoint eq $zName} {
      set ::lSavepoint [lreplace $::lSavepoint $i end]
      break
    }
  }

  if {[llength $::lSavepoint] == 0} {
    #puts stderr "-- End of transaction!!!!!!!!!!!!!"
  }
}

proc insert_rows {lX} {
  if {$::debug_op} { puts stderr "insert_rows $lX" ; flush stderr }
  foreach x $lX {
    set y [x_to_y $x]

    # Update database [db]
    sql "INSERT OR REPLACE INTO t1 VALUES($x, '$y')"

    # Update the Tcl database.
    set ::aEntry($x) $y
  }
}

proc delete_rows {lX} {
  if {$::debug_op} { puts stderr "delete_rows $lX" ; flush stderr }
  foreach x $lX {
    # Update database [db]
    sql "DELETE FROM t1 WHERE x = $x"

    # Update the Tcl database.
    unset -nocomplain ::aEntry($x)
  }
159
160
161
162
163
164
165





166
167
168
169
170
171
172
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186







+
+
+
+
+







  set ret [list]
  for {set i 0} {$i<$nRes} {incr i} {
    lappend ret [expr int(rand()*$nRange)]
  }
  return $ret
} 
#-------------------------------------------------------------------------

set ::debug_op 0
proc debug_ops {} {
  set ::debug_op 1
}

proc database_op {} {
  set i [expr int(rand()*2)] 
  if {$i==0} {
    insert_rows [random_integers 100 1000]
  }
  if {$i==1} {
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
195
196
197
198
199
200
201



202
203
204
205
206
207
208







-
-
-







proc savepoint_op {} {
  set names {one two three four five}
  set cmds  {savepoint savepoint savepoint savepoint release rollback}

  set C [lindex $cmds [expr int(rand()*6)]]
  set N [lindex $names [expr int(rand()*5)]]

  #puts stderr "   $C $N ;  "
  #flush stderr

  $C $N
  return ok
}

expr srand(0)

############################################################################

Changes to test/scanstatus.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
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
32
33
34
35
36
37
38
39

40
41
42
43
44
45
46
47
48
49


50
51
52
53
54
55
56
57
58


59
60
61
62
63
64
65
66
67
68


69
70
71
72
73
74
75
76
77
78


79
80
81
82
83
84
85
86
87
88


89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109

110
111
112
113
114
115
116
117

118
119
120
121
122
123
124
125

126
127
128
129
130
131
132
133

134
135
136
137
138
139
140
141

142
143
144
145
146
147
148
149
150
151
152
153
154

155
156
157
158
159
160
161
162

163
164
165
166
167
168
169
170

171
172
173
174
175
176
177
178

179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198

199
200

201
202
203
204
205
206
207
208

209
210

211
212
213
214
215
216
217
218
219

220
221

222
223
224
225
226
227
228
229

230
231
232
233
234
235
236
237

238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258

259
260
261
262
263
264
265
266
267
268
269
270

271
272

273
274
275
276
277
278
279
280







+
-
+
+








-
-
+
+







-
-
+
+








-
-
+
+








-
-
+
+








-
-
+
+



















-
+







-
+







-
+







-
+







-
+












-
+







-
+







-
+







-
+



















-
+

-
+







-
+

-
+








-
+

-
+







-
+







-
+




















-
+











-
+

-
+







proc do_scanstatus_test {tn res} {
  set stmt [db version -last-stmt-ptr]
  set idx 0
  set ret [list]
  while {1} {
    set r [sqlite3_stmt_scanstatus $stmt $idx]
    if {[llength $r]==0} break
    foreach v {nLoop nVisit nEst zName zExplain} {
    lappend ret {*}$r
      lappend ret $v [dict get $r $v]
    }
    incr idx
  }

  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 
# not FK action processing.
#
do_execsql_test 4.0 {
  CREATE TABLE t1(a, b, c);
  CREATE TABLE t2(x PRIMARY KEY, y, z);
  CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
    SELECT * FROM t2 WHERE x BETWEEN 20 AND 40;
  END;
  WITH d(x) AS (SELECT 1 UNION ALL SELECT x+1 AS n FROM d WHERE n<=100)
  INSERT INTO t2 SELECT x, x*2, x*3 FROM d;
}

do_execsql_test    4.1.1 { INSERT INTO t1 VALUES(1, 2, 3); }
do_scanstatus_test 4.1.2 { }
do_scanstatus_test 4.1.2 {}

do_execsql_test 4.2 {
  CREATE TABLE p1(x PRIMARY KEY);
  INSERT INTO p1 VALUES(1), (2), (3), (4);
  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} {
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
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







-
-
+
+

-
+







-
+




-
+





-
+






-
-
+
+





-
-
+
+

-
+






-
-
+
+





-
+

-
+







  ANALYZE;
}

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}
  nLoop 1 nVisit 10 nEst 10.0 zName t1
  zExplain {SCAN ii}
  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
  `--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}
  nLoop 1 nVisit 10 nEst 10.0 zName t1
  zExplain {SCAN t1}
  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
390
391
392
393
394
395
396

397
398
399
400
401
402







-
+





    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

Added test/scanstatus2.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022 December 5
#
# 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
set testprefix scanstatus2

ifcapable !scanstatus {
  finish_test
  return
}

do_execsql_test 1.0 {
  CREATE TABLE t1(a, b);
  CREATE TABLE t2(x, y);
  INSERT INTO t1 VALUES(1, 2);
  INSERT INTO t1 VALUES(3, 4);
  INSERT INTO t2 VALUES('a', 'b');
  INSERT INTO t2 VALUES('c', 'd');
  INSERT INTO t2 VALUES('e', 'f');
}

proc do_zexplain_test {v2 tn sql res} {
  db eval $sql
  set stmt [db version -last-stmt-ptr]
  set idx 0
  set ret [list]

  set cmd sqlite3_stmt_scanstatus
  set f [list]
  if {$v2} { lappend f complex }

  while {1} {
    set r [sqlite3_stmt_scanstatus -flags $f $stmt $idx]
    if {[llength $r]==0} break
    lappend ret [dict get $r zExplain]
    incr idx
  }
  uplevel [list do_test $tn [list set {} $ret] [list {*}$res]]
}

proc get_cycles {stmt} {
  set r [sqlite3_stmt_scanstatus $stmt -1]
  dict get $r nCycle
}

proc foreach_scan {varname stmt body} {
  upvar $varname var

  for {set ii 0} {1} {incr ii} {
    set r [sqlite3_stmt_scanstatus -flags complex $stmt $ii]
    if {[llength $r]==0} break
    array set var $r
    uplevel $body
  }
}

proc get_eqp_graph {stmt iPar nIndent} {
  set res ""
  foreach_scan A $stmt {
    if {$A(iParentId)==$iPar} {
      set txt $A(zExplain)
      if {$A(nCycle)>=0} {
        append txt " (nCycle=$A(nCycle))"
      }
      append res "[string repeat - $nIndent]$txt\n"
      append res [get_eqp_graph $stmt $A(iSelectId) [expr $nIndent+2]]
    }
  }
  set res
}

proc get_graph {stmt} {
  set nCycle [get_cycles $stmt]
  set res "QUERY (nCycle=$nCycle)\n"
  append res [get_eqp_graph $stmt 0 2]
}

proc do_graph_test {tn sql res} {
  db eval $sql
  set stmt [db version -last-stmt-ptr]
  set graph [string trim [get_graph $stmt]]

  set graph [regsub -all {nCycle=[0-9]+} $graph nCycle=nnn]
  uplevel [list do_test $tn [list set {} $graph] [string trim $res]]
}

proc puts_graph {sql} {
  db eval $sql
  set stmt [db version -last-stmt-ptr]
  puts [string trim [get_graph $stmt]]
}


do_zexplain_test 0 1.1 {
  SELECT (SELECT a FROM t1 WHERE b=x) FROM t2 WHERE y=2
} {
  {SCAN t2}
  {SCAN t1}
}
do_zexplain_test 1 1.2 {
  SELECT (SELECT a FROM t1 WHERE b=x) FROM t2 WHERE y=2
} {
  {SCAN t2}
  {CORRELATED SCALAR SUBQUERY 1}
  {SCAN t1}
}

do_graph_test 1.3 {
  SELECT (SELECT a FROM t1 WHERE b=x) FROM t2 WHERE y=2
} {
QUERY (nCycle=nnn)
--SCAN t2 (nCycle=nnn)
--CORRELATED SCALAR SUBQUERY 1 (nCycle=nnn)
----SCAN t1 (nCycle=nnn)
}

do_graph_test 1.4 {
  WITH v2(x,y) AS MATERIALIZED (
    SELECT x,y FROM t2
  )
  SELECT * FROM t1, v2 ORDER BY y;
} {
QUERY (nCycle=nnn)
--MATERIALIZE v2 (nCycle=nnn)
----SCAN t2 (nCycle=nnn)
--SCAN v2 (nCycle=nnn)
--SCAN t1 (nCycle=nnn)
--USE TEMP B-TREE FOR ORDER BY (nCycle=nnn)
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.0 {
  CREATE VIRTUAL TABLE ft USING fts5(a);
  INSERT INTO ft VALUES('abc');
  INSERT INTO ft VALUES('def');
  INSERT INTO ft VALUES('ghi');
}

do_graph_test 2.1 {
  SELECT * FROM ft('def')
} {
QUERY (nCycle=nnn)
--SCAN ft VIRTUAL TABLE INDEX 0:M1 (nCycle=nnn)
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 3.0 {
  CREATE TABLE x1(a, b);
  CREATE TABLE x2(c, d);

  WITH s(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<1000)
  INSERT INTO x1 SELECT i, i FROM s;
  INSERT INTO x2 SELECT a, b FROM x1;
}

do_graph_test 2.1 {
  SELECT * FROM x1, x2 WHERE c=+a;
} {
QUERY (nCycle=nnn)
--SCAN x1 (nCycle=nnn)
--CREATE AUTOMATIC INDEX ON x2(c, d) (nCycle=nnn)
--SEARCH x2 USING AUTOMATIC COVERING INDEX (c=?) (nCycle=nnn)
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 4.0 {
  CREATE TABLE rt1 (id INTEGER PRIMARY KEY, x1, x2);
  CREATE TABLE rt2 (id, x1, x2);
}

do_graph_test 4.1 {
  SELECT * FROM rt1, rt2 WHERE rt1.id%2 AND rt2.x1=rt1.x1;
} {
QUERY (nCycle=nnn)
--SCAN rt1 (nCycle=nnn)
--CREATE AUTOMATIC INDEX ON rt2(x1, id, x2) (nCycle=nnn)
--SEARCH rt2 USING AUTOMATIC COVERING INDEX (x1=?) (nCycle=nnn)
}

do_graph_test 4.2 {
  SELECT rt2.id FROM rt1, rt2 WHERE rt1.id%2 AND rt2.x1=rt1.x1;
} {
QUERY (nCycle=nnn)
--SCAN rt1 (nCycle=nnn)
--CREATE AUTOMATIC INDEX ON rt2(x1, id) (nCycle=nnn)
--SEARCH rt2 USING AUTOMATIC COVERING INDEX (x1=?) (nCycle=nnn)
}

do_graph_test 4.3 {
  SELECT rt2.id FROM rt1, rt2 WHERE rt1.id%2 AND (rt2.x1+1)=(rt1.x1+1);
} {
QUERY (nCycle=nnn)
--SCAN rt1 (nCycle=nnn)
--SCAN rt2 (nCycle=nnn)
}

do_graph_test 4.4 {
  SELECT rt2.id FROM rt1, rt2 WHERE rt1.id%2 AND rt2.x1=(rt1.x1+1) AND rt2.id>5;
} {
QUERY (nCycle=nnn)
--SCAN rt1 (nCycle=nnn)
--CREATE AUTOMATIC INDEX ON rt2(x1, id) WHERE <expr> (nCycle=nnn)
--SEARCH rt2 USING AUTOMATIC PARTIAL COVERING INDEX (x1=?) (nCycle=nnn)
}

do_graph_test 4.5 {
  SELECT v1.cnt FROM rt1, (
    SELECT count(*) AS cnt, rt2.x1 AS x1 FROM rt2 GROUP BY x1
  ) AS v1 WHERE rt1.x1=v1.x1
} {
QUERY (nCycle=nnn)
--CO-ROUTINE v1
----SCAN rt2 (nCycle=nnn)
----USE TEMP B-TREE FOR GROUP BY
--SCAN rt1 (nCycle=nnn)
--CREATE AUTOMATIC INDEX ON v1(x1, cnt) (nCycle=nnn)
--SEARCH v1 USING AUTOMATIC COVERING INDEX (x1=?) (nCycle=nnn)
}

finish_test


Changes to test/schema.test.

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
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







-
+
+
+


+


-
+


-
+


+
+
+
+
+
+
+
+
+







  do_test schema-7.4 {
    sqlite3_finalize $::STMT
  } {SQLITE_SCHEMA}
}

#---------------------------------------------------------------------
# Tests 8.1 and 8.2 check that prepared statements are invalidated when
# the authorization function is set.
# the authorization function is set to a non-null function.  Tests 8.11
# and 8.12 verify that no invalidations occur when the authorizer is
# cleared.
#
ifcapable auth {
  proc noop_auth {args} {return SQLITE_OK}
  do_test schema-8.1 {
    set ::STMT [sqlite3_prepare $::DB {SELECT * FROM sqlite_master} -1 TAIL]
    db auth {}
    db auth noop_auth
    sqlite3_step $::STMT
  } {SQLITE_ERROR}
  do_test schema-8.3 {
  do_test schema-8.2 {
    sqlite3_finalize $::STMT
  } {SQLITE_SCHEMA}
  do_test schema-8.11 {
    set ::STMT [sqlite3_prepare $::DB {SELECT * FROM sqlite_master} -1 TAIL]
    db auth {}
    sqlite3_step $::STMT
  } {SQLITE_ROW}
  do_test schema-8.12 {
    sqlite3_finalize $::STMT
  } {SQLITE_OK}

}

#---------------------------------------------------------------------
# schema-9.1: Test that if a table is dropped by one database connection, 
#             other database connections are aware of the schema change.
# schema-9.2: Test that if a view is dropped by one database connection,
#             other database connections are aware of the schema change.

Changes to test/schema3.test.

11
12
13
14
15
16
17






18
19
20
21
22
23
24
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30







+
+
+
+
+
+







# This file implements regression tests for SQLite library.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/malloc_common.tcl
source $testdir/lock_common.tcl

# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
ifcapable !altertable {
  finish_test
  return
}

# This block tests that if one client modifies the database schema, a
# second client updates its internal cache of the database schema before
# executing any queries. Specifically, it does not return a "no such column"
# or "no such table" error if the table or column in question does exist
# but was added after the second client loaded its cache of the database
# schema.

Added test/seekscan1.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022 October 7
#
# 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 seekscan1

do_execsql_test 1.0 {
  CREATE TABLE t1(a TEXT, b INT, c INT NOT NULL, PRIMARY KEY(a,b,c));
  WITH RECURSIVE c(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c WHERE x<1997)
    INSERT INTO t1(a,b,c) SELECT printf('xyz%d',x/10),x/6,x FROM c;
  INSERT INTO t1 VALUES('abc',234,6);
  INSERT INTO t1 VALUES('abc',345,7);
  ANALYZE;
}

do_execsql_test 1.1 {
  SELECT a,b,c FROM t1 
  WHERE b IN (234, 345) AND c BETWEEN 6 AND 6.5 AND a='abc' 
  ORDER BY a, b;
} {
  abc 234 6
}

do_execsql_test 1.2 {
  SELECT a,b,c FROM t1 
  WHERE b IN (234, 345) AND c BETWEEN 6 AND 7 AND a='abc' 
  ORDER BY a, b;
} {
  abc 234 6
  abc 345 7
}

do_execsql_test 1.3 {
  SELECT a,b,c FROM t1 
  WHERE b IN (234, 345) AND c >=6 AND a='abc' 
  ORDER BY a, b;
} {
  abc 234 6
  abc 345 7
}

do_execsql_test 1.4 {
  SELECT a,b,c FROM t1 
  WHERE b IN (234, 345) AND c<=7 AND a='abc' 
  ORDER BY a, b;
} {
  abc 234 6
  abc 345 7
}


finish_test

Changes to test/select1.test.

541
542
543
544
545
546
547
548

549
550

551
552
553
554
555

556
557
558
559
560
561
562
541
542
543
544
545
546
547

548
549

550
551
552
553
554

555
556
557
558
559
560
561
562







-
+

-
+




-
+







     SELECT * FROM test1 a, test1 b LIMIT 1
  }
} {a.f1 11 a.f2 22 b.f1 11 b.f2 22}
do_test select1-6.9.7 {
  set x [execsql2 {
     SELECT * FROM test1 a, (select 5, 6) LIMIT 1
  }]
  regsub -all {subquery_[0-9a-fA-F_]+} $x {subquery} x
  regsub -all {subquery-\d+} $x {subquery-0} x
  set x
} {a.f1 11 a.f2 22 subquery.5 5 subquery.6 6}
} {a.f1 11 a.f2 22 (subquery-0).5 5 (subquery-0).6 6}
do_test select1-6.9.8 {
  set x [execsql2 {
     SELECT * FROM test1 a, (select 5 AS x, 6 AS y) AS b LIMIT 1
  }]
  regsub -all {subquery_[0-9a-fA-F]+_} $x {subquery} x
  regsub -all {subquery-\d+} $x {subquery-0} x
  set x
} {a.f1 11 a.f2 22 b.x 5 b.y 6}
do_test select1-6.9.9 {
  execsql2 {
     SELECT a.f1, b.f2 FROM test1 a, test1 b LIMIT 1
  }
} {test1.f1 11 test1.f2 22}
1076
1077
1078
1079
1080
1081
1082
1083


































































































































1084
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







-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  catchsql {SELECT 1 FROM (SELECT *)}
} {1 {no tables specified}}

# 2015-04-17:  assertion fix.
do_catchsql_test select1-16.2 {
  SELECT 1 FROM sqlite_master LIMIT 1,#1;
} {1 {near "#1": syntax error}}
  

# 2019-01-16 Chromium bug 922312
# Sorting with a LIMIT clause using SRT_EphemTab and SRT_Table
#
do_execsql_test select1-17.1 {
  DROP TABLE IF EXISTS t1;
  DROP TABLE IF EXISTS t2;
  CREATE TABLE t1(x);   INSERT INTO t1 VALUES(1);
  CREATE TABLE t2(y,z); INSERT INTO t2 VALUES(2,3);
  CREATE INDEX t2y ON t2(y);
  SELECT * FROM t1,(SELECT * FROM t2 WHERE y=2 ORDER BY y,z);
} {1 2 3}
do_execsql_test select1-17.2 {
  SELECT * FROM t1,(SELECT * FROM t2 WHERE y=2 ORDER BY y,z LIMIT 4);
} {1 2 3}
do_execsql_test select1-17.3 {
  SELECT * FROM t1,(SELECT * FROM t2 WHERE y=2
         UNION ALL SELECT * FROM t2 WHERE y=3 ORDER BY y,z LIMIT 4);
} {1 2 3}

# 2019-07-24 Ticket https://sqlite.org/src/tktview/c52b09c7f38903b1311
#
do_execsql_test select1-18.1 {
  DROP TABLE IF EXISTS t1;
  DROP TABLE IF EXISTS t2;
  CREATE TABLE t1(c);
  CREATE TABLE t2(x PRIMARY KEY, y);
  INSERT INTO t1(c) VALUES(123);
  INSERT INTO t2(x) VALUES(123);
  SELECT x FROM t2, t1 WHERE x BETWEEN c AND null OR x AND
  x IN ((SELECT x FROM (SELECT x FROM t2, t1 
  WHERE x BETWEEN (SELECT x FROM (SELECT x COLLATE rtrim 
  FROM t2, t1 WHERE x BETWEEN c AND null
  OR x AND x IN (c)), t1 WHERE x BETWEEN c AND null
  OR x AND x IN (c)) AND null
  OR NOT EXISTS(SELECT -4.81 FROM t1, t2 WHERE x BETWEEN c AND null
  OR x AND x IN ((SELECT x FROM (SELECT x FROM t2, t1
  WHERE x BETWEEN (SELECT x FROM (SELECT x BETWEEN c AND null
  OR x AND x IN (c)), t1 WHERE x BETWEEN c AND null
  OR x AND x IN (c)) AND null
  OR x AND x IN (c)), t1 WHERE x BETWEEN c AND null
  OR x AND x IN (c)))) AND x IN (c)
  ), t1 WHERE x BETWEEN c AND null
  OR x AND x IN (c)));
} {}
do_execsql_test select1-18.2 {
  DROP TABLE IF EXISTS t1;
  DROP TABLE IF EXISTS t2;
  CREATE TABLE t1(c);
  CREATE TABLE t2(x PRIMARY KEY, y);
  INSERT INTO t1(c) VALUES(123);
  INSERT INTO t2(x) VALUES(123);
  SELECT x FROM t2, t1 WHERE x BETWEEN c AND (c+1) OR x AND
  x IN ((SELECT x FROM (SELECT x FROM t2, t1 
  WHERE x BETWEEN (SELECT x FROM (SELECT x COLLATE rtrim 
  FROM t2, t1 WHERE x BETWEEN c AND (c+1)
  OR x AND x IN (c)), t1 WHERE x BETWEEN c AND (c+1)
  OR x AND x IN (c)) AND (c+1)
  OR NOT EXISTS(SELECT -4.81 FROM t1, t2 WHERE x BETWEEN c AND (c+1)
  OR x AND x IN ((SELECT x FROM (SELECT x FROM t2, t1
  WHERE x BETWEEN (SELECT x FROM (SELECT x BETWEEN c AND (c+1)
  OR x AND x IN (c)), t1 WHERE x BETWEEN c AND (c+1)
  OR x AND x IN (c)) AND (c+1)
  OR x AND x IN (c)), t1 WHERE x BETWEEN c AND (c+1)
  OR x AND x IN (c)))) AND x IN (c)
  ), t1 WHERE x BETWEEN c AND (c+1)
  OR x AND x IN (c)));
} {123}
do_execsql_test select1-18.3 {
  SELECT 1 FROM t1 WHERE (
    SELECT 2 FROM t2 WHERE (
      SELECT 3 FROM (
        SELECT x FROM t2 WHERE x=c OR x=(SELECT x FROM (VALUES(0)))
      ) WHERE x>c OR x=c
    )
  );
} {1}
do_execsql_test select1-18.4 {
  SELECT 1 FROM t1, t2 WHERE (
    SELECT 3 FROM (
      SELECT x FROM t2 WHERE x=c OR x=(SELECT x FROM (VALUES(0)))
    ) WHERE x>c OR x=c
  );
} {1}

# 2019-12-17 gramfuzz find
#
do_execsql_test select1-19.10 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(x);
} {}
do_catchsql_test select1-19.20 {
  INSERT INTO t1
    SELECT 1,2,3,4,5,6,7
    UNION ALL SELECT 1,2,3,4,5,6,7
    ORDER BY 1;
} {1 {table t1 has 1 columns but 7 values were supplied}}
do_catchsql_test select1-19.21 {
  INSERT INTO t1
    SELECT 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
    UNION ALL SELECT 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
    ORDER BY 1;
} {1 {table t1 has 1 columns but 15 values were supplied}}

# 2020-01-01 Found by Yongheng's fuzzer
#
reset_db
do_execsql_test select1-20.10 {
  CREATE TABLE t1 (
    a INTEGER PRIMARY KEY,
    b AS('Y') UNIQUE
  );
  INSERT INTO t1(a) VALUES (10);
  SELECT * FROM t1 JOIN t1 USING(a,b)
   WHERE ((SELECT t1.a FROM t1 AS x GROUP BY b) AND b=0)
      OR a = 10;
} {10 Y}
do_execsql_test select1-20.20 {
  SELECT ifnull(a, max((SELECT 123))), count(a) FROM t1 ;
} {10 1}

# 2020-10-02 dbsqlfuzz find
reset_db
do_execsql_test select1-21.1 {
  CREATE TABLE t1(a IMTEGES PRIMARY KEY,R);
  CREATE TABLE t2(x UNIQUE);
  CREATE VIEW v1a(z,y) AS SELECT x IS NULL, x FROM t2;
  SELECT a,(+a)b,(+a)b,(+a)b,NOT EXISTS(SELECT null FROM t2),CASE z WHEN 487 THEN 992 WHEN 391 THEN 203 WHEN 10 THEN '?k<D Q' END,'' FROM t1 LEFT JOIN v1a ON z=b;
} {}

finish_test

Changes to test/select3.test.

114
115
116
117
118
119
120
121
122
123
124
125












126
127
128
129
130
131
132
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







-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+







do_test select3-2.14 {
  catchsql {
    SELECT log, count(*) FROM t1 GROUP BY;
  }
} {1 {near ";": syntax error}}

# Cannot have a HAVING without a GROUP BY
#
do_test select3-3.1 {
  set v [catch {execsql {SELECT log, count(*) FROM t1 HAVING log>=4}} msg]
  lappend v $msg
} {1 {a GROUP BY clause is required before HAVING}}
# 
# Update: As of 3.39.0, you can.
#
do_execsql_test select3-3.1 {
  SELECT log, count(*) FROM t1 HAVING log>=4
} {}
do_execsql_test select3-3.2 {
  SELECT count(*) FROM t1 HAVING log>=4
} {}
do_execsql_test select3-3.3 {
  SELECT count(*) FROM t1 HAVING log!=400
} {31}

# Toss in some HAVING clauses
#
do_test select3-4.1 {
  execsql {SELECT log, count(*) FROM t1 GROUP BY log HAVING log>=4 ORDER BY log}
} {4 8 5 15}
do_test select3-4.2 {
256
257
258
259
260
261
262
263





































































































































































264

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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
  }
} {real}
do_test select3-8.2 {
  execsql {
    SELECT typeof(sum(a3)) FROM a GROUP BY a1;
  }
} {real}

# 2019-05-09 ticket https://www.sqlite.org/src/tktview/6c1d3febc00b22d457c7
#
unset -nocomplain x
foreach {id x} {
  100 127
  101 128
  102 -127
  103 -128
  104 -129
  110 32767
  111 32768
  112 -32767
  113 -32768
  114 -32769
  120 2147483647
  121 2147483648
  122 -2147483647
  123 -2147483648
  124 -2147483649
  130 140737488355327
  131 140737488355328
  132 -140737488355327
  133 -140737488355328
  134 -140737488355329
  140 9223372036854775807
  141 -9223372036854775807
  142 -9223372036854775808
  143 9223372036854775806
  144 9223372036854775805
  145 -9223372036854775806
  146 -9223372036854775805

} {
  set x [expr {$x+0}]
  do_execsql_test select3-8.$id {
     DROP TABLE IF EXISTS t1;
     CREATE TABLE t1 (c0, c1 REAL PRIMARY KEY);
     INSERT INTO t1(c0, c1) VALUES (0, $x), (0, 0);
     UPDATE t1 SET c0 = NULL;
     UPDATE OR REPLACE t1 SET c1 = 1;
     SELECT DISTINCT * FROM t1 WHERE (t1.c0 IS NULL);
     PRAGMA integrity_check;
  } {{} 1.0 ok}
}

# 2020-03-10 ticket e0c2ad1aa8a9c691
reset_db
do_execsql_test select3-9.100 {
  CREATE TABLE t0(c0 REAL, c1 REAL GENERATED ALWAYS AS (c0));
  INSERT INTO t0(c0) VALUES (1);
  SELECT * FROM t0 GROUP BY c0;
} {1.0 1.0}

reset_db
do_execsql_test select3.10.100 {
  CREATE TABLE t1(a, b);
  CREATE TABLE t2(c, d);
  SELECT max(t1.a), 
         (SELECT 'xyz' FROM (SELECT * FROM t2 WHERE 0) WHERE t1.b=1) 
  FROM t1;
} {{} {}}

#-------------------------------------------------------------------------
# dbsqlfuzz crash-8e17857db2c5a9294c975123ac807156a6559f13.txt
# Associated with the flatten-left-join branch circa 2022-06-23.
#
foreach {tn sql} {
  1 {
    CREATE TABLE t1(a TEXT);
    CREATE TABLE t2(x INT);
    CREATE INDEX t2x ON t2(x);
    INSERT INTO t1 VALUES('abc');
  }
  2 {
    CREATE TABLE t1(a TEXT);
    CREATE TABLE t2(x INT);
    INSERT INTO t1 VALUES('abc');
  }
  3 {
    CREATE TABLE t1(a TEXT);
    CREATE TABLE t2(x INT);
    INSERT INTO t1 VALUES('abc');
    PRAGMA automatic_index=OFF;
  }
} {
  reset_db
  do_execsql_test select3-11.$tn.1 $sql 
  do_execsql_test select3.11.$tn.2 {
    SELECT max(a), val FROM t1 LEFT JOIN (
        SELECT 'constant' AS val FROM t2 WHERE x=1234
    )
  } {abc {}}
  do_execsql_test select3.11.$tn.3 {
    INSERT INTO t2 VALUES(123);
    SELECT max(a), val FROM t1 LEFT JOIN (
        SELECT 'constant' AS val FROM t2 WHERE x=1234
    )
  } {abc {}}
  do_execsql_test select3.11.$tn.4 {
    INSERT INTO t2 VALUES(1234);
    SELECT max(a), val FROM t1 LEFT JOIN (
        SELECT 'constant' AS val FROM t2 WHERE x=1234
    )
  } {abc constant}
}

reset_db
do_execsql_test 12.0 {
  CREATE TABLE t1(a);
  CREATE TABLE t2(x);
}
do_execsql_test 12.1 {
  SELECT count(x), m FROM t1 LEFT JOIN (SELECT x, 59 AS m FROM t2) GROUP BY a;
}
do_execsql_test 12.2 {
  INSERT INTO t1 VALUES(1), (1), (2), (3);
  SELECT count(x), m FROM t1 LEFT JOIN (SELECT x, 59 AS m FROM t2) GROUP BY a;
} {
  0 {}
  0 {}
  0 {}
}
do_execsql_test 12.3 {
  INSERT INTO t2 VALUES(45);
  SELECT count(x), m FROM t1 LEFT JOIN (SELECT x, 59 AS m FROM t2) GROUP BY a;
} {
  2 59
  1 59
  1 59
}
do_execsql_test 12.4 {
  INSERT INTO t2 VALUES(210);
  SELECT count(x), m FROM t1 LEFT JOIN (SELECT x, 59 AS m FROM t2) GROUP BY a;
} {
  4 59
  2 59
  2 59
}
do_execsql_test 12.5 {
  INSERT INTO t2 VALUES(NULL);
  SELECT count(x), m FROM t1 LEFT JOIN (SELECT x, 59 AS m FROM t2) GROUP BY a;
} {
  4 59
  2 59
  2 59
}
do_execsql_test 12.6 {
  DELETE FROM t2;
  DELETE FROM t1;
  INSERT INTO t1 VALUES('value');
  INSERT INTO t2 VALUES('hello');
} {}
do_execsql_test 12.7 {
  SELECT group_concat(x), m FROM t1 
    LEFT JOIN (SELECT x, 59 AS m FROM t2) GROUP BY a;
} {
  hello 59
}
do_execsql_test 12.8 {
  SELECT group_concat(x), m, n FROM t1 
    LEFT JOIN (SELECT x, 59 AS m, 60 AS n FROM t2) GROUP BY a;
} {
  hello 59 60
}

finish_test

Changes to test/select4.test.

1001
1002
1003
1004
1005
1006
1007



1008































1009
1010
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







+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


    SELECT a AS x, sum(b) AS y FROM t1 GROUP BY a LIMIT 3
    UNION
    SELECT 98 AS x, 99 AS y
  ) AS w WHERE y>=20
  ORDER BY +x;
} {1 {LIMIT clause should come after UNION not before}}

# 2020-04-03 ticket 51166be0159fd2ce from Yong Heng.
# Adverse interaction between the constant propagation and push-down
# optimizations.

#
reset_db
do_execsql_test select4-18.1 {
  CREATE VIEW v0(v0) AS WITH v0 AS(SELECT 0 v0) SELECT(SELECT min(v0) OVER()) FROM v0 GROUP BY v0;
  SELECT *FROM v0 v1 JOIN v0 USING(v0) WHERE datetime(v0) = (v0.v0)AND v0 = 10;
} {}
do_execsql_test select4-18.2 {
  CREATE VIEW t1(aa) AS
     WITH t2(bb) AS (SELECT 123)
     SELECT (SELECT min(bb) OVER()) FROM t2 GROUP BY bb;
  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/select6.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 SELECT statements that contain
# subqueries in their FROM clause.
#
# $Id: select6.test,v 1.29 2009/01/09 01:12:28 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Omit this whole file if the library is build without subquery support.
ifcapable !subquery {
  finish_test
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
165
166
167
168
169
170
171

172
173
174
175
176
177
178







-







do_test select6-3.2 {
  execsql {
    SELECT * FROM
      (SELECT a.q, a.p, b.r
       FROM (SELECT count(*) as p , b as q FROM t2 GROUP BY q) AS a,
            (SELECT max(a) as r, b as s FROM t2 GROUP BY s) as b
       WHERE a.q=b.s ORDER BY a.q)
    ORDER BY "a.q"
  }
} {1 1 1 2 2 3 3 4 7 4 8 15 5 5 20}
do_test select6-3.3 {
  execsql {
    SELECT a,b,a+b FROM (SELECT avg(x) as 'a', avg(y) as 'b' FROM t1)
  }
} {10.5 3.7 14.2}
609
610
611
612
613
614
615


616















617
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







+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  DROP TABLE t2;
  CREATE TABLE t1(x);
  CREATE TABLE t2(y, z);
  SELECT ( SELECT y FROM t2 WHERE z = cnt )
    FROM ( SELECT count(*) AS cnt FROM t1 );
} {{}}

# 2019-05-29 ticket https://www.sqlite.org/src/info/c41afac34f15781f
# A LIMIT clause in a subquery is incorrectly applied to a subquery.

#
do_execsql_test 12.100 {
  DROP TABLE t1;
  DROP TABLE t2;
  CREATE TABLE t1(a);
  INSERT INTO t1 VALUES(1);
  INSERT INTO t1 VALUES(2);
  CREATE TABLE t2(b);
  INSERT INTO t2 VALUES(3);
  SELECT * FROM (
    SELECT * FROM (SELECT * FROM t1 LIMIT 1)
    UNION ALL
    SELECT * from t2);
} {1 3}

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()
1441
1442
1443
1444
1445
1446
1447
1448

1449




























































1450
1441
1442
1443
1444
1445
1446
1447
1448
1449

1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510








+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  DROP TABLE IF EXISTS t1;
  DROP TABLE IF EXISTS t2;
  CREATE TABLE t1(a INTEGER);
  CREATE TABLE t2(b TEXT);
  INSERT INTO t2(b) VALUES('12345');
  SELECT * FROM (SELECT a FROM t1 UNION SELECT b FROM t2) WHERE a=a;
} {12345}

# 2020-06-15 ticket 8f157e8010b22af0

#
reset_db
do_execsql_test 7.1 {
  CREATE TABLE t1(c1);     INSERT INTO t1 VALUES(12),(123),(1234),(NULL),('abc');
  CREATE TABLE t2(c2);     INSERT INTO t2 VALUES(44),(55),(123);
  CREATE TABLE t3(c3,c4);  INSERT INTO t3 VALUES(66,1),(123,2),(77,3);
  CREATE VIEW t4 AS SELECT c3 FROM t3;
  CREATE VIEW t5 AS SELECT c3 FROM t3 ORDER BY c4;
}
do_execsql_test 7.2 {
  SELECT * FROM t1, t2 WHERE c1=(SELECT 123 INTERSECT SELECT c2 FROM t4) AND c1=123;
} {123 123}
do_execsql_test 7.3 {
  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))
} {}

#-------------------------------------------------------------------------
# dbsqlfuzz a34f455c91ad75a0cf8cd9476841903f42930a7a
#
reset_db
do_execsql_test 9.0 {
  CREATE TABLE t1(a COLLATE nocase);
  CREATE TABLE t2(b COLLATE nocase);

  INSERT INTO t1 VALUES('ABC');
  INSERT INTO t2 VALUES('abc');
}

do_execsql_test 9.1 {
  SELECT a FROM t1 INTERSECT SELECT b FROM t2;
} {ABC}

do_execsql_test 9.2 {
  SELECT * FROM (
      SELECT a FROM t1 INTERSECT SELECT b FROM t2
  ) WHERE a||'' = 'ABC';
} {ABC}



finish_test

Changes to test/selectC.test.

257
258
259
260
261
262
263
264

265
266
267


268
269
270
257
258
259
260
261
262
263

264
265


266
267
268
269
270







-
+

-
-
+
+



  SELECT * FROM x1, x4
} {
  a 21 a 22 a 23 a 24 a 25 a 302 a 303 a 301
  b 21 b 22 b 23 b 24 b 25 b 302 b 303 b 301
}

do_execsql_test 5.3 {
  SELECT * FROM x1, (SELECT b FROM vvv UNION ALL SELECT c from x3);
  SELECT * FROM x1, (SELECT b FROM vvv UNION ALL SELECT c from x3) ORDER BY 1,2;
} {
  a 21 a 22 a 23 a 24 a 25 a 302 a 303 a 301
  b 21 b 22 b 23 b 24 b 25 b 302 b 303 b 301
  a 21 a 22 a 23 a 24 a 25 a 301 a 302 a 303
  b 21 b 22 b 23 b 24 b 25 b 301 b 302 b 303
}

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/sessionfuzz.c.

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
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







+
-
+
+
















+
+
+


















+







  "  sessionfuzz run FILE ...   -- Run against fuzzed changeset FILE\n"
  "  sessionfuzz run SQLAR ...  -- Run against all files in the SQL Archive\n"
;

#include <stdio.h>
#include <string.h>
#include <assert.h>
#ifndef OMIT_ZLIB
#include "zlib.h"
#include <zlib.h>
#endif

/*
** Implementation of the "sqlar_uncompress(X,SZ)" SQL function
**
** Parameter SZ is interpreted as an integer. If it is less than or
** equal to zero, then this function returns a copy of X. Or, if
** SZ is equal to the size of X when interpreted as a blob, also
** return a copy of X. Otherwise, decompress blob X using zlib
** utility function uncompress() and return the results (another
** blob).
*/
static void sqlarUncompressFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
#ifdef OMIT_ZLIB
  sqlite3_result_value(context, argv[0]);
#else
  uLong nData;
  uLongf sz;

  assert( argc==2 );
  sz = sqlite3_value_int(argv[1]);

  if( sz<=0 || sz==(nData = sqlite3_value_bytes(argv[0])) ){
    sqlite3_result_value(context, argv[0]);
  }else{
    const Bytef *pData= sqlite3_value_blob(argv[0]);
    Bytef *pOut = sqlite3_malloc(sz);
    if( Z_OK!=uncompress(pOut, &sz, pData, nData) ){
      sqlite3_result_error(context, "error in uncompress()", -1);
    }else{
      sqlite3_result_blob(context, pOut, sz, SQLITE_TRANSIENT);
    }
    sqlite3_free(pOut);
  }
#endif
}


/* Run a chunk of SQL.  If any errors happen, print an error message
** and exit.
*/
static void runSql(sqlite3 *db, const char *zSql){
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
832
833
834
835
836
837
838

839
840
841
842
843
844
845







-







static int conflictCall(
  void *NotUsed,
  int eConflict,
  sqlite3_changeset_iter *p
){
  (void)NotUsed;
  (void)p;
  printf("Conflict %d\n", eConflict);
  return SQLITE_CHANGESET_OMIT;
}

/*
** Reset the database file
*/
static void db_reset(sqlite3 *db){

Changes to test/shared.test.

156
157
158
159
160
161
162
163

164
165
166
167

168
169
170
171
172
173
174
156
157
158
159
160
161
162

163


164

165
166
167
168
169
170
171
172







-
+
-
-

-
+







  # Commit the connection 1 transaction.
  execsql {
    COMMIT;
  }
} {}

do_test shared-$av.2.1 {
  # Open connection db3 to the database. Use a different path to the same
  # Open connection db3 to the database.
  # file so that db3 does *not* share the same pager cache as db and db2
  # (there should be two open file handles).
  if {$::tcl_platform(platform)=="unix"} {
    sqlite3 db3 ./test.db
    sqlite3 db3 "file:test.db?cache=private" -uri 1
  } else {
    sqlite3 db3 TEST.DB
  }
  set ::sqlite_open_file_count
  expr $sqlite_open_file_count-($extrafds_prelock+$extrafds_postlock)
} {2}
do_test shared-$av.2.2 {
796
797
798
799
800
801
802
803

804
805
806
807
808
809
810
794
795
796
797
798
799
800

801
802
803
804
805
806
807
808







-
+







    INSERT INTO de VALUES('Pataya', 30000);
  } db2
} {}
do_test shared-$av.10.3 {
  # An external connection should be able to read the database, but not
  # prepare a write operation.
  if {$::tcl_platform(platform)=="unix"} {
    sqlite3 db3 ./test.db
    sqlite3 db3 "file:test.db?cache=private" -uri 1
  } else {
    sqlite3 db3 TEST.DB
  }
  execsql {
    SELECT * FROM ab;
  } db3
  catchsql {

Changes to test/shared3.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
102
103
104
105
106
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







-
-
-
-
+
+
+
+
-
+

-
+
+



















-
+








# The cache-size should now be 10 pages. However at one point there was
# a bug that caused the cache size to return to the default value when
# a second connection was opened on the shared-cache (as happened in
# test case shared3-2.3 above). The goal of the following tests is to
# ensure that the cache-size really is 10 pages.
#
if {$::tcl_platform(platform)=="unix"} {
  set alternative_name ./test.db
} else {
  set alternative_name TEST.DB
#if {$::tcl_platform(platform)=="unix"} {
#  set alternative_name ./test.db
#} else {
#  set alternative_name TEST.DB
}
#}
do_test shared3-2.6 {
  sqlite3 db3 $alternative_name
  #sqlite3 db3 $alternative_name
  sqlite3 db3 "file:./test.db?cache=private" -uri 1
  catchsql {select count(*) from sqlite_master} db3
} {0 1}
do_test shared3-2.7 {
  execsql {
    BEGIN;
    INSERT INTO t1 VALUES(10, randomblob(5000))
  } db1
  catchsql {select count(*) from sqlite_master} db3
} {0 1}
do_test shared3-2.8 {
  db3 close
  execsql {
    INSERT INTO t1 VALUES(10, randomblob(10000))
  } db1

  # If the pager-cache is really still limited to 10 pages, then the INSERT
  # statement above should have caused the pager to grab an exclusive lock
  # on the database file so that the cache could be spilled.
  #
  catch { sqlite3 db3 $alternative_name }
  catch { sqlite3 db3 "file:./test.db?cache=private" -uri 1 }
  catchsql {select count(*) from sqlite_master} db3
} {1 {database is locked}}

db1 close
db2 close
db3 close

Changes to test/shared9.test.

15
16
17
18
19
20
21
22

23
24
25
26
27
28
29
15
16
17
18
19
20
21

22
23
24
25
26
27
28
29







-
+







#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
set testprefix shared9

ifcapable !view||!trigger {
ifcapable !view||!trigger||!shared_cache {
  finish_test
  return
}

db close
set enable_shared_cache [sqlite3_enable_shared_cache 1]

Changes to test/sharedA.test.

14
15
16
17
18
19
20





21
22
23
24
25
26
27
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32







+
+
+
+
+









set testdir [file dirname $argv0]
source $testdir/tester.tcl
if {[run_thread_tests]==0} { finish_test ; return }
db close
set ::testprefix sharedA

ifcapable !shared_cache {
  finish_test
  return
}

if {[atomic_batch_write test.db]} {
  finish_test
  return
}

set ::enable_shared_cache [sqlite3_enable_shared_cache 1]

Changes to test/sharedB.test.

19
20
21
22
23
24
25





26
27
28
29
30
31
32
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37







+
+
+
+
+









set testdir [file dirname $argv0]
source $testdir/tester.tcl
if {[run_thread_tests]==0} { finish_test ; return }
db close
set ::testprefix sharedB

ifcapable !shared_cache {
  finish_test
  return
}

set ::enable_shared_cache [sqlite3_enable_shared_cache 1]

#-------------------------------------------------------------------------
#
do_test 1.1 {
  sqlite3 db1 test.db

Changes to test/shell1.test.

14
15
16
17
18
19
20


21
22
23
24

25
26
27
28
29
30
31
14
15
16
17
18
19
20
21
22
23
24
25

26
27
28
29
30
31
32
33







+
+



-
+







#

# Test plan:
#
#   shell1-1.*: Basic command line option handling.
#   shell1-2.*: Basic "dot" command token parsing.
#   shell1-3.*: Basic test that "dot" command can be called.
#   shell1-{4-8}.*: Test various "dot" commands's functionality.
#   shell1-9.*: Basic test that "dot" commands and SQL intermix ok.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set CLI [test_find_cli]
set CLI [test_cli_invocation]
db close
forcedelete test.db test.db-journal test.db-wal
sqlite3 db test.db

#----------------------------------------------------------------------------
# Test cases shell1-1.*: Basic command line option handling.
#
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
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







-
+












+
+
+
+








-
+







do_test shell1-1.1.2 {
  catchcmd "test.db \"select+3\" \"select+4\"" ""
} {0 {3
4}}
# error on extra options
do_test shell1-1.1.3 {
  catchcmd "test.db FOO test.db BAD" ".quit"
} {1 {Error: near "FOO": syntax error}}
} {/1 .Error: in prepare, near "FOO": syntax error*/}

# -help
do_test shell1-1.2.1 {
  set res [catchcmd "-help test.db" ""]
  set rc [lindex $res 0]
  list $rc \
       [regexp {Usage} $res] \
       [regexp {\-init} $res] \
       [regexp {\-version} $res]
} {1 1 1 1}

# -init filename       read/process named file
forcedelete FOO
set out [open FOO w]
puts $out ""
close $out
do_test shell1-1.3.1 {
  catchcmd "-init FOO test.db" ""
} {0 {}}
do_test shell1-1.3.2 {
  catchcmd "-init FOO test.db .quit BAD" ""
} {0 {}}
do_test shell1-1.3.3 {
  catchcmd "-init FOO test.db BAD .quit" ""
} {1 {Error: near "BAD": syntax error}}
} {/1 .Error: in prepare, near "BAD": syntax error*/}

# -echo                print commands before execution
do_test shell1-1.4.1 {
  catchcmd "-echo test.db" ""
} {0 {}}

# -[no]header          turn headers on or off
195
196
197
198
199
200
201
202

203
204
205

206
207
208
209
210
211
212
201
202
203
204
205
206
207

208
209
210

211
212
213
214
215
216
217
218







-
+


-
+







  catchcmd "test.db" ".explain \"OFF"
} {0 {}}
do_test shell1-2.2.4 {
  catchcmd "test.db" ".explain \'OFF"
} {0 {}}
do_test shell1-2.2.5 {
  catchcmd "test.db" ".mode \"insert FOO"
} {1 {Error: mode should be one of: ascii column csv html insert line list quote tabs tcl}}
} {1 {Error: mode should be one of: ascii box column csv html insert json line list markdown qbox quote table tabs tcl}}
do_test shell1-2.2.6 {
  catchcmd "test.db" ".mode \'insert FOO"
} {1 {Error: mode should be one of: ascii column csv html insert line list quote tabs tcl}}
} {1 {Error: mode should be one of: ascii box column csv html insert json line list markdown qbox quote table tabs tcl}}

# check multiple tokens, and quoted tokens
do_test shell1-2.3.1 {
  catchcmd "test.db" ".explain 1"
} {0 {}}
do_test shell1-2.3.2 {
  catchcmd "test.db" ".explain on"
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
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







-
+
















+







do_test shell1-2.3.7 {
  catchcmd "test.db" ".\'explain\' \'OFF\'"
} {0 {}}

# check quoted args are unquoted
do_test shell1-2.4.1 {
  catchcmd "test.db" ".mode FOO"
} {1 {Error: mode should be one of: ascii column csv html insert line list quote tabs tcl}}
} {1 {Error: mode should be one of: ascii box column csv html insert json line list markdown qbox quote table tabs tcl}}
do_test shell1-2.4.2 {
  catchcmd "test.db" ".mode csv"
} {0 {}}
do_test shell1-2.4.2 {
  catchcmd "test.db" ".mode \"csv\""
} {0 {}}


#----------------------------------------------------------------------------
# Test cases shell1-3.*: Basic test that "dot" command can be called.
#

# .backup ?DB? FILE      Backup DB (default "main") to FILE
do_test shell1-3.1.1 {
  catchcmd "test.db" ".backup"
} {1 {missing FILENAME argument on .backup}}
forcedelete FOO
do_test shell1-3.1.2 {
  catchcmd "test.db" ".backup FOO"
} {0 {}}
do_test shell1-3.1.3 {
  catchcmd "test.db" ".backup FOO BAR"
} {1 {Error: unknown database FOO}}
do_test shell1-3.1.4 {
293
294
295
296
297
298
299

300
301
302
303




304
305
306
307
308
309
310
300
301
302
303
304
305
306
307




308
309
310
311
312
313
314
315
316
317
318







+
-
-
-
-
+
+
+
+







       [regexp {COMMIT;} $res]
} {1 1}
do_test shell1-3.4.2 {
  set res [catchcmd "test.db" ".dump FOO"]
  list [regexp {BEGIN TRANSACTION;} $res] \
       [regexp {COMMIT;} $res]
} {1 1}
# The .dump command now accepts multiple arguments
do_test shell1-3.4.3 {
  # too many arguments
  catchcmd "test.db" ".dump FOO BAD"
} {1 {Usage: .dump ?--preserve-rowids? ?--newlines? ?LIKE-PATTERN?}}
#do_test shell1-3.4.3 {
#  # too many arguments
#  catchcmd "test.db" ".dump FOO BAD"
#} {1 {Usage: .dump ?--preserve-rowids? ?--newlines? ?LIKE-PATTERN?}}

# .echo ON|OFF           Turn command echo on or off
do_test shell1-3.5.1 {
  catchcmd "test.db" ".echo"
} {1 {Usage: .echo on|off}}
do_test shell1-3.5.2 {
  catchcmd "test.db" ".echo ON"
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
392
393
394
395
396
397
398

399
400
401

402



403
404
405

406
407
408
409
410
411
412
413







-
+


-
+
-
-
-



-
+







       [regexp {.quit} $res] \
       [regexp {.show} $res]
} {1 1 1}

# .import FILE TABLE     Import data from FILE into TABLE
do_test shell1-3.11.1 {
  catchcmd "test.db" ".import"
} {1 {Usage: .import FILE TABLE}}
} {/1 .ERROR: missing FILE argument.*/}
do_test shell1-3.11.2 {
  catchcmd "test.db" ".import FOO"
} {1 {Usage: .import FILE TABLE}}
} {/1 .ERROR: missing TABLE argument.*/}
#do_test shell1-3.11.2 {
#  catchcmd "test.db" ".import FOO BAR"
#} {1 {Error: no such table: BAR}}
do_test shell1-3.11.3 {
  # too many arguments
  catchcmd "test.db" ".import FOO BAR BAD"
} {1 {Usage: .import FILE TABLE}}
} {/1 .ERROR: extra argument: "BAD".*./}

# .indexes ?TABLE?       Show names of all indexes
#                          If TABLE specified, only show indexes for tables
#                          matching LIKE pattern TABLE.
do_test shell1-3.12.1 {
  catchcmd "test.db" ".indexes"
} {0 {}}
428
429
430
431
432
433
434
435

436
437
438
439
440
441
442
433
434
435
436
437
438
439

440
441
442
443
444
445
446
447







-
+







#                          tabs     Tab-separated values
#                          tcl      TCL list elements
do_test shell1-3.13.1 {
  catchcmd "test.db" ".mode"
} {0 {current output mode: list}}
do_test shell1-3.13.2 {
  catchcmd "test.db" ".mode FOO"
} {1 {Error: mode should be one of: ascii column csv html insert line list quote tabs tcl}}
} {1 {Error: mode should be one of: ascii box column csv html insert json line list markdown qbox quote table tabs tcl}}
do_test shell1-3.13.3 {
  catchcmd "test.db" ".mode csv"
} {0 {}}
do_test shell1-3.13.4 {
  catchcmd "test.db" ".mode column"
} {0 {}}
do_test shell1-3.13.5 {
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
463
464
465
466
467
468
469











470
471
472
473
474
475
476







-
-
-
-
-
-
-
-
-
-
-







  catchcmd "test.db" ".mode tcl"
} {0 {}}
do_test shell1-3.13.11 {
  # extra arguments ignored
  catchcmd "test.db" ".mode tcl BAD"
} {0 {}}

# don't allow partial mode type matches
do_test shell1-3.13.12 {
  catchcmd "test.db" ".mode l"
} {1 {Error: mode should be one of: ascii column csv html insert line list quote tabs tcl}}
do_test shell1-3.13.13 {
  catchcmd "test.db" ".mode li"
} {1 {Error: mode should be one of: ascii column csv html insert line list quote tabs tcl}}
do_test shell1-3.13.14 {
  catchcmd "test.db" ".mode lin"
} {0 {}}

# .nullvalue STRING      Print STRING in place of NULL values
do_test shell1-3.14.1 {
  catchcmd "test.db" ".nullvalue"
} {1 {Usage: .nullvalue STRING}}
do_test shell1-3.14.2 {
  catchcmd "test.db" ".nullvalue FOO"
} {0 {}}
491
492
493
494
495
496
497
498








499
500
501
502
503
504
505
506
507








508
509
510
511
512
513
514
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







-
+
+
+
+
+
+
+
+








-
+
+
+
+
+
+
+
+







} {0 {}}
do_test shell1-3.15.2 {
  catchcmd "test.db" ".output FOO"
} {0 {}}
do_test shell1-3.15.3 {
  # too many arguments
  catchcmd "test.db" ".output FOO BAD"
} {1 {Usage: .output [-e|-x|FILE]}}
} {1 {ERROR: extra parameter: "BAD".  Usage:
.output ?FILE?           Send output to FILE or stdout if FILE is omitted
   If FILE begins with '|' then open it as a pipe.
   Options:
     --bom                 Prefix output with a UTF8 byte-order mark
     -e                    Send output to the system text editor
     -x                    Send output as CSV to a spreadsheet
child process exited abnormally}}

# .output stdout         Send output to the screen
do_test shell1-3.16.1 {
  catchcmd "test.db" ".output stdout"
} {0 {}}
do_test shell1-3.16.2 {
  # too many arguments
  catchcmd "test.db" ".output stdout BAD"
} {1 {Usage: .output [-e|-x|FILE]}}
} {1 {ERROR: extra parameter: "BAD".  Usage:
.output ?FILE?           Send output to FILE or stdout if FILE is omitted
   If FILE begins with '|' then open it as a pipe.
   Options:
     --bom                 Prefix output with a UTF8 byte-order mark
     -e                    Send output to the system text editor
     -x                    Send output as CSV to a spreadsheet
child process exited abnormally}}

# .prompt MAIN CONTINUE  Replace the standard prompts
do_test shell1-3.17.1 {
  catchcmd "test.db" ".prompt"
} {0 {}}
do_test shell1-3.17.2 {
  catchcmd "test.db" ".prompt FOO"
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
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







-
+













+
-
+







} {0 {}}
do_test shell1-3.21.2 {
  catchcmd "test.db" ".schema FOO"
} {0 {}}
do_test shell1-3.21.3 {
  # too many arguments
  catchcmd "test.db" ".schema FOO BAD"
} {1 {Usage: .schema ?--indent? ?LIKE-PATTERN?}}
} {1 {Usage: .schema ?--indent? ?--nosys? ?LIKE-PATTERN?}}

do_test shell1-3.21.4 {
  catchcmd "test.db" {
     CREATE TABLE t1(x);
     CREATE VIEW v2 AS SELECT x+1 AS y FROM t1;
     CREATE VIEW v1 AS SELECT y+1 FROM v2;
  }
  catchcmd "test.db" ".schema"
} {0 {CREATE TABLE t1(x);
CREATE VIEW v2 AS SELECT x+1 AS y FROM t1
/* v2(y) */;
CREATE VIEW v1 AS SELECT y+1 FROM v2
/* v1("y+1") */;}}

db eval {DROP VIEW v1; DROP VIEW v2; DROP TABLE t1;}
  catch {db eval {DROP VIEW v1; DROP VIEW v2; DROP TABLE t1;}}
}

# .separator STRING  Change column separator used by output and .import
do_test shell1-3.22.1 {
  catchcmd "test.db" ".separator"
} {1 {Usage: .separator COL ?ROW?}}
do_test shell1-3.22.2 {
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
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







-
+









-
+







  # too many arguments
  catchcmd "test.db" ".show BAD"
} {1 {Usage: .show}}

# .stats ON|OFF          Turn stats on or off
#do_test shell1-3.23b.1 {
#  catchcmd "test.db" ".stats"
#} {1 {Usage: .stats on|off}}
#} {1 {Usage: .stats on|off|stmt|vmstep}}
do_test shell1-3.23b.2 {
  catchcmd "test.db" ".stats ON"
} {0 {}}
do_test shell1-3.23b.3 {
  catchcmd "test.db" ".stats OFF"
} {0 {}}
do_test shell1-3.23b.4 {
  # too many arguments
  catchcmd "test.db" ".stats OFF BAD"
} {1 {Usage: .stats ?on|off?}}
} {1 {Usage: .stats ?on|off|stmt|vmstep?}}

# Ticket 7be932dfa60a8a6b3b26bcf7623ec46e0a403ddb 2018-06-07
# Adverse interaction between .stats and .eqp
#
do_test shell1-3.23b.5 {
  catchcmd "test.db" [string map {"\n    " "\n"} {
    CREATE TEMP TABLE t1(x);
693
694
695
696
697
698
699
700

701
702
703
704

705
706
707
708
709
710
711
702
703
704
705
706
707
708

709
710
711
712

713
714
715
716
717
718
719
720







-
+



-
+







  # this should be treated the same as a '0' width for col 1 and 2
} {0 {}}
do_test shell1-3.26.4 {
  catchcmd "test.db" ".width 1 1"
  # this should be treated the same as a '1' width for col 1 and 2
} {0 {}}
do_test shell1-3.26.5 {
  catchcmd "test.db" ".mode column\n.width 10 -10\nSELECT 'abcdefg', 123456;"
  catchcmd "test.db" ".mode column\n.header off\n.width 10 -10\nSELECT 'abcdefg', 123456;"
  # this should be treated the same as a '1' width for col 1 and 2
} {0 {abcdefg         123456}}
do_test shell1-3.26.6 {
  catchcmd "test.db" ".mode column\n.width -10 10\nSELECT 'abcdefg', 123456;"
  catchcmd "test.db" ".mode column\n.header off\n.width -10 10\nSELECT 'abcdefg', 123456;"
  # this should be treated the same as a '1' width for col 1 and 2
} {0 {   abcdefg  123456    }}


# .timer ON|OFF          Turn the CPU timer measurement on or off
do_test shell1-3.27.1 {
  catchcmd "test.db" ".timer"
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
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







+
+
+
+
+
+


















+
+







} {0 {"\""
"["
"]"
"\\{"
"\\}"
";"
"$"} 7}

# Test the output of ".mode quote"
#
do_test shell1-4.7 {
  catchcmd test.db ".mode quote\nselect x'0123456789ABCDEF';"
} {0 X'0123456789abcdef'}

# Test using arbitrary byte data with the shell via standard input/output.
#
do_test shell1-5.0 {
  #
  # NOTE: Skip NUL byte because it appears to be incompatible with command
  #       shell argument parsing.
  #
  for {set i 1} {$i < 256} {incr i} {
    #
    # NOTE: Due to how the Tcl [exec] command works (i.e. where it treats
    #       command channels opened for it as textual ones), the carriage
    #       return character (and on Windows, the end-of-file character)
    #       cannot be used here.
    #
    if {$i==0x0D || ($tcl_platform(platform)=="windows" && $i==0x1A)} {
      continue
    }
    # Tcl 8.7 maps 0x80 through 0x9f into valid UTF8.  So skip those tests.
    if {$i>=0x80 && $i<=0x9f} continue
    if {$i>=0xE0 && $tcl_platform(os)=="OpenBSD"}  continue
    if {$i>=0xE0 && $i<=0xEF && $tcl_platform(os)=="Linux"}  continue
    set hex [format %02X $i]
    set char [subst \\x$hex]; set oldChar $char
    set escapes [list]
    if {$tcl_platform(platform)=="windows"} {
      #
1147
1148
1149
1150
1151
1152
1153
1154




































































































1155
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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

} {0 {CREATE TABLE WWW (x TEXT PRIMARY KEY);
CREATE TABLE ___ (x TEXT PRIMARY KEY);}}
do_test shell1-7.1.7 {
  catchcmd "test.db" ".schema \\\\_\\\\_\\\\_"
} {0 {CREATE TABLE ___ (x TEXT PRIMARY KEY);}}

}

# Test case for the ieee754 and decimal extensions in the shell.
# See the "floatingpoint.html" file in the documentation for more
# information.
#
do_test shell1-8.1 {
  catchcmd ":memory:" {
    -- The pow2 table will hold all the necessary powers of two.
    CREATE TABLE pow2(x INTEGER PRIMARY KEY, v TEXT);
    WITH RECURSIVE c(x,v) AS (
      VALUES(0,'1')
      UNION ALL
      SELECT x+1, decimal_mul(v,'2') FROM c WHERE x+1<=971
    ) INSERT INTO pow2(x,v) SELECT x, v FROM c;
    WITH RECURSIVE c(x,v) AS (
      VALUES(-1,'0.5')
      UNION ALL
      SELECT x-1, decimal_mul(v,'0.5') FROM c WHERE x-1>=-1075
    ) INSERT INTO pow2(x,v) SELECT x, v FROM c;
    
    -- This query finds the decimal representation of each value in the "c" table.
    WITH c(n) AS (VALUES(47.49))
                     ----XXXXX----------- Replace with whatever you want
    SELECT decimal_mul(ieee754_mantissa(c.n),pow2.v)
      FROM pow2, c WHERE pow2.x=ieee754_exponent(c.n);
  }
} {0 47.49000000000000198951966012828052043914794921875}
do_test shell1-8.2 {
  catchcmd :memory: {
.mode box
SELECT ieee754(47.49) AS x;
  }
} {0 {┌───────────────────────────────┐
│               x               │
├───────────────────────────────┤
│ ieee754(6683623321994527,-47) │
└───────────────────────────────┘}}
do_test shell1-8.3 {
  catchcmd ":memory: --box" {
    select ieee754(6683623321994527,-47) as x;
  }
} {0 {┌───────┐
│   x   │
├───────┤
│ 47.49 │
└───────┘}}
do_test shell1-8.4 {
  catchcmd ":memory: --table" {SELECT ieee754_mantissa(47.49) AS M, ieee754_exponent(47.49) AS E;}
} {0 {+------------------+-----+
|        M         |  E  |
+------------------+-----+
| 6683623321994527 | -47 |
+------------------+-----+}}
do_test shell1-8.5 {
  catchcmd ":memory: --box" {
create table t(a text, b int);
insert into t values ('too long for one line', 1), ('shorter', NULL);
.header on
.width 10 10
.nullvalue NADA
select * from t;}
} {0 {┌────────────┬────────────┐
│     a      │     b      │
├────────────┼────────────┤
│ too long f │ 1          │
│ or one lin │            │
│ e          │            │
├────────────┼────────────┤
│ shorter    │ NADA       │
└────────────┴────────────┘}}

#----------------------------------------------------------------------------
# Test cases shell1-9.*: Basic test that "dot" commands and SQL intermix ok.
#
do_test shell1-9.1 {
  catchcmd :memory: {
.mode csv
/*
x */ select 1,2; --x
 -- .nada
;
.mode csv
--x
select 2,1; select 3,4;
}
} {0 {1,2
2,1
3,4}}

#----------------------------------------------------------------------------
# Test cases shell1-10.*: Test that certain static extensions are there.
#
do_test shell1-10.1 {
  catchcmd :memory: {
.mode list
.header off
select base64(base64(cast('digity-doo' as blob))),
 base85(base85(cast('digity-doo' as blob)));
}
} {0 digity-doo|digity-doo}

finish_test

Changes to test/shell2.test.

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
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







-
+
-

+
-
+
















-
+







  set fexist [file exist foo.db]
  list $rc $fexist
} {{0 {}} 1}

# Shell silently ignores extra parameters.
# Ticket [f5cb008a65].
do_test shell2-1.2.1 {
  set rc [catch { eval exec $CLI \":memory:\" \"select+3\" \"select+4\" } msg]
  catchcmdex {:memory: "select+3" "select+4"}
  list $rc $msg
} {0 {3
4
4}}
}}

# Test a problem reported on the mailing list. The shell was at one point
# returning the generic SQLITE_ERROR message ("SQL error or missing database")
# instead of the "too many levels..." message in the test below.
#
do_test shell2-1.3 {
  catchcmd "-batch test.db" {
    PRAGMA recursive_triggers = ON;
    CREATE TABLE t5(a PRIMARY KEY, b, c);
    INSERT INTO t5 VALUES(1, 2, 3);
    CREATE TRIGGER au_tble AFTER UPDATE ON t5 BEGIN
      UPDATE OR IGNORE t5 SET a = new.a, c = 10;
    END;

    UPDATE OR REPLACE t5 SET a = 4 WHERE a = 1;
  }
} {1 {Error: near line 9: too many levels of trigger recursion}}
} {1 {Runtime error near line 9: too many levels of trigger recursion}}



# Shell not echoing all commands with echo on.
# Ticket [eb620916be].

# Test with echo off
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
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







-
+












-
+

-

-
+
-
-
+


-









-
+














-
+


-


-
+
-
-
+



-





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

1}}

# Test with echo on using dot command and 
# multiple commands per line.
# NB. whitespace is important
do_test shell2-1.4.5 {
  forcedelete foo.db
  catchcmd "foo.db" {.echo ON
  catchcmdex "foo.db" {.echo ON
CREATE TABLE foo1(a);
INSERT INTO foo1(a) VALUES(1);
CREATE TABLE foo2(b);
INSERT INTO foo2(b) VALUES(1);
SELECT * FROM foo1; SELECT * FROM foo2;
INSERT INTO foo1(a) VALUES(2); INSERT INTO foo2(b) VALUES(2);
SELECT * FROM foo1; SELECT * FROM foo2;
}
} {0 {CREATE TABLE foo1(a);
INSERT INTO foo1(a) VALUES(1);
CREATE TABLE foo2(b);
INSERT INTO foo2(b) VALUES(1);
SELECT * FROM foo1;
SELECT * FROM foo1; SELECT * FROM foo2;
1
SELECT * FROM foo2;
1
INSERT INTO foo1(a) VALUES(2);
INSERT INTO foo1(a) VALUES(2); INSERT INTO foo2(b) VALUES(2);
INSERT INTO foo2(b) VALUES(2);
SELECT * FROM foo1;
SELECT * FROM foo1; SELECT * FROM foo2;
1
2
SELECT * FROM foo2;
1
2
}}

# Test with echo on and headers on using dot command and 
# multiple commands per line.
# NB. whitespace is important
do_test shell2-1.4.6 {
  forcedelete foo.db
  catchcmd "foo.db" {.echo ON
  catchcmdex "foo.db" {.echo ON
.headers ON
CREATE TABLE foo1(a);
INSERT INTO foo1(a) VALUES(1);
CREATE TABLE foo2(b);
INSERT INTO foo2(b) VALUES(1);
SELECT * FROM foo1; SELECT * FROM foo2;
INSERT INTO foo1(a) VALUES(2); INSERT INTO foo2(b) VALUES(2);
SELECT * FROM foo1; SELECT * FROM foo2;
}
} {0 {.headers ON
CREATE TABLE foo1(a);
INSERT INTO foo1(a) VALUES(1);
CREATE TABLE foo2(b);
INSERT INTO foo2(b) VALUES(1);
SELECT * FROM foo1;
SELECT * FROM foo1; SELECT * FROM foo2;
a
1
SELECT * FROM foo2;
b
1
INSERT INTO foo1(a) VALUES(2);
INSERT INTO foo1(a) VALUES(2); INSERT INTO foo2(b) VALUES(2);
INSERT INTO foo2(b) VALUES(2);
SELECT * FROM foo1;
SELECT * FROM foo1; SELECT * FROM foo2;
a
1
2
SELECT * FROM foo2;
b
1
2
}}

# Test for rejection of incomplete input at EOF.
# Reported at https://sqlite.org/forum/forumpost/718f489a43be3197
do_test shell2-1.4.7 {
  catchcmd ":memory:" {
 SELECT 'unclosed;}
} {1 {Parse error near line 2: unrecognized token: "'unclosed;"
  SELECT 'unclosed;
         ^--- error here}}

# Verify that safe mode rejects certain UDFs
# Reported at https://sqlite.org/forum/forumpost/07beac8056151b2f
do_test shell2-1.4.8 {
  catchcmd "-safe :memory:" {
 SELECT edit('DoNotCare');}
} {1 {line 2: cannot use the edit() function in safe mode}}
do_test shell2-1.4.9 {
  catchcmd "-safe :memory:" {
 SELECT writefile('DoNotCare', x'');}
} {1 {line 2: cannot use the writefile() function in safe mode}}

# Verify that .clone handles sequence table.
# See https://sqlite.org/forum/forumpost/71ff9e6c4c
do_test shell2-1.4.9 {
  forcedelete clone.db
  set res [catchcmd :memory: [string trim {
 CREATE TABLE t(id INTEGER PRIMARY KEY AUTOINCREMENT);
 INSERT INTO t VALUES (1),(2);
.clone clone.db
.open clone.db
 SELECT max(seq) FROM sqlite_sequence;}]]
} {0 {t... done
done
2}}


finish_test

Changes to test/shell3.test.

14
15
16
17
18
19
20

21
22
23
24

25
26
27

28
29
30
31
32
33
34
14
15
16
17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32
33
34
35
36







+



-
+



+







# $Id: shell2.test,v 1.7 2009/07/17 16:54:48 shaneh Exp $
#

# Test plan:
#
#   shell3-1.*: Basic tests for running SQL statments from command line.
#   shell3-2.*: Basic tests for running SQL file from command line.
#   shell3-3.*: Basic tests for processing odd SQL constructs.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set CLI [test_find_cli]
set CLI [test_cli_invocation]
db close
forcedelete test.db test.db-journal test.db-wal
sqlite3 db test.db


# There are inconsistencies in command-line argument quoting on Windows.
# In particular, individual applications are responsible for command-line
# parsing in Windows, not the shell.  Depending on whether the sqlite3.exe
# program is compiled with MinGW or MSVC, the command-line parsing is
# different.  This causes problems for the tests below.  To avoid
# issues, these tests are disabled for windows.
62
63
64
65
66
67
68
69

70
71
72
73
74
75
76
64
65
66
67
68
69
70

71
72
73
74
75
76
77
78







-
+







  catchcmd "foo.db \"CREATE TABLE t1(a); DROP TABLE t1;\""
} {0 {}}
do_test shell3-1.6 {
  catchcmd "foo.db" ".tables"
} {0 {}}
do_test shell3-1.7 {
  catchcmd "foo.db \"CREATE TABLE\""
} {1 {Error: incomplete input}}
} {1 {Error: in prepare, incomplete input}}

#----------------------------------------------------------------------------
#   shell3-2.*: Basic tests for running SQL file from command line.
#

# Run SQL file from command line
do_test shell3-2.1 {
92
93
94
95
96
97
98
99

100



































101
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







-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  catchcmd "foo.db" "CREATE TABLE t1(a); DROP TABLE t1;"
} {0 {}}
do_test shell3-2.6 {
  catchcmd "foo.db" ".tables"
} {0 {}}
do_test shell3-2.7 {
  catchcmd "foo.db" "CREATE TABLE"
} {1 {Error: near line 1: incomplete input}}
} {1 {Parse error near line 1: incomplete input}}


#----------------------------------------------------------------------------
#   shell3-3.*: Basic tests for processing odd SQL constructs.
#

# Run combinations of odd identifiers, comments, semicolon placement
do_test shell3-3.1 {
  forcedelete foo.db
  set rc [ catchcmd "foo.db" {CREATE TABLE t1("
a--.
" --x
); CREATE TABLE t2("a[""b""]");
.header on
INSERT INTO t1 VALUES ('
x''y');
INSERT INTO t2 VALUES ('
/*.
.*/ x
''y');
SELECT * from t1 limit 1;
SELECT * from t2 limit 1;
} ]
  set fexist [file exist foo.db]
  list $rc $fexist
} {{0 {
a--.


x'y
a["b"]

/*.
.*/ x
'y}} 1}

finish_test

Changes to test/shell4.test.

15
16
17
18
19
20
21

22
23
24
25


26
27
28
29
30
31
32
15
16
17
18
19
20
21
22
23
24
25

26
27
28
29
30
31
32
33
34







+



-
+
+







# 2015-03-19:  Added tests for .trace

# Test plan:
#
#   shell4-1.*: Basic tests specific to the "stats" command.
#   shell4-2.*: Basic tests for ".trace"
#   shell4-3.*: The ".read" command takes the shell out of interactive mode
#   shell4-4.*: Input redirects cannot recurse too much
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set CLI [test_find_cli]
set CLI [test_cli_invocation]
set CLI_ONLY [test_find_cli]
db close
forcedelete test.db test.db-journal test.db-wal
sqlite3 db test.db

#----------------------------------------------------------------------------
# Test cases shell4-1.*: Tests specific to the "stats" command.
#
62
63
64
65
66
67
68
69

70
71
72
73
74
75
76
64
65
66
67
68
69
70

71
72
73
74
75
76
77
78







-
+







} {0 {}}
do_test shell4-1.3.3 {
  catchcmd "test.db" ".stats OFF"
} {0 {}}
do_test shell4-1.3.4 {
  # too many arguments
  catchcmd "test.db" ".stats OFF BAD"
} {1 {Usage: .stats ?on|off?}}
} {1 {Usage: .stats ?on|off|stmt|vmstep?}}

# NB. whitespace is important
do_test shell4-1.4.1 {
  set res [catchcmd "test.db" {.show}]
  list [regexp {stats: off} $res]
} {1}

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
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







+









-






+
+
+
+
+
+







-
+





-
+


+
+
+
+
+
+
+

SELECT 1;
}]
  list [regexp {Memory Used} $res] \
       [regexp {Heap Usage} $res] \
       [regexp {Autoindex Inserts} $res]
} {1 1 1}

ifcapable trace {
do_test shell4-2.1 {
  catchcmd ":memory:" "CREATE TABLE t1(x);\n.trace --unknown"
} {1 {Unknown option "--unknown" on ".trace"}}
do_test shell4-2.2 {
  catchcmd ":memory:" "CREATE TABLE t1(x);\n.trace off\n.trace off\n"
} {0 {}}
do_test shell4-2.3 {
  catchcmd ":memory:" ".trace stdout\n.dump\n.trace off\n"
} {/^0 {PRAGMA.*}$/}
ifcapable trace {
do_test shell4-2.4 {
  catchcmd ":memory:" ".trace stdout\nCREATE TABLE t1(x);SELECT * FROM t1;"
} {0 {CREATE TABLE t1(x);
SELECT * FROM t1;}}
do_test shell4-2.5 {
  catchcmd ":memory:" "CREATE TABLE t1(x);\n.trace stdout\nSELECT * FROM t1;"
} {0 {SELECT * FROM t1;}}
do_test shell4-2.6 {
  catchcmd ":memory:" {
CREATE TABLE t1(x);
.trace --stmt stdout
SELECT * FROM t1;}
} {0 {SELECT * FROM t1;}}
}

do_test shell4-3.1 {
  set fd [open t1.txt wb]
  puts $fd "SELECT 'squirrel';"
  close $fd
  exec $::CLI :memory: --interactive ".read t1.txt"
  exec $::CLI_ONLY :memory: --interactive ".read t1.txt"
} {squirrel}
do_test shell4-3.2 {
  set fd [open t1.txt wb]
  puts $fd "SELECT 'pound: \302\243';"
  close $fd
  exec $::CLI :memory: --interactive ".read t1.txt"
  exec $::CLI_ONLY :memory: --interactive ".read t1.txt"
} {pound: £}

do_test shell4-4.1 {
  set fd [open t1.txt wb]
  puts $fd ".read t1.txt"
  close $fd
  catchcmd ":memory:" ".read t1.txt"
} {1 {Input nesting limit (25) reached at line 1. Check recursion.}}

finish_test

Changes to test/shell5.test.

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
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







-
+










-
+


-
+
-
-
-



-
+








# Test plan:
#
#   shell5-1.*: Basic tests specific to the ".import" command.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set CLI [test_find_cli]
set CLI [test_cli_invocation]
db close
forcedelete test.db test.db-journal test.db-wal

#----------------------------------------------------------------------------
# Test cases shell5-1.*: Basic handling of the .import and .separator commands.
#

# .import FILE TABLE     Import data from FILE into TABLE
do_test shell5-1.1.1 {
  catchcmd "test.db" ".import"
} {1 {Usage: .import FILE TABLE}}
} {/1 .ERROR: missing FILE argument.*/}
do_test shell5-1.1.2 {
  catchcmd "test.db" ".import FOO"
} {1 {Usage: .import FILE TABLE}}
} {/1 .ERROR: missing TABLE argument.*/}
#do_test shell5-1.1.2 {
#  catchcmd "test.db" ".import FOO BAR"
#} {1 {Error: no such table: BAR}}
do_test shell5-1.1.3 {
  # too many arguments
  catchcmd "test.db" ".import FOO BAR BAD"
} {1 {Usage: .import FILE TABLE}}
} {/1 .ERROR: extra argument.*/}

# .separator STRING      Change separator used by output mode and .import
do_test shell5-1.2.1 {
  catchcmd "test.db" ".separator"
} {1 {Usage: .separator COL ?ROW?}}
do_test shell5-1.2.2 {
  catchcmd "test.db" ".separator ONE"
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
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







-
-
+
+
+







-
+
+







-
+
+




















-
-
+
+
+







+
-
-
-
+
+
+







} {1 {Error: cannot open "FOO"}}

# empty import file
do_test shell5-1.4.2 {
  forcedelete shell5.csv
  set in [open shell5.csv w]
  close $in
  set res [catchcmd "test.db" {.import shell5.csv t1
SELECT COUNT(*) FROM t1;}]
  set res [catchcmd ":memory:" {ATTACH 'test.db' AS test;
.import -schema test shell5.csv t1
SELECT COUNT(*) FROM test.t1;}]
} {0 0}

# import file with 1 row, 1 column (expecting 2 cols)
do_test shell5-1.4.3 {
  set in [open shell5.csv w]
  puts $in "1"
  close $in
  set res [catchcmd "test.db" {.import shell5.csv t1}]
  set res [catchcmd ":memory:" {ATTACH 'test.db' AS test;
.import -schema test shell5.csv t1}]
} {1 {shell5.csv:1: expected 2 columns but found 1 - filling the rest with NULL}}

# import file with 1 row, 3 columns (expecting 2 cols)
do_test shell5-1.4.4 {
  set in [open shell5.csv w]
  puts $in "1|2|3"
  close $in
  set res [catchcmd "test.db" {.import shell5.csv t1}]
  set res [catchcmd ":memory:" {ATTACH 'test.db' AS test;
.import --schema test shell5.csv t1}]
} {1 {shell5.csv:1: expected 2 columns but found 3 - extras ignored}}

# import file with 1 row, 2 columns
do_test shell5-1.4.5 {
  set in [open shell5.csv w]
  puts $in "1|2"
  close $in
  set res [catchcmd "test.db" {DELETE FROM t1;
.import shell5.csv t1
SELECT COUNT(*) FROM t1;}]
} {0 1}

# import file with 2 rows, 2 columns
# note we end up with 3 rows because of the 1 row 
# imported above.
do_test shell5-1.4.6 {
  set in [open shell5.csv w]
  puts $in "2|3"
  puts $in "3|4"
  close $in
  set res [catchcmd "test.db" {.import shell5.csv t1
SELECT COUNT(*) FROM t1;}]
  set res [catchcmd ":memory:" {ATTACH 'test.db' AS test;
.import -schema test shell5.csv t1
SELECT COUNT(*) FROM test.t1;}]
} {0 3}

# import file with 1 row, 2 columns, using a comma
do_test shell5-1.4.7 {
  set in [open shell5.csv w]
  puts $in "4,5"
  close $in
  set res [catchcmd ":memory:" {ATTACH 'test.db' AS test;
  set res [catchcmd "test.db" {.separator ,
.import shell5.csv t1
SELECT COUNT(*) FROM t1;}]
.separator ,
.import --schema test shell5.csv t1
SELECT COUNT(*) FROM test.t1;}]
} {0 4}

# import file with 1 row, 2 columns, text data
do_test shell5-1.4.8.1 {
  set in [open shell5.csv w]
  puts $in "5|Now is the time for all good men to come to the aid of their country."
  close $in
256
257
258
259
260
261
262
263

264
265
266
267
268
269
270
258
259
260
261
262
263
264

265
266
267
268
269
270
271
272







-
+







  }
  close $in
  set res [catchcmd "test.db" {.mode csv
.import shell5.csv t3
SELECT COUNT(*) FROM t3;}]
} [list 0 $rows]

# Inport from a pipe.  (Unix only, as it requires "awk")
# Import from a pipe.  (Unix only, as it requires "awk")
if {$tcl_platform(platform)=="unix"} {
  do_test shell5-1.8 {
    forcedelete test.db
    catchcmd test.db {.mode csv
.import "|awk 'END{print \"x,y\";for(i=1;i<=5;i++){print i \",this is \" i}}'" t1
SELECT * FROM t1;}
  } {0 {1,"this is 1"
454
455
456
457
458
459
460
461













































































































462
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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  catchcmd test.db [string trim {
.mode csv
CREATE TABLE t7(a, b, c);
.import shell5.csv t7
  }]
  db eval { SELECT * FROM t7 ORDER BY a }
} {1 2 3 4 5 {} 6 7 8}

do_test shell5-4.3 {
  forcedelete shell5.csv
  set fd [open shell5.csv w]
  puts $fd ",,"
  puts $fd "1,2,3"
  close $fd
  catchcmd test.db [string trim {
.mode csv
CREATE TABLE t8(a, b, c);
.import -skip 1 shell5.csv t8
.nullvalue #
  }]
  db eval { SELECT * FROM t8 }
} {1 2 3}

do_test shell5-4.4 {
  forcedelete shell5.csv
  set fd [open shell5.csv w]
  puts $fd "1,2,3"
  close $fd
  catchcmd test.db [string trim {
.mode csv
CREATE TEMP TABLE t8(a, b, c);
.import shell5.csv t8
.nullvalue #
SELECT * FROM temp.t8
  }]
} {0 1,2,3}

#----------------------------------------------------------------------------
# Tests for the shell automatic column rename.
#
db close

# Import columns containing duplicates
do_test shell5-5.1 {
  set out [open shell5.csv w]
  fconfigure $out -translation lf
  puts $out {"","x","x","y","z","z_0","z_5","z"}
  puts $out {0,"x2","x3","y4","z5","z6","z7","z8"}
  close $out
  forcedelete test.db
  catchcmd test.db {.import -csv shell5.csv t1
.mode line
SELECT * FROM t1;}
} {1 {    ? = 0
 x_02 = x2
 x_03 = x3
    y = y4
 z_05 = z5
  z_0 = z6
  z_5 = z7
 z_08 = z8
Columns renamed during .import shell5.csv due to duplicates:
"x" to "x_02",
"x" to "x_03",
"z" to "z_05",
"z" to "z_08"}}

do_test shell5-5.1 {
  set out [open shell5.csv w]
  fconfigure $out -translation lf
  puts $out {"COW","cow","CoW","cOw"}
  puts $out {"uuu","lll","ulu","lul"}
  close $out
  forcedelete test.db
  catchcmd test.db {.import -csv shell5.csv t1
.mode line
SELECT * FROM t1;}
} {1 {COW_1 = uuu
cow_2 = lll
CoW_3 = ulu
cOw_4 = lul
Columns renamed during .import shell5.csv due to duplicates:
"COW" to "COW_1",
"cow" to "cow_2",
"CoW" to "CoW_3",
"cOw" to "cOw_4"}}

#----------------------------------------------------------------------------
# Tests for preserving utf-8 that is not also ASCII.
#

do_test shell5-6.1 {
  set out [open shell5.csv w]
  fconfigure $out -translation lf
  puts $out {あい,うえお}
  puts $out {1,2}
  close $out
  forcedelete test.db
  catchcmd test.db {.import -csv shell5.csv t1
.mode line
SELECT * FROM t1;}
} {0 {   あい = 1
うえお = 2}}

do_test shell5-6.2 {
  set out [open shell5.csv w]
  fconfigure $out -translation lf
  puts $out {1,2}
  puts $out {あい,うえお}
  close $out
  forcedelete test.db
  catchcmd test.db {.import -csv shell5.csv t1
.mode line
SELECT * FROM t1;}
} {0 {    1 = あい
    2 = うえお}}

finish_test

Changes to test/shell8.test.

15
16
17
18
19
20
21
22

23
24
25
26
27
28
29
15
16
17
18
19
20
21

22
23
24
25
26
27
28
29







-
+







set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix shell8

ifcapable !vtab {
  finish_test; return
}
set CLI [test_find_cli]
set CLI [test_cli_invocation]

# Check to make sure the shell has been compiled with ".archive" support.
#
if {[string match {*unknown command*} [catchcmd :memory: .archive]]} {
  finish_test; return
}

39
40
41
42
43
44
45




46
47
48
49
50
51
52
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56







+
+
+
+







    set path [file join $dirname $f]
    file mkdir [file dirname $path]
    set fd [open $path w]
    puts -nonewline $fd $d
    close $fd
  }
}

proc dir_content {dirname} {
  lsort [glob -nocomplain $dirname/*]
}

proc dir_to_list {dirname {n -1}} {
  if {$n<0} {set n [llength [file split $dirname]]}

  set res [list]
  foreach f [glob -nocomplain $dirname/*] {
    set mtime [file mtime $f]
166
167
168
169
170
171
172
173
174
175


















176
177
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







-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


      after 2000
      catchcmd test_ar.db $x1
      dir_to_list ar1
    } $expected
  }
}

finish_test


do_test 2.1.1 {
  populate_dir ar2 {
    file1 "abcd" 
    file2 "efgh"
    junk1 "j1"
    junk2 "j2"
    dir1/file3 "ijkl"
  }
  populate_dir ar4 {
    file2 "efgh"
  }
  catchcmd shell8.db {.ar -c}
  catchcmd shell8.db {.ar -C ar2 -i .}
  catchcmd shell8.db {.ar -r ./file2 ./dir1}
  catchcmd shell8.db {.ar -g -r ./ju*2}
  catchcmd shell8.db {.ar -C ar4 -x .}
  regsub -all {ar4} [dir_content ar4] ar2
} {ar2/file1 ar2/file2 ar2/junk1}

finish_test

Added test/shmlock.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2018 December 6
#
# 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

set testprefix shmlock

ifcapable !wal {finish_test ; return }

sqlite3 db2 test.db
sqlite3 db3 test.db

do_execsql_test 1.0 {
  PRAGMA journal_mode = wal;
  CREATE TABLE t1(a, b);
  INSERT INTO t1 VALUES(1, 2);
} {wal}
do_test 1.1 { execsql { SELECT * FROM t1 } db2 } {1 2}
do_test 1.2 { execsql { SELECT * FROM t1 } db3 } {1 2}

foreach {tn dbhandle cmd res} {
  1    db  {shared    lock   7 1}    OK
  2    db2 {exclusive lock   7 1}    BUSY
  3    db  {shared    unlock 7 1}    OK
  4    db2 {exclusive lock   7 1}    OK
  5    db  {shared    lock   7 1}    BUSY
  6    db  {exclusive lock   7 1}    BUSY
  7    db2 {exclusive unlock 7 1}    OK

  8    db  {exclusive lock   0 8}    OK
  9    db  {exclusive unlock 0 8}    OK
  10   db2 {exclusive lock   0 8}    OK
  11   db2 {exclusive unlock 0 8}    OK

  12   db  {shared    lock   0 1}    OK
  13   db2 {shared    lock   0 1}    OK
  14   db3 {shared    lock   0 1}    OK
  15   db3 {shared    unlock 0 1}    OK
  16   db3 {exclusive lock   0 1}    BUSY
  17   db2 {shared    unlock 0 1}    OK
  18   db3 {exclusive lock   0 1}    BUSY
  19   db  {shared    unlock 0 1}    OK
  20   db3 {exclusive lock   0 1}    OK
  21   db3 {exclusive unlock 0 1}    OK

  22   db  {shared    lock   3 1}    OK
  23   db2 {exclusive lock   2 2}    BUSY
  24   db  {shared    lock   2 1}    OK
  25   db2 {exclusive lock   0 5}    BUSY
  26   db2 {exclusive lock   0 4}    BUSY
  27   db2 {exclusive lock   0 3}    BUSY
  28   db  {shared    unlock 3 1}    OK
  29   db2 {exclusive lock   2 2}    BUSY
  28   db  {shared    unlock 2 1}    OK
  29   db2 {exclusive lock   2 2}    OK
  29   db2 {exclusive unlock 2 2}    OK
} {
  do_test 1.3.$tn [list vfs_shmlock $dbhandle main {*}$cmd] "SQLITE_$res"
}

db  close
db2 close
db3 close

if {[permutation]=="unix-excl"} {
  do_test 2.0 {
    for {set i 0} {$i < 256} {incr i} { 
      sqlite3 db$i test.db 
      execsql { SELECT * FROM t1 } db$i
    }
    for {set i 0} {$i < 255} {incr i} { 
      set rc [vfs_shmlock db$i main shared lock 4 1]
      if {$rc != "SQLITE_OK"} { error $rc }
    }

    vfs_shmlock db255 main shared lock 4 1
  } {SQLITE_BUSY}

  do_test 2.1 { vfs_shmlock db255 main exclusive lock   4 1 } SQLITE_BUSY
  do_test 2.2 { vfs_shmlock db0   main shared    unlock 4 1 } SQLITE_OK
  do_test 2.3 { vfs_shmlock db255 main shared    lock   4 1 } SQLITE_OK
  do_test 2.4 { vfs_shmlock db255 main shared    unlock 4 1 } SQLITE_OK
  do_test 2.5 { vfs_shmlock db255 main exclusive lock   4 1 } SQLITE_BUSY

  do_test 2.6 {
    for {set i 1} {$i < 255} {incr i} { 
      set rc [vfs_shmlock db255 main exclusive lock 4 1]
      if {$rc != "SQLITE_BUSY"} { error $rc }
      set rc [vfs_shmlock db$i main shared unlock 4 1]
      if {$rc != "SQLITE_OK"} { error $rc }
    }

    vfs_shmlock db255 main exclusive lock 4 1
  } {SQLITE_OK}

  vfs_shmlock db255 main exclusive unlock 4 1

  for {set i 0} {$i < 256} {incr i} {
    db$i close
  }
}

sqlite3 db0 test.db
sqlite3 db1 test.db
do_test 3.1 { execsql { SELECT * FROM t1 } db0 } {1 2}
do_test 3.2 { execsql { SELECT * FROM t1 } db1 } {1 2}
if {$tcl_platform(platform)=="windows"} {
  set isWindows 1
} else {
  set isWindows 0
}

set L(0) {n n n n n n n n}
set L(1) {n n n n n n n n}
proc random_lock_test {idx} {
  global L
  set iSlot [expr int(rand()*8)]
  if {[expr int(rand()*2)]} {
    # Unlock operation
    if {[lindex $L($idx) $iSlot]!="n"} {
      vfs_shmlock db$idx main [lindex $L($idx) $iSlot] unlock $iSlot 1
      lset L($idx) $iSlot n
    }
  } else {
    # Lock operation
    if {[lindex $L($idx) $iSlot]=="n"} {
      set locktype [lindex {e s} [expr int(rand()*2)]]
      set n 1
      if {$locktype=="e"} {
        for {set l $iSlot} {$l<8 && [lindex $L($idx) $l]=="n"} {incr l} {}
        set n [expr int(rand()*($l-$iSlot))+1]
        # The LockFile() and UnlockFile() apis on windows require that
        # every unlock correspond exactly to a prior lock.  Hence, we cannot
        # lock arbitrary ranges in this test on windows.
        if {$::isWindows} {set n 1}
        # puts "iSlot=$iSlot l=$l L=$L($idx)"
        # puts "$iSlot $n"
      }
      set res [vfs_shmlock db$idx main $locktype lock $iSlot $n]

      set bBusy 0
      for {set i $iSlot} {$i<($iSlot+$n)} {incr i} {
        set other [lindex $L([expr ($idx+1)%2]) $i]
        if {($other!="n" && $locktype=="e")||($other=="e" && $locktype=="s")} {
          if {$res != "SQLITE_BUSY"} { error "BUSY not detected" }
          set bBusy 1
          break
        } 
      }

      if {$bBusy==0} {
        if {$res != "SQLITE_OK"} { error "BUSY false-positive" }
        for {set i $iSlot} {$i<($iSlot+$n)} {incr i} {
          lset L($idx) $i $locktype
        }
      }
    }
  }
}

set nStep 100000
for {set i 0} {$i < $nStep} {incr i} {
  random_lock_test 0
  random_lock_test 1
}

db0 close
db1 close

finish_test

Changes to test/shrink.test.

20
21
22
23
24
25
26
27

28
29
30
31
32
33
34
20
21
22
23
24
25
26

27
28
29
30
31
32
33
34







-
+







unset -nocomplain baseline
do_test shrink-1.1 {
  db eval {
    PRAGMA cache_size = 2000;
    CREATE TABLE t1(x,y);
    INSERT INTO t1 VALUES(randomblob(1000000),1);
  }
  set ::baseline sqlite3_memory_used
  set ::baseline [sqlite3_memory_used]
  # EVIDENCE-OF: R-58814-63508 The sqlite3_db_release_memory(D) interface
  # attempts to free as much heap memory as possible from database
  # connection D.
  sqlite3_db_release_memory db
  expr {$::baseline > [sqlite3_memory_used]+500000}
} {1}
do_test shrink-1.2 {

Changes to test/skipscan1.test.

230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
230
231
232
233
234
235
236

237
238
239
240
241
242
243







-







  EXPLAIN QUERY PLAN
    SELECT xh, loc FROM t5 WHERE loc >= 'M' AND loc < 'N';
} {/.*COVERING INDEX t5i1 .*/}
do_execsql_test skipscan1-5.2 {
  ANALYZE;
  DELETE FROM sqlite_stat1;
  DROP TABLE IF EXISTS sqlite_stat4;
  DROP TABLE IF EXISTS sqlite_stat3;
  INSERT INTO sqlite_stat1 VALUES('t5','t5i1','2702931 3 2 2 2 2');
  INSERT INTO sqlite_stat1 VALUES('t5','t5i2','2702931 686 2 2 2');
  ANALYZE sqlite_master;
} {}
db cache flush
do_execsql_test skipscan1-5.3 {
  EXPLAIN QUERY PLAN
338
339
340
341
342
343
344
345

346
347











































































348
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







-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

} {/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);

  ANALYZE;
  DELETE FROM sqlite_stat1;
  INSERT INTO sqlite_stat1 VALUES('t6','t6abc','10000 5000 2000 10');
  ANALYZE sqlite_master;
  DELETE FROM t6;
} {}

do_execsql_test skipscan1-2.2eqp {
  EXPLAIN QUERY PLAN
  SELECT a,b,c,d,'|' FROM t6 WHERE d<>99 AND b=345 ORDER BY a;
} {/* USING INDEX t6abc (ANY(a) AND b=?)*/}
do_execsql_test skipscan1-2.2 {
  SELECT a,b,c,d,'|' FROM t6 WHERE d<>99 AND b=345 ORDER BY a;
} {}

do_execsql_test skipscan1-2.3eqp {
  EXPLAIN QUERY PLAN
  SELECT a,b,c,d,'|' FROM t6 WHERE d<>99 AND b=345 ORDER BY a DESC;
} {/* USING INDEX t6abc (ANY(a) AND b=?)*/}
do_execsql_test skipscan1-2.3 {
  SELECT a,b,c,d,'|' FROM t6 WHERE d<>99 AND b=345 ORDER BY a DESC;
} {}

# 2019-07-29 Ticket ced41c7c7d6b4d36
# A skipscan query is not order-distinct
#
db close
sqlite3 db :memory:
do_execsql_test skipscan1-3.1 {
  CREATE TABLE t1 (c1, c2, c3, c4, PRIMARY KEY(c4, c3));
  INSERT INTO t1 VALUES(3,0,1,NULL);
  INSERT INTO t1 VALUES(0,4,1,NULL);
  INSERT INTO t1 VALUES(5,6,1,NULL);
  INSERT INTO t1 VALUES(0,4,1,NULL);
  ANALYZE sqlite_master;
  INSERT INTO sqlite_stat1 VALUES('t1','sqlite_autoindex_t1_1','18 18 6');
  ANALYZE sqlite_master;
  SELECT DISTINCT quote(c1), quote(c2), quote(c3), quote(c4), '|'
    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 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 {
  CREATE TABLE t1(a,b INT);
  INSERT INTO t1(a,b) VALUES(1,2),(3,3),(4,5);
  CREATE UNIQUE INDEX i1 ON t1(b,b,a,a,a,a,a,b,a);
  ANALYZE;
  DROP TABLE IF EXISTS sqlite_stat4;
  INSERT INTO sqlite_stat1 VALUES('t1','i1','30 30 30 2 2 2 2 2 2 2');
  ANALYZE sqlite_master;

  SELECT DISTINCT a
    FROM t1
   WHERE a = b
     AND a = 3
     AND b IN (1,3,2,4)
     AND b >= 0
     AND a <= 10;
} {3}

finish_test

Changes to test/skipscan2.test.

153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
153
154
155
156
157
158
159

160
161
162
163
164
165
166







-







    role TEXT NOT NULL,
    height INT NOT NULL, -- in cm
    CHECK( role IN ('student','teacher') )
  ) WITHOUT ROWID;
  CREATE INDEX peoplew_idx1 ON peoplew(role, height);
  INSERT INTO peoplew(name,role,height)
     SELECT name, role, height FROM  people;
  ALTER TABLE people RENAME TO old_people;
  SELECT name FROM peoplew WHERE height>=180 ORDER BY +name;
} {David Jack Patrick Quiana Xavier}
do_execsql_test skipscan2-2.2 {
  SELECT name FROM peoplew
   WHERE role IN (SELECT DISTINCT role FROM peoplew)
     AND height>=180 ORDER BY +name;
} {David Jack Patrick Quiana Xavier}
195
196
197
198
199
200
201
202


203
204
205
194
195
196
197
198
199
200

201
202
203
204
205







-
+
+



  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.

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
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







-
+










-
+

-
-
-
+
+
+




-
+

-
-
-
+
+
+







do_execsql_test 1.1 {
  CREATE TABLE t1(a INT, b INT, c INT);
  CREATE INDEX i1 ON t1(a, b);
} {}

expr srand(4)
do_test 1.2 {
  for {set i 0} {$i < 100} {incr i} {
  for {set i 0} {$i < 1000} {incr i} {
    set a [expr int(rand()*4.0) + 1]
    set b [expr int(rand()*20.0) + 1]
    execsql { INSERT INTO t1 VALUES($a, $b, NULL) }
  }
  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 > 15"                  {/*ANY(a) AND b>?*/}
  6  "b > 5"                   {/*SCAN TABLE t1*/}
  7  "b < 15"                  {/*SCAN TABLE t1*/}
  5  "b > 16"                  {/*ANY(a) AND b>?*/}
  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 > '15'"                {/*ANY(a) AND b>?*/}
  15 "b > '5'"                 {/*SCAN TABLE t1*/}
  16 "b < '15'"                {/*SCAN TABLE t1*/}
  14 "b > '16'"                {/*ANY(a) AND b>?*/}
  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
118
100
101
102
103
104
105
106

107
108



109
110
111
112
113
114
115
116
117
118







-
+

-
-
-
+
+
+







      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*/}
    6 { c < 'c' }                     {/*ANY(a) AND ANY(b) AND c<?*/}
    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/snapshot_fault.test.

217
218
219
220
221
222
223

























224
225
226
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



  db eval COMMIT
} -body {
  sqlite3_snapshot_recover db main
} -test {
  faultsim_test_result {0 {}} {1 SQLITE_IOERR}
}

#-------------------------------------------------------------------------
# Test the handling of faults that occur within sqlite3_snapshot_get().
#
reset_db
do_execsql_test 5.0 {
  PRAGMA page_size = 512;
  PRAGMA journal_mode = wal;
  PRAGMA wal_autocheckpoint = 0;
  CREATE TABLE t1(zzz);
  INSERT INTO t1 VALUES(randomblob( 5000 ));
  PRAGMA user_version = 211;
} {wal 0}
faultsim_save_and_close

do_faultsim_test 5 -prep {
  faultsim_restore_and_reopen
  execsql { SELECT count(*) FROM sqlite_master }
  execsql BEGIN
} -body {
  sqlite3_snapshot_get_blob db main
  set {} {}
} -test {
  execsql END
  faultsim_test_result {0 {}} {1 SQLITE_IOERR} {1 SQLITE_NOMEM}
}


finish_test

Changes to test/sort.test.

591
592
593
594
595
596
597
































598
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

} {1 {UNIQUE constraint failed: t1.b, t1.a, t1.c}}

reset_db
do_execsql_test 17.1 {
  SELECT * FROM sqlite_master ORDER BY sql;
} {}

# 2022-12-03 Ticket e8b674241947eb3b
# Improve estimates for the cost of sorting relative
# to the cost of doing an index lookup, so as to get
# a better query plan.  See the ticket for a deetailed
# example.
#
reset_db
do_execsql_test 18.1 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<50)
                           -- increase to 5000 for actual test data ----^^
    INSERT INTO t1(a,b,c) SELECT x, random()%5000, random()%5000 FROM c;
  CREATE TABLE t2(d,e,f);
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<500)
                         -- increase to 50000 for actual test data -----^^^
    INSERT INTO t2(d,e,f) SELECT
       NULLIF(0, random()%2), random()%5000, random()%5000
       FROM c;
  ANALYZE;
  UPDATE sqlite_stat1 SET stat='50000' WHERE tbl='t2';
  UPDATE sqlite_stat1 SET stat='5000' WHERE tbl='t1';
  ANALYZE sqlite_schema;
} {}
do_execsql_test 18.2 {
  EXPLAIN QUERY PLAN
  SELECT a FROM t1 JOIN t2
   WHERE a IN (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20)
     AND a=CASE WHEN d IS NOT NULL THEN e ELSE f END
   ORDER BY a;
} {/.*SCAN t2.*SEARCH t1.*/}
#     ^^^^^^^--^^^^^^^^^---  t2 should be the outer loop.

finish_test

Changes to test/sorterref.test.

9
10
11
12
13
14
15






16
17
18
19
20
21
22
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28







+
+
+
+
+
+







#
#***********************************************************************
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix sorterref

# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
ifcapable !altertable {
  finish_test
  return
}

do_execsql_test 1.0 {
  CREATE TABLE t1(a, b, c);
  INSERT INTO t1 VALUES(1, 2, 3);
  INSERT INTO t1 VALUES(4, 5, 6);
  ALTER TABLE t1 ADD COLUMN d DEFAULT 'string';
  INSERT INTO t1 VALUES(7, 8, 9, 'text');

Changes to test/speedtest1.c.

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
1
2
3
4
5
6
7
8
9
10

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

48
49
50
51

52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122

123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205









+
-
+
+







+



+


+





+
+





+







-
+
+


-



















+
+
+
+
+
+
+
+
+
+
+
+
+
+
















+
+
+




+


+
+
+
+
+







-










+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







/*
** A program for performance testing.
**
** The available command-line options are described below:
*/
static const char zHelp[] =
  "Usage: %s [--options] DATABASE\n"
  "Options:\n"
  "  --autovacuum        Enable AUTOVACUUM mode\n"
  "  --big-transactions  Add BEGIN/END around all large tests\n"
  "  --cachesize N       Set the cache size to N\n" 
  "  --cachesize N       Set PRAGMA cache_size=N. Note: N is pages, not bytes\n"
  "  --checkpoint        Run PRAGMA wal_checkpoint after each test case\n"
  "  --exclusive         Enable locking_mode=EXCLUSIVE\n"
  "  --explain           Like --sqlonly but with added EXPLAIN keywords\n"
  "  --heap SZ MIN       Memory allocator uses SZ bytes & min allocation MIN\n"
  "  --incrvacuum        Enable incremenatal vacuum mode\n"
  "  --journal M         Set the journal_mode to M\n"
  "  --key KEY           Set the encryption key to KEY\n"
  "  --lookaside N SZ    Configure lookaside for N slots of SZ bytes each\n"
  "  --memdb             Use an in-memory database\n"
  "  --mmap SZ           MMAP the first SZ bytes of the database file\n"
  "  --multithread       Set multithreaded mode\n"
  "  --nomemstat         Disable memory statistics\n"
  "  --nomutex           Open db with SQLITE_OPEN_NOMUTEX\n"
  "  --nosync            Set PRAGMA synchronous=OFF\n"
  "  --notnull           Add NOT NULL constraints to table columns\n"
  "  --output FILE       Store SQL output in FILE\n"
  "  --pagesize N        Set the page size to N\n"
  "  --pcache N SZ       Configure N pages of pagecache each of size SZ bytes\n"
  "  --primarykey        Use PRIMARY KEY instead of UNIQUE where appropriate\n"
  "  --repeat N          Repeat each SELECT N times (default: 1)\n"
  "  --reprepare         Reprepare each statement upon every invocation\n"
  "  --reserve N         Reserve N bytes on each database page\n"
  "  --script FILE       Write an SQL script for the test into FILE\n"
  "  --serialized        Set serialized threading mode\n"
  "  --singlethread      Set single-threaded mode - disables all mutexing\n"
  "  --sqlonly           No-op.  Only show the SQL that would have been run.\n"
  "  --shrink-memory     Invoke sqlite3_db_release_memory() frequently.\n"
  "  --size N            Relative test size.  Default=100\n"
  "  --strict            Use STRICT table where appropriate\n"
  "  --stats             Show statistics at the end\n"
  "  --temp N            N from 0 to 9.  0: no temp table. 9: all temp tables\n"
  "  --testset T         Run test-set T (main, cte, rtree, orm, fp, debug)\n"
  "  --trace             Turn on SQL tracing\n"
  "  --threads N         Use up to N threads for sorting\n"
  "  --utf16be           Set text encoding to UTF-16BE\n"
  "  --utf16le           Set text encoding to UTF-16LE\n"
  "  --verify            Run additional verification steps.\n"
  "  --verify            Run additional verification steps\n"
  "  --vfs NAME          Use the given (preinstalled) VFS\n"
  "  --without-rowid     Use WITHOUT ROWID where appropriate\n"
;


#include "sqlite3.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#ifndef _WIN32
# include <unistd.h>
#else
# include <io.h>
#endif
#define ISSPACE(X) isspace((unsigned char)(X))
#define ISDIGIT(X) isdigit((unsigned char)(X))

#if SQLITE_VERSION_NUMBER<3005000
# define sqlite3_int64 sqlite_int64
#endif

typedef sqlite3_uint64 u64;

/*
** State structure for a Hash hash in progress
*/
typedef struct HashContext HashContext;
struct HashContext {
  unsigned char isInit;          /* True if initialized */
  unsigned char i, j;            /* State variables */
  unsigned char s[256];          /* State variables */
  unsigned char r[32];           /* Result */
};


/* All global state is held in this structure */
static struct Global {
  sqlite3 *db;               /* The open database connection */
  sqlite3_stmt *pStmt;       /* Current SQL statement */
  sqlite3_int64 iStart;      /* Start-time for the current test */
  sqlite3_int64 iTotal;      /* Total time */
  int bWithoutRowid;         /* True for --without-rowid */
  int bReprepare;            /* True to reprepare the SQL on each rerun */
  int bSqlOnly;              /* True to print the SQL once only */
  int bExplain;              /* Print SQL with EXPLAIN prefix */
  int bVerify;               /* Try to verify that results are correct */
  int bMemShrink;            /* Call sqlite3_db_release_memory() often */
  int eTemp;                 /* 0: no TEMP.  9: always TEMP. */
  int szTest;                /* Scale factor for test iterations */
  int nRepeat;               /* Repeat selects this many times */
  int doCheckpoint;          /* Run PRAGMA wal_checkpoint after each trans */
  int nReserve;              /* Reserve bytes */
  int doBigTransactions;     /* Enable transactions on tests 410 and 510 */
  const char *zWR;           /* Might be WITHOUT ROWID */
  const char *zNN;           /* Might be NOT NULL */
  const char *zPK;           /* Might be UNIQUE or PRIMARY KEY */
  unsigned int x, y;         /* Pseudo-random number generator state */
  u64 nResByte;              /* Total number of result bytes */
  int nResult;               /* Size of the current result */
  char zResult[3000];        /* Text of the current result */
  FILE *pScript;             /* Write an SQL script into this file */
#ifndef SPEEDTEST_OMIT_HASH
  FILE *hashFile;            /* Store all hash results in this file */
  HashContext hash;          /* Hash of all output */
#endif
} g;

/* Return " TEMP" or "", as appropriate for creating a table.
*/
static const char *isTemp(int N){
  return g.eTemp>=N ? " TEMP" : "";
}


/* Print an error message and exit */
static void fatal_error(const char *zMsg, ...){
  va_list ap;
  va_start(ap, zMsg);
  vfprintf(stderr, zMsg, ap);
  va_end(ap);
  exit(1);
}

#ifndef SPEEDTEST_OMIT_HASH
/****************************************************************************
** Hash algorithm used to verify that compilation is not miscompiled
** in such a was as to generate an incorrect result.
*/

/*
** Initialize a new hash.  iSize determines the size of the hash
** in bits and should be one of 224, 256, 384, or 512.  Or iSize
** can be zero to use the default hash size of 256 bits.
*/
static void HashInit(void){
  unsigned int k;
  g.hash.i = 0;
  g.hash.j = 0;
  for(k=0; k<256; k++) g.hash.s[k] = k;
}

/*
** Make consecutive calls to the HashUpdate function to add new content
** to the hash
*/
static void HashUpdate(
  const unsigned char *aData,
  unsigned int nData
){
  unsigned char t;
  unsigned char i = g.hash.i;
  unsigned char j = g.hash.j;
  unsigned int k;
  if( g.hashFile ) fwrite(aData, 1, nData, g.hashFile);
  for(k=0; k<nData; k++){
    j += g.hash.s[i] + aData[k];
    t = g.hash.s[j];
    g.hash.s[j] = g.hash.s[i];
    g.hash.s[i] = t;
    i++;
  }
  g.hash.i = i;
  g.hash.j = j;
}

/*
** After all content has been added, invoke HashFinal() to compute
** the final hash.  The hash result is stored in g.hash.r[].
*/
static void HashFinal(void){
  unsigned int k;
  unsigned char t, i, j;
  i = g.hash.i;
  j = g.hash.j;
  for(k=0; k<32; k++){
    i++;
    t = g.hash.s[i];
    j += t;
    g.hash.s[i] = g.hash.s[j];
    g.hash.s[j] = t;
    t += g.hash.s[i];
    g.hash.r[k] = g.hash.s[t];
  }
}

/* End of the Hash hashing logic
*****************************************************************************/
#endif /* SPEEDTEST_OMIT_HASH */

/*
** Return the value of a hexadecimal digit.  Return -1 if the input
** is not a hex digit.
*/
static int hexDigitValue(char c){
  if( c>='0' && c<='9' ) return c - '0';
  if( c>='a' && c<='f' ) return c - 'a' + 10;
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
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







+




+








+
+
+
+
+













+
+
+



+
+
+
+
+








+







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







}


/* Start a new test case */
#define NAMEWIDTH 60
static const char zDots[] =
  ".......................................................................";
static int iTestNumber = 0;  /* Current test # for begin/end_test(). */
void speedtest1_begin_test(int iTestNum, const char *zTestName, ...){
  int n = (int)strlen(zTestName);
  char *zName;
  va_list ap;
  iTestNumber = iTestNum;
  va_start(ap, zTestName);
  zName = sqlite3_vmprintf(zTestName, ap);
  va_end(ap);
  n = (int)strlen(zName);
  if( n>NAMEWIDTH ){
    zName[NAMEWIDTH] = 0;
    n = NAMEWIDTH;
  }
  if( g.pScript ){
    fprintf(g.pScript,"-- begin test %d %.*s\n", iTestNumber, n, zName)
      /* maintenance reminder: ^^^ code in ext/wasm expects %d to be
      ** field #4 (as in: cut -d' ' -f4). */;
  }
  if( g.bSqlOnly ){
    printf("/* %4d - %s%.*s */\n", iTestNum, zName, NAMEWIDTH-n, zDots);
  }else{
    printf("%4d - %s%.*s ", iTestNum, zName, NAMEWIDTH-n, zDots);
    fflush(stdout);
  }
  sqlite3_free(zName);
  g.nResult = 0;
  g.iStart = speedtest1_timestamp();
  g.x = 0xad131d0b;
  g.y = 0x44f9eac8;
}

/* Forward reference */
void speedtest1_exec(const char*,...);

/* Complete a test case */
void speedtest1_end_test(void){
  sqlite3_int64 iElapseTime = speedtest1_timestamp() - g.iStart;
  if( g.doCheckpoint ) speedtest1_exec("PRAGMA wal_checkpoint;");
  assert( iTestNumber > 0 );
  if( g.pScript ){
    fprintf(g.pScript,"-- end test %d\n", iTestNumber);
  }
  if( !g.bSqlOnly ){
    g.iTotal += iElapseTime;
    printf("%4d.%03ds\n", (int)(iElapseTime/1000), (int)(iElapseTime%1000));
  }
  if( g.pStmt ){
    sqlite3_finalize(g.pStmt);
    g.pStmt = 0;
  }
  iTestNumber = 0;
}

/* Report end of testing */
void speedtest1_final(void){
  if( !g.bSqlOnly ){
    printf("       TOTAL%.*s %4d.%03ds\n", NAMEWIDTH-5, zDots,
           (int)(g.iTotal/1000), (int)(g.iTotal%1000));
  }
  if( g.bVerify ){
#ifndef SPEEDTEST_OMIT_HASH
    int i;
#endif
    printf("Verification Hash: %llu ", g.nResByte);
#ifndef SPEEDTEST_OMIT_HASH
    HashUpdate((const unsigned char*)"\n", 1);
    HashFinal();
    for(i=0; i<24; i++){
      printf("%02x", g.hash.r[i]);
    }
    if( g.hashFile && g.hashFile!=stdout ) fclose(g.hashFile);
#endif
    printf("\n");
  }
}

/* Print an SQL statement to standard output */
static void printSql(const char *zSql){
  int n = (int)strlen(zSql);
  while( n>0 && (zSql[n-1]==';' || ISSPACE(zSql[n-1])) ){ n--; }
360
361
362
363
364
365
366




367

368
369
370
371
372
373



































374
375
376
377
378
379
380
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







+
+
+
+
-
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  va_start(ap, zFormat);
  zSql = sqlite3_vmprintf(zFormat, ap);
  va_end(ap);
  if( g.bSqlOnly ){
    printSql(zSql);
  }else{
    char *zErrMsg = 0;
    int rc;
    if( g.pScript ){
      fprintf(g.pScript,"%s;\n",zSql);
    }
    int rc = sqlite3_exec(g.db, zSql, 0, 0, &zErrMsg);
    rc = sqlite3_exec(g.db, zSql, 0, 0, &zErrMsg);
    if( zErrMsg ) fatal_error("SQL error: %s\n%s\n", zErrMsg, zSql);
    if( rc!=SQLITE_OK ) fatal_error("exec error: %s\n", sqlite3_errmsg(g.db));
  }
  sqlite3_free(zSql);
  speedtest1_shrink_memory();
}

/* Run SQL and return the first column of the first row as a string.  The
** returned string is obtained from sqlite_malloc() and must be freed by
** the caller.
*/
char *speedtest1_once(const char *zFormat, ...){
  va_list ap;
  char *zSql;
  sqlite3_stmt *pStmt;
  char *zResult = 0;
  va_start(ap, zFormat);
  zSql = sqlite3_vmprintf(zFormat, ap);
  va_end(ap);
  if( g.bSqlOnly ){
    printSql(zSql);
  }else{
    int rc = sqlite3_prepare_v2(g.db, zSql, -1, &pStmt, 0);
    if( rc ){
      fatal_error("SQL error: %s\n", sqlite3_errmsg(g.db));
    }
    if( g.pScript ){
      char *z = sqlite3_expanded_sql(pStmt);
      fprintf(g.pScript,"%s\n",z);
      sqlite3_free(z);
    }
    if( sqlite3_step(pStmt)==SQLITE_ROW ){
      const char *z = (const char*)sqlite3_column_text(pStmt, 0);
      if( z ) zResult = sqlite3_mprintf("%s", z);
    }
    sqlite3_finalize(pStmt);
  }
  sqlite3_free(zSql);
  speedtest1_shrink_memory();
  return zResult;
}

/* Prepare an SQL statement */
void speedtest1_prepare(const char *zFormat, ...){
  va_list ap;
  char *zSql;
  va_start(ap, zFormat);
  zSql = sqlite3_vmprintf(zFormat, ap);
394
395
396
397
398
399
400





401
402
403
404
405
406

































407
408
409
410
411
412
413
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







+
+
+
+
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








/* Run an SQL statement previously prepared */
void speedtest1_run(void){
  int i, n, len;
  if( g.bSqlOnly ) return;
  assert( g.pStmt );
  g.nResult = 0;
  if( g.pScript ){
    char *z = sqlite3_expanded_sql(g.pStmt);
    fprintf(g.pScript,"%s\n",z);
    sqlite3_free(z);
  }
  while( sqlite3_step(g.pStmt)==SQLITE_ROW ){
    n = sqlite3_column_count(g.pStmt);
    for(i=0; i<n; i++){
      const char *z = (const char*)sqlite3_column_text(g.pStmt, i);
      if( z==0 ) z = "nil";
      len = (int)strlen(z);
#ifndef SPEEDTEST_OMIT_HASH
      if( g.bVerify ){
        int eType = sqlite3_column_type(g.pStmt, i);
        unsigned char zPrefix[2];
        zPrefix[0] = '\n';
        zPrefix[1] = "-IFTBN"[eType];
        if( g.nResByte ){
          HashUpdate(zPrefix, 2);
        }else{
          HashUpdate(zPrefix+1, 1);
        }
        if( eType==SQLITE_FLOAT ){
          /* Omit the value of floating-point results from the verification
          ** hash.  The only thing we record is the fact that the result was
          ** a floating-point value. */
          g.nResByte += 2;
        }else if( eType==SQLITE_BLOB ){
          int nBlob = sqlite3_column_bytes(g.pStmt, i);
          int iBlob;
          unsigned char zChar[2];
          const unsigned char *aBlob = sqlite3_column_blob(g.pStmt, i);
          for(iBlob=0; iBlob<nBlob; iBlob++){
            zChar[0] = "0123456789abcdef"[aBlob[iBlob]>>4];
            zChar[1] = "0123456789abcdef"[aBlob[iBlob]&15];
            HashUpdate(zChar,2);
          }
          g.nResByte += nBlob*2 + 2;
        }else{
          HashUpdate((unsigned char*)z, len);
          g.nResByte += len + 2;
        }
      }
#endif
      if( g.nResult+len<sizeof(g.zResult)-2 ){
        if( g.nResult>0 ) g.zResult[g.nResult++] = ' ';
        memcpy(g.zResult + g.nResult, z, len+1);
        g.nResult += len;
      }
    }
  }
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
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







-
+

-
+
















-
+

-
+







  char zNum[2000];              /* A number name */

  sz = n = g.szTest*500;
  zNum[0] = 0;
  maxb = roundup_allones(sz);
  speedtest1_begin_test(100, "%d INSERTs into table with no index", n);
  speedtest1_exec("BEGIN");
  speedtest1_exec("CREATE%s TABLE t1(a INTEGER %s, b INTEGER %s, c TEXT %s);",
  speedtest1_exec("CREATE%s TABLE z1(a INTEGER %s, b INTEGER %s, c TEXT %s);",
                  isTemp(9), g.zNN, g.zNN, g.zNN);
  speedtest1_prepare("INSERT INTO t1 VALUES(?1,?2,?3); --  %d times", n);
  speedtest1_prepare("INSERT INTO z1 VALUES(?1,?2,?3); --  %d times", n);
  for(i=1; i<=n; i++){
    x1 = swizzle(i,maxb);
    speedtest1_numbername(x1, zNum, sizeof(zNum));
    sqlite3_bind_int64(g.pStmt, 1, (sqlite3_int64)x1);
    sqlite3_bind_int(g.pStmt, 2, i);
    sqlite3_bind_text(g.pStmt, 3, zNum, -1, SQLITE_STATIC);
    speedtest1_run();
  }
  speedtest1_exec("COMMIT");
  speedtest1_end_test();


  n = sz;
  speedtest1_begin_test(110, "%d ordered INSERTS with one index/PK", n);
  speedtest1_exec("BEGIN");
  speedtest1_exec(
     "CREATE%s TABLE t2(a INTEGER %s %s, b INTEGER %s, c TEXT %s) %s",
     "CREATE%s TABLE z2(a INTEGER %s %s, b INTEGER %s, c TEXT %s) %s",
     isTemp(5), g.zNN, g.zPK, g.zNN, g.zNN, g.zWR);
  speedtest1_prepare("INSERT INTO t2 VALUES(?1,?2,?3); -- %d times", n);
  speedtest1_prepare("INSERT INTO z2 VALUES(?1,?2,?3); -- %d times", n);
  for(i=1; i<=n; i++){
    x1 = swizzle(i,maxb);
    speedtest1_numbername(x1, zNum, sizeof(zNum));
    sqlite3_bind_int(g.pStmt, 1, i);
    sqlite3_bind_int64(g.pStmt, 2, (sqlite3_int64)x1);
    sqlite3_bind_text(g.pStmt, 3, zNum, -1, SQLITE_STATIC);
    speedtest1_run();
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
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







-
+



















-
+







                          0, groupStep, groupFinal);
#endif

  n = 25;
  speedtest1_begin_test(130, "%d SELECTS, numeric BETWEEN, unindexed", n);
  speedtest1_exec("BEGIN");
  speedtest1_prepare(
    "SELECT count(*), avg(b), sum(length(c)), group_concat(c) FROM t1\n"
    "SELECT count(*), avg(b), sum(length(c)), group_concat(c) FROM z1\n"
    " WHERE b BETWEEN ?1 AND ?2; -- %d times", n
  );
  for(i=1; i<=n; i++){
    if( (i-1)%g.nRepeat==0 ){
      x1 = speedtest1_random()%maxb;
      x2 = speedtest1_random()%10 + sz/5000 + x1;
    }
    sqlite3_bind_int(g.pStmt, 1, x1);
    sqlite3_bind_int(g.pStmt, 2, x2);
    speedtest1_run();
  }
  speedtest1_exec("COMMIT");
  speedtest1_end_test();


  n = 10;
  speedtest1_begin_test(140, "%d SELECTS, LIKE, unindexed", n);
  speedtest1_exec("BEGIN");
  speedtest1_prepare(
    "SELECT count(*), avg(b), sum(length(c)), group_concat(c) FROM t1\n"
    "SELECT count(*), avg(b), sum(length(c)), group_concat(c) FROM z1\n"
    " WHERE c LIKE ?1; -- %d times", n
  );
  for(i=1; i<=n; i++){
    if( (i-1)%g.nRepeat==0 ){
      x1 = speedtest1_random()%maxb;
      zNum[0] = '%';
      len = speedtest1_numbername(i, zNum+1, sizeof(zNum)-2);
635
636
637
638
639
640
641
642

643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663

664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686




687
688
689
690
691
692
693
694
695
696

697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716

717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736

737
738
739
740
741
742
743
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

900
901
902
903
904
905
906
907
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
935
936
937
938
939

940
941
942
943
944
945
946
947







-
+




















-
+



















-
-
-
-
+
+
+
+









-
+



















-
+



















-
+







  speedtest1_end_test();


  n = 10;
  speedtest1_begin_test(142, "%d SELECTS w/ORDER BY, unindexed", n);
  speedtest1_exec("BEGIN");
  speedtest1_prepare(
    "SELECT a, b, c FROM t1 WHERE c LIKE ?1\n"
    "SELECT a, b, c FROM z1 WHERE c LIKE ?1\n"
    " ORDER BY a; -- %d times", n
  );
  for(i=1; i<=n; i++){
    if( (i-1)%g.nRepeat==0 ){
      x1 = speedtest1_random()%maxb;
      zNum[0] = '%';
      len = speedtest1_numbername(i, zNum+1, sizeof(zNum)-2);
      zNum[len] = '%';
      zNum[len+1] = 0;
    }
    sqlite3_bind_text(g.pStmt, 1, zNum, len+1, SQLITE_STATIC);
    speedtest1_run();
  }
  speedtest1_exec("COMMIT");
  speedtest1_end_test();

  n = 10; /* g.szTest/5; */
  speedtest1_begin_test(145, "%d SELECTS w/ORDER BY and LIMIT, unindexed", n);
  speedtest1_exec("BEGIN");
  speedtest1_prepare(
    "SELECT a, b, c FROM t1 WHERE c LIKE ?1\n"
    "SELECT a, b, c FROM z1 WHERE c LIKE ?1\n"
    " ORDER BY a LIMIT 10; -- %d times", n
  );
  for(i=1; i<=n; i++){
    if( (i-1)%g.nRepeat==0 ){
      x1 = speedtest1_random()%maxb;
      zNum[0] = '%';
      len = speedtest1_numbername(i, zNum+1, sizeof(zNum)-2);
      zNum[len] = '%';
      zNum[len+1] = 0;
    }
    sqlite3_bind_text(g.pStmt, 1, zNum, len+1, SQLITE_STATIC);
    speedtest1_run();
  }
  speedtest1_exec("COMMIT");
  speedtest1_end_test();


  speedtest1_begin_test(150, "CREATE INDEX five times");
  speedtest1_exec("BEGIN;");
  speedtest1_exec("CREATE UNIQUE INDEX t1b ON t1(b);");
  speedtest1_exec("CREATE INDEX t1c ON t1(c);");
  speedtest1_exec("CREATE UNIQUE INDEX t2b ON t2(b);");
  speedtest1_exec("CREATE INDEX t2c ON t2(c DESC);");
  speedtest1_exec("CREATE UNIQUE INDEX t1b ON z1(b);");
  speedtest1_exec("CREATE INDEX t1c ON z1(c);");
  speedtest1_exec("CREATE UNIQUE INDEX t2b ON z2(b);");
  speedtest1_exec("CREATE INDEX t2c ON z2(c DESC);");
  speedtest1_exec("CREATE INDEX t3bc ON t3(b,c);");
  speedtest1_exec("COMMIT;");
  speedtest1_end_test();


  n = sz/5;
  speedtest1_begin_test(160, "%d SELECTS, numeric BETWEEN, indexed", n);
  speedtest1_exec("BEGIN");
  speedtest1_prepare(
    "SELECT count(*), avg(b), sum(length(c)), group_concat(a) FROM t1\n"
    "SELECT count(*), avg(b), sum(length(c)), group_concat(a) FROM z1\n"
    " WHERE b BETWEEN ?1 AND ?2; -- %d times", n
  );
  for(i=1; i<=n; i++){
    if( (i-1)%g.nRepeat==0 ){
      x1 = speedtest1_random()%maxb;
      x2 = speedtest1_random()%10 + sz/5000 + x1;
    }
    sqlite3_bind_int(g.pStmt, 1, x1);
    sqlite3_bind_int(g.pStmt, 2, x2);
    speedtest1_run();
  }
  speedtest1_exec("COMMIT");
  speedtest1_end_test();


  n = sz/5;
  speedtest1_begin_test(161, "%d SELECTS, numeric BETWEEN, PK", n);
  speedtest1_exec("BEGIN");
  speedtest1_prepare(
    "SELECT count(*), avg(b), sum(length(c)), group_concat(a) FROM t2\n"
    "SELECT count(*), avg(b), sum(length(c)), group_concat(a) FROM z2\n"
    " WHERE a BETWEEN ?1 AND ?2; -- %d times", n
  );
  for(i=1; i<=n; i++){
    if( (i-1)%g.nRepeat==0 ){
      x1 = speedtest1_random()%maxb;
      x2 = speedtest1_random()%10 + sz/5000 + x1;
    }
    sqlite3_bind_int(g.pStmt, 1, x1);
    sqlite3_bind_int(g.pStmt, 2, x2);
    speedtest1_run();
  }
  speedtest1_exec("COMMIT");
  speedtest1_end_test();


  n = sz/5;
  speedtest1_begin_test(170, "%d SELECTS, text BETWEEN, indexed", n);
  speedtest1_exec("BEGIN");
  speedtest1_prepare(
    "SELECT count(*), avg(b), sum(length(c)), group_concat(a) FROM t1\n"
    "SELECT count(*), avg(b), sum(length(c)), group_concat(a) FROM z1\n"
    " WHERE c BETWEEN ?1 AND (?1||'~'); -- %d times", n
  );
  for(i=1; i<=n; i++){
    if( (i-1)%g.nRepeat==0 ){
      x1 = swizzle(i, maxb);
      len = speedtest1_numbername(x1, zNum, sizeof(zNum)-1);
    }
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
959
960
961
962
963
964
965

966
967
968
969
970
971


972
973
974
975
976
977
978
979
980
981
982


983
984
985
986
987
988
989
990
991

992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008

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







-
+





-
-
+
+









-
-
+
+







-
+
















-
+










-
+




-
+








-
+







    "  a INTEGER %s %s,\n"
    "  b INTEGER %s,\n"
    "  c TEXT %s\n"
    ") %s",
    isTemp(1), g.zNN, g.zPK, g.zNN, g.zNN, g.zWR);
  speedtest1_exec("CREATE INDEX t4b ON t4(b)");
  speedtest1_exec("CREATE INDEX t4c ON t4(c)");
  speedtest1_exec("INSERT INTO t4 SELECT * FROM t1");
  speedtest1_exec("INSERT INTO t4 SELECT * FROM z1");
  speedtest1_exec("COMMIT");
  speedtest1_end_test();

  n = sz;
  speedtest1_begin_test(190, "DELETE and REFILL one table", n);
  speedtest1_exec("DELETE FROM t2;");
  speedtest1_exec("INSERT INTO t2 SELECT * FROM t1;");
  speedtest1_exec("DELETE FROM z2;");
  speedtest1_exec("INSERT INTO z2 SELECT * FROM z1;");
  speedtest1_end_test();


  speedtest1_begin_test(200, "VACUUM");
  speedtest1_exec("VACUUM");
  speedtest1_end_test();


  speedtest1_begin_test(210, "ALTER TABLE ADD COLUMN, and query");
  speedtest1_exec("ALTER TABLE t2 ADD COLUMN d DEFAULT 123");
  speedtest1_exec("SELECT sum(d) FROM t2");
  speedtest1_exec("ALTER TABLE z2 ADD COLUMN d INT DEFAULT 123");
  speedtest1_exec("SELECT sum(d) FROM z2");
  speedtest1_end_test();


  n = sz/5;
  speedtest1_begin_test(230, "%d UPDATES, numeric BETWEEN, indexed", n);
  speedtest1_exec("BEGIN");
  speedtest1_prepare(
    "UPDATE t2 SET d=b*2 WHERE b BETWEEN ?1 AND ?2; -- %d times", n
    "UPDATE z2 SET d=b*2 WHERE b BETWEEN ?1 AND ?2; -- %d times", n
  );
  for(i=1; i<=n; i++){
    x1 = speedtest1_random()%maxb;
    x2 = speedtest1_random()%10 + sz/5000 + x1;
    sqlite3_bind_int(g.pStmt, 1, x1);
    sqlite3_bind_int(g.pStmt, 2, x2);
    speedtest1_run();
  }
  speedtest1_exec("COMMIT");
  speedtest1_end_test();


  n = sz;
  speedtest1_begin_test(240, "%d UPDATES of individual rows", n);
  speedtest1_exec("BEGIN");
  speedtest1_prepare(
    "UPDATE t2 SET d=b*3 WHERE a=?1; -- %d times", n
    "UPDATE z2 SET d=b*3 WHERE a=?1; -- %d times", n
  );
  for(i=1; i<=n; i++){
    x1 = speedtest1_random()%sz + 1;
    sqlite3_bind_int(g.pStmt, 1, x1);
    speedtest1_run();
  }
  speedtest1_exec("COMMIT");
  speedtest1_end_test();

  speedtest1_begin_test(250, "One big UPDATE of the whole %d-row table", sz);
  speedtest1_exec("UPDATE t2 SET d=b*4");
  speedtest1_exec("UPDATE z2 SET d=b*4");
  speedtest1_end_test();


  speedtest1_begin_test(260, "Query added column after filling");
  speedtest1_exec("SELECT sum(d) FROM t2");
  speedtest1_exec("SELECT sum(d) FROM z2");
  speedtest1_end_test();



  n = sz/5;
  speedtest1_begin_test(270, "%d DELETEs, numeric BETWEEN, indexed", n);
  speedtest1_exec("BEGIN");
  speedtest1_prepare(
    "DELETE FROM t2 WHERE b BETWEEN ?1 AND ?2; -- %d times", n
    "DELETE FROM z2 WHERE b BETWEEN ?1 AND ?2; -- %d times", n
  );
  for(i=1; i<=n; i++){
    x1 = speedtest1_random()%maxb + 1;
    x2 = speedtest1_random()%10 + sz/5000 + x1;
    sqlite3_bind_int(g.pStmt, 1, x1);
    sqlite3_bind_int(g.pStmt, 2, x2);
    speedtest1_run();
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
900
901
902
903
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







-
-
+
+



-
-
-
-
-
+
+
+
+
+







-
+


-
-
+
+














-
-
+
+







    speedtest1_run();
  }
  speedtest1_exec("COMMIT");
  speedtest1_end_test();


  speedtest1_begin_test(290, "Refill two %d-row tables using REPLACE", sz);
  speedtest1_exec("REPLACE INTO t2(a,b,c) SELECT a,b,c FROM t1");
  speedtest1_exec("REPLACE INTO t3(a,b,c) SELECT a,b,c FROM t1");
  speedtest1_exec("REPLACE INTO z2(a,b,c) SELECT a,b,c FROM z1");
  speedtest1_exec("REPLACE INTO t3(a,b,c) SELECT a,b,c FROM z1");
  speedtest1_end_test();

  speedtest1_begin_test(300, "Refill a %d-row table using (b&1)==(a&1)", sz);
  speedtest1_exec("DELETE FROM t2;");
  speedtest1_exec("INSERT INTO t2(a,b,c)\n"
                  " SELECT a,b,c FROM t1  WHERE (b&1)==(a&1);");
  speedtest1_exec("INSERT INTO t2(a,b,c)\n"
                  " SELECT a,b,c FROM t1  WHERE (b&1)<>(a&1);");
  speedtest1_exec("DELETE FROM z2;");
  speedtest1_exec("INSERT INTO z2(a,b,c)\n"
                  " SELECT a,b,c FROM z1  WHERE (b&1)==(a&1);");
  speedtest1_exec("INSERT INTO z2(a,b,c)\n"
                  " SELECT a,b,c FROM z1  WHERE (b&1)<>(a&1);");
  speedtest1_end_test();


  n = sz/5;
  speedtest1_begin_test(310, "%d four-ways joins", n);
  speedtest1_exec("BEGIN");
  speedtest1_prepare(
    "SELECT t1.c FROM t1, t2, t3, t4\n"
    "SELECT z1.c FROM z1, z2, t3, t4\n"
    " WHERE t4.a BETWEEN ?1 AND ?2\n"
    "   AND t3.a=t4.b\n"
    "   AND t2.a=t3.b\n"
    "   AND t1.c=t2.c"
    "   AND z2.a=t3.b\n"
    "   AND z1.c=z2.c;"
  );
  for(i=1; i<=n; i++){
    x1 = speedtest1_random()%sz + 1;
    x2 = speedtest1_random()%10 + x1 + 4;
    sqlite3_bind_int(g.pStmt, 1, x1);
    sqlite3_bind_int(g.pStmt, 2, x2);
    speedtest1_run();
  }
  speedtest1_exec("COMMIT");
  speedtest1_end_test();

  speedtest1_begin_test(320, "subquery in result set", n);
  speedtest1_prepare(
    "SELECT sum(a), max(c),\n"
    "       avg((SELECT a FROM t2 WHERE 5+t2.b=t1.b) AND rowid<?1), max(c)\n"
    " FROM t1 WHERE rowid<?1;"
    "       avg((SELECT a FROM z2 WHERE 5+z2.b=z1.b) AND rowid<?1), max(c)\n"
    " FROM z1 WHERE rowid<?1;"
  );
  sqlite3_bind_int(g.pStmt, 1, est_square_root(g.szTest)*50);
  speedtest1_run();
  speedtest1_end_test();

  sz = n = g.szTest*700;
  zNum[0] = 0;
913
914
915
916
917
918
919









920
921
922
923
924
925



926
927
928
929
930
931
932
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







+
+
+
+
+
+
+
+
+






+
+
+







    sqlite3_bind_int(g.pStmt, 1, (sqlite3_int64)x1);
    sqlite3_bind_text(g.pStmt, 2, zNum, -1, SQLITE_STATIC);
    speedtest1_run();
  }
  speedtest1_exec("COMMIT");
  speedtest1_end_test();
  speedtest1_begin_test(410, "%d SELECTS on an IPK", n);
  if( g.doBigTransactions ){
    /* Historical note: tests 410 and 510 have historically not used
    ** explicit transactions. The --big-transactions flag was added
    ** 2022-09-08 to support the WASM/OPFS build, as the run-times
    ** approach 1 minute for each of these tests if they're not in an
    ** explicit transaction. The run-time effect of --big-transaciions
    ** on native builds is negligible. */
    speedtest1_exec("BEGIN");
  }
  speedtest1_prepare("SELECT b FROM t5 WHERE a=?1; --  %d times",n);
  for(i=1; i<=n; i++){
    x1 = swizzle(i,maxb);
    sqlite3_bind_int(g.pStmt, 1, (sqlite3_int64)x1);
    speedtest1_run();
  }
  if( g.doBigTransactions ){
    speedtest1_exec("COMMIT");
  }
  speedtest1_end_test();

  sz = n = g.szTest*700;
  zNum[0] = 0;
  maxb = roundup_allones(sz/3);
  speedtest1_begin_test(500, "%d REPLACE on TEXT PK", n);
  speedtest1_exec("BEGIN");
940
941
942
943
944
945
946




947
948
949
950
951
952
953



954
955
956
957
958
959
960
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







+
+
+
+







+
+
+







    sqlite3_bind_int(g.pStmt, 2, i);
    sqlite3_bind_text(g.pStmt, 1, zNum, -1, SQLITE_STATIC);
    speedtest1_run();
  }
  speedtest1_exec("COMMIT");
  speedtest1_end_test();
  speedtest1_begin_test(510, "%d SELECTS on a TEXT PK", n);
  if( g.doBigTransactions ){
    /* See notes for test 410. */
    speedtest1_exec("BEGIN");
  }
  speedtest1_prepare("SELECT b FROM t6 WHERE a=?1; --  %d times",n);
  for(i=1; i<=n; i++){
    x1 = swizzle(i,maxb);
    speedtest1_numbername(x1, zNum, sizeof(zNum));
    sqlite3_bind_text(g.pStmt, 1, zNum, -1, SQLITE_STATIC);
    speedtest1_run();
  }
  if( g.doBigTransactions ){
    speedtest1_exec("COMMIT");
  }
  speedtest1_end_test();
  speedtest1_begin_test(520, "%d SELECT DISTINCT", n);
  speedtest1_exec("SELECT DISTINCT b FROM t5;");
  speedtest1_exec("SELECT DISTINCT b FROM t6;");
  speedtest1_end_test();


1107
1108
1109
1110
1111
1112
1113
1114
1115


1116
1117

1118
1119
1120
1121
1122
1123
1124
1330
1331
1332
1333
1334
1335
1336


1337
1338
1339

1340
1341
1342
1343
1344
1345
1346
1347







-
-
+
+

-
+







  speedtest1_run();
  speedtest1_end_test();

  nElem = 10000*g.szTest;
  speedtest1_begin_test(400, "EXCEPT operator on %d-element tables", nElem);
  speedtest1_prepare(
    "WITH RECURSIVE \n"
    "  t1(x) AS (VALUES(2) UNION ALL SELECT x+2 FROM t1 WHERE x<%d),\n"
    "  t2(y) AS (VALUES(3) UNION ALL SELECT y+3 FROM t2 WHERE y<%d)\n"
    "  z1(x) AS (VALUES(2) UNION ALL SELECT x+2 FROM z1 WHERE x<%d),\n"
    "  z2(y) AS (VALUES(3) UNION ALL SELECT y+3 FROM z2 WHERE y<%d)\n"
    "SELECT count(x), avg(x) FROM (\n"
    "  SELECT x FROM t1 EXCEPT SELECT y FROM t2 ORDER BY 1\n"
    "  SELECT x FROM z1 EXCEPT SELECT y FROM z2 ORDER BY 1\n"
    ");",
    nElem, nElem
  );
  speedtest1_run();
  speedtest1_end_test();
}

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
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
1430
1431
1432
1433
1434
1435
1436







-
+

-
+












-
+











-
-
-
+
+
+





-
+








+
+
+
+
+
+
+
+
+
+
+
+
+







  int i;
  char zFP1[100];
  char zFP2[100];
  
  n = g.szTest*5000;
  speedtest1_begin_test(100, "Fill a table with %d FP values", n*2);
  speedtest1_exec("BEGIN");
  speedtest1_exec("CREATE%s TABLE t1(a REAL %s, b REAL %s);",
  speedtest1_exec("CREATE%s TABLE z1(a REAL %s, b REAL %s);",
                  isTemp(1), g.zNN, g.zNN);
  speedtest1_prepare("INSERT INTO t1 VALUES(?1,?2); -- %d times", n);
  speedtest1_prepare("INSERT INTO z1 VALUES(?1,?2); -- %d times", n);
  for(i=1; i<=n; i++){
    speedtest1_random_ascii_fp(zFP1);
    speedtest1_random_ascii_fp(zFP2);
    sqlite3_bind_text(g.pStmt, 1, zFP1, -1, SQLITE_STATIC);
    sqlite3_bind_text(g.pStmt, 2, zFP2, -1, SQLITE_STATIC);
    speedtest1_run();
  }
  speedtest1_exec("COMMIT");
  speedtest1_end_test();

  n = g.szTest/25 + 2;
  speedtest1_begin_test(110, "%d range queries", n);
  speedtest1_prepare("SELECT sum(b) FROM t1 WHERE a BETWEEN ?1 AND ?2");
  speedtest1_prepare("SELECT sum(b) FROM z1 WHERE a BETWEEN ?1 AND ?2");
  for(i=1; i<=n; i++){
    speedtest1_random_ascii_fp(zFP1);
    speedtest1_random_ascii_fp(zFP2);
    sqlite3_bind_text(g.pStmt, 1, zFP1, -1, SQLITE_STATIC);
    sqlite3_bind_text(g.pStmt, 2, zFP2, -1, SQLITE_STATIC);
    speedtest1_run();
  }
  speedtest1_end_test();

  speedtest1_begin_test(120, "CREATE INDEX three times");
  speedtest1_exec("BEGIN;");
  speedtest1_exec("CREATE INDEX t1a ON t1(a);");
  speedtest1_exec("CREATE INDEX t1b ON t1(b);");
  speedtest1_exec("CREATE INDEX t1ab ON t1(a,b);");
  speedtest1_exec("CREATE INDEX t1a ON z1(a);");
  speedtest1_exec("CREATE INDEX t1b ON z1(b);");
  speedtest1_exec("CREATE INDEX t1ab ON z1(a,b);");
  speedtest1_exec("COMMIT;");
  speedtest1_end_test();

  n = g.szTest/3 + 2;
  speedtest1_begin_test(130, "%d indexed range queries", n);
  speedtest1_prepare("SELECT sum(b) FROM t1 WHERE a BETWEEN ?1 AND ?2");
  speedtest1_prepare("SELECT sum(b) FROM z1 WHERE a BETWEEN ?1 AND ?2");
  for(i=1; i<=n; i++){
    speedtest1_random_ascii_fp(zFP1);
    speedtest1_random_ascii_fp(zFP2);
    sqlite3_bind_text(g.pStmt, 1, zFP1, -1, SQLITE_STATIC);
    sqlite3_bind_text(g.pStmt, 2, zFP2, -1, SQLITE_STATIC);
    speedtest1_run();
  }
  speedtest1_end_test();

  n = g.szTest*5000;
  speedtest1_begin_test(140, "%d calls to round()", n);
  speedtest1_exec("SELECT sum(round(a,2)+round(b,4)) FROM z1;");
  speedtest1_end_test();


  speedtest1_begin_test(150, "%d printf() calls", n*4);
  speedtest1_exec(
    "WITH c(fmt) AS (VALUES('%%g'),('%%e'),('%%!g'),('%%.20f'))"
    "SELECT sum(printf(fmt,a)) FROM z1, c"
  );
  speedtest1_end_test();
}

#ifdef SQLITE_ENABLE_RTREE
/* Generate two numbers between 1 and mx.  The first number is less than
** the second.  Usually the numbers are near each other but can sometimes
** be far apart.
*/
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
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







-
-
+
+

















-
+







    sqlite3_bind_int(g.pStmt, 7, z1);
    speedtest1_run();
  }
  speedtest1_exec("COMMIT");
  speedtest1_end_test();

  speedtest1_begin_test(101, "Copy from rtree to a regular table");
  speedtest1_exec("CREATE TABLE t1(id INTEGER PRIMARY KEY,x0,x1,y0,y1,z0,z1)");
  speedtest1_exec("INSERT INTO t1 SELECT * FROM rt1");
  speedtest1_exec("CREATE TABLE z1(id INTEGER PRIMARY KEY,x0,x1,y0,y1,z0,z1)");
  speedtest1_exec("INSERT INTO z1 SELECT * FROM rt1");
  speedtest1_end_test();

  n = g.szTest*200;
  speedtest1_begin_test(110, "%d one-dimensional intersect slice queries", n);
  speedtest1_prepare("SELECT count(*) FROM rt1 WHERE x0>=?1 AND x1<=?2");
  iStep = mxCoord/n;
  for(i=0; i<n; i++){
    sqlite3_bind_int(g.pStmt, 1, i*iStep);
    sqlite3_bind_int(g.pStmt, 2, (i+1)*iStep);
    speedtest1_run();
    aCheck[i] = atoi(g.zResult);
  }
  speedtest1_end_test();

  if( g.bVerify ){
    n = g.szTest*200;
    speedtest1_begin_test(111, "Verify result from 1-D intersect slice queries");
    speedtest1_prepare("SELECT count(*) FROM t1 WHERE x0>=?1 AND x1<=?2");
    speedtest1_prepare("SELECT count(*) FROM z1 WHERE x0>=?1 AND x1<=?2");
    iStep = mxCoord/n;
    for(i=0; i<n; i++){
      sqlite3_bind_int(g.pStmt, 1, i*iStep);
      sqlite3_bind_int(g.pStmt, 2, (i+1)*iStep);
      speedtest1_run();
      if( aCheck[i]!=atoi(g.zResult) ){
        fatal_error("Count disagree step %d: %d..%d.  %d vs %d",
1318
1319
1320
1321
1322
1323
1324
1325

1326
1327
1328
1329
1330
1331
1332
1554
1555
1556
1557
1558
1559
1560

1561
1562
1563
1564
1565
1566
1567
1568







-
+







    aCheck[i] = atoi(g.zResult);
  }
  speedtest1_end_test();

  if( g.bVerify ){
    n = g.szTest*200;
    speedtest1_begin_test(121, "Verify result from 1-D overlap slice queries");
    speedtest1_prepare("SELECT count(*) FROM t1 WHERE y1>=?1 AND y0<=?2");
    speedtest1_prepare("SELECT count(*) FROM z1 WHERE y1>=?1 AND y0<=?2");
    iStep = mxCoord/n;
    for(i=0; i<n; i++){
      sqlite3_bind_int(g.pStmt, 1, i*iStep);
      sqlite3_bind_int(g.pStmt, 2, (i+1)*iStep);
      speedtest1_run();
      if( aCheck[i]!=atoi(g.zResult) ){
        fatal_error("Count disagree step %d: %d..%d.  %d vs %d",
1414
1415
1416
1417
1418
1419
1420
1421

1422
1423
1424
1425
1426
1427
1428
1650
1651
1652
1653
1654
1655
1656

1657
1658
1659
1660
1661
1662
1663
1664







-
+







    sqlite3_bind_int(g.pStmt, 1, i*iStep);
    speedtest1_run();
    aCheck[i] = atoi(g.zResult);
  }
  speedtest1_end_test();

  speedtest1_begin_test(170, "Restore deleted entries using INSERT OR IGNORE");
  speedtest1_exec("INSERT OR IGNORE INTO rt1 SELECT * FROM t1");
  speedtest1_exec("INSERT OR IGNORE INTO rt1 SELECT * FROM z1");
  speedtest1_end_test();
}
#endif /* SQLITE_ENABLE_RTREE */

/*
** A testset that does key/value storage on tables with many columns.
** This is the kind of workload generated by ORMs such as CoreData.
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
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







-
-
+
+

-
-
+
+













-
-
+
+






-
+






-
+







  char zNum[2000];              /* A number name */

  const int NROW  = 500*g.szTest;
  const int NROW2 = 100*g.szTest;

  speedtest1_exec(
      "BEGIN;"
      "CREATE TABLE t1(rowid INTEGER PRIMARY KEY, i INTEGER, t TEXT);"
      "CREATE TABLE t2(rowid INTEGER PRIMARY KEY, i INTEGER, t TEXT);"
      "CREATE TABLE z1(rowid INTEGER PRIMARY KEY, i INTEGER, t TEXT);"
      "CREATE TABLE z2(rowid INTEGER PRIMARY KEY, i INTEGER, t TEXT);"
      "CREATE TABLE t3(rowid INTEGER PRIMARY KEY, i INTEGER, t TEXT);"
      "CREATE VIEW v1 AS SELECT rowid, i, t FROM t1;"
      "CREATE VIEW v2 AS SELECT rowid, i, t FROM t2;"
      "CREATE VIEW v1 AS SELECT rowid, i, t FROM z1;"
      "CREATE VIEW v2 AS SELECT rowid, i, t FROM z2;"
      "CREATE VIEW v3 AS SELECT rowid, i, t FROM t3;"
  );
  for(jj=1; jj<=3; jj++){
    speedtest1_prepare("INSERT INTO t%d VALUES(NULL,?1,?2)", jj);
    for(ii=0; ii<NROW; ii++){
      int x1 = speedtest1_random() % NROW;
      speedtest1_numbername(x1, zNum, sizeof(zNum));
      sqlite3_bind_int(g.pStmt, 1, x1);
      sqlite3_bind_text(g.pStmt, 2, zNum, -1, SQLITE_STATIC);
      speedtest1_run();
    }
  }
  speedtest1_exec(
      "CREATE INDEX i1 ON t1(t);"
      "CREATE INDEX i2 ON t2(t);"
      "CREATE INDEX i1 ON z1(t);"
      "CREATE INDEX i2 ON z2(t);"
      "CREATE INDEX i3 ON t3(t);"
      "COMMIT;"
  );

  speedtest1_begin_test(100, "speed4p-join1");
  speedtest1_prepare(
      "SELECT * FROM t1, t2, t3 WHERE t1.oid = t2.oid AND t2.oid = t3.oid"
      "SELECT * FROM z1, z2, t3 WHERE z1.oid = z2.oid AND z2.oid = t3.oid"
  );
  speedtest1_run();
  speedtest1_end_test();

  speedtest1_begin_test(110, "speed4p-join2");
  speedtest1_prepare(
      "SELECT * FROM t1, t2, t3 WHERE t1.t = t2.t AND t2.t = t3.t"
      "SELECT * FROM z1, z2, t3 WHERE z1.t = z2.t AND z2.t = t3.t"
  );
  speedtest1_run();
  speedtest1_end_test();

  speedtest1_begin_test(120, "speed4p-view1");
  for(jj=1; jj<=3; jj++){
    speedtest1_prepare("SELECT * FROM v%d WHERE rowid = ?", jj);
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
2005
2006
2007
2008
2009
2010
2011


2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023

2024
2025
2026
2027
2028
2029
2030
2031
2032
2033

2034
2035
2036
2037
2038
2039
2040
2041







-
-
+
+










-
+









-
+







      speedtest1_run();
    }
  }
  speedtest1_end_test();

  speedtest1_begin_test(150, "speed4p-subselect1");
  speedtest1_prepare("SELECT "
      "(SELECT t FROM t1 WHERE rowid = ?1),"
      "(SELECT t FROM t2 WHERE rowid = ?1),"
      "(SELECT t FROM z1 WHERE rowid = ?1),"
      "(SELECT t FROM z2 WHERE rowid = ?1),"
      "(SELECT t FROM t3 WHERE rowid = ?1)"
  );
  for(jj=0; jj<NROW2; jj++){
    sqlite3_bind_int(g.pStmt, 1, jj*3);
    speedtest1_run();
  }
  speedtest1_end_test();

  speedtest1_begin_test(160, "speed4p-rowid-update");
  speedtest1_exec("BEGIN");
  speedtest1_prepare("UPDATE t1 SET i=i+1 WHERE rowid=?1");
  speedtest1_prepare("UPDATE z1 SET i=i+1 WHERE rowid=?1");
  for(jj=0; jj<NROW2; jj++){
    sqlite3_bind_int(g.pStmt, 1, jj);
    speedtest1_run();
  }
  speedtest1_exec("COMMIT");
  speedtest1_end_test();

  speedtest1_exec("CREATE TABLE t5(t TEXT PRIMARY KEY, i INTEGER);");
  speedtest1_begin_test(170, "speed4p-insert-ignore");
  speedtest1_exec("INSERT OR IGNORE INTO t5 SELECT t, i FROM t1");
  speedtest1_exec("INSERT OR IGNORE INTO t5 SELECT t, i FROM z1");
  speedtest1_end_test();

  speedtest1_exec(
      "CREATE TABLE log(op TEXT, r INTEGER, i INTEGER, t TEXT);"
      "CREATE TABLE t4(rowid INTEGER PRIMARY KEY, i INTEGER, t TEXT);"
      "CREATE TRIGGER t4_trigger1 AFTER INSERT ON t4 BEGIN"
      "  INSERT INTO log VALUES('INSERT INTO t4', new.rowid, new.i, new.t);"
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
1984
1985
1986
1987
1988













1989
1990

1991
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
2017
2018
2019
2020
2021
2022

2023
2024
2025

2026
2027
2028

2029
2030
2031


2032
2033
2034
2035
2036
2037
2038
2039
2040

2041
2042


2043
2044
2045
2046
2047
2048


















2049
2050
2051

2052
2053
2054
2055
2056
2057
2058
2059
2060


2061
2062
2063
2064
2065
2066
2067
2068
2069







2070
2071
2072
2073
2074
2075

2076
2077
2078
2079
2080

2081
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
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199

2200
2201
2202
2203
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
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245

2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263



2264
2265
2266
2267
2268
2269
2270
2271
2272
2273

2274
2275
2276
2277
2278
2279
2280

2281
2282
2283

2284
2285
2286

2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300

2301
2302
2303
2304
2305
2306
2307
2308
2309


2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329

2330
2331
2332
2333
2334
2335
2336
2337


2338
2339

2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359

2360
2361
2362
2363
2364

2365
2366
2367
2368
2369
2370
2371

2372
2373
2374
2375
2376

2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399

2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424

2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446

2447
2448
2449
2450
2451
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
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492







+
+
+
+





-
















+
+
+
-
+
+











+
+
+
+
+
+
+
+
+
+
+
+
+

-
+














+
+

-
-
-
+
+


+
+




-
+






-
+


-
+


-
+



+
+








-
+


+
+




-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+







-
-
+
+
-








+
+
+
+
+
+
+





-
+




-
+






-
+




-
+







+
+
+
+
+
+
+
+
+

+
+
+
+
+
-
+
+

+
+
+
+
+
+
+
+














-
+




















+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+
+





-
+



+
+
+






+
+
+







  fclose(in);
}   
#endif

#if SQLITE_VERSION_NUMBER<3006018
#  define sqlite3_sourceid(X) "(before 3.6.18)"
#endif

#if SQLITE_CKSUMVFS_STATIC
int sqlite3_register_cksumvfs(const char*);
#endif

static int xCompileOptions(void *pCtx, int nVal, char **azVal, char **azCol){
  printf("-- Compile option: %s\n", azVal[0]);
  return SQLITE_OK;
}

int main(int argc, char **argv){
  int doAutovac = 0;            /* True for --autovacuum */
  int cacheSize = 0;            /* Desired cache size.  0 means default */
  int doExclusive = 0;          /* True for --exclusive */
  int nHeap = 0, mnHeap = 0;    /* Heap size from --heap */
  int doIncrvac = 0;            /* True for --incrvacuum */
  const char *zJMode = 0;       /* Journal mode */
  const char *zKey = 0;         /* Encryption key */
  int nLook = -1, szLook = 0;   /* --lookaside configuration */
  int noSync = 0;               /* True for --nosync */
  int pageSize = 0;             /* Desired page size.  0 means default */
  int nPCache = 0, szPCache = 0;/* --pcache configuration */
  int doPCache = 0;             /* True if --pcache is seen */
  int showStats = 0;            /* True for --stats */
  int nThread = 0;              /* --threads value */
  int mmapSize = 0;             /* How big of a memory map to use */
  int memDb = 0;                /* --memdb.  Use an in-memory database */
  int openFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE
    ;                           /* SQLITE_OPEN_xxx flags. */
  const char *zTSet = "main";   /* Which --testset torun */
  char *zTSet = "main";         /* Which --testset torun */
  const char * zVfs = 0;        /* --vfs NAME */
  int doTrace = 0;              /* True for --trace */
  const char *zEncoding = 0;    /* --utf16be or --utf16le */
  const char *zDbName = 0;      /* Name of the test database */

  void *pHeap = 0;              /* Allocated heap space */
  void *pLook = 0;              /* Allocated lookaside space */
  void *pPCache = 0;            /* Allocated storage for pcache */
  int iCur, iHi;                /* Stats values, current and "highwater" */
  int i;                        /* Loop counter */
  int rc;                       /* API return code */

#ifdef SQLITE_SPEEDTEST1_WASM
  /* Resetting all state is important for the WASM build, which may
  ** call main() multiple times. */
  memset(&g, 0, sizeof(g));
  iTestNumber = 0;
#endif
#ifdef SQLITE_CKSUMVFS_STATIC
  sqlite3_register_cksumvfs(0);
#endif
  /*
  ** Confirms that argc has at least N arguments following argv[i]. */
#define ARGC_VALUE_CHECK(N)                                       \
  if( i>=argc-(N) ) fatal_error("missing argument on %s\n", argv[i])
  /* Display the version of SQLite being tested */
  printf("-- Speedtest1 for SQLite %s %.50s\n",
  printf("-- Speedtest1 for SQLite %s %.48s\n",
         sqlite3_libversion(), sqlite3_sourceid());

  /* Process command-line arguments */
  g.zWR = "";
  g.zNN = "";
  g.zPK = "UNIQUE";
  g.szTest = 100;
  g.nRepeat = 1;
  for(i=1; i<argc; i++){
    const char *z = argv[i];
    if( z[0]=='-' ){
      do{ z++; }while( z[0]=='-' );
      if( strcmp(z,"autovacuum")==0 ){
        doAutovac = 1;
      }else if( strcmp(z,"big-transactions")==0 ){
        g.doBigTransactions = 1;
      }else if( strcmp(z,"cachesize")==0 ){
        if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
        i++;
        cacheSize = integerValue(argv[i]);
        ARGC_VALUE_CHECK(1);
        cacheSize = integerValue(argv[++i]);
      }else if( strcmp(z,"exclusive")==0 ){
        doExclusive = 1;
      }else if( strcmp(z,"checkpoint")==0 ){
        g.doCheckpoint = 1;
      }else if( strcmp(z,"explain")==0 ){
        g.bSqlOnly = 1;
        g.bExplain = 1;
      }else if( strcmp(z,"heap")==0 ){
        if( i>=argc-2 ) fatal_error("missing arguments on %s\n", argv[i]);
        ARGC_VALUE_CHECK(2);
        nHeap = integerValue(argv[i+1]);
        mnHeap = integerValue(argv[i+2]);
        i += 2;
      }else if( strcmp(z,"incrvacuum")==0 ){
        doIncrvac = 1;
      }else if( strcmp(z,"journal")==0 ){
        if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
        ARGC_VALUE_CHECK(1);
        zJMode = argv[++i];
      }else if( strcmp(z,"key")==0 ){
        if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
        ARGC_VALUE_CHECK(1);
        zKey = argv[++i];
      }else if( strcmp(z,"lookaside")==0 ){
        if( i>=argc-2 ) fatal_error("missing arguments on %s\n", argv[i]);
        ARGC_VALUE_CHECK(2);
        nLook = integerValue(argv[i+1]);
        szLook = integerValue(argv[i+2]);
        i += 2;
      }else if( strcmp(z,"memdb")==0 ){
        memDb = 1;
#if SQLITE_VERSION_NUMBER>=3006000
      }else if( strcmp(z,"multithread")==0 ){
        sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
      }else if( strcmp(z,"nomemstat")==0 ){
        sqlite3_config(SQLITE_CONFIG_MEMSTATUS, 0);
#endif
#if SQLITE_VERSION_NUMBER>=3007017
      }else if( strcmp(z, "mmap")==0 ){
        if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
        ARGC_VALUE_CHECK(1);
        mmapSize = integerValue(argv[++i]);
 #endif
      }else if( strcmp(z,"nomutex")==0 ){
        openFlags |= SQLITE_OPEN_NOMUTEX;
      }else if( strcmp(z,"nosync")==0 ){
        noSync = 1;
      }else if( strcmp(z,"notnull")==0 ){
        g.zNN = "NOT NULL";
      }else if( strcmp(z,"pagesize")==0 ){
        if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
      }else if( strcmp(z,"output")==0 ){
#ifdef SPEEDTEST_OMIT_HASH
        fatal_error("The --output option is not supported with"
                    " -DSPEEDTEST_OMIT_HASH\n");
#else
        ARGC_VALUE_CHECK(1);
        i++;
        if( strcmp(argv[i],"-")==0 ){
          g.hashFile = stdout;
        }else{
          g.hashFile = fopen(argv[i], "wb");
          if( g.hashFile==0 ){
            fatal_error("cannot open \"%s\" for writing\n", argv[i]);
          }
        }
#endif
      }else if( strcmp(z,"pagesize")==0 ){
        ARGC_VALUE_CHECK(1);
        pageSize = integerValue(argv[++i]);
      }else if( strcmp(z,"pcache")==0 ){
        if( i>=argc-2 ) fatal_error("missing arguments on %s\n", argv[i]);
        ARGC_VALUE_CHECK(2);
        nPCache = integerValue(argv[i+1]);
        szPCache = integerValue(argv[i+2]);
        doPCache = 1;
        i += 2;
      }else if( strcmp(z,"primarykey")==0 ){
        g.zPK = "PRIMARY KEY";
      }else if( strcmp(z,"repeat")==0 ){
        if( i>=argc-1 ) fatal_error("missing arguments on %s\n", argv[i]);
        g.nRepeat = integerValue(argv[i+1]);
        ARGC_VALUE_CHECK(1);
        g.nRepeat = integerValue(argv[++i]);
        i += 1;
      }else if( strcmp(z,"reprepare")==0 ){
        g.bReprepare = 1;
#if SQLITE_VERSION_NUMBER>=3006000
      }else if( strcmp(z,"serialized")==0 ){
        sqlite3_config(SQLITE_CONFIG_SERIALIZED);
      }else if( strcmp(z,"singlethread")==0 ){
        sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);
#endif
      }else if( strcmp(z,"script")==0 ){
        ARGC_VALUE_CHECK(1);
        if( g.pScript ) fclose(g.pScript);
        g.pScript = fopen(argv[++i], "wb");
        if( g.pScript==0 ){
          fatal_error("unable to open output file \"%s\"\n", argv[i]);
        }
      }else if( strcmp(z,"sqlonly")==0 ){
        g.bSqlOnly = 1;
      }else if( strcmp(z,"shrink-memory")==0 ){
        g.bMemShrink = 1;
      }else if( strcmp(z,"size")==0 ){
        if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
        ARGC_VALUE_CHECK(1);
        g.szTest = integerValue(argv[++i]);
      }else if( strcmp(z,"stats")==0 ){
        showStats = 1;
      }else if( strcmp(z,"temp")==0 ){
        if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
        ARGC_VALUE_CHECK(1);
        i++;
        if( argv[i][0]<'0' || argv[i][0]>'9' || argv[i][1]!=0 ){
          fatal_error("argument to --temp should be integer between 0 and 9");
        }
        g.eTemp = argv[i][0] - '0';
      }else if( strcmp(z,"testset")==0 ){
        if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
        ARGC_VALUE_CHECK(1);
        zTSet = argv[++i];
      }else if( strcmp(z,"trace")==0 ){
        doTrace = 1;
      }else if( strcmp(z,"threads")==0 ){
        if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
        ARGC_VALUE_CHECK(1);
        nThread = integerValue(argv[++i]);
      }else if( strcmp(z,"utf16le")==0 ){
        zEncoding = "utf16le";
      }else if( strcmp(z,"utf16be")==0 ){
        zEncoding = "utf16be";
      }else if( strcmp(z,"verify")==0 ){
        g.bVerify = 1;
#ifndef SPEEDTEST_OMIT_HASH
        HashInit();
#endif
      }else if( strcmp(z,"vfs")==0 ){
        ARGC_VALUE_CHECK(1);
        zVfs = argv[++i];
      }else if( strcmp(z,"reserve")==0 ){
        ARGC_VALUE_CHECK(1);
        g.nReserve = atoi(argv[++i]);
      }else if( strcmp(z,"without-rowid")==0 ){
        if( strstr(g.zWR,"WITHOUT")!=0 ){
          /* no-op */
        }else if( strstr(g.zWR,"STRICT")!=0 ){
          g.zWR = "WITHOUT ROWID,STRICT";
        }else{
        g.zWR = "WITHOUT ROWID";
          g.zWR = "WITHOUT ROWID";
        }
        g.zPK = "PRIMARY KEY";
      }else if( strcmp(z,"strict")==0 ){
        if( strstr(g.zWR,"STRICT")!=0 ){
          /* no-op */
        }else if( strstr(g.zWR,"WITHOUT")!=0 ){
          g.zWR = "WITHOUT ROWID,STRICT";
        }else{
          g.zWR = "STRICT";
        }
      }else if( strcmp(z, "help")==0 || strcmp(z,"?")==0 ){
        printf(zHelp, argv[0]);
        exit(0);
      }else{
        fatal_error("unknown option: %s\nUse \"%s -?\" for help\n",
                    argv[i], argv[0]);
      }
    }else if( zDbName==0 ){
      zDbName = argv[i];
    }else{
      fatal_error("surplus argument: %s\nUse \"%s -?\" for help\n",
                  argv[i], argv[0]);
    }
  }
  if( zDbName!=0 ) unlink(zDbName);
#undef ARGC_VALUE_CHECK
#if SQLITE_VERSION_NUMBER>=3006001
  if( nHeap>0 ){
    pHeap = malloc( nHeap );
    if( pHeap==0 ) fatal_error("cannot allocate %d-byte heap\n", nHeap);
    rc = sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nHeap, mnHeap);
    if( rc ) fatal_error("heap configuration failed: %d\n", rc);
  }
  if( doPCache ){
    if( nPCache>0 && szPCache>0 ){
      pPCache = malloc( nPCache*(sqlite3_int64)szPCache );
      if( pPCache==0 ) fatal_error("cannot allocate %lld-byte pcache\n",
                                   nPCache*(sqlite3_int64)szPCache);
    }
    rc = sqlite3_config(SQLITE_CONFIG_PAGECACHE, pPCache, szPCache, nPCache);
    if( rc ) fatal_error("pcache configuration failed: %d\n", rc);
  }
  if( nLook>=0 ){
    sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 0, 0);
  }
#endif
  sqlite3_initialize();
 

  if( zDbName!=0 ){
    sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs);
    /* For some VFSes, e.g. opfs, unlink() is not sufficient. Use the
    ** selected (or default) VFS's xDelete method to delete the
    ** database. This is specifically important for the "opfs" VFS
    ** when running from a WASM build of speedtest1, so that the db
    ** can be cleaned up properly. For historical compatibility, we'll
    ** also simply unlink(). */
    if( pVfs!=0 ){
      pVfs->xDelete(pVfs, zDbName, 1);
    }
    unlink(zDbName);
  }

  /* Open the database and the input file */
  if( sqlite3_open(zDbName, &g.db) ){
  if( sqlite3_open_v2(memDb ? ":memory:" : zDbName, &g.db,
                      openFlags, zVfs) ){
    fatal_error("Cannot open database file: %s\n", zDbName);
  }
#if SQLITE_VERSION_NUMBER>=3006001
  if( nLook>0 && szLook>0 ){
    pLook = malloc( nLook*szLook );
    rc = sqlite3_db_config(g.db, SQLITE_DBCONFIG_LOOKASIDE, pLook, szLook,nLook);
    rc = sqlite3_db_config(g.db, SQLITE_DBCONFIG_LOOKASIDE,pLook,szLook,nLook);
    if( rc ) fatal_error("lookaside configuration failed: %d\n", rc);
  }
#endif
  if( g.nReserve>0 ){
    sqlite3_file_control(g.db, 0, SQLITE_FCNTL_RESERVE_BYTES, &g.nReserve);
  }

  /* Set database connection options */
  sqlite3_create_function(g.db, "random", 0, SQLITE_UTF8, 0, randomFunc, 0, 0);
#ifndef SQLITE_OMIT_DEPRECATED
  if( doTrace ) sqlite3_trace(g.db, traceCallback, 0);
#endif
  if( memDb>0 ){
    speedtest1_exec("PRAGMA temp_store=memory");
  }
  if( mmapSize>0 ){
    speedtest1_exec("PRAGMA mmap_size=%d", mmapSize);
  }
  speedtest1_exec("PRAGMA threads=%d", nThread);
  if( zKey ){
    speedtest1_exec("PRAGMA key('%s')", zKey);
  }
2179
2180
2181
2182
2183
2184
2185












2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198













2199
2200

2201
2202
2203


2204
2205
2206
2207
2208
2209































2210
2211
2212
2213
2214
2215
2216
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527













2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541

2542
2543


2544
2545
2546





2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584







+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+

-
-
+
+

-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    speedtest1_exec("PRAGMA locking_mode=EXCLUSIVE");
  }
  if( zJMode ){
    speedtest1_exec("PRAGMA journal_mode=%s", zJMode);
  }

  if( g.bExplain ) printf(".explain\n.echo on\n");
  do{
    char *zThisTest = zTSet;
    char *zComma = strchr(zThisTest,',');
    if( zComma ){
      *zComma = 0;
      zTSet = zComma+1;
    }else{
      zTSet = "";
    }
    if( g.iTotal>0 || zComma!=0 ){
      printf("       Begin testset \"%s\"\n", zThisTest);
    }
  if( strcmp(zTSet,"main")==0 ){
    testset_main();
  }else if( strcmp(zTSet,"debug1")==0 ){
    testset_debug1();
  }else if( strcmp(zTSet,"orm")==0 ){
    testset_orm();
  }else if( strcmp(zTSet,"cte")==0 ){
    testset_cte();
  }else if( strcmp(zTSet,"fp")==0 ){
    testset_fp();
  }else if( strcmp(zTSet,"trigger")==0 ){
    testset_trigger();
  }else if( strcmp(zTSet,"rtree")==0 ){
    if( strcmp(zThisTest,"main")==0 ){
      testset_main();
    }else if( strcmp(zThisTest,"debug1")==0 ){
      testset_debug1();
    }else if( strcmp(zThisTest,"orm")==0 ){
      testset_orm();
    }else if( strcmp(zThisTest,"cte")==0 ){
      testset_cte();
    }else if( strcmp(zThisTest,"fp")==0 ){
      testset_fp();
    }else if( strcmp(zThisTest,"trigger")==0 ){
      testset_trigger();
    }else if( strcmp(zThisTest,"rtree")==0 ){
#ifdef SQLITE_ENABLE_RTREE
    testset_rtree(6, 147);
      testset_rtree(6, 147);
#else
    fatal_error("compile with -DSQLITE_ENABLE_RTREE to enable "
                "the R-Tree tests\n");
      fatal_error("compile with -DSQLITE_ENABLE_RTREE to enable "
                  "the R-Tree tests\n");
#endif
  }else{
    fatal_error("unknown testset: \"%s\"\n"
                "Choices: cte debug1 fp main orm rtree trigger\n",
                 zTSet);
  }
    }else{
      fatal_error("unknown testset: \"%s\"\n"
                  "Choices: cte debug1 fp main orm rtree trigger\n",
                   zThisTest);
    }
    if( zTSet[0] ){
      char *zSql, *zObj;
      speedtest1_begin_test(999, "Reset the database");
      while( 1 ){
        zObj = speedtest1_once(
             "SELECT name FROM main.sqlite_master"
             " WHERE sql LIKE 'CREATE %%TABLE%%'");
        if( zObj==0 ) break;
        zSql = sqlite3_mprintf("DROP TABLE main.\"%w\"", zObj);
        speedtest1_exec(zSql);
        sqlite3_free(zSql);
        sqlite3_free(zObj);
      }
      while( 1 ){
        zObj = speedtest1_once(
             "SELECT name FROM temp.sqlite_master"
             " WHERE sql LIKE 'CREATE %%TABLE%%'");
        if( zObj==0 ) break;
        zSql = sqlite3_mprintf("DROP TABLE main.\"%w\"", zObj);
        speedtest1_exec(zSql);
        sqlite3_free(zSql);
        sqlite3_free(zObj);
      }
      speedtest1_end_test();
    }
  }while( zTSet[0] );
  speedtest1_final();

  if( showStats ){
    sqlite3_exec(g.db, "PRAGMA compile_options", xCompileOptions, 0, 0);
  }

  /* Database connection statistics printed after both prepared statements
2264
2265
2266
2267
2268
2269
2270



2271
2272
2273
2274
2275
2276
2277










2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658







+
+
+







+
+
+
+
+
+
+
+
+
+
#endif

#ifdef __linux__
  if( showStats ){
    displayLinuxIoStats(stdout);
  }
#endif
  if( g.pScript ){
    fclose(g.pScript);
  }

  /* Release memory */
  free( pLook );
  free( pPCache );
  free( pHeap );
  return 0;
}

#ifdef SQLITE_SPEEDTEST1_WASM
/*
** A workaround for some inconsistent behaviour with how
** main() does (or does not) get exported to WASM.
*/
int wasm_main(int argc, char **argv){
  return main(argc, argv);
}
#endif

Changes to test/sqldiff1.test.

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
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







+
+
+
+















+
+
+
+
+





  db backup test2.db
  db eval {
    ATTACH 'test2.db' AS x2;
    DELETE FROM x2.t1 WHERE a=49;
    DELETE FROM x2.t2 WHERE a=48;
    INSERT INTO x2.t1(a,b) VALUES(1234,'hello');
    INSERT INTO x2.t2(a,b) VALUES(50.5,'xyzzy');
    INSERT INTO x2.t2(a,b) VALUES(51.5,'');
    INSERT INTO x2.t2(a,b) VALUES(52.5,''||X'0d0a');
    INSERT INTO x2.t2(a,b) VALUES(53.5,'one'||X'0a0d');
    INSERT INTO x2.t2(a,b) VALUES(54.5,'one'||X'0a'||'two');
    CREATE TABLE x2.t3(a,b,c);
    INSERT INTO x2.t3 VALUES(111,222,333);
    CREATE TABLE main.t4(x,y,z);
    INSERT INTO t4 SELECT * FROM t3;
  }
  set line "exec $PROG test.db test2.db"
  unset -nocomplain ::MSG
  catch {eval $line} ::MSG
} {0}
do_test sqldiff-1.1 {
  set ::MSG
} {DELETE FROM t1 WHERE a=49;
INSERT INTO t1(a,b) VALUES(1234,'hello');
DELETE FROM t2 WHERE a=48;
INSERT INTO t2(a,b) VALUES(50.5,'xyzzy');
INSERT INTO t2(a,b) VALUES(51.5,'');
INSERT INTO t2(a,b) VALUES(52.5,''||X'0d0a');
INSERT INTO t2(a,b) VALUES(53.5,'one'||X'0a0d');
INSERT INTO t2(a,b) VALUES(54.5,'one'||X'0a'
||'two');
CREATE TABLE t3(a,b,c);
INSERT INTO t3(rowid,a,b,c) VALUES(1,111,222,333);
DROP TABLE t4;}

finish_test

Changes to test/sqllimits1.test.

12
13
14
15
16
17
18

19
20
21
22
23
24
25
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26







+







# This file contains tests to verify that the limits defined in
# sqlite source file limits.h are enforced.
#
# $Id: sqllimits1.test,v 1.33 2009/06/25 01:47:12 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix sqllimits1

# Verify that the default per-connection limits are the same as
# the compile-time hard limits.
#
sqlite3 db2 :memory:
do_test sqllimits1-1.1 {
  sqlite3_limit db SQLITE_LIMIT_LENGTH -1
289
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
305
306
307
308
309
310
311







+
+
+
+
+
-
-
+
+
+







do_test sqllimits1-5.9 {
  set ::str [string repeat A 65537]
  set ::rep [string repeat B 65537]
  catchsql { SELECT replace($::str, 'A', $::rep) }
} {1 {string or blob too big}}

do_test sqllimits1-5.10 {
  # Prior to 3.37.0 strftime() allocated a large static buffer into
  # which to format its output. Using that strategy, 2100 repeats was
  # enough to exceed 100KiB and provoke the error. As of 3.37.0 strftime()
  # uses the StrAccum functions, so it requires 12100 to fail.
  #
  set ::str [string repeat %J 2100]
  catchsql { SELECT strftime($::str, '2003-10-31') }
  # set ::str [string repeat %J 2100]
  set ::str [string repeat %J 12100]
  catchsql { SELECT length(strftime($::str, '2003-10-31')) }
} {1 {string or blob too big}}

do_test sqllimits1-5.11 {
  set ::str1 [string repeat A [expr {$SQLITE_LIMIT_LENGTH - 10}]]
  set ::str2 [string repeat B [expr {$SQLITE_LIMIT_LENGTH - 10}]]
  catchsql { SELECT $::str1 || $::str2 }
} {1 {string or blob too big}}
337
338
339
340
341
342
343
344

345
346
347
348
349
350
351
344
345
346
347
348
349
350

351
352
353
354
355
356
357
358







-
+







}
do_test sqllimits1-5.14.6 {
  catch {sqlite3_bind_text $::STMT 1 $::str1 $np1} res
  set res
} {SQLITE_TOOBIG}
ifcapable utf16 {
  do_test sqllimits1-5.14.7 {
    catch {sqlite3_bind_text16 $::STMT 1 $::str1 $np1} res
    catch {sqlite3_bind_text16 $::STMT 1 $::str1 [expr $np1+1]} res
    set res
  } {SQLITE_TOOBIG}
}
do_test sqllimits1-5.14.8 {
  set n [expr {$np1-1}]
  catch {sqlite3_bind_text $::STMT 1 $::str1 $n} res
  set res
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
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







-
+














-
+







-
+







  }
} {1 {string or blob too big}}
db eval {DROP TABLE t4}

sqlite3_limit db SQLITE_LIMIT_SQL_LENGTH 0x7fffffff
set strvalue [string repeat A $::SQLITE_LIMIT_LENGTH]
do_test sqllimits1-5.16 {
  catchsql "SELECT '$strvalue'"
  catchsql "SELECT '$strvalue' AS x"
} [list 0 $strvalue]
do_test sqllimits1-5.17.1 {
  catchsql "SELECT 'A$strvalue'"
} [list 1 {string or blob too big}]
do_test sqllimits1-5.17.2 {
  sqlite3_limit db SQLITE_LIMIT_LENGTH 0x7fffffff
  catchsql {SELECT 'A' || $::strvalue}
} [list 0 A$strvalue]
do_test sqllimits1-5.17.3 {
  sqlite3_limit db SQLITE_LIMIT_LENGTH $SQLITE_LIMIT_LENGTH
  catchsql {SELECT 'A' || $::strvalue}
} [list 1 {string or blob too big}]
set blobvalue [string repeat 41 $::SQLITE_LIMIT_LENGTH]
do_test sqllimits1-5.18 {
  catchsql "SELECT x'$blobvalue'"
  catchsql "SELECT x'$blobvalue' AS x"
} [list 0 $strvalue]
do_test sqllimits1-5.19 {
  catchsql "SELECT '41$blobvalue'"
} [list 1 {string or blob too big}]
unset blobvalue

ifcapable datetime {
  set strvalue [string repeat D [expr {$SQLITE_LIMIT_LENGTH-12}]]
  set strvalue [string repeat D [expr {$SQLITE_LIMIT_LENGTH-11}]]
  do_test sqllimits1-5.20 {
    catchsql {SELECT strftime('%Y ' || $::strvalue, '2008-01-02')}
  } [list 0 [list "2008 $strvalue"]]
  do_test sqllimits1-5.21 {
    catchsql {SELECT strftime('%Y-%m-%d ' || $::strvalue, '2008-01-02')}
  } {1 {string or blob too big}}
}
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
866
867
868
869
870
871
872
873
874
875
876
877








878
879
880
881
882
883
884
885


886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978







+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
+
+
















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  }
} {1 {LIKE or GLOB pattern too complex}}

#--------------------------------------------------------------------
# This test case doesn't really belong with the other limits tests.
# It is in this file because it is taxing to run, like the limits tests.
#
# Update for 3.37.0: strftime() used to allocate a large static buffer
# into which it would write its result. With that implementation, the
# following would trigger an SQLITE_TOOBIG error. But strftime() now
# uses the StrAccum functions, causing this test to fail.
#
do_test sqllimits1-16.1 {
  set ::N [expr int(([expr pow(2,32)]/50) + 1)]
  expr (($::N*50) & 0xffffffff)<55
} {1}
do_test sqllimits1-16.2 {
  set ::format "[string repeat A 60][string repeat "%J" $::N]"
  catchsql {
    SELECT strftime($::format, 1);
#do_test sqllimits1-16.1 {
#  set ::N [expr int(([expr pow(2,32)]/50) + 1)]
#  expr (($::N*50) & 0xffffffff)<55
#} {1}
#do_test sqllimits1-16.2 {
#  set ::format "[string repeat A 60][string repeat "%J" $::N]"
#  catchsql {
#    SELECT strftime($::format, 1);
  }
} {1 {string or blob too big}}
#  }
#} {1 {string or blob too big}}

do_catchsql_test sqllimits1.17.0 {
  SELECT *,*,*,*,*,*,*,* FROM (
  SELECT *,*,*,*,*,*,*,* FROM (
  SELECT *,*,*,*,*,*,*,* FROM (
  SELECT *,*,*,*,*,*,*,* FROM (
  SELECT *,*,*,*,*,*,*,* FROM (
    SELECT 1,2,3,4,5,6,7,8,9,10
  )
  ))))
} "1 {too many columns in result set}"


foreach {key value} [array get saved] {
  catch {set $key $value}
}

#-------------------------------------------------------------------------
# At one point the following caused an assert() to fail.
#
sqlite3_limit db SQLITE_LIMIT_LENGTH 10000
set nm [string repeat x 10000]
do_catchsql_test sqllimits1-17.1 "
  CREATE TABLE $nm (x PRIMARY KEY)
" {1 {string or blob too big}}

#-------------------------------------------------------------------------
#
sqlite3_limit db SQLITE_LIMIT_COMPOUND_SELECT 10
do_catchsql_test sqllimits1-18.1 {
  CREATE TABLE b1(x);
  INSERT INTO b1 VALUES(1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11);
} {0 {}}

do_catchsql_test sqllimits1-18.2 {
  INSERT INTO b1 VALUES(1), (2), (3), (4), (5), (6), (7), (8), (9), (10)
    UNION VALUES(11);
} {1 {too many terms in compound SELECT}}

#-------------------------------------------------------------------------
#
reset_db
ifcapable utf16 {
  do_execsql_test 19.0 {
    PRAGMA encoding = 'utf16';
  }
  set bigstr [string repeat abcdefghij 5000]
  set bigstr16 [encoding convertto unicode $bigstr]

  do_test 19.1 {
    string length $bigstr16
  } {100000}

  do_test 19.2 {
    set ::stmt [sqlite3_prepare db "SELECT length( ? )" -1 TAIL]
    sqlite3_bind_text16 $::stmt 1 $bigstr16 100000
    sqlite3_step $::stmt
    set val [sqlite3_column_int $::stmt 0]
    sqlite3_finalize $::stmt
    set val
  } {50000}

  sqlite3_limit db SQLITE_LIMIT_LENGTH 100000

  do_test 19.3 {
    set ::stmt [sqlite3_prepare db "SELECT length( ? )" -1 TAIL]
    sqlite3_bind_text16 $::stmt 1 $bigstr16 100000
    sqlite3_step $::stmt
    set val [sqlite3_column_int $::stmt 0]
    sqlite3_finalize $::stmt
    set val
  } {50000}

  sqlite3_limit db SQLITE_LIMIT_LENGTH 99999

  do_test 19.4 {
    set ::stmt [sqlite3_prepare db "SELECT length( ? )" -1 TAIL]
    list [catch { sqlite3_bind_text16 $::stmt 1 $bigstr16 100000 } msg] $msg
  } {1 SQLITE_TOOBIG}
  sqlite3_finalize $::stmt

  sqlite3_limit db SQLITE_LIMIT_LENGTH 100000

  do_test 19.5 {
    set ::stmt [sqlite3_prepare db "SELECT length( ? )" -1 TAIL]
    list [catch { sqlite3_bind_text16 $::stmt 1 $bigstr16 100002 } msg] $msg
  } {1 SQLITE_TOOBIG}
  sqlite3_finalize $::stmt
}

finish_test

Added test/startup.c.





















































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2021-01-01
**
** 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 a program used to measure the start-up performance
** of SQLite.
**
** To use:
**
**     ./startup init
**     valgrind --tool=cachegrind ./startup run
**
**
** The "./startup init" command creates the test database file named
** "startup.db".  The performance test is run by the "./startup run"
** command.  That command does nothing but open the database file and
** parse the entire schema.
*/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "sqlite3.h"

static const char zHelp[] =
  "Usage: %s COMMAND\n"
  "Commands:\n"
  "  init                Initialized the startup.db database file\n"
  "  run                 Run the startup performance test\n"
  "Options:\n"
  "  --dbname NAME       Set the name of the test database file\n"
  "  --heap SZ MIN       Memory allocator uses SZ bytes & min allocation MIN\n"
  "  --stats             Show statistics at the end\n"
/* TBD
  "  --journal M         Set the journal_mode to M\n"
  "  --lookaside N SZ    Configure lookaside for N slots of SZ bytes each\n"
  "  --mmap SZ           MMAP the first SZ bytes of the database file\n"
  "  --multithread       Set multithreaded mode\n"
  "  --nomemstat         Disable memory statistics\n"
  "  --pagesize N        Set the page size to N\n"
  "  --pcache N SZ       Configure N pages of pagecache each of size SZ bytes\n"
  "  --serialized        Set serialized threading mode\n"
  "  --singlethread      Set single-threaded mode - disables all mutexing\n"
  "  --utf16be           Set text encoding to UTF-16BE\n"
  "  --utf16le           Set text encoding to UTF-16LE\n"
  "  --utf8              Set text encoding to UTF-8\n"
*/
;

static void usage(const char *argv0){
  printf(zHelp, argv0);
  exit(1);
}

/*
** The test schema is derived from the Fossil repository for SQLite itself.
** The schema covers the repository, the local checkout database, and
** the global configuration database.
*/
static const char zTestSchema[] = 
  "CREATE TABLE repo_blob(\n"
  "  rid INTEGER PRIMARY KEY,\n"
  "  rcvid INTEGER,\n"
  "  size INTEGER,\n"
  "  uuid TEXT UNIQUE NOT NULL,\n"
  "  content BLOB,\n"
  "  CHECK( length(uuid)>=40 AND rid>0 )\n"
  ");\n"
  "CREATE TABLE repo_delta(\n"
  "  rid INTEGER PRIMARY KEY,\n"
  "  srcid INTEGER NOT NULL REFERENCES blob\n"
  ");\n"
  "CREATE TABLE repo_rcvfrom(\n"
  "  rcvid INTEGER PRIMARY KEY,\n"
  "  uid INTEGER REFERENCES user,\n"
  "  mtime DATETIME,\n"
  "  nonce TEXT UNIQUE,\n"
  "  ipaddr TEXT\n"
  ");\n"
  "CREATE TABLE repo_private(rid INTEGER PRIMARY KEY);\n"
  "CREATE TABLE repo_accesslog(\n"
  "  uname TEXT,\n"
  "  ipaddr TEXT,\n"
  "  success BOOLEAN,\n"
  "  mtime TIMESTAMP);\n"
  "CREATE TABLE repo_user(\n"
  "  uid INTEGER PRIMARY KEY,\n"
  "  login TEXT UNIQUE,\n"
  "  pw TEXT,\n"
  "  cap TEXT,\n"
  "  cookie TEXT,\n"
  "  ipaddr TEXT,\n"
  "  cexpire DATETIME,\n"
  "  info TEXT,\n"
  "  mtime DATE,\n"
  "  photo BLOB\n"
  ");\n"
  "CREATE TABLE repo_reportfmt(\n"
  "   rn INTEGER PRIMARY KEY,\n"
  "   owner TEXT,\n"
  "   title TEXT UNIQUE,\n"
  "   mtime INTEGER,\n"
  "   cols TEXT,\n"
  "   sqlcode TEXT\n"
  ");\n"
  "CREATE TABLE repo_sqlite_stat2(tbl,idx,sampleno,sample);\n"
  "CREATE TABLE repo_sqlite_stat1(tbl,idx,stat);\n"
  "CREATE TABLE repo_sqlite_stat3(tbl,idx,neq,nlt,ndlt,sample);\n"
  "CREATE TABLE repo_config(\n"
  "  name TEXT PRIMARY KEY NOT NULL,\n"
  "  value CLOB, mtime INTEGER,\n"
  "  CHECK( typeof(name)='text' AND length(name)>=1 )\n"
  ") WITHOUT ROWID;\n"
  "CREATE TABLE repo_shun(uuid PRIMARY KEY,\n"
  "  mtime INTEGER,\n"
  "  scom TEXT) WITHOUT ROWID;\n"
  "CREATE TABLE repo_concealed(\n"
  "  hash TEXT PRIMARY KEY,\n"
  "  content TEXT\n"
  ", mtime INTEGER) WITHOUT ROWID;\n"
  "CREATE TABLE repo_admin_log(\n"
  " id INTEGER PRIMARY KEY,\n"
  " time INTEGER, -- Seconds since 1970\n"
  " page TEXT,    -- path of page\n"
  " who TEXT,     -- User who made the change\n"
  "  what TEXT     -- What changed\n"
  ");\n"
  "CREATE TABLE repo_unversioned(\n"
  "  name TEXT PRIMARY KEY,\n"
  "  rcvid INTEGER,\n"
  "  mtime DATETIME,\n"
  "  hash TEXT,\n"
  "  sz INTEGER,\n"
  "  encoding INT,\n"
  "  content BLOB\n"
  ") WITHOUT ROWID;\n"
  "CREATE TABLE repo_subscriber(\n"
  "  subscriberId INTEGER PRIMARY KEY,\n"
  "  subscriberCode BLOB DEFAULT (randomblob(32)) UNIQUE,\n"
  "  semail TEXT UNIQUE COLLATE nocase,\n"
  "  suname TEXT,\n"
  "  sverified BOOLEAN DEFAULT true,\n"
  "  sdonotcall BOOLEAN,\n"
  "  sdigest BOOLEAN,\n"
  "  ssub TEXT,\n"
  "  sctime INTDATE,\n"
  "  mtime INTDATE,\n"
  "  smip TEXT\n"
  ");\n"
  "CREATE TABLE repo_pending_alert(\n"
  "  eventid TEXT PRIMARY KEY,\n"
  "  sentSep BOOLEAN DEFAULT false,\n"
  "  sentDigest BOOLEAN DEFAULT false\n"
  ", sentMod BOOLEAN DEFAULT false) WITHOUT ROWID;\n"
  "CREATE INDEX repo_delta_i1 ON repo_delta(srcid);\n"
  "CREATE INDEX repo_blob_rcvid ON repo_blob(rcvid);\n"
  "CREATE INDEX repo_subscriberUname\n"
  "  ON repo_subscriber(suname) WHERE suname IS NOT NULL;\n"
  "CREATE VIEW repo_artifact(rid,rcvid,size,atype,srcid,hash,content) AS\n"
  "     SELECT blob.rid,rcvid,size,1,srcid,uuid,content\n"
  "       FROM repo_blob LEFT JOIN repo_delta ON (blob.rid=delta.rid);\n"
  "CREATE TABLE repo_filename(\n"
  "  fnid INTEGER PRIMARY KEY,\n"
  "  name TEXT UNIQUE\n"
  ");\n"
  "CREATE TABLE repo_mlink(\n"
  "  mid INTEGER,\n"
  "  fid INTEGER,\n"
  "  pmid INTEGER,\n"
  "  pid INTEGER,\n"
  "  fnid INTEGER REFERENCES filename,\n"
  "  pfnid INTEGER,\n"
  "  mperm INTEGER,\n"
  "  isaux BOOLEAN DEFAULT 0\n"
  ");\n"
  "CREATE INDEX repo_mlink_i1 ON repo_mlink(mid);\n"
  "CREATE INDEX repo_mlink_i2 ON repo_mlink(fnid);\n"
  "CREATE INDEX repo_mlink_i3 ON repo_mlink(fid);\n"
  "CREATE INDEX repo_mlink_i4 ON repo_mlink(pid);\n"
  "CREATE TABLE repo_plink(\n"
  "  pid INTEGER REFERENCES blob,\n"
  "  cid INTEGER REFERENCES blob,\n"
  "  isprim BOOLEAN,\n"
  "  mtime DATETIME,\n"
  "  baseid INTEGER REFERENCES blob,\n"
  "  UNIQUE(pid, cid)\n"
  ");\n"
  "CREATE INDEX repo_plink_i2 ON repo_plink(cid,pid);\n"
  "CREATE TABLE repo_leaf(rid INTEGER PRIMARY KEY);\n"
  "CREATE TABLE repo_event(\n"
  "  type TEXT,\n"
  "  mtime DATETIME,\n"
  "  objid INTEGER PRIMARY KEY,\n"
  "  tagid INTEGER,\n"
  "  uid INTEGER REFERENCES user,\n"
  "  bgcolor TEXT,\n"
  "  euser TEXT,\n"
  "  user TEXT,\n"
  "  ecomment TEXT,\n"
  "  comment TEXT,\n"
  "  brief TEXT,\n"
  "  omtime DATETIME\n"
  ");\n"
  "CREATE INDEX repo_event_i1 ON repo_event(mtime);\n"
  "CREATE TABLE repo_phantom(\n"
  "  rid INTEGER PRIMARY KEY\n"
  ");\n"
  "CREATE TABLE repo_orphan(\n"
  "  rid INTEGER PRIMARY KEY,\n"
  "  baseline INTEGER\n"
  ");\n"
  "CREATE INDEX repo_orphan_baseline ON repo_orphan(baseline);\n"
  "CREATE TABLE repo_unclustered(\n"
  "  rid INTEGER PRIMARY KEY\n"
  ");\n"
  "CREATE TABLE repo_unsent(\n"
  "  rid INTEGER PRIMARY KEY\n"
  ");\n"
  "CREATE TABLE repo_tag(\n"
  "  tagid INTEGER PRIMARY KEY,\n"
  "  tagname TEXT UNIQUE\n"
  ");\n"
  "CREATE TABLE repo_tagxref(\n"
  "  tagid INTEGER REFERENCES tag,\n"
  "  tagtype INTEGER,\n"
  "  srcid INTEGER REFERENCES blob,\n"
  "  origid INTEGER REFERENCES blob,\n"
  "  value TEXT,\n"
  "  mtime TIMESTAMP,\n"
  "  rid INTEGER REFERENCE blob,\n"
  "  UNIQUE(rid, tagid)\n"
  ");\n"
  "CREATE INDEX repo_tagxref_i1 ON repo_tagxref(tagid, mtime);\n"
  "CREATE TABLE repo_backlink(\n"
  "  target TEXT,\n"
  "  srctype INT,\n"
  "  srcid INT,\n"
  "  mtime TIMESTAMP,\n"
  "  UNIQUE(target, srctype, srcid)\n"
  ");\n"
  "CREATE INDEX repo_backlink_src ON repo_backlink(srcid, srctype);\n"
  "CREATE TABLE repo_attachment(\n"
  "  attachid INTEGER PRIMARY KEY,\n"
  "  isLatest BOOLEAN DEFAULT 0,\n"
  "  mtime TIMESTAMP,\n"
  "  src TEXT,\n"
  "  target TEXT,\n"
  "  filename TEXT,\n"
  "  comment TEXT,\n"
  "  user TEXT\n"
  ");\n"
  "CREATE INDEX repo_attachment_idx1\n"
  " ON repo_attachment(target, filename, mtime);\n"
  "CREATE INDEX repo_attachment_idx2 ON repo_attachment(src);\n"
  "CREATE TABLE repo_cherrypick(\n"
  "  parentid INT,\n"
  "  childid INT,\n"
  "  isExclude BOOLEAN DEFAULT false,\n"
  "  PRIMARY KEY(parentid, childid)\n"
  ") WITHOUT ROWID;\n"
  "CREATE INDEX repo_cherrypick_cid ON repo_cherrypick(childid);\n"
  "CREATE TABLE repo_ticket(\n"
  "  -- Do not change any column that begins with tkt_\n"
  "  tkt_id INTEGER PRIMARY KEY,\n"
  "  tkt_uuid TEXT UNIQUE,\n"
  "  tkt_mtime DATE,\n"
  "  tkt_ctime DATE,\n"
  "  -- Add as many fields as required below this line\n"
  "  type TEXT,\n"
  "  status TEXT,\n"
  "  subsystem TEXT,\n"
  "  priority TEXT,\n"
  "  severity TEXT,\n"
  "  foundin TEXT,\n"
  "  private_contact TEXT,\n"
  "  resolution TEXT,\n"
  "  title TEXT,\n"
  "  comment TEXT\n"
  ");\n"
  "CREATE TABLE repo_ticketchng(\n"
  "  -- Do not change any column that begins with tkt_\n"
  "  tkt_id INTEGER REFERENCES ticket,\n"
  "  tkt_rid INTEGER REFERENCES blob,\n"
  "  tkt_mtime DATE,\n"
  "  -- Add as many fields as required below this line\n"
  "  login TEXT,\n"
  "  username TEXT,\n"
  "  mimetype TEXT,\n"
  "  icomment TEXT\n"
  ");\n"
  "CREATE INDEX repo_ticketchng_idx1 ON repo_ticketchng(tkt_id, tkt_mtime);\n"
  "CREATE TRIGGER repo_alert_trigger1\n"
  "AFTER INSERT ON repo_event BEGIN\n"
  "  INSERT INTO repo_pending_alert(eventid)\n"
  "    SELECT printf('%.1c%d',new.type,new.objid) WHERE true\n"
  "    ON CONFLICT(eventId) DO NOTHING;\n"
  "END;\n"
  "CREATE TABLE repo_vcache(\n"
  "  vid INTEGER,         -- check-in ID\n"
  "  fname TEXT,          -- filename\n"
  "  rid INTEGER,         -- artifact ID\n"
  "  PRIMARY KEY(vid,fname)\n"
  ") WITHOUT ROWID;\n"
  "CREATE TABLE localdb_vvar(\n"
  "  name TEXT PRIMARY KEY NOT NULL,\n"
  "  value CLOB,\n"
  "  CHECK( typeof(name)='text' AND length(name)>=1 )\n"
  ");\n"
  "CREATE TABLE localdb_vfile(\n"
  "  id INTEGER PRIMARY KEY,\n"
  "  vid INTEGER REFERENCES blob,\n"
  "  chnged INT DEFAULT 0,\n"
  "  deleted BOOLEAN DEFAULT 0,\n"
  "  isexe BOOLEAN,\n"
  "  islink BOOLEAN,\n"
  "  rid INTEGER,\n"
  "  mrid INTEGER,\n"
  "  mtime INTEGER,\n"
  "  pathname TEXT,\n"
  "  origname TEXT, mhash,\n"
  "  UNIQUE(pathname,vid)\n"
  ");\n"
  "CREATE TABLE localdb_sqlite_stat1(tbl,idx,stat);\n"
  "CREATE TABLE localdb_vcache(\n"
  "  vid INTEGER,         -- check-in ID\n"
  "  fname TEXT,          -- filename\n"
  "  rid INTEGER,         -- artifact ID\n"
  "  PRIMARY KEY(vid,fname)\n"
  ") WITHOUT ROWID;\n"
  "CREATE TABLE localdb_stash(\n"
  "  stashid INTEGER PRIMARY KEY,\n"
  "  vid INTEGER,\n"
  "  hash TEXT,\n"
  "  comment TEXT,\n"
  "  ctime TIMESTAMP\n"
  ");\n"
  "CREATE TABLE localdb_stashfile(\n"
  "  stashid INTEGER REFERENCES stash,\n"
  "  isAdded BOOLEAN,\n"
  "  isRemoved BOOLEAN,\n"
  "  isExec BOOLEAN,\n"
  "  isLink BOOLEAN,\n"
  "  rid INTEGER,\n"
  "  hash TEXT,\n"
  "  origname TEXT,\n"
  "  newname TEXT,\n"
  "  delta BLOB,\n"
  "  PRIMARY KEY(newname, stashid)\n"
  ");\n"
  "CREATE TABLE localdb_vmerge(\n"
  "  id INTEGER REFERENCES vfile,\n"
  "  merge INTEGER,\n"
  "  mhash TEXT\n"
  ");\n"
  "CREATE UNIQUE INDEX localdb_vmergex1 ON localdb_vmerge(id,mhash);\n"
  "CREATE TRIGGER localdb_vmerge_ck1 AFTER INSERT ON localdb_vmerge\n"
  "WHEN new.mhash IS NULL BEGIN\n"
  "  SELECT raise(FAIL,\n"
  "  'trying to update a newer checkout with an older version of Fossil');\n"
  "END;\n"
  "CREATE TABLE configdb_global_config(\n"
  "  name TEXT PRIMARY KEY,\n"
  "  value TEXT\n"
  ");\n"
  "CREATE TABLE configdb_sqlite_stat1(tbl,idx,stat);\n"
;

#ifdef __linux__
#include <sys/types.h>
#include <unistd.h>

/*
** Attempt to display I/O stats on Linux using /proc/PID/io
*/
static void displayLinuxIoStats(FILE *out){
  FILE *in;
  char z[200];
  sqlite3_snprintf(sizeof(z), z, "/proc/%d/io", getpid());
  in = fopen(z, "rb");
  if( in==0 ) return;
  while( fgets(z, sizeof(z), in)!=0 ){
    static const struct {
      const char *zPattern;
      const char *zDesc;
    } aTrans[] = {
      { "rchar: ",                  "Bytes received by read():" },
      { "wchar: ",                  "Bytes sent to write():"    },
      { "syscr: ",                  "Read() system calls:"      },
      { "syscw: ",                  "Write() system calls:"     },
      { "read_bytes: ",             "Bytes rcvd from storage:"  },
      { "write_bytes: ",            "Bytes sent to storage:"    },
      { "cancelled_write_bytes: ",  "Cancelled write bytes:"    },
    };
    int i;
    for(i=0; i<sizeof(aTrans)/sizeof(aTrans[0]); i++){
      int n = (int)strlen(aTrans[i].zPattern);
      if( strncmp(aTrans[i].zPattern, z, n)==0 ){
        fprintf(out, "-- %-28s %s", aTrans[i].zDesc, &z[n]);
        break;
      }
    }
  }
  fclose(in);
}   
#endif

/*
** Return the value of a hexadecimal digit.  Return -1 if the input
** is not a hex digit.
*/
static int hexDigitValue(char c){
  if( c>='0' && c<='9' ) return c - '0';
  if( c>='a' && c<='f' ) return c - 'a' + 10;
  if( c>='A' && c<='F' ) return c - 'A' + 10;
  return -1;
}

/*
** Interpret zArg as an integer value, possibly with suffixes.
*/
static int integerValue(const char *zArg){
  sqlite3_int64 v = 0;
  static const struct { char *zSuffix; int iMult; } aMult[] = {
    { "KiB", 1024 },
    { "MiB", 1024*1024 },
    { "GiB", 1024*1024*1024 },
    { "KB",  1000 },
    { "MB",  1000000 },
    { "GB",  1000000000 },
    { "K",   1000 },
    { "M",   1000000 },
    { "G",   1000000000 },
  };
  int i;
  int isNeg = 0;
  if( zArg[0]=='-' ){
    isNeg = 1;
    zArg++;
  }else if( zArg[0]=='+' ){
    zArg++;
  }
  if( zArg[0]=='0' && zArg[1]=='x' ){
    int x;
    zArg += 2;
    while( (x = hexDigitValue(zArg[0]))>=0 ){
      v = (v<<4) + x;
      zArg++;
    }
  }else{
    while( isdigit(zArg[0]) ){
      v = v*10 + zArg[0] - '0';
      zArg++;
    }
  }
  for(i=0; i<sizeof(aMult)/sizeof(aMult[0]); i++){
    if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
      v *= aMult[i].iMult;
      break;
    }
  }
  if( v>0x7fffffff ){
    printf("ERROR: parameter too large - max 2147483648\n");
    exit(1);
  }
  return (int)(isNeg? -v : v);
}


int main(int argc, char **argv){
  const char *zCmd = 0;
  int i;
  int bAutovac = 0;
  int showStats = 0;
  const char *zDbName = "./startup.db";
  int nHeap = 0;
  int mnHeap = 0;

  for(i=1; i<argc; i++){
    const char *z = argv[i];
    if( z[0]!='-' ){
      if( zCmd ){
        usage(argv[0]);
      }
      zCmd = z;
      continue;
    }
    if( z[1]=='-' ) z++;
    if( strcmp(z, "-autovacuum")==0 ){
      bAutovac = 1;
    }else
    if( strcmp(z, "-dbname")==0 ){
      if( i==argc-1 ){
        printf("ERROR: missing argument on \"%s\"\n", argv[0]);
        exit(1);
      }
      zDbName = argv[++i];
    }else
    if( strcmp(z,"-heap")==0 ){
      if( i>=argc-2 ){
        printf("ERROR: missing arguments on %s\n", argv[i]);
        exit(1);
      }
      nHeap = integerValue(argv[i+1]);
      mnHeap = integerValue(argv[i+2]);
      i += 2;
    }else
    if( strcmp(z,"-stats")==0 ){
       showStats = 1;
    }else
    {
      printf("ERROR: unknown option \"%s\"\n", argv[i]);
      usage(argv[0]);
    }
  }
  if( zCmd==0 ){
    printf("ERROR: no COMMAND specified\n");
    usage(argv[0]);
  }
  if( strcmp(zCmd, "run")==0 ){
    sqlite3 *db;
    int rc;
    char *zErr = 0;
    void *pHeap = 0;
    if( nHeap>0 ){
      pHeap = malloc( nHeap );
      if( pHeap==0 ){
        printf("ERROR: cannot allocate %d-byte heap\n", nHeap);
        exit(1);
      }
      rc = sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nHeap, mnHeap);
      if( rc ){
        printf("ERROR: heap configuration failed: %d\n", rc);
        exit(1);
      }
    }
    rc = sqlite3_open(zDbName, &db);
    if( rc ){
      printf("SQLite error: %s\n", sqlite3_errmsg(db));
    }else{
      sqlite3_exec(db, "PRAGMA synchronous", 0, 0, &zErr);
    }
    if( zErr ){
      printf("ERROR: %s\n", zErr);
      sqlite3_free(zErr);
    }
    if( showStats ){
      int iCur, iHi;
      sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED, &iCur, &iHi, 0);
      printf("-- Lookaside Slots Used:        %d (max %d)\n", iCur,iHi);
      sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &iCur, &iHi, 0);
      printf("-- Successful lookasides:       %d\n", iHi);
      sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE, &iCur,&iHi,0);
      printf("-- Lookaside size faults:       %d\n", iHi);
      sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL, &iCur,&iHi,0);
      printf("-- Lookaside OOM faults:        %d\n", iHi);
      sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHi, 0);
      printf("-- Pager Heap Usage:            %d bytes\n", iCur);
      sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHi, 1);
      printf("-- Page cache hits:             %d\n", iCur);
      sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHi, 1);
      printf("-- Page cache misses:           %d\n", iCur);
      sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHi, 1);
      printf("-- Page cache writes:           %d\n", iCur); 
      sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHi, 0);
      printf("-- Schema Heap Usage:           %d bytes\n", iCur); 
      sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHi, 0);
      printf("-- Statement Heap Usage:        %d bytes\n", iCur); 
    }
    sqlite3_close(db);
    free(pHeap);
    /* Global memory usage statistics printed after the database connection
    ** has closed.  Memory usage should be zero at this point. */
    if( showStats ){
      int iCur, iHi;
      sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHi, 0);
      printf("-- Memory Used (bytes):         %d (max %d)\n", iCur,iHi);
      sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHi, 0);
      printf("-- Outstanding Allocations:     %d (max %d)\n", iCur,iHi);
      sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHi, 0);
      printf("-- Pcache Overflow Bytes:       %d (max %d)\n", iCur,iHi);
      sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &iCur, &iHi, 0);
      printf("-- Largest Allocation:          %d bytes\n",iHi);
      sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE, &iCur, &iHi, 0);
      printf("-- Largest Pcache Allocation:   %d bytes\n",iHi);
#ifdef __linux__
      displayLinuxIoStats(stdout);
#endif
    }
    return 0;
  }
  if( strcmp(zCmd, "init")==0 ){
    sqlite3 *db;
    char *zAux;
    char *zErr = 0;
    int rc;
    unlink(zDbName);
    zAux = sqlite3_mprintf("%s-journal", zDbName);
    unlink(zAux);
    sqlite3_free(zAux);
    zAux = sqlite3_mprintf("%s-wal", zDbName);
    unlink(zAux);
    sqlite3_free(zAux);
    rc = sqlite3_open(zDbName, &db);
    if( rc ){
      printf("SQLite error: %s\n", sqlite3_errmsg(db));
    }else{
      sqlite3_exec(db, "BEGIN", 0, 0, 0);
      sqlite3_exec(db, zTestSchema, 0, 0, &zErr);
      sqlite3_exec(db, "COMMIT", 0, 0, 0);
    }
    if( zErr ){
      printf("ERROR: %s\n", zErr);
      sqlite3_free(zErr);
    }
    sqlite3_close(db);
    return 0;

  }
}

Changes to test/stat.test.

32
33
34
35
36
37
38
39

40


41
42
43
44
45
46
47
32
33
34
35
36
37
38

39
40
41
42
43
44
45
46
47
48
49







-
+

+
+








register_dbstat_vtab db
do_execsql_test stat-0.0 {
  PRAGMA table_info(dbstat);
} {/0 name TEXT .* 1 path TEXT .* 9 pgsize INTEGER/}

# Attempts to drop an eponymous virtual table are a no-op.
do_execsql_test stat-0.1 {
do_catchsql_test stat-0.1a {
  DROP TABLE dbstat;
} {1 {table dbstat may not be dropped}}
do_execsql_test stat-0.1b {
  PRAGMA table_info=dbstat;
} {/0 name TEXT .* 1 path TEXT .* 9 pgsize INTEGER/}

db close
forcedelete test.db
sqlite3 db test.db
db func a_string a_string
55
56
57
58
59
60
61
62

63
64
65
66
67
68
69
57
58
59
60
61
62
63

64
65
66
67
68
69
70
71







-
+








if {[wal_is_capable]} {
  do_execsql_test stat-0.1 {
    PRAGMA journal_mode = WAL;
    PRAGMA journal_mode = delete;
    SELECT name, path, pageno, pagetype, ncell, payload, unused, mx_payload
      FROM stat;
  } {wal delete sqlite_master / 1 leaf 0 0 916 0}
  } {wal delete sqlite_schema / 1 leaf 0 0 916 0}
}

do_test stat-1.0 {
  execsql {
    CREATE TABLE t1(a, b);
    CREATE INDEX i1 ON t1(b);
    INSERT INTO t1(rowid, a, b) VALUES(2, 2, 3);
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
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







-
+

-
+




















-
+







    SELECT name, path, pageno, pagetype, ncell, payload, unused, mx_payload
      FROM stat WHERE name = 'i1';
  }
} {i1 / 3 leaf 2 10 1000 5}
do_test stat-1.3 {
  execsql {
    SELECT name, path, pageno, pagetype, ncell, payload, unused, mx_payload
      FROM stat WHERE name = 'sqlite_master';
      FROM stat WHERE name = 'sqlite_schema';
  }
} {sqlite_master / 1 leaf 2 77 831 40}
} {sqlite_schema / 1 leaf 2 77 831 40}
do_test stat-1.4 {
  execsql {
    DROP TABLE t1;
  }
} {}

do_execsql_test stat-2.1 {
  CREATE TABLE t3(a PRIMARY KEY, b);
  INSERT INTO t3(rowid, a, b) VALUES(2, a_string(111), a_string(222));
  INSERT INTO t3 SELECT a_string(110+rowid), a_string(221+rowid) FROM t3
   ORDER BY rowid;
  INSERT INTO t3 SELECT a_string(110+rowid), a_string(221+rowid) FROM t3
   ORDER BY rowid;
  INSERT INTO t3 SELECT a_string(110+rowid), a_string(221+rowid) FROM t3
   ORDER BY rowid;
  INSERT INTO t3 SELECT a_string(110+rowid), a_string(221+rowid) FROM t3
   ORDER BY rowid;
  INSERT INTO t3 SELECT a_string(110+rowid), a_string(221+rowid) FROM t3
   ORDER BY rowid;
  SELECT name, path, pageno, pagetype, ncell, payload, unused, mx_payload
    FROM stat WHERE name != 'sqlite_master';
    FROM stat WHERE name != 'sqlite_schema' ORDER BY name;
} [list \
  sqlite_autoindex_t3_1 / 3 internal 3 368 623 125       \
  sqlite_autoindex_t3_1 /000/ 8 leaf 8 946 46 123        \
  sqlite_autoindex_t3_1 /001/ 9 leaf 8 988 2 131         \
  sqlite_autoindex_t3_1 /002/ 15 leaf 7 857 137 132      \
  sqlite_autoindex_t3_1 /003/ 20 leaf 6 739 257 129      \
  t3 / 2 internal 15 0 907 0                             \
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
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







+
+
+
+
+
+
+
+

















-
+



















+
+
+
+
+
+
+
+
+







  t3 /00a/ 17 leaf 2 698 308 350                         \
  t3 /00b/ 18 leaf 2 706 300 354                         \
  t3 /00c/ 19 leaf 2 714 292 358                         \
  t3 /00d/ 21 leaf 2 722 284 362                         \
  t3 /00e/ 22 leaf 2 730 276 366                         \
  t3 /00f/ 23 leaf 2 738 268 370                         \
]

do_execsql_test stat-2.1agg {
  SELECT * FROM dbstat WHERE aggregate=TRUE ORDER BY name;
} [list \
  sqlite_autoindex_t3_1 {}  5 {} 32  3898 1065 132 {}  5120 \
  sqlite_schema         {}  1 {}  2    84  824  49 {}  1024 \
  t3                    {} 17 {} 47 11188 5815 370 {} 17408 \
]

# With every index entry overflowing, make sure no pages are missed 
# (other than the locking page which is 64 in this test build.)
#
do_execsql_test stat-2.2 {
  UPDATE t3 SET a=a||hex(randomblob(700));
  VACUUM;
  SELECT pageno FROM stat EXCEPT SELECT pageno-1 FROM stat;
} {64 136}

do_execsql_test stat-2.3 { DROP TABLE t3; VACUUM; } {}

do_execsql_test stat-3.1 {
  CREATE TABLE t4(x);
  CREATE INDEX i4 ON t4(x);
  INSERT INTO t4(rowid, x) VALUES(2, a_string(7777));
  SELECT name, path, pageno, pagetype, ncell, payload, unused, mx_payload
    FROM stat WHERE name != 'sqlite_master';
    FROM stat WHERE name != 'sqlite_schema' ORDER BY name;
} [list \
  i4 / 3 leaf 1 103 905 7782                 \
  i4 /000+000000 4 overflow 0 1020 0 0       \
  i4 /000+000001 5 overflow 0 1020 0 0      \
  i4 /000+000002 6 overflow 0 1020 0 0      \
  i4 /000+000003 7 overflow 0 1020 0 0      \
  i4 /000+000004 8 overflow 0 1020 0 0      \
  i4 /000+000005 9 overflow 0 1020 0 0      \
  i4 /000+000006 10 overflow 0 1020 0 0      \
  i4 /000+000007 11 overflow 0 539 481 0     \
  t4 / 2 leaf 1 640 367 7780                 \
  t4 /000+000000 12 overflow 0 1020 0 0      \
  t4 /000+000001 13 overflow 0 1020 0 0      \
  t4 /000+000002 14 overflow 0 1020 0 0      \
  t4 /000+000003 15 overflow 0 1020 0 0      \
  t4 /000+000004 16 overflow 0 1020 0 0      \
  t4 /000+000005 17 overflow 0 1020 0 0      \
  t4 /000+000006 18 overflow 0 1020 0 0      \
]

do_execsql_test stat-3.2 {
  SELECT *, '|' FROM dbstat WHERE aggregate=TRUE ORDER BY name;
} [list \
  i4            {} 9 {} 1 7782 1386 7782 {} 9216 | \
  sqlite_schema {} 1 {} 2   74  834   40 {} 1024 | \
  t4            {} 8 {} 1 7780  367 7780 {} 8192 | \
]


do_execsql_test stat-4.1 {
  CREATE TABLE t5(x);
  CREATE INDEX i5 ON t5(x);
  SELECT name, path, pageno, pagetype, ncell, payload, unused, mx_payload
    FROM stat WHERE name = 't5' OR name = 'i5';
} [list  \
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
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







+
+
+
+
+
+
+
+
+
+




















-
+





-
+






-
+






-
+












-
+









-
+







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  SELECT name, path, pageno, pagetype, ncell, payload, unused, mx_payload
    FROM stat WHERE name = 't1';
} [list \
  t1 / 2 leaf 2 993 5 1517                \
  t1 /000+000000 3 overflow 0 1020 0 0    \
  t1 /001+000000 4 overflow 0 1020 0 0    \
]

do_execsql_test stat-5.20 {
  SELECT name, quote(path), pageno, quote(pagetype), ncell, payload,
         unused, mx_payload, '|' FROM dbstat('main',1);
} {sqlite_schema NULL 1 NULL 1 34 878 34 | tx NULL 1 NULL 0 0 1016 0 |}
do_execsql_test stat-5.21 {
  SELECT name, quote(path), pageno, quote(pagetype), ncell, payload,
         unused, mx_payload, '|' FROM dbstat('aux1',1);
} {sqlite_schema NULL 1 NULL 1 34 878 34 | t1 NULL 3 NULL 2 3033 5 1517 |}


do_catchsql_test stat-6.1 {
  CREATE VIRTUAL TABLE temp.s2 USING dbstat(mainx);
} {1 {no such database: mainx}}

#-------------------------------------------------------------------------
# Test that the argument passed to the dbstat constructor is dequoted
# before it is matched against the names of attached databases.
#
forcedelete test.db2
do_execsql_test 7.1 {
  ATTACH 'test.db2' AS '123';
  PRAGMA "123".auto_vacuum = OFF;
  CREATE TABLE "123".x1(a, b);
  INSERT INTO x1 VALUES(1, 2);
}

do_execsql_test 7.1.1 {
  SELECT * FROM dbstat('123');
} {
  sqlite_master / 1 leaf 1 37 875 37 0 1024 
  sqlite_schema / 1 leaf 1 37 875 37 0 1024 
  x1 / 2 leaf 1 4 1008 4 1024 1024
}
do_execsql_test 7.1.2 {
  SELECT * FROM dbstat(123);
} {
  sqlite_master / 1 leaf 1 37 875 37 0 1024 
  sqlite_schema / 1 leaf 1 37 875 37 0 1024 
  x1 / 2 leaf 1 4 1008 4 1024 1024
}
do_execsql_test 7.1.3 {
  CREATE VIRTUAL TABLE x2 USING dbstat('123');
  SELECT * FROM x2;
} {
  sqlite_master / 1 leaf 1 37 875 37 0 1024 
  sqlite_schema / 1 leaf 1 37 875 37 0 1024 
  x1 / 2 leaf 1 4 1008 4 1024 1024
}
do_execsql_test 7.1.4 {
  CREATE VIRTUAL TABLE x3 USING dbstat(123);
  SELECT * FROM x3;
} {
  sqlite_master / 1 leaf 1 37 875 37 0 1024 
  sqlite_schema / 1 leaf 1 37 875 37 0 1024 
  x1 / 2 leaf 1 4 1008 4 1024 1024
}

do_execsql_test 7.2 {
  DETACH 123;
  DROP TABLE x2;
  DROP TABLE x3;
  ATTACH 'test.db2' AS '123corp';
}
do_execsql_test 7.2.1 {
  SELECT * FROM dbstat('123corp');
} {
  sqlite_master / 1 leaf 1 37 875 37 0 1024 
  sqlite_schema / 1 leaf 1 37 875 37 0 1024 
  x1 / 2 leaf 1 4 1008 4 1024 1024
}
do_catchsql_test 7.2.2 {
  SELECT * FROM dbstat(123corp);
} {1 {unrecognized token: "123corp"}}
do_execsql_test 7.2.3 {
  CREATE VIRTUAL TABLE x2 USING dbstat('123corp');
  SELECT * FROM x2;
} {
  sqlite_master / 1 leaf 1 37 875 37 0 1024 
  sqlite_schema / 1 leaf 1 37 875 37 0 1024 
  x1 / 2 leaf 1 4 1008 4 1024 1024
}
do_catchsql_test 7.2.4 {
  CREATE VIRTUAL TABLE x3 USING dbstat(123corp);
  SELECT * FROM x3;
} {1 {unrecognized token: "123corp"}}


do_execsql_test 8.1 {
  CREATE VIRTUAL TABLE st4 USING dbstat;
}
do_execsql_test 8.2 {
  SELECT * FROM st4 WHERE st4.aggregate = NULL;
}
do_execsql_test 8.3 {
  SELECT aggregate=1 FROM st4 WHERE aggregate = 5
}
do_execsql_test 8.4 {
  SELECT * FROM st4 WHERE name = NULL;
} {}
do_execsql_test 8.5 {
  SELECT * FROM st4 WHERE schema = NULL;
} {}

#-------------------------------------------------------------------------
reset_db
breakpoint
do_catchsql_test 9.1 {
  CREATE TABLE dbstat(x, y);
  DROP TABLE nosuchdb.dbstat;
} {/1 {(no such table: nosuchdb.dbstat|table dbstat may not be dropped)}/}

finish_test

Changes to test/statfault.test.

37
38
39
40
41
42
43








44


45

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

52
53
54
55







+
+
+
+
+
+
+
+
-
+
+

+
  execsql { SELECT 1 FROM sqlite_master LIMIT 1 }
} -body {
  execsql { SELECT count(*) FROM sss }
} -test {
  faultsim_test_result {0 8} 
}

do_faultsim_test 2 -faults * -prep {
  faultsim_restore_and_reopen
  register_dbstat_vtab db
  execsql { SELECT 1 FROM sqlite_master LIMIT 1 }
} -body {
  db eval { SELECT * FROM sss } { db eval { SELECT randomblob(5000) } }
} -test {
  faultsim_test_result {0 {}} 

}

finish_test

Added test/strict1.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2021-08-18
#
# 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 STRICT tables.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix strict1

# STRICT tables have on a limited number of allowed datatypes.
#
do_catchsql_test strict1-1.1 {
  CREATE TABLE t1(a) STRICT;
} {1 {missing datatype for t1.a}}
do_catchsql_test strict1-1.2 {
  CREATE TABLE t1(a PRIMARY KEY) STRICT, WITHOUT ROWID;
} {1 {missing datatype for t1.a}}
do_catchsql_test strict1-1.3 {
  CREATE TABLE t1(a PRIMARY KEY) WITHOUT ROWID, STRICT;
} {1 {missing datatype for t1.a}}
do_catchsql_test strict1-1.4 {
  CREATE TABLE t1(a BANJO PRIMARY KEY) WITHOUT ROWID, STRICT;
} {1 {unknown datatype for t1.a: "BANJO"}}
do_catchsql_test strict1-1.5 {
  CREATE TABLE t1(a TEXT PRIMARY KEY, b INT, c INTEGER, d REAL, e BLOB, f DATE) strict;
} {1 {unknown datatype for t1.f: "DATE"}}
do_catchsql_test strict1-1.6 {
  CREATE TABLE t1(a TEXT PRIMARY KEY, b INT, c INTEGER, d REAL, e BLOB, f TEXT(50)) WITHOUT ROWID, STRICT;
} {1 {unknown datatype for t1.f: "TEXT(50)"}}

do_execsql_test strict1-2.0 {
  CREATE TABLE t1(
    a INT,
    b INTEGER,
    c BLOB,
    d TEXT,
    e REAL
  ) STRICT;
} {}
ifcapable vtab {
  do_execsql_test strict1-2.0a {
    SELECT strict FROM pragma_table_list('t1');
  } {1}
}
do_catchsql_test strict1-2.1 {
  INSERT INTO t1(a) VALUES('xyz');
} {1 {cannot store TEXT value in INT column t1.a}}
do_catchsql_test strict1-2.2 {
  INSERT INTO t1(b) VALUES('xyz');
} {1 {cannot store TEXT value in INTEGER column t1.b}}
do_catchsql_test strict1-2.3 {
  INSERT INTO t1(c) VALUES('xyz');
} {1 {cannot store TEXT value in BLOB column t1.c}}
do_catchsql_test strict1-2.4 {
  INSERT INTO t1(d) VALUES(x'3142536475');
} {1 {cannot store BLOB value in TEXT column t1.d}}
do_catchsql_test strict1-2.5 {
  INSERT INTO t1(e) VALUES('xyz');
} {1 {cannot store TEXT value in REAL column t1.e}}


do_execsql_test strict1-3.1 {
  INSERT INTO t1(a, b) VALUES(1,2),('3','4'),(5.0, 6.0),(null,null);
  SELECT a, b, '|' FROM t1;
} {1 2 | 3 4 | 5 6 | {} {} |}
do_catchsql_test strict1-3.2 {
  INSERT INTO t1(a) VALUES(1.2);
} {1 {cannot store REAL value in INT column t1.a}}
do_catchsql_test strict1-3.3 {
  INSERT INTO t1(a) VALUES(x'313233');
} {1 {cannot store BLOB value in INT column t1.a}}
do_catchsql_test strict1-3.4 {
  INSERT INTO t1(b) VALUES(1.2);
} {1 {cannot store REAL value in INTEGER column t1.b}}
do_catchsql_test strict1-3.5 {
  INSERT INTO t1(b) VALUES(x'313233');
} {1 {cannot store BLOB value in INTEGER column t1.b}}

do_execsql_test strict1-4.1 {
  DELETE FROM t1;
  INSERT INTO t1(c) VALUES(x'313233'), (NULL);
  SELECT typeof(c), c FROM t1;
} {blob 123 null {}}
do_catchsql_test strict1-4.2 {
  INSERT INTO t1(c) VALUES('456');
} {1 {cannot store TEXT value in BLOB column t1.c}}

do_execsql_test strict1-5.1 {
  DELETE FROM t1;
  INSERT INTO t1(d) VALUES('xyz'),(4),(5.5),(NULL);
  SELECT typeof(d), d FROM t1;
} {text xyz text 4 text 5.5 null {}}
do_catchsql_test strict1-5.2 {
  INSERT INTO t1(d) VALUES(x'4567');
} {1 {cannot store BLOB value in TEXT column t1.d}}

do_execsql_test strict1-6.1 {
  DELETE FROM t1;
  INSERT INTO t1(e) VALUES(1),(2.5),('3'),('4.5'),(6.0),(NULL);
  SELECT typeof(e), e FROM t1;
} {real 1.0 real 2.5 real 3.0 real 4.5 real 6.0 null {}}
do_catchsql_test strict1-6.2 {
  INSERT INTO t1(e) VALUES('xyz');
} {1 {cannot store TEXT value in REAL column t1.e}}
do_catchsql_test strict1-6.3 {
  INSERT INTO t1(e) VALUES(x'3456');
} {1 {cannot store BLOB value in REAL column t1.e}}

ifcapable altertable {
  do_execsql_test strict1-7.1 {
    DROP TABLE IF EXISTS t4;
    CREATE TABLE t4(
      a INT AS (b*2) VIRTUAL,
      b INT AS (c*2) STORED,
      c INT PRIMARY KEY
    ) STRICT;
    INSERT INTO t4(c) VALUES(1);
    SELECT * FROM t4;
  } {4 2 1}
  do_catchsql_test strict1-7.2 {
    ALTER TABLE t4 ADD COLUMN d VARCHAR;
  } {1 {error in table t4 after add column: unknown datatype for t4.d: "VARCHAR"}}
  do_catchsql_test strict1-7.3 {
    ALTER TABLE t4 ADD COLUMN d;
  } {1 {error in table t4 after add column: missing datatype for t4.d}}
}

# 2022-01-17 https://sqlite.org/forum/forumpost/fa012c77796d9399
# 
reset_db
do_execsql_test strict1-8.1 {
  CREATE TABLE csv_import_table (
    "debit" TEXT,
    "credit" TEXT
  );
  INSERT INTO csv_import_table VALUES ('', '250.00');
  CREATE TABLE IF NOT EXISTS transactions (
      debit REAL,
      credit REAL,
      amount REAL GENERATED ALWAYS AS (ifnull(credit, 0.0) - ifnull(debit, 0.0))
  ) STRICT;
  INSERT INTO transactions
  SELECT
      nullif(debit, '') AS debit,
      nullif(credit, '') AS credit
  FROM csv_import_table;
  SELECT * FROM transactions;
} {{} 250.0 250.0}
do_execsql_test strict1-8.2 {
  CREATE TABLE t1(x REAL, y REAL AS (x)) STRICT;
  INSERT INTO t1 VALUES(5),(4611686018427387904);
  SELECT *, '|' FROM t1;
} {/5.0 5.0 4.6116\d*e\+18 4.6116\d+e\+18 |/}

finish_test

Added test/strict2.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2021-08-19
#
# 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 STRICT tables.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix strict2

# PRAGMA integrity_check on a STRICT table should verify that
# all of the values are of the correct type.
#
do_execsql_test strict2-1.1 {
  CREATE TABLE t1(
    a INT,
    b INTEGER,
    c TEXT,
    d REAL,
    e BLOB
  ) STRICT;
  CREATE TABLE t1nn(
    a INT NOT NULL,
    b INTEGER NOT NULL,
    c TEXT NOT NULL,
    d REAL NOT NULL,
    e BLOB NOT NULL
  ) STRICT;
  CREATE TABLE t2(a,b,c,d,e);
  INSERT INTO t1(a,b,c,d,e) VALUES(1,1,'one',1.0,x'b1'),(2,2,'two',2.25,x'b2b2b2');
  PRAGMA writable_schema=on;
  UPDATE sqlite_schema SET rootpage=(SELECT rootpage FROM sqlite_schema WHERE name='t1');
} {}
db close
sqlite3 db test.db
do_execsql_test strict2-1.2 {
  PRAGMA quick_check('t1');
} {ok}
do_execsql_test strict2-1.3 {
  UPDATE t2 SET a=2.5 WHERE b=2;
  PRAGMA quick_check('t1');
} {{non-INT value in t1.a}}
do_execsql_test strict2-1.4 {
  UPDATE t2 SET a='xyz' WHERE b=2;
  PRAGMA quick_check('t1');
} {{non-INT value in t1.a}}
do_execsql_test strict2-1.5 {
  UPDATE t2 SET a=x'445566' WHERE b=2;
  PRAGMA quick_check('t1');
} {{non-INT value in t1.a}}
do_execsql_test strict2-1.6 {
  UPDATE t2 SET a=2.5 WHERE b=2;
  PRAGMA quick_check('t1nn');
} {{non-INT value in t1nn.a}}
do_execsql_test strict2-1.7 {
  UPDATE t2 SET a='xyz' WHERE b=2;
  PRAGMA quick_check('t1nn');
} {{non-INT value in t1nn.a}}
do_execsql_test strict2-1.8 {
  UPDATE t2 SET a=x'445566' WHERE b=2;
  PRAGMA quick_check('t1nn');
} {{non-INT value in t1nn.a}}

do_execsql_test strict2-1.13 {
  UPDATE t2 SET a=2 WHERE b=2;
  UPDATE t2 SET b=2.5 WHERE a=2;
  PRAGMA quick_check('t1');
} {{non-INTEGER value in t1.b}}
do_execsql_test strict2-1.14 {
  UPDATE t2 SET b='two' WHERE a=2;
  PRAGMA quick_check('t1');
} {{non-INTEGER value in t1.b}}
do_execsql_test strict2-1.15 {
  UPDATE t2 SET b=x'b0b1b2b3b4' WHERE a=2;
  PRAGMA quick_check('t1');
} {{non-INTEGER value in t1.b}}
do_execsql_test strict2-1.16 {
  UPDATE t2 SET b=NULL WHERE a=2;
  PRAGMA quick_check('t1');
} {ok}
do_execsql_test strict2-1.17 {
  UPDATE t2 SET b=2.5 WHERE a=2;
  PRAGMA quick_check('t1nn');
} {{non-INTEGER value in t1nn.b}}
do_execsql_test strict2-1.18 {
  UPDATE t2 SET b=NULL WHERE a=2;
  PRAGMA quick_check('t1nn');
} {{NULL value in t1nn.b}}

do_execsql_test strict2-1.23 {
  UPDATE t2 SET b=2 WHERE a=2;
  UPDATE t2 SET c=9 WHERE a=2;
  PRAGMA quick_check('t1');
} {{non-TEXT value in t1.c}}
do_execsql_test strict2-1.24 {
  UPDATE t2 SET c=9.5 WHERE a=2;
  PRAGMA quick_check('t1');
} {{non-TEXT value in t1.c}}
do_execsql_test strict2-1.25 {
  UPDATE t2 SET c=x'b0b1b2b3b4' WHERE a=2;
  PRAGMA quick_check('t1');
} {{non-TEXT value in t1.c}}

do_execsql_test strict2-1.33 {
  UPDATE t2 SET c='two' WHERE a=2;
  UPDATE t2 SET d=9 WHERE a=2;
  PRAGMA quick_check('t1');
} {ok}
do_execsql_test strict2-1.34 {
  UPDATE t2 SET d='nine' WHERE a=2;
  PRAGMA quick_check('t1');
} {{non-REAL value in t1.d}}
do_execsql_test strict2-1.35 {
  UPDATE t2 SET d=x'b0b1b2b3b4' WHERE a=2;
  PRAGMA quick_check('t1');
} {{non-REAL value in t1.d}}

do_execsql_test strict2-1.43 {
  UPDATE t2 SET d=2.5 WHERE a=2;
  UPDATE t2 SET e=9 WHERE a=2;
  PRAGMA quick_check('t1');
} {{non-BLOB value in t1.e}}
do_execsql_test strict2-1.44 {
  UPDATE t2 SET e=9.5 WHERE a=2;
  PRAGMA quick_check('t1');
} {{non-BLOB value in t1.e}}
do_execsql_test strict2-1.45 {
  UPDATE t2 SET e='hello' WHERE a=2;
  PRAGMA quick_check('t1');
} {{non-BLOB value in t1.e}}

do_execsql_test strict2-2.0 {
  DROP TABLE IF EXISTS t2;
  CREATE TABLE t2(a INT, b ANY) STRICT;
  INSERT INTO t2(a,b) VALUES(1,2),(3,4.5),(5,'six'),(7,x'8888'),(9,NULL);
  PRAGMA integrity_check(t2);
} {ok}

do_execsql_test strict2-3.0 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(id ANY PRIMARY KEY, x TEXT);
  INSERT INTO t1 VALUES(1,2),('three','four'),(x'5555','six'),(NULL,'eight');
  PRAGMA writable_schema=ON;
  UPDATE sqlite_schema SET sql=(sql||'STRICT') WHERE name='t1';
  PRAGMA writable_schema=RESET;
  PRAGMA integrity_check(t1);
} {{NULL value in t1.id}}

finish_test

Changes to test/subquery.test.

473
474
475
476
477
478
479
480

481
482
483
484
485
486
487
473
474
475
476
477
478
479

480
481
482
483
484
485
486
487







-
+







    INSERT INTO t4 VALUES('four',4);
    CREATE TABLE t5(a,b);
    INSERT INTO t5 VALUES(1,11);
    INSERT INTO t5 VALUES(2,22);
    INSERT INTO t5 VALUES(3,33);
    INSERT INTO t5 VALUES(4,44);
    SELECT b FROM t5 WHERE a IN 
       (SELECT callcnt(y)+0 FROM t4 WHERE x="two")
       (SELECT callcnt(y)+0 FROM t4 WHERE x='two')
  }
} {22}
do_test subquery-5.2 {
  # This is the key test.  The subquery should have only run once.  If
  # The double-quoted identifier "two" were causing the subquery to be
  # processed as a correlated subquery, then it would have run 4 times.
  set callcnt
589
590
591
592
593
594
595
596



















597
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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# is plugged.
#
do_execsql_test subquery-8.1 {
  CREATE TABLE t8(a TEXT, b INT);
  SELECT (SELECT 0 FROM (SELECT * FROM t1)) AS x WHERE x;
  SELECT (SELECT 0 FROM (SELECT * FROM (SELECT 0))) AS x WHERE x;
} {}

# 2022-01-12 https://sqlite.org/forum/forumpost/0ec80f12d02acb3f
# 
reset_db
do_execsql_test subquery-9.1 {
  CREATE TABLE t1(x);
  INSERT INTO t1 VALUES(1),(1),(1);
  SELECT (SELECT DISTINCT x FROM t1 ORDER BY +x LIMIT 1 OFFSET 100) FROM t1;
} {{} {} {}}
do_execsql_test subquery-9.2 {
  SELECT (SELECT DISTINCT x FROM t1 ORDER BY +x LIMIT 1 OFFSET 0) FROM t1;
} {1 1 1}
do_execsql_test subquery-9.3 {
  INSERT INTO t1 VALUES(2);
  SELECT (SELECT DISTINCT x FROM t1 ORDER BY +x LIMIT 1 OFFSET 1) FROM t1;
} {2 2 2 2}
do_execsql_test subquery-9.4 {
  SELECT (SELECT DISTINCT x FROM t1 ORDER BY +x LIMIT 1 OFFSET 2) FROM t1;
} {{} {} {} {}}

finish_test

Changes to test/subquery2.test.

193
194
195
196
197
198
199

















200
201
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


  }
} {
  do_catchsql_test 4.$tn $sql [list {*}{
    1 {ORDER BY clause should come after UNION ALL not before}
  }]
}

#-------------------------------------------------------------------------
# Test that ticket [9cdc5c46] is fixed.
#
reset_db
do_execsql_test 5.0 {
  CREATE TABLE t1(x);
  INSERT INTO t1 VALUES('ALFKI');
  INSERT INTO t1 VALUES('ANATR');

  CREATE TABLE t2(y, z);
  CREATE INDEX t2y ON t2 (y);
  INSERT INTO t2 VALUES('ANATR', '1997-08-08 00:00:00');
  INSERT INTO t2 VALUES('ALFKI', '1997-08-25 00:00:00');
}
do_execsql_test 5.1 {
  SELECT ( SELECT y FROM t2 WHERE x = y ORDER BY y, z) FROM t1;
} {ALFKI ANATR}

finish_test

Changes to test/substr.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20













-







# 2007 May 14
#
# 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 the built-in SUBSTR() functions.
#
# $Id: substr.test,v 1.7 2009/02/03 13:10:54 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable !tclvar {
  finish_test
  return
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
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







-
+















-
+







    execsql {
      SELECT substr(t, $i1, $i2) FROM t1
    }
  }] [list $result]
  set qstr '[string map {' ''} $string]'
  do_test substr-$id.2 [subst {
    execsql {
      SELECT substr($qstr, $i1, $i2)
      SELECT substring($qstr, $i1, $i2)
    }
  }] [list $result]
}
proc subblob-test {id hex i1 i2 hexresult} {
  db eval "
    DELETE FROM t1;
    INSERT INTO t1(b) VALUES(x'$hex')
  "
  do_test substr-$id.1 [subst {
    execsql {
      SELECT hex(substr(b, $i1, $i2)) FROM t1
    }
  }] [list $hexresult]
  do_test substr-$id.2 [subst {
    execsql {
      SELECT hex(substr(x'$hex', $i1, $i2))
      SELECT hex(substring(x'$hex', $i1, $i2))
    }
  }] [list $hexresult]
}

# Basic SUBSTR functionality
#
substr-test 1.1 abcdefg 1 1 a
89
90
91
92
93
94
95
96

97
98
99
100
101
102
103
88
89
90
91
92
93
94

95
96
97
98
99
100
101
102







-
+







do_test substr-1.91 {
  db eval {SELECT ifnull(substr(NULL,1),'nil')}
} nil
do_test substr-1.92 {
  db eval {SELECT ifnull(substr('abcdefg',NULL,1),'nil')}
} nil
do_test substr-1.93 {
  db eval {SELECT ifnull(substr('abcdefg',NULL),'nil')}
  db eval {SELECT ifnull(substring('abcdefg',NULL),'nil')}
} nil
do_test substr-1.94 {
  db eval {SELECT ifnull(substr('abcdefg',1,NULL),'nil')}
} nil

# Make sure everything works with long unicode characters
#
145
146
147
148
149
150
151
152

153
154
155
156
157
158
159
144
145
146
147
148
149
150

151
152
153
154
155
156
157
158







-
+







    execsql {
      SELECT substr(t, $idx) FROM t1
    }
  }] [list $result]
  set qstr '[string map {' ''} $string]'
  do_test substr-$id.2 [subst {
    execsql {
      SELECT substr($qstr, $idx)
      SELECT substring($qstr, $idx)
    }
  }] [list $result]
}
substr-2-test 5.1 abcdefghijklmnop 5 efghijklmnop
substr-2-test 5.2 abcdef -5 bcdef

finish_test

Changes to test/subtype1.test.

23
24
25
26
27
28
29




























30
31
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


} {123}
do_execsql_test subtype1-120 {
  SELECT typeof(test_setsubtype('hello',123));
} {text}
do_execsql_test subtype1-130 {
  SELECT test_setsubtype('hello',123);
} {hello}

# 2022-06-09
# https://sqlite.org/forum/forumpost/3d9caa45cbe38c78
#
# Avoid carrying subtypes through into a subquery that has been flattened
# or to which the outer WHERE clause has been pushed down.
#
reset_db
do_execsql_test subtype1-200 {
  CREATE TABLE t1(a); INSERT INTO t1 VALUES ('x');
  CREATE VIEW t2(b) AS SELECT json(TRUE);
  CREATE TABLE t3(b); INSERT INTO t3 VALUES(json(TRUE));
}
do_execsql_test subtype1-210 {
  SELECT * FROM t3, t1 WHERE NOT json_quote(b);
} {1 x}
do_execsql_test subtype1-220 {
  SELECT * FROM t2, t1 WHERE NOT json_quote(b);
} {1 x}
do_execsql_test subtype1-230 {
  WITH t4(a) AS MATERIALIZED (SELECT json(1)) SELECT subtype(a) FROM t4;
} {0}
do_execsql_test subtype1-231 {
  WITH t4(a) AS NOT MATERIALIZED (SELECT json(1)) SELECT subtype(a) FROM t4;
} {0}




finish_test

Changes to test/swarmvtab.test.

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
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







-
-
+
+







-
-
+
+













-
-
+
+







}

db func fetch_db fetch_db

do_catchsql_test 3.1 {
  CREATE VIRTUAL TABLE temp.xyz USING swarmvtab(
    'VALUES
        ("test.db1", "t1", 1, 10),
        ("test.db2", "t1", 11, 20)
        (''test.db1'', ''t1'', 1, 10),
        (''test.db2'', ''t1'', 11, 20)
    ', 'fetch_db_no_such_function'
  );
} {1 {sql error: no such function: fetch_db_no_such_function}}

do_catchsql_test 3.2 {
  CREATE VIRTUAL TABLE temp.xyz USING swarmvtab(
    'VALUES
        ("test.db1", "t1", 1, 10),
        ("test.db2", "t1", 11, 20)
        (''test.db1'', ''t1'', 1, 10),
        (''test.db2'', ''t1'', 11, 20)
    ', 'fetch_db'
  );
} {1 {fetch_db error!}}

do_execsql_test 3.3.1 {
  ATTACH 'test.db1' AS aux;
  CREATE TABLE aux.t1(a INTEGER PRIMARY KEY, b);
  INSERT INTO aux.t1 VALUES(1, NULL);
  INSERT INTO aux.t1 VALUES(2, NULL);
  INSERT INTO aux.t1 VALUES(9, NULL);
  DETACH aux;
  CREATE VIRTUAL TABLE temp.xyz USING swarmvtab(
    'VALUES
        ("test.db1", "t1", 1, 10),
        ("test.db2", "t1", 11, 20)
        (''test.db1'', ''t1'', 1, 10),
        (''test.db2'', ''t1'', 11, 20)
    ', 'fetch_db'
  );
} {}

do_catchsql_test 3.3.2 { SELECT * FROM xyz } {1 {fetch_db error!}}


Changes to test/swarmvtab3.test.

144
145
146
147
148
149
150

151
152
153
154

155

156
157
158
159
160
161
162
144
145
146
147
148
149
150
151
152
153
154

155
156
157
158
159
160
161
162
163
164







+



-
+

+








catch { array unset ::dbcache }

# Set up 100 databases with filenames "remote_test.dbN", where N is a
# random integer between 0 and 1,000,000
# 0 and 99.
do_test 2.1 {
  catch { array unset ctx_used } 
  for {set i 0} {$i < 100} {incr i} {
    while 1 {
      set ctx [expr abs(int(rand() *1000000))]
      if {[info exists ::dbcache($ctx)]==0} break
      if {[info exists ctx_used($ctx)]==0} break
    }
    set ctx_used($ctx) 1

    set file test_remote.db$ctx
    forcedelete $file
    forcedelete test.db$i
    sqlite3 rrr $file
    rrr eval {
      CREATE TABLE t1(a INTEGER PRIMARY KEY, b);

Changes to test/symlink.test.

33
34
35
36
37
38
39



















40
41
42
43
44

45
46
47
48
49
50
51
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
+







forcedelete test.db2
do_test 1.1 {
  file link test.db2 test.db
  sqlite3 db2 test.db2
  sqlite3_db_filename db2 main
} [file join [pwd] test.db]

# But not with the -nofollow flag
#
do_test 1.1.2 {
  db2 close
  set rc [catch {sqlite3 db2 test.db2 -nofollow 1} msg]
  lappend rc $msg
} {1 {unable to open database file}}

# If the main database is successfully opened with -nofollow, then -nofollow
# is also used for ATTACH.
#
do_test 1.1.3 {
  catch {db2 close}
  sqlite3 db2 test.db -nofollow 1
} {}
do_test 1.1.4 {
  catchsql {ATTACH 'test.db2' AS aux1;} db2
} {1 {unable to open database: test.db2}}

# Test that if the symlink points to a file that does not exists, it is
# created when it is opened.
#
do_test 1.2.1 {
  db2 close
  catch {db2 close}
  db close
  forcedelete test.db
  file exists test.db
} 0
do_test 1.2.2 {
  sqlite3 db2 test.db2
  file exists test.db
183
184
185
186
187
188
189
190




























191
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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  db close
  sqlite3 db w/test.db
  db eval { SELECT * FROM t1 }
} {hello world}
do_test 4.4.2 {
  list [file exists x/test.db-wal] [file exists w/test.db-wal]
} {1 0}

#-------------------------------------------------------------------------
# Check that extra ".." in a path are ignored.
reset_db
do_execsql_test 5.0 {
  CREATE TABLE xyz(x, y, z);
  INSERT INTO xyz VALUES(1, 2, 3);
}

set path [pwd]
set nLink [llength [split $path /]]
set path "[string repeat ../ [expr $nLink*2]]..${path}/test.db"

sqlite3 db2 $path
do_execsql_test -db db2 5.1 {
  SELECT * FROM xyz;
} {1 2 3}
db close

forcedelete test.db2
file link test.db2 $path
sqlite3 db2 test.db2
do_execsql_test -db db2 5.2 {
  SELECT * FROM xyz;
} {1 2 3}
forcedelete test.db2



finish_test

Added test/symlink2.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019 November 18
#
# 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 that SQLite can follow symbolic links.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix symlink2

# This only runs on Windows.
if {$::tcl_platform(platform)!="windows"} {
  finish_test
  return
}

proc createWin32Symlink { link target } {
  exec -- $::env(ComSpec) /c mklink \
      [file nativename $link] [file nativename $target]
  return ""
}

proc deleteWin32Symlink { link } {
  exec -- $::env(ComSpec) /c del [file nativename $link]
  return ""
}

proc canCreateWin32Symlink {} {
  set link [file join $::testdir lnk[pid].sym]
  if {[file exists $link]} { return 0 }
  set target [info nameofexecutable]
  if {[catch {createWin32Symlink $link $target}] == 0} {
    deleteWin32Symlink $link
    return 1
  }
  return 0
}

# Creating symlinks may require administrator privileges on Windows.
if {![canCreateWin32Symlink]} {
  finish_test
  return
}

# Ensure that test.db has been created.
#
do_execsql_test 1.0 {
  CREATE TABLE t1(x, y);
  INSERT INTO t1 VALUES(1,9999);
}

do_test 2.0 {
  createWin32Symlink link.db test.db
} {}

do_test 2.1 {
  file exists test.db
} {1}

do_test 2.2 {
  file exists link.db
} {1}

do_test 3.1 {
  execsql { SELECT x, y FROM t1; } db
} {1 9999}

do_test 3.2 {
  sqlite3 db2 link.db
  execsql { SELECT x, y FROM t1; } db2
} {1 9999}

do_test 3.3 {
  sqlite3 db3 test.db -nofollow true
  execsql { SELECT x, y FROM t1; } db3
} {1 9999}

do_test 3.4 {
  db3 close
} {}

do_test 3.5 {
  list [catch {
    sqlite3 db4 link.db -nofollow true
    execsql { SELECT x, y FROM t1; } db4
  } res] $res
} {1 {unable to open database file}}

catch {db4 close}

do_test 4.0 {
  db2 close
  deleteWin32Symlink link.db
} {}

do_test 4.1 {
  file exists test.db
} {1}

do_test 4.2 {
  file exists link.db
} {0}

do_test 5.1 {
  execsql { SELECT x, y FROM t1; } db
} {1 9999}

finish_test

Changes to test/tabfunc01.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
44
45
46
47
48
49







-
+

+
+
+
+
+
+







do_execsql_test tabfunc01-1.1 {
  SELECT *, '|' FROM generate_series WHERE start=1 AND stop=9 AND step=2;
} {1 | 3 | 5 | 7 | 9 |}
do_execsql_test tabfunc01-1.1b {
  PRAGMA table_xinfo(generate_series);
} {0 value {} 0 {} 0 0 1 start {} 0 {} 0 1 2 stop {} 0 {} 0 1 3 step {} 0 {} 0 1}
do_execsql_test tabfunc01-1.2 {
  SELECT *, '|' FROM generate_series LIMIT 5;
  SELECT *, '|' FROM generate_series(0) LIMIT 5;
} {0 | 1 | 2 | 3 | 4 |}
do_catchsql_test tabfunc01-1.2b {
  SELECT *, '|' FROM generate_series LIMIT 5;
} {1 {first argument to "generate_series()" missing or unusable}}
do_catchsql_test tabfunc01-1.2c {
  SELECT *, '|' FROM generate_series(value) LIMIT 5;
} {1 {first argument to "generate_series()" missing or unusable}}
do_catchsql_test tabfunc01-1.3 {
  CREATE VIRTUAL TABLE t1 USING generate_series;
} {1 {no such module: generate_series}}
do_execsql_test tabfunc01-1.4 {
  SELECT * FROM generate_series(1,9,2);
} {1 3 5 7 9}
do_execsql_test tabfunc01-1.5 {
100
101
102
103
104
105
106
107

108
109
110
111
112













































113
114
115
116
117
118
119
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







-
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







} {2 1 | 2 2 | 3 1 | 3 2 | 3 3 |}
do_execsql_test tabfunc01-2.2 {
  SELECT *, '|' FROM (SELECT x FROM t1) AS y, generate_series(1,y.x)
  ORDER BY 1, 2;
} {2 1 | 2 2 | 3 1 | 3 2 | 3 3 |}

do_execsql_test tabfunc01-2.50 {
  SELECT * FROM generate_series() LIMIT 5;
  SELECT * FROM generate_series(0) LIMIT 5;
} {0 1 2 3 4}

do_execsql_test tabfunc01-3.1 {
  SELECT DISTINCT value FROM generate_series(1,x), t1 ORDER BY 1;
} {1 2 3}

do_eqp_test tabfunc01-3.10 {
  SELECT value FROM generate_series(1,10) ORDER BY value;
} {
  QUERY PLAN
  `--SCAN generate_series VIRTUAL TABLE INDEX 19:
}
do_eqp_test tabfunc01-3.11 {
  SELECT value FROM generate_series(1,10) ORDER BY +value;
} {
  QUERY PLAN
  |--SCAN generate_series VIRTUAL TABLE INDEX 3:
  `--USE TEMP B-TREE FOR ORDER BY
}
do_eqp_test tabfunc01-3.12 {
  SELECT value FROM generate_series(1,10) ORDER BY value, stop;
} {
  QUERY PLAN
  `--SCAN generate_series VIRTUAL TABLE INDEX 19:
}
do_eqp_test tabfunc01-3.13 {
  SELECT value FROM generate_series(1,10) ORDER BY stop, value;
} {
  QUERY PLAN
  |--SCAN generate_series VIRTUAL TABLE INDEX 3:
  `--USE TEMP B-TREE FOR ORDER BY
}


do_eqp_test tabfunc01-3.20 {
  WITH t1(a) AS (
    SELECT value FROM generate_series(0,10,2)
    UNION ALL
    SELECT value FROM generate_series(9,18,3)
  )
  SELECT * FROM t1 ORDER BY a;
} {
  QUERY PLAN
  `--MERGE (UNION ALL)
     |--LEFT
     |  `--SCAN generate_series VIRTUAL TABLE INDEX 23:
     `--RIGHT
        `--SCAN generate_series VIRTUAL TABLE INDEX 23:
}
  

# Eponymous virtual table exists in all schemas.
#
do_execsql_test tabfunc01-4.1 {
  SELECT * FROM main.generate_series(1,4)
} {1 2 3 4}
do_execsql_test tabfunc01-4.2 {
213
214
215
216
217
218
219





















































220
221
222
223
224
225
226
227
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








do_test tabfunc01-750 {
  db eval {
    SELECT aa.value, bb.value, '|'
      FROM carray(inttoptr($PTR4),5,'double') AS aa
      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 |}

# ticket https://www.sqlite.org/src/info/2ae0c599b735d59e
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

finish_test

Changes to test/tclsqlite.test.

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
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







+



-
+
















-
+







#
# $Id: tclsqlite.test,v 1.73 2009/03/16 13:19:36 danielk1977 Exp $

catch {sqlite3}

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix tcl

# Check the error messages generated by tclsqlite
#
set r "sqlite_orig HANDLE ?FILENAME? ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN? ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?"
set r "sqlite_orig HANDLE ?FILENAME? ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN? ?-nofollow BOOLEAN? ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?"
if {[sqlite3 -has-codec]} {
  append r " ?-key CODECKEY?"
}
do_test tcl-1.1 {
  set v [catch {sqlite3 -bogus} msg]
  regsub {really_sqlite3} $msg {sqlite3} msg
  lappend v $msg
} [list 1 "wrong # args: should be \"$r\""]
do_test tcl-1.1.1 {
  set v [catch {sqlite3} msg]
  regsub {really_sqlite3} $msg {sqlite3} msg
  lappend v $msg
} [list 1 "wrong # args: should be \"$r\""]
do_test tcl-1.2 {
  set v [catch {db bogus} msg]
  lappend v $msg
} {1 {bad option "bogus": must be authorizer, backup, busy, cache, changes, close, collate, collation_needed, commit_hook, complete, copy, deserialize, enable_load_extension, errorcode, eval, exists, function, incrblob, interrupt, last_insert_rowid, nullvalue, onecolumn, preupdate, profile, progress, rekey, restore, rollback_hook, serialize, status, timeout, total_changes, trace, trace_v2, transaction, unlock_notify, update_hook, version, or wal_hook}}
} {1 {bad option "bogus": must be authorizer, backup, bind_fallback, busy, cache, changes, close, collate, collation_needed, commit_hook, complete, config, copy, deserialize, enable_load_extension, errorcode, erroroffset, eval, exists, function, incrblob, interrupt, last_insert_rowid, nullvalue, onecolumn, preupdate, profile, progress, rekey, restore, rollback_hook, serialize, status, timeout, total_changes, trace, trace_v2, transaction, unlock_notify, update_hook, version, or wal_hook}}
do_test tcl-1.2.1 {
  set v [catch {db cache bogus} msg]
  lappend v $msg
} {1 {bad option "bogus": must be flush or size}}
do_test tcl-1.2.2 {
  set v [catch {db cache} msg]
  lappend v $msg
161
162
163
164
165
166
167
168

169
170
171
172
173
174
175
162
163
164
165
166
167
168

169
170
171
172
173
174
175
176







-
+







catch {unset ::result}
do_test tcl-2.1 {
  execsql "CREATE TABLE t\u0123x(a int, b\u1235 float)"
} {}
ifcapable schema_pragmas {
  do_test tcl-2.2 {
    execsql "PRAGMA table_info(t\u0123x)"
  } "0 a int 0 {} 0 1 b\u1235 float 0 {} 0"
  } "0 a INT 0 {} 0 1 b\u1235 float 0 {} 0"
}
do_test tcl-2.3 {
  execsql "INSERT INTO t\u0123x VALUES(1,2.3)"
  db eval "SELECT * FROM t\u0123x" result break
  set result(*)
} "a b\u1235"

366
367
368
369
370
371
372

373
374
375



376
377
378
379
380
381
382
367
368
369
370
371
372
373
374



375
376
377
378
379
380
381
382
383
384







+
-
-
-
+
+
+







      if {$n<=0} {return 0}
      set nm1 [expr {$n-1}]
      return [expr {[db eval {SELECT r1($nm1)}]+$n}]
    }
    db function r1 userfunc_r1
    execsql {SELECT r1(10)}
  } {55}
  # Fails under -fsanitize=address,undefined due to stack overflow
  do_test tcl-9.11 {
    execsql {SELECT r1(100)}
  } {5050}
  # do_test tcl-9.11 {
  #   execsql {SELECT r1(100)}
  # } {5050}
}

# Tests for the new transaction method
#
do_test tcl-10.1 {
  db transaction {}
} {}
707
708
709
710
711
712
713


714




715





716





717





























































































































































718
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
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







+
+
-
+
+
+
+

+
+
+
+
+

+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  unset -nocomplain x
  db eval -withoutnulls {SELECT * FROM t1} x {
    lappend res $x(a) [array names x]
  }
  set res
} {1 {a b *} 2 {a *} 3 {a b *}}

#-------------------------------------------------------------------------
# Test the -type option to [db function].

#
reset_db
proc add {a b} { return [expr $a + $b] }
proc ret {a} { return $a }

db function add_i -returntype integer add 
db function add_r -ret        real    add
db function add_t -return     text    add 
db function add_b -returntype blob    add 
db function add_a -returntype any     add 

db function ret_i -returntype int     ret 
db function ret_r -returntype real    ret
db function ret_t -returntype text    ret 
db function ret_b -returntype blob    ret 
db function ret_a -r          any     ret 

do_execsql_test 17.0 {
  SELECT quote( add_i(2, 3) );
  SELECT quote( add_r(2, 3) ); 
  SELECT quote( add_t(2, 3) ); 
  SELECT quote( add_b(2, 3) ); 
  SELECT quote( add_a(2, 3) ); 
} {5 5.0 '5' X'35' 5}

do_execsql_test 17.1 {
  SELECT quote( add_i(2.2, 3.3) );
  SELECT quote( add_r(2.2, 3.3) ); 
  SELECT quote( add_t(2.2, 3.3) ); 
  SELECT quote( add_b(2.2, 3.3) ); 
  SELECT quote( add_a(2.2, 3.3) ); 
} {5.5 5.5 '5.5' X'352E35' 5.5}

do_execsql_test 17.2 {
  SELECT quote( ret_i(2.5) );
  SELECT quote( ret_r(2.5) ); 
  SELECT quote( ret_t(2.5) ); 
  SELECT quote( ret_b(2.5) ); 
  SELECT quote( ret_a(2.5) ); 
} {2.5 2.5 '2.5' X'322E35' 2.5}

do_execsql_test 17.3 {
  SELECT quote( ret_i('2.5') );
  SELECT quote( ret_r('2.5') ); 
  SELECT quote( ret_t('2.5') ); 
  SELECT quote( ret_b('2.5') ); 
  SELECT quote( ret_a('2.5') ); 
} {2.5 2.5 '2.5' X'322E35' '2.5'}

do_execsql_test 17.4 {
  SELECT quote( ret_i('abc') );
  SELECT quote( ret_r('abc') ); 
  SELECT quote( ret_t('abc') ); 
  SELECT quote( ret_b('abc') ); 
  SELECT quote( ret_a('abc') ); 
} {'abc' 'abc' 'abc' X'616263' 'abc'}

do_execsql_test 17.5 {
  SELECT quote( ret_i(X'616263') );
  SELECT quote( ret_r(X'616263') ); 
  SELECT quote( ret_t(X'616263') ); 
  SELECT quote( ret_b(X'616263') ); 
  SELECT quote( ret_a(X'616263') ); 
} {'abc' 'abc' 'abc' X'616263' X'616263'}

do_test 17.6.1 {
  list [catch { db function xyz -return object ret } msg] $msg
} {1 {bad type "object": must be integer, real, text, blob, or any}}

do_test 17.6.2 {
  list [catch { db function xyz -return ret } msg] $msg
} {1 {option requires an argument: -return}}

do_test 17.6.3 {
  list [catch { db function xyz -n object ret } msg] $msg
} {1 {bad option "-n": must be -argcount, -deterministic, -directonly, -innocuous, or -returntype}}

# 2019-02-28: The "bind_fallback" command.
#
do_test 18.100 {
  unset -nocomplain bindings abc def ghi jkl mno e01 e02
  set bindings(abc) [expr {1+2}]
  set bindings(def) {hello}
  set bindings(ghi) [expr {3.1415926*1.0}]
  proc bind_callback {nm} {
    global bindings
    set n2 [string range $nm 1 end]
    if {[info exists bindings($n2)]} {
      return $bindings($n2)
    }
    if {[string match e* $n2]} {
      error "no such variable: $nm"
    }
    return -code return {}
  }
  db bind_fallback bind_callback
  db eval {SELECT $abc, typeof($abc), $def, typeof($def), $ghi, typeof($ghi)}
} {3 integer hello text 3.1415926 real}
do_test 18.110 {
  db eval {SELECT quote(@def), typeof(@def)}
} {X'68656C6C6F' blob}
do_execsql_test 18.120 {
  SELECT typeof($mno);
} {null}
do_catchsql_test 18.130 {
  SELECT $e01;
} {1 {no such variable: $e01}}
do_test 18.140 {
  db bind_fallback
} {bind_callback}
do_test 18.200 {
  db bind_fallback {}
  db eval {SELECT $abc, typeof($abc), $def, typeof($def), $ghi, typeof($ghi)}
} {{} null {} null {} null}
do_test 18.300 {
  unset -nocomplain bindings
  proc bind_callback {nm} {lappend ::bindings $nm}
  db bind_fallback bind_callback
  db eval {SELECT $abc, @def, $ghi(123), :mno}
  set bindings
} {{$abc} @def {$ghi(123)} :mno}
do_test 18.900 {
  set rc [catch {db bind_fallback a b} msg]
  lappend rc $msg
} {1 {wrong # args: should be "db bind_fallback ?CALLBACK?"}}
do_test 18.910 {
  db bind_fallback bind_fallback_does_not_exist
} {}
do_catchsql_test 19.911 {
  SELECT $abc, typeof($abc), $def, typeof($def), $ghi, typeof($ghi);
} {1 {invalid command name "bind_fallback_does_not_exist"}}
db bind_fallback {}

#-------------------------------------------------------------------------
do_test 20.0 {
  db transaction {
    db close
  }
} {}

do_test 20.1 {
  sqlite3 db test.db
  set rc [catch {
    db eval {SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3} { db close }
  } msg]
  list $rc $msg
} {1 {invalid command name "db"}}
  

proc closedb {} {
  db close
  return 10
}
proc func1 {} { return 1 }

sqlite3 db test.db
db func closedb closedb
db func func1 func1

do_test 20.2 {
  set rc [catch {
    db eval {
      SELECT closedb(),func1() UNION ALL SELECT 20,30 UNION ALL SELECT 30,40
    }
  } msg]
  list $rc $msg
} {0 {10 1 20 30 30 40}}

sqlite3 db :memory:
do_test 21.1 {
  catch {db eval {SELECT 1 2 3;}} msg
  db erroroffset
} {9}

finish_test

Changes to test/tempdb2.test.

93
94
95
96
97
98
99
100
93
94
95
96
97
98
99








-
}

do_execsql_test 2.2 {
  SELECT b FROM t1 WHERE a = 10001;
} "[int2str 1001][int2str 1001][int2str 1001]"

finish_test

Changes to test/temptable2.test.

1
2
3
4
5
6
7
8
9
10



11
12
13
14
15
16
17
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20










+
+
+







# 2016 March 3
#
# 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.
#
#***********************************************************************
#
# TESTRUNNER: slow
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix temptable2

do_execsql_test 1.1 {
  CREATE TEMP TABLE t1(a, b);

Changes to test/tester.tcl.

84
85
86
87
88
89
90



91
92
93
94
95
96
97
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100







+
+
+







#
# Command to test whether or not --verbose=1 was specified on the command
# line (returns 0 for not-verbose, 1 for verbose and 2 for "verbose in the
# output file only").
#
#      verbose
#

# Only run this script once.  If sourced a second time, make it a no-op
if {[info exists ::tester_tcl_has_run]} return

# Set the precision of FP arithmatic used by the interpreter. And
# configure SQLite to take database file locks on the page that begins
# 64KB into the database file instead of the one 1GB in. This means
# the code that handles that special case can be tested without creating
# very large database files.
#
125
126
127
128
129
130
131

132
133
134
135
136
137
138
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142







+







      if {[info exists ::G(perm:presql)]} {
        [lindex $args 0] eval $::G(perm:presql)
      }
      if {[info exists ::G(perm:dbconfig)]} {
        set ::dbhandle [lindex $args 0]
        uplevel #0 $::G(perm:dbconfig)
      }
      [lindex $args 0] cache size 3
      set res
    } else {
      # This command is not opening a new database connection. Pass the
      # arguments through to the C implementation as the are.
      #
      uplevel 1 sqlite_orig $args
    }
169
170
171
172
173
174
175






176
177

178
179
180
181
182
183
184
173
174
175
176
177
178
179
180
181
182
183
184
185
186

187
188
189
190
191
192
193
194







+
+
+
+
+
+

-
+







proc get_pwd {} {
  if {$::tcl_platform(platform) eq "windows"} {
    #
    # NOTE: Cannot use [file normalize] here because it would alter the
    #       case of the result to what Tcl considers canonical, which would
    #       defeat the purpose of this procedure.
    #
    if {[info exists ::env(ComSpec)]} {
      set comSpec $::env(ComSpec)
    } else {
      # NOTE: Hard-code the typical default value.
      set comSpec {C:\Windows\system32\cmd.exe}
    }
    return [string map [list \\ /] \
        [string trim [exec -- $::env(ComSpec) /c echo %CD%]]]
        [string trim [exec -- $comSpec /c CD]]]
  } else {
    return [pwd]
  }
}

# Copy file $from into $to. This is used because some versions of
# TCL for windows (notably the 8.4.1 binary package shipped with the
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
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







+




















+
















+








# Print a HELP message and exit
#
proc print_help_and_quit {} {
  puts {Options:
  --pause                  Wait for user input before continuing
  --soft-heap-limit=N      Set the soft-heap-limit to N
  --hard-heap-limit=N      Set the hard-heap-limit to N
  --maxerror=N             Quit after N errors
  --verbose=(0|1)          Control the amount of output.  Default '1'
  --output=FILE            set --verbose=2 and output to FILE.  Implies -q
  -q                       Shorthand for --verbose=0
  --help                   This message
}
  exit 1
}

# The following block only runs the first time this file is sourced. It
# does not run in slave interpreters (since the ::cmdlinearg array is
# populated before the test script is run in slave interpreters).
#
if {[info exists cmdlinearg]==0} {

  # Parse any options specified in the $argv array. This script accepts the
  # following options:
  #
  #   --pause
  #   --soft-heap-limit=NN
  #   --hard-heap-limit=NN
  #   --maxerror=NN
  #   --malloctrace=N
  #   --backtrace=N
  #   --binarylog=N
  #   --soak=N
  #   --file-retries=N
  #   --file-retry-delay=N
  #   --start=[$permutation:]$testfile
  #   --match=$pattern
  #   --verbose=$val
  #   --output=$filename
  #   -q                                      Reduce output
  #   --testdir=$dir                          Run tests in subdirectory $dir
  #   --help
  #
  set cmdlinearg(soft-heap-limit)    0
  set cmdlinearg(hard-heap-limit)    0
  set cmdlinearg(maxerror)        1000
  set cmdlinearg(malloctrace)        0
  set cmdlinearg(backtrace)         10
  set cmdlinearg(binarylog)          0
  set cmdlinearg(soak)               0
  set cmdlinearg(file-retries)       0
  set cmdlinearg(file-retry-delay)   0
446
447
448
449
450
451
452



453
454
455
456
457
458
459
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475







+
+
+







        puts -nonewline "Press RETURN to begin..."
        flush stdout
        gets stdin
      }
      {^-+soft-heap-limit=.+$} {
        foreach {dummy cmdlinearg(soft-heap-limit)} [split $a =] break
      }
      {^-+hard-heap-limit=.+$} {
        foreach {dummy cmdlinearg(hard-heap-limit)} [split $a =] break
      }
      {^-+maxerror=.+$} {
        foreach {dummy cmdlinearg(maxerror)} [split $a =] break
      }
      {^-+malloctrace=.+$} {
        foreach {dummy cmdlinearg(malloctrace)} [split $a =] break
        if {$cmdlinearg(malloctrace)} {
          if {0==$::sqlite_options(memdebug)} {
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
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







+
+
+
+






-
+
+








+







    set ::G(output_fd) [open $cmdlinearg(output) w]
    fconfigure $::G(output_fd) -buffering line
  }

  if {$cmdlinearg(verbose)==""} {
    set cmdlinearg(verbose) 1
  }

  if {[info commands vdbe_coverage]!=""} {
    vdbe_coverage start
  }
}

# Update the soft-heap-limit each time this script is run. In that
# way if an individual test file changes the soft-heap-limit, it
# will be reset at the start of the next test file.
#
sqlite3_soft_heap_limit $cmdlinearg(soft-heap-limit)
sqlite3_soft_heap_limit64 $cmdlinearg(soft-heap-limit)
sqlite3_hard_heap_limit64 $cmdlinearg(hard-heap-limit)

# Create a test database
#
proc reset_db {} {
  catch {db close}
  forcedelete test.db
  forcedelete test.db-journal
  forcedelete test.db-wal
  forcedelete test.db-wal2
  sqlite3 db ./test.db
  set ::DB [sqlite3_connection_pointer db]
  if {[info exists ::SETUP_SQL]} {
    db eval $::SETUP_SQL
  }
}
reset_db
767
768
769
770
771
772
773



774
775
776
777
778
779
780
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805







+
+
+








  if {![info exists ::G(match)] || [string match $::G(match) $name]} {
    if {[catch {uplevel #0 "$cmd;\n"} result]} {
      output2_if_no_verbose -nonewline $name...
      output2 "\nError: $result"
      fail_test $name
    } else {
      if {[permutation]=="maindbname"} {
        set result [string map [list [string tolower ICECUBE] main] $result]
      }
      if {[regexp {^[~#]?/.*/$} $expected]} {
        # "expected" is of the form "/PATTERN/" then the result if correct if
        # regular expression PATTERN matches the result.  "~/PATTERN/" means
        # the regular expression must not match.
        if {[string index $expected 0]=="~"} {
          set re [string range $expected 2 end-1]
          if {[string index $re 0]=="*"} {
883
884
885
886
887
888
889
890
891


892
893
894
895
896
897
898
908
909
910
911
912
913
914


915
916
917
918
919
920
921
922
923







-
-
+
+







  # puts [dumpbytes $msg]
  list $rc $msg
}

proc filepath_normalize {p} {
  # test cases should be written to assume "unix"-like file paths
  if {$::tcl_platform(platform)!="unix"} {
    # lreverse*2 as a hack to remove any unneeded {} after the string map
    lreverse [lreverse [string map {\\ /} [regsub -nocase -all {[a-z]:[/\\]+} $p {/}]]]
    string map [list \\ / \{/ / .db\} .db] \
        [regsub -nocase -all {[a-z]:[/\\]+} $p {/}]
  } {
    set p
  }
}
proc do_filepath_test {name cmd expected} {
  uplevel [list do_test $name [
    subst -nocommands { filepath_normalize [ $cmd ] }
937
938
939
940
941
942
943






944
945
946
947
948
949
950
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981







+
+
+
+
+
+







  }

  if {[llength $args]==2} {
    foreach {testname sql} $args {}
    set result ""
  } elseif {[llength $args]==3} {
    foreach {testname sql result} $args {}

    # With some versions of Tcl on windows, if $result is all whitespace but
    # contains some CR/LF characters, the [list {*}$result] below returns a
    # copy of $result instead of a zero length string. Not clear exactly why
    # this is. The following is a workaround.
    if {[llength $result]==0} { set result "" }
  } else {
    error [string trim {
      wrong # args: should be "do_execsql_test ?-db DB? testname sql ?result?"
    }]
  }

  fix_testname testname
977
978
979
980
981
982
983

984
985
986
987
988
989
990
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022







+







    set dx($id) $detail
    lappend cx($parent) $id
  }
  set a "\n  QUERY PLAN\n"
  append a [append_graph "  " dx cx 0]
  regsub -all { 0x[A-F0-9]+\y} $a { xxxxxx} a
  regsub -all {(MATERIALIZE|CO-ROUTINE|SUBQUERY) \d+\y} $a {\1 xxxxxx} a
  regsub -all {\((join|subquery)-\d+\)} $a {(\1-xxxxxx)} a
  return $a
}

# Helper routine for [query_plan_graph SQL]:
#
# Output rows of the graph that are children of $level.
#
1027
1028
1029
1030
1031
1032
1033







1034



1035
1036
1037
1038
1039
1040
1041
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072

1073
1074
1075
1076
1077
1078
1079
1080
1081
1082







+
+
+
+
+
+
+
-
+
+
+







# exactly.
#
# If $res does not begin with "\s+QUERY PLAN\n" then take it is a string
# that must be found somewhere in the query plan output.
#
proc do_eqp_test {name sql res} {
  if {[regexp {^\s+QUERY PLAN\n} $res]} {

    set query_plan [query_plan_graph $sql]

    if {[list {*}$query_plan]==[list {*}$res]} {
      uplevel [list do_test $name [list set {} ok] ok]
    } else {
      uplevel [list \
    uplevel do_test $name [list [list query_plan_graph $sql]] [list $res]
        do_test $name [list query_plan_graph $sql] $res
      ]
    }
  } else {
    if {[string index $res 0]!="/"} {
      set res "/*$res*/"
    }
    uplevel do_execsql_test $name [list "EXPLAIN QUERY PLAN $sql"] [list $res]
  }
}
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
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







-
+

-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

















-
+
+







    output2 "CREATE TABLE IF NOT EXISTS time(version, script, test, us);"
    foreach {test us} $::speed_trial_times {
      output2 "INSERT INTO time VALUES('$vers', '$name', '$test', $us);"
    }
  }
}

# Run this routine last
# Clear out left-over configuration setup from the end of a test
#
proc finish_test {} {
  catch {db close}
  catch {db1 close}
  catch {db2 close}
  catch {db3 close}
proc finish_test_precleanup {} {
  catch {db1 close}
  catch {db2 close}
  catch {db3 close}
  catch {unregister_devsim}
  catch {unregister_jt_vfs}
  catch {unregister_demovfs}
}

# Run this routine last
#
proc finish_test {} {
  global argv
  finish_test_precleanup
  if {[llength $argv]>0} {
    # If additional test scripts are specified on the command-line, 
    # run them also, before quitting.
    proc finish_test {} {
      finish_test_precleanup
      return
    }
    foreach extra $argv {
      puts "Running \"$extra\""
      db_delete_and_reopen
      uplevel #0 source $extra
    }
  }
  catch {db close}
  if {0==[info exists ::SLAVE]} { finalize_testing }
}
proc finalize_testing {} {
  global sqlite_open_file_count

  set omitList [set_test_counter omit_list]

  catch {db close}
  catch {db2 close}
  catch {db3 close}

  vfs_unlink_test
  sqlite3 db {}
  # sqlite3_clear_tsd_memdebug
  db close
  sqlite3_reset_auto_extension

  sqlite3_soft_heap_limit 0
  sqlite3_soft_heap_limit64 0
  sqlite3_hard_heap_limit64 0
  set nTest [incr_ntest]
  set nErr [set_test_counter errors]

  set nKnown 0
  if {[file readable known-problems.txt]} {
    set fd [open known-problems.txt]
    set content [read $fd]
1285
1286
1287
1288
1289
1290
1291



1292
1293
1294
1295
1296
1297
1298
1299
1300

































1301
1302
1303
1304
1305
1306
1307
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







+
+
+









+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    sqlite3_memdebug_log stop
    sqlite3_memdebug_log clear
    if {[sqlite3_memory_used]>0} {
      output2 "Writing leaks.tcl..."
      sqlite3_memdebug_log sync
      memdebug_log_sql leaks.tcl
    }
  }
  if {[info commands vdbe_coverage]!=""} {
    vdbe_coverage_report
  }
  foreach f [glob -nocomplain test.db-*-journal] {
    forcedelete $f
  }
  foreach f [glob -nocomplain test.db-mj*] {
    forcedelete $f
  }
  exit [expr {$nErr>0}]
}

proc vdbe_coverage_report {} {
  puts "Writing vdbe coverage report to vdbe_coverage.txt"
  set lSrc [list]
  set iLine 0
  if {[file exists ../sqlite3.c]} {
    set fd [open ../sqlite3.c]
    set iLine
    while { ![eof $fd] } {
      set line [gets $fd]
      incr iLine
      if {[regexp {^/\** Begin file (.*\.c) \**/} $line -> file]} {
        lappend lSrc [list $iLine $file]
      }
    }
    close $fd
  }
  set fd [open vdbe_coverage.txt w]
  foreach miss [vdbe_coverage report] {
    foreach {line branch never} $miss {}
    set nextfile ""
    while {[llength $lSrc]>0 && [lindex $lSrc 0 0] < $line} {
      set nextfile [lindex $lSrc 0 1]
      set lSrc [lrange $lSrc 1 end]
    }
    if {$nextfile != ""} {
      puts $fd ""
      puts $fd "### $nextfile ###"
    }
    puts $fd "Vdbe branch $line: never $never (path $branch)"
  }
  close $fd
}

# Display memory statistics for analysis and debugging purposes.
#
proc show_memstats {} {
  set x [sqlite3_status SQLITE_STATUS_MEMORY_USED 0]
  set y [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0]
  set val [format {now %10d  max %10d  max-size %10d} \
1452
1453
1454
1455
1456
1457
1458









































1459
1460
1461
1462
1463
1464
1465
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








    output2 [format {%-4d  %s%s%-12.12s%s  %-6d  %-6d  %-6d  % -17s %s  %s} \
      $addr $I $col $opcode $D $p1 $p2 $p3 $p4 $p5 $comment
    ]
  }
  output2 "----  ------------  ------  ------  ------  ----------------  --  -"
}

proc execsql_pp {sql {db db}} {
  set nCol 0
  $db eval $sql A {
    if {$nCol==0} {
      set nCol [llength $A(*)]
      foreach c $A(*) { 
        set aWidth($c) [string length $c] 
        lappend data $c
      }
    }
    foreach c $A(*) { 
      set n [string length $A($c)]
      if {$n > $aWidth($c)} {
        set aWidth($c) $n
      }
      lappend data $A($c)
    }
  }
  if {$nCol>0} {
    set nTotal 0
    foreach e [array names aWidth] { incr nTotal $aWidth($e) }
    incr nTotal [expr ($nCol-1) * 3]
    incr nTotal 4

    set fmt ""
    foreach c $A(*) { 
      lappend fmt "% -$aWidth($c)s"
    }
    set fmt "| [join $fmt { | }] |"
    
    puts [string repeat - $nTotal]
    for {set i 0} {$i < [llength $data]} {incr i $nCol} {
      set vals [lrange $data $i [expr $i+$nCol-1]]
      puts [format $fmt {*}$vals]
      if {$i==0} { puts [string repeat - $nTotal] }
    }
    puts [string repeat - $nTotal]
  }
}


# Show the VDBE program for an SQL statement but omit the Trace
# opcode at the beginning.  This procedure can be used to prove
# that different SQL statements generate exactly the same VDBE code.
#
proc explain_no_trace {sql} {
  set tr [db eval "EXPLAIN $sql"]
1627
1628
1629
1630
1631
1632
1633


1634
1635
1636

1637
1638
1639
1640
1641
1642
1643
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788







+
+



+








  # $crashfile gets compared to the native filename in
  # cfSync(), which can be different then what TCL uses by
  # default, so here we force it to the "nativename" format.
  set cfile [string map {\\ \\\\} [file nativename [file join [get_pwd] $crashfile]]]

  set f [open crash.tcl w]
  puts $f "sqlite3_initialize ; sqlite3_shutdown"
  puts $f "catch { install_malloc_faultsim 1 }"
  puts $f "sqlite3_crash_enable 1 $dfltvfs"
  puts $f "sqlite3_crashparams $blocksize $dc $crashdelay $cfile"
  puts $f "sqlite3_test_control_pending_byte $::sqlite_pending_byte"
  puts $f "autoinstall_test_functions"

  # This block sets the cache size of the main database to 10
  # pages. This is done in case the build is configured to omit
  # "PRAGMA cache_size".
  if {$opendb!=""} {
    puts $f $opendb 
    puts $f {db eval {SELECT * FROM sqlite_master;}}
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
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







-
+










+
+
+







  if {[string length $sql]>0} {
    puts $f "db eval {"
    puts $f   "$sql"
    puts $f "}"
  }
  close $f
  set r [catch {
    exec [info nameofexec] crash.tcl >@stdout
    exec [info nameofexec] crash.tcl >@stdout 2>@stdout
  } msg]

  # Windows/ActiveState TCL returns a slightly different
  # error message.  We map that to the expected message
  # so that we don't have to change all of the test
  # cases.
  if {$::tcl_platform(platform)=="windows"} {
    if {$msg=="child killed: unknown signal"} {
      set msg "child process exited abnormally"
    }
  }
  if {$r && [string match {*ERROR: LeakSanitizer*} $msg]} {
    set msg "child process exited abnormally"
  }

  lappend r $msg
}

#   crash_on_write ?-devchar DEVCHAR? CRASHDELAY SQL
#
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
1978
1979
1980
1981
1982
1983
1984
1985















1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008







+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    # at least N IO operations performed by SQLite as a result of
    # the script, the Nth will fail.
    do_test $testname.$n.3 {
      set ::sqlite_io_error_hit 0
      set ::sqlite_io_error_hardhit 0
      set r [catch $::ioerrorbody msg]
      set ::errseen $r
      if {[info commands db]!=""} {
      set rc [sqlite3_errcode $::DB]
      if {$::ioerropts(-erc)} {
        # If we are in extended result code mode, make sure all of the
        # IOERRs we get back really do have their extended code values.
        # If an extended result code is returned, the sqlite3_errcode
        # TCLcommand will return a string of the form:  SQLITE_IOERR+nnnn
        # where nnnn is a number
        if {[regexp {^SQLITE_IOERR} $rc] && ![regexp {IOERR\+\d} $rc]} {
          return $rc
        }
      } else {
        # If we are not in extended result code mode, make sure no
        # extended error codes are returned.
        if {[regexp {\+\d} $rc]} {
          return $rc
        set rc [sqlite3_errcode db]
        if {$::ioerropts(-erc)} {
          # If we are in extended result code mode, make sure all of the
          # IOERRs we get back really do have their extended code values.
          # If an extended result code is returned, the sqlite3_errcode
          # TCLcommand will return a string of the form:  SQLITE_IOERR+nnnn
          # where nnnn is a number
          if {[regexp {^SQLITE_IOERR} $rc] && ![regexp {IOERR\+\d} $rc]} {
            return $rc
          }
        } else {
          # If we are not in extended result code mode, make sure no
          # extended error codes are returned.
          if {[regexp {\+\d} $rc]} {
            return $rc
          }
        }
      }
      # The test repeats as long as $::go is non-zero.  $::go starts out
      # as 1.  When a test runs to completion without hitting an I/O
      # error, that means there is no point in continuing with this test
      # case so set $::go to zero.
      #
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
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
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
2234
2235
2236
2237
2238







+
+



-
+



















-
+





-
+







    foreach f $lStack {
      set frames($f) 1
    }
  }

  set tbl2 "CREATE TABLE ${database}.frame(frame INTEGER PRIMARY KEY, line);\n"
  set tbl3 "CREATE TABLE ${database}.file(name PRIMARY KEY, content);\n"

  set pid [pid]

  foreach f [array names frames] {
    set addr [format %x $f]
    set cmd "addr2line -e [info nameofexec] $addr"
    set cmd "eu-addr2line --pid=$pid $addr"
    set line [eval exec $cmd]
    append sql "INSERT INTO ${database}.frame VALUES($f, '$line');\n"

    set file [lindex [split $line :] 0]
    set files($file) 1
  }

  foreach f [array names files] {
    set contents ""
    catch {
      set fd [open $f]
      set contents [read $fd]
      close $fd
    }
    set contents [string map {' ''} $contents]
    append sql "INSERT INTO ${database}.file VALUES('$f', '$contents');\n"
  }

  set escaped "BEGIN; ${tbl}${tbl2}${tbl3}${sql} ; COMMIT;"
  set escaped [string map [list "{" "\\{" "}" "\\}"] $escaped] 
  set escaped [string map [list "{" "\\{" "}" "\\}" "\\" "\\\\"] $escaped] 

  set fd [open $filename w]
  puts $fd "set BUILTIN {"
  puts $fd $escaped
  puts $fd "}"
  puts $fd {set BUILTIN [string map [list "\\{" "{" "\\}" "}"] $BUILTIN]}
  puts $fd {set BUILTIN [string map [list "\\{" "{" "\\}" "}" "\\\\" "\\"] $BUILTIN]}
  set mtv [open $::testdir/malloctraceviewer.tcl]
  set txt [read $mtv]
  close $mtv
  puts $fd $txt
  close $fd
}

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
2288
2289
2290
2291
2292
2293
2294

2295
2296
2297
2298
2299


2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319

2320
2321
2322
2323
2324
2325
2326
2327







-
+
+
+


-
-
+
+
+
+
+
+
+
+
+
+
+





+
+
+
+
-
+







#     Otherwise (if not running a WAL permutation) this is a no-op.
#
#   wal_is_wal_mode
#
#     Returns true if this test should be run in WAL mode. False otherwise.
#
proc wal_is_wal_mode {} {
  expr {[permutation] eq "wal"}
  if {[permutation] eq "wal"} { return 1 }
  if {[permutation] eq "wal2"} { return 2 }
  return 0
}
proc wal_set_journal_mode {{db db}} {
  if { [wal_is_wal_mode] } {
    $db eval "PRAGMA journal_mode = WAL"
  switch -- [wal_is_wal_mode] {
    0 {
    }

    1 {
      $db eval "PRAGMA journal_mode = WAL"
    }

    2 {
      $db eval "PRAGMA journal_mode = WAL2"
    }
  }
}
proc wal_check_journal_mode {testname {db db}} {
  if { [wal_is_wal_mode] } {
    $db eval { SELECT * FROM sqlite_master }
    set expected "wal"
    if {[wal_is_wal_mode]==2} {
      set expected "wal2"
    }
    do_test $testname [list $db eval "PRAGMA main.journal_mode"] {wal}
    do_test $testname [list $db eval "PRAGMA main.journal_mode"] $expected
  }
}

proc wal_is_capable {} {
  ifcapable !wal { return 0 }
  if {[permutation]=="journaltest"} { return 0 }
  return 1
2373
2374
2375
2376
2377
2378
2379
2380

2381
2382
2383
2384
2385
2386
2387































2388
2389
2390
2391
2392
2393
2394
2540
2541
2542
2543
2544
2545
2546

2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592







-
+







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    finish_test
    return ""
  }
  return $ret
}

# Find the name of the 'shell' executable (e.g. "sqlite3.exe") to use for
# the tests in shell[1-5].test. If no such executable can be found, invoke
# the tests in shell*.test. If no such executable can be found, invoke
# [finish_test ; return] in the callers context.
#
proc test_find_cli {} {
  set prog [test_find_binary sqlite3]
  if {$prog==""} { return -code return }
  return $prog
}

# Find invocation of the 'shell' executable (e.g. "sqlite3.exe") to use
# for the tests in shell*.test with optional valgrind prefix when the
# environment variable SQLITE_CLI_VALGRIND_OPT is set. The set value
# operates as follows:
#   empty or 0 => no valgrind prefix;
#   1 => valgrind options for memory leak check;
#   other => use value as valgrind options.
# If shell not found, invoke [finish_test ; return] in callers context.
#
proc test_cli_invocation {} {
  set prog [test_find_binary sqlite3]
  if {$prog==""} { return -code return }
  set vgrun [expr {[permutation]=="valgrind"}]
  if {$vgrun || [info exists ::env(SQLITE_CLI_VALGRIND_OPT)]} {
    if {$vgrun} {
      set vgo "--quiet"
    } else {
      set vgo $::env(SQLITE_CLI_VALGRIND_OPT)
    }
    if {$vgo == 0 || $vgo eq ""} {
      return $prog
    } elseif {$vgo == 1} {
      return "valgrind --quiet --leak-check=yes $prog"
    } else {
      return "valgrind $vgo $prog"
    }
  } else {
    return $prog
  }
}

# Find the name of the 'sqldiff' executable (e.g. "sqlite3.exe") to use for
# the tests in sqldiff tests. If no such executable can be found, invoke
# [finish_test ; return] in the callers context.
#
proc test_find_sqldiff {} {
  set prog [test_find_binary sqldiff]
2415
2416
2417
2418
2419
2420
2421

2422
2423
2424


2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625







+



+
+
set sqlite_fts3_enable_parentheses 0

# During testing, assume that all database files are well-formed.  The
# few test cases that deliberately corrupt database files should rescind 
# this setting by invoking "database_can_be_corrupt"
#
database_never_corrupt
extra_schema_checks 1

source $testdir/thread_common.tcl
source $testdir/malloc_common.tcl

set tester_tcl_has_run 1

Added test/testrunner.tcl.


































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

#-------------------------------------------------------------------------
# Usage:
#
proc usage {} {
  set a0 testrunner.tcl

  set ::argv [list]
  uplevel [list source $::testdir/permutations.test]

  puts stderr "Usage: $a0 ?SWITCHES? ?PERMUTATION? ?PATTERNS?" 
  puts stderr ""
  puts stderr "where SWITCHES are:"
  puts stderr "    --jobs NUMBER-OF-JOBS"
  puts stderr ""
  puts stderr "available PERMUTATION values are:"
  set ii 0
  foreach name [lsort [array names ::testspec]] {
    if {($ii % 3)==0} { puts -nonewline stderr "  " }
    puts -nonewline stderr [format "% -22s" $name]
    if {($ii % 3)==2} { puts stderr "" }
    incr ii
  }
  puts stderr ""
  puts stderr ""
  puts stderr "Examples:"
  puts stderr " 1) Run the veryquick tests:"
  puts stderr "      $a0"
  puts stderr " 2) Run all test scripts in the source tree:"
  puts stderr "      $a0 full"
  puts stderr " 2) Run the 'memsubsys1' permutation:"
  puts stderr "      $a0 memsubsys1"
  puts stderr " 3) Run all permutations usually run by \[make fulltest\]"
  puts stderr "      $a0 release"
  puts stderr " 4) Run all scripts that match the pattern 'select%':"
  puts stderr "      $a0 select%"
  puts stderr "      $a0 all select%"
  puts stderr "      $a0 full select%"
  puts stderr " 5) Run all scripts that are part of the veryquick permutation and match the pattern 'select%':"
  puts stderr "      $a0 veryquick select%"
  puts stderr " 6) Run the 'memsubsys1' permutation, but just those scripts that match 'window%':"
  puts stderr "      $a0 memsubsys1 window%"
  puts stderr " 7) Run all the permutations, but only the scripts that match either 'fts5%' or 'rtree%':"
  puts stderr "      $a0 release fts5% rtree%"

  exit 1
}
#-------------------------------------------------------------------------

#-------------------------------------------------------------------------
# The database schema used by the testrunner.db database.
#
set R(schema) {
  DROP TABLE IF EXISTS script;
  DROP TABLE IF EXISTS msg;
  DROP TABLE IF EXISTS malloc;

  CREATE TABLE script(
    config TEXT,
    filename TEXT,                -- full path to test script
    slow BOOLEAN,                 -- true if script is "slow"
    state TEXT CHECK( state IN ('ready', 'running', 'done') ),
    testfixtureid,                -- Id of process that ran script
    time INTEGER,                 -- Time in ms
    nerr INTEGER,                 -- if 'done', the number of errors
    ntest INTEGER,                -- if 'done', the number of tests
    output TEXT,                  -- full output of test script
    PRIMARY KEY(config, filename)
  );

  CREATE TABLE malloc(
    id INTEGER PRIMARY KEY,
    nmalloc INTEGER,
    nbyte INTEGER,
    leaker TEXT
  );

  CREATE TABLE msg(
    id INTEGER PRIMARY KEY,
    msg TEXT
  );
}
#-------------------------------------------------------------------------

#-------------------------------------------------------------------------
# Try to estimate a the number of processes to use.
#
# Command [guess_number_of_cores] attempts to glean the number of logical
# cores. Command [default_njob] returns the default value for the --jobs
# switch.
#
proc guess_number_of_cores {} {
  set ret 4
  
  if {$::tcl_platform(os)=="Darwin"} {
    set cmd "sysctl -n hw.logicalcpu"
  } else {
    set cmd "nproc"
  }
  catch {
    set fd [open "|$cmd" r]
    set ret [gets $fd]
    close $fd
    set ret [expr $ret]
  }
  return $ret
}

proc default_njob {} {
  set nCore [guess_number_of_cores]
  set nHelper [expr int($nCore*0.75)]
  expr $nHelper>0 ? $nHelper : 1
}
#-------------------------------------------------------------------------


set R(dbname) [file normalize testrunner.db]
set R(logname) [file normalize testrunner.log]
set R(info_script) [file normalize [info script]]
set R(timeout) 10000              ;# Default busy-timeout for testrunner.db 
set R(nJob)    [default_njob]     ;# Default number of helper processes
set R(leaker)  ""                 ;# Name of first script to leak memory

set R(patternlist) [list]

set testdir [file dirname $argv0]

# Parse the command line options. There are two ways to invoke this
# script - to create a helper or coordinator process. If there are
# no helper processes, the coordinator runs test scripts.
#
# To create a helper process:
#
#    testrunner.tcl helper ID
#
# where ID is an integer greater than 0. The process will create and
# run tests in the "testdir$ID" directory. Helper processes are only
# created by coordinators - there is no need for a user to create
# helper processes manually.
#
# If the first argument is anything other than "helper", then a coordinator
# process is started. See the implementation of the [usage] proc above for
# details.
#
switch -- [lindex $argv 0] {
  helper {
    set R(helper) 1
    set R(helper_id) [lindex $argv 1]
    set argv [list --testdir=testdir$R(helper_id)]
  }

  default {
    set R(helper) 0
    set R(helper_id) 0

  }
}
if {$R(helper)==0} {
  for {set ii 0} {$ii < [llength $argv]} {incr ii} {
    set a [lindex $argv $ii]
    set n [string length $a]

    if {[string range $a 0 0]=="-"} {
      if {($n>2 && [string match "$a*" --jobs]) || $a=="-j"} {
        incr ii
          set R(nJob) [lindex $argv $ii]
      } else {
        usage
      }
    } else {
      lappend R(patternlist) [string map {% *} $a]
    }
  }

  set argv [list]
}
source $testdir/permutations.test

#-------------------------------------------------------------------------
# Return a list of tests to run. Each element of the list is itself a
# list of two elements - the name of a permuations.test configuration
# followed by the full path to a test script. i.e.:
#
#    {CONFIG FILENAME} {CONFIG FILENAME} ...
#
proc testset_patternlist {patternlist} {

  set first [lindex $patternlist 0]
  if {$first=="all"} { set first "full" }

  if {$first=="release"} {

    # The following mirrors the set of test suites invoked by "all.test".
    #
    set clist {
      full
      no_optimization memsubsys1 memsubsys2 singlethread 
      multithread onefile utf16 exclusive persistent_journal 
      persistent_journal_error no_journal no_journal_error
      autovacuum_ioerr no_mutex_try fullmutex journaltest 
      inmemory_journal pcache0 pcache10 pcache50 pcache90 
      pcache100 prepare mmap
    }
    ifcapable rbu { lappend clist rbu }
    if {$::tcl_platform(platform)=="unix"} {
      ifcapable !default_autovacuum {
        lappend clist autovacuum_crash 
      }
    }
    set patternlist [lrange $patternlist 1 end]

  } elseif {[info exists ::testspec($first)]} {
    set clist $first
    set patternlist [lrange $patternlist 1 end]
  } elseif { [llength $patternlist]==0 } {
    set clist veryquick
  } else {
    set clist full
  }

  set testset [list]

  foreach config $clist {
    catch { array unset O }
    array set O $::testspec($config)
    foreach f $O(-files) {
      if {[file pathtype $f]!="absolute"} {
        set f [file join $::testdir $f]
      }
      lappend testset [list $config [file normalize $f]]
    }
  }

  if {[llength $patternlist]>0} {
    foreach t $testset {
      set tail [file tail [lindex $t 1]]
      foreach p $patternlist {
        if {[string match $p $tail]} {
          lappend ret $t
          break;
        }
      }
    }
  } else {
    set ret $testset
  }

  set ret
}
#--------------------------------------------------------------------------


proc r_write_db {tcl} {
  global R

  sqlite3_test_control_pending_byte 0x010000
  sqlite3 db $R(dbname)
  db timeout $R(timeout)
  db eval { BEGIN EXCLUSIVE }

  uplevel $tcl

  db eval { COMMIT }
  db close
}

proc make_new_testset {} {
  global R

  set tests [testset_patternlist $R(patternlist)]
  r_write_db {
    db eval $R(schema)
    foreach t $tests {
      foreach {c s} $t {}
      set slow 0

      set fd [open $s]
      for {set ii 0} {$ii<100 && ![eof $fd]} {incr ii} {
        set line [gets $fd]
        if {[string match -nocase *testrunner:* $line]} {
          regexp -nocase {.*testrunner:(.*)} $line -> properties
          foreach p $properties {
            if {$p=="slow"} { set slow 1 }
          }
        }
      }
      close $fd

      db eval { 
        INSERT INTO script(config, filename, slow, state) 
            VALUES ($c, $s, $slow, 'ready') 
      }
    }
  }
}

# Find the next job in the database and mark it as 'running'. Then return
# a list consisting of the 
#
#   CONFIG FILENAME
#
# pair for the test.
#
proc get_next_test {} {
  global R
  set myid $R(helper_id)

  r_write_db {
    set f ""
    set c ""
    db eval {
      SELECT config, filename FROM script WHERE state='ready' 
      ORDER BY 
        (slow * (($myid+1) % 2)) DESC, 
        config!='full', 
        config,
        filename
      LIMIT 1
    } {
      set c $config
      set f $filename
    }
    if {$f!=""} {
      db eval { 
        UPDATE script SET state='running', testfixtureid=$myid 
        WHERE (config, filename) = ($c, $f)
      }
    }
  }

  if {$f==""} { return "" }
  list $c $f
}

proc r_testname {config filename} {
  set name [file tail $filename]
  if {$config!="" && $config!="full" && $config!="veryquick"} {
    set name "$config-$name"
  }
  return $name
}

proc r_set_test_result {config filename ms nerr ntest output} {
  global R

  set f [r_testname $config $filename]
  if {$nerr==0} {
    set msg "$f... Ok"
  } else {
    set msg "$f... FAILED - $nerr errors of $ntest tests"
  }
  append msg " (${ms}ms)"
  if {$R(helper)} {
    append msg " (helper $R(helper_id))"
  }

  sqlite3_shutdown
  set nMalloc [lindex [sqlite3_status SQLITE_STATUS_MALLOC_COUNT 0] 1]
  set nByte   [sqlite3_memory_used]
  if {($nByte>0 || $nMalloc>0) && $R(leaker)==""} {
    set R(leaker) $f
  }

  r_write_db {
    db eval {
      UPDATE script 
        SET state='done', output=$output, nerr=$nerr, ntest=$ntest, time=$ms
      WHERE (config, filename)=($config, $filename);

      INSERT INTO msg(msg) VALUES ($msg);
    }
  }
}

set R(iNextMsg) 1
proc r_get_messages {{db ""}} {
  global R

  sqlite3_test_control_pending_byte 0x010000

  if {$db==""} {
    sqlite3 rgmhandle $R(dbname)
    set dbhandle rgmhandle
    $dbhandle timeout $R(timeout)
  } else {
    set dbhandle $db
  }

  $dbhandle transaction {
    set next $R(iNextMsg)
    set ret [$dbhandle eval {SELECT msg FROM msg WHERE id>=$next}]
    set R(iNextMsg) [$dbhandle one {SELECT COALESCE(max(id), 0)+1 FROM msg}]
  }

  if {$db==""} {
    rgmhandle close
  }

  set ret
}

# This is called after all tests have been run to write the leaked memory
# report into the malloc table of testrunner.db.
#
proc r_memory_report {} {
  global R

  sqlite3_shutdown

  set nMalloc [lindex [sqlite3_status SQLITE_STATUS_MALLOC_COUNT 0] 1]
  set nByte   [sqlite3_memory_used]
  set id $R(helper_id)
  set leaker $R(leaker)

  r_write_db {
    db eval {
      INSERT INTO malloc(id, nMalloc, nByte, leaker) 
        VALUES($id, $nMalloc, $nByte, $leaker)
    }
  }
}


#--------------------------------------------------------------------------
#
set ::R_INSTALL_PUTS_WRAPPER {
  proc puts_sts_wrapper {args} {
    set n [llength $args]
    if {$n==1 || ($n==2 && [string first [lindex $args 0] -nonewline]==0)} {
      uplevel puts_into_caller $args
    } else {
      # A channel was explicitly specified.
      uplevel puts_sts_original $args
    }
  }
  rename puts puts_sts_original
  proc puts {args} { uplevel puts_sts_wrapper $args }
}

proc r_install_puts_wrapper {} $::R_INSTALL_PUTS_WRAPPER
proc r_uninstall_puts_wrapper {} {
  rename puts ""
  rename puts_sts_original puts
}

proc slave_test_script {script} {

  # Create the interpreter used to run the test script.
  interp create tinterp

  # Populate some global variables that tester.tcl expects to see.
  foreach {var value} [list              \
    ::argv0 $::argv0                     \
    ::argv  {}                           \
    ::SLAVE 1                            \
  ] {
    interp eval tinterp [list set $var $value]
  }

  # The alias used to access the global test counters.
  tinterp alias set_test_counter set_test_counter

  # Set up an empty ::cmdlinearg array in the slave.
  interp eval tinterp [list array set ::cmdlinearg [array get ::cmdlinearg]]

  # Set up the ::G array in the slave.
  interp eval tinterp [list array set ::G [array get ::G]]
  interp eval tinterp [list set ::G(runner.tcl) 1]

  interp eval tinterp $::R_INSTALL_PUTS_WRAPPER
  tinterp alias puts_into_caller puts_into_caller

  # Load the various test interfaces implemented in C.
  load_testfixture_extensions tinterp

  # Run the test script.
  set rc [catch { interp eval tinterp $script } msg opt]
  if {$rc} {
    puts_into_caller $msg
    puts_into_caller [dict get $opt -errorinfo]
    incr ::TC(errors)
  }

  # Check if the interpreter call [run_thread_tests]
  if { [interp eval tinterp {info exists ::run_thread_tests_called}] } {
    set ::run_thread_tests_called 1
  }

  # Delete the interpreter used to run the test script.
  interp delete tinterp
}

proc slave_test_file {zFile} {
  set tail [file tail $zFile]

  # Remember the value of the shared-cache setting. So that it is possible
  # to check afterwards that it was not modified by the test script.
  #
  ifcapable shared_cache { set scs [sqlite3_enable_shared_cache] }

  # Run the test script in a slave interpreter.
  #
  unset -nocomplain ::run_thread_tests_called
  reset_prng_state
  set ::sqlite_open_file_count 0
  set time [time { slave_test_script [list source $zFile] }]
  set ms [expr [lindex $time 0] / 1000]

  r_install_puts_wrapper

  # Test that all files opened by the test script were closed. Omit this
  # if the test script has "thread" in its name. The open file counter
  # is not thread-safe.
  #
  if {[info exists ::run_thread_tests_called]==0} {
    do_test ${tail}-closeallfiles { expr {$::sqlite_open_file_count>0} } {0}
  }
  set ::sqlite_open_file_count 0

  # Test that the global "shared-cache" setting was not altered by
  # the test script.
  #
  ifcapable shared_cache {
    set res [expr {[sqlite3_enable_shared_cache] == $scs}]
    do_test ${tail}-sharedcachesetting [list set {} $res] 1
  }

  # Add some info to the output.
  #
  output2 "Time: $tail $ms ms"
  show_memstats

  r_uninstall_puts_wrapper
  return $ms
}

proc puts_into_caller {args} {
  global R
  if {[llength $args]==1} {
    append R(output) [lindex $args 0]
    append R(output) "\n"
  } else {
    append R(output) [lindex $args 1]
  }
}

#-------------------------------------------------------------------------
#
proc r_final_report {} {
  global R

  sqlite3_test_control_pending_byte 0x010000
  sqlite3 db $R(dbname)

  db timeout $R(timeout)

  set errcode 0

  # Create the text log file. This is just the concatenation of the 
  # 'output' column of the database for every script that was run.
  set fd [open $R(logname) w]
  db eval {SELECT output FROM script ORDER BY config!='full',config,filename} {
    puts $fd $output
  }
  close $fd

  # Check if any scripts reported errors. If so, print one line noting
  # how many errors, and another identifying the scripts in which they
  # occured. Or, if no errors occurred, print out "no errors at all!".
  sqlite3 db $R(dbname)
  db timeout $R(timeout)
  db eval { SELECT sum(nerr) AS nerr, sum(ntest) AS ntest FROM script } { }
  puts "$nerr errors from $ntest tests."
  if {$nerr>0} {
    db eval { SELECT config, filename FROM script WHERE nerr>0 } {
      lappend errlist [r_testname $config $filename]
    }
    puts "Errors in: $errlist"
    set errcode 1
  }

  # Check if any scripts were not run or did not finish. Print out a
  # line identifying them if there are any. 
  set errlist [list]
  db eval { SELECT config, filename FROM script WHERE state!='done' } {
    lappend errlist [r_testname $config $filename]
  }
  if {$errlist!=[list]} {
    puts "Tests DID NOT FINISH (crashed?): $errlist"
    set errcode 1
  }

  set bLeak 0
  db eval {
    SELECT id, nmalloc, nbyte, leaker FROM malloc 
      WHERE nmalloc>0 OR nbyte>0
  } {
    if {$id==0} { 
      set line "This process " 
    } else {
      set line "Helper $id "
    }
    append line "leaked $nbyte byte in $nmalloc allocations"
    if {$leaker!=""} { append line " (perhaps in [file tail $leaker])" }
    puts $line
    set bLeak 1
  }
  if {$bLeak==0} {
    puts "No leaks - all allocations freed."
  }

  db close

  puts "Test database is $R(dbname)"
  puts "Test log file is $R(logname)"
  if {$errcode} {
    puts "This test has FAILED."
  }
  return $errcode
}


if {$R(helper)==0} {
  make_new_testset
}

set R(nHelperRunning) 0
if {$R(helper)==0 && $R(nJob)>1} {
  cd $cmdlinearg(TESTFIXTURE_HOME)
  for {set ii 1} {$ii <= $R(nJob)} {incr ii} {
    set cmd "[info nameofexec] $R(info_script) helper $ii 2>@1"
    puts "Launching helper $ii ($cmd)"
    set chan [open "|$cmd" r]
    fconfigure $chan -blocking false
    fileevent $chan readable [list r_helper_readable $ii $chan]
    incr R(nHelperRunning) 
  }
  cd $cmdlinearg(testdir)
}

proc r_helper_readable {id chan} {
  set data [gets $chan]
  if {$data!=""} { puts "helper $id:$data" }
  if {[eof $chan]} {
    puts "helper $id is finished"
    incr ::R(nHelperRunning) -1
    close $chan
  }
}

if {$R(nHelperRunning)==0} {
  while { ""!=[set t [get_next_test]] } {
    set R(output) ""
    set TC(count) 0
    set TC(errors) 0

    foreach {config filename} $t {}

    array set O $::testspec($config)
    set ::G(perm:name)         $config
    set ::G(perm:prefix)       $O(-prefix)
    set ::G(isquick)           1
    set ::G(perm:dbconfig)     $O(-dbconfig)
    set ::G(perm:presql)       $O(-presql)

    eval $O(-initialize)
    set ms [slave_test_file $filename]
    eval $O(-shutdown)

    unset -nocomplain ::G(perm:sqlite3_args)
    unset ::G(perm:name)
    unset ::G(perm:prefix)
    unset ::G(perm:dbconfig)
    unset ::G(perm:presql)

    r_set_test_result $config $filename $ms $TC(errors) $TC(count) $R(output)
  
    if {$R(helper)==0} {
      foreach msg [r_get_messages] { puts $msg }
    }
  }

  # Tests are finished - write a record into testrunner.db describing 
  # any memory leaks. 
  r_memory_report

} else {
  set TTT 0
  sqlite3 db $R(dbname)
  db timeout $R(timeout)
  while {$R(nHelperRunning)>0} {
    after 250 { incr TTT }
    vwait TTT
    foreach msg [r_get_messages db] { puts $msg }
  }
  db close
}

set errcode 0
if {$R(helper)==0} {
  set errcode [r_final_report]
}

exit $errcode

Changes to test/thread001.test.

11
12
13
14
15
16
17

18
19
20
21
22
23
24
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25







+







#
# $Id: thread001.test,v 1.10 2009/03/26 14:48:07 danielk1977 Exp $

set testdir [file dirname $argv0]

source $testdir/tester.tcl
if {[run_thread_tests]==0} { finish_test ; return }
ifcapable !shared_cache { finish_test ; return }

set ::enable_shared_cache [sqlite3_enable_shared_cache]

set ::NTHREAD 10

# Run this test three times: 
# 

Changes to test/thread002.test.

15
16
17
18
19
20
21
22

23
24
25
26
27
28
29
15
16
17
18
19
20
21

22
23
24
25
26
27
28
29







-
+







# $Id: thread002.test,v 1.9 2009/03/26 14:48:07 danielk1977 Exp $

set testdir [file dirname $argv0]

set do_not_use_codec 1
source $testdir/tester.tcl
if {[run_thread_tests]==0} { finish_test ; return }

ifcapable !shared_cache { finish_test ; return }

db close
set ::enable_shared_cache [sqlite3_enable_shared_cache 1]

set ::NTHREAD 10

do_test thread002.1 {

Changes to test/threadtest3.c.

28
29
30
31
32
33
34




35



36








37

38


























39
40










41
42
















43
44
45
46
47



























































































































































































































































































































































































































































































































































































































































































































































































































































































48
49
50
51
52
53
54
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91


92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978







+
+
+
+

+
+
+

+
+
+
+
+
+
+
+
-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







**        ./a.out walthread3      -- Run the "walthread3" test
**        ./a.out 'wal*'          -- Run all of the wal* tests
**        ./a.out --help          -- List all available tests
**
** The exit status is non-zero if any test fails.
*/

/* 
** The "Set Error Line" macro.
*/
#define SEL(e) ((e)->iLine = ((e)->rc ? (e)->iLine : __LINE__))

/* Database functions */
#define opendb(w,x,y,z)         (SEL(w), opendb_x(w,x,y,z))
#define closedb(y,z)            (SEL(y), closedb_x(y,z))

/* Functions to execute SQL */
#define sql_script(x,y,z)       (SEL(x), sql_script_x(x,y,z))
#define integrity_check(x,y)    (SEL(x), integrity_check_x(x,y))
#define execsql_i64(x,y,...)    (SEL(x), execsql_i64_x(x,y,__VA_ARGS__))
#define execsql_text(x,y,z,...) (SEL(x), execsql_text_x(x,y,z,__VA_ARGS__))
#define execsql(x,y,...)        (SEL(x), (void)execsql_i64_x(x,y,__VA_ARGS__))
#define sql_script_printf(x,y,z,...) (                \
    SEL(x), sql_script_printf_x(x,y,z,__VA_ARGS__)    \

) 

/* Thread functions */
#define launch_thread(w,x,y,z)     (SEL(w), launch_thread_x(w,x,y,z))
#define join_all_threads(y,z)      (SEL(y), join_all_threads_x(y,z))

/* Timer functions */
#define setstoptime(y,z)        (SEL(y), setstoptime_x(y,z))
#define timetostop(z)           (SEL(z), timetostop_x(z))

/* Report/clear errors. */
#define test_error(z, ...)      test_error_x(z, sqlite3_mprintf(__VA_ARGS__))
#define clear_error(y,z)        clear_error_x(y, z)

/* File-system operations */
#define filesize(y,z)           (SEL(y), filesize_x(y,z))
#define filecopy(x,y,z)         (SEL(x), filecopy_x(x,y,z))

#define PTR2INT(x) ((int)((intptr_t)x))
#define INT2PTR(x) ((void*)((intptr_t)x))

/*
** End of test code/infrastructure interface macros.
*************************************************************************/




#include <sqlite3.h>

#ifdef _WIN32
# include <stdio.h>
# include <string.h>
# include <assert.h>
# include <process.h>
# include <windows.h>
# include <sys/types.h> 
# include <sys/stat.h> 
# include <errno.h>
# include <fcntl.h>
#include "test_multiplex.h"
#include "tt3_core.c"
# include <io.h>
#else
# include <unistd.h>
# include <stdio.h>
# include <pthread.h>
# include <assert.h>
# include <sys/types.h> 
# include <sys/stat.h> 
# include <string.h>
# include <fcntl.h>
# include <errno.h>

# define O_BINARY 0
#endif

#include "test_multiplex.h"

/* Required to link test_multiplex.c */
#ifndef SQLITE_OMIT_WSD
int sqlite3PendingByte = 0x40000000;
#endif

/*
 * This code implements the MD5 message-digest algorithm.
 * The algorithm is due to Ron Rivest.  This code was
 * written by Colin Plumb in 1993, no copyright is claimed.
 * This code is in the public domain; do with it what you wish.
 *
 * Equivalent code is available from RSA Data Security, Inc.
 * This code has been tested against that, and is equivalent,
 * except that you don't need to include two pages of legalese
 * with every copy.
 *
 * To compute the message digest of a chunk of bytes, declare an
 * MD5Context structure, pass it to MD5Init, call MD5Update as
 * needed on buffers full of bytes, and then call MD5Final, which
 * will fill a supplied 16-byte array with the digest.
 */

/*
 * If compiled on a machine that doesn't have a 32-bit integer,
 * you just set "uint32" to the appropriate datatype for an
 * unsigned 32-bit integer.  For example:
 *
 *       cc -Duint32='unsigned long' md5.c
 *
 */
#ifndef uint32
#  define uint32 unsigned int
#endif

struct MD5Context {
  int isInit;
  uint32 buf[4];
  uint32 bits[2];
  union {
    unsigned char in[64];
    uint32 in32[16];
  } u;
};
typedef struct MD5Context MD5Context;

/*
 * Note: this code is harmless on little-endian machines.
 */
static void byteReverse (unsigned char *buf, unsigned longs){
  uint32 t;
  do {
    t = (uint32)((unsigned)buf[3]<<8 | buf[2]) << 16 |
          ((unsigned)buf[1]<<8 | buf[0]);
    *(uint32 *)buf = t;
    buf += 4;
  } while (--longs);
}
/* The four core functions - F1 is optimized somewhat */

/* #define F1(x, y, z) (x & y | ~x & z) */
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))

/* This is the central step in the MD5 algorithm. */
#define MD5STEP(f, w, x, y, z, data, s) \
  ( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )

/*
 * The core of the MD5 algorithm, this alters an existing MD5 hash to
 * reflect the addition of 16 longwords of new data.  MD5Update blocks
 * the data and converts bytes into longwords for this routine.
 */
static void MD5Transform(uint32 buf[4], const uint32 in[16]){
  register uint32 a, b, c, d;

  a = buf[0];
  b = buf[1];
  c = buf[2];
  d = buf[3];

  MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478,  7);
  MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
  MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
  MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
  MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf,  7);
  MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
  MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
  MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
  MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8,  7);
  MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
  MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
  MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
  MD5STEP(F1, a, b, c, d, in[12]+0x6b901122,  7);
  MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
  MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
  MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);

  MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562,  5);
  MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340,  9);
  MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
  MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
  MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d,  5);
  MD5STEP(F2, d, a, b, c, in[10]+0x02441453,  9);
  MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
  MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
  MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6,  5);
  MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6,  9);
  MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
  MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
  MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905,  5);
  MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8,  9);
  MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
  MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);

  MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942,  4);
  MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
  MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
  MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
  MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44,  4);
  MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
  MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
  MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
  MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6,  4);
  MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
  MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
  MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
  MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039,  4);
  MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
  MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
  MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);

  MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244,  6);
  MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
  MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
  MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
  MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3,  6);
  MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
  MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
  MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
  MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f,  6);
  MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
  MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
  MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
  MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82,  6);
  MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
  MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
  MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);

  buf[0] += a;
  buf[1] += b;
  buf[2] += c;
  buf[3] += d;
}

/*
 * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
 * initialization constants.
 */
static void MD5Init(MD5Context *ctx){
  ctx->isInit = 1;
  ctx->buf[0] = 0x67452301;
  ctx->buf[1] = 0xefcdab89;
  ctx->buf[2] = 0x98badcfe;
  ctx->buf[3] = 0x10325476;
  ctx->bits[0] = 0;
  ctx->bits[1] = 0;
}

/*
 * Update context to reflect the concatenation of another buffer full
 * of bytes.
 */
static 
void MD5Update(MD5Context *ctx, const unsigned char *buf, unsigned int len){
  uint32 t;

  /* Update bitcount */

  t = ctx->bits[0];
  if ((ctx->bits[0] = t + ((uint32)len << 3)) < t)
    ctx->bits[1]++; /* Carry from low to high */
  ctx->bits[1] += len >> 29;

  t = (t >> 3) & 0x3f;    /* Bytes already in shsInfo->data */

  /* Handle any leading odd-sized chunks */

  if ( t ) {
    unsigned char *p = (unsigned char *)ctx->u.in + t;

    t = 64-t;
    if (len < t) {
      memcpy(p, buf, len);
      return;
    }
    memcpy(p, buf, t);
    byteReverse(ctx->u.in, 16);
    MD5Transform(ctx->buf, (uint32 *)ctx->u.in);
    buf += t;
    len -= t;
  }

  /* Process data in 64-byte chunks */

  while (len >= 64) {
    memcpy(ctx->u.in, buf, 64);
    byteReverse(ctx->u.in, 16);
    MD5Transform(ctx->buf, (uint32 *)ctx->u.in);
    buf += 64;
    len -= 64;
  }

  /* Handle any remaining bytes of data. */

  memcpy(ctx->u.in, buf, len);
}

/*
 * Final wrapup - pad to 64-byte boundary with the bit pattern 
 * 1 0* (64-bit count of bits processed, MSB-first)
 */
static void MD5Final(unsigned char digest[16], MD5Context *ctx){
  unsigned count;
  unsigned char *p;

  /* Compute number of bytes mod 64 */
  count = (ctx->bits[0] >> 3) & 0x3F;

  /* Set the first char of padding to 0x80.  This is safe since there is
     always at least one byte free */
  p = ctx->u.in + count;
  *p++ = 0x80;

  /* Bytes of padding needed to make 64 bytes */
  count = 64 - 1 - count;

  /* Pad out to 56 mod 64 */
  if (count < 8) {
    /* Two lots of padding:  Pad the first block to 64 bytes */
    memset(p, 0, count);
    byteReverse(ctx->u.in, 16);
    MD5Transform(ctx->buf, (uint32 *)ctx->u.in);

    /* Now fill the next block with 56 bytes */
    memset(ctx->u.in, 0, 56);
  } else {
    /* Pad block to 56 bytes */
    memset(p, 0, count-8);
  }
  byteReverse(ctx->u.in, 14);

  /* Append length in bits and transform */
  ctx->u.in32[14] = ctx->bits[0];
  ctx->u.in32[15] = ctx->bits[1];

  MD5Transform(ctx->buf, (uint32 *)ctx->u.in);
  byteReverse((unsigned char *)ctx->buf, 4);
  memcpy(digest, ctx->buf, 16);
  memset(ctx, 0, sizeof(*ctx));    /* In case it is sensitive */
}

/*
** Convert a 128-bit MD5 digest into a 32-digit base-16 number.
*/
static void MD5DigestToBase16(unsigned char *digest, char *zBuf){
  static char const zEncode[] = "0123456789abcdef";
  int i, j;

  for(j=i=0; i<16; i++){
    int a = digest[i];
    zBuf[j++] = zEncode[(a>>4)&0xf];
    zBuf[j++] = zEncode[a & 0xf];
  }
  zBuf[j] = 0;
}

/*
** During testing, the special md5sum() aggregate function is available.
** inside SQLite.  The following routines implement that function.
*/
static void md5step(sqlite3_context *context, int argc, sqlite3_value **argv){
  MD5Context *p;
  int i;
  if( argc<1 ) return;
  p = sqlite3_aggregate_context(context, sizeof(*p));
  if( p==0 ) return;
  if( !p->isInit ){
    MD5Init(p);
  }
  for(i=0; i<argc; i++){
    const char *zData = (char*)sqlite3_value_text(argv[i]);
    if( zData ){
      MD5Update(p, (unsigned char*)zData, strlen(zData));
    }
  }
}
static void md5finalize(sqlite3_context *context){
  MD5Context *p;
  unsigned char digest[16];
  char zBuf[33];
  p = sqlite3_aggregate_context(context, sizeof(*p));
  MD5Final(digest,p);
  MD5DigestToBase16(digest, zBuf);
  sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
}

/*
** End of copied md5sum() code.
**************************************************************************/

typedef sqlite3_int64 i64;

typedef struct Error Error;
typedef struct Sqlite Sqlite;
typedef struct Statement Statement;

typedef struct Threadset Threadset;
typedef struct Thread Thread;

/* Total number of errors in this process so far. */
static int nGlobalErr = 0;

struct Error {
  int rc;
  int iLine;
  char *zErr;
};

struct Sqlite {
  sqlite3 *db;                    /* Database handle */
  Statement *pCache;              /* Linked list of cached statements */
  int nText;                      /* Size of array at aText[] */
  char **aText;                   /* Stored text results */
};

struct Statement {
  sqlite3_stmt *pStmt;            /* Pre-compiled statement handle */
  Statement *pNext;               /* Next statement in linked-list */
};

struct Thread {
  int iTid;                       /* Thread number within test */
  void* pArg;                     /* Pointer argument passed by caller */

#ifdef _WIN32
  uintptr_t winTid;               /* Thread handle */
#else
  pthread_t tid;                  /* Thread id */
#endif
  char *(*xProc)(int, void*);     /* Thread main proc */
  char *zRes;                     /* Value returned by xProc */
  Thread *pNext;                  /* Next in this list of threads */
};

struct Threadset {
  int iMaxTid;                    /* Largest iTid value allocated so far */
  Thread *pThread;                /* Linked list of threads */
};

static void free_err(Error *p){
  sqlite3_free(p->zErr);
  p->zErr = 0;
  p->rc = 0;
}

static void print_err(Error *p){
  if( p->rc!=SQLITE_OK ){
    int isWarn = 0;
    if( p->rc==SQLITE_SCHEMA ) isWarn = 1;
    if( sqlite3_strglob("* - no such table: *",p->zErr)==0 ) isWarn = 1;
    printf("%s: (%d) \"%s\" at line %d\n", isWarn ? "Warning" : "Error",
            p->rc, p->zErr, p->iLine);
    if( !isWarn ) nGlobalErr++;
    fflush(stdout);
  }
}

static void print_and_free_err(Error *p){
  print_err(p);
  free_err(p);
}

static void system_error(Error *pErr, int iSys){
  pErr->rc = iSys;
#if _WIN32
  pErr->zErr = sqlite3_mprintf("%s", strerror(iSys));
#else
  pErr->zErr = (char *)sqlite3_malloc(512);
  strerror_r(iSys, pErr->zErr, 512);
  pErr->zErr[511] = '\0';
#endif
}

static void sqlite_error(
  Error *pErr, 
  Sqlite *pDb, 
  const char *zFunc
){
  pErr->rc = sqlite3_errcode(pDb->db);
  pErr->zErr = sqlite3_mprintf(
      "sqlite3_%s() - %s (%d)", zFunc, sqlite3_errmsg(pDb->db),
      sqlite3_extended_errcode(pDb->db)
  );
}

static void test_error_x(
  Error *pErr,
  char *zErr
){
  if( pErr->rc==SQLITE_OK ){
    pErr->rc = 1;
    pErr->zErr = zErr;
  }else{
    sqlite3_free(zErr);
  }
}

static void clear_error_x(
  Error *pErr,
  int rc
){
  if( pErr->rc==rc ){
    pErr->rc = SQLITE_OK;
    sqlite3_free(pErr->zErr);
    pErr->zErr = 0;
  }
}

static int busyhandler(void *pArg, int n){
  sqlite3_sleep(10);
  return 1;
}

static void opendb_x(
  Error *pErr,                    /* IN/OUT: Error code */
  Sqlite *pDb,                    /* OUT: Database handle */
  const char *zFile,              /* Database file name */
  int bDelete                     /* True to delete db file before opening */
){
  if( pErr->rc==SQLITE_OK ){
    int rc;
    int flags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_URI;
    if( bDelete ) unlink(zFile);
    rc = sqlite3_open_v2(zFile, &pDb->db, flags, 0);
    if( rc ){
      sqlite_error(pErr, pDb, "open");
      sqlite3_close(pDb->db);
      pDb->db = 0;
    }else{
      sqlite3_create_function(
          pDb->db, "md5sum", -1, SQLITE_UTF8, 0, 0, md5step, md5finalize
      );
      sqlite3_busy_handler(pDb->db, busyhandler, 0);
      sqlite3_exec(pDb->db, "PRAGMA synchronous=OFF", 0, 0, 0);
    }
  }
}

static void closedb_x(
  Error *pErr,                    /* IN/OUT: Error code */
  Sqlite *pDb                     /* OUT: Database handle */
){
  int rc;
  int i;
  Statement *pIter;
  Statement *pNext;
  for(pIter=pDb->pCache; pIter; pIter=pNext){
    pNext = pIter->pNext;
    sqlite3_finalize(pIter->pStmt);
    sqlite3_free(pIter);
  }
  for(i=0; i<pDb->nText; i++){
    sqlite3_free(pDb->aText[i]);
  }
  sqlite3_free(pDb->aText);
  rc = sqlite3_close(pDb->db);
  if( rc && pErr->rc==SQLITE_OK ){
    pErr->zErr = sqlite3_mprintf("%s", sqlite3_errmsg(pDb->db));
  }
  memset(pDb, 0, sizeof(Sqlite));
}

static void sql_script_x(
  Error *pErr,                    /* IN/OUT: Error code */
  Sqlite *pDb,                    /* Database handle */
  const char *zSql                /* SQL script to execute */
){
  if( pErr->rc==SQLITE_OK ){
    pErr->rc = sqlite3_exec(pDb->db, zSql, 0, 0, &pErr->zErr);
  }
}

static void sql_script_printf_x(
  Error *pErr,                    /* IN/OUT: Error code */
  Sqlite *pDb,                    /* Database handle */
  const char *zFormat,            /* SQL printf format string */
  ...                             /* Printf args */
){
  va_list ap;                     /* ... printf arguments */
  va_start(ap, zFormat);
  if( pErr->rc==SQLITE_OK ){
    char *zSql = sqlite3_vmprintf(zFormat, ap);
    pErr->rc = sqlite3_exec(pDb->db, zSql, 0, 0, &pErr->zErr);
    sqlite3_free(zSql);
  }
  va_end(ap);
}

static Statement *getSqlStatement(
  Error *pErr,                    /* IN/OUT: Error code */
  Sqlite *pDb,                    /* Database handle */
  const char *zSql                /* SQL statement */
){
  Statement *pRet;
  int rc;

  for(pRet=pDb->pCache; pRet; pRet=pRet->pNext){
    if( 0==strcmp(sqlite3_sql(pRet->pStmt), zSql) ){
      return pRet;
    }
  }

  pRet = sqlite3_malloc(sizeof(Statement));
  rc = sqlite3_prepare_v2(pDb->db, zSql, -1, &pRet->pStmt, 0);
  if( rc!=SQLITE_OK ){
    sqlite_error(pErr, pDb, "prepare_v2");
    return 0;
  }
  assert( 0==strcmp(sqlite3_sql(pRet->pStmt), zSql) );

  pRet->pNext = pDb->pCache;
  pDb->pCache = pRet;
  return pRet;
}

static sqlite3_stmt *getAndBindSqlStatement(
  Error *pErr,                    /* IN/OUT: Error code */
  Sqlite *pDb,                    /* Database handle */
  va_list ap                      /* SQL followed by parameters */
){
  Statement *pStatement;          /* The SQLite statement wrapper */
  sqlite3_stmt *pStmt;            /* The SQLite statement to return */
  int i;                          /* Used to iterate through parameters */

  pStatement = getSqlStatement(pErr, pDb, va_arg(ap, const char *));
  if( !pStatement ) return 0;
  pStmt = pStatement->pStmt;
  for(i=1; i<=sqlite3_bind_parameter_count(pStmt); i++){
    const char *zName = sqlite3_bind_parameter_name(pStmt, i);
    void * pArg = va_arg(ap, void*);

    switch( zName[1] ){
      case 'i':
        sqlite3_bind_int64(pStmt, i, *(i64 *)pArg);
        break;

      default:
        pErr->rc = 1;
        pErr->zErr = sqlite3_mprintf("Cannot discern type: \"%s\"", zName);
        pStmt = 0;
        break;
    }
  }

  return pStmt;
}

static i64 execsql_i64_x(
  Error *pErr,                    /* IN/OUT: Error code */
  Sqlite *pDb,                    /* Database handle */
  ...                             /* SQL and pointers to parameter values */
){
  i64 iRet = 0;
  if( pErr->rc==SQLITE_OK ){
    sqlite3_stmt *pStmt;          /* SQL statement to execute */
    va_list ap;                   /* ... arguments */
    va_start(ap, pDb);
    pStmt = getAndBindSqlStatement(pErr, pDb, ap);
    if( pStmt ){
      int first = 1;
      while( SQLITE_ROW==sqlite3_step(pStmt) ){
        if( first && sqlite3_column_count(pStmt)>0 ){
          iRet = sqlite3_column_int64(pStmt, 0);
        }
        first = 0;
      }
      if( SQLITE_OK!=sqlite3_reset(pStmt) ){
        sqlite_error(pErr, pDb, "reset");
      }
    }
    va_end(ap);
  }
  return iRet;
}

static char * execsql_text_x(
  Error *pErr,                    /* IN/OUT: Error code */
  Sqlite *pDb,                    /* Database handle */
  int iSlot,                      /* Db handle slot to store text in */
  ...                             /* SQL and pointers to parameter values */
){
  char *zRet = 0;

  if( iSlot>=pDb->nText ){
    int nByte = sizeof(char *)*(iSlot+1);
    pDb->aText = (char **)sqlite3_realloc(pDb->aText, nByte);
    memset(&pDb->aText[pDb->nText], 0, sizeof(char*)*(iSlot+1-pDb->nText));
    pDb->nText = iSlot+1;
  }

  if( pErr->rc==SQLITE_OK ){
    sqlite3_stmt *pStmt;          /* SQL statement to execute */
    va_list ap;                   /* ... arguments */
    va_start(ap, iSlot);
    pStmt = getAndBindSqlStatement(pErr, pDb, ap);
    if( pStmt ){
      int first = 1;
      while( SQLITE_ROW==sqlite3_step(pStmt) ){
        if( first && sqlite3_column_count(pStmt)>0 ){
          zRet = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
          sqlite3_free(pDb->aText[iSlot]);
          pDb->aText[iSlot] = zRet;
        }
        first = 0;
      }
      if( SQLITE_OK!=sqlite3_reset(pStmt) ){
        sqlite_error(pErr, pDb, "reset");
      }
    }
    va_end(ap);
  }

  return zRet;
}

static void integrity_check_x(
  Error *pErr,                    /* IN/OUT: Error code */
  Sqlite *pDb                     /* Database handle */
){
  if( pErr->rc==SQLITE_OK ){
    Statement *pStatement;        /* Statement to execute */
    char *zErr = 0;               /* Integrity check error */

    pStatement = getSqlStatement(pErr, pDb, "PRAGMA integrity_check");
    if( pStatement ){
      sqlite3_stmt *pStmt = pStatement->pStmt;
      while( SQLITE_ROW==sqlite3_step(pStmt) ){
        const char *z = (const char*)sqlite3_column_text(pStmt, 0);
        if( strcmp(z, "ok") ){
          if( zErr==0 ){
            zErr = sqlite3_mprintf("%s", z);
          }else{
            zErr = sqlite3_mprintf("%z\n%s", zErr, z);
          }
        }
      }
      sqlite3_reset(pStmt);

      if( zErr ){
        pErr->zErr = zErr;
        pErr->rc = 1;
      }
    }
  }
}

#ifdef _WIN32
static unsigned __stdcall launch_thread_main(void *pArg){
  Thread *p = (Thread *)pArg;
  p->zRes = p->xProc(p->iTid, p->pArg);
  _endthreadex(0);
  return 0; /* NOT REACHED */
}
#else
static void *launch_thread_main(void *pArg){
  Thread *p = (Thread *)pArg;
  p->zRes = p->xProc(p->iTid, p->pArg);
  return 0;
}
#endif

static void launch_thread_x(
  Error *pErr,                    /* IN/OUT: Error code */
  Threadset *pThreads,            /* Thread set */
  char *(*xProc)(int, void*),     /* Proc to run */
  void *pArg                      /* Argument passed to thread proc */
){
  if( pErr->rc==SQLITE_OK ){
    int iTid = ++pThreads->iMaxTid;
    Thread *p;
    int rc;

    p = (Thread *)sqlite3_malloc(sizeof(Thread));
    memset(p, 0, sizeof(Thread));
    p->iTid = iTid;
    p->pArg = pArg;
    p->xProc = xProc;

#ifdef _WIN32
    rc = SQLITE_OK;
    p->winTid = _beginthreadex(0, 0, launch_thread_main, (void*)p, 0, 0);
    if( p->winTid==0 ) rc = errno ? errno : rc;
#else
    rc = pthread_create(&p->tid, NULL, launch_thread_main, (void *)p);
#endif
    if( rc!=0 ){
      system_error(pErr, rc);
      sqlite3_free(p);
    }else{
      p->pNext = pThreads->pThread;
      pThreads->pThread = p;
    }
  }
}

static void join_all_threads_x(
  Error *pErr,                    /* IN/OUT: Error code */
  Threadset *pThreads             /* Thread set */
){
  Thread *p;
  Thread *pNext;
  for(p=pThreads->pThread; p; p=pNext){
#ifndef _WIN32
    void *ret;
#endif
    int rc;
    pNext = p->pNext;

#ifdef _WIN32
    do {
      rc = WaitForSingleObjectEx((HANDLE)p->winTid, INFINITE, TRUE);
    }while( rc==WAIT_IO_COMPLETION );
    CloseHandle((HANDLE)p->winTid);
#else
    rc = pthread_join(p->tid, &ret);
#endif

    if( rc!=0 ){
      if( pErr->rc==SQLITE_OK ) system_error(pErr, rc);
    }else{
      printf("Thread %d says: %s\n", p->iTid, (p->zRes==0 ? "..." : p->zRes));
      fflush(stdout);
    }
    sqlite3_free(p->zRes);
    sqlite3_free(p);
  }
  pThreads->pThread = 0;
}

#ifdef _WIN32
# define THREADTEST3_STAT _stat
#else
# define THREADTEST3_STAT stat
#endif

static i64 filesize_x(
  Error *pErr,
  const char *zFile
){
  i64 iRet = 0;
  if( pErr->rc==SQLITE_OK ){
    struct THREADTEST3_STAT sStat;
    if( THREADTEST3_STAT(zFile, &sStat) ){
      iRet = -1;
    }else{
      iRet = sStat.st_size;
    }
  }
  return iRet;
}

static void filecopy_x(
  Error *pErr,
  const char *zFrom,
  const char *zTo
){
  if( pErr->rc==SQLITE_OK ){
    i64 nByte = filesize_x(pErr, zFrom);
    if( nByte<0 ){
      test_error_x(pErr, sqlite3_mprintf("no such file: %s", zFrom));
    }else{
      i64 iOff;
      char aBuf[1024];
      int fd1;
      int fd2;
      unlink(zTo);

      fd1 = open(zFrom, O_RDONLY|O_BINARY);
      if( fd1<0 ){
        system_error(pErr, errno);
        return;
      }
      fd2 = open(zTo, O_RDWR|O_CREAT|O_EXCL|O_BINARY, 0644);
      if( fd2<0 ){
        system_error(pErr, errno);
        close(fd1);
        return;
      }

      iOff = 0;
      while( iOff<nByte ){
        int nCopy = sizeof(aBuf);
        if( nCopy+iOff>nByte ){
          nCopy = nByte - iOff;
        }
        if( nCopy!=read(fd1, aBuf, nCopy) ){
          system_error(pErr, errno);
          break;
        }
        if( nCopy!=write(fd2, aBuf, nCopy) ){
          system_error(pErr, errno);
          break;
        }
        iOff += nCopy;
      }

      close(fd1);
      close(fd2);
    }
  }
}

/* 
** Used by setstoptime() and timetostop().
*/
static double timelimit = 0.0;

static double currentTime(void){
  double t;
  static sqlite3_vfs *pTimelimitVfs = 0;
  if( pTimelimitVfs==0 ) pTimelimitVfs = sqlite3_vfs_find(0);
  if( pTimelimitVfs->iVersion>=2 && pTimelimitVfs->xCurrentTimeInt64!=0 ){
    sqlite3_int64 tm;
    pTimelimitVfs->xCurrentTimeInt64(pTimelimitVfs, &tm);
    t = tm/86400000.0;
  }else{
    pTimelimitVfs->xCurrentTime(pTimelimitVfs, &t);
  }
  return t;
}

static void setstoptime_x(
  Error *pErr,                    /* IN/OUT: Error code */
  int nMs                         /* Milliseconds until "stop time" */
){
  if( pErr->rc==SQLITE_OK ){
    double t = currentTime();
    timelimit = t + ((double)nMs)/(1000.0*60.0*60.0*24.0);
  }
}

static int timetostop_x(
  Error *pErr                     /* IN/OUT: Error code */
){
  int ret = 1;
  if( pErr->rc==SQLITE_OK ){
    double t = currentTime();
    ret = (t >= timelimit);
  }
  return ret;
}


/*************************************************************************
**************************************************************************
**************************************************************************
** End infrastructure. Begin tests.
*/
98
99
100
101
102
103
104
105

106
107
108
109
110
111
112
1022
1023
1024
1025
1026
1027
1028

1029
1030
1031
1032
1033
1034
1035
1036







-
+







static char *walthread1_ckpt_thread(int iTid, void *pArg){
  Error err = {0};                /* Error code and message */
  Sqlite db = {0};                /* SQLite database connection */
  int nCkpt = 0;                  /* Checkpoints so far */

  opendb(&err, &db, "test.db", 0);
  while( !timetostop(&err) ){
    usleep(500*1000);
    sqlite3_sleep(500);
    execsql(&err, &db, "PRAGMA wal_checkpoint");
    if( err.rc==SQLITE_OK ) nCkpt++;
    clear_error(&err, SQLITE_BUSY);
  }
  closedb(&err, &db);

  print_and_free_err(&err);
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
1470
1471
1472
1473
1474
1475
1476

1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504







-
+

















+
+
+








  setstoptime(&err, nMs);

  sqlite3_enable_shared_cache(1);
  launch_thread(&err, &threads, dynamic_triggers_2, 0);
  launch_thread(&err, &threads, dynamic_triggers_2, 0);

  sleep(2);
  sqlite3_sleep(2*1000);
  sqlite3_enable_shared_cache(0);

  launch_thread(&err, &threads, dynamic_triggers_2, 0);
  launch_thread(&err, &threads, dynamic_triggers_1, 0);

  join_all_threads(&err, &threads);

  print_and_free_err(&err);
}



#include "tt3_checkpoint.c"
#include "tt3_index.c"
#include "tt3_lookaside1.c"
#include "tt3_vacuum.c"
#include "tt3_stress.c"
#include "tt3_shared.c"

#include "tt3_bcwal2.c"

int main(int argc, char **argv){
  struct ThreadTest {
    void (*xTest)(int);   /* Routine for running this test */
    const char *zTest;    /* Name of this test */
    int nMs;              /* How long to run this test, in milliseconds */
  } aTest[] = {
588
589
590
591
592
593
594



595
596
597
598
599
600
601
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531







+
+
+







    { checkpoint_starvation_2, "checkpoint_starvation_2", 10000 },

    { create_drop_index_1, "create_drop_index_1", 10000 },
    { lookaside1,          "lookaside1", 10000 },
    { vacuum1,             "vacuum1", 10000 },
    { stress1,             "stress1", 10000 },
    { stress2,             "stress2", 60000 },
    { shared1,             "shared1", 10000 },

    { bcwal2_1,            "bcwal2_1", 100000 },
  };
  static char *substArgv[] = { 0, "*", 0 };
  int i, iArg;
  int nTestfound = 0;

  sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
  if( argc<2 ){

Added test/threadtest5.c.




















































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2021-05-12
**
** 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.
**
*************************************************************************
**
** Testing threading behavior when multiple database connections in separate
** threads of the same process are all talking to the same database file.
**
** For best results, ensure that SQLite is compiled with HAVE_USLEEP=1
**
** Only works on unix platforms.
**
** Usage:
**
**      ./threadtest5  ?DATABASE?
**
** If DATABASE is omitted, it defaults to using file:/mem?vfs=memdb.
*/
#include "sqlite3.h"
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>

/* Name of the in-memory database */
static char *zDbName = 0;

/* True for debugging */
static int eVerbose = 0;

/* If rc is not SQLITE_OK, then print an error message and stop
** the test.
*/
static void error_out(int rc, const char *zCtx, int lineno){
  if( rc!=SQLITE_OK ){
    fprintf(stderr, "error %d at %d in \"%s\"\n", rc, lineno, zCtx);
    exit(-1);
  }
}

#if 0
/* Return the number of milliseconds since the Julian epoch (-4714-11-24).
*/
static sqlite3_int64 gettime(void){
  sqlite3_int64 tm;
  sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
  pVfs->xCurrentTimeInt64(pVfs, &tm);
  return tm;
}
#endif

/* Run the SQL in the second argument.
*/
static int exec(
  sqlite3 *db,
  const char *zId,
  int lineno,
  const char *zFormat,
  ...
){
  int rc;
  va_list ap;
  char *zSql;
  va_start(ap, zFormat);
  zSql = sqlite3_vmprintf(zFormat, ap);
  va_end(ap);
  if( eVerbose){
    printf("%s:%d: [%s]\n", zId, lineno, zSql);
    fflush(stdout);
  }
  rc = sqlite3_exec(db, zSql, 0, 0, 0);
  if( rc && eVerbose ){
    printf("%s:%d: return-code %d\n", zId, lineno, rc);
    fflush(stdout);
  }
  sqlite3_free(zSql);
  return rc;
}

/* Generate a perpared statement from the input SQL
*/
static sqlite3_stmt *prepare(
  sqlite3 *db,
  const char *zId,
  int lineno,
  const char *zFormat,
  ...
){
  int rc;
  va_list ap;
  char *zSql;
  sqlite3_stmt *pStmt = 0;
  va_start(ap, zFormat);
  zSql = sqlite3_vmprintf(zFormat, ap);
  va_end(ap);
  if( eVerbose){
    printf("%s:%d: [%s]\n", zId, lineno, zSql);
    fflush(stdout);
  }

  rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
  if( rc ){
    printf("%s:%d: ERROR - %s\n", zId, lineno, sqlite3_errmsg(db));
    exit(-1);
  }
  sqlite3_free(zSql);
  return pStmt;
}

/*
** Wait for table zTable to exist in the schema.
*/
static void waitOnTable(sqlite3 *db, const char *zWorker, const char *zTable){
  while(1){
    int eFound = 0;
    sqlite3_stmt *q = prepare(db, zWorker, __LINE__,
             "SELECT 1 FROM sqlite_schema WHERE name=%Q", zTable);
    if( sqlite3_step(q)==SQLITE_ROW && sqlite3_column_int(q,0)!=0 ){
      eFound = 1;
    }
    sqlite3_finalize(q);
    if( eFound ) return;
    sqlite3_sleep(1);
  }
}

/*
** Return true if x is  a prime number
*/
static int isPrime(int x){
  int i;
  if( x<2 ) return 1;
  for(i=2; i*i<=x; i++){
    if( (x%i)==0 ) return 0;
  }
  return 1;
}

/* Each worker thread runs an instance of the following */
static void *worker(void *pArg){
  int rc;
  const char *zName = (const char*)pArg;
  sqlite3 *db = 0;

  if( eVerbose ){
    printf("%s: startup\n", zName);
    fflush(stdout);
  }

  rc = sqlite3_open(zDbName, &db);
  error_out(rc, "sqlite3_open", __LINE__);
  sqlite3_busy_timeout(db, 2000);

  while( 1 ){
    sqlite3_stmt *q1;
    int tid = -1;
    q1 = prepare(db, zName, __LINE__,
            "UPDATE task SET doneby=%Q"
            " WHERE tid=(SELECT tid FROM task WHERE doneby IS NULL LIMIT 1)"
            "RETURNING tid", zName
    );
    if( sqlite3_step(q1)==SQLITE_ROW ){
      tid = sqlite3_column_int(q1,0);
    }
    sqlite3_finalize(q1);
    if( tid<0 ) break;
    if( eVerbose ){
      printf("%s: starting task %d\n", zName, tid);
      fflush(stdout);
    }
    if( tid==1 ){
      exec(db, zName, __LINE__,
         "CREATE TABLE IF NOT EXISTS p1(x INTEGER PRIMARY KEY);"
      );
    }else if( tid>=2 && tid<=51 ){
      int a, b, i;
      waitOnTable(db, zName, "p1");
      a = (tid-2)*200 + 1;
      b = a+200;
      for(i=a; i<b; i++){
        if( isPrime(i) ){
          exec(db, zName, __LINE__,
              "INSERT INTO p1(x) VALUES(%d)", i);
        }
      }
    }else if( tid==52 ){
      exec(db, zName, __LINE__,
         "CREATE TABLE IF NOT EXISTS p2(x INTEGER PRIMARY KEY);"
         "WITH RECURSIVE"
         "  c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<10000)"
         "INSERT INTO p2(x) SELECT x FROM c;"
      );
    }else if( tid>=53 && tid<=62 ){
      int a, b, i;
      waitOnTable(db, zName, "p2");
      a = (tid-53)*10 + 2;
      b = a+9;
      for(i=a; i<=b; i++){
        exec(db, zName, __LINE__,
          "DELETE FROM p2 WHERE x>%d AND (x %% %d)==0", i, i);
      }
    }
    if( eVerbose ){
      printf("%s: completed task %d\n", zName, tid);
      fflush(stdout);
    }
    sqlite3_sleep(1);
  }

  sqlite3_close(db);

  if( eVerbose ){
    printf("%s: exit\n", zName);
    fflush(stdout);
  }
  return 0;
}

/* Print a usage comment and die */
static void usage(const char *argv0){
  printf("Usage: %s [options]\n", argv0);
  printf(
    "  -num-workers N      Run N worker threads\n"
    "  -v                  Debugging output\n"
  );
  exit(1);
}

/* Maximum number of threads */
#define MX_WORKER 100

/*
** Main routine
*/
int main(int argc, char **argv){
  int i;
  int nWorker = 4;
  int rc;
  sqlite3 *db = 0;
  sqlite3_stmt *q;
  pthread_t aWorker[MX_WORKER];
  char aWorkerName[MX_WORKER][8];

  for(i=1; i<argc; i++){
    const char *zArg = argv[i];
    if( zArg[0]!='-' ){
      if( zDbName==0 ){
        zDbName = argv[i];
        continue;
      }
      printf("unknown argument: %s\n", zArg);
      usage(argv[0]);
    }
    if( zArg[1]=='-' ) zArg++;
    if( strcmp(zArg, "-v")==0 ){
      eVerbose = 1;
      continue;
    }
    if( strcmp(zArg, "-num-workers")==0 && i+1<argc ){
      nWorker = atoi(argv[++i]);
      if( nWorker<1 || nWorker>MX_WORKER ){
        printf("number of threads must be between 1 and %d\n", MX_WORKER);
        exit(1);
      }
      continue;
    }
    printf("unknown option: %s\n", argv[i]);
    usage(argv[0]);
  }
  if( zDbName==0 ) zDbName = "file:/mem?vfs=memdb";

  sqlite3_config(SQLITE_CONFIG_URI, (int)1);
  rc = sqlite3_open(zDbName, &db);
  error_out(rc, "sqlite3_open", __LINE__);

  rc = exec(db, "SETUP", __LINE__,
    "DROP TABLE IF EXISTS task;\n"
    "DROP TABLE IF EXISTS p1;\n"
    "DROP TABLE IF EXISTS p2;\n"
    "DROP TABLE IF EXISTS verify;\n"
    "CREATE TABLE IF NOT EXISTS task(\n"
    "  tid INTEGER PRIMARY KEY,\n"
    "  doneby TEXT\n"
    ");\n"
    "WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100)"
    "INSERT INTO task(tid) SELECT x FROM c;\n"
  );
  error_out(rc, "sqlite3_exec", __LINE__);

  for(i=0; i<nWorker; i++){
    sqlite3_snprintf(sizeof(aWorkerName[i]), aWorkerName[i],
             "W%02d", i);
    pthread_create(&aWorker[i], 0, worker, aWorkerName[i]);
  }
  for(i=0; i<nWorker; i++){
    pthread_join(aWorker[i], 0);
  }

  for(i=0; i<nWorker; i++){
    q = prepare(db, "MAIN", __LINE__,
          "SELECT group_concat(tid,',') FROM task WHERE doneby=%Q",
          aWorkerName[i]);
    if( sqlite3_step(q)==SQLITE_ROW ){
      printf("%s: %s\n", aWorkerName[i], sqlite3_column_text(q,0));
    }
    sqlite3_finalize(q);
  }
  q = prepare(db, "MAIN", __LINE__, "SELECT count(*) FROM p2");
  if( sqlite3_step(q)!=SQLITE_ROW || sqlite3_column_int(q,0)<10 ){
    printf("incorrect result\n");
    exit(-1);
  }
  sqlite3_finalize(q);
  q = prepare(db, "MAIN", __LINE__, "SELECT x FROM p1 EXCEPT SELECT x FROM p2");
  if( sqlite3_step(q)==SQLITE_ROW ){
    printf("incorrect result\n");
    exit(-1);
  }
  sqlite3_finalize(q);
  q = prepare(db, "MAIN", __LINE__, "SELECT x FROM p2 EXCEPT SELECT x FROM p1");
  if( sqlite3_step(q)==SQLITE_ROW ){
    printf("incorrect result\n");
    exit(-1);
  }
  sqlite3_finalize(q);
  printf("OK\n");

  sqlite3_close(db);
  return 0;
}

Added test/tkt-18458b1a.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019 September 10
#
# 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. In particular,
# that problems related to ticket [18458b1a] have been fixed.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix tkt-18458b1a

foreach tn {1 2} {
  reset_db
  if {$tn==1} {
    # Disable the flattener and push-down optimizations
    optimization_control db query-flattener 0
    optimization_control db push-down 0
  } else {
    # Enable them
    optimization_control db query-flattener 1
    optimization_control db push-down 1
  }

  db cache size 0

  do_execsql_test $tn.1.1 {
    CREATE TABLE t0(c0 COLLATE NOCASE);
    INSERT INTO t0(c0) VALUES ('B');
    CREATE VIEW v0(c0, c1) AS SELECT DISTINCT t0.c0, 'a' FROM t0;
  } 

  do_execsql_test $tn.1.2 {
    SELECT count(*) FROM v0 WHERE c1 >= c0;
  } 1

  do_execsql_test $tn.1.3 {
    SELECT count(*) FROM v0 WHERE NOT NOT (c1 >= c0);
  } 1

  do_execsql_test $tn.1.4 {
    SELECT count(*) FROM v0 WHERE ((c1 >= c0) OR 0+0);
  } 1
}

finish_test

Changes to test/tkt-2d1a5c67d.test.

15
16
17
18
19
20
21
22

23
24
25
26
27
28
29
15
16
17
18
19
20
21

22
23
24
25
26
27
28
29







-
+







# 
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix tkt-2d1a5c67d

ifcapable {!vtab} {finish_test; return}
ifcapable {!vtab || !incrblob} {finish_test; return}
if {[wal_is_capable]==0} {finish_test; return}

for {set ii 1} {$ii<=10} {incr ii} {
  do_test tkt-2d1a5c67d.1.$ii {
    db close
    forcedelete test.db test.db-wal
    sqlite3 db test.db

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-3a77c9714e.test.

1

2
3
4
5
6
7
8

1
2
3
4
5
6
7
8
-
+







# 2011 December 06
# 2011-12-06
#
# 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.
64
65
66
67
68
69
70

71














72
64
65
66
67
68
69
70
71

72
73
74
75
76
77
78
79
80
81
82
83
84
85
86







+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+

        SELECT SrcWord, B.Id as BeginningId, B.Title || E.Title As Connected
        FROM Beginnings B LEFT JOIN Endings E ON B.EndingId=E.EndingId
        WHERE Connected=SrcWord LIMIT 1
      )
    )
} {FACTORING FACTOR SWIMMING SWIMM} 

# Similar problem discovered by dbsqlfuzz on 2019-09-18

#
do_execsql_test 3.0 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(i INT PRIMARY KEY, a, b);
  INSERT INTO t1 VALUES(NULL,'one','i');
  CREATE INDEX i1a ON t1(a);
  CREATE INDEX i1b ON t1(b);
  SELECT (SELECT 1
            FROM (SELECT 1 FROM t1 WHERE a=1 OR b='i')
           WHERE a='o'
              OR b IN (SELECT a=('b' IN (SELECT 'a'))))
    FROM t1;
} {{}}

finish_test

Changes to test/tkt-78e04e52ea.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

65
66
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







-
-
+
+












-
+





-
+


} {0 {} {} 0 {} 0 1 x CHAR(100) 0 {} 0}
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 '1abc%';}
} {/*SCAN TABLE  USING COVERING INDEX i1*/}
 db eval {EXPLAIN QUERY PLAN SELECT "" FROM "" WHERE "" LIKE '1e5%';}
} {/*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-7bbfb7d442.test.

142
143
144
145
146
147
148
149

150
151
152
153
154
142
143
144
145
146
147
148

149
150
151
152
153
154







-
+





}

do_execsql_test 2.2 {
  SELECT SKU, DeliveredQty FROM InventoryControl WHERE SKU=31
} {31 10}

do_execsql_test 2.3 {
  SELECT CASE WHEN DeliveredQty=10 THEN "TEST PASSED!" ELSE "TEST FAILED!" END 
  SELECT CASE WHEN DeliveredQty=10 THEN 'TEST PASSED!' ELSE 'TEST FAILED!' END 
  FROM InventoryControl WHERE SKU=31; 
} {{TEST PASSED!}}


finish_test

Changes to test/tkt-80e031a00f.test.

20
21
22
23
24
25
26
27

28
29
30


31
32
33
34
35
36
37
38
20
21
22
23
24
25
26

27
28


29
30

31
32
33
34
35
36
37







-
+

-
-
+
+
-







source $testdir/lock_common.tcl
source $testdir/malloc_common.tcl

# EVIDENCE-OF: R-52275-55503 When the right operand is an empty set, the
# result of IN is false and the result of NOT IN is true, regardless of
# the left operand and even if the left operand is NULL.
#
# EVIDENCE-OF: R-13595-45863 Note that SQLite allows the parenthesized
# EVIDENCE-OF: R-64309-54027 Note that SQLite allows the parenthesized
# list of scalar values on the right-hand side of an IN or NOT IN
# operator to be an empty list but most other SQL database database
# engines and the SQL92 standard require the list to contain at least
# operator to be an empty list but most other SQL database engines and
# the SQL92 standard require the list to contain at least one element.
# one element.
#
do_execsql_test tkt-80e031a00f.1 {SELECT 1 IN ()} 0
do_execsql_test tkt-80e031a00f.1b {SELECT 1 IN (2)} 0
do_execsql_test tkt-80e031a00f.1c {SELECT 1 IN (2,3,4,5,6,7,8,9)} 0
do_execsql_test tkt-80e031a00f.2 {SELECT 1 NOT IN ()} 1
do_execsql_test tkt-80e031a00f.2b {SELECT 1 NOT IN (2)} 1
do_execsql_test tkt-80e031a00f.2c {SELECT 1 NOT IN (2,3,4,5,6,7,8,9)} 1

Changes to test/tkt-8454a207b9.test.

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
31
32







+
+
+
+
+
+







# it tests that ticket [8454a207b9fd2243c4c6b7a73f67ea0315717c1a].  Verify
# that a negative default value on an added text column actually comes
# out negative.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
ifcapable !altertable {
  finish_test
  return
}

do_test tkt-8454a207b9.1 {
  db eval {
    CREATE TABLE t1(a);
    INSERT INTO t1 VALUES(1);
    ALTER TABLE t1 ADD COLUMN b TEXT DEFAULT -123.0;
    SELECT b, typeof(b) FROM t1;

Added test/tkt-99378177930f87bd.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022-11-23
#
# 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 file implements tests to verify that the enhancement
# request documented by ticket 99378177930f87bd is working.
#
# The enhancement is that if an aggregate query with a GROUP BY clause
# uses subexpressions in the arguments to aggregate functions that are
# also columns of an index, then the values are pulled from the index
# rather than being recomputed.  This has the potential to make some
# indexed queries works as if the index were covering.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_execsql_test tkt-99378-100 {
  CREATE TABLE t1(a INT, b TEXT, c INT, d INT);
  INSERT INTO t1(a,b,c,d) VALUES
    (1, '{"x":1}', 12,  3),
    (1, '{"x":2}',  4,  5),
    (1, '{"x":1}',  6, 11),
    (2, '{"x":1}', 22,  3),
    (2, '{"x":2}',  4,  5),
    (3, '{"x":1}',  6,  7);
  CREATE INDEX t1x ON t1(d, a, b->>'x', c);
} {}
do_execsql_test tkt-99378-110 {
  SELECT a,
         SUM(1)                              AS t1,
         SUM(CASE WHEN b->>'x'=1 THEN 1 END) AS t2,
         SUM(c)                              AS t3,
         SUM(CASE WHEN b->>'x'=1 THEN c END) AS t4
    FROM t1
   WHERE d BETWEEN 0 and 10
   GROUP BY a;
} {
  1  2  1 16 12
  2  2  1 26 22
  3  1  1  6  6
}

# The proof that the index on the expression is being used is in the
# fact that the byte code contains no "Function" opcodes.  In other words,
# the ->> operator (which is implemented by a function) is never invoked.
# Instead, the b->>'x' value is pulled out of the index.
#
do_execsql_test tkt-99378-120 {
  EXPLAIN
  SELECT a,
         SUM(1)                              AS t1,
         SUM(CASE WHEN b->>'x'=1 THEN 1 END) AS t2,
         SUM(c)                              AS t3,
         SUM(CASE WHEN b->>'x'=1 THEN c END) AS t4
    FROM t1
   WHERE d BETWEEN 0 and 10
   GROUP BY a;
} {~/Function/}


do_execsql_test tkt-99378-130 {
  SELECT a,
         SUM(1)                              AS t1,
         SUM(CASE WHEN b->>'x'=1 THEN 1 END) AS t2,
         SUM(c)                              AS t3,
         SUM(CASE WHEN b->>'x'=1 THEN c END) AS t4
    FROM t1
   WHERE d BETWEEN 0 and 10
   GROUP BY +a;
} {
  1  2  1 16 12
  2  2  1 26 22
  3  1  1  6  6
}
do_execsql_test tkt-99378-140 {
  EXPLAIN
  SELECT a,
         SUM(1)                              AS t1,
         SUM(CASE WHEN b->>'x'=1 THEN 1 END) AS t2,
         SUM(c)                              AS t3,
         SUM(CASE WHEN b->>'x'=1 THEN c END) AS t4
    FROM t1
   WHERE d BETWEEN 0 and 10
   GROUP BY +a;
} {~/Function/}

do_execsql_test tkt-99378-200 {
  DROP INDEX t1x;
  CREATE INDEX t1x ON t1(a, d, b->>'x', c);
}
do_execsql_test tkt-99378-210 {
  SELECT a,
         SUM(1)                              AS t1,
         SUM(CASE WHEN b->>'x'=1 THEN 1 END) AS t2,
         SUM(c)                              AS t3,
         SUM(CASE WHEN b->>'x'=1 THEN c END) AS t4
    FROM t1
   WHERE d BETWEEN 0 and 10
   GROUP BY a;
} {
  1  2  1 16 12
  2  2  1 26 22
  3  1  1  6  6
}
do_execsql_test tkt-99378-220 {
  EXPLAIN
  SELECT a,
         SUM(1)                              AS t1,
         SUM(CASE WHEN b->>'x'=1 THEN 1 END) AS t2,
         SUM(c)                              AS t3,
         SUM(CASE WHEN b->>'x'=1 THEN c END) AS t4
    FROM t1
   WHERE d BETWEEN 0 and 10
   GROUP BY a;
} {~/Function/}
do_execsql_test tkt-99378-230 {
  SELECT a,
         SUM(1)                              AS t1,
         SUM(CASE WHEN b->>'x'=1 THEN 1 END) AS t2,
         SUM(c)                              AS t3,
         SUM(CASE WHEN b->>'x'=1 THEN c END) AS t4
    FROM t1
   WHERE d BETWEEN 0 and 10
   GROUP BY a;
} {
  1  2  1 16 12
  2  2  1 26 22
  3  1  1  6  6
}
do_execsql_test tkt-99378-240 {
  EXPLAIN
  SELECT a,
         SUM(1)                              AS t1,
         SUM(CASE WHEN b->>'x'=1 THEN 1 END) AS t2,
         SUM(c)                              AS t3,
         SUM(CASE WHEN b->>'x'=1 THEN c END) AS t4
    FROM t1
   WHERE d BETWEEN 0 and 10
   GROUP BY a;
} {~/Function/}

# 2022-12-20 dbsqlfuzz a644e70d7683a7ca59c71861a153c1dccf8850b9
#
do_execsql_test tkt-99378-300 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a INT);
  CREATE INDEX i1 ON t1(a,a=a);
  INSERT INTO t1 VALUES(1),(2),(3),(4);
  SELECT * FROM t1 NATURAL JOIN t1 
   WHERE a==1
      OR (
           (SELECT avg(
                (SELECT sum((SELECT 1 FROM t1 NATURAL RIGHT JOIN t1 WHERE a=a)))) AS xyz
           )
           AND a==2
         );
} {1 2}
do_execsql_test tkt-99378-310 {
  DROP INDEX i1;
  SELECT * FROM t1 NATURAL JOIN t1 
   WHERE a==1
      OR (
           (SELECT avg(
                (SELECT sum((SELECT 1 FROM t1 NATURAL RIGHT JOIN t1 WHERE a=a)))) AS xyz
           )
           AND a==2
         );
} {1 2}

finish_test

Added test/tkt-a7debbe0.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019 September 10
#
# 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. In particular,
# that problems related to ticket a7debbe0ad1 have been fixed.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix tkt-a7debbe0

foreach tn {1 2} {
  reset_db
  if {$tn==1} {
    # Disable the flattener
    optimization_control db query-flattener 0
  } else {
    # Enable the flattener
    optimization_control db query-flattener 1
  }

  do_execsql_test $tn.1.0 {
    CREATE TABLE t0(xyz INTEGER);
    INSERT INTO t0(xyz) VALUES(456);
    CREATE VIEW v2(a, B) AS 
        SELECT 'a', 'B' COLLATE NOCASE FROM t0;
    CREATE TABLE t2(a, B COLLATE NOCASE);
    INSERT INTO t2 VALUES('a', 'B');
    CREATE VIEW v3(a, B) AS
        SELECT 'a' COLLATE BINARY, 'B' COLLATE NOCASE FROM t0;

    CREATE VIEW v4(a, B) AS
        SELECT 'a', +CAST('B' COLLATE NOCASE AS TEXT) FROM t0;

    CREATE VIEW v5(a, B) AS
        SELECT 'a', ('B' COLLATE NOCASE) || '' FROM t0;
  }

  # Table t2 and views v2 through v5 should all be equivalent.
  do_execsql_test $tn.1.1.1 { SELECT a   >= B FROM t2;         } 1
  do_execsql_test $tn.1.1.2 { SELECT 'a' >= 'B' COLLATE NOCASE } 0
  do_execsql_test $tn.1.1.3 { SELECT a   >= B FROM v2          } 1
  do_execsql_test $tn.1.1.4 { SELECT a   >= B FROM v3          } 1
  do_execsql_test $tn.1.1.5 { SELECT a   >= B FROM v4          } 1
  do_execsql_test $tn.1.1.6 { SELECT a   >= B FROM v5          } 1

  do_execsql_test $tn.1.2.1 { SELECT B   < a FROM t2           } 0
  do_execsql_test $tn.1.2.2 { SELECT 'B' COLLATE NOCASE < 'a'  } 0
  do_execsql_test $tn.1.2.3 { SELECT B   < a FROM v2           } 0
  do_execsql_test $tn.1.2.4 { SELECT B   < a FROM v3           } 0
  do_execsql_test $tn.1.2.5 { SELECT a  < B FROM v4           } 0
  do_execsql_test $tn.1.2.6 { SELECT a  < B FROM v5           } 0

  #-------------------------------------------------------------------------
  do_execsql_test $tn.2.0 {
    CREATE TABLE t5(a, b COLLATE NOCASE);
    INSERT INTO t5 VALUES(1, 'XYZ');
  }

  # Result should be 0, as column "xyz" from the sub-query has implicit
  # collation sequence BINARY.
  do_execsql_test $tn.2.1 {
    SELECT xyz==b FROM ( SELECT a, 'xyz' AS xyz FROM t5 ), t5;
  } {0}

  # Result should be 1, as literal 'xyz' has no collation sequence, so
  # the comparison uses the implicit collation sequence of the RHS - NOCASE.
  do_execsql_test $tn.2.2 {
    SELECT 'xyz'==b FROM ( SELECT a, 'xyz' AS xyz FROM t5 ), t5;
  } {1}

  #-----------------------------------------------------------------------
  # The test case submitted with the ticket.
  #
  do_execsql_test $tn.3.0 {
    DROP TABLE t0;
    DROP VIEW v2;

    CREATE TABLE t0(c0);
    INSERT INTO t0(c0) VALUES('');
    CREATE VIEW v2(c0, c1) AS 
        SELECT 'B' COLLATE NOCASE, 'a' FROM t0 ORDER BY t0.c0;
    SELECT SUM(count) FROM (
      SELECT v2.c1 BETWEEN v2.c0 AND v2.c1 as count FROM v2
    );
  } 1

  # The result is 1, as the collation used is the implicit collation sequence
  # of v2.c1 - BINARY.
  do_execsql_test $tn.3.1 {
    SELECT v2.c1 BETWEEN v2.c0 AND v2.c1 as count FROM v2;
  } 1
}

finish_test

Changes to test/tkt-a8a0d2996a.test.

80
81
82
83
84
85
86
87

88
89
90

91
92
93


94
95
80
81
82
83
84
85
86

87
88
89

90
91


92
93
94
95







-
+


-
+

-
-
+
+


  SELECT '100x'+'-2y';
} {98}
do_execsql_test 4.3 {
  SELECT '100x'+'4.5y';
} {104.5}
do_execsql_test 4.4 {
  SELECT '-9223372036854775807x'-'1x';
} {-9.22337203685478e+18}
} {-9223372036854775808}
do_execsql_test 4.5 {
  SELECT '9223372036854775806x'+'1x';
} {9.22337203685478e+18}
} {9223372036854775807}
do_execsql_test 4.6 {
  SELECT '1234x'/'10y';
} {123.4}
  SELECT '1234x'/'10y', '1234x'/'10.y', '1234x'/'1e1y';
} {123 123.4 123.4}

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}

56
57
58
59
60
61
62
63

64
65
66
67
68
69
70
56
57
58
59
60
61
62

63
64
65
66
67
68
69
70







-
+







  6 "SELECT * FROM t1 GROUP BY y ORDER BY x"
  {1 3  2 2  3 1} {$tblscan*$grpsort*$sort}

  7 "SELECT * FROM t1 GROUP BY x, y ORDER BY x, y DESC"
  {1 3  2 2  3 1} {$idxscan*$sort}

  8 "SELECT * FROM t1 GROUP BY x, y ORDER BY x DESC, y DESC"
  {3 1  2 2  1 3} {$idxscan*$sort}
  {3 1  2 2  1 3} {$idxscan}

  9 "SELECT * FROM t1 GROUP BY x, y ORDER BY x ASC, y ASC"
  {1 3  2 2  3 1} {$idxscan}

  10 "SELECT * FROM t1 GROUP BY x, y ORDER BY x COLLATE nocase, y"
  {1 3  2 2  3 1} {$idxscan*$sort}

Changes to test/tkt-cbd054fa6b.test.

12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
12
13
14
15
16
17
18

19
20
21
22
23
24
25
26







-
+







# This file implements tests to verify that ticket [cbd054fa6b] has been
# fixed.  
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable !stat4&&!stat3 {
ifcapable !stat4 {
  finish_test
  return
}

proc s {blob} {
  set ret ""
  binary scan $blob c* bytes
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
51
52
53
54
55
56
57







58
59
60
61
62
63






64
65
66
67
68
69
70







-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-







    INSERT INTO t1 VALUES (NULL, 'H');
    INSERT INTO t1 VALUES (NULL, 'I');
    SELECT count(*) FROM t1;
  }
} {10}
do_test tkt-cbd05-1.2 {
  db eval { ANALYZE; }
  ifcapable stat4 {
    db eval {
      PRAGMA writable_schema = 1;
      CREATE VIEW vvv AS 
      SELECT tbl,idx,neq,nlt,ndlt,test_extract(sample,0) AS sample
      FROM sqlite_stat4;
      PRAGMA writable_schema = 0;
  db eval {
    PRAGMA writable_schema = 1;
    CREATE VIEW vvv AS 
    SELECT tbl,idx,neq,nlt,ndlt,test_extract(sample,0) AS sample
    FROM sqlite_stat4;
    PRAGMA writable_schema = 0;
    }
  } else {
    db eval {
      CREATE VIEW vvv AS 
      SELECT tbl,idx,neq,nlt,ndlt,sample FROM sqlite_stat3;
    }
  }
} {}
do_test tkt-cbd05-1.3 {
  execsql { 
    SELECT tbl,idx,group_concat(s(sample),' ') 
    FROM vvv 
    WHERE idx = 't1_x' 

Changes to test/tkt-f67b41381a.test.

10
11
12
13
14
15
16





17
18
19
20
21
22
23
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28







+
+
+
+
+







#***********************************************************************
# Test that ticket f67b41381a has been resolved.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix tkt-f67b41381a

ifcapable !altertable {
  finish_test
  return
}

do_execsql_test 1.0 {
  CREATE TABLE t1(a);
  INSERT INTO t1 VALUES(1);
  ALTER TABLE t1 ADD COLUMN b DEFAULT 2;
  CREATE TABLE t2(a, b);
  INSERT INTO t2 SELECT * FROM t1;

Changes to test/tkt-f7b4edec.test.

12
13
14
15
16
17
18

19
20
21
22
23
24
25
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26







+







#
# This file implements tests to verify that ticket 
# [f7b4edece25c994857dc139207f55a53c8319fae] has been fixed.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable !shared_cache { finish_test ; return }

# Open two database connections to the same database file in
# shared cache mode.  Create update hooks that will fire on
# each connection.
#
db close
set ::enable_shared_cache [sqlite3_enable_shared_cache 1]

Changes to test/tkt2854.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
24
25
26
27
28
29
30










31

32
33
34
35
36
37
38







-
-
-
-
-
-
-
-
-
-
+
-








# Open 3 database connections. Connection "db" and "db2" share a cache.
# Connection "db3" has its own cache.
#
do_test tkt2854-1.1 {
  sqlite3 db test.db
  sqlite3 db2 test.db

  # This is taken from shared.test.  The Windows VFS expands 
  # ./test.db (and test.db) to be the same thing so the path
  # matches and they share a cache.  By changing the case 
  # for Windows platform, we get around this and get a separate
  # connection.
  if {$::tcl_platform(platform)=="unix"} {
    sqlite3 db3 ./test.db
  } else {
    sqlite3 db3 TEST.DB
  sqlite3 db3 "file:test.db?cache=private" -uri 1
  }

  db eval {
    CREATE TABLE abc(a, b, c);
  }
} {}

# Check that an exclusive lock cannot be obtained if some other 

Changes to test/tkt3292.test.

16
17
18
19
20
21
22

23
24
25
26
27
28
29
30
31
16
17
18
19
20
21
22
23
24

25
26
27
28
29
30
31







+

-







#
# $Id: tkt3292.test,v 1.1 2008/08/13 14:07:41 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_test tkt3292-1.1 {
  sqlite3_db_config db LEGACY_FILE_FORMAT 0
  execsql {
    PRAGMA legacy_file_format=OFF;
    CREATE TABLE t1(a INTEGER PRIMARY KEY, b INT);
    INSERT INTO t1 VALUES(0, 1);
    INSERT INTO t1 VALUES(1, 1);
    INSERT INTO t1 VALUES(2, 1);
    CREATE INDEX i1 ON t1(b);
    SELECT * FROM t1 WHERE b>=1;
  }

Changes to test/tkt3442.test.

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
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







+


-
+


-
+






-
+







  }
} {}

# 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.
#
sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1
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/tkt3793.test.

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
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







-












-
-
-
-
-
+
-
-
+
-
-
-
-
+
+
-







#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests to verify that ticket #3793 has been
# fixed.  
#
# $Id: tkt3793.test,v 1.2 2009/06/01 16:42:18 shane Exp $


set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable !shared_cache||!attach {
  finish_test
  return
}
set ::enable_shared_cache [sqlite3_enable_shared_cache 1]

do_test tkt3793-1.1 {
  # This is taken from shared.test.  The Windows VFS expands 
  # ./test.db (and test.db) to be the same thing so the path
  # matches and they share a cache.  By changing the case 
  # for Windows platform, we get around this and get a separate
  # connection.
  db close
  if {$::tcl_platform(platform)=="unix"} {
    sqlite3 db1 test.db
  sqlite3 db "file:test.db" -uri 1
    sqlite3 db2 test.db
  } else {
    sqlite3 db1 TEST.DB
    sqlite3 db2 TEST.DB
  sqlite3 db1 "file:test.db?cache=private" -uri 1
  sqlite3 db2 "file:test.db?cache=shared" -uri 1
  }
  execsql {
    BEGIN;
    CREATE TABLE t1(a, b);
    CREATE TABLE t2(a PRIMARY KEY, b);
    INSERT INTO t1 VALUES(randstr(50,50), randstr(50,50));
    INSERT INTO t1 SELECT randstr(50,50), randstr(50,50) FROM t1;
    INSERT INTO t1 SELECT randstr(50,50), randstr(50,50) FROM t1;

Changes to test/tkt3810.test.

79
80
81
82
83
84
85
















86
87
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


  execsql {DROP TABLE t1}
  execsql {
    SELECT name FROM sqlite_temp_master;
  }
} {}

db2 close

# 2020-11-06 forum post https://sqlite.org/forum/forumpost/157dc791df
#
reset_db
do_test tkt3810-100 {
  db eval {
    ATTACH ':memory:' AS aux1;
    CREATE TABLE aux1.t1(x);
    CREATE TEMP TRIGGER r1 DELETE ON t1 BEGIN SELECT *; END;
    CREATE VIEW t1 AS SELECT *;
  }
  catch {db eval {
    CREATE VIRTUAL TABLE t2 USING nosuchmodule;
  }}
  db eval {CREATE TABLE t3(z);}
} {}

finish_test

Changes to test/tkt3841.test.

18
19
20
21
22
23
24

25
26
27
28
29
30
31
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32







+







source $testdir/tester.tcl

ifcapable !subquery {
  finish_test
  return
}

sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1
do_test tkt3841.1 {
  execsql {
    CREATE TABLE table2 (key TEXT, x TEXT);
    CREATE TABLE list (key TEXT, value TEXT);
  
    INSERT INTO table2 VALUES ("a", "alist");
    INSERT INTO table2 VALUES ("b", "blist");

Changes to test/tkt3935.test.

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
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_test tkt3935.3 {
  execsql { SELECT j1.b FROM (t1 INNER JOIN t2 ON a=c) AS j1 }
} {}


do_test tkt3935.4 {
  catchsql { SELECT a FROM (t1) AS t ON b USING(a) }
} {1 {a JOIN clause is required before ON}}
} {1 {near "USING": syntax error}}
do_test tkt3935.5 {
  catchsql { SELECT a FROM (t1) AS t ON b }
} {1 {a JOIN clause is required before ON}}
do_test tkt3935.6 {
  catchsql { SELECT a FROM (SELECT * FROM t1) AS t ON b USING(a) }
} {1 {a JOIN clause is required before ON}}
} {1 {near "USING": syntax error}}
do_test tkt3935.7 {
  catchsql { SELECT a FROM (SELECT * FROM t1) AS t ON b }
} {1 {a JOIN clause is required before ON}}
do_test tkt3935.8 {
  catchsql { SELECT a FROM t1 AS t ON b }
} {1 {a JOIN clause is required before ON}}
do_test tkt3935.9 {
  catchsql { SELECT a FROM t1 AS t ON b USING(a) }
} {1 {a JOIN clause is required before ON}}
} {1 {near "USING": syntax error}}
do_test tkt3935.10 {
  catchsql { SELECT a FROM t1 AS t USING(a) }
} {1 {a JOIN clause is required before USING}}

finish_test

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/trace3.test.

246
247
248
249
250
251
252















































































253
254
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



do_test trace3-11.2 {
  set ::stmtlist(record) {}
  db trace_v2 trace_v2_record 8
  db close
  set ::stmtlist(record)
} {/^-?\d+$/}

#-------------------------------------------------------------------------
reset_db
do_test 12.1.0 {
  set ::STMT [sqlite3_prepare_v2 $DB \
    "SELECT ?1 || ?1 || ?1 || ?2 || ?3 || ?4 || ? || ?1 || ?" -1 TAIL
  ]
  sqlite3_bind_parameter_count $::STMT
} {6}

do_test 12.1.1 {
  sqlite3_bind_text $STMT 1 "A" 1
  sqlite3_bind_text $STMT 2 "B" 1
  sqlite3_bind_text $STMT 3 "C" 1
  sqlite3_bind_text $STMT 4 "D" 1
  sqlite3_bind_text $STMT 5 "E" 1
  sqlite3_bind_text $STMT 6 "F" 1
  sqlite3_expanded_sql $STMT
} {SELECT 'A' || 'A' || 'A' || 'B' || 'C' || 'D' || 'E' || 'A' || 'F'}

do_test 12.1.2 {
  sqlite3_step $STMT
  sqlite3_column_text $STMT 0
} {AAABCDEAF}

do_test 12.1.3 {
  sqlite3_finalize $STMT
} {SQLITE_OK}

do_test 12.2.0 {
  execsql {
    CREATE TABLE nameFtsFuzzySearchTable(
      word, distance, langid, score, top, scope
    );
  }
  set ::STMT [sqlite3_prepare_v2 $DB {
    SELECT
      substr(word,1,length(?1)-1) AS term,
      distance,
      langid,
      score
    FROM
      nameFtsFuzzySearchTable
    WHERE
      word MATCH (?1) AND abs(?1) = abs(term)
      AND top = ?2 AND distance > ?3 AND scope = ?4 AND langid = ?
    GROUP BY term, langid 
    HAVING (1.0 - ((distance / 100.0) / CAST( length(?1) - 1 AS REAL ))) >= ?
  } -1 TAIL]
  sqlite3_bind_parameter_count $::STMT
} {6}

do_test 12.1.1 {
  sqlite3_bind_text $STMT 1 "A" 1
  sqlite3_bind_text $STMT 2 "B" 1
  sqlite3_bind_text $STMT 3 "C" 1
  sqlite3_bind_text $STMT 4 "D" 1
  sqlite3_bind_text $STMT 5 "E" 1
  sqlite3_bind_text $STMT 6 "F" 1
  sqlite3_expanded_sql $STMT
} {
    SELECT
      substr(word,1,length('A')-1) AS term,
      distance,
      langid,
      score
    FROM
      nameFtsFuzzySearchTable
    WHERE
      word MATCH ('A') AND abs('A') = abs(term)
      AND top = 'B' AND distance > 'C' AND scope = 'D' AND langid = 'E'
    GROUP BY term, langid 
    HAVING (1.0 - ((distance / 100.0) / CAST( length('A') - 1 AS REAL ))) >= 'F'
  }

do_test 12.1.2 {
  sqlite3_finalize $STMT
} {SQLITE_OK}


finish_test

Changes to test/trans.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20













-







# 2001 September 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 script is database locks.
#
# $Id: trans.test,v 1.41 2009/04/28 16:37:59 danielk1977 Exp $


set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create several tables to work with.
#
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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
















+
+
+







    CREATE TABLE two(a int PRIMARY KEY, b text);
    INSERT INTO two VALUES(1,'I');
    INSERT INTO two VALUES(5,'V');
    INSERT INTO two VALUES(10,'X');
    SELECT b FROM two ORDER BY a;
  }
} {I V X}
do_test trans-1.2.1 {
  sqlite3_txn_state db
} {0}
do_test trans-1.2.2 {
  sqlite3_txn_state db main
} {0}
do_test trans-1.2.3 {
  sqlite3_txn_state db temp
} {0}
do_test trans-1.2.4 {
  sqlite3_txn_state db no-such-schema
} {-1}

do_test trans-1.9 {
  sqlite3 altdb test.db
  execsql {SELECT b FROM one ORDER BY a} altdb
} {one two three}
do_test trans-1.10 {
  execsql {SELECT b FROM two ORDER BY a} altdb
} {I V X}
integrity_check trans-1.11
wal_check_journal_mode trans-1.12

# Basic transactions
#
do_test trans-2.1 {
  set v [catch {execsql {BEGIN}} msg]
  lappend v $msg
} {0 {}}
do_test trans-2.1b {
  sqlite3_txn_state db
} {0}
do_test trans-2.2 {
  set v [catch {execsql {END}} msg]
  lappend v $msg
} {0 {}}
do_test trans-2.3 {
  set v [catch {execsql {BEGIN TRANSACTION}} msg]
  lappend v $msg
91
92
93
94
95
96
97










98
99
100
101
102
103
104
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129







+
+
+
+
+
+
+
+
+
+







do_test trans-3.1 {
  execsql {
    BEGIN;
    UPDATE one SET a = 0 WHERE 0;
    SELECT a FROM one ORDER BY a;
  }
} {1 2 3}
do_test trans-3.1b {
  sqlite3_txn_state db
} {2}
do_test trans-3.1c {
  sqlite3_txn_state db main
} {2}
do_test trans-3.1d {
  sqlite3_txn_state db temp
} {0}

do_test trans-3.2 {
  catchsql {
    SELECT a FROM two ORDER BY a;
  } altdb
} {0 {1 5 10}}

do_test trans-3.3 {
135
136
137
138
139
140
141




142
143
144
145
146
147
148
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177







+
+
+
+







  catchsql {
    SELECT a FROM one ORDER BY a;
  } altdb
} {0 {1 2 3}}
do_test trans-3.10 {
  execsql {END TRANSACTION}
} {}
do_test trans-3.10b {
  sqlite3_txn_state db
} {0}


do_test trans-3.11 {
  set v [catch {execsql {
    SELECT a FROM two ORDER BY a;
  } altdb} msg]
  lappend v $msg
} {0 {1 4 5 10}}
248
249
250
251
252
253
254









255
256
257
258
259
260
261
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299







+
+
+
+
+
+
+
+
+







do_test trans-5.1 {
  execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
} {}
do_test trans-5.2 {
  execsql {BEGIN TRANSACTION}
  execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
} {}
do_test trans-5.2b {
  sqlite3_txn_state db
} {1}
do_test trans-5.2c {
  sqlite3_txn_state db main
} {1}
do_test trans-5.2d {
  sqlite3_txn_state db temp
} {0}
do_test trans-5.3 {
  execsql {CREATE TABLE one(a text, b int)}
  execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
} {one}
do_test trans-5.4 {
  execsql {SELECT a,b FROM one ORDER BY b}
} {}

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
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







-
+






-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


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);
} {}

#-------------------------------------------------------------------------
# 2021-08-31 forum https://sqlite.org/forum/forumpost/8d1b58f112
reset_db
do_execsql_test transitive1-700 {
  CREATE TABLE t1(a INT PRIMARY KEY);
  INSERT INTO t1(a) VALUES(1),(2),(3);
  CREATE TABLE t2(x INTEGER PRIMARY KEY,y INT);
  INSERT INTO t2(y) VALUES(2),(3);
}

do_execsql_test transitive1-710 {
  SELECT * FROM t1 CROSS JOIN t2 WHERE t2.y=t1.a AND t1.a=t2.x
} {}

do_execsql_test transitive1-720 {
  SELECT * FROM t1 CROSS JOIN t2 WHERE likely(t2.y=t1.a) AND unlikely(t1.a=t2.x)
} {}

# 2021-10-04 forum https://sqlite.org/forum/forumpost/a65cacbf5e1c41ba
#
reset_db
do_execsql_test transitive1-800 {
  CREATE TABLE t1(a INT);
  INSERT INTO t1 VALUES(0),(3);
  CREATE TABLE t2(b INT UNIQUE, c INT);
  INSERT INTO t2 VALUES(1,4)	,(0,5);
  SELECT * FROM t1 WHERE EXISTS (SELECT 1 FROM t2 WHERE c=a AND b IS a);
  SELECT * FROM t1 WHERE EXISTS (SELECT 1 FROM t2 WHERE a=c AND a IS b);
  SELECT * FROM t1 WHERE EXISTS (SELECT 1 FROM t2 WHERE a=c AND b IS a);
  SELECT * FROM t1 WHERE EXISTS (SELECT 1 FROM t2 WHERE c=a AND a IS b);
} {}
do_execsql_test transitive1-810 {
  CREATE TABLE t3(a INTEGER PRIMARY KEY,b);
  INSERT INTO t3(a,b) VALUES(1,2),(5,5),(7,11);
  SELECT * FROM t3 WHERE a=b AND a='5';
} {5 5}
do_execsql_test transitive1-811 {
  SELECT * FROM t3 WHERE a=b AND a='4';
} {}
do_execsql_test transitive1-812 {
  SELECT * FROM t3 WHERE a=b AND a='7';
} {}
do_execsql_test transitive1-813 {
  SELECT * FROM t3 WHERE a=b AND a='5x';
} {}

finish_test

Changes to test/trigger1.test.

763
764
765
766
767
768
769






































































770
771
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


} {1 2 2}
do_execsql_test trigger1-19.1 {
  DELETE FROM t19;
  INSERT INTO t19(a,b,c) VALUES(1,2,3);
  UPDATE t19 SET c=CASE WHEN b=2 THEN b ELSE b+99 END WHERE a=1;
  SELECT * FROM t19;
} {1 2 2}

# 2019-08-26 Chromium sqlite3_fts3_lpm_fuzzer find.
#
db close
sqlite3 db :memory:
do_execsql_test trigger1-20.1 {
  CREATE TABLE t20_1(x);
  ATTACH ':memory:' AS aux;
  CREATE TABLE aux.t20_2(y);
  CREATE TABLE aux.t20_3(z);
  CREATE TEMP TRIGGER r20_3 AFTER INSERT ON t20_2 BEGIN UPDATE t20_3 SET z=z+1; END;
  DETACH aux;
  DROP TRIGGER r20_3;
} {}

# 2019-10-24 ticket 50c09fc2cf0d91ce
#
db close
sqlite3 db :memory:
do_execsql_test trigger1-21.1 {
  PRAGMA recursive_triggers = true;
  CREATE TABLE t0(a, b, c UNIQUE);
  CREATE UNIQUE INDEX i0 ON t0(b) WHERE a;
  CREATE TRIGGER tr0 AFTER DELETE ON t0 BEGIN
    DELETE FROM t0;
  END;
  INSERT INTO t0(a,b,c) VALUES(0,0,9),(1,1,1);
  REPLACE INTO t0(a,b,c) VALUES(2,0,9);
  SELECT * FROM t0;
} {2 0 9}

# 2020-01-04 From Yongheng
# The test case below caused problems for the register validity
# tracking logic.  There was no bug in the release build.  The
# only problem was a false-positive in the register validity
# tracking.
#
reset_db
do_execsql_test trigger1-22.10 {
  CREATE TABLE t1(
    a INTEGER PRIMARY KEY,
    b DOUBLE
  );
  CREATE TRIGGER x AFTER UPDATE ON t1 BEGIN
   SELECT sum(b)OVER(ORDER BY (SELECT b FROM t1 AS x 
                               WHERE b IN (t1.a,127,t1.b)
                               GROUP BY b))
     FROM t1
     GROUP BY a;
  END;
  CREATE TEMP TRIGGER x BEFORE INSERT ON t1 BEGIN
    UPDATE t1
       SET b=randomblob(10)
     WHERE b >= 'E'
       AND a < (SELECT a FROM t1 WHERE a<22 GROUP BY b);
  END;
  INSERT INTO t1(b) VALUES('Y'),('X'),('Z');
  SELECT a, CASE WHEN typeof(b)='text' THEN quote(b) ELSE '<blob>' END, '|' FROM t1;
} {1 <blob> | 2 'X' | 3 'Z' |}

# 2022-03-06 https://sqlite.org/forum/forumpost/2024e94071
# Harmless assertion fault following a syntax error.
#
reset_db
do_catchsql_test trigger1-23.1 {
  CREATE TABLE t1(a INT);
  CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
    INSERT INTO t1 SELECT e_master LIMIT 1,#1;
  END;
} {1 {near "#1": syntax error}}

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
748
749
750
751
752
753
754















755
756









757








758

759

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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+

+

+
    CREATE TRIGGER trig1 INSTEAD OF DELETE ON v3 BEGIN
      SELECT 1;
    END;
    DELETE FROM v3 WHERE a = 1;
  }
} {}

integrity_check trigger2-9.99

# 2019-11-02 Problem found by TH3, related to generated column support.
db close
sqlite3 db :memory:
do_execsql_test trigger2-10.1 {
  CREATE TABLE t1(a,b,c,d);
  CREATE VIEW v2(a,b,c,d) AS SELECT * FROM t1;
  CREATE TRIGGER v2ins INSTEAD OF INSERT ON v2 BEGIN
    INSERT INTO t1(a,b,c,d) VALUES(new.a, new.b, new.c, new.d);
  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-9.9

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/triggerC.test.

1037
1038
1039
1040
1041
1042
1043





























1044
1045
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


  END;

  INSERT INTO x1 VALUES('go!');
}

do_execsql_test 15.2.2 { SELECT * FROM x2;       } {1 2 3 4}
do_execsql_test 15.2.3 { SELECT * FROM """x2"""; } {3 11 x y}

#-------------------------------------------------------------------------
# At one point queries such as the following were causing segfaults.
#
do_catchsql_test 16.1 {
  SELECT raise(ABORT, 'msg') FROM sqlite_master 
  UNION SELECT 1 
  ORDER BY raise(IGNORE);
} {1 {1st ORDER BY term does not match any column in the result set}}

do_catchsql_test 16.2 {
  SELECT count(*) FROM sqlite_master 
  GROUP BY raise(IGNORE) 
  HAVING raise(ABORT, 'msg');
} {1 {RAISE() may only be used within a trigger-program}}

#-------------------------------------------------------------------------
# Datatype mismatch on IPK when there are BEFORE triggers.
#
do_execsql_test 17.0 {
  CREATE TABLE xyz(x INTEGER PRIMARY KEY, y, z);
  CREATE TRIGGER xyz_tr BEFORE INSERT ON xyz BEGIN
    SELECT new.x;
  END;
}
do_catchsql_test 17.1 {
  INSERT INTO xyz VALUES('hello', 2, 3);
} {1 {datatype mismatch}}


finish_test

Changes to test/triggerE.test.

54
55
56
57
58
59
60


61
62
63
64
65
66
67
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69







+
+







  3 { BEFORE DELETE ON t1 BEGIN SELECT * FROM (SELECT * FROM (SELECT ?)); END; }
  5 { BEFORE DELETE ON t1 BEGIN SELECT * FROM t2 GROUP BY ?; END; }
  6 { BEFORE DELETE ON t1 BEGIN SELECT * FROM t2 LIMIT ?; END; }
  7 { BEFORE DELETE ON t1 BEGIN SELECT * FROM t2 ORDER BY ?; END; }
  8 { BEFORE UPDATE ON t1 BEGIN UPDATE t2 SET c = ?; END; }
  9 { BEFORE UPDATE ON t1 BEGIN UPDATE t2 SET c = 1 WHERE d = ?; END; }
 10 { AFTER INSERT ON t1 BEGIN SELECT * FROM pragma_stats(?); END; }
 11 { BEFORE INSERT ON t1 BEGIN 
      INSERT INTO t1 SELECT max(b) OVER(ORDER BY $1) FROM t1; END }
} {
  catchsql {drop trigger tr1}
  do_catchsql_test 1.1.$tn "CREATE TRIGGER tr1 $defn" [list 1 $errmsg]
  do_catchsql_test 1.2.$tn "CREATE TEMP TRIGGER tr1 $defn" [list 1 $errmsg]
}

#-------------------------------------------------------------------------

Changes to test/triggerF.test.

16
17
18
19
20
21
22
23

24
25
26
27
28
29
30
16
17
18
19
20
21
22

23
24
25
26
27
28
29
30







-
+







ifcapable {!trigger} {
  finish_test
  return
}


foreach {tn sql log} {
  1 { } { }
  1 {} {}

  2 { 
    CREATE TRIGGER trd AFTER DELETE ON t1 BEGIN
      INSERT INTO log VALUES(old.a || old.b || (SELECT count(*) FROM t1));
    END;
  } {1one2 2two1 3three1}

Changes to test/triggerG.test.

70
71
72
73
74
75
76
















77
78
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


    SELECT 0x2147483648e0e0099 AS y WHERE y;
  END;
}

do_catchsql_test 310 {
  INSERT INTO t4 VALUES(1);
} {1 {hex literal too big: 0x2147483648e0e0099}}

#-------------------------------------------------------------------------
# 
do_execsql_test 400 {
  CREATE VIEW v0(a) AS SELECT 1234;
  CREATE TRIGGER t0001 INSTEAD OF DELETE ON v0 BEGIN
    SELECT old.a;
  END;
}
do_execsql_test 405 {
  SELECT a FROM v0;
} {1234}
do_execsql_test 410 {
  DELETE FROM v0;
}


finish_test

Added test/triggerupfrom.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2020 July 14
#
# 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
set testprefix triggerupfrom

do_execsql_test 1.0 {
  CREATE TABLE map(k, v);
  INSERT INTO map VALUES(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four');

  CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);

  CREATE TRIGGER tr AFTER INSERT ON t1 BEGIN
    UPDATE t1 SET c = v FROM map WHERE k=new.a AND a=new.a;
  END;
}

do_execsql_test 1.1 {
  INSERT INTO t1(a) VALUES(1);
}

do_execsql_test 1.2 {
  SELECT a, c FROM t1 ORDER BY a;
} {1 one}

do_execsql_test 1.3 {
  INSERT INTO t1(a) VALUES(2), (3), (4), (5);
  SELECT a, c FROM t1 ORDER BY a;
} {1 one 2 two 3 three 4 four 5 {}}

forcedelete test.db2
do_execsql_test 2.0 {
  ATTACH 'test.db2' AS aux;
  CREATE TABLE aux.t3(x, y);
  INSERT INTO aux.t3 VALUES('x', 'y');
}

do_catchsql_test 2.1 {
  CREATE TRIGGER tr2 AFTER INSERT ON t1 BEGIN
    UPDATE t1 SET b = y FROM aux.t3 WHERE k=new.a;
  END;
} {1 {trigger tr2 cannot reference objects in database aux}}

do_execsql_test 2.2 {
  CREATE TEMP TRIGGER tr2 AFTER INSERT ON t1 BEGIN
    UPDATE t1 SET b = y FROM aux.t3 WHERE a=new.a;
  END;
  INSERT INTO t1(a) VALUES(10), (20);
  SELECT * FROM t1;
} {
  1 {} one 
  2 {} two 
  3 {} three 
  4 {} four 
  5 {} {} 
  10 y {} 
  20 y {}
}

do_execsql_test 2.3 {
  CREATE TABLE link(f, t);
  INSERT INTO link VALUES(5, 2), (20, 10), (2, 1);
  CREATE TRIGGER tr3 BEFORE DELETE ON t1 BEGIN
    UPDATE t1 SET b=coalesce(old.b,old.c) FROM main.link WHERE a=t AND old.a=f;
  END;
  DELETE FROM t1 WHERE a=2;
  SELECT * FROM t1;
} {
  1 two one 
  3 {} three 
  4 {} four 
  5 {} {} 
  10 y {} 
  20 y {}
}

db close
sqlite3 db ""
do_catchsql_test 2.4 {
  ATTACH 'test.db' AS yyy;
  SELECT * FROM t1;
} {1 {malformed database schema (tr3) - trigger tr3 cannot reference objects in database main}}

#-------------------------------------------------------------------------
reset_db
forcedelete test.db2
do_execsql_test 3.0 {
  CREATE TABLE mmm(x, y);
  INSERT INTO mmm VALUES(1, 'one');
  INSERT INTO mmm VALUES(2, 'two');
  INSERT INTO mmm VALUES(3, 'three');

  ATTACH 'test.db2' AS aux;
  CREATE TABLE aux.t1(a, b);
  CREATE TABLE aux.mmm(x, y);
  INSERT INTO aux.mmm VALUES(1, 'ONE');
  INSERT INTO aux.mmm VALUES(2, 'TWO');
  INSERT INTO aux.mmm VALUES(3, 'THREE');

  CREATE TRIGGER aux.ttt AFTER INSERT ON t1 BEGIN
    UPDATE t1 SET b=y FROM mmm WHERE x=new.a AND a=new.a;
  END;
  
  INSERT INTO t1(a) VALUES (2);
  SELECT * FROM t1;
} {2 TWO}

#-------------------------------------------------------------------------
# Test that INSTEAD OF UPDATE triggers on views work with UPDATE...FROM
# statements. Including, if the library is built with ENABLE_HIDDEN_COLUMNS, 
# that they work correctly on views with hidden columns.
#
reset_db
do_execsql_test 4.0 {
  CREATE TABLE t1(k, a, b);
  INSERT INTO t1 VALUES('a', 1, 'one');
  INSERT INTO t1 VALUES('b', 2, 'two');
  INSERT INTO t1 VALUES('c', 3, 'three');
  INSERT INTO t1 VALUES('d', 4, 'four');

  CREATE TABLE log(x);
  CREATE VIEW v1 AS SELECT k, a, b AS __hidden__b FROM t1;
  CREATE TRIGGER tr1 INSTEAD OF UPDATE ON v1 BEGIN
    INSERT INTO log VALUES(
      '('||old.a||','||old.__hidden__b||')->('||new.a||','||new.__hidden__b||')'
    );
  END;
}

ifcapable hiddencolumns {
  do_execsql_test 4.1-hc-enabled {
    SELECT * FROM v1
  } {a 1 b 2 c 3 d 4}
} else {
  do_execsql_test 4.1-hc-disabled {
    SELECT * FROM v1
  } {a 1 one b 2 two c 3 three d 4 four}
}

do_execsql_test 4.2 {
  UPDATE v1 SET a='xyz' WHERE k IN ('a', 'c');
  SELECT * FROM log;
  DELETE FROM log;
} {
  (1,one)->(xyz,one)
  (3,three)->(xyz,three)
}

do_execsql_test 4.3 {
  CREATE TABLE map(k, v);
  INSERT INTO map VALUES('b', 'twelve');
  INSERT INTO map VALUES('d', 'fourteen');
  UPDATE v1 SET a=map.v FROM map WHERE v1.k=map.k;
  SELECT * FROM log;
  DELETE FROM log;
} {
  (2,two)->(twelve,two)
  (4,four)->(fourteen,four)
}



finish_test

Added test/trustschema1.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2020-01-08
#
# 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.
#
#***********************************************************************
# 
# Test cases for managing execution of code snippets found in untrusted
# schemas.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix trustschema1

# edgy functions used in generated columns
#
proc f1 {x} {return $x}
do_test 1.100 {
  db function f1 -innocuous -deterministic f1
  db function f2 -deterministic f1
  db function f3 -directonly -deterministic f1
  db eval {
    CREATE TABLE t1(a, b AS (f1(a+1)), c AS (f2(a+2)));
    INSERT INTO t1 VALUES(100),(200);
  }
} {}
do_catchsql_test 1.110 {
  SELECT a, b, c FROM t1;
} {0 {100 101 102 200 201 202}}
do_execsql_test 1.120 {
  PRAGMA trusted_schema=OFF;
} {}
do_catchsql_test 1.130 {
  SELECT a, b FROM t1;
} {0 {100 101 200 201}}
do_catchsql_test 1.140 {
  SELECT a, b, c FROM t1;
} {1 {unsafe use of f2()}}
do_catchsql_test 1.150 {
  PRAGMA trusted_schema=ON;
  DROP TABLE t1;
  CREATE TABLE t1(a, b AS (f3(a+1)));
} {1 {unsafe use of f3()}}
do_execsql_test 1.160 {
  PRAGMA trusted_schema=OFF;
  CREATE TEMP TABLE temp1(a,b AS (f3(a+1)));
  INSERT INTO temp1(a) VALUES(100),(900);
  SELECT * FROM temp1;
} {100 101 900 901}

# edgy functions used in CHECK constraints
#
do_catchsql_test 1.200 {
  PRAGMA trusted_schema=ON;
  CREATE TABLE t2(a,b,c,CHECK(f3(c)==c));
} {1 {unsafe use of f3()}}
do_catchsql_test 1.210 {
  PRAGMA trusted_schema=Off;
  CREATE TABLE t2(a,b,c,CHECK(f2(c)==c));
} {1 {unsafe use of f2()}}
do_catchsql_test 1.211 {
  PRAGMA trusted_schema=On;
  CREATE TABLE t2(a,b,c,CHECK(f2(c)==c));
} {0 {}}
do_catchsql_test 1.220 {
  INSERT INTO t2 VALUES(1,2,3);
  SELECT * FROM t2;
} {0 {1 2 3}}
do_catchsql_test 1.230 {
  PRAGMA trusted_schema=off;
  INSERT INTO t2 VALUES(4,5,6);
} {1 {unsafe use of f2()}}
do_execsql_test 1.231 {
  SELECT * FROM t2;
} {1 2 3}
# Ok to put as many edgy functions as you want in a
# TEMP table.
do_execsql_test 1.240 {
  PRAGMA trusted_schema=OFF;
  CREATE TEMP TABLE temp2(a, b, CHECK(f3(b)==b));
  INSERT INTO temp2(a,b) VALUES(1,2),('x','y');
  SELECT * FROM temp2;
} {1 2 x y}

# edgy functions used in DEFAULT constraints
#
do_catchsql_test 1.300 {
  CREATE TABLE t3(a,b DEFAULT(f2(25)));
} {0 {}}
do_catchsql_test 1.310 {
  PRAGMA trusted_schema=Off;
  INSERT INTO t3(a) VALUES(1);
} {1 {unsafe use of f2()}}
do_catchsql_test 1.311 {
  INSERT INTO t3(a,b) VALUES(1,2);
} {0 {}}
do_execsql_test 1.320 {
  CREATE TEMP TABLE temp3(a, b DEFAULT(f3(31)));
  INSERT INTO temp3(a) VALUES(22);
  SELECT * FROM temp3;
} {22 31}

# edgy functions used in partial indexes.
#
do_execsql_test 1.400 {
  CREATE TABLE t4(a,b,c);
  INSERT INTO t4 VALUES(1,2,3),('a','b','c'),(4,'d',0);
  SELECT * FROM t4;
  CREATE TEMP TABLE temp4(a,b,c);
  INSERT INTO temp4 SELECT * FROM t4;
} {1 2 3 a b c 4 d 0}
do_catchsql_test 1.410 {
  CREATE INDEX t4a ON t4(a) WHERE f3(c);
} {1 {unsafe use of f3()}}
do_catchsql_test 1.420 {
  PRAGMA trusted_schema=OFF;
  CREATE INDEX t4a ON t4(a) WHERE f2(c);
} {1 {unsafe use of f2()}}
do_execsql_test 1.421 {
  CREATE INDEX t4a ON t4(a) WHERE f1(c);
  SELECT a FROM t4 WHERE f1(c) ORDER BY a;
} {1}
do_execsql_test 1.430 {
  PRAGMA trusted_schema=ON;
  CREATE INDEX t4b ON t4(b) WHERE f2(c);
  SELECT b FROM t4 WHERE f2(c) ORDER BY b;
} {2}
do_execsql_test 1.440 {
  PRAGMA trusted_schema=OFF;
  CREATE INDEX temp4a ON temp4(a) WHERE f3(c);
  SELECT a FROM temp4 WHERE f2(c) ORDER BY a;
} {1}

# edgy functions used in index expressions
#
do_execsql_test 1.500 {
  CREATE TABLE t5(a,b,c);
  INSERT INTO t5 VALUES(1,2,3),(4,5,6),(7,0,-3);
  SELECT * FROM t5;
  CREATE TEMP TABLE temp5(a,b,c);
  INSERT INTO temp5 SELECT * FROM t5;
} {1 2 3 4 5 6 7 0 -3}
do_catchsql_test 1.510 {
  CREATE INDEX t5x1 ON t5(a+f3(b));
} {1 {unsafe use of f3()}}
do_catchsql_test 1.520 {
  PRAGMA trusted_schema=OFF;
  CREATE INDEX t5x1 ON t5(a+f2(b));
} {1 {unsafe use of f2()}}
do_execsql_test 1.521 {
  CREATE INDEX t5x1 ON t5(a+f1(b));
  SELECT * FROM t5 INDEXED BY t5x1 WHERE a+f1(b)=3;
} {1 2 3}
do_execsql_test 1.530 {
  PRAGMA trusted_schema=ON;
  CREATE INDEX t5x2 ON t5(b+f2(c));
  SELECT * FROM t5 INDEXED BY t5x2 WHERE b+f2(c)=11;
} {4 5 6}
do_execsql_test 1.540 {
  PRAGMA trusted_schema=OFF;
  CREATE INDEX temp5x1 ON temp5(a+f3(b));
  SELECT * FROM temp5 INDEXED BY temp5x1 WHERE a+f3(b)=7;
} {7 0 -3}

# edgy functions in VIEWs
#
reset_db
db function f1 -innocuous -deterministic f1
db function f2 -deterministic f1
db function f3 -directonly -deterministic f1
do_execsql_test 2.100 {
  CREATE TABLE t1(a,b,c);
  INSERT INTO t1 VALUES(1,2,3),(100,50,75),(-11,22,-33);
  CREATE VIEW v1a AS SELECT f3(a+b) FROM t1;
  SELECT f3(a+b) FROM t1;
} {3 150 11}
do_catchsql_test 2.110 {
  PRAGMA trusted_schema=ON;
  SELECT * FROM v1a;
} {1 {unsafe use of f3()}}
do_catchsql_test 2.111 {
  PRAGMA trusted_schema=OFF;
  SELECT * FROM v1a;
} {1 {unsafe use of f3()}}
do_execsql_test 2.120 {
  DROP VIEW v1a;
  CREATE TEMP VIEW v1a AS SELECT f3(a+b) FROM t1;
  SELECT * FROM v1a;
} {3 150 11}
do_execsql_test 2.130 {
  CREATE VIEW v1b AS SELECT f2(b+c) FROM t1;
  SELECT f2(b+c) FROM t1;
} {5 125 -11}
do_catchsql_test 2.140 {
  PRAGMA trusted_schema=ON;
  SELECT * FROM v1b;
} {0 {5 125 -11}}
do_catchsql_test 2.141 {
  PRAGMA trusted_schema=OFF;
  SELECT * FROM v1b;
} {1 {unsafe use of f2()}}
do_execsql_test 2.150 {
  DROP VIEW v1b;
  CREATE TEMP VIEW v1b AS SELECT f2(b+c) FROM t1;
  SELECT * FROM v1b;
} {5 125 -11}

# edgy functions inside of triggers
#
do_execsql_test 3.100 {
  DELETE FROM t1;
  CREATE TABLE t2(x);
  CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
    INSERT INTO t2(x) SELECT f3(new.a);
  END;
} {}
do_catchsql_test 3.110 {
  INSERT INTO t1 VALUES(7,6,5);
} {1 {unsafe use of f3()}}
do_execsql_test 3.111 {
  SELECT * FROM t1;
  SELECT * FROM t2;
} {}

do_execsql_test 3.120 {
  DROP TRIGGER r1;
  CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
    INSERT INTO t2(x) SELECT f2(new.a)+100;
  END;
  PRAGMA trusted_schema=ON;
  INSERT INTO t1 VALUES(7,6,5);
  SELECT * FROM t1, t2;
} {7 6 5 107}
do_catchsql_test 3.130 {
  DELETE FROM t1;
  DELETE FROM t2;
  PRAGMA trusted_schema=OFF;
  INSERT INTO t1 VALUES(7,6,5);
} {1 {unsafe use of f2()}}
do_execsql_test 3.131 {
  SELECT * FROM t1;
  SELECT * FROM t2;
} {}

# 2023-01-09 https://sqlite.org/forum/forumpost/c88a671ad083d153
#
do_execsql_test 4.1 {
  PRAGMA trusted_schema=OFF;
  CREATE VIEW test41(x) AS SELECT json_extract('{"a":123}','$.a');
  SELECT * FROM test41;
} 123
do_execsql_test 4.2 {
  PRAGMA trusted_schema=ON;
  SELECT * FROM test41;
} 123

finish_test

Added test/tt3_bcwal2.c.



























































































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2011-02-02
**
** 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 is part of the test program "threadtest3". Despite being a C
** file it is not compiled separately, but included by threadtest3.c using
** the #include directive normally used with header files.
**
** This file contains the implementation of test cases:
**
**     bcwal2_1
*/

static char *bcwal2_1_checkpointer(int iTid, void *pArg){
  Error err = {0};                /* Error code and message */
  Sqlite db = {0};                /* SQLite database connection */
  int nIter = 0;

  opendb(&err, &db, "test.db", 0);
  while( !timetostop(&err) ){
    sql_script(&err, &db, "PRAGMA wal_checkpoint;");
    nIter++;
  }
  closedb(&err, &db);

  print_and_free_err(&err);
  return sqlite3_mprintf("%d iterations", nIter);
}

static char *bcwal2_1_integrity(int iTid, void *pArg){
  Error err = {0};                /* Error code and message */
  Sqlite db = {0};                /* SQLite database connection */
  int nIter = 0;

  opendb(&err, &db, "test.db", 0);
  while( !timetostop(&err) ){
    // integrity_check(&err, &db);
    sql_script(&err, &db, "SELECT * FROM t1;");
    nIter++;
  }
  closedb(&err, &db);

  print_and_free_err(&err);
  return sqlite3_mprintf("%d integrity-checks", nIter);
}

static char *bcwal2_1_writer(int iTid, void *pArg){
  Error err = {0};                /* Error code and message */
  Sqlite db = {0};                /* SQLite database connection */
  int nWrite = 0;                 /* Writes so far */
  int nBusy = 0;                  /* Busy errors so far */
  sqlite3_mutex *pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_APP1);

  opendb(&err, &db, "test.db", 0);
  while( !timetostop(&err) ){

    sql_script(&err, &db,
        "PRAGMA wal_autocheckpoint = 0;"
        "BEGIN CONCURRENT;"
        "  REPLACE INTO t1 VALUES( abs(random() % 100000), "
        "     hex(randomblob( abs( random() % 200 ) + 50 ))"
        "  );"
    );

    if( err.rc==SQLITE_OK ){
      sqlite3_mutex_enter(pMutex);
      sql_script(&err, &db, "COMMIT");
      sqlite3_mutex_leave(pMutex);
      if( err.rc==SQLITE_OK ){
        nWrite++;
      }else{
        clear_error(&err, SQLITE_BUSY);
        sql_script(&err, &db, "ROLLBACK");
        nBusy++;
      }

      assert( err.rc!=SQLITE_OK || sqlite3_get_autocommit(db.db)==1 );
    }
  }
  closedb(&err, &db);

  print_and_free_err(&err);
  return sqlite3_mprintf("%d successful writes, %d busy", nWrite, nBusy);
}

static void bcwal2_1(int nMs){
  Error err = {0};
  Sqlite db = {0};
  Threadset threads = {0};

  opendb(&err, &db, "test.db", 1);
  sql_script(&err, &db, 
      "PRAGMA page_size = 1024;"
      "PRAGMA journal_mode = wal2;"
      "CREATE TABLE t1(ii INTEGER PRIMARY KEY, tt TEXT);"
      "CREATE INDEX t1tt ON t1(tt);"
  );

  setstoptime(&err, nMs);

  launch_thread(&err, &threads, bcwal2_1_writer, 0);
  launch_thread(&err, &threads, bcwal2_1_writer, 0);
  launch_thread(&err, &threads, bcwal2_1_writer, 0);
  launch_thread(&err, &threads, bcwal2_1_integrity, 0);
  launch_thread(&err, &threads, bcwal2_1_checkpointer, 0);

  join_all_threads(&err, &threads);

  /* Do a final integrity-check on the db */
  integrity_check(&err, &db);
  closedb(&err, &db);

  print_and_free_err(&err);
}

Changes to test/tt3_checkpoint.c.

71
72
73
74
75
76
77
78

79
80
81
82
83
84
85
71
72
73
74
75
76
77

78
79
80
81
82
83
84
85







-
+







  Sqlite db = {0};

  opendb(&err, &db, "test.db", 0);
  while( !timetostop(&err) ){
    i64 iCount1, iCount2;
    sql_script(&err, &db, "BEGIN");
    iCount1 = execsql_i64(&err, &db, "SELECT count(x) FROM t1");
    usleep(CHECKPOINT_STARVATION_READMS*1000);
    sqlite3_sleep(CHECKPOINT_STARVATION_READMS);
    iCount2 = execsql_i64(&err, &db, "SELECT count(x) FROM t1");
    sql_script(&err, &db, "COMMIT");

    if( iCount1!=iCount2 ){
      test_error(&err, "Isolation failure - %lld %lld", iCount1, iCount2);
    }
  }
103
104
105
106
107
108
109
110

111
112
113
114
115
116
117
103
104
105
106
107
108
109

110
111
112
113
114
115
116
117







-
+







      "CREATE TABLE t1(x);"
  );

  setstoptime(&err, nMs);

  for(i=0; i<4; i++){
    launch_thread(&err, &threads, checkpoint_starvation_reader, 0);
    usleep(CHECKPOINT_STARVATION_READMS*1000/4);
    sqlite3_sleep(CHECKPOINT_STARVATION_READMS/4);
  }

  sqlite3_wal_hook(db.db, checkpoint_starvation_walhook, (void *)p);
  while( !timetostop(&err) ){
    sql_script(&err, &db, "INSERT INTO t1 VALUES(randomblob(1200))");
    nInsert++;
  }

Added test/tt3_shared.c.
























































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2020 September 5
**
** 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.
**
*************************************************************************
**
**
*/


/*
*/
static char *shared_thread1(int iTid, void *pArg){
  Error err = {0};                /* Error code and message */

  while( !timetostop(&err) ){
    Sqlite db = {0};              /* SQLite database connection */
    opendb(&err, &db, "test.db", 0);
    sql_script(&err, &db, "SELECT * FROM t1");
    closedb(&err, &db);
  }
  print_and_free_err(&err);
  return sqlite3_mprintf("done!");
}


static void shared1(int nMs){
  Error err = {0};
  Sqlite db = {0};              /* SQLite database connection */
  Threadset threads = {0};
  int ii;

  opendb(&err, &db, "test.db", 1);
  sql_script(&err, &db, "CREATE TABLE t1(x)");
  closedb(&err, &db);

  setstoptime(&err, nMs);
  sqlite3_enable_shared_cache(1);

  for(ii=0; ii<5; ii++){
    launch_thread(&err, &threads, shared_thread1, 0);
  }

  join_all_threads(&err, &threads);
  sqlite3_enable_shared_cache(0);

  print_and_free_err(&err);
}

Changes to test/tt3_stress.c.

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







-
+







** Thread 2. Open and close database connections.
*/
static char *stress_thread_2(int iTid, void *pArg){
  Error err = {0};                /* Error code and message */
  Sqlite db = {0};                /* SQLite database connection */
  while( !timetostop(&err) ){
    opendb(&err, &db, "test.db", 0);
    sql_script(&err, &db, "SELECT * FROM sqlite_master;");
    sql_script(&err, &db, "SELECT * FROM sqlite_schema;");
    clear_error(&err, SQLITE_LOCKED);
    closedb(&err, &db);
  }
  print_and_free_err(&err);
  return sqlite3_mprintf("ok");
}

262
263
264
265
266
267
268
269

270
271
272
273
274
275
276
262
263
264
265
266
267
268

269
270
271
272
273
274
275
276







-
+








static char *stress2_workload19(int iTid, void *pArg){
  Error err = {0};                /* Error code and message */
  Sqlite db = {0};                /* SQLite database connection */
  const char *zDb = (const char*)pArg;
  while( !timetostop(&err) ){
    opendb(&err, &db, zDb, 0);
    sql_script(&err, &db, "SELECT * FROM sqlite_master;");
    sql_script(&err, &db, "SELECT * FROM sqlite_schema;");
    clear_error(&err, SQLITE_LOCKED);
    closedb(&err, &db);
  }
  print_and_free_err(&err);
  return sqlite3_mprintf("ok");
}

358
359
360
361
362
363
364
365
366
367
368
358
359
360
361
362
363
364











-
-
-
-
  launch_thread(&err, &threads, stress2_workload19, (void*)zDb);
  launch_thread(&err, &threads, stress2_workload19, (void*)zDb);

  join_all_threads(&err, &threads);
  sqlite3_enable_shared_cache(0);
  print_and_free_err(&err);
}




Changes to test/tt3_vacuum.c.

19
20
21
22
23
24
25
26
27
28

29
30
31
32
33
34
35
19
20
21
22
23
24
25

26
27
28
29
30
31
32
33
34
35







-


+







**
*/


static char *vacuum1_thread_writer(int iTid, void *pArg){
  Error err = {0};                /* Error code and message */
  Sqlite db = {0};                /* SQLite database connection */
  opendb(&err, &db, "test.db", 0);
  i64 i = 0;

  opendb(&err, &db, "test.db", 0);
  while( !timetostop(&err) ){
    i++;

    /* Insert lots of rows. Then delete some. */
    execsql(&err, &db, 
        "WITH loop(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM loop WHERE i<100) "
        "INSERT INTO t1 SELECT randomblob(50), randomblob(2500) FROM loop"

Added test/unhex.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2023 January 23
#
# 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 [file join $testdir tester.tcl]

set testprefix unhex


foreach {tn hex} {
  1  0000
  2  FFFF
  3  0123456789ABCDEF
} {
  do_execsql_test 1.$tn.1 {
    SELECT hex( unhex( $hex ) );
  } $hex

  do_execsql_test 1.$tn.2 {
    SELECT hex( unhex( lower( $hex ) ) );
  } $hex
}

do_execsql_test 2.0 {
  SELECT typeof( unhex('') ), length( unhex('') );
} {blob 0}

foreach {tn hex} {
  1  ABC
  2  hello
  3  123456x7
  4  0xff
} {
  do_execsql_test 2.$tn {
    SELECT unhex( $hex ) IS NULL;
  } 1
}

do_catchsql_test 3.0 {
  SELECT unhex();
} {1 {wrong number of arguments to function unhex()}}
do_catchsql_test 3.1 {
  SELECT unhex('ABCD', '1234', '');
} {1 {wrong number of arguments to function unhex()}}

#--------------------------------------------------------------------------
# Test the 2-argument version.
#
foreach {tn hex} {
  1 "FFFF  ABCD"
  2 "FFFF ABCD"
  3 "FFFFABCD "
  4 " FFFFABCD"
  5 "--FFFF AB- -CD- "
  6 "--"
  7 " --"
} {
  set out ""
  foreach x [split $hex ""] {
    if {[string is xdigit $x]} { append out $x }
  }

  do_execsql_test 5.$tn.1 {
    SELECT hex( unhex($hex, ' -') );
  } [list $out]
}

do_execsql_test 6.0 {
  SELECT typeof( unhex(' ', ' -') ), length( unhex('-', ' -') );
} {blob 0}


do_execsql_test 6.1 "
  SELECT hex( unhex('\u0E01ABCD\u0E02', '\uE01\uE02') )
" {ABCD}
do_execsql_test 6.2 "
  SELECT typeof( unhex('\u0E01ABCD\u0E02', '\uE03\uE02') )
" {null}
do_execsql_test 6.3 "
  SELECT hex( unhex('\u0E01AB CD\uE02\uE01', '\uE01 \uE02') )
" {ABCD}

#--------------------------------------------------------------------------
# Test that if either argument is NULL, the returned value is also NULL.
#
do_execsql_test 6.4.1 { SELECT typeof(unhex(NULL)) } {null}
do_execsql_test 6.4.2 { SELECT typeof(unhex(NULL, ' ')) } {null}
do_execsql_test 6.4.3 { SELECT typeof(unhex('1234', NULL)) } {null}


finish_test


Added test/unionall.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2020-12-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.  The
# focus of this file is flattening UNION ALL sub-queries.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix unionall

do_execsql_test 1.0 {
  CREATE TABLE t1_a(a INTEGER PRIMARY KEY, b TEXT);
  CREATE TABLE t1_b(c INTEGER PRIMARY KEY, d TEXT);
  CREATE TABLE t1_c(e INTEGER PRIMARY KEY, f TEXT);

  INSERT INTO t1_a VALUES(1, 'one'), (4, 'four');
  INSERT INTO t1_b VALUES(2, 'two'), (5, 'five');
  INSERT INTO t1_c VALUES(3, 'three'), (6, 'six');

  CREATE VIEW t1 AS 
    SELECT a, b FROM t1_a   UNION ALL
    SELECT c, d FROM t1_b   UNION ALL
    SELECT e, f FROM t1_c;

  CREATE TABLE i1(x);
  INSERT INTO i1 VALUES(2), (5), (6), (1);
}

do_execsql_test 1.1 {
  SELECT a, b FROM (
    SELECT a, b FROM t1_a   UNION ALL
    SELECT c, d FROM t1_b   UNION ALL
    SELECT e, f FROM t1_c
  ) ORDER BY a
} {
  1 one 2 two 3 three 4 four 5 five 6 six
}

do_execsql_test 1.2 {
  SELECT a, b FROM t1 ORDER BY a
} {
  1 one 2 two 3 three 4 four 5 five 6 six
}

do_execsql_test 1.3 {
  SELECT a, b FROM i1, t1 WHERE a=x ORDER BY a
} {1 one 2 two 5 five 6 six}


# 2022-10-31 part of ticket 57c47526c34f01e8
# The queries below were causing an assertion fault in
# the comparison operators of the VDBE.
#
reset_db
database_never_corrupt
optimization_control db all 0
do_execsql_test 1.10 {
  CREATE TABLE t0(c0 INT);
  INSERT INTO t0 VALUES(0);
  CREATE TABLE t1_a(a INTEGER PRIMARY KEY, b TEXT);
  INSERT INTO t1_a VALUES(1,'one');
  CREATE TABLE t1_b(c INTEGER PRIMARY KEY, d TEXT);
  INSERT INTO t1_b VALUES(2,'two');
  CREATE VIEW t1 AS SELECT a, b FROM t1_a UNION ALL SELECT c, c FROM t1_b;
  SELECT * FROM (SELECT t1.a, t1.b AS b, t0.c0 FROM t0, t1);
} {1 one 0 2 2 0}
do_execsql_test 1.11 {
  SELECT * FROM (SELECT t1.a, t1.b AS b, t0.c0 FROM t0, t1) WHERE b=2;
} {2 2 0}

#-------------------------------------------------------------------------
reset_db

do_execsql_test 2.1.0 {
  CREATE TABLE t1(x, y);
  INSERT INTO t1 VALUES(1, 'one');
  INSERT INTO t1 VALUES(1, 'ONE');
  INSERT INTO t1 VALUES(2, 'two');
  INSERT INTO t1 VALUES(2, 'TWO');
  INSERT INTO t1 VALUES(3, 'three');
  INSERT INTO t1 VALUES(3, 'THREE');
}

do_execsql_test 2.1.1 {
  WITH s(i) AS (
      SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<3
  )
  SELECT * FROM (
    SELECT 0 AS i UNION ALL SELECT i FROM s UNION ALL SELECT 0
  ), t1 WHERE x=i;
} {
  1 1 one 1 1 ONE 2 2 two 2 2 TWO 3 3 three 3 3 THREE
}

do_catchsql_test 2.1.2 {
  WITH s(i) AS (
      SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<3 UNION ALL SELECT 4
  )
  SELECT * FROM s, t1 WHERE x=i;
} {1 {circular reference: s}}

do_execsql_test 2.2.0 {
  CREATE TABLE t2_a(k INTEGER PRIMARY KEY, v TEXT);
  CREATE TABLE t2_b(k INTEGER PRIMARY KEY, v TEXT);

  CREATE VIEW t2 AS 
    SELECT * FROM t2_a 
    UNION ALL 
    SELECT * FROM t2_b;

  CREATE TRIGGER t2_insert INSTEAD OF INSERT ON t2 BEGIN
    INSERT INTO t2_a SELECT new.k, new.v WHERE (new.k%2)==0;
    INSERT INTO t2_b SELECT new.k, new.v WHERE (new.k%2)==1;
  END;

  INSERT INTO t2 VALUES(5, 'v'), (4, 'iv'), (3, 'iii'), (2, 'ii');
}

do_execsql_test 2.2.1 {
  SELECT * FROM t1, t2 WHERE x=k;
} {
  2 two 2 ii 2 TWO 2 ii 3 three 3 iii 3 THREE 3 iii
}

do_execsql_test 2.2.2 {
  SELECT * FROM t1 LEFT JOIN t2 ON (x=k);
} {
  1 one {} {}
  1 ONE {} {}
  2 two 2 ii 2 TWO 2 ii 3 three 3 iii 3 THREE 3 iii
}

do_execsql_test 2.2.3 {
  SELECT x1.*, x2.* FROM t2 AS x1, t2 AS x2 WHERE x1.k=x2.k+1
} {
  4 iv   3 iii 
  3 iii  2 ii 
  5 v    4 iv
}

do_execsql_test 2.2.4 {
  SELECT * FROM t1, t2 WHERE x=k ORDER BY y;
} {
  3 THREE 3 iii 
  2 TWO 2 ii 
  3 three 3 iii 
  2 two 2 ii
}
do_execsql_test 2.2.5 {
  SELECT * FROM t1, t2 WHERE x=k ORDER BY y||'';
} {
  3 THREE 3 iii 
  2 TWO 2 ii 
  3 three 3 iii 
  2 two 2 ii
}
do_execsql_test 2.2.6 {
  SELECT * FROM t1, t2 WHERE x=k ORDER BY v
} {
  2 two   2 ii
  2 TWO   2 ii 
  3 three 3 iii 
  3 THREE 3 iii 
}
do_execsql_test 2.2.7 {
  SELECT * FROM t1, t2 WHERE x=k ORDER BY v||''
} {
  2 two   2 ii
  2 TWO   2 ii 
  3 three 3 iii 
  3 THREE 3 iii 
}
do_execsql_test 2.2.8 {
  SELECT * FROM t1, t2 WHERE x=k ORDER BY k,v||''
} {
  2 two   2 ii
  2 TWO   2 ii 
  3 three 3 iii 
  3 THREE 3 iii 
}
do_execsql_test 2.2.9a {
  SELECT * FROM t1, t2 ORDER BY +k
} {
  1 one 2 ii 1 ONE 2 ii 2 two 2 ii 
  2 TWO 2 ii 3 three 2 ii 3 THREE 2 ii 
  
  1 one 3 iii 1 ONE 3 iii 2 two 3 iii 
  2 TWO 3 iii 3 three 3 iii 3 THREE 3 iii 

  1 one 4 iv 1 ONE 4 iv 2 two 4 iv 
  2 TWO 4 iv 3 three 4 iv 3 THREE 4 iv 

  1 one 5 v 1 ONE 5 v 2 two 5 v 
  2 TWO 5 v 3 three 5 v 3 THREE 5 v
}

do_execsql_test 2.2.9b {
  SELECT * FROM t1, t2 ORDER BY k
} {
  1 one 2 ii 1 ONE 2 ii 2 two 2 ii 
  2 TWO 2 ii 3 three 2 ii 3 THREE 2 ii 
  
  1 one 3 iii 1 ONE 3 iii 2 two 3 iii 
  2 TWO 3 iii 3 three 3 iii 3 THREE 3 iii 

  1 one 4 iv 1 ONE 4 iv 2 two 4 iv 
  2 TWO 4 iv 3 three 4 iv 3 THREE 4 iv 

  1 one 5 v 1 ONE 5 v 2 two 5 v 
  2 TWO 5 v 3 three 5 v 3 THREE 5 v
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 3.0 {
  CREATE TABLE t1(c INTEGER PRIMARY KEY, d TEXT);
  INSERT INTO t1 VALUES(1,2);
  CREATE TABLE t3_a(k INTEGER PRIMARY KEY, v TEXT);
  INSERT INTO t3_a VALUES(2,'ii');
  CREATE TABLE t3_b(k INTEGER PRIMARY KEY, v TEXT);
  CREATE VIEW t3 AS
    SELECT * FROM t3_a
    UNION ALL
    SELECT * FROM t3_b;
} {}

do_execsql_test 3.1 {
  SELECT * FROM t1, t3 ORDER BY k;
} {1 2 2 ii}

reset_db
do_execsql_test 4.0 {

  CREATE TABLE t1_a(a INTEGER PRIMARY KEY, b TEXT);
  INSERT INTO t1_a VALUES(123, 't1_a');
  CREATE TABLE t1_b(c INTEGER PRIMARY KEY, d TEXT);

  CREATE VIEW t1 AS
    SELECT a, b FROM t1_a
    UNION ALL
    SELECT c, d FROM t1_b;

  CREATE TABLE t3_a(k INTEGER PRIMARY KEY, v TEXT);
  INSERT INTO t3_a VALUES(456, 't3_a');
  CREATE TABLE t3_b(k INTEGER PRIMARY KEY, v TEXT);

  CREATE VIEW t3 AS
    SELECT * FROM t3_a
    UNION ALL
    SELECT * FROM t3_b;
}

do_execsql_test 4.1 {
  SELECT * FROM t1, t3 ORDER BY k;
} {123 t1_a 456 t3_a}

do_execsql_test 4.2 {
  SELECT * FROM (SELECT * FROM t1, t3) ORDER BY k;
} {123 t1_a 456 t3_a}

do_execsql_test 4.3 {
  SELECT * FROM (SELECT * FROM t1, t3), (
    SELECT max(a) OVER () FROM t1
      UNION ALL
    SELECT min(a) OVER () FROM t1
  )
  ORDER BY k;
} {
  123 t1_a 456 t3_a 123
  123 t1_a 456 t3_a 123
}

do_execsql_test 4.3 {
  SELECT * FROM (SELECT * FROM t1, t3), (
    SELECT group_concat(a) OVER (ORDER BY a), 
           group_concat(a) OVER (ORDER BY a),
           group_concat(a) OVER (ORDER BY a),
           group_concat(a) OVER (ORDER BY a),
           group_concat(a) OVER (ORDER BY a),
           group_concat(a) OVER (ORDER BY a),
           group_concat(a) OVER (ORDER BY a),
           group_concat(a) OVER (ORDER BY a),
           group_concat(a) OVER (ORDER BY a)
    FROM t1
  )
  ORDER BY k;
} {
  123 t1_a 456 t3_a 123 123 123 123 123 123 123 123 123
}

do_execsql_test 4.3 {
  SELECT * FROM (SELECT * FROM t1, t3) AS o, (
    SELECT * FROM t1 LEFT JOIN t3 ON a=k
  );
} {
  123 t1_a 456 t3_a 123 t1_a {} {}
}

# 2020-12-30: dbsqlfuzz find
reset_db
do_execsql_test 5.1 {
  CREATE TABLE t1_a(a INTEGER PRIMARY KEY, b TEXT);
  INSERT INTO t1_a VALUES(1,'one');
  INSERT INTO t1_a VALUES(0,NULL);
  CREATE TABLE t1_b(c INTEGER PRIMARY KEY, d TEXT);
  INSERT INTO t1_b VALUES(2,'two');
  INSERT INTO t1_b VALUES(5,'five');
  CREATE TABLE t1_c(e INTEGER PRIMARY KEY, f TEXT);
  INSERT INTO t1_c VALUES(3,'three');
  INSERT INTO t1_c VALUES(6,'six');
  CREATE TABLE t2(k,v);
  INSERT INTO t2 VALUES(5,'v');
  INSERT INTO t2 VALUES(4,'iv');
  INSERT INTO t2 VALUES(3,'iii');
  INSERT INTO t2 VALUES(2,'ii');
  CREATE TABLE t3_a(k INTEGER PRIMARY KEY, v TEXT);
  INSERT INTO t3_a VALUES(2,'ii');
  INSERT INTO t3_a VALUES(4,'iv');
  CREATE TABLE t3_b(k INTEG5R PRIMARY KEY, v TEXT);
  INSERT INTO t3_b VALUES(NULL,'iii');
  INSERT INTO t3_b VALUES(NULL,'v');
  CREATE VIEW t1 AS 
    SELECT a, b FROM t1_a   UNION ALL
    SELECT c, d FROM t1_b   UNION ALL
    SELECT e, f FROM t1_c;
  CREATE VIEW t3 AS 
      SELECT * FROM t3_a 
      UNION ALL 
      SELECT * FROM t3_b;
  CREATE TRIGGER t3_insert INSTEAD OF INSERT ON t3 BEGIN
      INSERT INTO t3_a SELECT new.k, new.v WHERE (new.k%2)==0;
      INSERT INTO t3_b SELECT new.k, new.v WHERE (new.k%2)==1;
  END;
} {}
do_execsql_test 5.10 {
  SELECT *, '+' FROM t1 LEFT JOIN t2 ON (a NOT IN(SELECT v FROM t1, t3 WHERE a=k)=NOT EXISTS(SELECT 1 FROM t1 LEFT JOIN t3 ON (a=k)));
} {0 {} {} {} + 1 one {} {} + 2 two {} {} + 5 five {} {} + 3 three {} {} + 6 six {} {} +}
do_execsql_test 5.20 {
  SELECT *, '+' FROM t1 LEFT JOIN t3 ON (a NOT IN(SELECT v FROM t1 LEFT JOIN t2 ON (a=k))=k);
} {0 {} {} {} + 1 one {} {} + 2 two {} {} + 5 five {} {} + 3 three {} {} + 6 six {} {} +}

reset_db
do_execsql_test 6.0 {
  CREATE TABLE t1(a,b);
  INSERT INTO t1 VALUES(1,2);
  CREATE TABLE t2(a,b);
  INSERT INTO t2 VALUES(3,4);

  CREATE TABLE t3(a,b);
  INSERT INTO t3 VALUES(5,6);
  CREATE TABLE t4(a,b);
  INSERT INTO t4 VALUES(7,8);

  CREATE TABLE t5(a,b);
  INSERT INTO t5 VALUES(9,10);
}

do_execsql_test 6.1 {
  WITH x(c) AS (
    SELECT 1000 FROM t1 UNION ALL SELECT 800 FROM t2
  ),
  y(d) AS (
    SELECT  100 FROM t3 UNION ALL SELECT 400 FROM t4
  )
  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 |}

# 2022-10-31 ticket https://sqlite.org/src/info/57c47526c34f01e8
# dbsqlfuzz 37230460b46b3b6049f0d768eb801f3428189382
# UNION ALL subqueries or views which have arms with different
# affinities should not be flattened.
#
reset_db
do_execsql_test 8.1 {
  CREATE TABLE t0(c0 INT);
  INSERT INTO t0 VALUES(0);
  CREATE TABLE t1_a(a INTEGER PRIMARY KEY, b TEXT);
  INSERT INTO t1_a VALUES(1,'one');
  INSERT INTO t1_a VALUES(4,'four');
  CREATE TABLE t1_b(c INTEGER PRIMARY KEY, d TEXT);
  INSERT INTO t1_b VALUES(2,'two');
  INSERT INTO t1_b VALUES(5,'five');
  CREATE TABLE t1_c(e INTEGER PRIMARY KEY, f TEXT);
  INSERT INTO t1_c VALUES(3,'three');
  INSERT INTO t1_c VALUES(6,'six');
  CREATE VIEW v0(c0) AS SELECT CAST(t0.c0 AS INTEGER) FROM t0;
  CREATE VIEW t1 AS 
    SELECT a, b FROM t1_a   UNION ALL
    SELECT c, c FROM t1_b   UNION ALL
    SELECT e, f FROM t1_c;
  SELECT t1.a, t1.b, t0.c0 AS c, v0.c0 AS d FROM t0 LEFT JOIN v0 ON v0.c0>'0',t1;
} {1 one 0 {} 4 four 0 {} 2 2 0 {} 5 5 0 {} 3 three 0 {} 6 six 0 {}}

optimization_control db all 1
do_execsql_test 8.2 {
  SELECT * FROM (SELECT t1.a, t1.b, t0.c0 AS c, v0.c0 AS d FROM t0 LEFT JOIN v0 ON v0.c0>'0',t1) WHERE b=2;
} {2 2 0 {}}
do_execsql_test 8.3 {
  SELECT * FROM (SELECT t1.a, t1.b, t0.c0 AS c, v0.c0 AS d FROM t0 LEFT JOIN v0 ON v0.c0>'0',t1) WHERE b=2.0;
} {2 2 0 {}}
do_execsql_test 8.4 {
  SELECT * FROM (SELECT t1.a, t1.b, t0.c0 AS c, v0.c0 AS d FROM t0 LEFT JOIN v0 ON v0.c0>'0',t1) WHERE b='2';
} {}
optimization_control db query-flattener,push-down 0
do_execsql_test 8.5 {
  SELECT * FROM (SELECT t1.a, t1.b, t0.c0 AS c, v0.c0 AS d FROM t0 LEFT JOIN v0 ON v0.c0>'0',t1) WHERE b=2;
} {2 2 0 {}}
do_execsql_test 8.6 {
  SELECT * FROM (SELECT t1.a, t1.b, t0.c0 AS c, v0.c0 AS d FROM t0 LEFT JOIN v0 ON v0.c0>'0',t1) WHERE b=2.0;
} {2 2 0 {}}
do_execsql_test 8.7 {
  SELECT * FROM (SELECT t1.a, t1.b, t0.c0 AS c, v0.c0 AS d FROM t0 LEFT JOIN v0 ON v0.c0>'0',t1) WHERE b='2';
} {}
optimization_control db all 0
do_execsql_test 8.8 {
  SELECT * FROM (SELECT t1.a, t1.b, t0.c0 AS c, v0.c0 AS d FROM t0 LEFT JOIN v0 ON v0.c0>'0',t1) WHERE b=2;
} {2 2 0 {}}
do_execsql_test 8.9 {
  SELECT * FROM (SELECT t1.a, t1.b, t0.c0 AS c, v0.c0 AS d FROM t0 LEFT JOIN v0 ON v0.c0>'0',t1) WHERE b=2.0;
} {2 2 0 {}}
do_execsql_test 8.10 {
  SELECT * FROM (SELECT t1.a, t1.b, t0.c0 AS c, v0.c0 AS d FROM t0 LEFT JOIN v0 ON v0.c0>'0',t1) WHERE b='2';
} {}


finish_test

Added test/unionall2.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2020-12-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.  The
# focus of this file is flattening UNION ALL sub-queries.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix unionall2

do_execsql_test 1.0 {
  CREATE TABLE t1(a, b);
  CREATE TABLE t2(c, d);

  CREATE VIEW v1 AS SELECT * FROM t1, t2;
  CREATE VIEW v2 AS SELECT * FROM t1, t2;

  CREATE VIEW vA AS
    SELECT * FROM v1, (
      SELECT * FROM t1 LEFT JOIN t2 ON (a=c)
    )
    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

Added test/unionallfault.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2020-12-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.
#
#***********************************************************************
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix unionallfault

do_execsql_test 1.0 {
  CREATE TABLE t1(x,y,z);
  CREATE TABLE t3(x,y,z);
}
faultsim_save_and_close


do_faultsim_test 1 -faults oom-t* -prep {
  faultsim_restore_and_reopen
} -body {
  execsql {
    SELECT * FROM t1, (
      SELECT x FROM t1 UNION ALL SELECT y FROM t1
    ), t3
  }
} -test {
  faultsim_test_result {0 {}}
}

finish_test

Changes to test/unionvtab.test.

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
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







-
+




















-
+







do_execsql_test 4.3.3 {
  SELECT * FROM sl WHERE rowid<=-9223372036854775808
} {
  -9223372036854775808 one
}
do_execsql_test 4.3.4 {
  SELECT * FROM sl WHERE rowid<-9223372036854775808
} { }
} {}

do_execsql_test 4.4.1 {
  SELECT * FROM sl WHERE rowid<9223372036854775807
} {
  -9223372036854775808 one -9223372036854775807 two -9223372036854775806 three
   9223372036854775805 four 9223372036854775806 five
}
do_execsql_test 4.4.2 {
  SELECT * FROM sl WHERE rowid<=9223372036854775807
} {
  -9223372036854775808 one -9223372036854775807 two -9223372036854775806 three
   9223372036854775805 four 9223372036854775806 five 9223372036854775807 six
}
do_execsql_test 4.4.3 {
  SELECT * FROM sl WHERE rowid>=9223372036854775807
} {
  9223372036854775807 six
}
do_execsql_test 4.4.4 {
  SELECT * FROM sl WHERE rowid>9223372036854775807
} { }
} {}

#-------------------------------------------------------------------------
# More than 8 source tables.
#
do_execsql_test 5.0 {
  CREATE TABLE c0(one, two INTEGER PRIMARY KEY);
  CREATE TABLE c1(one, two INTEGER PRIMARY KEY);

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/update.test.

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
615
616
617
618
619
620
621
622










623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735







+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+











+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


} {1 {no such column: nosuchcol}}

} ;# ifcapable {trigger}

# Ticket [https://www.sqlite.org/src/tktview/43107840f1c02] on 2014-10-29
# An assertion fault on UPDATE
#
ifcapable altertable {
do_execsql_test update-15.1 {
  CREATE TABLE t15(a INTEGER PRIMARY KEY, b);
  INSERT INTO t15(a,b) VALUES(10,'abc'),(20,'def'),(30,'ghi');
  ALTER TABLE t15 ADD COLUMN c;
  CREATE INDEX t15c ON t15(c);
  INSERT INTO t15(a,b)
   VALUES(5,'zyx'),(15,'wvu'),(25,'tsr'),(35,'qpo');
  UPDATE t15 SET c=printf("y%d",a) WHERE c IS NULL;
  SELECT a,b,c,'|' FROM t15 ORDER BY a;
} {5 zyx y5 | 10 abc y10 | 15 wvu y15 | 20 def y20 | 25 tsr y25 | 30 ghi y30 | 35 qpo y35 |}
  do_execsql_test update-15.1 {
    CREATE TABLE t15(a INTEGER PRIMARY KEY, b);
    INSERT INTO t15(a,b) VALUES(10,'abc'),(20,'def'),(30,'ghi');
    ALTER TABLE t15 ADD COLUMN c;
    CREATE INDEX t15c ON t15(c);
    INSERT INTO t15(a,b)
      VALUES(5,'zyx'),(15,'wvu'),(25,'tsr'),(35,'qpo');
    UPDATE t15 SET c=printf('y%d',a) WHERE c IS NULL;
    SELECT a,b,c,'|' FROM t15 ORDER BY a;
  } {5 zyx y5 | 10 abc y10 | 15 wvu y15 | 20 def y20 | 25 tsr y25 | 30 ghi y30 | 35 qpo y35 |}
}

# Unreleased bug in UPDATE caused by the UPSERT changes.
# Found by OSSFuzz as soon as the UPSERT changes landed on trunk.
# Never released into the wild.  2018-04-19.
#
do_execsql_test update-16.1 {
  CREATE TABLE t16(a INTEGER PRIMARY KEY ON CONFLICT REPLACE, b UNIQUE);
  INSERT INTO t16(a,b) VALUES(1,2),(3,4),(5,6);
  UPDATE t16 SET a=a;
  SELECT * FROM t16 ORDER BY +a;
} {1 2 3 4 5 6}

# 2019-12-09 gramfuzz find
# If a partial index that does not reference any column of its table (which is you
# must admit is a very strange index, but one that is allowed) is used by an UPDATE
# statement, void the use of OP_DeferredSeek on the main loop, as the seek will not
# be resolved prior to the OP_Delete.
#
do_execsql_test update-17.10 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(x,y);
  INSERT INTO t1(x) VALUES(1);
  CREATE INDEX t1x1 ON t1(1) WHERE 3;
  UPDATE t1 SET x=2, y=3 WHERE 3;
  SELECT * FROM t1;
} {2 3}

# 2019-12-22 ticket 5ad2aa6921faa1ee
# Make a hard-copy of values that need to be run through OP_RealAffinity
# rather than a soft-copy.  This is not strictly necessary, but it avoids
# a memory-accounting assert().
#
reset_db
do_execsql_test update-18.10 {
  PRAGMA encoding = 'UTF16';
  CREATE TABLE t0(c0 REAL, c1);
  INSERT INTO t0(c0,c1) VALUES('xyz',11),('uvw',22);
  CREATE INDEX i0 ON t0(c1) WHERE c0 GLOB 3;
  CREATE INDEX i1 ON t0(c0,c1) WHERE typeof(c0)='text' AND typeof(c1)='integer';
  UPDATE t0 SET c1=345;
  SELECT * FROM t0;
} {xyz 345 uvw 345}

# 2019-12-22 ticket c62c5e58524b204d
# This is really the same underlying problem as 5ad2aa6921faa1ee
#
reset_db
do_execsql_test update-18.20 {
  PRAGMA encoding = 'utf16';
  CREATE TABLE t0(c0 TEXT);
  CREATE INDEX i0 ON t0(0 LIKE COALESCE(c0, 0));
  INSERT INTO t0(c0) VALUES (0), (0);
  SELECT * FROM t0;
} {0 0}

# 2019-12-28 assertion fault reported by Yongheng
# Similar to ticket ec8abb025e78f40c
# An UPDATE was reaching the OP_Delete after running OP_DeferredSeek
# without ever hitting an OP_Column. The enhanced solution is to
# fix OP_Delete so that it can do the seek itself.
#
reset_db
do_execsql_test update-19.10 {
  CREATE TABLE t1(
   a TEXT,
   b INTEGER PRIMARY KEY UNIQUE
  ); 
  INSERT INTO t1 VALUES(1,2);
  UPDATE t1 SET a = quote(b) WHERE b>=2;
  SELECT * FROM t1;
} {2 2}

# 2019-12-29 ticket https://www.sqlite.org/src/info/314cc133e5ada126
# REPLACE conflict resolution during an UPDATE causes a DELETE trigger 
# to fire.  If that DELETE trigger subsequently modifies the row
# being updated, bad things can happen.  Prevent this by prohibiting
# triggers from making changes to the table being updated while doing
# REPLACE conflict resolution on the UPDATE.
#
# See also tickets:
#   https://www.sqlite.org/src/info/c1e19e12046d23fe 2019-10-25
#   https://www.sqlite.org/src/info/a8a4847a2d96f5de 2019-10-16 
#
reset_db
do_execsql_test update-20.10 {
  PRAGMA recursive_triggers = true;
  CREATE TABLE t1(a UNIQUE ON CONFLICT REPLACE, b);
  INSERT INTO t1(a,b) VALUES(4,12),(9,13);
  CREATE INDEX i0 ON t1(b);
  CREATE TRIGGER tr0 DELETE ON t1 BEGIN
    UPDATE t1 SET b = a;
  END;
  PRAGMA integrity_check;
} {ok}
do_catchsql_test update-20.20 {
  UPDATE t1 SET a=0;
} {1 {constraint failed}}
do_execsql_test update-20.30 {
  PRAGMA integrity_check;
} {ok}

finish_test

Changes to test/update2.test.

211
212
213
214
215
216
217
















218
219
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


do_execsql_test 6.1 {
  UPDATE d1 SET a = a+2 WHERE a>0 OR b>0;
}

do_execsql_test 6.2 {
  SELECT * FROM d1;
} {3 2}

# 2019-01-22 Bug in UPDATE OR REPLACE discovered by the 
# Matt Denton's LPM fuzzer
#
do_execsql_test 7.100 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(x,y);
  CREATE UNIQUE INDEX t1x1 ON t1(x) WHERE x IS NOT NULL;
  INSERT INTO t1(x) VALUES(NULL),(NULL);
  CREATE INDEX t1x2 ON t1(y);
  SELECT quote(x), quote(y), '|' FROM t1;
} {NULL NULL | NULL NULL |}
do_execsql_test 7.110 {
  UPDATE OR REPLACE t1 SET x=1;
  SELECT quote(x), quote(y), '|' FROM t1;
} {1 NULL |}

finish_test

Added test/upfrom1.tcl.




















































































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2020 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.
#
#***********************************************************************
#

source [file join [file dirname $argv0] pg_common.tcl]

#=========================================================================

start_test upfrom1 "2020 April 22"

foreach {tn wo} {
  1 "WITHOUT ROWID"
  2 ""
} {
eval [string map [list %TN% $tn %WITHOUT_ROWID% $wo] {
execsql_test 1.%TN%.0 {
  DROP TABLE IF EXISTS t2;
  CREATE TABLE t2(a INTEGER PRIMARY KEY, b INTEGER, c INTEGER) %WITHOUT_ROWID%;
  INSERT INTO t2 VALUES(1, 2, 3);
  INSERT INTO t2 VALUES(4, 5, 6);
  INSERT INTO t2 VALUES(7, 8, 9);

  DROP TABLE IF EXISTS chng;
  CREATE TABLE chng(a INTEGER, b INTEGER, c INTEGER);
  INSERT INTO chng VALUES(1, 100, 1000);
  INSERT INTO chng VALUES(7, 700, 7000);
}

execsql_test 1.%TN%.1 {
  SELECT * FROM t2;
}

execsql_test 1.%TN%.2 {
  UPDATE t2 SET b = chng.b, c = chng.c FROM chng WHERE chng.a = t2.a;
  SELECT * FROM t2 ORDER BY a;
}

execsql_test 1.%TN%.3 {
  DELETE FROM t2;
  INSERT INTO t2 VALUES(1, 2, 3);
  INSERT INTO t2 VALUES(4, 5, 6);
  INSERT INTO t2 VALUES(7, 8, 9);
}

execsql_test 1.%TN%.4 {
  UPDATE t2 SET (b, c) = (SELECT b, c FROM chng WHERE a=t2.a) 
    WHERE a IN (SELECT a FROM chng);
  SELECT * FROM t2 ORDER BY a;
}

execsql_test 1.%TN%.5 {
  DROP TABLE IF EXISTS t3;
  CREATE TABLE t3(a INTEGER PRIMARY KEY, b INTEGER, c TEXT) %WITHOUT_ROWID%;
  INSERT INTO t3 VALUES(1, 1, 'one');
  INSERT INTO t3 VALUES(2, 2, 'two');
  INSERT INTO t3 VALUES(3, 3, 'three');

  DROP TABLE IF EXISTS t4;
  CREATE TABLE t4(x TEXT);
  INSERT INTO t4 VALUES('five');

  SELECT * FROM t3 ORDER BY a;
}

execsql_test 1.%TN%.6 {
  UPDATE t3 SET c=x FROM t4;
  SELECT * FROM t3 ORDER BY a;
}
}]}

execsql_test 2.1 {
  DROP TABLE IF EXISTS t5;
  DROP TABLE IF EXISTS m1;
  DROP TABLE IF EXISTS m2;
  CREATE TABLE t5(a INTEGER PRIMARY KEY, b TEXT, c TEXT);
  CREATE TABLE m1(x INTEGER PRIMARY KEY, y TEXT);
  CREATE TABLE m2(u INTEGER PRIMARY KEY, v TEXT);

  INSERT INTO t5 VALUES(1, 'one', 'ONE');
  INSERT INTO t5 VALUES(2, 'two', 'TWO');
  INSERT INTO t5 VALUES(3, 'three', 'THREE');
  INSERT INTO t5 VALUES(4, 'four', 'FOUR');

  INSERT INTO m1 VALUES(1, 'i');
  INSERT INTO m1 VALUES(2, 'ii');
  INSERT INTO m1 VALUES(3, 'iii');

  INSERT INTO m2 VALUES(1, 'I');
  INSERT INTO m2 VALUES(3, 'II');
  INSERT INTO m2 VALUES(4, 'III');
}

execsql_test 2.2 {
  UPDATE t5 SET b=y, c=v FROM m1 LEFT JOIN m2 ON (x=u) WHERE x=a;
  SELECT * FROM t5 ORDER BY a;
}

errorsql_test 2.3.1 {
  UPDATE t5 SET b=1 FROM t5;
}
errorsql_test 2.3.2 {
  UPDATE t5 AS apples SET b=1 FROM t5 AS apples;
}


finish_test

Added test/upfrom1.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
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2020 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.
#

####################################################
# DO NOT EDIT! THIS FILE IS AUTOMATICALLY GENERATED!
####################################################

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix upfrom1

do_execsql_test 1.1.0 {
  DROP TABLE IF EXISTS t2;
  CREATE TABLE t2(a INTEGER PRIMARY KEY, b INTEGER, c INTEGER) WITHOUT ROWID;
  INSERT INTO t2 VALUES(1, 2, 3);
  INSERT INTO t2 VALUES(4, 5, 6);
  INSERT INTO t2 VALUES(7, 8, 9);

  DROP TABLE IF EXISTS chng;
  CREATE TABLE chng(a INTEGER, b INTEGER, c INTEGER);
  INSERT INTO chng VALUES(1, 100, 1000);
  INSERT INTO chng VALUES(7, 700, 7000);
} {}

do_execsql_test 1.1.1 {
  SELECT * FROM t2;
} {1 2 3   4 5 6   7 8 9}

do_execsql_test 1.1.2 {
  UPDATE t2 SET b = chng.b, c = chng.c FROM chng WHERE chng.a = t2.a;
  SELECT * FROM t2 ORDER BY a;
} {1 100 1000   4 5 6   7 700 7000}

do_execsql_test 1.1.3 {
  DELETE FROM t2;
  INSERT INTO t2 VALUES(1, 2, 3);
  INSERT INTO t2 VALUES(4, 5, 6);
  INSERT INTO t2 VALUES(7, 8, 9);
} {}

do_execsql_test 1.1.4 {
  UPDATE t2 SET (b, c) = (SELECT b, c FROM chng WHERE a=t2.a) 
    WHERE a IN (SELECT a FROM chng);
  SELECT * FROM t2 ORDER BY a;
} {1 100 1000   4 5 6   7 700 7000}

do_execsql_test 1.1.5 {
  DROP TABLE IF EXISTS t3;
  CREATE TABLE t3(a INTEGER PRIMARY KEY, b INTEGER, c TEXT) WITHOUT ROWID;
  INSERT INTO t3 VALUES(1, 1, 'one');
  INSERT INTO t3 VALUES(2, 2, 'two');
  INSERT INTO t3 VALUES(3, 3, 'three');

  DROP TABLE IF EXISTS t4;
  CREATE TABLE t4(x TEXT);
  INSERT INTO t4 VALUES('five');

  SELECT * FROM t3 ORDER BY a;
} {1 1 one   2 2 two   3 3 three}

do_execsql_test 1.1.6 {
  UPDATE t3 SET c=x FROM t4;
  SELECT * FROM t3 ORDER BY a;
} {1 1 five   2 2 five   3 3 five}

do_execsql_test 1.2.0 {
  DROP TABLE IF EXISTS t2;
  CREATE TABLE t2(a INTEGER PRIMARY KEY, b INTEGER, c INTEGER) ;
  INSERT INTO t2 VALUES(1, 2, 3);
  INSERT INTO t2 VALUES(4, 5, 6);
  INSERT INTO t2 VALUES(7, 8, 9);

  DROP TABLE IF EXISTS chng;
  CREATE TABLE chng(a INTEGER, b INTEGER, c INTEGER);
  INSERT INTO chng VALUES(1, 100, 1000);
  INSERT INTO chng VALUES(7, 700, 7000);
} {}

do_execsql_test 1.2.1 {
  SELECT * FROM t2;
} {1 2 3   4 5 6   7 8 9}

do_execsql_test 1.2.2 {
  UPDATE t2 SET b = chng.b, c = chng.c FROM chng WHERE chng.a = t2.a;
  SELECT * FROM t2 ORDER BY a;
} {1 100 1000   4 5 6   7 700 7000}

do_execsql_test 1.2.3 {
  DELETE FROM t2;
  INSERT INTO t2 VALUES(1, 2, 3);
  INSERT INTO t2 VALUES(4, 5, 6);
  INSERT INTO t2 VALUES(7, 8, 9);
} {}

do_execsql_test 1.2.4 {
  UPDATE t2 SET (b, c) = (SELECT b, c FROM chng WHERE a=t2.a) 
    WHERE a IN (SELECT a FROM chng);
  SELECT * FROM t2 ORDER BY a;
} {1 100 1000   4 5 6   7 700 7000}

do_execsql_test 1.2.5 {
  DROP TABLE IF EXISTS t3;
  CREATE TABLE t3(a INTEGER PRIMARY KEY, b INTEGER, c TEXT) ;
  INSERT INTO t3 VALUES(1, 1, 'one');
  INSERT INTO t3 VALUES(2, 2, 'two');
  INSERT INTO t3 VALUES(3, 3, 'three');

  DROP TABLE IF EXISTS t4;
  CREATE TABLE t4(x TEXT);
  INSERT INTO t4 VALUES('five');

  SELECT * FROM t3 ORDER BY a;
} {1 1 one   2 2 two   3 3 three}

do_execsql_test 1.2.6 {
  UPDATE t3 SET c=x FROM t4;
  SELECT * FROM t3 ORDER BY a;
} {1 1 five   2 2 five   3 3 five}

do_execsql_test 2.1 {
  DROP TABLE IF EXISTS t5;
  DROP TABLE IF EXISTS m1;
  DROP TABLE IF EXISTS m2;
  CREATE TABLE t5(a INTEGER PRIMARY KEY, b TEXT, c TEXT);
  CREATE TABLE m1(x INTEGER PRIMARY KEY, y TEXT);
  CREATE TABLE m2(u INTEGER PRIMARY KEY, v TEXT);

  INSERT INTO t5 VALUES(1, 'one', 'ONE');
  INSERT INTO t5 VALUES(2, 'two', 'TWO');
  INSERT INTO t5 VALUES(3, 'three', 'THREE');
  INSERT INTO t5 VALUES(4, 'four', 'FOUR');

  INSERT INTO m1 VALUES(1, 'i');
  INSERT INTO m1 VALUES(2, 'ii');
  INSERT INTO m1 VALUES(3, 'iii');

  INSERT INTO m2 VALUES(1, 'I');
  INSERT INTO m2 VALUES(3, 'II');
  INSERT INTO m2 VALUES(4, 'III');
} {}

do_execsql_test 2.2 {
  UPDATE t5 SET b=y, c=v FROM m1 LEFT JOIN m2 ON (x=u) WHERE x=a;
  SELECT * FROM t5 ORDER BY a;
} {1 i I   2 ii {}   3 iii II   4 four FOUR}

# PG says ERROR:  table name "t5" specified more than once
do_test 2.3.1 { catch { execsql {
  UPDATE t5 SET b=1 FROM t5;
} } } 1

# PG says ERROR:  table name "apples" specified more than once
do_test 2.3.2 { catch { execsql {
  UPDATE t5 AS apples SET b=1 FROM t5 AS apples;
} } } 1

# Problem found by OSSFuzz on 2020-07-20
# https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=24282
#
reset_db
do_execsql_test 3.1 {
  CREATE TABLE t0(a);
  CREATE TABLE t1(b);
  UPDATE t1 SET b=sum(a) FROM t0;
  SELECT * FROM t0, t1;
} {}

# Problem described by forum post https://sqlite.org/forum/forumpost/a274248080
#
reset_db
do_execsql_test 4.1 {
  CREATE TABLE t1(x INT);  INSERT INTO t1 VALUES(1);
  CREATE TABLE t2(y INT);  INSERT INTO t2 VALUES(2);
  WITH t1 AS (SELECT y+100 AS x FROM t2) 
    UPDATE t1 SET x=(SELECT x FROM t1);
  SELECT x, y FROM t1, t2;
} {102 2}
do_execsql_test 4.2 {
  WITH t1 AS (SELECT y+100 AS x FROM t2)
    UPDATE t1 SET x=x+y FROM t2;
  SELECT x, y FROM t1, t2;
} {104 2}

# 2021-05-20
# Forum https://sqlite.org/forum/forumpost/339f487de5 by Yu Liang
# A bad assert()
#
reset_db
do_execsql_test 5.1 {
  CREATE TABLE t1(a);
  INSERT INTO t1(a) VALUES(5);
  CREATE VIEW t2 AS SELECT a FROM t1 UNION ALL SELECT a FROM t1;
  CREATE TABLE t3(b,c);
  INSERT INTO t3(b,c) VALUES(1,2);
  UPDATE t3 SET (c,b) = (SELECT 3,4) FROM t1, t2;
  SELECT * FROM t3;
} {4 3}


finish_test

Added test/upfrom2.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2020 April 29
#
# 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
set testprefix upfrom2

# Test cases:
#
#   1.*: Test that triggers are fired correctly for UPDATE FROM statements,
#        and only once for each row. Except for INSTEAD OF triggers on 
#        views - these are fired once for each row returned by the join, 
#        including duplicates.
#
#   2.*: Test adding ORDER BY and LIMIT clauses with UPDATE FROM statements.
#
#   5.*: Test that specifying the target table name or alias in the FROM
#        clause of an UPDATE statement is an error.
#

foreach {tn wo} {
  1 ""
  2 "WITHOUT ROWID"
} {
  reset_db

  eval [string map [list %WO% $wo %TN% $tn] {
  do_execsql_test 1.%TN%.0 {
    CREATE TABLE log(t TEXT);
    CREATE TABLE t1(x PRIMARY KEY, y, z UNIQUE) %WO%;
    CREATE INDEX t1y ON t1(y);

    INSERT INTO t1 VALUES(1, 'i',   'one');
    INSERT INTO t1 VALUES(2, 'ii',  'two');
    INSERT INTO t1 VALUES(3, 'iii', 'three');
    INSERT INTO t1 VALUES(4, 'iv',  'four');

    CREATE TRIGGER tr1 BEFORE UPDATE ON t1 BEGIN
      INSERT INTO log VALUES(old.z || '->' || new.z);
    END;
    CREATE TRIGGER tr2 AFTER UPDATE ON t1 BEGIN
      INSERT INTO log VALUES(old.y || '->' || new.y);
    END;
  }

  do_execsql_test 1.%TN%.1 {
    WITH data(k, v) AS (
      VALUES(3, 'thirty'), (1, 'ten')
    )
    UPDATE t1 SET z=v FROM data WHERE x=k;

    SELECT * FROM t1;
    SELECT * FROM log;
  } {
    1 i ten   2 ii two   3 iii thirty   4 iv four
    one->ten        i->i
    three->thirty   iii->iii
  }

  do_execsql_test 1.%TN%.2 {
    CREATE TABLE t2(a, b);
    CREATE TABLE t3(k, v);
  
    INSERT INTO t3 VALUES(5,   'v');
    INSERT INTO t3 VALUES(12, 'xii');
  
    INSERT INTO t2 VALUES(2, 12);
    INSERT INTO t2 VALUES(3, 5);
  
    DELETE FROM log;
    UPDATE t1 SET y=v FROM t2, t3 WHERE t1.x=t2.a AND t3.k=t2.b;
  
    SELECT * FROM t1;
    SELECT * FROM log;
  } {
    1 i ten   2 xii two   3 v thirty   4 iv four
    two->two         ii->xii
    thirty->thirty   iii->v
  }

  do_execsql_test 1.%TN%.3 {
    DELETE FROM log;
    WITH data(k, v) AS (
      VALUES(1, 'seven'), (1, 'eight'), (2, 'eleven'), (2, 'twelve')
    )
    UPDATE t1 SET z=v FROM data WHERE x=k;
  
    SELECT * FROM t1;
    SELECT * FROM log;
  } {
    1 i eight   2 xii twelve   3 v thirty   4 iv four
    ten->eight        i->i
    two->twelve       xii->xii
  }

  do_test 1.%TN%.4 { db changes } {2}

  do_execsql_test 1.%TN%.5 { 
    CREATE VIEW v1 AS SELECT * FROM t1;
    CREATE TRIGGER v1tr INSTEAD OF UPDATE ON v1 BEGIN
      UPDATE t1 SET y=new.y, z=new.z WHERE x=new.x;
    END;

    DELETE FROM log;
    WITH data(k, v) AS (
      VALUES(3, 'thirteen'), (3, 'fourteen'), (4, 'fifteen'), (4, 'sixteen')
    )
    UPDATE v1 SET z=v FROM data WHERE x=k;
  }

  do_execsql_test 1.%TN%.6 {
    SELECT * FROM v1;
    SELECT * FROM log;
  } {
    1 i eight   2 xii twelve   3 v fourteen   4 iv sixteen
    thirty->thirteen  v->v
    thirteen->fourteen  v->v
    four->fifteen  iv->iv
    fifteen->sixteen  iv->iv
  }

  #--------------------------------------------------------------

  do_execsql_test 1.%TN%.7 {
    CREATE TABLE o1(w, x, y, z UNIQUE, PRIMARY KEY(w, x)) %WO%;
    CREATE INDEX o1y ON t1(y);

    INSERT INTO o1 VALUES(0, 0, 'i', 'one');
    INSERT INTO o1 VALUES(0, 1, 'ii', 'two');
    INSERT INTO o1 VALUES(1, 0, 'iii', 'three');
    INSERT INTO o1 VALUES(1, 1, 'iv', 'four');

    CREATE TRIGGER tro1 BEFORE UPDATE ON o1 BEGIN
      INSERT INTO log VALUES(old.z || '->' || new.z);
    END;
    CREATE TRIGGER tro2 AFTER UPDATE ON o1 BEGIN
      INSERT INTO log VALUES(old.y || '->' || new.y);
    END;
  }

  do_execsql_test 1.%TN%.8 {
    DELETE FROM log;
    WITH data(k, v) AS (
      VALUES(3, 'thirty'), (1, 'ten')
    )
    UPDATE o1 SET z=v FROM data WHERE (1+x+w*2)=k;

    SELECT * FROM o1;
    SELECT * FROM log;
  } {
    0 0 i ten   0 1 ii two   1 0 iii thirty   1 1 iv four
    one->ten        i->i
    three->thirty   iii->iii
  }

  do_execsql_test 1.%TN%.9 {
    DELETE FROM log;
    UPDATE o1 SET y=v FROM t2, t3 WHERE (1+o1.w*2+o1.x)=t2.a AND t3.k=t2.b;
  
    SELECT * FROM o1;
    SELECT * FROM log;
  } {
    0 0 i ten   0 1 xii two   1 0 v thirty   1 1 iv four
    two->two         ii->xii
    thirty->thirty   iii->v
  }

  do_execsql_test 1.%TN%.10 {
    DELETE FROM log;
    WITH data(k, v) AS (
      VALUES(1, 'seven'), (1, 'eight'), (2, 'eleven'), (2, 'twelve')
    )
    UPDATE o1 SET z=v FROM data WHERE (1+w*2+x)=k;
  
    SELECT * FROM o1;
    SELECT * FROM log;
  } {
    0 0 i eight   0 1 xii twelve   1 0 v thirty   1 1 iv four
    ten->eight        i->i
    two->twelve       xii->xii
  }

  do_test 1.%TN%.11 { db changes } {2}

  do_execsql_test 1.%TN%.12 { 
    CREATE VIEW w1 AS SELECT * FROM o1;
    CREATE TRIGGER w1tr INSTEAD OF UPDATE ON w1 BEGIN
      UPDATE o1 SET y=new.y, z=new.z WHERE w=new.w AND x=new.x;
    END;

    DELETE FROM log;
    WITH data(k, v) AS (
      VALUES(3, 'thirteen'), (3, 'fourteen'), (4, 'fifteen'), (4, 'sixteen')
    )
    UPDATE w1 SET z=v FROM data WHERE (1+w*2+x)=k;
  }

  do_execsql_test 1.%TN%.13 {
    SELECT * FROM w1;
    SELECT * FROM log;
  } {
    0 0 i eight   0 1 xii twelve   1 0 v fourteen   1 1 iv sixteen
    thirty->thirteen  v->v
    thirteen->fourteen  v->v
    four->fifteen  iv->iv
    fifteen->sixteen  iv->iv
  }

}]
}

ifcapable update_delete_limit {
foreach {tn wo} {
  1 ""
  2 "WITHOUT ROWID"
} {
  reset_db

eval [string map [list %WO% $wo %TN% $tn] {
  do_execsql_test 2.%TN%.1 {
    CREATE TABLE x1(a INTEGER PRIMARY KEY, b) %WO%;
    INSERT INTO x1 VALUES
        (1, 'one'), (2, 'two'), (3, 'three'), (4, 'four'),
        (5, 'five'), (6, 'six'), (7, 'seven'), (8, 'eight');
  }

  do_execsql_test 2.%TN%.2 {
    CREATE TABLE data1(x, y);
    INSERT INTO data1 VALUES
    (1, 'eleven'), (1, 'twenty-one'), (2, 'twelve'), (2, 'twenty-two'),
    (3, 'thirteen'), (3, 'twenty-three'), (4, 'fourteen'), (4, 'twenty-four');
  }

  do_execsql_test 2.%TN%.3 {
    UPDATE x1 SET b=y FROM data1 WHERE a=x ORDER BY a LIMIT 3;
    SELECT * FROM x1;
  } {
    1 eleven 2 twelve 3 thirteen 4 four 5 five 6 six 7 seven 8 eight
  }

  do_execsql_test 2.%TN%.4 {
    UPDATE x1 SET b=b||y FROM data1 WHERE a=x ORDER BY b LIMIT 3;
    SELECT * FROM x1;
  } {
    1 eleveneleven 2 twelve 3 thirteenthirteen 4 fourfourteen 
    5 five 6 six 7 seven 8 eight
  }

  do_catchsql_test 2.%TN%.5 {
    UPDATE x1 SET b=b||b ORDER BY b;
  } {1 {ORDER BY without LIMIT on UPDATE}}
  do_catchsql_test 2.%TN%.6 {
    UPDATE x1 SET b=b||y FROM data1 WHERE a=x ORDER BY b;
  } {1 {ORDER BY without LIMIT on UPDATE}}

  #-----------------------------------------------------------------------

  do_execsql_test 2.%TN%.6 {
    DROP TABLE x1;
    CREATE TABLE x1(u, v, b, PRIMARY KEY(u, v)) %WO%;
    INSERT INTO x1 VALUES
        (0, 1, 'one'), (1, 0, 'two'), (1, 1, 'three'), (2, 0, 'four'),
        (2, 1, 'five'), (3, 0, 'six'), (3, 1, 'seven'), (4, 0, 'eight');
  }

  do_execsql_test 2.%TN%.7 {
    UPDATE x1 SET b=y FROM data1 WHERE (u*2+v)=x ORDER BY u, v LIMIT 3;
    SELECT * FROM x1;
  } {
    0 1 eleven 1 0 twelve 1 1 thirteen 2 0 four 
    2 1 five 3 0 six 3 1 seven 4 0 eight
  }

  do_execsql_test 2.%TN%.8 {
    UPDATE x1 SET b=b||y FROM data1 WHERE (u*2+v)=x ORDER BY b LIMIT 3;
    SELECT * FROM x1;
  } {
    0 1 eleveneleven 1 0 twelve 1 1 thirteenthirteen 2 0 fourfourteen 
    2 1 five  3 0 six 3 1 seven 4 0 eight
  }


}]
}}

reset_db
do_execsql_test 3.0 {
  CREATE TABLE data(x, y, z);
  CREATE VIEW t1 AS SELECT * FROM data;
  CREATE TRIGGER t1_insert INSTEAD OF INSERT ON t1 BEGIN
    INSERT INTO data VALUES(new.x, new.y, new.z);
  END;
  CREATE TRIGGER t1_update INSTEAD OF UPDATE ON t1 BEGIN
    INSERT INTO log VALUES(old.z || '->' || new.z);
  END;

  CREATE TABLE log(t TEXT);

  INSERT INTO t1 VALUES(1, 'i',   'one');
  INSERT INTO t1 VALUES(2, 'ii',  'two');
  INSERT INTO t1 VALUES(3, 'iii', 'three');
  INSERT INTO t1 VALUES(4, 'iv',  'four');
}

do_execsql_test 3.1 {
  WITH input(k, v) AS (
      VALUES(3, 'thirty'), (1, 'ten')
  )
  UPDATE t1 SET z=v FROM input WHERE x=k;
}

foreach {tn sql} {
  2 { 
    CREATE TABLE x1(a INT PRIMARY KEY, b, c) WITHOUT ROWID;
  }
  1 { 
    CREATE TABLE x1(a INTEGER PRIMARY KEY, b, c);
  }
  3 { 
    CREATE TABLE x1(a INT PRIMARY KEY, b, c);
  }
} {

  reset_db
  execsql $sql

  do_execsql_test 4.$tn.0 {
    INSERT INTO x1 VALUES(1, 1, 1);
    INSERT INTO x1 VALUES(2, 2, 2);
    INSERT INTO x1 VALUES(3, 3, 3);
    INSERT INTO x1 VALUES(4, 4, 4);
    INSERT INTO x1 VALUES(5, 5, 5);
    CREATE TABLE map(o, t);
    INSERT INTO map VALUES(3, 30), (4, 40), (1, 10);
  }

  do_execsql_test 4.$tn.1 {
    UPDATE x1 SET a=t FROM map WHERE a=o;
    SELECT * FROM x1 ORDER BY a;
  } {2 2 2   5 5 5   10 1 1  30 3 3  40 4 4}
}

reset_db
do_execsql_test 5.0 {
  CREATE TABLE x1(a, b, c);
  CREATE TABLE x2(a, b, c);
}

foreach {tn update nm} {
  1 "UPDATE x1 SET a=5 FROM x1" x1
  2 "UPDATE x1 AS grapes SET a=5 FROM x1 AS grapes" grapes
  3 "UPDATE x1 SET a=5 FROM x2, x1" x1
  4 "UPDATE x1 AS grapes SET a=5 FROM x2, x1 AS grapes" grapes
} {
  do_catchsql_test 5.$tn $update \
    "1 {target object/alias may not appear in FROM clause: $nm}"
}

#--------------------------------------------------------------------------
reset_db
do_execsql_test 6.0 {
  CREATE TABLE t1(a); 
}

do_execsql_test 6.1 {
  UPDATE t1 SET a = 1 FROM (
      SELECT * FROM t1
  )
} {}
do_execsql_test 6.2 {
  UPDATE t1 SET a = 1 FROM (
      SELECT * FROM t1 UNION ALL SELECT * FROM t1
  )
} {}

# 2022-03-21
# https://sqlite.org/forum/forumpost/929168fdd6
#
reset_db
do_execsql_test 7.0 {
  CREATE TABLE t1(a);
  INSERT INTO t1(a) VALUES(11),(22),(33),(44),(55);
  CREATE VIEW t2(b,c) AS SELECT a, COUNT(*) OVER () FROM t1;
  CREATE TABLE t3(x,y);
  CREATE TRIGGER t2r1 INSTEAD OF UPDATE ON t2 BEGIN
    INSERT INTO t3(x,y) VALUES(new.b,new.c);
  END;
  SELECT * FROM t2;
} {11 5 22 5 33 5 44 5 55 5}
do_execsql_test 7.1 {
  UPDATE t2 SET c=t1.a FROM t1 WHERE t2.b=t1.a;
  SELECT * FROM t3;
} {11 11 22 22 33 33 44 44 55 55}


finish_test

Added test/upfrom3.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2020 July 14
#
# 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
set testprefix upfrom3

# Test plan:
#
#   1.*: Test UPDATE ... FROM statements that modify IPK fields. And that
#        modify "INTEGER PRIMARY KEY" fields on WITHOUT ROWID tables.
#
#   2.*: Test UPDATE ... FROM statements that modify PK fields of WITHOUT
#        ROWID tables.
#
#   3.*: Test that UPDATE ... FROM statements are not confused if there
#        are multiple tables of the same name in attached databases.
#
#   4.*: Tests for UPDATE ... FROM statements and foreign keys.
#

foreach {tn wo} {
  1 ""
  2 "WITHOUT ROWID"
} {
  reset_db
  eval [string map [list %WO% $wo %TN% $tn] {

  do_execsql_test 1.%TN%.0 {
    CREATE TABLE log(t TEXT);
    CREATE TABLE t1(x INTEGER PRIMARY KEY, y, z UNIQUE) %WO%;
    CREATE INDEX t1y ON t1(y);

    INSERT INTO t1 VALUES(1, 'i',   'one');
    INSERT INTO t1 VALUES(2, 'ii',  'two');
    INSERT INTO t1 VALUES(3, 'iii', 'three');
    INSERT INTO t1 VALUES(4, 'iv',  'four');
  }

  do_execsql_test 1.%TN%.1 {
    CREATE TABLE x1(o, n);
    INSERT INTO x1 VALUES(1, 11);
    INSERT INTO x1 VALUES(2, 12);
    INSERT INTO x1 VALUES(3, 13);
    INSERT INTO x1 VALUES(4, 14);
    UPDATE t1 SET x=n FROM x1 WHERE x=o;
    SELECT x, y, z FROM t1 ORDER BY 1;
  } {
    11 i one
    12 ii two
    13 iii three
    14 iv four
  }

  do_test 1.%TN%.2 { db changes } 4

  do_execsql_test 1.%TN%.3 {
    INSERT INTO x1 VALUES(11, 21);
    INSERT INTO x1 VALUES(12, 22);
    INSERT INTO x1 VALUES(13, 23);
    INSERT INTO x1 VALUES(14, 24);

    INSERT INTO x1 VALUES(21, 31);
    INSERT INTO x1 VALUES(22, 32);
    INSERT INTO x1 VALUES(23, 33);
    INSERT INTO x1 VALUES(24, 34);
    UPDATE t1 SET x=n FROM x1 WHERE x=o;
    SELECT x, y, z FROM t1 ORDER BY 1;
  } {
    21 i one
    22 ii two
    23 iii three
    24 iv four
  }

  do_execsql_test 1.%TN%.4 {
    UPDATE t1 SET x=n FROM x1 WHERE x=o;
    SELECT x, y, z FROM t1 ORDER BY 1;
  } {
    31 i one
    32 ii two
    33 iii three
    34 iv four
  }

  do_execsql_test 1.%TN%.5 {
    INSERT INTO x1 VALUES(31, 32);
    INSERT INTO x1 VALUES(33, 34);
    UPDATE OR REPLACE t1 SET x=n FROM x1 WHERE x=o;
    SELECT x, y, z FROM t1 ORDER BY 1;
  } {
    32 i one
    34 iii three
  }

  do_execsql_test 1.%TN%.6 {
    INSERT INTO t1 VALUES(33, 'ii', 'two');
    INSERT INTO t1 VALUES(35, 'iv', 'four');
  }

  do_execsql_test 1.%TN%.7 {
    CREATE TABLE x2(o, n, zz);
    INSERT INTO x2 VALUES(32, 41, 'four');
    INSERT INTO x2 VALUES(33, 42, 'three');
    UPDATE OR IGNORE t1 SET x=n, z=zz FROM x2 WHERE x=o;
    SELECT x, y, z FROM t1 ORDER BY 1;
  } {
    32 i one 
    33 ii two 
    34 iii three 
    35 iv four
  }

  do_execsql_test 1.%TN%.8 {
    UPDATE OR REPLACE t1 SET x=n, z=zz FROM x2 WHERE x=o;
    SELECT x, y, z FROM t1 ORDER BY 1;
  } {
    41 i four
    42 ii three
  }

  }]
}

do_execsql_test 2.1.1 {
  CREATE TABLE u1(a, b, c, PRIMARY KEY(b, c)) WITHOUT ROWID;
  INSERT INTO u1 VALUES(0, 0, 0);
  INSERT INTO u1 VALUES(1, 0, 1);
  INSERT INTO u1 VALUES(2, 1, 0);
  INSERT INTO u1 VALUES(3, 1, 1);
}

do_execsql_test 2.1.2 {
  CREATE TABLE map(f, t);
  INSERT INTO map VALUES(0, 10);
  INSERT INTO map VALUES(1, 11);
  UPDATE u1 SET c=t FROM map WHERE c=f;
  SELECT * FROM u1 ORDER BY a;
} {
  0 0 10
  1 0 11
  2 1 10
  3 1 11
}

do_execsql_test 2.1.3 {
  UPDATE u1 SET b=t FROM map WHERE b=f;
  SELECT * FROM u1 ORDER BY a;
} {
  0 10 10
  1 10 11
  2 11 10
  3 11 11
}

do_execsql_test 2.1.4 {
  CREATE TABLE map2(o1, o2, n1, n2);
  INSERT INTO map2 VALUES
    (10, 10, 50, 50), (10, 11, 50, 60), 
    (11, 10, 60, 50), (11, 11, 60, 60);
  UPDATE u1 SET b=n1, c=n2 FROM map2 WHERE b=o1 AND c=o2;
  SELECT * FROM u1 ORDER BY a;
} {
  0 50 50
  1 50 60
  2 60 50
  3 60 60
}

#-------------------------------------------------------------------------
foreach {tn wo} {
  1 ""
  2 "WITHOUT ROWID"
} {
  reset_db
  forcedelete test.db2
  eval [string map [list %WO% $wo %TN% $tn] {
    do_execsql_test 3.$tn.1 {
      CREATE TABLE g1(a, b, c, PRIMARY KEY(a, b)) %WO%;
      INSERT INTO g1 VALUES(1, 1, 1);

      ATTACH 'test.db2' AS aux;
      CREATE TABLE aux.g1(a, b, c, PRIMARY KEY(a, b)) %WO%;
      INSERT INTO aux.g1 VALUES(10, 1, 10);
      INSERT INTO aux.g1 VALUES(20, 2, 20);
      INSERT INTO aux.g1 VALUES(30, 3, 30);
    }

    do_execsql_test 3.$tn.2 {
      UPDATE aux.g1 SET c=101 FROM main.g1;
    }
    do_execsql_test 3.$tn.3 {
      SELECT * FROM aux.g1;
    } {10 1 101  20 2 101  30 3 101}

    do_execsql_test 3.$tn.4 {
      UPDATE g1 SET c=101 FROM g1 AS g2;
    }
    do_execsql_test 3.$tn.5 {
      SELECT * FROM g1;
    } {1 1 101}
  }]
}

#-------------------------------------------------------------------------
reset_db
foreach {tn wo} {
  1 ""
  2 "WITHOUT ROWID"
} {
  reset_db
  forcedelete test.db2
  eval [string map [list %WO% $wo %TN% $tn] {

    do_execsql_test 4.$tn.1 {
      CREATE TABLE p1(a INTEGER PRIMARY KEY, b) %WO%;
      CREATE TABLE c1(x PRIMARY KEY, y REFERENCES p1 ON UPDATE CASCADE) %WO%;
      PRAGMA foreign_keys = 1;

      INSERT INTO p1 VALUES(1, 'one');
      INSERT INTO p1 VALUES(11, 'eleven');
      INSERT INTO p1 VALUES(111, 'eleventyone');

      INSERT INTO c1 VALUES('a', 1);
      INSERT INTO c1 VALUES('b', 11);
      INSERT INTO c1 VALUES('c', 111);
    }

    do_execsql_test 4.$tn.2 {
      CREATE TABLE map(f, t);
      INSERT INTO map VALUES('a', 111);
      INSERT INTO map VALUES('c', 112);
    }

    do_catchsql_test 4.$tn.3 {
      UPDATE c1 SET y=t FROM map WHERE x=f;
    } {1 {FOREIGN KEY constraint failed}}

    do_execsql_test 4.$tn.4 {
      INSERT INTO map VALUES('eleven', 12);
      INSERT INTO map VALUES('eleventyone', 112);
      UPDATE p1 SET a=t FROM map WHERE b=f;
    }

    do_execsql_test 4.$tn.5 {
      SELECT * FROM c1
    } {a 1  b 12  c 112}

  }]
}

finish_test

Added test/upfrom4.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022-05-24
#
# 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
set testprefix upfrom4

do_execsql_test 100 {
  DROP TABLE IF EXISTS t5;
  DROP TABLE IF EXISTS m1;
  DROP TABLE IF EXISTS m2;
  CREATE TABLE t5(a INTEGER PRIMARY KEY, b TEXT, c TEXT);
  CREATE TABLE m1(x INTEGER PRIMARY KEY, y TEXT);
  CREATE TABLE m2(u INTEGER PRIMARY KEY, v TEXT);

  INSERT INTO t5 VALUES(1, 'one', 'ONE');
  INSERT INTO t5 VALUES(2, 'two', 'TWO');
  INSERT INTO t5 VALUES(3, 'three', 'THREE');
  INSERT INTO t5 VALUES(4, 'four', 'FOUR');

  INSERT INTO m1 VALUES(1, 'i');
  INSERT INTO m1 VALUES(2, 'ii');
  INSERT INTO m1 VALUES(3, 'iii');

  INSERT INTO m2 VALUES(1, 'I');
  INSERT INTO m2 VALUES(3, 'II');
  INSERT INTO m2 VALUES(4, 'III');
  SELECT * FROM t5;
} {1 one ONE 2 two TWO 3 three THREE 4 four FOUR}

do_execsql_test 110 {
  BEGIN;
  UPDATE t5 SET b=y, c=v FROM m1 LEFT JOIN m2 ON (x=u) WHERE x=a;
  SELECT * FROM t5 ORDER BY a;
  ROLLBACK;
} {1 i I 2 ii {} 3 iii II 4 four FOUR}

do_execsql_test 120 {
  BEGIN;
  UPDATE t5 SET b=y, c=v FROM m2 RIGHT JOIN m1 ON (x=u) WHERE x=a;
  SELECT * FROM t5 ORDER BY a;
  ROLLBACK;
} {1 i I 2 ii {} 3 iii II 4 four FOUR}


reset_db
db null -
do_execsql_test 200 {
  CREATE TABLE t1(a INT PRIMARY KEY, b INT, c INT);
  INSERT INTO t1(a) VALUES(1),(2),(8),(19);
  CREATE TABLE c1(x INTEGER PRIMARY KEY, b INT);
  INSERT INTO c1(x,b) VALUES(1,1),(8,8),(17,17),(NULL,NULL);
  CREATE TABLE c2(x INT,c INT);
  INSERT INTO c2(x,c) VALUES(2,2),(8,8),(NULL,NULL);
  CREATE TABLE dual(dummy TEXT);
  INSERT INTO dual VALUES('X');
} {}
do_execsql_test 210 {
  BEGIN;
  SELECT * FROM t1 ORDER BY a;
  UPDATE t1 SET b=c1.b, c=c2.c
    FROM dual, c1 NATURAL RIGHT JOIN c2
   WHERE x=a;
  SELECT * FROM t1 ORDER BY a;
  ROLLBACK;
} {
  1  -  -
  2  -  -
  8  -  -
  19 -  -
  1  -  -
  2  -  2
  8  8  8
  19 -  -
}
do_execsql_test 300 {
  CREATE TABLE t2(x);
  CREATE TRIGGER AFTER INSERT ON t2 BEGIN
    UPDATE t1 SET b=c1.b, c=c2.c
      FROM dual, c1 NATURAL RIGHT JOIN c2
     WHERE x=a;
  END;
} {}
do_execsql_test 310 {
  BEGIN;
  SELECT * FROM t1 ORDER BY a;
  INSERT INTO t2(x) VALUES(1);
  SELECT * FROM t1 ORDER BY a;
  ROLLBACK;
} {
  1  -  -
  2  -  -
  8  -  -
  19 -  -
  1  -  -
  2  -  2
  8  8  8
  19 -  -
}

# 2022-05-26 dbsqlfuzz crash-9401d6ba699f1257d352a657de236286bf2b14da
#
reset_db
db null -
do_execsql_test 400 {
  CREATE TABLE t2(x,y,z PRIMARY KEY) WITHOUT ROWID;
  INSERT INTO t2 VALUES(89,-89,6);
  CREATE TABLE t1(a INT,b TEXT,c TEXT,d REAL) STRICT;
  INSERT INTO t1 VALUES(1,'xyz','def',4.5);
  CREATE TRIGGER t1tr BEFORE UPDATE ON t1 BEGIN
    INSERT INTO t1(a,b) VALUES(1000,'uvw');
    UPDATE t1 SET b=NULL FROM (SELECT CAST(a AS varchar) FROM t1 ORDER BY b) NATURAL LEFT FULL JOIN t1 AS text;
  END;
  UPDATE t1 SET b=b|100;
  SELECT * FROM t1 ORDER BY a;
} {
  1    100  def 4.5
  1000 -    -   -
}

finish_test

Added test/upfromfault.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2020 April 29
#
# 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
set testprefix upfromfault

foreach {tn sql} {
  1 {
    CREATE TABLE t1(x PRIMARY KEY, y, z UNIQUE);
    CREATE INDEX t1y ON t1(y);
  }
  2 {
    CREATE TABLE t1(x PRIMARY KEY, y, z UNIQUE) WITHOUT ROWID;
    CREATE INDEX t1y ON t1(y);
  }
  3 {
    CREATE TABLE t1(x, y, z UNIQUE, PRIMARY KEY(x,y)) WITHOUT ROWID;
  }
  4 {
    CREATE VIRTUAL TABLE t1 USING fts5(x, y, z);
  }
  5 {
    CREATE TABLE real(x, y, z);
    CREATE VIEW t1 AS SELECT * FROM real;
    CREATE TRIGGER t1_insert INSTEAD OF INSERT ON t1 BEGIN
      INSERT INTO real VALUES(new.x, new.y, new.z);
    END;
    CREATE TRIGGER t1_update INSTEAD OF UPDATE ON t1 BEGIN
      INSERT INTO log VALUES(old.z || '->' || new.z);
      UPDATE real SET y=new.y, z=new.z WHERE x=old.x;
    END;
  }
} {
if {$tn<5} continue
  reset_db

  ifcapable !fts5 { if {$tn==4} continue }

  execsql $sql
  do_execsql_test 1.$tn.0 {
    CREATE TABLE log(t TEXT);

    INSERT INTO t1 VALUES(1, 'i',   'one');
    INSERT INTO t1 VALUES(2, 'ii',  'two');
    INSERT INTO t1 VALUES(3, 'iii', 'three');
    INSERT INTO t1 VALUES(4, 'iv',  'four');
  }
  if {$tn!=4 && $tn!=5} {
    do_execsql_test 1.$tn.0b {
      CREATE TRIGGER tr1 BEFORE UPDATE ON t1 BEGIN
        INSERT INTO log VALUES(old.z || '->' || new.z);
      END;
      CREATE TRIGGER tr2 AFTER UPDATE ON t1 BEGIN
        INSERT INTO log VALUES(old.y || '->' || new.y);
      END;
    }
  }
  
  faultsim_save_and_close

  do_faultsim_test 1.$tn -prep {
    faultsim_restore_and_reopen
    execsql { SELECT * FROM t1 }
  } -body {
    execsql {
      WITH data(k, v) AS (
          VALUES(3, 'thirty'), (1, 'ten')
      )
      UPDATE t1 SET z=v FROM data WHERE x=k;
    }
  } -test {
    faultsim_test_result {0 {}} {1 {vtable constructor failed: t1}}
    if {$testrc==0} {
      set res [execsql { SELECT * FROM t1 }]
      if {$res!="1 i ten 2 ii two 3 iii thirty 4 iv four"} {
        error "unexpected result: $res"
      }
    }
  }
}

reset_db
do_execsql_test 2.0 {
  CREATE TABLE t1(a, b, c);
  CREATE TABLE t2(x, y, z);
}
faultsim_save_and_close
do_faultsim_test 2.1 -prep {
  faultsim_restore_and_reopen
} -body {
  execsql {
    CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
      UPDATE t2 SET x=a FROM t1 WHERE c=z;
    END;
  }
} -test {
    faultsim_test_result {0 {}}
}

faultsim_restore_and_reopen
do_execsql_test 2.2 {
  CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
    UPDATE t1 SET a=x FROM t2 WHERE c=z;
  END;

  INSERT INTO t2 VALUES(1, 1, 1);
  INSERT INTO t2 VALUES(2, 2, 2);
  INSERT INTO t2 VALUES(3, 3, 3);
} 
faultsim_save_and_close

do_faultsim_test 2.3 -prep {
  faultsim_restore_and_reopen
} -body {
  execsql {
    INSERT INTO t1 VALUES(NULL, NULL, 1), (NULL, NULL, 3);
  }
} -test {
  faultsim_test_result {0 {}}
  if {$testrc==0} {
    set res [execsql { SELECT * FROM t1 }]
    if {$res!="1 {} 1 3 {} 3"} {
      error "unexpected result: $res"
    }
  }
}


finish_test

Changes to test/upsert1.test.

206
207
208
209
210
211
212












































213
214
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


  DELETE FROM t1;
  INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
  INSERT INTO t1(a,b,c,d,e) VALUES(1,2,33,44,5)
    ON CONFLICT(b) DO UPDATE SET c=excluded.c;
  SELECT * FROM t1;
} {1 2 33 4 5}

# 2019-08-30 ticket https://sqlite.org/src/info/5a3dba8104421320
do_execsql_test upsert1-800 {
  DROP TABLE IF EXISTS t0;
  CREATE TABLE t0(c0 REAL UNIQUE, c1);
  CREATE UNIQUE INDEX test800i0 ON t0(0 || c1);
  INSERT INTO t0(c0, c1) VALUES (1, 2),  (2, 1);
  INSERT INTO t0(c0) VALUES (1) ON CONFLICT(c0) DO UPDATE SET c1=excluded.c0;
  PRAGMA integrity_check;
  REINDEX;
} {ok}

# 2019-12-06 gramfuzz find
sqlite3 db :memory:
do_execsql_test upsert1-900 {
  CREATE VIEW t1(a) AS SELECT 1;
  CREATE TRIGGER t1r1 INSTEAD OF INSERT ON t1 BEGIN
     SELECT 2;
  END;
}
do_catchsql_test upsert1-910 {
  INSERT INTO t1 VALUES(3) ON CONFLICT(x) DO NOTHING;
} {1 {cannot UPSERT a view}}

# 2019-12-26 ticket 7c13db5c3bf74001
reset_db
do_catchsql_test upsert1-1000 {
  CREATE TABLE t0(c0 PRIMARY KEY, c1, c2 UNIQUE) WITHOUT ROWID;
  INSERT OR FAIL INTO t0(c2) VALUES (0), (NULL)
    ON CONFLICT(c2) DO UPDATE SET c1 = c0;
} {1 {NOT NULL constraint failed: t0.c0}}

# 2021-12-29 forum post https://sqlite.org/forum/forumpost/06b16b8b29f8c8c3
# By Jingzhou Fu. When there is both an INTEGER PRIMARY KEY ON CONFLICT REPLACE
# and an upsert on a constraint other than the INTEGER PRIMARY KEY, the
# constraint checking logic generates invalid bytecode which might result
# in a NULL pointer dereference.
#
reset_db
do_execsql_test upsert1-1100 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT REPLACE, b UNIQUE);
  INSERT INTO t1(b) VALUES(22);
  INSERT INTO t1 VALUES(2,22) ON CONFLICT (b) DO NOTHING;
  SELECT * FROM t1;
} {1 22}

finish_test

Changes to test/upsert2.test.

68
69
70
71
72
73
74
75

76
77
78
79
80
81
82
83

84
85
86
87
88
89
90
68
69
70
71
72
73
74

75
76
77
78
79
80
81
82

83
84
85
86
87
88
89
90







-
+







-
+







#
do_execsql_test upsert2-300 {
  DROP TABLE t1;
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b int, c DEFAULT 0);
  CREATE TABLE record(x TEXT, y TEXT);
  CREATE TRIGGER r1 BEFORE INSERT ON t1 BEGIN
    INSERT INTO record(x,y)
        VALUES('before-insert',printf('%d,%d,%d',new.a,new.b,new.c));
        VALUES('before-insert',format('%d,%d,%d',new.a,new.b,new.c));
  END;
  CREATE TRIGGER r2 AFTER INSERT ON t1 BEGIN
    INSERT INTO record(x,y)
        VALUES('after-insert',printf('%d,%d,%d',new.a,new.b,new.c));
  END;
  CREATE TRIGGER r3 BEFORE UPDATE ON t1 BEGIN
    INSERT INTO record(x,y)
        VALUES('before-update',printf('%d,%d,%d/%d,%d,%d',
        VALUES('before-update',format('%d,%d,%d/%d,%d,%d',
                                      old.a,old.b,old.c,new.a,new.b,new.c));
  END;
  CREATE TRIGGER r4 AFTER UPDATE ON t1 BEGIN
    INSERT INTO record(x,y)
        VALUES('after-update',printf('%d,%d,%d/%d,%d,%d',
                                      old.a,old.b,old.c,new.a,new.b,new.c));
  END;
119
120
121
122
123
124
125
126

127
128
129
130
131
132
133
134

135
136
137
138
139
140
141
119
120
121
122
123
124
125

126
127
128
129
130
131
132
133

134
135
136
137
138
139
140
141







-
+







-
+







# Trigger tests repeated for a WITHOUT ROWID table.
#
do_execsql_test upsert2-400 {
  DROP TABLE t1;
  CREATE TABLE t1(a INT PRIMARY KEY, b int, c DEFAULT 0) WITHOUT ROWID;
  CREATE TRIGGER r1 BEFORE INSERT ON t1 BEGIN
    INSERT INTO record(x,y)
        VALUES('before-insert',printf('%d,%d,%d',new.a,new.b,new.c));
        VALUES('before-insert',format('%d,%d,%d',new.a,new.b,new.c));
  END;
  CREATE TRIGGER r2 AFTER INSERT ON t1 BEGIN
    INSERT INTO record(x,y)
        VALUES('after-insert',printf('%d,%d,%d',new.a,new.b,new.c));
  END;
  CREATE TRIGGER r3 BEFORE UPDATE ON t1 BEGIN
    INSERT INTO record(x,y)
        VALUES('before-update',printf('%d,%d,%d/%d,%d,%d',
        VALUES('before-update',format('%d,%d,%d/%d,%d,%d',
                                      old.a,old.b,old.c,new.a,new.b,new.c));
  END;
  CREATE TRIGGER r4 AFTER UPDATE ON t1 BEGIN
    INSERT INTO record(x,y)
        VALUES('after-update',printf('%d,%d,%d/%d,%d,%d',
                                      old.a,old.b,old.c,new.a,new.b,new.c));
  END;

Added test/upsert5.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2020-12-11
#
# 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.
#
#***********************************************************************
#
# Test cases for generalized UPSERT

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix upsert5

foreach {tn sql} {
  1 { CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c UNIQUE, d UNIQUE, e UNIQUE) }
  2 { CREATE TABLE t1(a INT PRIMARY KEY, b, c UNIQUE, d UNIQUE, e UNIQUE) }
  3 { CREATE TABLE t1(a INT PRIMARY KEY, b, c UNIQUE, d UNIQUE, e UNIQUE) WITHOUT ROWID}
  4 { CREATE TABLE t1(e UNIQUE, d UNIQUE, c UNIQUE, a INTEGER PRIMARY KEY, b) }
  5 { CREATE TABLE t1(e UNIQUE, d UNIQUE, c UNIQUE, a INT PRIMARY KEY, b) }
  6 { CREATE TABLE t1(e UNIQUE, d UNIQUE, c UNIQUE, a INT PRIMARY KEY, b) WITHOUT ROWID}
} {
  reset_db
  execsql $sql

  do_execsql_test 1.$tn.100 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,3,4,5)
      ON CONFLICT(a) DO UPDATE SET b='a'
      ON CONFLICT(c) DO UPDATE SET b='c'
      ON CONFLICT(d) DO UPDATE SET b='d'
      ON CONFLICT(e) DO UPDATE SET b='e';
    SELECT a,b,c,d,e FROM t1;
  } {1 a 3 4 5}
  do_execsql_test 1.$tn.101 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,3,4,5)
      ON CONFLICT(a) DO UPDATE SET b='a'
      ON CONFLICT(c) DO UPDATE SET b='c'
      ON CONFLICT(d) DO UPDATE SET b='d'
      ON CONFLICT(e) DO UPDATE SET b='e';
    SELECT a,b,c,d,e FROM t1;
  } {1 c 3 4 5}
  do_execsql_test 1.$tn.102 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,93,4,5)
      ON CONFLICT(a) DO UPDATE SET b='a'
      ON CONFLICT(c) DO UPDATE SET b='c'
      ON CONFLICT(d) DO UPDATE SET b='d'
      ON CONFLICT(e) DO UPDATE SET b='e';
    SELECT a,b,c,d,e FROM t1;
  } {1 d 3 4 5}
  do_execsql_test 1.$tn.103 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,93,94,5)
      ON CONFLICT(a) DO UPDATE SET b='a'
      ON CONFLICT(c) DO UPDATE SET b='c'
      ON CONFLICT(d) DO UPDATE SET b='d'
      ON CONFLICT(e) DO UPDATE SET b='e';
    SELECT a,b,c,d,e FROM t1;
  } {1 e 3 4 5}
  do_execsql_test 1.$tn.200 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,94,95)
      ON CONFLICT(c) DO UPDATE SET b='c'
      ON CONFLICT(a) DO UPDATE SET b='a'
      ON CONFLICT(d) DO UPDATE SET b='d'
      ON CONFLICT(e) DO UPDATE SET b='e';
    SELECT a,b,c,d,e FROM t1;
  } {1 a 3 4 5}
  do_execsql_test 1.$tn.201 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,3,94,95)
      ON CONFLICT(c) DO UPDATE SET b='c'
      ON CONFLICT(a) DO UPDATE SET b='a'
      ON CONFLICT(d) DO UPDATE SET b='d'
      ON CONFLICT(e) DO UPDATE SET b='e';
    SELECT a,b,c,d,e FROM t1;
  } {1 c 3 4 5}
  do_execsql_test 1.$tn.202 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,3,4,5)
      ON CONFLICT(c) DO UPDATE SET b='c'
      ON CONFLICT(a) DO UPDATE SET b='a'
      ON CONFLICT(d) DO UPDATE SET b='d'
      ON CONFLICT(e) DO UPDATE SET b='e';
    SELECT a,b,c,d,e FROM t1;
  } {1 c 3 4 5}
  do_execsql_test 1.$tn.203 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,94,5)
      ON CONFLICT(c) DO UPDATE SET b='c'
      ON CONFLICT(a) DO UPDATE SET b='a'
      ON CONFLICT(d) DO UPDATE SET b='d'
      ON CONFLICT(e) DO UPDATE SET b='e';
    SELECT a,b,c,d,e FROM t1;
  } {1 a 3 4 5}
  do_execsql_test 1.$tn.204 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,4,95)
      ON CONFLICT(c) DO UPDATE SET b='c'
      ON CONFLICT(a) DO UPDATE SET b='a'
      ON CONFLICT(d) DO UPDATE SET b='d'
      ON CONFLICT(e) DO UPDATE SET b='e';
    SELECT a,b,c,d,e FROM t1;
  } {1 a 3 4 5}
  do_execsql_test 1.$tn.210 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,94,95)
      ON CONFLICT(c) DO UPDATE SET b='c'
      ON CONFLICT(d) DO UPDATE SET b='d'
      ON CONFLICT(a) DO UPDATE SET b='a'
      ON CONFLICT(e) DO UPDATE SET b='e';
    SELECT a,b,c,d,e FROM t1;
  } {1 a 3 4 5}
  do_execsql_test 1.$tn.211 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,4,95)
      ON CONFLICT(c) DO UPDATE SET b='c'
      ON CONFLICT(d) DO UPDATE SET b='d'
      ON CONFLICT(a) DO UPDATE SET b='a'
      ON CONFLICT(e) DO UPDATE SET b='e';
    SELECT a,b,c,d,e FROM t1;
  } {1 d 3 4 5}
  do_execsql_test 1.$tn.212 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,94,5)
      ON CONFLICT(c) DO UPDATE SET b='c'
      ON CONFLICT(d) DO UPDATE SET b='d'
      ON CONFLICT(a) DO UPDATE SET b='a'
      ON CONFLICT(e) DO UPDATE SET b='e';
    SELECT a,b,c,d,e FROM t1;
  } {1 a 3 4 5}
  do_execsql_test 1.$tn.213 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,93,94,5)
      ON CONFLICT(c) DO UPDATE SET b='c'
      ON CONFLICT(d) DO UPDATE SET b='d'
      ON CONFLICT(a) DO UPDATE SET b='a'
      ON CONFLICT(e) DO UPDATE SET b='e';
    SELECT a,b,c,d,e FROM t1;
  } {1 e 3 4 5}
  do_execsql_test 1.$tn.214 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,93,94,5)
      ON CONFLICT(c) DO UPDATE SET b='c'
      ON CONFLICT(d) DO UPDATE SET b='d'
      ON CONFLICT(e) DO UPDATE SET b='e'
      ON CONFLICT(a) DO UPDATE SET b='a';
    SELECT a,b,c,d,e FROM t1;
  } {1 e 3 4 5}
  do_execsql_test 1.$tn.215 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,94,5)
      ON CONFLICT(c) DO UPDATE SET b='c'
      ON CONFLICT(d) DO UPDATE SET b='d'
      ON CONFLICT(e) DO UPDATE SET b='e'
      ON CONFLICT(a) DO UPDATE SET b='a';
    SELECT a,b,c,d,e FROM t1;
  } {1 e 3 4 5}
  do_execsql_test 1.$tn.216 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,94,95)
      ON CONFLICT(c) DO UPDATE SET b='c'
      ON CONFLICT(d) DO UPDATE SET b='d'
      ON CONFLICT(e) DO UPDATE SET b='e'
      ON CONFLICT(a) DO UPDATE SET b='a';
    SELECT a,b,c,d,e FROM t1;
  } {1 a 3 4 5}

  do_execsql_test 1.$tn.300 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,94,95)
      ON CONFLICT(c) DO UPDATE SET b='c'
      ON CONFLICT(d) DO UPDATE SET b='d'
      ON CONFLICT(a) DO UPDATE SET b='a1'
      ON CONFLICT(a) DO UPDATE SET b='a2'
      ON CONFLICT(a) DO UPDATE SET b='a3'
      ON CONFLICT(a) DO UPDATE SET b='a4'
      ON CONFLICT(a) DO UPDATE SET b='a5'
      ON CONFLICT(e) DO UPDATE SET b='e';
    SELECT a,b,c,d,e FROM t1;
  } {1 a1 3 4 5}
  do_execsql_test 1.$tn.301 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,93,94,5)
      ON CONFLICT(c) DO UPDATE SET b='c'
      ON CONFLICT(d) DO UPDATE SET b='d'
      ON CONFLICT(a) DO UPDATE SET b='a1'
      ON CONFLICT(a) DO UPDATE SET b='a2'
      ON CONFLICT(a) DO UPDATE SET b='a3'
      ON CONFLICT(a) DO UPDATE SET b='a4'
      ON CONFLICT(a) DO UPDATE SET b='a5'
      ON CONFLICT(e) DO UPDATE SET b='e';
    SELECT a,b,c,d,e FROM t1;
  } {1 e 3 4 5}

  do_execsql_test 1.$tn.400 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,94,95)
      ON CONFLICT(c) DO UPDATE SET b='c'
      ON CONFLICT(d) DO UPDATE SET b='d'
      ON CONFLICT DO UPDATE set b='x';
    SELECT a,b,c,d,e FROM t1;
  } {1 x 3 4 5}
  do_execsql_test 1.$tn.401 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,93,94,5)
      ON CONFLICT(c) DO UPDATE SET b='c'
      ON CONFLICT(d) DO UPDATE SET b='d'
      ON CONFLICT DO UPDATE set b='x';
    SELECT a,b,c,d,e FROM t1;
  } {1 x 3 4 5}
  do_execsql_test 1.$tn.402 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,94,95)
      ON CONFLICT(c) DO UPDATE SET b='c'
      ON CONFLICT(d) DO UPDATE SET b='d'
      ON CONFLICT DO UPDATE set b='x';
    SELECT a,b,c,d,e FROM t1;
  } {1 x 3 4 5}
  do_execsql_test 1.$tn.403 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,3,94,95)
      ON CONFLICT(c) DO UPDATE SET b='c'
      ON CONFLICT(d) DO UPDATE SET b='d'
      ON CONFLICT DO UPDATE set b='x';
    SELECT a,b,c,d,e FROM t1;
  } {1 c 3 4 5}
  do_execsql_test 1.$tn.404 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,3,4,95)
      ON CONFLICT(c) DO UPDATE SET b='c'
      ON CONFLICT(d) DO UPDATE SET b='d'
      ON CONFLICT DO UPDATE set b='x';
    SELECT a,b,c,d,e FROM t1;
  } {1 c 3 4 5}
  do_execsql_test 1.$tn.405 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,4,5)
      ON CONFLICT(c) DO UPDATE SET b='c'
      ON CONFLICT(d) DO UPDATE SET b='d'
      ON CONFLICT DO UPDATE set b='x';
    SELECT a,b,c,d,e FROM t1;
  } {1 d 3 4 5}

  do_execsql_test 1.$tn.410 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,94,95)
      ON CONFLICT DO UPDATE set b='x';
    SELECT a,b,c,d,e FROM t1;
  } {1 x 3 4 5}
  do_execsql_test 1.$tn.411 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,93,94,5)
      ON CONFLICT DO UPDATE set b='x';
    SELECT a,b,c,d,e FROM t1;
  } {1 x 3 4 5}
  do_execsql_test 1.$tn.412 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,93,4,95)
      ON CONFLICT DO UPDATE set b='x';
    SELECT a,b,c,d,e FROM t1;
  } {1 x 3 4 5}
  do_execsql_test 1.$tn.413 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,3,94,95)
      ON CONFLICT DO UPDATE set b='x';
    SELECT a,b,c,d,e FROM t1;
  } {1 x 3 4 5}

  do_execsql_test 1.$tn.420 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,94,95)
      ON CONFLICT(c) DO NOTHING
      ON CONFLICT(d) DO NOTHING
      ON CONFLICT DO UPDATE set b='x';
    SELECT a,b,c,d,e FROM t1;
  } {1 x 3 4 5}
  do_execsql_test 1.$tn.421 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,93,94,5)
      ON CONFLICT(c) DO NOTHING
      ON CONFLICT(d) DO NOTHING
      ON CONFLICT DO UPDATE set b='x';
    SELECT a,b,c,d,e FROM t1;
  } {1 x 3 4 5}
  do_execsql_test 1.$tn.422 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,93,4,95)
      ON CONFLICT(c) DO NOTHING
      ON CONFLICT(d) DO NOTHING
      ON CONFLICT DO UPDATE set b='x';
    SELECT a,b,c,d,e FROM t1;
  } {1 2 3 4 5}
  do_execsql_test 1.$tn.423 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,3,94,95)
      ON CONFLICT(c) DO NOTHING
      ON CONFLICT(d) DO NOTHING
      ON CONFLICT DO UPDATE set b='x';
    SELECT a,b,c,d,e FROM t1;
  } {1 2 3 4 5}

  do_execsql_test 1.$tn.500 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,94,95)
      ON CONFLICT(c) DO UPDATE SET b='c'
      ON CONFLICT(d) DO UPDATE SET b='d'
      ON CONFLICT DO NOTHING;
    SELECT a,b,c,d,e FROM t1;
  } {1 2 3 4 5}
  do_execsql_test 1.$tn.501 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,93,94,5)
      ON CONFLICT(c) DO UPDATE SET b='c'
      ON CONFLICT(d) DO UPDATE SET b='d'
      ON CONFLICT DO NOTHING;
    SELECT a,b,c,d,e FROM t1;
  } {1 2 3 4 5}
  do_execsql_test 1.$tn.502 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,94,95)
      ON CONFLICT(c) DO UPDATE SET b='c'
      ON CONFLICT(d) DO UPDATE SET b='d'
      ON CONFLICT DO NOTHING;
    SELECT a,b,c,d,e FROM t1;
  } {1 2 3 4 5}
  do_execsql_test 1.$tn.503 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,3,94,95)
      ON CONFLICT(c) DO UPDATE SET b='c'
      ON CONFLICT(d) DO UPDATE SET b='d'
      ON CONFLICT DO NOTHING;
    SELECT a,b,c,d,e FROM t1;
  } {1 c 3 4 5}
  do_execsql_test 1.$tn.504 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,3,4,95)
      ON CONFLICT(c) DO UPDATE SET b='c'
      ON CONFLICT(d) DO UPDATE SET b='d'
      ON CONFLICT DO NOTHING;
    SELECT a,b,c,d,e FROM t1;
  } {1 c 3 4 5}
  do_execsql_test 1.$tn.505 {
    DELETE FROM t1;
    INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
    INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,4,5)
      ON CONFLICT(c) DO UPDATE SET b='c'
      ON CONFLICT(d) DO UPDATE SET b='d'
      ON CONFLICT DO NOTHING;
    SELECT a,b,c,d,e FROM t1;
  } {1 d 3 4 5}

}

#--------------------------------------------------------------------------
reset_db
do_execsql_test 2.0 {
  CREATE TABLE t2(a, b, c REAL, d, e, PRIMARY KEY(a,b)) WITHOUT ROWID;
  CREATE UNIQUE INDEX t2c ON t2(c);
}

do_catchsql_test 2.1 {
  INSERT INTO t2(a,b,c,e,d) VALUES(1,2,3,4,5)
      ON CONFLICT(c) DO UPDATE SET b=''
      ON CONFLICT((SELECT t2 FROM nosuchtable)) DO NOTHING;

} {1 {no such table: nosuchtable}}

finish_test

Changes to test/uri.test.

190
191
192
193
194
195
196

197
198
199
200
201
202
203
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204







+







  set A(1) {0 {}}
  set A(0) [list 1 "access mode not allowed: $mode"]
  do_test 4.1.$tn.3 {
    list [catch {sqlite3 db "file:test.db?mode=$mode" -readonly 1} msg] $msg
  } $A($readonly_ok)
}

ifcapable shared_cache {
set orig [sqlite3_enable_shared_cache]
foreach {tn options sc_default is_shared} {
  1    ""                1   1
  2    "cache=private"   1   0
  3    "cache=shared"    1   1
  4    ""                0   0
  5    "cache=private"   0   0
219
220
221
222
223
224
225

226
227
228
229
230
231
232
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234







+







  do_test 4.2.$tn {
    db2 eval {BEGIN; INSERT INTO t1 VALUES(1, 2);}
    catchsql { SELECT * FROM t1 }
  } $A($is_shared)

  db2 close
}
} ;# end ifcapable shared_cache

do_test 4.3.1 {
  list [catch {sqlite3 db "file:test.db?mode=rc"} msg] $msg
} {1 {no such access mode: rc}}
do_test 4.3.2 {
  list [catch {sqlite3 db "file:test.db?cache=public"} msg] $msg
} {1 {no such cache mode: public}}
276
277
278
279
280
281
282
283

284
285
286
287

288
289
290
291
292
293
294
278
279
280
281
282
283
284

285
286
287
288

289
290
291
292
293
294
295
296







-
+



-
+







      CREATE TABLE aux.t2(a, b);
      PRAGMA main.journal_mode = WAL;
      PRAGMA aux.journal_mode = WAL;
      INSERT INTO t1 VALUES('x', 'y');
      INSERT INTO t2 VALUES('x', 'y');
    }
    lsort [array names ::T1]
  } {test.db1 test.db1-journal test.db1-wal}
  } {test.db1 test.db1-journal test.db1-wal test.db1-wal2}
  
  do_test 5.1.2 {
    lsort [array names ::T2]
  } {test.db2 test.db2-journal test.db2-wal}
  } {test.db2 test.db2-journal test.db2-wal test.db2-wal2}
  db close
  
  tvfs1 delete
  tvfs2 delete
}

#-------------------------------------------------------------------------

Changes to test/utf16align.test.

28
29
30
31
32
33
34

35
36
37
38
39
40
41
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42







+








# Create a database with a UTF16 encoding.  Put in lots of string
# data of varying lengths.
#
do_test utf16align-1.0 {
  set unaligned_string_counter 0
  add_alignment_test_collations [sqlite3_connection_pointer db]
  sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1
  execsql {
    PRAGMA encoding=UTF16;
    CREATE TABLE t1(
      id INTEGER PRIMARY KEY,
      spacer TEXT,
      a TEXT COLLATE utf16_aligned,
      b TEXT COLLATE utf16_unaligned

Changes to test/vacuum-into.test.

61
62
63
64
65
66
67









68













































































































69



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







+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
  CREATE TABLE t2(name TEXT);
  INSERT INTO t2 VALUES(':memory:');
  VACUUM main INTO (SELECT name FROM t2);
} {}
do_catchsql_test vacuum-into-310 {
  VACUUM INTO null;
} {1 {non-text filename}}
do_catchsql_test vacuum-into-320 {
  VACUUM INTO x;
} {1 {no such column: x}}
do_catchsql_test vacuum-into-330 {
  VACUUM INTO t1.nosuchcol;
} {1 {no such column: t1.nosuchcol}}
do_catchsql_test vacuum-into-340 {
  VACUUM INTO main.t1.nosuchcol;
} {1 {no such column: main.t1.nosuchcol}}

forcedelete test.db2
db func target target
proc target {} { return "test.db2" }
do_test vacuum-into-410 {
  execsql { VACUUM INTO target() }
  file exists test.db2
} 1
do_catchsql_test vacuum-into-420 {
  VACUUM INTO target2()
} {1 {no such function: target2}}

# The ability to VACUUM INTO a read-only database
db close
sqlite3 db test.db -readonly 1
forcedelete test.db2
do_execsql_test vacuum-into-500 {
  VACUUM INTO 'test.db2';
}
sqlite3 db2 test.db2
do_test vacuum-into-510 {
  db2 eval {SELECT name FROM sqlite_master ORDER BY 1}
} {t1 t1b t2}
db2 close
db close

# Change the page-size on a VACUUM INTO even if the original
# database is in WAL mode.
#
if {[wal_is_capable]} {
  forcedelete test.db
  forcedelete test.db2
  do_test vacuum-into-600 {
    sqlite3 db test.db
    db eval {
      PRAGMA page_size=4096;
      PRAGMA journal_mode=WAL;
      CREATE TABLE t1(a);
      INSERT INTO t1 VALUES(19);
      CREATE INDEX t1a ON t1(a);
      PRAGMA integrity_check;
    }
  } {wal ok}
  do_execsql_test vacuum-into-610 {
    PRAGMA page_size;
  } {4096}
  do_execsql_test vacuum-into-620 {
    PRAGMA page_size=1024;
    VACUUM INTO 'test.db2';
  } {}
  do_test vacuum-into-630 {
    sqlite3 db test.db2
    db eval {
      PRAGMA page_size;
      PRAGMA integrity_check;
    }
  } {1024 ok}
}

#-------------------------------------------------------------------------

testvfs tvfs -default 1
tvfs filter xSync
tvfs script xSyncCb
proc xSyncCb {method file fileid flags} {
  incr ::sync($flags)
}

reset_db

do_execsql_test vacuum-into-700 {
  CREATE TABLE t1(a, b);
  INSERT INTO t1 VALUES(1, 2);
}

foreach {tn pragma res} {
  710 {
    PRAGMA synchronous = normal
  } {normal 2}
  720 {
    PRAGMA synchronous = full
  } {normal 3}
  730 {
    PRAGMA synchronous = off
  } {}
  740 {
    PRAGMA synchronous = extra;
  } {normal 3}
  750 {
    PRAGMA fullfsync = 1;
    PRAGMA synchronous = full;
  } {full|dataonly 1 full 2}
} {

  forcedelete test.db2
  array unset ::sync
  do_execsql_test vacuum-into-$tn.1 "
    $pragma ;
    VACUUM INTO 'test.db2'
  "

  do_test vacuum-into-$tn.2 {
    array get ::sync
  } $res
}

db close
tvfs delete


finish_test



Changes to test/vacuum2.test.

52
53
54
55
56
57
58
59

60
61
62
63
64
65
66
52
53
54
55
56
57
58

59
60
61
62
63
64
65
66







-
+







  execsql {
    CREATE TABLE t1(x);
    CREATE TABLE t2(y);
    INSERT INTO t1 VALUES(1);
  }
  hexio_get_int [hexio_read test.db 24 4]
} [expr {[hexio_get_int [hexio_read test.db 24 4]]+3}]
do_test vacuum2-2.1 {
do_test vacuum2-2.2 {
  execsql {
    VACUUM
  }
  hexio_get_int [hexio_read test.db 24 4]
} [expr {[hexio_get_int [hexio_read test.db 24 4]]+1}]

############################################################################

Changes to test/vacuum3.test.

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
95
96
97
98
99
100
101







+
+
-
+
+
+
+
+
+
+
+
+







# Test cases vacuum3-2.* convert a simple 3-page database between a 
# few different page sizes.
#
do_test vacuum3-2.1 {
  execsql {
    PRAGMA page_size = 1024;
    VACUUM;
  }
  ifcapable altertable {
    ALTER TABLE t1 ADD COLUMN d;
    execsql { ALTER TABLE t1 ADD COLUMN d; }
  } else {
    execsql {
      DROP TABLE t1;
      CREATE TABLE t1(a, b, c, d);
      INSERT INTO t1 VALUES(1, 2, 3, NULL);
    }
  }
  execsql {
    UPDATE t1 SET d = randomblob(1000);
  }
  file size test.db
} {3072}
do_test vacuum3-2.2 {
  execsql { PRAGMA page_size }
} {1024}

Added test/vacuum6.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2016-08-19
#
# 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 a test for VACUUM on attached databases.
#
# TESTRUNNER: slow

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix vacuum6

# If the VACUUM statement is disabled in the current build, skip all
# the tests in this file.
#
ifcapable !vacuum {
  finish_test
  return
}


do_execsql_test 1.0 {
  CREATE TABLE t1(x INTEGER PRIMARY KEY, y);
  INSERT INTO t1 VALUES(1, 1);
} {}

do_execsql_test 1.1 {
  VACUUM
}

reset_db
do_execsql_test 1.2 {
  CREATE TABLE t1(x,b);
  CREATE INDEX x1 ON t1(x);
  CREATE INDEX x2 ON t1(x);
  CREATE INDEX x3 ON t1(x);
  INSERT INTO t1 SELECT 2,'';
  VACUUM;
}

#-------------------------------------------------------------------------
#
reset_db
foreach {tn sz} {1 400 2 4000 3 9999} {
  reset_db
  do_execsql_test 2.$tn.1 {
    CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
    WITH s(i) AS (
        SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<100
    )
    INSERT INTO t1 SELECT i, randomblob($sz) FROM s;
  }

  do_execsql_test 2.$tn.2 {
    vacuum;
  }

  do_execsql_test 2.$tn.3 {
    PRAGMA integrity_check;
  } {ok}
}

reset_db
do_execsql_test 3.0 {
  PRAGMA page_size = 1024;
  CREATE TABLE t1(x INTEGER PRIMARY KEY, y);
  INSERT INTO t1 VALUES(2, randomblob(1200));
} {}
do_execsql_test 3.1 {
  PRAGMA page_size = 512;
  VACUUM;
}
do_execsql_test 3.2 {
  PRAGMA integrity_check
} {ok}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 4.0 {
  CREATE TABLE tx(a, b);
  CREATE INDEX i1 ON tx(b);
  WITH s(i) AS (
      SELECT 8000 UNION ALL SELECT i+1 FROM s WHERE i<10000
  )
  INSERT INTO tx SELECT i, randomblob(i) FROM s;

  SELECT sum(length(b)) FROM tx;
} {18009000}
foreach {tn pgsz av} {
  1 2048   0
  2 1024   1
  3 65536  0
  4 8192   1
  5 512    0
  6 4096   1
} {
  do_execsql_test 4.1.$tn.1 "
    PRAGMA page_size = $pgsz;
    PRAGMA auto_vacuum = $av;
  "
  do_execsql_test 4.1.$tn.2 VACUUM
  integrity_check 4.1.$tn.3
}

finish_test

Changes to test/vacuummem.test.

8
9
10
11
12
13
14

15
16
17
18
19
20
21
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22







+







#    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 that the VACUUM statement correctly
# frees any memory used for a temporary cache.
#
# TESTRUNNER: slow

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix vacuummem

if {[permutation]=="memsubsys1"} {
  finish_test

Changes to test/view.test.

34
35
36
37
38
39
40






















41
42
43
44
45
46
47
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







do_test view-1.1 {
  execsql {
    BEGIN;
    CREATE VIEW IF NOT EXISTS v1 AS SELECT a,b FROM t1;
    SELECT * FROM v1 ORDER BY a;
  }
} {1 2 4 5 7 8}
do_test view-1.1.100 {
  db config enable_view off
  catchsql {
    SELECT * FROM v1 ORDER BY a;
  }
} {1 {access to view "v1" prohibited}}
do_execsql_test view-1.1.101 {
  CREATE TEMP VIEW v1temp AS SELECT a, b FROM t1;
  SELECT * FROM v1temp ORDER BY a;
} {1 2 4 5 7 8}
do_test view-1.1.110 {
  db config enable_view on
  catchsql {
    SELECT * FROM v1 ORDER BY a;
    SELECT * FROM v1temp ORDER BY a;
  }
} {0 {1 2 4 5 7 8 1 2 4 5 7 8}}
ifcapable vtab {
  do_execsql_test view-1.1.120 {
    SELECT name, type FROM pragma_table_list('v1');
  } {v1 view}
}
do_test view-1.2 {
  catchsql {
    ROLLBACK;
    SELECT * FROM v1 ORDER BY a;
  }
} {1 {no such table: v1}}
do_test view-1.3 {
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
645
646
647
648
649
650
651



































652
653
654
655
656
657
658







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







    DROP TABLE IF EXISTS t1;
    DROP VIEW IF EXISTS v1;
    CREATE TABLE t1(c1);
    CREATE VIEW v1 AS SELECT c1 FROM (SELECT t1.c1 FROM t1);
  }
} {}

# Ticket [d58ccbb3f1b]: Prevent Table.nRef overflow.
db close
sqlite3 db :memory:
do_test view-21.1 {
  catchsql {
    CREATE TABLE t1(x);
    INSERT INTO t1 VALUES(5);
    CREATE VIEW v1 AS SELECT x*2 FROM t1;
    CREATE VIEW v2 AS SELECT * FROM v1 UNION SELECT * FROM v1;
    CREATE VIEW v4 AS SELECT * FROM v2 UNION SELECT * FROM v2;
    CREATE VIEW v8 AS SELECT * FROM v4 UNION SELECT * FROM v4;
    CREATE VIEW v16 AS SELECT * FROM v8 UNION SELECT * FROM v8;
    CREATE VIEW v32 AS SELECT * FROM v16 UNION SELECT * FROM v16;
    CREATE VIEW v64 AS SELECT * FROM v32 UNION SELECT * FROM v32;
    CREATE VIEW v128 AS SELECT * FROM v64 UNION SELECT * FROM v64;
    CREATE VIEW v256 AS SELECT * FROM v128 UNION SELECT * FROM v128;
    CREATE VIEW v512 AS SELECT * FROM v256 UNION SELECT * FROM v256;
    CREATE VIEW v1024 AS SELECT * FROM v512 UNION SELECT * FROM v512;
    CREATE VIEW v2048 AS SELECT * FROM v1024 UNION SELECT * FROM v1024;
    CREATE VIEW v4096 AS SELECT * FROM v2048 UNION SELECT * FROM v2048;
    CREATE VIEW v8192 AS SELECT * FROM v4096 UNION SELECT * FROM v4096;
    CREATE VIEW v16384 AS SELECT * FROM v8192 UNION SELECT * FROM v8192;
    CREATE VIEW v32768 AS SELECT * FROM v16384 UNION SELECT * FROM v16384;
    SELECT * FROM v32768 UNION SELECT * FROM v32768;
  }
} {1 {too many references to "v1": max 65535}}
ifcapable progress {
  do_test view-21.2 {
    db progress 1000 {expr 1}
    catchsql {
      SELECT * FROM v32768;
    }
  } {1 interrupted}
}

db close
sqlite3 db :memory:
do_execsql_test view-22.1 {
  CREATE VIEW x1 AS SELECT 123 AS '', 234 AS '', 345 AS '';
  SELECT * FROM x1;
} {123 234 345}
do_test view-22.2 {
696
697
698
699
700
701
702
703

















































































































704
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
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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

set res [list {SQLITE_DELETE sqlite_stat1 {} main {}}]
ifcapable stat4 { lappend res {SQLITE_DELETE sqlite_stat4 {} main {}} }
do_test view-25.2 {
  set log ""
  db eval {DROP TABLE t25;}
  set log
} $res

#-------------------------------------------------------------------------
do_execsql_test view-26.0 {
  CREATE TABLE t16(a, b, c UNIQUE);
  INSERT INTO t16 VALUES(1, 1, 1);
  INSERT INTO t16 VALUES(2, 2, 2);
  INSERT INTO t16 VALUES(3, 3, 3);
  CREATE VIEW v16 AS SELECT max(a) AS mx, min(b) AS mn FROM t16 GROUP BY c;

  SELECT * FROM v16 AS one, v16 AS two WHERE one.mx=1;
} {
  1 1 1 1 
  1 1 2 2 
  1 1 3 3
}
do_execsql_test view-26.1 {
  WITH v17(x,y) AS (SELECT max(a), min(b) FROM t16 GROUP BY c)
  SELECT * FROM v17 AS one, v17 AS two WHERE one.x=1;
} {
  1 1 1 1 
  1 1 2 2 
  1 1 3 3
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test view-27.0 {
  CREATE TABLE t0(c0 TEXT, c1);
  INSERT INTO t0(c0, c1) VALUES (-1, 0);
  CREATE VIEW v0(c0, c1) AS SELECT t0.c0, AVG(t0.c1) FROM t0;
}

do_execsql_test view-27.1 {
  SELECT c0, typeof(c0), c1, typeof(c1) FROM v0;
} {
  -1   text
   0.0 real
}

do_execsql_test view-27.2 { SELECT c0<c1 FROM v0 } 1
do_execsql_test view-27.3 { SELECT c1<c0 FROM v0 } 0
do_execsql_test view-27.4 {
  SELECT 1 FROM v0 WHERE c1<c0
} {}
do_execsql_test view-27.5 {
  SELECT 1 FROM v0 WHERE c0<c1
} {1}

do_execsql_test view-27.6 { 
  SELECT c0<c1 FROM (SELECT t0.c0 AS c0, AVG(t0.c1) AS c1 FROM t0) 
} 1
do_execsql_test view-27.7 { 
  SELECT c1<c0 FROM (SELECT t0.c0 AS c0, AVG(t0.c1) AS c1 FROM t0) 
} 0
do_execsql_test view-27.8 {
  SELECT 1 FROM (SELECT t0.c0 AS c0, AVG(t0.c1) AS c1 FROM t0) WHERE c1<c0
} {}
do_execsql_test view-27.9 {
  SELECT 1 FROM (SELECT t0.c0 AS c0, AVG(t0.c1) AS c1 FROM t0) WHERE c0<c1
} {1}

#-------------------------------------------------------------------------
reset_db
do_execsql_test view-28.0 {
  CREATE TABLE t0(c0 TEXT);
  CREATE VIEW v0(c0) AS SELECT t0.c0 FROM t0;
  INSERT INTO t0(c0) VALUES ('0');
}
do_execsql_test view-28.1 {
  SELECT 0 IN (c0) FROM t0;
} {0}
do_execsql_test view-28.2 {
  SELECT 0 IN (c0) FROM (SELECT c0 FROM t0);
} {0}

#-------------------------------------------------------------------------
# 2020-10-26.  https://sqlite.org/forum/forumpost/daa2c728cc
#
reset_db
do_catchsql_test view-29.0 {
  CREATE TABLE t1(a,b,c);
  CREATE VIEW IF NOT EXISTS IF AS SELECT null;
} {1 {malformed database schema (IF) - near "AS": syntax error}}
do_catchsql_test view-29.1 {
  CREATE TABLE t2(c,d,e);
  SELECT name FROM sqlite_schema ORDER BY name;
} {0 {t1 t2}}

#-------------------------------------------------------------------------
# 2022-12-11.  https://sqlite.org/src/info/679ed6a2
#
# 2022-12-14 change:  If the AS SELECT of a VIEW is a compound where
# the datatypes on each arm of the compound are different, then the
# datatype of the overall column is BLOB (ANY).
#
reset_db
do_execsql_test view-30.0 {
  CREATE TABLE t0(a INT, b TEXT);

  INSERT INTO t0 VALUES(1,'one');

  CREATE VIEW t1      AS SELECT a, b FROM t0 UNION ALL SELECT 2, 2;
  CREATE VIEW t2(a,b) AS SELECT a, b FROM t0 UNION ALL SELECT 2, 2;
}

ifcapable schema_pragmas {
  do_execsql_test view-30.1 {
    PRAGMA table_info = t1;
  } { 0 a INT 0 {} 0 1 b BLOB 0 {} 0 }
  do_execsql_test view-30.2 {
    PRAGMA table_info = t2;
  } { 0 a INT 0 {} 0 1 b BLOB 0 {} 0 }
}

finish_test

Added test/view2.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2021 May 20
#
# 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 VIEW statements.
#
# $Id: view.test,v 1.39 2008/12/14 14:45:21 danielk1977 Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Omit this entire file if the library is not configured with views enabled.
ifcapable !view {
  finish_test
  return
}
set testprefix view2

do_execsql_test 1.0 {
  CREATE TABLE t1(x, y);
  INSERT INTO t1 VALUES(1, 2);
  CREATE VIEW v1 AS SELECT * FROM (
    WITH x1 AS (SELECT y, x FROM t1)
    SELECT * FROM x1
  );
}

do_execsql_test 1.1 {
  SELECT * FROM v1
} {2 1}

do_execsql_test 1.2 {
  CREATE VIEW v3 AS SELECT * FROM main.t1;
  WITH t1(a, b) AS ( SELECT 3, 4 ) SELECT * FROM v3;
} {1 2}

breakpoint
do_execsql_test 1.3 {
  CREATE VIEW v2 AS SELECT * FROM t1;
  WITH t1(a, b) AS ( SELECT 3, 4 ) SELECT * FROM v2;
} {1 2}

finish_test

Added test/view3.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022 July 19
#
# 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 VIEW statements.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Omit this entire file if the library is not configured with views enabled.
ifcapable !view {
  finish_test
  return
}
set testprefix view3

# Ticket [d58ccbb3f1b]: Prevent Table.nRef overflow.
db close
sqlite3 db :memory:
do_test 1.1 {
  catchsql {
    CREATE TABLE t1(x);
    INSERT INTO t1 VALUES(5);
    CREATE VIEW v1 AS SELECT x*2 FROM t1;
    CREATE VIEW v2 AS SELECT * FROM v1 UNION SELECT * FROM v1;
    CREATE VIEW v4 AS SELECT * FROM v2 UNION SELECT * FROM v2;
    CREATE VIEW v8 AS SELECT * FROM v4 UNION SELECT * FROM v4;
    CREATE VIEW v16 AS SELECT * FROM v8 UNION SELECT * FROM v8;
    CREATE VIEW v32 AS SELECT * FROM v16 UNION SELECT * FROM v16;
    CREATE VIEW v64 AS SELECT * FROM v32 UNION SELECT * FROM v32;
    CREATE VIEW v128 AS SELECT * FROM v64 UNION SELECT * FROM v64;
    CREATE VIEW v256 AS SELECT * FROM v128 UNION SELECT * FROM v128;
    CREATE VIEW v512 AS SELECT * FROM v256 UNION SELECT * FROM v256;
    CREATE VIEW v1024 AS SELECT * FROM v512 UNION SELECT * FROM v512;
    CREATE VIEW v2048 AS SELECT * FROM v1024 UNION SELECT * FROM v1024;
    CREATE VIEW v4096 AS SELECT * FROM v2048 UNION SELECT * FROM v2048;
    CREATE VIEW v8192 AS SELECT * FROM v4096 UNION SELECT * FROM v4096;
    CREATE VIEW v16384 AS SELECT * FROM v8192 UNION SELECT * FROM v8192;
    CREATE VIEW v32768 AS SELECT * FROM v16384 UNION SELECT * FROM v16384;
    SELECT * FROM v32768 UNION SELECT * FROM v32768;
  }
} {1 {too many references to "v1": max 65535}}
ifcapable progress {
  do_test 1.2 {
    db progress 1000 {expr 1}
    catchsql {
      SELECT * FROM v32768;
    }
  } {1 interrupted}
}


finish_test

Added test/vt02.c.




























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** This file implements an eponymous, read-only table-valued function
** (a virtual table) designed to be used for testing.  We are not aware
** of any practical real-world use case for the virtual table.
**
** This virtual table originated in the TH3 test suite.  It is still used
** there, but has now been copied into the public SQLite source tree and
** reused for a variety of testing purpose.  The name "vt02" comes from the
** fact that there are many different testing virtual tables in TH3, of which
** this one is the second.
**
** ## SUBJECT TO CHANGE
**
** Because this virtual table is intended for testing, its interface is not
** guaranteed to be stable across releases.  Future releases may contain
** changes in the vt02 design and interface.
**
** ## OVERVIEW
**
** The vt02 table-valued function has 10000 rows with 5 data columns.
** Column X contains all integer values between 0 and 9999 inclusive.
** Columns A, B, C, and D contain the individual base-10 digits associated
** with each X value:
**
**      X     A  B  C  D
**      ----  -  -  -  -
**      0     0  0  0  0
**      1     0  0  0  1
**      2     0  0  0  2
**              ...
**      4998  4  9  9  8
**      4999  4  9  9  9
**      5000  5  0  0  0
**              ...
**      9995  9  9  9  5
**      9996  9  9  9  6
**      9997  9  9  9  7
**
** The xBestIndex method recognizes a variety of equality constraints
** and attempts to optimize its output accordingly.
**
**      x=...
**      a=...
**      a=... AND b=...
**      a=... AND b=... AND c=...
**      a=... AND b=... AND c=... AND d=...
**
** Various ORDER BY constraints are also recognized and consumed.  The
** OFFSET constraint is recognized and consumed.
**
** ## TABLE-VALUED FUNCTION
**
** The vt02 virtual table is eponymous and has two hidden columns, meaning
** that it can functions a table-valued function.  The two hidden columns
** are "flags" and "logtab", in that order.  The "flags" column can be set
** to an integer where various bits enable or disable behaviors of the
** virtual table.  The "logtab" can set to the name of an ordinary SQLite
** table into which is written information about each call to xBestIndex.
**
** The bits of "flags" are as follows:
**
**       0x01           Ignore the aConstraint[].usable flag.  This might
**                      result in the xBestIndex method incorrectly using
**                      unusable entries in the aConstraint[] array, which
**                      should result in the SQLite core detecting and
**                      reporting that the virtual table is not behaving
**                      to spec.
**
**       0x02           Do not set the orderByConsumed flag, even if it
**                      could be set.
**
**       0x04           Do not consume the OFFSET constraint, if there is
**                      one.  Instead, let the generated byte-code visit
**                      and ignore the first few columns of output.
**
**       0x08           Use sqlite3_mprintf() to allocate an idxStr string.
**                      The string is never used, but allocating it does
**                      test the idxStr deallocation logic inside of the
**                      SQLite core.
**
**       0x10           Cause the xBestIndex method to generate an idxNum
**                      that xFilter does not understand, thus causing
**                      the OP_VFilter opcode to raise an error.
**
**       0x20           Set the omit flag for all equality constraints on
**                      columns X, A, B, C, and D that are used to limit
**                      the search.
**
**       0x40           Add all constraints against X,A,B,C,D to the
**                      vector of results sent to xFilter.  Only the first
**                      few are used, as required by idxNum.
**
** Because these flags take effect during xBestIndex, the RHS of the
** flag= constraint must be accessible.  In other words, the RHS of flag=
** needs to be an integer literal, not another column of a join or a
** bound parameter.
**
** ## LOGGING OUTPUT
**
** If the "logtab" columns is set, then each call to the xBestIndex method
** inserts multiple rows into the table identified by "logtab".  These
** rows collectively show the content of the sqlite3_index_info object and
** other context associated with the xBestIndex call.
**
** If the table named by "logtab" does not previously exist, it is created
** automatically.  The schema for the logtab table is like this:
**
**   CREATE TEMP TABLE vt02_log(
**     bi INT,         -- BestIndex call counter
**     vn TEXT,        -- Variable Name
**     ix INT,         -- Index or value
**     cn TEXT,        -- Column Name
**     op INT,         -- Opcode or "DESC" value
**     ux INT,         -- "Usable" flag
**     ra BOOLEAN,     -- Right-hand side Available.
**     rhs ANY,        -- Right-Hand Side value
**     cs TEXT         -- Collating Sequence for this constraint
**  );
**
** Because logging happens during xBestIindex, the RHS value of "logtab" must
** be known to xBestIndex, which means it must be a string literal, not a
** column in a join, or a bound parameter.
** 
** ## VIRTUAL TABLE SCHEMA
**
**    CREATE TABLE vt02(
**      x INT,              -- integer between 0 and 9999 inclusive
**      a INT,              -- The 1000s digit
**      b INT,              -- The 100s digit
**      c INT,              -- The 10s digit
**      d INT,              -- The 1s digit
**      flags INT HIDDEN,   -- Option flags
**      logtab TEXT HIDDEN, -- Name of table into which to log xBestIndex
**    );
**
** ## COMPILING AND RUNNING
**
** This file can also be compiled separately as a loadable extension
** for SQLite (as long as the -DTH3_VERSION is not defined).  To compile as a
** loadable extension do his:
**
**    gcc -Wall -g -shared -fPIC -I. -DSQLITE_DEBUG vt02.c -o vt02.so
**
** Or on Windows:
**
**    cl vt02.c -link -dll -out:vt02.dll
**
** Then load into the CLI using:
**
**    .load ./vt02 sqlite3_vt02_init
**
** ## IDXNUM SUMMARY
**
** The xBestIndex method communicates the query plan to xFilter using
** the idxNum value, as follows:
**
**     0           unconstrained
**     1           X=argv[0]
**     2           A=argv[0]
**     3           A=argv[0], B=argv[1]
**     4           A=argv[0], B=argv[1], C=argv[2]
**     5           A=argv[0], B=argv[1], C=argv[2], D=argv[3]
**     6           A=argv[0], D IN argv[2]
**     7           A=argv[0], B=argv[2], D IN argv[3]
**     8           A=argv[0], B=argv[2], C=argv[3], D IN argv[4]
**    1x           increment by 10
**    2x           increment by 100
**    3x           increment by 1000
**   1xx           Use offset provided by argv[N]
*/
#ifndef TH3_VERSION
  /* These bits for separate compilation as a loadable extension, only */
  #include "sqlite3ext.h"
  SQLITE_EXTENSION_INIT1
  #include <stdlib.h>
  #include <string.h>
  #include <assert.h>
#endif

/* Forward declarations */
typedef struct vt02_vtab vt02_vtab;
typedef struct vt02_cur vt02_cur;

/*
** The complete virtual table
*/
struct vt02_vtab {
  sqlite3_vtab parent;        /* Base clase.  Must be first. */
  sqlite3 *db;                /* Database connection */
  int busy;                   /* Currently running xBestIndex */
};

#define VT02_IGNORE_USABLE  0x0001  /* Ignore usable flags */
#define VT02_NO_SORT_OPT    0x0002  /* Do not do any sorting optimizations */
#define VT02_NO_OFFSET      0x0004  /* Omit the offset optimization */
#define VT02_ALLOC_IDXSTR   0x0008  /* Alloate an idxStr */
#define VT02_BAD_IDXNUM     0x0010  /* Generate an invalid idxNum */

/*
** A cursor
*/
struct vt02_cur {
  sqlite3_vtab_cursor parent; /* Base class.  Must be first */
  sqlite3_int64 i;            /* Current entry */
  sqlite3_int64 iEof;         /* Indicate EOF when reaching this value */
  int iIncr;                  /* Amount by which to increment */
  unsigned int mD;            /* Mask of allowed D-column values */
};

/* The xConnect method */
int vt02Connect(
  sqlite3 *db,                /* The database connection */
  void *pAux,                 /* Pointer to an alternative schema */
  int argc,                   /* Number of arguments */
  const char *const*argv,     /* Text of the arguments */
  sqlite3_vtab **ppVTab,      /* Write the new vtab here */
  char **pzErr                /* Error message written here */
){
  vt02_vtab *pVtab;
  int rc;
  const char *zSchema = (const char*)pAux;
  static const char zDefaultSchema[] = 
    "CREATE TABLE x(x INT, a INT, b INT, c INT, d INT,"
    " flags INT HIDDEN, logtab TEXT HIDDEN);";
#define VT02_COL_X       0
#define VT02_COL_A       1
#define VT02_COL_B       2
#define VT02_COL_C       3
#define VT02_COL_D       4
#define VT02_COL_FLAGS   5
#define VT02_COL_LOGTAB  6
#define VT02_COL_NONE    7

  pVtab = sqlite3_malloc( sizeof(*pVtab) );
  if( pVtab==0 ){
    *pzErr = sqlite3_mprintf("out of memory");
    return SQLITE_NOMEM;
  }
  memset(pVtab, 0, sizeof(*pVtab));
  pVtab->db = db;
  rc = sqlite3_declare_vtab(db, zSchema ? zSchema : zDefaultSchema);
  if( rc ){
    sqlite3_free(pVtab);
  }else{
    *ppVTab = &pVtab->parent;
  }
  return rc;
}

/* the xDisconnect method
*/
int vt02Disconnect(sqlite3_vtab *pVTab){
  sqlite3_free(pVTab);
  return SQLITE_OK;
}

/* Put an error message into the zErrMsg string of the virtual table.
*/
static void vt02ErrMsg(sqlite3_vtab *pVtab, const char *zFormat, ...){
  va_list ap;
  sqlite3_free(pVtab->zErrMsg);
  va_start(ap, zFormat);
  pVtab->zErrMsg = sqlite3_vmprintf(zFormat, ap);
  va_end(ap);
}


/* Open a cursor for scanning
*/
static int vt02Open(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
  vt02_cur *pCur;
  pCur = sqlite3_malloc( sizeof(*pCur) );
  if( pCur==0 ){
    vt02ErrMsg(pVTab, "out of memory");
    return SQLITE_NOMEM;
  }
  *ppCursor = &pCur->parent;
  pCur->i = -1;
  return SQLITE_OK;
}

/* Close a cursor
*/
static int vt02Close(sqlite3_vtab_cursor *pCursor){
  vt02_cur *pCur = (vt02_cur*)pCursor;
  sqlite3_free(pCur);
  return SQLITE_OK;
}

/* Return TRUE if we are at the end of the BVS and there are
** no more entries.
*/
static int vt02Eof(sqlite3_vtab_cursor *pCursor){
  vt02_cur *pCur = (vt02_cur*)pCursor;
  return pCur->i<0 || pCur->i>=pCur->iEof;
}

/* Advance the cursor to the next row in the table
*/
static int vt02Next(sqlite3_vtab_cursor *pCursor){
  vt02_cur *pCur = (vt02_cur*)pCursor;
  do{
    pCur->i += pCur->iIncr;
    if( pCur->i<0 ) pCur->i = pCur->iEof;
  }while( (pCur->mD & (1<<(pCur->i%10)))==0 && pCur->i<pCur->iEof );
  return SQLITE_OK;
}

/* Rewind a cursor back to the beginning of its scan.
**
** Scanning is always increasing.
**
**   idxNum
**     0           unconstrained
**     1           X=argv[0]
**     2           A=argv[0]
**     3           A=argv[0], B=argv[1]
**     4           A=argv[0], B=argv[1], C=argv[2]
**     5           A=argv[0], B=argv[1], C=argv[2], D=argv[3]
**     6           A=argv[0], D IN argv[2]
**     7           A=argv[0], B=argv[2], D IN argv[3]
**     8           A=argv[0], B=argv[2], C=argv[3], D IN argv[4]
**    1x           increment by 10
**    2x           increment by 100
**    3x           increment by 1000
**   1xx           Use offset provided by argv[N]
*/
static int vt02Filter(
  sqlite3_vtab_cursor *pCursor, /* The cursor to rewind */
  int idxNum,                   /* Search strategy */
  const char *idxStr,           /* Not used */
  int argc,                     /* Not used */
  sqlite3_value **argv          /* Not used */
){
  vt02_cur *pCur = (vt02_cur*)pCursor; /* The vt02 cursor */
  int bUseOffset = 0;                  /* True to use OFFSET value */
  int iArg = 0;                        /* argv[] values used so far */
  int iOrigIdxNum = idxNum;            /* Original value for idxNum */

  pCur->iIncr = 1;
  pCur->mD = 0x3ff;
  if( idxNum>=100 ){
    bUseOffset = 1;
    idxNum -= 100;
  }
  if( idxNum<0 || idxNum>38 ) goto vt02_bad_idxnum;
  while( idxNum>=10 ){
    pCur->iIncr *= 10;
    idxNum -= 10;
  }
  if( idxNum==0 ){
    pCur->i = 0;
    pCur->iEof = 10000;
  }else if( idxNum==1 ){
    pCur->i = sqlite3_value_int64(argv[0]);
    if( pCur->i<0 ) pCur->i = -1;
    if( pCur->i>9999 ) pCur->i = 10000;
    pCur->iEof = pCur->i+1;
    if( pCur->i<0 || pCur->i>9999 ) pCur->i = pCur->iEof;
  }else if( idxNum>=2 && idxNum<=5 ){
    int i, e, m;
    e = idxNum - 2;
    assert( e<=argc-1 );
    pCur->i = 0;
    for(m=1000, i=0; i<=e; i++, m /= 10){
      sqlite3_int64 v = sqlite3_value_int64(argv[iArg++]);
      if( v<0 ) v = 0;
      if( v>9 ) v = 9;
      pCur->i += m*v;
      pCur->iEof = pCur->i+m;
    }
  }else if( idxNum>=6 && idxNum<=8 ){
    int i, e, m, rc;
    sqlite3_value *pIn, *pVal;
    e = idxNum - 6;
    assert( e<=argc-2 );
    pCur->i = 0;
    for(m=1000, i=0; i<=e; i++, m /= 10){
      sqlite3_int64 v;
      pVal = 0;
      if( sqlite3_vtab_in_first(0, &pVal)!=SQLITE_MISUSE
       || sqlite3_vtab_in_first(argv[iArg], &pVal)!=SQLITE_MISUSE
      ){
        vt02ErrMsg(pCursor->pVtab, 
                "unexpected success from sqlite3_vtab_in_first()");
        return SQLITE_ERROR;
      }
      v = sqlite3_value_int64(argv[iArg++]);
      if( v<0 ) v = 0;
      if( v>9 ) v = 9;
      pCur->i += m*v;
      pCur->iEof = pCur->i+m;
    }
    pCur->mD = 0;
    pIn = argv[iArg++];
    assert( sqlite3_value_type(pIn)==SQLITE_NULL );
    for( rc = sqlite3_vtab_in_first(pIn, &pVal);
         rc==SQLITE_OK && pVal!=0;
         rc = sqlite3_vtab_in_next(pIn, &pVal)
    ){
      int eType = sqlite3_value_numeric_type(pVal);
      if( eType==SQLITE_FLOAT ){
        double r = sqlite3_value_double(pVal);
        if( r<0.0 || r>9.0 || r!=(int)r ) continue;
      }else if( eType!=SQLITE_INTEGER ){
        continue;
      }
      i = sqlite3_value_int(pVal);
      if( i<0 || i>9 ) continue;
      pCur->mD |= 1<<i;
    }
    if( rc!=SQLITE_OK && rc!=SQLITE_DONE ){
      vt02ErrMsg(pCursor->pVtab, "Error from sqlite3_vtab_in_first/next()");
      return rc;
    }
  }else{
    goto vt02_bad_idxnum;
  }
  if( bUseOffset ){
    int nSkip = sqlite3_value_int(argv[iArg]);
    while( nSkip-- > 0 ) vt02Next(pCursor);
  }
  return SQLITE_OK;

vt02_bad_idxnum:
  vt02ErrMsg(pCursor->pVtab, "invalid idxNum for vt02: %d", iOrigIdxNum);
  return SQLITE_ERROR;
}

/* Return the Nth column of the current row.
*/
static int vt02Column(
  sqlite3_vtab_cursor *pCursor,
  sqlite3_context *context,
  int N
){
  vt02_cur *pCur = (vt02_cur*)pCursor;
  int v = pCur->i;
  if( N==VT02_COL_X ){
    sqlite3_result_int(context, v);
  }else if( N>=VT02_COL_A && N<=VT02_COL_D ){
    static const int iDivisor[] = { 1, 1000, 100, 10, 1 };
    v = (v/iDivisor[N])%10;
    sqlite3_result_int(context, v);
  }
  return SQLITE_OK;
}

/* Return the rowid of the current row
*/
static int vt02Rowid(sqlite3_vtab_cursor *pCursor, sqlite3_int64 *pRowid){
  vt02_cur *pCur = (vt02_cur*)pCursor;
  *pRowid = pCur->i+1;
  return SQLITE_OK;
}

/*************************************************************************
** Logging Subsystem
**
** The sqlite3BestIndexLog() routine implements a logging system for
** xBestIndex calls.  This code is portable to any virtual table.
**
** sqlite3BestIndexLog() is the main routine,  sqlite3RunSql() is a
** helper routine used for running various SQL statements as part of
** creating the log.
**
** These two routines should be portable to other virtual tables.  Simply
** extract this code and call sqlite3BestIndexLog() near the end of the
** xBestIndex method in cases where logging is desired.
*/
/*
** Run SQL on behalf of sqlite3BestIndexLog.
**
** Construct the SQL using the zFormat string and subsequent arguments.
** Or if zFormat is NULL, take the SQL as the first argument after the
** zFormat.  In either case, the dynamically allocated SQL string is
** freed after it has been run.  If something goes wrong with the SQL,
** then an error is left in pVTab->zErrMsg.
*/
static void sqlite3RunSql(
  sqlite3 *db,               /* Run the SQL on this database connection */
  sqlite3_vtab *pVTab,       /* Report errors to this virtual table */
  const char *zFormat,       /* Format string for SQL, or NULL */
  ...                        /* Arguments, according to the format string */
){
  char *zSql;

  va_list ap;
  va_start(ap, zFormat);
  if( zFormat==0 ){
    zSql = va_arg(ap, char*);
  }else{
    zSql = sqlite3_vmprintf(zFormat, ap);
  }
  va_end(ap);
  if( zSql ){
    char *zErrMsg = 0;
    (void)sqlite3_exec(db, zSql, 0, 0, &zErrMsg);
    if( zErrMsg ){
      if( pVTab->zErrMsg==0 ){
        pVTab->zErrMsg = sqlite3_mprintf("%s in [%s]", zErrMsg, zSql);
      }
      sqlite3_free(zErrMsg);
    }
    sqlite3_free(zSql);
  }
}

/*
** Record information about each xBestIndex method call in a separate
** table:
**
**   CREATE TEMP TABLE [log-table-name] (
**     bi INT,      -- BestIndex call number
**     vn TEXT,     -- Variable Name
**     ix INT,      -- Index or value
**     cn TEXT,     -- Column Name
**     op INT,      -- Opcode or argvIndex
**     ux INT,      -- "usable" or "omit" flag
**     rx BOOLEAN,  -- True if has a RHS value
**     rhs ANY,     -- The RHS value
**     cs TEXT,     -- Collating Sequence
**     inop BOOLEAN -- True if this is a batchable IN operator
**  );
**
** If an error occurs, leave an error message in pVTab->zErrMsg.
*/
static void sqlite3BestIndexLog(
  sqlite3_index_info *pInfo,  /* The sqlite3_index_info object */
  const char *zLogTab,        /* Log into this table */
  sqlite3 *db,                /* Database connection containing zLogTab */
  const char **azColname,     /* Names of columns in the virtual table */
  sqlite3_vtab *pVTab         /* Record errors into this object */
){
  int i, rc;
  sqlite3_str *pStr;
  int iBI;

  if( sqlite3_table_column_metadata(db,0,zLogTab,0,0,0,0,0,0) ){
    /* The log table does not previously exist.  Create it. */
    sqlite3RunSql(db,pVTab, 
      "CREATE TABLE IF NOT EXISTS temp.\"%w\"(\n"
      " bi INT,          -- BestIndex call number\n"
      " vn TEXT,         -- Variable Name\n"
      " ix INT,          -- Index or value\n"
      " cn TEXT,         -- Column Name\n"
      " op INT,          -- Opcode or argvIndex\n"
      " ux INT,          -- usable for omit flag\n"
      " rx BOOLEAN,      -- Right-hand side value is available\n"
      " rhs ANY,         -- RHS value\n"
      " cs TEXT,         -- Collating Sequence\n"
      " inop BOOLEAN     -- IN operator capable of batch reads\n"
      ");", zLogTab
    );
    iBI = 1;
  }else{
    /* The log table does already exist.  We assume that it has the
    ** correct schema and proceed to find the largest prior "bi" value.
    ** If the schema is wrong, errors might result.  The code is able
    ** to deal with this. */
    sqlite3_stmt *pStmt;
    char *zSql;
    zSql = sqlite3_mprintf("SELECT max(bi) FROM temp.\"%w\"",zLogTab);
    if( zSql==0 ){
      sqlite3_free(pVTab->zErrMsg);
      pVTab->zErrMsg = sqlite3_mprintf("out of memory");
      return;
    }
    rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
    sqlite3_free(zSql);
    if( rc ){
      sqlite3_free(pVTab->zErrMsg);
      pVTab->zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(db));
      iBI = 0;
    }else if( sqlite3_step(pStmt)==SQLITE_ROW ){
      iBI = sqlite3_column_int(pStmt, 0)+1;
    }else{
      iBI = 1;
    }
    sqlite3_finalize(pStmt);
  }
  sqlite3RunSql(db,pVTab,
    "INSERT INTO temp.\"%w\"(bi,vn,ix) VALUES(%d,'nConstraint',%d)",
    zLogTab, iBI, pInfo->nConstraint
  );
  for(i=0; i<pInfo->nConstraint; i++){
    sqlite3_value *pVal;
    char *zSql;
    int iCol = pInfo->aConstraint[i].iColumn;
    int op = pInfo->aConstraint[i].op;
    const char *zCol;
    if( op==SQLITE_INDEX_CONSTRAINT_LIMIT
     || op==SQLITE_INDEX_CONSTRAINT_OFFSET
    ){
      zCol = "";
    }else if( iCol<0 ){
      zCol = "rowid";
    }else{
      zCol = azColname[iCol];
    }
    pStr = sqlite3_str_new(0);
    sqlite3_str_appendf(pStr,
       "INSERT INTO temp.\"%w\"(bi,vn,ix,cn,op,ux,rx,rhs,cs,inop)"
       "VALUES(%d,'aConstraint',%d,%Q,%d,%d",
       zLogTab, iBI,
       i,
       zCol,
       op,
       pInfo->aConstraint[i].usable);
    pVal = 0;
    rc = sqlite3_vtab_rhs_value(pInfo, i, &pVal);
    assert( pVal!=0 || rc!=SQLITE_OK );
    if( rc==SQLITE_OK ){
      sqlite3_str_appendf(pStr,",1,?1");
    }else{
      sqlite3_str_appendf(pStr,",0,NULL");
    }
    sqlite3_str_appendf(pStr,",%Q,%d)",
         sqlite3_vtab_collation(pInfo,i),
         sqlite3_vtab_in(pInfo,i,-1));
    zSql = sqlite3_str_finish(pStr);
    if( zSql==0 ){
      if( pVTab->zErrMsg==0 ) pVTab->zErrMsg = sqlite3_mprintf("out of memory");
    }else{
      sqlite3_stmt *pStmt = 0;
      rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
      if( rc ){
        if( pVTab->zErrMsg==0 ){
          pVTab->zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(db));
        }
      }else{
        if( pVal ) sqlite3_bind_value(pStmt, 1, pVal);
        sqlite3_step(pStmt);
        rc = sqlite3_reset(pStmt);
        if( rc && pVTab->zErrMsg==0 ){
          pVTab->zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(db));
        }
      }
      sqlite3_finalize(pStmt);
      sqlite3_free(zSql);
    }
  }
  sqlite3RunSql(db,pVTab,
    "INSERT INTO temp.\"%w\"(bi,vn,ix) VALUES(%d,'nOrderBy',%d)",
    zLogTab, iBI, pInfo->nOrderBy
  );
  for(i=0; i<pInfo->nOrderBy; i++){
    int iCol = pInfo->aOrderBy[i].iColumn;
    sqlite3RunSql(db,pVTab,
      "INSERT INTO temp.\"%w\"(bi,vn,ix,cn,op)VALUES(%d,'aOrderBy',%d,%Q,%d)",
      zLogTab, iBI,
      i,
      iCol>=0 ? azColname[iCol] : "rowid",
      pInfo->aOrderBy[i].desc
    );
  }
  sqlite3RunSql(db,pVTab,
    "INSERT INTO temp.\"%w\"(bi,vn,ix) VALUES(%d,'sqlite3_vtab_distinct',%d)",
    zLogTab, iBI, sqlite3_vtab_distinct(pInfo)
  );
  sqlite3RunSql(db,pVTab,
    "INSERT INTO temp.\"%w\"(bi,vn,ix) VALUES(%d,'colUsed',%lld)",
    zLogTab, iBI, pInfo->colUsed
  );
  for(i=0; i<pInfo->nConstraint; i++){
    int iCol = pInfo->aConstraint[i].iColumn;
    int op = pInfo->aConstraint[i].op;
    const char *zCol;
    if( op==SQLITE_INDEX_CONSTRAINT_LIMIT
     || op==SQLITE_INDEX_CONSTRAINT_OFFSET
    ){
      zCol = "";
    }else if( iCol<0 ){
      zCol = "rowid";
    }else{
      zCol = azColname[iCol];
    }
    sqlite3RunSql(db,pVTab,
       "INSERT INTO temp.\"%w\"(bi,vn,ix,cn,op,ux)"
       "VALUES(%d,'aConstraintUsage',%d,%Q,%d,%d)",
       zLogTab, iBI,
       i,
       zCol,
       pInfo->aConstraintUsage[i].argvIndex,
       pInfo->aConstraintUsage[i].omit
    );
  }
  sqlite3RunSql(db,pVTab,
    "INSERT INTO temp.\"%w\"(bi,vn,ix)VALUES(%d,'idxNum',%d)",
    zLogTab, iBI, pInfo->idxNum
  );
  sqlite3RunSql(db,pVTab,
    "INSERT INTO temp.\"%w\"(bi,vn,ix)VALUES(%d,'estimatedCost',%f)",
    zLogTab, iBI, pInfo->estimatedCost
  );
  sqlite3RunSql(db,pVTab,
    "INSERT INTO temp.\"%w\"(bi,vn,ix)VALUES(%d,'estimatedRows',%lld)",
    zLogTab, iBI, pInfo->estimatedRows
  );
  if( pInfo->idxStr ){
    sqlite3RunSql(db,pVTab,
      "INSERT INTO temp.\"%w\"(bi,vn,ix)VALUES(%d,'idxStr',%Q)",
      zLogTab, iBI, pInfo->idxStr
    );
    sqlite3RunSql(db,pVTab,
      "INSERT INTO temp.\"%w\"(bi,vn,ix)VALUES(%d,'needToFreeIdxStr',%d)",
      zLogTab, iBI, pInfo->needToFreeIdxStr
    );
  }
  if( pInfo->nOrderBy ){
    sqlite3RunSql(db,pVTab,
      "INSERT INTO temp.\"%w\"(bi,vn,ix)VALUES(%d,'orderByConsumed',%d)",
      zLogTab, iBI, pInfo->orderByConsumed
    );
  }
}
/*
** End of Logging Subsystem
*****************************************************************************/


/* Find an estimated cost of running a query against vt02.
*/
static int vt02BestIndex(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
  int i;                      /* Loop counter */
  int isEq[5];                /* Equality constraints on X, A, B, C, and D */
  int isUsed[5];              /* Other non-== cosntraints X, A, B, C, and D */
  int argvIndex = 0;          /* Next available argv[] slot */
  int iOffset = -1;           /* Constraint for OFFSET */
  void *pX = 0;               /* idxStr value */
  int flags = 0;              /* RHS value for flags= */
  const char *zLogTab = 0;    /* RHS value for logtab= */
  int iFlagTerm = -1;         /* Constraint term for flags= */
  int iLogTerm = -1;          /* Constraint term for logtab= */
  int iIn = -1;               /* Index of the IN constraint */
  vt02_vtab *pSelf;           /* This virtual table */

  pSelf = (vt02_vtab*)pVTab;
  if( pSelf->busy ){
    vt02ErrMsg(pVTab, "recursive use  of vt02 prohibited");
    return SQLITE_CONSTRAINT;
  }
  pSelf->busy++;
 

  /* Do an initial scan for flags=N and logtab=TAB constraints with
  ** usable RHS values */
  for(i=0; i<pInfo->nConstraint; i++){
    sqlite3_value *pVal;
    if( !pInfo->aConstraint[i].usable ) continue;
    if( pInfo->aConstraint[i].op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
    switch( pInfo->aConstraint[i].iColumn ){
      case VT02_COL_FLAGS:
        if( sqlite3_vtab_rhs_value(pInfo, i, &pVal)==SQLITE_OK
         && sqlite3_value_type(pVal)==SQLITE_INTEGER
        ){
          flags = sqlite3_value_int(pVal);
        }
        iFlagTerm = i;
        break;
      case VT02_COL_LOGTAB:
        if( sqlite3_vtab_rhs_value(pInfo, i, &pVal)==SQLITE_OK
         && sqlite3_value_type(pVal)==SQLITE_TEXT
        ){
          zLogTab = (const char*)sqlite3_value_text(pVal);
        }
        iLogTerm = i;
        break;
    }
  }

  /* Do a second scan to actually analyze the index information */
  memset(isEq, 0xff, sizeof(isEq));
  memset(isUsed, 0xff, sizeof(isUsed));
  for(i=0; i<pInfo->nConstraint; i++){
    int j = pInfo->aConstraint[i].iColumn;
    if( j>=VT02_COL_FLAGS ) continue;
    if( pInfo->aConstraint[i].usable==0
     && (flags & VT02_IGNORE_USABLE)==0 ) continue;
    if( j<0 ) j = VT02_COL_X;
    switch( pInfo->aConstraint[i].op ){
      case SQLITE_INDEX_CONSTRAINT_FUNCTION:
      case SQLITE_INDEX_CONSTRAINT_EQ:
        isEq[j] = i;
        break;
      case SQLITE_INDEX_CONSTRAINT_LT:
      case SQLITE_INDEX_CONSTRAINT_LE:
      case SQLITE_INDEX_CONSTRAINT_GT:
      case SQLITE_INDEX_CONSTRAINT_GE:
        isUsed[j] = i;
        break;
      case SQLITE_INDEX_CONSTRAINT_OFFSET:
        iOffset = i;
        break;
    }
  }

  /* Use the analysis to find an appropriate query plan */
  if( isEq[0]>=0 ){
    /* A constraint of X= takes priority */
    pInfo->estimatedCost = 1;
    pInfo->aConstraintUsage[isEq[0]].argvIndex = ++argvIndex;
    if( flags & 0x20 ) pInfo->aConstraintUsage[isEq[0]].omit = 1;
    pInfo->idxNum = 1;
  }else if( isEq[1]<0 ){
    /* If there is no X= nor A= then we have to do a full scan */
    pInfo->idxNum = 0;
    pInfo->estimatedCost = 10000;
  }else{
    int v = 1000;
    pInfo->aConstraintUsage[isEq[1]].argvIndex = ++argvIndex;
    if( flags & 0x20 ) pInfo->aConstraintUsage[isEq[1]].omit = 1;
    for(i=2; i<=4 && isEq[i]>=0; i++){
      if( i==4 && sqlite3_vtab_in(pInfo, isEq[4], 0) ) break;
      pInfo->aConstraintUsage[isEq[i]].argvIndex = ++argvIndex;
      if( flags & 0x20 ) pInfo->aConstraintUsage[isEq[i]].omit = 1;
      v /= 10;
    }
    pInfo->idxNum = i;
    if( isEq[4]>=0 && sqlite3_vtab_in(pInfo,isEq[4],1) ){
      iIn = isEq[4];
      pInfo->aConstraintUsage[iIn].argvIndex = ++argvIndex;
      if( flags & 0x20 ) pInfo->aConstraintUsage[iIn].omit = 1;
      v /= 5;
      i++;
      pInfo->idxNum += 4;
    }
    pInfo->estimatedCost = v;
  }
  pInfo->estimatedRows = (sqlite3_int64)pInfo->estimatedCost;

  /* Attempt to consume the ORDER BY clause.  Except, always leave
  ** orderByConsumed set to 0 for vt02_no_sort_opt.  In this way,
  ** we can compare vt02 and vt02_no_sort_opt to ensure they get
  ** the same answer.
  */
  if( pInfo->nOrderBy>0 && (flags & VT02_NO_SORT_OPT)==0 ){
    if( pInfo->idxNum==1 ){
      /* There will only be one row of output.  So it is always sorted. */
      pInfo->orderByConsumed = 1;
    }else
    if( pInfo->aOrderBy[0].iColumn<=0 
     && pInfo->aOrderBy[0].desc==0
    ){
      /* First column of order by is X ascending */
      pInfo->orderByConsumed = 1;
    }else
    if( sqlite3_vtab_distinct(pInfo)>=1 ){
      unsigned int x = 0;
      for(i=0; i<pInfo->nOrderBy; i++){
        int iCol = pInfo->aOrderBy[i].iColumn;
        if( iCol<0 ) iCol = 0;
        x |= 1<<iCol;
      }
      if( sqlite3_vtab_distinct(pInfo)==2 ){
        if( x==0x02 ){
          /* DISTINCT A */
          pInfo->idxNum += 30;
          pInfo->orderByConsumed = 1;
        }else if( x==0x06 ){
          /* DISTINCT A,B */
          pInfo->idxNum += 20;
          pInfo->orderByConsumed = 1;
        }else if( x==0x0e ){
          /* DISTINCT A,B,C */
          pInfo->idxNum += 10;
          pInfo->orderByConsumed = 1;
        }else if( x & 0x01 ){
          /* DISTINCT X */
          pInfo->orderByConsumed = 1;
        }else if( x==0x1e ){
          /* DISTINCT A,B,C,D */
          pInfo->orderByConsumed = 1;
        }
      }else{
        if( x==0x02 ){
          /* GROUP BY A */
          pInfo->orderByConsumed = 1;
        }else if( x==0x06 ){
          /* GROUP BY A,B */
          pInfo->orderByConsumed = 1;
        }else if( x==0x0e ){
          /* GROUP BY A,B,C */
          pInfo->orderByConsumed = 1;
        }else if( x & 0x01 ){
          /* GROUP BY X */
          pInfo->orderByConsumed = 1;
        }else if( x==0x1e ){
          /* GROUP BY A,B,C,D */
          pInfo->orderByConsumed = 1;
        }
      }
    }
  }

  if( flags & VT02_ALLOC_IDXSTR ){
    pInfo->idxStr = sqlite3_mprintf("test");
    pInfo->needToFreeIdxStr = 1;
  }
  if( flags & VT02_BAD_IDXNUM ){
    pInfo->idxNum += 1000;
  }

  if( iOffset>=0 ){
    pInfo->aConstraintUsage[iOffset].argvIndex = ++argvIndex;
    if( (flags & VT02_NO_OFFSET)==0
     && (pInfo->nOrderBy==0 || pInfo->orderByConsumed)
    ){
      pInfo->aConstraintUsage[iOffset].omit = 1;
      pInfo->idxNum += 100;
    }
  }


  /* Always omit flags= and logtab= constraints to prevent them from
  ** interfering with the bytecode.  Put them at the end of the argv[]
  ** array to keep them out of the way.
  */
  if( iFlagTerm>=0 ){
    pInfo->aConstraintUsage[iFlagTerm].omit = 1;
    pInfo->aConstraintUsage[iFlagTerm].argvIndex = ++argvIndex;
  }
  if( iLogTerm>=0 ){
    pInfo->aConstraintUsage[iLogTerm].omit = 1;
    pInfo->aConstraintUsage[iLogTerm].argvIndex = ++argvIndex;
  }

  /* The 0x40 flag means add all usable constraints to the output set */
  if( flags & 0x40 ){
    for(i=0; i<pInfo->nConstraint; i++){
      if( pInfo->aConstraint[i].usable
       && pInfo->aConstraintUsage[i].argvIndex==0
      ){
        pInfo->aConstraintUsage[i].argvIndex = ++argvIndex;
        if( flags & 0x20 )  pInfo->aConstraintUsage[i].omit = 1;
      }
    }
  }


  /* Generate the log if requested */
  if( zLogTab ){
    static const char *azColname[] = {
       "x", "a", "b", "c", "d", "flags", "logtab"
    };
    sqlite3 *db = ((vt02_vtab*)pVTab)->db;
    sqlite3BestIndexLog(pInfo, zLogTab, db, azColname, pVTab);
  }
  pSelf->busy--;

  /* Try to do a memory allocation solely for the purpose of causing
  ** an error under OOM testing loops */
  pX = sqlite3_malloc(800);
  if( pX==0 ) return SQLITE_NOMEM;
  sqlite3_free(pX);

  return pVTab->zErrMsg!=0 ? SQLITE_ERROR : SQLITE_OK;
}

/* This is the sqlite3_module definition for the the virtual table defined
** by this include file.
*/
const sqlite3_module vt02Module = {
  /* iVersion      */  2,
  /* xCreate       */  0,   /* This is an eponymous table */
  /* xConnect      */  vt02Connect,
  /* xBestIndex    */  vt02BestIndex,
  /* xDisconnect   */  vt02Disconnect,
  /* xDestroy      */  vt02Disconnect,
  /* xOpen         */  vt02Open,
  /* xClose        */  vt02Close,
  /* xFilter       */  vt02Filter,
  /* xNext         */  vt02Next,
  /* xEof          */  vt02Eof,
  /* xColumn       */  vt02Column,
  /* xRowid        */  vt02Rowid,
  /* xUpdate       */  0,
  /* xBegin        */  0, 
  /* xSync         */  0,
  /* xCommit       */  0, 
  /* xRollback     */  0,
  /* xFindFunction */  0,
  /* xRename       */  0,
  /* xSavepoint    */  0,
  /* xRelease      */  0,
  /* xRollbackTo   */  0
};

static void vt02CoreInit(sqlite3 *db){
  static const char zPkXSchema[] = 
    "CREATE TABLE x(x INT NOT NULL PRIMARY KEY, a INT, b INT, c INT, d INT,"
    " flags INT HIDDEN, logtab TEXT HIDDEN);";
  static const char zPkABCDSchema[] = 
    "CREATE TABLE x(x INT, a INT NOT NULL, b INT NOT NULL, c INT NOT NULL, "
    "d INT NOT NULL, flags INT HIDDEN, logtab TEXT HIDDEN, "
    "PRIMARY KEY(a,b,c,d));";
  sqlite3_create_module(db, "vt02", &vt02Module, 0);
  sqlite3_create_module(db, "vt02pkx", &vt02Module, (void*)zPkXSchema);
  sqlite3_create_module(db, "vt02pkabcd", &vt02Module, (void*)zPkABCDSchema);
}

#ifdef TH3_VERSION
static void vt02_init(th3state *p, int iDb, char *zArg){
  vt02CoreInit(th3dbPointer(p, iDb));
}
#else
#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_vt02_init(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  SQLITE_EXTENSION_INIT2(pApi);
  vt02CoreInit(db);
  return SQLITE_OK;
}
#endif /* TH3_VERSION */

Changes to test/vtab1.test.

870
871
872
873
874
875
876








877
878
879
880
881
882
883
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891







+
+
+
+
+
+
+
+







  }
} {31429}
do_test vtab1.7-13 {
  execsql {
    SELECT rowid, a, b, c FROM real_abc
  }
} {}

# PRAGMA index_info and index_xinfo are no-ops on a virtual table
do_test vtab1.7-14 {
  execsql {
    PRAGMA index_info('echo_abc');
    PRAGMA index_xinfo('echo_abc');
  }
} {}

ifcapable attach {
  do_test vtab1.8-1 {
    set echo_module ""
    execsql {
      ATTACH 'test2.db' AS aux;
      CREATE VIRTUAL TABLE aux.e2 USING echo(real_abc);
971
972
973
974
975
976
977

978
979
980
981
982
983
984
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993







+







} [list \
  xBestIndex {SELECT rowid, a, b, c FROM 'r'} \
  xFilter {SELECT rowid, a, b, c FROM 'r'}    \
]
proc match_func {args} {return ""}
do_test vtab1.10-6 {
  set echo_module ""
  sqlite_delete_function db match
  db function match match_func
  execsql {
    SELECT * FROM e WHERE match('pattern', rowid, 'pattern2');
  }
  set echo_module
} [list \
  xBestIndex {SELECT rowid, a, b, c FROM 'r'} \
1299
1300
1301
1302
1303
1304
1305

1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323






















1324
1325
1326
1327


1328
1329
1330




1331
1332
1333
1334
1335
1336
1337
1338
1339

1340
1341
1342
1343
1344
1345
1346
1347

1348
1349
1350
1351
1352
1353
1354
1308
1309
1310
1311
1312
1313
1314
1315


















1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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







+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
+
+


-
+
+
+
+








-
+







-
+







  INSERT INTO t6 VALUES(3, '8James');
  INSERT INTO t6 VALUES(4, '8John');
  INSERT INTO t6 VALUES(5, 'Phillip');
  INSERT INTO t6 VALUES(6, 'Bartholomew');
  CREATE VIRTUAL TABLE e6 USING echo(t6);
}

ifcapable !icu {
foreach {tn sql res filter} {
  1.1 "SELECT a FROM e6 WHERE b>'8James'" {4 2 6 1 5}
    {xFilter {SELECT rowid, a, b FROM 't6' WHERE b > ?} 8James}

  1.2 "SELECT a FROM e6 WHERE b>='8' AND b<'9'" {3 4}
    {xFilter {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ?} 8 9}

  1.3 "SELECT a FROM e6 WHERE b LIKE '8J%'" {3 4}
    {xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8J%}

  1.4 "SELECT a FROM e6 WHERE b LIKE '8j%'" {3 4}
    {xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8j%}
} {
  set echo_module {}
  do_execsql_test 18.$tn.1 $sql $res
  do_test         18.$tn.2 { lrange $::echo_module 2 end } $filter
}

  foreach {tn sql res filter} {
    1.1 "SELECT a FROM e6 WHERE b>'8James'" {4 2 6 1 5}
      {xFilter {SELECT rowid, a, b FROM 't6' WHERE b > ?} 8James}
  
    1.2 "SELECT a FROM e6 WHERE b>='8' AND b<'9'" {3 4}
      {xFilter {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ?} 8 9}
  
    1.3 "SELECT a FROM e6 WHERE b LIKE '8J%'" {3 4}
      {xFilter {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?} 8J 8k 8J%}
  
    1.4 "SELECT a FROM e6 WHERE b LIKE '8j%'" {3 4}
      {xFilter {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?} 8J 8k 8j%}
  
    1.5 "SELECT a FROM e6 WHERE b LIKE '8%'" {3 4}
      {xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8%}
  } {
    set echo_module {}
    do_execsql_test 18.$tn.1 $sql $res
    do_test         18.$tn.2 { lrange $::echo_module 2 end } $filter
  }
}

do_execsql_test 18.2.0 {  PRAGMA case_sensitive_like = ON }
foreach {tn sql res filter} {
  2.1 "SELECT a FROM e6 WHERE b LIKE '8J%'" {3 4}
    {xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8J%}
  2.1 "SELECT a FROM e6 WHERE b LIKE '8%'" {3 4}
    {xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8%}

  2.2 "SELECT a FROM e6 WHERE b LIKE '8j%'" {}
    {xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8j%}
    {xFilter {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?} 8j 8k 8j%}

  2.3 "SELECT a FROM e6 WHERE b LIKE '8J%'" {3 4}
    {xFilter {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?} 8J 8K 8J%}
} {
  set echo_module {}
  do_execsql_test 18.$tn.1 $sql $res
  do_test         18.$tn.2 { lrange $::echo_module 2 end } $filter
}
do_execsql_test 18.2.x {  PRAGMA case_sensitive_like = OFF }

#-------------------------------------------------------------------------
# Test that an existing module may not be overridden.
# Test that it is ok to override and existing module.
#
do_test 19.1 {
  sqlite3 db2 test.db
  register_echo_module [sqlite3_connection_pointer db2]
} SQLITE_OK
do_test 19.2 {
  register_echo_module [sqlite3_connection_pointer db2]
} SQLITE_MISUSE
} SQLITE_OK
do_test 19.3 {
  db2 close
} {}

#-------------------------------------------------------------------------
# Test that the bug fixed by [b0c1ba655d69] really is fixed.
#
1536
1537
1538
1539
1540
1541
1542
1543
































1544
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

    CREATE VIRTUAL TABLE t5 USING fts3();
    SAVEPOINT b;
    ROLLBACK TO a;
    SAVEPOINT c;
    RELEASE a;
  }
}

# 2021-07-04 https://sqlite.org/forum/forumpost/16ca0e9f32
# Yu Liang crash involving UPDATE on a virtual table with
# a duplicate column in a vector changeset and invoking the
# query flattener for UNION ALL.
#
reset_db
register_echo_module db
do_catchsql_test 25.0 {
  CREATE TABLE t0(a);
  CREATE VIRTUAL TABLE t1 USING echo(t0);
  WITH t3(a) AS (SELECT * FROM t1 UNION ALL SELECT * FROM t1)
  UPDATE t1 SET (a,a) = (SELECT 1, 0) FROM t3;
} {0 {}}

#--------------------------------------------------------------------------
#
reset_db
load_static_extension db wholenumber
do_execsql_test 26.1 {
  CREATE VIRTUAL TABLE t1 USING wholenumber;
  CREATE TABLE tx(a, b, c);
}
do_test 26.2 {
  sqlite3 db2 test.db
  db2 eval { CREATE TABLE ty(x, y) }
  db2 close
} {}
do_execsql_test 26.3 {
  SELECT value FROM t1 WHERE value<5
} {1 2 3 4}


finish_test

Changes to test/vtab6.test.

219
220
221
222
223
224
225
226
227
228



229
230


231
232
233
234
235
236
237
219
220
221
222
223
224
225



226
227
228


229
230
231
232
233
234
235
236
237







-
-
-
+
+
+
-
-
+
+







  }
} {1 2 3 4 2 3 4 5 3 4 5 {}}
do_test vtab6-2.2 {
  execsql {
    SELECT * FROM t2 NATURAL LEFT OUTER JOIN t1;
  }
} {1 2 3 {} 2 3 4 1 3 4 5 2}
do_test vtab6-2.3 {
  catchsql {
    SELECT * FROM t1 NATURAL RIGHT OUTER JOIN t2;
#do_test vtab6-2.3 {
#  catchsql {
#    SELECT * FROM t1 NATURAL RIGHT OUTER JOIN t2;
  }
} {1 {RIGHT and FULL OUTER JOINs are not currently supported}}
#  }
#} {1 {RIGHT and FULL OUTER JOINs are not currently supported}}
do_test vtab6-2.4 {
  execsql {
    SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.d
  }
} {1 2 3 {} {} {} 2 3 4 {} {} {} 3 4 5 1 2 3}
do_test vtab6-2.4.1 {
  execsql {
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
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







-
+













+
+
+




-
+
+




-
+







    SELECT * FROM t1 NATURAL JOIN t2 USING(b);
  }
} {1 {a NATURAL join may not have an ON or USING clause}}
do_test vtab6-3.3 {
  catchsql {
    SELECT * FROM t1 JOIN t2 ON t1.a=t2.b USING(b);
  }
} {1 {cannot have both ON and USING clauses in the same join}}
} {1 {near "USING": syntax error}}
do_test vtab6-3.4 {
  catchsql {
    SELECT * FROM t1 JOIN t2 USING(a);
  }
} {1 {cannot join using column a - column not present in both tables}}
do_test vtab6-3.5 {
  catchsql { SELECT * FROM t1 USING(a) }
} {1 {a JOIN clause is required before USING}}
do_test vtab6-3.6 {
  catchsql {
    SELECT * FROM t1 JOIN t2 ON t3.a=t2.b;
  }
} {1 {no such column: t3.a}}

# EVIDENCE-OF: R-47973-48020 you cannot say "INNER OUTER JOIN", because
# that would be contradictory.
do_test vtab6-3.7 {
  catchsql {
    SELECT * FROM t1 INNER OUTER JOIN t2;
  }
} {1 {unknown or unsupported join type: INNER OUTER}}
} {1 {unknown join type: INNER OUTER}}

do_test vtab6-3.7 {
  catchsql {
    SELECT * FROM t1 LEFT BOGUS JOIN t2;
  }
} {1 {unknown or unsupported join type: LEFT BOGUS}}
} {1 {unknown join type: LEFT BOGUS}}

do_test vtab6-4.1 {
  execsql {
    BEGIN;
    INSERT INTO t6 VALUES(NULL);
    INSERT INTO t6 VALUES(NULL);
    INSERT INTO t6 SELECT * FROM t6;
347
348
349
350
351
352
353

354
355
356
357
358
359
360
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365







+







    SELECT * FROM t6, t5 WHERE t6.a>t5.a;
  }
} {}

# A test for ticket #247.
#
do_test vtab6-7.1 {
  sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1
  execsql {
    INSERT INTO t7 VALUES ("pa1", 1);
    INSERT INTO t7 VALUES ("pa2", NULL);
    INSERT INTO t7 VALUES ("pa3", NULL);
    INSERT INTO t7 VALUES ("pa4", 2);
    INSERT INTO t7 VALUES ("pa30", 131);
    INSERT INTO t7 VALUES ("pa31", 130);

Changes to test/vtabA.test.

124
125
126
127
128
129
130
131

132
133
134
135
136
137
138
124
125
126
127
128
129
130

131
132
133
134
135
136
137
138







-
+







    lappend ret [get_decltype t1e $c]
  }
  set ret
}

do_test vtabA-2.1 {
  analyse_parse {(a text, b integer hidden, c hidden)} {a b c}
} {a text integer {}}
} {a TEXT integer {}}

do_test vtabA-2.2 {
  analyse_parse {(a hidden   , b integerhidden, c hidden1)} {a b c}
} {{b c} {} integerhidden hidden1}

do_test vtabA-2.3 {
  analyse_parse {(a HiDden, b HIDDEN, c hidden)} {a b c}

Changes to test/vtabH.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
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







+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








do_execsql_test 1.0 {
  CREATE TABLE t6(a, b TEXT);
  CREATE INDEX i6 ON t6(b, a);
  CREATE VIRTUAL TABLE e6 USING echo(t6);
}

ifcapable !icu {
foreach {tn sql expect} {
  1 "SELECT * FROM e6 WHERE b LIKE '8abc'" {
    xBestIndex {SELECT rowid, a, b FROM 't6' WHERE b like ?}
    xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8abc
  }

  2 "SELECT * FROM e6 WHERE b GLOB '8abc'" {
    xBestIndex {SELECT rowid, a, b FROM 't6' WHERE b glob ?}
    xFilter {SELECT rowid, a, b FROM 't6' WHERE b glob ?} 8abc
  }
} {
  do_test 1.$tn {
    set echo_module {}
    execsql $sql
    set ::echo_module
  } [list {*}$expect]
  foreach {tn sql expect} {
    1 "SELECT * FROM e6 WHERE b LIKE '8abc'" {
      xBestIndex 
         {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?}
      xFilter
         {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?}
         8ABC 8abd 8abc
    }
  
    2 "SELECT * FROM e6 WHERE b GLOB '8abc'" {
       xBestIndex
         {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b glob ?}
       xFilter
         {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b glob ?}
         8abc 8abd 8abc
    }
    3 "SELECT * FROM e6 WHERE b LIKE '8e/'" {
      xBestIndex {SELECT rowid, a, b FROM 't6' WHERE b like ?}
      xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8e/
    }
    4 "SELECT * FROM e6 WHERE b GLOB '8e/'" {
      xBestIndex {SELECT rowid, a, b FROM 't6' WHERE b glob ?}
      xFilter {SELECT rowid, a, b FROM 't6' WHERE b glob ?} 8e/
    }
  } {
    do_test 1.$tn {
      set echo_module {}
      execsql $sql
      set ::echo_module
    } [list {*}$expect]
  }
}


#--------------------------------------------------------------------------

register_tclvar_module db
set ::xyz 10

Changes to test/vtabJ.test.

117
118
119
120
121
122
123




























124
125
126
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



  SELECT name, value FROM tclvar where name = 'xx';
} {xx att}

do_execsql_test 181 {
  DELETE FROM tclvar WHERE name BETWEEN 'xx' AND 'xx' OR name='xx';
  SELECT name, value FROM tclvar where name = 'xx';
} {}

#-------------------------------------------------------------------------

do_execsql_test 200 {
  CREATE TABLE var(k TEXT, v TEXT);
  INSERT INTO var VALUES('testvar1', 10);
  INSERT INTO var VALUES('testvar2', 20);
  INSERT INTO var VALUES('testvar3', 30);
}

do_test 210 {
  foreach {testvar1 testvar2 testvar3} {1 2 3} {}
  execsql {
    UPDATE tclvar SET value = var.v FROM var WHERE name = var.k;
  }
  list $testvar1 $testvar2 $testvar3
} {10 20 30}

do_test 220 {
  execsql {
    CREATE TABLE nam(k TEXT, v TEXT);
    INSERT INTO nam VALUES('testvar1', 'tv1');
    INSERT INTO nam VALUES('testvar2', 'tv2');
    INSERT INTO nam VALUES('testvar3', 'tv3');
    UPDATE tclvar SET fullname = nam.v FROM nam WHERE name = nam.k;
  }
  list $tv1 $tv2 $tv3
} {10 20 30}


finish_test

Added test/vtabK.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2020-09-24
#
# 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 tests for a strange scenario discovered by
# dbsqlfuzz (0ad6d441f9bf3dfc32626a9900bc1700495b16f9) in which a
# virtual table is named "sqlite_stat1".
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix vtabK

ifcapable !vtab||!rtree||!fts5 {
  finish_test
  return
}

do_execsql_test 100 {
  CREATE TABLE t1(x);
  INSERT INTO t1 VALUES(123);
  PRAGMA writable_schema=ON;
  CREATE VIRTUAL TABLE sqlite_stat1 USING fts5(a);
  PRAGMA writable_schema=OFF;
  CREATE VIRTUAL TABLE t3 USING fts5(b);
  INSERT INTO t3 VALUES('this is a test');
}
do_catchsql_test 110 {
  CREATE VIRTUAL TABLE t2 USING rtree(id,x,y);
} {1 {no such column: stat}}
do_execsql_test 120 {
  SELECT * FROM t1;
} {123}
do_execsql_test 130 {
  INSERT INTO t3(b) VALUES('Four score and seven years ago');
  SELECT * FROM t3 WHERE t3 MATCH 'this';
} {{this is a test}}
do_execsql_test 140 {
  SELECT * FROM t3 WHERE t3 MATCH 'four seven';
} {{Four score and seven years ago}}
do_execsql_test 150 {
  INSERT INTO sqlite_stat1(a)
  VALUES('We hold these truths to be self-evident...');
  SELECT * FROM sqlite_stat1;
} {{We hold these truths to be self-evident...}}
do_catchsql_test 160 {
  ANALYZE;
} {1 {database disk image is malformed}}
do_execsql_test 170 {
  PRAGMA integrity_check;
} {ok}

# Follow-on dbsqlfuzz bc02a0cde82dee801a8d6f653d2831680f87dca1
reset_db
do_execsql_test 200 {
  CREATE TABLE t1(a);
  INSERT INTO t1 VALUES('Ebed-malech');
  CREATE TABLE x(a);
  PRAGMA writable_schema=ON;
  CREATE VIRTUAL TABLE sqlite_stat1 USING fts5(a);
} {}
do_catchsql_test 210 {
  CREATE VIRTUAL TABLE t2 USING rtree(id,x,y);
} {1 {no such column: stat}}
do_execsql_test 220 {
  SELECT * FROM t1;
} {Ebed-malech}

# Follow-on dbsqlfuzz a097eaad43c3c845b236126df92fb49b25449b0c
reset_db
do_catchsql_test 300 {
  CREATE VIRTUAL TABLE t1 USING rtree(a,b,c);
  CREATE TABLE t2(x);
  ALTER TABLE t2 ADD d GENERATED ALWAYS AS (c IN (SELECT 1 FROM t1)) VIRTUAL;
} {1 {error in table t2 after add column: subqueries prohibited in generated columns}}
  
finish_test

Added test/vtabdistinct.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022-01-21
#
# 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 tests for sqlite3_vtab_distinct() interface.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix vtabdistinct

ifcapable !vtab {
  finish_test
  return
}
load_static_extension db qpvtab

do_execsql_test 1.1 {
  SELECT ix FROM qpvtab WHERE vn='sqlite3_vtab_distinct';
} {0}
do_execsql_test 1.2 {
  SELECT DISTINCT ix FROM qpvtab WHERE vn='sqlite3_vtab_distinct';
} {2}
do_execsql_test 1.3 {
  SELECT distinct vn, ix FROM qpvtab(3)
   WHERE +vn IN ('sqlite3_vtab_distinct','nOrderBy');
} {nOrderBy 2 sqlite3_vtab_distinct 2}
do_execsql_test 1.4 {
  SELECT vn, ix FROM qpvtab
   GROUP BY vn
  HAVING vn='sqlite3_vtab_distinct';
} {sqlite3_vtab_distinct 1}

finish_test

Added test/vtabdrop.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2018 December 28
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# The tests in this file test edge cases surrounding DROP TABLE on 
# virtual tables.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable !vtab { finish_test ; return }
source $testdir/fts3_common.tcl
source $testdir/malloc_common.tcl

set testprefix vtabdrop

#-------------------------------------------------------------------------
# Test that if a DROP TABLE is executed against an rtree table, but the
# xDestroy() call fails, the rtree table is not dropped, the sqlite_master
# table is not modified and the internal schema remains intact.
# 
ifcapable rtree {
  do_execsql_test 1.0 {
    CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2);
    CREATE TABLE t1(x, y);
    INSERT INTO t1 VALUES(1, 2);
  }
  
  do_test 1.1 {
    execsql {
      BEGIN;
        INSERT INTO t1 VALUES(3, 4);
    }
    db eval { SELECT * FROM t1 } {
      catchsql { DROP TABLE rt }
    }
    execsql COMMIT
  } {}
  
  do_execsql_test 1.2 {
    SELECT name FROM sqlite_master ORDER BY 1;
    SELECT * FROM t1;
    SELECT * FROM rt;
  } {rt rt_node rt_parent rt_rowid t1 1 2 3 4}
  
  db close
  sqlite3 db test.db
  
  do_execsql_test 1.3 {
    SELECT name FROM sqlite_master ORDER BY 1;
  } {rt rt_node rt_parent rt_rowid t1}
}

#-------------------------------------------------------------------------
# Same as tests 1.*, except with fts5 instead of rtree.
# 
ifcapable fts5 {
  reset_db
  do_execsql_test 2.0 {
    CREATE VIRTUAL TABLE ft USING fts5(x);
    CREATE TABLE t1(x, y);
    INSERT INTO t1 VALUES(1, 2);
  }
  
  do_test 2.1 {
    execsql {
      BEGIN;
        INSERT INTO t1 VALUES(3, 4);
    }
    db eval { SELECT * FROM t1 } {
      catchsql { DROP TABLE ft }
    }
    execsql COMMIT
  } {}
  
  do_execsql_test 2.2 {
    SELECT name FROM sqlite_master ORDER BY 1;
  } {ft ft_config ft_content ft_data ft_docsize ft_idx t1}
  
  db close
  sqlite3 db test.db
  
  do_execsql_test 2.3 {
    SELECT name FROM sqlite_master ORDER BY 1;
  } {ft ft_config ft_content ft_data ft_docsize ft_idx t1}
}

#-------------------------------------------------------------------------
# Same as tests 1.*, except with fts3 instead of rtree.
# 
ifcapable fts3 {
  reset_db
  do_execsql_test 2.0 {
    CREATE VIRTUAL TABLE ft USING fts3(x);
    CREATE TABLE t1(x, y);
    INSERT INTO t1 VALUES(1, 2);
  }
  
  do_test 2.1 {
    execsql {
      BEGIN;
        INSERT INTO t1 VALUES(3, 4);
    }
    db eval { SELECT * FROM t1 } {
      catchsql { DROP TABLE ft }
    }
    execsql COMMIT
  } {}
  
  do_execsql_test 2.2 {
    SELECT name FROM sqlite_master ORDER BY 1;
  } {ft ft_content ft_segdir ft_segments sqlite_autoindex_ft_segdir_1 t1}
  
  db close
  sqlite3 db test.db
  
  do_execsql_test 2.3 {
    SELECT name FROM sqlite_master ORDER BY 1;
  } {ft ft_content ft_segdir ft_segments sqlite_autoindex_ft_segdir_1 t1}
}

finish_test

Added test/vtabrhs1.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022-01-20
#
# 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 tests for sqlite3_vtab_rhs_value() interface.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix vtabrhs1

ifcapable !vtab {
  finish_test
  return
}
load_static_extension db qpvtab

# EVIDENCE-OF: R-60223-49197 When the sqlite3_vtab_rhs_value(P,J,V)
# interface is invoked from within the xBestIndex method of a virtual
# table implementation, with P being a copy of the sqlite3_index_info
# object pointer passed into xBestIndex and J being a 0-based index into
# P->aConstraint[], then this routine attempts to set *V to the value
# of the right-hand operand of that constraint if the right-hand operand
# is known.
#
do_execsql_test 1.1 {
  SELECT rhs FROM qpvtab
   WHERE cn='a'
     AND a=12345
} {12345}
do_execsql_test 1.2 {
  SELECT rhs FROM qpvtab
   WHERE cn='a'
     AND a<>4.5
} {4.5}
do_execsql_test 1.3 {
  SELECT rhs FROM qpvtab
   WHERE cn='a'
     AND 'quokka' < a
} {'quokka'}
do_execsql_test 1.4 {
  SELECT rhs FROM qpvtab
   WHERE cn='a'
     AND a IS NULL
} {{}}
do_execsql_test 1.5 {
  SELECT rhs FROM qpvtab
   WHERE cn='a'
     AND a GLOB x'0123'
} {x'0123'}

# EVIDENCE-OF: R-37799-62852 If the right-hand operand is not known,
# then *V is set to a NULL pointer.
#
do_execsql_test 2.1 {
  SELECT typeof(rhs) FROM qpvtab WHERE cn='a' AND a=format('abc');
} {null}
do_execsql_test 2.2 {
  SELECT typeof(rhs) FROM qpvtab WHERE cn='a' AND a=?2
} {null}

# EVIDENCE-OF: R-14553-25174 When xBestIndex returns, the sqlite3_value
# object returned by sqlite3_vtab_rhs_value() is automatically
# deallocated.
#
# Where this not the case, the following "finish_test" statement would
# report a memory leak.
#
finish_test

Changes to test/wal.test.

39
40
41
42
43
44
45

46
47
48
49
50
51
52
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53







+







proc sqlite3_wal {args} {
  eval sqlite3 $args
  [lindex $args 0] eval { PRAGMA auto_vacuum = 0 }
  [lindex $args 0] eval { PRAGMA page_size = 1024 }
  [lindex $args 0] eval { PRAGMA journal_mode = wal }
  [lindex $args 0] eval { PRAGMA synchronous = normal }
  [lindex $args 0] function blob blob
  db timeout 1000
}

proc log_deleted {logfile} {
  return [expr [file exists $logfile]==0]
}

#
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
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







-
+









-
+






-
+







  5   2048    1
  6   4096    1
  7   8192    1
  8  16384    1
  9  32768    1
 10  65536    1
 11 131072    0
 11   1016    0
 12   1016    0
} {

  if {$::SQLITE_MAX_PAGE_SIZE < $pgsz} {
    set works 0
  }

  for {set pg 1} {$pg <= 3} {incr pg} {
    forcecopy testX.db test.db
    forcedelete test.db-wal
  

    # Check that the database now exists and consists of three pages. And
    # that there is no associated wal file.
    #
    do_test wal-18.2.$tn.$pg.1 { file exists test.db-wal } 0
    do_test wal-18.2.$tn.$pg.2 { file exists test.db } 1
    do_test wal-18.2.$tn.$pg.3 { file size test.db } [expr 1024*3]
  

    do_test wal-18.2.$tn.$pg.4 {

      # Create a wal file that contains a single frame (database page
      # number $pg) with the commit flag set. The frame checksum is
      # correct, but the contents of the database page are corrupt.
      #
      # The page-size in the log file header is set to $pgsz. If the
1219
1220
1221
1222
1223
1224
1225
1226

1227
1228
1229

1230
1231
1232
1233
1234
1235

1236
1237
1238
1239
1240
1241
1242
1220
1221
1222
1223
1224
1225
1226

1227
1228
1229

1230
1231
1232
1233
1234
1235

1236
1237
1238
1239
1240
1241
1242
1243







-
+


-
+





-
+








      set fd [open test.db-wal w]
      fconfigure $fd -encoding binary -translation binary
      puts -nonewline $fd $walhdr
      puts -nonewline $fd $framehdr
      puts -nonewline $fd $framebody
      close $fd
  

      file size test.db-wal
    } [wal_file_size 1 $pgsz]
  

    do_test wal-18.2.$tn.$pg.5 {
      sqlite3 db test.db
      set rc [catch { db one {PRAGMA integrity_check} } msg]
      expr { $rc!=0 || $msg!="ok" }
    } $works
  
 
    db close
  }
}

#-------------------------------------------------------------------------
# The following test - wal-19.* - fixes a bug that was present during
# development.
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344














































1345
1346
1347
1348
1349
1350
1351
1294
1295
1296
1297
1298
1299
1300
1301













































1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354







+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







#
#   3. Using connection 1, checkpoint the database. Make sure all
#      the data is present and the database is not corrupt.
#
# At one point, SQLite was failing to grow the mapping of the wal-index
# file in step 3 and the checkpoint was corrupting the database file.
#
if {[permutation]!="unix-excl"} {
do_test wal-20.1 {
  catch {db close}
  forcedelete test.db test.db-wal test.db-journal
  sqlite3 db test.db
  execsql {
    PRAGMA journal_mode = WAL;
    CREATE TABLE t1(x);
    INSERT INTO t1 VALUES(randomblob(900));
    SELECT count(*) FROM t1;
  }
} {wal 1}
do_test wal-20.2 {
  set ::buddy [launch_testfixture]
  testfixture $::buddy {
    sqlite3 db test.db
    db transaction { db eval {
      PRAGMA wal_autocheckpoint = 0;
      INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 2 */
      INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 4 */
      INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 8 */
      INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 16 */
      INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 32 */
      INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 64 */
      INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 128 */
      INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 256 */
      INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 512 */
      INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 1024 */
      INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 2048 */
      INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 4096 */
      INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 8192 */
      INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 16384 */
    } }
  }
} {0}
do_test wal-20.3 {
  close $::buddy
  execsql { PRAGMA wal_checkpoint }
  execsql { SELECT count(*) FROM t1 }
} {16384}
do_test wal-20.4 {
  db close
  sqlite3 db test.db
  execsql { SELECT count(*) FROM t1 }
} {16384}
integrity_check wal-20.5
  do_test wal-20.1 {
    catch {db close}
    forcedelete test.db test.db-wal test.db-journal
    sqlite3 db test.db
    execsql {
      PRAGMA journal_mode = WAL;
      CREATE TABLE t1(x);
      INSERT INTO t1 VALUES(randomblob(900));
      SELECT count(*) FROM t1;
    }
  } {wal 1}
  do_test wal-20.2 {
    set ::buddy [launch_testfixture]
    testfixture $::buddy {
      sqlite3 db test.db
      db transaction { db eval {
        PRAGMA wal_autocheckpoint = 0;
        INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 2 */
        INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 4 */
        INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 8 */
        INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 16 */
        INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 32 */
        INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 64 */
        INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 128 */
        INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 256 */
        INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 512 */
        INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 1024 */
        INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 2048 */
        INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 4096 */
        INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 8192 */
        INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 16384 */
      } }
    }
  } {0}
  do_test wal-20.3 {
    close $::buddy
    execsql { PRAGMA wal_checkpoint }
    execsql { SELECT count(*) FROM t1 }
  } {16384}
  do_test wal-20.4 {
    db close
    sqlite3 db test.db
    execsql { SELECT count(*) FROM t1 }
  } {16384}
  integrity_check wal-20.5
}

catch { db2 close }
catch { db close }

do_test wal-21.1 {
  faultsim_delete_and_reopen
  execsql { 
1507
1508
1509
1510
1511
1512
1513
1514































1515
1516
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
1546
1547
1548
1549
1550








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


  sqlite3 db test.db
  do_test wal-25.$mode {
    db eval "PRAGMA journal_mode=$mode"
    db eval {ATTACH 'test2.db' AS t2; PRAGMA journal_mode=WAL;}
  } {wal}
  db close
}

# 2021-03-10 forum post https://sqlite.org/forum/forumpost/a006d86f72
#
file delete test.db
sqlite3 db test.db
db eval {PRAGMA journal_mode=WAL}
for {set i 0} {$i<$SQLITE_MAX_ATTACHED} {incr i} {
  do_test wal-26.1.$i {
    file delete attached-$i.db
    db eval "ATTACH 'attached-$i.db' AS a$i;"
    db eval "PRAGMA a$i.journal_mode=WAL;"
    db eval "CREATE TABLE a$i.t$i (x);"
    db eval "INSERT INTO t$i VALUES(zeroblob(10000));"
    db eval "DELETE FROM t$i;"
    db eval "INSERT INTO t$i VALUES(randomblob(10000));"
    expr {[file size attached-$i.db-wal]>10000}
  } {1}
}
for {set i [expr {$SQLITE_MAX_ATTACHED-1}]} {$i>=0} {incr i -1} {
  do_test wal-26.2.$i {
    db eval "PRAGMA a$i.wal_checkpoint(TRUNCATE);"
    file size attached-$i.db-wal
  } {0}
  for {set j 0} {$j<$i} {incr j} {
    do_test wal-26.2.$i.$j {
      expr {[file size attached-$j.db-wal]>10000}
    } {1}
  }
}
db close


test_restore_config_pagecache
finish_test

Changes to test/wal2.test.

81
82
83
84
85
86
87
88
89






90
91
92
93
94
95
96
81
82
83
84
85
86
87


88
89
90
91
92
93
94
95
96
97
98
99
100







-
-
+
+
+
+
+
+







  }
} {4 10}
do_test wal2-1.1 {
  execsql { SELECT count(a), sum(a) FROM t1 } db2
} {4 10}

set RECOVER [list                                      \
  {0 1 lock exclusive}   {1 2 lock exclusive} {4 4 lock exclusive} \
  {1 2 unlock exclusive} {4 4 unlock exclusive} {0 1 unlock exclusive}  \
  {0 1 lock exclusive}   {1 2 lock exclusive}          \
  {4 1 lock exclusive}   {4 1 unlock exclusive}        \
  {5 1 lock exclusive}   {5 1 unlock exclusive}        \
  {6 1 lock exclusive}   {6 1 unlock exclusive}        \
  {7 1 lock exclusive}   {7 1 unlock exclusive}        \
  {1 2 unlock exclusive} {0 1 unlock exclusive}        \
]
set READ [list                                         \
  {4 1 lock shared}    {4 1 unlock shared}             \
]
set INITSLOT [list                                     \
  {4 1 lock exclusive} {4 1 unlock exclusive}          \
]
353
354
355
356
357
358
359
360









361
362

363
364
365
366
367
368
369
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







-
+
+
+
+
+
+
+
+
+

-
+







# required the client grabs all exclusive locks (just as it would for a
# recovery performed as a pre-cursor to a normal database transaction).
#
set expected_locks [list]
lappend expected_locks {1 1 lock exclusive}   ;# Lock checkpoint
lappend expected_locks {0 1 lock exclusive}   ;# Lock writer
lappend expected_locks {2 1 lock exclusive}   ;# Lock recovery
lappend expected_locks {4 4 lock exclusive}   ;# Lock all aReadMark[]
# lappend expected_locks {4 4 lock exclusive}   ;# Lock all aReadMark[]
lappend expected_locks {4 1 lock exclusive}   ;# Lock aReadMark[1]
lappend expected_locks {4 1 unlock exclusive} ;# Unlock aReadMark[1]
lappend expected_locks {5 1 lock exclusive}  
lappend expected_locks {5 1 unlock exclusive}
lappend expected_locks {6 1 lock exclusive} 
lappend expected_locks {6 1 unlock exclusive}
lappend expected_locks {7 1 lock exclusive} 
lappend expected_locks {7 1 unlock exclusive}
lappend expected_locks {2 1 unlock exclusive} ;# Unlock recovery 
lappend expected_locks {4 4 unlock exclusive} ;# Unlock all aReadMark[] 
# lappend expected_locks {4 4 unlock exclusive} ;# Unlock all aReadMark[] 
lappend expected_locks {0 1 unlock exclusive} ;# Unlock writer
lappend expected_locks {3 1 lock exclusive}   ;# Lock aReadMark[0]
lappend expected_locks {3 1 unlock exclusive} ;# Unlock aReadMark[0]
lappend expected_locks {1 1 unlock exclusive} ;# Unlock checkpoint
do_test wal2-5.1 {
  proc tvfs_cb {method args} {
    set ::shm_file [lindex $args 0]
584
585
586
587
588
589
590
591
592






593
594
595
596
597
598
599
596
597
598
599
600
601
602


603
604
605
606
607
608
609
610
611
612
613
614
615







-
-
+
+
+
+
+
+







  testvfs tvfs
  tvfs script tvfs_cb
  sqlite3 db test.db -vfs tvfs
  set {} {}
} {}

set RECOVERY {
  {0 1 lock exclusive} {1 2 lock exclusive} {4 4 lock exclusive}
  {1 2 unlock exclusive} {4 4 unlock exclusive} {0 1 unlock exclusive}
  {0 1 lock exclusive}   {1 2 lock exclusive}
  {4 1 lock exclusive}   {4 1 unlock exclusive}
  {5 1 lock exclusive}   {5 1 unlock exclusive}
  {6 1 lock exclusive}   {6 1 unlock exclusive}
  {7 1 lock exclusive}   {7 1 unlock exclusive}
  {1 2 unlock exclusive} {0 1 unlock exclusive}
}
set READMARK0_READ {
  {3 1 lock shared} {3 1 unlock shared}
}
set READMARK0_WRITE {
  {3 1 lock shared} 
  {0 1 lock exclusive} {3 1 unlock shared} 
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
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







-
+










-
+
+







   2 00666
   3 00600
   4 00755
  } {
    set effective [format %.5o [expr $permissions & ~$umask]]
    do_test wal2-12.2.$tn.1 {
      file attributes test.db -permissions $permissions
      file attributes test.db -permissions
      string map {o 0} [file attributes test.db -permissions]
    } $permissions
    do_test wal2-12.2.$tn.2 {
      list [file exists test.db-wal] [file exists test.db-shm]
    } {0 0}
    do_test wal2-12.2.$tn.3 {
      sqlite3 db test.db
      execsql { INSERT INTO tx DEFAULT VALUES }
      list [file exists test.db-wal] [file exists test.db-shm]
    } {1 1}
    do_test wal2-12.2.$tn.4 {
      list [file attr test.db-wal -perm] [file attr test.db-shm -perm]
      set x [list [file attr test.db-wal -perm] [file attr test.db-shm -perm]]
      string map {o 0} $x
    } [list $effective $effective]
    do_test wal2-12.2.$tn.5 {
      db close
      list [file exists test.db-wal] [file exists test.db-shm]
    } {0 0}
  }
}
1113
1114
1115
1116
1117
1118
1119

1120
1121
1122
1123
1124
1125
1126
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144







+







      file attr test.db     -perm $db_perm
      file attr test.db-wal -perm $wal_perm
      file attr test.db-shm -perm $shm_perm

      set     L [file attr test.db -perm]
      lappend L [file attr test.db-wal -perm]
      lappend L [file attr test.db-shm -perm]
      string map {o 0} $L
    } [list $db_perm $wal_perm $shm_perm]

    # If $can_open is true, then it should be possible to open a database
    # handle. Otherwise, if $can_open is 0, attempting to open the db
    # handle throws an "unable to open database file" exception.
    #
    set r(1) {0 ok}

Added test/wal2big.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2017 September 19
#
# 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 the operation of the library in
# "PRAGMA journal_mode=WAL2" mode.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/malloc_common.tcl
source $testdir/wal_common.tcl

set testprefix wal2big
ifcapable !wal {finish_test ; return }

do_execsql_test 1.0 {
  CREATE TABLE t1(a, b, c);
  CREATE INDEX t1a ON t1(a);
  CREATE INDEX t1b ON t1(b);
  CREATE INDEX t1c ON t1(c);
  PRAGMA journal_mode = wal2;
  PRAGMA journal_size_limit = 10000000;

  WITH s(i) AS (
    SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<200000
  )
  INSERT INTO t1 SELECT random(), random(), random() FROM s;
} {wal2 10000000}

do_execsql_test 1.1 {
  WITH s(i) AS (
    SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<200000
  )
  INSERT INTO t1 SELECT random(), random(), random() FROM s;
}

do_test 1.2 {
  list [expr [file size test.db-wal]>10000000] \
       [expr [file size test.db-wal2]>10000000]
} {1 1}

do_test 1.3 {
  sqlite3 db2 test.db
  execsql {
    SELECT count(*) FROM t1;
    PRAGMA integrity_check;
  } db2
} {400000 ok}

do_test 1.4 {
  db2 close
  forcecopy test.db test.db2
  forcecopy test.db-wal test.db2-wal
  forcecopy test.db-wal2 test.db2-wal2
  sqlite3 db2 test.db2
  execsql {
    SELECT count(*) FROM t1;
    PRAGMA integrity_check;
  }
} {400000 ok}

finish_test

Added test/wal2concurrent.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2018 December 6
#
# 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 wal2concurrent

ifcapable !concurrent {
  finish_test
  return
}


#-------------------------------------------------------------------------
# Warm-body test.
#
foreach tn {1 2} {
  reset_db
  sqlite3 db2 test.db
  do_execsql_test 1.0 {
    PRAGMA page_size = 1024;
    CREATE TABLE t1(x);
    CREATE TABLE t2(y);
    PRAGMA journal_size_limit = 5000;
    PRAGMA journal_mode = wal2;
  } {5000 wal2}
  
  do_execsql_test 1.1 {
    INSERT INTO t1 VALUES(1);
    BEGIN CONCURRENT;
      INSERT INTO t1 VALUES(2);
  } {}
  
  do_test 1.2 {
    execsql { 
      PRAGMA journal_size_limit = 5000;
      INSERT INTO t1 VALUES(3) 
    } db2
    catchsql { COMMIT }
  } {1 {database is locked}}
  
  do_catchsql_test 1.3 { COMMIT   } {1 {database is locked}}
  do_catchsql_test 1.4 { ROLLBACK } {0 {}}
  
  do_test 1.5 {
    list [file size test.db-wal] [file size test.db-wal2]
  } {2128 0}
  
  do_execsql_test 1.6 {
    BEGIN CONCURRENT;
      INSERT INTO t1 VALUES(2);
  } {}
  
  do_test 1.7 {
    execsql { INSERT INTO t2 VALUES(randomblob(4000)) } db2
    list [file size test.db-wal] [file size test.db-wal2]
  } {7368 0}
  
  if {$tn==1} {
    do_test 1.8 {
      execsql { 
        INSERT INTO t2 VALUES(1);
        INSERT INTO t1 VALUES(5);
      } db2
      list [file size test.db-wal] [file size test.db-wal2]
    } {7368 2128}

    do_catchsql_test 1.9  { COMMIT   } {1 {database is locked}}
    do_catchsql_test 1.10 { ROLLBACK } {0 {}}
    db close
    sqlite3 db test.db
    do_execsql_test 1.11 { SELECT * FROM t1 } {1 3 5}
    do_execsql_test 1.12 { SELECT count(*) FROM t2 } {2}
  } else {
    do_test 1.8 {
      execsql { 
        INSERT INTO t2 VALUES(1);
      } db2
      list [file size test.db-wal] [file size test.db-wal2]
    } {7368 1080}

    do_catchsql_test 1.9  { COMMIT   } {0 {}}
    db close
    sqlite3 db test.db
    do_execsql_test 1.11 { SELECT * FROM t1 } {1 3 2}
    do_execsql_test 1.12 { SELECT count(*) FROM t2 } {2}

    do_test 1.13 {
      list [file size test.db-wal] [file size test.db-wal2]
    } {7368 2128}
  }
}

do_multiclient_test tn {
  do_test 2.$tn.1 {
    sql1 {
      PRAGMA auto_vacuum = OFF;
      CREATE TABLE t1(x UNIQUE);
      CREATE TABLE t2(x UNIQUE);
      PRAGMA journal_mode = wal2;
      PRAGMA journal_size_limit = 15000;
    }
  } {wal2 15000}

  do_test 2.$tn.2 {
    sql1 {
      WITH s(i) AS (
        SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<=10
      )
      INSERT INTO t1 SELECT randomblob(800) FROM s;
    }
  } {}

  do_test 2.$tn.3 {
    sql1 { DELETE FROM t1 WHERE (rowid%4)==0 }
    list [expr [file size test.db-wal]>15000] \
         [expr [file size test.db-wal2]>15000]
  } {1 0}

  do_test 2.$tn.4 {
    sql1 { PRAGMA wal_checkpoint; }
    sql1 { 
      BEGIN CONCURRENT;
        INSERT INTO t1 VALUES(randomblob(800));
    }
  } {}

  do_test 2.$tn.5 {
    sql2 { 
      PRAGMA journal_size_limit = 15000;
      INSERT INTO t2 VALUES(randomblob(800));
      INSERT INTO t2 VALUES(randomblob(800));
      INSERT INTO t2 VALUES(randomblob(800));
      INSERT INTO t2 VALUES(randomblob(800));
      INSERT INTO t2 VALUES(randomblob(800));
      DELETE FROM t2;
    }
    list [expr [file size test.db-wal]>15000] \
         [expr [file size test.db-wal2]>15000]
  } {1 1}

  do_test 2.$tn.6 {
    sql1 { 
        INSERT INTO t1 VALUES(randomblob(800));
      COMMIT;
      PRAGMA integrity_check;
    }
  } {ok}
}



finish_test

Added test/wal2fault.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2010 May 03
#
# 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 the operation of the library in
# "PRAGMA journal_mode=WAL" mode.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/malloc_common.tcl
source $testdir/lock_common.tcl

ifcapable !wal {finish_test ; return }
set testprefix wal2fault

do_execsql_test 1.0 {
  CREATE TABLE t1(x,y);
  PRAGMA journal_mode = wal2;
  WITH s(i) AS ( SELECT 100 UNION ALL SELECT i-1 FROM s WHERE (i-1)>0 )
  INSERT INTO t1 SELECT i, randomblob(i) FROM s;
  WITH s(i) AS ( SELECT 100 UNION ALL SELECT i-1 FROM s WHERE (i-1)>0 )
  INSERT INTO t1 SELECT i, randomblob(i) FROM s;
} {wal2}

do_test 1.1 {
  expr [file size test.db-wal]>10000
} {1}
faultsim_save_and_close

do_faultsim_test 1 -prep {
  faultsim_restore_and_reopen
  execsql {
    PRAGMA journal_size_limit = 10000;
    SELECT count(*) FROM sqlite_master;
  }
} -body {
  execsql {
    INSERT INTO t1 VALUES(1, 2);
  }
} -test {
  faultsim_test_result {0 {}}
}

finish_test

Added test/wal2lock.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2018 December 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 the operation of the library in
# "PRAGMA journal_mode=WAL2" mode.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/malloc_common.tcl
source $testdir/wal_common.tcl

set testprefix wal2lock
ifcapable !wal {finish_test ; return }

db close
testvfs tvfs 
sqlite3 db test.db -vfs tvfs

do_execsql_test 1.0 {
  PRAGMA journal_mode = wal2;
  CREATE TABLE y1(y, yy);
  CREATE INDEX y1y ON y1(y);
  CREATE INDEX y1yy ON y1(yy);
  INSERT INTO y1 VALUES(1, 2), (3, 4), (5, 6);
} {wal2}

tvfs script vfs_callback
tvfs filter xShmLock

set ::lock [list]
proc vfs_callback {func file name lock} {
  lappend ::lock $lock
  return SQLITE_OK
}

do_execsql_test 1.1.1 {
  SELECT * FROM y1
} {1 2 3 4 5 6}
do_test 1.1.2 {
  set ::lock
} {{4 1 lock shared} {4 1 unlock shared}}

set ::bFirst 1
proc vfs_callback {func file name lock} {
  if {$::bFirst} {
    set ::bFirst 0
    return SQLITE_BUSY
  }
  return SQLITE_OK
}
do_execsql_test 1.2 {
  SELECT * FROM y1
} {1 2 3 4 5 6}

set ::bFirst 1
proc vfs_callback {func file name lock} {
  if {$::bFirst} {
    set ::bFirst 0
    return SQLITE_IOERR
  }
  return SQLITE_OK
}
do_catchsql_test 1.3 {
  SELECT * FROM y1
} {1 {disk I/O error}}

puts "# Warning: This next test case causes SQLite to call xSleep(1) 100 times."
puts "# Normally this equates to a delay of roughly 10 seconds, but if SQLite"
puts "# is built on unix without HAVE_USLEEP defined, it may be much longer."
proc vfs_callback {func file name lock} { return SQLITE_BUSY }
do_catchsql_test 1.4 {
  SELECT * FROM y1
} {1 {locking protocol}}
proc vfs_callback {func file name lock} { return SQLITE_OK }

sqlite3 db2 test.db -vfs tvfs
set ::bFirst 1

proc vfs_callback {func file name lock} {
  if {$::bFirst} {
    set ::bFirst 0
    db2 eval { INSERT INTO y1 VALUES(7, 8) }
  }
}

do_execsql_test 1.5.1 {
  SELECT * FROM y1
} {1 2 3 4 5 6 7 8}
do_execsql_test 1.5.2 {
  SELECT * FROM y1
} {1 2 3 4 5 6 7 8}

db close
db2 close
tvfs delete
finish_test

Added test/wal2openclose.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2017 September 19
#
# 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 the operation of the library in
# "PRAGMA journal_mode=WAL2" mode.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/malloc_common.tcl
source $testdir/wal_common.tcl

set testprefix wal2openclose
ifcapable !wal {finish_test ; return }

do_execsql_test 1.0 {
  CREATE TABLE t1(a, b, c);
  PRAGMA journal_mode = wal2;
  PRAGMA wal_autocheckpoint = 0;
  PRAGMA journal_size_limit = 75000;
} {wal2 0 75000}

do_test 1.1 {
  for {set ii 1} {$ii <= 200} {incr ii} {
    execsql {
      INSERT INTO t1 VALUES($ii, $ii, $ii);
    }
  }
  expr ([file size test.db-wal2] - 75000) > 30000
} {1}

do_test 1.2 {
  db close
  list [file exists test.db-wal] [file exists test.db-wal2]
} {0 0}

sqlite3 db test.db
do_execsql_test 1.3 {
  SELECT sum(c) FROM t1
} {20100}
db close

#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.0 {
  CREATE TABLE t1(a, b, c);
  PRAGMA journal_mode = wal2;
  INSERT INTO t1 VALUES(1, 2, 3);
} {wal2}
db_save_and_close

db_restore_and_reopen
do_execsql_test 2.1 {
  SELECT * FROM t1;
} {1 2 3}

do_test 2.2 {
  sqlite3 db2 test.db
  db2 eval {INSERT INTO t1 VALUES(4, 5, 6)}
  db2 close
} {}

breakpoint
db close
sqlite3 db test.db
do_execsql_test 2.2 {
  SELECT * FROM t1;
} {1 2 3 4 5 6}



finish_test

Added test/wal2recover.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2018 December 13
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the operation of the library in
# "PRAGMA journal_mode=WAL2" mode.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/malloc_common.tcl
source $testdir/wal_common.tcl

set testprefix wal2recover
ifcapable !wal {finish_test ; return }

proc db_copy {from to} {
  forcecopy $from $to
  forcecopy ${from}-wal ${to}-wal
  forcecopy ${from}-wal2 ${to}-wal2
}

do_execsql_test 1.0 {
  CREATE TABLE t1(a, b, c);
  CREATE INDEX t1a ON t1(a);
  CREATE INDEX t1b ON t1(b);
  CREATE INDEX t1c ON t1(c);
  PRAGMA journal_mode = wal2;
  PRAGMA journal_size_limit = 15000;
  PRAGMA wal_autocheckpoint = 0;
} {wal2 15000 0}

do_test 1.1 {
  for {set i 1} {$i <= 1000} {incr i} {
    execsql { INSERT INTO t1 VALUES(random(), random(), random()) }
    db_copy test.db test.db2
    sqlite3 db2 test.db
    set res [execsql {
      SELECT count(*) FROM t1;
      PRAGMA integrity_check;
    } db2]
    db2 close
    if {$res != [list $i ok]} {
      error "failure on iteration $i"
    }
  }
  set {} {}
} {}

#--------------------------------------------------------------------------
reset_db
do_execsql_test 2.0 {
  CREATE TABLE t1(x UNIQUE);
  CREATE TABLE t2(x UNIQUE);
  PRAGMA journal_mode = wal2;
  PRAGMA journal_size_limit = 10000;
  PRAGMA wal_autocheckpoint = 0;
  BEGIN;
    INSERT INTO t1 VALUES(randomblob(4000));
    INSERT INTO t1 VALUES(randomblob(4000));
    INSERT INTO t1 VALUES(randomblob(4000));
  COMMIT;
  BEGIN;
    INSERT INTO t2 VALUES(randomblob(4000));
    INSERT INTO t2 VALUES(randomblob(4000));
    INSERT INTO t2 VALUES(randomblob(4000));
  COMMIT;
} {wal2 10000 0}
do_test 2.0.1 {
  list [file size test.db] [file size test.db-wal] [file size test.db-wal2]
} {5120 28328 28328}

# Test recovery with both wal files intact.
#
do_test 2.1 {
  db_copy test.db test.db2
  sqlite3 db2 test.db2
  execsql {
    SELECT count(*) FROM t1;
    SELECT count(*) FROM t2;
    PRAGMA integrity_check;
  } db2
} {3 3 ok}

do_test 2.2 {
  db2 close
  db_copy test.db test.db2
  hexio_write test.db2-wal 16 12345678
  sqlite3 db2 test.db2
  execsql {
    SELECT count(*) FROM t1;
    SELECT count(*) FROM t2;
  } db2
} {0 3}

do_test 2.3 {
  db2 close
  db_copy test.db test.db2
  hexio_write test.db2-wal2 16 12345678
  sqlite3 db2 test.db2
  execsql {
    SELECT count(*) FROM t1;
    SELECT count(*) FROM t2;
    PRAGMA integrity_check;
  } db2
} {3 0 ok}

do_test 2.4 {
  db2 close
  db_copy test.db test.db2
  forcecopy test.db-wal test.db2-wal2
  sqlite3 db2 test.db2
  execsql {
    SELECT count(*) FROM t1;
    SELECT count(*) FROM t2;
    PRAGMA integrity_check;
  } db2
} {3 0 ok}

do_test 2.5 {
  db2 close
  db_copy test.db test.db2
  forcecopy test.db-wal  test.db2-wal2
  forcecopy test.db-wal2  test.db2-wal
  sqlite3 db2 test.db2
  execsql {
    SELECT count(*) FROM t1;
    SELECT count(*) FROM t2;
    PRAGMA integrity_check;
  } db2
} {3 3 ok}

do_test 2.6 {
  db2 close
  db_copy test.db test.db2
  forcecopy test.db-wal test.db2-wal2
  close [open test.db-wal w]
  sqlite3 db2 test.db2
  execsql {
    SELECT count(*) FROM t1;
    SELECT count(*) FROM t2;
    PRAGMA integrity_check;
  } db2
} {3 0 ok}

do_test 2.7 {
  db2 close
  db_copy test.db test.db2
  forcedelete test.db2-wal
  sqlite3 db2 test.db2
  execsql {
    SELECT count(*) FROM t1;
    SELECT count(*) FROM t2;
    PRAGMA integrity_check;
  } db2
} {0 0 ok}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 3.0 {
  CREATE TABLE t1(a TEXT, b TEXT, c TEXT);
  CREATE INDEX t1a ON t1(a);
  CREATE INDEX t1b ON t1(b);
  CREATE INDEX t1c ON t1(c);
  PRAGMA journal_mode = wal2;
  PRAGMA journal_size_limit = 10000;
  PRAGMA wal_autocheckpoint = 0;
  PRAGMA cache_size = 5;
} {wal2 10000 0}

do_execsql_test 3.1 {
  WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s where i < 200)
  INSERT INTO t1 SELECT i, i, i FROM s;

  INSERT INTO t1 VALUES(201, 201, 201);
} {}

do_test 3.2 {
  list [file size test.db] [file size test.db-wal] [file size test.db-wal2]
} {5120 15752 4224}

do_test 3.3 {
  forcecopy test.db test.db2
  forcecopy test.db-wal test.db2-wal
  forcecopy test.db-wal2 test.db2-wal2
  sqlite3 db2 test.db2
  execsql {
    PRAGMA journal_size_limit = 10000;
    PRAGMA wal_autocheckpoint = 0;
    PRAGMA cache_size = 5;
    BEGIN;
      WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s where i < 200)
      INSERT INTO t1 SELECT i, i, i FROM s;
  } db2
  list [file size test.db2] [file size test.db2-wal] [file size test.db2-wal2]
} {5120 15752 23088}

do_test 3.4 {
  set fd [open test.db2-shm]
  fconfigure $fd -encoding binary -translation binary
  set data [read $fd]
  close $fd

  set fd [open test.db-shm w]
  fconfigure $fd -encoding binary -translation binary
  puts -nonewline $fd $data
  close $fd

  execsql {
    WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s where i < 10)
      INSERT INTO t1 SELECT i, i, i FROM s;
    SELECT count(*) FROM t1;
    PRAGMA integrity_check;
  }
} {211 ok}

do_test 3.5 {
  list [file size test.db] [file size test.db-wal] [file size test.db-wal2]
} {5120 15752 18896}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 4.0 {
  PRAGMA journal_mode = wal2;
  CREATE TABLE xyz(x, y, z);
  INSERT INTO xyz VALUES('x', 'y', 'z');
} {wal2}
db close
do_test 4.1 {
  close [open test.db-wal w]
  file mkdir test.db-wal2
  sqlite3 db test.db
  catchsql { SELECT * FROM xyz }
} {1 {unable to open database file}}
db close
file delete test.db-wal2

do_test 4.2 {
  sqlite3 db test.db
  execsql { 
    INSERT INTO xyz VALUES('a', 'b', 'c');
  }
  forcecopy test.db test.db2
  forcecopy test.db-wal test.db2-wal
  forcedelete test.db2-wal2
  file mkdir test.db2-wal2
  sqlite3 db2 test.db2
  catchsql { SELECT * FROM xyz } db2
} {1 {unable to open database file}}
db2 close
file delete test.db2-wal2


finish_test

Added test/wal2recover2.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2018 December 13
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the operation of the library in
# "PRAGMA journal_mode=WAL2" mode.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/malloc_common.tcl
source $testdir/wal_common.tcl

set testprefix wal2recover2
ifcapable !wal {finish_test ; return }

do_execsql_test 1.0 {
  CREATE TABLE t1(x);
  CREATE TABLE t2(x);
  WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<1500 )
    INSERT INTO t1 SELECT i FROM s;
  WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<1500 )
    INSERT INTO t2 SELECT i FROM s;

  PRAGMA journal_mode = wal2;
  PRAGMA journal_size_limit = 10000;
} {wal2 10000}

set ::L 1125750
set ::M 1126500
set ::H 1127250

do_execsql_test 1.1 {
  UPDATE t1 SET x=x+1;
  UPDATE t2 SET x=x+1 WHERE rowid<=750;

  SELECT sum(x) FROM t1;
  SELECT sum(x) FROM t2;
} [list $H $M]

do_test 1.2 {
  list [file size test.db] [file size test.db-wal] [file size test.db-wal2]
} {31744 14704 7368}

proc cksum {zIn data} {
  if {[string length $zIn]==0} {
    set s0 0
    set s1 0
  } else {
    set s0 [hexio_get_int [string range $zIn 0 7]]
    set s1 [hexio_get_int [string range $zIn 8 15]]
  }
  set n [expr [string length $data] / 8]

  for {set i 0} {$i < $n} {incr i 2} {
    set x0 [hexio_get_int -l [string range $data [expr $i*8]   [expr $i*8+7]]]
    set x1 [hexio_get_int -l [string range $data [expr $i*8+8] [expr $i*8+8+7]]]

    set s0 [expr ($s0 + $x0 + $s1) & 0xFFFFFFFF]
    set s1 [expr ($s1 + $x1 + $s0) & 0xFFFFFFFF]
  }

  return "[hexio_render_int32 $s0][hexio_render_int32 $s1]"
}

proc fix_wal_cksums {file} {
  # Fix the checksum on the wal header.
  set data [hexio_read $file 0 32]
  set cksum [cksum {} [string range $data 0 47]]
  set salt [hexio_read $file 16 8]
  hexio_write $file 24 $cksum

  # Fix the checksums for all pages in the wal file.
  set pgsz [hexio_get_int [hexio_read $file 8 4]]
  set sz [file size $file]
  for {set off 32} {$off < $sz} {incr off [expr $pgsz+24]} {
    set e [hexio_read $file $off 8]
    set cksum [cksum $cksum $e]

    set p [hexio_read $file [expr $off+24] $pgsz]
    set cksum [cksum $cksum $p]

    hexio_write $file [expr $off+8] $salt
    hexio_write $file [expr $off+16] $cksum
  }
}

proc wal_incr_hdrfield {file field} {
  switch -- $field {
    nCkpt { set offset 12 }
    salt0 { set offset 16 }
    salt1 { set offset 20 }
    default {
      error "unknown field $field - should be \"nCkpt\", \"salt0\" or \"salt1\""
    }
  }

  # Increment the value in the wal header.
  set v [hexio_get_int [hexio_read $file $offset 4]]
  incr v
  hexio_write $file $offset [hexio_render_int32 $v]
  
  # Fix various checksums
  fix_wal_cksums $file
}

proc wal_set_nckpt {file val} {
  # Increment the value in the wal header.
  hexio_write $file 12 [hexio_render_int32 $val]
  
  # Fix various checksums
  fix_wal_cksums $file
}

proc wal_set_follow {file prevfile} {
  set pgsz [hexio_get_int [hexio_read $prevfile 8 4]]
  set sz [file size $prevfile]
  set cksum [hexio_read $prevfile [expr $sz-$pgsz-8] 8]

  hexio_write $file 16 $cksum
  fix_wal_cksums $file
}

foreach {tn file field} {
  1 test.db2-wal    salt0
  2 test.db2-wal    salt1
  3 test.db2-wal    nCkpt
  4 test.db2-wal2   salt0
  5 test.db2-wal2   salt1
  6 test.db2-wal2   nCkpt
} {
  do_test 1.3.$tn {
    forcecopy test.db test.db2
    forcecopy test.db-wal test.db2-wal
    forcecopy test.db-wal2 test.db2-wal2
    wal_incr_hdrfield $file $field
    sqlite3 db2 test.db2
    execsql {
      SELECT sum(x) FROM t1;
      SELECT sum(x) FROM t2;
    } db2
  } [list $H $L]
  db2 close
}

do_test 1.4 {
  forcecopy test.db test.db2
  forcecopy test.db-wal2 test.db2-wal
  forcedelete test.db2-wal2
  sqlite3 db2 test.db2
  execsql {
    SELECT sum(x) FROM t1;
    SELECT sum(x) FROM t2;
  } db2
} [list $L $M]

do_test 1.5 {
  forcecopy test.db test.db2
  forcecopy test.db-wal2 test.db2-wal
  forcecopy test.db-wal test.db2-wal2
  sqlite3 db2 test.db2
  execsql {
    SELECT sum(x) FROM t1;
    SELECT sum(x) FROM t2;
  } db2
} [list $H $M]

foreach {tn file field} {
  1 test.db2-wal    salt0
  2 test.db2-wal    salt1
  3 test.db2-wal2   salt0
  4 test.db2-wal2   salt1
} {
  do_test 1.6.$tn {
    forcecopy test.db test.db2
    forcecopy test.db-wal2 test.db2-wal
    forcecopy test.db-wal test.db2-wal2
    wal_incr_hdrfield $file $field
    sqlite3 db2 test.db2
    execsql {
      SELECT sum(x) FROM t1;
      SELECT sum(x) FROM t2;
    } db2
  } [list $H $L]
  db2 close
}

foreach {tn nCkpt1 nCkpt2 res} [list \
  1   2 1   "$H $M"                  \
  2   2 2   "$L $M"                  \
  3   3 1   "$H $L"                  \
  4   15 14 "$H $M"                  \
  5   0 15  "$H $M"                  \
  6   1 15  "$L $M"                  \
] {
  do_test 1.7.$tn {
    forcecopy test.db test.db2
    forcecopy test.db-wal2 test.db2-wal
    forcecopy test.db-wal test.db2-wal2

    wal_set_nckpt test.db2-wal2 $nCkpt2
    wal_set_nckpt test.db2-wal  $nCkpt1
    wal_set_follow test.db2-wal test.db2-wal2


    sqlite3 db2 test.db2
    execsql {
      SELECT sum(x) FROM t1;
      SELECT sum(x) FROM t2;
    } db2
  } $res
  db2 close
}


#-------------------------------------------------------------------------
reset_db
do_execsql_test 1.8.1 {
  PRAGMA autovacuum = 0;
  PRAGMA page_size = 4096;
  CREATE TABLE t1(x);
  CREATE TABLE t2(x);
  WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<1500 )
    INSERT INTO t1 SELECT i FROM s;
  WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<1500 )
    INSERT INTO t2 SELECT i FROM s;

  PRAGMA journal_mode = wal2;
  PRAGMA journal_size_limit = 10000;

  WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<1500 )
    INSERT INTO t2 SELECT i FROM s;
} {wal2 10000}

do_test 1.8.2 {
  list [file size test.db-wal] [file size test.db-wal2]
} {24752 0}

do_execsql_test 1.8.3 { PRAGMA user_version = 123 }
do_test 1.8.4 {
  list [file size test.db-wal] [file size test.db-wal2]
} {24752 4152}

do_test 1.8.5 {
  hexio_write test.db-wal2 [expr 56+16] 0400
  fix_wal_cksums test.db-wal2
} {}

do_test 1.8.6 {
  forcecopy test.db test.db2
  forcecopy test.db-wal test.db2-wal
  forcecopy test.db-wal2 test.db2-wal2
  sqlite3 db2 test.db2
  catchsql { SELECT * FROM sqlite_master } db2
} {1 {malformed database schema (?)}}
db2 close

#-------------------------------------------------------------------------
reset_db
do_execsql_test 1.0 {
  CREATE TABLE t1(a, b, c);
  CREATE INDEX t1a ON t1(a);
  CREATE INDEX t1b ON t1(b);
  CREATE INDEX t1c ON t1(c);
  PRAGMA journal_mode = wal2;

  INSERT INTO t1 VALUES(randomblob(50), randomblob(50), randomblob(50));
  INSERT INTO t1 VALUES(randomblob(50), randomblob(50), randomblob(50));
  INSERT INTO t1 VALUES(randomblob(50), randomblob(50), randomblob(50));
  PRAGMA journal_size_limit = 5000;
  INSERT INTO t1 VALUES(randomblob(50), randomblob(50), randomblob(50));
  INSERT INTO t1 VALUES(randomblob(50), randomblob(50), randomblob(50));
  INSERT INTO t1 VALUES(randomblob(50), randomblob(50), randomblob(50));
  INSERT INTO t1 VALUES(randomblob(50), randomblob(50), randomblob(50));
  INSERT INTO t1 VALUES(randomblob(50), randomblob(50), randomblob(50));
} {wal2 5000}

do_test 2.1 {
  forcecopy test.db test.db2
  forcecopy test.db-wal2 test.db2-wal
  forcecopy test.db-wal test.db2-wal2
  
  hexio_write test.db2-wal 5000 1234567890
} {5}

do_test 2.2 {
  sqlite3 db2 test.db2
  breakpoint
  execsql {
    SELECT count(*) FROM t1;
    PRAGMA integrity_check
  } db2
} {4 ok}

do_test 2.3 {
  execsql {
    INSERT INTO t1 VALUES(randomblob(50), randomblob(50), randomblob(50));
    SELECT count(*) FROM t1;
    PRAGMA integrity_check
  } db2
} {5 ok}


finish_test

Added test/wal2recover3.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022 June 28
#
# 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 the operation of the library in
# "PRAGMA journal_mode=WAL2" mode.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/malloc_common.tcl
source $testdir/wal_common.tcl

set testprefix wal2recover3
ifcapable !wal {finish_test ; return }

do_execsql_test 1.0 {
  CREATE TABLE t1(x);
  CREATE TABLE t2(x);
  PRAGMA journal_mode = wal2;
  PRAGMA wal_autocheckpoint = 0;
  PRAGMA journal_size_limit = 10000;
} {wal2 0 10000}

do_execsql_test 1.1 {
  WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<1500 )
    INSERT INTO t1 SELECT i FROM s;
  WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<1500 )
    INSERT INTO t2 SELECT i FROM s;
}

db_save_and_close
set fd [open sv_test.db-wal2 r+]
seek $fd 4000
puts -nonewline $fd 0
close $fd

db_restore_and_reopen
do_execsql_test 1.2 {
  SELECT sql FROM sqlite_schema;
} {{CREATE TABLE t1(x)} {CREATE TABLE t2(x)}}

finish_test

Added test/wal2rewrite.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2017 September 19
#
# 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 the operation of the library in
# "PRAGMA journal_mode=WAL2" mode.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/malloc_common.tcl
source $testdir/wal_common.tcl

set testprefix wal2rewrite
ifcapable !wal {finish_test ; return }

proc filesize {filename} {
  if {[file exists $filename]} {
    return [file size $filename]
  }
  return 0
}

foreach {tn jrnlmode} {
  1 wal
  2 wal2
} {
  reset_db
  execsql "PRAGMA journal_mode = $jrnlmode"
  do_execsql_test $tn.1 {
    PRAGMA journal_size_limit = 10000;
    PRAGMA cache_size = 5;
    PRAGMA wal_autocheckpoint = 10;
  
    CREATE TABLE t1(a INTEGER PRIMARY KEY, b INTEGER, c BLOB);
    CREATE INDEX t1b ON t1(b);
    CREATE INDEX t1c ON t1(c);
  
    WITH s(i) AS (
      SELECT 1 UNION SELECT i+1 FROM s WHERE i<10
    )
    INSERT INTO t1 SELECT i, i, randomblob(800) FROM s;
  } {10000 10}
  
  for {set i 0} {$i < 4} {incr i} {
    do_execsql_test $tn.$i.1 {
      UPDATE t1 SET c=randomblob(800) WHERE (b%10)==5 AND ($i%2)
    }
    do_execsql_test $tn.$i.2 {
      BEGIN;
      UPDATE t1 SET b=b+10, c=randomblob(800);
      UPDATE t1 SET b=b+10, c=randomblob(800);
      UPDATE t1 SET b=b+10, c=randomblob(800);
      UPDATE t1 SET b=b+10, c=randomblob(800);
      UPDATE t1 SET b=b+10, c=randomblob(800);
      UPDATE t1 SET b=b+10, c=randomblob(800);
      UPDATE t1 SET b=b+10, c=randomblob(800);
      UPDATE t1 SET b=b+10, c=randomblob(800);
      UPDATE t1 SET b=b+10, c=randomblob(800);
      UPDATE t1 SET b=b+10, c=randomblob(800);
    }
    execsql COMMIT

    do_test $tn.$i.3 { expr [filesize test.db-wal]  < 100000 } 1
    do_test $tn.$i.4 { expr [filesize test.db-wal2] < 100000 } 1

    set sum [db eval {SELECT sum(b), md5sum(c) FROM t1}]

    do_test $tn.$i.5 {
      foreach f [glob -nocomplain test.db2*] {forcedelete $f}
      foreach f [glob -nocomplain test.db*] {
        forcecopy $f [string map {test.db test.db2} $f]
      }

      sqlite3 db2 test.db2
      db2 eval {SELECT sum(b), md5sum(c) FROM t1}
    } $sum
    db2 close
  }
}
    


finish_test

Added test/wal2rollback.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2017 September 19
#
# 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 the operation of the library in
# "PRAGMA journal_mode=WAL2" mode.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/malloc_common.tcl
source $testdir/wal_common.tcl

set testprefix wal2rollback
ifcapable !wal {finish_test ; return }

do_execsql_test 1.0 {
  CREATE TABLE t1(a, b, c);
  CREATE TABLE t2(a, b, c);
  CREATE INDEX i1 ON t1(a);
  CREATE INDEX i2 ON t1(b);
  PRAGMA journal_mode = wal2;
  PRAGMA cache_size = 5;
  PRAGMA journal_size_limit = 10000;
  WITH s(i) AS (
    SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 1000
  )
  INSERT INTO t1 SELECT i, i, randomblob(200) FROM s;
} {wal2 10000}

do_test 1.1 {
  expr [file size test.db-wal] > 10000
} 1

do_test 1.2 {
  execsql {
    BEGIN;
      UPDATE t1 SET b=b+1;
      INSERT INTO t2 VALUES(1,2,3);
  }
  expr [file size test.db-wal2] > 10000
} {1}

breakpoint
do_execsql_test 1.3 {
  ROLLBACK;
  SELECT * FROM t2;
  SELECT count(*) FROM t1 WHERE a=b;
  PRAGMA integrity_check;
} {1000 ok}



finish_test

Added test/wal2savepoint.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2018 December 13
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the operation of the library in
# "PRAGMA journal_mode=WAL2" mode.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/malloc_common.tcl
source $testdir/wal_common.tcl

set testprefix wal2savepoint
ifcapable !wal {finish_test ; return }

do_execsql_test 1.0 {
  CREATE TABLE t1(a, b, c);
  CREATE INDEX t1a ON t1(a);
  CREATE INDEX t1b ON t1(b);
  CREATE INDEX t1c ON t1(c);
  PRAGMA journal_mode = wal2;
  PRAGMA journal_size_limit = 15000;
  PRAGMA wal_autocheckpoint = 0;
  PRAGMA cache_size = 5;
} {wal2 15000 0}

do_execsql_test 1.1 {
  WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s where i < 200)
  INSERT INTO t1 SELECT random(), random(), random() FROM s;
} {}

do_test 1.2 {
  list [file size test.db] [file size test.db-wal2] \
       [expr [file size test.db-wal]>20000]
} {5120 0 1}

do_execsql_test 1.3 {
  BEGIN;
    SAVEPOINT abc;
      WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s where i < 100)
      INSERT INTO t1 SELECT random(), random(), random() FROM s;
    ROLLBACK TO abc;
    WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s where i < 10)
    INSERT INTO t1 SELECT random(), random(), random() FROM s;
  COMMIT;
  SELECT count(*) FROM t1;
  PRAGMA integrity_check;
} {210 ok}

do_execsql_test 1.4 {
  BEGIN;
    SAVEPOINT abc;
      WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s where i < 100)
      INSERT INTO t1 SELECT random(), random(), random() FROM s;
    ROLLBACK TO abc;
    WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s where i < 10)
    INSERT INTO t1 SELECT random(), random(), random() FROM s;
  COMMIT;
  SELECT count(*) FROM t1;
  PRAGMA integrity_check;
} {220 ok}


finish_test

Added test/wal2simple.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2017 September 19
#
# 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 the operation of the library in
# "PRAGMA journal_mode=WAL2" mode.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/malloc_common.tcl
source $testdir/wal_common.tcl

set testprefix wal2simple
ifcapable !wal {finish_test ; return }

#-------------------------------------------------------------------------
# The following tests verify that a client can switch in and out of wal
# and wal2 mode. But that it is not possible to change directly from wal
# to wal2, or from wal2 to wal mode.
#
do_execsql_test 1.1.0 {
  PRAGMA journal_mode = wal2
} {wal2}
execsql { SELECT * FROM sqlite_master} 
do_execsql_test 1.x {
  PRAGMA journal_mode;
  PRAGMA main.journal_mode;
} {wal2 wal2}
db close
do_test 1.1.1 { file size test.db } {1024}
do_test 1.1.2 { hexio_read test.db 18 2 } 0303

sqlite3 db test.db
do_execsql_test 1.2.0 {
  SELECT * FROM sqlite_master;
  PRAGMA journal_mode = delete;
} {delete}
db close
do_test 1.2.1 { file size test.db } {1024}
do_test 1.2.2 { hexio_read test.db 18 2 } 0101

sqlite3 db test.db
do_execsql_test 1.3.0 {
  SELECT * FROM sqlite_master;
  PRAGMA journal_mode = wal;
} {wal}
db close
do_test 1.3.1 { file size test.db } {1024}
do_test 1.3.2 { hexio_read test.db 18 2 } 0202

sqlite3 db test.db
do_catchsql_test 1.4.0 {
  PRAGMA journal_mode = wal2;
} {1 {cannot change from wal to wal2 mode}}
do_execsql_test 1.4.1 {
  PRAGMA journal_mode = wal;
  PRAGMA journal_mode = delete;
  PRAGMA journal_mode = wal2;
  PRAGMA journal_mode = wal2;
} {wal delete wal2 wal2}
do_catchsql_test 1.4.2 {
  PRAGMA journal_mode = wal;
} {1 {cannot change from wal2 to wal mode}}
db close
do_test 1.4.3 { hexio_read test.db 18 2 } 0303

#-------------------------------------------------------------------------
# Test that recovery in wal2 mode works.
#
forcedelete test.db test.db-wal test.db-wal2
reset_db
do_execsql_test 2.0 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
  PRAGMA journal_mode = wal2;
  PRAGMA journal_size_limit = 5000;
} {wal2 5000}

proc wal_hook {DB nm nFrame} { $DB eval { PRAGMA wal_checkpoint } }
db wal_hook {wal_hook db}

for {set i 1} {$i <= 200} {incr i} {
  execsql { INSERT INTO t1 VALUES(NULL, randomblob(100)) }
  set res [db eval { SELECT sum(a), md5sum(b) FROM t1 }]

  do_test 2.1.$i {
    foreach f [glob -nocomplain test.db2*] { forcedelete $f }
    forcecopy test.db      test.db2
    forcecopy test.db-wal  test.db2-wal
    forcecopy test.db-wal2 test.db2-wal2

    sqlite3 db2 test.db2
    db2 eval { SELECT sum(a), md5sum(b) FROM t1 }
  } $res

  db2 close
}

#-------------------------------------------------------------------------

reset_db
do_execsql_test 3.0 {
  CREATE TABLE t1(x BLOB, y INTEGER PRIMARY KEY);
  CREATE INDEX i1 ON t1(x);
  PRAGMA cache_size = 5;
  PRAGMA journal_mode = wal2;
} {wal2}

do_test 3.1 {
  execsql BEGIN
  for {set i 1} {$i < 1000} {incr i} {
    execsql { INSERT INTO t1 VALUES(randomblob(800), $i) }
  }
  execsql COMMIT
} {}

do_execsql_test 3.2 {
  PRAGMA integrity_check;
} {ok}

#-------------------------------------------------------------------------
catch { db close }
foreach f [glob -nocomplain test.db*] { forcedelete $f }
reset_db
do_execsql_test 4.0 {
  CREATE TABLE t1(x, y);
  PRAGMA journal_mode = wal2;
} {wal2}

do_execsql_test 4.1 {
  SELECT * FROM t1;
} {}

do_execsql_test 4.2 {
  INSERT INTO t1 VALUES(1, 2);
} {}

do_execsql_test 4.3 {
  SELECT * FROM t1;
} {1 2}

do_test 4.4 {
  sqlite3 db2 test.db
  execsql { SELECT * FROM t1 } db2
} {1 2}

do_test 4.5 {
  lsort [glob test.db*]
} {test.db test.db-shm test.db-wal test.db-wal2}

do_test 4.6 {
  db close
  db2 close
  sqlite3 db test.db
  execsql { SELECT * FROM t1 }
} {1 2}

do_execsql_test 4.7 {
  PRAGMA journal_size_limit = 4000;
  INSERT INTO t1 VALUES(3, 4);
  INSERT INTO t1 VALUES(5, 6);
  INSERT INTO t1 VALUES(7, 8);
  INSERT INTO t1 VALUES(9, 10);
  INSERT INTO t1 VALUES(11, 12);
  INSERT INTO t1 VALUES(13, 14);
  INSERT INTO t1 VALUES(15, 16);
  INSERT INTO t1 VALUES(17, 18);
  SELECT * FROM t1;
} {4000 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18}

do_test 4.8 {
  sqlite3 db2 test.db
  execsql { SELECT * FROM t1 } db2
} {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18}

do_test 4.9 {
  db close
  db2 close
  lsort [glob test.db*]
} {test.db}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 5.0 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
  CREATE INDEX i1 ON t1(b, c);
  PRAGMA journal_mode = wal2;
  PRAGMA journal_size_limit = 4000;
} {wal2 4000}

proc wal_hook {DB nm nFrame} {
  $DB eval { PRAGMA wal_checkpoint }
}
db wal_hook [list wal_hook db]


foreach js {4000 8000 12000} {
  foreach NROW [list 100 200 300 400 500 600 1000] {
    do_test 5.$js.$NROW.1 {
      db eval "DELETE FROM t1"
      db eval "PRAGMA journal_size_limit = $js"
      set nTotal 0
      for {set i 0} {$i < $NROW} {incr i} {
        db eval { INSERT INTO t1 VALUES($i, $i, randomblob(abs(random()%50))) }
        incr nTotal $i
      }
      set {} {}
    } {}

    do_test 5.$js.$NROW.2 {
      sqlite3 db2 test.db
      db2 eval { 
        PRAGMA integrity_check;
        SELECT count(*), sum(b) FROM t1;
      }
    } [list ok $NROW $nTotal]

    db2 close
  }
}


#-------------------------------------------------------------------------
reset_db
do_execsql_test 6.0 {
  CREATE TABLE tx(x);
  PRAGMA journal_mode = wal2;
  PRAGMA journal_size_limit = 3500;
} {wal2 3500}

do_test 6.1 {
  for {set i 0} {$i < 10} {incr i} {
    execsql "CREATE TABLE t$i (x);"
  }
} {}

do_test 6.2.1 {
  foreach f [glob -nocomplain test.db2*] { forcedelete $f }
  forcecopy test.db-wal2 test.db2-wal2
  sqlite3 db2 test.db2
  db2 eval { SELECT * FROM sqlite_master }
} {}
do_test 6.2.2 {
  db2 eval {
    PRAGMA journal_mode = wal2;
    SELECT * FROM sqlite_master;
  }
} {wal2}

do_test 6.3.1 {
  db2 close
  foreach f [glob -nocomplain test.db2*] { forcedelete $f }
  forcecopy test.db-wal2 test.db2-wal2
  forcecopy test.db test.db2
  sqlite3 db2 test.db2
  db2 eval { SELECT * FROM sqlite_master }
} {table tx tx 2 {CREATE TABLE tx(x)}}
do_test 6.3.2 {
  db2 eval {
    PRAGMA journal_mode = wal2;
    SELECT * FROM sqlite_master;
  }
} {wal2 table tx tx 2 {CREATE TABLE tx(x)}}

do_test 6.4.1 {
  db2 close
  foreach f [glob -nocomplain test.db2*] { forcedelete $f }
  forcecopy test.db-wal2 test.db2-wal2
  forcecopy test.db-wal test.db2-wal
  sqlite3 db2 test.db2
  db2 eval { SELECT * FROM sqlite_master }
} {}
do_test 6.4.2 {
  db2 eval {
    PRAGMA journal_mode = wal2;
    SELECT * FROM sqlite_master;
  }
} {wal2}
db2 close

#-------------------------------------------------------------------------
reset_db
sqlite3 db2 test.db
do_execsql_test 7.0 {
  PRAGMA journal_size_limit = 10000;
  PRAGMA journal_mode = wal2;
  PRAGMA wal_autocheckpoint = 0;
  BEGIN;
    CREATE TABLE t1(a);
    INSERT INTO t1 VALUES( randomblob(8000) );
  COMMIT;
} {10000 wal2 0}

do_test 7.1 {
  list [file size test.db-wal] [file size test.db-wal2]
} {9464 0}

# Connection db2 is holding a PART1 lock. 
#
#   7.2.2: Test that the PART1 does not prevent db from switching to the
#          other wal file.
#
#   7.2.3: Test that the PART1 does prevent a checkpoint of test.db-wal.
#
#   7.2.4: Test that after the PART1 is released the checkpoint is possible.
#
do_test 7.2.1 {
  execsql {
    BEGIN;
      SELECT count(*) FROM t1;
  } db2
} {1}
do_test 7.2.2 {
  execsql {
    INSERT INTO t1 VALUES( randomblob(800) );
    INSERT INTO t1 VALUES( randomblob(800) );
  }
  list [file size test.db-wal] [file size test.db-wal2] [file size test.db]
} {13656 3176 1024}
do_test 7.2.3 {
  execsql { PRAGMA wal_checkpoint }
  list [file size test.db-wal] [file size test.db-wal2] [file size test.db]
} {13656 3176 1024}
do_test 7.2.4 {
  execsql { END } db2
  execsql { PRAGMA wal_checkpoint }
  list [file size test.db-wal] [file size test.db-wal2] [file size test.db]
} {13656 3176 11264}

# Connection db2 is holding a PART2_FULL1 lock. 
#
#   7.3.2: Test that the lock does not prevent checkpointing.
#
#   7.3.3: Test that the lock does prevent the writer from overwriting 
#          test.db-wal.
#
#   7.3.4: Test that after the PART2_FULL1 is released the writer can
#          switch wal files and overwrite test.db-wal
#
db close
db2 close
sqlite3 db test.db
sqlite3 db2 test.db
do_test 7.3.1 {
  execsql {
    PRAGMA wal_autocheckpoint = 0;
    PRAGMA journal_size_limit = 10000;
    INSERT INTO t1 VALUES(randomblob(10000));
    INSERT INTO t1 VALUES(randomblob(500));
  }
  execsql {
    BEGIN;
      SELECT count(*) FROM t1;
  } db2
  list [file size test.db-wal] [file size test.db-wal2] [file size test.db]
} {12608 3176 12288}
do_test 7.3.2 {
  execsql { PRAGMA wal_checkpoint }
  list [file size test.db-wal] [file size test.db-wal2] [file size test.db]
} {12608 3176 22528}
do_test 7.3.3 {
  execsql { 
    INSERT INTO t1 VALUES(randomblob(10000));
    INSERT INTO t1 VALUES(randomblob(500));
  }
  list [file size test.db-wal] [file size test.db-wal2] [file size test.db]
} {12608 18896 22528}
do_test 7.3.4 {
  execsql END db2
  execsql { INSERT INTO t1 VALUES(randomblob(5000)); }
  list [file size test.db-wal] [file size test.db-wal2] [file size test.db]
} {12608 18896 22528}

# Connection db2 is holding a PART2 lock. 
#
#   7.4.2: Test that the lock does not prevent writer switching to test.db-wal.
#
#   7.3.3: Test that the lock does prevent checkpointing of test.db-wal2.
#
#   7.3.4: Test that after the PART2 is released test.db-wal2 can be
#          checkpointed.
#
db close
db2 close
breakpoint
sqlite3 db test.db
sqlite3 db2 test.db
do_test 7.4.1 {
  execsql {
    PRAGMA wal_autocheckpoint = 0;
    PRAGMA journal_size_limit = 10000;
    INSERT INTO t1 VALUES(randomblob(10000));
    INSERT INTO t1 VALUES(randomblob(10000));
    PRAGMA wal_checkpoint;
  }
  execsql {
    BEGIN;
      SELECT count(*) FROM t1;
  } db2
  list [file size test.db-wal] [file size test.db-wal2] [file size test.db]
} {12608 12608 50176}
do_test 7.4.2 {
  execsql { 
    INSERT INTO t1 VALUES(randomblob(5000));
  }
  list [file size test.db-wal] [file size test.db-wal2] [file size test.db]
} {12608 12608 50176}
do_test 7.4.3 {
  execsql { PRAGMA wal_checkpoint }
  list [file size test.db-wal] [file size test.db-wal2] [file size test.db]
} {12608 12608 50176}
do_test 7.4.4 {
  execsql END db2
  execsql { PRAGMA wal_checkpoint }
  list [file size test.db-wal] [file size test.db-wal2] [file size test.db]
} {12608 12608 60416}

# Connection db2 is holding a PART1_FULL2 lock. 
#
#   7.5.2: Test that the lock does not prevent a checkpoint of test.db-wal2.
#
#   7.5.3: Test that the lock does prevent the writer from overwriting
#          test.db-wal2.
#
#   7.5.4: Test that after the PART1_FULL2 lock is released, the writer
#          can switch to test.db-wal2.
#
db close
db2 close
sqlite3 db test.db
sqlite3 db2 test.db
do_test 7.5.1 {
  execsql {
    PRAGMA wal_autocheckpoint = 0;
    PRAGMA journal_size_limit = 10000;
    INSERT INTO t1 VALUES(randomblob(10000));
    INSERT INTO t1 VALUES(randomblob(10000));
    PRAGMA wal_checkpoint;
    INSERT INTO t1 VALUES(randomblob(5000));
  }
  execsql {
    BEGIN;
      SELECT count(*) FROM t1;
  } db2
  list [file size test.db-wal] [file size test.db-wal2] [file size test.db]
} {12608 12608 76800}
do_test 7.5.2 {
  execsql { PRAGMA wal_checkpoint }
  list [file size test.db-wal] [file size test.db-wal2] [file size test.db]
} {12608 12608 87040}
do_test 7.5.3.1 {
  execsql { INSERT INTO t1 VALUES(randomblob(5000)) }
  list [file size test.db-wal] [file size test.db-wal2] [file size test.db]
} {14704 12608 87040}
do_test 7.5.3.2 {
  execsql { INSERT INTO t1 VALUES(randomblob(5000)) }
  list [file size test.db-wal] [file size test.db-wal2] [file size test.db]
} {22040 12608 87040}
do_test 7.5.4 {
  execsql END db2
  execsql { INSERT INTO t1 VALUES(randomblob(5000)) }
  list [file size test.db-wal] [file size test.db-wal2] [file size test.db]
} {22040 12608 87040}


finish_test

Added test/wal2snapshot.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2018 December 5
#
# 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 the operation of the library in
# "PRAGMA journal_mode=WAL2" mode.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

set testprefix wal2snapshot
ifcapable !wal {finish_test ; return }
ifcapable !snapshot {finish_test; return}

foreach {tn mode} {1 wal 2 wal2} {
  reset_db
  do_execsql_test $tn.1 "PRAGMA journal_mode = $mode" $mode

  do_execsql_test $tn.2 {
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES(1, 2);
    INSERT INTO t1 VALUES(3, 4);
    BEGIN;
  }

  # Check that sqlite3_snapshot_get() is an error for a wal2 db.
  #
  if {$tn==1} {
    do_test 1.3 {
      set S [sqlite3_snapshot_get db main]
      sqlite3_snapshot_free $S
    } {}
  } else {
    do_test 2.3 {
      list [catch { sqlite3_snapshot_get db main } msg] $msg
    } {1 SQLITE_ERROR}
  }
  
  # Check that sqlite3_snapshot_recover() is an error for a wal2 db.
  #
  do_execsql_test $tn.4 COMMIT
  if {$tn==1} {
    do_test 1.5 {
      sqlite3_snapshot_recover db main
    } {}
  } else {
    do_test 2.5 {
      list [catch { sqlite3_snapshot_recover db main } msg] $msg
    } {1 SQLITE_ERROR}
  }
 
  # Check that sqlite3_snapshot_open() is an error for a wal2 db.
  #
  if {$tn==1} {
    do_test 1.6 {
      execsql BEGIN
      set SNAPSHOT [sqlite3_snapshot_get_blob db main]
      sqlite3_snapshot_open_blob db main $SNAPSHOT
      execsql COMMIT
    } {}
  } else {

    do_test 2.6.1 {
      execsql BEGIN
      set res [
        list [catch { sqlite3_snapshot_open_blob db main $SNAPSHOT } msg] $msg
      ]
      execsql COMMIT
      set res
    } {1 SQLITE_ERROR}
    do_test 2.6.2 {
      execsql BEGIN
      execsql {SELECT * FROM sqlite_master}
      set res [
        list [catch { sqlite3_snapshot_open_blob db main $SNAPSHOT } msg] $msg
      ]
      execsql COMMIT
      set res
    } {1 SQLITE_ERROR}
  }
}


finish_test


Changes to test/wal3.test.

8
9
10
11
12
13
14

15
16
17
18
19
20
21
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22







+







#    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 the operation of the library in
# "PRAGMA journal_mode=WAL" mode.
#
# TESTRUNNER: slow

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/wal_common.tcl
source $testdir/malloc_common.tcl
ifcapable !wal {finish_test ; return }

Added test/walfault2.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2010 May 03
#
# 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 the operation of the library in
# "PRAGMA journal_mode=WAL" mode.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/malloc_common.tcl
source $testdir/lock_common.tcl

ifcapable !wal {finish_test ; return }
set testprefix walfault2

#-------------------------------------------------------------------------
# Inject faults while truncating the wal file.
#
do_execsql_test 1.0 {
  PRAGMA auto_vacuum = 0;
  CREATE TABLE t1(a, b);
  PRAGMA journal_mode = wal;
  WITH s(i) AS (
    SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 30
  )
  INSERT INTO t1 SELECT randomblob(400), randomblob(400) FROM s;
} {wal}
faultsim_save_and_close

do_faultsim_test 1 -prep {
  catch { db close }
  faultsim_restore
  sqlite3 db file:test.db?psow=0 -uri 1
  file_control_powersafe_overwrite db 0
  execsql {
    PRAGMA wal_checkpoint;
    PRAGMA journal_size_limit = 10000;
    PRAGMA synchronous = full;
  }
} -body {
  execsql { INSERT INTO t1 VALUES(1,1) }
} -test {
  faultsim_test_result {0 {}}
}

#-------------------------------------------------------------------------
# Inject faults while rewriting checksums.
#
reset_db
do_execsql_test 2.0 {
  PRAGMA auto_vacuum = 0;
  CREATE TABLE t1(a, b);
  PRAGMA journal_mode = wal;
  WITH s(i) AS (
    SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 30
  )
  INSERT INTO t1 SELECT randomblob(400), randomblob(400) FROM s;
} {wal}
faultsim_save_and_close

do_faultsim_test 2 -prep {
  faultsim_restore_and_reopen
  execsql {
    PRAGMA cache_size = 2;
    BEGIN;
    UPDATE t1 SET a=randomblob(400);
    UPDATE t1 SET b=randomblob(400);
    UPDATE t1 SET a=randomblob(400);
    UPDATE t1 SET b=randomblob(400);
    UPDATE t1 SET a=randomblob(400);
    UPDATE t1 SET b=randomblob(400);
    UPDATE t1 SET a=randomblob(400);
    UPDATE t1 SET b=randomblob(400);
  }
} -body {
  execsql COMMIT
} -test {
  faultsim_test_result {0 {}}
}



finish_test

Changes to test/walprotocol.test.

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
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







-
-
-
+
+
+
+
+
+
+
+






-
-
-
+
+
+
+
+
+
+
+







do_test 1.1 {
  testvfs T
  T filter xShmLock 
  T script lock_callback
  set ::locks [list]
  sqlite3 db test.db -vfs T
  execsql { SELECT * FROM x }
  lrange $::locks 0 5
} [list {0 1 lock exclusive} {1 2 lock exclusive} {4 4 lock exclusive} \
        {1 2 unlock exclusive} {4 4 unlock exclusive} {0 1 unlock exclusive}  \
  lrange $::locks 0 11
} [list {0 1 lock exclusive} {1 2 lock exclusive}     \
        {4 1 lock exclusive} {4 1 unlock exclusive}   \
        {5 1 lock exclusive} {5 1 unlock exclusive}   \
        {6 1 lock exclusive} {6 1 unlock exclusive}   \
        {7 1 lock exclusive} {7 1 unlock exclusive}   \
        {1 2 unlock exclusive}   \
        {0 1 unlock exclusive}  \
]
do_test 1.2 {
  db close
  set ::locks [list]
  sqlite3 db test.db -vfs T
  execsql { SELECT * FROM x }
  lrange $::locks 0 5
} [list {0 1 lock exclusive} {1 2 lock exclusive} {4 4 lock exclusive} \
        {1 2 unlock exclusive} {4 4 unlock exclusive} {0 1 unlock exclusive}  \
  lrange $::locks 0 11
} [list {0 1 lock exclusive} {1 2 lock exclusive}     \
        {4 1 lock exclusive} {4 1 unlock exclusive}   \
        {5 1 lock exclusive} {5 1 unlock exclusive}   \
        {6 1 lock exclusive} {6 1 unlock exclusive}   \
        {7 1 lock exclusive} {7 1 unlock exclusive}   \
        {1 2 unlock exclusive}   \
        {0 1 unlock exclusive}  \
]
proc lock_callback {method filename handle lock} {
  if {$lock == "1 2 lock exclusive"} { return SQLITE_BUSY }
  return SQLITE_OK
}
puts "# Warning: This next test case causes SQLite to call xSleep(1) 100 times."
puts "# Normally this equates to a delay of roughly 10 seconds, but if SQLite"
97
98
99
100
101
102
103
104

105
106
107
108
109
110
111
107
108
109
110
111
112
113

114
115
116
117
118
119
120
121







-
+







  return SQLITE_OK
}
do_test 1.5 {
  db close
  set ::locks [list]
  sqlite3 db test.db -vfs T
  catchsql { SELECT * FROM x }
} {1 {locking protocol}}
} {0 z}
db close
T delete

#-------------------------------------------------------------------------
# 
do_test 2.1 {
  forcedelete test.db test.db-journal test.db wal
156
157
158
159
160
161
162
163

164
165
166
167
168
169
170
166
167
168
169
170
171
172

173
174
175
176
177
178
179
180







-
+







sqlite3 db2 test.db
puts "# Warning: Another slow test!"
do_test 2.5 {
  execsql { SELECT * FROM b }
} {Tehran Qom Markazi Qazvin Gilan Ardabil}
do_test 2.6 {
  set ::r
} {1 {locking protocol}}
} {0 {Tehran Qom Markazi Qazvin Gilan Ardabil}}

db close
db2 close

faultsim_restore_and_reopen
sqlite3 db2 test.db
T filter xShmLock
178
179
180
181
182
183
184
185

186
187
188
189
190
191
188
189
190
191
192
193
194

195
196
197
198
199
200
201







-
+






unset ::r
puts "# Warning: Last one!"
do_test 2.7 {
  execsql { SELECT * FROM b }
} {Tehran Qom Markazi Qazvin Gilan Ardabil}
do_test 2.8 {
  set ::r
} {1 {locking protocol}}
} {0 {Tehran Qom Markazi Qazvin Gilan Ardabil}}

db close
db2 close
T delete

finish_test

Changes to test/walprotocol2.test.

81
82
83
84
85
86
87
88

89
90
91
92
93
94
95
81
82
83
84
85
86
87

88
89
90
91
92
93
94
95







-
+







#
proc lock_callback {method filename handle lock} {
  if {$lock=="0 1 lock exclusive"} {
    proc lock_callback {method filename handle lock} {}
    db2 eval { INSERT INTO x VALUES('x') }
  }
}
db timeout 10
db timeout 1100
do_catchsql_test 2.4 {
  BEGIN EXCLUSIVE;
} {0 {}}
do_execsql_test 2.5 {
  SELECT * FROM x;
  COMMIT;
} {z y x}

Changes to test/walro2.test.

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
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







+


+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



# possible *-shm file (i.e. the greater of 32KB and the system page-size).
#
do_execsql_test 0.0 {
  PRAGMA journal_mode = wal;
  CREATE TABLE t1(x);
} {wal}
set MINSHMSZ [file size test.db-shm]
set dfltpgsz [db one {PRAGMA page_size}]

foreach bZeroShm {0 1} {
  for {set pgsz 512} {$pgsz<=65536} {set pgsz [expr {$pgsz*2}]} {
set TN [expr $bZeroShm+1]
do_multiclient_test tn {
  
  # Close all connections and delete the database.
  #
  code1 { db close  }
  code2 { db2 close }
  code3 { db3 close }
  forcedelete test.db
  
  # Do not run tests with the connections in the same process.
  #
  if {$tn==2} continue

  foreach c {code1 code2 code3} {
    $c {
      sqlite3_shutdown
      sqlite3_config_uri 1
    }
  }

  do_test $TN.1.1 {
    code2 { sqlite3 db2 test.db }
    sql2 { 
      CREATE TABLE t1(x, y);
      PRAGMA journal_mode = WAL;
      INSERT INTO t1 VALUES('a', 'b');
      INSERT INTO t1 VALUES('c', 'd');
    }
    file exists test.db-shm
  } {1}

  do_test $TN.1.2.1 {
    copy_to_test2 $bZeroShm
    code1 {
      sqlite3 db file:test.db2?readonly_shm=1
    }

    sql1 { SELECT * FROM t1 }
  } {a b c d}
  do_test $TN.1.2.2 {
    sql1 { SELECT * FROM t1 }
  } {a b c d}

  do_test $TN.1.3.1 {
    code3 { sqlite3 db3 test.db2 }
    sql3 { SELECT * FROM t1 }
  } {a b c d}

  do_test $TN.1.3.2 {
    sql1 { SELECT * FROM t1 }
  } {a b c d}

  code1 { db close  }
  code2 { db2 close }
  code3 { db3 close }

  do_test $TN.2.1 {
    code2 { sqlite3 db2 test.db }
    sql2 { 
      INSERT INTO t1 VALUES('e', 'f');
      INSERT INTO t1 VALUES('g', 'h');
    }
    file exists test.db-shm
  } {1}

  do_test $TN.2.2 {
    copy_to_test2 $bZeroShm
    code1 {
      sqlite3 db file:test.db2?readonly_shm=1
    }
    sql1 { 
      BEGIN;
      SELECT * FROM t1;
    }
  } {a b c d e f g h}

  do_test $TN.2.3.1 {
    code3 { sqlite3 db3 test.db2 }
    sql3 { SELECT * FROM t1 }
  } {a b c d e f g h}
  do_test $TN.2.3.2 {
    sql3 { INSERT INTO t1 VALUES('i', 'j') }
    code3 { db3 close }
    sql1 { COMMIT } 
  } {}
  do_test $TN.2.3.3 {
    sql1 { SELECT * FROM t1 }
  } {a b c d e f g h i j}


  #-----------------------------------------------------------------------
  # 3.1.*: That a readonly_shm connection can read a database file if both
  #        the *-wal and *-shm files are zero bytes in size.
  #
  # 3.2.*: That it flushes the cache if, between transactions on a db with a
  #        zero byte *-wal file, some other connection modifies the db, then
  #        does "PRAGMA wal_checkpoint=truncate" to truncate the wal file
  #        back to zero bytes in size.
  #
  # 3.3.*: That, if between transactions some other process wraps the wal
  #        file, the readonly_shm client reruns recovery.
  #
  catch { code1 { db close } }
  catch { code2 { db2 close } }
  catch { code3 { db3 close } }
  do_test $TN.3.1.0 {
    list [file exists test.db-wal] [file exists test.db-shm]
  } {0 0}
  do_test $TN.3.1.1 {
    close [open test.db-wal w]
    close [open test.db-shm w]
    code1 {
      sqlite3 db file:test.db?readonly_shm=1
    }
    sql1 { SELECT * FROM t1 }
  } {a b c d e f g h}

  do_test $TN.3.2.0 {
    list [file size test.db-wal] [file size test.db-shm]
  } {0 0}
  do_test $TN.3.2.1 {
    code2 { sqlite3 db2 test.db }
    sql2 { INSERT INTO t1 VALUES(1, 2) ; PRAGMA wal_checkpoint=truncate }
    code2 { db2 close }
    sql1 { SELECT * FROM t1 }
  } {a b c d e f g h 1 2}
  do_test $TN.3.2.2 {
    list [file size test.db-wal] [file size test.db-shm]
  } [list 0 $MINSHMSZ]
    set TN [expr $bZeroShm+1]-$pgsz
    do_multiclient_test tn {
      
      # Close all connections and delete the database.
      #
      code1 { db close  }
      code2 { db2 close }
      code3 { db3 close }
      forcedelete test.db
      
      # Do not run tests with the connections in the same process.
      #
      if {$tn==2} continue
    
      foreach c {code1 code2 code3} {
        $c {
          sqlite3_shutdown
          sqlite3_config_uri 1
        }
      }
    
      do_test $TN.1.1 {
        code2 { sqlite3 db2 test.db }
        sql2 "PRAGMA page_size=$::pgsz"
        sql2 {
          CREATE TABLE t1(x, y);
          PRAGMA journal_mode = WAL;
          INSERT INTO t1 VALUES('a', 'b');
          INSERT INTO t1 VALUES('c', 'd');
        }
        file exists test.db-shm
      } {1}
    
      do_test $TN.1.2.1 {
        copy_to_test2 $bZeroShm
        code1 {
          sqlite3 db file:test.db2?readonly_shm=1
        }
    
        sql1 { SELECT * FROM t1 }
      } {a b c d}
      do_test $TN.1.2.2 {
        sql1 { SELECT * FROM t1 }
      } {a b c d}
    
      do_test $TN.1.3.1 {
        code3 { sqlite3 db3 test.db2 }
        sql3 { SELECT * FROM t1 }
      } {a b c d}
    
      do_test $TN.1.3.2 {
        sql1 { SELECT * FROM t1 }
      } {a b c d}
    
      code1 { db close  }
      code2 { db2 close }
      code3 { db3 close }
    
      do_test $TN.2.1 {
        code2 { sqlite3 db2 test.db }
        sql2 "PRAGMA page_size=$::pgsz;"
        sql2 { 
          INSERT INTO t1 VALUES('e', 'f');
          INSERT INTO t1 VALUES('g', 'h');
        }
        file exists test.db-shm
      } {1}
    
      do_test $TN.2.2 {
        copy_to_test2 $bZeroShm
        code1 {
          sqlite3 db file:test.db2?readonly_shm=1
        }
        sql1 { 
          BEGIN;
          SELECT * FROM t1;
        }
      } {a b c d e f g h}
    
      do_test $TN.2.3.1 {
        code3 { sqlite3 db3 test.db2 }
        sql3 { SELECT * FROM t1 }
      } {a b c d e f g h}
      do_test $TN.2.3.2 {
        sql3 { INSERT INTO t1 VALUES('i', 'j') }
        code3 { db3 close }
        sql1 { COMMIT } 
      } {}
      do_test $TN.2.3.3 {
        sql1 { SELECT * FROM t1 }
      } {a b c d e f g h i j}
    
    
      #-----------------------------------------------------------------------
      # 3.1.*: That a readonly_shm connection can read a database file if both
      #        the *-wal and *-shm files are zero bytes in size.
      #
      # 3.2.*: That it flushes the cache if, between transactions on a db with a
      #        zero byte *-wal file, some other connection modifies the db, then
      #        does "PRAGMA wal_checkpoint=truncate" to truncate the wal file
      #        back to zero bytes in size.
      #
      # 3.3.*: That, if between transactions some other process wraps the wal
      #        file, the readonly_shm client reruns recovery.
      #
      catch { code1 { db close } }
      catch { code2 { db2 close } }
      catch { code3 { db3 close } }
      do_test $TN.3.1.0 {
        list [file exists test.db-wal] [file exists test.db-shm]
      } {0 0}
      do_test $TN.3.1.1 {
        close [open test.db-wal w]
        close [open test.db-shm w]
        code1 {
          sqlite3 db file:test.db?readonly_shm=1
        }
        sql1 { SELECT * FROM t1 }
      } {a b c d e f g h}
    
      do_test $TN.3.2.0 {
        list [file size test.db-wal] [file size test.db-shm]
      } {0 0}
      do_test $TN.3.2.1 {
        code2 { sqlite3 db2 test.db }
        sql2 { INSERT INTO t1 VALUES(1, 2) ; PRAGMA wal_checkpoint=truncate }
        code2 { db2 close }
        sql1 { SELECT * FROM t1 }
      } {a b c d e f g h 1 2}
      if {$pgsz!=$dfltpgsz} continue
      do_test $TN.3.2.2 {
        list [file size test.db-wal] [file size test.db-shm]
      } [list 0 $MINSHMSZ]

  do_test $TN.3.3.0 {
    code2 { sqlite3 db2 test.db }
    sql2 { 
      INSERT INTO t1 VALUES(3, 4);
      INSERT INTO t1 VALUES(5, 6);
      INSERT INTO t1 VALUES(7, 8);
      INSERT INTO t1 VALUES(9, 10);
    }
    code2 { db2 close }
    code1 { db close }
    list [file size test.db-wal] [file size test.db-shm]
  } [list [wal_file_size 4 1024] $MINSHMSZ]
  do_test $TN.3.3.1 {
    code1 { sqlite3 db file:test.db?readonly_shm=1 }
    sql1 { SELECT * FROM t1 }
  } {a b c d e f g h 1 2 3 4 5 6 7 8 9 10}
  do_test $TN.3.3.2 {
    code2 { sqlite3 db2 test.db }
    sql2 { 
      PRAGMA wal_checkpoint; 
      DELETE FROM t1;
      INSERT INTO t1 VALUES('i', 'ii');
    }
    code2 { db2 close }
    list [file size test.db-wal] [file size test.db-shm]
  } [list [wal_file_size 4 1024] $MINSHMSZ]
  do_test $TN.3.3.3 {
    sql1 { SELECT * FROM t1 }
  } {i ii}

  #-----------------------------------------------------------------------
  #
  #
  catch { code1 { db close } }
  catch { code2 { db2 close } }
  catch { code3 { db3 close } }

  do_test $TN.4.0 {
    code1 { forcedelete test.db }
    code1 { sqlite3 db test.db }
    sql1 {
      PRAGMA journal_mode = wal;
      CREATE TABLE t1(x);
      INSERT INTO t1 VALUES('hello');
      INSERT INTO t1 VALUES('world');
    }

    copy_to_test2 $bZeroShm

    code1 { db close }
  } {}

  do_test $TN.4.1.1 {
    code2 { sqlite3 db2 file:test.db2?readonly_shm=1 }
    sql2 { SELECT * FROM t1 }
  } {hello world}

  do_test $TN.4.1.2 {
    code3 { sqlite3 db3 test.db2 }
    sql3 {
      INSERT INTO t1 VALUES('!');
      PRAGMA wal_checkpoint = truncate;
    }
    code3 { db3 close }
  } {}
  do_test $TN.4.1.3 {
    sql2 { SELECT * FROM t1 }
  } {hello world !}

  catch { code1 { db close } }
  catch { code2 { db2 close } }
  catch { code3 { db3 close } }

  do_test $TN.4.2.1 {
    code1 { sqlite3 db test.db }
    sql1 {
      INSERT INTO t1 VALUES('!');
      INSERT INTO t1 VALUES('!');

      PRAGMA cache_size = 10;
      CREATE TABLE t2(x);

      BEGIN;
        WITH s(i) AS (
          SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<500
          )
        INSERT INTO t2 SELECT randomblob(500) FROM s;
        SELECT count(*) FROM t2;
    } 
  } {500}
  set sz [file size test.db-wal]
  do_test $TN.4.2.2.(sz=$sz) {
    expr {$sz>400000}
  } {1}
  do_test $TN.4.2.4 {
    file_control_persist_wal db 1; db close

    copy_to_test2 $bZeroShm
    code2 { sqlite3 db2 file:test.db2?readonly_shm=1 }
    sql2 {
      SELECT * FROM t1;
      SELECT count(*) FROM t2;
    }
  } {hello world ! ! 0}

  #-----------------------------------------------------------------------
  #
  #
  catch { code1 { db close } }
  catch { code2 { db2 close } }
  catch { code3 { db3 close } }

  do_test $TN.5.0 {
    code1 { forcedelete test.db }
    code1 { sqlite3 db test.db }
    sql1 {
      PRAGMA journal_mode = wal;
      CREATE TABLE t1(x);
      INSERT INTO t1 VALUES('hello');
      INSERT INTO t1 VALUES('world');
      INSERT INTO t1 VALUES('!');
      INSERT INTO t1 VALUES('world');
      INSERT INTO t1 VALUES('hello');
    }

    copy_to_test2 $bZeroShm
    
    code1 { db close }
  } {}

  do_test $TN.5.1 {
    code2 { sqlite3 db2 file:test.db2?readonly_shm=1 }
    sql2 {
      SELECT * FROM t1;
    }
  } {hello world ! world hello}

  do_test $TN.5.2 {
    code1 {
      proc handle_read {op args} {
        if {$op=="xRead" && [file tail [lindex $args 0]]=="test.db2-wal"} {
          set ::res2 [sql2 { SELECT * FROM t1 }]
        }
        puts "$msg xRead $args"
        return "SQLITE_OK"
      }
      testvfs tvfs -fullshm 1

      sqlite3 db file:test.db2?vfs=tvfs
      db eval { SELECT * FROM sqlite_master }

      tvfs filter xRead
      tvfs script handle_read
    }
    sql1 {
      PRAGMA wal_checkpoint = truncate;
    }
    code1 { set ::res2 }
  } {hello world ! world hello}

  do_test $TN.5.3 {
    code1 { db close }
    code1 { tvfs delete }
  } {}

  #-----------------------------------------------------------------------
  #
  #
  catch { code1 { db close } }
  catch { code2 { db2 close } }
  catch { code3 { db3 close } }

  do_test $TN.6.1 {
    code1 { forcedelete test.db }
    code1 { sqlite3 db test.db }
    sql1 {
      PRAGMA journal_mode = wal;
      CREATE TABLE t1(x);
      INSERT INTO t1 VALUES('hello');
      INSERT INTO t1 VALUES('world');
      INSERT INTO t1 VALUES('!');
      INSERT INTO t1 VALUES('world');
      INSERT INTO t1 VALUES('hello');
    }

    copy_to_test2 $bZeroShm
    
    code1 { db close }
  } {}

  do_test $TN.6.2 {
    code1 {
      set ::nRem 5
      proc handle_read {op args} {
        if {$op=="xRead" && [file tail [lindex $args 0]]=="test.db2-wal"} {
          incr ::nRem -1
          if {$::nRem==0} {
            code2 { sqlite3 db2 test.db2 }
            sql2  { PRAGMA wal_checkpoint = truncate }
          }
        }
        return "SQLITE_OK"
      }
      testvfs tvfs -fullshm 1

      tvfs filter xRead
      tvfs script handle_read

      sqlite3 db file:test.db2?readonly_shm=1&vfs=tvfs
      db eval { SELECT * FROM t1 }
    }
  } {hello world ! world hello}

  do_test $TN.6.3 {
    code1 { db close }
    code1 { tvfs delete }
  } {}
}
      do_test $TN.3.3.0 {
        code2 { sqlite3 db2 test.db }
        sql2 { 
          INSERT INTO t1 VALUES(3, 4);
          INSERT INTO t1 VALUES(5, 6);
          INSERT INTO t1 VALUES(7, 8);
          INSERT INTO t1 VALUES(9, 10);
        }
        code2 { db2 close }
        code1 { db close }
        list [file size test.db-wal] [file size test.db-shm]
      } [list [wal_file_size 4 1024] $MINSHMSZ]
      do_test $TN.3.3.1 {
        code1 { sqlite3 db file:test.db?readonly_shm=1 }
        sql1 { SELECT * FROM t1 }
      } {a b c d e f g h 1 2 3 4 5 6 7 8 9 10}
      do_test $TN.3.3.2 {
        code2 { sqlite3 db2 test.db }
        sql2 { 
          PRAGMA wal_checkpoint; 
          DELETE FROM t1;
          INSERT INTO t1 VALUES('i', 'ii');
        }
        code2 { db2 close }
        list [file size test.db-wal] [file size test.db-shm]
      } [list [wal_file_size 4 1024] $MINSHMSZ]
      do_test $TN.3.3.3 {
        sql1 { SELECT * FROM t1 }
      } {i ii}
    
      #-----------------------------------------------------------------------
      #
      #
      catch { code1 { db close } }
      catch { code2 { db2 close } }
      catch { code3 { db3 close } }
    
      do_test $TN.4.0 {
        code1 { forcedelete test.db }
        code1 { sqlite3 db test.db }
        sql1 {
          PRAGMA journal_mode = wal;
          CREATE TABLE t1(x);
          INSERT INTO t1 VALUES('hello');
          INSERT INTO t1 VALUES('world');
        }
    
        copy_to_test2 $bZeroShm
    
        code1 { db close }
      } {}
    
      do_test $TN.4.1.1 {
        code2 { sqlite3 db2 file:test.db2?readonly_shm=1 }
        sql2 { SELECT * FROM t1 }
      } {hello world}
    
      do_test $TN.4.1.2 {
        code3 { sqlite3 db3 test.db2 }
        sql3 {
          INSERT INTO t1 VALUES('!');
          PRAGMA wal_checkpoint = truncate;
        }
        code3 { db3 close }
      } {}
      do_test $TN.4.1.3 {
        sql2 { SELECT * FROM t1 }
      } {hello world !}
    
      catch { code1 { db close } }
      catch { code2 { db2 close } }
      catch { code3 { db3 close } }
    
      do_test $TN.4.2.1 {
        code1 { sqlite3 db test.db }
        sql1 {
          INSERT INTO t1 VALUES('!');
          INSERT INTO t1 VALUES('!');
    
          PRAGMA cache_size = 10;
          CREATE TABLE t2(x);
    
          BEGIN;
            WITH s(i) AS (
              SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<500
              )
            INSERT INTO t2 SELECT randomblob(500) FROM s;
            SELECT count(*) FROM t2;
        } 
      } {500}
      set sz [file size test.db-wal]
      do_test $TN.4.2.2.(sz=$sz) {
        expr {$sz>400000}
      } {1}
      do_test $TN.4.2.4 {
        file_control_persist_wal db 1; db close
    
        copy_to_test2 $bZeroShm
        code2 { sqlite3 db2 file:test.db2?readonly_shm=1 }
        sql2 {
          SELECT * FROM t1;
          SELECT count(*) FROM t2;
        }
      } {hello world ! ! 0}
    
      #-----------------------------------------------------------------------
      #
      #
      catch { code1 { db close } }
      catch { code2 { db2 close } }
      catch { code3 { db3 close } }
    
      do_test $TN.5.0 {
        code1 { forcedelete test.db }
        code1 { sqlite3 db test.db }
        sql1 {
          PRAGMA journal_mode = wal;
          CREATE TABLE t1(x);
          INSERT INTO t1 VALUES('hello');
          INSERT INTO t1 VALUES('world');
          INSERT INTO t1 VALUES('!');
          INSERT INTO t1 VALUES('world');
          INSERT INTO t1 VALUES('hello');
        }
    
        copy_to_test2 $bZeroShm
        
        code1 { db close }
      } {}
    
      do_test $TN.5.1 {
        code2 { sqlite3 db2 file:test.db2?readonly_shm=1 }
        sql2 {
          SELECT * FROM t1;
        }
      } {hello world ! world hello}
    
      do_test $TN.5.2 {
        code1 {
          proc handle_read {op args} {
            if {$op=="xRead" && [file tail [lindex $args 0]]=="test.db2-wal"} {
              set ::res2 [sql2 { SELECT * FROM t1 }]
            }
            puts "$msg xRead $args"
            return "SQLITE_OK"
          }
          testvfs tvfs -fullshm 1
    
          sqlite3 db file:test.db2?vfs=tvfs
          db eval { SELECT * FROM sqlite_master }
    
          tvfs filter xRead
          tvfs script handle_read
        }
        sql1 {
          PRAGMA wal_checkpoint = truncate;
        }
        code1 { set ::res2 }
      } {hello world ! world hello}
    
      do_test $TN.5.3 {
        code1 { db close }
        code1 { tvfs delete }
      } {}
    
      #-----------------------------------------------------------------------
      #
      #
      catch { code1 { db close } }
      catch { code2 { db2 close } }
      catch { code3 { db3 close } }
    
      do_test $TN.6.1 {
        code1 { forcedelete test.db }
        code1 { sqlite3 db test.db }
        sql1 {
          PRAGMA journal_mode = wal;
          CREATE TABLE t1(x);
          INSERT INTO t1 VALUES('hello');
          INSERT INTO t1 VALUES('world');
          INSERT INTO t1 VALUES('!');
          INSERT INTO t1 VALUES('world');
          INSERT INTO t1 VALUES('hello');
        }
    
        copy_to_test2 $bZeroShm
        
        code1 { db close }
      } {}
    
      do_test $TN.6.2 {
        code1 {
          set ::nRem 5
          proc handle_read {op args} {
            if {$op=="xRead" && [file tail [lindex $args 0]]=="test.db2-wal"} {
              incr ::nRem -1
              if {$::nRem==0} {
                code2 { sqlite3 db2 test.db2 }
                sql2  { PRAGMA wal_checkpoint = truncate }
              }
            }
            return "SQLITE_OK"
          }
          testvfs tvfs -fullshm 1
    
          tvfs filter xRead
          tvfs script handle_read
    
          sqlite3 db file:test.db2?readonly_shm=1&vfs=tvfs
          db eval { SELECT * FROM t1 }
        }
      } {hello world ! world hello}
    
      do_test $TN.6.3 {
        code1 { db close }
        code1 { tvfs delete }
      } {}
    }
  } ;# for pgsz
} ;# foreach bZeroShm

finish_test

Changes to test/walrofault.test.

50
51
52
53
54
55
56
57
58
59
60
50
51
52
53
54
55
56


57
58







-
-


  faultsim_restore
  sqlite3 db file:test.db?readonly_shm=1
} -body {
  execsql { SELECT * FROM t1 }
} -test {
  faultsim_test_result {0 {hello world ! world hello}}
}



finish_test

Added test/walsetlk.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
189
190
191
192
193
194
195
196
197
198
199
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2020 May 06
#
# 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.
#
#***********************************************************************
#
# TESTRUNNER: slow
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
set testprefix walsetlk

ifcapable !wal {finish_test ; return }
db timeout 1000

#-------------------------------------------------------------------------
# 1.*: Test that nothing goes wrong if recovery is forced while opening
#      a write transaction or performing a checkpoint with blocking locks.
#

do_execsql_test 1.0 {
  CREATE TABLE t1(x, y);
  PRAGMA journal_mode = wal;
  INSERT INTO t1 VALUES(1, 2);
  INSERT INTO t1 VALUES(3, 4);
  INSERT INTO t1 VALUES(5, 6);
  INSERT INTO t1 VALUES(7, 8);
} {wal}

sqlite3 db2 test.db
db2 timeout 1000

do_execsql_test -db db2 1.1 {
  SELECT * FROM t1
} {1 2 3 4 5 6 7 8}

set fd [open test.db-shm r+]
puts $fd "blahblahblahblah"
flush $fd

do_execsql_test 1.2 {
  BEGIN;
    INSERT INTO t1 VALUES(9, 10);
}

do_execsql_test -db db2 1.3 {
  SELECT * FROM t1
} {1 2 3 4 5 6 7 8}

do_test 1.4 {
  list [catch {db2 eval { BEGIN EXCLUSIVE }} msg] $msg
} {1 {database is locked}}

do_execsql_test 1.5 { COMMIT }
do_execsql_test -db db2 1.6 {
  SELECT * FROM t1
} {1 2 3 4 5 6 7 8 9 10}

puts $fd "blahblahblahblah"
flush $fd

do_execsql_test -db db2 1.7 {
  PRAGMA wal_checkpoint = TRUNCATE
} {0 0 0}

do_test 1.8 {
  file size test.db-wal
} 0

close $fd
db close
db2 close
#-------------------------------------------------------------------------

do_multiclient_test tn {
  do_test 2.$tn.1 {
    sql1 {
      PRAGMA journal_mode = wal;
      CREATE TABLE t1(s, v);
      INSERT INTO t1 VALUES(1, 2);
      INSERT INTO t1 VALUES(3, 4);
      INSERT INTO t1 VALUES(5, 6);
    }
    code1 { db timeout 1100 }
  } {}

  do_test 2.$tn.2 {
    sql2 {
      BEGIN;
        INSERT INTO t1 VALUES(7, 8);
    }
  } {}

  do_test 2.$tn.3 {
    set us [lindex [time { catch {db eval "BEGIN EXCLUSIVE"} }] 0]
    expr $us>1000000 && $us<4000000
  } {1}

  do_test 2.$tn.4 {
    sql2 { COMMIT }
    sql1 { SELECT * FROM t1 }
  } {1 2 3 4 5 6 7 8}

  do_test 2.$tn.5 {
    sql2 {
      BEGIN;
        INSERT INTO t1 VALUES(9, 10);
    }
  } {}

  do_test 2.$tn.6 {
    set us [lindex [time { catch {db eval "PRAGMA wal_checkpoint=RESTART"} }] 0]
    expr $us>1000000 && $us<4000000
  } {1}

  do_test 2.$tn.7 {
    sql2 {
      COMMIT;
      BEGIN;
        SELECT * FROM t1;
    }
  } {1 2 3 4 5 6 7 8 9 10}

  do_test 2.$tn.8 {
    set us [lindex [time { catch {db eval "PRAGMA wal_checkpoint=RESTART"} }] 0]
    expr $us>1000000 && $us<4000000
  } {1}

  do_test 2.$tn.9 {
    sql3 {
      INSERT INTO t1 VALUES(11, 12);
    }
    sql2 {
      COMMIT;
      BEGIN;
        SELECT * FROM t1;
    }
    sql3 {
      INSERT INTO t1 VALUES(13, 14);
    }
  } {}

  do_test 2.$tn.10 {
    set us [lindex [time { catch {db eval "PRAGMA wal_checkpoint=RESTART"} }] 0]
    expr $us>1000000 && $us<4000000
  } {1}

  do_test 2.$tn.11 {
    sql3 {
      BEGIN;
        SELECT * FROM t1;
    }
    sql1 { INSERT INTO t1 VALUES(15, 16); }
  } {}

  do_test 2.$tn.12 {
    set us [lindex [time { catch {db eval "PRAGMA wal_checkpoint=RESTART"} }] 0]
    expr $us>1000000 && $us<4000000
  } {1}

  do_test 2.$tn.13 {
    sql2 {
      COMMIT;
      BEGIN;
        SELECT * FROM t1;
    }
    sql1 { INSERT INTO t1 VALUES(17, 18); }
  } {}

  do_test 2.$tn.14 {
    set us [lindex [time { catch {db eval "PRAGMA wal_checkpoint=RESTART"} }] 0]
    expr $us>1000000 && $us<4000000
  } {1}
  
}

#-------------------------------------------------------------------------
reset_db
sqlite3 db2 test.db
db2 timeout 1000
do_execsql_test 3.0 {
  PRAGMA journal_mode = wal;
  CREATE TABLE x1(x, y);
  BEGIN;
    INSERT INTO x1 VALUES(1, 2);
} {wal}

do_test 3.1 {
  list [catch { db2 eval {BEGIN EXCLUSIVE} } msg] $msg
} {1 {database is locked}}

finish_test

Changes to test/walshared.test.

12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
12
13
14
15
16
17
18

19
20
21
22
23
24
25
26







-
+







# focus of this file is testing the operation of the library in
# "PRAGMA journal_mode=WAL" mode with shared-cache turned on.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable !wal {finish_test ; return }
ifcapable !wal||!shared_cache {finish_test ; return }

db close
set ::enable_shared_cache [sqlite3_enable_shared_cache 1]

sqlite3 db  test.db
sqlite3 db2 test.db

Added test/walvfs.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2018 December 23
#
# 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 the operation of the library in
# "PRAGMA journal_mode=WAL" mode.
#
# TESTRUNNER: slow

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/malloc_common.tcl
source $testdir/wal_common.tcl
set testprefix walvfs

ifcapable !wal {finish_test ; return }

db close
testvfs tvfs 
tvfs script xSync
tvfs filter xSync
set ::sync_count 0
proc xSync {method file args} {
  if {[file tail $file]=="test.db-wal"} {
    incr ::sync_count
  }
}


#-------------------------------------------------------------------------
# Test that if IOCAP_SEQUENTIAL is set, the wal-header is not synced to
# disk immediately after it is written.
#
sqlite3 db test.db -vfs tvfs
do_execsql_test 1.0 {
  PRAGMA auto_vacuum = 0;
  PRAGMA journal_mode = wal;
  PRAGMA synchronous = normal;
  CREATE TABLE t1(a, b, c);
  INSERT INTO t1 VALUES(1, 2, 3);
  INSERT INTO t1 VALUES(4, 5, 6);
  INSERT INTO t1 VALUES(7, 8, 9);
  PRAGMA wal_checkpoint;
} {wal 0 5 5}

set ::sync_count 0
do_test 1.1 {
  execsql { INSERT INTO t1 VALUES(10, 11, 12) }
  set ::sync_count
} 1

db close
tvfs devchar sequential
sqlite3 db test.db -vfs tvfs
do_execsql_test 1.2 {
  PRAGMA synchronous = normal;
  INSERT INTO t1 VALUES(13, 14, 15);
  INSERT INTO t1 VALUES(16, 17, 18);
  PRAGMA wal_checkpoint;
} {0 4 4}

set ::sync_count 0
do_test 1.3 {
  execsql { INSERT INTO t1 VALUES(10, 11, 12) }
  set ::sync_count
} 0

#-------------------------------------------------------------------------
# Test that "PRAGMA journal_size_limit" works in wal mode.
#
reset_db
do_execsql_test 2.0 {
  PRAGMA journal_size_limit = 10000;
  CREATE TABLE t1(x);
  PRAGMA journal_mode = wal;
  WITH s(i) AS (
    SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 20
  )
  INSERT INTO t1 SELECT randomblob(750) FROM s;
} {10000 wal}
do_test 2.1 {
  expr [file size test.db-wal]>12000
} {1}
do_test 2.2 {
  execsql {
    PRAGMA wal_checkpoint;
    INSERT INTO t1 VALUES(randomblob(750));
  }
  file size test.db-wal
} {10000}
do_test 2.3 {
  execsql {
    PRAGMA journal_size_limit = 8000;
    PRAGMA wal_checkpoint;
    INSERT INTO t1 VALUES(randomblob(750));
  }
  file size test.db-wal
} {8000}

#-------------------------------------------------------------------------
# Test that a checkpoint may be interrupted using sqlite3_interrupt().
# And that the error code is SQLITE_NOMEM, not SQLITE_INTERRUPT, if
# an OOM error occurs just before the sqlite3_interrupt() call.
#
reset_db
db close
sqlite3 db test.db -vfs tvfs
tvfs filter {}

do_execsql_test 3.0 {
  CREATE TABLE t1(x);
  PRAGMA journal_mode = wal;
  WITH s(i) AS (
    SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 20
  )
  INSERT INTO t1 SELECT randomblob(750) FROM s;
} {wal}

tvfs filter xWrite
tvfs script xWrite
set ::cnt 2
proc xWrite {method file args} {
  if {[file tail $file]=="test.db"} {
    incr ::cnt -1
    if {$::cnt==0} {
      sqlite3_interrupt db
    }
  }
  return SQLITE_OK
}

do_catchsql_test 3.1 {
  PRAGMA wal_checkpoint
} {1 interrupted}

set ::cnt 2
proc xWrite {method file args} {
  if {[file tail $file]=="test.db"} {
    incr ::cnt -1
    if {$::cnt==0} {
      sqlite3_memdebug_fail 1 -repeat 0
      # For this test to pass, the following statement must call malloc() at 
      # least once. Even if the lookaside is enabled.
      set ::xwrite_stmt_res [catchsql { SELECT hex(randomblob(4000)) }]
      sqlite3_interrupt db
    }
  }
  return SQLITE_OK
}

set ::xwrite_stmt_res ""
do_catchsql_test 3.2 {
  PRAGMA wal_checkpoint
} {1 {out of memory}}
do_test 3.2.2 {
  set ::xwrite_stmt_res
} {1 {out of memory}}
unset ::xwrite_stmt_res

#-------------------------------------------------------------------------
#
reset_db
db close
do_test 4.0 {
  sqlite3 db test.db -vfs tvfs
  execsql {
    CREATE TABLE t1(x);
    PRAGMA journal_mode = wal;
    WITH s(i) AS (
        SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 20
    )
    INSERT INTO t1 SELECT randomblob(750) FROM s;
  } db
} {wal}
db close

tvfs filter xShmMap
tvfs script xShmMap
proc xShmMap {method file args} { 
  return SQLITE_READONLY 
}
sqlite3 db test.db -vfs tvfs
do_catchsql_test 4.1 {
  SELECT count(*) FROM t1
} {1 {attempt to write a readonly database}}

set ::cnt 5
tvfs filter {xShmMap xShmLock}
proc xShmMap {method file name args} { 
  switch -- $method {
    xShmMap {  return SQLITE_READONLY }
    xShmLock {
      if {$args == "{0 1 lock shared}"} {
        incr ::cnt -1
        if {$::cnt>0} { return SQLITE_BUSY }
      }
    }
  }
  return SQLITE_OK
}
do_catchsql_test 4.2 {
  SELECT count(*) FROM t1
} {1 {attempt to write a readonly database}}

#-------------------------------------------------------------------------
#
reset_db
db close 
sqlite3 db test.db -vfs tvfs
tvfs filter {}
do_execsql_test 5.0 {
  PRAGMA auto_vacuum = 0;
  PRAGMA page_size = 1024;
  CREATE TABLE t1(x);
  PRAGMA journal_mode = wal;
  WITH s(i) AS (
      SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 20
  )
  INSERT INTO t1 SELECT randomblob(750) FROM s;
} {wal}

do_execsql_test 5.1 {
  SELECT count(*) FROM t1
} {20}

do_test 5.2 {
  vfs_set_readmark db main 1 100
  vfs_set_readmark db main 2 100
  vfs_set_readmark db main 3 100
  vfs_set_readmark db main 4 100
} {100}

do_execsql_test 5.3 {
  SELECT count(*) FROM t1
} {20}

do_test 5.3 {
  list [vfs_set_readmark db main 1] \
       [vfs_set_readmark db main 2] \
       [vfs_set_readmark db main 3] \
       [vfs_set_readmark db main 4] 
} {24 100 100 100}

tvfs script xShmLock
tvfs filter xShmLock
set ::cnt 20
proc xShmLock {args} {
  incr ::cnt -1
  if {$::cnt>0} { return SQLITE_BUSY }
  return SQLITE_OK
}

do_test 5.4 {
  vfs_set_readmark db main 1 100
  execsql { SELECT count(*) FROM t1 }
} {20}

vfs_set_readmark db main 1 100
vfs_set_readmark db main 2 100
vfs_set_readmark db main 3 100
vfs_set_readmark db main 4 100

tvfs script xShmMapLock
tvfs filter {xShmLock xShmMap}
proc xShmMapLock {method args} {
  if {$method=="xShmMap"} {
    return "SQLITE_READONLY"
  }
  return SQLITE_BUSY
}

sqlite3 db2 test.db -vfs tvfs
breakpoint
do_test 5.5 {
  list [catch { execsql { SELECT count(*) FROM t1 } db2 } msg] $msg
} {1 {attempt to write a readonly database}}

tvfs filter {}
vfs_set_readmark db main 1 1

do_test 5.6 {
  list [catch { execsql { SELECT count(*) FROM t1 } db2 } msg] $msg
} {0 20}
db2 close
db close

#-------------------------------------------------------------------------
# Cause an SQLITE_PROTOCOL while attempting to restart the wal file.
#
reset_db
tvfs filter {}
db close
sqlite3 db test.db -vfs tvfs
do_execsql_test 6.0 {
  PRAGMA auto_vacuum = 0;
  PRAGMA page_size = 1024;
  CREATE TABLE t1(x);
  PRAGMA journal_mode = wal;
  WITH s(i) AS (
      SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 20
  )
  INSERT INTO t1 SELECT randomblob(750) FROM s;
} {wal}

do_test 6.1 {
  execsql { PRAGMA wal_checkpoint } 
  set {} {}
} {}

tvfs filter xShmLock
tvfs script xShmLock
set ::flag 0
proc xShmLock {method file handle spec} {
  if {$::flag && [lrange $spec 2 end]=="lock shared"} {
    return SQLITE_BUSY
  }
  if {$spec=="3 1 unlock shared"} {
    set ::flag 1
  }
  return SQLITE_OK
}

puts "# WARNING: This next test takes around 12 seconds"
do_catchsql_test 6.2 {
  INSERT INTO t1 VALUES(1);
} {1 {locking protocol}}

#-------------------------------------------------------------------------
# Check that a checkpoint fails if it cannot get the CHECKPOINTER lock
#
reset_db
tvfs filter {}
db close
sqlite3 db test.db -vfs tvfs
do_execsql_test 7.0 {
  PRAGMA auto_vacuum = 0;
  PRAGMA page_size = 1024;
  CREATE TABLE t1(x);
  PRAGMA journal_mode = wal;
  WITH s(i) AS (
      SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 20
  )
  INSERT INTO t1 SELECT randomblob(750) FROM s;
} {wal}

tvfs script xShmLock
tvfs filter xShmLock
proc xShmLock {method file handle spec} {
  if {$spec=="1 1 lock exclusive"} {
    return SQLITE_BUSY
  }
  return SQLITE_OK
}

do_execsql_test 7.1 {
  PRAGMA wal_checkpoint
} {1 -1 -1}

#-------------------------------------------------------------------------
# Check that the page cache is correctly flushed if a checkpointer using
# a version 2 VFS makes a checkpoint with an out-of-date cache.
#
reset_db
testvfs tvfs2 -iversion 2
db close
sqlite3 db test.db -vfs tvfs2
do_execsql_test 8.0 {
  PRAGMA auto_vacuum = 0;
  PRAGMA page_size = 1024;
  CREATE TABLE t1(x);
  PRAGMA journal_mode = wal;
  WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 20 )
  INSERT INTO t1 SELECT randomblob(75) FROM s;
} {wal}

do_execsql_test 8.1 { SELECT count(*) FROM t1 } {20}

do_test 8.2 {
  sqlite3 db2 test.db -vfs tvfs2
  execsql {
    INSERT INTO t1 VALUES(randomblob(75));
  } db2
  db2 close
} {}

do_execsql_test 8.3 { 
  PRAGMA wal_checkpoint;
  SELECT count(*) FROM t1 
} {0 5 5 21}
db close
tvfs2 delete

#-------------------------------------------------------------------------
reset_db
db close
sqlite3 db test.db -vfs tvfs
do_execsql_test 9.0 {
  PRAGMA auto_vacuum = 0;
  PRAGMA page_size = 1024;
  CREATE TABLE t1(x);
  PRAGMA journal_mode = wal;
  WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 20 )
  INSERT INTO t1 SELECT randomblob(75) FROM s;
} {wal}

sqlite3 db2 test.db -vfs tvfs
tvfs filter {xShmMap xShmLock}
tvfs script xShmMap
proc xShmMap {method file handle args} {
  switch -- $method {
    xShmMap {
      return "SQLITE_READONLY_CANTINIT"
    }
    xShmLock {
      if {$args=="{3 1 lock shared}"} {
        return "SQLITE_IOERR"
      }
    }
  }
}

do_test 9.1 {
  catchsql { SELECT count(*) FROM t1 } db2
} {1 {disk I/O error}}

db close
db2 close
tvfs delete
finish_test

Added test/wapp.tcl.




























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# Copyright (c) 2017 D. Richard Hipp
# 
# This program is free software; you can redistribute it and/or
# modify it under the terms of the Simplified BSD License (also
# known as the "2-Clause License" or "FreeBSD License".)
#
# This program is distributed in the hope that it will be useful,
# but without any warranty; without even the implied warranty of
# merchantability or fitness for a particular purpose.
#
#---------------------------------------------------------------------------
#
# Design rules:
#
#   (1)  All identifiers in the global namespace begin with "wapp"
#
#   (2)  Indentifiers intended for internal use only begin with "wappInt"
#
package require Tcl 8.6

# Add text to the end of the HTTP reply.  No interpretation or transformation
# of the text is performs.  The argument should be enclosed within {...}
#
proc wapp {txt} {
  global wapp
  dict append wapp .reply $txt
}

# Add text to the page under construction.  Do no escaping on the text.
#
# Though "unsafe" in general, there are uses for this kind of thing.
# For example, if you want to return the complete, unmodified content of
# a file:
#
#         set fd [open content.html rb]
#         wapp-unsafe [read $fd]
#         close $fd
#
# You could do the same thing using ordinary "wapp" instead of "wapp-unsafe".
# The difference is that wapp-safety-check will complain about the misuse
# of "wapp", but it assumes that the person who write "wapp-unsafe" understands
# the risks.
#
# Though occasionally necessary, the use of this interface should be minimized.
#
proc wapp-unsafe {txt} {
  global wapp
  dict append wapp .reply $txt
}

# Add text to the end of the reply under construction.  The following
# substitutions are made:
#
#     %html(...)          Escape text for inclusion in HTML
#     %url(...)           Escape text for use as a URL
#     %qp(...)            Escape text for use as a URI query parameter
#     %string(...)        Escape text for use within a JSON string
#     %unsafe(...)        No transformations of the text
#
# The substitutions above terminate at the first ")" character.  If the
# text of the TCL string in ... contains ")" characters itself, use instead:
#
#     %html%(...)%
#     %url%(...)%
#     %qp%(...)%
#     %string%(...)%
#     %unsafe%(...)%
#
# In other words, use "%(...)%" instead of "(...)" to include the TCL string
# to substitute.
#
# The %unsafe substitution should be avoided whenever possible, obviously.
# In addition to the substitutions above, the text also does backslash
# escapes.
#
# The wapp-trim proc works the same as wapp-subst except that it also removes
# whitespace from the left margin, so that the generated HTML/CSS/Javascript
# does not appear to be indented when delivered to the client web browser.
#
if {$tcl_version>=8.7} {
  proc wapp-subst {txt} {
    global wapp
    regsub -all -command \
       {%(html|url|qp|string|unsafe){1,1}?(|%)\((.+)\)\2} $txt wappInt-enc txt
    dict append wapp .reply [subst -novariables -nocommand $txt]
  }
  proc wapp-trim {txt} {
    global wapp
    regsub -all {\n\s+} [string trim $txt] \n txt
    regsub -all -command \
       {%(html|url|qp|string|unsafe){1,1}?(|%)\((.+)\)\2} $txt wappInt-enc txt
    dict append wapp .reply [subst -novariables -nocommand $txt]
  }
  proc wappInt-enc {all mode nu1 txt} {
    return [uplevel 2 "wappInt-enc-$mode \"$txt\""]
  }
} else {
  proc wapp-subst {txt} {
    global wapp
    regsub -all {%(html|url|qp|string|unsafe){1,1}?(|%)\((.+)\)\2} $txt \
           {[wappInt-enc-\1 "\3"]} txt
    dict append wapp .reply [uplevel 1 [list subst -novariables $txt]]
  }
  proc wapp-trim {txt} {
    global wapp
    regsub -all {\n\s+} [string trim $txt] \n txt
    regsub -all {%(html|url|qp|string|unsafe){1,1}?(|%)\((.+)\)\2} $txt \
           {[wappInt-enc-\1 "\3"]} txt
    dict append wapp .reply [uplevel 1 [list subst -novariables $txt]]
  }
}

# There must be a wappInt-enc-NAME routine for each possible substitution
# in wapp-subst.  Thus there are routines for "html", "url", "qp", and "unsafe".
#
#    wappInt-enc-html           Escape text so that it is safe to use in the
#                               body of an HTML document.
#
#    wappInt-enc-url            Escape text so that it is safe to pass as an
#                               argument to href= and src= attributes in HTML.
#
#    wappInt-enc-qp             Escape text so that it is safe to use as the
#                               value of a query parameter in a URL or in
#                               post data or in a cookie.
#
#    wappInt-enc-string         Escape ", ', \, and < for using inside of a
#                               javascript string literal.  The < character
#                               is escaped to prevent "</script>" from causing
#                               problems in embedded javascript.
#
#    wappInt-enc-unsafe         Perform no encoding at all.  Unsafe.
#
proc wappInt-enc-html {txt} {
  return [string map {& &amp; < &lt; > &gt; \" &quot; \\ &#92;} $txt]
}
proc wappInt-enc-unsafe {txt} {
  return $txt
}
proc wappInt-enc-url {s} {
  if {[regsub -all {[^-{}@~?=#_.:/a-zA-Z0-9]} $s {[wappInt-%HHchar {&}]} s]} {
    set s [subst -novar -noback $s]
  }
  if {[regsub -all {[{}]} $s {[wappInt-%HHchar \\&]} s]} {
    set s [subst -novar -noback $s]
  }
  return $s
}
proc wappInt-enc-qp {s} {
  if {[regsub -all {[^-{}_.a-zA-Z0-9]} $s {[wappInt-%HHchar {&}]} s]} {
    set s [subst -novar -noback $s]
  }
  if {[regsub -all {[{}]} $s {[wappInt-%HHchar \\&]} s]} {
    set s [subst -novar -noback $s]
  }
  return $s
}
proc wappInt-enc-string {s} {
  return [string map {\\ \\\\ \" \\\" ' \\' < \\u003c} $s]
}

# This is a helper routine for wappInt-enc-url and wappInt-enc-qp.  It returns
# an appropriate %HH encoding for the single character c.  If c is a unicode
# character, then this routine might return multiple bytes:  %HH%HH%HH
#
proc wappInt-%HHchar {c} {
  if {$c==" "} {return +}
  return [regsub -all .. [binary encode hex [encoding convertto utf-8 $c]] {%&}]
}


# Undo the www-url-encoded format.
#
# HT: This code stolen from ncgi.tcl
#
proc wappInt-decode-url {str} {
  set str [string map [list + { } "\\" "\\\\" \[ \\\[ \] \\\]] $str]
  regsub -all -- \
      {%([Ee][A-Fa-f0-9])%([89ABab][A-Fa-f0-9])%([89ABab][A-Fa-f0-9])} \
      $str {[encoding convertfrom utf-8 [binary decode hex \1\2\3]]} str
  regsub -all -- \
      {%([CDcd][A-Fa-f0-9])%([89ABab][A-Fa-f0-9])}                     \
      $str {[encoding convertfrom utf-8 [binary decode hex \1\2]]} str
  regsub -all -- {%([0-7][A-Fa-f0-9])} $str {\\u00\1} str
  return [subst -novar $str]
}

# Reset the document back to an empty string.
#
proc wapp-reset {} {
  global wapp
  dict set wapp .reply {}
}

# Change the mime-type of the result document.
#
proc wapp-mimetype {x} {
  global wapp
  dict set wapp .mimetype $x
}

# Change the reply code.
#
proc wapp-reply-code {x} {
  global wapp
  dict set wapp .reply-code $x
}

# Set a cookie
#
proc wapp-set-cookie {name value} {
  global wapp
  dict lappend wapp .new-cookies $name $value
}

# Unset a cookie
#
proc wapp-clear-cookie {name} {
  wapp-set-cookie $name {}
}

# Add extra entries to the reply header
#
proc wapp-reply-extra {name value} {
  global wapp
  dict lappend wapp .reply-extra $name $value
}

# Specifies how the web-page under construction should be cached.
# The argument should be one of:
#
#    no-cache
#    max-age=N             (for some integer number of seconds, N)
#    private,max-age=N
#
proc wapp-cache-control {x} {
  wapp-reply-extra Cache-Control $x
}

# Redirect to a different web page
#
proc wapp-redirect {uri} {
  wapp-reply-code {307 Redirect}
  wapp-reply-extra Location $uri
}

# Return the value of a wapp parameter
#
proc wapp-param {name {dflt {}}} {
  global wapp
  if {![dict exists $wapp $name]} {return $dflt}
  return [dict get $wapp $name]
}

# Return true if a and only if the wapp parameter $name exists
#
proc wapp-param-exists {name} {
  global wapp
  return [dict exists $wapp $name]
}

# Set the value of a wapp parameter
#
proc wapp-set-param {name value} {
  global wapp
  dict set wapp $name $value
}

# Return all parameter names that match the GLOB pattern, or all
# names if the GLOB pattern is omitted.
#
proc wapp-param-list {{glob {*}}} {
  global wapp
  return [dict keys $wapp $glob]
}

# By default, Wapp does not decode query parameters and POST parameters
# for cross-origin requests.  This is a security restriction, designed to
# help prevent cross-site request forgery (CSRF) attacks.
#
# As a consequence of this restriction, URLs for sites generated by Wapp
# that contain query parameters will not work as URLs found in other
# websites.  You cannot create a link from a second website into a Wapp
# website if the link contains query planner, by default.
#
# Of course, it is sometimes desirable to allow query parameters on external
# links.  For URLs for which this is safe, the application should invoke
# wapp-allow-xorigin-params.  This procedure tells Wapp that it is safe to
# go ahead and decode the query parameters even for cross-site requests.
#
# In other words, for Wapp security is the default setting.  Individual pages
# need to actively disable the cross-site request security if those pages
# are safe for cross-site access.
#
proc wapp-allow-xorigin-params {} {
  global wapp
  if {![dict exists $wapp .qp] && ![dict get $wapp SAME_ORIGIN]} {
    wappInt-decode-query-params
  }
}

# Set the content-security-policy.
#
# The default content-security-policy is very strict:  "default-src 'self'"
# The default policy prohibits the use of in-line javascript or CSS.
#
# Provide an alternative CSP as the argument.  Or use "off" to disable
# the CSP completely.
#
proc wapp-content-security-policy {val} {
  global wapp
  if {$val=="off"} {
    dict unset wapp .csp
  } else {
    dict set wapp .csp $val
  }
}

# Examine the bodys of all procedures in this program looking for
# unsafe calls to various Wapp interfaces.  Return a text string
# containing warnings. Return an empty string if all is ok.
#
# This routine is advisory only.  It misses some constructs that are
# dangerous and flags others that are safe.
#
proc wapp-safety-check {} {
  set res {}
  foreach p [info procs] {
    set ln 0
    foreach x [split [info body $p] \n] {
      incr ln
      if {[regexp {^[ \t]*wapp[ \t]+([^\n]+)} $x all tail]
       && [string index $tail 0]!="\173"
       && [regexp {[[$]} $tail]
      } {
        append res "$p:$ln: unsafe \"wapp\" call: \"[string trim $x]\"\n"
      }
      if {[regexp {^[ \t]*wapp-(subst|trim)[ \t]+[^\173]} $x all cx]} {
        append res "$p:$ln: unsafe \"wapp-$cx\" call: \"[string trim $x]\"\n"
      }
    }
  }
  return $res
}

# Return a string that descripts the current environment.  Applications
# might find this useful for debugging.
#
proc wapp-debug-env {} {
  global wapp
  set out {}
  foreach var [lsort [dict keys $wapp]] {
    if {[string index $var 0]=="."} continue
    append out "$var = [list [dict get $wapp $var]]\n"
  }
  append out "\[pwd\] = [list [pwd]]\n"
  return $out
}

# Tracing function for each HTTP request.  This is overridden by wapp-start
# if tracing is enabled.
#
proc wappInt-trace {} {}

# Start up a listening socket.  Arrange to invoke wappInt-new-connection
# for each inbound HTTP connection.
#
#    port            Listen on this TCP port.  0 means to select a port
#                    that is not currently in use
#
#    wappmode        One of "scgi", "remote-scgi", "server", or "local".
#
#    fromip          If not {}, then reject all requests from IP addresses
#                    other than $fromip
#
proc wappInt-start-listener {port wappmode fromip} {
  if {[string match *scgi $wappmode]} {
    set type SCGI
    set server [list wappInt-new-connection \
                wappInt-scgi-readable $wappmode $fromip]
  } else {
    set type HTTP
    set server [list wappInt-new-connection \
                wappInt-http-readable $wappmode $fromip]
  }
  if {$wappmode=="local" || $wappmode=="scgi"} {
    set x [socket -server $server -myaddr 127.0.0.1 $port]
  } else {
    set x [socket -server $server $port]
  }
  set coninfo [chan configure $x -sockname]
  set port [lindex $coninfo 2]
  if {$wappmode=="local"} {
    wappInt-start-browser http://127.0.0.1:$port/
  } elseif {$fromip!=""} {
    puts "Listening for $type requests on TCP port $port from IP $fromip"
  } else {
    puts "Listening for $type requests on TCP port $port"
  }
}

# Start a web-browser and point it at $URL
#
proc wappInt-start-browser {url} {
  global tcl_platform
  if {$tcl_platform(platform)=="windows"} {
    exec cmd /c start $url &
  } elseif {$tcl_platform(os)=="Darwin"} {
    exec open $url &
  } elseif {[catch {exec xdg-open $url}]} {
    exec firefox $url &
  }
}

# This routine is a "socket -server" callback.  The $chan, $ip, and $port
# arguments are added by the socket command.
#
# Arrange to invoke $callback when content is available on the new socket.
# The $callback will process inbound HTTP or SCGI content.  Reject the
# request if $fromip is not an empty string and does not match $ip.
#
proc wappInt-new-connection {callback wappmode fromip chan ip port} {
  upvar #0 wappInt-$chan W
  if {$fromip!="" && ![string match $fromip $ip]} {
    close $chan
    return
  }
  set W [dict create REMOTE_ADDR $ip REMOTE_PORT $port WAPP_MODE $wappmode \
         .header {}]
  fconfigure $chan -blocking 0 -translation binary
  fileevent $chan readable [list $callback $chan]
}

# Close an input channel
#
proc wappInt-close-channel {chan} {
  if {$chan=="stdout"} {
    # This happens after completing a CGI request
    exit 0
  } else {
    unset ::wappInt-$chan
    close $chan
  }
}

# Process new text received on an inbound HTTP request
#
proc wappInt-http-readable {chan} {
  if {[catch [list wappInt-http-readable-unsafe $chan] msg]} {
    puts stderr "$msg\n$::errorInfo"
    wappInt-close-channel $chan
  }
}
proc wappInt-http-readable-unsafe {chan} {
  upvar #0 wappInt-$chan W wapp wapp
  if {![dict exists $W .toread]} {
    # If the .toread key is not set, that means we are still reading
    # the header
    set line [string trimright [gets $chan]]
    set n [string length $line]
    if {$n>0} {
      if {[dict get $W .header]=="" || [regexp {^\s+} $line]} {
        dict append W .header $line
      } else {
        dict append W .header \n$line
      }
      if {[string length [dict get $W .header]]>100000} {
        error "HTTP request header too big - possible DOS attack"
      }
    } elseif {$n==0} {
      # We have reached the blank line that terminates the header.
      global argv0
      set a0 [file normalize $argv0]
      dict set W SCRIPT_FILENAME $a0
      dict set W DOCUMENT_ROOT [file dir $a0]
      if {[wappInt-parse-header $chan]} {
        catch {close $chan}
        return
      }
      set len 0
      if {[dict exists $W CONTENT_LENGTH]} {
        set len [dict get $W CONTENT_LENGTH]
      }
      if {$len>0} {
        # Still need to read the query content
        dict set W .toread $len
      } else {
        # There is no query content, so handle the request immediately
        set wapp $W
        wappInt-handle-request $chan 0
      }
    }
  } else {
    # If .toread is set, that means we are reading the query content.
    # Continue reading until .toread reaches zero.
    set got [read $chan [dict get $W .toread]]
    dict append W CONTENT $got
    dict set W .toread [expr {[dict get $W .toread]-[string length $got]}]
    if {[dict get $W .toread]<=0} {
      # Handle the request as soon as all the query content is received
      set wapp $W
      wappInt-handle-request $chan 0
    }
  }
}

# Decode the HTTP request header.
#
# This routine is always running inside of a [catch], so if
# any problems arise, simply raise an error.
#
proc wappInt-parse-header {chan} {
  upvar #0 wappInt-$chan W
  set hdr [split [dict get $W .header] \n]
  if {$hdr==""} {return 1}
  set req [lindex $hdr 0]
  dict set W REQUEST_METHOD [set method [lindex $req 0]]
  if {[lsearch {GET HEAD POST} $method]<0} {
    error "unsupported request method: \"[dict get $W REQUEST_METHOD]\""
  }
  set uri [lindex $req 1]
  set split_uri [split $uri ?]
  set uri0 [lindex $split_uri 0]
  if {![regexp {^/[-.a-z0-9_/]*$} $uri0]} {
    error "invalid request uri: \"$uri0\""
  }
  dict set W REQUEST_URI $uri0
  dict set W PATH_INFO $uri0
  set uri1 [lindex $split_uri 1]
  dict set W QUERY_STRING $uri1
  set n [llength $hdr]
  for {set i 1} {$i<$n} {incr i} {
    set x [lindex $hdr $i]
    if {![regexp {^(.+): +(.*)$} $x all name value]} {
      error "invalid header line: \"$x\""
    }
    set name [string toupper $name]
    switch -- $name {
      REFERER {set name HTTP_REFERER}
      USER-AGENT {set name HTTP_USER_AGENT}
      CONTENT-LENGTH {set name CONTENT_LENGTH}
      CONTENT-TYPE {set name CONTENT_TYPE}
      HOST {set name HTTP_HOST}
      COOKIE {set name HTTP_COOKIE}
      ACCEPT-ENCODING {set name HTTP_ACCEPT_ENCODING}
      default {set name .hdr:$name}
    }
    dict set W $name $value
  }
  return 0
}

# Decode the QUERY_STRING parameters from a GET request or the
# application/x-www-form-urlencoded CONTENT from a POST request.
#
# This routine sets the ".qp" element of the ::wapp dict as a signal
# that query parameters have already been decoded.
#
proc wappInt-decode-query-params {} {
  global wapp
  dict set wapp .qp 1
  if {[dict exists $wapp QUERY_STRING]} {
    foreach qterm [split [dict get $wapp QUERY_STRING] &] {
      set qsplit [split $qterm =]
      set nm [lindex $qsplit 0]
      if {[regexp {^[a-z][a-z0-9]*$} $nm]} {
        dict set wapp $nm [wappInt-decode-url [lindex $qsplit 1]]
      }
    }
  }
  if {[dict exists $wapp CONTENT_TYPE] && [dict exists $wapp CONTENT]} {
    set ctype [dict get $wapp CONTENT_TYPE]
    if {$ctype=="application/x-www-form-urlencoded"} {
      foreach qterm [split [string trim [dict get $wapp CONTENT]] &] {
        set qsplit [split $qterm =]
        set nm [lindex $qsplit 0]
        if {[regexp {^[a-z][-a-z0-9_]*$} $nm]} {
          dict set wapp $nm [wappInt-decode-url [lindex $qsplit 1]]
        }
      }
    } elseif {[string match multipart/form-data* $ctype]} {
      regexp {^(.*?)\r\n(.*)$} [dict get $wapp CONTENT] all divider body
      set ndiv [string length $divider]
      while {[string length $body]} {
        set idx [string first $divider $body]
        set unit [string range $body 0 [expr {$idx-3}]]
        set body [string range $body [expr {$idx+$ndiv+2}] end]
        if {[regexp {^Content-Disposition: form-data; (.*?)\r\n\r\n(.*)$} \
             $unit unit hdr content]} {
          if {[regexp {name="(.*)"; filename="(.*)"\r\nContent-Type: (.*?)$}\
                $hdr hr name filename mimetype]} {
            dict set wapp $name.filename \
              [string map [list \\\" \" \\\\ \\] $filename]
            dict set wapp $name.mimetype $mimetype
            dict set wapp $name.content $content
          } elseif {[regexp {name="(.*)"} $hdr hr name]} {
            dict set wapp $name $content
          }
        }
      }
    }
  }
}

# Invoke application-supplied methods to generate a reply to
# a single HTTP request.
#
# This routine always runs within [catch], so handle exceptions by
# invoking [error].
#
proc wappInt-handle-request {chan useCgi} {
  global wapp
  dict set wapp .reply {}
  dict set wapp .mimetype {text/html; charset=utf-8}
  dict set wapp .reply-code {200 Ok}
  dict set wapp .csp {default-src 'self'}

  # Set up additional CGI environment values
  #
  if {![dict exists $wapp HTTP_HOST]} {
    dict set wapp BASE_URL {}
  } elseif {[dict exists $wapp HTTPS]} {
    dict set wapp BASE_URL https://[dict get $wapp HTTP_HOST]
  } else {
    dict set wapp BASE_URL http://[dict get $wapp HTTP_HOST]
  }
  if {![dict exists $wapp REQUEST_URI]} {
    dict set wapp REQUEST_URI /
  } elseif {[regsub {\?.*} [dict get $wapp REQUEST_URI] {} newR]} {
    # Some servers (ex: nginx) append the query parameters to REQUEST_URI.
    # These need to be stripped off
    dict set wapp REQUEST_URI $newR
  }
  if {[dict exists $wapp SCRIPT_NAME]} {
    dict append wapp BASE_URL [dict get $wapp SCRIPT_NAME]
  } else {
    dict set wapp SCRIPT_NAME {}
  }
  if {![dict exists $wapp PATH_INFO]} {
    # If PATH_INFO is missing (ex: nginx) then construct it
    set URI [dict get $wapp REQUEST_URI]
    set skip [string length [dict get $wapp SCRIPT_NAME]]
    dict set wapp PATH_INFO [string range $URI $skip end]
  }
  if {[regexp {^/([^/]+)(.*)$} [dict get $wapp PATH_INFO] all head tail]} {
    dict set wapp PATH_HEAD $head
    dict set wapp PATH_TAIL [string trimleft $tail /]
  } else {
    dict set wapp PATH_INFO {}
    dict set wapp PATH_HEAD {}
    dict set wapp PATH_TAIL {}
  }
  dict set wapp SELF_URL [dict get $wapp BASE_URL]/[dict get $wapp PATH_HEAD]

  # Parse query parameters from the query string, the cookies, and
  # POST data
  #
  if {[dict exists $wapp HTTP_COOKIE]} {
    foreach qterm [split [dict get $wapp HTTP_COOKIE] {;}] {
      set qsplit [split [string trim $qterm] =]
      set nm [lindex $qsplit 0]
      if {[regexp {^[a-z][-a-z0-9_]*$} $nm]} {
        dict set wapp $nm [wappInt-decode-url [lindex $qsplit 1]]
      }
    }
  }
  set same_origin 0
  if {[dict exists $wapp HTTP_REFERER]} {
    set referer [dict get $wapp HTTP_REFERER]
    set base [dict get $wapp BASE_URL]
    if {$referer==$base || [string match $base/* $referer]} {
      set same_origin 1
    }
  }
  dict set wapp SAME_ORIGIN $same_origin
  if {$same_origin} {
    wappInt-decode-query-params
  }

  # Invoke the application-defined handler procedure for this page
  # request.  If an error occurs while running that procedure, generate
  # an HTTP reply that contains the error message.
  #
  wapp-before-dispatch-hook
  wappInt-trace
  set mname [dict get $wapp PATH_HEAD]
  if {[catch {
    if {$mname!="" && [llength [info proc wapp-page-$mname]]>0} {
      wapp-page-$mname
    } else {
      wapp-default
    }
  } msg]} {
    if {[wapp-param WAPP_MODE]=="local" || [wapp-param WAPP_MODE]=="server"} {
      puts "ERROR: $::errorInfo"
    }
    wapp-reset
    wapp-reply-code "500 Internal Server Error"
    wapp-mimetype text/html
    wapp-trim {
      <h1>Wapp Application Error</h1>
      <pre>%html($::errorInfo)</pre>
    }
    dict unset wapp .new-cookies
  }

  # Transmit the HTTP reply
  #
  if {$chan=="stdout"} {
    puts $chan "Status: [dict get $wapp .reply-code]\r"
  } else {
    puts $chan "HTTP/1.1 [dict get $wapp .reply-code]\r"
    puts $chan "Server: wapp\r"
    puts $chan "Connection: close\r"
  }
  if {[dict exists $wapp .reply-extra]} {
    foreach {name value} [dict get $wapp .reply-extra] {
      puts $chan "$name: $value\r"
    }
  }
  if {[dict exists $wapp .csp]} {
    puts $chan "Content-Security-Policy: [dict get $wapp .csp]\r"
  }
  set mimetype [dict get $wapp .mimetype]
  puts $chan "Content-Type: $mimetype\r"
  if {[dict exists $wapp .new-cookies]} {
    foreach {nm val} [dict get $wapp .new-cookies] {
      if {[regexp {^[a-z][-a-z0-9_]*$} $nm]} {
        if {$val==""} {
          puts $chan "Set-Cookie: $nm=; HttpOnly; Path=/; Max-Age=1\r"
        } else {
          set val [wappInt-enc-url $val]
          puts $chan "Set-Cookie: $nm=$val; HttpOnly; Path=/\r"
        }
      }
    }
  }
  if {[string match text/* $mimetype]} {
    set reply [encoding convertto utf-8 [dict get $wapp .reply]]
    if {[regexp {\ygzip\y} [wapp-param HTTP_ACCEPT_ENCODING]]} {
      catch {
        set x [zlib gzip $reply]
        set reply $x
        puts $chan "Content-Encoding: gzip\r"
      }
    }
  } else {
    set reply [dict get $wapp .reply]
  }
  puts $chan "Content-Length: [string length $reply]\r"
  puts $chan \r
  puts -nonewline $chan $reply
  flush $chan
  wappInt-close-channel $chan
}

# This routine runs just prior to request-handler dispatch.  The
# default implementation is a no-op, but applications can override
# to do additional transformations or checks.
#
proc wapp-before-dispatch-hook {} {return}

# Process a single CGI request
#
proc wappInt-handle-cgi-request {} {
  global wapp env
  foreach key {
    CONTENT_LENGTH
    CONTENT_TYPE
    DOCUMENT_ROOT
    HTTP_ACCEPT_ENCODING
    HTTP_COOKIE
    HTTP_HOST
    HTTP_REFERER
    HTTP_USER_AGENT
    HTTPS
    PATH_INFO
    QUERY_STRING
    REMOTE_ADDR
    REQUEST_METHOD
    REQUEST_URI
    REMOTE_USER
    SCRIPT_FILENAME
    SCRIPT_NAME
    SERVER_NAME
    SERVER_PORT
    SERVER_PROTOCOL
  } {
    if {[info exists env($key)]} {
      dict set wapp $key $env($key)
    }
  }
  set len 0
  if {[dict exists $wapp CONTENT_LENGTH]} {
    set len [dict get $wapp CONTENT_LENGTH]
  }
  if {$len>0} {
    fconfigure stdin -translation binary
    dict set wapp CONTENT [read stdin $len]
  }
  dict set wapp WAPP_MODE cgi
  fconfigure stdout -translation binary
  wappInt-handle-request stdout 1
}

# Process new text received on an inbound SCGI request
#
proc wappInt-scgi-readable {chan} {
  if {[catch [list wappInt-scgi-readable-unsafe $chan] msg]} {
    puts stderr "$msg\n$::errorInfo"
    wappInt-close-channel $chan
  }
}
proc wappInt-scgi-readable-unsafe {chan} {
  upvar #0 wappInt-$chan W wapp wapp
  if {![dict exists $W .toread]} {
    # If the .toread key is not set, that means we are still reading
    # the header.
    #
    # An SGI header is short.  This implementation assumes the entire
    # header is available all at once.
    #
    dict set W .remove_addr [dict get $W REMOTE_ADDR]
    set req [read $chan 15]
    set n [string length $req]
    scan $req %d:%s len hdr
    incr len [string length "$len:,"]
    append hdr [read $chan [expr {$len-15}]]
    foreach {nm val} [split $hdr \000] {
      if {$nm==","} break
      dict set W $nm $val
    }
    set len 0
    if {[dict exists $W CONTENT_LENGTH]} {
      set len [dict get $W CONTENT_LENGTH]
    }
    if {$len>0} {
      # Still need to read the query content
      dict set W .toread $len
    } else {
      # There is no query content, so handle the request immediately
      dict set W SERVER_ADDR [dict get $W .remove_addr]
      set wapp $W
      wappInt-handle-request $chan 0
    }
  } else {
    # If .toread is set, that means we are reading the query content.
    # Continue reading until .toread reaches zero.
    set got [read $chan [dict get $W .toread]]
    dict append W CONTENT $got
    dict set W .toread [expr {[dict get $W .toread]-[string length $got]}]
    if {[dict get $W .toread]<=0} {
      # Handle the request as soon as all the query content is received
      dict set W SERVER_ADDR [dict get $W .remove_addr]
      set wapp $W
      wappInt-handle-request $chan 0
    }
  }
}

# Start up the wapp framework.  Parameters are a list passed as the
# single argument.
#
#    -server $PORT         Listen for HTTP requests on this TCP port $PORT
#
#    -local $PORT          Listen for HTTP requests on 127.0.0.1:$PORT
#
#    -scgi $PORT           Listen for SCGI requests on 127.0.0.1:$PORT
#
#    -remote-scgi $PORT    Listen for SCGI requests on TCP port $PORT
#
#    -cgi                  Handle a single CGI request
#
# With no arguments, the behavior is called "auto".  In "auto" mode,
# if the GATEWAY_INTERFACE environment variable indicates CGI, then run
# as CGI.  Otherwise, start an HTTP server bound to the loopback address
# only, on an arbitrary TCP port, and automatically launch a web browser
# on that TCP port.
#
# Additional options:
#
#    -fromip GLOB         Reject any incoming request where the remote
#                         IP address does not match the GLOB pattern.  This
#                         value defaults to '127.0.0.1' for -local and -scgi.
#
#    -nowait              Do not wait in the event loop.  Return immediately
#                         after all event handlers are established.
#
#    -trace               "puts" each request URL as it is handled, for
#                         debugging
#
#    -lint                Run wapp-safety-check on the application instead
#                         of running the application itself
#
#    -Dvar=value          Set TCL global variable "var" to "value"
#
#
proc wapp-start {arglist} {
  global env
  set mode auto
  set port 0
  set nowait 0
  set fromip {}
  set n [llength $arglist]
  for {set i 0} {$i<$n} {incr i} {
    set term [lindex $arglist $i]
    if {[string match --* $term]} {set term [string range $term 1 end]}
    switch -glob -- $term {
      -server {
        incr i;
        set mode "server"
        set port [lindex $arglist $i]
      }
      -local {
        incr i;
        set mode "local"
        set fromip 127.0.0.1
        set port [lindex $arglist $i]
      }
      -scgi {
        incr i;
        set mode "scgi"
        set fromip 127.0.0.1
        set port [lindex $arglist $i]
      }
      -remote-scgi {
        incr i;
        set mode "remote-scgi"
        set port [lindex $arglist $i]
      }
      -cgi {
        set mode "cgi"
      }
      -fromip {
        incr i
        set fromip [lindex $arglist $i]
      }
      -nowait {
        set nowait 1
      }
      -trace {
        proc wappInt-trace {} {
          set q [wapp-param QUERY_STRING]
          set uri [wapp-param BASE_URL][wapp-param PATH_INFO]
          if {$q!=""} {append uri ?$q}
          puts $uri
        }
      }
      -lint {
        set res [wapp-safety-check]
        if {$res!=""} {
          puts "Potential problems in this code:"
          puts $res
          exit 1
        } else {
          exit
        }
      }
      -D*=* {
        if {[regexp {^.D([^=]+)=(.*)$} $term all var val]} {
          set ::$var $val
        }
      }
      default {
        error "unknown option: $term"
      }
    }
  }
  if {$mode=="auto"} {
    if {[info exists env(GATEWAY_INTERFACE)]
        && [string match CGI/1.* $env(GATEWAY_INTERFACE)]} {
      set mode cgi
    } else {
      set mode local
    }
  }
  if {$mode=="cgi"} {
    wappInt-handle-cgi-request
  } else {
    wappInt-start-listener $port $mode $fromip
    if {!$nowait} {
      vwait ::forever
    }
  }
}

# Call this version 1.0
package provide wapp 1.0

Added test/wapptest.tcl.














































































































































































































































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
908
909
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
#!/bin/sh
# \
exec wapptclsh "$0" ${1+"$@"}

# package required wapp
source [file join [file dirname [info script]] wapp.tcl]

# Variables set by the "control" form:
#
#   G(platform) - User selected platform.
#   G(cfgglob)  - Glob pattern that all configurations must match
#   G(test)     - Set to "Normal", "Veryquick", "Smoketest" or "Build-Only".
#   G(keep)     - Boolean. True to delete no files after each test.
#   G(msvc)     - Boolean. True to use MSVC as the compiler.
#   G(tcl)      - Use Tcl from this directory for builds.
#   G(jobs)     - How many sub-processes to run simultaneously.
#
set G(platform) $::tcl_platform(os)-$::tcl_platform(machine)
set G(cfgglob)  *
set G(test)     Normal
set G(keep)     1
set G(msvc)     0
set G(tcl)      [::tcl::pkgconfig get libdir,install]
set G(jobs)     3
set G(debug)    0

set G(noui)     0
set G(stdout)   0


proc wapptest_init {} {
  global G

  set lSave [list platform test keep msvc tcl jobs debug noui stdout cfgglob] 
  foreach k $lSave { set A($k) $G($k) }
  array unset G
  foreach k $lSave { set G($k) $A($k) }

  # The root of the SQLite source tree.
  set G(srcdir)   [file dirname [file dirname [info script]]]

  set G(sqlite_version) "unknown"

  # Either "config", "running" or "stopped":
  set G(state) "config"

  set G(hostname) "(unknown host)"
  catch { set G(hostname) [exec hostname] } 
  set G(host) $G(hostname)
  append G(host) " $::tcl_platform(os) $::tcl_platform(osVersion)"
  append G(host) " $::tcl_platform(machine) $::tcl_platform(byteOrder)"
}

proc wapptest_run {} {
  global G
  set_test_array
  set G(state) "running"

  wapptest_openlog

  wapptest_output "Running the following for $G(platform). $G(jobs) jobs."
  foreach t $G(test_array) {
    set config [dict get $t config]
    set target [dict get $t target]
    wapptest_output [format "    %-25s%s" $config $target]
  }
  wapptest_output [string repeat * 70]
}

proc releasetest_data {args} {
  global G
  set rtd [file join $G(srcdir) test releasetest_data.tcl]
  set fd [open "|[info nameofexecutable] $rtd $args" r+]
  set ret [read $fd]
  close $fd
  return $ret
}

# Generate the text for the box at the top of the UI. The current SQLite
# version, according to fossil, along with a warning if there are 
# uncommitted changes in the checkout.
#
proc generate_fossil_info {} {
  global G
  set pwd [pwd]
  cd $G(srcdir)
  set rc [catch {
    set r1 [exec fossil info]
    set r2 [exec fossil changes]
  }]
  cd $pwd
  if {$rc} return

  foreach line [split $r1 "\n"] {
    if {[regexp {^checkout: *(.*)$} $line -> co]} {
      wapp-trim { <br> %html($co) }
    }
  }

  if {[string trim $r2]!=""} {
    wapp-trim { 
      <br><span class=warning> 
      WARNING: Uncommitted changes in checkout
      </span>
    }
  }
}

# If the application is in "config" state, set the contents of the 
# ::G(test_array) global to reflect the tests that will be run. If the
# app is in some other state ("running" or "stopped"), this command
# is a no-op.
#
proc set_test_array {} {
  global G
  if { $G(state)=="config" } {
    set G(test_array) [list]
    set debug "-debug"
    if {$G(debug)==0} { set debug "-nodebug"}
    foreach {config target} [releasetest_data tests $debug $G(platform)] {

      # All configuration names must match $g(cfgglob), which defaults to *
      #
      if {![string match -nocase $G(cfgglob) $config]} continue

      # If using MSVC, do not run sanitize or valgrind tests. Or the
      # checksymbols test.
      if {$G(msvc) && (
          "Sanitize" == $config 
       || "checksymbols" in $target
       || "valgrindtest" in $target
      )} {
        continue
      }

      # If the test mode is not "Normal", override the target.
      #
      if {$target!="checksymbols" && $G(platform)!="Failure-Detection"} {
        switch -- $G(test) {
          Veryquick { set target quicktest }
          Smoketest { set target smoketest }
          Build-Only {
            set target testfixture
            if {$::tcl_platform(platform)=="windows"} {
              set target testfixture.exe
            }
          }
        }
      }

      lappend G(test_array) [dict create config $config target $target]
    }
  }
}

proc count_tests_and_errors {name logfile} {
  global G

  set fd [open $logfile rb]
  set seen 0
  while {![eof $fd]} {
    set line [gets $fd]
    if {[regexp {(\d+) errors out of (\d+) tests} $line all nerr ntest]} {
      incr G(test.$name.nError) $nerr
      incr G(test.$name.nTest) $ntest
      set seen 1
      if {$nerr>0} {
        set G(test.$name.errmsg) $line
      }
    }
    if {[regexp {runtime error: +(.*)} $line all msg]} {
      # skip over "value is outside range" errors
      if {[regexp {.* is outside the range of representable} $line]} {
         # noop
      } else {
        incr G(test.$name.nError)
        if {$G(test.$name.errmsg)==""} {
          set G(test.$name.errmsg) $msg
        }
      }
    }
    if {[regexp {fatal error +(.*)} $line all msg]} {
      incr G(test.$name.nError)
      if {$G(test.$name.errmsg)==""} {
        set G(test.$name.errmsg) $msg
      }
    }
    if {[regexp {ERROR SUMMARY: (\d+) errors.*} $line all cnt] && $cnt>0} {
      incr G(test.$name.nError)
      if {$G(test.$name.errmsg)==""} {
        set G(test.$name.errmsg) $all
      }
    }
    if {[regexp {^VERSION: 3\.\d+.\d+} $line]} {
      set v [string range $line 9 end]
      if {$G(sqlite_version) eq "unknown"} {
        set G(sqlite_version) $v
      } elseif {$G(sqlite_version) ne $v} {
        set G(test.$name.errmsg) "version conflict: {$G(sqlite_version)} vs. {$v}"
      }
    }
  }
  close $fd
  if {$G(test) == "Build-Only"} {
    incr G(test.$name.nTest)
    if {$G(test.$name.nError)>0} {
      set errmsg "Build failed"
    }
  } elseif {!$seen} {
    set G(test.$name.errmsg) "Test did not complete"
    if {[file readable core]} {
      append G(test.$name.errmsg) " - core file exists"
    }
  }
}

proc wapptest_output {str} {
  global G
  if {$G(stdout)} { puts $str }
  if {[info exists G(log)]} { 
    puts $G(log) $str 
    flush $G(log)
  }
}
proc wapptest_openlog {} {
  global G
  set G(log) [open wapptest-out.txt w+]
}
proc wapptest_closelog {} {
  global G
  close $G(log)
  unset G(log)
}

proc format_seconds {seconds} {
  set min [format %.2d [expr ($seconds / 60) % 60]]
  set  hr [format %.2d [expr $seconds / 3600]]
  set sec [format %.2d [expr $seconds % 60]]
  return "$hr:$min:$sec"
}

# This command is invoked once a slave process has finished running its
# tests, successfully or otherwise. Parameter $name is the name of the 
# test, $rc the exit code returned by the slave process.
#
proc slave_test_done {name rc} {
  global G
  set G(test.$name.done) [clock seconds]
  set G(test.$name.nError) 0
  set G(test.$name.nTest) 0
  set G(test.$name.errmsg) ""
  if {$rc} {
    incr G(test.$name.nError)
  }
  if {[file exists $G(test.$name.log)]} {
    count_tests_and_errors $name $G(test.$name.log)
  }

  # If the "keep files" checkbox is clear, delete all files except for
  # the executables and test logs. And any core file that is present.
  if {$G(keep)==0} {
    set keeplist {
      testfixture testfixture.exe
      sqlite3 sqlite3.exe
      test.log test-out.txt
      core
      wapptest_make.sh
      wapptest_configure.sh
      wapptest_run.tcl
    }
    foreach f [glob -nocomplain [file join $G(test.$name.dir) *]] {
      set t [file tail $f]
      if {[lsearch $keeplist $t]<0} {
        catch { file delete -force $f }
      }
    }
  }

  # Format a message regarding the success or failure of hte test.
  set t [format_seconds [expr $G(test.$name.done) - $G(test.$name.start)]]
  set res "OK"
  if {$G(test.$name.nError)} { set res "FAILED" }
  set dots [string repeat . [expr 60 - [string length $name]]]
  set msg "$name $dots $res ($t)"

  wapptest_output $msg
  if {[info exists G(test.$name.errmsg)] && $G(test.$name.errmsg)!=""} {
    wapptest_output "    $G(test.$name.errmsg)"
  }
}

# This is a fileevent callback invoked each time a file-descriptor that
# connects this process to a slave process is readable.
#
proc slave_fileevent {name} {
  global G
  set fd $G(test.$name.channel)

  if {[eof $fd]} {
    fconfigure $fd -blocking 1
    set rc [catch { close $fd }]
    unset G(test.$name.channel)
    slave_test_done $name $rc
  } else {
    set line [gets $fd]
    if {[string trim $line] != ""} { puts "Trace   : $name - \"$line\"" }
  }

  do_some_stuff
}

# Return the contents of the "slave script" - the script run by slave 
# processes to actually perform the test. All it does is execute the
# test script already written to disk (wapptest_cmd.sh or wapptest_cmd.bat).
#
proc wapptest_slave_script {} {
  global G
  if {$G(msvc)==0} {
    set dir [file join .. $G(srcdir)]
    set res [subst -nocommands {
      set rc [catch "exec sh wapptest_cmd.sh {$dir} >>& test.log" ]
      exit [set rc]
    }]
  } else {
    set dir [file nativename [file normalize $G(srcdir)]]
    set dir [string map [list "\\" "\\\\"] $dir]
    set res [subst -nocommands {
      set rc [catch "exec wapptest_cmd.bat {$dir} >>& test.log" ]
      exit [set rc]
    }]
  }

  set res
}


# Launch a slave process to run a test.
#
proc slave_launch {name target dir} {
  global G

  catch { file mkdir $dir } msg
  foreach f [glob -nocomplain [file join $dir *]] {
    catch { file delete -force $f }
  }
  set G(test.$name.dir) $dir

  # Write the test command to wapptest_cmd.sh|bat.
  #
  set ext sh
  if {$G(msvc)} { set ext bat }
  set fd1 [open [file join $dir wapptest_cmd.$ext] w]
  if {$G(msvc)} {
    puts $fd1 [releasetest_data script -msvc $name $target]
  } else {
    puts $fd1 [releasetest_data script $name $target]
  }
  close $fd1

  # Write the wapptest_run.tcl script to the test directory. To run the
  # commands in the other two files.
  #
  set fd3 [open [file join $dir wapptest_run.tcl] w]
  puts $fd3 [wapptest_slave_script]
  close $fd3

  set pwd [pwd]
  cd $dir
  set fd [open "|[info nameofexecutable] wapptest_run.tcl" r+]
  cd $pwd

  set G(test.$name.channel) $fd
  fconfigure $fd -blocking 0
  fileevent $fd readable [list slave_fileevent $name]
}

proc do_some_stuff {} {
  global G

  # Count the number of running jobs. A running job has an entry named
  # "channel" in its dictionary.
  set nRunning 0
  set bFinished 1
  foreach j $G(test_array) {
    set name [dict get $j config]
    if { [info exists G(test.$name.channel)]} { incr nRunning   }
    if {![info exists G(test.$name.done)]}    { set bFinished 0 }
  }

  if {$bFinished} {
    set nError 0
    set nTest 0
    set nConfig 0
    foreach j $G(test_array) {
      set name [dict get $j config]
      incr nError $G(test.$name.nError)
      incr nTest $G(test.$name.nTest)
      incr nConfig 
    }
    set G(result) "$nError errors from $nTest tests in $nConfig configurations."
    wapptest_output [string repeat * 70]
    wapptest_output $G(result)
    catch {
      append G(result) " SQLite version $G(sqlite_version)"
      wapptest_output " SQLite version $G(sqlite_version)"
    }
    set G(state) "stopped"
    wapptest_closelog
    if {$G(noui)} { exit 0 }
  } else {
    set nLaunch [expr $G(jobs) - $nRunning]
    foreach j $G(test_array) {
      if {$nLaunch<=0} break
      set name [dict get $j config]
      if { ![info exists G(test.$name.channel)]
        && ![info exists G(test.$name.done)]
      } {

        set target [dict get $j target]
        set dir [string tolower [string map {" " _ "-" _} $name]]
        set G(test.$name.start) [clock seconds]
        set G(test.$name.log) [file join $dir test.log]

        slave_launch $name $target $dir

        incr nLaunch -1
      }
    }
  }
}

proc generate_select_widget {label id lOpt opt} {
  wapp-trim {
    <label> %string($label) </label>
    <select id=%string($id) name=%string($id)>
  }
  foreach o $lOpt {
    set selected ""
    if {$o==$opt} { set selected " selected=1" }
    wapp-subst "<option $selected>$o</option>"
  }
  wapp-trim { </select> }
}

proc generate_main_page {{extra {}}} {
  global G
  set_test_array

  set hostname $G(hostname)
  wapp-trim {
    <html>
    <head>
      <title> %html($hostname): wapptest.tcl </title>
      <link rel="stylesheet" type="text/css" href="style.css"/>
    </head>
    <body>
  }

  set host $G(host)
  wapp-trim {
    <div class="border">%string($host)
  }
  generate_fossil_info
  wapp-trim {
    </div>
    <div class="border" id=controls> 
    <form action="control" method="post" name="control">
  }

  # Build the "platform" select widget. 
  set lOpt [releasetest_data platforms]
  generate_select_widget Platform control_platform $lOpt $G(platform)

  # Build the "test" select widget. 
  set lOpt [list Normal Veryquick Smoketest Build-Only] 
  generate_select_widget Test control_test $lOpt $G(test)

  # Build the "jobs" select widget. Options are 1 to 8.
  generate_select_widget Jobs control_jobs {1 2 3 4 5 6 7 8 12 16} $G(jobs)

  switch $G(state) {
    config {
      set txt "Run Tests!"
      set id control_run
    }
    running {
      set txt "STOP Tests!"
      set id control_stop
    }
    stopped {
      set txt "Reset!"
      set id control_reset
    }
  }
  wapp-trim {
    <div class=right>
    <input id=%string($id) name=%string($id) type=submit value="%string($txt)">
    </input>
    </div>
  }

  wapp-trim {
  <br><br>
        <label> Tcl: </label>
        <input id="control_tcl" name="control_tcl"></input>
        <label> Keep files: </label>
        <input id="control_keep" name="control_keep" type=checkbox value=1>
        </input>
        <label> Use MSVC: </label>
        <input id="control_msvc" name="control_msvc" type=checkbox value=1>
        <label> Debug tests: </label>
        <input id="control_debug" name="control_debug" type=checkbox value=1>
        </input>
  }
  wapp-trim {
     </form>
  }
  wapp-trim {
     </div>
     <div id=tests>
  }
  wapp-page-tests

  set script "script/$G(state).js"
  wapp-trim {
    </div>
      <script src=%string($script)></script>
    </body>
    </html>
  }
}

proc wapp-default {} {
  generate_main_page
}

proc wapp-page-tests {} {
  global G
  wapp-trim { <table class="border" width=100%> }
  foreach t $G(test_array) {
    set config [dict get $t config]
    set target [dict get $t target]

    set class "testwait"
    set seconds ""

    if {[info exists G(test.$config.log)]} {
      if {[info exists G(test.$config.channel)]} {
        set class "testrunning"
        set seconds [expr [clock seconds] - $G(test.$config.start)]
      } elseif {[info exists G(test.$config.done)]} {
        if {$G(test.$config.nError)>0} {
          set class "testfail" 
        } else {
          set class "testdone"
        }
        set seconds [expr $G(test.$config.done) - $G(test.$config.start)]
      }
      set seconds [format_seconds $seconds]
    }

    wapp-trim {
      <tr class=%string($class)>
      <td class="nowrap"> %html($config) 
      <td class="padleft nowrap"> %html($target)
      <td class="padleft nowrap"> %html($seconds)
      <td class="padleft nowrap">
    }
    if {[info exists G(test.$config.log)]} {
      set log $G(test.$config.log)
      set uri "log/$log"
      wapp-trim {
        <a href=%url($uri)> %html($log) </a>
      }
    }
    if {[info exists G(test.$config.errmsg)] && $G(test.$config.errmsg)!=""} {
      set errmsg $G(test.$config.errmsg)
      wapp-trim {
        <tr class=testfail>
        <td> <td class="padleft" colspan=3> %html($errmsg)
      }
    }
  }

  wapp-trim { </table> }

  if {[info exists G(result)]} {
    set res $G(result)
    wapp-trim {
      <div class=border id=result> %string($res) </div>
    }
  }
}

# URI: /control
#
# Whenever the form at the top of the application page is submitted, it
# is submitted here.
#
proc wapp-page-control {} {
  global G
  if {$::G(state)=="config"} {
    set lControls [list platform test tcl jobs keep msvc debug]
    set G(msvc) 0
    set G(keep) 0
    set G(debug) 0
  } else {
    set lControls [list jobs]
  }
  foreach v $lControls {
    if {[wapp-param-exists control_$v]} {
      set G($v) [wapp-param control_$v]
    }
  }

  if {[wapp-param-exists control_run]} {
    # This is a "run test" command.
    wapptest_run
  }

  if {[wapp-param-exists control_stop]} {
    # A "STOP tests" command.
    set G(state) "stopped"
    set G(result) "Test halted by user"
    foreach j $G(test_array) {
      set name [dict get $j config]
      if { [info exists G(test.$name.channel)] } {
        close $G(test.$name.channel)
        unset G(test.$name.channel)
        slave_test_done $name 1
      }
    }
    wapptest_closelog
  }

  if {[wapp-param-exists control_reset]} {
    # A "reset app" command.
    set G(state) "config"
    wapptest_init
  }

  if {$::G(state) == "running"} {
    do_some_stuff
  }
  wapp-redirect /
}

# URI: /style.css
#
# Return the stylesheet for the application main page.
#
proc wapp-page-style.css {} {
  wapp-subst {

    /* The boxes with black borders use this class */
    .border {
      border: 3px groove #444444;
      padding: 1em;
      margin-top: 1em;
      margin-bottom: 1em;
    }

    /* Float to the right (used for the Run/Stop/Reset button) */
    .right { float: right; }

    /* Style for the large red warning at the top of the page */
    .warning {
      color: red;
      font-weight: bold;
    }

    /* Styles used by cells in the test table */
    .padleft { padding-left: 5ex; }
    .nowrap  { white-space: nowrap; }

    /* Styles for individual tests, depending on the outcome */
    .testwait    {              }
    .testrunning { color: blue  }
    .testdone    { color: green }
    .testfail    { color: red   }
  }
}

# URI: /script/${state}.js
#
# The last part of this URI is always "config.js", "running.js" or 
# "stopped.js", depending on the state of the application. It returns
# the javascript part of the front-end for the requested state to the
# browser.
#
proc wapp-page-script {} {
  regexp {[^/]*$} [wapp-param REQUEST_URI] script

  set tcl $::G(tcl)
  set keep $::G(keep)
  set msvc $::G(msvc)
  set debug $::G(debug)
  
  wapp-subst {
    var lElem = \["control_platform", "control_test", "control_msvc", 
        "control_jobs", "control_debug"
    \];
    lElem.forEach(function(e) {
      var elem = document.getElementById(e);
      elem.addEventListener("change", function() { control.submit() } );
    })

    elem = document.getElementById("control_tcl");
    elem.value = "%string($tcl)"

    elem = document.getElementById("control_keep");
    elem.checked = %string($keep);

    elem = document.getElementById("control_msvc");
    elem.checked = %string($msvc);

    elem = document.getElementById("control_debug");
    elem.checked = %string($debug);
  }

  if {$script != "config.js"} {
    wapp-subst {
      var lElem = \["control_platform", "control_test", 
          "control_tcl", "control_keep", "control_msvc", 
          "control_debug"
      \];
      lElem.forEach(function(e) {
        var elem = document.getElementById(e);
        elem.disabled = true;
      })
    }
  }

  if {$script == "running.js"} {
    wapp-subst {
      function reload_tests() {
        fetch('tests')
          .then( data => data.text() )
          .then( data => {
            document.getElementById("tests").innerHTML = data;
          })
          .then( data => {
            if( document.getElementById("result") ){
              document.location = document.location;
            } else {
              setTimeout(reload_tests, 1000)
            }
          });
      }

      setTimeout(reload_tests, 1000)
    }
  }
}

# URI: /env
#
# This is for debugging only. Serves no other purpose.
#
proc wapp-page-env {} {
  wapp-allow-xorigin-params
  wapp-trim {
    <h1>Wapp Environment</h1>\n<pre>
    <pre>%html([wapp-debug-env])</pre>
  }
}

# URI: /log/dirname/test.log
#
# This URI reads file "dirname/test.log" from disk, wraps it in a <pre>
# block, and returns it to the browser. Use for viewing log files.
#
proc wapp-page-log {} {
  set log [string range [wapp-param REQUEST_URI] 5 end]
  set fd [open $log]
  set data [read $fd]
  close $fd
  wapp-trim {
    <pre>
    %html($data)
    </pre>
  }
}

# Print out a usage message. Then do [exit 1].
#
proc wapptest_usage {} {
  puts stderr {
This Tcl script is used to test various configurations of SQLite. By
default it uses "wapp" to provide an interactive interface. Supported 
command line options (all optional) are:

    --platform    PLATFORM         (which tests to run)
    --config      GLOB             (only run configurations matching GLOB)
    --smoketest                    (run "make smoketest" only)
    --veryquick                    (run veryquick.test only)
    --buildonly                    (build executables, do not run tests)
    --jobs        N                (number of concurrent jobs)
    --tcl         DIR              (where to find tclConfig.sh)
    --deletefiles                  (delete extra files after each test)
    --msvc                         (Use MS Visual C)
    --debug                        (Also run [n]debugging versions of tests)
    --noui                         (do not use wapp)
  }
  exit 1
}

# Sort command line arguments into two groups: those that belong to wapp,
# and those that belong to the application.
set WAPPARG(-server)      1
set WAPPARG(-local)       1
set WAPPARG(-scgi)        1
set WAPPARG(-remote-scgi) 1
set WAPPARG(-fromip)      1
set WAPPARG(-nowait)      0
set WAPPARG(-cgi)         0
set lWappArg [list]
set lTestArg [list]
for {set i 0} {$i < [llength $argv]} {incr i} {
  set arg [lindex $argv $i]
  if {[string range $arg 0 1]=="--"} {
    set arg [string range $arg 1 end]
  }
  if {[info exists WAPPARG($arg)]} {
    lappend lWappArg $arg
    if {$WAPPARG($arg)} {
      incr i
      lappend lWappArg [lindex $argv $i]
    }
  } else {
    lappend lTestArg $arg
  }
}

wapptest_init
for {set i 0} {$i < [llength $lTestArg]} {incr i} {
  set opt [lindex $lTestArg $i]
  if {[string range $opt 0 1]=="--"} {
    set opt [string range $opt 1 end]
  }
  switch -- $opt {
    -platform {
      if {$i==[llength $lTestArg]-1} { wapptest_usage }
      incr i
      set arg [lindex $lTestArg $i]
      set lPlatform [releasetest_data platforms]
      if {[lsearch $lPlatform $arg]<0} {
        puts stderr "No such platform: $arg. Platforms are: $lPlatform"
        exit -1
      }
      set G(platform) $arg
    }

    -smoketest { set G(test) Smoketest }
    -veryquick { set G(test) Veryquick }
    -buildonly { set G(test) Build-Only }
    -jobs {
      if {$i==[llength $lTestArg]-1} { wapptest_usage }
      incr i
      set G(jobs) [lindex $lTestArg $i]
    }

    -tcl {
      if {$i==[llength $lTestArg]-1} { wapptest_usage }
      incr i
      set G(tcl) [lindex $lTestArg $i]
    }

    -deletefiles {
      set G(keep) 0
    }

    -msvc {
      set G(msvc) 1
    }

    -debug {
      set G(debug) 1
    }

    -noui {
      set G(noui) 1
      set G(stdout) 1
    }

    -config {
      if {$i==[llength $lTestArg]-1} { wapptest_usage }
      incr i
      set G(cfgglob) [lindex $lTestArg $i]
    }

    -stdout {
      set G(stdout) 1
    }

    default {
      puts stderr "Unrecognized option: [lindex $lTestArg $i]"
      wapptest_usage
    }
  }
}

if {$G(noui)==0} {
  wapp-start $lWappArg
} else {
  wapptest_run
  do_some_stuff
  vwait forever
}

Changes to test/where.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20













-







# 2001 September 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 the use of indices in WHERE clases.
#
# $Id: where.test,v 1.50 2008/11/03 09:06:06 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Build some test data
#
do_test where-1.0 {
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
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







-
+


-
+











-
+





-
+







  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
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







-
+


-
+





-
+





-
+











-
+


-
+







  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 {
486
487
488
489
490
491
492
493

494
495
496
497
498

499
500
501
502
503
504
505
485
486
487
488
489
490
491

492
493
494
495
496

497
498
499
500
501
502
503
504







-
+




-
+







      SELECT * FROM t1 WHERE x IN (1,7) AND y NOT IN (6400,8100) ORDER BY 1;
    }
  } {2 1 9 3 1 16 6}
  do_test where-5.14 {
    count {
      SELECT * FROM t1 WHERE x IN (1,7) AND y IN (9,10) ORDER BY 1;
    }
  } {2 1 9 4}
  } {2 1 9 5}
  do_test where-5.15 {
    count {
      SELECT * FROM t1 WHERE x IN (1,7) AND y IN (9,16) ORDER BY 1;
    }
  } {2 1 9 3 1 16 8}
  } {2 1 9 3 1 16 9}
  do_test where-5.100 {
    db eval {
      SELECT w, x, y FROM t1 WHERE x IN (1,5) AND y IN (9,8,3025,1000,3969)
       ORDER BY x, y
    }
  } {2 1 9 54 5 3025 62 5 3969}
  do_test where-5.101 {
542
543
544
545
546
547
548

549
550
551
552
553
554
555
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555







+







  execsql {
    CREATE TABLE t3(a,b,c);
    CREATE INDEX t3a ON t3(a);
    CREATE INDEX t3bc ON t3(b,c);
    CREATE INDEX t3acb ON t3(a,c,b);
    INSERT INTO t3 SELECT w, 101-w, y FROM t1;
    SELECT count(*), sum(a), sum(b), sum(c) FROM t3;
    ANALYZE;
  }
} {100 5050 5050 348550}
do_test where-6.2 {
  cksort {
    SELECT * FROM t3 ORDER BY a LIMIT 3
  }
} {1 100 4 2 99 9 3 98 16 nosort}
1344
1345
1346
1347
1348
1349
1350



1351
1352
1353
1354
1355
1356



1357
1358
1359
1360



1361
1362
1363
1364
1365
1366
1367
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







+
+
+






+
+
+




+
+
+







#
do_execsql_test where-18.1 {
  CREATE TABLE t181(a);
  CREATE TABLE t182(b,c);
  INSERT INTO t181 VALUES(1);
  SELECT DISTINCT a FROM t181 LEFT JOIN t182 ON a=b ORDER BY c IS NULL;
} {1}
do_execsql_test where-18.1rj {
  SELECT DISTINCT a FROM t182 RIGHT JOIN t181 ON a=b ORDER BY c IS NULL;
} {1}
do_execsql_test where-18.2 {
  SELECT DISTINCT a FROM t181 LEFT JOIN t182 ON a=b ORDER BY +c;
} {1}
do_execsql_test where-18.3 {
  SELECT DISTINCT a FROM t181 LEFT JOIN t182 ON a=b ORDER BY c;
} {1}
do_execsql_test where-18.3rj {
  SELECT DISTINCT a FROM t182 RIGHT JOIN t181 ON a=b ORDER BY c;
} {1}
do_execsql_test where-18.4 {
  INSERT INTO t181 VALUES(1),(1),(1),(1);
  SELECT DISTINCT a FROM t181 LEFT JOIN t182 ON a=b ORDER BY +c;
} {1}
do_execsql_test where-18.4rj {
  SELECT DISTINCT a FROM t182 RIGHT JOIN t181 ON a=b ORDER BY +c;
} {1}
do_execsql_test where-18.5 {
  INSERT INTO t181 VALUES(2);
  SELECT DISTINCT a FROM t181 LEFT JOIN t182 ON a=b ORDER BY c IS NULL, +a;
} {1 2}
do_execsql_test where-18.6 {
  INSERT INTO t181 VALUES(2);
  SELECT DISTINCT a FROM t181 LEFT JOIN t182 ON a=b ORDER BY +a, +c IS NULL;
1421
1422
1423
1424
1425
1426
1427


1428










































































































































































































































































1429
1430
1431
1432
1433
1434
1435
1436
1437
1438

1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
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
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
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705







+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  CREATE TABLE t1(a INT);
  CREATE INDEX t1a ON t1(a);
  INSERT INTO t1(a) VALUES(NULL),(NULL),(42),(NULL),(NULL);
  CREATE TABLE t2(dummy INT);
  SELECT count(*) FROM t1 LEFT JOIN t2 ON a IS NOT NULL;
} {5}

# 20190-02-22:  A bug introduced by checkin
# https://www.sqlite.org/src/info/fa792714ae62fa98.

#
do_execsql_test where-23.0 {
  DROP TABLE IF EXISTS t1;
  DROP TABLE IF EXISTS t2;
  CREATE TABLE t1(a INTEGER PRIMARY KEY);
  INSERT INTO t1(a) VALUES(1),(2),(3);
  CREATE TABLE t2(x INTEGER PRIMARY KEY, y INT);
  INSERT INTO t2(y) VALUES(2),(3);
  SELECT * FROM t1, t2 WHERE a=y AND y=3;
} {3 2 3}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test where-24.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');
}

foreach {tn sql res} {
  1 "SELECT b FROM t1"                   {one two three four}
  2 "SELECT b FROM t1 WHERE a<4"         {one two three}
  3 "SELECT b FROM t1 WHERE a>1"         {two three four}
  4 "SELECT b FROM t1 WHERE a>1 AND a<4" {two three}

  5 "SELECT b FROM t1 WHERE a>? AND a<4" {}
  6 "SELECT b FROM t1 WHERE a>1 AND a<?" {}
  7 "SELECT b FROM t1 WHERE a>? AND a<?" {}

  7 "SELECT b FROM t1 WHERE a>=? AND a<=4" {}
  8 "SELECT b FROM t1 WHERE a>=1 AND a<=?" {}
  9 "SELECT b FROM t1 WHERE a>=? AND a<=?" {}
} {
  set rev [list]
  foreach r $res { set rev [concat $r $rev] }

  do_execsql_test where-24.$tn.1 "$sql"                     $res
  do_execsql_test where-24.$tn.2 "$sql ORDER BY rowid"      $res
  do_execsql_test where-24.$tn.3 "$sql ORDER BY rowid DESC" $rev

  do_execsql_test where-24-$tn.4 "
    BEGIN;
      DELETE FROM t1;
      $sql;
      $sql ORDER BY rowid;
      $sql ORDER BY rowid DESC;
    ROLLBACK;
  "
}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test where-25.0 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
  CREATE UNIQUE INDEX i1 ON t1(c);
  INSERT INTO t1 VALUES(1, 'one', 'i');
  INSERT INTO t1 VALUES(2, 'two', 'ii');

  CREATE TABLE t2(a INTEGER PRIMARY KEY, b, c);
  CREATE UNIQUE INDEX i2 ON t2(c);
  INSERT INTO t2 VALUES(1, 'one', 'i');
  INSERT INTO t2 VALUES(2, 'two', 'ii');
  INSERT INTO t2 VALUES(3, 'three', 'iii');

  PRAGMA writable_schema = 1;
  UPDATE sqlite_schema SET rootpage = (
    SELECT rootpage FROM sqlite_schema WHERE name = 'i2'
  ) WHERE name = 'i1';
}
db close
sqlite3 db test.db
do_catchsql_test where-25.1 {
  DELETE FROM t1 WHERE c='iii'
} {1 {database disk image is malformed}}
do_catchsql_test where-25.2 {
  INSERT INTO t1 VALUES(4, 'four', 'iii') 
    ON CONFLICT(c) DO UPDATE SET b=NULL
} {1 {database disk image is malformed}}

reset_db
do_execsql_test where-25.3 {
  CREATE TABLE t1(a PRIMARY KEY, b, c) WITHOUT ROWID;
  CREATE UNIQUE INDEX i1 ON t1(c);
  INSERT INTO t1 VALUES(1, 'one', 'i');
  INSERT INTO t1 VALUES(2, 'two', 'ii');

  CREATE TABLE t2(a INTEGER PRIMARY KEY, b, c);
  CREATE UNIQUE INDEX i2 ON t2(c);
  INSERT INTO t2 VALUES(1, 'one', 'i');
  INSERT INTO t2 VALUES(2, 'two', 'ii');
  INSERT INTO t2 VALUES(3, 'three', 'iii');

  PRAGMA writable_schema = 1;
  UPDATE sqlite_schema SET rootpage = (
    SELECT rootpage FROM sqlite_schema WHERE name = 'i2'
  ) WHERE name = 'i1';
}
db close
sqlite3 db test.db
do_catchsql_test where-25.4 {
  SELECT * FROM t1 WHERE c='iii'
} {0 {}}
do_catchsql_test where-25.5 {
  INSERT INTO t1 VALUES(4, 'four', 'iii') 
    ON CONFLICT(c) DO UPDATE SET b=NULL
} {1 {corrupt database}}

# 2019-08-21 Ticket https://www.sqlite.org/src/info/d9f584e936c7a8d0
#
db close
sqlite3 db :memory:
do_execsql_test where-26.1 {
  CREATE TABLE t0(c0 INTEGER PRIMARY KEY, c1 TEXT);
  INSERT INTO t0(c0, c1) VALUES (1, 'a');
  CREATE TABLE t1(c0 INT PRIMARY KEY, c1 TEXT);
  INSERT INTO t1(c0, c1) VALUES (1, 'a');
  SELECT * FROM t0 WHERE '-1' BETWEEN 0 AND t0.c0;
} {1 a}
do_execsql_test where-26.2 {
  SELECT * FROM t1 WHERE '-1' BETWEEN 0 AND t1.c0;
} {1 a}
do_execsql_test where-26.3 {
  SELECT * FROM t0 WHERE '-1'>=0 AND '-1'<=t0.c0;
} {1 a}
do_execsql_test where-26.4 {
  SELECT * FROM t1 WHERE '-1'>=0 AND '-1'<=t1.c0;
} {1 a}
do_execsql_test where-26.5 {
  SELECT '-1' BETWEEN 0 AND t0.c0 FROM t0;
} {1}
do_execsql_test where-26.6 {
  SELECT '-1' BETWEEN 0 AND t1.c0 FROM t1;
} {1}
do_execsql_test where-26.7 {
  SELECT '-1'>=0 AND '-1'<=t0.c0 FROM t0;
} {1}
do_execsql_test where-26.8 {
  SELECT '-1'>=0 AND '-1'<=t1.c0 FROM t1;
} {1}

# 2021-07-19 https://sqlite.org/forum/forumpost/2bdb86a068
# Lose of precision when doing comparisons between integer and
# floating point values that are near 9223372036854775807 in the
# OP_SeekGE opcode (and similar).
#
# Valgrind documentation acknowledges that under valgrind, FP calculations
# may not be as accurate as on x86/amd64 hardware. This seems to be causing
# these tests to fail.
#
#   https://valgrind.org/docs/manual/manual-core.html#manual-core.limits
#
if {[permutation]!="valgrind"} {
  reset_db
  do_execsql_test where-27.1 {
    CREATE TABLE t1(a INTEGER PRIMARY KEY);
    INSERT INTO t1(a) VALUES(9223372036854775807);
    SELECT 1 FROM t1 WHERE a>=(9223372036854775807+1);
  } {}
  do_execsql_test where-27.2 {
    SELECT a>=9223372036854775807+1 FROM t1;
  } {0}
}

# 2022-05-10 dbsqlfuzz 4c5e3e89bc251d28378be88233f531b84ec66901
# 
reset_db
do_execsql_test where-28.1 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b INT);
  CREATE INDEX t1b ON t1(b,b,b,b,b,b,b,b,b,b,b,b,b);
  INSERT INTO t1(a,b) VALUES(1,1),(15,2),(19,5);
  UPDATE t1 SET b=999 WHERE a IN (SELECT 15) AND b IN (1,2);
  SELECT * FROM t1;
} {
 1  1
 15 999
 19 5
}

# 2022-12-07 Yong Heng [https://sqlite.org/forum/forumpost/dfe8084751]
#
do_execsql_test where-29.1 {
  SELECT DISTINCT 'xyz' FROM pragma_cache_size
   WHERE rowid OR abs(0)
   ORDER BY
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 1, 1;
} {xyz}

# 2023-01-30
# Tests case for the query planner performance issue reported by
# https://sqlite.org/forum/forumpost/1d571c0296
#
# The fix was to adjust the cost of computing an automatic index for
# ephemeral tables, to help ensure that they are generated if they are
# needed.  The test case below only looks at the query plan.  But 12x
# improved performance has been verified by populating the "raw" table
# with 100K rows of random data and running actual speed tests.
#
do_test where-30.1 {
  unset -nocomplain res
  set res {}
  db eval {CREATE TABLE raw(country,date,total,delta, UNIQUE(country,date));}
  db eval {
    EXPLAIN QUERY PLAN
    WITH
      -- Find the country and min/max date
      init(country, date, fin) AS (SELECT country, min(date), max(date)
         FROM raw WHERE total > 0 GROUP BY country),
    
      -- Generate the date stream for each country
      src(country, date) AS (SELECT raw.country, raw.date
          FROM raw JOIN init i on raw.country = i.country AND raw.date > i.date
          ORDER BY raw.country, raw.date),
    
      -- Generate the x & y for each entry in the country/date stream
      vals(country, date, x, y) AS (SELECT src.country, src.date,
                julianday(raw.date) - julianday(src.date), log(delta+1)
          FROM src JOIN raw on raw.country = src.country
                        AND raw.date > date(src.date,'-7 days')
                        AND raw.date <= src.date AND delta >= 0),
    
      -- Accumulate the data we need
      sums(country, date, x2, x, n, xy, y) AS (SELECT country, date,
              sum(x*x*1.0), sum(x*1.0), sum(1.0), sum(x*y*1.0), sum(y*1.0)
         FROM vals GROUP BY 1, 2),
    
      -- use these to calculate to divisor for the inverse matrix
      mult(country, date, m) AS (SELECT country, date, 1.0/(x2 * n - x * x)
         FROM sums),
    
      -- Build the inverse matrix
      inv(country, date, a,b,c,d) AS (SELECT mult.country, mult.date, n * m,
                -x * m, -x * m, x2 * m
          FROM mult JOIN sums on sums.country=mult.country
                         AND mult.date=sums.date),
    
      -- Calculate the coefficients for the least squares fit
      fit(country, date, a, b) AS (SELECT inv.country, inv.date,
               a * xy + b * y, c * xy + d * y
          FROM inv
          JOIN mult on mult.country = inv.country AND mult.date = inv.date
          JOIN sums on sums.country = mult.country AND sums.date = mult.date
    )
    SELECT *, nFin/nPrev - 1 AS growth, log(2)/log(nFin/nPrev) AS doubling
      FROM (SELECT f.*, exp(b) - 1 AS nFin, exp(a* (-1) + b) - 1 AS nPrev
              FROM fit f JOIN init i on i.country = f.country
                          AND f.date <= date(i.fin,'-3 days'))
     WHERE nPrev > 0 AND nFin > 0;
  } {
    if {$parent!=0} continue
    if {![string match SCAN* $detail]} continue
    lappend res SCAN
  }
  set res
} {SCAN}
# ^^^^^^-- there should only be one top-level table scan in the query plan.

finish_test

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.

23349
23350
23351
23352
23353
23354
23355

23356
23357
23358




23359
23360
























23361
23362
23349
23350
23351
23352
23353
23354
23355
23356



23357
23358
23359
23360
23361
23362
23363
23364
23365
23366
23367
23368
23369
23370
23371
23372
23373
23374
23375
23376
23377
23378
23379
23380
23381
23382
23383
23384
23385
23386
23387
23388







+
-
-
-
+
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


      AND t302.c3 > 1287603136
      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 TABLE t301 USING INTEGER PRIMARY KEY (rowid=?)
  |--SEARCH TABLE t302 USING INDEX t302_c8_c3 (c8=? AND c3>?)
  |  |  `--SEARCH t301 USING COVERING INDEX t301_c4 (c4=?)
  |  `--INDEX 2
  |     `--SEARCH t301 USING INTEGER PRIMARY KEY (rowid=?)
  |--SEARCH t302 USING INDEX t302_c8_c3 (c8=? AND c3>?)
  `--USE TEMP B-TREE FOR ORDER BY
}

# 2022-03-03 https://sqlite.org/forum/forumpost/36937b197273d403
#
# In the multi-index OR, if there is an auxiliary WHERE clause term
# that includes a subquery and that subquery is pushed down into the
# OR-clause subqueries, WHERE subquery might get coded as a subroutine.
# In that case, the covering-index optimizer will attempt to change
# table-references into index-references.  But it will do so for the
# index of the OR branch in which the subquery is coded.  If the
# subquery subroutine is called from a different OR branch, the
# index might be different and the index-reference will no longer
# work.  tag-20220303a
#
reset_db
do_execsql_test 4.1 {
  CREATE TABLE t0(w);
  INSERT INTO t0(w) VALUES(1);
  CREATE TABLE t1(x INT, y INT PRIMARY KEY, z); 
  INSERT INTO t1 VALUES(0,111,222);
  CREATE INDEX t1zxy ON t1(z,x,y);
  SELECT y FROM t1
   WHERE (z=222 OR y=111)
     AND (false OR EXISTS(SELECT 1 FROM t0 WHERE t1.y));
} {111}

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
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 TABLE t2 USING COVERING INDEX t2f (f=?)
       |  `--SEARCH t2 USING INDEX t2d (d=?)
       `--INDEX 3
          `--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 TABLE t2 USING COVERING INDEX t2f (f=?)
       |  `--SEARCH t2 USING INDEX t2d (d=?) LEFT-JOIN
       `--INDEX 2
          `--SEARCH t2 USING COVERING INDEX t2f (f=?) LEFT-JOIN
  }]
} 

# Make sure that INDEXED BY and multi-index OR clauses play well with
# one another.
#
do_test where9-4.1 {
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
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







-
+















-
+







-
+









+
-
-
+
+
+






-
+






-
+







do_test where9-4.5 {
  catchsql {
    SELECT a FROM t1 INDEXED BY t1b
     WHERE +b>1000
       AND (c=31031 OR d IS NULL)
     ORDER BY +a
  }
} {1 {no query solution}}
} {0 {92 93 97}}
do_test where9-4.6 {
  count_steps {
    SELECT a FROM t1 NOT INDEXED
     WHERE b>1000
       AND (c=31031 OR d IS NULL)
     ORDER BY +a
  }
} {92 93 97 scan 98 sort 1}
do_test where9-4.7 {
  catchsql {
    SELECT a FROM t1 INDEXED BY t1c
     WHERE b>1000
       AND (c=31031 OR d IS NULL)
     ORDER BY +a
  }
} {1 {no query solution}}
} {0 {92 93 97}}
do_test where9-4.8 {
  catchsql {
    SELECT a FROM t1 INDEXED BY t1d
     WHERE b>1000
       AND (c=31031 OR d IS NULL)
     ORDER BY +a
  }
} {1 {no query solution}}
} {0 {92 93 97}}

# The (c=31031 OR d IS NULL) clause is preferred over b>1000 because
# the former is an equality test which is expected to return fewer rows.
#
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 TABLE t1 USING INDEX t1d (d=?)
     |  `--SEARCH t1 USING INDEX t1c (c=?)
     `--INDEX 2
        `--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}
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
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







-
+







-
+


-
+







do_test where9-6.8.1 {
  catchsql {
    DELETE FROM t1 INDEXED BY t1b
     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)
  }
} {1 {no query solution}}
} {0 {}}
do_test where9-6.8.2 {
  catchsql {
    UPDATE t1 INDEXED BY t1b SET a=a+100
     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)
  }
} {1 {no query solution}}
} {0 {}}

set solution_possible 0
ifcapable stat4||stat3 {
ifcapable stat4 {
  if {[permutation] != "no_optimization"} { set solution_possible 1 }
}
if $solution_possible {
  # When STAT3 is enabled, the "b NOT NULL" terms get translated
  # into b>NULL, which can be satified by the index t1b.  It is a very
  # expensive way to do the query, but it works, and so a solution is possible.
  do_test where9-6.8.3-stat4 {
808
809
810
811
812
813
814
815

816
817
818
819
820
821
822
823

824
825
826
827
828
829
830
814
815
816
817
818
819
820

821
822
823
824
825
826
827
828

829
830
831
832
833
834
835
836







-
+







-
+







  do_test where9-6.8.3 {
    catchsql {
      UPDATE t1 INDEXED BY t1b SET a=a+100
       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)
    }
  } {1 {no query solution}}
  } {0 {}}
  do_test where9-6.8.4 {
    catchsql {
      DELETE FROM t1 INDEXED BY t1b
       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)
    }
  } {1 {no query solution}}
  } {0 {}}
}
############################################################################
# Test cases where terms inside an OR series are combined with AND terms
# external to the OR clause.  In other words, cases where
#
#              x AND (y OR z)
#
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
856
857
858
859
860
861
862





863
864
865
866
867
868
869







-
-
-
-
-







    CREATE INDEX t5ye ON t5(y, e);
    CREATE INDEX t5yf ON t5(y, f);
    CREATE INDEX t5yg ON t5(y, g);
    CREATE TABLE t6(a, b, c, e, d, f, g, x, y);
    INSERT INTO t6 SELECT * FROM t5;
    ANALYZE t5;
  }
  ifcapable stat3 {
    sqlite3 db2 test.db
    db2 eval { DROP TABLE IF EXISTS sqlite_stat3 }
    db2 close
  }
} {}
do_test where9-7.1.1 {
  count_steps {
    SELECT a FROM t5 WHERE x='y' AND (b=913 OR c=27027) ORDER BY a;
  }
} {79 81 83 scan 0 sort 1}
do_test where9-7.1.2 {
977
978
979
980
981
982
983







984











985
986
978
979
980
981
982
983
984
985
986
987
988
989
990
991

992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004







+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+


    INSERT INTO t102 VALUES ('1');
    SELECT * FROM t102 AS t0
         LEFT JOIN t102 AS t1 ON t1.id GLOB 'abc%'
         JOIN t102 AS t2 ON (t2.id = t0.id OR (t2.id<>555 AND t2.id=t1.id));
  }
} {1 {} 1}

# dbsqlfuzz 9df1d53c24c4c96af0dae15ee764897af415ac76
# The MULTI-INDEX OR processing evaluates the same WHERE-clause sub-expression
# twice.  But if that sub-expression contains a UNION ALL SELECT statement
# subject to query flattening, the sub-expression might be transformed in a
# way that it can only be code-generated once.  An assert() will fail on
# the second attempt to generate code from the same sub-expression.
# The solution is to make a copy of sub-expressions used by MULTI-INDEX OR

#
reset_db
do_execsql_test where9-11.1 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT);
  CREATE TABLE t2_a(k INTEGER PRIMARY KEY, v TEXT);
  CREATE TABLE t2_b(k INTEGER PRIMARY KEY, v TEXT);
  CREATE VIEW t2 AS SELECT * FROM t2_a UNION ALL SELECT * FROM t2_b;
  SELECT 1 FROM t1 JOIN t1 USING(a)
   WHERE (a=1)
      OR (a=2 AND (SELECT 4 FROM t2,(SELECT 5 FROM t1 ORDER BY a) WHERE a));
} {}

finish_test

Changes to test/whereA.test.

165
166
167
168
169
170
171















172
173
174
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



  PRAGMA reverse_unordered_selects=on;
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a,b);
  INSERT INTO t1 VALUES(1,2);
  CREATE INDEX t1b ON t1(b);
  SELECT a FROM t1 WHERE b=-99 OR b>1;
} {1}

# 2020-10-02 OSSFuzz find for an issue introduced by a check-in
# on the previous day.
#
reset_db
do_execsql_test whereA-6.1 {
  CREATE TABLE t1(a, b);
  CREATE INDEX t1aa ON t1(a,a);
  INSERT INTO t1 VALUES(1,2);
  ANALYZE;
  UPDATE sqlite_stat1 SET stat='27 3 3' WHERE idx='t1aa';
  ANALYZE sqlite_schema;
  PRAGMA reverse_unordered_selects (1) ;
  SELECT a FROM t1 WHERE  a=1 OR a=2;
} {1}


finish_test

Changes to test/whereD.test.

332
333
334
335
336
337
338
















339
340
341
342
343
344
345
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







} {3 7 11 search 7}
do_searchcount_test 6.6.3 {
  SELECT c FROM x1 WHERE c=11 OR a=1 OR b=6 
} {11 3 7 search 7}
do_searchcount_test 6.6.4 {
  SELECT c FROM x1 WHERE b=6 OR c=11 OR a=1
} {7 11 3 search 7}

# 2020-02-22 ticket aa4378693018aa99
# In the OP_Column opcode, if a cursor is marked with OP_NullRow
# (because it is the right table of a LEFT JOIN that does not match)
# then do not substitute index cursors, as the index cursors do not
# have the VdbeCursor.nullRow flag set.
#
do_execsql_test 6.7 {
  DROP TABLE IF EXISTS t1;
  DROP TABLE IF EXISTS t2;
  CREATE TABLE t1(a UNIQUE, b UNIQUE);
  INSERT INTO t1(a,b) VALUES(null,2);
  CREATE VIEW t2 AS SELECT * FROM t1 WHERE b<10 OR a<7 ORDER BY b;
  SELECT t1.* FROM t1 LEFT JOIN t2 ON abs(t1.a)=abs(t2.b);
} {{} 2}


#-------------------------------------------------------------------------
#
do_execsql_test 7.0 {
  CREATE TABLE y1(a, b);
  CREATE TABLE y2(x, y);
  CREATE INDEX y2xy ON y2(x, y);

Changes to test/whereE.test.

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
31
32







+
+
+
+
+
+







# is making good planning decisions.
#


set testdir [file dirname $argv0]
source $testdir/tester.tcl
set ::testprefix whereE

# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
ifcapable !altertable {
  finish_test
  return
}

do_execsql_test 1.1 {
  CREATE TABLE t1(a,b);
  INSERT INTO t1 VALUES(1,10), (2,20), (3,30), (2,22), (3, 33);
  INSERT INTO t1 SELECT * FROM t1;
  INSERT INTO t1 SELECT * FROM t1;
  INSERT INTO t1 SELECT * FROM t1;
43
44
45
46
47
48
49
50

51
52
53

54
55
56
57

58
59
60

61
62
49
50
51
52
53
54
55

56
57
58

59
60
61
62

63
64
65

66
67
68







-
+


-
+



-
+


-
+


  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
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 t1}
} else {
do_eqp_test 5.3.1 {
  SELECT * FROM t1 WHERE a=?
} {SEARCH TABLE t1 USING INDEX i1 (a=?)}
  do_eqp_test 5.3.1 {
    SELECT * FROM t1 WHERE a=?
  } {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);
262
263
264
265
266
267
268


269















































































































270
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







+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

do_execsql_test 7.2 {
  SELECT likelihood(a,0.5), x FROM t1, t2 ORDER BY 1, 2;
} {1 3 1 4 9 3 9 4}
do_execsql_test 7.3 {
  SELECT coalesce(a,a), x FROM t1, t2 ORDER BY 1, 2;
} {1 3 1 4 9 3 9 4}

# 2019-08-22
# Ticket https://www.sqlite.org/src/info/7e07a3dbf5a8cd26

#
do_execsql_test 8.1 {
  DROP TABLE IF EXISTS t0;
  CREATE TABLE t0 (c0);
  INSERT INTO t0(c0) VALUES ('a');
  SELECT LIKELY(t0.rowid) <= '0' FROM t0;
} {1}
do_execsql_test 8.2 {
  SELECT * FROM t0 WHERE LIKELY(t0.rowid) <= '0';
} {a}
do_execsql_test 8.3 {
  SELECT (t0.rowid) <= '0' FROM t0;
} {0}
do_execsql_test 8.4 {
  SELECT * FROM t0 WHERE (t0.rowid) <= '0';
} {}
do_execsql_test 8.5 {
  SELECT unlikely(t0.rowid) <= '0', likelihood(t0.rowid,0.5) <= '0' FROM t0;
} {1 1}
do_execsql_test 8.6 {
  SELECT * FROM t0 WHERE unlikely(t0.rowid) <= '0';
} {a}
do_execsql_test 8.7 {
  SELECT * FROM t0 WHERE likelihood(t0.rowid, 0.5) <= '0';
} {a}
do_execsql_test 8.8 {
  SELECT unlikely(t0.rowid <= '0'),
         likely(t0.rowid <= '0'),
         likelihood(t0.rowid <= '0',0.5)
    FROM t0;
} {0 0 0}
do_execsql_test 8.9 {
  SELECT * FROM t0 WHERE unlikely(t0.rowid <= '0');
} {}
do_execsql_test 8.10 {
  SELECT * FROM t0 WHERE likelihood(t0.rowid <= '0', 0.5);
} {}

# 2019-12-31: assertion fault discovered by Yongheng's fuzzer.
# Harmless memIsValid() due to the code generators failure to
# release the registers used by OP_ResultRow.
#
do_execsql_test 9.10 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a, b FLOAT);
  INSERT INTO t1(a) VALUES(''),(NULL),('X'),(NULL);
  SELECT coalesce(max(quote(a)),10) FROM t1 GROUP BY a;
} {NULL '' 'X'}

# 2020-06-14: assert() changed back into testcase()
# ticket 9fb26d37cefaba40
#
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}

# 2021-06-14 forum https://sqlite.org/forum/forumpost/3b940c437a
# Affinity problem when a likely() function is used as a column in
# an index.
#
reset_db
do_execsql_test 12.0 {
  CREATE TABLE t1(a REAL);
  INSERT INTO t1(a) VALUES(123);
  CREATE INDEX t1x1 ON t1(likely(a));
  SELECT typeof(likely(a)) FROM t1 NOT INDEXED;
  SELECT typeof(likely(a)) FROM t1 INDEXED BY t1x1;
} {real real}
do_execsql_test 12.1 {
  CREATE INDEX t1x2 ON t1(abs(a));
  SELECT typeof(abs(a)) FROM t1 NOT INDEXED;
  SELECT typeof(abs(a)) FROM t1 INDEXED BY t1x2;
} {real real}


finish_test

Changes to test/whereI.test.

27
28
29
30
31
32
33

34
35



36
37
38
39
40
41
42
27
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 TABLE t1 USING INDEX i2 (c=?)
     |  `--SEARCH t1 USING INDEX i1 (b=?)
     `--INDEX 2
        `--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 {
57
58
59
60
61
62
63

64
65



66
67
68
69
70
71
72
59
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 TABLE t2 USING INDEX i4 (c=?)
     |  `--SEARCH t2 USING INDEX i3 (b=?)
     `--INDEX 2
        `--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.

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
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







-
-
-
-
-
-
+
+
+
+
+
+
-
-
+












-
-
-
+
+
+







  CREATE TABLE t3(a INT PRIMARY KEY, j, k, l, m);
  CREATE VIEW v4 AS SELECT * FROM t2 UNION ALL SELECT * FROM t3;
}
do_eqp_test 110 {
  SELECT * FROM t1, v4 WHERE t1.a=?1 AND v4.a=t1.a;
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |  `--COMPOUND QUERY
  |     |--LEFT-MOST SUBQUERY
  |     |  `--SEARCH TABLE t2 USING INDEX sqlite_autoindex_t2_1 (a=?)
  |     `--UNION ALL
  |        `--SEARCH TABLE t3 USING INDEX sqlite_autoindex_t3_1 (a=?)
  `--COMPOUND QUERY
     |--LEFT-MOST SUBQUERY
     |  |--SEARCH t1 USING INDEX sqlite_autoindex_t1_1 (a=?)
     |  `--SEARCH t2 USING INDEX sqlite_autoindex_t2_1 (a=?)
     `--UNION ALL
        |--SEARCH t1 USING INDEX sqlite_autoindex_t1_1 (a=?)
  |--SCAN SUBQUERY xxxxxx
  `--SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (a=?)
        `--SEARCH t3 USING INDEX sqlite_autoindex_t3_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);
117
118
119
120
121
122
123
124





































































125
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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

do_execsql_test 400 {
  CREATE TABLE x(a, b, c);
  CREATE TABLE y(a, b);
  INSERT INTO x VALUES (1, 0, 1);
  INSERT INTO y VALUES (1, 2);
  SELECT x.a FROM x JOIN y ON x.c = y.a WHERE x.b = 1 AND x.b = 1;
} {}

# 2020-01-07: ticket 82ac75ba0093e5dc
# Incorrect join result due to mishandling of affinity in constant
# propagation.
#
reset_db
do_execsql_test 500 {
  PRAGMA automatic_index=OFF;
  CREATE TABLE t0(c0);
  INSERT INTO t0 VALUES('0');
  CREATE VIEW v0(c0) AS SELECT CAST(0 AS INT) FROM t0;
  SELECT 200, * FROM t0, v0 WHERE 0 = t0.c0 AND t0.c0 = v0.c0;
} {}
do_execsql_test 510 {
  SELECT 200, * FROM t0, v0 WHERE t0.c0 = 0 AND t0.c0 = v0.c0;
} {}
do_execsql_test 520 {
  SELECT 200, * FROM t0, v0 WHERE 0 = t0.c0 AND v0.c0 = t0.c0;
} {}
do_execsql_test 530 {
  SELECT 200, * FROM t0, v0 WHERE t0.c0 = 0 AND v0.c0 = t0.c0;
} {}

# 2020-02-13: ticket 1dcb4d44964846ad
# A problem introduced while making optimizations on the fixes above.
#
reset_db
do_execsql_test 600 {
  CREATE TABLE t1(x TEXT);
  CREATE TABLE t2(y TEXT);
  INSERT INTO t1 VALUES('good'),('bad');
  INSERT INTO t2 VALUES('good'),('bad');
  SELECT * FROM t1 JOIN t2 ON x=y
   WHERE x='good' AND y='good';
} {good good}

# 2020-04-24: Another test case for the previous (1dcb4d44964846ad)
# ticket.  The test case comes from 
# https://stackoverflow.com/questions/61399253/sqlite3-different-result-in-console-compared-to-python-script/
# Output verified against postgresql.
#
do_execsql_test 610 {
  CREATE TABLE tableA(
    ID           int,
    RunYearMonth int
  );
  INSERT INTO tableA VALUES(1,202003),(2,202003),(3,202003),(4,202004),
    (5,202004),(6,202004),(7,202004),(8,202004);
  CREATE TABLE tableB (
    ID           int,
    RunYearMonth int
  );
  INSERT INTO tableB VALUES(1,202004),(2,202004),(3,202004),(4,202004),
  (5,202004);
  SELECT *
   FROM (
        SELECT *
        FROM tableA
        WHERE RunYearMonth = 202004
    ) AS A
    INNER JOIN (
        SELECT *
        FROM tableB
        WHERE RunYearMonth = 202004
    ) AS B
    ON A.ID = B.ID
    AND A.RunYearMonth = B.RunYearMonth;
} {4 202004 4 202004 5 202004 5 202004}


finish_test

Added test/whereM.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2021 May 27
#
# 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.
#
#***********************************************************************
# Tests focused on the "constant propagation" that occurs within the
# WHERE clause of a SELECT statemente.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/malloc_common.tcl
set testprefix whereM


do_execsql_test 1.0 {
  CREATE TABLE t1(a, b INTEGER, c TEXT, d REAL, e BLOB);
  INSERT INTO t1 VALUES(10.0, 10.0, 10.0, 10.0, 10.0);
  SELECT * FROM t1;
} {
  10.0 10 10.0 10.0 10.0
}

do_execsql_test 1.1.1 {
  SELECT a=10, a = '10.0', a LIKE '10.0' FROM t1;
} {1 0 1}
do_execsql_test 1.1.2 {
  SELECT count(*) FROM t1 WHERE a=10 AND a = '10.0'
} {0}
do_execsql_test 1.1.3 {
  SELECT count(*) FROM t1 WHERE a=10 AND a LIKE '10.0'
} {1}
do_execsql_test 1.1.4 {
  SELECT count(*) FROM t1 WHERE a='10.0' AND a LIKE '10.0'
} {0}

do_execsql_test 1.2.1 {
  SELECT b=10, b = '10.0', b LIKE '10.0', b LIKE '10' FROM t1;
} {1 1 0 1}
do_execsql_test 1.2.2 {
  SELECT count(*) FROM t1 WHERE b=10 AND b = '10.0'
} {1}
do_execsql_test 1.2.3 {
  SELECT count(*) FROM t1 WHERE b=10 AND b LIKE '10.0'
} {0}
do_execsql_test 1.2.4 {
  SELECT count(*) FROM t1 WHERE b='10.0' AND b LIKE '10.0'
} {0}
do_execsql_test 1.2.3 {
  SELECT count(*) FROM t1 WHERE b=10 AND b LIKE '10'
} {1}
do_execsql_test 1.2.4 {
  SELECT count(*) FROM t1 WHERE b='10.0' AND b LIKE '10'
} {1}

do_execsql_test 1.3.1 {
  SELECT c=10, c = 10.0, c = '10.0', c LIKE '10.0' FROM t1;
} {0 1 1 1}
do_execsql_test 1.3.2 {
  SELECT count(*) FROM t1 WHERE c=10 AND c = '10.0'
} {0}
do_execsql_test 1.3.3 {
  SELECT count(*) FROM t1 WHERE c=10 AND c LIKE '10.0'
} {0}
do_execsql_test 1.3.4 {
  SELECT count(*) FROM t1 WHERE c='10.0' AND c LIKE '10.0'
} {1}
do_execsql_test 1.3.5 {
  SELECT count(*) FROM t1 WHERE c=10.0 AND c = '10.0'
} {1}
do_execsql_test 1.3.6 {
  SELECT count(*) FROM t1 WHERE c=10.0 AND c LIKE '10.0'
} {1}

do_execsql_test 1.4.1 {
  SELECT d=10, d = 10.0, d = '10.0', d LIKE '10.0', d LIKE '10' FROM t1;
} {1 1 1 1 0}
do_execsql_test 1.4.2 {
  SELECT count(*) FROM t1 WHERE d=10 AND d = '10.0'
} {1}
do_execsql_test 1.4.3 {
  SELECT count(*) FROM t1 WHERE d=10 AND d LIKE '10.0'
} {1}
do_execsql_test 1.4.4 {
  SELECT count(*) FROM t1 WHERE d='10.0' AND d LIKE '10.0'
} {1}
do_execsql_test 1.4.5 {
  SELECT count(*) FROM t1 WHERE d='10' AND d LIKE '10.0'
} {1}

do_execsql_test 1.5.1 {
  SELECT e=10, e = '10.0', e LIKE '10.0', e LIKE '10' FROM t1;
} {1 0 1 0}
do_execsql_test 1.5.2 {
  SELECT count(*) FROM t1 WHERE e=10 AND e = '10.0'
} {0}
do_execsql_test 1.5.3 {
  SELECT count(*) FROM t1 WHERE e=10 AND e LIKE '10.0'
} {1}
do_execsql_test 1.5.4 {
  SELECT count(*) FROM t1 WHERE e='10.0' AND e LIKE '10.0'
} {0}
do_execsql_test 1.5.5 {
  SELECT count(*) FROM t1 WHERE e=10.0 AND e LIKE '10.0'
} {1}

finish_test

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.

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
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







+
+
+
+
+
+
+
+


-
+
+
+

-
+




-
+




-
+







    execsql {SELECT count(*) FROM t1}
  } {20}
  do_test wherelimit-1.3 {
    # limit 5
    execsql {DELETE FROM t1 ORDER BY x LIMIT 5}
    execsql {SELECT count(*) FROM t1}
  } {15}
  create_test_data 4
  do_test wherelimit-1.3b {
    # limit 5
    execsql {DELETE FROM t1 RETURNING x, y, '|' ORDER BY x, y LIMIT 5}
  } {1 1 | 1 2 | 1 3 | 1 4 | 2 1 |}
  do_test wherelimit-1.3c {
    execsql {SELECT count(*) FROM t1}
  } {11}
  do_test wherelimit-1.4 {
    # limit 5, offset 2
    execsql {DELETE FROM t1 ORDER BY x LIMIT 5 OFFSET 2}
    execsql {DELETE FROM t1 RETURNING x, y, '|' ORDER BY x  LIMIT 5 OFFSET 2}
  } {2 4 | 3 1 | 3 2 | 3 3 | 3 4 |}
  do_test wherelimit-1.4cnt {
    execsql {SELECT count(*) FROM t1}
  } {10}
  } {6}
  do_test wherelimit-1.5 {
    # limit 5, offset -2
    execsql {DELETE FROM t1 ORDER BY x LIMIT 5 OFFSET -2}
    execsql {SELECT count(*) FROM t1}
  } {5}
  } {1}
  do_test wherelimit-1.6 {
    # limit -5 (no limit), offset 2
    execsql {DELETE FROM t1 ORDER BY x LIMIT 2, -5}
    execsql {SELECT count(*) FROM t1}
  } {2}
  } {1}
  do_test wherelimit-1.7 {
    # limit 5, offset -2 (no offset)
    execsql {DELETE FROM t1 ORDER BY x LIMIT -2, 5}
    execsql {SELECT count(*) FROM t1}
  } {0}
  create_test_data 5
  do_test wherelimit-1.8 {
223
224
225
226
227
228
229
230



231
232
233
234
235
236
237
233
234
235
236
237
238
239

240
241
242
243
244
245
246
247
248
249







-
+
+
+







  } {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 LIMIT 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}
  } {9}

Changes to test/wherelimit2.test.

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
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







+
+
-
-
-
+
+
+






+
+
-
-
-
+
+
+







do_execsql_test 4.1 {
  BEGIN;
    DELETE FROM x1 ORDER BY a LIMIT 2;
    SELECT a FROM x1;
  ROLLBACK;
} {3 4 5 6}

# 2020-06-03: Query planner improved so that a solution is possible.
#
do_catchsql_test 4.2 {
  DELETE FROM x1 INDEXED BY x1bc WHERE d=3 LIMIT 1;
} {1 {no query solution}}
#do_catchsql_test 4.2 {
#  DELETE FROM x1 INDEXED BY x1bc WHERE d=3 LIMIT 1;
#} {1 {no query solution}}

do_execsql_test 4.3 {
  DELETE FROM x1 INDEXED BY x1bc WHERE b=3 LIMIT 1;
  SELECT a FROM x1;
} {1 2 3 4 6}

# 2020-06-03: Query planner improved so that a solution is possible.
#
do_catchsql_test 4.4 {
  UPDATE x1 INDEXED BY x1bc SET d=5 WHERE d=3 LIMIT 1;
} {1 {no query solution}}
#do_catchsql_test 4.4 {
#  UPDATE x1 INDEXED BY x1bc SET d=5 WHERE d=3 LIMIT 1;
#} {1 {no query solution}}

do_execsql_test 4.5 {
  UPDATE x1 INDEXED BY x1bc SET d=5 WHERE b=2 LIMIT 1;
  SELECT a, d FROM x1;
} {1 1 2 2 3 5 4 3 6 1}

#-------------------------------------------------------------------------

Added test/widetab1.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022-10-24
#
# 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 test cases for wide table (tables with more than
# 64 columns) and indexes that reference columns beyond the 63rd or 64th
# column.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix widetab1


# In order to pick the better index in the following query, SQLite needs to
# be able to detect when an index that references later columns in a wide
# table is a covering index.
#
do_execsql_test 100 {
  CREATE TABLE a(
   a00, a01, a02, a03, a04, a05, a06, a07, a08, a09,
   a10, a11, a12, a13, a14, a15, a16, a17, a18, a19,
   a20, a21, a22, a23, a24, a25, a26, a27, a28, a29,
   a30, a31, a32, a33, a34, a35, a36, a37, a38, a39,
   a40, a41, a42, a43, a44, a45, a46, a47, a48, a49,
   a50, a51, a52, a53, a54, a55, a56, a57, a58, a59,
   pd, bn, vb, bc, cn, ie, qm);
  CREATE INDEX a1 on a(pd, bn, vb, bc, cn); -- preferred index
  CREATE INDEX a2 on a(pd, bc, ie, qm);     -- suboptimal index
  CREATE TABLE b(bg, bc, bn, iv, ln, mg);
  CREATE INDEX b1 on b(bn, iv, bg);
}
do_eqp_test 110 {
  SELECT dc, count(cn)
    FROM (SELECT coalesce(b.bg, a.bc) as dc, cn
            FROM a LEFT JOIN b
                  ON a.bn = b.bn
                 AND CASE WHEN a.vb IS NOT NULL THEN 1 ELSE 0 END = b.iv
           WHERE pd BETWEEN 0 AND 10)
   GROUP BY dc;
} {
  QUERY PLAN
  |--SEARCH a USING COVERING INDEX a1 (pd>? AND pd<?)
  |--SEARCH b USING COVERING INDEX b1 (bn=? AND iv=?) LEFT-JOIN
  `--USE TEMP B-TREE FOR GROUP BY
}

reset_db
do_execsql_test 200 {
  CREATE TABLE t1(
    c00,c01,c02,c03,c04,c05,c06,c07,c08,c09,
    c10,c11,c12,c13,c14,c15,c16,c17,c18,c19,
    c20,c21,c22,c23,c24,c25,c26,c27,c28,c29,
    c30,c31,c32,c33,c34,c35,c36,c37,c38,c39,
    c40,c41,c42,c43,c44,c45,c46,c47,c48,c49,
    c50,c51,c52,c53,c54,c55,c56,c57,c58,c59,
    c60,c61,c62,c63,c64,c65,c66,c67,c68,c69,
    c70,c71,c72,c73,c74,c75,c76,c77,c78,c79,
    c80,c81,c82,c83,c84,c85,c86,c87,c88,c89,
    c90,c91,c92,c93,c94,c95,c96,c97,c98,c99,
    a,b,c,d,e
  );
  CREATE INDEX t1x1 on t1(c00,a,b,
        c01,c02,c03,c04,c05,c06,c07,c08,c09,
    c10,c11,c12,c13,c14,c15,c16,c17,c18,c19,
    c20,c21,c22,c23,c24,c25,c26,c27,c28,c29,
    c30,c31,c32,c33,c34,c35,c36,c37,c38,c39,
    c40,c41,c42,c43,c44,c45,c46,c47,c48,c49,
    c50,c51,c52,c53,c54,c55,c56,c57,c58,c59,
    c60,c61,c62,c63,c64,c65,c66,c67,c68,c69,
    c70,c71,c72,c73,c74,c75,c76,c77,c78,c79,
    c80,c81,c82,c83,c84,c85,c86,c87,c88,c89,
    c90,c91,c92,c93,c94,c00,c96,c97,c98,c99
  );
  CREATE INDEX t1cd ON t1(c,d);
  CREATE INDEX t1x2 ON t1(c01,c02,c03,a,b);
  WITH RECURSIVE c(x) AS (VALUES(0) UNION ALL SELECT x+1000 FROM c WHERE x<9000)
  INSERT INTO t1 SELECT
    x+00, x+01, x+02, x+03, x+04, x+05, x+06, x+07, x+08, x+09,
    x+10, x+11, x+12, x+13, x+14, x+15, x+16, x+17, x+18, x+19,
    x+20, x+21, x+22, x+23, x+24, x+25, x+26, x+27, x+28, x+29,
    x+30, x+31, x+32, x+33, x+34, x+35, x+36, x+37, x+38, x+39,
    x+40, x+41, x+42, x+43, x+44, x+45, x+46, x+47, x+48, x+49,
    x+50, x+51, x+52, x+53, x+54, x+55, x+56, x+57, x+58, x+59,
    x+60, x+61, x+62, x+63, x+64, x+65, x+66, x+67, x+68, x+69,
    x+70, x+71, x+72, x+73, x+74, x+75, x+76, x+77, x+78, x+79,
    x+80, x+81, x+82, x+83, x+84, x+85, x+86, x+87, x+88, x+89,
    x+90, x+91, x+92, x+93, x+94, x+95, x+96, x+97, x+98, x+99,
    x+100, x+101, x+102, x+103, x+104 FROM c;
}

do_execsql_test 210 {SELECT sum(c62) FROM t1;} 45620
do_execsql_test 220 {SELECT sum(c63) FROM t1;} 45630
do_execsql_test 230 {SELECT sum(c64) FROM t1;} 45640
do_execsql_test 240 {SELECT sum(c65) FROM t1;} 45650

do_execsql_test 300 {
  BEGIN;
  SELECT sum(c62) FROM t1;
  UPDATE t1 SET c62=c62+1 WHERE c00=1000;
  SELECT sum(c62) FROM t1;
} {45620 45621}
do_execsql_test 310 {
  SELECT sum(c65) FROM t1;
  UPDATE t1 SET c65=c65+1 WHERE c00=1000;
  SELECT sum(c65) FROM t1;
  ROLLBACK;
} {45650 45651}

do_execsql_test 320 {
  BEGIN;
  SELECT count(*) FROM t1;
  DELETE FROM t1 WHERE c=3102;
  SELECT COUNT(*) FROM t1;
  ROLLBACK;
} {10 9}
do_execsql_test 330 {
  BEGIN;
  SELECT count(*) FROM t1;
  DELETE FROM t1 WHERE c=3102 AND d=3103;
  SELECT COUNT(*) FROM t1;
  ROLLBACK;
} {10 9}
do_execsql_test 340 {
  BEGIN;
  DELETE FROM t1 WHERE (c,d) IN (VALUES(3102,3103),(4102,4103),(5102,5103),(1,2));
  SELECT count(*) FROM t1;
  ROLLBACK;
} {7}

do_execsql_test 400 {
  DROP INDEX t1cd;
  DROP INDEX t1x1;
  DROP INDEX t1x2;
  CREATE INDEX t1x3 ON t1(c00,c05,c08);
}
do_execsql_test 410 {SELECT sum(c08) FROM t1 WHERE c00 IN (1000,5000);} 6016
do_execsql_test 420 {SELECT sum(c63) FROM t1 WHERE c00 IN (1000,5000);} 6126
do_execsql_test 430 {SELECT sum(c64) FROM t1 WHERE c00 IN (1000,5000);} 6128

do_execsql_test 500 {
  DROP INDEX t1x3;
  CREATE TABLE t2 AS SELECT * FROM t1;
  CREATE INDEX t1x4 ON t1(c00, c62, a, b);
  CREATE INDEX t2x4 ON t2(c01, c62, c63, b, c);
  SELECT t1.b, t2.b FROM t1 JOIN t2 ON t2.c01=t1.c00+1 WHERE +t1.b<7000
   ORDER BY +t1.b;
} {101 101 1101 1101 2101 2101 3101 3101 4101 4101 5101 5101 6101 6101}

finish_test

Deleted test/wild001.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
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























































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# 2013-07-01
#
# 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 is a test case from content taken "from the wild".  In this
# particular instance, the query was provided with permission by
# Elan Feingold on 2013-06-27.  His message on the SQLite mailing list
# on that date reads:
#
#------------------------------------------------------------------------------
# > Can you send (1) the schema (2) the query that is giving problems, and (3)
# > the content of the sqlite_stat1 table after you have run ANALYZE?   If you
# > can combine all of the above into a script, that would be great!
# >
# > If you send (1..3) above and you give us written permission to include the
# > query in our test suite, that would be off-the-chain terrific.
#
# Please find items 1..3 in this file: http://www.plexapp.com/elan/sqlite_bug.txt
# 
# You have our permission to include the query in your test suite.
# 
# Thanks for an amazing product.
#-----------------------------------------------------------------------------
#
# This test case merely creates the schema and populates SQLITE_STAT1 and
# SQLITE_STAT3 then runs an EXPLAIN QUERY PLAN to ensure that the right plan
# is discovered.  This test case may need to be adjusted for future revisions
# of the query planner manage to select a better query plan.  The query plan
# shown here is known to be very fast with the original data.
#
# This test should work the same with and without SQLITE_ENABLE_STAT3
#
###############################################################################

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable !stat3 {
  finish_test
  return
}

do_execsql_test wild001.01 {
  CREATE TABLE "items" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "secid" integer, "parent_id" integer, "metadata_type" integer, "guid" varchar(255), "media_item_count" integer, "title" varchar(255), "title_sort" varchar(255) COLLATE NOCASE, "original_title" varchar(255), "studio" varchar(255), "rating" float, "rating_count" integer, "tagline" varchar(255), "summary" text, "trivia" text, "quotes" text, "content_rating" varchar(255), "content_rating_age" integer, "index" integer, "absolute_index" integer, "duration" integer, "user_thumb_url" varchar(255), "user_art_url" varchar(255), "user_banner_url" varchar(255), "user_music_url" varchar(255), "user_fields" varchar(255), "tags_genre" varchar(255), "tags_collection" varchar(255), "tags_director" varchar(255), "tags_writer" varchar(255), "tags_star" varchar(255), "originally_available_at" datetime, "available_at" datetime, "expires_at" datetime, "refreshed_at" datetime, "year" integer, "added_at" datetime, "created_at" datetime, "updated_at" datetime, "deleted_at" datetime, "tags_country" varchar(255), "extra_data" varchar(255), "hash" varchar(255));
  CREATE INDEX "i_secid" ON "items" ("secid" );
  CREATE INDEX "i_parent_id" ON "items" ("parent_id" );
  CREATE INDEX "i_created_at" ON "items" ("created_at" );
  CREATE INDEX "i_index" ON "items" ("index" );
  CREATE INDEX "i_title" ON "items" ("title" );
  CREATE INDEX "i_title_sort" ON "items" ("title_sort" );
  CREATE INDEX "i_guid" ON "items" ("guid" );
  CREATE INDEX "i_metadata_type" ON "items" ("metadata_type" );
  CREATE INDEX "i_deleted_at" ON "items" ("deleted_at" );
  CREATE INDEX "i_secid_ex1" ON "items" ("secid", "metadata_type", "added_at" );
  CREATE INDEX "i_hash" ON "items" ("hash" );
  CREATE TABLE "settings" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "account_id" integer, "guid" varchar(255), "rating" float, "view_offset" integer, "view_count" integer, "last_viewed_at" datetime, "created_at" datetime, "updated_at" datetime);
  CREATE INDEX "s_account_id" ON "settings" ("account_id" );
  CREATE INDEX "s_guid" ON "settings" ("guid" );
  ANALYZE;
  INSERT INTO sqlite_stat1 VALUES('settings','s_guid','4740 1');
  INSERT INTO sqlite_stat1 VALUES('settings','s_account_id','4740 4740');
  INSERT INTO sqlite_stat1 VALUES('items','i_hash','27316 2');
  INSERT INTO sqlite_stat1 VALUES('items','i_secid_ex1','27316 6829 4553 3');
  INSERT INTO sqlite_stat1 VALUES('items','i_deleted_at','27316 27316');
  INSERT INTO sqlite_stat1 VALUES('items','i_metadata_type','27316 6829');
  INSERT INTO sqlite_stat1 VALUES('items','i_guid','27316 2');
  INSERT INTO sqlite_stat1 VALUES('items','i_title_sort','27316 2');
  INSERT INTO sqlite_stat1 VALUES('items','i_title','27316 2');
  INSERT INTO sqlite_stat1 VALUES('items','i_index','27316 144');
  INSERT INTO sqlite_stat1 VALUES('items','i_created_at','27316 2');
  INSERT INTO sqlite_stat1 VALUES('items','i_parent_id','27316 15');
  INSERT INTO sqlite_stat1 VALUES('items','i_secid','27316 6829');
  INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,150,150,'com.plexapp.agents.thetvdb://153021/2/9?lang=en');
  INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,198,198,'com.plexapp.agents.thetvdb://194031/1/10?lang=en');
  INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,526,526,'com.plexapp.agents.thetvdb://71256/12/92?lang=en');
  INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,923,923,'com.plexapp.agents.thetvdb://71256/15/16?lang=en');
  INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,1008,1008,'com.plexapp.agents.thetvdb://71256/15/93?lang=en');
  INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,1053,1053,'com.plexapp.agents.thetvdb://71256/16/21?lang=en');
  INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,1068,1068,'com.plexapp.agents.thetvdb://71256/16/35?lang=en');
  INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,1235,1235,'com.plexapp.agents.thetvdb://71256/17/44?lang=en');
  INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,1255,1255,'com.plexapp.agents.thetvdb://71256/17/62?lang=en');
  INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,1573,1573,'com.plexapp.agents.thetvdb://71663/20/9?lang=en');
  INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,1580,1580,'com.plexapp.agents.thetvdb://71663/21/16?lang=en');
  INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,2000,2000,'com.plexapp.agents.thetvdb://73141/9/8?lang=en');
  INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,2107,2107,'com.plexapp.agents.thetvdb://73244/6/17?lang=en');
  INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,2256,2256,'com.plexapp.agents.thetvdb://74845/4/7?lang=en');
  INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,2408,2408,'com.plexapp.agents.thetvdb://75978/2/21?lang=en');
  INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,2634,2634,'com.plexapp.agents.thetvdb://79126/1/1?lang=en');
  INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,2962,2962,'com.plexapp.agents.thetvdb://79274/3/94?lang=en');
  INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,3160,3160,'com.plexapp.agents.thetvdb://79274/5/129?lang=en');
  INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,3161,3161,'com.plexapp.agents.thetvdb://79274/5/12?lang=en');
  INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,3688,3688,'com.plexapp.agents.thetvdb://79274/8/62?lang=en');
  INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,3714,3714,'com.plexapp.agents.thetvdb://79274/8/86?lang=en');
  INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,4002,4002,'com.plexapp.agents.thetvdb://79590/13/17?lang=en');
  INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,4215,4215,'com.plexapp.agents.thetvdb://80727/3/6?lang=en');
  INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,4381,4381,'com.plexapp.agents.thetvdb://83462/3/24?lang=en');
  INSERT INTO sqlite_stat3 VALUES('settings','s_account_id',4740,0,0,1);
  INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,1879,1879,'1113f632ccd52ec8b8d7ca3d6d56da4701e48018');
  INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,2721,2721,'1936154b97bb5567163edaebc2806830ae419ccf');
  INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,3035,3035,'1c122331d4b7bfa0dc2c003ab5fb4f7152b9987a');
  INSERT INTO sqlite_stat3 VALUES('items','i_hash',2,3393,3393,'1f81bdbc9acc3321dc592b1a109ca075731b549a');
  INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,6071,6070,'393cf7713efb4519c7a3d1d5403f0d945d15a16a');
  INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,7462,7461,'4677dd37011f8bd9ae7fbbdd3af6dcd8a5b4ab2d');
  INSERT INTO sqlite_stat3 VALUES('items','i_hash',2,8435,8434,'4ffa339485334e81a5e12e03a63b6508d76401cf');
  INSERT INTO sqlite_stat3 VALUES('items','i_hash',2,8716,8714,'52a093852e6599dd5004857b7ff5b5b82c7cdb25');
  INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,9107,9104,'561183e39f866d97ec728e9ff16ac4ad01466111');
  INSERT INTO sqlite_stat3 VALUES('items','i_hash',2,10942,10939,'66e99b72e29610f49499ae09ee04a376210d1f08');
  INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,12143,12139,'71f0602427e173dc2c551535f73fdb6885fe4302');
  INSERT INTO sqlite_stat3 VALUES('items','i_hash',2,14962,14958,'8ca8e4dfba696019830c19ab8a32c7ece9d8534b');
  INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,15179,15174,'8ebf1a5cf33f8ada1fc5853ac06ac4d7e074f825');
  INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,15375,15370,'908bc211bebdf21c79d2d2b54ebaa442ac1f5cae');
  INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,18215,18210,'ab29e4e18ec5a14fef95aa713d69e31c045a22c1');
  INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,18615,18610,'ae84c008cc0c338bf4f28d798a88575746452f6d');
  INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,18649,18644,'aec7c901353e115aa5307e94018ba7507bec3a45');
  INSERT INTO sqlite_stat3 VALUES('items','i_hash',2,19517,19512,'b75025fbf2e9c504e3c1197ff1b69250402a31f8');
  INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,21251,21245,'c7d32f0e3a8f3a0a3dbd00833833d2ccee62f0fd');
  INSERT INTO sqlite_stat3 VALUES('items','i_hash',2,23616,23610,'dd5ff61479a9bd4100de802515d9dcf72d46f07a');
  INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,24287,24280,'e3db00034301b7555419d4ef6f64769298d5845e');
  INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,24949,24942,'ea336abd197ecd7013854a25a4f4eb9dea7927c6');
  INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,25574,25567,'f018ea5182ec3f32768ca1c3cefbf3ad160ec20b');
  INSERT INTO sqlite_stat3 VALUES('items','i_hash',2,26139,26132,'f53709a8d81c12cb0f4f8d58004a25dd063de67c');
  INSERT INTO sqlite_stat3 VALUES('items','i_secid_ex1',25167,0,0,2);
  INSERT INTO sqlite_stat3 VALUES('items','i_secid_ex1',736,25167,1,3);
  INSERT INTO sqlite_stat3 VALUES('items','i_secid_ex1',15,25903,2,4);
  INSERT INTO sqlite_stat3 VALUES('items','i_secid_ex1',1398,25918,3,5);
  INSERT INTO sqlite_stat3 VALUES('items','i_deleted_at',27316,0,0,NULL);
  INSERT INTO sqlite_stat3 VALUES('items','i_metadata_type',2149,0,0,1);
  INSERT INTO sqlite_stat3 VALUES('items','i_metadata_type',411,2149,1,2);
  INSERT INTO sqlite_stat3 VALUES('items','i_metadata_type',1440,2560,2,3);
  INSERT INTO sqlite_stat3 VALUES('items','i_metadata_type',23316,4000,3,4);
  INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,215,215,'com.plexapp.agents.imdb://tt0065702?lang=en');
  INSERT INTO sqlite_stat3 VALUES('items','i_guid',2,711,711,'com.plexapp.agents.imdb://tt0198781?lang=en');
  INSERT INTO sqlite_stat3 VALUES('items','i_guid',2,987,986,'com.plexapp.agents.imdb://tt0454876?lang=en');
  INSERT INTO sqlite_stat3 VALUES('items','i_guid',2,1004,1002,'com.plexapp.agents.imdb://tt0464154?lang=en');
  INSERT INTO sqlite_stat3 VALUES('items','i_guid',2,1056,1053,'com.plexapp.agents.imdb://tt0499549?lang=en');
  INSERT INTO sqlite_stat3 VALUES('items','i_guid',2,1120,1116,'com.plexapp.agents.imdb://tt0903624?lang=en');
  INSERT INTO sqlite_stat3 VALUES('items','i_guid',2,1250,1245,'com.plexapp.agents.imdb://tt1268799?lang=en');
  INSERT INTO sqlite_stat3 VALUES('items','i_guid',2,1270,1264,'com.plexapp.agents.imdb://tt1320261?lang=en');
  INSERT INTO sqlite_stat3 VALUES('items','i_guid',2,1376,1369,'com.plexapp.agents.imdb://tt1772341?lang=en');
  INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,3035,3027,'com.plexapp.agents.thetvdb://153021/3/14?lang=en');
  INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,6071,6063,'com.plexapp.agents.thetvdb://71173/1/18?lang=en');
  INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,6342,6334,'com.plexapp.agents.thetvdb://71256/13/4?lang=en');
  INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,9107,9099,'com.plexapp.agents.thetvdb://72389/2/19?lang=en');
  INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,11740,11732,'com.plexapp.agents.thetvdb://73893/2/13?lang=en');
  INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,12143,12135,'com.plexapp.agents.thetvdb://73976/4/23?lang=en');
  INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,15179,15171,'com.plexapp.agents.thetvdb://75897/16/12?lang=en');
  INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,17408,17400,'com.plexapp.agents.thetvdb://76808/2/16?lang=en');
  INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,17984,17976,'com.plexapp.agents.thetvdb://77068/1/16?lang=en');
  INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,18215,18207,'com.plexapp.agents.thetvdb://77259/1/1?lang=en');
  INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,21251,21243,'com.plexapp.agents.thetvdb://78957/8/2?lang=en');
  INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,24287,24279,'com.plexapp.agents.thetvdb://80337/5/8?lang=en');
  INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,25513,25505,'com.plexapp.agents.thetvdb://82226/6?lang=en');
  INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,25548,25540,'com.plexapp.agents.thetvdb://82339/2/10?lang=en');
  INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,26770,26762,'com.plexapp.agents.thetvdb://86901/1/3?lang=en');
  INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',1524,0,0,'');
  INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',2,3034,1391,'Attack of the Giant Squid');
  INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',51,4742,2895,'Brad Sherwood');
  INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',11,4912,2996,'Brian Williams');
  INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',39,5847,3857,'Chip Esten');
  INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',1,6071,4015,'Chuck Versus the DeLorean');
  INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',12,7625,5436,'Denny Siegel');
  INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',30,8924,6618,'Episode 1');
  INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',29,9015,6629,'Episode 2');
  INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',32,9082,6643,'Episode 3');
  INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',28,9135,6654,'Episode 4');
  INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',26,9183,6665,'Episode 5');
  INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',27,9229,6677,'Episode 6');
  INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',22,9266,6688,'Episode 7');
  INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',20,9298,6699,'Episode 8');
  INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',55,11750,8817,'Greg Proops');
  INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',1,12143,9120,'Hardware Jungle');
  INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',33,14712,11435,'Kathy Greenwood');
  INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',3,15179,11840,'Last Call');
  INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',1,18215,14601,'Nature or Nurture?');
  INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',12,18241,14623,'Neil DeGrasse Tyson');
  INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',68,19918,16144,'Pilot');
  INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',7,21251,17298,'Reza Aslan');
  INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',1,24287,20035,'Technoviking');
  INSERT INTO sqlite_stat3 VALUES('items','i_title',1524,0,0,'');
  INSERT INTO sqlite_stat3 VALUES('items','i_title',1,3035,1429,'Anderson Can''t Dance');
  INSERT INTO sqlite_stat3 VALUES('items','i_title',51,4782,2991,'Brad Sherwood');
  INSERT INTO sqlite_stat3 VALUES('items','i_title',11,4936,3079,'Brian Williams');
  INSERT INTO sqlite_stat3 VALUES('items','i_title',39,5694,3783,'Chip Esten');
  INSERT INTO sqlite_stat3 VALUES('items','i_title',1,6071,4100,'Clive Warren');
  INSERT INTO sqlite_stat3 VALUES('items','i_title',12,7144,5078,'Denny Siegel');
  INSERT INTO sqlite_stat3 VALUES('items','i_title',30,8249,6097,'Episode 1');
  INSERT INTO sqlite_stat3 VALUES('items','i_title',29,8340,6108,'Episode 2');
  INSERT INTO sqlite_stat3 VALUES('items','i_title',32,8407,6122,'Episode 3');
  INSERT INTO sqlite_stat3 VALUES('items','i_title',28,8460,6133,'Episode 4');
  INSERT INTO sqlite_stat3 VALUES('items','i_title',26,8508,6144,'Episode 5');
  INSERT INTO sqlite_stat3 VALUES('items','i_title',27,8554,6156,'Episode 6');
  INSERT INTO sqlite_stat3 VALUES('items','i_title',22,8591,6167,'Episode 7');
  INSERT INTO sqlite_stat3 VALUES('items','i_title',20,8623,6178,'Episode 8');
  INSERT INTO sqlite_stat3 VALUES('items','i_title',1,9107,6537,'Fat Albert and the Cosby Kids');
  INSERT INTO sqlite_stat3 VALUES('items','i_title',55,10539,7843,'Greg Proops');
  INSERT INTO sqlite_stat3 VALUES('items','i_title',1,12143,9276,'Iron Age Remains');
  INSERT INTO sqlite_stat3 VALUES('items','i_title',33,13118,10143,'Kathy Greenwood');
  INSERT INTO sqlite_stat3 VALUES('items','i_title',1,15179,11972,'Mink');
  INSERT INTO sqlite_stat3 VALUES('items','i_title',68,17411,14035,'Pilot');
  INSERT INTO sqlite_stat3 VALUES('items','i_title',2,18214,14727,'Reflections');
  INSERT INTO sqlite_stat3 VALUES('items','i_title',4,21250,17481,'The Apartment');
  INSERT INTO sqlite_stat3 VALUES('items','i_title',1,24287,20283,'The Simpsons Already Did It');
  INSERT INTO sqlite_stat3 VALUES('items','i_index',4315,95,2,1);
  INSERT INTO sqlite_stat3 VALUES('items','i_index',1553,4410,3,2);
  INSERT INTO sqlite_stat3 VALUES('items','i_index',1485,5963,4,3);
  INSERT INTO sqlite_stat3 VALUES('items','i_index',1414,7448,5,4);
  INSERT INTO sqlite_stat3 VALUES('items','i_index',1367,8862,6,5);
  INSERT INTO sqlite_stat3 VALUES('items','i_index',1328,10229,7,6);
  INSERT INTO sqlite_stat3 VALUES('items','i_index',1161,11557,8,7);
  INSERT INTO sqlite_stat3 VALUES('items','i_index',1108,12718,9,8);
  INSERT INTO sqlite_stat3 VALUES('items','i_index',1033,13826,10,9);
  INSERT INTO sqlite_stat3 VALUES('items','i_index',1014,14859,11,10);
  INSERT INTO sqlite_stat3 VALUES('items','i_index',929,15873,12,11);
  INSERT INTO sqlite_stat3 VALUES('items','i_index',906,16802,13,12);
  INSERT INTO sqlite_stat3 VALUES('items','i_index',844,17708,14,13);
  INSERT INTO sqlite_stat3 VALUES('items','i_index',690,18552,15,14);
  INSERT INTO sqlite_stat3 VALUES('items','i_index',655,19242,16,15);
  INSERT INTO sqlite_stat3 VALUES('items','i_index',625,19897,17,16);
  INSERT INTO sqlite_stat3 VALUES('items','i_index',579,20522,18,17);
  INSERT INTO sqlite_stat3 VALUES('items','i_index',555,21101,19,18);
  INSERT INTO sqlite_stat3 VALUES('items','i_index',526,21656,20,19);
  INSERT INTO sqlite_stat3 VALUES('items','i_index',501,22182,21,20);
  INSERT INTO sqlite_stat3 VALUES('items','i_index',459,22683,22,21);
  INSERT INTO sqlite_stat3 VALUES('items','i_index',439,23142,23,22);
  INSERT INTO sqlite_stat3 VALUES('items','i_index',315,23581,24,23);
  INSERT INTO sqlite_stat3 VALUES('items','i_index',192,24177,26,25);
  INSERT INTO sqlite_stat3 VALUES('items','i_created_at',1851,0,0,NULL);
  INSERT INTO sqlite_stat3 VALUES('items','i_created_at',373,1857,2,'2011-10-22 14:54:39');
  INSERT INTO sqlite_stat3 VALUES('items','i_created_at',595,2230,3,'2011-10-22 14:54:41');
  INSERT INTO sqlite_stat3 VALUES('items','i_created_at',337,2825,4,'2011-10-22 14:54:43');
  INSERT INTO sqlite_stat3 VALUES('items','i_created_at',361,3378,8,'2011-10-22 14:54:54');
  INSERT INTO sqlite_stat3 VALUES('items','i_created_at',160,3739,9,'2011-10-22 14:54:56');
  INSERT INTO sqlite_stat3 VALUES('items','i_created_at',315,4000,11,'2011-10-22 14:54:59');
  INSERT INTO sqlite_stat3 VALUES('items','i_created_at',321,4334,13,'2011-10-22 14:55:02');
  INSERT INTO sqlite_stat3 VALUES('items','i_created_at',1292,4723,16,'2011-10-22 14:55:06');
  INSERT INTO sqlite_stat3 VALUES('items','i_created_at',161,6015,17,'2011-10-22 14:55:07');
  INSERT INTO sqlite_stat3 VALUES('items','i_created_at',1,9107,2677,'2012-09-04 18:07:50');
  INSERT INTO sqlite_stat3 VALUES('items','i_created_at',313,9717,3270,'2012-10-18 16:50:21');
  INSERT INTO sqlite_stat3 VALUES('items','i_created_at',450,10030,3271,'2012-10-18 16:50:22');
  INSERT INTO sqlite_stat3 VALUES('items','i_created_at',389,10668,3275,'2012-10-18 16:50:26');
  INSERT INTO sqlite_stat3 VALUES('items','i_created_at',796,11057,3276,'2012-10-18 16:51:06');
  INSERT INTO sqlite_stat3 VALUES('items','i_created_at',161,12041,3280,'2012-10-19 19:52:37');
  INSERT INTO sqlite_stat3 VALUES('items','i_created_at',135,13281,4186,'2013-02-19 00:56:10');
  INSERT INTO sqlite_stat3 VALUES('items','i_created_at',1063,13416,4187,'2013-02-19 00:56:11');
  INSERT INTO sqlite_stat3 VALUES('items','i_created_at',797,14479,4188,'2013-02-19 00:56:13');
  INSERT INTO sqlite_stat3 VALUES('items','i_created_at',147,15276,4189,'2013-02-19 00:56:15');
  INSERT INTO sqlite_stat3 VALUES('items','i_created_at',346,15423,4190,'2013-02-19 00:56:16');
  INSERT INTO sqlite_stat3 VALUES('items','i_created_at',1,18215,6436,'2013-05-05 14:09:54');
  INSERT INTO sqlite_stat3 VALUES('items','i_created_at',2,21251,8122,'2013-05-24 15:25:45');
  INSERT INTO sqlite_stat3 VALUES('items','i_created_at',1,24287,11116,'2013-05-26 14:17:39');
  INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',2560,0,0,NULL);
  INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',18,3022,31,2350);
  INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',10,6068,285,8150);
  INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',158,6346,315,8949);
  INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',34,9094,562,18831);
  INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',20,12139,794,22838);
  INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',134,14033,886,24739);
  INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',159,14167,887,24740);
  INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',161,14326,888,24741);
  INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',161,14487,889,24742);
  INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',124,14648,890,24743);
  INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',157,14772,891,24744);
  INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',126,15043,894,24747);
  INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',40,15169,895,24748);
  INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',161,15243,898,24753);
  INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',138,15404,899,24754);
  INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',160,15542,900,24755);
  INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',161,15702,901,24756);
  INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',161,15863,902,24757);
  INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',124,16024,903,24758);
  INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',155,16148,904,24759);
  INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',26,18208,1043,29704);
  INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',2,21251,1282,32952);
  INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',13,24279,1583,36068);
  INSERT INTO sqlite_stat3 VALUES('items','i_secid',25167,0,0,2);
  INSERT INTO sqlite_stat3 VALUES('items','i_secid',736,25167,1,3);
  INSERT INTO sqlite_stat3 VALUES('items','i_secid',15,25903,2,4);
  INSERT INTO sqlite_stat3 VALUES('items','i_secid',1398,25918,3,5);
  ANALYZE sqlite_master;
  
  explain query plan
  select items.title
    from items
         join items as child on child.parent_id=items.id
         join items as grandchild on grandchild.parent_id=child.id
         join settings
                    on settings.guid=grandchild.guid
                   and settings.account_id=1
   where items.metadata_type=2
     and items.secid=2
     and settings.last_viewed_at is not null
   group by items.id
   order by settings.last_viewed_at desc
   limit 10;
} [list \
 0 0 3 {SEARCH TABLE settings USING INDEX s_account_id (account_id=?)} \
 0 1 2 {SEARCH TABLE items AS grandchild USING INDEX i_guid (guid=?)} \
 0 2 1 {SEARCH TABLE items AS child USING INTEGER PRIMARY KEY (rowid=?)} \
 0 3 0 {SEARCH TABLE items USING INTEGER PRIMARY KEY (rowid=?)} \
 0 0 0 {USE TEMP B-TREE FOR GROUP BY} \
 0 0 0 {USE TEMP B-TREE FOR ORDER BY}]


finish_test

Changes to test/win32lock.test.

1
2
3
4
5
6
7
8
9
10
11
12
13


14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22













+
+







# 2011 July 11
#
# 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 script is recovery from transient manditory locks
# that sometimes appear on database files due to anti-virus software.
#
# TESTRUNNER: slow
#

if {$tcl_platform(platform)!="windows"} return

set testdir [file dirname $argv0]
source $testdir/tester.tcl

Changes to test/win32longpath.test.

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
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







+
-
+




















+
+
+



+
+
+



+
+
+




+
+
+
+
+
+
+







set testprefix win32longpath

do_test 1.0 {
  file_control_vfsname db
} win32

db close
set rawPath [get_pwd]
set path [file nativename [get_pwd]]
set path [file nativename $rawPath]
sqlite3 db [file join $path test.db] -vfs win32-longpath

do_test 1.1 {
  file_control_vfsname db
} win32-longpath

do_test 1.2 {
  db eval {
    BEGIN EXCLUSIVE;
    CREATE TABLE t1(x);
    INSERT INTO t1 VALUES(1);
    INSERT INTO t1 VALUES(2);
    INSERT INTO t1 VALUES(3);
    INSERT INTO t1 VALUES(4);
    SELECT x FROM t1 ORDER BY x;
    COMMIT;
  }
} {1 2 3 4}

set longPath(1) \\\\?\\$path\\[pid]
set uriPath(1a) %5C%5C%3F%5C$path\\[pid]
set uriPath(1b) %5C%5C%3F%5C$rawPath/[pid]

make_win32_dir $longPath(1)

set longPath(2) $longPath(1)\\[string repeat X 255]
set uriPath(2a) $uriPath(1a)\\[string repeat X 255]
set uriPath(2b) $uriPath(1b)/[string repeat X 255]

make_win32_dir $longPath(2)

set longPath(3) $longPath(2)\\[string repeat Y 255]
set uriPath(3a) $uriPath(2a)\\[string repeat Y 255]
set uriPath(3b) $uriPath(2b)/[string repeat Y 255]

make_win32_dir $longPath(3)

set fileName $longPath(3)\\test.db

set uri(1a) file:$uriPath(3a)\\test.db
set uri(1b) file:$uriPath(3b)/test.db
set uri(1c) file:///$uriPath(3a)\\test.db
set uri(1d) file:///$uriPath(3b)/test.db
set uri(1e) file://localhost/$uriPath(3a)\\test.db
set uri(1f) file://localhost/$uriPath(3b)/test.db

do_test 1.3 {
  list [catch {sqlite3 db2 [string range $fileName 4 end]} msg] $msg
} {1 {unable to open database file}}

sqlite3 db3 $fileName -vfs win32-longpath

do_test 1.4 {
95
96
97
98
99
100
101












102
103
104
105
106
107
108
109
110
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







+
+
+
+
+
+
+
+
+
+
+
+









    SELECT x FROM t1 ORDER BY x;
    COMMIT;
  }
} {5 6 7 8 9 10 11 12}

db3 close
# puts "  Database exists \{[exists_win32_path $fileName]\}"

foreach tn {1a 1b 1c 1d 1e 1f} {
  sqlite3 db3 $uri($tn) -vfs win32-longpath -uri 1 -translatefilename 0

  do_test 1.7.$tn {
    db3 eval {
      SELECT x FROM t1 ORDER BY x;
    }
  } {5 6 7 8 9 10 11 12}

  db3 close
}

do_delete_win32_file $fileName
# puts "  Files remaining \{[find_win32_file $longPath(3)\\*]\}"

do_remove_win32_dir $longPath(3)
do_remove_win32_dir $longPath(2)
do_remove_win32_dir $longPath(1)

finish_test

Changes to test/window1.test.

208
209
210
211
212
213
214
215


216
217
218

219
220
221
222
223
224
225
208
209
210
211
212
213
214

215
216
217

218
219
220
221
222
223
224
225
226







-
+
+

-

+







  CREATE TABLE t2(x);
  INSERT INTO t2 VALUES('b'), ('a');

  SELECT x, count(*) OVER (ORDER BY x) FROM t1;
} {1 1 2 2 3 3 4 4 5 5 6 6 7 7}

do_execsql_test 6.2 {
  SELECT * FROM t2, (SELECT x, count(*) OVER (ORDER BY x) FROM t1);
  SELECT * FROM t2, (SELECT x, count(*) OVER (ORDER BY x) FROM t1)
  ORDER BY 1, 2;
} {
  b 1 1 b 2 2 b 3 3 b 4 4 b 5 5 b 6 6 b 7 7
  a 1 1 a 2 2 a 3 3 a 4 4 a 5 5 a 6 6 a 7 7
  b 1 1 b 2 2 b 3 3 b 4 4 b 5 5 b 6 6 b 7 7
}

do_catchsql_test 6.3 {
  SELECT x, lag(x) FILTER (WHERE (x%2)=0) OVER w FROM t1 
  WINDOW w AS (ORDER BY x)
} {1 {FILTER clause may only be used with aggregate window functions}}
 
253
254
255
256
257
258
259



260
261
262
263
264
265
266
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270







+
+
+







} {1 {no such column: x}}
do_catchsql_test 7.1.6 {
  SELECT trim(x) OVER (ORDER BY y) FROM t1;
} {1 {trim() may not be used as a window function}}
do_catchsql_test 7.1.7 {
  SELECT max(x) OVER abc FROM t1 WINDOW def AS (ORDER BY y);
} {1 {no such window: abc}}
do_catchsql_test 7.1.8 {
  SELECT row_number(x) OVER () FROM t1
} {1 {wrong number of arguments to function row_number()}}

do_execsql_test 7.2 {
  SELECT 
    lead(y) OVER win, 
    lead(y, 2) OVER win, 
    lead(y, 3, 'default') OVER win
  FROM t1
367
368
369
370
371
372
373
































374
375
376
377
378
379
380
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  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),
587
588
589
590
591
592
593
594

595
596
597
598
599
600
601
602
623
624
625
626
627
628
629

630

631
632
633
634
635
636
637







-
+
-







  1 1   2 2 
}

do_execsql_test 13.5 {
  SELECT a, rank() OVER(ORDER BY b) FROM t1
    INTERSECT 
  SELECT a, rank() OVER(ORDER BY b DESC) FROM t1;
} {
} {}
}

# 2018-12-06
# https://www.sqlite.org/src/info/f09fcd17810f65f7
# Assertion fault when window functions are used.
#
# Root cause is the query flattener invoking sqlite3ExprDup() on
# expressions that contain subqueries with window functions.  The
616
617
618
619
620
621
622


















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































623
624
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
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
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
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
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
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
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
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
1984
1985
1986
1987
1988
1989
1990
1991
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
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
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
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


  CREATE TABLE t2(c); INSERT INTO t2(c) VALUES(1);
  SELECT y, y+1, y+2 FROM (
    SELECT c IN (
      SELECT (row_number() OVER()) FROM t1
    ) AS y FROM t2
  );
} {1 2 3}

# 2018-12-31
# https://www.sqlite.org/src/info/d0866b26f83e9c55
# Window function in correlated subquery causes assertion fault 
#
do_catchsql_test 15.0 {
  WITH t(id, parent) AS (
  SELECT CAST(1 AS INT), CAST(NULL AS INT)
  UNION ALL
  SELECT 2, NULL
  UNION ALL
  SELECT 3, 1
  UNION ALL
  SELECT 4, 1
  UNION ALL
  SELECT 5, 2
  UNION ALL
  SELECT 6, 2
  ), q AS (
  SELECT t.*, ROW_NUMBER() OVER (ORDER BY t.id) AS rn
    FROM t
   WHERE parent IS NULL
   UNION ALL
  SELECT t.*, ROW_NUMBER() OVER (ORDER BY t.id) AS rn
    FROM q
    JOIN t
      ON t.parent = q.id
  )
  SELECT *
    FROM q;
} {1 {cannot use window functions in recursive queries}}
do_execsql_test 15.1 {
  DROP TABLE IF EXISTS t1;
  DROP TABLE IF EXISTS t2;
  CREATE TABLE t1(x);
  INSERT INTO t1 VALUES('a'), ('b'), ('c');
  CREATE TABLE t2(a, b);
  INSERT INTO t2 VALUES('X', 1), ('X', 2), ('Y', 2), ('Y', 3);
  SELECT x, (
    SELECT sum(b)
      OVER (PARTITION BY a ROWS BETWEEN UNBOUNDED PRECEDING
                                    AND UNBOUNDED FOLLOWING)
    FROM t2 WHERE b<x
  ) FROM t1;
} {a 3 b 3 c 3}

do_execsql_test 15.2 {
  SELECT(
    WITH c AS(
      VALUES(1)
    ) SELECT '' FROM c,c
  ) x WHERE x+x;
} {}

#-------------------------------------------------------------------------

do_execsql_test 16.0 {
  CREATE TABLE t7(a,b); 
  INSERT INTO t7(rowid, a, b) VALUES
      (1, 1, 3),
      (2, 10, 4),
      (3, 100, 2);
}

do_execsql_test 16.1 {
  SELECT rowid, sum(a) OVER (PARTITION BY b IN (SELECT rowid FROM t7)) FROM t7;
} {
  2 10
  1 101
  3 101
}

do_execsql_test 16.2 {
  SELECT rowid, sum(a) OVER w1 FROM t7 
  WINDOW w1 AS (PARTITION BY b IN (SELECT rowid FROM t7));
} {
  2 10
  1 101
  3 101
}

#-------------------------------------------------------------------------
do_execsql_test 17.0 {
  CREATE TABLE t8(a);
  INSERT INTO t8 VALUES(1), (2), (3);
}

do_execsql_test 17.1 {
  SELECT +sum(0) OVER () ORDER BY +sum(0) OVER ();
} {0}

do_execsql_test 17.2 {
  select +sum(a) OVER () FROM t8 ORDER BY +sum(a) OVER () DESC;
} {6 6 6}

do_execsql_test 17.3 {
  SELECT 10+sum(a) OVER (ORDER BY a) 
  FROM t8 
  ORDER BY 10+sum(a) OVER (ORDER BY a) DESC;
} {16 13 11}


#-------------------------------------------------------------------------
# Test error cases from chaining window definitions.
#
reset_db
do_execsql_test 18.0 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT, c TEXT, d INTEGER);
  INSERT INTO t1 VALUES(1, 'odd',  'one',   1);
  INSERT INTO t1 VALUES(2, 'even', 'two',   2);
  INSERT INTO t1 VALUES(3, 'odd',  'three', 3);
  INSERT INTO t1 VALUES(4, 'even', 'four',  4);
  INSERT INTO t1 VALUES(5, 'odd',  'five',  5);
  INSERT INTO t1 VALUES(6, 'even', 'six',   6);
}

foreach {tn sql error} {
  1 {
    SELECT c, sum(d) OVER win2 FROM t1
      WINDOW win1 AS (ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING), 
             win2 AS (win1 ORDER BY b)
  } {cannot override frame specification of window: win1}

  2 {
    SELECT c, sum(d) OVER win2 FROM t1
      WINDOW win1 AS (),
             win2 AS (win4 ORDER BY b)
  } {no such window: win4}

  3 {
    SELECT c, sum(d) OVER win2 FROM t1
      WINDOW win1 AS (),
             win2 AS (win1 PARTITION BY d)
  } {cannot override PARTITION clause of window: win1}

  4 {
    SELECT c, sum(d) OVER win2 FROM t1
      WINDOW win1 AS (ORDER BY b),
             win2 AS (win1 ORDER BY d)
  } {cannot override ORDER BY clause of window: win1}
} {
  do_catchsql_test 18.1.$tn $sql [list 1 $error]
}

foreach {tn sql error} {
  1 {
    SELECT c, sum(d) OVER (win1 ORDER BY b) FROM t1
      WINDOW win1 AS (ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING)
  } {cannot override frame specification of window: win1}

  2 {
    SELECT c, sum(d) OVER (win4 ORDER BY b) FROM t1
      WINDOW win1 AS ()
  } {no such window: win4}

  3 {
    SELECT c, sum(d) OVER (win1 PARTITION BY d) FROM t1
      WINDOW win1 AS ()
  } {cannot override PARTITION clause of window: win1}

  4 {
    SELECT c, sum(d) OVER (win1 ORDER BY d) FROM t1
      WINDOW win1 AS (ORDER BY b)
  } {cannot override ORDER BY clause of window: win1}
} {
  do_catchsql_test 18.2.$tn $sql [list 1 $error]
}

do_execsql_test 18.3.1 {
  SELECT group_concat(c, '.') OVER (PARTITION BY b ORDER BY c)
  FROM t1
} {four four.six four.six.two five five.one five.one.three}

do_execsql_test 18.3.2 {
  SELECT group_concat(c, '.') OVER (win1 ORDER BY c)
  FROM t1
  WINDOW win1 AS (PARTITION BY b)
} {four four.six four.six.two five five.one five.one.three}

do_execsql_test 18.3.3 {
  SELECT group_concat(c, '.') OVER win2
  FROM t1
  WINDOW win1 AS (PARTITION BY b),
         win2 AS (win1 ORDER BY c)
} {four four.six four.six.two five five.one five.one.three}

do_execsql_test 18.3.4 {
  SELECT group_concat(c, '.') OVER (win2)
  FROM t1
  WINDOW win1 AS (PARTITION BY b),
         win2 AS (win1 ORDER BY c)
} {four four.six four.six.two five five.one five.one.three}

do_execsql_test 18.3.5 {
  SELECT group_concat(c, '.') OVER win5
  FROM t1
  WINDOW win1 AS (PARTITION BY b),
         win2 AS (win1),
         win3 AS (win2),
         win4 AS (win3),
         win5 AS (win4 ORDER BY c)
} {four four.six four.six.two five five.one five.one.three}

#-------------------------------------------------------------------------
# Test RANGE <expr> PRECEDING/FOLLOWING when there are string, blob
# and NULL values in the dataset.
#
reset_db
do_execsql_test 19.0 {
  CREATE TABLE t1(a, b);
  INSERT INTO t1 VALUES
    (1, 1), (2, 2), (3, 3), (4, 4), (5, 5),
    ('a', 6), ('b', 7), ('c', 8), ('d', 9), ('e', 10);
}
do_execsql_test 19.1 {
  SELECT a, sum(b) OVER (ORDER BY a) FROM t1;
} {1 1  2 3  3 6  4 10  5 15  a 21 b 28 c 36 d 45 e 55}

do_execsql_test 19.2.1 {
  SELECT a, sum(b) OVER (
    ORDER BY a RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING
  ) FROM t1;
} {1 3 2 6 3 9 4 12 5 9 a 6 b 7 c 8 d 9 e 10}
do_execsql_test 19.2.2 {
  SELECT a, sum(b) OVER (
    ORDER BY a DESC RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING
  ) FROM t1 ORDER BY a ASC;
} {1 3 2 6 3 9 4 12 5 9 a 6 b 7 c 8 d 9 e 10}

do_execsql_test 19.3.1 {
  SELECT a, sum(b) OVER (
    ORDER BY a RANGE BETWEEN 2 PRECEDING AND 1 FOLLOWING
  ) FROM t1;
} {1 3 2 6 3 10 4 14 5 12 a 6 b 7 c 8 d 9 e 10}
do_execsql_test 19.3.2 {
  SELECT a, sum(b) OVER (
    ORDER BY a DESC RANGE BETWEEN 1 PRECEDING AND 2 FOLLOWING
  ) FROM t1 ORDER BY a ASC;
} {1 3 2 6 3 10 4 14 5 12 a 6 b 7 c 8 d 9 e 10}


reset_db
do_execsql_test 20.0 {
  CREATE TABLE t1(a, b);
  INSERT INTO t1 VALUES
    (NULL, 100), (NULL, 100), 
    (1, 1), (2, 2), (3, 3), (4, 4), (5, 5),
    ('a', 6), ('b', 7), ('c', 8), ('d', 9), ('e', 10);
}
do_execsql_test 20.1 {
  SELECT a, sum(b) OVER (ORDER BY a) FROM t1;
} {
  {} 200 {} 200 1 201  2 203  3 206  4 210  5 215  
  a 221 b 228 c 236 d 245 e 255
}

do_execsql_test 20.2.1 {
  SELECT a, sum(b) OVER (
    ORDER BY a RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING
  ) FROM t1;
} {{} 200 {} 200 1 3 2 6 3 9 4 12 5 9 a 6 b 7 c 8 d 9 e 10}
do_execsql_test 20.2.2 {
  SELECT a, sum(b) OVER (
    ORDER BY a DESC RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING
  ) FROM t1 ORDER BY a ASC;
} {{} 200 {} 200 1 3 2 6 3 9 4 12 5 9 a 6 b 7 c 8 d 9 e 10}

do_execsql_test 20.3.1 {
  SELECT a, sum(b) OVER (
    ORDER BY a RANGE BETWEEN 2 PRECEDING AND 1 FOLLOWING
  ) FROM t1;
} {{} 200 {} 200 1 3 2 6 3 10 4 14 5 12 a 6 b 7 c 8 d 9 e 10}
do_execsql_test 20.3.2 {
  SELECT a, sum(b) OVER (
    ORDER BY a DESC RANGE BETWEEN 1 PRECEDING AND 2 FOLLOWING
  ) FROM t1 ORDER BY a ASC;
} {{} 200 {} 200 1 3 2 6 3 10 4 14 5 12 a 6 b 7 c 8 d 9 e 10}

#-------------------------------------------------------------------------
do_execsql_test 21.0 {
  CREATE TABLE keyword_tab(
    current, exclude, filter, following, groups, no, others, over,
    partition, preceding, range, ties, unbounded, window
  );
}
do_execsql_test 21.1 {
  SELECT
    current, exclude, filter, following, groups, no, others, over,
    partition, preceding, range, ties, unbounded, window
  FROM keyword_tab
}

#-------------------------------------------------------------------------
foreach {tn expr err} {
  1   4.5      0
  2   NULL     1
  3   0.0      0
  4   0.1      0
  5  -0.1      1
  6  ''        1
  7  '2.0'     0
  8  '2.0x'    1
  9  x'1234'   1
 10  '1.2'     0
} {
  set res {0 1}
  if {$err} {set res {1 {frame starting offset must be a non-negative number}} }
  do_catchsql_test 22.$tn.1 "
    WITH a(x, y) AS ( VALUES(1, 2) )
    SELECT sum(x) OVER (
      ORDER BY y RANGE BETWEEN $expr PRECEDING AND UNBOUNDED FOLLOWING
    ) FROM a
  " $res

  set res {0 1}
  if {$err} {set res {1 {frame ending offset must be a non-negative number}} }
  do_catchsql_test 22.$tn.2 "
    WITH a(x, y) AS ( VALUES(1, 2) )
    SELECT sum(x) OVER (
      ORDER BY y RANGE BETWEEN UNBOUNDED PRECEDING AND $expr FOLLOWING
    ) FROM a
  " $res
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 23.0 {
  CREATE TABLE t5(a, b, c);
  CREATE INDEX t5ab ON t5(a, b);
}

proc do_ordercount_test {tn sql nOrderBy} {
  set plan [execsql "EXPLAIN QUERY PLAN $sql"]
  uplevel [list do_test $tn [list regexp -all ORDER $plan] $nOrderBy]
}

do_ordercount_test 23.1 {
  SELECT 
    sum(c) OVER (ORDER BY a, b),
    sum(c) OVER (PARTITION BY a ORDER BY b)
  FROM t5
} 0

do_ordercount_test 23.2 {
  SELECT 
    sum(c) OVER (ORDER BY b, a),
    sum(c) OVER (PARTITION BY b ORDER BY a)
  FROM t5
} 1

do_ordercount_test 23.3 {
  SELECT 
    sum(c) OVER (ORDER BY b, a),
    sum(c) OVER (ORDER BY c, b)
  FROM t5
} 2

do_ordercount_test 23.4 {
  SELECT 
    sum(c) OVER (ORDER BY b ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW),
    sum(c) OVER (ORDER BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW),
    sum(c) OVER (ORDER BY b GROUPS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
  FROM t5
} 1

do_ordercount_test 23.5 {
  SELECT 
    sum(c) OVER (ORDER BY b+1 ROWS UNBOUNDED PRECEDING),
    sum(c) OVER (ORDER BY b+1 RANGE UNBOUNDED PRECEDING),
    sum(c) OVER (ORDER BY b+1 GROUPS UNBOUNDED PRECEDING)
  FROM t5
} 1

do_ordercount_test 23.6 {
  SELECT 
    sum(c) OVER (ORDER BY b+1 ROWS UNBOUNDED PRECEDING),
    sum(c) OVER (ORDER BY b+2 RANGE UNBOUNDED PRECEDING),
    sum(c) OVER (ORDER BY b+3 GROUPS UNBOUNDED PRECEDING)
  FROM t5
} 3

do_execsql_test 24.1 {
  SELECT sum(44) OVER ()
} {44}

do_execsql_test 24.2 {
  SELECT lead(44) OVER ()
} {{}}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 25.0 {
  CREATE TABLE t1 ( t1_id INTEGER PRIMARY KEY );
  CREATE TABLE t2 ( t2_id INTEGER PRIMARY KEY );
  CREATE TABLE t3 ( t3_id INTEGER PRIMARY KEY );

  INSERT INTO t1 VALUES(1),  (3), (5);
  INSERT INTO t2 VALUES      (3), (5);
  INSERT INTO t3 VALUES(10), (11), (12);
}

do_execsql_test 25.1 {
  SELECT t1.* FROM t1, t2 WHERE 
    t1_id=t2_id AND t1_id IN (
        SELECT t1_id + row_number() OVER ( ORDER BY t1_id ) FROM t3
    )
}

do_execsql_test 25.2 {
  SELECT t1.* FROM t1, t2 WHERE 
    t1_id=t2_id AND t1_id IN (
        SELECT         row_number() OVER ( ORDER BY t1_id ) FROM t3
    )
} {3}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 26.0 {
  CREATE TABLE t1(x);
  CREATE TABLE t2(c);
}

do_execsql_test 26.1 {
  SELECT ( SELECT row_number() OVER () FROM ( SELECT c FROM t1 ) ) FROM t2
} {}

do_execsql_test 26.2 {
  INSERT INTO t1 VALUES(1), (2), (3), (4);
  INSERT INTO t2 VALUES(2), (6), (8), (4);
  SELECT c, c IN ( 
    SELECT row_number() OVER () FROM ( SELECT c FROM t1 )
  ) FROM t2
} {2 1  6 0  8 0  4 1}

do_execsql_test 26.3 {
  DELETE FROM t1;
  DELETE FROM t2;

  INSERT INTO t2 VALUES(1), (2), (3), (4);
  INSERT INTO t1 VALUES(1), (1), (2), (3), (3), (3), (3), (4), (4);

  SELECT c, c IN ( 
    SELECT row_number() OVER () FROM ( SELECT 1 FROM t1 WHERE x=c )
  ) FROM t2
} {1 1  2 0  3 1  4 0}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 27.0 {
  CREATE TABLE t1(x);
  INSERT INTO t1 VALUES(NULL), (1), (2), (3), (4), (5);
}
do_execsql_test 27.1 {
  SELECT min(x) FROM t1;
} {1}
do_execsql_test 27.2 {
  SELECT min(x) OVER win FROM t1
  WINDOW win AS (ORDER BY rowid ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING)
} {1 1 1 2 3 4}

#-------------------------------------------------------------------------

reset_db
do_execsql_test 28.1.1 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b CHAR(1), c CHAR(2), d ANY);
  INSERT INTO t1 VALUES (3, 'C', 'cc', 1.0);
  INSERT INTO t1 VALUES (13,'M', 'cc', NULL);
}

do_execsql_test 28.1.2 {
  SELECT group_concat(b,'') OVER w1 FROM t1
    WINDOW w1 AS (ORDER BY a RANGE BETWEEN 3 PRECEDING AND 1 PRECEDING)
} {
  {} {}
}

do_execsql_test 28.2.1 {
  CREATE TABLE t2(a TEXT, b INTEGER);
  INSERT INTO t2 VALUES('A', NULL);
  INSERT INTO t2 VALUES('B', NULL);
}

do_execsql_test 28.2.1 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b CHAR(1), c CHAR(2), d ANY);
  INSERT INTO t1 VALUES
    (10,'J', 'cc', NULL),
    (11,'K', 'cc', 'xyz'),
    (13,'M', 'cc', NULL);
}

do_execsql_test 28.2.2 {
  SELECT a, b, c, quote(d), group_concat(b,'') OVER w1, '|' FROM t1
    WINDOW w1 AS
    (ORDER BY d DESC RANGE BETWEEN 7.0 PRECEDING AND 2.5 PRECEDING)
    ORDER BY c, d, a;
} {
  10 J cc NULL JM |
  13 M cc NULL JM | 
  11 K cc 'xyz' K |
}

#-------------------------------------------------------------------------
reset_db

do_execsql_test 29.1 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b CHAR(1), c CHAR(2), d ANY);
  INSERT INTO t1 VALUES
    (1, 'A', 'aa', 2.5),
    (2, 'B', 'bb', 3.75),
    (3, 'C', 'cc', 1.0),
    (4, 'D', 'cc', 8.25),
    (5, 'E', 'bb', 6.5),
    (6, 'F', 'aa', 6.5),
    (7, 'G', 'aa', 6.0),
    (8, 'H', 'bb', 9.0),
    (9, 'I', 'aa', 3.75),
    (10,'J', 'cc', NULL),
    (11,'K', 'cc', 'xyz'),
    (12,'L', 'cc', 'xyZ'),
    (13,'M', 'cc', NULL);
}

do_execsql_test 29.2 {
  SELECT a, b, c, quote(d), group_concat(b,'') OVER w1, '|' FROM t1
    WINDOW w1 AS
    (PARTITION BY c ORDER BY d DESC
     RANGE BETWEEN 7.0 PRECEDING AND 2.5 PRECEDING)
    ORDER BY c, d, a;
} {
  1 A aa 2.5 FG | 
  9 I aa 3.75 F | 
  7 G aa 6 {} | 
  6 F aa 6.5 {} | 
  2 B bb 3.75 HE |
  5 E bb 6.5 H | 
  8 H bb 9 {} | 
  10 J cc NULL JM | 
  13 M cc NULL JM | 
  3 C cc 1 {} | 
  4 D cc 8.25 {} | 
  12 L cc 'xyZ' L | 
  11 K cc 'xyz' K |
}

# 2019-07-18
# Check-in [7ef7b23cbb1b9ace] (which was itself a fix for ticket
# https://www.sqlite.org/src/info/1be72aab9) introduced a new problem
# if the LHS of a BETWEEN operator is a WINDOW function.  The problem
# was found by (the recently enhanced) dbsqlfuzz.
#
do_execsql_test 30.0 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a, b, c);
  INSERT INTO t1 VALUES('BB','aa',399);
  SELECT
    count () OVER win1 NOT BETWEEN 'a' AND 'mmm',
    count () OVER win3
  FROM t1
  WINDOW win1 AS (ORDER BY a GROUPS BETWEEN 4 PRECEDING AND 1 FOLLOWING
                  EXCLUDE CURRENT ROW),
         win2 AS (PARTITION BY b ORDER BY a),
         win3 AS (win2 RANGE BETWEEN 5.2 PRECEDING AND true PRECEDING );
} {1 1}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 31.1 {
  CREATE TABLE t1(a, b);
  CREATE TABLE t2(c, d);
  CREATE TABLE t3(e, f);

  INSERT INTO t1 VALUES(1, 1);
  INSERT INTO t2 VALUES(1, 1);
  INSERT INTO t3 VALUES(1, 1);
}

do_execsql_test 31.2 {
  SELECT d IN (SELECT sum(c) OVER (ORDER BY e+c) FROM t3) FROM (
    SELECT * FROM t2
  );
} {1}

do_execsql_test 31.3 {
  SELECT d IN (SELECT sum(c) OVER (PARTITION BY d ORDER BY e+c) FROM t3) FROM (
    SELECT * FROM t2
  );
} {1}

do_catchsql_test 31.3 {
  SELECT d IN (
    SELECT sum(c) OVER ( ROWS BETWEEN d FOLLOWING AND UNBOUNDED FOLLOWING) 
    FROM t3
  )
  FROM (
    SELECT * FROM t2
  );
} {1 {frame starting offset must be a non-negative integer}}

do_catchsql_test 31.3 {
  SELECT d IN (
    SELECT sum(c) OVER ( ROWS BETWEEN CURRENT ROW AND c FOLLOWING) 
    FROM t3
  )
  FROM (
    SELECT * FROM t2
  );
} {1 {frame ending offset must be a non-negative integer}}

# 2019-11-16 chromium issue 1025467
ifcapable altertable {
  db close
  sqlite3 db :memory:
  do_catchsql_test 32.10 {
    CREATE VIEW a AS SELECT NULL INTERSECT SELECT NULL ORDER BY s() OVER R;
    CREATE TABLE a0 AS SELECT 0;
    ALTER TABLE a0 RENAME TO S;
  } {1 {error in view a: 1st ORDER BY term does not match any column in the result set}}
}

reset_db
do_execsql_test 33.1 {
  CREATE TABLE t1(aa, bb);
  INSERT INTO t1 VALUES(1, 2);
  INSERT INTO t1 VALUES(5, 6);
  CREATE TABLE t2(x);
  INSERT INTO t2 VALUES(1);
}
do_execsql_test 33.2 {
  SELECT (SELECT DISTINCT sum(aa) OVER() FROM t1 ORDER BY 1), x FROM t2 
  ORDER BY 1;
} {6 1}

reset_db
do_execsql_test 34.1 {
  CREATE TABLE t1(a,b,c);
}
do_execsql_test 34.2 {
  SELECT avg(a) OVER (
      ORDER BY (SELECT sum(b) OVER ()
        FROM t1 ORDER BY (
          SELECT total(d) OVER (ORDER BY c)
          FROM (SELECT 1 AS d) ORDER BY 1
          )
        )
      )
  FROM t1;
}

#-------------------------------------------------------------------------
reset_db
do_catchsql_test 35.0 {
  SELECT * WINDOW f AS () ORDER BY name COLLATE nocase;
} {1 {no tables specified}}

do_catchsql_test 35.1 {
  VALUES(1) INTERSECT SELECT * WINDOW f AS () ORDER BY x COLLATE nocase;
} {1 {no tables specified}}

do_execsql_test 35.2 {
  CREATE TABLE t1(x);
  INSERT INTO t1 VALUES(1), (2), (3);
  VALUES(1) INTERSECT 
  SELECT sum(x) OVER f FROM t1 WINDOW f AS (ORDER BY x) ORDER BY 1;
} {1}

do_execsql_test 35.3 {
  VALUES(8) EXCEPT 
  SELECT sum(x) OVER f FROM t1 WINDOW f AS (ORDER BY x) ORDER BY 1;
} {8}

do_execsql_test 35.4 {
  VALUES(1) UNION 
  SELECT sum(x) OVER f FROM t1 WINDOW f AS (ORDER BY x) ORDER BY 1;
} {1 3 6}

# 2019-12-07 gramfuzz find
#
do_execsql_test 36.10 {
  VALUES(count(*)OVER());
} {1}
do_execsql_test 36.20 {
  VALUES(count(*)OVER()),(2);
} {1 2}
do_execsql_test 36.30 {
  VALUES(2),(count(*)OVER());
} {2 1}
do_execsql_test 36.40 {
  VALUES(2),(3),(count(*)OVER()),(4),(5);
} {2 3 1 4 5}

# 2019-12-17 crash test case found by Yongheng and Rui
# See check-in 1ca0bd982ab1183b
#
reset_db
do_execsql_test 37.10 {
  CREATE TABLE t0(a UNIQUE, b PRIMARY KEY);
  CREATE VIEW v0(c) AS SELECT max((SELECT count(a)OVER(ORDER BY 1))) FROM t0;
  SELECT c FROM v0 WHERE c BETWEEN 10 AND 20;
} {}
do_execsql_test 37.20 {
  DROP VIEW v0;
  CREATE VIEW v0(c) AS SELECT max((SELECT count(a)OVER(ORDER BY 1234))) FROM t0;
  SELECT c FROM v0 WHERE c BETWEEN -10 AND 20;
} {}

# 2019-12-20 mrigger reported problem with a FILTER clause on an aggregate
# in a join.
#
reset_db
do_catchsql_test 38.10 {
  CREATE TABLE t0(c0);
  CREATE TABLE t1(c0, c1 UNIQUE);
  INSERT INTO t0(c0) VALUES(1);
  INSERT INTO t1(c0,c1) VALUES(2,3);
  SELECT COUNT(*) FROM t0, t1 WHERE (SELECT AVG(0) FILTER(WHERE t1.c1));
} {1 {misuse of aggregate: AVG()}}
do_execsql_test 38.20 {
  SELECT COUNT(*), AVG(1) FILTER(WHERE t1.c1) FROM t0, t1;
} {1 1.0}
do_catchsql_test 38.30 {
  SELECT COUNT(*) FROM t0, t1 WHERE (SELECT AVG(1) FILTER(WHERE t1.c1));
} {1 {misuse of aggregate: AVG()}}

reset_db
do_execsql_test 39.1 {
  CREATE TABLE t0(c0 UNIQUE);
}
do_execsql_test 39.2 {
  SELECT FIRST_VALUE(0) OVER();
} {0}
do_execsql_test 39.3 {
  SELECT * FROM t0 WHERE(c0, 0) IN(SELECT FIRST_VALUE(0) OVER(), 0);
}
do_execsql_test 39.4 {
  SELECT * FROM t0 WHERE (t0.c0, 1) IN(SELECT NTILE(1) OVER(), 0 FROM t0);
}

ifcapable rtree {
  # 2019-12-25 ticket d87336c81c7d0873
  #
  reset_db
  do_catchsql_test 40.1 {
    CREATE VIRTUAL TABLE t0 USING rtree(c0, c1, c2);
    SELECT * FROM t0
     WHERE ((0,0) IN (SELECT COUNT(*),LAG(5)OVER(PARTITION BY 0) FROM t0),0)<=(c1,0);
  } {0 {}}
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 41.1 {
  CREATE TABLE t1(a, b, c);
  INSERT INTO t1 VALUES(NULL,'bb',355);
  INSERT INTO t1 VALUES('CC','aa',158);
  INSERT INTO t1 VALUES('GG','bb',929);
  INSERT INTO t1 VALUES('FF','Rb',574);
}

do_execsql_test 41.2 {
  SELECT min(c) OVER (
    ORDER BY a RANGE BETWEEN 5.2 PRECEDING AND 0.1 PRECEDING
  ) FROM t1
} {355 158 574 929}

do_execsql_test 41.2 {
  SELECT min(c) OVER (
    ORDER BY a RANGE BETWEEN 5.2 PRECEDING AND 0.1 PRECEDING
  ) << 100 FROM t1
} {0 0 0 0}

do_execsql_test 41.3 {
  SELECT
    min(c) OVER win3 << first_value(c) OVER win3,
    min(c) OVER win3 << first_value(c) OVER win3
  FROM t1
  WINDOW win3 AS (
    PARTITION BY 6 ORDER BY a RANGE BETWEEN 5.2 PRECEDING AND 0.1 PRECEDING
  );
} {0 0  0 0  0 0  0 0}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 42.1 {
  CREATE TABLE t1(a, b, c);
  INSERT INTO t1 VALUES(1, 1, 1);
  INSERT INTO t1 VALUES(2, 2, 2);
}
do_execsql_test 42.2 {
  SELECT * FROM t1 WHERE (0, 0) IN ( SELECT count(*), 0 FROM t1 )
} {}
do_execsql_test 42.3 {
  SELECT * FROM t1 WHERE (2, 0) IN ( SELECT count(*), 0 FROM t1 )
} {1 1 1 2 2 2}

do_execsql_test 42.3 {
  SELECT count(*), max(a) OVER () FROM t1 GROUP BY c; 
} {1 2 1 2}

do_execsql_test 42.4 {
  SELECT sum(a), max(b) OVER () FROM t1;
} {3 1}

do_execsql_test 42.5 {
  CREATE TABLE t2(a, b);
  INSERT INTO t2 VALUES('a', 1);
  INSERT INTO t2 VALUES('a', 2);
  INSERT INTO t2 VALUES('a', 3);
  INSERT INTO t2 VALUES('b', 4);
  INSERT INTO t2 VALUES('b', 5);
  INSERT INTO t2 VALUES('b', 6);
}

do_execsql_test 42.6 {
  SELECT a, sum(b), sum( sum(b) ) OVER (ORDER BY a) FROM t2 GROUP BY a;
} {a 6 6   b 15 21}

do_execsql_test 42.7 {
  SELECT sum(b), sum( sum(b) ) OVER (ORDER BY a) FROM t2;
} {21 21}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 43.1.1 {
  CREATE TABLE t1(x INTEGER PRIMARY KEY);
  INSERT INTO t1 VALUES (10);
}
do_catchsql_test 43.1.2 {
  SELECT count() OVER() AS m FROM t1 ORDER BY (SELECT m);
} {1 {misuse of aliased window function m}}

reset_db
do_execsql_test 43.2.1 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b INTEGER);
  INSERT INTO t1(a, b) VALUES(1,  10); -- 10
  INSERT INTO t1(a, b) VALUES(2,  15); -- 25
  INSERT INTO t1(a, b) VALUES(3,  -5); -- 20
  INSERT INTO t1(a, b) VALUES(4,  -5); -- 15
  INSERT INTO t1(a, b) VALUES(5,  20); -- 35
  INSERT INTO t1(a, b) VALUES(6, -11); -- 24
}

do_execsql_test 43.2.2 {
  SELECT a, sum(b) OVER (ORDER BY a) AS abc FROM t1 ORDER BY 2
} {
  1 10   4 15   3 20   6 24   2 25   5 35
}

do_execsql_test 43.2.3 {
  SELECT a, sum(b) OVER (ORDER BY a) AS abc FROM t1 ORDER BY abc
} {
  1 10   4 15   3 20   6 24   2 25   5 35
}

do_execsql_test 43.2.4 {
  SELECT a, sum(b) OVER (ORDER BY a) AS abc FROM t1 ORDER BY abc+5
} {
  1 10   4 15   3 20   6 24   2 25   5 35
}

do_catchsql_test 43.2.5 {
  SELECT a, sum(b) OVER (ORDER BY a) AS abc FROM t1 ORDER BY (SELECT abc)
} {1 {misuse of aliased window function abc}}

do_catchsql_test 43.2.6 {
  SELECT a, 1+sum(b) OVER (ORDER BY a) AS abc FROM t1 ORDER BY (SELECT abc)
} {1 {misuse of aliased window function abc}}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 44.1 {
  CREATE TABLE t0(c0);
}

do_catchsql_test 44.2.1 {
  SELECT ntile(0) OVER ();
} {1 {argument of ntile must be a positive integer}}
do_catchsql_test 44.2.2 {
  SELECT (0, 0) IN(SELECT MIN(c0), NTILE(0) OVER()) FROM t0;
} {1 {argument of ntile must be a positive integer}}

do_execsql_test 44.3.1 {
  SELECT ntile(1) OVER ();
} {1}
do_execsql_test 44.3.2 {
  SELECT (0, 0) IN(SELECT MIN(c0), NTILE(1) OVER()) FROM t0;
} {0}

do_execsql_test 44.4.2 {
  INSERT INTO t0 VALUES(2), (1), (0);
  SELECT (0, 1) IN(SELECT MIN(c0), NTILE(1) OVER()) FROM t0;
} {1}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 45.1 {
  CREATE TABLE t0(x);
  CREATE TABLE t1(a);
  INSERT INTO t1 VALUES(1000);
  INSERT INTO t1 VALUES(1000);
  INSERT INTO t0 VALUES(10000);
}
do_execsql_test 45.2 {
  SELECT * FROM (
      SELECT sum (a) OVER() FROM t1 UNION ALL SELECT x FROM t0
  );
} {2000 2000 10000}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 46.1 {
  CREATE TABLE t1 (a);
  CREATE INDEX i1 ON t1(a);

  INSERT INTO t1 VALUES (10);
}

do_execsql_test 46.2 {
  SELECT (SELECT sum(a) OVER(ORDER BY a)) FROM t1
} 10

do_execsql_test 46.3 {
  SELECT * FROM t1 WHERE (SELECT sum(a) OVER(ORDER BY a));
} 10

do_execsql_test 46.4 {
  SELECT * FROM t1 NATURAL JOIN t1
    WHERE a=1
    OR ((SELECT sum(a)OVER(ORDER BY a)) AND a<=10)
} 10

#-------------------------------------------------------------------------
reset_db
do_execsql_test 47.0 {
  CREATE TABLE t1(
      a,
      e,
      f,
      g UNIQUE,
      h UNIQUE
  );
}

do_execsql_test 47.1 {
  CREATE VIEW t2(k) AS
     SELECT e FROM t1 WHERE g = 'abc' OR h BETWEEN 10 AND f;
}

do_catchsql_test 47.2 {
  SELECT 234 FROM t2
    WHERE k=1
    OR (SELECT k FROM t2 WHERE (SELECT sum(a) OVER() FROM t1 GROUP BY 1));
} {1 {misuse of window function sum()}}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 48.0 {
  CREATE TABLE t1(a);
  INSERT INTO t1 VALUES(1);
  INSERT INTO t1 VALUES(2);
  INSERT INTO t1 VALUES(3);
  SELECT (SELECT max(x)OVER(ORDER BY x) + min(x)OVER(ORDER BY x))
    FROM (SELECT (SELECT sum(a) FROM t1) AS x FROM t1);
} {12 12 12}

do_execsql_test 48.1 {
  SELECT (SELECT max(x)OVER(ORDER BY x) + min(x)OVER(ORDER BY x))
    FROM (SELECT (SELECT sum(a) FROM t1 GROUP BY a) AS x FROM t1);
} {2 2 2}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 49.1 {
  CREATE TABLE t1 (a PRIMARY KEY);
  INSERT INTO t1 VALUES(1);
}

do_execsql_test 49.2 {
  SELECT b AS c FROM (
    SELECT a AS b FROM (
      SELECT a FROM t1 WHERE a=1 OR (SELECT sum(a) OVER ())
    ) 
    WHERE b=1 OR b<10
  ) 
  WHERE c=1 OR c>=10;
} {1}


#-------------------------------------------------------------------------
reset_db
do_execsql_test 50.0 {
  CREATE TABLE t1 (a DOUBLE PRIMARY KEY);
  INSERT INTO t1 VALUES(10.0);
}

do_execsql_test 50.1 {
  SELECT * FROM t1 WHERE a%1 OR (SELECT sum(a) OVER (ORDER BY a%2))
} {10.0}

do_execsql_test 50.2 {
  SELECT * FROM (
    SELECT * FROM t1 WHERE a%1 OR (SELECT sum(a) OVER (ORDER BY a%2))
  ) 
  WHERE a=1 OR ( (SELECT sum(a) OVER (ORDER BY a%4)) AND a<=10 )
} {10.0}

do_execsql_test 50.3 {
  SELECT a FROM (
    SELECT * FROM (
      SELECT * FROM t1 WHERE a%1 OR (SELECT sum(a) OVER (ORDER BY a%2))
    ) 
    WHERE a=1 OR ( (SELECT sum(a) OVER (ORDER BY a%4)) AND a<=10 )
  ) 
  WHERE a=1 OR a=10.0
} {10.0}

do_execsql_test 50.4 {
  SELECT a FROM (
    SELECT * FROM (
      SELECT * FROM t1 WHERE a%1 OR (SELECT sum(a) OVER (ORDER BY a%2))
    ) 
    WHERE a=1 OR ( (SELECT sum(a) OVER (ORDER BY a%4)) AND a<=10 )
  ) 
  WHERE a=1 OR ((SELECT sum(a) OVER(ORDER BY a%8)) AND 10<=a)
} {10.0}

do_execsql_test 50.5 {
SELECT * FROM (SELECT * FROM t1 NATURAL JOIN t1 WHERE a%1 OR ((SELECT sum(a)OVER(ORDER BY a)) AND a<=10)) NATURAL JOIN t1 WHERE a=1 OR ((SELECT sum((SELECT * FROM (SELECT * FROM (SELECT * FROM t1 NATURAL JOIN t1 WHERE a%1 OR ((SELECT sum(a)OVER(ORDER BY a)) AND a<=10)) NATURAL JOIN t1 WHERE a=1 OR ((SELECT sum((SELECT * FROM t1 NATURAL JOIN t1 WHERE a=1 OR ((SELECT sum(a)OVER(ORDER BY a)) AND a<=10)))OVER(ORDER BY a% 1 )) AND a<=10)) NATURAL JOIN t1 WHERE a=1 OR ((SELECT sum(a)OVER(ORDER BY a)) AND 10<=a)))OVER(ORDER BY a%5)) AND a<=10);
} {10.0}

# 2020-04-03 ticket af4556bb5c285c08
#
reset_db
do_catchsql_test 51.1 {
  CREATE TABLE a(b, c);
  SELECT c FROM a GROUP BY c
    HAVING(SELECT(sum(b) OVER(ORDER BY b),
                  sum(b) OVER(PARTITION BY min(DISTINCT c), c ORDER BY b)));
} {1 {row value misused}}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 52.1 {
  CREATE TABLE t1(a, b, c);
  INSERT INTO t1 VALUES('AA','bb',356);
  INSERT INTO t1 VALUES('CC','aa',158);
  INSERT INTO t1 VALUES('BB','aa',399);
  INSERT INTO t1 VALUES('FF','bb',938);
}

do_execsql_test 52.2 {
  SELECT
    count() OVER win1,
    sum(c) OVER win2, 
    first_value(c) OVER win2,
    count(a) OVER (ORDER BY b)
      FROM t1
      WINDOW
      win1 AS (ORDER BY a),
    win2 AS (PARTITION BY 6 ORDER BY a
        RANGE BETWEEN 5 PRECEDING AND 0 PRECEDING );
} {
  1 356 356 4 
  2 399 399 2 
  3 158 158 2 
  4 938 938 4
}

do_execsql_test 52.3 {
SELECT
  count() OVER (),
  sum(c) OVER win2, 
  first_value(c) OVER win2,
  count(a) OVER (ORDER BY b)
FROM t1
WINDOW
  win1 AS (ORDER BY a),
  win2 AS (PARTITION BY 6 COLLATE binary ORDER BY a
           RANGE BETWEEN 5 PRECEDING AND 0 PRECEDING );
} {
  4 356 356 4 
  4 399 399 2 
  4 158 158 2 
  4 938 938 4
}

do_execsql_test 52.4 {
  SELECT
    count() OVER win1,
    sum(c) OVER win2, 
    first_value(c) OVER win2,
    count(a) OVER (ORDER BY b)
  FROM t1
  WINDOW
    win1 AS (ORDER BY a),
    win2 AS (PARTITION BY 6 COLLATE binary ORDER BY a
             RANGE BETWEEN 5 PRECEDING AND 0 PRECEDING );
} {
  1 356 356 4 
  2 399 399 2 
  3 158 158 2 
  4 938 938 4
}

# 2020-05-23
# ticket 7a5279a25c57adf1
#
reset_db
do_execsql_test 53.0 {
  CREATE TABLE a(c UNIQUE);
  INSERT INTO a VALUES(4),(0),(9),(-9);
  SELECT a.c
    FROM a
    JOIN a AS b ON a.c=4
    JOIN a AS e ON a.c=e.c
   WHERE a.c=(SELECT (SELECT coalesce(lead(2) OVER(),0) + sum(d.c))
                FROM a AS d
               WHERE a.c);
} {4 4 4 4}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 54.1 {
  CREATE TABLE t1(a VARCHAR(20), b FLOAT);
  INSERT INTO t1 VALUES('1',10.0);
}

do_catchsql_test 54.2 {
  SELECT * FROM ( 
    SELECT sum(b) OVER() AS c FROM t1 
      UNION
    SELECT b AS c FROM t1
  ) WHERE c>10;
} {0 {}}

do_execsql_test 54.3 {
  INSERT INTO t1 VALUES('2',5.0);
  INSERT INTO t1 VALUES('3',15.0);
}

do_catchsql_test 54.4 {
  SELECT * FROM ( 
    SELECT sum(b) OVER() AS c FROM t1 
      UNION
    SELECT b AS c FROM t1
  ) WHERE c>10;
} {0 {15.0 30.0}}

# 2020-06-05 ticket c8d3b9f0a750a529
reset_db
do_execsql_test 55.1 {
   CREATE TABLE a(b);
   SELECT
      (SELECT b FROM a
        GROUP BY b
        HAVING (SELECT COUNT()OVER() + lead(b)OVER(ORDER BY SUM(DISTINCT b) + b))
      ) 
    FROM a
  UNION
   SELECT 99
    ORDER BY 1;
} {99}

#------------------------------------------------------------------------
reset_db
do_execsql_test 56.1 {
  CREATE TABLE t1(a, b INTEGER); 
  CREATE TABLE t2(c, d); 
}
do_catchsql_test 56.2 {
  SELECT avg(b) FROM t1 
    UNION ALL 
  SELECT min(c) OVER () FROM t2 
  ORDER BY nosuchcolumn;
} {1 {1st ORDER BY term does not match any column in the result set}}

reset_db
do_execsql_test 57.1 {
  CREATE TABLE t4(a, b, c, d, e);
}

do_catchsql_test 57.2  {
  SELECT b FROM t4
  UNION
  SELECT a FROM t4
  ORDER BY (
    SELECT sum(x) OVER() FROM (
      SELECT c AS x FROM t4
      UNION
      SELECT d FROM t4
      ORDER BY (SELECT e FROM t4)
    )
  );
} {1 {1st ORDER BY term does not match any column in the result set}}

# 2020-06-06 various dbsqlfuzz finds and
# ticket 0899cf62f597d7e7
#
reset_db
do_execsql_test 57.1 {
  CREATE TABLE t1(a, b, c);
  INSERT INTO t1 VALUES(NULL,NULL,NULL);
  SELECT 
    sum(a),
    min(b) OVER (),
    count(c) OVER (ORDER BY b)
  FROM t1;
} {{} {} 0}
do_execsql_test 57.2 {
  CREATE TABLE v0 ( v1 INTEGER PRIMARY KEY ) ; 
  INSERT INTO v0 VALUES ( 10 ) ; 
  SELECT DISTINCT v1, lead(v1) OVER() FROM v0 GROUP BY v1 ORDER BY 2;
} {10 {}}
do_catchsql_test 57.3 {
  DROP TABLE t1;
  CREATE TABLE t1(a);
  INSERT INTO t1(a) VALUES(22);
  CREATE TABLE t3(y);
  INSERT INTO t3(y) VALUES(5),(11),(-9);
  SELECT (
    SELECT max(y) OVER( ORDER BY (SELECT x FROM (SELECT sum(y) AS x FROM t1)))
  )
  FROM t3;
} {1 {misuse of aggregate: sum()}}

# 2020-06-06 ticket 1f6f353b684fc708
reset_db
do_execsql_test 58.1 {
  CREATE TABLE a(a, b, c);
  INSERT INTO a VALUES(1, 2, 3);
  INSERT INTO a VALUES(4, 5, 6);
  SELECT sum(345+b)      OVER (ORDER BY b),
         sum(avg(678)) OVER (ORDER BY c) FROM a;
} {347 678.0}

# 2020-06-06 ticket e5504e987e419fb0
do_catchsql_test 59.1 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(x INTEGER PRIMARY KEY);
  INSERT INTO t1 VALUES (123);
  SELECT
     ntile( (SELECT sum(x)) ) OVER(ORDER BY x),
     min(x) OVER(ORDER BY x)
    FROM t1; 
} {1 {misuse of aggregate: sum()}}

# 2020-06-07 ticket f7d890858f361402
do_execsql_test 60.1 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1 (x INTEGER PRIMARY KEY);
  INSERT INTO t1 VALUES (99);
  SELECT EXISTS(SELECT count(*) OVER() FROM t1 ORDER BY sum(x) OVER());
} {1}

# 2020-06-07 test case generated by dbsqlfuzz showing how an AggInfo
# object might be referenced after the sqlite3Select() call that created
# it returns.  This proves the need to persist all AggInfo objects until
# the Parse object is destroyed.
#
reset_db
do_catchsql_test 61.1 {
CREATE TABLE t1(a);
INSERT INTO t1 VALUES(5),(NULL),('seventeen');
SELECT (SELECT max(x)OVER(ORDER BY x) % min(x)OVER(ORDER BY CASE x WHEN 889 THEN x WHEN x THEN x END)) FROM (SELECT (SELECT sum(CAST(a IN(SELECT (SELECT max(x)OVER(ORDER BY CASE x WHEN 889 THEN 299 WHEN 863 THEN 863 END)) FROM (SELECT (SELECT sum(CAST((SELECT (SELECT max(x)OVER(ORDER BY x) / min(x)OVER(ORDER BY CASE x WHEN 889 THEN 299 WHEN -true THEN 863 END)) FROM (SELECT (SELECT sum(CAST(a IN(SELECT (SELECT max(x) & sum ( a )OVER(ORDER BY CASE x WHEN -8 THEN 299 WHEN 863 THEN 863 END)) FROM (SELECT (SELECT sum(CAST(a AS )) FROM t1) AS x FROM t1)) AS t1 )) FROM t1) AS x FROM t1)) AS x )) FROM t1) AS x FROM t1)) AS real)) FROM t1) AS x FROM t1);
} {0 {{} {} {}}}

foreach tn {1 2} {
  if {$tn==2} { optimization_control db query-flattener 0 }
  do_catchsql_test 61.2.$tn {
    SELECT 
      (SELECT max(x)OVER(ORDER BY x) / min(x) OVER() ) 
    FROM (
      SELECT (SELECT sum(a) FROM t1 ) AS x FROM t1
    )

  } {0 {1.0 1.0 1.0}}
}

reset_db
optimization_control db all 0 
do_execsql_test 61.3.0 {
  CREATE TABLE t1(a);
  CREATE TABLE t2(y);
}

do_execsql_test 61.3.1 {
  SELECT (
    SELECT count(a) OVER ( ORDER BY (SELECT sum(y) FROM t2) )
         + total(a) OVER() 
  )
  FROM t1
} {}
do_execsql_test 61.4.2 {
  SELECT (
    SELECT count(a) OVER ( ORDER BY sum(a) )
         + total(a) OVER() 
  )
  FROM t1
} {0.0}

do_catchsql_test 61.4.3 {
  SELECT 
    sum(a) OVER ( ORDER BY a ) 
  FROM t1 
  ORDER BY (SELECT sum(a) FROM t2)
} {1 {misuse of aggregate: sum()}}
do_execsql_test 61.4.4 {
  SELECT 
    sum(a) OVER ( ORDER BY a ) 
  FROM t1 
  ORDER BY (SELECT sum(y) FROM t2)
} 


#-------------------------------------------------------------------------
reset_db
do_execsql_test 62.1 {
  CREATE TABLE t1(a VARCHAR(20), b FLOAT);
  INSERT INTO t1 VALUES('1',10.0);
}

do_execsql_test 62.2 {
  SELECT * FROM ( 
      SELECT sum(b) OVER() AS c FROM t1 
      UNION
      SELECT b AS c FROM t1
      ) WHERE c>10;
}

do_execsql_test 62.3 {
  INSERT INTO t1 VALUES('2',5.0);
  INSERT INTO t1 VALUES('3',15.0);
}

do_execsql_test 62.4 {
  SELECT * FROM ( 
      SELECT sum(b) OVER() AS c FROM t1 
      UNION
      SELECT b AS c FROM t1
      ) WHERE c>10;
} {15.0 30.0}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 63.1 {
  CREATE TABLE t1(b, x);
  CREATE TABLE t2(c, d);
  CREATE TABLE t3(e, f);
}

do_execsql_test 63.2 {
  SELECT max(b) OVER(
      ORDER BY SUM(
        (SELECT c FROM t2 UNION SELECT x ORDER BY c)
      )
  ) FROM t1;
} {{}}

do_execsql_test 63.3 {
  SELECT sum(b) over(
      ORDER BY (
        SELECT max(b) OVER(
          ORDER BY sum(
            (SELECT x AS c UNION SELECT 1234 ORDER BY c)
          )
        ) AS e
        ORDER BY e
      )
    )
  FROM t1;
} {{}}

#-------------------------------------------------------------------------
reset_db 
do_execsql_test 64.1 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
  INSERT INTO t1 VALUES(1, 'abcd');
  INSERT INTO t1 VALUES(2, 'BCDE');
  INSERT INTO t1 VALUES(3, 'cdef');
  INSERT INTO t1 VALUES(4, 'DEFG');
}

do_execsql_test 64.2 {
  SELECT rowid, max(b COLLATE nocase)||'' 
  FROM t1 
  GROUP BY rowid
  ORDER BY max(b COLLATE nocase)||'';
} {1 abcd 2 BCDE 3 cdef 4 DEFG}

do_execsql_test 64.3 {
  SELECT count() OVER (), rowid, max(b COLLATE nocase)||'' 
  FROM t1 
  GROUP BY rowid
  ORDER BY max(b COLLATE nocase)||'';
} {4 1 abcd   4 2 BCDE   4 3 cdef   4 4 DEFG}

do_execsql_test 64.4 {
  SELECT count() OVER (), rowid, max(b COLLATE nocase)
  FROM t1 
  GROUP BY rowid
  ORDER BY max(b COLLATE nocase);
} {4 1 abcd   4 2 BCDE   4 3 cdef   4 4 DEFG}

#-------------------------------------------------------------------------
reset_db 
do_execsql_test 65.1 {
  CREATE TABLE t1(c1);
  INSERT INTO t1 VALUES('abcd');
}
do_execsql_test 65.2 {
  SELECT max(c1 COLLATE nocase) IN (SELECT 'aBCd') FROM t1;
} {1}

do_execsql_test 65.3 {
  SELECT 
     count() OVER (), 
     group_concat(c1 COLLATE nocase) IN (SELECT 'aBCd') FROM t1;
} {1 1}

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 {no such table: v1}}

do_catchsql_test 67.2 {
  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 t2)) )
  )
} {1 {1st ORDER BY term does not match any column in the result set}}

# 2021-05-07
# Do not allow aggregate functions in the ORDER BY clause even if
# there are window functions in the result set.
# Forum: /forumpost/540fdfef77
#
reset_db
do_catchsql_test 68.0 {
  CREATE TABLE t1(a,b);
  INSERT INTO t1(a,b) VALUES(0,0),(1,1),(2,4),(3,9),(4,99);
  SELECT rowid, a, b, sum(a)OVER() FROM t1 ORDER BY count(b);
} {1 {misuse of aggregate: count()}}

# 2021-05-22
# Forum https://sqlite.org/forum/forumpost/7e484e225c
#
reset_db
do_catchsql_test 69.0 {
  CREATE TABLE t1(a,b);
  CREATE INDEX t1ba ON t1(b,a);
  SELECT * FROM t1 WHERE b = (SELECT b FROM t1 ORDER BY lead(b) OVER () AND sum(a));
} {1 {misuse of aggregate: sum()}}
do_catchsql_test 69.1 {
  SELECT * FROM t1 WHERE b >= (SELECT b FROM t1 ORDER BY lead(b) OVER () AND sum(a));
} {1 {misuse of aggregate: sum()}}
do_catchsql_test 69.2 {
  SELECT * FROM t1 WHERE b <= (SELECT b FROM t1 ORDER BY lead(b) OVER () AND sum(a));
} {1 {misuse of aggregate: sum()}}

# 2021-06-23
# Forum https://sqlite.org/forum/forumpost/31e0432608
#
reset_db
do_execsql_test 70.0 {
  CREATE TABLE t1(a);
}
do_execsql_test 70.1 {
  SELECT substr(a,4,lag(a,7) OVER(PARTITION BY 'cf23' ORDER BY 2)) AS ca0 FROM t1 ORDER BY ca0;
}
do_execsql_test 70.2 {
  SELECT substr(a,4,lag(a,7) OVER(PARTITION BY 'cf23' ORDER BY likely(2))) AS ca0 FROM t1 ORDER BY ca0;
}

# 2021-11-07
# Bug report from Wang Ke
# https://sqlite.org/forum/forumpost/9ba4f60ff8
reset_db
do_catchsql_test 71.0 {
  CREATE TABLE t0(a);
  SELECT a FROM t0, (SELECT a AS b FROM t0)
   WHERE (a,1)=(SELECT 2,2 UNION SELECT sum(b),max(b) OVER(ORDER BY b) ORDER BY 2)
     AND b=4
   ORDER BY b;
} {/1 {.*}/}

do_execsql_test 72.1 {
  CREATE TABLE dual(dummy);  INSERT INTO dual VALUES('X');
  CREATE VIEW v1(x,y) AS SELECT RANK() OVER (PARTITION BY 0), SUM(0) FROM dual;
  SELECT * FROM v1 WHERE true;
} {1 0}

finish_test

Changes to test/window2.tcl.

413
414
415
416
417
418
419





420


































































421
422
423
424
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







+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




execsql_test 4.8.4 {
  SELECT b, sum(b) OVER (
    ORDER BY a
    ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
  ) FROM t2 ORDER BY 1, 2;
}

execsql_float_test 4.9 {
  SELECT 
    rank() OVER win AS rank,
    cume_dist() OVER win AS cume_dist FROM t1
  WINDOW win AS (ORDER BY 1);

}

execsql_test 4.10 {
  SELECT count(*) OVER (ORDER BY b) FROM t1
}

execsql_test 4.11 {
  SELECT count(distinct a) FILTER (WHERE b='odd') FROM t1
}

==========

execsql_test 5.0 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(x INTEGER, y INTEGER);
  INSERT INTO t1 VALUES(10, 1);
  INSERT INTO t1 VALUES(20, 2);
  INSERT INTO t1 VALUES(3, 3);
  INSERT INTO t1 VALUES(2, 4);
  INSERT INTO t1 VALUES(1, 5);
}

execsql_float_test 5.1 {
  SELECT avg(x) OVER (ORDER BY y) AS z FROM t1 ORDER BY z;
}

==========

execsql_test 6.0 {
  DROP TABLE IF EXISTS t0;
  CREATE TABLE t0(c0 INTEGER UNIQUE);
  INSERT INTO t0 VALUES(0);
}
execsql_test 6.1 {
  SELECT DENSE_RANK() OVER(), LAG(0) OVER() FROM t0;
}
execsql_test 6.2 {
  SELECT * FROM t0 WHERE 
      (0, t0.c0) IN (SELECT DENSE_RANK() OVER(), LAG(0) OVER() FROM t0);
} 

==========

execsql_test 7.0 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a INTEGER, b INTEGER, c INTEGER);
  INSERT INTO t1 VALUES(1, 1, 1);
  INSERT INTO t1 VALUES(1, 2, 2);
  INSERT INTO t1 VALUES(3, 3, 3);
  INSERT INTO t1 VALUES(3, 4, 4);
}

execsql_test 7.1 {
  SELECT c, sum(c) OVER win1 FROM t1 
  WINDOW win1 AS (ORDER BY b)
}

execsql_test 7.2 {
  SELECT c, sum(c) OVER win1 FROM t1 
  WINDOW win1 AS (PARTITION BY 1 ORDER BY b)
}

execsql_test 7.3 {
  SELECT c, sum(c) OVER win1 FROM t1 
  WINDOW win1 AS (ORDER BY 1)
}

finish_test


Changes to test/window2.test.

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
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
638
639
640
641
642
643
644
645
646
647
648
649
650

651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683

684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717

718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750

751
752
753
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976







-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


} {}

do_execsql_test 4.1 {
  SELECT a, sum(b) OVER (
    PARTITION BY (b%10)
    ORDER BY b
  ) FROM t2 ORDER BY a;
} {1 0   2 754   3 251   4 754   5 101   6 1247   7 132   8 266   9 6   10 950   11 667   12 1052   13 535   14 128   15 428   16 250   17 336   18 1122   19 368   20 6   21 1247   22 1000   23 92   24 368   25 584   26 320   27 1000   28 24   29 478   30 133   31 1049   32 1090   33 632   34 101   35 54   36 54   37 1049   38 450   39 145   40 354   41 21   42 764   43 754   44 424   45 1122   46 930   47 42   48 930   49 352   50 535   51 42   52 118   53 536   54 6   55 1122   56 86   57 770   58 255   59 50   60 52   61 950   62 75   63 354   64 2   65 536   66 160   67 352   68 536   69 54   70 675   71 276   72 950   73 868   74 678   75 667   76 4   77 1184   78 160   79 120   80 584   81 266   82 133   83 405   84 468   85 6   86 806   87 166   88 500   89 1090   90 552   91 251   92 27   93 424   94 687   95 1215   96 450   97 32   98 360   99 1052   100 868   101 2   102 66   103 754   104 450   105 145   106 5   107 687   108 24   109 302   110 806   111 251   112 42   113 24   114 30   115 128   116 128   117 50   118 1215   119 86   120 687   121 683   122 672   123 178   124 24   125 24   126 299   127 178   128 770   129 535   130 1052   131 270   132 255   133 675   134 632   135 266   136 6   137 21   138 930   139 411   140 754   141 133   142 340   143 535   144 46   145 250   146 132   147 132   148 354   149 500   150 770   151 276   152 360   153 354   154 27   155 552   156 552   157 602   158 266   159 1049   160 675   161 384   162 667   163 27   164 101   165 166   166 32   167 42   168 18   169 336   170 1122   171 276   172 1122   173 266   174 50   175 178   176 276   177 1247   178 6   179 1215   180 604   181 360   182 212   183 120   184 210   185 1090   186 10   187 1090   188 266   189 66   190 250   191 266   192 360   193 120   194 128   195 178   196 770   197 92   198 634   199 38   200 21}
} {1 0   2 754   3 251   4 754   5 101   6 1247   7 132   8 266   9 6   10 950
  11 667   12 1052   13 535   14 128   15 428   16 250   17 336   18 1122
  19 368   20 6   21 1247   22 1000   23 92   24 368   25 584   26 320
  27 1000   28 24   29 478   30 133   31 1049   32 1090   33 632   34 101
  35 54   36 54   37 1049   38 450   39 145   40 354   41 21   42 764
  43 754   44 424   45 1122   46 930   47 42   48 930   49 352   50 535
  51 42   52 118   53 536   54 6   55 1122   56 86   57 770   58 255   59 50
  60 52   61 950   62 75   63 354   64 2   65 536   66 160   67 352   68 536
  69 54   70 675   71 276   72 950   73 868   74 678   75 667   76 4
  77 1184   78 160   79 120   80 584   81 266   82 133   83 405   84 468
  85 6   86 806   87 166   88 500   89 1090   90 552   91 251   92 27
  93 424   94 687   95 1215   96 450   97 32   98 360   99 1052   100 868
  101 2   102 66   103 754   104 450   105 145   106 5   107 687   108 24
  109 302   110 806   111 251   112 42   113 24   114 30   115 128   116 128
  117 50   118 1215   119 86   120 687   121 683   122 672   123 178   124 24
  125 24   126 299   127 178   128 770   129 535   130 1052   131 270
  132 255   133 675   134 632   135 266   136 6   137 21   138 930   139 411
  140 754   141 133   142 340   143 535   144 46   145 250   146 132
  147 132   148 354   149 500   150 770   151 276   152 360   153 354
  154 27   155 552   156 552   157 602   158 266   159 1049   160 675
  161 384   162 667   163 27   164 101   165 166   166 32   167 42   168 18
  169 336   170 1122   171 276   172 1122   173 266   174 50   175 178
  176 276   177 1247   178 6   179 1215   180 604   181 360   182 212
  183 120   184 210   185 1090   186 10   187 1090   188 266   189 66
  190 250   191 266   192 360   193 120   194 128   195 178   196 770
  197 92   198 634   199 38   200 21}

do_execsql_test 4.2 {
  SELECT a, sum(b) OVER (
    PARTITION BY (b%10)
    ORDER BY b
    RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
  ) FROM t2 ORDER BY a;
} {1 0   2 754   3 251   4 754   5 101   6 1247   7 132   8 266   9 6   10 950   11 667   12 1052   13 535   14 128   15 428   16 250   17 336   18 1122   19 368   20 6   21 1247   22 1000   23 92   24 368   25 584   26 320   27 1000   28 24   29 478   30 133   31 1049   32 1090   33 632   34 101   35 54   36 54   37 1049   38 450   39 145   40 354   41 21   42 764   43 754   44 424   45 1122   46 930   47 42   48 930   49 352   50 535   51 42   52 118   53 536   54 6   55 1122   56 86   57 770   58 255   59 50   60 52   61 950   62 75   63 354   64 2   65 536   66 160   67 352   68 536   69 54   70 675   71 276   72 950   73 868   74 678   75 667   76 4   77 1184   78 160   79 120   80 584   81 266   82 133   83 405   84 468   85 6   86 806   87 166   88 500   89 1090   90 552   91 251   92 27   93 424   94 687   95 1215   96 450   97 32   98 360   99 1052   100 868   101 2   102 66   103 754   104 450   105 145   106 5   107 687   108 24   109 302   110 806   111 251   112 42   113 24   114 30   115 128   116 128   117 50   118 1215   119 86   120 687   121 683   122 672   123 178   124 24   125 24   126 299   127 178   128 770   129 535   130 1052   131 270   132 255   133 675   134 632   135 266   136 6   137 21   138 930   139 411   140 754   141 133   142 340   143 535   144 46   145 250   146 132   147 132   148 354   149 500   150 770   151 276   152 360   153 354   154 27   155 552   156 552   157 602   158 266   159 1049   160 675   161 384   162 667   163 27   164 101   165 166   166 32   167 42   168 18   169 336   170 1122   171 276   172 1122   173 266   174 50   175 178   176 276   177 1247   178 6   179 1215   180 604   181 360   182 212   183 120   184 210   185 1090   186 10   187 1090   188 266   189 66   190 250   191 266   192 360   193 120   194 128   195 178   196 770   197 92   198 634   199 38   200 21}
} {1 0   2 754   3 251   4 754   5 101   6 1247   7 132   8 266   9 6   10 950
  11 667   12 1052   13 535   14 128   15 428   16 250   17 336   18 1122
  19 368   20 6   21 1247   22 1000   23 92   24 368   25 584   26 320
  27 1000   28 24   29 478   30 133   31 1049   32 1090   33 632   34 101
  35 54   36 54   37 1049   38 450   39 145   40 354   41 21   42 764
  43 754   44 424   45 1122   46 930   47 42   48 930   49 352   50 535
  51 42   52 118   53 536   54 6   55 1122   56 86   57 770   58 255   59 50
  60 52   61 950   62 75   63 354   64 2   65 536   66 160   67 352   68 536
  69 54   70 675   71 276   72 950   73 868   74 678   75 667   76 4
  77 1184   78 160   79 120   80 584   81 266   82 133   83 405   84 468
  85 6   86 806   87 166   88 500   89 1090   90 552   91 251   92 27
  93 424   94 687   95 1215   96 450   97 32   98 360   99 1052   100 868
  101 2   102 66   103 754   104 450   105 145   106 5   107 687   108 24
  109 302   110 806   111 251   112 42   113 24   114 30   115 128   116 128
  117 50   118 1215   119 86   120 687   121 683   122 672   123 178   124 24
  125 24   126 299   127 178   128 770   129 535   130 1052   131 270
  132 255   133 675   134 632   135 266   136 6   137 21   138 930   139 411
  140 754   141 133   142 340   143 535   144 46   145 250   146 132
  147 132   148 354   149 500   150 770   151 276   152 360   153 354
  154 27   155 552   156 552   157 602   158 266   159 1049   160 675
  161 384   162 667   163 27   164 101   165 166   166 32   167 42   168 18
  169 336   170 1122   171 276   172 1122   173 266   174 50   175 178
  176 276   177 1247   178 6   179 1215   180 604   181 360   182 212
  183 120   184 210   185 1090   186 10   187 1090   188 266   189 66
  190 250   191 266   192 360   193 120   194 128   195 178   196 770
  197 92   198 634   199 38   200 21}

do_execsql_test 4.3 {
  SELECT b, sum(b) OVER (
    ORDER BY b
    ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
  ) FROM t2 ORDER BY b;
} {0 0   1 1   1 2   2 4   2 6   2 8   3 11   3 14   4 18   5 23   6 29   7 36   7 43   7 50   8 58   8 66   8 74   9 83   9 92   9 101   10 111   11 122   11 133   12 145   12 157   12 169   13 182   13 195   14 209   15 224   15 239   15 254   16 270   16 286   16 302   17 319   19 338   20 358   21 379   21 400   22 422   22 444   23 467   23 490   23 513   24 537   25 562   26 588   26 614   26 640   27 667   27 694   28 722   29 751   29 780   29 809   30 839   30 869   30 899   31 930   31 961   32 993   33 1026   33 1059   33 1092   33 1125   33 1158   34 1192   34 1226   34 1260   34 1294   35 1329   35 1364   36 1400   36 1436   36 1472   36 1508   37 1545   37 1582   38 1620   38 1658   39 1697   39 1736   39 1775   40 1815   41 1856   41 1897   41 1938   42 1980   43 2023   43 2066   44 2110   44 2154   46 2200   46 2246   47 2293   47 2340   47 2387   47 2434   49 2483   50 2533   51 2584   52 2636   53 2689   54 2743   55 2798   55 2853   56 2909   56 2965   56 3021   57 3078   58 3136   58 3194   58 3252   58 3310   59 3369   59 3428   59 3487   59 3546   60 3606   61 3667   61 3728   62 3790   62 3852   63 3915   64 3979   65 4044   65 4109   65 4174   66 4240   67 4307   68 4375   69 4444   70 4514   72 4586   72 4658   72 4730   73 4803   73 4876   73 4949   74 5023   74 5097   74 5171   74 5245   74 5319   75 5394   75 5469   75 5544   76 5620   77 5697   77 5774   78 5852   78 5930   79 6009   80 6089   80 6169   81 6250   81 6331   81 6412   82 6494   83 6577   84 6661   84 6745   84 6829   84 6913   85 6998   85 7083   85 7168   86 7254   87 7341   87 7428   88 7516   89 7605   89 7694   89 7783   90 7873   90 7963   90 8053   91 8144   91 8235   91 8326   91 8417   91 8508   93 8601   93 8694   93 8787   94 8881   95 8976   95 9071   95 9166   96 9262   96 9358   96 9454   97 9551   97 9648   98 9746   98 9844   99 9943   99 10042   99 10141}
} {0 0   1 1   1 2   2 4   2 6   2 8   3 11   3 14   4 18   5 23   6 29   7 36
  7 43   7 50   8 58   8 66   8 74   9 83   9 92   9 101   10 111   11 122
  11 133   12 145   12 157   12 169   13 182   13 195   14 209   15 224
  15 239   15 254   16 270   16 286   16 302   17 319   19 338   20 358
  21 379   21 400   22 422   22 444   23 467   23 490   23 513   24 537
  25 562   26 588   26 614   26 640   27 667   27 694   28 722   29 751
  29 780   29 809   30 839   30 869   30 899   31 930   31 961   32 993
  33 1026   33 1059   33 1092   33 1125   33 1158   34 1192   34 1226
  34 1260   34 1294   35 1329   35 1364   36 1400   36 1436   36 1472
  36 1508   37 1545   37 1582   38 1620   38 1658   39 1697   39 1736
  39 1775   40 1815   41 1856   41 1897   41 1938   42 1980   43 2023
  43 2066   44 2110   44 2154   46 2200   46 2246   47 2293   47 2340
  47 2387   47 2434   49 2483   50 2533   51 2584   52 2636   53 2689
  54 2743   55 2798   55 2853   56 2909   56 2965   56 3021   57 3078
  58 3136   58 3194   58 3252   58 3310   59 3369   59 3428   59 3487
  59 3546   60 3606   61 3667   61 3728   62 3790   62 3852   63 3915
  64 3979   65 4044   65 4109   65 4174   66 4240   67 4307   68 4375
  69 4444   70 4514   72 4586   72 4658   72 4730   73 4803   73 4876
  73 4949   74 5023   74 5097   74 5171   74 5245   74 5319   75 5394
  75 5469   75 5544   76 5620   77 5697   77 5774   78 5852   78 5930
  79 6009   80 6089   80 6169   81 6250   81 6331   81 6412   82 6494
  83 6577   84 6661   84 6745   84 6829   84 6913   85 6998   85 7083
  85 7168   86 7254   87 7341   87 7428   88 7516   89 7605   89 7694
  89 7783   90 7873   90 7963   90 8053   91 8144   91 8235   91 8326
  91 8417   91 8508   93 8601   93 8694   93 8787   94 8881   95 8976
  95 9071   95 9166   96 9262   96 9358   96 9454   97 9551   97 9648
  98 9746   98 9844   99 9943   99 10042   99 10141}

do_execsql_test 4.4 {
  SELECT b, sum(b) OVER (
    ORDER BY b
    RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
  ) FROM t2 ORDER BY b;
} {0 10141   1 10141   1 10141   2 10141   2 10141   2 10141   3 10141   3 10141   4 10141   5 10141   6 10141   7 10141   7 10141   7 10141   8 10141   8 10141   8 10141   9 10141   9 10141   9 10141   10 10141   11 10141   11 10141   12 10141   12 10141   12 10141   13 10141   13 10141   14 10141   15 10141   15 10141   15 10141   16 10141   16 10141   16 10141   17 10141   19 10141   20 10141   21 10141   21 10141   22 10141   22 10141   23 10141   23 10141   23 10141   24 10141   25 10141   26 10141   26 10141   26 10141   27 10141   27 10141   28 10141   29 10141   29 10141   29 10141   30 10141   30 10141   30 10141   31 10141   31 10141   32 10141   33 10141   33 10141   33 10141   33 10141   33 10141   34 10141   34 10141   34 10141   34 10141   35 10141   35 10141   36 10141   36 10141   36 10141   36 10141   37 10141   37 10141   38 10141   38 10141   39 10141   39 10141   39 10141   40 10141   41 10141   41 10141   41 10141   42 10141   43 10141   43 10141   44 10141   44 10141   46 10141   46 10141   47 10141   47 10141   47 10141   47 10141   49 10141   50 10141   51 10141   52 10141   53 10141   54 10141   55 10141   55 10141   56 10141   56 10141   56 10141   57 10141   58 10141   58 10141   58 10141   58 10141   59 10141   59 10141   59 10141   59 10141   60 10141   61 10141   61 10141   62 10141   62 10141   63 10141   64 10141   65 10141   65 10141   65 10141   66 10141   67 10141   68 10141   69 10141   70 10141   72 10141   72 10141   72 10141   73 10141   73 10141   73 10141   74 10141   74 10141   74 10141   74 10141   74 10141   75 10141   75 10141   75 10141   76 10141   77 10141   77 10141   78 10141   78 10141   79 10141   80 10141   80 10141   81 10141   81 10141   81 10141   82 10141   83 10141   84 10141   84 10141   84 10141   84 10141   85 10141   85 10141   85 10141   86 10141   87 10141   87 10141   88 10141   89 10141   89 10141   89 10141   90 10141   90 10141   90 10141   91 10141   91 10141   91 10141   91 10141   91 10141   93 10141   93 10141   93 10141   94 10141   95 10141   95 10141   95 10141   96 10141   96 10141   96 10141   97 10141   97 10141   98 10141   98 10141   99 10141   99 10141   99 10141}
} {0 10141   1 10141   1 10141   2 10141   2 10141   2 10141   3 10141
  3 10141   4 10141   5 10141   6 10141   7 10141   7 10141   7 10141
  8 10141   8 10141   8 10141   9 10141   9 10141   9 10141   10 10141
  11 10141   11 10141   12 10141   12 10141   12 10141   13 10141   13 10141
  14 10141   15 10141   15 10141   15 10141   16 10141   16 10141   16 10141
  17 10141   19 10141   20 10141   21 10141   21 10141   22 10141   22 10141
  23 10141   23 10141   23 10141   24 10141   25 10141   26 10141   26 10141
  26 10141   27 10141   27 10141   28 10141   29 10141   29 10141   29 10141
  30 10141   30 10141   30 10141   31 10141   31 10141   32 10141   33 10141
  33 10141   33 10141   33 10141   33 10141   34 10141   34 10141   34 10141
  34 10141   35 10141   35 10141   36 10141   36 10141   36 10141   36 10141
  37 10141   37 10141   38 10141   38 10141   39 10141   39 10141   39 10141
  40 10141   41 10141   41 10141   41 10141   42 10141   43 10141   43 10141
  44 10141   44 10141   46 10141   46 10141   47 10141   47 10141   47 10141
  47 10141   49 10141   50 10141   51 10141   52 10141   53 10141   54 10141
  55 10141   55 10141   56 10141   56 10141   56 10141   57 10141   58 10141
  58 10141   58 10141   58 10141   59 10141   59 10141   59 10141   59 10141
  60 10141   61 10141   61 10141   62 10141   62 10141   63 10141   64 10141
  65 10141   65 10141   65 10141   66 10141   67 10141   68 10141   69 10141
  70 10141   72 10141   72 10141   72 10141   73 10141   73 10141   73 10141
  74 10141   74 10141   74 10141   74 10141   74 10141   75 10141   75 10141
  75 10141   76 10141   77 10141   77 10141   78 10141   78 10141   79 10141
  80 10141   80 10141   81 10141   81 10141   81 10141   82 10141   83 10141
  84 10141   84 10141   84 10141   84 10141   85 10141   85 10141   85 10141
  86 10141   87 10141   87 10141   88 10141   89 10141   89 10141   89 10141
  90 10141   90 10141   90 10141   91 10141   91 10141   91 10141   91 10141
  91 10141   93 10141   93 10141   93 10141   94 10141   95 10141   95 10141
  95 10141   96 10141   96 10141   96 10141   97 10141   97 10141   98 10141
  98 10141   99 10141   99 10141   99 10141}

do_execsql_test 4.5 {
  SELECT b, sum(b) OVER (
    ORDER BY b
    RANGE BETWEEN CURRENT ROW AND CURRENT ROW
  ) FROM t2 ORDER BY b;
} {0 0   1 2   1 2   2 6   2 6   2 6   3 6   3 6   4 4   5 5   6 6   7 21   7 21   7 21   8 24   8 24   8 24   9 27   9 27   9 27   10 10   11 22   11 22   12 36   12 36   12 36   13 26   13 26   14 14   15 45   15 45   15 45   16 48   16 48   16 48   17 17   19 19   20 20   21 42   21 42   22 44   22 44   23 69   23 69   23 69   24 24   25 25   26 78   26 78   26 78   27 54   27 54   28 28   29 87   29 87   29 87   30 90   30 90   30 90   31 62   31 62   32 32   33 165   33 165   33 165   33 165   33 165   34 136   34 136   34 136   34 136   35 70   35 70   36 144   36 144   36 144   36 144   37 74   37 74   38 76   38 76   39 117   39 117   39 117   40 40   41 123   41 123   41 123   42 42   43 86   43 86   44 88   44 88   46 92   46 92   47 188   47 188   47 188   47 188   49 49   50 50   51 51   52 52   53 53   54 54   55 110   55 110   56 168   56 168   56 168   57 57   58 232   58 232   58 232   58 232   59 236   59 236   59 236   59 236   60 60   61 122   61 122   62 124   62 124   63 63   64 64   65 195   65 195   65 195   66 66   67 67   68 68   69 69   70 70   72 216   72 216   72 216   73 219   73 219   73 219   74 370   74 370   74 370   74 370   74 370   75 225   75 225   75 225   76 76   77 154   77 154   78 156   78 156   79 79   80 160   80 160   81 243   81 243   81 243   82 82   83 83   84 336   84 336   84 336   84 336   85 255   85 255   85 255   86 86   87 174   87 174   88 88   89 267   89 267   89 267   90 270   90 270   90 270   91 455   91 455   91 455   91 455   91 455   93 279   93 279   93 279   94 94   95 285   95 285   95 285   96 288   96 288   96 288   97 194   97 194   98 196   98 196   99 297   99 297   99 297}
} {0 0   1 2   1 2   2 6   2 6   2 6   3 6   3 6   4 4   5 5   6 6   7 21
  7 21   7 21   8 24   8 24   8 24   9 27   9 27   9 27   10 10   11 22
  11 22   12 36   12 36   12 36   13 26   13 26   14 14   15 45   15 45
  15 45   16 48   16 48   16 48   17 17   19 19   20 20   21 42   21 42
  22 44   22 44   23 69   23 69   23 69   24 24   25 25   26 78   26 78
  26 78   27 54   27 54   28 28   29 87   29 87   29 87   30 90   30 90
  30 90   31 62   31 62   32 32   33 165   33 165   33 165   33 165   33 165
  34 136   34 136   34 136   34 136   35 70   35 70   36 144   36 144
  36 144   36 144   37 74   37 74   38 76   38 76   39 117   39 117   39 117
  40 40   41 123   41 123   41 123   42 42   43 86   43 86   44 88   44 88
  46 92   46 92   47 188   47 188   47 188   47 188   49 49   50 50   51 51
  52 52   53 53   54 54   55 110   55 110   56 168   56 168   56 168   57 57
  58 232   58 232   58 232   58 232   59 236   59 236   59 236   59 236
  60 60   61 122   61 122   62 124   62 124   63 63   64 64   65 195   65 195
  65 195   66 66   67 67   68 68   69 69   70 70   72 216   72 216   72 216
  73 219   73 219   73 219   74 370   74 370   74 370   74 370   74 370
  75 225   75 225   75 225   76 76   77 154   77 154   78 156   78 156
  79 79   80 160   80 160   81 243   81 243   81 243   82 82   83 83   84 336
  84 336   84 336   84 336   85 255   85 255   85 255   86 86   87 174
  87 174   88 88   89 267   89 267   89 267   90 270   90 270   90 270
  91 455   91 455   91 455   91 455   91 455   93 279   93 279   93 279
  94 94   95 285   95 285   95 285   96 288   96 288   96 288   97 194
  97 194   98 196   98 196   99 297   99 297   99 297}

do_execsql_test 4.6.1 {
  SELECT b, sum(b) OVER (
    RANGE BETWEEN CURRENT ROW AND CURRENT ROW
  ) FROM t2 ORDER BY b;
} {0 10141   1 10141   1 10141   2 10141   2 10141   2 10141   3 10141   3 10141   4 10141   5 10141   6 10141   7 10141   7 10141   7 10141   8 10141   8 10141   8 10141   9 10141   9 10141   9 10141   10 10141   11 10141   11 10141   12 10141   12 10141   12 10141   13 10141   13 10141   14 10141   15 10141   15 10141   15 10141   16 10141   16 10141   16 10141   17 10141   19 10141   20 10141   21 10141   21 10141   22 10141   22 10141   23 10141   23 10141   23 10141   24 10141   25 10141   26 10141   26 10141   26 10141   27 10141   27 10141   28 10141   29 10141   29 10141   29 10141   30 10141   30 10141   30 10141   31 10141   31 10141   32 10141   33 10141   33 10141   33 10141   33 10141   33 10141   34 10141   34 10141   34 10141   34 10141   35 10141   35 10141   36 10141   36 10141   36 10141   36 10141   37 10141   37 10141   38 10141   38 10141   39 10141   39 10141   39 10141   40 10141   41 10141   41 10141   41 10141   42 10141   43 10141   43 10141   44 10141   44 10141   46 10141   46 10141   47 10141   47 10141   47 10141   47 10141   49 10141   50 10141   51 10141   52 10141   53 10141   54 10141   55 10141   55 10141   56 10141   56 10141   56 10141   57 10141   58 10141   58 10141   58 10141   58 10141   59 10141   59 10141   59 10141   59 10141   60 10141   61 10141   61 10141   62 10141   62 10141   63 10141   64 10141   65 10141   65 10141   65 10141   66 10141   67 10141   68 10141   69 10141   70 10141   72 10141   72 10141   72 10141   73 10141   73 10141   73 10141   74 10141   74 10141   74 10141   74 10141   74 10141   75 10141   75 10141   75 10141   76 10141   77 10141   77 10141   78 10141   78 10141   79 10141   80 10141   80 10141   81 10141   81 10141   81 10141   82 10141   83 10141   84 10141   84 10141   84 10141   84 10141   85 10141   85 10141   85 10141   86 10141   87 10141   87 10141   88 10141   89 10141   89 10141   89 10141   90 10141   90 10141   90 10141   91 10141   91 10141   91 10141   91 10141   91 10141   93 10141   93 10141   93 10141   94 10141   95 10141   95 10141   95 10141   96 10141   96 10141   96 10141   97 10141   97 10141   98 10141   98 10141   99 10141   99 10141   99 10141}
} {0 10141   1 10141   1 10141   2 10141   2 10141   2 10141   3 10141
  3 10141   4 10141   5 10141   6 10141   7 10141   7 10141   7 10141
  8 10141   8 10141   8 10141   9 10141   9 10141   9 10141   10 10141
  11 10141   11 10141   12 10141   12 10141   12 10141   13 10141   13 10141
  14 10141   15 10141   15 10141   15 10141   16 10141   16 10141   16 10141
  17 10141   19 10141   20 10141   21 10141   21 10141   22 10141   22 10141
  23 10141   23 10141   23 10141   24 10141   25 10141   26 10141   26 10141
  26 10141   27 10141   27 10141   28 10141   29 10141   29 10141   29 10141
  30 10141   30 10141   30 10141   31 10141   31 10141   32 10141   33 10141
  33 10141   33 10141   33 10141   33 10141   34 10141   34 10141   34 10141
  34 10141   35 10141   35 10141   36 10141   36 10141   36 10141   36 10141
  37 10141   37 10141   38 10141   38 10141   39 10141   39 10141   39 10141
  40 10141   41 10141   41 10141   41 10141   42 10141   43 10141   43 10141
  44 10141   44 10141   46 10141   46 10141   47 10141   47 10141   47 10141
  47 10141   49 10141   50 10141   51 10141   52 10141   53 10141   54 10141
  55 10141   55 10141   56 10141   56 10141   56 10141   57 10141   58 10141
  58 10141   58 10141   58 10141   59 10141   59 10141   59 10141   59 10141
  60 10141   61 10141   61 10141   62 10141   62 10141   63 10141   64 10141
  65 10141   65 10141   65 10141   66 10141   67 10141   68 10141   69 10141
  70 10141   72 10141   72 10141   72 10141   73 10141   73 10141   73 10141
  74 10141   74 10141   74 10141   74 10141   74 10141   75 10141   75 10141
  75 10141   76 10141   77 10141   77 10141   78 10141   78 10141   79 10141
  80 10141   80 10141   81 10141   81 10141   81 10141   82 10141   83 10141
  84 10141   84 10141   84 10141   84 10141   85 10141   85 10141   85 10141
  86 10141   87 10141   87 10141   88 10141   89 10141   89 10141   89 10141
  90 10141   90 10141   90 10141   91 10141   91 10141   91 10141   91 10141
  91 10141   93 10141   93 10141   93 10141   94 10141   95 10141   95 10141
  95 10141   96 10141   96 10141   96 10141   97 10141   97 10141   98 10141
  98 10141   99 10141   99 10141   99 10141}

do_execsql_test 4.6.2 {
  SELECT b, sum(b) OVER () FROM t2 ORDER BY b;
} {0 10141   1 10141   1 10141   2 10141   2 10141   2 10141   3 10141   3 10141   4 10141   5 10141   6 10141   7 10141   7 10141   7 10141   8 10141   8 10141   8 10141   9 10141   9 10141   9 10141   10 10141   11 10141   11 10141   12 10141   12 10141   12 10141   13 10141   13 10141   14 10141   15 10141   15 10141   15 10141   16 10141   16 10141   16 10141   17 10141   19 10141   20 10141   21 10141   21 10141   22 10141   22 10141   23 10141   23 10141   23 10141   24 10141   25 10141   26 10141   26 10141   26 10141   27 10141   27 10141   28 10141   29 10141   29 10141   29 10141   30 10141   30 10141   30 10141   31 10141   31 10141   32 10141   33 10141   33 10141   33 10141   33 10141   33 10141   34 10141   34 10141   34 10141   34 10141   35 10141   35 10141   36 10141   36 10141   36 10141   36 10141   37 10141   37 10141   38 10141   38 10141   39 10141   39 10141   39 10141   40 10141   41 10141   41 10141   41 10141   42 10141   43 10141   43 10141   44 10141   44 10141   46 10141   46 10141   47 10141   47 10141   47 10141   47 10141   49 10141   50 10141   51 10141   52 10141   53 10141   54 10141   55 10141   55 10141   56 10141   56 10141   56 10141   57 10141   58 10141   58 10141   58 10141   58 10141   59 10141   59 10141   59 10141   59 10141   60 10141   61 10141   61 10141   62 10141   62 10141   63 10141   64 10141   65 10141   65 10141   65 10141   66 10141   67 10141   68 10141   69 10141   70 10141   72 10141   72 10141   72 10141   73 10141   73 10141   73 10141   74 10141   74 10141   74 10141   74 10141   74 10141   75 10141   75 10141   75 10141   76 10141   77 10141   77 10141   78 10141   78 10141   79 10141   80 10141   80 10141   81 10141   81 10141   81 10141   82 10141   83 10141   84 10141   84 10141   84 10141   84 10141   85 10141   85 10141   85 10141   86 10141   87 10141   87 10141   88 10141   89 10141   89 10141   89 10141   90 10141   90 10141   90 10141   91 10141   91 10141   91 10141   91 10141   91 10141   93 10141   93 10141   93 10141   94 10141   95 10141   95 10141   95 10141   96 10141   96 10141   96 10141   97 10141   97 10141   98 10141   98 10141   99 10141   99 10141   99 10141}
} {0 10141   1 10141   1 10141   2 10141   2 10141   2 10141   3 10141
  3 10141   4 10141   5 10141   6 10141   7 10141   7 10141   7 10141
  8 10141   8 10141   8 10141   9 10141   9 10141   9 10141   10 10141
  11 10141   11 10141   12 10141   12 10141   12 10141   13 10141   13 10141
  14 10141   15 10141   15 10141   15 10141   16 10141   16 10141   16 10141
  17 10141   19 10141   20 10141   21 10141   21 10141   22 10141   22 10141
  23 10141   23 10141   23 10141   24 10141   25 10141   26 10141   26 10141
  26 10141   27 10141   27 10141   28 10141   29 10141   29 10141   29 10141
  30 10141   30 10141   30 10141   31 10141   31 10141   32 10141   33 10141
  33 10141   33 10141   33 10141   33 10141   34 10141   34 10141   34 10141
  34 10141   35 10141   35 10141   36 10141   36 10141   36 10141   36 10141
  37 10141   37 10141   38 10141   38 10141   39 10141   39 10141   39 10141
  40 10141   41 10141   41 10141   41 10141   42 10141   43 10141   43 10141
  44 10141   44 10141   46 10141   46 10141   47 10141   47 10141   47 10141
  47 10141   49 10141   50 10141   51 10141   52 10141   53 10141   54 10141
  55 10141   55 10141   56 10141   56 10141   56 10141   57 10141   58 10141
  58 10141   58 10141   58 10141   59 10141   59 10141   59 10141   59 10141
  60 10141   61 10141   61 10141   62 10141   62 10141   63 10141   64 10141
  65 10141   65 10141   65 10141   66 10141   67 10141   68 10141   69 10141
  70 10141   72 10141   72 10141   72 10141   73 10141   73 10141   73 10141
  74 10141   74 10141   74 10141   74 10141   74 10141   75 10141   75 10141
  75 10141   76 10141   77 10141   77 10141   78 10141   78 10141   79 10141
  80 10141   80 10141   81 10141   81 10141   81 10141   82 10141   83 10141
  84 10141   84 10141   84 10141   84 10141   85 10141   85 10141   85 10141
  86 10141   87 10141   87 10141   88 10141   89 10141   89 10141   89 10141
  90 10141   90 10141   90 10141   91 10141   91 10141   91 10141   91 10141
  91 10141   93 10141   93 10141   93 10141   94 10141   95 10141   95 10141
  95 10141   96 10141   96 10141   96 10141   97 10141   97 10141   98 10141
  98 10141   99 10141   99 10141   99 10141}

do_execsql_test 4.6.3 {
  SELECT b, sum(b) OVER (
    RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
  ) FROM t2 ORDER BY b;
} {0 10141   1 10141   1 10141   2 10141   2 10141   2 10141   3 10141   3 10141   4 10141   5 10141   6 10141   7 10141   7 10141   7 10141   8 10141   8 10141   8 10141   9 10141   9 10141   9 10141   10 10141   11 10141   11 10141   12 10141   12 10141   12 10141   13 10141   13 10141   14 10141   15 10141   15 10141   15 10141   16 10141   16 10141   16 10141   17 10141   19 10141   20 10141   21 10141   21 10141   22 10141   22 10141   23 10141   23 10141   23 10141   24 10141   25 10141   26 10141   26 10141   26 10141   27 10141   27 10141   28 10141   29 10141   29 10141   29 10141   30 10141   30 10141   30 10141   31 10141   31 10141   32 10141   33 10141   33 10141   33 10141   33 10141   33 10141   34 10141   34 10141   34 10141   34 10141   35 10141   35 10141   36 10141   36 10141   36 10141   36 10141   37 10141   37 10141   38 10141   38 10141   39 10141   39 10141   39 10141   40 10141   41 10141   41 10141   41 10141   42 10141   43 10141   43 10141   44 10141   44 10141   46 10141   46 10141   47 10141   47 10141   47 10141   47 10141   49 10141   50 10141   51 10141   52 10141   53 10141   54 10141   55 10141   55 10141   56 10141   56 10141   56 10141   57 10141   58 10141   58 10141   58 10141   58 10141   59 10141   59 10141   59 10141   59 10141   60 10141   61 10141   61 10141   62 10141   62 10141   63 10141   64 10141   65 10141   65 10141   65 10141   66 10141   67 10141   68 10141   69 10141   70 10141   72 10141   72 10141   72 10141   73 10141   73 10141   73 10141   74 10141   74 10141   74 10141   74 10141   74 10141   75 10141   75 10141   75 10141   76 10141   77 10141   77 10141   78 10141   78 10141   79 10141   80 10141   80 10141   81 10141   81 10141   81 10141   82 10141   83 10141   84 10141   84 10141   84 10141   84 10141   85 10141   85 10141   85 10141   86 10141   87 10141   87 10141   88 10141   89 10141   89 10141   89 10141   90 10141   90 10141   90 10141   91 10141   91 10141   91 10141   91 10141   91 10141   93 10141   93 10141   93 10141   94 10141   95 10141   95 10141   95 10141   96 10141   96 10141   96 10141   97 10141   97 10141   98 10141   98 10141   99 10141   99 10141   99 10141}
} {0 10141   1 10141   1 10141   2 10141   2 10141   2 10141   3 10141
  3 10141   4 10141   5 10141   6 10141   7 10141   7 10141   7 10141
  8 10141   8 10141   8 10141   9 10141   9 10141   9 10141   10 10141
  11 10141   11 10141   12 10141   12 10141   12 10141   13 10141   13 10141
  14 10141   15 10141   15 10141   15 10141   16 10141   16 10141   16 10141
  17 10141   19 10141   20 10141   21 10141   21 10141   22 10141   22 10141
  23 10141   23 10141   23 10141   24 10141   25 10141   26 10141   26 10141
  26 10141   27 10141   27 10141   28 10141   29 10141   29 10141   29 10141
  30 10141   30 10141   30 10141   31 10141   31 10141   32 10141   33 10141
  33 10141   33 10141   33 10141   33 10141   34 10141   34 10141   34 10141
  34 10141   35 10141   35 10141   36 10141   36 10141   36 10141   36 10141
  37 10141   37 10141   38 10141   38 10141   39 10141   39 10141   39 10141
  40 10141   41 10141   41 10141   41 10141   42 10141   43 10141   43 10141
  44 10141   44 10141   46 10141   46 10141   47 10141   47 10141   47 10141
  47 10141   49 10141   50 10141   51 10141   52 10141   53 10141   54 10141
  55 10141   55 10141   56 10141   56 10141   56 10141   57 10141   58 10141
  58 10141   58 10141   58 10141   59 10141   59 10141   59 10141   59 10141
  60 10141   61 10141   61 10141   62 10141   62 10141   63 10141   64 10141
  65 10141   65 10141   65 10141   66 10141   67 10141   68 10141   69 10141
  70 10141   72 10141   72 10141   72 10141   73 10141   73 10141   73 10141
  74 10141   74 10141   74 10141   74 10141   74 10141   75 10141   75 10141
  75 10141   76 10141   77 10141   77 10141   78 10141   78 10141   79 10141
  80 10141   80 10141   81 10141   81 10141   81 10141   82 10141   83 10141
  84 10141   84 10141   84 10141   84 10141   85 10141   85 10141   85 10141
  86 10141   87 10141   87 10141   88 10141   89 10141   89 10141   89 10141
  90 10141   90 10141   90 10141   91 10141   91 10141   91 10141   91 10141
  91 10141   93 10141   93 10141   93 10141   94 10141   95 10141   95 10141
  95 10141   96 10141   96 10141   96 10141   97 10141   97 10141   98 10141
  98 10141   99 10141   99 10141   99 10141}

do_execsql_test 4.6.4 {
  SELECT b, sum(b) OVER (
    RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
  ) FROM t2 ORDER BY b;
} {0 10141   1 10141   1 10141   2 10141   2 10141   2 10141   3 10141   3 10141   4 10141   5 10141   6 10141   7 10141   7 10141   7 10141   8 10141   8 10141   8 10141   9 10141   9 10141   9 10141   10 10141   11 10141   11 10141   12 10141   12 10141   12 10141   13 10141   13 10141   14 10141   15 10141   15 10141   15 10141   16 10141   16 10141   16 10141   17 10141   19 10141   20 10141   21 10141   21 10141   22 10141   22 10141   23 10141   23 10141   23 10141   24 10141   25 10141   26 10141   26 10141   26 10141   27 10141   27 10141   28 10141   29 10141   29 10141   29 10141   30 10141   30 10141   30 10141   31 10141   31 10141   32 10141   33 10141   33 10141   33 10141   33 10141   33 10141   34 10141   34 10141   34 10141   34 10141   35 10141   35 10141   36 10141   36 10141   36 10141   36 10141   37 10141   37 10141   38 10141   38 10141   39 10141   39 10141   39 10141   40 10141   41 10141   41 10141   41 10141   42 10141   43 10141   43 10141   44 10141   44 10141   46 10141   46 10141   47 10141   47 10141   47 10141   47 10141   49 10141   50 10141   51 10141   52 10141   53 10141   54 10141   55 10141   55 10141   56 10141   56 10141   56 10141   57 10141   58 10141   58 10141   58 10141   58 10141   59 10141   59 10141   59 10141   59 10141   60 10141   61 10141   61 10141   62 10141   62 10141   63 10141   64 10141   65 10141   65 10141   65 10141   66 10141   67 10141   68 10141   69 10141   70 10141   72 10141   72 10141   72 10141   73 10141   73 10141   73 10141   74 10141   74 10141   74 10141   74 10141   74 10141   75 10141   75 10141   75 10141   76 10141   77 10141   77 10141   78 10141   78 10141   79 10141   80 10141   80 10141   81 10141   81 10141   81 10141   82 10141   83 10141   84 10141   84 10141   84 10141   84 10141   85 10141   85 10141   85 10141   86 10141   87 10141   87 10141   88 10141   89 10141   89 10141   89 10141   90 10141   90 10141   90 10141   91 10141   91 10141   91 10141   91 10141   91 10141   93 10141   93 10141   93 10141   94 10141   95 10141   95 10141   95 10141   96 10141   96 10141   96 10141   97 10141   97 10141   98 10141   98 10141   99 10141   99 10141   99 10141}
} {0 10141   1 10141   1 10141   2 10141   2 10141   2 10141   3 10141
  3 10141   4 10141   5 10141   6 10141   7 10141   7 10141   7 10141
  8 10141   8 10141   8 10141   9 10141   9 10141   9 10141   10 10141
  11 10141   11 10141   12 10141   12 10141   12 10141   13 10141   13 10141
  14 10141   15 10141   15 10141   15 10141   16 10141   16 10141   16 10141
  17 10141   19 10141   20 10141   21 10141   21 10141   22 10141   22 10141
  23 10141   23 10141   23 10141   24 10141   25 10141   26 10141   26 10141
  26 10141   27 10141   27 10141   28 10141   29 10141   29 10141   29 10141
  30 10141   30 10141   30 10141   31 10141   31 10141   32 10141   33 10141
  33 10141   33 10141   33 10141   33 10141   34 10141   34 10141   34 10141
  34 10141   35 10141   35 10141   36 10141   36 10141   36 10141   36 10141
  37 10141   37 10141   38 10141   38 10141   39 10141   39 10141   39 10141
  40 10141   41 10141   41 10141   41 10141   42 10141   43 10141   43 10141
  44 10141   44 10141   46 10141   46 10141   47 10141   47 10141   47 10141
  47 10141   49 10141   50 10141   51 10141   52 10141   53 10141   54 10141
  55 10141   55 10141   56 10141   56 10141   56 10141   57 10141   58 10141
  58 10141   58 10141   58 10141   59 10141   59 10141   59 10141   59 10141
  60 10141   61 10141   61 10141   62 10141   62 10141   63 10141   64 10141
  65 10141   65 10141   65 10141   66 10141   67 10141   68 10141   69 10141
  70 10141   72 10141   72 10141   72 10141   73 10141   73 10141   73 10141
  74 10141   74 10141   74 10141   74 10141   74 10141   75 10141   75 10141
  75 10141   76 10141   77 10141   77 10141   78 10141   78 10141   79 10141
  80 10141   80 10141   81 10141   81 10141   81 10141   82 10141   83 10141
  84 10141   84 10141   84 10141   84 10141   85 10141   85 10141   85 10141
  86 10141   87 10141   87 10141   88 10141   89 10141   89 10141   89 10141
  90 10141   90 10141   90 10141   91 10141   91 10141   91 10141   91 10141
  91 10141   93 10141   93 10141   93 10141   94 10141   95 10141   95 10141
  95 10141   96 10141   96 10141   96 10141   97 10141   97 10141   98 10141
  98 10141   99 10141   99 10141   99 10141}

do_execsql_test 4.7.1 {
  SELECT b, sum(b) OVER (
    ROWS BETWEEN CURRENT ROW AND CURRENT ROW
  ) FROM t2 ORDER BY 1, 2;
} {0 0   1 1   1 1   2 2   2 2   2 2   3 3   3 3   4 4   5 5   6 6   7 7   7 7   7 7   8 8   8 8   8 8   9 9   9 9   9 9   10 10   11 11   11 11   12 12   12 12   12 12   13 13   13 13   14 14   15 15   15 15   15 15   16 16   16 16   16 16   17 17   19 19   20 20   21 21   21 21   22 22   22 22   23 23   23 23   23 23   24 24   25 25   26 26   26 26   26 26   27 27   27 27   28 28   29 29   29 29   29 29   30 30   30 30   30 30   31 31   31 31   32 32   33 33   33 33   33 33   33 33   33 33   34 34   34 34   34 34   34 34   35 35   35 35   36 36   36 36   36 36   36 36   37 37   37 37   38 38   38 38   39 39   39 39   39 39   40 40   41 41   41 41   41 41   42 42   43 43   43 43   44 44   44 44   46 46   46 46   47 47   47 47   47 47   47 47   49 49   50 50   51 51   52 52   53 53   54 54   55 55   55 55   56 56   56 56   56 56   57 57   58 58   58 58   58 58   58 58   59 59   59 59   59 59   59 59   60 60   61 61   61 61   62 62   62 62   63 63   64 64   65 65   65 65   65 65   66 66   67 67   68 68   69 69   70 70   72 72   72 72   72 72   73 73   73 73   73 73   74 74   74 74   74 74   74 74   74 74   75 75   75 75   75 75   76 76   77 77   77 77   78 78   78 78   79 79   80 80   80 80   81 81   81 81   81 81   82 82   83 83   84 84   84 84   84 84   84 84   85 85   85 85   85 85   86 86   87 87   87 87   88 88   89 89   89 89   89 89   90 90   90 90   90 90   91 91   91 91   91 91   91 91   91 91   93 93   93 93   93 93   94 94   95 95   95 95   95 95   96 96   96 96   96 96   97 97   97 97   98 98   98 98   99 99   99 99   99 99}
} {0 0   1 1   1 1   2 2   2 2   2 2   3 3   3 3   4 4   5 5   6 6   7 7   7 7
  7 7   8 8   8 8   8 8   9 9   9 9   9 9   10 10   11 11   11 11   12 12
  12 12   12 12   13 13   13 13   14 14   15 15   15 15   15 15   16 16
  16 16   16 16   17 17   19 19   20 20   21 21   21 21   22 22   22 22
  23 23   23 23   23 23   24 24   25 25   26 26   26 26   26 26   27 27
  27 27   28 28   29 29   29 29   29 29   30 30   30 30   30 30   31 31
  31 31   32 32   33 33   33 33   33 33   33 33   33 33   34 34   34 34
  34 34   34 34   35 35   35 35   36 36   36 36   36 36   36 36   37 37
  37 37   38 38   38 38   39 39   39 39   39 39   40 40   41 41   41 41
  41 41   42 42   43 43   43 43   44 44   44 44   46 46   46 46   47 47
  47 47   47 47   47 47   49 49   50 50   51 51   52 52   53 53   54 54
  55 55   55 55   56 56   56 56   56 56   57 57   58 58   58 58   58 58
  58 58   59 59   59 59   59 59   59 59   60 60   61 61   61 61   62 62
  62 62   63 63   64 64   65 65   65 65   65 65   66 66   67 67   68 68
  69 69   70 70   72 72   72 72   72 72   73 73   73 73   73 73   74 74
  74 74   74 74   74 74   74 74   75 75   75 75   75 75   76 76   77 77
  77 77   78 78   78 78   79 79   80 80   80 80   81 81   81 81   81 81
  82 82   83 83   84 84   84 84   84 84   84 84   85 85   85 85   85 85
  86 86   87 87   87 87   88 88   89 89   89 89   89 89   90 90   90 90
  90 90   91 91   91 91   91 91   91 91   91 91   93 93   93 93   93 93
  94 94   95 95   95 95   95 95   96 96   96 96   96 96   97 97   97 97
  98 98   98 98   99 99   99 99   99 99}

do_execsql_test 4.7.2 {
  SELECT b, sum(b) OVER (
    ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
  ) FROM t2 ORDER BY 1, 2;
} {0 0   1 3379   1 5443   2 372   2 4473   2 7074   3 2916   3 9096   4 4049   5 5643   6 1047   7 2205   7 7081   7 10141   8 1553   8 5926   8 6422   9 4883   9 7932   9 8497   10 9544   11 5727   11 6433   12 2825   12 5918   12 8582   13 5190   13 8570   14 8596   15 3189   15 6023   15 8924   16 1942   16 1958   16 3590   17 10134   19 7474   20 5946   21 5464   21 9682   22 3029   22 6140   23 212   23 1926   23 8520   24 2626   25 3331   26 337   26 7539   26 7565   27 1270   27 10035   28 3217   29 1649   29 4355   29 7326   30 4215   30 9400   30 9853   31 5977   31 6008   32 2857   33 370   33 4326   33 8175   33 8909   33 9661   34 6414   34 6516   34 8958   34 9925   35 2151   35 5638   36 3701   36 7818   36 8785   36 8994   37 4597   37 8557   38 735   38 9891   39 842   39 7513   39 9721   40 3475   41 115   41 4874   41 5906   42 4185   43 2754   43 3518   44 7072   44 9765   46 1041   46 1316   47 2198   47 3378   47 7612   47 7923   49 6482   50 9450   51 5778   52 9370   53 4408   54 1448   55 3174   55 6876   56 2913   56 3435   56 3574   57 7223   58 5248   58 7876   58 9318   58 9823   59 697   59 2813   59 6665   59 7455   60 6821   61 2426   61 4944   62 904   62 8658   63 4471   64 8407   65 2116   65 5177   65 5603   66 8142   67 1620   68 803   69 9260   70 7396   72 4833   72 8004   72 8076   73 5017   73 5716   73 6213   74 74   74 189   74 2365   74 5538   74 7297   75 3665   75 6951   75 8343   76 3964   77 1903   77 7028   78 1394   78 4293   79 6292   80 4677   80 7692   81 542   81 4045   81 8488   82 10117   83 10008   84 1826   84 4761   84 9534   84 9628   85 2602   85 2711   85 7166   86 2291   87 4560   87 5865   88 6380   89 461   89 3306   89 3790   90 3119   90 6606   90 7782   91 995   91 2517   91 3007   91 8749   91 8876   93 1742   93 2051   93 8268   94 4143   95 5112   95 6118   95 9191   96 638   96 5344   96 6761   97 1243   97 1545   98 3888   98 5442   99 311   99 1146   99 9093}
} {0 0   1 3379   1 5443   2 372   2 4473   2 7074   3 2916   3 9096   4 4049
  5 5643   6 1047   7 2205   7 7081   7 10141   8 1553   8 5926   8 6422
  9 4883   9 7932   9 8497   10 9544   11 5727   11 6433   12 2825   12 5918
  12 8582   13 5190   13 8570   14 8596   15 3189   15 6023   15 8924
  16 1942   16 1958   16 3590   17 10134   19 7474   20 5946   21 5464
  21 9682   22 3029   22 6140   23 212   23 1926   23 8520   24 2626
  25 3331   26 337   26 7539   26 7565   27 1270   27 10035   28 3217
  29 1649   29 4355   29 7326   30 4215   30 9400   30 9853   31 5977
  31 6008   32 2857   33 370   33 4326   33 8175   33 8909   33 9661
  34 6414   34 6516   34 8958   34 9925   35 2151   35 5638   36 3701
  36 7818   36 8785   36 8994   37 4597   37 8557   38 735   38 9891   39 842
  39 7513   39 9721   40 3475   41 115   41 4874   41 5906   42 4185
  43 2754   43 3518   44 7072   44 9765   46 1041   46 1316   47 2198
  47 3378   47 7612   47 7923   49 6482   50 9450   51 5778   52 9370
  53 4408   54 1448   55 3174   55 6876   56 2913   56 3435   56 3574
  57 7223   58 5248   58 7876   58 9318   58 9823   59 697   59 2813
  59 6665   59 7455   60 6821   61 2426   61 4944   62 904   62 8658
  63 4471   64 8407   65 2116   65 5177   65 5603   66 8142   67 1620
  68 803   69 9260   70 7396   72 4833   72 8004   72 8076   73 5017
  73 5716   73 6213   74 74   74 189   74 2365   74 5538   74 7297   75 3665
  75 6951   75 8343   76 3964   77 1903   77 7028   78 1394   78 4293
  79 6292   80 4677   80 7692   81 542   81 4045   81 8488   82 10117
  83 10008   84 1826   84 4761   84 9534   84 9628   85 2602   85 2711
  85 7166   86 2291   87 4560   87 5865   88 6380   89 461   89 3306
  89 3790   90 3119   90 6606   90 7782   91 995   91 2517   91 3007
  91 8749   91 8876   93 1742   93 2051   93 8268   94 4143   95 5112
  95 6118   95 9191   96 638   96 5344   96 6761   97 1243   97 1545
  98 3888   98 5442   99 311   99 1146   99 9093}

do_execsql_test 4.7.3 {
  SELECT b, sum(b) OVER (
    ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
  ) FROM t2 ORDER BY 1, 2;
} {0 10141   1 10141   1 10141   2 10141   2 10141   2 10141   3 10141   3 10141   4 10141   5 10141   6 10141   7 10141   7 10141   7 10141   8 10141   8 10141   8 10141   9 10141   9 10141   9 10141   10 10141   11 10141   11 10141   12 10141   12 10141   12 10141   13 10141   13 10141   14 10141   15 10141   15 10141   15 10141   16 10141   16 10141   16 10141   17 10141   19 10141   20 10141   21 10141   21 10141   22 10141   22 10141   23 10141   23 10141   23 10141   24 10141   25 10141   26 10141   26 10141   26 10141   27 10141   27 10141   28 10141   29 10141   29 10141   29 10141   30 10141   30 10141   30 10141   31 10141   31 10141   32 10141   33 10141   33 10141   33 10141   33 10141   33 10141   34 10141   34 10141   34 10141   34 10141   35 10141   35 10141   36 10141   36 10141   36 10141   36 10141   37 10141   37 10141   38 10141   38 10141   39 10141   39 10141   39 10141   40 10141   41 10141   41 10141   41 10141   42 10141   43 10141   43 10141   44 10141   44 10141   46 10141   46 10141   47 10141   47 10141   47 10141   47 10141   49 10141   50 10141   51 10141   52 10141   53 10141   54 10141   55 10141   55 10141   56 10141   56 10141   56 10141   57 10141   58 10141   58 10141   58 10141   58 10141   59 10141   59 10141   59 10141   59 10141   60 10141   61 10141   61 10141   62 10141   62 10141   63 10141   64 10141   65 10141   65 10141   65 10141   66 10141   67 10141   68 10141   69 10141   70 10141   72 10141   72 10141   72 10141   73 10141   73 10141   73 10141   74 10141   74 10141   74 10141   74 10141   74 10141   75 10141   75 10141   75 10141   76 10141   77 10141   77 10141   78 10141   78 10141   79 10141   80 10141   80 10141   81 10141   81 10141   81 10141   82 10141   83 10141   84 10141   84 10141   84 10141   84 10141   85 10141   85 10141   85 10141   86 10141   87 10141   87 10141   88 10141   89 10141   89 10141   89 10141   90 10141   90 10141   90 10141   91 10141   91 10141   91 10141   91 10141   91 10141   93 10141   93 10141   93 10141   94 10141   95 10141   95 10141   95 10141   96 10141   96 10141   96 10141   97 10141   97 10141   98 10141   98 10141   99 10141   99 10141   99 10141}
} {0 10141   1 10141   1 10141   2 10141   2 10141   2 10141   3 10141
  3 10141   4 10141   5 10141   6 10141   7 10141   7 10141   7 10141
  8 10141   8 10141   8 10141   9 10141   9 10141   9 10141   10 10141
  11 10141   11 10141   12 10141   12 10141   12 10141   13 10141   13 10141
  14 10141   15 10141   15 10141   15 10141   16 10141   16 10141   16 10141
  17 10141   19 10141   20 10141   21 10141   21 10141   22 10141   22 10141
  23 10141   23 10141   23 10141   24 10141   25 10141   26 10141   26 10141
  26 10141   27 10141   27 10141   28 10141   29 10141   29 10141   29 10141
  30 10141   30 10141   30 10141   31 10141   31 10141   32 10141   33 10141
  33 10141   33 10141   33 10141   33 10141   34 10141   34 10141   34 10141
  34 10141   35 10141   35 10141   36 10141   36 10141   36 10141   36 10141
  37 10141   37 10141   38 10141   38 10141   39 10141   39 10141   39 10141
  40 10141   41 10141   41 10141   41 10141   42 10141   43 10141   43 10141
  44 10141   44 10141   46 10141   46 10141   47 10141   47 10141   47 10141
  47 10141   49 10141   50 10141   51 10141   52 10141   53 10141   54 10141
  55 10141   55 10141   56 10141   56 10141   56 10141   57 10141   58 10141
  58 10141   58 10141   58 10141   59 10141   59 10141   59 10141   59 10141
  60 10141   61 10141   61 10141   62 10141   62 10141   63 10141   64 10141
  65 10141   65 10141   65 10141   66 10141   67 10141   68 10141   69 10141
  70 10141   72 10141   72 10141   72 10141   73 10141   73 10141   73 10141
  74 10141   74 10141   74 10141   74 10141   74 10141   75 10141   75 10141
  75 10141   76 10141   77 10141   77 10141   78 10141   78 10141   79 10141
  80 10141   80 10141   81 10141   81 10141   81 10141   82 10141   83 10141
  84 10141   84 10141   84 10141   84 10141   85 10141   85 10141   85 10141
  86 10141   87 10141   87 10141   88 10141   89 10141   89 10141   89 10141
  90 10141   90 10141   90 10141   91 10141   91 10141   91 10141   91 10141
  91 10141   93 10141   93 10141   93 10141   94 10141   95 10141   95 10141
  95 10141   96 10141   96 10141   96 10141   97 10141   97 10141   98 10141
  98 10141   99 10141   99 10141   99 10141}

do_execsql_test 4.7.4 {
  SELECT b, sum(b) OVER (
    ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
  ) FROM t2 ORDER BY 1, 2;
} {0 10141   1 4699   1 6763   2 3069   2 5670   2 9771   3 1048   3 7228   4 6096   5 4503   6 9100   7 7   7 3067   7 7943   8 3727   8 4223   8 8596   9 1653   9 2218   9 5267   10 607   11 3719   11 4425   12 1571   12 4235   12 7328   13 1584   13 4964   14 1559   15 1232   15 4133   15 6967   16 6567   16 8199   16 8215   17 24   19 2686   20 4215   21 480   21 4698   22 4023   22 7134   23 1644   23 8238   23 9952   24 7539   25 6835   26 2602   26 2628   26 9830   27 133   27 8898   28 6952   29 2844   29 5815   29 8521   30 318   30 771   30 5956   31 4164   31 4195   32 7316   33 513   33 1265   33 1999   33 5848   33 9804   34 250   34 1217   34 3659   34 3761   35 4538   35 8025   36 1183   36 1392   36 2359   36 6476   37 1621   37 5581   38 288   38 9444   39 459   39 2667   39 9338   40 6706   41 4276   41 5308   41 10067   42 5998   43 6666   43 7430   44 420   44 3113   46 8871   46 9146   47 2265   47 2576   47 6810   47 7990   49 3708   50 741   51 4414   52 823   53 5786   54 8747   55 3320   55 7022   56 6623   56 6762   56 7284   57 2975   58 376   58 881   58 2323   58 4951   59 2745   59 3535   59 7387   59 9503   60 3380   61 5258   61 7776   62 1545   62 9299   63 5733   64 1798   65 4603   65 5029   65 8090   66 2065   67 8588   68 9406   69 950   70 2815   72 2137   72 2209   72 5380   73 4001   73 4498   73 5197   74 2918   74 4677   74 7850   74 10026   74 10141   75 1873   75 3265   75 6551   76 6253   77 3190   77 8315   78 5926   78 8825   79 3928   80 2529   80 5544   81 1734   81 6177   81 9680   82 106   83 216   84 597   84 691   84 5464   84 8399   85 3060   85 7515   85 7624   86 7936   87 4363   87 5668   88 3849   89 6440   89 6924   89 9769   90 2449   90 3625   90 7112   91 1356   91 1483   91 7225   91 7715   91 9237   93 1966   93 8183   93 8492   94 6092   95 1045   95 4118   95 5124   96 3476   96 4893   96 9599   97 8693   97 8995   98 4797   98 6351   99 1147   99 9094   99 9929}
} {0 10141   1 4699   1 6763   2 3069   2 5670   2 9771   3 1048   3 7228
  4 6096   5 4503   6 9100   7 7   7 3067   7 7943   8 3727   8 4223   8 8596
  9 1653   9 2218   9 5267   10 607   11 3719   11 4425   12 1571   12 4235
  12 7328   13 1584   13 4964   14 1559   15 1232   15 4133   15 6967
  16 6567   16 8199   16 8215   17 24   19 2686   20 4215   21 480   21 4698
  22 4023   22 7134   23 1644   23 8238   23 9952   24 7539   25 6835
  26 2602   26 2628   26 9830   27 133   27 8898   28 6952   29 2844
  29 5815   29 8521   30 318   30 771   30 5956   31 4164   31 4195   32 7316
  33 513   33 1265   33 1999   33 5848   33 9804   34 250   34 1217   34 3659
  34 3761   35 4538   35 8025   36 1183   36 1392   36 2359   36 6476
  37 1621   37 5581   38 288   38 9444   39 459   39 2667   39 9338   40 6706
  41 4276   41 5308   41 10067   42 5998   43 6666   43 7430   44 420
  44 3113   46 8871   46 9146   47 2265   47 2576   47 6810   47 7990
  49 3708   50 741   51 4414   52 823   53 5786   54 8747   55 3320   55 7022
  56 6623   56 6762   56 7284   57 2975   58 376   58 881   58 2323   58 4951
  59 2745   59 3535   59 7387   59 9503   60 3380   61 5258   61 7776
  62 1545   62 9299   63 5733   64 1798   65 4603   65 5029   65 8090
  66 2065   67 8588   68 9406   69 950   70 2815   72 2137   72 2209
  72 5380   73 4001   73 4498   73 5197   74 2918   74 4677   74 7850
  74 10026   74 10141   75 1873   75 3265   75 6551   76 6253   77 3190
  77 8315   78 5926   78 8825   79 3928   80 2529   80 5544   81 1734
  81 6177   81 9680   82 106   83 216   84 597   84 691   84 5464   84 8399
  85 3060   85 7515   85 7624   86 7936   87 4363   87 5668   88 3849
  89 6440   89 6924   89 9769   90 2449   90 3625   90 7112   91 1356
  91 1483   91 7225   91 7715   91 9237   93 1966   93 8183   93 8492
  94 6092   95 1045   95 4118   95 5124   96 3476   96 4893   96 9599
  97 8693   97 8995   98 4797   98 6351   99 1147   99 9094   99 9929}

do_execsql_test 4.8.1 {
  SELECT b, sum(b) OVER (
    ORDER BY a
    ROWS BETWEEN CURRENT ROW AND CURRENT ROW
  ) FROM t2 ORDER BY 1, 2;
} {0 0   1 1   1 1   2 2   2 2   2 2   3 3   3 3   4 4   5 5   6 6   7 7   7 7   7 7   8 8   8 8   8 8   9 9   9 9   9 9   10 10   11 11   11 11   12 12   12 12   12 12   13 13   13 13   14 14   15 15   15 15   15 15   16 16   16 16   16 16   17 17   19 19   20 20   21 21   21 21   22 22   22 22   23 23   23 23   23 23   24 24   25 25   26 26   26 26   26 26   27 27   27 27   28 28   29 29   29 29   29 29   30 30   30 30   30 30   31 31   31 31   32 32   33 33   33 33   33 33   33 33   33 33   34 34   34 34   34 34   34 34   35 35   35 35   36 36   36 36   36 36   36 36   37 37   37 37   38 38   38 38   39 39   39 39   39 39   40 40   41 41   41 41   41 41   42 42   43 43   43 43   44 44   44 44   46 46   46 46   47 47   47 47   47 47   47 47   49 49   50 50   51 51   52 52   53 53   54 54   55 55   55 55   56 56   56 56   56 56   57 57   58 58   58 58   58 58   58 58   59 59   59 59   59 59   59 59   60 60   61 61   61 61   62 62   62 62   63 63   64 64   65 65   65 65   65 65   66 66   67 67   68 68   69 69   70 70   72 72   72 72   72 72   73 73   73 73   73 73   74 74   74 74   74 74   74 74   74 74   75 75   75 75   75 75   76 76   77 77   77 77   78 78   78 78   79 79   80 80   80 80   81 81   81 81   81 81   82 82   83 83   84 84   84 84   84 84   84 84   85 85   85 85   85 85   86 86   87 87   87 87   88 88   89 89   89 89   89 89   90 90   90 90   90 90   91 91   91 91   91 91   91 91   91 91   93 93   93 93   93 93   94 94   95 95   95 95   95 95   96 96   96 96   96 96   97 97   97 97   98 98   98 98   99 99   99 99   99 99}
} {0 0   1 1   1 1   2 2   2 2   2 2   3 3   3 3   4 4   5 5   6 6   7 7   7 7
  7 7   8 8   8 8   8 8   9 9   9 9   9 9   10 10   11 11   11 11   12 12
  12 12   12 12   13 13   13 13   14 14   15 15   15 15   15 15   16 16
  16 16   16 16   17 17   19 19   20 20   21 21   21 21   22 22   22 22
  23 23   23 23   23 23   24 24   25 25   26 26   26 26   26 26   27 27
  27 27   28 28   29 29   29 29   29 29   30 30   30 30   30 30   31 31
  31 31   32 32   33 33   33 33   33 33   33 33   33 33   34 34   34 34
  34 34   34 34   35 35   35 35   36 36   36 36   36 36   36 36   37 37
  37 37   38 38   38 38   39 39   39 39   39 39   40 40   41 41   41 41
  41 41   42 42   43 43   43 43   44 44   44 44   46 46   46 46   47 47
  47 47   47 47   47 47   49 49   50 50   51 51   52 52   53 53   54 54
  55 55   55 55   56 56   56 56   56 56   57 57   58 58   58 58   58 58
  58 58   59 59   59 59   59 59   59 59   60 60   61 61   61 61   62 62
  62 62   63 63   64 64   65 65   65 65   65 65   66 66   67 67   68 68
  69 69   70 70   72 72   72 72   72 72   73 73   73 73   73 73   74 74
  74 74   74 74   74 74   74 74   75 75   75 75   75 75   76 76   77 77
  77 77   78 78   78 78   79 79   80 80   80 80   81 81   81 81   81 81
  82 82   83 83   84 84   84 84   84 84   84 84   85 85   85 85   85 85
  86 86   87 87   87 87   88 88   89 89   89 89   89 89   90 90   90 90
  90 90   91 91   91 91   91 91   91 91   91 91   93 93   93 93   93 93
  94 94   95 95   95 95   95 95   96 96   96 96   96 96   97 97   97 97
  98 98   98 98   99 99   99 99   99 99}

do_execsql_test 4.8.2 {
  SELECT b, sum(b) OVER (
    ORDER BY a
    ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
  ) FROM t2 ORDER BY 1, 2;
} {0 0   1 3379   1 5443   2 372   2 4473   2 7074   3 2916   3 9096   4 4049   5 5643   6 1047   7 2205   7 7081   7 10141   8 1553   8 5926   8 6422   9 4883   9 7932   9 8497   10 9544   11 5727   11 6433   12 2825   12 5918   12 8582   13 5190   13 8570   14 8596   15 3189   15 6023   15 8924   16 1942   16 1958   16 3590   17 10134   19 7474   20 5946   21 5464   21 9682   22 3029   22 6140   23 212   23 1926   23 8520   24 2626   25 3331   26 337   26 7539   26 7565   27 1270   27 10035   28 3217   29 1649   29 4355   29 7326   30 4215   30 9400   30 9853   31 5977   31 6008   32 2857   33 370   33 4326   33 8175   33 8909   33 9661   34 6414   34 6516   34 8958   34 9925   35 2151   35 5638   36 3701   36 7818   36 8785   36 8994   37 4597   37 8557   38 735   38 9891   39 842   39 7513   39 9721   40 3475   41 115   41 4874   41 5906   42 4185   43 2754   43 3518   44 7072   44 9765   46 1041   46 1316   47 2198   47 3378   47 7612   47 7923   49 6482   50 9450   51 5778   52 9370   53 4408   54 1448   55 3174   55 6876   56 2913   56 3435   56 3574   57 7223   58 5248   58 7876   58 9318   58 9823   59 697   59 2813   59 6665   59 7455   60 6821   61 2426   61 4944   62 904   62 8658   63 4471   64 8407   65 2116   65 5177   65 5603   66 8142   67 1620   68 803   69 9260   70 7396   72 4833   72 8004   72 8076   73 5017   73 5716   73 6213   74 74   74 189   74 2365   74 5538   74 7297   75 3665   75 6951   75 8343   76 3964   77 1903   77 7028   78 1394   78 4293   79 6292   80 4677   80 7692   81 542   81 4045   81 8488   82 10117   83 10008   84 1826   84 4761   84 9534   84 9628   85 2602   85 2711   85 7166   86 2291   87 4560   87 5865   88 6380   89 461   89 3306   89 3790   90 3119   90 6606   90 7782   91 995   91 2517   91 3007   91 8749   91 8876   93 1742   93 2051   93 8268   94 4143   95 5112   95 6118   95 9191   96 638   96 5344   96 6761   97 1243   97 1545   98 3888   98 5442   99 311   99 1146   99 9093}
} {0 0   1 3379   1 5443   2 372   2 4473   2 7074   3 2916   3 9096   4 4049
  5 5643   6 1047   7 2205   7 7081   7 10141   8 1553   8 5926   8 6422
  9 4883   9 7932   9 8497   10 9544   11 5727   11 6433   12 2825   12 5918
  12 8582   13 5190   13 8570   14 8596   15 3189   15 6023   15 8924
  16 1942   16 1958   16 3590   17 10134   19 7474   20 5946   21 5464
  21 9682   22 3029   22 6140   23 212   23 1926   23 8520   24 2626
  25 3331   26 337   26 7539   26 7565   27 1270   27 10035   28 3217
  29 1649   29 4355   29 7326   30 4215   30 9400   30 9853   31 5977
  31 6008   32 2857   33 370   33 4326   33 8175   33 8909   33 9661
  34 6414   34 6516   34 8958   34 9925   35 2151   35 5638   36 3701
  36 7818   36 8785   36 8994   37 4597   37 8557   38 735   38 9891   39 842
  39 7513   39 9721   40 3475   41 115   41 4874   41 5906   42 4185
  43 2754   43 3518   44 7072   44 9765   46 1041   46 1316   47 2198
  47 3378   47 7612   47 7923   49 6482   50 9450   51 5778   52 9370
  53 4408   54 1448   55 3174   55 6876   56 2913   56 3435   56 3574
  57 7223   58 5248   58 7876   58 9318   58 9823   59 697   59 2813
  59 6665   59 7455   60 6821   61 2426   61 4944   62 904   62 8658
  63 4471   64 8407   65 2116   65 5177   65 5603   66 8142   67 1620
  68 803   69 9260   70 7396   72 4833   72 8004   72 8076   73 5017
  73 5716   73 6213   74 74   74 189   74 2365   74 5538   74 7297   75 3665
  75 6951   75 8343   76 3964   77 1903   77 7028   78 1394   78 4293
  79 6292   80 4677   80 7692   81 542   81 4045   81 8488   82 10117
  83 10008   84 1826   84 4761   84 9534   84 9628   85 2602   85 2711
  85 7166   86 2291   87 4560   87 5865   88 6380   89 461   89 3306
  89 3790   90 3119   90 6606   90 7782   91 995   91 2517   91 3007
  91 8749   91 8876   93 1742   93 2051   93 8268   94 4143   95 5112
  95 6118   95 9191   96 638   96 5344   96 6761   97 1243   97 1545
  98 3888   98 5442   99 311   99 1146   99 9093}

do_execsql_test 4.8.3 {
  SELECT b, sum(b) OVER (
    ORDER BY a
    ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
  ) FROM t2 ORDER BY 1, 2;
} {0 10141   1 10141   1 10141   2 10141   2 10141   2 10141   3 10141   3 10141   4 10141   5 10141   6 10141   7 10141   7 10141   7 10141   8 10141   8 10141   8 10141   9 10141   9 10141   9 10141   10 10141   11 10141   11 10141   12 10141   12 10141   12 10141   13 10141   13 10141   14 10141   15 10141   15 10141   15 10141   16 10141   16 10141   16 10141   17 10141   19 10141   20 10141   21 10141   21 10141   22 10141   22 10141   23 10141   23 10141   23 10141   24 10141   25 10141   26 10141   26 10141   26 10141   27 10141   27 10141   28 10141   29 10141   29 10141   29 10141   30 10141   30 10141   30 10141   31 10141   31 10141   32 10141   33 10141   33 10141   33 10141   33 10141   33 10141   34 10141   34 10141   34 10141   34 10141   35 10141   35 10141   36 10141   36 10141   36 10141   36 10141   37 10141   37 10141   38 10141   38 10141   39 10141   39 10141   39 10141   40 10141   41 10141   41 10141   41 10141   42 10141   43 10141   43 10141   44 10141   44 10141   46 10141   46 10141   47 10141   47 10141   47 10141   47 10141   49 10141   50 10141   51 10141   52 10141   53 10141   54 10141   55 10141   55 10141   56 10141   56 10141   56 10141   57 10141   58 10141   58 10141   58 10141   58 10141   59 10141   59 10141   59 10141   59 10141   60 10141   61 10141   61 10141   62 10141   62 10141   63 10141   64 10141   65 10141   65 10141   65 10141   66 10141   67 10141   68 10141   69 10141   70 10141   72 10141   72 10141   72 10141   73 10141   73 10141   73 10141   74 10141   74 10141   74 10141   74 10141   74 10141   75 10141   75 10141   75 10141   76 10141   77 10141   77 10141   78 10141   78 10141   79 10141   80 10141   80 10141   81 10141   81 10141   81 10141   82 10141   83 10141   84 10141   84 10141   84 10141   84 10141   85 10141   85 10141   85 10141   86 10141   87 10141   87 10141   88 10141   89 10141   89 10141   89 10141   90 10141   90 10141   90 10141   91 10141   91 10141   91 10141   91 10141   91 10141   93 10141   93 10141   93 10141   94 10141   95 10141   95 10141   95 10141   96 10141   96 10141   96 10141   97 10141   97 10141   98 10141   98 10141   99 10141   99 10141   99 10141}
} {0 10141   1 10141   1 10141   2 10141   2 10141   2 10141   3 10141
  3 10141   4 10141   5 10141   6 10141   7 10141   7 10141   7 10141
  8 10141   8 10141   8 10141   9 10141   9 10141   9 10141   10 10141
  11 10141   11 10141   12 10141   12 10141   12 10141   13 10141   13 10141
  14 10141   15 10141   15 10141   15 10141   16 10141   16 10141   16 10141
  17 10141   19 10141   20 10141   21 10141   21 10141   22 10141   22 10141
  23 10141   23 10141   23 10141   24 10141   25 10141   26 10141   26 10141
  26 10141   27 10141   27 10141   28 10141   29 10141   29 10141   29 10141
  30 10141   30 10141   30 10141   31 10141   31 10141   32 10141   33 10141
  33 10141   33 10141   33 10141   33 10141   34 10141   34 10141   34 10141
  34 10141   35 10141   35 10141   36 10141   36 10141   36 10141   36 10141
  37 10141   37 10141   38 10141   38 10141   39 10141   39 10141   39 10141
  40 10141   41 10141   41 10141   41 10141   42 10141   43 10141   43 10141
  44 10141   44 10141   46 10141   46 10141   47 10141   47 10141   47 10141
  47 10141   49 10141   50 10141   51 10141   52 10141   53 10141   54 10141
  55 10141   55 10141   56 10141   56 10141   56 10141   57 10141   58 10141
  58 10141   58 10141   58 10141   59 10141   59 10141   59 10141   59 10141
  60 10141   61 10141   61 10141   62 10141   62 10141   63 10141   64 10141
  65 10141   65 10141   65 10141   66 10141   67 10141   68 10141   69 10141
  70 10141   72 10141   72 10141   72 10141   73 10141   73 10141   73 10141
  74 10141   74 10141   74 10141   74 10141   74 10141   75 10141   75 10141
  75 10141   76 10141   77 10141   77 10141   78 10141   78 10141   79 10141
  80 10141   80 10141   81 10141   81 10141   81 10141   82 10141   83 10141
  84 10141   84 10141   84 10141   84 10141   85 10141   85 10141   85 10141
  86 10141   87 10141   87 10141   88 10141   89 10141   89 10141   89 10141
  90 10141   90 10141   90 10141   91 10141   91 10141   91 10141   91 10141
  91 10141   93 10141   93 10141   93 10141   94 10141   95 10141   95 10141
  95 10141   96 10141   96 10141   96 10141   97 10141   97 10141   98 10141
  98 10141   99 10141   99 10141   99 10141}

do_execsql_test 4.8.4 {
  SELECT b, sum(b) OVER (
    ORDER BY a
    ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
  ) FROM t2 ORDER BY 1, 2;
} {0 10141   1 4699   1 6763   2 3069   2 5670   2 9771   3 1048   3 7228   4 6096   5 4503   6 9100   7 7   7 3067   7 7943   8 3727   8 4223   8 8596   9 1653   9 2218   9 5267   10 607   11 3719   11 4425   12 1571   12 4235   12 7328   13 1584   13 4964   14 1559   15 1232   15 4133   15 6967   16 6567   16 8199   16 8215   17 24   19 2686   20 4215   21 480   21 4698   22 4023   22 7134   23 1644   23 8238   23 9952   24 7539   25 6835   26 2602   26 2628   26 9830   27 133   27 8898   28 6952   29 2844   29 5815   29 8521   30 318   30 771   30 5956   31 4164   31 4195   32 7316   33 513   33 1265   33 1999   33 5848   33 9804   34 250   34 1217   34 3659   34 3761   35 4538   35 8025   36 1183   36 1392   36 2359   36 6476   37 1621   37 5581   38 288   38 9444   39 459   39 2667   39 9338   40 6706   41 4276   41 5308   41 10067   42 5998   43 6666   43 7430   44 420   44 3113   46 8871   46 9146   47 2265   47 2576   47 6810   47 7990   49 3708   50 741   51 4414   52 823   53 5786   54 8747   55 3320   55 7022   56 6623   56 6762   56 7284   57 2975   58 376   58 881   58 2323   58 4951   59 2745   59 3535   59 7387   59 9503   60 3380   61 5258   61 7776   62 1545   62 9299   63 5733   64 1798   65 4603   65 5029   65 8090   66 2065   67 8588   68 9406   69 950   70 2815   72 2137   72 2209   72 5380   73 4001   73 4498   73 5197   74 2918   74 4677   74 7850   74 10026   74 10141   75 1873   75 3265   75 6551   76 6253   77 3190   77 8315   78 5926   78 8825   79 3928   80 2529   80 5544   81 1734   81 6177   81 9680   82 106   83 216   84 597   84 691   84 5464   84 8399   85 3060   85 7515   85 7624   86 7936   87 4363   87 5668   88 3849   89 6440   89 6924   89 9769   90 2449   90 3625   90 7112   91 1356   91 1483   91 7225   91 7715   91 9237   93 1966   93 8183   93 8492   94 6092   95 1045   95 4118   95 5124   96 3476   96 4893   96 9599   97 8693   97 8995   98 4797   98 6351   99 1147   99 9094   99 9929}
} {0 10141   1 4699   1 6763   2 3069   2 5670   2 9771   3 1048   3 7228
  4 6096   5 4503   6 9100   7 7   7 3067   7 7943   8 3727   8 4223   8 8596
  9 1653   9 2218   9 5267   10 607   11 3719   11 4425   12 1571   12 4235
  12 7328   13 1584   13 4964   14 1559   15 1232   15 4133   15 6967
  16 6567   16 8199   16 8215   17 24   19 2686   20 4215   21 480   21 4698
  22 4023   22 7134   23 1644   23 8238   23 9952   24 7539   25 6835
  26 2602   26 2628   26 9830   27 133   27 8898   28 6952   29 2844
  29 5815   29 8521   30 318   30 771   30 5956   31 4164   31 4195   32 7316
  33 513   33 1265   33 1999   33 5848   33 9804   34 250   34 1217   34 3659
  34 3761   35 4538   35 8025   36 1183   36 1392   36 2359   36 6476
  37 1621   37 5581   38 288   38 9444   39 459   39 2667   39 9338   40 6706
  41 4276   41 5308   41 10067   42 5998   43 6666   43 7430   44 420
  44 3113   46 8871   46 9146   47 2265   47 2576   47 6810   47 7990
  49 3708   50 741   51 4414   52 823   53 5786   54 8747   55 3320   55 7022
  56 6623   56 6762   56 7284   57 2975   58 376   58 881   58 2323   58 4951
  59 2745   59 3535   59 7387   59 9503   60 3380   61 5258   61 7776
  62 1545   62 9299   63 5733   64 1798   65 4603   65 5029   65 8090
  66 2065   67 8588   68 9406   69 950   70 2815   72 2137   72 2209
  72 5380   73 4001   73 4498   73 5197   74 2918   74 4677   74 7850
  74 10026   74 10141   75 1873   75 3265   75 6551   76 6253   77 3190
  77 8315   78 5926   78 8825   79 3928   80 2529   80 5544   81 1734
  81 6177   81 9680   82 106   83 216   84 597   84 691   84 5464   84 8399
  85 3060   85 7515   85 7624   86 7936   87 4363   87 5668   88 3849
  89 6440   89 6924   89 9769   90 2449   90 3625   90 7112   91 1356
  91 1483   91 7225   91 7715   91 9237   93 1966   93 8183   93 8492
  94 6092   95 1045   95 4118   95 5124   96 3476   96 4893   96 9599
  97 8693   97 8995   98 4797   98 6351   99 1147   99 9094   99 9929}


do_test 4.9 {
  set myres {}
  foreach r [db eval {SELECT 
    rank() OVER win AS rank,
    cume_dist() OVER win AS cume_dist FROM t1
  WINDOW win AS (ORDER BY 1);}] {
    lappend myres [format %.4f [set r]]
  }
  set res2 {1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000}
  set i 0
  foreach r [set myres] r2 [set res2] {
    if {[set r]<([set r2]-0.0001) || [set r]>([set r2]+0.0001)} {
      error "list element [set i] does not match: got=[set r] expected=[set r2]"
    }
    incr i
  }
  set {} {}
} {}

do_execsql_test 4.10 {
  SELECT count(*) OVER (ORDER BY b) FROM t1
} {3   3   3   6   6   6}

do_execsql_test 4.11 {
  SELECT count(distinct a) FILTER (WHERE b='odd') FROM t1
} {3}

#==========================================================================

do_execsql_test 5.0 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(x INTEGER, y INTEGER);
  INSERT INTO t1 VALUES(10, 1);
  INSERT INTO t1 VALUES(20, 2);
  INSERT INTO t1 VALUES(3, 3);
  INSERT INTO t1 VALUES(2, 4);
  INSERT INTO t1 VALUES(1, 5);
} {}


do_test 5.1 {
  set myres {}
  foreach r [db eval {SELECT avg(x) OVER (ORDER BY y) AS z FROM t1 ORDER BY z;}] {
    lappend myres [format %.4f [set r]]
  }
  set res2 {7.2000 8.7500 10.0000 11.0000 15.0000}
  set i 0
  foreach r [set myres] r2 [set res2] {
    if {[set r]<([set r2]-0.0001) || [set r]>([set r2]+0.0001)} {
      error "list element [set i] does not match: got=[set r] expected=[set r2]"
    }
    incr i
  }
  set {} {}
} {}

#==========================================================================

do_execsql_test 6.0 {
  DROP TABLE IF EXISTS t0;
  CREATE TABLE t0(c0 INTEGER UNIQUE);
  INSERT INTO t0 VALUES(0);
} {}

do_execsql_test 6.1 {
  SELECT DENSE_RANK() OVER(), LAG(0) OVER() FROM t0;
} {1 {}}

do_execsql_test 6.2 {
  SELECT * FROM t0 WHERE 
      (0, t0.c0) IN (SELECT DENSE_RANK() OVER(), LAG(0) OVER() FROM t0);
} {}

#==========================================================================

do_execsql_test 7.0 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a INTEGER, b INTEGER, c INTEGER);
  INSERT INTO t1 VALUES(1, 1, 1);
  INSERT INTO t1 VALUES(1, 2, 2);
  INSERT INTO t1 VALUES(3, 3, 3);
  INSERT INTO t1 VALUES(3, 4, 4);
} {}

do_execsql_test 7.1 {
  SELECT c, sum(c) OVER win1 FROM t1 
  WINDOW win1 AS (ORDER BY b)
} {1 1   2 3   3 6   4 10}

do_execsql_test 7.2 {
  SELECT c, sum(c) OVER win1 FROM t1 
  WINDOW win1 AS (PARTITION BY 1 ORDER BY b)
} {1 1   2 3   3 6   4 10}

do_execsql_test 7.3 {
  SELECT c, sum(c) OVER win1 FROM t1 
  WINDOW win1 AS (ORDER BY 1)
} {1 10   2 10   3 10   4 10}

finish_test

Changes to test/window3.tcl.

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
17
18
19
20
21
22
23

24
25
26
27
28
29
30







-







start_test window3 "2018 May 31"
ifcapable !windowfunc

execsql_test 1.0 {
  DROP TABLE IF EXISTS t2;
  CREATE TABLE t2(a INTEGER PRIMARY KEY, b INTEGER);
  INSERT INTO t2(a, b) VALUES
  (1,0), (2,74), (3,41), (4,74), (5,23), (6,99), (7,26), (8,33), (9,2),
  (10,89), (11,81), (12,96), (13,59), (14,38), (15,68), (16,39), (17,62),
  (18,91), (19,46), (20,6), (21,99), (22,97), (23,27), (24,46), (25,78),
  (26,54), (27,97), (28,8), (29,67), (30,29), (31,93), (32,84), (33,77),
  (34,23), (35,16), (36,16), (37,93), (38,65), (39,35), (40,47), (41,7),
  (42,86), (43,74), (44,61), (45,91), (46,85), (47,24), (48,85), (49,43),
  (50,59), (51,12), (52,32), (53,56), (54,3), (55,91), (56,22), (57,90),
  (58,55), (59,15), (60,28), (61,89), (62,25), (63,47), (64,1), (65,56),
69
70
71
72
73
74
75





76
77
78
79
80
81
82
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86







+
+
+
+
+







  11 "ROWS BETWEEN 4 PRECEDING    AND 2 FOLLOWING"
  12 "ROWS BETWEEN CURRENT ROW         AND 4 FOLLOWING"
  13 "ROWS BETWEEN 2 FOLLOWING    AND 4 FOLLOWING"
  14 "ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING"
  15 "ROWS BETWEEN 4 PRECEDING    AND UNBOUNDED FOLLOWING"
  16 "ROWS BETWEEN CURRENT ROW         AND UNBOUNDED FOLLOWING"
  17 "ROWS BETWEEN 4 FOLLOWING    AND UNBOUNDED FOLLOWING"

  18 "ROWS BETWEEN 4 PRECEDING    AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW"
  19 "ROWS BETWEEN 4 PRECEDING    AND UNBOUNDED FOLLOWING EXCLUDE TIES"
  20 "ROWS BETWEEN 4 PRECEDING    AND UNBOUNDED FOLLOWING EXCLUDE GROUP"

} {
  execsql_test 1.$tn.2.1 "SELECT max(b) OVER ( ORDER BY a $window ) FROM t2"
  execsql_test 1.$tn.2.2 "SELECT min(b) OVER ( ORDER BY a $window ) FROM t2"

  execsql_test 1.$tn.3.1 "
    SELECT row_number() OVER ( ORDER BY a $window ) FROM t2
  "
302
303
304
305
306
307
308






















309
310
311
312
313
314
315
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  "
  execsql_test 1.$tn.14.5 "
    SELECT string_agg(CAST(b AS TEXT), '.') OVER ( ORDER BY b%10,a $window ) FROM t2
  "
  execsql_test 1.$tn.14.6 "
    SELECT string_agg(CAST(b AS TEXT), '.') OVER (PARTITION BY b%2,a ORDER BY b%10 $window) FROM t2
  "

  execsql_test 1.$tn.14.7 "
    SELECT string_agg(CAST(b AS TEXT), '.') OVER (win1 ORDER BY b%10 $window) 
    FROM t2
    WINDOW win1 AS (PARTITION BY b%2,a)
    ORDER BY 1
  "

  execsql_test 1.$tn.14.8 "
    SELECT string_agg(CAST(b AS TEXT), '.') OVER (win1 $window) 
    FROM t2
    WINDOW win1 AS (PARTITION BY b%2,a ORDER BY b%10)
    ORDER BY 1
  "

  execsql_test 1.$tn.14.9 "
    SELECT string_agg(CAST(b AS TEXT), '.') OVER win2
    FROM t2
    WINDOW win1 AS (PARTITION BY b%2,a ORDER BY b%10),
           win2 AS (win1 $window)
    ORDER BY 1
  "

  execsql_test 1.$tn.15.1 "
    SELECT count(*) OVER win, string_agg(CAST(b AS TEXT), '.') 
    FILTER (WHERE a%2=0) OVER win FROM t2
    WINDOW win AS (ORDER BY a $window)
  "

Changes to test/window3.test.

cannot compute difference between binary files

Changes to test/window4.tcl.

1

2
3
4
5
6
7
8

1
2
3
4
5
6
7
8
-
+







# 2018 May 19
## 2018 May 19
#
# 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.
381
382
383
384
385
386
387


388

































389
390
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







+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



execsql_test 11.4 {
  SELECT * FROM (
    SELECT NTILE(256) OVER (ORDER BY total) - 1 AS nt FROM t8
  ) sub;
}

execsql_test 11.5 {
  SELECT sum( min(t) ) OVER () FROM t8 GROUP BY total;

}
execsql_test 11.5 {
  SELECT sum( max(t) ) OVER () FROM t8 GROUP BY total;
}

execsql_test 11.7 {
  SELECT sum( min(t) ) OVER () FROM t8;
}
execsql_test 11.8 {
  SELECT sum( max(t) ) OVER () FROM t8;
}

execsql_test 12.0 {
  DROP TABLE IF EXISTS t2;
  CREATE TABLE t2(a INTEGER);
  INSERT INTO t2 VALUES(1), (2), (3);
}

execsql_test 12.1 {
  SELECT (SELECT min(a) OVER ()) FROM t2
}

execsql_float_test 12.2 {
  SELECT (SELECT avg(a)) FROM t2 ORDER BY 1
}

execsql_float_test 12.3 {
  SELECT 
    (SELECT avg(a) UNION SELECT min(a) OVER ()) 
  FROM t2 GROUP BY a
  ORDER BY 1
}

finish_test

Changes to test/window4.test.

146
147
148
149
150
151
152
153


154
155
156
157
158
159
160
146
147
148
149
150
151
152

153
154
155
156
157
158
159
160
161







-
+
+







  SELECT a, lag(b, 3, 'abc') OVER (ORDER BY a) FROM t4
} {1 abc   2 abc   3 abc   4 A   5 B   6 C   7 D   8 E   9 F   10 G}

do_execsql_test 2.4.1 {
  SELECT group_concat(b, '.') OVER (
    ORDER BY a ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
  ) FROM t4
} {A.B.C.D.E.F.G.H.I.J   B.C.D.E.F.G.H.I.J   C.D.E.F.G.H.I.J   D.E.F.G.H.I.J   E.F.G.H.I.J   F.G.H.I.J   G.H.I.J   H.I.J   I.J   J}
} {A.B.C.D.E.F.G.H.I.J   B.C.D.E.F.G.H.I.J   C.D.E.F.G.H.I.J   D.E.F.G.H.I.J
  E.F.G.H.I.J   F.G.H.I.J   G.H.I.J   H.I.J   I.J   J}

do_execsql_test 3.0 {
  DROP TABLE IF EXISTS t5;
  CREATE TABLE t5(a INTEGER PRIMARY KEY, b TEXT, c TEXT, d INTEGER);
  INSERT INTO t5 VALUES(1, 'A', 'one',   5);
  INSERT INTO t5 VALUES(2, 'B', 'two',   4);
  INSERT INTO t5 VALUES(3, 'A', 'three', 3);
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
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







+




+



















+




+











+




+








do_test 9.3 {
  set myres {}
  foreach r [db eval {SELECT x, percent_rank() OVER (PARTITION BY x ORDER BY x) FROM t2}] {
    lappend myres [format %.4f [set r]]
  }
  set res2 {1.0000 0.0000 1.0000 0.0000 1.0000 0.0000 4.0000 0.0000 4.0000 0.0000 6.0000 0.0000 7.0000 0.0000}
  set i 0
  foreach r [set myres] r2 [set res2] {
    if {[set r]<([set r2]-0.0001) || [set r]>([set r2]+0.0001)} {
      error "list element [set i] does not match: got=[set r] expected=[set r2]"
    }
    incr i
  }
  set {} {}
} {}

do_execsql_test 9.4 {
  SELECT x, rank() OVER (ORDER BY x) FROM t2 ORDER BY 1,2
} {1 1   1 1   1 1   4 4   4 4   6 6   7 7}

do_execsql_test 9.5 {
  SELECT DISTINCT x, rank() OVER (ORDER BY x) FROM t2 ORDER BY 1,2
} {1 1   4 4   6 6   7 7}


do_test 9.6 {
  set myres {}
  foreach r [db eval {SELECT percent_rank() OVER () FROM t1}] {
    lappend myres [format %.4f [set r]]
  }
  set res2 {0.0000 0.0000 0.0000}
  set i 0
  foreach r [set myres] r2 [set res2] {
    if {[set r]<([set r2]-0.0001) || [set r]>([set r2]+0.0001)} {
      error "list element [set i] does not match: got=[set r] expected=[set r2]"
    }
    incr i
  }
  set {} {}
} {}


do_test 9.7 {
  set myres {}
  foreach r [db eval {SELECT cume_dist() OVER () FROM t1}] {
    lappend myres [format %.4f [set r]]
  }
  set res2 {1.0000 1.0000 1.0000}
  set i 0
  foreach r [set myres] r2 [set res2] {
    if {[set r]<([set r2]-0.0001) || [set r]>([set r2]+0.0001)} {
      error "list element [set i] does not match: got=[set r] expected=[set r2]"
    }
    incr i
  }
  set {} {}
} {}

do_execsql_test 10.0 {
  DROP TABLE IF EXISTS t7;
  CREATE TABLE t7(id INTEGER PRIMARY KEY, a INTEGER, b INTEGER);
1312
1313
1314
1315
1316
1317
1318
1319































































1320
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

} {0   1   2}

do_execsql_test 11.4 {
  SELECT * FROM (
    SELECT NTILE(256) OVER (ORDER BY total) - 1 AS nt FROM t8
  ) sub;
} {0   1   2}

do_execsql_test 11.5 {
  SELECT sum( min(t) ) OVER () FROM t8 GROUP BY total;
} {5   5}

do_execsql_test 11.5 {
  SELECT sum( max(t) ) OVER () FROM t8 GROUP BY total;
} {10   10}

do_execsql_test 11.7 {
  SELECT sum( min(t) ) OVER () FROM t8;
} {0}

do_execsql_test 11.8 {
  SELECT sum( max(t) ) OVER () FROM t8;
} {10}

do_execsql_test 12.0 {
  DROP TABLE IF EXISTS t2;
  CREATE TABLE t2(a INTEGER);
  INSERT INTO t2 VALUES(1), (2), (3);
} {}

do_execsql_test 12.1 {
  SELECT (SELECT min(a) OVER ()) FROM t2
} {1   2   3}


do_test 12.2 {
  set myres {}
  foreach r [db eval {SELECT (SELECT avg(a)) FROM t2 ORDER BY 1}] {
    lappend myres [format %.4f [set r]]
  }
  set res2 {2.0000}
  set i 0
  foreach r [set myres] r2 [set res2] {
    if {[set r]<([set r2]-0.0001) || [set r]>([set r2]+0.0001)} {
      error "list element [set i] does not match: got=[set r] expected=[set r2]"
    }
    incr i
  }
  set {} {}
} {}


do_test 12.3 {
  set myres {}
  foreach r [db eval {SELECT 
    (SELECT avg(a) UNION SELECT min(a) OVER ()) 
  FROM t2 GROUP BY a
  ORDER BY 1}] {
    lappend myres [format %.4f [set r]]
  }
  set res2 {1.0000 2.0000 3.0000}
  set i 0
  foreach r [set myres] r2 [set res2] {
    if {[set r]<([set r2]-0.0001) || [set r]>([set r2]+0.0001)} {
      error "list element [set i] does not match: got=[set r] expected=[set r2]"
    }
    incr i
  }
  set {} {}
} {}

finish_test

Changes to test/window6.test.

144
145
146
147
148
149
150

151
152
153
154
155
156
157
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158







+







  WINDOW win AS (ORDER BY x ROWS BETWEEN +2 FOLLOWING AND +3 FOLLOWING)
} {1 0 0}

#-------------------------------------------------------------------------
#

ifcapable !icu {
  sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1
  do_execsql_test 6.0 {
    SELECT LIKE('!', '', '!') x WHERE x;
  } {}
  do_execsql_test 6.1 {
    SELECT LIKE("!","","!")""WHeRE"";
  } {}
  do_catchsql_test 6.2 {
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
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







-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+







do_execsql_test 9.0 {
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<5)
  SELECT x, group_concat(x) OVER (ORDER BY x ROWS 2 PRECEDING)
  FROM c;
} {
  1 1  2 1,2  3 1,2,3  4 2,3,4  5 3,4,5
}
do_catchsql_test 9.1 {
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<5)
  SELECT x, group_concat(x) OVER (ORDER BY x RANGE 2 PRECEDING)
  FROM c;
} {1 {RANGE must use only UNBOUNDED or CURRENT ROW}}

do_catchsql_test 9.2 {
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<5)
  SELECT x, group_concat(x) OVER (ORDER BY x RANGE BETWEEN UNBOUNDED PRECEDING AND 2 FOLLOWING)
  FROM c;
} {1 {RANGE must use only UNBOUNDED or CURRENT ROW}}
#do_catchsql_test 9.1 {
#  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<5)
#  SELECT x, group_concat(x) OVER (ORDER BY x RANGE 2 PRECEDING)
#  FROM c;
#} {1 {RANGE must use only UNBOUNDED or CURRENT ROW}}
#
#do_catchsql_test 9.2 {
#  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<5)
#  SELECT x, group_concat(x) OVER (ORDER BY x RANGE BETWEEN UNBOUNDED PRECEDING AND 2 FOLLOWING)
#  FROM c;
#} {1 {RANGE must use only UNBOUNDED or CURRENT ROW}}

do_catchsql_test 9.3 {
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<5)
  SELECT count(DISTINCT x) OVER (ORDER BY x) FROM c;
} {1 {DISTINCT is not supported for window functions}}

do_catchsql_test 9.4 {
258
259
260
261
262
263
264
265

266
267
268
269
270
271
272
259
260
261
262
263
264
265

266
267
268
269
270
271
272
273







-
+







  4 "BETWEEN 4 FOLLOWING AND 2 PRECEDING"
} {
  do_catchsql_test 9.7.$tn "
    WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<5)
    SELECT count() OVER (
        ORDER BY x ROWS $frame 
    ) FROM c;
  " {1 {unsupported frame delimiter for ROWS}}
  " {1 {unsupported frame specification}}
}

do_catchsql_test 9.8.1 {
  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<5)
  SELECT count() OVER (
      ORDER BY x ROWS BETWEEN a PRECEDING AND 2 FOLLOWING
  ) FROM c;
332
333
334
335
336
337
338
339






























340
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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

do_execsql_test 11.2 {
  SELECT a, (SELECT y FROM t3 WHERE x=a), sum(a) OVER (ORDER BY a)
    FROM t1 ORDER BY a;
} {
  10 ten 10   15 fifteen 25   20 {} 65        20 {} 65   
  25 {} 90    30 thirty 150   30 thirty 150   50 {} 200
}

do_execsql_test 11.3.1 {
  SELECT a, sum(a) OVER win FROM t1
  WINDOW win AS (ORDER BY a ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
} {
  10 10 15 25 20 45 20 65 25 90 30 120 30 150 50 200
}
do_execsql_test 11.3.2 {
  SELECT a, sum(a) OVER win FROM t1
  WINDOW win AS (ORDER BY a ROWS BETWEEN UNBOUNDED PRECEDING AND 0 FOLLOWING)
} {
  10 10 15 25 20 45 20 65 25 90 30 120 30 150 50 200
}
do_execsql_test 11.3.3 {
  SELECT a, sum(a) OVER win FROM t1
  WINDOW win AS (ORDER BY a ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING)
} {
  10 10 15 25 20 45 20 65 25 90 30 120 30 150 50 200
}

do_execsql_test 11.4.1 {
  SELECT y, group_concat(y, '.') OVER win FROM t3
  WINDOW win AS (
    ORDER BY y RANGE BETWEEN UNBOUNDED PRECEDING AND 10 PRECEDING
  );
} {
  fifteen fifteen 
  ten     fifteen.ten 
  thirty  fifteen.ten.thirty
}

finish_test

Added test/window7.tcl.




























































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2018 May 19
#
# 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.
#
#***********************************************************************
#

source [file join [file dirname $argv0] pg_common.tcl]

#=========================================================================

start_test window7 "2019 March 01"
ifcapable !windowfunc

execsql_test 1.0 {
  DROP TABLE IF EXISTS t3;
  CREATE TABLE t3(a INTEGER, b INTEGER);
  INSERT INTO t3 VALUES
    (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8), 
    (9, 9), (0, 10), (1, 11), (2, 12), (3, 13), (4, 14), (5, 15), (6, 16), 
    (7, 17), (8, 18), (9, 19), (0, 20), (1, 21), (2, 22), (3, 23), (4, 24), 
    (5, 25), (6, 26), (7, 27), (8, 28), (9, 29), (0, 30), (1, 31), (2, 32), 
    (3, 33), (4, 34), (5, 35), (6, 36), (7, 37), (8, 38), (9, 39), (0, 40), 
    (1, 41), (2, 42), (3, 43), (4, 44), (5, 45), (6, 46), (7, 47), (8, 48), 
    (9, 49), (0, 50), (1, 51), (2, 52), (3, 53), (4, 54), (5, 55), (6, 56), 
    (7, 57), (8, 58), (9, 59), (0, 60), (1, 61), (2, 62), (3, 63), (4, 64), 
    (5, 65), (6, 66), (7, 67), (8, 68), (9, 69), (0, 70), (1, 71), (2, 72), 
    (3, 73), (4, 74), (5, 75), (6, 76), (7, 77), (8, 78), (9, 79), (0, 80), 
    (1, 81), (2, 82), (3, 83), (4, 84), (5, 85), (6, 86), (7, 87), (8, 88), 
    (9, 89), (0, 90), (1, 91), (2, 92), (3, 93), (4, 94), (5, 95), (6, 96), 
    (7, 97), (8, 98), (9, 99), (0, 100);
}

execsql_test 1.1 {
  SELECT a, sum(b) FROM t3 GROUP BY a ORDER BY 1;
}

execsql_test 1.2 {
  SELECT a, sum(b) OVER (
    ORDER BY a GROUPS BETWEEN CURRENT ROW AND CURRENT ROW
  ) FROM t3 ORDER BY 1;
}

execsql_test 1.3 {
  SELECT a, sum(b) OVER (
    ORDER BY a GROUPS BETWEEN 0 PRECEDING AND 0 FOLLOWING
  ) FROM t3 ORDER BY 1;
}

execsql_test 1.4 {
  SELECT a, sum(b) OVER (
    ORDER BY a GROUPS BETWEEN 2 PRECEDING AND 2 FOLLOWING
  ) FROM t3 ORDER BY 1;
}

execsql_test 1.5 {
  SELECT a, sum(b) OVER (
    ORDER BY a RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING
  ) FROM t3 ORDER BY 1;
}

execsql_test 1.6 {
  SELECT a, sum(b) OVER (
    ORDER BY a RANGE BETWEEN 2 PRECEDING AND 2 FOLLOWING
  ) FROM t3 ORDER BY 1;
}

execsql_test 1.7 {
  SELECT a, sum(b) OVER (
    ORDER BY a RANGE BETWEEN 2 PRECEDING AND 1 FOLLOWING
  ) FROM t3 ORDER BY 1;
}

execsql_test 1.8.1 {
  SELECT a, sum(b) OVER (
    ORDER BY a RANGE BETWEEN 0 PRECEDING AND 1 FOLLOWING
  ) FROM t3 ORDER BY 1;
}
execsql_test 1.8.2 {
  SELECT a, sum(b) OVER (
    ORDER BY a DESC RANGE BETWEEN 0 PRECEDING AND 1 FOLLOWING
  ) FROM t3 ORDER BY 1;
}

finish_test

Added test/window7.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019 March 01
#
# 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.
#

####################################################
# DO NOT EDIT! THIS FILE IS AUTOMATICALLY GENERATED!
####################################################

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix window7

ifcapable !windowfunc { finish_test ; return }
do_execsql_test 1.0 {
  DROP TABLE IF EXISTS t3;
  CREATE TABLE t3(a INTEGER, b INTEGER);
  INSERT INTO t3 VALUES
    (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8), 
    (9, 9), (0, 10), (1, 11), (2, 12), (3, 13), (4, 14), (5, 15), (6, 16), 
    (7, 17), (8, 18), (9, 19), (0, 20), (1, 21), (2, 22), (3, 23), (4, 24), 
    (5, 25), (6, 26), (7, 27), (8, 28), (9, 29), (0, 30), (1, 31), (2, 32), 
    (3, 33), (4, 34), (5, 35), (6, 36), (7, 37), (8, 38), (9, 39), (0, 40), 
    (1, 41), (2, 42), (3, 43), (4, 44), (5, 45), (6, 46), (7, 47), (8, 48), 
    (9, 49), (0, 50), (1, 51), (2, 52), (3, 53), (4, 54), (5, 55), (6, 56), 
    (7, 57), (8, 58), (9, 59), (0, 60), (1, 61), (2, 62), (3, 63), (4, 64), 
    (5, 65), (6, 66), (7, 67), (8, 68), (9, 69), (0, 70), (1, 71), (2, 72), 
    (3, 73), (4, 74), (5, 75), (6, 76), (7, 77), (8, 78), (9, 79), (0, 80), 
    (1, 81), (2, 82), (3, 83), (4, 84), (5, 85), (6, 86), (7, 87), (8, 88), 
    (9, 89), (0, 90), (1, 91), (2, 92), (3, 93), (4, 94), (5, 95), (6, 96), 
    (7, 97), (8, 98), (9, 99), (0, 100);
} {}

do_execsql_test 1.1 {
  SELECT a, sum(b) FROM t3 GROUP BY a ORDER BY 1;
} {0 550   1 460   2 470   3 480   4 490   5 500   6 510   7 520   8 530
  9 540}

do_execsql_test 1.2 {
  SELECT a, sum(b) OVER (
    ORDER BY a GROUPS BETWEEN CURRENT ROW AND CURRENT ROW
  ) FROM t3 ORDER BY 1;
} {0 550   0 550   0 550   0 550   0 550   0 550   0 550   0 550   0 550
  0 550   1 460   1 460   1 460   1 460   1 460   1 460   1 460   1 460
  1 460   1 460   2 470   2 470   2 470   2 470   2 470   2 470   2 470
  2 470   2 470   2 470   3 480   3 480   3 480   3 480   3 480   3 480
  3 480   3 480   3 480   3 480   4 490   4 490   4 490   4 490   4 490
  4 490   4 490   4 490   4 490   4 490   5 500   5 500   5 500   5 500
  5 500   5 500   5 500   5 500   5 500   5 500   6 510   6 510   6 510
  6 510   6 510   6 510   6 510   6 510   6 510   6 510   7 520   7 520
  7 520   7 520   7 520   7 520   7 520   7 520   7 520   7 520   8 530
  8 530   8 530   8 530   8 530   8 530   8 530   8 530   8 530   8 530
  9 540   9 540   9 540   9 540   9 540   9 540   9 540   9 540   9 540
  9 540}

do_execsql_test 1.3 {
  SELECT a, sum(b) OVER (
    ORDER BY a GROUPS BETWEEN 0 PRECEDING AND 0 FOLLOWING
  ) FROM t3 ORDER BY 1;
} {0 550   0 550   0 550   0 550   0 550   0 550   0 550   0 550   0 550
  0 550   1 460   1 460   1 460   1 460   1 460   1 460   1 460   1 460
  1 460   1 460   2 470   2 470   2 470   2 470   2 470   2 470   2 470
  2 470   2 470   2 470   3 480   3 480   3 480   3 480   3 480   3 480
  3 480   3 480   3 480   3 480   4 490   4 490   4 490   4 490   4 490
  4 490   4 490   4 490   4 490   4 490   5 500   5 500   5 500   5 500
  5 500   5 500   5 500   5 500   5 500   5 500   6 510   6 510   6 510
  6 510   6 510   6 510   6 510   6 510   6 510   6 510   7 520   7 520
  7 520   7 520   7 520   7 520   7 520   7 520   7 520   7 520   8 530
  8 530   8 530   8 530   8 530   8 530   8 530   8 530   8 530   8 530
  9 540   9 540   9 540   9 540   9 540   9 540   9 540   9 540   9 540
  9 540}

do_execsql_test 1.4 {
  SELECT a, sum(b) OVER (
    ORDER BY a GROUPS BETWEEN 2 PRECEDING AND 2 FOLLOWING
  ) FROM t3 ORDER BY 1;
} {0 1480   0 1480   0 1480   0 1480   0 1480   0 1480   0 1480   0 1480
  0 1480   0 1480   1 1960   1 1960   1 1960   1 1960   1 1960   1 1960
  1 1960   1 1960   1 1960   1 1960   2 2450   2 2450   2 2450   2 2450
  2 2450   2 2450   2 2450   2 2450   2 2450   2 2450   3 2400   3 2400
  3 2400   3 2400   3 2400   3 2400   3 2400   3 2400   3 2400   3 2400
  4 2450   4 2450   4 2450   4 2450   4 2450   4 2450   4 2450   4 2450
  4 2450   4 2450   5 2500   5 2500   5 2500   5 2500   5 2500   5 2500
  5 2500   5 2500   5 2500   5 2500   6 2550   6 2550   6 2550   6 2550
  6 2550   6 2550   6 2550   6 2550   6 2550   6 2550   7 2600   7 2600
  7 2600   7 2600   7 2600   7 2600   7 2600   7 2600   7 2600   7 2600
  8 2100   8 2100   8 2100   8 2100   8 2100   8 2100   8 2100   8 2100
  8 2100   8 2100   9 1590   9 1590   9 1590   9 1590   9 1590   9 1590
  9 1590   9 1590   9 1590   9 1590}

do_execsql_test 1.5 {
  SELECT a, sum(b) OVER (
    ORDER BY a RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING
  ) FROM t3 ORDER BY 1;
} {0 550   0 550   0 550   0 550   0 550   0 550   0 550   0 550   0 550
  0 550   1 460   1 460   1 460   1 460   1 460   1 460   1 460   1 460
  1 460   1 460   2 470   2 470   2 470   2 470   2 470   2 470   2 470
  2 470   2 470   2 470   3 480   3 480   3 480   3 480   3 480   3 480
  3 480   3 480   3 480   3 480   4 490   4 490   4 490   4 490   4 490
  4 490   4 490   4 490   4 490   4 490   5 500   5 500   5 500   5 500
  5 500   5 500   5 500   5 500   5 500   5 500   6 510   6 510   6 510
  6 510   6 510   6 510   6 510   6 510   6 510   6 510   7 520   7 520
  7 520   7 520   7 520   7 520   7 520   7 520   7 520   7 520   8 530
  8 530   8 530   8 530   8 530   8 530   8 530   8 530   8 530   8 530
  9 540   9 540   9 540   9 540   9 540   9 540   9 540   9 540   9 540
  9 540}

do_execsql_test 1.6 {
  SELECT a, sum(b) OVER (
    ORDER BY a RANGE BETWEEN 2 PRECEDING AND 2 FOLLOWING
  ) FROM t3 ORDER BY 1;
} {0 1480   0 1480   0 1480   0 1480   0 1480   0 1480   0 1480   0 1480
  0 1480   0 1480   1 1960   1 1960   1 1960   1 1960   1 1960   1 1960
  1 1960   1 1960   1 1960   1 1960   2 2450   2 2450   2 2450   2 2450
  2 2450   2 2450   2 2450   2 2450   2 2450   2 2450   3 2400   3 2400
  3 2400   3 2400   3 2400   3 2400   3 2400   3 2400   3 2400   3 2400
  4 2450   4 2450   4 2450   4 2450   4 2450   4 2450   4 2450   4 2450
  4 2450   4 2450   5 2500   5 2500   5 2500   5 2500   5 2500   5 2500
  5 2500   5 2500   5 2500   5 2500   6 2550   6 2550   6 2550   6 2550
  6 2550   6 2550   6 2550   6 2550   6 2550   6 2550   7 2600   7 2600
  7 2600   7 2600   7 2600   7 2600   7 2600   7 2600   7 2600   7 2600
  8 2100   8 2100   8 2100   8 2100   8 2100   8 2100   8 2100   8 2100
  8 2100   8 2100   9 1590   9 1590   9 1590   9 1590   9 1590   9 1590
  9 1590   9 1590   9 1590   9 1590}

do_execsql_test 1.7 {
  SELECT a, sum(b) OVER (
    ORDER BY a RANGE BETWEEN 2 PRECEDING AND 1 FOLLOWING
  ) FROM t3 ORDER BY 1;
} {0 1010   0 1010   0 1010   0 1010   0 1010   0 1010   0 1010   0 1010
  0 1010   0 1010   1 1480   1 1480   1 1480   1 1480   1 1480   1 1480
  1 1480   1 1480   1 1480   1 1480   2 1960   2 1960   2 1960   2 1960
  2 1960   2 1960   2 1960   2 1960   2 1960   2 1960   3 1900   3 1900
  3 1900   3 1900   3 1900   3 1900   3 1900   3 1900   3 1900   3 1900
  4 1940   4 1940   4 1940   4 1940   4 1940   4 1940   4 1940   4 1940
  4 1940   4 1940   5 1980   5 1980   5 1980   5 1980   5 1980   5 1980
  5 1980   5 1980   5 1980   5 1980   6 2020   6 2020   6 2020   6 2020
  6 2020   6 2020   6 2020   6 2020   6 2020   6 2020   7 2060   7 2060
  7 2060   7 2060   7 2060   7 2060   7 2060   7 2060   7 2060   7 2060
  8 2100   8 2100   8 2100   8 2100   8 2100   8 2100   8 2100   8 2100
  8 2100   8 2100   9 1590   9 1590   9 1590   9 1590   9 1590   9 1590
  9 1590   9 1590   9 1590   9 1590}

do_execsql_test 1.8.1 {
  SELECT a, sum(b) OVER (
    ORDER BY a RANGE BETWEEN 0 PRECEDING AND 1 FOLLOWING
  ) FROM t3 ORDER BY 1;
} {0 1010   0 1010   0 1010   0 1010   0 1010   0 1010   0 1010   0 1010
  0 1010   0 1010   1 930   1 930   1 930   1 930   1 930   1 930   1 930
  1 930   1 930   1 930   2 950   2 950   2 950   2 950   2 950   2 950
  2 950   2 950   2 950   2 950   3 970   3 970   3 970   3 970   3 970
  3 970   3 970   3 970   3 970   3 970   4 990   4 990   4 990   4 990
  4 990   4 990   4 990   4 990   4 990   4 990   5 1010   5 1010   5 1010
  5 1010   5 1010   5 1010   5 1010   5 1010   5 1010   5 1010   6 1030
  6 1030   6 1030   6 1030   6 1030   6 1030   6 1030   6 1030   6 1030
  6 1030   7 1050   7 1050   7 1050   7 1050   7 1050   7 1050   7 1050
  7 1050   7 1050   7 1050   8 1070   8 1070   8 1070   8 1070   8 1070
  8 1070   8 1070   8 1070   8 1070   8 1070   9 540   9 540   9 540   9 540
  9 540   9 540   9 540   9 540   9 540   9 540}

do_execsql_test 1.8.2 {
  SELECT a, sum(b) OVER (
    ORDER BY a DESC RANGE BETWEEN 0 PRECEDING AND 1 FOLLOWING
  ) FROM t3 ORDER BY 1;
} {0 550   0 550   0 550   0 550   0 550   0 550   0 550   0 550   0 550
  0 550   1 1010   1 1010   1 1010   1 1010   1 1010   1 1010   1 1010
  1 1010   1 1010   1 1010   2 930   2 930   2 930   2 930   2 930   2 930
  2 930   2 930   2 930   2 930   3 950   3 950   3 950   3 950   3 950
  3 950   3 950   3 950   3 950   3 950   4 970   4 970   4 970   4 970
  4 970   4 970   4 970   4 970   4 970   4 970   5 990   5 990   5 990
  5 990   5 990   5 990   5 990   5 990   5 990   5 990   6 1010   6 1010
  6 1010   6 1010   6 1010   6 1010   6 1010   6 1010   6 1010   6 1010
  7 1030   7 1030   7 1030   7 1030   7 1030   7 1030   7 1030   7 1030
  7 1030   7 1030   8 1050   8 1050   8 1050   8 1050   8 1050   8 1050
  8 1050   8 1050   8 1050   8 1050   9 1070   9 1070   9 1070   9 1070
  9 1070   9 1070   9 1070   9 1070   9 1070   9 1070}

finish_test

Added test/window8.tcl.
















































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2018 May 19
#
# 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.
#
#***********************************************************************
#

source [file join [file dirname $argv0] pg_common.tcl]

#=========================================================================

start_test window8 "2019 March 01"
ifcapable !windowfunc

execsql_test 1.0 {
  DROP TABLE IF EXISTS t3;
  CREATE TABLE t3(a TEXT, b TEXT, c INTEGER);
  INSERT INTO t3 VALUES
    ('HH', 'bb', 355), ('CC', 'aa', 158), ('BB', 'aa', 399), 
    ('FF', 'bb', 938), ('HH', 'aa', 480), ('FF', 'bb', 870), 
    ('JJ', 'aa', 768), ('JJ', 'aa', 899), ('GG', 'bb', 929), 
    ('II', 'bb', 421), ('GG', 'bb', 844), ('FF', 'bb', 574), 
    ('CC', 'bb', 822), ('GG', 'bb', 938), ('BB', 'aa', 660), 
    ('HH', 'aa', 979), ('BB', 'bb', 792), ('DD', 'aa', 845), 
    ('JJ', 'bb', 354), ('FF', 'bb', 295), ('JJ', 'aa', 234), 
    ('BB', 'bb', 840), ('AA', 'aa', 934), ('EE', 'aa', 113), 
    ('AA', 'bb', 309), ('BB', 'aa', 412), ('AA', 'aa', 911), 
    ('AA', 'bb', 572), ('II', 'aa', 398), ('II', 'bb', 250), 
    ('II', 'aa', 652), ('BB', 'bb', 633), ('AA', 'aa', 239), 
    ('FF', 'aa', 670), ('BB', 'bb', 705), ('HH', 'bb', 963), 
    ('CC', 'bb', 346), ('II', 'bb', 671), ('BB', 'aa', 247), 
    ('AA', 'aa', 223), ('GG', 'aa', 480), ('HH', 'aa', 790), 
    ('FF', 'aa', 208), ('BB', 'bb', 711), ('EE', 'aa', 777), 
    ('DD', 'bb', 716), ('CC', 'aa', 759), ('CC', 'aa', 430), 
    ('CC', 'aa', 607), ('DD', 'bb', 794), ('GG', 'aa', 148), 
    ('GG', 'aa', 634), ('JJ', 'bb', 257), ('DD', 'bb', 959), 
    ('FF', 'bb', 726), ('BB', 'aa', 762), ('JJ', 'bb', 336), 
    ('GG', 'aa', 335), ('HH', 'bb', 330), ('GG', 'bb', 160), 
    ('JJ', 'bb', 839), ('FF', 'aa', 618), ('BB', 'aa', 393), 
    ('EE', 'bb', 629), ('FF', 'aa', 667), ('AA', 'bb', 870), 
    ('FF', 'bb', 102), ('JJ', 'aa', 113), ('DD', 'aa', 224), 
    ('AA', 'bb', 627), ('HH', 'bb', 730), ('II', 'bb', 443), 
    ('HH', 'bb', 133), ('EE', 'bb', 252), ('II', 'bb', 805), 
    ('BB', 'bb', 786), ('EE', 'bb', 768), ('HH', 'bb', 683), 
    ('DD', 'bb', 238), ('DD', 'aa', 256);
}

foreach {tn frame} {
  1  { GROUPS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING }
  2  { GROUPS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW }
  3  { GROUPS BETWEEN UNBOUNDED PRECEDING AND 1 FOLLOWING }
  4  { GROUPS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING }
  5  { GROUPS BETWEEN 1 PRECEDING         AND 2 PRECEDING }
  6  { GROUPS BETWEEN 2 PRECEDING         AND 1 PRECEDING }
  7  { GROUPS BETWEEN 3 PRECEDING         AND 1 PRECEDING }
  8  { GROUPS BETWEEN 3 PRECEDING         AND 0 PRECEDING }
  9  { GROUPS BETWEEN 2 PRECEDING         AND CURRENT ROW }
  10 { GROUPS BETWEEN 3 PRECEDING         AND 0 FOLLOWING }
  11 { GROUPS BETWEEN 2 PRECEDING         AND UNBOUNDED FOLLOWING }
  12 { GROUPS BETWEEN CURRENT ROW         AND 0 FOLLOWING }
  13 { GROUPS BETWEEN CURRENT ROW         AND 1 FOLLOWING }
  14 { GROUPS BETWEEN CURRENT ROW         AND 100 FOLLOWING }
  15 { GROUPS BETWEEN CURRENT ROW         AND UNBOUNDED FOLLOWING }
  16 { GROUPS BETWEEN 0 FOLLOWING         AND 0 FOLLOWING }
  17 { GROUPS BETWEEN 1 FOLLOWING         AND 0 FOLLOWING }
  18 { GROUPS BETWEEN 1 FOLLOWING         AND 5 FOLLOWING }
  19 { GROUPS BETWEEN 1 FOLLOWING         AND UNBOUNDED FOLLOWING }

} {
  execsql_test 1.$tn.1 "
    SELECT a, b, sum(c) OVER (ORDER BY a $frame) FROM t3 ORDER BY 1, 2, 3;
  "
  execsql_test 1.$tn.2 "
    SELECT a, b, sum(c) OVER (ORDER BY a,b $frame) FROM t3 ORDER BY 1, 2, 3;
  "
  execsql_test 1.$tn.3 "
    SELECT a, b, rank() OVER (ORDER BY a $frame) FROM t3 ORDER BY 1, 2, 3;
  "
  execsql_test 1.$tn.4 "
    SELECT a, b, max(c) OVER (ORDER BY a,b $frame) FROM t3 ORDER BY 1, 2, 3;
  "
  execsql_test 1.$tn.5 "
    SELECT a, b, min(c) OVER (ORDER BY a,b $frame) FROM t3 ORDER BY 1, 2, 3;
  "

  set f2 "$frame EXCLUDE CURRENT ROW"

  execsql_test 1.$tn.6 "
    SELECT a, b, sum(c) OVER (ORDER BY a $f2) FROM t3 ORDER BY 1, 2, 3;
  "
  execsql_test 1.$tn.7 "
    SELECT a, b, sum(c) OVER (ORDER BY a,b $f2) FROM t3 ORDER BY 1, 2, 3;
  "

  execsql_test 1.$tn.8 "
    SELECT a, b, 
      sum(c) OVER (ORDER BY a $f2),
      sum(c) OVER (ORDER BY a $frame),
      sum(c) OVER (ORDER BY a,b $f2),
      sum(c) OVER (ORDER BY a,b $frame)
    FROM t3 ORDER BY 1, 2, 3;
  "
}


foreach {tn ex} {
  1  { EXCLUDE NO OTHERS }
  2  { EXCLUDE CURRENT ROW }
  3  { EXCLUDE GROUP }
  4  { EXCLUDE TIES }
} {
  execsql_test 2.$tn.1 "
    SELECT row_number() OVER win 
    FROM t3
    WINDOW win AS (
      ORDER BY c, b, a
      ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING $ex
    )
  "

  execsql_test 2.$tn.2 "
    SELECT nth_value(c, 14) OVER win 
    FROM t3
    WINDOW win AS (
      ORDER BY c, b, a
      ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING $ex
    )
  "

  execsql_test 2.$tn.3 "
    SELECT min(c) OVER win, max(c) OVER win, sum(c) OVER win FROM t3
    WINDOW win AS (
      ORDER BY c, b, a
      ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW $ex
    ) ORDER BY a, b, c;
  "
}

==========

execsql_test 3.0 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a REAL, b INTEGER);
  INSERT INTO t1 VALUES
      (5, 10), (10, 20), (13, 26), (13, 26), 
      (15, 30), (20, 40), (22,80), (30, 90);
}

foreach {tn frame} {
  1 { ORDER BY a RANGE BETWEEN 5 PRECEDING AND 5 FOLLOWING }
  2 { ORDER BY a RANGE BETWEEN 10 PRECEDING AND 5 PRECEDING }
  3 { ORDER BY a RANGE BETWEEN 2 FOLLOWING AND 3 FOLLOWING }
  4 { ORDER BY a DESC RANGE BETWEEN 5 PRECEDING AND 5 FOLLOWING }
  5 { ORDER BY a DESC RANGE BETWEEN 10 PRECEDING AND 5 PRECEDING }
  6 { ORDER BY a DESC RANGE BETWEEN 2 FOLLOWING AND 3 FOLLOWING }

  7  { ORDER BY a RANGE BETWEEN 5.1 PRECEDING AND 5.3 FOLLOWING }
  8  { ORDER BY a RANGE BETWEEN 10.2 PRECEDING AND 5.4 PRECEDING }
  9  { ORDER BY a RANGE BETWEEN 2.6 FOLLOWING AND 3.5 FOLLOWING }
  10 { ORDER BY a DESC RANGE BETWEEN 5.7 PRECEDING AND 5.8 FOLLOWING }
  11 { ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND 5.9 PRECEDING }
  12 { ORDER BY a DESC RANGE BETWEEN 2.1 FOLLOWING AND UNBOUNDED FOLLOWING }
  13  { ORDER BY a RANGE 5.1 PRECEDING }
} {
  execsql_test 3.$tn "
    SELECT CAST(a AS INTEGER), sum(b) OVER win FROM t1 WINDOW win AS ($frame)
  "
}

==========

execsql_test 4.0 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a INTEGER, b INTEGER);
  INSERT INTO t1 VALUES
    (NULL, 1), (NULL, 2), (NULL, 3), (10, 4), (10, 5);
}

execsql_test 4.1.1 {
  SELECT sum(b) OVER (
    ORDER BY a RANGE BETWEEN 5 PRECEDING AND 10 FOLLOWING
  ) FROM t1 ORDER BY 1;
}
execsql_test 4.1.2 {
  SELECT sum(b) OVER (
    ORDER BY a DESC RANGE BETWEEN 5 PRECEDING AND 10 FOLLOWING
  ) FROM t1 ORDER BY 1;
}

execsql_test 4.2.1 {
  SELECT sum(b) OVER (
    ORDER BY a RANGE BETWEEN 5 FOLLOWING AND 10 FOLLOWING
  ) FROM t1 ORDER BY 1 NULLS FIRST;
}
execsql_test 4.2.2 {
  SELECT sum(b) OVER (
    ORDER BY a RANGE BETWEEN 5 FOLLOWING AND 10 FOLLOWING
  ) FROM t1 ORDER BY 1 NULLS LAST;
}

execsql_test 4.2.3 {
  SELECT sum(b) OVER (
    ORDER BY a DESC RANGE BETWEEN 5 FOLLOWING AND 10 FOLLOWING
  ) FROM t1 ORDER BY 1 NULLS FIRST;
}
execsql_test 4.2.4 {
  SELECT sum(b) OVER (
    ORDER BY a DESC RANGE BETWEEN 5 FOLLOWING AND 10 FOLLOWING
  ) FROM t1 ORDER BY 1 NULLS LAST;
}

execsql_test 4.3.1 {
  SELECT sum(b) OVER (
    ORDER BY a NULLS FIRST RANGE BETWEEN UNBOUNDED PRECEDING AND 10 FOLLOWING
  ) FROM t1 ORDER BY 1 NULLS FIRST;
}
execsql_test 4.3.2 {
  SELECT sum(b) OVER (
    ORDER BY a NULLS LAST RANGE BETWEEN UNBOUNDED PRECEDING AND 10 FOLLOWING
  ) FROM t1 ORDER BY 1 NULLS LAST;
}

execsql_test 4.4.1 {
  SELECT sum(b) OVER (
    ORDER BY a NULLS FIRST ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING
  ) FROM t1 ORDER BY 1 NULLS FIRST;
}
execsql_test 4.4.2 {
  SELECT sum(b) OVER (
    ORDER BY a NULLS LAST ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING
  ) FROM t1 ORDER BY 1 NULLS LAST;
}

execsql_test 4.4.3 {
  SELECT sum(b) OVER (
    ORDER BY a DESC NULLS LAST ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING
  ) FROM t1 ORDER BY 1 NULLS FIRST;
}
execsql_test 4.4.4 {
  SELECT sum(b) OVER (
    ORDER BY a DESC NULLS LAST ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING
  ) FROM t1 ORDER BY 1 NULLS LAST;
}

execsql_test 4.5.1 {
  SELECT sum(b) OVER (
    ORDER BY a ASC  NULLS LAST RANGE BETWEEN UNBOUNDED PRECEDING AND 10 FOLLOWING
  ) FROM t1 ORDER BY 1 NULLS LAST;
}
execsql_test 4.5.2 {
  SELECT sum(b) OVER (
    ORDER BY a DESC NULLS FIRST RANGE 
    BETWEEN UNBOUNDED PRECEDING AND 10 FOLLOWING
  ) FROM t1 ORDER BY 1 NULLS LAST;
}

==========

execsql_test 5.0 {
  INSERT INTO t3 VALUES
    (NULL, 'bb', 355), (NULL, 'cc', 158), (NULL, 'aa', 399), 
    ('JJ', NULL, 839), ('FF', NULL, 618), ('BB', NULL, 393), 
    (NULL, 'bb', 629), (NULL, NULL, 667), (NULL, NULL, 870);
}

foreach {tn ex} {
  1  { EXCLUDE NO OTHERS }
  2  { EXCLUDE CURRENT ROW }
  3  { EXCLUDE GROUP }
  4  { EXCLUDE TIES }
} {
  foreach {tn2 frame} {
    1 { RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING }
    2 { ORDER BY a NULLS FIRST 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING }
    3 { PARTITION BY coalesce(a, '') 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING }
    4 { ORDER BY a NULLS FIRST GROUPS 6 PRECEDING }
    5 { ORDER BY c NULLS FIRST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING }
    6 { ORDER BY c NULLS FIRST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING }
    7 { ORDER BY c NULLS FIRST, b NULLS FIRST, a NULLS FIRST
        ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING }

    8 { RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING }
    9 { ORDER BY a NULLS LAST 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING }
   10 { PARTITION BY coalesce(a, '') 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING }
   11 { ORDER BY a NULLS LAST GROUPS 6 PRECEDING }
   12 { ORDER BY c NULLS LAST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING }
   13 { ORDER BY c NULLS LAST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING }
   14 { ORDER BY c NULLS LAST, b NULLS LAST, a NULLS LAST
        ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING }
  } {
    execsql_test 5.$tn.$tn2.1 "
      SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS ( $frame $ex )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
    "

    execsql_test 5.$tn.$tn2.2 "
      SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS ( $frame $ex )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
    "
  }
}

==========

execsql_test 6.0 {
  DROP TABLE IF EXISTS t2;
  CREATE TABLE t2(a TEXT, b INTEGER);
  INSERT INTO t2 VALUES('A', NULL);
  INSERT INTO t2 VALUES('B', NULL);
  INSERT INTO t2 VALUES('C', 1);
}

execsql_test 6.1 {
  SELECT string_agg(a, '.') OVER (
    ORDER BY b NULLS FIRST RANGE BETWEEN 7 PRECEDING AND 2 PRECEDING
  )
  FROM t2
}

execsql_test 6.2 {
  SELECT string_agg(a, '.') OVER (
    ORDER BY b DESC NULLS LAST RANGE BETWEEN 7 PRECEDING AND 2 PRECEDING
  )
  FROM t2
}

==========

execsql_test 7.0 {
  DROP TABLE IF EXISTS t2;
  CREATE TABLE t2(a INTEGER, b INTEGER);

  INSERT INTO t2 VALUES(1, 65);
  INSERT INTO t2 VALUES(2, NULL);
  INSERT INTO t2 VALUES(3, NULL);
  INSERT INTO t2 VALUES(4, NULL);
  INSERT INTO t2 VALUES(5, 66);
  INSERT INTO t2 VALUES(6, 67);
}

foreach {tn f ex} {
  1 sum ""
  2 min ""
  3 sum "EXCLUDE CURRENT ROW"
  4 max "EXCLUDE CURRENT ROW"
} {
execsql_test 7.$tn.1 "
  SELECT $f (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS LAST RANGE BETWEEN 6 FOLLOWING AND UNBOUNDED FOLLOWING
  );
"
execsql_test 7.$tn.2 "
  SELECT $f (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS LAST RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING
  );
"
execsql_test 7.$tn.3 "
  SELECT $f (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS LAST RANGE BETWEEN 2 FOLLOWING AND 1 FOLLOWING
  );
"
execsql_test 7.$tn.4 "
  SELECT $f (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS FIRST RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING
  );
"
execsql_test 7.$tn.5 "
  SELECT $f (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS FIRST RANGE BETWEEN 2 FOLLOWING AND 1 FOLLOWING
  );
"

execsql_test 7.$tn.6 "
  SELECT $f (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS LAST RANGE BETWEEN 1000 PRECEDING AND 2 PRECEDING
  );
"
execsql_test 7.$tn.7 "
  SELECT $f (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS LAST RANGE BETWEEN 2000 FOLLOWING AND 1000 FOLLOWING
  );
"
execsql_test 7.$tn.8 "
  SELECT $f (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS FIRST RANGE BETWEEN 1000 PRECEDING AND 2000 PRECEDING
  );
"
execsql_test 7.$tn.9 "
  SELECT $f (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS FIRST RANGE BETWEEN 2000 FOLLOWING AND 1000 FOLLOWING
  );
"
}

==========

execsql_test 8.0 {
  DROP TABLE IF EXISTS tx;
  CREATE TABLE tx(a INTEGER PRIMARY KEY);
  INSERT INTO tx VALUES(1), (2), (3), (4), (5), (6);

  DROP TABLE IF EXISTS map;
  CREATE TABLE map(v INTEGER PRIMARY KEY, t TEXT);
  INSERT INTO map VALUES
    (1, 'odd'), (2, 'even'), (3, 'odd'), 
    (4, 'even'), (5, 'odd'), (6, 'even');
}

execsql_test 8.1 {
  SELECT sum(a) OVER (
    PARTITION BY (
      SELECT t FROM map WHERE v=a
    ) ORDER BY a
  ) FROM tx;
}

execsql_test 8.2 {
  SELECT sum(a) OVER win FROM tx
  WINDOW win AS (
    PARTITION BY (
      SELECT t FROM map WHERE v=a
    ) ORDER BY a
  );
}

execsql_test 8.3 {
  WITH map2 AS (
    SELECT * FROM map
  )
  SELECT sum(a) OVER (
    PARTITION BY (
      SELECT t FROM map2 WHERE v=a
    ) ORDER BY a
  ) FROM tx;
}

execsql_test 8.4 {
  WITH map2 AS (
    SELECT * FROM map
  )
  SELECT sum(a) OVER win FROM tx
  WINDOW win AS (
    PARTITION BY (
      SELECT t FROM map2 WHERE v=a
    ) ORDER BY a
  );
}

==========

execsql_test 9.1 {
  DROP TABLE IF EXISTS t1;
  DROP TABLE IF EXISTS t2;
  CREATE TABLE t1(a INTEGER);
  CREATE TABLE t2(y INTEGER);
}

execsql_test 9.2 {
  SELECT (
    SELECT max(a) OVER ( ORDER BY (SELECT sum(a) FROM t1) )
         + min(a) OVER() 
  )
  FROM t1
}


finish_test


Added test/window8.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
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
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
900
901
902
903
904
905
906
907
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
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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
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
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
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
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
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
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
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
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
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
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
1984
1985
1986
1987
1988
1989
1990
1991
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
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
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
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
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
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
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
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
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
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
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
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
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
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
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
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
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
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
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
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
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
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
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
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
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
4360
4361
4362
4363
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
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
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
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
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
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
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
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
6457
6458
6459
6460
6461
6462
6463
6464
6465
6466
6467
6468
6469
6470
6471
6472
6473
6474
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485
6486
6487
6488
6489
6490
6491
6492
6493
6494
6495
6496
6497
6498
6499
6500
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516
6517
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019 March 01
#
# 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.
#

####################################################
# DO NOT EDIT! THIS FILE IS AUTOMATICALLY GENERATED!
####################################################

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix window8

ifcapable !windowfunc { finish_test ; return }
do_execsql_test 1.0 {
  DROP TABLE IF EXISTS t3;
  CREATE TABLE t3(a TEXT, b TEXT, c INTEGER);
  INSERT INTO t3 VALUES
    ('HH', 'bb', 355), ('CC', 'aa', 158), ('BB', 'aa', 399), 
    ('FF', 'bb', 938), ('HH', 'aa', 480), ('FF', 'bb', 870), 
    ('JJ', 'aa', 768), ('JJ', 'aa', 899), ('GG', 'bb', 929), 
    ('II', 'bb', 421), ('GG', 'bb', 844), ('FF', 'bb', 574), 
    ('CC', 'bb', 822), ('GG', 'bb', 938), ('BB', 'aa', 660), 
    ('HH', 'aa', 979), ('BB', 'bb', 792), ('DD', 'aa', 845), 
    ('JJ', 'bb', 354), ('FF', 'bb', 295), ('JJ', 'aa', 234), 
    ('BB', 'bb', 840), ('AA', 'aa', 934), ('EE', 'aa', 113), 
    ('AA', 'bb', 309), ('BB', 'aa', 412), ('AA', 'aa', 911), 
    ('AA', 'bb', 572), ('II', 'aa', 398), ('II', 'bb', 250), 
    ('II', 'aa', 652), ('BB', 'bb', 633), ('AA', 'aa', 239), 
    ('FF', 'aa', 670), ('BB', 'bb', 705), ('HH', 'bb', 963), 
    ('CC', 'bb', 346), ('II', 'bb', 671), ('BB', 'aa', 247), 
    ('AA', 'aa', 223), ('GG', 'aa', 480), ('HH', 'aa', 790), 
    ('FF', 'aa', 208), ('BB', 'bb', 711), ('EE', 'aa', 777), 
    ('DD', 'bb', 716), ('CC', 'aa', 759), ('CC', 'aa', 430), 
    ('CC', 'aa', 607), ('DD', 'bb', 794), ('GG', 'aa', 148), 
    ('GG', 'aa', 634), ('JJ', 'bb', 257), ('DD', 'bb', 959), 
    ('FF', 'bb', 726), ('BB', 'aa', 762), ('JJ', 'bb', 336), 
    ('GG', 'aa', 335), ('HH', 'bb', 330), ('GG', 'bb', 160), 
    ('JJ', 'bb', 839), ('FF', 'aa', 618), ('BB', 'aa', 393), 
    ('EE', 'bb', 629), ('FF', 'aa', 667), ('AA', 'bb', 870), 
    ('FF', 'bb', 102), ('JJ', 'aa', 113), ('DD', 'aa', 224), 
    ('AA', 'bb', 627), ('HH', 'bb', 730), ('II', 'bb', 443), 
    ('HH', 'bb', 133), ('EE', 'bb', 252), ('II', 'bb', 805), 
    ('BB', 'bb', 786), ('EE', 'bb', 768), ('HH', 'bb', 683), 
    ('DD', 'bb', 238), ('DD', 'aa', 256);
} {}

do_execsql_test 1.1.1 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa {}   AA aa {}   AA aa {}   AA aa {}   AA bb {}   AA bb {}   AA bb {}
  AA bb {}   BB aa 4685   BB aa 4685   BB aa 4685   BB aa 4685   BB aa 4685
  BB aa 4685   BB bb 4685   BB bb 4685   BB bb 4685   BB bb 4685   BB bb 4685
  BB bb 4685   CC aa 12025   CC aa 12025   CC aa 12025   CC aa 12025
  CC bb 12025   CC bb 12025   DD aa 15147   DD aa 15147   DD aa 15147
  DD bb 15147   DD bb 15147   DD bb 15147   DD bb 15147   EE aa 19179
  EE aa 19179   EE bb 19179   EE bb 19179   EE bb 19179   FF aa 21718
  FF aa 21718   FF aa 21718   FF aa 21718   FF bb 21718   FF bb 21718
  FF bb 21718   FF bb 21718   FF bb 21718   FF bb 21718   GG aa 27386
  GG aa 27386   GG aa 27386   GG aa 27386   GG bb 27386   GG bb 27386
  GG bb 27386   GG bb 27386   HH aa 31854   HH aa 31854   HH aa 31854
  HH bb 31854   HH bb 31854   HH bb 31854   HH bb 31854   HH bb 31854
  HH bb 31854   II aa 37297   II aa 37297   II bb 37297   II bb 37297
  II bb 37297   II bb 37297   II bb 37297   JJ aa 40937   JJ aa 40937
  JJ aa 40937   JJ aa 40937   JJ bb 40937   JJ bb 40937   JJ bb 40937
  JJ bb 40937}

do_execsql_test 1.1.2 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa {}   AA aa {}   AA aa {}   AA aa {}   AA bb 2307   AA bb 2307
  AA bb 2307   AA bb 2307   BB aa 4685   BB aa 4685   BB aa 4685   BB aa 4685
  BB aa 4685   BB aa 4685   BB bb 7558   BB bb 7558   BB bb 7558   BB bb 7558
  BB bb 7558   BB bb 7558   CC aa 12025   CC aa 12025   CC aa 12025
  CC aa 12025   CC bb 13979   CC bb 13979   DD aa 15147   DD aa 15147
  DD aa 15147   DD bb 16472   DD bb 16472   DD bb 16472   DD bb 16472
  EE aa 19179   EE aa 19179   EE bb 20069   EE bb 20069   EE bb 20069
  FF aa 21718   FF aa 21718   FF aa 21718   FF aa 21718   FF bb 23881
  FF bb 23881   FF bb 23881   FF bb 23881   FF bb 23881   FF bb 23881
  GG aa 27386   GG aa 27386   GG aa 27386   GG aa 27386   GG bb 28983
  GG bb 28983   GG bb 28983   GG bb 28983   HH aa 31854   HH aa 31854
  HH aa 31854   HH bb 34103   HH bb 34103   HH bb 34103   HH bb 34103
  HH bb 34103   HH bb 34103   II aa 37297   II aa 37297   II bb 38347
  II bb 38347   II bb 38347   II bb 38347   II bb 38347   JJ aa 40937
  JJ aa 40937   JJ aa 40937   JJ aa 40937   JJ bb 42951   JJ bb 42951
  JJ bb 42951   JJ bb 42951}

do_execsql_test 1.1.3 {
  SELECT a, b, rank() OVER (ORDER BY a  GROUPS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 1   AA aa 1   AA aa 1   AA aa 1   AA bb 1   AA bb 1   AA bb 1
  AA bb 1   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9
  BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   CC aa 21
  CC aa 21   CC aa 21   CC aa 21   CC bb 21   CC bb 21   DD aa 27   DD aa 27
  DD aa 27   DD bb 27   DD bb 27   DD bb 27   DD bb 27   EE aa 34   EE aa 34
  EE bb 34   EE bb 34   EE bb 34   FF aa 39   FF aa 39   FF aa 39   FF aa 39
  FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   GG aa 49
  GG aa 49   GG aa 49   GG aa 49   GG bb 49   GG bb 49   GG bb 49   GG bb 49
  HH aa 57   HH aa 57   HH aa 57   HH bb 57   HH bb 57   HH bb 57   HH bb 57
  HH bb 57   HH bb 57   II aa 66   II aa 66   II bb 66   II bb 66   II bb 66
  II bb 66   II bb 66   JJ aa 73   JJ aa 73   JJ aa 73   JJ aa 73   JJ bb 73
  JJ bb 73   JJ bb 73   JJ bb 73}

do_execsql_test 1.1.4 {
  SELECT a, b, max(c) OVER (ORDER BY a,b  GROUPS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa {}   AA aa {}   AA aa {}   AA aa {}   AA bb 934   AA bb 934
  AA bb 934   AA bb 934   BB aa 934   BB aa 934   BB aa 934   BB aa 934
  BB aa 934   BB aa 934   BB bb 934   BB bb 934   BB bb 934   BB bb 934
  BB bb 934   BB bb 934   CC aa 934   CC aa 934   CC aa 934   CC aa 934
  CC bb 934   CC bb 934   DD aa 934   DD aa 934   DD aa 934   DD bb 934
  DD bb 934   DD bb 934   DD bb 934   EE aa 959   EE aa 959   EE bb 959
  EE bb 959   EE bb 959   FF aa 959   FF aa 959   FF aa 959   FF aa 959
  FF bb 959   FF bb 959   FF bb 959   FF bb 959   FF bb 959   FF bb 959
  GG aa 959   GG aa 959   GG aa 959   GG aa 959   GG bb 959   GG bb 959
  GG bb 959   GG bb 959   HH aa 959   HH aa 959   HH aa 959   HH bb 979
  HH bb 979   HH bb 979   HH bb 979   HH bb 979   HH bb 979   II aa 979
  II aa 979   II bb 979   II bb 979   II bb 979   II bb 979   II bb 979
  JJ aa 979   JJ aa 979   JJ aa 979   JJ aa 979   JJ bb 979   JJ bb 979
  JJ bb 979   JJ bb 979}

do_execsql_test 1.1.5 {
  SELECT a, b, min(c) OVER (ORDER BY a,b  GROUPS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa {}   AA aa {}   AA aa {}   AA aa {}   AA bb 223   AA bb 223
  AA bb 223   AA bb 223   BB aa 223   BB aa 223   BB aa 223   BB aa 223
  BB aa 223   BB aa 223   BB bb 223   BB bb 223   BB bb 223   BB bb 223
  BB bb 223   BB bb 223   CC aa 223   CC aa 223   CC aa 223   CC aa 223
  CC bb 158   CC bb 158   DD aa 158   DD aa 158   DD aa 158   DD bb 158
  DD bb 158   DD bb 158   DD bb 158   EE aa 158   EE aa 158   EE bb 113
  EE bb 113   EE bb 113   FF aa 113   FF aa 113   FF aa 113   FF aa 113
  FF bb 113   FF bb 113   FF bb 113   FF bb 113   FF bb 113   FF bb 113
  GG aa 102   GG aa 102   GG aa 102   GG aa 102   GG bb 102   GG bb 102
  GG bb 102   GG bb 102   HH aa 102   HH aa 102   HH aa 102   HH bb 102
  HH bb 102   HH bb 102   HH bb 102   HH bb 102   HH bb 102   II aa 102
  II aa 102   II bb 102   II bb 102   II bb 102   II bb 102   II bb 102
  JJ aa 102   JJ aa 102   JJ aa 102   JJ aa 102   JJ bb 102   JJ bb 102
  JJ bb 102   JJ bb 102}

do_execsql_test 1.1.6 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa {}   AA aa {}   AA aa {}   AA aa {}   AA bb {}   AA bb {}   AA bb {}
  AA bb {}   BB aa 4685   BB aa 4685   BB aa 4685   BB aa 4685   BB aa 4685
  BB aa 4685   BB bb 4685   BB bb 4685   BB bb 4685   BB bb 4685   BB bb 4685
  BB bb 4685   CC aa 12025   CC aa 12025   CC aa 12025   CC aa 12025
  CC bb 12025   CC bb 12025   DD aa 15147   DD aa 15147   DD aa 15147
  DD bb 15147   DD bb 15147   DD bb 15147   DD bb 15147   EE aa 19179
  EE aa 19179   EE bb 19179   EE bb 19179   EE bb 19179   FF aa 21718
  FF aa 21718   FF aa 21718   FF aa 21718   FF bb 21718   FF bb 21718
  FF bb 21718   FF bb 21718   FF bb 21718   FF bb 21718   GG aa 27386
  GG aa 27386   GG aa 27386   GG aa 27386   GG bb 27386   GG bb 27386
  GG bb 27386   GG bb 27386   HH aa 31854   HH aa 31854   HH aa 31854
  HH bb 31854   HH bb 31854   HH bb 31854   HH bb 31854   HH bb 31854
  HH bb 31854   II aa 37297   II aa 37297   II bb 37297   II bb 37297
  II bb 37297   II bb 37297   II bb 37297   JJ aa 40937   JJ aa 40937
  JJ aa 40937   JJ aa 40937   JJ bb 40937   JJ bb 40937   JJ bb 40937
  JJ bb 40937}

do_execsql_test 1.1.7 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa {}   AA aa {}   AA aa {}   AA aa {}   AA bb 2307   AA bb 2307
  AA bb 2307   AA bb 2307   BB aa 4685   BB aa 4685   BB aa 4685   BB aa 4685
  BB aa 4685   BB aa 4685   BB bb 7558   BB bb 7558   BB bb 7558   BB bb 7558
  BB bb 7558   BB bb 7558   CC aa 12025   CC aa 12025   CC aa 12025
  CC aa 12025   CC bb 13979   CC bb 13979   DD aa 15147   DD aa 15147
  DD aa 15147   DD bb 16472   DD bb 16472   DD bb 16472   DD bb 16472
  EE aa 19179   EE aa 19179   EE bb 20069   EE bb 20069   EE bb 20069
  FF aa 21718   FF aa 21718   FF aa 21718   FF aa 21718   FF bb 23881
  FF bb 23881   FF bb 23881   FF bb 23881   FF bb 23881   FF bb 23881
  GG aa 27386   GG aa 27386   GG aa 27386   GG aa 27386   GG bb 28983
  GG bb 28983   GG bb 28983   GG bb 28983   HH aa 31854   HH aa 31854
  HH aa 31854   HH bb 34103   HH bb 34103   HH bb 34103   HH bb 34103
  HH bb 34103   HH bb 34103   II aa 37297   II aa 37297   II bb 38347
  II bb 38347   II bb 38347   II bb 38347   II bb 38347   JJ aa 40937
  JJ aa 40937   JJ aa 40937   JJ aa 40937   JJ bb 42951   JJ bb 42951
  JJ bb 42951   JJ bb 42951}

do_execsql_test 1.1.8 {
  SELECT a, b, 
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING ),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING )
    FROM t3 ORDER BY 1, 2, 3;
} {AA aa {} {} {} {}   AA aa {} {} {} {}   AA aa {} {} {} {}
  AA aa {} {} {} {}   AA bb {} {} 2307 2307   AA bb {} {} 2307 2307
  AA bb {} {} 2307 2307   AA bb {} {} 2307 2307   BB aa 4685 4685 4685 4685
  BB aa 4685 4685 4685 4685   BB aa 4685 4685 4685 4685
  BB aa 4685 4685 4685 4685   BB aa 4685 4685 4685 4685
  BB aa 4685 4685 4685 4685   BB bb 4685 4685 7558 7558
  BB bb 4685 4685 7558 7558   BB bb 4685 4685 7558 7558
  BB bb 4685 4685 7558 7558   BB bb 4685 4685 7558 7558
  BB bb 4685 4685 7558 7558   CC aa 12025 12025 12025 12025
  CC aa 12025 12025 12025 12025   CC aa 12025 12025 12025 12025
  CC aa 12025 12025 12025 12025   CC bb 12025 12025 13979 13979
  CC bb 12025 12025 13979 13979   DD aa 15147 15147 15147 15147
  DD aa 15147 15147 15147 15147   DD aa 15147 15147 15147 15147
  DD bb 15147 15147 16472 16472   DD bb 15147 15147 16472 16472
  DD bb 15147 15147 16472 16472   DD bb 15147 15147 16472 16472
  EE aa 19179 19179 19179 19179   EE aa 19179 19179 19179 19179
  EE bb 19179 19179 20069 20069   EE bb 19179 19179 20069 20069
  EE bb 19179 19179 20069 20069   FF aa 21718 21718 21718 21718
  FF aa 21718 21718 21718 21718   FF aa 21718 21718 21718 21718
  FF aa 21718 21718 21718 21718   FF bb 21718 21718 23881 23881
  FF bb 21718 21718 23881 23881   FF bb 21718 21718 23881 23881
  FF bb 21718 21718 23881 23881   FF bb 21718 21718 23881 23881
  FF bb 21718 21718 23881 23881   GG aa 27386 27386 27386 27386
  GG aa 27386 27386 27386 27386   GG aa 27386 27386 27386 27386
  GG aa 27386 27386 27386 27386   GG bb 27386 27386 28983 28983
  GG bb 27386 27386 28983 28983   GG bb 27386 27386 28983 28983
  GG bb 27386 27386 28983 28983   HH aa 31854 31854 31854 31854
  HH aa 31854 31854 31854 31854   HH aa 31854 31854 31854 31854
  HH bb 31854 31854 34103 34103   HH bb 31854 31854 34103 34103
  HH bb 31854 31854 34103 34103   HH bb 31854 31854 34103 34103
  HH bb 31854 31854 34103 34103   HH bb 31854 31854 34103 34103
  II aa 37297 37297 37297 37297   II aa 37297 37297 37297 37297
  II bb 37297 37297 38347 38347   II bb 37297 37297 38347 38347
  II bb 37297 37297 38347 38347   II bb 37297 37297 38347 38347
  II bb 37297 37297 38347 38347   JJ aa 40937 40937 40937 40937
  JJ aa 40937 40937 40937 40937   JJ aa 40937 40937 40937 40937
  JJ aa 40937 40937 40937 40937   JJ bb 40937 40937 42951 42951
  JJ bb 40937 40937 42951 42951   JJ bb 40937 40937 42951 42951
  JJ bb 40937 40937 42951 42951}

do_execsql_test 1.2.1 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 4685   AA aa 4685   AA aa 4685   AA aa 4685   AA bb 4685   AA bb 4685
  AA bb 4685   AA bb 4685   BB aa 12025   BB aa 12025   BB aa 12025
  BB aa 12025   BB aa 12025   BB aa 12025   BB bb 12025   BB bb 12025
  BB bb 12025   BB bb 12025   BB bb 12025   BB bb 12025   CC aa 15147
  CC aa 15147   CC aa 15147   CC aa 15147   CC bb 15147   CC bb 15147
  DD aa 19179   DD aa 19179   DD aa 19179   DD bb 19179   DD bb 19179
  DD bb 19179   DD bb 19179   EE aa 21718   EE aa 21718   EE bb 21718
  EE bb 21718   EE bb 21718   FF aa 27386   FF aa 27386   FF aa 27386
  FF aa 27386   FF bb 27386   FF bb 27386   FF bb 27386   FF bb 27386
  FF bb 27386   FF bb 27386   GG aa 31854   GG aa 31854   GG aa 31854
  GG aa 31854   GG bb 31854   GG bb 31854   GG bb 31854   GG bb 31854
  HH aa 37297   HH aa 37297   HH aa 37297   HH bb 37297   HH bb 37297
  HH bb 37297   HH bb 37297   HH bb 37297   HH bb 37297   II aa 40937
  II aa 40937   II bb 40937   II bb 40937   II bb 40937   II bb 40937
  II bb 40937   JJ aa 44737   JJ aa 44737   JJ aa 44737   JJ aa 44737
  JJ bb 44737   JJ bb 44737   JJ bb 44737   JJ bb 44737}

do_execsql_test 1.2.2 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 2307   AA aa 2307   AA aa 2307   AA aa 2307   AA bb 4685   AA bb 4685
  AA bb 4685   AA bb 4685   BB aa 7558   BB aa 7558   BB aa 7558   BB aa 7558
  BB aa 7558   BB aa 7558   BB bb 12025   BB bb 12025   BB bb 12025
  BB bb 12025   BB bb 12025   BB bb 12025   CC aa 13979   CC aa 13979
  CC aa 13979   CC aa 13979   CC bb 15147   CC bb 15147   DD aa 16472
  DD aa 16472   DD aa 16472   DD bb 19179   DD bb 19179   DD bb 19179
  DD bb 19179   EE aa 20069   EE aa 20069   EE bb 21718   EE bb 21718
  EE bb 21718   FF aa 23881   FF aa 23881   FF aa 23881   FF aa 23881
  FF bb 27386   FF bb 27386   FF bb 27386   FF bb 27386   FF bb 27386
  FF bb 27386   GG aa 28983   GG aa 28983   GG aa 28983   GG aa 28983
  GG bb 31854   GG bb 31854   GG bb 31854   GG bb 31854   HH aa 34103
  HH aa 34103   HH aa 34103   HH bb 37297   HH bb 37297   HH bb 37297
  HH bb 37297   HH bb 37297   HH bb 37297   II aa 38347   II aa 38347
  II bb 40937   II bb 40937   II bb 40937   II bb 40937   II bb 40937
  JJ aa 42951   JJ aa 42951   JJ aa 42951   JJ aa 42951   JJ bb 44737
  JJ bb 44737   JJ bb 44737   JJ bb 44737}

do_execsql_test 1.2.3 {
  SELECT a, b, rank() OVER (ORDER BY a  GROUPS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 1   AA aa 1   AA aa 1   AA aa 1   AA bb 1   AA bb 1   AA bb 1
  AA bb 1   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9
  BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   CC aa 21
  CC aa 21   CC aa 21   CC aa 21   CC bb 21   CC bb 21   DD aa 27   DD aa 27
  DD aa 27   DD bb 27   DD bb 27   DD bb 27   DD bb 27   EE aa 34   EE aa 34
  EE bb 34   EE bb 34   EE bb 34   FF aa 39   FF aa 39   FF aa 39   FF aa 39
  FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   GG aa 49
  GG aa 49   GG aa 49   GG aa 49   GG bb 49   GG bb 49   GG bb 49   GG bb 49
  HH aa 57   HH aa 57   HH aa 57   HH bb 57   HH bb 57   HH bb 57   HH bb 57
  HH bb 57   HH bb 57   II aa 66   II aa 66   II bb 66   II bb 66   II bb 66
  II bb 66   II bb 66   JJ aa 73   JJ aa 73   JJ aa 73   JJ aa 73   JJ bb 73
  JJ bb 73   JJ bb 73   JJ bb 73}

do_execsql_test 1.2.4 {
  SELECT a, b, max(c) OVER (ORDER BY a,b  GROUPS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 934   AA aa 934   AA aa 934   AA aa 934   AA bb 934   AA bb 934
  AA bb 934   AA bb 934   BB aa 934   BB aa 934   BB aa 934   BB aa 934
  BB aa 934   BB aa 934   BB bb 934   BB bb 934   BB bb 934   BB bb 934
  BB bb 934   BB bb 934   CC aa 934   CC aa 934   CC aa 934   CC aa 934
  CC bb 934   CC bb 934   DD aa 934   DD aa 934   DD aa 934   DD bb 959
  DD bb 959   DD bb 959   DD bb 959   EE aa 959   EE aa 959   EE bb 959
  EE bb 959   EE bb 959   FF aa 959   FF aa 959   FF aa 959   FF aa 959
  FF bb 959   FF bb 959   FF bb 959   FF bb 959   FF bb 959   FF bb 959
  GG aa 959   GG aa 959   GG aa 959   GG aa 959   GG bb 959   GG bb 959
  GG bb 959   GG bb 959   HH aa 979   HH aa 979   HH aa 979   HH bb 979
  HH bb 979   HH bb 979   HH bb 979   HH bb 979   HH bb 979   II aa 979
  II aa 979   II bb 979   II bb 979   II bb 979   II bb 979   II bb 979
  JJ aa 979   JJ aa 979   JJ aa 979   JJ aa 979   JJ bb 979   JJ bb 979
  JJ bb 979   JJ bb 979}

do_execsql_test 1.2.5 {
  SELECT a, b, min(c) OVER (ORDER BY a,b  GROUPS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 223   AA aa 223   AA aa 223   AA aa 223   AA bb 223   AA bb 223
  AA bb 223   AA bb 223   BB aa 223   BB aa 223   BB aa 223   BB aa 223
  BB aa 223   BB aa 223   BB bb 223   BB bb 223   BB bb 223   BB bb 223
  BB bb 223   BB bb 223   CC aa 158   CC aa 158   CC aa 158   CC aa 158
  CC bb 158   CC bb 158   DD aa 158   DD aa 158   DD aa 158   DD bb 158
  DD bb 158   DD bb 158   DD bb 158   EE aa 113   EE aa 113   EE bb 113
  EE bb 113   EE bb 113   FF aa 113   FF aa 113   FF aa 113   FF aa 113
  FF bb 102   FF bb 102   FF bb 102   FF bb 102   FF bb 102   FF bb 102
  GG aa 102   GG aa 102   GG aa 102   GG aa 102   GG bb 102   GG bb 102
  GG bb 102   GG bb 102   HH aa 102   HH aa 102   HH aa 102   HH bb 102
  HH bb 102   HH bb 102   HH bb 102   HH bb 102   HH bb 102   II aa 102
  II aa 102   II bb 102   II bb 102   II bb 102   II bb 102   II bb 102
  JJ aa 102   JJ aa 102   JJ aa 102   JJ aa 102   JJ bb 102   JJ bb 102
  JJ bb 102   JJ bb 102}

do_execsql_test 1.2.6 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 3751   AA aa 3774   AA aa 4446   AA aa 4462   AA bb 3815   AA bb 4058
  AA bb 4113   AA bb 4376   BB aa 11263   BB aa 11365   BB aa 11613
  BB aa 11626   BB aa 11632   BB aa 11778   BB bb 11185   BB bb 11233
  BB bb 11239   BB bb 11314   BB bb 11320   BB bb 11392   CC aa 14388
  CC aa 14540   CC aa 14717   CC aa 14989   CC bb 14325   CC bb 14801
  DD aa 18334   DD aa 18923   DD aa 18955   DD bb 18220   DD bb 18385
  DD bb 18463   DD bb 18941   EE aa 20941   EE aa 21605   EE bb 20950
  EE bb 21089   EE bb 21466   FF aa 26716   FF aa 26719   FF aa 26768
  FF aa 27178   FF bb 26448   FF bb 26516   FF bb 26660   FF bb 26812
  FF bb 27091   FF bb 27284   GG aa 31220   GG aa 31374   GG aa 31519
  GG aa 31706   GG bb 30916   GG bb 30925   GG bb 31010   GG bb 31694
  HH aa 36318   HH aa 36507   HH aa 36817   HH bb 36334   HH bb 36567
  HH bb 36614   HH bb 36942   HH bb 36967   HH bb 37164   II aa 40285
  II aa 40539   II bb 40132   II bb 40266   II bb 40494   II bb 40516
  II bb 40687   JJ aa 43838   JJ aa 43969   JJ aa 44503   JJ aa 44624
  JJ bb 43898   JJ bb 44383   JJ bb 44401   JJ bb 44480}

do_execsql_test 1.2.7 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 1373   AA aa 1396   AA aa 2068   AA aa 2084   AA bb 3815   AA bb 4058
  AA bb 4113   AA bb 4376   BB aa 6796   BB aa 6898   BB aa 7146   BB aa 7159
  BB aa 7165   BB aa 7311   BB bb 11185   BB bb 11233   BB bb 11239
  BB bb 11314   BB bb 11320   BB bb 11392   CC aa 13220   CC aa 13372
  CC aa 13549   CC aa 13821   CC bb 14325   CC bb 14801   DD aa 15627
  DD aa 16216   DD aa 16248   DD bb 18220   DD bb 18385   DD bb 18463
  DD bb 18941   EE aa 19292   EE aa 19956   EE bb 20950   EE bb 21089
  EE bb 21466   FF aa 23211   FF aa 23214   FF aa 23263   FF aa 23673
  FF bb 26448   FF bb 26516   FF bb 26660   FF bb 26812   FF bb 27091
  FF bb 27284   GG aa 28349   GG aa 28503   GG aa 28648   GG aa 28835
  GG bb 30916   GG bb 30925   GG bb 31010   GG bb 31694   HH aa 33124
  HH aa 33313   HH aa 33623   HH bb 36334   HH bb 36567   HH bb 36614
  HH bb 36942   HH bb 36967   HH bb 37164   II aa 37695   II aa 37949
  II bb 40132   II bb 40266   II bb 40494   II bb 40516   II bb 40687
  JJ aa 42052   JJ aa 42183   JJ aa 42717   JJ aa 42838   JJ bb 43898
  JJ bb 44383   JJ bb 44401   JJ bb 44480}

do_execsql_test 1.2.8 {
  SELECT a, b, 
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW )
    FROM t3 ORDER BY 1, 2, 3;
} {AA aa 3751 4685 1373 2307   AA aa 3774 4685 1396 2307
  AA aa 4446 4685 2068 2307   AA aa 4462 4685 2084 2307
  AA bb 3815 4685 3815 4685   AA bb 4058 4685 4058 4685
  AA bb 4113 4685 4113 4685   AA bb 4376 4685 4376 4685
  BB aa 11263 12025 6796 7558   BB aa 11365 12025 6898 7558
  BB aa 11613 12025 7146 7558   BB aa 11626 12025 7159 7558
  BB aa 11632 12025 7165 7558   BB aa 11778 12025 7311 7558
  BB bb 11185 12025 11185 12025   BB bb 11233 12025 11233 12025
  BB bb 11239 12025 11239 12025   BB bb 11314 12025 11314 12025
  BB bb 11320 12025 11320 12025   BB bb 11392 12025 11392 12025
  CC aa 14388 15147 13220 13979   CC aa 14540 15147 13372 13979
  CC aa 14717 15147 13549 13979   CC aa 14989 15147 13821 13979
  CC bb 14325 15147 14325 15147   CC bb 14801 15147 14801 15147
  DD aa 18334 19179 15627 16472   DD aa 18923 19179 16216 16472
  DD aa 18955 19179 16248 16472   DD bb 18220 19179 18220 19179
  DD bb 18385 19179 18385 19179   DD bb 18463 19179 18463 19179
  DD bb 18941 19179 18941 19179   EE aa 20941 21718 19292 20069
  EE aa 21605 21718 19956 20069   EE bb 20950 21718 20950 21718
  EE bb 21089 21718 21089 21718   EE bb 21466 21718 21466 21718
  FF aa 26716 27386 23211 23881   FF aa 26719 27386 23214 23881
  FF aa 26768 27386 23263 23881   FF aa 27178 27386 23673 23881
  FF bb 26448 27386 26448 27386   FF bb 26516 27386 26516 27386
  FF bb 26660 27386 26660 27386   FF bb 26812 27386 26812 27386
  FF bb 27091 27386 27091 27386   FF bb 27284 27386 27284 27386
  GG aa 31220 31854 28349 28983   GG aa 31374 31854 28503 28983
  GG aa 31519 31854 28648 28983   GG aa 31706 31854 28835 28983
  GG bb 30916 31854 30916 31854   GG bb 30925 31854 30925 31854
  GG bb 31010 31854 31010 31854   GG bb 31694 31854 31694 31854
  HH aa 36318 37297 33124 34103   HH aa 36507 37297 33313 34103
  HH aa 36817 37297 33623 34103   HH bb 36334 37297 36334 37297
  HH bb 36567 37297 36567 37297   HH bb 36614 37297 36614 37297
  HH bb 36942 37297 36942 37297   HH bb 36967 37297 36967 37297
  HH bb 37164 37297 37164 37297   II aa 40285 40937 37695 38347
  II aa 40539 40937 37949 38347   II bb 40132 40937 40132 40937
  II bb 40266 40937 40266 40937   II bb 40494 40937 40494 40937
  II bb 40516 40937 40516 40937   II bb 40687 40937 40687 40937
  JJ aa 43838 44737 42052 42951   JJ aa 43969 44737 42183 42951
  JJ aa 44503 44737 42717 42951   JJ aa 44624 44737 42838 42951
  JJ bb 43898 44737 43898 44737   JJ bb 44383 44737 44383 44737
  JJ bb 44401 44737 44401 44737   JJ bb 44480 44737 44480 44737}

do_execsql_test 1.3.1 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN UNBOUNDED PRECEDING AND 1 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 12025   AA aa 12025   AA aa 12025   AA aa 12025   AA bb 12025
  AA bb 12025   AA bb 12025   AA bb 12025   BB aa 15147   BB aa 15147
  BB aa 15147   BB aa 15147   BB aa 15147   BB aa 15147   BB bb 15147
  BB bb 15147   BB bb 15147   BB bb 15147   BB bb 15147   BB bb 15147
  CC aa 19179   CC aa 19179   CC aa 19179   CC aa 19179   CC bb 19179
  CC bb 19179   DD aa 21718   DD aa 21718   DD aa 21718   DD bb 21718
  DD bb 21718   DD bb 21718   DD bb 21718   EE aa 27386   EE aa 27386
  EE bb 27386   EE bb 27386   EE bb 27386   FF aa 31854   FF aa 31854
  FF aa 31854   FF aa 31854   FF bb 31854   FF bb 31854   FF bb 31854
  FF bb 31854   FF bb 31854   FF bb 31854   GG aa 37297   GG aa 37297
  GG aa 37297   GG aa 37297   GG bb 37297   GG bb 37297   GG bb 37297
  GG bb 37297   HH aa 40937   HH aa 40937   HH aa 40937   HH bb 40937
  HH bb 40937   HH bb 40937   HH bb 40937   HH bb 40937   HH bb 40937
  II aa 44737   II aa 44737   II bb 44737   II bb 44737   II bb 44737
  II bb 44737   II bb 44737   JJ aa 44737   JJ aa 44737   JJ aa 44737
  JJ aa 44737   JJ bb 44737   JJ bb 44737   JJ bb 44737   JJ bb 44737}

do_execsql_test 1.3.2 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN UNBOUNDED PRECEDING AND 1 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 4685   AA aa 4685   AA aa 4685   AA aa 4685   AA bb 7558   AA bb 7558
  AA bb 7558   AA bb 7558   BB aa 12025   BB aa 12025   BB aa 12025
  BB aa 12025   BB aa 12025   BB aa 12025   BB bb 13979   BB bb 13979
  BB bb 13979   BB bb 13979   BB bb 13979   BB bb 13979   CC aa 15147
  CC aa 15147   CC aa 15147   CC aa 15147   CC bb 16472   CC bb 16472
  DD aa 19179   DD aa 19179   DD aa 19179   DD bb 20069   DD bb 20069
  DD bb 20069   DD bb 20069   EE aa 21718   EE aa 21718   EE bb 23881
  EE bb 23881   EE bb 23881   FF aa 27386   FF aa 27386   FF aa 27386
  FF aa 27386   FF bb 28983   FF bb 28983   FF bb 28983   FF bb 28983
  FF bb 28983   FF bb 28983   GG aa 31854   GG aa 31854   GG aa 31854
  GG aa 31854   GG bb 34103   GG bb 34103   GG bb 34103   GG bb 34103
  HH aa 37297   HH aa 37297   HH aa 37297   HH bb 38347   HH bb 38347
  HH bb 38347   HH bb 38347   HH bb 38347   HH bb 38347   II aa 40937
  II aa 40937   II bb 42951   II bb 42951   II bb 42951   II bb 42951
  II bb 42951   JJ aa 44737   JJ aa 44737   JJ aa 44737   JJ aa 44737
  JJ bb 44737   JJ bb 44737   JJ bb 44737   JJ bb 44737}

do_execsql_test 1.3.3 {
  SELECT a, b, rank() OVER (ORDER BY a  GROUPS BETWEEN UNBOUNDED PRECEDING AND 1 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 1   AA aa 1   AA aa 1   AA aa 1   AA bb 1   AA bb 1   AA bb 1
  AA bb 1   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9
  BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   CC aa 21
  CC aa 21   CC aa 21   CC aa 21   CC bb 21   CC bb 21   DD aa 27   DD aa 27
  DD aa 27   DD bb 27   DD bb 27   DD bb 27   DD bb 27   EE aa 34   EE aa 34
  EE bb 34   EE bb 34   EE bb 34   FF aa 39   FF aa 39   FF aa 39   FF aa 39
  FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   GG aa 49
  GG aa 49   GG aa 49   GG aa 49   GG bb 49   GG bb 49   GG bb 49   GG bb 49
  HH aa 57   HH aa 57   HH aa 57   HH bb 57   HH bb 57   HH bb 57   HH bb 57
  HH bb 57   HH bb 57   II aa 66   II aa 66   II bb 66   II bb 66   II bb 66
  II bb 66   II bb 66   JJ aa 73   JJ aa 73   JJ aa 73   JJ aa 73   JJ bb 73
  JJ bb 73   JJ bb 73   JJ bb 73}

do_execsql_test 1.3.4 {
  SELECT a, b, max(c) OVER (ORDER BY a,b  GROUPS BETWEEN UNBOUNDED PRECEDING AND 1 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 934   AA aa 934   AA aa 934   AA aa 934   AA bb 934   AA bb 934
  AA bb 934   AA bb 934   BB aa 934   BB aa 934   BB aa 934   BB aa 934
  BB aa 934   BB aa 934   BB bb 934   BB bb 934   BB bb 934   BB bb 934
  BB bb 934   BB bb 934   CC aa 934   CC aa 934   CC aa 934   CC aa 934
  CC bb 934   CC bb 934   DD aa 959   DD aa 959   DD aa 959   DD bb 959
  DD bb 959   DD bb 959   DD bb 959   EE aa 959   EE aa 959   EE bb 959
  EE bb 959   EE bb 959   FF aa 959   FF aa 959   FF aa 959   FF aa 959
  FF bb 959   FF bb 959   FF bb 959   FF bb 959   FF bb 959   FF bb 959
  GG aa 959   GG aa 959   GG aa 959   GG aa 959   GG bb 979   GG bb 979
  GG bb 979   GG bb 979   HH aa 979   HH aa 979   HH aa 979   HH bb 979
  HH bb 979   HH bb 979   HH bb 979   HH bb 979   HH bb 979   II aa 979
  II aa 979   II bb 979   II bb 979   II bb 979   II bb 979   II bb 979
  JJ aa 979   JJ aa 979   JJ aa 979   JJ aa 979   JJ bb 979   JJ bb 979
  JJ bb 979   JJ bb 979}

do_execsql_test 1.3.5 {
  SELECT a, b, min(c) OVER (ORDER BY a,b  GROUPS BETWEEN UNBOUNDED PRECEDING AND 1 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 223   AA aa 223   AA aa 223   AA aa 223   AA bb 223   AA bb 223
  AA bb 223   AA bb 223   BB aa 223   BB aa 223   BB aa 223   BB aa 223
  BB aa 223   BB aa 223   BB bb 158   BB bb 158   BB bb 158   BB bb 158
  BB bb 158   BB bb 158   CC aa 158   CC aa 158   CC aa 158   CC aa 158
  CC bb 158   CC bb 158   DD aa 158   DD aa 158   DD aa 158   DD bb 113
  DD bb 113   DD bb 113   DD bb 113   EE aa 113   EE aa 113   EE bb 113
  EE bb 113   EE bb 113   FF aa 102   FF aa 102   FF aa 102   FF aa 102
  FF bb 102   FF bb 102   FF bb 102   FF bb 102   FF bb 102   FF bb 102
  GG aa 102   GG aa 102   GG aa 102   GG aa 102   GG bb 102   GG bb 102
  GG bb 102   GG bb 102   HH aa 102   HH aa 102   HH aa 102   HH bb 102
  HH bb 102   HH bb 102   HH bb 102   HH bb 102   HH bb 102   II aa 102
  II aa 102   II bb 102   II bb 102   II bb 102   II bb 102   II bb 102
  JJ aa 102   JJ aa 102   JJ aa 102   JJ aa 102   JJ bb 102   JJ bb 102
  JJ bb 102   JJ bb 102}

do_execsql_test 1.3.6 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN UNBOUNDED PRECEDING AND 1 FOLLOWING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 11091   AA aa 11114   AA aa 11786   AA aa 11802   AA bb 11155
  AA bb 11398   AA bb 11453   AA bb 11716   BB aa 14385   BB aa 14487
  BB aa 14735   BB aa 14748   BB aa 14754   BB aa 14900   BB bb 14307
  BB bb 14355   BB bb 14361   BB bb 14436   BB bb 14442   BB bb 14514
  CC aa 18420   CC aa 18572   CC aa 18749   CC aa 19021   CC bb 18357
  CC bb 18833   DD aa 20873   DD aa 21462   DD aa 21494   DD bb 20759
  DD bb 20924   DD bb 21002   DD bb 21480   EE aa 26609   EE aa 27273
  EE bb 26618   EE bb 26757   EE bb 27134   FF aa 31184   FF aa 31187
  FF aa 31236   FF aa 31646   FF bb 30916   FF bb 30984   FF bb 31128
  FF bb 31280   FF bb 31559   FF bb 31752   GG aa 36663   GG aa 36817
  GG aa 36962   GG aa 37149   GG bb 36359   GG bb 36368   GG bb 36453
  GG bb 37137   HH aa 39958   HH aa 40147   HH aa 40457   HH bb 39974
  HH bb 40207   HH bb 40254   HH bb 40582   HH bb 40607   HH bb 40804
  II aa 44085   II aa 44339   II bb 43932   II bb 44066   II bb 44294
  II bb 44316   II bb 44487   JJ aa 43838   JJ aa 43969   JJ aa 44503
  JJ aa 44624   JJ bb 43898   JJ bb 44383   JJ bb 44401   JJ bb 44480}

do_execsql_test 1.3.7 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN UNBOUNDED PRECEDING AND 1 FOLLOWING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 3751   AA aa 3774   AA aa 4446   AA aa 4462   AA bb 6688   AA bb 6931
  AA bb 6986   AA bb 7249   BB aa 11263   BB aa 11365   BB aa 11613
  BB aa 11626   BB aa 11632   BB aa 11778   BB bb 13139   BB bb 13187
  BB bb 13193   BB bb 13268   BB bb 13274   BB bb 13346   CC aa 14388
  CC aa 14540   CC aa 14717   CC aa 14989   CC bb 15650   CC bb 16126
  DD aa 18334   DD aa 18923   DD aa 18955   DD bb 19110   DD bb 19275
  DD bb 19353   DD bb 19831   EE aa 20941   EE aa 21605   EE bb 23113
  EE bb 23252   EE bb 23629   FF aa 26716   FF aa 26719   FF aa 26768
  FF aa 27178   FF bb 28045   FF bb 28113   FF bb 28257   FF bb 28409
  FF bb 28688   FF bb 28881   GG aa 31220   GG aa 31374   GG aa 31519
  GG aa 31706   GG bb 33165   GG bb 33174   GG bb 33259   GG bb 33943
  HH aa 36318   HH aa 36507   HH aa 36817   HH bb 37384   HH bb 37617
  HH bb 37664   HH bb 37992   HH bb 38017   HH bb 38214   II aa 40285
  II aa 40539   II bb 42146   II bb 42280   II bb 42508   II bb 42530
  II bb 42701   JJ aa 43838   JJ aa 43969   JJ aa 44503   JJ aa 44624
  JJ bb 43898   JJ bb 44383   JJ bb 44401   JJ bb 44480}

do_execsql_test 1.3.8 {
  SELECT a, b, 
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN UNBOUNDED PRECEDING AND 1 FOLLOWING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN UNBOUNDED PRECEDING AND 1 FOLLOWING ),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN UNBOUNDED PRECEDING AND 1 FOLLOWING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN UNBOUNDED PRECEDING AND 1 FOLLOWING )
    FROM t3 ORDER BY 1, 2, 3;
} {AA aa 11091 12025 3751 4685   AA aa 11114 12025 3774 4685
  AA aa 11786 12025 4446 4685   AA aa 11802 12025 4462 4685
  AA bb 11155 12025 6688 7558   AA bb 11398 12025 6931 7558
  AA bb 11453 12025 6986 7558   AA bb 11716 12025 7249 7558
  BB aa 14385 15147 11263 12025   BB aa 14487 15147 11365 12025
  BB aa 14735 15147 11613 12025   BB aa 14748 15147 11626 12025
  BB aa 14754 15147 11632 12025   BB aa 14900 15147 11778 12025
  BB bb 14307 15147 13139 13979   BB bb 14355 15147 13187 13979
  BB bb 14361 15147 13193 13979   BB bb 14436 15147 13268 13979
  BB bb 14442 15147 13274 13979   BB bb 14514 15147 13346 13979
  CC aa 18420 19179 14388 15147   CC aa 18572 19179 14540 15147
  CC aa 18749 19179 14717 15147   CC aa 19021 19179 14989 15147
  CC bb 18357 19179 15650 16472   CC bb 18833 19179 16126 16472
  DD aa 20873 21718 18334 19179   DD aa 21462 21718 18923 19179
  DD aa 21494 21718 18955 19179   DD bb 20759 21718 19110 20069
  DD bb 20924 21718 19275 20069   DD bb 21002 21718 19353 20069
  DD bb 21480 21718 19831 20069   EE aa 26609 27386 20941 21718
  EE aa 27273 27386 21605 21718   EE bb 26618 27386 23113 23881
  EE bb 26757 27386 23252 23881   EE bb 27134 27386 23629 23881
  FF aa 31184 31854 26716 27386   FF aa 31187 31854 26719 27386
  FF aa 31236 31854 26768 27386   FF aa 31646 31854 27178 27386
  FF bb 30916 31854 28045 28983   FF bb 30984 31854 28113 28983
  FF bb 31128 31854 28257 28983   FF bb 31280 31854 28409 28983
  FF bb 31559 31854 28688 28983   FF bb 31752 31854 28881 28983
  GG aa 36663 37297 31220 31854   GG aa 36817 37297 31374 31854
  GG aa 36962 37297 31519 31854   GG aa 37149 37297 31706 31854
  GG bb 36359 37297 33165 34103   GG bb 36368 37297 33174 34103
  GG bb 36453 37297 33259 34103   GG bb 37137 37297 33943 34103
  HH aa 39958 40937 36318 37297   HH aa 40147 40937 36507 37297
  HH aa 40457 40937 36817 37297   HH bb 39974 40937 37384 38347
  HH bb 40207 40937 37617 38347   HH bb 40254 40937 37664 38347
  HH bb 40582 40937 37992 38347   HH bb 40607 40937 38017 38347
  HH bb 40804 40937 38214 38347   II aa 44085 44737 40285 40937
  II aa 44339 44737 40539 40937   II bb 43932 44737 42146 42951
  II bb 44066 44737 42280 42951   II bb 44294 44737 42508 42951
  II bb 44316 44737 42530 42951   II bb 44487 44737 42701 42951
  JJ aa 43838 44737 43838 44737   JJ aa 43969 44737 43969 44737
  JJ aa 44503 44737 44503 44737   JJ aa 44624 44737 44624 44737
  JJ bb 43898 44737 43898 44737   JJ bb 44383 44737 44383 44737
  JJ bb 44401 44737 44401 44737   JJ bb 44480 44737 44480 44737}

do_execsql_test 1.4.1 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 44737   AA aa 44737   AA aa 44737   AA aa 44737   AA bb 44737
  AA bb 44737   AA bb 44737   AA bb 44737   BB aa 44737   BB aa 44737
  BB aa 44737   BB aa 44737   BB aa 44737   BB aa 44737   BB bb 44737
  BB bb 44737   BB bb 44737   BB bb 44737   BB bb 44737   BB bb 44737
  CC aa 44737   CC aa 44737   CC aa 44737   CC aa 44737   CC bb 44737
  CC bb 44737   DD aa 44737   DD aa 44737   DD aa 44737   DD bb 44737
  DD bb 44737   DD bb 44737   DD bb 44737   EE aa 44737   EE aa 44737
  EE bb 44737   EE bb 44737   EE bb 44737   FF aa 44737   FF aa 44737
  FF aa 44737   FF aa 44737   FF bb 44737   FF bb 44737   FF bb 44737
  FF bb 44737   FF bb 44737   FF bb 44737   GG aa 44737   GG aa 44737
  GG aa 44737   GG aa 44737   GG bb 44737   GG bb 44737   GG bb 44737
  GG bb 44737   HH aa 44737   HH aa 44737   HH aa 44737   HH bb 44737
  HH bb 44737   HH bb 44737   HH bb 44737   HH bb 44737   HH bb 44737
  II aa 44737   II aa 44737   II bb 44737   II bb 44737   II bb 44737
  II bb 44737   II bb 44737   JJ aa 44737   JJ aa 44737   JJ aa 44737
  JJ aa 44737   JJ bb 44737   JJ bb 44737   JJ bb 44737   JJ bb 44737}

do_execsql_test 1.4.2 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 44737   AA aa 44737   AA aa 44737   AA aa 44737   AA bb 44737
  AA bb 44737   AA bb 44737   AA bb 44737   BB aa 44737   BB aa 44737
  BB aa 44737   BB aa 44737   BB aa 44737   BB aa 44737   BB bb 44737
  BB bb 44737   BB bb 44737   BB bb 44737   BB bb 44737   BB bb 44737
  CC aa 44737   CC aa 44737   CC aa 44737   CC aa 44737   CC bb 44737
  CC bb 44737   DD aa 44737   DD aa 44737   DD aa 44737   DD bb 44737
  DD bb 44737   DD bb 44737   DD bb 44737   EE aa 44737   EE aa 44737
  EE bb 44737   EE bb 44737   EE bb 44737   FF aa 44737   FF aa 44737
  FF aa 44737   FF aa 44737   FF bb 44737   FF bb 44737   FF bb 44737
  FF bb 44737   FF bb 44737   FF bb 44737   GG aa 44737   GG aa 44737
  GG aa 44737   GG aa 44737   GG bb 44737   GG bb 44737   GG bb 44737
  GG bb 44737   HH aa 44737   HH aa 44737   HH aa 44737   HH bb 44737
  HH bb 44737   HH bb 44737   HH bb 44737   HH bb 44737   HH bb 44737
  II aa 44737   II aa 44737   II bb 44737   II bb 44737   II bb 44737
  II bb 44737   II bb 44737   JJ aa 44737   JJ aa 44737   JJ aa 44737
  JJ aa 44737   JJ bb 44737   JJ bb 44737   JJ bb 44737   JJ bb 44737}

do_execsql_test 1.4.3 {
  SELECT a, b, rank() OVER (ORDER BY a  GROUPS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 1   AA aa 1   AA aa 1   AA aa 1   AA bb 1   AA bb 1   AA bb 1
  AA bb 1   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9
  BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   CC aa 21
  CC aa 21   CC aa 21   CC aa 21   CC bb 21   CC bb 21   DD aa 27   DD aa 27
  DD aa 27   DD bb 27   DD bb 27   DD bb 27   DD bb 27   EE aa 34   EE aa 34
  EE bb 34   EE bb 34   EE bb 34   FF aa 39   FF aa 39   FF aa 39   FF aa 39
  FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   GG aa 49
  GG aa 49   GG aa 49   GG aa 49   GG bb 49   GG bb 49   GG bb 49   GG bb 49
  HH aa 57   HH aa 57   HH aa 57   HH bb 57   HH bb 57   HH bb 57   HH bb 57
  HH bb 57   HH bb 57   II aa 66   II aa 66   II bb 66   II bb 66   II bb 66
  II bb 66   II bb 66   JJ aa 73   JJ aa 73   JJ aa 73   JJ aa 73   JJ bb 73
  JJ bb 73   JJ bb 73   JJ bb 73}

do_execsql_test 1.4.4 {
  SELECT a, b, max(c) OVER (ORDER BY a,b  GROUPS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 979   AA aa 979   AA aa 979   AA aa 979   AA bb 979   AA bb 979
  AA bb 979   AA bb 979   BB aa 979   BB aa 979   BB aa 979   BB aa 979
  BB aa 979   BB aa 979   BB bb 979   BB bb 979   BB bb 979   BB bb 979
  BB bb 979   BB bb 979   CC aa 979   CC aa 979   CC aa 979   CC aa 979
  CC bb 979   CC bb 979   DD aa 979   DD aa 979   DD aa 979   DD bb 979
  DD bb 979   DD bb 979   DD bb 979   EE aa 979   EE aa 979   EE bb 979
  EE bb 979   EE bb 979   FF aa 979   FF aa 979   FF aa 979   FF aa 979
  FF bb 979   FF bb 979   FF bb 979   FF bb 979   FF bb 979   FF bb 979
  GG aa 979   GG aa 979   GG aa 979   GG aa 979   GG bb 979   GG bb 979
  GG bb 979   GG bb 979   HH aa 979   HH aa 979   HH aa 979   HH bb 979
  HH bb 979   HH bb 979   HH bb 979   HH bb 979   HH bb 979   II aa 979
  II aa 979   II bb 979   II bb 979   II bb 979   II bb 979   II bb 979
  JJ aa 979   JJ aa 979   JJ aa 979   JJ aa 979   JJ bb 979   JJ bb 979
  JJ bb 979   JJ bb 979}

do_execsql_test 1.4.5 {
  SELECT a, b, min(c) OVER (ORDER BY a,b  GROUPS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 102   AA aa 102   AA aa 102   AA aa 102   AA bb 102   AA bb 102
  AA bb 102   AA bb 102   BB aa 102   BB aa 102   BB aa 102   BB aa 102
  BB aa 102   BB aa 102   BB bb 102   BB bb 102   BB bb 102   BB bb 102
  BB bb 102   BB bb 102   CC aa 102   CC aa 102   CC aa 102   CC aa 102
  CC bb 102   CC bb 102   DD aa 102   DD aa 102   DD aa 102   DD bb 102
  DD bb 102   DD bb 102   DD bb 102   EE aa 102   EE aa 102   EE bb 102
  EE bb 102   EE bb 102   FF aa 102   FF aa 102   FF aa 102   FF aa 102
  FF bb 102   FF bb 102   FF bb 102   FF bb 102   FF bb 102   FF bb 102
  GG aa 102   GG aa 102   GG aa 102   GG aa 102   GG bb 102   GG bb 102
  GG bb 102   GG bb 102   HH aa 102   HH aa 102   HH aa 102   HH bb 102
  HH bb 102   HH bb 102   HH bb 102   HH bb 102   HH bb 102   II aa 102
  II aa 102   II bb 102   II bb 102   II bb 102   II bb 102   II bb 102
  JJ aa 102   JJ aa 102   JJ aa 102   JJ aa 102   JJ bb 102   JJ bb 102
  JJ bb 102   JJ bb 102}

do_execsql_test 1.4.6 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 43803   AA aa 43826   AA aa 44498   AA aa 44514   AA bb 43867
  AA bb 44110   AA bb 44165   AA bb 44428   BB aa 43975   BB aa 44077
  BB aa 44325   BB aa 44338   BB aa 44344   BB aa 44490   BB bb 43897
  BB bb 43945   BB bb 43951   BB bb 44026   BB bb 44032   BB bb 44104
  CC aa 43978   CC aa 44130   CC aa 44307   CC aa 44579   CC bb 43915
  CC bb 44391   DD aa 43892   DD aa 44481   DD aa 44513   DD bb 43778
  DD bb 43943   DD bb 44021   DD bb 44499   EE aa 43960   EE aa 44624
  EE bb 43969   EE bb 44108   EE bb 44485   FF aa 44067   FF aa 44070
  FF aa 44119   FF aa 44529   FF bb 43799   FF bb 43867   FF bb 44011
  FF bb 44163   FF bb 44442   FF bb 44635   GG aa 44103   GG aa 44257
  GG aa 44402   GG aa 44589   GG bb 43799   GG bb 43808   GG bb 43893
  GG bb 44577   HH aa 43758   HH aa 43947   HH aa 44257   HH bb 43774
  HH bb 44007   HH bb 44054   HH bb 44382   HH bb 44407   HH bb 44604
  II aa 44085   II aa 44339   II bb 43932   II bb 44066   II bb 44294
  II bb 44316   II bb 44487   JJ aa 43838   JJ aa 43969   JJ aa 44503
  JJ aa 44624   JJ bb 43898   JJ bb 44383   JJ bb 44401   JJ bb 44480}

do_execsql_test 1.4.7 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 43803   AA aa 43826   AA aa 44498   AA aa 44514   AA bb 43867
  AA bb 44110   AA bb 44165   AA bb 44428   BB aa 43975   BB aa 44077
  BB aa 44325   BB aa 44338   BB aa 44344   BB aa 44490   BB bb 43897
  BB bb 43945   BB bb 43951   BB bb 44026   BB bb 44032   BB bb 44104
  CC aa 43978   CC aa 44130   CC aa 44307   CC aa 44579   CC bb 43915
  CC bb 44391   DD aa 43892   DD aa 44481   DD aa 44513   DD bb 43778
  DD bb 43943   DD bb 44021   DD bb 44499   EE aa 43960   EE aa 44624
  EE bb 43969   EE bb 44108   EE bb 44485   FF aa 44067   FF aa 44070
  FF aa 44119   FF aa 44529   FF bb 43799   FF bb 43867   FF bb 44011
  FF bb 44163   FF bb 44442   FF bb 44635   GG aa 44103   GG aa 44257
  GG aa 44402   GG aa 44589   GG bb 43799   GG bb 43808   GG bb 43893
  GG bb 44577   HH aa 43758   HH aa 43947   HH aa 44257   HH bb 43774
  HH bb 44007   HH bb 44054   HH bb 44382   HH bb 44407   HH bb 44604
  II aa 44085   II aa 44339   II bb 43932   II bb 44066   II bb 44294
  II bb 44316   II bb 44487   JJ aa 43838   JJ aa 43969   JJ aa 44503
  JJ aa 44624   JJ bb 43898   JJ bb 44383   JJ bb 44401   JJ bb 44480}

do_execsql_test 1.4.8 {
  SELECT a, b, 
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING )
    FROM t3 ORDER BY 1, 2, 3;
} {AA aa 43803 44737 43803 44737   AA aa 43826 44737 43826 44737
  AA aa 44498 44737 44498 44737   AA aa 44514 44737 44514 44737
  AA bb 43867 44737 43867 44737   AA bb 44110 44737 44110 44737
  AA bb 44165 44737 44165 44737   AA bb 44428 44737 44428 44737
  BB aa 43975 44737 43975 44737   BB aa 44077 44737 44077 44737
  BB aa 44325 44737 44325 44737   BB aa 44338 44737 44338 44737
  BB aa 44344 44737 44344 44737   BB aa 44490 44737 44490 44737
  BB bb 43897 44737 43897 44737   BB bb 43945 44737 43945 44737
  BB bb 43951 44737 43951 44737   BB bb 44026 44737 44026 44737
  BB bb 44032 44737 44032 44737   BB bb 44104 44737 44104 44737
  CC aa 43978 44737 43978 44737   CC aa 44130 44737 44130 44737
  CC aa 44307 44737 44307 44737   CC aa 44579 44737 44579 44737
  CC bb 43915 44737 43915 44737   CC bb 44391 44737 44391 44737
  DD aa 43892 44737 43892 44737   DD aa 44481 44737 44481 44737
  DD aa 44513 44737 44513 44737   DD bb 43778 44737 43778 44737
  DD bb 43943 44737 43943 44737   DD bb 44021 44737 44021 44737
  DD bb 44499 44737 44499 44737   EE aa 43960 44737 43960 44737
  EE aa 44624 44737 44624 44737   EE bb 43969 44737 43969 44737
  EE bb 44108 44737 44108 44737   EE bb 44485 44737 44485 44737
  FF aa 44067 44737 44067 44737   FF aa 44070 44737 44070 44737
  FF aa 44119 44737 44119 44737   FF aa 44529 44737 44529 44737
  FF bb 43799 44737 43799 44737   FF bb 43867 44737 43867 44737
  FF bb 44011 44737 44011 44737   FF bb 44163 44737 44163 44737
  FF bb 44442 44737 44442 44737   FF bb 44635 44737 44635 44737
  GG aa 44103 44737 44103 44737   GG aa 44257 44737 44257 44737
  GG aa 44402 44737 44402 44737   GG aa 44589 44737 44589 44737
  GG bb 43799 44737 43799 44737   GG bb 43808 44737 43808 44737
  GG bb 43893 44737 43893 44737   GG bb 44577 44737 44577 44737
  HH aa 43758 44737 43758 44737   HH aa 43947 44737 43947 44737
  HH aa 44257 44737 44257 44737   HH bb 43774 44737 43774 44737
  HH bb 44007 44737 44007 44737   HH bb 44054 44737 44054 44737
  HH bb 44382 44737 44382 44737   HH bb 44407 44737 44407 44737
  HH bb 44604 44737 44604 44737   II aa 44085 44737 44085 44737
  II aa 44339 44737 44339 44737   II bb 43932 44737 43932 44737
  II bb 44066 44737 44066 44737   II bb 44294 44737 44294 44737
  II bb 44316 44737 44316 44737   II bb 44487 44737 44487 44737
  JJ aa 43838 44737 43838 44737   JJ aa 43969 44737 43969 44737
  JJ aa 44503 44737 44503 44737   JJ aa 44624 44737 44624 44737
  JJ bb 43898 44737 43898 44737   JJ bb 44383 44737 44383 44737
  JJ bb 44401 44737 44401 44737   JJ bb 44480 44737 44480 44737}

do_execsql_test 1.5.1 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN 1 PRECEDING         AND 2 PRECEDING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa {}   AA aa {}   AA aa {}   AA aa {}   AA bb {}   AA bb {}   AA bb {}
  AA bb {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}
  BB bb {}   BB bb {}   BB bb {}   BB bb {}   BB bb {}   BB bb {}   CC aa {}
  CC aa {}   CC aa {}   CC aa {}   CC bb {}   CC bb {}   DD aa {}   DD aa {}
  DD aa {}   DD bb {}   DD bb {}   DD bb {}   DD bb {}   EE aa {}   EE aa {}
  EE bb {}   EE bb {}   EE bb {}   FF aa {}   FF aa {}   FF aa {}   FF aa {}
  FF bb {}   FF bb {}   FF bb {}   FF bb {}   FF bb {}   FF bb {}   GG aa {}
  GG aa {}   GG aa {}   GG aa {}   GG bb {}   GG bb {}   GG bb {}   GG bb {}
  HH aa {}   HH aa {}   HH aa {}   HH bb {}   HH bb {}   HH bb {}   HH bb {}
  HH bb {}   HH bb {}   II aa {}   II aa {}   II bb {}   II bb {}   II bb {}
  II bb {}   II bb {}   JJ aa {}   JJ aa {}   JJ aa {}   JJ aa {}   JJ bb {}
  JJ bb {}   JJ bb {}   JJ bb {}}

do_execsql_test 1.5.2 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 1 PRECEDING         AND 2 PRECEDING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa {}   AA aa {}   AA aa {}   AA aa {}   AA bb {}   AA bb {}   AA bb {}
  AA bb {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}
  BB bb {}   BB bb {}   BB bb {}   BB bb {}   BB bb {}   BB bb {}   CC aa {}
  CC aa {}   CC aa {}   CC aa {}   CC bb {}   CC bb {}   DD aa {}   DD aa {}
  DD aa {}   DD bb {}   DD bb {}   DD bb {}   DD bb {}   EE aa {}   EE aa {}
  EE bb {}   EE bb {}   EE bb {}   FF aa {}   FF aa {}   FF aa {}   FF aa {}
  FF bb {}   FF bb {}   FF bb {}   FF bb {}   FF bb {}   FF bb {}   GG aa {}
  GG aa {}   GG aa {}   GG aa {}   GG bb {}   GG bb {}   GG bb {}   GG bb {}
  HH aa {}   HH aa {}   HH aa {}   HH bb {}   HH bb {}   HH bb {}   HH bb {}
  HH bb {}   HH bb {}   II aa {}   II aa {}   II bb {}   II bb {}   II bb {}
  II bb {}   II bb {}   JJ aa {}   JJ aa {}   JJ aa {}   JJ aa {}   JJ bb {}
  JJ bb {}   JJ bb {}   JJ bb {}}

do_execsql_test 1.5.3 {
  SELECT a, b, rank() OVER (ORDER BY a  GROUPS BETWEEN 1 PRECEDING         AND 2 PRECEDING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 1   AA aa 1   AA aa 1   AA aa 1   AA bb 1   AA bb 1   AA bb 1
  AA bb 1   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9
  BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   CC aa 21
  CC aa 21   CC aa 21   CC aa 21   CC bb 21   CC bb 21   DD aa 27   DD aa 27
  DD aa 27   DD bb 27   DD bb 27   DD bb 27   DD bb 27   EE aa 34   EE aa 34
  EE bb 34   EE bb 34   EE bb 34   FF aa 39   FF aa 39   FF aa 39   FF aa 39
  FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   GG aa 49
  GG aa 49   GG aa 49   GG aa 49   GG bb 49   GG bb 49   GG bb 49   GG bb 49
  HH aa 57   HH aa 57   HH aa 57   HH bb 57   HH bb 57   HH bb 57   HH bb 57
  HH bb 57   HH bb 57   II aa 66   II aa 66   II bb 66   II bb 66   II bb 66
  II bb 66   II bb 66   JJ aa 73   JJ aa 73   JJ aa 73   JJ aa 73   JJ bb 73
  JJ bb 73   JJ bb 73   JJ bb 73}

do_execsql_test 1.5.4 {
  SELECT a, b, max(c) OVER (ORDER BY a,b  GROUPS BETWEEN 1 PRECEDING         AND 2 PRECEDING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa {}   AA aa {}   AA aa {}   AA aa {}   AA bb {}   AA bb {}   AA bb {}
  AA bb {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}
  BB bb {}   BB bb {}   BB bb {}   BB bb {}   BB bb {}   BB bb {}   CC aa {}
  CC aa {}   CC aa {}   CC aa {}   CC bb {}   CC bb {}   DD aa {}   DD aa {}
  DD aa {}   DD bb {}   DD bb {}   DD bb {}   DD bb {}   EE aa {}   EE aa {}
  EE bb {}   EE bb {}   EE bb {}   FF aa {}   FF aa {}   FF aa {}   FF aa {}
  FF bb {}   FF bb {}   FF bb {}   FF bb {}   FF bb {}   FF bb {}   GG aa {}
  GG aa {}   GG aa {}   GG aa {}   GG bb {}   GG bb {}   GG bb {}   GG bb {}
  HH aa {}   HH aa {}   HH aa {}   HH bb {}   HH bb {}   HH bb {}   HH bb {}
  HH bb {}   HH bb {}   II aa {}   II aa {}   II bb {}   II bb {}   II bb {}
  II bb {}   II bb {}   JJ aa {}   JJ aa {}   JJ aa {}   JJ aa {}   JJ bb {}
  JJ bb {}   JJ bb {}   JJ bb {}}

do_execsql_test 1.5.5 {
  SELECT a, b, min(c) OVER (ORDER BY a,b  GROUPS BETWEEN 1 PRECEDING         AND 2 PRECEDING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa {}   AA aa {}   AA aa {}   AA aa {}   AA bb {}   AA bb {}   AA bb {}
  AA bb {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}
  BB bb {}   BB bb {}   BB bb {}   BB bb {}   BB bb {}   BB bb {}   CC aa {}
  CC aa {}   CC aa {}   CC aa {}   CC bb {}   CC bb {}   DD aa {}   DD aa {}
  DD aa {}   DD bb {}   DD bb {}   DD bb {}   DD bb {}   EE aa {}   EE aa {}
  EE bb {}   EE bb {}   EE bb {}   FF aa {}   FF aa {}   FF aa {}   FF aa {}
  FF bb {}   FF bb {}   FF bb {}   FF bb {}   FF bb {}   FF bb {}   GG aa {}
  GG aa {}   GG aa {}   GG aa {}   GG bb {}   GG bb {}   GG bb {}   GG bb {}
  HH aa {}   HH aa {}   HH aa {}   HH bb {}   HH bb {}   HH bb {}   HH bb {}
  HH bb {}   HH bb {}   II aa {}   II aa {}   II bb {}   II bb {}   II bb {}
  II bb {}   II bb {}   JJ aa {}   JJ aa {}   JJ aa {}   JJ aa {}   JJ bb {}
  JJ bb {}   JJ bb {}   JJ bb {}}

do_execsql_test 1.5.6 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN 1 PRECEDING         AND 2 PRECEDING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa {}   AA aa {}   AA aa {}   AA aa {}   AA bb {}   AA bb {}   AA bb {}
  AA bb {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}
  BB bb {}   BB bb {}   BB bb {}   BB bb {}   BB bb {}   BB bb {}   CC aa {}
  CC aa {}   CC aa {}   CC aa {}   CC bb {}   CC bb {}   DD aa {}   DD aa {}
  DD aa {}   DD bb {}   DD bb {}   DD bb {}   DD bb {}   EE aa {}   EE aa {}
  EE bb {}   EE bb {}   EE bb {}   FF aa {}   FF aa {}   FF aa {}   FF aa {}
  FF bb {}   FF bb {}   FF bb {}   FF bb {}   FF bb {}   FF bb {}   GG aa {}
  GG aa {}   GG aa {}   GG aa {}   GG bb {}   GG bb {}   GG bb {}   GG bb {}
  HH aa {}   HH aa {}   HH aa {}   HH bb {}   HH bb {}   HH bb {}   HH bb {}
  HH bb {}   HH bb {}   II aa {}   II aa {}   II bb {}   II bb {}   II bb {}
  II bb {}   II bb {}   JJ aa {}   JJ aa {}   JJ aa {}   JJ aa {}   JJ bb {}
  JJ bb {}   JJ bb {}   JJ bb {}}

do_execsql_test 1.5.7 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 1 PRECEDING         AND 2 PRECEDING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa {}   AA aa {}   AA aa {}   AA aa {}   AA bb {}   AA bb {}   AA bb {}
  AA bb {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}
  BB bb {}   BB bb {}   BB bb {}   BB bb {}   BB bb {}   BB bb {}   CC aa {}
  CC aa {}   CC aa {}   CC aa {}   CC bb {}   CC bb {}   DD aa {}   DD aa {}
  DD aa {}   DD bb {}   DD bb {}   DD bb {}   DD bb {}   EE aa {}   EE aa {}
  EE bb {}   EE bb {}   EE bb {}   FF aa {}   FF aa {}   FF aa {}   FF aa {}
  FF bb {}   FF bb {}   FF bb {}   FF bb {}   FF bb {}   FF bb {}   GG aa {}
  GG aa {}   GG aa {}   GG aa {}   GG bb {}   GG bb {}   GG bb {}   GG bb {}
  HH aa {}   HH aa {}   HH aa {}   HH bb {}   HH bb {}   HH bb {}   HH bb {}
  HH bb {}   HH bb {}   II aa {}   II aa {}   II bb {}   II bb {}   II bb {}
  II bb {}   II bb {}   JJ aa {}   JJ aa {}   JJ aa {}   JJ aa {}   JJ bb {}
  JJ bb {}   JJ bb {}   JJ bb {}}

do_execsql_test 1.5.8 {
  SELECT a, b, 
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN 1 PRECEDING         AND 2 PRECEDING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN 1 PRECEDING         AND 2 PRECEDING ),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 1 PRECEDING         AND 2 PRECEDING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 1 PRECEDING         AND 2 PRECEDING )
    FROM t3 ORDER BY 1, 2, 3;
} {AA aa {} {} {} {}   AA aa {} {} {} {}   AA aa {} {} {} {}
  AA aa {} {} {} {}   AA bb {} {} {} {}   AA bb {} {} {} {}
  AA bb {} {} {} {}   AA bb {} {} {} {}   BB aa {} {} {} {}
  BB aa {} {} {} {}   BB aa {} {} {} {}   BB aa {} {} {} {}
  BB aa {} {} {} {}   BB aa {} {} {} {}   BB bb {} {} {} {}
  BB bb {} {} {} {}   BB bb {} {} {} {}   BB bb {} {} {} {}
  BB bb {} {} {} {}   BB bb {} {} {} {}   CC aa {} {} {} {}
  CC aa {} {} {} {}   CC aa {} {} {} {}   CC aa {} {} {} {}
  CC bb {} {} {} {}   CC bb {} {} {} {}   DD aa {} {} {} {}
  DD aa {} {} {} {}   DD aa {} {} {} {}   DD bb {} {} {} {}
  DD bb {} {} {} {}   DD bb {} {} {} {}   DD bb {} {} {} {}
  EE aa {} {} {} {}   EE aa {} {} {} {}   EE bb {} {} {} {}
  EE bb {} {} {} {}   EE bb {} {} {} {}   FF aa {} {} {} {}
  FF aa {} {} {} {}   FF aa {} {} {} {}   FF aa {} {} {} {}
  FF bb {} {} {} {}   FF bb {} {} {} {}   FF bb {} {} {} {}
  FF bb {} {} {} {}   FF bb {} {} {} {}   FF bb {} {} {} {}
  GG aa {} {} {} {}   GG aa {} {} {} {}   GG aa {} {} {} {}
  GG aa {} {} {} {}   GG bb {} {} {} {}   GG bb {} {} {} {}
  GG bb {} {} {} {}   GG bb {} {} {} {}   HH aa {} {} {} {}
  HH aa {} {} {} {}   HH aa {} {} {} {}   HH bb {} {} {} {}
  HH bb {} {} {} {}   HH bb {} {} {} {}   HH bb {} {} {} {}
  HH bb {} {} {} {}   HH bb {} {} {} {}   II aa {} {} {} {}
  II aa {} {} {} {}   II bb {} {} {} {}   II bb {} {} {} {}
  II bb {} {} {} {}   II bb {} {} {} {}   II bb {} {} {} {}
  JJ aa {} {} {} {}   JJ aa {} {} {} {}   JJ aa {} {} {} {}
  JJ aa {} {} {} {}   JJ bb {} {} {} {}   JJ bb {} {} {} {}
  JJ bb {} {} {} {}   JJ bb {} {} {} {}}

do_execsql_test 1.6.1 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN 2 PRECEDING         AND 1 PRECEDING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa {}   AA aa {}   AA aa {}   AA aa {}   AA bb {}   AA bb {}   AA bb {}
  AA bb {}   BB aa 4685   BB aa 4685   BB aa 4685   BB aa 4685   BB aa 4685
  BB aa 4685   BB bb 4685   BB bb 4685   BB bb 4685   BB bb 4685   BB bb 4685
  BB bb 4685   CC aa 12025   CC aa 12025   CC aa 12025   CC aa 12025
  CC bb 12025   CC bb 12025   DD aa 10462   DD aa 10462   DD aa 10462
  DD bb 10462   DD bb 10462   DD bb 10462   DD bb 10462   EE aa 7154
  EE aa 7154   EE bb 7154   EE bb 7154   EE bb 7154   FF aa 6571   FF aa 6571
  FF aa 6571   FF aa 6571   FF bb 6571   FF bb 6571   FF bb 6571   FF bb 6571
  FF bb 6571   FF bb 6571   GG aa 8207   GG aa 8207   GG aa 8207   GG aa 8207
  GG bb 8207   GG bb 8207   GG bb 8207   GG bb 8207   HH aa 10136
  HH aa 10136   HH aa 10136   HH bb 10136   HH bb 10136   HH bb 10136
  HH bb 10136   HH bb 10136   HH bb 10136   II aa 9911   II aa 9911
  II bb 9911   II bb 9911   II bb 9911   II bb 9911   II bb 9911   JJ aa 9083
  JJ aa 9083   JJ aa 9083   JJ aa 9083   JJ bb 9083   JJ bb 9083   JJ bb 9083
  JJ bb 9083}

do_execsql_test 1.6.2 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 2 PRECEDING         AND 1 PRECEDING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa {}   AA aa {}   AA aa {}   AA aa {}   AA bb 2307   AA bb 2307
  AA bb 2307   AA bb 2307   BB aa 4685   BB aa 4685   BB aa 4685   BB aa 4685
  BB aa 4685   BB aa 4685   BB bb 5251   BB bb 5251   BB bb 5251   BB bb 5251
  BB bb 5251   BB bb 5251   CC aa 7340   CC aa 7340   CC aa 7340   CC aa 7340
  CC bb 6421   CC bb 6421   DD aa 3122   DD aa 3122   DD aa 3122   DD bb 2493
  DD bb 2493   DD bb 2493   DD bb 2493   EE aa 4032   EE aa 4032   EE bb 3597
  EE bb 3597   EE bb 3597   FF aa 2539   FF aa 2539   FF aa 2539   FF aa 2539
  FF bb 3812   FF bb 3812   FF bb 3812   FF bb 3812   FF bb 3812   FF bb 3812
  GG aa 5668   GG aa 5668   GG aa 5668   GG aa 5668   GG bb 5102   GG bb 5102
  GG bb 5102   GG bb 5102   HH aa 4468   HH aa 4468   HH aa 4468   HH bb 5120
  HH bb 5120   HH bb 5120   HH bb 5120   HH bb 5120   HH bb 5120   II aa 5443
  II aa 5443   II bb 4244   II bb 4244   II bb 4244   II bb 4244   II bb 4244
  JJ aa 3640   JJ aa 3640   JJ aa 3640   JJ aa 3640   JJ bb 4604   JJ bb 4604
  JJ bb 4604   JJ bb 4604}

do_execsql_test 1.6.3 {
  SELECT a, b, rank() OVER (ORDER BY a  GROUPS BETWEEN 2 PRECEDING         AND 1 PRECEDING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 1   AA aa 1   AA aa 1   AA aa 1   AA bb 1   AA bb 1   AA bb 1
  AA bb 1   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9
  BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   CC aa 21
  CC aa 21   CC aa 21   CC aa 21   CC bb 21   CC bb 21   DD aa 27   DD aa 27
  DD aa 27   DD bb 27   DD bb 27   DD bb 27   DD bb 27   EE aa 34   EE aa 34
  EE bb 34   EE bb 34   EE bb 34   FF aa 39   FF aa 39   FF aa 39   FF aa 39
  FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   GG aa 49
  GG aa 49   GG aa 49   GG aa 49   GG bb 49   GG bb 49   GG bb 49   GG bb 49
  HH aa 57   HH aa 57   HH aa 57   HH bb 57   HH bb 57   HH bb 57   HH bb 57
  HH bb 57   HH bb 57   II aa 66   II aa 66   II bb 66   II bb 66   II bb 66
  II bb 66   II bb 66   JJ aa 73   JJ aa 73   JJ aa 73   JJ aa 73   JJ bb 73
  JJ bb 73   JJ bb 73   JJ bb 73}

do_execsql_test 1.6.4 {
  SELECT a, b, max(c) OVER (ORDER BY a,b  GROUPS BETWEEN 2 PRECEDING         AND 1 PRECEDING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa {}   AA aa {}   AA aa {}   AA aa {}   AA bb 934   AA bb 934
  AA bb 934   AA bb 934   BB aa 934   BB aa 934   BB aa 934   BB aa 934
  BB aa 934   BB aa 934   BB bb 870   BB bb 870   BB bb 870   BB bb 870
  BB bb 870   BB bb 870   CC aa 840   CC aa 840   CC aa 840   CC aa 840
  CC bb 840   CC bb 840   DD aa 822   DD aa 822   DD aa 822   DD bb 845
  DD bb 845   DD bb 845   DD bb 845   EE aa 959   EE aa 959   EE bb 959
  EE bb 959   EE bb 959   FF aa 777   FF aa 777   FF aa 777   FF aa 777
  FF bb 768   FF bb 768   FF bb 768   FF bb 768   FF bb 768   FF bb 768
  GG aa 938   GG aa 938   GG aa 938   GG aa 938   GG bb 938   GG bb 938
  GG bb 938   GG bb 938   HH aa 938   HH aa 938   HH aa 938   HH bb 979
  HH bb 979   HH bb 979   HH bb 979   HH bb 979   HH bb 979   II aa 979
  II aa 979   II bb 963   II bb 963   II bb 963   II bb 963   II bb 963
  JJ aa 805   JJ aa 805   JJ aa 805   JJ aa 805   JJ bb 899   JJ bb 899
  JJ bb 899   JJ bb 899}

do_execsql_test 1.6.5 {
  SELECT a, b, min(c) OVER (ORDER BY a,b  GROUPS BETWEEN 2 PRECEDING         AND 1 PRECEDING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa {}   AA aa {}   AA aa {}   AA aa {}   AA bb 223   AA bb 223
  AA bb 223   AA bb 223   BB aa 223   BB aa 223   BB aa 223   BB aa 223
  BB aa 223   BB aa 223   BB bb 247   BB bb 247   BB bb 247   BB bb 247
  BB bb 247   BB bb 247   CC aa 247   CC aa 247   CC aa 247   CC aa 247
  CC bb 158   CC bb 158   DD aa 158   DD aa 158   DD aa 158   DD bb 224
  DD bb 224   DD bb 224   DD bb 224   EE aa 224   EE aa 224   EE bb 113
  EE bb 113   EE bb 113   FF aa 113   FF aa 113   FF aa 113   FF aa 113
  FF bb 208   FF bb 208   FF bb 208   FF bb 208   FF bb 208   FF bb 208
  GG aa 102   GG aa 102   GG aa 102   GG aa 102   GG bb 102   GG bb 102
  GG bb 102   GG bb 102   HH aa 148   HH aa 148   HH aa 148   HH bb 160
  HH bb 160   HH bb 160   HH bb 160   HH bb 160   HH bb 160   II aa 133
  II aa 133   II bb 133   II bb 133   II bb 133   II bb 133   II bb 133
  JJ aa 250   JJ aa 250   JJ aa 250   JJ aa 250   JJ bb 113   JJ bb 113
  JJ bb 113   JJ bb 113}

do_execsql_test 1.6.6 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN 2 PRECEDING         AND 1 PRECEDING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa {}   AA aa {}   AA aa {}   AA aa {}   AA bb {}   AA bb {}   AA bb {}
  AA bb {}   BB aa 4685   BB aa 4685   BB aa 4685   BB aa 4685   BB aa 4685
  BB aa 4685   BB bb 4685   BB bb 4685   BB bb 4685   BB bb 4685   BB bb 4685
  BB bb 4685   CC aa 12025   CC aa 12025   CC aa 12025   CC aa 12025
  CC bb 12025   CC bb 12025   DD aa 10462   DD aa 10462   DD aa 10462
  DD bb 10462   DD bb 10462   DD bb 10462   DD bb 10462   EE aa 7154
  EE aa 7154   EE bb 7154   EE bb 7154   EE bb 7154   FF aa 6571   FF aa 6571
  FF aa 6571   FF aa 6571   FF bb 6571   FF bb 6571   FF bb 6571   FF bb 6571
  FF bb 6571   FF bb 6571   GG aa 8207   GG aa 8207   GG aa 8207   GG aa 8207
  GG bb 8207   GG bb 8207   GG bb 8207   GG bb 8207   HH aa 10136
  HH aa 10136   HH aa 10136   HH bb 10136   HH bb 10136   HH bb 10136
  HH bb 10136   HH bb 10136   HH bb 10136   II aa 9911   II aa 9911
  II bb 9911   II bb 9911   II bb 9911   II bb 9911   II bb 9911   JJ aa 9083
  JJ aa 9083   JJ aa 9083   JJ aa 9083   JJ bb 9083   JJ bb 9083   JJ bb 9083
  JJ bb 9083}

do_execsql_test 1.6.7 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 2 PRECEDING         AND 1 PRECEDING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa {}   AA aa {}   AA aa {}   AA aa {}   AA bb 2307   AA bb 2307
  AA bb 2307   AA bb 2307   BB aa 4685   BB aa 4685   BB aa 4685   BB aa 4685
  BB aa 4685   BB aa 4685   BB bb 5251   BB bb 5251   BB bb 5251   BB bb 5251
  BB bb 5251   BB bb 5251   CC aa 7340   CC aa 7340   CC aa 7340   CC aa 7340
  CC bb 6421   CC bb 6421   DD aa 3122   DD aa 3122   DD aa 3122   DD bb 2493
  DD bb 2493   DD bb 2493   DD bb 2493   EE aa 4032   EE aa 4032   EE bb 3597
  EE bb 3597   EE bb 3597   FF aa 2539   FF aa 2539   FF aa 2539   FF aa 2539
  FF bb 3812   FF bb 3812   FF bb 3812   FF bb 3812   FF bb 3812   FF bb 3812
  GG aa 5668   GG aa 5668   GG aa 5668   GG aa 5668   GG bb 5102   GG bb 5102
  GG bb 5102   GG bb 5102   HH aa 4468   HH aa 4468   HH aa 4468   HH bb 5120
  HH bb 5120   HH bb 5120   HH bb 5120   HH bb 5120   HH bb 5120   II aa 5443
  II aa 5443   II bb 4244   II bb 4244   II bb 4244   II bb 4244   II bb 4244
  JJ aa 3640   JJ aa 3640   JJ aa 3640   JJ aa 3640   JJ bb 4604   JJ bb 4604
  JJ bb 4604   JJ bb 4604}

do_execsql_test 1.6.8 {
  SELECT a, b, 
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN 2 PRECEDING         AND 1 PRECEDING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN 2 PRECEDING         AND 1 PRECEDING ),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 2 PRECEDING         AND 1 PRECEDING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 2 PRECEDING         AND 1 PRECEDING )
    FROM t3 ORDER BY 1, 2, 3;
} {AA aa {} {} {} {}   AA aa {} {} {} {}   AA aa {} {} {} {}
  AA aa {} {} {} {}   AA bb {} {} 2307 2307   AA bb {} {} 2307 2307
  AA bb {} {} 2307 2307   AA bb {} {} 2307 2307   BB aa 4685 4685 4685 4685
  BB aa 4685 4685 4685 4685   BB aa 4685 4685 4685 4685
  BB aa 4685 4685 4685 4685   BB aa 4685 4685 4685 4685
  BB aa 4685 4685 4685 4685   BB bb 4685 4685 5251 5251
  BB bb 4685 4685 5251 5251   BB bb 4685 4685 5251 5251
  BB bb 4685 4685 5251 5251   BB bb 4685 4685 5251 5251
  BB bb 4685 4685 5251 5251   CC aa 12025 12025 7340 7340
  CC aa 12025 12025 7340 7340   CC aa 12025 12025 7340 7340
  CC aa 12025 12025 7340 7340   CC bb 12025 12025 6421 6421
  CC bb 12025 12025 6421 6421   DD aa 10462 10462 3122 3122
  DD aa 10462 10462 3122 3122   DD aa 10462 10462 3122 3122
  DD bb 10462 10462 2493 2493   DD bb 10462 10462 2493 2493
  DD bb 10462 10462 2493 2493   DD bb 10462 10462 2493 2493
  EE aa 7154 7154 4032 4032   EE aa 7154 7154 4032 4032
  EE bb 7154 7154 3597 3597   EE bb 7154 7154 3597 3597
  EE bb 7154 7154 3597 3597   FF aa 6571 6571 2539 2539
  FF aa 6571 6571 2539 2539   FF aa 6571 6571 2539 2539
  FF aa 6571 6571 2539 2539   FF bb 6571 6571 3812 3812
  FF bb 6571 6571 3812 3812   FF bb 6571 6571 3812 3812
  FF bb 6571 6571 3812 3812   FF bb 6571 6571 3812 3812
  FF bb 6571 6571 3812 3812   GG aa 8207 8207 5668 5668
  GG aa 8207 8207 5668 5668   GG aa 8207 8207 5668 5668
  GG aa 8207 8207 5668 5668   GG bb 8207 8207 5102 5102
  GG bb 8207 8207 5102 5102   GG bb 8207 8207 5102 5102
  GG bb 8207 8207 5102 5102   HH aa 10136 10136 4468 4468
  HH aa 10136 10136 4468 4468   HH aa 10136 10136 4468 4468
  HH bb 10136 10136 5120 5120   HH bb 10136 10136 5120 5120
  HH bb 10136 10136 5120 5120   HH bb 10136 10136 5120 5120
  HH bb 10136 10136 5120 5120   HH bb 10136 10136 5120 5120
  II aa 9911 9911 5443 5443   II aa 9911 9911 5443 5443
  II bb 9911 9911 4244 4244   II bb 9911 9911 4244 4244
  II bb 9911 9911 4244 4244   II bb 9911 9911 4244 4244
  II bb 9911 9911 4244 4244   JJ aa 9083 9083 3640 3640
  JJ aa 9083 9083 3640 3640   JJ aa 9083 9083 3640 3640
  JJ aa 9083 9083 3640 3640   JJ bb 9083 9083 4604 4604
  JJ bb 9083 9083 4604 4604   JJ bb 9083 9083 4604 4604
  JJ bb 9083 9083 4604 4604}

do_execsql_test 1.7.1 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN 3 PRECEDING         AND 1 PRECEDING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa {}   AA aa {}   AA aa {}   AA aa {}   AA bb {}   AA bb {}   AA bb {}
  AA bb {}   BB aa 4685   BB aa 4685   BB aa 4685   BB aa 4685   BB aa 4685
  BB aa 4685   BB bb 4685   BB bb 4685   BB bb 4685   BB bb 4685   BB bb 4685
  BB bb 4685   CC aa 12025   CC aa 12025   CC aa 12025   CC aa 12025
  CC bb 12025   CC bb 12025   DD aa 15147   DD aa 15147   DD aa 15147
  DD bb 15147   DD bb 15147   DD bb 15147   DD bb 15147   EE aa 14494
  EE aa 14494   EE bb 14494   EE bb 14494   EE bb 14494   FF aa 9693
  FF aa 9693   FF aa 9693   FF aa 9693   FF bb 9693   FF bb 9693   FF bb 9693
  FF bb 9693   FF bb 9693   FF bb 9693   GG aa 12239   GG aa 12239
  GG aa 12239   GG aa 12239   GG bb 12239   GG bb 12239   GG bb 12239
  GG bb 12239   HH aa 12675   HH aa 12675   HH aa 12675   HH bb 12675
  HH bb 12675   HH bb 12675   HH bb 12675   HH bb 12675   HH bb 12675
  II aa 15579   II aa 15579   II bb 15579   II bb 15579   II bb 15579
  II bb 15579   II bb 15579   JJ aa 13551   JJ aa 13551   JJ aa 13551
  JJ aa 13551   JJ bb 13551   JJ bb 13551   JJ bb 13551   JJ bb 13551}

do_execsql_test 1.7.2 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 3 PRECEDING         AND 1 PRECEDING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa {}   AA aa {}   AA aa {}   AA aa {}   AA bb 2307   AA bb 2307
  AA bb 2307   AA bb 2307   BB aa 4685   BB aa 4685   BB aa 4685   BB aa 4685
  BB aa 4685   BB aa 4685   BB bb 7558   BB bb 7558   BB bb 7558   BB bb 7558
  BB bb 7558   BB bb 7558   CC aa 9718   CC aa 9718   CC aa 9718   CC aa 9718
  CC bb 9294   CC bb 9294   DD aa 7589   DD aa 7589   DD aa 7589   DD bb 4447
  DD bb 4447   DD bb 4447   DD bb 4447   EE aa 5200   EE aa 5200   EE bb 4922
  EE bb 4922   EE bb 4922   FF aa 5246   FF aa 5246   FF aa 5246   FF aa 5246
  FF bb 4702   FF bb 4702   FF bb 4702   FF bb 4702   FF bb 4702   FF bb 4702
  GG aa 7317   GG aa 7317   GG aa 7317   GG aa 7317   GG bb 7265   GG bb 7265
  GG bb 7265   GG bb 7265   HH aa 7973   HH aa 7973   HH aa 7973   HH bb 6717
  HH bb 6717   HH bb 6717   HH bb 6717   HH bb 6717   HH bb 6717   II aa 8314
  II aa 8314   II bb 6493   II bb 6493   II bb 6493   II bb 6493   II bb 6493
  JJ aa 6834   JJ aa 6834   JJ aa 6834   JJ aa 6834   JJ bb 5654   JJ bb 5654
  JJ bb 5654   JJ bb 5654}

do_execsql_test 1.7.3 {
  SELECT a, b, rank() OVER (ORDER BY a  GROUPS BETWEEN 3 PRECEDING         AND 1 PRECEDING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 1   AA aa 1   AA aa 1   AA aa 1   AA bb 1   AA bb 1   AA bb 1
  AA bb 1   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9
  BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   CC aa 21
  CC aa 21   CC aa 21   CC aa 21   CC bb 21   CC bb 21   DD aa 27   DD aa 27
  DD aa 27   DD bb 27   DD bb 27   DD bb 27   DD bb 27   EE aa 34   EE aa 34
  EE bb 34   EE bb 34   EE bb 34   FF aa 39   FF aa 39   FF aa 39   FF aa 39
  FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   GG aa 49
  GG aa 49   GG aa 49   GG aa 49   GG bb 49   GG bb 49   GG bb 49   GG bb 49
  HH aa 57   HH aa 57   HH aa 57   HH bb 57   HH bb 57   HH bb 57   HH bb 57
  HH bb 57   HH bb 57   II aa 66   II aa 66   II bb 66   II bb 66   II bb 66
  II bb 66   II bb 66   JJ aa 73   JJ aa 73   JJ aa 73   JJ aa 73   JJ bb 73
  JJ bb 73   JJ bb 73   JJ bb 73}

do_execsql_test 1.7.4 {
  SELECT a, b, max(c) OVER (ORDER BY a,b  GROUPS BETWEEN 3 PRECEDING         AND 1 PRECEDING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa {}   AA aa {}   AA aa {}   AA aa {}   AA bb 934   AA bb 934
  AA bb 934   AA bb 934   BB aa 934   BB aa 934   BB aa 934   BB aa 934
  BB aa 934   BB aa 934   BB bb 934   BB bb 934   BB bb 934   BB bb 934
  BB bb 934   BB bb 934   CC aa 870   CC aa 870   CC aa 870   CC aa 870
  CC bb 840   CC bb 840   DD aa 840   DD aa 840   DD aa 840   DD bb 845
  DD bb 845   DD bb 845   DD bb 845   EE aa 959   EE aa 959   EE bb 959
  EE bb 959   EE bb 959   FF aa 959   FF aa 959   FF aa 959   FF aa 959
  FF bb 777   FF bb 777   FF bb 777   FF bb 777   FF bb 777   FF bb 777
  GG aa 938   GG aa 938   GG aa 938   GG aa 938   GG bb 938   GG bb 938
  GG bb 938   GG bb 938   HH aa 938   HH aa 938   HH aa 938   HH bb 979
  HH bb 979   HH bb 979   HH bb 979   HH bb 979   HH bb 979   II aa 979
  II aa 979   II bb 979   II bb 979   II bb 979   II bb 979   II bb 979
  JJ aa 963   JJ aa 963   JJ aa 963   JJ aa 963   JJ bb 899   JJ bb 899
  JJ bb 899   JJ bb 899}

do_execsql_test 1.7.5 {
  SELECT a, b, min(c) OVER (ORDER BY a,b  GROUPS BETWEEN 3 PRECEDING         AND 1 PRECEDING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa {}   AA aa {}   AA aa {}   AA aa {}   AA bb 223   AA bb 223
  AA bb 223   AA bb 223   BB aa 223   BB aa 223   BB aa 223   BB aa 223
  BB aa 223   BB aa 223   BB bb 223   BB bb 223   BB bb 223   BB bb 223
  BB bb 223   BB bb 223   CC aa 247   CC aa 247   CC aa 247   CC aa 247
  CC bb 158   CC bb 158   DD aa 158   DD aa 158   DD aa 158   DD bb 158
  DD bb 158   DD bb 158   DD bb 158   EE aa 224   EE aa 224   EE bb 113
  EE bb 113   EE bb 113   FF aa 113   FF aa 113   FF aa 113   FF aa 113
  FF bb 113   FF bb 113   FF bb 113   FF bb 113   FF bb 113   FF bb 113
  GG aa 102   GG aa 102   GG aa 102   GG aa 102   GG bb 102   GG bb 102
  GG bb 102   GG bb 102   HH aa 102   HH aa 102   HH aa 102   HH bb 148
  HH bb 148   HH bb 148   HH bb 148   HH bb 148   HH bb 148   II aa 133
  II aa 133   II bb 133   II bb 133   II bb 133   II bb 133   II bb 133
  JJ aa 133   JJ aa 133   JJ aa 133   JJ aa 133   JJ bb 113   JJ bb 113
  JJ bb 113   JJ bb 113}

do_execsql_test 1.7.6 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN 3 PRECEDING         AND 1 PRECEDING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa {}   AA aa {}   AA aa {}   AA aa {}   AA bb {}   AA bb {}   AA bb {}
  AA bb {}   BB aa 4685   BB aa 4685   BB aa 4685   BB aa 4685   BB aa 4685
  BB aa 4685   BB bb 4685   BB bb 4685   BB bb 4685   BB bb 4685   BB bb 4685
  BB bb 4685   CC aa 12025   CC aa 12025   CC aa 12025   CC aa 12025
  CC bb 12025   CC bb 12025   DD aa 15147   DD aa 15147   DD aa 15147
  DD bb 15147   DD bb 15147   DD bb 15147   DD bb 15147   EE aa 14494
  EE aa 14494   EE bb 14494   EE bb 14494   EE bb 14494   FF aa 9693
  FF aa 9693   FF aa 9693   FF aa 9693   FF bb 9693   FF bb 9693   FF bb 9693
  FF bb 9693   FF bb 9693   FF bb 9693   GG aa 12239   GG aa 12239
  GG aa 12239   GG aa 12239   GG bb 12239   GG bb 12239   GG bb 12239
  GG bb 12239   HH aa 12675   HH aa 12675   HH aa 12675   HH bb 12675
  HH bb 12675   HH bb 12675   HH bb 12675   HH bb 12675   HH bb 12675
  II aa 15579   II aa 15579   II bb 15579   II bb 15579   II bb 15579
  II bb 15579   II bb 15579   JJ aa 13551   JJ aa 13551   JJ aa 13551
  JJ aa 13551   JJ bb 13551   JJ bb 13551   JJ bb 13551   JJ bb 13551}

do_execsql_test 1.7.7 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 3 PRECEDING         AND 1 PRECEDING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa {}   AA aa {}   AA aa {}   AA aa {}   AA bb 2307   AA bb 2307
  AA bb 2307   AA bb 2307   BB aa 4685   BB aa 4685   BB aa 4685   BB aa 4685
  BB aa 4685   BB aa 4685   BB bb 7558   BB bb 7558   BB bb 7558   BB bb 7558
  BB bb 7558   BB bb 7558   CC aa 9718   CC aa 9718   CC aa 9718   CC aa 9718
  CC bb 9294   CC bb 9294   DD aa 7589   DD aa 7589   DD aa 7589   DD bb 4447
  DD bb 4447   DD bb 4447   DD bb 4447   EE aa 5200   EE aa 5200   EE bb 4922
  EE bb 4922   EE bb 4922   FF aa 5246   FF aa 5246   FF aa 5246   FF aa 5246
  FF bb 4702   FF bb 4702   FF bb 4702   FF bb 4702   FF bb 4702   FF bb 4702
  GG aa 7317   GG aa 7317   GG aa 7317   GG aa 7317   GG bb 7265   GG bb 7265
  GG bb 7265   GG bb 7265   HH aa 7973   HH aa 7973   HH aa 7973   HH bb 6717
  HH bb 6717   HH bb 6717   HH bb 6717   HH bb 6717   HH bb 6717   II aa 8314
  II aa 8314   II bb 6493   II bb 6493   II bb 6493   II bb 6493   II bb 6493
  JJ aa 6834   JJ aa 6834   JJ aa 6834   JJ aa 6834   JJ bb 5654   JJ bb 5654
  JJ bb 5654   JJ bb 5654}

do_execsql_test 1.7.8 {
  SELECT a, b, 
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN 3 PRECEDING         AND 1 PRECEDING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN 3 PRECEDING         AND 1 PRECEDING ),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 3 PRECEDING         AND 1 PRECEDING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 3 PRECEDING         AND 1 PRECEDING )
    FROM t3 ORDER BY 1, 2, 3;
} {AA aa {} {} {} {}   AA aa {} {} {} {}   AA aa {} {} {} {}
  AA aa {} {} {} {}   AA bb {} {} 2307 2307   AA bb {} {} 2307 2307
  AA bb {} {} 2307 2307   AA bb {} {} 2307 2307   BB aa 4685 4685 4685 4685
  BB aa 4685 4685 4685 4685   BB aa 4685 4685 4685 4685
  BB aa 4685 4685 4685 4685   BB aa 4685 4685 4685 4685
  BB aa 4685 4685 4685 4685   BB bb 4685 4685 7558 7558
  BB bb 4685 4685 7558 7558   BB bb 4685 4685 7558 7558
  BB bb 4685 4685 7558 7558   BB bb 4685 4685 7558 7558
  BB bb 4685 4685 7558 7558   CC aa 12025 12025 9718 9718
  CC aa 12025 12025 9718 9718   CC aa 12025 12025 9718 9718
  CC aa 12025 12025 9718 9718   CC bb 12025 12025 9294 9294
  CC bb 12025 12025 9294 9294   DD aa 15147 15147 7589 7589
  DD aa 15147 15147 7589 7589   DD aa 15147 15147 7589 7589
  DD bb 15147 15147 4447 4447   DD bb 15147 15147 4447 4447
  DD bb 15147 15147 4447 4447   DD bb 15147 15147 4447 4447
  EE aa 14494 14494 5200 5200   EE aa 14494 14494 5200 5200
  EE bb 14494 14494 4922 4922   EE bb 14494 14494 4922 4922
  EE bb 14494 14494 4922 4922   FF aa 9693 9693 5246 5246
  FF aa 9693 9693 5246 5246   FF aa 9693 9693 5246 5246
  FF aa 9693 9693 5246 5246   FF bb 9693 9693 4702 4702
  FF bb 9693 9693 4702 4702   FF bb 9693 9693 4702 4702
  FF bb 9693 9693 4702 4702   FF bb 9693 9693 4702 4702
  FF bb 9693 9693 4702 4702   GG aa 12239 12239 7317 7317
  GG aa 12239 12239 7317 7317   GG aa 12239 12239 7317 7317
  GG aa 12239 12239 7317 7317   GG bb 12239 12239 7265 7265
  GG bb 12239 12239 7265 7265   GG bb 12239 12239 7265 7265
  GG bb 12239 12239 7265 7265   HH aa 12675 12675 7973 7973
  HH aa 12675 12675 7973 7973   HH aa 12675 12675 7973 7973
  HH bb 12675 12675 6717 6717   HH bb 12675 12675 6717 6717
  HH bb 12675 12675 6717 6717   HH bb 12675 12675 6717 6717
  HH bb 12675 12675 6717 6717   HH bb 12675 12675 6717 6717
  II aa 15579 15579 8314 8314   II aa 15579 15579 8314 8314
  II bb 15579 15579 6493 6493   II bb 15579 15579 6493 6493
  II bb 15579 15579 6493 6493   II bb 15579 15579 6493 6493
  II bb 15579 15579 6493 6493   JJ aa 13551 13551 6834 6834
  JJ aa 13551 13551 6834 6834   JJ aa 13551 13551 6834 6834
  JJ aa 13551 13551 6834 6834   JJ bb 13551 13551 5654 5654
  JJ bb 13551 13551 5654 5654   JJ bb 13551 13551 5654 5654
  JJ bb 13551 13551 5654 5654}

do_execsql_test 1.8.1 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN 3 PRECEDING         AND 0 PRECEDING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 4685   AA aa 4685   AA aa 4685   AA aa 4685   AA bb 4685   AA bb 4685
  AA bb 4685   AA bb 4685   BB aa 12025   BB aa 12025   BB aa 12025
  BB aa 12025   BB aa 12025   BB aa 12025   BB bb 12025   BB bb 12025
  BB bb 12025   BB bb 12025   BB bb 12025   BB bb 12025   CC aa 15147
  CC aa 15147   CC aa 15147   CC aa 15147   CC bb 15147   CC bb 15147
  DD aa 19179   DD aa 19179   DD aa 19179   DD bb 19179   DD bb 19179
  DD bb 19179   DD bb 19179   EE aa 17033   EE aa 17033   EE bb 17033
  EE bb 17033   EE bb 17033   FF aa 15361   FF aa 15361   FF aa 15361
  FF aa 15361   FF bb 15361   FF bb 15361   FF bb 15361   FF bb 15361
  FF bb 15361   FF bb 15361   GG aa 16707   GG aa 16707   GG aa 16707
  GG aa 16707   GG bb 16707   GG bb 16707   GG bb 16707   GG bb 16707
  HH aa 18118   HH aa 18118   HH aa 18118   HH bb 18118   HH bb 18118
  HH bb 18118   HH bb 18118   HH bb 18118   HH bb 18118   II aa 19219
  II aa 19219   II bb 19219   II bb 19219   II bb 19219   II bb 19219
  II bb 19219   JJ aa 17351   JJ aa 17351   JJ aa 17351   JJ aa 17351
  JJ bb 17351   JJ bb 17351   JJ bb 17351   JJ bb 17351}

do_execsql_test 1.8.2 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 3 PRECEDING         AND 0 PRECEDING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 2307   AA aa 2307   AA aa 2307   AA aa 2307   AA bb 4685   AA bb 4685
  AA bb 4685   AA bb 4685   BB aa 7558   BB aa 7558   BB aa 7558   BB aa 7558
  BB aa 7558   BB aa 7558   BB bb 12025   BB bb 12025   BB bb 12025
  BB bb 12025   BB bb 12025   BB bb 12025   CC aa 11672   CC aa 11672
  CC aa 11672   CC aa 11672   CC bb 10462   CC bb 10462   DD aa 8914
  DD aa 8914   DD aa 8914   DD bb 7154   DD bb 7154   DD bb 7154   DD bb 7154
  EE aa 6090   EE aa 6090   EE bb 6571   EE bb 6571   EE bb 6571   FF aa 7409
  FF aa 7409   FF aa 7409   FF aa 7409   FF bb 8207   FF bb 8207   FF bb 8207
  FF bb 8207   FF bb 8207   FF bb 8207   GG aa 8914   GG aa 8914   GG aa 8914
  GG aa 8914   GG bb 10136   GG bb 10136   GG bb 10136   GG bb 10136
  HH aa 10222   HH aa 10222   HH aa 10222   HH bb 9911   HH bb 9911
  HH bb 9911   HH bb 9911   HH bb 9911   HH bb 9911   II aa 9364   II aa 9364
  II bb 9083   II bb 9083   II bb 9083   II bb 9083   II bb 9083   JJ aa 8848
  JJ aa 8848   JJ aa 8848   JJ aa 8848   JJ bb 7440   JJ bb 7440   JJ bb 7440
  JJ bb 7440}

do_execsql_test 1.8.3 {
  SELECT a, b, rank() OVER (ORDER BY a  GROUPS BETWEEN 3 PRECEDING         AND 0 PRECEDING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 1   AA aa 1   AA aa 1   AA aa 1   AA bb 1   AA bb 1   AA bb 1
  AA bb 1   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9
  BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   CC aa 21
  CC aa 21   CC aa 21   CC aa 21   CC bb 21   CC bb 21   DD aa 27   DD aa 27
  DD aa 27   DD bb 27   DD bb 27   DD bb 27   DD bb 27   EE aa 34   EE aa 34
  EE bb 34   EE bb 34   EE bb 34   FF aa 39   FF aa 39   FF aa 39   FF aa 39
  FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   GG aa 49
  GG aa 49   GG aa 49   GG aa 49   GG bb 49   GG bb 49   GG bb 49   GG bb 49
  HH aa 57   HH aa 57   HH aa 57   HH bb 57   HH bb 57   HH bb 57   HH bb 57
  HH bb 57   HH bb 57   II aa 66   II aa 66   II bb 66   II bb 66   II bb 66
  II bb 66   II bb 66   JJ aa 73   JJ aa 73   JJ aa 73   JJ aa 73   JJ bb 73
  JJ bb 73   JJ bb 73   JJ bb 73}

do_execsql_test 1.8.4 {
  SELECT a, b, max(c) OVER (ORDER BY a,b  GROUPS BETWEEN 3 PRECEDING         AND 0 PRECEDING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 934   AA aa 934   AA aa 934   AA aa 934   AA bb 934   AA bb 934
  AA bb 934   AA bb 934   BB aa 934   BB aa 934   BB aa 934   BB aa 934
  BB aa 934   BB aa 934   BB bb 934   BB bb 934   BB bb 934   BB bb 934
  BB bb 934   BB bb 934   CC aa 870   CC aa 870   CC aa 870   CC aa 870
  CC bb 840   CC bb 840   DD aa 845   DD aa 845   DD aa 845   DD bb 959
  DD bb 959   DD bb 959   DD bb 959   EE aa 959   EE aa 959   EE bb 959
  EE bb 959   EE bb 959   FF aa 959   FF aa 959   FF aa 959   FF aa 959
  FF bb 938   FF bb 938   FF bb 938   FF bb 938   FF bb 938   FF bb 938
  GG aa 938   GG aa 938   GG aa 938   GG aa 938   GG bb 938   GG bb 938
  GG bb 938   GG bb 938   HH aa 979   HH aa 979   HH aa 979   HH bb 979
  HH bb 979   HH bb 979   HH bb 979   HH bb 979   HH bb 979   II aa 979
  II aa 979   II bb 979   II bb 979   II bb 979   II bb 979   II bb 979
  JJ aa 963   JJ aa 963   JJ aa 963   JJ aa 963   JJ bb 899   JJ bb 899
  JJ bb 899   JJ bb 899}

do_execsql_test 1.8.5 {
  SELECT a, b, min(c) OVER (ORDER BY a,b  GROUPS BETWEEN 3 PRECEDING         AND 0 PRECEDING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 223   AA aa 223   AA aa 223   AA aa 223   AA bb 223   AA bb 223
  AA bb 223   AA bb 223   BB aa 223   BB aa 223   BB aa 223   BB aa 223
  BB aa 223   BB aa 223   BB bb 223   BB bb 223   BB bb 223   BB bb 223
  BB bb 223   BB bb 223   CC aa 158   CC aa 158   CC aa 158   CC aa 158
  CC bb 158   CC bb 158   DD aa 158   DD aa 158   DD aa 158   DD bb 158
  DD bb 158   DD bb 158   DD bb 158   EE aa 113   EE aa 113   EE bb 113
  EE bb 113   EE bb 113   FF aa 113   FF aa 113   FF aa 113   FF aa 113
  FF bb 102   FF bb 102   FF bb 102   FF bb 102   FF bb 102   FF bb 102
  GG aa 102   GG aa 102   GG aa 102   GG aa 102   GG bb 102   GG bb 102
  GG bb 102   GG bb 102   HH aa 102   HH aa 102   HH aa 102   HH bb 133
  HH bb 133   HH bb 133   HH bb 133   HH bb 133   HH bb 133   II aa 133
  II aa 133   II bb 133   II bb 133   II bb 133   II bb 133   II bb 133
  JJ aa 113   JJ aa 113   JJ aa 113   JJ aa 113   JJ bb 113   JJ bb 113
  JJ bb 113   JJ bb 113}

do_execsql_test 1.8.6 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN 3 PRECEDING         AND 0 PRECEDING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 3751   AA aa 3774   AA aa 4446   AA aa 4462   AA bb 3815   AA bb 4058
  AA bb 4113   AA bb 4376   BB aa 11263   BB aa 11365   BB aa 11613
  BB aa 11626   BB aa 11632   BB aa 11778   BB bb 11185   BB bb 11233
  BB bb 11239   BB bb 11314   BB bb 11320   BB bb 11392   CC aa 14388
  CC aa 14540   CC aa 14717   CC aa 14989   CC bb 14325   CC bb 14801
  DD aa 18334   DD aa 18923   DD aa 18955   DD bb 18220   DD bb 18385
  DD bb 18463   DD bb 18941   EE aa 16256   EE aa 16920   EE bb 16265
  EE bb 16404   EE bb 16781   FF aa 14691   FF aa 14694   FF aa 14743
  FF aa 15153   FF bb 14423   FF bb 14491   FF bb 14635   FF bb 14787
  FF bb 15066   FF bb 15259   GG aa 16073   GG aa 16227   GG aa 16372
  GG aa 16559   GG bb 15769   GG bb 15778   GG bb 15863   GG bb 16547
  HH aa 17139   HH aa 17328   HH aa 17638   HH bb 17155   HH bb 17388
  HH bb 17435   HH bb 17763   HH bb 17788   HH bb 17985   II aa 18567
  II aa 18821   II bb 18414   II bb 18548   II bb 18776   II bb 18798
  II bb 18969   JJ aa 16452   JJ aa 16583   JJ aa 17117   JJ aa 17238
  JJ bb 16512   JJ bb 16997   JJ bb 17015   JJ bb 17094}

do_execsql_test 1.8.7 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 3 PRECEDING         AND 0 PRECEDING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 1373   AA aa 1396   AA aa 2068   AA aa 2084   AA bb 3815   AA bb 4058
  AA bb 4113   AA bb 4376   BB aa 6796   BB aa 6898   BB aa 7146   BB aa 7159
  BB aa 7165   BB aa 7311   BB bb 11185   BB bb 11233   BB bb 11239
  BB bb 11314   BB bb 11320   BB bb 11392   CC aa 10913   CC aa 11065
  CC aa 11242   CC aa 11514   CC bb 9640   CC bb 10116   DD aa 8069
  DD aa 8658   DD aa 8690   DD bb 6195   DD bb 6360   DD bb 6438   DD bb 6916
  EE aa 5313   EE aa 5977   EE bb 5803   EE bb 5942   EE bb 6319   FF aa 6739
  FF aa 6742   FF aa 6791   FF aa 7201   FF bb 7269   FF bb 7337   FF bb 7481
  FF bb 7633   FF bb 7912   FF bb 8105   GG aa 8280   GG aa 8434   GG aa 8579
  GG aa 8766   GG bb 9198   GG bb 9207   GG bb 9292   GG bb 9976   HH aa 9243
  HH aa 9432   HH aa 9742   HH bb 8948   HH bb 9181   HH bb 9228   HH bb 9556
  HH bb 9581   HH bb 9778   II aa 8712   II aa 8966   II bb 8278   II bb 8412
  II bb 8640   II bb 8662   II bb 8833   JJ aa 7949   JJ aa 8080   JJ aa 8614
  JJ aa 8735   JJ bb 6601   JJ bb 7086   JJ bb 7104   JJ bb 7183}

do_execsql_test 1.8.8 {
  SELECT a, b, 
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN 3 PRECEDING         AND 0 PRECEDING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN 3 PRECEDING         AND 0 PRECEDING ),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 3 PRECEDING         AND 0 PRECEDING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 3 PRECEDING         AND 0 PRECEDING )
    FROM t3 ORDER BY 1, 2, 3;
} {AA aa 3751 4685 1373 2307   AA aa 3774 4685 1396 2307
  AA aa 4446 4685 2068 2307   AA aa 4462 4685 2084 2307
  AA bb 3815 4685 3815 4685   AA bb 4058 4685 4058 4685
  AA bb 4113 4685 4113 4685   AA bb 4376 4685 4376 4685
  BB aa 11263 12025 6796 7558   BB aa 11365 12025 6898 7558
  BB aa 11613 12025 7146 7558   BB aa 11626 12025 7159 7558
  BB aa 11632 12025 7165 7558   BB aa 11778 12025 7311 7558
  BB bb 11185 12025 11185 12025   BB bb 11233 12025 11233 12025
  BB bb 11239 12025 11239 12025   BB bb 11314 12025 11314 12025
  BB bb 11320 12025 11320 12025   BB bb 11392 12025 11392 12025
  CC aa 14388 15147 10913 11672   CC aa 14540 15147 11065 11672
  CC aa 14717 15147 11242 11672   CC aa 14989 15147 11514 11672
  CC bb 14325 15147 9640 10462   CC bb 14801 15147 10116 10462
  DD aa 18334 19179 8069 8914   DD aa 18923 19179 8658 8914
  DD aa 18955 19179 8690 8914   DD bb 18220 19179 6195 7154
  DD bb 18385 19179 6360 7154   DD bb 18463 19179 6438 7154
  DD bb 18941 19179 6916 7154   EE aa 16256 17033 5313 6090
  EE aa 16920 17033 5977 6090   EE bb 16265 17033 5803 6571
  EE bb 16404 17033 5942 6571   EE bb 16781 17033 6319 6571
  FF aa 14691 15361 6739 7409   FF aa 14694 15361 6742 7409
  FF aa 14743 15361 6791 7409   FF aa 15153 15361 7201 7409
  FF bb 14423 15361 7269 8207   FF bb 14491 15361 7337 8207
  FF bb 14635 15361 7481 8207   FF bb 14787 15361 7633 8207
  FF bb 15066 15361 7912 8207   FF bb 15259 15361 8105 8207
  GG aa 16073 16707 8280 8914   GG aa 16227 16707 8434 8914
  GG aa 16372 16707 8579 8914   GG aa 16559 16707 8766 8914
  GG bb 15769 16707 9198 10136   GG bb 15778 16707 9207 10136
  GG bb 15863 16707 9292 10136   GG bb 16547 16707 9976 10136
  HH aa 17139 18118 9243 10222   HH aa 17328 18118 9432 10222
  HH aa 17638 18118 9742 10222   HH bb 17155 18118 8948 9911
  HH bb 17388 18118 9181 9911   HH bb 17435 18118 9228 9911
  HH bb 17763 18118 9556 9911   HH bb 17788 18118 9581 9911
  HH bb 17985 18118 9778 9911   II aa 18567 19219 8712 9364
  II aa 18821 19219 8966 9364   II bb 18414 19219 8278 9083
  II bb 18548 19219 8412 9083   II bb 18776 19219 8640 9083
  II bb 18798 19219 8662 9083   II bb 18969 19219 8833 9083
  JJ aa 16452 17351 7949 8848   JJ aa 16583 17351 8080 8848
  JJ aa 17117 17351 8614 8848   JJ aa 17238 17351 8735 8848
  JJ bb 16512 17351 6601 7440   JJ bb 16997 17351 7086 7440
  JJ bb 17015 17351 7104 7440   JJ bb 17094 17351 7183 7440}

do_execsql_test 1.9.1 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN 2 PRECEDING         AND CURRENT ROW ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 4685   AA aa 4685   AA aa 4685   AA aa 4685   AA bb 4685   AA bb 4685
  AA bb 4685   AA bb 4685   BB aa 12025   BB aa 12025   BB aa 12025
  BB aa 12025   BB aa 12025   BB aa 12025   BB bb 12025   BB bb 12025
  BB bb 12025   BB bb 12025   BB bb 12025   BB bb 12025   CC aa 15147
  CC aa 15147   CC aa 15147   CC aa 15147   CC bb 15147   CC bb 15147
  DD aa 14494   DD aa 14494   DD aa 14494   DD bb 14494   DD bb 14494
  DD bb 14494   DD bb 14494   EE aa 9693   EE aa 9693   EE bb 9693
  EE bb 9693   EE bb 9693   FF aa 12239   FF aa 12239   FF aa 12239
  FF aa 12239   FF bb 12239   FF bb 12239   FF bb 12239   FF bb 12239
  FF bb 12239   FF bb 12239   GG aa 12675   GG aa 12675   GG aa 12675
  GG aa 12675   GG bb 12675   GG bb 12675   GG bb 12675   GG bb 12675
  HH aa 15579   HH aa 15579   HH aa 15579   HH bb 15579   HH bb 15579
  HH bb 15579   HH bb 15579   HH bb 15579   HH bb 15579   II aa 13551
  II aa 13551   II bb 13551   II bb 13551   II bb 13551   II bb 13551
  II bb 13551   JJ aa 12883   JJ aa 12883   JJ aa 12883   JJ aa 12883
  JJ bb 12883   JJ bb 12883   JJ bb 12883   JJ bb 12883}

do_execsql_test 1.9.2 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 2 PRECEDING         AND CURRENT ROW ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 2307   AA aa 2307   AA aa 2307   AA aa 2307   AA bb 4685   AA bb 4685
  AA bb 4685   AA bb 4685   BB aa 7558   BB aa 7558   BB aa 7558   BB aa 7558
  BB aa 7558   BB aa 7558   BB bb 9718   BB bb 9718   BB bb 9718   BB bb 9718
  BB bb 9718   BB bb 9718   CC aa 9294   CC aa 9294   CC aa 9294   CC aa 9294
  CC bb 7589   CC bb 7589   DD aa 4447   DD aa 4447   DD aa 4447   DD bb 5200
  DD bb 5200   DD bb 5200   DD bb 5200   EE aa 4922   EE aa 4922   EE bb 5246
  EE bb 5246   EE bb 5246   FF aa 4702   FF aa 4702   FF aa 4702   FF aa 4702
  FF bb 7317   FF bb 7317   FF bb 7317   FF bb 7317   FF bb 7317   FF bb 7317
  GG aa 7265   GG aa 7265   GG aa 7265   GG aa 7265   GG bb 7973   GG bb 7973
  GG bb 7973   GG bb 7973   HH aa 6717   HH aa 6717   HH aa 6717   HH bb 8314
  HH bb 8314   HH bb 8314   HH bb 8314   HH bb 8314   HH bb 8314   II aa 6493
  II aa 6493   II bb 6834   II bb 6834   II bb 6834   II bb 6834   II bb 6834
  JJ aa 5654   JJ aa 5654   JJ aa 5654   JJ aa 5654   JJ bb 6390   JJ bb 6390
  JJ bb 6390   JJ bb 6390}

do_execsql_test 1.9.3 {
  SELECT a, b, rank() OVER (ORDER BY a  GROUPS BETWEEN 2 PRECEDING         AND CURRENT ROW ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 1   AA aa 1   AA aa 1   AA aa 1   AA bb 1   AA bb 1   AA bb 1
  AA bb 1   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9
  BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   CC aa 21
  CC aa 21   CC aa 21   CC aa 21   CC bb 21   CC bb 21   DD aa 27   DD aa 27
  DD aa 27   DD bb 27   DD bb 27   DD bb 27   DD bb 27   EE aa 34   EE aa 34
  EE bb 34   EE bb 34   EE bb 34   FF aa 39   FF aa 39   FF aa 39   FF aa 39
  FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   GG aa 49
  GG aa 49   GG aa 49   GG aa 49   GG bb 49   GG bb 49   GG bb 49   GG bb 49
  HH aa 57   HH aa 57   HH aa 57   HH bb 57   HH bb 57   HH bb 57   HH bb 57
  HH bb 57   HH bb 57   II aa 66   II aa 66   II bb 66   II bb 66   II bb 66
  II bb 66   II bb 66   JJ aa 73   JJ aa 73   JJ aa 73   JJ aa 73   JJ bb 73
  JJ bb 73   JJ bb 73   JJ bb 73}

do_execsql_test 1.9.4 {
  SELECT a, b, max(c) OVER (ORDER BY a,b  GROUPS BETWEEN 2 PRECEDING         AND CURRENT ROW ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 934   AA aa 934   AA aa 934   AA aa 934   AA bb 934   AA bb 934
  AA bb 934   AA bb 934   BB aa 934   BB aa 934   BB aa 934   BB aa 934
  BB aa 934   BB aa 934   BB bb 870   BB bb 870   BB bb 870   BB bb 870
  BB bb 870   BB bb 870   CC aa 840   CC aa 840   CC aa 840   CC aa 840
  CC bb 840   CC bb 840   DD aa 845   DD aa 845   DD aa 845   DD bb 959
  DD bb 959   DD bb 959   DD bb 959   EE aa 959   EE aa 959   EE bb 959
  EE bb 959   EE bb 959   FF aa 777   FF aa 777   FF aa 777   FF aa 777
  FF bb 938   FF bb 938   FF bb 938   FF bb 938   FF bb 938   FF bb 938
  GG aa 938   GG aa 938   GG aa 938   GG aa 938   GG bb 938   GG bb 938
  GG bb 938   GG bb 938   HH aa 979   HH aa 979   HH aa 979   HH bb 979
  HH bb 979   HH bb 979   HH bb 979   HH bb 979   HH bb 979   II aa 979
  II aa 979   II bb 963   II bb 963   II bb 963   II bb 963   II bb 963
  JJ aa 899   JJ aa 899   JJ aa 899   JJ aa 899   JJ bb 899   JJ bb 899
  JJ bb 899   JJ bb 899}

do_execsql_test 1.9.5 {
  SELECT a, b, min(c) OVER (ORDER BY a,b  GROUPS BETWEEN 2 PRECEDING         AND CURRENT ROW ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 223   AA aa 223   AA aa 223   AA aa 223   AA bb 223   AA bb 223
  AA bb 223   AA bb 223   BB aa 223   BB aa 223   BB aa 223   BB aa 223
  BB aa 223   BB aa 223   BB bb 247   BB bb 247   BB bb 247   BB bb 247
  BB bb 247   BB bb 247   CC aa 158   CC aa 158   CC aa 158   CC aa 158
  CC bb 158   CC bb 158   DD aa 158   DD aa 158   DD aa 158   DD bb 224
  DD bb 224   DD bb 224   DD bb 224   EE aa 113   EE aa 113   EE bb 113
  EE bb 113   EE bb 113   FF aa 113   FF aa 113   FF aa 113   FF aa 113
  FF bb 102   FF bb 102   FF bb 102   FF bb 102   FF bb 102   FF bb 102
  GG aa 102   GG aa 102   GG aa 102   GG aa 102   GG bb 102   GG bb 102
  GG bb 102   GG bb 102   HH aa 148   HH aa 148   HH aa 148   HH bb 133
  HH bb 133   HH bb 133   HH bb 133   HH bb 133   HH bb 133   II aa 133
  II aa 133   II bb 133   II bb 133   II bb 133   II bb 133   II bb 133
  JJ aa 113   JJ aa 113   JJ aa 113   JJ aa 113   JJ bb 113   JJ bb 113
  JJ bb 113   JJ bb 113}

do_execsql_test 1.9.6 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN 2 PRECEDING         AND CURRENT ROW  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 3751   AA aa 3774   AA aa 4446   AA aa 4462   AA bb 3815   AA bb 4058
  AA bb 4113   AA bb 4376   BB aa 11263   BB aa 11365   BB aa 11613
  BB aa 11626   BB aa 11632   BB aa 11778   BB bb 11185   BB bb 11233
  BB bb 11239   BB bb 11314   BB bb 11320   BB bb 11392   CC aa 14388
  CC aa 14540   CC aa 14717   CC aa 14989   CC bb 14325   CC bb 14801
  DD aa 13649   DD aa 14238   DD aa 14270   DD bb 13535   DD bb 13700
  DD bb 13778   DD bb 14256   EE aa 8916   EE aa 9580   EE bb 8925
  EE bb 9064   EE bb 9441   FF aa 11569   FF aa 11572   FF aa 11621
  FF aa 12031   FF bb 11301   FF bb 11369   FF bb 11513   FF bb 11665
  FF bb 11944   FF bb 12137   GG aa 12041   GG aa 12195   GG aa 12340
  GG aa 12527   GG bb 11737   GG bb 11746   GG bb 11831   GG bb 12515
  HH aa 14600   HH aa 14789   HH aa 15099   HH bb 14616   HH bb 14849
  HH bb 14896   HH bb 15224   HH bb 15249   HH bb 15446   II aa 12899
  II aa 13153   II bb 12746   II bb 12880   II bb 13108   II bb 13130
  II bb 13301   JJ aa 11984   JJ aa 12115   JJ aa 12649   JJ aa 12770
  JJ bb 12044   JJ bb 12529   JJ bb 12547   JJ bb 12626}

do_execsql_test 1.9.7 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 2 PRECEDING         AND CURRENT ROW  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 1373   AA aa 1396   AA aa 2068   AA aa 2084   AA bb 3815   AA bb 4058
  AA bb 4113   AA bb 4376   BB aa 6796   BB aa 6898   BB aa 7146   BB aa 7159
  BB aa 7165   BB aa 7311   BB bb 8878   BB bb 8926   BB bb 8932   BB bb 9007
  BB bb 9013   BB bb 9085   CC aa 8535   CC aa 8687   CC aa 8864   CC aa 9136
  CC bb 6767   CC bb 7243   DD aa 3602   DD aa 4191   DD aa 4223   DD bb 4241
  DD bb 4406   DD bb 4484   DD bb 4962   EE aa 4145   EE aa 4809   EE bb 4478
  EE bb 4617   EE bb 4994   FF aa 4032   FF aa 4035   FF aa 4084   FF aa 4494
  FF bb 6379   FF bb 6447   FF bb 6591   FF bb 6743   FF bb 7022   FF bb 7215
  GG aa 6631   GG aa 6785   GG aa 6930   GG aa 7117   GG bb 7035   GG bb 7044
  GG bb 7129   GG bb 7813   HH aa 5738   HH aa 5927   HH aa 6237   HH bb 7351
  HH bb 7584   HH bb 7631   HH bb 7959   HH bb 7984   HH bb 8181   II aa 5841
  II aa 6095   II bb 6029   II bb 6163   II bb 6391   II bb 6413   II bb 6584
  JJ aa 4755   JJ aa 4886   JJ aa 5420   JJ aa 5541   JJ bb 5551   JJ bb 6036
  JJ bb 6054   JJ bb 6133}

do_execsql_test 1.9.8 {
  SELECT a, b, 
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN 2 PRECEDING         AND CURRENT ROW  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN 2 PRECEDING         AND CURRENT ROW ),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 2 PRECEDING         AND CURRENT ROW  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 2 PRECEDING         AND CURRENT ROW )
    FROM t3 ORDER BY 1, 2, 3;
} {AA aa 3751 4685 1373 2307   AA aa 3774 4685 1396 2307
  AA aa 4446 4685 2068 2307   AA aa 4462 4685 2084 2307
  AA bb 3815 4685 3815 4685   AA bb 4058 4685 4058 4685
  AA bb 4113 4685 4113 4685   AA bb 4376 4685 4376 4685
  BB aa 11263 12025 6796 7558   BB aa 11365 12025 6898 7558
  BB aa 11613 12025 7146 7558   BB aa 11626 12025 7159 7558
  BB aa 11632 12025 7165 7558   BB aa 11778 12025 7311 7558
  BB bb 11185 12025 8878 9718   BB bb 11233 12025 8926 9718
  BB bb 11239 12025 8932 9718   BB bb 11314 12025 9007 9718
  BB bb 11320 12025 9013 9718   BB bb 11392 12025 9085 9718
  CC aa 14388 15147 8535 9294   CC aa 14540 15147 8687 9294
  CC aa 14717 15147 8864 9294   CC aa 14989 15147 9136 9294
  CC bb 14325 15147 6767 7589   CC bb 14801 15147 7243 7589
  DD aa 13649 14494 3602 4447   DD aa 14238 14494 4191 4447
  DD aa 14270 14494 4223 4447   DD bb 13535 14494 4241 5200
  DD bb 13700 14494 4406 5200   DD bb 13778 14494 4484 5200
  DD bb 14256 14494 4962 5200   EE aa 8916 9693 4145 4922
  EE aa 9580 9693 4809 4922   EE bb 8925 9693 4478 5246
  EE bb 9064 9693 4617 5246   EE bb 9441 9693 4994 5246
  FF aa 11569 12239 4032 4702   FF aa 11572 12239 4035 4702
  FF aa 11621 12239 4084 4702   FF aa 12031 12239 4494 4702
  FF bb 11301 12239 6379 7317   FF bb 11369 12239 6447 7317
  FF bb 11513 12239 6591 7317   FF bb 11665 12239 6743 7317
  FF bb 11944 12239 7022 7317   FF bb 12137 12239 7215 7317
  GG aa 12041 12675 6631 7265   GG aa 12195 12675 6785 7265
  GG aa 12340 12675 6930 7265   GG aa 12527 12675 7117 7265
  GG bb 11737 12675 7035 7973   GG bb 11746 12675 7044 7973
  GG bb 11831 12675 7129 7973   GG bb 12515 12675 7813 7973
  HH aa 14600 15579 5738 6717   HH aa 14789 15579 5927 6717
  HH aa 15099 15579 6237 6717   HH bb 14616 15579 7351 8314
  HH bb 14849 15579 7584 8314   HH bb 14896 15579 7631 8314
  HH bb 15224 15579 7959 8314   HH bb 15249 15579 7984 8314
  HH bb 15446 15579 8181 8314   II aa 12899 13551 5841 6493
  II aa 13153 13551 6095 6493   II bb 12746 13551 6029 6834
  II bb 12880 13551 6163 6834   II bb 13108 13551 6391 6834
  II bb 13130 13551 6413 6834   II bb 13301 13551 6584 6834
  JJ aa 11984 12883 4755 5654   JJ aa 12115 12883 4886 5654
  JJ aa 12649 12883 5420 5654   JJ aa 12770 12883 5541 5654
  JJ bb 12044 12883 5551 6390   JJ bb 12529 12883 6036 6390
  JJ bb 12547 12883 6054 6390   JJ bb 12626 12883 6133 6390}

do_execsql_test 1.10.1 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN 3 PRECEDING         AND 0 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 4685   AA aa 4685   AA aa 4685   AA aa 4685   AA bb 4685   AA bb 4685
  AA bb 4685   AA bb 4685   BB aa 12025   BB aa 12025   BB aa 12025
  BB aa 12025   BB aa 12025   BB aa 12025   BB bb 12025   BB bb 12025
  BB bb 12025   BB bb 12025   BB bb 12025   BB bb 12025   CC aa 15147
  CC aa 15147   CC aa 15147   CC aa 15147   CC bb 15147   CC bb 15147
  DD aa 19179   DD aa 19179   DD aa 19179   DD bb 19179   DD bb 19179
  DD bb 19179   DD bb 19179   EE aa 17033   EE aa 17033   EE bb 17033
  EE bb 17033   EE bb 17033   FF aa 15361   FF aa 15361   FF aa 15361
  FF aa 15361   FF bb 15361   FF bb 15361   FF bb 15361   FF bb 15361
  FF bb 15361   FF bb 15361   GG aa 16707   GG aa 16707   GG aa 16707
  GG aa 16707   GG bb 16707   GG bb 16707   GG bb 16707   GG bb 16707
  HH aa 18118   HH aa 18118   HH aa 18118   HH bb 18118   HH bb 18118
  HH bb 18118   HH bb 18118   HH bb 18118   HH bb 18118   II aa 19219
  II aa 19219   II bb 19219   II bb 19219   II bb 19219   II bb 19219
  II bb 19219   JJ aa 17351   JJ aa 17351   JJ aa 17351   JJ aa 17351
  JJ bb 17351   JJ bb 17351   JJ bb 17351   JJ bb 17351}

do_execsql_test 1.10.2 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 3 PRECEDING         AND 0 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 2307   AA aa 2307   AA aa 2307   AA aa 2307   AA bb 4685   AA bb 4685
  AA bb 4685   AA bb 4685   BB aa 7558   BB aa 7558   BB aa 7558   BB aa 7558
  BB aa 7558   BB aa 7558   BB bb 12025   BB bb 12025   BB bb 12025
  BB bb 12025   BB bb 12025   BB bb 12025   CC aa 11672   CC aa 11672
  CC aa 11672   CC aa 11672   CC bb 10462   CC bb 10462   DD aa 8914
  DD aa 8914   DD aa 8914   DD bb 7154   DD bb 7154   DD bb 7154   DD bb 7154
  EE aa 6090   EE aa 6090   EE bb 6571   EE bb 6571   EE bb 6571   FF aa 7409
  FF aa 7409   FF aa 7409   FF aa 7409   FF bb 8207   FF bb 8207   FF bb 8207
  FF bb 8207   FF bb 8207   FF bb 8207   GG aa 8914   GG aa 8914   GG aa 8914
  GG aa 8914   GG bb 10136   GG bb 10136   GG bb 10136   GG bb 10136
  HH aa 10222   HH aa 10222   HH aa 10222   HH bb 9911   HH bb 9911
  HH bb 9911   HH bb 9911   HH bb 9911   HH bb 9911   II aa 9364   II aa 9364
  II bb 9083   II bb 9083   II bb 9083   II bb 9083   II bb 9083   JJ aa 8848
  JJ aa 8848   JJ aa 8848   JJ aa 8848   JJ bb 7440   JJ bb 7440   JJ bb 7440
  JJ bb 7440}

do_execsql_test 1.10.3 {
  SELECT a, b, rank() OVER (ORDER BY a  GROUPS BETWEEN 3 PRECEDING         AND 0 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 1   AA aa 1   AA aa 1   AA aa 1   AA bb 1   AA bb 1   AA bb 1
  AA bb 1   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9
  BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   CC aa 21
  CC aa 21   CC aa 21   CC aa 21   CC bb 21   CC bb 21   DD aa 27   DD aa 27
  DD aa 27   DD bb 27   DD bb 27   DD bb 27   DD bb 27   EE aa 34   EE aa 34
  EE bb 34   EE bb 34   EE bb 34   FF aa 39   FF aa 39   FF aa 39   FF aa 39
  FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   GG aa 49
  GG aa 49   GG aa 49   GG aa 49   GG bb 49   GG bb 49   GG bb 49   GG bb 49
  HH aa 57   HH aa 57   HH aa 57   HH bb 57   HH bb 57   HH bb 57   HH bb 57
  HH bb 57   HH bb 57   II aa 66   II aa 66   II bb 66   II bb 66   II bb 66
  II bb 66   II bb 66   JJ aa 73   JJ aa 73   JJ aa 73   JJ aa 73   JJ bb 73
  JJ bb 73   JJ bb 73   JJ bb 73}

do_execsql_test 1.10.4 {
  SELECT a, b, max(c) OVER (ORDER BY a,b  GROUPS BETWEEN 3 PRECEDING         AND 0 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 934   AA aa 934   AA aa 934   AA aa 934   AA bb 934   AA bb 934
  AA bb 934   AA bb 934   BB aa 934   BB aa 934   BB aa 934   BB aa 934
  BB aa 934   BB aa 934   BB bb 934   BB bb 934   BB bb 934   BB bb 934
  BB bb 934   BB bb 934   CC aa 870   CC aa 870   CC aa 870   CC aa 870
  CC bb 840   CC bb 840   DD aa 845   DD aa 845   DD aa 845   DD bb 959
  DD bb 959   DD bb 959   DD bb 959   EE aa 959   EE aa 959   EE bb 959
  EE bb 959   EE bb 959   FF aa 959   FF aa 959   FF aa 959   FF aa 959
  FF bb 938   FF bb 938   FF bb 938   FF bb 938   FF bb 938   FF bb 938
  GG aa 938   GG aa 938   GG aa 938   GG aa 938   GG bb 938   GG bb 938
  GG bb 938   GG bb 938   HH aa 979   HH aa 979   HH aa 979   HH bb 979
  HH bb 979   HH bb 979   HH bb 979   HH bb 979   HH bb 979   II aa 979
  II aa 979   II bb 979   II bb 979   II bb 979   II bb 979   II bb 979
  JJ aa 963   JJ aa 963   JJ aa 963   JJ aa 963   JJ bb 899   JJ bb 899
  JJ bb 899   JJ bb 899}

do_execsql_test 1.10.5 {
  SELECT a, b, min(c) OVER (ORDER BY a,b  GROUPS BETWEEN 3 PRECEDING         AND 0 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 223   AA aa 223   AA aa 223   AA aa 223   AA bb 223   AA bb 223
  AA bb 223   AA bb 223   BB aa 223   BB aa 223   BB aa 223   BB aa 223
  BB aa 223   BB aa 223   BB bb 223   BB bb 223   BB bb 223   BB bb 223
  BB bb 223   BB bb 223   CC aa 158   CC aa 158   CC aa 158   CC aa 158
  CC bb 158   CC bb 158   DD aa 158   DD aa 158   DD aa 158   DD bb 158
  DD bb 158   DD bb 158   DD bb 158   EE aa 113   EE aa 113   EE bb 113
  EE bb 113   EE bb 113   FF aa 113   FF aa 113   FF aa 113   FF aa 113
  FF bb 102   FF bb 102   FF bb 102   FF bb 102   FF bb 102   FF bb 102
  GG aa 102   GG aa 102   GG aa 102   GG aa 102   GG bb 102   GG bb 102
  GG bb 102   GG bb 102   HH aa 102   HH aa 102   HH aa 102   HH bb 133
  HH bb 133   HH bb 133   HH bb 133   HH bb 133   HH bb 133   II aa 133
  II aa 133   II bb 133   II bb 133   II bb 133   II bb 133   II bb 133
  JJ aa 113   JJ aa 113   JJ aa 113   JJ aa 113   JJ bb 113   JJ bb 113
  JJ bb 113   JJ bb 113}

do_execsql_test 1.10.6 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN 3 PRECEDING         AND 0 FOLLOWING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 3751   AA aa 3774   AA aa 4446   AA aa 4462   AA bb 3815   AA bb 4058
  AA bb 4113   AA bb 4376   BB aa 11263   BB aa 11365   BB aa 11613
  BB aa 11626   BB aa 11632   BB aa 11778   BB bb 11185   BB bb 11233
  BB bb 11239   BB bb 11314   BB bb 11320   BB bb 11392   CC aa 14388
  CC aa 14540   CC aa 14717   CC aa 14989   CC bb 14325   CC bb 14801
  DD aa 18334   DD aa 18923   DD aa 18955   DD bb 18220   DD bb 18385
  DD bb 18463   DD bb 18941   EE aa 16256   EE aa 16920   EE bb 16265
  EE bb 16404   EE bb 16781   FF aa 14691   FF aa 14694   FF aa 14743
  FF aa 15153   FF bb 14423   FF bb 14491   FF bb 14635   FF bb 14787
  FF bb 15066   FF bb 15259   GG aa 16073   GG aa 16227   GG aa 16372
  GG aa 16559   GG bb 15769   GG bb 15778   GG bb 15863   GG bb 16547
  HH aa 17139   HH aa 17328   HH aa 17638   HH bb 17155   HH bb 17388
  HH bb 17435   HH bb 17763   HH bb 17788   HH bb 17985   II aa 18567
  II aa 18821   II bb 18414   II bb 18548   II bb 18776   II bb 18798
  II bb 18969   JJ aa 16452   JJ aa 16583   JJ aa 17117   JJ aa 17238
  JJ bb 16512   JJ bb 16997   JJ bb 17015   JJ bb 17094}

do_execsql_test 1.10.7 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 3 PRECEDING         AND 0 FOLLOWING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 1373   AA aa 1396   AA aa 2068   AA aa 2084   AA bb 3815   AA bb 4058
  AA bb 4113   AA bb 4376   BB aa 6796   BB aa 6898   BB aa 7146   BB aa 7159
  BB aa 7165   BB aa 7311   BB bb 11185   BB bb 11233   BB bb 11239
  BB bb 11314   BB bb 11320   BB bb 11392   CC aa 10913   CC aa 11065
  CC aa 11242   CC aa 11514   CC bb 9640   CC bb 10116   DD aa 8069
  DD aa 8658   DD aa 8690   DD bb 6195   DD bb 6360   DD bb 6438   DD bb 6916
  EE aa 5313   EE aa 5977   EE bb 5803   EE bb 5942   EE bb 6319   FF aa 6739
  FF aa 6742   FF aa 6791   FF aa 7201   FF bb 7269   FF bb 7337   FF bb 7481
  FF bb 7633   FF bb 7912   FF bb 8105   GG aa 8280   GG aa 8434   GG aa 8579
  GG aa 8766   GG bb 9198   GG bb 9207   GG bb 9292   GG bb 9976   HH aa 9243
  HH aa 9432   HH aa 9742   HH bb 8948   HH bb 9181   HH bb 9228   HH bb 9556
  HH bb 9581   HH bb 9778   II aa 8712   II aa 8966   II bb 8278   II bb 8412
  II bb 8640   II bb 8662   II bb 8833   JJ aa 7949   JJ aa 8080   JJ aa 8614
  JJ aa 8735   JJ bb 6601   JJ bb 7086   JJ bb 7104   JJ bb 7183}

do_execsql_test 1.10.8 {
  SELECT a, b, 
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN 3 PRECEDING         AND 0 FOLLOWING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN 3 PRECEDING         AND 0 FOLLOWING ),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 3 PRECEDING         AND 0 FOLLOWING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 3 PRECEDING         AND 0 FOLLOWING )
    FROM t3 ORDER BY 1, 2, 3;
} {AA aa 3751 4685 1373 2307   AA aa 3774 4685 1396 2307
  AA aa 4446 4685 2068 2307   AA aa 4462 4685 2084 2307
  AA bb 3815 4685 3815 4685   AA bb 4058 4685 4058 4685
  AA bb 4113 4685 4113 4685   AA bb 4376 4685 4376 4685
  BB aa 11263 12025 6796 7558   BB aa 11365 12025 6898 7558
  BB aa 11613 12025 7146 7558   BB aa 11626 12025 7159 7558
  BB aa 11632 12025 7165 7558   BB aa 11778 12025 7311 7558
  BB bb 11185 12025 11185 12025   BB bb 11233 12025 11233 12025
  BB bb 11239 12025 11239 12025   BB bb 11314 12025 11314 12025
  BB bb 11320 12025 11320 12025   BB bb 11392 12025 11392 12025
  CC aa 14388 15147 10913 11672   CC aa 14540 15147 11065 11672
  CC aa 14717 15147 11242 11672   CC aa 14989 15147 11514 11672
  CC bb 14325 15147 9640 10462   CC bb 14801 15147 10116 10462
  DD aa 18334 19179 8069 8914   DD aa 18923 19179 8658 8914
  DD aa 18955 19179 8690 8914   DD bb 18220 19179 6195 7154
  DD bb 18385 19179 6360 7154   DD bb 18463 19179 6438 7154
  DD bb 18941 19179 6916 7154   EE aa 16256 17033 5313 6090
  EE aa 16920 17033 5977 6090   EE bb 16265 17033 5803 6571
  EE bb 16404 17033 5942 6571   EE bb 16781 17033 6319 6571
  FF aa 14691 15361 6739 7409   FF aa 14694 15361 6742 7409
  FF aa 14743 15361 6791 7409   FF aa 15153 15361 7201 7409
  FF bb 14423 15361 7269 8207   FF bb 14491 15361 7337 8207
  FF bb 14635 15361 7481 8207   FF bb 14787 15361 7633 8207
  FF bb 15066 15361 7912 8207   FF bb 15259 15361 8105 8207
  GG aa 16073 16707 8280 8914   GG aa 16227 16707 8434 8914
  GG aa 16372 16707 8579 8914   GG aa 16559 16707 8766 8914
  GG bb 15769 16707 9198 10136   GG bb 15778 16707 9207 10136
  GG bb 15863 16707 9292 10136   GG bb 16547 16707 9976 10136
  HH aa 17139 18118 9243 10222   HH aa 17328 18118 9432 10222
  HH aa 17638 18118 9742 10222   HH bb 17155 18118 8948 9911
  HH bb 17388 18118 9181 9911   HH bb 17435 18118 9228 9911
  HH bb 17763 18118 9556 9911   HH bb 17788 18118 9581 9911
  HH bb 17985 18118 9778 9911   II aa 18567 19219 8712 9364
  II aa 18821 19219 8966 9364   II bb 18414 19219 8278 9083
  II bb 18548 19219 8412 9083   II bb 18776 19219 8640 9083
  II bb 18798 19219 8662 9083   II bb 18969 19219 8833 9083
  JJ aa 16452 17351 7949 8848   JJ aa 16583 17351 8080 8848
  JJ aa 17117 17351 8614 8848   JJ aa 17238 17351 8735 8848
  JJ bb 16512 17351 6601 7440   JJ bb 16997 17351 7086 7440
  JJ bb 17015 17351 7104 7440   JJ bb 17094 17351 7183 7440}

do_execsql_test 1.11.1 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN 2 PRECEDING         AND UNBOUNDED FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 44737   AA aa 44737   AA aa 44737   AA aa 44737   AA bb 44737
  AA bb 44737   AA bb 44737   AA bb 44737   BB aa 44737   BB aa 44737
  BB aa 44737   BB aa 44737   BB aa 44737   BB aa 44737   BB bb 44737
  BB bb 44737   BB bb 44737   BB bb 44737   BB bb 44737   BB bb 44737
  CC aa 44737   CC aa 44737   CC aa 44737   CC aa 44737   CC bb 44737
  CC bb 44737   DD aa 40052   DD aa 40052   DD aa 40052   DD bb 40052
  DD bb 40052   DD bb 40052   DD bb 40052   EE aa 32712   EE aa 32712
  EE bb 32712   EE bb 32712   EE bb 32712   FF aa 29590   FF aa 29590
  FF aa 29590   FF aa 29590   FF bb 29590   FF bb 29590   FF bb 29590
  FF bb 29590   FF bb 29590   FF bb 29590   GG aa 25558   GG aa 25558
  GG aa 25558   GG aa 25558   GG bb 25558   GG bb 25558   GG bb 25558
  GG bb 25558   HH aa 23019   HH aa 23019   HH aa 23019   HH bb 23019
  HH bb 23019   HH bb 23019   HH bb 23019   HH bb 23019   HH bb 23019
  II aa 17351   II aa 17351   II bb 17351   II bb 17351   II bb 17351
  II bb 17351   II bb 17351   JJ aa 12883   JJ aa 12883   JJ aa 12883
  JJ aa 12883   JJ bb 12883   JJ bb 12883   JJ bb 12883   JJ bb 12883}

do_execsql_test 1.11.2 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 2 PRECEDING         AND UNBOUNDED FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 44737   AA aa 44737   AA aa 44737   AA aa 44737   AA bb 44737
  AA bb 44737   AA bb 44737   AA bb 44737   BB aa 44737   BB aa 44737
  BB aa 44737   BB aa 44737   BB aa 44737   BB aa 44737   BB bb 42430
  BB bb 42430   BB bb 42430   BB bb 42430   BB bb 42430   BB bb 42430
  CC aa 40052   CC aa 40052   CC aa 40052   CC aa 40052   CC bb 37179
  CC bb 37179   DD aa 32712   DD aa 32712   DD aa 32712   DD bb 30758
  DD bb 30758   DD bb 30758   DD bb 30758   EE aa 29590   EE aa 29590
  EE bb 28265   EE bb 28265   EE bb 28265   FF aa 25558   FF aa 25558
  FF aa 25558   FF aa 25558   FF bb 24668   FF bb 24668   FF bb 24668
  FF bb 24668   FF bb 24668   FF bb 24668   GG aa 23019   GG aa 23019
  GG aa 23019   GG aa 23019   GG bb 20856   GG bb 20856   GG bb 20856
  GG bb 20856   HH aa 17351   HH aa 17351   HH aa 17351   HH bb 15754
  HH bb 15754   HH bb 15754   HH bb 15754   HH bb 15754   HH bb 15754
  II aa 12883   II aa 12883   II bb 10634   II bb 10634   II bb 10634
  II bb 10634   II bb 10634   JJ aa 7440   JJ aa 7440   JJ aa 7440
  JJ aa 7440   JJ bb 6390   JJ bb 6390   JJ bb 6390   JJ bb 6390}

do_execsql_test 1.11.3 {
  SELECT a, b, rank() OVER (ORDER BY a  GROUPS BETWEEN 2 PRECEDING         AND UNBOUNDED FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 1   AA aa 1   AA aa 1   AA aa 1   AA bb 1   AA bb 1   AA bb 1
  AA bb 1   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9
  BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   CC aa 21
  CC aa 21   CC aa 21   CC aa 21   CC bb 21   CC bb 21   DD aa 27   DD aa 27
  DD aa 27   DD bb 27   DD bb 27   DD bb 27   DD bb 27   EE aa 34   EE aa 34
  EE bb 34   EE bb 34   EE bb 34   FF aa 39   FF aa 39   FF aa 39   FF aa 39
  FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   GG aa 49
  GG aa 49   GG aa 49   GG aa 49   GG bb 49   GG bb 49   GG bb 49   GG bb 49
  HH aa 57   HH aa 57   HH aa 57   HH bb 57   HH bb 57   HH bb 57   HH bb 57
  HH bb 57   HH bb 57   II aa 66   II aa 66   II bb 66   II bb 66   II bb 66
  II bb 66   II bb 66   JJ aa 73   JJ aa 73   JJ aa 73   JJ aa 73   JJ bb 73
  JJ bb 73   JJ bb 73   JJ bb 73}

do_execsql_test 1.11.4 {
  SELECT a, b, max(c) OVER (ORDER BY a,b  GROUPS BETWEEN 2 PRECEDING         AND UNBOUNDED FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 979   AA aa 979   AA aa 979   AA aa 979   AA bb 979   AA bb 979
  AA bb 979   AA bb 979   BB aa 979   BB aa 979   BB aa 979   BB aa 979
  BB aa 979   BB aa 979   BB bb 979   BB bb 979   BB bb 979   BB bb 979
  BB bb 979   BB bb 979   CC aa 979   CC aa 979   CC aa 979   CC aa 979
  CC bb 979   CC bb 979   DD aa 979   DD aa 979   DD aa 979   DD bb 979
  DD bb 979   DD bb 979   DD bb 979   EE aa 979   EE aa 979   EE bb 979
  EE bb 979   EE bb 979   FF aa 979   FF aa 979   FF aa 979   FF aa 979
  FF bb 979   FF bb 979   FF bb 979   FF bb 979   FF bb 979   FF bb 979
  GG aa 979   GG aa 979   GG aa 979   GG aa 979   GG bb 979   GG bb 979
  GG bb 979   GG bb 979   HH aa 979   HH aa 979   HH aa 979   HH bb 979
  HH bb 979   HH bb 979   HH bb 979   HH bb 979   HH bb 979   II aa 979
  II aa 979   II bb 963   II bb 963   II bb 963   II bb 963   II bb 963
  JJ aa 899   JJ aa 899   JJ aa 899   JJ aa 899   JJ bb 899   JJ bb 899
  JJ bb 899   JJ bb 899}

do_execsql_test 1.11.5 {
  SELECT a, b, min(c) OVER (ORDER BY a,b  GROUPS BETWEEN 2 PRECEDING         AND UNBOUNDED FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 102   AA aa 102   AA aa 102   AA aa 102   AA bb 102   AA bb 102
  AA bb 102   AA bb 102   BB aa 102   BB aa 102   BB aa 102   BB aa 102
  BB aa 102   BB aa 102   BB bb 102   BB bb 102   BB bb 102   BB bb 102
  BB bb 102   BB bb 102   CC aa 102   CC aa 102   CC aa 102   CC aa 102
  CC bb 102   CC bb 102   DD aa 102   DD aa 102   DD aa 102   DD bb 102
  DD bb 102   DD bb 102   DD bb 102   EE aa 102   EE aa 102   EE bb 102
  EE bb 102   EE bb 102   FF aa 102   FF aa 102   FF aa 102   FF aa 102
  FF bb 102   FF bb 102   FF bb 102   FF bb 102   FF bb 102   FF bb 102
  GG aa 102   GG aa 102   GG aa 102   GG aa 102   GG bb 102   GG bb 102
  GG bb 102   GG bb 102   HH aa 113   HH aa 113   HH aa 113   HH bb 113
  HH bb 113   HH bb 113   HH bb 113   HH bb 113   HH bb 113   II aa 113
  II aa 113   II bb 113   II bb 113   II bb 113   II bb 113   II bb 113
  JJ aa 113   JJ aa 113   JJ aa 113   JJ aa 113   JJ bb 113   JJ bb 113
  JJ bb 113   JJ bb 113}

do_execsql_test 1.11.6 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN 2 PRECEDING         AND UNBOUNDED FOLLOWING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 43803   AA aa 43826   AA aa 44498   AA aa 44514   AA bb 43867
  AA bb 44110   AA bb 44165   AA bb 44428   BB aa 43975   BB aa 44077
  BB aa 44325   BB aa 44338   BB aa 44344   BB aa 44490   BB bb 43897
  BB bb 43945   BB bb 43951   BB bb 44026   BB bb 44032   BB bb 44104
  CC aa 43978   CC aa 44130   CC aa 44307   CC aa 44579   CC bb 43915
  CC bb 44391   DD aa 39207   DD aa 39796   DD aa 39828   DD bb 39093
  DD bb 39258   DD bb 39336   DD bb 39814   EE aa 31935   EE aa 32599
  EE bb 31944   EE bb 32083   EE bb 32460   FF aa 28920   FF aa 28923
  FF aa 28972   FF aa 29382   FF bb 28652   FF bb 28720   FF bb 28864
  FF bb 29016   FF bb 29295   FF bb 29488   GG aa 24924   GG aa 25078
  GG aa 25223   GG aa 25410   GG bb 24620   GG bb 24629   GG bb 24714
  GG bb 25398   HH aa 22040   HH aa 22229   HH aa 22539   HH bb 22056
  HH bb 22289   HH bb 22336   HH bb 22664   HH bb 22689   HH bb 22886
  II aa 16699   II aa 16953   II bb 16546   II bb 16680   II bb 16908
  II bb 16930   II bb 17101   JJ aa 11984   JJ aa 12115   JJ aa 12649
  JJ aa 12770   JJ bb 12044   JJ bb 12529   JJ bb 12547   JJ bb 12626}

do_execsql_test 1.11.7 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 2 PRECEDING         AND UNBOUNDED FOLLOWING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 43803   AA aa 43826   AA aa 44498   AA aa 44514   AA bb 43867
  AA bb 44110   AA bb 44165   AA bb 44428   BB aa 43975   BB aa 44077
  BB aa 44325   BB aa 44338   BB aa 44344   BB aa 44490   BB bb 41590
  BB bb 41638   BB bb 41644   BB bb 41719   BB bb 41725   BB bb 41797
  CC aa 39293   CC aa 39445   CC aa 39622   CC aa 39894   CC bb 36357
  CC bb 36833   DD aa 31867   DD aa 32456   DD aa 32488   DD bb 29799
  DD bb 29964   DD bb 30042   DD bb 30520   EE aa 28813   EE aa 29477
  EE bb 27497   EE bb 27636   EE bb 28013   FF aa 24888   FF aa 24891
  FF aa 24940   FF aa 25350   FF bb 23730   FF bb 23798   FF bb 23942
  FF bb 24094   FF bb 24373   FF bb 24566   GG aa 22385   GG aa 22539
  GG aa 22684   GG aa 22871   GG bb 19918   GG bb 19927   GG bb 20012
  GG bb 20696   HH aa 16372   HH aa 16561   HH aa 16871   HH bb 14791
  HH bb 15024   HH bb 15071   HH bb 15399   HH bb 15424   HH bb 15621
  II aa 12231   II aa 12485   II bb 9829   II bb 9963   II bb 10191
  II bb 10213   II bb 10384   JJ aa 6541   JJ aa 6672   JJ aa 7206
  JJ aa 7327   JJ bb 5551   JJ bb 6036   JJ bb 6054   JJ bb 6133}

do_execsql_test 1.11.8 {
  SELECT a, b, 
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN 2 PRECEDING         AND UNBOUNDED FOLLOWING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN 2 PRECEDING         AND UNBOUNDED FOLLOWING ),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 2 PRECEDING         AND UNBOUNDED FOLLOWING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 2 PRECEDING         AND UNBOUNDED FOLLOWING )
    FROM t3 ORDER BY 1, 2, 3;
} {AA aa 43803 44737 43803 44737   AA aa 43826 44737 43826 44737
  AA aa 44498 44737 44498 44737   AA aa 44514 44737 44514 44737
  AA bb 43867 44737 43867 44737   AA bb 44110 44737 44110 44737
  AA bb 44165 44737 44165 44737   AA bb 44428 44737 44428 44737
  BB aa 43975 44737 43975 44737   BB aa 44077 44737 44077 44737
  BB aa 44325 44737 44325 44737   BB aa 44338 44737 44338 44737
  BB aa 44344 44737 44344 44737   BB aa 44490 44737 44490 44737
  BB bb 43897 44737 41590 42430   BB bb 43945 44737 41638 42430
  BB bb 43951 44737 41644 42430   BB bb 44026 44737 41719 42430
  BB bb 44032 44737 41725 42430   BB bb 44104 44737 41797 42430
  CC aa 43978 44737 39293 40052   CC aa 44130 44737 39445 40052
  CC aa 44307 44737 39622 40052   CC aa 44579 44737 39894 40052
  CC bb 43915 44737 36357 37179   CC bb 44391 44737 36833 37179
  DD aa 39207 40052 31867 32712   DD aa 39796 40052 32456 32712
  DD aa 39828 40052 32488 32712   DD bb 39093 40052 29799 30758
  DD bb 39258 40052 29964 30758   DD bb 39336 40052 30042 30758
  DD bb 39814 40052 30520 30758   EE aa 31935 32712 28813 29590
  EE aa 32599 32712 29477 29590   EE bb 31944 32712 27497 28265
  EE bb 32083 32712 27636 28265   EE bb 32460 32712 28013 28265
  FF aa 28920 29590 24888 25558   FF aa 28923 29590 24891 25558
  FF aa 28972 29590 24940 25558   FF aa 29382 29590 25350 25558
  FF bb 28652 29590 23730 24668   FF bb 28720 29590 23798 24668
  FF bb 28864 29590 23942 24668   FF bb 29016 29590 24094 24668
  FF bb 29295 29590 24373 24668   FF bb 29488 29590 24566 24668
  GG aa 24924 25558 22385 23019   GG aa 25078 25558 22539 23019
  GG aa 25223 25558 22684 23019   GG aa 25410 25558 22871 23019
  GG bb 24620 25558 19918 20856   GG bb 24629 25558 19927 20856
  GG bb 24714 25558 20012 20856   GG bb 25398 25558 20696 20856
  HH aa 22040 23019 16372 17351   HH aa 22229 23019 16561 17351
  HH aa 22539 23019 16871 17351   HH bb 22056 23019 14791 15754
  HH bb 22289 23019 15024 15754   HH bb 22336 23019 15071 15754
  HH bb 22664 23019 15399 15754   HH bb 22689 23019 15424 15754
  HH bb 22886 23019 15621 15754   II aa 16699 17351 12231 12883
  II aa 16953 17351 12485 12883   II bb 16546 17351 9829 10634
  II bb 16680 17351 9963 10634   II bb 16908 17351 10191 10634
  II bb 16930 17351 10213 10634   II bb 17101 17351 10384 10634
  JJ aa 11984 12883 6541 7440   JJ aa 12115 12883 6672 7440
  JJ aa 12649 12883 7206 7440   JJ aa 12770 12883 7327 7440
  JJ bb 12044 12883 5551 6390   JJ bb 12529 12883 6036 6390
  JJ bb 12547 12883 6054 6390   JJ bb 12626 12883 6133 6390}

do_execsql_test 1.12.1 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN CURRENT ROW         AND 0 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 4685   AA aa 4685   AA aa 4685   AA aa 4685   AA bb 4685   AA bb 4685
  AA bb 4685   AA bb 4685   BB aa 7340   BB aa 7340   BB aa 7340   BB aa 7340
  BB aa 7340   BB aa 7340   BB bb 7340   BB bb 7340   BB bb 7340   BB bb 7340
  BB bb 7340   BB bb 7340   CC aa 3122   CC aa 3122   CC aa 3122   CC aa 3122
  CC bb 3122   CC bb 3122   DD aa 4032   DD aa 4032   DD aa 4032   DD bb 4032
  DD bb 4032   DD bb 4032   DD bb 4032   EE aa 2539   EE aa 2539   EE bb 2539
  EE bb 2539   EE bb 2539   FF aa 5668   FF aa 5668   FF aa 5668   FF aa 5668
  FF bb 5668   FF bb 5668   FF bb 5668   FF bb 5668   FF bb 5668   FF bb 5668
  GG aa 4468   GG aa 4468   GG aa 4468   GG aa 4468   GG bb 4468   GG bb 4468
  GG bb 4468   GG bb 4468   HH aa 5443   HH aa 5443   HH aa 5443   HH bb 5443
  HH bb 5443   HH bb 5443   HH bb 5443   HH bb 5443   HH bb 5443   II aa 3640
  II aa 3640   II bb 3640   II bb 3640   II bb 3640   II bb 3640   II bb 3640
  JJ aa 3800   JJ aa 3800   JJ aa 3800   JJ aa 3800   JJ bb 3800   JJ bb 3800
  JJ bb 3800   JJ bb 3800}

do_execsql_test 1.12.2 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN CURRENT ROW         AND 0 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 2307   AA aa 2307   AA aa 2307   AA aa 2307   AA bb 2378   AA bb 2378
  AA bb 2378   AA bb 2378   BB aa 2873   BB aa 2873   BB aa 2873   BB aa 2873
  BB aa 2873   BB aa 2873   BB bb 4467   BB bb 4467   BB bb 4467   BB bb 4467
  BB bb 4467   BB bb 4467   CC aa 1954   CC aa 1954   CC aa 1954   CC aa 1954
  CC bb 1168   CC bb 1168   DD aa 1325   DD aa 1325   DD aa 1325   DD bb 2707
  DD bb 2707   DD bb 2707   DD bb 2707   EE aa 890   EE aa 890   EE bb 1649
  EE bb 1649   EE bb 1649   FF aa 2163   FF aa 2163   FF aa 2163   FF aa 2163
  FF bb 3505   FF bb 3505   FF bb 3505   FF bb 3505   FF bb 3505   FF bb 3505
  GG aa 1597   GG aa 1597   GG aa 1597   GG aa 1597   GG bb 2871   GG bb 2871
  GG bb 2871   GG bb 2871   HH aa 2249   HH aa 2249   HH aa 2249   HH bb 3194
  HH bb 3194   HH bb 3194   HH bb 3194   HH bb 3194   HH bb 3194   II aa 1050
  II aa 1050   II bb 2590   II bb 2590   II bb 2590   II bb 2590   II bb 2590
  JJ aa 2014   JJ aa 2014   JJ aa 2014   JJ aa 2014   JJ bb 1786   JJ bb 1786
  JJ bb 1786   JJ bb 1786}

do_execsql_test 1.12.3 {
  SELECT a, b, rank() OVER (ORDER BY a  GROUPS BETWEEN CURRENT ROW         AND 0 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 1   AA aa 1   AA aa 1   AA aa 1   AA bb 1   AA bb 1   AA bb 1
  AA bb 1   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9
  BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   CC aa 21
  CC aa 21   CC aa 21   CC aa 21   CC bb 21   CC bb 21   DD aa 27   DD aa 27
  DD aa 27   DD bb 27   DD bb 27   DD bb 27   DD bb 27   EE aa 34   EE aa 34
  EE bb 34   EE bb 34   EE bb 34   FF aa 39   FF aa 39   FF aa 39   FF aa 39
  FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   GG aa 49
  GG aa 49   GG aa 49   GG aa 49   GG bb 49   GG bb 49   GG bb 49   GG bb 49
  HH aa 57   HH aa 57   HH aa 57   HH bb 57   HH bb 57   HH bb 57   HH bb 57
  HH bb 57   HH bb 57   II aa 66   II aa 66   II bb 66   II bb 66   II bb 66
  II bb 66   II bb 66   JJ aa 73   JJ aa 73   JJ aa 73   JJ aa 73   JJ bb 73
  JJ bb 73   JJ bb 73   JJ bb 73}

do_execsql_test 1.12.4 {
  SELECT a, b, max(c) OVER (ORDER BY a,b  GROUPS BETWEEN CURRENT ROW         AND 0 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 934   AA aa 934   AA aa 934   AA aa 934   AA bb 870   AA bb 870
  AA bb 870   AA bb 870   BB aa 762   BB aa 762   BB aa 762   BB aa 762
  BB aa 762   BB aa 762   BB bb 840   BB bb 840   BB bb 840   BB bb 840
  BB bb 840   BB bb 840   CC aa 759   CC aa 759   CC aa 759   CC aa 759
  CC bb 822   CC bb 822   DD aa 845   DD aa 845   DD aa 845   DD bb 959
  DD bb 959   DD bb 959   DD bb 959   EE aa 777   EE aa 777   EE bb 768
  EE bb 768   EE bb 768   FF aa 670   FF aa 670   FF aa 670   FF aa 670
  FF bb 938   FF bb 938   FF bb 938   FF bb 938   FF bb 938   FF bb 938
  GG aa 634   GG aa 634   GG aa 634   GG aa 634   GG bb 938   GG bb 938
  GG bb 938   GG bb 938   HH aa 979   HH aa 979   HH aa 979   HH bb 963
  HH bb 963   HH bb 963   HH bb 963   HH bb 963   HH bb 963   II aa 652
  II aa 652   II bb 805   II bb 805   II bb 805   II bb 805   II bb 805
  JJ aa 899   JJ aa 899   JJ aa 899   JJ aa 899   JJ bb 839   JJ bb 839
  JJ bb 839   JJ bb 839}

do_execsql_test 1.12.5 {
  SELECT a, b, min(c) OVER (ORDER BY a,b  GROUPS BETWEEN CURRENT ROW         AND 0 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 223   AA aa 223   AA aa 223   AA aa 223   AA bb 309   AA bb 309
  AA bb 309   AA bb 309   BB aa 247   BB aa 247   BB aa 247   BB aa 247
  BB aa 247   BB aa 247   BB bb 633   BB bb 633   BB bb 633   BB bb 633
  BB bb 633   BB bb 633   CC aa 158   CC aa 158   CC aa 158   CC aa 158
  CC bb 346   CC bb 346   DD aa 224   DD aa 224   DD aa 224   DD bb 238
  DD bb 238   DD bb 238   DD bb 238   EE aa 113   EE aa 113   EE bb 252
  EE bb 252   EE bb 252   FF aa 208   FF aa 208   FF aa 208   FF aa 208
  FF bb 102   FF bb 102   FF bb 102   FF bb 102   FF bb 102   FF bb 102
  GG aa 148   GG aa 148   GG aa 148   GG aa 148   GG bb 160   GG bb 160
  GG bb 160   GG bb 160   HH aa 480   HH aa 480   HH aa 480   HH bb 133
  HH bb 133   HH bb 133   HH bb 133   HH bb 133   HH bb 133   II aa 398
  II aa 398   II bb 250   II bb 250   II bb 250   II bb 250   II bb 250
  JJ aa 113   JJ aa 113   JJ aa 113   JJ aa 113   JJ bb 257   JJ bb 257
  JJ bb 257   JJ bb 257}

do_execsql_test 1.12.6 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN CURRENT ROW         AND 0 FOLLOWING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 3751   AA aa 3774   AA aa 4446   AA aa 4462   AA bb 3815   AA bb 4058
  AA bb 4113   AA bb 4376   BB aa 6578   BB aa 6680   BB aa 6928   BB aa 6941
  BB aa 6947   BB aa 7093   BB bb 6500   BB bb 6548   BB bb 6554   BB bb 6629
  BB bb 6635   BB bb 6707   CC aa 2363   CC aa 2515   CC aa 2692   CC aa 2964
  CC bb 2300   CC bb 2776   DD aa 3187   DD aa 3776   DD aa 3808   DD bb 3073
  DD bb 3238   DD bb 3316   DD bb 3794   EE aa 1762   EE aa 2426   EE bb 1771
  EE bb 1910   EE bb 2287   FF aa 4998   FF aa 5001   FF aa 5050   FF aa 5460
  FF bb 4730   FF bb 4798   FF bb 4942   FF bb 5094   FF bb 5373   FF bb 5566
  GG aa 3834   GG aa 3988   GG aa 4133   GG aa 4320   GG bb 3530   GG bb 3539
  GG bb 3624   GG bb 4308   HH aa 4464   HH aa 4653   HH aa 4963   HH bb 4480
  HH bb 4713   HH bb 4760   HH bb 5088   HH bb 5113   HH bb 5310   II aa 2988
  II aa 3242   II bb 2835   II bb 2969   II bb 3197   II bb 3219   II bb 3390
  JJ aa 2901   JJ aa 3032   JJ aa 3566   JJ aa 3687   JJ bb 2961   JJ bb 3446
  JJ bb 3464   JJ bb 3543}

do_execsql_test 1.12.7 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN CURRENT ROW         AND 0 FOLLOWING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 1373   AA aa 1396   AA aa 2068   AA aa 2084   AA bb 1508   AA bb 1751
  AA bb 1806   AA bb 2069   BB aa 2111   BB aa 2213   BB aa 2461   BB aa 2474
  BB aa 2480   BB aa 2626   BB bb 3627   BB bb 3675   BB bb 3681   BB bb 3756
  BB bb 3762   BB bb 3834   CC aa 1195   CC aa 1347   CC aa 1524   CC aa 1796
  CC bb 346   CC bb 822   DD aa 480   DD aa 1069   DD aa 1101   DD bb 1748
  DD bb 1913   DD bb 1991   DD bb 2469   EE aa 113   EE aa 777   EE bb 881
  EE bb 1020   EE bb 1397   FF aa 1493   FF aa 1496   FF aa 1545   FF aa 1955
  FF bb 2567   FF bb 2635   FF bb 2779   FF bb 2931   FF bb 3210   FF bb 3403
  GG aa 963   GG aa 1117   GG aa 1262   GG aa 1449   GG bb 1933   GG bb 1942
  GG bb 2027   GG bb 2711   HH aa 1270   HH aa 1459   HH aa 1769   HH bb 2231
  HH bb 2464   HH bb 2511   HH bb 2839   HH bb 2864   HH bb 3061   II aa 398
  II aa 652   II bb 1785   II bb 1919   II bb 2147   II bb 2169   II bb 2340
  JJ aa 1115   JJ aa 1246   JJ aa 1780   JJ aa 1901   JJ bb 947   JJ bb 1432
  JJ bb 1450   JJ bb 1529}

do_execsql_test 1.12.8 {
  SELECT a, b, 
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN CURRENT ROW         AND 0 FOLLOWING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN CURRENT ROW         AND 0 FOLLOWING ),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN CURRENT ROW         AND 0 FOLLOWING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN CURRENT ROW         AND 0 FOLLOWING )
    FROM t3 ORDER BY 1, 2, 3;
} {AA aa 3751 4685 1373 2307   AA aa 3774 4685 1396 2307
  AA aa 4446 4685 2068 2307   AA aa 4462 4685 2084 2307
  AA bb 3815 4685 1508 2378   AA bb 4058 4685 1751 2378
  AA bb 4113 4685 1806 2378   AA bb 4376 4685 2069 2378
  BB aa 6578 7340 2111 2873   BB aa 6680 7340 2213 2873
  BB aa 6928 7340 2461 2873   BB aa 6941 7340 2474 2873
  BB aa 6947 7340 2480 2873   BB aa 7093 7340 2626 2873
  BB bb 6500 7340 3627 4467   BB bb 6548 7340 3675 4467
  BB bb 6554 7340 3681 4467   BB bb 6629 7340 3756 4467
  BB bb 6635 7340 3762 4467   BB bb 6707 7340 3834 4467
  CC aa 2363 3122 1195 1954   CC aa 2515 3122 1347 1954
  CC aa 2692 3122 1524 1954   CC aa 2964 3122 1796 1954
  CC bb 2300 3122 346 1168   CC bb 2776 3122 822 1168
  DD aa 3187 4032 480 1325   DD aa 3776 4032 1069 1325
  DD aa 3808 4032 1101 1325   DD bb 3073 4032 1748 2707
  DD bb 3238 4032 1913 2707   DD bb 3316 4032 1991 2707
  DD bb 3794 4032 2469 2707   EE aa 1762 2539 113 890
  EE aa 2426 2539 777 890   EE bb 1771 2539 881 1649
  EE bb 1910 2539 1020 1649   EE bb 2287 2539 1397 1649
  FF aa 4998 5668 1493 2163   FF aa 5001 5668 1496 2163
  FF aa 5050 5668 1545 2163   FF aa 5460 5668 1955 2163
  FF bb 4730 5668 2567 3505   FF bb 4798 5668 2635 3505
  FF bb 4942 5668 2779 3505   FF bb 5094 5668 2931 3505
  FF bb 5373 5668 3210 3505   FF bb 5566 5668 3403 3505
  GG aa 3834 4468 963 1597   GG aa 3988 4468 1117 1597
  GG aa 4133 4468 1262 1597   GG aa 4320 4468 1449 1597
  GG bb 3530 4468 1933 2871   GG bb 3539 4468 1942 2871
  GG bb 3624 4468 2027 2871   GG bb 4308 4468 2711 2871
  HH aa 4464 5443 1270 2249   HH aa 4653 5443 1459 2249
  HH aa 4963 5443 1769 2249   HH bb 4480 5443 2231 3194
  HH bb 4713 5443 2464 3194   HH bb 4760 5443 2511 3194
  HH bb 5088 5443 2839 3194   HH bb 5113 5443 2864 3194
  HH bb 5310 5443 3061 3194   II aa 2988 3640 398 1050
  II aa 3242 3640 652 1050   II bb 2835 3640 1785 2590
  II bb 2969 3640 1919 2590   II bb 3197 3640 2147 2590
  II bb 3219 3640 2169 2590   II bb 3390 3640 2340 2590
  JJ aa 2901 3800 1115 2014   JJ aa 3032 3800 1246 2014
  JJ aa 3566 3800 1780 2014   JJ aa 3687 3800 1901 2014
  JJ bb 2961 3800 947 1786   JJ bb 3446 3800 1432 1786
  JJ bb 3464 3800 1450 1786   JJ bb 3543 3800 1529 1786}

do_execsql_test 1.13.1 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN CURRENT ROW         AND 1 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 12025   AA aa 12025   AA aa 12025   AA aa 12025   AA bb 12025
  AA bb 12025   AA bb 12025   AA bb 12025   BB aa 10462   BB aa 10462
  BB aa 10462   BB aa 10462   BB aa 10462   BB aa 10462   BB bb 10462
  BB bb 10462   BB bb 10462   BB bb 10462   BB bb 10462   BB bb 10462
  CC aa 7154   CC aa 7154   CC aa 7154   CC aa 7154   CC bb 7154   CC bb 7154
  DD aa 6571   DD aa 6571   DD aa 6571   DD bb 6571   DD bb 6571   DD bb 6571
  DD bb 6571   EE aa 8207   EE aa 8207   EE bb 8207   EE bb 8207   EE bb 8207
  FF aa 10136   FF aa 10136   FF aa 10136   FF aa 10136   FF bb 10136
  FF bb 10136   FF bb 10136   FF bb 10136   FF bb 10136   FF bb 10136
  GG aa 9911   GG aa 9911   GG aa 9911   GG aa 9911   GG bb 9911   GG bb 9911
  GG bb 9911   GG bb 9911   HH aa 9083   HH aa 9083   HH aa 9083   HH bb 9083
  HH bb 9083   HH bb 9083   HH bb 9083   HH bb 9083   HH bb 9083   II aa 7440
  II aa 7440   II bb 7440   II bb 7440   II bb 7440   II bb 7440   II bb 7440
  JJ aa 3800   JJ aa 3800   JJ aa 3800   JJ aa 3800   JJ bb 3800   JJ bb 3800
  JJ bb 3800   JJ bb 3800}

do_execsql_test 1.13.2 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN CURRENT ROW         AND 1 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 4685   AA aa 4685   AA aa 4685   AA aa 4685   AA bb 5251   AA bb 5251
  AA bb 5251   AA bb 5251   BB aa 7340   BB aa 7340   BB aa 7340   BB aa 7340
  BB aa 7340   BB aa 7340   BB bb 6421   BB bb 6421   BB bb 6421   BB bb 6421
  BB bb 6421   BB bb 6421   CC aa 3122   CC aa 3122   CC aa 3122   CC aa 3122
  CC bb 2493   CC bb 2493   DD aa 4032   DD aa 4032   DD aa 4032   DD bb 3597
  DD bb 3597   DD bb 3597   DD bb 3597   EE aa 2539   EE aa 2539   EE bb 3812
  EE bb 3812   EE bb 3812   FF aa 5668   FF aa 5668   FF aa 5668   FF aa 5668
  FF bb 5102   FF bb 5102   FF bb 5102   FF bb 5102   FF bb 5102   FF bb 5102
  GG aa 4468   GG aa 4468   GG aa 4468   GG aa 4468   GG bb 5120   GG bb 5120
  GG bb 5120   GG bb 5120   HH aa 5443   HH aa 5443   HH aa 5443   HH bb 4244
  HH bb 4244   HH bb 4244   HH bb 4244   HH bb 4244   HH bb 4244   II aa 3640
  II aa 3640   II bb 4604   II bb 4604   II bb 4604   II bb 4604   II bb 4604
  JJ aa 3800   JJ aa 3800   JJ aa 3800   JJ aa 3800   JJ bb 1786   JJ bb 1786
  JJ bb 1786   JJ bb 1786}

do_execsql_test 1.13.3 {
  SELECT a, b, rank() OVER (ORDER BY a  GROUPS BETWEEN CURRENT ROW         AND 1 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 1   AA aa 1   AA aa 1   AA aa 1   AA bb 1   AA bb 1   AA bb 1
  AA bb 1   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9
  BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   CC aa 21
  CC aa 21   CC aa 21   CC aa 21   CC bb 21   CC bb 21   DD aa 27   DD aa 27
  DD aa 27   DD bb 27   DD bb 27   DD bb 27   DD bb 27   EE aa 34   EE aa 34
  EE bb 34   EE bb 34   EE bb 34   FF aa 39   FF aa 39   FF aa 39   FF aa 39
  FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   GG aa 49
  GG aa 49   GG aa 49   GG aa 49   GG bb 49   GG bb 49   GG bb 49   GG bb 49
  HH aa 57   HH aa 57   HH aa 57   HH bb 57   HH bb 57   HH bb 57   HH bb 57
  HH bb 57   HH bb 57   II aa 66   II aa 66   II bb 66   II bb 66   II bb 66
  II bb 66   II bb 66   JJ aa 73   JJ aa 73   JJ aa 73   JJ aa 73   JJ bb 73
  JJ bb 73   JJ bb 73   JJ bb 73}

do_execsql_test 1.13.4 {
  SELECT a, b, max(c) OVER (ORDER BY a,b  GROUPS BETWEEN CURRENT ROW         AND 1 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 934   AA aa 934   AA aa 934   AA aa 934   AA bb 870   AA bb 870
  AA bb 870   AA bb 870   BB aa 840   BB aa 840   BB aa 840   BB aa 840
  BB aa 840   BB aa 840   BB bb 840   BB bb 840   BB bb 840   BB bb 840
  BB bb 840   BB bb 840   CC aa 822   CC aa 822   CC aa 822   CC aa 822
  CC bb 845   CC bb 845   DD aa 959   DD aa 959   DD aa 959   DD bb 959
  DD bb 959   DD bb 959   DD bb 959   EE aa 777   EE aa 777   EE bb 768
  EE bb 768   EE bb 768   FF aa 938   FF aa 938   FF aa 938   FF aa 938
  FF bb 938   FF bb 938   FF bb 938   FF bb 938   FF bb 938   FF bb 938
  GG aa 938   GG aa 938   GG aa 938   GG aa 938   GG bb 979   GG bb 979
  GG bb 979   GG bb 979   HH aa 979   HH aa 979   HH aa 979   HH bb 963
  HH bb 963   HH bb 963   HH bb 963   HH bb 963   HH bb 963   II aa 805
  II aa 805   II bb 899   II bb 899   II bb 899   II bb 899   II bb 899
  JJ aa 899   JJ aa 899   JJ aa 899   JJ aa 899   JJ bb 839   JJ bb 839
  JJ bb 839   JJ bb 839}

do_execsql_test 1.13.5 {
  SELECT a, b, min(c) OVER (ORDER BY a,b  GROUPS BETWEEN CURRENT ROW         AND 1 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 223   AA aa 223   AA aa 223   AA aa 223   AA bb 247   AA bb 247
  AA bb 247   AA bb 247   BB aa 247   BB aa 247   BB aa 247   BB aa 247
  BB aa 247   BB aa 247   BB bb 158   BB bb 158   BB bb 158   BB bb 158
  BB bb 158   BB bb 158   CC aa 158   CC aa 158   CC aa 158   CC aa 158
  CC bb 224   CC bb 224   DD aa 224   DD aa 224   DD aa 224   DD bb 113
  DD bb 113   DD bb 113   DD bb 113   EE aa 113   EE aa 113   EE bb 208
  EE bb 208   EE bb 208   FF aa 102   FF aa 102   FF aa 102   FF aa 102
  FF bb 102   FF bb 102   FF bb 102   FF bb 102   FF bb 102   FF bb 102
  GG aa 148   GG aa 148   GG aa 148   GG aa 148   GG bb 160   GG bb 160
  GG bb 160   GG bb 160   HH aa 133   HH aa 133   HH aa 133   HH bb 133
  HH bb 133   HH bb 133   HH bb 133   HH bb 133   HH bb 133   II aa 250
  II aa 250   II bb 113   II bb 113   II bb 113   II bb 113   II bb 113
  JJ aa 113   JJ aa 113   JJ aa 113   JJ aa 113   JJ bb 257   JJ bb 257
  JJ bb 257   JJ bb 257}

do_execsql_test 1.13.6 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN CURRENT ROW         AND 1 FOLLOWING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 11091   AA aa 11114   AA aa 11786   AA aa 11802   AA bb 11155
  AA bb 11398   AA bb 11453   AA bb 11716   BB aa 9700   BB aa 9802
  BB aa 10050   BB aa 10063   BB aa 10069   BB aa 10215   BB bb 9622
  BB bb 9670   BB bb 9676   BB bb 9751   BB bb 9757   BB bb 9829   CC aa 6395
  CC aa 6547   CC aa 6724   CC aa 6996   CC bb 6332   CC bb 6808   DD aa 5726
  DD aa 6315   DD aa 6347   DD bb 5612   DD bb 5777   DD bb 5855   DD bb 6333
  EE aa 7430   EE aa 8094   EE bb 7439   EE bb 7578   EE bb 7955   FF aa 9466
  FF aa 9469   FF aa 9518   FF aa 9928   FF bb 9198   FF bb 9266   FF bb 9410
  FF bb 9562   FF bb 9841   FF bb 10034   GG aa 9277   GG aa 9431
  GG aa 9576   GG aa 9763   GG bb 8973   GG bb 8982   GG bb 9067   GG bb 9751
  HH aa 8104   HH aa 8293   HH aa 8603   HH bb 8120   HH bb 8353   HH bb 8400
  HH bb 8728   HH bb 8753   HH bb 8950   II aa 6788   II aa 7042   II bb 6635
  II bb 6769   II bb 6997   II bb 7019   II bb 7190   JJ aa 2901   JJ aa 3032
  JJ aa 3566   JJ aa 3687   JJ bb 2961   JJ bb 3446   JJ bb 3464   JJ bb 3543}

do_execsql_test 1.13.7 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN CURRENT ROW         AND 1 FOLLOWING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 3751   AA aa 3774   AA aa 4446   AA aa 4462   AA bb 4381   AA bb 4624
  AA bb 4679   AA bb 4942   BB aa 6578   BB aa 6680   BB aa 6928   BB aa 6941
  BB aa 6947   BB aa 7093   BB bb 5581   BB bb 5629   BB bb 5635   BB bb 5710
  BB bb 5716   BB bb 5788   CC aa 2363   CC aa 2515   CC aa 2692   CC aa 2964
  CC bb 1671   CC bb 2147   DD aa 3187   DD aa 3776   DD aa 3808   DD bb 2638
  DD bb 2803   DD bb 2881   DD bb 3359   EE aa 1762   EE aa 2426   EE bb 3044
  EE bb 3183   EE bb 3560   FF aa 4998   FF aa 5001   FF aa 5050   FF aa 5460
  FF bb 4164   FF bb 4232   FF bb 4376   FF bb 4528   FF bb 4807   FF bb 5000
  GG aa 3834   GG aa 3988   GG aa 4133   GG aa 4320   GG bb 4182   GG bb 4191
  GG bb 4276   GG bb 4960   HH aa 4464   HH aa 4653   HH aa 4963   HH bb 3281
  HH bb 3514   HH bb 3561   HH bb 3889   HH bb 3914   HH bb 4111   II aa 2988
  II aa 3242   II bb 3799   II bb 3933   II bb 4161   II bb 4183   II bb 4354
  JJ aa 2901   JJ aa 3032   JJ aa 3566   JJ aa 3687   JJ bb 947   JJ bb 1432
  JJ bb 1450   JJ bb 1529}

do_execsql_test 1.13.8 {
  SELECT a, b, 
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN CURRENT ROW         AND 1 FOLLOWING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN CURRENT ROW         AND 1 FOLLOWING ),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN CURRENT ROW         AND 1 FOLLOWING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN CURRENT ROW         AND 1 FOLLOWING )
    FROM t3 ORDER BY 1, 2, 3;
} {AA aa 11091 12025 3751 4685   AA aa 11114 12025 3774 4685
  AA aa 11786 12025 4446 4685   AA aa 11802 12025 4462 4685
  AA bb 11155 12025 4381 5251   AA bb 11398 12025 4624 5251
  AA bb 11453 12025 4679 5251   AA bb 11716 12025 4942 5251
  BB aa 9700 10462 6578 7340   BB aa 9802 10462 6680 7340
  BB aa 10050 10462 6928 7340   BB aa 10063 10462 6941 7340
  BB aa 10069 10462 6947 7340   BB aa 10215 10462 7093 7340
  BB bb 9622 10462 5581 6421   BB bb 9670 10462 5629 6421
  BB bb 9676 10462 5635 6421   BB bb 9751 10462 5710 6421
  BB bb 9757 10462 5716 6421   BB bb 9829 10462 5788 6421
  CC aa 6395 7154 2363 3122   CC aa 6547 7154 2515 3122
  CC aa 6724 7154 2692 3122   CC aa 6996 7154 2964 3122
  CC bb 6332 7154 1671 2493   CC bb 6808 7154 2147 2493
  DD aa 5726 6571 3187 4032   DD aa 6315 6571 3776 4032
  DD aa 6347 6571 3808 4032   DD bb 5612 6571 2638 3597
  DD bb 5777 6571 2803 3597   DD bb 5855 6571 2881 3597
  DD bb 6333 6571 3359 3597   EE aa 7430 8207 1762 2539
  EE aa 8094 8207 2426 2539   EE bb 7439 8207 3044 3812
  EE bb 7578 8207 3183 3812   EE bb 7955 8207 3560 3812
  FF aa 9466 10136 4998 5668   FF aa 9469 10136 5001 5668
  FF aa 9518 10136 5050 5668   FF aa 9928 10136 5460 5668
  FF bb 9198 10136 4164 5102   FF bb 9266 10136 4232 5102
  FF bb 9410 10136 4376 5102   FF bb 9562 10136 4528 5102
  FF bb 9841 10136 4807 5102   FF bb 10034 10136 5000 5102
  GG aa 9277 9911 3834 4468   GG aa 9431 9911 3988 4468
  GG aa 9576 9911 4133 4468   GG aa 9763 9911 4320 4468
  GG bb 8973 9911 4182 5120   GG bb 8982 9911 4191 5120
  GG bb 9067 9911 4276 5120   GG bb 9751 9911 4960 5120
  HH aa 8104 9083 4464 5443   HH aa 8293 9083 4653 5443
  HH aa 8603 9083 4963 5443   HH bb 8120 9083 3281 4244
  HH bb 8353 9083 3514 4244   HH bb 8400 9083 3561 4244
  HH bb 8728 9083 3889 4244   HH bb 8753 9083 3914 4244
  HH bb 8950 9083 4111 4244   II aa 6788 7440 2988 3640
  II aa 7042 7440 3242 3640   II bb 6635 7440 3799 4604
  II bb 6769 7440 3933 4604   II bb 6997 7440 4161 4604
  II bb 7019 7440 4183 4604   II bb 7190 7440 4354 4604
  JJ aa 2901 3800 2901 3800   JJ aa 3032 3800 3032 3800
  JJ aa 3566 3800 3566 3800   JJ aa 3687 3800 3687 3800
  JJ bb 2961 3800 947 1786   JJ bb 3446 3800 1432 1786
  JJ bb 3464 3800 1450 1786   JJ bb 3543 3800 1529 1786}

do_execsql_test 1.14.1 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN CURRENT ROW         AND 100 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 44737   AA aa 44737   AA aa 44737   AA aa 44737   AA bb 44737
  AA bb 44737   AA bb 44737   AA bb 44737   BB aa 40052   BB aa 40052
  BB aa 40052   BB aa 40052   BB aa 40052   BB aa 40052   BB bb 40052
  BB bb 40052   BB bb 40052   BB bb 40052   BB bb 40052   BB bb 40052
  CC aa 32712   CC aa 32712   CC aa 32712   CC aa 32712   CC bb 32712
  CC bb 32712   DD aa 29590   DD aa 29590   DD aa 29590   DD bb 29590
  DD bb 29590   DD bb 29590   DD bb 29590   EE aa 25558   EE aa 25558
  EE bb 25558   EE bb 25558   EE bb 25558   FF aa 23019   FF aa 23019
  FF aa 23019   FF aa 23019   FF bb 23019   FF bb 23019   FF bb 23019
  FF bb 23019   FF bb 23019   FF bb 23019   GG aa 17351   GG aa 17351
  GG aa 17351   GG aa 17351   GG bb 17351   GG bb 17351   GG bb 17351
  GG bb 17351   HH aa 12883   HH aa 12883   HH aa 12883   HH bb 12883
  HH bb 12883   HH bb 12883   HH bb 12883   HH bb 12883   HH bb 12883
  II aa 7440   II aa 7440   II bb 7440   II bb 7440   II bb 7440   II bb 7440
  II bb 7440   JJ aa 3800   JJ aa 3800   JJ aa 3800   JJ aa 3800   JJ bb 3800
  JJ bb 3800   JJ bb 3800   JJ bb 3800}

do_execsql_test 1.14.2 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN CURRENT ROW         AND 100 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 44737   AA aa 44737   AA aa 44737   AA aa 44737   AA bb 42430
  AA bb 42430   AA bb 42430   AA bb 42430   BB aa 40052   BB aa 40052
  BB aa 40052   BB aa 40052   BB aa 40052   BB aa 40052   BB bb 37179
  BB bb 37179   BB bb 37179   BB bb 37179   BB bb 37179   BB bb 37179
  CC aa 32712   CC aa 32712   CC aa 32712   CC aa 32712   CC bb 30758
  CC bb 30758   DD aa 29590   DD aa 29590   DD aa 29590   DD bb 28265
  DD bb 28265   DD bb 28265   DD bb 28265   EE aa 25558   EE aa 25558
  EE bb 24668   EE bb 24668   EE bb 24668   FF aa 23019   FF aa 23019
  FF aa 23019   FF aa 23019   FF bb 20856   FF bb 20856   FF bb 20856
  FF bb 20856   FF bb 20856   FF bb 20856   GG aa 17351   GG aa 17351
  GG aa 17351   GG aa 17351   GG bb 15754   GG bb 15754   GG bb 15754
  GG bb 15754   HH aa 12883   HH aa 12883   HH aa 12883   HH bb 10634
  HH bb 10634   HH bb 10634   HH bb 10634   HH bb 10634   HH bb 10634
  II aa 7440   II aa 7440   II bb 6390   II bb 6390   II bb 6390   II bb 6390
  II bb 6390   JJ aa 3800   JJ aa 3800   JJ aa 3800   JJ aa 3800   JJ bb 1786
  JJ bb 1786   JJ bb 1786   JJ bb 1786}

do_execsql_test 1.14.3 {
  SELECT a, b, rank() OVER (ORDER BY a  GROUPS BETWEEN CURRENT ROW         AND 100 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 1   AA aa 1   AA aa 1   AA aa 1   AA bb 1   AA bb 1   AA bb 1
  AA bb 1   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9
  BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   CC aa 21
  CC aa 21   CC aa 21   CC aa 21   CC bb 21   CC bb 21   DD aa 27   DD aa 27
  DD aa 27   DD bb 27   DD bb 27   DD bb 27   DD bb 27   EE aa 34   EE aa 34
  EE bb 34   EE bb 34   EE bb 34   FF aa 39   FF aa 39   FF aa 39   FF aa 39
  FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   GG aa 49
  GG aa 49   GG aa 49   GG aa 49   GG bb 49   GG bb 49   GG bb 49   GG bb 49
  HH aa 57   HH aa 57   HH aa 57   HH bb 57   HH bb 57   HH bb 57   HH bb 57
  HH bb 57   HH bb 57   II aa 66   II aa 66   II bb 66   II bb 66   II bb 66
  II bb 66   II bb 66   JJ aa 73   JJ aa 73   JJ aa 73   JJ aa 73   JJ bb 73
  JJ bb 73   JJ bb 73   JJ bb 73}

do_execsql_test 1.14.4 {
  SELECT a, b, max(c) OVER (ORDER BY a,b  GROUPS BETWEEN CURRENT ROW         AND 100 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 979   AA aa 979   AA aa 979   AA aa 979   AA bb 979   AA bb 979
  AA bb 979   AA bb 979   BB aa 979   BB aa 979   BB aa 979   BB aa 979
  BB aa 979   BB aa 979   BB bb 979   BB bb 979   BB bb 979   BB bb 979
  BB bb 979   BB bb 979   CC aa 979   CC aa 979   CC aa 979   CC aa 979
  CC bb 979   CC bb 979   DD aa 979   DD aa 979   DD aa 979   DD bb 979
  DD bb 979   DD bb 979   DD bb 979   EE aa 979   EE aa 979   EE bb 979
  EE bb 979   EE bb 979   FF aa 979   FF aa 979   FF aa 979   FF aa 979
  FF bb 979   FF bb 979   FF bb 979   FF bb 979   FF bb 979   FF bb 979
  GG aa 979   GG aa 979   GG aa 979   GG aa 979   GG bb 979   GG bb 979
  GG bb 979   GG bb 979   HH aa 979   HH aa 979   HH aa 979   HH bb 963
  HH bb 963   HH bb 963   HH bb 963   HH bb 963   HH bb 963   II aa 899
  II aa 899   II bb 899   II bb 899   II bb 899   II bb 899   II bb 899
  JJ aa 899   JJ aa 899   JJ aa 899   JJ aa 899   JJ bb 839   JJ bb 839
  JJ bb 839   JJ bb 839}

do_execsql_test 1.14.5 {
  SELECT a, b, min(c) OVER (ORDER BY a,b  GROUPS BETWEEN CURRENT ROW         AND 100 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 102   AA aa 102   AA aa 102   AA aa 102   AA bb 102   AA bb 102
  AA bb 102   AA bb 102   BB aa 102   BB aa 102   BB aa 102   BB aa 102
  BB aa 102   BB aa 102   BB bb 102   BB bb 102   BB bb 102   BB bb 102
  BB bb 102   BB bb 102   CC aa 102   CC aa 102   CC aa 102   CC aa 102
  CC bb 102   CC bb 102   DD aa 102   DD aa 102   DD aa 102   DD bb 102
  DD bb 102   DD bb 102   DD bb 102   EE aa 102   EE aa 102   EE bb 102
  EE bb 102   EE bb 102   FF aa 102   FF aa 102   FF aa 102   FF aa 102
  FF bb 102   FF bb 102   FF bb 102   FF bb 102   FF bb 102   FF bb 102
  GG aa 113   GG aa 113   GG aa 113   GG aa 113   GG bb 113   GG bb 113
  GG bb 113   GG bb 113   HH aa 113   HH aa 113   HH aa 113   HH bb 113
  HH bb 113   HH bb 113   HH bb 113   HH bb 113   HH bb 113   II aa 113
  II aa 113   II bb 113   II bb 113   II bb 113   II bb 113   II bb 113
  JJ aa 113   JJ aa 113   JJ aa 113   JJ aa 113   JJ bb 257   JJ bb 257
  JJ bb 257   JJ bb 257}

do_execsql_test 1.14.6 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN CURRENT ROW         AND 100 FOLLOWING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 43803   AA aa 43826   AA aa 44498   AA aa 44514   AA bb 43867
  AA bb 44110   AA bb 44165   AA bb 44428   BB aa 39290   BB aa 39392
  BB aa 39640   BB aa 39653   BB aa 39659   BB aa 39805   BB bb 39212
  BB bb 39260   BB bb 39266   BB bb 39341   BB bb 39347   BB bb 39419
  CC aa 31953   CC aa 32105   CC aa 32282   CC aa 32554   CC bb 31890
  CC bb 32366   DD aa 28745   DD aa 29334   DD aa 29366   DD bb 28631
  DD bb 28796   DD bb 28874   DD bb 29352   EE aa 24781   EE aa 25445
  EE bb 24790   EE bb 24929   EE bb 25306   FF aa 22349   FF aa 22352
  FF aa 22401   FF aa 22811   FF bb 22081   FF bb 22149   FF bb 22293
  FF bb 22445   FF bb 22724   FF bb 22917   GG aa 16717   GG aa 16871
  GG aa 17016   GG aa 17203   GG bb 16413   GG bb 16422   GG bb 16507
  GG bb 17191   HH aa 11904   HH aa 12093   HH aa 12403   HH bb 11920
  HH bb 12153   HH bb 12200   HH bb 12528   HH bb 12553   HH bb 12750
  II aa 6788   II aa 7042   II bb 6635   II bb 6769   II bb 6997   II bb 7019
  II bb 7190   JJ aa 2901   JJ aa 3032   JJ aa 3566   JJ aa 3687   JJ bb 2961
  JJ bb 3446   JJ bb 3464   JJ bb 3543}

do_execsql_test 1.14.7 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN CURRENT ROW         AND 100 FOLLOWING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 43803   AA aa 43826   AA aa 44498   AA aa 44514   AA bb 41560
  AA bb 41803   AA bb 41858   AA bb 42121   BB aa 39290   BB aa 39392
  BB aa 39640   BB aa 39653   BB aa 39659   BB aa 39805   BB bb 36339
  BB bb 36387   BB bb 36393   BB bb 36468   BB bb 36474   BB bb 36546
  CC aa 31953   CC aa 32105   CC aa 32282   CC aa 32554   CC bb 29936
  CC bb 30412   DD aa 28745   DD aa 29334   DD aa 29366   DD bb 27306
  DD bb 27471   DD bb 27549   DD bb 28027   EE aa 24781   EE aa 25445
  EE bb 23900   EE bb 24039   EE bb 24416   FF aa 22349   FF aa 22352
  FF aa 22401   FF aa 22811   FF bb 19918   FF bb 19986   FF bb 20130
  FF bb 20282   FF bb 20561   FF bb 20754   GG aa 16717   GG aa 16871
  GG aa 17016   GG aa 17203   GG bb 14816   GG bb 14825   GG bb 14910
  GG bb 15594   HH aa 11904   HH aa 12093   HH aa 12403   HH bb 9671
  HH bb 9904   HH bb 9951   HH bb 10279   HH bb 10304   HH bb 10501
  II aa 6788   II aa 7042   II bb 5585   II bb 5719   II bb 5947   II bb 5969
  II bb 6140   JJ aa 2901   JJ aa 3032   JJ aa 3566   JJ aa 3687   JJ bb 947
  JJ bb 1432   JJ bb 1450   JJ bb 1529}

do_execsql_test 1.14.8 {
  SELECT a, b, 
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN CURRENT ROW         AND 100 FOLLOWING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN CURRENT ROW         AND 100 FOLLOWING ),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN CURRENT ROW         AND 100 FOLLOWING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN CURRENT ROW         AND 100 FOLLOWING )
    FROM t3 ORDER BY 1, 2, 3;
} {AA aa 43803 44737 43803 44737   AA aa 43826 44737 43826 44737
  AA aa 44498 44737 44498 44737   AA aa 44514 44737 44514 44737
  AA bb 43867 44737 41560 42430   AA bb 44110 44737 41803 42430
  AA bb 44165 44737 41858 42430   AA bb 44428 44737 42121 42430
  BB aa 39290 40052 39290 40052   BB aa 39392 40052 39392 40052
  BB aa 39640 40052 39640 40052   BB aa 39653 40052 39653 40052
  BB aa 39659 40052 39659 40052   BB aa 39805 40052 39805 40052
  BB bb 39212 40052 36339 37179   BB bb 39260 40052 36387 37179
  BB bb 39266 40052 36393 37179   BB bb 39341 40052 36468 37179
  BB bb 39347 40052 36474 37179   BB bb 39419 40052 36546 37179
  CC aa 31953 32712 31953 32712   CC aa 32105 32712 32105 32712
  CC aa 32282 32712 32282 32712   CC aa 32554 32712 32554 32712
  CC bb 31890 32712 29936 30758   CC bb 32366 32712 30412 30758
  DD aa 28745 29590 28745 29590   DD aa 29334 29590 29334 29590
  DD aa 29366 29590 29366 29590   DD bb 28631 29590 27306 28265
  DD bb 28796 29590 27471 28265   DD bb 28874 29590 27549 28265
  DD bb 29352 29590 28027 28265   EE aa 24781 25558 24781 25558
  EE aa 25445 25558 25445 25558   EE bb 24790 25558 23900 24668
  EE bb 24929 25558 24039 24668   EE bb 25306 25558 24416 24668
  FF aa 22349 23019 22349 23019   FF aa 22352 23019 22352 23019
  FF aa 22401 23019 22401 23019   FF aa 22811 23019 22811 23019
  FF bb 22081 23019 19918 20856   FF bb 22149 23019 19986 20856
  FF bb 22293 23019 20130 20856   FF bb 22445 23019 20282 20856
  FF bb 22724 23019 20561 20856   FF bb 22917 23019 20754 20856
  GG aa 16717 17351 16717 17351   GG aa 16871 17351 16871 17351
  GG aa 17016 17351 17016 17351   GG aa 17203 17351 17203 17351
  GG bb 16413 17351 14816 15754   GG bb 16422 17351 14825 15754
  GG bb 16507 17351 14910 15754   GG bb 17191 17351 15594 15754
  HH aa 11904 12883 11904 12883   HH aa 12093 12883 12093 12883
  HH aa 12403 12883 12403 12883   HH bb 11920 12883 9671 10634
  HH bb 12153 12883 9904 10634   HH bb 12200 12883 9951 10634
  HH bb 12528 12883 10279 10634   HH bb 12553 12883 10304 10634
  HH bb 12750 12883 10501 10634   II aa 6788 7440 6788 7440
  II aa 7042 7440 7042 7440   II bb 6635 7440 5585 6390
  II bb 6769 7440 5719 6390   II bb 6997 7440 5947 6390
  II bb 7019 7440 5969 6390   II bb 7190 7440 6140 6390
  JJ aa 2901 3800 2901 3800   JJ aa 3032 3800 3032 3800
  JJ aa 3566 3800 3566 3800   JJ aa 3687 3800 3687 3800
  JJ bb 2961 3800 947 1786   JJ bb 3446 3800 1432 1786
  JJ bb 3464 3800 1450 1786   JJ bb 3543 3800 1529 1786}

do_execsql_test 1.15.1 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN CURRENT ROW         AND UNBOUNDED FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 44737   AA aa 44737   AA aa 44737   AA aa 44737   AA bb 44737
  AA bb 44737   AA bb 44737   AA bb 44737   BB aa 40052   BB aa 40052
  BB aa 40052   BB aa 40052   BB aa 40052   BB aa 40052   BB bb 40052
  BB bb 40052   BB bb 40052   BB bb 40052   BB bb 40052   BB bb 40052
  CC aa 32712   CC aa 32712   CC aa 32712   CC aa 32712   CC bb 32712
  CC bb 32712   DD aa 29590   DD aa 29590   DD aa 29590   DD bb 29590
  DD bb 29590   DD bb 29590   DD bb 29590   EE aa 25558   EE aa 25558
  EE bb 25558   EE bb 25558   EE bb 25558   FF aa 23019   FF aa 23019
  FF aa 23019   FF aa 23019   FF bb 23019   FF bb 23019   FF bb 23019
  FF bb 23019   FF bb 23019   FF bb 23019   GG aa 17351   GG aa 17351
  GG aa 17351   GG aa 17351   GG bb 17351   GG bb 17351   GG bb 17351
  GG bb 17351   HH aa 12883   HH aa 12883   HH aa 12883   HH bb 12883
  HH bb 12883   HH bb 12883   HH bb 12883   HH bb 12883   HH bb 12883
  II aa 7440   II aa 7440   II bb 7440   II bb 7440   II bb 7440   II bb 7440
  II bb 7440   JJ aa 3800   JJ aa 3800   JJ aa 3800   JJ aa 3800   JJ bb 3800
  JJ bb 3800   JJ bb 3800   JJ bb 3800}

do_execsql_test 1.15.2 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN CURRENT ROW         AND UNBOUNDED FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 44737   AA aa 44737   AA aa 44737   AA aa 44737   AA bb 42430
  AA bb 42430   AA bb 42430   AA bb 42430   BB aa 40052   BB aa 40052
  BB aa 40052   BB aa 40052   BB aa 40052   BB aa 40052   BB bb 37179
  BB bb 37179   BB bb 37179   BB bb 37179   BB bb 37179   BB bb 37179
  CC aa 32712   CC aa 32712   CC aa 32712   CC aa 32712   CC bb 30758
  CC bb 30758   DD aa 29590   DD aa 29590   DD aa 29590   DD bb 28265
  DD bb 28265   DD bb 28265   DD bb 28265   EE aa 25558   EE aa 25558
  EE bb 24668   EE bb 24668   EE bb 24668   FF aa 23019   FF aa 23019
  FF aa 23019   FF aa 23019   FF bb 20856   FF bb 20856   FF bb 20856
  FF bb 20856   FF bb 20856   FF bb 20856   GG aa 17351   GG aa 17351
  GG aa 17351   GG aa 17351   GG bb 15754   GG bb 15754   GG bb 15754
  GG bb 15754   HH aa 12883   HH aa 12883   HH aa 12883   HH bb 10634
  HH bb 10634   HH bb 10634   HH bb 10634   HH bb 10634   HH bb 10634
  II aa 7440   II aa 7440   II bb 6390   II bb 6390   II bb 6390   II bb 6390
  II bb 6390   JJ aa 3800   JJ aa 3800   JJ aa 3800   JJ aa 3800   JJ bb 1786
  JJ bb 1786   JJ bb 1786   JJ bb 1786}

do_execsql_test 1.15.3 {
  SELECT a, b, rank() OVER (ORDER BY a  GROUPS BETWEEN CURRENT ROW         AND UNBOUNDED FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 1   AA aa 1   AA aa 1   AA aa 1   AA bb 1   AA bb 1   AA bb 1
  AA bb 1   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9
  BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   CC aa 21
  CC aa 21   CC aa 21   CC aa 21   CC bb 21   CC bb 21   DD aa 27   DD aa 27
  DD aa 27   DD bb 27   DD bb 27   DD bb 27   DD bb 27   EE aa 34   EE aa 34
  EE bb 34   EE bb 34   EE bb 34   FF aa 39   FF aa 39   FF aa 39   FF aa 39
  FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   GG aa 49
  GG aa 49   GG aa 49   GG aa 49   GG bb 49   GG bb 49   GG bb 49   GG bb 49
  HH aa 57   HH aa 57   HH aa 57   HH bb 57   HH bb 57   HH bb 57   HH bb 57
  HH bb 57   HH bb 57   II aa 66   II aa 66   II bb 66   II bb 66   II bb 66
  II bb 66   II bb 66   JJ aa 73   JJ aa 73   JJ aa 73   JJ aa 73   JJ bb 73
  JJ bb 73   JJ bb 73   JJ bb 73}

do_execsql_test 1.15.4 {
  SELECT a, b, max(c) OVER (ORDER BY a,b  GROUPS BETWEEN CURRENT ROW         AND UNBOUNDED FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 979   AA aa 979   AA aa 979   AA aa 979   AA bb 979   AA bb 979
  AA bb 979   AA bb 979   BB aa 979   BB aa 979   BB aa 979   BB aa 979
  BB aa 979   BB aa 979   BB bb 979   BB bb 979   BB bb 979   BB bb 979
  BB bb 979   BB bb 979   CC aa 979   CC aa 979   CC aa 979   CC aa 979
  CC bb 979   CC bb 979   DD aa 979   DD aa 979   DD aa 979   DD bb 979
  DD bb 979   DD bb 979   DD bb 979   EE aa 979   EE aa 979   EE bb 979
  EE bb 979   EE bb 979   FF aa 979   FF aa 979   FF aa 979   FF aa 979
  FF bb 979   FF bb 979   FF bb 979   FF bb 979   FF bb 979   FF bb 979
  GG aa 979   GG aa 979   GG aa 979   GG aa 979   GG bb 979   GG bb 979
  GG bb 979   GG bb 979   HH aa 979   HH aa 979   HH aa 979   HH bb 963
  HH bb 963   HH bb 963   HH bb 963   HH bb 963   HH bb 963   II aa 899
  II aa 899   II bb 899   II bb 899   II bb 899   II bb 899   II bb 899
  JJ aa 899   JJ aa 899   JJ aa 899   JJ aa 899   JJ bb 839   JJ bb 839
  JJ bb 839   JJ bb 839}

do_execsql_test 1.15.5 {
  SELECT a, b, min(c) OVER (ORDER BY a,b  GROUPS BETWEEN CURRENT ROW         AND UNBOUNDED FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 102   AA aa 102   AA aa 102   AA aa 102   AA bb 102   AA bb 102
  AA bb 102   AA bb 102   BB aa 102   BB aa 102   BB aa 102   BB aa 102
  BB aa 102   BB aa 102   BB bb 102   BB bb 102   BB bb 102   BB bb 102
  BB bb 102   BB bb 102   CC aa 102   CC aa 102   CC aa 102   CC aa 102
  CC bb 102   CC bb 102   DD aa 102   DD aa 102   DD aa 102   DD bb 102
  DD bb 102   DD bb 102   DD bb 102   EE aa 102   EE aa 102   EE bb 102
  EE bb 102   EE bb 102   FF aa 102   FF aa 102   FF aa 102   FF aa 102
  FF bb 102   FF bb 102   FF bb 102   FF bb 102   FF bb 102   FF bb 102
  GG aa 113   GG aa 113   GG aa 113   GG aa 113   GG bb 113   GG bb 113
  GG bb 113   GG bb 113   HH aa 113   HH aa 113   HH aa 113   HH bb 113
  HH bb 113   HH bb 113   HH bb 113   HH bb 113   HH bb 113   II aa 113
  II aa 113   II bb 113   II bb 113   II bb 113   II bb 113   II bb 113
  JJ aa 113   JJ aa 113   JJ aa 113   JJ aa 113   JJ bb 257   JJ bb 257
  JJ bb 257   JJ bb 257}

do_execsql_test 1.15.6 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN CURRENT ROW         AND UNBOUNDED FOLLOWING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 43803   AA aa 43826   AA aa 44498   AA aa 44514   AA bb 43867
  AA bb 44110   AA bb 44165   AA bb 44428   BB aa 39290   BB aa 39392
  BB aa 39640   BB aa 39653   BB aa 39659   BB aa 39805   BB bb 39212
  BB bb 39260   BB bb 39266   BB bb 39341   BB bb 39347   BB bb 39419
  CC aa 31953   CC aa 32105   CC aa 32282   CC aa 32554   CC bb 31890
  CC bb 32366   DD aa 28745   DD aa 29334   DD aa 29366   DD bb 28631
  DD bb 28796   DD bb 28874   DD bb 29352   EE aa 24781   EE aa 25445
  EE bb 24790   EE bb 24929   EE bb 25306   FF aa 22349   FF aa 22352
  FF aa 22401   FF aa 22811   FF bb 22081   FF bb 22149   FF bb 22293
  FF bb 22445   FF bb 22724   FF bb 22917   GG aa 16717   GG aa 16871
  GG aa 17016   GG aa 17203   GG bb 16413   GG bb 16422   GG bb 16507
  GG bb 17191   HH aa 11904   HH aa 12093   HH aa 12403   HH bb 11920
  HH bb 12153   HH bb 12200   HH bb 12528   HH bb 12553   HH bb 12750
  II aa 6788   II aa 7042   II bb 6635   II bb 6769   II bb 6997   II bb 7019
  II bb 7190   JJ aa 2901   JJ aa 3032   JJ aa 3566   JJ aa 3687   JJ bb 2961
  JJ bb 3446   JJ bb 3464   JJ bb 3543}

do_execsql_test 1.15.7 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN CURRENT ROW         AND UNBOUNDED FOLLOWING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 43803   AA aa 43826   AA aa 44498   AA aa 44514   AA bb 41560
  AA bb 41803   AA bb 41858   AA bb 42121   BB aa 39290   BB aa 39392
  BB aa 39640   BB aa 39653   BB aa 39659   BB aa 39805   BB bb 36339
  BB bb 36387   BB bb 36393   BB bb 36468   BB bb 36474   BB bb 36546
  CC aa 31953   CC aa 32105   CC aa 32282   CC aa 32554   CC bb 29936
  CC bb 30412   DD aa 28745   DD aa 29334   DD aa 29366   DD bb 27306
  DD bb 27471   DD bb 27549   DD bb 28027   EE aa 24781   EE aa 25445
  EE bb 23900   EE bb 24039   EE bb 24416   FF aa 22349   FF aa 22352
  FF aa 22401   FF aa 22811   FF bb 19918   FF bb 19986   FF bb 20130
  FF bb 20282   FF bb 20561   FF bb 20754   GG aa 16717   GG aa 16871
  GG aa 17016   GG aa 17203   GG bb 14816   GG bb 14825   GG bb 14910
  GG bb 15594   HH aa 11904   HH aa 12093   HH aa 12403   HH bb 9671
  HH bb 9904   HH bb 9951   HH bb 10279   HH bb 10304   HH bb 10501
  II aa 6788   II aa 7042   II bb 5585   II bb 5719   II bb 5947   II bb 5969
  II bb 6140   JJ aa 2901   JJ aa 3032   JJ aa 3566   JJ aa 3687   JJ bb 947
  JJ bb 1432   JJ bb 1450   JJ bb 1529}

do_execsql_test 1.15.8 {
  SELECT a, b, 
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN CURRENT ROW         AND UNBOUNDED FOLLOWING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN CURRENT ROW         AND UNBOUNDED FOLLOWING ),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN CURRENT ROW         AND UNBOUNDED FOLLOWING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN CURRENT ROW         AND UNBOUNDED FOLLOWING )
    FROM t3 ORDER BY 1, 2, 3;
} {AA aa 43803 44737 43803 44737   AA aa 43826 44737 43826 44737
  AA aa 44498 44737 44498 44737   AA aa 44514 44737 44514 44737
  AA bb 43867 44737 41560 42430   AA bb 44110 44737 41803 42430
  AA bb 44165 44737 41858 42430   AA bb 44428 44737 42121 42430
  BB aa 39290 40052 39290 40052   BB aa 39392 40052 39392 40052
  BB aa 39640 40052 39640 40052   BB aa 39653 40052 39653 40052
  BB aa 39659 40052 39659 40052   BB aa 39805 40052 39805 40052
  BB bb 39212 40052 36339 37179   BB bb 39260 40052 36387 37179
  BB bb 39266 40052 36393 37179   BB bb 39341 40052 36468 37179
  BB bb 39347 40052 36474 37179   BB bb 39419 40052 36546 37179
  CC aa 31953 32712 31953 32712   CC aa 32105 32712 32105 32712
  CC aa 32282 32712 32282 32712   CC aa 32554 32712 32554 32712
  CC bb 31890 32712 29936 30758   CC bb 32366 32712 30412 30758
  DD aa 28745 29590 28745 29590   DD aa 29334 29590 29334 29590
  DD aa 29366 29590 29366 29590   DD bb 28631 29590 27306 28265
  DD bb 28796 29590 27471 28265   DD bb 28874 29590 27549 28265
  DD bb 29352 29590 28027 28265   EE aa 24781 25558 24781 25558
  EE aa 25445 25558 25445 25558   EE bb 24790 25558 23900 24668
  EE bb 24929 25558 24039 24668   EE bb 25306 25558 24416 24668
  FF aa 22349 23019 22349 23019   FF aa 22352 23019 22352 23019
  FF aa 22401 23019 22401 23019   FF aa 22811 23019 22811 23019
  FF bb 22081 23019 19918 20856   FF bb 22149 23019 19986 20856
  FF bb 22293 23019 20130 20856   FF bb 22445 23019 20282 20856
  FF bb 22724 23019 20561 20856   FF bb 22917 23019 20754 20856
  GG aa 16717 17351 16717 17351   GG aa 16871 17351 16871 17351
  GG aa 17016 17351 17016 17351   GG aa 17203 17351 17203 17351
  GG bb 16413 17351 14816 15754   GG bb 16422 17351 14825 15754
  GG bb 16507 17351 14910 15754   GG bb 17191 17351 15594 15754
  HH aa 11904 12883 11904 12883   HH aa 12093 12883 12093 12883
  HH aa 12403 12883 12403 12883   HH bb 11920 12883 9671 10634
  HH bb 12153 12883 9904 10634   HH bb 12200 12883 9951 10634
  HH bb 12528 12883 10279 10634   HH bb 12553 12883 10304 10634
  HH bb 12750 12883 10501 10634   II aa 6788 7440 6788 7440
  II aa 7042 7440 7042 7440   II bb 6635 7440 5585 6390
  II bb 6769 7440 5719 6390   II bb 6997 7440 5947 6390
  II bb 7019 7440 5969 6390   II bb 7190 7440 6140 6390
  JJ aa 2901 3800 2901 3800   JJ aa 3032 3800 3032 3800
  JJ aa 3566 3800 3566 3800   JJ aa 3687 3800 3687 3800
  JJ bb 2961 3800 947 1786   JJ bb 3446 3800 1432 1786
  JJ bb 3464 3800 1450 1786   JJ bb 3543 3800 1529 1786}

do_execsql_test 1.16.1 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN 0 FOLLOWING         AND 0 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 4685   AA aa 4685   AA aa 4685   AA aa 4685   AA bb 4685   AA bb 4685
  AA bb 4685   AA bb 4685   BB aa 7340   BB aa 7340   BB aa 7340   BB aa 7340
  BB aa 7340   BB aa 7340   BB bb 7340   BB bb 7340   BB bb 7340   BB bb 7340
  BB bb 7340   BB bb 7340   CC aa 3122   CC aa 3122   CC aa 3122   CC aa 3122
  CC bb 3122   CC bb 3122   DD aa 4032   DD aa 4032   DD aa 4032   DD bb 4032
  DD bb 4032   DD bb 4032   DD bb 4032   EE aa 2539   EE aa 2539   EE bb 2539
  EE bb 2539   EE bb 2539   FF aa 5668   FF aa 5668   FF aa 5668   FF aa 5668
  FF bb 5668   FF bb 5668   FF bb 5668   FF bb 5668   FF bb 5668   FF bb 5668
  GG aa 4468   GG aa 4468   GG aa 4468   GG aa 4468   GG bb 4468   GG bb 4468
  GG bb 4468   GG bb 4468   HH aa 5443   HH aa 5443   HH aa 5443   HH bb 5443
  HH bb 5443   HH bb 5443   HH bb 5443   HH bb 5443   HH bb 5443   II aa 3640
  II aa 3640   II bb 3640   II bb 3640   II bb 3640   II bb 3640   II bb 3640
  JJ aa 3800   JJ aa 3800   JJ aa 3800   JJ aa 3800   JJ bb 3800   JJ bb 3800
  JJ bb 3800   JJ bb 3800}

do_execsql_test 1.16.2 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 0 FOLLOWING         AND 0 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 2307   AA aa 2307   AA aa 2307   AA aa 2307   AA bb 2378   AA bb 2378
  AA bb 2378   AA bb 2378   BB aa 2873   BB aa 2873   BB aa 2873   BB aa 2873
  BB aa 2873   BB aa 2873   BB bb 4467   BB bb 4467   BB bb 4467   BB bb 4467
  BB bb 4467   BB bb 4467   CC aa 1954   CC aa 1954   CC aa 1954   CC aa 1954
  CC bb 1168   CC bb 1168   DD aa 1325   DD aa 1325   DD aa 1325   DD bb 2707
  DD bb 2707   DD bb 2707   DD bb 2707   EE aa 890   EE aa 890   EE bb 1649
  EE bb 1649   EE bb 1649   FF aa 2163   FF aa 2163   FF aa 2163   FF aa 2163
  FF bb 3505   FF bb 3505   FF bb 3505   FF bb 3505   FF bb 3505   FF bb 3505
  GG aa 1597   GG aa 1597   GG aa 1597   GG aa 1597   GG bb 2871   GG bb 2871
  GG bb 2871   GG bb 2871   HH aa 2249   HH aa 2249   HH aa 2249   HH bb 3194
  HH bb 3194   HH bb 3194   HH bb 3194   HH bb 3194   HH bb 3194   II aa 1050
  II aa 1050   II bb 2590   II bb 2590   II bb 2590   II bb 2590   II bb 2590
  JJ aa 2014   JJ aa 2014   JJ aa 2014   JJ aa 2014   JJ bb 1786   JJ bb 1786
  JJ bb 1786   JJ bb 1786}

do_execsql_test 1.16.3 {
  SELECT a, b, rank() OVER (ORDER BY a  GROUPS BETWEEN 0 FOLLOWING         AND 0 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 1   AA aa 1   AA aa 1   AA aa 1   AA bb 1   AA bb 1   AA bb 1
  AA bb 1   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9
  BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   CC aa 21
  CC aa 21   CC aa 21   CC aa 21   CC bb 21   CC bb 21   DD aa 27   DD aa 27
  DD aa 27   DD bb 27   DD bb 27   DD bb 27   DD bb 27   EE aa 34   EE aa 34
  EE bb 34   EE bb 34   EE bb 34   FF aa 39   FF aa 39   FF aa 39   FF aa 39
  FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   GG aa 49
  GG aa 49   GG aa 49   GG aa 49   GG bb 49   GG bb 49   GG bb 49   GG bb 49
  HH aa 57   HH aa 57   HH aa 57   HH bb 57   HH bb 57   HH bb 57   HH bb 57
  HH bb 57   HH bb 57   II aa 66   II aa 66   II bb 66   II bb 66   II bb 66
  II bb 66   II bb 66   JJ aa 73   JJ aa 73   JJ aa 73   JJ aa 73   JJ bb 73
  JJ bb 73   JJ bb 73   JJ bb 73}

do_execsql_test 1.16.4 {
  SELECT a, b, max(c) OVER (ORDER BY a,b  GROUPS BETWEEN 0 FOLLOWING         AND 0 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 934   AA aa 934   AA aa 934   AA aa 934   AA bb 870   AA bb 870
  AA bb 870   AA bb 870   BB aa 762   BB aa 762   BB aa 762   BB aa 762
  BB aa 762   BB aa 762   BB bb 840   BB bb 840   BB bb 840   BB bb 840
  BB bb 840   BB bb 840   CC aa 759   CC aa 759   CC aa 759   CC aa 759
  CC bb 822   CC bb 822   DD aa 845   DD aa 845   DD aa 845   DD bb 959
  DD bb 959   DD bb 959   DD bb 959   EE aa 777   EE aa 777   EE bb 768
  EE bb 768   EE bb 768   FF aa 670   FF aa 670   FF aa 670   FF aa 670
  FF bb 938   FF bb 938   FF bb 938   FF bb 938   FF bb 938   FF bb 938
  GG aa 634   GG aa 634   GG aa 634   GG aa 634   GG bb 938   GG bb 938
  GG bb 938   GG bb 938   HH aa 979   HH aa 979   HH aa 979   HH bb 963
  HH bb 963   HH bb 963   HH bb 963   HH bb 963   HH bb 963   II aa 652
  II aa 652   II bb 805   II bb 805   II bb 805   II bb 805   II bb 805
  JJ aa 899   JJ aa 899   JJ aa 899   JJ aa 899   JJ bb 839   JJ bb 839
  JJ bb 839   JJ bb 839}

do_execsql_test 1.16.5 {
  SELECT a, b, min(c) OVER (ORDER BY a,b  GROUPS BETWEEN 0 FOLLOWING         AND 0 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 223   AA aa 223   AA aa 223   AA aa 223   AA bb 309   AA bb 309
  AA bb 309   AA bb 309   BB aa 247   BB aa 247   BB aa 247   BB aa 247
  BB aa 247   BB aa 247   BB bb 633   BB bb 633   BB bb 633   BB bb 633
  BB bb 633   BB bb 633   CC aa 158   CC aa 158   CC aa 158   CC aa 158
  CC bb 346   CC bb 346   DD aa 224   DD aa 224   DD aa 224   DD bb 238
  DD bb 238   DD bb 238   DD bb 238   EE aa 113   EE aa 113   EE bb 252
  EE bb 252   EE bb 252   FF aa 208   FF aa 208   FF aa 208   FF aa 208
  FF bb 102   FF bb 102   FF bb 102   FF bb 102   FF bb 102   FF bb 102
  GG aa 148   GG aa 148   GG aa 148   GG aa 148   GG bb 160   GG bb 160
  GG bb 160   GG bb 160   HH aa 480   HH aa 480   HH aa 480   HH bb 133
  HH bb 133   HH bb 133   HH bb 133   HH bb 133   HH bb 133   II aa 398
  II aa 398   II bb 250   II bb 250   II bb 250   II bb 250   II bb 250
  JJ aa 113   JJ aa 113   JJ aa 113   JJ aa 113   JJ bb 257   JJ bb 257
  JJ bb 257   JJ bb 257}

do_execsql_test 1.16.6 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN 0 FOLLOWING         AND 0 FOLLOWING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 3751   AA aa 3774   AA aa 4446   AA aa 4462   AA bb 3815   AA bb 4058
  AA bb 4113   AA bb 4376   BB aa 6578   BB aa 6680   BB aa 6928   BB aa 6941
  BB aa 6947   BB aa 7093   BB bb 6500   BB bb 6548   BB bb 6554   BB bb 6629
  BB bb 6635   BB bb 6707   CC aa 2363   CC aa 2515   CC aa 2692   CC aa 2964
  CC bb 2300   CC bb 2776   DD aa 3187   DD aa 3776   DD aa 3808   DD bb 3073
  DD bb 3238   DD bb 3316   DD bb 3794   EE aa 1762   EE aa 2426   EE bb 1771
  EE bb 1910   EE bb 2287   FF aa 4998   FF aa 5001   FF aa 5050   FF aa 5460
  FF bb 4730   FF bb 4798   FF bb 4942   FF bb 5094   FF bb 5373   FF bb 5566
  GG aa 3834   GG aa 3988   GG aa 4133   GG aa 4320   GG bb 3530   GG bb 3539
  GG bb 3624   GG bb 4308   HH aa 4464   HH aa 4653   HH aa 4963   HH bb 4480
  HH bb 4713   HH bb 4760   HH bb 5088   HH bb 5113   HH bb 5310   II aa 2988
  II aa 3242   II bb 2835   II bb 2969   II bb 3197   II bb 3219   II bb 3390
  JJ aa 2901   JJ aa 3032   JJ aa 3566   JJ aa 3687   JJ bb 2961   JJ bb 3446
  JJ bb 3464   JJ bb 3543}

do_execsql_test 1.16.7 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 0 FOLLOWING         AND 0 FOLLOWING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 1373   AA aa 1396   AA aa 2068   AA aa 2084   AA bb 1508   AA bb 1751
  AA bb 1806   AA bb 2069   BB aa 2111   BB aa 2213   BB aa 2461   BB aa 2474
  BB aa 2480   BB aa 2626   BB bb 3627   BB bb 3675   BB bb 3681   BB bb 3756
  BB bb 3762   BB bb 3834   CC aa 1195   CC aa 1347   CC aa 1524   CC aa 1796
  CC bb 346   CC bb 822   DD aa 480   DD aa 1069   DD aa 1101   DD bb 1748
  DD bb 1913   DD bb 1991   DD bb 2469   EE aa 113   EE aa 777   EE bb 881
  EE bb 1020   EE bb 1397   FF aa 1493   FF aa 1496   FF aa 1545   FF aa 1955
  FF bb 2567   FF bb 2635   FF bb 2779   FF bb 2931   FF bb 3210   FF bb 3403
  GG aa 963   GG aa 1117   GG aa 1262   GG aa 1449   GG bb 1933   GG bb 1942
  GG bb 2027   GG bb 2711   HH aa 1270   HH aa 1459   HH aa 1769   HH bb 2231
  HH bb 2464   HH bb 2511   HH bb 2839   HH bb 2864   HH bb 3061   II aa 398
  II aa 652   II bb 1785   II bb 1919   II bb 2147   II bb 2169   II bb 2340
  JJ aa 1115   JJ aa 1246   JJ aa 1780   JJ aa 1901   JJ bb 947   JJ bb 1432
  JJ bb 1450   JJ bb 1529}

do_execsql_test 1.16.8 {
  SELECT a, b, 
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN 0 FOLLOWING         AND 0 FOLLOWING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN 0 FOLLOWING         AND 0 FOLLOWING ),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 0 FOLLOWING         AND 0 FOLLOWING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 0 FOLLOWING         AND 0 FOLLOWING )
    FROM t3 ORDER BY 1, 2, 3;
} {AA aa 3751 4685 1373 2307   AA aa 3774 4685 1396 2307
  AA aa 4446 4685 2068 2307   AA aa 4462 4685 2084 2307
  AA bb 3815 4685 1508 2378   AA bb 4058 4685 1751 2378
  AA bb 4113 4685 1806 2378   AA bb 4376 4685 2069 2378
  BB aa 6578 7340 2111 2873   BB aa 6680 7340 2213 2873
  BB aa 6928 7340 2461 2873   BB aa 6941 7340 2474 2873
  BB aa 6947 7340 2480 2873   BB aa 7093 7340 2626 2873
  BB bb 6500 7340 3627 4467   BB bb 6548 7340 3675 4467
  BB bb 6554 7340 3681 4467   BB bb 6629 7340 3756 4467
  BB bb 6635 7340 3762 4467   BB bb 6707 7340 3834 4467
  CC aa 2363 3122 1195 1954   CC aa 2515 3122 1347 1954
  CC aa 2692 3122 1524 1954   CC aa 2964 3122 1796 1954
  CC bb 2300 3122 346 1168   CC bb 2776 3122 822 1168
  DD aa 3187 4032 480 1325   DD aa 3776 4032 1069 1325
  DD aa 3808 4032 1101 1325   DD bb 3073 4032 1748 2707
  DD bb 3238 4032 1913 2707   DD bb 3316 4032 1991 2707
  DD bb 3794 4032 2469 2707   EE aa 1762 2539 113 890
  EE aa 2426 2539 777 890   EE bb 1771 2539 881 1649
  EE bb 1910 2539 1020 1649   EE bb 2287 2539 1397 1649
  FF aa 4998 5668 1493 2163   FF aa 5001 5668 1496 2163
  FF aa 5050 5668 1545 2163   FF aa 5460 5668 1955 2163
  FF bb 4730 5668 2567 3505   FF bb 4798 5668 2635 3505
  FF bb 4942 5668 2779 3505   FF bb 5094 5668 2931 3505
  FF bb 5373 5668 3210 3505   FF bb 5566 5668 3403 3505
  GG aa 3834 4468 963 1597   GG aa 3988 4468 1117 1597
  GG aa 4133 4468 1262 1597   GG aa 4320 4468 1449 1597
  GG bb 3530 4468 1933 2871   GG bb 3539 4468 1942 2871
  GG bb 3624 4468 2027 2871   GG bb 4308 4468 2711 2871
  HH aa 4464 5443 1270 2249   HH aa 4653 5443 1459 2249
  HH aa 4963 5443 1769 2249   HH bb 4480 5443 2231 3194
  HH bb 4713 5443 2464 3194   HH bb 4760 5443 2511 3194
  HH bb 5088 5443 2839 3194   HH bb 5113 5443 2864 3194
  HH bb 5310 5443 3061 3194   II aa 2988 3640 398 1050
  II aa 3242 3640 652 1050   II bb 2835 3640 1785 2590
  II bb 2969 3640 1919 2590   II bb 3197 3640 2147 2590
  II bb 3219 3640 2169 2590   II bb 3390 3640 2340 2590
  JJ aa 2901 3800 1115 2014   JJ aa 3032 3800 1246 2014
  JJ aa 3566 3800 1780 2014   JJ aa 3687 3800 1901 2014
  JJ bb 2961 3800 947 1786   JJ bb 3446 3800 1432 1786
  JJ bb 3464 3800 1450 1786   JJ bb 3543 3800 1529 1786}

do_execsql_test 1.17.1 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN 1 FOLLOWING         AND 0 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa {}   AA aa {}   AA aa {}   AA aa {}   AA bb {}   AA bb {}   AA bb {}
  AA bb {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}
  BB bb {}   BB bb {}   BB bb {}   BB bb {}   BB bb {}   BB bb {}   CC aa {}
  CC aa {}   CC aa {}   CC aa {}   CC bb {}   CC bb {}   DD aa {}   DD aa {}
  DD aa {}   DD bb {}   DD bb {}   DD bb {}   DD bb {}   EE aa {}   EE aa {}
  EE bb {}   EE bb {}   EE bb {}   FF aa {}   FF aa {}   FF aa {}   FF aa {}
  FF bb {}   FF bb {}   FF bb {}   FF bb {}   FF bb {}   FF bb {}   GG aa {}
  GG aa {}   GG aa {}   GG aa {}   GG bb {}   GG bb {}   GG bb {}   GG bb {}
  HH aa {}   HH aa {}   HH aa {}   HH bb {}   HH bb {}   HH bb {}   HH bb {}
  HH bb {}   HH bb {}   II aa {}   II aa {}   II bb {}   II bb {}   II bb {}
  II bb {}   II bb {}   JJ aa {}   JJ aa {}   JJ aa {}   JJ aa {}   JJ bb {}
  JJ bb {}   JJ bb {}   JJ bb {}}

do_execsql_test 1.17.2 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 1 FOLLOWING         AND 0 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa {}   AA aa {}   AA aa {}   AA aa {}   AA bb {}   AA bb {}   AA bb {}
  AA bb {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}
  BB bb {}   BB bb {}   BB bb {}   BB bb {}   BB bb {}   BB bb {}   CC aa {}
  CC aa {}   CC aa {}   CC aa {}   CC bb {}   CC bb {}   DD aa {}   DD aa {}
  DD aa {}   DD bb {}   DD bb {}   DD bb {}   DD bb {}   EE aa {}   EE aa {}
  EE bb {}   EE bb {}   EE bb {}   FF aa {}   FF aa {}   FF aa {}   FF aa {}
  FF bb {}   FF bb {}   FF bb {}   FF bb {}   FF bb {}   FF bb {}   GG aa {}
  GG aa {}   GG aa {}   GG aa {}   GG bb {}   GG bb {}   GG bb {}   GG bb {}
  HH aa {}   HH aa {}   HH aa {}   HH bb {}   HH bb {}   HH bb {}   HH bb {}
  HH bb {}   HH bb {}   II aa {}   II aa {}   II bb {}   II bb {}   II bb {}
  II bb {}   II bb {}   JJ aa {}   JJ aa {}   JJ aa {}   JJ aa {}   JJ bb {}
  JJ bb {}   JJ bb {}   JJ bb {}}

do_execsql_test 1.17.3 {
  SELECT a, b, rank() OVER (ORDER BY a  GROUPS BETWEEN 1 FOLLOWING         AND 0 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 1   AA aa 1   AA aa 1   AA aa 1   AA bb 1   AA bb 1   AA bb 1
  AA bb 1   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9
  BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   CC aa 21
  CC aa 21   CC aa 21   CC aa 21   CC bb 21   CC bb 21   DD aa 27   DD aa 27
  DD aa 27   DD bb 27   DD bb 27   DD bb 27   DD bb 27   EE aa 34   EE aa 34
  EE bb 34   EE bb 34   EE bb 34   FF aa 39   FF aa 39   FF aa 39   FF aa 39
  FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   GG aa 49
  GG aa 49   GG aa 49   GG aa 49   GG bb 49   GG bb 49   GG bb 49   GG bb 49
  HH aa 57   HH aa 57   HH aa 57   HH bb 57   HH bb 57   HH bb 57   HH bb 57
  HH bb 57   HH bb 57   II aa 66   II aa 66   II bb 66   II bb 66   II bb 66
  II bb 66   II bb 66   JJ aa 73   JJ aa 73   JJ aa 73   JJ aa 73   JJ bb 73
  JJ bb 73   JJ bb 73   JJ bb 73}

do_execsql_test 1.17.4 {
  SELECT a, b, max(c) OVER (ORDER BY a,b  GROUPS BETWEEN 1 FOLLOWING         AND 0 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa {}   AA aa {}   AA aa {}   AA aa {}   AA bb {}   AA bb {}   AA bb {}
  AA bb {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}
  BB bb {}   BB bb {}   BB bb {}   BB bb {}   BB bb {}   BB bb {}   CC aa {}
  CC aa {}   CC aa {}   CC aa {}   CC bb {}   CC bb {}   DD aa {}   DD aa {}
  DD aa {}   DD bb {}   DD bb {}   DD bb {}   DD bb {}   EE aa {}   EE aa {}
  EE bb {}   EE bb {}   EE bb {}   FF aa {}   FF aa {}   FF aa {}   FF aa {}
  FF bb {}   FF bb {}   FF bb {}   FF bb {}   FF bb {}   FF bb {}   GG aa {}
  GG aa {}   GG aa {}   GG aa {}   GG bb {}   GG bb {}   GG bb {}   GG bb {}
  HH aa {}   HH aa {}   HH aa {}   HH bb {}   HH bb {}   HH bb {}   HH bb {}
  HH bb {}   HH bb {}   II aa {}   II aa {}   II bb {}   II bb {}   II bb {}
  II bb {}   II bb {}   JJ aa {}   JJ aa {}   JJ aa {}   JJ aa {}   JJ bb {}
  JJ bb {}   JJ bb {}   JJ bb {}}

do_execsql_test 1.17.5 {
  SELECT a, b, min(c) OVER (ORDER BY a,b  GROUPS BETWEEN 1 FOLLOWING         AND 0 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa {}   AA aa {}   AA aa {}   AA aa {}   AA bb {}   AA bb {}   AA bb {}
  AA bb {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}
  BB bb {}   BB bb {}   BB bb {}   BB bb {}   BB bb {}   BB bb {}   CC aa {}
  CC aa {}   CC aa {}   CC aa {}   CC bb {}   CC bb {}   DD aa {}   DD aa {}
  DD aa {}   DD bb {}   DD bb {}   DD bb {}   DD bb {}   EE aa {}   EE aa {}
  EE bb {}   EE bb {}   EE bb {}   FF aa {}   FF aa {}   FF aa {}   FF aa {}
  FF bb {}   FF bb {}   FF bb {}   FF bb {}   FF bb {}   FF bb {}   GG aa {}
  GG aa {}   GG aa {}   GG aa {}   GG bb {}   GG bb {}   GG bb {}   GG bb {}
  HH aa {}   HH aa {}   HH aa {}   HH bb {}   HH bb {}   HH bb {}   HH bb {}
  HH bb {}   HH bb {}   II aa {}   II aa {}   II bb {}   II bb {}   II bb {}
  II bb {}   II bb {}   JJ aa {}   JJ aa {}   JJ aa {}   JJ aa {}   JJ bb {}
  JJ bb {}   JJ bb {}   JJ bb {}}

do_execsql_test 1.17.6 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN 1 FOLLOWING         AND 0 FOLLOWING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa {}   AA aa {}   AA aa {}   AA aa {}   AA bb {}   AA bb {}   AA bb {}
  AA bb {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}
  BB bb {}   BB bb {}   BB bb {}   BB bb {}   BB bb {}   BB bb {}   CC aa {}
  CC aa {}   CC aa {}   CC aa {}   CC bb {}   CC bb {}   DD aa {}   DD aa {}
  DD aa {}   DD bb {}   DD bb {}   DD bb {}   DD bb {}   EE aa {}   EE aa {}
  EE bb {}   EE bb {}   EE bb {}   FF aa {}   FF aa {}   FF aa {}   FF aa {}
  FF bb {}   FF bb {}   FF bb {}   FF bb {}   FF bb {}   FF bb {}   GG aa {}
  GG aa {}   GG aa {}   GG aa {}   GG bb {}   GG bb {}   GG bb {}   GG bb {}
  HH aa {}   HH aa {}   HH aa {}   HH bb {}   HH bb {}   HH bb {}   HH bb {}
  HH bb {}   HH bb {}   II aa {}   II aa {}   II bb {}   II bb {}   II bb {}
  II bb {}   II bb {}   JJ aa {}   JJ aa {}   JJ aa {}   JJ aa {}   JJ bb {}
  JJ bb {}   JJ bb {}   JJ bb {}}

do_execsql_test 1.17.7 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 1 FOLLOWING         AND 0 FOLLOWING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa {}   AA aa {}   AA aa {}   AA aa {}   AA bb {}   AA bb {}   AA bb {}
  AA bb {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}   BB aa {}
  BB bb {}   BB bb {}   BB bb {}   BB bb {}   BB bb {}   BB bb {}   CC aa {}
  CC aa {}   CC aa {}   CC aa {}   CC bb {}   CC bb {}   DD aa {}   DD aa {}
  DD aa {}   DD bb {}   DD bb {}   DD bb {}   DD bb {}   EE aa {}   EE aa {}
  EE bb {}   EE bb {}   EE bb {}   FF aa {}   FF aa {}   FF aa {}   FF aa {}
  FF bb {}   FF bb {}   FF bb {}   FF bb {}   FF bb {}   FF bb {}   GG aa {}
  GG aa {}   GG aa {}   GG aa {}   GG bb {}   GG bb {}   GG bb {}   GG bb {}
  HH aa {}   HH aa {}   HH aa {}   HH bb {}   HH bb {}   HH bb {}   HH bb {}
  HH bb {}   HH bb {}   II aa {}   II aa {}   II bb {}   II bb {}   II bb {}
  II bb {}   II bb {}   JJ aa {}   JJ aa {}   JJ aa {}   JJ aa {}   JJ bb {}
  JJ bb {}   JJ bb {}   JJ bb {}}

do_execsql_test 1.17.8 {
  SELECT a, b, 
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN 1 FOLLOWING         AND 0 FOLLOWING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN 1 FOLLOWING         AND 0 FOLLOWING ),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 1 FOLLOWING         AND 0 FOLLOWING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 1 FOLLOWING         AND 0 FOLLOWING )
    FROM t3 ORDER BY 1, 2, 3;
} {AA aa {} {} {} {}   AA aa {} {} {} {}   AA aa {} {} {} {}
  AA aa {} {} {} {}   AA bb {} {} {} {}   AA bb {} {} {} {}
  AA bb {} {} {} {}   AA bb {} {} {} {}   BB aa {} {} {} {}
  BB aa {} {} {} {}   BB aa {} {} {} {}   BB aa {} {} {} {}
  BB aa {} {} {} {}   BB aa {} {} {} {}   BB bb {} {} {} {}
  BB bb {} {} {} {}   BB bb {} {} {} {}   BB bb {} {} {} {}
  BB bb {} {} {} {}   BB bb {} {} {} {}   CC aa {} {} {} {}
  CC aa {} {} {} {}   CC aa {} {} {} {}   CC aa {} {} {} {}
  CC bb {} {} {} {}   CC bb {} {} {} {}   DD aa {} {} {} {}
  DD aa {} {} {} {}   DD aa {} {} {} {}   DD bb {} {} {} {}
  DD bb {} {} {} {}   DD bb {} {} {} {}   DD bb {} {} {} {}
  EE aa {} {} {} {}   EE aa {} {} {} {}   EE bb {} {} {} {}
  EE bb {} {} {} {}   EE bb {} {} {} {}   FF aa {} {} {} {}
  FF aa {} {} {} {}   FF aa {} {} {} {}   FF aa {} {} {} {}
  FF bb {} {} {} {}   FF bb {} {} {} {}   FF bb {} {} {} {}
  FF bb {} {} {} {}   FF bb {} {} {} {}   FF bb {} {} {} {}
  GG aa {} {} {} {}   GG aa {} {} {} {}   GG aa {} {} {} {}
  GG aa {} {} {} {}   GG bb {} {} {} {}   GG bb {} {} {} {}
  GG bb {} {} {} {}   GG bb {} {} {} {}   HH aa {} {} {} {}
  HH aa {} {} {} {}   HH aa {} {} {} {}   HH bb {} {} {} {}
  HH bb {} {} {} {}   HH bb {} {} {} {}   HH bb {} {} {} {}
  HH bb {} {} {} {}   HH bb {} {} {} {}   II aa {} {} {} {}
  II aa {} {} {} {}   II bb {} {} {} {}   II bb {} {} {} {}
  II bb {} {} {} {}   II bb {} {} {} {}   II bb {} {} {} {}
  JJ aa {} {} {} {}   JJ aa {} {} {} {}   JJ aa {} {} {} {}
  JJ aa {} {} {} {}   JJ bb {} {} {} {}   JJ bb {} {} {} {}
  JJ bb {} {} {} {}   JJ bb {} {} {} {}}

do_execsql_test 1.18.1 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN 1 FOLLOWING         AND 5 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 22701   AA aa 22701   AA aa 22701   AA aa 22701   AA bb 22701
  AA bb 22701   AA bb 22701   AA bb 22701   BB aa 19829   BB aa 19829
  BB aa 19829   BB aa 19829   BB aa 19829   BB aa 19829   BB bb 19829
  BB bb 19829   BB bb 19829   BB bb 19829   BB bb 19829   BB bb 19829
  CC aa 22150   CC aa 22150   CC aa 22150   CC aa 22150   CC bb 22150
  CC bb 22150   DD aa 21758   DD aa 21758   DD aa 21758   DD bb 21758
  DD bb 21758   DD bb 21758   DD bb 21758   EE aa 23019   EE aa 23019
  EE bb 23019   EE bb 23019   EE bb 23019   FF aa 17351   FF aa 17351
  FF aa 17351   FF aa 17351   FF bb 17351   FF bb 17351   FF bb 17351
  FF bb 17351   FF bb 17351   FF bb 17351   GG aa 12883   GG aa 12883
  GG aa 12883   GG aa 12883   GG bb 12883   GG bb 12883   GG bb 12883
  GG bb 12883   HH aa 7440   HH aa 7440   HH aa 7440   HH bb 7440
  HH bb 7440   HH bb 7440   HH bb 7440   HH bb 7440   HH bb 7440   II aa 3800
  II aa 3800   II bb 3800   II bb 3800   II bb 3800   II bb 3800   II bb 3800
  JJ aa {}   JJ aa {}   JJ aa {}   JJ aa {}   JJ bb {}   JJ bb {}   JJ bb {}
  JJ bb {}}

do_execsql_test 1.18.2 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 1 FOLLOWING         AND 5 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 12840   AA aa 12840   AA aa 12840   AA aa 12840   AA bb 11787
  AA bb 11787   AA bb 11787   AA bb 11787   BB aa 11621   BB aa 11621
  BB aa 11621   BB aa 11621   BB aa 11621   BB aa 11621   BB bb 8044
  BB bb 8044   BB bb 8044   BB bb 8044   BB bb 8044   BB bb 8044   CC aa 7739
  CC aa 7739   CC aa 7739   CC aa 7739   CC bb 8734   CC bb 8734
  DD aa 10914   DD aa 10914   DD aa 10914   DD bb 9804   DD bb 9804
  DD bb 9804   DD bb 9804   EE aa 11785   EE aa 11785   EE bb 12385
  EE bb 12385   EE bb 12385   FF aa 13416   FF aa 13416   FF aa 13416
  FF aa 13416   FF bb 10961   FF bb 10961   FF bb 10961   FF bb 10961
  FF bb 10961   FF bb 10961   GG aa 11954   GG aa 11954   GG aa 11954
  GG aa 11954   GG bb 11097   GG bb 11097   GG bb 11097   GG bb 11097
  HH aa 10634   HH aa 10634   HH aa 10634   HH bb 7440   HH bb 7440
  HH bb 7440   HH bb 7440   HH bb 7440   HH bb 7440   II aa 6390   II aa 6390
  II bb 3800   II bb 3800   II bb 3800   II bb 3800   II bb 3800   JJ aa 1786
  JJ aa 1786   JJ aa 1786   JJ aa 1786   JJ bb {}   JJ bb {}   JJ bb {}
  JJ bb {}}

do_execsql_test 1.18.3 {
  SELECT a, b, rank() OVER (ORDER BY a  GROUPS BETWEEN 1 FOLLOWING         AND 5 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 1   AA aa 1   AA aa 1   AA aa 1   AA bb 1   AA bb 1   AA bb 1
  AA bb 1   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9
  BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   CC aa 21
  CC aa 21   CC aa 21   CC aa 21   CC bb 21   CC bb 21   DD aa 27   DD aa 27
  DD aa 27   DD bb 27   DD bb 27   DD bb 27   DD bb 27   EE aa 34   EE aa 34
  EE bb 34   EE bb 34   EE bb 34   FF aa 39   FF aa 39   FF aa 39   FF aa 39
  FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   GG aa 49
  GG aa 49   GG aa 49   GG aa 49   GG bb 49   GG bb 49   GG bb 49   GG bb 49
  HH aa 57   HH aa 57   HH aa 57   HH bb 57   HH bb 57   HH bb 57   HH bb 57
  HH bb 57   HH bb 57   II aa 66   II aa 66   II bb 66   II bb 66   II bb 66
  II bb 66   II bb 66   JJ aa 73   JJ aa 73   JJ aa 73   JJ aa 73   JJ bb 73
  JJ bb 73   JJ bb 73   JJ bb 73}

do_execsql_test 1.18.4 {
  SELECT a, b, max(c) OVER (ORDER BY a,b  GROUPS BETWEEN 1 FOLLOWING         AND 5 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 870   AA aa 870   AA aa 870   AA aa 870   AA bb 845   AA bb 845
  AA bb 845   AA bb 845   BB aa 959   BB aa 959   BB aa 959   BB aa 959
  BB aa 959   BB aa 959   BB bb 959   BB bb 959   BB bb 959   BB bb 959
  BB bb 959   BB bb 959   CC aa 959   CC aa 959   CC aa 959   CC aa 959
  CC bb 959   CC bb 959   DD aa 959   DD aa 959   DD aa 959   DD bb 938
  DD bb 938   DD bb 938   DD bb 938   EE aa 938   EE aa 938   EE bb 979
  EE bb 979   EE bb 979   FF aa 979   FF aa 979   FF aa 979   FF aa 979
  FF bb 979   FF bb 979   FF bb 979   FF bb 979   FF bb 979   FF bb 979
  GG aa 979   GG aa 979   GG aa 979   GG aa 979   GG bb 979   GG bb 979
  GG bb 979   GG bb 979   HH aa 963   HH aa 963   HH aa 963   HH bb 899
  HH bb 899   HH bb 899   HH bb 899   HH bb 899   HH bb 899   II aa 899
  II aa 899   II bb 899   II bb 899   II bb 899   II bb 899   II bb 899
  JJ aa 839   JJ aa 839   JJ aa 839   JJ aa 839   JJ bb {}   JJ bb {}
  JJ bb {}   JJ bb {}}

do_execsql_test 1.18.5 {
  SELECT a, b, min(c) OVER (ORDER BY a,b  GROUPS BETWEEN 1 FOLLOWING         AND 5 FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 158   AA aa 158   AA aa 158   AA aa 158   AA bb 158   AA bb 158
  AA bb 158   AA bb 158   BB aa 158   BB aa 158   BB aa 158   BB aa 158
  BB aa 158   BB aa 158   BB bb 113   BB bb 113   BB bb 113   BB bb 113
  BB bb 113   BB bb 113   CC aa 113   CC aa 113   CC aa 113   CC aa 113
  CC bb 113   CC bb 113   DD aa 102   DD aa 102   DD aa 102   DD bb 102
  DD bb 102   DD bb 102   DD bb 102   EE aa 102   EE aa 102   EE bb 102
  EE bb 102   EE bb 102   FF aa 102   FF aa 102   FF aa 102   FF aa 102
  FF bb 133   FF bb 133   FF bb 133   FF bb 133   FF bb 133   FF bb 133
  GG aa 133   GG aa 133   GG aa 133   GG aa 133   GG bb 113   GG bb 113
  GG bb 113   GG bb 113   HH aa 113   HH aa 113   HH aa 113   HH bb 113
  HH bb 113   HH bb 113   HH bb 113   HH bb 113   HH bb 113   II aa 113
  II aa 113   II bb 113   II bb 113   II bb 113   II bb 113   II bb 113
  JJ aa 257   JJ aa 257   JJ aa 257   JJ aa 257   JJ bb {}   JJ bb {}
  JJ bb {}   JJ bb {}}

do_execsql_test 1.18.6 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN 1 FOLLOWING         AND 5 FOLLOWING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 22701   AA aa 22701   AA aa 22701   AA aa 22701   AA bb 22701
  AA bb 22701   AA bb 22701   AA bb 22701   BB aa 19829   BB aa 19829
  BB aa 19829   BB aa 19829   BB aa 19829   BB aa 19829   BB bb 19829
  BB bb 19829   BB bb 19829   BB bb 19829   BB bb 19829   BB bb 19829
  CC aa 22150   CC aa 22150   CC aa 22150   CC aa 22150   CC bb 22150
  CC bb 22150   DD aa 21758   DD aa 21758   DD aa 21758   DD bb 21758
  DD bb 21758   DD bb 21758   DD bb 21758   EE aa 23019   EE aa 23019
  EE bb 23019   EE bb 23019   EE bb 23019   FF aa 17351   FF aa 17351
  FF aa 17351   FF aa 17351   FF bb 17351   FF bb 17351   FF bb 17351
  FF bb 17351   FF bb 17351   FF bb 17351   GG aa 12883   GG aa 12883
  GG aa 12883   GG aa 12883   GG bb 12883   GG bb 12883   GG bb 12883
  GG bb 12883   HH aa 7440   HH aa 7440   HH aa 7440   HH bb 7440
  HH bb 7440   HH bb 7440   HH bb 7440   HH bb 7440   HH bb 7440   II aa 3800
  II aa 3800   II bb 3800   II bb 3800   II bb 3800   II bb 3800   II bb 3800
  JJ aa {}   JJ aa {}   JJ aa {}   JJ aa {}   JJ bb {}   JJ bb {}   JJ bb {}
  JJ bb {}}

do_execsql_test 1.18.7 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 1 FOLLOWING         AND 5 FOLLOWING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 12840   AA aa 12840   AA aa 12840   AA aa 12840   AA bb 11787
  AA bb 11787   AA bb 11787   AA bb 11787   BB aa 11621   BB aa 11621
  BB aa 11621   BB aa 11621   BB aa 11621   BB aa 11621   BB bb 8044
  BB bb 8044   BB bb 8044   BB bb 8044   BB bb 8044   BB bb 8044   CC aa 7739
  CC aa 7739   CC aa 7739   CC aa 7739   CC bb 8734   CC bb 8734
  DD aa 10914   DD aa 10914   DD aa 10914   DD bb 9804   DD bb 9804
  DD bb 9804   DD bb 9804   EE aa 11785   EE aa 11785   EE bb 12385
  EE bb 12385   EE bb 12385   FF aa 13416   FF aa 13416   FF aa 13416
  FF aa 13416   FF bb 10961   FF bb 10961   FF bb 10961   FF bb 10961
  FF bb 10961   FF bb 10961   GG aa 11954   GG aa 11954   GG aa 11954
  GG aa 11954   GG bb 11097   GG bb 11097   GG bb 11097   GG bb 11097
  HH aa 10634   HH aa 10634   HH aa 10634   HH bb 7440   HH bb 7440
  HH bb 7440   HH bb 7440   HH bb 7440   HH bb 7440   II aa 6390   II aa 6390
  II bb 3800   II bb 3800   II bb 3800   II bb 3800   II bb 3800   JJ aa 1786
  JJ aa 1786   JJ aa 1786   JJ aa 1786   JJ bb {}   JJ bb {}   JJ bb {}
  JJ bb {}}

do_execsql_test 1.18.8 {
  SELECT a, b, 
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN 1 FOLLOWING         AND 5 FOLLOWING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN 1 FOLLOWING         AND 5 FOLLOWING ),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 1 FOLLOWING         AND 5 FOLLOWING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 1 FOLLOWING         AND 5 FOLLOWING )
    FROM t3 ORDER BY 1, 2, 3;
} {AA aa 22701 22701 12840 12840   AA aa 22701 22701 12840 12840
  AA aa 22701 22701 12840 12840   AA aa 22701 22701 12840 12840
  AA bb 22701 22701 11787 11787   AA bb 22701 22701 11787 11787
  AA bb 22701 22701 11787 11787   AA bb 22701 22701 11787 11787
  BB aa 19829 19829 11621 11621   BB aa 19829 19829 11621 11621
  BB aa 19829 19829 11621 11621   BB aa 19829 19829 11621 11621
  BB aa 19829 19829 11621 11621   BB aa 19829 19829 11621 11621
  BB bb 19829 19829 8044 8044   BB bb 19829 19829 8044 8044
  BB bb 19829 19829 8044 8044   BB bb 19829 19829 8044 8044
  BB bb 19829 19829 8044 8044   BB bb 19829 19829 8044 8044
  CC aa 22150 22150 7739 7739   CC aa 22150 22150 7739 7739
  CC aa 22150 22150 7739 7739   CC aa 22150 22150 7739 7739
  CC bb 22150 22150 8734 8734   CC bb 22150 22150 8734 8734
  DD aa 21758 21758 10914 10914   DD aa 21758 21758 10914 10914
  DD aa 21758 21758 10914 10914   DD bb 21758 21758 9804 9804
  DD bb 21758 21758 9804 9804   DD bb 21758 21758 9804 9804
  DD bb 21758 21758 9804 9804   EE aa 23019 23019 11785 11785
  EE aa 23019 23019 11785 11785   EE bb 23019 23019 12385 12385
  EE bb 23019 23019 12385 12385   EE bb 23019 23019 12385 12385
  FF aa 17351 17351 13416 13416   FF aa 17351 17351 13416 13416
  FF aa 17351 17351 13416 13416   FF aa 17351 17351 13416 13416
  FF bb 17351 17351 10961 10961   FF bb 17351 17351 10961 10961
  FF bb 17351 17351 10961 10961   FF bb 17351 17351 10961 10961
  FF bb 17351 17351 10961 10961   FF bb 17351 17351 10961 10961
  GG aa 12883 12883 11954 11954   GG aa 12883 12883 11954 11954
  GG aa 12883 12883 11954 11954   GG aa 12883 12883 11954 11954
  GG bb 12883 12883 11097 11097   GG bb 12883 12883 11097 11097
  GG bb 12883 12883 11097 11097   GG bb 12883 12883 11097 11097
  HH aa 7440 7440 10634 10634   HH aa 7440 7440 10634 10634
  HH aa 7440 7440 10634 10634   HH bb 7440 7440 7440 7440
  HH bb 7440 7440 7440 7440   HH bb 7440 7440 7440 7440
  HH bb 7440 7440 7440 7440   HH bb 7440 7440 7440 7440
  HH bb 7440 7440 7440 7440   II aa 3800 3800 6390 6390
  II aa 3800 3800 6390 6390   II bb 3800 3800 3800 3800
  II bb 3800 3800 3800 3800   II bb 3800 3800 3800 3800
  II bb 3800 3800 3800 3800   II bb 3800 3800 3800 3800
  JJ aa {} {} 1786 1786   JJ aa {} {} 1786 1786   JJ aa {} {} 1786 1786
  JJ aa {} {} 1786 1786   JJ bb {} {} {} {}   JJ bb {} {} {} {}
  JJ bb {} {} {} {}   JJ bb {} {} {} {}}

do_execsql_test 1.19.1 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN 1 FOLLOWING         AND UNBOUNDED FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 40052   AA aa 40052   AA aa 40052   AA aa 40052   AA bb 40052
  AA bb 40052   AA bb 40052   AA bb 40052   BB aa 32712   BB aa 32712
  BB aa 32712   BB aa 32712   BB aa 32712   BB aa 32712   BB bb 32712
  BB bb 32712   BB bb 32712   BB bb 32712   BB bb 32712   BB bb 32712
  CC aa 29590   CC aa 29590   CC aa 29590   CC aa 29590   CC bb 29590
  CC bb 29590   DD aa 25558   DD aa 25558   DD aa 25558   DD bb 25558
  DD bb 25558   DD bb 25558   DD bb 25558   EE aa 23019   EE aa 23019
  EE bb 23019   EE bb 23019   EE bb 23019   FF aa 17351   FF aa 17351
  FF aa 17351   FF aa 17351   FF bb 17351   FF bb 17351   FF bb 17351
  FF bb 17351   FF bb 17351   FF bb 17351   GG aa 12883   GG aa 12883
  GG aa 12883   GG aa 12883   GG bb 12883   GG bb 12883   GG bb 12883
  GG bb 12883   HH aa 7440   HH aa 7440   HH aa 7440   HH bb 7440
  HH bb 7440   HH bb 7440   HH bb 7440   HH bb 7440   HH bb 7440   II aa 3800
  II aa 3800   II bb 3800   II bb 3800   II bb 3800   II bb 3800   II bb 3800
  JJ aa {}   JJ aa {}   JJ aa {}   JJ aa {}   JJ bb {}   JJ bb {}   JJ bb {}
  JJ bb {}}

do_execsql_test 1.19.2 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 1 FOLLOWING         AND UNBOUNDED FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 42430   AA aa 42430   AA aa 42430   AA aa 42430   AA bb 40052
  AA bb 40052   AA bb 40052   AA bb 40052   BB aa 37179   BB aa 37179
  BB aa 37179   BB aa 37179   BB aa 37179   BB aa 37179   BB bb 32712
  BB bb 32712   BB bb 32712   BB bb 32712   BB bb 32712   BB bb 32712
  CC aa 30758   CC aa 30758   CC aa 30758   CC aa 30758   CC bb 29590
  CC bb 29590   DD aa 28265   DD aa 28265   DD aa 28265   DD bb 25558
  DD bb 25558   DD bb 25558   DD bb 25558   EE aa 24668   EE aa 24668
  EE bb 23019   EE bb 23019   EE bb 23019   FF aa 20856   FF aa 20856
  FF aa 20856   FF aa 20856   FF bb 17351   FF bb 17351   FF bb 17351
  FF bb 17351   FF bb 17351   FF bb 17351   GG aa 15754   GG aa 15754
  GG aa 15754   GG aa 15754   GG bb 12883   GG bb 12883   GG bb 12883
  GG bb 12883   HH aa 10634   HH aa 10634   HH aa 10634   HH bb 7440
  HH bb 7440   HH bb 7440   HH bb 7440   HH bb 7440   HH bb 7440   II aa 6390
  II aa 6390   II bb 3800   II bb 3800   II bb 3800   II bb 3800   II bb 3800
  JJ aa 1786   JJ aa 1786   JJ aa 1786   JJ aa 1786   JJ bb {}   JJ bb {}
  JJ bb {}   JJ bb {}}

do_execsql_test 1.19.3 {
  SELECT a, b, rank() OVER (ORDER BY a  GROUPS BETWEEN 1 FOLLOWING         AND UNBOUNDED FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 1   AA aa 1   AA aa 1   AA aa 1   AA bb 1   AA bb 1   AA bb 1
  AA bb 1   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9   BB aa 9
  BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   BB bb 9   CC aa 21
  CC aa 21   CC aa 21   CC aa 21   CC bb 21   CC bb 21   DD aa 27   DD aa 27
  DD aa 27   DD bb 27   DD bb 27   DD bb 27   DD bb 27   EE aa 34   EE aa 34
  EE bb 34   EE bb 34   EE bb 34   FF aa 39   FF aa 39   FF aa 39   FF aa 39
  FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   FF bb 39   GG aa 49
  GG aa 49   GG aa 49   GG aa 49   GG bb 49   GG bb 49   GG bb 49   GG bb 49
  HH aa 57   HH aa 57   HH aa 57   HH bb 57   HH bb 57   HH bb 57   HH bb 57
  HH bb 57   HH bb 57   II aa 66   II aa 66   II bb 66   II bb 66   II bb 66
  II bb 66   II bb 66   JJ aa 73   JJ aa 73   JJ aa 73   JJ aa 73   JJ bb 73
  JJ bb 73   JJ bb 73   JJ bb 73}

do_execsql_test 1.19.4 {
  SELECT a, b, max(c) OVER (ORDER BY a,b  GROUPS BETWEEN 1 FOLLOWING         AND UNBOUNDED FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 979   AA aa 979   AA aa 979   AA aa 979   AA bb 979   AA bb 979
  AA bb 979   AA bb 979   BB aa 979   BB aa 979   BB aa 979   BB aa 979
  BB aa 979   BB aa 979   BB bb 979   BB bb 979   BB bb 979   BB bb 979
  BB bb 979   BB bb 979   CC aa 979   CC aa 979   CC aa 979   CC aa 979
  CC bb 979   CC bb 979   DD aa 979   DD aa 979   DD aa 979   DD bb 979
  DD bb 979   DD bb 979   DD bb 979   EE aa 979   EE aa 979   EE bb 979
  EE bb 979   EE bb 979   FF aa 979   FF aa 979   FF aa 979   FF aa 979
  FF bb 979   FF bb 979   FF bb 979   FF bb 979   FF bb 979   FF bb 979
  GG aa 979   GG aa 979   GG aa 979   GG aa 979   GG bb 979   GG bb 979
  GG bb 979   GG bb 979   HH aa 963   HH aa 963   HH aa 963   HH bb 899
  HH bb 899   HH bb 899   HH bb 899   HH bb 899   HH bb 899   II aa 899
  II aa 899   II bb 899   II bb 899   II bb 899   II bb 899   II bb 899
  JJ aa 839   JJ aa 839   JJ aa 839   JJ aa 839   JJ bb {}   JJ bb {}
  JJ bb {}   JJ bb {}}

do_execsql_test 1.19.5 {
  SELECT a, b, min(c) OVER (ORDER BY a,b  GROUPS BETWEEN 1 FOLLOWING         AND UNBOUNDED FOLLOWING ) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 102   AA aa 102   AA aa 102   AA aa 102   AA bb 102   AA bb 102
  AA bb 102   AA bb 102   BB aa 102   BB aa 102   BB aa 102   BB aa 102
  BB aa 102   BB aa 102   BB bb 102   BB bb 102   BB bb 102   BB bb 102
  BB bb 102   BB bb 102   CC aa 102   CC aa 102   CC aa 102   CC aa 102
  CC bb 102   CC bb 102   DD aa 102   DD aa 102   DD aa 102   DD bb 102
  DD bb 102   DD bb 102   DD bb 102   EE aa 102   EE aa 102   EE bb 102
  EE bb 102   EE bb 102   FF aa 102   FF aa 102   FF aa 102   FF aa 102
  FF bb 113   FF bb 113   FF bb 113   FF bb 113   FF bb 113   FF bb 113
  GG aa 113   GG aa 113   GG aa 113   GG aa 113   GG bb 113   GG bb 113
  GG bb 113   GG bb 113   HH aa 113   HH aa 113   HH aa 113   HH bb 113
  HH bb 113   HH bb 113   HH bb 113   HH bb 113   HH bb 113   II aa 113
  II aa 113   II bb 113   II bb 113   II bb 113   II bb 113   II bb 113
  JJ aa 257   JJ aa 257   JJ aa 257   JJ aa 257   JJ bb {}   JJ bb {}
  JJ bb {}   JJ bb {}}

do_execsql_test 1.19.6 {
  SELECT a, b, sum(c) OVER (ORDER BY a  GROUPS BETWEEN 1 FOLLOWING         AND UNBOUNDED FOLLOWING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 40052   AA aa 40052   AA aa 40052   AA aa 40052   AA bb 40052
  AA bb 40052   AA bb 40052   AA bb 40052   BB aa 32712   BB aa 32712
  BB aa 32712   BB aa 32712   BB aa 32712   BB aa 32712   BB bb 32712
  BB bb 32712   BB bb 32712   BB bb 32712   BB bb 32712   BB bb 32712
  CC aa 29590   CC aa 29590   CC aa 29590   CC aa 29590   CC bb 29590
  CC bb 29590   DD aa 25558   DD aa 25558   DD aa 25558   DD bb 25558
  DD bb 25558   DD bb 25558   DD bb 25558   EE aa 23019   EE aa 23019
  EE bb 23019   EE bb 23019   EE bb 23019   FF aa 17351   FF aa 17351
  FF aa 17351   FF aa 17351   FF bb 17351   FF bb 17351   FF bb 17351
  FF bb 17351   FF bb 17351   FF bb 17351   GG aa 12883   GG aa 12883
  GG aa 12883   GG aa 12883   GG bb 12883   GG bb 12883   GG bb 12883
  GG bb 12883   HH aa 7440   HH aa 7440   HH aa 7440   HH bb 7440
  HH bb 7440   HH bb 7440   HH bb 7440   HH bb 7440   HH bb 7440   II aa 3800
  II aa 3800   II bb 3800   II bb 3800   II bb 3800   II bb 3800   II bb 3800
  JJ aa {}   JJ aa {}   JJ aa {}   JJ aa {}   JJ bb {}   JJ bb {}   JJ bb {}
  JJ bb {}}

do_execsql_test 1.19.7 {
  SELECT a, b, sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 1 FOLLOWING         AND UNBOUNDED FOLLOWING  EXCLUDE CURRENT ROW) FROM t3 ORDER BY 1, 2, 3;
} {AA aa 42430   AA aa 42430   AA aa 42430   AA aa 42430   AA bb 40052
  AA bb 40052   AA bb 40052   AA bb 40052   BB aa 37179   BB aa 37179
  BB aa 37179   BB aa 37179   BB aa 37179   BB aa 37179   BB bb 32712
  BB bb 32712   BB bb 32712   BB bb 32712   BB bb 32712   BB bb 32712
  CC aa 30758   CC aa 30758   CC aa 30758   CC aa 30758   CC bb 29590
  CC bb 29590   DD aa 28265   DD aa 28265   DD aa 28265   DD bb 25558
  DD bb 25558   DD bb 25558   DD bb 25558   EE aa 24668   EE aa 24668
  EE bb 23019   EE bb 23019   EE bb 23019   FF aa 20856   FF aa 20856
  FF aa 20856   FF aa 20856   FF bb 17351   FF bb 17351   FF bb 17351
  FF bb 17351   FF bb 17351   FF bb 17351   GG aa 15754   GG aa 15754
  GG aa 15754   GG aa 15754   GG bb 12883   GG bb 12883   GG bb 12883
  GG bb 12883   HH aa 10634   HH aa 10634   HH aa 10634   HH bb 7440
  HH bb 7440   HH bb 7440   HH bb 7440   HH bb 7440   HH bb 7440   II aa 6390
  II aa 6390   II bb 3800   II bb 3800   II bb 3800   II bb 3800   II bb 3800
  JJ aa 1786   JJ aa 1786   JJ aa 1786   JJ aa 1786   JJ bb {}   JJ bb {}
  JJ bb {}   JJ bb {}}

do_execsql_test 1.19.8 {
  SELECT a, b, 
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN 1 FOLLOWING         AND UNBOUNDED FOLLOWING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a  GROUPS BETWEEN 1 FOLLOWING         AND UNBOUNDED FOLLOWING ),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 1 FOLLOWING         AND UNBOUNDED FOLLOWING  EXCLUDE CURRENT ROW),
      sum(c) OVER (ORDER BY a,b  GROUPS BETWEEN 1 FOLLOWING         AND UNBOUNDED FOLLOWING )
    FROM t3 ORDER BY 1, 2, 3;
} {AA aa 40052 40052 42430 42430   AA aa 40052 40052 42430 42430
  AA aa 40052 40052 42430 42430   AA aa 40052 40052 42430 42430
  AA bb 40052 40052 40052 40052   AA bb 40052 40052 40052 40052
  AA bb 40052 40052 40052 40052   AA bb 40052 40052 40052 40052
  BB aa 32712 32712 37179 37179   BB aa 32712 32712 37179 37179
  BB aa 32712 32712 37179 37179   BB aa 32712 32712 37179 37179
  BB aa 32712 32712 37179 37179   BB aa 32712 32712 37179 37179
  BB bb 32712 32712 32712 32712   BB bb 32712 32712 32712 32712
  BB bb 32712 32712 32712 32712   BB bb 32712 32712 32712 32712
  BB bb 32712 32712 32712 32712   BB bb 32712 32712 32712 32712
  CC aa 29590 29590 30758 30758   CC aa 29590 29590 30758 30758
  CC aa 29590 29590 30758 30758   CC aa 29590 29590 30758 30758
  CC bb 29590 29590 29590 29590   CC bb 29590 29590 29590 29590
  DD aa 25558 25558 28265 28265   DD aa 25558 25558 28265 28265
  DD aa 25558 25558 28265 28265   DD bb 25558 25558 25558 25558
  DD bb 25558 25558 25558 25558   DD bb 25558 25558 25558 25558
  DD bb 25558 25558 25558 25558   EE aa 23019 23019 24668 24668
  EE aa 23019 23019 24668 24668   EE bb 23019 23019 23019 23019
  EE bb 23019 23019 23019 23019   EE bb 23019 23019 23019 23019
  FF aa 17351 17351 20856 20856   FF aa 17351 17351 20856 20856
  FF aa 17351 17351 20856 20856   FF aa 17351 17351 20856 20856
  FF bb 17351 17351 17351 17351   FF bb 17351 17351 17351 17351
  FF bb 17351 17351 17351 17351   FF bb 17351 17351 17351 17351
  FF bb 17351 17351 17351 17351   FF bb 17351 17351 17351 17351
  GG aa 12883 12883 15754 15754   GG aa 12883 12883 15754 15754
  GG aa 12883 12883 15754 15754   GG aa 12883 12883 15754 15754
  GG bb 12883 12883 12883 12883   GG bb 12883 12883 12883 12883
  GG bb 12883 12883 12883 12883   GG bb 12883 12883 12883 12883
  HH aa 7440 7440 10634 10634   HH aa 7440 7440 10634 10634
  HH aa 7440 7440 10634 10634   HH bb 7440 7440 7440 7440
  HH bb 7440 7440 7440 7440   HH bb 7440 7440 7440 7440
  HH bb 7440 7440 7440 7440   HH bb 7440 7440 7440 7440
  HH bb 7440 7440 7440 7440   II aa 3800 3800 6390 6390
  II aa 3800 3800 6390 6390   II bb 3800 3800 3800 3800
  II bb 3800 3800 3800 3800   II bb 3800 3800 3800 3800
  II bb 3800 3800 3800 3800   II bb 3800 3800 3800 3800
  JJ aa {} {} 1786 1786   JJ aa {} {} 1786 1786   JJ aa {} {} 1786 1786
  JJ aa {} {} 1786 1786   JJ bb {} {} {} {}   JJ bb {} {} {} {}
  JJ bb {} {} {} {}   JJ bb {} {} {} {}}

do_execsql_test 2.1.1 {
  SELECT row_number() OVER win 
    FROM t3
    WINDOW win AS (
      ORDER BY c, b, a
      ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING  EXCLUDE NO OTHERS 
    )
} {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}

do_execsql_test 2.1.2 {
  SELECT nth_value(c, 14) OVER win 
    FROM t3
    WINDOW win AS (
      ORDER BY c, b, a
      ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING  EXCLUDE NO OTHERS 
    )
} {247   247   247   247   247   247   247   247   247   247   247   247   247
  247   247   247   247   247   247   247   247   247   247   247   247   247
  247   247   247   247   247   247   247   247   247   247   247   247   247
  247   247   247   247   247   247   247   247   247   247   247   247   247
  247   247   247   247   247   247   247   247   247   247   247   247   247
  247   247   247   247   247   247   247   247   247   247   247   247   247
  247   247}

do_execsql_test 2.1.3 {
  SELECT min(c) OVER win, max(c) OVER win, sum(c) OVER win FROM t3
    WINDOW win AS (
      ORDER BY c, b, a
      ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW  EXCLUDE NO OTHERS 
    ) ORDER BY a, b, c;
} {102 223 1358   102 239 2293   102 911 38097   102 934 39960   102 309 4159
  102 572 10643   102 627 13069   102 870 35417   102 247 2540   102 393 6608
  102 399 7405   102 412 7817   102 660 16277   102 762 24077   102 633 14331
  102 705 19673   102 711 20384   102 786 27176   102 792 28758
  102 840 32858   102 158 767   102 430 8668   102 607 11824   102 759 23315
  102 346 5506   102 822 31179   102 224 1582   102 256 3298   102 845 34547
  102 238 2054   102 716 21100   102 794 29552   102 959 42795   102 113 215
  102 777 26390   102 252 3042   102 629 13698   102 768 25613   102 208 1135
  102 618 12442   102 667 16944   102 670 17614   102 102 102   102 295 3850
  102 574 11217   102 726 21826   102 870 36287   102 938 40898   102 148 609
  102 335 4824   102 480 9591   102 634 14965   102 160 927   102 844 33702
  102 929 39026   102 938 41836   102 480 10071   102 790 27966
  102 979 44737   102 133 461   102 330 4489   102 355 6215   102 683 18968
  102 730 22556   102 963 43758   102 398 7006   102 652 15617   102 250 2790
  102 421 8238   102 443 9111   102 671 18285   102 805 30357   102 113 328
  102 234 1816   102 768 24845   102 899 37186   102 257 3555   102 336 5160
  102 354 5860   102 839 32018}

do_execsql_test 2.2.1 {
  SELECT row_number() OVER win 
    FROM t3
    WINDOW win AS (
      ORDER BY c, b, a
      ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING  EXCLUDE CURRENT ROW 
    )
} {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}

do_execsql_test 2.2.2 {
  SELECT nth_value(c, 14) OVER win 
    FROM t3
    WINDOW win AS (
      ORDER BY c, b, a
      ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING  EXCLUDE CURRENT ROW 
    )
} {250   250   250   250   250   250   250   250   250   250   250   250   250
  250   247   247   247   247   247   247   247   247   247   247   247   247
  247   247   247   247   247   247   247   247   247   247   247   247   247
  247   247   247   247   247   247   247   247   247   247   247   247   247
  247   247   247   247   247   247   247   247   247   247   247   247   247
  247   247   247   247   247   247   247   247   247   247   247   247   247
  247   247}

do_execsql_test 2.2.3 {
  SELECT min(c) OVER win, max(c) OVER win, sum(c) OVER win FROM t3
    WINDOW win AS (
      ORDER BY c, b, a
      ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW  EXCLUDE CURRENT ROW 
    ) ORDER BY a, b, c;
} {102 208 1135   102 238 2054   102 899 37186   102 929 39026   102 295 3850
  102 480 10071   102 618 12442   102 845 34547   102 239 2293   102 355 6215
  102 398 7006   102 399 7405   102 652 15617   102 759 23315   102 629 13698
  102 683 18968   102 705 19673   102 777 26390   102 790 27966
  102 839 32018   102 148 609   102 421 8238   102 574 11217   102 730 22556
  102 336 5160   102 805 30357   102 223 1358   102 252 3042   102 844 33702
  102 234 1816   102 711 20384   102 792 28758   102 938 41836   102 102 102
  102 768 25613   102 250 2790   102 627 13069   102 768 24845   102 160 927
  102 607 11824   102 660 16277   102 667 16944   {} {} {}   102 257 3555
  102 572 10643   102 716 21100   102 870 35417   102 934 39960   102 133 461
  102 330 4489   102 443 9111   102 633 14331   102 158 767   102 840 32858
  102 911 38097   102 938 40898   102 480 9591   102 786 27176
  102 963 43758   102 113 328   102 309 4159   102 354 5860   102 671 18285
  102 726 21826   102 959 42795   102 393 6608   102 634 14965   102 247 2540
  102 412 7817   102 430 8668   102 670 17614   102 794 29552   102 113 215
  102 224 1582   102 762 24077   102 870 36287   102 256 3298   102 335 4824
  102 346 5506   102 822 31179}

do_execsql_test 2.3.1 {
  SELECT row_number() OVER win 
    FROM t3
    WINDOW win AS (
      ORDER BY c, b, a
      ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING  EXCLUDE GROUP 
    )
} {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}

do_execsql_test 2.3.2 {
  SELECT nth_value(c, 14) OVER win 
    FROM t3
    WINDOW win AS (
      ORDER BY c, b, a
      ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING  EXCLUDE GROUP 
    )
} {250   250   250   250   250   250   250   250   250   250   250   250   250
  250   247   247   247   247   247   247   247   247   247   247   247   247
  247   247   247   247   247   247   247   247   247   247   247   247   247
  247   247   247   247   247   247   247   247   247   247   247   247   247
  247   247   247   247   247   247   247   247   247   247   247   247   247
  247   247   247   247   247   247   247   247   247   247   247   247   247
  247   247}

do_execsql_test 2.3.3 {
  SELECT min(c) OVER win, max(c) OVER win, sum(c) OVER win FROM t3
    WINDOW win AS (
      ORDER BY c, b, a
      ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW  EXCLUDE GROUP 
    ) ORDER BY a, b, c;
} {102 208 1135   102 238 2054   102 899 37186   102 929 39026   102 295 3850
  102 480 10071   102 618 12442   102 845 34547   102 239 2293   102 355 6215
  102 398 7006   102 399 7405   102 652 15617   102 759 23315   102 629 13698
  102 683 18968   102 705 19673   102 777 26390   102 790 27966
  102 839 32018   102 148 609   102 421 8238   102 574 11217   102 730 22556
  102 336 5160   102 805 30357   102 223 1358   102 252 3042   102 844 33702
  102 234 1816   102 711 20384   102 792 28758   102 938 41836   102 102 102
  102 768 25613   102 250 2790   102 627 13069   102 768 24845   102 160 927
  102 607 11824   102 660 16277   102 667 16944   {} {} {}   102 257 3555
  102 572 10643   102 716 21100   102 870 35417   102 934 39960   102 133 461
  102 330 4489   102 443 9111   102 633 14331   102 158 767   102 840 32858
  102 911 38097   102 938 40898   102 480 9591   102 786 27176
  102 963 43758   102 113 328   102 309 4159   102 354 5860   102 671 18285
  102 726 21826   102 959 42795   102 393 6608   102 634 14965   102 247 2540
  102 412 7817   102 430 8668   102 670 17614   102 794 29552   102 113 215
  102 224 1582   102 762 24077   102 870 36287   102 256 3298   102 335 4824
  102 346 5506   102 822 31179}

do_execsql_test 2.4.1 {
  SELECT row_number() OVER win 
    FROM t3
    WINDOW win AS (
      ORDER BY c, b, a
      ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING  EXCLUDE TIES 
    )
} {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}

do_execsql_test 2.4.2 {
  SELECT nth_value(c, 14) OVER win 
    FROM t3
    WINDOW win AS (
      ORDER BY c, b, a
      ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING  EXCLUDE TIES 
    )
} {247   247   247   247   247   247   247   247   247   247   247   247   247
  247   247   247   247   247   247   247   247   247   247   247   247   247
  247   247   247   247   247   247   247   247   247   247   247   247   247
  247   247   247   247   247   247   247   247   247   247   247   247   247
  247   247   247   247   247   247   247   247   247   247   247   247   247
  247   247   247   247   247   247   247   247   247   247   247   247   247
  247   247}

do_execsql_test 2.4.3 {
  SELECT min(c) OVER win, max(c) OVER win, sum(c) OVER win FROM t3
    WINDOW win AS (
      ORDER BY c, b, a
      ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW  EXCLUDE TIES 
    ) ORDER BY a, b, c;
} {102 223 1358   102 239 2293   102 911 38097   102 934 39960   102 309 4159
  102 572 10643   102 627 13069   102 870 35417   102 247 2540   102 393 6608
  102 399 7405   102 412 7817   102 660 16277   102 762 24077   102 633 14331
  102 705 19673   102 711 20384   102 786 27176   102 792 28758
  102 840 32858   102 158 767   102 430 8668   102 607 11824   102 759 23315
  102 346 5506   102 822 31179   102 224 1582   102 256 3298   102 845 34547
  102 238 2054   102 716 21100   102 794 29552   102 959 42795   102 113 215
  102 777 26390   102 252 3042   102 629 13698   102 768 25613   102 208 1135
  102 618 12442   102 667 16944   102 670 17614   102 102 102   102 295 3850
  102 574 11217   102 726 21826   102 870 36287   102 938 40898   102 148 609
  102 335 4824   102 480 9591   102 634 14965   102 160 927   102 844 33702
  102 929 39026   102 938 41836   102 480 10071   102 790 27966
  102 979 44737   102 133 461   102 330 4489   102 355 6215   102 683 18968
  102 730 22556   102 963 43758   102 398 7006   102 652 15617   102 250 2790
  102 421 8238   102 443 9111   102 671 18285   102 805 30357   102 113 328
  102 234 1816   102 768 24845   102 899 37186   102 257 3555   102 336 5160
  102 354 5860   102 839 32018}

#==========================================================================

do_execsql_test 3.0 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a REAL, b INTEGER);
  INSERT INTO t1 VALUES
      (5, 10), (10, 20), (13, 26), (13, 26), 
      (15, 30), (20, 40), (22,80), (30, 90);
} {}

do_execsql_test 3.1 {
  SELECT CAST(a AS INTEGER), sum(b) OVER win FROM t1 WINDOW win AS ( ORDER BY a RANGE BETWEEN 5 PRECEDING AND 5 FOLLOWING )
} {5 30   10 112   13 102   13 102   15 142   20 150   22 120   30 90}

do_execsql_test 3.2 {
  SELECT CAST(a AS INTEGER), sum(b) OVER win FROM t1 WINDOW win AS ( ORDER BY a RANGE BETWEEN 10 PRECEDING AND 5 PRECEDING )
} {5 {}   10 10   13 10   13 10   15 30   20 102   22 82   30 120}

do_execsql_test 3.3 {
  SELECT CAST(a AS INTEGER), sum(b) OVER win FROM t1 WINDOW win AS ( ORDER BY a RANGE BETWEEN 2 FOLLOWING AND 3 FOLLOWING )
} {5 {}   10 52   13 30   13 30   15 {}   20 80   22 {}   30 {}}

do_execsql_test 3.4 {
  SELECT CAST(a AS INTEGER), sum(b) OVER win FROM t1 WINDOW win AS ( ORDER BY a DESC RANGE BETWEEN 5 PRECEDING AND 5 FOLLOWING )
} {30 90   22 120   20 150   15 142   13 102   13 102   10 112   5 30}

do_execsql_test 3.5 {
  SELECT CAST(a AS INTEGER), sum(b) OVER win FROM t1 WINDOW win AS ( ORDER BY a DESC RANGE BETWEEN 10 PRECEDING AND 5 PRECEDING )
} {30 {}   22 90   20 90   15 120   13 120   13 120   10 70   5 102}

do_execsql_test 3.6 {
  SELECT CAST(a AS INTEGER), sum(b) OVER win FROM t1 WINDOW win AS ( ORDER BY a DESC RANGE BETWEEN 2 FOLLOWING AND 3 FOLLOWING )
} {30 {}   22 40   20 {}   15 52   13 20   13 20   10 {}   5 {}}

do_execsql_test 3.7 {
  SELECT CAST(a AS INTEGER), sum(b) OVER win FROM t1 WINDOW win AS ( ORDER BY a RANGE BETWEEN 5.1 PRECEDING AND 5.3 FOLLOWING )
} {5 30   10 112   13 102   13 102   15 142   20 150   22 120   30 90}

do_execsql_test 3.8 {
  SELECT CAST(a AS INTEGER), sum(b) OVER win FROM t1 WINDOW win AS ( ORDER BY a RANGE BETWEEN 10.2 PRECEDING AND 5.4 PRECEDING )
} {5 {}   10 {}   13 10   13 10   15 10   20 72   22 82   30 120}

do_execsql_test 3.9 {
  SELECT CAST(a AS INTEGER), sum(b) OVER win FROM t1 WINDOW win AS ( ORDER BY a RANGE BETWEEN 2.6 FOLLOWING AND 3.5 FOLLOWING )
} {5 {}   10 52   13 {}   13 {}   15 {}   20 {}   22 {}   30 {}}

do_execsql_test 3.10 {
  SELECT CAST(a AS INTEGER), sum(b) OVER win FROM t1 WINDOW win AS ( ORDER BY a DESC RANGE BETWEEN 5.7 PRECEDING AND 5.8 FOLLOWING )
} {30 90   22 120   20 150   15 142   13 102   13 102   10 112   5 30}

do_execsql_test 3.11 {
  SELECT CAST(a AS INTEGER), sum(b) OVER win FROM t1 WINDOW win AS ( ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND 5.9 PRECEDING )
} {30 {}   22 90   20 90   15 170   13 210   13 210   10 210   5 292}

do_execsql_test 3.12 {
  SELECT CAST(a AS INTEGER), sum(b) OVER win FROM t1 WINDOW win AS ( ORDER BY a DESC RANGE BETWEEN 2.1 FOLLOWING AND UNBOUNDED FOLLOWING )
} {30 232   22 112   20 112   15 30   13 30   13 30   10 10   5 {}}

do_execsql_test 3.13 {
  SELECT CAST(a AS INTEGER), sum(b) OVER win FROM t1 WINDOW win AS ( ORDER BY a RANGE 5.1 PRECEDING )
} {5 10   10 30   13 72   13 72   15 102   20 70   22 120   30 90}

#==========================================================================

do_execsql_test 4.0 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a INTEGER, b INTEGER);
  INSERT INTO t1 VALUES
    (NULL, 1), (NULL, 2), (NULL, 3), (10, 4), (10, 5);
} {}

do_execsql_test 4.1.1 {
  SELECT sum(b) OVER (
    ORDER BY a RANGE BETWEEN 5 PRECEDING AND 10 FOLLOWING
  ) FROM t1 ORDER BY 1;
} {6   6   6   9   9}

do_execsql_test 4.1.2 {
  SELECT sum(b) OVER (
    ORDER BY a DESC RANGE BETWEEN 5 PRECEDING AND 10 FOLLOWING
  ) FROM t1 ORDER BY 1;
} {6   6   6   9   9}

do_execsql_test 4.2.1 {
  SELECT sum(b) OVER (
    ORDER BY a RANGE BETWEEN 5 FOLLOWING AND 10 FOLLOWING
  ) FROM t1 ORDER BY 1 NULLS FIRST;
} {{}   {}   6   6   6}

do_execsql_test 4.2.2 {
  SELECT sum(b) OVER (
    ORDER BY a RANGE BETWEEN 5 FOLLOWING AND 10 FOLLOWING
  ) FROM t1 ORDER BY 1 NULLS LAST;
} {6   6   6   {}   {}}

do_execsql_test 4.2.3 {
  SELECT sum(b) OVER (
    ORDER BY a DESC RANGE BETWEEN 5 FOLLOWING AND 10 FOLLOWING
  ) FROM t1 ORDER BY 1 NULLS FIRST;
} {{}   {}   6   6   6}

do_execsql_test 4.2.4 {
  SELECT sum(b) OVER (
    ORDER BY a DESC RANGE BETWEEN 5 FOLLOWING AND 10 FOLLOWING
  ) FROM t1 ORDER BY 1 NULLS LAST;
} {6   6   6   {}   {}}

do_execsql_test 4.3.1 {
  SELECT sum(b) OVER (
    ORDER BY a NULLS FIRST RANGE BETWEEN UNBOUNDED PRECEDING AND 10 FOLLOWING
  ) FROM t1 ORDER BY 1 NULLS FIRST;
} {6   6   6   15   15}

do_execsql_test 4.3.2 {
  SELECT sum(b) OVER (
    ORDER BY a NULLS LAST RANGE BETWEEN UNBOUNDED PRECEDING AND 10 FOLLOWING
  ) FROM t1 ORDER BY 1 NULLS LAST;
} {9   9   15   15   15}

do_execsql_test 4.4.1 {
  SELECT sum(b) OVER (
    ORDER BY a NULLS FIRST ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING
  ) FROM t1 ORDER BY 1 NULLS FIRST;
} {3   6   9   9   12}

do_execsql_test 4.4.2 {
  SELECT sum(b) OVER (
    ORDER BY a NULLS LAST ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING
  ) FROM t1 ORDER BY 1 NULLS LAST;
} {5   6   8   9   10}

do_execsql_test 4.4.3 {
  SELECT sum(b) OVER (
    ORDER BY a DESC NULLS LAST ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING
  ) FROM t1 ORDER BY 1 NULLS FIRST;
} {5   6   8   9   10}

do_execsql_test 4.4.4 {
  SELECT sum(b) OVER (
    ORDER BY a DESC NULLS LAST ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING
  ) FROM t1 ORDER BY 1 NULLS LAST;
} {5   6   8   9   10}

do_execsql_test 4.5.1 {
  SELECT sum(b) OVER (
    ORDER BY a ASC  NULLS LAST RANGE BETWEEN UNBOUNDED PRECEDING AND 10 FOLLOWING
  ) FROM t1 ORDER BY 1 NULLS LAST;
} {9   9   15   15   15}

do_execsql_test 4.5.2 {
  SELECT sum(b) OVER (
    ORDER BY a DESC NULLS FIRST RANGE 
    BETWEEN UNBOUNDED PRECEDING AND 10 FOLLOWING
  ) FROM t1 ORDER BY 1 NULLS LAST;
} {6   6   6   15   15}

#==========================================================================

do_execsql_test 5.0 {
  INSERT INTO t3 VALUES
    (NULL, 'bb', 355), (NULL, 'cc', 158), (NULL, 'aa', 399), 
    ('JJ', NULL, 839), ('FF', NULL, 618), ('BB', NULL, 393), 
    (NULL, 'bb', 629), (NULL, NULL, 667), (NULL, NULL, 870);
} {}

do_execsql_test 5.1.1.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE NO OTHERS  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 102 83}

do_execsql_test 5.1.1.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE NO OTHERS  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1}

do_execsql_test 5.1.2.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY a NULLS FIRST 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE NO OTHERS  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {899 113 9   899 113 9   899 113 9   899 113 9   899 113 9   899 113 9
  899 113 9   899 113 9   899 113 9   899 113 16   899 113 16   899 113 16
  899 113 16   899 113 16   899 113 16   899 113 16   979 102 44   979 102 44
  979 102 44   979 102 44   979 102 44   979 102 44   979 102 44   979 102 44
  979 102 44   979 102 44   979 102 44   979 102 49   979 102 49   979 102 49
  979 102 49   979 102 49   979 102 56   979 102 56   979 102 56   979 102 56
  979 102 56   979 102 56   979 102 56   979 102 62   979 102 62   979 102 62
  979 102 62   979 102 62   979 102 62   979 102 75   979 102 75   979 102 75
  979 102 75   979 102 75   979 102 75   979 102 75   979 102 75   979 102 75
  979 102 75   979 102 75   979 102 75   979 102 75   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 113 25   979 113 25   979 113 25   979 113 25   979 113 25   979 113 25
  979 113 25   979 113 25   979 113 25   979 113 33   979 113 33   979 113 33
  979 113 33   979 113 33   979 113 33   979 113 33   979 113 33}

do_execsql_test 5.1.2.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY a NULLS FIRST 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE NO OTHERS  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {2947 81 11   2947 81 11   2947 81 11   2947 81 11   2947 81 11   2947 81 11
  2947 81 11   2947 81 11   2947 81 11   5287 74 10   5287 74 10   5287 74 10
  5287 74 10   5287 74 10   5287 74 10   5287 74 10   8400 65 9   8400 65 9
  8400 65 9   8400 65 9   8400 65 9   8400 65 9   8400 65 9   8400 65 9
  8400 65 9   9664 57 8   9664 57 8   9664 57 8   9664 57 8   9664 57 8
  9664 57 8   9664 57 8   9664 57 8   10626 46 7   10626 46 7   10626 46 7
  10626 46 7   10626 46 7   10626 46 7   10626 46 7   10626 46 7   10626 46 7
  10626 46 7   10626 46 7   12145 41 6   12145 41 6   12145 41 6   12145 41 6
  12145 41 6   13949 34 5   13949 34 5   13949 34 5   13949 34 5   13949 34 5
  13949 34 5   13949 34 5   15315 28 4   15315 28 4   15315 28 4   15315 28 4
  15315 28 4   15315 28 4   18796 15 3   18796 15 3   18796 15 3   18796 15 3
  18796 15 3   18796 15 3   18796 15 3   18796 15 3   18796 15 3   18796 15 3
  18796 15 3   18796 15 3   18796 15 3   21105 7 2   21105 7 2   21105 7 2
  21105 7 2   21105 7 2   21105 7 2   21105 7 2   21105 7 2   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1}

do_execsql_test 5.1.3.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  PARTITION BY coalesce(a, '') 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE NO OTHERS  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {777 113 5   777 113 5   777 113 5   777 113 5   777 113 5   805 250 7
  805 250 7   805 250 7   805 250 7   805 250 7   805 250 7   805 250 7
  822 158 6   822 158 6   822 158 6   822 158 6   822 158 6   822 158 6
  840 247 13   840 247 13   840 247 13   840 247 13   840 247 13   840 247 13
  840 247 13   840 247 13   840 247 13   840 247 13   840 247 13   840 247 13
  840 247 13   870 158 0   870 158 0   870 158 0   870 158 0   870 158 0
  870 158 0   899 113 9   899 113 9   899 113 9   899 113 9   899 113 9
  899 113 9   899 113 9   899 113 9   899 113 9   934 223 8   934 223 8
  934 223 8   934 223 8   934 223 8   934 223 8   934 223 8   934 223 8
  938 102 11   938 102 11   938 102 11   938 102 11   938 102 11   938 102 11
  938 102 11   938 102 11   938 102 11   938 102 11   938 102 11   938 148 8
  938 148 8   938 148 8   938 148 8   938 148 8   938 148 8   938 148 8
  938 148 8   959 224 7   959 224 7   959 224 7   959 224 7   959 224 7
  959 224 7   959 224 7   979 133 9   979 133 9   979 133 9   979 133 9
  979 133 9   979 133 9   979 133 9   979 133 9   979 133 9}

do_execsql_test 5.1.3.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  PARTITION BY coalesce(a, '') 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE NO OTHERS  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {962 1 1   962 1 1   962 1 1   962 1 1   962 1 1   962 1 1   962 1 1
  962 1 1   962 1 1   962 1 1   962 1 1   1264 1 1   1264 1 1   1264 1 1
  1264 1 1   1264 1 1   1264 1 1   1264 1 1   1264 1 1   1366 1 1   1366 1 1
  1366 1 1   1366 1 1   1366 1 1   1366 1 1   1519 1 1   1519 1 1   1519 1 1
  1519 1 1   1519 1 1   1804 1 1   1804 1 1   1804 1 1   1804 1 1   1804 1 1
  1804 1 1   1804 1 1   2050 1 1   2050 1 1   2050 1 1   2050 1 1   2050 1 1
  2050 1 1   2309 1 1   2309 1 1   2309 1 1   2309 1 1   2309 1 1   2309 1 1
  2309 1 1   2309 1 1   2340 1 1   2340 1 1   2340 1 1   2340 1 1   2340 1 1
  2340 1 1   2340 1 1   2947 1 1   2947 1 1   2947 1 1   2947 1 1   2947 1 1
  2947 1 1   2947 1 1   2947 1 1   2947 1 1   3113 1 1   3113 1 1   3113 1 1
  3113 1 1   3113 1 1   3113 1 1   3113 1 1   3113 1 1   3113 1 1   3481 1 1
  3481 1 1   3481 1 1   3481 1 1   3481 1 1   3481 1 1   3481 1 1   3481 1 1
  3481 1 1   3481 1 1   3481 1 1   3481 1 1   3481 1 1}

do_execsql_test 5.1.4.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY a NULLS FIRST GROUPS 6 PRECEDING   EXCLUDE NO OTHERS  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {870 158 0   870 158 0   870 158 0   870 158 0   870 158 0   870 158 0
  934 158 8   934 158 8   934 158 8   934 158 8   934 158 8   934 158 8
  934 158 8   934 158 8   934 158 21   934 158 21   934 158 21   934 158 21
  934 158 21   934 158 21   934 158 21   934 158 21   934 158 21   934 158 21
  934 158 21   934 158 21   934 158 21   934 158 27   934 158 27   934 158 27
  934 158 27   934 158 27   934 158 27   959 102 50   959 102 50   959 102 50
  959 102 50   959 102 50   959 102 50   959 102 50   959 102 50   959 102 50
  959 102 50   959 102 50   959 102 58   959 102 58   959 102 58   959 102 58
  959 102 58   959 102 58   959 102 58   959 102 58   959 113 39   959 113 39
  959 113 39   959 113 39   959 113 39   959 158 34   959 158 34   959 158 34
  959 158 34   959 158 34   959 158 34   959 158 34   979 102 53   979 102 53
  979 102 53   979 102 53   979 102 53   979 102 53   979 102 53   979 102 56
  979 102 56   979 102 56   979 102 56   979 102 56   979 102 56   979 102 56
  979 102 56   979 102 56   979 102 59   979 102 59   979 102 59   979 102 59
  979 102 59   979 102 59   979 102 59   979 102 59   979 102 59}

do_execsql_test 5.1.4.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY a NULLS FIRST GROUPS 6 PRECEDING   EXCLUDE NO OTHERS  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {2050 1 1   2050 1 1   2050 1 1   2050 1 1   2050 1 1   2050 1 1   4359 7 2
  4359 7 2   4359 7 2   4359 7 2   4359 7 2   4359 7 2   4359 7 2   4359 7 2
  7840 15 3   7840 15 3   7840 15 3   7840 15 3   7840 15 3   7840 15 3
  7840 15 3   7840 15 3   7840 15 3   7840 15 3   7840 15 3   7840 15 3
  7840 15 3   9206 28 4   9206 28 4   9206 28 4   9206 28 4   9206 28 4
  9206 28 4   11010 34 5   11010 34 5   11010 34 5   11010 34 5   11010 34 5
  11010 34 5   11010 34 5   12368 74 10   12368 74 10   12368 74 10
  12368 74 10   12368 74 10   12368 74 10   12368 74 10   12529 41 6
  12529 41 6   12529 41 6   12529 41 6   12529 41 6   12705 57 8   12705 57 8
  12705 57 8   12705 57 8   12705 57 8   12705 57 8   12705 57 8   12705 57 8
  13491 46 7   13491 46 7   13491 46 7   13491 46 7   13491 46 7   13491 46 7
  13491 46 7   13491 46 7   13491 46 7   13491 46 7   13491 46 7   13509 65 9
  13509 65 9   13509 65 9   13509 65 9   13509 65 9   13509 65 9   13509 65 9
  13509 65 9   13509 65 9   13949 81 11   13949 81 11   13949 81 11
  13949 81 11   13949 81 11   13949 81 11   13949 81 11   13949 81 11
  13949 81 11}

do_execsql_test 5.1.5.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS FIRST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING   EXCLUDE NO OTHERS  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {102 102 1   113 113 2   113 113 2   133 133 1   148 148 1   160 158 2
  160 158 2   160 158 2   208 208 1   224 223 2   224 223 2   239 234 3
  239 234 3   239 234 3   252 247 3   257 247 5   257 247 5   257 250 4
  257 252 3   295 295 1   309 309 1   336 330 3   336 330 3   336 330 3
  346 346 1   355 354 2   355 354 2   355 354 2   399 393 4   399 393 4
  399 393 4   399 393 4   399 393 4   412 412 1   421 421 1   430 430 1
  443 443 1   480 480 2   480 480 2   574 572 2   574 572 2   607 607 1
  618 618 2   618 618 2   634 627 4   634 627 4   634 627 4   634 627 4
  634 629 3   652 652 1   667 660 2   671 667 3   671 667 3   671 667 3
  671 667 3   683 683 1   711 705 2   716 705 3   716 711 2   730 726 2
  730 726 2   762 759 2   768 759 4   768 762 3   768 762 3   777 777 1
  792 786 3   794 786 4   794 786 4   794 790 3   805 805 1   822 822 1
  845 839 5   845 839 5   845 839 5   845 839 5   845 839 5   870 870 2
  870 870 2   870 870 2   899 899 1   911 911 1   934 929 2   938 929 4
  938 934 3   938 934 3   963 959 2   963 959 2   979 979 1}

do_execsql_test 5.1.5.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS FIRST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING   EXCLUDE NO OTHERS  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} 1 1   {} 5 4   {} 6 5   {} 6 5   {} 8 6   {} 9 7   {} 25 23   {} 34 29
  {} 36 31   {} 38 33   {} 38 33   {} 40 34   {} 41 35   {} 43 37   {} 43 37
  {} 50 42   {} 60 51   {} 61 52   {} 64 55   {} 64 55   {} 67 57   {} 68 58
  {} 69 59   {} 70 60   {} 72 62   {} 78 67   {} 78 67   {} 78 67   {} 85 72
  {} 85 72   133 4 3   223 10 8   223 11 9   226 2 2   226 2 2   239 12 10
  239 13 11   239 14 12   247 15 13   257 18 16   257 19 17   295 20 18
  309 21 19   335 22 20   335 23 21   335 24 22   421 35 30   443 37 32
  504 16 14   504 17 15   607 42 36   683 56 47   710 26 24   710 27 25
  710 27 25   711 59 50   759 62 53   759 63 54   777 66 56   805 71 61
  899 81 68   911 82 69   929 83 70   929 84 71   979 89 75   1334 51 43
  1416 57 48   1416 58 49   1584 29 26   1584 29 26   1584 31 27   1584 32 28
  1584 32 28   1891 49 41   1922 87 73   1922 88 74   2005 52 44   2005 52 44
  2005 54 45   2005 55 46   2518 45 38   2518 46 39   2518 46 39   2518 48 40
  2523 73 63   2523 73 63   2523 75 64   2523 76 65   2523 77 66}

do_execsql_test 5.1.6.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS FIRST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING   EXCLUDE NO OTHERS  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {102 102 1   113 113 2   113 113 2   133 133 1   148 148 1   158 158 1
  158 158 1   160 160 1   208 208 1   223 223 1   224 224 1   234 234 1
  238 238 1   239 239 1   247 247 1   250 250 1   252 252 1   256 256 1
  257 257 1   295 295 1   309 309 1   330 330 1   335 335 1   336 336 1
  346 346 1   354 354 1   355 355 1   355 355 1   393 393 2   393 393 2
  398 398 1   399 399 1   399 399 1   412 412 1   421 421 1   430 430 1
  443 443 1   480 480 2   480 480 2   572 572 1   574 574 1   607 607 1
  618 618 2   618 618 2   627 627 1   629 629 1   629 629 1   633 633 1
  634 634 1   652 652 1   660 660 1   667 667 1   667 667 1   670 670 1
  671 671 1   683 683 1   705 705 1   711 711 1   716 716 1   726 726 1
  730 730 1   759 759 1   762 762 1   768 768 2   768 768 2   777 777 1
  786 786 1   790 790 1   792 792 1   794 794 1   805 805 1   822 822 1
  839 839 2   839 839 2   840 840 1   844 844 1   845 845 1   870 870 2
  870 870 2   870 870 2   899 899 1   911 911 1   929 929 1   934 934 1
  938 938 2   938 938 2   959 959 1   963 963 1   979 979 1}

do_execsql_test 5.1.6.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS FIRST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING   EXCLUDE NO OTHERS  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} 1 1   {} 5 4   {} 6 5   {} 6 5   {} 8 6   {} 9 7   {} 11 9   {} 12 10
  {} 13 11   {} 16 14   {} 17 15   {} 18 16   {} 22 20   {} 24 22   {} 25 23
  {} 26 24   {} 31 27   {} 34 29   {} 36 31   {} 38 33   {} 38 33   {} 40 34
  {} 41 35   {} 43 37   {} 43 37   {} 49 41   {} 50 42   {} 51 43   {} 54 45
  {} 59 50   {} 60 51   {} 61 52   {} 63 54   {} 64 55   {} 64 55   {} 67 57
  {} 68 58   {} 69 59   {} 70 60   {} 72 62   {} 75 64   {} 76 65   {} 78 67
  {} 78 67   {} 78 67   {} 84 71   {} 85 72   {} 85 72   133 4 3   223 10 8
  226 2 2   226 2 2   239 14 12   247 15 13   257 19 17   295 20 18
  309 21 19   335 23 21   421 35 30   443 37 32   607 42 36   627 45 38
  633 48 40   671 55 46   683 56 47   705 57 48   710 27 25   710 27 25
  711 58 49   759 62 53   777 66 56   786 29 26   786 29 26   798 32 28
  798 32 28   805 71 61   845 77 66   899 81 68   911 82 69   929 83 70
  959 87 73   963 88 74   979 89 75   1258 46 39   1258 46 39   1334 52 44
  1334 52 44   1678 73 63   1678 73 63}

do_execsql_test 5.1.7.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS FIRST, b NULLS FIRST, a NULLS FIRST
        ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING   EXCLUDE NO OTHERS  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 102 83   979 113 81   979 113 82   979 133 80   979 148 79   979 158 77
  979 158 78   979 160 77   979 208 76   979 223 75   979 224 74   979 234 73
  979 238 72   979 239 71   979 247 70   979 250 69   979 252 68   979 256 67
  979 257 66   979 295 65   979 309 64   979 330 63   979 335 62   979 336 61
  979 346 60   979 354 59   979 355 58   979 355 58   979 393 56   979 393 57
  979 398 55   979 399 54   979 399 54   979 412 53   979 421 52   979 430 51
  979 443 50   979 480 48   979 480 49   979 572 47   979 574 46   979 607 45
  979 618 43   979 618 44   979 627 42   979 629 41   979 629 41   979 633 40
  979 634 39   979 652 38   979 660 37   979 667 36   979 667 36   979 670 35
  979 671 34   979 683 33   979 705 32   979 711 31   979 716 30   979 726 29
  979 730 28   979 759 27   979 762 26   979 768 24   979 768 25   979 777 23
  979 786 22   979 790 21   979 792 20   979 794 19   979 805 18   979 822 17
  979 839 15   979 839 16   979 840 14   979 844 13   979 845 12   979 870 10
  979 870 11   979 870 11   979 899 9   979 911 8   979 929 7}

do_execsql_test 5.1.7.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS FIRST, b NULLS FIRST, a NULLS FIRST
        ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING   EXCLUDE NO OTHERS  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {3830 89 89   4741 88 88   5640 84 84   5640 85 85   5640 86 86   5640 87 87
  6485 81 81   6485 82 82   6485 83 83   7324 80 80   8163 78 78   8163 79 79
  8968 73 73   8968 74 74   8968 75 75   8968 76 76   8968 77 77   9745 69 69
  9745 70 70   9745 71 71   9745 72 72   10504 65 65   10504 66 66
  10504 67 67   10504 68 68   11215 64 64   11920 63 63   12603 62 62
  13274 60 60   13274 61 61   13941 59 59   14608 55 55   14608 56 56
  14608 57 57   14608 58 58   15241 54 54   15870 53 53   16499 52 52
  17126 49 49   17126 50 50   17126 51 51   17733 44 44   17733 45 45
  17733 46 46   17733 47 47   17733 48 48   18176 42 42   18176 43 43
  18597 40 40   18597 41 41   18996 39 39   19395 37 37   19395 38 38
  19788 36 36   20181 35 35   20536 34 34   20891 30 30   20891 31 31
  20891 32 32   20891 33 33   21226 28 28   21226 29 29   21535 27 27
  21830 26 26   22087 22 22   22087 23 23   22087 24 24   22087 25 25
  22334 21 21   22573 17 17   22573 18 18   22573 19 19   22573 20 20
  22796 11 11   22796 12 12   22796 13 13   22796 14 14   22796 15 15
  22796 16 16   22929 10 10   23042 9 9   23155 1 1   23155 2 2   23155 3 3
  23155 4 4   23155 5 5   23155 6 6   23155 7 7   23155 8 8}

do_execsql_test 5.1.8.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE NO OTHERS  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 102 83}

do_execsql_test 5.1.8.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE NO OTHERS  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1}

do_execsql_test 5.1.9.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY a NULLS LAST 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE NO OTHERS  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {870 158 0   870 158 0   870 158 0   870 158 0   870 158 0   870 158 0
  899 113 9   899 113 9   899 113 9   899 113 9   899 113 9   899 113 9
  899 113 9   899 113 9   899 113 9   899 113 16   899 113 16   899 113 16
  899 113 16   899 113 16   899 113 16   899 113 16   979 102 44   979 102 44
  979 102 44   979 102 44   979 102 44   979 102 44   979 102 44   979 102 44
  979 102 44   979 102 44   979 102 44   979 102 49   979 102 49   979 102 49
  979 102 49   979 102 49   979 102 56   979 102 56   979 102 56   979 102 56
  979 102 56   979 102 56   979 102 56   979 102 62   979 102 62   979 102 62
  979 102 62   979 102 62   979 102 62   979 102 75   979 102 75   979 102 75
  979 102 75   979 102 75   979 102 75   979 102 75   979 102 75   979 102 75
  979 102 75   979 102 75   979 102 75   979 102 75   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 113 25   979 113 25   979 113 25   979 113 25   979 113 25   979 113 25
  979 113 25   979 113 25   979 113 25   979 113 33   979 113 33   979 113 33
  979 113 33   979 113 33   979 113 33   979 113 33   979 113 33}

do_execsql_test 5.1.9.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY a NULLS LAST 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE NO OTHERS  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {2050 84 11   2050 84 11   2050 84 11   2050 84 11   2050 84 11   2050 84 11
  4997 75 10   4997 75 10   4997 75 10   4997 75 10   4997 75 10   4997 75 10
  4997 75 10   4997 75 10   4997 75 10   7337 68 9   7337 68 9   7337 68 9
  7337 68 9   7337 68 9   7337 68 9   7337 68 9   10450 59 8   10450 59 8
  10450 59 8   10450 59 8   10450 59 8   10450 59 8   10450 59 8   10450 59 8
  10450 59 8   11714 51 7   11714 51 7   11714 51 7   11714 51 7   11714 51 7
  11714 51 7   11714 51 7   11714 51 7   12676 40 6   12676 40 6   12676 40 6
  12676 40 6   12676 40 6   12676 40 6   12676 40 6   12676 40 6   12676 40 6
  12676 40 6   12676 40 6   14195 35 5   14195 35 5   14195 35 5   14195 35 5
  14195 35 5   15999 28 4   15999 28 4   15999 28 4   15999 28 4   15999 28 4
  15999 28 4   15999 28 4   17365 22 3   17365 22 3   17365 22 3   17365 22 3
  17365 22 3   17365 22 3   20846 9 2   20846 9 2   20846 9 2   20846 9 2
  20846 9 2   20846 9 2   20846 9 2   20846 9 2   20846 9 2   20846 9 2
  20846 9 2   20846 9 2   20846 9 2   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1}

do_execsql_test 5.1.10.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  PARTITION BY coalesce(a, '') 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE NO OTHERS  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {777 113 5   777 113 5   777 113 5   777 113 5   777 113 5   805 250 7
  805 250 7   805 250 7   805 250 7   805 250 7   805 250 7   805 250 7
  822 158 6   822 158 6   822 158 6   822 158 6   822 158 6   822 158 6
  840 247 13   840 247 13   840 247 13   840 247 13   840 247 13   840 247 13
  840 247 13   840 247 13   840 247 13   840 247 13   840 247 13   840 247 13
  840 247 13   870 158 0   870 158 0   870 158 0   870 158 0   870 158 0
  870 158 0   899 113 9   899 113 9   899 113 9   899 113 9   899 113 9
  899 113 9   899 113 9   899 113 9   899 113 9   934 223 8   934 223 8
  934 223 8   934 223 8   934 223 8   934 223 8   934 223 8   934 223 8
  938 102 11   938 102 11   938 102 11   938 102 11   938 102 11   938 102 11
  938 102 11   938 102 11   938 102 11   938 102 11   938 102 11   938 148 8
  938 148 8   938 148 8   938 148 8   938 148 8   938 148 8   938 148 8
  938 148 8   959 224 7   959 224 7   959 224 7   959 224 7   959 224 7
  959 224 7   959 224 7   979 133 9   979 133 9   979 133 9   979 133 9
  979 133 9   979 133 9   979 133 9   979 133 9   979 133 9}

do_execsql_test 5.1.10.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  PARTITION BY coalesce(a, '') 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE NO OTHERS  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {962 1 1   962 1 1   962 1 1   962 1 1   962 1 1   962 1 1   962 1 1
  962 1 1   962 1 1   962 1 1   962 1 1   1264 1 1   1264 1 1   1264 1 1
  1264 1 1   1264 1 1   1264 1 1   1264 1 1   1264 1 1   1366 1 1   1366 1 1
  1366 1 1   1366 1 1   1366 1 1   1366 1 1   1519 1 1   1519 1 1   1519 1 1
  1519 1 1   1519 1 1   1804 1 1   1804 1 1   1804 1 1   1804 1 1   1804 1 1
  1804 1 1   1804 1 1   2050 1 1   2050 1 1   2050 1 1   2050 1 1   2050 1 1
  2050 1 1   2309 1 1   2309 1 1   2309 1 1   2309 1 1   2309 1 1   2309 1 1
  2309 1 1   2309 1 1   2340 1 1   2340 1 1   2340 1 1   2340 1 1   2340 1 1
  2340 1 1   2340 1 1   2947 1 1   2947 1 1   2947 1 1   2947 1 1   2947 1 1
  2947 1 1   2947 1 1   2947 1 1   2947 1 1   3113 1 1   3113 1 1   3113 1 1
  3113 1 1   3113 1 1   3113 1 1   3113 1 1   3113 1 1   3113 1 1   3481 1 1
  3481 1 1   3481 1 1   3481 1 1   3481 1 1   3481 1 1   3481 1 1   3481 1 1
  3481 1 1   3481 1 1   3481 1 1   3481 1 1   3481 1 1}

do_execsql_test 5.1.11.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY a NULLS LAST GROUPS 6 PRECEDING   EXCLUDE NO OTHERS  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {934 158 27   934 158 27   934 158 27   934 158 27   934 158 27   934 158 27
  934 223 8   934 223 8   934 223 8   934 223 8   934 223 8   934 223 8
  934 223 8   934 223 8   934 223 21   934 223 21   934 223 21   934 223 21
  934 223 21   934 223 21   934 223 21   934 223 21   934 223 21   934 223 21
  934 223 21   934 223 21   934 223 21   959 102 50   959 102 50   959 102 50
  959 102 50   959 102 50   959 102 50   959 102 50   959 102 50   959 102 50
  959 102 50   959 102 50   959 102 58   959 102 58   959 102 58   959 102 58
  959 102 58   959 102 58   959 102 58   959 102 58   959 113 39   959 113 39
  959 113 39   959 113 39   959 113 39   959 158 34   959 158 34   959 158 34
  959 158 34   959 158 34   959 158 34   959 158 34   979 102 49   979 102 49
  979 102 49   979 102 49   979 102 49   979 102 49   979 102 53   979 102 53
  979 102 53   979 102 53   979 102 53   979 102 53   979 102 53   979 102 56
  979 102 56   979 102 56   979 102 56   979 102 56   979 102 56   979 102 56
  979 102 56   979 102 56   979 102 59   979 102 59   979 102 59   979 102 59
  979 102 59   979 102 59   979 102 59   979 102 59   979 102 59}

do_execsql_test 5.1.11.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY a NULLS LAST GROUPS 6 PRECEDING   EXCLUDE NO OTHERS  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {2309 1 1   2309 1 1   2309 1 1   2309 1 1   2309 1 1   2309 1 1   2309 1 1
  2309 1 1   5790 9 2   5790 9 2   5790 9 2   5790 9 2   5790 9 2   5790 9 2
  5790 9 2   5790 9 2   5790 9 2   5790 9 2   5790 9 2   5790 9 2   5790 9 2
  7156 22 3   7156 22 3   7156 22 3   7156 22 3   7156 22 3   7156 22 3
  8960 28 4   8960 28 4   8960 28 4   8960 28 4   8960 28 4   8960 28 4
  8960 28 4   10479 35 5   10479 35 5   10479 35 5   10479 35 5   10479 35 5
  11441 40 6   11441 40 6   11441 40 6   11441 40 6   11441 40 6   11441 40 6
  11441 40 6   11441 40 6   11441 40 6   11441 40 6   11441 40 6   12368 68 9
  12368 68 9   12368 68 9   12368 68 9   12368 68 9   12368 68 9   12368 68 9
  12705 51 7   12705 51 7   12705 51 7   12705 51 7   12705 51 7   12705 51 7
  12705 51 7   12705 51 7   13509 59 8   13509 59 8   13509 59 8   13509 59 8
  13509 59 8   13509 59 8   13509 59 8   13509 59 8   13509 59 8
  13949 75 10   13949 75 10   13949 75 10   13949 75 10   13949 75 10
  13949 75 10   13949 75 10   13949 75 10   13949 75 10   14195 84 11
  14195 84 11   14195 84 11   14195 84 11   14195 84 11   14195 84 11}

do_execsql_test 5.1.12.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS LAST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING   EXCLUDE NO OTHERS  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {102 102 1   113 113 2   113 113 2   133 133 1   148 148 1   160 158 2
  160 158 2   160 158 2   208 208 1   224 223 2   224 223 2   239 234 3
  239 234 3   239 234 3   252 247 3   257 247 5   257 247 5   257 250 4
  257 252 3   295 295 1   309 309 1   336 330 3   336 330 3   336 330 3
  346 346 1   355 354 2   355 354 2   355 354 2   399 393 4   399 393 4
  399 393 4   399 393 4   399 393 4   412 412 1   421 421 1   430 430 1
  443 443 1   480 480 2   480 480 2   574 572 2   574 572 2   607 607 1
  618 618 2   618 618 2   634 627 4   634 627 4   634 627 4   634 627 4
  634 629 3   652 652 1   667 660 2   671 667 3   671 667 3   671 667 3
  671 667 3   683 683 1   711 705 2   716 705 3   716 711 2   730 726 2
  730 726 2   762 759 2   768 759 4   768 762 3   768 762 3   777 777 1
  792 786 3   794 786 4   794 786 4   794 790 3   805 805 1   822 822 1
  845 839 5   845 839 5   845 839 5   845 839 5   845 839 5   870 870 2
  870 870 2   870 870 2   899 899 1   911 911 1   934 929 2   938 929 4
  938 934 3   938 934 3   963 959 2   963 959 2   979 979 1}

do_execsql_test 5.1.12.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS LAST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING   EXCLUDE NO OTHERS  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} 1 1   {} 5 4   {} 6 5   {} 6 5   {} 8 6   {} 9 7   {} 25 23   {} 34 29
  {} 36 31   {} 38 33   {} 38 33   {} 40 34   {} 41 35   {} 43 37   {} 43 37
  {} 50 42   {} 60 51   {} 61 52   {} 64 55   {} 64 55   {} 67 57   {} 68 58
  {} 69 59   {} 70 60   {} 72 62   {} 78 67   {} 78 67   {} 78 67   {} 85 72
  {} 85 72   133 4 3   223 10 8   223 11 9   226 2 2   226 2 2   239 12 10
  239 13 11   239 14 12   247 15 13   257 18 16   257 19 17   295 20 18
  309 21 19   335 22 20   335 23 21   335 24 22   421 35 30   443 37 32
  504 16 14   504 17 15   607 42 36   683 56 47   710 26 24   710 27 25
  710 27 25   711 59 50   759 62 53   759 63 54   777 66 56   805 71 61
  899 81 68   911 82 69   929 83 70   929 84 71   979 89 75   1334 51 43
  1416 57 48   1416 58 49   1584 29 26   1584 29 26   1584 31 27   1584 32 28
  1584 32 28   1891 49 41   1922 87 73   1922 88 74   2005 52 44   2005 52 44
  2005 54 45   2005 55 46   2518 45 38   2518 46 39   2518 46 39   2518 48 40
  2523 73 63   2523 73 63   2523 75 64   2523 76 65   2523 77 66}

do_execsql_test 5.1.13.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS LAST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING   EXCLUDE NO OTHERS  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {102 102 1   113 113 2   113 113 2   133 133 1   148 148 1   158 158 1
  158 158 1   160 160 1   208 208 1   223 223 1   224 224 1   234 234 1
  238 238 1   239 239 1   247 247 1   250 250 1   252 252 1   256 256 1
  257 257 1   295 295 1   309 309 1   330 330 1   335 335 1   336 336 1
  346 346 1   354 354 1   355 355 1   355 355 1   393 393 2   393 393 2
  398 398 1   399 399 1   399 399 1   412 412 1   421 421 1   430 430 1
  443 443 1   480 480 2   480 480 2   572 572 1   574 574 1   607 607 1
  618 618 2   618 618 2   627 627 1   629 629 1   629 629 1   633 633 1
  634 634 1   652 652 1   660 660 1   667 667 1   667 667 1   670 670 1
  671 671 1   683 683 1   705 705 1   711 711 1   716 716 1   726 726 1
  730 730 1   759 759 1   762 762 1   768 768 2   768 768 2   777 777 1
  786 786 1   790 790 1   792 792 1   794 794 1   805 805 1   822 822 1
  839 839 2   839 839 2   840 840 1   844 844 1   845 845 1   870 870 2
  870 870 2   870 870 2   899 899 1   911 911 1   929 929 1   934 934 1
  938 938 2   938 938 2   959 959 1   963 963 1   979 979 1}

do_execsql_test 5.1.13.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS LAST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING   EXCLUDE NO OTHERS  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} 1 1   {} 5 4   {} 6 5   {} 6 5   {} 8 6   {} 9 7   {} 11 9   {} 12 10
  {} 13 11   {} 16 14   {} 17 15   {} 18 16   {} 22 20   {} 24 22   {} 25 23
  {} 26 24   {} 31 27   {} 34 29   {} 36 31   {} 38 33   {} 38 33   {} 40 34
  {} 41 35   {} 43 37   {} 43 37   {} 49 41   {} 50 42   {} 51 43   {} 54 45
  {} 59 50   {} 60 51   {} 61 52   {} 63 54   {} 64 55   {} 64 55   {} 67 57
  {} 68 58   {} 69 59   {} 70 60   {} 72 62   {} 75 64   {} 76 65   {} 78 67
  {} 78 67   {} 78 67   {} 84 71   {} 85 72   {} 85 72   133 4 3   223 10 8
  226 2 2   226 2 2   239 14 12   247 15 13   257 19 17   295 20 18
  309 21 19   335 23 21   421 35 30   443 37 32   607 42 36   627 45 38
  633 48 40   671 55 46   683 56 47   705 57 48   710 27 25   710 27 25
  711 58 49   759 62 53   777 66 56   786 29 26   786 29 26   798 32 28
  798 32 28   805 71 61   845 77 66   899 81 68   911 82 69   929 83 70
  959 87 73   963 88 74   979 89 75   1258 46 39   1258 46 39   1334 52 44
  1334 52 44   1678 73 63   1678 73 63}

do_execsql_test 5.1.14.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS LAST, b NULLS LAST, a NULLS LAST
        ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING   EXCLUDE NO OTHERS  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 102 83   979 113 81   979 113 82   979 133 80   979 148 79   979 158 77
  979 158 78   979 160 77   979 208 76   979 223 75   979 224 74   979 234 73
  979 238 72   979 239 71   979 247 70   979 250 69   979 252 68   979 256 67
  979 257 66   979 295 65   979 309 64   979 330 63   979 335 62   979 336 61
  979 346 60   979 354 59   979 355 57   979 355 58   979 393 56   979 393 57
  979 398 55   979 399 53   979 399 54   979 412 53   979 421 52   979 430 51
  979 443 50   979 480 48   979 480 49   979 572 47   979 574 46   979 607 45
  979 618 43   979 618 44   979 627 42   979 629 40   979 629 41   979 633 40
  979 634 39   979 652 38   979 660 37   979 667 35   979 667 36   979 670 35
  979 671 34   979 683 33   979 705 32   979 711 31   979 716 30   979 726 29
  979 730 28   979 759 27   979 762 26   979 768 24   979 768 25   979 777 23
  979 786 22   979 790 21   979 792 20   979 794 19   979 805 18   979 822 17
  979 839 15   979 839 16   979 840 14   979 844 13   979 845 12   979 870 9
  979 870 10   979 870 11   979 899 9   979 911 8   979 929 7}

do_execsql_test 5.1.14.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS LAST, b NULLS LAST, a NULLS LAST
        ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING   EXCLUDE NO OTHERS  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {3830 89 89   4741 88 88   5640 84 84   5640 85 85   5640 86 86   5640 87 87
  6485 81 81   6485 82 82   6485 83 83   7324 80 80   8163 78 78   8163 79 79
  8968 73 73   8968 74 74   8968 75 75   8968 76 76   8968 77 77   9745 69 69
  9745 70 70   9745 71 71   9745 72 72   10504 65 65   10504 66 66
  10504 67 67   10504 68 68   11215 64 64   11920 63 63   12603 62 62
  13274 60 60   13274 61 61   13941 59 59   14608 55 55   14608 56 56
  14608 57 57   14608 58 58   15241 54 54   15870 53 53   16499 52 52
  17126 49 49   17126 50 50   17126 51 51   17733 44 44   17733 45 45
  17733 46 46   17733 47 47   17733 48 48   18176 42 42   18176 43 43
  18597 40 40   18597 41 41   18996 39 39   19395 37 37   19395 38 38
  19788 36 36   20181 35 35   20536 34 34   20891 30 30   20891 31 31
  20891 32 32   20891 33 33   21226 28 28   21226 29 29   21535 27 27
  21830 26 26   22087 22 22   22087 23 23   22087 24 24   22087 25 25
  22334 21 21   22573 17 17   22573 18 18   22573 19 19   22573 20 20
  22796 11 11   22796 12 12   22796 13 13   22796 14 14   22796 15 15
  22796 16 16   22929 10 10   23042 9 9   23155 1 1   23155 2 2   23155 3 3
  23155 4 4   23155 5 5   23155 6 6   23155 7 7   23155 8 8}

do_execsql_test 5.2.1.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE CURRENT ROW  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {963 102 82   979 102 82   979 102 82   979 102 82   979 102 82   979 102 82
  979 102 82   979 102 82   979 102 82   979 102 82   979 102 82   979 102 82
  979 102 82   979 102 82   979 102 82   979 102 82   979 102 82   979 102 82
  979 102 82   979 102 82   979 102 82   979 102 82   979 102 82   979 102 82
  979 102 82   979 102 82   979 102 82   979 102 82   979 102 82   979 102 82
  979 102 82   979 102 82   979 102 82   979 102 82   979 102 82   979 102 82
  979 102 82   979 102 82   979 102 82   979 102 82   979 102 82   979 102 82
  979 102 82   979 102 82   979 102 82   979 102 82   979 102 82   979 102 82
  979 102 82   979 102 82   979 102 82   979 102 82   979 102 82   979 102 82
  979 102 82   979 102 82   979 102 82   979 102 82   979 102 82   979 102 82
  979 102 82   979 102 82   979 102 82   979 102 82   979 102 82   979 102 82
  979 102 82   979 102 82   979 102 82   979 102 82   979 102 82   979 102 82
  979 102 82   979 102 82   979 102 82   979 102 82   979 102 82   979 102 82
  979 102 82   979 102 82   979 102 82   979 102 82   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 113 82}

do_execsql_test 5.2.1.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE CURRENT ROW  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {22176 1 1   22192 1 1   22196 1 1   22226 1 1   22244 1 1   22256 1 1
  22310 1 1   22316 1 1   22316 1 1   22350 1 1   22378 1 1   22396 1 1
  22444 1 1   22450 1 1   22472 1 1   22484 1 1   22488 1 1   22488 1 1
  22522 1 1   22526 1 1   22526 1 1   22528 1 1   22548 1 1   22712 1 1
  22734 1 1   22756 1 1   22756 1 1   22762 1 1   22762 1 1   22800 1 1
  22800 1 1   22820 1 1   22846 1 1   22860 1 1   22898 1 1   22908 1 1
  22916 1 1   22932 1 1   23022 1 1   23042 1 1   23042 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1}

do_execsql_test 5.2.2.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY a NULLS FIRST 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE CURRENT ROW  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {839 113 8   899 113 8   899 113 8   899 113 8   899 113 8   899 113 8
  899 113 8   899 113 8   899 113 15   899 113 15   899 113 15   899 113 15
  899 113 15   899 113 15   899 113 15   899 234 8   963 113 24   979 102 43
  979 102 43   979 102 43   979 102 43   979 102 43   979 102 43   979 102 43
  979 102 43   979 102 43   979 102 43   979 102 48   979 102 48   979 102 48
  979 102 48   979 102 48   979 102 55   979 102 55   979 102 55   979 102 55
  979 102 55   979 102 55   979 102 55   979 102 61   979 102 61   979 102 61
  979 102 61   979 102 61   979 102 61   979 102 74   979 102 74   979 102 74
  979 102 74   979 102 74   979 102 74   979 102 74   979 102 74   979 102 74
  979 102 74   979 102 74   979 102 74   979 102 74   979 102 82   979 102 82
  979 102 82   979 102 82   979 102 82   979 102 82   979 102 82   979 102 82
  979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 113 24   979 113 24   979 113 24   979 113 24   979 113 24   979 113 24
  979 113 24   979 113 24   979 113 32   979 113 32   979 113 32   979 113 32
  979 113 32   979 113 32   979 113 32   979 113 32   979 113 43}

do_execsql_test 5.2.2.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY a NULLS FIRST 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE CURRENT ROW  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {2048 81 11   2108 81 11   2108 81 11   2690 81 11   2834 81 11   2947 81 11
  2947 81 11   2947 81 11   2947 81 11   4482 74 10   4616 74 10   4844 74 10
  4866 74 10   5287 74 10   5287 74 10   5287 74 10   7421 65 9   7437 65 9
  7717 65 9   8045 65 9   8267 65 9   8400 65 9   8400 65 9   8400 65 9
  8400 65 9   8735 57 8   9329 57 8   9664 57 8   9664 57 8   9664 57 8
  9664 57 8   9664 57 8   9664 57 8   9959 46 7   10331 46 7   10626 46 7
  10626 46 7   10626 46 7   10626 46 7   10626 46 7   10626 46 7   10626 46 7
  10626 46 7   10626 46 7   11368 41 6   11516 41 6   12032 41 6   12145 41 6
  12145 41 6   12990 34 5   13104 34 5   13949 34 5   13949 34 5   13949 34 5
  13949 34 5   13949 34 5   14556 28 4   14708 28 4   15315 28 4   15315 28 4
  15315 28 4   15315 28 4   18085 15 3   18091 15 3   18163 15 3   18397 15 3
  18403 15 3   18403 15 3   18549 15 3   18796 15 3   18796 15 3   18796 15 3
  18796 15 3   18796 15 3   18796 15 3   20194 7 2   20478 7 2   20796 7 2
  20866 7 2   20882 7 2   21105 7 2   21105 7 2   21105 7 2   22488 1 1
  22526 1 1   22756 1 1   22800 1 1   23155 1 1   23155 1 1}

do_execsql_test 5.2.3.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  PARTITION BY coalesce(a, '') 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE CURRENT ROW  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {667 158 0   671 250 6   759 158 5   768 113 4   777 113 4   777 113 4
  777 113 4   777 252 4   792 247 12   805 250 6   805 250 6   805 250 6
  805 250 6   805 250 6   805 398 6   822 158 5   822 158 5   822 158 5
  822 158 5   822 346 5   839 113 8   840 247 12   840 247 12   840 247 12
  840 247 12   840 247 12   840 247 12   840 247 12   840 247 12   840 247 12
  840 247 12   840 247 12   840 393 12   845 224 6   870 102 10   870 158 0
  870 158 0   870 158 0   870 158 0   870 355 0   899 113 8   899 113 8
  899 113 8   899 113 8   899 113 8   899 113 8   899 113 8   899 234 8
  911 223 7   929 148 7   934 223 7   934 223 7   934 223 7   934 223 7
  934 223 7   934 223 7   934 239 7   938 102 10   938 102 10   938 102 10
  938 102 10   938 102 10   938 102 10   938 102 10   938 102 10   938 102 10
  938 148 7   938 148 7   938 148 7   938 148 7   938 148 7   938 148 7
  938 160 7   938 208 10   959 224 6   959 224 6   959 224 6   959 224 6
  959 224 6   959 238 6   963 133 8   979 133 8   979 133 8   979 133 8
  979 133 8   979 133 8   979 133 8   979 133 8   979 330 8}

do_execsql_test 5.2.3.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  PARTITION BY coalesce(a, '') 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE CURRENT ROW  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {295 1 1   335 1 1   607 1 1   667 1 1   742 1 1   759 1 1   845 1 1
  890 1 1   929 1 1   959 1 1   962 1 1   962 1 1   962 1 1   962 1 1
  962 1 1   962 1 1   962 1 1   962 1 1   962 1 1   1264 1 1   1264 1 1
  1264 1 1   1264 1 1   1264 1 1   1264 1 1   1366 1 1   1366 1 1   1366 1 1
  1366 1 1   1383 1 1   1398 1 1   1406 1 1   1421 1 1   1519 1 1   1519 1 1
  1535 1 1   1651 1 1   1669 1 1   1682 1 1   1695 1 1   1804 1 1   1804 1 1
  1804 1 1   1804 1 1   1804 1 1   1897 1 1   1919 1 1   2000 1 1   2048 1 1
  2050 1 1   2050 1 1   2070 1 1   2086 1 1   2108 1 1   2108 1 1   2134 1 1
  2150 1 1   2309 1 1   2309 1 1   2309 1 1   2340 1 1   2340 1 1   2340 1 1
  2430 1 1   2690 1 1   2758 1 1   2770 1 1   2776 1 1   2834 1 1   2848 1 1
  2947 1 1   2947 1 1   2947 1 1   2947 1 1   2980 1 1   3082 1 1   3088 1 1
  3088 1 1   3113 1 1   3113 1 1   3113 1 1   3113 1 1   3234 1 1   3481 1 1
  3481 1 1   3481 1 1   3481 1 1   3481 1 1   3481 1 1}

do_execsql_test 5.2.4.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY a NULLS FIRST GROUPS 6 PRECEDING   EXCLUDE CURRENT ROW  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {667 158 0   870 158 0   870 158 0   870 158 0   870 158 0   870 355 0
  911 158 7   934 158 7   934 158 7   934 158 7   934 158 7   934 158 7
  934 158 7   934 158 7   934 158 20   934 158 20   934 158 20   934 158 20
  934 158 20   934 158 20   934 158 20   934 158 20   934 158 20   934 158 20
  934 158 20   934 158 20   934 158 20   934 158 26   934 158 26   934 158 26
  934 158 26   934 158 26   934 158 26   934 158 33   959 102 49   959 102 49
  959 102 49   959 102 49   959 102 49   959 102 49   959 102 49   959 102 49
  959 102 49   959 102 49   959 102 57   959 102 57   959 102 57   959 102 57
  959 102 57   959 102 57   959 102 57   959 102 57   959 113 38   959 113 38
  959 113 38   959 113 38   959 113 49   959 158 33   959 158 33   959 158 33
  959 158 33   959 158 33   959 158 33   959 158 38   963 102 58   979 102 52
  979 102 52   979 102 52   979 102 52   979 102 52   979 102 52   979 102 52
  979 102 55   979 102 55   979 102 55   979 102 55   979 102 55   979 102 55
  979 102 55   979 102 55   979 102 55   979 102 58   979 102 58   979 102 58
  979 102 58   979 102 58   979 102 58   979 102 58   979 102 58}

do_execsql_test 5.2.4.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY a NULLS FIRST GROUPS 6 PRECEDING   EXCLUDE CURRENT ROW  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {1383 1 1   1421 1 1   1651 1 1   1695 1 1   2050 1 1   2050 1 1   3448 7 2
  3732 7 2   4050 7 2   4120 7 2   4136 7 2   4359 7 2   4359 7 2   4359 7 2
  7129 15 3   7135 15 3   7207 15 3   7441 15 3   7447 15 3   7447 15 3
  7593 15 3   7840 15 3   7840 15 3   7840 15 3   7840 15 3   7840 15 3
  7840 15 3   8447 28 4   8599 28 4   9206 28 4   9206 28 4   9206 28 4
  9206 28 4   10051 34 5   10165 34 5   11010 34 5   11010 34 5   11010 34 5
  11010 34 5   11010 34 5   11563 74 10   11697 74 10   11752 41 6
  11776 57 8   11900 41 6   11925 74 10   11947 74 10   12368 74 10
  12368 74 10   12368 74 10   12370 57 8   12416 41 6   12529 41 6
  12529 41 6   12530 65 9   12546 65 9   12705 57 8   12705 57 8   12705 57 8
  12705 57 8   12705 57 8   12705 57 8   12824 46 7   12826 65 9
  13050 81 11   13110 81 11   13110 81 11   13154 65 9   13196 46 7
  13376 65 9   13491 46 7   13491 46 7   13491 46 7   13491 46 7   13491 46 7
  13491 46 7   13491 46 7   13491 46 7   13491 46 7   13509 65 9   13509 65 9
  13509 65 9   13509 65 9   13692 81 11   13836 81 11   13949 81 11
  13949 81 11   13949 81 11   13949 81 11}

do_execsql_test 5.2.5.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS FIRST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING   EXCLUDE CURRENT ROW  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   113 113 1
  113 113 1   158 158 1   160 158 1   160 158 2   223 223 1   224 224 1
  238 234 2   239 234 2   239 238 2   252 250 2   256 252 2   257 247 4
  257 247 4   257 250 3   335 330 2   336 330 2   336 335 2   355 354 1
  355 354 2   355 355 1   399 393 3   399 393 3   399 393 3   399 393 3
  399 393 4   480 480 1   480 480 1   572 572 1   574 574 1   618 618 1
  618 618 1   633 629 2   634 627 3   634 627 3   634 627 4   634 629 3
  667 667 1   670 667 2   671 667 2   671 667 2   671 667 3   711 711 1
  711 711 1   716 705 2   726 726 1   730 730 1   762 762 1   768 759 3
  768 762 2   768 762 2   792 790 2   792 790 2   794 786 3   794 786 3
  844 839 4   845 839 4   845 839 4   845 839 4   845 839 4   870 870 1
  870 870 1   870 870 2   934 934 1   938 929 3   938 934 2   938 934 2
  959 959 1   963 963 1}

do_execsql_test 5.2.5.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS FIRST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING   EXCLUDE CURRENT ROW  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} 1 1   {} 4 3   {} 5 4   {} 6 5   {} 6 5   {} 8 6   {} 9 7   {} 10 8
  {} 14 12   {} 15 13   {} 19 17   {} 20 18   {} 21 19   {} 23 21   {} 25 23
  {} 34 29   {} 35 30   {} 36 31   {} 37 32   {} 38 33   {} 38 33   {} 40 34
  {} 41 35   {} 42 36   {} 43 37   {} 43 37   {} 50 42   {} 56 47   {} 60 51
  {} 61 52   {} 62 53   {} 64 55   {} 64 55   {} 66 56   {} 67 57   {} 68 58
  {} 69 59   {} 70 60   {} 71 61   {} 72 62   {} 78 67   {} 78 67   {} 78 67
  {} 81 68   {} 82 69   {} 83 70   {} 85 72   {} 85 72   {} 89 75   113 2 2
  113 2 2   223 11 9   239 12 10   239 13 11   257 18 16   335 22 20
  335 24 22   355 27 25   355 27 25   504 16 14   504 17 15   705 58 49
  710 26 24   711 57 48   711 59 50   759 63 54   929 84 71   959 88 74
  963 87 73   1185 32 28   1185 32 28   1191 29 26   1191 29 26   1334 51 43
  1334 55 46   1338 52 44   1338 52 44   1584 31 27   1678 77 66   1684 73 63
  1684 73 63   1885 48 40   1889 46 39   1889 46 39   1891 45 38   1891 49 41
  2005 54 45   2523 75 64   2523 76 65}

do_execsql_test 5.2.6.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS FIRST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING   EXCLUDE CURRENT ROW  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   113 113 1
  113 113 1   158 158 0   158 158 1   355 355 0   355 355 1   393 393 1
  393 393 1   399 399 0   399 399 1   480 480 1   480 480 1   618 618 1
  618 618 1   629 629 0   629 629 1   667 667 0   667 667 1   768 768 1
  768 768 1   839 839 1   839 839 1   870 870 1   870 870 1   870 870 2
  938 938 1   938 938 1}

do_execsql_test 5.2.6.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS FIRST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING   EXCLUDE CURRENT ROW  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} 1 1   {} 4 3   {} 5 4   {} 6 5   {} 6 5   {} 8 6   {} 9 7   {} 10 8
  {} 11 9   {} 12 10   {} 13 11   {} 14 12   {} 15 13   {} 16 14   {} 17 15
  {} 18 16   {} 19 17   {} 20 18   {} 21 19   {} 22 20   {} 23 21   {} 24 22
  {} 25 23   {} 26 24   {} 31 27   {} 34 29   {} 35 30   {} 36 31   {} 37 32
  {} 38 33   {} 38 33   {} 40 34   {} 41 35   {} 42 36   {} 43 37   {} 43 37
  {} 45 38   {} 48 40   {} 49 41   {} 50 42   {} 51 43   {} 54 45   {} 55 46
  {} 56 47   {} 57 48   {} 58 49   {} 59 50   {} 60 51   {} 61 52   {} 62 53
  {} 63 54   {} 64 55   {} 64 55   {} 66 56   {} 67 57   {} 68 58   {} 69 59
  {} 70 60   {} 71 61   {} 72 62   {} 75 64   {} 76 65   {} 77 66   {} 78 67
  {} 78 67   {} 78 67   {} 81 68   {} 82 69   {} 83 70   {} 84 71   {} 85 72
  {} 85 72   {} 87 73   {} 88 74   {} 89 75   113 2 2   113 2 2   355 27 25
  355 27 25   393 29 26   393 29 26   399 32 28   399 32 28   629 46 39
  629 46 39   667 52 44   667 52 44   839 73 63   839 73 63}

do_execsql_test 5.2.7.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS FIRST, b NULLS FIRST, a NULLS FIRST
        ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING   EXCLUDE CURRENT ROW  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {963 929 6   979 102 82   979 102 82   979 102 82   979 102 82   979 102 82
  979 102 83   979 113 80   979 113 81   979 113 82   979 133 79   979 148 78
  979 158 76   979 158 77   979 160 76   979 208 75   979 223 74   979 224 73
  979 234 72   979 238 71   979 239 70   979 247 69   979 250 68   979 252 67
  979 256 66   979 257 65   979 295 64   979 309 64   979 330 62   979 335 61
  979 336 60   979 346 59   979 354 59   979 355 57   979 355 57   979 393 55
  979 393 56   979 398 54   979 399 53   979 399 53   979 412 52   979 421 51
  979 430 50   979 443 49   979 480 47   979 480 48   979 572 47   979 574 45
  979 607 44   979 618 42   979 618 43   979 627 41   979 629 40   979 629 41
  979 633 39   979 634 38   979 652 37   979 660 36   979 667 35   979 667 35
  979 670 34   979 671 33   979 683 32   979 705 31   979 711 30   979 716 29
  979 726 28   979 730 27   979 759 26   979 762 25   979 768 23   979 768 24
  979 777 22   979 786 21   979 790 20   979 792 19   979 794 18   979 805 17
  979 822 17   979 839 14   979 839 15   979 840 13   979 844 12   979 845 11
  979 870 9   979 870 10   979 870 10   979 899 8   979 911 7}

do_execsql_test 5.2.7.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS FIRST, b NULLS FIRST, a NULLS FIRST
        ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING   EXCLUDE CURRENT ROW  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {2851 89 89   3778 88 88   4681 87 87   5556 83 83   5574 82 82   5586 81 81
  5640 84 84   5640 85 85   5640 86 86   7324 80 80   8123 77 77   8129 73 73
  8129 74 74   8163 78 78   8163 79 79   8940 71 71   8968 75 75   8968 76 76
  9727 66 66   9745 69 69   9745 70 70   9745 72 72   10504 65 65
  10504 67 67   10504 68 68   11215 64 64   11844 62 62   11920 63 63
  13274 60 60   13274 61 61   13897 58 58   13903 57 57   13925 56 56
  13937 55 55   13941 59 59   15203 53 53   15241 54 54   15832 52 52
  17100 48 48   17104 46 46   17104 47 47   17106 45 45   17126 49 49
  17126 50 50   17126 51 51   17569 42 42   17733 44 44   18176 43 43
  18597 40 40   18597 41 41   18952 37 37   18996 39 39   19395 38 38
  19760 35 35   19788 36 36   20492 32 32   20492 33 33   20498 30 30
  20536 34 34   20833 29 29   20871 28 28   20891 31 31   21180 27 27
  21752 23 23   21830 26 26   22025 21 21   22087 22 22   22087 24 24
  22087 25 25   22278 20 20   22316 19 19   22549 15 15   22557 14 14
  22573 17 17   22573 18 18   22706 10 10   22796 11 11   22796 12 12
  22796 13 13   22796 16 16   23022 4 4   23042 2 2   23042 3 3   23042 9 9
  23155 1 1   23155 5 5   23155 6 6   23155 7 7   23155 8 8}

do_execsql_test 5.2.8.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE CURRENT ROW  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {963 102 82   979 102 82   979 102 82   979 102 82   979 102 82   979 102 82
  979 102 82   979 102 82   979 102 82   979 102 82   979 102 82   979 102 82
  979 102 82   979 102 82   979 102 82   979 102 82   979 102 82   979 102 82
  979 102 82   979 102 82   979 102 82   979 102 82   979 102 82   979 102 82
  979 102 82   979 102 82   979 102 82   979 102 82   979 102 82   979 102 82
  979 102 82   979 102 82   979 102 82   979 102 82   979 102 82   979 102 82
  979 102 82   979 102 82   979 102 82   979 102 82   979 102 82   979 102 82
  979 102 82   979 102 82   979 102 82   979 102 82   979 102 82   979 102 82
  979 102 82   979 102 82   979 102 82   979 102 82   979 102 82   979 102 82
  979 102 82   979 102 82   979 102 82   979 102 82   979 102 82   979 102 82
  979 102 82   979 102 82   979 102 82   979 102 82   979 102 82   979 102 82
  979 102 82   979 102 82   979 102 82   979 102 82   979 102 82   979 102 82
  979 102 82   979 102 82   979 102 82   979 102 82   979 102 82   979 102 82
  979 102 82   979 102 82   979 102 82   979 102 82   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 113 82}

do_execsql_test 5.2.8.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE CURRENT ROW  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {22176 1 1   22192 1 1   22196 1 1   22226 1 1   22244 1 1   22256 1 1
  22310 1 1   22316 1 1   22316 1 1   22350 1 1   22378 1 1   22396 1 1
  22444 1 1   22450 1 1   22472 1 1   22484 1 1   22488 1 1   22488 1 1
  22522 1 1   22526 1 1   22526 1 1   22528 1 1   22548 1 1   22712 1 1
  22734 1 1   22756 1 1   22756 1 1   22762 1 1   22762 1 1   22800 1 1
  22800 1 1   22820 1 1   22846 1 1   22860 1 1   22898 1 1   22908 1 1
  22916 1 1   22932 1 1   23022 1 1   23042 1 1   23042 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1
  23155 1 1   23155 1 1   23155 1 1   23155 1 1   23155 1 1}

do_execsql_test 5.2.9.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY a NULLS LAST 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE CURRENT ROW  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {667 158 0   870 113 8   870 158 0   870 158 0   870 158 0   870 158 0
  870 355 0   899 113 8   899 113 8   899 113 8   899 113 8   899 113 8
  899 113 8   899 113 8   899 113 15   899 113 15   899 113 15   899 113 15
  899 113 15   899 113 15   899 113 15   899 158 8   963 113 24   979 102 43
  979 102 43   979 102 43   979 102 43   979 102 43   979 102 43   979 102 43
  979 102 43   979 102 43   979 102 43   979 102 48   979 102 48   979 102 48
  979 102 48   979 102 48   979 102 55   979 102 55   979 102 55   979 102 55
  979 102 55   979 102 55   979 102 55   979 102 61   979 102 61   979 102 61
  979 102 61   979 102 61   979 102 61   979 102 74   979 102 74   979 102 74
  979 102 74   979 102 74   979 102 74   979 102 74   979 102 74   979 102 74
  979 102 74   979 102 74   979 102 74   979 102 74   979 102 82   979 102 82
  979 102 82   979 102 82   979 102 82   979 102 82   979 102 82   979 102 82
  979 113 24   979 113 24   979 113 24   979 113 24   979 113 24   979 113 24
  979 113 24   979 113 24   979 113 32   979 113 32   979 113 32   979 113 32
  979 113 32   979 113 32   979 113 32   979 113 32   979 113 43}

do_execsql_test 5.2.9.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY a NULLS LAST 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE CURRENT ROW  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {1383 84 11   1421 84 11   1651 84 11   1695 84 11   2050 84 11   2050 84 11
  4098 75 10   4158 75 10   4158 75 10   4740 75 10   4884 75 10   4997 75 10
  4997 75 10   4997 75 10   4997 75 10   6532 68 9   6666 68 9   6894 68 9
  6916 68 9   7337 68 9   7337 68 9   7337 68 9   9471 59 8   9487 59 8
  9767 59 8   10095 59 8   10317 59 8   10450 59 8   10450 59 8   10450 59 8
  10450 59 8   10785 51 7   11379 51 7   11714 51 7   11714 51 7   11714 51 7
  11714 51 7   11714 51 7   11714 51 7   12009 40 6   12381 40 6   12676 40 6
  12676 40 6   12676 40 6   12676 40 6   12676 40 6   12676 40 6   12676 40 6
  12676 40 6   12676 40 6   13418 35 5   13566 35 5   14082 35 5   14195 35 5
  14195 35 5   15040 28 4   15154 28 4   15999 28 4   15999 28 4   15999 28 4
  15999 28 4   15999 28 4   16606 22 3   16758 22 3   17365 22 3   17365 22 3
  17365 22 3   17365 22 3   20135 9 2   20141 9 2   20213 9 2   20447 9 2
  20453 9 2   20453 9 2   20599 9 2   20846 9 2   20846 9 2   20846 9 2
  20846 9 2   20846 9 2   20846 9 2   22244 1 1   22528 1 1   22846 1 1
  22916 1 1   22932 1 1   23155 1 1   23155 1 1   23155 1 1}

do_execsql_test 5.2.10.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  PARTITION BY coalesce(a, '') 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE CURRENT ROW  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {667 158 0   671 250 6   759 158 5   768 113 4   777 113 4   777 113 4
  777 113 4   777 252 4   792 247 12   805 250 6   805 250 6   805 250 6
  805 250 6   805 250 6   805 398 6   822 158 5   822 158 5   822 158 5
  822 158 5   822 346 5   839 113 8   840 247 12   840 247 12   840 247 12
  840 247 12   840 247 12   840 247 12   840 247 12   840 247 12   840 247 12
  840 247 12   840 247 12   840 393 12   845 224 6   870 102 10   870 158 0
  870 158 0   870 158 0   870 158 0   870 355 0   899 113 8   899 113 8
  899 113 8   899 113 8   899 113 8   899 113 8   899 113 8   899 234 8
  911 223 7   929 148 7   934 223 7   934 223 7   934 223 7   934 223 7
  934 223 7   934 223 7   934 239 7   938 102 10   938 102 10   938 102 10
  938 102 10   938 102 10   938 102 10   938 102 10   938 102 10   938 102 10
  938 148 7   938 148 7   938 148 7   938 148 7   938 148 7   938 148 7
  938 160 7   938 208 10   959 224 6   959 224 6   959 224 6   959 224 6
  959 224 6   959 238 6   963 133 8   979 133 8   979 133 8   979 133 8
  979 133 8   979 133 8   979 133 8   979 133 8   979 330 8}

do_execsql_test 5.2.10.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  PARTITION BY coalesce(a, '') 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE CURRENT ROW  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {295 1 1   335 1 1   607 1 1   667 1 1   742 1 1   759 1 1   845 1 1
  890 1 1   929 1 1   959 1 1   962 1 1   962 1 1   962 1 1   962 1 1
  962 1 1   962 1 1   962 1 1   962 1 1   962 1 1   1264 1 1   1264 1 1
  1264 1 1   1264 1 1   1264 1 1   1264 1 1   1366 1 1   1366 1 1   1366 1 1
  1366 1 1   1383 1 1   1398 1 1   1406 1 1   1421 1 1   1519 1 1   1519 1 1
  1535 1 1   1651 1 1   1669 1 1   1682 1 1   1695 1 1   1804 1 1   1804 1 1
  1804 1 1   1804 1 1   1804 1 1   1897 1 1   1919 1 1   2000 1 1   2048 1 1
  2050 1 1   2050 1 1   2070 1 1   2086 1 1   2108 1 1   2108 1 1   2134 1 1
  2150 1 1   2309 1 1   2309 1 1   2309 1 1   2340 1 1   2340 1 1   2340 1 1
  2430 1 1   2690 1 1   2758 1 1   2770 1 1   2776 1 1   2834 1 1   2848 1 1
  2947 1 1   2947 1 1   2947 1 1   2947 1 1   2980 1 1   3082 1 1   3088 1 1
  3088 1 1   3113 1 1   3113 1 1   3113 1 1   3113 1 1   3234 1 1   3481 1 1
  3481 1 1   3481 1 1   3481 1 1   3481 1 1   3481 1 1}

do_execsql_test 5.2.11.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY a NULLS LAST GROUPS 6 PRECEDING   EXCLUDE CURRENT ROW  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {911 223 7   934 158 26   934 158 26   934 158 26   934 158 26   934 158 26
  934 158 33   934 223 7   934 223 7   934 223 7   934 223 7   934 223 7
  934 223 7   934 223 20   934 223 20   934 223 20   934 223 20   934 223 20
  934 223 20   934 223 20   934 223 20   934 223 20   934 223 20   934 223 20
  934 223 20   934 223 20   934 223 26   934 239 7   959 102 49   959 102 49
  959 102 49   959 102 49   959 102 49   959 102 49   959 102 49   959 102 49
  959 102 49   959 102 49   959 102 57   959 102 57   959 102 57   959 102 57
  959 102 57   959 102 57   959 102 57   959 102 57   959 113 38   959 113 38
  959 113 38   959 113 38   959 113 49   959 158 33   959 158 33   959 158 33
  959 158 33   959 158 33   959 158 33   959 158 38   963 102 58   979 102 49
  979 102 49   979 102 49   979 102 49   979 102 49   979 102 49   979 102 52
  979 102 52   979 102 52   979 102 52   979 102 52   979 102 52   979 102 52
  979 102 55   979 102 55   979 102 55   979 102 55   979 102 55   979 102 55
  979 102 55   979 102 55   979 102 55   979 102 58   979 102 58   979 102 58
  979 102 58   979 102 58   979 102 58   979 102 58   979 102 58}

do_execsql_test 5.2.11.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY a NULLS LAST GROUPS 6 PRECEDING   EXCLUDE CURRENT ROW  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {1398 1 1   1682 1 1   2000 1 1   2070 1 1   2086 1 1   2309 1 1   2309 1 1
  2309 1 1   5079 9 2   5085 9 2   5157 9 2   5391 9 2   5397 9 2   5397 9 2
  5543 9 2   5790 9 2   5790 9 2   5790 9 2   5790 9 2   5790 9 2   5790 9 2
  6397 22 3   6549 22 3   7156 22 3   7156 22 3   7156 22 3   7156 22 3
  8001 28 4   8115 28 4   8960 28 4   8960 28 4   8960 28 4   8960 28 4
  8960 28 4   9702 35 5   9850 35 5   10366 35 5   10479 35 5   10479 35 5
  10774 40 6   11146 40 6   11441 40 6   11441 40 6   11441 40 6   11441 40 6
  11441 40 6   11441 40 6   11441 40 6   11441 40 6   11441 40 6   11563 68 9
  11697 68 9   11776 51 7   11925 68 9   11947 68 9   12368 68 9   12368 68 9
  12368 68 9   12370 51 7   12530 59 8   12546 59 8   12705 51 7   12705 51 7
  12705 51 7   12705 51 7   12705 51 7   12705 51 7   12826 59 8
  13050 75 10   13110 75 10   13110 75 10   13154 59 8   13376 59 8
  13509 59 8   13509 59 8   13509 59 8   13509 59 8   13528 84 11
  13566 84 11   13692 75 10   13796 84 11   13836 75 10   13840 84 11
  13949 75 10   13949 75 10   13949 75 10   13949 75 10   14195 84 11
  14195 84 11}

do_execsql_test 5.2.12.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS LAST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING   EXCLUDE CURRENT ROW  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   113 113 1
  113 113 1   158 158 1   160 158 1   160 158 2   223 223 1   224 224 1
  238 234 2   239 234 2   239 238 2   252 250 2   256 252 2   257 247 4
  257 247 4   257 250 3   335 330 2   336 330 2   336 335 2   355 354 1
  355 354 2   355 355 1   399 393 3   399 393 3   399 393 3   399 393 3
  399 393 4   480 480 1   480 480 1   572 572 1   574 574 1   618 618 1
  618 618 1   633 629 2   634 627 3   634 627 3   634 627 4   634 629 3
  667 667 1   670 667 2   671 667 2   671 667 2   671 667 3   711 711 1
  711 711 1   716 705 2   726 726 1   730 730 1   762 762 1   768 759 3
  768 762 2   768 762 2   792 790 2   792 790 2   794 786 3   794 786 3
  844 839 4   845 839 4   845 839 4   845 839 4   845 839 4   870 870 1
  870 870 1   870 870 2   934 934 1   938 929 3   938 934 2   938 934 2
  959 959 1   963 963 1}

do_execsql_test 5.2.12.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS LAST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING   EXCLUDE CURRENT ROW  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} 1 1   {} 4 3   {} 5 4   {} 6 5   {} 6 5   {} 8 6   {} 9 7   {} 10 8
  {} 14 12   {} 15 13   {} 19 17   {} 20 18   {} 21 19   {} 23 21   {} 25 23
  {} 34 29   {} 35 30   {} 36 31   {} 37 32   {} 38 33   {} 38 33   {} 40 34
  {} 41 35   {} 42 36   {} 43 37   {} 43 37   {} 50 42   {} 56 47   {} 60 51
  {} 61 52   {} 62 53   {} 64 55   {} 64 55   {} 66 56   {} 67 57   {} 68 58
  {} 69 59   {} 70 60   {} 71 61   {} 72 62   {} 78 67   {} 78 67   {} 78 67
  {} 81 68   {} 82 69   {} 83 70   {} 85 72   {} 85 72   {} 89 75   113 2 2
  113 2 2   223 11 9   239 12 10   239 13 11   257 18 16   335 22 20
  335 24 22   355 27 25   355 27 25   504 16 14   504 17 15   705 58 49
  710 26 24   711 57 48   711 59 50   759 63 54   929 84 71   959 88 74
  963 87 73   1185 32 28   1185 32 28   1191 29 26   1191 29 26   1334 51 43
  1334 55 46   1338 52 44   1338 52 44   1584 31 27   1678 77 66   1684 73 63
  1684 73 63   1885 48 40   1889 46 39   1889 46 39   1891 45 38   1891 49 41
  2005 54 45   2523 75 64   2523 76 65}

do_execsql_test 5.2.13.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS LAST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING   EXCLUDE CURRENT ROW  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   113 113 1
  113 113 1   158 158 0   158 158 1   355 355 0   355 355 1   393 393 1
  393 393 1   399 399 0   399 399 1   480 480 1   480 480 1   618 618 1
  618 618 1   629 629 0   629 629 1   667 667 0   667 667 1   768 768 1
  768 768 1   839 839 1   839 839 1   870 870 1   870 870 1   870 870 2
  938 938 1   938 938 1}

do_execsql_test 5.2.13.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS LAST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING   EXCLUDE CURRENT ROW  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} 1 1   {} 4 3   {} 5 4   {} 6 5   {} 6 5   {} 8 6   {} 9 7   {} 10 8
  {} 11 9   {} 12 10   {} 13 11   {} 14 12   {} 15 13   {} 16 14   {} 17 15
  {} 18 16   {} 19 17   {} 20 18   {} 21 19   {} 22 20   {} 23 21   {} 24 22
  {} 25 23   {} 26 24   {} 31 27   {} 34 29   {} 35 30   {} 36 31   {} 37 32
  {} 38 33   {} 38 33   {} 40 34   {} 41 35   {} 42 36   {} 43 37   {} 43 37
  {} 45 38   {} 48 40   {} 49 41   {} 50 42   {} 51 43   {} 54 45   {} 55 46
  {} 56 47   {} 57 48   {} 58 49   {} 59 50   {} 60 51   {} 61 52   {} 62 53
  {} 63 54   {} 64 55   {} 64 55   {} 66 56   {} 67 57   {} 68 58   {} 69 59
  {} 70 60   {} 71 61   {} 72 62   {} 75 64   {} 76 65   {} 77 66   {} 78 67
  {} 78 67   {} 78 67   {} 81 68   {} 82 69   {} 83 70   {} 84 71   {} 85 72
  {} 85 72   {} 87 73   {} 88 74   {} 89 75   113 2 2   113 2 2   355 27 25
  355 27 25   393 29 26   393 29 26   399 32 28   399 32 28   629 46 39
  629 46 39   667 52 44   667 52 44   839 73 63   839 73 63}

do_execsql_test 5.2.14.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS LAST, b NULLS LAST, a NULLS LAST
        ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING   EXCLUDE CURRENT ROW  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {963 929 6   979 102 82   979 102 82   979 102 82   979 102 82   979 102 82
  979 102 83   979 113 80   979 113 81   979 113 82   979 133 79   979 148 78
  979 158 76   979 158 77   979 160 76   979 208 75   979 223 74   979 224 73
  979 234 72   979 238 71   979 239 70   979 247 69   979 250 68   979 252 67
  979 256 66   979 257 65   979 295 64   979 309 63   979 330 63   979 335 61
  979 336 60   979 346 59   979 354 58   979 355 56   979 355 58   979 393 55
  979 393 56   979 398 54   979 399 52   979 399 53   979 412 52   979 421 51
  979 430 50   979 443 49   979 480 47   979 480 48   979 572 46   979 574 46
  979 607 44   979 618 42   979 618 43   979 627 41   979 629 40   979 629 40
  979 633 39   979 634 38   979 652 37   979 660 36   979 667 34   979 667 35
  979 670 34   979 671 33   979 683 32   979 705 31   979 711 30   979 716 29
  979 726 28   979 730 27   979 759 26   979 762 25   979 768 23   979 768 24
  979 777 22   979 786 21   979 790 20   979 792 19   979 794 18   979 805 17
  979 822 16   979 839 15   979 839 15   979 840 13   979 844 12   979 845 11
  979 870 8   979 870 9   979 870 10   979 899 8   979 911 7}

do_execsql_test 5.2.14.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS LAST, b NULLS LAST, a NULLS LAST
        ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING   EXCLUDE CURRENT ROW  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {2851 89 89   3778 88 88   4681 87 87   5556 83 83   5574 82 82   5586 81 81
  5640 84 84   5640 85 85   5640 86 86   7324 80 80   8123 77 77   8129 73 73
  8129 74 74   8163 78 78   8163 79 79   8940 71 71   8968 75 75   8968 76 76
  9727 66 66   9745 69 69   9745 70 70   9745 72 72   10504 65 65
  10504 67 67   10504 68 68   11215 64 64   11844 62 62   11920 63 63
  13274 60 60   13274 61 61   13897 58 58   13903 57 57   13925 56 56
  13937 55 55   13941 59 59   15203 53 53   15241 54 54   15832 52 52
  17100 48 48   17104 46 46   17104 47 47   17106 45 45   17126 49 49
  17126 50 50   17126 51 51   17569 42 42   17733 44 44   18176 43 43
  18597 40 40   18597 41 41   18952 37 37   18996 39 39   19395 38 38
  19760 35 35   19788 36 36   20492 32 32   20492 33 33   20498 30 30
  20536 34 34   20833 29 29   20871 28 28   20891 31 31   21180 27 27
  21752 23 23   21830 26 26   22025 21 21   22087 22 22   22087 24 24
  22087 25 25   22278 20 20   22316 19 19   22549 15 15   22557 14 14
  22573 17 17   22573 18 18   22706 10 10   22796 11 11   22796 12 12
  22796 13 13   22796 16 16   23022 4 4   23042 2 2   23042 3 3   23042 9 9
  23155 1 1   23155 5 5   23155 6 6   23155 7 7   23155 8 8}

do_execsql_test 5.3.1.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE GROUP  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0}

do_execsql_test 5.3.1.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE GROUP  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1}

do_execsql_test 5.3.2.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY a NULLS FIRST 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE GROUP  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   899 113 9   899 113 9   899 113 9   899 113 9
  899 113 9   899 113 9   899 113 9   899 113 16   899 113 16   899 113 16
  899 113 16   899 113 16   899 113 16   899 113 16   899 113 16   899 113 16
  979 102 44   979 102 44   979 102 44   979 102 44   979 102 44   979 102 49
  979 102 49   979 102 49   979 102 49   979 102 49   979 102 49   979 102 49
  979 102 56   979 102 56   979 102 56   979 102 56   979 102 56   979 102 56
  979 102 62   979 102 62   979 102 62   979 102 62   979 102 62   979 102 62
  979 102 62   979 102 62   979 102 62   979 102 62   979 102 62   979 102 62
  979 102 62   979 102 75   979 102 75   979 102 75   979 102 75   979 102 75
  979 102 75   979 102 75   979 102 75   979 102 83   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 113 25   979 113 25   979 113 25
  979 113 25   979 113 25   979 113 25   979 113 25   979 113 25   979 113 33
  979 113 33   979 113 33   979 113 33   979 113 33   979 113 33   979 113 33
  979 113 33   979 113 33   979 113 33   979 113 33}

do_execsql_test 5.3.2.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY a NULLS FIRST 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE GROUP  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} 81 11   {} 81 11   {} 81 11   {} 81 11   {} 81 11   {} 81 11   {} 81 11
  {} 81 11   {} 81 11   2947 74 10   2947 74 10   2947 74 10   2947 74 10
  2947 74 10   2947 74 10   2947 74 10   5287 65 9   5287 65 9   5287 65 9
  5287 65 9   5287 65 9   5287 65 9   5287 65 9   5287 65 9   5287 65 9
  8400 57 8   8400 57 8   8400 57 8   8400 57 8   8400 57 8   8400 57 8
  8400 57 8   8400 57 8   9664 46 7   9664 46 7   9664 46 7   9664 46 7
  9664 46 7   9664 46 7   9664 46 7   9664 46 7   9664 46 7   9664 46 7
  9664 46 7   10626 41 6   10626 41 6   10626 41 6   10626 41 6   10626 41 6
  12145 34 5   12145 34 5   12145 34 5   12145 34 5   12145 34 5   12145 34 5
  12145 34 5   13949 28 4   13949 28 4   13949 28 4   13949 28 4   13949 28 4
  13949 28 4   15315 15 3   15315 15 3   15315 15 3   15315 15 3   15315 15 3
  15315 15 3   15315 15 3   15315 15 3   15315 15 3   15315 15 3   15315 15 3
  15315 15 3   15315 15 3   18796 7 2   18796 7 2   18796 7 2   18796 7 2
  18796 7 2   18796 7 2   18796 7 2   18796 7 2   21105 1 1   21105 1 1
  21105 1 1   21105 1 1   21105 1 1   21105 1 1}

do_execsql_test 5.3.3.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  PARTITION BY coalesce(a, '') 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE GROUP  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0}

do_execsql_test 5.3.3.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  PARTITION BY coalesce(a, '') 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE GROUP  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1}

do_execsql_test 5.3.4.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY a NULLS FIRST GROUPS 6 PRECEDING   EXCLUDE GROUP  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   870 158 0
  870 158 0   870 158 0   870 158 0   870 158 0   870 158 0   870 158 0
  870 158 0   934 158 8   934 158 8   934 158 8   934 158 8   934 158 8
  934 158 8   934 158 8   934 158 8   934 158 8   934 158 8   934 158 8
  934 158 8   934 158 8   934 158 21   934 158 21   934 158 21   934 158 21
  934 158 21   934 158 21   934 158 27   934 158 27   934 158 27   934 158 27
  934 158 27   934 158 27   934 158 27   959 102 50   959 102 50   959 102 50
  959 102 50   959 102 50   959 102 50   959 102 50   959 102 50   959 102 50
  959 102 50   959 102 50   959 102 50   959 102 50   959 102 50   959 102 50
  959 102 50   959 102 50   959 113 39   959 113 39   959 113 39   959 113 39
  959 113 39   959 113 39   959 113 39   959 113 39   959 113 39   959 113 39
  959 113 39   959 158 34   959 158 34   959 158 34   959 158 34   959 158 34
  979 102 46   979 102 46   979 102 46   979 102 46   979 102 46   979 102 46
  979 102 46   979 102 47   979 102 47   979 102 47   979 102 47   979 102 47
  979 102 47   979 102 47   979 102 47   979 102 47}

do_execsql_test 5.3.4.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY a NULLS FIRST GROUPS 6 PRECEDING   EXCLUDE GROUP  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   2050 7 2   2050 7 2
  2050 7 2   2050 7 2   2050 7 2   2050 7 2   2050 7 2   2050 7 2   4359 15 3
  4359 15 3   4359 15 3   4359 15 3   4359 15 3   4359 15 3   4359 15 3
  4359 15 3   4359 15 3   4359 15 3   4359 15 3   4359 15 3   4359 15 3
  7840 28 4   7840 28 4   7840 28 4   7840 28 4   7840 28 4   7840 28 4
  9206 34 5   9206 34 5   9206 34 5   9206 34 5   9206 34 5   9206 34 5
  9206 34 5   10028 74 10   10028 74 10   10028 74 10   10028 74 10
  10028 74 10   10028 74 10   10028 74 10   10396 65 9   10396 65 9
  10396 65 9   10396 65 9   10396 65 9   10396 65 9   10396 65 9   10396 65 9
  10396 65 9   11002 81 11   11002 81 11   11002 81 11   11002 81 11
  11002 81 11   11002 81 11   11002 81 11   11002 81 11   11002 81 11
  11010 41 6   11010 41 6   11010 41 6   11010 41 6   11010 41 6   11441 57 8
  11441 57 8   11441 57 8   11441 57 8   11441 57 8   11441 57 8   11441 57 8
  11441 57 8   12529 46 7   12529 46 7   12529 46 7   12529 46 7   12529 46 7
  12529 46 7   12529 46 7   12529 46 7   12529 46 7   12529 46 7   12529 46 7}

do_execsql_test 5.3.5.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS FIRST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING   EXCLUDE GROUP  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   158 158 1   160 160 1   160 160 1   223 223 1   224 224 1
  238 234 2   239 234 2   239 238 2   252 250 2   256 252 2   257 247 4
  257 247 4   257 250 3   335 330 2   336 330 2   336 335 2   354 354 1
  354 354 1   355 355 1   398 393 3   398 393 3   399 393 3   399 398 2
  399 398 2   572 572 1   574 574 1   633 629 2   634 627 3   634 627 3
  634 627 3   634 629 3   667 667 1   670 667 2   671 667 2   671 670 2
  671 670 2   711 711 1   711 711 1   716 705 2   726 726 1   730 730 1
  762 762 1   762 762 1   762 762 1   768 759 3   792 790 2   792 790 2
  794 786 3   794 786 3   844 839 4   845 839 4   845 839 4   845 840 3
  845 840 3   934 934 1   934 934 1   934 934 1   938 929 3   959 959 1
  963 963 1}

do_execsql_test 5.3.5.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS FIRST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING   EXCLUDE GROUP  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} 1 1   {} 2 2   {} 2 2   {} 4 3   {} 5 4   {} 6 5   {} 6 5   {} 8 6
  {} 9 7   {} 10 8   {} 14 12   {} 15 13   {} 19 17   {} 20 18   {} 21 19
  {} 23 21   {} 25 23   {} 27 25   {} 27 25   {} 34 29   {} 35 30   {} 36 31
  {} 37 32   {} 38 33   {} 38 33   {} 40 34   {} 41 35   {} 42 36   {} 43 37
  {} 43 37   {} 50 42   {} 56 47   {} 60 51   {} 61 52   {} 62 53   {} 64 55
  {} 64 55   {} 66 56   {} 67 57   {} 68 58   {} 69 59   {} 70 60   {} 71 61
  {} 72 62   {} 78 67   {} 78 67   {} 78 67   {} 81 68   {} 82 69   {} 83 70
  {} 85 72   {} 85 72   {} 89 75   223 11 9   239 12 10   239 13 11
  257 18 16   335 22 20   335 24 22   504 16 14   504 17 15   671 52 44
  671 52 44   705 58 49   710 26 24   711 57 48   711 59 50   759 63 54
  786 32 28   786 32 28   798 29 26   798 29 26   845 73 63   845 73 63
  929 84 71   959 88 74   963 87 73   1260 46 39   1260 46 39   1334 51 43
  1334 55 46   1584 31 27   1678 77 66   1885 48 40   1891 45 38   1891 49 41
  2005 54 45   2523 75 64   2523 76 65}

do_execsql_test 5.3.6.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS FIRST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING   EXCLUDE GROUP  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0}

do_execsql_test 5.3.6.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS FIRST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING   EXCLUDE GROUP  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} 1 1   {} 2 2   {} 2 2   {} 4 3   {} 5 4   {} 6 5   {} 6 5   {} 8 6
  {} 9 7   {} 10 8   {} 11 9   {} 12 10   {} 13 11   {} 14 12   {} 15 13
  {} 16 14   {} 17 15   {} 18 16   {} 19 17   {} 20 18   {} 21 19   {} 22 20
  {} 23 21   {} 24 22   {} 25 23   {} 26 24   {} 27 25   {} 27 25   {} 29 26
  {} 29 26   {} 31 27   {} 32 28   {} 32 28   {} 34 29   {} 35 30   {} 36 31
  {} 37 32   {} 38 33   {} 38 33   {} 40 34   {} 41 35   {} 42 36   {} 43 37
  {} 43 37   {} 45 38   {} 46 39   {} 46 39   {} 48 40   {} 49 41   {} 50 42
  {} 51 43   {} 52 44   {} 52 44   {} 54 45   {} 55 46   {} 56 47   {} 57 48
  {} 58 49   {} 59 50   {} 60 51   {} 61 52   {} 62 53   {} 63 54   {} 64 55
  {} 64 55   {} 66 56   {} 67 57   {} 68 58   {} 69 59   {} 70 60   {} 71 61
  {} 72 62   {} 73 63   {} 73 63   {} 75 64   {} 76 65   {} 77 66   {} 78 67
  {} 78 67   {} 78 67   {} 81 68   {} 82 69   {} 83 70   {} 84 71   {} 85 72
  {} 85 72   {} 87 73   {} 88 74   {} 89 75}

do_execsql_test 5.3.7.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS FIRST, b NULLS FIRST, a NULLS FIRST
        ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING   EXCLUDE GROUP  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {963 929 6   979 102 82   979 102 82   979 102 82   979 102 82   979 102 82
  979 102 83   979 113 80   979 113 81   979 113 82   979 133 79   979 148 78
  979 158 76   979 158 77   979 160 76   979 208 75   979 223 74   979 224 73
  979 234 72   979 238 71   979 239 70   979 247 69   979 250 68   979 252 67
  979 256 66   979 257 65   979 295 64   979 309 64   979 330 62   979 335 61
  979 336 60   979 346 59   979 354 59   979 355 57   979 355 57   979 393 55
  979 393 56   979 398 54   979 399 53   979 399 53   979 412 52   979 421 51
  979 430 50   979 443 49   979 480 47   979 480 48   979 572 47   979 574 45
  979 607 44   979 618 42   979 618 43   979 627 41   979 629 40   979 629 41
  979 633 39   979 634 38   979 652 37   979 660 36   979 667 35   979 667 35
  979 670 34   979 671 33   979 683 32   979 705 31   979 711 30   979 716 29
  979 726 28   979 730 27   979 759 26   979 762 25   979 768 23   979 768 24
  979 777 22   979 786 21   979 790 20   979 792 19   979 794 18   979 805 17
  979 822 17   979 839 14   979 839 15   979 840 13   979 844 12   979 845 11
  979 870 9   979 870 10   979 870 10   979 899 8   979 911 7}

do_execsql_test 5.3.7.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS FIRST, b NULLS FIRST, a NULLS FIRST
        ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING   EXCLUDE GROUP  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {2851 89 89   3778 88 88   4681 87 87   5556 83 83   5574 82 82   5586 81 81
  5640 84 84   5640 85 85   5640 86 86   7324 80 80   8123 77 77   8129 73 73
  8129 74 74   8163 78 78   8163 79 79   8940 71 71   8968 75 75   8968 76 76
  9727 66 66   9745 69 69   9745 70 70   9745 72 72   10504 65 65
  10504 67 67   10504 68 68   11215 64 64   11844 62 62   11920 63 63
  13274 60 60   13274 61 61   13897 58 58   13903 57 57   13925 56 56
  13937 55 55   13941 59 59   15203 53 53   15241 54 54   15832 52 52
  17100 48 48   17104 46 46   17104 47 47   17106 45 45   17126 49 49
  17126 50 50   17126 51 51   17569 42 42   17733 44 44   18176 43 43
  18597 40 40   18597 41 41   18952 37 37   18996 39 39   19395 38 38
  19760 35 35   19788 36 36   20492 32 32   20492 33 33   20498 30 30
  20536 34 34   20833 29 29   20871 28 28   20891 31 31   21180 27 27
  21752 23 23   21830 26 26   22025 21 21   22087 22 22   22087 24 24
  22087 25 25   22278 20 20   22316 19 19   22549 15 15   22557 14 14
  22573 17 17   22573 18 18   22706 10 10   22796 11 11   22796 12 12
  22796 13 13   22796 16 16   23022 4 4   23042 2 2   23042 3 3   23042 9 9
  23155 1 1   23155 5 5   23155 6 6   23155 7 7   23155 8 8}

do_execsql_test 5.3.8.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE GROUP  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0}

do_execsql_test 5.3.8.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE GROUP  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1}

do_execsql_test 5.3.9.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY a NULLS LAST 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE GROUP  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   870 158 0
  870 158 0   870 158 0   870 158 0   870 158 0   870 158 0   870 158 0
  870 158 0   870 158 0   899 113 9   899 113 9   899 113 9   899 113 9
  899 113 9   899 113 9   899 113 9   899 113 16   899 113 16   899 113 16
  899 113 16   899 113 16   899 113 16   899 113 16   899 113 16   899 113 16
  979 102 44   979 102 44   979 102 44   979 102 44   979 102 44   979 102 49
  979 102 49   979 102 49   979 102 49   979 102 49   979 102 49   979 102 49
  979 102 56   979 102 56   979 102 56   979 102 56   979 102 56   979 102 56
  979 102 62   979 102 62   979 102 62   979 102 62   979 102 62   979 102 62
  979 102 62   979 102 62   979 102 62   979 102 62   979 102 62   979 102 62
  979 102 62   979 102 75   979 102 75   979 102 75   979 102 75   979 102 75
  979 102 75   979 102 75   979 102 75   979 113 25   979 113 25   979 113 25
  979 113 25   979 113 25   979 113 25   979 113 25   979 113 25   979 113 33
  979 113 33   979 113 33   979 113 33   979 113 33   979 113 33   979 113 33
  979 113 33   979 113 33   979 113 33   979 113 33}

do_execsql_test 5.3.9.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY a NULLS LAST 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE GROUP  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} 84 11   {} 84 11   {} 84 11   {} 84 11   {} 84 11   {} 84 11
  2050 75 10   2050 75 10   2050 75 10   2050 75 10   2050 75 10   2050 75 10
  2050 75 10   2050 75 10   2050 75 10   4997 68 9   4997 68 9   4997 68 9
  4997 68 9   4997 68 9   4997 68 9   4997 68 9   7337 59 8   7337 59 8
  7337 59 8   7337 59 8   7337 59 8   7337 59 8   7337 59 8   7337 59 8
  7337 59 8   10450 51 7   10450 51 7   10450 51 7   10450 51 7   10450 51 7
  10450 51 7   10450 51 7   10450 51 7   11714 40 6   11714 40 6   11714 40 6
  11714 40 6   11714 40 6   11714 40 6   11714 40 6   11714 40 6   11714 40 6
  11714 40 6   11714 40 6   12676 35 5   12676 35 5   12676 35 5   12676 35 5
  12676 35 5   14195 28 4   14195 28 4   14195 28 4   14195 28 4   14195 28 4
  14195 28 4   14195 28 4   15999 22 3   15999 22 3   15999 22 3   15999 22 3
  15999 22 3   15999 22 3   17365 9 2   17365 9 2   17365 9 2   17365 9 2
  17365 9 2   17365 9 2   17365 9 2   17365 9 2   17365 9 2   17365 9 2
  17365 9 2   17365 9 2   17365 9 2   20846 1 1   20846 1 1   20846 1 1
  20846 1 1   20846 1 1   20846 1 1   20846 1 1   20846 1 1}

do_execsql_test 5.3.10.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  PARTITION BY coalesce(a, '') 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE GROUP  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0}

do_execsql_test 5.3.10.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  PARTITION BY coalesce(a, '') 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE GROUP  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1}

do_execsql_test 5.3.11.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY a NULLS LAST GROUPS 6 PRECEDING   EXCLUDE GROUP  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   934 158 27   934 158 27   934 158 27   934 158 27   934 158 27
  934 158 27   934 158 27   934 223 8   934 223 8   934 223 8   934 223 8
  934 223 8   934 223 8   934 223 8   934 223 8   934 223 8   934 223 8
  934 223 8   934 223 8   934 223 8   934 223 21   934 223 21   934 223 21
  934 223 21   934 223 21   934 223 21   959 102 50   959 102 50   959 102 50
  959 102 50   959 102 50   959 102 50   959 102 50   959 102 50   959 102 50
  959 102 50   959 102 50   959 102 50   959 102 50   959 102 50   959 102 50
  959 102 50   959 102 50   959 113 39   959 113 39   959 113 39   959 113 39
  959 113 39   959 113 39   959 113 39   959 113 39   959 113 39   959 113 39
  959 113 39   959 158 34   959 158 34   959 158 34   959 158 34   959 158 34
  979 102 46   979 102 46   979 102 46   979 102 46   979 102 46   979 102 46
  979 102 46   979 102 47   979 102 47   979 102 47   979 102 47   979 102 47
  979 102 47   979 102 47   979 102 47   979 102 47   979 102 49   979 102 49
  979 102 49   979 102 49   979 102 49   979 102 49}

do_execsql_test 5.3.11.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY a NULLS LAST GROUPS 6 PRECEDING   EXCLUDE GROUP  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  2309 9 2   2309 9 2   2309 9 2   2309 9 2   2309 9 2   2309 9 2   2309 9 2
  2309 9 2   2309 9 2   2309 9 2   2309 9 2   2309 9 2   2309 9 2   5790 22 3
  5790 22 3   5790 22 3   5790 22 3   5790 22 3   5790 22 3   7156 28 4
  7156 28 4   7156 28 4   7156 28 4   7156 28 4   7156 28 4   7156 28 4
  8960 35 5   8960 35 5   8960 35 5   8960 35 5   8960 35 5   10028 68 9
  10028 68 9   10028 68 9   10028 68 9   10028 68 9   10028 68 9   10028 68 9
  10396 59 8   10396 59 8   10396 59 8   10396 59 8   10396 59 8   10396 59 8
  10396 59 8   10396 59 8   10396 59 8   10479 40 6   10479 40 6   10479 40 6
  10479 40 6   10479 40 6   10479 40 6   10479 40 6   10479 40 6   10479 40 6
  10479 40 6   10479 40 6   11002 75 10   11002 75 10   11002 75 10
  11002 75 10   11002 75 10   11002 75 10   11002 75 10   11002 75 10
  11002 75 10   11441 51 7   11441 51 7   11441 51 7   11441 51 7
  11441 51 7   11441 51 7   11441 51 7   11441 51 7   12145 84 11
  12145 84 11   12145 84 11   12145 84 11   12145 84 11   12145 84 11}

do_execsql_test 5.3.12.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS LAST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING   EXCLUDE GROUP  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   158 158 1   160 160 1   160 160 1   223 223 1   224 224 1
  238 234 2   239 234 2   239 238 2   252 250 2   256 252 2   257 247 4
  257 247 4   257 250 3   335 330 2   336 330 2   336 335 2   354 354 1
  354 354 1   355 355 1   398 393 3   398 393 3   399 393 3   399 398 2
  399 398 2   572 572 1   574 574 1   633 629 2   634 627 3   634 627 3
  634 627 3   634 629 3   667 667 1   670 667 2   671 667 2   671 670 2
  671 670 2   711 711 1   711 711 1   716 705 2   726 726 1   730 730 1
  762 762 1   762 762 1   762 762 1   768 759 3   792 790 2   792 790 2
  794 786 3   794 786 3   844 839 4   845 839 4   845 839 4   845 840 3
  845 840 3   934 934 1   934 934 1   934 934 1   938 929 3   959 959 1
  963 963 1}

do_execsql_test 5.3.12.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS LAST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING   EXCLUDE GROUP  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} 1 1   {} 2 2   {} 2 2   {} 4 3   {} 5 4   {} 6 5   {} 6 5   {} 8 6
  {} 9 7   {} 10 8   {} 14 12   {} 15 13   {} 19 17   {} 20 18   {} 21 19
  {} 23 21   {} 25 23   {} 27 25   {} 27 25   {} 34 29   {} 35 30   {} 36 31
  {} 37 32   {} 38 33   {} 38 33   {} 40 34   {} 41 35   {} 42 36   {} 43 37
  {} 43 37   {} 50 42   {} 56 47   {} 60 51   {} 61 52   {} 62 53   {} 64 55
  {} 64 55   {} 66 56   {} 67 57   {} 68 58   {} 69 59   {} 70 60   {} 71 61
  {} 72 62   {} 78 67   {} 78 67   {} 78 67   {} 81 68   {} 82 69   {} 83 70
  {} 85 72   {} 85 72   {} 89 75   223 11 9   239 12 10   239 13 11
  257 18 16   335 22 20   335 24 22   504 16 14   504 17 15   671 52 44
  671 52 44   705 58 49   710 26 24   711 57 48   711 59 50   759 63 54
  786 32 28   786 32 28   798 29 26   798 29 26   845 73 63   845 73 63
  929 84 71   959 88 74   963 87 73   1260 46 39   1260 46 39   1334 51 43
  1334 55 46   1584 31 27   1678 77 66   1885 48 40   1891 45 38   1891 49 41
  2005 54 45   2523 75 64   2523 76 65}

do_execsql_test 5.3.13.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS LAST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING   EXCLUDE GROUP  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0
  {} {} 0   {} {} 0   {} {} 0   {} {} 0   {} {} 0}

do_execsql_test 5.3.13.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS LAST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING   EXCLUDE GROUP  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} 1 1   {} 2 2   {} 2 2   {} 4 3   {} 5 4   {} 6 5   {} 6 5   {} 8 6
  {} 9 7   {} 10 8   {} 11 9   {} 12 10   {} 13 11   {} 14 12   {} 15 13
  {} 16 14   {} 17 15   {} 18 16   {} 19 17   {} 20 18   {} 21 19   {} 22 20
  {} 23 21   {} 24 22   {} 25 23   {} 26 24   {} 27 25   {} 27 25   {} 29 26
  {} 29 26   {} 31 27   {} 32 28   {} 32 28   {} 34 29   {} 35 30   {} 36 31
  {} 37 32   {} 38 33   {} 38 33   {} 40 34   {} 41 35   {} 42 36   {} 43 37
  {} 43 37   {} 45 38   {} 46 39   {} 46 39   {} 48 40   {} 49 41   {} 50 42
  {} 51 43   {} 52 44   {} 52 44   {} 54 45   {} 55 46   {} 56 47   {} 57 48
  {} 58 49   {} 59 50   {} 60 51   {} 61 52   {} 62 53   {} 63 54   {} 64 55
  {} 64 55   {} 66 56   {} 67 57   {} 68 58   {} 69 59   {} 70 60   {} 71 61
  {} 72 62   {} 73 63   {} 73 63   {} 75 64   {} 76 65   {} 77 66   {} 78 67
  {} 78 67   {} 78 67   {} 81 68   {} 82 69   {} 83 70   {} 84 71   {} 85 72
  {} 85 72   {} 87 73   {} 88 74   {} 89 75}

do_execsql_test 5.3.14.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS LAST, b NULLS LAST, a NULLS LAST
        ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING   EXCLUDE GROUP  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {963 929 6   979 102 82   979 102 82   979 102 82   979 102 82   979 102 82
  979 102 83   979 113 80   979 113 81   979 113 82   979 133 79   979 148 78
  979 158 76   979 158 77   979 160 76   979 208 75   979 223 74   979 224 73
  979 234 72   979 238 71   979 239 70   979 247 69   979 250 68   979 252 67
  979 256 66   979 257 65   979 295 64   979 309 63   979 330 63   979 335 61
  979 336 60   979 346 59   979 354 58   979 355 56   979 355 58   979 393 55
  979 393 56   979 398 54   979 399 52   979 399 53   979 412 52   979 421 51
  979 430 50   979 443 49   979 480 47   979 480 48   979 572 46   979 574 46
  979 607 44   979 618 42   979 618 43   979 627 41   979 629 40   979 629 40
  979 633 39   979 634 38   979 652 37   979 660 36   979 667 34   979 667 35
  979 670 34   979 671 33   979 683 32   979 705 31   979 711 30   979 716 29
  979 726 28   979 730 27   979 759 26   979 762 25   979 768 23   979 768 24
  979 777 22   979 786 21   979 790 20   979 792 19   979 794 18   979 805 17
  979 822 16   979 839 15   979 839 15   979 840 13   979 844 12   979 845 11
  979 870 8   979 870 9   979 870 10   979 899 8   979 911 7}

do_execsql_test 5.3.14.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS LAST, b NULLS LAST, a NULLS LAST
        ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING   EXCLUDE GROUP  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {2851 89 89   3778 88 88   4681 87 87   5556 83 83   5574 82 82   5586 81 81
  5640 84 84   5640 85 85   5640 86 86   7324 80 80   8123 77 77   8129 73 73
  8129 74 74   8163 78 78   8163 79 79   8940 71 71   8968 75 75   8968 76 76
  9727 66 66   9745 69 69   9745 70 70   9745 72 72   10504 65 65
  10504 67 67   10504 68 68   11215 64 64   11844 62 62   11920 63 63
  13274 60 60   13274 61 61   13897 58 58   13903 57 57   13925 56 56
  13937 55 55   13941 59 59   15203 53 53   15241 54 54   15832 52 52
  17100 48 48   17104 46 46   17104 47 47   17106 45 45   17126 49 49
  17126 50 50   17126 51 51   17569 42 42   17733 44 44   18176 43 43
  18597 40 40   18597 41 41   18952 37 37   18996 39 39   19395 38 38
  19760 35 35   19788 36 36   20492 32 32   20492 33 33   20498 30 30
  20536 34 34   20833 29 29   20871 28 28   20891 31 31   21180 27 27
  21752 23 23   21830 26 26   22025 21 21   22087 22 22   22087 24 24
  22087 25 25   22278 20 20   22316 19 19   22549 15 15   22557 14 14
  22573 17 17   22573 18 18   22706 10 10   22796 11 11   22796 12 12
  22796 13 13   22796 16 16   23022 4 4   23042 2 2   23042 3 3   23042 9 9
  23155 1 1   23155 5 5   23155 6 6   23155 7 7   23155 8 8}

do_execsql_test 5.4.1.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE TIES  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {102 102 1   113 113 1   113 113 1   133 133 1   148 148 1   158 158 0
  158 158 1   160 160 1   208 208 1   223 223 1   224 224 1   234 234 1
  238 238 1   239 239 1   247 247 1   250 250 1   252 252 1   256 256 1
  257 257 1   295 295 1   309 309 1   330 330 1   335 335 1   336 336 1
  346 346 1   354 354 1   355 355 0   355 355 1   393 393 1   393 393 1
  398 398 1   399 399 0   399 399 1   412 412 1   421 421 1   430 430 1
  443 443 1   480 480 1   480 480 1   572 572 1   574 574 1   607 607 1
  618 618 1   618 618 1   627 627 1   629 629 0   629 629 1   633 633 1
  634 634 1   652 652 1   660 660 1   667 667 0   667 667 1   670 670 1
  671 671 1   683 683 1   705 705 1   711 711 1   716 716 1   726 726 1
  730 730 1   759 759 1   762 762 1   768 768 1   768 768 1   777 777 1
  786 786 1   790 790 1   792 792 1   794 794 1   805 805 1   822 822 1
  839 839 1   839 839 1   840 840 1   844 844 1   845 845 1   870 870 0
  870 870 1   870 870 1   899 899 1   911 911 1   929 929 1   934 934 1
  938 938 1   938 938 1   959 959 1   963 963 1   979 979 1}

do_execsql_test 5.4.1.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE TIES  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  113 1 1   113 1 1   133 1 1   223 1 1   239 1 1   247 1 1   257 1 1
  295 1 1   309 1 1   335 1 1   355 1 1   355 1 1   393 1 1   393 1 1
  399 1 1   399 1 1   421 1 1   443 1 1   607 1 1   627 1 1   629 1 1
  629 1 1   633 1 1   667 1 1   667 1 1   671 1 1   683 1 1   705 1 1
  711 1 1   759 1 1   777 1 1   805 1 1   839 1 1   839 1 1   845 1 1
  899 1 1   911 1 1   929 1 1   959 1 1   963 1 1   979 1 1}

do_execsql_test 5.4.2.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY a NULLS FIRST 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE TIES  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {113 113 1   234 234 1   257 257 1   336 336 1   354 354 1   768 768 1
  839 839 1   839 839 1   899 113 10   899 113 10   899 113 10   899 113 10
  899 113 10   899 113 10   899 113 10   899 113 17   899 113 17   899 113 17
  899 113 17   899 113 17   899 113 17   899 113 17   899 899 1   963 113 17
  979 102 34   979 102 45   979 102 45   979 102 45   979 102 45   979 102 45
  979 102 50   979 102 50   979 102 50   979 102 50   979 102 50   979 102 50
  979 102 50   979 102 57   979 102 57   979 102 57   979 102 57   979 102 57
  979 102 57   979 102 63   979 102 63   979 102 63   979 102 63   979 102 63
  979 102 63   979 102 63   979 102 63   979 102 63   979 102 63   979 102 63
  979 102 63   979 102 63   979 102 76   979 102 76   979 102 76   979 102 76
  979 102 76   979 102 76   979 102 76   979 102 76   979 102 83   979 102 83
  979 102 83   979 102 83   979 102 83   979 102 83   979 113 17   979 113 26
  979 113 26   979 113 26   979 113 26   979 113 26   979 113 26   979 113 26
  979 113 26   979 113 34   979 113 34   979 113 34   979 113 34   979 113 34
  979 113 34   979 113 34   979 113 34   979 113 34   979 113 34}

do_execsql_test 5.4.2.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY a NULLS FIRST 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE TIES  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} 81 11   {} 81 11   {} 81 11   {} 81 11   113 81 11   257 81 11
  839 81 11   839 81 11   899 81 11   2947 74 10   2947 74 10   2947 74 10
  3368 74 10   3390 74 10   3618 74 10   3752 74 10   5287 65 9   5287 65 9
  5287 65 9   5287 65 9   5420 65 9   5642 65 9   5970 65 9   6250 65 9
  6266 65 9   8400 57 8   8400 57 8   8400 57 8   8400 57 8   8400 57 8
  8400 57 8   8735 57 8   9329 57 8   9664 46 7   9664 46 7   9664 46 7
  9664 46 7   9664 46 7   9664 46 7   9664 46 7   9664 46 7   9664 46 7
  9959 46 7   10331 46 7   10626 41 6   10626 41 6   10739 41 6   11255 41 6
  11403 41 6   12145 34 5   12145 34 5   12145 34 5   12145 34 5   12145 34 5
  12990 34 5   13104 34 5   13949 28 4   13949 28 4   13949 28 4   13949 28 4
  14556 28 4   14708 28 4   15315 15 3   15315 15 3   15315 15 3   15315 15 3
  15315 15 3   15315 15 3   15562 15 3   15708 15 3   15708 15 3   15714 15 3
  15948 15 3   16020 15 3   16026 15 3   18796 7 2   18796 7 2   18796 7 2
  19019 7 2   19035 7 2   19105 7 2   19423 7 2   19707 7 2   21105 1 1
  21105 1 1   21460 1 1   21504 1 1   21734 1 1   21772 1 1}

do_execsql_test 5.4.3.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  PARTITION BY coalesce(a, '') 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE TIES  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {102 102 1   113 113 1   113 113 1   133 133 1   148 148 1   158 158 0
  158 158 1   160 160 1   208 208 1   223 223 1   224 224 1   234 234 1
  238 238 1   239 239 1   247 247 1   250 250 1   252 252 1   256 256 1
  257 257 1   295 295 1   309 309 1   330 330 1   335 335 1   336 336 1
  346 346 1   354 354 1   355 355 0   355 355 1   393 393 1   393 393 1
  398 398 1   399 399 0   399 399 1   412 412 1   421 421 1   430 430 1
  443 443 1   480 480 1   480 480 1   572 572 1   574 574 1   607 607 1
  618 618 1   618 618 1   627 627 1   629 629 0   629 629 1   633 633 1
  634 634 1   652 652 1   660 660 1   667 667 0   667 667 1   670 670 1
  671 671 1   683 683 1   705 705 1   711 711 1   716 716 1   726 726 1
  730 730 1   759 759 1   762 762 1   768 768 1   768 768 1   777 777 1
  786 786 1   790 790 1   792 792 1   794 794 1   805 805 1   822 822 1
  839 839 1   839 839 1   840 840 1   844 844 1   845 845 1   870 870 0
  870 870 1   870 870 1   899 899 1   911 911 1   929 929 1   934 934 1
  938 938 1   938 938 1   959 959 1   963 963 1   979 979 1}

do_execsql_test 5.4.3.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  PARTITION BY coalesce(a, '') 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE TIES  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  113 1 1   113 1 1   133 1 1   223 1 1   239 1 1   247 1 1   257 1 1
  295 1 1   309 1 1   335 1 1   355 1 1   355 1 1   393 1 1   393 1 1
  399 1 1   399 1 1   421 1 1   443 1 1   607 1 1   627 1 1   629 1 1
  629 1 1   633 1 1   667 1 1   667 1 1   671 1 1   683 1 1   705 1 1
  711 1 1   759 1 1   777 1 1   805 1 1   839 1 1   839 1 1   845 1 1
  899 1 1   911 1 1   929 1 1   959 1 1   963 1 1   979 1 1}

do_execsql_test 5.4.4.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY a NULLS FIRST GROUPS 6 PRECEDING   EXCLUDE TIES  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {158 158 0   355 355 0   399 399 0   629 629 0   667 667 0   870 158 1
  870 158 1   870 158 1   870 158 1   870 158 1   870 158 1   870 870 0
  911 158 1   934 158 1   934 158 9   934 158 9   934 158 9   934 158 9
  934 158 9   934 158 9   934 158 9   934 158 9   934 158 9   934 158 9
  934 158 9   934 158 9   934 158 9   934 158 22   934 158 22   934 158 22
  934 158 22   934 158 22   934 158 22   934 158 28   934 158 28   934 158 28
  934 158 28   934 158 28   934 158 28   959 102 40   959 102 51   959 102 51
  959 102 51   959 102 51   959 102 51   959 102 51   959 102 51   959 102 51
  959 102 51   959 102 51   959 102 51   959 102 51   959 102 51   959 102 51
  959 102 51   959 113 35   959 113 40   959 113 40   959 113 40   959 113 40
  959 113 40   959 113 40   959 113 40   959 113 40   959 113 40   959 113 40
  959 158 28   959 158 35   959 158 35   959 158 35   959 158 35   963 102 51
  979 102 47   979 102 47   979 102 47   979 102 47   979 102 47   979 102 47
  979 102 47   979 102 48   979 102 48   979 102 48   979 102 48   979 102 48
  979 102 48   979 102 48   979 102 48   979 102 48   979 102 51}

do_execsql_test 5.4.4.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY a NULLS FIRST GROUPS 6 PRECEDING   EXCLUDE TIES  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} 1 1   {} 1 1   355 1 1   399 1 1   629 1 1   667 1 1   2050 7 2
  2050 7 2   2050 7 2   2273 7 2   2289 7 2   2359 7 2   2677 7 2   2961 7 2
  4359 15 3   4359 15 3   4359 15 3   4359 15 3   4359 15 3   4359 15 3
  4606 15 3   4752 15 3   4752 15 3   4758 15 3   4992 15 3   5064 15 3
  5070 15 3   7840 28 4   7840 28 4   7840 28 4   7840 28 4   8447 28 4
  8599 28 4   9206 34 5   9206 34 5   9206 34 5   9206 34 5   9206 34 5
  10028 74 10   10028 74 10   10028 74 10   10051 34 5   10165 34 5
  10396 65 9   10396 65 9   10396 65 9   10396 65 9   10449 74 10
  10471 74 10   10529 65 9   10699 74 10   10751 65 9   10833 74 10
  11002 81 11   11002 81 11   11002 81 11   11002 81 11   11010 41 6
  11010 41 6   11079 65 9   11115 81 11   11123 41 6   11259 81 11
  11359 65 9   11375 65 9   11441 57 8   11441 57 8   11441 57 8   11441 57 8
  11441 57 8   11441 57 8   11639 41 6   11776 57 8   11787 41 6
  11841 81 11   11841 81 11   11901 81 11   12370 57 8   12529 46 7
  12529 46 7   12529 46 7   12529 46 7   12529 46 7   12529 46 7   12529 46 7
  12529 46 7   12529 46 7   12824 46 7   13196 46 7}

do_execsql_test 5.4.5.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS FIRST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING   EXCLUDE TIES  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {102 102 1   113 113 1   113 113 1   133 133 1   148 148 1   160 158 1
  160 158 2   160 158 2   208 208 1   224 223 2   224 223 2   239 234 3
  239 234 3   239 234 3   252 247 3   257 247 5   257 247 5   257 250 4
  257 252 3   295 295 1   309 309 1   336 330 3   336 330 3   336 330 3
  346 346 1   355 354 1   355 354 2   355 354 2   399 393 3   399 393 3
  399 393 3   399 393 4   399 393 4   412 412 1   421 421 1   430 430 1
  443 443 1   480 480 1   480 480 1   574 572 2   574 572 2   607 607 1
  618 618 1   618 618 1   634 627 3   634 627 4   634 627 4   634 627 4
  634 629 3   652 652 1   667 660 2   671 667 2   671 667 3   671 667 3
  671 667 3   683 683 1   711 705 2   716 705 3   716 711 2   730 726 2
  730 726 2   762 759 2   768 759 4   768 762 2   768 762 2   777 777 1
  792 786 3   794 786 4   794 786 4   794 790 3   805 805 1   822 822 1
  845 839 4   845 839 4   845 839 5   845 839 5   845 839 5   870 870 0
  870 870 1   870 870 1   899 899 1   911 911 1   934 929 2   938 929 4
  938 934 2   938 934 2   963 959 2   963 959 2   979 979 1}

do_execsql_test 5.4.5.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS FIRST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING   EXCLUDE TIES  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} 1 1   {} 5 4   {} 6 5   {} 6 5   {} 8 6   {} 9 7   {} 25 23   {} 34 29
  {} 36 31   {} 38 33   {} 38 33   {} 40 34   {} 41 35   {} 43 37   {} 43 37
  {} 50 42   {} 60 51   {} 61 52   {} 64 55   {} 64 55   {} 67 57   {} 68 58
  {} 69 59   {} 70 60   {} 72 62   {} 78 67   {} 78 67   {} 78 67   {} 85 72
  {} 85 72   113 2 2   113 2 2   133 4 3   223 10 8   223 11 9   239 12 10
  239 13 11   239 14 12   247 15 13   257 18 16   257 19 17   295 20 18
  309 21 19   335 22 20   335 23 21   335 24 22   355 27 25   355 27 25
  421 35 30   443 37 32   504 16 14   504 17 15   607 42 36   683 56 47
  710 26 24   711 59 50   759 62 53   759 63 54   777 66 56   805 71 61
  899 81 68   911 82 69   929 83 70   929 84 71   979 89 75   1185 32 28
  1185 32 28   1191 29 26   1191 29 26   1334 51 43   1338 52 44   1338 52 44
  1416 57 48   1416 58 49   1584 31 27   1684 73 63   1684 73 63   1889 46 39
  1889 46 39   1891 49 41   1922 87 73   1922 88 74   2005 54 45   2005 55 46
  2518 45 38   2518 48 40   2523 75 64   2523 76 65   2523 77 66}

do_execsql_test 5.4.6.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS FIRST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING   EXCLUDE TIES  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {102 102 1   113 113 1   113 113 1   133 133 1   148 148 1   158 158 0
  158 158 1   160 160 1   208 208 1   223 223 1   224 224 1   234 234 1
  238 238 1   239 239 1   247 247 1   250 250 1   252 252 1   256 256 1
  257 257 1   295 295 1   309 309 1   330 330 1   335 335 1   336 336 1
  346 346 1   354 354 1   355 355 0   355 355 1   393 393 1   393 393 1
  398 398 1   399 399 0   399 399 1   412 412 1   421 421 1   430 430 1
  443 443 1   480 480 1   480 480 1   572 572 1   574 574 1   607 607 1
  618 618 1   618 618 1   627 627 1   629 629 0   629 629 1   633 633 1
  634 634 1   652 652 1   660 660 1   667 667 0   667 667 1   670 670 1
  671 671 1   683 683 1   705 705 1   711 711 1   716 716 1   726 726 1
  730 730 1   759 759 1   762 762 1   768 768 1   768 768 1   777 777 1
  786 786 1   790 790 1   792 792 1   794 794 1   805 805 1   822 822 1
  839 839 1   839 839 1   840 840 1   844 844 1   845 845 1   870 870 0
  870 870 1   870 870 1   899 899 1   911 911 1   929 929 1   934 934 1
  938 938 1   938 938 1   959 959 1   963 963 1   979 979 1}

do_execsql_test 5.4.6.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS FIRST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING   EXCLUDE TIES  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} 1 1   {} 5 4   {} 6 5   {} 6 5   {} 8 6   {} 9 7   {} 11 9   {} 12 10
  {} 13 11   {} 16 14   {} 17 15   {} 18 16   {} 22 20   {} 24 22   {} 25 23
  {} 26 24   {} 31 27   {} 34 29   {} 36 31   {} 38 33   {} 38 33   {} 40 34
  {} 41 35   {} 43 37   {} 43 37   {} 49 41   {} 50 42   {} 51 43   {} 54 45
  {} 59 50   {} 60 51   {} 61 52   {} 63 54   {} 64 55   {} 64 55   {} 67 57
  {} 68 58   {} 69 59   {} 70 60   {} 72 62   {} 75 64   {} 76 65   {} 78 67
  {} 78 67   {} 78 67   {} 84 71   {} 85 72   {} 85 72   113 2 2   113 2 2
  133 4 3   223 10 8   239 14 12   247 15 13   257 19 17   295 20 18
  309 21 19   335 23 21   355 27 25   355 27 25   393 29 26   393 29 26
  399 32 28   399 32 28   421 35 30   443 37 32   607 42 36   627 45 38
  629 46 39   629 46 39   633 48 40   667 52 44   667 52 44   671 55 46
  683 56 47   705 57 48   711 58 49   759 62 53   777 66 56   805 71 61
  839 73 63   839 73 63   845 77 66   899 81 68   911 82 69   929 83 70
  959 87 73   963 88 74   979 89 75}

do_execsql_test 5.4.7.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS FIRST, b NULLS FIRST, a NULLS FIRST
        ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING   EXCLUDE TIES  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 102 83   979 113 81   979 113 82   979 133 80   979 148 79   979 158 77
  979 158 78   979 160 77   979 208 76   979 223 75   979 224 74   979 234 73
  979 238 72   979 239 71   979 247 70   979 250 69   979 252 68   979 256 67
  979 257 66   979 295 65   979 309 64   979 330 63   979 335 62   979 336 61
  979 346 60   979 354 59   979 355 58   979 355 58   979 393 56   979 393 57
  979 398 55   979 399 54   979 399 54   979 412 53   979 421 52   979 430 51
  979 443 50   979 480 48   979 480 49   979 572 47   979 574 46   979 607 45
  979 618 43   979 618 44   979 627 42   979 629 41   979 629 41   979 633 40
  979 634 39   979 652 38   979 660 37   979 667 36   979 667 36   979 670 35
  979 671 34   979 683 33   979 705 32   979 711 31   979 716 30   979 726 29
  979 730 28   979 759 27   979 762 26   979 768 24   979 768 25   979 777 23
  979 786 22   979 790 21   979 792 20   979 794 19   979 805 18   979 822 17
  979 839 15   979 839 16   979 840 14   979 844 13   979 845 12   979 870 10
  979 870 11   979 870 11   979 899 9   979 911 8   979 929 7}

do_execsql_test 5.4.7.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS FIRST, b NULLS FIRST, a NULLS FIRST
        ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING   EXCLUDE TIES  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {3830 89 89   4741 88 88   5640 84 84   5640 85 85   5640 86 86   5640 87 87
  6485 81 81   6485 82 82   6485 83 83   7324 80 80   8163 78 78   8163 79 79
  8968 73 73   8968 74 74   8968 75 75   8968 76 76   8968 77 77   9745 69 69
  9745 70 70   9745 71 71   9745 72 72   10504 65 65   10504 66 66
  10504 67 67   10504 68 68   11215 64 64   11920 63 63   12603 62 62
  13274 60 60   13274 61 61   13941 59 59   14608 55 55   14608 56 56
  14608 57 57   14608 58 58   15241 54 54   15870 53 53   16499 52 52
  17126 49 49   17126 50 50   17126 51 51   17733 44 44   17733 45 45
  17733 46 46   17733 47 47   17733 48 48   18176 42 42   18176 43 43
  18597 40 40   18597 41 41   18996 39 39   19395 37 37   19395 38 38
  19788 36 36   20181 35 35   20536 34 34   20891 30 30   20891 31 31
  20891 32 32   20891 33 33   21226 28 28   21226 29 29   21535 27 27
  21830 26 26   22087 22 22   22087 23 23   22087 24 24   22087 25 25
  22334 21 21   22573 17 17   22573 18 18   22573 19 19   22573 20 20
  22796 11 11   22796 12 12   22796 13 13   22796 14 14   22796 15 15
  22796 16 16   22929 10 10   23042 9 9   23155 1 1   23155 2 2   23155 3 3
  23155 4 4   23155 5 5   23155 6 6   23155 7 7   23155 8 8}

do_execsql_test 5.4.8.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE TIES  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {102 102 1   113 113 1   113 113 1   133 133 1   148 148 1   158 158 0
  158 158 1   160 160 1   208 208 1   223 223 1   224 224 1   234 234 1
  238 238 1   239 239 1   247 247 1   250 250 1   252 252 1   256 256 1
  257 257 1   295 295 1   309 309 1   330 330 1   335 335 1   336 336 1
  346 346 1   354 354 1   355 355 0   355 355 1   393 393 1   393 393 1
  398 398 1   399 399 0   399 399 1   412 412 1   421 421 1   430 430 1
  443 443 1   480 480 1   480 480 1   572 572 1   574 574 1   607 607 1
  618 618 1   618 618 1   627 627 1   629 629 0   629 629 1   633 633 1
  634 634 1   652 652 1   660 660 1   667 667 0   667 667 1   670 670 1
  671 671 1   683 683 1   705 705 1   711 711 1   716 716 1   726 726 1
  730 730 1   759 759 1   762 762 1   768 768 1   768 768 1   777 777 1
  786 786 1   790 790 1   792 792 1   794 794 1   805 805 1   822 822 1
  839 839 1   839 839 1   840 840 1   844 844 1   845 845 1   870 870 0
  870 870 1   870 870 1   899 899 1   911 911 1   929 929 1   934 934 1
  938 938 1   938 938 1   959 959 1   963 963 1   979 979 1}

do_execsql_test 5.4.8.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE TIES  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  113 1 1   113 1 1   133 1 1   223 1 1   239 1 1   247 1 1   257 1 1
  295 1 1   309 1 1   335 1 1   355 1 1   355 1 1   393 1 1   393 1 1
  399 1 1   399 1 1   421 1 1   443 1 1   607 1 1   627 1 1   629 1 1
  629 1 1   633 1 1   667 1 1   667 1 1   671 1 1   683 1 1   705 1 1
  711 1 1   759 1 1   777 1 1   805 1 1   839 1 1   839 1 1   845 1 1
  899 1 1   911 1 1   929 1 1   959 1 1   963 1 1   979 1 1}

do_execsql_test 5.4.9.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY a NULLS LAST 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE TIES  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {158 158 0   355 355 0   399 399 0   629 629 0   667 667 0   870 113 1
  870 158 1   870 158 1   870 158 1   870 158 1   870 158 1   870 158 1
  870 158 1   870 870 0   899 113 10   899 113 10   899 113 10   899 113 10
  899 113 10   899 113 10   899 113 10   899 113 17   899 113 17   899 113 17
  899 113 17   899 113 17   899 113 17   899 113 17   899 158 1   963 113 17
  979 102 34   979 102 45   979 102 45   979 102 45   979 102 45   979 102 45
  979 102 50   979 102 50   979 102 50   979 102 50   979 102 50   979 102 50
  979 102 50   979 102 57   979 102 57   979 102 57   979 102 57   979 102 57
  979 102 57   979 102 63   979 102 63   979 102 63   979 102 63   979 102 63
  979 102 63   979 102 63   979 102 63   979 102 63   979 102 63   979 102 63
  979 102 63   979 102 63   979 102 76   979 102 76   979 102 76   979 102 76
  979 102 76   979 102 76   979 102 76   979 102 76   979 113 17   979 113 26
  979 113 26   979 113 26   979 113 26   979 113 26   979 113 26   979 113 26
  979 113 26   979 113 34   979 113 34   979 113 34   979 113 34   979 113 34
  979 113 34   979 113 34   979 113 34   979 113 34   979 113 34}

do_execsql_test 5.4.9.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY a NULLS LAST 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE TIES  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} 84 11   {} 84 11   355 84 11   399 84 11   629 84 11   667 84 11
  2050 75 10   2050 75 10   2050 75 10   2050 75 10   2163 75 10   2307 75 10
  2889 75 10   2889 75 10   2949 75 10   4997 68 9   4997 68 9   4997 68 9
  5418 68 9   5440 68 9   5668 68 9   5802 68 9   7337 59 8   7337 59 8
  7337 59 8   7337 59 8   7470 59 8   7692 59 8   8020 59 8   8300 59 8
  8316 59 8   10450 51 7   10450 51 7   10450 51 7   10450 51 7   10450 51 7
  10450 51 7   10785 51 7   11379 51 7   11714 40 6   11714 40 6   11714 40 6
  11714 40 6   11714 40 6   11714 40 6   11714 40 6   11714 40 6   11714 40 6
  12009 40 6   12381 40 6   12676 35 5   12676 35 5   12789 35 5   13305 35 5
  13453 35 5   14195 28 4   14195 28 4   14195 28 4   14195 28 4   14195 28 4
  15040 28 4   15154 28 4   15999 22 3   15999 22 3   15999 22 3   15999 22 3
  16606 22 3   16758 22 3   17365 9 2   17365 9 2   17365 9 2   17365 9 2
  17365 9 2   17365 9 2   17612 9 2   17758 9 2   17758 9 2   17764 9 2
  17998 9 2   18070 9 2   18076 9 2   20846 1 1   20846 1 1   20846 1 1
  21069 1 1   21085 1 1   21155 1 1   21473 1 1   21757 1 1}

do_execsql_test 5.4.10.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  PARTITION BY coalesce(a, '') 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE TIES  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {102 102 1   113 113 1   113 113 1   133 133 1   148 148 1   158 158 0
  158 158 1   160 160 1   208 208 1   223 223 1   224 224 1   234 234 1
  238 238 1   239 239 1   247 247 1   250 250 1   252 252 1   256 256 1
  257 257 1   295 295 1   309 309 1   330 330 1   335 335 1   336 336 1
  346 346 1   354 354 1   355 355 0   355 355 1   393 393 1   393 393 1
  398 398 1   399 399 0   399 399 1   412 412 1   421 421 1   430 430 1
  443 443 1   480 480 1   480 480 1   572 572 1   574 574 1   607 607 1
  618 618 1   618 618 1   627 627 1   629 629 0   629 629 1   633 633 1
  634 634 1   652 652 1   660 660 1   667 667 0   667 667 1   670 670 1
  671 671 1   683 683 1   705 705 1   711 711 1   716 716 1   726 726 1
  730 730 1   759 759 1   762 762 1   768 768 1   768 768 1   777 777 1
  786 786 1   790 790 1   792 792 1   794 794 1   805 805 1   822 822 1
  839 839 1   839 839 1   840 840 1   844 844 1   845 845 1   870 870 0
  870 870 1   870 870 1   899 899 1   911 911 1   929 929 1   934 934 1
  938 938 1   938 938 1   959 959 1   963 963 1   979 979 1}

do_execsql_test 5.4.10.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  PARTITION BY coalesce(a, '') 
        RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING   EXCLUDE TIES  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1   {} 1 1
  113 1 1   113 1 1   133 1 1   223 1 1   239 1 1   247 1 1   257 1 1
  295 1 1   309 1 1   335 1 1   355 1 1   355 1 1   393 1 1   393 1 1
  399 1 1   399 1 1   421 1 1   443 1 1   607 1 1   627 1 1   629 1 1
  629 1 1   633 1 1   667 1 1   667 1 1   671 1 1   683 1 1   705 1 1
  711 1 1   759 1 1   777 1 1   805 1 1   839 1 1   839 1 1   845 1 1
  899 1 1   911 1 1   929 1 1   959 1 1   963 1 1   979 1 1}

do_execsql_test 5.4.11.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY a NULLS LAST GROUPS 6 PRECEDING   EXCLUDE TIES  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {223 223 1   239 239 1   309 309 1   572 572 1   627 627 1   870 870 1
  911 911 1   934 158 22   934 158 28   934 158 28   934 158 28   934 158 28
  934 158 28   934 158 28   934 223 9   934 223 9   934 223 9   934 223 9
  934 223 9   934 223 9   934 223 9   934 223 9   934 223 9   934 223 9
  934 223 9   934 223 9   934 223 9   934 223 22   934 223 22   934 223 22
  934 223 22   934 223 22   934 934 1   959 102 40   959 102 51   959 102 51
  959 102 51   959 102 51   959 102 51   959 102 51   959 102 51   959 102 51
  959 102 51   959 102 51   959 102 51   959 102 51   959 102 51   959 102 51
  959 102 51   959 113 35   959 113 40   959 113 40   959 113 40   959 113 40
  959 113 40   959 113 40   959 113 40   959 113 40   959 113 40   959 113 40
  959 158 28   959 158 35   959 158 35   959 158 35   959 158 35   963 102 51
  979 102 47   979 102 47   979 102 47   979 102 47   979 102 47   979 102 47
  979 102 47   979 102 48   979 102 48   979 102 48   979 102 48   979 102 48
  979 102 48   979 102 48   979 102 48   979 102 48   979 102 49   979 102 49
  979 102 49   979 102 49   979 102 49   979 102 49   979 102 51}

do_execsql_test 5.4.11.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY a NULLS LAST GROUPS 6 PRECEDING   EXCLUDE TIES  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} 1 1   {} 1 1   {} 1 1   223 1 1   239 1 1   309 1 1   627 1 1   911 1 1
  2309 9 2   2309 9 2   2309 9 2   2309 9 2   2309 9 2   2309 9 2   2556 9 2
  2702 9 2   2702 9 2   2708 9 2   2942 9 2   3014 9 2   3020 9 2   5790 22 3
  5790 22 3   5790 22 3   5790 22 3   6397 22 3   6549 22 3   7156 28 4
  7156 28 4   7156 28 4   7156 28 4   7156 28 4   8001 28 4   8115 28 4
  8960 35 5   8960 35 5   9073 35 5   9589 35 5   9737 35 5   10028 68 9
  10028 68 9   10028 68 9   10396 59 8   10396 59 8   10396 59 8   10396 59 8
  10449 68 9   10471 68 9   10479 40 6   10479 40 6   10479 40 6   10479 40 6
  10479 40 6   10479 40 6   10479 40 6   10479 40 6   10479 40 6   10529 59 8
  10699 68 9   10751 59 8   10774 40 6   10833 68 9   11002 75 10
  11002 75 10   11002 75 10   11002 75 10   11079 59 8   11115 75 10
  11146 40 6   11259 75 10   11359 59 8   11375 59 8   11441 51 7
  11441 51 7   11441 51 7   11441 51 7   11441 51 7   11441 51 7   11776 51 7
  11841 75 10   11841 75 10   11901 75 10   12145 84 11   12145 84 11
  12370 51 7   12500 84 11   12544 84 11   12774 84 11   12812 84 11}

do_execsql_test 5.4.12.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS LAST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING   EXCLUDE TIES  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {102 102 1   113 113 1   113 113 1   133 133 1   148 148 1   160 158 1
  160 158 2   160 158 2   208 208 1   224 223 2   224 223 2   239 234 3
  239 234 3   239 234 3   252 247 3   257 247 5   257 247 5   257 250 4
  257 252 3   295 295 1   309 309 1   336 330 3   336 330 3   336 330 3
  346 346 1   355 354 1   355 354 2   355 354 2   399 393 3   399 393 3
  399 393 3   399 393 4   399 393 4   412 412 1   421 421 1   430 430 1
  443 443 1   480 480 1   480 480 1   574 572 2   574 572 2   607 607 1
  618 618 1   618 618 1   634 627 3   634 627 4   634 627 4   634 627 4
  634 629 3   652 652 1   667 660 2   671 667 2   671 667 3   671 667 3
  671 667 3   683 683 1   711 705 2   716 705 3   716 711 2   730 726 2
  730 726 2   762 759 2   768 759 4   768 762 2   768 762 2   777 777 1
  792 786 3   794 786 4   794 786 4   794 790 3   805 805 1   822 822 1
  845 839 4   845 839 4   845 839 5   845 839 5   845 839 5   870 870 0
  870 870 1   870 870 1   899 899 1   911 911 1   934 929 2   938 929 4
  938 934 2   938 934 2   963 959 2   963 959 2   979 979 1}

do_execsql_test 5.4.12.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS LAST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING   EXCLUDE TIES  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} 1 1   {} 5 4   {} 6 5   {} 6 5   {} 8 6   {} 9 7   {} 25 23   {} 34 29
  {} 36 31   {} 38 33   {} 38 33   {} 40 34   {} 41 35   {} 43 37   {} 43 37
  {} 50 42   {} 60 51   {} 61 52   {} 64 55   {} 64 55   {} 67 57   {} 68 58
  {} 69 59   {} 70 60   {} 72 62   {} 78 67   {} 78 67   {} 78 67   {} 85 72
  {} 85 72   113 2 2   113 2 2   133 4 3   223 10 8   223 11 9   239 12 10
  239 13 11   239 14 12   247 15 13   257 18 16   257 19 17   295 20 18
  309 21 19   335 22 20   335 23 21   335 24 22   355 27 25   355 27 25
  421 35 30   443 37 32   504 16 14   504 17 15   607 42 36   683 56 47
  710 26 24   711 59 50   759 62 53   759 63 54   777 66 56   805 71 61
  899 81 68   911 82 69   929 83 70   929 84 71   979 89 75   1185 32 28
  1185 32 28   1191 29 26   1191 29 26   1334 51 43   1338 52 44   1338 52 44
  1416 57 48   1416 58 49   1584 31 27   1684 73 63   1684 73 63   1889 46 39
  1889 46 39   1891 49 41   1922 87 73   1922 88 74   2005 54 45   2005 55 46
  2518 45 38   2518 48 40   2523 75 64   2523 76 65   2523 77 66}

do_execsql_test 5.4.13.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS LAST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING   EXCLUDE TIES  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {102 102 1   113 113 1   113 113 1   133 133 1   148 148 1   158 158 0
  158 158 1   160 160 1   208 208 1   223 223 1   224 224 1   234 234 1
  238 238 1   239 239 1   247 247 1   250 250 1   252 252 1   256 256 1
  257 257 1   295 295 1   309 309 1   330 330 1   335 335 1   336 336 1
  346 346 1   354 354 1   355 355 0   355 355 1   393 393 1   393 393 1
  398 398 1   399 399 0   399 399 1   412 412 1   421 421 1   430 430 1
  443 443 1   480 480 1   480 480 1   572 572 1   574 574 1   607 607 1
  618 618 1   618 618 1   627 627 1   629 629 0   629 629 1   633 633 1
  634 634 1   652 652 1   660 660 1   667 667 0   667 667 1   670 670 1
  671 671 1   683 683 1   705 705 1   711 711 1   716 716 1   726 726 1
  730 730 1   759 759 1   762 762 1   768 768 1   768 768 1   777 777 1
  786 786 1   790 790 1   792 792 1   794 794 1   805 805 1   822 822 1
  839 839 1   839 839 1   840 840 1   844 844 1   845 845 1   870 870 0
  870 870 1   870 870 1   899 899 1   911 911 1   929 929 1   934 934 1
  938 938 1   938 938 1   959 959 1   963 963 1   979 979 1}

do_execsql_test 5.4.13.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS LAST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING   EXCLUDE TIES  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {{} 1 1   {} 5 4   {} 6 5   {} 6 5   {} 8 6   {} 9 7   {} 11 9   {} 12 10
  {} 13 11   {} 16 14   {} 17 15   {} 18 16   {} 22 20   {} 24 22   {} 25 23
  {} 26 24   {} 31 27   {} 34 29   {} 36 31   {} 38 33   {} 38 33   {} 40 34
  {} 41 35   {} 43 37   {} 43 37   {} 49 41   {} 50 42   {} 51 43   {} 54 45
  {} 59 50   {} 60 51   {} 61 52   {} 63 54   {} 64 55   {} 64 55   {} 67 57
  {} 68 58   {} 69 59   {} 70 60   {} 72 62   {} 75 64   {} 76 65   {} 78 67
  {} 78 67   {} 78 67   {} 84 71   {} 85 72   {} 85 72   113 2 2   113 2 2
  133 4 3   223 10 8   239 14 12   247 15 13   257 19 17   295 20 18
  309 21 19   335 23 21   355 27 25   355 27 25   393 29 26   393 29 26
  399 32 28   399 32 28   421 35 30   443 37 32   607 42 36   627 45 38
  629 46 39   629 46 39   633 48 40   667 52 44   667 52 44   671 55 46
  683 56 47   705 57 48   711 58 49   759 62 53   777 66 56   805 71 61
  839 73 63   839 73 63   845 77 66   899 81 68   911 82 69   929 83 70
  959 87 73   963 88 74   979 89 75}

do_execsql_test 5.4.14.1 {
  SELECT max(c) OVER win,
             min(c) OVER win,
             count(a) OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS LAST, b NULLS LAST, a NULLS LAST
        ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING   EXCLUDE TIES  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {979 102 83   979 102 83   979 102 83   979 102 83   979 102 83   979 102 83
  979 102 83   979 113 81   979 113 82   979 133 80   979 148 79   979 158 77
  979 158 78   979 160 77   979 208 76   979 223 75   979 224 74   979 234 73
  979 238 72   979 239 71   979 247 70   979 250 69   979 252 68   979 256 67
  979 257 66   979 295 65   979 309 64   979 330 63   979 335 62   979 336 61
  979 346 60   979 354 59   979 355 57   979 355 58   979 393 56   979 393 57
  979 398 55   979 399 53   979 399 54   979 412 53   979 421 52   979 430 51
  979 443 50   979 480 48   979 480 49   979 572 47   979 574 46   979 607 45
  979 618 43   979 618 44   979 627 42   979 629 40   979 629 41   979 633 40
  979 634 39   979 652 38   979 660 37   979 667 35   979 667 36   979 670 35
  979 671 34   979 683 33   979 705 32   979 711 31   979 716 30   979 726 29
  979 730 28   979 759 27   979 762 26   979 768 24   979 768 25   979 777 23
  979 786 22   979 790 21   979 792 20   979 794 19   979 805 18   979 822 17
  979 839 15   979 839 16   979 840 14   979 844 13   979 845 12   979 870 9
  979 870 10   979 870 11   979 899 9   979 911 8   979 929 7}

do_execsql_test 5.4.14.2 {
  SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
             rank() OVER win,
             dense_rank() OVER win
      FROM t3
      WINDOW win AS (  ORDER BY c NULLS LAST, b NULLS LAST, a NULLS LAST
        ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING   EXCLUDE TIES  )
      ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
} {3830 89 89   4741 88 88   5640 84 84   5640 85 85   5640 86 86   5640 87 87
  6485 81 81   6485 82 82   6485 83 83   7324 80 80   8163 78 78   8163 79 79
  8968 73 73   8968 74 74   8968 75 75   8968 76 76   8968 77 77   9745 69 69
  9745 70 70   9745 71 71   9745 72 72   10504 65 65   10504 66 66
  10504 67 67   10504 68 68   11215 64 64   11920 63 63   12603 62 62
  13274 60 60   13274 61 61   13941 59 59   14608 55 55   14608 56 56
  14608 57 57   14608 58 58   15241 54 54   15870 53 53   16499 52 52
  17126 49 49   17126 50 50   17126 51 51   17733 44 44   17733 45 45
  17733 46 46   17733 47 47   17733 48 48   18176 42 42   18176 43 43
  18597 40 40   18597 41 41   18996 39 39   19395 37 37   19395 38 38
  19788 36 36   20181 35 35   20536 34 34   20891 30 30   20891 31 31
  20891 32 32   20891 33 33   21226 28 28   21226 29 29   21535 27 27
  21830 26 26   22087 22 22   22087 23 23   22087 24 24   22087 25 25
  22334 21 21   22573 17 17   22573 18 18   22573 19 19   22573 20 20
  22796 11 11   22796 12 12   22796 13 13   22796 14 14   22796 15 15
  22796 16 16   22929 10 10   23042 9 9   23155 1 1   23155 2 2   23155 3 3
  23155 4 4   23155 5 5   23155 6 6   23155 7 7   23155 8 8}

#==========================================================================

do_execsql_test 6.0 {
  DROP TABLE IF EXISTS t2;
  CREATE TABLE t2(a TEXT, b INTEGER);
  INSERT INTO t2 VALUES('A', NULL);
  INSERT INTO t2 VALUES('B', NULL);
  INSERT INTO t2 VALUES('C', 1);
} {}

do_execsql_test 6.1 {
  SELECT group_concat(a, '.') OVER (
    ORDER BY b NULLS FIRST RANGE BETWEEN 7 PRECEDING AND 2 PRECEDING
  )
  FROM t2
} {A.B   A.B   {}}

do_execsql_test 6.2 {
  SELECT group_concat(a, '.') OVER (
    ORDER BY b DESC NULLS LAST RANGE BETWEEN 7 PRECEDING AND 2 PRECEDING
  )
  FROM t2
} {{}   A.B   A.B}

#==========================================================================

do_execsql_test 7.0 {
  DROP TABLE IF EXISTS t2;
  CREATE TABLE t2(a INTEGER, b INTEGER);

  INSERT INTO t2 VALUES(1, 65);
  INSERT INTO t2 VALUES(2, NULL);
  INSERT INTO t2 VALUES(3, NULL);
  INSERT INTO t2 VALUES(4, NULL);
  INSERT INTO t2 VALUES(5, 66);
  INSERT INTO t2 VALUES(6, 67);
} {}

do_execsql_test 7.1.1 {
  SELECT sum (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS LAST RANGE BETWEEN 6 FOLLOWING AND UNBOUNDED FOLLOWING
  );
} {9   9   9   9   9   9}

do_execsql_test 7.1.2 {
  SELECT sum (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS LAST RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING
  );
} {{}   {}   {}   9   9   9}

do_execsql_test 7.1.3 {
  SELECT sum (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS LAST RANGE BETWEEN 2 FOLLOWING AND 1 FOLLOWING
  );
} {{}   {}   {}   9   9   9}

do_execsql_test 7.1.4 {
  SELECT sum (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS FIRST RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING
  );
} {9   9   9   {}   {}   {}}

do_execsql_test 7.1.5 {
  SELECT sum (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS FIRST RANGE BETWEEN 2 FOLLOWING AND 1 FOLLOWING
  );
} {9   9   9   {}   {}   {}}

do_execsql_test 7.1.6 {
  SELECT sum (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS LAST RANGE BETWEEN 1000 PRECEDING AND 2 PRECEDING
  );
} {{}   {}   1   9   9   9}

do_execsql_test 7.1.7 {
  SELECT sum (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS LAST RANGE BETWEEN 2000 FOLLOWING AND 1000 FOLLOWING
  );
} {{}   {}   {}   9   9   9}

do_execsql_test 7.1.8 {
  SELECT sum (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS FIRST RANGE BETWEEN 1000 PRECEDING AND 2000 PRECEDING
  );
} {9   9   9   {}   {}   {}}

do_execsql_test 7.1.9 {
  SELECT sum (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS FIRST RANGE BETWEEN 2000 FOLLOWING AND 1000 FOLLOWING
  );
} {9   9   9   {}   {}   {}}

do_execsql_test 7.2.1 {
  SELECT min (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS LAST RANGE BETWEEN 6 FOLLOWING AND UNBOUNDED FOLLOWING
  );
} {2   2   2   2   2   2}

do_execsql_test 7.2.2 {
  SELECT min (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS LAST RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING
  );
} {{}   {}   {}   2   2   2}

do_execsql_test 7.2.3 {
  SELECT min (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS LAST RANGE BETWEEN 2 FOLLOWING AND 1 FOLLOWING
  );
} {{}   {}   {}   2   2   2}

do_execsql_test 7.2.4 {
  SELECT min (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS FIRST RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING
  );
} {2   2   2   {}   {}   {}}

do_execsql_test 7.2.5 {
  SELECT min (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS FIRST RANGE BETWEEN 2 FOLLOWING AND 1 FOLLOWING
  );
} {2   2   2   {}   {}   {}}

do_execsql_test 7.2.6 {
  SELECT min (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS LAST RANGE BETWEEN 1000 PRECEDING AND 2 PRECEDING
  );
} {{}   {}   1   2   2   2}

do_execsql_test 7.2.7 {
  SELECT min (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS LAST RANGE BETWEEN 2000 FOLLOWING AND 1000 FOLLOWING
  );
} {{}   {}   {}   2   2   2}

do_execsql_test 7.2.8 {
  SELECT min (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS FIRST RANGE BETWEEN 1000 PRECEDING AND 2000 PRECEDING
  );
} {2   2   2   {}   {}   {}}

do_execsql_test 7.2.9 {
  SELECT min (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS FIRST RANGE BETWEEN 2000 FOLLOWING AND 1000 FOLLOWING
  );
} {2   2   2   {}   {}   {}}

do_execsql_test 7.3.1 {
  SELECT sum (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS LAST RANGE BETWEEN 6 FOLLOWING AND UNBOUNDED FOLLOWING
  );
} {9   9   9   9   9   9}

do_execsql_test 7.3.2 {
  SELECT sum (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS LAST RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING
  );
} {{}   {}   {}   9   9   9}

do_execsql_test 7.3.3 {
  SELECT sum (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS LAST RANGE BETWEEN 2 FOLLOWING AND 1 FOLLOWING
  );
} {{}   {}   {}   9   9   9}

do_execsql_test 7.3.4 {
  SELECT sum (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS FIRST RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING
  );
} {9   9   9   {}   {}   {}}

do_execsql_test 7.3.5 {
  SELECT sum (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS FIRST RANGE BETWEEN 2 FOLLOWING AND 1 FOLLOWING
  );
} {9   9   9   {}   {}   {}}

do_execsql_test 7.3.6 {
  SELECT sum (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS LAST RANGE BETWEEN 1000 PRECEDING AND 2 PRECEDING
  );
} {{}   {}   1   9   9   9}

do_execsql_test 7.3.7 {
  SELECT sum (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS LAST RANGE BETWEEN 2000 FOLLOWING AND 1000 FOLLOWING
  );
} {{}   {}   {}   9   9   9}

do_execsql_test 7.3.8 {
  SELECT sum (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS FIRST RANGE BETWEEN 1000 PRECEDING AND 2000 PRECEDING
  );
} {9   9   9   {}   {}   {}}

do_execsql_test 7.3.9 {
  SELECT sum (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS FIRST RANGE BETWEEN 2000 FOLLOWING AND 1000 FOLLOWING
  );
} {9   9   9   {}   {}   {}}

do_execsql_test 7.4.1 {
  SELECT max (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS LAST RANGE BETWEEN 6 FOLLOWING AND UNBOUNDED FOLLOWING
  );
} {4   4   4   4   4   4}

do_execsql_test 7.4.2 {
  SELECT max (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS LAST RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING
  );
} {{}   {}   {}   4   4   4}

do_execsql_test 7.4.3 {
  SELECT max (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS LAST RANGE BETWEEN 2 FOLLOWING AND 1 FOLLOWING
  );
} {{}   {}   {}   4   4   4}

do_execsql_test 7.4.4 {
  SELECT max (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS FIRST RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING
  );
} {4   4   4   {}   {}   {}}

do_execsql_test 7.4.5 {
  SELECT max (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS FIRST RANGE BETWEEN 2 FOLLOWING AND 1 FOLLOWING
  );
} {4   4   4   {}   {}   {}}

do_execsql_test 7.4.6 {
  SELECT max (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS LAST RANGE BETWEEN 1000 PRECEDING AND 2 PRECEDING
  );
} {{}   {}   1   4   4   4}

do_execsql_test 7.4.7 {
  SELECT max (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS LAST RANGE BETWEEN 2000 FOLLOWING AND 1000 FOLLOWING
  );
} {{}   {}   {}   4   4   4}

do_execsql_test 7.4.8 {
  SELECT max (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS FIRST RANGE BETWEEN 1000 PRECEDING AND 2000 PRECEDING
  );
} {4   4   4   {}   {}   {}}

do_execsql_test 7.4.9 {
  SELECT max (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS FIRST RANGE BETWEEN 2000 FOLLOWING AND 1000 FOLLOWING
  );
} {4   4   4   {}   {}   {}}

#==========================================================================

do_execsql_test 8.0 {
  DROP TABLE IF EXISTS tx;
  CREATE TABLE tx(a INTEGER PRIMARY KEY);
  INSERT INTO tx VALUES(1), (2), (3), (4), (5), (6);

  DROP TABLE IF EXISTS map;
  CREATE TABLE map(v INTEGER PRIMARY KEY, t TEXT);
  INSERT INTO map VALUES
    (1, 'odd'), (2, 'even'), (3, 'odd'), 
    (4, 'even'), (5, 'odd'), (6, 'even');
} {}

do_execsql_test 8.1 {
  SELECT sum(a) OVER (
    PARTITION BY (
      SELECT t FROM map WHERE v=a
    ) ORDER BY a
  ) FROM tx;
} {2   6   12   1   4   9}

do_execsql_test 8.2 {
  SELECT sum(a) OVER win FROM tx
  WINDOW win AS (
    PARTITION BY (
      SELECT t FROM map WHERE v=a
    ) ORDER BY a
  );
} {2   6   12   1   4   9}

do_execsql_test 8.3 {
  WITH map2 AS (
    SELECT * FROM map
  )
  SELECT sum(a) OVER (
    PARTITION BY (
      SELECT t FROM map2 WHERE v=a
    ) ORDER BY a
  ) FROM tx;
} {2   6   12   1   4   9}

do_execsql_test 8.4 {
  WITH map2 AS (
    SELECT * FROM map
  )
  SELECT sum(a) OVER win FROM tx
  WINDOW win AS (
    PARTITION BY (
      SELECT t FROM map2 WHERE v=a
    ) ORDER BY a
  );
} {2   6   12   1   4   9}

#==========================================================================

do_execsql_test 9.1 {
  DROP TABLE IF EXISTS t1;
  DROP TABLE IF EXISTS t2;
  CREATE TABLE t1(a INTEGER);
  CREATE TABLE t2(y INTEGER);
} {}

do_execsql_test 9.2 {
  SELECT (
    SELECT max(a) OVER ( ORDER BY (SELECT sum(a) FROM t1) )
         + min(a) OVER() 
  )
  FROM t1
} {}

finish_test

Added test/window9.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019 June 8
#
# 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 window9

ifcapable !windowfunc {
  finish_test
  return
}

do_execsql_test 1.0 {
  CREATE TABLE fruits(
     name TEXT COLLATE NOCASE,
     color TEXT COLLATE NOCASE
  );
}

do_execsql_test 1.1 {
  INSERT INTO fruits (name, color) VALUES ('apple', 'RED');
  INSERT INTO fruits (name, color) VALUES ('APPLE', 'yellow');
  INSERT INTO fruits (name, color) VALUES ('pear', 'YELLOW');
  INSERT INTO fruits (name, color) VALUES ('PEAR', 'green');
}

do_execsql_test 1.2 {
  SELECT name, color, dense_rank() OVER (ORDER BY name) FROM fruits;
} {
  apple RED    1
  APPLE yellow 1
  pear  YELLOW 2
  PEAR  green  2
}

do_execsql_test 1.3 {
  SELECT name, color,
    dense_rank() OVER (PARTITION BY name ORDER BY color)
  FROM fruits;
} {
  apple RED    1 
  APPLE yellow 2 
  PEAR green   1 
  pear YELLOW  2
}

do_execsql_test 1.4 {
  SELECT name, color,
    dense_rank() OVER (ORDER BY name),
    dense_rank() OVER (PARTITION BY name ORDER BY color)
  FROM fruits;
} {
  apple RED    1 1 
  APPLE yellow 1 2 
  PEAR  green  2 1 
  pear  YELLOW 2 2
}

do_execsql_test 1.5 {
  SELECT name, color,
    dense_rank() OVER (ORDER BY name),
    dense_rank() OVER (PARTITION BY name ORDER BY color)
  FROM fruits ORDER BY color;
} {
  PEAR  green  2 1 
  apple RED    1 1 
  APPLE yellow 1 2 
  pear  YELLOW 2 2
}

do_execsql_test 2.0 {
  CREATE TABLE t1(a BLOB, b INTEGER, c COLLATE nocase);
  INSERT INTO t1 VALUES(1, 2, 'abc');
  INSERT INTO t1 VALUES(3, 4, 'ABC');
}

do_execsql_test 2.1.1 {
  SELECT c=='Abc' FROM t1
} {1     1}
do_execsql_test 2.1.2 {
  SELECT c=='Abc', rank() OVER (ORDER BY b) FROM t1
} {1 1   1 2}

do_execsql_test 2.2.1 {
  SELECT b=='2' FROM t1
} {1     0}
do_execsql_test 2.2.2 {
  SELECT b=='2', rank() OVER (ORDER BY a) FROM t1
} {1 1   0 2}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 3.0 {
  CREATE TABLE t1(a);
  CREATE TABLE t2(a,b,c);
}

do_execsql_test 3.1 {
  SELECT EXISTS(SELECT 1 FROM t1 ORDER BY sum(a) OVER ()) FROM t1;
}

do_execsql_test 3.2 {
  SELECT sum(a) OVER () FROM t2
   ORDER BY EXISTS(SELECT 1 FROM t2 ORDER BY sum(a) OVER ());
}

do_catchsql_test 3.3 {
  SELECT a, sum(a) OVER (ORDER BY a DESC) FROM t2 
  ORDER BY EXISTS(
    SELECT 1 FROM t2 ORDER BY sum(a) OVER (ORDER BY a)
  ) OVER (ORDER BY a);
} {1 {near "OVER": syntax error}}

do_catchsql_test 3.4 {
  SELECT y, y+1, y+2 FROM (
      SELECT c IN (
        SELECT min(a) OVER (),
        (abs(row_number() OVER())+22)/19,
        max(a) OVER () FROM t1
        ) AS y FROM t2
      );
} {1 {sub-select returns 3 columns - expected 1}}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 4.0 {
  CREATE TABLE t1(a, b TEXT);
  INSERT INTO t1 VALUES('A', 1), ('A', 2), ('2', 1), ('2', 2);
}

do_execsql_test 4.1.1 {
  SELECT b, b=count(*), '1,2'                   FROM t1 GROUP BY b;
} {1 0 1,2 2 1 1,2}
do_execsql_test 4.1.2 {
  SELECT b, b=count(*), group_concat(b) OVER () FROM t1 GROUP BY b;
} {1 0 1,2 2 1 1,2}

#--------------------------------------------------------------------------
reset_db
do_execsql_test 5.0 {
  CREATE TABLE t1(a, b, c, d, e);
  CREATE INDEX i1 ON t1(a, b, c, d, e);
}

foreach {tn sql} {
  1 {
    SELECT 
      sum(e) OVER (),
      sum(e) OVER (ORDER BY a),
      sum(e) OVER (PARTITION BY a ORDER BY b),
      sum(e) OVER (PARTITION BY a, b ORDER BY c),
      sum(e) OVER (PARTITION BY a, b, c ORDER BY d)
    FROM t1;
  }
  2 {
    SELECT sum(e) OVER (PARTITION BY a ORDER BY b) FROM t1 ORDER BY a;
  }
} {
  do_test 5.1.$tn {
    execsql "EXPLAIN QUERY PLAN $sql"
  } {~/ORDER/}
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 6.0 {
  CREATE TABLE t0(c0);
  INSERT INTO t0(c0) VALUES (0);
}

do_execsql_test 6.1 {
  SELECT * FROM t0 WHERE 
  EXISTS (
    SELECT MIN(c0) OVER (), CUME_DIST() OVER () FROM t0
  ) >=1 AND 
  EXISTS (
    SELECT MIN(c0) OVER (), CUME_DIST() OVER () FROM t0
  ) <=1;
} {0}

do_execsql_test 6.2 {
  SELECT * FROM t0 WHERE EXISTS (
    SELECT MIN(c0) OVER (), CUME_DIST() OVER () FROM t0
  ) 
  BETWEEN 1 AND 1;
} {0}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 7.0 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(x, y);
  INSERT INTO t1 VALUES(10, 1);
  INSERT INTO t1 VALUES(20, 2);
  INSERT INTO t1 VALUES(3, 3);
  INSERT INTO t1 VALUES(2, 4);
  INSERT INTO t1 VALUES(1, 5);
} {}


do_execsql_test 7.1 {
  SELECT avg(x) OVER (ORDER BY y) AS z FROM t1 ORDER BY z
} {
  7.2 8.75 10.0 11.0 15.0
}

do_execsql_test 7.2 {
  SELECT avg(x) OVER (ORDER BY y) z FROM t1 ORDER BY (z IS y);
} {
  10.0 15.0 11.0 8.75 7.2
}

do_execsql_test 7.3 {
  SELECT avg(x) OVER (ORDER BY y) z FROM t1 ORDER BY (y IS z);
} {
  10.0 15.0 11.0 8.75 7.2
}

do_execsql_test 7.4 {
  SELECT avg(x) OVER (ORDER BY y) z FROM t1 ORDER BY z + 0.0;
} {
  7.2 8.75 10.0 11.0 15.0
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 8.1.1 {
  CREATE TABLE t1(a, b);
  INSERT INTO t1 VALUES(1, 2), (3, 4);
  SELECT min( sum(a) ) OVER () FROM t1;
} {4}

do_execsql_test 8.1.2 {
  SELECT min( sum(a) ) OVER () FROM t1 GROUP BY a;
} {1 1}

do_execsql_test 8.2 {
  CREATE VIEW v1 AS 
    SELECT 0 AS x
      UNION 
    SELECT count() OVER() FROM (SELECT 0) 
    ORDER BY 1
  ;
}

do_catchsql_test 8.3 {
  SELECT min( max((SELECT x FROM v1)) ) OVER()
} {0 0}

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

Added test/windowA.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019-08-30
#
# 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.
#
#***********************************************************************
# Test cases for RANGE BETWEEN and especially with NULLS LAST
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix windowA

ifcapable !windowfunc {
  finish_test
  return
}

do_execsql_test 1.0 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b CHAR(1), d FLOAT);
  INSERT INTO t1 VALUES
   (1, 'A', 5.4),
   (2, 'B', 5.55),
   (3, 'C', 8.0),
   (4, 'D', 10.25),
   (5, 'E', 10.26),
   (6, 'N', NULL),
   (7, 'N', NULL);
} {}

do_execsql_test 1.1 {
  SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1
  WINDOW w1 AS 
     (ORDER BY d DESC NULLS LAST
      RANGE BETWEEN 2.50 PRECEDING AND 2.25 FOLLOWING)
  ORDER BY +d DESC NULLS LAST, +a;
} [list \
  5 E 10.26 ED   \
  4 D 10.25 EDC  \
  3 C   8.0 EDC  \
  2 B  5.55 CBA  \
  1 A   5.4 BA   \
  6 N  NULL NN   \
  7 N  NULL NN   \
]

do_execsql_test 1.2 {
  SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1
  WINDOW w1 AS 
     (ORDER BY d DESC NULLS FIRST
      RANGE BETWEEN 2.50 PRECEDING AND 2.25 FOLLOWING)
  ORDER BY +d DESC NULLS FIRST, +a;
} [list \
  6 N  NULL NN   \
  7 N  NULL NN   \
  5 E 10.26 ED   \
  4 D 10.25 EDC  \
  3 C   8.0 EDC  \
  2 B  5.55 CBA  \
  1 A   5.4 BA   \
]

do_execsql_test 1.3 {
  SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1
  WINDOW w1 AS 
     (ORDER BY d DESC NULLS LAST
      RANGE BETWEEN 2.50 PRECEDING AND UNBOUNDED FOLLOWING)
  ORDER BY +d DESC NULLS LAST, +a;
} [list \
  5 E 10.26 EDCBANN  \
  4 D 10.25 EDCBANN  \
  3 C   8.0 EDCBANN  \
  2 B  5.55 CBANN    \
  1 A   5.4 BANN     \
  6 N  NULL NN       \
  7 N  NULL NN       \
]

do_execsql_test 1.4 {
  SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1
  WINDOW w1 AS 
     (ORDER BY d DESC NULLS FIRST
      RANGE BETWEEN 2.50 PRECEDING AND UNBOUNDED FOLLOWING)
  ORDER BY +d DESC NULLS FIRST, +a;
} [list \
  6 N  NULL NNEDCBA  \
  7 N  NULL NNEDCBA  \
  5 E 10.26 EDCBA    \
  4 D 10.25 EDCBA    \
  3 C   8.0 EDCBA    \
  2 B  5.55 CBA      \
  1 A   5.4 BA       \
]

do_execsql_test 1.5 {
  SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1
  WINDOW w1 AS 
     (ORDER BY d DESC NULLS LAST
      RANGE BETWEEN 2.50 PRECEDING AND CURRENT ROW)
  ORDER BY +d DESC NULLS LAST, +a;
} [list \
  5 E 10.26 E    \
  4 D 10.25 ED   \
  3 C   8.0 EDC  \
  2 B  5.55 CB   \
  1 A   5.4 BA   \
  6 N  NULL NN   \
  7 N  NULL NN   \
]

do_execsql_test 1.6 {
  SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1
  WINDOW w1 AS 
     (ORDER BY d DESC NULLS FIRST
      RANGE BETWEEN 2.50 PRECEDING AND CURRENT ROW)
  ORDER BY +d DESC NULLS FIRST, +a;
} [list \
  6 N  NULL NN   \
  7 N  NULL NN   \
  5 E 10.26 E    \
  4 D 10.25 ED   \
  3 C   8.0 EDC  \
  2 B  5.55 CB   \
  1 A   5.4 BA   \
]

do_execsql_test 2.1 {
  SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1
  WINDOW w1 AS 
     (ORDER BY d DESC NULLS LAST
      RANGE BETWEEN UNBOUNDED PRECEDING AND 2.25 FOLLOWING)
  ORDER BY +d DESC NULLS LAST, +a;
} [list \
  5 E 10.26 ED       \
  4 D 10.25 EDC      \
  3 C   8.0 EDC      \
  2 B  5.55 EDCBA    \
  1 A   5.4 EDCBA    \
  6 N  NULL EDCBANN  \
  7 N  NULL EDCBANN  \
]

do_execsql_test 2.2 {
  SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1
  WINDOW w1 AS 
     (ORDER BY d DESC NULLS FIRST
      RANGE BETWEEN UNBOUNDED PRECEDING AND 2.25 FOLLOWING)
  ORDER BY +d DESC NULLS FIRST, +a;
} [list \
  6 N  NULL NN         \
  7 N  NULL NN         \
  5 E 10.26 NNED       \
  4 D 10.25 NNEDC      \
  3 C   8.0 NNEDC      \
  2 B  5.55 NNEDCBA    \
  1 A   5.4 NNEDCBA    \
]

do_execsql_test 2.3 {
  SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1
  WINDOW w1 AS 
     (ORDER BY d DESC NULLS LAST
      RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
  ORDER BY +d DESC NULLS LAST, +a;
} [list \
  5 E 10.26 EDCBANN  \
  4 D 10.25 EDCBANN  \
  3 C   8.0 EDCBANN  \
  2 B  5.55 EDCBANN  \
  1 A   5.4 EDCBANN  \
  6 N  NULL EDCBANN  \
  7 N  NULL EDCBANN  \
]

do_execsql_test 2.4 {
  SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1
  WINDOW w1 AS 
     (ORDER BY d DESC NULLS FIRST
      RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
  ORDER BY +d DESC NULLS FIRST, +a;
} [list \
  6 N  NULL NNEDCBA  \
  7 N  NULL NNEDCBA  \
  5 E 10.26 NNEDCBA  \
  4 D 10.25 NNEDCBA  \
  3 C   8.0 NNEDCBA  \
  2 B  5.55 NNEDCBA  \
  1 A   5.4 NNEDCBA  \
]

do_execsql_test 2.5 {
  SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1
  WINDOW w1 AS 
     (ORDER BY d DESC NULLS LAST
      RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
  ORDER BY +d DESC NULLS LAST, +a;
} [list \
  5 E 10.26 E        \
  4 D 10.25 ED       \
  3 C   8.0 EDC      \
  2 B  5.55 EDCB     \
  1 A   5.4 EDCBA    \
  6 N  NULL EDCBANN  \
  7 N  NULL EDCBANN  \
]

do_execsql_test 2.6 {
  SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1
  WINDOW w1 AS 
     (ORDER BY d DESC NULLS FIRST
      RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
  ORDER BY +d DESC NULLS FIRST, +a;
} [list \
  6 N  NULL NN       \
  7 N  NULL NN       \
  5 E 10.26 NNE      \
  4 D 10.25 NNED     \
  3 C   8.0 NNEDC    \
  2 B  5.55 NNEDCB   \
  1 A   5.4 NNEDCBA  \
]


do_execsql_test 3.1 {
  SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1
  WINDOW w1 AS 
     (ORDER BY d DESC NULLS LAST
      RANGE BETWEEN CURRENT ROW AND 2.25 FOLLOWING)
  ORDER BY +d DESC NULLS LAST, +a;
} [list \
  5 E 10.26 ED       \
  4 D 10.25 DC       \
  3 C   8.0 C        \
  2 B  5.55 BA       \
  1 A   5.4 A        \
  6 N  NULL NN       \
  7 N  NULL NN       \
]

do_execsql_test 3.2 {
  SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1
  WINDOW w1 AS 
     (ORDER BY d DESC NULLS FIRST
      RANGE BETWEEN CURRENT ROW AND 2.25 FOLLOWING)
  ORDER BY +d DESC NULLS FIRST, +a;
} [list \
  6 N  NULL NN       \
  7 N  NULL NN       \
  5 E 10.26 ED       \
  4 D 10.25 DC       \
  3 C   8.0 C        \
  2 B  5.55 BA       \
  1 A   5.4 A        \
]

do_execsql_test 3.3 {
  SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1
  WINDOW w1 AS 
     (ORDER BY d DESC NULLS LAST
      RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
  ORDER BY +d DESC NULLS LAST, +a;
} [list \
  5 E 10.26 EDCBANN  \
  4 D 10.25 DCBANN   \
  3 C   8.0 CBANN    \
  2 B  5.55 BANN     \
  1 A   5.4 ANN      \
  6 N  NULL NN       \
  7 N  NULL NN       \
]

do_execsql_test 3.4 {
  SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1
  WINDOW w1 AS 
     (ORDER BY d DESC NULLS FIRST
      RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
  ORDER BY +d DESC NULLS FIRST, +a;
} [list \
  6 N  NULL NNEDCBA  \
  7 N  NULL NNEDCBA  \
  5 E 10.26 EDCBA    \
  4 D 10.25 DCBA     \
  3 C   8.0 CBA      \
  2 B  5.55 BA       \
  1 A   5.4 A        \
]

do_execsql_test 4.0 {
  SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1
  WINDOW w1 AS 
     (ORDER BY d DESC NULLS FIRST
      RANGE BETWEEN 2.50 PRECEDING AND 0.5 PRECEDING)
  ORDER BY +d DESC NULLS FIRST, +a;
} [list \
  6 N  NULL NN  \
  7 N  NULL NN  \
  5 E 10.26 {}  \
  4 D 10.25 {}  \
  3 C   8.0 ED  \
  2 B  5.55 C   \
  1 A   5.4 {}  \
]


finish_test

Added test/windowB.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019-08-30
#
# 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.
#
#***********************************************************************
# Test cases for RANGE BETWEEN and especially with NULLS LAST
# and for varying separator handling by group_concat().
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix windowB

ifcapable !windowfunc {
  finish_test
  return
}

do_execsql_test 1.0 {
  CREATE TABLE t1(a, b);
  INSERT INTO t1 VALUES(NULL, 1);
  INSERT INTO t1 VALUES(NULL, 2);
  INSERT INTO t1 VALUES(NULL, 3);
} {}

foreach {tn win} {
  1 { ORDER BY a RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING }
  2 { ORDER BY a NULLS LAST RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING }
  3 { ORDER BY a DESC RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING }
  4 { ORDER BY a DESC NULLS FIRST RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING }

  5 { ORDER BY a      NULLS LAST  RANGE BETWEEN 1 FOLLOWING AND 2 FOLLOWING }
  6 { ORDER BY a DESC NULLS FIRST RANGE BETWEEN 1 FOLLOWING AND 2 FOLLOWING }

  7 { ORDER BY a      NULLS LAST  RANGE BETWEEN 2 PRECEDING AND 1 PRECEDING }
  8 { ORDER BY a DESC NULLS FIRST RANGE BETWEEN 2 PRECEDING AND 1 PRECEDING }
} {
  do_execsql_test 1.$tn "
    SELECT sum(b) OVER win FROM t1
    WINDOW win AS ( $win )
  " {6 6 6}
}

do_execsql_test 1.2 {
  SELECT sum(b) OVER win FROM t1
  WINDOW win AS (
    ORDER BY a DESC NULLS FIRST RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING
  )
} {6 6 6}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.0 {
  CREATE TABLE t1(a, b);
  INSERT INTO t1 VALUES(1, NULL);
  INSERT INTO t1 VALUES(2, 45);
  INSERT INTO t1 VALUES(3, 66.2);
  INSERT INTO t1 VALUES(4, 'hello world');
  INSERT INTO t1 VALUES(5, 'hello world');
  INSERT INTO t1 VALUES(6, X'1234');
  INSERT INTO t1 VALUES(7, X'1234');
  INSERT INTO t1 VALUES(8, NULL);
}

foreach {tn win} {
  1 "ORDER BY b RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING"
  2 "ORDER BY b RANGE BETWEEN 2 FOLLOWING AND 2 FOLLOWING"
  3 "ORDER BY b NULLS LAST RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING"
  4 "ORDER BY b NULLS LAST RANGE BETWEEN 2 FOLLOWING AND 2 FOLLOWING"
} {
  do_execsql_test 2.1.$tn "
    SELECT a, sum(a) OVER win FROM t1
    WINDOW win AS ( $win )
    ORDER BY 1
  " {1 9   2 {}  3 {}  4 9  5 9  6 13  7 13  8 9}
}

#-------------------------------------------------------------------------
ifcapable json1 {
  reset_db
  do_execsql_test 3.0 {
    CREATE TABLE testjson(id INTEGER PRIMARY KEY, j TEXT, x TEXT);
    INSERT INTO testjson VALUES(1, '{"a":1}', 'a');
    INSERT INTO testjson VALUES(2, '{"b":2}', 'b');
    INSERT INTO testjson VALUES(3, '{"c":3}', 'c');
    INSERT INTO testjson VALUES(4, '{"d":4}', 'd');
  }
  
  do_execsql_test 3.1 {
    SELECT json_group_array(json(j)) FROM testjson;
  } {
    {[{"a":1},{"b":2},{"c":3},{"d":4}]}
  }
  
  do_execsql_test 3.2 {
    SELECT json_group_array(json(j)) OVER (ORDER BY id) FROM testjson;
  } {
    {[{"a":1}]}
    {[{"a":1},{"b":2}]}
    {[{"a":1},{"b":2},{"c":3}]}
    {[{"a":1},{"b":2},{"c":3},{"d":4}]}
  }
  
  do_execsql_test 3.3 {
    SELECT json_group_array(json(j)) OVER (
      ORDER BY id RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
      EXCLUDE TIES
    ) FROM testjson;
  } {
    {[{"a":1}]}
    {[{"a":1},{"b":2}]}
    {[{"a":1},{"b":2},{"c":3}]}
    {[{"a":1},{"b":2},{"c":3},{"d":4}]}
  }
  
  do_execsql_test 3.4 {
    SELECT json_group_array(json(j)) OVER (
      ORDER BY id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING
    ) FROM testjson;
  } {
    {[{"a":1},{"b":2}]}
    {[{"a":1},{"b":2},{"c":3}]}
    {[{"b":2},{"c":3},{"d":4}]}
    {[{"c":3},{"d":4}]}
  }
  
  do_execsql_test 3.5 {
    SELECT json_group_array(json(j)) OVER (
      ORDER BY id ROWS BETWEEN 2 PRECEDING AND 1 PRECEDING
    ) FROM testjson;
  } {
    {[]}
    {[{"a":1}]}
    {[{"a":1},{"b":2}]}
    {[{"b":2},{"c":3}]}
  }
  
  do_execsql_test 3.5a {
    UPDATE testjson SET j = replace(j,char(125),',"e":9'||char(125));
    SELECT j FROM testjson;
  } {
    {{"a":1,"e":9}}
    {{"b":2,"e":9}}
    {{"c":3,"e":9}}
    {{"d":4,"e":9}}
  }
  do_execsql_test 3.5b {
    SELECT group_concat(x,'') OVER (
      ORDER BY id ROWS BETWEEN 1 FOLLOWING AND 2 FOLLOWING
    ) FROM testjson ORDER BY id;
  } {bc cd d {}}
  do_execsql_test 3.5c {
    SELECT json_group_array(json(j)) OVER (
      ORDER BY id ROWS BETWEEN 1 FOLLOWING AND 2 FOLLOWING
    ) FROM testjson;
  } {
    {[{"b":2,"e":9},{"c":3,"e":9}]}
    {[{"c":3,"e":9},{"d":4,"e":9}]}
    {[{"d":4,"e":9}]}
    {[]}
  }
  do_execsql_test 3.5d {
    SELECT json_group_object(x,json(j)) OVER (
      ORDER BY id ROWS BETWEEN 1 FOLLOWING AND 2 FOLLOWING
    ) FROM testjson;
  } {
    {{"b":{"b":2,"e":9},"c":{"c":3,"e":9}}}
    {{"c":{"c":3,"e":9},"d":{"d":4,"e":9}}}
    {{"d":{"d":4,"e":9}}}
    {{}}
  }
  
  do_execsql_test 3.7b {
    SELECT group_concat(x,'') FILTER (WHERE id!=2) OVER (
      ORDER BY id ROWS BETWEEN 2 PRECEDING AND 1 PRECEDING
    ) FROM testjson;
  } {{} a a c}

  do_execsql_test 3.7c {
    SELECT json_group_array(json(j)) FILTER (WHERE id!=2) OVER (
      ORDER BY id ROWS BETWEEN 2 PRECEDING AND 1 PRECEDING
    ) FROM testjson
  } {
    {[]}
    {[{"a":1,"e":9}]}
    {[{"a":1,"e":9}]}
    {[{"c":3,"e":9}]}
  }
  do_execsql_test 3.7d {
    SELECT json_group_object(x,json(j)) FILTER (WHERE id!=2) OVER (
      ORDER BY id ROWS BETWEEN 2 PRECEDING AND 1 PRECEDING
    ) FROM testjson
  } {
    {{}}
    {{"a":{"a":1,"e":9}}}
    {{"a":{"a":1,"e":9}}}
    {{"c":{"c":3,"e":9}}}
  }
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 4.0 {
  CREATE TABLE x(a);
  INSERT INTO x VALUES(1);
  INSERT INTO x VALUES(2);
}

do_execsql_test 4.1 {
  WITH y AS (
      SELECT Row_Number() OVER (win) FROM x WINDOW win AS (PARTITION BY a)
  )
  SELECT * FROM y;
} {
  1 1
}

do_catchsql_test 4.2 {
  WITH y AS (
    SELECT Row_Number() OVER (win) FROM x WINDOW win AS (PARTITION
  BY fake_column))
  SELECT * FROM y;
} {1 {no such column: fake_column}}

do_catchsql_test 4.3 {
  SELECT 1 WINDOW win AS (PARTITION BY fake_column);
} {0 1}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 5.0 {
  CREATE TABLE t1(a, c);
  CREATE INDEX i1 ON t1(a);

  INSERT INTO t1 VALUES(0, 421);
  INSERT INTO t1 VALUES(1, 844);
  INSERT INTO t1 VALUES(2, 1001);
}

do_execsql_test 5.1 {
  SELECT a, sum(c) OVER (
    ORDER BY a RANGE BETWEEN 0 PRECEDING AND 3 PRECEDING
  ) FROM t1;
} {0 {} 1 {} 2 {}}

do_execsql_test 5.2 {
  INSERT INTO t1 VALUES(NULL, 123);
  INSERT INTO t1 VALUES(NULL, 111);
  INSERT INTO t1 VALUES('xyz', 222);
  INSERT INTO t1 VALUES('xyz', 333);

  SELECT a, sum(c) OVER (
    ORDER BY a RANGE BETWEEN 0 PRECEDING AND 3 PRECEDING
  ) FROM t1;
} {{} 234 {} 234 0 {} 1 {} 2 {} xyz 555 xyz 555}

do_execsql_test 5.3 {
  SELECT a, sum(c) OVER (
    ORDER BY a RANGE BETWEEN 2 FOLLOWING AND 0 FOLLOWING
  ) FROM t1;
} {{} 234 {} 234 0 {} 1 {} 2 {} xyz 555 xyz 555}

do_execsql_test 5.4 {
  SELECT a, sum(c) OVER (
    ORDER BY a RANGE BETWEEN 0 PRECEDING AND 3 PRECEDING EXCLUDE NO OTHERS
  ) FROM t1;
} {{} 234 {} 234 0 {} 1 {} 2 {} xyz 555 xyz 555}

do_execsql_test 5.5 {
  SELECT a, sum(c) OVER (
    ORDER BY a RANGE BETWEEN 2 FOLLOWING AND 0 FOLLOWING EXCLUDE NO OTHERS
  ) FROM t1;
} {{} 234 {} 234 0 {} 1 {} 2 {} xyz 555 xyz 555}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 6.0 {
  CREATE TABLE t1(a, c);
  CREATE INDEX i1 ON t1(a);

  INSERT INTO t1 VALUES(7,  997);
  INSERT INTO t1 VALUES(8,  997);
  INSERT INTO t1 VALUES('abc', 1001);
}
do_execsql_test 6.1 {
  SELECT a, sum(c) OVER (
    ORDER BY a RANGE BETWEEN 2 FOLLOWING AND 0 FOLLOWING 
  ) FROM t1;
} {7 {} 8 {} abc 1001} 
do_execsql_test 6.2 {
  SELECT a, sum(c) OVER (
    ORDER BY a RANGE BETWEEN 2 FOLLOWING AND 0 FOLLOWING EXCLUDE NO OTHERS
  ) FROM t1;
} {7 {} 8 {} abc 1001} 

#-------------------------------------------------------------------------
reset_db
do_execsql_test 7.0 {
  CREATE TABLE t1(a, c);
  CREATE INDEX i1 ON t1(a);

  INSERT INTO t1 VALUES(NULL, 46);
  INSERT INTO t1 VALUES(NULL, 45);
  INSERT INTO t1 VALUES(7,  997);
  INSERT INTO t1 VALUES(7,  1000);
  INSERT INTO t1 VALUES(8,  997);
  INSERT INTO t1 VALUES(8,  1000);
  INSERT INTO t1 VALUES('abc', 1001);
  INSERT INTO t1 VALUES('abc', 1004);
  INSERT INTO t1 VALUES('xyz', 3333);
}

do_execsql_test 7.1 {
  SELECT a, max(c) OVER (
    ORDER BY a RANGE BETWEEN 2 FOLLOWING AND 0 FOLLOWING
  ) FROM t1;
} {{} 46 {} 46  7 {} 7 {} 8 {} 8 {}  abc 1004 abc 1004 xyz 3333}
do_execsql_test 7.2 {
  SELECT a, min(c) OVER (
    ORDER BY a RANGE BETWEEN 2 FOLLOWING AND 0 FOLLOWING
  ) FROM t1;
} {{} 45 {} 45  7 {} 7 {} 8 {} 8 {}  abc 1001 abc 1001 xyz 3333}

do_execsql_test 7.3 {
  SELECT a, max(c) OVER (
    ORDER BY a RANGE BETWEEN 0 PRECEDING AND 2 PRECEDING
  ) FROM t1;
} {{} 46 {} 46  7 {} 7 {} 8 {} 8 {}  abc 1004 abc 1004 xyz 3333}
do_execsql_test 7.4 {
  SELECT a, min(c) OVER (
    ORDER BY a RANGE BETWEEN 0 PRECEDING AND 2 PRECEDING
  ) FROM t1;
} {{} 45 {} 45  7 {} 7 {} 8 {} 8 {}  abc 1001 abc 1001 xyz 3333}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 8.0 {
  BEGIN TRANSACTION;
    CREATE TABLE t1(a, c);
    INSERT INTO t1 VALUES('aa', 111);
    INSERT INTO t1 VALUES('BB', 660);
    INSERT INTO t1 VALUES('CC', 938);
    INSERT INTO t1 VALUES('dd', 979);
  COMMIT;

  CREATE INDEX i1 ON t1(a COLLATE nocase);
}

do_execsql_test 8.1 {
  SELECT sum(c) OVER
    (ORDER BY a COLLATE nocase RANGE BETWEEN 10.0 PRECEDING AND 5.0 PRECEDING)
  FROM t1;
} {111 660 938 979}

do_execsql_test 9.0 {
  CREATE TABLE seps(x);
  INSERT INTO seps(x) VALUES ('1'), ('22'), ('333'), ('4444');
  SELECT group_concat('-', x)
    OVER ( ORDER BY x ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING )
  FROM seps;
} {-22- -22-333- -333-4444- -4444-}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 10.1 {
  CREATE TABLE t1(i INTEGER PRIMARY KEY, v);
  INSERT INTO t1 VALUES( 1, 'one' );
  INSERT INTO t1 VALUES( 2, 'two' );
}

do_execsql_test 10.2 {
  SELECT 
    json_group_array( v ) OVER w,
    json_group_array( v ) OVER w
  FROM t1
  window w as ( 
    range between unbounded preceding and unbounded following 
  )
} {
  {["one","two"]} 
  {["one","two"]} 
  {["one","two"]} 
  {["one","two"]} 
}

do_execsql_test 10.3 {
  SELECT 
    group_concat( v ) OVER w,
    json_group_array( v ) OVER w,
    json_group_array( v ) OVER w,
    group_concat( v ) OVER w
  FROM t1
  window w as ( 
    range between unbounded preceding and unbounded following 
  )
} {
  one,two
  {["one","two"]} 
  {["one","two"]} 
  one,two

  one,two
  {["one","two"]} 
  {["one","two"]} 
  one,two
}

ifcapable json1 {

  do_execsql_test 11.0 {
    SELECT value FROM json_each('[1,2,3,4,5]');
  } {1 2 3 4 5}

  do_execsql_test 11.1 {
    SELECT key, value FROM json_each('[1,2,3,4,5]');
  } {0 1  1 2  2 3  3 4  4 5}
  do_execsql_test 11.2 {
    SELECT rowid, value FROM json_each('[1,2,3,4,5]');
  } {0 1  1 2  2 3  3 4  4 5}

  do_execsql_test 11.3 {
    SELECT sum(value) OVER (ORDER BY rowid) FROM json_each('[1,2,3,4,5]')
  } {1 3 6 10 15}

  do_execsql_test 11.4 {
    SELECT sum(value) OVER (
        ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
    ) FROM json_each('[1,2,3,4,5]')
  } {1 3 6 10 15}

  do_eqp_test 11.5 {
    SELECT sum(value) OVER (
        ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
    ) FROM json_each('[1,2,3,4,5]')
  } {
    QUERY PLAN
      |--CO-ROUTINE (subquery-xxxxxx)
      |  `--SCAN json_each VIRTUAL TABLE INDEX 1:
      `--SCAN (subquery-xxxxxx)
  }

  do_eqp_test 11.6 {
    SELECT sum(value) OVER (ORDER BY rowid) FROM json_each('[1,2,3,4,5]')
  } {
    QUERY PLAN
      |--CO-ROUTINE (subquery-xxxxxx)
      |  `--SCAN json_each VIRTUAL TABLE INDEX 1:
      `--SCAN (subquery-xxxxxx)
  }

  do_eqp_test 11.8 {
    SELECT sum(value) OVER (ORDER BY rowid DESC) FROM json_each('[1,2,3,4,5]')
  } {
    QUERY PLAN
      |--CO-ROUTINE (subquery-xxxxxx)
      |  |--SCAN json_each VIRTUAL TABLE INDEX 1:
      |  `--USE TEMP B-TREE FOR ORDER BY
      `--SCAN (subquery-xxxxxx)
  }

  do_execsql_test 11.9 {
    SELECT sum(value) OVER (ORDER BY rowid DESC) FROM json_each('[1,2,3,4,5]')
  } {5 9 12 14 15}

  do_execsql_test 11.10 {
    SELECT sum(value) OVER (ORDER BY value ASC) FROM json_each('[2,1,4,3,5]')
  } {1 3 6 10 15}
  do_eqp_test 11.11 {
    SELECT sum(value) OVER (ORDER BY value ASC) FROM json_each('[2,1,4,3,5]')
  } {
    QUERY PLAN
      |--CO-ROUTINE (subquery-xxxxxx)
      |  |--SCAN json_each VIRTUAL TABLE INDEX 1:
      |  `--USE TEMP B-TREE FOR ORDER BY
      `--SCAN (subquery-xxxxxx)
  }
}

finish_test

Added test/windowC.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2021-09-29
#
# 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.
#
#***********************************************************************
# Test cases for varying separator handling by group_concat().
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix windowC

ifcapable !windowfunc {
  finish_test
  return
}

do_execsql_test 1.0 {
  CREATE TABLE x1(i INTEGER PRIMARY KEY, x);
}

foreach {tn bBlob seps} {
  1 0 {a b c def g}
  2 0 {abcdefg {} {} abcdefg}
  3 0 {a bc def ghij klmno pqrstu}
  4 1 {a bc def ghij klmno pqrstu}
  5 1 {, , , , , , , , , , , , ....... , ,}
} {
  foreach type {text blob} {
    do_test 1.$type.$tn.1 {
      execsql { DELETE FROM x1 }
      foreach s $seps {
        if {$type=="text"} {
          execsql {INSERT INTO x1 VALUES(NULL, $s)}
        } else {
          execsql {INSERT INTO x1 VALUES(NULL, CAST ($s AS blob))}
        }
      }
    } {}

    foreach {tn2 win} {
      1     "ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING"
      2     "ROWS BETWEEN 2 PRECEDING AND CURRENT ROW"
      3     "ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING"
    } {
      do_test 1.$type.$tn.2.$tn2 {
        db eval "
          SELECT group_concat('val', x) OVER ( ORDER BY i $win ) AS val FROM x1
          " {
            if {[string range $val 0 2]!="val"
              || [string range $val end-2 end]!="val"
            } {
              error "unexpected return value: $val"
            }
          }
      } {} 
    }
  }
}

# 2021-10-12 dbsqlfuzz 6c31db077a14149a7b22a1069294bdb068be8a96
#
reset_db
do_execsql_test 2.0 {
  PRAGMA encoding=UTF16le;
  WITH separator(x) AS (VALUES(',a,'),(',bc,')),
       value(y) AS (VALUES(1),(x'5585d09013455178cd11ce4a'))
  SELECT group_concat(y,x) OVER (ORDER BY x ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING)
  FROM separator, value;
} {{} 1 蕕郐䔓硑ᇍ䫎 1}
reset_db
do_execsql_test 2.1 {
  PRAGMA encoding=UTF16be;
  WITH separator(x) AS (VALUES(',a,'),(',bc,')),
       value(y) AS (VALUES(1),(x'5585d09013455178cd11ce4a'))
  SELECT group_concat(y,x) OVER (ORDER BY x ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING)
  FROM separator, value;
} {{} 1 喅킐ፅ典촑칊 1}

finish_test

Added test/windowD.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022 June 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
set testprefix windowD


do_execsql_test 1.0 {
  CREATE TABLE t0(c0 TEXT);
  CREATE VIEW v0(c0, c1) 
    AS SELECT CUME_DIST() OVER (PARTITION BY t0.c0), TRUE FROM t0;
  INSERT INTO t0 VALUES ('x');
}

do_execsql_test 1.1 {
  SELECT ('500') IS (v0.c1) FROM v0;
} {
  0
}

do_execsql_test 1.2 {
  SELECT (('500') IS (v0.c1)) FROM v0, t0;
} {
  0
}

do_execsql_test 1.2 {
  SELECT (('500') IS (v0.c1)) IS FALSE FROM v0;
} {
  1
}

do_execsql_test 1.3 {
  SELECT * FROM v0;
} {
  1.0 1
}

do_execsql_test 1.4 {
  SELECT * FROM v0 WHERE ('500' IS v0.c1) IS FALSE;
} {
  1.0 1
}

#-------------------------------------------------------------------------

reset_db
do_execsql_test 2.0 {
  CREATE TABLE t1(x);
  INSERT INTO t1 VALUES('value');
  CREATE VIEW v1(a, b, c, d) AS SELECT 1, 2, TRUE, FALSE FROM t1;
}

do_execsql_test 2.1 {
  SELECT 500 IS a, 500 IS b, 500 IS c, 500 IS d FROM v1
} {0 0 0 0}

do_execsql_test 2.2 {
  SELECT * FROM v1 WHERE 500 IS c;
} {}

do_execsql_test 2.3 {
  SELECT * FROM v1 WHERE 500 IS d;
} {}

do_execsql_test 2.4 {
  CREATE VIEW v2 AS SELECT max(x) OVER () AS a, TRUE AS c FROM t1;
}

do_execsql_test 2.5 {
  SELECT 500 IS c FROM v2;
} 0

do_execsql_test 2.6 {
  SELECT * FROM v2 WHERE 500 IS c;
} {}






finish_test

Added test/windowE.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2022 October 18
#
# 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
set testprefix windowE

proc custom {a b} { return [string compare $a $b] }
db collate custom custom

do_execsql_test 1.0 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT COLLATE custom);
  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');
  CREATE INDEX t1b ON t1(b);
}

do_execsql_test 1.1 {
  SELECT * FROM t1
} {
  1 one 2 two 3 three 4 four 5 five 6 six
}

do_execsql_test 1.2 {
  SELECT group_concat(a,',') OVER win FROM t1 
  WINDOW win AS (
    ORDER BY b RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING
  )
} {
  5 4 1 6 3 2
}

proc custom {a b} { return [string compare $b $a] }

do_execsql_test 1.3 {
  SELECT group_concat(a,',') OVER win FROM t1 
  WINDOW win AS (
    ORDER BY b RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING
  )
} {
  5 5,4 5,4,1 5,4,1,6 5,4,1,6,3 5,4,1,6,3,2
}

finish_test

Added test/windowerr.tcl.









































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2018 May 19
#
# 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.
#
#***********************************************************************
#

source [file join [file dirname $argv0] pg_common.tcl]

#=========================================================================

start_test windowerr "2019 March 01"
ifcapable !windowfunc

execsql_test 1.0 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a INTEGER, b INTEGER);
  INSERT INTO t1 VALUES(1, 1);
  INSERT INTO t1 VALUES(2, 2);
  INSERT INTO t1 VALUES(3, 3);
  INSERT INTO t1 VALUES(4, 4);
  INSERT INTO t1 VALUES(5, 5);
}

foreach {tn frame} {
  1 "ORDER BY a ROWS BETWEEN -1 PRECEDING AND 1 FOLLOWING"
  2 "ORDER BY a ROWS BETWEEN  1 PRECEDING AND -1 FOLLOWING"

  3 "ORDER BY a RANGE BETWEEN -1 PRECEDING AND 1 FOLLOWING"
  4 "ORDER BY a RANGE BETWEEN  1 PRECEDING AND -1 FOLLOWING"

  5 "ORDER BY a GROUPS BETWEEN -1 PRECEDING AND 1 FOLLOWING"
  6 "ORDER BY a GROUPS BETWEEN  1 PRECEDING AND -1 FOLLOWING"

  7 "ORDER BY a,b RANGE BETWEEN  1 PRECEDING AND 1 FOLLOWING"

  8 "PARTITION BY a RANGE BETWEEN  1 PRECEDING AND 1 FOLLOWING"
} {
  errorsql_test 1.$tn "
  SELECT a, sum(b) OVER (
    $frame
  ) FROM t1 ORDER BY 1
  "
}
errorsql_test 2.1 {
  SELECT sum( sum(a) OVER () ) FROM t1;
}

errorsql_test 2.2 {
  SELECT sum(a) OVER () AS xyz FROM t1 ORDER BY sum(xyz);
}

errorsql_test 3.0 {
  SELECT sum(a) OVER win FROM t1
  WINDOW win AS (ROWS BETWEEN 'hello' PRECEDING AND 10 FOLLOWING)
}
errorsql_test 3.2 {
  SELECT sum(a) OVER win FROM t1
  WINDOW win AS (ROWS BETWEEN 10 PRECEDING AND x'ABCD' FOLLOWING)
}

errorsql_test 3.3 {
  SELECT row_number(a) OVER () FROM t1;
}

finish_test

Added test/windowerr.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019 March 01
#
# 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.
#

####################################################
# DO NOT EDIT! THIS FILE IS AUTOMATICALLY GENERATED!
####################################################

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix windowerr

ifcapable !windowfunc { finish_test ; return }
do_execsql_test 1.0 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a INTEGER, b INTEGER);
  INSERT INTO t1 VALUES(1, 1);
  INSERT INTO t1 VALUES(2, 2);
  INSERT INTO t1 VALUES(3, 3);
  INSERT INTO t1 VALUES(4, 4);
  INSERT INTO t1 VALUES(5, 5);
} {}

# PG says ERROR:  frame starting offset must not be negative
do_test 1.1 { catch { execsql {
  SELECT a, sum(b) OVER (
    ORDER BY a ROWS BETWEEN -1 PRECEDING AND 1 FOLLOWING
  ) FROM t1 ORDER BY 1
} } } 1

# PG says ERROR:  frame ending offset must not be negative
do_test 1.2 { catch { execsql {
  SELECT a, sum(b) OVER (
    ORDER BY a ROWS BETWEEN  1 PRECEDING AND -1 FOLLOWING
  ) FROM t1 ORDER BY 1
} } } 1

# PG says ERROR:  invalid preceding or following size in window function
do_test 1.3 { catch { execsql {
  SELECT a, sum(b) OVER (
    ORDER BY a RANGE BETWEEN -1 PRECEDING AND 1 FOLLOWING
  ) FROM t1 ORDER BY 1
} } } 1

# PG says ERROR:  invalid preceding or following size in window function
do_test 1.4 { catch { execsql {
  SELECT a, sum(b) OVER (
    ORDER BY a RANGE BETWEEN  1 PRECEDING AND -1 FOLLOWING
  ) FROM t1 ORDER BY 1
} } } 1

# PG says ERROR:  frame starting offset must not be negative
do_test 1.5 { catch { execsql {
  SELECT a, sum(b) OVER (
    ORDER BY a GROUPS BETWEEN -1 PRECEDING AND 1 FOLLOWING
  ) FROM t1 ORDER BY 1
} } } 1

# PG says ERROR:  frame ending offset must not be negative
do_test 1.6 { catch { execsql {
  SELECT a, sum(b) OVER (
    ORDER BY a GROUPS BETWEEN  1 PRECEDING AND -1 FOLLOWING
  ) FROM t1 ORDER BY 1
} } } 1

# PG says ERROR:  RANGE with offset PRECEDING/FOLLOWING requires exactly one ORDER BY column
do_test 1.7 { catch { execsql {
  SELECT a, sum(b) OVER (
    ORDER BY a,b RANGE BETWEEN  1 PRECEDING AND 1 FOLLOWING
  ) FROM t1 ORDER BY 1
} } } 1

# PG says ERROR:  RANGE with offset PRECEDING/FOLLOWING requires exactly one ORDER BY column
do_test 1.8 { catch { execsql {
  SELECT a, sum(b) OVER (
    PARTITION BY a RANGE BETWEEN  1 PRECEDING AND 1 FOLLOWING
  ) FROM t1 ORDER BY 1
} } } 1

# PG says ERROR:  aggregate function calls cannot contain window function calls
do_test 2.1 { catch { execsql {
  SELECT sum( sum(a) OVER () ) FROM t1;
} } } 1

# PG says ERROR:  column "xyz" does not exist
do_test 2.2 { catch { execsql {
  SELECT sum(a) OVER () AS xyz FROM t1 ORDER BY sum(xyz);
} } } 1

# PG says ERROR:  invalid input syntax for integer: "hello"
do_test 3.0 { catch { execsql {
  SELECT sum(a) OVER win FROM t1
  WINDOW win AS (ROWS BETWEEN 'hello' PRECEDING AND 10 FOLLOWING)
} } } 1

# PG says ERROR:  argument of ROWS must be type bigint, not type bit
do_test 3.2 { catch { execsql {
  SELECT sum(a) OVER win FROM t1
  WINDOW win AS (ROWS BETWEEN 10 PRECEDING AND x'ABCD' FOLLOWING)
} } } 1

# PG says ERROR:  function row_number(integer) does not exist
do_test 3.3 { catch { execsql {
  SELECT row_number(a) OVER () FROM t1;
} } } 1

finish_test

Changes to test/windowfault.test.

24
25
26
27
28
29
30
31

32
33
34
35
36
37
38
24
25
26
27
28
29
30

31
32
33
34
35
36
37
38







-
+







  CREATE TABLE t1(a, b, c, d);
  INSERT INTO t1 VALUES(1, 2, 3, 4);
  INSERT INTO t1 VALUES(5, 6, 7, 8);
  INSERT INTO t1 VALUES(9, 10, 11, 12);
}
faultsim_save_and_close

do_faultsim_test 1 -start 1 -faults oom-* -prep {
do_faultsim_test 1 -start 1 -faults oom-t* -prep {
  faultsim_restore_and_reopen
} -body {
  execsql {
    SELECT row_number() OVER win,
           rank() OVER win,
           dense_rank() OVER win,
           ntile(2) OVER win,
157
158
159
160
161
162
163
164









































































































































































165
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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

      WINDOW win1 AS (PARTITION BY a ),
             win2 AS (PARTITION BY b )
    ORDER BY a;
  }
} -test {
  faultsim_test_result {0 {1 2 5 6 9 10}}
}

#-------------------------------------------------------------------------
# The following test causes a cursor in REQURESEEK state to be passed
# to sqlite3BtreeDelete(). An error is simulated within the seek operation
# to restore the cursors position.
#
reset_db
set big [string repeat x 900]
do_execsql_test 9.0 {
  PRAGMA page_size = 512;
  PRAGMA cache_size = 2;
  CREATE TABLE t(x INTEGER PRIMARY KEY, y TEXT);
  WITH s(i) AS (
    VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<1900
  )
  INSERT INTO t(y) SELECT $big FROM s;
}
db close

testvfs tvfs -default 1
tvfs script vfs_callback
tvfs filter xRead

sqlite3 db test.db
proc vfs_callback {method file args} {
  if {$file=="" && [info exists ::tmp_read_fail]} {
    incr ::tmp_read_fail -1
    if {$::tmp_read_fail<=0} {
      return "SQLITE_IOERR"
    }
  }
  return "SQLITE_OK"
}

set FAULTSIM(tmpread) [list                \
  -injectstart   tmpread_injectstart       \
  -injectstop    tmpread_injectstop        \
  -injecterrlist {{1 {disk I/O error}}}    \
]
proc tmpread_injectstart {iFail} {
  set ::tmp_read_fail $iFail
}
proc tmpread_injectstop {} {
  set ret [expr $::tmp_read_fail<=0]
  unset -nocomplain ::tmp_read_fail 
  return $ret
}

set L [db eval {SELECT 0.0 FROM t}]
do_faultsim_test 9 -end 25 -faults tmpread -body {
  execsql {
    SELECT sum(y) OVER win FROM t
    WINDOW win AS (
      ORDER BY x ROWS BETWEEN UNBOUNDED PRECEDING AND 1800 FOLLOWING
    )
  }
} -test {
  faultsim_test_result [list 0 $::L]
}

catch {db close}
tvfs delete

reset_db
do_execsql_test 10.0 {
  CREATE TABLE t1(a, b, c, d);
  CREATE TABLE t2(a, b, c, d);
}

do_faultsim_test 10 -faults oom* -prep {
} -body {
  execsql {
    SELECT row_number() OVER win
    FROM t1
    WINDOW win AS (
      ORDER BY (
        SELECT percent_rank() OVER win2 FROM t2
        WINDOW win2 AS (ORDER BY a)
      )
    )
  }
} -test {
  faultsim_test_result {0 {}}
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 11.0 {
  DROP TABLE IF EXISTS t0;
  CREATE TABLE t0(c0 INTEGER UNIQUE);
  INSERT INTO t0 VALUES(0);
} {}

do_faultsim_test 11.1 -faults oom* -prep {
} -body {
  execsql {
    SELECT * FROM t0 WHERE 
      (0, t0.c0) IN (SELECT DENSE_RANK() OVER(), LAG(0) OVER() FROM t0);
  }
} -test {
  faultsim_test_result {0 {}}
}

do_faultsim_test 11.2 -faults oom* -prep {
} -body {
  execsql {
    VALUES(false),(current_date collate binary) 
    intersect 
    values(count() not like group_concat(cast(cast(0e00 as text) as integer) <= NULL || 0.4e-0 || 0x8 & true ) over () collate rtrim);
  }
} -test {
  faultsim_test_result {0 {}}
}

#-------------------------------------------------------------------------
reset_db
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 COLLATE nocase ORDER BY b) FROM t1
    )
    SELECT * FROM v WHERE a=2
  }
} -test {
  faultsim_test_result {0 {}}
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 13.0 {
  CREATE TABLE t1(id INTEGER PRIMARY KEY, a, b);
  INSERT INTO t1 VALUES(1, '1', 'a');
  INSERT INTO t1 VALUES(2, '22', 'b');
  INSERT INTO t1 VALUES(3, '333', 'c');
  INSERT INTO t1 VALUES(4, '4444', 'dddd');
  INSERT INTO t1 VALUES(5, '55555', 'e');
  INSERT INTO t1 VALUES(6, '666666', 'f');
  INSERT INTO t1 VALUES(7, '7777777', 'gggggggggg');
} {}

set queryres [list {*}{
  1b22
  1b22c333
  22c333dddd4444 
  333dddd4444e55555 
  4444e55555f666666
  55555f666666gggggggggg7777777 
  666666gggggggggg7777777
}]
do_execsql_test 13.1 {
  SELECT group_concat(a, b) OVER (
    ORDER BY id RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING
  ) FROM t1
} $queryres

do_faultsim_test 13 -faults oom* -prep {
} -body {
  execsql {
    SELECT group_concat(a, b) OVER (
        ORDER BY id RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING
    ) FROM t1
  }
} -test {
  faultsim_test_result [list 0 $::queryres]
}

finish_test

Added test/windowpushd.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2021 February 23
#
# 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 the push-down optimization when
# WHERE constraints are pushed down into a sub-query that uses
# window functions.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix windowpushd

do_execsql_test 1.0 {
  CREATE TABLE t1(id INTEGER PRIMARY KEY, grp_id);
  CREATE INDEX i1 ON t1(grp_id);
  CREATE VIEW lll AS SELECT
    row_number() OVER (PARTITION BY grp_id), 
    grp_id, id 
  FROM t1
}

do_execsql_test 1.1 {
  INSERT INTO t1 VALUES
    (1, 2), (2, 3), (3, 3), (4, 1), (5, 1),
    (6, 1), (7, 1), (8, 1), (9, 3), (10, 3), 
    (11, 2), (12, 3), (13, 3), (14, 2), (15, 1),
    (16, 2), (17, 1), (18, 2), (19, 3), (20, 2)
}

do_execsql_test 1.2 {
  SELECT * FROM lll
} {
  1 1 4 2 1 5 3 1 6 4 1 7 5 1 8 6 1 15 7 1 17 
  1 2 1 2 2 11 3 2 14 4 2 16 5 2 18 6 2 20 
  1 3 2 2 3 3 3 3 9 4 3 10 5 3 12 6 3 13 7 3 19
}

do_execsql_test 1.3 {
  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 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);
  INSERT INTO t1 VALUES('A', 'E', 3,  0.3);
  INSERT INTO t1 VALUES('A', 'C', 4,  0.4);
  INSERT INTO t1 VALUES('B', 'D', 5,  0.5);
  INSERT INTO t1 VALUES('B', 'E', 6,  0.6);
  INSERT INTO t1 VALUES('B', 'C', 7,  0.7);
  INSERT INTO t1 VALUES('B', 'D', 8,  0.8);
  INSERT INTO t1 VALUES('C', 'E', 9,  0.9);
  INSERT INTO t1 VALUES('C', 'C', 10, 1.0);
  INSERT INTO t1 VALUES('C', 'D', 11, 1.1);
  INSERT INTO t1 VALUES('C', 'E', 12, 1.2);

  CREATE INDEX i1 ON t1(a);
  CREATE INDEX i2 ON t1(b);

  CREATE VIEW v1 AS SELECT a, c, max(c) OVER (PARTITION BY a) FROM t1;

  CREATE VIEW v2 AS SELECT a, c, 
      max(c) OVER (PARTITION BY a),
      row_number() OVER ()
  FROM t1;

  CREATE VIEW v3 AS SELECT b, d, 
      max(d) OVER (PARTITION BY b),
      row_number() OVER (PARTITION BY b)
  FROM t1;

  CREATE TABLE t2(x, y, z);
  INSERT INTO t2 VALUES('W', 3, 1);
  INSERT INTO t2 VALUES('W', 2, 2);
  INSERT INTO t2 VALUES('X', 1, 4);
  INSERT INTO t2 VALUES('X', 5, 7);
  INSERT INTO t2 VALUES('Y', 1, 9);
  INSERT INTO t2 VALUES('Y', 4, 2);
  INSERT INTO t2 VALUES('Z', 3, 3);
  INSERT INTO t2 VALUES('Z', 3, 4);
}

foreach tn {0 1} {
  optimization_control db push-down $tn

  do_execsql_test 2.$tn.1.1 {
    SELECT * FROM v1;
  } {
    A 1 4   A 2 4   A 3 4   A 4 4
    B 5 8   B 6 8   B 7 8   B 8 8
    C 9 12  C 10 12 C 11 12 C 12 12
  }

  do_execsql_test 2.$tn.1.2 {
    SELECT * FROM v1 WHERE a IN ('A', 'B');
  } {
    A 1 4   A 2 4   A 3 4   A 4 4
    B 5 8   B 6 8   B 7 8   B 8 8
  }

  do_execsql_test 2.$tn.1.3 {
    SELECT * FROM v1 WHERE a IS 'C'
  } {
    C 9 12  C 10 12 C 11 12 C 12 12
  }

  if {$tn==1} {
    do_eqp_test 2.$tn.1.4 {
      SELECT * FROM v1 WHERE a IN ('A', 'B');
    } {USING INDEX i1 (a=?)}

    do_eqp_test 2.$tn.1.5 {
      SELECT * FROM v1 WHERE a = 'c' COLLATE nocase
    } {USING INDEX i1}
  }

  do_execsql_test 2.$tn.2.1 {
    SELECT * FROM v2;
  } {
    A 1 4 1    A 2 4 2     A 3 4 3      A 4 4 4
    B 5 8 5    B 6 8 6     B 7 8 7      B 8 8 8
    C 9 12 9   C 10 12 10  C 11 12 11   C 12 12 12
  }

  do_execsql_test 2.$tn.2.2 {
    SELECT * FROM v2 WHERE a = 'C';
  } {
    C 9 12 9   C 10 12 10  C 11 12 11   C 12 12 12
  }

  do_execsql_test 2.$tn.3.1 { SELECT * FROM v3; } { 
    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 
    E 0.3 1.2 1 E 0.6 1.2 2 E 0.9 1.2 3 E 1.2 1.2 4
  }

  do_execsql_test 2.$tn.3.2 { SELECT * FROM v3 WHERE b<'E' } { 
    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 t1 USING INDEX i2 (b=?)}
    do_eqp_test 2.$tn.3.4 {
      SELECT * FROM v3 WHERE b>'C'
    } {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 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
    )
  } {
    W 5 2
    X 6 7
    Y 5 9
    Z 6 4
  }

  do_execsql_test 2.$tn.4.1 {
    SELECT * FROM (
      SELECT x, sum(y) AS s, max(z) AS m,
        max( max(z) ) OVER (PARTITION BY sum(y) 
            ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
        )
      FROM t2 GROUP BY x
    )
  } {
    W 5 2   9
    Y 5 9   9
    X 6 7   7
    Z 6 4   7
  }

  do_execsql_test 2.$tn.4.2 {
    SELECT * FROM (
      SELECT x, sum(y) AS s, max(z) AS m,
        max( max(z) ) OVER (PARTITION BY sum(y) 
            ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
        )
      FROM t2 GROUP BY x
    ) WHERE s=6
  } {
    X 6 7   7
    Z 6 4   7
  }

  do_execsql_test 2.$tn.4.3 {
    SELECT * FROM (
      SELECT x, sum(y) AS s, max(z) AS m,
        max( max(z) ) OVER (PARTITION BY sum(y) 
            ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
        )
      FROM t2 GROUP BY x
    ) WHERE s<6
  } {
    W 5 2   9
    Y 5 9   9
  }

}




finish_test

Changes to test/with1.test.

348
349
350
351
352
353
354
355

356
357
358
359
360
361
362
348
349
350
351
352
353
354

355
356
357
358
359
360
361
362







-
+







do_catchsql_test 7.4 {
  WITH t(id) AS (
    VALUES(2)
    UNION ALL
    SELECT i FROM tree WHERE p IN (SELECT id FROM t)
  ) 
  SELECT id FROM t;
} {1 {recursive reference in a subquery: t}}
} {1 {circular reference: t}}

do_catchsql_test 7.5 {
  WITH t(id) AS (
    VALUES(2)
    UNION ALL
    SELECT i FROM tree, t WHERE p = id AND p IN (SELECT id FROM t)
  ) 
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
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







-
+

-
-
+
+















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  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.
#
do_execsql_test 20.1 {
  WITH c(i)AS(VALUES(9)UNION SELECT~i FROM c)SELECT max(5)>i fROM c;
} {0}
do_execsql_test 20.2 {
  WITH c(i)AS(VALUES(5)UNIoN SELECT 0)SELECT min(1)-i fROM c;
} {1}

# 2018-12-26
# Two different CTE tables with the same name appear in within a single FROM
# clause due to the query-flattener optimization.  make sure this does not cause
# problems.  This problem was discovered by Matt Denton.
#
do_execsql_test 21.1 {
   WITH RECURSIVE t21(a,b) AS (
    WITH t21(x) AS (VALUES(1))
    SELECT x, x FROM t21 ORDER BY 1
  )
  SELECT * FROM t21 AS tA, t21 AS tB
} {1 1 1 1}
do_execsql_test 21.1b {
   /* This variant from chromium bug 922312 on 2019-01-16 */
   WITH RECURSIVE t21(a,b) AS (
    WITH t21(x) AS (VALUES(1))
    SELECT x, x FROM t21 ORDER BY 1 LIMIT 5
  )
  SELECT * FROM t21 AS tA, t21 AS tB
} {1 1 1 1}
do_execsql_test 21.2 {
  SELECT printf('',
     EXISTS (WITH RECURSIVE Table0 AS (WITH Table0 AS (SELECT DISTINCT 1)
                                       SELECT *, * FROM Table0 ORDER BY 1 DESC)
             SELECT * FROM Table0  NATURAL JOIN  Table0));
} {{}}

# 2019-01-17
# Make sure crazy nexted CTE joins terminate with an error quickly.
#
do_catchsql_test 22.1 {
  WITH RECURSIVE c AS NOT MATERIALIZED (
     WITH RECURSIVE c AS NOT MATERIALIZED (
        WITH RECURSIVE c AS NOT MATERIALIZED (
           WITH RECURSIVE c AS NOT MATERIALIZED (
               WITH  c AS (VALUES(0))
               SELECT 1 FROM c LEFT JOIN c ON ltrim(1)
           )
           SELECT 1 FROM c,c,c,c,c,c,c,c,c
        )
        SELECT  2 FROM c,c,c,c,c,c,c,c,c
     )
     SELECT 3 FROM c,c,c,c,c,c,c,c,c
  )
  SELECT 4 FROM c,c,c,c,c,c,c,c,c;
} {1 {too many FROM clause terms, max: 200}}

# 2019-05-22
# ticket https://www.sqlite.org/src/tktview/ce823231949d3abf42453c8f20
#
sqlite3 db :memory:
do_execsql_test 23.1 {
  CREATE TABLE t1(id INTEGER NULL PRIMARY KEY, name Text);
  INSERT INTO t1 VALUES (1, 'john');
  INSERT INTO t1 VALUES (2, 'james');
  INSERT INTO t1 VALUES (3, 'jingle');
  INSERT INTO t1 VALUES (4, 'himer');
  INSERT INTO t1 VALUES (5, 'smith');
  CREATE VIEW v2 AS
    WITH t4(Name) AS (VALUES ('A'), ('B'))
    SELECT Name Name FROM t4;
  CREATE VIEW v3 AS
    WITH t4(Att, Val, Act) AS (VALUES
      ('C', 'D', 'E'),
      ('F', 'G', 'H')
    )
    SELECT D.Id Id, P.Name Protocol, T.Att Att, T.Val Val, T.Act Act
    FROM t1 D
    CROSS JOIN v2 P
    CROSS JOIN t4 T;
  SELECT * FROM v3;
} {1 A C D E 1 A F G H 1 B C D E 1 B F G H 2 A C D E 2 A F G H 2 B C D E 2 B F G H 3 A C D E 3 A F G H 3 B C D E 3 B F G H 4 A C D E 4 A F G H 4 B C D E 4 B F G H 5 A C D E 5 A F G H 5 B C D E 5 B F G H}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 24.1 {
  CREATE TABLE t1(a, b, c);
  CREATE VIEW v1 AS SELECT max(a), min(b) FROM t1 GROUP BY c;
}
do_test 24.1 {
  set program [db eval {EXPLAIN SELECT 1 FROM v1,v1,v1}]
  expr [lsearch $program OpenDup]>0
} {1}
do_execsql_test 24.2 {
  ATTACH "" AS aux;
  CREATE VIEW aux.v3 AS VALUES(1);
  CREATE VIEW main.v3 AS VALUES(3);

  CREATE VIEW aux.v2 AS SELECT * FROM v3;
  CREATE VIEW main.v2 AS SELECT * FROM v3;

  SELECT * FROM main.v2 AS a, aux.v2 AS b, aux.v2 AS c, main.v2 AS d;
} {
  3 1 1 3
}

# 2020-01-02 chromium ticket 1033461
# Do not allow the generated name of a CTE be "true" or "false" as
# such a label might be later confused for the boolean literals of
# the same name, causing inconsistencies in the abstract syntax
# tree.  This problem first arose in version 3.23.0 when SQLite
# began recognizing "true" and "false" as boolean literals, but also
# had to continue to recognize "true" and "false" as identifiers for
# backwards compatibility.
#
foreach {id dual} {
  1  {CREATE TABLE dual AS SELECT 'X' AS dummy}
  2  {CREATE TEMP TABLE dual AS SELECT 'X' AS dummy}
  3  {CREATE VIEW dual(dummy) AS VALUES('X')}
  4  {CREATE TEMP VIEW dual(dummy) AS VALUES('X')}
} {
  reset_db
  db eval $dual
  do_execsql_test 25.$id {
    WITH cte1 AS (
      SELECT TRUE, (
        WITH cte2 AS (SELECT avg(DISTINCT TRUE) FROM dual)
        SELECT 2571 FROM cte2
      ) AS subquery1
      FROM dual
      GROUP BY 1
    )
    SELECT (SELECT 1324 FROM cte1) FROM cte1;
  } {1324}
}

do_catchsql_test 26.0 {
  WITH i(x) AS ( 
    VALUES(1) UNION ALL SELECT x+1 FRO, a.b,O. * ,I¬i O, a.b,O. * ORDER BY 1
  )
  SELECT x,O. * O FROM i ¬I,I? 10;
} {1 {near "O": syntax error}}

# 2020-09-17 ticket c51489c3b8f919c5
# DISTINCT cannot be ignored in a UNION ALL recursive CTE
#
reset_db
do_execsql_test 26.1 {
  CREATE TABLE t (label VARCHAR(10), step INTEGER);
  INSERT INTO T VALUES('a', 1);
  INSERT INTO T VALUES('a', 1);
  INSERT INTO T VALUES('b', 1);
  WITH RECURSIVE cte(label, step) AS (
      SELECT DISTINCT * FROM t 
    UNION ALL 
      SELECT label, step + 1 FROM cte WHERE step < 3
  )
  SELECT * FROM cte ORDER BY +label, +step;
} {a 1 a 2 a 3 b 1 b 2 b 3}
do_execsql_test 26.2 {
  WITH RECURSIVE cte(label, step) AS (
      SELECT * FROM t 
    UNION
      SELECT label, step + 1 FROM cte WHERE step < 3
  )
  SELECT * FROM cte ORDER BY +label, +step;
} {a 1 a 2 a 3 b 1 b 2 b 3}
do_execsql_test 26.3 {
  CREATE TABLE tworow(x);
  INSERT INTO tworow(x) VALUES(1),(2);
  DELETE FROM t WHERE rowid=2;
  WITH RECURSIVE cte(label, step) AS (
      SELECT * FROM t
    UNION ALL
      SELECT DISTINCT label, step + 1 FROM cte, tworow WHERE step < 3
  )
  SELECT * FROM cte ORDER BY +label, +step;
} {a 1 a 2 a 3 b 1 b 2 b 3}

# 2021-05-20
# forum post https://sqlite.org/forum/forumpost/8590e3f6dc
#
reset_db
do_execsql_test 27.1 {
  CREATE TABLE t1(k);
  CREATE TABLE log(k, cte_map, main_map);
  CREATE TABLE map(k, v);
  INSERT INTO map VALUES(1, 'main1'), (2, 'main2');
  
  CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
    INSERT INTO log
        WITH map(k,v) AS (VALUES(1,'cte1'),(2,'cte2'))
        SELECT
          new.k,
          (SELECT v FROM map WHERE k=new.k),
          (SELECT v FROM main.map WHERE k=new.k);
  END;
  
  INSERT INTO t1 VALUES(1);
  INSERT INTO t1 VALUES(2);
  SELECT k, cte_map, main_map, '|' FROM log ORDER BY k;
} {1 cte1 main1 | 2 cte2 main2 |}

finish_test

Changes to test/with2.test.

410
411
412
413
414
415
416


















































































































































































































417
418
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


    SELECT 1
    UNION ALL
    SELECT a+1 FROM q, v WHERE a<5
  )
  SELECT * FROM q;
} {1 2 3 4 5}

# 2021-03-18
# Ticket bb8a9fd4a9b7fce5
reset_db
do_execsql_test 9.1 {
  WITH xyz(a) AS (
    WITH abc AS ( SELECT 1234 ) SELECT * FROM abc
  )
  SELECT * FROM xyz AS one, xyz AS two, (
    SELECT * FROM xyz UNION ALL SELECT * FROM xyz
  );
} {1234 1234 1234 1234 1234 1234}
ifcapable vtab {
load_static_extension db series
do_execsql_test 9.2 {
  WITH
    cst(rsx, rsy) AS  (
      SELECT 100, 100
    ),
    cst2(minx, maxx, stepx, miny, maxy, stepy, qualitativex, qualitativey) AS (
      SELECT NULL, NULL, NULL, NULL, NULL, NULL, 0, 0
    ),
    ds0(m, n, x, y, x2, y2, title, size, mark, label, markmode) AS (
      SELECT 1, 2, 3, 4, 5, 6, 7 , 8, 9, 10, 11
    ),
    ds(m, n, x, y, x2, y2, title, size, mark, label, markmode) AS (
      SELECT m, n, x,
        y, x2,
        y2,
        title, size, mark, label, markmode
      FROM ds0
      WINDOW w AS (PARTITION BY m, x ORDER BY n)
    ),
    d(m, n, x, y, x2, y2, labelx,labely,title,size,mark,label,markmode) AS (
      SELECT m, n, x, y,  x2, y2, x, y, title, size, mark, label, markmode
      FROM ds, cst2
    ),
    ylabels(y, label) AS (
      SELECT y, MIN(labely) FROM d GROUP BY y
    ),
    yaxis(maxy, miny, stepy , minstepy) AS (
      WITH
        xt0(minx, maxx) AS (
          SELECT  coalesce(miny, min(min(y2),
                  min(y))), coalesce(maxy, max(max(y2),
                  max(y))) + qualitativey
           FROM d, cst2
        ),
        xt1(mx, mn) AS (SELECT maxx, minx FROM xt0),
        xt2(mx, mn, step) AS (SELECT mx, mn, (mx-mn)  FROM xt1),
        
        xt3(mx, mn, ms) AS (
          SELECT mx, mn, first_value(rs) OVER (order by x desc) AS ms
            FROM (SELECT mx, mn, step, f,(mx-mn) as rng,
                         1.0*step/f as rs, 1.0*(mx-mn)/(step/f) AS x
                    FROM xt2, (SELECT 1 AS f UNION ALL SELECT 2
                                UNION ALL SELECT 4
                                UNION ALL SELECT 5)) AS src
                   WHERE x < 10 limit 1),
        xt4(minstepy) AS (
          SELECT MIN(abs(y2-y)) FROM d WHERE y2 != y
        )
      SELECT (mx/ms)*ms, (mn/ms)*ms, coalesce(stepy, ms),
                     coalesce(minstepy, ms, stepy)  FROM xt3, cst2,xt4
    ),
    distinct_mark_n_m(mark, ze, zem, title) AS (
      SELECT DISTINCT mark, n AS ze, m AS zem, title FROM ds0
    ),
    facet0(m, mi, title, radial) AS (
      SELECT md, row_number() OVER () - 1, title, 'radial'
                      IN (SELECT mark FROM distinct_mark_n_m WHERE zem = md)
      FROM (SELECT DISTINCT zem AS md, title AS title
                       FROM distinct_mark_n_m ORDER BY 2, 1)
    ),
    facet(m, mi, xorigin, yorigin, title, radial) AS (
      SELECT m, mi,
        rsx * 1.2 * IFNULL(CASE WHEN (
          0
        ) > 0 THEN mi / (
          0
        ) ELSE mi % (
          2
        )  END, mi),
        rsy  * 1.2 * IFNULL(CASE WHEN (
          2
        ) > 0 THEN mi / (
          2
        ) ELSE mi / (
          0
        )  END, 0),
        title, radial FROM facet0, cst
    ),
    radygrid(m, mi, tty, wty, ttx, ttx2, xorigin, yorigin) AS (
      SELECT m, mi,  rsy / 2 / ((maxy-miny)/stepy) * (value-1) AS tty,
             coalesce(NULL, miny + stepy * (value-1)) AS wty,
             xorigin, xorigin+rsx, xorigin + rsx / 2,
             yorigin + rsy / 2
        FROM generate_series(1), yaxis, cst,
             facet LEFT JOIN ylabels ON ylabels.y = (miny + (value-1) * stepy)
       WHERE radial AND stop = 1+1.0*(maxy-miny)/stepy
    ),
    ypos(m, mi, pcx, pcy, radial) AS (
      SELECT m, mi, xorigin, yorigin + CASE
        WHEN 0 BETWEEN miny AND maxy THEN
          rsy - (0 - miny) * rsy / (maxy-miny)
        WHEN 0 >= maxy THEN 0
        ELSE  rsy
      END, radial FROM yaxis, cst, facet WHERE NOT radial
      UNION ALL
      SELECT m, mi, xorigin + rsx / 2, yorigin + (CASE
        WHEN 0 BETWEEN miny AND maxy THEN
          rsy - (0 - miny) * rsy / 2 / (maxy-miny)
        WHEN 0 >= maxy THEN 0
        ELSE  rsy
      END ) / 2, radial FROM yaxis, cst, facet WHERE radial
    )
  SELECT * FROM radygrid , ypos;
} {}
} ;# end ifcapable vtab

# 2021-03-19
# dbsqlfuzz 01b8355086998f0a452cb31208e80b9d29ca739a
#
# Correlated CTEs should not be materialized.
#
reset_db
do_execsql_test 10.1 {
  SELECT 1 AS c WHERE (
    SELECT (
      WITH t1(a) AS (VALUES( c ))
      SELECT ( SELECT t1a.a FROM t1 AS t1a, t1 AS t1x )
      FROM t1 AS xyz GROUP BY 1
    )
  )
} {1}

# 2021-05-21
# Forum post https://sqlite.org/forum/forumpost/aa4a7a3980
#
ifcapable altertable {
reset_db
  do_execsql_test 11.1 {
    CREATE TABLE t1(a);
    CREATE VIEW v2(c) AS
        WITH x AS (
          WITH y AS (
             WITH z AS(SELECT * FROM t1)
             SELECT * FROM v2
          ) SELECT a
        ) SELECT * from t1;
    ALTER TABLE t1 RENAME COLUMN a TO b;
    SELECT sql FROM sqlite_schema WHERE name='t1';
  } {{CREATE TABLE t1(b)}}
  do_catchsql_test 11.2 {
    INSERT INTO t1 VALUES(55);
    SELECT * FROM v2;
  } {0 55}
  do_catchsql_test 11.3 {
    DROP VIEW v2;
    CREATE VIEW v2(c) AS
        WITH x AS (
          WITH y AS (
             WITH z AS(SELECT * FROM t1)
             SELECT * FROM v2
          ) SELECT a
        ) SELECT * from t1, x;
    SELECT * FROM v2;
  } {1 {no such column: a}}
  do_catchsql_test 11.4 {
    DROP VIEW v2;
    CREATE VIEW v2(c) AS
        WITH x AS (
          WITH y AS (
             WITH z AS(SELECT * FROM t1)
             SELECT * FROM v2
          ) SELECT *
        ) SELECT * from t1, x;
    SELECT * FROM v2;
  } {1 {no tables specified}}
  do_catchsql_test 11.5 {
    WITH x AS (
      WITH y AS (
         WITH z AS(SELECT * FROM t1)
         SELECT * FROM no_such_table
      ) SELECT a
    ) SELECT * from t1;
  } {0 55}
}

# 2021-05-23 dbsqlfuzz 6b7a144674e215f06ddfeb9042c873d9ee956ac0 */
reset_db
ifcapable altertable {
  do_execsql_test 12.1 {
    CREATE TABLE t1(a);
    INSERT INTO t1 VALUES(1),('hello'),(4.25),(NULL),(x'3c626c6f623e');
    CREATE VIEW v2(c) AS WITH x AS (WITH y AS (WITH z AS(SELECT * FROM t1) SELECT * FROM v2) SELECT a) SELECT * from t1;
    CREATE VIEW v3(c) AS WITH x AS (WITH y AS (WITH z AS(SELECT * FROM v2) SELECT * FROM v3) SELECT a) SELECT * from t1;
    ALTER TABLE t1 RENAME TO t1x;
    SELECT quote(c) FROM v3;
  } {1 'hello' 4.25 NULL X'3C626C6F623E'}
}

# 2021-08-11 https://sqlite.org/forum/forumpost/d496c3d29bc93736
reset_db
do_execsql_test 13.1 {
  WITH
    t1(x) AS (SELECT 111),
    t2(y) AS (SELECT 222),
    t3(z) AS (SELECT * FROM t2 WHERE false UNION ALL SELECT * FROM t2)
  SELECT * FROM t1, t3;
} {111 222}

finish_test

Changes to test/with3.test.

28
29
30
31
32
33
34








35
36
37
38
39
40
41
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49







+
+
+
+
+
+
+
+







  WITH i(x) AS (
    WITH j AS (SELECT 10)
    SELECT 5 FROM t0 UNION SELECT 8 FROM m
  )
  SELECT * FROM i;
} {1 {no such table: m}}

# 2019-11-09 dbfuzzcheck find
do_catchsql_test 1.1 {
  CREATE VIEW v1(x,y) AS
    WITH t1(a,b) AS (VALUES(1,2))
    SELECT * FROM nosuchtable JOIN t1;
  SELECT * FROM v1;
} {1 {no such table: main.nosuchtable}}

# Additional test cases that came out of the work to
# fix for Kostya's problem.
#
do_execsql_test 2.0 {
 WITH
  x1 AS (SELECT 10),
  x2 AS (SELECT 11),
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
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







-
+



-
-
-
+
+
+







-
+



-
-
-
+
+
+















-
+


-
-
+
+

-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  }

  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
    |--CO-ROUTINE 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
    |--CO-ROUTINE 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
  |--CO-ROUTINE c
  |  |--SETUP
  |  |  |--SCAN CONSTANT ROW
  |  |  `--SCALAR SUBQUERY
  |  |     `--SCAN TABLE w2
  |  |  `--SCALAR SUBQUERY xxxxxx
  |  |     `--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 c
  |     `--SCAN w1
  |--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 (
          WITH t1 AS (SELECT 1 AS c1 GROUP BY 1) 
          SELECT a.c1 FROM t1 AS a, t1 AS b
          WHERE anoncol1 = 1
        )
        SELECT (SELECT 1 FROM t2) FROM t2
      ) 
      SELECT t3col1 FROM t3 WHERE t3col1
    ) FROM (SELECT 1 AS anoncol1)
  )
  SELECT t5col1, t5col1 FROM t5
} {1 1}
do_execsql_test 4.1 {
  SELECT EXISTS (
    WITH RECURSIVE Table0 AS (
      WITH RECURSIVE Table0(Col0) AS (SELECT ALL 1  ) 
      SELECT ALL (
        WITH RECURSIVE Table0 AS (
          WITH RECURSIVE Table0 AS (
            WITH RECURSIVE Table0 AS (SELECT DISTINCT 1  GROUP BY 1  ) 
            SELECT DISTINCT * FROM Table0 NATURAL INNER JOIN Table0
            WHERE Col0 = 1  
          )
          SELECT ALL (SELECT DISTINCT * FROM Table0) FROM Table0 WHERE Col0 = 1
        ) 
        SELECT ALL * FROM Table0  NATURAL INNER JOIN  Table0      
      ) FROM Table0 ) 
      SELECT DISTINCT * FROM Table0  NATURAL INNER JOIN  Table0      
    ); 
} {1}

# 2020-01-18 chrome ticket 1043236
# Correct handling of the sequence:
#    OP_OpenEphem
#    OP_OpenDup
#    Op_OpenEphem
#    OP_OpenDup
#
do_execsql_test 4.2 {
  SELECT (
    WITH t1(a) AS (VALUES(1))
    SELECT (
      WITH t2(b) AS (
        WITH t3(c) AS (
          WITH t4(d) AS (VALUES('elvis'))
          SELECT t4a.d FROM t4 AS t4a JOIN t4 AS t4b LEFT JOIN t4 AS t4c
        )
        SELECT c FROM t3 WHERE a = 1
      )
      SELECT t2a.b FROM t2 AS t2a JOIN t2 AS t2x
    )
    FROM t1 GROUP BY 1
  )
  GROUP BY 1;
} {elvis}

# 2021-02-13
# Avoid manifesting the same CTE multiple times.
#
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 c
  |  |--SETUP
  |  |  `--SCAN CONSTANT ROW
  |  `--RECURSIVE STEP
  |     `--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}

#-------------------------------------------------------------------------
# At one point this would incorrectly report "circular reference: cte1"
#
do_catchsql_test 6.0 {
  with
    cte1(x, y) AS ( select 1, 2, 3 ),
    cte2(z) as ( select 1 from cte1 )
  select * from cte2, cte1;
} {1 {table cte1 has 3 values for 2 columns}}

do_catchsql_test 6.1 {
  with
    cte1(x, y) AS ( select 1, 2, 3 ),
    cte2(z) as ( select 1 from cte1 UNION ALL SELECT z+1 FROM cte2 WHERE z<5)
  select * from cte2, cte1;
} {1 {table cte1 has 3 values for 2 columns}}




finish_test

Added test/with5.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
189
190
191
192
193
194
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2020-10-19
#
# 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 recursive common table expressions with
# multiple recursive terms in the compound select.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set ::testprefix with5

ifcapable {!cte} {
  finish_test
  return
}

do_execsql_test 100 {
  CREATE TABLE link(aa INT, bb INT);
  CREATE INDEX link_f ON link(aa,bb);
  CREATE INDEX link_t ON link(bb,aa);
  INSERT INTO link(aa,bb) VALUES
    (1,3),
    (5,3),
    (7,1),
    (7,9),
    (9,9),
    (5,11),
    (11,7),
    (2,4),
    (4,6),
    (8,6);
} {}
do_execsql_test 110 {
  WITH RECURSIVE closure(x) AS (
     VALUES(1)
     UNION
     SELECT aa FROM closure, link WHERE link.bb=closure.x
     UNION
     SELECT bb FROM closure, link WHERE link.aa=closure.x
  )
  SELECT x FROM closure ORDER BY x;
} {1 3 5 7 9 11}
do_execsql_test 111 {
  WITH RECURSIVE closure(x) AS (
     VALUES(1)
     UNION
     SELECT aa FROM link, closure WHERE link.bb=closure.x
     UNION
     SELECT bb FROM closure, link WHERE link.aa=closure.x
  )
  SELECT x FROM closure ORDER BY x;
} {1 3 5 7 9 11}
do_execsql_test 112 {
  WITH RECURSIVE closure(x) AS (
     VALUES(1)
     UNION
     SELECT bb FROM closure, link WHERE link.aa=closure.x
     UNION
     SELECT aa FROM link, closure WHERE link.bb=closure.x
  )
  SELECT x FROM closure ORDER BY x;
} {1 3 5 7 9 11}
do_execsql_test 113 {
  WITH RECURSIVE closure(x) AS (
     VALUES(1),(200),(300),(400)
     INTERSECT
     VALUES(1)
     UNION
     SELECT bb FROM closure, link WHERE link.aa=closure.x
     UNION
     SELECT aa FROM link, closure WHERE link.bb=closure.x
  )
  SELECT x FROM closure ORDER BY x;
} {1 3 5 7 9 11}
do_execsql_test 114 {
  WITH RECURSIVE closure(x) AS (
     VALUES(1),(200),(300),(400)
     UNION ALL
     VALUES(2)
     UNION
     SELECT bb FROM closure, link WHERE link.aa=closure.x
     UNION
     SELECT aa FROM link, closure WHERE link.bb=closure.x
  )
  SELECT x FROM closure ORDER BY x;
} {1 2 3 4 5 6 7 8 9 11 200 300 400}

do_catchsql_test 120 {
  WITH RECURSIVE closure(x) AS (
     VALUES(1),(200),(300),(400)
     UNION ALL
     VALUES(2)
     UNION ALL
     SELECT bb FROM closure, link WHERE link.aa=closure.x
     UNION
     SELECT aa FROM link, closure WHERE link.bb=closure.x
  )
  SELECT x FROM closure ORDER BY x;
} {1 {circular reference: closure}}
do_catchsql_test 121 {
  WITH RECURSIVE closure(x) AS (
     VALUES(1),(200),(300),(400)
     UNION ALL
     VALUES(2)
     UNION
     SELECT bb FROM closure, link WHERE link.aa=closure.x
     UNION ALL
     SELECT aa FROM link, closure WHERE link.bb=closure.x
  )
  SELECT x FROM closure ORDER BY x;
} {1 {circular reference: closure}}

do_execsql_test 130 {
  WITH RECURSIVE closure(x) AS (
    SELECT 1 AS x
    UNION
    SELECT aa FROM link JOIN closure ON bb=x
    UNION
    SELECT bb FROM link JOIN closure on aa=x
    ORDER BY x LIMIT 4
  )
  SELECT * FROM closure;
} {1 3 5 7}
do_execsql_test 131 {
  WITH RECURSIVE closure(x) AS (
    SELECT 1 AS x
    UNION ALL
    SELECT 2
    UNION
    SELECT aa FROM link JOIN closure ON bb=x
    UNION
    SELECT bb FROM link JOIN closure on aa=x
    ORDER BY x LIMIT 4
  )
  SELECT * FROM closure;
} {1 2 3 4}

do_execsql_test 200 {
  CREATE TABLE linkA(aa1,aa2);
  INSERT INTO linkA(aa1,aa2) VALUES(1,3),(5,7),(9,11);
  CREATE TABLE linkB(bb1,bb2);
  INSERT INTO linkB(bb1,bb2) VALUES(7,9),(11,13),(3,5);
  CREATE TABLE linkC(cc1,cc2);
  INSERT INTO linkC(cc1,cc2) VALUES(1,2),(2,4),(6,8);
  CREATE TABLE linkD(dd1,dd2);
  INSERT INTO linkD(dd1,dd2) VALUES(4,6),(100,110);
} {}
do_execsql_test 210 {
  WITH RECURSIVE closure(x) AS (
    VALUES(1)
    UNION ALL
    SELECT aa2 FROM linkA JOIN closure ON x=aa1
    UNION ALL
    SELECT bb2 FROM linkB JOIN closure ON x=bb1
    UNION ALL
    SELECT cc2 FROM linkC JOIN closure ON x=cc1
    UNION ALL
    SELECT dd2 FROM linkD JOIN closure ON x=dd1
  )
  SELECT x FROM closure ORDER BY +x;
} {1 2 3 4 5 6 7 8 9 11 13}
do_execsql_test 220 {
  CREATE TABLE linkA_ipk(aa1 INTEGER PRIMARY KEY,aa2);
  INSERT INTO linkA_ipk(aa1,aa2) SELECT aa1, aa2 FROM linkA;
  CREATE TABLE linkB_ipk(bb1 INTEGER PRIMARY KEY,bb2);
  INSERT INTO linkB_ipk(bb1,bb2) SELECT bb1, bb2 FROM linkB;
  CREATE TABLE linkC_ipk(cc1 INTEGER PRIMARY KEY,cc2);
  INSERT INTO linkC_ipk(cc1,cc2) SELECT cc1, cc2 FROM linkC;
  CREATE TABLE linkD_ipk(dd1 INTEGER PRIMARY KEY,dd2);
  INSERT INTO linkD_ipk(dd1,dd2) SELECT dd1, dd2 FROM linkD;
  WITH RECURSIVE closure(x) AS (
    VALUES(1)
    UNION ALL
    SELECT aa2 FROM linkA_ipk JOIN closure ON x=aa1
    UNION ALL
    SELECT bb2 FROM linkB_ipk JOIN closure ON x=bb1
    UNION ALL
    SELECT cc2 FROM linkC_ipk JOIN closure ON x=cc1
    UNION ALL
    SELECT dd2 FROM linkD_ipk JOIN closure ON x=dd1
  )
  SELECT x FROM closure ORDER BY +x;
} {1 2 3 4 5 6 7 8 9 11 13}


finish_test

Added test/with6.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2021-02-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.  The
# focus of this file is the MATERIALIZED hint to common table expressions
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set ::testprefix with6

ifcapable {!cte} {
  finish_test
  return
}

do_execsql_test 100 {
  WITH c(x) AS (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 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 c
  |  `--SCAN 2 CONSTANT ROWS
  |--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 c
  |  `--SCAN 2 CONSTANT ROWS
  |--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 c
  |  `--SCAN 2 CONSTANT ROWS
  |--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
  |--CO-ROUTINE c1
  |  |--CO-ROUTINE c
  |  |  `--SCAN 2 CONSTANT ROWS
  |  `--SCAN c
  |--MATERIALIZE c2
  |  |--CO-ROUTINE c
  |  |  `--SCAN 2 CONSTANT ROWS
  |  `--SCAN c
  |--MATERIALIZE c3
  |  |--CO-ROUTINE c
  |  |  `--SCAN 2 CONSTANT ROWS
  |  `--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 {
  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;
} {000 001 010 011 100 101 110 111}
do_eqp_test 141 {
  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
  |--CO-ROUTINE c1
  |  |--MATERIALIZE c
  |  |  `--SCAN 2 CONSTANT ROWS
  |  `--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
  |--CO-ROUTINE c1
  |  |--MATERIALIZE c
  |  |  `--SCAN 2 CONSTANT ROWS
  |  `--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 c
  |  `--SCAN 2 CONSTANT ROWS
  |--SCAN c2
  `--CORRELATED SCALAR 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 c
  |  `--SCAN 2 CONSTANT ROWS
  |--SCAN c2
  `--CORRELATED SCALAR SUBQUERY xxxxxx
     |--CO-ROUTINE c
     |  `--SCAN 2 CONSTANT ROWS
     `--SCAN c
}


do_execsql_test 200 {
  CREATE TABLE t1(x);
  INSERT INTO t1(x) VALUES(4);
  CREATE VIEW t2(y) AS
    WITH c(z) AS (VALUES(4),(5),(6))
    SELECT c1.z+c2.z*100+t1.x*10000
      FROM t1,
           (SELECT z FROM c LIMIT 5) AS c1,
           (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_execsql_test 210 {
  DROP VIEW t2;
  CREATE VIEW t2(y) AS
    WITH c(z) AS NOT MATERIALIZED (VALUES(4),(5),(6))
    SELECT c1.z+c2.z*100+t1.x*10000
      FROM t1,
           (SELECT z FROM c LIMIT 5) AS c1,
           (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
  |--CO-ROUTINE c1
  |  |--CO-ROUTINE c
  |  |  `--SCAN 3 CONSTANT ROWS
  |  `--SCAN c
  |--MATERIALIZE c2
  |  |--CO-ROUTINE c
  |  |  `--SCAN 3 CONSTANT ROWS
  |  `--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
      FROM t1,
           (SELECT z FROM c LIMIT 5) AS c1,
           (SELECT z FROM c LIMIT 5) AS c2;
  SELECT y FROM t2 ORDER BY y;
} {40404 40405 40406 40504 40505 40506 40604 40605 40606}

# 2022-04-22: Do not allow flattening of a MATERIALIZED CTE into
# an outer query.
#
reset_db
db null -
do_execsql_test 300 {
  CREATE TABLE t2(a INT,b INT,d INT); INSERT INTO t2 VALUES(4,5,6),(7,8,9);
  CREATE TABLE t3(a INT,b INT,e INT); INSERT INTO t3 VALUES(3,3,3),(8,8,8);
} {}
do_execsql_test 310 {
  WITH t23 AS MATERIALIZED (SELECT * FROM t2 FULL JOIN t3 USING(b))
  SELECT * FROM t23;
} {
  4 5 6 - -
  7 8 9 8 8
  - 3 - 3 3
}
do_eqp_test 311 {
  WITH t23 AS MATERIALIZED (SELECT * FROM t2 FULL JOIN t3 USING(b))
  SELECT * FROM t23;
} {
  QUERY PLAN
  |--MATERIALIZE t23
  |  |--SCAN t2
  |  |--SCAN t3 LEFT-JOIN
  |  `--RIGHT-JOIN t3
  |     `--SCAN t3
  `--SCAN t23
}
do_execsql_test 320 {
  WITH t23 AS NOT MATERIALIZED (SELECT * FROM t2 FULL JOIN t3 USING(b))
  SELECT * FROM t23;
} {
  4 5 6 - -
  7 8 9 8 8
  - 3 - 3 3
}
do_eqp_test 321 {
  WITH t23 AS NOT MATERIALIZED (SELECT * FROM t2 FULL JOIN t3 USING(b))
  SELECT * FROM t23;
} {
  QUERY PLAN
  |--SCAN t2
  |--SCAN t3 LEFT-JOIN
  `--RIGHT-JOIN t3
     `--SCAN t3
}
do_execsql_test 330 {
  WITH t23 AS (SELECT * FROM t2 FULL JOIN t3 USING(b))
  SELECT * FROM t23;
} {
  4 5 6 - -
  7 8 9 8 8
  - 3 - 3 3
}
do_eqp_test 331 {
  WITH t23 AS (SELECT * FROM t2 FULL JOIN t3 USING(b))
  SELECT * FROM t23;
} {
  QUERY PLAN
  |--SCAN t2
  |--SCAN t3 LEFT-JOIN
  `--RIGHT-JOIN t3
     `--SCAN t3
}

# 2023-02-01
# https://sqlite.org/forum/forumpost/1d571c02963355ed
#
# Just because a CTE is used more than once, does not mean it should be
# marked with M10d_Yes and hence prohibited from participating in the
# query flattening optimization.
#
reset_db
db eval {
  CREATE TABLE raw(country,date,total,delta, UNIQUE(country,date));
}
do_eqp_test 400 {
  with recursive
    init(country, date, fin) AS (SELECT country, min(date), max(date) FROM raw WHERE total > 0 GROUP BY country),
    src(country, date) AS (SELECT raw.country, raw.date
        FROM raw JOIN init i on raw.country = i.country AND raw.date > i.date
        ORDER BY raw.country, raw.date),
    vals(country, date, x, y) AS (SELECT src.country, src.date, julianday(raw.date) - julianday(src.date), log(delta+1)
        FROM src JOIN raw on raw.country = src.country AND raw.date > date(src.date,'-7 days') AND raw.date <= src.date AND delta >= 0),
    sums(country, date, x2, x, n, xy, y) AS (SELECT country, date, sum(x*x*1.0), sum(x*1.0), sum(1.0), sum(x*y*1.0), sum(y*1.0) FROM vals GROUP BY 1, 2),
    mult(country, date, m) AS (SELECT country, date, 1.0/(x2 * n - x * x) FROM sums),
    inv(country, date, a,b,c,d) AS (SELECT mult.country, mult.date, n * m, -x * m, -x * m, x2 * m
        FROM mult JOIN sums on sums.country=mult.country AND mult.date=sums.date),
    fit(country, date, a, b) AS (SELECT inv.country, inv.date, a * xy + b * y, c * xy + d * y
        FROM inv
        JOIN mult on mult.country = inv.country AND mult.date = inv.date
        JOIN sums on sums.country = mult.country AND sums.date = mult.date
  )
  SELECT *, nFin/nPrev - 1 AS growth, log(2)/log(nFin/nPrev) AS doubling
    FROM (SELECT f.*, exp(b) - 1 AS nFin, exp(a* (-1) + b) - 1 AS nPrev
            FROM fit f JOIN init i on i.country = f.country AND f.date <= date(i.fin,'-3 days'))
   WHERE nPrev > 0 AND nFin > 0;
} {
  QUERY PLAN
  |--MATERIALIZE sums
  |  |--MATERIALIZE src
  |  |  |--MATERIALIZE init
  |  |  |  `--SCAN raw USING INDEX sqlite_autoindex_raw_1
  |  |  |--SCAN i
  |  |  |--SEARCH raw USING COVERING INDEX sqlite_autoindex_raw_1 (country=? AND date>?)
  |  |  `--USE TEMP B-TREE FOR ORDER BY
  |  |--SCAN src
  |  |--SEARCH raw USING INDEX sqlite_autoindex_raw_1 (country=? AND date>? AND date<?)
  |  `--USE TEMP B-TREE FOR GROUP BY
  |--SCAN sums
  |--SEARCH sums USING AUTOMATIC COVERING INDEX (country=? AND date=?)
  |--SEARCH sums USING AUTOMATIC COVERING INDEX (country=? AND date=?)
  |--SEARCH sums USING AUTOMATIC COVERING INDEX (country=? AND date=?)
  `--SEARCH i USING AUTOMATIC COVERING INDEX (country=?)
}


finish_test

Changes to test/without_rowid1.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
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







+
+
+
+














+
+
+
+
+
+
+







# This file implements regression tests for SQLite library.  The
# focus of this file is testing WITHOUT ROWID tables.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix without_rowid1

proc do_execsql_test_if_vtab {tn sql {res {}}} {
  ifcapable vtab { uplevel [list do_execsql_test $tn $sql $res] }
}

# Create and query a WITHOUT ROWID table.
#
do_execsql_test without_rowid1-1.0 {
  CREATE TABLE t1(a,b,c,d, PRIMARY KEY(c,a)) WITHOUT ROWID;
  CREATE INDEX t1bd ON t1(b, d);
  INSERT INTO t1 VALUES('journal','sherman','ammonia','helena');
  INSERT INTO t1 VALUES('dynamic','juliet','flipper','command');
  INSERT INTO t1 VALUES('journal','sherman','gamma','patriot');
  INSERT INTO t1 VALUES('arctic','sleep','ammonia','helena');
  SELECT *, '|' FROM t1 ORDER BY c, a;
} {arctic sleep ammonia helena | journal sherman ammonia helena | dynamic juliet flipper command | journal sherman gamma patriot |}

integrity_check without_rowid1-1.0ic

do_execsql_test_if_vtab without_rowid1-1.0ixi {
  SELECT name, key FROM pragma_index_xinfo('t1');
} {c 1 a 1 b 0 d 0}
do_execsql_test_if_vtab without_rowid1-1.0tl {
  SELECT wr FROM pragma_table_list('t1');
} {1}

do_execsql_test without_rowid1-1.1 {
  SELECT *, '|' FROM t1 ORDER BY +c, a;
} {arctic sleep ammonia helena | journal sherman ammonia helena | dynamic juliet flipper command | journal sherman gamma patriot |}

do_execsql_test without_rowid1-1.2 {
  SELECT *, '|' FROM t1 ORDER BY c DESC, a DESC;
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
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







-
-
-
-
-

















+
+
+












+
+
+
+
+






+
+
+
+
+














+
+
+
+
+








# Verify that ANALYZE works
#
do_execsql_test without_rowid1-1.50 {
  ANALYZE;
  SELECT * FROM sqlite_stat1 ORDER BY idx;
} {t1 t1 {4 2 1} t1 t1bd {4 2 2}}
ifcapable stat3 {
  do_execsql_test without_rowid1-1.51 {
    SELECT DISTINCT tbl, idx FROM sqlite_stat3 ORDER BY idx;
  } {t1 t1 t1 t1bd}
}
ifcapable stat4 {
  do_execsql_test without_rowid1-1.52 {
    SELECT DISTINCT tbl, idx FROM sqlite_stat4 ORDER BY idx;
  } {t1 t1 t1 t1bd}
}

#----------

do_execsql_test 2.1.1 {
  CREATE TABLE t4 (a COLLATE nocase PRIMARY KEY, b) WITHOUT ROWID;
  INSERT INTO t4 VALUES('abc', 'def');
  SELECT * FROM t4;
} {abc def}
do_execsql_test 2.1.2 {
  UPDATE t4 SET a = 'ABC';
  SELECT * FROM t4;
} {ABC def}
do_execsql_test_if_vtab 2.1.3 {
  SELECT name, coll, key FROM pragma_index_xinfo('t4');
} {a nocase 1 b BINARY 0}

do_execsql_test 2.2.1 {
  DROP TABLE t4;
  CREATE TABLE t4 (b, a COLLATE nocase PRIMARY KEY) WITHOUT ROWID;
  INSERT INTO t4(a, b) VALUES('abc', 'def');
  SELECT * FROM t4;
} {def abc}

do_execsql_test 2.2.2 {
  UPDATE t4 SET a = 'ABC', b = 'xyz';
  SELECT * FROM t4;
} {xyz ABC}

do_execsql_test_if_vtab 2.2.3 {
  SELECT name, coll, key FROM pragma_index_xinfo('t4');
} {a nocase 1 b BINARY 0}


do_execsql_test 2.3.1 {
  CREATE TABLE t5 (a, b, PRIMARY KEY(b, a)) WITHOUT ROWID;
  INSERT INTO t5(a, b) VALUES('abc', 'def');
  UPDATE t5 SET a='abc', b='def';
} {}

do_execsql_test_if_vtab 2.3.2 {
  SELECT name, coll, key FROM pragma_index_xinfo('t5');
} {b BINARY 1 a BINARY 1}


do_execsql_test 2.4.1 {
  CREATE TABLE t6 (
    a COLLATE nocase, b, c UNIQUE, PRIMARY KEY(b, a)
  ) WITHOUT ROWID;

  INSERT INTO t6(a, b, c) VALUES('abc', 'def', 'ghi');
  UPDATE t6 SET a='ABC', c='ghi';
} {}

do_execsql_test 2.4.2 {
  SELECT * FROM t6 ORDER BY b, a;
  SELECT * FROM t6 ORDER BY c;
} {ABC def ghi ABC def ghi}

do_execsql_test_if_vtab 2.4.3 {
  SELECT name, coll, key FROM pragma_index_xinfo('t6');
} {b BINARY 1 a nocase 1 c BINARY 0}


#-------------------------------------------------------------------------
# Unless the destination table is completely empty, the xfer optimization 
# is disabled for WITHOUT ROWID tables. The following tests check for
# some problems that might occur if this were not the case.
#
reset_db
316
317
318
319
320
321
322
323

324
325
326
327
328
329
330
340
341
342
343
344
345
346

347
348
349
350
351
352
353
354







-
+







     a INT CHECK( rowid!=33 ),
     b TEXT PRIMARY KEY
  );
  INSERT INTO t70a(a,b) VALUES(99,'hello');
} {}
do_catchsql_test 7.2 {
  INSERT INTO t70a(rowid,a,b) VALUES(33,99,'xyzzy');
} {1 {CHECK constraint failed: t70a}}
} {1 {CHECK constraint failed: rowid!=33}}
do_catchsql_test 7.3 {
  CREATE TABLE t70b(
     a INT CHECK( rowid!=33 ),
     b TEXT PRIMARY KEY
  ) WITHOUT ROWID;
} {1 {no such column: rowid}}

351
352
353
354
355
356
357


358










































































































359
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







+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  UPDATE t2 SET b=1 WHERE b='';
}

do_execsql_test 10.1 {
  DELETE FROM t2 WHERE b=1
}

#-------------------------------------------------------------------------
# UNIQUE constraint violation in an UPDATE with a multi-column PK.
  
#
reset_db
do_execsql_test 10.0 {
  CREATE TABLE t1(a, b, c UNIQUE, PRIMARY KEY(a, b)) WITHOUT ROWID;
  INSERT INTO t1 VALUES('a', 'a', 1);
  INSERT INTO t1 VALUES('a', 'b', 2);
  INSERT INTO t1 VALUES('b', 'a', 3);
  INSERT INTO t1 VALUES('b', 'b', 4);
}

do_catchsql_test 10.1 {
  UPDATE t1 SET c=1 WHERE (a, b) = ('a', 'a');
} {0 {}}
do_catchsql_test 10.2 {
  UPDATE t1 SET c=1 WHERE (a, b) = ('a', 'b');
} {1 {UNIQUE constraint failed: t1.c}}
do_catchsql_test 10.3 {
  UPDATE t1 SET c=1 WHERE (a, b) = ('b', 'a');
} {1 {UNIQUE constraint failed: t1.c}}
do_catchsql_test 10.4 {
  UPDATE t1 SET c=1 WHERE (a, b) = ('b', 'b');
} {1 {UNIQUE constraint failed: t1.c}}
do_catchsql_test 10.5 {
  UPDATE t1 SET c=1 WHERE (a, b) = ('c', 'c');
} {0 {}}

do_execsql_test 10.6 {
  CREATE TRIGGER t1_tr BEFORE UPDATE ON t1 BEGIN
    DELETE FROM t1 WHERE a = new.a;
  END;
  UPDATE t1 SET c = c+1 WHERE a = 'a';
  SELECT * FROM t1;
} {b a 3  b b 4}

# 2019-04-29 ticket https://www.sqlite.org/src/info/3182d3879020ef3
do_execsql_test 11.1 {
  CREATE TABLE t11(a TEXT PRIMARY KEY, b INT) WITHOUT ROWID;
  CREATE INDEX t11a ON t11(a COLLATE NOCASE);
  INSERT INTO t11(a,b) VALUES ('A',1),('a',2);
  PRAGMA integrity_check;
  SELECT a FROM t11 ORDER BY a COLLATE binary;
} {ok A a}

# 2019-05-13 ticket https://www.sqlite.org/src/info/bba7b69f9849b5b
do_execsql_test 12.1 {
  DROP TABLE IF EXISTS t0;
  CREATE TABLE t0 (c0 INTEGER PRIMARY KEY DESC, c1 UNIQUE DEFAULT NULL) WITHOUT ROWID;
  INSERT INTO t0(c0) VALUES (1), (2), (3), (4), (5);
  REINDEX;
  PRAGMA integrity_check;
} {ok}

# 2019-11-07 ticket https://www.sqlite.org/src/info/302027baf1374498
# The xferCompatibleIndex() function confuses a PRIMARY KEY index
# with a UNIQUE index.
#
do_execsql_test 13.10 {
  DROP TABLE IF EXISTS t0;
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t0(
    c0,
    c1 UNIQUE,
    PRIMARY KEY(c1, c1)
  ) WITHOUT ROWID;
  INSERT INTO t0(c0,c1) VALUES('abc','xyz');
  CREATE TABLE t1(
    c0,
    c1 UNIQUE,
    PRIMARY KEY(c1, c1)
  ) WITHOUT ROWID;
  INSERT INTO t1 SELECT * FROM t0;
  PRAGMA integrity_check;
  SELECT * FROM t0, t1;
} {ok abc xyz abc xyz}

# 2021-05-13 https://sqlite.org/forum/forumpost/6c8960f545
reset_db
ifcapable altertable {
  do_execsql_test 14.1 {
    CREATE TABLE t1(a INT PRIMARY KEY) WITHOUT ROWID;
    INSERT INTO t1(a) VALUES(10);
    ALTER TABLE t1 ADD COLUMN b INT;
    SELECT * FROM t1 WHERE a=20 OR (a=10 AND b=10);
  } {}
  do_execsql_test 14.2 {
    CREATE TABLE dual AS SELECT 'X' AS dummy;
    EXPLAIN QUERY PLAN SELECT * FROM dual, t1 WHERE a=10 AND b=10;
  } {~/b=/}
}

# 2022-01-01 https://sqlite.org/forum/forumpost/b03d86f951 PoC #1
# Omit an assert() from 2013 that no longer serves any purpose and
# is no longer always true.
#
ifcapable altertable {
  reset_db
  do_execsql_test 15.1 {
    PRAGMA writable_schema=ON;
    CREATE TABLE sqlite_sequence (name PRIMARY KEY) WITHOUT ROWID;
    PRAGMA writable_schema=OFF;
    CREATE TABLE c1(x);
    INSERT INTO sqlite_sequence(name) VALUES('c0'),('c1'),('c2');
    ALTER TABLE c1 RENAME TO a;
    SELECT name FROM sqlite_sequence ORDER BY +name;
  } {a c0 c2}
}
finish_test

Changes to test/without_rowid3.test.

413
414
415
416
417
418
419
420

421
422
423
424
425
426
427

428
429
430
431
432
433
434
413
414
415
416
417
418
419

420
421
422
423
424
425
426

427
428
429
430
431
432
433
434







-
+






-
+







    INSERT INTO ab VALUES(1, 'b');
    INSERT INTO cd VALUES(1, 'd');
    INSERT INTO ef VALUES(1, 'e');
  }
} {}
do_test without_rowid3-3.1.3 {
  catchsql { UPDATE ab SET a = 5 }
} {1 {CHECK constraint failed: ef}}
} {1 {CHECK constraint failed: e!=5}}
do_test without_rowid3-3.1.4 {
  execsql { SELECT * FROM ab }
} {1 b}
do_test without_rowid3-3.1.4 {
  execsql BEGIN;
  catchsql { UPDATE ab SET a = 5 }
} {1 {CHECK constraint failed: ef}}
} {1 {CHECK constraint failed: e!=5}}
do_test without_rowid3-3.1.5 {
  execsql COMMIT;
  execsql { SELECT * FROM ab; SELECT * FROM cd; SELECT * FROM ef }
} {1 b 1 d 1 e}

do_test without_rowid3-3.2.1 {
  execsql BEGIN;
917
918
919
920
921
922
923

924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944

945
946
947
948
949
950
951
952
953
954
955
956

957
958
959
960
961
962
963
964
965
966

967
968
969
970
971
972
973
974
975
976
977
978

979
980
981
982
983
984
985
986
987

988
989
990
991
992
993
994
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944

945
946
947
948
949
950
951
952
953
954
955
956

957
958
959
960
961
962
963
964
965
966

967
968
969
970
971
972
973
974
975
976
977
978

979
980
981
982
983
984
985
986
987

988
989
990
991
992
993
994
995







+




















-
+











-
+









-
+











-
+








-
+







drop_all_tables
ifcapable altertable {
  do_test without_rowid3-14.1.1 {
    # Adding a column with a REFERENCES clause is not supported.
    execsql { 
      CREATE TABLE t1(a PRIMARY KEY) WITHOUT rowid;
      CREATE TABLE t2(a, b);
      INSERT INTO t2(a,b) VALUES(1,2);
    }
    catchsql { ALTER TABLE t2 ADD COLUMN c REFERENCES t1 }
  } {0 {}}
  do_test without_rowid3-14.1.2 {
    catchsql { ALTER TABLE t2 ADD COLUMN d DEFAULT NULL REFERENCES t1 }
  } {0 {}}
  do_test without_rowid3-14.1.3 {
    catchsql { ALTER TABLE t2 ADD COLUMN e REFERENCES t1 DEFAULT NULL}
  } {0 {}}
  do_test without_rowid3-14.1.4 {
    catchsql { ALTER TABLE t2 ADD COLUMN f REFERENCES t1 DEFAULT 'text'}
  } {1 {Cannot add a REFERENCES column with non-NULL default value}}
  do_test without_rowid3-14.1.5 {
    catchsql { ALTER TABLE t2 ADD COLUMN g DEFAULT CURRENT_TIME REFERENCES t1 }
  } {1 {Cannot add a REFERENCES column with non-NULL default value}}
  do_test without_rowid3-14.1.6 {
    execsql { 
      PRAGMA foreign_keys = off;
      ALTER TABLE t2 ADD COLUMN h DEFAULT 'text' REFERENCES t1;
      PRAGMA foreign_keys = on;
      SELECT sql FROM sqlite_master WHERE name='t2';
      SELECT sql FROM sqlite_schema WHERE name='t2';
    }
  } {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}}
  
  
  # Test the sqlite_rename_parent() function directly.
  #
  proc test_rename_parent {zCreate zOld zNew} {
    db eval {SELECT sqlite_rename_table(
        'main', 'table', 't1', $zCreate, $zOld, $zNew, 0
    )}
  }
  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1
  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db
  do_test without_rowid3-14.2.1.1 {
    test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3
  } {{CREATE TABLE t1(a REFERENCES "t3")}}
  do_test without_rowid3-14.2.1.2 {
    test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t4 t3
  } {{CREATE TABLE t1(a REFERENCES t2)}}
  do_test without_rowid3-14.2.1.3 {
    test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3
  } {{CREATE TABLE t1(a REFERENCES "t3")}}
  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0
  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db
  
  # Test ALTER TABLE RENAME TABLE a bit.
  #
  do_test without_rowid3-14.2.2.1 {
    drop_all_tables
    execsql {
      CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1) WITHOUT rowid;
      CREATE TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2)
            WITHOUT rowid;
      CREATE TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1);
    }
    execsql { SELECT sql FROM sqlite_master WHERE type = 'table'}
    execsql { SELECT sql FROM sqlite_schema WHERE type = 'table'}
  } [list \
    {CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1) WITHOUT rowid}       \
    {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2)
            WITHOUT rowid}    \
    {CREATE TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1)}  \
  ]
  do_test without_rowid3-14.2.2.2 {
    execsql { ALTER TABLE t1 RENAME TO t4 }
    execsql { SELECT sql FROM sqlite_master WHERE type = 'table'}
    execsql { SELECT sql FROM sqlite_schema WHERE type = 'table'}
  } [list \
    {CREATE TABLE "t4"(a PRIMARY KEY, b REFERENCES "t4") WITHOUT rowid}      \
    {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES "t4", c REFERENCES t2)
            WITHOUT rowid}     \
    {CREATE TABLE t3(a REFERENCES "t4", b REFERENCES t2, c REFERENCES "t4")} \
  ]
  do_test without_rowid3-14.2.2.3 {
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
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







+




















-
+



-
+









-
+











-
+








-
+







  #
  drop_all_tables
  do_test without_rowid3-14.1tmp.1 {
    # Adding a column with a REFERENCES clause is not supported.
    execsql { 
      CREATE TEMP TABLE t1(a PRIMARY KEY) WITHOUT rowid;
      CREATE TEMP TABLE t2(a, b);
      INSERT INTO temp.t2(a,b) VALUES(1,2);
    }
    catchsql { ALTER TABLE t2 ADD COLUMN c REFERENCES t1 }
  } {0 {}}
  do_test without_rowid3-14.1tmp.2 {
    catchsql { ALTER TABLE t2 ADD COLUMN d DEFAULT NULL REFERENCES t1 }
  } {0 {}}
  do_test without_rowid3-14.1tmp.3 {
    catchsql { ALTER TABLE t2 ADD COLUMN e REFERENCES t1 DEFAULT NULL}
  } {0 {}}
  do_test without_rowid3-14.1tmp.4 {
    catchsql { ALTER TABLE t2 ADD COLUMN f REFERENCES t1 DEFAULT 'text'}
  } {1 {Cannot add a REFERENCES column with non-NULL default value}}
  do_test without_rowid3-14.1tmp.5 {
    catchsql { ALTER TABLE t2 ADD COLUMN g DEFAULT CURRENT_TIME REFERENCES t1 }
  } {1 {Cannot add a REFERENCES column with non-NULL default value}}
  do_test without_rowid3-14.1tmp.6 {
    execsql { 
      PRAGMA foreign_keys = off;
      ALTER TABLE t2 ADD COLUMN h DEFAULT 'text' REFERENCES t1;
      PRAGMA foreign_keys = on;
      SELECT sql FROM temp.sqlite_master WHERE name='t2';
      SELECT sql FROM temp.sqlite_schema WHERE name='t2';
    }
  } {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}}

  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1
  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db
  do_test without_rowid3-14.2tmp.1.1 {
    test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3
  } {{CREATE TABLE t1(a REFERENCES "t3")}}
  do_test without_rowid3-14.2tmp.1.2 {
    test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t4 t3
  } {{CREATE TABLE t1(a REFERENCES t2)}}
  do_test without_rowid3-14.2tmp.1.3 {
    test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3
  } {{CREATE TABLE t1(a REFERENCES "t3")}}
  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0
  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db
  
  # Test ALTER TABLE RENAME TABLE a bit.
  #
  do_test without_rowid3-14.2tmp.2.1 {
    drop_all_tables
    execsql {
      CREATE TEMP TABLE t1(a PRIMARY KEY, b REFERENCES t1) WITHOUT rowid;
      CREATE TEMP TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2)
            WITHOUT rowid;
      CREATE TEMP TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1);
    }
    execsql { SELECT sql FROM sqlite_temp_master WHERE type = 'table'}
    execsql { SELECT sql FROM sqlite_temp_schema WHERE type = 'table'}
  } [list \
    {CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1) WITHOUT rowid}       \
    {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2)
            WITHOUT rowid}    \
    {CREATE TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1)}  \
  ]
  do_test without_rowid3-14.2tmp.2.2 {
    execsql { ALTER TABLE t1 RENAME TO t4 }
    execsql { SELECT sql FROM temp.sqlite_master WHERE type = 'table'}
    execsql { SELECT sql FROM temp.sqlite_schema WHERE type = 'table'}
  } [list \
    {CREATE TABLE "t4"(a PRIMARY KEY, b REFERENCES "t4") WITHOUT rowid}      \
    {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES "t4", c REFERENCES t2)
            WITHOUT rowid}     \
    {CREATE TABLE t3(a REFERENCES "t4", b REFERENCES t2, c REFERENCES "t4")} \
  ]
  do_test without_rowid3-14.2tmp.2.3 {
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
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







+




















-
+



-
+









-
+











-
+








-
+







  drop_all_tables
  do_test without_rowid3-14.1aux.1 {
    # Adding a column with a REFERENCES clause is not supported.
    execsql { 
      ATTACH ':memory:' AS aux;
      CREATE TABLE aux.t1(a PRIMARY KEY) WITHOUT rowid;
      CREATE TABLE aux.t2(a, b);
      INSERT INTO aux.t2(a,b) VALUES(1,2);
    }
    catchsql { ALTER TABLE t2 ADD COLUMN c REFERENCES t1 }
  } {0 {}}
  do_test without_rowid3-14.1aux.2 {
    catchsql { ALTER TABLE t2 ADD COLUMN d DEFAULT NULL REFERENCES t1 }
  } {0 {}}
  do_test without_rowid3-14.1aux.3 {
    catchsql { ALTER TABLE t2 ADD COLUMN e REFERENCES t1 DEFAULT NULL}
  } {0 {}}
  do_test without_rowid3-14.1aux.4 {
    catchsql { ALTER TABLE t2 ADD COLUMN f REFERENCES t1 DEFAULT 'text'}
  } {1 {Cannot add a REFERENCES column with non-NULL default value}}
  do_test without_rowid3-14.1aux.5 {
    catchsql { ALTER TABLE t2 ADD COLUMN g DEFAULT CURRENT_TIME REFERENCES t1 }
  } {1 {Cannot add a REFERENCES column with non-NULL default value}}
  do_test without_rowid3-14.1aux.6 {
    execsql { 
      PRAGMA foreign_keys = off;
      ALTER TABLE t2 ADD COLUMN h DEFAULT 'text' REFERENCES t1;
      PRAGMA foreign_keys = on;
      SELECT sql FROM aux.sqlite_master WHERE name='t2';
      SELECT sql FROM aux.sqlite_schema WHERE name='t2';
    }
  } {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}}

  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1
  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db
  do_test without_rowid3-14.2aux.1.1 {
    test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3
  } {{CREATE TABLE t1(a REFERENCES "t3")}}
  do_test without_rowid3-14.2aux.1.2 {
    test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t4 t3
  } {{CREATE TABLE t1(a REFERENCES t2)}}
  do_test without_rowid3-14.2aux.1.3 {
    test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3
  } {{CREATE TABLE t1(a REFERENCES "t3")}}
  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0
  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db
  
  # Test ALTER TABLE RENAME TABLE a bit.
  #
  do_test without_rowid3-14.2aux.2.1 {
    drop_all_tables
    execsql {
      CREATE TABLE aux.t1(a PRIMARY KEY, b REFERENCES t1) WITHOUT rowid;
      CREATE TABLE aux.t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2)
            WITHOUT rowid;
      CREATE TABLE aux.t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1);
    }
    execsql { SELECT sql FROM aux.sqlite_master WHERE type = 'table'}
    execsql { SELECT sql FROM aux.sqlite_schema WHERE type = 'table'}
  } [list \
    {CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1) WITHOUT rowid}       \
    {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2)
            WITHOUT rowid}    \
    {CREATE TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1)}  \
  ]
  do_test without_rowid3-14.2aux.2.2 {
    execsql { ALTER TABLE t1 RENAME TO t4 }
    execsql { SELECT sql FROM aux.sqlite_master WHERE type = 'table'}
    execsql { SELECT sql FROM aux.sqlite_schema WHERE type = 'table'}
  } [list \
    {CREATE TABLE "t4"(a PRIMARY KEY, b REFERENCES "t4") WITHOUT rowid}      \
    {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES "t4", c REFERENCES t2)
            WITHOUT rowid}     \
    {CREATE TABLE t3(a REFERENCES "t4", b REFERENCES t2, c REFERENCES "t4")} \
  ]
  do_test without_rowid3-14.2aux.2.3 {

Changes to test/without_rowid5.test.

11
12
13
14
15
16
17




18
19
20
21
22
23
24
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28







+
+
+
+







#
# Requirements testing for WITHOUT ROWID tables.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable !incrblob {
  finish_test
  return
}

# EVIDENCE-OF: R-36924-43758 By default, every row in SQLite has a
# special column, usually called the "rowid", that uniquely identifies
# that row within the table.
#
# EVIDENCE-OF: R-32341-39358 However if the phrase "WITHOUT ROWID" is
# added to the end of a CREATE TABLE statement, then the special "rowid"
181
182
183
184
185
186
187

















































































188
189
190
191
192
193
194
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







} {1 {NOT NULL constraint failed: nnw.c}}
do_catchsql_test without_rowid5-5.8 {
  INSERT INTO nnw VALUES(4,5,6,7,NULL)
} {1 {NOT NULL constraint failed: nnw.e}}
do_execsql_test without_rowid5-5.9 {
  SELECT count(*) FROM nnw;
} {1}

# Ticket f2be158c57aaa8c6 (2021-08-18)
# NOT NULL ON CONFLICT clauses work on WITHOUT ROWID tables now.
# 
do_test without_rowid5-5.100 {
  db eval {
    DROP TABLE IF EXISTS t5;
    CREATE TABLE t5(
      a INT NOT NULL ON CONFLICT ROLLBACK,
      b TEXT,
      c TEXT,
      PRIMARY KEY(a,b)
    ) WITHOUT ROWID;
    BEGIN;
    INSERT INTO t5(a,b,c) VALUES(1,2,3);
  }
  catch {db eval {INSERT INTO t5(a,b,c) VALUES(NULL,6,7);}}
  db eval {
    SELECT * FROM t5;
  }
} {}
do_test without_rowid5-5.101 {
  db eval {
    DROP TABLE IF EXISTS t5;
    CREATE TABLE t5(
      a INT NOT NULL ON CONFLICT ABORT,
      b TEXT,
      c TEXT,
      PRIMARY KEY(a,b)
    ) WITHOUT ROWID;
    BEGIN;
    INSERT INTO t5(a,b,c) VALUES(1,2,3);
  }
  catch {db eval {INSERT INTO t5(a,b,c) VALUES(NULL,6,7);}}
  db eval {
    COMMIT;
    SELECT * FROM t5;
  }
} {1 2 3}
do_test without_rowid5-5.102 {
  db eval {
    DROP TABLE IF EXISTS t5;
    CREATE TABLE t5(
      a INT NOT NULL ON CONFLICT FAIL,
      b TEXT,
      c TEXT,
      PRIMARY KEY(a,b)
    ) WITHOUT ROWID;
  }
  catch {db eval {INSERT INTO t5(a,b,c) VALUES(1,2,3),(NULL,4,5),(6,7,8);}}
  db eval {
    SELECT * FROM t5;
  }
} {1 2 3}
do_test without_rowid5-5.103 {
  db eval {
    DROP TABLE IF EXISTS t5;
    CREATE TABLE t5(
      a INT NOT NULL ON CONFLICT IGNORE,
      b TEXT,
      c TEXT,
      PRIMARY KEY(a,b)
    ) WITHOUT ROWID;
    INSERT INTO t5(a,b,c) VALUES(1,2,3),(NULL,4,5),(6,7,8);
    SELECT * FROM t5;
  }
} {1 2 3 6 7 8}
do_test without_rowid5-5.104 {
  db eval {
    DROP TABLE IF EXISTS t5;
    CREATE TABLE t5(
      a INT NOT NULL ON CONFLICT REPLACE DEFAULT 3,
      b TEXT,
      c TEXT,
      PRIMARY KEY(a,b)
    ) WITHOUT ROWID;
    INSERT INTO t5(a,b,c) VALUES(1,2,3),(NULL,4,5),(6,7,8);
    SELECT * FROM t5;
  }
} {1 2 3 3 4 5 6 7 8}


# EVIDENCE-OF: R-12643-30541 The incremental blob I/O mechanism does not
# work for WITHOUT ROWID tables.
#
# EVIDENCE-OF: R-40134-30296 Table zTable is a WITHOUT ROWID table
#
do_execsql_test without_rowid5-6.1 {

Changes to test/without_rowid6.test.

11
12
13
14
15
16
17




18
19
20
21
22
23
24
25
26



27
28
29
30
31
32
33
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







+
+
+
+









+
+
+







#
# Verify that WITHOUT ROWID tables work correctly when the PRIMARY KEY
# has redundant columns.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

proc do_execsql_test_if_vtab {tn sql {res {}}} {
  ifcapable vtab { uplevel [list do_execsql_test $tn $sql $res] }
}

do_execsql_test without_rowid6-100 {
  CREATE TABLE t1(a,b,c,d,e, PRIMARY KEY(a,b,c,a,b,c,d,a,b,c)) WITHOUT ROWID;
  CREATE INDEX t1a ON t1(b, b);
  WITH RECURSIVE
    c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<1000)
  INSERT INTO t1(a,b,c,d,e) SELECT i, i+1000, printf('x%dy',i), 0, 0 FROM c;
  ANALYZE;
} {}
do_execsql_test_if_vtab without_rowid6-101 {
  SELECT name, key FROM pragma_index_xinfo('t1');
} {a 1 b 1 c 1 d 1 e 0}
do_execsql_test without_rowid6-110 {
  SELECT c FROM t1 WHERE a=123;
} {x123y}
do_execsql_test without_rowid6-120 {
  SELECT c FROM t1 WHERE b=1123;
} {x123y}
do_execsql_test without_rowid6-130 {
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
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







+
+
+



-
+


















-
+

















-
+













+
+
+



-
+










    b UNIQUE,
    c UNIQUE,
    PRIMARY KEY(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_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

Added test/without_rowid7.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2019 July 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 without_rowid7

proc do_execsql_test_if_vtab {tn sql {res {}}} {
  ifcapable vtab { uplevel [list do_execsql_test $tn $sql $res] }
}

do_execsql_test 1.0 {
  CREATE TABLE t1(a, b COLLATE nocase, PRIMARY KEY(a, a, b)) WITHOUT ROWID;
}

do_catchsql_test 1.1 {
  INSERT INTO t1 VALUES(1, 'one'), (1, 'ONE');
} {1 {UNIQUE constraint failed: t1.a, t1.b}}


do_execsql_test 2.0 {
  CREATE TABLE t2(a, b, PRIMARY KEY(a COLLATE nocase, a)) WITHOUT ROWID;
}

do_execsql_test 2.1 {
  INSERT INTO t2 VALUES(1, 'one');
  SELECT b FROM t2;
} {one}

do_execsql_test 2.2a {
  PRAGMA index_info(t2);
} {0 0 a 1 0 a}
do_execsql_test_if_vtab 2.2b {
  SELECT *, '|' FROM pragma_index_info('t2');
} {0 0 a | 1 0 a |}
do_execsql_test 2.3a {
  PRAGMA index_xinfo(t2);
} {0 0 a 0 nocase 1 1 0 a 0 BINARY 1 2 1 b 0 BINARY 0}
do_execsql_test_if_vtab 2.3b {
  SELECT *, '|' FROM pragma_index_xinfo('t2');
} {0 0 a 0 nocase 1 | 1 0 a 0 BINARY 1 | 2 1 b 0 BINARY 0 |}

do_execsql_test 2.4 {
  CREATE TABLE t3(a, b, PRIMARY KEY(a COLLATE nocase, a));
  PRAGMA index_info(t3);
} {}



finish_test

Changes to test/zeroblob.test.

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
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







-
+
-
-
-



















+
+
+
+
-
-
+
+
-
-
-
-
+
+
+
+
+







#
# $Id: zeroblob.test,v 1.14 2009/07/14 02:33:02 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix zeroblob

ifcapable !incrblob {
# ifcapable !incrblob { finish_test return }
  finish_test
  return
}

test_set_config_pagecache 0 0

# When zeroblob() is used for the last field of a column, then the
# content of the zeroblob is never instantiated on the VDBE stack.
# But it does get inserted into the database correctly.
#
db eval {PRAGMA cache_size=10}
sqlite3_memory_highwater 1
unset -nocomplain memused
set memused [sqlite3_memory_used]
do_test zeroblob-1.1 {
  execsql {
    CREATE TABLE t1(a,b,c,d);
  }
  set ::sqlite3_max_blobsize 0
  execsql {
    INSERT INTO t1 VALUES(2,3,4,zeroblob(1000000));
  }
} {}

ifcapable incrblob {
  do_test zeroblob-1.1.1 {
  set ::sqlite3_max_blobsize
} {10}
    set ::sqlite3_max_blobsize
  } {10}

do_test zeroblob-1.1.1 {
  expr {[sqlite3_memory_highwater]<$::memused+35000}
} {1}
  do_test zeroblob-1.1.2 {
    expr {[sqlite3_memory_highwater]<$::memused+35000}
  } {1}
}

do_test zeroblob-1.2 {
  execsql {
    SELECT length(d) FROM t1
  }
} {1000000}

# If a non-NULL column follows the zeroblob, then the content of
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
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







+
+
+
-
-
+
+
+














+
+
+
-
-
+
+
+







# of the blob content occurs on the stack.
#
do_test zeroblob-1.5 {
  set ::sqlite3_max_blobsize 0
  execsql {
    INSERT INTO t1 VALUES(4,5,zeroblob(10000),zeroblob(10000));
  }
} {}
ifcapable incrblob {
  do_test zeroblob-1.5.1 {
  set ::sqlite3_max_blobsize
} {11}
    set ::sqlite3_max_blobsize
  } {11}
}
do_test zeroblob-1.6 {
  execsql {
    SELECT length(c), length(d) FROM t1
  }
} {1 1000000 10000 1 10000 10000}

# NULLs can follow the zeroblob() or be intermixed with zeroblobs and
# no instantiation of the zeroblobs occurs on the stack.
#
do_test zeroblob-1.7 {
  set ::sqlite3_max_blobsize 0
  execsql {
    INSERT INTO t1 VALUES(5,zeroblob(10000),NULL,zeroblob(10000));
  }
} {}
ifcapable incrblob {
  do_test zeroblob-1.7.1 {
  set ::sqlite3_max_blobsize
} {10}
    set ::sqlite3_max_blobsize
  } {10}
}
do_test zeroblob-1.8 {
  execsql {
    SELECT length(b), length(d) FROM t1 WHERE a=5
  }
} {10000 10000}

# Comparisons against zeroblobs work.
210
211
212
213
214
215
216

217
218
219
220
221
222







223
224
225
226
227
228
229
220
221
222
223
224
225
226
227






228
229
230
231
232
233
234
235
236
237
238
239
240
241







+
-
-
-
-
-
-
+
+
+
+
+
+
+







} {SQLITE_ROW}
do_test zeroblob-7.2 {
  sqlite3_column_int $::STMT 0
} {450000}
do_test zeroblob-7.3 {
  sqlite3_finalize $::STMT
} {SQLITE_OK}
ifcapable incrblob {
do_test zeroblob-7.4 {
  set ::sqlite3_max_blobsize
} {0}
do_test zeroblob-7.5 {
  expr {[sqlite3_memory_highwater]<$::memused+10000}
} {1}
  do_test zeroblob-7.4 {
    set ::sqlite3_max_blobsize
  } {0}
  do_test zeroblob-7.5 {
    expr {[sqlite3_memory_highwater]<$::memused+10000}
  } {1}
}

# Test that MakeRecord can handle a value with some real content
# and a zero-blob tail.
#
do_test zeroblob-8.1 {
  llength [execsql {
    SELECT 'hello' AS a, zeroblob(10) as b from t1 ORDER BY a, b;
311
312
313
314
315
316
317











318
319
320
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343







+
+
+
+
+
+
+
+
+
+
+



  sqlite3_step $stmt
  set ret [sqlite3_column_int $stmt 0]
  sqlite3_reset $stmt
  set ret
} {1000}

sqlite3_finalize $stmt

# 2019-01-25 https://sqlite.org/src/tktview/bb4bdb9f7f654b0bb9f34cfbac
# Zeroblob truncated by an index on expression
#
do_execsql_test 13.100 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a,b,c);
  CREATE INDEX t1bbc ON t1(b, b+c);
  INSERT INTO t1(a,b,c) VALUES(1,zeroblob(8),3);
  SELECT a, quote(b), length(b), c FROM t1;
} {1 X'0000000000000000' 8 3}

test_restore_config_pagecache
finish_test

Added test/zeroblobfault.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2021 November 8
#
# 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

set testprefix zeroblobfault
set quoted_res [db one { SELECT quote(zeroblob(2000)) }]

do_faultsim_test 1 -prep {
  sqlite3 db test.db
} -body {
  execsql { SELECT quote(zeroblob(2000)) }
} -test {
  faultsim_test_result [list 0 $::quoted_res]
}

finish_test

Changes to test/zipfile.test.

790
791
792
793
794
795
796




































































797
798
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


    SELECT name FROM d JOIN x JOIN fsdir(d) ORDER BY 1;
  } {subdir subdir/x1.txt subdir/x2.txt}

  do_execsql_test 12.5 {
    SELECT name FROM d JOIN x JOIN fsdir('.', d) ORDER BY 1;
  } {. ./x1.txt ./x2.txt}
}

# 2019-12-18 Yongheng and Rui fuzzer
#
do_execsql_test 13.10 {
  DROP TABLE IF EXISTS t0;
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t0(a,b,c,d,e,f,g);
  REPLACE INTO t0(c,b,f) VALUES(10,10,10);
  CREATE VIRTUAL TABLE t1 USING zipfile('h.zip');
  REPLACE INTO t1 SELECT * FROM t0;
  SELECT quote(name),quote(mode),quote(mtime),quote(sz),quote(rawdata),
         quote(data),quote(method) FROM t1;
} {'' 10 10 2 X'3130' X'3130' 0}

# 2019-12-23 Yongheng and Rui fuzzer
# Run using valgrind to see the problem.
#
do_execsql_test 14.10 {
  DROP TABLE t1;
  CREATE TABLE t1(x char);
  INSERT INTO t1(x) VALUES('1');
  INSERT INTO t1(x) SELECT zipfile(x, 'xyz') FROM t1;
  INSERT INTO t1(x) SELECT zipfile(x, 'uvw') FROM t1;
  SELECT count(*) FROM t1;
  PRAGMA integrity_check;
} {3 ok}

# 2019-12-26 More problems in zipfile from the Yongheng and Rui fuzzer
#
do_execsql_test 15.10 {
  DROP TABLE IF EXISTS t1;
  CREATE VIRTUAL TABLE t1 USING zipfile(null);
  REPLACE INTO t1 VALUES(null,null,0,null,null,null,null);
} {}
do_execsql_test 15.20 {
  DROP TABLE IF EXISTS t2;
  CREATE VIRTUAL TABLE t2 USING zipfile(null);
  REPLACE INTO t2 values(null,null,null,null,null,10,null);
} {}

# 2020-01-02 Yongheng fuzzer discovery
#
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}

# 2023-01-04
# https://sqlite.org/forum/forumpost/d1c96a9032e564f8
# Call to fopen() with a NULL filename.
#
do_catchsql_test 18.1 {
  SELECT * FROM zipfile(NULL);
} {1 {cannot open file: }}


finish_test

Changes to tool/GetFile.cs.

163
164
165
166
167
168
169
170


171
172
173
174
175
176
177
163
164
165
166
167
168
169

170
171
172
173
174
175
176
177
178







-
+
+







        {
            if (message != null)
                Console.WriteLine(message);

            string fileName = Path.GetFileName(
                Process.GetCurrentProcess().MainModule.FileName);

            Console.WriteLine(String.Format("usage: {0} <uri>", fileName));
            Console.WriteLine(String.Format(
                "usage: {0} <uri> [fileName]", fileName));
        }

        ///////////////////////////////////////////////////////////////////////

        /// <summary>
        /// This method attempts to determine the file name portion of the
        /// specified URI.
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
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







-
+


















+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+

-
-
-
-
+
+
+
+
+

















+
+
+
+
+
+
+
+
+







            //
            if (args == null)
            {
                Error(null, true);
                return (int)ExitCode.MissingArgs;
            }

            if (args.Length != 1)
            if ((args.Length < 1) || (args.Length > 2))
            {
                Error(null, true);
                return (int)ExitCode.WrongNumArgs;
            }

            //
            // NOTE: Attempt to convert the first (and only) command line
            //       argument to an absolute URI.
            //
            Uri uri;

            if (!Uri.TryCreate(args[0], UriKind.Absolute, out uri))
            {
                Error("Could not create absolute URI from argument.", false);
                return (int)ExitCode.BadUri;
            }

            //
            // NOTE: If a file name was specified on the command line, try to
            //       use it (without its directory name); otherwise, fallback
            //       to using the file name portion of the URI.
            //
            string fileName = (args.Length == 2) ?
                Path.GetFileName(args[1]) : null;

            if (String.IsNullOrEmpty(fileName))
            {
                //
            // NOTE: Attempt to extract the file name portion of the URI we
            //       just created.
            //
            string fileName = GetFileName(uri);
                // NOTE: Attempt to extract the file name portion of the URI
                //       we just created.
                //
                fileName = GetFileName(uri);

            if (fileName == null)
            {
                Error("Could not extract the file name from the URI.", false);
                return (int)ExitCode.BadFileName;
                if (fileName == null)
                {
                    Error("Could not extract file name from URI.", false);
                    return (int)ExitCode.BadFileName;
                }
            }

            //
            // NOTE: Grab the temporary path setup for this process.  If it is
            //       unavailable, we will not continue.
            //
            string directory = Path.GetTempPath();

            if (String.IsNullOrEmpty(directory) ||
                !Directory.Exists(directory))
            {
                Error("Temporary directory is invalid or unavailable.", false);
                return (int)ExitCode.BadTempPath;
            }

            try
            {
                //
                // HACK: For use of the TLS 1.2 security protocol because some
                //       web servers fail without it.  In order to support the
                //       .NET Framework 2.0+ at compilation time, must use its
                //       integer constant here.
                //
                ServicePointManager.SecurityProtocol =
                    (SecurityProtocolType)0xC00;

                using (WebClient webClient = new WebClient())
                {
                    //
                    // NOTE: Create the event used to signal completion of the
                    //       file download.
                    //
                    doneEvent = new ManualResetEvent(false);

Changes to tool/GetTclKit.bat.

9
10
11
12
13
14
15


16
17
18
19
20
21
22
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24







+
+







SETLOCAL

REM SET __ECHO=ECHO
REM SET __ECHO2=ECHO
REM SET __ECHO3=ECHO
IF NOT DEFINED _AECHO (SET _AECHO=REM)
IF NOT DEFINED _CECHO (SET _CECHO=REM)
IF NOT DEFINED _CECHO2 (SET _CECHO2=REM)
IF NOT DEFINED _CECHO3 (SET _CECHO3=REM)
IF NOT DEFINED _VECHO (SET _VECHO=REM)

SET OVERWRITE=^>
IF DEFINED __ECHO SET OVERWRITE=^^^>

SET APPEND=^>^>
IF DEFINED __ECHO SET APPEND=^^^>^^^>
35
36
37
38
39
40
41
42
43
44
45





46
47
48
49
50
51
52
37
38
39
40
41
42
43




44
45
46
47
48
49
50
51
52
53
54
55







-
-
-
-
+
+
+
+
+








SET DUMMY2=%2

IF DEFINED DUMMY2 (
  GOTO usage
)

SET ROOT=%~dp0\..
SET ROOT=%ROOT:\\=\%

%_VECHO% Root = '%ROOT%'
IF NOT DEFINED ENVDIR (
  SET ENVDIR=%CD%
)

%_VECHO% EnvDir = '%ENVDIR%'

SET TOOLS=%~dp0
SET TOOLS=%TOOLS:~0,-1%

%_VECHO% Tools = '%TOOLS%'

IF NOT DEFINED windir (
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
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







-
+




+
+
+
+
+
+
+
+
+
+
+
+


+
+
+
+


+
+
+
+






+







  ECHO The TEMP environment variable must be set first.
  GOTO errors
)

%_VECHO% Temp = '%TEMP%'

IF NOT DEFINED TCLKIT_URI (
  SET TCLKIT_URI=https://tclsh.com/
  SET TCLKIT_URI=https://urn.to/r/tclsh/
)

%_VECHO% TclKitUri = '%TCLKIT_URI%'

IF NOT DEFINED TCLKIT_PATCHLEVEL (
  SET TCLKIT_PATCHLEVEL=8.6.6
)

%_VECHO% TclKitPatchLevel = '%TCLKIT_PATCHLEVEL%'

IF NOT DEFINED TCLKIT_EXE_PATCHLEVEL (
  SET TCLKIT_EXE_PATCHLEVEL=8.6.4
)

%_VECHO% TclKitExePatchLevel = '%TCLKIT_EXE_PATCHLEVEL%'

IF /I "%PROCESSOR%" == "x86" (
  CALL :fn_TclKitX86Variables

  IF ERRORLEVEL 1 (
    GOTO errors
  )
) ELSE IF /I "%PROCESSOR%" == "x64" (
  CALL :fn_TclKitX64Variables

  IF ERRORLEVEL 1 (
    GOTO errors
  )
) ELSE (
  GOTO usage
)

%_VECHO% TclKitVersion = '%TCLKIT_VERSION%'
%_VECHO% TclKitPatchLevel = '%TCLKIT_PATCHLEVEL%'
%_VECHO% TclKitExePatchLevel = '%TCLKIT_EXE_PATCHLEVEL%'
%_VECHO% TclKitNoEnv = '%TCLKIT_NOENV%'
%_VECHO% TclKitNoSdk = '%TCLKIT_NOSDK%'
%_VECHO% TclKitExe = '%TCLKIT_EXE%'
%_VECHO% TclKitLib = '%TCLKIT_LIB%'
%_VECHO% TclKitLibStub = '%TCLKIT_LIB_STUB%'
%_VECHO% TclKitSdk = '%TCLKIT_SDK%'
%_VECHO% TclKitSdkZip = '%TCLKIT_SDK_ZIP%'
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
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







-
+



-
-
-
-
-
+
+
+
+
+




-
+















-
+
+
+



+
-
-
+
+
+
+


















-
+
+
+



+
-
-
+
+
+
+







  GOTO errors
)

:skip_sdkUnZip

IF DEFINED TCLKIT_NOENV GOTO skip_sdkEnvironment

%__ECHO% ECHO SET TCLSH_CMD=%TEMP%\%TCLKIT_EXE%%OVERWRITE%"%ROOT%\SetTclKitEnv.bat"
%__ECHO% ECHO SET TCLSH_CMD=%TEMP%\%TCLKIT_EXE%%OVERWRITE%"%ENVDIR%\SetTclKitEnv.bat"

IF DEFINED TCLKIT_NOSDK GOTO skip_sdkVariables

%__ECHO% ECHO SET TCLINCDIR=%TEMP%\%TCLKIT_SDK%\include%APPEND%"%ROOT%\SetTclKitEnv.bat"
%__ECHO% ECHO SET TCLLIBDIR=%TEMP%\%TCLKIT_SDK%\lib%APPEND%"%ROOT%\SetTclKitEnv.bat"
%__ECHO% ECHO SET LIBTCLPATH=%TEMP%\%TCLKIT_SDK%\lib%APPEND%"%ROOT%\SetTclKitEnv.bat"
%__ECHO% ECHO SET LIBTCL=%TCLKIT_LIB%%APPEND%"%ROOT%\SetTclKitEnv.bat"
%__ECHO% ECHO SET LIBTCLSTUB=%TCLKIT_LIB_STUB%%APPEND%"%ROOT%\SetTclKitEnv.bat"
%__ECHO% ECHO SET TCLINCDIR=%TEMP%\%TCLKIT_SDK%\include%APPEND%"%ENVDIR%\SetTclKitEnv.bat"
%__ECHO% ECHO SET TCLLIBDIR=%TEMP%\%TCLKIT_SDK%\lib%APPEND%"%ENVDIR%\SetTclKitEnv.bat"
%__ECHO% ECHO SET LIBTCLPATH=%TEMP%\%TCLKIT_SDK%\lib%APPEND%"%ENVDIR%\SetTclKitEnv.bat"
%__ECHO% ECHO SET LIBTCL=%TCLKIT_LIB%%APPEND%"%ENVDIR%\SetTclKitEnv.bat"
%__ECHO% ECHO SET LIBTCLSTUB=%TCLKIT_LIB_STUB%%APPEND%"%ENVDIR%\SetTclKitEnv.bat"

:skip_sdkVariables

ECHO.
ECHO Wrote "%ROOT%\SetTclKitEnv.bat".
ECHO Wrote "%ENVDIR%\SetTclKitEnv.bat".
ECHO Please run it to set the necessary Tcl environment variables.
ECHO.

:skip_sdkEnvironment

GOTO no_errors

:fn_TclKitX86Variables
  REM
  REM NOTE: By default, use latest available version of the TclKit SDK
  REM       for x86.  However, the "default" TclKit executable for x86
  REM       is still used here because it is the only one "well-known"
  REM       to be available for download.
  REM
  IF NOT DEFINED TCLKIT_PATCHLEVEL (
    SET TCLKIT_PATCHLEVEL=8.6.6
    ECHO The TCLKIT_PATCHLEVEL environment variable must be set first.
    CALL :fn_SetErrorLevel
    GOTO :EOF
  )
  SET TCLKIT_VERSION=%TCLKIT_PATCHLEVEL:.=%
  SET TCLKIT_VERSION=%TCLKIT_VERSION:~0,2%
  IF DEFINED TCLKIT_EXE_PATCHLEVEL (
  REM SET TCLKIT_EXE=tclkit-%TCLKIT_PATCHLEVEL%.exe
  SET TCLKIT_EXE=tclkit-8.6.4.exe
    SET TCLKIT_EXE=tclkit-%TCLKIT_EXE_PATCHLEVEL%.exe
  ) ELSE (
    SET TCLKIT_EXE=tclkit-%TCLKIT_PATCHLEVEL%.exe
  )
  SET TCLKIT_LIB=libtclkit%TCLKIT_PATCHLEVEL:.=%.lib
  SET TCLKIT_LIB_STUB=libtclstub%TCLKIT_VERSION:.=%.a
  SET TCLKIT_SDK=libtclkit-sdk-x86-%TCLKIT_PATCHLEVEL%
  SET TCLKIT_SDK_ZIP=%TCLKIT_SDK%.zip
  SET TCLKIT_FILES=%TCLKIT_EXE%
  IF NOT DEFINED TCLKIT_NOENV IF NOT DEFINED TCLKIT_NOSDK (
    SET TCLKIT_FILES=%TCLKIT_FILES% unzip.exe %TCLKIT_SDK_ZIP%
  )
  GOTO :EOF

:fn_TclKitX64Variables
  REM
  REM NOTE: By default, use latest available version of the TclKit SDK
  REM       for x64.  However, the "default" TclKit executable for x86
  REM       is still used here because it is the only one "well-known"
  REM       to be available for download.
  REM
  IF NOT DEFINED TCLKIT_PATCHLEVEL (
    SET TCLKIT_PATCHLEVEL=8.6.6
    ECHO The TCLKIT_PATCHLEVEL environment variable must be set first.
    CALL :fn_SetErrorLevel
    GOTO :EOF
  )
  SET TCLKIT_VERSION=%TCLKIT_PATCHLEVEL:.=%
  SET TCLKIT_VERSION=%TCLKIT_VERSION:~0,2%
  IF DEFINED TCLKIT_EXE_PATCHLEVEL (
  REM SET TCLKIT_EXE=tclkit-%TCLKIT_PATCHLEVEL%.exe
  SET TCLKIT_EXE=tclkit-8.6.4.exe
    SET TCLKIT_EXE=tclkit-%TCLKIT_EXE_PATCHLEVEL%.exe
  ) ELSE (
    SET TCLKIT_EXE=tclkit-%TCLKIT_PATCHLEVEL%.exe
  )
  SET TCLKIT_LIB=libtclkit%TCLKIT_PATCHLEVEL:.=%.lib
  SET TCLKIT_LIB_STUB=libtclstub%TCLKIT_VERSION:.=%.a
  SET TCLKIT_SDK=libtclkit-sdk-x64-%TCLKIT_PATCHLEVEL%
  SET TCLKIT_SDK_ZIP=%TCLKIT_SDK%.zip
  SET TCLKIT_FILES=%TCLKIT_EXE%
  IF NOT DEFINED TCLKIT_NOENV IF NOT DEFINED TCLKIT_NOSDK (
    SET TCLKIT_FILES=%TCLKIT_FILES% unzip.exe %TCLKIT_SDK_ZIP%

Deleted tool/addopcodes.tcl.

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

































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#!/usr/bin/tclsh
#
# This script appends additional token codes to the end of the
# parse.h file that lemon generates.  These extra token codes are
# not used by the parser.  But they are used by the tokenizer and/or
# the code generator.
#
#
set in [open [lindex $argv 0] rb]
set max 0
while {![eof $in]} {
  set line [gets $in]
  if {[regexp {^#define TK_} $line]} {
    puts $line
    set x [lindex $line 2]
    if {$x>$max} {set max $x}
  }
}
close $in

# The following are the extra token codes to be added.  SPACE and 
# ILLEGAL *must* be the last two token codes and they must be in that order.
#
set extras {
  TRUEFALSE
  ISNOT
  FUNCTION
  COLUMN
  AGG_FUNCTION
  AGG_COLUMN
  UMINUS
  UPLUS
  TRUTH
  REGISTER
  CONCURRENT
  VECTOR
  SELECT_COLUMN
  IF_NULL_ROW
  ASTERISK
  SPAN
  END_OF_FILE
  UNCLOSED_STRING
  SPACE
  ILLEGAL
}
if {[lrange $extras end-1 end]!="SPACE ILLEGAL"} {
  error "SPACE and ILLEGAL must be the last two token codes and they\
         must be in that order"
}
foreach x $extras {
  incr max
  puts [format "#define TK_%-29s %4d" $x $max]
}

# Some additional #defines related to token codes.
#
puts "\n/* The token codes above must all fit in 8 bits */"
puts [format "#define %-20s %-6s" TKFLG_MASK 0xff]
puts "\n/* Flags that can be added to a token code when it is not"
puts "** being stored in a u8: */"
foreach {fg val comment} {
  TKFLG_DONTFOLD  0x100  {/* Omit constant folding optimizations */}
} {
  puts [format "#define %-20s %-6s %s" $fg $val $comment]
}

Changes to tool/build-all-msvc.bat.

125
126
127
128
129
130
131


132
133
134
135
136
137
138
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140







+
+







SETLOCAL

REM SET __ECHO=ECHO
REM SET __ECHO2=ECHO
REM SET __ECHO3=ECHO
IF NOT DEFINED _AECHO (SET _AECHO=REM)
IF NOT DEFINED _CECHO (SET _CECHO=REM)
IF NOT DEFINED _CECHO2 (SET _CECHO2=REM)
IF NOT DEFINED _CECHO3 (SET _CECHO3=REM)
IF NOT DEFINED _VECHO (SET _VECHO=REM)

SET REDIRECT=^>
IF DEFINED __ECHO SET REDIRECT=^^^>

%_AECHO% Running %0 %*

173
174
175
176
177
178
179

180
181
182
183
184
185
186
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189







+







REM
CALL :fn_ResetErrorLevel

REM
REM NOTE: Change the current directory to the root of the source tree, saving
REM       the current directory on the directory stack.
REM
%_CECHO2% PUSHD "%ROOT%"
%__ECHO2% PUSHD "%ROOT%"

IF ERRORLEVEL 1 (
  ECHO Could not change directory to "%ROOT%".
  GOTO errors
)

520
521
522
523
524
525
526

527
528
529
530
531
532
533
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537







+







      REM          symbols file for this platform to the platform-specific
      REM          directory beneath the binary directory.
      REM
      "%ComSpec%" /C (
        REM
        REM NOTE: Attempt to setup the MSVC environment for this platform.
        REM
        %_CECHO3% CALL "%VCVARSALL%" %%P
        %__ECHO3% CALL "%VCVARSALL%" %%P

        IF ERRORLEVEL 1 (
          ECHO Failed to call "%VCVARSALL%" for platform %%P.
          GOTO errors
        )

745
746
747
748
749
750
751

752
753
754
755
756
757
758
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763







+







    GOTO errors
  )
)

REM
REM NOTE: Restore the saved current directory from the directory stack.
REM
%_CECHO2% POPD
%__ECHO2% POPD

IF ERRORLEVEL 1 (
  ECHO Could not restore directory.
  GOTO errors
)

Changes to tool/cg_anno.tcl.

1



2
3
4
5
6
7
8

1
2
3
4
5
6
7
8
9
10
-
+
+
+







#!/usr/bin/tclsh
#!/bin/sh
# \
exec tclsh "$0" ${1+"$@"}
#
# A wrapper around cg_annotate that sets appropriate command-line options
# and rearranges the output so that annotated files occur in a consistent
# sorted order.  Used by the speed-check.tcl script.
#

set in [open "|cg_annotate --show=Ir --auto=yes --context=40 $argv" r]

Changes to tool/dbhash.c.

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
58
59
60
61
62
63
64













65
66
67


68
69
70
71
72
73
74







-
-
-
-
-
-
-
-
-
-
-
-
-



-
-







*/
/*
 * blk0() and blk() perform the initial expand.
 * I got the idea of expanding during the round function from SSLeay
 *
 * blk0le() for little-endian and blk0be() for big-endian.
 */
#if __GNUC__ && (defined(__i386__) || defined(__x86_64__))
/*
 * GCC by itself only generates left rotates.  Use right rotates if
 * possible to be kinder to dinky implementations with iterative rotate
 * instructions.
 */
#define SHA_ROT(op, x, k) \
        ({ unsigned int y; asm(op " %1,%0" : "=r" (y) : "I" (k), "0" (x)); y; })
#define rol(x,k) SHA_ROT("roll", x, k)
#define ror(x,k) SHA_ROT("rorl", x, k)

#else
/* Generic C equivalent */
#define SHA_ROT(x,l,r) ((x) << (l) | (x) >> (r))
#define rol(x,k) SHA_ROT(x,k,32-(k))
#define ror(x,k) SHA_ROT(x,32-(k),k)
#endif


#define blk0le(i) (block[i] = (ror(block[i],8)&0xFF00FF00) \
    |(rol(block[i],8)&0x00FF00FF))
#define blk0be(i) block[i]
#define blk(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15] \
    ^block[(i+2)&15]^block[i&15],1))

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
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







-
+













-
+







    ;
    zDb = argv[i];
    rc = sqlite3_open_v2(zDb, &g.db, openFlags, 0);
    if( rc ){
      fprintf(stderr, "cannot open database file '%s'\n", zDb);
      continue;
    }
    rc = sqlite3_exec(g.db, "SELECT * FROM sqlite_master", 0, 0, &zErrMsg);
    rc = sqlite3_exec(g.db, "SELECT * FROM sqlite_schema", 0, 0, &zErrMsg);
    if( rc || zErrMsg ){
      sqlite3_close(g.db);
      g.db = 0;
      fprintf(stderr, "'%s' is not a valid SQLite database\n", zDb);
      continue;
    }

    /* Start the hash */
    hash_init();
  
    /* Hash table content */
    if( !omitContent ){
      pStmt = db_prepare(
        "SELECT name FROM sqlite_master\n"
        "SELECT name FROM sqlite_schema\n"
        " WHERE type='table' AND sql NOT LIKE 'CREATE VIRTUAL%%'\n"
        "   AND name NOT LIKE 'sqlite_%%'\n"
        "   AND name LIKE '%q'\n"
        " ORDER BY name COLLATE nocase;\n",
        zLike
      );
      while( SQLITE_ROW==sqlite3_step(pStmt) ){
487
488
489
490
491
492
493
494

495
496
497
498
499
500
501
502
503
504
505
506
472
473
474
475
476
477
478

479
480
481
482
483
484
485
486
487
488
489
490
491







-
+












      }
      sqlite3_finalize(pStmt);
    }
  
    /* Hash the database schema */
    if( !omitSchema ){
      hash_one_query(
         "SELECT type, name, tbl_name, sql FROM sqlite_master\n"
         "SELECT type, name, tbl_name, sql FROM sqlite_schema\n"
         " WHERE tbl_name LIKE '%q'\n"
         " ORDER BY name COLLATE nocase;\n",
         zLike
      );
    }
  
    /* Finish and output the hash and close the database connection. */
    hash_finish(zDb);
    sqlite3_close(g.db);
  }
  return 0;
}

Changes to tool/dbtotxt.c.

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
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












-
+
+
+
+
+
+
+
+
+
+
+
+
















+










+
+


+






+
-
-
+
+
+
+
+
+
+













+
+
+
+
+
+
+
















-
+
+










-
-
+
+


+
+
+
+
+
-
-
+
+


+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










-
+

+
+
+

-
+
-
-
-
+
-
-
-
-
-
-










-
-
+
+



-

+
+
+
+


/*
** Copyright 2008 D. Richard Hipp and Hipp, Wyrick & Company, Inc.
** All Rights Reserved
**
******************************************************************************
**
** This file implements a stand-alone utility program that converts
** a binary file (usually an SQLite database) into a text format that
** is compact and friendly to human-readers.
**
** Usage:
**
**         dbtotxt [--pagesize N] FILENAME
**         dbtotxt [OPTIONS] FILENAME
**
** where OPTIONS are zero or more of:
**
**    --for-cli          prepending '.open --hexdb' to the output
**
**    --script           The input file is expected to start with a
**                       zero-terminated SQL string.  Output the
**                       ".open --hexdb" header, then the database
**                       then the SQL.
**
**    --pagesize N       set the database page size for later reading
**
** The translation of the database appears on standard output.  If the
** --pagesize command-line option is omitted, then the page size is taken
** from the database header.
**
** Compactness is achieved by suppressing lines of all zero bytes.  This
** works well at compressing test databases that are mostly empty.  But
** the output will probably be lengthy for a real database containing lots
** of real content.  For maximum compactness, it is suggested that test
** databases be constructed with "zeroblob()" rather than "randomblob()"
** used for filler content and with "PRAGMA secure_delete=ON" selected to
** zero-out deleted content.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
 
/* Return true if the line is all zeros */
static int allZero(unsigned char *aLine){
  int i;
  for(i=0; i<16 && aLine[i]==0; i++){}
  return i==16;
}

int main(int argc, char **argv){
  int pgsz = 0;               /* page size */
  int forCli = 0;             /* whether to prepend with .open */
  int bSQL = 0;               /* Expect and SQL prefix */
  long szFile;                /* Size of the input file in bytes */
  FILE *in;                   /* Input file */
  int nSQL;                   /* Number of bytes of script */
  int i, j;                   /* Loop counters */
  int nErr = 0;               /* Number of errors */
  const char *zInputFile = 0; /* Name of the input file */
  const char *zBaseName = 0;  /* Base name of the file */
  int lastPage = 0;           /* Last page number shown */
  int iPage;                  /* Current page number */
  unsigned char *aData = 0;   /* All data */
  unsigned char aLine[16];    /* A single line of the file */
  unsigned char aHdr[100];    /* File header */
  unsigned char *aLine;       /* A single line of the file */
  unsigned char *aHdr;        /* File header */
  unsigned char bShow[256];   /* Characters ok to display */
  memset(bShow, '.', sizeof(bShow));
  for(i=' '; i<='~'; i++){
    if( i!='{' && i!='}' && i!='"' && i!='\\' ) bShow[i] = (unsigned char)i;
  }
  for(i=1; i<argc; i++){
    if( argv[i][0]=='-' ){
      const char *z = argv[i];
      z++;
      if( z[0]=='-' ) z++;
      if( strcmp(z,"pagesize")==0 ){
        i++;
        pgsz = atoi(argv[i]);
        if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ){
          fprintf(stderr, "Page size must be a power of two between"
                          " 512 and 65536.\n");
          nErr++;
        }
        continue;
      }else if( strcmp(z,"for-cli")==0 ){
        forCli = 1;
        continue;
      }else if( strcmp(z,"script")==0 ){
        forCli = 1;
        bSQL = 1;
        continue;
      }
      fprintf(stderr, "Unknown option: %s\n", argv[i]);
      nErr++;
    }else if( zInputFile ){
      fprintf(stderr, "Already using a different input file: [%s]\n", argv[i]);
      nErr++;
    }else{
      zInputFile = argv[i];
    }
  }
  if( zInputFile==0 ){
    fprintf(stderr, "No input file specified.\n");
    nErr++;
  }
  if( nErr ){
    fprintf(stderr, "Usage: %s [--pagesize N] FILENAME\n", argv[0]);
    fprintf(stderr, 
       "Usage: %s [--pagesize N] [--script] [--for-cli] FILENAME\n", argv[0]);
    exit(1);
  }
  in = fopen(zInputFile, "rb");
  if( in==0 ){
    fprintf(stderr, "Cannot open input file [%s]\n", zInputFile);
    exit(1);
  }
  fseek(in, 0, SEEK_END);
  szFile = ftell(in);
  rewind(in);
  if( szFile<512 ){
    fprintf(stderr, "File too short. Minimum size is 512 bytes.\n");
  if( szFile<100 ){
    fprintf(stderr, "File too short. Minimum size is 100 bytes.\n");
    exit(1);
  }
  aData = malloc( szFile+16 );
  if( aData==0 ){
    fprintf(stderr, "Failed to allocate %ld bytes\n", szFile);
    exit(1);
  }
  if( fread(aHdr, 100, 1, in)!=1 ){
    fprintf(stderr, "Cannot read file header\n");
  if( fread(aData, szFile, 1, in)!=1 ){
    fprintf(stderr, "Cannot read file info memory\n");
    exit(1);
  }
  memset(aData+szFile, 0, 16);
  rewind(in);
  fclose(in);
  if( bSQL ){
    for(i=0; i<szFile && aData[i]!=0; i++){}
    if( i==szFile ){
      fprintf(stderr, "No zero terminator on SQL script\n");
      exit(1);
    }
    nSQL = i+1;
    if( szFile - nSQL<100 ){
      fprintf(stderr, "Less than 100 bytes in the database\n");
      exit(1);
    }
  }else{
    nSQL = 0;
  }
  aHdr = aData + nSQL;
  if( pgsz==0 ){
    pgsz = (aHdr[16]<<8) | aHdr[17];
    if( pgsz==1 ) pgsz = 65536;
    if( pgsz<512 || (pgsz&(pgsz-1))!=0 ){
      fprintf(stderr, "Invalid page size in header: %d\n", pgsz);
      exit(1);
    }
  }
  zBaseName = zInputFile;
  for(i=0; zInputFile[i]; i++){
    if( zInputFile[i]=='/' && zInputFile[i+1]!=0 ) zBaseName = zInputFile+1;
    if( zInputFile[i]=='/' && zInputFile[i+1]!=0 ) zBaseName = zInputFile+i+1;
  }
  if( forCli ){
    printf(".open --hexdb\n");
  }
  printf("| size %d pagesize %d filename %s\n",(int)szFile,pgsz,zBaseName);
  for(i=0; i<szFile; i+=16){
  for(i=nSQL; i<szFile; i+=16){
    int got = (int)fread(aLine, 1, 16, in);
    if( got!=16 ){
      static int once = 1;
    aLine = aData+i;
      if( once ){
        fprintf(stderr, "Could not read input file starting at byte %d\n",
                         i+got);
      }
      memset(aLine+got, 0, 16-got);
    }
    if( allZero(aLine) ) continue;
    iPage = i/pgsz + 1;
    if( lastPage!=iPage ){
      printf("| page %d offset %d\n", iPage, (iPage-1)*pgsz);
      lastPage = iPage;
    }
    printf("|  %5d:", i-(iPage-1)*pgsz);
    for(j=0; j<16; j++) printf(" %02x", aLine[j]);
    printf("   ");
    for(j=0; j<16; j++){
      char c = aLine[j];
      fputc(c>=0x20 && c<=0x7e ? c : '.', stdout);
      unsigned char c = (unsigned char)aLine[j];
      fputc( bShow[c], stdout);
    }
    fputc('\n', stdout);
  }
  fclose(in);
  printf("| end %s\n", zBaseName);
  if( nSQL>0 ){
    printf("%s\n", aData);
  }
  free( aData );
  return 0;
}

Added tool/enlargedb.c.





































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** Try to enlarge an SQLite database by appending many unused pages.
** The resulting database will fail PRAGMA integrity_check due to the
** appended unused pages, but it should work otherwise.
**
** Usage:
**
**        enlargedb  DATABASE   N
**
** Adds N blank pages onto the end of DATABASE.  N can be decimal
** or hex.  The total number of pages after adding must be no greater
** than 4294967297
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char **argv){
  char *zEnd;
  long long int toAppend;
  long long int currentSz;
  long long int newSz;
  FILE *f;
  size_t got;
  int pgsz;
  char zero = 0;
  unsigned char buf[100];

  if( argc!=3 ) goto usage_error;
  toAppend = strtoll(argv[2], &zEnd, 0);
  if( zEnd==argv[2] || zEnd[0] ) goto usage_error;
  if( toAppend<1 ){
    fprintf(stderr, "N must be at least 1\n");
    exit(1);
  }
  f = fopen(argv[1], "r+b");
  if( f==0 ){
    fprintf(stderr, "cannot open \"%s\" for reading and writing\n", argv[1]);
    exit(1);
  }
  got = fread(buf, 1, sizeof(buf), f);
  if( got!=sizeof(buf) ) goto not_valid_db;
  if( strcmp((char*)buf,"SQLite format 3")!=0 ) goto not_valid_db;
  pgsz = (buf[16]<<8) + buf[17];
  if( pgsz==1 ) pgsz = 65536;
  if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ) goto not_valid_db;
  currentSz = (buf[28]<<24) + (buf[29]<<16) + (buf[30]<<8) + buf[31];
  newSz = currentSz + toAppend;
  if( newSz > 0xffffffff ) newSz = 0xffffffff;
  buf[28] = (newSz>>24) & 0xff;
  buf[29] = (newSz>>16) & 0xff;
  buf[30] = (newSz>>8) & 0xff;
  buf[31] = newSz & 0xff;
  fseek(f, 28, SEEK_SET);
  fwrite(&buf[28],4,1,f);
  fseek(f, (long)(newSz*pgsz - 1), SEEK_SET);
  fwrite(&zero,1,1,f);
  fclose(f);
  return 0;  

not_valid_db:
  fprintf(stderr,"not a valid database: %s\n", argv[1]);
  exit(1);  

usage_error:
  fprintf(stderr,"Usage: %s DATABASE N\n", argv[0]);
  exit(1);
}

Added tool/extract-sqlite3h.tcl.






















1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
#!/usr/bin/tclsh
#
# Given an sqlite3.c source file identified by the command-line
# argument, extract the "sqlite3.h" header file that is embedded inside
# the sqlite3.c source file and write it to standard output.
#
if {[llength $argv]!=1} {
  puts stderr "Usage: $argv0 sqlite3.c >sqlite3.h"
  exit 1
}
set in [open [lindex $argv 0] rb]
while {![eof $in]} {
  set line [gets $in]
  if {[string match {* Begin file sqlite3.h *} $line]} break
}
while {![eof $in]} {
  set line [gets $in]
  if {[string match {* End of sqlite3.h *} $line]} break
  puts $line
}
close $in

Changes to tool/fast_vacuum.c.

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
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







-
+











-
+




-
+



-
+









-
+








-
+




-
+








-
+

-
+







  sqlite3_free(zSql);

  /* TODO:
  ** Set the page_size and auto_vacuum mode for zTempDb here, if desired.
  */

  /* The vacuum will occur inside of a transaction.  Set writable_schema
  ** to ON so that we can directly update the sqlite_master table in the
  ** to ON so that we can directly update the sqlite_schema table in the
  ** zTempDb database.
  */
  execSql(db, "PRAGMA writable_schema=ON");
  execSql(db, "BEGIN");


  /* Query the schema of the main database. Create a mirror schema
  ** in the temporary database.
  */
  execExecSql(db, 
      "SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14) "
      "  FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'"
      "  FROM sqlite_schema WHERE type='table' AND name!='sqlite_sequence'"
      "   AND rootpage>0"
  );
  execExecSql(db,
      "SELECT 'CREATE INDEX vacuum_db.' || substr(sql,14)"
      "  FROM sqlite_master WHERE sql LIKE 'CREATE INDEX %'"
      "  FROM sqlite_schema WHERE sql LIKE 'CREATE INDEX %'"
  );
  execExecSql(db,
      "SELECT 'CREATE UNIQUE INDEX vacuum_db.' || substr(sql,21) "
      "  FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %'"
      "  FROM sqlite_schema WHERE sql LIKE 'CREATE UNIQUE INDEX %'"
  );

  /* Loop through the tables in the main database. For each, do
  ** an "INSERT INTO vacuum_db.xxx SELECT * FROM main.xxx;" to copy
  ** the contents to the temporary database.
  */
  execExecSql(db,
      "SELECT 'INSERT INTO vacuum_db.' || quote(name) "
      "|| ' SELECT * FROM main.' || quote(name) "
      "FROM main.sqlite_master "
      "FROM main.sqlite_schema "
      "WHERE type = 'table' AND name!='sqlite_sequence' "
      "  AND rootpage>0"
  );

  /* Copy over the sequence table
  */
  execExecSql(db,
      "SELECT 'DELETE FROM vacuum_db.' || quote(name) "
      "FROM vacuum_db.sqlite_master WHERE name='sqlite_sequence'"
      "FROM vacuum_db.sqlite_schema WHERE name='sqlite_sequence'"
  );
  execExecSql(db,
      "SELECT 'INSERT INTO vacuum_db.' || quote(name) "
      "|| ' SELECT * FROM main.' || quote(name) "
      "FROM vacuum_db.sqlite_master WHERE name=='sqlite_sequence'"
      "FROM vacuum_db.sqlite_schema WHERE name=='sqlite_sequence'"
  );

  /* Copy the triggers, views, and virtual tables from the main database
  ** over to the temporary database.  None of these objects has any
  ** associated storage, so all we have to do is copy their entries
  ** from the SQLITE_MASTER table.
  */
  execSql(db,
      "INSERT INTO vacuum_db.sqlite_master "
      "INSERT INTO vacuum_db.sqlite_schema "
      "  SELECT type, name, tbl_name, rootpage, sql"
      "    FROM main.sqlite_master"
      "    FROM main.sqlite_schema"
      "   WHERE type='view' OR type='trigger'"
      "      OR (type='table' AND rootpage=0)"
  );

  /* Commit the transaction and close the database
  */
  execSql(db, "COMMIT");

Changes to tool/index_usage.c.

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
17
18
19
20
21
22
23

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

107
108
109
110
111
112
113
114
115
116


117
118
119
120
121
122
123
124
125
126
127
128

129
130
131
132
133
134
135
136
137
138
139
140

141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169

170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188

189
190



191
192
193



194
195
196
197
198
199
200
201
202
203
204
205
206
207



208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233







-
+














+
+
+
+
+
+













+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
+









-
-
+
+










-
+











-
+
+
+






+
+
+
+
+
+
+
+
+










+
-
+

+
+


+
+
+
+
+








-
+

-
-
-
+
+
+
-
-
-
+
+
+
+










-
-
-
+
+
+


















+




#include "sqlite3.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>

static void usage(const char *argv0){
  printf("Usage: %s DATABASE LOG\n\n", argv0);
  printf("Usage: %s [OPTIONS] DATABASE LOG\n\n", argv0);
  printf(
    "DATABASE is an SQLite database against which various statements\n"
    "have been run.  The SQL text is stored in LOG.  LOG is an SQLite\n"
    "database with this schema:\n"
    "\n"
    "    CREATE TABLE sqllog(sql TEXT);\n"
    "\n"
    "This utility program analyzes statements contained in LOG and prints\n"
    "a report showing how many times each index in DATABASE is used by the\n"
    "statements in LOG.\n"
    "\n"
    "DATABASE only needs to contain the schema used by the statements in\n"
    "LOG. The content can be removed from DATABASE.\n"
  );
  printf(
    "\nOPTIONS:\n\n"
    "    --progress N   Show a progress message after every N input rows\n"
    "    -q             Omit error message when parsing log entries\n"
    "    --using NAME   Print SQL statements that use index NAME\n"
  );
  printf("\nAnalysis will be done by SQLite version %s dated %.20s\n"
         "checkin number %.40s. Different versions\n"
         "of SQLite might use different indexes.\n",
         sqlite3_libversion(), sqlite3_sourceid(), sqlite3_sourceid()+21);
  exit(1);
}

int main(int argc, char **argv){
  sqlite3 *db = 0;          /* The main database */
  sqlite3_stmt *pStmt = 0;  /* a query */
  char *zSql;
  int nErr = 0;
  int rc;
  int bQuiet = 0;
  int i, j;
  const char *zUsing = 0;
  sqlite3_stmt *pIncrCnt = 0;
  int nRow = 0;
  int iProgress = 0;

  for(i=j=1; i<argc; i++){
    const char *z = argv[i];
    if( z[0]=='-' ){
      z++;
      if( z[0]=='-' ) z++;
      if( strcmp(z,"progress")==0 ){
        if( i+1<argc ){
          iProgress = strtol(argv[++i],0,0);
          continue;
        }
        printf("The --progress option requires an argument\n");
        exit(0);
      }
      if( strcmp(z,"q")==0 ){
        bQuiet = 1;
        continue;
      }
      if( strcmp(z,"using")==0 ){
        if( i+1<argc ){
          zUsing = argv[++i];
          continue;
        }
        printf("The --using option requires an argument\n");
        exit(0);
      }
      if( strcmp(z, "help")==0 || strcmp(z, "?")==0 ){
        usage(argv[0]);
      }
      printf("Unknown command-line option: \"%s\"\n", argv[i]);
      exit(0);
    }else{
      if( j<i ) argv[j++] = argv[i];
    }
  }
  argc = j;

  if( argc!=3 ) usage(argv[0]);
  rc = sqlite3_open_v2(argv[1], &db, SQLITE_OPEN_READONLY, 0);
  if( rc ){
    printf("Cannot open \"%s\" for reading: %s\n", argv[1], sqlite3_errmsg(db));
    goto errorOut;
  }
  rc = sqlite3_prepare_v2(db, "SELECT * FROM sqlite_master", -1, &pStmt, 0);
  rc = sqlite3_prepare_v2(db, "SELECT * FROM sqlite_schema", -1, &pStmt, 0);
  if( rc ){
    printf("Cannot read the schema from \"%s\" - %s\n", argv[1],
           sqlite3_errmsg(db));
    goto errorOut;
  }
  sqlite3_finalize(pStmt);
  pStmt = 0;
  rc = sqlite3_exec(db, 
     "CREATE TABLE temp.idxu(\n"
     "  tbl TEXT,\n"
     "  idx TEXT,\n"
     "  tbl TEXT COLLATE nocase,\n"
     "  idx TEXT COLLATE nocase,\n"
     "  cnt INT,\n"
     "  PRIMARY KEY(idx)\n"
     ") WITHOUT ROWID;", 0, 0, 0);
  if( rc ){
    printf("Cannot create the result table - %s\n",
           sqlite3_errmsg(db));
    goto errorOut;
  }
  rc = sqlite3_exec(db,
     "INSERT INTO temp.idxu(tbl,idx,cnt)"
     " SELECT tbl_name, name, 0 FROM sqlite_master"
     " SELECT tbl_name, name, 0 FROM sqlite_schema"
     " WHERE type='index' AND sql IS NOT NULL", 0, 0, 0);

  /* Open the LOG database */
  zSql = sqlite3_mprintf("ATTACH %Q AS log", argv[2]);
  rc = sqlite3_exec(db, zSql, 0, 0, 0);
  sqlite3_free(zSql);
  if( rc ){
    printf("Cannot open the LOG database \"%s\" - %s\n",
           argv[2], sqlite3_errmsg(db));
    goto errorOut;
  }
  rc = sqlite3_prepare_v2(db, "SELECT sql, rowid FROM log.sqllog",
  rc = sqlite3_prepare_v2(db,
     "SELECT sql, rowid FROM log.sqllog"
     " WHERE upper(substr(sql,1,5)) NOT IN ('BEGIN','COMMI','ROLLB','PRAGM')",
                          -1, &pStmt, 0);
  if( rc ){
    printf("Cannot read the SQLLOG table in the LOG database \"%s\" - %s\n",
           argv[2], sqlite3_errmsg(db));
    goto errorOut;
  }

  rc = sqlite3_prepare_v2(db,
    "UPDATE temp.idxu SET cnt=cnt+1 WHERE idx=?1",
    -1, &pIncrCnt, 0);
  if( rc ){
    printf("Cannot prepare a statement to increment a counter for "
           "indexes used\n");
    goto errorOut;
  }

  /* Update the counts based on LOG */
  while( sqlite3_step(pStmt)==SQLITE_ROW ){
    const char *zLog = (const char*)sqlite3_column_text(pStmt, 0);
    sqlite3_stmt *pS2;
    if( zLog==0 ) continue;
    zSql = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zLog);
    rc = sqlite3_prepare_v2(db, zSql, -1, &pS2, 0);
    sqlite3_free(zSql);
    if( rc ){
      if( !bQuiet ){
      printf("Cannot compile LOG entry %d (%s): %s\n",
        printf("Cannot compile LOG entry %d (%s): %s\n",
             sqlite3_column_int(pStmt, 1), zLog, sqlite3_errmsg(db));
        fflush(stdout);
      }
      nErr++;
    }else{
      nRow++;
      if( iProgress>0 && (nRow%iProgress)==0 ){
        printf("%d...\n", nRow);
        fflush(stdout);
      }
      while( sqlite3_step(pS2)==SQLITE_ROW ){
        const char *zExplain = (const char*)sqlite3_column_text(pS2,3);
        const char *z1, *z2;
        int n;
        /* printf("EXPLAIN: %s\n", zExplain); */
        z1 = strstr(zExplain, " USING INDEX ");
        if( z1==0 ) continue;
        z1 += 13;
        for(z2=z1+1; z2[1] && z2[1]!='('; z2++){}
        for(z2=z1+1; z2[0] && z2[1]!='('; z2++){}
        n = z2 - z1;
        zSql = sqlite3_mprintf(
          "UPDATE temp.idxu SET cnt=cnt+1 WHERE idx='%.*q'", n, z1
        );
        if( zUsing && sqlite3_strnicmp(zUsing, z1, n)==0 ){
          printf("Using %s:\n%s\n", zUsing, zLog);
          fflush(stdout);
        /* printf("sql: %s\n", zSql); */
        sqlite3_exec(db, zSql, 0, 0, 0);
        sqlite3_free(zSql);
        }
        sqlite3_bind_text(pIncrCnt,1,z1,n,SQLITE_STATIC);
        sqlite3_step(pIncrCnt);
        sqlite3_reset(pIncrCnt);
      }
    }
    sqlite3_finalize(pS2);
  }
  sqlite3_finalize(pStmt);

  /* Generate the report */
  rc = sqlite3_prepare_v2(db,
     "SELECT tbl, idx, cnt, "
     "   (SELECT group_concat(name,',') FROM pragma_index_info(idx))"
     " FROM temp.idxu, main.sqlite_master"
     " WHERE temp.idxu.tbl=main.sqlite_master.tbl_name"
     "   AND temp.idxu.idx=main.sqlite_master.name"
     " FROM temp.idxu, main.sqlite_schema"
     " WHERE temp.idxu.tbl=main.sqlite_schema.tbl_name"
     "   AND temp.idxu.idx=main.sqlite_schema.name"
     " ORDER BY cnt DESC, tbl, idx",
     -1, &pStmt, 0);
  if( rc ){
    printf("Cannot query the result table - %s\n",
           sqlite3_errmsg(db));
    goto errorOut;
  }
  while( sqlite3_step(pStmt)==SQLITE_ROW ){
    printf("%10d %s on %s(%s)\n", 
       sqlite3_column_int(pStmt, 2),
       sqlite3_column_text(pStmt, 1),
       sqlite3_column_text(pStmt, 0),
       sqlite3_column_text(pStmt, 3));
  }
  sqlite3_finalize(pStmt);
  pStmt = 0;

errorOut:
  sqlite3_finalize(pIncrCnt);
  sqlite3_finalize(pStmt);
  sqlite3_close(db);
  return nErr;
}

Changes to tool/lemon.c.

44
45
46
47
48
49
50

51
52
53
54
55
56
57
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58







+








#ifdef TEST
#define MAXRHS 5       /* Set low to exercise exception code */
#else
#define MAXRHS 1000
#endif

extern void memory_error();
static int showPrecedenceConflict = 0;
static char *msort(char*,char**,int(*)(const char*,const char*));

/*
** Compilers are getting increasingly pedantic about type conversions
** as C evolves ever closer to Ada....  To work around the latest problems
** we have to define the following variant of strlen().
213
214
215
216
217
218
219
220

221
222
223
224
225
226
227
214
215
216
217
218
219
220

221
222
223
224
225
226
227
228







-
+







void Plink_add(struct plink **, struct config *);
void Plink_copy(struct plink **, struct plink *);
void Plink_delete(struct plink *);

/********** From the file "report.h" *************************************/
void Reprint(struct lemon *);
void ReportOutput(struct lemon *);
void ReportTable(struct lemon *, int);
void ReportTable(struct lemon *, int, int);
void ReportHeader(struct lemon *);
void CompressTables(struct lemon *);
void ResortStates(struct lemon *);

/********** From the file "set.h" ****************************************/
void  SetSize(int);             /* All sets will be of size N */
char *SetNew(void);               /* A new set for element 0..N */
287
288
289
290
291
292
293
294
295
296
297
298


299
300


301
302
303
304
305
306
307
288
289
290
291
292
293
294


295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310







-
-



+
+


+
+







  int nrhs;                /* Number of RHS symbols */
  struct symbol **rhs;     /* The RHS symbols */
  const char **rhsalias;   /* An alias for each RHS symbol (NULL if none) */
  int line;                /* Line number at which code begins */
  const char *code;        /* The code executed when this rule is reduced */
  const char *codePrefix;  /* Setup code before code[] above */
  const char *codeSuffix;  /* Breakdown code after code[] above */
  int noCode;              /* True if this rule has no associated C code */
  int codeEmitted;         /* True if the code has been emitted already */
  struct symbol *precsym;  /* Precedence symbol for this rule */
  int index;               /* An index number for this rule */
  int iRule;               /* Rule number as used in the generated tables */
  Boolean noCode;          /* True if this rule has no associated C code */
  Boolean codeEmitted;     /* True if the code has been emitted already */
  Boolean canReduce;       /* True if this rule is ever reduced */
  Boolean doesReduce;      /* Reduce actions occur after optimization */
  Boolean neverReduce;     /* Reduce is theoretically possible, but prevented
                           ** by actions or other outside implementation */
  struct rule *nextlhs;    /* Next rule with the same LHS */
  struct rule *next;       /* Next rule in the global list */
};

/* A configuration is a production rule of the grammar together with
** a mark (dot) showing how much of that rule has been processed so far.
** Configurations also contain a follow-set which is a list of terminal
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
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







+













-
+







struct lemon {
  struct state **sorted;   /* Table of states sorted by state number */
  struct rule *rule;       /* List of all rules */
  struct rule *startRule;  /* First rule */
  int nstate;              /* Number of states */
  int nxstate;             /* nstate with tail degenerate states removed */
  int nrule;               /* Number of rules */
  int nruleWithAction;     /* Number of rules with actions */
  int nsymbol;             /* Number of terminal and nonterminal symbols */
  int nterminal;           /* Number of terminal symbols */
  int minShiftReduce;      /* Minimum shift-reduce action value */
  int errAction;           /* Error action value */
  int accAction;           /* Accept action value */
  int noAction;            /* No-op action value */
  int minReduce;           /* Minimum reduce action */
  int maxAction;           /* Maximum action value of any kind */
  struct symbol **symbols; /* Sorted array of pointers to symbols */
  int errorcnt;            /* Number of errors */
  struct symbol *errsym;   /* The error symbol */
  struct symbol *wildcard; /* Token that matches anything */
  char *name;              /* Name of the generated parser */
  char *arg;               /* Declaration of the 3th argument to parser */
  char *arg;               /* Declaration of the 3rd argument to parser */
  char *ctx;               /* Declaration of 2nd argument to constructor */
  char *tokentype;         /* Type of terminal symbols in the parser stack */
  char *vartype;           /* The default type of non-terminal symbols */
  char *start;             /* Name of the start symbol for the grammar */
  char *stacksize;         /* Size of the parser stack */
  char *include;           /* Code to put at the start of the C file */
  char *error;             /* Code to execute when an error is seen */
415
416
417
418
419
420
421

422
423
424
425
426
427
428
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433







+







  char *outname;           /* Name of the current output file */
  char *tokenprefix;       /* A prefix added to token names in the .h file */
  int nconflict;           /* Number of parsing conflicts */
  int nactiontab;          /* Number of entries in the yy_action[] table */
  int nlookaheadtab;       /* Number of entries in yy_lookahead[] */
  int tablesize;           /* Total table size of all tables in bytes */
  int basisflag;           /* Print only basis configurations */
  int printPreprocessed;   /* Show preprocessor output on stdout */
  int has_fallback;        /* True if any %fallback is seen in the grammar */
  int nolinenosflag;       /* True if #line statements should not be printed */
  char *argv0;             /* Name of the program */
};

#define MemoryCheck(X) if((X)==0){ \
  extern void memory_error(); \
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
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







-
+


-
+


-
-
+
+



-
-
+
+

-
-
+
+







/****************** From the file "action.c" *******************************/
/*
** Routines processing parser actions in the LEMON parser generator.
*/

/* Allocate a new parser action */
static struct action *Action_new(void){
  static struct action *freelist = 0;
  static struct action *actionfreelist = 0;
  struct action *newaction;

  if( freelist==0 ){
  if( actionfreelist==0 ){
    int i;
    int amt = 100;
    freelist = (struct action *)calloc(amt, sizeof(struct action));
    if( freelist==0 ){
    actionfreelist = (struct action *)calloc(amt, sizeof(struct action));
    if( actionfreelist==0 ){
      fprintf(stderr,"Unable to allocate memory for a new parser action.");
      exit(1);
    }
    for(i=0; i<amt-1; i++) freelist[i].next = &freelist[i+1];
    freelist[amt-1].next = 0;
    for(i=0; i<amt-1; i++) actionfreelist[i].next = &actionfreelist[i+1];
    actionfreelist[amt-1].next = 0;
  }
  newaction = freelist;
  freelist = freelist->next;
  newaction = actionfreelist;
  actionfreelist = actionfreelist->next;
  return newaction;
}

/* Compare two actions for sorting purposes.  Return negative, zero, or
** positive if the first action is less than, equal to, or greater than
** the first
*/
902
903
904
905
906
907
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
935
936
907
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



935
936
937
938
939
940
941
942
943
944







-
-
-
+
+
+



-
+

+
+
+










-
-
-
+
+
+







  Configlist_init();

  /* Find the start symbol */
  if( lemp->start ){
    sp = Symbol_find(lemp->start);
    if( sp==0 ){
      ErrorMsg(lemp->filename,0,
"The specified start symbol \"%s\" is not \
in a nonterminal of the grammar.  \"%s\" will be used as the start \
symbol instead.",lemp->start,lemp->startRule->lhs->name);
        "The specified start symbol \"%s\" is not "
        "in a nonterminal of the grammar.  \"%s\" will be used as the start "
        "symbol instead.",lemp->start,lemp->startRule->lhs->name);
      lemp->errorcnt++;
      sp = lemp->startRule->lhs;
    }
  }else{
  }else if( lemp->startRule ){
    sp = lemp->startRule->lhs;
  }else{
    ErrorMsg(lemp->filename,0,"Internal error - no start rule\n");
    exit(1);
  }

  /* Make sure the start symbol doesn't occur on the right-hand side of
  ** any rule.  Report an error if it does.  (YACC would generate a new
  ** start symbol in this case.) */
  for(rp=lemp->rule; rp; rp=rp->next){
    int i;
    for(i=0; i<rp->nrhs; i++){
      if( rp->rhs[i]==sp ){   /* FIX ME:  Deal with multiterminals */
        ErrorMsg(lemp->filename,0,
"The start symbol \"%s\" occurs on the \
right-hand side of a rule. This will result in a parser which \
does not work properly.",sp->name);
          "The start symbol \"%s\" occurs on the "
          "right-hand side of a rule. This will result in a parser which "
          "does not work properly.",sp->name);
        lemp->errorcnt++;
      }
    }
  }

  /* The basis configuration set for the first state
  ** is all rules which have the start symbol as their
1018
1019
1020
1021
1022
1023
1024
1025

1026
1027
1028
1029
1030
1031
1032
1026
1027
1028
1029
1030
1031
1032

1033
1034
1035
1036
1037
1038
1039
1040







-
+







  struct config *cfp;  /* For looping thru the config closure of "stp" */
  struct config *bcfp; /* For the inner loop on config closure of "stp" */
  struct config *newcfg;  /* */
  struct symbol *sp;   /* Symbol following the dot in configuration "cfp" */
  struct symbol *bsp;  /* Symbol following the dot in configuration "bcfp" */
  struct state *newstp; /* A pointer to a successor state */

  /* Each configuration becomes complete after it contibutes to a successor
  /* Each configuration becomes complete after it contributes to a successor
  ** state.  Initially, all configurations are incomplete */
  for(cfp=stp->cfp; cfp; cfp=cfp->next) cfp->status = INCOMPLETE;

  /* Loop through all configurations of the state "stp" */
  for(cfp=stp->cfp; cfp; cfp=cfp->next){
    if( cfp->status==COMPLETE ) continue;    /* Already used by inner loop */
    if( cfp->dot>=cfp->rp->nrhs ) continue;  /* Can't shift this config */
1074
1075
1076
1077
1078
1079
1080
1081

1082
1083
1084
1085
1086
1087
1088
1089
1090

1091
1092
1093
1094
1095
1096
1097
1082
1083
1084
1085
1086
1087
1088

1089
1090
1091
1092
1093
1094
1095
1096
1097

1098
1099
1100
1101
1102
1103
1104
1105







-
+








-
+







  struct plink *plp;

  /* Housekeeping detail:
  ** Add to every propagate link a pointer back to the state to
  ** which the link is attached. */
  for(i=0; i<lemp->nstate; i++){
    stp = lemp->sorted[i];
    for(cfp=stp->cfp; cfp; cfp=cfp->next){
    for(cfp=stp?stp->cfp:0; cfp; cfp=cfp->next){
      cfp->stp = stp;
    }
  }

  /* Convert all backlinks into forward links.  Only the forward
  ** links are used in the follow-set computation. */
  for(i=0; i<lemp->nstate; i++){
    stp = lemp->sorted[i];
    for(cfp=stp->cfp; cfp; cfp=cfp->next){
    for(cfp=stp?stp->cfp:0; cfp; cfp=cfp->next){
      for(plp=cfp->bplp; plp; plp=plp->next){
        other = plp->cfp;
        Plink_add(&other->fplp,cfp);
      }
    }
  }
}
1106
1107
1108
1109
1110
1111
1112

1113
1114
1115
1116
1117
1118
1119
1120

1121
1122
1123
1124
1125
1126
1127
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137







+








+







  int i;
  struct config *cfp;
  struct plink *plp;
  int progress;
  int change;

  for(i=0; i<lemp->nstate; i++){
    assert( lemp->sorted[i]!=0 );
    for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){
      cfp->status = INCOMPLETE;
    }
  }

  do{
    progress = 0;
    for(i=0; i<lemp->nstate; i++){
      assert( lemp->sorted[i]!=0 );
      for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){
        if( cfp->status==COMPLETE ) continue;
        for(plp=cfp->fplp; plp; plp=plp->next){
          change = SetUnion(plp->cfp->fws,cfp->fws);
          if( change ){
            plp->cfp->status = INCOMPLETE;
            progress = 1;
1163
1164
1165
1166
1167
1168
1169






1170


1171
1172
1173
1174
1175
1176
1177
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185

1186
1187
1188
1189
1190
1191
1192
1193
1194







+
+
+
+
+
+
-
+
+







      }
    }
  }

  /* Add the accepting token */
  if( lemp->start ){
    sp = Symbol_find(lemp->start);
    if( sp==0 ){
      if( lemp->startRule==0 ){
        fprintf(stderr, "internal error on source line %d: no start rule\n",
                __LINE__);
        exit(1);
      }
    if( sp==0 ) sp = lemp->startRule->lhs;
      sp = lemp->startRule->lhs;
    }
  }else{
    sp = lemp->startRule->lhs;
  }
  /* Add to the first state (which is always the starting state of the
  ** finite state machine) an action to ACCEPT if the lookahead is the
  ** start nonterminal.  */
  Action_add(&lemp->sorted[0]->ap,ACCEPT,sp,0);
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
1318
1307
1308
1309
1310
1311
1312
1313





1314










1315
1316
1317
1318
1319
1320
1321







-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-







static struct config *current = 0;       /* Top of list of configurations */
static struct config **currentend = 0;   /* Last on list of configs */
static struct config *basis = 0;         /* Top of list of basis configs */
static struct config **basisend = 0;     /* End of list of basis configs */

/* Return a pointer to a new configuration */
PRIVATE struct config *newconfig(void){
  struct config *newcfg;
  if( freelist==0 ){
    int i;
    int amt = 3;
    freelist = (struct config *)calloc( amt, sizeof(struct config) );
  return (struct config*)calloc(1, sizeof(struct config));
    if( freelist==0 ){
      fprintf(stderr,"Unable to allocate memory for a new configuration.");
      exit(1);
    }
    for(i=0; i<amt-1; i++) freelist[i].next = &freelist[i+1];
    freelist[amt-1].next = 0;
  }
  newcfg = freelist;
  freelist = freelist->next;
  return newcfg;
}

/* The configuration "old" is no longer used */
PRIVATE void deleteconfig(struct config *old)
{
  old->next = freelist;
  freelist = old;
1582
1583
1584
1585
1586
1587
1588
1589

1590
1591
1592
1593
1594
1595
1596

1597
1598
1599
1600
1601
1602
1603
1585
1586
1587
1588
1589
1590
1591

1592
1593
1594
1595
1596
1597
1598

1599
1600
1601
1602
1603
1604
1605
1606







-
+






-
+







  return pFirst;
}

/*
** Sort a list of rules in order of increasing iRule value
*/
static struct rule *Rule_sort(struct rule *rp){
  int i;
  unsigned int i;
  struct rule *pNext;
  struct rule *x[32];
  memset(x, 0, sizeof(x));
  while( rp ){
    pNext = rp->next;
    rp->next = 0;
    for(i=0; i<sizeof(x)/sizeof(x[0]) && x[i]; i++){
    for(i=0; i<sizeof(x)/sizeof(x[0])-1 && x[i]; i++){
      rp = Rule_merge(x[i], rp);
      x[i] = 0;
    }
    x[i] = rp;
    rp = pNext;
  }
  rp = 0;
1616
1617
1618
1619
1620
1621
1622
1623

1624
1625
1626
1627
1628
1629
1630
1631
1632
1633


1634
1635
1636
1637
1638
1639

1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651


1652
1653
1654
1655
1656
1657
1658
1659
1660
1661

1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681

1682
1683
1684
1685
1686

1687
1688
1689
1690
1691
1692
1693
1619
1620
1621
1622
1623
1624
1625

1626

1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694

1695
1696
1697
1698
1699
1700
1701
1702







-
+
-









+
+






+












+
+










+




















+




-
+







  int nLabel = lemonStrlen(zLabel);
  printf("  %s%.*s %5d\n", zLabel,
         35-nLabel, "................................",
         iValue);
}

/* The main program.  Parse the command line and do it... */
int main(int argc, char **argv)
int main(int argc, char **argv){
{
  static int version = 0;
  static int rpflag = 0;
  static int basisflag = 0;
  static int compress = 0;
  static int quiet = 0;
  static int statistics = 0;
  static int mhflag = 0;
  static int nolinenosflag = 0;
  static int noResort = 0;
  static int sqlFlag = 0;
  static int printPP = 0;
  
  static struct s_options options[] = {
    {OPT_FLAG, "b", (char*)&basisflag, "Print only the basis in report."},
    {OPT_FLAG, "c", (char*)&compress, "Don't compress the action table."},
    {OPT_FSTR, "d", (char*)&handle_d_option, "Output directory.  Default '.'"},
    {OPT_FSTR, "D", (char*)handle_D_option, "Define an %ifdef macro."},
    {OPT_FLAG, "E", (char*)&printPP, "Print input file after preprocessing."},
    {OPT_FSTR, "f", 0, "Ignored.  (Placeholder for -f compiler options.)"},
    {OPT_FLAG, "g", (char*)&rpflag, "Print grammar without actions."},
    {OPT_FSTR, "I", 0, "Ignored.  (Placeholder for '-I' compiler options.)"},
    {OPT_FLAG, "m", (char*)&mhflag, "Output a makeheaders compatible file."},
    {OPT_FLAG, "l", (char*)&nolinenosflag, "Do not print #line statements."},
    {OPT_FSTR, "O", 0, "Ignored.  (Placeholder for '-O' compiler options.)"},
    {OPT_FLAG, "p", (char*)&showPrecedenceConflict,
                    "Show conflicts resolved by precedence rules"},
    {OPT_FLAG, "q", (char*)&quiet, "(Quiet) Don't print the report file."},
    {OPT_FLAG, "r", (char*)&noResort, "Do not sort or renumber states"},
    {OPT_FLAG, "s", (char*)&statistics,
                                   "Print parser stats to standard output."},
    {OPT_FLAG, "S", (char*)&sqlFlag,
                    "Generate the *.sql file describing the parser tables."},
    {OPT_FLAG, "x", (char*)&version, "Print the version number."},
    {OPT_FSTR, "T", (char*)handle_T_option, "Specify a template file."},
    {OPT_FSTR, "W", 0, "Ignored.  (Placeholder for '-W' compiler options.)"},
    {OPT_FLAG,0,0,0}
  };
  int i;
  int exitcode;
  struct lemon lem;
  struct rule *rp;

  (void)argc;
  OptInit(argv,options,stderr);
  if( version ){
     printf("Lemon version 1.0\n");
     exit(0);
  }
  if( OptNArgs()!=1 ){
    fprintf(stderr,"Exactly one filename argument is required.\n");
    exit(1);
  }
  memset(&lem, 0, sizeof(lem));
  lem.errorcnt = 0;

  /* Initialize the machine */
  Strsafe_init();
  Symbol_init();
  State_init();
  lem.argv0 = argv[0];
  lem.filename = OptArg(0);
  lem.basisflag = basisflag;
  lem.nolinenosflag = nolinenosflag;
  lem.printPreprocessed = printPP;
  Symbol_new("$");

  /* Parse the input file */
  Parse(&lem);
  if( lem.errorcnt ) exit(lem.errorcnt);
  if( lem.printPreprocessed || lem.errorcnt ) exit(lem.errorcnt);
  if( lem.nrule==0 ){
    fprintf(stderr,"Empty grammar.\n");
    exit(1);
  }
  lem.errsym = Symbol_find("error");

  /* Count and index the symbols of the grammar */
1706
1707
1708
1709
1710
1711
1712

1713
1714
1715
1716
1717
1718
1719
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729







+







  /* Assign sequential rule numbers.  Start with 0.  Put rules that have no
  ** reduce action C-code associated with them last, so that the switch()
  ** statement that selects reduction actions will have a smaller jump table.
  */
  for(i=0, rp=lem.rule; rp; rp=rp->next){
    rp->iRule = rp->code ? i++ : -1;
  }
  lem.nruleWithAction = i;
  for(rp=lem.rule; rp; rp=rp->next){
    if( rp->iRule<0 ) rp->iRule = i++;
  }
  lem.startRule = lem.rule;
  lem.rule = Rule_sort(lem.rule);

  /* Generate a reprint of the grammar, if requested on the command line */
1753
1754
1755
1756
1757
1758
1759
1760

1761
1762
1763
1764
1765
1766
1767
1763
1764
1765
1766
1767
1768
1769

1770
1771
1772
1773
1774
1775
1776
1777







-
+







    ** generated parser tables smaller. */
    if( noResort==0 ) ResortStates(&lem);

    /* Generate a report of the parser generated.  (the "y.output" file) */
    if( !quiet ) ReportOutput(&lem);

    /* Generate the source code for the parser */
    ReportTable(&lem, mhflag);
    ReportTable(&lem, mhflag, sqlFlag);

    /* Produce a header file for use by the scanner.  (This step is
    ** omitted if the "-m" option is used because makeheaders will
    ** generate the file for us.) */
    if( !mhflag ) ReportHeader(&lem);
  }
  if( statistics ){
1871
1872
1873
1874
1875
1876
1877
1878

1879
1880
1881
1882
1883
1884
1885
1881
1882
1883
1884
1885
1886
1887

1888
1889
1890
1891
1892
1893
1894
1895







-
+







** Inputs:
**   list:      Pointer to a singly-linked list of structures.
**   next:      Pointer to pointer to the second element of the list.
**   cmp:       A comparison function.
**
** Return Value:
**   A pointer to the head of a sorted list containing the elements
**   orginally in list.
**   originally in list.
**
** Side effects:
**   The "next" pointers for elements in list are changed.
*/
#define LISTSIZE 30
static char *msort(
  char *list,
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
1984
1985

1986
1987
1988
1989
1990
1991
1992
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
1984

1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998

1999
2000
2001
2002
2003
2004
2005
2006







-
+












+
-
-
-
-
-
+
+
+
+
+
+
+
+


-
+















-
-
-
+
+
+



-
+
















-
+

-
+













-
+







    set[i] = ep;
  }
  ep = 0;
  for(i=0; i<LISTSIZE; i++) if( set[i] ) ep = merge(set[i],ep,cmp,offset);
  return ep;
}
/************************ From the file "option.c" **************************/
static char **argv;
static char **g_argv;
static struct s_options *op;
static FILE *errstream;

#define ISOPT(X) ((X)[0]=='-'||(X)[0]=='+'||strchr((X),'=')!=0)

/*
** Print the command line with a carrot pointing to the k-th character
** of the n-th field.
*/
static void errline(int n, int k, FILE *err)
{
  int spcnt, i;
  if( g_argv[0] ){
  if( argv[0] ) fprintf(err,"%s",argv[0]);
  spcnt = lemonStrlen(argv[0]) + 1;
  for(i=1; i<n && argv[i]; i++){
    fprintf(err," %s",argv[i]);
    spcnt += lemonStrlen(argv[i])+1;
    fprintf(err,"%s",g_argv[0]);
    spcnt = lemonStrlen(g_argv[0]) + 1;
  }else{
    spcnt = 0;
  }
  for(i=1; i<n && g_argv[i]; i++){
    fprintf(err," %s",g_argv[i]);
    spcnt += lemonStrlen(g_argv[i])+1;
  }
  spcnt += k;
  for(; argv[i]; i++) fprintf(err," %s",argv[i]);
  for(; g_argv[i]; i++) fprintf(err," %s",g_argv[i]);
  if( spcnt<20 ){
    fprintf(err,"\n%*s^-- here\n",spcnt,"");
  }else{
    fprintf(err,"\n%*shere --^\n",spcnt-7,"");
  }
}

/*
** Return the index of the N-th non-switch argument.  Return -1
** if N is out of range.
*/
static int argindex(int n)
{
  int i;
  int dashdash = 0;
  if( argv!=0 && *argv!=0 ){
    for(i=1; argv[i]; i++){
      if( dashdash || !ISOPT(argv[i]) ){
  if( g_argv!=0 && *g_argv!=0 ){
    for(i=1; g_argv[i]; i++){
      if( dashdash || !ISOPT(g_argv[i]) ){
        if( n==0 ) return i;
        n--;
      }
      if( strcmp(argv[i],"--")==0 ) dashdash = 1;
      if( strcmp(g_argv[i],"--")==0 ) dashdash = 1;
    }
  }
  return -1;
}

static char emsg[] = "Command line syntax error: ";

/*
** Process a flag command line argument.
*/
static int handleflags(int i, FILE *err)
{
  int v;
  int errcnt = 0;
  int j;
  for(j=0; op[j].label; j++){
    if( strncmp(&argv[i][1],op[j].label,lemonStrlen(op[j].label))==0 ) break;
    if( strncmp(&g_argv[i][1],op[j].label,lemonStrlen(op[j].label))==0 ) break;
  }
  v = argv[i][0]=='-' ? 1 : 0;
  v = g_argv[i][0]=='-' ? 1 : 0;
  if( op[j].label==0 ){
    if( err ){
      fprintf(err,"%sundefined option.\n",emsg);
      errline(i,1,err);
    }
    errcnt++;
  }else if( op[j].arg==0 ){
    /* Ignore this option */
  }else if( op[j].type==OPT_FLAG ){
    *((int*)op[j].arg) = v;
  }else if( op[j].type==OPT_FFLAG ){
    (*(void(*)(int))(op[j].arg))(v);
  }else if( op[j].type==OPT_FSTR ){
    (*(void(*)(char *))(op[j].arg))(&argv[i][2]);
    (*(void(*)(char *))(op[j].arg))(&g_argv[i][2]);
  }else{
    if( err ){
      fprintf(err,"%smissing argument on switch.\n",emsg);
      errline(i,1,err);
    }
    errcnt++;
  }
2000
2001
2002
2003
2004
2005
2006
2007

2008
2009
2010
2011

2012
2013
2014
2015
2016
2017
2018
2014
2015
2016
2017
2018
2019
2020

2021
2022
2023
2024

2025
2026
2027
2028
2029
2030
2031
2032







-
+



-
+







{
  int lv = 0;
  double dv = 0.0;
  char *sv = 0, *end;
  char *cp;
  int j;
  int errcnt = 0;
  cp = strchr(argv[i],'=');
  cp = strchr(g_argv[i],'=');
  assert( cp!=0 );
  *cp = 0;
  for(j=0; op[j].label; j++){
    if( strcmp(argv[i],op[j].label)==0 ) break;
    if( strcmp(g_argv[i],op[j].label)==0 ) break;
  }
  *cp = '=';
  if( op[j].label==0 ){
    if( err ){
      fprintf(err,"%sundefined option.\n",emsg);
      errline(i,0,err);
    }
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
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







-
+










-
+







      case OPT_DBL:
      case OPT_FDBL:
        dv = strtod(cp,&end);
        if( *end ){
          if( err ){
            fprintf(err,
               "%sillegal character in floating-point argument.\n",emsg);
            errline(i,(int)((char*)end-(char*)argv[i]),err);
            errline(i,(int)((char*)end-(char*)g_argv[i]),err);
          }
          errcnt++;
        }
        break;
      case OPT_INT:
      case OPT_FINT:
        lv = strtol(cp,&end,0);
        if( *end ){
          if( err ){
            fprintf(err,"%sillegal character in integer argument.\n",emsg);
            errline(i,(int)((char*)end-(char*)argv[i]),err);
            errline(i,(int)((char*)end-(char*)g_argv[i]),err);
          }
          errcnt++;
        }
        break;
      case OPT_STR:
      case OPT_FSTR:
        sv = cp;
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
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







-
+


-
+

-
-
+
+

-
+
















-
-
-
-
+
+
+
+









-
+







  }
  return errcnt;
}

int OptInit(char **a, struct s_options *o, FILE *err)
{
  int errcnt = 0;
  argv = a;
  g_argv = a;
  op = o;
  errstream = err;
  if( argv && *argv && op ){
  if( g_argv && *g_argv && op ){
    int i;
    for(i=1; argv[i]; i++){
      if( argv[i][0]=='+' || argv[i][0]=='-' ){
    for(i=1; g_argv[i]; i++){
      if( g_argv[i][0]=='+' || g_argv[i][0]=='-' ){
        errcnt += handleflags(i,err);
      }else if( strchr(argv[i],'=') ){
      }else if( strchr(g_argv[i],'=') ){
        errcnt += handleswitch(i,err);
      }
    }
  }
  if( errcnt>0 ){
    fprintf(err,"Valid command line options for \"%s\" are:\n",*a);
    OptPrint();
    exit(1);
  }
  return 0;
}

int OptNArgs(void){
  int cnt = 0;
  int dashdash = 0;
  int i;
  if( argv!=0 && argv[0]!=0 ){
    for(i=1; argv[i]; i++){
      if( dashdash || !ISOPT(argv[i]) ) cnt++;
      if( strcmp(argv[i],"--")==0 ) dashdash = 1;
  if( g_argv!=0 && g_argv[0]!=0 ){
    for(i=1; g_argv[i]; i++){
      if( dashdash || !ISOPT(g_argv[i]) ) cnt++;
      if( strcmp(g_argv[i],"--")==0 ) dashdash = 1;
    }
  }
  return cnt;
}

char *OptArg(int n)
{
  int i;
  i = argindex(n);
  return i>=0 ? argv[i] : 0;
  return i>=0 ? g_argv[i] : 0;
}

void OptErr(int n)
{
  int i;
  i = argindex(n);
  if( i>=0 ) errline(i,0,errstream);
2250
2251
2252
2253
2254
2255
2256
2257

2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270


2271
2272
2273
2274
2275


2276


2277
2278
2279
2280
2281
2282
2283
2264
2265
2266
2267
2268
2269
2270

2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282


2283
2284
2285
2286
2287


2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299







-
+











-
-
+
+



-
-
+
+

+
+







#endif
  switch( psp->state ){
    case INITIALIZE:
      psp->prevrule = 0;
      psp->preccounter = 0;
      psp->firstrule = psp->lastrule = 0;
      psp->gp->nrule = 0;
      /* Fall thru to next case */
      /* fall through */
    case WAITING_FOR_DECL_OR_RULE:
      if( x[0]=='%' ){
        psp->state = WAITING_FOR_DECL_KEYWORD;
      }else if( ISLOWER(x[0]) ){
        psp->lhs = Symbol_new(x);
        psp->nrhs = 0;
        psp->lhsalias = 0;
        psp->state = WAITING_FOR_ARROW;
      }else if( x[0]=='{' ){
        if( psp->prevrule==0 ){
          ErrorMsg(psp->filename,psp->tokenlineno,
"There is no prior rule upon which to attach the code \
fragment which begins on this line.");
            "There is no prior rule upon which to attach the code "
            "fragment which begins on this line.");
          psp->errorcnt++;
        }else if( psp->prevrule->code!=0 ){
          ErrorMsg(psp->filename,psp->tokenlineno,
"Code fragment beginning on this line is not the first \
to follow the previous rule.");
            "Code fragment beginning on this line is not the first "
            "to follow the previous rule.");
          psp->errorcnt++;
        }else if( strcmp(x, "{NEVER-REDUCE")==0 ){
          psp->prevrule->neverReduce = 1;
        }else{
          psp->prevrule->line = psp->tokenlineno;
          psp->prevrule->code = &x[1];
          psp->prevrule->noCode = 0;
        }
      }else if( x[0]=='[' ){
        psp->state = PRECEDENCE_MARK_1;
2295
2296
2297
2298
2299
2300
2301
2302
2303


2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317


2318
2319
2320
2321
2322
2323
2324
2325
2326







-
-
+
+







        psp->errorcnt++;
      }else if( psp->prevrule==0 ){
        ErrorMsg(psp->filename,psp->tokenlineno,
          "There is no prior rule to assign precedence \"[%s]\".",x);
        psp->errorcnt++;
      }else if( psp->prevrule->precsym!=0 ){
        ErrorMsg(psp->filename,psp->tokenlineno,
"Precedence mark on this line is not the first \
to follow the previous rule.");
          "Precedence mark on this line is not the first "
          "to follow the previous rule.");
        psp->errorcnt++;
      }else{
        psp->prevrule->precsym = Symbol_new(x);
      }
      psp->state = PRECEDENCE_MARK_2;
      break;
    case PRECEDENCE_MARK_2:
2408
2409
2410
2411
2412
2413
2414
2415

2416
2417
2418
2419
2420
2421
2422
2424
2425
2426
2427
2428
2429
2430

2431
2432
2433
2434
2435
2436
2437
2438







-
+







          psp->errorcnt++;
          psp->state = RESYNC_AFTER_RULE_ERROR;
        }else{
          psp->rhs[psp->nrhs] = Symbol_new(x);
          psp->alias[psp->nrhs] = 0;
          psp->nrhs++;
        }
      }else if( (x[0]=='|' || x[0]=='/') && psp->nrhs>0 ){
      }else if( (x[0]=='|' || x[0]=='/') && psp->nrhs>0 && ISUPPER(x[1]) ){
        struct symbol *msp = psp->rhs[psp->nrhs-1];
        if( msp->type!=MULTITERMINAL ){
          struct symbol *origsp = msp;
          msp = (struct symbol *) calloc(1,sizeof(*msp));
          memset(msp, 0, sizeof(*msp));
          msp->type = MULTITERMINAL;
          msp->nsubsym = 1;
2620
2621
2622
2623
2624
2625
2626
2627
2628




2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642


2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653







-
-
+
+
+
+







        if( *psp->declargslot ){
          zOld = *psp->declargslot;
        }else{
          zOld = "";
        }
        nOld = lemonStrlen(zOld);
        n = nOld + nNew + 20;
        addLineMacro = !psp->gp->nolinenosflag && psp->insertLineMacro &&
                        (psp->decllinenoslot==0 || psp->decllinenoslot[0]!=0);
        addLineMacro = !psp->gp->nolinenosflag
                       && psp->insertLineMacro
                       && psp->tokenlineno>1
                       && (psp->decllinenoslot==0 || psp->decllinenoslot[0]!=0);
        if( addLineMacro ){
          for(z=psp->filename, nBack=0; *z; z++){
            if( *z=='\\' ) nBack++;
          }
          lemon_sprintf(zLine, "#line %d ", psp->tokenlineno);
          nLine = lemonStrlen(zLine);
          n += nLine + lemonStrlen(psp->filename) + nBack;
2688
2689
2690
2691
2692
2693
2694
2695

2696
2697
2698
2699
2700
2701
2702
2706
2707
2708
2709
2710
2711
2712

2713
2714
2715
2716
2717
2718
2719
2720







-
+







      }
      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]) ){
2724
2725
2726
2727
2728
2729
2730
2731

2732
2733
2734
2735
2736
2737
2738
2742
2743
2744
2745
2746
2747
2748

2749
2750
2751
2752
2753
2754
2755
2756







-
+







          psp->errorcnt++;
        }
      }
      break;
    case WAITING_FOR_CLASS_ID:
      if( !ISLOWER(x[0]) ){
        ErrorMsg(psp->filename, psp->tokenlineno,
          "%%token_class must be followed by an identifier: ", x);
          "%%token_class must be followed by an identifier: %s", x);
        psp->errorcnt++;
        psp->state = RESYNC_AFTER_DECL_ERROR;
     }else if( Symbol_find(x) ){
        ErrorMsg(psp->filename, psp->tokenlineno,
          "Symbol \"%s\" already used", x);
        psp->errorcnt++;
        psp->state = RESYNC_AFTER_DECL_ERROR;
2764
2765
2766
2767
2768
2769
2770
2771































































































2772
2773
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
2811
2812
2813
2814
2815
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
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890

2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916


2917
2918
2919
2920
2921
2922
2923
2924



2925
2926
2927
2928
2929




2930
2931
2932



2933
2934
2935
2936
2937
2938
2939
2940








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
+















+
+
+
+
+
+
+
+
+
+
-
-
+
+
+



+
+
-
-
-
+
+
+
+
+
-
-
-
-
+
+
+
-
-
-
+







**      break; */
    case RESYNC_AFTER_DECL_ERROR:
      if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE;
      if( x[0]=='%' ) psp->state = WAITING_FOR_DECL_KEYWORD;
      break;
  }
}

/* The text in the input is part of the argument to an %ifdef or %ifndef.
** Evaluate the text as a boolean expression.  Return true or false.
*/
static int eval_preprocessor_boolean(char *z, int lineno){
  int neg = 0;
  int res = 0;
  int okTerm = 1;
  int i;
  for(i=0; z[i]!=0; i++){
    if( ISSPACE(z[i]) ) continue;
    if( z[i]=='!' ){
      if( !okTerm ) goto pp_syntax_error;
      neg = !neg;
      continue;
    }
    if( z[i]=='|' && z[i+1]=='|' ){
      if( okTerm ) goto pp_syntax_error;
      if( res ) return 1;
      i++;
      okTerm = 1;
      continue;
    }
    if( z[i]=='&' && z[i+1]=='&' ){
      if( okTerm ) goto pp_syntax_error;
      if( !res ) return 0;
      i++;
      okTerm = 1;
      continue;
    }
    if( z[i]=='(' ){
      int k;
      int n = 1;
      if( !okTerm ) goto pp_syntax_error;
      for(k=i+1; z[k]; k++){
        if( z[k]==')' ){
          n--;
          if( n==0 ){
            z[k] = 0;
            res = eval_preprocessor_boolean(&z[i+1], -1);
            z[k] = ')';
            if( res<0 ){
              i = i-res;
              goto pp_syntax_error;
            }
            i = k;
            break;
          }
        }else if( z[k]=='(' ){
          n++;
        }else if( z[k]==0 ){
          i = k;
          goto pp_syntax_error;
        }
      }
      if( neg ){
        res = !res;
        neg = 0;
      }
      okTerm = 0;
      continue;
    }
    if( ISALPHA(z[i]) ){
      int j, k, n;
      if( !okTerm ) goto pp_syntax_error;
      for(k=i+1; ISALNUM(z[k]) || z[k]=='_'; k++){}
      n = k - i;
      res = 0;
      for(j=0; j<nDefine; j++){
        if( strncmp(azDefine[j],&z[i],n)==0 && azDefine[j][n]==0 ){
          res = 1;
          break;
        }
      }
      i = k-1;
      if( neg ){
        res = !res;
        neg = 0;
      }
      okTerm = 0;
      continue;
    }
    goto pp_syntax_error;
  }
  return res;

pp_syntax_error:
  if( lineno>0 ){
    fprintf(stderr, "%%if syntax error on line %d.\n", lineno);
    fprintf(stderr, "  %.*s <-- syntax error here\n", i+1, z);
    exit(1);
  }else{
    return -(i+1);
  }
}

/* Run the preprocessor over the input file text.  The global variables
** azDefine[0] through azDefine[nDefine-1] contains the names of all defined
** macros.  This routine looks for "%ifdef" and "%ifndef" and "%endif" and
** comments them out.  Text in between is also commented out as appropriate.
*/
static void preprocess_input(char *z){
  int i, j, k, n;
  int i, j, k;
  int exclude = 0;
  int start = 0;
  int lineno = 1;
  int start_lineno = 1;
  for(i=0; z[i]; i++){
    if( z[i]=='\n' ) lineno++;
    if( z[i]!='%' || (i>0 && z[i-1]!='\n') ) continue;
    if( strncmp(&z[i],"%endif",6)==0 && ISSPACE(z[i+6]) ){
      if( exclude ){
        exclude--;
        if( exclude==0 ){
          for(j=start; j<i; j++) if( z[j]!='\n' ) z[j] = ' ';
        }
      }
      for(j=i; z[j] && z[j]!='\n'; j++) z[j] = ' ';
    }else if( strncmp(&z[i],"%else",5)==0 && ISSPACE(z[i+5]) ){
      if( exclude==1){
        exclude = 0;
        for(j=start; j<i; j++) if( z[j]!='\n' ) z[j] = ' ';
      }else if( exclude==0 ){
        exclude = 1;
        start = i;
        start_lineno = lineno;
      }
      for(j=i; z[j] && z[j]!='\n'; j++) z[j] = ' ';
    }else if( (strncmp(&z[i],"%ifdef",6)==0 && ISSPACE(z[i+6]))
          || (strncmp(&z[i],"%ifndef",7)==0 && ISSPACE(z[i+7])) ){
    }else if( strncmp(&z[i],"%ifdef ",7)==0 
          || strncmp(&z[i],"%if ",4)==0
          || strncmp(&z[i],"%ifndef ",8)==0 ){
      if( exclude ){
        exclude++;
      }else{
        int isNot;
        int iBool;
        for(j=i+7; ISSPACE(z[j]); j++){}
        for(n=0; z[j+n] && !ISSPACE(z[j+n]); n++){}
        exclude = 1;
        for(j=i; z[j] && !ISSPACE(z[j]); j++){}
        iBool = j;
        isNot = (j==i+7);
        while( z[j] && z[j]!='\n' ){ j++; }
        k = z[j];
        for(k=0; k<nDefine; k++){
          if( strncmp(azDefine[k],&z[j],n)==0 && lemonStrlen(azDefine[k])==n ){
            exclude = 0;
            break;
        z[j] = 0;
        exclude = eval_preprocessor_boolean(&z[iBool], lineno);
        z[j] = k;
          }
        }
        if( z[i+3]=='n' ) exclude = !exclude;
        if( !isNot ) exclude = !exclude;
        if( exclude ){
          start = i;
          start_lineno = lineno;
        }
      }
      for(j=i; z[j] && z[j]!='\n'; j++) z[j] = ' ';
    }
2869
2870
2871
2872
2873
2874
2875




2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888

2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906


2907
2908
2909
2910
2911
2912
2913
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035

3036
3037
3038
3039
3040
3041
3042
3043
3044







+
+
+
+













+

















-
+
+







    return;
  }
  fclose(fp);
  filebuf[filesize] = 0;

  /* Make an initial pass through the file to handle %ifdef and %ifndef */
  preprocess_input(filebuf);
  if( gp->printPreprocessed ){
    printf("%s\n", filebuf);
    return;
  }

  /* Now scan the text of the input file */
  lineno = 1;
  for(cp=filebuf; (c= *cp)!=0; ){
    if( c=='\n' ) lineno++;              /* Keep track of the line number */
    if( ISSPACE(c) ){ cp++; continue; }  /* Skip all white space */
    if( c=='/' && cp[1]=='/' ){          /* Skip C++ style comments */
      cp+=2;
      while( (c= *cp)!=0 && c!='\n' ) cp++;
      continue;
    }
    if( c=='/' && cp[1]=='*' ){          /* Skip C style comments */
      cp+=2;
      if( (*cp)=='/' ) cp++;
      while( (c= *cp)!=0 && (c!='/' || cp[-1]!='*') ){
        if( c=='\n' ) lineno++;
        cp++;
      }
      if( c ) cp++;
      continue;
    }
    ps.tokenstart = cp;                /* Mark the beginning of the token */
    ps.tokenlineno = lineno;           /* Linenumber on which token begins */
    if( c=='\"' ){                     /* String literals */
      cp++;
      while( (c= *cp)!=0 && c!='\"' ){
        if( c=='\n' ) lineno++;
        cp++;
      }
      if( c==0 ){
        ErrorMsg(ps.filename,startline,
"String starting on this line is not terminated before the end of the file.");
            "String starting on this line is not terminated before "
            "the end of the file.");
        ps.errorcnt++;
        nextcp = cp;
      }else{
        nextcp = cp+1;
      }
    }else if( c=='{' ){               /* A block of C code */
      int level;
2938
2939
2940
2941
2942
2943
2944
2945


2946
2947
2948
2949
2950
2951
2952
3069
3070
3071
3072
3073
3074
3075

3076
3077
3078
3079
3080
3081
3082
3083
3084







-
+
+







            if( prevc=='\\' ) prevc = 0;
            else              prevc = c;
          }
        }
      }
      if( c==0 ){
        ErrorMsg(ps.filename,ps.tokenlineno,
"C code starting on this line is not terminated before the end of the file.");
          "C code starting on this line is not terminated before "
          "the end of the file.");
        ps.errorcnt++;
        nextcp = cp;
      }else{
        nextcp = cp+1;
      }
    }else if( ISALNUM(c) ){          /* Identifiers */
      while( (c= *cp)!=0 && (ISALNUM(c) || c=='_') ) cp++;
3380
3381
3382
3383
3384
3385
3386
3387

3388
3389
3390
3391
3392


3393
3394
3395
3396
3397
3398
3399
3512
3513
3514
3515
3516
3517
3518

3519
3520
3521
3522


3523
3524
3525
3526
3527
3528
3529
3530
3531







-
+



-
-
+
+







    fprintf(fp,"\n");
  }
  fclose(fp);
  return;
}

/* Search for the file "name" which is in the same directory as
** the exacutable */
** the executable */
PRIVATE char *pathsearch(char *argv0, char *name, int modemask)
{
  const char *pathlist;
  char *pathbufptr;
  char *pathbuf;
  char *pathbufptr = 0;
  char *pathbuf = 0;
  char *path,*cp;
  char c;

#ifdef __WIN32__
  cp = strrchr(argv0,'\\');
#else
  cp = strrchr(argv0,'/');
3419
3420
3421
3422
3423
3424
3425
3426
3427

3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445



3446
3447
3448
3449
3450
3451
3452
3551
3552
3553
3554
3555
3556
3557

3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576

3577
3578
3579
3580
3581
3582
3583
3584
3585
3586







-

+

















-
+
+
+







        *cp = 0;
        lemon_sprintf(path,"%s/%s",pathbuf,name);
        *cp = c;
        if( c==0 ) pathbuf[0] = 0;
        else pathbuf = &cp[1];
        if( access(path,modemask)==0 ) break;
      }
      free(pathbufptr);
    }
    free(pathbufptr);
  }
  return path;
}

/* Given an action, compute the integer value for that action
** which is to be put in the action table of the generated machine.
** Return negative if no action should be generated.
*/
PRIVATE int compute_action(struct lemon *lemp, struct action *ap)
{
  int act;
  switch( ap->type ){
    case SHIFT:  act = ap->x.stp->statenum;                        break;
    case SHIFTREDUCE: {
      /* Since a SHIFT is inherient after a prior REDUCE, convert any
      ** SHIFTREDUCE action with a nonterminal on the LHS into a simple
      ** REDUCE action: */
      if( ap->sp->index>=lemp->nterminal ){
      if( ap->sp->index>=lemp->nterminal
       && (lemp->errsym==0 || ap->sp->index!=lemp->errsym->index)
      ){
        act = lemp->minReduce + ap->x.rp->iRule;
      }else{
        act = lemp->minShiftReduce + ap->x.rp->iRule;
      }
      break;
    }
    case REDUCE: act = lemp->minReduce + ap->x.rp->iRule;          break;
3485
3486
3487
3488
3489
3490
3491










3492
3493
3494
3495
3496
3497
3498
3499
3500

3501
3502
3503
3504
3505
3506
3507
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







+
+
+
+
+
+
+
+
+
+









+







          iStart = i+1;
        }
      }
    }
    fprintf(out,"%s",&line[iStart]);
  }
}

/* Skip forward past the header of the template file to the first "%%"
*/
PRIVATE void tplt_skip_header(FILE *in, int *lineno)
{
  char line[LINESIZE];
  while( fgets(line,LINESIZE,in) && (line[0]!='%' || line[1]!='%') ){
    (*lineno)++;
  }
}

/* The next function finds the template file and opens it, returning
** a pointer to the opened file. */
PRIVATE FILE *tplt_open(struct lemon *lemp)
{
  static char templatename[] = "lempar.c";
  char buf[1000];
  FILE *in;
  char *tpltname;
  char *toFree = 0;
  char *cp;

  /* first, see if user specified a template filename on the command line. */
  if (user_templatename != 0) {
    if( access(user_templatename,004)==-1 ){
      fprintf(stderr,"Can't find the parser driver template file \"%s\".\n",
        user_templatename);
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
3670
3671
3672
3673
3674
3675
3676

3677
3678
3679
3680
3681
3682
3683
3684
3685
3686

3687
3688

3689
3690
3691
3692
3693
3694
3695
3696
3697







-
+









-
+

-

+







    lemon_sprintf(buf,"%s.lt",lemp->filename);
  }
  if( access(buf,004)==0 ){
    tpltname = buf;
  }else if( access(templatename,004)==0 ){
    tpltname = templatename;
  }else{
    tpltname = pathsearch(lemp->argv0,templatename,0);
    toFree = tpltname = pathsearch(lemp->argv0,templatename,0);
  }
  if( tpltname==0 ){
    fprintf(stderr,"Can't find the parser driver template file \"%s\".\n",
    templatename);
    lemp->errorcnt++;
    return 0;
  }
  in = fopen(tpltname,"rb");
  if( in==0 ){
    fprintf(stderr,"Can't open the template file \"%s\".\n",templatename);
    fprintf(stderr,"Can't open the template file \"%s\".\n",tpltname);
    lemp->errorcnt++;
    return 0;
  }
  free(toFree);
  return in;
}

/* Print a #line directive line to the output file. */
PRIVATE void tplt_linedir(FILE *out, int lineno, char *filename)
{
  fprintf(out,"#line %d \"",lineno);
3724
3725
3726
3727
3728
3729
3730
3731

3732
3733
3734
3735
3736
3737
3738
3869
3870
3871
3872
3873
3874
3875

3876
3877
3878
3879
3880
3881
3882
3883







-
+









  if( rp->nrhs==0 ){
    /* If there are no RHS symbols, then writing directly to the LHS is ok */
    lhsdirect = 1;
  }else if( rp->rhsalias[0]==0 ){
    /* The left-most RHS symbol has no value.  LHS direct is ok.  But
    ** we have to call the distructor on the RHS symbol first. */
    ** we have to call the destructor on the RHS symbol first. */
    lhsdirect = 1;
    if( has_destructor(rp->rhs[0],lemp) ){
      append_str(0,0,0,0);
      append_str("  yy_destructor(yypParser,%d,&yymsp[%d].minor);\n", 0,
                 rp->rhs[0]->index,1-rp->nrhs);
      rp->codePrefix = Strsafe(append_str(0,0,0,0));
      rp->noCode = 0;
3844
3845
3846
3847
3848
3849
3850
3851

3852
3853
3854
3855
3856
3857
3858
3989
3990
3991
3992
3993
3994
3995

3996
3997
3998
3999
4000
4001
4002
4003







-
+







    if( rp->rhsalias[i] ){
      if( i>0 ){
        int j;
        if( rp->lhsalias && strcmp(rp->lhsalias,rp->rhsalias[i])==0 ){
          ErrorMsg(lemp->filename,rp->ruleline,
            "%s(%s) has the same label as the LHS but is not the left-most "
            "symbol on the RHS.",
            rp->rhs[i]->name, rp->rhsalias);
            rp->rhs[i]->name, rp->rhsalias[i]);
          lemp->errorcnt++;
        }
        for(j=0; j<i; j++){
          if( rp->rhsalias[j] && strcmp(rp->rhsalias[j],rp->rhsalias[i])==0 ){
            ErrorMsg(lemp->filename,rp->ruleline,
              "Label %s used for multiple symbols on the RHS of a rule.",
              rp->rhsalias[i]);
3946
3947
3948
3949
3950
3951
3952
3953

3954
3955
3956
3957
3958
3959
3960
4091
4092
4093
4094
4095
4096
4097

4098
4099
4100
4101
4102
4103
4104
4105







-
+







*/
void print_stack_union(
  FILE *out,                  /* The output stream */
  struct lemon *lemp,         /* The main info structure for this parser */
  int *plineno,               /* Pointer to the line number */
  int mhflag                  /* True if generating makeheaders output */
){
  int lineno = *plineno;    /* The line number of the output */
  int lineno;               /* The line number of the output */
  char **types;             /* A hash table of datatypes */
  int arraysize;            /* Size of the "types" array */
  int maxdtlength;          /* Maximum length of any ".datatype" field. */
  char *stddt;              /* Standardized name for a datatype */
  int i,j;                  /* Loop counters */
  unsigned hash;            /* For hashing the name of a type */
  const char *name;         /* Name of the parser */
4138
4139
4140
4141
4142
4143
4144
4145


4146
4147

4148
4149
4150
4151
4152
4153
4154

4155
4156
4157
4158
4159
4160

4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175








































































4176


















4177


4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188


4189
4190
4191
4192
4193
4194
4195
4196
4197
4198








4199
4200
4201
4202
4203
4204
4205
4206
4283
4284
4285
4286
4287
4288
4289

4290
4291
4292

4293

4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
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
4360
4361
4362
4363
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
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413

4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429

4430







4431
4432
4433
4434
4435
4436
4437
4438

4439
4440
4441
4442
4443
4444
4445







-
+
+

-
+
-






+






+















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+











+
+

-

-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-







  }
}


/* Generate C source code for the parser */
void ReportTable(
  struct lemon *lemp,
  int mhflag     /* Output in makeheaders format if true */
  int mhflag,     /* Output in makeheaders format if true */
  int sqlFlag     /* Generate the *.sql file too */
){
  FILE *out, *in;
  FILE *out, *in, *sql;
  char line[LINESIZE];
  int  lineno;
  struct state *stp;
  struct action *ap;
  struct rule *rp;
  struct acttab *pActtab;
  int i, j, n, sz;
  int nLookAhead;
  int szActionType;     /* sizeof(YYACTIONTYPE) */
  int szCodeType;       /* sizeof(YYCODETYPE)   */
  const char *name;
  int mnTknOfst, mxTknOfst;
  int mnNtOfst, mxNtOfst;
  struct axset *ax;
  char *prefix;

  lemp->minShiftReduce = lemp->nstate;
  lemp->errAction = lemp->minShiftReduce + lemp->nrule;
  lemp->accAction = lemp->errAction + 1;
  lemp->noAction = lemp->accAction + 1;
  lemp->minReduce = lemp->noAction + 1;
  lemp->maxAction = lemp->minReduce + lemp->nrule;

  in = tplt_open(lemp);
  if( in==0 ) return;
  out = file_open(lemp,".c","wb");
  if( out==0 ){
    fclose(in);
    return;
  }
  if( sqlFlag==0 ){
    sql = 0;
  }else{
    sql = file_open(lemp, ".sql", "wb");
    if( sql==0 ){
      fclose(in);
      fclose(out);
      return;
    }
    fprintf(sql,
       "BEGIN;\n"
       "CREATE TABLE symbol(\n"
       "  id INTEGER PRIMARY KEY,\n"
       "  name TEXT NOT NULL,\n"
       "  isTerminal BOOLEAN NOT NULL,\n"
       "  fallback INTEGER REFERENCES symbol"
               " DEFERRABLE INITIALLY DEFERRED\n"
       ");\n"
    );
    for(i=0; i<lemp->nsymbol; i++){
      fprintf(sql,
         "INSERT INTO symbol(id,name,isTerminal,fallback)"
         "VALUES(%d,'%s',%s",
         i, lemp->symbols[i]->name,
         i<lemp->nterminal ? "TRUE" : "FALSE"
      );
      if( lemp->symbols[i]->fallback ){
        fprintf(sql, ",%d);\n", lemp->symbols[i]->fallback->index);
      }else{
        fprintf(sql, ",NULL);\n");
      }
    }
    fprintf(sql,
      "CREATE TABLE rule(\n"
      "  ruleid INTEGER PRIMARY KEY,\n"
      "  lhs INTEGER REFERENCES symbol(id),\n"
      "  txt TEXT\n"
      ");\n"
      "CREATE TABLE rulerhs(\n"
      "  ruleid INTEGER REFERENCES rule(ruleid),\n"
      "  pos INTEGER,\n"
      "  sym INTEGER REFERENCES symbol(id)\n"
      ");\n"
    );
    for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
      assert( i==rp->iRule );
      fprintf(sql,
        "INSERT INTO rule(ruleid,lhs,txt)VALUES(%d,%d,'",
        rp->iRule, rp->lhs->index
      );
      writeRuleText(sql, rp);
      fprintf(sql,"');\n");
      for(j=0; j<rp->nrhs; j++){
        struct symbol *sp = rp->rhs[j];
        if( sp->type!=MULTITERMINAL ){
          fprintf(sql,
            "INSERT INTO rulerhs(ruleid,pos,sym)VALUES(%d,%d,%d);\n",
            i,j,sp->index
          );
        }else{
          int k;
          for(k=0; k<sp->nsubsym; k++){
            fprintf(sql,
              "INSERT INTO rulerhs(ruleid,pos,sym)VALUES(%d,%d,%d);\n",
              i,j,sp->subsym[k]->index
            );
          }
        }
      }
    }
    fprintf(sql, "COMMIT;\n");
  }
  lineno = 1;

  fprintf(out, 
     "/* This file is automatically generated by Lemon from input grammar\n"
     "** source file \"%s\". */\n", lemp->filename); lineno += 2;
  
  /* The first %include directive begins with a C-language comment,
  ** then skip over the header comment of the template file
  */
  if( lemp->include==0 ) lemp->include = "";
  for(i=0; ISSPACE(lemp->include[i]); i++){
    if( lemp->include[i]=='\n' ){
      lemp->include += i+1;
      i = -1;
    }
  }
  if( lemp->include[0]=='/' ){
    tplt_skip_header(in,&lineno);
  }else{
  tplt_xfer(lemp->name,in,out,&lineno);
    tplt_xfer(lemp->name,in,out,&lineno);
  }

  /* Generate the include code, if any */
  tplt_print(out,lemp,lemp->include,&lineno);
  if( mhflag ){
    char *incName = file_makename(lemp, ".h");
    fprintf(out,"#include \"%s\"\n", incName); lineno++;
    free(incName);
  }
  tplt_xfer(lemp->name,in,out,&lineno);

  /* Generate #defines for all tokens */
  if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
  else                    prefix = "";
  if( mhflag ){
    const char *prefix;
    fprintf(out,"#if INTERFACE\n"); lineno++;
    if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
    else                    prefix = "";
    for(i=1; i<lemp->nterminal; i++){
      fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
      lineno++;
    }
    fprintf(out,"#endif\n"); lineno++;
  }else{
    fprintf(out,"#ifndef %s%s\n", prefix, lemp->symbols[1]->name);
  }
  for(i=1; i<lemp->nterminal; i++){
    fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
    lineno++;
  }
  fprintf(out,"#endif\n"); lineno++;
  }
  tplt_xfer(lemp->name,in,out,&lineno);

  /* Generate the defines */
  fprintf(out,"#define YYCODETYPE %s\n",
    minimum_size_type(0, lemp->nsymbol, &szCodeType)); lineno++;
  fprintf(out,"#define YYNOCODE %d\n",lemp->nsymbol);  lineno++;
  fprintf(out,"#define YYACTIONTYPE %s\n",
4344
4345
4346
4347
4348
4349
4350


4351
4352
4353
4354
4355
4356
4357
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598







+
+







    }
  }

  /* Finish rendering the constants now that the action table has
  ** been computed */
  fprintf(out,"#define YYNSTATE             %d\n",lemp->nxstate);  lineno++;
  fprintf(out,"#define YYNRULE              %d\n",lemp->nrule);  lineno++;
  fprintf(out,"#define YYNRULE_WITH_ACTION  %d\n",lemp->nruleWithAction);
         lineno++;
  fprintf(out,"#define YYNTOKEN             %d\n",lemp->nterminal); lineno++;
  fprintf(out,"#define YY_MAX_SHIFT         %d\n",lemp->nxstate-1); lineno++;
  i = lemp->minShiftReduce;
  fprintf(out,"#define YY_MIN_SHIFTREDUCE   %d\n",i); lineno++;
  i += lemp->nrule;
  fprintf(out,"#define YY_MAX_SHIFTREDUCE   %d\n", i-1); lineno++;
  fprintf(out,"#define YY_ERROR_ACTION      %d\n", lemp->errAction); lineno++;
4398
4399
4400
4401
4402
4403
4404
4405















4406
4407
4408
4409
4410

4411

4412
4413
4414
4415
4416
4417
4418
4639
4640
4641
4642
4643
4644
4645

4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675







-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





+

+







  lemp->tablesize += n*szCodeType;
  fprintf(out,"static const YYCODETYPE yy_lookahead[] = {\n"); lineno++;
  for(i=j=0; i<n; i++){
    int la = acttab_yylookahead(pActtab, i);
    if( la<0 ) la = lemp->nsymbol;
    if( j==0 ) fprintf(out," /* %5d */ ", i);
    fprintf(out, " %4d,", la);
    if( j==9 || i==n-1 ){
    if( j==9 ){
      fprintf(out, "\n"); lineno++;
      j = 0;
    }else{
      j++;
    }
  }
  /* Add extra entries to the end of the yy_lookahead[] table so that
  ** yy_shift_ofst[]+iToken will always be a valid index into the array,
  ** even for the largest possible value of yy_shift_ofst[] and iToken. */
  nLookAhead = lemp->nterminal + lemp->nactiontab;
  while( i<nLookAhead ){
    if( j==0 ) fprintf(out," /* %5d */ ", i);
    fprintf(out, " %4d,", lemp->nterminal);
    if( j==9 ){
      fprintf(out, "\n"); lineno++;
      j = 0;
    }else{
      j++;
    }
    i++;
  }
  if( j>0 ){ fprintf(out, "\n"); lineno++; }
  fprintf(out, "};\n"); lineno++;

  /* Output the yy_shift_ofst[] table */
  n = lemp->nxstate;
  while( n>0 && lemp->sorted[n-1]->iTknOfst==NO_OFFSET ) n--;
  fprintf(out, "#define YY_SHIFT_COUNT    (%d)\n", n-1); lineno++;
  fprintf(out, "#define YY_SHIFT_MIN      (%d)\n", mnTknOfst); lineno++;
4484
4485
4486
4487
4488
4489
4490


4491

4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4741
4742
4743
4744
4745
4746
4747
4748
4749

4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767

4768
4769
4770
4771
4772
4773
4774







+
+
-
+

















-







  fprintf(out, "};\n"); lineno++;
  tplt_xfer(lemp->name,in,out,&lineno);

  /* Generate the table of fallback tokens.
  */
  if( lemp->has_fallback ){
    int mx = lemp->nterminal - 1;
    /* 2019-08-28:  Generate fallback entries for every token to avoid
    ** having to do a range check on the index */
    while( mx>0 && lemp->symbols[mx]->fallback==0 ){ mx--; }
    /* while( mx>0 && lemp->symbols[mx]->fallback==0 ){ mx--; } */
    lemp->tablesize += (mx+1)*szCodeType;
    for(i=0; i<=mx; i++){
      struct symbol *p = lemp->symbols[i];
      if( p->fallback==0 ){
        fprintf(out, "    0,  /* %10s => nothing */\n", p->name);
      }else{
        fprintf(out, "  %3d,  /* %10s => %s */\n", p->fallback->index,
          p->name, p->fallback->name);
      }
      lineno++;
    }
  }
  tplt_xfer(lemp->name, in, out, &lineno);

  /* Generate a table containing the symbolic name of every symbol
  */
  for(i=0; i<lemp->nsymbol; i++){
    lemon_sprintf(line,"\"%s\",",lemp->symbols[i]->name);
    fprintf(out,"  /* %4d */ \"%s\",\n",i, lemp->symbols[i]->name); lineno++;
  }
  tplt_xfer(lemp->name,in,out,&lineno);

  /* Generate a table containing a text string that describes every
  ** rule in the rule set of the grammar.  This information is used
  ** when tracing REDUCE actions.
4590
4591
4592
4593
4594
4595
4596
4597

4598
4599
4600
4601
4602
4603
4604
4848
4849
4850
4851
4852
4853
4854

4855
4856
4857
4858
4859
4860
4861
4862







-
+







  tplt_print(out,lemp,lemp->overflow,&lineno);
  tplt_xfer(lemp->name,in,out,&lineno);

  /* Generate the tables of rule information.  yyRuleInfoLhs[] and
  ** yyRuleInfoNRhs[].
  **
  ** Note: This code depends on the fact that rules are number
  ** sequentually beginning with 0.
  ** sequentially beginning with 0.
  */
  for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
    fprintf(out,"  %4d,  /* (%d) ", rp->lhs->index, i);
     rule_print(out, rp);
    fprintf(out," */\n"); lineno++;
  }
  tplt_xfer(lemp->name,in,out,&lineno);
4645
4646
4647
4648
4649
4650
4651



4652

4653
4654
4655
4656
4657
4658
4659
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912

4913
4914
4915
4916
4917
4918
4919
4920







+
+
+
-
+







  ** empty actions. */
  fprintf(out,"      default:\n"); lineno++;
  for(rp=lemp->rule; rp; rp=rp->next){
    if( rp->codeEmitted ) continue;
    assert( rp->noCode );
    fprintf(out,"      /* (%d) ", rp->iRule);
    writeRuleText(out, rp);
    if( rp->neverReduce ){
      fprintf(out, " (NEVER REDUCES) */ assert(yyruleno!=%d);\n",
              rp->iRule); lineno++;
    if( rp->doesReduce ){
    }else if( rp->doesReduce ){
      fprintf(out, " */ yytestcase(yyruleno==%d);\n", rp->iRule); lineno++;
    }else{
      fprintf(out, " (OPTIMIZED OUT) */ assert(yyruleno!=%d);\n",
              rp->iRule); lineno++;
    }
  }
  fprintf(out,"        break;\n"); lineno++;
4670
4671
4672
4673
4674
4675
4676

4677
4678

4679
4680
4681
4682
4683
4684
4685
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948







+


+







  /* Generate code which executes when the parser accepts its input */
  tplt_print(out,lemp,lemp->accept,&lineno);
  tplt_xfer(lemp->name,in,out,&lineno);

  /* Append any addition code the user desires */
  tplt_print(out,lemp,lemp->extracode,&lineno);

  acttab_free(pActtab);
  fclose(in);
  fclose(out);
  if( sql ) fclose(sql);
  return;
}

/* Generate a header file for the parser */
void ReportHeader(struct lemon *lemp)
{
  FILE *out, *in;
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
5177
5178
5179
5180
5181
5182
5183

5184
5185
5186
5187
5188
5189
5190







-







}

/* Allocate a new set */
char *SetNew(void){
  char *s;
  s = (char*)calloc( size, 1);
  if( s==0 ){
    extern void memory_error();
    memory_error();
  }
  return s;
}

/* Deallocate a set */
void SetFree(char *s)
5074
5075
5076
5077
5078
5079
5080
5081


5082
5083
5084
5085
5086
5087
5088
5336
5337
5338
5339
5340
5341
5342

5343
5344
5345
5346
5347
5348
5349
5350
5351







-
+
+







      newnp = &(array.tbl[i]);
      if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
      newnp->next = array.ht[h];
      newnp->data = oldnp->data;
      newnp->from = &(array.ht[h]);
      array.ht[h] = newnp;
    }
    free(x1a->tbl);
    /* free(x1a->tbl); // This program was originally for 16-bit machines.
    ** Don't worry about freeing memory on modern platforms. */
    *x1a = array;
  }
  /* Insert the new data */
  h = ph & (x1a->size-1);
  np = &(x1a->tbl[x1a->count++]);
  np->data = data;
  if( x1a->ht[h] ) x1a->ht[h]->from = &(np->next);
5242
5243
5244
5245
5246
5247
5248
5249



5250
5251
5252
5253
5254
5255
5256
5505
5506
5507
5508
5509
5510
5511

5512
5513
5514
5515
5516
5517
5518
5519
5520
5521







-
+
+
+







      if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
      newnp->next = array.ht[h];
      newnp->key = oldnp->key;
      newnp->data = oldnp->data;
      newnp->from = &(array.ht[h]);
      array.ht[h] = newnp;
    }
    free(x2a->tbl);
    /* free(x2a->tbl); // This program was originally written for 16-bit
    ** machines.  Don't worry about freeing this trivial amount of memory
    ** on modern platforms.  Just leak it. */
    *x2a = array;
  }
  /* Insert the new data */
  h = ph & (x2a->size-1);
  np = &(x2a->tbl[x2a->count++]);
  np->key = key;
  np->data = data;
5578
5579
5580
5581
5582
5583
5584
5585



5586
5587
5588
5589
5590
5591
5592
5843
5844
5845
5846
5847
5848
5849

5850
5851
5852
5853
5854
5855
5856
5857
5858
5859







-
+
+
+







      newnp = &(array.tbl[i]);
      if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
      newnp->next = array.ht[h];
      newnp->data = oldnp->data;
      newnp->from = &(array.ht[h]);
      array.ht[h] = newnp;
    }
    free(x4a->tbl);
    /* free(x4a->tbl); // This code was originall written for 16-bit machines.
    ** on modern machines, don't worry about freeing this trival amount of
    ** memory. */
    *x4a = array;
  }
  /* Insert the new data */
  h = ph & (x4a->size-1);
  np = &(x4a->tbl[x4a->count++]);
  np->data = data;
  if( x4a->ht[h] ) x4a->ht[h]->from = &(np->next);

Changes to tool/lempar.c.

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
18
19
20
21
22
23
24


25
26
27

28



29
30

31
32
33
34
35
36
37
38







-
-



-
+
-
-
-
+

-
+







** the value of the %name directive from the grammar.  Otherwise, the content
** of this template is copied straight through into the generate parser
** source file.
**
** The following is the concatenation of all %include directives from the
** input grammar file:
*/
#include <stdio.h>
#include <assert.h>
/************ Begin %include sections from the grammar ************************/
%%
/**************** End of %include directives **********************************/
/* These constants specify the various numeric values for terminal symbols
/* These constants specify the various numeric values for terminal symbols.
** in a format understandable to "makeheaders".  This section is blank unless
** "lemon" is run with the "-m" command-line option.
***************** Begin makeheaders token definitions *************************/
***************** Begin token definitions *************************************/
%%
/**************** End makeheaders token definitions ***************************/
/**************** End token definitions ***************************************/

/* The next sections is a series of control #defines.
** various aspects of the generated parser.
**    YYCODETYPE         is the data type used to store the integer codes
**                       that represent terminal and non-terminal symbols.
**                       "unsigned char" is used if there are fewer than
**                       256 symbols.  Larger types otherwise.
223
224
225
226
227
228
229

230
231
232
233
234
235
236
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233







+







#else
  yyStackEntry yystack[YYSTACKDEPTH];  /* The parser's stack */
  yyStackEntry *yystackEnd;            /* Last entry in the stack */
#endif
};
typedef struct yyParser yyParser;

#include <assert.h>
#ifndef NDEBUG
#include <stdio.h>
static FILE *yyTraceFILE = 0;
static char *yyTracePrompt = 0;
#endif /* NDEBUG */

#ifndef NDEBUG
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
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







+
-
+



+
-
+


-
-
+
+
+














-
-
-
-
-
-
-
-
-
+
+
-













+







  assert( stateno <= YY_SHIFT_COUNT );
#if defined(YYCOVERAGE)
  yycoverage[stateno][iLookAhead] = 1;
#endif
  do{
    i = yy_shift_ofst[stateno];
    assert( i>=0 );
    assert( i<=YY_ACTTAB_COUNT );
    /* assert( i+YYNTOKEN<=(int)YY_NLOOKAHEAD ); */
    assert( i+YYNTOKEN<=(int)YY_NLOOKAHEAD );
    assert( iLookAhead!=YYNOCODE );
    assert( iLookAhead < YYNTOKEN );
    i += iLookAhead;
    assert( i<(int)YY_NLOOKAHEAD );
    if( i>=YY_NLOOKAHEAD || yy_lookahead[i]!=iLookAhead ){
    if( yy_lookahead[i]!=iLookAhead ){
#ifdef YYFALLBACK
      YYCODETYPE iFallback;            /* Fallback token */
      if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
             && (iFallback = yyFallback[iLookAhead])!=0 ){
      assert( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0]) );
      iFallback = yyFallback[iLookAhead];
      if( iFallback!=0 ){
#ifndef NDEBUG
        if( yyTraceFILE ){
          fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
             yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
        }
#endif
        assert( yyFallback[iFallback]==0 ); /* Fallback loop must terminate */
        iLookAhead = iFallback;
        continue;
      }
#endif
#ifdef YYWILDCARD
      {
        int j = i - iLookAhead + YYWILDCARD;
        if( 
#if YY_SHIFT_MIN+YYWILDCARD<0
          j>=0 &&
#endif
#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT
          j<YY_ACTTAB_COUNT &&
#endif
          j<(int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])) &&
          yy_lookahead[j]==YYWILDCARD && iLookAhead>0
        assert( j<(int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])) );
        if( yy_lookahead[j]==YYWILDCARD && iLookAhead>0 ){
        ){
#ifndef NDEBUG
          if( yyTraceFILE ){
            fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n",
               yyTracePrompt, yyTokenName[iLookAhead],
               yyTokenName[YYWILDCARD]);
          }
#endif /* NDEBUG */
          return yy_action[j];
        }
      }
#endif /* YYWILDCARD */
      return yy_default[stateno];
    }else{
      assert( i>=0 && i<(int)(sizeof(yy_action)/sizeof(yy_action[0])) );
      return yy_action[i];
    }
  }while(1);
}

/*
** Find the appropriate action for a parser given the non-terminal
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
775
776
777
778
779
714
715
716
717
718
719
720













































721
722
723
724
725
726
727







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







  YYACTIONTYPE yyact;             /* The next action */
  yyStackEntry *yymsp;            /* The top of the parser's stack */
  int yysize;                     /* Amount to pop the stack */
  ParseARG_FETCH
  (void)yyLookahead;
  (void)yyLookaheadToken;
  yymsp = yypParser->yytos;
#ifndef NDEBUG
  if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
    yysize = yyRuleInfoNRhs[yyruleno];
    if( yysize ){
      fprintf(yyTraceFILE, "%sReduce %d [%s], go to state %d.\n",
        yyTracePrompt,
        yyruleno, yyRuleName[yyruleno], yymsp[yysize].stateno);
    }else{
      fprintf(yyTraceFILE, "%sReduce %d [%s].\n",
        yyTracePrompt, yyruleno, yyRuleName[yyruleno]);
    }
  }
#endif /* NDEBUG */

  /* Check that the stack is large enough to grow by a single entry
  ** if the RHS of the rule is empty.  This ensures that there is room
  ** enough on the stack to push the LHS value */
  if( yyRuleInfoNRhs[yyruleno]==0 ){
#ifdef YYTRACKMAXSTACKDEPTH
    if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){
      yypParser->yyhwm++;
      assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack));
    }
#endif
#if YYSTACKDEPTH>0 
    if( yypParser->yytos>=yypParser->yystackEnd ){
      yyStackOverflow(yypParser);
      /* The call to yyStackOverflow() above pops the stack until it is
      ** empty, causing the main parser loop to exit.  So the return value
      ** is never used and does not matter. */
      return 0;
    }
#else
    if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz-1] ){
      if( yyGrowStack(yypParser) ){
        yyStackOverflow(yypParser);
        /* The call to yyStackOverflow() above pops the stack until it is
        ** empty, causing the main parser loop to exit.  So the return value
        ** is never used and does not matter. */
        return 0;
      }
      yymsp = yypParser->yytos;
    }
#endif
  }

  switch( yyruleno ){
  /* Beginning here are the reduction cases.  A typical example
  ** follows:
  **   case 0:
  **  #line <lineno> <grammarfile>
  **     { ... }           // User supplied code
924
925
926
927
928
929
930
931


932
933
934


















935
936



























937
938
939
940
941
942
943
872
873
874
875
876
877
878

879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901


902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935







-
+
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    }else{
      fprintf(yyTraceFILE,"%sInput '%s' with pending reduce %d\n",
              yyTracePrompt,yyTokenName[yymajor],yyact-YY_MIN_REDUCE);
    }
  }
#endif

  do{
  while(1){ /* Exit by "break" */
    assert( yypParser->yytos>=yypParser->yystack );
    assert( yyact==yypParser->yytos->stateno );
    yyact = yy_find_shift_action((YYCODETYPE)yymajor,yyact);
    if( yyact >= YY_MIN_REDUCE ){
      unsigned int yyruleno = yyact - YY_MIN_REDUCE; /* Reduce by this rule */
#ifndef NDEBUG
      assert( yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) );
      if( yyTraceFILE ){
        int yysize = yyRuleInfoNRhs[yyruleno];
        if( yysize ){
          fprintf(yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n",
            yyTracePrompt,
            yyruleno, yyRuleName[yyruleno],
            yyruleno<YYNRULE_WITH_ACTION ? "" : " without external action",
            yypParser->yytos[yysize].stateno);
        }else{
          fprintf(yyTraceFILE, "%sReduce %d [%s]%s.\n",
            yyTracePrompt, yyruleno, yyRuleName[yyruleno],
            yyruleno<YYNRULE_WITH_ACTION ? "" : " without external action");
        }
      }
#endif /* NDEBUG */
      yyact = yy_reduce(yypParser,yyact-YY_MIN_REDUCE,yymajor,
                        yyminor ParseCTX_PARAM);

      /* Check that the stack is large enough to grow by a single entry
      ** if the RHS of the rule is empty.  This ensures that there is room
      ** enough on the stack to push the LHS value */
      if( yyRuleInfoNRhs[yyruleno]==0 ){
#ifdef YYTRACKMAXSTACKDEPTH
        if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){
          yypParser->yyhwm++;
          assert( yypParser->yyhwm ==
                  (int)(yypParser->yytos - yypParser->yystack));
        }
#endif
#if YYSTACKDEPTH>0 
        if( yypParser->yytos>=yypParser->yystackEnd ){
          yyStackOverflow(yypParser);
          break;
        }
#else
        if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz-1] ){
          if( yyGrowStack(yypParser) ){
            yyStackOverflow(yypParser);
            break;
          }
        }
#endif
      }
      yyact = yy_reduce(yypParser,yyruleno,yymajor,yyminor ParseCTX_PARAM);
    }else if( yyact <= YY_MAX_SHIFTREDUCE ){
      yy_shift(yypParser,yyact,(YYCODETYPE)yymajor,yyminor);
#ifndef YYNOERRORRECOVERY
      yypParser->yyerrcnt--;
#endif
      break;
    }else if( yyact==YY_ACCEPT_ACTION ){
985
986
987
988
989
990
991
992
993


994
995

996

997
998
999

1000
1001
1002
1003
1004
1005
1006
977
978
979
980
981
982
983


984
985


986

987
988
989

990
991
992
993
994
995
996
997







-
-
+
+
-
-
+
-
+


-
+







          fprintf(yyTraceFILE,"%sDiscard input token %s\n",
             yyTracePrompt,yyTokenName[yymajor]);
        }
#endif
        yy_destructor(yypParser, (YYCODETYPE)yymajor, &yyminorunion);
        yymajor = YYNOCODE;
      }else{
        while( yypParser->yytos >= yypParser->yystack
            && (yyact = yy_find_reduce_action(
        while( yypParser->yytos > yypParser->yystack ){
          yyact = yy_find_reduce_action(yypParser->yytos->stateno,
                        yypParser->yytos->stateno,
                        YYERRORSYMBOL)) > YY_MAX_SHIFTREDUCE
                                        YYERRORSYMBOL);
        ){
          if( yyact<=YY_MAX_SHIFTREDUCE ) break;
          yy_pop_parser_stack(yypParser);
        }
        if( yypParser->yytos < yypParser->yystack || yymajor==0 ){
        if( yypParser->yytos <= yypParser->yystack || yymajor==0 ){
          yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
          yy_parse_failed(yypParser);
#ifndef YYNOERRORRECOVERY
          yypParser->yyerrcnt = -1;
#endif
          yymajor = YYNOCODE;
        }else if( yymx!=YYERRORSYMBOL ){
1042
1043
1044
1045
1046
1047
1048
1049

1050
1051
1052
1053
1054
1055
1056
1033
1034
1035
1036
1037
1038
1039

1040
1041
1042
1043
1044
1045
1046
1047







-
+







#ifndef YYNOERRORRECOVERY
        yypParser->yyerrcnt = -1;
#endif
      }
      break;
#endif
    }
  }while( yypParser->yytos>yypParser->yystack );
  }
#ifndef NDEBUG
  if( yyTraceFILE ){
    yyStackEntry *i;
    char cDiv = '[';
    fprintf(yyTraceFILE,"%sReturn. Stack=",yyTracePrompt);
    for(i=&yypParser->yystack[1]; i<=yypParser->yytos; i++){
      fprintf(yyTraceFILE,"%c%s", cDiv, yyTokenName[i->major]);
1064
1065
1066
1067
1068
1069
1070
1071
1072


1073
1074
1075
1076
1077

1078
1055
1056
1057
1058
1059
1060
1061


1062
1063

1064
1065

1066
1067
1068







-
-
+
+
-


-

+


/*
** Return the fallback token corresponding to canonical token iToken, or
** 0 if iToken has no fallback.
*/
int ParseFallback(int iToken){
#ifdef YYFALLBACK
  if( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) ){
    return yyFallback[iToken];
  assert( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) );
  return yyFallback[iToken];
  }
#else
  (void)iToken;
#endif
  return 0;
#endif
}

Changes to tool/logest.c.

71
72
73
74
75
76
77

78
79
80
81
82
83
84
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85







+







static sqlite3_uint64 logEstToInt(LogEst x){
  sqlite3_uint64 n;
  if( x<10 ) return 1;
  n = x%10;
  x /= 10;
  if( n>=5 ) n -= 2;
  else if( n>=1 ) n -= 1;
  if( x>60 ) return (((sqlite3_uint64)0xffffffff)<<32)+(sqlite3_uint64)0xffffffff;
  if( x>=3 ) return (n+8)<<(x-3);
  return (n+8)>>(3-x);
}
static LogEst logEstFromDouble(double x){
  sqlite3_uint64 a;
  LogEst e;
  assert( sizeof(x)==8 && sizeof(a)==8 );
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
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







-
+











+
+







    }else if( strcmp(z,"nlogn")==0 ){
      if( n>0 ) a[n-1] += logEstFromInteger(a[n-1]) - 33;
    }else if( strcmp(z,"inv")==0 ){
      if( n>0 ) a[n-1] = -a[n-1];
    }else if( z[0]=='^' ){
      a[n++] = (LogEst)atoi(z+1);
    }else if( isInteger(z) ){
      a[n++] = logEstFromInteger(atoi(z));
      a[n++] = logEstFromInteger(atoll(z));
    }else if( isFloat(z) && z[0]!='-' ){
      a[n++] = logEstFromDouble(atof(z));
    }else{
      showHelp(argv[0]);
    }
  }
  for(i=n-1; i>=0; i--){
    if( a[i]<-40 ){
      printf("%5d (%f)\n", a[i], 1.0/(double)logEstToInt(-a[i]));
    }else if( a[i]<10 ){
      printf("%5d (%f)\n", a[i], logEstToInt(a[i]+100)/1024.0);
    }else if( a[i]>100 ){
      printf("%5d (%lld)\n", a[i], logEstToInt(a[i]));
    }else{
      sqlite3_uint64 x = logEstToInt(a[i]+100)*100/1024;
      printf("%5d (%lld.%02lld)\n", a[i], x/100, x%100);
    }
  }
  return 0;
}

Added tool/merge-test.tcl.




































































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
#!/usr/bin/tcl
#
# Run this script to test to see that the latest trunk changes can be
# merged into LTS branches without breaking anything.
#
# To Use:
#
#   *  Copy this script into a directory above the sqlite checkout
#   *  Run "fossil update trunk" and "fossil revert"
#   *  Run "tclsh ../merge-test.tcl"  (in other words run this script)
#
# Operation:
#
# This script changes to each LTS branch to be tested, merges the latest
# trunk changes into the branch (without committing them) and then
# runs "make test".  Any errors are stored in local files.
#
# Limitations:
#
# Some LTS branches are not synced directly from trunk but rather from
# other LTS branches.  These other branches cannot be tested because
# there is no good way to generate the intermediate merges.
#
###############################################################################

# Run a shell command contained in arguments.  Put the return code in
# global variable ::res and the output string in global variable ::result
#
proc safeexec {args} {
  global res result
  set res [catch "exec $args" result]
}

# Run the shell command contained in arguments.  Print an error and exit
# if anything goes wrong.
#
proc mustbeok {args} {
  global res result
  set res [catch "exec $args" result]
  if {$res} {
    puts "FAILED: $args"
    puts $result
    exit 1
  }
}

# Write $content into a file named $filename.  The file is overwritten if it
# already exist.  The file is create if it does not already exist.
#
proc writefile {filename content} {
  set fd [open $filename wb]
  puts $fd $content
  close $fd
}

# Run the merge-test
#
foreach {branch configopts} {
  begin-concurrent         {--enable-json1}
  begin-concurrent-pnu     {--enable-json1}
  wal2                     {--enable-all}
  reuse-schema             {--enable-all}
} {
  puts $branch
  set errorfile ${branch}-error.txt
  mustbeok fossil revert
  mustbeok fossil up $branch
  safeexec fossil merge trunk
  if {$res} {
    puts "   merge failed - see $errorfile"
    writefile $errorfile $result
  } else {
    puts "   merge ok"
    safeexec  ./configure --enable-debug {*}$configopts
    if {$res} {
      puts "   configure failed - see $errorfile"
      writefile $errorfile $result
    } else {
      puts "   configure ok"
      safeexec make fuzzcheck sqlite3 testfixture
      if {$res} {
        puts "   build failed - see $errorfile"
        writefile $errorfile $result
      } else {
        puts "   build ok"
        safeexec make test
        if {$res} {
          puts "   test failed - see $errorfile"
          writefile $errorfile $result
        } else {
          puts "   test ok"
        }
      }
    }
  }
}
mustbeok fossil revert
mustbeok fossil up trunk
puts "reset back to trunk"

Changes to tool/mkautoconfamal.sh.

1
2
3
4
5
6


7
8
9
10
11
12
13
1
2
3
4


5
6
7
8
9
10
11
12
13




-
-
+
+







#!/bin/sh
# This script is used to build the amalgamation autoconf package.
# It assumes the following:
#
#   1. The files "sqlite3.c", "sqlite3.h" and "sqlite3ext.h"
#      are available in the current directory.
#   1. The files "sqlite3.c", "sqlite3.h", "sqlite3ext.h", "shell.c",
#      and "sqlite3rc.h" are available in the current directory.
#
#   2. Variable $TOP is set to the full path of the root directory
#      of the SQLite source tree.
#
#   3. There is nothing of value in the ./mkpkg_tmp_dir directory.
#      This is important, as the script executes "rm -rf ./mkpkg_tmp_dir".
#
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







+







fi

rm -rf $TMPSPACE
cp -R $TOP/autoconf       $TMPSPACE
cp sqlite3.c              $TMPSPACE
cp sqlite3.h              $TMPSPACE
cp sqlite3ext.h           $TMPSPACE
cp sqlite3rc.h            $TMPSPACE
cp $TOP/sqlite3.1         $TMPSPACE
cp $TOP/sqlite3.pc.in     $TMPSPACE
cp shell.c                $TMPSPACE
cp $TOP/src/sqlite3.rc    $TMPSPACE
cp $TOP/tool/Replace.cs   $TMPSPACE

cat $TMPSPACE/configure.ac |

Changes to tool/mkctimec.tcl.

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
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

84
85
86
87

88
89
90
91
92
93
94
95
96
97
98
99
100
101

102
103
104
105
106
107
108
109
110
111
112

113
114
115
116
117
118
119
120
121
122
123
124
125
126
127

128
129
130
131
132




133
134
135
136
137
138
139
140
141
142
143
144
145



146
147
148
149
150
151
152
153
154
155
156
157



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179


180
181
182
183
184
185
186
187
188
189
190

191
192
193
194

195
196
197
198
199
200
201
202
203
204
205
206

207
208
209
210
211
212



213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233






-
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+

-
+
+
+
+
+
+
+
+
+
+
+



-











-














+
-
+




-
-
-
-
+
+
+
+





+



-
-
-
+
+
+




+

+


-
-
-
+
+
+


+

+

+
+











-
-











-




-












-






-
-
-
+
+
+









+
+







#!/usr/bin/tclsh
#
# To build the
#
#   const char **azCompileOpt[]
#
# declaration used in src/ctime.c, run this script.
# definition used in src/ctime.c, run this script from
# the checkout root. It generates src/ctime.c .
#


set ::headWarning {/* DO NOT EDIT!
** This file is automatically generated by the script in the canonical
** SQLite source tree at tool/mkctimec.tcl.
**
** To modify this header, edit any of the various lists in that script
** which specify categories of generated conditionals in this file.
*/}

# Make { and } easier to put into literals (even on EBCDIC machines.)
regexp {(\{)(\})} "{}" ma ::lb ::rb

set ::headCode "
/*
** 2010 February 23
**
** 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 routines used to report what compile-time options
** SQLite was built with.
*/
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS /* IMP: R-16824-07538 */

/*
** Include the configuration header output by 'configure' if we're using the
** autoconf-based build
*/
#if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H)
#include \"sqlite_cfg.h\"
#define SQLITECONFIG_H 1
#endif

/* These macros are provided to \"stringify\" the value of the define
** for those options in which the value is meaningful. */
#define CTIMEOPT_VAL_(opt) #opt
#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)

/* Like CTIMEOPT_VAL, but especially for SQLITE_DEFAULT_LOOKASIDE. This
** option requires a separate macro because legal values contain a single
** comma. e.g. (-DSQLITE_DEFAULT_LOOKASIDE=\"100,100\") */
#define CTIMEOPT_VAL2_(opt1,opt2) #opt1 \",\" #opt2
#define CTIMEOPT_VAL2(opt) CTIMEOPT_VAL2_(opt)
#include \"sqliteInt.h\"

/*
** An array of names of all compile-time options.  This array should 
** be sorted A-Z.
**
** This array looks large, but in a typical installation actually uses
** only a handful of compile-time options, so most times this array is usually
** rather short and uses little memory space.
*/
static const char * const sqlite3azCompileOpt\[\] = $::lb
"

set ::tailCode "
$::rb ;

const char **sqlite3CompileOptions(int *pnOpt){
  *pnOpt = sizeof(sqlite3azCompileOpt) / sizeof(sqlite3azCompileOpt\[0\]);
  return (const char**)sqlite3azCompileOpt;
}

#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
"

# All Boolean compile time options.
# All Boolean compile time options which default to something
# other than 0 or empty. The default is paired with the PP
# symbol so that a differing define can be detected.
#
set boolean_options {
set boolean_defnnz_options {
  {SQLITE_HOMEGROWN_RECURSIVE_MUTEX 1}
  {SQLITE_POWERSAFE_OVERWRITE 1}
  {SQLITE_DEFAULT_MEMSTATUS 1}
  {SQLITE_OMIT_TRACE 1}
  {SQLITE_ALLOW_COVERING_INDEX_SCAN 1}
}

# All Boolean compile time options which default to 0 or empty.
#
set boolean_defnil_options {
  SQLITE_32BIT_ROWID
  SQLITE_4_BYTE_ALIGNED_MALLOC
  SQLITE_64BIT_STATS
  SQLITE_ALLOW_COVERING_INDEX_SCAN
  SQLITE_ALLOW_URI_AUTHORITY
  SQLITE_BUG_COMPATIBLE_20160819
  SQLITE_CASE_SENSITIVE_LIKE
  SQLITE_CHECK_PAGES
  SQLITE_COVERAGE_TEST
  SQLITE_DEBUG
  SQLITE_DEFAULT_AUTOMATIC_INDEX
  SQLITE_DEFAULT_AUTOVACUUM
  SQLITE_DEFAULT_CKPTFULLFSYNC
  SQLITE_DEFAULT_FOREIGN_KEYS
  SQLITE_DEFAULT_LOCKING_MODE
  SQLITE_DEFAULT_MEMSTATUS
  SQLITE_DEFAULT_RECURSIVE_TRIGGERS
  SQLITE_DEFAULT_SYNCHRONOUS
  SQLITE_DEFAULT_WAL_SYNCHRONOUS
  SQLITE_DIRECT_OVERFLOW_READ
  SQLITE_DISABLE_DIRSYNC
  SQLITE_DISABLE_FTS3_UNICODE
  SQLITE_DISABLE_FTS4_DEFERRED
  SQLITE_DISABLE_INTRINSIC
  SQLITE_DISABLE_LFS
  SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
  SQLITE_DISABLE_SKIPAHEAD_DISTINCT
  SQLITE_ENABLE_8_3_NAMES
  SQLITE_ENABLE_API_ARMOR
  SQLITE_ENABLE_ATOMIC_WRITE
  SQLITE_ENABLE_BATCH_ATOMIC_WRITE
  SQLITE_ENABLE_CEROD
  SQLITE_ENABLE_BYTECODE_VTAB
  SQLITE_ENABLE_COLUMN_METADATA
  SQLITE_ENABLE_COLUMN_USED_MASK
  SQLITE_ENABLE_COSTMULT
  SQLITE_ENABLE_CURSOR_HINTS
  SQLITE_ENABLE_DBSTAT_VTAB
  SQLITE_ENABLE_EXPENSIVE_ASSERT
  SQLITE_ENABLE_FTS1
  SQLITE_ENABLE_FTS2
  SQLITE_ENABLE_DBPAGE_VTAB
  SQLITE_ENABLE_DBSTAT_VTAB
  SQLITE_ENABLE_EXPENSIVE_ASSERT
  SQLITE_ENABLE_EXPLAIN_COMMENTS
  SQLITE_ENABLE_FTS3
  SQLITE_ENABLE_FTS3_PARENTHESIS
  SQLITE_ENABLE_FTS3_TOKENIZER
  SQLITE_ENABLE_FTS4
  SQLITE_ENABLE_FTS5
  SQLITE_ENABLE_GEOPOLY
  SQLITE_ENABLE_HIDDEN_COLUMNS
  SQLITE_ENABLE_ICU
  SQLITE_ENABLE_IOTRACE
  SQLITE_ENABLE_JSON1
  SQLITE_ENABLE_LOAD_EXTENSION
  SQLITE_ENABLE_LOCKING_STYLE
  SQLITE_ENABLE_LOAD_EXTENSION
  SQLITE_ENABLE_LOCKING_STYLE
  SQLITE_ENABLE_MATH_FUNCTIONS
  SQLITE_ENABLE_MEMORY_MANAGEMENT
  SQLITE_ENABLE_MEMSYS3
  SQLITE_ENABLE_MEMSYS5
  SQLITE_ENABLE_MULTIPLEX
  SQLITE_ENABLE_NORMALIZE
  SQLITE_ENABLE_NULL_TRIM
  SQLITE_ENABLE_OFFSET_SQL_FUNC
  SQLITE_ENABLE_OVERSIZE_CELL_CHECK
  SQLITE_ENABLE_PREUPDATE_HOOK
  SQLITE_ENABLE_RBU
  SQLITE_ENABLE_RTREE
  SQLITE_ENABLE_SELECTTRACE
  SQLITE_ENABLE_QPSG
  SQLITE_ENABLE_RBU
  SQLITE_ENABLE_RTREE
  SQLITE_ENABLE_SESSION
  SQLITE_ENABLE_SNAPSHOT
  SQLITE_ENABLE_SORTER_REFERENCES
  SQLITE_ENABLE_SQLLOG
  SQLITE_ENABLE_STAT4
  SQLITE_ENABLE_STMT_SCANSTATUS
  SQLITE_ENABLE_STMTVTAB
  SQLITE_ENABLE_TREETRACE
  SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
  SQLITE_ENABLE_UNLOCK_NOTIFY
  SQLITE_ENABLE_UPDATE_DELETE_LIMIT
  SQLITE_ENABLE_URI_00_ERROR
  SQLITE_ENABLE_VFSTRACE
  SQLITE_ENABLE_WHERETRACE
  SQLITE_ENABLE_ZIPVFS
  SQLITE_EXPLAIN_ESTIMATED_ROWS
  SQLITE_EXTRA_IFNULLROW
  SQLITE_FTS5_ENABLE_TEST_MI
  SQLITE_FTS5_NO_WITHOUT_ROWID
  SQLITE_HAS_CODEC
  SQLITE_HOMEGROWN_RECURSIVE_MUTEX
  SQLITE_IGNORE_AFP_LOCK_ERRORS
  SQLITE_IGNORE_FLOCK_LOCK_ERRORS
  SQLITE_INLINE_MEMCPY
  SQLITE_INT64_TYPE
  SQLITE_LIKE_DOESNT_MATCH_BLOBS
  SQLITE_LOCK_TRACE
  SQLITE_LOG_CACHE_SPILL
  SQLITE_MEMDEBUG
  SQLITE_MIXED_ENDIAN_64BIT_FLOAT
  SQLITE_MMAP_READWRITE
  SQLITE_MUTEX_NOOP
  SQLITE_MUTEX_NREF
  SQLITE_MUTEX_OMIT
  SQLITE_MUTEX_PTHREADS
  SQLITE_MUTEX_W32
  SQLITE_NEED_ERR_NAME
  SQLITE_NOINLINE
  SQLITE_NO_SYNC
  SQLITE_OMIT_ALTERTABLE
  SQLITE_OMIT_ANALYZE
  SQLITE_OMIT_ATTACH
  SQLITE_OMIT_AUTHORIZATION
  SQLITE_OMIT_AUTOINCREMENT
  SQLITE_OMIT_AUTOINIT
  SQLITE_OMIT_AUTOMATIC_INDEX
  SQLITE_OMIT_AUTORESET
  SQLITE_OMIT_AUTOVACUUM
  SQLITE_OMIT_BETWEEN_OPTIMIZATION
  SQLITE_OMIT_BLOB_LITERAL
  SQLITE_OMIT_BTREECOUNT
  SQLITE_OMIT_CAST
  SQLITE_OMIT_CHECK
  SQLITE_OMIT_COMPLETE
  SQLITE_OMIT_COMPOUND_SELECT
  SQLITE_OMIT_CONFLICT_CLAUSE
  SQLITE_OMIT_CTE
  SQLITE_OMIT_DATETIME_FUNCS
  SQLITE_OMIT_DECLTYPE
  SQLITE_OMIT_DEPRECATED
  SQLITE_OMIT_DECLTYPE
  SQLITE_OMIT_DEPRECATED
  SQLITE_OMIT_DESERIALIZE
  SQLITE_OMIT_DISKIO
  SQLITE_OMIT_EXPLAIN
  SQLITE_OMIT_FLAG_PRAGMAS
  SQLITE_OMIT_FLOATING_POINT
  SQLITE_OMIT_FOREIGN_KEY
  SQLITE_OMIT_GET_TABLE
  SQLITE_OMIT_HEX_INTEGER
  SQLITE_OMIT_INCRBLOB
  SQLITE_OMIT_INTEGRITY_CHECK
  SQLITE_OMIT_INTROSPECTION_PRAGMAS
  SQLITE_OMIT_JSON
  SQLITE_OMIT_LIKE_OPTIMIZATION
  SQLITE_OMIT_LOAD_EXTENSION
  SQLITE_OMIT_LOCALTIME
  SQLITE_OMIT_LOOKASIDE
  SQLITE_OMIT_MEMORYDB
  SQLITE_OMIT_OR_OPTIMIZATION
  SQLITE_OMIT_PAGER_PRAGMAS
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
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







-









-

-








-













-
+
+

+
+
+
+
+
+
+

+






-










+

+







  SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
  SQLITE_OMIT_SHARED_CACHE
  SQLITE_OMIT_SHUTDOWN_DIRECTORIES
  SQLITE_OMIT_SUBQUERY
  SQLITE_OMIT_TCL_VARIABLE
  SQLITE_OMIT_TEMPDB
  SQLITE_OMIT_TEST_CONTROL
  SQLITE_OMIT_TRACE
  SQLITE_OMIT_TRIGGER
  SQLITE_OMIT_TRUNCATE_OPTIMIZATION
  SQLITE_OMIT_UTF16
  SQLITE_OMIT_VACUUM
  SQLITE_OMIT_VIEW
  SQLITE_OMIT_VIRTUALTABLE
  SQLITE_OMIT_WAL
  SQLITE_OMIT_WSD
  SQLITE_OMIT_XFER_OPT
  SQLITE_PCACHE_SEPARATE_HEADER
  SQLITE_PERFORMANCE_TRACE
  SQLITE_POWERSAFE_OVERWRITE
  SQLITE_PREFER_PROXY_LOCKING
  SQLITE_PROXY_DEBUG
  SQLITE_REVERSE_UNORDERED_SELECTS
  SQLITE_RTREE_INT_ONLY
  SQLITE_SECURE_DELETE
  SQLITE_SMALL_STACK
  SQLITE_SOUNDEX
  SQLITE_SUBSTR_COMPATIBILITY
  SQLITE_SYSTEM_MALLOC
  SQLITE_TCL
  SQLITE_TEST
  SQLITE_UNLINK_AFTER_CLOSE
  SQLITE_UNTESTABLE
  SQLITE_USE_ALLOCA
  SQLITE_USE_FCNTL_TRACE
  SQLITE_USER_AUTHENTICATION
  SQLITE_USE_URI
  SQLITE_VDBE_COVERAGE
  SQLITE_WIN32_MALLOC
  SQLITE_ZERO_MALLOC
}

# All compile time options for which the assigned value is other than boolean.
# All compile time options for which the assigned value is other than boolean
# and is a comma-separated scalar pair.
#
set value2_options {
  SQLITE_DEFAULT_LOOKASIDE
}

# All compile time options for which the assigned value is other than boolean
# and is a single scalar.
#
set value_options {
  SQLITE_ATOMIC_INTRINSICS
  SQLITE_BITMASK_TYPE
  SQLITE_DEFAULT_CACHE_SIZE
  SQLITE_DEFAULT_FILE_FORMAT
  SQLITE_DEFAULT_FILE_PERMISSIONS
  SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT
  SQLITE_DEFAULT_LOCKING_MODE
  SQLITE_DEFAULT_LOOKASIDE
  SQLITE_DEFAULT_MMAP_SIZE
  SQLITE_DEFAULT_PAGE_SIZE
  SQLITE_DEFAULT_PCACHE_INITSZ
  SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
  SQLITE_DEFAULT_ROWEST
  SQLITE_DEFAULT_SECTOR_SIZE
  SQLITE_DEFAULT_SYNCHRONOUS
  SQLITE_DEFAULT_WAL_AUTOCHECKPOINT
  SQLITE_DEFAULT_WAL_SYNCHRONOUS
  SQLITE_DEFAULT_WORKER_THREADS
  SQLITE_DQS
  SQLITE_ENABLE_8_3_NAMES
  SQLITE_ENABLE_CEROD
  SQLITE_ENABLE_LOCKING_STYLE
  SQLITE_EXTRA_INIT
  SQLITE_EXTRA_SHUTDOWN
  SQLITE_FTS3_MAX_EXPR_DEPTH
  SQLITE_INTEGRITY_CHECK_ERROR_MAX
  SQLITE_MALLOC_SOFT_LIMIT
  SQLITE_MAX_ATTACHED
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

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







-
-
-
-
-
-
-
















+
+
+
+
+
+
+
+
+
+
+
+
+






-
+











+
+
+
+
+
+
+
+
+
+
+
+
+
-
+


-
+













-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+

-
+

+
  SQLITE_STAT4_SAMPLES
  SQLITE_STMTJRNL_SPILL
  SQLITE_TEMP_STORE
}

# Options that require custom code.
#
set options(ENABLE_STAT3) {
#if defined(SQLITE_ENABLE_STAT4)
  "ENABLE_STAT4",
#elif defined(SQLITE_ENABLE_STAT3)
  "ENABLE_STAT3",
#endif
}
set options(COMPILER) {
#if defined(__clang__) && defined(__clang_major__)
  "COMPILER=clang-" CTIMEOPT_VAL(__clang_major__) "."
                    CTIMEOPT_VAL(__clang_minor__) "."
                    CTIMEOPT_VAL(__clang_patchlevel__),
#elif defined(_MSC_VER)
  "COMPILER=msvc-" CTIMEOPT_VAL(_MSC_VER),
#elif defined(__GNUC__) && defined(__VERSION__)
  "COMPILER=gcc-" __VERSION__,
#endif
}
set options(HAVE_ISNAN) {
#if HAVE_ISNAN || SQLITE_HAVE_ISNAN
  "HAVE_ISNAN",
#endif
}
set options(OMIT_DATETIME_FUNCS) {
#if defined(SQLITE_OMIT_DATETIME_FUNCS) || defined(SQLITE_OMIT_FLOATING_POINT)
  "OMIT_DATETIME_FUNCS",
#endif
}
set options(SYSTEM_MALLOC) "\
#if (!defined(SQLITE_WIN32_MALLOC) \\
     && !defined(SQLITE_ZERO_MALLOC) \\
     && !defined(SQLITE_MEMDEBUG) \\
    ) || defined(SQLITE_SYSTEM_MALLOC)
  \"SYSTEM_MALLOC\",
#endif
"
set options(THREADSAFE) {
#if defined(SQLITE_THREADSAFE)
  "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
#elif defined(THREADSAFE)
  "THREADSAFE=" CTIMEOPT_VAL(THREADSAFE),
#else
  "THREADSAFE=1"
  "THREADSAFE=1",
#endif
}

proc trim_name {in} {
  set ret $in
  if {[string range $in 0 6]=="SQLITE_"} {
    set ret [string range $in 7 end]
  }
  return $ret
}

foreach name_defval $boolean_defnnz_options {
  set b [lindex $name_defval 0]
  set defval [lindex $name_defval 1]
  set name [trim_name $b]
  set options($name) [subst {
#ifdef $b
# if $b != $defval
  "$name=" CTIMEOPT_VAL($b),
# endif
#endif
}]
}

foreach b $boolean_options {
foreach b $boolean_defnil_options {
  set name [trim_name $b]
  set options($name) [subst {
#if $b
#ifdef $b
  "$name",
#endif
}]
}
  
foreach v $value_options {
  set name [trim_name $v]
  set options($name) [subst {
#ifdef $v
  "$name=" CTIMEOPT_VAL($v),
#endif
}]
}

  
foreach v $value2_options {
  set name [trim_name $v]
  set options($name) [subst {
#ifdef $v
  "$name=" CTIMEOPT_VAL2($v),
#endif
}]
}

set ctime_c "src/ctime.c"

if {[catch {set cfd [open $ctime_c w]}]!=0} {
  puts stderr "File '$ctime_c' unwritable."
  exit 1;
}

puts $cfd $::headWarning;
puts $cfd $::headCode;
foreach o [lsort [array names options]] {
  puts [string trim $options($o)]
  puts $cfd [string trim $options($o)]
}

puts -nonewline $cfd $::tailCode;

close $cfd

Changes to tool/mkkeywordhash.c.

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
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







+















-
+







** table composed of instances of the following structure.
*/
typedef struct Keyword Keyword;
struct Keyword {
  char *zName;         /* The keyword name */
  char *zTokenType;    /* Token value for this keyword */
  int mask;            /* Code this keyword if non-zero */
  int priority;        /* Put higher priorities earlier in the hash chain */
  int id;              /* Unique ID for this record */
  int hash;            /* Hash on the keyword */
  int offset;          /* Offset to start of name string */
  int len;             /* Length of this keyword, not counting final \000 */
  int prefix;          /* Number of characters in prefix */
  int longestSuffix;   /* Longest suffix that is a prefix on another word */
  int iNext;           /* Index in aKeywordTable[] of next with same hash */
  int substrId;        /* Id to another keyword this keyword is embedded in */
  int substrOffset;    /* Offset into substrId for start of this keyword */
  char zOrigName[20];  /* Original keyword name before processing */
};

/*
** Define masks used to determine which keywords are allowed
*/
#ifdef SQLITE_OMIT_ALTERTABLE
#if defined(SQLITE_OMIT_ALTERTABLE) || defined(SQLITE_OMIT_VIRTUALTABLE)
#  define ALTER      0
#else
#  define ALTER      0x00000001
#endif
#define ALWAYS       0x00000002
#ifdef SQLITE_OMIT_ANALYZE
#  define ANALYZE    0
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
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







+
+
+
+
+
+
+
+
+
+
+





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-







#  define UPSERT     0x00080000
#endif
#ifdef SQLITE_OMIT_WINDOWFUNC
#  define WINDOWFUNC 0
#else
#  define WINDOWFUNC 0x00100000
#endif
#ifdef SQLITE_OMIT_GENERATED_COLUMNS
#  define GENCOL     0
#else
#  define GENCOL     0x00200000
#endif
#ifdef SQLITE_OMIT_RETURNING
#  define RETURNING  0
#else
#  define RETURNING  0x00400000
#endif


/*
** These are the keywords
*/
static Keyword aKeywordTable[] = {
  { "ABORT",            "TK_ABORT",        CONFLICT|TRIGGER       },
  { "ACTION",           "TK_ACTION",       FKEY                   },
  { "ADD",              "TK_ADD",          ALTER                  },
  { "AFTER",            "TK_AFTER",        TRIGGER                },
  { "ALL",              "TK_ALL",          ALWAYS                 },
  { "ALTER",            "TK_ALTER",        ALTER                  },
  { "ANALYZE",          "TK_ANALYZE",      ANALYZE                },
  { "AND",              "TK_AND",          ALWAYS                 },
  { "AS",               "TK_AS",           ALWAYS                 },
  { "ASC",              "TK_ASC",          ALWAYS                 },
  { "ATTACH",           "TK_ATTACH",       ATTACH                 },
  { "AUTOINCREMENT",    "TK_AUTOINCR",     AUTOINCR               },
  { "BEFORE",           "TK_BEFORE",       TRIGGER                },
  { "BEGIN",            "TK_BEGIN",        ALWAYS                 },
  { "BETWEEN",          "TK_BETWEEN",      ALWAYS                 },
  { "BY",               "TK_BY",           ALWAYS                 },
  { "CASCADE",          "TK_CASCADE",      FKEY                   },
  { "CASE",             "TK_CASE",         ALWAYS                 },
  { "CAST",             "TK_CAST",         CAST                   },
  { "CHECK",            "TK_CHECK",        ALWAYS                 },
  { "COLLATE",          "TK_COLLATE",      ALWAYS                 },
  { "COLUMN",           "TK_COLUMNKW",     ALTER                  },
  { "COMMIT",           "TK_COMMIT",       ALWAYS                 },
  { "CONFLICT",         "TK_CONFLICT",     CONFLICT               },
  { "CONSTRAINT",       "TK_CONSTRAINT",   ALWAYS                 },
  { "CREATE",           "TK_CREATE",       ALWAYS                 },
  { "CROSS",            "TK_JOIN_KW",      ALWAYS                 },
  { "CURRENT",          "TK_CURRENT",      WINDOWFUNC             },
  { "CURRENT_DATE",     "TK_CTIME_KW",     ALWAYS                 },
  { "CURRENT_TIME",     "TK_CTIME_KW",     ALWAYS                 },
  { "CURRENT_TIMESTAMP","TK_CTIME_KW",     ALWAYS                 },
  { "DATABASE",         "TK_DATABASE",     ATTACH                 },
  { "DEFAULT",          "TK_DEFAULT",      ALWAYS                 },
  { "DEFERRED",         "TK_DEFERRED",     ALWAYS                 },
  { "DEFERRABLE",       "TK_DEFERRABLE",   FKEY                   },
  { "DELETE",           "TK_DELETE",       ALWAYS                 },
  { "DESC",             "TK_DESC",         ALWAYS                 },
  { "DETACH",           "TK_DETACH",       ATTACH                 },
  { "DISTINCT",         "TK_DISTINCT",     ALWAYS                 },
  { "DO",               "TK_DO",           UPSERT                 },
  { "DROP",             "TK_DROP",         ALWAYS                 },
  { "END",              "TK_END",          ALWAYS                 },
  { "EACH",             "TK_EACH",         TRIGGER                },
  { "ELSE",             "TK_ELSE",         ALWAYS                 },
  { "ESCAPE",           "TK_ESCAPE",       ALWAYS                 },
  { "EXCEPT",           "TK_EXCEPT",       COMPOUND               },
  { "EXISTS",           "TK_EXISTS",       ALWAYS                 },
  { "EXPLAIN",          "TK_EXPLAIN",      EXPLAIN                },
  { "FAIL",             "TK_FAIL",         CONFLICT|TRIGGER       },
  { "FILTER",           "TK_FILTER",       WINDOWFUNC             },
  { "FOLLOWING",        "TK_FOLLOWING",    WINDOWFUNC             },
  { "FOR",              "TK_FOR",          TRIGGER                },
  { "FOREIGN",          "TK_FOREIGN",      FKEY                   },
  { "FROM",             "TK_FROM",         ALWAYS                 },
  { "FULL",             "TK_JOIN_KW",      ALWAYS                 },
  { "GLOB",             "TK_LIKE_KW",      ALWAYS                 },
  { "GROUP",            "TK_GROUP",        ALWAYS                 },
  { "HAVING",           "TK_HAVING",       ALWAYS                 },
  { "IF",               "TK_IF",           ALWAYS                 },
  { "IGNORE",           "TK_IGNORE",       CONFLICT|TRIGGER       },
  { "IMMEDIATE",        "TK_IMMEDIATE",    ALWAYS                 },
  { "IN",               "TK_IN",           ALWAYS                 },
  { "INDEX",            "TK_INDEX",        ALWAYS                 },
  { "INDEXED",          "TK_INDEXED",      ALWAYS                 },
  { "INITIALLY",        "TK_INITIALLY",    FKEY                   },
  { "INNER",            "TK_JOIN_KW",      ALWAYS                 },
  { "INSERT",           "TK_INSERT",       ALWAYS                 },
  { "INSTEAD",          "TK_INSTEAD",      TRIGGER                },
  { "INTERSECT",        "TK_INTERSECT",    COMPOUND               },
  { "INTO",             "TK_INTO",         ALWAYS                 },
  { "IS",               "TK_IS",           ALWAYS                 },
  { "ISNULL",           "TK_ISNULL",       ALWAYS                 },
  { "JOIN",             "TK_JOIN",         ALWAYS                 },
  { "KEY",              "TK_KEY",          ALWAYS                 },
  { "LEFT",             "TK_JOIN_KW",      ALWAYS                 },
  { "LIKE",             "TK_LIKE_KW",      ALWAYS                 },
  { "LIMIT",            "TK_LIMIT",        ALWAYS                 },
  { "MATCH",            "TK_MATCH",        ALWAYS                 },
  { "NATURAL",          "TK_JOIN_KW",      ALWAYS                 },
  { "NO",               "TK_NO",           FKEY                   },
  { "NOT",              "TK_NOT",          ALWAYS                 },
  { "NOTHING",          "TK_NOTHING",      UPSERT                 },
  { "NOTNULL",          "TK_NOTNULL",      ALWAYS                 },
  { "NULL",             "TK_NULL",         ALWAYS                 },
  { "OF",               "TK_OF",           ALWAYS                 },
  { "OFFSET",           "TK_OFFSET",       ALWAYS                 },
  { "ON",               "TK_ON",           ALWAYS                 },
  { "OR",               "TK_OR",           ALWAYS                 },
  { "ORDER",            "TK_ORDER",        ALWAYS                 },
  { "OUTER",            "TK_JOIN_KW",      ALWAYS                 },
  { "OVER",             "TK_OVER",         WINDOWFUNC             },
  { "PARTITION",        "TK_PARTITION",    WINDOWFUNC             },
  { "PLAN",             "TK_PLAN",         EXPLAIN                },
  { "PRAGMA",           "TK_PRAGMA",       PRAGMA                 },
  { "PRECEDING",        "TK_PRECEDING",    WINDOWFUNC             },
  { "PRIMARY",          "TK_PRIMARY",      ALWAYS                 },
  { "QUERY",            "TK_QUERY",        EXPLAIN                },
  { "RAISE",            "TK_RAISE",        TRIGGER                },
  { "RANGE",            "TK_RANGE",        WINDOWFUNC             },
  { "RECURSIVE",        "TK_RECURSIVE",    CTE                    },
  { "REFERENCES",       "TK_REFERENCES",   FKEY                   },
  { "REGEXP",           "TK_LIKE_KW",      ALWAYS                 },
  { "REINDEX",          "TK_REINDEX",      REINDEX                },
  { "RELEASE",          "TK_RELEASE",      ALWAYS                 },
  { "RENAME",           "TK_RENAME",       ALTER                  },
  { "REPLACE",          "TK_REPLACE",      CONFLICT               },
  { "RESTRICT",         "TK_RESTRICT",     FKEY                   },
  { "RIGHT",            "TK_JOIN_KW",      ALWAYS                 },
  { "ROLLBACK",         "TK_ROLLBACK",     ALWAYS                 },
  { "ROW",              "TK_ROW",          TRIGGER                },
  { "ROWS",             "TK_ROWS",         ALWAYS                 },
  { "SAVEPOINT",        "TK_SAVEPOINT",    ALWAYS                 },
  { "SELECT",           "TK_SELECT",       ALWAYS                 },
  { "SET",              "TK_SET",          ALWAYS                 },
  { "TABLE",            "TK_TABLE",        ALWAYS                 },
  { "TEMP",             "TK_TEMP",         ALWAYS                 },
  { "TEMPORARY",        "TK_TEMP",         ALWAYS                 },
  { "THEN",             "TK_THEN",         ALWAYS                 },
  { "TO",               "TK_TO",           ALWAYS                 },
  { "TRANSACTION",      "TK_TRANSACTION",  ALWAYS                 },
  { "TRIGGER",          "TK_TRIGGER",      TRIGGER                },
  { "UNBOUNDED",        "TK_UNBOUNDED",    WINDOWFUNC             },
  { "UNION",            "TK_UNION",        COMPOUND               },
  { "UNIQUE",           "TK_UNIQUE",       ALWAYS                 },
  { "UPDATE",           "TK_UPDATE",       ALWAYS                 },
  { "USING",            "TK_USING",        ALWAYS                 },
  { "VACUUM",           "TK_VACUUM",       VACUUM                 },
  { "VALUES",           "TK_VALUES",       ALWAYS                 },
  { "VIEW",             "TK_VIEW",         VIEW                   },
  { "VIRTUAL",          "TK_VIRTUAL",      VTAB                   },
  { "WINDOW",           "TK_WINDOW",       WINDOWFUNC             },
  { "WITH",             "TK_WITH",         CTE                    },
  { "WITHOUT",          "TK_WITHOUT",      ALWAYS                 },
  { "ABORT",            "TK_ABORT",        CONFLICT|TRIGGER, 0      },
  { "ACTION",           "TK_ACTION",       FKEY,             0      },
  { "ADD",              "TK_ADD",          ALTER,            1      },
  { "AFTER",            "TK_AFTER",        TRIGGER,          0      },
  { "ALL",              "TK_ALL",          ALWAYS,           0      },
  { "ALTER",            "TK_ALTER",        ALTER,            0      },
  { "ALWAYS",           "TK_ALWAYS",       GENCOL,           0      },
  { "ANALYZE",          "TK_ANALYZE",      ANALYZE,          0      },
  { "AND",              "TK_AND",          ALWAYS,           10     },
  { "AS",               "TK_AS",           ALWAYS,           10     },
  { "ASC",              "TK_ASC",          ALWAYS,           0      },
  { "ATTACH",           "TK_ATTACH",       ATTACH,           1      },
  { "AUTOINCREMENT",    "TK_AUTOINCR",     AUTOINCR,         0      },
  { "BEFORE",           "TK_BEFORE",       TRIGGER,          0      },
  { "BEGIN",            "TK_BEGIN",        ALWAYS,           1      },
  { "BETWEEN",          "TK_BETWEEN",      ALWAYS,           5      },
  { "BY",               "TK_BY",           ALWAYS,           10     },
  { "CASCADE",          "TK_CASCADE",      FKEY,             1      },
  { "CASE",             "TK_CASE",         ALWAYS,           5      },
  { "CAST",             "TK_CAST",         CAST,             5      },
  { "CHECK",            "TK_CHECK",        ALWAYS,           1      },
  { "COLLATE",          "TK_COLLATE",      ALWAYS,           1      },
  { "COLUMN",           "TK_COLUMNKW",     ALTER,            1      },
  { "COMMIT",           "TK_COMMIT",       ALWAYS,           1      },
  { "CONFLICT",         "TK_CONFLICT",     CONFLICT,         0      },
  { "CONSTRAINT",       "TK_CONSTRAINT",   ALWAYS,           1      },
  { "CREATE",           "TK_CREATE",       ALWAYS,           2      },
  { "CROSS",            "TK_JOIN_KW",      ALWAYS,           3      },
  { "CURRENT",          "TK_CURRENT",      WINDOWFUNC,       1      },
  { "CURRENT_DATE",     "TK_CTIME_KW",     ALWAYS,           1      },
  { "CURRENT_TIME",     "TK_CTIME_KW",     ALWAYS,           1      },
  { "CURRENT_TIMESTAMP","TK_CTIME_KW",     ALWAYS,           1      },
  { "DATABASE",         "TK_DATABASE",     ATTACH,           0      },
  { "DEFAULT",          "TK_DEFAULT",      ALWAYS,           1      },
  { "DEFERRED",         "TK_DEFERRED",     ALWAYS,           1      },
  { "DEFERRABLE",       "TK_DEFERRABLE",   FKEY,             1      },
  { "DELETE",           "TK_DELETE",       ALWAYS,           10     },
  { "DESC",             "TK_DESC",         ALWAYS,           3      },
  { "DETACH",           "TK_DETACH",       ATTACH,           0      },
  { "DISTINCT",         "TK_DISTINCT",     ALWAYS,           5      },
  { "DO",               "TK_DO",           UPSERT,           2      },
  { "DROP",             "TK_DROP",         ALWAYS,           1      },
  { "END",              "TK_END",          ALWAYS,           1      },
  { "EACH",             "TK_EACH",         TRIGGER,          1      },
  { "ELSE",             "TK_ELSE",         ALWAYS,           2      },
  { "ESCAPE",           "TK_ESCAPE",       ALWAYS,           4      },
  { "EXCEPT",           "TK_EXCEPT",       COMPOUND,         4      },
  { "EXCLUSIVE",        "TK_EXCLUSIVE",    ALWAYS,           1      },
  { "EXCLUDE",          "TK_EXCLUDE",      WINDOWFUNC,       1      },
  { "EXISTS",           "TK_EXISTS",       ALWAYS,           4      },
  { "EXPLAIN",          "TK_EXPLAIN",      EXPLAIN,          1      },
  { "FAIL",             "TK_FAIL",         CONFLICT|TRIGGER, 1      },
  { "FILTER",           "TK_FILTER",       WINDOWFUNC,       4      },
  { "FIRST",            "TK_FIRST",        ALWAYS,           4      },
  { "FOLLOWING",        "TK_FOLLOWING",    WINDOWFUNC,       4      },
  { "FOR",              "TK_FOR",          TRIGGER,          2      },
  { "FOREIGN",          "TK_FOREIGN",      FKEY,             1      },
  { "FROM",             "TK_FROM",         ALWAYS,           10     },
  { "FULL",             "TK_JOIN_KW",      ALWAYS,           3      },
  { "GENERATED",        "TK_GENERATED",    ALWAYS,           1      },
  { "GLOB",             "TK_LIKE_KW",      ALWAYS,           3      },
  { "GROUP",            "TK_GROUP",        ALWAYS,           5      },
  { "GROUPS",           "TK_GROUPS",       WINDOWFUNC,       2      },
  { "HAVING",           "TK_HAVING",       ALWAYS,           5      },
  { "IF",               "TK_IF",           ALWAYS,           2      },
  { "IGNORE",           "TK_IGNORE",       CONFLICT|TRIGGER, 1      },
  { "IMMEDIATE",        "TK_IMMEDIATE",    ALWAYS,           1      },
  { "IN",               "TK_IN",           ALWAYS,           10     },
  { "INDEX",            "TK_INDEX",        ALWAYS,           1      },
  { "INDEXED",          "TK_INDEXED",      ALWAYS,           0      },
  { "INITIALLY",        "TK_INITIALLY",    FKEY,             1      },
  { "INNER",            "TK_JOIN_KW",      ALWAYS,           1      },
  { "INSERT",           "TK_INSERT",       ALWAYS,           10     },
  { "INSTEAD",          "TK_INSTEAD",      TRIGGER,          1      },
  { "INTERSECT",        "TK_INTERSECT",    COMPOUND,         5      },
  { "INTO",             "TK_INTO",         ALWAYS,           10     },
  { "IS",               "TK_IS",           ALWAYS,           5      },
  { "ISNULL",           "TK_ISNULL",       ALWAYS,           5      },
  { "JOIN",             "TK_JOIN",         ALWAYS,           5      },
  { "KEY",              "TK_KEY",          ALWAYS,           1      },
  { "LAST",             "TK_LAST",         ALWAYS,           4      },
  { "LEFT",             "TK_JOIN_KW",      ALWAYS,           5      },
  { "LIKE",             "TK_LIKE_KW",      ALWAYS,           5      },
  { "LIMIT",            "TK_LIMIT",        ALWAYS,           3      },
  { "MATCH",            "TK_MATCH",        ALWAYS,           2      },
  { "MATERIALIZED",     "TK_MATERIALIZED", CTE,              12     },
  { "NATURAL",          "TK_JOIN_KW",      ALWAYS,           3      },
  { "NO",               "TK_NO",           FKEY|WINDOWFUNC,  2      },
  { "NOT",              "TK_NOT",          ALWAYS,           10     },
  { "NOTHING",          "TK_NOTHING",      UPSERT,           1      },
  { "NOTNULL",          "TK_NOTNULL",      ALWAYS,           3      },
  { "NULL",             "TK_NULL",         ALWAYS,           10     },
  { "NULLS",            "TK_NULLS",        ALWAYS,           3      },
  { "OF",               "TK_OF",           ALWAYS,           3      },
  { "OFFSET",           "TK_OFFSET",       ALWAYS,           1      },
  { "ON",               "TK_ON",           ALWAYS,           1      },
  { "OR",               "TK_OR",           ALWAYS,           9      },
  { "ORDER",            "TK_ORDER",        ALWAYS,           10     },
  { "OTHERS",           "TK_OTHERS",       WINDOWFUNC,       3      },
  { "OUTER",            "TK_JOIN_KW",      ALWAYS,           5      },
  { "OVER",             "TK_OVER",         WINDOWFUNC,       3      },
  { "PARTITION",        "TK_PARTITION",    WINDOWFUNC,       3      },
  { "PLAN",             "TK_PLAN",         EXPLAIN,          0      },
  { "PRAGMA",           "TK_PRAGMA",       PRAGMA,           0      },
  { "PRECEDING",        "TK_PRECEDING",    WINDOWFUNC,       3      },
  { "PRIMARY",          "TK_PRIMARY",      ALWAYS,           1      },
  { "QUERY",            "TK_QUERY",        EXPLAIN,          0      },
  { "RAISE",            "TK_RAISE",        TRIGGER,          1      },
  { "RANGE",            "TK_RANGE",        WINDOWFUNC,       3      },
  { "RECURSIVE",        "TK_RECURSIVE",    CTE,              3      },
  { "REFERENCES",       "TK_REFERENCES",   FKEY,             1      },
  { "REGEXP",           "TK_LIKE_KW",      ALWAYS,           3      },
  { "REINDEX",          "TK_REINDEX",      REINDEX,          1      },
  { "RELEASE",          "TK_RELEASE",      ALWAYS,           1      },
  { "RENAME",           "TK_RENAME",       ALTER,            1      },
  { "REPLACE",          "TK_REPLACE",      CONFLICT,         10     },
  { "RESTRICT",         "TK_RESTRICT",     FKEY,             1      },
  { "RETURNING",        "TK_RETURNING",    RETURNING,        10     },
  { "RIGHT",            "TK_JOIN_KW",      ALWAYS,           0      },
  { "ROLLBACK",         "TK_ROLLBACK",     ALWAYS,           1      },
  { "ROW",              "TK_ROW",          TRIGGER,          1      },
  { "ROWS",             "TK_ROWS",         ALWAYS,           1      },
  { "SAVEPOINT",        "TK_SAVEPOINT",    ALWAYS,           1      },
  { "SELECT",           "TK_SELECT",       ALWAYS,           10     },
  { "SET",              "TK_SET",          ALWAYS,           10     },
  { "TABLE",            "TK_TABLE",        ALWAYS,           1      },
  { "TEMP",             "TK_TEMP",         ALWAYS,           1      },
  { "TEMPORARY",        "TK_TEMP",         ALWAYS,           1      },
  { "THEN",             "TK_THEN",         ALWAYS,           3      },
  { "TIES",             "TK_TIES",         WINDOWFUNC,       3      },
  { "TO",               "TK_TO",           ALWAYS,           3      },
  { "TRANSACTION",      "TK_TRANSACTION",  ALWAYS,           1      },
  { "TRIGGER",          "TK_TRIGGER",      TRIGGER,          1      },
  { "UNBOUNDED",        "TK_UNBOUNDED",    WINDOWFUNC,       3      },
  { "UNION",            "TK_UNION",        COMPOUND,         3      },
  { "UNIQUE",           "TK_UNIQUE",       ALWAYS,           1      },
  { "UPDATE",           "TK_UPDATE",       ALWAYS,           10     },
  { "USING",            "TK_USING",        ALWAYS,           8      },
  { "VACUUM",           "TK_VACUUM",       VACUUM,           1      },
  { "VALUES",           "TK_VALUES",       ALWAYS,           10     },
  { "VIEW",             "TK_VIEW",         VIEW,             1      },
  { "VIRTUAL",          "TK_VIRTUAL",      VTAB,             1      },
  { "WHEN",             "TK_WHEN",         ALWAYS,           1      },
  { "WHERE",            "TK_WHERE",        ALWAYS,           10     },
  { "WINDOW",           "TK_WINDOW",       WINDOWFUNC,       3      },
  { "WITH",             "TK_WITH",         CTE,              4      },
  { "WITHOUT",          "TK_WITHOUT",      ALWAYS,           1      },
  { "WHEN",             "TK_WHEN",         ALWAYS                 },
  { "WHERE",            "TK_WHERE",        ALWAYS                 },
};

/* Number of keywords */
static int nKeyword = (sizeof(aKeywordTable)/sizeof(aKeywordTable[0]));

/* Map all alphabetic characters into lower-case for hashing.  This is
** only valid for alphabetics.  In particular it does not work for '_'
343
344
345
346
347
348
349


























350
351
352
353
354
355
356
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  int i;
  for(i=0; i<nKeyword; i++){
    if( aKeywordTable[i].id==id ) break;
  }
  return &aKeywordTable[i];
}

/*
** If aKeyword[*pFrom-1].iNext has a higher priority that aKeyword[*pFrom-1]
** itself, then swap them.
*/
static void reorder(int *pFrom){
  int i = *pFrom - 1;
  int j;
  if( i<0 ) return;
  j = aKeywordTable[i].iNext;
  if( j==0 ) return;
  j--;
  if( aKeywordTable[i].priority >= aKeywordTable[j].priority ) return;
  aKeywordTable[i].iNext = aKeywordTable[j].iNext;
  aKeywordTable[j].iNext = i+1;
  *pFrom = j+1;
  reorder(&aKeywordTable[i].iNext);
}

/* Parameter to the hash function
*/
#define HASH_OP ^
#define HASH_CC '^'
#define HASH_C0 4
#define HASH_C1 3
#define HASH_C2 1

/*
** This routine does the work.  The generated code is printed on standard
** output.
*/
int main(int argc, char **argv){
  int i, j, k, h;
  int bestSize, bestCount;
373
374
375
376
377
378
379
380
381



382
383
384
385
386
387
388
423
424
425
426
427
428
429


430
431
432
433
434
435
436
437
438
439







-
-
+
+
+







  /* Fill in the lengths of strings and hashes for all entries. */
  for(i=0; i<nKeyword; i++){
    Keyword *p = &aKeywordTable[i];
    p->len = (int)strlen(p->zName);
    assert( p->len<sizeof(p->zOrigName) );
    memcpy(p->zOrigName, p->zName, p->len+1);
    totalLen += p->len;
    p->hash = (charMap(p->zName[0])*4) ^
              (charMap(p->zName[p->len-1])*3) ^ (p->len*1);
    p->hash = (charMap(p->zName[0])*HASH_C0) HASH_OP
              (charMap(p->zName[p->len-1])*HASH_C1) HASH_OP
              (p->len*HASH_C2);
    p->id = i+1;
  }

  /* Sort the table from shortest to longest keyword */
  qsort(aKeywordTable, nKeyword, sizeof(aKeywordTable[0]), keywordCompare1);

  /* Look for short keywords embedded in longer keywords */
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
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







+



















+







  qsort(aKeywordTable, nKeyword, sizeof(aKeywordTable[0]), keywordCompare3);

  /* Figure out how big to make the hash table in order to minimize the
  ** number of collisions */
  bestSize = nKeyword;
  bestCount = nKeyword*nKeyword;
  for(i=nKeyword/2; i<=2*nKeyword; i++){
    if( i<=0 ) continue;
    for(j=0; j<i; j++) aKWHash[j] = 0;
    for(j=0; j<nKeyword; j++){
      h = aKeywordTable[j].hash % i;
      aKWHash[h] *= 2;
      aKWHash[h]++;
    }
    for(j=count=0; j<i; j++) count += aKWHash[j];
    if( count<bestCount ){
      bestCount = count;
      bestSize = i;
    }
  }

  /* Compute the hash */
  for(i=0; i<bestSize; i++) aKWHash[i] = 0;
  for(i=0; i<nKeyword; i++){
    h = aKeywordTable[i].hash % bestSize;
    aKeywordTable[i].iNext = aKWHash[h];
    aKWHash[h] = i+1;
    reorder(&aKWHash[h]);
  }

  /* Begin generating code */
  printf("%s", zHdr);
  printf("/* Hash score: %d */\n", bestCount);
  printf("/* zKWText[] encodes %d bytes of keyword text in %d bytes */\n",
          totalLen + nKeyword, nChar+1 );
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
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







+
+
+
+
+
+
+
+
+
+
+







-
-
+
+
+


-


+
+
+



+
+
+







    j++;
    if( j>=5 ){
      printf("\n");
      j = 0;
    }
  }
  printf("%s};\n", j==0 ? "" : "\n");
  printf("/* Hash table decoded:\n");
  for(i=0; i<bestSize; i++){
    j = aKWHash[i];
    printf("** %3d:", i);
    while( j ){
      printf(" %s", aKeywordTable[j-1].zOrigName);
      j = aKeywordTable[j-1].iNext;
    }
    printf("\n");
  }
  printf("*/\n");
  printf("/* Check to see if z[0..n-1] is a keyword. If it is, write the\n");
  printf("** parser symbol code for that keyword into *pType.  Always\n");
  printf("** return the integer n (the length of the token). */\n");
  printf("static int keywordCode(const char *z, int n, int *pType){\n");
  printf("  int i, j;\n");
  printf("  const char *zKW;\n");
  printf("  if( n>=2 ){\n");
  printf("    i = ((charMap(z[0])*4) ^ (charMap(z[n-1])*3) ^ n) %% %d;\n",
          bestSize);
  printf("    i = ((charMap(z[0])*%d) %c", HASH_C0, HASH_CC);
  printf(" (charMap(z[n-1])*%d) %c", HASH_C1, HASH_CC);
  printf(" n*%d) %% %d;\n", HASH_C2, bestSize);
  printf("    for(i=((int)aKWHash[i])-1; i>=0; i=((int)aKWNext[i])-1){\n");
  printf("      if( aKWLen[i]!=n ) continue;\n");
  printf("      j = 0;\n");
  printf("      zKW = &zKWText[aKWOffset[i]];\n");
  printf("#ifdef SQLITE_ASCII\n");
  printf("      if( (z[0]&~0x20)!=zKW[0] ) continue;\n");
  printf("      if( (z[1]&~0x20)!=zKW[1] ) continue;\n");
  printf("      j = 2;\n");
  printf("      while( j<n && (z[j]&~0x20)==zKW[j] ){ j++; }\n");
  printf("#endif\n");
  printf("#ifdef SQLITE_EBCDIC\n");
  printf("      if( toupper(z[0])!=zKW[0] ) continue;\n");
  printf("      if( toupper(z[1])!=zKW[1] ) continue;\n");
  printf("      j = 2;\n");
  printf("      while( j<n && toupper(z[j])==zKW[j] ){ j++; }\n");
  printf("#endif\n");
  printf("      if( j<n ) continue;\n");
  for(i=0; i<nKeyword; i++){
    printf("      testcase( i==%d ); /* %s */\n",
           i, aKeywordTable[i].zOrigName);
  }

Changes to tool/mkmsvcmin.tcl.

79
80
81
82
83
84
85
86

87
88
89
90
91
92
93
79
80
81
82
83
84
85

86
87
88
89
90
91
92
93







-
+







set blocks(2) [string trimleft [string map [list \\\\ \\] {
Replace.exe:
	$(CSC) /target:exe $(TOP)\Replace.cs

sqlite3.def:	Replace.exe $(LIBOBJ)
	echo EXPORTS > sqlite3.def
	dumpbin /all $(LIBOBJ) \\
		| .\Replace.exe "^\s+/EXPORT:_?(sqlite3(?:session|changeset|changegroup|rebaser)?_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \\
		| .\Replace.exe "^\s+/EXPORT:_?(sqlite3(?:session|changeset|changegroup|rebaser|rbu)?_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \\
		| sort >> sqlite3.def
}]]

set data "#### DO NOT EDIT ####\n"
append data "# This makefile is automatically "
append data "generated from the [file tail $fromFileName] at\n"
append data "# the root of the canonical SQLite source tree (not the\n"

Changes to tool/mkopcodec.tcl.

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







-
+
+







puts "#else"
puts "# define OpHelp(X)"
puts "#endif"
puts "const char *sqlite3OpcodeName(int i)\173"
puts " static const char *const azName\[\] = \173"
set mx 0

set in [open [lindex $argv 0] rb]
set in [open [lindex $argv 0]]
fconfigure $in -translation binary
while {![eof $in]} {
  set line [gets $in]
  if {[regexp {^#define OP_} $line]} {
    set name [lindex $line 1]
    regsub {^OP_} $name {} name
    set i [lindex $line 2]
    set label($i) $name

Changes to tool/mkopcodeh.tcl.

82
83
84
85
86
87
88

89
90
91
92
93
94
95
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96







+







    set group($name) 0
    set jump($name) 0
    set in1($name) 0
    set in2($name) 0
    set in3($name) 0
    set out2($name) 0
    set out3($name) 0
    set ncycle($name) 0
    for {set i 3} {$i<[llength $line]-1} {incr i} {
       switch [string trim [lindex $line $i] ,] {
         same {
           incr i
           if {[lindex $line $i]=="as"} {
             incr i
             set sym [string trim [lindex $line $i] ,]
103
104
105
106
107
108
109

110
111
112
113
114
115
116
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118







+







         group {set group($name) 1}
         jump  {set jump($name) 1}
         in1   {set in1($name) 1}
         in2   {set in2($name) 1}
         in3   {set in3($name) 1}
         out2  {set out2($name) 1}
         out3  {set out3($name) 1}
         ncycle {set ncycle($name) 1}
       }
    }
    if {$group($name)} {
      set newGroup 0
      if {[info exists groups($nGroup)]} {
        if {$prevName=="" || !$group($prevName)} {
          set newGroup 1
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
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







+





-
+
+
+










-
+
-
-
-
-


-
+













+







foreach name {OP_Noop OP_Explain OP_Abortable} {
  set jump($name) 0
  set in1($name) 0
  set in2($name) 0
  set in3($name) 0
  set out2($name) 0
  set out3($name) 0
  set ncycle($name) 0
  set op($name) -1
  set order($nOp) $name
  incr nOp
}

# The following are the opcodes that are processed by resolveP2Values()
# The following are the opcodes that receive special processing in the
# resolveP2Values() routine.  Update this list whenever new cases are
# added to the pOp->opcode switch within resolveP2Values().
#
set rp2v_ops {
  OP_Transaction
  OP_AutoCommit
  OP_Savepoint
  OP_Checkpoint
  OP_Vacuum
  OP_JournalMode
  OP_VUpdate
  OP_VFilter
  OP_Next
  OP_Init
  OP_NextIfOpen
  OP_SorterNext
  OP_Prev
  OP_PrevIfOpen
}

# Assign small values to opcodes that are processed by resolveP2Values()
# Assign the smallest values to opcodes that are processed by resolveP2Values()
# to make code generation for the switch() statement smaller and faster.
#
set cnt -1
for {set i 0} {$i<$nOp} {incr i} {
  set name $order($i)
  if {[lsearch $rp2v_ops $name]>=0} {
    incr cnt
    while {[info exists used($cnt)]} {incr cnt}
    set op($name) $cnt
    set used($cnt) 1
    set def($cnt) $name
  }
}
set mxCase1 $cnt

# Assign the next group of values to JUMP opcodes
#
for {set i 0} {$i<$nOp} {incr i} {
  set name $order($i)
  if {$op($name)>=0} continue
  if {!$jump($name)} continue
203
204
205
206
207
208
209

210
211

212
213
214
215
216
217
218
205
206
207
208
209
210
211
212
213

214
215
216
217
218
219
220
221







+

-
+







# Generate the numeric values for all remaining opcodes, while
# preserving any groupings of opcodes (i.e. those that must be
# together).
#
for {set g 0} {$g<$nGroup} {incr g} {
  set gLen [llength $groups($g)]
  set ok 0; set start -1
  set seek $cnt
  while {!$ok} {
    set seek $cnt; incr seek
    incr seek
    while {[info exists used($seek)]} {incr seek}
    set ok 1; set start $seek
    for {set j 0} {$j<$gLen} {incr j} {
      incr seek
      if {[info exists used($seek)]} {
        set ok 0; break
      }
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
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







+














+












-
+






  if {[string match OP_NotUsed* $name]==0} {
    if {$jump($name)}  {incr x 1}
    if {$in1($name)}   {incr x 2}
    if {$in2($name)}   {incr x 4}
    if {$in3($name)}   {incr x 8}
    if {$out2($name)}  {incr x 16}
    if {$out3($name)}  {incr x 32}
    if {$ncycle($name)}  {incr x 64}
  }
  set bv($i) $x
}
puts ""
puts "/* Properties such as \"out2\" or \"jump\" that are specified in"
puts "** comments following the \"case\" for each opcode in the vdbe.c"
puts "** are encoded into bitvectors as follows:"
puts "*/"
puts "#define OPFLG_JUMP        0x01  /* jump:  P2 holds jmp target */"
puts "#define OPFLG_IN1         0x02  /* in1:   P1 is an input */"
puts "#define OPFLG_IN2         0x04  /* in2:   P2 is an input */"
puts "#define OPFLG_IN3         0x08  /* in3:   P3 is an input */"
puts "#define OPFLG_OUT2        0x10  /* out2:  P2 is an output */"
puts "#define OPFLG_OUT3        0x20  /* out3:  P3 is an output */"
puts "#define OPFLG_NCYCLE      0x40  /* ncycle:Cycles count against P1 */"
puts "#define OPFLG_INITIALIZER \173\\"
for {set i 0} {$i<=$max} {incr i} {
  if {$i%8==0} {
    puts -nonewline [format "/* %3d */" $i]
  }
  puts -nonewline [format " 0x%02x," $bv($i)]
  if {$i%8==7} {
    puts "\\"
  }
}
puts "\175"
puts ""
puts "/* The sqlite3P2Values() routine is able to run faster if it knows"
puts "/* The resolve3P2Values() routine is able to run faster if it knows"
puts "** the value of the largest JUMP opcode.  The smaller the maximum"
puts "** JUMP opcode the better, so the mkopcodeh.tcl script that"
puts "** generated this include file strives to group all JUMP opcodes"
puts "** together near the beginning of the list."
puts "*/"
puts "#define SQLITE_MX_JUMP_OPCODE  $mxJump  /* Maximum JUMP opcode */"

Changes to tool/mkpragmatab.tcl.

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
37
38
39
40
41
42
43





44
45
46
47
48
49
50







-
-
-
-
-







  IF:   !defined(SQLITE_OMIT_FLAG_PRAGMAS)

  NAME: empty_result_callbacks
  TYPE: FLAG
  ARG:  SQLITE_NullCallback
  IF:   !defined(SQLITE_OMIT_FLAG_PRAGMAS)

  NAME: legacy_file_format
  TYPE: FLAG
  ARG:  SQLITE_LegacyFileFmt
  IF:   !defined(SQLITE_OMIT_FLAG_PRAGMAS)

  NAME: fullfsync
  TYPE: FLAG
  ARG:  SQLITE_FullFSync
  IF:   !defined(SQLITE_OMIT_FLAG_PRAGMAS)

  NAME: checkpoint_fullfsync
  TYPE: FLAG
135
136
137
138
139
140
141





142
143
144
145
146
147
148
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148







+
+
+
+
+







  IF:   !defined(SQLITE_OMIT_FLAG_PRAGMAS)

  NAME: recursive_triggers
  TYPE: FLAG
  ARG:  SQLITE_RecTriggers
  IF:   !defined(SQLITE_OMIT_FLAG_PRAGMAS)

  NAME: trusted_schema
  TYPE: FLAG
  ARG:  SQLITE_TrustedSchema
  IF:   !defined(SQLITE_OMIT_FLAG_PRAGMAS)

  NAME: foreign_keys
  TYPE: FLAG
  ARG:  SQLITE_ForeignKeys
  IF:   !defined(SQLITE_OMIT_FLAG_PRAGMAS)
  IF:   !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)

  NAME: defer_foreign_keys
233
234
235
236
237
238
239






240
241
242
243
244
245
246
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252







+
+
+
+
+
+







  NAME: table_xinfo
  TYPE: TABLE_INFO
  FLAG: NeedSchema Result1 SchemaOpt
  ARG:  1
  COLS: cid name type notnull dflt_value pk hidden
  IF:   !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)

  NAME: table_list
  TYPE: TABLE_LIST
  FLAG: NeedSchema Result1
  COLS: schema name type ncol wr strict
  IF:   !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)

  NAME: stats
  FLAG: NeedSchema Result0 SchemaReq
  COLS: tbl idx wdth hght flgs
  IF:   !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) && defined(SQLITE_DEBUG)

  NAME: index_info
  TYPE: INDEX_INFO
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
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







-
+





-
+

-
+






-
+




-
+












-
+




+
+
+
-
+



+


-
+




-
+








  NAME: index_list
  FLAG: NeedSchema Result1 SchemaOpt
  COLS: seq name unique origin partial
  IF:   !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)

  NAME: database_list
  FLAG: NeedSchema Result0
  FLAG: Result0
  COLS: seq name file
  IF:   !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)

  NAME: function_list
  FLAG: Result0
  COLS: name builtin
  COLS: name builtin type enc narg flags
  IF:   !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
  IF:   defined(SQLITE_INTROSPECTION_PRAGMAS)
  IF:   !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS)

  NAME: module_list
  FLAG: Result0
  COLS: name
  IF:   !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
  IF:   !defined(SQLITE_OMIT_VIRTUALTABLE)
  IF:   defined(SQLITE_INTROSPECTION_PRAGMAS)
  IF:   !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS)

  NAME: pragma_list
  FLAG: Result0
  COLS: name
  IF:   defined(SQLITE_INTROSPECTION_PRAGMAS)
  IF:   !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS)

  NAME: collation_list
  FLAG: Result0
  COLS: seq name
  IF:   !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)

  NAME: foreign_key_list
  FLAG: NeedSchema Result1 SchemaOpt
  COLS: id seq table from to on_update on_delete match
  IF:   !defined(SQLITE_OMIT_FOREIGN_KEY)

  NAME: foreign_key_check
  FLAG: NeedSchema Result0
  FLAG: NeedSchema Result0 Result1 SchemaOpt
  COLS: table rowid parent fkid
  IF:   !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)

  NAME: parser_trace
  TYPE: FLAG
  ARG:  SQLITE_ParserTrace
  IF:   !defined(SQLITE_OMIT_FLAG_PRAGMAS)
  IF:   defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_PARSER_TRACE)
  IF:   defined(SQLITE_DEBUG)

  NAME: case_sensitive_like
  FLAG: NoColumns
  IF:   !defined(SQLITE_OMIT_CASE_SENSITIVE_LIKE_PRAGMA)

  NAME: integrity_check
  FLAG: NeedSchema Result0 Result1
  FLAG: NeedSchema Result0 Result1 SchemaOpt
  IF:   !defined(SQLITE_OMIT_INTEGRITY_CHECK)

  NAME: quick_check
  TYPE: INTEGRITY_CHECK
  FLAG: NeedSchema Result0 Result1
  FLAG: NeedSchema Result0 Result1 SchemaOpt
  IF:   !defined(SQLITE_OMIT_INTEGRITY_CHECK)

  NAME: encoding
  FLAG: Result0 NoColumns1
  IF:   !defined(SQLITE_OMIT_UTF16)

  NAME: schema_version
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
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







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
+




+
+
+


+
+
+







  COLS: timeout

  NAME: lock_status
  FLAG: Result0
  COLS: database status
  IF:   defined(SQLITE_DEBUG) || defined(SQLITE_TEST)

  NAME: key
  TYPE: KEY
  ARG:  0
  IF:   defined(SQLITE_HAS_CODEC)

  NAME: rekey
  TYPE: KEY
  ARG:  1
  IF:   defined(SQLITE_HAS_CODEC)

  NAME: hexkey
  TYPE: HEXKEY
  ARG:  2
  IF:   defined(SQLITE_HAS_CODEC)

  NAME: hexrekey
  TYPE: HEXKEY
  ARG:  3
  IF:   defined(SQLITE_HAS_CODEC)

  NAME: textkey
  TYPE: KEY
  ARG:  4
  IF:   defined(SQLITE_HAS_CODEC)

  NAME: textrekey
  TYPE: KEY
  ARG:  5
  IF:   defined(SQLITE_HAS_CODEC)

  NAME: activate_extensions
  IF:   defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
  IF:   defined(SQLITE_ENABLE_CEROD)

  NAME: soft_heap_limit
  FLAG: Result0

  NAME: hard_heap_limit
  FLAG: Result0

  NAME: threads
  FLAG: Result0

  NAME: analysis_limit
  FLAG: Result0

  NAME: optimize
  FLAG: Result1 NeedSchema

  NAME: legacy_alter_table
  TYPE: FLAG
  ARG:  SQLITE_LegacyAlter
491
492
493
494
495
496
497
498

499
500
501
502
503
504
505
477
478
479
480
481
482
483

484
485
486
487
488
489
490
491







-
+







    error "bad pragma_def line: $line"
  }
}
record_one
set allnames [lsort [array names allbyname]]

# Generate #defines for all pragma type names.  Group the pragmas that are
# omit in default builds (defined(SQLITE_DEBUG) and defined(SQLITE_HAS_CODEC))
# omit in default builds (ex: defined(SQLITE_DEBUG))
# at the end.
#
puts $fd "\n/* The various pragma types */"
set pnum 0
foreach name $allnames {
  set type [lindex $allbyname($name) 0]
  if {[info exists seentype($type)]} continue

Changes to tool/mkshellc.tcl.

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
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













+


















-
+
+


-
-
-
+
+
+

-
+



+



+



+
-
+
+


-
+
+
+








+






#!/usr/bin/tclsh
#
# Run this script to generate the "shell.c" source file from 
# constituent parts.
#
# No arguments are required.  This script determines the location
# of its input files relative to the location of the script itself.
# This script should be tool/mkshellc.tcl.  If the directory holding
# the script is $DIR, then the component parts are located in $DIR/../src
# and $DIR/../ext/misc.
#
set topdir [file dir [file dir [file normal $argv0]]]
set out stdout
fconfigure stdout -translation binary
puts $out {/* DO NOT EDIT!
** This file is automatically generated by the script in the canonical
** SQLite source tree at tool/mkshellc.tcl.  That script combines source
** code from various constituent source files of SQLite into this single
** "shell.c" file used to implement the SQLite command-line shell.
**
** Most of the code found below comes from the "src/shell.c.in" file in
** the canonical SQLite source tree.  That main file contains "INCLUDE"
** lines that specify other files in the canonical source tree that are
** inserted to getnerate this complete program source file.
**
** The code from multiple files is combined into this single "shell.c"
** source file to help make the command-line program easier to compile.
**
** To modify this program, get a copy of the canonical SQLite source tree,
** edit the src/shell.c.in" and/or some of the other files that are included
** by "src/shell.c.in", then rerun the tool/mkshellc.tcl script.
*/}
set in [open $topdir/src/shell.c.in rb]
set in [open $topdir/src/shell.c.in]
fconfigure $in -translation binary
proc omit_redundant_typedefs {line} {
  global typedef_seen
  if {[regexp {^typedef .*;} $line]} {
    if {[info exists typedef_seen($line)]} {
      return "/* $line */"
  if {[regexp {^typedef .*\y([a-zA-Z0-9_]+);} $line all typename]} {
    if {[info exists typedef_seen($typename)]} {
      return "/* [string map {/* // */ //} $line] */"
    }
    set typedef_seen($line) 1
    set typedef_seen($typename) 1
  }
  return $line
}
set iLine 0
while {1} {
  set lx [omit_redundant_typedefs [gets $in]]
  if {[eof $in]} break;
  incr iLine
  if {[regexp {^INCLUDE } $lx]} {
    set cfile [lindex $lx 1]
    puts $out "/************************* Begin $cfile ******************/"
#   puts $out "#line 1 \"$cfile\""
    set in2 [open $topdir/src/$cfile rb]
    set in2 [open $topdir/src/$cfile]
    fconfigure $in2 -translation binary
    while {![eof $in2]} {
      set lx [omit_redundant_typedefs [gets $in2]]
      if {[regexp {^#include "sqlite} $lx]} continue
      if {[regexp {^# *include "sqlite} $lx]} {
        set lx "/* $lx */"
      }
      if {[regexp {^# *include "test_windirent.h"} $lx]} {
        set lx "/* $lx */"
      }
      set lx [string map [list __declspec(dllexport) {}] $lx]
      puts $out $lx
    }
    close $in2
    puts $out "/************************* End $cfile ********************/"
#   puts $out "#line [expr $iLine+1] \"shell.c.in\""
    continue
  }
  puts $out $lx
}
close $in
close $out

Changes to tool/mksourceid.c.

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
536
537
538
539
540
541
542













543
544
545





546
547
548
549
550
551
552







-
-
-
-
-
-
-
-
-
-
-
-
-



-
-
-
-
-








/*
 * blk0() and blk() perform the initial expand.
 * I got the idea of expanding during the round function from SSLeay
 *
 * blk0le() for little-endian and blk0be() for big-endian.
 */
#if __GNUC__ && (defined(__i386__) || defined(__x86_64__))
/*
 * GCC by itself only generates left rotates.  Use right rotates if
 * possible to be kinder to dinky implementations with iterative rotate
 * instructions.
 */
#define SHA_ROT(op, x, k) \
        ({ unsigned int y; asm(op " %1,%0" : "=r" (y) : "I" (k), "0" (x)); y; })
#define rol(x,k) SHA_ROT("roll", x, k)
#define ror(x,k) SHA_ROT("rorl", x, k)

#else
/* Generic C equivalent */
#define SHA_ROT(x,l,r) ((x) << (l) | (x) >> (r))
#define rol(x,k) SHA_ROT(x,k,32-(k))
#define ror(x,k) SHA_ROT(x,32-(k),k)
#endif





#define blk0le(i) (block[i] = (ror(block[i],8)&0xFF00FF00) \
    |(rol(block[i],8)&0x00FF00FF))
#define blk0be(i) block[i]
#define blk(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15] \
    ^block[(i+2)&15]^block[i&15],1))

Changes to tool/mksqlite3c.tcl.

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
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







-
+



+
+
+
+
+
+
+
+
+
+





+



+
+
+


+
+
-
+

-
-
-
+
+
+
+

+
+
+
+
+
+
+
+
+




-
+













+
+
-
+







# For example, the "parse.c" and "parse.h" files to implement the
# the parser are derived from "parse.y" using lemon.  And the
# "keywordhash.h" files is generated by a program named "mkkeywordhash".
#
# After the "tsrc" directory has been created and populated, run
# this script:
#
#      tclsh mksqlite3c.tcl --srcdir $SRC
#      tclsh mksqlite3c.tcl
#
# The amalgamated SQLite code will be written into sqlite3.c
#

set help {Usage: tclsh mksqlite3c.tcl <options>
 where <options> is zero or more of the following with these effects:
   --nostatic     => Do not generate with compile-time modifiable linkage.
   --linemacros=?  => Emit #line directives into output or not. (? = 1 or 0)
   --useapicall   => Prepend functions with SQLITE_APICALL or SQLITE_CDECL.
   --srcdir $SRC  => Specify the directory containing constituent sources.
   --help         => See this.
 The value setting options default to --linemacros=1 and '--srcdir tsrc' .
}

# Begin by reading the "sqlite3.h" header file.  Extract the version number
# from in this file.  The version number is needed to generate the header
# comment of the amalgamation.
#

set addstatic 1
set linemacros 0
set useapicall 0
set enable_recover 0
set srcdir tsrc

for {set i 0} {$i<[llength $argv]} {incr i} {
  set x [lindex $argv $i]
  if {[regexp {^-?-enable-recover$} $x]} {
    set enable_recover 1
  if {[regexp {^-+nostatic$} $x]} {
  } elseif {[regexp {^-?-nostatic$} $x]} {
    set addstatic 0
  } elseif {[regexp {^-+linemacros} $x]} {
    set linemacros 1
  } elseif {[regexp {^-+useapicall} $x]} {
  } elseif {[regexp {^-?-linemacros(?:=([01]))?$} $x ma ulm]} {
    if {$ulm == ""} {set ulm 1}
    set linemacros $ulm
  } elseif {[regexp {^-?-useapicall$} $x]} {
    set useapicall 1
  } elseif {[regexp {^-?-srcdir$} $x]} {
    incr i
    if {$i==[llength $argv]} {
      error "No argument following $x"
    }
    set srcdir [lindex $argv $i]
  } elseif {[regexp {^-?-((help)|\?)$} $x]} {
    puts $help
    exit 0
  } else {
    error "unknown command-line option: $x"
  }
}
set in [open tsrc/sqlite3.h]
set in [open $srcdir/sqlite3.h]
set cnt 0
set VERSION ?????
while {![eof $in]} {
  set line [gets $in]
  if {$line=="" && [eof $in]} break
  incr cnt
  regexp {#define\s+SQLITE_VERSION\s+"(.*)"} $line all VERSION
}
close $in

# Open the output file and write a header comment at the beginning
# of the file.
#
set fname sqlite3.c
if {$enable_recover} { set fname sqlite3r.c }
set out [open sqlite3.c w]
set out [open $fname w]
# Force the output to use unix line endings, even on Windows.
fconfigure $out -translation lf
set today [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S UTC" -gmt 1]
puts $out [subst \
{/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
** version $VERSION.  By combining all the individual C code files into this
83
84
85
86
87
88
89












90
91
92
93
94
95
96
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







+
+
+
+
+
+
+
+
+
+
+
+







#define SQLITE_AMALGAMATION 1}]
if {$addstatic} {
  puts $out \
{#ifndef SQLITE_PRIVATE
# define SQLITE_PRIVATE static
#endif}
}

# Examine the parse.c file.  If it contains lines of the form:
#
#    "#ifndef SQLITE_ENABLE_UPDATE_LIMIT
# 
# then set the SQLITE_UDL_CAPABLE_PARSER flag in the amalgamation.
#
set in [open $srcdir/parse.c]
if {[regexp {ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT} [read $in]]} {
  puts $out "#define SQLITE_UDL_CAPABLE_PARSER 1"
}
close $in

# These are the header files used by SQLite.  The first time any of these
# files are seen in a #include statement in the C code, include the complete
# text of the file in-line.  The file only needs to be included once.
#
foreach hdr {
   btree.h
123
124
125
126
127
128
129

130
131
132
133

134
135
136
137
138
139
140
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182







+




+







   sqliteInt.h
   sqliteLimit.h
   vdbe.h
   vdbeInt.h
   vxworks.h
   wal.h
   whereInt.h
   sqlite3recover.h
} {
  set available_hdr($hdr) 1
}
set available_hdr(sqliteInt.h) 0
set available_hdr(os_common.h) 0
set available_hdr(sqlite3session.h) 0

# These headers should be copied into the amalgamation without modifying any
# of their function declarations or definitions.
set varonly_hdr(sqlite3.h) 1

# These are the functions that accept a variable number of arguments.  They
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
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







-
+












-
+




-
-
+
-

-
+








# Read the source file named $filename and write it into the
# sqlite3.c output file.  If any #include statements are seen,
# process them appropriately.
#
proc copy_file {filename} {
  global seen_hdr available_hdr varonly_hdr cdecllist out
  global addstatic linemacros useapicall
  global addstatic linemacros useapicall srcdir
  set ln 0
  set tail [file tail $filename]
  section_comment "Begin file $tail"
  if {$linemacros} {puts $out "#line 1 \"$filename\""}
  set in [open $filename r]
  set varpattern {^[a-zA-Z][a-zA-Z_0-9 *]+(sqlite3[_a-zA-Z0-9]+)(\[|;| =)}
  set declpattern {([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3[_a-zA-Z0-9]+)(\(.*)}
  if {[file extension $filename]==".h"} {
    set declpattern " *$declpattern"
  }
  set declpattern ^$declpattern\$
  while {![eof $in]} {
    set line [gets $in]
    set line [string trimright [gets $in]]
    incr ln
    if {[regexp {^\s*#\s*include\s+["<]([^">]+)[">]} $line all hdr]} {
      if {[info exists available_hdr($hdr)]} {
        if {$available_hdr($hdr)} {
          if {$hdr!="os_common.h" && $hdr!="hwtime.h"} {
            set available_hdr($hdr) 0
          set available_hdr($hdr) 0
          }
          section_comment "Include $hdr in the middle of $tail"
          copy_file tsrc/$hdr
          copy_file $srcdir/$hdr
          section_comment "Continuing where we left off in $tail"
          if {$linemacros} {puts $out "#line [expr {$ln+1}] \"$filename\""}
        } else {
          # Comment out the entire line, replacing any nested comment
          # begin/end markers with the harmless substring "**".
          puts $out "/* [string map [list /* ** */ **] $line] */"
        }
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
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







-
+













-
+
+







            if {[lsearch -exact $cdecllist $funcname] >= 0} {
              append line SQLITE_CDECL " "
            } else {
              append line SQLITE_APICALL " "
            }
          }
          append line $funcname $rest
          if {$funcname=="sqlite3_sourceid" && !$linemacros} {
          if {$funcname=="sqlite3_sourceid"} {
            # The sqlite3_sourceid() routine is synthesized at the end of
            # the amalgamation
            puts $out "/* $line */"
          } else {
            puts $out $line
          }
        } else {
          puts $out "SQLITE_PRIVATE $line"
        }
      } elseif {[regexp $varpattern $line all varname]} {
          # Add the SQLITE_PRIVATE before variable declarations or
          # definitions for internal use
          regsub {^SQLITE_API } $line {} line
          if {![regexp {^sqlite3_} $varname]} {
          if {![regexp {^sqlite3_} $varname]
              && ![regexp {^sqlite3Show[A-Z]} $varname]} {
            regsub {^extern } $line {} line
            puts $out "SQLITE_PRIVATE $line"
          } else {
            if {[regexp {const char sqlite3_version\[\];} $line]} {
              set line {const char sqlite3_version[] = SQLITE_VERSION;}
            }
            regsub {^SQLITE_EXTERN } $line {} line
286
287
288
289
290
291
292
293

294
295


296
297
298
299
300
301
302
327
328
329
330
331
332
333

334

335
336
337
338
339
340
341
342
343
344







-
+
-

+
+







}


# Process the source files.  Process files containing commonly
# used subroutines first in order to help the compiler find
# inlining opportunities.
#
foreach file {
set flist {
   ctime.c
   sqliteInt.h
   os_common.h
   ctime.c

   global.c
   status.c
   date.c
   os.c

   fault.c
315
316
317
318
319
320
321

322
323
324
325
326
327
328
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371







+







   random.c
   threads.c
   utf.c
   util.c
   hash.c
   opcodes.c

   os_kv.c
   os_unix.c
   os_win.c
   memdb.c

   bitvec.c
   pcache.c
   pcache1.c
337
338
339
340
341
342
343

344
345
346
347
348
349
350
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394







+







   vdbemem.c
   vdbeaux.c
   vdbeapi.c
   vdbetrace.c
   vdbe.c
   vdbeblob.c
   vdbesort.c
   vdbevtab.c
   memjournal.c

   walker.c
   resolve.c
   expr.c
   alter.c
   analyze.c
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
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







-
+









-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
-
-
-
-
-
+
+
-
-
+
-
-
-
-
-
+

-
+




   fts3_tokenizer1.c
   fts3_tokenize_vtab.c
   fts3_write.c
   fts3_snippet.c
   fts3_unicode.c
   fts3_unicode2.c

   json1.c
   json.c
   rtree.c
   icu.c
   fts3_icu.c
   sqlite3rbu.c
   dbstat.c
   dbpage.c
   sqlite3session.c
   fts5.c
   stmt.c
} {
  copy_file tsrc/$file
}

} 
if {$enable_recover} {
  lappend flist sqlite3recover.c dbdata.c
}
# Synthesize an alternative sqlite3_sourceid() implementation that
# that tries to detects changes in the amalgamation source text
# and modify returns a modified source-id if changes are detected.
#
# The only detection mechanism we have is the __LINE__ macro.  So only
# edits that changes the number of lines of source code are detected.
#
if {!$linemacros} {
  flush $out
foreach file $flist {
  set in2 [open sqlite3.c]
  set cnt 0
  set oldsrcid {}
  while {![eof $in2]} {
  copy_file $srcdir/$file
    incr cnt
    gets $in2 line
    if {[regexp {^#define SQLITE_SOURCE_ID } $line]} {set oldsrcid $line}
  }
  close $in2
}

  regsub {[0-9a-flt]{4}"} $oldsrcid {alt2"} oldsrcid
  puts $out \
puts $out \
"#if __LINE__!=[expr {$cnt+0}]
#undef SQLITE_SOURCE_ID
$oldsrcid
#endif
/* Return the source-id for this library */
"/* Return the source-id for this library */
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }"
}

puts $out \
"/************************** End of sqlite3.c ******************************/"

close $out

Changes to tool/mksqlite3h.tcl.

35
36
37
38
39
40
41




42
43
44



45
46
47
48
49
50
51
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58







+
+
+
+



+
+
+







# Get the source tree root directory from the command-line
#
set TOP [lindex $argv 0]

# Enable use of SQLITE_APICALL macros at the right points?
#
set useapicall 0

# Include sqlite3recover.h?
#
set enable_recover 0

if {[lsearch -regexp [lrange $argv 1 end] {^-+useapicall}] != -1} {
  set useapicall 1
}
if {[lsearch -regexp [lrange $argv 1 end] {^-+enable-recover}] != -1} {
  set enable_recover 1
}

# Get the SQLite version number (ex: 3.6.18) from the $TOP/VERSION file.
#
set in [open $TOP/VERSION]
set zVersion [string trim [read $in]]
close $in
80
81
82
83
84
85
86



87
88
89
90
91
92
93
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103







+
+
+








set filelist [subst {
  $TOP/src/sqlite.h.in
  $TOP/ext/rtree/sqlite3rtree.h
  $TOP/ext/session/sqlite3session.h
  $TOP/ext/fts5/fts5.h
}]
if {$enable_recover} {
  lappend filelist "$TOP/ext/recover/sqlite3recover.h"
}

# These are the functions that accept a variable number of arguments.  They
# always need to use the "cdecl" calling convention even when another calling
# convention (e.g. "stcall") is being used for the rest of the library.
set cdecllist {
  sqlite3_config
  sqlite3_db_config
103
104
105
106
107
108
109
110

111
112
113
114
115
116
117
113
114
115
116
117
118
119

120
121
122
123
124
125
126
127







-
+







foreach file $filelist {
  set in [open $file]
  if {![regexp {sqlite\.h\.in} $file]} {
    puts "/******** Begin file [file tail $file] *********/"
  }
  while {![eof $in]} {

    set line [gets $in]
    set line [string trimright [gets $in]]

    # File sqlite3rtree.h contains a line "#include <sqlite3.h>". Omit this
    # line when copying sqlite3rtree.h into sqlite3.h.
    #
    if {[string match {*#include*[<"]sqlite3.h[>"]*} $line]} continue

    regsub -- --VERS--           $line $zVersion line

Changes to tool/offsets.c.

71
72
73
74
75
76
77
78

79
80
81
82
83
84
85
71
72
73
74
75
76
77

78
79
80
81
82
83
84
85







-
+







  int rc;
  if( p->zErr ) return;
  rc = sqlite3_open(zFile, &db);
  if( rc ){
    ofstError(p, "cannot open database file \"%s\"", zFile);
    goto rootAndColumn_exit;
  }
  zSql = sqlite3_mprintf("SELECT rootpage FROM sqlite_master WHERE name=%Q",
  zSql = sqlite3_mprintf("SELECT rootpage FROM sqlite_schema WHERE name=%Q",
                         zTable);
  rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
  if( rc ) ofstError(p, "%s: [%s]", sqlite3_errmsg(db), zSql);
  sqlite3_free(zSql);
  if( p->zErr ) goto rootAndColumn_exit;
  if( sqlite3_step(pStmt)!=SQLITE_ROW ){
    ofstError(p, "cannot find table [%s]\n", zTable);

Added tool/omittest-msvc.tcl.




































































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# Run this TCL script in order to build using MSVC multiple times
# with various compile-time options.  Use this to verify that the various
# compile-time options all work with MSVC.
#
set OPTIONS [list \
  SQLITE_ALLOW_ROWID_IN_VIEW \
  SQLITE_ENABLE_COLUMN_METADATA \
  SQLITE_ENABLE_EXPENSIVE_ASSERT \
  SQLITE_ENABLE_IOTRACE \
  SQLITE_ENABLE_MEMORY_MANAGEMENT \
  SQLITE_ENABLE_MEMSYS3 \
  SQLITE_ENABLE_MEMSYS5 \
  SQLITE_ENABLE_OVERSIZE_CELL_CHECK \
  SQLITE_ENABLE_UNLOCK_NOTIFY \
  SQLITE_ENABLE_UPDATE_DELETE_LIMIT \
  SQLITE_OMIT_ALTERTABLE-x \
  SQLITE_OMIT_ATTACH-x \
  SQLITE_OMIT_AUTHORIZATION \
  SQLITE_OMIT_AUTOINCREMENT \
  SQLITE_OMIT_AUTOINIT \
  SQLITE_OMIT_AUTOMATIC_INDEX \
  SQLITE_OMIT_AUTORESET \
  SQLITE_OMIT_AUTOVACUUM \
  SQLITE_OMIT_BETWEEN_OPTIMIZATION \
  SQLITE_OMIT_BLOB_LITERAL \
  SQLITE_OMIT_BTREECOUNT \
  SQLITE_OMIT_CASE_SENSITIVE_LIKE_PRAGMA \
  SQLITE_OMIT_CAST \
  SQLITE_OMIT_CHECK \
  SQLITE_OMIT_COMPILEOPTION_DIAGS \
  SQLITE_OMIT_COMPLETE \
  SQLITE_OMIT_COMPOUND_SELECT \
  SQLITE_OMIT_CONFLICT_CLAUSE \
  SQLITE_OMIT_CTE \
  SQLITE_OMIT_DATETIME_FUNCS \
  SQLITE_OMIT_DECLTYPE \
  SQLITE_OMIT_DEPRECATED \
  SQLITE_OMIT_DESERIALIZE \
  SQLITE_OMIT_DISKIO-x \
  SQLITE_OMIT_EXPLAIN-x \
  SQLITE_OMIT_FLAG_PRAGMAS \
  SQLITE_OMIT_FLOATING_POINT \
  SQLITE_OMIT_FOREIGN_KEY \
  SQLITE_OMIT_GENERATED_COLUMNS \
  SQLITE_OMIT_GET_TABLE \
  SQLITE_OMIT_HEX_INTEGER \
  SQLITE_OMIT_INCRBLOB-x \
  SQLITE_OMIT_INTEGRITY_CHECK \
  SQLITE_OMIT_INTROSPECTION_PRAGMAS \
  SQLITE_OMIT_JSON \
  SQLITE_OMIT_LIKE_OPTIMIZATION \
  SQLITE_OMIT_LOAD_EXTENSION \
  SQLITE_OMIT_LOCALTIME \
  SQLITE_OMIT_LOOKASIDE \
  SQLITE_OMIT_MEMORYDB \
  SQLITE_OMIT_OR_OPTIMIZATION \
  SQLITE_OMIT_PAGER_PRAGMAS-x \
  SQLITE_OMIT_PARSER_TRACE \
  SQLITE_OMIT_POPEN \
  SQLITE_OMIT_PRAGMA-x \
  SQLITE_OMIT_PROGRESS_CALLBACK \
  SQLITE_OMIT_QUICKBALANCE \
  SQLITE_OMIT_RANDOMNESS \
  SQLITE_OMIT_REINDEX-x \
  SQLITE_OMIT_SCHEMA_PRAGMAS \
  SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS \
  SQLITE_OMIT_SHARED_CACHE \
  SQLITE_OMIT_SHUTDOWN_DIRECTORIES \
  SQLITE_OMIT_SUBQUERY-x \
  SQLITE_OMIT_TCL_VARIABLE \
  SQLITE_OMIT_TEMPDB \
  SQLITE_OMIT_TEST_CONTROL \
  SQLITE_OMIT_TRACE \
  SQLITE_OMIT_TRIGGER \
  SQLITE_OMIT_TRUNCATE_OPTIMIZATION \
  SQLITE_OMIT_UPSERT \
  SQLITE_OMIT_UTF16 \
  SQLITE_OMIT_VACUUM-x \
  SQLITE_OMIT_VIEW-x \
  SQLITE_OMIT_VIRTUALTABLE-x \
  SQLITE_OMIT_WAL \
  SQLITE_OMIT_WINDOWFUNC-x \
  SQLITE_OMIT_WSD \
  SQLITE_OMIT_XFER_OPT \
]
set start [lindex $argv 0]
foreach opt $OPTIONS {
  if {[regexp x $opt]} continue
  if {[string compare $opt $start]<0} continue
  exec fossil clean -x
  set cmd "nmake /f Makefile.msc USE_FULLWARN=0 OPTIMIZATIONS=0"
  append cmd " CCOPTS=-D$opt"
  puts $cmd
  set res [catch {eval exec $cmd} outtxt]
  if {[regexp {sqlite3.c.\d+.: error} $outtxt]} {
    puts "FAILED:\n$outtxt"
    exit
  }
}

Changes to tool/omittest.tcl.

94
95
96
97
98
99
100
101

102
103
104
105
106
107
108
94
95
96
97
98
99
100

101
102
103
104
105
106
107
108







-
+







  if {![file exists $sqlite3_dummy]} {
    set wr [open $sqlite3_dummy w]
    puts $wr "dummy"
    close $wr
  }

  if {$::SKIP_RUN} {
      puts "Skip testing $dir."
    #  puts "Skip testing $dir."
  } else {
    # Run the test suite.
    puts -nonewline "Testing $dir..."
    flush stdout
    set rc [catch {
      exec $::MAKEBIN -C $dir -f makefile test >& $dir/test.log
    }]
123
124
125
126
127
128
129
130

131
132
133
134
135
136
137
123
124
125
126
127
128
129

130
131
132
133
134
135
136
137







-
+







proc process_options {argv} {
  set ::MAKEBIN make                        ;# Default value
  if {$::tcl_platform(platform)=="windows"} {
    set ::MAKEFILE ./Makefile               ;# Default value on Windows
  } else {
    set ::MAKEFILE ./Makefile.linux-gcc     ;# Default value
  }
  set ::SKIP_RUN 0                          ;# Default to attempt test
  set ::SKIP_RUN 1                          ;# Default to attempt test
  set ::TARGET testfixture                  ;# Default thing to build

  for {set i 0} {$i < [llength $argv]} {incr i} {
    switch -regexp -- [lindex $argv $i] {
      -{1,2}makefile {
        incr i
        set ::MAKEFILE [lindex $argv $i]
146
147
148
149
150
151
152



153
154
155
156
157
158
159
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162







+
+
+







        incr i
        set ::TARGET [lindex $argv $i]
      }

      -{1,2}skip_run {
        set ::SKIP_RUN 1
      }
      -{1,2}run {
        set ::SKIP_RUN 0
      }

      -{1,2}help {
        puts $::USAGE_MESSAGE
        exit
      }

      -.* {
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
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







-
+





+




+
+




+

+


+
+







+
+



+




+



+



-
+





+





+







    SQLITE_OMIT_AUTOINIT \
    SQLITE_OMIT_AUTOMATIC_INDEX \
    SQLITE_OMIT_AUTORESET \
    SQLITE_OMIT_AUTOVACUUM \
    SQLITE_OMIT_BETWEEN_OPTIMIZATION \
    SQLITE_OMIT_BLOB_LITERAL \
    SQLITE_OMIT_BTREECOUNT \
    SQLITE_OMIT_BUILTIN_TEST \
    SQLITE_OMIT_CASE_SENSITIVE_LIKE_PRAGMA \
    SQLITE_OMIT_CAST \
    SQLITE_OMIT_CHECK \
    SQLITE_OMIT_COMPILEOPTION_DIAGS \
    SQLITE_OMIT_COMPLETE \
    SQLITE_OMIT_COMPOUND_SELECT \
    SQLITE_OMIT_CONFLICT_CLAUSE \
    SQLITE_OMIT_CTE \
    SQLITE_OMIT_DATETIME_FUNCS \
    SQLITE_OMIT_DECLTYPE \
    SQLITE_OMIT_DEPRECATED \
    SQLITE_OMIT_DESERIALIZE \
    SQLITE_OMIT_DISKIO \
    SQLITE_OMIT_EXPLAIN \
    SQLITE_OMIT_FLAG_PRAGMAS \
    SQLITE_OMIT_FLOATING_POINT \
    SQLITE_OMIT_FOREIGN_KEY \
    SQLITE_OMIT_GENERATED_COLUMNS \
    SQLITE_OMIT_GET_TABLE \
    SQLITE_OMIT_HEX_INTEGER \
    SQLITE_OMIT_INCRBLOB \
    SQLITE_OMIT_INTEGRITY_CHECK \
    SQLITE_OMIT_INTROSPECTION_PRAGMAS \
    SQLITE_OMIT_JSON \
    SQLITE_OMIT_LIKE_OPTIMIZATION \
    SQLITE_OMIT_LOAD_EXTENSION \
    SQLITE_OMIT_LOCALTIME \
    SQLITE_OMIT_LOOKASIDE \
    SQLITE_OMIT_MEMORYDB \
    SQLITE_OMIT_OR_OPTIMIZATION \
    SQLITE_OMIT_PAGER_PRAGMAS \
    SQLITE_OMIT_PARSER_TRACE \
    SQLITE_OMIT_POPEN \
    SQLITE_OMIT_PRAGMA \
    SQLITE_OMIT_PROGRESS_CALLBACK \
    SQLITE_OMIT_QUICKBALANCE \
    SQLITE_OMIT_RANDOMNESS \
    SQLITE_OMIT_REINDEX \
    SQLITE_OMIT_SCHEMA_PRAGMAS \
    SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS \
    SQLITE_OMIT_SHARED_CACHE \
    SQLITE_OMIT_SHUTDOWN_DIRECTORIES \
    SQLITE_OMIT_SUBQUERY \
    SQLITE_OMIT_TCL_VARIABLE \
    SQLITE_OMIT_TEMPDB \
    SQLITE_OMIT_TEST_CONTROL \
    SQLITE_OMIT_TRACE \
    SQLITE_OMIT_TRIGGER \
    SQLITE_OMIT_TRUNCATE_OPTIMIZATION \
    SQLITE_OMIT_UNIQUE_ENFORCEMENT \
    SQLITE_OMIT_UPSERT \
    SQLITE_OMIT_UTF16 \
    SQLITE_OMIT_VACUUM \
    SQLITE_OMIT_VIEW \
    SQLITE_OMIT_VIRTUALTABLE \
    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/replace.tcl.

1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19











-
+







#!/usr/bin/tcl
#
# Replace string with another string -OR- include
# only lines successfully modified with a regular
# expression.
#
fconfigure stdout -translation binary -encoding binary
fconfigure stderr -translation binary -encoding binary
set mode [string tolower [lindex $argv 0]]
set from [lindex $argv 1]
set to [lindex $argv 2]
if {$mode ni [list exact regsub include]} {exit 1}
if {-1 == [lsearch -exact [list exact regsub include] $mode]} {exit 1}
if {[string length $from]==0} {exit 2}
while {![eof stdin]} {
  set line [gets stdin]
  if {[eof stdin]} break
  switch -exact $mode {
    exact {set line [string map [list $from $to] $line]}
    regsub {regsub -all -- $from $line $to line}

Changes to tool/showdb.c.

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
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







+
+
+
+

+

-
+

-
+





-
-
-
-




















-
+







#endif

#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "sqlite3.h"

typedef unsigned char u8;         /* unsigned 8-bit */
typedef unsigned int u32;         /* unsigned 32-bit */
typedef sqlite3_int64 i64;        /* signed 64-bit */
typedef sqlite3_uint64 u64;       /* unsigned 64-bit */


static struct GlobalData {
  int pagesize;                   /* Size of a database page */
  u32 pagesize;                   /* Size of a database page */
  int dbfd;                       /* File descriptor for reading the DB */
  int mxPage;                     /* Last page number */
  u32 mxPage;                     /* Last page number */
  int perLine;                    /* HEX elements to print per line */
  int bRaw;                       /* True to access db file via OS APIs */
  sqlite3_file *pFd;              /* File descriptor for non-raw mode */
  sqlite3 *pDb;                   /* Database handle that owns pFd */
} g = {1024, -1, 0, 16,   0, 0, 0};


typedef long long int i64;      /* Datatype for 64-bit integers */


/*
** Convert the var-int format into i64.  Return the number of bytes
** in the var-int.  Write the var-int value into *pVal.
*/
static int decodeVarint(const unsigned char *z, i64 *pVal){
  i64 v = 0;
  int i;
  for(i=0; i<8; i++){
    v = (v<<7) + (z[i]&0x7f);
    if( (z[i]&0x80)==0 ){ *pVal = v; return i+1; }
  }
  v = (v<<8) + (z[i]&0xff);
  *pVal = v;
  return 9;
}

/*
** Extract a big-endian 32-bit integer
*/
static unsigned int decodeInt32(const unsigned char *z){
static u32 decodeInt32(const u8 *z){
  return (z[0]<<24) + (z[1]<<16) + (z[2]<<8) + z[3];
}

/* Report an out-of-memory error and die.
*/
static void out_of_memory(void){
  fprintf(stderr,"Out of memory...\n");
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
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







-
+



















-
-
+
+







**
** Space to hold the content is obtained from sqlite3_malloc() and needs 
** to be freed by the caller.
*/
static unsigned char *fileRead(sqlite3_int64 ofst, int nByte){
  unsigned char *aData;
  int got;
  aData = sqlite3_malloc(nByte+32);
  aData = sqlite3_malloc64(32+(i64)nByte);
  if( aData==0 ) out_of_memory();
  memset(aData, 0, nByte+32);
  if( g.bRaw==0 ){
    int rc = g.pFd->pMethods->xRead(g.pFd, (void*)aData, nByte, ofst);
    if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){
      fprintf(stderr, "error in xRead() - %d\n", rc);
      exit(1);
    }
  }else{
    lseek(g.dbfd, (long)ofst, SEEK_SET);
    got = read(g.dbfd, aData, nByte);
    if( got>0 && got<nByte ) memset(aData+got, 0, nByte-got);
  }
  return aData;
}

/*
** Return the size of the file in byte.
*/
static sqlite3_int64 fileGetsize(void){
  sqlite3_int64 res = 0;
static i64 fileGetsize(void){
  i64 res = 0;
  if( g.bRaw==0 ){
    int rc = g.pFd->pMethods->xFileSize(g.pFd, &res);
    if( rc!=SQLITE_OK ){
      fprintf(stderr, "error in xFileSize() - %d\n", rc);
      exit(1);
    }
  }else{
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
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







-
-
-
+
+
+



















+
+
+
+
+
+







** End of low-level file access functions.
**************************************************************************/

/*
** Print a range of bytes as hex and as ascii.
*/
static unsigned char *print_byte_range(
  int ofst,          /* First byte in the range of bytes to print */
  int nByte,         /* Number of bytes to print */
  int printOfst      /* Add this amount to the index on the left column */
  sqlite3_int64 ofst,  /* First byte in the range of bytes to print */
  int nByte,           /* Number of bytes to print */
  int printOfst        /* Add this amount to the index on the left column */
){
  unsigned char *aData;
  int i, j;
  const char *zOfstFmt;

  if( ((printOfst+nByte)&~0xfff)==0 ){
    zOfstFmt = " %03x: ";
  }else if( ((printOfst+nByte)&~0xffff)==0 ){
    zOfstFmt = " %04x: ";
  }else if( ((printOfst+nByte)&~0xfffff)==0 ){
    zOfstFmt = " %05x: ";
  }else if( ((printOfst+nByte)&~0xffffff)==0 ){
    zOfstFmt = " %06x: ";
  }else{
    zOfstFmt = " %08x: ";
  }

  aData = fileRead(ofst, nByte);
  for(i=0; i<nByte; i += g.perLine){
    int go = 0;
    for(j=0; j<g.perLine; j++){
      if( i+j>nByte ){ break; }
      if( aData[i+j] ){ go = 1; break; }
    }
    if( !go && i>0 && i+g.perLine<nByte ) continue;
    fprintf(stdout, zOfstFmt, i+printOfst);
    for(j=0; j<g.perLine; j++){
      if( i+j>nByte ){
        fprintf(stdout, "   ");
      }else{
        fprintf(stdout,"%02x ", aData[i+j]);
      }
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
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







-
-
+
+

-
-
+
+






-
+







-
+












-
+







  }
  return aData;
}

/*
** Print an entire page of content as hex
*/
static void print_page(int iPg){
  int iStart;
static void print_page(u32 iPg){
  i64 iStart;
  unsigned char *aData;
  iStart = (iPg-1)*g.pagesize;
  fprintf(stdout, "Page %d:   (offsets 0x%x..0x%x)\n",
  iStart = ((i64)(iPg-1))*g.pagesize;
  fprintf(stdout, "Page %u:   (offsets 0x%llx..0x%llx)\n",
          iPg, iStart, iStart+g.pagesize-1);
  aData = print_byte_range(iStart, g.pagesize, 0);
  sqlite3_free(aData);
}


/* Print a line of decode output showing a 4-byte integer.
/* Print a line of decoded output showing a 4-byte unsigned integer.
*/
static void print_decode_line(
  unsigned char *aData,      /* Content being decoded */
  int ofst, int nByte,       /* Start and size of decode */
  const char *zMsg           /* Message to append */
){
  int i, j;
  int val = aData[ofst];
  u32 val = aData[ofst];
  char zBuf[100];
  sprintf(zBuf, " %03x: %02x", ofst, aData[ofst]);
  i = (int)strlen(zBuf);
  for(j=1; j<4; j++){
    if( j>=nByte ){
      sprintf(&zBuf[i], "   ");
    }else{
      sprintf(&zBuf[i], " %02x", aData[ofst+j]);
      val = val*256 + aData[ofst+j];
    }
    i += (int)strlen(&zBuf[i]);
  }
  sprintf(&zBuf[i], "   %9d", val);
  sprintf(&zBuf[i], "   %10u", val);
  printf("%s  %s\n", zBuf, zMsg);
}

/*
** Decode the database header.
*/
static void print_db_header(void){
292
293
294
295
296
297
298

299
300
301
302
303
304
305
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313







+







  print_decode_line(aData, 72, 4, "meta[8]");
  print_decode_line(aData, 76, 4, "meta[9]");
  print_decode_line(aData, 80, 4, "meta[10]");
  print_decode_line(aData, 84, 4, "meta[11]");
  print_decode_line(aData, 88, 4, "meta[12]");
  print_decode_line(aData, 92, 4, "Change counter for version number");
  print_decode_line(aData, 96, 4, "SQLite version number");
  sqlite3_free(aData);
}

/*
** Describe cell content.
*/
static i64 describeContent(
  unsigned char *a,       /* Cell content */
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
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







-
+









-
+




















-
+


-
+







  unsigned char *a,       /* Cell content */
  int showCellContent,    /* Show cell content if true */
  char **pzDesc           /* Store description here */
){
  int i;
  i64 nDesc = 0;
  int n = 0;
  int leftChild;
  u32 leftChild;
  i64 nPayload;
  i64 rowid;
  i64 nLocal;
  static char zDesc[1000];
  i = 0;
  if( cType<=5 ){
    leftChild = ((a[0]*256 + a[1])*256 + a[2])*256 + a[3];
    a += 4;
    n += 4;
    sprintf(zDesc, "lx: %d ", leftChild);
    sprintf(zDesc, "lx: %u ", leftChild);
    nDesc = strlen(zDesc);
  }
  if( cType!=5 ){
    i = decodeVarint(a, &nPayload);
    a += i;
    n += i;
    sprintf(&zDesc[nDesc], "n: %lld ", nPayload);
    nDesc += strlen(&zDesc[nDesc]);
    nLocal = localPayload(nPayload, cType);
  }else{
    nPayload = nLocal = 0;
  }
  if( cType==5 || cType==13 ){
    i = decodeVarint(a, &rowid);
    a += i;
    n += i;
    sprintf(&zDesc[nDesc], "r: %lld ", rowid);
    nDesc += strlen(&zDesc[nDesc]);
  }
  if( nLocal<nPayload ){
    int ovfl;
    u32 ovfl;
    unsigned char *b = &a[nLocal];
    ovfl = ((b[0]*256 + b[1])*256 + b[2])*256 + b[3];
    sprintf(&zDesc[nDesc], "ov: %d ", ovfl);
    sprintf(&zDesc[nDesc], "ov: %u ", ovfl);
    nDesc += strlen(&zDesc[nDesc]);
    n += 4;
  }
  if( showCellContent && cType!=5 ){
    nDesc += describeContent(a, nLocal, &zDesc[nDesc-1]);
  }
  *pzDesc = zDesc;
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
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







-
+


















-
+







  unsigned char *a,       /* Page content (without the page-1 header) */
  unsigned pgno,          /* Page number */
  int iCell,              /* Cell index */
  int szPgHdr,            /* Size of the page header.  0 or 100 */
  int ofst                /* Cell begins at a[ofst] */
){
  int i, j = 0;
  int leftChild;
  u32 leftChild;
  i64 k;
  i64 nPayload;
  i64 rowid;
  i64 nHdr;
  i64 iType;
  i64 nLocal;
  unsigned char *x = a + ofst;
  unsigned char *end;
  unsigned char cType = a[0];
  int nCol = 0;
  int szCol[2000];
  int ofstCol[2000];
  int typeCol[2000];

  printf("Cell[%d]:\n", iCell);
  if( cType<=5 ){
    leftChild = ((x[0]*256 + x[1])*256 + x[2])*256 + x[3];
    printBytes(a, x, 4);
    printf("left child page:: %d\n", leftChild);
    printf("left child page:: %u\n", leftChild);
    x += 4;
  }
  if( cType!=5 ){
    i = decodeVarint(x, &nPayload);
    printBytes(a, x, i);
    nLocal = localPayload(nPayload, cType);
    if( nLocal==nPayload ){
618
619
620
621
622
623
624
625

626
627
628
629
630
631
632
626
627
628
629
630
631
632

633
634
635
636
637
638
639
640







-
+







  }
  if( j<nLocal ){
    printBytes(a, x+j, 0);
    printf("... %lld bytes of content ...\n", nLocal-j);
  }
  if( nLocal<nPayload ){
    printBytes(a, x+nLocal, 4);
    printf("overflow-page: %d\n", decodeInt32(x+nLocal));
    printf("overflow-page: %u\n", decodeInt32(x+nLocal));
  }
}


/*
** Decode a btree page
*/
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
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
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
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







-
+










-
+



-
+
+







-
-
-
-
+
+
+
+









-
+













-
+







-
+



















-
+







      printf(" %03x: cell[%d] %s\n", cofst, i, zDesc);
    }else if( cellToDecode==(-1) || cellToDecode==i ){
      decodeCell(a, pgno, i, hdrSize, cofst-hdrSize);
    }
  }
  if( showMap ){
    printf("Page map:  (H=header P=cell-index 1=page-1-header .=free-space)\n");
    for(i=0; i<g.pagesize; i+=64){
    for(i=0; (u32)i<g.pagesize; i+=64){
      printf(" %03x: %.64s\n", i, &zMap[i]);
    }
    sqlite3_free(zMap);
  }
}

/*
** Decode a freelist trunk page.
*/
static void decode_trunk_page(
  int pgno,             /* The page number */
  u32 pgno,             /* The page number */
  int detail,           /* Show leaf pages if true */
  int recursive         /* Follow the trunk change if true */
){
  int n, i;
  u32 i;
  u32 n;
  unsigned char *a;
  while( pgno>0 ){
    a = fileRead((pgno-1)*g.pagesize, g.pagesize);
    printf("Decode of freelist trunk page %d:\n", pgno);
    print_decode_line(a, 0, 4, "Next freelist trunk page");
    print_decode_line(a, 4, 4, "Number of entries on this page");
    if( detail ){
      n = (int)decodeInt32(&a[4]);
      for(i=0; i<n; i++){
        unsigned int x = decodeInt32(&a[8+4*i]);
        char zIdx[10];
      n = decodeInt32(&a[4]);
      for(i=0; i<n && i<g.pagesize/4; i++){
        u32 x = decodeInt32(&a[8+4*i]);
        char zIdx[13];
        sprintf(zIdx, "[%d]", i);
        printf("  %5s %7u", zIdx, x);
        if( i%5==4 ) printf("\n");
      }
      if( i%5!=0 ) printf("\n");
    }
    if( !recursive ){
      pgno = 0;
    }else{
      pgno = (int)decodeInt32(&a[0]);
      pgno = decodeInt32(&a[0]);
    }
    sqlite3_free(a);
  }
}

/*
** A short text comment on the use of each page.
*/
static char **zPageUse;

/*
** Add a comment on the use of a page.
*/
static void page_usage_msg(int pgno, const char *zFormat, ...){
static void page_usage_msg(u32 pgno, const char *zFormat, ...){
  va_list ap;
  char *zMsg;

  va_start(ap, zFormat);
  zMsg = sqlite3_vmprintf(zFormat, ap);
  va_end(ap);
  if( pgno<=0 || pgno>g.mxPage ){
    printf("ERROR: page %d out of range 1..%d: %s\n",
    printf("ERROR: page %d out of range 1..%u: %s\n",
            pgno, g.mxPage, zMsg);
    sqlite3_free(zMsg);
    return;
  }
  if( zPageUse[pgno]!=0 ){
    printf("ERROR: page %d used multiple times:\n", pgno);
    printf("ERROR:    previous: %s\n", zPageUse[pgno]);
    printf("ERROR:    current:  %s\n", zMsg);
    sqlite3_free(zPageUse[pgno]);
  }
  zPageUse[pgno] = zMsg;
}

/*
** Find overflow pages of a cell and describe their usage.
*/
static void page_usage_cell(
  unsigned char cType,    /* Page type */
  unsigned char *a,       /* Cell content */
  int pgno,               /* page containing the cell */
  u32 pgno,               /* page containing the cell */
  int cellno              /* Index of the cell on the page */
){
  int i;
  int n = 0;
  i64 nPayload;
  i64 rowid;
  i64 nLocal;
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
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
900
901
902
903
904
905
906
907
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







-
-
+
+

-
+

-
+






+
+
+
+
+
+
-
+
+
+

-
+
+
+
+


-
+









+




+
+
+
+
+
+
+
+
+
+




+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+

-


-
+

+
-
+

-
-
+
+
+
+
+
+
+
+
+
+







  }
  if( cType==5 || cType==13 ){
    i = decodeVarint(a, &rowid);
    a += i;
    n += i;
  }
  if( nLocal<nPayload ){
    int ovfl = decodeInt32(a+nLocal);
    int cnt = 0;
    u32 ovfl = decodeInt32(a+nLocal);
    u32 cnt = 0;
    while( ovfl && (cnt++)<g.mxPage ){
      page_usage_msg(ovfl, "overflow %d from cell %d of page %d",
      page_usage_msg(ovfl, "overflow %d from cell %d of page %u",
                     cnt, cellno, pgno);
      a = fileRead((ovfl-1)*g.pagesize, 4);
      a = fileRead((ovfl-1)*(sqlite3_int64)g.pagesize, 4);
      ovfl = decodeInt32(a);
      sqlite3_free(a);
    }
  }
}

/*
** True if the memory is all zeros
*/
static int allZero(unsigned char *a, int n){
  while( n && (a++)[0]==0 ){ n--; }
  return n==0;

}


/*
** Describe the usages of a b-tree page
** Describe the usages of a b-tree page.
**
** If parent==0, then this is the root of a btree.  If parent<0 then
** this is an orphan page.
*/
static void page_usage_btree(
  int pgno,             /* Page to describe */
  u32 pgno,             /* Page to describe */
  int parent,           /* Parent of this page.  0 for root pages */
  int idx,              /* Which child of the parent */
  const char *zName     /* Name of the table */
){
  unsigned char *a;
  const char *zType = "corrupt node";
  int nCell;
  int i;
  int hdr = pgno==1 ? 100 : 0;
  char zEntry[30];

  if( pgno<=0 || pgno>g.mxPage ) return;
  a = fileRead((pgno-1)*g.pagesize, g.pagesize);
  switch( a[hdr] ){
    case 0: {
      if( allZero(a, g.pagesize) ){
        zType = "zeroed page";
      }else if( parent<0 ){
        return;
      }else{
        zType = "corrupt node";
      }
      break;
    }
    case 2:  zType = "interior node of index";  break;
    case 5:  zType = "interior node of table";  break;
    case 10: zType = "leaf of index";           break;
    case 13: zType = "leaf of table";           break;
    default: {
      if( parent<0 ) return;
      zType = "corrupt node";
  }
  if( parent ){
    page_usage_msg(pgno, "%s [%s], child %d of page %d",
                   zType, zName, idx, parent);
    }
  }
  nCell = a[hdr+3]*256 + a[hdr+4];
  if( nCell==1 ){
    sqlite3_snprintf(sizeof(zEntry),zEntry,"1 row");
  }else{
    sqlite3_snprintf(sizeof(zEntry),zEntry,"%d rows", nCell);
  }
  if( parent>0 ){
    page_usage_msg(pgno, "%s [%s], child %d of page %d, %s",
                   zType, zName, idx, parent, zEntry);
  }else if( parent==0 ){
    page_usage_msg(pgno, "root %s [%s], %s", zType, zName, zEntry);
  }else{
    page_usage_msg(pgno, "root %s [%s]", zType, zName);
    page_usage_msg(pgno, "orphaned %s, %s", zType, zEntry);
  }
  nCell = a[hdr+3]*256 + a[hdr+4];
  if( a[hdr]==2 || a[hdr]==5 ){
    int cellstart = hdr+12;
    unsigned int child;
    u32 child;
    for(i=0; i<nCell; i++){
      u32 cellidx;
      int ofst;
      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 ){
891
892
893
894
895
896
897
898

899
900
901
902
903
904
905
906

907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926


927
928

929
930
931

932
933
934
935
936
937
938
939
940
941
942

943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960

961
962
963
964
965
966
967
968
969

970
971
972
973
974
975
976
977
978

979
980
981
982
983
984
985
986
987
988
989
990

991



992
993
994
995
996
997
998
999
1000
1001
1002

1003
1004
1005
1006
1007
1008
1009
942
943
944
945
946
947
948

949
950
951
952
953
954
955
956

957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975


976
977
978

979
980
981

982
983
984
985
986
987
988
989
990
991
992

993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
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







-
+







-
+


















-
-
+
+

-
+


-
+










-
+

















-
+








-
+








-
+












+
-
+
+
+










-
+







  }
  sqlite3_free(a);
}

/*
** Determine page usage by the freelist
*/
static void page_usage_freelist(int pgno){
static void page_usage_freelist(u32 pgno){
  unsigned char *a;
  int cnt = 0;
  int i;
  int n;
  int iNext;
  int parent = 1;

  while( pgno>0 && pgno<=g.mxPage && (cnt++)<g.mxPage ){
  while( pgno>0 && pgno<=g.mxPage && (u32)(cnt++)<g.mxPage ){
    page_usage_msg(pgno, "freelist trunk #%d child of %d", cnt, parent);
    a = fileRead((pgno-1)*g.pagesize, g.pagesize);
    iNext = decodeInt32(a);
    n = decodeInt32(a+4);
    for(i=0; i<n; i++){
      int child = decodeInt32(a + (i*4+8));
      page_usage_msg(child, "freelist leaf, child %d of trunk page %d",
                     i, pgno);
    }
    sqlite3_free(a);
    parent = pgno;
    pgno = iNext;
  }
}

/*
** Determine pages used as PTRMAP pages
*/
static void page_usage_ptrmap(unsigned char *a){
  if( a[55] ){
static void page_usage_ptrmap(u8 *a){
  if( decodeInt32(a+52) ){
    int usable = g.pagesize - a[20];
    int pgno = 2;
    u64 pgno = 2;
    int perPage = usable/5;
    while( pgno<=g.mxPage ){
      page_usage_msg(pgno, "PTRMAP page covering %d..%d",
      page_usage_msg((u32)pgno, "PTRMAP page covering %llu..%llu",
                           pgno+1, pgno+perPage);
      pgno += perPage + 1;
    }
  }
}

/*
** Try to figure out how every page in the database file is being used.
*/
static void page_usage_report(const char *zPrg, const char *zDbName){
  int i, j;
  u32 i, j;
  int rc;
  sqlite3 *db;
  sqlite3_stmt *pStmt;
  unsigned char *a;
  char zQuery[200];

  /* Avoid the pathological case */
  if( g.mxPage<1 ){
    printf("empty database\n");
    return;
  }

  /* Open the database file */
  db = openDatabase(zPrg, zDbName);

  /* Set up global variables zPageUse[] and g.mxPage to record page
  ** usages */
  zPageUse = sqlite3_malloc( sizeof(zPageUse[0])*(g.mxPage+1) );
  zPageUse = sqlite3_malloc64( sizeof(zPageUse[0])*(g.mxPage+1) );
  if( zPageUse==0 ) out_of_memory();
  memset(zPageUse, 0, sizeof(zPageUse[0])*(g.mxPage+1));

  /* Discover the usage of each page */
  a = fileRead(0, 100);
  page_usage_freelist(decodeInt32(a+32));
  page_usage_ptrmap(a);
  sqlite3_free(a);
  page_usage_btree(1, 0, 0, "sqlite_master");
  page_usage_btree(1, 0, 0, "sqlite_schema");
  sqlite3_exec(db, "PRAGMA writable_schema=ON", 0, 0, 0);
  for(j=0; j<2; j++){
    sqlite3_snprintf(sizeof(zQuery), zQuery,
             "SELECT type, name, rootpage FROM SQLITE_MASTER WHERE rootpage"
             " ORDER BY rowid %s", j?"DESC":"");
    rc = sqlite3_prepare_v2(db, zQuery, -1, &pStmt, 0);
    if( rc==SQLITE_OK ){
      while( sqlite3_step(pStmt)==SQLITE_ROW ){
        int pgno = sqlite3_column_int(pStmt, 2);
        u32 pgno = (u32)sqlite3_column_int64(pStmt, 2);
        page_usage_btree(pgno, 0, 0, (const char*)sqlite3_column_text(pStmt,1));
      }
    }else{
      printf("ERROR: cannot query database: %s\n", sqlite3_errmsg(db));
    }
    rc = sqlite3_finalize(pStmt);
    if( rc==SQLITE_OK ) break;
  }
  sqlite3_close(db);

  /* Print the report and free memory used */
  for(i=1; i<=g.mxPage; i++){
    if( zPageUse[i]==0 ) page_usage_btree(i, -1, 0, 0);
    printf("%5d: %s\n", i, zPageUse[i] ? zPageUse[i] : "???");
    printf("%5u: %s\n", i, zPageUse[i] ? zPageUse[i] : "???");
  }
  for(i=1; i<=g.mxPage; i++){
    sqlite3_free(zPageUse[i]);
  }
  sqlite3_free(zPageUse);
  zPageUse = 0;
}

/*
** Try to figure out how every page in the database file is being used.
*/
static void ptrmap_coverage_report(const char *zDbName){
  int pgno;
  u64 pgno;
  unsigned char *aHdr;
  unsigned char *a;
  int usable;
  int perPage;
  int i;

  /* Avoid the pathological case */
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
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







-
+

-
+




-
+







-
+







  if( aHdr[55]==0 ){
    printf("database does not use PTRMAP pages\n");
    return;
  }
  usable = g.pagesize - aHdr[20];
  perPage = usable/5;
  sqlite3_free(aHdr);
  printf("%5d: root of sqlite_master\n", 1);
  printf("%5d: root of sqlite_schema\n", 1);
  for(pgno=2; pgno<=g.mxPage; pgno += perPage+1){
    printf("%5d: PTRMAP page covering %d..%d\n", pgno,
    printf("%5llu: PTRMAP page covering %llu..%llu\n", pgno,
           pgno+1, pgno+perPage);
    a = fileRead((pgno-1)*g.pagesize, usable);
    for(i=0; i+5<=usable && pgno+1+i/5<=g.mxPage; i+=5){
      const char *zType = "???";
      unsigned int iFrom = decodeInt32(&a[i+1]);
      u32 iFrom = decodeInt32(&a[i+1]);
      switch( a[i] ){
        case 1:  zType = "b-tree root page";        break;
        case 2:  zType = "freelist page";           break;
        case 3:  zType = "first page of overflow";  break;
        case 4:  zType = "later page of overflow";  break;
        case 5:  zType = "b-tree non-root page";    break;
      }
      printf("%5d: %s, parent=%u\n", pgno+1+i/5, zType, iFrom);
      printf("%5llu: %s, parent=%u\n", pgno+1+i/5, zType, iFrom);
    }
    sqlite3_free(a);
  }
}

/*
** Print a usage comment
1094
1095
1096
1097
1098
1099
1100
1101

1102
1103

1104
1105

1106
1107
1108
1109
1110

1111
1112
1113
1114
1115
1116
1117
1148
1149
1150
1151
1152
1153
1154

1155
1156

1157
1158

1159
1160
1161
1162
1163

1164
1165
1166
1167
1168
1169
1170
1171







-
+

-
+

-
+




-
+








  zPgSz = fileRead(16, 2);
  g.pagesize = zPgSz[0]*256 + zPgSz[1]*65536;
  if( g.pagesize==0 ) g.pagesize = 1024;
  sqlite3_free(zPgSz);

  printf("Pagesize: %d\n", g.pagesize);
  g.mxPage = (int)((szFile+g.pagesize-1)/g.pagesize);
  g.mxPage = (u32)((szFile+g.pagesize-1)/g.pagesize);

  printf("Available pages: 1..%d\n", g.mxPage);
  printf("Available pages: 1..%u\n", g.mxPage);
  if( nArg==2 ){
    int i;
    u32 i;
    for(i=1; i<=g.mxPage; i++) print_page(i);
  }else{
    int i;
    for(i=2; i<nArg; i++){
      int iStart, iEnd;
      u32 iStart, iEnd;
      char *zLeft;
      if( strcmp(azArg[i], "dbheader")==0 ){
        print_db_header();
        continue;
      }
      if( strcmp(azArg[i], "pgidx")==0 ){
        page_usage_report(zPrg, azArg[1]);
1125
1126
1127
1128
1129
1130
1131
1132

1133
1134
1135
1136
1137
1138
1139
1179
1180
1181
1182
1183
1184
1185

1186
1187
1188
1189
1190
1191
1192
1193







-
+







        usage(zPrg);
        continue;
      }
      if( !ISDIGIT(azArg[i][0]) ){
        fprintf(stderr, "%s: unknown option: [%s]\n", zPrg, azArg[i]);
        continue;
      }
      iStart = strtol(azArg[i], &zLeft, 0);
      iStart = strtoul(azArg[i], &zLeft, 0);
      if( zLeft && strcmp(zLeft,"..end")==0 ){
        iEnd = g.mxPage;
      }else if( zLeft && zLeft[0]=='.' && zLeft[1]=='.' ){
        iEnd = strtol(&zLeft[2], 0, 0);
      }else if( zLeft && zLeft[0]=='b' ){
        int ofst, nByte, hdrSize;
        unsigned char *a;

Changes to tool/showlocks.c.

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
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







+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







/*
** Print all locks on the inode of "fd" that occur in between
** lwr and upr, inclusive.
*/
static int showLocksInRange(int fd, off_t lwr, off_t upr){
  int cnt = 0;
  struct flock x;
  struct lockRange {
    off_t lwr;
    off_t upr;
  } *aPending = 0;
  int nAlloc = 1;
  int nPending = 0;
  int nDone = 0;

  nPending = 1;
  aPending = malloc( sizeof(aPending[0]) );
  if( aPending==0 ){
    fprintf(stderr, "out of memory\n");
    exit(1);
  }
  aPending[0].lwr = lwr;
  aPending[0].upr = upr;

  for(nDone=0; nDone<nPending; nDone++){
    lwr = aPending[nDone].lwr;
    upr = aPending[nDone].upr;
    if( lwr>=upr ) continue;
  x.l_type = F_WRLCK;
  x.l_whence = SEEK_SET;
  x.l_start = lwr;
  x.l_len = upr-lwr;
  fcntl(fd, F_GETLK, &x);
  if( x.l_type==F_UNLCK ) return 0;
  printf("start: %-12d len: %-5d pid: %-5d type: %s\n",
       (int)x.l_start, (int)x.l_len,
       x.l_pid, x.l_type==F_WRLCK ? "WRLCK" : "RDLCK");
  cnt++;
  if( x.l_start>lwr ){
    cnt += showLocksInRange(fd, lwr, x.l_start-1);
  }
  if( x.l_start+x.l_len<upr ){
    cnt += showLocksInRange(fd, x.l_start+x.l_len+1, upr);
  }
    x.l_type = F_WRLCK;
    x.l_whence = SEEK_SET;
    x.l_start = lwr;
    x.l_len = upr - lwr;
    fcntl(fd, F_GETLK, &x);
    if( x.l_type==F_UNLCK ) continue;
    printf("start: %-12d len: %-5d pid: %-5d type: %s\n",
         (int)x.l_start, (int)x.l_len,
         x.l_pid, x.l_type==F_WRLCK ? "WRLCK" : "RDLCK");
    cnt++;
    if( nPending+2 > nAlloc ){
      nAlloc = nAlloc*2 + 2;
      aPending = realloc(aPending, sizeof(aPending[0])*nAlloc );
    }
    if( aPending==0 ){
      fprintf(stderr, "unable to realloc for %d bytes\n",
                      (int)sizeof(aPending[0])*(nPending+2));
      exit(1);
    }
    if( lwr<x.l_start ){
      aPending[nPending].lwr = lwr;
      aPending[nPending].upr = x.l_start;
      nPending++;
    }
    if( x.l_start+x.l_len<=upr ){
      aPending[nPending].lwr = x.l_start + x.l_len;
      aPending[nPending].upr = upr;
      nPending++;
    }
  }
  free(aPending);
  return cnt;
}

int main(int argc, char **argv){
  int fd;
  int cnt;

Changes to tool/showwal.c.

113
114
115
116
117
118
119
120

121
122
123
124
125
126
127
113
114
115
116
117
118
119

120
121
122
123
124
125
126
127







-
+








/*
** Read content from the file.
**
** Space to hold the content is obtained from malloc() and needs to be
** freed by the caller.
*/
static unsigned char *getContent(int ofst, int nByte){
static unsigned char *getContent(i64 ofst, int nByte){
  unsigned char *aData;
  aData = malloc(nByte);
  if( aData==0 ) out_of_memory();
  lseek(fd, ofst, SEEK_SET);
  read(fd, aData, nByte);
  return aData;
}
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
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







-
+

-
-
+
+
















-
+


-
+







  printf("%s  %s\n", zBuf, zMsg);
}

/*
** Print an entire page of content as hex
*/
static void print_frame(int iFrame){
  int iStart;
  i64 iStart;
  unsigned char *aData;
  iStart = 32 + (iFrame-1)*(pagesize+24);
  fprintf(stdout, "Frame %d:   (offsets 0x%x..0x%x)\n",
  iStart = 32 + (i64)(iFrame-1)*(pagesize+24);
  fprintf(stdout, "Frame %d:   (offsets 0x%llx..0x%llx)\n",
          iFrame, iStart, iStart+pagesize+24);
  aData = getContent(iStart, pagesize+24);
  print_decode_line(aData, 0, 4, 0, "Page number");
  print_decode_line(aData, 4, 4, 0, "DB size, or 0 for non-commit");
  print_decode_line(aData, 8, 4, 1, "Salt-1");
  print_decode_line(aData,12, 4, 1, "Salt-2");
  print_decode_line(aData,16, 4, 1, "Checksum-1");
  print_decode_line(aData,20, 4, 1, "Checksum-2");
  print_byte_range(iStart+24, pagesize, aData+24, 0);
  free(aData);
}

/*
** Summarize a single frame on a single line.
*/
static void print_oneline_frame(int iFrame, Cksum *pCksum){
  int iStart;
  i64 iStart;
  unsigned char *aData;
  unsigned int s0, s1;
  iStart = 32 + (iFrame-1)*(pagesize+24);
  iStart = 32 + (i64)(iFrame-1)*(pagesize+24);
  aData = getContent(iStart, 24);
  extendCksum(pCksum, aData, 8, 0);
  extendCksum(pCksum, getContent(iStart+24, pagesize), pagesize, 0);
  s0 = getInt32(aData+16);
  s1 = getInt32(aData+20);
  fprintf(stdout, "Frame %4d: %6d %6d 0x%08x,%08x 0x%08x,%08x %s\n",
          iFrame, 
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
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







+
-
+







-
+


-
+







      }
      iStart = strtol(argv[i], &zLeft, 0);
      if( zLeft && strcmp(zLeft,"..end")==0 ){
        iEnd = mxFrame;
      }else if( zLeft && zLeft[0]=='.' && zLeft[1]=='.' ){
        iEnd = strtol(&zLeft[2], 0, 0);
      }else if( zLeft && zLeft[0]=='b' ){
        i64 ofst;
        int ofst, nByte, hdrSize;
        int nByte, hdrSize;
        unsigned char *a;
        if( iStart==1 ){
          hdrSize = 100;
          ofst = hdrSize = 100;
          nByte = pagesize-100;
        }else{
          hdrSize = 0;
          ofst = (iStart-1)*pagesize;
          ofst = (i64)(iStart-1)*pagesize;
          nByte = pagesize;
        }
        ofst = 32 + hdrSize + (iStart-1)*(pagesize+24) + 24;
        ofst = 32 + hdrSize + (i64)(iStart-1)*(pagesize+24) + 24;
        a = getContent(ofst, nByte);
        decode_btree_page(a, iStart, hdrSize, zLeft+1);
        free(a);
        continue;
#if !defined(_MSC_VER)
      }else if( zLeft && strcmp(zLeft,"truncate")==0 ){
        /* Frame number followed by "truncate" truncates the WAL file

Changes to tool/spaceanal.tcl.

12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
12
13
14
15
16
17
18

19
20
21
22
23
24
25
26







-
+







# false otherwise.
#
proc is_without_rowid {tname} {
  set t [string map {' ''} $tname]
  db eval "PRAGMA index_list = '$t'" o {
    if {$o(origin) == "pk"} {
      set n $o(name)
      if {0==[db one { SELECT count(*) FROM sqlite_master WHERE name=$n }]} {
      if {0==[db one { SELECT count(*) FROM sqlite_schema WHERE name=$n }]} {
        return 1
      }
    }
  }
  return 0
}

156
157
158
159
160
161
162
163

164
165
166
167
168
169
170
156
157
158
159
160
161
162

163
164
165
166
167
168
169
170







-
+







  puts "The SQLite database engine linked with this application\
        lacks required capabilities. Recompile using the\
        -DSQLITE_ENABLE_DBSTAT_VTAB compile-time option to fix\
        this problem."
  exit 1
}

db eval {SELECT count(*) FROM sqlite_master}
db eval {SELECT count(*) FROM sqlite_schema}
set pageSize [expr {wide([db one {PRAGMA page_size}])}]

if {$flags(-pageinfo)} {
  db eval {CREATE VIRTUAL TABLE temp.stat USING dbstat}
  db eval {SELECT name, path, pageno FROM temp.stat ORDER BY pageno} {
    puts "$pageno $name $path"
  }
241
242
243
244
245
246
247
248
249


250
251
252
253
254
255
256
241
242
243
244
245
246
247


248
249
250
251
252
253
254
255
256







-
-
+
+







db eval {CREATE TEMP TABLE dbstat AS SELECT * FROM temp.stat
         ORDER BY name, path}
db eval {DROP TABLE temp.stat}

set isCompressed 0
set compressOverhead 0
set depth 0
set sql { SELECT name, tbl_name FROM sqlite_master WHERE rootpage>0 }
foreach {name tblname} [concat sqlite_master sqlite_master [db eval $sql]] {
set sql { SELECT name, tbl_name FROM sqlite_schema WHERE rootpage>0 }
foreach {name tblname} [concat sqlite_schema sqlite_schema [db eval $sql]] {

  set is_index [expr {$name!=$tblname}]
  set is_without_rowid [is_without_rowid $name]
  db eval {
    SELECT 
      sum(ncell) AS nentry,
      sum((pagetype=='leaf')*ncell) AS leaf_entries,
556
557
558
559
560
561
562
563

564
565
566
567
568
569
570
556
557
558
559
560
561
562

563
564
565
566
567
568
569
570







-
+







# free_percent:  Percentage of file consumed by free pages (calculated).
# free_percent2: Percentage of file consumed by free pages (header).
# ntable:        Number of tables in the db.
# nindex:        Number of indices in the db.
# nautoindex:    Number of indices created automatically.
# nmanindex:     Number of indices created manually.
# user_payload:  Number of bytes of payload in table btrees 
#                (not including sqlite_master)
#                (not including sqlite_schema)
# user_percent:  $user_payload as a percentage of total file size.

### The following, setting $file_bytes based on the actual size of the file
### on disk, causes this tool to choke on zipvfs databases. So set it based
### on the return of [PRAGMA page_count] instead.
if 0 {
  set file_bytes  [file size $file_to_analyze]
583
584
585
586
587
588
589



590
591
592



593
594
595
596
597
598

599
600
601
602
603
604
605
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







+
+
+
-
-
-
+
+
+





-
+







set free_pgcnt    [expr {$file_pgcnt-$inuse_pgcnt-$av_pgcnt}]
set free_percent  [percent $free_pgcnt $file_pgcnt]
set free_pgcnt2   [db one {PRAGMA freelist_count}]
set free_percent2 [percent $free_pgcnt2 $file_pgcnt]

set file_pgcnt2 [expr {$inuse_pgcnt+$free_pgcnt2+$av_pgcnt}]

# Account for the lockbyte page
if {$file_pgcnt2*$pageSize>1073742335} {incr file_pgcnt2}

set ntable [db eval {SELECT count(*)+1 FROM sqlite_master WHERE type='table'}]
set nindex [db eval {SELECT count(*) FROM sqlite_master WHERE type='index'}]
set sql {SELECT count(*) FROM sqlite_master WHERE name LIKE 'sqlite_autoindex%'}
set ntable [db eval {SELECT count(*)+1 FROM sqlite_schema WHERE type='table'}]
set nindex [db eval {SELECT count(*) FROM sqlite_schema WHERE type='index'}]
set sql {SELECT count(*) FROM sqlite_schema WHERE name LIKE 'sqlite_autoindex%'}
set nautoindex [db eval $sql]
set nmanindex [expr {$nindex-$nautoindex}]

# set total_payload [mem eval "SELECT sum(payload) FROM space_used"]
set user_payload [mem one {SELECT int(sum(payload)) FROM space_used
     WHERE NOT is_index AND name NOT LIKE 'sqlite_master'}]
     WHERE NOT is_index AND name NOT LIKE 'sqlite_schema'}]
set user_percent [percent $user_payload $file_bytes]

# Output the summary statistics calculated above.
#
puts "/** Disk-Space Utilization Report For $root_filename"
puts ""
statline {Page size in bytes} $pageSize
724
725
726
727
728
729
730
731

732
733
734
735
736
737
738
727
728
729
730
731
732
733

734
735
736
737
738
739
740
741







-
+







Pages of auto-vacuum overhead

    The number of pages that store data used by the database to facilitate
    auto-vacuum. This is zero for databases that do not support auto-vacuum.

Number of tables in the database

    The number of tables in the database, including the SQLITE_MASTER table
    The number of tables in the database, including the SQLITE_SCHEMA table
    used to store schema information.

Number of indices

    The total number of indices in the database.

Number of defined indices
747
748
749
750
751
752
753
754

755
756
757
758
759
760
761
750
751
752
753
754
755
756

757
758
759
760
761
762
763
764







-
+







Size of the file in bytes

    The total amount of disk space used by the entire database files.

Bytes of user payload stored

    The total number of bytes of user payload stored in the database. The
    schema information in the SQLITE_MASTER table is not counted when
    schema information in the SQLITE_SCHEMA table is not counted when
    computing this number.  The percentage at the right shows the payload
    divided by the total file size.

Percentage of total database

    The amount of the complete database file that is devoted to storing
    information described by this category.

Changes to tool/speed-check.sh.

1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
1
2
3
4
5



6
7
8
9
10
11
12
13
14
15





-
-
-
+
+
+







#!/bin/bash
#
# This is a template for a script used for day-to-day size and 
# performance monitoring of SQLite.  Typical usage:
#
#     sh run-speed-test.sh trunk  #  Baseline measurement of trunk
#     sh run-speed-test.sh x1     # Measure some experimental change
#     fossil test-diff --tk cout-trunk.txt cout-x1.txt   # View chanages
#     sh speed-check.sh trunk  #  Baseline measurement of trunk
#     sh speed-check.sh x1     # Measure some experimental change
#     fossil xdiff --tk cout-trunk.txt cout-x1.txt   # View chanages
#
# There are multiple output files, all with a base name given by
# the first argument:
#
#     summary-$BASE.txt           # Copy of standard output
#     cout-$BASE.txt              # cachegrind output
#     explain-$BASE.txt           # EXPLAIN listings (only with --explain)
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
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







+
+
+



+
+
+
+
+
+
+
+
+





+
+
+
+










+
+
+
+
+
+







        ;;
    --stats)
        SPEEDTEST_OPTS="$SPEEDTEST_OPTS $1"
        ;;
    --without-rowid)
        SPEEDTEST_OPTS="$SPEEDTEST_OPTS $1"
        ;;
    --strict)
        SPEEDTEST_OPTS="$SPEEDTEST_OPTS $1"
        ;;
    --nomemstat)
        SPEEDTEST_OPTS="$SPEEDTEST_OPTS $1"
        ;;
    --multithread)
        SPEEDTEST_OPTS="$SPEEDTEST_OPTS $1"
        ;;
    --singlethread)
        SPEEDTEST_OPTS="$SPEEDTEST_OPTS $1"
        ;;
    --serialized)
        SPEEDTEST_OPTS="$SPEEDTEST_OPTS $1"
        ;;
    --temp)
        SPEEDTEST_OPTS="$SPEEDTEST_OPTS --temp 6"
        ;;
    --legacy)
	doWal=0
        CC_OPTS="$CC_OPTS -DSPEEDTEST_OMIT_HASH"
        ;;
    --verify)
        SPEEDTEST_OPTS="$SPEEDTEST_OPTS --verify"
        ;;
    --wal)
        doWal=1
        ;;
    --size)
        shift; SIZE=$1
        ;;
    --cachesize)
        shift; SPEEDTEST_OPTS="$SPEEDTEST_OPTS --cachesize $1"
        ;;
    --stmtcache)
        shift; SPEEDTEST_OPTS="$SPEEDTEST_OPTS --stmtcache $1"
        ;;
    --checkpoint)
        SPEEDTEST_OPTS="$SPEEDTEST_OPTS --checkpoint"
        ;;
    --explain)
        doExplain=1
        ;;
    --vdbeprofile)
        rm -f vdbe_profile.out
        CC_OPTS="$CC_OPTS -DVDBE_PROFILE"
        doCachegrind=0
120
121
122
123
124
125
126



127
128
129
130
131
132
133
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158







+
+
+







        shift;
        SPEEDTEST_OPTS="$SPEEDTEST_OPTS --mmap $1"
        ;;
    --rtree)
        SPEEDTEST_OPTS="$SPEEDTEST_OPTS --testset rtree"
        CC_OPTS="$CC_OPTS -DSQLITE_ENABLE_RTREE"
        ;;
    --persist)
        SPEEDTEST_OPTS="$SPEEDTEST_OPTS --persist"
        ;;
    --orm)
        SPEEDTEST_OPTS="$SPEEDTEST_OPTS --testset orm"
        ;;
    --cte)
        SPEEDTEST_OPTS="$SPEEDTEST_OPTS --testset cte"
        ;;
    --fp)

Changes to tool/split-sqlite3c.tcl.

70
71
72
73
74
75
76





77
78
79
80
81
82
83
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88







+
+
+
+
+







    set all {}
    set N 0
  }
  append all $buf
  incr N $n
  while {[gets $in line]>=0} {
    if {[regexp $BEGIN $line]} break
    if {$N>0} {
      write_one_file $all
      set N 0
      set all {}
    }
    puts $out1 $line
  }
}
if {$N>0} {
  write_one_file $all
}
close $out1

Changes to tool/sqldiff.c.

31
32
33
34
35
36
37

38
39
40
41
42
43
44
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45







+







*/
struct GlobalVars {
  const char *zArgv0;       /* Name of program */
  int bSchemaOnly;          /* Only show schema differences */
  int bSchemaPK;            /* Use the schema-defined PK, not the true PK */
  int bHandleVtab;          /* Handle fts3, fts4, fts5 and rtree vtabs */
  unsigned fDebug;          /* Debug flags */
  int bSchemaCompare;       /* Doing single-table sqlite_schema compare */
  sqlite3 *db;              /* The database connection */
} g;

/*
** Allowed values for g.fDebug
*/
#define DEBUG_COLUMN_NAMES  0x000001
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
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







-
+






-
+








+
+
+







    int i;
    for(i=0; az[i]; i++) sqlite3_free(az[i]);
    sqlite3_free(az);
  }
}

/*
** Return a list of column names for the table zDb.zTab.  Space to
** Return a list of column names [a] for the table zDb.zTab.  Space to
** hold the list is obtained from sqlite3_malloc() and should released
** using namelistFree() when no longer needed.
**
** Primary key columns are listed first, followed by data columns.
** The number of columns in the primary key is returned in *pnPkey.
**
** Normally, the "primary key" in the previous sentence is the true
** Normally [a], the "primary key" in the previous sentence is the true
** primary key - the rowid or INTEGER PRIMARY KEY for ordinary tables
** or the declared PRIMARY KEY for WITHOUT ROWID tables.  However, if
** the g.bSchemaPK flag is set, then the schema-defined PRIMARY KEY is
** used in all cases.  In that case, entries that have NULL values in
** any of their primary key fields will be excluded from the analysis.
**
** If the primary key for a table is the rowid but rowid is inaccessible,
** then this routine returns a NULL pointer.
**
** [a. If the lone, named table is "sqlite_schema", "rootpage" column is
**  omitted and the "type" and "name" columns are made to be the PK.]
**
** Examples:
**    CREATE TABLE t1(a INT UNIQUE, b INTEGER, c TEXT, PRIMARY KEY(c));
**    *pnPKey = 1;
**    az = { "rowid", "a", "b", "c", 0 }  // Normal case
**    az = { "c", "a", "b", 0 }           // g.bSchemaPK==1
**
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
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







+
+
+
+
+
+
+






+
+
+
+

+


-
+

+
+
+
+
-
-
-
+
+
+
+










-
-
-
+
+
+
+
+







    pStmt = db_prepare("PRAGMA %s.table_info=%Q", zDb, zTab);
    while( SQLITE_ROW==sqlite3_step(pStmt) ){
      if( sqlite3_column_int(pStmt,5)>0 ) nPK++;
    }
    sqlite3_reset(pStmt);
    if( nPK==0 ) nPK = 1;
    truePk = 1;
  }
  if( g.bSchemaCompare ){
    assert( sqlite3_stricmp(zTab,"sqlite_schema")==0
            || sqlite3_stricmp(zTab,"sqlite_master")==0 );
    /* For sqlite_schema, will use type and name as the PK. */
    nPK = 2;
    truePk = 0;
  }
  *pnPKey = nPK;
  naz = nPK;
  az = sqlite3_malloc( sizeof(char*)*(nPK+1) );
  if( az==0 ) runtimeError("out of memory");
  memset(az, 0, sizeof(char*)*(nPK+1));
  if( g.bSchemaCompare ){
    az[0] = sqlite3_mprintf("%s", "type");
    az[1] = sqlite3_mprintf("%s", "name");
  }
  while( SQLITE_ROW==sqlite3_step(pStmt) ){
    char * sid = safeId((char*)sqlite3_column_text(pStmt,1));
    int iPKey;
    if( truePk && (iPKey = sqlite3_column_int(pStmt,5))>0 ){
      az[iPKey-1] = safeId((char*)sqlite3_column_text(pStmt,1));
      az[iPKey-1] = sid;
    }else{
      if( !g.bSchemaCompare
          || !(strcmp(sid,"rootpage")==0
               ||strcmp(sid,"name")==0
               ||strcmp(sid,"type")==0)){
      az = sqlite3_realloc(az, sizeof(char*)*(naz+2) );
      if( az==0 ) runtimeError("out of memory");
      az[naz++] = safeId((char*)sqlite3_column_text(pStmt,1));
        az = sqlite3_realloc(az, sizeof(char*)*(naz+2) );
        if( az==0 ) runtimeError("out of memory");
        az[naz++] = sid;
      }
    }
  }
  sqlite3_finalize(pStmt);
  if( az ) az[naz] = 0;

  /* If it is non-NULL, set *pbRowid to indicate whether or not the PK of 
  ** this table is an implicit rowid (*pbRowid==1) or not (*pbRowid==0).  */
  if( pbRowid ) *pbRowid = (az[0]==0);

  /* If this table has an implicit rowid for a PK, figure out how to refer
  ** to it. There are three options - "rowid", "_rowid_" and "oid". Any
  ** of these will work, unless the table has an explicit column of the
  ** same name.  */
  ** to it. There are usually three options - "rowid", "_rowid_" and "oid".
  ** Any of these will work, unless the table has an explicit column of the
  ** same name or the sqlite_schema tables are to be compared. In the latter
  ** case, pretend that the "true" primary key is the name column, which
  ** avoids extraneous diffs against the schemas due to rowid variance. */
  if( az[0]==0 ){
    const char *azRowid[] = { "rowid", "_rowid_", "oid" };
    for(i=0; i<sizeof(azRowid)/sizeof(azRowid[0]); i++){
      for(j=1; j<naz; j++){
        if( sqlite3_stricmp(az[j], azRowid[i])==0 ) break;
      }
      if( j>=naz ){
376
377
378
379
380
381
382
383
384
385
386
387


388
389














390
391
392




393
394
395
396
397
398
399
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







-




+
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+







        /* Could be an OOM, could be a zero-byte blob */
        fprintf(out, "X''");
      }
      break;
    }
    case SQLITE_TEXT: {
      const unsigned char *zArg = sqlite3_value_text(X);
      int i, j;

      if( zArg==0 ){
        fprintf(out, "NULL");
      }else{
        int inctl = 0;
        int i, j;
        fprintf(out, "'");
        for(i=j=0; zArg[i]; i++){
          char c = zArg[i];
          int ctl = iscntrl(c);
          if( ctl>inctl ){
            inctl = ctl;
            fprintf(out, "%.*s'||X'%02x", i-j, &zArg[j], c);
            j = i+1;
          }else if( ctl ){
            fprintf(out, "%02x", c);
            j = i+1;
          }else{
            if( inctl ){
              inctl = 0;
              fprintf(out, "'\n||'");
            }
          if( zArg[i]=='\'' ){
            fprintf(out, "%.*s'", i-j+1, &zArg[j]);
            j = i+1;
            if( c=='\'' ){
              fprintf(out, "%.*s'", i-j+1, &zArg[j]);
              j = i+1;
            }
          }
        }
        fprintf(out, "%s'", &zArg[j]);
      }
      break;
    }
    case SQLITE_NULL: {
412
413
414
415
416
417
418
419

420
421
422
423
424
425
426
451
452
453
454
455
456
457

458
459
460
461
462
463
464
465







-
+







  int nPk;                  /* Number of true primary key columns */
  int nCol;                 /* Number of data columns */
  int i;                    /* Loop counter */
  sqlite3_stmt *pStmt;      /* SQL statement */
  const char *zSep;         /* Separator string */
  Str ins;                  /* Beginning of the INSERT statement */

  pStmt = db_prepare("SELECT sql FROM aux.sqlite_master WHERE name=%Q", zTab);
  pStmt = db_prepare("SELECT sql FROM aux.sqlite_schema WHERE name=%Q", zTab);
  if( SQLITE_ROW==sqlite3_step(pStmt) ){
    fprintf(out, "%s;\n", sqlite3_column_text(pStmt,0));
  }
  sqlite3_finalize(pStmt);
  if( !g.bSchemaOnly ){
    az = columnNames("aux", zTab, &nPk, 0);
    strInit(&ins);
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
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







-
+






+




-
+
+














+
+




















-




+
+
+
-
+






+
+
+
-
+
















-
+







        zSep = ",";
      }
      fprintf(out, ");\n");
    }
    sqlite3_finalize(pStmt);
    strFree(&ins);
  } /* endif !g.bSchemaOnly */
  pStmt = db_prepare("SELECT sql FROM aux.sqlite_master"
  pStmt = db_prepare("SELECT sql FROM aux.sqlite_schema"
                     " WHERE type='index' AND tbl_name=%Q AND sql IS NOT NULL",
                     zTab);
  while( SQLITE_ROW==sqlite3_step(pStmt) ){
    fprintf(out, "%s;\n", sqlite3_column_text(pStmt,0));
  }
  sqlite3_finalize(pStmt);
  sqlite3_free(zId);
}


/*
** Compute all differences for a single table.
** Compute all differences for a single table, except if the
** table name is sqlite_schema, ignore the rootpage column.
*/
static void diff_one_table(const char *zTab, FILE *out){
  char *zId = safeId(zTab); /* Name of table (translated for us in SQL) */
  char **az = 0;            /* Columns in main */
  char **az2 = 0;           /* Columns in aux */
  int nPk;                  /* Primary key columns in main */
  int nPk2;                 /* Primary key columns in aux */
  int n = 0;                /* Number of columns in main */
  int n2;                   /* Number of columns in aux */
  int nQ;                   /* Number of output columns in the diff query */
  int i;                    /* Loop counter */
  const char *zSep;         /* Separator string */
  Str sql;                  /* Comparison query */
  sqlite3_stmt *pStmt;      /* Query statement to do the diff */
  const char *zLead =       /* Becomes line-comment for sqlite_schema */
    (g.bSchemaCompare)? "-- " : "";

  strInit(&sql);
  if( g.fDebug==DEBUG_COLUMN_NAMES ){
    /* Simply run columnNames() on all tables of the origin
    ** database and show the results.  This is used for testing
    ** and debugging of the columnNames() function.
    */
    az = columnNames("aux",zTab, &nPk, 0);
    if( az==0 ){
      printf("Rowid not accessible for %s\n", zId);
    }else{
      printf("%s:", zId);
      for(i=0; az[i]; i++){
        printf(" %s", az[i]);
        if( i+1==nPk ) printf(" *");
      }
      printf("\n");
    }
    goto end_diff_one_table;
  }
    

  if( sqlite3_table_column_metadata(g.db,"aux",zTab,0,0,0,0,0,0) ){
    if( !sqlite3_table_column_metadata(g.db,"main",zTab,0,0,0,0,0,0) ){
      /* Table missing from second database. */
      if( g.bSchemaCompare )
        fprintf(out, "-- 2nd DB has no %s table\n", zTab);
      else
      fprintf(out, "DROP TABLE %s;\n", zId);
        fprintf(out, "DROP TABLE %s;\n", zId);
    }
    goto end_diff_one_table;
  }

  if( sqlite3_table_column_metadata(g.db,"main",zTab,0,0,0,0,0,0) ){
    /* Table missing from source */
    if( g.bSchemaCompare )
      fprintf(out, "-- 1st DB has no %s table\n", zTab);
    else
    dump_table(zTab, out);
      dump_table(zTab, out);
    goto end_diff_one_table;
  }

  az = columnNames("main", zTab, &nPk, 0);
  az2 = columnNames("aux", zTab, &nPk2, 0);
  if( az && az2 ){
    for(n=0; az[n] && az2[n]; n++){
      if( sqlite3_stricmp(az[n],az2[n])!=0 ) break;
    }
  }
  if( az==0
   || az2==0
   || nPk!=nPk2
   || az[n]
  ){
    /* Schema mismatch */
    fprintf(out, "DROP TABLE %s; -- due to schema mismatch\n", zId);
    fprintf(out, "%sDROP TABLE %s; -- due to schema mismatch\n", zLead, zId);
    dump_table(zTab, out);
    goto end_diff_one_table;
  }

  /* Build the comparison query */
  for(n2=n; az2[n2]; n2++){
    fprintf(out, "ALTER TABLE %s ADD COLUMN %s;\n", zId, safeId(az2[n2]));
635
636
637
638
639
640
641
642

643
644
645

646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663

664
665
666
667
668
669
670
671
672

673
674
675
676
677
678
679
680
681
682

683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703

704
705
706

707
708
709
710
711
712
713
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







-
+


-
+

















-
+








-
+









-
+




















-
+


-
+







  if( g.fDebug & DEBUG_DIFF_SQL ){ 
    printf("SQL for %s:\n%s\n", zId, sql.z);
    goto end_diff_one_table;
  }

  /* Drop indexes that are missing in the destination */
  pStmt = db_prepare(
    "SELECT name FROM main.sqlite_master"
    "SELECT name FROM main.sqlite_schema"
    " WHERE type='index' AND tbl_name=%Q"
    "   AND sql IS NOT NULL"
    "   AND sql NOT IN (SELECT sql FROM aux.sqlite_master"
    "   AND sql NOT IN (SELECT sql FROM aux.sqlite_schema"
    "                    WHERE type='index' AND tbl_name=%Q"
    "                      AND sql IS NOT NULL)",
    zTab, zTab);
  while( SQLITE_ROW==sqlite3_step(pStmt) ){
    char *z = safeId((const char*)sqlite3_column_text(pStmt,0));
    fprintf(out, "DROP INDEX %s;\n", z);
    sqlite3_free(z);
  }
  sqlite3_finalize(pStmt);

  /* Run the query and output differences */
  if( !g.bSchemaOnly ){
    pStmt = db_prepare("%s", sql.z);
    while( SQLITE_ROW==sqlite3_step(pStmt) ){
      int iType = sqlite3_column_int(pStmt, nPk);
      if( iType==1 || iType==2 ){
        if( iType==1 ){       /* Change the content of a row */
          fprintf(out, "UPDATE %s", zId);
          fprintf(out, "%sUPDATE %s", zLead, zId);
          zSep = " SET";
          for(i=nPk+1; i<nQ; i+=2){
            if( sqlite3_column_int(pStmt,i)==0 ) continue;
            fprintf(out, "%s %s=", zSep, az2[(i+nPk-1)/2]);
            zSep = ",";
            printQuoted(out, sqlite3_column_value(pStmt,i+1));
          }
        }else{                /* Delete a row */
          fprintf(out, "DELETE FROM %s", zId);
          fprintf(out, "%sDELETE FROM %s", zLead, zId);
        }
        zSep = " WHERE";
        for(i=0; i<nPk; i++){
          fprintf(out, "%s %s=", zSep, az2[i]);
          printQuoted(out, sqlite3_column_value(pStmt,i));
          zSep = " AND";
        }
        fprintf(out, ";\n");
      }else{                  /* Insert a row */
        fprintf(out, "INSERT INTO %s(%s", zId, az2[0]);
        fprintf(out, "%sINSERT INTO %s(%s", zLead, zId, az2[0]);
        for(i=1; az2[i]; i++) fprintf(out, ",%s", az2[i]);
        fprintf(out, ") VALUES");
        zSep = "(";
        for(i=0; i<nPk2; i++){
          fprintf(out, "%s", zSep);
          zSep = ",";
          printQuoted(out, sqlite3_column_value(pStmt,i));
        }
        for(i=nPk2+2; i<nQ; i+=2){
          fprintf(out, ",");
          printQuoted(out, sqlite3_column_value(pStmt,i));
        }
        fprintf(out, ");\n");
      }
    }
    sqlite3_finalize(pStmt);
  } /* endif !g.bSchemaOnly */

  /* Create indexes that are missing in the source */
  pStmt = db_prepare(
    "SELECT sql FROM aux.sqlite_master"
    "SELECT sql FROM aux.sqlite_schema"
    " WHERE type='index' AND tbl_name=%Q"
    "   AND sql IS NOT NULL"
    "   AND sql NOT IN (SELECT sql FROM main.sqlite_master"
    "   AND sql NOT IN (SELECT sql FROM main.sqlite_schema"
    "                    WHERE type='index' AND tbl_name=%Q"
    "                      AND sql IS NOT NULL)",
    zTab, zTab);
  while( SQLITE_ROW==sqlite3_step(pStmt) ){
    fprintf(out, "%s;\n", sqlite3_column_text(pStmt,0));
  }
  sqlite3_finalize(pStmt);
724
725
726
727
728
729
730
731

732
733
734
735
736
737
738
772
773
774
775
776
777
778

779
780
781
782
783
784
785
786







-
+







** Check that table zTab exists and has the same schema in both the "main"
** and "aux" databases currently opened by the global db handle. If they
** do not, output an error message on stderr and exit(1). Otherwise, if
** the schemas do match, return control to the caller.
*/
static void checkSchemasMatch(const char *zTab){
  sqlite3_stmt *pStmt = db_prepare(
      "SELECT A.sql=B.sql FROM main.sqlite_master A, aux.sqlite_master B"
      "SELECT A.sql=B.sql FROM main.sqlite_schema A, aux.sqlite_schema B"
      " WHERE A.name=%Q AND B.name=%Q", zTab, zTab
  );
  if( SQLITE_ROW==sqlite3_step(pStmt) ){
    if( sqlite3_column_int(pStmt,0)==0 ){
      runtimeError("schema changes for table %s", safeId(zTab));
    }
  }else{
1540
1541
1542
1543
1544
1545
1546

1547
1548
1549
1550
1551
1552
1553
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602







+







  int nPk = 0;                  /* Number of PRIMARY KEY columns */
  Str sql;                      /* SQL for the diff query */
  int i, k;                     /* Loop counters */
  const char *zSep;             /* List separator */

  /* Check that the schemas of the two tables match. Exit early otherwise. */
  checkSchemasMatch(zTab);
  strInit(&sql);

  pStmt = db_prepare("PRAGMA main.table_info=%Q", zTab);
  while( SQLITE_ROW==sqlite3_step(pStmt) ){
    nCol++;
    azCol = sqlite3_realloc(azCol, sizeof(char*)*nCol);
    if( azCol==0 ) runtimeError("out of memory");
    aiFlg = sqlite3_realloc(aiFlg, sizeof(int)*nCol);
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1610
1611
1612
1613
1614
1615
1616

1617
1618
1619
1620
1621
1622
1623







-







        if( aiPk==0 ) runtimeError("out of memory");
      }
      aiPk[i-1] = nCol-1;
    }
  }
  sqlite3_finalize(pStmt);
  if( nPk==0 ) goto end_changeset_one_table; 
  strInit(&sql);
  if( nCol>nPk ){
    strPrintf(&sql, "SELECT %d", SQLITE_UPDATE);
    for(i=0; i<nCol; i++){
      if( aiFlg[i] ){
        strPrintf(&sql, ",\n       A.%s", azCol[i]);
      }else{
        strPrintf(&sql, ",\n       A.%s IS NOT B.%s, A.%s, B.%s",
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
1755
1756
1757
1758
1759
1760

1761
1762
1763
1764
1765
1766
1767
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







+
+
+
+
+
+
+
+
+
+








-
+






-
+


















-
+















-
+







  sqlite3_finalize(pStmt);
  
end_changeset_one_table:
  while( nCol>0 ) sqlite3_free(azCol[--nCol]);
  sqlite3_free(azCol);
  sqlite3_free(aiPk);
  sqlite3_free(zId);
  sqlite3_free(aiFlg);
  strFree(&sql);
}

/*
** Return true if the ascii character passed as the only argument is a
** whitespace character. Otherwise return false.
*/
static int is_whitespace(char x){
  return (x==' ' || x=='\t' || x=='\n' || x=='\r');
}

/*
** Extract the next SQL keyword or quoted string from buffer zIn and copy it
** (or a prefix of it if it will not fit) into buffer zBuf, size nBuf bytes.
** Return a pointer to the character within zIn immediately following 
** the token or quoted string just extracted.
*/
const char *gobble_token(const char *zIn, char *zBuf, int nBuf){
static const char *gobble_token(const char *zIn, char *zBuf, int nBuf){
  const char *p = zIn;
  char *pOut = zBuf;
  char *pEnd = &pOut[nBuf-1];
  char q = 0;                     /* quote character, if any */

  if( p==0 ) return 0;
  while( *p==' ' ) p++;
  while( is_whitespace(*p) ) p++;
  switch( *p ){
    case '"': q = '"'; break;
    case '\'': q = '\''; break;
    case '`': q = '`'; break;
    case '[': q = ']'; break;
  }

  if( q ){
    p++;
    while( *p && pOut<pEnd ){
      if( *p==q ){
        p++;
        if( *p!=q ) break;
      }
      if( pOut<pEnd ) *pOut++ = *p;
      p++;
    }
  }else{
    while( *p && *p!=' ' && *p!='(' ){
    while( *p && !is_whitespace(*p) && *p!='(' ){
      if( pOut<pEnd ) *pOut++ = *p;
      p++;
    }
  }

  *pOut = '\0';
  return p;
}

/*
** This function is the implementation of SQL scalar function "module_name":
**
**   module_name(SQL)
**
** The only argument should be an SQL statement of the type that may appear
** in the sqlite_master table. If the statement is a "CREATE VIRTUAL TABLE"
** in the sqlite_schema table. If the statement is a "CREATE VIRTUAL TABLE"
** statement, then the value returned is the name of the module that it
** uses. Otherwise, if the statement is not a CVT, NULL is returned.
*/
static void module_name_func(
  sqlite3_context *pCtx, 
  int nVal, sqlite3_value **apVal
){
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
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







-
+





-
+



-
+





-
+





-
+


-
+







  
    rc = sqlite3_create_function(
        g.db, "module_name", 1, SQLITE_UTF8, 0, module_name_func, 0, 0
    );
    assert( rc==SQLITE_OK );
  
    return 
      "SELECT name FROM main.sqlite_master\n"
      "SELECT name FROM main.sqlite_schema\n"
      " WHERE type='table' AND (\n"
      "    module_name(sql) IS NULL OR \n"
      "    module_name(sql) IN (SELECT module FROM temp.tblmap)\n"
      " ) AND name NOT IN (\n"
      "  SELECT a.name || b.postfix \n"
        "FROM main.sqlite_master AS a, temp.tblmap AS b \n"
        "FROM main.sqlite_schema AS a, temp.tblmap AS b \n"
        "WHERE module_name(a.sql) = b.module\n" 
      " )\n"
      "UNION \n"
      "SELECT name FROM aux.sqlite_master\n"
      "SELECT name FROM aux.sqlite_schema\n"
      " WHERE type='table' AND (\n"
      "    module_name(sql) IS NULL OR \n"
      "    module_name(sql) IN (SELECT module FROM temp.tblmap)\n"
      " ) AND name NOT IN (\n"
      "  SELECT a.name || b.postfix \n"
        "FROM aux.sqlite_master AS a, temp.tblmap AS b \n"
        "FROM aux.sqlite_schema AS a, temp.tblmap AS b \n"
        "WHERE module_name(a.sql) = b.module\n" 
      " )\n"
      " ORDER BY name";
  }else{
    return
      "SELECT name FROM main.sqlite_master\n"
      "SELECT name FROM main.sqlite_schema\n"
      " WHERE type='table' AND sql NOT LIKE 'CREATE VIRTUAL%%'\n"
      " UNION\n"
      "SELECT name FROM aux.sqlite_master\n"
      "SELECT name FROM aux.sqlite_schema\n"
      " WHERE type='table' AND sql NOT LIKE 'CREATE VIRTUAL%%'\n"
      " ORDER BY name";
  }
}

/*
** Print sketchy documentation for this utility program
1860
1861
1862
1863
1864
1865
1866

1867
1868
1869
1870
1871
1872
1873
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932







+







"  --primarykey          Use schema-defined PRIMARY KEYs\n"
"  --rbu                 Output SQL to create/populate RBU table(s)\n"
"  --schema              Show only differences in the schema\n"
"  --summary             Show only a summary of the differences\n"
"  --table TAB           Show only differences in table TAB\n"
"  --transaction         Show SQL output inside a transaction\n"
"  --vtab                Handle fts3, fts4, fts5 and rtree tables\n"
"See https://sqlite.org/sqldiff.html for detailed explanation.\n"
  );
}

int main(int argc, char **argv){
  const char *zDb1 = 0;
  const char *zDb2 = 0;
  int i;
1926
1927
1928
1929
1930
1931
1932



1933
1934
1935
1936
1937
1938
1939
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001







+
+
+







      }else
      if( strcmp(z,"summary")==0 ){
        xDiff = summarize_one_table;
      }else
      if( strcmp(z,"table")==0 ){
        if( i==argc-1 ) cmdlineError("missing argument to %s", argv[i]);
        zTab = argv[++i];
        g.bSchemaCompare =
          sqlite3_stricmp(zTab, "sqlite_schema")==0
          || sqlite3_stricmp(zTab, "sqlite_master")==0;
      }else
      if( strcmp(z,"transaction")==0 ){
        useTransaction = 1;
      }else
      if( strcmp(z,"vtab")==0 ){
        g.bHandleVtab = 1;
      }else
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
1984
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022

2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043

2044
2045
2046
2047
2048
2049
2050
2051







+
+
+




-
+















+
+



-
+







    }else{
      cmdlineError("unknown argument: %s", argv[i]);
    }
  }
  if( zDb2==0 ){
    cmdlineError("two database arguments required");
  }
  if( g.bSchemaOnly && g.bSchemaCompare ){
    cmdlineError("The --schema option is useless with --table %s .", zTab);
  }
  rc = sqlite3_open(zDb1, &g.db);
  if( rc ){
    cmdlineError("cannot open database file \"%s\"", zDb1);
  }
  rc = sqlite3_exec(g.db, "SELECT * FROM sqlite_master", 0, 0, &zErrMsg);
  rc = sqlite3_exec(g.db, "SELECT * FROM sqlite_schema", 0, 0, &zErrMsg);
  if( rc || zErrMsg ){
    cmdlineError("\"%s\" does not appear to be a valid SQLite database", zDb1);
  }
#ifndef SQLITE_OMIT_LOAD_EXTENSION
  sqlite3_enable_load_extension(g.db, 1);
  for(i=0; i<nExt; i++){
    rc = sqlite3_load_extension(g.db, azExt[i], 0, &zErrMsg);
    if( rc || zErrMsg ){
      cmdlineError("error loading %s: %s", azExt[i], zErrMsg);
    }
  }
  free(azExt);
#endif
  zSql = sqlite3_mprintf("ATTACH %Q as aux;", zDb2);
  rc = sqlite3_exec(g.db, zSql, 0, 0, &zErrMsg);
  sqlite3_free(zSql);
  zSql = 0;
  if( rc || zErrMsg ){
    cmdlineError("cannot attach database \"%s\"", zDb2);
  }
  rc = sqlite3_exec(g.db, "SELECT * FROM aux.sqlite_master", 0, 0, &zErrMsg);
  rc = sqlite3_exec(g.db, "SELECT * FROM aux.sqlite_schema", 0, 0, &zErrMsg);
  if( rc || zErrMsg ){
    cmdlineError("\"%s\" does not appear to be a valid SQLite database", zDb2);
  }

  if( neverUseTransaction ) useTransaction = 0;
  if( useTransaction ) fprintf(out, "BEGIN TRANSACTION;\n");
  if( xDiff==rbudiff_one_table ){

Changes to tool/sqlite3_analyzer.c.in.

10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
10
11
12
13
14
15
16

17
18
19
20
21
22
23
24







-
+







#define SQLITE_OMIT_DECLTYPE 1
#define SQLITE_OMIT_DEPRECATED 1
#define SQLITE_OMIT_PROGRESS_CALLBACK 1
#define SQLITE_OMIT_SHARED_CACHE 1
#define SQLITE_DEFAULT_MEMSTATUS 0
#define SQLITE_MAX_EXPR_DEPTH 0
#define SQLITE_OMIT_LOAD_EXTENSION 1
#ifndef USE_EXTERNAL_SQLITE
#if !defined(SQLITE_AMALGAMATION) && !defined(USE_EXTERNAL_SQLITE)
INCLUDE sqlite3.c
#endif
INCLUDE $ROOT/src/tclsqlite.c

const char *sqlite3_analyzer_init_proc(Tcl_Interp *interp){
  (void)interp;
  return

Added tool/stripccomments.c.





































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/**
   Strips C- and C++-style comments from stdin, sending the results to
   stdout. It assumes that its input is legal C-like code, and does
   only little error handling.

   It treats string literals as anything starting and ending with
   matching double OR single quotes OR backticks (for use with
   scripting languages which use those). It assumes that a quote
   character within a string which uses the same quote type is escaped
   by a backslash. It should not be used on any code which might
   contain C/C++ comments inside heredocs, and similar constructs, as
   it will strip those out.

   Usage: $0 [--keep-first|-k] < input > output

   The --keep-first (-k) flag tells it to retain the first comment in the
   input stream (which is often a license or attribution block). It
   may be given repeatedly, each one incrementing the number of
   retained comments by one.

   License: Public Domain
   Author: Stephan Beal (stephan@wanderinghorse.net)
*/
#include <stdio.h>
#include <assert.h>
#include <string.h>

#if 1
#define MARKER(pfexp)                                                \
  do{ printf("MARKER: %s:%d:\t",__FILE__,__LINE__);                  \
    printf pfexp;                                                    \
  } while(0)
#else
#define MARKER(exp) if(0) printf
#endif

struct {
  FILE * input;
  FILE * output;
  int rc;
  int keepFirst;
} App = {
  0/*input*/,
  0/*output*/,
  0/*rc*/,
  0/*keepFirst*/
};

void do_it_all(void){
  enum states {
    S_NONE = 0 /* not in comment */,
    S_SLASH1 = 1 /* slash - possibly comment prefix */,
    S_CPP = 2 /* in C++ comment */,
    S_C = 3 /* in C comment */
  };
  int ch, prev = EOF;
  FILE * out = App.output;
  int const slash = '/';
  int const star = '*';
  int line = 1;
  int col = 0;
  enum states state = S_NONE /* current state */;
  int elide = 0 /* true if currently eliding output */;
  int state3Col = -99
    /* huge kludge for odd corner case: */
    /*/ <--- here. state3Col marks the source column in which a C-style
      comment starts, so that it can tell if star-slash inside a
      C-style comment is the end of the comment or is the weird corner
      case marked at the start of _this_ comment block. */;
  for( ; EOF != (ch = fgetc(App.input)); prev = ch,
         ++col){
    switch(state){
      case S_NONE:
        if('\''==ch || '"'==ch || '`'==ch){
          /* Read string literal...
             needed to properly catch comments in strings. */
          int const quote = ch,
            startLine = line, startCol = col;
          int ch2, escaped = 0, endOfString = 0;
          fputc(ch, out);
          for( ++col; !endOfString && EOF != (ch2 = fgetc(App.input));
               ++col ){
            switch(ch2){
              case '\\': escaped = !escaped;
                break;
              case '`':
              case '\'':
              case '"':
                if(!escaped && quote == ch2) endOfString = 1;
                escaped = 0;
                break;
              default:
                escaped = 0;
                break;
            }
            if('\n'==ch2){
              ++line;
              col = 0;
            }
            fputc(ch2, out);
          }
          if(EOF == ch2){
            fprintf(stderr, "Unexpected EOF while reading %s literal "
                    "on line %d column %d.\n",
                    ('\''==ch) ? "char" : "string",
                    startLine, startCol);
            App.rc = 1;
            return;
          }
          break;
        }
        else if(slash == ch){
          /* MARKER(("state 0 ==> 1 @ %d:%d\n", line, col)); */
          state = S_SLASH1;
          break;
        }
        fputc(ch, out);
        break;
      case S_SLASH1: /* 1 slash */
        /* MARKER(("SLASH1 @ %d:%d App.keepFirst=%d\n",
           line, col, App.keepFirst)); */
        switch(ch){
          case '*':
            /* Enter C comment */
            if(App.keepFirst>0){
              elide = 0;
              --App.keepFirst;
            }else{
              elide = 1;
            }
            /*MARKER(("state 1 ==> 3 @ %d:%d\n", line, col));*/
            state = S_C;
            state3Col = col-1;
            if(!elide){
              fputc(prev, out);
              fputc(ch, out);
            }
            break;
          case '/':
            /* Enter C++ comment */
            if(App.keepFirst>0){
              elide = 0;
              --App.keepFirst;
            }else{
              elide = 1;
            }
            /*MARKER(("state 1 ==> 2 @ %d:%d\n", line, col));*/
            state = S_CPP;
            if(!elide){
              fputc(prev, out);
              fputc(ch, out);
            }
            break;
          default:
            /* It wasn't a comment after all. */
            state = S_NONE;
            if(!elide){
              fputc(prev, out);
              fputc(ch, out);
            }
        }
        break;
      case S_CPP: /* C++ comment */
        if('\n' == ch){
          /* MARKER(("state 2 ==> 0 @ %d:%d\n", line, col)); */
          state = S_NONE;
          elide = 0;
        }
        if(!elide){
          fputc(ch, out);
        }
        break;
      case S_C: /* C comment */
        if(!elide){
          fputc(ch, out);
        }
        if(slash == ch){
          if(star == prev){
            /* MARKER(("state 3 ==> 0 @ %d:%d\n", line, col)); */
            /* Corner case which breaks this: */
            /*/ <-- slash there */
            /* That shows up twice in a piece of 3rd-party
               code i use. */
            /* And thus state3Col was introduced :/ */
            if(col!=state3Col+2){
              state = S_NONE;
              elide = 0;
              state3Col = -99;
            }
          }
        }
        break;
      default:
        assert(!"impossible!");
        break;
    }
    if('\n' == ch){
      ++line;
      col = 0;
      state3Col = -99;
    }
  }
}

static void usage(char const *zAppName){
  fprintf(stderr, "Strips C- and C++-style comments from stdin and sends "
          "the results to stdout.\n");
  fprintf(stderr, "Usage: %s [--keep-first|-k] < input > output\n", zAppName);
}

int main( int argc, char const * const * argv ){
  int i;
  for(i = 1; i < argc; ++i){
    char const * zArg = argv[i];
    while( '-'==*zArg ) ++zArg;
    if( 0==strcmp(zArg,"k")
        || 0==strcmp(zArg,"keep-first") ){
      ++App.keepFirst;
    }else{
      usage(argv[0]);
      return 1;
    }
  }
  App.input = stdin;
  App.output = stdout;
  do_it_all();
  return App.rc ? 1 : 0;
}

Changes to tool/symbols.sh.

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
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







-
+




-
+
+



-
-
+
+
+







#!/bin/sh
#
# Run this script in a directory that contains a valid SQLite makefile in
# order to verify that unintentionally exported symbols.
#
make sqlite3.c

echo '****** Exported symbols from a build including RTREE, FTS4 & ICU ******'
echo '****** Exported symbols from a build including RTREE, FTS4 & FTS5 ******'
gcc -c -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE \
  -DSQLITE_ENABLE_MEMORY_MANAGEMENT -DSQLITE_ENABLE_STAT3 \
  -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_ENABLE_UNLOCK_NOTIFY \
  -DSQLITE_ENABLE_COLUMN_METADATA -DSQLITE_ENABLE_ATOMIC_WRITE \
  -DSQLITE_ENABLE_ICU -DSQLITE_ENABLE_PREUPDATE_HOOK -DSQLITE_ENABLE_SESSION \
  -DSQLITE_ENABLE_PREUPDATE_HOOK -DSQLITE_ENABLE_SESSION \
  -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_GEOPOLY \
  sqlite3.c
nm sqlite3.o | grep ' [TD] ' | sort -k 3

echo '****** Surplus symbols from a build including RTREE, FTS4 & ICU ******'
nm sqlite3.o | grep ' [TD] ' | grep -v ' .*sqlite3_'
echo '****** Surplus symbols from a build including RTREE, FTS4 & FTS5 ******'
nm sqlite3.o | grep ' [TD] ' |
   egrep -v ' .*sqlite3(session|rebaser|changeset|changegroup)?_'

echo '****** Dependencies of the core. No extensions. No OS interface *******'
gcc -c -DSQLITE_ENABLE_MEMORY_MANAGEMENT -DSQLITE_ENABLE_STAT3 \
  -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_ENABLE_UNLOCK_NOTIFY \
  -DSQLITE_ENABLE_COLUMN_METADATA -DSQLITE_ENABLE_ATOMIC_WRITE \
  -DSQLITE_OS_OTHER -DSQLITE_THREADSAFE=0 \
  sqlite3.c

Added tool/tserver.c.




































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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
638
639
640
641
642
643
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2017 June 7
**
** 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.
**
*************************************************************************
**
** Simple multi-threaded server used for informal testing of concurrency
** between connections in different threads. Listens for tcp/ip connections
** on port 9999 of the 127.0.0.1 interface only. To build:
**
**   gcc -g $(TOP)/tool/tserver.c sqlite3.o -lpthread -o tserver
**
** To run using "x.db" as the db file:
**
**   ./tserver x.db
**
** To connect, open a client socket on port 9999 and start sending commands.
** Commands are either SQL - which must be terminated by a semi-colon, or
** dot-commands, which must be terminated by a newline. If an SQL statement
** is seen, it is prepared and added to an internal list.
**
** Dot-commands are:
**
**   .list                    Display all SQL statements in the list.
**   .quit                    Disconnect.
**   .run                     Run all SQL statements in the list.
**   .repeats N               Configure the number of repeats per ".run".
**   .seconds N               Configure the number of seconds to ".run" for.
**   .mutex_commit            Add a "COMMIT" protected by a g.commit_mutex
**                            to the current SQL.
**   .stop                    Stop the tserver process - exit(0).
**   .checkpoint N
**   .integrity_check
**
** Example input:
**
**   BEGIN;
**     INSERT INTO t1 VALUES(randomblob(10), randomblob(100));
**     INSERT INTO t1 VALUES(randomblob(10), randomblob(100));
**     INSERT INTO t1 VALUES(randomblob(10), randomblob(100));
**   COMMIT;
**   .repeats 100000
**   .run
**
*/
#define TSERVER_PORTNUMBER 9999

#include <arpa/inet.h>
#include <assert.h>
#include <pthread.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <unistd.h>

#include "sqlite3.h"

#define TSERVER_DEFAULT_CHECKPOINT_THRESHOLD 3900

/* Global variables */
struct TserverGlobal {
  char *zDatabaseName;             /* Database used by this server */
  char *zVfs;
  sqlite3_mutex *commit_mutex;
  sqlite3 *db;                     /* Global db handle */

  /* The following use native pthreads instead of a portable interface. This
  ** is because a condition variable, as well as a mutex, is required.  */
  pthread_mutex_t ckpt_mutex;
  pthread_cond_t ckpt_cond;
  int nThreshold;                  /* Checkpoint when wal is this large */
  int bCkptRequired;               /* True if wal checkpoint is required */
  int nRun;                        /* Number of clients in ".run" */
  int nWait;                       /* Number of clients waiting on ckpt_cond */
};

static struct TserverGlobal g = {0};

typedef struct ClientSql ClientSql;
struct ClientSql {
  sqlite3_stmt *pStmt;
  int flags;
};

#define TSERVER_CLIENTSQL_MUTEX     0x0001
#define TSERVER_CLIENTSQL_INTEGRITY 0x0002

typedef struct ClientCtx ClientCtx;
struct ClientCtx {
  sqlite3 *db;                    /* Database handle for this client */
  int fd;                         /* Client fd */
  int nRepeat;                    /* Number of times to repeat SQL */
  int nSecond;                    /* Number of seconds to run for */
  ClientSql *aPrepare;            /* Array of prepared statements */
  int nPrepare;                   /* Valid size of apPrepare[] */
  int nAlloc;                     /* Allocated size of apPrepare[] */

  int nClientThreshold;           /* Threshold for checkpointing */
  int bClientCkptRequired;        /* True to do a checkpoint */
};

static int is_eol(int i){
  return (i=='\n' || i=='\r');
}
static int is_whitespace(int i){
  return (i==' ' || i=='\t' || is_eol(i));
}

/*
** Implementation of SQL scalar function usleep().
*/
static void usleepFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  int nUs;
  sqlite3_vfs *pVfs = (sqlite3_vfs*)sqlite3_user_data(context);
  assert( argc==1 );
  nUs = sqlite3_value_int64(argv[0]);
  pVfs->xSleep(pVfs, nUs);
}

static void trim_string(const char **pzStr, int *pnStr){
  const char *zStr = *pzStr;
  int nStr = *pnStr;

  while( nStr>0 && is_whitespace(zStr[0]) ){
    zStr++;
    nStr--;
  }
  while( nStr>0 && is_whitespace(zStr[nStr-1]) ){
    nStr--;
  }

  *pzStr = zStr;
  *pnStr = nStr;
}

static int send_message(ClientCtx *p, const char *zFmt, ...){
  char *zMsg;
  va_list ap;                             /* Vararg list */
  va_start(ap, zFmt);
  int res = -1;

  zMsg = sqlite3_vmprintf(zFmt, ap);
  if( zMsg ){
    res = write(p->fd, zMsg, strlen(zMsg));
  }
  sqlite3_free(zMsg);
  va_end(ap);

  return (res<0);
}

static int handle_some_sql(ClientCtx *p, const char *zSql, int nSql){
  const char *zTail = zSql;
  int nTail = nSql;
  int rc = SQLITE_OK;

  while( rc==SQLITE_OK ){
    if( p->nPrepare>=p->nAlloc ){
      int nByte = (p->nPrepare+32) * sizeof(ClientSql);
      ClientSql *aNew = sqlite3_realloc(p->aPrepare, nByte);
      if( aNew ){
        memset(&aNew[p->nPrepare], 0, sizeof(ClientSql)*32);
        p->aPrepare = aNew;
        p->nAlloc = p->nPrepare+32;
      }else{
        rc = SQLITE_NOMEM;
        break;
      }
    }
    rc = sqlite3_prepare_v2(
        p->db, zTail, nTail, &p->aPrepare[p->nPrepare].pStmt, &zTail
    );
    if( rc!=SQLITE_OK ){
      send_message(p, "error - %s (eec=%d)\n", sqlite3_errmsg(p->db),
          sqlite3_extended_errcode(p->db)
      );
      rc = 1;
      break;
    }
    if( p->aPrepare[p->nPrepare].pStmt==0 ){
      break;
    }
    p->nPrepare++;
    nTail = nSql - (zTail-zSql);
    rc = send_message(p, "ok (%d SQL statements)\n", p->nPrepare);
  }

  return rc;
}

/*
** Return a micro-seconds resolution timer.
*/
static sqlite3_int64 get_timer(void){
  struct timeval t;
  gettimeofday(&t, 0);
  return (sqlite3_int64)t.tv_usec + ((sqlite3_int64)t.tv_sec * 1000000);
}

static void clear_sql(ClientCtx *p){
  int j;
  for(j=0; j<p->nPrepare; j++){
    sqlite3_finalize(p->aPrepare[j].pStmt);
  }
  p->nPrepare = 0;
}

/*
** The sqlite3_wal_hook() callback used by all client database connections.
*/
static int clientWalHook(void *pArg, sqlite3 *db, const char *zDb, int nFrame){
  if( g.nThreshold>0 ){
    if( nFrame>=g.nThreshold ){
      g.bCkptRequired = 1;
    }
  }else{
    ClientCtx *pCtx = (ClientCtx*)pArg;
    if( pCtx->nClientThreshold && nFrame>=pCtx->nClientThreshold ){
      pCtx->bClientCkptRequired = 1;
    }
  }
  return SQLITE_OK;
}

static int handle_run_command(ClientCtx *p){
  int i, j;
  int nBusy = 0;
  sqlite3_int64 t0 = get_timer();
  sqlite3_int64 t1 = t0;
  sqlite3_int64 tCommit = 0;
  int nT1 = 0;
  int nTBusy1 = 0;
  int rc = SQLITE_OK;

  pthread_mutex_lock(&g.ckpt_mutex);
  g.nRun++;
  pthread_mutex_unlock(&g.ckpt_mutex);

  for(j=0; (p->nRepeat<=0 || j<p->nRepeat) && rc==SQLITE_OK; j++){
    sqlite3_int64 t2;

    for(i=0; i<p->nPrepare && rc==SQLITE_OK; i++){
      sqlite3_stmt *pStmt = p->aPrepare[i].pStmt;

      /* If the MUTEX flag is set, grab g.commit_mutex before executing
      ** the SQL statement (which is always "COMMIT" in this case). */
      if( p->aPrepare[i].flags & TSERVER_CLIENTSQL_MUTEX ){
        sqlite3_mutex_enter(g.commit_mutex);
        tCommit -= get_timer();
      }

      /* Execute the statement */
      if( p->aPrepare[i].flags & TSERVER_CLIENTSQL_INTEGRITY ){
        sqlite3_step(pStmt);
        if( sqlite3_stricmp("ok", (const char*)sqlite3_column_text(pStmt, 0)) ){
          send_message(p, "error - integrity_check failed: %s\n", 
              sqlite3_column_text(pStmt, 0)
          );
        }
        sqlite3_reset(pStmt);
      }
      while( sqlite3_step(pStmt)==SQLITE_ROW );
      rc = sqlite3_reset(pStmt);

      /* Relinquish the g.commit_mutex mutex if required. */
      if( p->aPrepare[i].flags & TSERVER_CLIENTSQL_MUTEX ){
        tCommit += get_timer();
        sqlite3_mutex_leave(g.commit_mutex);
      }

      if( (rc & 0xFF)==SQLITE_BUSY ){
        if( sqlite3_get_autocommit(p->db)==0 ){
          sqlite3_exec(p->db, "ROLLBACK", 0, 0, 0);
        }
        nBusy++;
        rc = SQLITE_OK;
        break;
      }
      else if( rc!=SQLITE_OK ){
        send_message(p, "error - %s (eec=%d)\n", sqlite3_errmsg(p->db),
            sqlite3_extended_errcode(p->db)
        );
      }
    }

    t2 = get_timer();
    if( t2>=(t1+1000000) ){
      sqlite3_int64 nUs = (t2 - t1);
      sqlite3_int64 nDone = (j+1 - nBusy - nT1);

      rc = send_message(
          p, "(%d done @ %lld per second, %d busy)\n", 
          (int)nDone, (1000000*nDone + nUs/2) / nUs, nBusy - nTBusy1
      );
      t1 = t2;
      nT1 = j+1 - nBusy;
      nTBusy1 = nBusy;
      if( p->nSecond>0 && ((sqlite3_int64)p->nSecond*1000000)<=t1-t0 ) break;
    }

    /* Global checkpoint handling. */
    if( g.nThreshold>0 ){
      pthread_mutex_lock(&g.ckpt_mutex);
      if( rc==SQLITE_OK && g.bCkptRequired ){
        if( g.nWait==g.nRun-1 ){
          /* All other clients are already waiting on the condition variable.
          ** Run the checkpoint, signal the condition and move on.  */
          rc = sqlite3_wal_checkpoint(p->db, "main");
          g.bCkptRequired = 0;
          pthread_cond_broadcast(&g.ckpt_cond);
        }else{
          assert( g.nWait<g.nRun-1 );
          g.nWait++;
          pthread_cond_wait(&g.ckpt_cond, &g.ckpt_mutex);
          g.nWait--;
        }
      }
      pthread_mutex_unlock(&g.ckpt_mutex);
    }

    if( rc==SQLITE_OK && p->bClientCkptRequired ){
      rc = sqlite3_wal_checkpoint(p->db, "main");
      if( rc==SQLITE_BUSY ) rc = SQLITE_OK;
      assert( rc==SQLITE_OK );
      p->bClientCkptRequired = 0;
    }
  }

  if( rc==SQLITE_OK ){
    int nMs = (get_timer() - t0) / 1000;
    send_message(p, "ok (%d/%d SQLITE_BUSY)\n", nBusy, j);
    if( p->nRepeat<=0 ){
      send_message(p, "### ok %d busy %d ms %d commit-ms %d\n", 
          j-nBusy, nBusy, nMs, (int)(tCommit / 1000)
      );
    }
  }
  clear_sql(p);

  pthread_mutex_lock(&g.ckpt_mutex);
  g.nRun--;
  pthread_mutex_unlock(&g.ckpt_mutex);

  return rc;
}

static int handle_dot_command(ClientCtx *p, const char *zCmd, int nCmd){
  int n;
  int rc = 0;
  const char *z = &zCmd[1];
  const char *zArg;
  int nArg;

  assert( zCmd[0]=='.' );
  for(n=0; n<(nCmd-1); n++){
    if( is_whitespace(z[n]) ) break;
  }

  zArg = &z[n];
  nArg = nCmd-n;
  trim_string(&zArg, &nArg);

  if( n>=1 && n<=4 && 0==strncmp(z, "list", n) ){
    int i;
    for(i=0; rc==0 && i<p->nPrepare; i++){
      const char *zSql = sqlite3_sql(p->aPrepare[i].pStmt);
      int nSql = strlen(zSql);
      trim_string(&zSql, &nSql);
      rc = send_message(p, "%d: %.*s\n", i, nSql, zSql);
    }
  }

  else if( n>=1 && n<=4 && 0==strncmp(z, "quit", n) ){
    rc = -1;
  }

  else if( n>=2 && n<=7 && 0==strncmp(z, "repeats", n) ){
    if( nArg ){
      p->nRepeat = strtol(zArg, 0, 0);
      if( p->nRepeat>0 ) p->nSecond = 0;
    }
    rc = send_message(p, "ok (repeat=%d)\n", p->nRepeat);
  }

  else if( n>=2 && n<=3 && 0==strncmp(z, "run", n) ){
    rc = handle_run_command(p);
  }

  else if( n>=2 && n<=7 && 0==strncmp(z, "seconds", n) ){
    if( nArg ){
      p->nSecond = strtol(zArg, 0, 0);
      if( p->nSecond>0 ) p->nRepeat = 0;
    }
    rc = send_message(p, "ok (seconds=%d)\n", p->nSecond);
  }

  else if( n>=1 && n<=12 && 0==strncmp(z, "mutex_commit", n) ){
    rc = handle_some_sql(p, "COMMIT;", 7);
    if( rc==SQLITE_OK ){
      p->aPrepare[p->nPrepare-1].flags |= TSERVER_CLIENTSQL_MUTEX;
    }
  }

  else if( n>=1 && n<=10 && 0==strncmp(z, "checkpoint", n) ){
    if( nArg ){
      p->nClientThreshold = strtol(zArg, 0, 0);
    }
    rc = send_message(p, "ok (checkpoint=%d)\n", p->nClientThreshold);
  }

  else if( n>=2 && n<=4 && 0==strncmp(z, "stop", n) ){
    sqlite3_close(g.db);
    exit(0);
  }

  else if( n>=2 && n<=15 && 0==strncmp(z, "integrity_check", n) ){
    rc = handle_some_sql(p, "PRAGMA integrity_check;", 23);
    if( rc==SQLITE_OK ){
      p->aPrepare[p->nPrepare-1].flags |= TSERVER_CLIENTSQL_INTEGRITY;
    }
  }

  else{
    send_message(p, 
        "unrecognized dot command: %.*s\n"
        "should be \"list\", \"run\", \"repeats\", \"mutex_commit\", "
        "\"checkpoint\", \"integrity_check\" or \"seconds\"\n", n, z
    );
    rc = 1;
  }

  return rc;
}

static void *handle_client(void *pArg){
  char zCmd[32*1024];             /* Read buffer */
  int nCmd = 0;                   /* Valid bytes in zCmd[] */
  int res;                        /* Result of read() call */
  int rc = SQLITE_OK;

  ClientCtx ctx;
  memset(&ctx, 0, sizeof(ClientCtx));

  ctx.fd = (int)(intptr_t)pArg;
  ctx.nRepeat = 1;
  rc = sqlite3_open_v2(g.zDatabaseName, &ctx.db,
      SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, g.zVfs
  );
  if( rc!=SQLITE_OK ){
    fprintf(stderr, "sqlite3_open(): %s\n", sqlite3_errmsg(ctx.db));
    return 0;
  }
  sqlite3_create_function(
      ctx.db, "usleep", 1, SQLITE_UTF8, (void*)sqlite3_vfs_find(0), 
      usleepFunc, 0, 0
  );

  /* Register the wal-hook with the new client connection */
  sqlite3_wal_hook(ctx.db, clientWalHook, (void*)&ctx);

  while( rc==SQLITE_OK ){
    int i;
    int iStart;
    int nConsume;
    res = read(ctx.fd, &zCmd[nCmd], sizeof(zCmd)-nCmd-1);
    if( res<=0 ) break;
    nCmd += res;
    if( nCmd>=sizeof(zCmd)-1 ){
      fprintf(stderr, "oversized (>32KiB) message\n");
      res = 0;
      break;
    }
    zCmd[nCmd] = '\0';

    do {
      nConsume = 0;

      /* Gobble up any whitespace */
      iStart = 0;
      while( is_whitespace(zCmd[iStart]) ) iStart++;

      if( zCmd[iStart]=='.' ){
        /* This is a dot-command. Search for end-of-line. */
        for(i=iStart; i<nCmd; i++){
          if( is_eol(zCmd[i]) ){
            rc = handle_dot_command(&ctx, &zCmd[iStart], i-iStart);
            nConsume = i+1;
            break;
          }
        }
      }else{

        int iSemi;
        char c = 0;
        for(iSemi=iStart; iSemi<nCmd; iSemi++){
          if( zCmd[iSemi]==';' ){
            c = zCmd[iSemi+1];
            zCmd[iSemi+1] = '\0';
            break;
          }
        }

        if( iSemi<nCmd ){
          if( sqlite3_complete(zCmd) ){
            rc = handle_some_sql(&ctx, zCmd, iSemi+1);
            nConsume = iSemi+1;
          }

          if( c ){
            zCmd[iSemi+1] = c;
          }
        }
      }

      if( nConsume>0 ){
        nCmd = nCmd-nConsume;
        if( nCmd>0 ){
          memmove(zCmd, &zCmd[nConsume], nCmd);
        }
      }
    }while( rc==SQLITE_OK && nConsume>0 );
  }

  fprintf(stdout, "Client %d disconnects (rc=%d)\n", ctx.fd, rc);
  fflush(stdout);
  close(ctx.fd);
  clear_sql(&ctx);
  sqlite3_free(ctx.aPrepare);
  sqlite3_close(ctx.db);
  return 0;
} 

static void usage(const char *zExec){
  fprintf(stderr, "Usage: %s ?-vfs VFS? DATABASE\n", zExec);
  exit(1);
}

int main(int argc, char *argv[]) {
  int sfd;
  int rc;
  int yes = 1;
  struct sockaddr_in server;
  int i;

  /* Ignore SIGPIPE. Otherwise the server exits if a client disconnects
  ** abruptly.  */
  signal(SIGPIPE, SIG_IGN);

  g.nThreshold = TSERVER_DEFAULT_CHECKPOINT_THRESHOLD;
  if( (argc%2) ) usage(argv[0]);
  for(i=1; i<(argc-1); i+=2){
    int n = strlen(argv[i]);
    if( n>=2 && 0==sqlite3_strnicmp("-walautocheckpoint", argv[i], n) ){
      g.nThreshold = strtol(argv[i+1], 0, 0);
    }else 
    if( n>=2 && 0==sqlite3_strnicmp("-vfs", argv[i], n) ){
      g.zVfs = argv[i+1];
    }
  }
  g.zDatabaseName = argv[argc-1];

  g.commit_mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
  pthread_mutex_init(&g.ckpt_mutex, 0);
  pthread_cond_init(&g.ckpt_cond, 0);

  rc = sqlite3_open_v2(g.zDatabaseName, &g.db,
      SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, g.zVfs
  );
  if( rc!=SQLITE_OK ){
    fprintf(stderr, "sqlite3_open(): %s\n", sqlite3_errmsg(g.db));
    return 1;
  }

  rc = sqlite3_exec(g.db, "SELECT * FROM sqlite_master", 0, 0, 0);
  if( rc!=SQLITE_OK ){
    fprintf(stderr, "sqlite3_exec(): %s\n", sqlite3_errmsg(g.db));
    return 1;
  }

  sfd = socket(AF_INET, SOCK_STREAM, 0);
  if( sfd<0 ){
    fprintf(stderr, "socket() failed\n");
    return 1;
  }

  rc = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
  if( rc<0 ){
    perror("setsockopt");
    return 1;
  }

  memset(&server, 0, sizeof(server));
  server.sin_family = AF_INET;
  server.sin_addr.s_addr = inet_addr("127.0.0.1");
  server.sin_port = htons(TSERVER_PORTNUMBER);

  rc = bind(sfd, (struct sockaddr *)&server, sizeof(struct sockaddr));
  if( rc<0 ){
    fprintf(stderr, "bind() failed\n");
    return 1;
  }

  rc = listen(sfd, 8);
  if( rc<0 ){
    fprintf(stderr, "listen() failed\n");
    return 1;
  }

  while( 1 ){
    pthread_t tid;
    int cfd = accept(sfd, NULL, NULL);
    if( cfd<0 ){
      perror("accept()");
      return 1;
    }

    fprintf(stdout, "Client %d connects\n", cfd);
    fflush(stdout);
    rc = pthread_create(&tid, NULL, handle_client, (void*)(intptr_t)cfd);
    if( rc!=0 ){
      perror("pthread_create()");
      return 1;
    }

    pthread_detach(tid);
  }

  return 0;
}

Added tool/tserver_test.tcl.

















































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
#!/usr/bin/tclsh
#
# This script is used to run the performance test cases described in
# README-server-edition.html.
#


package require sqlite3

# Default values for command line switches:
set O(-database)  ""
set O(-rows)      [expr 5000000]
set O(-mode)      wal2
set O(-tserver)   "./tserver"
set O(-seconds)   20
set O(-writers)   1
set O(-readers)   0
set O(-integrity) 0
set O(-verbose)   0
set O(-external)   0


proc error_out {err} {
  puts stderr $err
  exit -1
}

proc usage {} {
  puts stderr "Usage: $::argv0 ?OPTIONS?"
  puts stderr ""
  puts stderr "Where OPTIONS are:"
  puts stderr "  -database <database file>             (default: test.db)"
  puts stderr "  -mode <mode>                          (default: wal2)"
  puts stderr "  -rows <number of rows>                (default: 5000000)"
  puts stderr "  -tserver <path to tserver executable> (default: ./tserver)"
  puts stderr "  -seconds <time to run for in seconds> (default: 20)"
  puts stderr "  -writers <number of writer clients>   (default: 1)"
  puts stderr "  -readers <number of reader clients>   (default: 0)"
  puts stderr "  -integrity <number of IC clients>     (default: 0)"
  puts stderr "  -verbose 0|1                          (default: 0)"
  puts stderr "  -external 0|1                         (default: 0)"
  exit -1
}

for {set i 0} {$i < [llength $argv]} {incr i} {
  set opt ""
  set arg [lindex $argv $i]
  set n [expr [string length $arg]-1]
  foreach k [array names ::O] {
    if {[string range $k 0 $n]==$arg} {
      if {$opt==""} {
        set opt $k
      } else {
        error_out "ambiguous option: $arg ($k or $opt)"
      }
    }
  }
  if {$opt==""} { usage }
  if {$i==[llength $argv]-1} {
    error_out "option requires an argument: $opt"
  }
  incr i
  set val [lindex $argv $i]
  switch -- $opt {
    -mode {
      if {$val != "wal" && $val != "wal2"} {
        set xyz "\"wal\" or \"wal2\""
        error_out "Found \"$val\" - expected $xyz"
      }
    }
  }
  set O($opt) [lindex $argv $i]
}
if {$O(-database)==""} {
  set O(-database) "test.db"
}

set O(-rows) [expr $O(-rows)]

#--------------------------------------------------------------------------
# Create and populate the required test database, if it is not already 
# present in the file-system.
#
proc create_test_database {} {
  global O

  if {$O(-external)} return

  if {[file exists $O(-database)]} {
    sqlite3 db $O(-database)

    # Check the schema looks Ok.
    set s [db one {
      SELECT group_concat(name||pk, '.') FROM pragma_table_info('t1');
    }]
    if {$s != "a1.b0.c0.d0"} {
      error_out "Database $O(-database) exists but is not usable (schema)"
    }

    # Check that the row count matches.
    set n [db one { SELECT count(*) FROM t1 }]
    if {$n != $O(-rows)} {
      error_out "Database $O(-database) exists but is not usable (row-count)"
    }
    db close
  } else {
    catch { file delete -force $O(-database)-journal }
    catch { file delete -force $O(-database)-wal }

    if {$O(-verbose)} {
      puts "Building database $O(-database)..."
    }

    sqlite3 db $O(-database)
    db eval {
      CREATE TABLE t1(
        a INTEGER PRIMARY KEY, 
        b BLOB(16), 
        c BLOB(16), 
        d BLOB(400)
      );
      CREATE INDEX i1 ON t1(b);
      CREATE INDEX i2 ON t1(c);

      WITH s(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<$O(-rows))
      INSERT INTO t1 
      SELECT i-1, randomblob(16), randomblob(16), randomblob(400) FROM s;
    }
    db close
  }

  switch -- $O(-mode) {
    wal {
      sqlite3 db $O(-database)
      db eval {PRAGMA journal_mode = delete}
      db eval {PRAGMA journal_mode = wal}
      db close
    }

    wal2 {
      sqlite3 db $O(-database)
      db eval {PRAGMA journal_mode = delete}
      db eval {PRAGMA journal_mode = wal2}
      db close
    }
  }
}

#-------------------------------------------------------------------------
# Functions to start and stop the tserver process:
#
#   tserver_start
#   tserver_stop
#
set ::tserver {}
proc tserver_start {} {
  global O
  if {$O(-external)} return
  set cmd "|$O(-tserver) -vfs unix-excl "
  if {$O(-mode)=="wal2"} {
    append cmd " -walautocheckpoint 0 "
  }
  append cmd "$O(-database)"
  set ::tserver [open $cmd]
  fconfigure $::tserver -blocking 0
  fileevent $::tserver readable tserver_data
}

proc tserver_data {} {
  global O
  if {[eof $::tserver]} {
    error_out "tserver has exited"
  }
  set line [gets $::tserver]
  if {$line != "" && $O(-verbose)} {
    puts "tserver: $line"
  }
}

proc tserver_stop {} {
  global O
  if {$O(-external)} return
  close $::tserver
  set fd [socket localhost 9999]
  puts $fd ".stop"
  close $fd
}
#-------------------------------------------------------------------------

set ::nClient 0
set ::client_output [list]

proc client_data {name fd} {
  global O
  if {[eof $fd]} {
    incr ::nClient -1
    close $fd
    return
  }
  set str [gets $fd]
  if {[string trim $str]!=""} {
    if {[string range $str 0 3]=="### "} {
      lappend ::client_output [concat [list name $name] [lrange $str 1 end]]
    } 
    if {$O(-verbose)} {
      puts "$name: $str"
    }
  }
}

proc client_launch {name script} {
  global O
  set fd [socket localhost 9999]
  fconfigure $fd -blocking 0
  puts $fd "PRAGMA synchronous = OFF;"
  puts $fd ".repeat 1"
  puts $fd ".run"
  puts $fd $script
  puts $fd ".seconds $O(-seconds)"
  puts $fd ".run"
  puts $fd ".quit"
  flush $fd
  incr ::nClient
  fileevent $fd readable [list client_data $name $fd]
}

proc client_wait {} {
  while {$::nClient>0} {vwait ::nClient}
}

proc script_writer {bCkpt} {
  global O

  set commit ".mutex_commit"
  set begin "BEGIN CONCURRENT;"
  set ckpt ""
  if {$bCkpt} {
    set ckpt ".checkpoint 2000"
  }

  set tail "randomblob(16), randomblob(16), randomblob(400));"
  return [subst -nocommands {
    $ckpt
    $begin
      REPLACE INTO t1 VALUES(abs(random() % $O(-rows)), $tail
    $commit
  }]
}

proc script_reader {} {
  global O

  return [subst -nocommands {
    BEGIN;
      SELECT * FROM t1 WHERE a>abs((random()%$O(-rows))) LIMIT 10;
    END;
  }]
}

proc script_integrity {} {
  global O

  return {
    .integrity_check
  }
}


create_test_database
tserver_start

for {set i 0} {$i < $O(-writers)} {incr i} {
  client_launch w.$i [script_writer [expr {$i==0 && $O(-mode)=="wal2"}]]
}
for {set i 0} {$i < $O(-readers)} {incr i} {
  client_launch r.$i [script_reader]
}
for {set i 0} {$i < $O(-integrity)} {incr i} {
  client_launch i.$i [script_integrity]
}
client_wait

set name(w) "Writers"
set name(r) "Readers"
set name(i) "Integrity"
foreach r $::client_output {
  array set a $r
  set type [string range $a(name) 0 0]
  incr x($type.ok) $a(ok);
  incr x($type.busy) $a(busy);
  incr x($type.n) 1
  set t($type) 1
}

foreach type [array names t] {
  set nTPS [expr $x($type.ok) / $O(-seconds)]
  set nC [expr $nTPS / $x($type.n)]
  set nTotal [expr $x($type.ok) + $x($type.busy)]
  set bp [format %.2f [expr $x($type.busy) * 100.0 / $nTotal]]
  puts "$name($type): $nTPS transactions/second ($nC per client) ($bp% busy)"
}

tserver_stop

Changes to tool/vdbe-compress.tcl.

61
62
63
64
65
66
67
68

69
70
71
72
73
74
75
61
62
63
64
65
66
67

68
69
70
71
72
73
74
75







-
+







  append beforeUnion $line\n
}

# Process the remaining text.  Build up the union definition as we go.
#
set vlist {}
set seenDecl 0
set namechars {abcdefghijklmnopqrstuvwxyz}
set namechars {abcefghjklmnopqrstuvwxyz}
set nnc [string length $namechars]
while {![eof stdin]} {
  set line [gets stdin]
  if {[regexp "^case (OP_\\w+): \173" $line all operator]} {
    append afterUnion $line\n
    set vlist {}
    while {![eof stdin]} {

Changes to tool/vdbe_profile.tcl.

62
63
64
65
66
67
68


69
70
71
72
73
74
75
76


77


78
79
80
81
82
83
84
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







+
+








+
+

+
+







}
close $in

foreach stmt $allstmt {
  puts "********************************************************************"
  puts [string trim $sql($stmt)]
  puts "Execution count: $cnt($stmt)"
  set tcx 0
  set ttx 0
  for {set i 0} {[info exists stat($stmt,$i)]} {incr i} {
    foreach {cx tx detail} $stat($stmt,$i) break
    if {$cx==0} {
      set ax 0
    } else {
      set ax [expr {$tx/$cx}]
    }
    puts [format {%8d %12d %12d %4d %s} $cx $tx $ax $i $detail]
    incr tcx $cx
    incr ttx $tx
  }
  set tax [expr {$tcx>0?$ttx/$tcx:0}]
  puts [format {%8d %12d %12d      TOTAL} $tcx $ttx $tax]
}
puts "********************************************************************"
puts "OPCODES:"
foreach op [lsort [array names opcnt]] {
  set cx $opcnt($op)
  set tx $opcycle($op)
  if {$cx==0} {

Changes to tool/warnings.sh.

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
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













+
+
+
-
+
+
+
+








-
+







#/bin/sh
#
# Run this script in a directory with a working makefile to check for 
# compiler warnings in SQLite.
#

if uname | grep -i openbsd ; then
  # Use these for testing on OpenBSD:
  WARNING_OPTS=-Wall
  WARNING_ANDROID_OPTS=-Wall
else
  # Use these for testing on Linux and Mac OSX:
  WARNING_OPTS="-Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long"
  gccvers=`gcc -v 2>&1 | grep '^gcc version'`
  if test "$gccvers" '<' 'gcc version 6'
  then
  WARNING_ANDROID_OPTS="-Wshadow -Wall -Wextra"
    WARNING_ANDROID_OPTS="-Wshadow -Wall -Wextra"
  else
    WARNING_ANDROID_OPTS="-Wshadow -Wall -Wextra -Wimplicit-fallthrough=0"
  fi
fi

rm -f sqlite3.c
make sqlite3.c
echo '********** No optimizations.  Includes FTS4/5, GEOPOLY, JSON1 ***'
echo '**********    ' Options: $WARNING_OPTS
gcc -c $WARNING_OPTS -std=c89 \
      -ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_GEOPOLY \
      -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_JSON1 \
      -DSQLITE_ENABLE_FTS5 \
      sqlite3.c
if test x`uname` = 'xLinux'; then
echo '********** Android configuration ******************************'
echo '**********    ' Options: $WARNING_ANDROID_OPTS
gcc -c \
  -DHAVE_USLEEP=1 \
  -DSQLITE_HAVE_ISNAN \
52
53
54
55
56
57
58
59

60
58
59
60
61
62
63
64

65
66







-
+

gcc -c $WARNING_OPTS -std=c89 \
      -ansi -DSQLITE_ENABLE_STAT4 -DSQLITE_THREADSAFE=0 \
      sqlite3.c
echo '********** Optimized -O3.  Includes FTS4/5, GEOPOLY, JSON1 ******'
echo '**********    ' Options: $WARNING_OPTS
gcc -O3 -c $WARNING_OPTS -std=c89 \
      -ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_GEOPOLY \
      -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_JSON1 \
      -DSQLITE_ENABLE_FTS5 \
      sqlite3.c

Changes to vsixtest/App.xaml.cpp.